On Mon, 17 Feb 2025 at 19:14, Richard Henderson
<richard.hender...@linaro.org> wrote:
>
> On 2/17/25 04:50, Peter Maydell wrote:
> > Currently we compile-time set an 'm68k_denormal' flag in the FloatFmt
> > for floatx80 for m68k.  This controls our handling of what the Intel
> > documentation calls a "pseudo-denormal": a value where the exponent
> > field is zero and the explicit integer bit is set.
> >
> > For x86, the x87 FPU is supposed to accept a pseudo-denormal as
> > input, but never generate one on output.  For m68k, these values are
> > permitted on input and may be produced on output.
> >
> > Replace the flag in the FloatFmt with a flag indicating whether the
> > float format has an explicit bit (which will be true for floatx80 for
> > all targets, and false for every other float type).  Then we can gate
> > the handling of these pseudo-denormals on the setting of a
> > floatx80_behaviour flag.
> >
> > As far as I can see from the code we don't actually handle the
> > x86-mandated "accept on input but don't generate" behaviour, because
> > the handling in partsN(canonicalize) looked at fmt->m68k_denormal.
> > So I have added TODO comments to that effect.
> >
> > This commit doesn't change any behaviour for any target.
> >
> > Signed-off-by: Peter Maydell <peter.mayd...@linaro.org>
> > ---
> > I'm confident this commit preserves existing behaviour, but
> > somewhat less confident that I've correctly analysed what our
> > current code does, in particular that it doesn't do the x86
> > mandated "handle pseudo-denormals on input" part.
>
> Test case:
>
> #include <stdio.h>
>
> int main()
> {
>      union {
>          struct {
>              unsigned long long m;
>              unsigned short e;
>          } i;
>          long double f;
>      } u[2] = { };
>      unsigned short sw;
>
>      asm volatile("fnclex" : : : "memory");
>
>      u[0].i.m = 0xc000000000000000ull;
>      u[0].f += u[1].f;  /* denormal + zero -> renormalize */
>
>      asm volatile("fstsw %w0" : "=a"(sw) : : "memory");
>
>      printf("%04x %016llx  %04x\n", u[0].i.e, u[0].i.m, sw);
>      return 0;
> }
>
> Expected behaviour is setting DE for consuming a denormal.

So, on real hardware I see
0001 c000000000000000  0002

and on QEMU, with the patchset that fixes the DE bit handling
https://patchew.org/QEMU/20250213142613.151308-1-peter.mayd...@linaro.org/
I also see the same thing.

That suggests that we are correctly implementing the x87
required behaviour in QEMU, and so that the TODO comment
I add in this patch isn't right. But then I'm a bit confused
about what the code is actually doing. Why do we need to look
at fmt->m68k_denormal in the input (canonicalize) code (i.e.
to have different behaviour here for x86 and m68k), if
both x86 and m68k accept these pseudodenormals as input?

Is the difference that for x86 we accept but canonicalize
into the equivalent normal number immediately on input,
whereas for m68k we accept and leave the pseudodenormal
as a pseudodenormal (well, m68k calls these a kind of
normal number) ?

thanks
-- PMM

Reply via email to