diff mbox series

[v2,for-10.0,28/54] softfloat: Create floatx80 default NaN from parts64_default_nan

Message ID 20241202131347.498124-29-peter.maydell@linaro.org
State Superseded
Headers show
Series fpu: Remove pickNaNMulAdd, default-NaN ifdefs | expand

Commit Message

Peter Maydell Dec. 2, 2024, 1:13 p.m. UTC
We create our 128-bit default NaN by calling parts64_default_nan()
and then adjusting the result.  We can do the same trick for creating
the floatx80 default NaN, which lets us drop a target ifdef.

floatx80 is used only by:
 i386
 m68k
 arm nwfpe old floating-point emulation emulation support
    (which is essentially dead, especially the parts involving floatx80)
 PPC (only in the xsrqpxp instruction, which just rounds an input
    value by converting to floatx80 and back, so will never generate
    the default NaN)

The floatx80 default NaN as currently implemented is:
 m68k: sign = 0, exp = 1...1, int = 1, frac = 1....1
 i386: sign = 1, exp = 1...1, int = 1, frac = 10...0

These are the same as the parts64_default_nan for these architectures.

This is technically a possible behaviour change for arm linux-user
nwfpe emulation emulation, because the default NaN will now have the
sign bit clear.  But we were already generating a different floatx80
default NaN from the real kernel emulation we are supposedly
following, which appears to use an all-bits-1 value:
 https://elixir.bootlin.com/linux/v6.12/source/arch/arm/nwfpe/softfloat-specialize#L267

This won't affect the only "real" use of the nwfpe emulation, which
is ancient binaries that used it as part of the old floating point
calling convention; that only uses loads and stores of 32 and 64 bit
floats, not any of the floatx80 behaviour the original hardware had.
We also get the nwfpe float64 default NaN value wrong:
 https://elixir.bootlin.com/linux/v6.12/source/arch/arm/nwfpe/softfloat-specialize#L166
so if we ever cared about this obscure corner the right fix would be
to correct that so nwfpe used its own default-NaN setting rather
than the Arm VFP one.

Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
---
 fpu/softfloat-specialize.c.inc | 20 ++++++++++----------
 1 file changed, 10 insertions(+), 10 deletions(-)

Comments

Richard Henderson Dec. 2, 2024, 5:19 p.m. UTC | #1
On 12/2/24 07:13, Peter Maydell wrote:
> We create our 128-bit default NaN by calling parts64_default_nan()
> and then adjusting the result.  We can do the same trick for creating
> the floatx80 default NaN, which lets us drop a target ifdef.
> 
> floatx80 is used only by:
>   i386
>   m68k
>   arm nwfpe old floating-point emulation emulation support
>      (which is essentially dead, especially the parts involving floatx80)
>   PPC (only in the xsrqpxp instruction, which just rounds an input
>      value by converting to floatx80 and back, so will never generate
>      the default NaN)
> 
> The floatx80 default NaN as currently implemented is:
>   m68k: sign = 0, exp = 1...1, int = 1, frac = 1....1
>   i386: sign = 1, exp = 1...1, int = 1, frac = 10...0
> 
> These are the same as the parts64_default_nan for these architectures.
> 
> This is technically a possible behaviour change for arm linux-user
> nwfpe emulation emulation, because the default NaN will now have the
> sign bit clear.  But we were already generating a different floatx80
> default NaN from the real kernel emulation we are supposedly
> following, which appears to use an all-bits-1 value:
>   https://elixir.bootlin.com/linux/v6.12/source/arch/arm/nwfpe/softfloat-specialize#L267
> 
> This won't affect the only "real" use of the nwfpe emulation, which
> is ancient binaries that used it as part of the old floating point
> calling convention; that only uses loads and stores of 32 and 64 bit
> floats, not any of the floatx80 behaviour the original hardware had.
> We also get the nwfpe float64 default NaN value wrong:
>   https://elixir.bootlin.com/linux/v6.12/source/arch/arm/nwfpe/softfloat-specialize#L166
> so if we ever cared about this obscure corner the right fix would be
> to correct that so nwfpe used its own default-NaN setting rather
> than the Arm VFP one.
> 
> Signed-off-by: Peter Maydell<peter.maydell@linaro.org>
> ---
>   fpu/softfloat-specialize.c.inc | 20 ++++++++++----------
>   1 file changed, 10 insertions(+), 10 deletions(-)

Reviewed-by: Richard Henderson <richard.henderson@linaro.org>

r~
diff mbox series

Patch

diff --git a/fpu/softfloat-specialize.c.inc b/fpu/softfloat-specialize.c.inc
index 5fbc953e71e..9f913ce20ab 100644
--- a/fpu/softfloat-specialize.c.inc
+++ b/fpu/softfloat-specialize.c.inc
@@ -227,17 +227,17 @@  static void parts128_silence_nan(FloatParts128 *p, float_status *status)
 floatx80 floatx80_default_nan(float_status *status)
 {
     floatx80 r;
+    /*
+     * Extrapolate from the choices made by parts64_default_nan to fill
+     * in the floatx80 format. We assume that floatx80's explicit
+     * integer bit is always set (this is true for i386 and m68k,
+     * which are the only real users of this format).
+     */
+    FloatParts64 p64;
+    parts64_default_nan(&p64, status);
 
-    /* None of the targets that have snan_bit_is_one use floatx80.  */
-    assert(!snan_bit_is_one(status));
-#if defined(TARGET_M68K)
-    r.low = UINT64_C(0xFFFFFFFFFFFFFFFF);
-    r.high = 0x7FFF;
-#else
-    /* X86 */
-    r.low = UINT64_C(0xC000000000000000);
-    r.high = 0xFFFF;
-#endif
+    r.high = 0x7FFF | (p64.sign << 15);
+    r.low = (1ULL << DECOMPOSED_BINARY_POINT) | p64.frac;
     return r;
 }