diff options
author | Serguei Katkov <serguei.i.katkov@intel.com> | 2014-06-23 13:23:38 +0700 |
---|---|---|
committer | Serguei Katkov <serguei.i.katkov@intel.com> | 2014-06-24 00:40:03 +0700 |
commit | 1c55703526827b5fc63f5d4b8477f36574649342 (patch) | |
tree | c71dacfb709787b57fba2ce117fb8ba120d7b150 | |
parent | be781e55b86ddd2dacf12b80a26fa9a5612948c3 (diff) | |
download | art-1c55703526827b5fc63f5d4b8477f36574649342.tar.gz art-1c55703526827b5fc63f5d4b8477f36574649342.tar.bz2 art-1c55703526827b5fc63f5d4b8477f36574649342.zip |
x86_64: Correct fix for cmp-long
We cannot rely on the sign of the sub instruction because
LONG_MAX - LONG_MIN = -1 and the sign will indicate that
LONG_MAX < KONG_MIN and it is incorrect.
The fix also contains small improvement for load wide constant.
Change-Id: I74df70d7c198cebff5cad8c1d5614c1d29b79a1b
Signed-off-by: Serguei Katkov <serguei.i.katkov@intel.com>
-rw-r--r-- | compiler/dex/quick/x86/assemble_x86.cc | 17 | ||||
-rw-r--r-- | compiler/dex/quick/x86/int_x86.cc | 15 | ||||
-rw-r--r-- | compiler/dex/quick/x86/utility_x86.cc | 8 | ||||
-rw-r--r-- | compiler/dex/quick/x86/x86_lir.h | 6 |
4 files changed, 33 insertions, 13 deletions
diff --git a/compiler/dex/quick/x86/assemble_x86.cc b/compiler/dex/quick/x86/assemble_x86.cc index 3f54798b7e..f06f08ee52 100644 --- a/compiler/dex/quick/x86/assemble_x86.cc +++ b/compiler/dex/quick/x86/assemble_x86.cc @@ -325,11 +325,21 @@ ENCODING_MAP(Cmp, IS_LOAD, 0, 0, { kX86 ## opname ## RM, kRegMem, IS_LOAD | IS_TERTIARY_OP | reg_def | REG_USE1, { prefix, 0, 0x0F, opcode, 0, 0, 0, 0, false }, #opname "RM", "!0r,[!1r+!2d]" }, \ { kX86 ## opname ## RA, kRegArray, IS_LOAD | IS_QUIN_OP | reg_def | REG_USE12, { prefix, 0, 0x0F, opcode, 0, 0, 0, 0, false }, #opname "RA", "!0r,[!1r+!2r<<!3d+!4d]" } +#define EXT_0F_REX_NO_PREFIX_ENCODING_MAP(opname, opcode, reg_def) \ +{ kX86 ## opname ## RR, kRegReg, IS_BINARY_OP | reg_def | REG_USE1, { REX, 0x00, 0x0F, opcode, 0, 0, 0, 0, false }, #opname "RR", "!0r,!1r" }, \ +{ kX86 ## opname ## RM, kRegMem, IS_LOAD | IS_TERTIARY_OP | reg_def | REG_USE1, { REX, 0x00, 0x0F, opcode, 0, 0, 0, 0, false }, #opname "RM", "!0r,[!1r+!2d]" }, \ +{ kX86 ## opname ## RA, kRegArray, IS_LOAD | IS_QUIN_OP | reg_def | REG_USE12, { REX, 0x00, 0x0F, opcode, 0, 0, 0, 0, false }, #opname "RA", "!0r,[!1r+!2r<<!3d+!4d]" } + #define EXT_0F_REX_W_ENCODING_MAP(opname, prefix, opcode, reg_def) \ { kX86 ## opname ## RR, kRegReg, IS_BINARY_OP | reg_def | REG_USE1, { prefix, REX_W, 0x0F, opcode, 0, 0, 0, 0, false }, #opname "RR", "!0r,!1r" }, \ { kX86 ## opname ## RM, kRegMem, IS_LOAD | IS_TERTIARY_OP | reg_def | REG_USE1, { prefix, REX_W, 0x0F, opcode, 0, 0, 0, 0, false }, #opname "RM", "!0r,[!1r+!2d]" }, \ { kX86 ## opname ## RA, kRegArray, IS_LOAD | IS_QUIN_OP | reg_def | REG_USE12, { prefix, REX_W, 0x0F, opcode, 0, 0, 0, 0, false }, #opname "RA", "!0r,[!1r+!2r<<!3d+!4d]" } +#define EXT_0F_REX_W_NO_PREFIX_ENCODING_MAP(opname, opcode, reg_def) \ +{ kX86 ## opname ## RR, kRegReg, IS_BINARY_OP | reg_def | REG_USE1, { REX_W, 0x00, 0x0F, opcode, 0, 0, 0, 0, false }, #opname "RR", "!0r,!1r" }, \ +{ kX86 ## opname ## RM, kRegMem, IS_LOAD | IS_TERTIARY_OP | reg_def | REG_USE1, { REX_W, 0x00, 0x0F, opcode, 0, 0, 0, 0, false }, #opname "RM", "!0r,[!1r+!2d]" }, \ +{ kX86 ## opname ## RA, kRegArray, IS_LOAD | IS_QUIN_OP | reg_def | REG_USE12, { REX_W, 0x00, 0x0F, opcode, 0, 0, 0, 0, false }, #opname "RA", "!0r,[!1r+!2r<<!3d+!4d]" } + #define EXT_0F_ENCODING2_MAP(opname, prefix, opcode, opcode2, reg_def) \ { kX86 ## opname ## RR, kRegReg, IS_BINARY_OP | reg_def | REG_USE1, { prefix, 0, 0x0F, opcode, opcode2, 0, 0, 0, false }, #opname "RR", "!0r,!1r" }, \ { kX86 ## opname ## RM, kRegMem, IS_LOAD | IS_TERTIARY_OP | reg_def | REG_USE1, { prefix, 0, 0x0F, opcode, opcode2, 0, 0, 0, false }, #opname "RM", "!0r,[!1r+!2d]" }, \ @@ -481,6 +491,10 @@ ENCODING_MAP(Cmp, IS_LOAD, 0, 0, EXT_0F_ENCODING_MAP(Movzx16, 0x00, 0xB7, REG_DEF0), EXT_0F_ENCODING_MAP(Movsx8, 0x00, 0xBE, REG_DEF0), EXT_0F_ENCODING_MAP(Movsx16, 0x00, 0xBF, REG_DEF0), + EXT_0F_REX_NO_PREFIX_ENCODING_MAP(Movzx8q, 0xB6, REG_DEF0), + EXT_0F_REX_W_NO_PREFIX_ENCODING_MAP(Movzx16q, 0xB7, REG_DEF0), + EXT_0F_REX_NO_PREFIX_ENCODING_MAP(Movsx8q, 0xBE, REG_DEF0), + EXT_0F_REX_W_NO_PREFIX_ENCODING_MAP(Movsx16q, 0xBF, REG_DEF0), #undef EXT_0F_ENCODING_MAP { kX86Jcc8, kJcc, IS_BINARY_OP | IS_BRANCH | NEEDS_FIXUP | USES_CCODES, { 0, 0, 0x70, 0, 0, 0, 0, 0, false }, "Jcc8", "!1c !0t" }, @@ -827,7 +841,8 @@ void X86Mir2Lir::CheckValidByteRegister(const X86EncodingMap* entry, int32_t raw CHECK(strchr(entry->name, '8') != nullptr) << entry->name; } else { if (entry->skeleton.immediate_bytes != 1) { // Ignore ...I8 instructions. - if (!StartsWith(entry->name, "Movzx8") && !StartsWith(entry->name, "Movsx8")) { + if (!StartsWith(entry->name, "Movzx8") && !StartsWith(entry->name, "Movsx8") + && !StartsWith(entry->name, "Movzx8q") && !StartsWith(entry->name, "Movsx8q")) { CHECK(strchr(entry->name, '8') == nullptr) << entry->name; } } diff --git a/compiler/dex/quick/x86/int_x86.cc b/compiler/dex/quick/x86/int_x86.cc index 48fcd2c23a..2f914c1e39 100644 --- a/compiler/dex/quick/x86/int_x86.cc +++ b/compiler/dex/quick/x86/int_x86.cc @@ -35,17 +35,12 @@ void X86Mir2Lir::GenCmpLong(RegLocation rl_dest, RegLocation rl_src1, rl_src1 = LoadValueWide(rl_src1, kCoreReg); rl_src2 = LoadValueWide(rl_src2, kCoreReg); RegLocation rl_result = EvalLoc(rl_dest, kCoreReg, true); - RegStorage rl_result_wide = RegStorage::Solo64(rl_result.reg.GetRegNum()); RegStorage temp_reg = AllocTemp(); - OpRegReg(kOpXor, temp_reg, temp_reg); // temp = 0 - OpRegRegReg(kOpSub, rl_result_wide, rl_src1.reg, rl_src2.reg); - NewLIR2(kX86Set8R, temp_reg.GetReg(), kX86CondG); // temp = (src1 > src2) ? 1 : temp - - NewLIR2(kX86Rol64RI, rl_result_wide.GetReg(), 1); - OpRegImm(kOpAnd, rl_result.reg, 1); - OpRegReg(kOpNeg, rl_result.reg, rl_result.reg); - // result = (src1 < src2) ? -1 : 0; - OpRegReg(kOpAdd, rl_result.reg, temp_reg); + OpRegReg(kOpCmp, rl_src1.reg, rl_src2.reg); + NewLIR2(kX86Set8R, rl_result.reg.GetReg(), kX86CondG); // result = (src1 > src2) ? 1 : 0 + NewLIR2(kX86Set8R, temp_reg.GetReg(), kX86CondL); // temp = (src1 >= src2) ? 0 : 1 + NewLIR2(kX86Sub8RR, rl_result.reg.GetReg(), temp_reg.GetReg()); + NewLIR2(kX86Movsx8qRR, rl_result.reg.GetReg(), rl_result.reg.GetReg()); StoreValue(rl_dest, rl_result); FreeTemp(temp_reg); diff --git a/compiler/dex/quick/x86/utility_x86.cc b/compiler/dex/quick/x86/utility_x86.cc index 46e877f8f9..ac5162e376 100644 --- a/compiler/dex/quick/x86/utility_x86.cc +++ b/compiler/dex/quick/x86/utility_x86.cc @@ -611,8 +611,12 @@ LIR* X86Mir2Lir::LoadConstantWide(RegStorage r_dest, int64_t value) { if (val_lo < 0) { val_hi += 1; } - res = LoadConstantNoClobber(RegStorage::Solo32(r_dest.GetReg()), val_hi); - NewLIR2(kX86Sal64RI, r_dest.GetReg(), 32); + if (val_hi != 0) { + res = LoadConstantNoClobber(RegStorage::Solo32(r_dest.GetReg()), val_hi); + NewLIR2(kX86Sal64RI, r_dest.GetReg(), 32); + } else { + res = NewLIR2(kX86Xor64RR, r_dest.GetReg(), r_dest.GetReg()); + } if (val_lo != 0) { NewLIR2(kX86Add64RI, r_dest.GetReg(), val_lo); } diff --git a/compiler/dex/quick/x86/x86_lir.h b/compiler/dex/quick/x86/x86_lir.h index 28b9dca193..17c44bc2c7 100644 --- a/compiler/dex/quick/x86/x86_lir.h +++ b/compiler/dex/quick/x86/x86_lir.h @@ -609,6 +609,10 @@ enum X86OpCode { Binary0fOpCode(kX86Movzx16), // zero-extend 16-bit value Binary0fOpCode(kX86Movsx8), // sign-extend 8-bit value Binary0fOpCode(kX86Movsx16), // sign-extend 16-bit value + Binary0fOpCode(kX86Movzx8q), // zero-extend 8-bit value to quad word + Binary0fOpCode(kX86Movzx16q), // zero-extend 16-bit value to quad word + Binary0fOpCode(kX86Movsx8q), // sign-extend 8-bit value to quad word + Binary0fOpCode(kX86Movsx16q), // sign-extend 16-bit value to quad word #undef Binary0fOpCode kX86Jcc8, kX86Jcc32, // jCC rel8/32; lir operands - 0: rel, 1: CC, target assigned kX86Jmp8, kX86Jmp32, // jmp rel8/32; lir operands - 0: rel, target assigned @@ -707,6 +711,8 @@ struct X86EncodingMap { #define REX_X 0x42 // Extension of the ModR/M r/m field, SIB base field, or Opcode reg field #define REX_B 0x41 +// Extended register set +#define REX 0x40 // Mask extracting the least 3 bits of r0..r15 #define kRegNumMask32 0x07 // Value indicating that base or reg is not used |