* [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 a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).