The MC68881 say about infinities (3.2.4):

"*For the extended precision format, the most significant bit of the
mantissa (the integer bit) is a don't care."

https://www.nxp.com/docs/en/reference-manual/MC68881UM.pdf

The m68k extended format is implemented with the floatx80 and
floatx80_invalid_encoding currently treats 0x7fff00000000000000000000 as
an invalid encoding.  This patch fixes floatx80_invalid_encoding so it
accepts that the most significant bit of the mantissa can be 0.

This bug can be revealed with the following code which pushes extended
infinity on the stack as a double and then reloads it as a double.  It
should normally be converted and read back as infinity and is currently
read back as nan:

        .global _start
        .text
_start:
        lea val, %a0
        lea fp, %fp
        fmovex (%a0), %fp0
        fmoved %fp0, %fp@(-8)
        fmoved %fp@(-8), %fp0
end:
        bra end

.align 0x4
val:
        .fill 1, 4, 0x7fff0000
        .fill 1, 4, 0x00000000
        .fill 1, 4, 0x00000000
.align 0x4
        .fill 0x100, 1, 0
fp:

-------------

(gdb) tar rem :1234
Remote debugging using :1234
_start () at main.S:5
5              lea val, %a0
(gdb) display $fp0
1: $fp0 = nan(0xffffffffffffffff)
(gdb) si
6             lea fp, %fp
1: $fp0 = nan(0xffffffffffffffff)
(gdb) si
_start () at main.S:7
7              fmovex (%a0), %fp0
1: $fp0 = nan(0xffffffffffffffff)
(gdb) si
8             fmoved %fp0, %fp@(-8)
1: $fp0 = inf
(gdb) si
9             fmoved %fp@(-8), %fp0
1: $fp0 = inf
(gdb) si
end () at main.S:12
12          bra end
1: $fp0 = nan(0xfffffffffffff800)
(gdb) x/1xg $fp-8
0x40000120 <val+260>:   0x7fffffffffffffff

Signed-off-by: KONRAD Frederic <frederic.kon...@adacore.com>
---
 include/fpu/softfloat.h | 5 +++++
 1 file changed, 5 insertions(+)

diff --git a/include/fpu/softfloat.h b/include/fpu/softfloat.h
index ecb8ba0..dc80298 100644
--- a/include/fpu/softfloat.h
+++ b/include/fpu/softfloat.h
@@ -688,7 +688,12 @@ static inline int floatx80_is_any_nan(floatx80 a)
 *----------------------------------------------------------------------------*/
 static inline bool floatx80_invalid_encoding(floatx80 a)
 {
+#if defined(TARGET_M68K)
+    return (a.low & (1ULL << 63)) == 0 && (((a.high & 0x7FFF) != 0)
+                                           && (a.high != 0x7FFF));
+#else
     return (a.low & (1ULL << 63)) == 0 && (a.high & 0x7FFF) != 0;
+#endif
 }
 
 #define floatx80_zero make_floatx80(0x0000, 0x0000000000000000LL)
-- 
1.8.3.1


Reply via email to