Skip to content

floating-point operations broken on hppa

Host environment

  • Operating system: Ubuntu 24.04
  • OS/kernel version: Linux 6.8.0-83-generic
  • Architecture: x86_64
  • QEMU flavor: qemu-system-hppa
  • QEMU version: 9.2.4, 10.0.5, 10.1.1
  • QEMU command line:
    qemu-system-hppa -M B160L -m 256 -drive file=t2sde.qcow2,format=qcow2,id=hd0 -nographic -kernel boot/vmlinux-6.16.10-t2 -initrd boot/initrd-6.16.10-t2 -append root=/dev/sda1

Emulated/Virtualized environment

  • Operating system: T2SDE 25.10
  • OS/kernel version: Linux 6.16.10-t2
  • Architecture: hppa

Description of problem

Starting with qemu version 9.2.x, some floating-point operations, especially regarding the floating-point environment, are broken on hppa.

Steps to reproduce

The binaries in https://haible.de/bruno/gnu/qemu-hppa-failing-tests.tar.xz

  test-fenv-env-2
  test-fenv-env-3
  test-fenv-env-4
  test-fenv-env-5
  test-fenv-except-state-2
  test-fenv-except-state-4
  test-fenv-except-tracking-1
  test-snan-1

are 32-bit hppa binaries, created in two steps:

  1. Using gnulib, create a compilable directory:
$ ./gnulib-tool --create-testdir --dir=../testdir1 fenv-environment fenv-exceptions-state-c23 fenv-exceptions-tracking-c99 snan
  1. Build it on a T2SDE 25.10 (https://dl.t2sde.org/binary/2025/t2-25.10-hppa-base-wayland-glibc-gcc.iso) virtual machine, with CC="gcc -static".

These binaries work fine

  • on real HPPA hardware (hppadev.matoro.tk),
  • in said virtual machine, with qemu versions 8.2.10, 9.0.4, 9.1.3.

These binaries crash due to assertion failures

  • in said virtual machine, with qemu versions 9.2.4, 10.0.5, 10.1.1.

Failures:

$ ./test-fenv-env-2
../../gltests/test-fenv-env-2.c:66: assertion '(fetestexcept (FE_ALL_EXCEPT) & ~FE_VXSOFT) == (FE_INVALID | FE_OVERFLOW | FE_INEXACT)' failed

Source code location: https://github.com/coreutils/gnulib/blob/master/tests/test-fenv-env-2.c#L66

$ ./test-fenv-env-3
../../gltests/test-fenv-env-3.c:66: assertion '(fetestexcept (FE_ALL_EXCEPT) & ~FE_VXSOFT) == (FE_INVALID | FE_OVERFLOW | FE_INEXACT)' failed

Source code location: https://github.com/coreutils/gnulib/blob/master/tests/test-fenv-env-3.c#L66

$ ./test-fenv-env-4
../../gltests/test-fenv-env-4.c:85: assertion 'fetestexcept (FE_ALL_EXCEPT) == (supports_tracking ? FE_UNDERFLOW | FE_INEXACT : 0)' failed

Source code location: https://github.com/coreutils/gnulib/blob/master/tests/test-fenv-env-4.c#L85

$ ./test-fenv-env-5
../../gltests/test-fenv-env-5.c:87: assertion 'fetestexcept (FE_ALL_EXCEPT) == (supports_tracking ? FE_UNDERFLOW | FE_INEXACT : 0)' failed

Source code location: https://github.com/coreutils/gnulib/blob/master/tests/test-fenv-env-5.c#L87

$ ./test-fenv-except-state-2
../../gltests/test-fenv-except-state-2.c:47: assertion 'fetestexcept (FE_INVALID) == FE_INVALID' failed

Source code location: https://github.com/coreutils/gnulib/blob/master/tests/test-fenv-except-state-2.c#L47

$ ./test-fenv-except-state-4
../../gltests/test-fenv-except-state-4.c:44: assertion 'fetestexceptflag (&saved_flags_1, FE_INVALID | FE_DIVBYZERO | FE_OVERFLOW | FE_UNDERFLOW | FE_INEXACT) == (FE_INVALID | FE_DIVBYZERO | FE_OVERFLOW | FE_UNDERFLOW | FE_INEXACT)' failed

Source code location: https://github.com/coreutils/gnulib/blob/master/tests/test-fenv-except-state-4.c#L44

$ ./test-fenv-except-tracking-1
../../gltests/test-fenv-except-tracking-1.c:45: assertion 'fetestexcept (FE_ALL_EXCEPT) == FE_ALL_EXCEPT || (fetestexcept (FE_ALL_EXCEPT) & ~FE_VXSOFT) == (FE_DIVBYZERO | FE_INEXACT | FE_INVALID | FE_OVERFLOW | FE_UNDERFLOW)' failed

Source code location: https://github.com/coreutils/gnulib/blob/master/tests/test-fenv-except-tracking-1.c#L45

$ ./test-snan-1
../../gltests/test-snan-1.c:75: assertion 'fetestexcept (FE_INVALID)' failed

Source code location: https://github.com/coreutils/gnulib/blob/master/tests/test-snan-1.c#L75

Additional information

What this points to, is that these assembly language statements don't work any more:

/* The status register is located in bits 0 to 31 of floating-point register 0.  */
# define _FPU_GETCW(cw) \
({                                                                              \
  union { __extension__ unsigned long long __fpreg; unsigned int __halfreg[2]; } __fullfp; \
  /* Get the current status word. */                                            \
  __asm__ ("fstd %%fr0,0(%1)\n\t"                                               \
           "fldd 0(%1),%%fr0\n\t"                                               \
           : "=m" (__fullfp.__fpreg) : "r" (&__fullfp.__fpreg) : "%r0");        \
  cw = __fullfp.__halfreg[0];                                                   \
})
# define _FPU_SETCW(cw) \
({                                                                              \
  union { __extension__ unsigned long long __fpreg; unsigned int __halfreg[2]; } __fullfp; \
  /* Get the current status word and set the control word.  */                  \
  __asm__ ("fstd %%fr0,0(%1)\n\t"                                               \
           : "=m" (__fullfp.__fpreg) : "r" (&__fullfp.__fpreg) : "%r0");        \
  __fullfp.__halfreg[0] = cw;                                                   \
  __asm__ ("fldd 0(%1),%%fr0\n\t"                                               \
           : : "m" (__fullfp.__fpreg), "r" (&__fullfp.__fpreg) : "%r0" );       \
})
To upload designs, you'll need to enable LFS and have an admin enable hashed storage. More information