commit 829dab1d743604e6025b929be7287c3215a57d21
Author: Julian Brown <julian@henry8.codesourcery.com>
Date: Fri May 27 04:49:33 2011 -0700
Fix hard-float ABI for double-precision helpers on single-precision CPUs.
@@ -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;