This patch (finally!) moves MIPS over to the soft-fp routines.  The main
advantage is that we now handle 128-bit long-double exceptions properly
on hard-float targets.

This also removes the last use of TPBIT in libgcc.  It might be worth
removing support for that at some point -- including the associated
libgcc2.c routines -- but probably not at this stage of 4.9.

Tested on mips64-linux-gnu and mipsisa64-sde-elf.  It fixes the
c11-atomic-exec-5.c failures for n32 and n64.  I also checked that
the exported libgcc.so symbols were unchanged for all 3 GNU/Linux ABIs,
just to be sure.  I also did some spot checking of FCSR values after
long-double operations, as well as checking that SIGFPE was raised
for long-double operations when the associated enable bit was set.
Applied.

Thanks,
Richard


libgcc/
        * configure.ac: Check __mips64 when setting host_address.
        * configure: Regenerate.
        * config.host (mips*-*-*): Add t-softfp-sfdf, mips/t-softfp-tf,
        mips/t-mips64 and t-softfp.
        (mips*-*-linux*): Don't add mips/t-tpbit.
        * config/mips/t-mips (LIB2_SIDITI_CONV_FUNCS, FPBIT, FPBIT_CFLAGS)
        (DPBIT, DPBIT_CFLAGS): Delete.
        * config/mips/sfp-machine.h: New file.
        * config/mips/t-mips64: Likewise.
        * config/mips/t-softfp-tf: Likewise.
        * config/mips/t-tpbit: Delete.

Index: libgcc/configure.ac
===================================================================
--- libgcc/configure.ac 2014-02-02 08:29:06.963467177 +0000
+++ libgcc/configure.ac 2014-02-02 08:37:35.158153333 +0000
@@ -279,9 +279,11 @@ AC_CACHE_CHECK([whether assembler suppor
   [libgcc_cv_cfi=yes],
   [libgcc_cv_cfi=no])])
 
-# Check 32bit or 64bit
+# Check 32bit or 64bit.  In the case of MIPS, this really determines the
+# word size rather than the address size.
 cat > conftest.c <<EOF
-#if defined(__x86_64__) || (!defined(__i386__) && defined(__LP64__))
+#if defined(__x86_64__) || (!defined(__i386__) && defined(__LP64__)) \
+    || defined(__mips64)
 host_address=64
 #else
 host_address=32
Index: libgcc/config.host
===================================================================
--- libgcc/config.host  2014-02-02 08:29:06.963467177 +0000
+++ libgcc/config.host  2014-02-02 08:37:35.130153075 +0000
@@ -140,8 +140,16 @@ microblaze*-*-*)
        cpu_type=microblaze
        ;;
 mips*-*-*)
+       # All MIPS targets provide a full set of FP routines.
        cpu_type=mips
-       tmake_file=mips/t-mips
+       tmake_file="mips/t-mips t-softfp-sfdf"
+       if test "${ac_cv_sizeof_long_double}" = 16; then
+               tmake_file="${tmake_file} mips/t-softfp-tf"
+       fi
+       if test "${host_address}" = 64; then
+               tmake_file="${tmake_file} mips/t-mips64"
+       fi
+       tmake_file="${tmake_file} t-softfp"
        ;;
 nds32*-*)
        cpu_type=nds32
@@ -776,9 +784,6 @@ mips*-*-linux*)                             # Linux MIPS, 
either
            ;;
        esac
        md_unwind_header=mips/linux-unwind.h
-       if test "${ac_cv_sizeof_long_double}" = 16; then
-               tmake_file="${tmake_file} mips/t-tpbit"
-       fi
        ;;
 mips*-sde-elf*)
        tmake_file="$tmake_file mips/t-crtstuff mips/t-mips16"
Index: libgcc/config/mips/t-mips
===================================================================
--- libgcc/config/mips/t-mips   2014-02-02 08:29:06.963467177 +0000
+++ libgcc/config/mips/t-mips   2014-02-02 08:37:35.138153148 +0000
@@ -1,8 +1,1 @@
-LIB2_SIDITI_CONV_FUNCS = yes
-
-FPBIT = true
-FPBIT_CFLAGS = -DQUIET_NAN_NEGATED
-DPBIT = true
-DPBIT_CFLAGS = -DQUIET_NAN_NEGATED
-
 LIB2ADD_ST += $(srcdir)/config/mips/lib2funcs.c
Index: libgcc/config/mips/sfp-machine.h
===================================================================
--- /dev/null   2014-01-30 08:06:21.701666182 +0000
+++ libgcc/config/mips/sfp-machine.h    2014-02-02 08:57:55.358362947 +0000
@@ -0,0 +1,178 @@
+/* softfp machine description for MIPS.
+   Copyright (C) 2009-2014 Free Software Foundation, Inc.
+
+This file is part of GCC.
+
+GCC is free software; you can redistribute it and/or modify it under
+the terms of the GNU General Public License as published by the Free
+Software Foundation; either version 3, or (at your option) any later
+version.
+
+GCC is distributed in the hope that it will be useful, but WITHOUT ANY
+WARRANTY; without even the implied warranty of MERCHANTABILITY or
+FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+for more details.
+
+Under Section 7 of GPL version 3, you are granted additional
+permissions described in the GCC Runtime Library Exception, version
+3.1, as published by the Free Software Foundation.
+
+You should have received a copy of the GNU General Public License and
+a copy of the GCC Runtime Library Exception along with this program;
+see the files COPYING3 and COPYING.RUNTIME respectively.  If not, see
+<http://www.gnu.org/licenses/>.  */
+
+#ifdef __mips64
+#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
+
+typedef int TItype __attribute__ ((mode (TI)));
+typedef unsigned int UTItype __attribute__ ((mode (TI)));
+#define TI_BITS (__CHAR_BIT__ * (int) sizeof (TItype))
+
+#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_1_wide(_FP_WFRACBITS_D,R,X,Y,umul_ppmm)
+#define _FP_MUL_MEAT_Q(R,X,Y)                          \
+  _FP_MUL_MEAT_2_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_1_udiv_norm(D,R,X,Y)
+#define _FP_DIV_MEAT_Q(R,X,Y)  _FP_DIV_MEAT_2_udiv(Q,R,X,Y)
+
+#ifdef __mips_nan2008
+# define _FP_NANFRAC_S         ((_FP_QNANBIT_S << 1) - 1)
+# define _FP_NANFRAC_D         ((_FP_QNANBIT_D << 1) - 1)
+# define _FP_NANFRAC_Q         ((_FP_QNANBIT_Q << 1) - 1), -1
+#else
+# define _FP_NANFRAC_S         (_FP_QNANBIT_S - 1)
+# define _FP_NANFRAC_D         (_FP_QNANBIT_D - 1)
+# define _FP_NANFRAC_Q         (_FP_QNANBIT_Q - 1), -1
+#endif
+#else
+#define _FP_W_TYPE_SIZE                32
+#define _FP_W_TYPE             unsigned int
+#define _FP_WS_TYPE            signed int
+#define _FP_I_TYPE             int
+
+#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)
+
+#ifdef __mips_nan2008
+# 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
+#else
+# define _FP_NANFRAC_S         (_FP_QNANBIT_S - 1)
+# define _FP_NANFRAC_D         (_FP_QNANBIT_D - 1), -1
+# define _FP_NANFRAC_Q         (_FP_QNANBIT_Q - 1), -1, -1, -1
+#endif
+#endif
+
+/* The type of the result of a floating point comparison.  This must
+   match __libgcc_cmp_return__ in GCC for the target.  */
+typedef int __gcc_CMPtype __attribute__ ((mode (__libgcc_cmp_return__)));
+#define CMPtype __gcc_CMPtype
+
+#define _FP_NANSIGN_S          0
+#define _FP_NANSIGN_D          0
+#define _FP_NANSIGN_Q          0
+
+#define _FP_KEEPNANFRACP 1
+#ifdef __mips_nan2008
+# define _FP_QNANNEGATEDP 0
+#else
+# define _FP_QNANNEGATEDP 1
+#endif
+
+/* Comment from glibc: */
+/* 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)
+
+#ifdef __mips_hard_float
+#define FP_EX_INVALID           0x40
+#define FP_EX_DIVZERO           0x20
+#define FP_EX_OVERFLOW          0x10
+#define FP_EX_UNDERFLOW         0x08
+#define FP_EX_INEXACT           0x04
+#define FP_EX_ALL \
+       (FP_EX_INVALID | FP_EX_DIVZERO | FP_EX_OVERFLOW | FP_EX_UNDERFLOW \
+        | FP_EX_INEXACT)
+
+#define FP_EX_ENABLE_SHIFT     5
+#define FP_EX_CAUSE_SHIFT      10
+
+#define FP_RND_NEAREST         0x0
+#define FP_RND_ZERO            0x1
+#define FP_RND_PINF            0x2
+#define FP_RND_MINF            0x3
+#define FP_RND_MASK            0x3
+
+#define _FP_DECL_EX \
+  unsigned long int _fcsr __attribute__ ((unused)) = FP_RND_NEAREST
+
+#define FP_INIT_ROUNDMODE                      \
+  do {                                         \
+    _fcsr = __builtin_mips_get_fcsr ();                \
+  } while (0)
+
+#define FP_ROUNDMODE (_fcsr & FP_RND_MASK)
+
+#define FP_TRAPPING_EXCEPTIONS ((_fcsr >> FP_EX_ENABLE_SHIFT) & FP_EX_ALL)
+
+#define FP_HANDLE_EXCEPTIONS                           \
+  do {                                                 \
+    _fcsr &= ~(FP_EX_ALL << FP_EX_CAUSE_SHIFT);                \
+    /* Also clear Unimplemented Operation.  */         \
+    _fcsr &= ~(1 << 17);                               \
+    _fcsr |= _fex | (_fex << FP_EX_CAUSE_SHIFT);       \
+    __builtin_mips_set_fcsr (_fcsr);                   \
+  } while (0);
+
+#else
+#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)
+#endif
+
+#define        __LITTLE_ENDIAN 1234
+#define        __BIG_ENDIAN    4321
+
+#if defined _MIPSEB
+# define __BYTE_ORDER __BIG_ENDIAN
+#else
+# define __BYTE_ORDER __LITTLE_ENDIAN
+#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: libgcc/config/mips/t-mips64
===================================================================
--- /dev/null   2014-01-30 08:06:21.701666182 +0000
+++ libgcc/config/mips/t-mips64 2014-02-02 08:37:35.139153157 +0000
@@ -0,0 +1,1 @@
+softfp_int_modes += ti
Index: libgcc/config/mips/t-softfp-tf
===================================================================
--- /dev/null   2014-01-30 08:06:21.701666182 +0000
+++ libgcc/config/mips/t-softfp-tf      2014-02-02 08:37:35.139153157 +0000
@@ -0,0 +1,3 @@
+softfp_float_modes += tf
+softfp_extensions += sftf dftf
+softfp_truncations += tfsf tfdf
Index: libgcc/config/mips/t-tpbit
===================================================================
--- libgcc/config/mips/t-tpbit  2014-02-02 08:29:06.963467177 +0000
+++ /dev/null   2014-01-30 08:06:21.701666182 +0000
@@ -1,4 +0,0 @@
-ifeq ($(long_double_type_size),128)
-TPBIT = true
-TPBIT_CFLAGS = -DQUIET_NAN_NEGATED
-endif

Reply via email to