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