On 13/12/2014 23:10, Torbjörn Granlund wrote: > I wrote: > > The s390 instruction emulation makes GMP fail most of its tests. > I have isolated one of the problems: > > How to reproduce: > > gcc m.c x.s > ./a.out > > Correct output on actual hardware: > ffffffff > > Incorrect output using QEMU 2.2.0 rc4: > 0 > > File m.c: > #include <stdio.h> > int foo(); > int main() { printf("%x\n", foo()); return 0; } > > File x.s: > .text > .align 8 > .globl foo > .type foo,@function > foo: lghi %r2, 0 > lghi %r3, 1 > slgr %r2, %r3 > slbgr %r3, %r3 > slbgr %r2, %r2 > br %r14 > > Turns out that all failures except 3 are due to subb borrow handling > code which (almost) never works when there is borrow-in. A minimal fix > is quite simple: > > *** /home/tege/qemu/qemu-2.2.0/target-s390x/.~/cc_helper.c.~1~ Tue Dec > 9 15:45:44 2014 > --- /home/tege/qemu/qemu-2.2.0/target-s390x/cc_helper.c Sat Dec 13 > 22:47:11 2014 > *************** > *** 182,184 **** > /* We had borrow-in if normal subtraction isn't equal. */ > ! int borrow_in = ar - (a1 - a2); > int borrow_out; > --- 182,184 ---- > /* We had borrow-in if normal subtraction isn't equal. */ > ! int borrow_in = (a1 - a2) - ar; > int borrow_out; > > There is at least one more instruction emulation error which I have not > yet isolated [two test failures]. And then EX is not implemented for > logical operations [one test failure]. > > This latter problem is adequately reported by qemu: > qemu: fatal: EXECUTE on instruction prefix 0xd400 not implemented > qemu: fatal: EXECUTE on instruction prefix 0xd600 not implemented
Something like this? diff --git a/target-s390x/mem_helper.c b/target-s390x/mem_helper.c index 5a55de8..4de3fc2 100644 --- a/target-s390x/mem_helper.c +++ b/target-s390x/mem_helper.c @@ -490,10 +490,18 @@ uint32_t HELPER(ex)(CPUS390XState *env, uint32_t cc, uint64_t v1, helper_mvc(env, l, get_address(env, 0, b1, d1), get_address(env, 0, b2, d2)); break; + case 0x400: + cc = helper_nc(env, l, get_address(env, 0, b1, d1), + get_address(env, 0, b2, d2)); + break; case 0x500: cc = helper_clc(env, l, get_address(env, 0, b1, d1), get_address(env, 0, b2, d2)); break; + case 0x600: + cc = helper_oc(env, l, get_address(env, 0, b1, d1), + get_address(env, 0, b2, d2)); + break; case 0x700: cc = helper_xc(env, l, get_address(env, 0, b1, d1), get_address(env, 0, b2, d2)); Paolo