commit 829dab1d743604e6025b929be7287c3215a57d21 Author: Julian Brown Date: Fri May 27 04:49:33 2011 -0700 Fix hard-float ABI for double-precision helpers on single-precision CPUs. diff --git a/gcc/config/arm/arm.c b/gcc/config/arm/arm.c index 5a62802..47fba2c 100644 --- a/gcc/config/arm/arm.c +++ b/gcc/config/arm/arm.c @@ -3472,6 +3472,28 @@ arm_libcall_uses_aapcs_base (const_rtx libcall) convert_optab_libfunc (sfix_optab, DImode, SFmode)); add_libcall (libcall_htab, convert_optab_libfunc (ufix_optab, DImode, SFmode)); + + /* Values from double-precision helper functions are returned in core + registers if the selected core only supports single-precision + arithmetic, even if we are using the hard-float ABI. */ + if (TARGET_VFP) + { + add_libcall (libcall_htab, optab_libfunc (add_optab, DFmode)); + add_libcall (libcall_htab, optab_libfunc (sdiv_optab, DFmode)); + add_libcall (libcall_htab, optab_libfunc (smul_optab, DFmode)); + add_libcall (libcall_htab, optab_libfunc (neg_optab, DFmode)); + add_libcall (libcall_htab, optab_libfunc (sub_optab, DFmode)); + add_libcall (libcall_htab, optab_libfunc (eq_optab, DFmode)); + add_libcall (libcall_htab, optab_libfunc (lt_optab, DFmode)); + add_libcall (libcall_htab, optab_libfunc (le_optab, DFmode)); + add_libcall (libcall_htab, optab_libfunc (ge_optab, DFmode)); + add_libcall (libcall_htab, optab_libfunc (gt_optab, DFmode)); + add_libcall (libcall_htab, optab_libfunc (unord_optab, DFmode)); + add_libcall (libcall_htab, + convert_optab_libfunc (sext_optab, DFmode, SFmode)); + add_libcall (libcall_htab, + convert_optab_libfunc (trunc_optab, SFmode, DFmode)); + } } return libcall && htab_find (libcall_htab, libcall) != NULL; @@ -4438,6 +4460,31 @@ arm_init_cumulative_args (CUMULATIVE_ARGS *pcum, tree fntype, if (arm_libcall_uses_aapcs_base (libname)) pcum->pcs_variant = ARM_PCS_AAPCS; + /* We must pass arguments to double-precision helper functions in core + registers if we only have hardware support for single-precision + arithmetic, even if we are using the hard-float ABI. */ + if (TARGET_VFP + && (rtx_equal_p (libname, optab_libfunc (add_optab, DFmode)) + || rtx_equal_p (libname, optab_libfunc (sdiv_optab, DFmode)) + || rtx_equal_p (libname, optab_libfunc (smul_optab, DFmode)) + || rtx_equal_p (libname, optab_libfunc (neg_optab, DFmode)) + || rtx_equal_p (libname, optab_libfunc (sub_optab, DFmode)) + || rtx_equal_p (libname, optab_libfunc (eq_optab, DFmode)) + || rtx_equal_p (libname, optab_libfunc (lt_optab, DFmode)) + || rtx_equal_p (libname, optab_libfunc (le_optab, DFmode)) + || rtx_equal_p (libname, optab_libfunc (ge_optab, DFmode)) + || rtx_equal_p (libname, optab_libfunc (gt_optab, DFmode)) + || rtx_equal_p (libname, optab_libfunc (unord_optab, DFmode)) + || rtx_equal_p (libname, convert_optab_libfunc (sext_optab, + DFmode, SFmode)) + || rtx_equal_p (libname, convert_optab_libfunc (trunc_optab, + SFmode, DFmode)) + || rtx_equal_p (libname, convert_optab_libfunc (sfix_optab, + SImode, DFmode)) + || rtx_equal_p (libname, convert_optab_libfunc (ufix_optab, + SImode, DFmode)))) + pcum->pcs_variant = ARM_PCS_AAPCS; + pcum->aapcs_ncrn = pcum->aapcs_next_ncrn = 0; pcum->aapcs_reg = NULL_RTX; pcum->aapcs_partial = 0;