user-level: 0.838 permissions: 0.836 graphic: 0.800 virtual: 0.796 semantic: 0.746 debug: 0.716 register: 0.709 assembly: 0.693 device: 0.642 arm: 0.620 PID: 0.616 hypervisor: 0.607 architecture: 0.587 peripherals: 0.582 TCG: 0.582 mistranslation: 0.567 performance: 0.566 kernel: 0.538 ppc: 0.535 risc-v: 0.524 files: 0.494 x86: 0.452 boot: 0.441 VMM: 0.397 network: 0.370 socket: 0.369 vnc: 0.364 KVM: 0.357 i386: 0.234 -------------------- user-level: 0.976 ppc: 0.816 debug: 0.097 files: 0.072 TCG: 0.017 hypervisor: 0.016 virtual: 0.010 PID: 0.007 assembly: 0.007 kernel: 0.005 register: 0.005 semantic: 0.004 device: 0.004 graphic: 0.003 VMM: 0.002 performance: 0.002 architecture: 0.001 network: 0.001 peripherals: 0.001 x86: 0.001 boot: 0.001 vnc: 0.001 socket: 0.001 mistranslation: 0.001 permissions: 0.001 risc-v: 0.000 KVM: 0.000 arm: 0.000 i386: 0.000 qemu-ppc (user) incorrectly converts float(nan)->double(non-nan) Noticed on qemu-3.1.0 on GHC test suite where float32 comparisons didn't work on NaNs. Here is the minimal reproducer: ```c // cat a.c #include #include #include int main() { volatile float f1 = NAN; volatile float f2 = NAN; printf ("f1 (%e, %#x) >= f2 (%e, %#x): %s\n", f1, *(volatile uint32_t*)&f1, f2, *(volatile uint32_t*)&f2, (f1 >= f2) ? "True" : "False"); volatile double d = f1; printf ("d (%e, %#llx)\n", d, *(volatile uint64_t*)&d); } ``` ``` # incorrect execution: $ powerpc-unknown-linux-gnu-gcc -O2 a.c -o a -static && qemu-ppc ./a f1 (5.104236e+38, 0x7fc00000) >= f2 (5.104236e+38, 0x7fc00000): True d (5.104236e+38, 0x47f8000000000000) # correct execution $ scp a timberdoodle.ppc64.dev.gentoo.org:~/; ssh timberdoodle.ppc64.dev.gentoo.org ./a f1 (nan, 0x7fc00000) >= f2 (nan, 0x7fc00000): False d (nan, 0x7ff8000000000000) ``` Note: qemu-ppc handled float32 extension as it was not a NaN (exp=111..1111) but a normalized number. The bug is in the same area as https://bugs.launchpad.net/qemu/+bug/1821444 but in another branch of 'uint64_t helper_todouble(uint32_t arg=0x1)'. We also hit this regression when testing CompCert for e5500 with qemu 3.1.0. The minimal example > #include > #include > > union C { float f; unsigned long l; }; > int main (void) { > union C c; > c.f = NAN; > printf("Float: %f\n Hex: 0x%x\n", c.f, c.l); > printf("The above float is %s NAN\n", c.f == NAN ? "==" : "!="); > return 0; > } does not exhibit the error with GCC 6.3.0, since that statically optimizes the c.f == NAN to always be false. But CompCert doesn't do this optimization and thus triggers the regression in the float compare. With qemu 3.0.0 the example outputs (whether built with compcert or gcc): > Float: nan > Hex: 0x7fc00000 > The above float is != NAN The example works well with qemu 3.0.0 and we stumbled over this with qemu 3.1.0; both build from the released source tarballs. My native system is a x86_64 GNU/Linux (openSUSE Tumbleweed with Kernel 4.20.13-1-default). Output with qemu 3.1.0 and built with GCC: > $ ./qemu-ppc64abi32-3.1.0 bug25310.gcc.elf > Float: 510423550381407695195061911147652317184.000000 > Hex: 0x7fc00000 > The above float is != NAN qemu 3.1.0 and example built with CompCert: > $ ./qemu-ppc64abi32-3.1.0 bug25310.ccomp.elf > Float: 510423550381407695195061911147652317184.000000 > Hex: 0x7fc00000 > The above float is == NAN I attached example binaries (statically built): > $ ../../compcert_internal_ppc/bin/ccomp --version > The CompCert C verified compiler, Release: 18.10i, Build: 4503984, Tag: auto/2019/02/11/1924 > $ ../../compcert_internal_ppc/bin/ccomp -target e5500-linux -g -static bug25310.c -o bug25310.ccomp.elf > > $ ../../compcert_internal_ppc/gcc/bin/powerpc-unknown-linux-gnu-gcc --version > powerpc-unknown-linux-gnu-gcc (crosstool-NG crosstool-ng-1.23.0) 6.3.0 > $ ../../compcert_internal_ppc/gcc/bin/powerpc-unknown-linux-gnu-gcc bug25310.c -g -static -O0 -o bug25310.gcc.elf -mcpu=e5500