Patchwork MIPS/libgcc: Add soft-fp support for SDE bare-iron targets

login
register
mail settings
Submitter Maciej W. Rozycki
Date June 28, 2012, 12:30 p.m.
Message ID <alpine.DEB.1.10.1206281254420.23962@tp.orcam.me.uk>
Download mbox | patch
Permalink /patch/167862/
State New
Headers show

Comments

Maciej W. Rozycki - June 28, 2012, 12:30 p.m.
Hello,

 This change adds soft-fp support for SDE bare-iron targets.

 The settings have been mostly based on the version already present in 
glibc, except that the ABI variations have been merged into a single file 
and conditionalised on preprocessor macros (and the file reformatted to 
follow the GNU coding standard that the glibc variants don't).  Only n32 
has to be treated somewhat specially as it is ILP32 but its "long long" 
type is 64-bit with native support (using single registers rather than 
pairs).  The rest is handled generically, based on the width of the types 
chosen.

 This has been regression tested for the mips-sde-elf target with no new 
failures, using the o32 and n64 ABI multilibs, with and without 
-msoft-float, o32 also with MIPS16 variants.

 There's currently no SDE runtime support for n32, however despite the 
unability to test I decided the configuration shouldn't be pessimised by 
default (by avoiding the special exception and using the 32-bit "long" 
type) as glibc already uses such an arrangement so it's been verified 
elsewhere and if a platform that supports the n32 ABI decides later on to 
enable soft-fp too, it will be verified in libgcc anyway.  I believe this 
is reasonable and avoids the risk of someone chooing the "long" type by 
omission.

 Comments or questions are welcome, otherwise OK to apply?

2012-06-28  Catherine Moore  <clm@codesourcery.com>
            Maciej W. Rozycki  <macro@codesourcery.com>

	libgcc/
	* config/mips/sfp-machine.h: New file.
	* config.host <mips*-sde-elf*>: Enable soft-fp.

  Maciej

gcc-mips-softfp.diff
Joseph S. Myers - June 28, 2012, 1:50 p.m.
On Thu, 28 Jun 2012, Maciej W. Rozycki wrote:

> 	* config/mips/sfp-machine.h: New file.
> 	* config.host <mips*-sde-elf*>: Enable soft-fp.

The compiler uses MIPS NaN conventions on MIPS; fp-bit knows about those 
but soft-fp does not.  Are you not concerned about that regression?  (Is 
this code only ever going to be used in software floating-point 
configurations, without exception support, so the choice of NaN doesn't 
matter much?)

libgcc/config/mips/t-mips sets FPBIT and DPBIT.  Shouldn't you do 
something to override those settings?  Even if the libgcc logic is to 
build soft-fp if both soft-fp and fp-bit are configured, it would seem 
cleaner for the fragments to configure only the relevant one.

Patch

Index: gcc-trunk-4.6/libgcc/config/mips/sfp-machine.h
===================================================================
--- /dev/null	1970-01-01 00:00:00.000000000 +0000
+++ gcc-trunk-4.6/libgcc/config/mips/sfp-machine.h	2012-06-24 14:38:40.083663725 +0100
@@ -0,0 +1,101 @@ 
+#if defined _ABIN32 && _MIPS_SIM == _ABIN32
+
+#define _FP_W_TYPE_SIZE		64
+#define _FP_W_TYPE		unsigned long long
+#define _FP_WS_TYPE		signed long long
+#define _FP_I_TYPE		long long
+
+#else
+
+#define _FP_W_TYPE_SIZE		_MIPS_SZLONG
+#define _FP_W_TYPE		unsigned long
+#define _FP_WS_TYPE		signed long
+#define _FP_I_TYPE		long
+
+#endif
+
+#if _FP_W_TYPE_SIZE < 64
+
+#define _FP_MUL_MEAT_S(R, X, Y)					\
+  _FP_MUL_MEAT_1_wide (_FP_WFRACBITS_S, R, X, Y, umul_ppmm)
+#define _FP_MUL_MEAT_D(R, X, Y)					\
+  _FP_MUL_MEAT_2_wide (_FP_WFRACBITS_D, R, X, Y, umul_ppmm)
+#define _FP_MUL_MEAT_Q(R, X, Y)					\
+  _FP_MUL_MEAT_4_wide (_FP_WFRACBITS_Q, R, X, Y, umul_ppmm)
+
+#define _FP_DIV_MEAT_S(R, X, Y)					\
+  _FP_DIV_MEAT_1_udiv_norm (S, R, X, Y)
+#define _FP_DIV_MEAT_D(R, X, Y)					\
+  _FP_DIV_MEAT_2_udiv (D, R, X, Y)
+#define _FP_DIV_MEAT_Q(R, X, Y)					\
+  _FP_DIV_MEAT_4_udiv (Q, R, X, Y)
+
+#else
+
+#define _FP_MUL_MEAT_S(R, X, Y)					\
+  _FP_MUL_MEAT_1_imm (_FP_WFRACBITS_S, R, X, Y)
+#define _FP_MUL_MEAT_D(R, X, Y)					\
+  _FP_MUL_MEAT_1_wide (_FP_WFRACBITS_D, R, X, Y, umul_ppmm)
+#define _FP_MUL_MEAT_Q(R, X, Y)					\
+  _FP_MUL_MEAT_2_wide_3mul (_FP_WFRACBITS_Q, R, X, Y, umul_ppmm)
+
+#define _FP_DIV_MEAT_S(R, X, Y)					\
+  _FP_DIV_MEAT_1_imm (S, R, X, Y, _FP_DIV_HELP_imm)
+#define _FP_DIV_MEAT_D(R, X, Y)					\
+  _FP_DIV_MEAT_1_udiv_norm (D, R, X, Y)
+#define _FP_DIV_MEAT_Q(R, X, Y)					\
+  _FP_DIV_MEAT_2_udiv (Q, R, X, Y)
+
+#endif
+
+#define _FP_NANFRAC_S		((_FP_QNANBIT_S << 1) - 1)
+#define _FP_NANFRAC_D		((_FP_QNANBIT_D << 1) - 1), -1
+#define _FP_NANFRAC_Q		((_FP_QNANBIT_Q << 1) - 1), -1, -1, -1
+#define _FP_NANSIGN_S		0
+#define _FP_NANSIGN_D		0
+#define _FP_NANSIGN_Q		0
+
+#define _FP_KEEPNANFRACP 1
+/* From my experiments it seems X is chosen unless one of the
+   NaNs is sNaN,  in which case the result is NANSIGN/NANFRAC.  */
+#define _FP_CHOOSENAN(fs, wc, R, X, Y, OP)			\
+  do {								\
+    if ((_FP_FRAC_HIGH_RAW_##fs (X)				\
+	 | _FP_FRAC_HIGH_RAW_##fs (Y)) & _FP_QNANBIT_##fs)	\
+      {								\
+	R##_s = _FP_NANSIGN_##fs;				\
+        _FP_FRAC_SET_##wc (R, _FP_NANFRAC_##fs);		\
+      }								\
+    else							\
+      {								\
+	R##_s = X##_s;						\
+        _FP_FRAC_COPY_##wc (R, X);				\
+      }								\
+    R##_c = FP_CLS_NAN;						\
+  } while (0)
+
+#define FP_EX_INVALID           (1 << 4)
+#define FP_EX_DIVZERO           (1 << 3)
+#define FP_EX_OVERFLOW          (1 << 2)
+#define FP_EX_UNDERFLOW         (1 << 1)
+#define FP_EX_INEXACT           (1 << 0)
+
+#define __LITTLE_ENDIAN         1234
+#define __BIG_ENDIAN            4321
+
+#if defined MIPS_EB || defined __MIPSEB__ || defined MIPSEB || defined _MIPSEB
+# if defined MIPS_EL || defined __MIPSEL__ || defined MIPSEL || defined _MIPSEL
+#  error "Both BIG_ENDIAN and LITTLE_ENDIAN defined!"
+# endif
+# define __BYTE_ORDER __BIG_ENDIAN
+#elif defined MIPS_EL || defined __MIPSEL__ || defined MIPSEL || defined _MIPSEL
+# define __BYTE_ORDER __LITTLE_ENDIAN
+#else
+# error "Cannot determine current byte order"
+#endif
+
+
+/* Define ALIASNAME as a strong alias for NAME.  */
+#define strong_alias(name, aliasname) _strong_alias (name, aliasname)
+#define _strong_alias(name, aliasname) \
+  extern __typeof (name) aliasname __attribute__ ((alias (#name)));
Index: gcc-trunk-4.6/libgcc/config.host
===================================================================
--- gcc-trunk-4.6.orig/libgcc/config.host	2012-06-22 20:31:35.000000000 +0100
+++ gcc-trunk-4.6/libgcc/config.host	2012-06-22 20:31:37.654759477 +0100
@@ -737,7 +737,7 @@  mips*-*-linux*)				# Linux MIPS, either 
 	fi
 	;;
 mips*-sde-elf*)
-	tmake_file="$tmake_file mips/t-crtstuff mips/t-mips16"
+	tmake_file="$tmake_file mips/t-crtstuff mips/t-mips16 t-softfp-sfdf t-softfp-excl t-softfp"
 	case "${with_newlib}" in
 	  yes)
 	    # newlib / libgloss.