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