From 1d9489a76ea8085640fb1835aae709a912eb964c Mon Sep 17 00:00:00 2001 From: Joel Dice Date: Tue, 30 Nov 2010 16:58:51 -0700 Subject: [PATCH] fix a couple of 64-bit-op-on-32-bit-system bugs We weren't properly handling the case where a 64-bit value is multipled with itself in multiplyRR, leading to wrong code. Also, addCarryCR didn't know how to handle constants more than 8-bits wide. --- src/x86.cpp | 28 ++++++++++++++++++++++------ test/Longs.java | 17 +++++++++++++++++ 2 files changed, 39 insertions(+), 6 deletions(-) diff --git a/src/x86.cpp b/src/x86.cpp index 4e67576f1f..65ac67ce30 100644 --- a/src/x86.cpp +++ b/src/x86.cpp @@ -1403,17 +1403,18 @@ addRR(Context* c, unsigned aSize, Assembler::Register* a, } void -addCarryCR(Context* c, unsigned size UNUSED, Assembler::Constant* a, +addCarryCR(Context* c, unsigned size, Assembler::Constant* a, Assembler::Register* b) { int64_t v = a->value->value(); + maybeRex(c, size, b); if (isInt8(v)) { - maybeRex(c, size, b); opcode(c, 0x83, 0xd0 + regCode(b)); c->code.append(v); } else { - abort(c); + opcode(c, 0x81, 0xd0 + regCode(b)); + c->code.append4(v); } } @@ -1740,16 +1741,31 @@ multiplyRR(Context* c, unsigned aSize, Assembler::Register* a, Assembler::Register ah(a->high); Assembler::Register bh(b->high); + Assembler::Register tmp(-1); + Assembler::Register* scratch; + if (a->low == b->low) { + tmp.low = c->client->acquireTemporary + (GeneralRegisterMask & ~(1 << rax)); + scratch = &tmp; + moveRR(c, 4, b, 4, scratch); + } else { + scratch = b; + } + moveRR(c, 4, b, 4, &axdx); - multiplyRR(c, 4, &ah, 4, b); + multiplyRR(c, 4, &ah, 4, scratch); multiplyRR(c, 4, a, 4, &bh); - addRR(c, 4, &bh, 4, b); + addRR(c, 4, &bh, 4, scratch); // mul a->low,%eax%edx opcode(c, 0xf7, 0xe0 + a->low); - addRR(c, 4, b, 4, &bh); + addRR(c, 4, scratch, 4, &bh); moveRR(c, 4, &axdx, 4, b); + + if (tmp.low != -1) { + c->client->releaseTemporary(tmp.low); + } } else { maybeRex(c, aSize, b, a); opcode(c, 0x0f, 0xaf); diff --git a/test/Longs.java b/test/Longs.java index 7565b42121..8c34fddce9 100644 --- a/test/Longs.java +++ b/test/Longs.java @@ -243,6 +243,23 @@ public class Longs { expect(buffer.getLong() == 231); expect(unsignedShiftRight32(231) == 0); + + { int[] x = new int[] { 1701899151 }; + int[] z = new int[x.length * 2]; + final long LONG_MASK = 0xffffffffL; + + int lastProductLowWord = 0; + for (int j=0, i=0; j>> 33); + z[i++] = (int) (product >>> 1); + lastProductLowWord = (int) product; + } + + expect(z[0] == 337192406); + expect(z[1] == -437261072); + } } }