This is the mail archive of the gcc-patches@gcc.gnu.org mailing list for the GCC project.


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]
Other format: [Raw text]

[PATCH, ARM] Fix ABI for double-precision helpers on single-float-only CPUs


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

ChangeLog

    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.
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.

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;

Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]