2 * ARMv4 code generator for TCC
4 * Copyright (c) 2003 Daniel Glöckner
6 * Based on i386-gen.c by Fabrice Bellard
8 * This library is free software; you can redistribute it and/or
9 * modify it under the terms of the GNU Lesser General Public
10 * License as published by the Free Software Foundation; either
11 * version 2 of the License, or (at your option) any later version.
13 * This library is distributed in the hope that it will be useful,
14 * but WITHOUT ANY WARRANTY; without even the implied warranty of
15 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
16 * Lesser General Public License for more details.
18 * You should have received a copy of the GNU Lesser General Public
19 * License along with this library; if not, write to the Free Software
20 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
23 #ifdef TARGET_DEFS_ONLY
26 #ifndef TCC_ARM_VFP // Avoid useless warning
31 /* number of available registers */
38 /* a register can belong to several classes. The classes must be
39 sorted from more general to more precise (see gv2() code which does
40 assumptions on it). */
41 #define RC_INT 0x0001 /* generic integer register */
42 #define RC_FLOAT 0x0002 /* generic float register */
58 #define RC_IRET RC_R0 /* function return: integer register */
59 #define RC_LRET RC_R1 /* function return: second integer register */
60 #define RC_FRET RC_F0 /* function return: float register */
62 /* pretty names for the registers */
82 #define T2CPR(t) (((t) & VT_BTYPE) != VT_FLOAT ? 0x100 : 0)
85 /* return registers for function */
86 #define REG_IRET TREG_R0 /* single word int return register */
87 #define REG_LRET TREG_R1 /* second word return register (for long long) */
88 #define REG_FRET TREG_F0 /* float return register */
91 #define TOK___divdi3 TOK___aeabi_ldivmod
92 #define TOK___moddi3 TOK___aeabi_ldivmod
93 #define TOK___udivdi3 TOK___aeabi_uldivmod
94 #define TOK___umoddi3 TOK___aeabi_uldivmod
97 /* defined if function parameters must be evaluated in reverse order */
98 #define INVERT_FUNC_PARAMS
100 /* defined if structures are passed as pointers. Otherwise structures
101 are directly pushed on stack. */
102 //#define FUNC_STRUCT_PARAM_AS_PTR
104 #if defined(TCC_ARM_EABI) && defined(TCC_ARM_VFP)
105 ST_DATA CType float_type
, double_type
, func_float_type
, func_double_type
;
106 #define func_ldouble_type func_double_type
108 #define func_float_type func_old_type
109 #define func_double_type func_old_type
110 #define func_ldouble_type func_old_type
113 /* pointer size, in bytes */
116 /* long double size and alignment, in bytes */
118 #define LDOUBLE_SIZE 8
122 #define LDOUBLE_SIZE 8
126 #define LDOUBLE_ALIGN 8
128 #define LDOUBLE_ALIGN 4
131 /* maximum alignment (for aligned attribute support) */
134 #define CHAR_IS_UNSIGNED
136 /******************************************************/
139 #define EM_TCC_TARGET EM_ARM
141 /* relocation type for 32 bit data relocation */
142 #define R_DATA_32 R_ARM_ABS32
143 #define R_DATA_PTR R_ARM_ABS32
144 #define R_JMP_SLOT R_ARM_JUMP_SLOT
145 #define R_COPY R_ARM_COPY
147 #define ELF_START_ADDR 0x00008000
148 #define ELF_PAGE_SIZE 0x1000
150 /******************************************************/
151 #else /* ! TARGET_DEFS_ONLY */
152 /******************************************************/
155 ST_DATA
const int reg_classes
[NB_REGS
] = {
156 /* r0 */ RC_INT
| RC_R0
,
157 /* r1 */ RC_INT
| RC_R1
,
158 /* r2 */ RC_INT
| RC_R2
,
159 /* r3 */ RC_INT
| RC_R3
,
160 /* r12 */ RC_INT
| RC_R12
,
161 /* f0 */ RC_FLOAT
| RC_F0
,
162 /* f1 */ RC_FLOAT
| RC_F1
,
163 /* f2 */ RC_FLOAT
| RC_F2
,
164 /* f3 */ RC_FLOAT
| RC_F3
,
166 /* d4/s8 */ RC_FLOAT
| RC_F4
,
167 /* d5/s10 */ RC_FLOAT
| RC_F5
,
168 /* d6/s12 */ RC_FLOAT
| RC_F6
,
169 /* d7/s14 */ RC_FLOAT
| RC_F7
,
173 /* keep in sync with line 104 above */
174 #if defined(TCC_ARM_EABI) && defined(TCC_ARM_VFP)
175 ST_DATA CType float_type
, double_type
, func_float_type
, func_double_type
;
178 static int func_sub_sp_offset
, last_itod_magic
;
181 static int two2mask(int a
,int b
) {
182 return (reg_classes
[a
]|reg_classes
[b
])&~(RC_INT
|RC_FLOAT
);
185 static int regmask(int r
) {
186 return reg_classes
[r
]&~(RC_INT
|RC_FLOAT
);
189 /******************************************************/
193 /* this is a good place to start adding big-endian support*/
197 if (!cur_text_section
)
198 tcc_error("compiler error! This happens f.ex. if the compiler\n"
199 "can't evaluate constant expressions outside of a function.");
200 if (ind1
> cur_text_section
->data_allocated
)
201 section_realloc(cur_text_section
, ind1
);
202 cur_text_section
->data
[ind
++] = i
&255;
204 cur_text_section
->data
[ind
++] = i
&255;
206 cur_text_section
->data
[ind
++] = i
&255;
208 cur_text_section
->data
[ind
++] = i
;
211 static uint32_t stuff_const(uint32_t op
, uint32_t c
)
214 uint32_t nc
= 0, negop
= 0;
224 case 0x1A00000: //mov
225 case 0x1E00000: //mvn
232 return (op
&0xF010F000)|((op
>>16)&0xF)|0x1E00000;
236 return (op
&0xF010F000)|((op
>>16)&0xF)|0x1A00000;
237 case 0x1C00000: //bic
242 case 0x1800000: //orr
244 return (op
&0xFFF0FFFF)|0x1E00000;
250 if(c
<256) /* catch undefined <<32 */
253 m
=(0xff>>i
)|(0xff<<(32-i
));
255 return op
|(i
<<7)|(c
<<i
)|(c
>>(32-i
));
265 void stuff_const_harder(uint32_t op
, uint32_t v
) {
271 uint32_t a
[16], nv
, no
, o2
, n2
;
274 o2
=(op
&0xfff0ffff)|((op
&0xf000)<<4);;
276 a
[i
]=(a
[i
-1]>>2)|(a
[i
-1]<<30);
278 for(j
=i
<4?i
+12:15;j
>=i
+4;j
--)
279 if((v
&(a
[i
]|a
[j
]))==v
) {
280 o(stuff_const(op
,v
&a
[i
]));
281 o(stuff_const(o2
,v
&a
[j
]));
288 for(j
=i
<4?i
+12:15;j
>=i
+4;j
--)
289 if((nv
&(a
[i
]|a
[j
]))==nv
) {
290 o(stuff_const(no
,nv
&a
[i
]));
291 o(stuff_const(n2
,nv
&a
[j
]));
296 for(k
=i
<4?i
+12:15;k
>=j
+4;k
--)
297 if((v
&(a
[i
]|a
[j
]|a
[k
]))==v
) {
298 o(stuff_const(op
,v
&a
[i
]));
299 o(stuff_const(o2
,v
&a
[j
]));
300 o(stuff_const(o2
,v
&a
[k
]));
307 for(k
=i
<4?i
+12:15;k
>=j
+4;k
--)
308 if((nv
&(a
[i
]|a
[j
]|a
[k
]))==nv
) {
309 o(stuff_const(no
,nv
&a
[i
]));
310 o(stuff_const(n2
,nv
&a
[j
]));
311 o(stuff_const(n2
,nv
&a
[k
]));
314 o(stuff_const(op
,v
&a
[0]));
315 o(stuff_const(o2
,v
&a
[4]));
316 o(stuff_const(o2
,v
&a
[8]));
317 o(stuff_const(o2
,v
&a
[12]));
321 ST_FUNC
uint32_t encbranch(int pos
, int addr
, int fail
)
325 if(addr
>=0x1000000 || addr
<-0x1000000) {
327 tcc_error("FIXME: function bigger than 32MB");
330 return 0x0A000000|(addr
&0xffffff);
333 int decbranch(int pos
)
336 x
=*(uint32_t *)(cur_text_section
->data
+ pos
);
343 /* output a symbol and patch all calls to it */
344 void gsym_addr(int t
, int a
)
349 x
=(uint32_t *)(cur_text_section
->data
+ t
);
352 *x
=0xE1A00000; // nop
355 *x
|= encbranch(lt
,a
,1);
366 static uint32_t vfpr(int r
)
368 if(r
<TREG_F0
|| r
>TREG_F7
)
369 tcc_error("compiler error! register %i is no vfp register",r
);
373 static uint32_t fpr(int r
)
375 if(r
<TREG_F0
|| r
>TREG_F3
)
376 tcc_error("compiler error! register %i is no fpa register",r
);
381 static uint32_t intr(int r
)
385 if((r
<0 || r
>4) && r
!=14)
386 tcc_error("compiler error! register %i is no int register",r
);
390 static void calcaddr(uint32_t *base
, int *off
, int *sgn
, int maxoff
, unsigned shift
)
392 if(*off
>maxoff
|| *off
&((1<<shift
)-1)) {
399 y
=stuff_const(x
,*off
&~maxoff
);
405 y
=stuff_const(x
,(*off
+maxoff
)&~maxoff
);
409 *off
=((*off
+maxoff
)&~maxoff
)-*off
;
412 stuff_const_harder(x
,*off
&~maxoff
);
417 static uint32_t mapcc(int cc
)
422 return 0x30000000; /* CC/LO */
424 return 0x20000000; /* CS/HS */
426 return 0x00000000; /* EQ */
428 return 0x10000000; /* NE */
430 return 0x90000000; /* LS */
432 return 0x80000000; /* HI */
434 return 0x40000000; /* MI */
436 return 0x50000000; /* PL */
438 return 0xB0000000; /* LT */
440 return 0xA0000000; /* GE */
442 return 0xD0000000; /* LE */
444 return 0xC0000000; /* GT */
446 tcc_error("unexpected condition code");
447 return 0xE0000000; /* AL */
450 static int negcc(int cc
)
479 tcc_error("unexpected condition code");
483 /* load 'r' from value 'sv' */
484 void load(int r
, SValue
*sv
)
486 int v
, ft
, fc
, fr
, sign
;
503 uint32_t base
= 0xB; // fp
506 v1
.r
= VT_LOCAL
| VT_LVAL
;
508 load(base
=14 /* lr */, &v1
);
511 } else if(v
== VT_CONST
) {
519 } else if(v
< VT_CONST
) {
526 calcaddr(&base
,&fc
,&sign
,1020,2);
528 op
=0xED100A00; /* flds */
531 if ((ft
& VT_BTYPE
) != VT_FLOAT
)
532 op
|=0x100; /* flds -> fldd */
533 o(op
|(vfpr(r
)<<12)|(fc
>>2)|(base
<<16));
538 #if LDOUBLE_SIZE == 8
539 if ((ft
& VT_BTYPE
) != VT_FLOAT
)
542 if ((ft
& VT_BTYPE
) == VT_DOUBLE
)
544 else if ((ft
& VT_BTYPE
) == VT_LDOUBLE
)
547 o(op
|(fpr(r
)<<12)|(fc
>>2)|(base
<<16));
549 } else if((ft
& (VT_BTYPE
|VT_UNSIGNED
)) == VT_BYTE
550 || (ft
& VT_BTYPE
) == VT_SHORT
) {
551 calcaddr(&base
,&fc
,&sign
,255,0);
553 if ((ft
& VT_BTYPE
) == VT_SHORT
)
555 if ((ft
& VT_UNSIGNED
) == 0)
559 o(op
|(intr(r
)<<12)|(base
<<16)|((fc
&0xf0)<<4)|(fc
&0xf));
561 calcaddr(&base
,&fc
,&sign
,4095,0);
565 if ((ft
& VT_BTYPE
) == VT_BYTE
)
567 o(op
|(intr(r
)<<12)|fc
|(base
<<16));
573 op
=stuff_const(0xE3A00000|(intr(r
)<<12),sv
->c
.ul
);
574 if (fr
& VT_SYM
|| !op
) {
575 o(0xE59F0000|(intr(r
)<<12));
578 greloc(cur_text_section
, sv
->sym
, ind
, R_ARM_ABS32
);
583 } else if (v
== VT_LOCAL
) {
584 op
=stuff_const(0xE28B0000|(intr(r
)<<12),sv
->c
.ul
);
585 if (fr
& VT_SYM
|| !op
) {
586 o(0xE59F0000|(intr(r
)<<12));
588 if(fr
& VT_SYM
) // needed ?
589 greloc(cur_text_section
, sv
->sym
, ind
, R_ARM_ABS32
);
591 o(0xE08B0000|(intr(r
)<<12)|intr(r
));
595 } else if(v
== VT_CMP
) {
596 o(mapcc(sv
->c
.ul
)|0x3A00001|(intr(r
)<<12));
597 o(mapcc(negcc(sv
->c
.ul
))|0x3A00000|(intr(r
)<<12));
599 } else if (v
== VT_JMP
|| v
== VT_JMPI
) {
602 o(0xE3A00000|(intr(r
)<<12)|t
);
605 o(0xE3A00000|(intr(r
)<<12)|(t
^1));
607 } else if (v
< VT_CONST
) {
610 o(0xEEB00A40|(vfpr(r
)<<12)|vfpr(v
)|T2CPR(ft
)); /* fcpyX */
612 o(0xEE008180|(fpr(r
)<<12)|fpr(v
));
615 o(0xE1A00000|(intr(r
)<<12)|intr(v
));
619 tcc_error("load unimplemented!");
622 /* store register 'r' in lvalue 'v' */
623 void store(int r
, SValue
*sv
)
626 int v
, ft
, fc
, fr
, sign
;
641 if (fr
& VT_LVAL
|| fr
== VT_LOCAL
) {
647 } else if(v
== VT_CONST
) {
658 calcaddr(&base
,&fc
,&sign
,1020,2);
660 op
=0xED000A00; /* fsts */
663 if ((ft
& VT_BTYPE
) != VT_FLOAT
)
664 op
|=0x100; /* fsts -> fstd */
665 o(op
|(vfpr(r
)<<12)|(fc
>>2)|(base
<<16));
670 #if LDOUBLE_SIZE == 8
671 if ((ft
& VT_BTYPE
) != VT_FLOAT
)
674 if ((ft
& VT_BTYPE
) == VT_DOUBLE
)
676 if ((ft
& VT_BTYPE
) == VT_LDOUBLE
)
679 o(op
|(fpr(r
)<<12)|(fc
>>2)|(base
<<16));
682 } else if((ft
& VT_BTYPE
) == VT_SHORT
) {
683 calcaddr(&base
,&fc
,&sign
,255,0);
687 o(op
|(intr(r
)<<12)|(base
<<16)|((fc
&0xf0)<<4)|(fc
&0xf));
689 calcaddr(&base
,&fc
,&sign
,4095,0);
693 if ((ft
& VT_BTYPE
) == VT_BYTE
)
695 o(op
|(intr(r
)<<12)|fc
|(base
<<16));
700 tcc_error("store unimplemented");
703 static void gadd_sp(int val
)
705 stuff_const_harder(0xE28DD000,val
);
708 /* 'is_jmp' is '1' if it is a jump */
709 static void gcall_or_jmp(int is_jmp
)
712 if ((vtop
->r
& (VT_VALMASK
| VT_LVAL
)) == VT_CONST
) {
715 x
=encbranch(ind
,ind
+vtop
->c
.ul
,0);
717 if (vtop
->r
& VT_SYM
) {
718 /* relocation case */
719 greloc(cur_text_section
, vtop
->sym
, ind
, R_ARM_PC24
);
721 put_elf_reloc(symtab_section
, cur_text_section
, ind
, R_ARM_PC24
, 0);
722 o(x
|(is_jmp
?0xE0000000:0xE1000000));
725 o(0xE28FE004); // add lr,pc,#4
726 o(0xE51FF004); // ldr pc,[pc,#-4]
727 if (vtop
->r
& VT_SYM
)
728 greloc(cur_text_section
, vtop
->sym
, ind
, R_ARM_ABS32
);
732 /* otherwise, indirect call */
735 o(0xE1A0E00F); // mov lr,pc
736 o(0xE1A0F000|intr(r
)); // mov pc,r
740 #ifdef TCC_ARM_HARDFLOAT
741 static int is_float_hgen_aggr(CType
*type
)
743 if ((type
->t
& VT_BTYPE
) == VT_STRUCT
) {
745 int btype
, nb_fields
= 0;
748 btype
= ref
->type
.t
& VT_BTYPE
;
749 if (btype
== VT_FLOAT
|| btype
== VT_DOUBLE
) {
750 for(; ref
&& btype
== (ref
->type
.t
& VT_BTYPE
); ref
= ref
->next
, nb_fields
++);
751 return !ref
&& nb_fields
<= 4;
758 /* worst case: f(float, double, 3 float struct, double, 3 float struct, double) */
759 signed char avail
[3];
765 #define AVAIL_REGS_INITIALIZER (struct avail_regs) { { 0, 0, 0}, 0, 0, 0 }
767 /* Assign a register for a CPRC param with correct size and alignment
768 * size and align are in bytes, as returned by type_size */
769 int assign_fpreg(struct avail_regs
*avregs
, int align
, int size
)
773 if (avregs
->first_free_reg
== -1)
775 if (align
>> 3) { // alignment needed (base type: double)
776 first_reg
= avregs
->first_free_reg
;
778 avregs
->avail
[avregs
->last_hole
++] = first_reg
++;
780 if (size
== 4 && avregs
->first_hole
!= avregs
->last_hole
)
781 return avregs
->avail
[avregs
->first_hole
++];
783 first_reg
= avregs
->first_free_reg
;
785 if (first_reg
+ size
/ 4 <= 16) {
786 avregs
->first_free_reg
= first_reg
+ size
/ 4;
789 avregs
->first_free_reg
= -1;
794 /* Generate function call. The function address is pushed first, then
795 all the parameters in call order. This functions pops all the
796 parameters and the function address. */
797 void gfunc_call(int nb_args
)
799 int size
, align
, r
, args_size
, i
, ncrn
, ncprn
, argno
, vfp_argno
;
800 signed char plan
[4][2]={{-1,-1},{-1,-1},{-1,-1},{-1,-1}};
801 SValue
*before_stack
= NULL
; /* SValue before first on stack argument */
802 SValue
*before_vfpreg_hfa
= NULL
; /* SValue before first in VFP reg hfa argument */
803 #ifdef TCC_ARM_HARDFLOAT
804 struct avail_regs avregs
= AVAIL_REGS_INITIALIZER
;
805 signed char vfp_plan
[16];
809 int plan2
[4]={0,0,0,0};
814 #ifdef TCC_ARM_HARDFLOAT
815 memset(vfp_plan
, -1, sizeof(vfp_plan
));
816 memset(plan2
, 0, sizeof(plan2
));
817 variadic
= (vtop
[-nb_args
].type
.ref
->c
== FUNC_ELLIPSIS
);
819 r
= vtop
->r
& VT_VALMASK
;
820 if (r
== VT_CMP
|| (r
& ~1) == VT_JMP
)
823 if((vtop
[-nb_args
].type
.ref
->type
.t
& VT_BTYPE
) == VT_STRUCT
824 && type_size(&vtop
[-nb_args
].type
.ref
->type
, &align
) <= 4) {
827 vtop
[-nb_args
]=vtop
[-nb_args
+1];
828 vtop
[-nb_args
+1]=tmp
;
833 vtop
->type
.t
= VT_LLONG
;
836 ncrn
= ncprn
= argno
= vfp_argno
= 0;
837 /* Assign argument to registers and stack with alignment.
838 If, considering alignment constraints, enough registers of the correct type
839 (core or VFP) are free for the current argument, assign them to it, else
840 allocate on stack with correct alignment. Whenever a structure is allocated
841 in registers or on stack, it is always put on the stack at this stage. The
842 stack is divided in 3 zones. The zone are, from low addresses to high
843 addresses: structures to be loaded in core registers, structures to be
844 loaded in VFP registers, argument allocated to stack. SValue's representing
845 structures in the first zone are moved just after the SValue pointed by
846 before_vfpreg_hfa. SValue's representing structures in the second zone are
847 moved just after the SValue pointer by before_stack. */
848 for(i
= nb_args
+ 1 ; i
-- ;) {
849 int j
, assigned_vfpreg
= 0;
850 size
= type_size(&vtop
[-i
].type
, &align
);
851 switch(vtop
[-i
].type
.t
& VT_BTYPE
) {
856 #ifdef TCC_ARM_HARDFLOAT
858 int hfa
= 0; /* Homogeneous float aggregate */
860 if (is_float(vtop
[-i
].type
.t
)
861 || (hfa
= is_float_hgen_aggr(&vtop
[-i
].type
))) {
864 assigned_vfpreg
= assign_fpreg(&avregs
, align
, size
);
865 end_reg
= assigned_vfpreg
+ (size
- 1) / 4;
866 if (assigned_vfpreg
>= 0) {
867 vfp_plan
[vfp_argno
++]=TREG_F0
+ assigned_vfpreg
/2;
869 /* before_stack can only have been set because all core registers
870 are assigned, so no need to care about before_vfpreg_hfa if
871 before_stack is set */
873 vrote(&vtop
[-i
], &vtop
[-i
] - before_stack
);
875 } else if (!before_vfpreg_hfa
)
876 before_vfpreg_hfa
= &vtop
[-i
-1];
877 for (j
= assigned_vfpreg
; j
<= end_reg
; j
++)
884 /* No need to update before_stack as no more hfa can be allocated in
886 if (!before_vfpreg_hfa
)
887 before_vfpreg_hfa
= &vtop
[-i
-1];
893 ncrn
= (ncrn
+ (align
-1)/4) & -(align
/4);
894 size
= (size
+ 3) & -4;
895 if (ncrn
+ size
/4 <= 4 || (ncrn
< 4 && assigned_vfpreg
!= -1)) {
896 /* Either there is HFA in VFP registers, or there is arguments on stack,
897 it cannot be both. Hence either before_stack already points after
898 the slot where the vtop[-i] SValue is moved, or before_stack will not
900 if (before_vfpreg_hfa
) {
901 vrote(&vtop
[-i
], &vtop
[-i
] - before_vfpreg_hfa
);
904 for (j
= ncrn
; j
< 4 && j
< ncrn
+ size
/ 4; j
++)
908 args_size
= (ncrn
- 4) * 4;
910 before_stack
= &vtop
[-i
-1];
915 /* No need to set before_vfpreg_hfa if not set since there will no
916 longer be any structure assigned to core registers */
918 before_stack
= &vtop
[-i
-1];
927 int is_long
= (vtop
[-i
].type
.t
& VT_BTYPE
) == VT_LLONG
;
930 ncrn
= (ncrn
+ 1) & -2;
936 plan
[argno
++][0]=ncrn
++;
938 plan
[argno
-1][1]=ncrn
++;
945 if(args_size
& (align
-1)) {
947 vtop
->type
.t
= VT_VOID
; /* padding */
954 args_size
+= (size
+ 3) & -4;
957 args_size
= keep
= 0;
958 for(i
= 0;i
< nb_args
; i
++) {
960 if ((vtop
->type
.t
& VT_BTYPE
) == VT_STRUCT
) {
961 size
= type_size(&vtop
->type
, &align
);
962 /* align to stack align size */
963 size
= (size
+ 3) & -4;
964 /* allocate the necessary size on stack */
966 /* generate structure store */
968 o(0xE1A0000D|(intr(r
)<<12));
969 vset(&vtop
->type
, r
| VT_LVAL
, 0);
974 } else if (is_float(vtop
->type
.t
)) {
975 #ifdef TCC_ARM_HARDFLOAT
976 if (!variadic
&& --vfp_argno
<16 && vfp_plan
[vfp_argno
]!=-1) {
977 plan2
[keep
++]=vfp_plan
[vfp_argno
];
982 r
=vfpr(gv(RC_FLOAT
))<<12;
984 if ((vtop
->type
.t
& VT_BTYPE
) != VT_FLOAT
)
987 r
|=0x101; /* fstms -> fstmd */
991 r
=fpr(gv(RC_FLOAT
))<<12;
992 if ((vtop
->type
.t
& VT_BTYPE
) == VT_FLOAT
)
994 else if ((vtop
->type
.t
& VT_BTYPE
) == VT_DOUBLE
)
1004 o(0xED2D0100|r
|(size
>>2));
1010 /* simple type (currently always same size) */
1011 /* XXX: implicit cast ? */
1013 if ((vtop
->type
.t
& VT_BTYPE
) == VT_LLONG
) {
1016 if(--argno
<4 && plan
[argno
][1]!=-1)
1022 o(0xE52D0004|(intr(r
)<<12)); /* str r,[sp,#-4]! */
1032 if(--argno
<4 && plan
[argno
][0]!=-1)
1035 if(vtop
->type
.t
== VT_VOID
) {
1037 o(0xE24DD004); /* sub sp,sp,#4 */
1043 o(0xE52D0004|(intr(r
)<<12)); /* str r,[sp,#-4]! */
1053 for(i
= 0; i
< keep
; i
++) {
1055 gv(regmask(plan2
[i
]));
1056 /* arg is in s(2d+1): plan2[i]<plan2[i+1] => alignment occured (ex f,d,f) */
1057 if (i
< keep
- 1 && is_float(vtop
->type
.t
) && (plan2
[i
] <= plan2
[i
+ 1])) {
1058 o(0xEEF00A40|(vfpr(plan2
[i
])<<12)|vfpr(plan2
[i
]));
1061 save_regs(keep
); /* save used temporary registers */
1067 todo
&=((1<<ncrn
)-1);
1079 args_size
-=nb_regs
*4;
1085 if(vfp_todo
&(1<<i
)) {
1086 o(0xED9D0A00|(i
&1)<<22|(i
>>1)<<12|nb_fregs
);
1088 /* There might be 2 floats in a double VFP reg but that doesn't seem
1091 vtop
->r
=TREG_F0
+i
/2;
1096 gadd_sp(nb_fregs
*4);
1097 args_size
-=nb_fregs
*4;
1105 if((vtop
->type
.ref
->type
.t
& VT_BTYPE
) == VT_STRUCT
1106 && type_size(&vtop
->type
.ref
->type
, &align
) <= 4)
1108 store(REG_IRET
,vtop
-keep
);
1112 #ifdef TCC_ARM_HARDFLOAT
1113 else if(variadic
&& is_float(vtop
->type
.ref
->type
.t
)) {
1115 else if(is_float(vtop
->type
.ref
->type
.t
)) {
1117 if((vtop
->type
.ref
->type
.t
& VT_BTYPE
) == VT_FLOAT
) {
1118 o(0xEE000A10); /* fmsr s0,r0 */
1120 o(0xEE000B10); /* fmdlr d0,r0 */
1121 o(0xEE201B10); /* fmdhr d0,r1 */
1130 /* generate function prolog of type 't' */
1131 void gfunc_prolog(CType
*func_type
)
1134 int n
,nf
,size
,align
, variadic
, struct_ret
= 0;
1135 #ifdef TCC_ARM_HARDFLOAT
1136 struct avail_regs avregs
= AVAIL_REGS_INITIALIZER
;
1139 sym
= func_type
->ref
;
1140 func_vt
= sym
->type
;
1143 variadic
= (func_type
->ref
->c
== FUNC_ELLIPSIS
);
1144 if((func_vt
.t
& VT_BTYPE
) == VT_STRUCT
1145 && type_size(&func_vt
,&align
) > 4)
1150 for(sym2
=sym
->next
;sym2
&& (n
<4 || nf
<16);sym2
=sym2
->next
) {
1151 size
= type_size(&sym2
->type
, &align
);
1152 #ifdef TCC_ARM_HARDFLOAT
1153 if (!variadic
&& (is_float(sym2
->type
.t
)
1154 || is_float_hgen_aggr(&sym2
->type
))) {
1155 int tmpnf
= assign_fpreg(&avregs
, align
, size
) + 1;
1156 nf
= (tmpnf
> nf
) ? tmpnf
: nf
;
1160 n
+= (size
+ 3) / 4;
1164 o(0xE1A0C00D); /* mov ip,sp */
1173 o(0xE92D0000|((1<<n
)-1)); /* save r0-r4 on stack if needed */
1178 nf
=(nf
+1)&-2; /* nf => HARDFLOAT => EABI */
1179 o(0xED2D0A00|nf
); /* save s0-s15 on stack if needed */
1181 o(0xE92D5800); /* save fp, ip, lr */
1182 o(0xE28DB00C); /* add fp, sp, #12 */
1183 func_sub_sp_offset
= ind
;
1184 o(0xE1A00000); /* nop, leave space for stack adjustment in epilogue */
1186 int addr
, pn
= struct_ret
, sn
= 0; /* pn=core, sn=stack */
1188 #ifdef TCC_ARM_HARDFLOAT
1189 avregs
= AVAIL_REGS_INITIALIZER
;
1191 while ((sym
= sym
->next
)) {
1194 size
= type_size(type
, &align
);
1195 size
= (size
+ 3) >> 2;
1196 #ifdef TCC_ARM_HARDFLOAT
1197 if (!variadic
&& (is_float(sym
->type
.t
)
1198 || is_float_hgen_aggr(&sym
->type
))) {
1199 int fpn
= assign_fpreg(&avregs
, align
, size
<< 2);
1208 pn
= (pn
+ (align
-1)/4) & -(align
/4);
1210 addr
= (nf
+ pn
) * 4;
1215 #ifdef TCC_ARM_HARDFLOAT
1219 sn
= (sn
+ (align
-1)/4) & -(align
/4);
1221 addr
= (n
+ nf
+ sn
) * 4;
1224 sym_push(sym
->v
& ~SYM_FIELD
, type
, VT_LOCAL
| lvalue_type(type
->t
), addr
);
1232 /* generate function epilog */
1233 void gfunc_epilog(void)
1238 /* Useless but harmless copy of the float result into main register(s) in case
1239 of variadic function in the hardfloat variant */
1240 if(is_float(func_vt
.t
)) {
1241 if((func_vt
.t
& VT_BTYPE
) == VT_FLOAT
)
1242 o(0xEE100A10); /* fmrs r0, s0 */
1244 o(0xEE100B10); /* fmrdl r0, d0 */
1245 o(0xEE301B10); /* fmrdh r1, d0 */
1249 o(0xE91BA800); /* restore fp, sp, pc */
1250 diff
= (-loc
+ 3) & -4;
1253 diff
= (diff
+ 7) & -8;
1256 x
=stuff_const(0xE24BD000, diff
); /* sub sp,fp,# */
1258 *(uint32_t *)(cur_text_section
->data
+ func_sub_sp_offset
) = x
;
1262 o(0xE59FC004); /* ldr ip,[pc+4] */
1263 o(0xE04BD00C); /* sub sp,fp,ip */
1264 o(0xE1A0F00E); /* mov pc,lr */
1266 *(uint32_t *)(cur_text_section
->data
+ func_sub_sp_offset
) = 0xE1000000|encbranch(func_sub_sp_offset
,addr
,1);
1271 /* generate a jump to a label */
1276 o(0xE0000000|encbranch(r
,t
,1));
1280 /* generate a jump to a fixed address */
1281 void gjmp_addr(int a
)
1286 /* generate a test. set 'inv' to invert test. Stack entry is popped */
1287 int gtst(int inv
, int t
)
1291 v
= vtop
->r
& VT_VALMASK
;
1294 op
=mapcc(inv
?negcc(vtop
->c
.i
):vtop
->c
.i
);
1295 op
|=encbranch(r
,t
,1);
1298 } else if (v
== VT_JMP
|| v
== VT_JMPI
) {
1299 if ((v
& 1) == inv
) {
1308 p
= decbranch(lp
=p
);
1310 x
= (uint32_t *)(cur_text_section
->data
+ lp
);
1312 *x
|= encbranch(lp
,t
,1);
1321 if (is_float(vtop
->type
.t
)) {
1324 o(0xEEB50A40|(vfpr(r
)<<12)|T2CPR(vtop
->type
.t
)); /* fcmpzX */
1325 o(0xEEF1FA10); /* fmstat */
1327 o(0xEE90F118|(fpr(r
)<<16));
1331 return gtst(inv
, t
);
1332 } else if ((vtop
->r
& (VT_VALMASK
| VT_LVAL
| VT_SYM
)) == VT_CONST
) {
1333 /* constant jmp optimization */
1334 if ((vtop
->c
.i
!= 0) != inv
)
1338 o(0xE3300000|(intr(v
)<<16));
1341 return gtst(inv
, t
);
1348 /* generate an integer binary operation */
1349 void gen_opi(int op
)
1352 uint32_t opc
= 0, r
, fr
;
1353 unsigned short retreg
= REG_IRET
;
1361 case TOK_ADDC1
: /* add with carry generation */
1369 case TOK_SUBC1
: /* sub with carry generation */
1373 case TOK_ADDC2
: /* add with carry use */
1377 case TOK_SUBC2
: /* sub with carry use */
1394 gv2(RC_INT
, RC_INT
);
1398 o(0xE0000090|(intr(r
)<<16)|(intr(r
)<<8)|intr(fr
));
1423 func
=TOK___aeabi_idivmod
;
1432 func
=TOK___aeabi_uidivmod
;
1440 gv2(RC_INT
, RC_INT
);
1441 r
=intr(vtop
[-1].r2
=get_reg(RC_INT
));
1443 vtop
[-1].r
=get_reg_ex(RC_INT
,regmask(c
));
1445 o(0xE0800090|(r
<<16)|(intr(vtop
->r
)<<12)|(intr(c
)<<8)|intr(vtop
[1].r
));
1454 if((vtop
[-1].r
& (VT_VALMASK
| VT_LVAL
| VT_SYM
)) == VT_CONST
) {
1455 if(opc
== 4 || opc
== 5 || opc
== 0xc) {
1457 opc
|=2; // sub -> rsb
1460 if ((vtop
->r
& VT_VALMASK
) == VT_CMP
||
1461 (vtop
->r
& (VT_VALMASK
& ~1)) == VT_JMP
)
1466 opc
=0xE0000000|(opc
<<20)|(c
<<16);
1467 if((vtop
->r
& (VT_VALMASK
| VT_LVAL
| VT_SYM
)) == VT_CONST
) {
1469 x
=stuff_const(opc
|0x2000000,vtop
->c
.i
);
1471 r
=intr(vtop
[-1].r
=get_reg_ex(RC_INT
,regmask(vtop
[-1].r
)));
1476 fr
=intr(gv(RC_INT
));
1477 r
=intr(vtop
[-1].r
=get_reg_ex(RC_INT
,two2mask(vtop
->r
,vtop
[-1].r
)));
1481 if (op
>= TOK_ULT
&& op
<= TOK_GT
) {
1487 opc
=0xE1A00000|(opc
<<5);
1488 if ((vtop
->r
& VT_VALMASK
) == VT_CMP
||
1489 (vtop
->r
& (VT_VALMASK
& ~1)) == VT_JMP
)
1495 if ((vtop
->r
& (VT_VALMASK
| VT_LVAL
| VT_SYM
)) == VT_CONST
) {
1496 fr
=intr(vtop
[-1].r
=get_reg_ex(RC_INT
,regmask(vtop
[-1].r
)));
1497 c
= vtop
->c
.i
& 0x1f;
1498 o(opc
|(c
<<7)|(fr
<<12));
1500 fr
=intr(gv(RC_INT
));
1501 c
=intr(vtop
[-1].r
=get_reg_ex(RC_INT
,two2mask(vtop
->r
,vtop
[-1].r
)));
1502 o(opc
|(c
<<12)|(fr
<<8)|0x10);
1507 vpush_global_sym(&func_old_type
, func
);
1514 tcc_error("gen_opi %i unimplemented!",op
);
1519 static int is_zero(int i
)
1521 if((vtop
[i
].r
& (VT_VALMASK
| VT_LVAL
| VT_SYM
)) != VT_CONST
)
1523 if (vtop
[i
].type
.t
== VT_FLOAT
)
1524 return (vtop
[i
].c
.f
== 0.f
);
1525 else if (vtop
[i
].type
.t
== VT_DOUBLE
)
1526 return (vtop
[i
].c
.d
== 0.0);
1527 return (vtop
[i
].c
.ld
== 0.l
);
1530 /* generate a floating point operation 'v = t1 op t2' instruction. The
1531 * two operands are guaranted to have the same floating point type */
1532 void gen_opf(int op
)
1536 x
=0xEE000A00|T2CPR(vtop
->type
.t
);
1554 x
|=0x810000; /* fsubX -> fnegX */
1567 if(op
< TOK_ULT
&& op
> TOK_GT
) {
1568 tcc_error("unknown fp op %x!",op
);
1574 case TOK_LT
: op
=TOK_GT
; break;
1575 case TOK_GE
: op
=TOK_ULE
; break;
1576 case TOK_LE
: op
=TOK_GE
; break;
1577 case TOK_GT
: op
=TOK_ULT
; break;
1580 x
|=0xB40040; /* fcmpX */
1581 if(op
!=TOK_EQ
&& op
!=TOK_NE
)
1582 x
|=0x80; /* fcmpX -> fcmpeX */
1585 o(x
|0x10000|(vfpr(gv(RC_FLOAT
))<<12)); /* fcmp(e)X -> fcmp(e)zX */
1587 x
|=vfpr(gv(RC_FLOAT
));
1589 o(x
|(vfpr(gv(RC_FLOAT
))<<12));
1592 o(0xEEF1FA10); /* fmstat */
1595 case TOK_LE
: op
=TOK_ULE
; break;
1596 case TOK_LT
: op
=TOK_ULT
; break;
1597 case TOK_UGE
: op
=TOK_GE
; break;
1598 case TOK_UGT
: op
=TOK_GT
; break;
1615 vtop
->r
=get_reg_ex(RC_FLOAT
,r
);
1618 o(x
|(vfpr(vtop
->r
)<<12));
1622 static uint32_t is_fconst()
1626 if((vtop
->r
& (VT_VALMASK
| VT_LVAL
| VT_SYM
)) != VT_CONST
)
1628 if (vtop
->type
.t
== VT_FLOAT
)
1630 else if (vtop
->type
.t
== VT_DOUBLE
)
1660 /* generate a floating point operation 'v = t1 op t2' instruction. The
1661 two operands are guaranted to have the same floating point type */
1662 void gen_opf(int op
)
1664 uint32_t x
, r
, r2
, c1
, c2
;
1665 //fputs("gen_opf\n",stderr);
1671 #if LDOUBLE_SIZE == 8
1672 if ((vtop
->type
.t
& VT_BTYPE
) != VT_FLOAT
)
1675 if ((vtop
->type
.t
& VT_BTYPE
) == VT_DOUBLE
)
1677 else if ((vtop
->type
.t
& VT_BTYPE
) == VT_LDOUBLE
)
1688 r
=fpr(gv(RC_FLOAT
));
1695 r2
=fpr(gv(RC_FLOAT
));
1704 r
=fpr(gv(RC_FLOAT
));
1706 } else if(c1
&& c1
<=0xf) {
1709 r
=fpr(gv(RC_FLOAT
));
1714 r
=fpr(gv(RC_FLOAT
));
1716 r2
=fpr(gv(RC_FLOAT
));
1725 r
=fpr(gv(RC_FLOAT
));
1730 r2
=fpr(gv(RC_FLOAT
));
1738 r
=fpr(gv(RC_FLOAT
));
1740 } else if(c1
&& c1
<=0xf) {
1743 r
=fpr(gv(RC_FLOAT
));
1748 r
=fpr(gv(RC_FLOAT
));
1750 r2
=fpr(gv(RC_FLOAT
));
1754 if(op
>= TOK_ULT
&& op
<= TOK_GT
) {
1755 x
|=0xd0f110; // cmfe
1756 /* bug (intention?) in Linux FPU emulator
1757 doesn't set carry if equal */
1763 tcc_error("unsigned comparision on floats?");
1769 op
=TOK_ULE
; /* correct in unordered case only if AC bit in FPSR set */
1773 x
&=~0x400000; // cmfe -> cmf
1795 r
=fpr(gv(RC_FLOAT
));
1802 r2
=fpr(gv(RC_FLOAT
));
1804 vtop
[-1].r
= VT_CMP
;
1807 tcc_error("unknown fp op %x!",op
);
1811 if(vtop
[-1].r
== VT_CMP
)
1817 vtop
[-1].r
=get_reg_ex(RC_FLOAT
,two2mask(vtop
[-1].r
,c1
));
1821 o(x
|(r
<<16)|(c1
<<12)|r2
);
1825 /* convert integers to fp 't' type. Must handle 'int', 'unsigned int'
1826 and 'long long' cases. */
1827 ST_FUNC
void gen_cvt_itof1(int t
)
1831 bt
=vtop
->type
.t
& VT_BTYPE
;
1832 if(bt
== VT_INT
|| bt
== VT_SHORT
|| bt
== VT_BYTE
) {
1838 r2
=vfpr(vtop
->r
=get_reg(RC_FLOAT
));
1839 o(0xEE000A10|(r
<<12)|(r2
<<16)); /* fmsr */
1841 if(!(vtop
->type
.t
& VT_UNSIGNED
))
1842 r2
|=0x80; /* fuitoX -> fsituX */
1843 o(0xEEB80A40|r2
|T2CPR(t
)); /* fYitoX*/
1845 r2
=fpr(vtop
->r
=get_reg(RC_FLOAT
));
1846 if((t
& VT_BTYPE
) != VT_FLOAT
)
1847 dsize
=0x80; /* flts -> fltd */
1848 o(0xEE000110|dsize
|(r2
<<16)|(r
<<12)); /* flts */
1849 if((vtop
->type
.t
& (VT_UNSIGNED
|VT_BTYPE
)) == (VT_UNSIGNED
|VT_INT
)) {
1851 o(0xE3500000|(r
<<12)); /* cmp */
1852 r
=fpr(get_reg(RC_FLOAT
));
1853 if(last_itod_magic
) {
1854 off
=ind
+8-last_itod_magic
;
1859 o(0xBD1F0100|(r
<<12)|off
); /* ldflts */
1861 o(0xEA000000); /* b */
1862 last_itod_magic
=ind
;
1863 o(0x4F800000); /* 4294967296.0f */
1865 o(0xBE000100|dsize
|(r2
<<16)|(r2
<<12)|r
); /* adflt */
1869 } else if(bt
== VT_LLONG
) {
1871 CType
*func_type
= 0;
1872 if((t
& VT_BTYPE
) == VT_FLOAT
) {
1873 func_type
= &func_float_type
;
1874 if(vtop
->type
.t
& VT_UNSIGNED
)
1875 func
=TOK___floatundisf
;
1877 func
=TOK___floatdisf
;
1878 #if LDOUBLE_SIZE != 8
1879 } else if((t
& VT_BTYPE
) == VT_LDOUBLE
) {
1880 func_type
= &func_ldouble_type
;
1881 if(vtop
->type
.t
& VT_UNSIGNED
)
1882 func
=TOK___floatundixf
;
1884 func
=TOK___floatdixf
;
1885 } else if((t
& VT_BTYPE
) == VT_DOUBLE
) {
1887 } else if((t
& VT_BTYPE
) == VT_DOUBLE
|| (t
& VT_BTYPE
) == VT_LDOUBLE
) {
1889 func_type
= &func_double_type
;
1890 if(vtop
->type
.t
& VT_UNSIGNED
)
1891 func
=TOK___floatundidf
;
1893 func
=TOK___floatdidf
;
1896 vpush_global_sym(func_type
, func
);
1904 tcc_error("unimplemented gen_cvt_itof %x!",vtop
->type
.t
);
1907 /* convert fp to int 't' type */
1908 void gen_cvt_ftoi(int t
)
1914 r2
=vtop
->type
.t
& VT_BTYPE
;
1917 r
=vfpr(gv(RC_FLOAT
));
1919 o(0xEEBC0A40|(r
<<12)|r
|T2CPR(r2
)); /* ftoXiY */
1920 r2
=intr(vtop
->r
=get_reg(RC_INT
));
1921 o(0xEE100A10|(r
<<16)|(r2
<<12));
1926 func
=TOK___fixunssfsi
;
1927 #if LDOUBLE_SIZE != 8
1928 else if(r2
== VT_LDOUBLE
)
1929 func
=TOK___fixunsxfsi
;
1930 else if(r2
== VT_DOUBLE
)
1932 else if(r2
== VT_LDOUBLE
|| r2
== VT_DOUBLE
)
1934 func
=TOK___fixunsdfsi
;
1936 r
=fpr(gv(RC_FLOAT
));
1937 r2
=intr(vtop
->r
=get_reg(RC_INT
));
1938 o(0xEE100170|(r2
<<12)|r
);
1942 } else if(t
== VT_LLONG
) { // unsigned handled in gen_cvt_ftoi1
1945 #if LDOUBLE_SIZE != 8
1946 else if(r2
== VT_LDOUBLE
)
1948 else if(r2
== VT_DOUBLE
)
1950 else if(r2
== VT_LDOUBLE
|| r2
== VT_DOUBLE
)
1955 vpush_global_sym(&func_old_type
, func
);
1960 vtop
->r2
= REG_LRET
;
1964 tcc_error("unimplemented gen_cvt_ftoi!");
1967 /* convert from one floating point type to another */
1968 void gen_cvt_ftof(int t
)
1971 if(((vtop
->type
.t
& VT_BTYPE
) == VT_FLOAT
) != ((t
& VT_BTYPE
) == VT_FLOAT
)) {
1972 uint32_t r
= vfpr(gv(RC_FLOAT
));
1973 o(0xEEB70AC0|(r
<<12)|r
|T2CPR(vtop
->type
.t
));
1976 /* all we have to do on i386 and FPA ARM is to put the float in a register */
1981 /* computed goto support */
1988 /* end of ARM code generator */
1989 /*************************************************************/
1991 /*************************************************************/