All of lore.kernel.org
 help / color / mirror / Atom feed
* [Qemu-devel] [PATCH 00/19] softfloat: Clean up NaN handling
@ 2018-05-11  0:43 Richard Henderson
  2018-05-11  0:43 ` [Qemu-devel] [PATCH 01/19] fpu/softfloat: Merge NO_SIGNALING_NANS definitions Richard Henderson
                   ` (18 more replies)
  0 siblings, 19 replies; 29+ messages in thread
From: Richard Henderson @ 2018-05-11  0:43 UTC (permalink / raw)
  To: qemu-devel; +Cc: peter.maydell, alex.bennee

This is intended to address Peter's comments wrt Alex's float-to-float
conversion patches.  In particular, the handling of NaNs therein, where
some SNaN get converted to Inf instead of the appropriate QNaN.

I canonicalize NaNs within FloatParts much like we do with the original
softfpu commonNaNT.  With this, a couple of new specialize functions
allows me to remove the float_class_dnan/float_class_msnan placeholders.

This is based on some of Alex's work, which includes both the check-tcg
and the float-to-float patches.  My guess is that in the end we should
order this first.  But writing it this way was easier, for testing.

The full tree is

  git://github.com/rth7680/qemu.git fpu-snan

with these patches beginning at the merge at 537ab46101f5.


r~


Richard Henderson (19):
  fpu/softfloat: Merge NO_SIGNALING_NANS definitions
  fpu/softfloat: Split floatXX_silence_nan from floatXX_maybe_silence_nan
  fpu/softfloat: Move softfloat-specialize.h below FloatParts definition
  fpu/softfloat: Canonicalize NaN fraction
  fpu/softfloat: Introduce parts_is_snan_frac
  fpu/softfloat: Replace float_class_dnan with parts_default_nan
  fpu/softfloat: Replace float_class_msnan with parts_silence_nan
  target/arm: Use floatX_silence_nan when we have already checked for SNaN
  target/arm: Remove floatX_maybe_silence_nan from conversions
  target/hppa: Remove floatX_maybe_silence_nan from conversions
  target/m68k: Use floatX_silence_nan when we have already checked for SNaN
  target/mips: Remove floatX_maybe_silence_nan from conversions
  target/riscv: Remove floatX_maybe_silence_nan from conversions
  target/s390x: Remove floatX_maybe_silence_nan from conversions
  fpu/softfloat: Use float*_silence_nan in propagateFloat*NaN
  fpu/softfloat: Remove floatX_maybe_silence_nan
  fpu/softfloat: Introduce SNAN_BIT_IS_ONE
  fpu/softfloat: Pass FloatClass to pickNaN
  fpu/softfloat: Pass FloatClass to pickNaNMulAdd

 fpu/softfloat-specialize.h    | 621 +++++++++++++++++++---------------
 include/fpu/softfloat-types.h |   1 +
 include/fpu/softfloat.h       |  14 +-
 target/mips/cpu.h             |   4 +-
 fpu/softfloat.c               | 162 ++++-----
 target/arm/helper-a64.c       |   7 +-
 target/arm/helper.c           |  24 +-
 target/hppa/cpu.c             |   1 -
 target/hppa/op_helper.c       |   2 -
 target/m68k/softfloat.c       |   3 +-
 target/mips/msa_helper.c      |   4 -
 target/mips/op_helper.c       |   2 -
 target/mips/translate_init.c  |   4 +-
 target/ppc/fpu_helper.c       |   1 -
 target/riscv/fpu_helper.c     |   6 +-
 target/s390x/fpu_helper.c     |  12 +-
 target/sh4/cpu.c              |   1 -
 target/unicore32/cpu.c        |   2 -
 18 files changed, 430 insertions(+), 441 deletions(-)

-- 
2.17.0

^ permalink raw reply	[flat|nested] 29+ messages in thread

* [Qemu-devel] [PATCH 01/19] fpu/softfloat: Merge NO_SIGNALING_NANS definitions
  2018-05-11  0:43 [Qemu-devel] [PATCH 00/19] softfloat: Clean up NaN handling Richard Henderson
@ 2018-05-11  0:43 ` Richard Henderson
  2018-05-11  6:44   ` Alex Bennée
  2018-05-11  0:43 ` [Qemu-devel] [PATCH 02/19] fpu/softfloat: Split floatXX_silence_nan from floatXX_maybe_silence_nan Richard Henderson
                   ` (17 subsequent siblings)
  18 siblings, 1 reply; 29+ messages in thread
From: Richard Henderson @ 2018-05-11  0:43 UTC (permalink / raw)
  To: qemu-devel; +Cc: peter.maydell, alex.bennee

Move the ifdef inside the relevant functions instead of
duplicating the function declarations.

Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
---
 fpu/softfloat-specialize.h | 100 +++++++++++++++----------------------
 1 file changed, 40 insertions(+), 60 deletions(-)

diff --git a/fpu/softfloat-specialize.h b/fpu/softfloat-specialize.h
index a20b440159..8bd553abd2 100644
--- a/fpu/softfloat-specialize.h
+++ b/fpu/softfloat-specialize.h
@@ -233,17 +233,6 @@ typedef struct {
     uint64_t high, low;
 } commonNaNT;
 
-#ifdef NO_SIGNALING_NANS
-int float16_is_quiet_nan(float16 a_, float_status *status)
-{
-    return float16_is_any_nan(a_);
-}
-
-int float16_is_signaling_nan(float16 a_, float_status *status)
-{
-    return 0;
-}
-#else
 /*----------------------------------------------------------------------------
 | Returns 1 if the half-precision floating-point value `a' is a quiet
 | NaN; otherwise returns 0.
@@ -251,12 +240,16 @@ int float16_is_signaling_nan(float16 a_, float_status *status)
 
 int float16_is_quiet_nan(float16 a_, float_status *status)
 {
+#ifdef NO_SIGNALING_NANS
+    return float16_is_any_nan(a_);
+#else
     uint16_t a = float16_val(a_);
     if (status->snan_bit_is_one) {
         return (((a >> 9) & 0x3F) == 0x3E) && (a & 0x1FF);
     } else {
         return ((a & ~0x8000) >= 0x7C80);
     }
+#endif
 }
 
 /*----------------------------------------------------------------------------
@@ -266,14 +259,17 @@ int float16_is_quiet_nan(float16 a_, float_status *status)
 
 int float16_is_signaling_nan(float16 a_, float_status *status)
 {
+#ifdef NO_SIGNALING_NANS
+    return 0;
+#else
     uint16_t a = float16_val(a_);
     if (status->snan_bit_is_one) {
         return ((a & ~0x8000) >= 0x7C80);
     } else {
         return (((a >> 9) & 0x3F) == 0x3E) && (a & 0x1FF);
     }
-}
 #endif
+}
 
 /*----------------------------------------------------------------------------
 | Returns a quiet NaN if the half-precision floating point value `a' is a
@@ -293,17 +289,6 @@ float16 float16_maybe_silence_nan(float16 a_, float_status *status)
     return a_;
 }
 
-#ifdef NO_SIGNALING_NANS
-int float32_is_quiet_nan(float32 a_, float_status *status)
-{
-    return float32_is_any_nan(a_);
-}
-
-int float32_is_signaling_nan(float32 a_, float_status *status)
-{
-    return 0;
-}
-#else
 /*----------------------------------------------------------------------------
 | Returns 1 if the single-precision floating-point value `a' is a quiet
 | NaN; otherwise returns 0.
@@ -311,12 +296,16 @@ int float32_is_signaling_nan(float32 a_, float_status *status)
 
 int float32_is_quiet_nan(float32 a_, float_status *status)
 {
+#ifdef NO_SIGNALING_NANS
+    return float32_is_any_nan(a_);
+#else
     uint32_t a = float32_val(a_);
     if (status->snan_bit_is_one) {
         return (((a >> 22) & 0x1FF) == 0x1FE) && (a & 0x003FFFFF);
     } else {
         return ((uint32_t)(a << 1) >= 0xFF800000);
     }
+#endif
 }
 
 /*----------------------------------------------------------------------------
@@ -326,14 +315,17 @@ int float32_is_quiet_nan(float32 a_, float_status *status)
 
 int float32_is_signaling_nan(float32 a_, float_status *status)
 {
+#ifdef NO_SIGNALING_NANS
+    return 0;
+#else
     uint32_t a = float32_val(a_);
     if (status->snan_bit_is_one) {
         return ((uint32_t)(a << 1) >= 0xFF800000);
     } else {
         return (((a >> 22) & 0x1FF) == 0x1FE) && (a & 0x003FFFFF);
     }
-}
 #endif
+}
 
 /*----------------------------------------------------------------------------
 | Returns a quiet NaN if the single-precision floating point value `a' is a
@@ -704,17 +696,6 @@ static float32 propagateFloat32NaN(float32 a, float32 b, float_status *status)
     }
 }
 
-#ifdef NO_SIGNALING_NANS
-int float64_is_quiet_nan(float64 a_, float_status *status)
-{
-    return float64_is_any_nan(a_);
-}
-
-int float64_is_signaling_nan(float64 a_, float_status *status)
-{
-    return 0;
-}
-#else
 /*----------------------------------------------------------------------------
 | Returns 1 if the double-precision floating-point value `a' is a quiet
 | NaN; otherwise returns 0.
@@ -722,6 +703,9 @@ int float64_is_signaling_nan(float64 a_, float_status *status)
 
 int float64_is_quiet_nan(float64 a_, float_status *status)
 {
+#ifdef NO_SIGNALING_NANS
+    return float64_is_any_nan(a_);
+#else
     uint64_t a = float64_val(a_);
     if (status->snan_bit_is_one) {
         return (((a >> 51) & 0xFFF) == 0xFFE)
@@ -729,6 +713,7 @@ int float64_is_quiet_nan(float64 a_, float_status *status)
     } else {
         return ((a << 1) >= 0xFFF0000000000000ULL);
     }
+#endif
 }
 
 /*----------------------------------------------------------------------------
@@ -738,6 +723,9 @@ int float64_is_quiet_nan(float64 a_, float_status *status)
 
 int float64_is_signaling_nan(float64 a_, float_status *status)
 {
+#ifdef NO_SIGNALING_NANS
+    return 0;
+#else
     uint64_t a = float64_val(a_);
     if (status->snan_bit_is_one) {
         return ((a << 1) >= 0xFFF0000000000000ULL);
@@ -745,8 +733,8 @@ int float64_is_signaling_nan(float64 a_, float_status *status)
         return (((a >> 51) & 0xFFF) == 0xFFE)
             && (a & LIT64(0x0007FFFFFFFFFFFF));
     }
-}
 #endif
+}
 
 /*----------------------------------------------------------------------------
 | Returns a quiet NaN if the double-precision floating point value `a' is a
@@ -859,17 +847,6 @@ static float64 propagateFloat64NaN(float64 a, float64 b, float_status *status)
     }
 }
 
-#ifdef NO_SIGNALING_NANS
-int floatx80_is_quiet_nan(floatx80 a_, float_status *status)
-{
-    return floatx80_is_any_nan(a_);
-}
-
-int floatx80_is_signaling_nan(floatx80 a_, float_status *status)
-{
-    return 0;
-}
-#else
 /*----------------------------------------------------------------------------
 | Returns 1 if the extended double-precision floating-point value `a' is a
 | quiet NaN; otherwise returns 0. This slightly differs from the same
@@ -878,6 +855,9 @@ int floatx80_is_signaling_nan(floatx80 a_, float_status *status)
 
 int floatx80_is_quiet_nan(floatx80 a, float_status *status)
 {
+#ifdef NO_SIGNALING_NANS
+    return floatx80_is_any_nan(a);
+#else
     if (status->snan_bit_is_one) {
         uint64_t aLow;
 
@@ -889,6 +869,7 @@ int floatx80_is_quiet_nan(floatx80 a, float_status *status)
         return ((a.high & 0x7FFF) == 0x7FFF)
             && (LIT64(0x8000000000000000) <= ((uint64_t)(a.low << 1)));
     }
+#endif
 }
 
 /*----------------------------------------------------------------------------
@@ -899,6 +880,9 @@ int floatx80_is_quiet_nan(floatx80 a, float_status *status)
 
 int floatx80_is_signaling_nan(floatx80 a, float_status *status)
 {
+#ifdef NO_SIGNALING_NANS
+    return 0;
+#else
     if (status->snan_bit_is_one) {
         return ((a.high & 0x7FFF) == 0x7FFF)
             && ((a.low << 1) >= 0x8000000000000000ULL);
@@ -910,8 +894,8 @@ int floatx80_is_signaling_nan(floatx80 a, float_status *status)
             && (uint64_t)(aLow << 1)
             && (a.low == aLow);
     }
-}
 #endif
+}
 
 /*----------------------------------------------------------------------------
 | Returns a quiet NaN if the extended double-precision floating point value
@@ -1020,17 +1004,6 @@ floatx80 propagateFloatx80NaN(floatx80 a, floatx80 b, float_status *status)
     }
 }
 
-#ifdef NO_SIGNALING_NANS
-int float128_is_quiet_nan(float128 a_, float_status *status)
-{
-    return float128_is_any_nan(a_);
-}
-
-int float128_is_signaling_nan(float128 a_, float_status *status)
-{
-    return 0;
-}
-#else
 /*----------------------------------------------------------------------------
 | Returns 1 if the quadruple-precision floating-point value `a' is a quiet
 | NaN; otherwise returns 0.
@@ -1038,6 +1011,9 @@ int float128_is_signaling_nan(float128 a_, float_status *status)
 
 int float128_is_quiet_nan(float128 a, float_status *status)
 {
+#ifdef NO_SIGNALING_NANS
+    return float128_is_any_nan(a);
+#else
     if (status->snan_bit_is_one) {
         return (((a.high >> 47) & 0xFFFF) == 0xFFFE)
             && (a.low || (a.high & 0x00007FFFFFFFFFFFULL));
@@ -1045,6 +1021,7 @@ int float128_is_quiet_nan(float128 a, float_status *status)
         return ((a.high << 1) >= 0xFFFF000000000000ULL)
             && (a.low || (a.high & 0x0000FFFFFFFFFFFFULL));
     }
+#endif
 }
 
 /*----------------------------------------------------------------------------
@@ -1054,6 +1031,9 @@ int float128_is_quiet_nan(float128 a, float_status *status)
 
 int float128_is_signaling_nan(float128 a, float_status *status)
 {
+#ifdef NO_SIGNALING_NANS
+    return 0;
+#else
     if (status->snan_bit_is_one) {
         return ((a.high << 1) >= 0xFFFF000000000000ULL)
             && (a.low || (a.high & 0x0000FFFFFFFFFFFFULL));
@@ -1061,8 +1041,8 @@ int float128_is_signaling_nan(float128 a, float_status *status)
         return (((a.high >> 47) & 0xFFFF) == 0xFFFE)
             && (a.low || (a.high & LIT64(0x00007FFFFFFFFFFF)));
     }
-}
 #endif
+}
 
 /*----------------------------------------------------------------------------
 | Returns a quiet NaN if the quadruple-precision floating point value `a' is
-- 
2.17.0

^ permalink raw reply related	[flat|nested] 29+ messages in thread

* [Qemu-devel] [PATCH 02/19] fpu/softfloat: Split floatXX_silence_nan from floatXX_maybe_silence_nan
  2018-05-11  0:43 [Qemu-devel] [PATCH 00/19] softfloat: Clean up NaN handling Richard Henderson
  2018-05-11  0:43 ` [Qemu-devel] [PATCH 01/19] fpu/softfloat: Merge NO_SIGNALING_NANS definitions Richard Henderson
@ 2018-05-11  0:43 ` Richard Henderson
  2018-05-11  7:47   ` Alex Bennée
  2018-05-11  0:43 ` [Qemu-devel] [PATCH 03/19] fpu/softfloat: Move softfloat-specialize.h below FloatParts definition Richard Henderson
                   ` (16 subsequent siblings)
  18 siblings, 1 reply; 29+ messages in thread
From: Richard Henderson @ 2018-05-11  0:43 UTC (permalink / raw)
  To: qemu-devel; +Cc: peter.maydell, alex.bennee

The new function assumes that the input is an SNaN and
does not double-check.

Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
---
 fpu/softfloat-specialize.h | 174 +++++++++++++++++++++++++------------
 include/fpu/softfloat.h    |   5 ++
 2 files changed, 123 insertions(+), 56 deletions(-)

diff --git a/fpu/softfloat-specialize.h b/fpu/softfloat-specialize.h
index 8bd553abd2..b59356f6a5 100644
--- a/fpu/softfloat-specialize.h
+++ b/fpu/softfloat-specialize.h
@@ -271,22 +271,35 @@ int float16_is_signaling_nan(float16 a_, float_status *status)
 #endif
 }
 
+/*----------------------------------------------------------------------------
+| Returns a quiet NaN from a signalling NaN for the half-precision
+| floating point value `a'.
+*----------------------------------------------------------------------------*/
+
+float16 float16_silence_nan(float16 a, float_status *status)
+{
+#ifdef NO_SIGNALING_NANS
+    g_assert_not_reached();
+#else
+    if (status->snan_bit_is_one) {
+        return float16_default_nan(status);
+    } else {
+        return a | (1 << 9);
+    }
+#endif
+}
+
 /*----------------------------------------------------------------------------
 | Returns a quiet NaN if the half-precision floating point value `a' is a
 | signaling NaN; otherwise returns `a'.
 *----------------------------------------------------------------------------*/
-float16 float16_maybe_silence_nan(float16 a_, float_status *status)
+
+float16 float16_maybe_silence_nan(float16 a, float_status *status)
 {
-    if (float16_is_signaling_nan(a_, status)) {
-        if (status->snan_bit_is_one) {
-            return float16_default_nan(status);
-        } else {
-            uint16_t a = float16_val(a_);
-            a |= (1 << 9);
-            return make_float16(a);
-        }
+    if (float16_is_signaling_nan(a, status)) {
+        float16_silence_nan(a, status);
     }
-    return a_;
+    return a;
 }
 
 /*----------------------------------------------------------------------------
@@ -327,30 +340,40 @@ int float32_is_signaling_nan(float32 a_, float_status *status)
 #endif
 }
 
+/*----------------------------------------------------------------------------
+| Returns a quiet NaN from a signalling NaN for the single-precision
+| floating point value `a'.
+*----------------------------------------------------------------------------*/
+
+float32 float32_silence_nan(float32 a, float_status *status)
+{
+#ifdef NO_SIGNALING_NANS
+    g_assert_not_reached();
+#else
+    if (status->snan_bit_is_one) {
+# ifdef TARGET_HPPA
+        a &= ~0x00400000;
+        a |=  0x00200000;
+        return a;
+# else
+        return float32_default_nan(status);
+# endif
+    } else {
+        return a | (1 << 22);
+    }
+#endif
+}
 /*----------------------------------------------------------------------------
 | Returns a quiet NaN if the single-precision floating point value `a' is a
 | signaling NaN; otherwise returns `a'.
 *----------------------------------------------------------------------------*/
 
-float32 float32_maybe_silence_nan(float32 a_, float_status *status)
+float32 float32_maybe_silence_nan(float32 a, float_status *status)
 {
-    if (float32_is_signaling_nan(a_, status)) {
-        if (status->snan_bit_is_one) {
-#ifdef TARGET_HPPA
-            uint32_t a = float32_val(a_);
-            a &= ~0x00400000;
-            a |=  0x00200000;
-            return make_float32(a);
-#else
-            return float32_default_nan(status);
-#endif
-        } else {
-            uint32_t a = float32_val(a_);
-            a |= (1 << 22);
-            return make_float32(a);
-        }
+    if (float32_is_signaling_nan(a, status)) {
+        float32_silence_nan(a, status);
     }
-    return a_;
+    return a;
 }
 
 /*----------------------------------------------------------------------------
@@ -736,30 +759,41 @@ int float64_is_signaling_nan(float64 a_, float_status *status)
 #endif
 }
 
+/*----------------------------------------------------------------------------
+| Returns a quiet NaN from a signalling NaN for the double-precision
+| floating point value `a'.
+*----------------------------------------------------------------------------*/
+
+float64 float64_silence_nan(float64 a, float_status *status)
+{
+#ifdef NO_SIGNALING_NANS
+    g_assert_not_reached();
+#else
+    if (status->snan_bit_is_one) {
+# ifdef TARGET_HPPA
+        a &= ~0x0008000000000000ULL;
+        a |=  0x0004000000000000ULL;
+        return a;
+# else
+        return float64_default_nan(status);
+# endif
+    } else {
+        return a | LIT64(0x0008000000000000);
+    }
+#endif
+}
+
 /*----------------------------------------------------------------------------
 | Returns a quiet NaN if the double-precision floating point value `a' is a
 | signaling NaN; otherwise returns `a'.
 *----------------------------------------------------------------------------*/
 
-float64 float64_maybe_silence_nan(float64 a_, float_status *status)
+float64 float64_maybe_silence_nan(float64 a, float_status *status)
 {
-    if (float64_is_signaling_nan(a_, status)) {
-        if (status->snan_bit_is_one) {
-#ifdef TARGET_HPPA
-            uint64_t a = float64_val(a_);
-            a &= ~0x0008000000000000ULL;
-            a |=  0x0004000000000000ULL;
-            return make_float64(a);
-#else
-            return float64_default_nan(status);
-#endif
-        } else {
-            uint64_t a = float64_val(a_);
-            a |= LIT64(0x0008000000000000);
-            return make_float64(a);
-        }
+    if (float64_is_signaling_nan(a, status)) {
+        return float64_silence_nan(a, status);
     }
-    return a_;
+    return a;
 }
 
 /*----------------------------------------------------------------------------
@@ -897,6 +931,25 @@ int floatx80_is_signaling_nan(floatx80 a, float_status *status)
 #endif
 }
 
+/*----------------------------------------------------------------------------
+| Returns a quiet NaN from a signalling NaN for the extended double-precision
+| floating point value `a'.
+*----------------------------------------------------------------------------*/
+
+floatx80 floatx80_silence_nan(floatx80 a, float_status *status)
+{
+#ifdef NO_SIGNALING_NANS
+    g_assert_not_reached();
+#else
+    if (status->snan_bit_is_one) {
+        return floatx80_default_nan(status);
+    } else {
+        a.low |= LIT64(0xC000000000000000);
+        return a;
+    }
+#endif
+}
+
 /*----------------------------------------------------------------------------
 | Returns a quiet NaN if the extended double-precision floating point value
 | `a' is a signaling NaN; otherwise returns `a'.
@@ -905,12 +958,7 @@ int floatx80_is_signaling_nan(floatx80 a, float_status *status)
 floatx80 floatx80_maybe_silence_nan(floatx80 a, float_status *status)
 {
     if (floatx80_is_signaling_nan(a, status)) {
-        if (status->snan_bit_is_one) {
-            a = floatx80_default_nan(status);
-        } else {
-            a.low |= LIT64(0xC000000000000000);
-            return a;
-        }
+        return floatx80_silence_nan(a, status);
     }
     return a;
 }
@@ -1044,6 +1092,25 @@ int float128_is_signaling_nan(float128 a, float_status *status)
 #endif
 }
 
+/*----------------------------------------------------------------------------
+| Returns a quiet NaN from a signalling NaN for the quadruple-precision
+| floating point value `a'.
+*----------------------------------------------------------------------------*/
+
+float128 float128_silence_nan(float128 a, float_status *status)
+{
+#ifdef NO_SIGNALING_NANS
+    g_assert_not_reached();
+#else
+    if (status->snan_bit_is_one) {
+        return float128_default_nan(status);
+    } else {
+        a.high |= LIT64(0x0000800000000000);
+        return a;
+    }
+#endif
+}
+
 /*----------------------------------------------------------------------------
 | Returns a quiet NaN if the quadruple-precision floating point value `a' is
 | a signaling NaN; otherwise returns `a'.
@@ -1052,12 +1119,7 @@ int float128_is_signaling_nan(float128 a, float_status *status)
 float128 float128_maybe_silence_nan(float128 a, float_status *status)
 {
     if (float128_is_signaling_nan(a, status)) {
-        if (status->snan_bit_is_one) {
-            a = float128_default_nan(status);
-        } else {
-            a.high |= LIT64(0x0000800000000000);
-            return a;
-        }
+        return float128_silence_nan(a, status);
     }
     return a;
 }
diff --git a/include/fpu/softfloat.h b/include/fpu/softfloat.h
index 01ef1c6b81..a6860e858d 100644
--- a/include/fpu/softfloat.h
+++ b/include/fpu/softfloat.h
@@ -257,6 +257,7 @@ int float16_compare_quiet(float16, float16, float_status *status);
 
 int float16_is_quiet_nan(float16, float_status *status);
 int float16_is_signaling_nan(float16, float_status *status);
+float16 float16_silence_nan(float16, float_status *status);
 float16 float16_maybe_silence_nan(float16, float_status *status);
 
 static inline int float16_is_any_nan(float16 a)
@@ -368,6 +369,7 @@ float32 float32_minnummag(float32, float32, float_status *status);
 float32 float32_maxnummag(float32, float32, float_status *status);
 int float32_is_quiet_nan(float32, float_status *status);
 int float32_is_signaling_nan(float32, float_status *status);
+float32 float32_silence_nan(float32, float_status *status);
 float32 float32_maybe_silence_nan(float32, float_status *status);
 float32 float32_scalbn(float32, int, float_status *status);
 
@@ -497,6 +499,7 @@ float64 float64_minnummag(float64, float64, float_status *status);
 float64 float64_maxnummag(float64, float64, float_status *status);
 int float64_is_quiet_nan(float64 a, float_status *status);
 int float64_is_signaling_nan(float64, float_status *status);
+float64 float64_silence_nan(float64, float_status *status);
 float64 float64_maybe_silence_nan(float64, float_status *status);
 float64 float64_scalbn(float64, int, float_status *status);
 
@@ -600,6 +603,7 @@ int floatx80_compare(floatx80, floatx80, float_status *status);
 int floatx80_compare_quiet(floatx80, floatx80, float_status *status);
 int floatx80_is_quiet_nan(floatx80, float_status *status);
 int floatx80_is_signaling_nan(floatx80, float_status *status);
+floatx80 floatx80_silence_nan(floatx80, float_status *status);
 floatx80 floatx80_maybe_silence_nan(floatx80, float_status *status);
 floatx80 floatx80_scalbn(floatx80, int, float_status *status);
 
@@ -811,6 +815,7 @@ int float128_compare(float128, float128, float_status *status);
 int float128_compare_quiet(float128, float128, float_status *status);
 int float128_is_quiet_nan(float128, float_status *status);
 int float128_is_signaling_nan(float128, float_status *status);
+float128 float128_silence_nan(float128, float_status *status);
 float128 float128_maybe_silence_nan(float128, float_status *status);
 float128 float128_scalbn(float128, int, float_status *status);
 
-- 
2.17.0

^ permalink raw reply related	[flat|nested] 29+ messages in thread

* [Qemu-devel] [PATCH 03/19] fpu/softfloat: Move softfloat-specialize.h below FloatParts definition
  2018-05-11  0:43 [Qemu-devel] [PATCH 00/19] softfloat: Clean up NaN handling Richard Henderson
  2018-05-11  0:43 ` [Qemu-devel] [PATCH 01/19] fpu/softfloat: Merge NO_SIGNALING_NANS definitions Richard Henderson
  2018-05-11  0:43 ` [Qemu-devel] [PATCH 02/19] fpu/softfloat: Split floatXX_silence_nan from floatXX_maybe_silence_nan Richard Henderson
@ 2018-05-11  0:43 ` Richard Henderson
  2018-05-11  7:48   ` Alex Bennée
  2018-05-11  0:43 ` [Qemu-devel] [PATCH 04/19] fpu/softfloat: Canonicalize NaN fraction Richard Henderson
                   ` (15 subsequent siblings)
  18 siblings, 1 reply; 29+ messages in thread
From: Richard Henderson @ 2018-05-11  0:43 UTC (permalink / raw)
  To: qemu-devel; +Cc: peter.maydell, alex.bennee

We want to be able to specialize on the canonical representation.

Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
---
 fpu/softfloat.c | 20 ++++++++++----------
 1 file changed, 10 insertions(+), 10 deletions(-)

diff --git a/fpu/softfloat.c b/fpu/softfloat.c
index e7c8213a5e..5e4982b035 100644
--- a/fpu/softfloat.c
+++ b/fpu/softfloat.c
@@ -95,16 +95,6 @@ this code that are retained.
 *----------------------------------------------------------------------------*/
 #include "fpu/softfloat-macros.h"
 
-/*----------------------------------------------------------------------------
-| Functions and definitions to determine:  (1) whether tininess for underflow
-| is detected before or after rounding by default, (2) what (if anything)
-| happens when exceptions are raised, (3) how signaling NaNs are distinguished
-| from quiet NaNs, (4) the default generated quiet NaNs, and (5) how NaNs
-| are propagated from function inputs to output.  These details are target-
-| specific.
-*----------------------------------------------------------------------------*/
-#include "softfloat-specialize.h"
-
 /*----------------------------------------------------------------------------
 | Returns the fraction bits of the half-precision floating-point value `a'.
 *----------------------------------------------------------------------------*/
@@ -241,6 +231,16 @@ typedef struct {
     bool arm_althp;
 } FloatFmt;
 
+/*----------------------------------------------------------------------------
+| Functions and definitions to determine:  (1) whether tininess for underflow
+| is detected before or after rounding by default, (2) what (if anything)
+| happens when exceptions are raised, (3) how signaling NaNs are distinguished
+| from quiet NaNs, (4) the default generated quiet NaNs, and (5) how NaNs
+| are propagated from function inputs to output.  These details are target-
+| specific.
+*----------------------------------------------------------------------------*/
+#include "softfloat-specialize.h"
+
 /* Expand fields based on the size of exponent and fraction */
 #define FLOAT_PARAMS(E, F)                                           \
     .exp_size       = E,                                             \
-- 
2.17.0

^ permalink raw reply related	[flat|nested] 29+ messages in thread

* [Qemu-devel] [PATCH 04/19] fpu/softfloat: Canonicalize NaN fraction
  2018-05-11  0:43 [Qemu-devel] [PATCH 00/19] softfloat: Clean up NaN handling Richard Henderson
                   ` (2 preceding siblings ...)
  2018-05-11  0:43 ` [Qemu-devel] [PATCH 03/19] fpu/softfloat: Move softfloat-specialize.h below FloatParts definition Richard Henderson
@ 2018-05-11  0:43 ` Richard Henderson
  2018-05-11 16:26   ` Alex Bennée
  2018-05-11  0:43 ` [Qemu-devel] [PATCH 05/19] fpu/softfloat: Introduce parts_is_snan_frac Richard Henderson
                   ` (14 subsequent siblings)
  18 siblings, 1 reply; 29+ messages in thread
From: Richard Henderson @ 2018-05-11  0:43 UTC (permalink / raw)
  To: qemu-devel; +Cc: peter.maydell, alex.bennee

Shift the NaN fraction to a canonical position, much like we do
for the fraction of normal numbers.  Immediately, this simplifies
the float-to-float conversion.  Later, this will facilitate
manipulation of NaNs within the shared code paths.

Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
---
 fpu/softfloat.c | 13 ++++++-------
 1 file changed, 6 insertions(+), 7 deletions(-)

diff --git a/fpu/softfloat.c b/fpu/softfloat.c
index 5e4982b035..df377b6314 100644
--- a/fpu/softfloat.c
+++ b/fpu/softfloat.c
@@ -329,10 +329,11 @@ static FloatParts canonicalize(FloatParts part, const FloatFmt *parm,
         if (part.frac == 0) {
             part.cls = float_class_inf;
         } else {
+            part.frac <<= parm->frac_shift;
 #ifdef NO_SIGNALING_NANS
             part.cls = float_class_qnan;
 #else
-            int64_t msb = part.frac << (parm->frac_shift + 2);
+            int64_t msb = part.frac << 2;
             if ((msb < 0) == status->snan_bit_is_one) {
                 part.cls = float_class_snan;
             } else {
@@ -498,6 +499,7 @@ static FloatParts round_canonical(FloatParts p, float_status *s,
     case float_class_qnan:
     case float_class_snan:
         exp = exp_max;
+        frac >>= parm->frac_shift;
         break;
 
     default:
@@ -1264,13 +1266,10 @@ static FloatParts float_to_float(FloatParts a,
         }
 
         /*
-         * Our only option now is to "re-pack" the NaN. As the
-         * canonilization process doesn't mess with fraction bits for
-         * NaNs we do it all here. We also reset a.exp to the
-         * destination format exp_max as the maybe_silence_nan code
-         * assumes it is correct (which is would be for non-conversions).
+         * Reset a.exp to the destination format exp_max as
+         * the maybe_silence_nan code assumes it is correct
+         * (which it would be for non-conversions).
          */
-        a.frac = a.frac << (64 - srcf->frac_size) >> (64 - dstf->frac_size);
         a.exp = dstf->exp_max;
         a.cls = float_class_msnan;
     }
-- 
2.17.0

^ permalink raw reply related	[flat|nested] 29+ messages in thread

* [Qemu-devel] [PATCH 05/19] fpu/softfloat: Introduce parts_is_snan_frac
  2018-05-11  0:43 [Qemu-devel] [PATCH 00/19] softfloat: Clean up NaN handling Richard Henderson
                   ` (3 preceding siblings ...)
  2018-05-11  0:43 ` [Qemu-devel] [PATCH 04/19] fpu/softfloat: Canonicalize NaN fraction Richard Henderson
@ 2018-05-11  0:43 ` Richard Henderson
  2018-05-11  0:43 ` [Qemu-devel] [PATCH 06/19] fpu/softfloat: Replace float_class_dnan with parts_default_nan Richard Henderson
                   ` (13 subsequent siblings)
  18 siblings, 0 replies; 29+ messages in thread
From: Richard Henderson @ 2018-05-11  0:43 UTC (permalink / raw)
  To: qemu-devel; +Cc: peter.maydell, alex.bennee

Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
---
 fpu/softfloat-specialize.h | 15 +++++++++++++++
 fpu/softfloat.c            | 12 ++----------
 2 files changed, 17 insertions(+), 10 deletions(-)

diff --git a/fpu/softfloat-specialize.h b/fpu/softfloat-specialize.h
index b59356f6a5..82d7a030e7 100644
--- a/fpu/softfloat-specialize.h
+++ b/fpu/softfloat-specialize.h
@@ -86,6 +86,21 @@ this code that are retained.
 #define NO_SIGNALING_NANS 1
 #endif
 
+/*----------------------------------------------------------------------------
+| For the deconstructed floating-point with fraction FRAC, return true
+| if the fraction represents a signalling NaN; otherwise false.
+*----------------------------------------------------------------------------*/
+
+static bool parts_is_snan_frac(uint64_t frac, float_status *status)
+{
+#ifdef NO_SIGNALING_NANS
+    return false;
+#else
+    flag msb = extract64(frac, DECOMPOSED_BINARY_POINT - 1, 1);
+    return msb == status->snan_bit_is_one;
+#endif
+}
+
 /*----------------------------------------------------------------------------
 | The pattern for a default generated half-precision NaN.
 *----------------------------------------------------------------------------*/
diff --git a/fpu/softfloat.c b/fpu/softfloat.c
index df377b6314..6dfc992a7f 100644
--- a/fpu/softfloat.c
+++ b/fpu/softfloat.c
@@ -330,16 +330,8 @@ static FloatParts canonicalize(FloatParts part, const FloatFmt *parm,
             part.cls = float_class_inf;
         } else {
             part.frac <<= parm->frac_shift;
-#ifdef NO_SIGNALING_NANS
-            part.cls = float_class_qnan;
-#else
-            int64_t msb = part.frac << 2;
-            if ((msb < 0) == status->snan_bit_is_one) {
-                part.cls = float_class_snan;
-            } else {
-                part.cls = float_class_qnan;
-            }
-#endif
+            part.cls = (parts_is_snan_frac(part.frac, status)
+                        ? float_class_snan : float_class_qnan);
         }
     } else if (part.exp == 0) {
         if (likely(part.frac == 0)) {
-- 
2.17.0

^ permalink raw reply related	[flat|nested] 29+ messages in thread

* [Qemu-devel] [PATCH 06/19] fpu/softfloat: Replace float_class_dnan with parts_default_nan
  2018-05-11  0:43 [Qemu-devel] [PATCH 00/19] softfloat: Clean up NaN handling Richard Henderson
                   ` (4 preceding siblings ...)
  2018-05-11  0:43 ` [Qemu-devel] [PATCH 05/19] fpu/softfloat: Introduce parts_is_snan_frac Richard Henderson
@ 2018-05-11  0:43 ` Richard Henderson
  2018-05-11  0:43 ` [Qemu-devel] [PATCH 07/19] fpu/softfloat: Replace float_class_msnan with parts_silence_nan Richard Henderson
                   ` (12 subsequent siblings)
  18 siblings, 0 replies; 29+ messages in thread
From: Richard Henderson @ 2018-05-11  0:43 UTC (permalink / raw)
  To: qemu-devel; +Cc: peter.maydell, alex.bennee

With a canonical representation of NaNs, we can return the
default nan directly rather than delay the expansion until
the final format is known.

Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
---
 fpu/softfloat-specialize.h | 37 +++++++++++++++++++++++++++++++++++++
 fpu/softfloat.c            | 38 ++++++++++++--------------------------
 2 files changed, 49 insertions(+), 26 deletions(-)

diff --git a/fpu/softfloat-specialize.h b/fpu/softfloat-specialize.h
index 82d7a030e7..2ad524b11e 100644
--- a/fpu/softfloat-specialize.h
+++ b/fpu/softfloat-specialize.h
@@ -101,6 +101,43 @@ static bool parts_is_snan_frac(uint64_t frac, float_status *status)
 #endif
 }
 
+/*----------------------------------------------------------------------------
+| The pattern for a default generated deconstructed floating-point NaN.
+*----------------------------------------------------------------------------*/
+
+static FloatParts parts_default_nan(float_status *status)
+{
+    bool sign = 0;
+    uint64_t frac;
+
+#if defined(TARGET_SPARC) || defined(TARGET_M68K)
+    frac = (1ULL << DECOMPOSED_BINARY_POINT) - 1;
+#elif defined(TARGET_PPC) || defined(TARGET_ARM) || defined(TARGET_ALPHA) || \
+      defined(TARGET_S390X) || defined(TARGET_RISCV)
+    frac = 1ULL << (DECOMPOSED_BINARY_POINT - 1);
+#elif defined(TARGET_HPPA)
+    frac = 1ULL << (DECOMPOSED_BINARY_POINT - 2);
+#else
+    if (status->snan_bit_is_one) {
+        frac = (1ULL << (DECOMPOSED_BINARY_POINT - 1)) - 1;
+    } else {
+#if defined(TARGET_MIPS)
+        frac = 1ULL << (DECOMPOSED_BINARY_POINT - 1);
+#else
+        frac = 1ULL << (DECOMPOSED_BINARY_POINT - 1);
+        sign = 1;
+#endif
+    }
+#endif
+
+    return (FloatParts) {
+        .cls = float_class_qnan,
+        .sign = sign,
+        .exp = INT_MAX,
+        .frac = frac
+    };
+}
+
 /*----------------------------------------------------------------------------
 | The pattern for a default generated half-precision NaN.
 *----------------------------------------------------------------------------*/
diff --git a/fpu/softfloat.c b/fpu/softfloat.c
index 6dfc992a7f..01036b158e 100644
--- a/fpu/softfloat.c
+++ b/fpu/softfloat.c
@@ -179,7 +179,6 @@ typedef enum __attribute__ ((__packed__)) {
     float_class_inf,
     float_class_qnan,  /* all NaNs from here */
     float_class_snan,
-    float_class_dnan,
     float_class_msnan, /* maybe silenced */
 } FloatClass;
 
@@ -521,8 +520,6 @@ static float16 float16a_round_pack_canonical(const FloatFmt *params,
                                              FloatParts p, float_status *s)
 {
     switch (p.cls) {
-    case float_class_dnan:
-        return float16_default_nan(s);
     case float_class_msnan:
         return float16_maybe_silence_nan(float16_pack_raw(p), s);
     default:
@@ -544,8 +541,6 @@ static FloatParts float32_unpack_canonical(float32 f, float_status *s)
 static float32 float32_round_pack_canonical(FloatParts p, float_status *s)
 {
     switch (p.cls) {
-    case float_class_dnan:
-        return float32_default_nan(s);
     case float_class_msnan:
         return float32_maybe_silence_nan(float32_pack_raw(p), s);
     default:
@@ -562,8 +557,6 @@ static FloatParts float64_unpack_canonical(float64 f, float_status *s)
 static float64 float64_round_pack_canonical(FloatParts p, float_status *s)
 {
     switch (p.cls) {
-    case float_class_dnan:
-        return float64_default_nan(s);
     case float_class_msnan:
         return float64_maybe_silence_nan(float64_pack_raw(p), s);
     default:
@@ -595,7 +588,7 @@ static FloatParts return_nan(FloatParts a, float_status *s)
         /* fall through */
     case float_class_qnan:
         if (s->default_nan_mode) {
-            a.cls = float_class_dnan;
+            return parts_default_nan(s);
         }
         break;
 
@@ -612,7 +605,7 @@ static FloatParts pick_nan(FloatParts a, FloatParts b, float_status *s)
     }
 
     if (s->default_nan_mode) {
-        a.cls = float_class_dnan;
+        return parts_default_nan(s);
     } else {
         if (pickNaN(is_qnan(a.cls), is_snan(a.cls),
                     is_qnan(b.cls), is_snan(b.cls),
@@ -633,7 +626,7 @@ static FloatParts pick_nan_muladd(FloatParts a, FloatParts b, FloatParts c,
     }
 
     if (s->default_nan_mode) {
-        a.cls = float_class_dnan;
+        return parts_default_nan(s);
     } else {
         switch (pickNaNMulAdd(is_qnan(a.cls), is_snan(a.cls),
                               is_qnan(b.cls), is_snan(b.cls),
@@ -648,8 +641,7 @@ static FloatParts pick_nan_muladd(FloatParts a, FloatParts b, FloatParts c,
             a = c;
             break;
         case 3:
-            a.cls = float_class_dnan;
-            return a;
+            return parts_default_nan(s);
         default:
             g_assert_not_reached();
         }
@@ -703,7 +695,7 @@ static FloatParts addsub_floats(FloatParts a, FloatParts b, bool subtract,
         if (a.cls == float_class_inf) {
             if (b.cls == float_class_inf) {
                 float_raise(float_flag_invalid, s);
-                a.cls = float_class_dnan;
+                return parts_default_nan(s);
             }
             return a;
         }
@@ -849,7 +841,7 @@ static FloatParts mul_floats(FloatParts a, FloatParts b, float_status *s)
     if ((a.cls == float_class_inf && b.cls == float_class_zero) ||
         (a.cls == float_class_zero && b.cls == float_class_inf)) {
         s->float_exception_flags |= float_flag_invalid;
-        a.cls = float_class_dnan;
+        a = parts_default_nan(s);
         a.sign = sign;
         return a;
     }
@@ -929,8 +921,7 @@ static FloatParts muladd_floats(FloatParts a, FloatParts b, FloatParts c,
 
     if (inf_zero) {
         s->float_exception_flags |= float_flag_invalid;
-        a.cls = float_class_dnan;
-        return a;
+        return parts_default_nan(s);
     }
 
     if (flags & float_muladd_negate_c) {
@@ -954,12 +945,12 @@ static FloatParts muladd_floats(FloatParts a, FloatParts b, FloatParts c,
     if (c.cls == float_class_inf) {
         if (p_class == float_class_inf && p_sign != c.sign) {
             s->float_exception_flags |= float_flag_invalid;
-            a.cls = float_class_dnan;
+            return parts_default_nan(s);
         } else {
             a.cls = float_class_inf;
             a.sign = c.sign ^ sign_flip;
+            return a;
         }
-        return a;
     }
 
     if (p_class == float_class_inf) {
@@ -1169,8 +1160,7 @@ static FloatParts div_floats(FloatParts a, FloatParts b, float_status *s)
         &&
         (a.cls == float_class_inf || a.cls == float_class_zero)) {
         s->float_exception_flags |= float_flag_invalid;
-        a.cls = float_class_dnan;
-        return a;
+        return parts_default_nan(s);
     }
     /* Inf / x or 0 / x */
     if (a.cls == float_class_inf || a.cls == float_class_zero) {
@@ -1253,8 +1243,7 @@ static FloatParts float_to_float(FloatParts a,
         }
 
         if (s->default_nan_mode) {
-            a.cls = float_class_dnan;
-            return a;
+            return parts_default_nan(s);
         }
 
         /*
@@ -1470,7 +1459,6 @@ static int64_t round_to_int_and_pack(FloatParts in, int rmode,
     switch (p.cls) {
     case float_class_snan:
     case float_class_qnan:
-    case float_class_dnan:
     case float_class_msnan:
         s->float_exception_flags = orig_flags | float_flag_invalid;
         return max;
@@ -1562,7 +1550,6 @@ static uint64_t round_to_uint_and_pack(FloatParts in, int rmode, uint64_t max,
     switch (p.cls) {
     case float_class_snan:
     case float_class_qnan:
-    case float_class_dnan:
     case float_class_msnan:
         s->float_exception_flags = orig_flags | float_flag_invalid;
         return max;
@@ -2063,8 +2050,7 @@ static FloatParts sqrt_float(FloatParts a, float_status *s, const FloatFmt *p)
     }
     if (a.sign) {
         s->float_exception_flags |= float_flag_invalid;
-        a.cls = float_class_dnan;
-        return a;
+        return parts_default_nan(s);
     }
     if (a.cls == float_class_inf) {
         return a;  /* sqrt(+inf) = +inf */
-- 
2.17.0

^ permalink raw reply related	[flat|nested] 29+ messages in thread

* [Qemu-devel] [PATCH 07/19] fpu/softfloat: Replace float_class_msnan with parts_silence_nan
  2018-05-11  0:43 [Qemu-devel] [PATCH 00/19] softfloat: Clean up NaN handling Richard Henderson
                   ` (5 preceding siblings ...)
  2018-05-11  0:43 ` [Qemu-devel] [PATCH 06/19] fpu/softfloat: Replace float_class_dnan with parts_default_nan Richard Henderson
@ 2018-05-11  0:43 ` Richard Henderson
  2018-05-11  0:43 ` [Qemu-devel] [PATCH 08/19] target/arm: Use floatX_silence_nan when we have already checked for SNaN Richard Henderson
                   ` (11 subsequent siblings)
  18 siblings, 0 replies; 29+ messages in thread
From: Richard Henderson @ 2018-05-11  0:43 UTC (permalink / raw)
  To: qemu-devel; +Cc: peter.maydell, alex.bennee

With a canonical representation of NaNs, we can silence an SNaN
immediately rather than delay until the final format is known.

Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
---
 fpu/softfloat-specialize.h | 23 +++++++++++++++++
 fpu/softfloat.c            | 51 +++++++++++---------------------------
 2 files changed, 38 insertions(+), 36 deletions(-)

diff --git a/fpu/softfloat-specialize.h b/fpu/softfloat-specialize.h
index 2ad524b11e..53a4f45a8c 100644
--- a/fpu/softfloat-specialize.h
+++ b/fpu/softfloat-specialize.h
@@ -138,6 +138,29 @@ static FloatParts parts_default_nan(float_status *status)
     };
 }
 
+/*----------------------------------------------------------------------------
+| Returns a quiet NaN from a signalling NaN for the deconstructed
+| floating-point parts.
+*----------------------------------------------------------------------------*/
+
+static FloatParts parts_silence_nan(FloatParts a, float_status *status)
+{
+#ifdef NO_SIGNALING_NANS
+    g_assert_not_reached();
+#elif defined(TARGET_HPPA)
+    a.frac &= ~(1ULL << (DECOMPOSED_BINARY_POINT - 1));
+    a.frac |= 1ULL << (DECOMPOSED_BINARY_POINT - 2);
+#else
+    if (status->snan_bit_is_one) {
+        return parts_default_nan(status);
+    } else {
+        a.frac |= 1ULL << (DECOMPOSED_BINARY_POINT - 1);
+    }
+#endif
+    a.cls = float_class_qnan;
+    return a;
+}
+
 /*----------------------------------------------------------------------------
 | The pattern for a default generated half-precision NaN.
 *----------------------------------------------------------------------------*/
diff --git a/fpu/softfloat.c b/fpu/softfloat.c
index 01036b158e..cce94136d4 100644
--- a/fpu/softfloat.c
+++ b/fpu/softfloat.c
@@ -179,7 +179,6 @@ typedef enum __attribute__ ((__packed__)) {
     float_class_inf,
     float_class_qnan,  /* all NaNs from here */
     float_class_snan,
-    float_class_msnan, /* maybe silenced */
 } FloatClass;
 
 /*
@@ -519,13 +518,7 @@ static FloatParts float16_unpack_canonical(float16 f, float_status *s)
 static float16 float16a_round_pack_canonical(const FloatFmt *params,
                                              FloatParts p, float_status *s)
 {
-    switch (p.cls) {
-    case float_class_msnan:
-        return float16_maybe_silence_nan(float16_pack_raw(p), s);
-    default:
-        p = round_canonical(p, s, params);
-        return float16_pack_raw(p);
-    }
+    return float16_pack_raw(round_canonical(p, s, params));
 }
 
 static float16 float16_round_pack_canonical(FloatParts p, float_status *s)
@@ -540,13 +533,7 @@ static FloatParts float32_unpack_canonical(float32 f, float_status *s)
 
 static float32 float32_round_pack_canonical(FloatParts p, float_status *s)
 {
-    switch (p.cls) {
-    case float_class_msnan:
-        return float32_maybe_silence_nan(float32_pack_raw(p), s);
-    default:
-        p = round_canonical(p, s, &float32_params);
-        return float32_pack_raw(p);
-    }
+    return float32_pack_raw(round_canonical(p, s, &float32_params));
 }
 
 static FloatParts float64_unpack_canonical(float64 f, float_status *s)
@@ -556,13 +543,7 @@ static FloatParts float64_unpack_canonical(float64 f, float_status *s)
 
 static float64 float64_round_pack_canonical(FloatParts p, float_status *s)
 {
-    switch (p.cls) {
-    case float_class_msnan:
-        return float64_maybe_silence_nan(float64_pack_raw(p), s);
-    default:
-        p = round_canonical(p, s, &float64_params);
-        return float64_pack_raw(p);
-    }
+    return float64_pack_raw(round_canonical(p, s, &float64_params));
 }
 
 /* Simple helpers for checking if what NaN we have */
@@ -570,10 +551,12 @@ static bool is_nan(FloatClass c)
 {
     return unlikely(c >= float_class_qnan);
 }
+
 static bool is_snan(FloatClass c)
 {
     return c == float_class_snan;
 }
+
 static bool is_qnan(FloatClass c)
 {
     return c == float_class_qnan;
@@ -584,7 +567,7 @@ static FloatParts return_nan(FloatParts a, float_status *s)
     switch (a.cls) {
     case float_class_snan:
         s->float_exception_flags |= float_flag_invalid;
-        a.cls = float_class_msnan;
+        a = parts_silence_nan(a, s);
         /* fall through */
     case float_class_qnan:
         if (s->default_nan_mode) {
@@ -613,7 +596,9 @@ static FloatParts pick_nan(FloatParts a, FloatParts b, float_status *s)
                     (a.frac == b.frac && a.sign < b.sign))) {
             a = b;
         }
-        a.cls = float_class_msnan;
+        if (is_snan(a.cls)) {
+            return parts_silence_nan(a, s);
+        }
     }
     return a;
 }
@@ -645,8 +630,9 @@ static FloatParts pick_nan_muladd(FloatParts a, FloatParts b, FloatParts c,
         default:
             g_assert_not_reached();
         }
-
-        a.cls = float_class_msnan;
+        if (is_snan(a.cls)) {
+            return parts_silence_nan(a, s);
+        }
     }
     return a;
 }
@@ -1245,14 +1231,9 @@ static FloatParts float_to_float(FloatParts a,
         if (s->default_nan_mode) {
             return parts_default_nan(s);
         }
-
-        /*
-         * Reset a.exp to the destination format exp_max as
-         * the maybe_silence_nan code assumes it is correct
-         * (which it would be for non-conversions).
-         */
-        a.exp = dstf->exp_max;
-        a.cls = float_class_msnan;
+        if (is_snan(a.cls)) {
+            return parts_silence_nan(a, s);
+        }
     }
 
     return a;
@@ -1459,7 +1440,6 @@ static int64_t round_to_int_and_pack(FloatParts in, int rmode,
     switch (p.cls) {
     case float_class_snan:
     case float_class_qnan:
-    case float_class_msnan:
         s->float_exception_flags = orig_flags | float_flag_invalid;
         return max;
     case float_class_inf:
@@ -1550,7 +1530,6 @@ static uint64_t round_to_uint_and_pack(FloatParts in, int rmode, uint64_t max,
     switch (p.cls) {
     case float_class_snan:
     case float_class_qnan:
-    case float_class_msnan:
         s->float_exception_flags = orig_flags | float_flag_invalid;
         return max;
     case float_class_inf:
-- 
2.17.0

^ permalink raw reply related	[flat|nested] 29+ messages in thread

* [Qemu-devel] [PATCH 08/19] target/arm: Use floatX_silence_nan when we have already checked for SNaN
  2018-05-11  0:43 [Qemu-devel] [PATCH 00/19] softfloat: Clean up NaN handling Richard Henderson
                   ` (6 preceding siblings ...)
  2018-05-11  0:43 ` [Qemu-devel] [PATCH 07/19] fpu/softfloat: Replace float_class_msnan with parts_silence_nan Richard Henderson
@ 2018-05-11  0:43 ` Richard Henderson
  2018-05-11  0:43 ` [Qemu-devel] [PATCH 09/19] target/arm: Remove floatX_maybe_silence_nan from conversions Richard Henderson
                   ` (10 subsequent siblings)
  18 siblings, 0 replies; 29+ messages in thread
From: Richard Henderson @ 2018-05-11  0:43 UTC (permalink / raw)
  To: qemu-devel; +Cc: peter.maydell, alex.bennee

Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
---
 target/arm/helper-a64.c |  6 +++---
 target/arm/helper.c     | 12 ++++++------
 2 files changed, 9 insertions(+), 9 deletions(-)

diff --git a/target/arm/helper-a64.c b/target/arm/helper-a64.c
index afb25ad20c..976eaba37a 100644
--- a/target/arm/helper-a64.c
+++ b/target/arm/helper-a64.c
@@ -366,7 +366,7 @@ float16 HELPER(frecpx_f16)(float16 a, void *fpstp)
         float16 nan = a;
         if (float16_is_signaling_nan(a, fpst)) {
             float_raise(float_flag_invalid, fpst);
-            nan = float16_maybe_silence_nan(a, fpst);
+            nan = float16_silence_nan(a, fpst);
         }
         if (fpst->default_nan_mode) {
             nan = float16_default_nan(fpst);
@@ -395,7 +395,7 @@ float32 HELPER(frecpx_f32)(float32 a, void *fpstp)
         float32 nan = a;
         if (float32_is_signaling_nan(a, fpst)) {
             float_raise(float_flag_invalid, fpst);
-            nan = float32_maybe_silence_nan(a, fpst);
+            nan = float32_silence_nan(a, fpst);
         }
         if (fpst->default_nan_mode) {
             nan = float32_default_nan(fpst);
@@ -424,7 +424,7 @@ float64 HELPER(frecpx_f64)(float64 a, void *fpstp)
         float64 nan = a;
         if (float64_is_signaling_nan(a, fpst)) {
             float_raise(float_flag_invalid, fpst);
-            nan = float64_maybe_silence_nan(a, fpst);
+            nan = float64_silence_nan(a, fpst);
         }
         if (fpst->default_nan_mode) {
             nan = float64_default_nan(fpst);
diff --git a/target/arm/helper.c b/target/arm/helper.c
index a5f3d3b7e5..3065045e0c 100644
--- a/target/arm/helper.c
+++ b/target/arm/helper.c
@@ -11679,7 +11679,7 @@ float16 HELPER(recpe_f16)(float16 input, void *fpstp)
         float16 nan = f16;
         if (float16_is_signaling_nan(f16, fpst)) {
             float_raise(float_flag_invalid, fpst);
-            nan = float16_maybe_silence_nan(f16, fpst);
+            nan = float16_silence_nan(f16, fpst);
         }
         if (fpst->default_nan_mode) {
             nan =  float16_default_nan(fpst);
@@ -11727,7 +11727,7 @@ float32 HELPER(recpe_f32)(float32 input, void *fpstp)
         float32 nan = f32;
         if (float32_is_signaling_nan(f32, fpst)) {
             float_raise(float_flag_invalid, fpst);
-            nan = float32_maybe_silence_nan(f32, fpst);
+            nan = float32_silence_nan(f32, fpst);
         }
         if (fpst->default_nan_mode) {
             nan =  float32_default_nan(fpst);
@@ -11775,7 +11775,7 @@ float64 HELPER(recpe_f64)(float64 input, void *fpstp)
         float64 nan = f64;
         if (float64_is_signaling_nan(f64, fpst)) {
             float_raise(float_flag_invalid, fpst);
-            nan = float64_maybe_silence_nan(f64, fpst);
+            nan = float64_silence_nan(f64, fpst);
         }
         if (fpst->default_nan_mode) {
             nan =  float64_default_nan(fpst);
@@ -11874,7 +11874,7 @@ float16 HELPER(rsqrte_f16)(float16 input, void *fpstp)
         float16 nan = f16;
         if (float16_is_signaling_nan(f16, s)) {
             float_raise(float_flag_invalid, s);
-            nan = float16_maybe_silence_nan(f16, s);
+            nan = float16_silence_nan(f16, s);
         }
         if (s->default_nan_mode) {
             nan =  float16_default_nan(s);
@@ -11918,7 +11918,7 @@ float32 HELPER(rsqrte_f32)(float32 input, void *fpstp)
         float32 nan = f32;
         if (float32_is_signaling_nan(f32, s)) {
             float_raise(float_flag_invalid, s);
-            nan = float32_maybe_silence_nan(f32, s);
+            nan = float32_silence_nan(f32, s);
         }
         if (s->default_nan_mode) {
             nan =  float32_default_nan(s);
@@ -11961,7 +11961,7 @@ float64 HELPER(rsqrte_f64)(float64 input, void *fpstp)
         float64 nan = f64;
         if (float64_is_signaling_nan(f64, s)) {
             float_raise(float_flag_invalid, s);
-            nan = float64_maybe_silence_nan(f64, s);
+            nan = float64_silence_nan(f64, s);
         }
         if (s->default_nan_mode) {
             nan =  float64_default_nan(s);
-- 
2.17.0

^ permalink raw reply related	[flat|nested] 29+ messages in thread

* [Qemu-devel] [PATCH 09/19] target/arm: Remove floatX_maybe_silence_nan from conversions
  2018-05-11  0:43 [Qemu-devel] [PATCH 00/19] softfloat: Clean up NaN handling Richard Henderson
                   ` (7 preceding siblings ...)
  2018-05-11  0:43 ` [Qemu-devel] [PATCH 08/19] target/arm: Use floatX_silence_nan when we have already checked for SNaN Richard Henderson
@ 2018-05-11  0:43 ` Richard Henderson
  2018-05-11  0:43 ` [Qemu-devel] [PATCH 10/19] target/hppa: " Richard Henderson
                   ` (9 subsequent siblings)
  18 siblings, 0 replies; 29+ messages in thread
From: Richard Henderson @ 2018-05-11  0:43 UTC (permalink / raw)
  To: qemu-devel; +Cc: peter.maydell, alex.bennee

This is now handled properly by the generic softfloat code.

Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
---
 target/arm/helper-a64.c |  1 -
 target/arm/helper.c     | 12 ++----------
 2 files changed, 2 insertions(+), 11 deletions(-)

diff --git a/target/arm/helper-a64.c b/target/arm/helper-a64.c
index 976eaba37a..5e51d1be9d 100644
--- a/target/arm/helper-a64.c
+++ b/target/arm/helper-a64.c
@@ -456,7 +456,6 @@ float32 HELPER(fcvtx_f64_to_f32)(float64 a, CPUARMState *env)
     set_float_rounding_mode(float_round_to_zero, &tstat);
     set_float_exception_flags(0, &tstat);
     r = float64_to_float32(a, &tstat);
-    r = float32_maybe_silence_nan(r, &tstat);
     exflags = get_float_exception_flags(&tstat);
     if (exflags & float_flag_inexact) {
         r = make_float32(float32_val(r) | 1);
diff --git a/target/arm/helper.c b/target/arm/helper.c
index 3065045e0c..61f8820487 100644
--- a/target/arm/helper.c
+++ b/target/arm/helper.c
@@ -11369,20 +11369,12 @@ FLOAT_CONVS(ui, d, 64, u)
 /* floating point conversion */
 float64 VFP_HELPER(fcvtd, s)(float32 x, CPUARMState *env)
 {
-    float64 r = float32_to_float64(x, &env->vfp.fp_status);
-    /* ARM requires that S<->D conversion of any kind of NaN generates
-     * a quiet NaN by forcing the most significant frac bit to 1.
-     */
-    return float64_maybe_silence_nan(r, &env->vfp.fp_status);
+    return float32_to_float64(x, &env->vfp.fp_status);
 }
 
 float32 VFP_HELPER(fcvts, d)(float64 x, CPUARMState *env)
 {
-    float32 r =  float64_to_float32(x, &env->vfp.fp_status);
-    /* ARM requires that S<->D conversion of any kind of NaN generates
-     * a quiet NaN by forcing the most significant frac bit to 1.
-     */
-    return float32_maybe_silence_nan(r, &env->vfp.fp_status);
+    return float64_to_float32(x, &env->vfp.fp_status);
 }
 
 /* VFP3 fixed point conversion.  */
-- 
2.17.0

^ permalink raw reply related	[flat|nested] 29+ messages in thread

* [Qemu-devel] [PATCH 10/19] target/hppa: Remove floatX_maybe_silence_nan from conversions
  2018-05-11  0:43 [Qemu-devel] [PATCH 00/19] softfloat: Clean up NaN handling Richard Henderson
                   ` (8 preceding siblings ...)
  2018-05-11  0:43 ` [Qemu-devel] [PATCH 09/19] target/arm: Remove floatX_maybe_silence_nan from conversions Richard Henderson
@ 2018-05-11  0:43 ` Richard Henderson
  2018-05-11  0:43 ` [Qemu-devel] [PATCH 11/19] target/m68k: Use floatX_silence_nan when we have already checked for SNaN Richard Henderson
                   ` (8 subsequent siblings)
  18 siblings, 0 replies; 29+ messages in thread
From: Richard Henderson @ 2018-05-11  0:43 UTC (permalink / raw)
  To: qemu-devel; +Cc: peter.maydell, alex.bennee

This is now handled properly by the generic softfloat code.

Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
---
 target/hppa/op_helper.c | 2 --
 1 file changed, 2 deletions(-)

diff --git a/target/hppa/op_helper.c b/target/hppa/op_helper.c
index a3af62daf7..912e8d5be4 100644
--- a/target/hppa/op_helper.c
+++ b/target/hppa/op_helper.c
@@ -341,7 +341,6 @@ float64 HELPER(fdiv_d)(CPUHPPAState *env, float64 a, float64 b)
 float64 HELPER(fcnv_s_d)(CPUHPPAState *env, float32 arg)
 {
     float64 ret = float32_to_float64(arg, &env->fp_status);
-    ret = float64_maybe_silence_nan(ret, &env->fp_status);
     update_fr0_op(env, GETPC());
     return ret;
 }
@@ -349,7 +348,6 @@ float64 HELPER(fcnv_s_d)(CPUHPPAState *env, float32 arg)
 float32 HELPER(fcnv_d_s)(CPUHPPAState *env, float64 arg)
 {
     float32 ret = float64_to_float32(arg, &env->fp_status);
-    ret = float32_maybe_silence_nan(ret, &env->fp_status);
     update_fr0_op(env, GETPC());
     return ret;
 }
-- 
2.17.0

^ permalink raw reply related	[flat|nested] 29+ messages in thread

* [Qemu-devel] [PATCH 11/19] target/m68k: Use floatX_silence_nan when we have already checked for SNaN
  2018-05-11  0:43 [Qemu-devel] [PATCH 00/19] softfloat: Clean up NaN handling Richard Henderson
                   ` (9 preceding siblings ...)
  2018-05-11  0:43 ` [Qemu-devel] [PATCH 10/19] target/hppa: " Richard Henderson
@ 2018-05-11  0:43 ` Richard Henderson
  2018-05-11 10:11   ` Laurent Vivier
  2018-05-11  0:43 ` [Qemu-devel] [PATCH 12/19] target/mips: Remove floatX_maybe_silence_nan from conversions Richard Henderson
                   ` (7 subsequent siblings)
  18 siblings, 1 reply; 29+ messages in thread
From: Richard Henderson @ 2018-05-11  0:43 UTC (permalink / raw)
  To: qemu-devel; +Cc: peter.maydell, alex.bennee, Laurent Vivier

Cc: Laurent Vivier <laurent@vivier.eu>
Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
---
 target/m68k/softfloat.c | 3 ++-
 1 file changed, 2 insertions(+), 1 deletion(-)

diff --git a/target/m68k/softfloat.c b/target/m68k/softfloat.c
index e41b07d042..6ec227e20f 100644
--- a/target/m68k/softfloat.c
+++ b/target/m68k/softfloat.c
@@ -31,13 +31,14 @@ static floatx80 propagateFloatx80NaNOneArg(floatx80 a, float_status *status)
 {
     if (floatx80_is_signaling_nan(a, status)) {
         float_raise(float_flag_invalid, status);
+        a = floatx80_silence_nan(a, status);
     }
 
     if (status->default_nan_mode) {
         return floatx80_default_nan(status);
     }
 
-    return floatx80_maybe_silence_nan(a, status);
+    return a;
 }
 
 /*----------------------------------------------------------------------------
-- 
2.17.0

^ permalink raw reply related	[flat|nested] 29+ messages in thread

* [Qemu-devel] [PATCH 12/19] target/mips: Remove floatX_maybe_silence_nan from conversions
  2018-05-11  0:43 [Qemu-devel] [PATCH 00/19] softfloat: Clean up NaN handling Richard Henderson
                   ` (10 preceding siblings ...)
  2018-05-11  0:43 ` [Qemu-devel] [PATCH 11/19] target/m68k: Use floatX_silence_nan when we have already checked for SNaN Richard Henderson
@ 2018-05-11  0:43 ` Richard Henderson
  2018-05-11  0:43 ` [Qemu-devel] [PATCH 13/19] target/riscv: " Richard Henderson
                   ` (6 subsequent siblings)
  18 siblings, 0 replies; 29+ messages in thread
From: Richard Henderson @ 2018-05-11  0:43 UTC (permalink / raw)
  To: qemu-devel; +Cc: peter.maydell, alex.bennee, Aurelien Jarno, Yongbok Kim

This is now handled properly by the generic softfloat code.

Cc: Aurelien Jarno <aurelien@aurel32.net>
Cc: Yongbok Kim <yongbok.kim@mips.com>
Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
---
 target/mips/msa_helper.c | 4 ----
 target/mips/op_helper.c  | 2 --
 2 files changed, 6 deletions(-)

diff --git a/target/mips/msa_helper.c b/target/mips/msa_helper.c
index 8fb7a369ca..c74e3cdc65 100644
--- a/target/mips/msa_helper.c
+++ b/target/mips/msa_helper.c
@@ -1615,7 +1615,6 @@ static inline float16 float16_from_float32(int32_t a, flag ieee,
       float16 f_val;
 
       f_val = float32_to_float16((float32)a, ieee, status);
-      f_val = float16_maybe_silence_nan(f_val, status);
 
       return a < 0 ? (f_val | (1 << 15)) : f_val;
 }
@@ -1625,7 +1624,6 @@ static inline float32 float32_from_float64(int64_t a, float_status *status)
       float32 f_val;
 
       f_val = float64_to_float32((float64)a, status);
-      f_val = float32_maybe_silence_nan(f_val, status);
 
       return a < 0 ? (f_val | (1 << 31)) : f_val;
 }
@@ -1636,7 +1634,6 @@ static inline float32 float32_from_float16(int16_t a, flag ieee,
       float32 f_val;
 
       f_val = float16_to_float32((float16)a, ieee, status);
-      f_val = float32_maybe_silence_nan(f_val, status);
 
       return a < 0 ? (f_val | (1 << 31)) : f_val;
 }
@@ -1646,7 +1643,6 @@ static inline float64 float64_from_float32(int32_t a, float_status *status)
       float64 f_val;
 
       f_val = float32_to_float64((float64)a, status);
-      f_val = float64_maybe_silence_nan(f_val, status);
 
       return a < 0 ? (f_val | (1ULL << 63)) : f_val;
 }
diff --git a/target/mips/op_helper.c b/target/mips/op_helper.c
index 798cdad030..9025f42366 100644
--- a/target/mips/op_helper.c
+++ b/target/mips/op_helper.c
@@ -2700,7 +2700,6 @@ uint64_t helper_float_cvtd_s(CPUMIPSState *env, uint32_t fst0)
     uint64_t fdt2;
 
     fdt2 = float32_to_float64(fst0, &env->active_fpu.fp_status);
-    fdt2 = float64_maybe_silence_nan(fdt2, &env->active_fpu.fp_status);
     update_fcr31(env, GETPC());
     return fdt2;
 }
@@ -2790,7 +2789,6 @@ uint32_t helper_float_cvts_d(CPUMIPSState *env, uint64_t fdt0)
     uint32_t fst2;
 
     fst2 = float64_to_float32(fdt0, &env->active_fpu.fp_status);
-    fst2 = float32_maybe_silence_nan(fst2, &env->active_fpu.fp_status);
     update_fcr31(env, GETPC());
     return fst2;
 }
-- 
2.17.0

^ permalink raw reply related	[flat|nested] 29+ messages in thread

* [Qemu-devel] [PATCH 13/19] target/riscv: Remove floatX_maybe_silence_nan from conversions
  2018-05-11  0:43 [Qemu-devel] [PATCH 00/19] softfloat: Clean up NaN handling Richard Henderson
                   ` (11 preceding siblings ...)
  2018-05-11  0:43 ` [Qemu-devel] [PATCH 12/19] target/mips: Remove floatX_maybe_silence_nan from conversions Richard Henderson
@ 2018-05-11  0:43 ` Richard Henderson
  2018-05-11  0:43 ` [Qemu-devel] [PATCH 14/19] target/s390x: " Richard Henderson
                   ` (5 subsequent siblings)
  18 siblings, 0 replies; 29+ messages in thread
From: Richard Henderson @ 2018-05-11  0:43 UTC (permalink / raw)
  To: qemu-devel
  Cc: peter.maydell, alex.bennee, Michael Clark, Palmer Dabbelt,
	Sagar Karandikar, Bastian Koppelmann

This is now handled properly by the generic softfloat code.

Cc: Michael Clark <mjc@sifive.com>
Cc: Palmer Dabbelt <palmer@sifive.com>
Cc: Sagar Karandikar <sagark@eecs.berkeley.edu>
Cc: Bastian Koppelmann <kbastian@mail.uni-paderborn.de>
Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
---
 target/riscv/fpu_helper.c | 6 ++----
 1 file changed, 2 insertions(+), 4 deletions(-)

diff --git a/target/riscv/fpu_helper.c b/target/riscv/fpu_helper.c
index abbadead5c..fdb87d8d82 100644
--- a/target/riscv/fpu_helper.c
+++ b/target/riscv/fpu_helper.c
@@ -279,14 +279,12 @@ uint64_t helper_fmax_d(CPURISCVState *env, uint64_t frs1, uint64_t frs2)
 
 uint64_t helper_fcvt_s_d(CPURISCVState *env, uint64_t rs1)
 {
-    rs1 = float64_to_float32(rs1, &env->fp_status);
-    return float32_maybe_silence_nan(rs1, &env->fp_status);
+    return float64_to_float32(rs1, &env->fp_status);
 }
 
 uint64_t helper_fcvt_d_s(CPURISCVState *env, uint64_t rs1)
 {
-    rs1 = float32_to_float64(rs1, &env->fp_status);
-    return float64_maybe_silence_nan(rs1, &env->fp_status);
+    return float32_to_float64(rs1, &env->fp_status);
 }
 
 uint64_t helper_fsqrt_d(CPURISCVState *env, uint64_t frs1)
-- 
2.17.0

^ permalink raw reply related	[flat|nested] 29+ messages in thread

* [Qemu-devel] [PATCH 14/19] target/s390x: Remove floatX_maybe_silence_nan from conversions
  2018-05-11  0:43 [Qemu-devel] [PATCH 00/19] softfloat: Clean up NaN handling Richard Henderson
                   ` (12 preceding siblings ...)
  2018-05-11  0:43 ` [Qemu-devel] [PATCH 13/19] target/riscv: " Richard Henderson
@ 2018-05-11  0:43 ` Richard Henderson
  2018-05-11  6:47   ` David Hildenbrand
  2018-05-11  0:43 ` [Qemu-devel] [PATCH 15/19] fpu/softfloat: Use float*_silence_nan in propagateFloat*NaN Richard Henderson
                   ` (4 subsequent siblings)
  18 siblings, 1 reply; 29+ messages in thread
From: Richard Henderson @ 2018-05-11  0:43 UTC (permalink / raw)
  To: qemu-devel; +Cc: peter.maydell, alex.bennee, Alexander Graf, David Hildenbrand

This is now handled properly by the generic softfloat code.

Cc: Alexander Graf <agraf@suse.de>
Cc: David Hildenbrand <david@redhat.com>
Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
---
 target/s390x/fpu_helper.c | 12 ++++++------
 1 file changed, 6 insertions(+), 6 deletions(-)

diff --git a/target/s390x/fpu_helper.c b/target/s390x/fpu_helper.c
index 43f8bf1c94..5c5b451b3b 100644
--- a/target/s390x/fpu_helper.c
+++ b/target/s390x/fpu_helper.c
@@ -269,7 +269,7 @@ uint64_t HELPER(ldeb)(CPUS390XState *env, uint64_t f2)
 {
     float64 ret = float32_to_float64(f2, &env->fpu_status);
     handle_exceptions(env, GETPC());
-    return float64_maybe_silence_nan(ret, &env->fpu_status);
+    return ret;
 }
 
 /* convert 128-bit float to 64-bit float */
@@ -277,7 +277,7 @@ uint64_t HELPER(ldxb)(CPUS390XState *env, uint64_t ah, uint64_t al)
 {
     float64 ret = float128_to_float64(make_float128(ah, al), &env->fpu_status);
     handle_exceptions(env, GETPC());
-    return float64_maybe_silence_nan(ret, &env->fpu_status);
+    return ret;
 }
 
 /* convert 64-bit float to 128-bit float */
@@ -285,7 +285,7 @@ uint64_t HELPER(lxdb)(CPUS390XState *env, uint64_t f2)
 {
     float128 ret = float64_to_float128(f2, &env->fpu_status);
     handle_exceptions(env, GETPC());
-    return RET128(float128_maybe_silence_nan(ret, &env->fpu_status));
+    return RET128(ret);
 }
 
 /* convert 32-bit float to 128-bit float */
@@ -293,7 +293,7 @@ uint64_t HELPER(lxeb)(CPUS390XState *env, uint64_t f2)
 {
     float128 ret = float32_to_float128(f2, &env->fpu_status);
     handle_exceptions(env, GETPC());
-    return RET128(float128_maybe_silence_nan(ret, &env->fpu_status));
+    return RET128(ret);
 }
 
 /* convert 64-bit float to 32-bit float */
@@ -301,7 +301,7 @@ uint64_t HELPER(ledb)(CPUS390XState *env, uint64_t f2)
 {
     float32 ret = float64_to_float32(f2, &env->fpu_status);
     handle_exceptions(env, GETPC());
-    return float32_maybe_silence_nan(ret, &env->fpu_status);
+    return ret;
 }
 
 /* convert 128-bit float to 32-bit float */
@@ -309,7 +309,7 @@ uint64_t HELPER(lexb)(CPUS390XState *env, uint64_t ah, uint64_t al)
 {
     float32 ret = float128_to_float32(make_float128(ah, al), &env->fpu_status);
     handle_exceptions(env, GETPC());
-    return float32_maybe_silence_nan(ret, &env->fpu_status);
+    return ret;
 }
 
 /* 32-bit FP compare */
-- 
2.17.0

^ permalink raw reply related	[flat|nested] 29+ messages in thread

* [Qemu-devel] [PATCH 15/19] fpu/softfloat: Use float*_silence_nan in propagateFloat*NaN
  2018-05-11  0:43 [Qemu-devel] [PATCH 00/19] softfloat: Clean up NaN handling Richard Henderson
                   ` (13 preceding siblings ...)
  2018-05-11  0:43 ` [Qemu-devel] [PATCH 14/19] target/s390x: " Richard Henderson
@ 2018-05-11  0:43 ` Richard Henderson
  2018-05-11  0:43 ` [Qemu-devel] [PATCH 16/19] fpu/softfloat: Remove floatX_maybe_silence_nan Richard Henderson
                   ` (3 subsequent siblings)
  18 siblings, 0 replies; 29+ messages in thread
From: Richard Henderson @ 2018-05-11  0:43 UTC (permalink / raw)
  To: qemu-devel; +Cc: peter.maydell, alex.bennee

We have already checked the arguments for SNaN;
we don't need to do it again.

Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
---
 fpu/softfloat-specialize.h | 44 +++++++++++++++++++++++++++++---------
 1 file changed, 34 insertions(+), 10 deletions(-)

diff --git a/fpu/softfloat-specialize.h b/fpu/softfloat-specialize.h
index 53a4f45a8c..08ab8181d5 100644
--- a/fpu/softfloat-specialize.h
+++ b/fpu/softfloat-specialize.h
@@ -498,7 +498,7 @@ static float32 commonNaNToFloat32(commonNaNT a, float_status *status)
 | The routine is passed various bits of information about the
 | two NaNs and should return 0 to select NaN a and 1 for NaN b.
 | Note that signalling NaNs are always squashed to quiet NaNs
-| by the caller, by calling floatXX_maybe_silence_nan() before
+| by the caller, by calling floatXX_silence_nan() before
 | returning them.
 |
 | aIsLargerSignificand is only valid if both a and b are NaNs
@@ -536,7 +536,7 @@ static int pickNaN(flag aIsQNaN, flag aIsSNaN, flag bIsQNaN, flag bIsSNaN,
 {
     /* According to MIPS specifications, if one of the two operands is
      * a sNaN, a new qNaN has to be generated. This is done in
-     * floatXX_maybe_silence_nan(). For qNaN inputs the specifications
+     * floatXX_silence_nan(). For qNaN inputs the specifications
      * says: "When possible, this QNaN result is one of the operand QNaN
      * values." In practice it seems that most implementations choose
      * the first operand if both operands are qNaN. In short this gives
@@ -788,9 +788,15 @@ static float32 propagateFloat32NaN(float32 a, float32 b, float_status *status)
 
     if (pickNaN(aIsQuietNaN, aIsSignalingNaN, bIsQuietNaN, bIsSignalingNaN,
                 aIsLargerSignificand)) {
-        return float32_maybe_silence_nan(b, status);
+        if (bIsSignalingNaN) {
+            return float32_silence_nan(b, status);
+        }
+        return b;
     } else {
-        return float32_maybe_silence_nan(a, status);
+        if (aIsSignalingNaN) {
+            return float32_silence_nan(a, status);
+        }
+        return a;
     }
 }
 
@@ -950,9 +956,15 @@ static float64 propagateFloat64NaN(float64 a, float64 b, float_status *status)
 
     if (pickNaN(aIsQuietNaN, aIsSignalingNaN, bIsQuietNaN, bIsSignalingNaN,
                 aIsLargerSignificand)) {
-        return float64_maybe_silence_nan(b, status);
+        if (bIsSignalingNaN) {
+            return float64_silence_nan(b, status);
+        }
+        return b;
     } else {
-        return float64_maybe_silence_nan(a, status);
+        if (aIsSignalingNaN) {
+            return float64_silence_nan(a, status);
+        }
+        return a;
     }
 }
 
@@ -1121,9 +1133,15 @@ floatx80 propagateFloatx80NaN(floatx80 a, floatx80 b, float_status *status)
 
     if (pickNaN(aIsQuietNaN, aIsSignalingNaN, bIsQuietNaN, bIsSignalingNaN,
                 aIsLargerSignificand)) {
-        return floatx80_maybe_silence_nan(b, status);
+        if (bIsSignalingNaN) {
+            return floatx80_silence_nan(b, status);
+        }
+        return b;
     } else {
-        return floatx80_maybe_silence_nan(a, status);
+        if (aIsSignalingNaN) {
+            return floatx80_silence_nan(a, status);
+        }
+        return a;
     }
 }
 
@@ -1270,8 +1288,14 @@ static float128 propagateFloat128NaN(float128 a, float128 b,
 
     if (pickNaN(aIsQuietNaN, aIsSignalingNaN, bIsQuietNaN, bIsSignalingNaN,
                 aIsLargerSignificand)) {
-        return float128_maybe_silence_nan(b, status);
+        if (bIsSignalingNaN) {
+            return float128_silence_nan(b, status);
+        }
+        return b;
     } else {
-        return float128_maybe_silence_nan(a, status);
+        if (aIsSignalingNaN) {
+            return float128_silence_nan(a, status);
+        }
+        return a;
     }
 }
-- 
2.17.0

^ permalink raw reply related	[flat|nested] 29+ messages in thread

* [Qemu-devel] [PATCH 16/19] fpu/softfloat: Remove floatX_maybe_silence_nan
  2018-05-11  0:43 [Qemu-devel] [PATCH 00/19] softfloat: Clean up NaN handling Richard Henderson
                   ` (14 preceding siblings ...)
  2018-05-11  0:43 ` [Qemu-devel] [PATCH 15/19] fpu/softfloat: Use float*_silence_nan in propagateFloat*NaN Richard Henderson
@ 2018-05-11  0:43 ` Richard Henderson
  2018-05-11  0:43 ` [Qemu-devel] [PATCH 17/19] fpu/softfloat: Introduce SNAN_BIT_IS_ONE Richard Henderson
                   ` (2 subsequent siblings)
  18 siblings, 0 replies; 29+ messages in thread
From: Richard Henderson @ 2018-05-11  0:43 UTC (permalink / raw)
  To: qemu-devel; +Cc: peter.maydell, alex.bennee

These functions are now unused.

Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
---
 fpu/softfloat-specialize.h | 63 --------------------------------------
 include/fpu/softfloat.h    |  5 ---
 2 files changed, 68 deletions(-)

diff --git a/fpu/softfloat-specialize.h b/fpu/softfloat-specialize.h
index 08ab8181d5..d7033b7757 100644
--- a/fpu/softfloat-specialize.h
+++ b/fpu/softfloat-specialize.h
@@ -364,19 +364,6 @@ float16 float16_silence_nan(float16 a, float_status *status)
 #endif
 }
 
-/*----------------------------------------------------------------------------
-| Returns a quiet NaN if the half-precision floating point value `a' is a
-| signaling NaN; otherwise returns `a'.
-*----------------------------------------------------------------------------*/
-
-float16 float16_maybe_silence_nan(float16 a, float_status *status)
-{
-    if (float16_is_signaling_nan(a, status)) {
-        float16_silence_nan(a, status);
-    }
-    return a;
-}
-
 /*----------------------------------------------------------------------------
 | Returns 1 if the single-precision floating-point value `a' is a quiet
 | NaN; otherwise returns 0.
@@ -438,18 +425,6 @@ float32 float32_silence_nan(float32 a, float_status *status)
     }
 #endif
 }
-/*----------------------------------------------------------------------------
-| Returns a quiet NaN if the single-precision floating point value `a' is a
-| signaling NaN; otherwise returns `a'.
-*----------------------------------------------------------------------------*/
-
-float32 float32_maybe_silence_nan(float32 a, float_status *status)
-{
-    if (float32_is_signaling_nan(a, status)) {
-        float32_silence_nan(a, status);
-    }
-    return a;
-}
 
 /*----------------------------------------------------------------------------
 | Returns the result of converting the single-precision floating-point NaN
@@ -864,18 +839,6 @@ float64 float64_silence_nan(float64 a, float_status *status)
 #endif
 }
 
-/*----------------------------------------------------------------------------
-| Returns a quiet NaN if the double-precision floating point value `a' is a
-| signaling NaN; otherwise returns `a'.
-*----------------------------------------------------------------------------*/
-
-float64 float64_maybe_silence_nan(float64 a, float_status *status)
-{
-    if (float64_is_signaling_nan(a, status)) {
-        return float64_silence_nan(a, status);
-    }
-    return a;
-}
 
 /*----------------------------------------------------------------------------
 | Returns the result of converting the double-precision floating-point NaN
@@ -1037,19 +1000,6 @@ floatx80 floatx80_silence_nan(floatx80 a, float_status *status)
 #endif
 }
 
-/*----------------------------------------------------------------------------
-| Returns a quiet NaN if the extended double-precision floating point value
-| `a' is a signaling NaN; otherwise returns `a'.
-*----------------------------------------------------------------------------*/
-
-floatx80 floatx80_maybe_silence_nan(floatx80 a, float_status *status)
-{
-    if (floatx80_is_signaling_nan(a, status)) {
-        return floatx80_silence_nan(a, status);
-    }
-    return a;
-}
-
 /*----------------------------------------------------------------------------
 | Returns the result of converting the extended double-precision floating-
 | point NaN `a' to the canonical NaN format.  If `a' is a signaling NaN, the
@@ -1204,19 +1154,6 @@ float128 float128_silence_nan(float128 a, float_status *status)
 #endif
 }
 
-/*----------------------------------------------------------------------------
-| Returns a quiet NaN if the quadruple-precision floating point value `a' is
-| a signaling NaN; otherwise returns `a'.
-*----------------------------------------------------------------------------*/
-
-float128 float128_maybe_silence_nan(float128 a, float_status *status)
-{
-    if (float128_is_signaling_nan(a, status)) {
-        return float128_silence_nan(a, status);
-    }
-    return a;
-}
-
 /*----------------------------------------------------------------------------
 | Returns the result of converting the quadruple-precision floating-point NaN
 | `a' to the canonical NaN format.  If `a' is a signaling NaN, the invalid
diff --git a/include/fpu/softfloat.h b/include/fpu/softfloat.h
index a6860e858d..69f4dbc4db 100644
--- a/include/fpu/softfloat.h
+++ b/include/fpu/softfloat.h
@@ -258,7 +258,6 @@ int float16_compare_quiet(float16, float16, float_status *status);
 int float16_is_quiet_nan(float16, float_status *status);
 int float16_is_signaling_nan(float16, float_status *status);
 float16 float16_silence_nan(float16, float_status *status);
-float16 float16_maybe_silence_nan(float16, float_status *status);
 
 static inline int float16_is_any_nan(float16 a)
 {
@@ -370,7 +369,6 @@ float32 float32_maxnummag(float32, float32, float_status *status);
 int float32_is_quiet_nan(float32, float_status *status);
 int float32_is_signaling_nan(float32, float_status *status);
 float32 float32_silence_nan(float32, float_status *status);
-float32 float32_maybe_silence_nan(float32, float_status *status);
 float32 float32_scalbn(float32, int, float_status *status);
 
 static inline float32 float32_abs(float32 a)
@@ -500,7 +498,6 @@ float64 float64_maxnummag(float64, float64, float_status *status);
 int float64_is_quiet_nan(float64 a, float_status *status);
 int float64_is_signaling_nan(float64, float_status *status);
 float64 float64_silence_nan(float64, float_status *status);
-float64 float64_maybe_silence_nan(float64, float_status *status);
 float64 float64_scalbn(float64, int, float_status *status);
 
 static inline float64 float64_abs(float64 a)
@@ -604,7 +601,6 @@ int floatx80_compare_quiet(floatx80, floatx80, float_status *status);
 int floatx80_is_quiet_nan(floatx80, float_status *status);
 int floatx80_is_signaling_nan(floatx80, float_status *status);
 floatx80 floatx80_silence_nan(floatx80, float_status *status);
-floatx80 floatx80_maybe_silence_nan(floatx80, float_status *status);
 floatx80 floatx80_scalbn(floatx80, int, float_status *status);
 
 static inline floatx80 floatx80_abs(floatx80 a)
@@ -816,7 +812,6 @@ int float128_compare_quiet(float128, float128, float_status *status);
 int float128_is_quiet_nan(float128, float_status *status);
 int float128_is_signaling_nan(float128, float_status *status);
 float128 float128_silence_nan(float128, float_status *status);
-float128 float128_maybe_silence_nan(float128, float_status *status);
 float128 float128_scalbn(float128, int, float_status *status);
 
 static inline float128 float128_abs(float128 a)
-- 
2.17.0

^ permalink raw reply related	[flat|nested] 29+ messages in thread

* [Qemu-devel] [PATCH 17/19] fpu/softfloat: Introduce SNAN_BIT_IS_ONE
  2018-05-11  0:43 [Qemu-devel] [PATCH 00/19] softfloat: Clean up NaN handling Richard Henderson
                   ` (15 preceding siblings ...)
  2018-05-11  0:43 ` [Qemu-devel] [PATCH 16/19] fpu/softfloat: Remove floatX_maybe_silence_nan Richard Henderson
@ 2018-05-11  0:43 ` Richard Henderson
  2018-05-11  0:43 ` [Qemu-devel] [PATCH 18/19] fpu/softfloat: Pass FloatClass to pickNaN Richard Henderson
  2018-05-11  0:43 ` [Qemu-devel] [PATCH 19/19] fpu/softfloat: Pass FloatClass to pickNaNMulAdd Richard Henderson
  18 siblings, 0 replies; 29+ messages in thread
From: Richard Henderson @ 2018-05-11  0:43 UTC (permalink / raw)
  To: qemu-devel; +Cc: peter.maydell, alex.bennee

Only MIPS requires snan_bit_is_one to be variable.  While we are
specializing softfloat behaviour, allow other targets to eliminate
this runtime check.

Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
---
 fpu/softfloat-specialize.h    | 57 ++++++++++++++++++++---------------
 include/fpu/softfloat-types.h |  1 +
 include/fpu/softfloat.h       |  4 ---
 target/mips/cpu.h             |  4 +--
 target/hppa/cpu.c             |  1 -
 target/mips/translate_init.c  |  4 +--
 target/ppc/fpu_helper.c       |  1 -
 target/sh4/cpu.c              |  1 -
 target/unicore32/cpu.c        |  2 --
 9 files changed, 37 insertions(+), 38 deletions(-)

diff --git a/fpu/softfloat-specialize.h b/fpu/softfloat-specialize.h
index d7033b7757..e7b4544e48 100644
--- a/fpu/softfloat-specialize.h
+++ b/fpu/softfloat-specialize.h
@@ -83,7 +83,14 @@ this code that are retained.
 /* Define for architectures which deviate from IEEE in not supporting
  * signaling NaNs (so all NaNs are treated as quiet).
  */
-#define NO_SIGNALING_NANS 1
+# define NO_SIGNALING_NANS   1
+# define SNAN_BIT_IS_ONE(S)  0
+#elif defined(TARGET_MIPS)
+# define SNAN_BIT_IS_ONE(S)  ((S)->snan_bit_is_one)
+#elif defined(TARGET_HPPA) || defined(TARGET_UNICORE32) || defined(TARGET_SH4)
+# define SNAN_BIT_IS_ONE(S)  1
+#else
+# define SNAN_BIT_IS_ONE(S)  0
 #endif
 
 /*----------------------------------------------------------------------------
@@ -97,7 +104,7 @@ static bool parts_is_snan_frac(uint64_t frac, float_status *status)
     return false;
 #else
     flag msb = extract64(frac, DECOMPOSED_BINARY_POINT - 1, 1);
-    return msb == status->snan_bit_is_one;
+    return msb == SNAN_BIT_IS_ONE(status);
 #endif
 }
 
@@ -118,7 +125,7 @@ static FloatParts parts_default_nan(float_status *status)
 #elif defined(TARGET_HPPA)
     frac = 1ULL << (DECOMPOSED_BINARY_POINT - 2);
 #else
-    if (status->snan_bit_is_one) {
+    if (SNAN_BIT_IS_ONE(status)) {
         frac = (1ULL << (DECOMPOSED_BINARY_POINT - 1)) - 1;
     } else {
 #if defined(TARGET_MIPS)
@@ -151,7 +158,7 @@ static FloatParts parts_silence_nan(FloatParts a, float_status *status)
     a.frac &= ~(1ULL << (DECOMPOSED_BINARY_POINT - 1));
     a.frac |= 1ULL << (DECOMPOSED_BINARY_POINT - 2);
 #else
-    if (status->snan_bit_is_one) {
+    if (SNAN_BIT_IS_ONE(status)) {
         return parts_default_nan(status);
     } else {
         a.frac |= 1ULL << (DECOMPOSED_BINARY_POINT - 1);
@@ -169,7 +176,7 @@ float16 float16_default_nan(float_status *status)
 #if defined(TARGET_ARM)
     return const_float16(0x7E00);
 #else
-    if (status->snan_bit_is_one) {
+    if (SNAN_BIT_IS_ONE(status)) {
         return const_float16(0x7DFF);
     } else {
 #if defined(TARGET_MIPS)
@@ -195,7 +202,7 @@ float32 float32_default_nan(float_status *status)
 #elif defined(TARGET_HPPA)
     return const_float32(0x7FA00000);
 #else
-    if (status->snan_bit_is_one) {
+    if (SNAN_BIT_IS_ONE(status)) {
         return const_float32(0x7FBFFFFF);
     } else {
 #if defined(TARGET_MIPS)
@@ -220,7 +227,7 @@ float64 float64_default_nan(float_status *status)
 #elif defined(TARGET_HPPA)
     return const_float64(LIT64(0x7FF4000000000000));
 #else
-    if (status->snan_bit_is_one) {
+    if (SNAN_BIT_IS_ONE(status)) {
         return const_float64(LIT64(0x7FF7FFFFFFFFFFFF));
     } else {
 #if defined(TARGET_MIPS)
@@ -242,7 +249,7 @@ floatx80 floatx80_default_nan(float_status *status)
     r.low = LIT64(0xFFFFFFFFFFFFFFFF);
     r.high = 0x7FFF;
 #else
-    if (status->snan_bit_is_one) {
+    if (SNAN_BIT_IS_ONE(status)) {
         r.low = LIT64(0xBFFFFFFFFFFFFFFF);
         r.high = 0x7FFF;
     } else {
@@ -274,7 +281,7 @@ float128 float128_default_nan(float_status *status)
 {
     float128 r;
 
-    if (status->snan_bit_is_one) {
+    if (SNAN_BIT_IS_ONE(status)) {
         r.low = LIT64(0xFFFFFFFFFFFFFFFF);
         r.high = LIT64(0x7FFF7FFFFFFFFFFF);
     } else {
@@ -319,7 +326,7 @@ int float16_is_quiet_nan(float16 a_, float_status *status)
     return float16_is_any_nan(a_);
 #else
     uint16_t a = float16_val(a_);
-    if (status->snan_bit_is_one) {
+    if (SNAN_BIT_IS_ONE(status)) {
         return (((a >> 9) & 0x3F) == 0x3E) && (a & 0x1FF);
     } else {
         return ((a & ~0x8000) >= 0x7C80);
@@ -338,7 +345,7 @@ int float16_is_signaling_nan(float16 a_, float_status *status)
     return 0;
 #else
     uint16_t a = float16_val(a_);
-    if (status->snan_bit_is_one) {
+    if (SNAN_BIT_IS_ONE(status)) {
         return ((a & ~0x8000) >= 0x7C80);
     } else {
         return (((a >> 9) & 0x3F) == 0x3E) && (a & 0x1FF);
@@ -356,7 +363,7 @@ float16 float16_silence_nan(float16 a, float_status *status)
 #ifdef NO_SIGNALING_NANS
     g_assert_not_reached();
 #else
-    if (status->snan_bit_is_one) {
+    if (SNAN_BIT_IS_ONE(status)) {
         return float16_default_nan(status);
     } else {
         return a | (1 << 9);
@@ -375,7 +382,7 @@ int float32_is_quiet_nan(float32 a_, float_status *status)
     return float32_is_any_nan(a_);
 #else
     uint32_t a = float32_val(a_);
-    if (status->snan_bit_is_one) {
+    if (SNAN_BIT_IS_ONE(status)) {
         return (((a >> 22) & 0x1FF) == 0x1FE) && (a & 0x003FFFFF);
     } else {
         return ((uint32_t)(a << 1) >= 0xFF800000);
@@ -394,7 +401,7 @@ int float32_is_signaling_nan(float32 a_, float_status *status)
     return 0;
 #else
     uint32_t a = float32_val(a_);
-    if (status->snan_bit_is_one) {
+    if (SNAN_BIT_IS_ONE(status)) {
         return ((uint32_t)(a << 1) >= 0xFF800000);
     } else {
         return (((a >> 22) & 0x1FF) == 0x1FE) && (a & 0x003FFFFF);
@@ -412,7 +419,7 @@ float32 float32_silence_nan(float32 a, float_status *status)
 #ifdef NO_SIGNALING_NANS
     g_assert_not_reached();
 #else
-    if (status->snan_bit_is_one) {
+    if (SNAN_BIT_IS_ONE(status)) {
 # ifdef TARGET_HPPA
         a &= ~0x00400000;
         a |=  0x00200000;
@@ -651,7 +658,7 @@ static int pickNaNMulAdd(flag aIsQNaN, flag aIsSNaN, flag bIsQNaN, flag bIsSNaN,
         return 3;
     }
 
-    if (status->snan_bit_is_one) {
+    if (SNAN_BIT_IS_ONE(status)) {
         /* Prefer sNaN over qNaN, in the a, b, c order. */
         if (aIsSNaN) {
             return 0;
@@ -786,7 +793,7 @@ int float64_is_quiet_nan(float64 a_, float_status *status)
     return float64_is_any_nan(a_);
 #else
     uint64_t a = float64_val(a_);
-    if (status->snan_bit_is_one) {
+    if (SNAN_BIT_IS_ONE(status)) {
         return (((a >> 51) & 0xFFF) == 0xFFE)
             && (a & 0x0007FFFFFFFFFFFFULL);
     } else {
@@ -806,7 +813,7 @@ int float64_is_signaling_nan(float64 a_, float_status *status)
     return 0;
 #else
     uint64_t a = float64_val(a_);
-    if (status->snan_bit_is_one) {
+    if (SNAN_BIT_IS_ONE(status)) {
         return ((a << 1) >= 0xFFF0000000000000ULL);
     } else {
         return (((a >> 51) & 0xFFF) == 0xFFE)
@@ -825,7 +832,7 @@ float64 float64_silence_nan(float64 a, float_status *status)
 #ifdef NO_SIGNALING_NANS
     g_assert_not_reached();
 #else
-    if (status->snan_bit_is_one) {
+    if (SNAN_BIT_IS_ONE(status)) {
 # ifdef TARGET_HPPA
         a &= ~0x0008000000000000ULL;
         a |=  0x0004000000000000ULL;
@@ -942,7 +949,7 @@ int floatx80_is_quiet_nan(floatx80 a, float_status *status)
 #ifdef NO_SIGNALING_NANS
     return floatx80_is_any_nan(a);
 #else
-    if (status->snan_bit_is_one) {
+    if (SNAN_BIT_IS_ONE(status)) {
         uint64_t aLow;
 
         aLow = a.low & ~0x4000000000000000ULL;
@@ -967,7 +974,7 @@ int floatx80_is_signaling_nan(floatx80 a, float_status *status)
 #ifdef NO_SIGNALING_NANS
     return 0;
 #else
-    if (status->snan_bit_is_one) {
+    if (SNAN_BIT_IS_ONE(status)) {
         return ((a.high & 0x7FFF) == 0x7FFF)
             && ((a.low << 1) >= 0x8000000000000000ULL);
     } else {
@@ -991,7 +998,7 @@ floatx80 floatx80_silence_nan(floatx80 a, float_status *status)
 #ifdef NO_SIGNALING_NANS
     g_assert_not_reached();
 #else
-    if (status->snan_bit_is_one) {
+    if (SNAN_BIT_IS_ONE(status)) {
         return floatx80_default_nan(status);
     } else {
         a.low |= LIT64(0xC000000000000000);
@@ -1105,7 +1112,7 @@ int float128_is_quiet_nan(float128 a, float_status *status)
 #ifdef NO_SIGNALING_NANS
     return float128_is_any_nan(a);
 #else
-    if (status->snan_bit_is_one) {
+    if (SNAN_BIT_IS_ONE(status)) {
         return (((a.high >> 47) & 0xFFFF) == 0xFFFE)
             && (a.low || (a.high & 0x00007FFFFFFFFFFFULL));
     } else {
@@ -1125,7 +1132,7 @@ int float128_is_signaling_nan(float128 a, float_status *status)
 #ifdef NO_SIGNALING_NANS
     return 0;
 #else
-    if (status->snan_bit_is_one) {
+    if (SNAN_BIT_IS_ONE(status)) {
         return ((a.high << 1) >= 0xFFFF000000000000ULL)
             && (a.low || (a.high & 0x0000FFFFFFFFFFFFULL));
     } else {
@@ -1145,7 +1152,7 @@ float128 float128_silence_nan(float128 a, float_status *status)
 #ifdef NO_SIGNALING_NANS
     g_assert_not_reached();
 #else
-    if (status->snan_bit_is_one) {
+    if (SNAN_BIT_IS_ONE(status)) {
         return float128_default_nan(status);
     } else {
         a.high |= LIT64(0x0000800000000000);
diff --git a/include/fpu/softfloat-types.h b/include/fpu/softfloat-types.h
index 4e378cb612..b5207d4537 100644
--- a/include/fpu/softfloat-types.h
+++ b/include/fpu/softfloat-types.h
@@ -173,6 +173,7 @@ typedef struct float_status {
     /* should denormalised inputs go to zero and set the input_denormal flag? */
     flag flush_inputs_to_zero;
     flag default_nan_mode;
+    /* not always used -- see SNAN_BIT_IS_ONE in softfloat-specialize.h */
     flag snan_bit_is_one;
 } float_status;
 
diff --git a/include/fpu/softfloat.h b/include/fpu/softfloat.h
index 69f4dbc4db..e72cc9525d 100644
--- a/include/fpu/softfloat.h
+++ b/include/fpu/softfloat.h
@@ -125,10 +125,6 @@ static inline void set_default_nan_mode(flag val, float_status *status)
 {
     status->default_nan_mode = val;
 }
-static inline void set_snan_bit_is_one(flag val, float_status *status)
-{
-    status->snan_bit_is_one = val;
-}
 static inline int get_float_detect_tininess(float_status *status)
 {
     return status->float_detect_tininess;
diff --git a/target/mips/cpu.h b/target/mips/cpu.h
index cfe1735e0e..2abce47ea3 100644
--- a/target/mips/cpu.h
+++ b/target/mips/cpu.h
@@ -755,8 +755,8 @@ target_ulong exception_resume_pc (CPUMIPSState *env);
 
 static inline void restore_snan_bit_mode(CPUMIPSState *env)
 {
-    set_snan_bit_is_one((env->active_fpu.fcr31 & (1 << FCR31_NAN2008)) == 0,
-                        &env->active_fpu.fp_status);
+    env->active_fpu.fp_status.snan_bit_is_one
+        = (env->active_fpu.fcr31 & (1 << FCR31_NAN2008)) == 0;
 }
 
 static inline void cpu_get_tb_cpu_state(CPUMIPSState *env, target_ulong *pc,
diff --git a/target/hppa/cpu.c b/target/hppa/cpu.c
index c261b6b090..00bf444620 100644
--- a/target/hppa/cpu.c
+++ b/target/hppa/cpu.c
@@ -141,7 +141,6 @@ static void hppa_cpu_initfn(Object *obj)
     cs->env_ptr = env;
     cs->exception_index = -1;
     cpu_hppa_loaded_fr0(env);
-    set_snan_bit_is_one(true, &env->fp_status);
     cpu_hppa_put_psw(env, PSW_W);
 }
 
diff --git a/target/mips/translate_init.c b/target/mips/translate_init.c
index c7ba6ee5f9..5e40d6a198 100644
--- a/target/mips/translate_init.c
+++ b/target/mips/translate_init.c
@@ -878,6 +878,6 @@ static void msa_reset(CPUMIPSState *env)
     /* clear float_status nan mode */
     set_default_nan_mode(0, &env->active_tc.msa_fp_status);
 
-    /* set proper signanling bit meaning ("1" means "quiet") */
-    set_snan_bit_is_one(0, &env->active_tc.msa_fp_status);
+    /* set proper signaling bit meaning ("1" means "quiet") */
+    env->active_tc.msa_fp_status.snan_bit_is_one = 0;
 }
diff --git a/target/ppc/fpu_helper.c b/target/ppc/fpu_helper.c
index 9ae418a577..d31a933cbb 100644
--- a/target/ppc/fpu_helper.c
+++ b/target/ppc/fpu_helper.c
@@ -3382,7 +3382,6 @@ void helper_xssqrtqp(CPUPPCState *env, uint32_t opcode)
             xt.f128 = xb.f128;
         } else if (float128_is_neg(xb.f128) && !float128_is_zero(xb.f128)) {
             float_invalid_op_excp(env, POWERPC_EXCP_FP_VXSQRT, 1);
-            set_snan_bit_is_one(0, &env->fp_status);
             xt.f128 = float128_default_nan(&env->fp_status);
         }
     }
diff --git a/target/sh4/cpu.c b/target/sh4/cpu.c
index 541ffc2d97..b9f393b7c7 100644
--- a/target/sh4/cpu.c
+++ b/target/sh4/cpu.c
@@ -71,7 +71,6 @@ static void superh_cpu_reset(CPUState *s)
     set_flush_to_zero(1, &env->fp_status);
 #endif
     set_default_nan_mode(1, &env->fp_status);
-    set_snan_bit_is_one(1, &env->fp_status);
 }
 
 static void superh_cpu_disas_set_info(CPUState *cpu, disassemble_info *info)
diff --git a/target/unicore32/cpu.c b/target/unicore32/cpu.c
index 29d160a88d..68f978d80b 100644
--- a/target/unicore32/cpu.c
+++ b/target/unicore32/cpu.c
@@ -70,7 +70,6 @@ static void unicore_ii_cpu_initfn(Object *obj)
 
     set_feature(env, UC32_HWCAP_CMOV);
     set_feature(env, UC32_HWCAP_UCF64);
-    set_snan_bit_is_one(1, &env->ucf64.fp_status);
 }
 
 static void uc32_any_cpu_initfn(Object *obj)
@@ -83,7 +82,6 @@ static void uc32_any_cpu_initfn(Object *obj)
 
     set_feature(env, UC32_HWCAP_CMOV);
     set_feature(env, UC32_HWCAP_UCF64);
-    set_snan_bit_is_one(1, &env->ucf64.fp_status);
 }
 
 static void uc32_cpu_realizefn(DeviceState *dev, Error **errp)
-- 
2.17.0

^ permalink raw reply related	[flat|nested] 29+ messages in thread

* [Qemu-devel] [PATCH 18/19] fpu/softfloat: Pass FloatClass to pickNaN
  2018-05-11  0:43 [Qemu-devel] [PATCH 00/19] softfloat: Clean up NaN handling Richard Henderson
                   ` (16 preceding siblings ...)
  2018-05-11  0:43 ` [Qemu-devel] [PATCH 17/19] fpu/softfloat: Introduce SNAN_BIT_IS_ONE Richard Henderson
@ 2018-05-11  0:43 ` Richard Henderson
  2018-05-11  0:43 ` [Qemu-devel] [PATCH 19/19] fpu/softfloat: Pass FloatClass to pickNaNMulAdd Richard Henderson
  18 siblings, 0 replies; 29+ messages in thread
From: Richard Henderson @ 2018-05-11  0:43 UTC (permalink / raw)
  To: qemu-devel; +Cc: peter.maydell, alex.bennee

For each operand, pass a single enumeration instead of a pair of booleans.

Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
---
 fpu/softfloat-specialize.h | 168 ++++++++++++++++++-------------------
 fpu/softfloat.c            |  35 ++++----
 2 files changed, 98 insertions(+), 105 deletions(-)

diff --git a/fpu/softfloat-specialize.h b/fpu/softfloat-specialize.h
index e7b4544e48..83e5bf83b9 100644
--- a/fpu/softfloat-specialize.h
+++ b/fpu/softfloat-specialize.h
@@ -490,10 +490,10 @@ static float32 commonNaNToFloat32(commonNaNT a, float_status *status)
 | tie-break rule.
 *----------------------------------------------------------------------------*/
 
-#if defined(TARGET_ARM)
-static int pickNaN(flag aIsQNaN, flag aIsSNaN, flag bIsQNaN, flag bIsSNaN,
+static int pickNaN(FloatClass a_cls, FloatClass b_cls,
                    flag aIsLargerSignificand)
 {
+#if defined(TARGET_ARM) || defined(TARGET_MIPS) || defined(TARGET_HPPA)
     /* ARM mandated NaN propagation rules (see FPProcessNaNs()), take
      * the first of:
      *  1. A if it is signaling
@@ -502,20 +502,6 @@ static int pickNaN(flag aIsQNaN, flag aIsSNaN, flag bIsQNaN, flag bIsSNaN,
      *  4. B (quiet)
      * A signaling NaN is always quietened before returning it.
      */
-    if (aIsSNaN) {
-        return 0;
-    } else if (bIsSNaN) {
-        return 1;
-    } else if (aIsQNaN) {
-        return 0;
-    } else {
-        return 1;
-    }
-}
-#elif defined(TARGET_MIPS) || defined(TARGET_HPPA)
-static int pickNaN(flag aIsQNaN, flag aIsSNaN, flag bIsQNaN, flag bIsSNaN,
-                    flag aIsLargerSignificand)
-{
     /* According to MIPS specifications, if one of the two operands is
      * a sNaN, a new qNaN has to be generated. This is done in
      * floatXX_silence_nan(). For qNaN inputs the specifications
@@ -529,35 +515,21 @@ static int pickNaN(flag aIsQNaN, flag aIsSNaN, flag bIsQNaN, flag bIsSNaN,
      *  4. B (quiet)
      * A signaling NaN is always silenced before returning it.
      */
-    if (aIsSNaN) {
+    if (is_snan(a_cls)) {
         return 0;
-    } else if (bIsSNaN) {
+    } else if (is_snan(b_cls)) {
         return 1;
-    } else if (aIsQNaN) {
+    } else if (is_qnan(a_cls)) {
         return 0;
     } else {
         return 1;
     }
-}
-#elif defined(TARGET_PPC) || defined(TARGET_XTENSA)
-static int pickNaN(flag aIsQNaN, flag aIsSNaN, flag bIsQNaN, flag bIsSNaN,
-                   flag aIsLargerSignificand)
-{
+#elif defined(TARGET_PPC) || defined(TARGET_XTENSA) || defined(TARGET_M68K)
     /* PowerPC propagation rules:
      *  1. A if it sNaN or qNaN
      *  2. B if it sNaN or qNaN
      * A signaling NaN is always silenced before returning it.
      */
-    if (aIsSNaN || aIsQNaN) {
-        return 0;
-    } else {
-        return 1;
-    }
-}
-#elif defined(TARGET_M68K)
-static int pickNaN(flag aIsQNaN, flag aIsSNaN, flag bIsQNaN, flag bIsSNaN,
-                   flag aIsLargerSignificand)
-{
     /* M68000 FAMILY PROGRAMMER'S REFERENCE MANUAL
      * 3.4 FLOATING-POINT INSTRUCTION DETAILS
      * If either operand, but not both operands, of an operation is a
@@ -572,16 +544,12 @@ static int pickNaN(flag aIsQNaN, flag aIsSNaN, flag bIsQNaN, flag bIsSNaN,
      * a nonsignaling NaN. The operation then continues as described in the
      * preceding paragraph for nonsignaling NaNs.
      */
-    if (aIsQNaN || aIsSNaN) { /* a is the destination operand */
-        return 0; /* return the destination operand */
+    if (is_nan(a_cls)) {
+        return 0;
     } else {
-        return 1; /* return b */
+        return 1;
     }
-}
 #else
-static int pickNaN(flag aIsQNaN, flag aIsSNaN, flag bIsQNaN, flag bIsSNaN,
-                    flag aIsLargerSignificand)
-{
     /* This implements x87 NaN propagation rules:
      * SNaN + QNaN => return the QNaN
      * two SNaNs => return the one with the larger significand, silenced
@@ -592,13 +560,13 @@ static int pickNaN(flag aIsQNaN, flag aIsSNaN, flag bIsQNaN, flag bIsSNaN,
      * If we get down to comparing significands and they are the same,
      * return the NaN with the positive sign bit (if any).
      */
-    if (aIsSNaN) {
-        if (bIsSNaN) {
+    if (is_snan(a_cls)) {
+        if (is_snan(b_cls)) {
             return aIsLargerSignificand ? 0 : 1;
         }
-        return bIsQNaN ? 1 : 0;
-    } else if (aIsQNaN) {
-        if (bIsSNaN || !bIsQNaN) {
+        return is_qnan(b_cls) ? 1 : 0;
+    } else if (is_qnan(a_cls)) {
+        if (is_snan(b_cls) || !is_qnan(b_cls)) {
             return 0;
         } else {
             return aIsLargerSignificand ? 0 : 1;
@@ -606,8 +574,8 @@ static int pickNaN(flag aIsQNaN, flag aIsSNaN, flag bIsQNaN, flag bIsSNaN,
     } else {
         return 1;
     }
-}
 #endif
+}
 
 /*----------------------------------------------------------------------------
 | Select which NaN to propagate for a three-input operation.
@@ -741,18 +709,26 @@ static int pickNaNMulAdd(flag aIsQNaN, flag aIsSNaN, flag bIsQNaN, flag bIsSNaN,
 
 static float32 propagateFloat32NaN(float32 a, float32 b, float_status *status)
 {
-    flag aIsQuietNaN, aIsSignalingNaN, bIsQuietNaN, bIsSignalingNaN;
     flag aIsLargerSignificand;
     uint32_t av, bv;
+    FloatClass a_cls, b_cls;
+
+    /* This is not complete, but is good enough for pickNaN.  */
+    a_cls = (!float32_is_any_nan(a)
+             ? float_class_normal
+             : float32_is_signaling_nan(a, status)
+             ? float_class_snan
+             : float_class_qnan);
+    b_cls = (!float32_is_any_nan(b)
+             ? float_class_normal
+             : float32_is_signaling_nan(b, status)
+             ? float_class_snan
+             : float_class_qnan);
 
-    aIsQuietNaN = float32_is_quiet_nan(a, status);
-    aIsSignalingNaN = float32_is_signaling_nan(a, status);
-    bIsQuietNaN = float32_is_quiet_nan(b, status);
-    bIsSignalingNaN = float32_is_signaling_nan(b, status);
     av = float32_val(a);
     bv = float32_val(b);
 
-    if (aIsSignalingNaN | bIsSignalingNaN) {
+    if (is_snan(a_cls) || is_snan(b_cls)) {
         float_raise(float_flag_invalid, status);
     }
 
@@ -768,14 +744,13 @@ static float32 propagateFloat32NaN(float32 a, float32 b, float_status *status)
         aIsLargerSignificand = (av < bv) ? 1 : 0;
     }
 
-    if (pickNaN(aIsQuietNaN, aIsSignalingNaN, bIsQuietNaN, bIsSignalingNaN,
-                aIsLargerSignificand)) {
-        if (bIsSignalingNaN) {
+    if (pickNaN(a_cls, b_cls, aIsLargerSignificand)) {
+        if (is_snan(b_cls)) {
             return float32_silence_nan(b, status);
         }
         return b;
     } else {
-        if (aIsSignalingNaN) {
+        if (is_snan(a_cls)) {
             return float32_silence_nan(a, status);
         }
         return a;
@@ -897,18 +872,26 @@ static float64 commonNaNToFloat64(commonNaNT a, float_status *status)
 
 static float64 propagateFloat64NaN(float64 a, float64 b, float_status *status)
 {
-    flag aIsQuietNaN, aIsSignalingNaN, bIsQuietNaN, bIsSignalingNaN;
     flag aIsLargerSignificand;
     uint64_t av, bv;
+    FloatClass a_cls, b_cls;
+
+    /* This is not complete, but is good enough for pickNaN.  */
+    a_cls = (!float64_is_any_nan(a)
+             ? float_class_normal
+             : float64_is_signaling_nan(a, status)
+             ? float_class_snan
+             : float_class_qnan);
+    b_cls = (!float64_is_any_nan(b)
+             ? float_class_normal
+             : float64_is_signaling_nan(b, status)
+             ? float_class_snan
+             : float_class_qnan);
 
-    aIsQuietNaN = float64_is_quiet_nan(a, status);
-    aIsSignalingNaN = float64_is_signaling_nan(a, status);
-    bIsQuietNaN = float64_is_quiet_nan(b, status);
-    bIsSignalingNaN = float64_is_signaling_nan(b, status);
     av = float64_val(a);
     bv = float64_val(b);
 
-    if (aIsSignalingNaN | bIsSignalingNaN) {
+    if (is_snan(a_cls) || is_snan(b_cls)) {
         float_raise(float_flag_invalid, status);
     }
 
@@ -924,14 +907,13 @@ static float64 propagateFloat64NaN(float64 a, float64 b, float_status *status)
         aIsLargerSignificand = (av < bv) ? 1 : 0;
     }
 
-    if (pickNaN(aIsQuietNaN, aIsSignalingNaN, bIsQuietNaN, bIsSignalingNaN,
-                aIsLargerSignificand)) {
-        if (bIsSignalingNaN) {
+    if (pickNaN(a_cls, b_cls, aIsLargerSignificand)) {
+        if (is_snan(b_cls)) {
             return float64_silence_nan(b, status);
         }
         return b;
     } else {
-        if (aIsSignalingNaN) {
+        if (is_snan(a_cls)) {
             return float64_silence_nan(a, status);
         }
         return a;
@@ -1064,15 +1046,22 @@ static floatx80 commonNaNToFloatx80(commonNaNT a, float_status *status)
 
 floatx80 propagateFloatx80NaN(floatx80 a, floatx80 b, float_status *status)
 {
-    flag aIsQuietNaN, aIsSignalingNaN, bIsQuietNaN, bIsSignalingNaN;
     flag aIsLargerSignificand;
+    FloatClass a_cls, b_cls;
 
-    aIsQuietNaN = floatx80_is_quiet_nan(a, status);
-    aIsSignalingNaN = floatx80_is_signaling_nan(a, status);
-    bIsQuietNaN = floatx80_is_quiet_nan(b, status);
-    bIsSignalingNaN = floatx80_is_signaling_nan(b, status);
+    /* This is not complete, but is good enough for pickNaN.  */
+    a_cls = (!floatx80_is_any_nan(a)
+             ? float_class_normal
+             : floatx80_is_signaling_nan(a, status)
+             ? float_class_snan
+             : float_class_qnan);
+    b_cls = (!floatx80_is_any_nan(b)
+             ? float_class_normal
+             : floatx80_is_signaling_nan(b, status)
+             ? float_class_snan
+             : float_class_qnan);
 
-    if (aIsSignalingNaN | bIsSignalingNaN) {
+    if (is_snan(a_cls) || is_snan(b_cls)) {
         float_raise(float_flag_invalid, status);
     }
 
@@ -1088,14 +1077,13 @@ floatx80 propagateFloatx80NaN(floatx80 a, floatx80 b, float_status *status)
         aIsLargerSignificand = (a.high < b.high) ? 1 : 0;
     }
 
-    if (pickNaN(aIsQuietNaN, aIsSignalingNaN, bIsQuietNaN, bIsSignalingNaN,
-                aIsLargerSignificand)) {
-        if (bIsSignalingNaN) {
+    if (pickNaN(a_cls, b_cls, aIsLargerSignificand)) {
+        if (is_snan(b_cls)) {
             return floatx80_silence_nan(b, status);
         }
         return b;
     } else {
-        if (aIsSignalingNaN) {
+        if (is_snan(a_cls)) {
             return floatx80_silence_nan(a, status);
         }
         return a;
@@ -1206,15 +1194,22 @@ static float128 commonNaNToFloat128(commonNaNT a, float_status *status)
 static float128 propagateFloat128NaN(float128 a, float128 b,
                                      float_status *status)
 {
-    flag aIsQuietNaN, aIsSignalingNaN, bIsQuietNaN, bIsSignalingNaN;
     flag aIsLargerSignificand;
+    FloatClass a_cls, b_cls;
 
-    aIsQuietNaN = float128_is_quiet_nan(a, status);
-    aIsSignalingNaN = float128_is_signaling_nan(a, status);
-    bIsQuietNaN = float128_is_quiet_nan(b, status);
-    bIsSignalingNaN = float128_is_signaling_nan(b, status);
+    /* This is not complete, but is good enough for pickNaN.  */
+    a_cls = (!float128_is_any_nan(a)
+             ? float_class_normal
+             : float128_is_signaling_nan(a, status)
+             ? float_class_snan
+             : float_class_qnan);
+    b_cls = (!float128_is_any_nan(b)
+             ? float_class_normal
+             : float128_is_signaling_nan(b, status)
+             ? float_class_snan
+             : float_class_qnan);
 
-    if (aIsSignalingNaN | bIsSignalingNaN) {
+    if (is_snan(a_cls) || is_snan(b_cls)) {
         float_raise(float_flag_invalid, status);
     }
 
@@ -1230,14 +1225,13 @@ static float128 propagateFloat128NaN(float128 a, float128 b,
         aIsLargerSignificand = (a.high < b.high) ? 1 : 0;
     }
 
-    if (pickNaN(aIsQuietNaN, aIsSignalingNaN, bIsQuietNaN, bIsSignalingNaN,
-                aIsLargerSignificand)) {
-        if (bIsSignalingNaN) {
+    if (pickNaN(a_cls, b_cls, aIsLargerSignificand)) {
+        if (is_snan(b_cls)) {
             return float128_silence_nan(b, status);
         }
         return b;
     } else {
-        if (aIsSignalingNaN) {
+        if (is_snan(a_cls)) {
             return float128_silence_nan(a, status);
         }
         return a;
diff --git a/fpu/softfloat.c b/fpu/softfloat.c
index cce94136d4..cd56beb277 100644
--- a/fpu/softfloat.c
+++ b/fpu/softfloat.c
@@ -181,6 +181,22 @@ typedef enum __attribute__ ((__packed__)) {
     float_class_snan,
 } FloatClass;
 
+/* Simple helpers for checking if what NaN we have */
+static bool is_nan(FloatClass c)
+{
+    return unlikely(c >= float_class_qnan);
+}
+
+static bool is_snan(FloatClass c)
+{
+    return c == float_class_snan;
+}
+
+static bool is_qnan(FloatClass c)
+{
+    return c == float_class_qnan;
+}
+
 /*
  * Structure holding all of the decomposed parts of a float. The
  * exponent is unbiased and the fraction is normalized. All
@@ -546,22 +562,6 @@ static float64 float64_round_pack_canonical(FloatParts p, float_status *s)
     return float64_pack_raw(round_canonical(p, s, &float64_params));
 }
 
-/* Simple helpers for checking if what NaN we have */
-static bool is_nan(FloatClass c)
-{
-    return unlikely(c >= float_class_qnan);
-}
-
-static bool is_snan(FloatClass c)
-{
-    return c == float_class_snan;
-}
-
-static bool is_qnan(FloatClass c)
-{
-    return c == float_class_qnan;
-}
-
 static FloatParts return_nan(FloatParts a, float_status *s)
 {
     switch (a.cls) {
@@ -590,8 +590,7 @@ static FloatParts pick_nan(FloatParts a, FloatParts b, float_status *s)
     if (s->default_nan_mode) {
         return parts_default_nan(s);
     } else {
-        if (pickNaN(is_qnan(a.cls), is_snan(a.cls),
-                    is_qnan(b.cls), is_snan(b.cls),
+        if (pickNaN(a.cls, b.cls,
                     a.frac > b.frac ||
                     (a.frac == b.frac && a.sign < b.sign))) {
             a = b;
-- 
2.17.0

^ permalink raw reply related	[flat|nested] 29+ messages in thread

* [Qemu-devel] [PATCH 19/19] fpu/softfloat: Pass FloatClass to pickNaNMulAdd
  2018-05-11  0:43 [Qemu-devel] [PATCH 00/19] softfloat: Clean up NaN handling Richard Henderson
                   ` (17 preceding siblings ...)
  2018-05-11  0:43 ` [Qemu-devel] [PATCH 18/19] fpu/softfloat: Pass FloatClass to pickNaN Richard Henderson
@ 2018-05-11  0:43 ` Richard Henderson
  18 siblings, 0 replies; 29+ messages in thread
From: Richard Henderson @ 2018-05-11  0:43 UTC (permalink / raw)
  To: qemu-devel; +Cc: peter.maydell, alex.bennee

For each operand, pass a single enumeration instead of a pair of booleans.

Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
---
 fpu/softfloat-specialize.h | 70 +++++++++++++++-----------------------
 fpu/softfloat.c            | 11 +++---
 2 files changed, 31 insertions(+), 50 deletions(-)

diff --git a/fpu/softfloat-specialize.h b/fpu/softfloat-specialize.h
index 83e5bf83b9..637f1ea1be 100644
--- a/fpu/softfloat-specialize.h
+++ b/fpu/softfloat-specialize.h
@@ -583,15 +583,14 @@ static int pickNaN(FloatClass a_cls, FloatClass b_cls,
 | information.
 | Return values : 0 : a; 1 : b; 2 : c; 3 : default-NaN
 *----------------------------------------------------------------------------*/
-#if defined(TARGET_ARM)
-static int pickNaNMulAdd(flag aIsQNaN, flag aIsSNaN, flag bIsQNaN, flag bIsSNaN,
-                         flag cIsQNaN, flag cIsSNaN, flag infzero,
-                         float_status *status)
+static int pickNaNMulAdd(FloatClass a_cls, FloatClass b_cls, FloatClass c_cls,
+                         bool infzero, float_status *status)
 {
+#if defined(TARGET_ARM)
     /* For ARM, the (inf,zero,qnan) case sets InvalidOp and returns
      * the default NaN
      */
-    if (infzero && cIsQNaN) {
+    if (infzero && is_qnan(c_cls)) {
         float_raise(float_flag_invalid, status);
         return 3;
     }
@@ -599,25 +598,20 @@ static int pickNaNMulAdd(flag aIsQNaN, flag aIsSNaN, flag bIsQNaN, flag bIsSNaN,
     /* This looks different from the ARM ARM pseudocode, because the ARM ARM
      * puts the operands to a fused mac operation (a*b)+c in the order c,a,b.
      */
-    if (cIsSNaN) {
+    if (is_snan(c_cls)) {
         return 2;
-    } else if (aIsSNaN) {
+    } else if (is_snan(a_cls)) {
         return 0;
-    } else if (bIsSNaN) {
+    } else if (is_snan(b_cls)) {
         return 1;
-    } else if (cIsQNaN) {
+    } else if (is_qnan(c_cls)) {
         return 2;
-    } else if (aIsQNaN) {
+    } else if (is_qnan(a_cls)) {
         return 0;
     } else {
         return 1;
     }
-}
 #elif defined(TARGET_MIPS)
-static int pickNaNMulAdd(flag aIsQNaN, flag aIsSNaN, flag bIsQNaN, flag bIsSNaN,
-                         flag cIsQNaN, flag cIsSNaN, flag infzero,
-                         float_status *status)
-{
     /* For MIPS, the (inf,zero,qnan) case sets InvalidOp and returns
      * the default NaN
      */
@@ -628,41 +622,36 @@ static int pickNaNMulAdd(flag aIsQNaN, flag aIsSNaN, flag bIsQNaN, flag bIsSNaN,
 
     if (SNAN_BIT_IS_ONE(status)) {
         /* Prefer sNaN over qNaN, in the a, b, c order. */
-        if (aIsSNaN) {
+        if (is_snan(a_cls)) {
             return 0;
-        } else if (bIsSNaN) {
+        } else if (is_snan(b_cls)) {
             return 1;
-        } else if (cIsSNaN) {
+        } else if (is_snan(c_cls)) {
             return 2;
-        } else if (aIsQNaN) {
+        } else if (is_qnan(a_cls)) {
             return 0;
-        } else if (bIsQNaN) {
+        } else if (is_qnan(b_cls)) {
             return 1;
         } else {
             return 2;
         }
     } else {
         /* Prefer sNaN over qNaN, in the c, a, b order. */
-        if (cIsSNaN) {
+        if (is_snan(c_cls)) {
             return 2;
-        } else if (aIsSNaN) {
+        } else if (is_snan(a_cls)) {
             return 0;
-        } else if (bIsSNaN) {
+        } else if (is_snan(b_cls)) {
             return 1;
-        } else if (cIsQNaN) {
+        } else if (is_qnan(c_cls)) {
             return 2;
-        } else if (aIsQNaN) {
+        } else if (is_qnan(a_cls)) {
             return 0;
         } else {
             return 1;
         }
     }
-}
 #elif defined(TARGET_PPC)
-static int pickNaNMulAdd(flag aIsQNaN, flag aIsSNaN, flag bIsQNaN, flag bIsSNaN,
-                         flag cIsQNaN, flag cIsSNaN, flag infzero,
-                         float_status *status)
-{
     /* For PPC, the (inf,zero,qnan) case sets InvalidOp, but we prefer
      * to return an input NaN if we have one (ie c) rather than generating
      * a default NaN
@@ -675,31 +664,26 @@ static int pickNaNMulAdd(flag aIsQNaN, flag aIsSNaN, flag bIsQNaN, flag bIsSNaN,
     /* If fRA is a NaN return it; otherwise if fRB is a NaN return it;
      * otherwise return fRC. Note that muladd on PPC is (fRA * fRC) + frB
      */
-    if (aIsSNaN || aIsQNaN) {
+    if (is_nan(a_cls)) {
         return 0;
-    } else if (cIsSNaN || cIsQNaN) {
+    } else if (is_nan(c_cls)) {
         return 2;
     } else {
         return 1;
     }
-}
 #else
-/* A default implementation: prefer a to b to c.
- * This is unlikely to actually match any real implementation.
- */
-static int pickNaNMulAdd(flag aIsQNaN, flag aIsSNaN, flag bIsQNaN, flag bIsSNaN,
-                         flag cIsQNaN, flag cIsSNaN, flag infzero,
-                         float_status *status)
-{
-    if (aIsSNaN || aIsQNaN) {
+    /* A default implementation: prefer a to b to c.
+     * This is unlikely to actually match any real implementation.
+     */
+    if (is_nan(a_cls)) {
         return 0;
-    } else if (bIsSNaN || bIsQNaN) {
+    } else if (is_nan(b_cls)) {
         return 1;
     } else {
         return 2;
     }
-}
 #endif
+}
 
 /*----------------------------------------------------------------------------
 | Takes two single-precision floating-point values `a' and `b', one of which
diff --git a/fpu/softfloat.c b/fpu/softfloat.c
index cd56beb277..4e957a5d6f 100644
--- a/fpu/softfloat.c
+++ b/fpu/softfloat.c
@@ -182,17 +182,17 @@ typedef enum __attribute__ ((__packed__)) {
 } FloatClass;
 
 /* Simple helpers for checking if what NaN we have */
-static bool is_nan(FloatClass c)
+static inline __attribute__((unused)) bool is_nan(FloatClass c)
 {
     return unlikely(c >= float_class_qnan);
 }
 
-static bool is_snan(FloatClass c)
+static inline __attribute__((unused)) bool is_snan(FloatClass c)
 {
     return c == float_class_snan;
 }
 
-static bool is_qnan(FloatClass c)
+static inline __attribute__((unused)) bool is_qnan(FloatClass c)
 {
     return c == float_class_qnan;
 }
@@ -612,10 +612,7 @@ static FloatParts pick_nan_muladd(FloatParts a, FloatParts b, FloatParts c,
     if (s->default_nan_mode) {
         return parts_default_nan(s);
     } else {
-        switch (pickNaNMulAdd(is_qnan(a.cls), is_snan(a.cls),
-                              is_qnan(b.cls), is_snan(b.cls),
-                              is_qnan(c.cls), is_snan(c.cls),
-                              inf_zero, s)) {
+        switch (pickNaNMulAdd(a.cls, b.cls, c.cls, inf_zero, s)) {
         case 0:
             break;
         case 1:
-- 
2.17.0

^ permalink raw reply related	[flat|nested] 29+ messages in thread

* Re: [Qemu-devel] [PATCH 01/19] fpu/softfloat: Merge NO_SIGNALING_NANS definitions
  2018-05-11  0:43 ` [Qemu-devel] [PATCH 01/19] fpu/softfloat: Merge NO_SIGNALING_NANS definitions Richard Henderson
@ 2018-05-11  6:44   ` Alex Bennée
  0 siblings, 0 replies; 29+ messages in thread
From: Alex Bennée @ 2018-05-11  6:44 UTC (permalink / raw)
  To: Richard Henderson; +Cc: qemu-devel, peter.maydell


Richard Henderson <richard.henderson@linaro.org> writes:

> Move the ifdef inside the relevant functions instead of
> duplicating the function declarations.
>
> Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
Reviewed-by: Alex Bennée <alex.bennee@linaro.org>

> ---
>  fpu/softfloat-specialize.h | 100 +++++++++++++++----------------------
>  1 file changed, 40 insertions(+), 60 deletions(-)
>
> diff --git a/fpu/softfloat-specialize.h b/fpu/softfloat-specialize.h
> index a20b440159..8bd553abd2 100644
> --- a/fpu/softfloat-specialize.h
> +++ b/fpu/softfloat-specialize.h
> @@ -233,17 +233,6 @@ typedef struct {
>      uint64_t high, low;
>  } commonNaNT;
>
> -#ifdef NO_SIGNALING_NANS
> -int float16_is_quiet_nan(float16 a_, float_status *status)
> -{
> -    return float16_is_any_nan(a_);
> -}
> -
> -int float16_is_signaling_nan(float16 a_, float_status *status)
> -{
> -    return 0;
> -}
> -#else
>  /*----------------------------------------------------------------------------
>  | Returns 1 if the half-precision floating-point value `a' is a quiet
>  | NaN; otherwise returns 0.
> @@ -251,12 +240,16 @@ int float16_is_signaling_nan(float16 a_, float_status *status)
>
>  int float16_is_quiet_nan(float16 a_, float_status *status)
>  {
> +#ifdef NO_SIGNALING_NANS
> +    return float16_is_any_nan(a_);
> +#else
>      uint16_t a = float16_val(a_);
>      if (status->snan_bit_is_one) {
>          return (((a >> 9) & 0x3F) == 0x3E) && (a & 0x1FF);
>      } else {
>          return ((a & ~0x8000) >= 0x7C80);
>      }
> +#endif
>  }
>
>  /*----------------------------------------------------------------------------
> @@ -266,14 +259,17 @@ int float16_is_quiet_nan(float16 a_, float_status *status)
>
>  int float16_is_signaling_nan(float16 a_, float_status *status)
>  {
> +#ifdef NO_SIGNALING_NANS
> +    return 0;
> +#else
>      uint16_t a = float16_val(a_);
>      if (status->snan_bit_is_one) {
>          return ((a & ~0x8000) >= 0x7C80);
>      } else {
>          return (((a >> 9) & 0x3F) == 0x3E) && (a & 0x1FF);
>      }
> -}
>  #endif
> +}
>
>  /*----------------------------------------------------------------------------
>  | Returns a quiet NaN if the half-precision floating point value `a' is a
> @@ -293,17 +289,6 @@ float16 float16_maybe_silence_nan(float16 a_, float_status *status)
>      return a_;
>  }
>
> -#ifdef NO_SIGNALING_NANS
> -int float32_is_quiet_nan(float32 a_, float_status *status)
> -{
> -    return float32_is_any_nan(a_);
> -}
> -
> -int float32_is_signaling_nan(float32 a_, float_status *status)
> -{
> -    return 0;
> -}
> -#else
>  /*----------------------------------------------------------------------------
>  | Returns 1 if the single-precision floating-point value `a' is a quiet
>  | NaN; otherwise returns 0.
> @@ -311,12 +296,16 @@ int float32_is_signaling_nan(float32 a_, float_status *status)
>
>  int float32_is_quiet_nan(float32 a_, float_status *status)
>  {
> +#ifdef NO_SIGNALING_NANS
> +    return float32_is_any_nan(a_);
> +#else
>      uint32_t a = float32_val(a_);
>      if (status->snan_bit_is_one) {
>          return (((a >> 22) & 0x1FF) == 0x1FE) && (a & 0x003FFFFF);
>      } else {
>          return ((uint32_t)(a << 1) >= 0xFF800000);
>      }
> +#endif
>  }
>
>  /*----------------------------------------------------------------------------
> @@ -326,14 +315,17 @@ int float32_is_quiet_nan(float32 a_, float_status *status)
>
>  int float32_is_signaling_nan(float32 a_, float_status *status)
>  {
> +#ifdef NO_SIGNALING_NANS
> +    return 0;
> +#else
>      uint32_t a = float32_val(a_);
>      if (status->snan_bit_is_one) {
>          return ((uint32_t)(a << 1) >= 0xFF800000);
>      } else {
>          return (((a >> 22) & 0x1FF) == 0x1FE) && (a & 0x003FFFFF);
>      }
> -}
>  #endif
> +}
>
>  /*----------------------------------------------------------------------------
>  | Returns a quiet NaN if the single-precision floating point value `a' is a
> @@ -704,17 +696,6 @@ static float32 propagateFloat32NaN(float32 a, float32 b, float_status *status)
>      }
>  }
>
> -#ifdef NO_SIGNALING_NANS
> -int float64_is_quiet_nan(float64 a_, float_status *status)
> -{
> -    return float64_is_any_nan(a_);
> -}
> -
> -int float64_is_signaling_nan(float64 a_, float_status *status)
> -{
> -    return 0;
> -}
> -#else
>  /*----------------------------------------------------------------------------
>  | Returns 1 if the double-precision floating-point value `a' is a quiet
>  | NaN; otherwise returns 0.
> @@ -722,6 +703,9 @@ int float64_is_signaling_nan(float64 a_, float_status *status)
>
>  int float64_is_quiet_nan(float64 a_, float_status *status)
>  {
> +#ifdef NO_SIGNALING_NANS
> +    return float64_is_any_nan(a_);
> +#else
>      uint64_t a = float64_val(a_);
>      if (status->snan_bit_is_one) {
>          return (((a >> 51) & 0xFFF) == 0xFFE)
> @@ -729,6 +713,7 @@ int float64_is_quiet_nan(float64 a_, float_status *status)
>      } else {
>          return ((a << 1) >= 0xFFF0000000000000ULL);
>      }
> +#endif
>  }
>
>  /*----------------------------------------------------------------------------
> @@ -738,6 +723,9 @@ int float64_is_quiet_nan(float64 a_, float_status *status)
>
>  int float64_is_signaling_nan(float64 a_, float_status *status)
>  {
> +#ifdef NO_SIGNALING_NANS
> +    return 0;
> +#else
>      uint64_t a = float64_val(a_);
>      if (status->snan_bit_is_one) {
>          return ((a << 1) >= 0xFFF0000000000000ULL);
> @@ -745,8 +733,8 @@ int float64_is_signaling_nan(float64 a_, float_status *status)
>          return (((a >> 51) & 0xFFF) == 0xFFE)
>              && (a & LIT64(0x0007FFFFFFFFFFFF));
>      }
> -}
>  #endif
> +}
>
>  /*----------------------------------------------------------------------------
>  | Returns a quiet NaN if the double-precision floating point value `a' is a
> @@ -859,17 +847,6 @@ static float64 propagateFloat64NaN(float64 a, float64 b, float_status *status)
>      }
>  }
>
> -#ifdef NO_SIGNALING_NANS
> -int floatx80_is_quiet_nan(floatx80 a_, float_status *status)
> -{
> -    return floatx80_is_any_nan(a_);
> -}
> -
> -int floatx80_is_signaling_nan(floatx80 a_, float_status *status)
> -{
> -    return 0;
> -}
> -#else
>  /*----------------------------------------------------------------------------
>  | Returns 1 if the extended double-precision floating-point value `a' is a
>  | quiet NaN; otherwise returns 0. This slightly differs from the same
> @@ -878,6 +855,9 @@ int floatx80_is_signaling_nan(floatx80 a_, float_status *status)
>
>  int floatx80_is_quiet_nan(floatx80 a, float_status *status)
>  {
> +#ifdef NO_SIGNALING_NANS
> +    return floatx80_is_any_nan(a);
> +#else
>      if (status->snan_bit_is_one) {
>          uint64_t aLow;
>
> @@ -889,6 +869,7 @@ int floatx80_is_quiet_nan(floatx80 a, float_status *status)
>          return ((a.high & 0x7FFF) == 0x7FFF)
>              && (LIT64(0x8000000000000000) <= ((uint64_t)(a.low << 1)));
>      }
> +#endif
>  }
>
>  /*----------------------------------------------------------------------------
> @@ -899,6 +880,9 @@ int floatx80_is_quiet_nan(floatx80 a, float_status *status)
>
>  int floatx80_is_signaling_nan(floatx80 a, float_status *status)
>  {
> +#ifdef NO_SIGNALING_NANS
> +    return 0;
> +#else
>      if (status->snan_bit_is_one) {
>          return ((a.high & 0x7FFF) == 0x7FFF)
>              && ((a.low << 1) >= 0x8000000000000000ULL);
> @@ -910,8 +894,8 @@ int floatx80_is_signaling_nan(floatx80 a, float_status *status)
>              && (uint64_t)(aLow << 1)
>              && (a.low == aLow);
>      }
> -}
>  #endif
> +}
>
>  /*----------------------------------------------------------------------------
>  | Returns a quiet NaN if the extended double-precision floating point value
> @@ -1020,17 +1004,6 @@ floatx80 propagateFloatx80NaN(floatx80 a, floatx80 b, float_status *status)
>      }
>  }
>
> -#ifdef NO_SIGNALING_NANS
> -int float128_is_quiet_nan(float128 a_, float_status *status)
> -{
> -    return float128_is_any_nan(a_);
> -}
> -
> -int float128_is_signaling_nan(float128 a_, float_status *status)
> -{
> -    return 0;
> -}
> -#else
>  /*----------------------------------------------------------------------------
>  | Returns 1 if the quadruple-precision floating-point value `a' is a quiet
>  | NaN; otherwise returns 0.
> @@ -1038,6 +1011,9 @@ int float128_is_signaling_nan(float128 a_, float_status *status)
>
>  int float128_is_quiet_nan(float128 a, float_status *status)
>  {
> +#ifdef NO_SIGNALING_NANS
> +    return float128_is_any_nan(a);
> +#else
>      if (status->snan_bit_is_one) {
>          return (((a.high >> 47) & 0xFFFF) == 0xFFFE)
>              && (a.low || (a.high & 0x00007FFFFFFFFFFFULL));
> @@ -1045,6 +1021,7 @@ int float128_is_quiet_nan(float128 a, float_status *status)
>          return ((a.high << 1) >= 0xFFFF000000000000ULL)
>              && (a.low || (a.high & 0x0000FFFFFFFFFFFFULL));
>      }
> +#endif
>  }
>
>  /*----------------------------------------------------------------------------
> @@ -1054,6 +1031,9 @@ int float128_is_quiet_nan(float128 a, float_status *status)
>
>  int float128_is_signaling_nan(float128 a, float_status *status)
>  {
> +#ifdef NO_SIGNALING_NANS
> +    return 0;
> +#else
>      if (status->snan_bit_is_one) {
>          return ((a.high << 1) >= 0xFFFF000000000000ULL)
>              && (a.low || (a.high & 0x0000FFFFFFFFFFFFULL));
> @@ -1061,8 +1041,8 @@ int float128_is_signaling_nan(float128 a, float_status *status)
>          return (((a.high >> 47) & 0xFFFF) == 0xFFFE)
>              && (a.low || (a.high & LIT64(0x00007FFFFFFFFFFF)));
>      }
> -}
>  #endif
> +}
>
>  /*----------------------------------------------------------------------------
>  | Returns a quiet NaN if the quadruple-precision floating point value `a' is


--
Alex Bennée

^ permalink raw reply	[flat|nested] 29+ messages in thread

* Re: [Qemu-devel] [PATCH 14/19] target/s390x: Remove floatX_maybe_silence_nan from conversions
  2018-05-11  0:43 ` [Qemu-devel] [PATCH 14/19] target/s390x: " Richard Henderson
@ 2018-05-11  6:47   ` David Hildenbrand
  0 siblings, 0 replies; 29+ messages in thread
From: David Hildenbrand @ 2018-05-11  6:47 UTC (permalink / raw)
  To: Richard Henderson, qemu-devel; +Cc: peter.maydell, alex.bennee, Alexander Graf

On 11.05.2018 02:43, Richard Henderson wrote:
> This is now handled properly by the generic softfloat code.
> 
> Cc: Alexander Graf <agraf@suse.de>
> Cc: David Hildenbrand <david@redhat.com>
> Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
> ---
>  target/s390x/fpu_helper.c | 12 ++++++------
>  1 file changed, 6 insertions(+), 6 deletions(-)
> 
> diff --git a/target/s390x/fpu_helper.c b/target/s390x/fpu_helper.c
> index 43f8bf1c94..5c5b451b3b 100644
> --- a/target/s390x/fpu_helper.c
> +++ b/target/s390x/fpu_helper.c
> @@ -269,7 +269,7 @@ uint64_t HELPER(ldeb)(CPUS390XState *env, uint64_t f2)
>  {
>      float64 ret = float32_to_float64(f2, &env->fpu_status);
>      handle_exceptions(env, GETPC());
> -    return float64_maybe_silence_nan(ret, &env->fpu_status);
> +    return ret;
>  }
>  
>  /* convert 128-bit float to 64-bit float */
> @@ -277,7 +277,7 @@ uint64_t HELPER(ldxb)(CPUS390XState *env, uint64_t ah, uint64_t al)
>  {
>      float64 ret = float128_to_float64(make_float128(ah, al), &env->fpu_status);
>      handle_exceptions(env, GETPC());
> -    return float64_maybe_silence_nan(ret, &env->fpu_status);
> +    return ret;
>  }
>  
>  /* convert 64-bit float to 128-bit float */
> @@ -285,7 +285,7 @@ uint64_t HELPER(lxdb)(CPUS390XState *env, uint64_t f2)
>  {
>      float128 ret = float64_to_float128(f2, &env->fpu_status);
>      handle_exceptions(env, GETPC());
> -    return RET128(float128_maybe_silence_nan(ret, &env->fpu_status));
> +    return RET128(ret);
>  }
>  
>  /* convert 32-bit float to 128-bit float */
> @@ -293,7 +293,7 @@ uint64_t HELPER(lxeb)(CPUS390XState *env, uint64_t f2)
>  {
>      float128 ret = float32_to_float128(f2, &env->fpu_status);
>      handle_exceptions(env, GETPC());
> -    return RET128(float128_maybe_silence_nan(ret, &env->fpu_status));
> +    return RET128(ret);
>  }
>  
>  /* convert 64-bit float to 32-bit float */
> @@ -301,7 +301,7 @@ uint64_t HELPER(ledb)(CPUS390XState *env, uint64_t f2)
>  {
>      float32 ret = float64_to_float32(f2, &env->fpu_status);
>      handle_exceptions(env, GETPC());
> -    return float32_maybe_silence_nan(ret, &env->fpu_status);
> +    return ret;
>  }
>  
>  /* convert 128-bit float to 32-bit float */
> @@ -309,7 +309,7 @@ uint64_t HELPER(lexb)(CPUS390XState *env, uint64_t ah, uint64_t al)
>  {
>      float32 ret = float128_to_float32(make_float128(ah, al), &env->fpu_status);
>      handle_exceptions(env, GETPC());
> -    return float32_maybe_silence_nan(ret, &env->fpu_status);
> +    return ret;
>  }
>  
>  /* 32-bit FP compare */
> 

Reviewed-by: David Hildenbrand <david@redhat.com>

-- 

Thanks,

David / dhildenb

^ permalink raw reply	[flat|nested] 29+ messages in thread

* Re: [Qemu-devel] [PATCH 02/19] fpu/softfloat: Split floatXX_silence_nan from floatXX_maybe_silence_nan
  2018-05-11  0:43 ` [Qemu-devel] [PATCH 02/19] fpu/softfloat: Split floatXX_silence_nan from floatXX_maybe_silence_nan Richard Henderson
@ 2018-05-11  7:47   ` Alex Bennée
  2018-05-11 15:06     ` Alex Bennée
  0 siblings, 1 reply; 29+ messages in thread
From: Alex Bennée @ 2018-05-11  7:47 UTC (permalink / raw)
  To: Richard Henderson; +Cc: qemu-devel, peter.maydell


Richard Henderson <richard.henderson@linaro.org> writes:

> The new function assumes that the input is an SNaN and
> does not double-check.
>
> Signed-off-by: Richard Henderson <richard.henderson@linaro.org>

Reviewed-by: Alex Bennée <alex.bennee@linaro.org>

> ---
>  fpu/softfloat-specialize.h | 174 +++++++++++++++++++++++++------------
>  include/fpu/softfloat.h    |   5 ++
>  2 files changed, 123 insertions(+), 56 deletions(-)
>
> diff --git a/fpu/softfloat-specialize.h b/fpu/softfloat-specialize.h
> index 8bd553abd2..b59356f6a5 100644
> --- a/fpu/softfloat-specialize.h
> +++ b/fpu/softfloat-specialize.h
> @@ -271,22 +271,35 @@ int float16_is_signaling_nan(float16 a_, float_status *status)
>  #endif
>  }
>
> +/*----------------------------------------------------------------------------
> +| Returns a quiet NaN from a signalling NaN for the half-precision
> +| floating point value `a'.
> +*----------------------------------------------------------------------------*/
> +
> +float16 float16_silence_nan(float16 a, float_status *status)
> +{
> +#ifdef NO_SIGNALING_NANS
> +    g_assert_not_reached();
> +#else
> +    if (status->snan_bit_is_one) {
> +        return float16_default_nan(status);
> +    } else {
> +        return a | (1 << 9);
> +    }
> +#endif
> +}
> +
>  /*----------------------------------------------------------------------------
>  | Returns a quiet NaN if the half-precision floating point value `a' is a
>  | signaling NaN; otherwise returns `a'.
>  *----------------------------------------------------------------------------*/
> -float16 float16_maybe_silence_nan(float16 a_, float_status *status)
> +
> +float16 float16_maybe_silence_nan(float16 a, float_status *status)
>  {
> -    if (float16_is_signaling_nan(a_, status)) {
> -        if (status->snan_bit_is_one) {
> -            return float16_default_nan(status);
> -        } else {
> -            uint16_t a = float16_val(a_);
> -            a |= (1 << 9);
> -            return make_float16(a);
> -        }
> +    if (float16_is_signaling_nan(a, status)) {
> +        float16_silence_nan(a, status);
>      }
> -    return a_;
> +    return a;
>  }
>
>  /*----------------------------------------------------------------------------
> @@ -327,30 +340,40 @@ int float32_is_signaling_nan(float32 a_, float_status *status)
>  #endif
>  }
>
> +/*----------------------------------------------------------------------------
> +| Returns a quiet NaN from a signalling NaN for the single-precision
> +| floating point value `a'.
> +*----------------------------------------------------------------------------*/
> +
> +float32 float32_silence_nan(float32 a, float_status *status)
> +{
> +#ifdef NO_SIGNALING_NANS
> +    g_assert_not_reached();
> +#else
> +    if (status->snan_bit_is_one) {
> +# ifdef TARGET_HPPA
> +        a &= ~0x00400000;
> +        a |=  0x00200000;
> +        return a;
> +# else
> +        return float32_default_nan(status);
> +# endif
> +    } else {
> +        return a | (1 << 22);
> +    }
> +#endif
> +}
>  /*----------------------------------------------------------------------------
>  | Returns a quiet NaN if the single-precision floating point value `a' is a
>  | signaling NaN; otherwise returns `a'.
>  *----------------------------------------------------------------------------*/
>
> -float32 float32_maybe_silence_nan(float32 a_, float_status *status)
> +float32 float32_maybe_silence_nan(float32 a, float_status *status)
>  {
> -    if (float32_is_signaling_nan(a_, status)) {
> -        if (status->snan_bit_is_one) {
> -#ifdef TARGET_HPPA
> -            uint32_t a = float32_val(a_);
> -            a &= ~0x00400000;
> -            a |=  0x00200000;
> -            return make_float32(a);
> -#else
> -            return float32_default_nan(status);
> -#endif
> -        } else {
> -            uint32_t a = float32_val(a_);
> -            a |= (1 << 22);
> -            return make_float32(a);
> -        }
> +    if (float32_is_signaling_nan(a, status)) {
> +        float32_silence_nan(a, status);
>      }
> -    return a_;
> +    return a;
>  }
>
>  /*----------------------------------------------------------------------------
> @@ -736,30 +759,41 @@ int float64_is_signaling_nan(float64 a_, float_status *status)
>  #endif
>  }
>
> +/*----------------------------------------------------------------------------
> +| Returns a quiet NaN from a signalling NaN for the double-precision
> +| floating point value `a'.
> +*----------------------------------------------------------------------------*/
> +
> +float64 float64_silence_nan(float64 a, float_status *status)
> +{
> +#ifdef NO_SIGNALING_NANS
> +    g_assert_not_reached();
> +#else
> +    if (status->snan_bit_is_one) {
> +# ifdef TARGET_HPPA
> +        a &= ~0x0008000000000000ULL;
> +        a |=  0x0004000000000000ULL;
> +        return a;
> +# else
> +        return float64_default_nan(status);
> +# endif
> +    } else {
> +        return a | LIT64(0x0008000000000000);
> +    }
> +#endif
> +}
> +
>  /*----------------------------------------------------------------------------
>  | Returns a quiet NaN if the double-precision floating point value `a' is a
>  | signaling NaN; otherwise returns `a'.
>  *----------------------------------------------------------------------------*/
>
> -float64 float64_maybe_silence_nan(float64 a_, float_status *status)
> +float64 float64_maybe_silence_nan(float64 a, float_status *status)
>  {
> -    if (float64_is_signaling_nan(a_, status)) {
> -        if (status->snan_bit_is_one) {
> -#ifdef TARGET_HPPA
> -            uint64_t a = float64_val(a_);
> -            a &= ~0x0008000000000000ULL;
> -            a |=  0x0004000000000000ULL;
> -            return make_float64(a);
> -#else
> -            return float64_default_nan(status);
> -#endif
> -        } else {
> -            uint64_t a = float64_val(a_);
> -            a |= LIT64(0x0008000000000000);
> -            return make_float64(a);
> -        }
> +    if (float64_is_signaling_nan(a, status)) {
> +        return float64_silence_nan(a, status);
>      }
> -    return a_;
> +    return a;
>  }
>
>  /*----------------------------------------------------------------------------
> @@ -897,6 +931,25 @@ int floatx80_is_signaling_nan(floatx80 a, float_status *status)
>  #endif
>  }
>
> +/*----------------------------------------------------------------------------
> +| Returns a quiet NaN from a signalling NaN for the extended double-precision
> +| floating point value `a'.
> +*----------------------------------------------------------------------------*/
> +
> +floatx80 floatx80_silence_nan(floatx80 a, float_status *status)
> +{
> +#ifdef NO_SIGNALING_NANS
> +    g_assert_not_reached();
> +#else
> +    if (status->snan_bit_is_one) {
> +        return floatx80_default_nan(status);
> +    } else {
> +        a.low |= LIT64(0xC000000000000000);
> +        return a;
> +    }
> +#endif
> +}
> +
>  /*----------------------------------------------------------------------------
>  | Returns a quiet NaN if the extended double-precision floating point value
>  | `a' is a signaling NaN; otherwise returns `a'.
> @@ -905,12 +958,7 @@ int floatx80_is_signaling_nan(floatx80 a, float_status *status)
>  floatx80 floatx80_maybe_silence_nan(floatx80 a, float_status *status)
>  {
>      if (floatx80_is_signaling_nan(a, status)) {
> -        if (status->snan_bit_is_one) {
> -            a = floatx80_default_nan(status);
> -        } else {
> -            a.low |= LIT64(0xC000000000000000);
> -            return a;
> -        }
> +        return floatx80_silence_nan(a, status);
>      }
>      return a;
>  }
> @@ -1044,6 +1092,25 @@ int float128_is_signaling_nan(float128 a, float_status *status)
>  #endif
>  }
>
> +/*----------------------------------------------------------------------------
> +| Returns a quiet NaN from a signalling NaN for the quadruple-precision
> +| floating point value `a'.
> +*----------------------------------------------------------------------------*/
> +
> +float128 float128_silence_nan(float128 a, float_status *status)
> +{
> +#ifdef NO_SIGNALING_NANS
> +    g_assert_not_reached();
> +#else
> +    if (status->snan_bit_is_one) {
> +        return float128_default_nan(status);
> +    } else {
> +        a.high |= LIT64(0x0000800000000000);
> +        return a;
> +    }
> +#endif
> +}
> +
>  /*----------------------------------------------------------------------------
>  | Returns a quiet NaN if the quadruple-precision floating point value `a' is
>  | a signaling NaN; otherwise returns `a'.
> @@ -1052,12 +1119,7 @@ int float128_is_signaling_nan(float128 a, float_status *status)
>  float128 float128_maybe_silence_nan(float128 a, float_status *status)
>  {
>      if (float128_is_signaling_nan(a, status)) {
> -        if (status->snan_bit_is_one) {
> -            a = float128_default_nan(status);
> -        } else {
> -            a.high |= LIT64(0x0000800000000000);
> -            return a;
> -        }
> +        return float128_silence_nan(a, status);
>      }
>      return a;
>  }
> diff --git a/include/fpu/softfloat.h b/include/fpu/softfloat.h
> index 01ef1c6b81..a6860e858d 100644
> --- a/include/fpu/softfloat.h
> +++ b/include/fpu/softfloat.h
> @@ -257,6 +257,7 @@ int float16_compare_quiet(float16, float16, float_status *status);
>
>  int float16_is_quiet_nan(float16, float_status *status);
>  int float16_is_signaling_nan(float16, float_status *status);
> +float16 float16_silence_nan(float16, float_status *status);
>  float16 float16_maybe_silence_nan(float16, float_status *status);
>
>  static inline int float16_is_any_nan(float16 a)
> @@ -368,6 +369,7 @@ float32 float32_minnummag(float32, float32, float_status *status);
>  float32 float32_maxnummag(float32, float32, float_status *status);
>  int float32_is_quiet_nan(float32, float_status *status);
>  int float32_is_signaling_nan(float32, float_status *status);
> +float32 float32_silence_nan(float32, float_status *status);
>  float32 float32_maybe_silence_nan(float32, float_status *status);
>  float32 float32_scalbn(float32, int, float_status *status);
>
> @@ -497,6 +499,7 @@ float64 float64_minnummag(float64, float64, float_status *status);
>  float64 float64_maxnummag(float64, float64, float_status *status);
>  int float64_is_quiet_nan(float64 a, float_status *status);
>  int float64_is_signaling_nan(float64, float_status *status);
> +float64 float64_silence_nan(float64, float_status *status);
>  float64 float64_maybe_silence_nan(float64, float_status *status);
>  float64 float64_scalbn(float64, int, float_status *status);
>
> @@ -600,6 +603,7 @@ int floatx80_compare(floatx80, floatx80, float_status *status);
>  int floatx80_compare_quiet(floatx80, floatx80, float_status *status);
>  int floatx80_is_quiet_nan(floatx80, float_status *status);
>  int floatx80_is_signaling_nan(floatx80, float_status *status);
> +floatx80 floatx80_silence_nan(floatx80, float_status *status);
>  floatx80 floatx80_maybe_silence_nan(floatx80, float_status *status);
>  floatx80 floatx80_scalbn(floatx80, int, float_status *status);
>
> @@ -811,6 +815,7 @@ int float128_compare(float128, float128, float_status *status);
>  int float128_compare_quiet(float128, float128, float_status *status);
>  int float128_is_quiet_nan(float128, float_status *status);
>  int float128_is_signaling_nan(float128, float_status *status);
> +float128 float128_silence_nan(float128, float_status *status);
>  float128 float128_maybe_silence_nan(float128, float_status *status);
>  float128 float128_scalbn(float128, int, float_status *status);


--
Alex Bennée

^ permalink raw reply	[flat|nested] 29+ messages in thread

* Re: [Qemu-devel] [PATCH 03/19] fpu/softfloat: Move softfloat-specialize.h below FloatParts definition
  2018-05-11  0:43 ` [Qemu-devel] [PATCH 03/19] fpu/softfloat: Move softfloat-specialize.h below FloatParts definition Richard Henderson
@ 2018-05-11  7:48   ` Alex Bennée
  0 siblings, 0 replies; 29+ messages in thread
From: Alex Bennée @ 2018-05-11  7:48 UTC (permalink / raw)
  To: Richard Henderson; +Cc: qemu-devel, peter.maydell


Richard Henderson <richard.henderson@linaro.org> writes:

> We want to be able to specialize on the canonical representation.
>
> Signed-off-by: Richard Henderson <richard.henderson@linaro.org>

Reviewed-by: Alex Bennée <alex.bennee@linaro.org>

> ---
>  fpu/softfloat.c | 20 ++++++++++----------
>  1 file changed, 10 insertions(+), 10 deletions(-)
>
> diff --git a/fpu/softfloat.c b/fpu/softfloat.c
> index e7c8213a5e..5e4982b035 100644
> --- a/fpu/softfloat.c
> +++ b/fpu/softfloat.c
> @@ -95,16 +95,6 @@ this code that are retained.
>  *----------------------------------------------------------------------------*/
>  #include "fpu/softfloat-macros.h"
>
> -/*----------------------------------------------------------------------------
> -| Functions and definitions to determine:  (1) whether tininess for underflow
> -| is detected before or after rounding by default, (2) what (if anything)
> -| happens when exceptions are raised, (3) how signaling NaNs are distinguished
> -| from quiet NaNs, (4) the default generated quiet NaNs, and (5) how NaNs
> -| are propagated from function inputs to output.  These details are target-
> -| specific.
> -*----------------------------------------------------------------------------*/
> -#include "softfloat-specialize.h"
> -
>  /*----------------------------------------------------------------------------
>  | Returns the fraction bits of the half-precision floating-point value `a'.
>  *----------------------------------------------------------------------------*/
> @@ -241,6 +231,16 @@ typedef struct {
>      bool arm_althp;
>  } FloatFmt;
>
> +/*----------------------------------------------------------------------------
> +| Functions and definitions to determine:  (1) whether tininess for underflow
> +| is detected before or after rounding by default, (2) what (if anything)
> +| happens when exceptions are raised, (3) how signaling NaNs are distinguished
> +| from quiet NaNs, (4) the default generated quiet NaNs, and (5) how NaNs
> +| are propagated from function inputs to output.  These details are target-
> +| specific.
> +*----------------------------------------------------------------------------*/
> +#include "softfloat-specialize.h"
> +
>  /* Expand fields based on the size of exponent and fraction */
>  #define FLOAT_PARAMS(E, F)                                           \
>      .exp_size       = E,                                             \


--
Alex Bennée

^ permalink raw reply	[flat|nested] 29+ messages in thread

* Re: [Qemu-devel] [PATCH 11/19] target/m68k: Use floatX_silence_nan when we have already checked for SNaN
  2018-05-11  0:43 ` [Qemu-devel] [PATCH 11/19] target/m68k: Use floatX_silence_nan when we have already checked for SNaN Richard Henderson
@ 2018-05-11 10:11   ` Laurent Vivier
  0 siblings, 0 replies; 29+ messages in thread
From: Laurent Vivier @ 2018-05-11 10:11 UTC (permalink / raw)
  To: Richard Henderson, qemu-devel; +Cc: peter.maydell, alex.bennee

Le 11/05/2018 à 02:43, Richard Henderson a écrit :
> Cc: Laurent Vivier <laurent@vivier.eu>
> Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
> ---
>  target/m68k/softfloat.c | 3 ++-
>  1 file changed, 2 insertions(+), 1 deletion(-)

Reviewed-by: Laurent Vivier <laurent@vivier.eu>

^ permalink raw reply	[flat|nested] 29+ messages in thread

* Re: [Qemu-devel] [PATCH 02/19] fpu/softfloat: Split floatXX_silence_nan from floatXX_maybe_silence_nan
  2018-05-11  7:47   ` Alex Bennée
@ 2018-05-11 15:06     ` Alex Bennée
  2018-05-11 15:16       ` Richard Henderson
  0 siblings, 1 reply; 29+ messages in thread
From: Alex Bennée @ 2018-05-11 15:06 UTC (permalink / raw)
  To: Richard Henderson; +Cc: qemu-devel, peter.maydell


Alex Bennée <alex.bennee@linaro.org> writes:

> Richard Henderson <richard.henderson@linaro.org> writes:
>
>> The new function assumes that the input is an SNaN and
>> does not double-check.
>>
>> Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
>
> Reviewed-by: Alex Bennée <alex.bennee@linaro.org>

but...but...
>> -float16 float16_maybe_silence_nan(float16 a_, float_status *status)
>> +
>> +float16 float16_maybe_silence_nan(float16 a, float_status *status)
>>  {
>> -    if (float16_is_signaling_nan(a_, status)) {
>> -        if (status->snan_bit_is_one) {
>> -            return float16_default_nan(status);
>> -        } else {
>> -            uint16_t a = float16_val(a_);
>> -            a |= (1 << 9);
>> -            return make_float16(a);
>> -        }
>> +    if (float16_is_signaling_nan(a, status)) {
>> +        float16_silence_nan(a, status);

You need a return here.
>>
>> -float32 float32_maybe_silence_nan(float32 a_, float_status *status)
>> +float32 float32_maybe_silence_nan(float32 a, float_status *status)
>>  {
>> -    if (float32_is_signaling_nan(a_, status)) {
>> -        if (status->snan_bit_is_one) {
>> -#ifdef TARGET_HPPA
>> -            uint32_t a = float32_val(a_);
>> -            a &= ~0x00400000;
>> -            a |=  0x00200000;
>> -            return make_float32(a);
>> -#else
>> -            return float32_default_nan(status);
>> -#endif
>> -        } else {
>> -            uint32_t a = float32_val(a_);
>> -            a |= (1 << 22);
>> -            return make_float32(a);
>> -        }
>> +    if (float32_is_signaling_nan(a, status)) {
>> +        float32_silence_nan(a, status);

And here.

Amazing what tests pass with those in, but RISU picked them up.

--
Alex Bennée

^ permalink raw reply	[flat|nested] 29+ messages in thread

* Re: [Qemu-devel] [PATCH 02/19] fpu/softfloat: Split floatXX_silence_nan from floatXX_maybe_silence_nan
  2018-05-11 15:06     ` Alex Bennée
@ 2018-05-11 15:16       ` Richard Henderson
  0 siblings, 0 replies; 29+ messages in thread
From: Richard Henderson @ 2018-05-11 15:16 UTC (permalink / raw)
  To: Alex Bennée; +Cc: qemu-devel, peter.maydell

On 05/11/2018 08:06 AM, Alex Bennée wrote:
> but...but...
>>> -float16 float16_maybe_silence_nan(float16 a_, float_status *status)
>>> +
>>> +float16 float16_maybe_silence_nan(float16 a, float_status *status)
>>>  {
>>> +    if (float16_is_signaling_nan(a, status)) {
>>> +        float16_silence_nan(a, status);
> 
> You need a return here.

Oops.

> Amazing what tests pass with those in, but RISU picked them up.

Heh.  In my case I hadn't bothered testing until further down the patch set
when these functions have been removed.


r~

^ permalink raw reply	[flat|nested] 29+ messages in thread

* Re: [Qemu-devel] [PATCH 04/19] fpu/softfloat: Canonicalize NaN fraction
  2018-05-11  0:43 ` [Qemu-devel] [PATCH 04/19] fpu/softfloat: Canonicalize NaN fraction Richard Henderson
@ 2018-05-11 16:26   ` Alex Bennée
  2018-05-11 16:46     ` Richard Henderson
  0 siblings, 1 reply; 29+ messages in thread
From: Alex Bennée @ 2018-05-11 16:26 UTC (permalink / raw)
  To: Richard Henderson; +Cc: qemu-devel, peter.maydell


Richard Henderson <richard.henderson@linaro.org> writes:

> Shift the NaN fraction to a canonical position, much like we do
> for the fraction of normal numbers.  Immediately, this simplifies
> the float-to-float conversion.  Later, this will facilitate
> manipulation of NaNs within the shared code paths.
>
> Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
> ---
>  fpu/softfloat.c | 13 ++++++-------
>  1 file changed, 6 insertions(+), 7 deletions(-)
>
> diff --git a/fpu/softfloat.c b/fpu/softfloat.c
> index 5e4982b035..df377b6314 100644
> --- a/fpu/softfloat.c
> +++ b/fpu/softfloat.c
> @@ -329,10 +329,11 @@ static FloatParts canonicalize(FloatParts part, const FloatFmt *parm,
>          if (part.frac == 0) {
>              part.cls = float_class_inf;
>          } else {
> +            part.frac <<= parm->frac_shift;
>  #ifdef NO_SIGNALING_NANS
>              part.cls = float_class_qnan;
>  #else
> -            int64_t msb = part.frac << (parm->frac_shift + 2);
> +            int64_t msb = part.frac << 2;
>              if ((msb < 0) == status->snan_bit_is_one) {
>                  part.cls = float_class_snan;
>              } else {
> @@ -498,6 +499,7 @@ static FloatParts round_canonical(FloatParts p, float_status *s,
>      case float_class_qnan:
>      case float_class_snan:
>          exp = exp_max;
> +        frac >>= parm->frac_shift;

Unfortunately we now miss this step when we handle:

    case float_class_msnan:
        return float64_maybe_silence_nan(float64_pack_raw(p), s);

This seems to fix that:

recanonicalise frac before packing and sending

1 file changed, 3 insertions(+)
fpu/softfloat.c | 3 +++

modified   fpu/softfloat.c
@@ -532,6 +532,7 @@ static float16 float16a_round_pack_canonical(const FloatFmt *params,
     case float_class_dnan:
         return float16_default_nan(s);
     case float_class_msnan:
+        p.frac >>= params->frac_shift;
         return float16_maybe_silence_nan(float16_pack_raw(p), s);
     default:
         p = round_canonical(p, s, params);
@@ -555,6 +556,7 @@ static float32 float32_round_pack_canonical(FloatParts p, float_status *s)
     case float_class_dnan:
         return float32_default_nan(s);
     case float_class_msnan:
+        p.frac >>= float32_params.frac_shift;
         return float32_maybe_silence_nan(float32_pack_raw(p), s);
     default:
         p = round_canonical(p, s, &float32_params);
@@ -573,6 +575,7 @@ static float64 float64_round_pack_canonical(FloatParts p, float_status *s)
     case float_class_dnan:
         return float64_default_nan(s);
     case float_class_msnan:
+        p.frac >>= float64_params.frac_shift;
         return float64_maybe_silence_nan(float64_pack_raw(p), s);
     default:
         p = round_canonical(p, s, &float64_params);

--
Alex Bennée

^ permalink raw reply	[flat|nested] 29+ messages in thread

* Re: [Qemu-devel] [PATCH 04/19] fpu/softfloat: Canonicalize NaN fraction
  2018-05-11 16:26   ` Alex Bennée
@ 2018-05-11 16:46     ` Richard Henderson
  0 siblings, 0 replies; 29+ messages in thread
From: Richard Henderson @ 2018-05-11 16:46 UTC (permalink / raw)
  To: Alex Bennée; +Cc: qemu-devel, peter.maydell

On 05/11/2018 09:26 AM, Alex Bennée wrote:
> 
> Richard Henderson <richard.henderson@linaro.org> writes:
> 
>> Shift the NaN fraction to a canonical position, much like we do
>> for the fraction of normal numbers.  Immediately, this simplifies
>> the float-to-float conversion.  Later, this will facilitate
>> manipulation of NaNs within the shared code paths.
>>
>> Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
>> ---
>>  fpu/softfloat.c | 13 ++++++-------
>>  1 file changed, 6 insertions(+), 7 deletions(-)
>>
>> diff --git a/fpu/softfloat.c b/fpu/softfloat.c
>> index 5e4982b035..df377b6314 100644
>> --- a/fpu/softfloat.c
>> +++ b/fpu/softfloat.c
>> @@ -329,10 +329,11 @@ static FloatParts canonicalize(FloatParts part, const FloatFmt *parm,
>>          if (part.frac == 0) {
>>              part.cls = float_class_inf;
>>          } else {
>> +            part.frac <<= parm->frac_shift;
>>  #ifdef NO_SIGNALING_NANS
>>              part.cls = float_class_qnan;
>>  #else
>> -            int64_t msb = part.frac << (parm->frac_shift + 2);
>> +            int64_t msb = part.frac << 2;
>>              if ((msb < 0) == status->snan_bit_is_one) {
>>                  part.cls = float_class_snan;
>>              } else {
>> @@ -498,6 +499,7 @@ static FloatParts round_canonical(FloatParts p, float_status *s,
>>      case float_class_qnan:
>>      case float_class_snan:
>>          exp = exp_max;
>> +        frac >>= parm->frac_shift;
> 
> Unfortunately we now miss this step when we handle:
> 
>     case float_class_msnan:
>         return float64_maybe_silence_nan(float64_pack_raw(p), s);
> 
> This seems to fix that:
> 
> recanonicalise frac before packing and sending

Good catch.  Merged for bisection.


r~

^ permalink raw reply	[flat|nested] 29+ messages in thread

end of thread, other threads:[~2018-05-11 16:47 UTC | newest]

Thread overview: 29+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2018-05-11  0:43 [Qemu-devel] [PATCH 00/19] softfloat: Clean up NaN handling Richard Henderson
2018-05-11  0:43 ` [Qemu-devel] [PATCH 01/19] fpu/softfloat: Merge NO_SIGNALING_NANS definitions Richard Henderson
2018-05-11  6:44   ` Alex Bennée
2018-05-11  0:43 ` [Qemu-devel] [PATCH 02/19] fpu/softfloat: Split floatXX_silence_nan from floatXX_maybe_silence_nan Richard Henderson
2018-05-11  7:47   ` Alex Bennée
2018-05-11 15:06     ` Alex Bennée
2018-05-11 15:16       ` Richard Henderson
2018-05-11  0:43 ` [Qemu-devel] [PATCH 03/19] fpu/softfloat: Move softfloat-specialize.h below FloatParts definition Richard Henderson
2018-05-11  7:48   ` Alex Bennée
2018-05-11  0:43 ` [Qemu-devel] [PATCH 04/19] fpu/softfloat: Canonicalize NaN fraction Richard Henderson
2018-05-11 16:26   ` Alex Bennée
2018-05-11 16:46     ` Richard Henderson
2018-05-11  0:43 ` [Qemu-devel] [PATCH 05/19] fpu/softfloat: Introduce parts_is_snan_frac Richard Henderson
2018-05-11  0:43 ` [Qemu-devel] [PATCH 06/19] fpu/softfloat: Replace float_class_dnan with parts_default_nan Richard Henderson
2018-05-11  0:43 ` [Qemu-devel] [PATCH 07/19] fpu/softfloat: Replace float_class_msnan with parts_silence_nan Richard Henderson
2018-05-11  0:43 ` [Qemu-devel] [PATCH 08/19] target/arm: Use floatX_silence_nan when we have already checked for SNaN Richard Henderson
2018-05-11  0:43 ` [Qemu-devel] [PATCH 09/19] target/arm: Remove floatX_maybe_silence_nan from conversions Richard Henderson
2018-05-11  0:43 ` [Qemu-devel] [PATCH 10/19] target/hppa: " Richard Henderson
2018-05-11  0:43 ` [Qemu-devel] [PATCH 11/19] target/m68k: Use floatX_silence_nan when we have already checked for SNaN Richard Henderson
2018-05-11 10:11   ` Laurent Vivier
2018-05-11  0:43 ` [Qemu-devel] [PATCH 12/19] target/mips: Remove floatX_maybe_silence_nan from conversions Richard Henderson
2018-05-11  0:43 ` [Qemu-devel] [PATCH 13/19] target/riscv: " Richard Henderson
2018-05-11  0:43 ` [Qemu-devel] [PATCH 14/19] target/s390x: " Richard Henderson
2018-05-11  6:47   ` David Hildenbrand
2018-05-11  0:43 ` [Qemu-devel] [PATCH 15/19] fpu/softfloat: Use float*_silence_nan in propagateFloat*NaN Richard Henderson
2018-05-11  0:43 ` [Qemu-devel] [PATCH 16/19] fpu/softfloat: Remove floatX_maybe_silence_nan Richard Henderson
2018-05-11  0:43 ` [Qemu-devel] [PATCH 17/19] fpu/softfloat: Introduce SNAN_BIT_IS_ONE Richard Henderson
2018-05-11  0:43 ` [Qemu-devel] [PATCH 18/19] fpu/softfloat: Pass FloatClass to pickNaN Richard Henderson
2018-05-11  0:43 ` [Qemu-devel] [PATCH 19/19] fpu/softfloat: Pass FloatClass to pickNaNMulAdd Richard Henderson

This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.