• 80-bit subnormals printed incorrectly on Debian 11 M68K

    From Nelson H. F. Beebe@21:1/5 to All on Wed Jul 21 16:00:01 2021
    I run a large farm of physical and virtual machines that we use for
    software testing. We have multiple versions of most of the major
    operating systems, covering the major CPU families of the past 30
    years, including M68K.

    In testing some numerical software on Debian 11 on M68k (emulated by
    QEMU 4.2.1), I discovered that 80-bit subnormals are printed
    incorrectly: they are exactly HALF their correct values.

    A test program is provided below, and a snippet of its identical and
    correct output on x86_64 and IA-64 (Itanium) physical hardware looks
    like this around the transition from tiny normal numbers to subnormal
    numbers:

    k = -16380 x = 0x8.0000000000000000p-16383 = 1.344841257244837403e-4931 = 0x0003_80000000_00000000
    k = -16381 x = 0x8.0000000000000000p-16384 = 6.724206286224187013e-4932 = 0x0002_80000000_00000000
    k = -16382 x = 0x8.0000000000000000p-16385 = 3.362103143112093506e-4932 = 0x0001_80000000_00000000

    ---------- begin subnormals ----------

    k = -16383 x = 0x4.0000000000000000p-16385 = 1.681051571556046753e-4932 = 0x0000_40000000_00000000
    k = -16384 x = 0x2.0000000000000000p-16385 = 8.405257857780233766e-4933 = 0x0000_20000000_00000000
    k = -16385 x = 0x1.0000000000000000p-16385 = 4.202628928890116883e-4933 = 0x0000_10000000_00000000

    Here is the output from Debian 11 on M68k (identical with both gcc-9
    and gcc-10):

    k = -16380 x = 0x8.0000000000000000p-16383 = 1.344841257244837403e-4931 = 0x0003_80000000_00000000
    k = -16381 x = 0x8.0000000000000000p-16384 = 6.724206286224187013e-4932 = 0x0002_80000000_00000000
    k = -16382 x = 0x8.0000000000000000p-16385 = 3.362103143112093506e-4932 = 0x0001_80000000_00000000

    ---------- begin subnormals ----------

    k = -16383 x = 0x4.0000000000000000p-16386 = 8.405257857780233766e-4933 = 0x0000_40000000_00000000
    k = -16384 x = 0x2.0000000000000000p-16386 = 4.202628928890116883e-4933 = 0x0000_20000000_00000000
    k = -16385 x = 0x1.0000000000000000p-16386 = 2.101314464445058441e-4933 = 0x0000_10000000_00000000

    In the output, k is the power of 2. The M68K normals are correct, but
    the subnormals are half their correct size in both hexadecimal and
    decimal. The storage values shown in hex on the right prove that the
    hardware, and QEMU, are doing the right thing, so it is definitely not
    a QEMU bug.

    The cause MIGHT be the incorrect value in <float.h> of LDBL_MIN_EXP:
    the M68K system has -16382, whereas test output from every other
    system in our farm that supports an 80-bit IEEE 754 format has -16381.

    For another possibly independent check, I tried to install clang on
    M68K: clang is listed in the Debian 11 package repertoire, but it
    fails to install because of a missing dependency.

    It is unclear to me what the appropriate bug reporting address is for
    this problem: the wrong output is produced by the printf() family in
    libc, but the <float.h> file is provided by the compiler. Both need
    fixing.

    A local patch to <float.h> won't fix the problem, because the value of
    the macro LDBL_MIN_EXP has already been compiled and frozen into code
    in libc.

    Perhaps a seasoned debian-68k list member might be kind enough to
    suggest an appropriate bug-reporting address.

    At present, I have no other operating system than Debian 11 on M68K.
    Web searches indicate that OpenBSD 5.1 ran on that CPU, but its
    package archives have been been deleted. NetBSD 9.2 has an ISO image
    for M68K, but I have not yet successfully created a VM for it.
    Suggestions for other O/Ses to try are welcome.

    The test code below can be run like this:

    $ cc bug-float80.c && ./a.out

    $ cat bug-float80.c /***********************************************************************
    ** Demonstrate a bug in the Debian 11 M68K display of subnormal numbers,
    ** which are shown in both decimal and hexadecimal at half their correct
    ** values. The stored memory patterns agree on M68K, Intel x86, and
    ** Intel IA-64, showing that the hardware (and its QEMU emulation) is
    ** consistent and correct.
    **
    ** The bug MIGHT be traceable to the off-by-one error in <float.h> of
    ** LDBL_MIN_EXP, which is incorrectly defined as -16382, instead of the
    ** correct -16381 found on the Intel systems.
    **
    ** [20-Jul-2021] ***********************************************************************/

    #include <float.h>
    #include <stdint.h>
    #include <stdio.h>
    #include <stdlib.h>

    #if defined(__m68k__)
    typedef long double __float80;
    #endif

    #define PRINTF (void)printf

    int
    main(void)
    {
    __float80 x;
    int k, big_endian;
    union { long double v; uint16_t i[6]; uint32_t j[3]; } u;

    u.v = 0x1p0;
    big_endian = (u.i[4] == 0);

    PRINTF("Addressing is %s-endian\n", big_endian ? "big" : "little");
    PRINTF("sizeof(long double) = %d\n", (int)sizeof(long double));
    PRINTF("\n");

    PRINTF("LDBL_MANT_DIG = %d\n", (int)LDBL_MANT_DIG);
    PRINTF("LDBL_MIN_EXP = %d\n", (int)LDBL_MIN_EXP);
    PRINTF("LDBL_MIN = %0.16La = %0.19Lg\n", (long double)LDBL_MIN, (long double)LDBL_MIN);
    PRINTF("\n");

    x = 0x0.deadbeefcafefeedp-16381L;
    u.v = x;
    k = -16381;

    /*
    ** From the M68000 Family Programmer’s Reference Manual, page 1-16,
    ** M68000PM/A Rev. 1, 1992, memory storage of an 80-bit floating-point value
    ** is in a 96-bit (12-byte) big-endian-addressed field that looks like this:
    **
    ** |-- sign |||||||||||||||--always zero
    ** v vvvvvvvvvvvvvvv
    ** 94 79 63 0
    ** seeeeeeeeeeeeeee0000000000000000mmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmm
    ** ^^^^^^^^^^^^^^^
    ** |||||||||||||||-- exponent
    ** ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
    ** ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||-- significand (formerly, mantissa)
    **
    ** aaaaaaaaaaaaaaaa0000000000000000bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbcccccccccccccccccccccccccccccccc <- 32-bit fullwords
    ** 0 1 2 <- fullword number
    **
    ** aaaaaaaaaaaaaaaa0000000000000000bbbbbbbbbbbbbbbbccccccccccccccccddddddddddddddddeeeeeeeeeeeeeeee <- 16-bit halfword
    ** 0 1 2 3 4 5 <- halfword number
    **
    ** aaaaaaaabbbbbbbb0000000000000000ccccccccddddddddeeeeeeeeffffffffgggggggghhhhhhhhiiiiiiiijjjjjjjj <- 8-bit bytes
    ** 0 1 2 3 4 5 6 7 8 9 10 11 <- byte number
    **
    ** Notice that storage bits 64--80 are unused, and set to zero.
    **
    ** On the Intel x86 and IA-64 and the MC 68K, the binary point lies
    ** AFTER the first (high-order) significand digit, which is always
    ** explicitly stored (never hidden). The Intel formats store an
    ** 80-bit value right-adjusted in a 16-byte little-endian-addressed field,
    ** with the high order six bytes set to zero.
    **
    ** On page 1-17, the PRM says:
    **
    ** There is a subtle difference between the definition of an
    ** extended-precision number with an exponent equal to zero and a
    ** single- or double-precision number with an exponent equal to
    ** zero. The zero exponent of a single- or double-precision number
    ** denormalizes the number's definition, and the implied integer bit is
    ** zero. An extended-precision number with an exponent of zero may have
    ** an explicit integer bit equal to one. This results in a normalized
    ** number, though the exponent is equal to the minimum value. For
    ** simplicity, the following discussion treats all three floating-point
    ** formats in the same manner, where an exponent value of zero
    ** identifies a denormalized number. However, remember the
    ** extended-precision format can deviate from this rule.
    **
    ** The code below exhibits the stored data via both 32-bit and 16-bit integer
    ** overlays, being careful to discard bytes in positions 64..80
    */

    if (big_endian)
    PRINTF("k = %6d\tx = %0.16La = %#0.19Lg = 0x%04x_%08x_%08x\n", k, x, x, u.j[0] >> 16, u.j[1], u.j[2]);
    else
    PRINTF("k = %6d\tx = %0.16La = %#0.19Lg = 0x%04x_%08x_%08x\n", k, x, x, u.j[2], u.j[1], u.j[0]);

    if (big_endian)
    PRINTF("k = %6d\tx = %0.16La = %#0.19Lg = 0x%04hx_%04hx%04hx_%04hx%04hx\n", k, x, x, u.i[0], u.i[2], u.i[3], u.i[4], u.i[5]);
    else
    PRINTF("k = %6d\tx = %0.16La = %#0.19Lg = 0x%04hx_%04hx%04hx_%04hx%04hx\n", k, x, x, u.i[4], u.i[3], u.i[2], u.i[1], u.i[0]);

    PRINTF("\n");

    x = 0x1p-16376L;
    for (k = -16376; k > -16390; --k)
    {
    u.v = x;

    if (big_endian)
    PRINTF("k = %6d\tx = %0.16La = %#0.19Lg = 0x%04hx_%04hx%04hx_%04hx%04hx\n", k, x, x, u.i[0], u.i[2], u.i[3], u.i[4], u.i[5]);
    else
    PRINTF("k = %6d\tx = %0.16La = %#0.19Lg = 0x%04hx_%04hx%04hx_%04hx%04hx\n", k, x, x, u.i[4], u.i[3], u.i[2], u.i[1], u.i[0]);

    if (k == -16382)
    PRINTF("\n---------- begin subnormals ----------\n\n");

    x *= 0.5L;
    }

    return (EXIT_SUCCESS);
    }

    ------------------------------------------------------------------------------- - Nelson H. F. Beebe Tel: +1 801 581 5254 - - University of Utah FAX: +1 801 581 4148 - - Department of Mathematics, 110 LCB Internet e-mail: beebe@math.utah.edu - - 155 S 1400 E RM 233 beebe@acm.org beebe@computer.org - - Salt Lake City, UT 84112-0090, USA URL: http://www.math.utah.edu/~beebe/ - -------------------------------------------------------------------------------

    --- SoupGate-Win32 v1.05
    * Origin: fsxNet Usenet Gateway (21:1/5)
  • From Andreas Schwab@21:1/5 to Nelson H. F. Beebe on Wed Jul 21 16:50:01 2021
    On Jul 21 2021, Nelson H. F. Beebe wrote:

    The cause MIGHT be the incorrect value in <float.h> of LDBL_MIN_EXP:
    the M68K system has -16382, whereas test output from every other
    system in our farm that supports an 80-bit IEEE 754 format has -16381.

    This is correct. In the m68881 extended float format, denormals have an exponent bias of 0x3fff, whereas in the i387 extended float format, the
    bias is 0x3fffe. That means that a normalized number in m68881 ext
    format can have a biased exponent of zero.

    Andreas.

    --
    Andreas Schwab, schwab@linux-m68k.org
    GPG Key fingerprint = 7578 EB47 D4E5 4D69 2510 2552 DF73 E780 A9DA AEC1
    "And now for something completely different."

    --- SoupGate-Win32 v1.05
    * Origin: fsxNet Usenet Gateway (21:1/5)
  • From Nelson H. F. Beebe@21:1/5 to All on Wed Jul 21 18:30:01 2021
    Andreas Schwab responds to my problem report posted at

    https://lists.debian.org/debian-68k/2021/07/msg00000.html

    ...
    The cause MIGHT be the incorrect value in <float.h> of LDBL_MIN_EXP:
    the M68K system has -16382, whereas test output from every other
    system in our farm that supports an 80-bit IEEE 754 format has -16381.

    This is correct. In the m68881 extended float format, denormals have an
    exponent bias of 0x3fff, whereas in the i387 extended float format, the
    bias is 0x3fffe. That means that a normalized number in m68881 ext
    format can have a biased exponent of zero.
    ...

    I must disagree.

    From the cited M68000 Family Programmer's Reference Manual, on page
    1-23, in Table 1-6. Extended-Precision Real Format Summary, the biased
    exponent is defined as 15 bits wide, with a bias of +16383 (0x3fff).

    In IA-32 Intel Architecture Software Developer’s Manual Volume 1:
    Basic Architecture, 2001, page 4-6, below Table 4-3, Floating-Point
    Number and NaN Encodings, it says:

    ...
    The biasing constant is 127 for the single-precision format, 1023 for
    the double-precision format, and 16,383 for the double
    extended-precision format.
    ...

    The Intel IA-64 Application Developer's Architecture Guide, May 1999,
    (Order Number: 245188-001) on page 5-1, in Table 5-1 has

    ...
    Total memory format width (bits) 32 64 80 128 >> Exponent bias +127 +1023 +16383 +16383 >> ...


    IEEE Std 754-1985, IEEE Standard for Floating-Point Arithmetic on page
    3, says that the exponent bias for the single and double extended
    formats is unspecified. The later 2008 and 2019 IEEE Standards do not
    mention the 80-bit format.

    The IEEE 754 designers wrote a series of papers in the IEEE journal
    Computer in 1980, one of which is

    Jerome T. Coonen
    An Implementation Guide to a Proposed Standard for Floating-Point Arithmetic
    Computer 13(1) 68--79 (January 1980)
    https://doi.org/10.1109/MC.1980.1653344

    Its Table 2 on page 70 shows a minimum exponent of the 80-bit format
    as less than or equal to -16383 (at the time, CPU designs for IEEE 754
    were in progress at Intel and Motorola, and possibly also National Semiconductor, but those companies had not yet released details, or
    chips). The earliest hardware implementing the IEEE 754 draft was the
    Intel 8087 floating-point co-processor, which hit the market in the
    summer of 1980. It is described in detail in the book

    John F. Palmer and Stephen P. Morse
    The 8087 Primer
    Wiley (1984)
    ISBN 0-471-87569-4

    The Motorola 68881 floating-point co-processor reached the market in
    1984. It is described in

    MC68881 Floating-Point Coprocessor User's Manual, second edition
    (1985)

    See also

    https://en.wikipedia.org/wiki/IA-64
    https://en.wikipedia.org/wiki/Intel_8087
    https://en.wikipedia.org/wiki/Motorola_68881
    https://en.wikipedia.org/wiki/NS32000

    More information about floating-point designs can be found in this
    extensive bibliography of about 6900 literature references:

    http://www.math.utah.edu/pub/tex/bib/fparith.bib
    http://www.math.utah.edu/pub/tex/bib/fparith.bib

    Thus, three independent hardware designs --- M68K, IA-32, and IA-64
    --- agree that the bias in the 80-bit format is 16363 (0x3fff). That
    in turn means that their in-CPU-register formats for the 80-bit size
    are identical, except for the question of what bit patterns are used
    for NaNs, which are not relevant for my report.

    The test output in my report shows that all three architectures have
    the same bit patterns for numbers on either side of the transition
    from normals to subnormals. The M68K subnormals in the output should
    have values of 2**k, but are in fact printed as half that. The test
    loop halves the x value on each iteration (an EXACT operation in
    binary floating-point), so the tabulated numbers must fall by exactly
    half. They do for x86 and IA-64, but not for M68K once subnormals are
    reached.

    ------------------------------------------------------------------------------- - Nelson H. F. Beebe Tel: +1 801 581 5254 - - University of Utah FAX: +1 801 581 4148 - - Department of Mat
  • From Andreas Schwab@21:1/5 to Nelson H. F. Beebe on Wed Jul 21 19:20:02 2021
    On Jul 21 2021, Nelson H. F. Beebe wrote:

    The Intel IA-64 Application Developer's Architecture Guide, May 1999,
    (Order Number: 245188-001) on page 5-1, in Table 5-1 has

    ...
    Total memory format width (bits) 32 64 80 128 >>> Exponent bias +127 +1023 +16383 +16383

    That are the biases for normalized numbers. What does it say about denormalized numbers? Note that the i387 format does not allow for a
    biased exponent of zero when the explicit integer bit is one, unlike the
    m68881 format.

    Andreas.

    --
    Andreas Schwab, schwab@linux-m68k.org
    GPG Key fingerprint = 7578 EB47 D4E5 4D69 2510 2552 DF73 E780 A9DA AEC1
    "And now for something completely different."

    --- SoupGate-Win32 v1.05
    * Origin: fsxNet Usenet Gateway (21:1/5)
  • From Finn Thain@21:1/5 to Stan Johnson on Thu Jul 22 12:00:01 2021
    On Wed, 21 Jul 2021, Stan Johnson wrote:


    Here is the output from Debian 11 on M68k (identical with both gcc-9
    and gcc-10):

    k = -16380 x = 0x8.0000000000000000p-16383 = 1.344841257244837403e-4931 = 0x0003_80000000_00000000
    k = -16381 x = 0x8.0000000000000000p-16384 = 6.724206286224187013e-4932 = 0x0002_80000000_00000000
    k = -16382 x = 0x8.0000000000000000p-16385 = 3.362103143112093506e-4932 = 0x0001_80000000_00000000

    ---------- begin subnormals ----------

    k = -16383 x = 0x4.0000000000000000p-16386 = 8.405257857780233766e-4933 = 0x0000_40000000_00000000
    k = -16384 x = 0x2.0000000000000000p-16386 = 4.202628928890116883e-4933 = 0x0000_20000000_00000000
    k = -16385 x = 0x1.0000000000000000p-16386 = 2.101314464445058441e-4933 = 0x0000_10000000_00000000


    Here's the output of your program from a Mac IIci running Debian SID
    (using gcc version 9.2.1):

    -----

    $ cat /proc/cpuinfo
    CPU: 68030
    MMU: 68030
    FPU: 68882

    I wonder if that hardware should be expected to give the same result as
    68040 hardware (?) Both QEMU and Aranym emulate the latter:

    CPU: 68040
    MMU: 68040
    FPU: 68040
    Clocking: 211.0MHz
    BogoMips: 140.69
    Calibration: 703488 loops

    Clocking: 23.1MHz
    BogoMips: 5.78
    Calibration: 28928 loops

    $ cc bug-float80.c
    $ ./a.out
    Addressing is big-endian
    sizeof(long double) = 12

    LDBL_MANT_DIG = 64
    LDBL_MIN_EXP = -16382
    LDBL_MIN = 0x8.0000000000000000p-16386 = 1.681051571556046753e-4932

    k = -16381 x = 0xd.eadbeefcafefeed0p-16385 = 5.848974526544159967e-4932 = 0x0001_deadbeef_cafefeed
    k = -16381 x = 0xd.eadbeefcafefeed0p-16385 = 5.848974526544159967e-4932 = 0x0001_deadbeef_cafefeed

    k = -16376 x = 0x8.0000000000000000p-16379 = 2.151746011591739844e-4930 = 0x0007_80000000_00000000
    k = -16377 x = 0x8.0000000000000000p-16380 = 1.075873005795869922e-4930 = 0x0006_80000000_00000000
    k = -16378 x = 0x8.0000000000000000p-16381 = 5.379365028979349610e-4931 = 0x0005_80000000_00000000
    k = -16379 x = 0x8.0000000000000000p-16382 = 2.689682514489674805e-4931 = 0x0004_80000000_00000000
    k = -16380 x = 0x8.0000000000000000p-16383 = 1.344841257244837403e-4931 = 0x0003_80000000_00000000
    k = -16381 x = 0x8.0000000000000000p-16384 = 6.724206286224187013e-4932 = 0x0002_80000000_00000000
    k = -16382 x = 0x8.0000000000000000p-16385 = 3.362103143112093506e-4932 = 0x0001_80000000_00000000

    ---------- begin subnormals ----------

    k = -16383 x = 0x8.0000000000000000p-16386 = 1.681051571556046753e-4932 = 0x0000_80000000_00000000
    k = -16384 x = 0x4.0000000000000000p-16386 = 8.405257857780233766e-4933 = 0x0000_40000000_00000000
    k = -16385 x = 0x2.0000000000000000p-16386 = 4.202628928890116883e-4933 = 0x0000_20000000_00000000
    k = -16386 x = 0x1.0000000000000000p-16386 = 2.101314464445058441e-4933 = 0x0000_10000000_00000000
    k = -16387 x = 0x0.8000000000000000p-16386 = 1.050657232222529221e-4933 = 0x0000_08000000_00000000
    k = -16388 x = 0x0.4000000000000000p-16386 = 5.253286161112646104e-4934 = 0x0000_04000000_00000000
    k = -16389 x = 0x0.2000000000000000p-16386 = 2.626643080556323052e-4934 = 0x0000_02000000_00000000


    My Aranym 68040 test agrees with the Motorola 68882 result from Stan.

    My QEMU 68040 test agrees with Nelson's results.

    It's suprising to see a discrepancy between the two emulators, but it
    seems to be real (same rootfs image).

    $ qemu-system-m68k --version
    QEMU emulator version 6.0.0
    Copyright (c) 2003-2021 Fabrice Bellard and the QEMU Project developers

    $ aranym-mmu --version
    ARAnyM 1.1.0 2020/06/16 (git:3ab938a4)
    Using config file: '/home/fthain/.aranym/config'
    Configuration:
    SDL (compiled) : 2.0.10
    SDL (linked) : 2.0.14
    CPU JIT compiler : disabled
    FPU JIT compiler : disabled
    Addressing mode : direct
    Memory check : page
    Full MMU : enabled
    FPU : MPFR
    DSP : enabled
    DSP disassembler : disabled
    OpenGL support : enabled
    Native features : audio bootstrap xhdi ethernet hostfs cdrom(linux) scsi jpeg vdi(opengl,sw) exec config clipboard

    ...
    At present, I have no other operating system than Debian 11 on M68K.
    Web searches indicate that OpenBSD 5.1 ran on that CPU, but its
    package archives have been been deleted. NetBSD 9.2 has an ISO image
    for M68K, but I have not yet successfully created a VM for it.
    Suggestions for other O/Ses to try are welcome.

    NetBSD runs on m68k systems; see http://www.netbsd.org. You could also
    try an earlier version of Debian (3.0 or 4.0) on m68k. And you might
    want to compare the musl libc to glibc; see https://wiki.musl-libc.org/functional-differences-from-glibc.html


    Another possibility would be A/UX, if more results are needed. There is an emulator that's intented to run A/UX called Shoebill. https://github.com/pruten/shoebill

    I don't know whether any of the many available emulators is capable of
    running a NetBSD/m68k port. That might be a question for a different
    mailing list.

    --- SoupGate-Win32 v1.05
    * Origin: fsxNet Usenet Gateway (21:1/5)
  • From Brad Boyer@21:1/5 to Finn Thain on Fri Jul 23 02:30:01 2021
    On Thu, Jul 22, 2021 at 07:32:49PM +1000, Finn Thain wrote:
    $ cat /proc/cpuinfo
    CPU: 68030
    MMU: 68030
    FPU: 68882

    I wonder if that hardware should be expected to give the same result as
    68040 hardware (?) Both QEMU and Aranym emulate the latter:

    CPU: 68040
    MMU: 68040
    FPU: 68040

    The m68k PRM does document some minor differences between the 68881/68882
    and the built-in FPU in the 68040 (other than the obvious unimplemented instructions in the 68040), but I don't think any of it would rise to
    this level. They're almost entirely compatible. My first guess would be
    an emulation bug. This is the sort of thing that would likely be easy to
    get wrong.

    My apologies for not having any of my 68040 systems available for a test
    on the real hardware. I'm not even sure if any of them still work.

    Brad Boyer
    flar@allandria.com

    --- SoupGate-Win32 v1.05
    * Origin: fsxNet Usenet Gateway (21:1/5)
  • From Finn Thain@21:1/5 to Stan Johnson on Sat Jul 24 06:10:01 2021
    On Fri, 23 Jul 2021, Stan Johnson wrote:

    On 7/22/21 5:57 PM, Brad Boyer wrote:
    On Thu, Jul 22, 2021 at 07:32:49PM +1000, Finn Thain wrote:
    $ cat /proc/cpuinfo
    CPU: 68030
    MMU: 68030
    FPU: 68882

    I wonder if that hardware should be expected to give the same result as
    68040 hardware (?) Both QEMU and Aranym emulate the latter:

    CPU: 68040
    MMU: 68040
    FPU: 68040

    The m68k PRM does document some minor differences between the 68881/68882 and the built-in FPU in the 68040 (other than the obvious unimplemented instructions in the 68040), but I don't think any of it would rise to
    this level. They're almost entirely compatible. My first guess would be
    an emulation bug. This is the sort of thing that would likely be easy to get wrong.

    My apologies for not having any of my 68040 systems available for a test
    on the real hardware. I'm not even sure if any of them still work.

    Brad Boyer
    flar@allandria.com


    Attached are three results of running bug-float80.c on m68k hardware:

    1) 68040, Centris 650, Debian SID, gcc 9.2.1

    It appears that your Motorola 68040 result agrees with your Motorola 68882 result, as Brad predicted.

    2) 68040, Centris 650, NetBSD 9.1, gcc 7.5.0
    3) 68030, Mac SE/30, NetBSD 9.1, gcc 7.5.0


    The NetBSD test results are in agreement, but they differ from Linux. I
    wonder why?

    The bug-float80.c program doesn't compile in its current form in A/UX;
    not only does stdint.h not exist there, but both Aople's C compiler and
    an early gcc (2.7.2) repported syntax errors.


    The program can probably be ported to System V Release 2 without too much
    pain. You'll have to drop stdint.h. You may need to include limits.h. And
    you may need to build it with "gcc -D__m68k__ bug-float80.c".

    Debian/m68k 3 "woody" has gcc 2.95.4, and it fails like this:

    sh-2.05a# cc -D__m68k__ bug-float80.c
    bug-float80.c: In function `main':
    bug-float80.c:45: hexadecimal floating constant has no exponent bug-float80.c:45: missing white space after number `0x0.deadbee' bug-float80.c:45: parse error before `cafefeedp'

    So I think you'll want to start with a patch like this:

    --- a/bug-float80.c 2021-07-22 19:08:30.000000000 +1000
    +++ b/bug-float80.c 2021-07-24 23:40:27.000000000 +1000
    @@ -13,9 +13,10 @@
    ***********************************************************************/

    #include <float.h>
    -#include <stdint.h>
    #include <stdio.h>
    #include <stdlib.h>
    +#include <string.h>
    +#include <limits.h>

    #if defined(__m68k__)
    typedef long double __float80;
    @@ -28,7 +29,7 @@
    {
    __float80 x;
    int k, big_endian;
    - union { long double v; uint16_t i[6]; uint32_t j[3]; } u;
    + union { long double v; unsigned short i[6]; unsigned long j[3]; } u;

    u.v = 0x1p0;
    big_endian = (u.i[4] == 0);
    @@ -42,7 +43,7 @@
    PRINTF("LDBL_MIN = %0.16La = %0.19Lg\n", (long double)LDBL_MIN, (long double)LDBL_MIN);
    PRINTF("\n");

    - x = 0x0.deadbeefcafefeedp-16381L;
    + memcpy(&x, "\x00\x01\x00\x00\xDE\xAD\xBE\xEF\xCA\xFE\xFE\xED", sizeof(x));
    u.v = x;
    k = -16381;


    BTW, limits.h in A/UX 3.0.1 has this:

    #if !defined(DBL_MIN)
  • From Antonio Vargas Gonzalez@21:1/5 to fthain@linux-m68k.org on Thu Jul 29 17:30:01 2021
    I could run this on my physical A1200 / 68060 compiling via VBCC for
    AmigaOS if you are interested in further info.

    ( FWIW: I'd really expect that 68882 68040 and 68060 will agree on all encondings, and also could be interesting to double check against WinUAE or FS-UAE)


    On Sat, Jul 24, 2021 at 6:06 AM Finn Thain <fthain@linux-m68k.org> wrote:

    On Fri, 23 Jul 2021, Stan Johnson wrote:

    On 7/22/21 5:57 PM, Brad Boyer wrote:
    On Thu, Jul 22, 2021 at 07:32:49PM +1000, Finn Thain wrote:
    $ cat /proc/cpuinfo
    CPU: 68030
    MMU: 68030
    FPU: 68882

    I wonder if that hardware should be expected to give the same result
    as
    68040 hardware (?) Both QEMU and Aranym emulate the latter:

    CPU: 68040
    MMU: 68040
    FPU: 68040

    The m68k PRM does document some minor differences between the
    68881/68882
    and the built-in FPU in the 68040 (other than the obvious unimplemented instructions in the 68040), but I don't think any of it would rise to this level. They're almost entirely compatible. My first guess would be an emulation bug. This is the sort of thing that would likely be easy
    to
    get wrong.

    My apologies for not having any of my 68040 systems available for a
    test
    on the real hardware. I'm not even sure if any of them still work.

    Brad Boyer
    flar@allandria.com


    Attached are three results of running bug-float80.c on m68k hardware:

    1) 68040, Centris 650, Debian SID, gcc 9.2.1

    It appears that your Motorola 68040 result agrees with your Motorola 68882 result, as Brad predicted.

    2) 68040, Centris 650, NetBSD 9.1, gcc 7.5.0
    3) 68030, Mac SE/30, NetBSD 9.1, gcc 7.5.0


    The NetBSD test results are in agreement, but they differ from Linux. I wonder why?

    The bug-float80.c program doesn't compile in its current form in A/UX;
    not only does stdint.h not exist there, but both Aople's C compiler and
    an early gcc (2.7.2) repported syntax errors.


    The program can probably be ported to System V Release 2 without too much pain. You'll have to drop stdint.h. You may need to include limits.h. And
    you may need to build it with "gcc -D__m68k__ bug-float80.c".

    Debian/m68k 3 "woody" has gcc 2.95.4, and it fails like this:

    sh-2.05a# cc -D__m68k__ bug-float80.c
    bug-float80.c: In function `main':
    bug-float80.c:45: hexadecimal floating constant has no exponent bug-float80.c:45: missing white space after number `0x0.deadbee' bug-float80.c:45: parse error before `cafefeedp'

    So I think you'll want to start with a patch like this:

    --- a/bug-float80.c 2021-07-22 19:08:30.000000000 +1000
    +++ b/bug-float80.c 2021-07-24 23:40:27.000000000 +1000
    @@ -13,9 +13,10 @@
    ***********************************************************************/

    #include <float.h>
    -#include <stdint.h>
    #include <stdio.h>
    #include <stdlib.h>
    +#include <string.h>
    +#include <limits.h>

    #if defined(__m68k__)
    typedef long double __float80;
    @@ -28,7 +29,7 @@
    {
    __float80 x;
    int k, big_endian;
    - union { long double v; uint16_t i[6]; uint32_t j[3]; } u;
    + union { long double v; unsigned short i[6]; unsigned long j[3]; } u;

    u.v = 0x1p0;
    big_endian = (u.i[4] == 0);
    @@ -42,7 +43,7 @@
    PRINTF("LDBL_MIN = %0.16La = %0.19Lg\n", (long double)LDBL_MIN, (long double)LDBL_MIN);
    PRINTF("\n");

    - x = 0x0.deadbeefcafefeedp-16381L;
    + memcpy(&x, "\x00\x01\x00\x00\xDE\xAD\xBE\xEF\xCA\xFE\xFE\xED", sizeof(x));
    u.v = x;
    k = -16381;


    BTW, limits.h in A/UX 3.0.1 has this:

    #if !defined(DBL_MIN)
    /* Minimum normalised double */
    #ifndef __STDC__
    # define DBL_MIN (2.2250738585072018e-308)
    #else
    # define DBL_MIN (2.2250738585072014e-308)
    #endif
    #endif

    However, the LDBL_* definitions seem to be independent of other macros.



    --
    Antonio Vargas Gonzalez | winden ^ capsule ^ rgba ^ network ^ batman.group |
    +windenntw <https://plus.google.com/117143451409201100384/about> | windenntw@gmail.com

    <div dir="ltr"><div><br></div>I could run this on my physical A1200 / 68060 compiling via VBCC for AmigaOS if you are interested in further info.<div><br></div><div>( FWIW: I&#39;d really expect that 68882 68040 and 68060 will agree on all encondings,
    and also could be interesting to double check against WinUAE or FS-UAE)</div><div><br></div></div><br><div class="gmail_quote"><div dir="ltr" class="gmail_attr">On Sat, Jul 24, 2021 at 6:06 AM Finn Thain &lt;<a href="mailto:fthain@linux-m68k.org">fthain@
    linux-m68k.org</a>&gt; wrote:<br></div><blockquote class="gmail_quote" style="margin:0px 0px 0px 0.8ex;border-left:1px solid rgb(204,204,204);padding-left:1ex">On Fri, 23 Jul 2021, Stan Johnson wrote:<br>

    &gt; On 7/22/21 5:57 PM, Brad Boyer wrote:<br>
    &gt; &gt; On Thu, Jul 22, 2021 at 07:32:49PM +1000, Finn Thain wrote:<br>
    &gt; &gt;&gt;&gt; $ cat /proc/cpuinfo<br>
    &gt; &gt;&gt;&gt; CPU:              68030<br>
    &gt; &gt;&gt;&gt; MMU:              68030<br>
    &gt; &gt;&gt;&gt; FPU:              68882<br>
    &gt; &gt;&gt;<br>
    &gt; &gt;&gt; I wonder if that hardware should be expected to give the same result as <br>
    &gt; &gt;&gt; 68040 hardware (?) Both QEMU and Aranym emulate the latter:<br> &gt; &gt;&gt;<br>
    &gt; &gt;&gt; CPU:            68040<br>
    &gt; &gt;&gt; MMU:            68040<br>
    &gt; &gt;&gt; FPU:            68040<br>
    &gt; &gt; <br>
    &gt; &gt; The m68k PRM does document some minor differences between the 68881/68882<br>
    &gt; &gt; and the built-in FPU in the 68040 (other than the obvious unimplemented<br>
    &gt; &gt; instructions in the 68040), but I don&#39;t think any of it would rise to<br>
    &gt; &gt; this level. They&#39;re almost entirely compatible. My first guess would be<br>
    &gt; &gt; an emulation bug. This is the sort of thing that would likely be easy to<br>
    &gt; &gt; get wrong.<br>
    &gt; &gt; <br>
    &gt; &gt; My apologies for not having any of my 68040 systems available for a test<br>
    &gt; &gt; on the real hardware. I&#39;m not even sure if any of them still work.<br>
    &gt; &gt; <br>
    &gt; &gt;     Brad Boyer<br>
    &gt; &gt;     <a href="mailto:flar@allandria.com" target="_blank">flar@allandria.com</a><br>
    &gt; &gt; <br>
    &gt; <br>
    &gt; Attached are three results of running bug-float80.c on m68k hardware:<br> &gt; <br>
    &gt; 1) 68040, Centris 650, Debian SID, gcc 9.2.1<br>

    It appears that your Motorola 68040 result agrees with your Motorola 68882 <br> result, as Brad predicted.<br>

    &gt; 2) 68040, Centris 650, NetBSD 9.1, gcc 7.5.0<br>
    &gt; 3) 68030, Mac SE/30, NetBSD 9.1, gcc 7.5.0<br>
    &gt; <br>

    The NetBSD test results are in agreement, but they differ from Linux. I <br> wonder why?<br>

    &gt; The bug-float80.c program doesn&#39;t compile in its current form in A/UX; <br>
    &gt; not only does stdint.h not exist there, but both Aople&#39;s C compiler and <br>
    &gt; an early gcc (2.7.2) repported syntax errors.<br>
    &gt; <br>

    The program can probably be ported to System V Release 2 without too much <br> pain. You&#39;ll have to drop stdint.h. You may need to include limits.h. And <br>
    you may need to build it with &quot;gcc -D__m68k__ bug-float80.c&quot;.<br>

    Debian/m68k 3 &quot;woody&quot; has gcc 2.95.4, and it fails like this:<br>

    sh-2.05a# cc -D__m68k__ bug-float80.c   <br>
    bug-float80.c: In function `main&#39;:<br>
    bug-float80.c:45: hexadecimal floating constant has no exponent<br> bug-float80.c:45: missing white space after number `0x0.deadbee&#39;<br> bug-float80.c:45: parse error before `cafefeedp&#39;<br>

    So I think you&#39;ll want to start with a patch like this:<br>

    --- a/bug-float80.c     2021-07-22 19:08:30.000000000 +1000<br>
    +++ b/bug-float80.c     2021-07-24 23:40:27.000000000 +1000<br>
    @@ -13,9 +13,10 @@<br>  ***********************************************************************/<br>

     #include &lt;float.h&gt;<br>
    -#include &lt;stdint.h&gt;<br>
     #include &lt;stdio.h&gt;<br>
     #include &lt;stdlib.h&gt;<br>
    +#include &lt;string.h&gt;<br>
    +#include &lt;limits.h&gt;<br>

     #if defined(__m68k__)<br>
     typedef long double __float80;<br>
    @@ -28,7 +29,7 @@<br>
     {<br>
         __float80 x;<br>
         int k, big_endian;<br>
    -    union { long double v; uint16_t i[6]; uint32_t j[3]; } u;<br>
    +    union { long double v; unsigned short i[6]; unsigned long j[3]; } u;<br>

         u.v = 0x1p0;<br>
         big_endian = (u.i[4] == 0);<br>
    @@ -42,7 +43,7 @@<br>
         PRINTF(&quot;LDBL_MIN      = %0.16La = %0.19Lg\n&quot;, (long double)LDBL_MIN, (long double)LDBL_MIN);<br>
         PRINTF(&quot;\n&quot;);<br>

    -    x = 0x
  • From Finn Thain@21:1/5 to All on Wed Aug 4 02:10:01 2021
    Hi Nelson,

    The results from your bug-float80.c program demonstrate two discrepancies: results from NetBSD and Linux (running on Motorola processors) are inconsistent, as are results from Aranym and QEMU (with Linux guests). Do
    you know of any official bug reports about these two issues?

    Regards,
    Finn

    --- SoupGate-Win32 v1.05
    * Origin: fsxNet Usenet Gateway (21:1/5)
  • From Eero Tamminen@21:1/5 to Finn Thain on Mon Aug 9 12:50:01 2021
    Hi,

    On 4.8.2021 2.52, Finn Thain wrote:
    The results from your bug-float80.c program demonstrate two discrepancies: results from NetBSD and Linux (running on Motorola processors) are inconsistent, as are results from Aranym and QEMU (with Linux guests). Do
    you know of any official bug reports about these two issues?

    (Git versions) of WinUAE and Hatari emulators
    could also be tried, with their software FPU
    emulation options.

    (In Hatari case, "--fpu-softfloat on" option.)


    - Eero

    --- SoupGate-Win32 v1.05
    * Origin: fsxNet Usenet Gateway (21:1/5)
  • From Vincent Lefevre@21:1/5 to Andreas Schwab on Sun Dec 25 00:10:01 2022
    In article <87pmvbobbn.fsf@igel.home>,
    Andreas Schwab <schwab@linux-m68k.org> wrote:

    On Jul 21 2021, Nelson H. F. Beebe wrote:

    The Intel IA-64 Application Developer's Architecture Guide, May 1999, (Order Number: 245188-001) on page 5-1, in Table 5-1 has

    ...
    Total memory format width (bits) 32 64 80 128
    Exponent bias +127 +1023 +16383 +16383

    That are the biases for normalized numbers. What does it say about denormalized numbers? Note that the i387 format does not allow for a
    biased exponent of zero when the explicit integer bit is one, unlike the m68881 format.

    As this has been discussed in the GNU MPFR mailing-list a few days ago,
    I've found that https://www.nxp.com/docs/en/reference-manual/M68000PM.pdf (MOTOROLA M68000 FAMILY – Programmer's Reference Manual) confirms the difference with the i387 format:

    Page 1-18, Section 1.6.1 "Normalized Numbers" says:

    In extended precision, the mantissa's MSB, the explicit integer bit,
    can only be a one (see Figure 1-13); and the exponent can be zero.

    and Section 1.6.2 "Denormalized Numbers" says:

    In extended precision, the mantissa's MSB, the explicit integer bit,
    can only be a zero (see Figure 1-14).

    So on m86k, emin is one less the Intel x87 emin, and the printf output
    is correct.

    --
    Vincent Lefèvre <vincent@vinc17.net> - Web: <https://www.vinc17.net/>
    100% accessible validated (X)HTML - Blog: <https://www.vinc17.net/blog/>
    Work: CR INRIA - computer arithmetic / AriC project (LIP, ENS-Lyon)

    --- SoupGate-Win32 v1.05
    * Origin: fsxNet Usenet Gateway (21:1/5)
  • From John Paul Adrian Glaubitz@21:1/5 to Vincent Lefevre on Sun Dec 25 00:10:01 2022
    Hi Vincent!

    On 12/24/22 23:51, Vincent Lefevre wrote:
    Here, the number has been divided by 4 instead of 2. The printf output
    is correct. This is a QEMU bug in the multiplication with subnormals.
    See the discussion in the MPFR mailing-list:
    https://sympa.inria.fr/sympa/arc/mpfr/2022-12/msg00036.html

    I'm actually the admin of the machine QEMU machine "mitchy" that was used by the
    original poster. I have actually not updated the QEMU version for some time and I think I should actually do that :-).

    I will use the sample code from the thread to see if the update made any difference.

    Adrian

    --
    .''`. John Paul Adrian Glaubitz
    : :' : Debian Developer
    `. `' Physicist
    `- GPG: 62FF 8A75 84E0 2956 9546 0006 7426 3B37 F5B5 F913

    --- SoupGate-Win32 v1.05
    * Origin: fsxNet Usenet Gateway (21:1/5)
  • From Vincent Lefevre@21:1/5 to Nelson H. F. Beebe on Sun Dec 25 00:10:01 2022
    In article <CMM.0.95.0.1626875139.beebe@gamma.math.utah.edu>,
    Nelson H. F. Beebe <beebe@math.utah.edu> wrote:

    I run a large farm of physical and virtual machines that we use for
    software testing. We have multiple versions of most of the major
    operating systems, covering the major CPU families of the past 30
    years, including M68K.

    In testing some numerical software on Debian 11 on M68k (emulated by
    QEMU 4.2.1), I discovered that 80-bit subnormals are printed
    incorrectly: they are exactly HALF their correct values.

    A test program is provided below, and a snippet of its identical and
    correct output on x86_64 and IA-64 (Itanium) physical hardware looks
    like this around the transition from tiny normal numbers to subnormal numbers:

    k = -16380 x = 0x8.0000000000000000p-16383 = 1.344841257244837403e-4931 = 0x0003_80000000_00000000
    k = -16381 x = 0x8.0000000000000000p-16384 = 6.724206286224187013e-4932 = 0x0002_80000000_00000000
    k = -16382 x = 0x8.0000000000000000p-16385 = 3.362103143112093506e-4932 = 0x0001_80000000_00000000

    ---------- begin subnormals ----------

    k = -16383 x = 0x4.0000000000000000p-16385 = 1.681051571556046753e-4932 = 0x0000_40000000_00000000
    k = -16384 x = 0x2.0000000000000000p-16385 = 8.405257857780233766e-4933 = 0x0000_20000000_00000000
    k = -16385 x = 0x1.0000000000000000p-16385 = 4.202628928890116883e-4933 = 0x0000_10000000_00000000

    Here is the output from Debian 11 on M68k (identical with both gcc-9
    and gcc-10):

    k = -16380 x = 0x8.0000000000000000p-16383 = 1.344841257244837403e-4931 = 0x0003_80000000_00000000
    k = -16381 x = 0x8.0000000000000000p-16384 = 6.724206286224187013e-4932 = 0x0002_80000000_00000000
    k = -16382 x = 0x8.0000000000000000p-16385 = 3.362103143112093506e-4932 = 0x0001_80000000_00000000

    ---------- begin subnormals ----------

    k = -16383 x = 0x4.0000000000000000p-16386 = 8.405257857780233766e-4933 = 0x0000_40000000_00000000

    Here, the number has been divided by 4 instead of 2. The printf output
    is correct. This is a QEMU bug in the multiplication with subnormals.
    See the discussion in the MPFR mailing-list:
    https://sympa.inria.fr/sympa/arc/mpfr/2022-12/msg00036.html

    --
    Vincent Lefèvre <vincent@vinc17.net> - Web: <https://www.vinc17.net/>
    100% accessible validated (X)HTML - Blog: <https://www.vinc17.net/blog/>
    Work: CR INRIA - computer arithmetic / AriC project (LIP, ENS-Lyon)

    --- SoupGate-Win32 v1.05
    * Origin: fsxNet Usenet Gateway (21:1/5)