This improves commit 5cbe03b9c47e676e045b4978c384087433bd6042 by avoiding a double transfer when the default float ABI is already softfp. It's also more clean by expliciting that the ABI is simply changed for runtime ABI functions.
Unified · Split
| @@ -923,7 +923,7 @@ struct plan { · 922 unmodified lines | |||
| 923 | definition of union reg_class). | 923 | definition of union reg_class). |
| 924 | 924 | ||
| 925 | nb_args: number of parameters of the function for which a call is generated | 925 | nb_args: number of parameters of the function for which a call is generated |
| 926 | corefloat: whether to pass float via core registers or not | 926 | float_abi: float ABI in use for this function call |
| 927 | plan: the structure where the overall assignment is recorded | 927 | plan: the structure where the overall assignment is recorded |
| 928 | todo: a bitmap that record which core registers hold a parameter | 928 | todo: a bitmap that record which core registers hold a parameter |
| 929 | 929 | ||
| @@ -932,7 +932,7 @@ struct plan { · 2 unmodified lines | |||
| 932 | Note: this function allocated an array in plan->pplans with tcc_malloc. It | 932 | Note: this function allocated an array in plan->pplans with tcc_malloc. It |
| 933 | is the responsability of the caller to free this array once used (ie not | 933 | is the responsability of the caller to free this array once used (ie not |
| 934 | before copy_params). */ | 934 | before copy_params). */ |
| 935 | static int assign_regs(int nb_args, int corefloat, struct plan *plan, int *todo) | 935 | static int assign_regs(int nb_args, int float_abi, struct plan *plan, int *todo) |
| 936 | { | 936 | { |
| 937 | int i, size, align; | 937 | int i, size, align; |
| 938 | int ncrn /* next core register number */, nsaa /* next stacked argument address*/; | 938 | int ncrn /* next core register number */, nsaa /* next stacked argument address*/; |
| @@ -952,7 +952,7 @@ static int assign_regs(int nb_args, int corefloat, struct plan *plan, int *todo) · 13 unmodified lines | |||
| 952 | case VT_FLOAT: | 952 | case VT_FLOAT: |
| 953 | case VT_DOUBLE: | 953 | case VT_DOUBLE: |
| 954 | case VT_LDOUBLE: | 954 | case VT_LDOUBLE: |
| 955 | if (!corefloat) { | 955 | if (float_abi == ARM_HARD_FLOAT) { |
| 956 | int is_hfa = 0; /* Homogeneous float aggregate */ | 956 | int is_hfa = 0; /* Homogeneous float aggregate */ |
| 957 | 957 | ||
| 958 | if (is_float(vtop[-i].type.t) | 958 | if (is_float(vtop[-i].type.t) |
| @@ -1183,14 +1183,15 @@ static int copy_params(int nb_args, struct plan *plan, int todo) · 224 unmodified lines | |||
| 1183 | void gfunc_call(int nb_args) | 1183 | void gfunc_call(int nb_args) |
| 1184 | { | 1184 | { |
| 1185 | int r, args_size; | 1185 | int r, args_size; |
| 1186 | int variadic, corefloat = 1; | 1186 | int variadic, def_float_abi = float_abi; |
| 1187 | int todo; | 1187 | int todo; |
| 1188 | struct plan plan; | 1188 | struct plan plan; |
| 1189 | 1189 | ||
| 1190 | #ifdef TCC_ARM_EABI | 1190 | #ifdef TCC_ARM_EABI |
| 1191 | if (float_abi == ARM_HARD_FLOAT) { | 1191 | if (float_abi == ARM_HARD_FLOAT) { |
| 1192 | variadic = (vtop[-nb_args].type.ref->c == FUNC_ELLIPSIS); | 1192 | variadic = (vtop[-nb_args].type.ref->c == FUNC_ELLIPSIS); |
| 1193 | corefloat = variadic || floats_in_core_regs(&vtop[-nb_args]); | 1193 | if (variadic || floats_in_core_regs(&vtop[-nb_args])) |
| 1194 | float_abi = ARM_SOFTFP_FLOAT; | ||
| 1194 | } | 1195 | } |
| 1195 | #endif | 1196 | #endif |
| 1196 | /* cannot let cpu flags if other instruction are generated. Also avoid leaving | 1197 | /* cannot let cpu flags if other instruction are generated. Also avoid leaving |
| @@ -1200,7 +1201,7 @@ void gfunc_call(int nb_args) · 3 unmodified lines | |||
| 1200 | if (r == VT_CMP || (r & ~1) == VT_JMP) | 1201 | if (r == VT_CMP || (r & ~1) == VT_JMP) |
| 1201 | gv(RC_INT); | 1202 | gv(RC_INT); |
| 1202 | 1203 | ||
| 1203 | args_size = assign_regs(nb_args, corefloat, &plan, &todo); | 1204 | args_size = assign_regs(nb_args, float_abi, &plan, &todo); |
| 1204 | 1205 | ||
| 1205 | #ifdef TCC_ARM_EABI | 1206 | #ifdef TCC_ARM_EABI |
| 1206 | if (args_size & 7) { /* Stack must be 8 byte aligned at fct call for EABI */ | 1207 | if (args_size & 7) { /* Stack must be 8 byte aligned at fct call for EABI */ |
| @@ -1218,8 +1219,7 @@ void gfunc_call(int nb_args) · 11 unmodified lines | |||
| 1218 | if (args_size) | 1219 | if (args_size) |
| 1219 | gadd_sp(args_size); /* pop all parameters passed on the stack */ | 1220 | gadd_sp(args_size); /* pop all parameters passed on the stack */ |
| 1220 | #if defined(TCC_ARM_EABI) && defined(TCC_ARM_VFP) | 1221 | #if defined(TCC_ARM_EABI) && defined(TCC_ARM_VFP) |
| 1221 | if(float_abi == ARM_SOFTFP_FLOAT && corefloat && | 1222 | if(float_abi == ARM_SOFTFP_FLOAT && is_float(vtop->type.ref->type.t)) { |
| 1222 | is_float(vtop->type.ref->type.t)) { | ||
| 1223 | if((vtop->type.ref->type.t & VT_BTYPE) == VT_FLOAT) { | 1223 | if((vtop->type.ref->type.t & VT_BTYPE) == VT_FLOAT) { |
| 1224 | o(0xEE000A10); /*vmov s0, r0 */ | 1224 | o(0xEE000A10); /*vmov s0, r0 */ |
| 1225 | } else { | 1225 | } else { |
| @@ -1230,6 +1230,7 @@ void gfunc_call(int nb_args) · 4 unmodified lines | |||
| 1230 | #endif | 1230 | #endif |
| 1231 | vtop -= nb_args + 1; /* Pop all params and fct address from value stack */ | 1231 | vtop -= nb_args + 1; /* Pop all params and fct address from value stack */ |
| 1232 | leaffunc = 0; /* we are calling a function, so we aren't in a leaf function */ | 1232 | leaffunc = 0; /* we are calling a function, so we aren't in a leaf function */ |
| 1233 | float_abi = def_float_abi; | ||
| 1233 | } | 1234 | } |
| 1234 | 1235 | ||
| 1235 | /* generate function prolog of type 't' */ | 1236 | /* generate function prolog of type 't' */ |
| @@ -1979,17 +1980,8 @@ ST_FUNC void gen_cvt_itof1(int t) · 743 unmodified lines | |||
| 1979 | vpush_global_sym(func_type, func); | 1980 | vpush_global_sym(func_type, func); |
| 1980 | vswap(); | 1981 | vswap(); |
| 1981 | gfunc_call(1); | 1982 | gfunc_call(1); |
| 1982 | #if defined(TCC_ARM_VFP) && defined(TCC_ARM_EABI) | ||
| 1983 | r=get_reg(RC_FLOAT); | ||
| 1984 | r2=vfpr(r); | ||
| 1985 | o(0xEE000B10|(r2<<16)); /* vmov.32 dr2[0], r0 */ | ||
| 1986 | o(0xEE201B10|(r2<<16)); /* vmov.32 dr2[1], r1 */ | ||
| 1987 | vpushi(0); | ||
| 1988 | vtop->r=r; | ||
| 1989 | #else | ||
| 1990 | vpushi(0); | 1983 | vpushi(0); |
| 1991 | vtop->r=TREG_F0; | 1984 | vtop->r=TREG_F0; |
| 1992 | #endif | ||
| 1993 | return; | 1985 | return; |
| 1994 | } | 1986 | } |
| 1995 | } | 1987 | } |