Message ID | 1588094279-17913-2-git-send-email-frederic.konrad@adacore.com |
---|---|
State | New |
Headers | show |
Series | m68k fpu fixes | expand |
KONRAD Frederic <frederic.konrad@adacore.com> writes: > 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: Do you have any real HW on which you could record some .ref files for the various multiarch float tests we have (float_convs/float_madds)? Does this different of invalid encoding show up when you add them? > > .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.konrad@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)
Le 28/04/2020 à 19:17, KONRAD Frederic a écrit : > 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 As we use 68040 I refer to: https://www.nxp.com/files-static/archives/doc/ref_manual/M68000PRM.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.konrad@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) > This is denormalized numbers and should generate an exception. I tried something like that in the past: https://patchew.org/QEMU/20170207005930.28327-1-laurent@vivier.eu/20170207005930.28327-3-laurent@vivier.eu/ Pierre tried recently: https://patchew.org/QEMU/1615bbe5-3033-3b76-5cfb-52e343dc4d67@freepascal.org/ See "1.6.2 Denormalized Numbers" in M68000 FAMILY PROGRAMMER’S REFERENCE MANUAL. "Since the extended-precision data format has an explicit integer bit, a number can be formatted with a nonzero exponent, less than the maximum value, and a zero integer bit. The IEEE 754 standard does not define a zero integer bit. Such a number is an unnormalized number. Hardware does not directly support denormalized and unnormalized numbers, but implicitly supports them by trapping them as unimplemented data types, allowing efficient conversion in software." But m68k FPU exceptions are not currently implemented in QEMU. Thanks, Laurent
Le 28/04/2020 à 20:43, Alex Bennée a écrit : > > KONRAD Frederic <frederic.konrad@adacore.com> writes: > >> 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: > > Do you have any real HW on which you could record some .ref files for > the various multiarch float tests we have (float_convs/float_madds)? > Does this different of invalid encoding show up when you add them? On my side, in the past when I started to implement m68k FPU, I used TestFloat and SoftFloat I have ported to m68k and I compare the result in QEMU and in a Quadra 800. https://github.com/vivier/m68k-testfloat https://github.com/vivier/m68k-softfloat I also used the gcc and libc testsuite to detect problems but this was a very slow process... I have also ported RISU to m68k, but I didn't add FPU test in it (does it support FPU test?). Thanks, Laurent
Laurent Vivier <laurent@vivier.eu> writes: > Le 28/04/2020 à 20:43, Alex Bennée a écrit : >> >> KONRAD Frederic <frederic.konrad@adacore.com> writes: >> >>> 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: >> >> Do you have any real HW on which you could record some .ref files for >> the various multiarch float tests we have (float_convs/float_madds)? >> Does this different of invalid encoding show up when you add them? > > On my side, in the past when I started to implement m68k FPU, I used > TestFloat and SoftFloat I have ported to m68k and I compare the result > in QEMU and in a Quadra 800. Surely TestFloat and SoftFloat is all emulation though? Anyway if you have a Quadra 800 running Linux could you generate some .ref files for the float_convs and float_madds test cases. The binaries are static so you should just be able to copy them and run. > https://github.com/vivier/m68k-testfloat > https://github.com/vivier/m68k-softfloat Ahh I see you have sys_float functions to compare to TestFloat. > I also used the gcc and libc testsuite to detect problems but this was a > very slow process... > > I have also ported RISU to m68k, but I didn't add FPU test in it (does > it support FPU test?). There is no reason why it couldn't. The FPU support would basically be ensuring the appropriate registers are saved out of the context. I did similar when we expanded the aarch64 RISU to support SVE. In fact looking at the code: for (i = 0; i < 8; i++) { if (m->fpregs.f_fpregs[i][0] != a->fpregs.f_fpregs[i][0] || m->fpregs.f_fpregs[i][1] != a->fpregs.f_fpregs[i][1] || m->fpregs.f_fpregs[i][2] != a->fpregs.f_fpregs[i][2]) { return 0; } } it seems the fpregs are included and tested so it should be good. That said RISU's random instruction approach means most floating point numbers very quickly become tend to NaNs which is part of the reason I wrote the float_convs/float_madds tests which try to be more systematic in exercising the range of float types (normals, denormals, min and max etc). Maybe we could improve risugen's seeding of floating point values to better exercise FP ops rather than just dumping random stuff there. > > Thanks, > Laurent
Le 29/04/2020 à 11:26, Alex Bennée a écrit : > > Laurent Vivier <laurent@vivier.eu> writes: > >> Le 28/04/2020 à 20:43, Alex Bennée a écrit : >>> >>> KONRAD Frederic <frederic.konrad@adacore.com> writes: >>> >>>> 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: >>> >>> Do you have any real HW on which you could record some .ref files for >>> the various multiarch float tests we have (float_convs/float_madds)? >>> Does this different of invalid encoding show up when you add them? >> >> On my side, in the past when I started to implement m68k FPU, I used >> TestFloat and SoftFloat I have ported to m68k and I compare the result >> in QEMU and in a Quadra 800. > > Surely TestFloat and SoftFloat is all emulation though? > > Anyway if you have a Quadra 800 running Linux could you generate some > .ref files for the float_convs and float_madds test cases. The binaries > are static so you should just be able to copy them and run. > Is there any HOWTO somewhere? Or should I dig into the code as usual? Thanks, Laurent
Laurent Vivier <laurent@vivier.eu> writes: > Le 29/04/2020 à 11:26, Alex Bennée a écrit : >> >> Laurent Vivier <laurent@vivier.eu> writes: >> >>> Le 28/04/2020 à 20:43, Alex Bennée a écrit : >>>> >>>> KONRAD Frederic <frederic.konrad@adacore.com> writes: >>>> >>>>> 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: >>>> >>>> Do you have any real HW on which you could record some .ref files for >>>> the various multiarch float tests we have (float_convs/float_madds)? >>>> Does this different of invalid encoding show up when you add them? >>> >>> On my side, in the past when I started to implement m68k FPU, I used >>> TestFloat and SoftFloat I have ported to m68k and I compare the result >>> in QEMU and in a Quadra 800. >> >> Surely TestFloat and SoftFloat is all emulation though? >> >> Anyway if you have a Quadra 800 running Linux could you generate some >> .ref files for the float_convs and float_madds test cases. The binaries >> are static so you should just be able to copy them and run. >> > Is there any HOWTO somewhere? Or should I dig into the code as usual? On your known good HW: ./float_convs > float_convs.ref and copy the file into tests/tcg/m68k and the: run-float_%: float_% $(call run-test,$<, $(QEMU) $(QEMU_OPTS) $<,"$< on $(TARGET_NAME)") $(call conditional-diff-out,$<,$(SRC_PATH)/tests/tcg/$(TARGET_NAME)/$<.ref) should automatically include the diff on the next run. > > Thanks, > Laurent
Le 4/29/20 à 10:42 AM, Laurent Vivier a écrit : > Le 28/04/2020 à 19:17, KONRAD Frederic a écrit : >> 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 > > As we use 68040 I refer to: > > https://www.nxp.com/files-static/archives/doc/ref_manual/M68000PRM.pdf > [...] > > This is denormalized numbers and should generate an exception. > > I tried something like that in the past: > > https://patchew.org/QEMU/20170207005930.28327-1-laurent@vivier.eu/20170207005930.28327-3-laurent@vivier.eu/ > > Pierre tried recently: > https://patchew.org/QEMU/1615bbe5-3033-3b76-5cfb-52e343dc4d67@freepascal.org/ Arg, yes that's almost the same! Sorry Pierre I missed this one :(. > > See "1.6.2 Denormalized Numbers" in M68000 FAMILY PROGRAMMER’S REFERENCE > MANUAL. > > "Since the extended-precision data format has an explicit integer bit, a > number can be formatted with a nonzero exponent, less than the maximum > value, and a zero integer bit. The IEEE 754 standard does not define a > zero integer bit. Such a number is an unnormalized number. Hardware does > not directly support denormalized and unnormalized numbers, but > implicitly supports them by trapping them as unimplemented data types, > allowing efficient conversion in software." > > But m68k FPU exceptions are not currently implemented in QEMU. Hmm ok, I don't have any m68k with an FPU at hand for testing. I just tested with an other simulator and it seems to trap when I load the value in the register. So I'm probably chasing the wrong bug here. Thanks for the tips Laurent! Fred > > Thanks, > Laurent >
Le 29/04/2020 à 11:26, Alex Bennée a écrit : > > Laurent Vivier <laurent@vivier.eu> writes: > >> Le 28/04/2020 à 20:43, Alex Bennée a écrit : >>> >>> KONRAD Frederic <frederic.konrad@adacore.com> writes: >>> >>>> 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: >>> >>> Do you have any real HW on which you could record some .ref files for >>> the various multiarch float tests we have (float_convs/float_madds)? >>> Does this different of invalid encoding show up when you add them? >> >> On my side, in the past when I started to implement m68k FPU, I used >> TestFloat and SoftFloat I have ported to m68k and I compare the result >> in QEMU and in a Quadra 800. > > Surely TestFloat and SoftFloat is all emulation though? > > Anyway if you have a Quadra 800 running Linux could you generate some > .ref files for the float_convs and float_madds test cases. The binaries > are static so you should just be able to copy them and run. > > Here are the files I have generated on Q800. Thanks, Laurent
Laurent Vivier <laurent@vivier.eu> writes: > Le 29/04/2020 à 11:26, Alex Bennée a écrit : >> >> Laurent Vivier <laurent@vivier.eu> writes: >> >>> Le 28/04/2020 à 20:43, Alex Bennée a écrit : >>>> >>>> KONRAD Frederic <frederic.konrad@adacore.com> writes: >>>> >>>>> 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: >>>> >>>> Do you have any real HW on which you could record some .ref files for >>>> the various multiarch float tests we have (float_convs/float_madds)? >>>> Does this different of invalid encoding show up when you add them? >>> >>> On my side, in the past when I started to implement m68k FPU, I used >>> TestFloat and SoftFloat I have ported to m68k and I compare the result >>> in QEMU and in a Quadra 800. >> >> Surely TestFloat and SoftFloat is all emulation though? >> >> Anyway if you have a Quadra 800 running Linux could you generate some >> .ref files for the float_convs and float_madds test cases. The binaries >> are static so you should just be able to copy them and run. >> >> > > Here are the files I have generated on Q800. So running those with: run-float_convs: QEMU_OPTS += -cpu m68040 run-float_madds: QEMU_OPTS += -cpu m68040 We see the m68k float needs a fair bit of work from the get go: Reference qemu-m68k -cou m68040 ### Rounding to nearest ### Rounding to nearest > from single: f32(-nan:0xffbfffff) > to double: f64(-nan:0x00fff7ffffe0000000) (OK) > to int32: 2147483647 (OK) > to int64: 9223372034707292159 (OK) > to uint32: 2147483647 (OK) > to uint64: 9223372034707292159 (OK) from single: f32(-nan:0xffffffff) from single: f32(-nan:0xffffffff) to double: f64(-nan:0x00ffffffffe0000000) (OK) to double: f64(-nan:0x00ffffffffe0000000) (OK) to int32: 2147483392 (INVALID) | to int32: 2147483647 (OK) to int64: 9223370939490631424 (INVALID) | to int64: 9223372034707292159 (OK) to uint32: 2147483392 (INVALID) | to uint32: 2147483647 (OK) to uint64: 9223370939490631424 (INVALID) | to uint64: 9223372034707292159 (OK) from single: f32(-nan:0xffffffff) | from single: f32(nan:0x7fffffff) to double: f64(-nan:0x00ffffffffe0000000) (OK) | to double: f64(nan:0x007fffffffe0000000) (OK) to int32: 2147483392 (INVALID) | to int32: 2147483647 (OK) to int64: 9223370939490631424 (INVALID) | to int64: 9223372034707292159 (OK) to uint32: 2147483392 (INVALID) | to uint32: 2147483647 (OK) to uint64: 9223370939490631424 (INVALID) | to uint64: 9223372034707292159 (OK) from single: f32(-inf:0xff800000) < to double: f64(-inf:0x00fff0000000000000) (OK) < to int32: -2147483648 (INVALID) < to int64: 1 (INVALID) < to uint32: -2147483648 (INVALID) < to uint64: -9223372034707292160 (INVALID) < from single: f32(-0x1.fffffe00000000000000p+127:0xff7fffff) from single: f32(-0x1.fffffe00000000000000p+127:0xff7fffff) to double: f64(-0x1.fffffe00000000000000p+127:0x00c7efffffe to double: f64(-0x1.fffffe00000000000000p+127:0x00c7efffffe to int32: -2147483648 (INVALID) | to int32: -2147483648 (OK) to int64: 1 (INVALID) | to int64: 1 (OK) to uint32: -2147483648 (INVALID) | to uint32: -2147483648 (OK) to uint64: -9223372034707292160 (INVALID) | to uint64: -9223372034707292160 (OK) snipped a bunch more.
Le 28/04/2020 à 19:17, KONRAD Frederic a écrit : > 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.konrad@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) > According to "M68000 FAMILY PROGRAMMER’S REFERENCE MANUAL" the explicit integer bit is "Don't care" for signed infinite (a.high == 0x7FFF) (this is the case this patch manages). But wit a zero exponent and a non zero mantissa, it's a denormal number, and a signed zero has also a zero explicit integer bit but a zero mantissa. (both cases are already managed in the existing code). with a non zero exponent less than the maximum value it's an unnormal number. The denormal and unnormal numbers must be managed during the load operation in the m68k TCG emulation to generate directly the FP_UNIMP exception. So I think, in the end, we don't have invalid number at softfloat level and floatx80_invalid_encoding() should always return "false" for TARGET_M68K. Thanks, Laurent
Missed this one sorry. Le 6/12/20 à 10:31 AM, Laurent Vivier a écrit : > Le 28/04/2020 à 19:17, KONRAD Frederic a écrit : >> 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: >> [...] > > According to "M68000 FAMILY PROGRAMMER’S REFERENCE MANUAL" the explicit > integer bit is "Don't care" for signed infinite (a.high == 0x7FFF) (this > is the case this patch manages). > > But wit a zero exponent and a non zero mantissa, it's a denormal number, > and a signed zero has also a zero explicit integer bit but a zero > mantissa. (both cases are already managed in the existing code). > > with a non zero exponent less than the maximum value it's an unnormal > number. > > The denormal and unnormal numbers must be managed during the load > operation in the m68k TCG emulation to generate directly the FP_UNIMP > exception. Is this already handled in the TCG code? Thanks, Fred > > So I think, in the end, we don't have invalid number at softfloat level > and floatx80_invalid_encoding() should always return "false" for > TARGET_M68K. > > Thanks, > Laurent >
Le 15/06/2020 à 17:59, Fred Konrad a écrit : > Missed this one sorry. > > Le 6/12/20 à 10:31 AM, Laurent Vivier a écrit : >> Le 28/04/2020 à 19:17, KONRAD Frederic a écrit : >>> 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: >>> > > [...] > >> >> According to "M68000 FAMILY PROGRAMMER’S REFERENCE MANUAL" the explicit >> integer bit is "Don't care" for signed infinite (a.high == 0x7FFF) (this >> is the case this patch manages). >> >> But wit a zero exponent and a non zero mantissa, it's a denormal number, >> and a signed zero has also a zero explicit integer bit but a zero >> mantissa. (both cases are already managed in the existing code). >> >> with a non zero exponent less than the maximum value it's an unnormal >> number. >> >> The denormal and unnormal numbers must be managed during the load >> operation in the m68k TCG emulation to generate directly the FP_UNIMP >> exception. > > Is this already handled in the TCG code? No, I have a skeleton with a workaround but if we enable the exception the kernel crashes because the size of the frame saved in the stack by fsave is not the one expected by the kernel (we save an IDLE frame and not the UNIMP frame). https://github.com/vivier/qemu-m68k/commit/c1297f61db283ccd592333f56907bd2961f1843c I've also sent a patch similar to yours but disabling totally the floatx80_invalid_encoding() check. https://patchew.org/QEMU/20200612140400.2130118-1-laurent@vivier.eu/ Thanks, Laurent
On Apr 29 2020, Laurent Vivier wrote: > "Since the extended-precision data format has an explicit integer bit, a > number can be formatted with a nonzero exponent, less than the maximum > value, and a zero integer bit. The IEEE 754 standard does not define a > zero integer bit. Such a number is an unnormalized number. Hardware does > not directly support denormalized and unnormalized numbers, but > implicitly supports them by trapping them as unimplemented data types, > allowing efficient conversion in software." This is supposed to be handled transparently by fpsp040, to be compatible with the 68881. Andreas.
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)
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.konrad@adacore.com> --- include/fpu/softfloat.h | 5 +++++ 1 file changed, 5 insertions(+)