Merge "Load 64 bit constant into GPR by single instruction for 64bit mode"
diff --git a/compiler/dex/quick/x86/assemble_x86.cc b/compiler/dex/quick/x86/assemble_x86.cc
index a491873..737b8b9 100644
--- a/compiler/dex/quick/x86/assemble_x86.cc
+++ b/compiler/dex/quick/x86/assemble_x86.cc
@@ -208,7 +208,8 @@
{ kX86Mov64RM, kRegMem, IS_LOAD | IS_TERTIARY_OP | REG_DEF0_USE1, { REX_W, 0, 0x8B, 0, 0, 0, 0, 0, false }, "Mov64RM", "!0r,[!1r+!2d]" },
{ kX86Mov64RA, kRegArray, IS_LOAD | IS_QUIN_OP | REG_DEF0_USE12, { REX_W, 0, 0x8B, 0, 0, 0, 0, 0, false }, "Mov64RA", "!0r,[!1r+!2r<<!3d+!4d]" },
{ kX86Mov64RT, kRegThread, IS_LOAD | IS_BINARY_OP | REG_DEF0, { THREAD_PREFIX, REX_W, 0x8B, 0, 0, 0, 0, 0, false }, "Mov64RT", "!0r,fs:[!1d]" },
- { kX86Mov64RI, kMovRegImm, IS_BINARY_OP | REG_DEF0, { REX_W, 0, 0xB8, 0, 0, 0, 0, 8, false }, "Mov64RI", "!0r,!1d" },
+ { kX86Mov64RI32, kRegImm, IS_BINARY_OP | REG_DEF0, { REX_W, 0, 0xC7, 0, 0, 0, 0, 4, false }, "Mov64RI32", "!0r,!1d" },
+ { kX86Mov64RI64, kMovRegQuadImm, IS_TERTIARY_OP | REG_DEF0, { REX_W, 0, 0xB8, 0, 0, 0, 0, 8, false }, "Mov64RI64", "!0r,!1q" },
{ kX86Mov64MI, kMemImm, IS_STORE | IS_TERTIARY_OP | REG_USE0, { REX_W, 0, 0xC7, 0, 0, 0, 0, 4, false }, "Mov64MI", "[!0r+!1d],!2d" },
{ kX86Mov64AI, kArrayImm, IS_STORE | IS_QUIN_OP | REG_USE01, { REX_W, 0, 0xC7, 0, 0, 0, 0, 4, false }, "Mov64AI", "[!0r+!1r<<!2d+!3d],!4d" },
{ kX86Mov64TI, kThreadImm, IS_STORE | IS_BINARY_OP, { THREAD_PREFIX, REX_W, 0xC7, 0, 0, 0, 0, 4, false }, "Mov64TI", "fs:[!0d],!1d" },
@@ -723,6 +724,7 @@
return ComputeSize(entry, lir->operands[0], lir->operands[2], lir->operands[1],
lir->operands[4]);
case kMovRegImm: // lir operands - 0: reg, 1: immediate
+ case kMovRegQuadImm:
return ((entry->skeleton.prefix1 != 0 || NeedsRex(lir->operands[0])) ? 1 : 0) + 1 +
entry->skeleton.immediate_bytes;
case kShiftRegImm: // lir operands - 0: reg, 1: immediate
@@ -1787,6 +1789,12 @@
case kMovRegImm: // lir operands - 0: reg, 1: immediate
EmitMovRegImm(entry, lir->operands[0], lir->operands[1]);
break;
+ case kMovRegQuadImm: {
+ int64_t value = static_cast<int64_t>(static_cast<int64_t>(lir->operands[1]) << 32 |
+ static_cast<uint32_t>(lir->operands[2]));
+ EmitMovRegImm(entry, lir->operands[0], value);
+ }
+ break;
case kShiftRegImm: // lir operands - 0: reg, 1: immediate
EmitShiftRegImm(entry, lir->operands[0], lir->operands[1]);
break;
diff --git a/compiler/dex/quick/x86/target_x86.cc b/compiler/dex/quick/x86/target_x86.cc
index 72b2cea..730a271 100644
--- a/compiler/dex/quick/x86/target_x86.cc
+++ b/compiler/dex/quick/x86/target_x86.cc
@@ -331,6 +331,11 @@
case 'd':
buf += StringPrintf("%d", operand);
break;
+ case 'q': {
+ int64_t value = static_cast<int64_t>(static_cast<int64_t>(operand) << 32 |
+ static_cast<uint32_t>(lir->operands[operand_number+1]));
+ buf +=StringPrintf("%" PRId64, value);
+ }
case 'p': {
EmbeddedData *tab_rec = reinterpret_cast<EmbeddedData*>(UnwrapPointer(operand));
buf += StringPrintf("0x%08x", tab_rec->offset);
diff --git a/compiler/dex/quick/x86/utility_x86.cc b/compiler/dex/quick/x86/utility_x86.cc
index d835b22..4770ade 100644
--- a/compiler/dex/quick/x86/utility_x86.cc
+++ b/compiler/dex/quick/x86/utility_x86.cc
@@ -608,18 +608,12 @@
res = LoadConstantNoClobber(r_dest.GetLow(), val_lo);
LoadConstantNoClobber(r_dest.GetHigh(), val_hi);
} else {
- // TODO(64) make int64_t value parameter of LoadConstantNoClobber
- if (val_lo < 0) {
- val_hi += 1;
- }
- if (val_hi != 0) {
- res = LoadConstantNoClobber(RegStorage::Solo32(r_dest.GetReg()), val_hi);
- NewLIR2(kX86Sal64RI, r_dest.GetReg(), 32);
- } else {
+ if (value == 0) {
res = NewLIR2(kX86Xor64RR, r_dest.GetReg(), r_dest.GetReg());
- }
- if (val_lo != 0) {
- NewLIR2(kX86Add64RI, r_dest.GetReg(), val_lo);
+ } else if (value >= INT_MIN && value <= INT_MAX) {
+ res = NewLIR2(kX86Mov64RI32, r_dest.GetReg(), val_lo);
+ } else {
+ res = NewLIR3(kX86Mov64RI64, r_dest.GetReg(), val_hi, val_lo);
}
}
}
diff --git a/compiler/dex/quick/x86/x86_lir.h b/compiler/dex/quick/x86/x86_lir.h
index 17c44bc..7ff4f72 100644
--- a/compiler/dex/quick/x86/x86_lir.h
+++ b/compiler/dex/quick/x86/x86_lir.h
@@ -439,7 +439,7 @@
kX86Lea32RA,
kX86Mov64MR, kX86Mov64AR, kX86Mov64TR,
kX86Mov64RR, kX86Mov64RM, kX86Mov64RA, kX86Mov64RT,
- kX86Mov64RI, kX86Mov64MI, kX86Mov64AI, kX86Mov64TI,
+ kX86Mov64RI32, kX86Mov64RI64, kX86Mov64MI, kX86Mov64AI, kX86Mov64TI,
kX86Lea64RM,
kX86Lea64RA,
// RRC - Register Register ConditionCode - cond_opcode reg1, reg2
@@ -649,6 +649,7 @@
kRegImm, kMemImm, kArrayImm, kThreadImm, // RI, MI, AI and TI instruction kinds.
kRegRegImm, kRegMemImm, kRegArrayImm, // RRI, RMI and RAI instruction kinds.
kMovRegImm, // Shorter form move RI.
+ kMovRegQuadImm, // 64 bit move RI
kRegRegImmStore, // RRI following the store modrm reg-reg encoding rather than the load.
kMemRegImm, // MRI instruction kinds.
kShiftRegImm, kShiftMemImm, kShiftArrayImm, // Shift opcode with immediate.
diff --git a/disassembler/disassembler_x86.cc b/disassembler/disassembler_x86.cc
index 1d8cf9b..1021789 100644
--- a/disassembler/disassembler_x86.cc
+++ b/disassembler/disassembler_x86.cc
@@ -21,6 +21,7 @@
#include "base/logging.h"
#include "base/stringprintf.h"
#include "thread.h"
+#include <inttypes.h>
namespace art {
namespace x86 {
@@ -914,6 +915,12 @@
reg_in_opcode = true;
break;
case 0xB8: case 0xB9: case 0xBA: case 0xBB: case 0xBC: case 0xBD: case 0xBE: case 0xBF:
+ if (rex == 0x48) {
+ opcode << "movabsq";
+ immediate_bytes = 8;
+ reg_in_opcode = true;
+ break;
+ }
opcode << "mov";
immediate_bytes = 4;
reg_in_opcode = true;
@@ -1144,8 +1151,7 @@
if (immediate_bytes == 1) {
args << StringPrintf("%d", *reinterpret_cast<const int8_t*>(instr));
instr++;
- } else {
- CHECK_EQ(immediate_bytes, 4u);
+ } else if (immediate_bytes == 4) {
if (prefix[2] == 0x66) { // Operand size override from 32-bit to 16-bit.
args << StringPrintf("%d", *reinterpret_cast<const int16_t*>(instr));
instr += 2;
@@ -1153,6 +1159,10 @@
args << StringPrintf("%d", *reinterpret_cast<const int32_t*>(instr));
instr += 4;
}
+ } else {
+ CHECK_EQ(immediate_bytes, 8u);
+ args << StringPrintf("%" PRId64, *reinterpret_cast<const int64_t*>(instr));
+ instr += 8;
}
} else if (branch_bytes > 0) {
DCHECK(!has_modrm);