Deprecate FPA and OABI support for ARM
[tinycc.git] / arm-gen.c
blob9aa093eb37ac22ab5087c51bcf06100a1c98d621
1 /*
2 * ARMv4 code generator for TCC
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 #if defined(TCC_ARM_EABI) && !defined(TCC_ARM_VFP)
27 #error "Currently TinyCC only supports float computation with VFP instructions"
28 #endif
30 /* number of available registers */
31 #ifdef TCC_ARM_VFP
32 #define NB_REGS 13
33 #else
34 #define NB_REGS 9
35 #endif
37 #ifndef TCC_ARM_VERSION
38 # define TCC_ARM_VERSION 5
39 #endif
41 /* a register can belong to several classes. The classes must be
42 sorted from more general to more precise (see gv2() code which does
43 assumptions on it). */
44 #define RC_INT 0x0001 /* generic integer register */
45 #define RC_FLOAT 0x0002 /* generic float register */
46 #define RC_R0 0x0004
47 #define RC_R1 0x0008
48 #define RC_R2 0x0010
49 #define RC_R3 0x0020
50 #define RC_R12 0x0040
51 #define RC_F0 0x0080
52 #define RC_F1 0x0100
53 #define RC_F2 0x0200
54 #define RC_F3 0x0400
55 #ifdef TCC_ARM_VFP
56 #define RC_F4 0x0800
57 #define RC_F5 0x1000
58 #define RC_F6 0x2000
59 #define RC_F7 0x4000
60 #endif
61 #define RC_IRET RC_R0 /* function return: integer register */
62 #define RC_LRET RC_R1 /* function return: second integer register */
63 #define RC_FRET RC_F0 /* function return: float register */
65 /* pretty names for the registers */
66 enum {
67 TREG_R0 = 0,
68 TREG_R1,
69 TREG_R2,
70 TREG_R3,
71 TREG_R12,
72 TREG_F0,
73 TREG_F1,
74 TREG_F2,
75 TREG_F3,
76 #ifdef TCC_ARM_VFP
77 TREG_F4,
78 TREG_F5,
79 TREG_F6,
80 TREG_F7,
81 #endif
84 #ifdef TCC_ARM_VFP
85 #define T2CPR(t) (((t) & VT_BTYPE) != VT_FLOAT ? 0x100 : 0)
86 #endif
88 /* return registers for function */
89 #define REG_IRET TREG_R0 /* single word int return register */
90 #define REG_LRET TREG_R1 /* second word return register (for long long) */
91 #define REG_FRET TREG_F0 /* float return register */
93 #ifdef TCC_ARM_EABI
94 #define TOK___divdi3 TOK___aeabi_ldivmod
95 #define TOK___moddi3 TOK___aeabi_ldivmod
96 #define TOK___udivdi3 TOK___aeabi_uldivmod
97 #define TOK___umoddi3 TOK___aeabi_uldivmod
98 #endif
100 /* defined if function parameters must be evaluated in reverse order */
101 #define INVERT_FUNC_PARAMS
103 /* defined if structures are passed as pointers. Otherwise structures
104 are directly pushed on stack. */
105 /* #define FUNC_STRUCT_PARAM_AS_PTR */
107 /* pointer size, in bytes */
108 #define PTR_SIZE 4
110 /* long double size and alignment, in bytes */
111 #ifdef TCC_ARM_VFP
112 #define LDOUBLE_SIZE 8
113 #endif
115 #ifndef LDOUBLE_SIZE
116 #define LDOUBLE_SIZE 8
117 #endif
119 #ifdef TCC_ARM_EABI
120 #define LDOUBLE_ALIGN 8
121 #else
122 #define LDOUBLE_ALIGN 4
123 #endif
125 /* maximum alignment (for aligned attribute support) */
126 #define MAX_ALIGN 8
128 #define CHAR_IS_UNSIGNED
130 /******************************************************/
131 /* ELF defines */
133 #define EM_TCC_TARGET EM_ARM
135 /* relocation type for 32 bit data relocation */
136 #define R_DATA_32 R_ARM_ABS32
137 #define R_DATA_PTR R_ARM_ABS32
138 #define R_JMP_SLOT R_ARM_JUMP_SLOT
139 #define R_COPY R_ARM_COPY
141 #define ELF_START_ADDR 0x00008000
142 #define ELF_PAGE_SIZE 0x1000
144 enum float_abi {
145 ARM_SOFTFP_FLOAT,
146 ARM_HARD_FLOAT,
149 /******************************************************/
150 #else /* ! TARGET_DEFS_ONLY */
151 /******************************************************/
152 #include "tcc.h"
154 enum float_abi float_abi;
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 static int func_sub_sp_offset, last_itod_magic;
175 static int leaffunc;
177 #if defined(TCC_ARM_EABI) && defined(TCC_ARM_VFP)
178 static CType float_type, double_type, func_float_type, func_double_type;
179 ST_FUNC void arm_init(struct TCCState *s)
181 float_type.t = VT_FLOAT;
182 double_type.t = VT_DOUBLE;
183 func_float_type.t = VT_FUNC;
184 func_float_type.ref = sym_push(SYM_FIELD, &float_type, FUNC_CDECL, FUNC_OLD);
185 func_double_type.t = VT_FUNC;
186 func_double_type.ref = sym_push(SYM_FIELD, &double_type, FUNC_CDECL, FUNC_OLD);
188 float_abi = s->float_abi;
190 #else
191 #define func_float_type func_old_type
192 #define func_double_type func_old_type
193 #define func_ldouble_type func_old_type
194 ST_FUNC void arm_init(struct TCCState *s)
196 #if !defined (TCC_ARM_VFP)
197 tcc_warning("Support for FPA is deprecated and will be removed in next"
198 " release");
199 #endif
200 #if !defined (TCC_ARM_EABI)
201 tcc_warning("Support for OABI is deprecated and will be removed in next"
202 " release");
203 #endif
205 #endif
207 static int two2mask(int a,int b) {
208 return (reg_classes[a]|reg_classes[b])&~(RC_INT|RC_FLOAT);
211 static int regmask(int r) {
212 return reg_classes[r]&~(RC_INT|RC_FLOAT);
215 /******************************************************/
217 #ifdef TCC_ARM_EABI
218 char *default_elfinterp(struct TCCState *s)
220 if (s->float_abi == ARM_HARD_FLOAT)
221 return "/lib/ld-linux-armhf.so.3";
222 else
223 return "/lib/ld-linux.so.3";
225 #endif
227 void o(uint32_t i)
229 /* this is a good place to start adding big-endian support*/
230 int ind1;
232 ind1 = ind + 4;
233 if (!cur_text_section)
234 tcc_error("compiler error! This happens f.ex. if the compiler\n"
235 "can't evaluate constant expressions outside of a function.");
236 if (ind1 > cur_text_section->data_allocated)
237 section_realloc(cur_text_section, ind1);
238 cur_text_section->data[ind++] = i&255;
239 i>>=8;
240 cur_text_section->data[ind++] = i&255;
241 i>>=8;
242 cur_text_section->data[ind++] = i&255;
243 i>>=8;
244 cur_text_section->data[ind++] = i;
247 static uint32_t stuff_const(uint32_t op, uint32_t c)
249 int try_neg=0;
250 uint32_t nc = 0, negop = 0;
252 switch(op&0x1F00000)
254 case 0x800000: //add
255 case 0x400000: //sub
256 try_neg=1;
257 negop=op^0xC00000;
258 nc=-c;
259 break;
260 case 0x1A00000: //mov
261 case 0x1E00000: //mvn
262 try_neg=1;
263 negop=op^0x400000;
264 nc=~c;
265 break;
266 case 0x200000: //xor
267 if(c==~0)
268 return (op&0xF010F000)|((op>>16)&0xF)|0x1E00000;
269 break;
270 case 0x0: //and
271 if(c==~0)
272 return (op&0xF010F000)|((op>>16)&0xF)|0x1A00000;
273 case 0x1C00000: //bic
274 try_neg=1;
275 negop=op^0x1C00000;
276 nc=~c;
277 break;
278 case 0x1800000: //orr
279 if(c==~0)
280 return (op&0xFFF0FFFF)|0x1E00000;
281 break;
283 do {
284 uint32_t m;
285 int i;
286 if(c<256) /* catch undefined <<32 */
287 return op|c;
288 for(i=2;i<32;i+=2) {
289 m=(0xff>>i)|(0xff<<(32-i));
290 if(!(c&~m))
291 return op|(i<<7)|(c<<i)|(c>>(32-i));
293 op=negop;
294 c=nc;
295 } while(try_neg--);
296 return 0;
300 //only add,sub
301 void stuff_const_harder(uint32_t op, uint32_t v) {
302 uint32_t x;
303 x=stuff_const(op,v);
304 if(x)
305 o(x);
306 else {
307 uint32_t a[16], nv, no, o2, n2;
308 int i,j,k;
309 a[0]=0xff;
310 o2=(op&0xfff0ffff)|((op&0xf000)<<4);;
311 for(i=1;i<16;i++)
312 a[i]=(a[i-1]>>2)|(a[i-1]<<30);
313 for(i=0;i<12;i++)
314 for(j=i<4?i+12:15;j>=i+4;j--)
315 if((v&(a[i]|a[j]))==v) {
316 o(stuff_const(op,v&a[i]));
317 o(stuff_const(o2,v&a[j]));
318 return;
320 no=op^0xC00000;
321 n2=o2^0xC00000;
322 nv=-v;
323 for(i=0;i<12;i++)
324 for(j=i<4?i+12:15;j>=i+4;j--)
325 if((nv&(a[i]|a[j]))==nv) {
326 o(stuff_const(no,nv&a[i]));
327 o(stuff_const(n2,nv&a[j]));
328 return;
330 for(i=0;i<8;i++)
331 for(j=i+4;j<12;j++)
332 for(k=i<4?i+12:15;k>=j+4;k--)
333 if((v&(a[i]|a[j]|a[k]))==v) {
334 o(stuff_const(op,v&a[i]));
335 o(stuff_const(o2,v&a[j]));
336 o(stuff_const(o2,v&a[k]));
337 return;
339 no=op^0xC00000;
340 nv=-v;
341 for(i=0;i<8;i++)
342 for(j=i+4;j<12;j++)
343 for(k=i<4?i+12:15;k>=j+4;k--)
344 if((nv&(a[i]|a[j]|a[k]))==nv) {
345 o(stuff_const(no,nv&a[i]));
346 o(stuff_const(n2,nv&a[j]));
347 o(stuff_const(n2,nv&a[k]));
348 return;
350 o(stuff_const(op,v&a[0]));
351 o(stuff_const(o2,v&a[4]));
352 o(stuff_const(o2,v&a[8]));
353 o(stuff_const(o2,v&a[12]));
357 ST_FUNC uint32_t encbranch(int pos, int addr, int fail)
359 addr-=pos+8;
360 addr/=4;
361 if(addr>=0x1000000 || addr<-0x1000000) {
362 if(fail)
363 tcc_error("FIXME: function bigger than 32MB");
364 return 0;
366 return 0x0A000000|(addr&0xffffff);
369 int decbranch(int pos)
371 int x;
372 x=*(uint32_t *)(cur_text_section->data + pos);
373 x&=0x00ffffff;
374 if(x&0x800000)
375 x-=0x1000000;
376 return x*4+pos+8;
379 /* output a symbol and patch all calls to it */
380 void gsym_addr(int t, int a)
382 uint32_t *x;
383 int lt;
384 while(t) {
385 x=(uint32_t *)(cur_text_section->data + t);
386 t=decbranch(lt=t);
387 if(a==lt+4)
388 *x=0xE1A00000; // nop
389 else {
390 *x &= 0xff000000;
391 *x |= encbranch(lt,a,1);
396 void gsym(int t)
398 gsym_addr(t, ind);
401 #ifdef TCC_ARM_VFP
402 static uint32_t vfpr(int r)
404 if(r<TREG_F0 || r>TREG_F7)
405 tcc_error("compiler error! register %i is no vfp register",r);
406 return r-5;
408 #else
409 static uint32_t fpr(int r)
411 if(r<TREG_F0 || r>TREG_F3)
412 tcc_error("compiler error! register %i is no fpa register",r);
413 return r-5;
415 #endif
417 static uint32_t intr(int r)
419 if(r==4)
420 return 12;
421 if((r<0 || r>4) && r!=14)
422 tcc_error("compiler error! register %i is no int register",r);
423 return r;
426 static void calcaddr(uint32_t *base, int *off, int *sgn, int maxoff, unsigned shift)
428 if(*off>maxoff || *off&((1<<shift)-1)) {
429 uint32_t x, y;
430 x=0xE280E000;
431 if(*sgn)
432 x=0xE240E000;
433 x|=(*base)<<16;
434 *base=14; // lr
435 y=stuff_const(x,*off&~maxoff);
436 if(y) {
437 o(y);
438 *off&=maxoff;
439 return;
441 y=stuff_const(x,(*off+maxoff)&~maxoff);
442 if(y) {
443 o(y);
444 *sgn=!*sgn;
445 *off=((*off+maxoff)&~maxoff)-*off;
446 return;
448 stuff_const_harder(x,*off&~maxoff);
449 *off&=maxoff;
453 static uint32_t mapcc(int cc)
455 switch(cc)
457 case TOK_ULT:
458 return 0x30000000; /* CC/LO */
459 case TOK_UGE:
460 return 0x20000000; /* CS/HS */
461 case TOK_EQ:
462 return 0x00000000; /* EQ */
463 case TOK_NE:
464 return 0x10000000; /* NE */
465 case TOK_ULE:
466 return 0x90000000; /* LS */
467 case TOK_UGT:
468 return 0x80000000; /* HI */
469 case TOK_Nset:
470 return 0x40000000; /* MI */
471 case TOK_Nclear:
472 return 0x50000000; /* PL */
473 case TOK_LT:
474 return 0xB0000000; /* LT */
475 case TOK_GE:
476 return 0xA0000000; /* GE */
477 case TOK_LE:
478 return 0xD0000000; /* LE */
479 case TOK_GT:
480 return 0xC0000000; /* GT */
482 tcc_error("unexpected condition code");
483 return 0xE0000000; /* AL */
486 static int negcc(int cc)
488 switch(cc)
490 case TOK_ULT:
491 return TOK_UGE;
492 case TOK_UGE:
493 return TOK_ULT;
494 case TOK_EQ:
495 return TOK_NE;
496 case TOK_NE:
497 return TOK_EQ;
498 case TOK_ULE:
499 return TOK_UGT;
500 case TOK_UGT:
501 return TOK_ULE;
502 case TOK_Nset:
503 return TOK_Nclear;
504 case TOK_Nclear:
505 return TOK_Nset;
506 case TOK_LT:
507 return TOK_GE;
508 case TOK_GE:
509 return TOK_LT;
510 case TOK_LE:
511 return TOK_GT;
512 case TOK_GT:
513 return TOK_LE;
515 tcc_error("unexpected condition code");
516 return TOK_NE;
519 /* load 'r' from value 'sv' */
520 void load(int r, SValue *sv)
522 int v, ft, fc, fr, sign;
523 uint32_t op;
524 SValue v1;
526 fr = sv->r;
527 ft = sv->type.t;
528 fc = sv->c.ul;
530 if(fc>=0)
531 sign=0;
532 else {
533 sign=1;
534 fc=-fc;
537 v = fr & VT_VALMASK;
538 if (fr & VT_LVAL) {
539 uint32_t base = 0xB; // fp
540 if(v == VT_LLOCAL) {
541 v1.type.t = VT_PTR;
542 v1.r = VT_LOCAL | VT_LVAL;
543 v1.c.ul = sv->c.ul;
544 load(base=14 /* lr */, &v1);
545 fc=sign=0;
546 v=VT_LOCAL;
547 } else if(v == VT_CONST) {
548 v1.type.t = VT_PTR;
549 v1.r = fr&~VT_LVAL;
550 v1.c.ul = sv->c.ul;
551 v1.sym=sv->sym;
552 load(base=14, &v1);
553 fc=sign=0;
554 v=VT_LOCAL;
555 } else if(v < VT_CONST) {
556 base=intr(v);
557 fc=sign=0;
558 v=VT_LOCAL;
560 if(v == VT_LOCAL) {
561 if(is_float(ft)) {
562 calcaddr(&base,&fc,&sign,1020,2);
563 #ifdef TCC_ARM_VFP
564 op=0xED100A00; /* flds */
565 if(!sign)
566 op|=0x800000;
567 if ((ft & VT_BTYPE) != VT_FLOAT)
568 op|=0x100; /* flds -> fldd */
569 o(op|(vfpr(r)<<12)|(fc>>2)|(base<<16));
570 #else
571 op=0xED100100;
572 if(!sign)
573 op|=0x800000;
574 #if LDOUBLE_SIZE == 8
575 if ((ft & VT_BTYPE) != VT_FLOAT)
576 op|=0x8000;
577 #else
578 if ((ft & VT_BTYPE) == VT_DOUBLE)
579 op|=0x8000;
580 else if ((ft & VT_BTYPE) == VT_LDOUBLE)
581 op|=0x400000;
582 #endif
583 o(op|(fpr(r)<<12)|(fc>>2)|(base<<16));
584 #endif
585 } else if((ft & (VT_BTYPE|VT_UNSIGNED)) == VT_BYTE
586 || (ft & VT_BTYPE) == VT_SHORT) {
587 calcaddr(&base,&fc,&sign,255,0);
588 op=0xE1500090;
589 if ((ft & VT_BTYPE) == VT_SHORT)
590 op|=0x20;
591 if ((ft & VT_UNSIGNED) == 0)
592 op|=0x40;
593 if(!sign)
594 op|=0x800000;
595 o(op|(intr(r)<<12)|(base<<16)|((fc&0xf0)<<4)|(fc&0xf));
596 } else {
597 calcaddr(&base,&fc,&sign,4095,0);
598 op=0xE5100000;
599 if(!sign)
600 op|=0x800000;
601 if ((ft & VT_BTYPE) == VT_BYTE || (ft & VT_BTYPE) == VT_BOOL)
602 op|=0x400000;
603 o(op|(intr(r)<<12)|fc|(base<<16));
605 return;
607 } else {
608 if (v == VT_CONST) {
609 op=stuff_const(0xE3A00000|(intr(r)<<12),sv->c.ul);
610 if (fr & VT_SYM || !op) {
611 o(0xE59F0000|(intr(r)<<12));
612 o(0xEA000000);
613 if(fr & VT_SYM)
614 greloc(cur_text_section, sv->sym, ind, R_ARM_ABS32);
615 o(sv->c.ul);
616 } else
617 o(op);
618 return;
619 } else if (v == VT_LOCAL) {
620 op=stuff_const(0xE28B0000|(intr(r)<<12),sv->c.ul);
621 if (fr & VT_SYM || !op) {
622 o(0xE59F0000|(intr(r)<<12));
623 o(0xEA000000);
624 if(fr & VT_SYM) // needed ?
625 greloc(cur_text_section, sv->sym, ind, R_ARM_ABS32);
626 o(sv->c.ul);
627 o(0xE08B0000|(intr(r)<<12)|intr(r));
628 } else
629 o(op);
630 return;
631 } else if(v == VT_CMP) {
632 o(mapcc(sv->c.ul)|0x3A00001|(intr(r)<<12));
633 o(mapcc(negcc(sv->c.ul))|0x3A00000|(intr(r)<<12));
634 return;
635 } else if (v == VT_JMP || v == VT_JMPI) {
636 int t;
637 t = v & 1;
638 o(0xE3A00000|(intr(r)<<12)|t);
639 o(0xEA000000);
640 gsym(sv->c.ul);
641 o(0xE3A00000|(intr(r)<<12)|(t^1));
642 return;
643 } else if (v < VT_CONST) {
644 if(is_float(ft))
645 #ifdef TCC_ARM_VFP
646 o(0xEEB00A40|(vfpr(r)<<12)|vfpr(v)|T2CPR(ft)); /* fcpyX */
647 #else
648 o(0xEE008180|(fpr(r)<<12)|fpr(v));
649 #endif
650 else
651 o(0xE1A00000|(intr(r)<<12)|intr(v));
652 return;
655 tcc_error("load unimplemented!");
658 /* store register 'r' in lvalue 'v' */
659 void store(int r, SValue *sv)
661 SValue v1;
662 int v, ft, fc, fr, sign;
663 uint32_t op;
665 fr = sv->r;
666 ft = sv->type.t;
667 fc = sv->c.ul;
669 if(fc>=0)
670 sign=0;
671 else {
672 sign=1;
673 fc=-fc;
676 v = fr & VT_VALMASK;
677 if (fr & VT_LVAL || fr == VT_LOCAL) {
678 uint32_t base = 0xb;
679 if(v < VT_CONST) {
680 base=intr(v);
681 v=VT_LOCAL;
682 fc=sign=0;
683 } else if(v == VT_CONST) {
684 v1.type.t = ft;
685 v1.r = fr&~VT_LVAL;
686 v1.c.ul = sv->c.ul;
687 v1.sym=sv->sym;
688 load(base=14, &v1);
689 fc=sign=0;
690 v=VT_LOCAL;
692 if(v == VT_LOCAL) {
693 if(is_float(ft)) {
694 calcaddr(&base,&fc,&sign,1020,2);
695 #ifdef TCC_ARM_VFP
696 op=0xED000A00; /* fsts */
697 if(!sign)
698 op|=0x800000;
699 if ((ft & VT_BTYPE) != VT_FLOAT)
700 op|=0x100; /* fsts -> fstd */
701 o(op|(vfpr(r)<<12)|(fc>>2)|(base<<16));
702 #else
703 op=0xED000100;
704 if(!sign)
705 op|=0x800000;
706 #if LDOUBLE_SIZE == 8
707 if ((ft & VT_BTYPE) != VT_FLOAT)
708 op|=0x8000;
709 #else
710 if ((ft & VT_BTYPE) == VT_DOUBLE)
711 op|=0x8000;
712 if ((ft & VT_BTYPE) == VT_LDOUBLE)
713 op|=0x400000;
714 #endif
715 o(op|(fpr(r)<<12)|(fc>>2)|(base<<16));
716 #endif
717 return;
718 } else if((ft & VT_BTYPE) == VT_SHORT) {
719 calcaddr(&base,&fc,&sign,255,0);
720 op=0xE14000B0;
721 if(!sign)
722 op|=0x800000;
723 o(op|(intr(r)<<12)|(base<<16)|((fc&0xf0)<<4)|(fc&0xf));
724 } else {
725 calcaddr(&base,&fc,&sign,4095,0);
726 op=0xE5000000;
727 if(!sign)
728 op|=0x800000;
729 if ((ft & VT_BTYPE) == VT_BYTE || (ft & VT_BTYPE) == VT_BOOL)
730 op|=0x400000;
731 o(op|(intr(r)<<12)|fc|(base<<16));
733 return;
736 tcc_error("store unimplemented");
739 static void gadd_sp(int val)
741 stuff_const_harder(0xE28DD000,val);
744 /* 'is_jmp' is '1' if it is a jump */
745 static void gcall_or_jmp(int is_jmp)
747 int r;
748 if ((vtop->r & (VT_VALMASK | VT_LVAL)) == VT_CONST) {
749 uint32_t x;
750 /* constant case */
751 x=encbranch(ind,ind+vtop->c.ul,0);
752 if(x) {
753 if (vtop->r & VT_SYM) {
754 /* relocation case */
755 greloc(cur_text_section, vtop->sym, ind, R_ARM_PC24);
756 } else
757 put_elf_reloc(symtab_section, cur_text_section, ind, R_ARM_PC24, 0);
758 o(x|(is_jmp?0xE0000000:0xE1000000));
759 } else {
760 if(!is_jmp)
761 o(0xE28FE004); // add lr,pc,#4
762 o(0xE51FF004); // ldr pc,[pc,#-4]
763 if (vtop->r & VT_SYM)
764 greloc(cur_text_section, vtop->sym, ind, R_ARM_ABS32);
765 o(vtop->c.ul);
767 } else {
768 /* otherwise, indirect call */
769 r = gv(RC_INT);
770 if(!is_jmp)
771 o(0xE1A0E00F); // mov lr,pc
772 o(0xE1A0F000|intr(r)); // mov pc,r
776 /* Return whether a structure is an homogeneous float aggregate or not.
777 The answer is true if all the elements of the structure are of the same
778 primitive float type and there is less than 4 elements.
780 type: the type corresponding to the structure to be tested */
781 static int is_hgen_float_aggr(CType *type)
783 if ((type->t & VT_BTYPE) == VT_STRUCT) {
784 struct Sym *ref;
785 int btype, nb_fields = 0;
787 ref = type->ref->next;
788 btype = ref->type.t & VT_BTYPE;
789 if (btype == VT_FLOAT || btype == VT_DOUBLE) {
790 for(; ref && btype == (ref->type.t & VT_BTYPE); ref = ref->next, nb_fields++);
791 return !ref && nb_fields <= 4;
794 return 0;
797 struct avail_regs {
798 signed char avail[3]; /* 3 holes max with only float and double alignments */
799 int first_hole; /* first available hole */
800 int last_hole; /* last available hole (none if equal to first_hole) */
801 int first_free_reg; /* next free register in the sequence, hole excluded */
804 #define AVAIL_REGS_INITIALIZER (struct avail_regs) { { 0, 0, 0}, 0, 0, 0 }
806 /* Find suitable registers for a VFP Co-Processor Register Candidate (VFP CPRC
807 param) according to the rules described in the procedure call standard for
808 the ARM architecture (AAPCS). If found, the registers are assigned to this
809 VFP CPRC parameter. Registers are allocated in sequence unless a hole exists
810 and the parameter is a single float.
812 avregs: opaque structure to keep track of available VFP co-processor regs
813 align: alignment contraints for the param, as returned by type_size()
814 size: size of the parameter, as returned by type_size() */
815 int assign_vfpreg(struct avail_regs *avregs, int align, int size)
817 int first_reg = 0;
819 if (avregs->first_free_reg == -1)
820 return -1;
821 if (align >> 3) { /* double alignment */
822 first_reg = avregs->first_free_reg;
823 /* alignment contraint not respected so use next reg and record hole */
824 if (first_reg & 1)
825 avregs->avail[avregs->last_hole++] = first_reg++;
826 } else { /* no special alignment (float or array of float) */
827 /* if single float and a hole is available, assign the param to it */
828 if (size == 4 && avregs->first_hole != avregs->last_hole)
829 return avregs->avail[avregs->first_hole++];
830 else
831 first_reg = avregs->first_free_reg;
833 if (first_reg + size / 4 <= 16) {
834 avregs->first_free_reg = first_reg + size / 4;
835 return first_reg;
837 avregs->first_free_reg = -1;
838 return -1;
841 /* Returns whether all params need to be passed in core registers or not.
842 This is the case for function part of the runtime ABI. */
843 int floats_in_core_regs(SValue *sval)
845 if (!sval->sym)
846 return 0;
848 switch (sval->sym->v) {
849 case TOK___floatundisf:
850 case TOK___floatundidf:
851 case TOK___fixunssfdi:
852 case TOK___fixunsdfdi:
853 #ifndef TCC_ARM_VFP
854 case TOK___fixunsxfdi:
855 #endif
856 case TOK___floatdisf:
857 case TOK___floatdidf:
858 case TOK___fixsfdi:
859 case TOK___fixdfdi:
860 return 1;
862 default:
863 return 0;
867 /* Return the number of registers needed to return the struct, or 0 if
868 returning via struct pointer. */
869 ST_FUNC int gfunc_sret(CType *vt, int variadic, CType *ret, int *ret_align) {
870 #ifdef TCC_ARM_EABI
871 int size, align;
872 size = type_size(vt, &align);
873 if (float_abi == ARM_HARD_FLOAT && !variadic &&
874 (is_float(vt->t) || is_hgen_float_aggr(vt))) {
875 *ret_align = 8;
876 ret->ref = NULL;
877 ret->t = VT_DOUBLE;
878 return (size + 7) >> 3;
879 } else if (size <= 4) {
880 *ret_align = 4;
881 ret->ref = NULL;
882 ret->t = VT_INT;
883 return 1;
884 } else
885 return 0;
886 #else
887 return 0;
888 #endif
891 /* Parameters are classified according to how they are copied to their final
892 destination for the function call. Because the copying is performed class
893 after class according to the order in the union below, it is important that
894 some constraints about the order of the members of this union are respected:
895 - CORE_STRUCT_CLASS must come after STACK_CLASS;
896 - CORE_CLASS must come after STACK_CLASS, CORE_STRUCT_CLASS and
897 VFP_STRUCT_CLASS;
898 - VFP_STRUCT_CLASS must come after VFP_CLASS.
899 See the comment for the main loop in copy_params() for the reason. */
900 enum reg_class {
901 STACK_CLASS = 0,
902 CORE_STRUCT_CLASS,
903 VFP_CLASS,
904 VFP_STRUCT_CLASS,
905 CORE_CLASS,
906 NB_CLASSES
909 struct param_plan {
910 int start; /* first reg or addr used depending on the class */
911 int end; /* last reg used or next free addr depending on the class */
912 SValue *sval; /* pointer to SValue on the value stack */
913 struct param_plan *prev; /* previous element in this class */
916 struct plan {
917 struct param_plan *pplans; /* array of all the param plans */
918 struct param_plan *clsplans[NB_CLASSES]; /* per class lists of param plans */
921 #define add_param_plan(plan,pplan,class) \
922 do { \
923 pplan.prev = plan->clsplans[class]; \
924 plan->pplans[plan ## _nb] = pplan; \
925 plan->clsplans[class] = &plan->pplans[plan ## _nb++]; \
926 } while(0)
928 /* Assign parameters to registers and stack with alignment according to the
929 rules in the procedure call standard for the ARM architecture (AAPCS).
930 The overall assignment is recorded in an array of per parameter structures
931 called parameter plans. The parameter plans are also further organized in a
932 number of linked lists, one per class of parameter (see the comment for the
933 definition of union reg_class).
935 nb_args: number of parameters of the function for which a call is generated
936 float_abi: float ABI in use for this function call
937 plan: the structure where the overall assignment is recorded
938 todo: a bitmap that record which core registers hold a parameter
940 Returns the amount of stack space needed for parameter passing
942 Note: this function allocated an array in plan->pplans with tcc_malloc. It
943 is the responsability of the caller to free this array once used (ie not
944 before copy_params). */
945 static int assign_regs(int nb_args, int float_abi, struct plan *plan, int *todo)
947 int i, size, align;
948 int ncrn /* next core register number */, nsaa /* next stacked argument address*/;
949 int plan_nb = 0;
950 struct param_plan pplan;
951 struct avail_regs avregs = AVAIL_REGS_INITIALIZER;
953 ncrn = nsaa = 0;
954 *todo = 0;
955 plan->pplans = tcc_malloc(nb_args * sizeof(*plan->pplans));
956 memset(plan->clsplans, 0, sizeof(plan->clsplans));
957 for(i = nb_args; i-- ;) {
958 int j, start_vfpreg = 0;
959 size = type_size(&vtop[-i].type, &align);
960 size = (size + 3) & ~3;
961 align = (align + 3) & ~3;
962 switch(vtop[-i].type.t & VT_BTYPE) {
963 case VT_STRUCT:
964 case VT_FLOAT:
965 case VT_DOUBLE:
966 case VT_LDOUBLE:
967 if (float_abi == ARM_HARD_FLOAT) {
968 int is_hfa = 0; /* Homogeneous float aggregate */
970 if (is_float(vtop[-i].type.t)
971 || (is_hfa = is_hgen_float_aggr(&vtop[-i].type))) {
972 int end_vfpreg;
974 start_vfpreg = assign_vfpreg(&avregs, align, size);
975 end_vfpreg = start_vfpreg + ((size - 1) >> 2);
976 if (start_vfpreg >= 0) {
977 pplan = (struct param_plan) {start_vfpreg, end_vfpreg, &vtop[-i]};
978 if (is_hfa)
979 add_param_plan(plan, pplan, VFP_STRUCT_CLASS);
980 else
981 add_param_plan(plan, pplan, VFP_CLASS);
982 continue;
983 } else
984 break;
987 ncrn = (ncrn + (align-1)/4) & ~((align/4) - 1);
988 if (ncrn + size/4 <= 4 || (ncrn < 4 && start_vfpreg != -1)) {
989 /* The parameter is allocated both in core register and on stack. As
990 * such, it can be of either class: it would either be the last of
991 * CORE_STRUCT_CLASS or the first of STACK_CLASS. */
992 for (j = ncrn; j < 4 && j < ncrn + size / 4; j++)
993 *todo|=(1<<j);
994 pplan = (struct param_plan) {ncrn, j, &vtop[-i]};
995 add_param_plan(plan, pplan, CORE_STRUCT_CLASS);
996 ncrn += size/4;
997 if (ncrn > 4)
998 nsaa = (ncrn - 4) * 4;
999 } else {
1000 ncrn = 4;
1001 break;
1003 continue;
1004 default:
1005 if (ncrn < 4) {
1006 int is_long = (vtop[-i].type.t & VT_BTYPE) == VT_LLONG;
1008 if (is_long) {
1009 ncrn = (ncrn + 1) & -2;
1010 if (ncrn == 4)
1011 break;
1013 pplan = (struct param_plan) {ncrn, ncrn, &vtop[-i]};
1014 ncrn++;
1015 if (is_long)
1016 pplan.end = ncrn++;
1017 add_param_plan(plan, pplan, CORE_CLASS);
1018 continue;
1021 nsaa = (nsaa + (align - 1)) & ~(align - 1);
1022 pplan = (struct param_plan) {nsaa, nsaa + size, &vtop[-i]};
1023 add_param_plan(plan, pplan, STACK_CLASS);
1024 nsaa += size; /* size already rounded up before */
1026 return nsaa;
1029 #undef add_param_plan
1031 /* Copy parameters to their final destination (core reg, VFP reg or stack) for
1032 function call.
1034 nb_args: number of parameters the function take
1035 plan: the overall assignment plan for parameters
1036 todo: a bitmap indicating what core reg will hold a parameter
1038 Returns the number of SValue added by this function on the value stack */
1039 static int copy_params(int nb_args, struct plan *plan, int todo)
1041 int size, align, r, i, nb_extra_sval = 0;
1042 struct param_plan *pplan;
1044 /* Several constraints require parameters to be copied in a specific order:
1045 - structures are copied to the stack before being loaded in a reg;
1046 - floats loaded to an odd numbered VFP reg are first copied to the
1047 preceding even numbered VFP reg and then moved to the next VFP reg.
1049 It is thus important that:
1050 - structures assigned to core regs must be copied after parameters
1051 assigned to the stack but before structures assigned to VFP regs because
1052 a structure can lie partly in core registers and partly on the stack;
1053 - parameters assigned to the stack and all structures be copied before
1054 parameters assigned to a core reg since copying a parameter to the stack
1055 require using a core reg;
1056 - parameters assigned to VFP regs be copied before structures assigned to
1057 VFP regs as the copy might use an even numbered VFP reg that already
1058 holds part of a structure. */
1059 for(i = 0; i < NB_CLASSES; i++) {
1060 for(pplan = plan->clsplans[i]; pplan; pplan = pplan->prev) {
1061 vpushv(pplan->sval);
1062 pplan->sval->r = pplan->sval->r2 = VT_CONST; /* disable entry */
1063 switch(i) {
1064 case STACK_CLASS:
1065 case CORE_STRUCT_CLASS:
1066 case VFP_STRUCT_CLASS:
1067 if ((pplan->sval->type.t & VT_BTYPE) == VT_STRUCT) {
1068 int padding = 0;
1069 size = type_size(&pplan->sval->type, &align);
1070 /* align to stack align size */
1071 size = (size + 3) & ~3;
1072 if (i == STACK_CLASS && pplan->prev)
1073 padding = pplan->start - pplan->prev->end;
1074 size += padding; /* Add padding if any */
1075 /* allocate the necessary size on stack */
1076 gadd_sp(-size);
1077 /* generate structure store */
1078 r = get_reg(RC_INT);
1079 o(0xE28D0000|(intr(r)<<12)|padding); /* add r, sp, padding */
1080 vset(&vtop->type, r | VT_LVAL, 0);
1081 vswap();
1082 vstore(); /* memcpy to current sp + potential padding */
1084 /* Homogeneous float aggregate are loaded to VFP registers
1085 immediately since there is no way of loading data in multiple
1086 non consecutive VFP registers as what is done for other
1087 structures (see the use of todo). */
1088 if (i == VFP_STRUCT_CLASS) {
1089 int first = pplan->start, nb = pplan->end - first + 1;
1090 /* vpop.32 {pplan->start, ..., pplan->end} */
1091 o(0xECBD0A00|(first&1)<<22|(first>>1)<<12|nb);
1092 /* No need to write the register used to a SValue since VFP regs
1093 cannot be used for gcall_or_jmp */
1095 } else {
1096 if (is_float(pplan->sval->type.t)) {
1097 #ifdef TCC_ARM_VFP
1098 r = vfpr(gv(RC_FLOAT)) << 12;
1099 if ((pplan->sval->type.t & VT_BTYPE) == VT_FLOAT)
1100 size = 4;
1101 else {
1102 size = 8;
1103 r |= 0x101; /* vpush.32 -> vpush.64 */
1105 o(0xED2D0A01 + r); /* vpush */
1106 #else
1107 r = fpr(gv(RC_FLOAT)) << 12;
1108 if ((pplan->sval->type.t & VT_BTYPE) == VT_FLOAT)
1109 size = 4;
1110 else if ((pplan->sval->type.t & VT_BTYPE) == VT_DOUBLE)
1111 size = 8;
1112 else
1113 size = LDOUBLE_SIZE;
1115 if (size == 12)
1116 r |= 0x400000;
1117 else if(size == 8)
1118 r|=0x8000;
1120 o(0xED2D0100|r|(size>>2)); /* some kind of vpush for FPA */
1121 #endif
1122 } else {
1123 /* simple type (currently always same size) */
1124 /* XXX: implicit cast ? */
1125 size=4;
1126 if ((pplan->sval->type.t & VT_BTYPE) == VT_LLONG) {
1127 lexpand_nr();
1128 size = 8;
1129 r = gv(RC_INT);
1130 o(0xE52D0004|(intr(r)<<12)); /* push r */
1131 vtop--;
1133 r = gv(RC_INT);
1134 o(0xE52D0004|(intr(r)<<12)); /* push r */
1136 if (i == STACK_CLASS && pplan->prev)
1137 gadd_sp(pplan->prev->end - pplan->start); /* Add padding if any */
1139 break;
1141 case VFP_CLASS:
1142 gv(regmask(TREG_F0 + (pplan->start >> 1)));
1143 if (pplan->start & 1) { /* Must be in upper part of double register */
1144 o(0xEEF00A40|((pplan->start>>1)<<12)|(pplan->start>>1)); /* vmov.f32 s(n+1), sn */
1145 vtop->r = VT_CONST; /* avoid being saved on stack by gv for next float */
1147 break;
1149 case CORE_CLASS:
1150 if ((pplan->sval->type.t & VT_BTYPE) == VT_LLONG) {
1151 lexpand_nr();
1152 gv(regmask(pplan->end));
1153 pplan->sval->r2 = vtop->r;
1154 vtop--;
1156 gv(regmask(pplan->start));
1157 /* Mark register as used so that gcall_or_jmp use another one
1158 (regs >=4 are free as never used to pass parameters) */
1159 pplan->sval->r = vtop->r;
1160 break;
1162 vtop--;
1166 /* Manually free remaining registers since next parameters are loaded
1167 * manually, without the help of gv(int). */
1168 save_regs(nb_args);
1170 if(todo) {
1171 o(0xE8BD0000|todo); /* pop {todo} */
1172 for(pplan = plan->clsplans[CORE_STRUCT_CLASS]; pplan; pplan = pplan->prev) {
1173 int r;
1174 pplan->sval->r = pplan->start;
1175 /* An SValue can only pin 2 registers at best (r and r2) but a structure
1176 can occupy more than 2 registers. Thus, we need to push on the value
1177 stack some fake parameter to have on SValue for each registers used
1178 by a structure (r2 is not used). */
1179 for (r = pplan->start + 1; r <= pplan->end; r++) {
1180 if (todo & (1 << r)) {
1181 nb_extra_sval++;
1182 vpushi(0);
1183 vtop->r = r;
1188 return nb_extra_sval;
1191 /* Generate function call. The function address is pushed first, then
1192 all the parameters in call order. This functions pops all the
1193 parameters and the function address. */
1194 void gfunc_call(int nb_args)
1196 int r, args_size;
1197 int variadic, def_float_abi = float_abi;
1198 int todo;
1199 struct plan plan;
1201 #ifdef TCC_ARM_EABI
1202 if (float_abi == ARM_HARD_FLOAT) {
1203 variadic = (vtop[-nb_args].type.ref->c == FUNC_ELLIPSIS);
1204 if (variadic || floats_in_core_regs(&vtop[-nb_args]))
1205 float_abi = ARM_SOFTFP_FLOAT;
1207 #endif
1208 /* cannot let cpu flags if other instruction are generated. Also avoid leaving
1209 VT_JMP anywhere except on the top of the stack because it would complicate
1210 the code generator. */
1211 r = vtop->r & VT_VALMASK;
1212 if (r == VT_CMP || (r & ~1) == VT_JMP)
1213 gv(RC_INT);
1215 args_size = assign_regs(nb_args, float_abi, &plan, &todo);
1217 #ifdef TCC_ARM_EABI
1218 if (args_size & 7) { /* Stack must be 8 byte aligned at fct call for EABI */
1219 args_size = (args_size + 7) & ~7;
1220 o(0xE24DD004); /* sub sp, sp, #4 */
1222 #endif
1224 nb_args += copy_params(nb_args, &plan, todo);
1225 tcc_free(plan.pplans);
1227 /* Move fct SValue on top as required by gcall_or_jmp */
1228 vrotb(nb_args + 1);
1229 gcall_or_jmp(0);
1230 if (args_size)
1231 gadd_sp(args_size); /* pop all parameters passed on the stack */
1232 #if defined(TCC_ARM_EABI) && defined(TCC_ARM_VFP)
1233 if(float_abi == ARM_SOFTFP_FLOAT && is_float(vtop->type.ref->type.t)) {
1234 if((vtop->type.ref->type.t & VT_BTYPE) == VT_FLOAT) {
1235 o(0xEE000A10); /*vmov s0, r0 */
1236 } else {
1237 o(0xEE000B10); /* vmov.32 d0[0], r0 */
1238 o(0xEE201B10); /* vmov.32 d0[1], r1 */
1241 #endif
1242 vtop -= nb_args + 1; /* Pop all params and fct address from value stack */
1243 leaffunc = 0; /* we are calling a function, so we aren't in a leaf function */
1244 float_abi = def_float_abi;
1247 /* generate function prolog of type 't' */
1248 void gfunc_prolog(CType *func_type)
1250 Sym *sym,*sym2;
1251 int n, nf, size, align, struct_ret = 0;
1252 int addr, pn, sn; /* pn=core, sn=stack */
1253 struct avail_regs avregs = AVAIL_REGS_INITIALIZER;
1254 CType ret_type;
1256 sym = func_type->ref;
1257 func_vt = sym->type;
1258 func_var = (func_type->ref->c == FUNC_ELLIPSIS);
1260 n = nf = 0;
1261 if ((func_vt.t & VT_BTYPE) == VT_STRUCT &&
1262 !gfunc_sret(&func_vt, func_var, &ret_type, &align))
1264 n++;
1265 struct_ret = 1;
1266 func_vc = 12; /* Offset from fp of the place to store the result */
1268 for(sym2 = sym->next; sym2 && (n < 4 || nf < 16); sym2 = sym2->next) {
1269 size = type_size(&sym2->type, &align);
1270 #ifdef TCC_ARM_EABI
1271 if (float_abi == ARM_HARD_FLOAT && !func_var &&
1272 (is_float(sym2->type.t) || is_hgen_float_aggr(&sym2->type))) {
1273 int tmpnf = assign_vfpreg(&avregs, align, size);
1274 tmpnf += (size + 3) / 4;
1275 nf = (tmpnf > nf) ? tmpnf : nf;
1276 } else
1277 #endif
1278 if (n < 4)
1279 n += (size + 3) / 4;
1281 o(0xE1A0C00D); /* mov ip,sp */
1282 if (func_var)
1283 n=4;
1284 if (n) {
1285 if(n>4)
1286 n=4;
1287 #ifdef TCC_ARM_EABI
1288 n=(n+1)&-2;
1289 #endif
1290 o(0xE92D0000|((1<<n)-1)); /* save r0-r4 on stack if needed */
1292 if (nf) {
1293 if (nf>16)
1294 nf=16;
1295 nf=(nf+1)&-2; /* nf => HARDFLOAT => EABI */
1296 o(0xED2D0A00|nf); /* save s0-s15 on stack if needed */
1298 o(0xE92D5800); /* save fp, ip, lr */
1299 o(0xE1A0B00D); /* mov fp, sp */
1300 func_sub_sp_offset = ind;
1301 o(0xE1A00000); /* nop, leave space for stack adjustment in epilog */
1303 #ifdef TCC_ARM_EABI
1304 if (float_abi == ARM_HARD_FLOAT) {
1305 func_vc += nf * 4;
1306 avregs = AVAIL_REGS_INITIALIZER;
1308 #endif
1309 pn = struct_ret, sn = 0;
1310 while ((sym = sym->next)) {
1311 CType *type;
1312 type = &sym->type;
1313 size = type_size(type, &align);
1314 size = (size + 3) >> 2;
1315 align = (align + 3) & ~3;
1316 #ifdef TCC_ARM_EABI
1317 if (float_abi == ARM_HARD_FLOAT && !func_var && (is_float(sym->type.t)
1318 || is_hgen_float_aggr(&sym->type))) {
1319 int fpn = assign_vfpreg(&avregs, align, size << 2);
1320 if (fpn >= 0)
1321 addr = fpn * 4;
1322 else
1323 goto from_stack;
1324 } else
1325 #endif
1326 if (pn < 4) {
1327 #ifdef TCC_ARM_EABI
1328 pn = (pn + (align-1)/4) & -(align/4);
1329 #endif
1330 addr = (nf + pn) * 4;
1331 pn += size;
1332 if (!sn && pn > 4)
1333 sn = (pn - 4);
1334 } else {
1335 from_stack:
1336 #ifdef TCC_ARM_EABI
1337 sn = (sn + (align-1)/4) & -(align/4);
1338 #endif
1339 addr = (n + nf + sn) * 4;
1340 sn += size;
1342 sym_push(sym->v & ~SYM_FIELD, type, VT_LOCAL | lvalue_type(type->t),
1343 addr + 12);
1345 last_itod_magic=0;
1346 leaffunc = 1;
1347 loc = 0;
1350 /* generate function epilog */
1351 void gfunc_epilog(void)
1353 uint32_t x;
1354 int diff;
1355 /* Copy float return value to core register if base standard is used and
1356 float computation is made with VFP */
1357 #if defined(TCC_ARM_EABI) && defined(TCC_ARM_VFP)
1358 if ((float_abi == ARM_SOFTFP_FLOAT || func_var) && is_float(func_vt.t)) {
1359 if((func_vt.t & VT_BTYPE) == VT_FLOAT)
1360 o(0xEE100A10); /* fmrs r0, s0 */
1361 else {
1362 o(0xEE100B10); /* fmrdl r0, d0 */
1363 o(0xEE301B10); /* fmrdh r1, d0 */
1366 #endif
1367 o(0xE89BA800); /* restore fp, sp, pc */
1368 diff = (-loc + 3) & -4;
1369 #ifdef TCC_ARM_EABI
1370 if(!leaffunc)
1371 diff = ((diff + 11) & -8) - 4;
1372 #endif
1373 if(diff > 0) {
1374 x=stuff_const(0xE24BD000, diff); /* sub sp,fp,# */
1375 if(x)
1376 *(uint32_t *)(cur_text_section->data + func_sub_sp_offset) = x;
1377 else {
1378 int addr;
1379 addr=ind;
1380 o(0xE59FC004); /* ldr ip,[pc+4] */
1381 o(0xE04BD00C); /* sub sp,fp,ip */
1382 o(0xE1A0F00E); /* mov pc,lr */
1383 o(diff);
1384 *(uint32_t *)(cur_text_section->data + func_sub_sp_offset) = 0xE1000000|encbranch(func_sub_sp_offset,addr,1);
1389 /* generate a jump to a label */
1390 int gjmp(int t)
1392 int r;
1393 r=ind;
1394 o(0xE0000000|encbranch(r,t,1));
1395 return r;
1398 /* generate a jump to a fixed address */
1399 void gjmp_addr(int a)
1401 gjmp(a);
1404 /* generate a test. set 'inv' to invert test. Stack entry is popped */
1405 int gtst(int inv, int t)
1407 int v, r;
1408 uint32_t op;
1409 v = vtop->r & VT_VALMASK;
1410 r=ind;
1411 if (v == VT_CMP) {
1412 op=mapcc(inv?negcc(vtop->c.i):vtop->c.i);
1413 op|=encbranch(r,t,1);
1414 o(op);
1415 t=r;
1416 } else { /* VT_JMP || VT_JMPI */
1417 if ((v & 1) == inv) {
1418 if(!vtop->c.i)
1419 vtop->c.i=t;
1420 else {
1421 uint32_t *x;
1422 int p,lp;
1423 if(t) {
1424 p = vtop->c.i;
1425 do {
1426 p = decbranch(lp=p);
1427 } while(p);
1428 x = (uint32_t *)(cur_text_section->data + lp);
1429 *x &= 0xff000000;
1430 *x |= encbranch(lp,t,1);
1432 t = vtop->c.i;
1434 } else {
1435 t = gjmp(t);
1436 gsym(vtop->c.i);
1439 vtop--;
1440 return t;
1443 /* generate an integer binary operation */
1444 void gen_opi(int op)
1446 int c, func = 0;
1447 uint32_t opc = 0, r, fr;
1448 unsigned short retreg = REG_IRET;
1450 c=0;
1451 switch(op) {
1452 case '+':
1453 opc = 0x8;
1454 c=1;
1455 break;
1456 case TOK_ADDC1: /* add with carry generation */
1457 opc = 0x9;
1458 c=1;
1459 break;
1460 case '-':
1461 opc = 0x4;
1462 c=1;
1463 break;
1464 case TOK_SUBC1: /* sub with carry generation */
1465 opc = 0x5;
1466 c=1;
1467 break;
1468 case TOK_ADDC2: /* add with carry use */
1469 opc = 0xA;
1470 c=1;
1471 break;
1472 case TOK_SUBC2: /* sub with carry use */
1473 opc = 0xC;
1474 c=1;
1475 break;
1476 case '&':
1477 opc = 0x0;
1478 c=1;
1479 break;
1480 case '^':
1481 opc = 0x2;
1482 c=1;
1483 break;
1484 case '|':
1485 opc = 0x18;
1486 c=1;
1487 break;
1488 case '*':
1489 gv2(RC_INT, RC_INT);
1490 r = vtop[-1].r;
1491 fr = vtop[0].r;
1492 vtop--;
1493 o(0xE0000090|(intr(r)<<16)|(intr(r)<<8)|intr(fr));
1494 return;
1495 case TOK_SHL:
1496 opc = 0;
1497 c=2;
1498 break;
1499 case TOK_SHR:
1500 opc = 1;
1501 c=2;
1502 break;
1503 case TOK_SAR:
1504 opc = 2;
1505 c=2;
1506 break;
1507 case '/':
1508 case TOK_PDIV:
1509 func=TOK___divsi3;
1510 c=3;
1511 break;
1512 case TOK_UDIV:
1513 func=TOK___udivsi3;
1514 c=3;
1515 break;
1516 case '%':
1517 #ifdef TCC_ARM_EABI
1518 func=TOK___aeabi_idivmod;
1519 retreg=REG_LRET;
1520 #else
1521 func=TOK___modsi3;
1522 #endif
1523 c=3;
1524 break;
1525 case TOK_UMOD:
1526 #ifdef TCC_ARM_EABI
1527 func=TOK___aeabi_uidivmod;
1528 retreg=REG_LRET;
1529 #else
1530 func=TOK___umodsi3;
1531 #endif
1532 c=3;
1533 break;
1534 case TOK_UMULL:
1535 gv2(RC_INT, RC_INT);
1536 r=intr(vtop[-1].r2=get_reg(RC_INT));
1537 c=vtop[-1].r;
1538 vtop[-1].r=get_reg_ex(RC_INT,regmask(c));
1539 vtop--;
1540 o(0xE0800090|(r<<16)|(intr(vtop->r)<<12)|(intr(c)<<8)|intr(vtop[1].r));
1541 return;
1542 default:
1543 opc = 0x15;
1544 c=1;
1545 break;
1547 switch(c) {
1548 case 1:
1549 if((vtop[-1].r & (VT_VALMASK | VT_LVAL | VT_SYM)) == VT_CONST) {
1550 if(opc == 4 || opc == 5 || opc == 0xc) {
1551 vswap();
1552 opc|=2; // sub -> rsb
1555 if ((vtop->r & VT_VALMASK) == VT_CMP ||
1556 (vtop->r & (VT_VALMASK & ~1)) == VT_JMP)
1557 gv(RC_INT);
1558 vswap();
1559 c=intr(gv(RC_INT));
1560 vswap();
1561 opc=0xE0000000|(opc<<20)|(c<<16);
1562 if((vtop->r & (VT_VALMASK | VT_LVAL | VT_SYM)) == VT_CONST) {
1563 uint32_t x;
1564 x=stuff_const(opc|0x2000000,vtop->c.i);
1565 if(x) {
1566 r=intr(vtop[-1].r=get_reg_ex(RC_INT,regmask(vtop[-1].r)));
1567 o(x|(r<<12));
1568 goto done;
1571 fr=intr(gv(RC_INT));
1572 r=intr(vtop[-1].r=get_reg_ex(RC_INT,two2mask(vtop->r,vtop[-1].r)));
1573 o(opc|(r<<12)|fr);
1574 done:
1575 vtop--;
1576 if (op >= TOK_ULT && op <= TOK_GT) {
1577 vtop->r = VT_CMP;
1578 vtop->c.i = op;
1580 break;
1581 case 2:
1582 opc=0xE1A00000|(opc<<5);
1583 if ((vtop->r & VT_VALMASK) == VT_CMP ||
1584 (vtop->r & (VT_VALMASK & ~1)) == VT_JMP)
1585 gv(RC_INT);
1586 vswap();
1587 r=intr(gv(RC_INT));
1588 vswap();
1589 opc|=r;
1590 if ((vtop->r & (VT_VALMASK | VT_LVAL | VT_SYM)) == VT_CONST) {
1591 fr=intr(vtop[-1].r=get_reg_ex(RC_INT,regmask(vtop[-1].r)));
1592 c = vtop->c.i & 0x1f;
1593 o(opc|(c<<7)|(fr<<12));
1594 } else {
1595 fr=intr(gv(RC_INT));
1596 c=intr(vtop[-1].r=get_reg_ex(RC_INT,two2mask(vtop->r,vtop[-1].r)));
1597 o(opc|(c<<12)|(fr<<8)|0x10);
1599 vtop--;
1600 break;
1601 case 3:
1602 vpush_global_sym(&func_old_type, func);
1603 vrott(3);
1604 gfunc_call(2);
1605 vpushi(0);
1606 vtop->r = retreg;
1607 break;
1608 default:
1609 tcc_error("gen_opi %i unimplemented!",op);
1613 #ifdef TCC_ARM_VFP
1614 static int is_zero(int i)
1616 if((vtop[i].r & (VT_VALMASK | VT_LVAL | VT_SYM)) != VT_CONST)
1617 return 0;
1618 if (vtop[i].type.t == VT_FLOAT)
1619 return (vtop[i].c.f == 0.f);
1620 else if (vtop[i].type.t == VT_DOUBLE)
1621 return (vtop[i].c.d == 0.0);
1622 return (vtop[i].c.ld == 0.l);
1625 /* generate a floating point operation 'v = t1 op t2' instruction. The
1626 * two operands are guaranted to have the same floating point type */
1627 void gen_opf(int op)
1629 uint32_t x;
1630 int fneg=0,r;
1631 x=0xEE000A00|T2CPR(vtop->type.t);
1632 switch(op) {
1633 case '+':
1634 if(is_zero(-1))
1635 vswap();
1636 if(is_zero(0)) {
1637 vtop--;
1638 return;
1640 x|=0x300000;
1641 break;
1642 case '-':
1643 x|=0x300040;
1644 if(is_zero(0)) {
1645 vtop--;
1646 return;
1648 if(is_zero(-1)) {
1649 x|=0x810000; /* fsubX -> fnegX */
1650 vswap();
1651 vtop--;
1652 fneg=1;
1654 break;
1655 case '*':
1656 x|=0x200000;
1657 break;
1658 case '/':
1659 x|=0x800000;
1660 break;
1661 default:
1662 if(op < TOK_ULT || op > TOK_GT) {
1663 tcc_error("unknown fp op %x!",op);
1664 return;
1666 if(is_zero(-1)) {
1667 vswap();
1668 switch(op) {
1669 case TOK_LT: op=TOK_GT; break;
1670 case TOK_GE: op=TOK_ULE; break;
1671 case TOK_LE: op=TOK_GE; break;
1672 case TOK_GT: op=TOK_ULT; break;
1675 x|=0xB40040; /* fcmpX */
1676 if(op!=TOK_EQ && op!=TOK_NE)
1677 x|=0x80; /* fcmpX -> fcmpeX */
1678 if(is_zero(0)) {
1679 vtop--;
1680 o(x|0x10000|(vfpr(gv(RC_FLOAT))<<12)); /* fcmp(e)X -> fcmp(e)zX */
1681 } else {
1682 x|=vfpr(gv(RC_FLOAT));
1683 vswap();
1684 o(x|(vfpr(gv(RC_FLOAT))<<12));
1685 vtop--;
1687 o(0xEEF1FA10); /* fmstat */
1689 switch(op) {
1690 case TOK_LE: op=TOK_ULE; break;
1691 case TOK_LT: op=TOK_ULT; break;
1692 case TOK_UGE: op=TOK_GE; break;
1693 case TOK_UGT: op=TOK_GT; break;
1696 vtop->r = VT_CMP;
1697 vtop->c.i = op;
1698 return;
1700 r=gv(RC_FLOAT);
1701 x|=vfpr(r);
1702 r=regmask(r);
1703 if(!fneg) {
1704 int r2;
1705 vswap();
1706 r2=gv(RC_FLOAT);
1707 x|=vfpr(r2)<<16;
1708 r|=regmask(r2);
1710 vtop->r=get_reg_ex(RC_FLOAT,r);
1711 if(!fneg)
1712 vtop--;
1713 o(x|(vfpr(vtop->r)<<12));
1716 #else
1717 static uint32_t is_fconst()
1719 long double f;
1720 uint32_t r;
1721 if((vtop->r & (VT_VALMASK | VT_LVAL | VT_SYM)) != VT_CONST)
1722 return 0;
1723 if (vtop->type.t == VT_FLOAT)
1724 f = vtop->c.f;
1725 else if (vtop->type.t == VT_DOUBLE)
1726 f = vtop->c.d;
1727 else
1728 f = vtop->c.ld;
1729 if(!ieee_finite(f))
1730 return 0;
1731 r=0x8;
1732 if(f<0.0) {
1733 r=0x18;
1734 f=-f;
1736 if(f==0.0)
1737 return r;
1738 if(f==1.0)
1739 return r|1;
1740 if(f==2.0)
1741 return r|2;
1742 if(f==3.0)
1743 return r|3;
1744 if(f==4.0)
1745 return r|4;
1746 if(f==5.0)
1747 return r|5;
1748 if(f==0.5)
1749 return r|6;
1750 if(f==10.0)
1751 return r|7;
1752 return 0;
1755 /* generate a floating point operation 'v = t1 op t2' instruction. The
1756 two operands are guaranted to have the same floating point type */
1757 void gen_opf(int op)
1759 uint32_t x, r, r2, c1, c2;
1760 //fputs("gen_opf\n",stderr);
1761 vswap();
1762 c1 = is_fconst();
1763 vswap();
1764 c2 = is_fconst();
1765 x=0xEE000100;
1766 #if LDOUBLE_SIZE == 8
1767 if ((vtop->type.t & VT_BTYPE) != VT_FLOAT)
1768 x|=0x80;
1769 #else
1770 if ((vtop->type.t & VT_BTYPE) == VT_DOUBLE)
1771 x|=0x80;
1772 else if ((vtop->type.t & VT_BTYPE) == VT_LDOUBLE)
1773 x|=0x80000;
1774 #endif
1775 switch(op)
1777 case '+':
1778 if(!c2) {
1779 vswap();
1780 c2=c1;
1782 vswap();
1783 r=fpr(gv(RC_FLOAT));
1784 vswap();
1785 if(c2) {
1786 if(c2>0xf)
1787 x|=0x200000; // suf
1788 r2=c2&0xf;
1789 } else {
1790 r2=fpr(gv(RC_FLOAT));
1792 break;
1793 case '-':
1794 if(c2) {
1795 if(c2<=0xf)
1796 x|=0x200000; // suf
1797 r2=c2&0xf;
1798 vswap();
1799 r=fpr(gv(RC_FLOAT));
1800 vswap();
1801 } else if(c1 && c1<=0xf) {
1802 x|=0x300000; // rsf
1803 r2=c1;
1804 r=fpr(gv(RC_FLOAT));
1805 vswap();
1806 } else {
1807 x|=0x200000; // suf
1808 vswap();
1809 r=fpr(gv(RC_FLOAT));
1810 vswap();
1811 r2=fpr(gv(RC_FLOAT));
1813 break;
1814 case '*':
1815 if(!c2 || c2>0xf) {
1816 vswap();
1817 c2=c1;
1819 vswap();
1820 r=fpr(gv(RC_FLOAT));
1821 vswap();
1822 if(c2 && c2<=0xf)
1823 r2=c2;
1824 else
1825 r2=fpr(gv(RC_FLOAT));
1826 x|=0x100000; // muf
1827 break;
1828 case '/':
1829 if(c2 && c2<=0xf) {
1830 x|=0x400000; // dvf
1831 r2=c2;
1832 vswap();
1833 r=fpr(gv(RC_FLOAT));
1834 vswap();
1835 } else if(c1 && c1<=0xf) {
1836 x|=0x500000; // rdf
1837 r2=c1;
1838 r=fpr(gv(RC_FLOAT));
1839 vswap();
1840 } else {
1841 x|=0x400000; // dvf
1842 vswap();
1843 r=fpr(gv(RC_FLOAT));
1844 vswap();
1845 r2=fpr(gv(RC_FLOAT));
1847 break;
1848 default:
1849 if(op >= TOK_ULT && op <= TOK_GT) {
1850 x|=0xd0f110; // cmfe
1851 /* bug (intention?) in Linux FPU emulator
1852 doesn't set carry if equal */
1853 switch(op) {
1854 case TOK_ULT:
1855 case TOK_UGE:
1856 case TOK_ULE:
1857 case TOK_UGT:
1858 tcc_error("unsigned comparision on floats?");
1859 break;
1860 case TOK_LT:
1861 op=TOK_Nset;
1862 break;
1863 case TOK_LE:
1864 op=TOK_ULE; /* correct in unordered case only if AC bit in FPSR set */
1865 break;
1866 case TOK_EQ:
1867 case TOK_NE:
1868 x&=~0x400000; // cmfe -> cmf
1869 break;
1871 if(c1 && !c2) {
1872 c2=c1;
1873 vswap();
1874 switch(op) {
1875 case TOK_Nset:
1876 op=TOK_GT;
1877 break;
1878 case TOK_GE:
1879 op=TOK_ULE;
1880 break;
1881 case TOK_ULE:
1882 op=TOK_GE;
1883 break;
1884 case TOK_GT:
1885 op=TOK_Nset;
1886 break;
1889 vswap();
1890 r=fpr(gv(RC_FLOAT));
1891 vswap();
1892 if(c2) {
1893 if(c2>0xf)
1894 x|=0x200000;
1895 r2=c2&0xf;
1896 } else {
1897 r2=fpr(gv(RC_FLOAT));
1899 vtop[-1].r = VT_CMP;
1900 vtop[-1].c.i = op;
1901 } else {
1902 tcc_error("unknown fp op %x!",op);
1903 return;
1906 if(vtop[-1].r == VT_CMP)
1907 c1=15;
1908 else {
1909 c1=vtop->r;
1910 if(r2&0x8)
1911 c1=vtop[-1].r;
1912 vtop[-1].r=get_reg_ex(RC_FLOAT,two2mask(vtop[-1].r,c1));
1913 c1=fpr(vtop[-1].r);
1915 vtop--;
1916 o(x|(r<<16)|(c1<<12)|r2);
1918 #endif
1920 /* convert integers to fp 't' type. Must handle 'int', 'unsigned int'
1921 and 'long long' cases. */
1922 ST_FUNC void gen_cvt_itof1(int t)
1924 uint32_t r, r2;
1925 int bt;
1926 bt=vtop->type.t & VT_BTYPE;
1927 if(bt == VT_INT || bt == VT_SHORT || bt == VT_BYTE) {
1928 #ifndef TCC_ARM_VFP
1929 uint32_t dsize = 0;
1930 #endif
1931 r=intr(gv(RC_INT));
1932 #ifdef TCC_ARM_VFP
1933 r2=vfpr(vtop->r=get_reg(RC_FLOAT));
1934 o(0xEE000A10|(r<<12)|(r2<<16)); /* fmsr */
1935 r2|=r2<<12;
1936 if(!(vtop->type.t & VT_UNSIGNED))
1937 r2|=0x80; /* fuitoX -> fsituX */
1938 o(0xEEB80A40|r2|T2CPR(t)); /* fYitoX*/
1939 #else
1940 r2=fpr(vtop->r=get_reg(RC_FLOAT));
1941 if((t & VT_BTYPE) != VT_FLOAT)
1942 dsize=0x80; /* flts -> fltd */
1943 o(0xEE000110|dsize|(r2<<16)|(r<<12)); /* flts */
1944 if((vtop->type.t & (VT_UNSIGNED|VT_BTYPE)) == (VT_UNSIGNED|VT_INT)) {
1945 uint32_t off = 0;
1946 o(0xE3500000|(r<<12)); /* cmp */
1947 r=fpr(get_reg(RC_FLOAT));
1948 if(last_itod_magic) {
1949 off=ind+8-last_itod_magic;
1950 off/=4;
1951 if(off>255)
1952 off=0;
1954 o(0xBD1F0100|(r<<12)|off); /* ldflts */
1955 if(!off) {
1956 o(0xEA000000); /* b */
1957 last_itod_magic=ind;
1958 o(0x4F800000); /* 4294967296.0f */
1960 o(0xBE000100|dsize|(r2<<16)|(r2<<12)|r); /* adflt */
1962 #endif
1963 return;
1964 } else if(bt == VT_LLONG) {
1965 int func;
1966 CType *func_type = 0;
1967 if((t & VT_BTYPE) == VT_FLOAT) {
1968 func_type = &func_float_type;
1969 if(vtop->type.t & VT_UNSIGNED)
1970 func=TOK___floatundisf;
1971 else
1972 func=TOK___floatdisf;
1973 #if LDOUBLE_SIZE != 8
1974 } else if((t & VT_BTYPE) == VT_LDOUBLE) {
1975 func_type = &func_ldouble_type;
1976 if(vtop->type.t & VT_UNSIGNED)
1977 func=TOK___floatundixf;
1978 else
1979 func=TOK___floatdixf;
1980 } else if((t & VT_BTYPE) == VT_DOUBLE) {
1981 #else
1982 } else if((t & VT_BTYPE) == VT_DOUBLE || (t & VT_BTYPE) == VT_LDOUBLE) {
1983 #endif
1984 func_type = &func_double_type;
1985 if(vtop->type.t & VT_UNSIGNED)
1986 func=TOK___floatundidf;
1987 else
1988 func=TOK___floatdidf;
1990 if(func_type) {
1991 vpush_global_sym(func_type, func);
1992 vswap();
1993 gfunc_call(1);
1994 vpushi(0);
1995 vtop->r=TREG_F0;
1996 return;
1999 tcc_error("unimplemented gen_cvt_itof %x!",vtop->type.t);
2002 /* convert fp to int 't' type */
2003 void gen_cvt_ftoi(int t)
2005 uint32_t r, r2;
2006 int u, func = 0;
2007 u=t&VT_UNSIGNED;
2008 t&=VT_BTYPE;
2009 r2=vtop->type.t & VT_BTYPE;
2010 if(t==VT_INT) {
2011 #ifdef TCC_ARM_VFP
2012 r=vfpr(gv(RC_FLOAT));
2013 u=u?0:0x10000;
2014 o(0xEEBC0AC0|(r<<12)|r|T2CPR(r2)|u); /* ftoXizY */
2015 r2=intr(vtop->r=get_reg(RC_INT));
2016 o(0xEE100A10|(r<<16)|(r2<<12));
2017 return;
2018 #else
2019 if(u) {
2020 if(r2 == VT_FLOAT)
2021 func=TOK___fixunssfsi;
2022 #if LDOUBLE_SIZE != 8
2023 else if(r2 == VT_LDOUBLE)
2024 func=TOK___fixunsxfsi;
2025 else if(r2 == VT_DOUBLE)
2026 #else
2027 else if(r2 == VT_LDOUBLE || r2 == VT_DOUBLE)
2028 #endif
2029 func=TOK___fixunsdfsi;
2030 } else {
2031 r=fpr(gv(RC_FLOAT));
2032 r2=intr(vtop->r=get_reg(RC_INT));
2033 o(0xEE100170|(r2<<12)|r);
2034 return;
2036 #endif
2037 } else if(t == VT_LLONG) { // unsigned handled in gen_cvt_ftoi1
2038 if(r2 == VT_FLOAT)
2039 func=TOK___fixsfdi;
2040 #if LDOUBLE_SIZE != 8
2041 else if(r2 == VT_LDOUBLE)
2042 func=TOK___fixxfdi;
2043 else if(r2 == VT_DOUBLE)
2044 #else
2045 else if(r2 == VT_LDOUBLE || r2 == VT_DOUBLE)
2046 #endif
2047 func=TOK___fixdfdi;
2049 if(func) {
2050 vpush_global_sym(&func_old_type, func);
2051 vswap();
2052 gfunc_call(1);
2053 vpushi(0);
2054 if(t == VT_LLONG)
2055 vtop->r2 = REG_LRET;
2056 vtop->r = REG_IRET;
2057 return;
2059 tcc_error("unimplemented gen_cvt_ftoi!");
2062 /* convert from one floating point type to another */
2063 void gen_cvt_ftof(int t)
2065 #ifdef TCC_ARM_VFP
2066 if(((vtop->type.t & VT_BTYPE) == VT_FLOAT) != ((t & VT_BTYPE) == VT_FLOAT)) {
2067 uint32_t r = vfpr(gv(RC_FLOAT));
2068 o(0xEEB70AC0|(r<<12)|r|T2CPR(vtop->type.t));
2070 #else
2071 /* all we have to do on i386 and FPA ARM is to put the float in a register */
2072 gv(RC_FLOAT);
2073 #endif
2076 /* computed goto support */
2077 void ggoto(void)
2079 gcall_or_jmp(1);
2080 vtop--;
2083 /* Save the stack pointer onto the stack and return the location of its address */
2084 ST_FUNC void gen_vla_sp_save(int addr) {
2085 tcc_error("variable length arrays unsupported for this target");
2088 /* Restore the SP from a location on the stack */
2089 ST_FUNC void gen_vla_sp_restore(int addr) {
2090 tcc_error("variable length arrays unsupported for this target");
2093 /* Subtract from the stack pointer, and push the resulting value onto the stack */
2094 ST_FUNC void gen_vla_alloc(CType *type, int align) {
2095 tcc_error("variable length arrays unsupported for this target");
2098 /* end of ARM code generator */
2099 /*************************************************************/
2100 #endif
2101 /*************************************************************/