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);