[backport from gcc-4.7/trunk via ARM/embedded-4_6-branch ] Date: Fri, 27 May 2011 17:32:38 +0100 From: Julian Brown Subject: [PATCH, ARM] Fix ABI for double-precision helpers on single-float-only CPUs List-Archive: The helper functions used to implement double-precision arithmetic on ARM processors that only support single-precision arithmetic in hardware should use the soft-float ABI (i.e. passing and returning floating-point arguments in core registers), even when -mfloat-abi=hard is in effect. This patch tweaks the ABI for the affected functions so that is true. Tested with cross to ARM EABI, and by manually observing compiler output. We've also been carrying this patch in our local tree for some time without issue. OK to apply? Thanks, Julian gcc/ 2011-09-19 Jiangning Liu Backport r174803 from mainline 2011-06-08 Julian Brown * config/arm/arm.c (arm_libcall_uses_aapcs_base): Use correct ABI for double-precision helper functions in hard-float mode if only single-precision arithmetic is supported in hardware. --- gcc-4.6.2/gcc/config/arm/arm.c.~1~ 2011-10-20 11:24:06.000000000 +0200 +++ gcc-4.6.2/gcc/config/arm/arm.c 2011-12-17 18:53:40.000000000 +0100 @@ -3577,6 +3577,28 @@ arm_libcall_uses_aapcs_base (const_rtx l 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. The same is + true for single-precision helpers, but we will never be using the + hard-float ABI on a CPU which doesn't support single-precision + operations in hardware. */ + 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;