configure: use relative paths for in-tree build
[tinycc.git] / arm-gen.c
blob02b035e151e7a0f9e5efc03cdd81f4fa12630a61
1 /*
2 * ARMv4 code generator for TCC
3 *
4 * Copyright (c) 2003 Daniel Glöckner
5 * Copyright (c) 2012 Thomas Preud'homme
7 * Based on i386-gen.c by Fabrice Bellard
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.
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.
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
24 #ifdef TARGET_DEFS_ONLY
26 #ifdef TCC_ARM_EABI
27 #ifndef TCC_ARM_VFP // Avoid useless warning
28 #define TCC_ARM_VFP
29 #endif
30 #endif
32 /* number of available registers */
33 #ifdef TCC_ARM_VFP
34 #define NB_REGS 13
35 #else
36 #define NB_REGS 9
37 #endif
39 /* a register can belong to several classes. The classes must be
40 sorted from more general to more precise (see gv2() code which does
41 assumptions on it). */
42 #define RC_INT 0x0001 /* generic integer register */
43 #define RC_FLOAT 0x0002 /* generic float register */
44 #define RC_R0 0x0004
45 #define RC_R1 0x0008
46 #define RC_R2 0x0010
47 #define RC_R3 0x0020
48 #define RC_R12 0x0040
49 #define RC_F0 0x0080
50 #define RC_F1 0x0100
51 #define RC_F2 0x0200
52 #define RC_F3 0x0400
53 #ifdef TCC_ARM_VFP
54 #define RC_F4 0x0800
55 #define RC_F5 0x1000
56 #define RC_F6 0x2000
57 #define RC_F7 0x4000
58 #endif
59 #define RC_IRET RC_R0 /* function return: integer register */
60 #define RC_LRET RC_R1 /* function return: second integer register */
61 #define RC_FRET RC_F0 /* function return: float register */
63 /* pretty names for the registers */
64 enum {
65 TREG_R0 = 0,
66 TREG_R1,
67 TREG_R2,
68 TREG_R3,
69 TREG_R12,
70 TREG_F0,
71 TREG_F1,
72 TREG_F2,
73 TREG_F3,
74 #ifdef TCC_ARM_VFP
75 TREG_F4,
76 TREG_F5,
77 TREG_F6,
78 TREG_F7,
79 #endif
82 #ifdef TCC_ARM_VFP
83 #define T2CPR(t) (((t) & VT_BTYPE) != VT_FLOAT ? 0x100 : 0)
84 #endif
86 /* return registers for function */
87 #define REG_IRET TREG_R0 /* single word int return register */
88 #define REG_LRET TREG_R1 /* second word return register (for long long) */
89 #define REG_FRET TREG_F0 /* float return register */
91 #ifdef TCC_ARM_EABI
92 #define TOK___divdi3 TOK___aeabi_ldivmod
93 #define TOK___moddi3 TOK___aeabi_ldivmod
94 #define TOK___udivdi3 TOK___aeabi_uldivmod
95 #define TOK___umoddi3 TOK___aeabi_uldivmod
96 #endif
98 /* defined if function parameters must be evaluated in reverse order */
99 #define INVERT_FUNC_PARAMS
101 /* defined if structures are passed as pointers. Otherwise structures
102 are directly pushed on stack. */
103 //#define FUNC_STRUCT_PARAM_AS_PTR
105 #if defined(TCC_ARM_EABI) && defined(TCC_ARM_VFP)
106 ST_DATA CType float_type, double_type, func_float_type, func_double_type;
107 #define func_ldouble_type func_double_type
108 #else
109 #define func_float_type func_old_type
110 #define func_double_type func_old_type
111 #define func_ldouble_type func_old_type
112 #endif
114 /* pointer size, in bytes */
115 #define PTR_SIZE 4
117 /* long double size and alignment, in bytes */
118 #ifdef TCC_ARM_VFP
119 #define LDOUBLE_SIZE 8
120 #endif
122 #ifndef LDOUBLE_SIZE
123 #define LDOUBLE_SIZE 8
124 #endif
126 #ifdef TCC_ARM_EABI
127 #define LDOUBLE_ALIGN 8
128 #else
129 #define LDOUBLE_ALIGN 4
130 #endif
132 /* maximum alignment (for aligned attribute support) */
133 #define MAX_ALIGN 8
135 #define CHAR_IS_UNSIGNED
137 /******************************************************/
138 /* ELF defines */
140 #define EM_TCC_TARGET EM_ARM
142 /* relocation type for 32 bit data relocation */
143 #define R_DATA_32 R_ARM_ABS32
144 #define R_DATA_PTR R_ARM_ABS32
145 #define R_JMP_SLOT R_ARM_JUMP_SLOT
146 #define R_COPY R_ARM_COPY
148 #define ELF_START_ADDR 0x00008000
149 #define ELF_PAGE_SIZE 0x1000
151 /******************************************************/
152 #else /* ! TARGET_DEFS_ONLY */
153 /******************************************************/
154 #include "tcc.h"
156 ST_DATA const int reg_classes[NB_REGS] = {
157 /* r0 */ RC_INT | RC_R0,
158 /* r1 */ RC_INT | RC_R1,
159 /* r2 */ RC_INT | RC_R2,
160 /* r3 */ RC_INT | RC_R3,
161 /* r12 */ RC_INT | RC_R12,
162 /* f0 */ RC_FLOAT | RC_F0,
163 /* f1 */ RC_FLOAT | RC_F1,
164 /* f2 */ RC_FLOAT | RC_F2,
165 /* f3 */ RC_FLOAT | RC_F3,
166 #ifdef TCC_ARM_VFP
167 /* d4/s8 */ RC_FLOAT | RC_F4,
168 /* d5/s10 */ RC_FLOAT | RC_F5,
169 /* d6/s12 */ RC_FLOAT | RC_F6,
170 /* d7/s14 */ RC_FLOAT | RC_F7,
171 #endif
174 /* keep in sync with line 104 above */
175 #if defined(TCC_ARM_EABI) && defined(TCC_ARM_VFP)
176 ST_DATA CType float_type, double_type, func_float_type, func_double_type;
177 #endif
179 static int func_sub_sp_offset, last_itod_magic;
180 static int leaffunc;
182 static int two2mask(int a,int b) {
183 return (reg_classes[a]|reg_classes[b])&~(RC_INT|RC_FLOAT);
186 static int regmask(int r) {
187 return reg_classes[r]&~(RC_INT|RC_FLOAT);
190 /******************************************************/
192 void o(uint32_t i)
194 /* this is a good place to start adding big-endian support*/
195 int ind1;
197 ind1 = ind + 4;
198 if (!cur_text_section)
199 tcc_error("compiler error! This happens f.ex. if the compiler\n"
200 "can't evaluate constant expressions outside of a function.");
201 if (ind1 > cur_text_section->data_allocated)
202 section_realloc(cur_text_section, ind1);
203 cur_text_section->data[ind++] = i&255;
204 i>>=8;
205 cur_text_section->data[ind++] = i&255;
206 i>>=8;
207 cur_text_section->data[ind++] = i&255;
208 i>>=8;
209 cur_text_section->data[ind++] = i;
212 static uint32_t stuff_const(uint32_t op, uint32_t c)
214 int try_neg=0;
215 uint32_t nc = 0, negop = 0;
217 switch(op&0x1F00000)
219 case 0x800000: //add
220 case 0x400000: //sub
221 try_neg=1;
222 negop=op^0xC00000;
223 nc=-c;
224 break;
225 case 0x1A00000: //mov
226 case 0x1E00000: //mvn
227 try_neg=1;
228 negop=op^0x400000;
229 nc=~c;
230 break;
231 case 0x200000: //xor
232 if(c==~0)
233 return (op&0xF010F000)|((op>>16)&0xF)|0x1E00000;
234 break;
235 case 0x0: //and
236 if(c==~0)
237 return (op&0xF010F000)|((op>>16)&0xF)|0x1A00000;
238 case 0x1C00000: //bic
239 try_neg=1;
240 negop=op^0x1C00000;
241 nc=~c;
242 break;
243 case 0x1800000: //orr
244 if(c==~0)
245 return (op&0xFFF0FFFF)|0x1E00000;
246 break;
248 do {
249 uint32_t m;
250 int i;
251 if(c<256) /* catch undefined <<32 */
252 return op|c;
253 for(i=2;i<32;i+=2) {
254 m=(0xff>>i)|(0xff<<(32-i));
255 if(!(c&~m))
256 return op|(i<<7)|(c<<i)|(c>>(32-i));
258 op=negop;
259 c=nc;
260 } while(try_neg--);
261 return 0;
265 //only add,sub
266 void stuff_const_harder(uint32_t op, uint32_t v) {
267 uint32_t x;
268 x=stuff_const(op,v);
269 if(x)
270 o(x);
271 else {
272 uint32_t a[16], nv, no, o2, n2;
273 int i,j,k;
274 a[0]=0xff;
275 o2=(op&0xfff0ffff)|((op&0xf000)<<4);;
276 for(i=1;i<16;i++)
277 a[i]=(a[i-1]>>2)|(a[i-1]<<30);
278 for(i=0;i<12;i++)
279 for(j=i<4?i+12:15;j>=i+4;j--)
280 if((v&(a[i]|a[j]))==v) {
281 o(stuff_const(op,v&a[i]));
282 o(stuff_const(o2,v&a[j]));
283 return;
285 no=op^0xC00000;
286 n2=o2^0xC00000;
287 nv=-v;
288 for(i=0;i<12;i++)
289 for(j=i<4?i+12:15;j>=i+4;j--)
290 if((nv&(a[i]|a[j]))==nv) {
291 o(stuff_const(no,nv&a[i]));
292 o(stuff_const(n2,nv&a[j]));
293 return;
295 for(i=0;i<8;i++)
296 for(j=i+4;j<12;j++)
297 for(k=i<4?i+12:15;k>=j+4;k--)
298 if((v&(a[i]|a[j]|a[k]))==v) {
299 o(stuff_const(op,v&a[i]));
300 o(stuff_const(o2,v&a[j]));
301 o(stuff_const(o2,v&a[k]));
302 return;
304 no=op^0xC00000;
305 nv=-v;
306 for(i=0;i<8;i++)
307 for(j=i+4;j<12;j++)
308 for(k=i<4?i+12:15;k>=j+4;k--)
309 if((nv&(a[i]|a[j]|a[k]))==nv) {
310 o(stuff_const(no,nv&a[i]));
311 o(stuff_const(n2,nv&a[j]));
312 o(stuff_const(n2,nv&a[k]));
313 return;
315 o(stuff_const(op,v&a[0]));
316 o(stuff_const(o2,v&a[4]));
317 o(stuff_const(o2,v&a[8]));
318 o(stuff_const(o2,v&a[12]));
322 ST_FUNC uint32_t encbranch(int pos, int addr, int fail)
324 addr-=pos+8;
325 addr/=4;
326 if(addr>=0x1000000 || addr<-0x1000000) {
327 if(fail)
328 tcc_error("FIXME: function bigger than 32MB");
329 return 0;
331 return 0x0A000000|(addr&0xffffff);
334 int decbranch(int pos)
336 int x;
337 x=*(uint32_t *)(cur_text_section->data + pos);
338 x&=0x00ffffff;
339 if(x&0x800000)
340 x-=0x1000000;
341 return x*4+pos+8;
344 /* output a symbol and patch all calls to it */
345 void gsym_addr(int t, int a)
347 uint32_t *x;
348 int lt;
349 while(t) {
350 x=(uint32_t *)(cur_text_section->data + t);
351 t=decbranch(lt=t);
352 if(a==lt+4)
353 *x=0xE1A00000; // nop
354 else {
355 *x &= 0xff000000;
356 *x |= encbranch(lt,a,1);
361 void gsym(int t)
363 gsym_addr(t, ind);
366 #ifdef TCC_ARM_VFP
367 static uint32_t vfpr(int r)
369 if(r<TREG_F0 || r>TREG_F7)
370 tcc_error("compiler error! register %i is no vfp register",r);
371 return r-5;
373 #else
374 static uint32_t fpr(int r)
376 if(r<TREG_F0 || r>TREG_F3)
377 tcc_error("compiler error! register %i is no fpa register",r);
378 return r-5;
380 #endif
382 static uint32_t intr(int r)
384 if(r==4)
385 return 12;
386 if((r<0 || r>4) && r!=14)
387 tcc_error("compiler error! register %i is no int register",r);
388 return r;
391 static void calcaddr(uint32_t *base, int *off, int *sgn, int maxoff, unsigned shift)
393 if(*off>maxoff || *off&((1<<shift)-1)) {
394 uint32_t x, y;
395 x=0xE280E000;
396 if(*sgn)
397 x=0xE240E000;
398 x|=(*base)<<16;
399 *base=14; // lr
400 y=stuff_const(x,*off&~maxoff);
401 if(y) {
402 o(y);
403 *off&=maxoff;
404 return;
406 y=stuff_const(x,(*off+maxoff)&~maxoff);
407 if(y) {
408 o(y);
409 *sgn=!*sgn;
410 *off=((*off+maxoff)&~maxoff)-*off;
411 return;
413 stuff_const_harder(x,*off&~maxoff);
414 *off&=maxoff;
418 static uint32_t mapcc(int cc)
420 switch(cc)
422 case TOK_ULT:
423 return 0x30000000; /* CC/LO */
424 case TOK_UGE:
425 return 0x20000000; /* CS/HS */
426 case TOK_EQ:
427 return 0x00000000; /* EQ */
428 case TOK_NE:
429 return 0x10000000; /* NE */
430 case TOK_ULE:
431 return 0x90000000; /* LS */
432 case TOK_UGT:
433 return 0x80000000; /* HI */
434 case TOK_Nset:
435 return 0x40000000; /* MI */
436 case TOK_Nclear:
437 return 0x50000000; /* PL */
438 case TOK_LT:
439 return 0xB0000000; /* LT */
440 case TOK_GE:
441 return 0xA0000000; /* GE */
442 case TOK_LE:
443 return 0xD0000000; /* LE */
444 case TOK_GT:
445 return 0xC0000000; /* GT */
447 tcc_error("unexpected condition code");
448 return 0xE0000000; /* AL */
451 static int negcc(int cc)
453 switch(cc)
455 case TOK_ULT:
456 return TOK_UGE;
457 case TOK_UGE:
458 return TOK_ULT;
459 case TOK_EQ:
460 return TOK_NE;
461 case TOK_NE:
462 return TOK_EQ;
463 case TOK_ULE:
464 return TOK_UGT;
465 case TOK_UGT:
466 return TOK_ULE;
467 case TOK_Nset:
468 return TOK_Nclear;
469 case TOK_Nclear:
470 return TOK_Nset;
471 case TOK_LT:
472 return TOK_GE;
473 case TOK_GE:
474 return TOK_LT;
475 case TOK_LE:
476 return TOK_GT;
477 case TOK_GT:
478 return TOK_LE;
480 tcc_error("unexpected condition code");
481 return TOK_NE;
484 /* load 'r' from value 'sv' */
485 void load(int r, SValue *sv)
487 int v, ft, fc, fr, sign;
488 uint32_t op;
489 SValue v1;
491 fr = sv->r;
492 ft = sv->type.t;
493 fc = sv->c.ul;
495 if(fc>=0)
496 sign=0;
497 else {
498 sign=1;
499 fc=-fc;
502 v = fr & VT_VALMASK;
503 if (fr & VT_LVAL) {
504 uint32_t base = 0xB; // fp
505 if(v == VT_LLOCAL) {
506 v1.type.t = VT_PTR;
507 v1.r = VT_LOCAL | VT_LVAL;
508 v1.c.ul = sv->c.ul;
509 load(base=14 /* lr */, &v1);
510 fc=sign=0;
511 v=VT_LOCAL;
512 } else if(v == VT_CONST) {
513 v1.type.t = VT_PTR;
514 v1.r = fr&~VT_LVAL;
515 v1.c.ul = sv->c.ul;
516 v1.sym=sv->sym;
517 load(base=14, &v1);
518 fc=sign=0;
519 v=VT_LOCAL;
520 } else if(v < VT_CONST) {
521 base=intr(v);
522 fc=sign=0;
523 v=VT_LOCAL;
525 if(v == VT_LOCAL) {
526 if(is_float(ft)) {
527 calcaddr(&base,&fc,&sign,1020,2);
528 #ifdef TCC_ARM_VFP
529 op=0xED100A00; /* flds */
530 if(!sign)
531 op|=0x800000;
532 if ((ft & VT_BTYPE) != VT_FLOAT)
533 op|=0x100; /* flds -> fldd */
534 o(op|(vfpr(r)<<12)|(fc>>2)|(base<<16));
535 #else
536 op=0xED100100;
537 if(!sign)
538 op|=0x800000;
539 #if LDOUBLE_SIZE == 8
540 if ((ft & VT_BTYPE) != VT_FLOAT)
541 op|=0x8000;
542 #else
543 if ((ft & VT_BTYPE) == VT_DOUBLE)
544 op|=0x8000;
545 else if ((ft & VT_BTYPE) == VT_LDOUBLE)
546 op|=0x400000;
547 #endif
548 o(op|(fpr(r)<<12)|(fc>>2)|(base<<16));
549 #endif
550 } else if((ft & (VT_BTYPE|VT_UNSIGNED)) == VT_BYTE
551 || (ft & VT_BTYPE) == VT_SHORT) {
552 calcaddr(&base,&fc,&sign,255,0);
553 op=0xE1500090;
554 if ((ft & VT_BTYPE) == VT_SHORT)
555 op|=0x20;
556 if ((ft & VT_UNSIGNED) == 0)
557 op|=0x40;
558 if(!sign)
559 op|=0x800000;
560 o(op|(intr(r)<<12)|(base<<16)|((fc&0xf0)<<4)|(fc&0xf));
561 } else {
562 calcaddr(&base,&fc,&sign,4095,0);
563 op=0xE5100000;
564 if(!sign)
565 op|=0x800000;
566 if ((ft & VT_BTYPE) == VT_BYTE)
567 op|=0x400000;
568 o(op|(intr(r)<<12)|fc|(base<<16));
570 return;
572 } else {
573 if (v == VT_CONST) {
574 op=stuff_const(0xE3A00000|(intr(r)<<12),sv->c.ul);
575 if (fr & VT_SYM || !op) {
576 o(0xE59F0000|(intr(r)<<12));
577 o(0xEA000000);
578 if(fr & VT_SYM)
579 greloc(cur_text_section, sv->sym, ind, R_ARM_ABS32);
580 o(sv->c.ul);
581 } else
582 o(op);
583 return;
584 } else if (v == VT_LOCAL) {
585 op=stuff_const(0xE28B0000|(intr(r)<<12),sv->c.ul);
586 if (fr & VT_SYM || !op) {
587 o(0xE59F0000|(intr(r)<<12));
588 o(0xEA000000);
589 if(fr & VT_SYM) // needed ?
590 greloc(cur_text_section, sv->sym, ind, R_ARM_ABS32);
591 o(sv->c.ul);
592 o(0xE08B0000|(intr(r)<<12)|intr(r));
593 } else
594 o(op);
595 return;
596 } else if(v == VT_CMP) {
597 o(mapcc(sv->c.ul)|0x3A00001|(intr(r)<<12));
598 o(mapcc(negcc(sv->c.ul))|0x3A00000|(intr(r)<<12));
599 return;
600 } else if (v == VT_JMP || v == VT_JMPI) {
601 int t;
602 t = v & 1;
603 o(0xE3A00000|(intr(r)<<12)|t);
604 o(0xEA000000);
605 gsym(sv->c.ul);
606 o(0xE3A00000|(intr(r)<<12)|(t^1));
607 return;
608 } else if (v < VT_CONST) {
609 if(is_float(ft))
610 #ifdef TCC_ARM_VFP
611 o(0xEEB00A40|(vfpr(r)<<12)|vfpr(v)|T2CPR(ft)); /* fcpyX */
612 #else
613 o(0xEE008180|(fpr(r)<<12)|fpr(v));
614 #endif
615 else
616 o(0xE1A00000|(intr(r)<<12)|intr(v));
617 return;
620 tcc_error("load unimplemented!");
623 /* store register 'r' in lvalue 'v' */
624 void store(int r, SValue *sv)
626 SValue v1;
627 int v, ft, fc, fr, sign;
628 uint32_t op;
630 fr = sv->r;
631 ft = sv->type.t;
632 fc = sv->c.ul;
634 if(fc>=0)
635 sign=0;
636 else {
637 sign=1;
638 fc=-fc;
641 v = fr & VT_VALMASK;
642 if (fr & VT_LVAL || fr == VT_LOCAL) {
643 uint32_t base = 0xb;
644 if(v < VT_CONST) {
645 base=intr(v);
646 v=VT_LOCAL;
647 fc=sign=0;
648 } else if(v == VT_CONST) {
649 v1.type.t = ft;
650 v1.r = fr&~VT_LVAL;
651 v1.c.ul = sv->c.ul;
652 v1.sym=sv->sym;
653 load(base=14, &v1);
654 fc=sign=0;
655 v=VT_LOCAL;
657 if(v == VT_LOCAL) {
658 if(is_float(ft)) {
659 calcaddr(&base,&fc,&sign,1020,2);
660 #ifdef TCC_ARM_VFP
661 op=0xED000A00; /* fsts */
662 if(!sign)
663 op|=0x800000;
664 if ((ft & VT_BTYPE) != VT_FLOAT)
665 op|=0x100; /* fsts -> fstd */
666 o(op|(vfpr(r)<<12)|(fc>>2)|(base<<16));
667 #else
668 op=0xED000100;
669 if(!sign)
670 op|=0x800000;
671 #if LDOUBLE_SIZE == 8
672 if ((ft & VT_BTYPE) != VT_FLOAT)
673 op|=0x8000;
674 #else
675 if ((ft & VT_BTYPE) == VT_DOUBLE)
676 op|=0x8000;
677 if ((ft & VT_BTYPE) == VT_LDOUBLE)
678 op|=0x400000;
679 #endif
680 o(op|(fpr(r)<<12)|(fc>>2)|(base<<16));
681 #endif
682 return;
683 } else if((ft & VT_BTYPE) == VT_SHORT) {
684 calcaddr(&base,&fc,&sign,255,0);
685 op=0xE14000B0;
686 if(!sign)
687 op|=0x800000;
688 o(op|(intr(r)<<12)|(base<<16)|((fc&0xf0)<<4)|(fc&0xf));
689 } else {
690 calcaddr(&base,&fc,&sign,4095,0);
691 op=0xE5000000;
692 if(!sign)
693 op|=0x800000;
694 if ((ft & VT_BTYPE) == VT_BYTE)
695 op|=0x400000;
696 o(op|(intr(r)<<12)|fc|(base<<16));
698 return;
701 tcc_error("store unimplemented");
704 static void gadd_sp(int val)
706 stuff_const_harder(0xE28DD000,val);
709 /* 'is_jmp' is '1' if it is a jump */
710 static void gcall_or_jmp(int is_jmp)
712 int r;
713 if ((vtop->r & (VT_VALMASK | VT_LVAL)) == VT_CONST) {
714 uint32_t x;
715 /* constant case */
716 x=encbranch(ind,ind+vtop->c.ul,0);
717 if(x) {
718 if (vtop->r & VT_SYM) {
719 /* relocation case */
720 greloc(cur_text_section, vtop->sym, ind, R_ARM_PC24);
721 } else
722 put_elf_reloc(symtab_section, cur_text_section, ind, R_ARM_PC24, 0);
723 o(x|(is_jmp?0xE0000000:0xE1000000));
724 } else {
725 if(!is_jmp)
726 o(0xE28FE004); // add lr,pc,#4
727 o(0xE51FF004); // ldr pc,[pc,#-4]
728 if (vtop->r & VT_SYM)
729 greloc(cur_text_section, vtop->sym, ind, R_ARM_ABS32);
730 o(vtop->c.ul);
732 } else {
733 /* otherwise, indirect call */
734 r = gv(RC_INT);
735 if(!is_jmp)
736 o(0xE1A0E00F); // mov lr,pc
737 o(0xE1A0F000|intr(r)); // mov pc,r
741 #ifdef TCC_ARM_HARDFLOAT
742 static int is_float_hgen_aggr(CType *type)
744 if ((type->t & VT_BTYPE) == VT_STRUCT) {
745 struct Sym *ref;
746 int btype, nb_fields = 0;
748 ref = type->ref;
749 btype = ref->type.t & VT_BTYPE;
750 if (btype == VT_FLOAT || btype == VT_DOUBLE) {
751 for(; ref && btype == (ref->type.t & VT_BTYPE); ref = ref->next, nb_fields++);
752 return !ref && nb_fields <= 4;
755 return 0;
758 struct avail_regs {
759 /* worst case: f(float, double, 3 float struct, double, 3 float struct, double) */
760 signed char avail[3];
761 int first_hole;
762 int last_hole;
763 int first_free_reg;
766 #define AVAIL_REGS_INITIALIZER (struct avail_regs) { { 0, 0, 0}, 0, 0, 0 }
768 /* Assign a register for a CPRC param with correct size and alignment
769 * size and align are in bytes, as returned by type_size */
770 int assign_fpreg(struct avail_regs *avregs, int align, int size)
772 int first_reg = 0;
774 if (avregs->first_free_reg == -1)
775 return -1;
776 if (align >> 3) { // alignment needed (base type: double)
777 first_reg = avregs->first_free_reg;
778 if (first_reg & 1)
779 avregs->avail[avregs->last_hole++] = first_reg++;
780 } else {
781 if (size == 4 && avregs->first_hole != avregs->last_hole)
782 return avregs->avail[avregs->first_hole++];
783 else
784 first_reg = avregs->first_free_reg;
786 if (first_reg + size / 4 <= 16) {
787 avregs->first_free_reg = first_reg + size / 4;
788 return first_reg;
790 avregs->first_free_reg = -1;
791 return -1;
793 #endif
795 /* Generate function call. The function address is pushed first, then
796 all the parameters in call order. This functions pops all the
797 parameters and the function address. */
798 void gfunc_call(int nb_args)
800 int size, align, r, args_size, i, ncrn, ncprn, argno, vfp_argno;
801 signed char plan[4][2]={{-1,-1},{-1,-1},{-1,-1},{-1,-1}};
802 SValue *before_stack = NULL; /* SValue before first on stack argument */
803 SValue *before_vfpreg_hfa = NULL; /* SValue before first in VFP reg hfa argument */
804 #ifdef TCC_ARM_HARDFLOAT
805 struct avail_regs avregs = AVAIL_REGS_INITIALIZER;
806 signed char vfp_plan[16];
807 int plan2[4+16];
808 int variadic;
809 #else
810 int plan2[4]={0,0,0,0};
811 #endif
812 int vfp_todo=0;
813 int todo=0, keep;
815 #ifdef TCC_ARM_HARDFLOAT
816 memset(vfp_plan, -1, sizeof(vfp_plan));
817 memset(plan2, 0, sizeof(plan2));
818 variadic = (vtop[-nb_args].type.ref->c == FUNC_ELLIPSIS);
819 #endif
820 r = vtop->r & VT_VALMASK;
821 if (r == VT_CMP || (r & ~1) == VT_JMP)
822 gv(RC_INT);
823 #ifdef TCC_ARM_EABI
824 if((vtop[-nb_args].type.ref->type.t & VT_BTYPE) == VT_STRUCT
825 && type_size(&vtop[-nb_args].type.ref->type, &align) <= 4) {
826 SValue tmp;
827 tmp=vtop[-nb_args];
828 vtop[-nb_args]=vtop[-nb_args+1];
829 vtop[-nb_args+1]=tmp;
830 --nb_args;
833 vpushi(0), nb_args++;
834 vtop->type.t = VT_LLONG;
835 args_size = 0;
836 #endif
837 ncrn = ncprn = argno = vfp_argno = 0;
838 /* Assign argument to registers and stack with alignment.
839 If, considering alignment constraints, enough registers of the correct type
840 (core or VFP) are free for the current argument, assign them to it, else
841 allocate on stack with correct alignment. Whenever a structure is allocated
842 in registers or on stack, it is always put on the stack at this stage. The
843 stack is divided in 3 zones. The zone are, from low addresses to high
844 addresses: structures to be loaded in core registers, structures to be
845 loaded in VFP registers, argument allocated to stack. SValue's representing
846 structures in the first zone are moved just after the SValue pointed by
847 before_vfpreg_hfa. SValue's representing structures in the second zone are
848 moved just after the SValue pointer by before_stack. */
849 for(i = nb_args; i-- ;) {
850 int j, assigned_vfpreg = 0;
851 size = type_size(&vtop[-i].type, &align);
852 switch(vtop[-i].type.t & VT_BTYPE) {
853 case VT_STRUCT:
854 case VT_FLOAT:
855 case VT_DOUBLE:
856 case VT_LDOUBLE:
857 #ifdef TCC_ARM_HARDFLOAT
858 if (!variadic) {
859 int hfa = 0; /* Homogeneous float aggregate */
861 if (is_float(vtop[-i].type.t)
862 || (hfa = is_float_hgen_aggr(&vtop[-i].type))) {
863 int end_reg;
865 assigned_vfpreg = assign_fpreg(&avregs, align, size);
866 end_reg = assigned_vfpreg + (size - 1) / 4;
867 if (assigned_vfpreg >= 0) {
868 vfp_plan[vfp_argno++]=TREG_F0 + assigned_vfpreg/2;
869 if (hfa) {
870 /* before_stack can only have been set because all core registers
871 are assigned, so no need to care about before_vfpreg_hfa if
872 before_stack is set */
873 if (before_stack) {
874 vrote(&vtop[-i], &vtop[-i] - before_stack);
875 before_stack++;
876 } else if (!before_vfpreg_hfa)
877 before_vfpreg_hfa = &vtop[-i-1];
878 for (j = assigned_vfpreg; j <= end_reg; j++)
879 vfp_todo|=(1<<j);
881 continue;
882 } else {
883 if (!hfa)
884 vfp_argno++;
885 /* No need to update before_stack as no more hfa can be allocated in
886 VFP regs */
887 if (!before_vfpreg_hfa)
888 before_vfpreg_hfa = &vtop[-i-1];
889 break;
893 #endif
894 ncrn = (ncrn + (align-1)/4) & -(align/4);
895 size = (size + 3) & -4;
896 if (ncrn + size/4 <= 4 || (ncrn < 4 && assigned_vfpreg != -1)) {
897 /* Either there is HFA in VFP registers, or there is arguments on stack,
898 it cannot be both. Hence either before_stack already points after
899 the slot where the vtop[-i] SValue is moved, or before_stack will not
900 be used */
901 if (before_vfpreg_hfa) {
902 vrote(&vtop[-i], &vtop[-i] - before_vfpreg_hfa);
903 before_vfpreg_hfa++;
905 for (j = ncrn; j < 4 && j < ncrn + size / 4; j++)
906 todo|=(1<<j);
907 ncrn+=size/4;
908 if (ncrn > 4) {
909 args_size = (ncrn - 4) * 4;
910 if (!before_stack)
911 before_stack = &vtop[-i-1];
914 else {
915 ncrn = 4;
916 /* No need to set before_vfpreg_hfa if not set since there will no
917 longer be any structure assigned to core registers */
918 if (!before_stack)
919 before_stack = &vtop[-i-1];
920 break;
922 continue;
923 default:
924 #ifdef TCC_ARM_EABI
925 if (!i) {
926 break;
928 #endif
929 if (ncrn < 4) {
930 int is_long = (vtop[-i].type.t & VT_BTYPE) == VT_LLONG;
932 if (is_long) {
933 ncrn = (ncrn + 1) & -2;
934 if (ncrn == 4) {
935 argno++;
936 break;
939 plan[argno++][0]=ncrn++;
940 if (is_long) {
941 plan[argno-1][1]=ncrn++;
943 continue;
945 argno++;
947 #ifdef TCC_ARM_EABI
948 if(args_size & (align-1)) {
949 vpushi(0);
950 vtop->type.t = VT_VOID; /* padding */
951 vrott(i+2);
952 args_size += 4;
953 nb_args++;
954 argno++;
956 #endif
957 args_size += (size + 3) & -4;
959 #ifdef TCC_ARM_EABI
960 vtop--, nb_args--;
961 #endif
962 args_size = keep = 0;
963 for(i = 0;i < nb_args; i++) {
964 vrotb(keep+1);
965 if ((vtop->type.t & VT_BTYPE) == VT_STRUCT) {
966 size = type_size(&vtop->type, &align);
967 /* align to stack align size */
968 size = (size + 3) & -4;
969 /* allocate the necessary size on stack */
970 gadd_sp(-size);
971 /* generate structure store */
972 r = get_reg(RC_INT);
973 o(0xE1A0000D|(intr(r)<<12));
974 vset(&vtop->type, r | VT_LVAL, 0);
975 vswap();
976 vstore();
977 vtop--;
978 args_size += size;
979 } else if (is_float(vtop->type.t)) {
980 #ifdef TCC_ARM_HARDFLOAT
981 if (!variadic && --vfp_argno<16 && vfp_plan[vfp_argno]!=-1) {
982 plan2[keep++]=vfp_plan[vfp_argno];
983 continue;
985 #endif
986 #ifdef TCC_ARM_VFP
987 r=vfpr(gv(RC_FLOAT))<<12;
988 size=4;
989 if ((vtop->type.t & VT_BTYPE) != VT_FLOAT)
991 size=8;
992 r|=0x101; /* fstms -> fstmd */
994 o(0xED2D0A01+r);
995 #else
996 r=fpr(gv(RC_FLOAT))<<12;
997 if ((vtop->type.t & VT_BTYPE) == VT_FLOAT)
998 size = 4;
999 else if ((vtop->type.t & VT_BTYPE) == VT_DOUBLE)
1000 size = 8;
1001 else
1002 size = LDOUBLE_SIZE;
1004 if (size == 12)
1005 r|=0x400000;
1006 else if(size == 8)
1007 r|=0x8000;
1009 o(0xED2D0100|r|(size>>2));
1010 #endif
1011 vtop--;
1012 args_size += size;
1013 } else {
1014 int s;
1015 /* simple type (currently always same size) */
1016 /* XXX: implicit cast ? */
1017 size=4;
1018 if ((vtop->type.t & VT_BTYPE) == VT_LLONG) {
1019 lexpand_nr();
1020 s=-1;
1021 if(--argno<4 && plan[argno][1]!=-1)
1022 s=plan[argno][1];
1023 argno++;
1024 size = 8;
1025 if(s==-1) {
1026 r = gv(RC_INT);
1027 o(0xE52D0004|(intr(r)<<12)); /* str r,[sp,#-4]! */
1028 vtop--;
1029 } else {
1030 size=0;
1031 plan2[keep]=s;
1032 keep++;
1033 vswap();
1036 s=-1;
1037 if(--argno<4 && plan[argno][0]!=-1)
1038 s=plan[argno][0];
1039 #ifdef TCC_ARM_EABI
1040 if(vtop->type.t == VT_VOID) {
1041 if(s == -1)
1042 o(0xE24DD004); /* sub sp,sp,#4 */
1043 vtop--;
1044 } else
1045 #endif
1046 if(s == -1) {
1047 r = gv(RC_INT);
1048 o(0xE52D0004|(intr(r)<<12)); /* str r,[sp,#-4]! */
1049 vtop--;
1050 } else {
1051 size=0;
1052 plan2[keep]=s;
1053 keep++;
1055 args_size += size;
1058 for(i = 0; i < keep; i++) {
1059 vrotb(keep);
1060 gv(regmask(plan2[i]));
1061 #ifdef TCC_ARM_HARDFLOAT
1062 /* arg is in s(2d+1): plan2[i]<plan2[i+1] => alignment occured (ex f,d,f) */
1063 if (i < keep - 1 && is_float(vtop->type.t) && (plan2[i] <= plan2[i + 1])) {
1064 o(0xEEF00A40|(vfpr(plan2[i])<<12)|vfpr(plan2[i]));
1066 #endif
1068 save_regs(keep); /* save used temporary registers */
1069 keep++;
1070 if(ncrn) {
1071 int nb_regs=0;
1072 if (ncrn>4)
1073 ncrn=4;
1074 todo&=((1<<ncrn)-1);
1075 if(todo) {
1076 int i;
1077 o(0xE8BD0000|todo);
1078 for(i=0;i<4;i++)
1079 if(todo&(1<<i)) {
1080 vpushi(0);
1081 vtop->r=i;
1082 keep++;
1083 nb_regs++;
1086 args_size-=nb_regs*4;
1088 if(vfp_todo) {
1089 int nb_fregs=0;
1091 for(i=0;i<16;i++)
1092 if(vfp_todo&(1<<i)) {
1093 o(0xED9D0A00|(i&1)<<22|(i>>1)<<12|nb_fregs);
1094 vpushi(0);
1095 /* There might be 2 floats in a double VFP reg but that doesn't seem
1096 to matter */
1097 if (!(i%2))
1098 vtop->r=TREG_F0+i/2;
1099 keep++;
1100 nb_fregs++;
1102 if (nb_fregs) {
1103 gadd_sp(nb_fregs*4);
1104 args_size-=nb_fregs*4;
1107 vrotb(keep);
1108 gcall_or_jmp(0);
1109 if (args_size)
1110 gadd_sp(args_size);
1111 #ifdef TCC_ARM_EABI
1112 if((vtop->type.ref->type.t & VT_BTYPE) == VT_STRUCT
1113 && type_size(&vtop->type.ref->type, &align) <= 4)
1115 store(REG_IRET,vtop-keep);
1116 ++keep;
1118 #ifdef TCC_ARM_VFP
1119 #ifdef TCC_ARM_HARDFLOAT
1120 else if(variadic && is_float(vtop->type.ref->type.t)) {
1121 #else
1122 else if(is_float(vtop->type.ref->type.t)) {
1123 #endif
1124 if((vtop->type.ref->type.t & VT_BTYPE) == VT_FLOAT) {
1125 o(0xEE000A10); /* fmsr s0,r0 */
1126 } else {
1127 o(0xEE000B10); /* fmdlr d0,r0 */
1128 o(0xEE201B10); /* fmdhr d0,r1 */
1131 #endif
1132 #endif
1133 vtop-=keep;
1134 leaffunc = 0;
1137 /* generate function prolog of type 't' */
1138 void gfunc_prolog(CType *func_type)
1140 Sym *sym,*sym2;
1141 int n,nf,size,align, variadic, struct_ret = 0;
1142 #ifdef TCC_ARM_HARDFLOAT
1143 struct avail_regs avregs = AVAIL_REGS_INITIALIZER;
1144 #endif
1146 sym = func_type->ref;
1147 func_vt = sym->type;
1149 n = nf = 0;
1150 variadic = (func_type->ref->c == FUNC_ELLIPSIS);
1151 if((func_vt.t & VT_BTYPE) == VT_STRUCT
1152 && type_size(&func_vt,&align) > 4)
1154 n++;
1155 struct_ret = 1;
1156 func_vc = 12; /* Offset from fp of the place to store the result */
1158 for(sym2=sym->next;sym2 && (n<4 || nf<16);sym2=sym2->next) {
1159 size = type_size(&sym2->type, &align);
1160 #ifdef TCC_ARM_HARDFLOAT
1161 if (!variadic && (is_float(sym2->type.t)
1162 || is_float_hgen_aggr(&sym2->type))) {
1163 int tmpnf = assign_fpreg(&avregs, align, size) + 1;
1164 nf = (tmpnf > nf) ? tmpnf : nf;
1165 } else
1166 #endif
1167 if (n < 4)
1168 n += (size + 3) / 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(0xE1A0B00D); /* mov fp, sp */
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+12);
1233 last_itod_magic=0;
1234 leaffunc = 1;
1235 loc = 0;
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(0xE89BA800); /* restore fp, sp, pc */
1256 diff = (-loc + 3) & -4;
1257 #ifdef TCC_ARM_EABI
1258 if(!leaffunc)
1259 diff = ((diff + 11) & -8) - 4;
1260 #endif
1261 if(diff > 0) {
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 /*************************************************************/