Make MIPS soft-fp preserve NaN payloads for NAN2008.
authorJoseph Myers <joseph@codesourcery.com>
Wed, 4 Jan 2017 17:06:33 +0000 (17:06 +0000)
committerJoseph Myers <jsm28@gcc.gnu.org>
Wed, 4 Jan 2017 17:06:33 +0000 (17:06 +0000)
The MIPS sfp-machine.h has an _FP_CHOOSENAN implementation which
emulates hardware semantics of not preserving signaling NaN payloads
for an operation with two NaN arguments (although that doesn't suffice
to avoid sNaN payload preservation in any case with just one NaN
argument).

However, those are only hardware semantics in the legacy NaN case; in
the NAN2008 case, the architecture documentation says hardware
preserves payloads in such cases.  Furthermore, this implementation
assumes legacy NaN semantics, so in the NAN2008 case the
implementation actually has the effect of preserving sNaN payloads but
not preserving qNaN payloads, when both should be preserved.

This patch fixes the code just to copy from the first argument (at the
level of libgcc, it's not meaningful which argument is the first and
which is the second).

Tested for mips64-linux-gnu (soft float, NAN2008) with the glibc math/
tests.

* config/mips/sfp-machine.h (_FP_CHOOSENAN): Always preserve NaN
payload if [__mips_nan2008].

From-SVN: r244059

libgcc/ChangeLog
libgcc/config/mips/sfp-machine.h

index 45e5c4ed02395e297722762a6b71f944fc0ed50e..f0eb567c591274e21734fc6de6b73b6856a1245b 100644 (file)
@@ -1,3 +1,8 @@
+2017-01-04  Joseph Myers  <joseph@codesourcery.com>
+
+       * config/mips/sfp-machine.h (_FP_CHOOSENAN): Always preserve NaN
+       payload if [__mips_nan2008].
+
 2017-01-04  Alan Modra  <amodra@gmail.com>
 
        * Makefile.in (configure_deps): Update.
index 7aa6d28a2cda1b90455c5e359d4b7afc423b0828..07d11580ee682e95cecd25eb323745f8978688a7 100644 (file)
@@ -96,10 +96,21 @@ typedef int __gcc_CMPtype __attribute__ ((mode (__libgcc_cmp_return__)));
 # define _FP_QNANNEGATEDP 1
 #endif
 
+#ifdef __mips_nan2008
+/* NaN payloads should be preserved for NAN2008.  */
+# define _FP_CHOOSENAN(fs, wc, R, X, Y, OP)    \
+  do                                           \
+    {                                          \
+      R##_s = X##_s;                           \
+      _FP_FRAC_COPY_##wc (R, X);               \
+      R##_c = FP_CLS_NAN;                      \
+    }                                          \
+  while (0)
+#else
 /* 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)                     \
+# 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)         \
@@ -114,6 +125,7 @@ typedef int __gcc_CMPtype __attribute__ ((mode (__libgcc_cmp_return__)));
       }                                                                \
     R##_c = FP_CLS_NAN;                                                \
   } while (0)
+#endif
 
 #ifdef __mips_hard_float
 #define FP_EX_INVALID           0x40