From fa5d76b43e3129130deb12c1a184abce804e8382 Mon Sep 17 00:00:00 2001 From: Joel Dice Date: Mon, 13 Aug 2012 08:26:39 -0600 Subject: [PATCH] fix 64-bit shifts on x86_32 --- src/x86.cpp | 58 +++++++++++++++++++++++++++++++++++++--------- test/Integers.java | 19 +++++++++++++-- test/Longs.java | 30 ++++++++++++++++++++++++ 3 files changed, 94 insertions(+), 13 deletions(-) diff --git a/src/x86.cpp b/src/x86.cpp index f8ed8abd0a..06a492dcfd 100644 --- a/src/x86.cpp +++ b/src/x86.cpp @@ -2164,7 +2164,9 @@ doShift(Context* c, UNUSED void (*shift) c->client->save(rcx); Assembler::Register cx(rcx); - moveCR(c, 4, a, 4, &cx); + ResolvedPromise promise(v & 0x3F); + Assembler::Constant masked(&promise); + moveCR(c, 4, &masked, 4, &cx); shift(c, aSize, &cx, bSize, b); } else { maybeRex(c, bSize, b); @@ -2183,9 +2185,16 @@ void shiftLeftRR(Context* c, UNUSED unsigned aSize, Assembler::Register* a, unsigned bSize, Assembler::Register* b) { - assert(c, a->low == rcx); - if (TargetBytesPerWord == 4 and bSize == 8) { + if (a->low != rcx) { + c->client->save(rcx); + Assembler::Register cx(rcx); + ResolvedPromise promise(0x3F); + Assembler::Constant mask(&promise); + moveRR(c, 4, a, 4, &cx); + andCR(c, 4, &mask, 4, &cx); + } + // shld opcode(c, 0x0f, 0xa5); modrm(c, 0xc0, b->high, b->low); @@ -2204,6 +2213,8 @@ shiftLeftRR(Context* c, UNUSED unsigned aSize, Assembler::Register* a, moveRR(c, 4, b, 4, &bh); // 2 bytes xorRR(c, 4, b, 4, b); // 2 bytes } else { + assert(c, a->low == rcx); + maybeRex(c, bSize, a, b); opcode(c, 0xd3, 0xe0 + regCode(b)); } @@ -2220,8 +2231,16 @@ void shiftRightRR(Context* c, UNUSED unsigned aSize, Assembler::Register* a, unsigned bSize, Assembler::Register* b) { - assert(c, a->low == rcx); if (TargetBytesPerWord == 4 and bSize == 8) { + if (a->low != rcx) { + c->client->save(rcx); + Assembler::Register cx(rcx); + ResolvedPromise promise(0x3F); + Assembler::Constant mask(&promise); + moveRR(c, 4, a, 4, &cx); + andCR(c, 4, &mask, 4, &cx); + } + // shrd opcode(c, 0x0f, 0xad); modrm(c, 0xc0, b->low, b->high); @@ -2243,6 +2262,8 @@ shiftRightRR(Context* c, UNUSED unsigned aSize, Assembler::Register* a, opcode(c, 0xc1, 0xf8 + b->high); c->code.append(31); } else { + assert(c, a->low == rcx); + maybeRex(c, bSize, a, b); opcode(c, 0xd3, 0xf8 + regCode(b)); } @@ -2259,9 +2280,16 @@ void unsignedShiftRightRR(Context* c, UNUSED unsigned aSize, Assembler::Register* a, unsigned bSize, Assembler::Register* b) { - assert(c, a->low == rcx); - if (TargetBytesPerWord == 4 and bSize == 8) { + if (a->low != rcx) { + c->client->save(rcx); + Assembler::Register cx(rcx); + ResolvedPromise promise(0x3F); + Assembler::Constant mask(&promise); + moveRR(c, 4, a, 4, &cx); + andCR(c, 4, &mask, 4, &cx); + } + // shrd opcode(c, 0x0f, 0xad); modrm(c, 0xc0, b->low, b->high); @@ -2280,6 +2308,8 @@ unsignedShiftRightRR(Context* c, UNUSED unsigned aSize, Assembler::Register* a, moveRR(c, 4, &bh, 4, b); // 2 bytes xorRR(c, 4, &bh, 4, &bh); // 2 bytes } else { + assert(c, a->low == rcx); + maybeRex(c, bSize, a, b); opcode(c, 0xd3, 0xe8 + regCode(b)); } @@ -3232,7 +3262,7 @@ class MyArchitecture: public Assembler::Architecture { virtual void planSource (TernaryOperation op, unsigned aSize, uint8_t *aTypeMask, uint64_t *aRegisterMask, - unsigned, uint8_t* bTypeMask, uint64_t* bRegisterMask, + unsigned bSize, uint8_t* bTypeMask, uint64_t* bRegisterMask, unsigned, bool* thunk) { *aTypeMask = (1 << RegisterOperand) | (1 << ConstantOperand); @@ -3302,10 +3332,16 @@ class MyArchitecture: public Assembler::Architecture { case ShiftLeft: case ShiftRight: case UnsignedShiftRight: { - *aRegisterMask = (static_cast(GeneralRegisterMask) << 32) - | (static_cast(1) << rcx); - const uint32_t mask = GeneralRegisterMask & ~(1 << rcx); - *bRegisterMask = (static_cast(mask) << 32) | mask; + if (TargetBytesPerWord == 4 and bSize == 8) { + const uint32_t mask = GeneralRegisterMask & ~(1 << rcx); + *aRegisterMask = (static_cast(mask) << 32) | mask; + *bRegisterMask = (static_cast(mask) << 32) | mask; + } else { + *aRegisterMask = (static_cast(GeneralRegisterMask) << 32) + | (static_cast(1) << rcx); + const uint32_t mask = GeneralRegisterMask & ~(1 << rcx); + *bRegisterMask = (static_cast(mask) << 32) | mask; + } } break; case JumpIfFloatEqual: diff --git a/test/Integers.java b/test/Integers.java index 1420bb640d..bbaa710351 100644 --- a/test/Integers.java +++ b/test/Integers.java @@ -262,8 +262,8 @@ public class Integers { expect(bytesPerLine == 24); } - int y = -11760768; - expect((y + 0x8000) == (-11760768 + 0x8000)); + { int y = -11760768; + expect((y + 0x8000) == (-11760768 + 0x8000)); } expect(Math.min(796, 1069) == 796); @@ -299,5 +299,20 @@ public class Integers { { int b = 0xBE; expect(((b >>> 0) & 0xFF) == 0xBE); } + + { int b = 0xBE; int x = 0xFF; + expect((b & x) == 0xBE); } + + { int b = 0xBE; int x = 0; + expect((b >>> x) == 0xBE); } + + { int b = 0xBE; int x = 0; + expect((b >> x) == 0xBE); } + + { int b = 0xBE; int x = 0; + expect((b << x) == 0xBE); } + + { int b = 0xBE; int x = 0; int y = 0xFF; + expect(((b >>> x) & y) == 0xBE); } } } diff --git a/test/Longs.java b/test/Longs.java index a4c7e182ea..649ec6b2ff 100644 --- a/test/Longs.java +++ b/test/Longs.java @@ -355,6 +355,36 @@ public class Longs { { long b = 0x10000000000L; int s = -63; expect((b >> s) == 0x8000000000L); } + + { long b = 0xBEL; + expect((b & 0xFF) == 0xBEL); } + + { long b = 0xBEL; + expect((b >>> 0) == 0xBEL); } + + { long b = 0xBEL; + expect((b >> 0) == 0xBEL); } + + { long b = 0xBEL; + expect((b << 0) == 0xBEL); } + + { long b = 0xBEL; + expect(((b >>> 0) & 0xFF) == 0xBEL); } + + { long b = 0xBEL; int x = 0xFF; + expect((b & x) == 0xBEL); } + + { long b = 0xBEL; int x = 0; + expect((b >>> x) == 0xBEL); } + + { long b = 0xBEL; int x = 0; + expect((b >> x) == 0xBEL); } + + { long b = 0xBEL; int x = 0; + expect((b << x) == 0xBEL); } + + { long b = 0xBEL; int x = 0; int y = 0xFF; + expect(((b >>> x) & y) == 0xBEL); } } }