aboutsummaryrefslogtreecommitdiff
path: root/target-s390x/cc_helper.c
diff options
context:
space:
mode:
authorTorbjorn Granlund <torbjorng@google.com>2015-01-08 18:01:09 +0100
committerRichard Henderson <rth@twiddle.net>2015-02-03 12:27:05 -0800
commit9ef1473693a1400a903567489d3122fc9511765d (patch)
tree57aa8c3e98c7ad5e93e14d89447c8925561b5bfb /target-s390x/cc_helper.c
parent8cf02f93dc37bc3de30dfb74eb0e904d1700dbf6 (diff)
target-s390x: fix and optimize slb* and slbg* computation of carry/borrow flag
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.) Signed-off-by: Torbjorn Granlund <torbjorng@google.com> Signed-off-by: Paolo Bonzini <pbonzini@redhat.com> Signed-off-by: Richard Henderson <rth@twiddle.net>
Diffstat (limited to 'target-s390x/cc_helper.c')
-rw-r--r--target-s390x/cc_helper.c18
1 files changed, 4 insertions, 14 deletions
diff --git a/target-s390x/cc_helper.c b/target-s390x/cc_helper.c
index 373eb176a1..00bc883a8a 100644
--- a/target-s390x/cc_helper.c
+++ b/target-s390x/cc_helper.c
@@ -179,16 +179,11 @@ static uint32_t cc_calc_subu_64(uint64_t a1, uint64_t a2, uint64_t ar)
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_subu_32(uint32_t a1, uint32_t a2, uint32_t ar)
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);
}