* [Qemu-devel] Bug in s390 instruction emulation
@ 2014-12-03 21:16 Torbjörn Granlund
2014-12-13 22:10 ` Torbjörn Granlund
0 siblings, 1 reply; 4+ messages in thread
From: Torbjörn Granlund @ 2014-12-03 21:16 UTC (permalink / raw)
To: qemu-devel
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
(This is using "user mode" emulation. System mode emulation doesn't
work at all, and never did, as I am sure you know. I suppose getting
basic instruction emulation correct is a good first step.)
--
Torbjörn
Please encrypt, key id 0xC8601622
^ permalink raw reply [flat|nested] 4+ messages in thread
* Re: [Qemu-devel] Bug in s390 instruction emulation
2014-12-03 21:16 [Qemu-devel] Bug in s390 instruction emulation Torbjörn Granlund
@ 2014-12-13 22:10 ` Torbjörn Granlund
2014-12-14 21:45 ` Paolo Bonzini
0 siblings, 1 reply; 4+ messages in thread
From: Torbjörn Granlund @ 2014-12-13 22:10 UTC (permalink / raw)
To: qemu-devel
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
(I will not follow up in any way about this bug. If you choose to
ignore the bug report, then qemu will remain slightly buggier. If you
choose to deal with the bug in a reasonably timely manner, I'd be happy
to contribute.)
Torbjörn
Please encrypt, key id 0xC8601622
^ permalink raw reply [flat|nested] 4+ messages in thread
* Re: [Qemu-devel] Bug in s390 instruction emulation
2014-12-13 22:10 ` Torbjörn Granlund
@ 2014-12-14 21:45 ` Paolo Bonzini
2014-12-15 23:44 ` Torbjörn Granlund
0 siblings, 1 reply; 4+ messages in thread
From: Paolo Bonzini @ 2014-12-14 21:45 UTC (permalink / raw)
To: Torbjörn Granlund, qemu-devel
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
^ permalink raw reply related [flat|nested] 4+ messages in thread
* Re: [Qemu-devel] Bug in s390 instruction emulation
2014-12-14 21:45 ` Paolo Bonzini
@ 2014-12-15 23:44 ` Torbjörn Granlund
0 siblings, 0 replies; 4+ messages in thread
From: Torbjörn Granlund @ 2014-12-15 23:44 UTC (permalink / raw)
To: Paolo Bonzini; +Cc: qemu-devel
Paolo Bonzini <pbonzini@redhat.com> writes:
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));
That seems to work as per the needs of GMP. I had expected a bigger
change to be needed. Thanks!
Below is a more complete patch for the SLB* and SLBG* bugs.
This patch is to be attributed to torbjorng@google.com.
This patch fixes the bug with borrow_in being set incorrectly, but it
also simplifies the logic to be much more plain, improving speed. It
fixes both the 32-bit SLB* and 64-bit SLBG*.
The SLBG* change has been well-tested. I haven't tested the SLB* change
explicitly, but the code was copy-pasted from the tested code.
The error of these functions' current implementations would not likely
be triggered by compiler-generated code, since the only error was in the
state of the carry/borrow flag. Compilers rarely generate an
instruction sequence such as carry-set -> carry-set-and-use ->
carry-use.
(With Paolo's fix and mine, there are still a couple of failures from
GMP's testsuite, but they are almost surely due to incorrect code
generation from gcc 4.9. But since this gcc is running under qemu, it
might be qemu bugs. I intend to investigate this.)
--- target-s390x/.~/cc_helper.c.~1~ 2014-12-09 15:45:44.000000000 +0100
+++ target-s390x/cc_helper.c 2014-12-14 23:02:31.605725763 +0100
@@ -179,16 +179,11 @@
static uint32_t cc_calc_subb_64(uint64_t a1, uint64_t a2, uint64_t ar)
{
- /* We had borrow-in if normal subtraction isn't equal. */
- int borrow_in = ar - (a1 - a2);
int borrow_out;
- /* If a2 was ULONG_MAX, and borrow_in, then a2 is logically 65 bits,
- and we must have had borrow out. */
- if (borrow_in && a2 == (uint64_t)-1) {
- borrow_out = 1;
+ if (ar != a1 - a2) { /* difference means borrow-in */
+ borrow_out = (a2 >= a1);
} else {
- a2 += borrow_in;
borrow_out = (a2 > a1);
}
@@ -285,16 +280,11 @@
static uint32_t cc_calc_subb_32(uint32_t a1, uint32_t a2, uint32_t ar)
{
- /* We had borrow-in if normal subtraction isn't equal. */
- int borrow_in = ar - (a1 - a2);
int borrow_out;
- /* If a2 was UINT_MAX, and borrow_in, then a2 is logically 65 bits,
- and we must have had borrow out. */
- if (borrow_in && a2 == (uint32_t)-1) {
- borrow_out = 1;
+ if (ar != a1 - a2) { /* difference means borrow-in */
+ borrow_out = (a2 >= a1);
} else {
- a2 += borrow_in;
borrow_out = (a2 > a1);
}
--
Torbjörn
Please encrypt, key id 0xC8601622
^ permalink raw reply [flat|nested] 4+ messages in thread
end of thread, other threads:[~2014-12-15 23:45 UTC | newest]
Thread overview: 4+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2014-12-03 21:16 [Qemu-devel] Bug in s390 instruction emulation Torbjörn Granlund
2014-12-13 22:10 ` Torbjörn Granlund
2014-12-14 21:45 ` Paolo Bonzini
2014-12-15 23:44 ` Torbjörn Granlund
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).