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