Merge from Sourcery G++ 4.4: 2010-02-15 Julian Brown Issue #7486 gcc/ * config/arm/arm.c (arm_libcall_uses_aapcs_base) (arm_init_cumulative_args): Use correct ABI for double-precision helper functions in hard-float mode if only single-precision arithmetic is supported in hardware. 2010-07-26 Julian Brown Backport from FSF mainline: Julian Brown === modified file 'gcc/config/arm/arm.c' --- old/gcc/config/arm/arm.c 2010-08-13 10:30:35 +0000 +++ new/gcc/config/arm/arm.c 2010-08-13 10:43:42 +0000 @@ -3453,6 +3453,28 @@ 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; @@ -4406,6 +4428,31 @@ 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;