arm-gen.c 38 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066106710681069107010711072107310741075107610771078107910801081108210831084108510861087108810891090109110921093109410951096109710981099110011011102110311041105110611071108110911101111111211131114111511161117111811191120112111221123112411251126112711281129113011311132113311341135113611371138113911401141114211431144114511461147114811491150115111521153115411551156115711581159116011611162116311641165116611671168116911701171117211731174117511761177117811791180118111821183118411851186118711881189119011911192119311941195119611971198119912001201120212031204120512061207120812091210121112121213121412151216121712181219122012211222122312241225122612271228122912301231123212331234123512361237123812391240124112421243124412451246124712481249125012511252125312541255125612571258125912601261126212631264126512661267126812691270127112721273127412751276127712781279128012811282128312841285128612871288128912901291129212931294129512961297129812991300130113021303130413051306130713081309131013111312131313141315131613171318131913201321132213231324132513261327132813291330133113321333133413351336133713381339134013411342134313441345134613471348134913501351135213531354135513561357135813591360136113621363136413651366136713681369137013711372137313741375137613771378137913801381138213831384138513861387138813891390139113921393139413951396139713981399140014011402140314041405140614071408140914101411141214131414141514161417141814191420142114221423142414251426142714281429143014311432143314341435143614371438143914401441144214431444144514461447144814491450145114521453145414551456145714581459146014611462146314641465146614671468146914701471147214731474147514761477147814791480148114821483148414851486148714881489149014911492149314941495149614971498149915001501150215031504150515061507150815091510151115121513151415151516151715181519152015211522152315241525152615271528152915301531153215331534153515361537153815391540154115421543154415451546154715481549155015511552155315541555155615571558155915601561156215631564156515661567156815691570157115721573157415751576157715781579158015811582158315841585158615871588158915901591159215931594159515961597159815991600160116021603160416051606160716081609161016111612161316141615161616171618161916201621162216231624162516261627162816291630163116321633163416351636163716381639164016411642164316441645164616471648164916501651165216531654165516561657165816591660166116621663166416651666166716681669167016711672167316741675167616771678167916801681168216831684168516861687168816891690169116921693169416951696169716981699170017011702170317041705170617071708170917101711171217131714171517161717171817191720172117221723172417251726172717281729173017311732173317341735
  1. /*
  2. * ARMv4 code generator for TCC
  3. *
  4. * Copyright (c) 2003 Daniel Glöckner
  5. *
  6. * Based on i386-gen.c by Fabrice Bellard
  7. *
  8. * This library is free software; you can redistribute it and/or
  9. * modify it under the terms of the GNU Lesser General Public
  10. * License as published by the Free Software Foundation; either
  11. * version 2 of the License, or (at your option) any later version.
  12. *
  13. * This library is distributed in the hope that it will be useful,
  14. * but WITHOUT ANY WARRANTY; without even the implied warranty of
  15. * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
  16. * Lesser General Public License for more details.
  17. *
  18. * You should have received a copy of the GNU Lesser General Public
  19. * License along with this library; if not, write to the Free Software
  20. * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
  21. */
  22. #ifdef TCC_ARM_EABI
  23. #define TCC_ARM_VFP
  24. #endif
  25. /* number of available registers */
  26. #ifdef TCC_ARM_VFP
  27. #define NB_REGS 13
  28. #else
  29. #define NB_REGS 9
  30. #endif
  31. /* a register can belong to several classes. The classes must be
  32. sorted from more general to more precise (see gv2() code which does
  33. assumptions on it). */
  34. #define RC_INT 0x0001 /* generic integer register */
  35. #define RC_FLOAT 0x0002 /* generic float register */
  36. #define RC_R0 0x0004
  37. #define RC_R1 0x0008
  38. #define RC_R2 0x0010
  39. #define RC_R3 0x0020
  40. #define RC_R12 0x0040
  41. #define RC_F0 0x0080
  42. #define RC_F1 0x0100
  43. #define RC_F2 0x0200
  44. #define RC_F3 0x0400
  45. #ifdef TCC_ARM_VFP
  46. #define RC_F4 0x0800
  47. #define RC_F5 0x1000
  48. #define RC_F6 0x2000
  49. #define RC_F7 0x4000
  50. #endif
  51. #define RC_IRET RC_R0 /* function return: integer register */
  52. #define RC_LRET RC_R1 /* function return: second integer register */
  53. #define RC_FRET RC_F0 /* function return: float register */
  54. /* pretty names for the registers */
  55. enum {
  56. TREG_R0 = 0,
  57. TREG_R1,
  58. TREG_R2,
  59. TREG_R3,
  60. TREG_R12,
  61. TREG_F0,
  62. TREG_F1,
  63. TREG_F2,
  64. TREG_F3,
  65. #ifdef TCC_ARM_VFP
  66. TREG_F4,
  67. TREG_F5,
  68. TREG_F6,
  69. TREG_F7,
  70. #endif
  71. };
  72. int reg_classes[NB_REGS] = {
  73. /* r0 */ RC_INT | RC_R0,
  74. /* r1 */ RC_INT | RC_R1,
  75. /* r2 */ RC_INT | RC_R2,
  76. /* r3 */ RC_INT | RC_R3,
  77. /* r12 */ RC_INT | RC_R12,
  78. /* f0 */ RC_FLOAT | RC_F0,
  79. /* f1 */ RC_FLOAT | RC_F1,
  80. /* f2 */ RC_FLOAT | RC_F2,
  81. /* f3 */ RC_FLOAT | RC_F3,
  82. #ifdef TCC_ARM_VFP
  83. /* d4/s8 */ RC_FLOAT | RC_F4,
  84. /* d5/s10 */ RC_FLOAT | RC_F5,
  85. /* d6/s12 */ RC_FLOAT | RC_F6,
  86. /* d7/s14 */ RC_FLOAT | RC_F7,
  87. #endif
  88. };
  89. static int two2mask(int a,int b) {
  90. return (reg_classes[a]|reg_classes[b])&~(RC_INT|RC_FLOAT);
  91. }
  92. static int regmask(int r) {
  93. return reg_classes[r]&~(RC_INT|RC_FLOAT);
  94. }
  95. #ifdef TCC_ARM_VFP
  96. #define T2CPR(t) (((t) & VT_BTYPE) != VT_FLOAT ? 0x100 : 0)
  97. #endif
  98. /* return registers for function */
  99. #define REG_IRET TREG_R0 /* single word int return register */
  100. #define REG_LRET TREG_R1 /* second word return register (for long long) */
  101. #define REG_FRET TREG_F0 /* float return register */
  102. #ifdef TCC_ARM_EABI
  103. #define TOK___divdi3 TOK___aeabi_ldivmod
  104. #define TOK___moddi3 TOK___aeabi_ldivmod
  105. #define TOK___udivdi3 TOK___aeabi_uldivmod
  106. #define TOK___umoddi3 TOK___aeabi_uldivmod
  107. #endif
  108. /* defined if function parameters must be evaluated in reverse order */
  109. #define INVERT_FUNC_PARAMS
  110. /* defined if structures are passed as pointers. Otherwise structures
  111. are directly pushed on stack. */
  112. //#define FUNC_STRUCT_PARAM_AS_PTR
  113. #if defined(TCC_ARM_EABI) && defined(TCC_ARM_VFP)
  114. static CType float_type, double_type, func_float_type, func_double_type;
  115. #define func_ldouble_type func_double_type
  116. #else
  117. #define func_float_type func_old_type
  118. #define func_double_type func_old_type
  119. #define func_ldouble_type func_old_type
  120. #endif
  121. /* pointer size, in bytes */
  122. #define PTR_SIZE 4
  123. /* long double size and alignment, in bytes */
  124. #ifdef TCC_ARM_VFP
  125. #define LDOUBLE_SIZE 8
  126. #endif
  127. #ifndef LDOUBLE_SIZE
  128. #define LDOUBLE_SIZE 8
  129. #endif
  130. #ifdef TCC_ARM_EABI
  131. #define LDOUBLE_ALIGN 8
  132. #else
  133. #define LDOUBLE_ALIGN 4
  134. #endif
  135. /* maximum alignment (for aligned attribute support) */
  136. #define MAX_ALIGN 8
  137. #define CHAR_IS_UNSIGNED
  138. /******************************************************/
  139. /* ELF defines */
  140. #define EM_TCC_TARGET EM_ARM
  141. /* relocation type for 32 bit data relocation */
  142. #define R_DATA_32 R_ARM_ABS32
  143. #define R_JMP_SLOT R_ARM_JUMP_SLOT
  144. #define R_COPY R_ARM_COPY
  145. #define ELF_START_ADDR 0x00008000
  146. #define ELF_PAGE_SIZE 0x1000
  147. /******************************************************/
  148. static unsigned long func_sub_sp_offset,last_itod_magic;
  149. static int leaffunc;
  150. void o(unsigned long i)
  151. {
  152. /* this is a good place to start adding big-endian support*/
  153. int ind1;
  154. ind1 = ind + 4;
  155. if (!cur_text_section)
  156. error("compiler error! This happens f.ex. if the compiler\n"
  157. "can't evaluate constant expressions outside of a function.");
  158. if (ind1 > cur_text_section->data_allocated)
  159. section_realloc(cur_text_section, ind1);
  160. cur_text_section->data[ind++] = i&255;
  161. i>>=8;
  162. cur_text_section->data[ind++] = i&255;
  163. i>>=8;
  164. cur_text_section->data[ind++] = i&255;
  165. i>>=8;
  166. cur_text_section->data[ind++] = i;
  167. }
  168. static unsigned long stuff_const(unsigned long op,unsigned long c)
  169. {
  170. int try_neg=0;
  171. unsigned long nc = 0,negop = 0;
  172. switch(op&0x1F00000)
  173. {
  174. case 0x800000: //add
  175. case 0x400000: //sub
  176. try_neg=1;
  177. negop=op^0xC00000;
  178. nc=-c;
  179. break;
  180. case 0x1A00000: //mov
  181. case 0x1E00000: //mvn
  182. try_neg=1;
  183. negop=op^0x400000;
  184. nc=~c;
  185. break;
  186. case 0x200000: //xor
  187. if(c==~0)
  188. return (op&0xF010F000)|((op>>16)&0xF)|0x1E00000;
  189. break;
  190. case 0x0: //and
  191. if(c==~0)
  192. return (op&0xF010F000)|((op>>16)&0xF)|0x1A00000;
  193. case 0x1C00000: //bic
  194. try_neg=1;
  195. negop=op^0x1C00000;
  196. nc=~c;
  197. break;
  198. case 0x1800000: //orr
  199. if(c==~0)
  200. return (op&0xFFF0FFFF)|0x1E00000;
  201. break;
  202. }
  203. do {
  204. unsigned long m;
  205. int i;
  206. if(c<256) /* catch undefined <<32 */
  207. return op|c;
  208. for(i=2;i<32;i+=2) {
  209. m=(0xff>>i)|(0xff<<(32-i));
  210. if(!(c&~m))
  211. return op|(i<<7)|(c<<i)|(c>>(32-i));
  212. }
  213. op=negop;
  214. c=nc;
  215. } while(try_neg--);
  216. return 0;
  217. }
  218. //only add,sub
  219. void stuff_const_harder(unsigned long op,unsigned long v) {
  220. unsigned long x;
  221. x=stuff_const(op,v);
  222. if(x)
  223. o(x);
  224. else {
  225. unsigned long a[16],nv,no,o2,n2;
  226. int i,j,k;
  227. a[0]=0xff;
  228. o2=(op&0xfff0ffff)|((op&0xf000)<<4);;
  229. for(i=1;i<16;i++)
  230. a[i]=(a[i-1]>>2)|(a[i-1]<<30);
  231. for(i=0;i<12;i++)
  232. for(j=i<4?i+12:15;j>=i+4;j--)
  233. if((v&(a[i]|a[j]))==v) {
  234. o(stuff_const(op,v&a[i]));
  235. o(stuff_const(o2,v&a[j]));
  236. return;
  237. }
  238. no=op^0xC00000;
  239. n2=o2^0xC00000;
  240. nv=-v;
  241. for(i=0;i<12;i++)
  242. for(j=i<4?i+12:15;j>=i+4;j--)
  243. if((nv&(a[i]|a[j]))==nv) {
  244. o(stuff_const(no,nv&a[i]));
  245. o(stuff_const(n2,nv&a[j]));
  246. return;
  247. }
  248. for(i=0;i<8;i++)
  249. for(j=i+4;j<12;j++)
  250. for(k=i<4?i+12:15;k>=j+4;k--)
  251. if((v&(a[i]|a[j]|a[k]))==v) {
  252. o(stuff_const(op,v&a[i]));
  253. o(stuff_const(o2,v&a[j]));
  254. o(stuff_const(o2,v&a[k]));
  255. return;
  256. }
  257. no=op^0xC00000;
  258. nv=-v;
  259. for(i=0;i<8;i++)
  260. for(j=i+4;j<12;j++)
  261. for(k=i<4?i+12:15;k>=j+4;k--)
  262. if((nv&(a[i]|a[j]|a[k]))==nv) {
  263. o(stuff_const(no,nv&a[i]));
  264. o(stuff_const(n2,nv&a[j]));
  265. o(stuff_const(n2,nv&a[k]));
  266. return;
  267. }
  268. o(stuff_const(op,v&a[0]));
  269. o(stuff_const(o2,v&a[4]));
  270. o(stuff_const(o2,v&a[8]));
  271. o(stuff_const(o2,v&a[12]));
  272. }
  273. }
  274. unsigned long encbranch(int pos,int addr,int fail)
  275. {
  276. addr-=pos+8;
  277. addr/=4;
  278. if(addr>=0x1000000 || addr<-0x1000000) {
  279. if(fail)
  280. error("FIXME: function bigger than 32MB");
  281. return 0;
  282. }
  283. return 0x0A000000|(addr&0xffffff);
  284. }
  285. int decbranch(int pos)
  286. {
  287. int x;
  288. x=*(int *)(cur_text_section->data + pos);
  289. x&=0x00ffffff;
  290. if(x&0x800000)
  291. x-=0x1000000;
  292. return x*4+pos+8;
  293. }
  294. /* output a symbol and patch all calls to it */
  295. void gsym_addr(int t, int a)
  296. {
  297. unsigned long *x;
  298. int lt;
  299. while(t) {
  300. x=(unsigned long *)(cur_text_section->data + t);
  301. t=decbranch(lt=t);
  302. if(a==lt+4)
  303. *x=0xE1A00000; // nop
  304. else {
  305. *x &= 0xff000000;
  306. *x |= encbranch(lt,a,1);
  307. }
  308. }
  309. }
  310. void gsym(int t)
  311. {
  312. gsym_addr(t, ind);
  313. }
  314. #ifdef TCC_ARM_VFP
  315. static unsigned long vfpr(int r)
  316. {
  317. if(r<TREG_F0 || r>TREG_F7)
  318. error("compiler error! register %i is no vfp register",r);
  319. return r-5;
  320. }
  321. #else
  322. static unsigned long fpr(int r)
  323. {
  324. if(r<TREG_F0 || r>TREG_F3)
  325. error("compiler error! register %i is no fpa register",r);
  326. return r-5;
  327. }
  328. #endif
  329. static unsigned long intr(int r)
  330. {
  331. if(r==4)
  332. return 12;
  333. if((r<0 || r>4) && r!=14)
  334. error("compiler error! register %i is no int register",r);
  335. return r;
  336. }
  337. static void calcaddr(unsigned long *base,int *off,int *sgn,int maxoff,unsigned shift)
  338. {
  339. if(*off>maxoff || *off&((1<<shift)-1)) {
  340. unsigned long x,y;
  341. x=0xE280E000;
  342. if(*sgn)
  343. x=0xE240E000;
  344. x|=(*base)<<16;
  345. *base=14; // lr
  346. y=stuff_const(x,*off&~maxoff);
  347. if(y) {
  348. o(y);
  349. *off&=maxoff;
  350. return;
  351. }
  352. y=stuff_const(x,(*off+maxoff)&~maxoff);
  353. if(y) {
  354. o(y);
  355. *sgn=!*sgn;
  356. *off=((*off+maxoff)&~maxoff)-*off;
  357. return;
  358. }
  359. stuff_const_harder(x,*off&~maxoff);
  360. *off&=maxoff;
  361. }
  362. }
  363. static unsigned long mapcc(int cc)
  364. {
  365. switch(cc)
  366. {
  367. case TOK_ULT:
  368. return 0x30000000; /* CC/LO */
  369. case TOK_UGE:
  370. return 0x20000000; /* CS/HS */
  371. case TOK_EQ:
  372. return 0x00000000; /* EQ */
  373. case TOK_NE:
  374. return 0x10000000; /* NE */
  375. case TOK_ULE:
  376. return 0x90000000; /* LS */
  377. case TOK_UGT:
  378. return 0x80000000; /* HI */
  379. case TOK_Nset:
  380. return 0x40000000; /* MI */
  381. case TOK_Nclear:
  382. return 0x50000000; /* PL */
  383. case TOK_LT:
  384. return 0xB0000000; /* LT */
  385. case TOK_GE:
  386. return 0xA0000000; /* GE */
  387. case TOK_LE:
  388. return 0xD0000000; /* LE */
  389. case TOK_GT:
  390. return 0xC0000000; /* GT */
  391. }
  392. error("unexpected condition code");
  393. return 0xE0000000; /* AL */
  394. }
  395. static int negcc(int cc)
  396. {
  397. switch(cc)
  398. {
  399. case TOK_ULT:
  400. return TOK_UGE;
  401. case TOK_UGE:
  402. return TOK_ULT;
  403. case TOK_EQ:
  404. return TOK_NE;
  405. case TOK_NE:
  406. return TOK_EQ;
  407. case TOK_ULE:
  408. return TOK_UGT;
  409. case TOK_UGT:
  410. return TOK_ULE;
  411. case TOK_Nset:
  412. return TOK_Nclear;
  413. case TOK_Nclear:
  414. return TOK_Nset;
  415. case TOK_LT:
  416. return TOK_GE;
  417. case TOK_GE:
  418. return TOK_LT;
  419. case TOK_LE:
  420. return TOK_GT;
  421. case TOK_GT:
  422. return TOK_LE;
  423. }
  424. error("unexpected condition code");
  425. return TOK_NE;
  426. }
  427. /* load 'r' from value 'sv' */
  428. void load(int r, SValue *sv)
  429. {
  430. int v, ft, fc, fr, sign;
  431. unsigned long op;
  432. SValue v1;
  433. fr = sv->r;
  434. ft = sv->type.t;
  435. fc = sv->c.ul;
  436. if(fc>=0)
  437. sign=0;
  438. else {
  439. sign=1;
  440. fc=-fc;
  441. }
  442. v = fr & VT_VALMASK;
  443. if (fr & VT_LVAL) {
  444. unsigned long base=0xB; // fp
  445. if(v == VT_LLOCAL) {
  446. v1.type.t = VT_PTR;
  447. v1.r = VT_LOCAL | VT_LVAL;
  448. v1.c.ul = sv->c.ul;
  449. load(base=14 /* lr */, &v1);
  450. fc=sign=0;
  451. v=VT_LOCAL;
  452. } else if(v == VT_CONST) {
  453. v1.type.t = VT_PTR;
  454. v1.r = fr&~VT_LVAL;
  455. v1.c.ul = sv->c.ul;
  456. v1.sym=sv->sym;
  457. load(base=14, &v1);
  458. fc=sign=0;
  459. v=VT_LOCAL;
  460. } else if(v < VT_CONST) {
  461. base=intr(v);
  462. fc=sign=0;
  463. v=VT_LOCAL;
  464. }
  465. if(v == VT_LOCAL) {
  466. if(is_float(ft)) {
  467. calcaddr(&base,&fc,&sign,1020,2);
  468. #ifdef TCC_ARM_VFP
  469. op=0xED100A00; /* flds */
  470. if(!sign)
  471. op|=0x800000;
  472. if ((ft & VT_BTYPE) != VT_FLOAT)
  473. op|=0x100; /* flds -> fldd */
  474. o(op|(vfpr(r)<<12)|(fc>>2)|(base<<16));
  475. #else
  476. op=0xED100100;
  477. if(!sign)
  478. op|=0x800000;
  479. #if LDOUBLE_SIZE == 8
  480. if ((ft & VT_BTYPE) != VT_FLOAT)
  481. op|=0x8000;
  482. #else
  483. if ((ft & VT_BTYPE) == VT_DOUBLE)
  484. op|=0x8000;
  485. else if ((ft & VT_BTYPE) == VT_LDOUBLE)
  486. op|=0x400000;
  487. #endif
  488. o(op|(fpr(r)<<12)|(fc>>2)|(base<<16));
  489. #endif
  490. } else if((ft & (VT_BTYPE|VT_UNSIGNED)) == VT_BYTE
  491. || (ft & VT_BTYPE) == VT_SHORT) {
  492. calcaddr(&base,&fc,&sign,255,0);
  493. op=0xE1500090;
  494. if ((ft & VT_BTYPE) == VT_SHORT)
  495. op|=0x20;
  496. if ((ft & VT_UNSIGNED) == 0)
  497. op|=0x40;
  498. if(!sign)
  499. op|=0x800000;
  500. o(op|(intr(r)<<12)|(base<<16)|((fc&0xf0)<<4)|(fc&0xf));
  501. } else {
  502. calcaddr(&base,&fc,&sign,4095,0);
  503. op=0xE5100000;
  504. if(!sign)
  505. op|=0x800000;
  506. if ((ft & VT_BTYPE) == VT_BYTE)
  507. op|=0x400000;
  508. o(op|(intr(r)<<12)|fc|(base<<16));
  509. }
  510. return;
  511. }
  512. } else {
  513. if (v == VT_CONST) {
  514. op=stuff_const(0xE3A00000|(intr(r)<<12),sv->c.ul);
  515. if (fr & VT_SYM || !op) {
  516. o(0xE59F0000|(intr(r)<<12));
  517. o(0xEA000000);
  518. if(fr & VT_SYM)
  519. greloc(cur_text_section, sv->sym, ind, R_ARM_ABS32);
  520. o(sv->c.ul);
  521. } else
  522. o(op);
  523. return;
  524. } else if (v == VT_LOCAL) {
  525. op=stuff_const(0xE28B0000|(intr(r)<<12),sv->c.ul);
  526. if (fr & VT_SYM || !op) {
  527. o(0xE59F0000|(intr(r)<<12));
  528. o(0xEA000000);
  529. if(fr & VT_SYM) // needed ?
  530. greloc(cur_text_section, sv->sym, ind, R_ARM_ABS32);
  531. o(sv->c.ul);
  532. o(0xE08B0000|(intr(r)<<12)|intr(r));
  533. } else
  534. o(op);
  535. return;
  536. } else if(v == VT_CMP) {
  537. o(mapcc(sv->c.ul)|0x3A00001|(intr(r)<<12));
  538. o(mapcc(negcc(sv->c.ul))|0x3A00000|(intr(r)<<12));
  539. return;
  540. } else if (v == VT_JMP || v == VT_JMPI) {
  541. int t;
  542. t = v & 1;
  543. o(0xE3A00000|(intr(r)<<12)|t);
  544. o(0xEA000000);
  545. gsym(sv->c.ul);
  546. o(0xE3A00000|(intr(r)<<12)|(t^1));
  547. return;
  548. } else if (v < VT_CONST) {
  549. if(is_float(ft))
  550. #ifdef TCC_ARM_VFP
  551. o(0xEEB00A40|(vfpr(r)<<12)|vfpr(v)|T2CPR(ft)); /* fcpyX */
  552. #else
  553. o(0xEE008180|(fpr(r)<<12)|fpr(v));
  554. #endif
  555. else
  556. o(0xE1A00000|(intr(r)<<12)|intr(v));
  557. return;
  558. }
  559. }
  560. error("load unimplemented!");
  561. }
  562. /* store register 'r' in lvalue 'v' */
  563. void store(int r, SValue *sv)
  564. {
  565. SValue v1;
  566. int v, ft, fc, fr, sign;
  567. unsigned long op;
  568. fr = sv->r;
  569. ft = sv->type.t;
  570. fc = sv->c.ul;
  571. if(fc>=0)
  572. sign=0;
  573. else {
  574. sign=1;
  575. fc=-fc;
  576. }
  577. v = fr & VT_VALMASK;
  578. if (fr & VT_LVAL || fr == VT_LOCAL) {
  579. unsigned long base=0xb;
  580. if(v < VT_CONST) {
  581. base=intr(v);
  582. v=VT_LOCAL;
  583. fc=sign=0;
  584. } else if(v == VT_CONST) {
  585. v1.type.t = ft;
  586. v1.r = fr&~VT_LVAL;
  587. v1.c.ul = sv->c.ul;
  588. v1.sym=sv->sym;
  589. load(base=14, &v1);
  590. fc=sign=0;
  591. v=VT_LOCAL;
  592. }
  593. if(v == VT_LOCAL) {
  594. if(is_float(ft)) {
  595. calcaddr(&base,&fc,&sign,1020,2);
  596. #ifdef TCC_ARM_VFP
  597. op=0xED000A00; /* fsts */
  598. if(!sign)
  599. op|=0x800000;
  600. if ((ft & VT_BTYPE) != VT_FLOAT)
  601. op|=0x100; /* fsts -> fstd */
  602. o(op|(vfpr(r)<<12)|(fc>>2)|(base<<16));
  603. #else
  604. op=0xED000100;
  605. if(!sign)
  606. op|=0x800000;
  607. #if LDOUBLE_SIZE == 8
  608. if ((ft & VT_BTYPE) != VT_FLOAT)
  609. op|=0x8000;
  610. #else
  611. if ((ft & VT_BTYPE) == VT_DOUBLE)
  612. op|=0x8000;
  613. if ((ft & VT_BTYPE) == VT_LDOUBLE)
  614. op|=0x400000;
  615. #endif
  616. o(op|(fpr(r)<<12)|(fc>>2)|(base<<16));
  617. #endif
  618. return;
  619. } else if((ft & VT_BTYPE) == VT_SHORT) {
  620. calcaddr(&base,&fc,&sign,255,0);
  621. op=0xE14000B0;
  622. if(!sign)
  623. op|=0x800000;
  624. o(op|(intr(r)<<12)|(base<<16)|((fc&0xf0)<<4)|(fc&0xf));
  625. } else {
  626. calcaddr(&base,&fc,&sign,4095,0);
  627. op=0xE5000000;
  628. if(!sign)
  629. op|=0x800000;
  630. if ((ft & VT_BTYPE) == VT_BYTE)
  631. op|=0x400000;
  632. o(op|(intr(r)<<12)|fc|(base<<16));
  633. }
  634. return;
  635. }
  636. }
  637. error("store unimplemented");
  638. }
  639. static void gadd_sp(int val)
  640. {
  641. stuff_const_harder(0xE28DD000,val);
  642. }
  643. /* 'is_jmp' is '1' if it is a jump */
  644. static void gcall_or_jmp(int is_jmp)
  645. {
  646. int r;
  647. if ((vtop->r & (VT_VALMASK | VT_LVAL)) == VT_CONST) {
  648. unsigned long x;
  649. /* constant case */
  650. x=encbranch(ind,ind+vtop->c.ul,0);
  651. if(x) {
  652. if (vtop->r & VT_SYM) {
  653. /* relocation case */
  654. greloc(cur_text_section, vtop->sym, ind, R_ARM_PC24);
  655. } else
  656. put_elf_reloc(symtab_section, cur_text_section, ind, R_ARM_PC24, 0);
  657. o(x|(is_jmp?0xE0000000:0xE1000000));
  658. } else {
  659. if(!is_jmp)
  660. o(0xE28FE004); // add lr,pc,#4
  661. o(0xE51FF004); // ldr pc,[pc,#-4]
  662. if (vtop->r & VT_SYM)
  663. greloc(cur_text_section, vtop->sym, ind, R_ARM_ABS32);
  664. o(vtop->c.ul);
  665. }
  666. } else {
  667. /* otherwise, indirect call */
  668. r = gv(RC_INT);
  669. if(!is_jmp)
  670. o(0xE1A0E00F); // mov lr,pc
  671. o(0xE1A0F000|intr(r)); // mov pc,r
  672. }
  673. }
  674. /* Generate function call. The function address is pushed first, then
  675. all the parameters in call order. This functions pops all the
  676. parameters and the function address. */
  677. void gfunc_call(int nb_args)
  678. {
  679. int size, align, r, args_size, i;
  680. Sym *func_sym;
  681. signed char plan[4][2]={{-1,-1},{-1,-1},{-1,-1},{-1,-1}};
  682. int todo=0xf, keep, plan2[4]={0,0,0,0};
  683. r = vtop->r & VT_VALMASK;
  684. if (r == VT_CMP || (r & ~1) == VT_JMP)
  685. gv(RC_INT);
  686. #ifdef TCC_ARM_EABI
  687. if((vtop[-nb_args].type.ref->type.t & VT_BTYPE) == VT_STRUCT
  688. && type_size(&vtop[-nb_args].type, &align) <= 4) {
  689. SValue tmp;
  690. tmp=vtop[-nb_args];
  691. vtop[-nb_args]=vtop[-nb_args+1];
  692. vtop[-nb_args+1]=tmp;
  693. --nb_args;
  694. }
  695. vpushi(0);
  696. vtop->type.t = VT_LLONG;
  697. args_size = 0;
  698. for(i = nb_args + 1 ; i-- ;) {
  699. size = type_size(&vtop[-i].type, &align);
  700. if(args_size & (align-1)) {
  701. vpushi(0);
  702. vtop->type.t = VT_VOID; /* padding */
  703. vrott(i+2);
  704. args_size += 4;
  705. ++nb_args;
  706. }
  707. args_size += (size + 3) & -4;
  708. }
  709. vtop--;
  710. #endif
  711. args_size = 0;
  712. for(i = nb_args ; i-- && args_size < 16 ;) {
  713. switch(vtop[-i].type.t & VT_BTYPE) {
  714. case VT_STRUCT:
  715. case VT_FLOAT:
  716. case VT_DOUBLE:
  717. case VT_LDOUBLE:
  718. size = type_size(&vtop[-i].type, &align);
  719. size = (size + 3) & -4;
  720. args_size += size;
  721. break;
  722. default:
  723. plan[nb_args-1-i][0]=args_size/4;
  724. args_size += 4;
  725. if ((vtop[-i].type.t & VT_BTYPE) == VT_LLONG && args_size < 16) {
  726. plan[nb_args-1-i][1]=args_size/4;
  727. args_size += 4;
  728. }
  729. }
  730. }
  731. args_size = keep = 0;
  732. for(i = 0;i < nb_args; i++) {
  733. vnrott(keep+1);
  734. if ((vtop->type.t & VT_BTYPE) == VT_STRUCT) {
  735. size = type_size(&vtop->type, &align);
  736. /* align to stack align size */
  737. size = (size + 3) & -4;
  738. /* allocate the necessary size on stack */
  739. gadd_sp(-size);
  740. /* generate structure store */
  741. r = get_reg(RC_INT);
  742. o(0xE1A0000D|(intr(r)<<12));
  743. vset(&vtop->type, r | VT_LVAL, 0);
  744. vswap();
  745. vstore();
  746. vtop--;
  747. args_size += size;
  748. } else if (is_float(vtop->type.t)) {
  749. #ifdef TCC_ARM_VFP
  750. r=vfpr(gv(RC_FLOAT))<<12;
  751. size=4;
  752. if ((vtop->type.t & VT_BTYPE) != VT_FLOAT)
  753. {
  754. size=8;
  755. r|=0x101; /* fstms -> fstmd */
  756. }
  757. o(0xED2D0A01+r);
  758. #else
  759. r=fpr(gv(RC_FLOAT))<<12;
  760. if ((vtop->type.t & VT_BTYPE) == VT_FLOAT)
  761. size = 4;
  762. else if ((vtop->type.t & VT_BTYPE) == VT_DOUBLE)
  763. size = 8;
  764. else
  765. size = LDOUBLE_SIZE;
  766. if (size == 12)
  767. r|=0x400000;
  768. else if(size == 8)
  769. r|=0x8000;
  770. o(0xED2D0100|r|(size>>2));
  771. #endif
  772. vtop--;
  773. args_size += size;
  774. } else {
  775. int s;
  776. /* simple type (currently always same size) */
  777. /* XXX: implicit cast ? */
  778. size=4;
  779. if ((vtop->type.t & VT_BTYPE) == VT_LLONG) {
  780. lexpand_nr();
  781. s=RC_INT;
  782. if(nb_args-i<5 && plan[nb_args-i-1][1]!=-1) {
  783. s=regmask(plan[nb_args-i-1][1]);
  784. todo&=~(1<<plan[nb_args-i-1][1]);
  785. }
  786. if(s==RC_INT) {
  787. r = gv(s);
  788. o(0xE52D0004|(intr(r)<<12)); /* str r,[sp,#-4]! */
  789. vtop--;
  790. } else {
  791. plan2[keep]=s;
  792. keep++;
  793. vswap();
  794. }
  795. size = 8;
  796. }
  797. s=RC_INT;
  798. if(nb_args-i<5 && plan[nb_args-i-1][0]!=-1) {
  799. s=regmask(plan[nb_args-i-1][0]);
  800. todo&=~(1<<plan[nb_args-i-1][0]);
  801. }
  802. #ifdef TCC_ARM_EABI
  803. if(vtop->type.t == VT_VOID) {
  804. if(s == RC_INT)
  805. o(0xE24DD004); /* sub sp,sp,#4 */
  806. vtop--;
  807. } else
  808. #endif
  809. if(s == RC_INT) {
  810. r = gv(s);
  811. o(0xE52D0004|(intr(r)<<12)); /* str r,[sp,#-4]! */
  812. vtop--;
  813. } else {
  814. plan2[keep]=s;
  815. keep++;
  816. }
  817. args_size += size;
  818. }
  819. }
  820. for(i=keep;i--;) {
  821. gv(plan2[i]);
  822. vrott(keep);
  823. }
  824. save_regs(keep); /* save used temporary registers */
  825. keep++;
  826. if(args_size) {
  827. int n;
  828. n=args_size/4;
  829. if(n>4)
  830. n=4;
  831. todo&=((1<<n)-1);
  832. if(todo) {
  833. int i;
  834. o(0xE8BD0000|todo);
  835. for(i=0;i<4;i++)
  836. if(todo&(1<<i)) {
  837. vpushi(0);
  838. vtop->r=i;
  839. keep++;
  840. }
  841. }
  842. args_size-=n*4;
  843. }
  844. vnrott(keep);
  845. func_sym = vtop->type.ref;
  846. gcall_or_jmp(0);
  847. if (args_size)
  848. gadd_sp(args_size);
  849. #ifdef TCC_ARM_EABI
  850. if((vtop->type.ref->type.t & VT_BTYPE) == VT_STRUCT
  851. && type_size(&vtop->type.ref->type, &align) <= 4)
  852. {
  853. store(REG_IRET,vtop-keep);
  854. ++keep;
  855. }
  856. #ifdef TCC_ARM_VFP
  857. else if(is_float(vtop->type.ref->type.t)) {
  858. if((vtop->type.ref->type.t & VT_BTYPE) == VT_FLOAT) {
  859. o(0xEE000A10); /* fmsr s0,r0 */
  860. } else {
  861. o(0xEE000B10); /* fmdlr d0,r0 */
  862. o(0xEE201B10); /* fmdhr d0,r1 */
  863. }
  864. }
  865. #endif
  866. #endif
  867. vtop-=keep;
  868. leaffunc = 0;
  869. }
  870. /* generate function prolog of type 't' */
  871. void gfunc_prolog(CType *func_type)
  872. {
  873. Sym *sym,*sym2;
  874. int n,addr,size,align;
  875. sym = func_type->ref;
  876. func_vt = sym->type;
  877. n = 0;
  878. addr = 0;
  879. if((func_vt.t & VT_BTYPE) == VT_STRUCT
  880. && type_size(&func_vt,&align) > 4)
  881. {
  882. func_vc = addr;
  883. addr += 4;
  884. n++;
  885. }
  886. for(sym2=sym->next;sym2 && n<4;sym2=sym2->next) {
  887. size = type_size(&sym2->type, &align);
  888. n += (size + 3) / 4;
  889. }
  890. o(0xE1A0C00D); /* mov ip,sp */
  891. if(func_type->ref->c == FUNC_ELLIPSIS)
  892. n=4;
  893. if(n) {
  894. if(n>4)
  895. n=4;
  896. #ifdef TCC_ARM_EABI
  897. n=(n+1)&-2;
  898. #endif
  899. o(0xE92D0000|((1<<n)-1)); /* save r0-r4 on stack if needed */
  900. }
  901. o(0xE92D5800); /* save fp, ip, lr */
  902. o(0xE28DB00C); /* add fp, sp, #12 */
  903. func_sub_sp_offset = ind;
  904. o(0xE1A00000); /* nop, leave space for stack adjustment */
  905. while ((sym = sym->next)) {
  906. CType *type;
  907. type = &sym->type;
  908. size = type_size(type, &align);
  909. size = (size + 3) & -4;
  910. #ifdef TCC_ARM_EABI
  911. addr = (addr + align - 1) & -align;
  912. #endif
  913. sym_push(sym->v & ~SYM_FIELD, type, VT_LOCAL | lvalue_type(type->t), addr);
  914. addr += size;
  915. }
  916. last_itod_magic=0;
  917. leaffunc = 1;
  918. loc = -12;
  919. }
  920. /* generate function epilog */
  921. void gfunc_epilog(void)
  922. {
  923. unsigned long x;
  924. int diff;
  925. #ifdef TCC_ARM_EABI
  926. if(is_float(func_vt.t)) {
  927. if((func_vt.t & VT_BTYPE) == VT_FLOAT)
  928. o(0xEE100A10); /* fmrs r0, s0 */
  929. else {
  930. o(0xEE100B10); /* fmrdl r0, d0 */
  931. o(0xEE301B10); /* fmrdh r1, d0 */
  932. }
  933. }
  934. #endif
  935. o(0xE91BA800); /* restore fp, sp, pc */
  936. diff = (-loc + 3) & -4;
  937. #ifdef TCC_ARM_EABI
  938. if(!leaffunc)
  939. diff = (diff + 7) & -8;
  940. #endif
  941. if(diff > 12) {
  942. x=stuff_const(0xE24BD000, diff); /* sub sp,fp,# */
  943. if(x)
  944. *(unsigned long *)(cur_text_section->data + func_sub_sp_offset) = x;
  945. else {
  946. unsigned long addr;
  947. addr=ind;
  948. o(0xE59FC004); /* ldr ip,[pc+4] */
  949. o(0xE04BD00C); /* sub sp,fp,ip */
  950. o(0xE1A0F00E); /* mov pc,lr */
  951. o(diff);
  952. *(unsigned long *)(cur_text_section->data + func_sub_sp_offset) = 0xE1000000|encbranch(func_sub_sp_offset,addr,1);
  953. }
  954. }
  955. }
  956. /* generate a jump to a label */
  957. int gjmp(int t)
  958. {
  959. int r;
  960. r=ind;
  961. o(0xE0000000|encbranch(r,t,1));
  962. return r;
  963. }
  964. /* generate a jump to a fixed address */
  965. void gjmp_addr(int a)
  966. {
  967. gjmp(a);
  968. }
  969. /* generate a test. set 'inv' to invert test. Stack entry is popped */
  970. int gtst(int inv, int t)
  971. {
  972. int v, r;
  973. unsigned long op;
  974. v = vtop->r & VT_VALMASK;
  975. r=ind;
  976. if (v == VT_CMP) {
  977. op=mapcc(inv?negcc(vtop->c.i):vtop->c.i);
  978. op|=encbranch(r,t,1);
  979. o(op);
  980. t=r;
  981. } else if (v == VT_JMP || v == VT_JMPI) {
  982. if ((v & 1) == inv) {
  983. if(!vtop->c.i)
  984. vtop->c.i=t;
  985. else {
  986. unsigned long *x;
  987. int p,lp;
  988. if(t) {
  989. p = vtop->c.i;
  990. do {
  991. p = decbranch(lp=p);
  992. } while(p);
  993. x = (unsigned long *)(cur_text_section->data + lp);
  994. *x &= 0xff000000;
  995. *x |= encbranch(lp,t,1);
  996. }
  997. t = vtop->c.i;
  998. }
  999. } else {
  1000. t = gjmp(t);
  1001. gsym(vtop->c.i);
  1002. }
  1003. } else {
  1004. if (is_float(vtop->type.t)) {
  1005. r=gv(RC_FLOAT);
  1006. #ifdef TCC_ARM_VFP
  1007. o(0xEEB50A40|(vfpr(r)<<12)|T2CPR(vtop->type.t)); /* fcmpzX */
  1008. o(0xEEF1FA10); /* fmstat */
  1009. #else
  1010. o(0xEE90F118|(fpr(r)<<16));
  1011. #endif
  1012. vtop->r = VT_CMP;
  1013. vtop->c.i = TOK_NE;
  1014. return gtst(inv, t);
  1015. } else if ((vtop->r & (VT_VALMASK | VT_LVAL | VT_SYM)) == VT_CONST) {
  1016. /* constant jmp optimization */
  1017. if ((vtop->c.i != 0) != inv)
  1018. t = gjmp(t);
  1019. } else {
  1020. v = gv(RC_INT);
  1021. o(0xE3300000|(intr(v)<<16));
  1022. vtop->r = VT_CMP;
  1023. vtop->c.i = TOK_NE;
  1024. return gtst(inv, t);
  1025. }
  1026. }
  1027. vtop--;
  1028. return t;
  1029. }
  1030. /* generate an integer binary operation */
  1031. void gen_opi(int op)
  1032. {
  1033. int c, func = 0;
  1034. unsigned long opc = 0,r,fr;
  1035. unsigned short retreg = REG_IRET;
  1036. c=0;
  1037. switch(op) {
  1038. case '+':
  1039. opc = 0x8;
  1040. c=1;
  1041. break;
  1042. case TOK_ADDC1: /* add with carry generation */
  1043. opc = 0x9;
  1044. c=1;
  1045. break;
  1046. case '-':
  1047. opc = 0x4;
  1048. c=1;
  1049. break;
  1050. case TOK_SUBC1: /* sub with carry generation */
  1051. opc = 0x5;
  1052. c=1;
  1053. break;
  1054. case TOK_ADDC2: /* add with carry use */
  1055. opc = 0xA;
  1056. c=1;
  1057. break;
  1058. case TOK_SUBC2: /* sub with carry use */
  1059. opc = 0xC;
  1060. c=1;
  1061. break;
  1062. case '&':
  1063. opc = 0x0;
  1064. c=1;
  1065. break;
  1066. case '^':
  1067. opc = 0x2;
  1068. c=1;
  1069. break;
  1070. case '|':
  1071. opc = 0x18;
  1072. c=1;
  1073. break;
  1074. case '*':
  1075. gv2(RC_INT, RC_INT);
  1076. r = vtop[-1].r;
  1077. fr = vtop[0].r;
  1078. vtop--;
  1079. o(0xE0000090|(intr(r)<<16)|(intr(r)<<8)|intr(fr));
  1080. return;
  1081. case TOK_SHL:
  1082. opc = 0;
  1083. c=2;
  1084. break;
  1085. case TOK_SHR:
  1086. opc = 1;
  1087. c=2;
  1088. break;
  1089. case TOK_SAR:
  1090. opc = 2;
  1091. c=2;
  1092. break;
  1093. case '/':
  1094. case TOK_PDIV:
  1095. func=TOK___divsi3;
  1096. c=3;
  1097. break;
  1098. case TOK_UDIV:
  1099. func=TOK___udivsi3;
  1100. c=3;
  1101. break;
  1102. case '%':
  1103. #ifdef TCC_ARM_EABI
  1104. func=TOK___aeabi_idivmod;
  1105. retreg=REG_LRET;
  1106. #else
  1107. func=TOK___modsi3;
  1108. #endif
  1109. c=3;
  1110. break;
  1111. case TOK_UMOD:
  1112. #ifdef TCC_ARM_EABI
  1113. func=TOK___aeabi_uidivmod;
  1114. retreg=REG_LRET;
  1115. #else
  1116. func=TOK___umodsi3;
  1117. #endif
  1118. c=3;
  1119. break;
  1120. case TOK_UMULL:
  1121. gv2(RC_INT, RC_INT);
  1122. r=intr(vtop[-1].r2=get_reg(RC_INT));
  1123. c=vtop[-1].r;
  1124. vtop[-1].r=get_reg_ex(RC_INT,regmask(c));
  1125. vtop--;
  1126. o(0xE0800090|(r<<16)|(intr(vtop->r)<<12)|(intr(c)<<8)|intr(vtop[1].r));
  1127. return;
  1128. default:
  1129. opc = 0x15;
  1130. c=1;
  1131. break;
  1132. }
  1133. switch(c) {
  1134. case 1:
  1135. if((vtop[-1].r & (VT_VALMASK | VT_LVAL | VT_SYM)) == VT_CONST) {
  1136. if(opc == 4 || opc == 5 || opc == 0xc) {
  1137. vswap();
  1138. opc|=2; // sub -> rsb
  1139. }
  1140. }
  1141. if ((vtop->r & VT_VALMASK) == VT_CMP ||
  1142. (vtop->r & (VT_VALMASK & ~1)) == VT_JMP)
  1143. gv(RC_INT);
  1144. vswap();
  1145. c=intr(gv(RC_INT));
  1146. vswap();
  1147. opc=0xE0000000|(opc<<20)|(c<<16);
  1148. if((vtop->r & (VT_VALMASK | VT_LVAL | VT_SYM)) == VT_CONST) {
  1149. unsigned long x;
  1150. x=stuff_const(opc|0x2000000,vtop->c.i);
  1151. if(x) {
  1152. r=intr(vtop[-1].r=get_reg_ex(RC_INT,regmask(vtop[-1].r)));
  1153. o(x|(r<<12));
  1154. goto done;
  1155. }
  1156. }
  1157. fr=intr(gv(RC_INT));
  1158. r=intr(vtop[-1].r=get_reg_ex(RC_INT,two2mask(vtop->r,vtop[-1].r)));
  1159. o(opc|(r<<12)|fr);
  1160. done:
  1161. vtop--;
  1162. if (op >= TOK_ULT && op <= TOK_GT) {
  1163. vtop->r = VT_CMP;
  1164. vtop->c.i = op;
  1165. }
  1166. break;
  1167. case 2:
  1168. opc=0xE1A00000|(opc<<5);
  1169. if ((vtop->r & VT_VALMASK) == VT_CMP ||
  1170. (vtop->r & (VT_VALMASK & ~1)) == VT_JMP)
  1171. gv(RC_INT);
  1172. vswap();
  1173. r=intr(gv(RC_INT));
  1174. vswap();
  1175. opc|=r;
  1176. if ((vtop->r & (VT_VALMASK | VT_LVAL | VT_SYM)) == VT_CONST) {
  1177. fr=intr(vtop[-1].r=get_reg_ex(RC_INT,regmask(vtop[-1].r)));
  1178. c = vtop->c.i & 0x1f;
  1179. o(opc|(c<<7)|(fr<<12));
  1180. } else {
  1181. fr=intr(gv(RC_INT));
  1182. c=intr(vtop[-1].r=get_reg_ex(RC_INT,two2mask(vtop->r,vtop[-1].r)));
  1183. o(opc|(c<<12)|(fr<<8)|0x10);
  1184. }
  1185. vtop--;
  1186. break;
  1187. case 3:
  1188. vpush_global_sym(&func_old_type, func);
  1189. vrott(3);
  1190. gfunc_call(2);
  1191. vpushi(0);
  1192. vtop->r = retreg;
  1193. break;
  1194. default:
  1195. error("gen_opi %i unimplemented!",op);
  1196. }
  1197. }
  1198. #ifdef TCC_ARM_VFP
  1199. static int is_zero(int i)
  1200. {
  1201. if((vtop[i].r & (VT_VALMASK | VT_LVAL | VT_SYM)) != VT_CONST)
  1202. return 0;
  1203. if (vtop[i].type.t == VT_FLOAT)
  1204. return (vtop[i].c.f == 0.f);
  1205. else if (vtop[i].type.t == VT_DOUBLE)
  1206. return (vtop[i].c.d == 0.0);
  1207. return (vtop[i].c.ld == 0.l);
  1208. }
  1209. /* generate a floating point operation 'v = t1 op t2' instruction. The
  1210. * two operands are guaranted to have the same floating point type */
  1211. void gen_opf(int op)
  1212. {
  1213. unsigned long x;
  1214. int fneg=0,r;
  1215. x=0xEE000A00|T2CPR(vtop->type.t);
  1216. switch(op) {
  1217. case '+':
  1218. if(is_zero(-1))
  1219. vswap();
  1220. if(is_zero(0)) {
  1221. vtop--;
  1222. return;
  1223. }
  1224. x|=0x300000;
  1225. break;
  1226. case '-':
  1227. x|=0x300040;
  1228. if(is_zero(0)) {
  1229. vtop--;
  1230. return;
  1231. }
  1232. if(is_zero(-1)) {
  1233. x|=0x810000; /* fsubX -> fnegX */
  1234. vswap();
  1235. vtop--;
  1236. fneg=1;
  1237. }
  1238. break;
  1239. case '*':
  1240. x|=0x200000;
  1241. break;
  1242. case '/':
  1243. x|=0x800000;
  1244. break;
  1245. default:
  1246. if(op < TOK_ULT && op > TOK_GT) {
  1247. error("unknown fp op %x!",op);
  1248. return;
  1249. }
  1250. if(is_zero(-1)) {
  1251. vswap();
  1252. switch(op) {
  1253. case TOK_LT: op=TOK_GT; break;
  1254. case TOK_GE: op=TOK_ULE; break;
  1255. case TOK_LE: op=TOK_GE; break;
  1256. case TOK_GT: op=TOK_ULT; break;
  1257. }
  1258. }
  1259. x|=0xB40040; /* fcmpX */
  1260. if(op!=TOK_EQ && op!=TOK_NE)
  1261. x|=0x80; /* fcmpX -> fcmpeX */
  1262. if(is_zero(0)) {
  1263. vtop--;
  1264. o(x|0x10000|(vfpr(gv(RC_FLOAT))<<12)); /* fcmp(e)X -> fcmp(e)zX */
  1265. } else {
  1266. x|=vfpr(gv(RC_FLOAT));
  1267. vswap();
  1268. o(x|(vfpr(gv(RC_FLOAT))<<12));
  1269. vtop--;
  1270. }
  1271. o(0xEEF1FA10); /* fmstat */
  1272. switch(op) {
  1273. case TOK_LE: op=TOK_ULE; break;
  1274. case TOK_LT: op=TOK_ULT; break;
  1275. case TOK_UGE: op=TOK_GE; break;
  1276. case TOK_UGT: op=TOK_GT; break;
  1277. }
  1278. vtop->r = VT_CMP;
  1279. vtop->c.i = op;
  1280. return;
  1281. }
  1282. r=gv(RC_FLOAT);
  1283. x|=vfpr(r);
  1284. r=regmask(r);
  1285. if(!fneg) {
  1286. int r2;
  1287. vswap();
  1288. r2=gv(RC_FLOAT);
  1289. x|=vfpr(r2)<<16;
  1290. r|=regmask(r2);
  1291. }
  1292. vtop->r=get_reg_ex(RC_FLOAT,r);
  1293. if(!fneg)
  1294. vtop--;
  1295. o(x|(vfpr(vtop->r)<<12));
  1296. }
  1297. #else
  1298. static int is_fconst()
  1299. {
  1300. long double f;
  1301. int r;
  1302. if((vtop->r & (VT_VALMASK | VT_LVAL | VT_SYM)) != VT_CONST)
  1303. return 0;
  1304. if (vtop->type.t == VT_FLOAT)
  1305. f = vtop->c.f;
  1306. else if (vtop->type.t == VT_DOUBLE)
  1307. f = vtop->c.d;
  1308. else
  1309. f = vtop->c.ld;
  1310. if(!ieee_finite(f))
  1311. return 0;
  1312. r=0x8;
  1313. if(f<0.0) {
  1314. r=0x18;
  1315. f=-f;
  1316. }
  1317. if(f==0.0)
  1318. return r;
  1319. if(f==1.0)
  1320. return r|1;
  1321. if(f==2.0)
  1322. return r|2;
  1323. if(f==3.0)
  1324. return r|3;
  1325. if(f==4.0)
  1326. return r|4;
  1327. if(f==5.0)
  1328. return r|5;
  1329. if(f==0.5)
  1330. return r|6;
  1331. if(f==10.0)
  1332. return r|7;
  1333. return 0;
  1334. }
  1335. /* generate a floating point operation 'v = t1 op t2' instruction. The
  1336. two operands are guaranted to have the same floating point type */
  1337. void gen_opf(int op)
  1338. {
  1339. unsigned long x;
  1340. int r,r2,c1,c2;
  1341. //fputs("gen_opf\n",stderr);
  1342. vswap();
  1343. c1 = is_fconst();
  1344. vswap();
  1345. c2 = is_fconst();
  1346. x=0xEE000100;
  1347. #if LDOUBLE_SIZE == 8
  1348. if ((vtop->type.t & VT_BTYPE) != VT_FLOAT)
  1349. x|=0x80;
  1350. #else
  1351. if ((vtop->type.t & VT_BTYPE) == VT_DOUBLE)
  1352. x|=0x80;
  1353. else if ((vtop->type.t & VT_BTYPE) == VT_LDOUBLE)
  1354. x|=0x80000;
  1355. #endif
  1356. switch(op)
  1357. {
  1358. case '+':
  1359. if(!c2) {
  1360. vswap();
  1361. c2=c1;
  1362. }
  1363. vswap();
  1364. r=fpr(gv(RC_FLOAT));
  1365. vswap();
  1366. if(c2) {
  1367. if(c2>0xf)
  1368. x|=0x200000; // suf
  1369. r2=c2&0xf;
  1370. } else {
  1371. r2=fpr(gv(RC_FLOAT));
  1372. }
  1373. break;
  1374. case '-':
  1375. if(c2) {
  1376. if(c2<=0xf)
  1377. x|=0x200000; // suf
  1378. r2=c2&0xf;
  1379. vswap();
  1380. r=fpr(gv(RC_FLOAT));
  1381. vswap();
  1382. } else if(c1 && c1<=0xf) {
  1383. x|=0x300000; // rsf
  1384. r2=c1;
  1385. r=fpr(gv(RC_FLOAT));
  1386. vswap();
  1387. } else {
  1388. x|=0x200000; // suf
  1389. vswap();
  1390. r=fpr(gv(RC_FLOAT));
  1391. vswap();
  1392. r2=fpr(gv(RC_FLOAT));
  1393. }
  1394. break;
  1395. case '*':
  1396. if(!c2 || c2>0xf) {
  1397. vswap();
  1398. c2=c1;
  1399. }
  1400. vswap();
  1401. r=fpr(gv(RC_FLOAT));
  1402. vswap();
  1403. if(c2 && c2<=0xf)
  1404. r2=c2;
  1405. else
  1406. r2=fpr(gv(RC_FLOAT));
  1407. x|=0x100000; // muf
  1408. break;
  1409. case '/':
  1410. if(c2 && c2<=0xf) {
  1411. x|=0x400000; // dvf
  1412. r2=c2;
  1413. vswap();
  1414. r=fpr(gv(RC_FLOAT));
  1415. vswap();
  1416. } else if(c1 && c1<=0xf) {
  1417. x|=0x500000; // rdf
  1418. r2=c1;
  1419. r=fpr(gv(RC_FLOAT));
  1420. vswap();
  1421. } else {
  1422. x|=0x400000; // dvf
  1423. vswap();
  1424. r=fpr(gv(RC_FLOAT));
  1425. vswap();
  1426. r2=fpr(gv(RC_FLOAT));
  1427. }
  1428. break;
  1429. default:
  1430. if(op >= TOK_ULT && op <= TOK_GT) {
  1431. x|=0xd0f110; // cmfe
  1432. /* bug (intention?) in Linux FPU emulator
  1433. doesn't set carry if equal */
  1434. switch(op) {
  1435. case TOK_ULT:
  1436. case TOK_UGE:
  1437. case TOK_ULE:
  1438. case TOK_UGT:
  1439. error("unsigned comparison on floats?");
  1440. break;
  1441. case TOK_LT:
  1442. op=TOK_Nset;
  1443. break;
  1444. case TOK_LE:
  1445. op=TOK_ULE; /* correct in unordered case only if AC bit in FPSR set */
  1446. break;
  1447. case TOK_EQ:
  1448. case TOK_NE:
  1449. x&=~0x400000; // cmfe -> cmf
  1450. break;
  1451. }
  1452. if(c1 && !c2) {
  1453. c2=c1;
  1454. vswap();
  1455. switch(op) {
  1456. case TOK_Nset:
  1457. op=TOK_GT;
  1458. break;
  1459. case TOK_GE:
  1460. op=TOK_ULE;
  1461. break;
  1462. case TOK_ULE:
  1463. op=TOK_GE;
  1464. break;
  1465. case TOK_GT:
  1466. op=TOK_Nset;
  1467. break;
  1468. }
  1469. }
  1470. vswap();
  1471. r=fpr(gv(RC_FLOAT));
  1472. vswap();
  1473. if(c2) {
  1474. if(c2>0xf)
  1475. x|=0x200000;
  1476. r2=c2&0xf;
  1477. } else {
  1478. r2=fpr(gv(RC_FLOAT));
  1479. }
  1480. vtop[-1].r = VT_CMP;
  1481. vtop[-1].c.i = op;
  1482. } else {
  1483. error("unknown fp op %x!",op);
  1484. return;
  1485. }
  1486. }
  1487. if(vtop[-1].r == VT_CMP)
  1488. c1=15;
  1489. else {
  1490. c1=vtop->r;
  1491. if(r2&0x8)
  1492. c1=vtop[-1].r;
  1493. vtop[-1].r=get_reg_ex(RC_FLOAT,two2mask(vtop[-1].r,c1));
  1494. c1=fpr(vtop[-1].r);
  1495. }
  1496. vtop--;
  1497. o(x|(r<<16)|(c1<<12)|r2);
  1498. }
  1499. #endif
  1500. /* convert integers to fp 't' type. Must handle 'int', 'unsigned int'
  1501. and 'long long' cases. */
  1502. void gen_cvt_itof1(int t)
  1503. {
  1504. int r,r2,bt;
  1505. bt=vtop->type.t & VT_BTYPE;
  1506. if(bt == VT_INT || bt == VT_SHORT || bt == VT_BYTE) {
  1507. #ifndef TCC_ARM_VFP
  1508. unsigned int dsize=0;
  1509. #endif
  1510. r=intr(gv(RC_INT));
  1511. #ifdef TCC_ARM_VFP
  1512. r2=vfpr(vtop->r=get_reg(RC_FLOAT));
  1513. o(0xEE000A10|(r<<12)|(r2<<16)); /* fmsr */
  1514. r2<<=12;
  1515. if(!(vtop->type.t & VT_UNSIGNED))
  1516. r2|=0x80; /* fuitoX -> fsituX */
  1517. o(0xEEB80A40|r2|T2CPR(t)); /* fYitoX*/
  1518. #else
  1519. r2=fpr(vtop->r=get_reg(RC_FLOAT));
  1520. if((t & VT_BTYPE) != VT_FLOAT)
  1521. dsize=0x80; /* flts -> fltd */
  1522. o(0xEE000110|dsize|(r2<<16)|(r<<12)); /* flts */
  1523. if((vtop->type.t & (VT_UNSIGNED|VT_BTYPE)) == (VT_UNSIGNED|VT_INT)) {
  1524. unsigned int off=0;
  1525. o(0xE3500000|(r<<12)); /* cmp */
  1526. r=fpr(get_reg(RC_FLOAT));
  1527. if(last_itod_magic) {
  1528. off=ind+8-last_itod_magic;
  1529. off/=4;
  1530. if(off>255)
  1531. off=0;
  1532. }
  1533. o(0xBD1F0100|(r<<12)|off); /* ldflts */
  1534. if(!off) {
  1535. o(0xEA000000); /* b */
  1536. last_itod_magic=ind;
  1537. o(0x4F800000); /* 4294967296.0f */
  1538. }
  1539. o(0xBE000100|dsize|(r2<<16)|(r2<<12)|r); /* adflt */
  1540. }
  1541. #endif
  1542. return;
  1543. } else if(bt == VT_LLONG) {
  1544. int func;
  1545. CType *func_type = 0;
  1546. if((t & VT_BTYPE) == VT_FLOAT) {
  1547. func_type = &func_float_type;
  1548. if(vtop->type.t & VT_UNSIGNED)
  1549. func=TOK___floatundisf;
  1550. else
  1551. func=TOK___floatdisf;
  1552. #if LDOUBLE_SIZE != 8
  1553. } else if((t & VT_BTYPE) == VT_LDOUBLE) {
  1554. func_type = &func_ldouble_type;
  1555. if(vtop->type.t & VT_UNSIGNED)
  1556. func=TOK___floatundixf;
  1557. else
  1558. func=TOK___floatdixf;
  1559. } else if((t & VT_BTYPE) == VT_DOUBLE) {
  1560. #else
  1561. } else if((t & VT_BTYPE) == VT_DOUBLE || (t & VT_BTYPE) == VT_LDOUBLE) {
  1562. #endif
  1563. func_type = &func_double_type;
  1564. if(vtop->type.t & VT_UNSIGNED)
  1565. func=TOK___floatundidf;
  1566. else
  1567. func=TOK___floatdidf;
  1568. }
  1569. if(func_type) {
  1570. vpush_global_sym(func_type, func);
  1571. vswap();
  1572. gfunc_call(1);
  1573. vpushi(0);
  1574. vtop->r=TREG_F0;
  1575. return;
  1576. }
  1577. }
  1578. error("unimplemented gen_cvt_itof %x!",vtop->type.t);
  1579. }
  1580. /* convert fp to int 't' type */
  1581. void gen_cvt_ftoi(int t)
  1582. {
  1583. int r,r2,u,func=0;
  1584. u=t&VT_UNSIGNED;
  1585. t&=VT_BTYPE;
  1586. r2=vtop->type.t & VT_BTYPE;
  1587. if(t==VT_INT) {
  1588. #ifdef TCC_ARM_VFP
  1589. r=vfpr(gv(RC_FLOAT));
  1590. u=u?0:0x10000;
  1591. o(0xEEBC0A40|(r<<12)|r|T2CPR(r2)); /* ftoXiY */
  1592. r2=intr(vtop->r=get_reg(RC_INT));
  1593. o(0xEE100A10|(r<<16)|(r2<<12));
  1594. return;
  1595. #else
  1596. if(u) {
  1597. if(r2 == VT_FLOAT)
  1598. func=TOK___fixunssfsi;
  1599. #if LDOUBLE_SIZE != 8
  1600. else if(r2 == VT_LDOUBLE)
  1601. func=TOK___fixunsxfsi;
  1602. else if(r2 == VT_DOUBLE)
  1603. #else
  1604. else if(r2 == VT_LDOUBLE || r2 == VT_DOUBLE)
  1605. #endif
  1606. func=TOK___fixunsdfsi;
  1607. } else {
  1608. r=fpr(gv(RC_FLOAT));
  1609. r2=intr(vtop->r=get_reg(RC_INT));
  1610. o(0xEE100170|(r2<<12)|r);
  1611. return;
  1612. }
  1613. #endif
  1614. } else if(t == VT_LLONG) { // unsigned handled in gen_cvt_ftoi1
  1615. if(r2 == VT_FLOAT)
  1616. func=TOK___fixsfdi;
  1617. #if LDOUBLE_SIZE != 8
  1618. else if(r2 == VT_LDOUBLE)
  1619. func=TOK___fixxfdi;
  1620. else if(r2 == VT_DOUBLE)
  1621. #else
  1622. else if(r2 == VT_LDOUBLE || r2 == VT_DOUBLE)
  1623. #endif
  1624. func=TOK___fixdfdi;
  1625. }
  1626. if(func) {
  1627. vpush_global_sym(&func_old_type, func);
  1628. vswap();
  1629. gfunc_call(1);
  1630. vpushi(0);
  1631. if(t == VT_LLONG)
  1632. vtop->r2 = REG_LRET;
  1633. vtop->r = REG_IRET;
  1634. return;
  1635. }
  1636. error("unimplemented gen_cvt_ftoi!");
  1637. }
  1638. /* convert from one floating point type to another */
  1639. void gen_cvt_ftof(int t)
  1640. {
  1641. #ifdef TCC_ARM_VFP
  1642. if(((vtop->type.t & VT_BTYPE) == VT_FLOAT) != ((t & VT_BTYPE) == VT_FLOAT)) {
  1643. int r=vfpr(gv(RC_FLOAT));
  1644. o(0xEEB70AC0|(r<<12)|r|T2CPR(vtop->type.t));
  1645. }
  1646. #else
  1647. /* all we have to do on i386 and FPA ARM is to put the float in a register */
  1648. gv(RC_FLOAT);
  1649. #endif
  1650. }
  1651. /* computed goto support */
  1652. void ggoto(void)
  1653. {
  1654. gcall_or_jmp(1);
  1655. vtop--;
  1656. }
  1657. /* end of ARM code generator */
  1658. /*************************************************************/