Update load/store utilities for 64-bit backends

This CL replaces the typical use of LoadWord/StoreWord
utilities (which, in practice, were 32-bit load/store) in
favor of a new set that make the size explicit.  We now have:

   LoadWordDisp/StoreWordDisp:
    32 or 64 depending on target.  Load or store the natural
    word size.  Expect this to be used infrequently - generally
    when we know we're dealing with a native pointer or flushed
    register not holding a Dalvik value (Dalvik values will flush
    to home location sizes based on Dalvik, rather than the target).

   Load32Disp/Store32Disp:
     Load or store 32 bits, regardless of target.

   Load64Disp/Store64Disp:
     Load or store 64 bits, regardless of target.

   LoadRefDisp:
     Load a 32-bit compressed reference, and expand it to the
     natural word size in the target register.

   StoreRefDisp:
     Compress a reference held in a register of the natural word
     size and store it as a 32-bit compressed reference.

Change-Id: I50fcbc8684476abd9527777ee7c152c61ba41c6f
diff --git a/compiler/dex/quick/x86/call_x86.cc b/compiler/dex/quick/x86/call_x86.cc
index 729b30d..746ae9e 100644
--- a/compiler/dex/quick/x86/call_x86.cc
+++ b/compiler/dex/quick/x86/call_x86.cc
@@ -251,7 +251,8 @@
     // We have been asked to save the address of the method start for later use.
     setup_method_address_[0] = NewLIR1(kX86StartOfMethod, rX86_ARG0);
     int displacement = SRegOffset(base_of_code_->s_reg_low);
-    setup_method_address_[1] = StoreBaseDisp(rs_rX86_SP, displacement, rs_rX86_ARG0, kWord);
+    // Native pointer - must be natural word size.
+    setup_method_address_[1] = StoreWordDisp(rs_rX86_SP, displacement, rs_rX86_ARG0);
   }
 
   FreeTemp(rX86_ARG0);
diff --git a/compiler/dex/quick/x86/fp_x86.cc b/compiler/dex/quick/x86/fp_x86.cc
index ee5387f..f7b0c9d 100644
--- a/compiler/dex/quick/x86/fp_x86.cc
+++ b/compiler/dex/quick/x86/fp_x86.cc
@@ -193,7 +193,7 @@
     } else {
       rl_result = EvalLoc(rl_dest, kFPReg, true);
 
-      LoadWordDisp(TargetReg(kSp), dest_v_reg_offset, rl_result.reg);
+      Load32Disp(TargetReg(kSp), dest_v_reg_offset, rl_result.reg);
 
       StoreFinalValue(rl_dest, rl_result);
     }
diff --git a/compiler/dex/quick/x86/int_x86.cc b/compiler/dex/quick/x86/int_x86.cc
index 4ffb9a4..cae30b2 100644
--- a/compiler/dex/quick/x86/int_x86.cc
+++ b/compiler/dex/quick/x86/int_x86.cc
@@ -704,15 +704,15 @@
 bool X86Mir2Lir::GenInlinedPeek(CallInfo* info, OpSize size) {
   RegLocation rl_src_address = info->args[0];  // long address
   rl_src_address = NarrowRegLoc(rl_src_address);  // ignore high half in info->args[1]
-  RegLocation rl_dest = size == kLong ? InlineTargetWide(info) : InlineTarget(info);
+  RegLocation rl_dest = size == k64 ? InlineTargetWide(info) : InlineTarget(info);
   RegLocation rl_address = LoadValue(rl_src_address, kCoreReg);
   RegLocation rl_result = EvalLoc(rl_dest, kCoreReg, true);
-  if (size == kLong) {
+  if (size == k64) {
     // Unaligned access is allowed on x86.
     LoadBaseDispWide(rl_address.reg, 0, rl_result.reg, INVALID_SREG);
     StoreValueWide(rl_dest, rl_result);
   } else {
-    DCHECK(size == kSignedByte || size == kSignedHalf || size == kWord);
+    DCHECK(size == kSignedByte || size == kSignedHalf || size == k32);
     // Unaligned access is allowed on x86.
     LoadBaseDisp(rl_address.reg, 0, rl_result.reg, size, INVALID_SREG);
     StoreValue(rl_dest, rl_result);
@@ -725,12 +725,12 @@
   rl_src_address = NarrowRegLoc(rl_src_address);  // ignore high half in info->args[1]
   RegLocation rl_src_value = info->args[2];  // [size] value
   RegLocation rl_address = LoadValue(rl_src_address, kCoreReg);
-  if (size == kLong) {
+  if (size == k64) {
     // Unaligned access is allowed on x86.
     RegLocation rl_value = LoadValueWide(rl_src_value, kCoreReg);
     StoreBaseDispWide(rl_address.reg, 0, rl_value.reg);
   } else {
-    DCHECK(size == kSignedByte || size == kSignedHalf || size == kWord);
+    DCHECK(size == kSignedByte || size == kSignedHalf || size == k32);
     // Unaligned access is allowed on x86.
     RegLocation rl_value = LoadValue(rl_src_value, kCoreReg);
     StoreBaseDisp(rl_address.reg, 0, rl_value.reg, size);
@@ -780,6 +780,7 @@
     int srcObjSp = IsInReg(this, rl_src_obj, rs_rSI) ? 0
                 : (IsInReg(this, rl_src_obj, rs_rDI) ? 4
                 : (SRegOffset(rl_src_obj.s_reg_low) + push_offset));
+    // FIXME: needs 64-bit update.
     LoadWordDisp(TargetReg(kSp), srcObjSp, rs_rDI);
     int srcOffsetSp = IsInReg(this, rl_src_offset, rs_rSI) ? 0
                    : (IsInReg(this, rl_src_offset, rs_rDI) ? 4
@@ -944,7 +945,7 @@
       NewLIR2(kX86Xor32RR, dest.GetReg(), dest.GetReg());
       break;
     case 1:
-      LoadBaseDisp(rs_rX86_SP, displacement, dest, kWord, sreg);
+      LoadBaseDisp(rs_rX86_SP, displacement, dest, k32, sreg);
       break;
     default:
       m = NewLIR4(IS_SIMM8(val) ? kX86Imul32RMI8 : kX86Imul32RMI, dest.GetReg(), rX86_SP,
@@ -1050,7 +1051,7 @@
     NewLIR2(kX86Mov32RR, r1, rl_src1.reg.GetHighReg());
   } else {
     LoadBaseDisp(rs_rX86_SP, SRegOffset(rl_src1.s_reg_low) + HIWORD_OFFSET, rs_r1,
-                 kWord, GetSRegHi(rl_src1.s_reg_low));
+                 k32, GetSRegHi(rl_src1.s_reg_low));
   }
 
   if (is_square) {
@@ -1073,7 +1074,7 @@
       NewLIR2(kX86Mov32RR, r0, rl_src2.reg.GetHighReg());
     } else {
       LoadBaseDisp(rs_rX86_SP, SRegOffset(rl_src2.s_reg_low) + HIWORD_OFFSET, rs_r0,
-                   kWord, GetSRegHi(rl_src2.s_reg_low));
+                   k32, GetSRegHi(rl_src2.s_reg_low));
     }
 
     // EAX <- EAX * 1L  (2H * 1L)
@@ -1105,7 +1106,7 @@
     NewLIR2(kX86Mov32RR, r0, rl_src2.reg.GetLowReg());
   } else {
     LoadBaseDisp(rs_rX86_SP, SRegOffset(rl_src2.s_reg_low) + LOWORD_OFFSET, rs_r0,
-                 kWord, rl_src2.s_reg_low);
+                 k32, rl_src2.s_reg_low);
   }
 
   // EDX:EAX <- 2L * 1L (double precision)
@@ -1325,7 +1326,7 @@
   rl_array = LoadValue(rl_array, kCoreReg);
 
   int data_offset;
-  if (size == kLong || size == kDouble) {
+  if (size == k64 || size == kDouble) {
     data_offset = mirror::Array::DataOffset(sizeof(int64_t)).Int32Value();
   } else {
     data_offset = mirror::Array::DataOffset(sizeof(int32_t)).Int32Value();
@@ -1355,7 +1356,7 @@
     }
   }
   rl_result = EvalLoc(rl_dest, reg_class, true);
-  if ((size == kLong) || (size == kDouble)) {
+  if ((size == k64) || (size == kDouble)) {
     LoadBaseIndexedDisp(rl_array.reg, rl_index.reg, scale, data_offset, rl_result.reg.GetLow(),
                         rl_result.reg.GetHigh(), size, INVALID_SREG);
     StoreValueWide(rl_dest, rl_result);
@@ -1376,7 +1377,7 @@
   int len_offset = mirror::Array::LengthOffset().Int32Value();
   int data_offset;
 
-  if (size == kLong || size == kDouble) {
+  if (size == k64 || size == kDouble) {
     data_offset = mirror::Array::DataOffset(sizeof(int64_t)).Int32Value();
   } else {
     data_offset = mirror::Array::DataOffset(sizeof(int32_t)).Int32Value();
@@ -1406,7 +1407,7 @@
       GenRegMemCheck(kCondUge, rl_index.reg, rl_array.reg, len_offset, kThrowArrayBounds);
     }
   }
-  if ((size == kLong) || (size == kDouble)) {
+  if ((size == k64) || (size == kDouble)) {
     rl_src = LoadValueWide(rl_src, reg_class);
   } else {
     rl_src = LoadValue(rl_src, reg_class);
@@ -1793,22 +1794,22 @@
 
   if (rl_method.location == kLocPhysReg) {
     if (use_declaring_class) {
-      LoadWordDisp(rl_method.reg, mirror::ArtMethod::DeclaringClassOffset().Int32Value(),
+      LoadRefDisp(rl_method.reg, mirror::ArtMethod::DeclaringClassOffset().Int32Value(),
                    check_class);
     } else {
-      LoadWordDisp(rl_method.reg, mirror::ArtMethod::DexCacheResolvedTypesOffset().Int32Value(),
+      LoadRefDisp(rl_method.reg, mirror::ArtMethod::DexCacheResolvedTypesOffset().Int32Value(),
                    check_class);
-      LoadWordDisp(check_class, offset_of_type, check_class);
+      LoadRefDisp(check_class, offset_of_type, check_class);
     }
   } else {
     LoadCurrMethodDirect(check_class);
     if (use_declaring_class) {
-      LoadWordDisp(check_class, mirror::ArtMethod::DeclaringClassOffset().Int32Value(),
+      LoadRefDisp(check_class, mirror::ArtMethod::DeclaringClassOffset().Int32Value(),
                    check_class);
     } else {
-      LoadWordDisp(check_class, mirror::ArtMethod::DexCacheResolvedTypesOffset().Int32Value(),
+      LoadRefDisp(check_class, mirror::ArtMethod::DexCacheResolvedTypesOffset().Int32Value(),
                    check_class);
-      LoadWordDisp(check_class, offset_of_type, check_class);
+      LoadRefDisp(check_class, offset_of_type, check_class);
     }
   }
 
@@ -1849,17 +1850,17 @@
     LoadValueDirectFixed(rl_src, TargetReg(kArg0));
   } else if (use_declaring_class) {
     LoadValueDirectFixed(rl_src, TargetReg(kArg0));
-    LoadWordDisp(TargetReg(kArg1), mirror::ArtMethod::DeclaringClassOffset().Int32Value(),
+    LoadRefDisp(TargetReg(kArg1), mirror::ArtMethod::DeclaringClassOffset().Int32Value(),
                  class_reg);
   } else {
     // Load dex cache entry into class_reg (kArg2).
     LoadValueDirectFixed(rl_src, TargetReg(kArg0));
-    LoadWordDisp(TargetReg(kArg1), mirror::ArtMethod::DexCacheResolvedTypesOffset().Int32Value(),
+    LoadRefDisp(TargetReg(kArg1), mirror::ArtMethod::DexCacheResolvedTypesOffset().Int32Value(),
                  class_reg);
     int32_t offset_of_type =
         mirror::Array::DataOffset(sizeof(mirror::Class*)).Int32Value() + (sizeof(mirror::Class*)
         * type_idx);
-    LoadWordDisp(class_reg, offset_of_type, class_reg);
+    LoadRefDisp(class_reg, offset_of_type, class_reg);
     if (!can_assume_type_is_in_dex_cache) {
       // Need to test presence of type in dex cache at runtime.
       LIR* hop_branch = OpCmpImmBranch(kCondNe, class_reg, 0, NULL);
@@ -1883,7 +1884,7 @@
 
   /* Load object->klass_. */
   DCHECK_EQ(mirror::Object::ClassOffset().Int32Value(), 0);
-  LoadWordDisp(TargetReg(kArg0),  mirror::Object::ClassOffset().Int32Value(), TargetReg(kArg1));
+  LoadRefDisp(TargetReg(kArg0),  mirror::Object::ClassOffset().Int32Value(), TargetReg(kArg1));
   /* kArg0 is ref, kArg1 is ref->klass_, kArg2 is class. */
   LIR* branchover = nullptr;
   if (type_known_final) {
diff --git a/compiler/dex/quick/x86/target_x86.cc b/compiler/dex/quick/x86/target_x86.cc
index 5a8ad7a..209285a 100644
--- a/compiler/dex/quick/x86/target_x86.cc
+++ b/compiler/dex/quick/x86/target_x86.cc
@@ -369,12 +369,13 @@
 }
 
 void X86Mir2Lir::FlushReg(RegStorage reg) {
+  // FIXME: need to handle 32 bits in 64-bit register as well as wide values held in single reg.
   DCHECK(!reg.IsPair());
   RegisterInfo* info = GetRegInfo(reg.GetReg());
   if (info->live && info->dirty) {
     info->dirty = false;
     int v_reg = mir_graph_->SRegToVReg(info->s_reg);
-    StoreBaseDisp(rs_rX86_SP, VRegOffset(v_reg), reg, kWord);
+    StoreBaseDisp(rs_rX86_SP, VRegOffset(v_reg), reg, k32);
   }
 }
 
@@ -1061,7 +1062,7 @@
   NewLIR1(kX86Push32R, rDI);
 
   // Compute the number of words to search in to rCX.
-  LoadWordDisp(rs_rDX, count_offset, rs_rCX);
+  Load32Disp(rs_rDX, count_offset, rs_rCX);
   LIR *length_compare = nullptr;
   int start_value = 0;
   bool is_index_on_stack = false;
@@ -1101,7 +1102,7 @@
       } else {
         // Load the start index from stack, remembering that we pushed EDI.
         int displacement = SRegOffset(rl_start.s_reg_low) + sizeof(uint32_t);
-        LoadWordDisp(rs_rX86_SP, displacement, rs_rBX);
+        Load32Disp(rs_rX86_SP, displacement, rs_rBX);
         OpRegReg(kOpXor, rs_rDI, rs_rDI);
         OpRegReg(kOpCmp, rs_rBX, rs_rDI);
         OpCondRegReg(kOpCmov, kCondLt, rs_rBX, rs_rDI);
@@ -1120,8 +1121,8 @@
 
   // Load the address of the string into EBX.
   // The string starts at VALUE(String) + 2 * OFFSET(String) + DATA_OFFSET.
-  LoadWordDisp(rs_rDX, value_offset, rs_rDI);
-  LoadWordDisp(rs_rDX, offset_offset, rs_rBX);
+  Load32Disp(rs_rDX, value_offset, rs_rDI);
+  Load32Disp(rs_rDX, offset_offset, rs_rBX);
   OpLea(rs_rBX, rs_rDI, rs_rBX, 1, data_offset);
 
   // Now compute into EDI where the search will start.
diff --git a/compiler/dex/quick/x86/utility_x86.cc b/compiler/dex/quick/x86/utility_x86.cc
index e9faa7f..00bebd2 100644
--- a/compiler/dex/quick/x86/utility_x86.cc
+++ b/compiler/dex/quick/x86/utility_x86.cc
@@ -554,7 +554,7 @@
   bool is64bit = false;
   X86OpCode opcode = kX86Nop;
   switch (size) {
-    case kLong:
+    case k64:
     case kDouble:
       // TODO: use regstorage attributes here.
       is64bit = true;
@@ -567,8 +567,9 @@
       // TODO: double store is to unaligned address
       DCHECK_EQ((displacement & 0x3), 0);
       break;
-    case kWord:
+    case k32:
     case kSingle:
+    case kReference:  // TODO: update for reference decompression on 64-bit targets.
       opcode = is_array ? kX86Mov32RA : kX86Mov32RM;
       if (X86_FPREG(r_dest.GetReg())) {
         opcode = is_array ? kX86MovssRA : kX86MovssRM;
@@ -669,6 +670,10 @@
 
 LIR* X86Mir2Lir::LoadBaseDisp(RegStorage r_base, int displacement,
                   RegStorage r_dest, OpSize size, int s_reg) {
+  // TODO: base this on target.
+  if (size == kWord) {
+    size = k32;
+  }
   return LoadBaseIndexedDisp(r_base, RegStorage::InvalidReg(), 0, displacement,
                              r_dest, RegStorage::InvalidReg(), size, s_reg);
 }
@@ -676,7 +681,7 @@
 LIR* X86Mir2Lir::LoadBaseDispWide(RegStorage r_base, int displacement, RegStorage r_dest,
                                   int s_reg) {
   return LoadBaseIndexedDisp(r_base, RegStorage::InvalidReg(), 0, displacement,
-                             r_dest.GetLow(), r_dest.GetHigh(), kLong, s_reg);
+                             r_dest.GetLow(), r_dest.GetHigh(), k64, s_reg);
 }
 
 LIR* X86Mir2Lir::StoreBaseIndexedDisp(RegStorage r_base, RegStorage r_index, int scale,
@@ -690,7 +695,7 @@
   bool is64bit = false;
   X86OpCode opcode = kX86Nop;
   switch (size) {
-    case kLong:
+    case k64:
     case kDouble:
       is64bit = true;
       if (X86_FPREG(r_src.GetReg())) {
@@ -702,8 +707,9 @@
       // TODO: double store is to unaligned address
       DCHECK_EQ((displacement & 0x3), 0);
       break;
-    case kWord:
+    case k32:
     case kSingle:
+    case kReference:
       opcode = is_array ? kX86Mov32AR : kX86Mov32MR;
       if (X86_FPREG(r_src.GetReg())) {
         opcode = is_array ? kX86MovssAR : kX86MovssMR;
@@ -763,13 +769,17 @@
 
 LIR* X86Mir2Lir::StoreBaseDisp(RegStorage r_base, int displacement,
                                RegStorage r_src, OpSize size) {
-    return StoreBaseIndexedDisp(r_base, RegStorage::InvalidReg(), 0, displacement, r_src,
-                                RegStorage::InvalidReg(), size, INVALID_SREG);
+  // TODO: base this on target.
+  if (size == kWord) {
+    size = k32;
+  }
+  return StoreBaseIndexedDisp(r_base, RegStorage::InvalidReg(), 0, displacement, r_src,
+                              RegStorage::InvalidReg(), size, INVALID_SREG);
 }
 
 LIR* X86Mir2Lir::StoreBaseDispWide(RegStorage r_base, int displacement, RegStorage r_src) {
   return StoreBaseIndexedDisp(r_base, RegStorage::InvalidReg(), 0, displacement,
-                              r_src.GetLow(), r_src.GetHigh(), kLong, INVALID_SREG);
+                              r_src.GetLow(), r_src.GetHigh(), k64, INVALID_SREG);
 }
 
 /*