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
27 #ifndef TCC_ARM_VFP /* Avoid useless warning */
32 /* number of available registers */
39 #ifndef TCC_ARM_VERSION
40 # define TCC_ARM_VERSION 5
43 /* a register can belong to several classes. The classes must be
44 sorted from more general to more precise (see gv2() code which does
45 assumptions on it). */
46 #define RC_INT 0x0001 /* generic integer register */
47 #define RC_FLOAT 0x0002 /* generic float register */
63 #define RC_IRET RC_R0 /* function return: integer register */
64 #define RC_LRET RC_R1 /* function return: second integer register */
65 #define RC_FRET RC_F0 /* function return: float register */
67 /* pretty names for the registers */
87 #define T2CPR(t) (((t) & VT_BTYPE) != VT_FLOAT ? 0x100 : 0)
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 */
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
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 */
112 /* long double size and alignment, in bytes */
114 #define LDOUBLE_SIZE 8
118 #define LDOUBLE_SIZE 8
122 #define LDOUBLE_ALIGN 8
124 #define LDOUBLE_ALIGN 4
127 /* maximum alignment (for aligned attribute support) */
130 #define CHAR_IS_UNSIGNED
132 /******************************************************/
135 #define EM_TCC_TARGET EM_ARM
137 /* relocation type for 32 bit data relocation */
138 #define R_DATA_32 R_ARM_ABS32
139 #define R_DATA_PTR R_ARM_ABS32
140 #define R_JMP_SLOT R_ARM_JUMP_SLOT
141 #define R_COPY R_ARM_COPY
143 #define ELF_START_ADDR 0x00008000
144 #define ELF_PAGE_SIZE 0x1000
146 /******************************************************/
147 #else /* ! TARGET_DEFS_ONLY */
148 /******************************************************/
151 ST_DATA
const int reg_classes
[NB_REGS
] = {
152 /* r0 */ RC_INT
| RC_R0
,
153 /* r1 */ RC_INT
| RC_R1
,
154 /* r2 */ RC_INT
| RC_R2
,
155 /* r3 */ RC_INT
| RC_R3
,
156 /* r12 */ RC_INT
| RC_R12
,
157 /* f0 */ RC_FLOAT
| RC_F0
,
158 /* f1 */ RC_FLOAT
| RC_F1
,
159 /* f2 */ RC_FLOAT
| RC_F2
,
160 /* f3 */ RC_FLOAT
| RC_F3
,
162 /* d4/s8 */ RC_FLOAT
| RC_F4
,
163 /* d5/s10 */ RC_FLOAT
| RC_F5
,
164 /* d6/s12 */ RC_FLOAT
| RC_F6
,
165 /* d7/s14 */ RC_FLOAT
| RC_F7
,
169 static int func_sub_sp_offset
, last_itod_magic
;
172 #if defined(TCC_ARM_EABI) && defined(TCC_ARM_VFP)
173 static CType float_type
, double_type
, func_float_type
, func_double_type
;
174 ST_FUNC
void arm_init_types(void)
176 float_type
.t
= VT_FLOAT
;
177 double_type
.t
= VT_DOUBLE
;
178 func_float_type
.t
= VT_FUNC
;
179 func_float_type
.ref
= sym_push(SYM_FIELD
, &float_type
, FUNC_CDECL
, FUNC_OLD
);
180 func_double_type
.t
= VT_FUNC
;
181 func_double_type
.ref
= sym_push(SYM_FIELD
, &double_type
, FUNC_CDECL
, FUNC_OLD
);
184 #define func_float_type func_old_type
185 #define func_double_type func_old_type
186 #define func_ldouble_type func_old_type
187 ST_FUNC
void arm_init_types(void) {}
190 static int two2mask(int a
,int b
) {
191 return (reg_classes
[a
]|reg_classes
[b
])&~(RC_INT
|RC_FLOAT
);
194 static int regmask(int r
) {
195 return reg_classes
[r
]&~(RC_INT
|RC_FLOAT
);
198 /******************************************************/
202 /* this is a good place to start adding big-endian support*/
206 if (!cur_text_section
)
207 tcc_error("compiler error! This happens f.ex. if the compiler\n"
208 "can't evaluate constant expressions outside of a function.");
209 if (ind1
> cur_text_section
->data_allocated
)
210 section_realloc(cur_text_section
, ind1
);
211 cur_text_section
->data
[ind
++] = i
&255;
213 cur_text_section
->data
[ind
++] = i
&255;
215 cur_text_section
->data
[ind
++] = i
&255;
217 cur_text_section
->data
[ind
++] = i
;
220 static uint32_t stuff_const(uint32_t op
, uint32_t c
)
223 uint32_t nc
= 0, negop
= 0;
233 case 0x1A00000: //mov
234 case 0x1E00000: //mvn
241 return (op
&0xF010F000)|((op
>>16)&0xF)|0x1E00000;
245 return (op
&0xF010F000)|((op
>>16)&0xF)|0x1A00000;
246 case 0x1C00000: //bic
251 case 0x1800000: //orr
253 return (op
&0xFFF0FFFF)|0x1E00000;
259 if(c
<256) /* catch undefined <<32 */
262 m
=(0xff>>i
)|(0xff<<(32-i
));
264 return op
|(i
<<7)|(c
<<i
)|(c
>>(32-i
));
274 void stuff_const_harder(uint32_t op
, uint32_t v
) {
280 uint32_t a
[16], nv
, no
, o2
, n2
;
283 o2
=(op
&0xfff0ffff)|((op
&0xf000)<<4);;
285 a
[i
]=(a
[i
-1]>>2)|(a
[i
-1]<<30);
287 for(j
=i
<4?i
+12:15;j
>=i
+4;j
--)
288 if((v
&(a
[i
]|a
[j
]))==v
) {
289 o(stuff_const(op
,v
&a
[i
]));
290 o(stuff_const(o2
,v
&a
[j
]));
297 for(j
=i
<4?i
+12:15;j
>=i
+4;j
--)
298 if((nv
&(a
[i
]|a
[j
]))==nv
) {
299 o(stuff_const(no
,nv
&a
[i
]));
300 o(stuff_const(n2
,nv
&a
[j
]));
305 for(k
=i
<4?i
+12:15;k
>=j
+4;k
--)
306 if((v
&(a
[i
]|a
[j
]|a
[k
]))==v
) {
307 o(stuff_const(op
,v
&a
[i
]));
308 o(stuff_const(o2
,v
&a
[j
]));
309 o(stuff_const(o2
,v
&a
[k
]));
316 for(k
=i
<4?i
+12:15;k
>=j
+4;k
--)
317 if((nv
&(a
[i
]|a
[j
]|a
[k
]))==nv
) {
318 o(stuff_const(no
,nv
&a
[i
]));
319 o(stuff_const(n2
,nv
&a
[j
]));
320 o(stuff_const(n2
,nv
&a
[k
]));
323 o(stuff_const(op
,v
&a
[0]));
324 o(stuff_const(o2
,v
&a
[4]));
325 o(stuff_const(o2
,v
&a
[8]));
326 o(stuff_const(o2
,v
&a
[12]));
330 ST_FUNC
uint32_t encbranch(int pos
, int addr
, int fail
)
334 if(addr
>=0x1000000 || addr
<-0x1000000) {
336 tcc_error("FIXME: function bigger than 32MB");
339 return 0x0A000000|(addr
&0xffffff);
342 int decbranch(int pos
)
345 x
=*(uint32_t *)(cur_text_section
->data
+ pos
);
352 /* output a symbol and patch all calls to it */
353 void gsym_addr(int t
, int a
)
358 x
=(uint32_t *)(cur_text_section
->data
+ t
);
361 *x
=0xE1A00000; // nop
364 *x
|= encbranch(lt
,a
,1);
375 static uint32_t vfpr(int r
)
377 if(r
<TREG_F0
|| r
>TREG_F7
)
378 tcc_error("compiler error! register %i is no vfp register",r
);
382 static uint32_t fpr(int r
)
384 if(r
<TREG_F0
|| r
>TREG_F3
)
385 tcc_error("compiler error! register %i is no fpa register",r
);
390 static uint32_t intr(int r
)
394 if((r
<0 || r
>4) && r
!=14)
395 tcc_error("compiler error! register %i is no int register",r
);
399 static void calcaddr(uint32_t *base
, int *off
, int *sgn
, int maxoff
, unsigned shift
)
401 if(*off
>maxoff
|| *off
&((1<<shift
)-1)) {
408 y
=stuff_const(x
,*off
&~maxoff
);
414 y
=stuff_const(x
,(*off
+maxoff
)&~maxoff
);
418 *off
=((*off
+maxoff
)&~maxoff
)-*off
;
421 stuff_const_harder(x
,*off
&~maxoff
);
426 static uint32_t mapcc(int cc
)
431 return 0x30000000; /* CC/LO */
433 return 0x20000000; /* CS/HS */
435 return 0x00000000; /* EQ */
437 return 0x10000000; /* NE */
439 return 0x90000000; /* LS */
441 return 0x80000000; /* HI */
443 return 0x40000000; /* MI */
445 return 0x50000000; /* PL */
447 return 0xB0000000; /* LT */
449 return 0xA0000000; /* GE */
451 return 0xD0000000; /* LE */
453 return 0xC0000000; /* GT */
455 tcc_error("unexpected condition code");
456 return 0xE0000000; /* AL */
459 static int negcc(int cc
)
488 tcc_error("unexpected condition code");
492 /* load 'r' from value 'sv' */
493 void load(int r
, SValue
*sv
)
495 int v
, ft
, fc
, fr
, sign
;
512 uint32_t base
= 0xB; // fp
515 v1
.r
= VT_LOCAL
| VT_LVAL
;
517 load(base
=14 /* lr */, &v1
);
520 } else if(v
== VT_CONST
) {
528 } else if(v
< VT_CONST
) {
535 calcaddr(&base
,&fc
,&sign
,1020,2);
537 op
=0xED100A00; /* flds */
540 if ((ft
& VT_BTYPE
) != VT_FLOAT
)
541 op
|=0x100; /* flds -> fldd */
542 o(op
|(vfpr(r
)<<12)|(fc
>>2)|(base
<<16));
547 #if LDOUBLE_SIZE == 8
548 if ((ft
& VT_BTYPE
) != VT_FLOAT
)
551 if ((ft
& VT_BTYPE
) == VT_DOUBLE
)
553 else if ((ft
& VT_BTYPE
) == VT_LDOUBLE
)
556 o(op
|(fpr(r
)<<12)|(fc
>>2)|(base
<<16));
558 } else if((ft
& (VT_BTYPE
|VT_UNSIGNED
)) == VT_BYTE
559 || (ft
& VT_BTYPE
) == VT_SHORT
) {
560 calcaddr(&base
,&fc
,&sign
,255,0);
562 if ((ft
& VT_BTYPE
) == VT_SHORT
)
564 if ((ft
& VT_UNSIGNED
) == 0)
568 o(op
|(intr(r
)<<12)|(base
<<16)|((fc
&0xf0)<<4)|(fc
&0xf));
570 calcaddr(&base
,&fc
,&sign
,4095,0);
574 if ((ft
& VT_BTYPE
) == VT_BYTE
|| (ft
& VT_BTYPE
) == VT_BOOL
)
576 o(op
|(intr(r
)<<12)|fc
|(base
<<16));
582 op
=stuff_const(0xE3A00000|(intr(r
)<<12),sv
->c
.ul
);
583 if (fr
& VT_SYM
|| !op
) {
584 o(0xE59F0000|(intr(r
)<<12));
587 greloc(cur_text_section
, sv
->sym
, ind
, R_ARM_ABS32
);
592 } else if (v
== VT_LOCAL
) {
593 op
=stuff_const(0xE28B0000|(intr(r
)<<12),sv
->c
.ul
);
594 if (fr
& VT_SYM
|| !op
) {
595 o(0xE59F0000|(intr(r
)<<12));
597 if(fr
& VT_SYM
) // needed ?
598 greloc(cur_text_section
, sv
->sym
, ind
, R_ARM_ABS32
);
600 o(0xE08B0000|(intr(r
)<<12)|intr(r
));
604 } else if(v
== VT_CMP
) {
605 o(mapcc(sv
->c
.ul
)|0x3A00001|(intr(r
)<<12));
606 o(mapcc(negcc(sv
->c
.ul
))|0x3A00000|(intr(r
)<<12));
608 } else if (v
== VT_JMP
|| v
== VT_JMPI
) {
611 o(0xE3A00000|(intr(r
)<<12)|t
);
614 o(0xE3A00000|(intr(r
)<<12)|(t
^1));
616 } else if (v
< VT_CONST
) {
619 o(0xEEB00A40|(vfpr(r
)<<12)|vfpr(v
)|T2CPR(ft
)); /* fcpyX */
621 o(0xEE008180|(fpr(r
)<<12)|fpr(v
));
624 o(0xE1A00000|(intr(r
)<<12)|intr(v
));
628 tcc_error("load unimplemented!");
631 /* store register 'r' in lvalue 'v' */
632 void store(int r
, SValue
*sv
)
635 int v
, ft
, fc
, fr
, sign
;
650 if (fr
& VT_LVAL
|| fr
== VT_LOCAL
) {
656 } else if(v
== VT_CONST
) {
667 calcaddr(&base
,&fc
,&sign
,1020,2);
669 op
=0xED000A00; /* fsts */
672 if ((ft
& VT_BTYPE
) != VT_FLOAT
)
673 op
|=0x100; /* fsts -> fstd */
674 o(op
|(vfpr(r
)<<12)|(fc
>>2)|(base
<<16));
679 #if LDOUBLE_SIZE == 8
680 if ((ft
& VT_BTYPE
) != VT_FLOAT
)
683 if ((ft
& VT_BTYPE
) == VT_DOUBLE
)
685 if ((ft
& VT_BTYPE
) == VT_LDOUBLE
)
688 o(op
|(fpr(r
)<<12)|(fc
>>2)|(base
<<16));
691 } else if((ft
& VT_BTYPE
) == VT_SHORT
) {
692 calcaddr(&base
,&fc
,&sign
,255,0);
696 o(op
|(intr(r
)<<12)|(base
<<16)|((fc
&0xf0)<<4)|(fc
&0xf));
698 calcaddr(&base
,&fc
,&sign
,4095,0);
702 if ((ft
& VT_BTYPE
) == VT_BYTE
|| (ft
& VT_BTYPE
) == VT_BOOL
)
704 o(op
|(intr(r
)<<12)|fc
|(base
<<16));
709 tcc_error("store unimplemented");
712 static void gadd_sp(int val
)
714 stuff_const_harder(0xE28DD000,val
);
717 /* 'is_jmp' is '1' if it is a jump */
718 static void gcall_or_jmp(int is_jmp
)
721 if ((vtop
->r
& (VT_VALMASK
| VT_LVAL
)) == VT_CONST
) {
724 x
=encbranch(ind
,ind
+vtop
->c
.ul
,0);
726 if (vtop
->r
& VT_SYM
) {
727 /* relocation case */
728 greloc(cur_text_section
, vtop
->sym
, ind
, R_ARM_PC24
);
730 put_elf_reloc(symtab_section
, cur_text_section
, ind
, R_ARM_PC24
, 0);
731 o(x
|(is_jmp
?0xE0000000:0xE1000000));
734 o(0xE28FE004); // add lr,pc,#4
735 o(0xE51FF004); // ldr pc,[pc,#-4]
736 if (vtop
->r
& VT_SYM
)
737 greloc(cur_text_section
, vtop
->sym
, ind
, R_ARM_ABS32
);
741 /* otherwise, indirect call */
744 o(0xE1A0E00F); // mov lr,pc
745 o(0xE1A0F000|intr(r
)); // mov pc,r
749 #ifdef TCC_ARM_HARDFLOAT
750 static int is_float_hgen_aggr(CType
*type
)
752 if ((type
->t
& VT_BTYPE
) == VT_STRUCT
) {
754 int btype
, nb_fields
= 0;
757 btype
= ref
->type
.t
& VT_BTYPE
;
758 if (btype
== VT_FLOAT
|| btype
== VT_DOUBLE
) {
759 for(; ref
&& btype
== (ref
->type
.t
& VT_BTYPE
); ref
= ref
->next
, nb_fields
++);
760 return !ref
&& nb_fields
<= 4;
767 /* worst case: f(float, double, 3 float struct, double, 3 float struct, double) */
768 signed char avail
[3];
774 #define AVAIL_REGS_INITIALIZER (struct avail_regs) { { 0, 0, 0}, 0, 0, 0 }
776 /* Assign a register for a CPRC param with correct size and alignment
777 * size and align are in bytes, as returned by type_size */
778 int assign_fpreg(struct avail_regs
*avregs
, int align
, int size
)
782 if (avregs
->first_free_reg
== -1)
784 if (align
>> 3) { // alignment needed (base type: double)
785 first_reg
= avregs
->first_free_reg
;
787 avregs
->avail
[avregs
->last_hole
++] = first_reg
++;
789 if (size
== 4 && avregs
->first_hole
!= avregs
->last_hole
)
790 return avregs
->avail
[avregs
->first_hole
++];
792 first_reg
= avregs
->first_free_reg
;
794 if (first_reg
+ size
/ 4 <= 16) {
795 avregs
->first_free_reg
= first_reg
+ size
/ 4;
798 avregs
->first_free_reg
= -1;
803 /* Return 1 if this function returns via an sret pointer, 0 otherwise */
804 ST_FUNC
int gfunc_sret(CType
*vt
, CType
*ret
, int *ret_align
) {
807 size
= type_size(vt
, &align
);
821 /* Generate function call. The function address is pushed first, then
822 all the parameters in call order. This functions pops all the
823 parameters and the function address. */
824 void gfunc_call(int nb_args
)
826 int size
, align
, r
, args_size
, i
, ncrn
, ncprn
, argno
, vfp_argno
;
827 signed char plan
[4][2]={{-1,-1},{-1,-1},{-1,-1},{-1,-1}};
828 SValue
*before_stack
= NULL
; /* SValue before first on stack argument */
829 SValue
*before_creg
= NULL
; /* SValue before first argument of type struct in core register */
830 #ifdef TCC_ARM_HARDFLOAT
831 struct avail_regs avregs
= AVAIL_REGS_INITIALIZER
;
832 signed char vfp_plan
[16];
836 int plan2
[4]={0,0,0,0};
841 #ifdef TCC_ARM_HARDFLOAT
842 memset(vfp_plan
, -1, sizeof(vfp_plan
));
843 memset(plan2
, 0, sizeof(plan2
));
844 variadic
= (vtop
[-nb_args
].type
.ref
->c
== FUNC_ELLIPSIS
);
846 r
= vtop
->r
& VT_VALMASK
;
847 if (r
== VT_CMP
|| (r
& ~1) == VT_JMP
)
850 if((vtop
[-nb_args
].type
.ref
->type
.t
& VT_BTYPE
) == VT_STRUCT
851 && type_size(&vtop
[-nb_args
].type
.ref
->type
, &align
) <= 4) {
854 vtop
[-nb_args
]=vtop
[-nb_args
+1];
855 vtop
[-nb_args
+1]=tmp
;
859 vpushi(0), nb_args
++;
860 vtop
->type
.t
= VT_LLONG
;
862 ncrn
= ncprn
= argno
= vfp_argno
= args_size
= 0;
863 /* Assign argument to registers and stack with alignment.
864 If, considering alignment constraints, enough registers of the correct type
865 (core or VFP) are free for the current argument, assign them to it, else
866 allocate on stack with correct alignment. Whenever a structure is allocated
867 in registers or on stack, it is always put on the stack at this stage. The
868 stack is divided in 3 zones. The zone are, from high addresses to low
869 addresses: structures to be loaded in core registers, structures to be
870 loaded in VFP registers, argument allocated to stack. SValue's representing
871 structures in the first zone are moved just after the SValue pointed by
872 before_stack. SValue's representing structures in the second zone are
873 moved just after the SValue pointer by before_creg. */
874 for(i
= nb_args
; i
-- ;) {
875 int j
, assigned_vfpreg
= 0;
876 size
= type_size(&vtop
[-i
].type
, &align
);
877 switch(vtop
[-i
].type
.t
& VT_BTYPE
) {
882 #ifdef TCC_ARM_HARDFLOAT
884 int hfa
= 0; /* Homogeneous float aggregate */
886 if (is_float(vtop
[-i
].type
.t
)
887 || (hfa
= is_float_hgen_aggr(&vtop
[-i
].type
))) {
890 assigned_vfpreg
= assign_fpreg(&avregs
, align
, size
);
891 end_reg
= assigned_vfpreg
+ (size
- 1) / 4;
892 if (assigned_vfpreg
>= 0) {
893 vfp_plan
[vfp_argno
++]=TREG_F0
+ assigned_vfpreg
/2;
895 /* if before_creg is not set, it means that no parameter has been
896 * allocated in core register. This implied that no argument has
897 * been allocated on stack neither because a VFP was available for
900 /* before_creg already exists and we just update it */
901 vrote(&vtop
[-i
], &vtop
[-i
] - before_creg
);
904 for (j
= assigned_vfpreg
; j
<= end_reg
; j
++)
912 before_stack
= &vtop
[-i
-1];
918 ncrn
= (ncrn
+ (align
-1)/4) & -(align
/4);
919 size
= (size
+ 3) & -4;
920 if (ncrn
+ size
/4 <= 4 || (ncrn
< 4 && assigned_vfpreg
!= -1)) {
922 vrote(&vtop
[-i
], &vtop
[-i
] - before_stack
);
924 /* before_stack can only have been set because all VFP registers are
925 * assigned, so no need to care about before_creg if before_stack is
926 * set since no more argument will be allocated in a VFP register. */
927 } else if (!before_creg
)
928 before_creg
= &vtop
[-i
];
929 for (j
= ncrn
; j
< 4 && j
< ncrn
+ size
/ 4; j
++)
933 args_size
= (ncrn
- 4) * 4;
935 before_stack
= &vtop
[-i
-1];
939 /* No need to set before_creg since it has already been set when
940 * assigning argument to core registers */
942 before_stack
= &vtop
[-i
-1];
953 int is_long
= (vtop
[-i
].type
.t
& VT_BTYPE
) == VT_LLONG
;
956 ncrn
= (ncrn
+ 1) & -2;
962 plan
[argno
++][0]=ncrn
++;
964 plan
[argno
-1][1]=ncrn
++;
971 if(args_size
& (align
-1)) {
973 vtop
->type
.t
= VT_VOID
; /* padding */
980 args_size
+= (size
+ 3) & -4;
985 args_size
= keep
= 0;
986 for(i
= 0;i
< nb_args
; i
++) {
988 if ((vtop
->type
.t
& VT_BTYPE
) == VT_STRUCT
) {
989 size
= type_size(&vtop
->type
, &align
);
990 /* align to stack align size */
991 size
= (size
+ 3) & -4;
992 /* allocate the necessary size on stack */
994 /* generate structure store */
996 o(0xE1A0000D|(intr(r
)<<12));
997 vset(&vtop
->type
, r
| VT_LVAL
, 0);
1002 } else if (is_float(vtop
->type
.t
)) {
1003 #ifdef TCC_ARM_HARDFLOAT
1004 if (!variadic
&& --vfp_argno
<16 && vfp_plan
[vfp_argno
]!=-1) {
1005 plan2
[keep
++]=vfp_plan
[vfp_argno
];
1010 r
=vfpr(gv(RC_FLOAT
))<<12;
1012 if ((vtop
->type
.t
& VT_BTYPE
) != VT_FLOAT
)
1015 r
|=0x101; /* fstms -> fstmd */
1019 r
=fpr(gv(RC_FLOAT
))<<12;
1020 if ((vtop
->type
.t
& VT_BTYPE
) == VT_FLOAT
)
1022 else if ((vtop
->type
.t
& VT_BTYPE
) == VT_DOUBLE
)
1025 size
= LDOUBLE_SIZE
;
1032 o(0xED2D0100|r
|(size
>>2));
1038 /* simple type (currently always same size) */
1039 /* XXX: implicit cast ? */
1041 if ((vtop
->type
.t
& VT_BTYPE
) == VT_LLONG
) {
1044 if(--argno
<4 && plan
[argno
][1]!=-1)
1050 o(0xE52D0004|(intr(r
)<<12)); /* str r,[sp,#-4]! */
1060 if(--argno
<4 && plan
[argno
][0]!=-1)
1063 if(vtop
->type
.t
== VT_VOID
) {
1065 o(0xE24DD004); /* sub sp,sp,#4 */
1071 o(0xE52D0004|(intr(r
)<<12)); /* str r,[sp,#-4]! */
1081 for(i
= 0; i
< keep
; i
++) {
1083 gv(regmask(plan2
[i
]));
1084 #ifdef TCC_ARM_HARDFLOAT
1085 /* arg is in s(2d+1): plan2[i]<plan2[i+1] => alignment occured (ex f,d,f) */
1086 if (i
< keep
- 1 && is_float(vtop
->type
.t
) && (plan2
[i
] <= plan2
[i
+ 1])) {
1087 o(0xEEF00A40|(vfpr(plan2
[i
])<<12)|vfpr(plan2
[i
]));
1091 save_regs(keep
); /* save used temporary registers */
1097 if(vfp_todo
&(1<<i
)) {
1098 o(0xED9D0A00|(i
&1)<<22|(i
>>1)<<12|nb_fregs
);
1100 /* There might be 2 floats in a double VFP reg but that doesn't seem
1103 vtop
->r
=TREG_F0
+i
/2;
1108 gadd_sp(nb_fregs
*4);
1109 args_size
-=nb_fregs
*4;
1116 todo
&=((1<<ncrn
)-1);
1128 args_size
-=nb_regs
*4;
1135 if((vtop
->type
.ref
->type
.t
& VT_BTYPE
) == VT_STRUCT
1136 && type_size(&vtop
->type
.ref
->type
, &align
) <= 4)
1138 store(REG_IRET
,vtop
-keep
);
1142 #ifdef TCC_ARM_HARDFLOAT
1143 else if(variadic
&& is_float(vtop
->type
.ref
->type
.t
)) {
1145 else if(is_float(vtop
->type
.ref
->type
.t
)) {
1147 if((vtop
->type
.ref
->type
.t
& VT_BTYPE
) == VT_FLOAT
) {
1148 o(0xEE000A10); /* fmsr s0,r0 */
1150 o(0xEE000B10); /* fmdlr d0,r0 */
1151 o(0xEE201B10); /* fmdhr d0,r1 */
1160 /* generate function prolog of type 't' */
1161 void gfunc_prolog(CType
*func_type
)
1164 int n
,nf
,size
,align
, variadic
, struct_ret
= 0;
1165 #ifdef TCC_ARM_HARDFLOAT
1166 struct avail_regs avregs
= AVAIL_REGS_INITIALIZER
;
1169 sym
= func_type
->ref
;
1170 func_vt
= sym
->type
;
1173 variadic
= (func_type
->ref
->c
== FUNC_ELLIPSIS
);
1174 if((func_vt
.t
& VT_BTYPE
) == VT_STRUCT
1175 && type_size(&func_vt
,&align
) > 4)
1179 func_vc
= 12; /* Offset from fp of the place to store the result */
1181 for(sym2
=sym
->next
;sym2
&& (n
<4 || nf
<16);sym2
=sym2
->next
) {
1182 size
= type_size(&sym2
->type
, &align
);
1183 #ifdef TCC_ARM_HARDFLOAT
1184 if (!variadic
&& (is_float(sym2
->type
.t
)
1185 || is_float_hgen_aggr(&sym2
->type
))) {
1186 int tmpnf
= assign_fpreg(&avregs
, align
, size
) + 1;
1187 nf
= (tmpnf
> nf
) ? tmpnf
: nf
;
1191 n
+= (size
+ 3) / 4;
1193 o(0xE1A0C00D); /* mov ip,sp */
1202 o(0xE92D0000|((1<<n
)-1)); /* save r0-r4 on stack if needed */
1207 nf
=(nf
+1)&-2; /* nf => HARDFLOAT => EABI */
1208 o(0xED2D0A00|nf
); /* save s0-s15 on stack if needed */
1210 o(0xE92D5800); /* save fp, ip, lr */
1211 o(0xE1A0B00D); /* mov fp, sp */
1212 func_sub_sp_offset
= ind
;
1213 o(0xE1A00000); /* nop, leave space for stack adjustment in epilogue */
1215 int addr
, pn
= struct_ret
, sn
= 0; /* pn=core, sn=stack */
1217 #ifdef TCC_ARM_HARDFLOAT
1219 avregs
= AVAIL_REGS_INITIALIZER
;
1221 while ((sym
= sym
->next
)) {
1224 size
= type_size(type
, &align
);
1225 size
= (size
+ 3) >> 2;
1226 align
= (align
+ 3) & ~3;
1227 #ifdef TCC_ARM_HARDFLOAT
1228 if (!variadic
&& (is_float(sym
->type
.t
)
1229 || is_float_hgen_aggr(&sym
->type
))) {
1230 int fpn
= assign_fpreg(&avregs
, align
, size
<< 2);
1239 pn
= (pn
+ (align
-1)/4) & -(align
/4);
1241 addr
= (nf
+ pn
) * 4;
1246 #ifdef TCC_ARM_HARDFLOAT
1250 sn
= (sn
+ (align
-1)/4) & -(align
/4);
1252 addr
= (n
+ nf
+ sn
) * 4;
1255 sym_push(sym
->v
& ~SYM_FIELD
, type
, VT_LOCAL
| lvalue_type(type
->t
), addr
+12);
1263 /* generate function epilog */
1264 void gfunc_epilog(void)
1269 /* Useless but harmless copy of the float result into main register(s) in case
1270 of variadic function in the hardfloat variant */
1271 if(is_float(func_vt
.t
)) {
1272 if((func_vt
.t
& VT_BTYPE
) == VT_FLOAT
)
1273 o(0xEE100A10); /* fmrs r0, s0 */
1275 o(0xEE100B10); /* fmrdl r0, d0 */
1276 o(0xEE301B10); /* fmrdh r1, d0 */
1280 o(0xE89BA800); /* restore fp, sp, pc */
1281 diff
= (-loc
+ 3) & -4;
1284 diff
= ((diff
+ 11) & -8) - 4;
1287 x
=stuff_const(0xE24BD000, diff
); /* sub sp,fp,# */
1289 *(uint32_t *)(cur_text_section
->data
+ func_sub_sp_offset
) = x
;
1293 o(0xE59FC004); /* ldr ip,[pc+4] */
1294 o(0xE04BD00C); /* sub sp,fp,ip */
1295 o(0xE1A0F00E); /* mov pc,lr */
1297 *(uint32_t *)(cur_text_section
->data
+ func_sub_sp_offset
) = 0xE1000000|encbranch(func_sub_sp_offset
,addr
,1);
1302 /* generate a jump to a label */
1307 o(0xE0000000|encbranch(r
,t
,1));
1311 /* generate a jump to a fixed address */
1312 void gjmp_addr(int a
)
1317 /* generate a test. set 'inv' to invert test. Stack entry is popped */
1318 int gtst(int inv
, int t
)
1322 v
= vtop
->r
& VT_VALMASK
;
1325 op
=mapcc(inv
?negcc(vtop
->c
.i
):vtop
->c
.i
);
1326 op
|=encbranch(r
,t
,1);
1329 } else if (v
== VT_JMP
|| v
== VT_JMPI
) {
1330 if ((v
& 1) == inv
) {
1339 p
= decbranch(lp
=p
);
1341 x
= (uint32_t *)(cur_text_section
->data
+ lp
);
1343 *x
|= encbranch(lp
,t
,1);
1352 if (is_float(vtop
->type
.t
)) {
1355 o(0xEEB50A40|(vfpr(r
)<<12)|T2CPR(vtop
->type
.t
)); /* fcmpzX */
1356 o(0xEEF1FA10); /* fmstat */
1358 o(0xEE90F118|(fpr(r
)<<16));
1362 return gtst(inv
, t
);
1363 } else if ((vtop
->r
& (VT_VALMASK
| VT_LVAL
| VT_SYM
)) == VT_CONST
) {
1364 /* constant jmp optimization */
1365 if ((vtop
->c
.i
!= 0) != inv
)
1369 o(0xE3300000|(intr(v
)<<16));
1372 return gtst(inv
, t
);
1379 /* generate an integer binary operation */
1380 void gen_opi(int op
)
1383 uint32_t opc
= 0, r
, fr
;
1384 unsigned short retreg
= REG_IRET
;
1392 case TOK_ADDC1
: /* add with carry generation */
1400 case TOK_SUBC1
: /* sub with carry generation */
1404 case TOK_ADDC2
: /* add with carry use */
1408 case TOK_SUBC2
: /* sub with carry use */
1425 gv2(RC_INT
, RC_INT
);
1429 o(0xE0000090|(intr(r
)<<16)|(intr(r
)<<8)|intr(fr
));
1454 func
=TOK___aeabi_idivmod
;
1463 func
=TOK___aeabi_uidivmod
;
1471 gv2(RC_INT
, RC_INT
);
1472 r
=intr(vtop
[-1].r2
=get_reg(RC_INT
));
1474 vtop
[-1].r
=get_reg_ex(RC_INT
,regmask(c
));
1476 o(0xE0800090|(r
<<16)|(intr(vtop
->r
)<<12)|(intr(c
)<<8)|intr(vtop
[1].r
));
1485 if((vtop
[-1].r
& (VT_VALMASK
| VT_LVAL
| VT_SYM
)) == VT_CONST
) {
1486 if(opc
== 4 || opc
== 5 || opc
== 0xc) {
1488 opc
|=2; // sub -> rsb
1491 if ((vtop
->r
& VT_VALMASK
) == VT_CMP
||
1492 (vtop
->r
& (VT_VALMASK
& ~1)) == VT_JMP
)
1497 opc
=0xE0000000|(opc
<<20)|(c
<<16);
1498 if((vtop
->r
& (VT_VALMASK
| VT_LVAL
| VT_SYM
)) == VT_CONST
) {
1500 x
=stuff_const(opc
|0x2000000,vtop
->c
.i
);
1502 r
=intr(vtop
[-1].r
=get_reg_ex(RC_INT
,regmask(vtop
[-1].r
)));
1507 fr
=intr(gv(RC_INT
));
1508 r
=intr(vtop
[-1].r
=get_reg_ex(RC_INT
,two2mask(vtop
->r
,vtop
[-1].r
)));
1512 if (op
>= TOK_ULT
&& op
<= TOK_GT
) {
1518 opc
=0xE1A00000|(opc
<<5);
1519 if ((vtop
->r
& VT_VALMASK
) == VT_CMP
||
1520 (vtop
->r
& (VT_VALMASK
& ~1)) == VT_JMP
)
1526 if ((vtop
->r
& (VT_VALMASK
| VT_LVAL
| VT_SYM
)) == VT_CONST
) {
1527 fr
=intr(vtop
[-1].r
=get_reg_ex(RC_INT
,regmask(vtop
[-1].r
)));
1528 c
= vtop
->c
.i
& 0x1f;
1529 o(opc
|(c
<<7)|(fr
<<12));
1531 fr
=intr(gv(RC_INT
));
1532 c
=intr(vtop
[-1].r
=get_reg_ex(RC_INT
,two2mask(vtop
->r
,vtop
[-1].r
)));
1533 o(opc
|(c
<<12)|(fr
<<8)|0x10);
1538 vpush_global_sym(&func_old_type
, func
);
1545 tcc_error("gen_opi %i unimplemented!",op
);
1550 static int is_zero(int i
)
1552 if((vtop
[i
].r
& (VT_VALMASK
| VT_LVAL
| VT_SYM
)) != VT_CONST
)
1554 if (vtop
[i
].type
.t
== VT_FLOAT
)
1555 return (vtop
[i
].c
.f
== 0.f
);
1556 else if (vtop
[i
].type
.t
== VT_DOUBLE
)
1557 return (vtop
[i
].c
.d
== 0.0);
1558 return (vtop
[i
].c
.ld
== 0.l
);
1561 /* generate a floating point operation 'v = t1 op t2' instruction. The
1562 * two operands are guaranted to have the same floating point type */
1563 void gen_opf(int op
)
1567 x
=0xEE000A00|T2CPR(vtop
->type
.t
);
1585 x
|=0x810000; /* fsubX -> fnegX */
1598 if(op
< TOK_ULT
|| op
> TOK_GT
) {
1599 tcc_error("unknown fp op %x!",op
);
1605 case TOK_LT
: op
=TOK_GT
; break;
1606 case TOK_GE
: op
=TOK_ULE
; break;
1607 case TOK_LE
: op
=TOK_GE
; break;
1608 case TOK_GT
: op
=TOK_ULT
; break;
1611 x
|=0xB40040; /* fcmpX */
1612 if(op
!=TOK_EQ
&& op
!=TOK_NE
)
1613 x
|=0x80; /* fcmpX -> fcmpeX */
1616 o(x
|0x10000|(vfpr(gv(RC_FLOAT
))<<12)); /* fcmp(e)X -> fcmp(e)zX */
1618 x
|=vfpr(gv(RC_FLOAT
));
1620 o(x
|(vfpr(gv(RC_FLOAT
))<<12));
1623 o(0xEEF1FA10); /* fmstat */
1626 case TOK_LE
: op
=TOK_ULE
; break;
1627 case TOK_LT
: op
=TOK_ULT
; break;
1628 case TOK_UGE
: op
=TOK_GE
; break;
1629 case TOK_UGT
: op
=TOK_GT
; break;
1646 vtop
->r
=get_reg_ex(RC_FLOAT
,r
);
1649 o(x
|(vfpr(vtop
->r
)<<12));
1653 static uint32_t is_fconst()
1657 if((vtop
->r
& (VT_VALMASK
| VT_LVAL
| VT_SYM
)) != VT_CONST
)
1659 if (vtop
->type
.t
== VT_FLOAT
)
1661 else if (vtop
->type
.t
== VT_DOUBLE
)
1691 /* generate a floating point operation 'v = t1 op t2' instruction. The
1692 two operands are guaranted to have the same floating point type */
1693 void gen_opf(int op
)
1695 uint32_t x
, r
, r2
, c1
, c2
;
1696 //fputs("gen_opf\n",stderr);
1702 #if LDOUBLE_SIZE == 8
1703 if ((vtop
->type
.t
& VT_BTYPE
) != VT_FLOAT
)
1706 if ((vtop
->type
.t
& VT_BTYPE
) == VT_DOUBLE
)
1708 else if ((vtop
->type
.t
& VT_BTYPE
) == VT_LDOUBLE
)
1719 r
=fpr(gv(RC_FLOAT
));
1726 r2
=fpr(gv(RC_FLOAT
));
1735 r
=fpr(gv(RC_FLOAT
));
1737 } else if(c1
&& c1
<=0xf) {
1740 r
=fpr(gv(RC_FLOAT
));
1745 r
=fpr(gv(RC_FLOAT
));
1747 r2
=fpr(gv(RC_FLOAT
));
1756 r
=fpr(gv(RC_FLOAT
));
1761 r2
=fpr(gv(RC_FLOAT
));
1769 r
=fpr(gv(RC_FLOAT
));
1771 } else if(c1
&& c1
<=0xf) {
1774 r
=fpr(gv(RC_FLOAT
));
1779 r
=fpr(gv(RC_FLOAT
));
1781 r2
=fpr(gv(RC_FLOAT
));
1785 if(op
>= TOK_ULT
&& op
<= TOK_GT
) {
1786 x
|=0xd0f110; // cmfe
1787 /* bug (intention?) in Linux FPU emulator
1788 doesn't set carry if equal */
1794 tcc_error("unsigned comparision on floats?");
1800 op
=TOK_ULE
; /* correct in unordered case only if AC bit in FPSR set */
1804 x
&=~0x400000; // cmfe -> cmf
1826 r
=fpr(gv(RC_FLOAT
));
1833 r2
=fpr(gv(RC_FLOAT
));
1835 vtop
[-1].r
= VT_CMP
;
1838 tcc_error("unknown fp op %x!",op
);
1842 if(vtop
[-1].r
== VT_CMP
)
1848 vtop
[-1].r
=get_reg_ex(RC_FLOAT
,two2mask(vtop
[-1].r
,c1
));
1852 o(x
|(r
<<16)|(c1
<<12)|r2
);
1856 /* convert integers to fp 't' type. Must handle 'int', 'unsigned int'
1857 and 'long long' cases. */
1858 ST_FUNC
void gen_cvt_itof1(int t
)
1862 bt
=vtop
->type
.t
& VT_BTYPE
;
1863 if(bt
== VT_INT
|| bt
== VT_SHORT
|| bt
== VT_BYTE
) {
1869 r2
=vfpr(vtop
->r
=get_reg(RC_FLOAT
));
1870 o(0xEE000A10|(r
<<12)|(r2
<<16)); /* fmsr */
1872 if(!(vtop
->type
.t
& VT_UNSIGNED
))
1873 r2
|=0x80; /* fuitoX -> fsituX */
1874 o(0xEEB80A40|r2
|T2CPR(t
)); /* fYitoX*/
1876 r2
=fpr(vtop
->r
=get_reg(RC_FLOAT
));
1877 if((t
& VT_BTYPE
) != VT_FLOAT
)
1878 dsize
=0x80; /* flts -> fltd */
1879 o(0xEE000110|dsize
|(r2
<<16)|(r
<<12)); /* flts */
1880 if((vtop
->type
.t
& (VT_UNSIGNED
|VT_BTYPE
)) == (VT_UNSIGNED
|VT_INT
)) {
1882 o(0xE3500000|(r
<<12)); /* cmp */
1883 r
=fpr(get_reg(RC_FLOAT
));
1884 if(last_itod_magic
) {
1885 off
=ind
+8-last_itod_magic
;
1890 o(0xBD1F0100|(r
<<12)|off
); /* ldflts */
1892 o(0xEA000000); /* b */
1893 last_itod_magic
=ind
;
1894 o(0x4F800000); /* 4294967296.0f */
1896 o(0xBE000100|dsize
|(r2
<<16)|(r2
<<12)|r
); /* adflt */
1900 } else if(bt
== VT_LLONG
) {
1902 CType
*func_type
= 0;
1903 if((t
& VT_BTYPE
) == VT_FLOAT
) {
1904 func_type
= &func_float_type
;
1905 if(vtop
->type
.t
& VT_UNSIGNED
)
1906 func
=TOK___floatundisf
;
1908 func
=TOK___floatdisf
;
1909 #if LDOUBLE_SIZE != 8
1910 } else if((t
& VT_BTYPE
) == VT_LDOUBLE
) {
1911 func_type
= &func_ldouble_type
;
1912 if(vtop
->type
.t
& VT_UNSIGNED
)
1913 func
=TOK___floatundixf
;
1915 func
=TOK___floatdixf
;
1916 } else if((t
& VT_BTYPE
) == VT_DOUBLE
) {
1918 } else if((t
& VT_BTYPE
) == VT_DOUBLE
|| (t
& VT_BTYPE
) == VT_LDOUBLE
) {
1920 func_type
= &func_double_type
;
1921 if(vtop
->type
.t
& VT_UNSIGNED
)
1922 func
=TOK___floatundidf
;
1924 func
=TOK___floatdidf
;
1927 vpush_global_sym(func_type
, func
);
1935 tcc_error("unimplemented gen_cvt_itof %x!",vtop
->type
.t
);
1938 /* convert fp to int 't' type */
1939 void gen_cvt_ftoi(int t
)
1945 r2
=vtop
->type
.t
& VT_BTYPE
;
1948 r
=vfpr(gv(RC_FLOAT
));
1950 o(0xEEBC0AC0|(r
<<12)|r
|T2CPR(r2
)|u
); /* ftoXizY */
1951 r2
=intr(vtop
->r
=get_reg(RC_INT
));
1952 o(0xEE100A10|(r
<<16)|(r2
<<12));
1957 func
=TOK___fixunssfsi
;
1958 #if LDOUBLE_SIZE != 8
1959 else if(r2
== VT_LDOUBLE
)
1960 func
=TOK___fixunsxfsi
;
1961 else if(r2
== VT_DOUBLE
)
1963 else if(r2
== VT_LDOUBLE
|| r2
== VT_DOUBLE
)
1965 func
=TOK___fixunsdfsi
;
1967 r
=fpr(gv(RC_FLOAT
));
1968 r2
=intr(vtop
->r
=get_reg(RC_INT
));
1969 o(0xEE100170|(r2
<<12)|r
);
1973 } else if(t
== VT_LLONG
) { // unsigned handled in gen_cvt_ftoi1
1976 #if LDOUBLE_SIZE != 8
1977 else if(r2
== VT_LDOUBLE
)
1979 else if(r2
== VT_DOUBLE
)
1981 else if(r2
== VT_LDOUBLE
|| r2
== VT_DOUBLE
)
1986 vpush_global_sym(&func_old_type
, func
);
1991 vtop
->r2
= REG_LRET
;
1995 tcc_error("unimplemented gen_cvt_ftoi!");
1998 /* convert from one floating point type to another */
1999 void gen_cvt_ftof(int t
)
2002 if(((vtop
->type
.t
& VT_BTYPE
) == VT_FLOAT
) != ((t
& VT_BTYPE
) == VT_FLOAT
)) {
2003 uint32_t r
= vfpr(gv(RC_FLOAT
));
2004 o(0xEEB70AC0|(r
<<12)|r
|T2CPR(vtop
->type
.t
));
2007 /* all we have to do on i386 and FPA ARM is to put the float in a register */
2012 /* computed goto support */
2019 /* Save the stack pointer onto the stack and return the location of its address */
2020 ST_FUNC
void gen_vla_sp_save(int addr
) {
2021 tcc_error("variable length arrays unsupported for this target");
2024 /* Restore the SP from a location on the stack */
2025 ST_FUNC
void gen_vla_sp_restore(int addr
) {
2026 tcc_error("variable length arrays unsupported for this target");
2029 /* Subtract from the stack pointer, and push the resulting value onto the stack */
2030 ST_FUNC
void gen_vla_alloc(CType
*type
, int align
) {
2031 tcc_error("variable length arrays unsupported for this target");
2034 /* end of ARM code generator */
2035 /*************************************************************/
2037 /*************************************************************/