As per architecture, SuperH has a reversed NaN signalling bit
vs IEEE754-2008, it also has a NaN propgation rule similar to
MIPS style.

Use mips style float format and mode for all float types, and
correct sfp-machine header accordingly.

        PR target/111814

gcc/ChangeLog:

        * config/sh/sh-modes.def (RESET_FLOAT_FORMAT): Use mips format.
        (FLOAT_MODE): Use mips mode.

libgcc/ChangeLog:

        * config/sh/sfp-machine.h (_FP_NANFRAC_B): Reverse signaling bit.
        (_FP_NANFRAC_H): Likewise.
        (_FP_NANFRAC_S): Likewise.
        (_FP_NANFRAC_D): Likewise.
        (_FP_NANFRAC_Q): Likewise.
        (_FP_KEEPNANFRACP): Enable for target.
        (_FP_QNANNEGATEDP): Enable for target.
        (_FP_CHOOSENAN): Port from MIPS.

gcc/testsuite/ChangeLog:

        * gcc.target/sh/pr111814.c: New test.

Signed-off-by: Jiaxun Yang <jiaxun.y...@flygoat.com>
---
Changes in v2:
- Fix compile error
- Link to v1: 
https://inbox.sourceware.org/20241231-sh-nan-v1-1-6ee9c9130...@flygoat.com
---
 gcc/config/sh/sh-modes.def             |  6 ++++++
 gcc/testsuite/gcc.target/sh/pr111814.c |  7 +++++++
 libgcc/config/sh/sfp-machine.h         | 36 ++++++++++++++++++++++------------
 3 files changed, 36 insertions(+), 13 deletions(-)

diff --git a/gcc/config/sh/sh-modes.def b/gcc/config/sh/sh-modes.def
index 
a1d6fa9c4903abefa5b3be664853542e41f53a78..b5b459b8da60a8ad8e61a38bf4c437e8a100aa97
 100644
--- a/gcc/config/sh/sh-modes.def
+++ b/gcc/config/sh/sh-modes.def
@@ -17,6 +17,12 @@ You should have received a copy of the GNU General Public 
License
 along with GCC; see the file COPYING3.  If not see
 <http://www.gnu.org/licenses/>.  */
 
+/* SH has the same reversed quiet bit as MIPS.  */
+RESET_FLOAT_FORMAT (SF, mips_single_format);
+RESET_FLOAT_FORMAT (DF, mips_double_format);
+/* TFmode: IEEE quad floating point (software).  */
+FLOAT_MODE (TF, 16, mips_quad_format);
+
 /* Vector modes.  */
 VECTOR_MODE  (INT, QI, 2);    /*                 V2QI */
 VECTOR_MODES (INT, 4);        /*            V4QI V2HI */
diff --git a/gcc/testsuite/gcc.target/sh/pr111814.c 
b/gcc/testsuite/gcc.target/sh/pr111814.c
new file mode 100644
index 
0000000000000000000000000000000000000000..a88e5d786ba0c4d629d345db527c3da7ddfed0df
--- /dev/null
+++ b/gcc/testsuite/gcc.target/sh/pr111814.c
@@ -0,0 +1,7 @@
+/* Verify that __builtin_nan("") produces a constant matches
+   architecture specification. */
+/* { dg-do compile } */
+
+double d = __builtin_nan ("");
+
+/* { dg-final { scan-assembler "\t.long\t-1\n\t.long\t2146959359\n" } } */
diff --git a/libgcc/config/sh/sfp-machine.h b/libgcc/config/sh/sfp-machine.h
index 
26f65166976b2a8dc5d93f69b2c7136a3e010d8e..68695cc30f941f0738016da4f7d825808b57d24b
 100644
--- a/libgcc/config/sh/sfp-machine.h
+++ b/libgcc/config/sh/sfp-machine.h
@@ -39,11 +39,11 @@ see the files COPYING3 and COPYING.RUNTIME respectively.  
If not, see
 #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)
 
-#define _FP_NANFRAC_B  _FP_QNANBIT_B
-#define _FP_NANFRAC_H  _FP_QNANBIT_H
-#define _FP_NANFRAC_S  _FP_QNANBIT_S
-#define _FP_NANFRAC_D  _FP_QNANBIT_D, 0
-#define _FP_NANFRAC_Q  _FP_QNANBIT_Q, 0, 0, 0
+#define _FP_NANFRAC_B  (_FP_QNANBIT_B - 1)
+#define _FP_NANFRAC_H  (_FP_QNANBIT_H - 1)
+#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
 
 /* The type of the result of a floating point comparison.  This must
    match __libgcc_cmp_return__ in GCC for the target.  */
@@ -56,14 +56,24 @@ typedef int __gcc_CMPtype __attribute__ ((mode 
(__libgcc_cmp_return__)));
 #define _FP_NANSIGN_D  0
 #define _FP_NANSIGN_Q  0
 
-#define _FP_KEEPNANFRACP 0
-#define _FP_QNANNEGATEDP 0
-
-#define _FP_CHOOSENAN(fs, wc, R, X, Y, OP)  \
-  do {                      \
-    R##_s = _FP_NANSIGN_##fs;           \
-    _FP_FRAC_SET_##wc(R,_FP_NANFRAC_##fs);  \
-    R##_c = FP_CLS_NAN;             \
+#define _FP_KEEPNANFRACP 1
+#define _FP_QNANNEGATEDP 1
+
+/* X is chosen unless one of the NaNs is sNaN.  */
+# 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_TININESS_AFTER_ROUNDING 1

---
base-commit: 3672194ad2b594027311789bab9c067b7791fabd
change-id: 20241231-sh-nan-b777b3af0342
prerequisite-change-id: 20241231-b4-workflow-2ca134652c07:v1

Best regards,
-- 
Jiaxun Yang <jiaxun.y...@flygoat.com>

Reply via email to