riscv: Handle some usual relocs
[tinycc.git] / arm-gen.c
blobb93d298f35752fc6e0af3d4c70a5266cfc2a95ce
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_CPU_VERSION
38 # define TCC_CPU_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
82 TREG_SP = 13,
83 TREG_LR,
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 /* pointer size, in bytes */
110 #define PTR_SIZE 4
112 /* long double size and alignment, in bytes */
113 #ifdef TCC_ARM_VFP
114 #define LDOUBLE_SIZE 8
115 #endif
117 #ifndef LDOUBLE_SIZE
118 #define LDOUBLE_SIZE 8
119 #endif
121 #ifdef TCC_ARM_EABI
122 #define LDOUBLE_ALIGN 8
123 #else
124 #define LDOUBLE_ALIGN 4
125 #endif
127 /* maximum alignment (for aligned attribute support) */
128 #define MAX_ALIGN 8
130 #define CHAR_IS_UNSIGNED
132 /******************************************************/
133 #else /* ! TARGET_DEFS_ONLY */
134 /******************************************************/
135 #include "tcc.h"
137 enum float_abi float_abi;
139 ST_DATA const int reg_classes[NB_REGS] = {
140 /* r0 */ RC_INT | RC_R0,
141 /* r1 */ RC_INT | RC_R1,
142 /* r2 */ RC_INT | RC_R2,
143 /* r3 */ RC_INT | RC_R3,
144 /* r12 */ RC_INT | RC_R12,
145 /* f0 */ RC_FLOAT | RC_F0,
146 /* f1 */ RC_FLOAT | RC_F1,
147 /* f2 */ RC_FLOAT | RC_F2,
148 /* f3 */ RC_FLOAT | RC_F3,
149 #ifdef TCC_ARM_VFP
150 /* d4/s8 */ RC_FLOAT | RC_F4,
151 /* d5/s10 */ RC_FLOAT | RC_F5,
152 /* d6/s12 */ RC_FLOAT | RC_F6,
153 /* d7/s14 */ RC_FLOAT | RC_F7,
154 #endif
157 static int func_sub_sp_offset, last_itod_magic;
158 static int leaffunc;
160 #if defined(TCC_ARM_EABI) && defined(TCC_ARM_VFP)
161 static CType float_type, double_type, func_float_type, func_double_type;
162 ST_FUNC void arm_init(struct TCCState *s)
164 float_type.t = VT_FLOAT;
165 double_type.t = VT_DOUBLE;
166 func_float_type.t = VT_FUNC;
167 func_float_type.ref = sym_push(SYM_FIELD, &float_type, FUNC_CDECL, FUNC_OLD);
168 func_double_type.t = VT_FUNC;
169 func_double_type.ref = sym_push(SYM_FIELD, &double_type, FUNC_CDECL, FUNC_OLD);
171 float_abi = s->float_abi;
172 #ifndef TCC_ARM_HARDFLOAT
173 tcc_warning("soft float ABI currently not supported: default to softfp");
174 #endif
176 #else
177 #define func_float_type func_old_type
178 #define func_double_type func_old_type
179 #define func_ldouble_type func_old_type
180 ST_FUNC void arm_init(struct TCCState *s)
182 #if 0
183 #if !defined (TCC_ARM_VFP)
184 tcc_warning("Support for FPA is deprecated and will be removed in next"
185 " release");
186 #endif
187 #if !defined (TCC_ARM_EABI)
188 tcc_warning("Support for OABI is deprecated and will be removed in next"
189 " release");
190 #endif
191 #endif
193 #endif
195 static int two2mask(int a,int b) {
196 return (reg_classes[a]|reg_classes[b])&~(RC_INT|RC_FLOAT);
199 static int regmask(int r) {
200 return reg_classes[r]&~(RC_INT|RC_FLOAT);
203 /******************************************************/
205 #if defined(TCC_ARM_EABI) && !defined(CONFIG_TCC_ELFINTERP)
206 const char *default_elfinterp(struct TCCState *s)
208 if (s->float_abi == ARM_HARD_FLOAT)
209 return "/lib/ld-linux-armhf.so.3";
210 else
211 return "/lib/ld-linux.so.3";
213 #endif
215 void o(uint32_t i)
217 /* this is a good place to start adding big-endian support*/
218 int ind1;
219 if (nocode_wanted)
220 return;
221 ind1 = ind + 4;
222 if (!cur_text_section)
223 tcc_error("compiler error! This happens f.ex. if the compiler\n"
224 "can't evaluate constant expressions outside of a function.");
225 if (ind1 > cur_text_section->data_allocated)
226 section_realloc(cur_text_section, ind1);
227 cur_text_section->data[ind++] = i&255;
228 i>>=8;
229 cur_text_section->data[ind++] = i&255;
230 i>>=8;
231 cur_text_section->data[ind++] = i&255;
232 i>>=8;
233 cur_text_section->data[ind++] = i;
236 static uint32_t stuff_const(uint32_t op, uint32_t c)
238 int try_neg=0;
239 uint32_t nc = 0, negop = 0;
241 switch(op&0x1F00000)
243 case 0x800000: //add
244 case 0x400000: //sub
245 try_neg=1;
246 negop=op^0xC00000;
247 nc=-c;
248 break;
249 case 0x1A00000: //mov
250 case 0x1E00000: //mvn
251 try_neg=1;
252 negop=op^0x400000;
253 nc=~c;
254 break;
255 case 0x200000: //xor
256 if(c==~0)
257 return (op&0xF010F000)|((op>>16)&0xF)|0x1E00000;
258 break;
259 case 0x0: //and
260 if(c==~0)
261 return (op&0xF010F000)|((op>>16)&0xF)|0x1A00000;
262 case 0x1C00000: //bic
263 try_neg=1;
264 negop=op^0x1C00000;
265 nc=~c;
266 break;
267 case 0x1800000: //orr
268 if(c==~0)
269 return (op&0xFFF0FFFF)|0x1E00000;
270 break;
272 do {
273 uint32_t m;
274 int i;
275 if(c<256) /* catch undefined <<32 */
276 return op|c;
277 for(i=2;i<32;i+=2) {
278 m=(0xff>>i)|(0xff<<(32-i));
279 if(!(c&~m))
280 return op|(i<<7)|(c<<i)|(c>>(32-i));
282 op=negop;
283 c=nc;
284 } while(try_neg--);
285 return 0;
289 //only add,sub
290 void stuff_const_harder(uint32_t op, uint32_t v) {
291 uint32_t x;
292 x=stuff_const(op,v);
293 if(x)
294 o(x);
295 else {
296 uint32_t a[16], nv, no, o2, n2;
297 int i,j,k;
298 a[0]=0xff;
299 o2=(op&0xfff0ffff)|((op&0xf000)<<4);;
300 for(i=1;i<16;i++)
301 a[i]=(a[i-1]>>2)|(a[i-1]<<30);
302 for(i=0;i<12;i++)
303 for(j=i<4?i+12:15;j>=i+4;j--)
304 if((v&(a[i]|a[j]))==v) {
305 o(stuff_const(op,v&a[i]));
306 o(stuff_const(o2,v&a[j]));
307 return;
309 no=op^0xC00000;
310 n2=o2^0xC00000;
311 nv=-v;
312 for(i=0;i<12;i++)
313 for(j=i<4?i+12:15;j>=i+4;j--)
314 if((nv&(a[i]|a[j]))==nv) {
315 o(stuff_const(no,nv&a[i]));
316 o(stuff_const(n2,nv&a[j]));
317 return;
319 for(i=0;i<8;i++)
320 for(j=i+4;j<12;j++)
321 for(k=i<4?i+12:15;k>=j+4;k--)
322 if((v&(a[i]|a[j]|a[k]))==v) {
323 o(stuff_const(op,v&a[i]));
324 o(stuff_const(o2,v&a[j]));
325 o(stuff_const(o2,v&a[k]));
326 return;
328 no=op^0xC00000;
329 nv=-v;
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((nv&(a[i]|a[j]|a[k]))==nv) {
334 o(stuff_const(no,nv&a[i]));
335 o(stuff_const(n2,nv&a[j]));
336 o(stuff_const(n2,nv&a[k]));
337 return;
339 o(stuff_const(op,v&a[0]));
340 o(stuff_const(o2,v&a[4]));
341 o(stuff_const(o2,v&a[8]));
342 o(stuff_const(o2,v&a[12]));
346 uint32_t encbranch(int pos, int addr, int fail)
348 addr-=pos+8;
349 addr/=4;
350 if(addr>=0x1000000 || addr<-0x1000000) {
351 if(fail)
352 tcc_error("FIXME: function bigger than 32MB");
353 return 0;
355 return 0x0A000000|(addr&0xffffff);
358 int decbranch(int pos)
360 int x;
361 x=*(uint32_t *)(cur_text_section->data + pos);
362 x&=0x00ffffff;
363 if(x&0x800000)
364 x-=0x1000000;
365 return x*4+pos+8;
368 /* output a symbol and patch all calls to it */
369 void gsym_addr(int t, int a)
371 uint32_t *x;
372 int lt;
373 while(t) {
374 x=(uint32_t *)(cur_text_section->data + t);
375 t=decbranch(lt=t);
376 if(a==lt+4)
377 *x=0xE1A00000; // nop
378 else {
379 *x &= 0xff000000;
380 *x |= encbranch(lt,a,1);
385 #ifdef TCC_ARM_VFP
386 static uint32_t vfpr(int r)
388 if(r<TREG_F0 || r>TREG_F7)
389 tcc_error("compiler error! register %i is no vfp register",r);
390 return r - TREG_F0;
392 #else
393 static uint32_t fpr(int r)
395 if(r<TREG_F0 || r>TREG_F3)
396 tcc_error("compiler error! register %i is no fpa register",r);
397 return r - TREG_F0;
399 #endif
401 static uint32_t intr(int r)
403 if(r == TREG_R12)
404 return 12;
405 if(r >= TREG_R0 && r <= TREG_R3)
406 return r - TREG_R0;
407 if (!(r >= TREG_SP && r <= TREG_LR))
408 tcc_error("compiler error! register %i is no int register",r);
409 return r + (13 - TREG_SP);
412 static void calcaddr(uint32_t *base, int *off, int *sgn, int maxoff, unsigned shift)
414 if(*off>maxoff || *off&((1<<shift)-1)) {
415 uint32_t x, y;
416 x=0xE280E000;
417 if(*sgn)
418 x=0xE240E000;
419 x|=(*base)<<16;
420 *base=14; // lr
421 y=stuff_const(x,*off&~maxoff);
422 if(y) {
423 o(y);
424 *off&=maxoff;
425 return;
427 y=stuff_const(x,(*off+maxoff)&~maxoff);
428 if(y) {
429 o(y);
430 *sgn=!*sgn;
431 *off=((*off+maxoff)&~maxoff)-*off;
432 return;
434 stuff_const_harder(x,*off&~maxoff);
435 *off&=maxoff;
439 static uint32_t mapcc(int cc)
441 switch(cc)
443 case TOK_ULT:
444 return 0x30000000; /* CC/LO */
445 case TOK_UGE:
446 return 0x20000000; /* CS/HS */
447 case TOK_EQ:
448 return 0x00000000; /* EQ */
449 case TOK_NE:
450 return 0x10000000; /* NE */
451 case TOK_ULE:
452 return 0x90000000; /* LS */
453 case TOK_UGT:
454 return 0x80000000; /* HI */
455 case TOK_Nset:
456 return 0x40000000; /* MI */
457 case TOK_Nclear:
458 return 0x50000000; /* PL */
459 case TOK_LT:
460 return 0xB0000000; /* LT */
461 case TOK_GE:
462 return 0xA0000000; /* GE */
463 case TOK_LE:
464 return 0xD0000000; /* LE */
465 case TOK_GT:
466 return 0xC0000000; /* GT */
468 tcc_error("unexpected condition code");
469 return 0xE0000000; /* AL */
472 static int negcc(int cc)
474 switch(cc)
476 case TOK_ULT:
477 return TOK_UGE;
478 case TOK_UGE:
479 return TOK_ULT;
480 case TOK_EQ:
481 return TOK_NE;
482 case TOK_NE:
483 return TOK_EQ;
484 case TOK_ULE:
485 return TOK_UGT;
486 case TOK_UGT:
487 return TOK_ULE;
488 case TOK_Nset:
489 return TOK_Nclear;
490 case TOK_Nclear:
491 return TOK_Nset;
492 case TOK_LT:
493 return TOK_GE;
494 case TOK_GE:
495 return TOK_LT;
496 case TOK_LE:
497 return TOK_GT;
498 case TOK_GT:
499 return TOK_LE;
501 tcc_error("unexpected condition code");
502 return TOK_NE;
505 /* load 'r' from value 'sv' */
506 void load(int r, SValue *sv)
508 int v, ft, fc, fr, sign;
509 uint32_t op;
510 SValue v1;
512 fr = sv->r;
513 ft = sv->type.t;
514 fc = sv->c.i;
516 if(fc>=0)
517 sign=0;
518 else {
519 sign=1;
520 fc=-fc;
523 v = fr & VT_VALMASK;
524 if (fr & VT_LVAL) {
525 uint32_t base = 0xB; // fp
526 if(v == VT_LLOCAL) {
527 v1.type.t = VT_PTR;
528 v1.r = VT_LOCAL | VT_LVAL;
529 v1.c.i = sv->c.i;
530 load(TREG_LR, &v1);
531 base = 14; /* lr */
532 fc=sign=0;
533 v=VT_LOCAL;
534 } else if(v == VT_CONST) {
535 v1.type.t = VT_PTR;
536 v1.r = fr&~VT_LVAL;
537 v1.c.i = sv->c.i;
538 v1.sym=sv->sym;
539 load(TREG_LR, &v1);
540 base = 14; /* lr */
541 fc=sign=0;
542 v=VT_LOCAL;
543 } else if(v < VT_CONST) {
544 base=intr(v);
545 fc=sign=0;
546 v=VT_LOCAL;
548 if(v == VT_LOCAL) {
549 if(is_float(ft)) {
550 calcaddr(&base,&fc,&sign,1020,2);
551 #ifdef TCC_ARM_VFP
552 op=0xED100A00; /* flds */
553 if(!sign)
554 op|=0x800000;
555 if ((ft & VT_BTYPE) != VT_FLOAT)
556 op|=0x100; /* flds -> fldd */
557 o(op|(vfpr(r)<<12)|(fc>>2)|(base<<16));
558 #else
559 op=0xED100100;
560 if(!sign)
561 op|=0x800000;
562 #if LDOUBLE_SIZE == 8
563 if ((ft & VT_BTYPE) != VT_FLOAT)
564 op|=0x8000;
565 #else
566 if ((ft & VT_BTYPE) == VT_DOUBLE)
567 op|=0x8000;
568 else if ((ft & VT_BTYPE) == VT_LDOUBLE)
569 op|=0x400000;
570 #endif
571 o(op|(fpr(r)<<12)|(fc>>2)|(base<<16));
572 #endif
573 } else if((ft & (VT_BTYPE|VT_UNSIGNED)) == VT_BYTE
574 || (ft & VT_BTYPE) == VT_SHORT) {
575 calcaddr(&base,&fc,&sign,255,0);
576 op=0xE1500090;
577 if ((ft & VT_BTYPE) == VT_SHORT)
578 op|=0x20;
579 if ((ft & VT_UNSIGNED) == 0)
580 op|=0x40;
581 if(!sign)
582 op|=0x800000;
583 o(op|(intr(r)<<12)|(base<<16)|((fc&0xf0)<<4)|(fc&0xf));
584 } else {
585 calcaddr(&base,&fc,&sign,4095,0);
586 op=0xE5100000;
587 if(!sign)
588 op|=0x800000;
589 if ((ft & VT_BTYPE) == VT_BYTE || (ft & VT_BTYPE) == VT_BOOL)
590 op|=0x400000;
591 o(op|(intr(r)<<12)|fc|(base<<16));
593 return;
595 } else {
596 if (v == VT_CONST) {
597 op=stuff_const(0xE3A00000|(intr(r)<<12),sv->c.i);
598 if (fr & VT_SYM || !op) {
599 o(0xE59F0000|(intr(r)<<12));
600 o(0xEA000000);
601 if(fr & VT_SYM)
602 greloc(cur_text_section, sv->sym, ind, R_ARM_ABS32);
603 o(sv->c.i);
604 } else
605 o(op);
606 return;
607 } else if (v == VT_LOCAL) {
608 op=stuff_const(0xE28B0000|(intr(r)<<12),sv->c.i);
609 if (fr & VT_SYM || !op) {
610 o(0xE59F0000|(intr(r)<<12));
611 o(0xEA000000);
612 if(fr & VT_SYM) // needed ?
613 greloc(cur_text_section, sv->sym, ind, R_ARM_ABS32);
614 o(sv->c.i);
615 o(0xE08B0000|(intr(r)<<12)|intr(r));
616 } else
617 o(op);
618 return;
619 } else if(v == VT_CMP) {
620 o(mapcc(sv->c.i)|0x3A00001|(intr(r)<<12));
621 o(mapcc(negcc(sv->c.i))|0x3A00000|(intr(r)<<12));
622 return;
623 } else if (v == VT_JMP || v == VT_JMPI) {
624 int t;
625 t = v & 1;
626 o(0xE3A00000|(intr(r)<<12)|t);
627 o(0xEA000000);
628 gsym(sv->c.i);
629 o(0xE3A00000|(intr(r)<<12)|(t^1));
630 return;
631 } else if (v < VT_CONST) {
632 if(is_float(ft))
633 #ifdef TCC_ARM_VFP
634 o(0xEEB00A40|(vfpr(r)<<12)|vfpr(v)|T2CPR(ft)); /* fcpyX */
635 #else
636 o(0xEE008180|(fpr(r)<<12)|fpr(v));
637 #endif
638 else
639 o(0xE1A00000|(intr(r)<<12)|intr(v));
640 return;
643 tcc_error("load unimplemented!");
646 /* store register 'r' in lvalue 'v' */
647 void store(int r, SValue *sv)
649 SValue v1;
650 int v, ft, fc, fr, sign;
651 uint32_t op;
653 fr = sv->r;
654 ft = sv->type.t;
655 fc = sv->c.i;
657 if(fc>=0)
658 sign=0;
659 else {
660 sign=1;
661 fc=-fc;
664 v = fr & VT_VALMASK;
665 if (fr & VT_LVAL || fr == VT_LOCAL) {
666 uint32_t base = 0xb; /* fp */
667 if(v < VT_CONST) {
668 base=intr(v);
669 v=VT_LOCAL;
670 fc=sign=0;
671 } else if(v == VT_CONST) {
672 v1.type.t = ft;
673 v1.r = fr&~VT_LVAL;
674 v1.c.i = sv->c.i;
675 v1.sym=sv->sym;
676 load(TREG_LR, &v1);
677 base = 14; /* lr */
678 fc=sign=0;
679 v=VT_LOCAL;
681 if(v == VT_LOCAL) {
682 if(is_float(ft)) {
683 calcaddr(&base,&fc,&sign,1020,2);
684 #ifdef TCC_ARM_VFP
685 op=0xED000A00; /* fsts */
686 if(!sign)
687 op|=0x800000;
688 if ((ft & VT_BTYPE) != VT_FLOAT)
689 op|=0x100; /* fsts -> fstd */
690 o(op|(vfpr(r)<<12)|(fc>>2)|(base<<16));
691 #else
692 op=0xED000100;
693 if(!sign)
694 op|=0x800000;
695 #if LDOUBLE_SIZE == 8
696 if ((ft & VT_BTYPE) != VT_FLOAT)
697 op|=0x8000;
698 #else
699 if ((ft & VT_BTYPE) == VT_DOUBLE)
700 op|=0x8000;
701 if ((ft & VT_BTYPE) == VT_LDOUBLE)
702 op|=0x400000;
703 #endif
704 o(op|(fpr(r)<<12)|(fc>>2)|(base<<16));
705 #endif
706 return;
707 } else if((ft & VT_BTYPE) == VT_SHORT) {
708 calcaddr(&base,&fc,&sign,255,0);
709 op=0xE14000B0;
710 if(!sign)
711 op|=0x800000;
712 o(op|(intr(r)<<12)|(base<<16)|((fc&0xf0)<<4)|(fc&0xf));
713 } else {
714 calcaddr(&base,&fc,&sign,4095,0);
715 op=0xE5000000;
716 if(!sign)
717 op|=0x800000;
718 if ((ft & VT_BTYPE) == VT_BYTE || (ft & VT_BTYPE) == VT_BOOL)
719 op|=0x400000;
720 o(op|(intr(r)<<12)|fc|(base<<16));
722 return;
725 tcc_error("store unimplemented");
728 static void gadd_sp(int val)
730 stuff_const_harder(0xE28DD000,val);
733 /* 'is_jmp' is '1' if it is a jump */
734 static void gcall_or_jmp(int is_jmp)
736 int r;
737 uint32_t x;
738 if ((vtop->r & (VT_VALMASK | VT_LVAL)) == VT_CONST) {
739 /* constant case */
740 if(vtop->r & VT_SYM){
741 x=encbranch(ind,ind+vtop->c.i,0);
742 if(x) {
743 /* relocation case */
744 greloc(cur_text_section, vtop->sym, ind, R_ARM_PC24);
745 o(x|(is_jmp?0xE0000000:0xE1000000));
746 } else {
747 if(!is_jmp)
748 o(0xE28FE004); // add lr,pc,#4
749 o(0xE51FF004); // ldr pc,[pc,#-4]
750 greloc(cur_text_section, vtop->sym, ind, R_ARM_ABS32);
751 o(vtop->c.i);
753 }else{
754 if(!is_jmp)
755 o(0xE28FE004); // add lr,pc,#4
756 o(0xE51FF004); // ldr pc,[pc,#-4]
757 o(vtop->c.i);
759 } else {
760 /* otherwise, indirect call */
761 r = gv(RC_INT);
762 if(!is_jmp)
763 o(0xE1A0E00F); // mov lr,pc
764 o(0xE1A0F000|intr(r)); // mov pc,r
768 static int unalias_ldbl(int btype)
770 #if LDOUBLE_SIZE == 8
771 if (btype == VT_LDOUBLE)
772 btype = VT_DOUBLE;
773 #endif
774 return btype;
777 /* Return whether a structure is an homogeneous float aggregate or not.
778 The answer is true if all the elements of the structure are of the same
779 primitive float type and there is less than 4 elements.
781 type: the type corresponding to the structure to be tested */
782 static int is_hgen_float_aggr(CType *type)
784 if ((type->t & VT_BTYPE) == VT_STRUCT) {
785 struct Sym *ref;
786 int btype, nb_fields = 0;
788 ref = type->ref->next;
789 btype = unalias_ldbl(ref->type.t & VT_BTYPE);
790 if (btype == VT_FLOAT || btype == VT_DOUBLE) {
791 for(; ref && btype == unalias_ldbl(ref->type.t & VT_BTYPE); ref = ref->next, nb_fields++);
792 return !ref && nb_fields <= 4;
795 return 0;
798 struct avail_regs {
799 signed char avail[3]; /* 3 holes max with only float and double alignments */
800 int first_hole; /* first available hole */
801 int last_hole; /* last available hole (none if equal to first_hole) */
802 int first_free_reg; /* next free register in the sequence, hole excluded */
805 #define AVAIL_REGS_INITIALIZER (struct avail_regs) { { 0, 0, 0}, 0, 0, 0 }
807 /* Find suitable registers for a VFP Co-Processor Register Candidate (VFP CPRC
808 param) according to the rules described in the procedure call standard for
809 the ARM architecture (AAPCS). If found, the registers are assigned to this
810 VFP CPRC parameter. Registers are allocated in sequence unless a hole exists
811 and the parameter is a single float.
813 avregs: opaque structure to keep track of available VFP co-processor regs
814 align: alignment constraints for the param, as returned by type_size()
815 size: size of the parameter, as returned by type_size() */
816 int assign_vfpreg(struct avail_regs *avregs, int align, int size)
818 int first_reg = 0;
820 if (avregs->first_free_reg == -1)
821 return -1;
822 if (align >> 3) { /* double alignment */
823 first_reg = avregs->first_free_reg;
824 /* alignment constraint not respected so use next reg and record hole */
825 if (first_reg & 1)
826 avregs->avail[avregs->last_hole++] = first_reg++;
827 } else { /* no special alignment (float or array of float) */
828 /* if single float and a hole is available, assign the param to it */
829 if (size == 4 && avregs->first_hole != avregs->last_hole)
830 return avregs->avail[avregs->first_hole++];
831 else
832 first_reg = avregs->first_free_reg;
834 if (first_reg + size / 4 <= 16) {
835 avregs->first_free_reg = first_reg + size / 4;
836 return first_reg;
838 avregs->first_free_reg = -1;
839 return -1;
842 /* Returns whether all params need to be passed in core registers or not.
843 This is the case for function part of the runtime ABI. */
844 int floats_in_core_regs(SValue *sval)
846 if (!sval->sym)
847 return 0;
849 switch (sval->sym->v) {
850 case TOK___floatundisf:
851 case TOK___floatundidf:
852 case TOK___fixunssfdi:
853 case TOK___fixunsdfdi:
854 #ifndef TCC_ARM_VFP
855 case TOK___fixunsxfdi:
856 #endif
857 case TOK___floatdisf:
858 case TOK___floatdidf:
859 case TOK___fixsfdi:
860 case TOK___fixdfdi:
861 return 1;
863 default:
864 return 0;
868 /* Return the number of registers needed to return the struct, or 0 if
869 returning via struct pointer. */
870 ST_FUNC int gfunc_sret(CType *vt, int variadic, CType *ret, int *ret_align, int *regsize) {
871 #ifdef TCC_ARM_EABI
872 int size, align;
873 size = type_size(vt, &align);
874 if (float_abi == ARM_HARD_FLOAT && !variadic &&
875 (is_float(vt->t) || is_hgen_float_aggr(vt))) {
876 *ret_align = 8;
877 *regsize = 8;
878 ret->ref = NULL;
879 ret->t = VT_DOUBLE;
880 return (size + 7) >> 3;
881 } else if (size <= 4) {
882 *ret_align = 4;
883 *regsize = 4;
884 ret->ref = NULL;
885 ret->t = VT_INT;
886 return 1;
887 } else
888 return 0;
889 #else
890 return 0;
891 #endif
894 /* Parameters are classified according to how they are copied to their final
895 destination for the function call. Because the copying is performed class
896 after class according to the order in the union below, it is important that
897 some constraints about the order of the members of this union are respected:
898 - CORE_STRUCT_CLASS must come after STACK_CLASS;
899 - CORE_CLASS must come after STACK_CLASS, CORE_STRUCT_CLASS and
900 VFP_STRUCT_CLASS;
901 - VFP_STRUCT_CLASS must come after VFP_CLASS.
902 See the comment for the main loop in copy_params() for the reason. */
903 enum reg_class {
904 STACK_CLASS = 0,
905 CORE_STRUCT_CLASS,
906 VFP_CLASS,
907 VFP_STRUCT_CLASS,
908 CORE_CLASS,
909 NB_CLASSES
912 struct param_plan {
913 int start; /* first reg or addr used depending on the class */
914 int end; /* last reg used or next free addr depending on the class */
915 SValue *sval; /* pointer to SValue on the value stack */
916 struct param_plan *prev; /* previous element in this class */
919 struct plan {
920 struct param_plan *pplans; /* array of all the param plans */
921 struct param_plan *clsplans[NB_CLASSES]; /* per class lists of param plans */
924 #define add_param_plan(plan,pplan,class) \
925 do { \
926 pplan.prev = plan->clsplans[class]; \
927 plan->pplans[plan ## _nb] = pplan; \
928 plan->clsplans[class] = &plan->pplans[plan ## _nb++]; \
929 } while(0)
931 /* Assign parameters to registers and stack with alignment according to the
932 rules in the procedure call standard for the ARM architecture (AAPCS).
933 The overall assignment is recorded in an array of per parameter structures
934 called parameter plans. The parameter plans are also further organized in a
935 number of linked lists, one per class of parameter (see the comment for the
936 definition of union reg_class).
938 nb_args: number of parameters of the function for which a call is generated
939 float_abi: float ABI in use for this function call
940 plan: the structure where the overall assignment is recorded
941 todo: a bitmap that record which core registers hold a parameter
943 Returns the amount of stack space needed for parameter passing
945 Note: this function allocated an array in plan->pplans with tcc_malloc. It
946 is the responsibility of the caller to free this array once used (ie not
947 before copy_params). */
948 static int assign_regs(int nb_args, int float_abi, struct plan *plan, int *todo)
950 int i, size, align;
951 int ncrn /* next core register number */, nsaa /* next stacked argument address*/;
952 int plan_nb = 0;
953 struct param_plan pplan;
954 struct avail_regs avregs = AVAIL_REGS_INITIALIZER;
956 ncrn = nsaa = 0;
957 *todo = 0;
958 plan->pplans = tcc_malloc(nb_args * sizeof(*plan->pplans));
959 memset(plan->clsplans, 0, sizeof(plan->clsplans));
960 for(i = nb_args; i-- ;) {
961 int j, start_vfpreg = 0;
962 CType type = vtop[-i].type;
963 type.t &= ~VT_ARRAY;
964 size = type_size(&type, &align);
965 size = (size + 3) & ~3;
966 align = (align + 3) & ~3;
967 switch(vtop[-i].type.t & VT_BTYPE) {
968 case VT_STRUCT:
969 case VT_FLOAT:
970 case VT_DOUBLE:
971 case VT_LDOUBLE:
972 if (float_abi == ARM_HARD_FLOAT) {
973 int is_hfa = 0; /* Homogeneous float aggregate */
975 if (is_float(vtop[-i].type.t)
976 || (is_hfa = is_hgen_float_aggr(&vtop[-i].type))) {
977 int end_vfpreg;
979 start_vfpreg = assign_vfpreg(&avregs, align, size);
980 end_vfpreg = start_vfpreg + ((size - 1) >> 2);
981 if (start_vfpreg >= 0) {
982 pplan = (struct param_plan) {start_vfpreg, end_vfpreg, &vtop[-i]};
983 if (is_hfa)
984 add_param_plan(plan, pplan, VFP_STRUCT_CLASS);
985 else
986 add_param_plan(plan, pplan, VFP_CLASS);
987 continue;
988 } else
989 break;
992 ncrn = (ncrn + (align-1)/4) & ~((align/4) - 1);
993 if (ncrn + size/4 <= 4 || (ncrn < 4 && start_vfpreg != -1)) {
994 /* The parameter is allocated both in core register and on stack. As
995 * such, it can be of either class: it would either be the last of
996 * CORE_STRUCT_CLASS or the first of STACK_CLASS. */
997 for (j = ncrn; j < 4 && j < ncrn + size / 4; j++)
998 *todo|=(1<<j);
999 pplan = (struct param_plan) {ncrn, j, &vtop[-i]};
1000 add_param_plan(plan, pplan, CORE_STRUCT_CLASS);
1001 ncrn += size/4;
1002 if (ncrn > 4)
1003 nsaa = (ncrn - 4) * 4;
1004 } else {
1005 ncrn = 4;
1006 break;
1008 continue;
1009 default:
1010 if (ncrn < 4) {
1011 int is_long = (vtop[-i].type.t & VT_BTYPE) == VT_LLONG;
1013 if (is_long) {
1014 ncrn = (ncrn + 1) & -2;
1015 if (ncrn == 4)
1016 break;
1018 pplan = (struct param_plan) {ncrn, ncrn, &vtop[-i]};
1019 ncrn++;
1020 if (is_long)
1021 pplan.end = ncrn++;
1022 add_param_plan(plan, pplan, CORE_CLASS);
1023 continue;
1026 nsaa = (nsaa + (align - 1)) & ~(align - 1);
1027 pplan = (struct param_plan) {nsaa, nsaa + size, &vtop[-i]};
1028 add_param_plan(plan, pplan, STACK_CLASS);
1029 nsaa += size; /* size already rounded up before */
1031 return nsaa;
1034 #undef add_param_plan
1036 /* Copy parameters to their final destination (core reg, VFP reg or stack) for
1037 function call.
1039 nb_args: number of parameters the function take
1040 plan: the overall assignment plan for parameters
1041 todo: a bitmap indicating what core reg will hold a parameter
1043 Returns the number of SValue added by this function on the value stack */
1044 static int copy_params(int nb_args, struct plan *plan, int todo)
1046 int size, align, r, i, nb_extra_sval = 0;
1047 struct param_plan *pplan;
1048 int pass = 0;
1050 /* Several constraints require parameters to be copied in a specific order:
1051 - structures are copied to the stack before being loaded in a reg;
1052 - floats loaded to an odd numbered VFP reg are first copied to the
1053 preceding even numbered VFP reg and then moved to the next VFP reg.
1055 It is thus important that:
1056 - structures assigned to core regs must be copied after parameters
1057 assigned to the stack but before structures assigned to VFP regs because
1058 a structure can lie partly in core registers and partly on the stack;
1059 - parameters assigned to the stack and all structures be copied before
1060 parameters assigned to a core reg since copying a parameter to the stack
1061 require using a core reg;
1062 - parameters assigned to VFP regs be copied before structures assigned to
1063 VFP regs as the copy might use an even numbered VFP reg that already
1064 holds part of a structure. */
1065 again:
1066 for(i = 0; i < NB_CLASSES; i++) {
1067 for(pplan = plan->clsplans[i]; pplan; pplan = pplan->prev) {
1069 if (pass
1070 && (i != CORE_CLASS || pplan->sval->r < VT_CONST))
1071 continue;
1073 vpushv(pplan->sval);
1074 pplan->sval->r = pplan->sval->r2 = VT_CONST; /* disable entry */
1075 switch(i) {
1076 case STACK_CLASS:
1077 case CORE_STRUCT_CLASS:
1078 case VFP_STRUCT_CLASS:
1079 if ((pplan->sval->type.t & VT_BTYPE) == VT_STRUCT) {
1080 int padding = 0;
1081 size = type_size(&pplan->sval->type, &align);
1082 /* align to stack align size */
1083 size = (size + 3) & ~3;
1084 if (i == STACK_CLASS && pplan->prev)
1085 padding = pplan->start - pplan->prev->end;
1086 size += padding; /* Add padding if any */
1087 /* allocate the necessary size on stack */
1088 gadd_sp(-size);
1089 /* generate structure store */
1090 r = get_reg(RC_INT);
1091 o(0xE28D0000|(intr(r)<<12)|padding); /* add r, sp, padding */
1092 vset(&vtop->type, r | VT_LVAL, 0);
1093 vswap();
1094 vstore(); /* memcpy to current sp + potential padding */
1096 /* Homogeneous float aggregate are loaded to VFP registers
1097 immediately since there is no way of loading data in multiple
1098 non consecutive VFP registers as what is done for other
1099 structures (see the use of todo). */
1100 if (i == VFP_STRUCT_CLASS) {
1101 int first = pplan->start, nb = pplan->end - first + 1;
1102 /* vpop.32 {pplan->start, ..., pplan->end} */
1103 o(0xECBD0A00|(first&1)<<22|(first>>1)<<12|nb);
1104 /* No need to write the register used to a SValue since VFP regs
1105 cannot be used for gcall_or_jmp */
1107 } else {
1108 if (is_float(pplan->sval->type.t)) {
1109 #ifdef TCC_ARM_VFP
1110 r = vfpr(gv(RC_FLOAT)) << 12;
1111 if ((pplan->sval->type.t & VT_BTYPE) == VT_FLOAT)
1112 size = 4;
1113 else {
1114 size = 8;
1115 r |= 0x101; /* vpush.32 -> vpush.64 */
1117 o(0xED2D0A01 + r); /* vpush */
1118 #else
1119 r = fpr(gv(RC_FLOAT)) << 12;
1120 if ((pplan->sval->type.t & VT_BTYPE) == VT_FLOAT)
1121 size = 4;
1122 else if ((pplan->sval->type.t & VT_BTYPE) == VT_DOUBLE)
1123 size = 8;
1124 else
1125 size = LDOUBLE_SIZE;
1127 if (size == 12)
1128 r |= 0x400000;
1129 else if(size == 8)
1130 r|=0x8000;
1132 o(0xED2D0100|r|(size>>2)); /* some kind of vpush for FPA */
1133 #endif
1134 } else {
1135 /* simple type (currently always same size) */
1136 /* XXX: implicit cast ? */
1137 size=4;
1138 if ((pplan->sval->type.t & VT_BTYPE) == VT_LLONG) {
1139 lexpand();
1140 size = 8;
1141 r = gv(RC_INT);
1142 o(0xE52D0004|(intr(r)<<12)); /* push r */
1143 vtop--;
1145 r = gv(RC_INT);
1146 o(0xE52D0004|(intr(r)<<12)); /* push r */
1148 if (i == STACK_CLASS && pplan->prev)
1149 gadd_sp(pplan->prev->end - pplan->start); /* Add padding if any */
1151 break;
1153 case VFP_CLASS:
1154 gv(regmask(TREG_F0 + (pplan->start >> 1)));
1155 if (pplan->start & 1) { /* Must be in upper part of double register */
1156 o(0xEEF00A40|((pplan->start>>1)<<12)|(pplan->start>>1)); /* vmov.f32 s(n+1), sn */
1157 vtop->r = VT_CONST; /* avoid being saved on stack by gv for next float */
1159 break;
1161 case CORE_CLASS:
1162 if ((pplan->sval->type.t & VT_BTYPE) == VT_LLONG) {
1163 lexpand();
1164 gv(regmask(pplan->end));
1165 pplan->sval->r2 = vtop->r;
1166 vtop--;
1168 gv(regmask(pplan->start));
1169 /* Mark register as used so that gcall_or_jmp use another one
1170 (regs >=4 are free as never used to pass parameters) */
1171 pplan->sval->r = vtop->r;
1172 break;
1174 vtop--;
1178 /* second pass to restore registers that were saved on stack by accident.
1179 Maybe redundant after the "lvalue_save" patch in tccgen.c:gv() */
1180 if (++pass < 2)
1181 goto again;
1183 /* Manually free remaining registers since next parameters are loaded
1184 * manually, without the help of gv(int). */
1185 save_regs(nb_args);
1187 if(todo) {
1188 o(0xE8BD0000|todo); /* pop {todo} */
1189 for(pplan = plan->clsplans[CORE_STRUCT_CLASS]; pplan; pplan = pplan->prev) {
1190 int r;
1191 pplan->sval->r = pplan->start;
1192 /* An SValue can only pin 2 registers at best (r and r2) but a structure
1193 can occupy more than 2 registers. Thus, we need to push on the value
1194 stack some fake parameter to have on SValue for each registers used
1195 by a structure (r2 is not used). */
1196 for (r = pplan->start + 1; r <= pplan->end; r++) {
1197 if (todo & (1 << r)) {
1198 nb_extra_sval++;
1199 vpushi(0);
1200 vtop->r = r;
1205 return nb_extra_sval;
1208 /* Generate function call. The function address is pushed first, then
1209 all the parameters in call order. This functions pops all the
1210 parameters and the function address. */
1211 void gfunc_call(int nb_args)
1213 int r, args_size;
1214 int def_float_abi = float_abi;
1215 int todo;
1216 struct plan plan;
1218 #ifdef TCC_ARM_EABI
1219 int variadic;
1221 if (float_abi == ARM_HARD_FLOAT) {
1222 variadic = (vtop[-nb_args].type.ref->f.func_type == FUNC_ELLIPSIS);
1223 if (variadic || floats_in_core_regs(&vtop[-nb_args]))
1224 float_abi = ARM_SOFTFP_FLOAT;
1226 #endif
1227 /* cannot let cpu flags if other instruction are generated. Also avoid leaving
1228 VT_JMP anywhere except on the top of the stack because it would complicate
1229 the code generator. */
1230 r = vtop->r & VT_VALMASK;
1231 if (r == VT_CMP || (r & ~1) == VT_JMP)
1232 gv(RC_INT);
1234 args_size = assign_regs(nb_args, float_abi, &plan, &todo);
1236 #ifdef TCC_ARM_EABI
1237 if (args_size & 7) { /* Stack must be 8 byte aligned at fct call for EABI */
1238 args_size = (args_size + 7) & ~7;
1239 o(0xE24DD004); /* sub sp, sp, #4 */
1241 #endif
1243 nb_args += copy_params(nb_args, &plan, todo);
1244 tcc_free(plan.pplans);
1246 /* Move fct SValue on top as required by gcall_or_jmp */
1247 vrotb(nb_args + 1);
1248 gcall_or_jmp(0);
1249 if (args_size)
1250 gadd_sp(args_size); /* pop all parameters passed on the stack */
1251 #if defined(TCC_ARM_EABI) && defined(TCC_ARM_VFP)
1252 if(float_abi == ARM_SOFTFP_FLOAT && is_float(vtop->type.ref->type.t)) {
1253 if((vtop->type.ref->type.t & VT_BTYPE) == VT_FLOAT) {
1254 o(0xEE000A10); /*vmov s0, r0 */
1255 } else {
1256 o(0xEE000B10); /* vmov.32 d0[0], r0 */
1257 o(0xEE201B10); /* vmov.32 d0[1], r1 */
1260 #endif
1261 vtop -= nb_args + 1; /* Pop all params and fct address from value stack */
1262 leaffunc = 0; /* we are calling a function, so we aren't in a leaf function */
1263 float_abi = def_float_abi;
1266 /* generate function prolog of type 't' */
1267 void gfunc_prolog(CType *func_type)
1269 Sym *sym,*sym2;
1270 int n, nf, size, align, rs, struct_ret = 0;
1271 int addr, pn, sn; /* pn=core, sn=stack */
1272 CType ret_type;
1274 #ifdef TCC_ARM_EABI
1275 struct avail_regs avregs = AVAIL_REGS_INITIALIZER;
1276 #endif
1278 sym = func_type->ref;
1279 func_vt = sym->type;
1280 func_var = (func_type->ref->f.func_type == FUNC_ELLIPSIS);
1282 n = nf = 0;
1283 if ((func_vt.t & VT_BTYPE) == VT_STRUCT &&
1284 !gfunc_sret(&func_vt, func_var, &ret_type, &align, &rs))
1286 n++;
1287 struct_ret = 1;
1288 func_vc = 12; /* Offset from fp of the place to store the result */
1290 for(sym2 = sym->next; sym2 && (n < 4 || nf < 16); sym2 = sym2->next) {
1291 size = type_size(&sym2->type, &align);
1292 #ifdef TCC_ARM_EABI
1293 if (float_abi == ARM_HARD_FLOAT && !func_var &&
1294 (is_float(sym2->type.t) || is_hgen_float_aggr(&sym2->type))) {
1295 int tmpnf = assign_vfpreg(&avregs, align, size);
1296 tmpnf += (size + 3) / 4;
1297 nf = (tmpnf > nf) ? tmpnf : nf;
1298 } else
1299 #endif
1300 if (n < 4)
1301 n += (size + 3) / 4;
1303 o(0xE1A0C00D); /* mov ip,sp */
1304 if (func_var)
1305 n=4;
1306 if (n) {
1307 if(n>4)
1308 n=4;
1309 #ifdef TCC_ARM_EABI
1310 n=(n+1)&-2;
1311 #endif
1312 o(0xE92D0000|((1<<n)-1)); /* save r0-r4 on stack if needed */
1314 if (nf) {
1315 if (nf>16)
1316 nf=16;
1317 nf=(nf+1)&-2; /* nf => HARDFLOAT => EABI */
1318 o(0xED2D0A00|nf); /* save s0-s15 on stack if needed */
1320 o(0xE92D5800); /* save fp, ip, lr */
1321 o(0xE1A0B00D); /* mov fp, sp */
1322 func_sub_sp_offset = ind;
1323 o(0xE1A00000); /* nop, leave space for stack adjustment in epilog */
1325 #ifdef TCC_ARM_EABI
1326 if (float_abi == ARM_HARD_FLOAT) {
1327 func_vc += nf * 4;
1328 avregs = AVAIL_REGS_INITIALIZER;
1330 #endif
1331 pn = struct_ret, sn = 0;
1332 while ((sym = sym->next)) {
1333 CType *type;
1334 type = &sym->type;
1335 size = type_size(type, &align);
1336 size = (size + 3) >> 2;
1337 align = (align + 3) & ~3;
1338 #ifdef TCC_ARM_EABI
1339 if (float_abi == ARM_HARD_FLOAT && !func_var && (is_float(sym->type.t)
1340 || is_hgen_float_aggr(&sym->type))) {
1341 int fpn = assign_vfpreg(&avregs, align, size << 2);
1342 if (fpn >= 0)
1343 addr = fpn * 4;
1344 else
1345 goto from_stack;
1346 } else
1347 #endif
1348 if (pn < 4) {
1349 #ifdef TCC_ARM_EABI
1350 pn = (pn + (align-1)/4) & -(align/4);
1351 #endif
1352 addr = (nf + pn) * 4;
1353 pn += size;
1354 if (!sn && pn > 4)
1355 sn = (pn - 4);
1356 } else {
1357 #ifdef TCC_ARM_EABI
1358 from_stack:
1359 sn = (sn + (align-1)/4) & -(align/4);
1360 #endif
1361 addr = (n + nf + sn) * 4;
1362 sn += size;
1364 sym_push(sym->v & ~SYM_FIELD, type, VT_LOCAL | lvalue_type(type->t),
1365 addr + 12);
1367 last_itod_magic=0;
1368 leaffunc = 1;
1369 loc = 0;
1372 /* generate function epilog */
1373 void gfunc_epilog(void)
1375 uint32_t x;
1376 int diff;
1377 /* Copy float return value to core register if base standard is used and
1378 float computation is made with VFP */
1379 #if defined(TCC_ARM_EABI) && defined(TCC_ARM_VFP)
1380 if ((float_abi == ARM_SOFTFP_FLOAT || func_var) && is_float(func_vt.t)) {
1381 if((func_vt.t & VT_BTYPE) == VT_FLOAT)
1382 o(0xEE100A10); /* fmrs r0, s0 */
1383 else {
1384 o(0xEE100B10); /* fmrdl r0, d0 */
1385 o(0xEE301B10); /* fmrdh r1, d0 */
1388 #endif
1389 o(0xE89BA800); /* restore fp, sp, pc */
1390 diff = (-loc + 3) & -4;
1391 #ifdef TCC_ARM_EABI
1392 if(!leaffunc)
1393 diff = ((diff + 11) & -8) - 4;
1394 #endif
1395 if(diff > 0) {
1396 x=stuff_const(0xE24BD000, diff); /* sub sp,fp,# */
1397 if(x)
1398 *(uint32_t *)(cur_text_section->data + func_sub_sp_offset) = x;
1399 else {
1400 int addr;
1401 addr=ind;
1402 o(0xE59FC004); /* ldr ip,[pc+4] */
1403 o(0xE04BD00C); /* sub sp,fp,ip */
1404 o(0xE1A0F00E); /* mov pc,lr */
1405 o(diff);
1406 *(uint32_t *)(cur_text_section->data + func_sub_sp_offset) = 0xE1000000|encbranch(func_sub_sp_offset,addr,1);
1411 ST_FUNC void gen_fill_nops(int bytes)
1413 if ((bytes & 3))
1414 tcc_error("alignment of code section not multiple of 4");
1415 while (bytes > 0) {
1416 o(0xE1A00000);
1417 bytes -= 4;
1421 /* generate a jump to a label */
1422 ST_FUNC int gjmp(int t)
1424 int r;
1425 if (nocode_wanted)
1426 return t;
1427 r=ind;
1428 o(0xE0000000|encbranch(r,t,1));
1429 return r;
1432 /* generate a jump to a fixed address */
1433 ST_FUNC void gjmp_addr(int a)
1435 gjmp(a);
1438 ST_FUNC int gjmp_cond(int op, int t)
1440 int r;
1441 if (nocode_wanted)
1442 return t;
1443 r=ind;
1444 op=mapcc(op);
1445 op|=encbranch(r,t,1);
1446 o(op);
1447 return r;
1450 ST_FUNC int gjmp_append(int n, int t)
1452 uint32_t *x;
1453 int p,lp;
1454 if(n) {
1455 p = n;
1456 do {
1457 p = decbranch(lp=p);
1458 } while(p);
1459 x = (uint32_t *)(cur_text_section->data + lp);
1460 *x &= 0xff000000;
1461 *x |= encbranch(lp,t,1);
1462 t = n;
1464 return t;
1467 /* generate an integer binary operation */
1468 void gen_opi(int op)
1470 int c, func = 0;
1471 uint32_t opc = 0, r, fr;
1472 unsigned short retreg = REG_IRET;
1474 c=0;
1475 switch(op) {
1476 case '+':
1477 opc = 0x8;
1478 c=1;
1479 break;
1480 case TOK_ADDC1: /* add with carry generation */
1481 opc = 0x9;
1482 c=1;
1483 break;
1484 case '-':
1485 opc = 0x4;
1486 c=1;
1487 break;
1488 case TOK_SUBC1: /* sub with carry generation */
1489 opc = 0x5;
1490 c=1;
1491 break;
1492 case TOK_ADDC2: /* add with carry use */
1493 opc = 0xA;
1494 c=1;
1495 break;
1496 case TOK_SUBC2: /* sub with carry use */
1497 opc = 0xC;
1498 c=1;
1499 break;
1500 case '&':
1501 opc = 0x0;
1502 c=1;
1503 break;
1504 case '^':
1505 opc = 0x2;
1506 c=1;
1507 break;
1508 case '|':
1509 opc = 0x18;
1510 c=1;
1511 break;
1512 case '*':
1513 gv2(RC_INT, RC_INT);
1514 r = vtop[-1].r;
1515 fr = vtop[0].r;
1516 vtop--;
1517 o(0xE0000090|(intr(r)<<16)|(intr(r)<<8)|intr(fr));
1518 return;
1519 case TOK_SHL:
1520 opc = 0;
1521 c=2;
1522 break;
1523 case TOK_SHR:
1524 opc = 1;
1525 c=2;
1526 break;
1527 case TOK_SAR:
1528 opc = 2;
1529 c=2;
1530 break;
1531 case '/':
1532 case TOK_PDIV:
1533 func=TOK___divsi3;
1534 c=3;
1535 break;
1536 case TOK_UDIV:
1537 func=TOK___udivsi3;
1538 c=3;
1539 break;
1540 case '%':
1541 #ifdef TCC_ARM_EABI
1542 func=TOK___aeabi_idivmod;
1543 retreg=REG_LRET;
1544 #else
1545 func=TOK___modsi3;
1546 #endif
1547 c=3;
1548 break;
1549 case TOK_UMOD:
1550 #ifdef TCC_ARM_EABI
1551 func=TOK___aeabi_uidivmod;
1552 retreg=REG_LRET;
1553 #else
1554 func=TOK___umodsi3;
1555 #endif
1556 c=3;
1557 break;
1558 case TOK_UMULL:
1559 gv2(RC_INT, RC_INT);
1560 r=intr(vtop[-1].r2=get_reg(RC_INT));
1561 c=vtop[-1].r;
1562 vtop[-1].r=get_reg_ex(RC_INT,regmask(c));
1563 vtop--;
1564 o(0xE0800090|(r<<16)|(intr(vtop->r)<<12)|(intr(c)<<8)|intr(vtop[1].r));
1565 return;
1566 default:
1567 opc = 0x15;
1568 c=1;
1569 break;
1571 switch(c) {
1572 case 1:
1573 if((vtop[-1].r & (VT_VALMASK | VT_LVAL | VT_SYM)) == VT_CONST) {
1574 if(opc == 4 || opc == 5 || opc == 0xc) {
1575 vswap();
1576 opc|=2; // sub -> rsb
1579 if ((vtop->r & VT_VALMASK) == VT_CMP ||
1580 (vtop->r & (VT_VALMASK & ~1)) == VT_JMP)
1581 gv(RC_INT);
1582 vswap();
1583 c=intr(gv(RC_INT));
1584 vswap();
1585 opc=0xE0000000|(opc<<20)|(c<<16);
1586 if((vtop->r & (VT_VALMASK | VT_LVAL | VT_SYM)) == VT_CONST) {
1587 uint32_t x;
1588 x=stuff_const(opc|0x2000000,vtop->c.i);
1589 if(x) {
1590 r=intr(vtop[-1].r=get_reg_ex(RC_INT,regmask(vtop[-1].r)));
1591 o(x|(r<<12));
1592 goto done;
1595 fr=intr(gv(RC_INT));
1596 r=intr(vtop[-1].r=get_reg_ex(RC_INT,two2mask(vtop->r,vtop[-1].r)));
1597 o(opc|(r<<12)|fr);
1598 done:
1599 vtop--;
1600 if (op >= TOK_ULT && op <= TOK_GT)
1601 vset_VT_CMP(op);
1602 break;
1603 case 2:
1604 opc=0xE1A00000|(opc<<5);
1605 if ((vtop->r & VT_VALMASK) == VT_CMP ||
1606 (vtop->r & (VT_VALMASK & ~1)) == VT_JMP)
1607 gv(RC_INT);
1608 vswap();
1609 r=intr(gv(RC_INT));
1610 vswap();
1611 opc|=r;
1612 if ((vtop->r & (VT_VALMASK | VT_LVAL | VT_SYM)) == VT_CONST) {
1613 fr=intr(vtop[-1].r=get_reg_ex(RC_INT,regmask(vtop[-1].r)));
1614 c = vtop->c.i & 0x1f;
1615 o(opc|(c<<7)|(fr<<12));
1616 } else {
1617 fr=intr(gv(RC_INT));
1618 c=intr(vtop[-1].r=get_reg_ex(RC_INT,two2mask(vtop->r,vtop[-1].r)));
1619 o(opc|(c<<12)|(fr<<8)|0x10);
1621 vtop--;
1622 break;
1623 case 3:
1624 vpush_global_sym(&func_old_type, func);
1625 vrott(3);
1626 gfunc_call(2);
1627 vpushi(0);
1628 vtop->r = retreg;
1629 break;
1630 default:
1631 tcc_error("gen_opi %i unimplemented!",op);
1635 #ifdef TCC_ARM_VFP
1636 static int is_zero(int i)
1638 if((vtop[i].r & (VT_VALMASK | VT_LVAL | VT_SYM)) != VT_CONST)
1639 return 0;
1640 if (vtop[i].type.t == VT_FLOAT)
1641 return (vtop[i].c.f == 0.f);
1642 else if (vtop[i].type.t == VT_DOUBLE)
1643 return (vtop[i].c.d == 0.0);
1644 return (vtop[i].c.ld == 0.l);
1647 /* generate a floating point operation 'v = t1 op t2' instruction. The
1648 * two operands are guaranteed to have the same floating point type */
1649 void gen_opf(int op)
1651 uint32_t x;
1652 int fneg=0,r;
1653 x=0xEE000A00|T2CPR(vtop->type.t);
1654 switch(op) {
1655 case '+':
1656 if(is_zero(-1))
1657 vswap();
1658 if(is_zero(0)) {
1659 vtop--;
1660 return;
1662 x|=0x300000;
1663 break;
1664 case '-':
1665 x|=0x300040;
1666 if(is_zero(0)) {
1667 vtop--;
1668 return;
1670 if(is_zero(-1)) {
1671 x|=0x810000; /* fsubX -> fnegX */
1672 vswap();
1673 vtop--;
1674 fneg=1;
1676 break;
1677 case '*':
1678 x|=0x200000;
1679 break;
1680 case '/':
1681 x|=0x800000;
1682 break;
1683 default:
1684 if(op < TOK_ULT || op > TOK_GT) {
1685 tcc_error("unknown fp op %x!",op);
1686 return;
1688 if(is_zero(-1)) {
1689 vswap();
1690 switch(op) {
1691 case TOK_LT: op=TOK_GT; break;
1692 case TOK_GE: op=TOK_ULE; break;
1693 case TOK_LE: op=TOK_GE; break;
1694 case TOK_GT: op=TOK_ULT; break;
1697 x|=0xB40040; /* fcmpX */
1698 if(op!=TOK_EQ && op!=TOK_NE)
1699 x|=0x80; /* fcmpX -> fcmpeX */
1700 if(is_zero(0)) {
1701 vtop--;
1702 o(x|0x10000|(vfpr(gv(RC_FLOAT))<<12)); /* fcmp(e)X -> fcmp(e)zX */
1703 } else {
1704 x|=vfpr(gv(RC_FLOAT));
1705 vswap();
1706 o(x|(vfpr(gv(RC_FLOAT))<<12));
1707 vtop--;
1709 o(0xEEF1FA10); /* fmstat */
1711 switch(op) {
1712 case TOK_LE: op=TOK_ULE; break;
1713 case TOK_LT: op=TOK_ULT; break;
1714 case TOK_UGE: op=TOK_GE; break;
1715 case TOK_UGT: op=TOK_GT; break;
1717 vset_VT_CMP(op);
1718 return;
1720 r=gv(RC_FLOAT);
1721 x|=vfpr(r);
1722 r=regmask(r);
1723 if(!fneg) {
1724 int r2;
1725 vswap();
1726 r2=gv(RC_FLOAT);
1727 x|=vfpr(r2)<<16;
1728 r|=regmask(r2);
1730 vtop->r=get_reg_ex(RC_FLOAT,r);
1731 if(!fneg)
1732 vtop--;
1733 o(x|(vfpr(vtop->r)<<12));
1736 #else
1737 static uint32_t is_fconst()
1739 long double f;
1740 uint32_t r;
1741 if((vtop->r & (VT_VALMASK | VT_LVAL | VT_SYM)) != VT_CONST)
1742 return 0;
1743 if (vtop->type.t == VT_FLOAT)
1744 f = vtop->c.f;
1745 else if (vtop->type.t == VT_DOUBLE)
1746 f = vtop->c.d;
1747 else
1748 f = vtop->c.ld;
1749 if(!ieee_finite(f))
1750 return 0;
1751 r=0x8;
1752 if(f<0.0) {
1753 r=0x18;
1754 f=-f;
1756 if(f==0.0)
1757 return r;
1758 if(f==1.0)
1759 return r|1;
1760 if(f==2.0)
1761 return r|2;
1762 if(f==3.0)
1763 return r|3;
1764 if(f==4.0)
1765 return r|4;
1766 if(f==5.0)
1767 return r|5;
1768 if(f==0.5)
1769 return r|6;
1770 if(f==10.0)
1771 return r|7;
1772 return 0;
1775 /* generate a floating point operation 'v = t1 op t2' instruction. The
1776 two operands are guaranteed to have the same floating point type */
1777 void gen_opf(int op)
1779 uint32_t x, r, r2, c1, c2;
1780 //fputs("gen_opf\n",stderr);
1781 vswap();
1782 c1 = is_fconst();
1783 vswap();
1784 c2 = is_fconst();
1785 x=0xEE000100;
1786 #if LDOUBLE_SIZE == 8
1787 if ((vtop->type.t & VT_BTYPE) != VT_FLOAT)
1788 x|=0x80;
1789 #else
1790 if ((vtop->type.t & VT_BTYPE) == VT_DOUBLE)
1791 x|=0x80;
1792 else if ((vtop->type.t & VT_BTYPE) == VT_LDOUBLE)
1793 x|=0x80000;
1794 #endif
1795 switch(op)
1797 case '+':
1798 if(!c2) {
1799 vswap();
1800 c2=c1;
1802 vswap();
1803 r=fpr(gv(RC_FLOAT));
1804 vswap();
1805 if(c2) {
1806 if(c2>0xf)
1807 x|=0x200000; // suf
1808 r2=c2&0xf;
1809 } else {
1810 r2=fpr(gv(RC_FLOAT));
1812 break;
1813 case '-':
1814 if(c2) {
1815 if(c2<=0xf)
1816 x|=0x200000; // suf
1817 r2=c2&0xf;
1818 vswap();
1819 r=fpr(gv(RC_FLOAT));
1820 vswap();
1821 } else if(c1 && c1<=0xf) {
1822 x|=0x300000; // rsf
1823 r2=c1;
1824 r=fpr(gv(RC_FLOAT));
1825 vswap();
1826 } else {
1827 x|=0x200000; // suf
1828 vswap();
1829 r=fpr(gv(RC_FLOAT));
1830 vswap();
1831 r2=fpr(gv(RC_FLOAT));
1833 break;
1834 case '*':
1835 if(!c2 || c2>0xf) {
1836 vswap();
1837 c2=c1;
1839 vswap();
1840 r=fpr(gv(RC_FLOAT));
1841 vswap();
1842 if(c2 && c2<=0xf)
1843 r2=c2;
1844 else
1845 r2=fpr(gv(RC_FLOAT));
1846 x|=0x100000; // muf
1847 break;
1848 case '/':
1849 if(c2 && c2<=0xf) {
1850 x|=0x400000; // dvf
1851 r2=c2;
1852 vswap();
1853 r=fpr(gv(RC_FLOAT));
1854 vswap();
1855 } else if(c1 && c1<=0xf) {
1856 x|=0x500000; // rdf
1857 r2=c1;
1858 r=fpr(gv(RC_FLOAT));
1859 vswap();
1860 } else {
1861 x|=0x400000; // dvf
1862 vswap();
1863 r=fpr(gv(RC_FLOAT));
1864 vswap();
1865 r2=fpr(gv(RC_FLOAT));
1867 break;
1868 default:
1869 if(op >= TOK_ULT && op <= TOK_GT) {
1870 x|=0xd0f110; // cmfe
1871 /* bug (intention?) in Linux FPU emulator
1872 doesn't set carry if equal */
1873 switch(op) {
1874 case TOK_ULT:
1875 case TOK_UGE:
1876 case TOK_ULE:
1877 case TOK_UGT:
1878 tcc_error("unsigned comparison on floats?");
1879 break;
1880 case TOK_LT:
1881 op=TOK_Nset;
1882 break;
1883 case TOK_LE:
1884 op=TOK_ULE; /* correct in unordered case only if AC bit in FPSR set */
1885 break;
1886 case TOK_EQ:
1887 case TOK_NE:
1888 x&=~0x400000; // cmfe -> cmf
1889 break;
1891 if(c1 && !c2) {
1892 c2=c1;
1893 vswap();
1894 switch(op) {
1895 case TOK_Nset:
1896 op=TOK_GT;
1897 break;
1898 case TOK_GE:
1899 op=TOK_ULE;
1900 break;
1901 case TOK_ULE:
1902 op=TOK_GE;
1903 break;
1904 case TOK_GT:
1905 op=TOK_Nset;
1906 break;
1909 vswap();
1910 r=fpr(gv(RC_FLOAT));
1911 vswap();
1912 if(c2) {
1913 if(c2>0xf)
1914 x|=0x200000;
1915 r2=c2&0xf;
1916 } else {
1917 r2=fpr(gv(RC_FLOAT));
1919 --vtop;
1920 vset_VT_CMP(op);
1921 ++vtop;
1922 } else {
1923 tcc_error("unknown fp op %x!",op);
1924 return;
1927 if(vtop[-1].r == VT_CMP)
1928 c1=15;
1929 else {
1930 c1=vtop->r;
1931 if(r2&0x8)
1932 c1=vtop[-1].r;
1933 vtop[-1].r=get_reg_ex(RC_FLOAT,two2mask(vtop[-1].r,c1));
1934 c1=fpr(vtop[-1].r);
1936 vtop--;
1937 o(x|(r<<16)|(c1<<12)|r2);
1939 #endif
1941 /* convert integers to fp 't' type. Must handle 'int', 'unsigned int'
1942 and 'long long' cases. */
1943 ST_FUNC void gen_cvt_itof1(int t)
1945 uint32_t r, r2;
1946 int bt;
1947 bt=vtop->type.t & VT_BTYPE;
1948 if(bt == VT_INT || bt == VT_SHORT || bt == VT_BYTE) {
1949 #ifndef TCC_ARM_VFP
1950 uint32_t dsize = 0;
1951 #endif
1952 r=intr(gv(RC_INT));
1953 #ifdef TCC_ARM_VFP
1954 r2=vfpr(vtop->r=get_reg(RC_FLOAT));
1955 o(0xEE000A10|(r<<12)|(r2<<16)); /* fmsr */
1956 r2|=r2<<12;
1957 if(!(vtop->type.t & VT_UNSIGNED))
1958 r2|=0x80; /* fuitoX -> fsituX */
1959 o(0xEEB80A40|r2|T2CPR(t)); /* fYitoX*/
1960 #else
1961 r2=fpr(vtop->r=get_reg(RC_FLOAT));
1962 if((t & VT_BTYPE) != VT_FLOAT)
1963 dsize=0x80; /* flts -> fltd */
1964 o(0xEE000110|dsize|(r2<<16)|(r<<12)); /* flts */
1965 if((vtop->type.t & (VT_UNSIGNED|VT_BTYPE)) == (VT_UNSIGNED|VT_INT)) {
1966 uint32_t off = 0;
1967 o(0xE3500000|(r<<12)); /* cmp */
1968 r=fpr(get_reg(RC_FLOAT));
1969 if(last_itod_magic) {
1970 off=ind+8-last_itod_magic;
1971 off/=4;
1972 if(off>255)
1973 off=0;
1975 o(0xBD1F0100|(r<<12)|off); /* ldflts */
1976 if(!off) {
1977 o(0xEA000000); /* b */
1978 last_itod_magic=ind;
1979 o(0x4F800000); /* 4294967296.0f */
1981 o(0xBE000100|dsize|(r2<<16)|(r2<<12)|r); /* adflt */
1983 #endif
1984 return;
1985 } else if(bt == VT_LLONG) {
1986 int func;
1987 CType *func_type = 0;
1988 if((t & VT_BTYPE) == VT_FLOAT) {
1989 func_type = &func_float_type;
1990 if(vtop->type.t & VT_UNSIGNED)
1991 func=TOK___floatundisf;
1992 else
1993 func=TOK___floatdisf;
1994 #if LDOUBLE_SIZE != 8
1995 } else if((t & VT_BTYPE) == VT_LDOUBLE) {
1996 func_type = &func_ldouble_type;
1997 if(vtop->type.t & VT_UNSIGNED)
1998 func=TOK___floatundixf;
1999 else
2000 func=TOK___floatdixf;
2001 } else if((t & VT_BTYPE) == VT_DOUBLE) {
2002 #else
2003 } else if((t & VT_BTYPE) == VT_DOUBLE || (t & VT_BTYPE) == VT_LDOUBLE) {
2004 #endif
2005 func_type = &func_double_type;
2006 if(vtop->type.t & VT_UNSIGNED)
2007 func=TOK___floatundidf;
2008 else
2009 func=TOK___floatdidf;
2011 if(func_type) {
2012 vpush_global_sym(func_type, func);
2013 vswap();
2014 gfunc_call(1);
2015 vpushi(0);
2016 vtop->r=TREG_F0;
2017 return;
2020 tcc_error("unimplemented gen_cvt_itof %x!",vtop->type.t);
2023 /* convert fp to int 't' type */
2024 void gen_cvt_ftoi(int t)
2026 uint32_t r, r2;
2027 int u, func = 0;
2028 u=t&VT_UNSIGNED;
2029 t&=VT_BTYPE;
2030 r2=vtop->type.t & VT_BTYPE;
2031 if(t==VT_INT) {
2032 #ifdef TCC_ARM_VFP
2033 r=vfpr(gv(RC_FLOAT));
2034 u=u?0:0x10000;
2035 o(0xEEBC0AC0|(r<<12)|r|T2CPR(r2)|u); /* ftoXizY */
2036 r2=intr(vtop->r=get_reg(RC_INT));
2037 o(0xEE100A10|(r<<16)|(r2<<12));
2038 return;
2039 #else
2040 if(u) {
2041 if(r2 == VT_FLOAT)
2042 func=TOK___fixunssfsi;
2043 #if LDOUBLE_SIZE != 8
2044 else if(r2 == VT_LDOUBLE)
2045 func=TOK___fixunsxfsi;
2046 else if(r2 == VT_DOUBLE)
2047 #else
2048 else if(r2 == VT_LDOUBLE || r2 == VT_DOUBLE)
2049 #endif
2050 func=TOK___fixunsdfsi;
2051 } else {
2052 r=fpr(gv(RC_FLOAT));
2053 r2=intr(vtop->r=get_reg(RC_INT));
2054 o(0xEE100170|(r2<<12)|r);
2055 return;
2057 #endif
2058 } else if(t == VT_LLONG) { // unsigned handled in gen_cvt_ftoi1
2059 if(r2 == VT_FLOAT)
2060 func=TOK___fixsfdi;
2061 #if LDOUBLE_SIZE != 8
2062 else if(r2 == VT_LDOUBLE)
2063 func=TOK___fixxfdi;
2064 else if(r2 == VT_DOUBLE)
2065 #else
2066 else if(r2 == VT_LDOUBLE || r2 == VT_DOUBLE)
2067 #endif
2068 func=TOK___fixdfdi;
2070 if(func) {
2071 vpush_global_sym(&func_old_type, func);
2072 vswap();
2073 gfunc_call(1);
2074 vpushi(0);
2075 if(t == VT_LLONG)
2076 vtop->r2 = REG_LRET;
2077 vtop->r = REG_IRET;
2078 return;
2080 tcc_error("unimplemented gen_cvt_ftoi!");
2083 /* convert from one floating point type to another */
2084 void gen_cvt_ftof(int t)
2086 #ifdef TCC_ARM_VFP
2087 if(((vtop->type.t & VT_BTYPE) == VT_FLOAT) != ((t & VT_BTYPE) == VT_FLOAT)) {
2088 uint32_t r = vfpr(gv(RC_FLOAT));
2089 o(0xEEB70AC0|(r<<12)|r|T2CPR(vtop->type.t));
2091 #else
2092 /* all we have to do on i386 and FPA ARM is to put the float in a register */
2093 gv(RC_FLOAT);
2094 #endif
2097 /* computed goto support */
2098 void ggoto(void)
2100 gcall_or_jmp(1);
2101 vtop--;
2104 /* Save the stack pointer onto the stack and return the location of its address */
2105 ST_FUNC void gen_vla_sp_save(int addr) {
2106 SValue v;
2107 v.type.t = VT_PTR;
2108 v.r = VT_LOCAL | VT_LVAL;
2109 v.c.i = addr;
2110 store(TREG_SP, &v);
2113 /* Restore the SP from a location on the stack */
2114 ST_FUNC void gen_vla_sp_restore(int addr) {
2115 SValue v;
2116 v.type.t = VT_PTR;
2117 v.r = VT_LOCAL | VT_LVAL;
2118 v.c.i = addr;
2119 load(TREG_SP, &v);
2122 /* Subtract from the stack pointer, and push the resulting value onto the stack */
2123 ST_FUNC void gen_vla_alloc(CType *type, int align) {
2124 int r = intr(gv(RC_INT));
2125 o(0xE04D0000|(r<<12)|r); /* sub r, sp, r */
2126 #ifdef TCC_ARM_EABI
2127 if (align < 8)
2128 align = 8;
2129 #else
2130 if (align < 4)
2131 align = 4;
2132 #endif
2133 if (align & (align - 1))
2134 tcc_error("alignment is not a power of 2: %i", align);
2135 o(stuff_const(0xE3C0D000|(r<<16), align - 1)); /* bic sp, r, #align-1 */
2136 vpop();
2139 /* end of ARM code generator */
2140 /*************************************************************/
2141 #endif
2142 /*************************************************************/