graphic: 0.958 user-level: 0.952 semantic: 0.948 performance: 0.944 architecture: 0.942 assembly: 0.942 debug: 0.942 permissions: 0.941 risc-v: 0.940 hypervisor: 0.938 ppc: 0.936 vnc: 0.935 arm: 0.932 virtual: 0.931 PID: 0.930 files: 0.918 device: 0.916 mistranslation: 0.915 VMM: 0.913 TCG: 0.912 KVM: 0.909 socket: 0.900 kernel: 0.889 register: 0.889 peripherals: 0.888 boot: 0.861 x86: 0.860 network: 0.826 i386: 0.769 overflow condition code determined incorrectly after addition on s390x Description of problem: The following program foo.c [foo.c](/uploads/78f5f799af6e3c400a6a42634f3f0e63/foo.c) ``` #include int overflow_32 (int x, int y) { int sum; return ! __builtin_add_overflow (x, y, &sum); } int overflow_64 (long long x, long long y) { long sum; return ! __builtin_add_overflow (x, y, &sum); } int a1 = -2147483648; int b1 = -2147483648; long long a2 = -9223372036854775808L; long long b2 = -9223372036854775808L; int main () { { int a = a1; int b = b1; printf ("a = 0x%x, b = 0x%x\n", a, b); printf ("no_overflow = %d\n", overflow_32 (a, b)); } { long long a = a2; long long b = b2; printf ("a = 0x%llx, b = 0x%llx\n", a, b); printf ("no_overflow = %d\n", overflow_64 (a, b)); } } ``` should print ``` a = 0x80000000, b = 0x80000000 no_overflow = 0 a = 0x8000000000000000, b = 0x8000000000000000 no_overflow = 0 ``` However, when compiled as an s390x program and executed through qemu 6.1.0 (Linux user-mode), it prints 'no_overflow = 1' twice. ``` $ s390x-linux-gnu-gcc-10 --version s390x-linux-gnu-gcc-10 (Ubuntu 10.3.0-1ubuntu1~20.04) 10.3.0 ``` ``` $ s390x-linux-gnu-gcc-10 -static foo.c $ ~/inst-qemu/6.1.0/bin/qemu-s390x a.out a = 0x80000000, b = 0x80000000 no_overflow = 1 a = 0x8000000000000000, b = 0x8000000000000000 no_overflow = 1 ``` ``` $ s390x-linux-gnu-gcc-10 -O2 -static foo.c $ ~/inst-qemu/6.1.0/bin/qemu-s390x a.out a = 0x80000000, b = 0x80000000 no_overflow = 1 a = 0x8000000000000000, b = 0x8000000000000000 no_overflow = 1 ``` The code generated by 's390x-linux-gnu-gcc-10 -O2' makes use of the 'o' (overflow / ones) condition code: ``` overflow_64: lgr %r1,%r2 ;; copy a into %r1 lghi %r2,0 agr %r1,%r3 ;; add a and b bnor %r14 ;; if no overflow, return %r2 = 0 lghi %r2,1 br %r14 ;; otherwise, return %r2 = 1 ``` Either the bug is in GCC, that is, GCC produces code that uses the CPU's overflow condition code when it shouldn't. Or the bug is in QEMU, that is, QEMU does not set the overflow condition code correctly. This can be decided by running the above program on real Linux/s390x hardware (to which I don't have access). Steps to reproduce: [foo.static.s390x](/uploads/ac41abf4c54baf9ca96ba82d75a24ad6/foo.static.s390x) (foo.static.s390x is attached, the result of "s390x-linux-gnu-gcc-10 -static -O2 foo.c -o foo.static.s390x") 1. `qemu-s390x foo.static.s390x` Additional information: If the bug is really in QEMU, the attached patch fixes it. [0001-s390x-Fix-determination-of-overflow-condition-code-a.patch](/uploads/552917079ccd25f1861d682fc9dee3e8/0001-s390x-Fix-determination-of-overflow-condition-code-a.patch)