Continuing register cleanup

Ready for review.

Continue the process of using RegStorage rather than
ints to hold register value in the top layers of codegen.
Given the huge number of changes in this CL, I've attempted
to minimize the number of actual logic changes.  With this
CL, the use of ints for registers has largely been eliminated
except in the lowest utility levels.  "Wide" utility routines
have been updated to take a single RegStorage rather than
a pair of ints representing low and high registers.

Upcoming CLs will be smaller and more targeted.  My expectations:
   o Allocate float double registers as a single double rather than
     a pair of float single registers.
   o Refactor to push code which assumes long and double Dalvik
     values are held in a pair of register to the target dependent
     layer.
   o Clean-up of the xxx_mir.h files to reduce the amount of #defines
     for registers.  May also do a register renumbering to bring all
     of our targets' register naming more consistent.  Possibly
     introduce a target-independent float/non-float test at the
     RegStorage level.

Change-Id: I646de7392bdec94595dd2c6f76e0f1c4331096ff
diff --git a/compiler/dex/mir_graph.h b/compiler/dex/mir_graph.h
index e10f66f..2c125f6 100644
--- a/compiler/dex/mir_graph.h
+++ b/compiler/dex/mir_graph.h
@@ -175,7 +175,6 @@
 
 #define INVALID_SREG (-1)
 #define INVALID_VREG (0xFFFFU)
-#define INVALID_REG (0x7F)
 #define INVALID_OFFSET (0xDEADF00FU)
 
 #define MIR_IGNORE_NULL_CHECK           (1 << kMIRIgnoreNullCheck)
diff --git a/compiler/dex/quick/arm/arm_lir.h b/compiler/dex/quick/arm/arm_lir.h
index c218621..1784af3 100644
--- a/compiler/dex/quick/arm/arm_lir.h
+++ b/compiler/dex/quick/arm/arm_lir.h
@@ -203,19 +203,53 @@
   dr15 = fr30 + ARM_FP_DOUBLE,
 };
 
+// TODO: clean this up; reduce use of or eliminate macros
+
+const RegStorage rs_r0(RegStorage::k32BitSolo, r0);
+const RegStorage rs_r1(RegStorage::k32BitSolo, r1);
+const RegStorage rs_r2(RegStorage::k32BitSolo, r2);
+const RegStorage rs_r3(RegStorage::k32BitSolo, r3);
+const RegStorage rs_rARM_SUSPEND(RegStorage::k32BitSolo, rARM_SUSPEND);
+const RegStorage rs_r5(RegStorage::k32BitSolo, r5);
+const RegStorage rs_r6(RegStorage::k32BitSolo, r6);
+const RegStorage rs_r7(RegStorage::k32BitSolo, r7);
+const RegStorage rs_r8(RegStorage::k32BitSolo, r8);
+const RegStorage rs_rARM_SELF(RegStorage::k32BitSolo, rARM_SELF);
+const RegStorage rs_r10(RegStorage::k32BitSolo, r10);
+const RegStorage rs_r11(RegStorage::k32BitSolo, r11);
+const RegStorage rs_r12(RegStorage::k32BitSolo, r12);
+const RegStorage rs_r13sp(RegStorage::k32BitSolo, r13sp);
+const RegStorage rs_rARM_SP(RegStorage::k32BitSolo, rARM_SP);
+const RegStorage rs_r14lr(RegStorage::k32BitSolo, r14lr);
+const RegStorage rs_rARM_LR(RegStorage::k32BitSolo, rARM_LR);
+const RegStorage rs_r15pc(RegStorage::k32BitSolo, r15pc);
+const RegStorage rs_rARM_PC(RegStorage::k32BitSolo, rARM_PC);
+const RegStorage rs_invalid(RegStorage::kInvalid);
+
 // Target-independent aliases.
 #define rARM_ARG0 r0
+#define rs_rARM_ARG0 rs_r0
 #define rARM_ARG1 r1
+#define rs_rARM_ARG1 rs_r1
 #define rARM_ARG2 r2
+#define rs_rARM_ARG2 rs_r2
 #define rARM_ARG3 r3
+#define rs_rARM_ARG3 rs_r3
 #define rARM_FARG0 r0
+#define rs_ARM_FARG0 rs_r0
 #define rARM_FARG1 r1
+#define rs_rARM_FARG1 rs_r1
 #define rARM_FARG2 r2
+#define rs_rARM_FARG2 rs_r2
 #define rARM_FARG3 r3
+#define rs_rARM_FARG3 rs_r3
 #define rARM_RET0 r0
+#define rs_rARM_RET0 rs_r0
 #define rARM_RET1 r1
+#define rs_rARM_RET1 rs_r1
 #define rARM_INVOKE_TGT rARM_LR
-#define rARM_COUNT INVALID_REG
+#define rs_rARM_INVOKE_TGT rs_rARM_LR
+#define rARM_COUNT RegStorage::kInvalidRegVal
 
 // RegisterLocation templates return values (r0, or r0/r1).
 const RegLocation arm_loc_c_return
diff --git a/compiler/dex/quick/arm/call_arm.cc b/compiler/dex/quick/arm/call_arm.cc
index 94f0ca4..175fc06 100644
--- a/compiler/dex/quick/arm/call_arm.cc
+++ b/compiler/dex/quick/arm/call_arm.cc
@@ -31,11 +31,11 @@
  *
  * The test loop will look something like:
  *
- *   adr   rBase, <table>
+ *   adr   r_base, <table>
  *   ldr   r_val, [rARM_SP, v_reg_off]
  *   mov   r_idx, #table_size
  * lp:
- *   ldmia rBase!, {r_key, r_disp}
+ *   ldmia r_base!, {r_key, r_disp}
  *   sub   r_idx, #1
  *   cmp   r_val, r_key
  *   ifeq
@@ -60,29 +60,29 @@
 
   // Get the switch value
   rl_src = LoadValue(rl_src, kCoreReg);
-  int rBase = AllocTemp();
+  RegStorage r_base = AllocTemp();
   /* Allocate key and disp temps */
-  int r_key = AllocTemp();
-  int r_disp = AllocTemp();
+  RegStorage r_key = AllocTemp();
+  RegStorage r_disp = AllocTemp();
   // Make sure r_key's register number is less than r_disp's number for ldmia
-  if (r_key > r_disp) {
-    int tmp = r_disp;
+  if (r_key.GetReg() > r_disp.GetReg()) {
+    RegStorage tmp = r_disp;
     r_disp = r_key;
     r_key = tmp;
   }
   // Materialize a pointer to the switch table
-  NewLIR3(kThumb2Adr, rBase, 0, WrapPointer(tab_rec));
+  NewLIR3(kThumb2Adr, r_base.GetReg(), 0, WrapPointer(tab_rec));
   // Set up r_idx
-  int r_idx = AllocTemp();
+  RegStorage r_idx = AllocTemp();
   LoadConstant(r_idx, size);
   // Establish loop branch target
   LIR* target = NewLIR0(kPseudoTargetLabel);
   // Load next key/disp
-  NewLIR2(kThumb2LdmiaWB, rBase, (1 << r_key) | (1 << r_disp));
-  OpRegReg(kOpCmp, r_key, rl_src.reg.GetReg());
+  NewLIR2(kThumb2LdmiaWB, r_base.GetReg(), (1 << r_key.GetReg()) | (1 << r_disp.GetReg()));
+  OpRegReg(kOpCmp, r_key, rl_src.reg);
   // Go if match. NOTE: No instruction set switch here - must stay Thumb2
   OpIT(kCondEq, "");
-  LIR* switch_branch = NewLIR1(kThumb2AddPCR, r_disp);
+  LIR* switch_branch = NewLIR1(kThumb2AddPCR, r_disp.GetReg());
   tab_rec->anchor = switch_branch;
   // Needs to use setflags encoding here
   OpRegRegImm(kOpSub, r_idx, r_idx, 1);  // For value == 1, this should set flags.
@@ -109,28 +109,28 @@
 
   // Get the switch value
   rl_src = LoadValue(rl_src, kCoreReg);
-  int table_base = AllocTemp();
+  RegStorage table_base = AllocTemp();
   // Materialize a pointer to the switch table
-  NewLIR3(kThumb2Adr, table_base, 0, WrapPointer(tab_rec));
+  NewLIR3(kThumb2Adr, table_base.GetReg(), 0, WrapPointer(tab_rec));
   int low_key = s4FromSwitchData(&table[2]);
-  int keyReg;
+  RegStorage keyReg;
   // Remove the bias, if necessary
   if (low_key == 0) {
-    keyReg = rl_src.reg.GetReg();
+    keyReg = rl_src.reg;
   } else {
     keyReg = AllocTemp();
-    OpRegRegImm(kOpSub, keyReg, rl_src.reg.GetReg(), low_key);
+    OpRegRegImm(kOpSub, keyReg, rl_src.reg, low_key);
   }
   // Bounds check - if < 0 or >= size continue following switch
   OpRegImm(kOpCmp, keyReg, size-1);
   LIR* branch_over = OpCondBranch(kCondHi, NULL);
 
   // Load the displacement from the switch table
-  int disp_reg = AllocTemp();
+  RegStorage disp_reg = AllocTemp();
   LoadBaseIndexed(table_base, keyReg, disp_reg, 2, kWord);
 
   // ..and go! NOTE: No instruction set switch here - must stay Thumb2
-  LIR* switch_branch = NewLIR1(kThumb2AddPCR, disp_reg);
+  LIR* switch_branch = NewLIR1(kThumb2AddPCR, disp_reg.GetReg());
   tab_rec->anchor = switch_branch;
 
   /* branch_over target here */
@@ -163,13 +163,13 @@
 
   // Making a call - use explicit registers
   FlushAllRegs();   /* Everything to home location */
-  LoadValueDirectFixed(rl_src, r0);
-  LoadWordDisp(rARM_SELF, QUICK_ENTRYPOINT_OFFSET(pHandleFillArrayData).Int32Value(),
-               rARM_LR);
+  LoadValueDirectFixed(rl_src, rs_r0);
+  LoadWordDisp(rs_rARM_SELF, QUICK_ENTRYPOINT_OFFSET(pHandleFillArrayData).Int32Value(),
+               rs_rARM_LR);
   // Materialize a pointer to the fill data image
   NewLIR3(kThumb2Adr, r1, 0, WrapPointer(tab_rec));
   ClobberCallerSave();
-  LIR* call_inst = OpReg(kOpBlx, rARM_LR);
+  LIR* call_inst = OpReg(kOpBlx, rs_rARM_LR);
   MarkSafepointPC(call_inst);
 }
 
@@ -179,7 +179,7 @@
  */
 void ArmMir2Lir::GenMonitorEnter(int opt_flags, RegLocation rl_src) {
   FlushAllRegs();
-  LoadValueDirectFixed(rl_src, r0);  // Get obj
+  LoadValueDirectFixed(rl_src, rs_r0);  // Get obj
   LockCallTemps();  // Prepare for explicit register usage
   constexpr bool kArchVariantHasGoodBranchPredictor = false;  // TODO: true if cortex-A15.
   if (kArchVariantHasGoodBranchPredictor) {
@@ -188,13 +188,13 @@
       null_check_branch = nullptr;  // No null check.
     } else {
       // If the null-check fails its handled by the slow-path to reduce exception related meta-data.
-      null_check_branch = OpCmpImmBranch(kCondEq, r0, 0, NULL);
+      null_check_branch = OpCmpImmBranch(kCondEq, rs_r0, 0, NULL);
     }
-    LoadWordDisp(rARM_SELF, Thread::ThinLockIdOffset().Int32Value(), r2);
+    LoadWordDisp(rs_rARM_SELF, Thread::ThinLockIdOffset().Int32Value(), rs_r2);
     NewLIR3(kThumb2Ldrex, r1, r0, mirror::Object::MonitorOffset().Int32Value() >> 2);
-    LIR* not_unlocked_branch = OpCmpImmBranch(kCondNe, r1, 0, NULL);
+    LIR* not_unlocked_branch = OpCmpImmBranch(kCondNe, rs_r1, 0, NULL);
     NewLIR4(kThumb2Strex, r1, r2, r0, mirror::Object::MonitorOffset().Int32Value() >> 2);
-    LIR* lock_success_branch = OpCmpImmBranch(kCondEq, r1, 0, NULL);
+    LIR* lock_success_branch = OpCmpImmBranch(kCondEq, rs_r1, 0, NULL);
 
 
     LIR* slow_path_target = NewLIR0(kPseudoTargetLabel);
@@ -204,9 +204,9 @@
     }
     // TODO: move to a slow path.
     // Go expensive route - artLockObjectFromCode(obj);
-    LoadWordDisp(rARM_SELF, QUICK_ENTRYPOINT_OFFSET(pLockObject).Int32Value(), rARM_LR);
+    LoadWordDisp(rs_rARM_SELF, QUICK_ENTRYPOINT_OFFSET(pLockObject).Int32Value(), rs_rARM_LR);
     ClobberCallerSave();
-    LIR* call_inst = OpReg(kOpBlx, rARM_LR);
+    LIR* call_inst = OpReg(kOpBlx, rs_rARM_LR);
     MarkSafepointPC(call_inst);
 
     LIR* success_target = NewLIR0(kPseudoTargetLabel);
@@ -214,19 +214,19 @@
     GenMemBarrier(kLoadLoad);
   } else {
     // Explicit null-check as slow-path is entered using an IT.
-    GenNullCheck(r0, opt_flags);
-    LoadWordDisp(rARM_SELF, Thread::ThinLockIdOffset().Int32Value(), r2);
+    GenNullCheck(rs_r0, opt_flags);
+    LoadWordDisp(rs_rARM_SELF, Thread::ThinLockIdOffset().Int32Value(), rs_r2);
     MarkPossibleNullPointerException(opt_flags);
     NewLIR3(kThumb2Ldrex, r1, r0, mirror::Object::MonitorOffset().Int32Value() >> 2);
-    OpRegImm(kOpCmp, r1, 0);
+    OpRegImm(kOpCmp, rs_r1, 0);
     OpIT(kCondEq, "");
     NewLIR4(kThumb2Strex/*eq*/, r1, r2, r0, mirror::Object::MonitorOffset().Int32Value() >> 2);
-    OpRegImm(kOpCmp, r1, 0);
+    OpRegImm(kOpCmp, rs_r1, 0);
     OpIT(kCondNe, "T");
     // Go expensive route - artLockObjectFromCode(self, obj);
-    LoadWordDisp/*ne*/(rARM_SELF, QUICK_ENTRYPOINT_OFFSET(pLockObject).Int32Value(), rARM_LR);
+    LoadWordDisp/*ne*/(rs_rARM_SELF, QUICK_ENTRYPOINT_OFFSET(pLockObject).Int32Value(), rs_rARM_LR);
     ClobberCallerSave();
-    LIR* call_inst = OpReg(kOpBlx/*ne*/, rARM_LR);
+    LIR* call_inst = OpReg(kOpBlx/*ne*/, rs_rARM_LR);
     MarkSafepointPC(call_inst);
     GenMemBarrier(kLoadLoad);
   }
@@ -239,22 +239,22 @@
  */
 void ArmMir2Lir::GenMonitorExit(int opt_flags, RegLocation rl_src) {
   FlushAllRegs();
-  LoadValueDirectFixed(rl_src, r0);  // Get obj
+  LoadValueDirectFixed(rl_src, rs_r0);  // Get obj
   LockCallTemps();  // Prepare for explicit register usage
   LIR* null_check_branch;
-  LoadWordDisp(rARM_SELF, Thread::ThinLockIdOffset().Int32Value(), r2);
+  LoadWordDisp(rs_rARM_SELF, Thread::ThinLockIdOffset().Int32Value(), rs_r2);
   constexpr bool kArchVariantHasGoodBranchPredictor = false;  // TODO: true if cortex-A15.
   if (kArchVariantHasGoodBranchPredictor) {
     if ((opt_flags & MIR_IGNORE_NULL_CHECK) && !(cu_->disable_opt & (1 << kNullCheckElimination))) {
       null_check_branch = nullptr;  // No null check.
     } else {
       // If the null-check fails its handled by the slow-path to reduce exception related meta-data.
-      null_check_branch = OpCmpImmBranch(kCondEq, r0, 0, NULL);
+      null_check_branch = OpCmpImmBranch(kCondEq, rs_r0, 0, NULL);
     }
-    LoadWordDisp(r0, mirror::Object::MonitorOffset().Int32Value(), r1);
-    LoadConstantNoClobber(r3, 0);
-    LIR* slow_unlock_branch = OpCmpBranch(kCondNe, r1, r2, NULL);
-    StoreWordDisp(r0, mirror::Object::MonitorOffset().Int32Value(), r3);
+    LoadWordDisp(rs_r0, mirror::Object::MonitorOffset().Int32Value(), rs_r1);
+    LoadConstantNoClobber(rs_r3, 0);
+    LIR* slow_unlock_branch = OpCmpBranch(kCondNe, rs_r1, rs_r2, NULL);
+    StoreWordDisp(rs_r0, mirror::Object::MonitorOffset().Int32Value(), rs_r3);
     LIR* unlock_success_branch = OpUnconditionalBranch(NULL);
 
     LIR* slow_path_target = NewLIR0(kPseudoTargetLabel);
@@ -264,9 +264,9 @@
     }
     // TODO: move to a slow path.
     // Go expensive route - artUnlockObjectFromCode(obj);
-    LoadWordDisp(rARM_SELF, QUICK_ENTRYPOINT_OFFSET(pUnlockObject).Int32Value(), rARM_LR);
+    LoadWordDisp(rs_rARM_SELF, QUICK_ENTRYPOINT_OFFSET(pUnlockObject).Int32Value(), rs_rARM_LR);
     ClobberCallerSave();
-    LIR* call_inst = OpReg(kOpBlx, rARM_LR);
+    LIR* call_inst = OpReg(kOpBlx, rs_rARM_LR);
     MarkSafepointPC(call_inst);
 
     LIR* success_target = NewLIR0(kPseudoTargetLabel);
@@ -274,19 +274,20 @@
     GenMemBarrier(kStoreLoad);
   } else {
     // Explicit null-check as slow-path is entered using an IT.
-    GenNullCheck(r0, opt_flags);
-    LoadWordDisp(r0, mirror::Object::MonitorOffset().Int32Value(), r1);  // Get lock
+    GenNullCheck(rs_r0, opt_flags);
+    LoadWordDisp(rs_r0, mirror::Object::MonitorOffset().Int32Value(), rs_r1);  // Get lock
     MarkPossibleNullPointerException(opt_flags);
-    LoadWordDisp(rARM_SELF, Thread::ThinLockIdOffset().Int32Value(), r2);
-    LoadConstantNoClobber(r3, 0);
+    LoadWordDisp(rs_rARM_SELF, Thread::ThinLockIdOffset().Int32Value(), rs_r2);
+    LoadConstantNoClobber(rs_r3, 0);
     // Is lock unheld on lock or held by us (==thread_id) on unlock?
-    OpRegReg(kOpCmp, r1, r2);
+    OpRegReg(kOpCmp, rs_r1, rs_r2);
     OpIT(kCondEq, "EE");
-    StoreWordDisp/*eq*/(r0, mirror::Object::MonitorOffset().Int32Value(), r3);
+    StoreWordDisp/*eq*/(rs_r0, mirror::Object::MonitorOffset().Int32Value(), rs_r3);
     // Go expensive route - UnlockObjectFromCode(obj);
-    LoadWordDisp/*ne*/(rARM_SELF, QUICK_ENTRYPOINT_OFFSET(pUnlockObject).Int32Value(), rARM_LR);
+    LoadWordDisp/*ne*/(rs_rARM_SELF, QUICK_ENTRYPOINT_OFFSET(pUnlockObject).Int32Value(),
+                       rs_rARM_LR);
     ClobberCallerSave();
-    LIR* call_inst = OpReg(kOpBlx/*ne*/, rARM_LR);
+    LIR* call_inst = OpReg(kOpBlx/*ne*/, rs_rARM_LR);
     MarkSafepointPC(call_inst);
     GenMemBarrier(kStoreLoad);
   }
@@ -295,10 +296,10 @@
 void ArmMir2Lir::GenMoveException(RegLocation rl_dest) {
   int ex_offset = Thread::ExceptionOffset().Int32Value();
   RegLocation rl_result = EvalLoc(rl_dest, kCoreReg, true);
-  int reset_reg = AllocTemp();
-  LoadWordDisp(rARM_SELF, ex_offset, rl_result.reg.GetReg());
+  RegStorage reset_reg = AllocTemp();
+  LoadWordDisp(rs_rARM_SELF, ex_offset, rl_result.reg);
   LoadConstant(reset_reg, 0);
-  StoreWordDisp(rARM_SELF, ex_offset, reset_reg);
+  StoreWordDisp(rs_rARM_SELF, ex_offset, reset_reg);
   FreeTemp(reset_reg);
   StoreValue(rl_dest, rl_result);
 }
@@ -306,14 +307,13 @@
 /*
  * Mark garbage collection card. Skip if the value we're storing is null.
  */
-void ArmMir2Lir::MarkGCCard(int val_reg, int tgt_addr_reg) {
-  int reg_card_base = AllocTemp();
-  int reg_card_no = AllocTemp();
+void ArmMir2Lir::MarkGCCard(RegStorage val_reg, RegStorage tgt_addr_reg) {
+  RegStorage reg_card_base = AllocTemp();
+  RegStorage reg_card_no = AllocTemp();
   LIR* branch_over = OpCmpImmBranch(kCondEq, val_reg, 0, NULL);
-  LoadWordDisp(rARM_SELF, Thread::CardTableOffset().Int32Value(), reg_card_base);
+  LoadWordDisp(rs_rARM_SELF, Thread::CardTableOffset().Int32Value(), reg_card_base);
   OpRegRegImm(kOpLsr, reg_card_no, tgt_addr_reg, gc::accounting::CardTable::kCardShift);
-  StoreBaseIndexed(reg_card_base, reg_card_no, reg_card_base, 0,
-                   kUnsignedByte);
+  StoreBaseIndexed(reg_card_base, reg_card_no, reg_card_base, 0, kUnsignedByte);
   LIR* target = NewLIR0(kPseudoTargetLabel);
   branch_over->target = target;
   FreeTemp(reg_card_base);
@@ -344,7 +344,7 @@
   if (!skip_overflow_check) {
     if (Runtime::Current()->ExplicitStackOverflowChecks()) {
       /* Load stack limit */
-      LoadWordDisp(rARM_SELF, Thread::StackEndOffset().Int32Value(), r12);
+      LoadWordDisp(rs_rARM_SELF, Thread::StackEndOffset().Int32Value(), rs_r12);
     }
   }
   /* Spill core callee saves */
@@ -374,14 +374,14 @@
           m2l_->ResetDefTracking();
           GenerateTargetLabel();
           if (restore_lr_) {
-            m2l_->LoadWordDisp(kArmRegSP, sp_displace_ - 4, kArmRegLR);
+            m2l_->LoadWordDisp(rs_rARM_SP, sp_displace_ - 4, rs_rARM_LR);
           }
-          m2l_->OpRegImm(kOpAdd, kArmRegSP, sp_displace_);
+          m2l_->OpRegImm(kOpAdd, rs_rARM_SP, sp_displace_);
           m2l_->ClobberCallerSave();
           ThreadOffset func_offset = QUICK_ENTRYPOINT_OFFSET(pThrowStackOverflow);
           // Load the entrypoint directly into the pc instead of doing a load + branch. Assumes
           // codegen and target are in thumb2 mode.
-          m2l_->LoadWordDisp(rARM_SELF, func_offset.Int32Value(), rARM_PC);
+          m2l_->LoadWordDisp(rs_rARM_SELF, func_offset.Int32Value(), rs_rARM_PC);
         }
 
        private:
@@ -389,29 +389,29 @@
         const size_t sp_displace_;
       };
       if (static_cast<size_t>(frame_size_) > Thread::kStackOverflowReservedUsableBytes) {
-        OpRegRegImm(kOpSub, rARM_LR, rARM_SP, frame_size_without_spills);
-        LIR* branch = OpCmpBranch(kCondUlt, rARM_LR, r12, nullptr);
+        OpRegRegImm(kOpSub, rs_rARM_LR, rs_rARM_SP, frame_size_without_spills);
+        LIR* branch = OpCmpBranch(kCondUlt, rs_rARM_LR, rs_r12, nullptr);
         // Need to restore LR since we used it as a temp.
         AddSlowPath(new(arena_)StackOverflowSlowPath(this, branch, true,
                                                      frame_size_without_spills));
-        OpRegCopy(rARM_SP, rARM_LR);     // Establish stack
+        OpRegCopy(rs_rARM_SP, rs_rARM_LR);     // Establish stack
       } else {
         // If the frame is small enough we are guaranteed to have enough space that remains to
         // handle signals on the user stack.
-        OpRegRegImm(kOpSub, rARM_SP, rARM_SP, frame_size_without_spills);
-        LIR* branch = OpCmpBranch(kCondUlt, rARM_SP, r12, nullptr);
+        OpRegRegImm(kOpSub, rs_rARM_SP, rs_rARM_SP, frame_size_without_spills);
+        LIR* branch = OpCmpBranch(kCondUlt, rs_rARM_SP, rs_r12, nullptr);
         AddSlowPath(new(arena_)StackOverflowSlowPath(this, branch, false, frame_size_));
       }
     } else {
       // Implicit stack overflow check.
       // Generate a load from [sp, #-framesize].  If this is in the stack
       // redzone we will get a segmentation fault.
-      OpRegImm(kOpSub, rARM_SP, frame_size_without_spills);
-      LoadWordDisp(rARM_SP, 0, rARM_LR);
+      OpRegImm(kOpSub, rs_rARM_SP, frame_size_without_spills);
+      LoadWordDisp(rs_rARM_SP, 0, rs_rARM_LR);
       MarkPossibleStackOverflowException();
     }
   } else {
-    OpRegImm(kOpSub, rARM_SP, frame_size_without_spills);
+    OpRegImm(kOpSub, rs_rARM_SP, frame_size_without_spills);
   }
 
   FlushIns(ArgLocs, rl_method);
@@ -432,7 +432,7 @@
   LockTemp(r1);
 
   NewLIR0(kPseudoMethodExit);
-  OpRegImm(kOpAdd, rARM_SP, frame_size_ - (spill_count * 4));
+  OpRegImm(kOpAdd, rs_rARM_SP, frame_size_ - (spill_count * 4));
   /* Need to restore any FP callee saves? */
   if (num_fp_spills_) {
     NewLIR1(kThumb2VPopCS, num_fp_spills_);
diff --git a/compiler/dex/quick/arm/codegen_arm.h b/compiler/dex/quick/arm/codegen_arm.h
index 6e72c80..0f1e171 100644
--- a/compiler/dex/quick/arm/codegen_arm.h
+++ b/compiler/dex/quick/arm/codegen_arm.h
@@ -28,32 +28,35 @@
 
     // Required for target - codegen helpers.
     bool SmallLiteralDivRem(Instruction::Code dalvik_opcode, bool is_div, RegLocation rl_src,
-                                    RegLocation rl_dest, int lit);
-    int LoadHelper(ThreadOffset offset);
+                            RegLocation rl_dest, int lit);
     LIR* CheckSuspendUsingLoad() OVERRIDE;
-    LIR* LoadBaseDisp(int rBase, int displacement, int r_dest, OpSize size, int s_reg);
-    LIR* LoadBaseDispWide(int rBase, int displacement, int r_dest_lo, int r_dest_hi,
-                          int s_reg);
-    LIR* LoadBaseIndexed(int rBase, int r_index, int r_dest, int scale, OpSize size);
-    LIR* LoadBaseIndexedDisp(int rBase, int r_index, int scale, int displacement,
-                             int r_dest, int r_dest_hi, OpSize size, int s_reg);
-    LIR* LoadConstantNoClobber(int r_dest, int value);
-    LIR* LoadConstantWide(int r_dest_lo, int r_dest_hi, int64_t value);
-    LIR* StoreBaseDisp(int rBase, int displacement, int r_src, OpSize size);
-    LIR* StoreBaseDispWide(int rBase, int displacement, int r_src_lo, int r_src_hi);
-    LIR* StoreBaseIndexed(int rBase, int r_index, int r_src, int scale, OpSize size);
-    LIR* StoreBaseIndexedDisp(int rBase, int r_index, int scale, int displacement,
-                              int r_src, int r_src_hi, OpSize size, int s_reg);
-    void MarkGCCard(int val_reg, int tgt_addr_reg);
+    RegStorage LoadHelper(ThreadOffset offset);
+    LIR* LoadBaseDisp(RegStorage r_base, int displacement, RegStorage r_dest, OpSize size,
+                      int s_reg);
+    LIR* LoadBaseDispWide(RegStorage r_base, int displacement, RegStorage r_dest, int s_reg);
+    LIR* LoadBaseIndexed(RegStorage r_base, RegStorage r_index, RegStorage r_dest, int scale,
+                         OpSize size);
+    LIR* LoadBaseIndexedDisp(RegStorage r_base, RegStorage r_index, int scale, int displacement,
+                             RegStorage r_dest, RegStorage r_dest_hi, OpSize size, int s_reg);
+    LIR* LoadConstantNoClobber(RegStorage r_dest, int value);
+    LIR* LoadConstantWide(RegStorage r_dest, int64_t value);
+    LIR* StoreBaseDisp(RegStorage r_base, int displacement, RegStorage r_src, OpSize size);
+    LIR* StoreBaseDispWide(RegStorage r_base, int displacement, RegStorage r_src);
+    LIR* StoreBaseIndexed(RegStorage r_base, RegStorage r_index, RegStorage r_src, int scale,
+                          OpSize size);
+    LIR* StoreBaseIndexedDisp(RegStorage r_base, RegStorage r_index, int scale, int displacement,
+                              RegStorage r_src, RegStorage r_src_hi, OpSize size, int s_reg);
+    void MarkGCCard(RegStorage val_reg, RegStorage tgt_addr_reg);
 
     // Required for target - register utilities.
     bool IsFpReg(int reg);
+    bool IsFpReg(RegStorage reg);
     bool SameRegType(int reg1, int reg2);
-    int AllocTypedTemp(bool fp_hint, int reg_class);
+    RegStorage AllocTypedTemp(bool fp_hint, int reg_class);
     RegStorage AllocTypedTempWide(bool fp_hint, int reg_class);
     int S2d(int low_reg, int high_reg);
-    int TargetReg(SpecialTargetRegister reg);
-    int GetArgMappingToPhysicalReg(int arg_num);
+    RegStorage TargetReg(SpecialTargetRegister reg);
+    RegStorage GetArgMappingToPhysicalReg(int arg_num);
     RegLocation GetReturnAlt();
     RegLocation GetReturnWideAlt();
     RegLocation LocCReturn();
@@ -64,8 +67,8 @@
     uint64_t GetRegMaskCommon(int reg);
     void AdjustSpillMask();
     void ClobberCallerSave();
-    void FlushReg(int reg);
-    void FlushRegWide(int reg1, int reg2);
+    void FlushReg(RegStorage reg);
+    void FlushRegWide(RegStorage reg);
     void FreeCallTemps();
     void FreeRegLocTemps(RegLocation rl_keep, RegLocation rl_free);
     void LockCallTemps();
@@ -97,13 +100,16 @@
                      RegLocation rl_src, int scale, bool card_mark);
     void GenShiftImmOpLong(Instruction::Code opcode, RegLocation rl_dest,
                            RegLocation rl_src1, RegLocation rl_shift);
-    void GenMulLong(Instruction::Code opcode, RegLocation rl_dest, RegLocation rl_src1, RegLocation rl_src2);
-    void GenAddLong(Instruction::Code opcode, RegLocation rl_dest, RegLocation rl_src1, RegLocation rl_src2);
-    void GenAndLong(Instruction::Code opcode, RegLocation rl_dest, RegLocation rl_src1, RegLocation rl_src2);
-    void GenArithOpDouble(Instruction::Code opcode, RegLocation rl_dest,
-                          RegLocation rl_src1, RegLocation rl_src2);
-    void GenArithOpFloat(Instruction::Code opcode, RegLocation rl_dest,
-                         RegLocation rl_src1, RegLocation rl_src2);
+    void GenMulLong(Instruction::Code opcode, RegLocation rl_dest, RegLocation rl_src1,
+                    RegLocation rl_src2);
+    void GenAddLong(Instruction::Code opcode, RegLocation rl_dest, RegLocation rl_src1,
+                    RegLocation rl_src2);
+    void GenAndLong(Instruction::Code opcode, RegLocation rl_dest, RegLocation rl_src1,
+                    RegLocation rl_src2);
+    void GenArithOpDouble(Instruction::Code opcode, RegLocation rl_dest, RegLocation rl_src1,
+                          RegLocation rl_src2);
+    void GenArithOpFloat(Instruction::Code opcode, RegLocation rl_dest, RegLocation rl_src1,
+                         RegLocation rl_src2);
     void GenCmpFP(Instruction::Code opcode, RegLocation rl_dest, RegLocation rl_src1,
                   RegLocation rl_src2);
     void GenConversion(Instruction::Code opcode, RegLocation rl_dest, RegLocation rl_src);
@@ -113,15 +119,18 @@
     bool GenInlinedPeek(CallInfo* info, OpSize size);
     bool GenInlinedPoke(CallInfo* info, OpSize size);
     void GenNegLong(RegLocation rl_dest, RegLocation rl_src);
-    void GenOrLong(Instruction::Code opcode, RegLocation rl_dest, RegLocation rl_src1, RegLocation rl_src2);
-    void GenSubLong(Instruction::Code opcode, RegLocation rl_dest, RegLocation rl_src1, RegLocation rl_src2);
-    void GenXorLong(Instruction::Code opcode, RegLocation rl_dest, RegLocation rl_src1, RegLocation rl_src2);
-    LIR* GenRegMemCheck(ConditionCode c_code, int reg1, int base, int offset,
-                                ThrowKind kind);
-    RegLocation GenDivRem(RegLocation rl_dest, int reg_lo, int reg_hi, bool is_div);
-    RegLocation GenDivRemLit(RegLocation rl_dest, int reg_lo, int lit, bool is_div);
+    void GenOrLong(Instruction::Code opcode, RegLocation rl_dest, RegLocation rl_src1,
+                   RegLocation rl_src2);
+    void GenSubLong(Instruction::Code opcode, RegLocation rl_dest, RegLocation rl_src1,
+                    RegLocation rl_src2);
+    void GenXorLong(Instruction::Code opcode, RegLocation rl_dest, RegLocation rl_src1,
+                    RegLocation rl_src2);
+    LIR* GenRegMemCheck(ConditionCode c_code, RegStorage reg1, RegStorage base, int offset,
+                        ThrowKind kind);
+    RegLocation GenDivRem(RegLocation rl_dest, RegStorage reg_lo, RegStorage reg_hi, bool is_div);
+    RegLocation GenDivRemLit(RegLocation rl_dest, RegStorage reg_lo, int lit, bool is_div);
     void GenCmpLong(RegLocation rl_dest, RegLocation rl_src1, RegLocation rl_src2);
-    void GenDivZeroCheck(int reg_lo, int reg_hi);
+    void GenDivZeroCheck(RegStorage reg);
     void GenEntrySequence(RegLocation* ArgLocs, RegLocation rl_method);
     void GenExitSequence();
     void GenSpecialExitSequence();
@@ -134,7 +143,7 @@
     void GenMonitorExit(int opt_flags, RegLocation rl_src);
     void GenMoveException(RegLocation rl_dest);
     void GenMultiplyByTwoBitMultiplier(RegLocation rl_src, RegLocation rl_result, int lit,
-                                               int first_bit, int second_bit);
+                                       int first_bit, int second_bit);
     void GenNegDouble(RegLocation rl_dest, RegLocation rl_src);
     void GenNegFloat(RegLocation rl_dest, RegLocation rl_src);
     void GenPackedSwitch(MIR* mir, DexOffset table_offset, RegLocation rl_src);
@@ -142,36 +151,36 @@
 
     // Required for target - single operation generators.
     LIR* OpUnconditionalBranch(LIR* target);
-    LIR* OpCmpBranch(ConditionCode cond, int src1, int src2, LIR* target);
-    LIR* OpCmpImmBranch(ConditionCode cond, int reg, int check_value, LIR* target);
+    LIR* OpCmpBranch(ConditionCode cond, RegStorage src1, RegStorage src2, LIR* target);
+    LIR* OpCmpImmBranch(ConditionCode cond, RegStorage reg, int check_value, LIR* target);
     LIR* OpCondBranch(ConditionCode cc, LIR* target);
-    LIR* OpDecAndBranch(ConditionCode c_code, int reg, LIR* target);
-    LIR* OpFpRegCopy(int r_dest, int r_src);
+    LIR* OpDecAndBranch(ConditionCode c_code, RegStorage reg, LIR* target);
+    LIR* OpFpRegCopy(RegStorage r_dest, RegStorage r_src);
     LIR* OpIT(ConditionCode cond, const char* guide);
-    LIR* OpMem(OpKind op, int rBase, int disp);
-    LIR* OpPcRelLoad(int reg, LIR* target);
-    LIR* OpReg(OpKind op, int r_dest_src);
-    LIR* OpRegCopy(int r_dest, int r_src);
-    LIR* OpRegCopyNoInsert(int r_dest, int r_src);
-    LIR* OpRegImm(OpKind op, int r_dest_src1, int value);
-    LIR* OpRegMem(OpKind op, int r_dest, int rBase, int offset);
-    LIR* OpRegReg(OpKind op, int r_dest_src1, int r_src2);
-    LIR* OpMovRegMem(int r_dest, int r_base, int offset, MoveType move_type);
-    LIR* OpMovMemReg(int r_base, int offset, int r_src, MoveType move_type);
-    LIR* OpCondRegReg(OpKind op, ConditionCode cc, int r_dest, int r_src);
-    LIR* OpRegRegImm(OpKind op, int r_dest, int r_src1, int value);
-    LIR* OpRegRegReg(OpKind op, int r_dest, int r_src1, int r_src2);
+    LIR* OpMem(OpKind op, RegStorage r_base, int disp);
+    LIR* OpPcRelLoad(RegStorage reg, LIR* target);
+    LIR* OpReg(OpKind op, RegStorage r_dest_src);
+    LIR* OpRegCopy(RegStorage r_dest, RegStorage r_src);
+    LIR* OpRegCopyNoInsert(RegStorage r_dest, RegStorage r_src);
+    LIR* OpRegImm(OpKind op, RegStorage r_dest_src1, int value);
+    LIR* OpRegMem(OpKind op, RegStorage r_dest, RegStorage r_base, int offset);
+    LIR* OpRegReg(OpKind op, RegStorage r_dest_src1, RegStorage r_src2);
+    LIR* OpMovRegMem(RegStorage r_dest, RegStorage r_base, int offset, MoveType move_type);
+    LIR* OpMovMemReg(RegStorage r_base, int offset, RegStorage r_src, MoveType move_type);
+    LIR* OpCondRegReg(OpKind op, ConditionCode cc, RegStorage r_dest, RegStorage r_src);
+    LIR* OpRegRegImm(OpKind op, RegStorage r_dest, RegStorage r_src1, int value);
+    LIR* OpRegRegReg(OpKind op, RegStorage r_dest, RegStorage r_src1, RegStorage r_src2);
     LIR* OpTestSuspend(LIR* target);
     LIR* OpThreadMem(OpKind op, ThreadOffset thread_offset);
-    LIR* OpVldm(int rBase, int count);
-    LIR* OpVstm(int rBase, int count);
-    void OpLea(int rBase, int reg1, int reg2, int scale, int offset);
-    void OpRegCopyWide(int dest_lo, int dest_hi, int src_lo, int src_hi);
+    LIR* OpVldm(RegStorage r_base, int count);
+    LIR* OpVstm(RegStorage r_base, int count);
+    void OpLea(RegStorage r_base, RegStorage reg1, RegStorage reg2, int scale, int offset);
+    void OpRegCopyWide(RegStorage dest, RegStorage src);
     void OpTlsCmp(ThreadOffset offset, int val);
 
-    LIR* LoadBaseDispBody(int rBase, int displacement, int r_dest, int r_dest_hi, OpSize size,
+    LIR* LoadBaseDispBody(RegStorage r_base, int displacement, RegStorage r_dest, OpSize size,
                           int s_reg);
-    LIR* StoreBaseDispBody(int rBase, int displacement, int r_src, int r_src_hi, OpSize size);
+    LIR* StoreBaseDispBody(RegStorage r_base, int displacement, RegStorage r_src, OpSize size);
     LIR* OpRegRegRegShift(OpKind op, int r_dest, int r_src1, int r_src2, int shift);
     LIR* OpRegRegShift(OpKind op, int r_dest_src1, int r_src2, int shift);
     static const ArmEncodingMap EncodingMap[kArmLast];
@@ -190,8 +199,8 @@
     void ReplaceFixup(LIR* prev_lir, LIR* orig_lir, LIR* new_lir);
     void InsertFixupBefore(LIR* prev_lir, LIR* orig_lir, LIR* new_lir);
     void AssignDataOffsets();
-    RegLocation GenDivRem(RegLocation rl_dest, RegLocation rl_src1,
-                          RegLocation rl_src2, bool is_div, bool check_zero);
+    RegLocation GenDivRem(RegLocation rl_dest, RegLocation rl_src1, RegLocation rl_src2,
+                          bool is_div, bool check_zero);
     RegLocation GenDivRemLit(RegLocation rl_dest, RegLocation rl_src1, int lit, bool is_div);
 };
 
diff --git a/compiler/dex/quick/arm/fp_arm.cc b/compiler/dex/quick/arm/fp_arm.cc
index 6868f6f..398bf96 100644
--- a/compiler/dex/quick/arm/fp_arm.cc
+++ b/compiler/dex/quick/arm/fp_arm.cc
@@ -111,8 +111,8 @@
   rl_result = EvalLoc(rl_dest, kFPReg, true);
   DCHECK(rl_dest.wide);
   DCHECK(rl_result.wide);
-  NewLIR3(op, S2d(rl_result.reg.GetReg(), rl_result.reg.GetHighReg()), S2d(rl_src1.reg.GetReg(), rl_src1.reg.GetHighReg()),
-          S2d(rl_src2.reg.GetReg(), rl_src2.reg.GetHighReg()));
+  NewLIR3(op, S2d(rl_result.reg.GetLowReg(), rl_result.reg.GetHighReg()), S2d(rl_src1.reg.GetLowReg(), rl_src1.reg.GetHighReg()),
+          S2d(rl_src2.reg.GetLowReg(), rl_src2.reg.GetHighReg()));
   StoreValueWide(rl_dest, rl_result);
 }
 
@@ -143,17 +143,19 @@
       break;
     case Instruction::LONG_TO_DOUBLE: {
       rl_src = LoadValueWide(rl_src, kFPReg);
-      src_reg = S2d(rl_src.reg.GetReg(), rl_src.reg.GetHighReg());
+      src_reg = S2d(rl_src.reg.GetLowReg(), rl_src.reg.GetHighReg());
       rl_result = EvalLoc(rl_dest, kFPReg, true);
-      // TODO: clean up AllocTempDouble so that its result has the double bits set.
-      int tmp1 = AllocTempDouble();
-      int tmp2 = AllocTempDouble();
+      // TODO: fix AllocTempDouble to return a k64BitSolo double reg and lose the ARM_FP_DOUBLE.
+      RegStorage tmp1 = AllocTempDouble();
+      RegStorage tmp2 = AllocTempDouble();
 
-      NewLIR2(kThumb2VcvtF64S32, tmp1 | ARM_FP_DOUBLE, (src_reg & ~ARM_FP_DOUBLE) + 1);
-      NewLIR2(kThumb2VcvtF64U32, S2d(rl_result.reg.GetReg(), rl_result.reg.GetHighReg()), (src_reg & ~ARM_FP_DOUBLE));
-      LoadConstantWide(tmp2, tmp2 + 1, INT64_C(0x41f0000000000000));
-      NewLIR3(kThumb2VmlaF64, S2d(rl_result.reg.GetReg(), rl_result.reg.GetHighReg()), tmp1 | ARM_FP_DOUBLE,
-              tmp2 | ARM_FP_DOUBLE);
+      // FIXME: needs 64-bit register cleanup.
+      NewLIR2(kThumb2VcvtF64S32, tmp1.GetLowReg() | ARM_FP_DOUBLE, (src_reg & ~ARM_FP_DOUBLE) + 1);
+      NewLIR2(kThumb2VcvtF64U32, S2d(rl_result.reg.GetLowReg(), rl_result.reg.GetHighReg()),
+              (src_reg & ~ARM_FP_DOUBLE));
+      LoadConstantWide(tmp2, 0x41f0000000000000LL);
+      NewLIR3(kThumb2VmlaF64, S2d(rl_result.reg.GetLowReg(), rl_result.reg.GetHighReg()),
+              tmp1.GetLowReg() | ARM_FP_DOUBLE, tmp2.GetLowReg() | ARM_FP_DOUBLE);
       FreeTemp(tmp1);
       FreeTemp(tmp2);
       StoreValueWide(rl_dest, rl_result);
@@ -164,20 +166,23 @@
       return;
     case Instruction::LONG_TO_FLOAT: {
       rl_src = LoadValueWide(rl_src, kFPReg);
-      src_reg = S2d(rl_src.reg.GetReg(), rl_src.reg.GetHighReg());
+      src_reg = S2d(rl_src.reg.GetLowReg(), rl_src.reg.GetHighReg());
       rl_result = EvalLoc(rl_dest, kFPReg, true);
       // Allocate temp registers.
-      int high_val = AllocTempDouble();
-      int low_val = AllocTempDouble();
-      int const_val = AllocTempDouble();
+      RegStorage high_val = AllocTempDouble();
+      RegStorage low_val = AllocTempDouble();
+      RegStorage const_val = AllocTempDouble();
       // Long to double.
-      NewLIR2(kThumb2VcvtF64S32, high_val | ARM_FP_DOUBLE, (src_reg & ~ARM_FP_DOUBLE) + 1);
-      NewLIR2(kThumb2VcvtF64U32, low_val | ARM_FP_DOUBLE, (src_reg & ~ARM_FP_DOUBLE));
-      LoadConstantWide(const_val, const_val + 1, INT64_C(0x41f0000000000000));
-      NewLIR3(kThumb2VmlaF64, low_val | ARM_FP_DOUBLE, high_val | ARM_FP_DOUBLE,
-          const_val | ARM_FP_DOUBLE);
+      NewLIR2(kThumb2VcvtF64S32, high_val.GetLowReg() | ARM_FP_DOUBLE,
+              (src_reg & ~ARM_FP_DOUBLE) + 1);
+      NewLIR2(kThumb2VcvtF64U32, low_val.GetLowReg() | ARM_FP_DOUBLE,
+              (src_reg & ~ARM_FP_DOUBLE));
+      LoadConstantWide(const_val, INT64_C(0x41f0000000000000));
+      NewLIR3(kThumb2VmlaF64, low_val.GetLowReg() | ARM_FP_DOUBLE,
+              high_val.GetLowReg() | ARM_FP_DOUBLE,
+              const_val.GetLowReg() | ARM_FP_DOUBLE);
       // Double to float.
-      NewLIR2(kThumb2VcvtDF, rl_result.reg.GetReg(), low_val | ARM_FP_DOUBLE);
+      NewLIR2(kThumb2VcvtDF, rl_result.reg.GetReg(), low_val.GetLowReg() | ARM_FP_DOUBLE);
       // Free temp registers.
       FreeTemp(high_val);
       FreeTemp(low_val);
@@ -194,14 +199,14 @@
   }
   if (rl_src.wide) {
     rl_src = LoadValueWide(rl_src, kFPReg);
-    src_reg = S2d(rl_src.reg.GetReg(), rl_src.reg.GetHighReg());
+    src_reg = S2d(rl_src.reg.GetLowReg(), rl_src.reg.GetHighReg());
   } else {
     rl_src = LoadValue(rl_src, kFPReg);
     src_reg = rl_src.reg.GetReg();
   }
   if (rl_dest.wide) {
     rl_result = EvalLoc(rl_dest, kFPReg, true);
-    NewLIR2(op, S2d(rl_result.reg.GetReg(), rl_result.reg.GetHighReg()), src_reg);
+    NewLIR2(op, S2d(rl_result.reg.GetLowReg(), rl_result.reg.GetHighReg()), src_reg);
     StoreValueWide(rl_dest, rl_result);
   } else {
     rl_result = EvalLoc(rl_dest, kFPReg, true);
@@ -220,8 +225,8 @@
     rl_src2 = mir_graph_->GetSrcWide(mir, 2);
     rl_src1 = LoadValueWide(rl_src1, kFPReg);
     rl_src2 = LoadValueWide(rl_src2, kFPReg);
-    NewLIR2(kThumb2Vcmpd, S2d(rl_src1.reg.GetReg(), rl_src2.reg.GetHighReg()),
-            S2d(rl_src2.reg.GetReg(), rl_src2.reg.GetHighReg()));
+    NewLIR2(kThumb2Vcmpd, S2d(rl_src1.reg.GetLowReg(), rl_src2.reg.GetHighReg()),
+            S2d(rl_src2.reg.GetLowReg(), rl_src2.reg.GetHighReg()));
   } else {
     rl_src1 = mir_graph_->GetSrc(mir, 0);
     rl_src2 = mir_graph_->GetSrc(mir, 1);
@@ -294,16 +299,16 @@
     // In case result vreg is also a src vreg, break association to avoid useless copy by EvalLoc()
     ClobberSReg(rl_dest.s_reg_low);
     rl_result = EvalLoc(rl_dest, kCoreReg, true);
-    LoadConstant(rl_result.reg.GetReg(), default_result);
-    NewLIR2(kThumb2Vcmpd, S2d(rl_src1.reg.GetReg(), rl_src2.reg.GetHighReg()),
-            S2d(rl_src2.reg.GetReg(), rl_src2.reg.GetHighReg()));
+    LoadConstant(rl_result.reg, default_result);
+    NewLIR2(kThumb2Vcmpd, S2d(rl_src1.reg.GetLowReg(), rl_src2.reg.GetHighReg()),
+            S2d(rl_src2.reg.GetLowReg(), rl_src2.reg.GetHighReg()));
   } else {
     rl_src1 = LoadValue(rl_src1, kFPReg);
     rl_src2 = LoadValue(rl_src2, kFPReg);
     // In case result vreg is also a srcvreg, break association to avoid useless copy by EvalLoc()
     ClobberSReg(rl_dest.s_reg_low);
     rl_result = EvalLoc(rl_dest, kCoreReg, true);
-    LoadConstant(rl_result.reg.GetReg(), default_result);
+    LoadConstant(rl_result.reg, default_result);
     NewLIR2(kThumb2Vcmps, rl_src1.reg.GetReg(), rl_src2.reg.GetReg());
   }
   DCHECK(!ARM_FPREG(rl_result.reg.GetReg()));
@@ -315,7 +320,7 @@
   GenBarrier();
 
   OpIT(kCondEq, "");
-  LoadConstant(rl_result.reg.GetReg(), 0);
+  LoadConstant(rl_result.reg, 0);
   GenBarrier();
 
   StoreValue(rl_dest, rl_result);
@@ -333,8 +338,8 @@
   RegLocation rl_result;
   rl_src = LoadValueWide(rl_src, kFPReg);
   rl_result = EvalLoc(rl_dest, kFPReg, true);
-  NewLIR2(kThumb2Vnegd, S2d(rl_result.reg.GetReg(), rl_result.reg.GetHighReg()),
-          S2d(rl_src.reg.GetReg(), rl_src.reg.GetHighReg()));
+  NewLIR2(kThumb2Vnegd, S2d(rl_result.reg.GetLowReg(), rl_result.reg.GetHighReg()),
+          S2d(rl_src.reg.GetLowReg(), rl_src.reg.GetHighReg()));
   StoreValueWide(rl_dest, rl_result);
 }
 
@@ -345,18 +350,19 @@
   RegLocation rl_dest = InlineTargetWide(info);  // double place for result
   rl_src = LoadValueWide(rl_src, kFPReg);
   RegLocation rl_result = EvalLoc(rl_dest, kFPReg, true);
-  NewLIR2(kThumb2Vsqrtd, S2d(rl_result.reg.GetReg(), rl_result.reg.GetHighReg()),
-          S2d(rl_src.reg.GetReg(), rl_src.reg.GetHighReg()));
-  NewLIR2(kThumb2Vcmpd, S2d(rl_result.reg.GetReg(), rl_result.reg.GetHighReg()),
-          S2d(rl_result.reg.GetReg(), rl_result.reg.GetHighReg()));
+  // TODO: shouldn't need S2d once 64bitSolo has proper double tag bit.
+  NewLIR2(kThumb2Vsqrtd, S2d(rl_result.reg.GetLowReg(), rl_result.reg.GetHighReg()),
+          S2d(rl_src.reg.GetLowReg(), rl_src.reg.GetHighReg()));
+  NewLIR2(kThumb2Vcmpd, S2d(rl_result.reg.GetLowReg(), rl_result.reg.GetHighReg()),
+          S2d(rl_result.reg.GetLowReg(), rl_result.reg.GetHighReg()));
   NewLIR0(kThumb2Fmstat);
   branch = NewLIR2(kThumbBCond, 0, kArmCondEq);
   ClobberCallerSave();
   LockCallTemps();  // Using fixed registers
-  int r_tgt = LoadHelper(QUICK_ENTRYPOINT_OFFSET(pSqrt));
-  NewLIR3(kThumb2Fmrrd, r0, r1, S2d(rl_src.reg.GetReg(), rl_src.reg.GetHighReg()));
-  NewLIR1(kThumbBlxR, r_tgt);
-  NewLIR3(kThumb2Fmdrr, S2d(rl_result.reg.GetReg(), rl_result.reg.GetHighReg()), r0, r1);
+  RegStorage r_tgt = LoadHelper(QUICK_ENTRYPOINT_OFFSET(pSqrt));
+  NewLIR3(kThumb2Fmrrd, r0, r1, S2d(rl_src.reg.GetLowReg(), rl_src.reg.GetHighReg()));
+  NewLIR1(kThumbBlxR, r_tgt.GetReg());
+  NewLIR3(kThumb2Fmdrr, S2d(rl_result.reg.GetLowReg(), rl_result.reg.GetHighReg()), r0, r1);
   branch->target = NewLIR0(kPseudoTargetLabel);
   StoreValueWide(rl_dest, rl_result);
   return true;
diff --git a/compiler/dex/quick/arm/int_arm.cc b/compiler/dex/quick/arm/int_arm.cc
index 93d48d6..46db466 100644
--- a/compiler/dex/quick/arm/int_arm.cc
+++ b/compiler/dex/quick/arm/int_arm.cc
@@ -24,7 +24,7 @@
 
 namespace art {
 
-LIR* ArmMir2Lir::OpCmpBranch(ConditionCode cond, int src1, int src2, LIR* target) {
+LIR* ArmMir2Lir::OpCmpBranch(ConditionCode cond, RegStorage src1, RegStorage src2, LIR* target) {
   OpRegReg(kOpCmp, src1, src2);
   return OpCondBranch(cond, target);
 }
@@ -88,16 +88,16 @@
   LIR* target2;
   rl_src1 = LoadValueWide(rl_src1, kCoreReg);
   rl_src2 = LoadValueWide(rl_src2, kCoreReg);
-  int t_reg = AllocTemp();
+  RegStorage t_reg = AllocTemp();
   LoadConstant(t_reg, -1);
-  OpRegReg(kOpCmp, rl_src1.reg.GetHighReg(), rl_src2.reg.GetHighReg());
+  OpRegReg(kOpCmp, rl_src1.reg.GetHigh(), rl_src2.reg.GetHigh());
   LIR* branch1 = OpCondBranch(kCondLt, NULL);
   LIR* branch2 = OpCondBranch(kCondGt, NULL);
-  OpRegRegReg(kOpSub, t_reg, rl_src1.reg.GetReg(), rl_src2.reg.GetReg());
+  OpRegRegReg(kOpSub, t_reg, rl_src1.reg, rl_src2.reg);
   LIR* branch3 = OpCondBranch(kCondEq, NULL);
 
   OpIT(kCondHi, "E");
-  NewLIR2(kThumb2MovI8M, t_reg, ModifiedImmediate(-1));
+  NewLIR2(kThumb2MovI8M, t_reg.GetReg(), ModifiedImmediate(-1));
   LoadConstant(t_reg, 1);
   GenBarrier();
 
@@ -107,7 +107,7 @@
   target1 = NewLIR0(kPseudoTargetLabel);
 
   RegLocation rl_temp = LocCReturn();  // Just using as template, will change
-  rl_temp.reg.SetReg(t_reg);
+  rl_temp.reg.SetReg(t_reg.GetReg());
   StoreValue(rl_dest, rl_temp);
   FreeTemp(t_reg);
 
@@ -125,12 +125,12 @@
   LIR* taken = &block_label_list_[bb->taken];
   LIR* not_taken = &block_label_list_[bb->fall_through];
   rl_src1 = LoadValueWide(rl_src1, kCoreReg);
-  int32_t low_reg = rl_src1.reg.GetReg();
-  int32_t high_reg = rl_src1.reg.GetHighReg();
+  RegStorage low_reg = rl_src1.reg.GetLow();
+  RegStorage high_reg = rl_src1.reg.GetHigh();
 
   if (val == 0 && (ccode == kCondEq || ccode == kCondNe)) {
-    int t_reg = AllocTemp();
-    NewLIR4(kThumb2OrrRRRs, t_reg, low_reg, high_reg, 0);
+    RegStorage t_reg = AllocTemp();
+    NewLIR4(kThumb2OrrRRRs, t_reg.GetReg(), low_reg.GetReg(), high_reg.GetReg(), 0);
     FreeTemp(t_reg);
     OpCondBranch(ccode, taken);
     return;
@@ -185,33 +185,33 @@
     }
     bool cheap_false_val = InexpensiveConstantInt(false_val);
     if (cheap_false_val && ccode == kCondEq && (true_val == 0 || true_val == -1)) {
-      OpRegRegImm(kOpSub, rl_result.reg.GetReg(), rl_src.reg.GetReg(), -true_val);
+      OpRegRegImm(kOpSub, rl_result.reg, rl_src.reg, -true_val);
       DCHECK(last_lir_insn_->u.m.def_mask & ENCODE_CCODE);
       OpIT(true_val == 0 ? kCondNe : kCondUge, "");
-      LoadConstant(rl_result.reg.GetReg(), false_val);
+      LoadConstant(rl_result.reg, false_val);
       GenBarrier();  // Add a scheduling barrier to keep the IT shadow intact
     } else if (cheap_false_val && ccode == kCondEq && true_val == 1) {
-      OpRegRegImm(kOpRsub, rl_result.reg.GetReg(), rl_src.reg.GetReg(), 1);
+      OpRegRegImm(kOpRsub, rl_result.reg, rl_src.reg, 1);
       DCHECK(last_lir_insn_->u.m.def_mask & ENCODE_CCODE);
       OpIT(kCondLs, "");
-      LoadConstant(rl_result.reg.GetReg(), false_val);
+      LoadConstant(rl_result.reg, false_val);
       GenBarrier();  // Add a scheduling barrier to keep the IT shadow intact
     } else if (cheap_false_val && InexpensiveConstantInt(true_val)) {
-      OpRegImm(kOpCmp, rl_src.reg.GetReg(), 0);
+      OpRegImm(kOpCmp, rl_src.reg, 0);
       OpIT(ccode, "E");
-      LoadConstant(rl_result.reg.GetReg(), true_val);
-      LoadConstant(rl_result.reg.GetReg(), false_val);
+      LoadConstant(rl_result.reg, true_val);
+      LoadConstant(rl_result.reg, false_val);
       GenBarrier();  // Add a scheduling barrier to keep the IT shadow intact
     } else {
       // Unlikely case - could be tuned.
-      int t_reg1 = AllocTemp();
-      int t_reg2 = AllocTemp();
+      RegStorage t_reg1 = AllocTemp();
+      RegStorage t_reg2 = AllocTemp();
       LoadConstant(t_reg1, true_val);
       LoadConstant(t_reg2, false_val);
-      OpRegImm(kOpCmp, rl_src.reg.GetReg(), 0);
+      OpRegImm(kOpCmp, rl_src.reg, 0);
       OpIT(ccode, "E");
-      OpRegCopy(rl_result.reg.GetReg(), t_reg1);
-      OpRegCopy(rl_result.reg.GetReg(), t_reg2);
+      OpRegCopy(rl_result.reg, t_reg1);
+      OpRegCopy(rl_result.reg, t_reg2);
       GenBarrier();  // Add a scheduling barrier to keep the IT shadow intact
     }
   } else {
@@ -221,17 +221,17 @@
     rl_true = LoadValue(rl_true, kCoreReg);
     rl_false = LoadValue(rl_false, kCoreReg);
     rl_result = EvalLoc(rl_dest, kCoreReg, true);
-    OpRegImm(kOpCmp, rl_src.reg.GetReg(), 0);
+    OpRegImm(kOpCmp, rl_src.reg, 0);
     if (rl_result.reg.GetReg() == rl_true.reg.GetReg()) {  // Is the "true" case already in place?
       OpIT(NegateComparison(ccode), "");
-      OpRegCopy(rl_result.reg.GetReg(), rl_false.reg.GetReg());
+      OpRegCopy(rl_result.reg, rl_false.reg);
     } else if (rl_result.reg.GetReg() == rl_false.reg.GetReg()) {  // False case in place?
       OpIT(ccode, "");
-      OpRegCopy(rl_result.reg.GetReg(), rl_true.reg.GetReg());
+      OpRegCopy(rl_result.reg, rl_true.reg);
     } else {  // Normal - select between the two.
       OpIT(ccode, "E");
-      OpRegCopy(rl_result.reg.GetReg(), rl_true.reg.GetReg());
-      OpRegCopy(rl_result.reg.GetReg(), rl_false.reg.GetReg());
+      OpRegCopy(rl_result.reg, rl_true.reg);
+      OpRegCopy(rl_result.reg, rl_false.reg);
     }
     GenBarrier();  // Add a scheduling barrier to keep the IT shadow intact
   }
@@ -261,7 +261,7 @@
   LIR* not_taken = &block_label_list_[bb->fall_through];
   rl_src1 = LoadValueWide(rl_src1, kCoreReg);
   rl_src2 = LoadValueWide(rl_src2, kCoreReg);
-  OpRegReg(kOpCmp, rl_src1.reg.GetHighReg(), rl_src2.reg.GetHighReg());
+  OpRegReg(kOpCmp, rl_src1.reg.GetHigh(), rl_src2.reg.GetHigh());
   switch (ccode) {
     case kCondEq:
       OpCondBranch(kCondNe, not_taken);
@@ -292,7 +292,7 @@
     default:
       LOG(FATAL) << "Unexpected ccode: " << ccode;
   }
-  OpRegReg(kOpCmp, rl_src1.reg.GetReg(), rl_src2.reg.GetReg());
+  OpRegReg(kOpCmp, rl_src1.reg.GetLow(), rl_src2.reg.GetLow());
   OpCondBranch(ccode, taken);
 }
 
@@ -300,8 +300,7 @@
  * Generate a register comparison to an immediate and branch.  Caller
  * is responsible for setting branch target field.
  */
-LIR* ArmMir2Lir::OpCmpImmBranch(ConditionCode cond, int reg, int check_value,
-                                LIR* target) {
+LIR* ArmMir2Lir::OpCmpImmBranch(ConditionCode cond, RegStorage reg, int check_value, LIR* target) {
   LIR* branch;
   ArmConditionCode arm_cond = ArmConditionEncoding(cond);
   /*
@@ -315,10 +314,10 @@
    */
   bool skip = ((target != NULL) && (target->opcode == kPseudoThrowTarget));
   skip &= ((cu_->code_item->insns_size_in_code_units_ - current_dalvik_offset_) > 64);
-  if (!skip && (ARM_LOWREG(reg)) && (check_value == 0) &&
+  if (!skip && (ARM_LOWREG(reg.GetReg())) && (check_value == 0) &&
      ((arm_cond == kArmCondEq) || (arm_cond == kArmCondNe))) {
     branch = NewLIR2((arm_cond == kArmCondEq) ? kThumb2Cbz : kThumb2Cbnz,
-                     reg, 0);
+                     reg.GetReg(), 0);
   } else {
     OpRegImm(kOpCmp, reg, check_value);
     branch = NewLIR2(kThumbBCond, 0, arm_cond);
@@ -327,56 +326,64 @@
   return branch;
 }
 
-LIR* ArmMir2Lir::OpRegCopyNoInsert(int r_dest, int r_src) {
+LIR* ArmMir2Lir::OpRegCopyNoInsert(RegStorage r_dest, RegStorage r_src) {
   LIR* res;
   int opcode;
-  if (ARM_FPREG(r_dest) || ARM_FPREG(r_src))
+  // If src or dest is a pair, we'll be using low reg.
+  if (r_dest.IsPair()) {
+    r_dest = r_dest.GetLow();
+  }
+  if (r_src.IsPair()) {
+    r_src = r_src.GetLow();
+  }
+  if (ARM_FPREG(r_dest.GetReg()) || ARM_FPREG(r_src.GetReg()))
     return OpFpRegCopy(r_dest, r_src);
-  if (ARM_LOWREG(r_dest) && ARM_LOWREG(r_src))
+  if (ARM_LOWREG(r_dest.GetReg()) && ARM_LOWREG(r_src.GetReg()))
     opcode = kThumbMovRR;
-  else if (!ARM_LOWREG(r_dest) && !ARM_LOWREG(r_src))
+  else if (!ARM_LOWREG(r_dest.GetReg()) && !ARM_LOWREG(r_src.GetReg()))
      opcode = kThumbMovRR_H2H;
-  else if (ARM_LOWREG(r_dest))
+  else if (ARM_LOWREG(r_dest.GetReg()))
      opcode = kThumbMovRR_H2L;
   else
      opcode = kThumbMovRR_L2H;
-  res = RawLIR(current_dalvik_offset_, opcode, r_dest, r_src);
+  res = RawLIR(current_dalvik_offset_, opcode, r_dest.GetReg(), r_src.GetReg());
   if (!(cu_->disable_opt & (1 << kSafeOptimizations)) && r_dest == r_src) {
     res->flags.is_nop = true;
   }
   return res;
 }
 
-LIR* ArmMir2Lir::OpRegCopy(int r_dest, int r_src) {
+LIR* ArmMir2Lir::OpRegCopy(RegStorage r_dest, RegStorage r_src) {
   LIR* res = OpRegCopyNoInsert(r_dest, r_src);
   AppendLIR(res);
   return res;
 }
 
-void ArmMir2Lir::OpRegCopyWide(int dest_lo, int dest_hi, int src_lo,
-                               int src_hi) {
-  bool dest_fp = ARM_FPREG(dest_lo) && ARM_FPREG(dest_hi);
-  bool src_fp = ARM_FPREG(src_lo) && ARM_FPREG(src_hi);
-  DCHECK_EQ(ARM_FPREG(src_lo), ARM_FPREG(src_hi));
-  DCHECK_EQ(ARM_FPREG(dest_lo), ARM_FPREG(dest_hi));
+void ArmMir2Lir::OpRegCopyWide(RegStorage r_dest, RegStorage r_src) {
+  bool dest_fp = ARM_FPREG(r_dest.GetLowReg());
+  bool src_fp = ARM_FPREG(r_src.GetLowReg());
   if (dest_fp) {
     if (src_fp) {
-      OpRegCopy(S2d(dest_lo, dest_hi), S2d(src_lo, src_hi));
+      // FIXME: handle 64-bit solo's here.
+      OpRegCopy(RegStorage::Solo64(S2d(r_dest.GetLowReg(), r_dest.GetHighReg())),
+                RegStorage::Solo64(S2d(r_src.GetLowReg(), r_src.GetHighReg())));
     } else {
-      NewLIR3(kThumb2Fmdrr, S2d(dest_lo, dest_hi), src_lo, src_hi);
+      NewLIR3(kThumb2Fmdrr, S2d(r_dest.GetLowReg(), r_dest.GetHighReg()),
+              r_src.GetLowReg(), r_src.GetHighReg());
     }
   } else {
     if (src_fp) {
-      NewLIR3(kThumb2Fmrrd, dest_lo, dest_hi, S2d(src_lo, src_hi));
+      NewLIR3(kThumb2Fmrrd, r_dest.GetLowReg(), r_dest.GetHighReg(), S2d(r_src.GetLowReg(),
+              r_src.GetHighReg()));
     } else {
       // Handle overlap
-      if (src_hi == dest_lo) {
-        DCHECK_NE(src_lo, dest_hi);
-        OpRegCopy(dest_hi, src_hi);
-        OpRegCopy(dest_lo, src_lo);
+      if (r_src.GetHighReg() == r_dest.GetLowReg()) {
+        DCHECK_NE(r_src.GetLowReg(), r_dest.GetHighReg());
+        OpRegCopy(r_dest.GetHigh(), r_src.GetHigh());
+        OpRegCopy(r_dest.GetLow(), r_src.GetLow());
       } else {
-        OpRegCopy(dest_lo, src_lo);
-        OpRegCopy(dest_hi, src_hi);
+        OpRegCopy(r_dest.GetLow(), r_src.GetLow());
+        OpRegCopy(r_dest.GetHigh(), r_src.GetHigh());
       }
     }
   }
@@ -423,27 +430,27 @@
     return false;
   }
 
-  int r_magic = AllocTemp();
+  RegStorage r_magic = AllocTemp();
   LoadConstant(r_magic, magic_table[lit].magic);
   rl_src = LoadValue(rl_src, kCoreReg);
   RegLocation rl_result = EvalLoc(rl_dest, kCoreReg, true);
-  int r_hi = AllocTemp();
-  int r_lo = AllocTemp();
-  NewLIR4(kThumb2Smull, r_lo, r_hi, r_magic, rl_src.reg.GetReg());
+  RegStorage r_hi = AllocTemp();
+  RegStorage r_lo = AllocTemp();
+  NewLIR4(kThumb2Smull, r_lo.GetReg(), r_hi.GetReg(), r_magic.GetReg(), rl_src.reg.GetReg());
   switch (pattern) {
     case Divide3:
-      OpRegRegRegShift(kOpSub, rl_result.reg.GetReg(), r_hi,
+      OpRegRegRegShift(kOpSub, rl_result.reg.GetReg(), r_hi.GetReg(),
                rl_src.reg.GetReg(), EncodeShift(kArmAsr, 31));
       break;
     case Divide5:
-      OpRegRegImm(kOpAsr, r_lo, rl_src.reg.GetReg(), 31);
-      OpRegRegRegShift(kOpRsub, rl_result.reg.GetReg(), r_lo, r_hi,
+      OpRegRegImm(kOpAsr, r_lo, rl_src.reg, 31);
+      OpRegRegRegShift(kOpRsub, rl_result.reg.GetReg(), r_lo.GetReg(), r_hi.GetReg(),
                EncodeShift(kArmAsr, magic_table[lit].shift));
       break;
     case Divide7:
-      OpRegReg(kOpAdd, r_hi, rl_src.reg.GetReg());
-      OpRegRegImm(kOpAsr, r_lo, rl_src.reg.GetReg(), 31);
-      OpRegRegRegShift(kOpRsub, rl_result.reg.GetReg(), r_lo, r_hi,
+      OpRegReg(kOpAdd, r_hi, rl_src.reg);
+      OpRegRegImm(kOpAsr, r_lo, rl_src.reg, 31);
+      OpRegRegRegShift(kOpRsub, rl_result.reg.GetReg(), r_lo.GetReg(), r_hi.GetReg(),
                EncodeShift(kArmAsr, magic_table[lit].shift));
       break;
     default:
@@ -453,8 +460,8 @@
   return true;
 }
 
-LIR* ArmMir2Lir::GenRegMemCheck(ConditionCode c_code,
-                    int reg1, int base, int offset, ThrowKind kind) {
+LIR* ArmMir2Lir::GenRegMemCheck(ConditionCode c_code, RegStorage reg1, RegStorage base,
+                                int offset, ThrowKind kind) {
   LOG(FATAL) << "Unexpected use of GenRegMemCheck for Arm";
   return NULL;
 }
@@ -470,12 +477,11 @@
   return rl_dest;
 }
 
-RegLocation ArmMir2Lir::GenDivRemLit(RegLocation rl_dest, int reg1, int lit,
-                                     bool is_div) {
+RegLocation ArmMir2Lir::GenDivRemLit(RegLocation rl_dest, RegStorage reg1, int lit, bool is_div) {
   RegLocation rl_result = EvalLoc(rl_dest, kCoreReg, true);
 
   // Put the literal in a temp.
-  int lit_temp = AllocTemp();
+  RegStorage lit_temp = AllocTemp();
   LoadConstant(lit_temp, lit);
   // Use the generic case for div/rem with arg2 in a register.
   // TODO: The literal temp can be freed earlier during a modulus to reduce reg pressure.
@@ -485,22 +491,22 @@
   return rl_result;
 }
 
-RegLocation ArmMir2Lir::GenDivRem(RegLocation rl_dest, int reg1, int reg2,
+RegLocation ArmMir2Lir::GenDivRem(RegLocation rl_dest, RegStorage reg1, RegStorage reg2,
                                   bool is_div) {
   RegLocation rl_result = EvalLoc(rl_dest, kCoreReg, true);
   if (is_div) {
     // Simple case, use sdiv instruction.
-    OpRegRegReg(kOpDiv, rl_result.reg.GetReg(), reg1, reg2);
+    OpRegRegReg(kOpDiv, rl_result.reg, reg1, reg2);
   } else {
     // Remainder case, use the following code:
     // temp = reg1 / reg2      - integer division
     // temp = temp * reg2
     // dest = reg1 - temp
 
-    int temp = AllocTemp();
+    RegStorage temp = AllocTemp();
     OpRegRegReg(kOpDiv, temp, reg1, reg2);
     OpRegReg(kOpMul, temp, reg2);
-    OpRegRegReg(kOpSub, rl_result.reg.GetReg(), reg1, temp);
+    OpRegRegReg(kOpSub, rl_result.reg, reg1, temp);
     FreeTemp(temp);
   }
 
@@ -515,10 +521,10 @@
   rl_src2 = LoadValue(rl_src2, kCoreReg);
   RegLocation rl_dest = InlineTarget(info);
   RegLocation rl_result = EvalLoc(rl_dest, kCoreReg, true);
-  OpRegReg(kOpCmp, rl_src1.reg.GetReg(), rl_src2.reg.GetReg());
+  OpRegReg(kOpCmp, rl_src1.reg, rl_src2.reg);
   OpIT((is_min) ? kCondGt : kCondLt, "E");
-  OpRegReg(kOpMov, rl_result.reg.GetReg(), rl_src2.reg.GetReg());
-  OpRegReg(kOpMov, rl_result.reg.GetReg(), rl_src1.reg.GetReg());
+  OpRegReg(kOpMov, rl_result.reg, rl_src2.reg);
+  OpRegReg(kOpMov, rl_result.reg, rl_src1.reg);
   GenBarrier();
   StoreValue(rl_dest, rl_result);
   return true;
@@ -526,24 +532,24 @@
 
 bool ArmMir2Lir::GenInlinedPeek(CallInfo* info, OpSize size) {
   RegLocation rl_src_address = info->args[0];  // long address
-  rl_src_address.wide = 0;  // ignore high half in info->args[1]
+  rl_src_address = NarrowRegLoc(rl_src_address);  // ignore high half in info->args[1]
   RegLocation rl_dest = InlineTarget(info);
   RegLocation rl_address = LoadValue(rl_src_address, kCoreReg);
   RegLocation rl_result = EvalLoc(rl_dest, kCoreReg, true);
   if (size == kLong) {
     // Fake unaligned LDRD by two unaligned LDR instructions on ARMv7 with SCTLR.A set to 0.
-    if (rl_address.reg.GetReg() != rl_result.reg.GetReg()) {
-      LoadBaseDisp(rl_address.reg.GetReg(), 0, rl_result.reg.GetReg(), kWord, INVALID_SREG);
-      LoadBaseDisp(rl_address.reg.GetReg(), 4, rl_result.reg.GetHighReg(), kWord, INVALID_SREG);
+    if (rl_address.reg.GetReg() != rl_result.reg.GetLowReg()) {
+      LoadWordDisp(rl_address.reg, 0, rl_result.reg.GetLow());
+      LoadWordDisp(rl_address.reg, 4, rl_result.reg.GetHigh());
     } else {
-      LoadBaseDisp(rl_address.reg.GetReg(), 4, rl_result.reg.GetHighReg(), kWord, INVALID_SREG);
-      LoadBaseDisp(rl_address.reg.GetReg(), 0, rl_result.reg.GetReg(), kWord, INVALID_SREG);
+      LoadWordDisp(rl_address.reg, 4, rl_result.reg.GetHigh());
+      LoadWordDisp(rl_address.reg, 0, rl_result.reg.GetLow());
     }
     StoreValueWide(rl_dest, rl_result);
   } else {
     DCHECK(size == kSignedByte || size == kSignedHalf || size == kWord);
     // Unaligned load with LDR and LDRSH is allowed on ARMv7 with SCTLR.A set to 0.
-    LoadBaseDisp(rl_address.reg.GetReg(), 0, rl_result.reg.GetReg(), size, INVALID_SREG);
+    LoadBaseDisp(rl_address.reg, 0, rl_result.reg, size, INVALID_SREG);
     StoreValue(rl_dest, rl_result);
   }
   return true;
@@ -551,24 +557,24 @@
 
 bool ArmMir2Lir::GenInlinedPoke(CallInfo* info, OpSize size) {
   RegLocation rl_src_address = info->args[0];  // long address
-  rl_src_address.wide = 0;  // ignore high half in info->args[1]
+  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) {
     // Fake unaligned STRD by two unaligned STR instructions on ARMv7 with SCTLR.A set to 0.
     RegLocation rl_value = LoadValueWide(rl_src_value, kCoreReg);
-    StoreBaseDisp(rl_address.reg.GetReg(), 0, rl_value.reg.GetReg(), kWord);
-    StoreBaseDisp(rl_address.reg.GetReg(), 4, rl_value.reg.GetHighReg(), kWord);
+    StoreBaseDisp(rl_address.reg, 0, rl_value.reg.GetLow(), kWord);
+    StoreBaseDisp(rl_address.reg, 4, rl_value.reg.GetHigh(), kWord);
   } else {
     DCHECK(size == kSignedByte || size == kSignedHalf || size == kWord);
     // Unaligned store with STR and STRSH is allowed on ARMv7 with SCTLR.A set to 0.
     RegLocation rl_value = LoadValue(rl_src_value, kCoreReg);
-    StoreBaseDisp(rl_address.reg.GetReg(), 0, rl_value.reg.GetReg(), size);
+    StoreBaseDisp(rl_address.reg, 0, rl_value.reg, size);
   }
   return true;
 }
 
-void ArmMir2Lir::OpLea(int rBase, int reg1, int reg2, int scale, int offset) {
+void ArmMir2Lir::OpLea(RegStorage r_base, RegStorage reg1, RegStorage reg2, int scale, int offset) {
   LOG(FATAL) << "Unexpected use of OpLea for Arm";
 }
 
@@ -581,7 +587,7 @@
   // Unused - RegLocation rl_src_unsafe = info->args[0];
   RegLocation rl_src_obj = info->args[1];  // Object - known non-null
   RegLocation rl_src_offset = info->args[2];  // long low
-  rl_src_offset.wide = 0;  // ignore high half in info->args[3]
+  rl_src_offset = NarrowRegLoc(rl_src_offset);  // ignore high half in info->args[3]
   RegLocation rl_src_expected = info->args[4];  // int, long or Object
   // If is_long, high half is in info->args[5]
   RegLocation rl_src_new_value = info->args[is_long ? 6 : 5];  // int, long or Object
@@ -602,25 +608,25 @@
   LockTemp(rARM_LR);
   bool load_early = true;
   if (is_long) {
-    bool expected_is_core_reg =
-        rl_src_expected.location == kLocPhysReg && !IsFpReg(rl_src_expected.reg.GetReg());
-    bool new_value_is_core_reg =
-        rl_src_new_value.location == kLocPhysReg && !IsFpReg(rl_src_new_value.reg.GetReg());
-    bool expected_is_good_reg = expected_is_core_reg && !IsTemp(rl_src_expected.reg.GetReg());
-    bool new_value_is_good_reg = new_value_is_core_reg && !IsTemp(rl_src_new_value.reg.GetReg());
+    int expected_reg = is_long ? rl_src_expected.reg.GetLowReg() : rl_src_expected.reg.GetReg();
+    int new_val_reg = is_long ? rl_src_new_value.reg.GetLowReg() : rl_src_new_value.reg.GetReg();
+    bool expected_is_core_reg = rl_src_expected.location == kLocPhysReg && !IsFpReg(expected_reg);
+    bool new_value_is_core_reg = rl_src_new_value.location == kLocPhysReg && !IsFpReg(new_val_reg);
+    bool expected_is_good_reg = expected_is_core_reg && !IsTemp(expected_reg);
+    bool new_value_is_good_reg = new_value_is_core_reg && !IsTemp(new_val_reg);
 
     if (!expected_is_good_reg && !new_value_is_good_reg) {
       // None of expected/new_value is non-temp reg, need to load both late
       load_early = false;
       // Make sure they are not in the temp regs and the load will not be skipped.
       if (expected_is_core_reg) {
-        FlushRegWide(rl_src_expected.reg.GetReg(), rl_src_expected.reg.GetHighReg());
+        FlushRegWide(rl_src_expected.reg);
         ClobberSReg(rl_src_expected.s_reg_low);
         ClobberSReg(GetSRegHi(rl_src_expected.s_reg_low));
         rl_src_expected.location = kLocDalvikFrame;
       }
       if (new_value_is_core_reg) {
-        FlushRegWide(rl_src_new_value.reg.GetReg(), rl_src_new_value.reg.GetHighReg());
+        FlushRegWide(rl_src_new_value.reg);
         ClobberSReg(rl_src_new_value.s_reg_low);
         ClobberSReg(GetSRegHi(rl_src_new_value.s_reg_low));
         rl_src_new_value.location = kLocDalvikFrame;
@@ -641,13 +647,13 @@
 
   if (is_object && !mir_graph_->IsConstantNullRef(rl_new_value)) {
     // Mark card for object assuming new value is stored.
-    MarkGCCard(rl_new_value.reg.GetReg(), rl_object.reg.GetReg());
+    MarkGCCard(rl_new_value.reg, rl_object.reg);
   }
 
   RegLocation rl_offset = LoadValue(rl_src_offset, kCoreReg);
 
-  int r_ptr = rARM_LR;
-  OpRegRegReg(kOpAdd, r_ptr, rl_object.reg.GetReg(), rl_offset.reg.GetReg());
+  RegStorage r_ptr = rs_rARM_LR;
+  OpRegRegReg(kOpAdd, r_ptr, rl_object.reg, rl_offset.reg);
 
   // Free now unneeded rl_object and rl_offset to give more temps.
   ClobberSReg(rl_object.s_reg_low);
@@ -662,8 +668,8 @@
     rl_expected = LoadValueWide(rl_src_expected, kCoreReg);
   } else {
     // NOTE: partially defined rl_expected & rl_new_value - but we just want the regs.
-    int low_reg = AllocTemp();
-    int high_reg = AllocTemp();
+    int low_reg = AllocTemp().GetReg();
+    int high_reg = AllocTemp().GetReg();
     rl_new_value.reg = RegStorage(RegStorage::k64BitPair, low_reg, high_reg);
     rl_expected = rl_new_value;
   }
@@ -673,38 +679,38 @@
   // } while (tmp == 0 && failure([r_ptr] <- r_new_value));
   // result = tmp != 0;
 
-  int r_tmp = AllocTemp();
+  RegStorage r_tmp = AllocTemp();
   LIR* target = NewLIR0(kPseudoTargetLabel);
 
   if (is_long) {
-    int r_tmp_high = AllocTemp();
+    RegStorage r_tmp_high = AllocTemp();
     if (!load_early) {
-      LoadValueDirectWide(rl_src_expected, rl_expected.reg.GetReg(), rl_expected.reg.GetHighReg());
+      LoadValueDirectWide(rl_src_expected, rl_expected.reg);
     }
-    NewLIR3(kThumb2Ldrexd, r_tmp, r_tmp_high, r_ptr);
-    OpRegReg(kOpSub, r_tmp, rl_expected.reg.GetReg());
-    OpRegReg(kOpSub, r_tmp_high, rl_expected.reg.GetHighReg());
+    NewLIR3(kThumb2Ldrexd, r_tmp.GetReg(), r_tmp_high.GetReg(), r_ptr.GetReg());
+    OpRegReg(kOpSub, r_tmp, rl_expected.reg.GetLow());
+    OpRegReg(kOpSub, r_tmp_high, rl_expected.reg.GetHigh());
     if (!load_early) {
-      LoadValueDirectWide(rl_src_new_value, rl_new_value.reg.GetReg(), rl_new_value.reg.GetHighReg());
+      LoadValueDirectWide(rl_src_new_value, rl_new_value.reg);
     }
     // Make sure we use ORR that sets the ccode
-    if (ARM_LOWREG(r_tmp) && ARM_LOWREG(r_tmp_high)) {
-      NewLIR2(kThumbOrr, r_tmp, r_tmp_high);
+    if (ARM_LOWREG(r_tmp.GetReg()) && ARM_LOWREG(r_tmp_high.GetReg())) {
+      NewLIR2(kThumbOrr, r_tmp.GetReg(), r_tmp_high.GetReg());
     } else {
-      NewLIR4(kThumb2OrrRRRs, r_tmp, r_tmp, r_tmp_high, 0);
+      NewLIR4(kThumb2OrrRRRs, r_tmp.GetReg(), r_tmp.GetReg(), r_tmp_high.GetReg(), 0);
     }
     FreeTemp(r_tmp_high);  // Now unneeded
 
     DCHECK(last_lir_insn_->u.m.def_mask & ENCODE_CCODE);
     OpIT(kCondEq, "T");
-    NewLIR4(kThumb2Strexd /* eq */, r_tmp, rl_new_value.reg.GetReg(), rl_new_value.reg.GetHighReg(), r_ptr);
+    NewLIR4(kThumb2Strexd /* eq */, r_tmp.GetReg(), rl_new_value.reg.GetLowReg(), rl_new_value.reg.GetHighReg(), r_ptr.GetReg());
 
   } else {
-    NewLIR3(kThumb2Ldrex, r_tmp, r_ptr, 0);
-    OpRegReg(kOpSub, r_tmp, rl_expected.reg.GetReg());
+    NewLIR3(kThumb2Ldrex, r_tmp.GetReg(), r_ptr.GetReg(), 0);
+    OpRegReg(kOpSub, r_tmp, rl_expected.reg);
     DCHECK(last_lir_insn_->u.m.def_mask & ENCODE_CCODE);
     OpIT(kCondEq, "T");
-    NewLIR4(kThumb2Strex /* eq */, r_tmp, rl_new_value.reg.GetReg(), r_ptr, 0);
+    NewLIR4(kThumb2Strex /* eq */, r_tmp.GetReg(), rl_new_value.reg.GetReg(), r_ptr.GetReg(), 0);
   }
 
   // Still one conditional left from OpIT(kCondEq, "T") from either branch
@@ -712,16 +718,15 @@
   OpCondBranch(kCondEq, target);
 
   if (!load_early) {
-    FreeTemp(rl_expected.reg.GetReg());  // Now unneeded.
-    FreeTemp(rl_expected.reg.GetHighReg());  // Now unneeded.
+    FreeTemp(rl_expected.reg);  // Now unneeded.
   }
 
   // result := (tmp1 != 0) ? 0 : 1;
   RegLocation rl_result = EvalLoc(rl_dest, kCoreReg, true);
-  OpRegRegImm(kOpRsub, rl_result.reg.GetReg(), r_tmp, 1);
+  OpRegRegImm(kOpRsub, rl_result.reg, r_tmp, 1);
   DCHECK(last_lir_insn_->u.m.def_mask & ENCODE_CCODE);
   OpIT(kCondUlt, "");
-  LoadConstant(rl_result.reg.GetReg(), 0); /* cc */
+  LoadConstant(rl_result.reg, 0); /* cc */
   FreeTemp(r_tmp);  // Now unneeded.
 
   StoreValue(rl_dest, rl_result);
@@ -732,16 +737,16 @@
   return true;
 }
 
-LIR* ArmMir2Lir::OpPcRelLoad(int reg, LIR* target) {
-  return RawLIR(current_dalvik_offset_, kThumb2LdrPcRel12, reg, 0, 0, 0, 0, target);
+LIR* ArmMir2Lir::OpPcRelLoad(RegStorage reg, LIR* target) {
+  return RawLIR(current_dalvik_offset_, kThumb2LdrPcRel12, reg.GetReg(), 0, 0, 0, 0, target);
 }
 
-LIR* ArmMir2Lir::OpVldm(int rBase, int count) {
-  return NewLIR3(kThumb2Vldms, rBase, fr0, count);
+LIR* ArmMir2Lir::OpVldm(RegStorage r_base, int count) {
+  return NewLIR3(kThumb2Vldms, r_base.GetReg(), fr0, count);
 }
 
-LIR* ArmMir2Lir::OpVstm(int rBase, int count) {
-  return NewLIR3(kThumb2Vstms, rBase, fr0, count);
+LIR* ArmMir2Lir::OpVstm(RegStorage r_base, int count) {
+  return NewLIR3(kThumb2Vstms, r_base.GetReg(), fr0, count);
 }
 
 void ArmMir2Lir::GenMultiplyByTwoBitMultiplier(RegLocation rl_src,
@@ -750,13 +755,14 @@
   OpRegRegRegShift(kOpAdd, rl_result.reg.GetReg(), rl_src.reg.GetReg(), rl_src.reg.GetReg(),
                    EncodeShift(kArmLsl, second_bit - first_bit));
   if (first_bit != 0) {
-    OpRegRegImm(kOpLsl, rl_result.reg.GetReg(), rl_result.reg.GetReg(), first_bit);
+    OpRegRegImm(kOpLsl, rl_result.reg, rl_result.reg, first_bit);
   }
 }
 
-void ArmMir2Lir::GenDivZeroCheck(int reg_lo, int reg_hi) {
-  int t_reg = AllocTemp();
-  NewLIR4(kThumb2OrrRRRs, t_reg, reg_lo, reg_hi, 0);
+void ArmMir2Lir::GenDivZeroCheck(RegStorage reg) {
+  DCHECK(reg.IsPair());   // TODO: support k64BitSolo.
+  RegStorage t_reg = AllocTemp();
+  NewLIR4(kThumb2OrrRRRs, t_reg.GetReg(), reg.GetLowReg(), reg.GetHighReg(), 0);
   FreeTemp(t_reg);
   GenCheck(kCondEq, kThrowDivZero);
 }
@@ -768,7 +774,7 @@
 }
 
 // Decrement register and branch on condition
-LIR* ArmMir2Lir::OpDecAndBranch(ConditionCode c_code, int reg, LIR* target) {
+LIR* ArmMir2Lir::OpDecAndBranch(ConditionCode c_code, RegStorage reg, LIR* target) {
   // Combine sub & test using sub setflags encoding here
   OpRegRegImm(kOpSub, reg, reg, 1);  // For value == 1, this should set flags.
   DCHECK(last_lir_insn_->u.m.def_mask & ENCODE_CCODE);
@@ -808,17 +814,17 @@
 void ArmMir2Lir::GenNegLong(RegLocation rl_dest, RegLocation rl_src) {
   rl_src = LoadValueWide(rl_src, kCoreReg);
   RegLocation rl_result = EvalLoc(rl_dest, kCoreReg, true);
-  int z_reg = AllocTemp();
+  RegStorage z_reg = AllocTemp();
   LoadConstantNoClobber(z_reg, 0);
   // Check for destructive overlap
-  if (rl_result.reg.GetReg() == rl_src.reg.GetHighReg()) {
-    int t_reg = AllocTemp();
-    OpRegRegReg(kOpSub, rl_result.reg.GetReg(), z_reg, rl_src.reg.GetReg());
-    OpRegRegReg(kOpSbc, rl_result.reg.GetHighReg(), z_reg, t_reg);
+  if (rl_result.reg.GetLowReg() == rl_src.reg.GetHighReg()) {
+    RegStorage t_reg = AllocTemp();
+    OpRegRegReg(kOpSub, rl_result.reg.GetLow(), z_reg, rl_src.reg.GetLow());
+    OpRegRegReg(kOpSbc, rl_result.reg.GetHigh(), z_reg, t_reg);
     FreeTemp(t_reg);
   } else {
-    OpRegRegReg(kOpSub, rl_result.reg.GetReg(), z_reg, rl_src.reg.GetReg());
-    OpRegRegReg(kOpSbc, rl_result.reg.GetHighReg(), z_reg, rl_src.reg.GetHighReg());
+    OpRegRegReg(kOpSub, rl_result.reg.GetLow(), z_reg, rl_src.reg.GetLow());
+    OpRegRegReg(kOpSbc, rl_result.reg.GetHigh(), z_reg, rl_src.reg.GetHigh());
   }
   FreeTemp(z_reg);
   StoreValueWide(rl_dest, rl_result);
@@ -854,19 +860,19 @@
     rl_src2 = LoadValueWide(rl_src2, kCoreReg);
 
     int reg_status = 0;
-    int res_lo = INVALID_REG;
-    int res_hi = INVALID_REG;
-    bool dest_promoted = rl_dest.location == kLocPhysReg && !rl_dest.reg.IsInvalid() &&
-        !IsTemp(rl_dest.reg.GetReg()) && !IsTemp(rl_dest.reg.GetHighReg());
-    bool src1_promoted = !IsTemp(rl_src1.reg.GetReg()) && !IsTemp(rl_src1.reg.GetHighReg());
-    bool src2_promoted = !IsTemp(rl_src2.reg.GetReg()) && !IsTemp(rl_src2.reg.GetHighReg());
+    RegStorage res_lo;
+    RegStorage res_hi;
+    bool dest_promoted = rl_dest.location == kLocPhysReg && rl_dest.reg.Valid() &&
+        !IsTemp(rl_dest.reg.GetLowReg()) && !IsTemp(rl_dest.reg.GetHighReg());
+    bool src1_promoted = !IsTemp(rl_src1.reg.GetLowReg()) && !IsTemp(rl_src1.reg.GetHighReg());
+    bool src2_promoted = !IsTemp(rl_src2.reg.GetLowReg()) && !IsTemp(rl_src2.reg.GetHighReg());
     // Check if rl_dest is *not* either operand and we have enough temp registers.
     if ((rl_dest.s_reg_low != rl_src1.s_reg_low && rl_dest.s_reg_low != rl_src2.s_reg_low) &&
         (dest_promoted || src1_promoted || src2_promoted)) {
       // In this case, we do not need to manually allocate temp registers for result.
       rl_result = EvalLoc(rl_dest, kCoreReg, true);
-      res_lo = rl_result.reg.GetReg();
-      res_hi = rl_result.reg.GetHighReg();
+      res_lo = rl_result.reg.GetLow();
+      res_hi = rl_result.reg.GetHigh();
     } else {
       res_lo = AllocTemp();
       if ((rl_src1.s_reg_low == rl_src2.s_reg_low) || src1_promoted || src2_promoted) {
@@ -883,34 +889,37 @@
     // Temporarily add LR to the temp pool, and assign it to tmp1
     MarkTemp(rARM_LR);
     FreeTemp(rARM_LR);
-    int tmp1 = rARM_LR;
+    RegStorage tmp1 = rs_rARM_LR;
     LockTemp(rARM_LR);
 
-    if (rl_src1.reg.GetReg() == rl_src2.reg.GetReg()) {
-      DCHECK_NE(res_hi, INVALID_REG);
-      DCHECK_NE(res_lo, INVALID_REG);
-      NewLIR3(kThumb2MulRRR, tmp1, rl_src1.reg.GetReg(), rl_src1.reg.GetHighReg());
-      NewLIR4(kThumb2Umull, res_lo, res_hi, rl_src1.reg.GetReg(), rl_src1.reg.GetReg());
-      OpRegRegRegShift(kOpAdd, res_hi, res_hi, tmp1, EncodeShift(kArmLsl, 1));
+    if (rl_src1.reg == rl_src2.reg) {
+      DCHECK(res_hi.Valid());
+      DCHECK(res_lo.Valid());
+      NewLIR3(kThumb2MulRRR, tmp1.GetReg(), rl_src1.reg.GetLowReg(), rl_src1.reg.GetHighReg());
+      NewLIR4(kThumb2Umull, res_lo.GetReg(), res_hi.GetReg(), rl_src1.reg.GetLowReg(),
+              rl_src1.reg.GetLowReg());
+      OpRegRegRegShift(kOpAdd, res_hi.GetReg(), res_hi.GetReg(), tmp1.GetReg(),
+                       EncodeShift(kArmLsl, 1));
     } else {
-      NewLIR3(kThumb2MulRRR, tmp1, rl_src2.reg.GetReg(), rl_src1.reg.GetHighReg());
+      NewLIR3(kThumb2MulRRR, tmp1.GetReg(), rl_src2.reg.GetLowReg(), rl_src1.reg.GetHighReg());
       if (reg_status == 2) {
-        DCHECK_EQ(res_hi, INVALID_REG);
-        DCHECK_NE(rl_src1.reg.GetReg(), rl_src2.reg.GetReg());
+        DCHECK(!res_hi.Valid());
+        DCHECK_NE(rl_src1.reg.GetLowReg(), rl_src2.reg.GetLowReg());
         DCHECK_NE(rl_src1.reg.GetHighReg(), rl_src2.reg.GetHighReg());
         FreeTemp(rl_src1.reg.GetHighReg());
         res_hi = AllocTemp();
       }
-      DCHECK_NE(res_hi, INVALID_REG);
-      DCHECK_NE(res_lo, INVALID_REG);
-      NewLIR4(kThumb2Umull, res_lo, res_hi, rl_src2.reg.GetReg(), rl_src1.reg.GetReg());
-      NewLIR4(kThumb2Mla, tmp1, rl_src1.reg.GetReg(), rl_src2.reg.GetHighReg(), tmp1);
-      NewLIR4(kThumb2AddRRR, res_hi, tmp1, res_hi, 0);
+      DCHECK(res_hi.Valid());
+      DCHECK(res_lo.Valid());
+      NewLIR4(kThumb2Umull, res_lo.GetReg(), res_hi.GetReg(), rl_src2.reg.GetLowReg(),
+              rl_src1.reg.GetLowReg());
+      NewLIR4(kThumb2Mla, tmp1.GetReg(), rl_src1.reg.GetLowReg(), rl_src2.reg.GetHighReg(),
+              tmp1.GetReg());
+      NewLIR4(kThumb2AddRRR, res_hi.GetReg(), tmp1.GetReg(), res_hi.GetReg(), 0);
       if (reg_status == 2) {
         // Clobber rl_src1 since it was corrupted.
-        FreeTemp(rl_src1.reg.GetReg());
-        Clobber(rl_src1.reg.GetReg());
-        Clobber(rl_src1.reg.GetHighReg());
+        FreeTemp(rl_src1.reg);
+        Clobber(rl_src1.reg);
       }
     }
 
@@ -923,8 +932,7 @@
       // We had manually allocated registers for rl_result.
       // Now construct a RegLocation.
       rl_result = GetReturnWide(false);  // Just using as a template.
-      rl_result.reg.SetReg(res_lo);
-      rl_result.reg.SetHighReg(res_hi);
+      rl_result.reg = RegStorage::MakeRegPair(res_lo, res_hi);
     }
 
     StoreValueWide(rl_dest, rl_result);
@@ -982,26 +990,26 @@
   }
 
   /* null object? */
-  GenNullCheck(rl_array.reg.GetReg(), opt_flags);
+  GenNullCheck(rl_array.reg, opt_flags);
 
   bool needs_range_check = (!(opt_flags & MIR_IGNORE_RANGE_CHECK));
-  int reg_len = INVALID_REG;
+  RegStorage reg_len;
   if (needs_range_check) {
     reg_len = AllocTemp();
     /* Get len */
-    LoadWordDisp(rl_array.reg.GetReg(), len_offset, reg_len);
+    LoadWordDisp(rl_array.reg, len_offset, reg_len);
     MarkPossibleNullPointerException(opt_flags);
   } else {
-    ForceImplicitNullCheck(rl_array.reg.GetReg(), opt_flags);
+    ForceImplicitNullCheck(rl_array.reg, opt_flags);
   }
   if (rl_dest.wide || rl_dest.fp || constant_index) {
-    int reg_ptr;
+    RegStorage reg_ptr;
     if (constant_index) {
-      reg_ptr = rl_array.reg.GetReg();  // NOTE: must not alter reg_ptr in constant case.
+      reg_ptr = rl_array.reg;  // NOTE: must not alter reg_ptr in constant case.
     } else {
       // No special indexed operation, lea + load w/ displacement
       reg_ptr = AllocTemp();
-      OpRegRegRegShift(kOpAdd, reg_ptr, rl_array.reg.GetReg(), rl_index.reg.GetReg(),
+      OpRegRegRegShift(kOpAdd, reg_ptr.GetReg(), rl_array.reg.GetReg(), rl_index.reg.GetReg(),
                        EncodeShift(kArmLsl, scale));
       FreeTemp(rl_index.reg.GetReg());
     }
@@ -1011,20 +1019,19 @@
       if (constant_index) {
         GenImmedCheck(kCondLs, reg_len, mir_graph_->ConstantValue(rl_index), kThrowConstantArrayBounds);
       } else {
-        GenRegRegCheck(kCondLs, reg_len, rl_index.reg.GetReg(), kThrowArrayBounds);
+        GenRegRegCheck(kCondLs, reg_len, rl_index.reg, kThrowArrayBounds);
       }
       FreeTemp(reg_len);
     }
     if (rl_dest.wide) {
-      LoadBaseDispWide(reg_ptr, data_offset, rl_result.reg.GetReg(), rl_result.reg.GetHighReg(),
-        INVALID_SREG);
+      LoadBaseDispWide(reg_ptr, data_offset, rl_result.reg, INVALID_SREG);
       MarkPossibleNullPointerException(opt_flags);
       if (!constant_index) {
         FreeTemp(reg_ptr);
       }
       StoreValueWide(rl_dest, rl_result);
     } else {
-      LoadBaseDisp(reg_ptr, data_offset, rl_result.reg.GetReg(), size, INVALID_SREG);
+      LoadBaseDisp(reg_ptr, data_offset, rl_result.reg, size, INVALID_SREG);
       MarkPossibleNullPointerException(opt_flags);
       if (!constant_index) {
         FreeTemp(reg_ptr);
@@ -1033,16 +1040,16 @@
     }
   } else {
     // Offset base, then use indexed load
-    int reg_ptr = AllocTemp();
-    OpRegRegImm(kOpAdd, reg_ptr, rl_array.reg.GetReg(), data_offset);
+    RegStorage reg_ptr = AllocTemp();
+    OpRegRegImm(kOpAdd, reg_ptr, rl_array.reg, data_offset);
     FreeTemp(rl_array.reg.GetReg());
     rl_result = EvalLoc(rl_dest, reg_class, true);
 
     if (needs_range_check) {
-      GenRegRegCheck(kCondUge, rl_index.reg.GetReg(), reg_len, kThrowArrayBounds);
+      GenRegRegCheck(kCondUge, rl_index.reg, reg_len, kThrowArrayBounds);
       FreeTemp(reg_len);
     }
-    LoadBaseIndexed(reg_ptr, rl_index.reg.GetReg(), rl_result.reg.GetReg(), scale, size);
+    LoadBaseIndexed(reg_ptr, rl_index.reg, rl_result.reg, scale, size);
     MarkPossibleNullPointerException(opt_flags);
     FreeTemp(reg_ptr);
     StoreValue(rl_dest, rl_result);
@@ -1076,31 +1083,31 @@
     rl_index = LoadValue(rl_index, kCoreReg);
   }
 
-  int reg_ptr;
+  RegStorage reg_ptr;
   bool allocated_reg_ptr_temp = false;
   if (constant_index) {
-    reg_ptr = rl_array.reg.GetReg();
+    reg_ptr = rl_array.reg;
   } else if (IsTemp(rl_array.reg.GetReg()) && !card_mark) {
     Clobber(rl_array.reg.GetReg());
-    reg_ptr = rl_array.reg.GetReg();
+    reg_ptr = rl_array.reg;
   } else {
     allocated_reg_ptr_temp = true;
     reg_ptr = AllocTemp();
   }
 
   /* null object? */
-  GenNullCheck(rl_array.reg.GetReg(), opt_flags);
+  GenNullCheck(rl_array.reg, opt_flags);
 
   bool needs_range_check = (!(opt_flags & MIR_IGNORE_RANGE_CHECK));
-  int reg_len = INVALID_REG;
+  RegStorage reg_len;
   if (needs_range_check) {
     reg_len = AllocTemp();
     // NOTE: max live temps(4) here.
     /* Get len */
-    LoadWordDisp(rl_array.reg.GetReg(), len_offset, reg_len);
+    LoadWordDisp(rl_array.reg, len_offset, reg_len);
     MarkPossibleNullPointerException(opt_flags);
   } else {
-    ForceImplicitNullCheck(rl_array.reg.GetReg(), opt_flags);
+    ForceImplicitNullCheck(rl_array.reg, opt_flags);
   }
   /* at this point, reg_ptr points to array, 2 live temps */
   if (rl_src.wide || rl_src.fp || constant_index) {
@@ -1110,41 +1117,40 @@
       rl_src = LoadValue(rl_src, reg_class);
     }
     if (!constant_index) {
-      OpRegRegRegShift(kOpAdd, reg_ptr, rl_array.reg.GetReg(), rl_index.reg.GetReg(),
+      OpRegRegRegShift(kOpAdd, reg_ptr.GetReg(), rl_array.reg.GetReg(), rl_index.reg.GetReg(),
                        EncodeShift(kArmLsl, scale));
     }
     if (needs_range_check) {
       if (constant_index) {
         GenImmedCheck(kCondLs, reg_len, mir_graph_->ConstantValue(rl_index), kThrowConstantArrayBounds);
       } else {
-        GenRegRegCheck(kCondLs, reg_len, rl_index.reg.GetReg(), kThrowArrayBounds);
+        GenRegRegCheck(kCondLs, reg_len, rl_index.reg, kThrowArrayBounds);
       }
       FreeTemp(reg_len);
     }
 
     if (rl_src.wide) {
-      StoreBaseDispWide(reg_ptr, data_offset, rl_src.reg.GetReg(), rl_src.reg.GetHighReg());
+      StoreBaseDispWide(reg_ptr, data_offset, rl_src.reg);
     } else {
-      StoreBaseDisp(reg_ptr, data_offset, rl_src.reg.GetReg(), size);
+      StoreBaseDisp(reg_ptr, data_offset, rl_src.reg, size);
     }
     MarkPossibleNullPointerException(opt_flags);
   } else {
     /* reg_ptr -> array data */
-    OpRegRegImm(kOpAdd, reg_ptr, rl_array.reg.GetReg(), data_offset);
+    OpRegRegImm(kOpAdd, reg_ptr, rl_array.reg, data_offset);
     rl_src = LoadValue(rl_src, reg_class);
     if (needs_range_check) {
-      GenRegRegCheck(kCondUge, rl_index.reg.GetReg(), reg_len, kThrowArrayBounds);
+      GenRegRegCheck(kCondUge, rl_index.reg, reg_len, kThrowArrayBounds);
       FreeTemp(reg_len);
     }
-    StoreBaseIndexed(reg_ptr, rl_index.reg.GetReg(), rl_src.reg.GetReg(),
-                     scale, size);
+    StoreBaseIndexed(reg_ptr, rl_index.reg, rl_src.reg, scale, size);
     MarkPossibleNullPointerException(opt_flags);
   }
   if (allocated_reg_ptr_temp) {
     FreeTemp(reg_ptr);
   }
   if (card_mark) {
-    MarkGCCard(rl_src.reg.GetReg(), rl_array.reg.GetReg());
+    MarkGCCard(rl_src.reg, rl_array.reg);
   }
 }
 
@@ -1167,53 +1173,53 @@
     case Instruction::SHL_LONG:
     case Instruction::SHL_LONG_2ADDR:
       if (shift_amount == 1) {
-        OpRegRegReg(kOpAdd, rl_result.reg.GetReg(), rl_src.reg.GetReg(), rl_src.reg.GetReg());
-        OpRegRegReg(kOpAdc, rl_result.reg.GetHighReg(), rl_src.reg.GetHighReg(), rl_src.reg.GetHighReg());
+        OpRegRegReg(kOpAdd, rl_result.reg.GetLow(), rl_src.reg.GetLow(), rl_src.reg.GetLow());
+        OpRegRegReg(kOpAdc, rl_result.reg.GetHigh(), rl_src.reg.GetHigh(), rl_src.reg.GetHigh());
       } else if (shift_amount == 32) {
-        OpRegCopy(rl_result.reg.GetHighReg(), rl_src.reg.GetReg());
-        LoadConstant(rl_result.reg.GetReg(), 0);
+        OpRegCopy(rl_result.reg.GetHigh(), rl_src.reg);
+        LoadConstant(rl_result.reg.GetLow(), 0);
       } else if (shift_amount > 31) {
-        OpRegRegImm(kOpLsl, rl_result.reg.GetHighReg(), rl_src.reg.GetReg(), shift_amount - 32);
-        LoadConstant(rl_result.reg.GetReg(), 0);
+        OpRegRegImm(kOpLsl, rl_result.reg.GetHigh(), rl_src.reg.GetLow(), shift_amount - 32);
+        LoadConstant(rl_result.reg.GetLow(), 0);
       } else {
-        OpRegRegImm(kOpLsl, rl_result.reg.GetHighReg(), rl_src.reg.GetHighReg(), shift_amount);
-        OpRegRegRegShift(kOpOr, rl_result.reg.GetHighReg(), rl_result.reg.GetHighReg(), rl_src.reg.GetReg(),
+        OpRegRegImm(kOpLsl, rl_result.reg.GetHigh(), rl_src.reg.GetHigh(), shift_amount);
+        OpRegRegRegShift(kOpOr, rl_result.reg.GetHighReg(), rl_result.reg.GetHighReg(), rl_src.reg.GetLowReg(),
                          EncodeShift(kArmLsr, 32 - shift_amount));
-        OpRegRegImm(kOpLsl, rl_result.reg.GetReg(), rl_src.reg.GetReg(), shift_amount);
+        OpRegRegImm(kOpLsl, rl_result.reg.GetLow(), rl_src.reg.GetLow(), shift_amount);
       }
       break;
     case Instruction::SHR_LONG:
     case Instruction::SHR_LONG_2ADDR:
       if (shift_amount == 32) {
-        OpRegCopy(rl_result.reg.GetReg(), rl_src.reg.GetHighReg());
-        OpRegRegImm(kOpAsr, rl_result.reg.GetHighReg(), rl_src.reg.GetHighReg(), 31);
+        OpRegCopy(rl_result.reg.GetLow(), rl_src.reg.GetHigh());
+        OpRegRegImm(kOpAsr, rl_result.reg.GetHigh(), rl_src.reg.GetHigh(), 31);
       } else if (shift_amount > 31) {
-        OpRegRegImm(kOpAsr, rl_result.reg.GetReg(), rl_src.reg.GetHighReg(), shift_amount - 32);
-        OpRegRegImm(kOpAsr, rl_result.reg.GetHighReg(), rl_src.reg.GetHighReg(), 31);
+        OpRegRegImm(kOpAsr, rl_result.reg.GetLow(), rl_src.reg.GetHigh(), shift_amount - 32);
+        OpRegRegImm(kOpAsr, rl_result.reg.GetHigh(), rl_src.reg.GetHigh(), 31);
       } else {
-        int t_reg = AllocTemp();
-        OpRegRegImm(kOpLsr, t_reg, rl_src.reg.GetReg(), shift_amount);
-        OpRegRegRegShift(kOpOr, rl_result.reg.GetReg(), t_reg, rl_src.reg.GetHighReg(),
+        RegStorage t_reg = AllocTemp();
+        OpRegRegImm(kOpLsr, t_reg, rl_src.reg.GetLow(), shift_amount);
+        OpRegRegRegShift(kOpOr, rl_result.reg.GetLowReg(), t_reg.GetReg(), rl_src.reg.GetHighReg(),
                          EncodeShift(kArmLsl, 32 - shift_amount));
         FreeTemp(t_reg);
-        OpRegRegImm(kOpAsr, rl_result.reg.GetHighReg(), rl_src.reg.GetHighReg(), shift_amount);
+        OpRegRegImm(kOpAsr, rl_result.reg.GetHigh(), rl_src.reg.GetHigh(), shift_amount);
       }
       break;
     case Instruction::USHR_LONG:
     case Instruction::USHR_LONG_2ADDR:
       if (shift_amount == 32) {
-        OpRegCopy(rl_result.reg.GetReg(), rl_src.reg.GetHighReg());
-        LoadConstant(rl_result.reg.GetHighReg(), 0);
+        OpRegCopy(rl_result.reg.GetLow(), rl_src.reg.GetHigh());
+        LoadConstant(rl_result.reg.GetHigh(), 0);
       } else if (shift_amount > 31) {
-        OpRegRegImm(kOpLsr, rl_result.reg.GetReg(), rl_src.reg.GetHighReg(), shift_amount - 32);
-        LoadConstant(rl_result.reg.GetHighReg(), 0);
+        OpRegRegImm(kOpLsr, rl_result.reg.GetLow(), rl_src.reg.GetHigh(), shift_amount - 32);
+        LoadConstant(rl_result.reg.GetHigh(), 0);
       } else {
-        int t_reg = AllocTemp();
-        OpRegRegImm(kOpLsr, t_reg, rl_src.reg.GetReg(), shift_amount);
-        OpRegRegRegShift(kOpOr, rl_result.reg.GetReg(), t_reg, rl_src.reg.GetHighReg(),
+        RegStorage t_reg = AllocTemp();
+        OpRegRegImm(kOpLsr, t_reg, rl_src.reg.GetLow(), shift_amount);
+        OpRegRegRegShift(kOpOr, rl_result.reg.GetLowReg(), t_reg.GetReg(), rl_src.reg.GetHighReg(),
                          EncodeShift(kArmLsl, 32 - shift_amount));
         FreeTemp(t_reg);
-        OpRegRegImm(kOpLsr, rl_result.reg.GetHighReg(), rl_src.reg.GetHighReg(), shift_amount);
+        OpRegRegImm(kOpLsr, rl_result.reg.GetHigh(), rl_src.reg.GetHigh(), shift_amount);
       }
       break;
     default:
@@ -1268,35 +1274,35 @@
   switch (opcode) {
     case Instruction::ADD_LONG:
     case Instruction::ADD_LONG_2ADDR:
-      NewLIR3(kThumb2AddRRI8M, rl_result.reg.GetReg(), rl_src1.reg.GetReg(), mod_imm_lo);
+      NewLIR3(kThumb2AddRRI8M, rl_result.reg.GetLowReg(), rl_src1.reg.GetLowReg(), mod_imm_lo);
       NewLIR3(kThumb2AdcRRI8M, rl_result.reg.GetHighReg(), rl_src1.reg.GetHighReg(), mod_imm_hi);
       break;
     case Instruction::OR_LONG:
     case Instruction::OR_LONG_2ADDR:
-      if ((val_lo != 0) || (rl_result.reg.GetReg() != rl_src1.reg.GetReg())) {
-        OpRegRegImm(kOpOr, rl_result.reg.GetReg(), rl_src1.reg.GetReg(), val_lo);
+      if ((val_lo != 0) || (rl_result.reg.GetLowReg() != rl_src1.reg.GetLowReg())) {
+        OpRegRegImm(kOpOr, rl_result.reg.GetLow(), rl_src1.reg.GetLow(), val_lo);
       }
       if ((val_hi != 0) || (rl_result.reg.GetHighReg() != rl_src1.reg.GetHighReg())) {
-        OpRegRegImm(kOpOr, rl_result.reg.GetHighReg(), rl_src1.reg.GetHighReg(), val_hi);
+        OpRegRegImm(kOpOr, rl_result.reg.GetHigh(), rl_src1.reg.GetHigh(), val_hi);
       }
       break;
     case Instruction::XOR_LONG:
     case Instruction::XOR_LONG_2ADDR:
-      OpRegRegImm(kOpXor, rl_result.reg.GetReg(), rl_src1.reg.GetReg(), val_lo);
-      OpRegRegImm(kOpXor, rl_result.reg.GetHighReg(), rl_src1.reg.GetHighReg(), val_hi);
+      OpRegRegImm(kOpXor, rl_result.reg.GetLow(), rl_src1.reg.GetLow(), val_lo);
+      OpRegRegImm(kOpXor, rl_result.reg.GetHigh(), rl_src1.reg.GetHigh(), val_hi);
       break;
     case Instruction::AND_LONG:
     case Instruction::AND_LONG_2ADDR:
-      if ((val_lo != 0xffffffff) || (rl_result.reg.GetReg() != rl_src1.reg.GetReg())) {
-        OpRegRegImm(kOpAnd, rl_result.reg.GetReg(), rl_src1.reg.GetReg(), val_lo);
+      if ((val_lo != 0xffffffff) || (rl_result.reg.GetLowReg() != rl_src1.reg.GetLowReg())) {
+        OpRegRegImm(kOpAnd, rl_result.reg.GetLow(), rl_src1.reg.GetLow(), val_lo);
       }
       if ((val_hi != 0xffffffff) || (rl_result.reg.GetHighReg() != rl_src1.reg.GetHighReg())) {
-        OpRegRegImm(kOpAnd, rl_result.reg.GetHighReg(), rl_src1.reg.GetHighReg(), val_hi);
+        OpRegRegImm(kOpAnd, rl_result.reg.GetHigh(), rl_src1.reg.GetHigh(), val_hi);
       }
       break;
     case Instruction::SUB_LONG_2ADDR:
     case Instruction::SUB_LONG:
-      NewLIR3(kThumb2SubRRI8M, rl_result.reg.GetReg(), rl_src1.reg.GetReg(), mod_imm_lo);
+      NewLIR3(kThumb2SubRRI8M, rl_result.reg.GetLowReg(), rl_src1.reg.GetLowReg(), mod_imm_lo);
       NewLIR3(kThumb2SbcRRI8M, rl_result.reg.GetHighReg(), rl_src1.reg.GetHighReg(), mod_imm_hi);
       break;
     default:
diff --git a/compiler/dex/quick/arm/target_arm.cc b/compiler/dex/quick/arm/target_arm.cc
index 7f8656a..5bab0e3 100644
--- a/compiler/dex/quick/arm/target_arm.cc
+++ b/compiler/dex/quick/arm/target_arm.cc
@@ -53,43 +53,43 @@
 }
 
 // Return a target-dependent special register.
-int ArmMir2Lir::TargetReg(SpecialTargetRegister reg) {
-  int res = INVALID_REG;
+RegStorage ArmMir2Lir::TargetReg(SpecialTargetRegister reg) {
+  int res_reg = RegStorage::kInvalidRegVal;
   switch (reg) {
-    case kSelf: res = rARM_SELF; break;
-    case kSuspend: res =  rARM_SUSPEND; break;
-    case kLr: res =  rARM_LR; break;
-    case kPc: res =  rARM_PC; break;
-    case kSp: res =  rARM_SP; break;
-    case kArg0: res = rARM_ARG0; break;
-    case kArg1: res = rARM_ARG1; break;
-    case kArg2: res = rARM_ARG2; break;
-    case kArg3: res = rARM_ARG3; break;
-    case kFArg0: res = rARM_FARG0; break;
-    case kFArg1: res = rARM_FARG1; break;
-    case kFArg2: res = rARM_FARG2; break;
-    case kFArg3: res = rARM_FARG3; break;
-    case kRet0: res = rARM_RET0; break;
-    case kRet1: res = rARM_RET1; break;
-    case kInvokeTgt: res = rARM_INVOKE_TGT; break;
-    case kHiddenArg: res = r12; break;
-    case kHiddenFpArg: res = INVALID_REG; break;
-    case kCount: res = rARM_COUNT; break;
+    case kSelf: res_reg = rARM_SELF; break;
+    case kSuspend: res_reg =  rARM_SUSPEND; break;
+    case kLr: res_reg =  rARM_LR; break;
+    case kPc: res_reg =  rARM_PC; break;
+    case kSp: res_reg =  rARM_SP; break;
+    case kArg0: res_reg = rARM_ARG0; break;
+    case kArg1: res_reg = rARM_ARG1; break;
+    case kArg2: res_reg = rARM_ARG2; break;
+    case kArg3: res_reg = rARM_ARG3; break;
+    case kFArg0: res_reg = rARM_FARG0; break;
+    case kFArg1: res_reg = rARM_FARG1; break;
+    case kFArg2: res_reg = rARM_FARG2; break;
+    case kFArg3: res_reg = rARM_FARG3; break;
+    case kRet0: res_reg = rARM_RET0; break;
+    case kRet1: res_reg = rARM_RET1; break;
+    case kInvokeTgt: res_reg = rARM_INVOKE_TGT; break;
+    case kHiddenArg: res_reg = r12; break;
+    case kHiddenFpArg: res_reg = RegStorage::kInvalidRegVal; break;
+    case kCount: res_reg = rARM_COUNT; break;
   }
-  return res;
+  return RegStorage::Solo32(res_reg);
 }
 
-int ArmMir2Lir::GetArgMappingToPhysicalReg(int arg_num) {
+RegStorage ArmMir2Lir::GetArgMappingToPhysicalReg(int arg_num) {
   // For the 32-bit internal ABI, the first 3 arguments are passed in registers.
   switch (arg_num) {
     case 0:
-      return rARM_ARG1;
+      return rs_rARM_ARG1;
     case 1:
-      return rARM_ARG2;
+      return rs_rARM_ARG2;
     case 2:
-      return rARM_ARG3;
+      return rs_rARM_ARG3;
     default:
-      return INVALID_REG;
+      return RegStorage::InvalidReg();
   }
 }
 
@@ -528,20 +528,16 @@
 
 // Alloc a pair of core registers, or a double.
 RegStorage ArmMir2Lir::AllocTypedTempWide(bool fp_hint, int reg_class) {
-  int high_reg;
-  int low_reg;
-
   if (((reg_class == kAnyReg) && fp_hint) || (reg_class == kFPReg)) {
-    low_reg = AllocTempDouble();
-    high_reg = low_reg + 1;
+    return AllocTempDouble();
   } else {
-    low_reg = AllocTemp();
-    high_reg = AllocTemp();
+    RegStorage low_reg = AllocTemp();
+    RegStorage high_reg = AllocTemp();
+    return RegStorage::MakeRegPair(low_reg, high_reg);
   }
-  return RegStorage(RegStorage::k64BitPair, low_reg, high_reg);
 }
 
-int ArmMir2Lir::AllocTypedTemp(bool fp_hint, int reg_class) {
+RegStorage ArmMir2Lir::AllocTypedTemp(bool fp_hint, int reg_class) {
   if (((reg_class == kAnyReg) && fp_hint) || (reg_class == kFPReg))
     return AllocTempFloat();
   return AllocTemp();
@@ -583,15 +579,18 @@
   reg_pool_->next_core_reg = r2;
 }
 
-void ArmMir2Lir::FreeRegLocTemps(RegLocation rl_keep,
-                     RegLocation rl_free) {
-  if ((rl_free.reg.GetReg() != rl_keep.reg.GetReg()) && (rl_free.reg.GetReg() != rl_keep.reg.GetHighReg()) &&
-    (rl_free.reg.GetHighReg() != rl_keep.reg.GetReg()) && (rl_free.reg.GetHighReg() != rl_keep.reg.GetHighReg())) {
-    // No overlap, free both
-    FreeTemp(rl_free.reg.GetReg());
-    FreeTemp(rl_free.reg.GetHighReg());
+void ArmMir2Lir::FreeRegLocTemps(RegLocation rl_keep, RegLocation rl_free) {
+  DCHECK(rl_keep.wide);
+  DCHECK(rl_free.wide);
+  if ((rl_free.reg.GetLowReg() != rl_keep.reg.GetLowReg()) &&
+      (rl_free.reg.GetLowReg() != rl_keep.reg.GetHighReg()) &&
+      (rl_free.reg.GetHighReg() != rl_keep.reg.GetLowReg()) &&
+      (rl_free.reg.GetHighReg() != rl_keep.reg.GetHighReg())) {
+    // No overlap, free.
+    FreeTemp(rl_free.reg);
   }
 }
+
 /*
  * TUNING: is true leaf?  Can't just use METHOD_IS_LEAF to determine as some
  * instructions might call out to C/assembly helper functions.  Until
@@ -624,9 +623,9 @@
   fp_spill_mask_ = ((1 << num_fp_spills_) - 1) << ARM_FP_CALLEE_SAVE_BASE;
 }
 
-void ArmMir2Lir::FlushRegWide(int reg1, int reg2) {
-  RegisterInfo* info1 = GetRegInfo(reg1);
-  RegisterInfo* info2 = GetRegInfo(reg2);
+void ArmMir2Lir::FlushRegWide(RegStorage reg) {
+  RegisterInfo* info1 = GetRegInfo(reg.GetLowReg());
+  RegisterInfo* info2 = GetRegInfo(reg.GetHighReg());
   DCHECK(info1 && info2 && info1->pair && info2->pair &&
        (info1->partner == info2->reg) &&
        (info2->partner == info1->reg));
@@ -642,16 +641,18 @@
       mir_graph_->SRegToVReg(info1->s_reg))
       info1 = info2;
     int v_reg = mir_graph_->SRegToVReg(info1->s_reg);
-    StoreBaseDispWide(rARM_SP, VRegOffset(v_reg), info1->reg, info1->partner);
+    StoreBaseDispWide(rs_rARM_SP, VRegOffset(v_reg),
+                      RegStorage(RegStorage::k64BitPair, info1->reg, info1->partner));
   }
 }
 
-void ArmMir2Lir::FlushReg(int reg) {
-  RegisterInfo* info = GetRegInfo(reg);
+void ArmMir2Lir::FlushReg(RegStorage 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(rARM_SP, VRegOffset(v_reg), reg, kWord);
+    StoreBaseDisp(rs_rARM_SP, VRegOffset(v_reg), reg, kWord);
   }
 }
 
@@ -660,6 +661,10 @@
   return ARM_FPREG(reg);
 }
 
+bool ArmMir2Lir::IsFpReg(RegStorage reg) {
+  return IsFpReg(reg.IsPair() ? reg.GetLowReg() : reg.GetReg());
+}
+
 /* Clobber all regs that might be used by an external C call */
 void ArmMir2Lir::ClobberCallerSave() {
   Clobber(r0);
@@ -694,7 +699,7 @@
   Clobber(r3);
   MarkInUse(r2);
   MarkInUse(r3);
-  MarkPair(res.reg.GetReg(), res.reg.GetHighReg());
+  MarkPair(res.reg.GetLowReg(), res.reg.GetHighReg());
   return res;
 }
 
@@ -722,14 +727,14 @@
   FreeTemp(r3);
 }
 
-int ArmMir2Lir::LoadHelper(ThreadOffset offset) {
-  LoadWordDisp(rARM_SELF, offset.Int32Value(), rARM_LR);
-  return rARM_LR;
+RegStorage ArmMir2Lir::LoadHelper(ThreadOffset offset) {
+  LoadWordDisp(rs_rARM_SELF, offset.Int32Value(), rs_rARM_LR);
+  return rs_rARM_LR;
 }
 
 LIR* ArmMir2Lir::CheckSuspendUsingLoad() {
-  int tmp = r0;
-  LoadWordDisp(rARM_SELF, Thread::ThreadSuspendTriggerOffset().Int32Value(), tmp);
+  RegStorage tmp = rs_r0;
+  LoadWordDisp(rs_rARM_SELF, Thread::ThreadSuspendTriggerOffset().Int32Value(), tmp);
   LIR* load2 = LoadWordDisp(tmp, 0, tmp);
   return load2;
 }
diff --git a/compiler/dex/quick/arm/utility_arm.cc b/compiler/dex/quick/arm/utility_arm.cc
index 1a7f2fc..1ec0a2c 100644
--- a/compiler/dex/quick/arm/utility_arm.cc
+++ b/compiler/dex/quick/arm/utility_arm.cc
@@ -169,37 +169,37 @@
  * 1) r_dest is freshly returned from AllocTemp or
  * 2) The codegen is under fixed register usage
  */
-LIR* ArmMir2Lir::LoadConstantNoClobber(int r_dest, int value) {
+LIR* ArmMir2Lir::LoadConstantNoClobber(RegStorage r_dest, int value) {
   LIR* res;
   int mod_imm;
 
-  if (ARM_FPREG(r_dest)) {
-    return LoadFPConstantValue(r_dest, value);
+  if (ARM_FPREG(r_dest.GetReg())) {
+    return LoadFPConstantValue(r_dest.GetReg(), value);
   }
 
   /* See if the value can be constructed cheaply */
-  if (ARM_LOWREG(r_dest) && (value >= 0) && (value <= 255)) {
-    return NewLIR2(kThumbMovImm, r_dest, value);
+  if (ARM_LOWREG(r_dest.GetReg()) && (value >= 0) && (value <= 255)) {
+    return NewLIR2(kThumbMovImm, r_dest.GetReg(), value);
   }
   /* Check Modified immediate special cases */
   mod_imm = ModifiedImmediate(value);
   if (mod_imm >= 0) {
-    res = NewLIR2(kThumb2MovI8M, r_dest, mod_imm);
+    res = NewLIR2(kThumb2MovI8M, r_dest.GetReg(), mod_imm);
     return res;
   }
   mod_imm = ModifiedImmediate(~value);
   if (mod_imm >= 0) {
-    res = NewLIR2(kThumb2MvnI8M, r_dest, mod_imm);
+    res = NewLIR2(kThumb2MvnI8M, r_dest.GetReg(), mod_imm);
     return res;
   }
   /* 16-bit immediate? */
   if ((value & 0xffff) == value) {
-    res = NewLIR2(kThumb2MovImm16, r_dest, value);
+    res = NewLIR2(kThumb2MovImm16, r_dest.GetReg(), value);
     return res;
   }
   /* Do a low/high pair */
-  res = NewLIR2(kThumb2MovImm16, r_dest, Low16Bits(value));
-  NewLIR2(kThumb2MovImm16H, r_dest, High16Bits(value));
+  res = NewLIR2(kThumb2MovImm16, r_dest.GetReg(), Low16Bits(value));
+  NewLIR2(kThumb2MovImm16H, r_dest.GetReg(), High16Bits(value));
   return res;
 }
 
@@ -219,7 +219,7 @@
   return branch;
 }
 
-LIR* ArmMir2Lir::OpReg(OpKind op, int r_dest_src) {
+LIR* ArmMir2Lir::OpReg(OpKind op, RegStorage r_dest_src) {
   ArmOpcode opcode = kThumbBkpt;
   switch (op) {
     case kOpBlx:
@@ -231,7 +231,7 @@
     default:
       LOG(FATAL) << "Bad opcode " << op;
   }
-  return NewLIR1(opcode, r_dest_src);
+  return NewLIR1(opcode, r_dest_src.GetReg());
 }
 
 LIR* ArmMir2Lir::OpRegRegShift(OpKind op, int r_dest_src1, int r_src2,
@@ -366,21 +366,21 @@
   }
 }
 
-LIR* ArmMir2Lir::OpRegReg(OpKind op, int r_dest_src1, int r_src2) {
-  return OpRegRegShift(op, r_dest_src1, r_src2, 0);
+LIR* ArmMir2Lir::OpRegReg(OpKind op, RegStorage r_dest_src1, RegStorage r_src2) {
+  return OpRegRegShift(op, r_dest_src1.GetReg(), r_src2.GetReg(), 0);
 }
 
-LIR* ArmMir2Lir::OpMovRegMem(int r_dest, int r_base, int offset, MoveType move_type) {
+LIR* ArmMir2Lir::OpMovRegMem(RegStorage r_dest, RegStorage r_base, int offset, MoveType move_type) {
   UNIMPLEMENTED(FATAL);
   return nullptr;
 }
 
-LIR* ArmMir2Lir::OpMovMemReg(int r_base, int offset, int r_src, MoveType move_type) {
+LIR* ArmMir2Lir::OpMovMemReg(RegStorage r_base, int offset, RegStorage r_src, MoveType move_type) {
   UNIMPLEMENTED(FATAL);
   return nullptr;
 }
 
-LIR* ArmMir2Lir::OpCondRegReg(OpKind op, ConditionCode cc, int r_dest, int r_src) {
+LIR* ArmMir2Lir::OpCondRegReg(OpKind op, ConditionCode cc, RegStorage r_dest, RegStorage r_src) {
   LOG(FATAL) << "Unexpected use of OpCondRegReg for Arm";
   return NULL;
 }
@@ -455,44 +455,44 @@
   }
 }
 
-LIR* ArmMir2Lir::OpRegRegReg(OpKind op, int r_dest, int r_src1, int r_src2) {
-  return OpRegRegRegShift(op, r_dest, r_src1, r_src2, 0);
+LIR* ArmMir2Lir::OpRegRegReg(OpKind op, RegStorage r_dest, RegStorage r_src1, RegStorage r_src2) {
+  return OpRegRegRegShift(op, r_dest.GetReg(), r_src1.GetReg(), r_src2.GetReg(), 0);
 }
 
-LIR* ArmMir2Lir::OpRegRegImm(OpKind op, int r_dest, int r_src1, int value) {
+LIR* ArmMir2Lir::OpRegRegImm(OpKind op, RegStorage r_dest, RegStorage r_src1, int value) {
   LIR* res;
   bool neg = (value < 0);
   int32_t abs_value = (neg) ? -value : value;
   ArmOpcode opcode = kThumbBkpt;
   ArmOpcode alt_opcode = kThumbBkpt;
-  bool all_low_regs = (ARM_LOWREG(r_dest) && ARM_LOWREG(r_src1));
+  bool all_low_regs = (ARM_LOWREG(r_dest.GetReg()) && ARM_LOWREG(r_src1.GetReg()));
   int32_t mod_imm = ModifiedImmediate(value);
 
   switch (op) {
     case kOpLsl:
       if (all_low_regs)
-        return NewLIR3(kThumbLslRRI5, r_dest, r_src1, value);
+        return NewLIR3(kThumbLslRRI5, r_dest.GetReg(), r_src1.GetReg(), value);
       else
-        return NewLIR3(kThumb2LslRRI5, r_dest, r_src1, value);
+        return NewLIR3(kThumb2LslRRI5, r_dest.GetReg(), r_src1.GetReg(), value);
     case kOpLsr:
       if (all_low_regs)
-        return NewLIR3(kThumbLsrRRI5, r_dest, r_src1, value);
+        return NewLIR3(kThumbLsrRRI5, r_dest.GetReg(), r_src1.GetReg(), value);
       else
-        return NewLIR3(kThumb2LsrRRI5, r_dest, r_src1, value);
+        return NewLIR3(kThumb2LsrRRI5, r_dest.GetReg(), r_src1.GetReg(), value);
     case kOpAsr:
       if (all_low_regs)
-        return NewLIR3(kThumbAsrRRI5, r_dest, r_src1, value);
+        return NewLIR3(kThumbAsrRRI5, r_dest.GetReg(), r_src1.GetReg(), value);
       else
-        return NewLIR3(kThumb2AsrRRI5, r_dest, r_src1, value);
+        return NewLIR3(kThumb2AsrRRI5, r_dest.GetReg(), r_src1.GetReg(), value);
     case kOpRor:
-      return NewLIR3(kThumb2RorRRI5, r_dest, r_src1, value);
+      return NewLIR3(kThumb2RorRRI5, r_dest.GetReg(), r_src1.GetReg(), value);
     case kOpAdd:
-      if (ARM_LOWREG(r_dest) && (r_src1 == r13sp) &&
+      if (ARM_LOWREG(r_dest.GetReg()) && (r_src1 == rs_r13sp) &&
         (value <= 1020) && ((value & 0x3) == 0)) {
-        return NewLIR3(kThumbAddSpRel, r_dest, r_src1, value >> 2);
-      } else if (ARM_LOWREG(r_dest) && (r_src1 == r15pc) &&
+        return NewLIR3(kThumbAddSpRel, r_dest.GetReg(), r_src1.GetReg(), value >> 2);
+      } else if (ARM_LOWREG(r_dest.GetReg()) && (r_src1 == rs_r15pc) &&
           (value <= 1020) && ((value & 0x3) == 0)) {
-        return NewLIR3(kThumbAddPcRel, r_dest, r_src1, value >> 2);
+        return NewLIR3(kThumbAddPcRel, r_dest.GetReg(), r_src1.GetReg(), value >> 2);
       }
       // Note: intentional fallthrough
     case kOpSub:
@@ -501,7 +501,7 @@
           opcode = (neg) ? kThumbSubRRI3 : kThumbAddRRI3;
         else
           opcode = (neg) ? kThumbAddRRI3 : kThumbSubRRI3;
-        return NewLIR3(opcode, r_dest, r_src1, abs_value);
+        return NewLIR3(opcode, r_dest.GetReg(), r_src1.GetReg(), abs_value);
       }
       if (mod_imm < 0) {
         mod_imm = ModifiedImmediate(-value);
@@ -516,7 +516,7 @@
           opcode = (neg) ? kThumb2SubRRI12 : kThumb2AddRRI12;
         else
           opcode = (neg) ? kThumb2AddRRI12 : kThumb2SubRRI12;
-        return NewLIR3(opcode, r_dest, r_src1, abs_value);
+        return NewLIR3(opcode, r_dest.GetReg(), r_src1.GetReg(), abs_value);
       }
       if (op == kOpSub) {
         opcode = kThumb2SubRRI8M;
@@ -546,7 +546,7 @@
       if (mod_imm < 0) {
         mod_imm = ModifiedImmediate(~value);
         if (mod_imm >= 0) {
-          return NewLIR3(kThumb2BicRRI8M, r_dest, r_src1, mod_imm);
+          return NewLIR3(kThumb2BicRRI8M, r_dest.GetReg(), r_src1.GetReg(), mod_imm);
         }
       }
       opcode = kThumb2AndRRI8M;
@@ -564,13 +564,13 @@
     case kOpCmp: {
       LIR* res;
       if (mod_imm >= 0) {
-        res = NewLIR2(kThumb2CmpRI8M, r_src1, mod_imm);
+        res = NewLIR2(kThumb2CmpRI8M, r_src1.GetReg(), mod_imm);
       } else {
         mod_imm = ModifiedImmediate(-value);
         if (mod_imm >= 0) {
-          res = NewLIR2(kThumb2CmnRI8M, r_src1, mod_imm);
+          res = NewLIR2(kThumb2CmnRI8M, r_src1.GetReg(), mod_imm);
         } else {
-          int r_tmp = AllocTemp();
+          RegStorage r_tmp = AllocTemp();
           res = LoadConstant(r_tmp, value);
           OpRegReg(kOpCmp, r_src1, r_tmp);
           FreeTemp(r_tmp);
@@ -583,28 +583,28 @@
   }
 
   if (mod_imm >= 0) {
-    return NewLIR3(opcode, r_dest, r_src1, mod_imm);
+    return NewLIR3(opcode, r_dest.GetReg(), r_src1.GetReg(), mod_imm);
   } else {
-    int r_scratch = AllocTemp();
+    RegStorage r_scratch = AllocTemp();
     LoadConstant(r_scratch, value);
     if (EncodingMap[alt_opcode].flags & IS_QUAD_OP)
-      res = NewLIR4(alt_opcode, r_dest, r_src1, r_scratch, 0);
+      res = NewLIR4(alt_opcode, r_dest.GetReg(), r_src1.GetReg(), r_scratch.GetReg(), 0);
     else
-      res = NewLIR3(alt_opcode, r_dest, r_src1, r_scratch);
+      res = NewLIR3(alt_opcode, r_dest.GetReg(), r_src1.GetReg(), r_scratch.GetReg());
     FreeTemp(r_scratch);
     return res;
   }
 }
 
 /* Handle Thumb-only variants here - otherwise punt to OpRegRegImm */
-LIR* ArmMir2Lir::OpRegImm(OpKind op, int r_dest_src1, int value) {
+LIR* ArmMir2Lir::OpRegImm(OpKind op, RegStorage r_dest_src1, int value) {
   bool neg = (value < 0);
   int32_t abs_value = (neg) ? -value : value;
-  bool short_form = (((abs_value & 0xff) == abs_value) && ARM_LOWREG(r_dest_src1));
+  bool short_form = (((abs_value & 0xff) == abs_value) && ARM_LOWREG(r_dest_src1.GetReg()));
   ArmOpcode opcode = kThumbBkpt;
   switch (op) {
     case kOpAdd:
-      if (!neg && (r_dest_src1 == r13sp) && (value <= 508)) { /* sp */
+      if (!neg && (r_dest_src1 == rs_r13sp) && (value <= 508)) { /* sp */
         DCHECK_EQ((value & 0x3), 0);
         return NewLIR1(kThumbAddSpI7, value >> 2);
       } else if (short_form) {
@@ -612,7 +612,7 @@
       }
       break;
     case kOpSub:
-      if (!neg && (r_dest_src1 == r13sp) && (value <= 508)) { /* sp */
+      if (!neg && (r_dest_src1 == rs_r13sp) && (value <= 508)) { /* sp */
         DCHECK_EQ((value & 0x3), 0);
         return NewLIR1(kThumbSubSpI7, value >> 2);
       } else if (short_form) {
@@ -632,18 +632,18 @@
       break;
   }
   if (short_form) {
-    return NewLIR2(opcode, r_dest_src1, abs_value);
+    return NewLIR2(opcode, r_dest_src1.GetReg(), abs_value);
   } else {
     return OpRegRegImm(op, r_dest_src1, r_dest_src1, value);
   }
 }
 
-LIR* ArmMir2Lir::LoadConstantWide(int r_dest_lo, int r_dest_hi, int64_t value) {
+LIR* ArmMir2Lir::LoadConstantWide(RegStorage r_dest, int64_t value) {
   LIR* res = NULL;
   int32_t val_lo = Low32Bits(value);
   int32_t val_hi = High32Bits(value);
-  int target_reg = S2d(r_dest_lo, r_dest_hi);
-  if (ARM_FPREG(r_dest_lo)) {
+  int target_reg = S2d(r_dest.GetLowReg(), r_dest.GetHighReg());
+  if (ARM_FPREG(r_dest.GetLowReg())) {
     if ((val_lo == 0) && (val_hi == 0)) {
       // TODO: we need better info about the target CPU.  a vector exclusive or
       //       would probably be better here if we could rely on its existance.
@@ -659,8 +659,8 @@
     }
   } else {
     if ((InexpensiveConstantInt(val_lo) && (InexpensiveConstantInt(val_hi)))) {
-      res = LoadConstantNoClobber(r_dest_lo, val_lo);
-      LoadConstantNoClobber(r_dest_hi, val_hi);
+      res = LoadConstantNoClobber(r_dest.GetLow(), val_lo);
+      LoadConstantNoClobber(r_dest.GetHigh(), val_hi);
     }
   }
   if (res == NULL) {
@@ -669,12 +669,13 @@
     if (data_target == NULL) {
       data_target = AddWideData(&literal_list_, val_lo, val_hi);
     }
-    if (ARM_FPREG(r_dest_lo)) {
+    if (ARM_FPREG(r_dest.GetLowReg())) {
       res = RawLIR(current_dalvik_offset_, kThumb2Vldrd,
                    target_reg, r15pc, 0, 0, 0, data_target);
     } else {
+      DCHECK(r_dest.IsPair());
       res = RawLIR(current_dalvik_offset_, kThumb2LdrdPcRel8,
-                   r_dest_lo, r_dest_hi, r15pc, 0, 0, data_target);
+                   r_dest.GetLowReg(), r_dest.GetHighReg(), r15pc, 0, 0, data_target);
     }
     SetMemRefType(res, true, kLiteral);
     AppendLIR(res);
@@ -686,23 +687,24 @@
   return ((amount & 0x1f) << 2) | code;
 }
 
-LIR* ArmMir2Lir::LoadBaseIndexed(int rBase, int r_index, int r_dest,
+LIR* ArmMir2Lir::LoadBaseIndexed(RegStorage r_base, RegStorage r_index, RegStorage r_dest,
                                  int scale, OpSize size) {
-  bool all_low_regs = ARM_LOWREG(rBase) && ARM_LOWREG(r_index) && ARM_LOWREG(r_dest);
+  bool all_low_regs = ARM_LOWREG(r_base.GetReg()) && ARM_LOWREG(r_index.GetReg()) &&
+      ARM_LOWREG(r_dest.GetReg());
   LIR* load;
   ArmOpcode opcode = kThumbBkpt;
   bool thumb_form = (all_low_regs && (scale == 0));
-  int reg_ptr;
+  RegStorage reg_ptr;
 
-  if (ARM_FPREG(r_dest)) {
-    if (ARM_SINGLEREG(r_dest)) {
+  if (ARM_FPREG(r_dest.GetReg())) {
+    if (ARM_SINGLEREG(r_dest.GetReg())) {
       DCHECK((size == kWord) || (size == kSingle));
       opcode = kThumb2Vldrs;
       size = kSingle;
     } else {
-      DCHECK(ARM_DOUBLEREG(r_dest));
+      DCHECK(ARM_DOUBLEREG(r_dest.GetReg()));
       DCHECK((size == kLong) || (size == kDouble));
-      DCHECK_EQ((r_dest & 0x1), 0);
+      DCHECK_EQ((r_dest.GetReg() & 0x1), 0);
       opcode = kThumb2Vldrd;
       size = kDouble;
     }
@@ -716,12 +718,12 @@
     case kSingle:
       reg_ptr = AllocTemp();
       if (scale) {
-        NewLIR4(kThumb2AddRRR, reg_ptr, rBase, r_index,
+        NewLIR4(kThumb2AddRRR, reg_ptr.GetReg(), r_base.GetReg(), r_index.GetReg(),
                 EncodeShift(kArmLsl, scale));
       } else {
-        OpRegRegReg(kOpAdd, reg_ptr, rBase, r_index);
+        OpRegRegReg(kOpAdd, reg_ptr, r_base, r_index);
       }
-      load = NewLIR3(opcode, r_dest, reg_ptr, 0);
+      load = NewLIR3(opcode, r_dest.GetReg(), reg_ptr.GetReg(), 0);
       FreeTemp(reg_ptr);
       return load;
     case kWord:
@@ -743,30 +745,31 @@
       LOG(FATAL) << "Bad size: " << size;
   }
   if (thumb_form)
-    load = NewLIR3(opcode, r_dest, rBase, r_index);
+    load = NewLIR3(opcode, r_dest.GetReg(), r_base.GetReg(), r_index.GetReg());
   else
-    load = NewLIR4(opcode, r_dest, rBase, r_index, scale);
+    load = NewLIR4(opcode, r_dest.GetReg(), r_base.GetReg(), r_index.GetReg(), scale);
 
   return load;
 }
 
-LIR* ArmMir2Lir::StoreBaseIndexed(int rBase, int r_index, int r_src,
+LIR* ArmMir2Lir::StoreBaseIndexed(RegStorage r_base, RegStorage r_index, RegStorage r_src,
                                   int scale, OpSize size) {
-  bool all_low_regs = ARM_LOWREG(rBase) && ARM_LOWREG(r_index) && ARM_LOWREG(r_src);
+  bool all_low_regs = ARM_LOWREG(r_base.GetReg()) && ARM_LOWREG(r_index.GetReg()) &&
+      ARM_LOWREG(r_src.GetReg());
   LIR* store = NULL;
   ArmOpcode opcode = kThumbBkpt;
   bool thumb_form = (all_low_regs && (scale == 0));
-  int reg_ptr;
+  RegStorage reg_ptr;
 
-  if (ARM_FPREG(r_src)) {
-    if (ARM_SINGLEREG(r_src)) {
+  if (ARM_FPREG(r_src.GetReg())) {
+    if (ARM_SINGLEREG(r_src.GetReg())) {
       DCHECK((size == kWord) || (size == kSingle));
       opcode = kThumb2Vstrs;
       size = kSingle;
     } else {
-      DCHECK(ARM_DOUBLEREG(r_src));
+      DCHECK(ARM_DOUBLEREG(r_src.GetReg()));
       DCHECK((size == kLong) || (size == kDouble));
-      DCHECK_EQ((r_src & 0x1), 0);
+      DCHECK_EQ((r_src.GetReg() & 0x1), 0);
       opcode = kThumb2Vstrd;
       size = kDouble;
     }
@@ -780,12 +783,12 @@
     case kSingle:
       reg_ptr = AllocTemp();
       if (scale) {
-        NewLIR4(kThumb2AddRRR, reg_ptr, rBase, r_index,
+        NewLIR4(kThumb2AddRRR, reg_ptr.GetReg(), r_base.GetReg(), r_index.GetReg(),
                 EncodeShift(kArmLsl, scale));
       } else {
-        OpRegRegReg(kOpAdd, reg_ptr, rBase, r_index);
+        OpRegRegReg(kOpAdd, reg_ptr, r_base, r_index);
       }
-      store = NewLIR3(opcode, r_src, reg_ptr, 0);
+      store = NewLIR3(opcode, r_src.GetReg(), reg_ptr.GetReg(), 0);
       FreeTemp(reg_ptr);
       return store;
     case kWord:
@@ -803,9 +806,9 @@
       LOG(FATAL) << "Bad size: " << size;
   }
   if (thumb_form)
-    store = NewLIR3(opcode, r_src, rBase, r_index);
+    store = NewLIR3(opcode, r_src.GetReg(), r_base.GetReg(), r_index.GetReg());
   else
-    store = NewLIR4(opcode, r_src, rBase, r_index, scale);
+    store = NewLIR4(opcode, r_src.GetReg(), r_base.GetReg(), r_index.GetReg(), scale);
 
   return store;
 }
@@ -815,45 +818,44 @@
  * on base (which must have an associated s_reg and MIR).  If not
  * performing null check, incoming MIR can be null.
  */
-LIR* ArmMir2Lir::LoadBaseDispBody(int rBase, int displacement, int r_dest,
-                                  int r_dest_hi, OpSize size, int s_reg) {
+LIR* ArmMir2Lir::LoadBaseDispBody(RegStorage r_base, int displacement, RegStorage r_dest,
+                                  OpSize size, int s_reg) {
   LIR* load = NULL;
   ArmOpcode opcode = kThumbBkpt;
   bool short_form = false;
   bool thumb2Form = (displacement < 4092 && displacement >= 0);
-  bool all_low_regs = (ARM_LOWREG(rBase) && ARM_LOWREG(r_dest));
+  bool all_low = r_dest.Is32Bit() && ARM_LOWREG(r_base.GetReg() && ARM_LOWREG(r_dest.GetReg()));
   int encoded_disp = displacement;
-  bool is64bit = false;
   bool already_generated = false;
+  int dest_low_reg = r_dest.IsPair() ? r_dest.GetLowReg() : r_dest.GetReg();
   switch (size) {
     case kDouble:
     case kLong:
-      is64bit = true;
-      if (ARM_FPREG(r_dest)) {
-        if (ARM_SINGLEREG(r_dest)) {
-          DCHECK(ARM_FPREG(r_dest_hi));
-          r_dest = S2d(r_dest, r_dest_hi);
+      if (ARM_FPREG(dest_low_reg)) {
+        // Note: following change to avoid using pairs for doubles, replace conversion w/ DCHECK.
+        if (r_dest.IsPair()) {
+          DCHECK(ARM_FPREG(r_dest.GetHighReg()));
+          r_dest = RegStorage::Solo64(S2d(r_dest.GetLowReg(), r_dest.GetHighReg()));
         }
         opcode = kThumb2Vldrd;
         if (displacement <= 1020) {
           short_form = true;
           encoded_disp >>= 2;
         }
-        break;
       } else {
         if (displacement <= 1020) {
-          load = NewLIR4(kThumb2LdrdI8, r_dest, r_dest_hi, rBase, displacement >> 2);
+          load = NewLIR4(kThumb2LdrdI8, r_dest.GetLowReg(), r_dest.GetHighReg(), r_base.GetReg(),
+                         displacement >> 2);
         } else {
-          load = LoadBaseDispBody(rBase, displacement, r_dest,
-                                 -1, kWord, s_reg);
-          LoadBaseDispBody(rBase, displacement + 4, r_dest_hi,
-                           -1, kWord, INVALID_SREG);
+          load = LoadBaseDispBody(r_base, displacement, r_dest.GetLow(), kWord, s_reg);
+          LoadBaseDispBody(r_base, displacement + 4, r_dest.GetHigh(), kWord, INVALID_SREG);
         }
         already_generated = true;
       }
+      break;
     case kSingle:
     case kWord:
-      if (ARM_FPREG(r_dest)) {
+      if (ARM_FPREG(r_dest.GetReg())) {
         opcode = kThumb2Vldrs;
         if (displacement <= 1020) {
           short_form = true;
@@ -861,17 +863,17 @@
         }
         break;
       }
-      if (ARM_LOWREG(r_dest) && (rBase == r15pc) &&
+      if (ARM_LOWREG(r_dest.GetReg()) && (r_base.GetReg() == r15pc) &&
           (displacement <= 1020) && (displacement >= 0)) {
         short_form = true;
         encoded_disp >>= 2;
         opcode = kThumbLdrPcRel;
-      } else if (ARM_LOWREG(r_dest) && (rBase == r13sp) &&
+      } else if (ARM_LOWREG(r_dest.GetReg()) && (r_base.GetReg() == r13sp) &&
           (displacement <= 1020) && (displacement >= 0)) {
         short_form = true;
         encoded_disp >>= 2;
         opcode = kThumbLdrSpRel;
-      } else if (all_low_regs && displacement < 128 && displacement >= 0) {
+      } else if (all_low && displacement < 128 && displacement >= 0) {
         DCHECK_EQ((displacement & 0x3), 0);
         short_form = true;
         encoded_disp >>= 2;
@@ -882,7 +884,7 @@
       }
       break;
     case kUnsignedHalf:
-      if (all_low_regs && displacement < 64 && displacement >= 0) {
+      if (all_low && displacement < 64 && displacement >= 0) {
         DCHECK_EQ((displacement & 0x1), 0);
         short_form = true;
         encoded_disp >>= 1;
@@ -899,7 +901,7 @@
       }
       break;
     case kUnsignedByte:
-      if (all_low_regs && displacement < 32 && displacement >= 0) {
+      if (all_low && displacement < 32 && displacement >= 0) {
         short_form = true;
         opcode = kThumbLdrbRRI5;
       } else if (thumb2Form) {
@@ -919,65 +921,67 @@
 
   if (!already_generated) {
     if (short_form) {
-      load = NewLIR3(opcode, r_dest, rBase, encoded_disp);
+      load = NewLIR3(opcode, r_dest.GetReg(), r_base.GetReg(), encoded_disp);
     } else {
-      int reg_offset = AllocTemp();
+      RegStorage reg_offset = AllocTemp();
       LoadConstant(reg_offset, encoded_disp);
-      if (ARM_FPREG(r_dest)) {
+      if (ARM_FPREG(dest_low_reg)) {
         // No index ops - must use a long sequence.  Turn the offset into a direct pointer.
-        OpRegReg(kOpAdd, reg_offset, rBase);
-        load = LoadBaseDispBody(reg_offset, 0, r_dest, r_dest_hi, size, s_reg);
+        OpRegReg(kOpAdd, reg_offset, r_base);
+        load = LoadBaseDispBody(reg_offset, 0, r_dest, size, s_reg);
       } else {
-        load = LoadBaseIndexed(rBase, reg_offset, r_dest, 0, size);
+        load = LoadBaseIndexed(r_base, reg_offset, r_dest, 0, size);
       }
       FreeTemp(reg_offset);
     }
   }
 
   // TODO: in future may need to differentiate Dalvik accesses w/ spills
-  if (rBase == rARM_SP) {
-    AnnotateDalvikRegAccess(load, displacement >> 2, true /* is_load */, is64bit);
+  if (r_base == rs_rARM_SP) {
+    AnnotateDalvikRegAccess(load, displacement >> 2, true /* is_load */, r_dest.Is64Bit());
   }
   return load;
 }
 
-LIR* ArmMir2Lir::LoadBaseDisp(int rBase, int displacement, int r_dest,
-                              OpSize size, int s_reg) {
-  return LoadBaseDispBody(rBase, displacement, r_dest, -1, size, s_reg);
+LIR* ArmMir2Lir::LoadBaseDisp(RegStorage r_base, int displacement, RegStorage r_dest, OpSize size,
+                              int s_reg) {
+  DCHECK(!((size == kLong) || (size == kDouble)));
+  return LoadBaseDispBody(r_base, displacement, r_dest, size, s_reg);
 }
 
-LIR* ArmMir2Lir::LoadBaseDispWide(int rBase, int displacement, int r_dest_lo,
-                                  int r_dest_hi, int s_reg) {
-  return LoadBaseDispBody(rBase, displacement, r_dest_lo, r_dest_hi, kLong, s_reg);
+LIR* ArmMir2Lir::LoadBaseDispWide(RegStorage r_base, int displacement, RegStorage r_dest,
+                                  int s_reg) {
+  return LoadBaseDispBody(r_base, displacement, r_dest, kLong, s_reg);
 }
 
 
-LIR* ArmMir2Lir::StoreBaseDispBody(int rBase, int displacement,
-                                   int r_src, int r_src_hi, OpSize size) {
+LIR* ArmMir2Lir::StoreBaseDispBody(RegStorage r_base, int displacement, RegStorage r_src,
+                                   OpSize size) {
   LIR* store = NULL;
   ArmOpcode opcode = kThumbBkpt;
   bool short_form = false;
   bool thumb2Form = (displacement < 4092 && displacement >= 0);
-  bool all_low_regs = (ARM_LOWREG(rBase) && ARM_LOWREG(r_src));
+  bool all_low = r_src.Is32Bit() && (ARM_LOWREG(r_base.GetReg()) && ARM_LOWREG(r_src.GetReg()));
   int encoded_disp = displacement;
-  bool is64bit = false;
   bool already_generated = false;
+  int src_low_reg = r_src.IsPair() ? r_src.GetLowReg() : r_src.GetReg();
   switch (size) {
     case kLong:
     case kDouble:
-      is64bit = true;
-      if (!ARM_FPREG(r_src)) {
+      if (!ARM_FPREG(src_low_reg)) {
         if (displacement <= 1020) {
-          store = NewLIR4(kThumb2StrdI8, r_src, r_src_hi, rBase, displacement >> 2);
+          store = NewLIR4(kThumb2StrdI8, r_src.GetLowReg(), r_src.GetHighReg(), r_base.GetReg(),
+                          displacement >> 2);
         } else {
-          store = StoreBaseDispBody(rBase, displacement, r_src, -1, kWord);
-          StoreBaseDispBody(rBase, displacement + 4, r_src_hi, -1, kWord);
+          store = StoreBaseDispBody(r_base, displacement, r_src.GetLow(), kWord);
+          StoreBaseDispBody(r_base, displacement + 4, r_src.GetHigh(), kWord);
         }
         already_generated = true;
       } else {
-        if (ARM_SINGLEREG(r_src)) {
-          DCHECK(ARM_FPREG(r_src_hi));
-          r_src = S2d(r_src, r_src_hi);
+        // Note: following change to avoid using pairs for doubles, replace conversion w/ DCHECK.
+        if (r_src.IsPair()) {
+          DCHECK(ARM_FPREG(r_src.GetHighReg()));
+          r_src = RegStorage::Solo64(S2d(r_src.GetLowReg(), r_src.GetHighReg()));
         }
         opcode = kThumb2Vstrd;
         if (displacement <= 1020) {
@@ -988,8 +992,8 @@
       break;
     case kSingle:
     case kWord:
-      if (ARM_FPREG(r_src)) {
-        DCHECK(ARM_SINGLEREG(r_src));
+      if (ARM_FPREG(r_src.GetReg())) {
+        DCHECK(ARM_SINGLEREG(r_src.GetReg()));
         opcode = kThumb2Vstrs;
         if (displacement <= 1020) {
           short_form = true;
@@ -997,12 +1001,12 @@
         }
         break;
       }
-      if (ARM_LOWREG(r_src) && (rBase == r13sp) &&
+      if (ARM_LOWREG(r_src.GetReg()) && (r_base == rs_r13sp) &&
           (displacement <= 1020) && (displacement >= 0)) {
         short_form = true;
         encoded_disp >>= 2;
         opcode = kThumbStrSpRel;
-      } else if (all_low_regs && displacement < 128 && displacement >= 0) {
+      } else if (all_low && displacement < 128 && displacement >= 0) {
         DCHECK_EQ((displacement & 0x3), 0);
         short_form = true;
         encoded_disp >>= 2;
@@ -1014,7 +1018,7 @@
       break;
     case kUnsignedHalf:
     case kSignedHalf:
-      if (all_low_regs && displacement < 64 && displacement >= 0) {
+      if (all_low && displacement < 64 && displacement >= 0) {
         DCHECK_EQ((displacement & 0x1), 0);
         short_form = true;
         encoded_disp >>= 1;
@@ -1026,7 +1030,7 @@
       break;
     case kUnsignedByte:
     case kSignedByte:
-      if (all_low_regs && displacement < 32 && displacement >= 0) {
+      if (all_low && displacement < 32 && displacement >= 0) {
         short_form = true;
         opcode = kThumbStrbRRI5;
       } else if (thumb2Form) {
@@ -1039,52 +1043,52 @@
   }
   if (!already_generated) {
     if (short_form) {
-      store = NewLIR3(opcode, r_src, rBase, encoded_disp);
+      store = NewLIR3(opcode, r_src.GetReg(), r_base.GetReg(), encoded_disp);
     } else {
-      int r_scratch = AllocTemp();
+      RegStorage r_scratch = AllocTemp();
       LoadConstant(r_scratch, encoded_disp);
-      if (ARM_FPREG(r_src)) {
+      if (ARM_FPREG(src_low_reg)) {
         // No index ops - must use a long sequence.  Turn the offset into a direct pointer.
-        OpRegReg(kOpAdd, r_scratch, rBase);
-        store = StoreBaseDispBody(r_scratch, 0, r_src, r_src_hi, size);
+        OpRegReg(kOpAdd, r_scratch, r_base);
+        store = StoreBaseDispBody(r_scratch, 0, r_src, size);
       } else {
-        store = StoreBaseIndexed(rBase, r_scratch, r_src, 0, size);
+        store = StoreBaseIndexed(r_base, r_scratch, r_src, 0, size);
       }
       FreeTemp(r_scratch);
     }
   }
 
   // TODO: In future, may need to differentiate Dalvik & spill accesses
-  if (rBase == rARM_SP) {
-    AnnotateDalvikRegAccess(store, displacement >> 2, false /* is_load */, is64bit);
+  if (r_base == rs_rARM_SP) {
+    AnnotateDalvikRegAccess(store, displacement >> 2, false /* is_load */, r_src.Is64Bit());
   }
   return store;
 }
 
-LIR* ArmMir2Lir::StoreBaseDisp(int rBase, int displacement, int r_src,
+LIR* ArmMir2Lir::StoreBaseDisp(RegStorage r_base, int displacement, RegStorage r_src,
                                OpSize size) {
-  return StoreBaseDispBody(rBase, displacement, r_src, -1, size);
+  DCHECK(!((size == kLong) || (size == kDouble)));
+  return StoreBaseDispBody(r_base, displacement, r_src, size);
 }
 
-LIR* ArmMir2Lir::StoreBaseDispWide(int rBase, int displacement,
-                                   int r_src_lo, int r_src_hi) {
-  return StoreBaseDispBody(rBase, displacement, r_src_lo, r_src_hi, kLong);
+LIR* ArmMir2Lir::StoreBaseDispWide(RegStorage r_base, int displacement, RegStorage r_src) {
+  return StoreBaseDispBody(r_base, displacement, r_src, kLong);
 }
 
-LIR* ArmMir2Lir::OpFpRegCopy(int r_dest, int r_src) {
+LIR* ArmMir2Lir::OpFpRegCopy(RegStorage r_dest, RegStorage r_src) {
   int opcode;
-  DCHECK_EQ(ARM_DOUBLEREG(r_dest), ARM_DOUBLEREG(r_src));
-  if (ARM_DOUBLEREG(r_dest)) {
+  DCHECK_EQ(ARM_DOUBLEREG(r_dest.GetReg()), ARM_DOUBLEREG(r_src.GetReg()));
+  if (ARM_DOUBLEREG(r_dest.GetReg())) {
     opcode = kThumb2Vmovd;
   } else {
-    if (ARM_SINGLEREG(r_dest)) {
-      opcode = ARM_SINGLEREG(r_src) ? kThumb2Vmovs : kThumb2Fmsr;
+    if (ARM_SINGLEREG(r_dest.GetReg())) {
+      opcode = ARM_SINGLEREG(r_src.GetReg()) ? kThumb2Vmovs : kThumb2Fmsr;
     } else {
-      DCHECK(ARM_SINGLEREG(r_src));
+      DCHECK(ARM_SINGLEREG(r_src.GetReg()));
       opcode = kThumb2Fmrs;
     }
   }
-  LIR* res = RawLIR(current_dalvik_offset_, opcode, r_dest, r_src);
+  LIR* res = RawLIR(current_dalvik_offset_, opcode, r_dest.GetReg(), r_src.GetReg());
   if (!(cu_->disable_opt & (1 << kSafeOptimizations)) && r_dest == r_src) {
     res->flags.is_nop = true;
   }
@@ -1096,26 +1100,26 @@
   return NULL;
 }
 
-LIR* ArmMir2Lir::OpMem(OpKind op, int rBase, int disp) {
+LIR* ArmMir2Lir::OpMem(OpKind op, RegStorage r_base, int disp) {
   LOG(FATAL) << "Unexpected use of OpMem for Arm";
   return NULL;
 }
 
-LIR* ArmMir2Lir::StoreBaseIndexedDisp(int rBase, int r_index, int scale,
-                                      int displacement, int r_src, int r_src_hi, OpSize size,
-                                      int s_reg) {
+LIR* ArmMir2Lir::StoreBaseIndexedDisp(RegStorage r_base, RegStorage r_index, int scale,
+                                      int displacement, RegStorage r_src, RegStorage r_src_hi,
+                                      OpSize size, int s_reg) {
   LOG(FATAL) << "Unexpected use of StoreBaseIndexedDisp for Arm";
   return NULL;
 }
 
-LIR* ArmMir2Lir::OpRegMem(OpKind op, int r_dest, int rBase, int offset) {
+LIR* ArmMir2Lir::OpRegMem(OpKind op, RegStorage r_dest, RegStorage r_base, int offset) {
   LOG(FATAL) << "Unexpected use of OpRegMem for Arm";
   return NULL;
 }
 
-LIR* ArmMir2Lir::LoadBaseIndexedDisp(int rBase, int r_index, int scale,
-                                     int displacement, int r_dest, int r_dest_hi, OpSize size,
-                                     int s_reg) {
+LIR* ArmMir2Lir::LoadBaseIndexedDisp(RegStorage r_base, RegStorage r_index, int scale,
+                                     int displacement, RegStorage r_dest, RegStorage r_dest_hi,
+                                     OpSize size, int s_reg) {
   LOG(FATAL) << "Unexpected use of LoadBaseIndexedDisp for Arm";
   return NULL;
 }
diff --git a/compiler/dex/quick/codegen_util.cc b/compiler/dex/quick/codegen_util.cc
index 60f8796..717ad86 100644
--- a/compiler/dex/quick/codegen_util.cc
+++ b/compiler/dex/quick/codegen_util.cc
@@ -1113,7 +1113,7 @@
   return (abs(mir_graph_->SRegToVReg(rl_src.s_reg_low) - mir_graph_->SRegToVReg(rl_dest.s_reg_low)) == 1);
 }
 
-LIR *Mir2Lir::OpCmpMemImmBranch(ConditionCode cond, int temp_reg, int base_reg,
+LIR *Mir2Lir::OpCmpMemImmBranch(ConditionCode cond, RegStorage temp_reg, RegStorage base_reg,
                                 int offset, int check_value, LIR* target) {
   // Handle this for architectures that can't compare to memory.
   LoadWordDisp(base_reg, offset, temp_reg);
@@ -1168,4 +1168,12 @@
   return nullptr;
 }
 
+RegLocation Mir2Lir::NarrowRegLoc(RegLocation loc) {
+  loc.wide = false;
+  if (loc.reg.IsPair()) {
+    loc.reg = loc.reg.GetLow();
+  }
+  return loc;
+}
+
 }  // namespace art
diff --git a/compiler/dex/quick/gen_common.cc b/compiler/dex/quick/gen_common.cc
index 3235977..2afa5ca 100644
--- a/compiler/dex/quick/gen_common.cc
+++ b/compiler/dex/quick/gen_common.cc
@@ -54,12 +54,15 @@
   return branch;
 }
 
-LIR* Mir2Lir::GenImmedCheck(ConditionCode c_code, int reg, int imm_val, ThrowKind kind) {
-  LIR* tgt = RawLIR(0, kPseudoThrowTarget, kind, current_dalvik_offset_, reg, imm_val);
+LIR* Mir2Lir::GenImmedCheck(ConditionCode c_code, RegStorage reg, int imm_val, ThrowKind kind) {
+  LIR* tgt;
   LIR* branch;
   if (c_code == kCondAl) {
+    tgt = RawLIR(0, kPseudoThrowTarget, kind, current_dalvik_offset_, RegStorage::kInvalidRegVal,
+                 imm_val);
     branch = OpUnconditionalBranch(tgt);
   } else {
+    tgt = RawLIR(0, kPseudoThrowTarget, kind, current_dalvik_offset_, reg.GetReg(), imm_val);
     branch = OpCmpImmBranch(c_code, reg, imm_val, tgt);
   }
   // Remember branch target - will process later
@@ -69,7 +72,7 @@
 
 
 /* Perform null-check on a register.  */
-LIR* Mir2Lir::GenNullCheck(int m_reg, int opt_flags) {
+LIR* Mir2Lir::GenNullCheck(RegStorage m_reg, int opt_flags) {
   if (Runtime::Current()->ExplicitNullChecks()) {
     if (!(cu_->disable_opt & (1 << kNullCheckElimination)) && (opt_flags & MIR_IGNORE_NULL_CHECK)) {
       return NULL;
@@ -94,14 +97,15 @@
   }
 }
 
-void Mir2Lir::ForceImplicitNullCheck(int reg, int opt_flags) {
+void Mir2Lir::ForceImplicitNullCheck(RegStorage reg, int opt_flags) {
   if (!Runtime::Current()->ExplicitNullChecks()) {
     if (!(cu_->disable_opt & (1 << kNullCheckElimination)) && (opt_flags & MIR_IGNORE_NULL_CHECK)) {
       return;
     }
     // Force an implicit null check by performing a memory operation (load) from the given
     // register with offset 0.  This will cause a signal if the register contains 0 (null).
-    int tmp = AllocTemp();
+    RegStorage tmp = AllocTemp();
+    // TODO: for Mips, would be best to use rZERO as the bogus register target.
     LIR* load = LoadWordDisp(reg, 0, tmp);
     FreeTemp(tmp);
     MarkSafepointPC(load);
@@ -109,9 +113,10 @@
 }
 
 /* Perform check on two registers */
-LIR* Mir2Lir::GenRegRegCheck(ConditionCode c_code, int reg1, int reg2,
+LIR* Mir2Lir::GenRegRegCheck(ConditionCode c_code, RegStorage reg1, RegStorage reg2,
                              ThrowKind kind) {
-  LIR* tgt = RawLIR(0, kPseudoThrowTarget, kind, current_dalvik_offset_, reg1, reg2);
+  LIR* tgt = RawLIR(0, kPseudoThrowTarget, kind, current_dalvik_offset_, reg1.GetReg(),
+                    reg2.GetReg());
   LIR* branch = OpCmpBranch(c_code, reg1, reg2, tgt);
   // Remember branch target - will process later
   throw_launchpads_.Insert(tgt);
@@ -162,12 +167,12 @@
     if ((rl_temp.location == kLocDalvikFrame) &&
         InexpensiveConstantInt(mir_graph_->ConstantValue(rl_src2))) {
       // OK - convert this to a compare immediate and branch
-      OpCmpImmBranch(cond, rl_src1.reg.GetReg(), mir_graph_->ConstantValue(rl_src2), taken);
+      OpCmpImmBranch(cond, rl_src1.reg, mir_graph_->ConstantValue(rl_src2), taken);
       return;
     }
   }
   rl_src2 = LoadValue(rl_src2, kCoreReg);
-  OpCmpBranch(cond, rl_src1.reg.GetReg(), rl_src2.reg.GetReg(), taken);
+  OpCmpBranch(cond, rl_src1.reg, rl_src2.reg, taken);
 }
 
 void Mir2Lir::GenCompareZeroAndBranch(Instruction::Code opcode, RegLocation rl_src, LIR* taken,
@@ -197,17 +202,17 @@
       cond = static_cast<ConditionCode>(0);
       LOG(FATAL) << "Unexpected opcode " << opcode;
   }
-  OpCmpImmBranch(cond, rl_src.reg.GetReg(), 0, taken);
+  OpCmpImmBranch(cond, rl_src.reg, 0, taken);
 }
 
 void Mir2Lir::GenIntToLong(RegLocation rl_dest, RegLocation rl_src) {
   RegLocation rl_result = EvalLoc(rl_dest, kCoreReg, true);
   if (rl_src.location == kLocPhysReg) {
-    OpRegCopy(rl_result.reg.GetReg(), rl_src.reg.GetReg());
+    OpRegCopy(rl_result.reg, rl_src.reg);
   } else {
-    LoadValueDirect(rl_src, rl_result.reg.GetReg());
+    LoadValueDirect(rl_src, rl_result.reg.GetLow());
   }
-  OpRegRegImm(kOpAsr, rl_result.reg.GetHighReg(), rl_result.reg.GetReg(), 31);
+  OpRegRegImm(kOpAsr, rl_result.reg.GetHigh(), rl_result.reg.GetLow(), 31);
   StoreValueWide(rl_dest, rl_result);
 }
 
@@ -229,7 +234,7 @@
     default:
       LOG(ERROR) << "Bad int conversion type";
   }
-  OpRegReg(op, rl_result.reg.GetReg(), rl_src.reg.GetReg());
+  OpRegReg(op, rl_result.reg, rl_src.reg);
   StoreValue(rl_dest, rl_result);
 }
 
@@ -323,8 +328,7 @@
     for (int i = 0; i < elems; i++) {
       RegLocation loc = UpdateLoc(info->args[i]);
       if (loc.location == kLocPhysReg) {
-        StoreBaseDisp(TargetReg(kSp), SRegOffset(loc.s_reg_low),
-                      loc.reg.GetReg(), kWord);
+        StoreBaseDisp(TargetReg(kSp), SRegOffset(loc.s_reg_low), loc.reg, kWord);
       }
     }
     /*
@@ -332,10 +336,10 @@
      * this is an uncommon operation and isn't especially performance
      * critical.
      */
-    int r_src = AllocTemp();
-    int r_dst = AllocTemp();
-    int r_idx = AllocTemp();
-    int r_val = INVALID_REG;
+    RegStorage r_src = AllocTemp();
+    RegStorage r_dst = AllocTemp();
+    RegStorage r_idx = AllocTemp();
+    RegStorage r_val;
     switch (cu_->instruction_set) {
       case kThumb2:
         r_val = TargetReg(kLr);
@@ -374,11 +378,11 @@
     for (int i = 0; i < elems; i++) {
       RegLocation rl_arg = LoadValue(info->args[i], kCoreReg);
       StoreBaseDisp(TargetReg(kRet0),
-                    mirror::Array::DataOffset(component_size).Int32Value() +
-                    i * 4, rl_arg.reg.GetReg(), kWord);
+                    mirror::Array::DataOffset(component_size).Int32Value() + i * 4,
+                    rl_arg.reg, kWord);
       // If the LoadValue caused a temp to be allocated, free it
-      if (IsTemp(rl_arg.reg.GetReg())) {
-        FreeTemp(rl_arg.reg.GetReg());
+      if (IsTemp(rl_arg.reg)) {
+        FreeTemp(rl_arg.reg);
       }
     }
   }
@@ -392,17 +396,17 @@
 //
 class StaticFieldSlowPath : public Mir2Lir::LIRSlowPath {
  public:
-  StaticFieldSlowPath(Mir2Lir* m2l, LIR* unresolved, LIR* uninit, LIR* cont,
-           int storage_index, int r_base) :
-    LIRSlowPath(m2l, m2l->GetCurrentDexPc(), unresolved, cont), uninit_(uninit), storage_index_(storage_index),
-    r_base_(r_base) {
+  StaticFieldSlowPath(Mir2Lir* m2l, LIR* unresolved, LIR* uninit, LIR* cont, int storage_index,
+                      RegStorage r_base) :
+    LIRSlowPath(m2l, m2l->GetCurrentDexPc(), unresolved, cont), uninit_(uninit),
+               storage_index_(storage_index), r_base_(r_base) {
   }
 
   void Compile() {
     LIR* unresolved_target = GenerateTargetLabel();
     uninit_->target = unresolved_target;
     m2l_->CallRuntimeHelperImm(QUICK_ENTRYPOINT_OFFSET(pInitializeStaticStorage),
-                            storage_index_, true);
+                               storage_index_, true);
     // Copy helper's result into r_base, a no-op on all but MIPS.
     m2l_->OpRegCopy(r_base_,  m2l_->TargetReg(kRet0));
 
@@ -412,7 +416,7 @@
  private:
   LIR* const uninit_;
   const int storage_index_;
-  const int r_base_;
+  const RegStorage r_base_;
 };
 
 void Mir2Lir::GenSput(MIR* mir, RegLocation rl_src, bool is_long_or_double,
@@ -421,15 +425,14 @@
   cu_->compiler_driver->ProcessedStaticField(field_info.FastPut(), field_info.IsReferrersClass());
   if (field_info.FastPut() && !SLOW_FIELD_PATH) {
     DCHECK_GE(field_info.FieldOffset().Int32Value(), 0);
-    int r_base;
+    RegStorage r_base;
     if (field_info.IsReferrersClass()) {
       // Fast path, static storage base is this method's class
       RegLocation rl_method  = LoadCurrMethod();
       r_base = AllocTemp();
-      LoadWordDisp(rl_method.reg.GetReg(),
-                   mirror::ArtMethod::DeclaringClassOffset().Int32Value(), r_base);
-      if (IsTemp(rl_method.reg.GetReg())) {
-        FreeTemp(rl_method.reg.GetReg());
+      LoadWordDisp(rl_method.reg, mirror::ArtMethod::DeclaringClassOffset().Int32Value(), r_base);
+      if (IsTemp(rl_method.reg)) {
+        FreeTemp(rl_method.reg);
       }
     } else {
       // Medium path, static storage base in a different class which requires checks that the other
@@ -439,14 +442,12 @@
       // May do runtime call so everything to home locations.
       FlushAllRegs();
       // Using fixed register to sync with possible call to runtime support.
-      int r_method = TargetReg(kArg1);
+      RegStorage r_method = TargetReg(kArg1);
       LockTemp(r_method);
       LoadCurrMethodDirect(r_method);
       r_base = TargetReg(kArg0);
       LockTemp(r_base);
-      LoadWordDisp(r_method,
-                   mirror::ArtMethod::DexCacheResolvedTypesOffset().Int32Value(),
-                   r_base);
+      LoadWordDisp(r_method, mirror::ArtMethod::DexCacheResolvedTypesOffset().Int32Value(), r_base);
       LoadWordDisp(r_base, mirror::Array::DataOffset(sizeof(mirror::Object*)).Int32Value() +
                    sizeof(int32_t*) * field_info.StorageIndex(), r_base);
       // r_base now points at static storage (Class*) or NULL if the type is not yet resolved.
@@ -457,15 +458,14 @@
         // The slow path is invoked if the r_base is NULL or the class pointed
         // to by it is not initialized.
         LIR* unresolved_branch = OpCmpImmBranch(kCondEq, r_base, 0, NULL);
-        int r_tmp = TargetReg(kArg2);
+        RegStorage r_tmp = TargetReg(kArg2);
         LockTemp(r_tmp);
         LIR* uninit_branch = OpCmpMemImmBranch(kCondLt, r_tmp, r_base,
                                           mirror::Class::StatusOffset().Int32Value(),
                                           mirror::Class::kStatusInitialized, NULL);
         LIR* cont = NewLIR0(kPseudoTargetLabel);
 
-        AddSlowPath(new (arena_) StaticFieldSlowPath(this,
-                                                     unresolved_branch, uninit_branch, cont,
+        AddSlowPath(new (arena_) StaticFieldSlowPath(this, unresolved_branch, uninit_branch, cont,
                                                      field_info.StorageIndex(), r_base));
 
         FreeTemp(r_tmp);
@@ -483,17 +483,16 @@
       GenMemBarrier(kStoreStore);
     }
     if (is_long_or_double) {
-      StoreBaseDispWide(r_base, field_info.FieldOffset().Int32Value(), rl_src.reg.GetReg(),
-                        rl_src.reg.GetHighReg());
+      StoreBaseDispWide(r_base, field_info.FieldOffset().Int32Value(), rl_src.reg);
     } else {
-      StoreWordDisp(r_base, field_info.FieldOffset().Int32Value(), rl_src.reg.GetReg());
+      StoreWordDisp(r_base, field_info.FieldOffset().Int32Value(), rl_src.reg);
     }
     if (field_info.IsVolatile()) {
       // A load might follow the volatile store so insert a StoreLoad barrier.
       GenMemBarrier(kStoreLoad);
     }
     if (is_object && !mir_graph_->IsConstantNullRef(rl_src)) {
-      MarkGCCard(rl_src.reg.GetReg(), r_base);
+      MarkGCCard(rl_src.reg, r_base);
     }
     FreeTemp(r_base);
   } else {
@@ -512,13 +511,12 @@
   cu_->compiler_driver->ProcessedStaticField(field_info.FastGet(), field_info.IsReferrersClass());
   if (field_info.FastGet() && !SLOW_FIELD_PATH) {
     DCHECK_GE(field_info.FieldOffset().Int32Value(), 0);
-    int r_base;
+    RegStorage r_base;
     if (field_info.IsReferrersClass()) {
       // Fast path, static storage base is this method's class
       RegLocation rl_method  = LoadCurrMethod();
       r_base = AllocTemp();
-      LoadWordDisp(rl_method.reg.GetReg(),
-                   mirror::ArtMethod::DeclaringClassOffset().Int32Value(), r_base);
+      LoadWordDisp(rl_method.reg, mirror::ArtMethod::DeclaringClassOffset().Int32Value(), r_base);
     } else {
       // Medium path, static storage base in a different class which requires checks that the other
       // class is initialized
@@ -526,14 +524,12 @@
       // May do runtime call so everything to home locations.
       FlushAllRegs();
       // Using fixed register to sync with possible call to runtime support.
-      int r_method = TargetReg(kArg1);
+      RegStorage r_method = TargetReg(kArg1);
       LockTemp(r_method);
       LoadCurrMethodDirect(r_method);
       r_base = TargetReg(kArg0);
       LockTemp(r_base);
-      LoadWordDisp(r_method,
-                   mirror::ArtMethod::DexCacheResolvedTypesOffset().Int32Value(),
-                   r_base);
+      LoadWordDisp(r_method, mirror::ArtMethod::DexCacheResolvedTypesOffset().Int32Value(), r_base);
       LoadWordDisp(r_base, mirror::Array::DataOffset(sizeof(mirror::Object*)).Int32Value() +
                    sizeof(int32_t*) * field_info.StorageIndex(), r_base);
       // r_base now points at static storage (Class*) or NULL if the type is not yet resolved.
@@ -544,15 +540,14 @@
         // The slow path is invoked if the r_base is NULL or the class pointed
         // to by it is not initialized.
         LIR* unresolved_branch = OpCmpImmBranch(kCondEq, r_base, 0, NULL);
-        int r_tmp = TargetReg(kArg2);
+        RegStorage r_tmp = TargetReg(kArg2);
         LockTemp(r_tmp);
         LIR* uninit_branch = OpCmpMemImmBranch(kCondLt, r_tmp, r_base,
                                           mirror::Class::StatusOffset().Int32Value(),
                                           mirror::Class::kStatusInitialized, NULL);
         LIR* cont = NewLIR0(kPseudoTargetLabel);
 
-        AddSlowPath(new (arena_) StaticFieldSlowPath(this,
-                                                     unresolved_branch, uninit_branch, cont,
+        AddSlowPath(new (arena_) StaticFieldSlowPath(this, unresolved_branch, uninit_branch, cont,
                                                      field_info.StorageIndex(), r_base));
 
         FreeTemp(r_tmp);
@@ -563,10 +558,9 @@
     RegLocation rl_result = EvalLoc(rl_dest, kAnyReg, true);
 
     if (is_long_or_double) {
-      LoadBaseDispWide(r_base, field_info.FieldOffset().Int32Value(), rl_result.reg.GetReg(),
-                       rl_result.reg.GetHighReg(), INVALID_SREG);
+      LoadBaseDispWide(r_base, field_info.FieldOffset().Int32Value(), rl_result.reg, INVALID_SREG);
     } else {
-      LoadWordDisp(r_base, field_info.FieldOffset().Int32Value(), rl_result.reg.GetReg());
+      LoadWordDisp(r_base, field_info.FieldOffset().Int32Value(), rl_result.reg);
     }
     FreeTemp(r_base);
 
@@ -619,7 +613,7 @@
     LIR* resume_lab = reinterpret_cast<LIR*>(UnwrapPointer(lab->operands[0]));
     current_dalvik_offset_ = lab->operands[1];
     AppendLIR(lab);
-    int r_tgt = CallHelperSetup(helper_offset);
+    RegStorage r_tgt = CallHelperSetup(helper_offset);
     CallHelper(r_tgt, helper_offset, true /* MarkSafepointPC */);
     OpUnconditionalBranch(resume_lab);
   }
@@ -644,9 +638,10 @@
       case kThrowConstantArrayBounds:  // v1 is length reg (for Arm/Mips), v2 constant index
         // v1 holds the constant array index.  Mips/Arm uses v2 for length, x86 reloads.
         if (target_x86) {
-          OpRegMem(kOpMov, TargetReg(kArg1), v1, mirror::Array::LengthOffset().Int32Value());
+          OpRegMem(kOpMov, TargetReg(kArg1), RegStorage::Solo32(v1),
+                   mirror::Array::LengthOffset().Int32Value());
         } else {
-          OpRegCopy(TargetReg(kArg1), v1);
+          OpRegCopy(TargetReg(kArg1), RegStorage::Solo32(v1));
         }
         // Make sure the following LoadConstant doesn't mess with kArg1.
         LockTemp(TargetReg(kArg1));
@@ -655,33 +650,36 @@
         break;
       case kThrowArrayBounds:
         // Move v1 (array index) to kArg0 and v2 (array length) to kArg1
-        if (v2 != TargetReg(kArg0)) {
-          OpRegCopy(TargetReg(kArg0), v1);
+        if (v2 != TargetReg(kArg0).GetReg()) {
+          OpRegCopy(TargetReg(kArg0), RegStorage::Solo32(v1));
           if (target_x86) {
             // x86 leaves the array pointer in v2, so load the array length that the handler expects
-            OpRegMem(kOpMov, TargetReg(kArg1), v2, mirror::Array::LengthOffset().Int32Value());
+            OpRegMem(kOpMov, TargetReg(kArg1), RegStorage::Solo32(v2),
+                     mirror::Array::LengthOffset().Int32Value());
           } else {
-            OpRegCopy(TargetReg(kArg1), v2);
+            OpRegCopy(TargetReg(kArg1), RegStorage::Solo32(v2));
           }
         } else {
-          if (v1 == TargetReg(kArg1)) {
+          if (v1 == TargetReg(kArg1).GetReg()) {
             // Swap v1 and v2, using kArg2 as a temp
-            OpRegCopy(TargetReg(kArg2), v1);
+            OpRegCopy(TargetReg(kArg2), RegStorage::Solo32(v1));
             if (target_x86) {
               // x86 leaves the array pointer in v2; load the array length that the handler expects
-              OpRegMem(kOpMov, TargetReg(kArg1), v2, mirror::Array::LengthOffset().Int32Value());
+              OpRegMem(kOpMov, TargetReg(kArg1), RegStorage::Solo32(v2),
+                       mirror::Array::LengthOffset().Int32Value());
             } else {
-              OpRegCopy(TargetReg(kArg1), v2);
+              OpRegCopy(TargetReg(kArg1), RegStorage::Solo32(v2));
             }
             OpRegCopy(TargetReg(kArg0), TargetReg(kArg2));
           } else {
             if (target_x86) {
               // x86 leaves the array pointer in v2; load the array length that the handler expects
-              OpRegMem(kOpMov, TargetReg(kArg1), v2, mirror::Array::LengthOffset().Int32Value());
+              OpRegMem(kOpMov, TargetReg(kArg1), RegStorage::Solo32(v2),
+                       mirror::Array::LengthOffset().Int32Value());
             } else {
-              OpRegCopy(TargetReg(kArg1), v2);
+              OpRegCopy(TargetReg(kArg1), RegStorage::Solo32(v2));
             }
-            OpRegCopy(TargetReg(kArg0), v1);
+            OpRegCopy(TargetReg(kArg0), RegStorage::Solo32(v1));
           }
         }
         func_offset = QUICK_ENTRYPOINT_OFFSET(pThrowArrayBounds);
@@ -690,7 +688,7 @@
         func_offset = QUICK_ENTRYPOINT_OFFSET(pThrowDivZero);
         break;
       case kThrowNoSuchMethod:
-        OpRegCopy(TargetReg(kArg0), v1);
+        OpRegCopy(TargetReg(kArg0), RegStorage::Solo32(v1));
         func_offset =
           QUICK_ENTRYPOINT_OFFSET(pThrowNoSuchMethod);
         break;
@@ -698,7 +696,7 @@
         LOG(FATAL) << "Unexpected throw kind: " << lab->operands[0];
     }
     ClobberCallerSave();
-    int r_tgt = CallHelperSetup(func_offset);
+    RegStorage r_tgt = CallHelperSetup(func_offset);
     CallHelper(r_tgt, func_offset, true /* MarkSafepointPC */, true /* UseLink */);
   }
 }
@@ -715,13 +713,13 @@
     rl_obj = LoadValue(rl_obj, kCoreReg);
     if (is_long_or_double) {
       DCHECK(rl_dest.wide);
-      GenNullCheck(rl_obj.reg.GetReg(), opt_flags);
+      GenNullCheck(rl_obj.reg, opt_flags);
       if (cu_->instruction_set == kX86) {
         rl_result = EvalLoc(rl_dest, reg_class, true);
-        GenNullCheck(rl_obj.reg.GetReg(), opt_flags);
-        LoadBaseDispWide(rl_obj.reg.GetReg(), field_info.FieldOffset().Int32Value(),
-                         rl_result.reg.GetReg(),
-                         rl_result.reg.GetHighReg(), rl_obj.s_reg_low);
+        // FIXME?  duplicate null check?
+        GenNullCheck(rl_obj.reg, opt_flags);
+        LoadBaseDispWide(rl_obj.reg, field_info.FieldOffset().Int32Value(), rl_result.reg,
+                         rl_obj.s_reg_low);
         MarkPossibleNullPointerException(opt_flags);
         if (field_info.IsVolatile()) {
           // Without context sensitive analysis, we must issue the most conservative barriers.
@@ -730,11 +728,10 @@
           GenMemBarrier(kLoadStore);
         }
       } else {
-        int reg_ptr = AllocTemp();
-        OpRegRegImm(kOpAdd, reg_ptr, rl_obj.reg.GetReg(), field_info.FieldOffset().Int32Value());
+        RegStorage reg_ptr = AllocTemp();
+        OpRegRegImm(kOpAdd, reg_ptr, rl_obj.reg, field_info.FieldOffset().Int32Value());
         rl_result = EvalLoc(rl_dest, reg_class, true);
-        LoadBaseDispWide(reg_ptr, 0, rl_result.reg.GetReg(), rl_result.reg.GetHighReg(),
-                         INVALID_SREG);
+        LoadBaseDispWide(reg_ptr, 0, rl_result.reg, INVALID_SREG);
         if (field_info.IsVolatile()) {
           // Without context sensitive analysis, we must issue the most conservative barriers.
           // In this case, either a load or store may follow so we issue both barriers.
@@ -746,9 +743,9 @@
       StoreValueWide(rl_dest, rl_result);
     } else {
       rl_result = EvalLoc(rl_dest, reg_class, true);
-      GenNullCheck(rl_obj.reg.GetReg(), opt_flags);
-      LoadBaseDisp(rl_obj.reg.GetReg(), field_info.FieldOffset().Int32Value(),
-                   rl_result.reg.GetReg(), kWord, rl_obj.s_reg_low);
+      GenNullCheck(rl_obj.reg, opt_flags);
+      LoadBaseDisp(rl_obj.reg, field_info.FieldOffset().Int32Value(), rl_result.reg, kWord,
+                   rl_obj.s_reg_low);
       MarkPossibleNullPointerException(opt_flags);
       if (field_info.IsVolatile()) {
         // Without context sensitive analysis, we must issue the most conservative barriers.
@@ -784,16 +781,15 @@
     DCHECK_GE(field_info.FieldOffset().Int32Value(), 0);
     rl_obj = LoadValue(rl_obj, kCoreReg);
     if (is_long_or_double) {
-      int reg_ptr;
       rl_src = LoadValueWide(rl_src, kAnyReg);
-      GenNullCheck(rl_obj.reg.GetReg(), opt_flags);
-      reg_ptr = AllocTemp();
-      OpRegRegImm(kOpAdd, reg_ptr, rl_obj.reg.GetReg(), field_info.FieldOffset().Int32Value());
+      GenNullCheck(rl_obj.reg, opt_flags);
+      RegStorage reg_ptr = AllocTemp();
+      OpRegRegImm(kOpAdd, reg_ptr, rl_obj.reg, field_info.FieldOffset().Int32Value());
       if (field_info.IsVolatile()) {
         // There might have been a store before this volatile one so insert StoreStore barrier.
         GenMemBarrier(kStoreStore);
       }
-      StoreBaseDispWide(reg_ptr, 0, rl_src.reg.GetReg(), rl_src.reg.GetHighReg());
+      StoreBaseDispWide(reg_ptr, 0, rl_src.reg);
       MarkPossibleNullPointerException(opt_flags);
       if (field_info.IsVolatile()) {
         // A load might follow the volatile store so insert a StoreLoad barrier.
@@ -802,20 +798,19 @@
       FreeTemp(reg_ptr);
     } else {
       rl_src = LoadValue(rl_src, reg_class);
-      GenNullCheck(rl_obj.reg.GetReg(), opt_flags);
+      GenNullCheck(rl_obj.reg, opt_flags);
       if (field_info.IsVolatile()) {
         // There might have been a store before this volatile one so insert StoreStore barrier.
         GenMemBarrier(kStoreStore);
       }
-      StoreBaseDisp(rl_obj.reg.GetReg(), field_info.FieldOffset().Int32Value(),
-        rl_src.reg.GetReg(), kWord);
+      StoreBaseDisp(rl_obj.reg, field_info.FieldOffset().Int32Value(), rl_src.reg, kWord);
       MarkPossibleNullPointerException(opt_flags);
       if (field_info.IsVolatile()) {
         // A load might follow the volatile store so insert a StoreLoad barrier.
         GenMemBarrier(kStoreLoad);
       }
       if (is_object && !mir_graph_->IsConstantNullRef(rl_src)) {
-        MarkGCCard(rl_src.reg.GetReg(), rl_obj.reg.GetReg());
+        MarkGCCard(rl_src.reg, rl_obj.reg);
       }
     }
   } else {
@@ -842,7 +837,7 @@
 
 void Mir2Lir::GenConstClass(uint32_t type_idx, RegLocation rl_dest) {
   RegLocation rl_method = LoadCurrMethod();
-  int res_reg = AllocTemp();
+  RegStorage res_reg = AllocTemp();
   RegLocation rl_result = EvalLoc(rl_dest, kCoreReg, true);
   if (!cu_->compiler_driver->CanAccessTypeWithoutChecks(cu_->method_idx,
                                                    *cu_->dex_file,
@@ -850,23 +845,23 @@
     // Call out to helper which resolves type and verifies access.
     // Resolved type returned in kRet0.
     CallRuntimeHelperImmReg(QUICK_ENTRYPOINT_OFFSET(pInitializeTypeAndVerifyAccess),
-                            type_idx, rl_method.reg.GetReg(), true);
+                            type_idx, rl_method.reg, true);
     RegLocation rl_result = GetReturn(false);
     StoreValue(rl_dest, rl_result);
   } else {
     // We're don't need access checks, load type from dex cache
     int32_t dex_cache_offset =
         mirror::ArtMethod::DexCacheResolvedTypesOffset().Int32Value();
-    LoadWordDisp(rl_method.reg.GetReg(), dex_cache_offset, res_reg);
+    LoadWordDisp(rl_method.reg, dex_cache_offset, res_reg);
     int32_t offset_of_type =
         mirror::Array::DataOffset(sizeof(mirror::Class*)).Int32Value() + (sizeof(mirror::Class*)
                           * type_idx);
-    LoadWordDisp(res_reg, offset_of_type, rl_result.reg.GetReg());
+    LoadWordDisp(res_reg, offset_of_type, rl_result.reg);
     if (!cu_->compiler_driver->CanAssumeTypeIsPresentInDexCache(*cu_->dex_file,
         type_idx) || SLOW_TYPE_PATH) {
       // Slow path, at runtime test if type is null and if so initialize
       FlushAllRegs();
-      LIR* branch = OpCmpImmBranch(kCondEq, rl_result.reg.GetReg(), 0, NULL);
+      LIR* branch = OpCmpImmBranch(kCondEq, rl_result.reg, 0, NULL);
       LIR* cont = NewLIR0(kPseudoTargetLabel);
 
       // Object to generate the slow path for class resolution.
@@ -882,8 +877,8 @@
           GenerateTargetLabel();
 
           m2l_->CallRuntimeHelperImmReg(QUICK_ENTRYPOINT_OFFSET(pInitializeType), type_idx_,
-                                        rl_method_.reg.GetReg(), true);
-          m2l_->OpRegCopy(rl_result_.reg.GetReg(),  m2l_->TargetReg(kRet0));
+                                        rl_method_.reg, true);
+          m2l_->OpRegCopy(rl_result_.reg,  m2l_->TargetReg(kRet0));
 
           m2l_->OpUnconditionalBranch(cont_);
         }
@@ -895,8 +890,7 @@
       };
 
       // Add to list for future.
-      AddSlowPath(new (arena_) SlowPath(this, branch, cont,
-                                        type_idx, rl_method, rl_result));
+      AddSlowPath(new (arena_) SlowPath(this, branch, cont, type_idx, rl_method, rl_result));
 
       StoreValue(rl_dest, rl_result);
      } else {
@@ -918,11 +912,11 @@
 
     // If the Method* is already in a register, we can save a copy.
     RegLocation rl_method = mir_graph_->GetMethodLoc();
-    int r_method;
+    RegStorage r_method;
     if (rl_method.location == kLocPhysReg) {
       // A temp would conflict with register use below.
-      DCHECK(!IsTemp(rl_method.reg.GetReg()));
-      r_method = rl_method.reg.GetReg();
+      DCHECK(!IsTemp(rl_method.reg));
+      r_method = rl_method.reg;
     } else {
       r_method = TargetReg(kArg2);
       LoadCurrMethodDirect(r_method);
@@ -943,14 +937,14 @@
       // Object to generate the slow path for string resolution.
       class SlowPath : public LIRSlowPath {
        public:
-        SlowPath(Mir2Lir* m2l, LIR* fromfast, LIR* cont, int r_method) :
+        SlowPath(Mir2Lir* m2l, LIR* fromfast, LIR* cont, RegStorage r_method) :
           LIRSlowPath(m2l, m2l->GetCurrentDexPc(), fromfast, cont), r_method_(r_method) {
         }
 
         void Compile() {
           GenerateTargetLabel();
 
-          int r_tgt = m2l_->CallHelperSetup(QUICK_ENTRYPOINT_OFFSET(pResolveString));
+          RegStorage r_tgt = m2l_->CallHelperSetup(QUICK_ENTRYPOINT_OFFSET(pResolveString));
 
           m2l_->OpRegCopy(m2l_->TargetReg(kArg0), r_method_);   // .eq
           LIR* call_inst = m2l_->OpReg(kOpBlx, r_tgt);
@@ -961,7 +955,7 @@
         }
 
        private:
-         int r_method_;
+         RegStorage r_method_;
       };
 
       // Add to list for future.
@@ -970,8 +964,8 @@
       DCHECK_EQ(cu_->instruction_set, kX86);
       LIR* branch = OpCmpImmBranch(kCondNe, TargetReg(kRet0), 0, NULL);
       LoadConstant(TargetReg(kArg1), string_idx);
-      CallRuntimeHelperRegReg(QUICK_ENTRYPOINT_OFFSET(pResolveString), r_method,
-                              TargetReg(kArg1), true);
+      CallRuntimeHelperRegReg(QUICK_ENTRYPOINT_OFFSET(pResolveString), r_method, TargetReg(kArg1),
+                              true);
       LIR* target = NewLIR0(kPseudoTargetLabel);
       branch->target = target;
     }
@@ -979,11 +973,10 @@
     StoreValue(rl_dest, GetReturn(false));
   } else {
     RegLocation rl_method = LoadCurrMethod();
-    int res_reg = AllocTemp();
+    RegStorage res_reg = AllocTemp();
     RegLocation rl_result = EvalLoc(rl_dest, kCoreReg, true);
-    LoadWordDisp(rl_method.reg.GetReg(),
-                 mirror::ArtMethod::DexCacheStringsOffset().Int32Value(), res_reg);
-    LoadWordDisp(res_reg, offset_of_string, rl_result.reg.GetReg());
+    LoadWordDisp(rl_method.reg, mirror::ArtMethod::DexCacheStringsOffset().Int32Value(), res_reg);
+    LoadWordDisp(res_reg, offset_of_string, rl_result.reg);
     StoreValue(rl_dest, rl_result);
   }
 }
@@ -1056,25 +1049,24 @@
 
   RegLocation object = LoadValue(rl_src, kCoreReg);
   RegLocation rl_result = EvalLoc(rl_dest, kCoreReg, true);
-  int result_reg = rl_result.reg.GetReg();
-  if (result_reg == object.reg.GetReg()) {
+  RegStorage result_reg = rl_result.reg;
+  if (result_reg == object.reg) {
     result_reg = AllocTypedTemp(false, kCoreReg);
   }
   LoadConstant(result_reg, 0);     // assume false
-  LIR* null_branchover = OpCmpImmBranch(kCondEq, object.reg.GetReg(), 0, NULL);
+  LIR* null_branchover = OpCmpImmBranch(kCondEq, object.reg, 0, NULL);
 
-  int check_class = AllocTypedTemp(false, kCoreReg);
-  int object_class = AllocTypedTemp(false, kCoreReg);
+  RegStorage check_class = AllocTypedTemp(false, kCoreReg);
+  RegStorage object_class = AllocTypedTemp(false, kCoreReg);
 
   LoadCurrMethodDirect(check_class);
   if (use_declaring_class) {
-    LoadWordDisp(check_class, mirror::ArtMethod::DeclaringClassOffset().Int32Value(),
-                 check_class);
-    LoadWordDisp(object.reg.GetReg(),  mirror::Object::ClassOffset().Int32Value(), object_class);
+    LoadWordDisp(check_class, mirror::ArtMethod::DeclaringClassOffset().Int32Value(), check_class);
+    LoadWordDisp(object.reg,  mirror::Object::ClassOffset().Int32Value(), object_class);
   } else {
     LoadWordDisp(check_class, mirror::ArtMethod::DexCacheResolvedTypesOffset().Int32Value(),
                  check_class);
-    LoadWordDisp(object.reg.GetReg(),  mirror::Object::ClassOffset().Int32Value(), object_class);
+    LoadWordDisp(object.reg,  mirror::Object::ClassOffset().Int32Value(), object_class);
     int32_t offset_of_type =
       mirror::Array::DataOffset(sizeof(mirror::Class*)).Int32Value() +
       (sizeof(mirror::Class*) * type_idx);
@@ -1098,7 +1090,7 @@
   FreeTemp(object_class);
   FreeTemp(check_class);
   if (IsTemp(result_reg)) {
-    OpRegCopy(rl_result.reg.GetReg(), result_reg);
+    OpRegCopy(rl_result.reg, result_reg);
     FreeTemp(result_reg);
   }
   StoreValue(rl_dest, rl_result);
@@ -1116,7 +1108,7 @@
   // May generate a call - use explicit registers
   LockCallTemps();
   LoadCurrMethodDirect(TargetReg(kArg1));  // kArg1 <= current Method*
-  int class_reg = TargetReg(kArg2);  // kArg2 will hold the Class*
+  RegStorage class_reg = TargetReg(kArg2);  // kArg2 will hold the Class*
   if (needs_access_check) {
     // Check we have access to type_idx and if not throw IllegalAccessError,
     // returns Class* in kArg0
@@ -1126,13 +1118,13 @@
     LoadValueDirectFixed(rl_src, TargetReg(kArg0));  // kArg0 <= ref
   } else if (use_declaring_class) {
     LoadValueDirectFixed(rl_src, TargetReg(kArg0));  // kArg0 <= ref
-    LoadWordDisp(TargetReg(kArg1),
-                 mirror::ArtMethod::DeclaringClassOffset().Int32Value(), class_reg);
+    LoadWordDisp(TargetReg(kArg1), mirror::ArtMethod::DeclaringClassOffset().Int32Value(),
+                 class_reg);
   } else {
     // Load dex cache entry into class_reg (kArg2)
     LoadValueDirectFixed(rl_src, TargetReg(kArg0));  // kArg0 <= ref
-    LoadWordDisp(TargetReg(kArg1),
-                 mirror::ArtMethod::DexCacheResolvedTypesOffset().Int32Value(), class_reg);
+    LoadWordDisp(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);
@@ -1154,7 +1146,7 @@
   RegLocation rl_result = GetReturn(false);
   if (cu_->instruction_set == kMips) {
     // On MIPS rArg0 != rl_result, place false in result if branch is taken.
-    LoadConstant(rl_result.reg.GetReg(), 0);
+    LoadConstant(rl_result.reg, 0);
   }
   LIR* branch1 = OpCmpImmBranch(kCondEq, TargetReg(kArg0), 0, NULL);
 
@@ -1168,16 +1160,16 @@
     if (cu_->instruction_set == kThumb2) {
       OpRegReg(kOpCmp, TargetReg(kArg1), TargetReg(kArg2));  // Same?
       OpIT(kCondEq, "E");   // if-convert the test
-      LoadConstant(rl_result.reg.GetReg(), 1);     // .eq case - load true
-      LoadConstant(rl_result.reg.GetReg(), 0);     // .ne case - load false
+      LoadConstant(rl_result.reg, 1);     // .eq case - load true
+      LoadConstant(rl_result.reg, 0);     // .ne case - load false
     } else {
-      LoadConstant(rl_result.reg.GetReg(), 0);     // ne case - load false
+      LoadConstant(rl_result.reg, 0);     // ne case - load false
       branchover = OpCmpBranch(kCondNe, TargetReg(kArg1), TargetReg(kArg2), NULL);
-      LoadConstant(rl_result.reg.GetReg(), 1);     // eq case - load true
+      LoadConstant(rl_result.reg, 1);     // eq case - load true
     }
   } else {
     if (cu_->instruction_set == kThumb2) {
-      int r_tgt = LoadHelper(QUICK_ENTRYPOINT_OFFSET(pInstanceofNonTrivial));
+      RegStorage r_tgt = LoadHelper(QUICK_ENTRYPOINT_OFFSET(pInstanceofNonTrivial));
       if (!type_known_abstract) {
       /* Uses conditional nullification */
         OpRegReg(kOpCmp, TargetReg(kArg1), TargetReg(kArg2));  // Same?
@@ -1190,10 +1182,10 @@
     } else {
       if (!type_known_abstract) {
         /* Uses branchovers */
-        LoadConstant(rl_result.reg.GetReg(), 1);     // assume true
+        LoadConstant(rl_result.reg, 1);     // assume true
         branchover = OpCmpBranch(kCondEq, TargetReg(kArg1), TargetReg(kArg2), NULL);
       }
-      int r_tgt = LoadHelper(QUICK_ENTRYPOINT_OFFSET(pInstanceofNonTrivial));
+      RegStorage r_tgt = LoadHelper(QUICK_ENTRYPOINT_OFFSET(pInstanceofNonTrivial));
       OpRegCopy(TargetReg(kArg0), TargetReg(kArg2));    // .ne case - arg0 <= class
       OpReg(kOpBlx, r_tgt);    // .ne case: helper(class, ref->class)
       FreeTemp(r_tgt);
@@ -1249,7 +1241,7 @@
   // May generate a call - use explicit registers
   LockCallTemps();
   LoadCurrMethodDirect(TargetReg(kArg1));  // kArg1 <= current Method*
-  int class_reg = TargetReg(kArg2);  // kArg2 will hold the Class*
+  RegStorage class_reg = TargetReg(kArg2);  // kArg2 will hold the Class*
   if (needs_access_check) {
     // Check we have access to type_idx and if not throw IllegalAccessError,
     // returns Class* in kRet0
@@ -1258,12 +1250,12 @@
                             type_idx, TargetReg(kArg1), true);
     OpRegCopy(class_reg, TargetReg(kRet0));  // Align usage with fast path
   } else if (use_declaring_class) {
-    LoadWordDisp(TargetReg(kArg1),
-                 mirror::ArtMethod::DeclaringClassOffset().Int32Value(), class_reg);
+    LoadWordDisp(TargetReg(kArg1), mirror::ArtMethod::DeclaringClassOffset().Int32Value(),
+                 class_reg);
   } else {
     // Load dex cache entry into class_reg (kArg2)
-    LoadWordDisp(TargetReg(kArg1),
-                 mirror::ArtMethod::DexCacheResolvedTypesOffset().Int32Value(), class_reg);
+    LoadWordDisp(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);
@@ -1277,7 +1269,7 @@
       class SlowPath : public LIRSlowPath {
        public:
         SlowPath(Mir2Lir* m2l, LIR* fromfast, LIR* cont, const int type_idx,
-                 const int class_reg) :
+                 const RegStorage class_reg) :
                    LIRSlowPath(m2l, m2l->GetCurrentDexPc(), fromfast, cont), type_idx_(type_idx),
                    class_reg_(class_reg) {
         }
@@ -1294,11 +1286,10 @@
         }
        public:
         const int type_idx_;
-        const int class_reg_;
+        const RegStorage class_reg_;
       };
 
-      AddSlowPath(new (arena_) SlowPath(this, hop_branch, cont,
-                                        type_idx, class_reg));
+      AddSlowPath(new (arena_) SlowPath(this, hop_branch, cont, type_idx, class_reg));
     }
   }
   // At this point, class_reg (kArg2) has class
@@ -1343,8 +1334,7 @@
     LIR* branch1 = OpCmpImmBranch(kCondEq, TargetReg(kArg0), 0, NULL);
     /* load object->klass_ */
     DCHECK_EQ(mirror::Object::ClassOffset().Int32Value(), 0);
-    LoadWordDisp(TargetReg(kArg0), mirror::Object::ClassOffset().Int32Value(),
-                    TargetReg(kArg1));
+    LoadWordDisp(TargetReg(kArg0), mirror::Object::ClassOffset().Int32Value(), TargetReg(kArg1));
 
     LIR* branch2 = OpCmpBranch(kCondNe, TargetReg(kArg1), class_reg, NULL);
     LIR* cont = NewLIR0(kPseudoTargetLabel);
@@ -1376,16 +1366,15 @@
   rl_src2 = LoadValueWide(rl_src2, kCoreReg);
   rl_result = EvalLoc(rl_dest, kCoreReg, true);
   // The longs may overlap - use intermediate temp if so
-  if ((rl_result.reg.GetReg() == rl_src1.reg.GetHighReg()) || (rl_result.reg.GetReg() == rl_src2.reg.GetHighReg())) {
-    int t_reg = AllocTemp();
-    OpRegRegReg(first_op, t_reg, rl_src1.reg.GetReg(), rl_src2.reg.GetReg());
-    OpRegRegReg(second_op, rl_result.reg.GetHighReg(), rl_src1.reg.GetHighReg(), rl_src2.reg.GetHighReg());
-    OpRegCopy(rl_result.reg.GetReg(), t_reg);
+  if ((rl_result.reg.GetLowReg() == rl_src1.reg.GetHighReg()) || (rl_result.reg.GetLowReg() == rl_src2.reg.GetHighReg())) {
+    RegStorage t_reg = AllocTemp();
+    OpRegRegReg(first_op, t_reg, rl_src1.reg.GetLow(), rl_src2.reg.GetLow());
+    OpRegRegReg(second_op, rl_result.reg.GetHigh(), rl_src1.reg.GetHigh(), rl_src2.reg.GetHigh());
+    OpRegCopy(rl_result.reg.GetLow(), t_reg);
     FreeTemp(t_reg);
   } else {
-    OpRegRegReg(first_op, rl_result.reg.GetReg(), rl_src1.reg.GetReg(), rl_src2.reg.GetReg());
-    OpRegRegReg(second_op, rl_result.reg.GetHighReg(), rl_src1.reg.GetHighReg(),
-                rl_src2.reg.GetHighReg());
+    OpRegRegReg(first_op, rl_result.reg.GetLow(), rl_src1.reg.GetLow(), rl_src2.reg.GetLow());
+    OpRegRegReg(second_op, rl_result.reg.GetHigh(), rl_src1.reg.GetHigh(), rl_src2.reg.GetHigh());
   }
   /*
    * NOTE: If rl_dest refers to a frame variable in a large frame, the
@@ -1508,22 +1497,21 @@
     if (unary) {
       rl_src1 = LoadValue(rl_src1, kCoreReg);
       rl_result = EvalLoc(rl_dest, kCoreReg, true);
-      OpRegReg(op, rl_result.reg.GetReg(), rl_src1.reg.GetReg());
+      OpRegReg(op, rl_result.reg, rl_src1.reg);
     } else {
       if (shift_op) {
-        int t_reg = INVALID_REG;
         rl_src2 = LoadValue(rl_src2, kCoreReg);
-        t_reg = AllocTemp();
-        OpRegRegImm(kOpAnd, t_reg, rl_src2.reg.GetReg(), 31);
+        RegStorage t_reg = AllocTemp();
+        OpRegRegImm(kOpAnd, t_reg, rl_src2.reg, 31);
         rl_src1 = LoadValue(rl_src1, kCoreReg);
         rl_result = EvalLoc(rl_dest, kCoreReg, true);
-        OpRegRegReg(op, rl_result.reg.GetReg(), rl_src1.reg.GetReg(), t_reg);
+        OpRegRegReg(op, rl_result.reg, rl_src1.reg, t_reg);
         FreeTemp(t_reg);
       } else {
         rl_src1 = LoadValue(rl_src1, kCoreReg);
         rl_src2 = LoadValue(rl_src2, kCoreReg);
         rl_result = EvalLoc(rl_dest, kCoreReg, true);
-        OpRegRegReg(op, rl_result.reg.GetReg(), rl_src1.reg.GetReg(), rl_src2.reg.GetReg());
+        OpRegRegReg(op, rl_result.reg, rl_src1.reg, rl_src2.reg);
       }
     }
     StoreValue(rl_dest, rl_result);
@@ -1533,9 +1521,9 @@
       rl_src1 = LoadValue(rl_src1, kCoreReg);
       rl_src2 = LoadValue(rl_src2, kCoreReg);
       if (check_zero) {
-          GenImmedCheck(kCondEq, rl_src2.reg.GetReg(), 0, kThrowDivZero);
+          GenImmedCheck(kCondEq, rl_src2.reg, 0, kThrowDivZero);
       }
-      rl_result = GenDivRem(rl_dest, rl_src1.reg.GetReg(), rl_src2.reg.GetReg(), op == kOpDiv);
+      rl_result = GenDivRem(rl_dest, rl_src1.reg, rl_src2.reg, op == kOpDiv);
       done = true;
     } else if (cu_->instruction_set == kThumb2) {
       if (cu_->GetInstructionSetFeatures().HasDivideInstruction()) {
@@ -1544,9 +1532,9 @@
         rl_src1 = LoadValue(rl_src1, kCoreReg);
         rl_src2 = LoadValue(rl_src2, kCoreReg);
         if (check_zero) {
-            GenImmedCheck(kCondEq, rl_src2.reg.GetReg(), 0, kThrowDivZero);
+            GenImmedCheck(kCondEq, rl_src2.reg, 0, kThrowDivZero);
         }
-        rl_result = GenDivRem(rl_dest, rl_src1.reg.GetReg(), rl_src2.reg.GetReg(), op == kOpDiv);
+        rl_result = GenDivRem(rl_dest, rl_src1.reg, rl_src2.reg, op == kOpDiv);
         done = true;
       }
     }
@@ -1556,7 +1544,7 @@
       ThreadOffset func_offset = QUICK_ENTRYPOINT_OFFSET(pIdivmod);
       FlushAllRegs();   /* Send everything to home location */
       LoadValueDirectFixed(rl_src2, TargetReg(kArg1));
-      int r_tgt = CallHelperSetup(func_offset);
+      RegStorage r_tgt = CallHelperSetup(func_offset);
       LoadValueDirectFixed(rl_src1, TargetReg(kArg0));
       if (check_zero) {
         GenImmedCheck(kCondEq, TargetReg(kArg1), 0, kThrowDivZero);
@@ -1603,32 +1591,32 @@
   rl_src = LoadValue(rl_src, kCoreReg);
   RegLocation rl_result = EvalLoc(rl_dest, kCoreReg, true);
   if (is_div) {
-    int t_reg = AllocTemp();
+    RegStorage t_reg = AllocTemp();
     if (lit == 2) {
       // Division by 2 is by far the most common division by constant.
-      OpRegRegImm(kOpLsr, t_reg, rl_src.reg.GetReg(), 32 - k);
-      OpRegRegReg(kOpAdd, t_reg, t_reg, rl_src.reg.GetReg());
-      OpRegRegImm(kOpAsr, rl_result.reg.GetReg(), t_reg, k);
+      OpRegRegImm(kOpLsr, t_reg, rl_src.reg, 32 - k);
+      OpRegRegReg(kOpAdd, t_reg, t_reg, rl_src.reg);
+      OpRegRegImm(kOpAsr, rl_result.reg, t_reg, k);
     } else {
-      OpRegRegImm(kOpAsr, t_reg, rl_src.reg.GetReg(), 31);
+      OpRegRegImm(kOpAsr, t_reg, rl_src.reg, 31);
       OpRegRegImm(kOpLsr, t_reg, t_reg, 32 - k);
-      OpRegRegReg(kOpAdd, t_reg, t_reg, rl_src.reg.GetReg());
-      OpRegRegImm(kOpAsr, rl_result.reg.GetReg(), t_reg, k);
+      OpRegRegReg(kOpAdd, t_reg, t_reg, rl_src.reg);
+      OpRegRegImm(kOpAsr, rl_result.reg, t_reg, k);
     }
   } else {
-    int t_reg1 = AllocTemp();
-    int t_reg2 = AllocTemp();
+    RegStorage t_reg1 = AllocTemp();
+    RegStorage t_reg2 = AllocTemp();
     if (lit == 2) {
-      OpRegRegImm(kOpLsr, t_reg1, rl_src.reg.GetReg(), 32 - k);
-      OpRegRegReg(kOpAdd, t_reg2, t_reg1, rl_src.reg.GetReg());
+      OpRegRegImm(kOpLsr, t_reg1, rl_src.reg, 32 - k);
+      OpRegRegReg(kOpAdd, t_reg2, t_reg1, rl_src.reg);
       OpRegRegImm(kOpAnd, t_reg2, t_reg2, lit -1);
-      OpRegRegReg(kOpSub, rl_result.reg.GetReg(), t_reg2, t_reg1);
+      OpRegRegReg(kOpSub, rl_result.reg, t_reg2, t_reg1);
     } else {
-      OpRegRegImm(kOpAsr, t_reg1, rl_src.reg.GetReg(), 31);
+      OpRegRegImm(kOpAsr, t_reg1, rl_src.reg, 31);
       OpRegRegImm(kOpLsr, t_reg1, t_reg1, 32 - k);
-      OpRegRegReg(kOpAdd, t_reg2, t_reg1, rl_src.reg.GetReg());
+      OpRegRegReg(kOpAdd, t_reg2, t_reg1, rl_src.reg);
       OpRegRegImm(kOpAnd, t_reg2, t_reg2, lit - 1);
-      OpRegRegReg(kOpSub, rl_result.reg.GetReg(), t_reg2, t_reg1);
+      OpRegRegReg(kOpSub, rl_result.reg, t_reg2, t_reg1);
     }
   }
   StoreValue(rl_dest, rl_result);
@@ -1658,7 +1646,7 @@
   RegLocation rl_result = EvalLoc(rl_dest, kCoreReg, true);
   if (power_of_two) {
     // Shift.
-    OpRegRegImm(kOpLsl, rl_result.reg.GetReg(), rl_src.reg.GetReg(), LowestSetBit(lit));
+    OpRegRegImm(kOpLsl, rl_result.reg, rl_src.reg, LowestSetBit(lit));
   } else if (pop_count_le2) {
     // Shift and add and shift.
     int first_bit = LowestSetBit(lit);
@@ -1668,9 +1656,9 @@
     // Reverse subtract: (src << (shift + 1)) - src.
     DCHECK(power_of_two_minus_one);
     // TUNING: rsb dst, src, src lsl#LowestSetBit(lit + 1)
-    int t_reg = AllocTemp();
-    OpRegRegImm(kOpLsl, t_reg, rl_src.reg.GetReg(), LowestSetBit(lit + 1));
-    OpRegRegReg(kOpSub, rl_result.reg.GetReg(), t_reg, rl_src.reg.GetReg());
+    RegStorage t_reg = AllocTemp();
+    OpRegRegImm(kOpLsl, t_reg, rl_src.reg, LowestSetBit(lit + 1));
+    OpRegRegReg(kOpSub, rl_result.reg, t_reg, rl_src.reg);
   }
   StoreValue(rl_dest, rl_result);
   return true;
@@ -1689,10 +1677,10 @@
       rl_src = LoadValue(rl_src, kCoreReg);
       rl_result = EvalLoc(rl_dest, kCoreReg, true);
       if (cu_->instruction_set == kThumb2) {
-        OpRegRegImm(kOpRsub, rl_result.reg.GetReg(), rl_src.reg.GetReg(), lit);
+        OpRegRegImm(kOpRsub, rl_result.reg, rl_src.reg, lit);
       } else {
-        OpRegReg(kOpNeg, rl_result.reg.GetReg(), rl_src.reg.GetReg());
-        OpRegImm(kOpAdd, rl_result.reg.GetReg(), lit);
+        OpRegReg(kOpNeg, rl_result.reg, rl_src.reg);
+        OpRegImm(kOpAdd, rl_result.reg, lit);
       }
       StoreValue(rl_dest, rl_result);
       return;
@@ -1767,7 +1755,7 @@
     case Instruction::REM_INT_LIT8:
     case Instruction::REM_INT_LIT16: {
       if (lit == 0) {
-        GenImmedCheck(kCondAl, 0, 0, kThrowDivZero);
+        GenImmedCheck(kCondAl, RegStorage::InvalidReg(), 0, kThrowDivZero);
         return;
       }
       if ((opcode == Instruction::DIV_INT) ||
@@ -1785,7 +1773,7 @@
       bool done = false;
       if (cu_->instruction_set == kMips) {
         rl_src = LoadValue(rl_src, kCoreReg);
-        rl_result = GenDivRemLit(rl_dest, rl_src.reg.GetReg(), lit, is_div);
+        rl_result = GenDivRemLit(rl_dest, rl_src.reg, lit, is_div);
         done = true;
       } else if (cu_->instruction_set == kX86) {
         rl_result = GenDivRemLit(rl_dest, rl_src, lit, is_div);
@@ -1795,7 +1783,7 @@
           // Use ARM SDIV instruction for division.  For remainder we also need to
           // calculate using a MUL and subtract.
           rl_src = LoadValue(rl_src, kCoreReg);
-          rl_result = GenDivRemLit(rl_dest, rl_src.reg.GetReg(), lit, is_div);
+          rl_result = GenDivRemLit(rl_dest, rl_src.reg, lit, is_div);
           done = true;
         }
       }
@@ -1821,9 +1809,9 @@
   rl_result = EvalLoc(rl_dest, kCoreReg, true);
   // Avoid shifts by literal 0 - no support in Thumb.  Change to copy.
   if (shift_op && (lit == 0)) {
-    OpRegCopy(rl_result.reg.GetReg(), rl_src.reg.GetReg());
+    OpRegCopy(rl_result.reg, rl_src.reg);
   } else {
-    OpRegRegImm(op, rl_result.reg.GetReg(), rl_src.reg.GetReg(), lit);
+    OpRegRegImm(op, rl_result.reg, rl_src.reg, lit);
   }
   StoreValue(rl_dest, rl_result);
 }
@@ -1836,22 +1824,22 @@
   bool call_out = false;
   bool check_zero = false;
   ThreadOffset func_offset(-1);
-  int ret_reg = TargetReg(kRet0);
+  int ret_reg = TargetReg(kRet0).GetReg();
 
   switch (opcode) {
     case Instruction::NOT_LONG:
       rl_src2 = LoadValueWide(rl_src2, kCoreReg);
       rl_result = EvalLoc(rl_dest, kCoreReg, true);
       // Check for destructive overlap
-      if (rl_result.reg.GetReg() == rl_src2.reg.GetHighReg()) {
-        int t_reg = AllocTemp();
-        OpRegCopy(t_reg, rl_src2.reg.GetHighReg());
-        OpRegReg(kOpMvn, rl_result.reg.GetReg(), rl_src2.reg.GetReg());
-        OpRegReg(kOpMvn, rl_result.reg.GetHighReg(), t_reg);
+      if (rl_result.reg.GetLowReg() == rl_src2.reg.GetHighReg()) {
+        RegStorage t_reg = AllocTemp();
+        OpRegCopy(t_reg, rl_src2.reg.GetHigh());
+        OpRegReg(kOpMvn, rl_result.reg.GetLow(), rl_src2.reg.GetLow());
+        OpRegReg(kOpMvn, rl_result.reg.GetHigh(), t_reg);
         FreeTemp(t_reg);
       } else {
-        OpRegReg(kOpMvn, rl_result.reg.GetReg(), rl_src2.reg.GetReg());
-        OpRegReg(kOpMvn, rl_result.reg.GetHighReg(), rl_src2.reg.GetHighReg());
+        OpRegReg(kOpMvn, rl_result.reg.GetLow(), rl_src2.reg.GetLow());
+        OpRegReg(kOpMvn, rl_result.reg.GetHigh(), rl_src2.reg.GetHigh());
       }
       StoreValueWide(rl_dest, rl_result);
       return;
@@ -1880,7 +1868,7 @@
         return;
       } else {
         call_out = true;
-        ret_reg = TargetReg(kRet0);
+        ret_reg = TargetReg(kRet0).GetReg();
         func_offset = QUICK_ENTRYPOINT_OFFSET(pLmul);
       }
       break;
@@ -1888,7 +1876,7 @@
     case Instruction::DIV_LONG_2ADDR:
       call_out = true;
       check_zero = true;
-      ret_reg = TargetReg(kRet0);
+      ret_reg = TargetReg(kRet0).GetReg();
       func_offset = QUICK_ENTRYPOINT_OFFSET(pLdiv);
       break;
     case Instruction::REM_LONG:
@@ -1897,7 +1885,7 @@
       check_zero = true;
       func_offset = QUICK_ENTRYPOINT_OFFSET(pLmod);
       /* NOTE - for Arm, result is in kArg2/kArg3 instead of kRet0/kRet1 */
-      ret_reg = (cu_->instruction_set == kThumb2) ? TargetReg(kArg2) : TargetReg(kRet0);
+      ret_reg = (cu_->instruction_set == kThumb2) ? TargetReg(kArg2).GetReg() : TargetReg(kRet0).GetReg();
       break;
     case Instruction::AND_LONG_2ADDR:
     case Instruction::AND_LONG:
@@ -1937,17 +1925,19 @@
   } else {
     FlushAllRegs();   /* Send everything to home location */
     if (check_zero) {
-      LoadValueDirectWideFixed(rl_src2, TargetReg(kArg2), TargetReg(kArg3));
-      int r_tgt = CallHelperSetup(func_offset);
-      GenDivZeroCheck(TargetReg(kArg2), TargetReg(kArg3));
-      LoadValueDirectWideFixed(rl_src1, TargetReg(kArg0), TargetReg(kArg1));
+      RegStorage r_tmp1 = RegStorage::MakeRegPair(TargetReg(kArg0), TargetReg(kArg1));
+      RegStorage r_tmp2 = RegStorage::MakeRegPair(TargetReg(kArg2), TargetReg(kArg3));
+      LoadValueDirectWideFixed(rl_src2, r_tmp2);
+      RegStorage r_tgt = CallHelperSetup(func_offset);
+      GenDivZeroCheck(RegStorage::MakeRegPair(TargetReg(kArg2), TargetReg(kArg3)));
+      LoadValueDirectWideFixed(rl_src1, r_tmp1);
       // NOTE: callout here is not a safepoint
       CallHelper(r_tgt, func_offset, false /* not safepoint */);
     } else {
       CallRuntimeHelperRegLocationRegLocation(func_offset, rl_src1, rl_src2, false);
     }
     // Adjust return regs in to handle case of rem returning kArg2/kArg3
-    if (ret_reg == TargetReg(kRet0))
+    if (ret_reg == TargetReg(kRet0).GetReg())
       rl_result = GetReturnWide(false);
     else
       rl_result = GetReturnWideAlt();
@@ -2040,7 +2030,7 @@
 /* Generic code for generating a wide constant into a VR. */
 void Mir2Lir::GenConstWide(RegLocation rl_dest, int64_t value) {
   RegLocation rl_result = EvalLoc(rl_dest, kAnyReg, true);
-  LoadConstantWide(rl_result.reg.GetReg(), rl_result.reg.GetHighReg(), value);
+  LoadConstantWide(rl_result.reg, value);
   StoreValueWide(rl_dest, rl_result);
 }
 
diff --git a/compiler/dex/quick/gen_invoke.cc b/compiler/dex/quick/gen_invoke.cc
index 9e50749..a0242d5 100644
--- a/compiler/dex/quick/gen_invoke.cc
+++ b/compiler/dex/quick/gen_invoke.cc
@@ -66,12 +66,13 @@
  * has a memory call operation, part 1 is a NOP for x86.  For other targets,
  * load arguments between the two parts.
  */
-int Mir2Lir::CallHelperSetup(ThreadOffset helper_offset) {
-  return (cu_->instruction_set == kX86) ? 0 : LoadHelper(helper_offset);
+RegStorage Mir2Lir::CallHelperSetup(ThreadOffset helper_offset) {
+  return (cu_->instruction_set == kX86) ? RegStorage::InvalidReg() : LoadHelper(helper_offset);
 }
 
 /* NOTE: if r_tgt is a temp, it will be freed following use */
-LIR* Mir2Lir::CallHelper(int r_tgt, ThreadOffset helper_offset, bool safepoint_pc, bool use_link) {
+LIR* Mir2Lir::CallHelper(RegStorage r_tgt, ThreadOffset helper_offset, bool safepoint_pc,
+                         bool use_link) {
   LIR* call_inst;
   OpKind op = use_link ? kOpBlx : kOpBx;
   if (cu_->instruction_set == kX86) {
@@ -87,14 +88,14 @@
 }
 
 void Mir2Lir::CallRuntimeHelperImm(ThreadOffset helper_offset, int arg0, bool safepoint_pc) {
-  int r_tgt = CallHelperSetup(helper_offset);
+  RegStorage r_tgt = CallHelperSetup(helper_offset);
   LoadConstant(TargetReg(kArg0), arg0);
   ClobberCallerSave();
   CallHelper(r_tgt, helper_offset, safepoint_pc);
 }
 
-void Mir2Lir::CallRuntimeHelperReg(ThreadOffset helper_offset, int arg0, bool safepoint_pc) {
-  int r_tgt = CallHelperSetup(helper_offset);
+void Mir2Lir::CallRuntimeHelperReg(ThreadOffset helper_offset, RegStorage arg0, bool safepoint_pc) {
+  RegStorage r_tgt = CallHelperSetup(helper_offset);
   OpRegCopy(TargetReg(kArg0), arg0);
   ClobberCallerSave();
   CallHelper(r_tgt, helper_offset, safepoint_pc);
@@ -102,12 +103,12 @@
 
 void Mir2Lir::CallRuntimeHelperRegLocation(ThreadOffset helper_offset, RegLocation arg0,
                                            bool safepoint_pc) {
-  int r_tgt = CallHelperSetup(helper_offset);
-  if (arg0.wide) {
-    LoadValueDirectWideFixed(arg0, arg0.fp ? TargetReg(kFArg0) : TargetReg(kArg0),
-        arg0.fp ? TargetReg(kFArg1) : TargetReg(kArg1));
+  RegStorage r_tgt = CallHelperSetup(helper_offset);
+  if (arg0.wide == 0) {
+    LoadValueDirectFixed(arg0, TargetReg(kArg0));
   } else {
-    LoadValueDirectFixed(arg0, arg0.fp ? TargetReg(kFArg0) : TargetReg(kArg0));
+    RegStorage r_tmp = RegStorage::MakeRegPair(TargetReg(kArg0), TargetReg(kArg1));
+    LoadValueDirectWideFixed(arg0, r_tmp);
   }
   ClobberCallerSave();
   CallHelper(r_tgt, helper_offset, safepoint_pc);
@@ -115,7 +116,7 @@
 
 void Mir2Lir::CallRuntimeHelperImmImm(ThreadOffset helper_offset, int arg0, int arg1,
                                       bool safepoint_pc) {
-  int r_tgt = CallHelperSetup(helper_offset);
+  RegStorage r_tgt = CallHelperSetup(helper_offset);
   LoadConstant(TargetReg(kArg0), arg0);
   LoadConstant(TargetReg(kArg1), arg1);
   ClobberCallerSave();
@@ -124,11 +125,12 @@
 
 void Mir2Lir::CallRuntimeHelperImmRegLocation(ThreadOffset helper_offset, int arg0,
                                               RegLocation arg1, bool safepoint_pc) {
-  int r_tgt = CallHelperSetup(helper_offset);
+  RegStorage r_tgt = CallHelperSetup(helper_offset);
   if (arg1.wide == 0) {
     LoadValueDirectFixed(arg1, TargetReg(kArg1));
   } else {
-    LoadValueDirectWideFixed(arg1, TargetReg(kArg1), TargetReg(kArg2));
+    RegStorage r_tmp = RegStorage::MakeRegPair(TargetReg(kArg1), TargetReg(kArg2));
+    LoadValueDirectWideFixed(arg1, r_tmp);
   }
   LoadConstant(TargetReg(kArg0), arg0);
   ClobberCallerSave();
@@ -137,25 +139,25 @@
 
 void Mir2Lir::CallRuntimeHelperRegLocationImm(ThreadOffset helper_offset, RegLocation arg0, int arg1,
                                               bool safepoint_pc) {
-  int r_tgt = CallHelperSetup(helper_offset);
+  RegStorage r_tgt = CallHelperSetup(helper_offset);
   LoadValueDirectFixed(arg0, TargetReg(kArg0));
   LoadConstant(TargetReg(kArg1), arg1);
   ClobberCallerSave();
   CallHelper(r_tgt, helper_offset, safepoint_pc);
 }
 
-void Mir2Lir::CallRuntimeHelperImmReg(ThreadOffset helper_offset, int arg0, int arg1,
+void Mir2Lir::CallRuntimeHelperImmReg(ThreadOffset helper_offset, int arg0, RegStorage arg1,
                                       bool safepoint_pc) {
-  int r_tgt = CallHelperSetup(helper_offset);
+  RegStorage r_tgt = CallHelperSetup(helper_offset);
   OpRegCopy(TargetReg(kArg1), arg1);
   LoadConstant(TargetReg(kArg0), arg0);
   ClobberCallerSave();
   CallHelper(r_tgt, helper_offset, safepoint_pc);
 }
 
-void Mir2Lir::CallRuntimeHelperRegImm(ThreadOffset helper_offset, int arg0, int arg1,
+void Mir2Lir::CallRuntimeHelperRegImm(ThreadOffset helper_offset, RegStorage arg0, int arg1,
                                       bool safepoint_pc) {
-  int r_tgt = CallHelperSetup(helper_offset);
+  RegStorage r_tgt = CallHelperSetup(helper_offset);
   OpRegCopy(TargetReg(kArg0), arg0);
   LoadConstant(TargetReg(kArg1), arg1);
   ClobberCallerSave();
@@ -163,16 +165,17 @@
 }
 
 void Mir2Lir::CallRuntimeHelperImmMethod(ThreadOffset helper_offset, int arg0, bool safepoint_pc) {
-  int r_tgt = CallHelperSetup(helper_offset);
+  RegStorage r_tgt = CallHelperSetup(helper_offset);
   LoadCurrMethodDirect(TargetReg(kArg1));
   LoadConstant(TargetReg(kArg0), arg0);
   ClobberCallerSave();
   CallHelper(r_tgt, helper_offset, safepoint_pc);
 }
 
-void Mir2Lir::CallRuntimeHelperRegMethod(ThreadOffset helper_offset, int arg0, bool safepoint_pc) {
-  int r_tgt = CallHelperSetup(helper_offset);
-  DCHECK_NE(TargetReg(kArg1), arg0);
+void Mir2Lir::CallRuntimeHelperRegMethod(ThreadOffset helper_offset, RegStorage arg0,
+                                         bool safepoint_pc) {
+  RegStorage r_tgt = CallHelperSetup(helper_offset);
+  DCHECK_NE(TargetReg(kArg1).GetReg(), arg0.GetReg());
   if (TargetReg(kArg0) != arg0) {
     OpRegCopy(TargetReg(kArg0), arg0);
   }
@@ -181,10 +184,10 @@
   CallHelper(r_tgt, helper_offset, safepoint_pc);
 }
 
-void Mir2Lir::CallRuntimeHelperRegMethodRegLocation(ThreadOffset helper_offset, int arg0,
+void Mir2Lir::CallRuntimeHelperRegMethodRegLocation(ThreadOffset helper_offset, RegStorage arg0,
                                                     RegLocation arg2, bool safepoint_pc) {
-  int r_tgt = CallHelperSetup(helper_offset);
-  DCHECK_NE(TargetReg(kArg1), arg0);
+  RegStorage r_tgt = CallHelperSetup(helper_offset);
+  DCHECK_NE(TargetReg(kArg1).GetReg(), arg0.GetReg());
   if (TargetReg(kArg0) != arg0) {
     OpRegCopy(TargetReg(kArg0), arg0);
   }
@@ -196,7 +199,7 @@
 
 void Mir2Lir::CallRuntimeHelperRegLocationRegLocation(ThreadOffset helper_offset, RegLocation arg0,
                                                       RegLocation arg1, bool safepoint_pc) {
-  int r_tgt = CallHelperSetup(helper_offset);
+  RegStorage r_tgt = CallHelperSetup(helper_offset);
   if (arg0.wide == 0) {
     LoadValueDirectFixed(arg0, arg0.fp ? TargetReg(kFArg0) : TargetReg(kArg0));
     if (arg1.wide == 0) {
@@ -207,37 +210,56 @@
       }
     } else {
       if (cu_->instruction_set == kMips) {
-        LoadValueDirectWideFixed(arg1, arg1.fp ? TargetReg(kFArg2) : TargetReg(kArg1), arg1.fp ? TargetReg(kFArg3) : TargetReg(kArg2));
+        RegStorage r_tmp;
+        if (arg1.fp) {
+          r_tmp = RegStorage::MakeRegPair(TargetReg(kFArg2), TargetReg(kFArg3));
+        } else {
+          r_tmp = RegStorage::MakeRegPair(TargetReg(kArg1), TargetReg(kArg2));
+        }
+        LoadValueDirectWideFixed(arg1, r_tmp);
       } else {
-        LoadValueDirectWideFixed(arg1, TargetReg(kArg1), TargetReg(kArg2));
+        RegStorage r_tmp = RegStorage::MakeRegPair(TargetReg(kArg1), TargetReg(kArg2));
+        LoadValueDirectWideFixed(arg1, r_tmp);
       }
     }
   } else {
-    LoadValueDirectWideFixed(arg0, arg0.fp ? TargetReg(kFArg0) : TargetReg(kArg0), arg0.fp ? TargetReg(kFArg1) : TargetReg(kArg1));
+    RegStorage r_tmp;
+    if (arg0.fp) {
+      r_tmp = RegStorage::MakeRegPair(TargetReg(kFArg0), TargetReg(kFArg1));
+    } else {
+      r_tmp = RegStorage::MakeRegPair(TargetReg(kArg0), TargetReg(kArg1));
+    }
+    LoadValueDirectWideFixed(arg0, r_tmp);
     if (arg1.wide == 0) {
       LoadValueDirectFixed(arg1, arg1.fp ? TargetReg(kFArg2) : TargetReg(kArg2));
     } else {
-      LoadValueDirectWideFixed(arg1, arg1.fp ? TargetReg(kFArg2) : TargetReg(kArg2), arg1.fp ? TargetReg(kFArg3) : TargetReg(kArg3));
+      RegStorage r_tmp;
+      if (arg1.fp) {
+        r_tmp = RegStorage::MakeRegPair(TargetReg(kFArg2), TargetReg(kFArg3));
+      } else {
+        r_tmp = RegStorage::MakeRegPair(TargetReg(kArg2), TargetReg(kArg3));
+      }
+      LoadValueDirectWideFixed(arg1, r_tmp);
     }
   }
   ClobberCallerSave();
   CallHelper(r_tgt, helper_offset, safepoint_pc);
 }
 
-void Mir2Lir::CallRuntimeHelperRegReg(ThreadOffset helper_offset, int arg0, int arg1,
-                                      bool safepoint_pc) {
-  int r_tgt = CallHelperSetup(helper_offset);
-  DCHECK_NE(TargetReg(kArg0), arg1);  // check copy into arg0 won't clobber arg1
+void Mir2Lir::CallRuntimeHelperRegReg(ThreadOffset helper_offset, RegStorage arg0,
+                                      RegStorage arg1, bool safepoint_pc) {
+  RegStorage r_tgt = CallHelperSetup(helper_offset);
+  DCHECK_NE(TargetReg(kArg0).GetReg(), arg1.GetReg());  // check copy into arg0 won't clobber arg1
   OpRegCopy(TargetReg(kArg0), arg0);
   OpRegCopy(TargetReg(kArg1), arg1);
   ClobberCallerSave();
   CallHelper(r_tgt, helper_offset, safepoint_pc);
 }
 
-void Mir2Lir::CallRuntimeHelperRegRegImm(ThreadOffset helper_offset, int arg0, int arg1,
-                                         int arg2, bool safepoint_pc) {
-  int r_tgt = CallHelperSetup(helper_offset);
-  DCHECK_NE(TargetReg(kArg0), arg1);  // check copy into arg0 won't clobber arg1
+void Mir2Lir::CallRuntimeHelperRegRegImm(ThreadOffset helper_offset, RegStorage arg0,
+                                         RegStorage arg1, int arg2, bool safepoint_pc) {
+  RegStorage r_tgt = CallHelperSetup(helper_offset);
+  DCHECK_NE(TargetReg(kArg0).GetReg(), arg1.GetReg());  // check copy into arg0 won't clobber arg1
   OpRegCopy(TargetReg(kArg0), arg0);
   OpRegCopy(TargetReg(kArg1), arg1);
   LoadConstant(TargetReg(kArg2), arg2);
@@ -247,7 +269,7 @@
 
 void Mir2Lir::CallRuntimeHelperImmMethodRegLocation(ThreadOffset helper_offset,
                                                     int arg0, RegLocation arg2, bool safepoint_pc) {
-  int r_tgt = CallHelperSetup(helper_offset);
+  RegStorage r_tgt = CallHelperSetup(helper_offset);
   LoadValueDirectFixed(arg2, TargetReg(kArg2));
   LoadCurrMethodDirect(TargetReg(kArg1));
   LoadConstant(TargetReg(kArg0), arg0);
@@ -257,7 +279,7 @@
 
 void Mir2Lir::CallRuntimeHelperImmMethodImm(ThreadOffset helper_offset, int arg0,
                                             int arg2, bool safepoint_pc) {
-  int r_tgt = CallHelperSetup(helper_offset);
+  RegStorage r_tgt = CallHelperSetup(helper_offset);
   LoadCurrMethodDirect(TargetReg(kArg1));
   LoadConstant(TargetReg(kArg2), arg2);
   LoadConstant(TargetReg(kArg0), arg0);
@@ -268,13 +290,14 @@
 void Mir2Lir::CallRuntimeHelperImmRegLocationRegLocation(ThreadOffset helper_offset,
                                                          int arg0, RegLocation arg1,
                                                          RegLocation arg2, bool safepoint_pc) {
-  int r_tgt = CallHelperSetup(helper_offset);
+  RegStorage r_tgt = CallHelperSetup(helper_offset);
   DCHECK_EQ(arg1.wide, 0U);
   LoadValueDirectFixed(arg1, TargetReg(kArg1));
   if (arg2.wide == 0) {
     LoadValueDirectFixed(arg2, TargetReg(kArg2));
   } else {
-    LoadValueDirectWideFixed(arg2, TargetReg(kArg2), TargetReg(kArg3));
+    RegStorage r_tmp = RegStorage::MakeRegPair(TargetReg(kArg2), TargetReg(kArg3));
+    LoadValueDirectWideFixed(arg2, r_tmp);
   }
   LoadConstant(TargetReg(kArg0), arg0);
   ClobberCallerSave();
@@ -285,7 +308,7 @@
                                                                  RegLocation arg0, RegLocation arg1,
                                                                  RegLocation arg2,
                                                                  bool safepoint_pc) {
-  int r_tgt = CallHelperSetup(helper_offset);
+  RegStorage r_tgt = CallHelperSetup(helper_offset);
   DCHECK_EQ(arg0.wide, 0U);
   LoadValueDirectFixed(arg0, TargetReg(kArg0));
   DCHECK_EQ(arg1.wide, 0U);
@@ -312,9 +335,9 @@
    */
   RegLocation rl_src = rl_method;
   rl_src.location = kLocPhysReg;
-  rl_src.reg = RegStorage(RegStorage::k32BitSolo, TargetReg(kArg0));
+  rl_src.reg = TargetReg(kArg0);
   rl_src.home = false;
-  MarkLive(rl_src.reg.GetReg(), rl_src.s_reg_low);
+  MarkLive(rl_src.reg, rl_src.s_reg_low);
   StoreValue(rl_method, rl_src);
   // If Method* has been promoted, explicitly flush
   if (rl_method.location == kLocPhysReg) {
@@ -340,17 +363,17 @@
    */
   for (int i = 0; i < cu_->num_ins; i++) {
     PromotionMap* v_map = &promotion_map_[start_vreg + i];
-    int reg = GetArgMappingToPhysicalReg(i);
+    RegStorage reg = GetArgMappingToPhysicalReg(i);
 
-    if (reg != INVALID_REG) {
+    if (reg.Valid()) {
       // If arriving in register
       bool need_flush = true;
       RegLocation* t_loc = &ArgLocs[i];
       if ((v_map->core_location == kLocPhysReg) && !t_loc->fp) {
-        OpRegCopy(v_map->core_reg, reg);
+        OpRegCopy(RegStorage::Solo32(v_map->core_reg), reg);
         need_flush = false;
       } else if ((v_map->fp_location == kLocPhysReg) && t_loc->fp) {
-        OpRegCopy(v_map->FpReg, reg);
+        OpRegCopy(RegStorage::Solo32(v_map->FpReg), reg);
         need_flush = false;
       } else {
         need_flush = true;
@@ -386,11 +409,10 @@
       // If arriving in frame & promoted
       if (v_map->core_location == kLocPhysReg) {
         LoadWordDisp(TargetReg(kSp), SRegOffset(start_vreg + i),
-                     v_map->core_reg);
+                     RegStorage::Solo32(v_map->core_reg));
       }
       if (v_map->fp_location == kLocPhysReg) {
-        LoadWordDisp(TargetReg(kSp), SRegOffset(start_vreg + i),
-                     v_map->FpReg);
+        LoadWordDisp(TargetReg(kSp), SRegOffset(start_vreg + i), RegStorage::Solo32(v_map->FpReg));
       }
     }
   }
@@ -433,7 +455,8 @@
       break;
     case 1:  // Get method->dex_cache_resolved_methods_
       cg->LoadWordDisp(cg->TargetReg(kArg0),
-        mirror::ArtMethod::DexCacheResolvedMethodsOffset().Int32Value(), cg->TargetReg(kArg0));
+                       mirror::ArtMethod::DexCacheResolvedMethodsOffset().Int32Value(),
+                       cg->TargetReg(kArg0));
       // Set up direct code if known.
       if (direct_code != 0) {
         if (direct_code != static_cast<unsigned int>(-1)) {
@@ -448,8 +471,7 @@
       CHECK_EQ(cu->dex_file, target_method.dex_file);
       cg->LoadWordDisp(cg->TargetReg(kArg0),
                        mirror::Array::DataOffset(sizeof(mirror::Object*)).Int32Value() +
-                           (target_method.dex_method_index * 4),
-                       cg-> TargetReg(kArg0));
+                       (target_method.dex_method_index * 4), cg->TargetReg(kArg0));
       break;
     case 3:  // Grab the code from the method*
       if (cu->instruction_set != kX86) {
@@ -643,8 +665,8 @@
                          const MethodReference& target_method,
                          uint32_t vtable_idx, uintptr_t direct_code,
                          uintptr_t direct_method, InvokeType type, bool skip_this) {
-  int last_arg_reg = TargetReg(kArg3);
-  int next_reg = TargetReg(kArg1);
+  int last_arg_reg = TargetReg(kArg3).GetReg();
+  int next_reg = TargetReg(kArg1).GetReg();
   int next_arg = 0;
   if (skip_this) {
     next_reg++;
@@ -653,16 +675,17 @@
   for (; (next_reg <= last_arg_reg) && (next_arg < info->num_arg_words); next_reg++) {
     RegLocation rl_arg = info->args[next_arg++];
     rl_arg = UpdateRawLoc(rl_arg);
-    if (rl_arg.wide && (next_reg <= TargetReg(kArg2))) {
-      LoadValueDirectWideFixed(rl_arg, next_reg, next_reg + 1);
+    if (rl_arg.wide && (next_reg <= TargetReg(kArg2).GetReg())) {
+      RegStorage r_tmp(RegStorage::k64BitPair, next_reg, next_reg + 1);
+      LoadValueDirectWideFixed(rl_arg, r_tmp);
       next_reg++;
       next_arg++;
     } else {
       if (rl_arg.wide) {
-        rl_arg.wide = false;
+        rl_arg = NarrowRegLoc(rl_arg);
         rl_arg.is_const = false;
       }
-      LoadValueDirectFixed(rl_arg, next_reg);
+      LoadValueDirectFixed(rl_arg, RegStorage::Solo32(next_reg));
     }
     call_state = next_call_insn(cu_, info, call_state, target_method, vtable_idx,
                                 direct_code, direct_method, type);
@@ -698,13 +721,12 @@
     RegLocation rl_use0 = info->args[0];
     RegLocation rl_use1 = info->args[1];
     RegLocation rl_use2 = info->args[2];
-    if (((!rl_use0.wide && !rl_use1.wide) || rl_use0.wide) &&
-      rl_use2.wide) {
-      int reg = -1;
+    if (((!rl_use0.wide && !rl_use1.wide) || rl_use0.wide) && rl_use2.wide) {
+      RegStorage reg;
       // Wide spans, we need the 2nd half of uses[2].
       rl_arg = UpdateLocWide(rl_use2);
       if (rl_arg.location == kLocPhysReg) {
-        reg = rl_arg.reg.GetHighReg();
+        reg = rl_arg.reg.GetHigh();
       } else {
         // kArg2 & rArg3 can safely be used here
         reg = TargetReg(kArg3);
@@ -719,20 +741,22 @@
     }
     // Loop through the rest
     while (next_use < info->num_arg_words) {
-      int low_reg;
-      int high_reg = -1;
+      RegStorage low_reg;
+      RegStorage high_reg;
       rl_arg = info->args[next_use];
       rl_arg = UpdateRawLoc(rl_arg);
       if (rl_arg.location == kLocPhysReg) {
-        low_reg = rl_arg.reg.GetReg();
         if (rl_arg.wide) {
-          high_reg = rl_arg.reg.GetHighReg();
+          low_reg = rl_arg.reg.GetLow();
+          high_reg = rl_arg.reg.GetHigh();
+        } else {
+          low_reg = rl_arg.reg;
         }
       } else {
         low_reg = TargetReg(kArg2);
         if (rl_arg.wide) {
           high_reg = TargetReg(kArg3);
-          LoadValueDirectWideFixed(rl_arg, low_reg, high_reg);
+          LoadValueDirectWideFixed(rl_arg, RegStorage::MakeRegPair(low_reg, high_reg));
         } else {
           LoadValueDirectFixed(rl_arg, low_reg);
         }
@@ -741,7 +765,7 @@
       }
       int outs_offset = (next_use + 1) * 4;
       if (rl_arg.wide) {
-        StoreBaseDispWide(TargetReg(kSp), outs_offset, low_reg, high_reg);
+        StoreBaseDispWide(TargetReg(kSp), outs_offset, RegStorage::MakeRegPair(low_reg, high_reg));
         next_use += 2;
       } else {
         StoreWordDisp(TargetReg(kSp), outs_offset, low_reg);
@@ -799,15 +823,13 @@
     if (loc.wide) {
       loc = UpdateLocWide(loc);
       if ((next_arg >= 2) && (loc.location == kLocPhysReg)) {
-        StoreBaseDispWide(TargetReg(kSp), SRegOffset(loc.s_reg_low),
-                          loc.reg.GetReg(), loc.reg.GetHighReg());
+        StoreBaseDispWide(TargetReg(kSp), SRegOffset(loc.s_reg_low), loc.reg);
       }
       next_arg += 2;
     } else {
       loc = UpdateLoc(loc);
       if ((next_arg >= 3) && (loc.location == kLocPhysReg)) {
-        StoreBaseDisp(TargetReg(kSp), SRegOffset(loc.s_reg_low),
-                      loc.reg.GetReg(), kWord);
+        StoreBaseDisp(TargetReg(kSp), SRegOffset(loc.s_reg_low), loc.reg, kWord);
       }
       next_arg++;
     }
@@ -866,8 +888,8 @@
 
         // Allocate a free xmm temp. Since we are working through the calling sequence,
         // we expect to have an xmm temporary available.
-        int temp = AllocTempDouble();
-        CHECK_GT(temp, 0);
+        RegStorage temp = AllocTempDouble();
+        CHECK_GT(temp.GetLowReg(), 0);
 
         LIR* ld1 = nullptr;
         LIR* ld2 = nullptr;
@@ -888,7 +910,8 @@
           ld1 = OpMovRegMem(temp, TargetReg(kSp), current_src_offset, kMovA128FP);
         } else if (src_is_8b_aligned) {
           ld1 = OpMovRegMem(temp, TargetReg(kSp), current_src_offset, kMovLo128FP);
-          ld2 = OpMovRegMem(temp, TargetReg(kSp), current_src_offset + (bytes_to_move >> 1), kMovHi128FP);
+          ld2 = OpMovRegMem(temp, TargetReg(kSp), current_src_offset + (bytes_to_move >> 1),
+                            kMovHi128FP);
         } else {
           ld1 = OpMovRegMem(temp, TargetReg(kSp), current_src_offset, kMovU128FP);
         }
@@ -897,7 +920,8 @@
           st1 = OpMovMemReg(TargetReg(kSp), current_dest_offset, temp, kMovA128FP);
         } else if (dest_is_8b_aligned) {
           st1 = OpMovMemReg(TargetReg(kSp), current_dest_offset, temp, kMovLo128FP);
-          st2 = OpMovMemReg(TargetReg(kSp), current_dest_offset + (bytes_to_move >> 1), temp, kMovHi128FP);
+          st2 = OpMovMemReg(TargetReg(kSp), current_dest_offset + (bytes_to_move >> 1),
+                            temp, kMovHi128FP);
         } else {
           st1 = OpMovMemReg(TargetReg(kSp), current_dest_offset, temp, kMovU128FP);
         }
@@ -928,14 +952,16 @@
         }
 
         // Free the temporary used for the data movement.
-        FreeTemp(temp);
+        // CLEANUP: temp is currently a bogus pair, elmiminate extra free when updated.
+        FreeTemp(temp.GetLow());
+        FreeTemp(temp.GetHigh());
       } else {
         // Moving 32-bits via general purpose register.
         bytes_to_move = sizeof(uint32_t);
 
         // Instead of allocating a new temp, simply reuse one of the registers being used
         // for argument passing.
-        int temp = TargetReg(kArg3);
+        RegStorage temp = TargetReg(kArg3);
 
         // Now load the argument VR and store to the outs.
         LoadWordDisp(TargetReg(kSp), current_src_offset, temp);
@@ -1007,26 +1033,26 @@
   if (!(cu_->instruction_set == kX86 && rl_idx.is_const)) {
     rl_idx = LoadValue(rl_idx, kCoreReg);
   }
-  int reg_max;
-  GenNullCheck(rl_obj.reg.GetReg(), info->opt_flags);
+  RegStorage reg_max;
+  GenNullCheck(rl_obj.reg, info->opt_flags);
   bool range_check = (!(info->opt_flags & MIR_IGNORE_RANGE_CHECK));
   LIR* range_check_branch = nullptr;
-  int reg_off = INVALID_REG;
-  int reg_ptr = INVALID_REG;
+  RegStorage reg_off;
+  RegStorage reg_ptr;
   if (cu_->instruction_set != kX86) {
     reg_off = AllocTemp();
     reg_ptr = AllocTemp();
     if (range_check) {
       reg_max = AllocTemp();
-      LoadWordDisp(rl_obj.reg.GetReg(), count_offset, reg_max);
+      LoadWordDisp(rl_obj.reg, count_offset, reg_max);
       MarkPossibleNullPointerException(info->opt_flags);
     }
-    LoadWordDisp(rl_obj.reg.GetReg(), offset_offset, reg_off);
+    LoadWordDisp(rl_obj.reg, offset_offset, reg_off);
     MarkPossibleNullPointerException(info->opt_flags);
-    LoadWordDisp(rl_obj.reg.GetReg(), value_offset, reg_ptr);
+    LoadWordDisp(rl_obj.reg, value_offset, reg_ptr);
     if (range_check) {
       // Set up a launch pad to allow retry in case of bounds violation */
-      OpRegReg(kOpCmp, rl_idx.reg.GetReg(), reg_max);
+      OpRegReg(kOpCmp, rl_idx.reg, reg_max);
       FreeTemp(reg_max);
       range_check_branch = OpCondBranch(kCondUge, nullptr);
     }
@@ -1037,34 +1063,34 @@
       // Set up a launch pad to allow retry in case of bounds violation */
       if (rl_idx.is_const) {
         range_check_branch = OpCmpMemImmBranch(
-            kCondUlt, INVALID_REG, rl_obj.reg.GetReg(), count_offset,
+            kCondUlt, RegStorage::InvalidReg(), rl_obj.reg, count_offset,
             mir_graph_->ConstantValue(rl_idx.orig_sreg), nullptr);
       } else {
-        OpRegMem(kOpCmp, rl_idx.reg.GetReg(), rl_obj.reg.GetReg(), count_offset);
+        OpRegMem(kOpCmp, rl_idx.reg, rl_obj.reg, count_offset);
         range_check_branch = OpCondBranch(kCondUge, nullptr);
       }
     }
     reg_off = AllocTemp();
     reg_ptr = AllocTemp();
-    LoadWordDisp(rl_obj.reg.GetReg(), offset_offset, reg_off);
-    LoadWordDisp(rl_obj.reg.GetReg(), value_offset, reg_ptr);
+    LoadWordDisp(rl_obj.reg, offset_offset, reg_off);
+    LoadWordDisp(rl_obj.reg, value_offset, reg_ptr);
   }
   if (rl_idx.is_const) {
     OpRegImm(kOpAdd, reg_off, mir_graph_->ConstantValue(rl_idx.orig_sreg));
   } else {
-    OpRegReg(kOpAdd, reg_off, rl_idx.reg.GetReg());
+    OpRegReg(kOpAdd, reg_off, rl_idx.reg);
   }
-  FreeTemp(rl_obj.reg.GetReg());
+  FreeTemp(rl_obj.reg);
   if (rl_idx.location == kLocPhysReg) {
-    FreeTemp(rl_idx.reg.GetReg());
+    FreeTemp(rl_idx.reg);
   }
   RegLocation rl_dest = InlineTarget(info);
   RegLocation rl_result = EvalLoc(rl_dest, kCoreReg, true);
   if (cu_->instruction_set != kX86) {
-    LoadBaseIndexed(reg_ptr, reg_off, rl_result.reg.GetReg(), 1, kUnsignedHalf);
+    LoadBaseIndexed(reg_ptr, reg_off, rl_result.reg, 1, kUnsignedHalf);
   } else {
-    LoadBaseIndexedDisp(reg_ptr, reg_off, 1, data_offset, rl_result.reg.GetReg(),
-                        INVALID_REG, kUnsignedHalf, INVALID_SREG);
+    LoadBaseIndexedDisp(reg_ptr, reg_off, 1, data_offset, rl_result.reg,
+                        RegStorage::InvalidReg(), kUnsignedHalf, INVALID_SREG);
   }
   FreeTemp(reg_off);
   FreeTemp(reg_ptr);
@@ -1088,20 +1114,19 @@
   rl_obj = LoadValue(rl_obj, kCoreReg);
   RegLocation rl_dest = InlineTarget(info);
   RegLocation rl_result = EvalLoc(rl_dest, kCoreReg, true);
-  GenNullCheck(rl_obj.reg.GetReg(), info->opt_flags);
-  LoadWordDisp(rl_obj.reg.GetReg(), mirror::String::CountOffset().Int32Value(),
-               rl_result.reg.GetReg());
+  GenNullCheck(rl_obj.reg, info->opt_flags);
+  LoadWordDisp(rl_obj.reg, mirror::String::CountOffset().Int32Value(), rl_result.reg);
   MarkPossibleNullPointerException(info->opt_flags);
   if (is_empty) {
     // dst = (dst == 0);
     if (cu_->instruction_set == kThumb2) {
-      int t_reg = AllocTemp();
-      OpRegReg(kOpNeg, t_reg, rl_result.reg.GetReg());
-      OpRegRegReg(kOpAdc, rl_result.reg.GetReg(), rl_result.reg.GetReg(), t_reg);
+      RegStorage t_reg = AllocTemp();
+      OpRegReg(kOpNeg, t_reg, rl_result.reg);
+      OpRegRegReg(kOpAdc, rl_result.reg, rl_result.reg, t_reg);
     } else {
       DCHECK_EQ(cu_->instruction_set, kX86);
-      OpRegImm(kOpSub, rl_result.reg.GetReg(), 1);
-      OpRegImm(kOpLsr, rl_result.reg.GetReg(), 31);
+      OpRegImm(kOpSub, rl_result.reg, 1);
+      OpRegImm(kOpLsr, rl_result.reg, 31);
     }
   }
   StoreValue(rl_dest, rl_result);
@@ -1118,15 +1143,15 @@
   RegLocation rl_result = EvalLoc(rl_dest, kCoreReg, true);
   if (size == kLong) {
     RegLocation rl_i = LoadValueWide(rl_src_i, kCoreReg);
-    int r_i_low = rl_i.reg.GetReg();
-    if (rl_i.reg.GetReg() == rl_result.reg.GetReg()) {
+    RegStorage r_i_low = rl_i.reg.GetLow();
+    if (rl_i.reg.GetLowReg() == rl_result.reg.GetLowReg()) {
       // First REV shall clobber rl_result.reg.GetReg(), save the value in a temp for the second REV.
       r_i_low = AllocTemp();
-      OpRegCopy(r_i_low, rl_i.reg.GetReg());
+      OpRegCopy(r_i_low, rl_i.reg);
     }
-    OpRegReg(kOpRev, rl_result.reg.GetReg(), rl_i.reg.GetHighReg());
-    OpRegReg(kOpRev, rl_result.reg.GetHighReg(), r_i_low);
-    if (rl_i.reg.GetReg() == rl_result.reg.GetReg()) {
+    OpRegReg(kOpRev, rl_result.reg.GetLow(), rl_i.reg.GetHigh());
+    OpRegReg(kOpRev, rl_result.reg.GetHigh(), r_i_low);
+    if (rl_i.reg.GetLowReg() == rl_result.reg.GetLowReg()) {
       FreeTemp(r_i_low);
     }
     StoreValueWide(rl_dest, rl_result);
@@ -1134,7 +1159,7 @@
     DCHECK(size == kWord || size == kSignedHalf);
     OpKind op = (size == kWord) ? kOpRev : kOpRevsh;
     RegLocation rl_i = LoadValue(rl_src_i, kCoreReg);
-    OpRegReg(op, rl_result.reg.GetReg(), rl_i.reg.GetReg());
+    OpRegReg(op, rl_result.reg, rl_i.reg);
     StoreValue(rl_dest, rl_result);
   }
   return true;
@@ -1149,11 +1174,11 @@
   rl_src = LoadValue(rl_src, kCoreReg);
   RegLocation rl_dest = InlineTarget(info);
   RegLocation rl_result = EvalLoc(rl_dest, kCoreReg, true);
-  int sign_reg = AllocTemp();
+  RegStorage sign_reg = AllocTemp();
   // abs(x) = y<=x>>31, (x+y)^y.
-  OpRegRegImm(kOpAsr, sign_reg, rl_src.reg.GetReg(), 31);
-  OpRegRegReg(kOpAdd, rl_result.reg.GetReg(), rl_src.reg.GetReg(), sign_reg);
-  OpRegReg(kOpXor, rl_result.reg.GetReg(), sign_reg);
+  OpRegRegImm(kOpAsr, sign_reg, rl_src.reg, 31);
+  OpRegRegReg(kOpAdd, rl_result.reg, rl_src.reg, sign_reg);
+  OpRegReg(kOpXor, rl_result.reg, sign_reg);
   StoreValue(rl_dest, rl_result);
   return true;
 }
@@ -1169,27 +1194,25 @@
   RegLocation rl_result = EvalLoc(rl_dest, kCoreReg, true);
 
   // If on x86 or if we would clobber a register needed later, just copy the source first.
-  if (cu_->instruction_set == kX86 || rl_result.reg.GetReg() == rl_src.reg.GetHighReg()) {
-    OpRegCopyWide(rl_result.reg.GetReg(), rl_result.reg.GetHighReg(),
-                  rl_src.reg.GetReg(), rl_src.reg.GetHighReg());
-    if (rl_result.reg.GetReg() != rl_src.reg.GetReg() &&
-        rl_result.reg.GetReg() != rl_src.reg.GetHighReg() &&
-        rl_result.reg.GetHighReg() != rl_src.reg.GetReg() &&
+  if (cu_->instruction_set == kX86 || rl_result.reg.GetLowReg() == rl_src.reg.GetHighReg()) {
+    OpRegCopyWide(rl_result.reg, rl_src.reg);
+    if (rl_result.reg.GetLowReg() != rl_src.reg.GetLowReg() &&
+        rl_result.reg.GetLowReg() != rl_src.reg.GetHighReg() &&
+        rl_result.reg.GetHighReg() != rl_src.reg.GetLowReg() &&
         rl_result.reg.GetHighReg() != rl_src.reg.GetHighReg()) {
       // Reuse source registers to avoid running out of temps.
-      FreeTemp(rl_src.reg.GetReg());
-      FreeTemp(rl_src.reg.GetHighReg());
+      FreeTemp(rl_src.reg);
     }
     rl_src = rl_result;
   }
 
   // abs(x) = y<=x>>31, (x+y)^y.
-  int sign_reg = AllocTemp();
-  OpRegRegImm(kOpAsr, sign_reg, rl_src.reg.GetHighReg(), 31);
-  OpRegRegReg(kOpAdd, rl_result.reg.GetReg(), rl_src.reg.GetReg(), sign_reg);
-  OpRegRegReg(kOpAdc, rl_result.reg.GetHighReg(), rl_src.reg.GetHighReg(), sign_reg);
-  OpRegReg(kOpXor, rl_result.reg.GetReg(), sign_reg);
-  OpRegReg(kOpXor, rl_result.reg.GetHighReg(), sign_reg);
+  RegStorage sign_reg = AllocTemp();
+  OpRegRegImm(kOpAsr, sign_reg, rl_src.reg.GetHigh(), 31);
+  OpRegRegReg(kOpAdd, rl_result.reg.GetLow(), rl_src.reg.GetLow(), sign_reg);
+  OpRegRegReg(kOpAdc, rl_result.reg.GetHigh(), rl_src.reg.GetHigh(), sign_reg);
+  OpRegReg(kOpXor, rl_result.reg.GetLow(), sign_reg);
+  OpRegReg(kOpXor, rl_result.reg.GetHigh(), sign_reg);
   StoreValueWide(rl_dest, rl_result);
   return true;
 }
@@ -1203,7 +1226,7 @@
   rl_src = LoadValue(rl_src, kCoreReg);
   RegLocation rl_dest = InlineTarget(info);
   RegLocation rl_result = EvalLoc(rl_dest, kCoreReg, true);
-  OpRegRegImm(kOpAnd, rl_result.reg.GetReg(), rl_src.reg.GetReg(), 0x7fffffff);
+  OpRegRegImm(kOpAnd, rl_result.reg, rl_src.reg, 0x7fffffff);
   StoreValue(rl_dest, rl_result);
   return true;
 }
@@ -1217,8 +1240,8 @@
   rl_src = LoadValueWide(rl_src, kCoreReg);
   RegLocation rl_dest = InlineTargetWide(info);
   RegLocation rl_result = EvalLoc(rl_dest, kCoreReg, true);
-  OpRegCopyWide(rl_result.reg.GetReg(), rl_result.reg.GetHighReg(), rl_src.reg.GetReg(), rl_src.reg.GetHighReg());
-  OpRegImm(kOpAnd, rl_result.reg.GetHighReg(), 0x7fffffff);
+  OpRegCopyWide(rl_result.reg, rl_src.reg);
+  OpRegImm(kOpAnd, rl_result.reg.GetHigh(), 0x7fffffff);
   StoreValueWide(rl_dest, rl_result);
   return true;
 }
@@ -1263,9 +1286,9 @@
 
   ClobberCallerSave();
   LockCallTemps();  // Using fixed registers
-  int reg_ptr = TargetReg(kArg0);
-  int reg_char = TargetReg(kArg1);
-  int reg_start = TargetReg(kArg2);
+  RegStorage reg_ptr = TargetReg(kArg0);
+  RegStorage reg_char = TargetReg(kArg1);
+  RegStorage reg_start = TargetReg(kArg2);
 
   LoadValueDirectFixed(rl_obj, reg_ptr);
   LoadValueDirectFixed(rl_char, reg_char);
@@ -1275,7 +1298,7 @@
     RegLocation rl_start = info->args[2];     // 3rd arg only present in III flavor of IndexOf.
     LoadValueDirectFixed(rl_start, reg_start);
   }
-  int r_tgt = LoadHelper(QUICK_ENTRYPOINT_OFFSET(pIndexOf));
+  RegStorage r_tgt = LoadHelper(QUICK_ENTRYPOINT_OFFSET(pIndexOf));
   GenNullCheck(reg_ptr, info->opt_flags);
   LIR* high_code_point_branch =
       rl_char.is_const ? nullptr : OpCmpImmBranch(kCondGt, reg_char, 0xFFFF, nullptr);
@@ -1305,15 +1328,15 @@
   }
   ClobberCallerSave();
   LockCallTemps();  // Using fixed registers
-  int reg_this = TargetReg(kArg0);
-  int reg_cmp = TargetReg(kArg1);
+  RegStorage reg_this = TargetReg(kArg0);
+  RegStorage reg_cmp = TargetReg(kArg1);
 
   RegLocation rl_this = info->args[0];
   RegLocation rl_cmp = info->args[1];
   LoadValueDirectFixed(rl_this, reg_this);
   LoadValueDirectFixed(rl_cmp, reg_cmp);
-  int r_tgt = (cu_->instruction_set != kX86) ?
-      LoadHelper(QUICK_ENTRYPOINT_OFFSET(pStringCompareTo)) : 0;
+  RegStorage r_tgt = (cu_->instruction_set != kX86) ?
+      LoadHelper(QUICK_ENTRYPOINT_OFFSET(pStringCompareTo)) : RegStorage::InvalidReg();
   GenNullCheck(reg_this, info->opt_flags);
   info->opt_flags |= MIR_IGNORE_NULL_CHECK;  // Record that we've null checked.
   // TUNING: check if rl_cmp.s_reg_low is already null checked
@@ -1336,7 +1359,7 @@
   RegLocation rl_result = EvalLoc(rl_dest, kCoreReg, true);
   ThreadOffset offset = Thread::PeerOffset();
   if (cu_->instruction_set == kThumb2 || cu_->instruction_set == kMips) {
-    LoadWordDisp(TargetReg(kSelf), offset.Int32Value(), rl_result.reg.GetReg());
+    LoadWordDisp(TargetReg(kSelf), offset.Int32Value(), rl_result.reg);
   } else {
     CHECK(cu_->instruction_set == kX86);
     reinterpret_cast<X86Mir2Lir*>(this)->OpRegThreadMem(kOpMov, rl_result.reg.GetReg(), offset);
@@ -1354,17 +1377,17 @@
   // Unused - RegLocation rl_src_unsafe = info->args[0];
   RegLocation rl_src_obj = info->args[1];  // Object
   RegLocation rl_src_offset = info->args[2];  // long low
-  rl_src_offset.wide = 0;  // ignore high half in info->args[3]
+  rl_src_offset = NarrowRegLoc(rl_src_offset);  // ignore high half in info->args[3]
   RegLocation rl_dest = is_long ? InlineTargetWide(info) : InlineTarget(info);  // result reg
 
   RegLocation rl_object = LoadValue(rl_src_obj, kCoreReg);
   RegLocation rl_offset = LoadValue(rl_src_offset, kCoreReg);
   RegLocation rl_result = EvalLoc(rl_dest, kCoreReg, true);
   if (is_long) {
-    OpRegReg(kOpAdd, rl_object.reg.GetReg(), rl_offset.reg.GetReg());
-    LoadBaseDispWide(rl_object.reg.GetReg(), 0, rl_result.reg.GetReg(), rl_result.reg.GetHighReg(), INVALID_SREG);
+    OpRegReg(kOpAdd, rl_object.reg, rl_offset.reg);
+    LoadBaseDispWide(rl_object.reg, 0, rl_result.reg, INVALID_SREG);
   } else {
-    LoadBaseIndexed(rl_object.reg.GetReg(), rl_offset.reg.GetReg(), rl_result.reg.GetReg(), 0, kWord);
+    LoadBaseIndexed(rl_object.reg, rl_offset.reg, rl_result.reg, 0, kWord);
   }
 
   if (is_volatile) {
@@ -1391,7 +1414,7 @@
   // Unused - RegLocation rl_src_unsafe = info->args[0];
   RegLocation rl_src_obj = info->args[1];  // Object
   RegLocation rl_src_offset = info->args[2];  // long low
-  rl_src_offset.wide = 0;  // ignore high half in info->args[3]
+  rl_src_offset = NarrowRegLoc(rl_src_offset);  // ignore high half in info->args[3]
   RegLocation rl_src_value = info->args[4];  // value to store
   if (is_volatile || is_ordered) {
     // There might have been a store before this volatile one so insert StoreStore barrier.
@@ -1402,11 +1425,11 @@
   RegLocation rl_value;
   if (is_long) {
     rl_value = LoadValueWide(rl_src_value, kCoreReg);
-    OpRegReg(kOpAdd, rl_object.reg.GetReg(), rl_offset.reg.GetReg());
-    StoreBaseDispWide(rl_object.reg.GetReg(), 0, rl_value.reg.GetReg(), rl_value.reg.GetHighReg());
+    OpRegReg(kOpAdd, rl_object.reg, rl_offset.reg);
+    StoreBaseDispWide(rl_object.reg, 0, rl_value.reg);
   } else {
     rl_value = LoadValue(rl_src_value, kCoreReg);
-    StoreBaseIndexed(rl_object.reg.GetReg(), rl_offset.reg.GetReg(), rl_value.reg.GetReg(), 0, kWord);
+    StoreBaseIndexed(rl_object.reg, rl_offset.reg, rl_value.reg, 0, kWord);
   }
 
   // Free up the temp early, to ensure x86 doesn't run out of temporaries in MarkGCCard.
@@ -1417,7 +1440,7 @@
     GenMemBarrier(kStoreLoad);
   }
   if (is_object) {
-    MarkGCCard(rl_value.reg.GetReg(), rl_object.reg.GetReg());
+    MarkGCCard(rl_value.reg, rl_object.reg);
   }
   return true;
 }
@@ -1429,7 +1452,7 @@
         ((cu_->disable_opt & (1 << kNullCheckElimination)) != 0 ||
          (info->opt_flags & MIR_IGNORE_NULL_CHECK) == 0))  {
       RegLocation rl_obj = LoadValue(info->args[0], kCoreReg);
-      GenImmedCheck(kCondEq, rl_obj.reg.GetReg(), 0, kThrowNullPointer);
+      GenImmedCheck(kCondEq, rl_obj.reg, 0, kThrowNullPointer);
     }
     return;
   }
diff --git a/compiler/dex/quick/gen_loadstore.cc b/compiler/dex/quick/gen_loadstore.cc
index 3b79df9..36d6199 100644
--- a/compiler/dex/quick/gen_loadstore.cc
+++ b/compiler/dex/quick/gen_loadstore.cc
@@ -27,7 +27,7 @@
  * Load an immediate value into a fixed or temp register.  Target
  * register is clobbered, and marked in_use.
  */
-LIR* Mir2Lir::LoadConstant(int r_dest, int value) {
+LIR* Mir2Lir::LoadConstant(RegStorage r_dest, int value) {
   if (IsTemp(r_dest)) {
     Clobber(r_dest);
     MarkInUse(r_dest);
@@ -40,7 +40,7 @@
  * promoted floating point register, also copy a zero into the int/ref identity of
  * that sreg.
  */
-void Mir2Lir::Workaround7250540(RegLocation rl_dest, int zero_reg) {
+void Mir2Lir::Workaround7250540(RegLocation rl_dest, RegStorage zero_reg) {
   if (rl_dest.fp) {
     int pmap_index = SRegToPMap(rl_dest.s_reg_low);
     if (promotion_map_[pmap_index].fp_location == kLocPhysReg) {
@@ -55,19 +55,19 @@
       if (!used_as_reference) {
         return;
       }
-      int temp_reg = zero_reg;
-      if (temp_reg == INVALID_REG) {
+      RegStorage temp_reg = zero_reg;
+      if (!temp_reg.Valid()) {
         temp_reg = AllocTemp();
         LoadConstant(temp_reg, 0);
       }
       if (promotion_map_[pmap_index].core_location == kLocPhysReg) {
         // Promoted - just copy in a zero
-        OpRegCopy(promotion_map_[pmap_index].core_reg, temp_reg);
+        OpRegCopy(RegStorage::Solo32(promotion_map_[pmap_index].core_reg), temp_reg);
       } else {
         // Lives in the frame, need to store.
         StoreBaseDisp(TargetReg(kSp), SRegOffset(rl_dest.s_reg_low), temp_reg, kWord);
       }
-      if (zero_reg == INVALID_REG) {
+      if (!zero_reg.Valid()) {
         FreeTemp(temp_reg);
       }
     }
@@ -75,13 +75,12 @@
 }
 
 /* Load a word at base + displacement.  Displacement must be word multiple */
-LIR* Mir2Lir::LoadWordDisp(int rBase, int displacement, int r_dest) {
-  return LoadBaseDisp(rBase, displacement, r_dest, kWord,
-                      INVALID_SREG);
+LIR* Mir2Lir::LoadWordDisp(RegStorage r_base, int displacement, RegStorage r_dest) {
+  return LoadBaseDisp(r_base, displacement, r_dest, kWord, INVALID_SREG);
 }
 
-LIR* Mir2Lir::StoreWordDisp(int rBase, int displacement, int r_src) {
-  return StoreBaseDisp(rBase, displacement, r_src, kWord);
+LIR* Mir2Lir::StoreWordDisp(RegStorage r_base, int displacement, RegStorage r_src) {
+  return StoreBaseDisp(r_base, displacement, r_src, kWord);
 }
 
 /*
@@ -89,10 +88,10 @@
  * using this routine, as it doesn't perform any bookkeeping regarding
  * register liveness.  That is the responsibility of the caller.
  */
-void Mir2Lir::LoadValueDirect(RegLocation rl_src, int r_dest) {
+void Mir2Lir::LoadValueDirect(RegLocation rl_src, RegStorage r_dest) {
   rl_src = UpdateLoc(rl_src);
   if (rl_src.location == kLocPhysReg) {
-    OpRegCopy(r_dest, rl_src.reg.GetReg());
+    OpRegCopy(r_dest, rl_src.reg);
   } else if (IsInexpensiveConstant(rl_src)) {
     LoadConstantNoClobber(r_dest, mir_graph_->ConstantValue(rl_src));
   } else {
@@ -107,7 +106,7 @@
  * register.  Should be used when loading to a fixed register (for example,
  * loading arguments to an out of line call.
  */
-void Mir2Lir::LoadValueDirectFixed(RegLocation rl_src, int r_dest) {
+void Mir2Lir::LoadValueDirectFixed(RegLocation rl_src, RegStorage r_dest) {
   Clobber(r_dest);
   MarkInUse(r_dest);
   LoadValueDirect(rl_src, r_dest);
@@ -118,18 +117,16 @@
  * using this routine, as it doesn't perform any bookkeeping regarding
  * register liveness.  That is the responsibility of the caller.
  */
-void Mir2Lir::LoadValueDirectWide(RegLocation rl_src, int reg_lo,
-             int reg_hi) {
+void Mir2Lir::LoadValueDirectWide(RegLocation rl_src, RegStorage r_dest) {
   rl_src = UpdateLocWide(rl_src);
   if (rl_src.location == kLocPhysReg) {
-    OpRegCopyWide(reg_lo, reg_hi, rl_src.reg.GetReg(), rl_src.reg.GetHighReg());
+    OpRegCopyWide(r_dest, rl_src.reg);
   } else if (IsInexpensiveConstant(rl_src)) {
-    LoadConstantWide(reg_lo, reg_hi, mir_graph_->ConstantValueWide(rl_src));
+    LoadConstantWide(r_dest, mir_graph_->ConstantValueWide(rl_src));
   } else {
     DCHECK((rl_src.location == kLocDalvikFrame) ||
            (rl_src.location == kLocCompilerTemp));
-    LoadBaseDispWide(TargetReg(kSp), SRegOffset(rl_src.s_reg_low),
-                     reg_lo, reg_hi, INVALID_SREG);
+    LoadBaseDispWide(TargetReg(kSp), SRegOffset(rl_src.s_reg_low), r_dest, INVALID_SREG);
   }
 }
 
@@ -138,21 +135,18 @@
  * registers.  Should be used when loading to a fixed registers (for example,
  * loading arguments to an out of line call.
  */
-void Mir2Lir::LoadValueDirectWideFixed(RegLocation rl_src, int reg_lo,
-                                       int reg_hi) {
-  Clobber(reg_lo);
-  Clobber(reg_hi);
-  MarkInUse(reg_lo);
-  MarkInUse(reg_hi);
-  LoadValueDirectWide(rl_src, reg_lo, reg_hi);
+void Mir2Lir::LoadValueDirectWideFixed(RegLocation rl_src, RegStorage r_dest) {
+  Clobber(r_dest);
+  MarkInUse(r_dest);
+  LoadValueDirectWide(rl_src, r_dest);
 }
 
 RegLocation Mir2Lir::LoadValue(RegLocation rl_src, RegisterClass op_kind) {
   rl_src = EvalLoc(rl_src, op_kind, false);
   if (IsInexpensiveConstant(rl_src) || rl_src.location != kLocPhysReg) {
-    LoadValueDirect(rl_src, rl_src.reg.GetReg());
+    LoadValueDirect(rl_src, rl_src.reg);
     rl_src.location = kLocPhysReg;
-    MarkLive(rl_src.reg.GetReg(), rl_src.s_reg_low);
+    MarkLive(rl_src.reg, rl_src.s_reg_low);
   }
   return rl_src;
 }
@@ -175,34 +169,32 @@
   rl_src = UpdateLoc(rl_src);
   rl_dest = UpdateLoc(rl_dest);
   if (rl_src.location == kLocPhysReg) {
-    if (IsLive(rl_src.reg.GetReg()) ||
-      IsPromoted(rl_src.reg.GetReg()) ||
+    if (IsLive(rl_src.reg) ||
+      IsPromoted(rl_src.reg) ||
       (rl_dest.location == kLocPhysReg)) {
       // Src is live/promoted or Dest has assigned reg.
       rl_dest = EvalLoc(rl_dest, kAnyReg, false);
-      OpRegCopy(rl_dest.reg.GetReg(), rl_src.reg.GetReg());
+      OpRegCopy(rl_dest.reg, rl_src.reg);
     } else {
       // Just re-assign the registers.  Dest gets Src's regs
       rl_dest.reg = rl_src.reg;
-      Clobber(rl_src.reg.GetReg());
+      Clobber(rl_src.reg);
     }
   } else {
     // Load Src either into promoted Dest or temps allocated for Dest
     rl_dest = EvalLoc(rl_dest, kAnyReg, false);
-    LoadValueDirect(rl_src, rl_dest.reg.GetReg());
+    LoadValueDirect(rl_src, rl_dest.reg);
   }
 
   // Dest is now live and dirty (until/if we flush it to home location)
-  MarkLive(rl_dest.reg.GetReg(), rl_dest.s_reg_low);
+  MarkLive(rl_dest.reg, rl_dest.s_reg_low);
   MarkDirty(rl_dest);
 
 
   ResetDefLoc(rl_dest);
-  if (IsDirty(rl_dest.reg.GetReg()) &&
-      oat_live_out(rl_dest.s_reg_low)) {
+  if (IsDirty(rl_dest.reg) && oat_live_out(rl_dest.s_reg_low)) {
     def_start = last_lir_insn_;
-    StoreBaseDisp(TargetReg(kSp), SRegOffset(rl_dest.s_reg_low),
-                  rl_dest.reg.GetReg(), kWord);
+    StoreBaseDisp(TargetReg(kSp), SRegOffset(rl_dest.s_reg_low), rl_dest.reg, kWord);
     MarkClean(rl_dest);
     def_end = last_lir_insn_;
     if (!rl_dest.ref) {
@@ -216,10 +208,10 @@
   DCHECK(rl_src.wide);
   rl_src = EvalLoc(rl_src, op_kind, false);
   if (IsInexpensiveConstant(rl_src) || rl_src.location != kLocPhysReg) {
-    LoadValueDirectWide(rl_src, rl_src.reg.GetReg(), rl_src.reg.GetHighReg());
+    LoadValueDirectWide(rl_src, rl_src.reg);
     rl_src.location = kLocPhysReg;
-    MarkLive(rl_src.reg.GetReg(), rl_src.s_reg_low);
-    MarkLive(rl_src.reg.GetHighReg(), GetSRegHi(rl_src.s_reg_low));
+    MarkLive(rl_src.reg.GetLow(), rl_src.s_reg_low);
+    MarkLive(rl_src.reg.GetHigh(), GetSRegHi(rl_src.s_reg_low));
   }
   return rl_src;
 }
@@ -237,59 +229,51 @@
   }
   LIR* def_start;
   LIR* def_end;
-  DCHECK((rl_src.location != kLocPhysReg) ||
-         (IsFpReg(rl_src.reg.GetReg()) == IsFpReg(rl_src.reg.GetHighReg())));
   DCHECK(rl_dest.wide);
   DCHECK(rl_src.wide);
   rl_src = UpdateLocWide(rl_src);
   rl_dest = UpdateLocWide(rl_dest);
   if (rl_src.location == kLocPhysReg) {
-    if (IsLive(rl_src.reg.GetReg()) ||
-        IsLive(rl_src.reg.GetHighReg()) ||
-        IsPromoted(rl_src.reg.GetReg()) ||
-        IsPromoted(rl_src.reg.GetHighReg()) ||
+    if (IsLive(rl_src.reg) ||
+        IsPromoted(rl_src.reg) ||
         (rl_dest.location == kLocPhysReg)) {
       // Src is live or promoted or Dest has assigned reg.
       rl_dest = EvalLoc(rl_dest, kAnyReg, false);
-      OpRegCopyWide(rl_dest.reg.GetReg(), rl_dest.reg.GetHighReg(),
-                    rl_src.reg.GetReg(), rl_src.reg.GetHighReg());
+      OpRegCopyWide(rl_dest.reg, rl_src.reg);
     } else {
       // Just re-assign the registers.  Dest gets Src's regs
       rl_dest.reg = rl_src.reg;
-      Clobber(rl_src.reg.GetReg());
-      Clobber(rl_src.reg.GetHighReg());
+      Clobber(rl_src.reg);
     }
   } else {
     // Load Src either into promoted Dest or temps allocated for Dest
     rl_dest = EvalLoc(rl_dest, kAnyReg, false);
-    LoadValueDirectWide(rl_src, rl_dest.reg.GetReg(), rl_dest.reg.GetHighReg());
+    LoadValueDirectWide(rl_src, rl_dest.reg);
   }
 
   // Dest is now live and dirty (until/if we flush it to home location)
-  MarkLive(rl_dest.reg.GetReg(), rl_dest.s_reg_low);
+  MarkLive(rl_dest.reg.GetLow(), rl_dest.s_reg_low);
 
   // Does this wide value live in two registers (or one vector one)?
-  if (rl_dest.reg.GetReg() != rl_dest.reg.GetHighReg()) {
-    MarkLive(rl_dest.reg.GetHighReg(), GetSRegHi(rl_dest.s_reg_low));
+  // FIXME: wide reg update.
+  if (rl_dest.reg.GetLowReg() != rl_dest.reg.GetHighReg()) {
+    MarkLive(rl_dest.reg.GetHigh(), GetSRegHi(rl_dest.s_reg_low));
     MarkDirty(rl_dest);
-    MarkPair(rl_dest.reg.GetReg(), rl_dest.reg.GetHighReg());
+    MarkPair(rl_dest.reg.GetLowReg(), rl_dest.reg.GetHighReg());
   } else {
     // This must be an x86 vector register value,
-    DCHECK(IsFpReg(rl_dest.reg.GetReg()) && (cu_->instruction_set == kX86));
+    DCHECK(IsFpReg(rl_dest.reg) && (cu_->instruction_set == kX86));
     MarkDirty(rl_dest);
   }
 
 
   ResetDefLocWide(rl_dest);
-  if ((IsDirty(rl_dest.reg.GetReg()) ||
-      IsDirty(rl_dest.reg.GetHighReg())) &&
-      (oat_live_out(rl_dest.s_reg_low) ||
+  if (IsDirty(rl_dest.reg) && (oat_live_out(rl_dest.s_reg_low) ||
       oat_live_out(GetSRegHi(rl_dest.s_reg_low)))) {
     def_start = last_lir_insn_;
     DCHECK_EQ((mir_graph_->SRegToVReg(rl_dest.s_reg_low)+1),
               mir_graph_->SRegToVReg(GetSRegHi(rl_dest.s_reg_low)));
-    StoreBaseDispWide(TargetReg(kSp), SRegOffset(rl_dest.s_reg_low),
-                      rl_dest.reg.GetReg(), rl_dest.reg.GetHighReg());
+    StoreBaseDispWide(TargetReg(kSp), SRegOffset(rl_dest.s_reg_low), rl_dest.reg);
     MarkClean(rl_dest);
     def_end = last_lir_insn_;
     MarkDefWide(rl_dest, def_start, def_end);
@@ -300,25 +284,24 @@
   DCHECK_EQ(rl_src.location, kLocPhysReg);
 
   if (rl_dest.location == kLocPhysReg) {
-    OpRegCopy(rl_dest.reg.GetReg(), rl_src.reg.GetReg());
+    OpRegCopy(rl_dest.reg, rl_src.reg);
   } else {
     // Just re-assign the register.  Dest gets Src's reg.
     rl_dest.location = kLocPhysReg;
     rl_dest.reg = rl_src.reg;
-    Clobber(rl_src.reg.GetReg());
+    Clobber(rl_src.reg);
   }
 
   // Dest is now live and dirty (until/if we flush it to home location)
-  MarkLive(rl_dest.reg.GetReg(), rl_dest.s_reg_low);
+  MarkLive(rl_dest.reg, rl_dest.s_reg_low);
   MarkDirty(rl_dest);
 
 
   ResetDefLoc(rl_dest);
-  if (IsDirty(rl_dest.reg.GetReg()) &&
+  if (IsDirty(rl_dest.reg) &&
       oat_live_out(rl_dest.s_reg_low)) {
     LIR *def_start = last_lir_insn_;
-    StoreBaseDisp(TargetReg(kSp), SRegOffset(rl_dest.s_reg_low),
-                  rl_dest.reg.GetReg(), kWord);
+    StoreBaseDisp(TargetReg(kSp), SRegOffset(rl_dest.s_reg_low), rl_dest.reg, kWord);
     MarkClean(rl_dest);
     LIR *def_end = last_lir_insn_;
     if (!rl_dest.ref) {
@@ -329,45 +312,43 @@
 }
 
 void Mir2Lir::StoreFinalValueWide(RegLocation rl_dest, RegLocation rl_src) {
-  DCHECK_EQ(IsFpReg(rl_src.reg.GetReg()), IsFpReg(rl_src.reg.GetHighReg()));
+  DCHECK_EQ(IsFpReg(rl_src.reg.GetLowReg()), IsFpReg(rl_src.reg.GetHighReg()));
   DCHECK(rl_dest.wide);
   DCHECK(rl_src.wide);
   DCHECK_EQ(rl_src.location, kLocPhysReg);
 
   if (rl_dest.location == kLocPhysReg) {
-    OpRegCopyWide(rl_dest.reg.GetReg(), rl_dest.reg.GetHighReg(), rl_src.reg.GetReg(), rl_src.reg.GetHighReg());
+    OpRegCopyWide(rl_dest.reg, rl_src.reg);
   } else {
     // Just re-assign the registers.  Dest gets Src's regs.
     rl_dest.location = kLocPhysReg;
     rl_dest.reg = rl_src.reg;
-    Clobber(rl_src.reg.GetReg());
+    Clobber(rl_src.reg.GetLowReg());
     Clobber(rl_src.reg.GetHighReg());
   }
 
   // Dest is now live and dirty (until/if we flush it to home location).
-  MarkLive(rl_dest.reg.GetReg(), rl_dest.s_reg_low);
+  MarkLive(rl_dest.reg.GetLow(), rl_dest.s_reg_low);
 
   // Does this wide value live in two registers (or one vector one)?
-  if (rl_dest.reg.GetReg() != rl_dest.reg.GetHighReg()) {
-    MarkLive(rl_dest.reg.GetHighReg(), GetSRegHi(rl_dest.s_reg_low));
+  // FIXME: wide reg.
+  if (rl_dest.reg.GetLowReg() != rl_dest.reg.GetHighReg()) {
+    MarkLive(rl_dest.reg.GetHigh(), GetSRegHi(rl_dest.s_reg_low));
     MarkDirty(rl_dest);
-    MarkPair(rl_dest.reg.GetReg(), rl_dest.reg.GetHighReg());
+    MarkPair(rl_dest.reg.GetLowReg(), rl_dest.reg.GetHighReg());
   } else {
     // This must be an x86 vector register value,
-    DCHECK(IsFpReg(rl_dest.reg.GetReg()) && (cu_->instruction_set == kX86));
+    DCHECK(IsFpReg(rl_dest.reg) && (cu_->instruction_set == kX86));
     MarkDirty(rl_dest);
   }
 
   ResetDefLocWide(rl_dest);
-  if ((IsDirty(rl_dest.reg.GetReg()) ||
-      IsDirty(rl_dest.reg.GetHighReg())) &&
-      (oat_live_out(rl_dest.s_reg_low) ||
+  if (IsDirty(rl_dest.reg) && (oat_live_out(rl_dest.s_reg_low) ||
       oat_live_out(GetSRegHi(rl_dest.s_reg_low)))) {
     LIR *def_start = last_lir_insn_;
     DCHECK_EQ((mir_graph_->SRegToVReg(rl_dest.s_reg_low)+1),
               mir_graph_->SRegToVReg(GetSRegHi(rl_dest.s_reg_low)));
-    StoreBaseDispWide(TargetReg(kSp), SRegOffset(rl_dest.s_reg_low),
-                      rl_dest.reg.GetReg(), rl_dest.reg.GetHighReg());
+    StoreBaseDispWide(TargetReg(kSp), SRegOffset(rl_dest.s_reg_low), rl_dest.reg);
     MarkClean(rl_dest);
     LIR *def_end = last_lir_insn_;
     MarkDefWide(rl_dest, def_start, def_end);
@@ -375,7 +356,7 @@
 }
 
 /* Utilities to load the current Method* */
-void Mir2Lir::LoadCurrMethodDirect(int r_tgt) {
+void Mir2Lir::LoadCurrMethodDirect(RegStorage r_tgt) {
   LoadValueDirectFixed(mir_graph_->GetMethodLoc(), r_tgt);
 }
 
@@ -386,13 +367,13 @@
 RegLocation Mir2Lir::ForceTemp(RegLocation loc) {
   DCHECK(!loc.wide);
   DCHECK(loc.location == kLocPhysReg);
-  DCHECK(!IsFpReg(loc.reg.GetReg()));
-  if (IsTemp(loc.reg.GetReg())) {
-    Clobber(loc.reg.GetReg());
+  DCHECK(!IsFpReg(loc.reg));
+  if (IsTemp(loc.reg)) {
+    Clobber(loc.reg);
   } else {
-    int temp_low = AllocTemp();
-    OpRegCopy(temp_low, loc.reg.GetReg());
-    loc.reg.SetReg(temp_low);
+    RegStorage temp_low = AllocTemp();
+    OpRegCopy(temp_low, loc.reg);
+    loc.reg = temp_low;
   }
 
   // Ensure that this doesn't represent the original SR any more.
@@ -400,24 +381,25 @@
   return loc;
 }
 
+// FIXME: wide regs.
 RegLocation Mir2Lir::ForceTempWide(RegLocation loc) {
   DCHECK(loc.wide);
   DCHECK(loc.location == kLocPhysReg);
-  DCHECK(!IsFpReg(loc.reg.GetReg()));
+  DCHECK(!IsFpReg(loc.reg.GetLowReg()));
   DCHECK(!IsFpReg(loc.reg.GetHighReg()));
-  if (IsTemp(loc.reg.GetReg())) {
-    Clobber(loc.reg.GetReg());
+  if (IsTemp(loc.reg.GetLowReg())) {
+    Clobber(loc.reg.GetLowReg());
   } else {
-    int temp_low = AllocTemp();
-    OpRegCopy(temp_low, loc.reg.GetReg());
-    loc.reg.SetReg(temp_low);
+    RegStorage temp_low = AllocTemp();
+    OpRegCopy(temp_low, loc.reg.GetLow());
+    loc.reg.SetLowReg(temp_low.GetReg());
   }
   if (IsTemp(loc.reg.GetHighReg())) {
     Clobber(loc.reg.GetHighReg());
   } else {
-    int temp_high = AllocTemp();
-    OpRegCopy(temp_high, loc.reg.GetHighReg());
-    loc.reg.SetHighReg(temp_high);
+    RegStorage temp_high = AllocTemp();
+    OpRegCopy(temp_high, loc.reg.GetHigh());
+    loc.reg.SetHighReg(temp_high.GetReg());
   }
 
   // Ensure that this doesn't represent the original SR any more.
diff --git a/compiler/dex/quick/local_optimizations.cc b/compiler/dex/quick/local_optimizations.cc
index dd4af9c..8f64408 100644
--- a/compiler/dex/quick/local_optimizations.cc
+++ b/compiler/dex/quick/local_optimizations.cc
@@ -39,7 +39,7 @@
 }
 
 /* Convert a more expensive instruction (ie load) into a move */
-void Mir2Lir::ConvertMemOpIntoMove(LIR* orig_lir, int dest, int src) {
+void Mir2Lir::ConvertMemOpIntoMove(LIR* orig_lir, RegStorage dest, RegStorage src) {
   /* Insert a move to replace the load */
   LIR* move_lir;
   move_lir = OpRegCopyNoInsert(dest, src);
@@ -169,7 +169,9 @@
              * a move
              */
             if (check_lir->operands[0] != native_reg_id) {
-              ConvertMemOpIntoMove(check_lir, check_lir->operands[0], native_reg_id);
+              // TODO: update for 64-bit regs.
+              ConvertMemOpIntoMove(check_lir, RegStorage::Solo32(check_lir->operands[0]),
+                                   RegStorage::Solo32(native_reg_id));
             }
             NopLIR(check_lir);
           }
@@ -186,9 +188,10 @@
                  * Different destination register -
                  * insert a move
                  */
-                if (check_lir->operands[0] !=
-                  native_reg_id) {
-                  ConvertMemOpIntoMove(check_lir, check_lir->operands[0], native_reg_id);
+                if (check_lir->operands[0] != native_reg_id) {
+                  // TODO: update for 64-bit regs.
+                  ConvertMemOpIntoMove(check_lir, RegStorage::Solo32(check_lir->operands[0]),
+                                       RegStorage::Solo32(native_reg_id));
                 }
                 NopLIR(check_lir);
               } else {
diff --git a/compiler/dex/quick/mips/assemble_mips.cc b/compiler/dex/quick/mips/assemble_mips.cc
index bd3355f..ee142e5 100644
--- a/compiler/dex/quick/mips/assemble_mips.cc
+++ b/compiler/dex/quick/mips/assemble_mips.cc
@@ -432,12 +432,12 @@
  * Long conditional branch
  * -----------------------
  *      bne  rs,rt,hop
- *      bal  .+8   ; r_RA <- anchor
- *      lui  r_AT, ((target-anchor) >> 16)
+ *      bal  .+8   ; rRA <- anchor
+ *      lui  rAT, ((target-anchor) >> 16)
  * anchor:
- *      ori  r_AT, r_AT, ((target-anchor) & 0xffff)
- *      addu r_AT, r_AT, r_RA
- *      jr   r_AT
+ *      ori  rAT, rAT, ((target-anchor) & 0xffff)
+ *      addu rAT, rAT, rRA
+ *      jr   rAT
  * hop:
  *
  * Orig unconditional branch
@@ -446,12 +446,12 @@
  *
  * Long unconditional branch
  * -----------------------
- *      bal  .+8   ; r_RA <- anchor
- *      lui  r_AT, ((target-anchor) >> 16)
+ *      bal  .+8   ; rRA <- anchor
+ *      lui  rAT, ((target-anchor) >> 16)
  * anchor:
- *      ori  r_AT, r_AT, ((target-anchor) & 0xffff)
- *      addu r_AT, r_AT, r_RA
- *      jr   r_AT
+ *      ori  rAT, rAT, ((target-anchor) & 0xffff)
+ *      addu rAT, rAT, rRA
+ *      jr   rAT
  *
  *
  * NOTE: An out-of-range bal isn't supported because it should
@@ -489,16 +489,16 @@
   LIR* curr_pc = RawLIR(dalvik_offset, kMipsCurrPC);
   InsertLIRBefore(lir, curr_pc);
   LIR* anchor = RawLIR(dalvik_offset, kPseudoTargetLabel);
-  LIR* delta_hi = RawLIR(dalvik_offset, kMipsDeltaHi, r_AT, 0, WrapPointer(anchor), 0, 0,
+  LIR* delta_hi = RawLIR(dalvik_offset, kMipsDeltaHi, rAT, 0, WrapPointer(anchor), 0, 0,
                          lir->target);
   InsertLIRBefore(lir, delta_hi);
   InsertLIRBefore(lir, anchor);
-  LIR* delta_lo = RawLIR(dalvik_offset, kMipsDeltaLo, r_AT, 0, WrapPointer(anchor), 0, 0,
+  LIR* delta_lo = RawLIR(dalvik_offset, kMipsDeltaLo, rAT, 0, WrapPointer(anchor), 0, 0,
                          lir->target);
   InsertLIRBefore(lir, delta_lo);
-  LIR* addu = RawLIR(dalvik_offset, kMipsAddu, r_AT, r_AT, r_RA);
+  LIR* addu = RawLIR(dalvik_offset, kMipsAddu, rAT, rAT, rRA);
   InsertLIRBefore(lir, addu);
-  LIR* jr = RawLIR(dalvik_offset, kMipsJr, r_AT);
+  LIR* jr = RawLIR(dalvik_offset, kMipsJr, rAT);
   InsertLIRBefore(lir, jr);
   if (!unconditional) {
     InsertLIRBefore(lir, hop_target);
@@ -559,7 +559,7 @@
           InsertLIRBefore(lir, new_delta_lo);
           LIR *new_addu =
               RawLIR(lir->dalvik_offset, kMipsAddu,
-                     lir->operands[0], lir->operands[0], r_RA);
+                     lir->operands[0], lir->operands[0], rRA);
           InsertLIRBefore(lir, new_addu);
           NopLIR(lir);
           res = kRetryAll;
diff --git a/compiler/dex/quick/mips/call_mips.cc b/compiler/dex/quick/mips/call_mips.cc
index 95fd6e7..972457a 100644
--- a/compiler/dex/quick/mips/call_mips.cc
+++ b/compiler/dex/quick/mips/call_mips.cc
@@ -32,8 +32,8 @@
 /*
  * The lack of pc-relative loads on Mips presents somewhat of a challenge
  * for our PIC switch table strategy.  To materialize the current location
- * we'll do a dummy JAL and reference our tables using r_RA as the
- * base register.  Note that r_RA will be used both as the base to
+ * we'll do a dummy JAL and reference our tables using rRA as the
+ * base register.  Note that rRA will be used both as the base to
  * locate the switch table data and as the reference base for the switch
  * target offsets stored in the table.  We'll use a special pseudo-instruction
  * to represent the jal and trigger the construction of the
@@ -42,21 +42,21 @@
  *
  * The test loop will look something like:
  *
- *   ori   rEnd, r_ZERO, #table_size  ; size in bytes
- *   jal   BaseLabel         ; stores "return address" (BaseLabel) in r_RA
+ *   ori   r_end, rZERO, #table_size  ; size in bytes
+ *   jal   BaseLabel         ; stores "return address" (BaseLabel) in rRA
  *   nop                     ; opportunistically fill
  * BaseLabel:
- *   addiu rBase, r_RA, <table> - <BaseLabel>  ; table relative to BaseLabel
-     addu  rEnd, rEnd, rBase                   ; end of table
+ *   addiu r_base, rRA, <table> - <BaseLabel>    ; table relative to BaseLabel
+     addu  r_end, r_end, r_base                   ; end of table
  *   lw    r_val, [rSP, v_reg_off]                ; Test Value
  * loop:
- *   beq   rBase, rEnd, done
- *   lw    r_key, 0(rBase)
- *   addu  rBase, 8
+ *   beq   r_base, r_end, done
+ *   lw    r_key, 0(r_base)
+ *   addu  r_base, 8
  *   bne   r_val, r_key, loop
- *   lw    r_disp, -4(rBase)
- *   addu  r_RA, r_disp
- *   jr    r_RA
+ *   lw    r_disp, -4(r_base)
+ *   addu  rRA, r_disp
+ *   jr    rRA
  * done:
  *
  */
@@ -82,18 +82,18 @@
   int size_hi = byte_size >> 16;
   int size_lo = byte_size & 0xffff;
 
-  int rEnd = AllocTemp();
+  RegStorage r_end = AllocTemp();
   if (size_hi) {
-    NewLIR2(kMipsLui, rEnd, size_hi);
+    NewLIR2(kMipsLui, r_end.GetReg(), size_hi);
   }
   // Must prevent code motion for the curr pc pair
   GenBarrier();  // Scheduling barrier
   NewLIR0(kMipsCurrPC);  // Really a jal to .+8
   // Now, fill the branch delay slot
   if (size_hi) {
-    NewLIR3(kMipsOri, rEnd, rEnd, size_lo);
+    NewLIR3(kMipsOri, r_end.GetReg(), r_end.GetReg(), size_lo);
   } else {
-    NewLIR3(kMipsOri, rEnd, r_ZERO, size_lo);
+    NewLIR3(kMipsOri, r_end.GetReg(), rZERO, size_lo);
   }
   GenBarrier();  // Scheduling barrier
 
@@ -101,24 +101,24 @@
   LIR* base_label = NewLIR0(kPseudoTargetLabel);
   // Remember base label so offsets can be computed later
   tab_rec->anchor = base_label;
-  int rBase = AllocTemp();
-  NewLIR4(kMipsDelta, rBase, 0, WrapPointer(base_label), WrapPointer(tab_rec));
-  OpRegRegReg(kOpAdd, rEnd, rEnd, rBase);
+  RegStorage r_base = AllocTemp();
+  NewLIR4(kMipsDelta, r_base.GetReg(), 0, WrapPointer(base_label), WrapPointer(tab_rec));
+  OpRegRegReg(kOpAdd, r_end, r_end, r_base);
 
   // Grab switch test value
   rl_src = LoadValue(rl_src, kCoreReg);
 
   // Test loop
-  int r_key = AllocTemp();
+  RegStorage r_key = AllocTemp();
   LIR* loop_label = NewLIR0(kPseudoTargetLabel);
-  LIR* exit_branch = OpCmpBranch(kCondEq, rBase, rEnd, NULL);
-  LoadWordDisp(rBase, 0, r_key);
-  OpRegImm(kOpAdd, rBase, 8);
-  OpCmpBranch(kCondNe, rl_src.reg.GetReg(), r_key, loop_label);
-  int r_disp = AllocTemp();
-  LoadWordDisp(rBase, -4, r_disp);
-  OpRegRegReg(kOpAdd, r_RA, r_RA, r_disp);
-  OpReg(kOpBx, r_RA);
+  LIR* exit_branch = OpCmpBranch(kCondEq, r_base, r_end, NULL);
+  LoadWordDisp(r_base, 0, r_key);
+  OpRegImm(kOpAdd, r_base, 8);
+  OpCmpBranch(kCondNe, rl_src.reg, r_key, loop_label);
+  RegStorage r_disp = AllocTemp();
+  LoadWordDisp(r_base, -4, r_disp);
+  OpRegRegReg(kOpAdd, rs_rRA, rs_rRA, r_disp);
+  OpReg(kOpBx, rs_rRA);
 
   // Loop exit
   LIR* exit_label = NewLIR0(kPseudoTargetLabel);
@@ -129,13 +129,13 @@
  * Code pattern will look something like:
  *
  *   lw    r_val
- *   jal   BaseLabel         ; stores "return address" (BaseLabel) in r_RA
+ *   jal   BaseLabel         ; stores "return address" (BaseLabel) in rRA
  *   nop                     ; opportunistically fill
  *   [subiu r_val, bias]      ; Remove bias if low_val != 0
  *   bound check -> done
- *   lw    r_disp, [r_RA, r_val]
- *   addu  r_RA, r_disp
- *   jr    r_RA
+ *   lw    r_disp, [rRA, r_val]
+ *   addu  rRA, r_disp
+ *   jr    rRA
  * done:
  */
 void MipsMir2Lir::GenPackedSwitch(MIR* mir, DexOffset table_offset,
@@ -160,9 +160,9 @@
   // Prepare the bias.  If too big, handle 1st stage here
   int low_key = s4FromSwitchData(&table[2]);
   bool large_bias = false;
-  int r_key;
+  RegStorage r_key;
   if (low_key == 0) {
-    r_key = rl_src.reg.GetReg();
+    r_key = rl_src.reg;
   } else if ((low_key & 0xffff) != low_key) {
     r_key = AllocTemp();
     LoadConstant(r_key, low_key);
@@ -179,9 +179,9 @@
     NewLIR0(kMipsNop);
   } else {
     if (large_bias) {
-      OpRegRegReg(kOpSub, r_key, rl_src.reg.GetReg(), r_key);
+      OpRegRegReg(kOpSub, r_key, rl_src.reg, r_key);
     } else {
-      OpRegRegImm(kOpSub, r_key, rl_src.reg.GetReg(), low_key);
+      OpRegRegImm(kOpSub, r_key, rl_src.reg, low_key);
     }
   }
   GenBarrier();  // Scheduling barrier
@@ -195,16 +195,16 @@
   LIR* branch_over = OpCmpImmBranch(kCondHi, r_key, size-1, NULL);
 
   // Materialize the table base pointer
-  int rBase = AllocTemp();
-  NewLIR4(kMipsDelta, rBase, 0, WrapPointer(base_label), WrapPointer(tab_rec));
+  RegStorage r_base = AllocTemp();
+  NewLIR4(kMipsDelta, r_base.GetReg(), 0, WrapPointer(base_label), WrapPointer(tab_rec));
 
   // Load the displacement from the switch table
-  int r_disp = AllocTemp();
-  LoadBaseIndexed(rBase, r_key, r_disp, 2, kWord);
+  RegStorage r_disp = AllocTemp();
+  LoadBaseIndexed(r_base, r_key, r_disp, 2, kWord);
 
-  // Add to r_AP and go
-  OpRegRegReg(kOpAdd, r_RA, r_RA, r_disp);
-  OpReg(kOpBx, r_RA);
+  // Add to rAP and go
+  OpRegRegReg(kOpAdd, rs_rRA, rs_rRA, r_disp);
+  OpReg(kOpBx, rs_rRA);
 
   /* branch_over target here */
   LIR* target = NewLIR0(kPseudoTargetLabel);
@@ -238,13 +238,13 @@
   // Making a call - use explicit registers
   FlushAllRegs();   /* Everything to home location */
   LockCallTemps();
-  LoadValueDirectFixed(rl_src, rMIPS_ARG0);
+  LoadValueDirectFixed(rl_src, rs_rMIPS_ARG0);
 
   // Must prevent code motion for the curr pc pair
   GenBarrier();
   NewLIR0(kMipsCurrPC);  // Really a jal to .+8
   // Now, fill the branch delay slot with the helper load
-  int r_tgt = LoadHelper(QUICK_ENTRYPOINT_OFFSET(pHandleFillArrayData));
+  RegStorage r_tgt = LoadHelper(QUICK_ENTRYPOINT_OFFSET(pHandleFillArrayData));
   GenBarrier();  // Scheduling barrier
 
   // Construct BaseLabel and set up table base register
@@ -262,10 +262,10 @@
 void MipsMir2Lir::GenMoveException(RegLocation rl_dest) {
   int ex_offset = Thread::ExceptionOffset().Int32Value();
   RegLocation rl_result = EvalLoc(rl_dest, kCoreReg, true);
-  int reset_reg = AllocTemp();
-  LoadWordDisp(rMIPS_SELF, ex_offset, rl_result.reg.GetReg());
+  RegStorage reset_reg = AllocTemp();
+  LoadWordDisp(rs_rMIPS_SELF, ex_offset, rl_result.reg);
   LoadConstant(reset_reg, 0);
-  StoreWordDisp(rMIPS_SELF, ex_offset, reset_reg);
+  StoreWordDisp(rs_rMIPS_SELF, ex_offset, reset_reg);
   FreeTemp(reset_reg);
   StoreValue(rl_dest, rl_result);
 }
@@ -273,14 +273,13 @@
 /*
  * Mark garbage collection card. Skip if the value we're storing is null.
  */
-void MipsMir2Lir::MarkGCCard(int val_reg, int tgt_addr_reg) {
-  int reg_card_base = AllocTemp();
-  int reg_card_no = AllocTemp();
+void MipsMir2Lir::MarkGCCard(RegStorage val_reg, RegStorage tgt_addr_reg) {
+  RegStorage reg_card_base = AllocTemp();
+  RegStorage reg_card_no = AllocTemp();
   LIR* branch_over = OpCmpImmBranch(kCondEq, val_reg, 0, NULL);
-  LoadWordDisp(rMIPS_SELF, Thread::CardTableOffset().Int32Value(), reg_card_base);
+  LoadWordDisp(rs_rMIPS_SELF, Thread::CardTableOffset().Int32Value(), reg_card_base);
   OpRegRegImm(kOpLsr, reg_card_no, tgt_addr_reg, gc::accounting::CardTable::kCardShift);
-  StoreBaseIndexed(reg_card_base, reg_card_no, reg_card_base, 0,
-                   kUnsignedByte);
+  StoreBaseIndexed(reg_card_base, reg_card_no, reg_card_base, 0, kUnsignedByte);
   LIR* target = NewLIR0(kPseudoTargetLabel);
   branch_over->target = target;
   FreeTemp(reg_card_base);
@@ -307,11 +306,11 @@
   bool skip_overflow_check = (mir_graph_->MethodIsLeaf() &&
       (static_cast<size_t>(frame_size_) < Thread::kStackOverflowReservedBytes));
   NewLIR0(kPseudoMethodEntry);
-  int check_reg = AllocTemp();
-  int new_sp = AllocTemp();
+  RegStorage check_reg = AllocTemp();
+  RegStorage new_sp = AllocTemp();
   if (!skip_overflow_check) {
     /* Load stack limit */
-    LoadWordDisp(rMIPS_SELF, Thread::StackEndOffset().Int32Value(), check_reg);
+    LoadWordDisp(rs_rMIPS_SELF, Thread::StackEndOffset().Int32Value(), check_reg);
   }
   /* Spill core callee saves */
   SpillCoreRegs();
@@ -329,24 +328,24 @@
         m2l_->ResetDefTracking();
         GenerateTargetLabel();
         // LR is offset 0 since we push in reverse order.
-        m2l_->LoadWordDisp(kMipsRegSP, 0, kMipsRegLR);
-        m2l_->OpRegImm(kOpAdd, kMipsRegSP, sp_displace_);
+        m2l_->LoadWordDisp(rs_rMIPS_SP, 0, rs_rRA);
+        m2l_->OpRegImm(kOpAdd, rs_rMIPS_SP, sp_displace_);
         m2l_->ClobberCallerSave();
         ThreadOffset func_offset = QUICK_ENTRYPOINT_OFFSET(pThrowStackOverflow);
-        int r_tgt = m2l_->CallHelperSetup(func_offset);  // Doesn't clobber LR.
+        RegStorage r_tgt = m2l_->CallHelperSetup(func_offset);  // Doesn't clobber LR.
         m2l_->CallHelper(r_tgt, func_offset, false /* MarkSafepointPC */, false /* UseLink */);
       }
 
      private:
       const size_t sp_displace_;
     };
-    OpRegRegImm(kOpSub, new_sp, rMIPS_SP, frame_sub);
+    OpRegRegImm(kOpSub, new_sp, rs_rMIPS_SP, frame_sub);
     LIR* branch = OpCmpBranch(kCondUlt, new_sp, check_reg, nullptr);
     AddSlowPath(new(arena_)StackOverflowSlowPath(this, branch, spill_count * 4));
     // TODO: avoid copy for small frame sizes.
-    OpRegCopy(rMIPS_SP, new_sp);     // Establish stack
+    OpRegCopy(rs_rMIPS_SP, new_sp);     // Establish stack
   } else {
-    OpRegImm(kOpSub, rMIPS_SP, frame_sub);
+    OpRegImm(kOpSub, rs_rMIPS_SP, frame_sub);
   }
 
   FlushIns(ArgLocs, rl_method);
@@ -367,11 +366,11 @@
 
   NewLIR0(kPseudoMethodExit);
   UnSpillCoreRegs();
-  OpReg(kOpBx, r_RA);
+  OpReg(kOpBx, rs_rRA);
 }
 
 void MipsMir2Lir::GenSpecialExitSequence() {
-  OpReg(kOpBx, r_RA);
+  OpReg(kOpBx, rs_rRA);
 }
 
 }  // namespace art
diff --git a/compiler/dex/quick/mips/codegen_mips.h b/compiler/dex/quick/mips/codegen_mips.h
index 28ebe0e..bc1ad02 100644
--- a/compiler/dex/quick/mips/codegen_mips.h
+++ b/compiler/dex/quick/mips/codegen_mips.h
@@ -28,32 +28,36 @@
 
     // Required for target - codegen utilities.
     bool SmallLiteralDivRem(Instruction::Code dalvik_opcode, bool is_div, RegLocation rl_src,
-                                    RegLocation rl_dest, int lit);
-    int LoadHelper(ThreadOffset offset);
+                            RegLocation rl_dest, int lit);
     LIR* CheckSuspendUsingLoad() OVERRIDE;
-    LIR* LoadBaseDisp(int rBase, int displacement, int r_dest, OpSize size, int s_reg);
-    LIR* LoadBaseDispWide(int rBase, int displacement, int r_dest_lo, int r_dest_hi,
-                                  int s_reg);
-    LIR* LoadBaseIndexed(int rBase, int r_index, int r_dest, int scale, OpSize size);
-    LIR* LoadBaseIndexedDisp(int rBase, int r_index, int scale, int displacement,
-                                     int r_dest, int r_dest_hi, OpSize size, int s_reg);
-    LIR* LoadConstantNoClobber(int r_dest, int value);
-    LIR* LoadConstantWide(int r_dest_lo, int r_dest_hi, int64_t value);
-    LIR* StoreBaseDisp(int rBase, int displacement, int r_src, OpSize size);
-    LIR* StoreBaseDispWide(int rBase, int displacement, int r_src_lo, int r_src_hi);
-    LIR* StoreBaseIndexed(int rBase, int r_index, int r_src, int scale, OpSize size);
-    LIR* StoreBaseIndexedDisp(int rBase, int r_index, int scale, int displacement,
-                                      int r_src, int r_src_hi, OpSize size, int s_reg);
-    void MarkGCCard(int val_reg, int tgt_addr_reg);
+    RegStorage LoadHelper(ThreadOffset offset);
+    LIR* LoadBaseDisp(int r_base, int displacement, int r_dest, OpSize size, int s_reg);
+    LIR* LoadBaseDisp(RegStorage r_base, int displacement, RegStorage r_dest, OpSize size,
+                      int s_reg);
+    LIR* LoadBaseDispWide(RegStorage r_base, int displacement, RegStorage r_dest, int s_reg);
+    LIR* LoadBaseIndexed(RegStorage r_base, RegStorage r_index, RegStorage r_dest, int scale,
+                         OpSize size);
+    LIR* LoadBaseIndexedDisp(RegStorage r_base, RegStorage r_index, int scale, int displacement,
+                             RegStorage r_dest, RegStorage r_dest_hi, OpSize size, int s_reg);
+    LIR* LoadConstantNoClobber(RegStorage r_dest, int value);
+    LIR* LoadConstantWide(RegStorage r_dest, int64_t value);
+    LIR* StoreBaseDisp(RegStorage r_base, int displacement, RegStorage r_src, OpSize size);
+    LIR* StoreBaseDispWide(RegStorage r_base, int displacement, RegStorage r_src);
+    LIR* StoreBaseIndexed(RegStorage r_base, RegStorage r_index, RegStorage r_src, int scale,
+                          OpSize size);
+    LIR* StoreBaseIndexedDisp(RegStorage r_base, RegStorage r_index, int scale, int displacement,
+                              RegStorage r_src, RegStorage r_src_hi, OpSize size, int s_reg);
+    void MarkGCCard(RegStorage val_reg, RegStorage tgt_addr_reg);
 
     // Required for target - register utilities.
     bool IsFpReg(int reg);
+    bool IsFpReg(RegStorage reg);
     bool SameRegType(int reg1, int reg2);
-    int AllocTypedTemp(bool fp_hint, int reg_class);
+    RegStorage AllocTypedTemp(bool fp_hint, int reg_class);
     RegStorage AllocTypedTempWide(bool fp_hint, int reg_class);
     int S2d(int low_reg, int high_reg);
-    int TargetReg(SpecialTargetRegister reg);
-    int GetArgMappingToPhysicalReg(int arg_num);
+    RegStorage TargetReg(SpecialTargetRegister reg);
+    RegStorage GetArgMappingToPhysicalReg(int arg_num);
     RegLocation GetReturnAlt();
     RegLocation GetReturnWideAlt();
     RegLocation LocCReturn();
@@ -64,8 +68,8 @@
     uint64_t GetRegMaskCommon(int reg);
     void AdjustSpillMask();
     void ClobberCallerSave();
-    void FlushReg(int reg);
-    void FlushRegWide(int reg1, int reg2);
+    void FlushReg(RegStorage reg);
+    void FlushRegWide(RegStorage reg);
     void FreeCallTemps();
     void FreeRegLocTemps(RegLocation rl_keep, RegLocation rl_free);
     void LockCallTemps();
@@ -89,22 +93,25 @@
 
     // Required for target - Dalvik-level generators.
     void GenArithImmOpLong(Instruction::Code opcode, RegLocation rl_dest,
-                                   RegLocation rl_src1, RegLocation rl_src2);
+                           RegLocation rl_src1, RegLocation rl_src2);
     void GenArrayGet(int opt_flags, OpSize size, RegLocation rl_array,
                      RegLocation rl_index, RegLocation rl_dest, int scale);
     void GenArrayPut(int opt_flags, OpSize size, RegLocation rl_array,
                      RegLocation rl_index, RegLocation rl_src, int scale, bool card_mark);
-    void GenShiftImmOpLong(Instruction::Code opcode, RegLocation rl_dest,
-                                   RegLocation rl_src1, RegLocation rl_shift);
-    void GenMulLong(Instruction::Code opcode, RegLocation rl_dest, RegLocation rl_src1, RegLocation rl_src2);
-    void GenAddLong(Instruction::Code opcode, RegLocation rl_dest, RegLocation rl_src1, RegLocation rl_src2);
-    void GenAndLong(Instruction::Code opcode, RegLocation rl_dest, RegLocation rl_src1, RegLocation rl_src2);
-    void GenArithOpDouble(Instruction::Code opcode, RegLocation rl_dest,
-                                  RegLocation rl_src1, RegLocation rl_src2);
-    void GenArithOpFloat(Instruction::Code opcode, RegLocation rl_dest,
-                                 RegLocation rl_src1, RegLocation rl_src2);
-    void GenCmpFP(Instruction::Code opcode, RegLocation rl_dest, RegLocation rl_src1,
+    void GenShiftImmOpLong(Instruction::Code opcode, RegLocation rl_dest, RegLocation rl_src1,
+                           RegLocation rl_shift);
+    void GenMulLong(Instruction::Code opcode, RegLocation rl_dest, RegLocation rl_src1,
+                    RegLocation rl_src2);
+    void GenAddLong(Instruction::Code opcode, RegLocation rl_dest, RegLocation rl_src1,
+                    RegLocation rl_src2);
+    void GenAndLong(Instruction::Code opcode, RegLocation rl_dest, RegLocation rl_src1,
+                    RegLocation rl_src2);
+    void GenArithOpDouble(Instruction::Code opcode, RegLocation rl_dest, RegLocation rl_src1,
                           RegLocation rl_src2);
+    void GenArithOpFloat(Instruction::Code opcode, RegLocation rl_dest, RegLocation rl_src1,
+                         RegLocation rl_src2);
+    void GenCmpFP(Instruction::Code opcode, RegLocation rl_dest, RegLocation rl_src1,
+                  RegLocation rl_src2);
     void GenConversion(Instruction::Code opcode, RegLocation rl_dest, RegLocation rl_src);
     bool GenInlinedCas(CallInfo* info, bool is_long, bool is_object);
     bool GenInlinedMinMaxInt(CallInfo* info, bool is_min);
@@ -112,15 +119,18 @@
     bool GenInlinedPeek(CallInfo* info, OpSize size);
     bool GenInlinedPoke(CallInfo* info, OpSize size);
     void GenNegLong(RegLocation rl_dest, RegLocation rl_src);
-    void GenOrLong(Instruction::Code opcode, RegLocation rl_dest, RegLocation rl_src1, RegLocation rl_src2);
-    void GenSubLong(Instruction::Code opcode, RegLocation rl_dest, RegLocation rl_src1, RegLocation rl_src2);
-    void GenXorLong(Instruction::Code opcode, RegLocation rl_dest, RegLocation rl_src1, RegLocation rl_src2);
-    LIR* GenRegMemCheck(ConditionCode c_code, int reg1, int base, int offset,
-                                ThrowKind kind);
-    RegLocation GenDivRem(RegLocation rl_dest, int reg_lo, int reg_hi, bool is_div);
-    RegLocation GenDivRemLit(RegLocation rl_dest, int reg_lo, int lit, bool is_div);
+    void GenOrLong(Instruction::Code opcode, RegLocation rl_dest, RegLocation rl_src1,
+                   RegLocation rl_src2);
+    void GenSubLong(Instruction::Code opcode, RegLocation rl_dest, RegLocation rl_src1,
+                    RegLocation rl_src2);
+    void GenXorLong(Instruction::Code opcode, RegLocation rl_dest, RegLocation rl_src1,
+                    RegLocation rl_src2);
+    LIR* GenRegMemCheck(ConditionCode c_code, RegStorage reg1, RegStorage base, int offset,
+                        ThrowKind kind);
+    RegLocation GenDivRem(RegLocation rl_dest, RegStorage reg_lo, RegStorage reg_hi, bool is_div);
+    RegLocation GenDivRemLit(RegLocation rl_dest, RegStorage reg_lo, int lit, bool is_div);
     void GenCmpLong(RegLocation rl_dest, RegLocation rl_src1, RegLocation rl_src2);
-    void GenDivZeroCheck(int reg_lo, int reg_hi);
+    void GenDivZeroCheck(RegStorage reg);
     void GenEntrySequence(RegLocation* ArgLocs, RegLocation rl_method);
     void GenExitSequence();
     void GenSpecialExitSequence();
@@ -131,7 +141,7 @@
     void GenMemBarrier(MemBarrierKind barrier_kind);
     void GenMoveException(RegLocation rl_dest);
     void GenMultiplyByTwoBitMultiplier(RegLocation rl_src, RegLocation rl_result, int lit,
-                                               int first_bit, int second_bit);
+                                       int first_bit, int second_bit);
     void GenNegDouble(RegLocation rl_dest, RegLocation rl_src);
     void GenNegFloat(RegLocation rl_dest, RegLocation rl_src);
     void GenPackedSwitch(MIR* mir, uint32_t table_offset, RegLocation rl_src);
@@ -140,36 +150,39 @@
 
     // Required for target - single operation generators.
     LIR* OpUnconditionalBranch(LIR* target);
-    LIR* OpCmpBranch(ConditionCode cond, int src1, int src2, LIR* target);
-    LIR* OpCmpImmBranch(ConditionCode cond, int reg, int check_value, LIR* target);
+    LIR* OpCmpBranch(ConditionCode cond, RegStorage src1, RegStorage src2, LIR* target);
+    LIR* OpCmpImmBranch(ConditionCode cond, RegStorage reg, int check_value, LIR* target);
     LIR* OpCondBranch(ConditionCode cc, LIR* target);
-    LIR* OpDecAndBranch(ConditionCode c_code, int reg, LIR* target);
-    LIR* OpFpRegCopy(int r_dest, int r_src);
+    LIR* OpDecAndBranch(ConditionCode c_code, RegStorage reg, LIR* target);
+    LIR* OpFpRegCopy(RegStorage r_dest, RegStorage r_src);
     LIR* OpIT(ConditionCode cond, const char* guide);
-    LIR* OpMem(OpKind op, int rBase, int disp);
-    LIR* OpPcRelLoad(int reg, LIR* target);
-    LIR* OpReg(OpKind op, int r_dest_src);
-    LIR* OpRegCopy(int r_dest, int r_src);
-    LIR* OpRegCopyNoInsert(int r_dest, int r_src);
-    LIR* OpRegImm(OpKind op, int r_dest_src1, int value);
-    LIR* OpRegMem(OpKind op, int r_dest, int rBase, int offset);
-    LIR* OpRegReg(OpKind op, int r_dest_src1, int r_src2);
-    LIR* OpMovRegMem(int r_dest, int r_base, int offset, MoveType move_type);
-    LIR* OpMovMemReg(int r_base, int offset, int r_src, MoveType move_type);
-    LIR* OpCondRegReg(OpKind op, ConditionCode cc, int r_dest, int r_src);
-    LIR* OpRegRegImm(OpKind op, int r_dest, int r_src1, int value);
-    LIR* OpRegRegReg(OpKind op, int r_dest, int r_src1, int r_src2);
+    LIR* OpMem(OpKind op, RegStorage r_base, int disp);
+    LIR* OpPcRelLoad(RegStorage reg, LIR* target);
+    LIR* OpReg(OpKind op, RegStorage r_dest_src);
+    LIR* OpRegCopy(RegStorage r_dest, RegStorage r_src);
+    LIR* OpRegCopyNoInsert(RegStorage r_dest, RegStorage r_src);
+    LIR* OpRegImm(OpKind op, RegStorage r_dest_src1, int value);
+    LIR* OpRegMem(OpKind op, RegStorage r_dest, RegStorage r_base, int offset);
+    LIR* OpRegReg(OpKind op, RegStorage r_dest_src1, RegStorage r_src2);
+    LIR* OpMovRegMem(RegStorage r_dest, RegStorage r_base, int offset, MoveType move_type);
+    LIR* OpMovMemReg(RegStorage r_base, int offset, RegStorage r_src, MoveType move_type);
+    LIR* OpCondRegReg(OpKind op, ConditionCode cc, RegStorage r_dest, RegStorage r_src);
+    LIR* OpRegRegImm(OpKind op, RegStorage r_dest, RegStorage r_src1, int value);
+    LIR* OpRegRegReg(OpKind op, RegStorage r_dest, RegStorage r_src1, RegStorage r_src2);
     LIR* OpTestSuspend(LIR* target);
     LIR* OpThreadMem(OpKind op, ThreadOffset thread_offset);
-    LIR* OpVldm(int rBase, int count);
-    LIR* OpVstm(int rBase, int count);
-    void OpLea(int rBase, int reg1, int reg2, int scale, int offset);
-    void OpRegCopyWide(int dest_lo, int dest_hi, int src_lo, int src_hi);
+    LIR* OpVldm(RegStorage r_base, int count);
+    LIR* OpVstm(RegStorage r_base, int count);
+    void OpLea(RegStorage r_base, RegStorage reg1, RegStorage reg2, int scale, int offset);
+    void OpRegCopyWide(RegStorage dest, RegStorage src);
     void OpTlsCmp(ThreadOffset offset, int val);
 
-    LIR* LoadBaseDispBody(int rBase, int displacement, int r_dest, int r_dest_hi, OpSize size,
-                          int s_reg);
-    LIR* StoreBaseDispBody(int rBase, int displacement, int r_src, int r_src_hi, OpSize size);
+    // TODO: collapse r_dest.
+    LIR* LoadBaseDispBody(RegStorage r_base, int displacement, RegStorage r_dest,
+                          RegStorage r_dest_hi, OpSize size, int s_reg);
+    // TODO: collapse r_src.
+    LIR* StoreBaseDispBody(RegStorage r_base, int displacement, RegStorage r_src,
+                           RegStorage r_src_hi, OpSize size);
     void SpillCoreRegs();
     void UnSpillCoreRegs();
     static const MipsEncodingMap EncodingMap[kMipsLast];
diff --git a/compiler/dex/quick/mips/fp_mips.cc b/compiler/dex/quick/mips/fp_mips.cc
index cf4f19f..2bc5540 100644
--- a/compiler/dex/quick/mips/fp_mips.cc
+++ b/compiler/dex/quick/mips/fp_mips.cc
@@ -111,8 +111,8 @@
   rl_result = EvalLoc(rl_dest, kFPReg, true);
   DCHECK(rl_dest.wide);
   DCHECK(rl_result.wide);
-  NewLIR3(op, S2d(rl_result.reg.GetReg(), rl_result.reg.GetHighReg()), S2d(rl_src1.reg.GetReg(), rl_src1.reg.GetHighReg()),
-          S2d(rl_src2.reg.GetReg(), rl_src2.reg.GetHighReg()));
+  NewLIR3(op, S2d(rl_result.reg.GetLowReg(), rl_result.reg.GetHighReg()), S2d(rl_src1.reg.GetLowReg(), rl_src1.reg.GetHighReg()),
+          S2d(rl_src2.reg.GetLowReg(), rl_src2.reg.GetHighReg()));
   StoreValueWide(rl_dest, rl_result);
 }
 
@@ -157,14 +157,14 @@
   }
   if (rl_src.wide) {
     rl_src = LoadValueWide(rl_src, kFPReg);
-    src_reg = S2d(rl_src.reg.GetReg(), rl_src.reg.GetHighReg());
+    src_reg = S2d(rl_src.reg.GetLowReg(), rl_src.reg.GetHighReg());
   } else {
     rl_src = LoadValue(rl_src, kFPReg);
     src_reg = rl_src.reg.GetReg();
   }
   if (rl_dest.wide) {
     rl_result = EvalLoc(rl_dest, kFPReg, true);
-    NewLIR2(op, S2d(rl_result.reg.GetReg(), rl_result.reg.GetHighReg()), src_reg);
+    NewLIR2(op, S2d(rl_result.reg.GetLowReg(), rl_result.reg.GetHighReg()), src_reg);
     StoreValueWide(rl_dest, rl_result);
   } else {
     rl_result = EvalLoc(rl_dest, kFPReg, true);
@@ -199,13 +199,15 @@
   FlushAllRegs();
   LockCallTemps();
   if (wide) {
-    LoadValueDirectWideFixed(rl_src1, rMIPS_FARG0, rMIPS_FARG1);
-    LoadValueDirectWideFixed(rl_src2, rMIPS_FARG2, rMIPS_FARG3);
+    RegStorage r_tmp1(RegStorage::k64BitPair, rMIPS_FARG0, rMIPS_FARG1);
+    RegStorage r_tmp2(RegStorage::k64BitPair, rMIPS_FARG2, rMIPS_FARG3);
+    LoadValueDirectWideFixed(rl_src1, r_tmp1);
+    LoadValueDirectWideFixed(rl_src2, r_tmp2);
   } else {
-    LoadValueDirectFixed(rl_src1, rMIPS_FARG0);
-    LoadValueDirectFixed(rl_src2, rMIPS_FARG2);
+    LoadValueDirectFixed(rl_src1, rs_rMIPS_FARG0);
+    LoadValueDirectFixed(rl_src2, rs_rMIPS_FARG2);
   }
-  int r_tgt = LoadHelper(offset);
+  RegStorage r_tgt = LoadHelper(offset);
   // NOTE: not a safepoint
   OpReg(kOpBlx, r_tgt);
   RegLocation rl_result = GetReturn(false);
@@ -221,7 +223,7 @@
   RegLocation rl_result;
   rl_src = LoadValue(rl_src, kCoreReg);
   rl_result = EvalLoc(rl_dest, kCoreReg, true);
-  OpRegRegImm(kOpAdd, rl_result.reg.GetReg(), rl_src.reg.GetReg(), 0x80000000);
+  OpRegRegImm(kOpAdd, rl_result.reg, rl_src.reg, 0x80000000);
   StoreValue(rl_dest, rl_result);
 }
 
@@ -229,8 +231,8 @@
   RegLocation rl_result;
   rl_src = LoadValueWide(rl_src, kCoreReg);
   rl_result = EvalLoc(rl_dest, kCoreReg, true);
-  OpRegRegImm(kOpAdd, rl_result.reg.GetHighReg(), rl_src.reg.GetHighReg(), 0x80000000);
-  OpRegCopy(rl_result.reg.GetReg(), rl_src.reg.GetReg());
+  OpRegRegImm(kOpAdd, rl_result.reg.GetHigh(), rl_src.reg.GetHigh(), 0x80000000);
+  OpRegCopy(rl_result.reg, rl_src.reg);
   StoreValueWide(rl_dest, rl_result);
 }
 
diff --git a/compiler/dex/quick/mips/int_mips.cc b/compiler/dex/quick/mips/int_mips.cc
index 9fcc8bb..dfe8b35 100644
--- a/compiler/dex/quick/mips/int_mips.cc
+++ b/compiler/dex/quick/mips/int_mips.cc
@@ -44,15 +44,15 @@
                              RegLocation rl_src2) {
   rl_src1 = LoadValueWide(rl_src1, kCoreReg);
   rl_src2 = LoadValueWide(rl_src2, kCoreReg);
-  int t0 = AllocTemp();
-  int t1 = AllocTemp();
+  int t0 = AllocTemp().GetReg();
+  int t1 = AllocTemp().GetReg();
   RegLocation rl_result = EvalLoc(rl_dest, kCoreReg, true);
   NewLIR3(kMipsSlt, t0, rl_src1.reg.GetHighReg(), rl_src2.reg.GetHighReg());
   NewLIR3(kMipsSlt, t1, rl_src2.reg.GetHighReg(), rl_src1.reg.GetHighReg());
   NewLIR3(kMipsSubu, rl_result.reg.GetReg(), t1, t0);
-  LIR* branch = OpCmpImmBranch(kCondNe, rl_result.reg.GetReg(), 0, NULL);
-  NewLIR3(kMipsSltu, t0, rl_src1.reg.GetReg(), rl_src2.reg.GetReg());
-  NewLIR3(kMipsSltu, t1, rl_src2.reg.GetReg(), rl_src1.reg.GetReg());
+  LIR* branch = OpCmpImmBranch(kCondNe, rl_result.reg, 0, NULL);
+  NewLIR3(kMipsSltu, t0, rl_src1.reg.GetLowReg(), rl_src2.reg.GetLowReg());
+  NewLIR3(kMipsSltu, t1, rl_src2.reg.GetLowReg(), rl_src1.reg.GetLowReg());
   NewLIR3(kMipsSubu, rl_result.reg.GetReg(), t1, t0);
   FreeTemp(t0);
   FreeTemp(t1);
@@ -61,8 +61,7 @@
   StoreValue(rl_dest, rl_result);
 }
 
-LIR* MipsMir2Lir::OpCmpBranch(ConditionCode cond, int src1, int src2,
-                              LIR* target) {
+LIR* MipsMir2Lir::OpCmpBranch(ConditionCode cond, RegStorage src1, RegStorage src2, LIR* target) {
   LIR* branch;
   MipsOpCode slt_op;
   MipsOpCode br_op;
@@ -113,13 +112,13 @@
       return NULL;
   }
   if (cmp_zero) {
-    branch = NewLIR2(br_op, src1, src2);
+    branch = NewLIR2(br_op, src1.GetReg(), src2.GetReg());
   } else {
-    int t_reg = AllocTemp();
+    int t_reg = AllocTemp().GetReg();
     if (swapped) {
-      NewLIR3(slt_op, t_reg, src2, src1);
+      NewLIR3(slt_op, t_reg, src2.GetReg(), src1.GetReg());
     } else {
-      NewLIR3(slt_op, t_reg, src1, src2);
+      NewLIR3(slt_op, t_reg, src1.GetReg(), src2.GetReg());
     }
     branch = NewLIR1(br_op, t_reg);
     FreeTemp(t_reg);
@@ -128,12 +127,11 @@
   return branch;
 }
 
-LIR* MipsMir2Lir::OpCmpImmBranch(ConditionCode cond, int reg,
-                                 int check_value, LIR* target) {
+LIR* MipsMir2Lir::OpCmpImmBranch(ConditionCode cond, RegStorage reg, int check_value, LIR* target) {
   LIR* branch;
   if (check_value != 0) {
     // TUNING: handle s16 & kCondLt/Mi case using slti
-    int t_reg = AllocTemp();
+    RegStorage t_reg = AllocTemp();
     LoadConstant(t_reg, check_value);
     branch = OpCmpBranch(cond, reg, t_reg, target);
     FreeTemp(t_reg);
@@ -150,60 +148,66 @@
     case kCondNe: opc = kMipsBnez; break;
     default:
       // Tuning: use slti when applicable
-      int t_reg = AllocTemp();
+      RegStorage t_reg = AllocTemp();
       LoadConstant(t_reg, check_value);
       branch = OpCmpBranch(cond, reg, t_reg, target);
       FreeTemp(t_reg);
       return branch;
   }
-  branch = NewLIR1(opc, reg);
+  branch = NewLIR1(opc, reg.GetReg());
   branch->target = target;
   return branch;
 }
 
-LIR* MipsMir2Lir::OpRegCopyNoInsert(int r_dest, int r_src) {
-  if (MIPS_FPREG(r_dest) || MIPS_FPREG(r_src))
+LIR* MipsMir2Lir::OpRegCopyNoInsert(RegStorage r_dest, RegStorage r_src) {
+  // If src or dest is a pair, we'll be using low reg.
+  if (r_dest.IsPair()) {
+    r_dest = r_dest.GetLow();
+  }
+  if (r_src.IsPair()) {
+    r_src = r_src.GetLow();
+  }
+  if (MIPS_FPREG(r_dest.GetReg()) || MIPS_FPREG(r_src.GetReg()))
     return OpFpRegCopy(r_dest, r_src);
   LIR* res = RawLIR(current_dalvik_offset_, kMipsMove,
-            r_dest, r_src);
+            r_dest.GetReg(), r_src.GetReg());
   if (!(cu_->disable_opt & (1 << kSafeOptimizations)) && r_dest == r_src) {
     res->flags.is_nop = true;
   }
   return res;
 }
 
-LIR* MipsMir2Lir::OpRegCopy(int r_dest, int r_src) {
+LIR* MipsMir2Lir::OpRegCopy(RegStorage r_dest, RegStorage r_src) {
   LIR *res = OpRegCopyNoInsert(r_dest, r_src);
   AppendLIR(res);
   return res;
 }
 
-void MipsMir2Lir::OpRegCopyWide(int dest_lo, int dest_hi, int src_lo,
-                                int src_hi) {
-  bool dest_fp = MIPS_FPREG(dest_lo) && MIPS_FPREG(dest_hi);
-  bool src_fp = MIPS_FPREG(src_lo) && MIPS_FPREG(src_hi);
-  assert(MIPS_FPREG(src_lo) == MIPS_FPREG(src_hi));
-  assert(MIPS_FPREG(dest_lo) == MIPS_FPREG(dest_hi));
+void MipsMir2Lir::OpRegCopyWide(RegStorage r_dest, RegStorage r_src) {
+  bool dest_fp = MIPS_FPREG(r_dest.GetLowReg());
+  bool src_fp = MIPS_FPREG(r_src.GetLowReg());
   if (dest_fp) {
     if (src_fp) {
-      OpRegCopy(S2d(dest_lo, dest_hi), S2d(src_lo, src_hi));
+      // FIXME: handle this here - reserve OpRegCopy for 32-bit copies.
+      OpRegCopy(RegStorage::Solo64(S2d(r_dest.GetLowReg(), r_dest.GetHighReg())),
+                RegStorage::Solo64(S2d(r_src.GetLowReg(), r_src.GetHighReg())));
     } else {
        /* note the operands are swapped for the mtc1 instr */
-      NewLIR2(kMipsMtc1, src_lo, dest_lo);
-      NewLIR2(kMipsMtc1, src_hi, dest_hi);
+      NewLIR2(kMipsMtc1, r_src.GetLowReg(), r_dest.GetLowReg());
+      NewLIR2(kMipsMtc1, r_src.GetHighReg(), r_dest.GetHighReg());
     }
   } else {
     if (src_fp) {
-      NewLIR2(kMipsMfc1, dest_lo, src_lo);
-      NewLIR2(kMipsMfc1, dest_hi, src_hi);
+      NewLIR2(kMipsMfc1, r_dest.GetLowReg(), r_src.GetLowReg());
+      NewLIR2(kMipsMfc1, r_dest.GetHighReg(), r_src.GetHighReg());
     } else {
       // Handle overlap
-      if (src_hi == dest_lo) {
-        OpRegCopy(dest_hi, src_hi);
-        OpRegCopy(dest_lo, src_lo);
+      if (r_src.GetHighReg() == r_dest.GetLowReg()) {
+        OpRegCopy(r_dest.GetHigh(), r_src.GetHigh());
+        OpRegCopy(r_dest.GetLow(), r_src.GetLow());
       } else {
-        OpRegCopy(dest_lo, src_lo);
-        OpRegCopy(dest_hi, src_hi);
+        OpRegCopy(r_dest.GetLow(), r_src.GetLow());
+        OpRegCopy(r_dest.GetHigh(), r_src.GetHigh());
       }
     }
   }
@@ -217,34 +221,34 @@
   UNIMPLEMENTED(FATAL) << "Need codegen for fused long cmp branch";
 }
 
-LIR* MipsMir2Lir::GenRegMemCheck(ConditionCode c_code,
-                    int reg1, int base, int offset, ThrowKind kind) {
+LIR* MipsMir2Lir::GenRegMemCheck(ConditionCode c_code, RegStorage reg1, RegStorage base,
+                                 int offset, ThrowKind kind) {
   LOG(FATAL) << "Unexpected use of GenRegMemCheck for Arm";
   return NULL;
 }
 
-RegLocation MipsMir2Lir::GenDivRem(RegLocation rl_dest, int reg1, int reg2,
+RegLocation MipsMir2Lir::GenDivRem(RegLocation rl_dest, RegStorage reg1, RegStorage reg2,
                                     bool is_div) {
-  NewLIR4(kMipsDiv, r_HI, r_LO, reg1, reg2);
+  NewLIR4(kMipsDiv, rHI, rLO, reg1.GetReg(), reg2.GetReg());
   RegLocation rl_result = EvalLoc(rl_dest, kCoreReg, true);
   if (is_div) {
-    NewLIR2(kMipsMflo, rl_result.reg.GetReg(), r_LO);
+    NewLIR2(kMipsMflo, rl_result.reg.GetReg(), rLO);
   } else {
-    NewLIR2(kMipsMfhi, rl_result.reg.GetReg(), r_HI);
+    NewLIR2(kMipsMfhi, rl_result.reg.GetReg(), rHI);
   }
   return rl_result;
 }
 
-RegLocation MipsMir2Lir::GenDivRemLit(RegLocation rl_dest, int reg1, int lit,
+RegLocation MipsMir2Lir::GenDivRemLit(RegLocation rl_dest, RegStorage reg1, int lit,
                                        bool is_div) {
-  int t_reg = AllocTemp();
-  NewLIR3(kMipsAddiu, t_reg, r_ZERO, lit);
-  NewLIR4(kMipsDiv, r_HI, r_LO, reg1, t_reg);
+  int t_reg = AllocTemp().GetReg();
+  NewLIR3(kMipsAddiu, t_reg, rZERO, lit);
+  NewLIR4(kMipsDiv, rHI, rLO, reg1.GetReg(), t_reg);
   RegLocation rl_result = EvalLoc(rl_dest, kCoreReg, true);
   if (is_div) {
-    NewLIR2(kMipsMflo, rl_result.reg.GetReg(), r_LO);
+    NewLIR2(kMipsMflo, rl_result.reg.GetReg(), rLO);
   } else {
-    NewLIR2(kMipsMfhi, rl_result.reg.GetReg(), r_HI);
+    NewLIR2(kMipsMfhi, rl_result.reg.GetReg(), rHI);
   }
   FreeTemp(t_reg);
   return rl_result;
@@ -261,7 +265,8 @@
   return rl_dest;
 }
 
-void MipsMir2Lir::OpLea(int rBase, int reg1, int reg2, int scale, int offset) {
+void MipsMir2Lir::OpLea(RegStorage r_base, RegStorage reg1, RegStorage reg2, int scale,
+                        int offset) {
   LOG(FATAL) << "Unexpected use of OpLea for Arm";
 }
 
@@ -285,12 +290,12 @@
     return false;
   }
   RegLocation rl_src_address = info->args[0];  // long address
-  rl_src_address.wide = 0;  // ignore high half in info->args[1]
+  rl_src_address = NarrowRegLoc(rl_src_address);  // ignore high half in info->args[1]
   RegLocation rl_dest = InlineTarget(info);
   RegLocation rl_address = LoadValue(rl_src_address, kCoreReg);
   RegLocation rl_result = EvalLoc(rl_dest, kCoreReg, true);
   DCHECK(size == kSignedByte);
-  LoadBaseDisp(rl_address.reg.GetReg(), 0, rl_result.reg.GetReg(), size, INVALID_SREG);
+  LoadBaseDisp(rl_address.reg, 0, rl_result.reg, size, INVALID_SREG);
   StoreValue(rl_dest, rl_result);
   return true;
 }
@@ -301,26 +306,26 @@
     return false;
   }
   RegLocation rl_src_address = info->args[0];  // long address
-  rl_src_address.wide = 0;  // ignore high half in info->args[1]
+  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);
   DCHECK(size == kSignedByte);
   RegLocation rl_value = LoadValue(rl_src_value, kCoreReg);
-  StoreBaseDisp(rl_address.reg.GetReg(), 0, rl_value.reg.GetReg(), size);
+  StoreBaseDisp(rl_address.reg, 0, rl_value.reg, size);
   return true;
 }
 
-LIR* MipsMir2Lir::OpPcRelLoad(int reg, LIR* target) {
+LIR* MipsMir2Lir::OpPcRelLoad(RegStorage reg, LIR* target) {
   LOG(FATAL) << "Unexpected use of OpPcRelLoad for Mips";
   return NULL;
 }
 
-LIR* MipsMir2Lir::OpVldm(int rBase, int count) {
+LIR* MipsMir2Lir::OpVldm(RegStorage r_base, int count) {
   LOG(FATAL) << "Unexpected use of OpVldm for Mips";
   return NULL;
 }
 
-LIR* MipsMir2Lir::OpVstm(int rBase, int count) {
+LIR* MipsMir2Lir::OpVstm(RegStorage r_base, int count) {
   LOG(FATAL) << "Unexpected use of OpVstm for Mips";
   return NULL;
 }
@@ -328,30 +333,31 @@
 void MipsMir2Lir::GenMultiplyByTwoBitMultiplier(RegLocation rl_src,
                                                 RegLocation rl_result, int lit,
                                                 int first_bit, int second_bit) {
-  int t_reg = AllocTemp();
-  OpRegRegImm(kOpLsl, t_reg, rl_src.reg.GetReg(), second_bit - first_bit);
-  OpRegRegReg(kOpAdd, rl_result.reg.GetReg(), rl_src.reg.GetReg(), t_reg);
+  RegStorage t_reg = AllocTemp();
+  OpRegRegImm(kOpLsl, t_reg, rl_src.reg, second_bit - first_bit);
+  OpRegRegReg(kOpAdd, rl_result.reg, rl_src.reg, t_reg);
   FreeTemp(t_reg);
   if (first_bit != 0) {
-    OpRegRegImm(kOpLsl, rl_result.reg.GetReg(), rl_result.reg.GetReg(), first_bit);
+    OpRegRegImm(kOpLsl, rl_result.reg, rl_result.reg, first_bit);
   }
 }
 
-void MipsMir2Lir::GenDivZeroCheck(int reg_lo, int reg_hi) {
-  int t_reg = AllocTemp();
-  OpRegRegReg(kOpOr, t_reg, reg_lo, reg_hi);
+void MipsMir2Lir::GenDivZeroCheck(RegStorage reg) {
+  DCHECK(reg.IsPair());   // TODO: support k64BitSolo.
+  RegStorage t_reg = AllocTemp();
+  OpRegRegReg(kOpOr, t_reg, reg.GetLow(), reg.GetHigh());
   GenImmedCheck(kCondEq, t_reg, 0, kThrowDivZero);
   FreeTemp(t_reg);
 }
 
 // Test suspend flag, return target of taken suspend branch
 LIR* MipsMir2Lir::OpTestSuspend(LIR* target) {
-  OpRegImm(kOpSub, rMIPS_SUSPEND, 1);
-  return OpCmpImmBranch((target == NULL) ? kCondEq : kCondNe, rMIPS_SUSPEND, 0, target);
+  OpRegImm(kOpSub, rs_rMIPS_SUSPEND, 1);
+  return OpCmpImmBranch((target == NULL) ? kCondEq : kCondNe, rs_rMIPS_SUSPEND, 0, target);
 }
 
 // Decrement register and branch on condition
-LIR* MipsMir2Lir::OpDecAndBranch(ConditionCode c_code, int reg, LIR* target) {
+LIR* MipsMir2Lir::OpDecAndBranch(ConditionCode c_code, RegStorage reg, LIR* target) {
   OpRegImm(kOpSub, reg, 1);
   return OpCmpImmBranch(c_code, reg, 0, target);
 }
@@ -385,11 +391,11 @@
    *  addu v1,v1,t1
    */
 
-  OpRegRegReg(kOpAdd, rl_result.reg.GetReg(), rl_src2.reg.GetReg(), rl_src1.reg.GetReg());
-  int t_reg = AllocTemp();
-  OpRegRegReg(kOpAdd, t_reg, rl_src2.reg.GetHighReg(), rl_src1.reg.GetHighReg());
-  NewLIR3(kMipsSltu, rl_result.reg.GetHighReg(), rl_result.reg.GetReg(), rl_src2.reg.GetReg());
-  OpRegRegReg(kOpAdd, rl_result.reg.GetHighReg(), rl_result.reg.GetHighReg(), t_reg);
+  OpRegRegReg(kOpAdd, rl_result.reg.GetLow(), rl_src2.reg.GetLow(), rl_src1.reg.GetLow());
+  RegStorage t_reg = AllocTemp();
+  OpRegRegReg(kOpAdd, t_reg, rl_src2.reg.GetHigh(), rl_src1.reg.GetHigh());
+  NewLIR3(kMipsSltu, rl_result.reg.GetHighReg(), rl_result.reg.GetLowReg(), rl_src2.reg.GetLowReg());
+  OpRegRegReg(kOpAdd, rl_result.reg.GetHigh(), rl_result.reg.GetHigh(), t_reg);
   FreeTemp(t_reg);
   StoreValueWide(rl_dest, rl_result);
 }
@@ -407,11 +413,11 @@
    *  subu  v1,v1,t1
    */
 
-  int t_reg = AllocTemp();
-  NewLIR3(kMipsSltu, t_reg, rl_src1.reg.GetReg(), rl_src2.reg.GetReg());
-  OpRegRegReg(kOpSub, rl_result.reg.GetReg(), rl_src1.reg.GetReg(), rl_src2.reg.GetReg());
-  OpRegRegReg(kOpSub, rl_result.reg.GetHighReg(), rl_src1.reg.GetHighReg(), rl_src2.reg.GetHighReg());
-  OpRegRegReg(kOpSub, rl_result.reg.GetHighReg(), rl_result.reg.GetHighReg(), t_reg);
+  RegStorage t_reg = AllocTemp();
+  NewLIR3(kMipsSltu, t_reg.GetReg(), rl_src1.reg.GetLowReg(), rl_src2.reg.GetLowReg());
+  OpRegRegReg(kOpSub, rl_result.reg.GetLow(), rl_src1.reg.GetLow(), rl_src2.reg.GetLow());
+  OpRegRegReg(kOpSub, rl_result.reg.GetHigh(), rl_src1.reg.GetHigh(), rl_src2.reg.GetHigh());
+  OpRegRegReg(kOpSub, rl_result.reg.GetHigh(), rl_result.reg.GetHigh(), t_reg);
   FreeTemp(t_reg);
   StoreValueWide(rl_dest, rl_result);
 }
@@ -427,11 +433,11 @@
    *  subu  v1,v1,t1
    */
 
-  OpRegReg(kOpNeg, rl_result.reg.GetReg(), rl_src.reg.GetReg());
-  OpRegReg(kOpNeg, rl_result.reg.GetHighReg(), rl_src.reg.GetHighReg());
-  int t_reg = AllocTemp();
-  NewLIR3(kMipsSltu, t_reg, r_ZERO, rl_result.reg.GetReg());
-  OpRegRegReg(kOpSub, rl_result.reg.GetHighReg(), rl_result.reg.GetHighReg(), t_reg);
+  OpRegReg(kOpNeg, rl_result.reg.GetLow(), rl_src.reg.GetLow());
+  OpRegReg(kOpNeg, rl_result.reg.GetHigh(), rl_src.reg.GetHigh());
+  RegStorage t_reg = AllocTemp();
+  NewLIR3(kMipsSltu, t_reg.GetReg(), rZERO, rl_result.reg.GetLowReg());
+  OpRegRegReg(kOpSub, rl_result.reg.GetHigh(), rl_result.reg.GetHigh(), t_reg);
   FreeTemp(t_reg);
   StoreValueWide(rl_dest, rl_result);
 }
@@ -471,36 +477,36 @@
   }
 
   /* null object? */
-  GenNullCheck(rl_array.reg.GetReg(), opt_flags);
+  GenNullCheck(rl_array.reg, opt_flags);
 
-  int reg_ptr = AllocTemp();
+  RegStorage reg_ptr = AllocTemp();
   bool needs_range_check = (!(opt_flags & MIR_IGNORE_RANGE_CHECK));
-  int reg_len = INVALID_REG;
+  RegStorage reg_len;
   if (needs_range_check) {
     reg_len = AllocTemp();
     /* Get len */
-    LoadWordDisp(rl_array.reg.GetReg(), len_offset, reg_len);
+    LoadWordDisp(rl_array.reg, len_offset, reg_len);
   }
   /* reg_ptr -> array data */
-  OpRegRegImm(kOpAdd, reg_ptr, rl_array.reg.GetReg(), data_offset);
+  OpRegRegImm(kOpAdd, reg_ptr, rl_array.reg, data_offset);
   FreeTemp(rl_array.reg.GetReg());
   if ((size == kLong) || (size == kDouble)) {
     if (scale) {
-      int r_new_index = AllocTemp();
-      OpRegRegImm(kOpLsl, r_new_index, rl_index.reg.GetReg(), scale);
+      RegStorage r_new_index = AllocTemp();
+      OpRegRegImm(kOpLsl, r_new_index, rl_index.reg, scale);
       OpRegReg(kOpAdd, reg_ptr, r_new_index);
       FreeTemp(r_new_index);
     } else {
-      OpRegReg(kOpAdd, reg_ptr, rl_index.reg.GetReg());
+      OpRegReg(kOpAdd, reg_ptr, rl_index.reg);
     }
-    FreeTemp(rl_index.reg.GetReg());
+    FreeTemp(rl_index.reg);
     rl_result = EvalLoc(rl_dest, reg_class, true);
 
     if (needs_range_check) {
-      GenRegRegCheck(kCondUge, rl_index.reg.GetReg(), reg_len, kThrowArrayBounds);
+      GenRegRegCheck(kCondUge, rl_index.reg, reg_len, kThrowArrayBounds);
       FreeTemp(reg_len);
     }
-    LoadBaseDispWide(reg_ptr, 0, rl_result.reg.GetReg(), rl_result.reg.GetHighReg(), INVALID_SREG);
+    LoadBaseDispWide(reg_ptr, 0, rl_result.reg, INVALID_SREG);
 
     FreeTemp(reg_ptr);
     StoreValueWide(rl_dest, rl_result);
@@ -508,10 +514,10 @@
     rl_result = EvalLoc(rl_dest, reg_class, true);
 
     if (needs_range_check) {
-      GenRegRegCheck(kCondUge, rl_index.reg.GetReg(), reg_len, kThrowArrayBounds);
+      GenRegRegCheck(kCondUge, rl_index.reg, reg_len, kThrowArrayBounds);
       FreeTemp(reg_len);
     }
-    LoadBaseIndexed(reg_ptr, rl_index.reg.GetReg(), rl_result.reg.GetReg(), scale, size);
+    LoadBaseIndexed(reg_ptr, rl_index.reg, rl_result.reg, scale, size);
 
     FreeTemp(reg_ptr);
     StoreValue(rl_dest, rl_result);
@@ -536,27 +542,27 @@
 
   rl_array = LoadValue(rl_array, kCoreReg);
   rl_index = LoadValue(rl_index, kCoreReg);
-  int reg_ptr = INVALID_REG;
+  RegStorage reg_ptr;
   bool allocated_reg_ptr_temp = false;
   if (IsTemp(rl_array.reg.GetReg()) && !card_mark) {
     Clobber(rl_array.reg.GetReg());
-    reg_ptr = rl_array.reg.GetReg();
+    reg_ptr = rl_array.reg;
   } else {
     reg_ptr = AllocTemp();
-    OpRegCopy(reg_ptr, rl_array.reg.GetReg());
+    OpRegCopy(reg_ptr, rl_array.reg);
     allocated_reg_ptr_temp = true;
   }
 
   /* null object? */
-  GenNullCheck(rl_array.reg.GetReg(), opt_flags);
+  GenNullCheck(rl_array.reg, opt_flags);
 
   bool needs_range_check = (!(opt_flags & MIR_IGNORE_RANGE_CHECK));
-  int reg_len = INVALID_REG;
+  RegStorage reg_len;
   if (needs_range_check) {
     reg_len = AllocTemp();
     // NOTE: max live temps(4) here.
     /* Get len */
-    LoadWordDisp(rl_array.reg.GetReg(), len_offset, reg_len);
+    LoadWordDisp(rl_array.reg, len_offset, reg_len);
   }
   /* reg_ptr -> array data */
   OpRegImm(kOpAdd, reg_ptr, data_offset);
@@ -564,35 +570,34 @@
   if ((size == kLong) || (size == kDouble)) {
     // TUNING: specific wide routine that can handle fp regs
     if (scale) {
-      int r_new_index = AllocTemp();
-      OpRegRegImm(kOpLsl, r_new_index, rl_index.reg.GetReg(), scale);
+      RegStorage r_new_index = AllocTemp();
+      OpRegRegImm(kOpLsl, r_new_index, rl_index.reg, scale);
       OpRegReg(kOpAdd, reg_ptr, r_new_index);
       FreeTemp(r_new_index);
     } else {
-      OpRegReg(kOpAdd, reg_ptr, rl_index.reg.GetReg());
+      OpRegReg(kOpAdd, reg_ptr, rl_index.reg);
     }
     rl_src = LoadValueWide(rl_src, reg_class);
 
     if (needs_range_check) {
-      GenRegRegCheck(kCondUge, rl_index.reg.GetReg(), reg_len, kThrowArrayBounds);
+      GenRegRegCheck(kCondUge, rl_index.reg, reg_len, kThrowArrayBounds);
       FreeTemp(reg_len);
     }
 
-    StoreBaseDispWide(reg_ptr, 0, rl_src.reg.GetReg(), rl_src.reg.GetHighReg());
+    StoreBaseDispWide(reg_ptr, 0, rl_src.reg);
   } else {
     rl_src = LoadValue(rl_src, reg_class);
     if (needs_range_check) {
-      GenRegRegCheck(kCondUge, rl_index.reg.GetReg(), reg_len, kThrowArrayBounds);
+      GenRegRegCheck(kCondUge, rl_index.reg, reg_len, kThrowArrayBounds);
       FreeTemp(reg_len);
     }
-    StoreBaseIndexed(reg_ptr, rl_index.reg.GetReg(), rl_src.reg.GetReg(),
-                     scale, size);
+    StoreBaseIndexed(reg_ptr, rl_index.reg, rl_src.reg, scale, size);
   }
   if (allocated_reg_ptr_temp) {
     FreeTemp(reg_ptr);
   }
   if (card_mark) {
-    MarkGCCard(rl_src.reg.GetReg(), rl_array.reg.GetReg());
+    MarkGCCard(rl_src.reg, rl_array.reg);
   }
 }
 
diff --git a/compiler/dex/quick/mips/mips_lir.h b/compiler/dex/quick/mips/mips_lir.h
index 77ae337..96cd3d8 100644
--- a/compiler/dex/quick/mips/mips_lir.h
+++ b/compiler/dex/quick/mips/mips_lir.h
@@ -109,36 +109,37 @@
 // Mask to strip off fp flags.
 #define MIPS_FP_REG_MASK (MIPS_FP_REG_OFFSET-1)
 
-#ifdef HAVE_LITTLE_ENDIAN
 #define LOWORD_OFFSET 0
 #define HIWORD_OFFSET 4
-#define r_ARG0 r_A0
-#define r_ARG1 r_A1
-#define r_ARG2 r_A2
-#define r_ARG3 r_A3
-#define r_RESULT0 r_V0
-#define r_RESULT1 r_V1
-#else
-#define LOWORD_OFFSET 4
-#define HIWORD_OFFSET 0
-#define r_ARG0 r_A1
-#define r_ARG1 r_A0
-#define r_ARG2 r_A3
-#define r_ARG3 r_A2
-#define r_RESULT0 r_V1
-#define r_RESULT1 r_V0
-#endif
+#define rARG0 rA0
+#define rs_rARG0 rs_rA0
+#define rARG1 rA1
+#define rs_rARG1 rs_rA1
+#define rARG2 rA2
+#define rs_rARG2 rs_rA2
+#define rARG3 rA3
+#define rs_rARG3 rs_rA3
+#define rRESULT0 rV0
+#define rs_rRESULT0 rs_rV0
+#define rRESULT1 rV1
+#define rs_rRESULT1 rs_rV1
 
-// These are the same for both big and little endian.
-#define r_FARG0 r_F12
-#define r_FARG1 r_F13
-#define r_FARG2 r_F14
-#define r_FARG3 r_F15
-#define r_FRESULT0 r_F0
-#define r_FRESULT1 r_F1
+#define rFARG0 rF12
+#define rs_rFARG0 rs_rF12
+#define rFARG1 rF13
+#define rs_rFARG1 rs_rF13
+#define rFARG2 rF14
+#define rs_rFARG2 rs_rF14
+#define rFARG3 rF15
+#define rs_rFARG3 rs_rF15
+#define rFRESULT0 rF0
+#define rs_rFRESULT0 rs_rF0
+#define rFRESULT1 rF1
+#define rs_rFRESULT1 rs_rF1
 
 // Regs not used for Mips.
-#define rMIPS_PC INVALID_REG
+#define rMIPS_LR RegStorage::kInvalidRegVal
+#define rMIPS_PC RegStorage::kInvalidRegVal
 
 enum MipsResourceEncodingPos {
   kMipsGPReg0   = 0,
@@ -158,130 +159,183 @@
 #define ENCODE_MIPS_REG_PC           (1ULL << kMipsRegPC)
 
 enum MipsNativeRegisterPool {
-  r_ZERO = 0,
-  r_AT = 1,
-  r_V0 = 2,
-  r_V1 = 3,
-  r_A0 = 4,
-  r_A1 = 5,
-  r_A2 = 6,
-  r_A3 = 7,
-  r_T0 = 8,
-  r_T1 = 9,
-  r_T2 = 10,
-  r_T3 = 11,
-  r_T4 = 12,
-  r_T5 = 13,
-  r_T6 = 14,
-  r_T7 = 15,
-  r_S0 = 16,
-  r_S1 = 17,
-  r_S2 = 18,
-  r_S3 = 19,
-  r_S4 = 20,
-  r_S5 = 21,
-  r_S6 = 22,
-  r_S7 = 23,
-  r_T8 = 24,
-  r_T9 = 25,
-  r_K0 = 26,
-  r_K1 = 27,
-  r_GP = 28,
-  r_SP = 29,
-  r_FP = 30,
-  r_RA = 31,
+  rZERO = 0,
+  rAT = 1,
+  rV0 = 2,
+  rV1 = 3,
+  rA0 = 4,
+  rA1 = 5,
+  rA2 = 6,
+  rA3 = 7,
+  rT0 = 8,
+  rT1 = 9,
+  rT2 = 10,
+  rT3 = 11,
+  rT4 = 12,
+  rT5 = 13,
+  rT6 = 14,
+  rT7 = 15,
+  rS0 = 16,
+  rS1 = 17,
+  rS2 = 18,
+  rS3 = 19,
+  rS4 = 20,
+  rS5 = 21,
+  rS6 = 22,
+  rS7 = 23,
+  rT8 = 24,
+  rT9 = 25,
+  rK0 = 26,
+  rK1 = 27,
+  rGP = 28,
+  rSP = 29,
+  rFP = 30,
+  rRA = 31,
 
-  r_F0 = 0 + MIPS_FP_REG_OFFSET,
-  r_F1,
-  r_F2,
-  r_F3,
-  r_F4,
-  r_F5,
-  r_F6,
-  r_F7,
-  r_F8,
-  r_F9,
-  r_F10,
-  r_F11,
-  r_F12,
-  r_F13,
-  r_F14,
-  r_F15,
+  rF0 = 0 + MIPS_FP_REG_OFFSET,
+  rF1,
+  rF2,
+  rF3,
+  rF4,
+  rF5,
+  rF6,
+  rF7,
+  rF8,
+  rF9,
+  rF10,
+  rF11,
+  rF12,
+  rF13,
+  rF14,
+  rF15,
 #if 0
   /*
    * TODO: The shared resource mask doesn't have enough bit positions to describe all
    * MIPS registers.  Expand it and enable use of fp registers 16 through 31.
    */
-  r_F16,
-  r_F17,
-  r_F18,
-  r_F19,
-  r_F20,
-  r_F21,
-  r_F22,
-  r_F23,
-  r_F24,
-  r_F25,
-  r_F26,
-  r_F27,
-  r_F28,
-  r_F29,
-  r_F30,
-  r_F31,
+  rF16,
+  rF17,
+  rF18,
+  rF19,
+  rF20,
+  rF21,
+  rF22,
+  rF23,
+  rF24,
+  rF25,
+  rF26,
+  rF27,
+  rF28,
+  rF29,
+  rF30,
+  rF31,
 #endif
-  r_DF0 = r_F0 + MIPS_FP_DOUBLE,
-  r_DF1 = r_F2 + MIPS_FP_DOUBLE,
-  r_DF2 = r_F4 + MIPS_FP_DOUBLE,
-  r_DF3 = r_F6 + MIPS_FP_DOUBLE,
-  r_DF4 = r_F8 + MIPS_FP_DOUBLE,
-  r_DF5 = r_F10 + MIPS_FP_DOUBLE,
-  r_DF6 = r_F12 + MIPS_FP_DOUBLE,
-  r_DF7 = r_F14 + MIPS_FP_DOUBLE,
+  rDF0 = rF0 + MIPS_FP_DOUBLE,
+  rDF1 = rF2 + MIPS_FP_DOUBLE,
+  rDF2 = rF4 + MIPS_FP_DOUBLE,
+  rDF3 = rF6 + MIPS_FP_DOUBLE,
+  rDF4 = rF8 + MIPS_FP_DOUBLE,
+  rDF5 = rF10 + MIPS_FP_DOUBLE,
+  rDF6 = rF12 + MIPS_FP_DOUBLE,
+  rDF7 = rF14 + MIPS_FP_DOUBLE,
 #if 0  // TODO: expand resource mask to enable use of all MIPS fp registers.
-  r_DF8 = r_F16 + MIPS_FP_DOUBLE,
-  r_DF9 = r_F18 + MIPS_FP_DOUBLE,
-  r_DF10 = r_F20 + MIPS_FP_DOUBLE,
-  r_DF11 = r_F22 + MIPS_FP_DOUBLE,
-  r_DF12 = r_F24 + MIPS_FP_DOUBLE,
-  r_DF13 = r_F26 + MIPS_FP_DOUBLE,
-  r_DF14 = r_F28 + MIPS_FP_DOUBLE,
-  r_DF15 = r_F30 + MIPS_FP_DOUBLE,
+  rDF8 = rF16 + MIPS_FP_DOUBLE,
+  rDF9 = rF18 + MIPS_FP_DOUBLE,
+  rDF10 = rF20 + MIPS_FP_DOUBLE,
+  rDF11 = rF22 + MIPS_FP_DOUBLE,
+  rDF12 = rF24 + MIPS_FP_DOUBLE,
+  rDF13 = rF26 + MIPS_FP_DOUBLE,
+  rDF14 = rF28 + MIPS_FP_DOUBLE,
+  rDF15 = rF30 + MIPS_FP_DOUBLE,
 #endif
-  r_HI = MIPS_EXTRA_REG_OFFSET,
-  r_LO,
-  r_PC,
+  rHI = MIPS_EXTRA_REG_OFFSET,
+  rLO,
+  rPC,
 };
 
-#define rMIPS_SUSPEND r_S0
-#define rMIPS_SELF r_S1
-#define rMIPS_SP r_SP
-#define rMIPS_ARG0 r_ARG0
-#define rMIPS_ARG1 r_ARG1
-#define rMIPS_ARG2 r_ARG2
-#define rMIPS_ARG3 r_ARG3
-#define rMIPS_FARG0 r_FARG0
-#define rMIPS_FARG1 r_FARG1
-#define rMIPS_FARG2 r_FARG2
-#define rMIPS_FARG3 r_FARG3
-#define rMIPS_RET0 r_RESULT0
-#define rMIPS_RET1 r_RESULT1
-#define rMIPS_INVOKE_TGT r_T9
-#define rMIPS_COUNT INVALID_REG
-#define rMIPS_LR r_RA
+const RegStorage rs_rZERO(RegStorage::k32BitSolo, rZERO);
+const RegStorage rs_rAT(RegStorage::k32BitSolo, rAT);
+const RegStorage rs_rV0(RegStorage::k32BitSolo, rV0);
+const RegStorage rs_rV1(RegStorage::k32BitSolo, rV1);
+const RegStorage rs_rA0(RegStorage::k32BitSolo, rA0);
+const RegStorage rs_rA1(RegStorage::k32BitSolo, rA1);
+const RegStorage rs_rA2(RegStorage::k32BitSolo, rA2);
+const RegStorage rs_rA3(RegStorage::k32BitSolo, rA3);
+const RegStorage rs_rT0(RegStorage::k32BitSolo, rT0);
+const RegStorage rs_rT1(RegStorage::k32BitSolo, rT1);
+const RegStorage rs_rT2(RegStorage::k32BitSolo, rT2);
+const RegStorage rs_rT3(RegStorage::k32BitSolo, rT3);
+const RegStorage rs_rT4(RegStorage::k32BitSolo, rT4);
+const RegStorage rs_rT5(RegStorage::k32BitSolo, rT5);
+const RegStorage rs_rT6(RegStorage::k32BitSolo, rT6);
+const RegStorage rs_rT7(RegStorage::k32BitSolo, rT7);
+const RegStorage rs_rS0(RegStorage::k32BitSolo, rS0);
+const RegStorage rs_rS1(RegStorage::k32BitSolo, rS1);
+const RegStorage rs_rS2(RegStorage::k32BitSolo, rS2);
+const RegStorage rs_rS3(RegStorage::k32BitSolo, rS3);
+const RegStorage rs_rS4(RegStorage::k32BitSolo, rS4);
+const RegStorage rs_rS5(RegStorage::k32BitSolo, rS5);
+const RegStorage rs_rS6(RegStorage::k32BitSolo, rS6);
+const RegStorage rs_rS7(RegStorage::k32BitSolo, rS7);
+const RegStorage rs_rT8(RegStorage::k32BitSolo, rT8);
+const RegStorage rs_rT9(RegStorage::k32BitSolo, rT9);
+const RegStorage rs_rK0(RegStorage::k32BitSolo, rK0);
+const RegStorage rs_rK1(RegStorage::k32BitSolo, rK1);
+const RegStorage rs_rGP(RegStorage::k32BitSolo, rGP);
+const RegStorage rs_rSP(RegStorage::k32BitSolo, rSP);
+const RegStorage rs_rFP(RegStorage::k32BitSolo, rFP);
+const RegStorage rs_rRA(RegStorage::k32BitSolo, rRA);
+const RegStorage rs_rF12(RegStorage::k32BitSolo, rF12);
+const RegStorage rs_rF13(RegStorage::k32BitSolo, rF13);
+const RegStorage rs_rF14(RegStorage::k32BitSolo, rF14);
+const RegStorage rs_rF15(RegStorage::k32BitSolo, rF15);
+const RegStorage rs_rF0(RegStorage::k32BitSolo, rF0);
+const RegStorage rs_rF1(RegStorage::k32BitSolo, rF1);
+
+// TODO: reduce/eliminate use of these.
+#define rMIPS_SUSPEND rS0
+#define rs_rMIPS_SUSPEND rs_rS0
+#define rMIPS_SELF rS1
+#define rs_rMIPS_SELF rs_rS1
+#define rMIPS_SP rSP
+#define rs_rMIPS_SP rs_rSP
+#define rMIPS_ARG0 rARG0
+#define rs_rMIPS_ARG0 rs_rARG0
+#define rMIPS_ARG1 rARG1
+#define rs_rMIPS_ARG1 rs_rARG1
+#define rMIPS_ARG2 rARG2
+#define rs_rMIPS_ARG2 rs_rARG2
+#define rMIPS_ARG3 rARG3
+#define rs_rMIPS_ARG3 rs_rARG3
+#define rMIPS_FARG0 rFARG0
+#define rs_rMIPS_FARG0 rs_rFARG0
+#define rMIPS_FARG1 rFARG1
+#define rs_rMIPS_FARG1 rs_rFARG1
+#define rMIPS_FARG2 rFARG2
+#define rs_rMIPS_FARG2 rs_rFARG2
+#define rMIPS_FARG3 rFARG3
+#define rs_MIPS_FARG3 rs_rFARG3
+#define rMIPS_RET0 rRESULT0
+#define rs_MIPS_RET0 rs_rRESULT0
+#define rMIPS_RET1 rRESULT1
+#define rs_rMIPS_RET1 rs_rRESULT1
+#define rMIPS_INVOKE_TGT rT9
+#define rs_rMIPS_INVOKE_TGT rs_rT9
+#define rMIPS_COUNT RegStorage::kInvalidRegVal
 
 // RegisterLocation templates return values (r_V0, or r_V0/r_V1).
 const RegLocation mips_loc_c_return
     {kLocPhysReg, 0, 0, 0, 0, 0, 0, 0, 1, kVectorNotUsed,
-     RegStorage(RegStorage::k32BitSolo, r_V0), INVALID_SREG, INVALID_SREG};
+     RegStorage(RegStorage::k32BitSolo, rV0), INVALID_SREG, INVALID_SREG};
 const RegLocation mips_loc_c_return_wide
     {kLocPhysReg, 1, 0, 0, 0, 0, 0, 0, 1, kVectorNotUsed,
-     RegStorage(RegStorage::k64BitPair, r_V0, r_V1), INVALID_SREG, INVALID_SREG};
+     RegStorage(RegStorage::k64BitPair, rV0, rV1), INVALID_SREG, INVALID_SREG};
 const RegLocation mips_loc_c_return_float
     {kLocPhysReg, 0, 0, 0, 1, 0, 0, 0, 1, kVectorNotUsed,
-     RegStorage(RegStorage::k32BitSolo, r_F0), INVALID_SREG, INVALID_SREG};
+     RegStorage(RegStorage::k32BitSolo, rF0), INVALID_SREG, INVALID_SREG};
 const RegLocation mips_loc_c_return_double
     {kLocPhysReg, 1, 0, 0, 1, 0, 0, 0, 1, kVectorNotUsed,
-     RegStorage(RegStorage::k64BitPair, r_F0, r_F1), INVALID_SREG, INVALID_SREG};
+     RegStorage(RegStorage::k64BitPair, rF0, rF1), INVALID_SREG, INVALID_SREG};
 
 enum MipsShiftEncodings {
   kMipsLsl = 0x0,
diff --git a/compiler/dex/quick/mips/target_mips.cc b/compiler/dex/quick/mips/target_mips.cc
index b7fb2f4..67a44fa 100644
--- a/compiler/dex/quick/mips/target_mips.cc
+++ b/compiler/dex/quick/mips/target_mips.cc
@@ -26,18 +26,18 @@
 
 namespace art {
 
-static int core_regs[] = {r_ZERO, r_AT, r_V0, r_V1, r_A0, r_A1, r_A2, r_A3,
-                          r_T0, r_T1, r_T2, r_T3, r_T4, r_T5, r_T6, r_T7,
-                          r_S0, r_S1, r_S2, r_S3, r_S4, r_S5, r_S6, r_S7, r_T8,
-                          r_T9, r_K0, r_K1, r_GP, r_SP, r_FP, r_RA};
-static int ReservedRegs[] = {r_ZERO, r_AT, r_S0, r_S1, r_K0, r_K1, r_GP, r_SP,
-                             r_RA};
-static int core_temps[] = {r_V0, r_V1, r_A0, r_A1, r_A2, r_A3, r_T0, r_T1, r_T2,
-                           r_T3, r_T4, r_T5, r_T6, r_T7, r_T8};
-static int FpRegs[] = {r_F0, r_F1, r_F2, r_F3, r_F4, r_F5, r_F6, r_F7,
-                       r_F8, r_F9, r_F10, r_F11, r_F12, r_F13, r_F14, r_F15};
-static int fp_temps[] = {r_F0, r_F1, r_F2, r_F3, r_F4, r_F5, r_F6, r_F7,
-                         r_F8, r_F9, r_F10, r_F11, r_F12, r_F13, r_F14, r_F15};
+static int core_regs[] = {rZERO, rAT, rV0, rV1, rA0, rA1, rA2, rA3,
+                          rT0, rT1, rT2, rT3, rT4, rT5, rT6, rT7,
+                          rS0, rS1, rS2, rS3, rS4, rS5, rS6, rS7, rT8,
+                          rT9, rK0, rK1, rGP, rSP, rFP, rRA};
+static int ReservedRegs[] = {rZERO, rAT, rS0, rS1, rK0, rK1, rGP, rSP,
+                             rRA};
+static int core_temps[] = {rV0, rV1, rA0, rA1, rA2, rA3, rT0, rT1, rT2,
+                           rT3, rT4, rT5, rT6, rT7, rT8};
+static int FpRegs[] = {rF0, rF1, rF2, rF3, rF4, rF5, rF6, rF7,
+                       rF8, rF9, rF10, rF11, rF12, rF13, rF14, rF15};
+static int fp_temps[] = {rF0, rF1, rF2, rF3, rF4, rF5, rF6, rF7,
+                         rF8, rF9, rF10, rF11, rF12, rF13, rF14, rF15};
 
 RegLocation MipsMir2Lir::LocCReturn() {
   return mips_loc_c_return;
@@ -56,43 +56,43 @@
 }
 
 // Return a target-dependent special register.
-int MipsMir2Lir::TargetReg(SpecialTargetRegister reg) {
-  int res = INVALID_REG;
+RegStorage MipsMir2Lir::TargetReg(SpecialTargetRegister reg) {
+  int res_reg = RegStorage::kInvalidRegVal;
   switch (reg) {
-    case kSelf: res = rMIPS_SELF; break;
-    case kSuspend: res =  rMIPS_SUSPEND; break;
-    case kLr: res =  rMIPS_LR; break;
-    case kPc: res =  rMIPS_PC; break;
-    case kSp: res =  rMIPS_SP; break;
-    case kArg0: res = rMIPS_ARG0; break;
-    case kArg1: res = rMIPS_ARG1; break;
-    case kArg2: res = rMIPS_ARG2; break;
-    case kArg3: res = rMIPS_ARG3; break;
-    case kFArg0: res = rMIPS_FARG0; break;
-    case kFArg1: res = rMIPS_FARG1; break;
-    case kFArg2: res = rMIPS_FARG2; break;
-    case kFArg3: res = rMIPS_FARG3; break;
-    case kRet0: res = rMIPS_RET0; break;
-    case kRet1: res = rMIPS_RET1; break;
-    case kInvokeTgt: res = rMIPS_INVOKE_TGT; break;
-    case kHiddenArg: res = r_T0; break;
-    case kHiddenFpArg: res = INVALID_REG; break;
-    case kCount: res = rMIPS_COUNT; break;
+    case kSelf: res_reg = rMIPS_SELF; break;
+    case kSuspend: res_reg =  rMIPS_SUSPEND; break;
+    case kLr: res_reg =  rMIPS_LR; break;
+    case kPc: res_reg =  rMIPS_PC; break;
+    case kSp: res_reg =  rMIPS_SP; break;
+    case kArg0: res_reg = rMIPS_ARG0; break;
+    case kArg1: res_reg = rMIPS_ARG1; break;
+    case kArg2: res_reg = rMIPS_ARG2; break;
+    case kArg3: res_reg = rMIPS_ARG3; break;
+    case kFArg0: res_reg = rMIPS_FARG0; break;
+    case kFArg1: res_reg = rMIPS_FARG1; break;
+    case kFArg2: res_reg = rMIPS_FARG2; break;
+    case kFArg3: res_reg = rMIPS_FARG3; break;
+    case kRet0: res_reg = rMIPS_RET0; break;
+    case kRet1: res_reg = rMIPS_RET1; break;
+    case kInvokeTgt: res_reg = rMIPS_INVOKE_TGT; break;
+    case kHiddenArg: res_reg = rT0; break;
+    case kHiddenFpArg: res_reg = RegStorage::kInvalidRegVal; break;
+    case kCount: res_reg = rMIPS_COUNT; break;
   }
-  return res;
+  return RegStorage::Solo32(res_reg);
 }
 
-int MipsMir2Lir::GetArgMappingToPhysicalReg(int arg_num) {
+RegStorage MipsMir2Lir::GetArgMappingToPhysicalReg(int arg_num) {
   // For the 32-bit internal ABI, the first 3 arguments are passed in registers.
   switch (arg_num) {
     case 0:
-      return rMIPS_ARG1;
+      return rs_rMIPS_ARG1;
     case 1:
-      return rMIPS_ARG2;
+      return rs_rMIPS_ARG2;
     case 2:
-      return rMIPS_ARG3;
+      return rs_rMIPS_ARG3;
     default:
-      return INVALID_REG;
+      return RegStorage::InvalidReg();
   }
 }
 
@@ -311,7 +311,7 @@
  */
 
 void MipsMir2Lir::AdjustSpillMask() {
-  core_spill_mask_ |= (1 << r_RA);
+  core_spill_mask_ |= (1 << rRA);
   num_core_spills_++;
 }
 
@@ -325,9 +325,9 @@
   LOG(FATAL) << "No support yet for promoted FP regs";
 }
 
-void MipsMir2Lir::FlushRegWide(int reg1, int reg2) {
-  RegisterInfo* info1 = GetRegInfo(reg1);
-  RegisterInfo* info2 = GetRegInfo(reg2);
+void MipsMir2Lir::FlushRegWide(RegStorage reg) {
+  RegisterInfo* info1 = GetRegInfo(reg.GetLowReg());
+  RegisterInfo* info2 = GetRegInfo(reg.GetHighReg());
   DCHECK(info1 && info2 && info1->pair && info2->pair &&
          (info1->partner == info2->reg) &&
          (info2->partner == info1->reg));
@@ -342,16 +342,18 @@
     if (mir_graph_->SRegToVReg(info2->s_reg) < mir_graph_->SRegToVReg(info1->s_reg))
       info1 = info2;
     int v_reg = mir_graph_->SRegToVReg(info1->s_reg);
-    StoreBaseDispWide(rMIPS_SP, VRegOffset(v_reg), info1->reg, info1->partner);
+    StoreBaseDispWide(rs_rMIPS_SP, VRegOffset(v_reg),
+                      RegStorage(RegStorage::k64BitPair, info1->reg, info1->partner));
   }
 }
 
-void MipsMir2Lir::FlushReg(int reg) {
-  RegisterInfo* info = GetRegInfo(reg);
+void MipsMir2Lir::FlushReg(RegStorage 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(rMIPS_SP, VRegOffset(v_reg), reg, kWord);
+    StoreBaseDisp(rs_rMIPS_SP, VRegOffset(v_reg), reg, kWord);
   }
 }
 
@@ -360,47 +362,51 @@
   return MIPS_FPREG(reg);
 }
 
+bool MipsMir2Lir::IsFpReg(RegStorage reg) {
+  return IsFpReg(reg.IsPair() ? reg.GetLowReg() : reg.GetReg());
+}
+
 /* Clobber all regs that might be used by an external C call */
 void MipsMir2Lir::ClobberCallerSave() {
-  Clobber(r_ZERO);
-  Clobber(r_AT);
-  Clobber(r_V0);
-  Clobber(r_V1);
-  Clobber(r_A0);
-  Clobber(r_A1);
-  Clobber(r_A2);
-  Clobber(r_A3);
-  Clobber(r_T0);
-  Clobber(r_T1);
-  Clobber(r_T2);
-  Clobber(r_T3);
-  Clobber(r_T4);
-  Clobber(r_T5);
-  Clobber(r_T6);
-  Clobber(r_T7);
-  Clobber(r_T8);
-  Clobber(r_T9);
-  Clobber(r_K0);
-  Clobber(r_K1);
-  Clobber(r_GP);
-  Clobber(r_FP);
-  Clobber(r_RA);
-  Clobber(r_F0);
-  Clobber(r_F1);
-  Clobber(r_F2);
-  Clobber(r_F3);
-  Clobber(r_F4);
-  Clobber(r_F5);
-  Clobber(r_F6);
-  Clobber(r_F7);
-  Clobber(r_F8);
-  Clobber(r_F9);
-  Clobber(r_F10);
-  Clobber(r_F11);
-  Clobber(r_F12);
-  Clobber(r_F13);
-  Clobber(r_F14);
-  Clobber(r_F15);
+  Clobber(rZERO);
+  Clobber(rAT);
+  Clobber(rV0);
+  Clobber(rV1);
+  Clobber(rA0);
+  Clobber(rA1);
+  Clobber(rA2);
+  Clobber(rA3);
+  Clobber(rT0);
+  Clobber(rT1);
+  Clobber(rT2);
+  Clobber(rT3);
+  Clobber(rT4);
+  Clobber(rT5);
+  Clobber(rT6);
+  Clobber(rT7);
+  Clobber(rT8);
+  Clobber(rT9);
+  Clobber(rK0);
+  Clobber(rK1);
+  Clobber(rGP);
+  Clobber(rFP);
+  Clobber(rRA);
+  Clobber(rF0);
+  Clobber(rF1);
+  Clobber(rF2);
+  Clobber(rF3);
+  Clobber(rF4);
+  Clobber(rF5);
+  Clobber(rF6);
+  Clobber(rF7);
+  Clobber(rF8);
+  Clobber(rF9);
+  Clobber(rF10);
+  Clobber(rF11);
+  Clobber(rF12);
+  Clobber(rF13);
+  Clobber(rF14);
+  Clobber(rF15);
 }
 
 RegLocation MipsMir2Lir::GetReturnWideAlt() {
@@ -443,17 +449,15 @@
   int low_reg;
 
   if (((reg_class == kAnyReg) && fp_hint) || (reg_class == kFPReg)) {
-    low_reg = AllocTempDouble();
-    high_reg = low_reg + 1;
-    return RegStorage(RegStorage::k64BitPair, low_reg, high_reg);
+    return AllocTempDouble();
   }
 
-  low_reg = AllocTemp();
-  high_reg = AllocTemp();
+  low_reg = AllocTemp().GetReg();
+  high_reg = AllocTemp().GetReg();
   return RegStorage(RegStorage::k64BitPair, low_reg, high_reg);
 }
 
-int MipsMir2Lir::AllocTypedTemp(bool fp_hint, int reg_class) {
+RegStorage MipsMir2Lir::AllocTypedTemp(bool fp_hint, int reg_class) {
   if (((reg_class == kAnyReg) && fp_hint) || (reg_class == kFPReg)) {
     return AllocTempFloat();
 }
@@ -494,11 +498,14 @@
 }
 
 void MipsMir2Lir::FreeRegLocTemps(RegLocation rl_keep, RegLocation rl_free) {
-  if ((rl_free.reg.GetReg() != rl_keep.reg.GetReg()) && (rl_free.reg.GetReg() != rl_keep.reg.GetHighReg()) &&
-    (rl_free.reg.GetHighReg() != rl_keep.reg.GetReg()) && (rl_free.reg.GetHighReg() != rl_keep.reg.GetHighReg())) {
-    // No overlap, free both
-    FreeTemp(rl_free.reg.GetReg());
-    FreeTemp(rl_free.reg.GetHighReg());
+  DCHECK(rl_keep.wide);
+  DCHECK(rl_free.wide);
+  if ((rl_free.reg.GetLowReg() != rl_keep.reg.GetLowReg()) &&
+      (rl_free.reg.GetLowReg() != rl_keep.reg.GetHighReg()) &&
+      (rl_free.reg.GetHighReg() != rl_keep.reg.GetLowReg()) &&
+      (rl_free.reg.GetHighReg() != rl_keep.reg.GetHighReg())) {
+    // No overlap, free.
+    FreeTemp(rl_free.reg);
   }
 }
 /*
@@ -507,14 +514,14 @@
  * ensure that all branch instructions can be restarted if
  * there is a trap in the shadow.  Allocate a temp register.
  */
-int MipsMir2Lir::LoadHelper(ThreadOffset offset) {
-  LoadWordDisp(rMIPS_SELF, offset.Int32Value(), r_T9);
-  return r_T9;
+RegStorage MipsMir2Lir::LoadHelper(ThreadOffset offset) {
+  LoadWordDisp(rs_rMIPS_SELF, offset.Int32Value(), rs_rT9);
+  return rs_rT9;
 }
 
 LIR* MipsMir2Lir::CheckSuspendUsingLoad() {
-  int tmp = AllocTemp();
-  LoadWordDisp(rMIPS_SELF, Thread::ThreadSuspendTriggerOffset().Int32Value(), tmp);
+  RegStorage tmp = AllocTemp();
+  LoadWordDisp(rs_rMIPS_SELF, Thread::ThreadSuspendTriggerOffset().Int32Value(), tmp);
   LIR *inst = LoadWordDisp(tmp, 0, tmp);
   FreeTemp(tmp);
   return inst;
@@ -526,11 +533,11 @@
   }
   uint32_t mask = core_spill_mask_;
   int offset = num_core_spills_ * 4;
-  OpRegImm(kOpSub, rMIPS_SP, offset);
+  OpRegImm(kOpSub, rs_rSP, offset);
   for (int reg = 0; mask; mask >>= 1, reg++) {
     if (mask & 0x1) {
       offset -= 4;
-      StoreWordDisp(rMIPS_SP, offset, reg);
+      StoreWordDisp(rs_rMIPS_SP, offset, RegStorage::Solo32(reg));
     }
   }
 }
@@ -544,10 +551,10 @@
   for (int reg = 0; mask; mask >>= 1, reg++) {
     if (mask & 0x1) {
       offset -= 4;
-      LoadWordDisp(rMIPS_SP, offset, reg);
+      LoadWordDisp(rs_rMIPS_SP, offset, RegStorage::Solo32(reg));
     }
   }
-  OpRegImm(kOpAdd, rMIPS_SP, frame_size_);
+  OpRegImm(kOpAdd, rs_rSP, frame_size_);
 }
 
 bool MipsMir2Lir::IsUnconditionalBranch(LIR* lir) {
diff --git a/compiler/dex/quick/mips/utility_mips.cc b/compiler/dex/quick/mips/utility_mips.cc
index 21c971c..4f31341 100644
--- a/compiler/dex/quick/mips/utility_mips.cc
+++ b/compiler/dex/quick/mips/utility_mips.cc
@@ -21,29 +21,29 @@
 namespace art {
 
 /* This file contains codegen for the MIPS32 ISA. */
-LIR* MipsMir2Lir::OpFpRegCopy(int r_dest, int r_src) {
+LIR* MipsMir2Lir::OpFpRegCopy(RegStorage r_dest, RegStorage r_src) {
   int opcode;
   /* must be both DOUBLE or both not DOUBLE */
-  DCHECK_EQ(MIPS_DOUBLEREG(r_dest), MIPS_DOUBLEREG(r_src));
-  if (MIPS_DOUBLEREG(r_dest)) {
+  DCHECK_EQ(MIPS_DOUBLEREG(r_dest.GetReg()), MIPS_DOUBLEREG(r_src.GetReg()));
+  if (MIPS_DOUBLEREG(r_dest.GetReg())) {
     opcode = kMipsFmovd;
   } else {
-    if (MIPS_SINGLEREG(r_dest)) {
-      if (MIPS_SINGLEREG(r_src)) {
+    if (MIPS_SINGLEREG(r_dest.GetReg())) {
+      if (MIPS_SINGLEREG(r_src.GetReg())) {
         opcode = kMipsFmovs;
       } else {
         /* note the operands are swapped for the mtc1 instr */
-        int t_opnd = r_src;
+        RegStorage t_opnd = r_src;
         r_src = r_dest;
         r_dest = t_opnd;
         opcode = kMipsMtc1;
       }
     } else {
-      DCHECK(MIPS_SINGLEREG(r_src));
+      DCHECK(MIPS_SINGLEREG(r_src.GetReg()));
       opcode = kMipsMfc1;
     }
   }
-  LIR* res = RawLIR(current_dalvik_offset_, opcode, r_src, r_dest);
+  LIR* res = RawLIR(current_dalvik_offset_, opcode, r_src.GetReg(), r_dest.GetReg());
   if (!(cu_->disable_opt & (1 << kSafeOptimizations)) && r_dest == r_src) {
     res->flags.is_nop = true;
   }
@@ -75,31 +75,31 @@
  * 1) r_dest is freshly returned from AllocTemp or
  * 2) The codegen is under fixed register usage
  */
-LIR* MipsMir2Lir::LoadConstantNoClobber(int r_dest, int value) {
+LIR* MipsMir2Lir::LoadConstantNoClobber(RegStorage r_dest, int value) {
   LIR *res;
 
-  int r_dest_save = r_dest;
-  int is_fp_reg = MIPS_FPREG(r_dest);
+  RegStorage r_dest_save = r_dest;
+  int is_fp_reg = MIPS_FPREG(r_dest.GetReg());
   if (is_fp_reg) {
-    DCHECK(MIPS_SINGLEREG(r_dest));
+    DCHECK(MIPS_SINGLEREG(r_dest.GetReg()));
     r_dest = AllocTemp();
   }
 
   /* See if the value can be constructed cheaply */
   if (value == 0) {
-    res = NewLIR2(kMipsMove, r_dest, r_ZERO);
+    res = NewLIR2(kMipsMove, r_dest.GetReg(), rZERO);
   } else if ((value > 0) && (value <= 65535)) {
-    res = NewLIR3(kMipsOri, r_dest, r_ZERO, value);
+    res = NewLIR3(kMipsOri, r_dest.GetReg(), rZERO, value);
   } else if ((value < 0) && (value >= -32768)) {
-    res = NewLIR3(kMipsAddiu, r_dest, r_ZERO, value);
+    res = NewLIR3(kMipsAddiu, r_dest.GetReg(), rZERO, value);
   } else {
-    res = NewLIR2(kMipsLui, r_dest, value >> 16);
+    res = NewLIR2(kMipsLui, r_dest.GetReg(), value >> 16);
     if (value & 0xffff)
-      NewLIR3(kMipsOri, r_dest, r_dest, value);
+      NewLIR3(kMipsOri, r_dest.GetReg(), r_dest.GetReg(), value);
   }
 
   if (is_fp_reg) {
-    NewLIR2(kMipsMtc1, r_dest, r_dest_save);
+    NewLIR2(kMipsMtc1, r_dest.GetReg(), r_dest_save.GetReg());
     FreeTemp(r_dest);
   }
 
@@ -112,23 +112,22 @@
   return res;
 }
 
-LIR* MipsMir2Lir::OpReg(OpKind op, int r_dest_src) {
+LIR* MipsMir2Lir::OpReg(OpKind op, RegStorage r_dest_src) {
   MipsOpCode opcode = kMipsNop;
   switch (op) {
     case kOpBlx:
       opcode = kMipsJalr;
       break;
     case kOpBx:
-      return NewLIR1(kMipsJr, r_dest_src);
+      return NewLIR1(kMipsJr, r_dest_src.GetReg());
       break;
     default:
       LOG(FATAL) << "Bad case in OpReg";
   }
-  return NewLIR2(opcode, r_RA, r_dest_src);
+  return NewLIR2(opcode, rRA, r_dest_src.GetReg());
 }
 
-LIR* MipsMir2Lir::OpRegImm(OpKind op, int r_dest_src1,
-          int value) {
+LIR* MipsMir2Lir::OpRegImm(OpKind op, RegStorage r_dest_src1, int value) {
   LIR *res;
   bool neg = (value < 0);
   int abs_value = (neg) ? -value : value;
@@ -146,19 +145,19 @@
       break;
   }
   if (short_form) {
-    res = NewLIR2(opcode, r_dest_src1, abs_value);
+    res = NewLIR2(opcode, r_dest_src1.GetReg(), abs_value);
   } else {
-    int r_scratch = AllocTemp();
+    RegStorage r_scratch = AllocTemp();
     res = LoadConstant(r_scratch, value);
     if (op == kOpCmp)
-      NewLIR2(opcode, r_dest_src1, r_scratch);
+      NewLIR2(opcode, r_dest_src1.GetReg(), r_scratch.GetReg());
     else
-      NewLIR3(opcode, r_dest_src1, r_dest_src1, r_scratch);
+      NewLIR3(opcode, r_dest_src1.GetReg(), r_dest_src1.GetReg(), r_scratch.GetReg());
   }
   return res;
 }
 
-LIR* MipsMir2Lir::OpRegRegReg(OpKind op, int r_dest, int r_src1, int r_src2) {
+LIR* MipsMir2Lir::OpRegRegReg(OpKind op, RegStorage r_dest, RegStorage r_src1, RegStorage r_src2) {
   MipsOpCode opcode = kMipsNop;
   switch (op) {
     case kOpAdd:
@@ -196,10 +195,10 @@
       LOG(FATAL) << "bad case in OpRegRegReg";
       break;
   }
-  return NewLIR3(opcode, r_dest, r_src1, r_src2);
+  return NewLIR3(opcode, r_dest.GetReg(), r_src1.GetReg(), r_src2.GetReg());
 }
 
-LIR* MipsMir2Lir::OpRegRegImm(OpKind op, int r_dest, int r_src1, int value) {
+LIR* MipsMir2Lir::OpRegRegImm(OpKind op, RegStorage r_dest, RegStorage r_src1, int value) {
   LIR *res;
   MipsOpCode opcode = kMipsNop;
   bool short_form = true;
@@ -268,21 +267,21 @@
   }
 
   if (short_form) {
-    res = NewLIR3(opcode, r_dest, r_src1, value);
+    res = NewLIR3(opcode, r_dest.GetReg(), r_src1.GetReg(), value);
   } else {
     if (r_dest != r_src1) {
       res = LoadConstant(r_dest, value);
-      NewLIR3(opcode, r_dest, r_src1, r_dest);
+      NewLIR3(opcode, r_dest.GetReg(), r_src1.GetReg(), r_dest.GetReg());
     } else {
-      int r_scratch = AllocTemp();
+      RegStorage r_scratch = AllocTemp();
       res = LoadConstant(r_scratch, value);
-      NewLIR3(opcode, r_dest, r_src1, r_scratch);
+      NewLIR3(opcode, r_dest.GetReg(), r_src1.GetReg(), r_scratch.GetReg());
     }
   }
   return res;
 }
 
-LIR* MipsMir2Lir::OpRegReg(OpKind op, int r_dest_src1, int r_src2) {
+LIR* MipsMir2Lir::OpRegReg(OpKind op, RegStorage r_dest_src1, RegStorage r_src2) {
   MipsOpCode opcode = kMipsNop;
   LIR *res;
   switch (op) {
@@ -290,9 +289,9 @@
       opcode = kMipsMove;
       break;
     case kOpMvn:
-      return NewLIR3(kMipsNor, r_dest_src1, r_src2, r_ZERO);
+      return NewLIR3(kMipsNor, r_dest_src1.GetReg(), r_src2.GetReg(), rZERO);
     case kOpNeg:
-      return NewLIR3(kMipsSubu, r_dest_src1, r_ZERO, r_src2);
+      return NewLIR3(kMipsSubu, r_dest_src1.GetReg(), rZERO, r_src2.GetReg());
     case kOpAdd:
     case kOpAnd:
     case kOpMul:
@@ -302,7 +301,7 @@
       return OpRegRegReg(op, r_dest_src1, r_dest_src1, r_src2);
     case kOp2Byte:
 #if __mips_isa_rev >= 2
-      res = NewLIR2(kMipsSeb, r_dest_src1, r_src2);
+      res = NewLIR2(kMipsSeb, r_dest_src1.GetReg(), r_src2.GetReg());
 #else
       res = OpRegRegImm(kOpLsl, r_dest_src1, r_src2, 24);
       OpRegRegImm(kOpAsr, r_dest_src1, r_dest_src1, 24);
@@ -310,53 +309,54 @@
       return res;
     case kOp2Short:
 #if __mips_isa_rev >= 2
-      res = NewLIR2(kMipsSeh, r_dest_src1, r_src2);
+      res = NewLIR2(kMipsSeh, r_dest_src1.GetReg(), r_src2.GetReg());
 #else
       res = OpRegRegImm(kOpLsl, r_dest_src1, r_src2, 16);
       OpRegRegImm(kOpAsr, r_dest_src1, r_dest_src1, 16);
 #endif
       return res;
     case kOp2Char:
-       return NewLIR3(kMipsAndi, r_dest_src1, r_src2, 0xFFFF);
+       return NewLIR3(kMipsAndi, r_dest_src1.GetReg(), r_src2.GetReg(), 0xFFFF);
     default:
       LOG(FATAL) << "Bad case in OpRegReg";
       break;
   }
-  return NewLIR2(opcode, r_dest_src1, r_src2);
+  return NewLIR2(opcode, r_dest_src1.GetReg(), r_src2.GetReg());
 }
 
-LIR* MipsMir2Lir::OpMovRegMem(int r_dest, int r_base, int offset, MoveType move_type) {
+LIR* MipsMir2Lir::OpMovRegMem(RegStorage r_dest, RegStorage r_base, int offset,
+                              MoveType move_type) {
   UNIMPLEMENTED(FATAL);
   return nullptr;
 }
 
-LIR* MipsMir2Lir::OpMovMemReg(int r_base, int offset, int r_src, MoveType move_type) {
+LIR* MipsMir2Lir::OpMovMemReg(RegStorage r_base, int offset, RegStorage r_src, MoveType move_type) {
   UNIMPLEMENTED(FATAL);
   return nullptr;
 }
 
-LIR* MipsMir2Lir::OpCondRegReg(OpKind op, ConditionCode cc, int r_dest, int r_src) {
+LIR* MipsMir2Lir::OpCondRegReg(OpKind op, ConditionCode cc, RegStorage r_dest, RegStorage r_src) {
   LOG(FATAL) << "Unexpected use of OpCondRegReg for MIPS";
   return NULL;
 }
 
-LIR* MipsMir2Lir::LoadConstantWide(int r_dest_lo, int r_dest_hi, int64_t value) {
+LIR* MipsMir2Lir::LoadConstantWide(RegStorage r_dest, int64_t value) {
   LIR *res;
-  res = LoadConstantNoClobber(r_dest_lo, Low32Bits(value));
-  LoadConstantNoClobber(r_dest_hi, High32Bits(value));
+  res = LoadConstantNoClobber(r_dest.GetLow(), Low32Bits(value));
+  LoadConstantNoClobber(r_dest.GetHigh(), High32Bits(value));
   return res;
 }
 
 /* Load value from base + scaled index. */
-LIR* MipsMir2Lir::LoadBaseIndexed(int rBase, int r_index, int r_dest,
+LIR* MipsMir2Lir::LoadBaseIndexed(RegStorage r_base, RegStorage r_index, RegStorage r_dest,
                                   int scale, OpSize size) {
   LIR *first = NULL;
   LIR *res;
   MipsOpCode opcode = kMipsNop;
-  int t_reg = AllocTemp();
+  RegStorage t_reg = AllocTemp();
 
-  if (MIPS_FPREG(r_dest)) {
-    DCHECK(MIPS_SINGLEREG(r_dest));
+  if (MIPS_FPREG(r_dest.GetReg())) {
+    DCHECK(MIPS_SINGLEREG(r_dest.GetReg()));
     DCHECK((size == kWord) || (size == kSingle));
     size = kSingle;
   } else {
@@ -365,10 +365,10 @@
   }
 
   if (!scale) {
-    first = NewLIR3(kMipsAddu, t_reg , rBase, r_index);
+    first = NewLIR3(kMipsAddu, t_reg.GetReg() , r_base.GetReg(), r_index.GetReg());
   } else {
     first = OpRegRegImm(kOpLsl, t_reg, r_index, scale);
-    NewLIR3(kMipsAddu, t_reg , rBase, t_reg);
+    NewLIR3(kMipsAddu, t_reg.GetReg() , r_base.GetReg(), t_reg.GetReg());
   }
 
   switch (size) {
@@ -394,21 +394,20 @@
       LOG(FATAL) << "Bad case in LoadBaseIndexed";
   }
 
-  res = NewLIR3(opcode, r_dest, 0, t_reg);
+  res = NewLIR3(opcode, r_dest.GetReg(), 0, t_reg.GetReg());
   FreeTemp(t_reg);
   return (first) ? first : res;
 }
 
 /* store value base base + scaled index. */
-LIR* MipsMir2Lir::StoreBaseIndexed(int rBase, int r_index, int r_src,
+LIR* MipsMir2Lir::StoreBaseIndexed(RegStorage r_base, RegStorage r_index, RegStorage r_src,
                                    int scale, OpSize size) {
   LIR *first = NULL;
   MipsOpCode opcode = kMipsNop;
-  int r_new_index = r_index;
-  int t_reg = AllocTemp();
+  RegStorage t_reg = AllocTemp();
 
-  if (MIPS_FPREG(r_src)) {
-    DCHECK(MIPS_SINGLEREG(r_src));
+  if (MIPS_FPREG(r_src.GetReg())) {
+    DCHECK(MIPS_SINGLEREG(r_src.GetReg()));
     DCHECK((size == kWord) || (size == kSingle));
     size = kSingle;
   } else {
@@ -417,10 +416,10 @@
   }
 
   if (!scale) {
-    first = NewLIR3(kMipsAddu, t_reg , rBase, r_index);
+    first = NewLIR3(kMipsAddu, t_reg.GetReg() , r_base.GetReg(), r_index.GetReg());
   } else {
     first = OpRegRegImm(kOpLsl, t_reg, r_index, scale);
-    NewLIR3(kMipsAddu, t_reg , rBase, t_reg);
+    NewLIR3(kMipsAddu, t_reg.GetReg() , r_base.GetReg(), t_reg.GetReg());
   }
 
   switch (size) {
@@ -441,13 +440,13 @@
     default:
       LOG(FATAL) << "Bad case in StoreBaseIndexed";
   }
-  NewLIR3(opcode, r_src, 0, t_reg);
-  FreeTemp(r_new_index);
+  NewLIR3(opcode, r_src.GetReg(), 0, t_reg.GetReg());
   return first;
 }
 
-LIR* MipsMir2Lir::LoadBaseDispBody(int rBase, int displacement, int r_dest,
-                                   int r_dest_hi, OpSize size, int s_reg) {
+// FIXME: don't split r_dest into 2 containers.
+LIR* MipsMir2Lir::LoadBaseDispBody(RegStorage r_base, int displacement, RegStorage r_dest,
+                                   RegStorage r_dest_hi, OpSize size, int s_reg) {
 /*
  * Load value from base + displacement.  Optionally perform null check
  * on base (which must have an associated s_reg and MIR).  If not
@@ -468,15 +467,16 @@
     case kDouble:
       pair = true;
       opcode = kMipsLw;
-      if (MIPS_FPREG(r_dest)) {
+      if (MIPS_FPREG(r_dest.GetReg())) {
         opcode = kMipsFlwc1;
-        if (MIPS_DOUBLEREG(r_dest)) {
-          r_dest = r_dest - MIPS_FP_DOUBLE;
+        if (MIPS_DOUBLEREG(r_dest.GetReg())) {
+          // TODO: rework to use k64BitSolo
+          r_dest.SetReg(r_dest.GetReg() - MIPS_FP_DOUBLE);
         } else {
-          DCHECK(MIPS_FPREG(r_dest_hi));
-          DCHECK(r_dest == (r_dest_hi - 1));
+          DCHECK(MIPS_FPREG(r_dest_hi.GetReg()));
+          DCHECK_EQ(r_dest.GetReg(), r_dest_hi.GetReg() - 1);
         }
-        r_dest_hi = r_dest + 1;
+        r_dest_hi.SetReg(r_dest.GetReg() + 1);
       }
       short_form = IS_SIMM16_2WORD(displacement);
       DCHECK_EQ((displacement & 0x3), 0);
@@ -484,9 +484,9 @@
     case kWord:
     case kSingle:
       opcode = kMipsLw;
-      if (MIPS_FPREG(r_dest)) {
+      if (MIPS_FPREG(r_dest.GetReg())) {
         opcode = kMipsFlwc1;
-        DCHECK(MIPS_SINGLEREG(r_dest));
+        DCHECK(MIPS_SINGLEREG(r_dest.GetReg()));
       }
       DCHECK_EQ((displacement & 0x3), 0);
       break;
@@ -510,30 +510,28 @@
 
   if (short_form) {
     if (!pair) {
-      load = res = NewLIR3(opcode, r_dest, displacement, rBase);
+      load = res = NewLIR3(opcode, r_dest.GetReg(), displacement, r_base.GetReg());
     } else {
-      load = res = NewLIR3(opcode, r_dest,
-                           displacement + LOWORD_OFFSET, rBase);
-      load2 = NewLIR3(opcode, r_dest_hi,
-                      displacement + HIWORD_OFFSET, rBase);
+      load = res = NewLIR3(opcode, r_dest.GetReg(), displacement + LOWORD_OFFSET, r_base.GetReg());
+      load2 = NewLIR3(opcode, r_dest_hi.GetReg(), displacement + HIWORD_OFFSET, r_base.GetReg());
     }
   } else {
     if (pair) {
-      int r_tmp = AllocTemp();
-      res = OpRegRegImm(kOpAdd, r_tmp, rBase, displacement);
-      load = NewLIR3(opcode, r_dest, LOWORD_OFFSET, r_tmp);
-      load2 = NewLIR3(opcode, r_dest_hi, HIWORD_OFFSET, r_tmp);
+      RegStorage r_tmp = AllocTemp();
+      res = OpRegRegImm(kOpAdd, r_tmp, r_base, displacement);
+      load = NewLIR3(opcode, r_dest.GetReg(), LOWORD_OFFSET, r_tmp.GetReg());
+      load2 = NewLIR3(opcode, r_dest_hi.GetReg(), HIWORD_OFFSET, r_tmp.GetReg());
       FreeTemp(r_tmp);
     } else {
-      int r_tmp = (rBase == r_dest) ? AllocTemp() : r_dest;
-      res = OpRegRegImm(kOpAdd, r_tmp, rBase, displacement);
-      load = NewLIR3(opcode, r_dest, 0, r_tmp);
+      RegStorage r_tmp = (r_base == r_dest) ? AllocTemp() : r_dest;
+      res = OpRegRegImm(kOpAdd, r_tmp, r_base, displacement);
+      load = NewLIR3(opcode, r_dest.GetReg(), 0, r_tmp.GetReg());
       if (r_tmp != r_dest)
         FreeTemp(r_tmp);
     }
   }
 
-  if (rBase == rMIPS_SP) {
+  if (r_base == rs_rMIPS_SP) {
     AnnotateDalvikRegAccess(load, (displacement + (pair ? LOWORD_OFFSET : 0)) >> 2,
                             true /* is_load */, pair /* is64bit */);
     if (pair) {
@@ -544,19 +542,19 @@
   return load;
 }
 
-LIR* MipsMir2Lir::LoadBaseDisp(int rBase, int displacement, int r_dest,
+LIR* MipsMir2Lir::LoadBaseDisp(RegStorage r_base, int displacement, RegStorage r_dest,
                                OpSize size, int s_reg) {
-  return LoadBaseDispBody(rBase, displacement, r_dest, -1,
-                          size, s_reg);
+  return LoadBaseDispBody(r_base, displacement, r_dest, RegStorage::InvalidReg(), size,
+                          s_reg);
 }
 
-LIR* MipsMir2Lir::LoadBaseDispWide(int rBase, int displacement,
-                                   int r_dest_lo, int r_dest_hi, int s_reg) {
-  return LoadBaseDispBody(rBase, displacement, r_dest_lo, r_dest_hi, kLong, s_reg);
+LIR* MipsMir2Lir::LoadBaseDispWide(RegStorage r_base, int displacement, RegStorage r_dest,
+                                   int s_reg) {
+  return LoadBaseDispBody(r_base, displacement, r_dest.GetLow(), r_dest.GetHigh(), kLong, s_reg);
 }
 
-LIR* MipsMir2Lir::StoreBaseDispBody(int rBase, int displacement,
-                                    int r_src, int r_src_hi, OpSize size) {
+LIR* MipsMir2Lir::StoreBaseDispBody(RegStorage r_base, int displacement,
+                                    RegStorage r_src, RegStorage r_src_hi, OpSize size) {
   LIR *res;
   LIR *store = NULL;
   LIR *store2 = NULL;
@@ -569,15 +567,15 @@
     case kDouble:
       pair = true;
       opcode = kMipsSw;
-      if (MIPS_FPREG(r_src)) {
+      if (MIPS_FPREG(r_src.GetReg())) {
         opcode = kMipsFswc1;
-        if (MIPS_DOUBLEREG(r_src)) {
-          r_src = r_src - MIPS_FP_DOUBLE;
+        if (MIPS_DOUBLEREG(r_src.GetReg())) {
+          r_src.SetReg(r_src.GetReg() - MIPS_FP_DOUBLE);
         } else {
-          DCHECK(MIPS_FPREG(r_src_hi));
-          DCHECK_EQ(r_src, (r_src_hi - 1));
+          DCHECK(MIPS_FPREG(r_src_hi.GetReg()));
+          DCHECK_EQ(r_src.GetReg(), (r_src_hi.GetReg() - 1));
         }
-        r_src_hi = r_src + 1;
+        r_src_hi.SetReg(r_src.GetReg() + 1);
       }
       short_form = IS_SIMM16_2WORD(displacement);
       DCHECK_EQ((displacement & 0x3), 0);
@@ -585,9 +583,9 @@
     case kWord:
     case kSingle:
       opcode = kMipsSw;
-      if (MIPS_FPREG(r_src)) {
+      if (MIPS_FPREG(r_src.GetReg())) {
         opcode = kMipsFswc1;
-        DCHECK(MIPS_SINGLEREG(r_src));
+        DCHECK(MIPS_SINGLEREG(r_src.GetReg()));
       }
       DCHECK_EQ((displacement & 0x3), 0);
       break;
@@ -601,31 +599,29 @@
       opcode = kMipsSb;
       break;
     default:
-      LOG(FATAL) << "Bad case in StoreBaseIndexedBody";
+      LOG(FATAL) << "Bad case in StoreBaseDispBody";
   }
 
   if (short_form) {
     if (!pair) {
-      store = res = NewLIR3(opcode, r_src, displacement, rBase);
+      store = res = NewLIR3(opcode, r_src.GetReg(), displacement, r_base.GetReg());
     } else {
-      store = res = NewLIR3(opcode, r_src, displacement + LOWORD_OFFSET,
-                            rBase);
-      store2 = NewLIR3(opcode, r_src_hi, displacement + HIWORD_OFFSET,
-                       rBase);
+      store = res = NewLIR3(opcode, r_src.GetReg(), displacement + LOWORD_OFFSET, r_base.GetReg());
+      store2 = NewLIR3(opcode, r_src_hi.GetReg(), displacement + HIWORD_OFFSET, r_base.GetReg());
     }
   } else {
-    int r_scratch = AllocTemp();
-    res = OpRegRegImm(kOpAdd, r_scratch, rBase, displacement);
+    RegStorage r_scratch = AllocTemp();
+    res = OpRegRegImm(kOpAdd, r_scratch, r_base, displacement);
     if (!pair) {
-      store =  NewLIR3(opcode, r_src, 0, r_scratch);
+      store =  NewLIR3(opcode, r_src.GetReg(), 0, r_scratch.GetReg());
     } else {
-      store =  NewLIR3(opcode, r_src, LOWORD_OFFSET, r_scratch);
-      store2 = NewLIR3(opcode, r_src_hi, HIWORD_OFFSET, r_scratch);
+      store =  NewLIR3(opcode, r_src.GetReg(), LOWORD_OFFSET, r_scratch.GetReg());
+      store2 = NewLIR3(opcode, r_src_hi.GetReg(), HIWORD_OFFSET, r_scratch.GetReg());
     }
     FreeTemp(r_scratch);
   }
 
-  if (rBase == rMIPS_SP) {
+  if (r_base == rs_rMIPS_SP) {
     AnnotateDalvikRegAccess(store, (displacement + (pair ? LOWORD_OFFSET : 0)) >> 2,
                             false /* is_load */, pair /* is64bit */);
     if (pair) {
@@ -637,14 +633,13 @@
   return res;
 }
 
-LIR* MipsMir2Lir::StoreBaseDisp(int rBase, int displacement, int r_src,
+LIR* MipsMir2Lir::StoreBaseDisp(RegStorage r_base, int displacement, RegStorage r_src,
                                 OpSize size) {
-  return StoreBaseDispBody(rBase, displacement, r_src, -1, size);
+  return StoreBaseDispBody(r_base, displacement, r_src, RegStorage::InvalidReg(), size);
 }
 
-LIR* MipsMir2Lir::StoreBaseDispWide(int rBase, int displacement,
-                                    int r_src_lo, int r_src_hi) {
-  return StoreBaseDispBody(rBase, displacement, r_src_lo, r_src_hi, kLong);
+LIR* MipsMir2Lir::StoreBaseDispWide(RegStorage r_base, int displacement, RegStorage r_src) {
+  return StoreBaseDispBody(r_base, displacement, r_src.GetLow(), r_src.GetHigh(), kLong);
 }
 
 LIR* MipsMir2Lir::OpThreadMem(OpKind op, ThreadOffset thread_offset) {
@@ -652,25 +647,26 @@
   return NULL;
 }
 
-LIR* MipsMir2Lir::OpMem(OpKind op, int rBase, int disp) {
+LIR* MipsMir2Lir::OpMem(OpKind op, RegStorage r_base, int disp) {
   LOG(FATAL) << "Unexpected use of OpMem for MIPS";
   return NULL;
 }
 
-LIR* MipsMir2Lir::StoreBaseIndexedDisp(int rBase, int r_index, int scale, int displacement,
-                                       int r_src, int r_src_hi, OpSize size, int s_reg) {
+LIR* MipsMir2Lir::StoreBaseIndexedDisp(RegStorage r_base, RegStorage r_index, int scale,
+                                       int displacement, RegStorage r_src, RegStorage r_src_hi,
+                                       OpSize size, int s_reg) {
   LOG(FATAL) << "Unexpected use of StoreBaseIndexedDisp for MIPS";
   return NULL;
 }
 
-LIR* MipsMir2Lir::OpRegMem(OpKind op, int r_dest, int rBase,
-              int offset) {
+LIR* MipsMir2Lir::OpRegMem(OpKind op, RegStorage r_dest, RegStorage r_base, int offset) {
   LOG(FATAL) << "Unexpected use of OpRegMem for MIPS";
   return NULL;
 }
 
-LIR* MipsMir2Lir::LoadBaseIndexedDisp(int rBase, int r_index, int scale, int displacement,
-                                      int r_dest, int r_dest_hi, OpSize size, int s_reg) {
+LIR* MipsMir2Lir::LoadBaseIndexedDisp(RegStorage r_base, RegStorage r_index, int scale,
+                                      int displacement, RegStorage r_dest, RegStorage r_dest_hi,
+                                      OpSize size, int s_reg) {
   LOG(FATAL) << "Unexpected use of LoadBaseIndexedDisp for MIPS";
   return NULL;
 }
diff --git a/compiler/dex/quick/mir_to_lir.cc b/compiler/dex/quick/mir_to_lir.cc
index 657c3d9..e81a037 100644
--- a/compiler/dex/quick/mir_to_lir.cc
+++ b/compiler/dex/quick/mir_to_lir.cc
@@ -24,20 +24,23 @@
 namespace art {
 
 void Mir2Lir::LockArg(int in_position, bool wide) {
-  int reg_arg_low = GetArgMappingToPhysicalReg(in_position);
-  int reg_arg_high = wide ? GetArgMappingToPhysicalReg(in_position + 1) : INVALID_REG;
+  RegStorage reg_arg_low = GetArgMappingToPhysicalReg(in_position);
+  RegStorage reg_arg_high = wide ? GetArgMappingToPhysicalReg(in_position + 1) :
+      RegStorage::InvalidReg();
 
-  if (reg_arg_low != INVALID_REG) {
+  if (reg_arg_low.Valid()) {
     LockTemp(reg_arg_low);
   }
-  if (reg_arg_high != INVALID_REG && reg_arg_low != reg_arg_high) {
+  if (reg_arg_high.Valid() && reg_arg_low != reg_arg_high) {
     LockTemp(reg_arg_high);
   }
 }
 
-int Mir2Lir::LoadArg(int in_position, bool wide) {
-  int reg_arg_low = GetArgMappingToPhysicalReg(in_position);
-  int reg_arg_high = wide ? GetArgMappingToPhysicalReg(in_position + 1) : INVALID_REG;
+// TODO: needs revisit for 64-bit.
+RegStorage Mir2Lir::LoadArg(int in_position, bool wide) {
+  RegStorage reg_arg_low = GetArgMappingToPhysicalReg(in_position);
+  RegStorage reg_arg_high = wide ? GetArgMappingToPhysicalReg(in_position + 1) :
+      RegStorage::InvalidReg();
 
   int offset = StackVisitor::GetOutVROffset(in_position);
   if (cu_->instruction_set == kX86) {
@@ -50,13 +53,13 @@
   }
 
   // If the VR is wide and there is no register for high part, we need to load it.
-  if (wide && reg_arg_high == INVALID_REG) {
+  if (wide && !reg_arg_high.Valid()) {
     // If the low part is not in a reg, we allocate a pair. Otherwise, we just load to high reg.
-    if (reg_arg_low == INVALID_REG) {
+    if (!reg_arg_low.Valid()) {
       RegStorage new_regs = AllocTypedTempWide(false, kAnyReg);
-      reg_arg_low = new_regs.GetReg();
-      reg_arg_high = new_regs.GetHighReg();
-      LoadBaseDispWide(TargetReg(kSp), offset, reg_arg_low, reg_arg_high, INVALID_SREG);
+      reg_arg_low = new_regs.GetLow();
+      reg_arg_high = new_regs.GetHigh();
+      LoadBaseDispWide(TargetReg(kSp), offset, new_regs, INVALID_SREG);
     } else {
       reg_arg_high = AllocTemp();
       int offset_high = offset + sizeof(uint32_t);
@@ -65,14 +68,13 @@
   }
 
   // If the low part is not in a register yet, we need to load it.
-  if (reg_arg_low == INVALID_REG) {
+  if (!reg_arg_low.Valid()) {
     reg_arg_low = AllocTemp();
     LoadWordDisp(TargetReg(kSp), offset, reg_arg_low);
   }
 
   if (wide) {
-    // TODO: replace w/ RegStorage.
-    return ENCODE_REG_PAIR(reg_arg_low, reg_arg_high);
+    return RegStorage::MakeRegPair(reg_arg_low, reg_arg_high);
   } else {
     return reg_arg_low;
   }
@@ -90,27 +92,27 @@
   }
 
   if (!rl_dest.wide) {
-    int reg = GetArgMappingToPhysicalReg(in_position);
-    if (reg != INVALID_REG) {
-      OpRegCopy(rl_dest.reg.GetReg(), reg);
+    RegStorage reg = GetArgMappingToPhysicalReg(in_position);
+    if (reg.Valid()) {
+      OpRegCopy(rl_dest.reg, reg);
     } else {
-      LoadWordDisp(TargetReg(kSp), offset, rl_dest.reg.GetReg());
+      LoadWordDisp(TargetReg(kSp), offset, rl_dest.reg);
     }
   } else {
-    int reg_arg_low = GetArgMappingToPhysicalReg(in_position);
-    int reg_arg_high = GetArgMappingToPhysicalReg(in_position + 1);
+    RegStorage reg_arg_low = GetArgMappingToPhysicalReg(in_position);
+    RegStorage reg_arg_high = GetArgMappingToPhysicalReg(in_position + 1);
 
-    if (reg_arg_low != INVALID_REG && reg_arg_high != INVALID_REG) {
-      OpRegCopyWide(rl_dest.reg.GetReg(), rl_dest.reg.GetHighReg(), reg_arg_low, reg_arg_high);
-    } else if (reg_arg_low != INVALID_REG && reg_arg_high == INVALID_REG) {
-      OpRegCopy(rl_dest.reg.GetReg(), reg_arg_low);
+    if (reg_arg_low.Valid() && reg_arg_high.Valid()) {
+      OpRegCopyWide(rl_dest.reg, RegStorage::MakeRegPair(reg_arg_low, reg_arg_high));
+    } else if (reg_arg_low.Valid() && !reg_arg_high.Valid()) {
+      OpRegCopy(rl_dest.reg, reg_arg_low);
       int offset_high = offset + sizeof(uint32_t);
-      LoadWordDisp(TargetReg(kSp), offset_high, rl_dest.reg.GetHighReg());
-    } else if (reg_arg_low == INVALID_REG && reg_arg_high != INVALID_REG) {
-      OpRegCopy(rl_dest.reg.GetHighReg(), reg_arg_high);
-      LoadWordDisp(TargetReg(kSp), offset, rl_dest.reg.GetReg());
+      LoadWordDisp(TargetReg(kSp), offset_high, rl_dest.reg.GetHigh());
+    } else if (!reg_arg_low.Valid() && reg_arg_high.Valid()) {
+      OpRegCopy(rl_dest.reg.GetHigh(), reg_arg_high);
+      LoadWordDisp(TargetReg(kSp), offset, rl_dest.reg.GetLow());
     } else {
-      LoadBaseDispWide(TargetReg(kSp), offset, rl_dest.reg.GetReg(), rl_dest.reg.GetHighReg(), INVALID_SREG);
+      LoadBaseDispWide(TargetReg(kSp), offset, rl_dest.reg, INVALID_SREG);
     }
   }
 }
@@ -131,11 +133,11 @@
   GenPrintLabel(mir);
   LockArg(data.object_arg);
   RegLocation rl_dest = wide ? GetReturnWide(double_or_float) : GetReturn(double_or_float);
-  int reg_obj = LoadArg(data.object_arg);
+  RegStorage reg_obj = LoadArg(data.object_arg);
   if (wide) {
-    LoadBaseDispWide(reg_obj, data.field_offset, rl_dest.reg.GetReg(), rl_dest.reg.GetHighReg(), INVALID_SREG);
+    LoadBaseDispWide(reg_obj, data.field_offset, rl_dest.reg, INVALID_SREG);
   } else {
-    LoadBaseDisp(reg_obj, data.field_offset, rl_dest.reg.GetReg(), kWord, INVALID_SREG);
+    LoadWordDisp(reg_obj, data.field_offset, rl_dest.reg);
   }
   if (data.is_volatile) {
     // Without context sensitive analysis, we must issue the most conservative barriers.
@@ -160,16 +162,14 @@
   GenPrintLabel(mir);
   LockArg(data.object_arg);
   LockArg(data.src_arg, wide);
-  int reg_obj = LoadArg(data.object_arg);
-  int reg_src = LoadArg(data.src_arg, wide);
+  RegStorage reg_obj = LoadArg(data.object_arg);
+  RegStorage reg_src = LoadArg(data.src_arg, wide);
   if (data.is_volatile) {
     // There might have been a store before this volatile one so insert StoreStore barrier.
     GenMemBarrier(kStoreStore);
   }
   if (wide) {
-    int low_reg, high_reg;
-    DECODE_REG_PAIR(reg_src, low_reg, high_reg);
-    StoreBaseDispWide(reg_obj, data.field_offset, low_reg, high_reg);
+    StoreBaseDispWide(reg_obj, data.field_offset, reg_src);
   } else {
     StoreBaseDisp(reg_obj, data.field_offset, reg_src, kWord);
   }
@@ -216,7 +216,7 @@
       successful = true;
       RegLocation rl_dest = GetReturn(cu_->shorty[0] == 'F');
       GenPrintLabel(mir);
-      LoadConstant(rl_dest.reg.GetReg(), static_cast<int>(special.d.data));
+      LoadConstant(rl_dest.reg, static_cast<int>(special.d.data));
       return_mir = bb->GetNextUnconditionalMir(mir_graph_, mir);
       break;
     }
@@ -384,19 +384,19 @@
     case Instruction::CONST_4:
     case Instruction::CONST_16:
       rl_result = EvalLoc(rl_dest, kAnyReg, true);
-      LoadConstantNoClobber(rl_result.reg.GetReg(), vB);
+      LoadConstantNoClobber(rl_result.reg, vB);
       StoreValue(rl_dest, rl_result);
       if (vB == 0) {
-        Workaround7250540(rl_dest, rl_result.reg.GetReg());
+        Workaround7250540(rl_dest, rl_result.reg);
       }
       break;
 
     case Instruction::CONST_HIGH16:
       rl_result = EvalLoc(rl_dest, kAnyReg, true);
-      LoadConstantNoClobber(rl_result.reg.GetReg(), vB << 16);
+      LoadConstantNoClobber(rl_result.reg, vB << 16);
       StoreValue(rl_dest, rl_result);
       if (vB == 0) {
-        Workaround7250540(rl_dest, rl_result.reg.GetReg());
+        Workaround7250540(rl_dest, rl_result.reg);
       }
       break;
 
@@ -411,8 +411,7 @@
 
     case Instruction::CONST_WIDE_HIGH16:
       rl_result = EvalLoc(rl_dest, kAnyReg, true);
-      LoadConstantWide(rl_result.reg.GetReg(), rl_result.reg.GetHighReg(),
-                           static_cast<int64_t>(vB) << 48);
+      LoadConstantWide(rl_result.reg, static_cast<int64_t>(vB) << 48);
       StoreValueWide(rl_dest, rl_result);
       break;
 
@@ -444,9 +443,9 @@
       int len_offset;
       len_offset = mirror::Array::LengthOffset().Int32Value();
       rl_src[0] = LoadValue(rl_src[0], kCoreReg);
-      GenNullCheck(rl_src[0].reg.GetReg(), opt_flags);
+      GenNullCheck(rl_src[0].reg, opt_flags);
       rl_result = EvalLoc(rl_dest, kCoreReg, true);
-      LoadWordDisp(rl_src[0].reg.GetReg(), len_offset, rl_result.reg.GetReg());
+      LoadWordDisp(rl_src[0].reg, len_offset, rl_result.reg);
       StoreValue(rl_dest, rl_result);
       break;
 
diff --git a/compiler/dex/quick/mir_to_lir.h b/compiler/dex/quick/mir_to_lir.h
index 51fe8f1..1c8f6dc 100644
--- a/compiler/dex/quick/mir_to_lir.h
+++ b/compiler/dex/quick/mir_to_lir.h
@@ -440,9 +440,11 @@
     LIR* InsertCaseLabel(DexOffset vaddr, int keyVal);
     void MarkPackedCaseLabels(Mir2Lir::SwitchTable* tab_rec);
     void MarkSparseCaseLabels(Mir2Lir::SwitchTable* tab_rec);
+    // Handle bookkeeping to convert a wide RegLocation to a narow RegLocation.  No code generated.
+    RegLocation NarrowRegLoc(RegLocation loc);
 
     // Shared by all targets - implemented in local_optimizations.cc
-    void ConvertMemOpIntoMove(LIR* orig_lir, int dest, int src);
+    void ConvertMemOpIntoMove(LIR* orig_lir, RegStorage dest, RegStorage src);
     void ApplyLoadStoreElimination(LIR* head_lir, LIR* tail_lir);
     void ApplyLoadHoisting(LIR* head_lir, LIR* tail_lir);
     void ApplyLocalOptimizations(LIR* head_lir, LIR* tail_lir);
@@ -461,28 +463,36 @@
     void Clobber(int reg) {
       ClobberBody(GetRegInfo(reg));
     }
+    void Clobber(RegStorage reg);
     void ClobberSRegBody(RegisterInfo* p, int num_regs, int s_reg);
     void ClobberSReg(int s_reg);
     int SRegToPMap(int s_reg);
-    void RecordCorePromotion(int reg, int s_reg);
-    int AllocPreservedCoreReg(int s_reg);
-    void RecordFpPromotion(int reg, int s_reg);
-    int AllocPreservedSingle(int s_reg);
-    int AllocPreservedDouble(int s_reg);
-    int AllocTempBody(RegisterInfo* p, int num_regs, int* next_temp, bool required);
-    virtual int AllocTempDouble();
-    int AllocFreeTemp();
-    int AllocTemp();
-    int AllocTempFloat();
+    void RecordCorePromotion(RegStorage reg, int s_reg);
+    RegStorage AllocPreservedCoreReg(int s_reg);
+    void RecordFpPromotion(RegStorage reg, int s_reg);
+    RegStorage AllocPreservedSingle(int s_reg);
+    RegStorage AllocPreservedDouble(int s_reg);
+    RegStorage AllocTempBody(RegisterInfo* p, int num_regs, int* next_temp, bool required);
+    virtual RegStorage AllocTempDouble();
+    RegStorage AllocFreeTemp();
+    RegStorage AllocTemp();
+    RegStorage AllocTempFloat();
     RegisterInfo* AllocLiveBody(RegisterInfo* p, int num_regs, int s_reg);
     RegisterInfo* AllocLive(int s_reg, int reg_class);
     void FreeTemp(int reg);
+    void FreeTemp(RegStorage reg);
     RegisterInfo* IsLive(int reg);
+    RegisterInfo* IsLive(RegStorage reg);
     RegisterInfo* IsTemp(int reg);
+    RegisterInfo* IsTemp(RegStorage reg);
     RegisterInfo* IsPromoted(int reg);
+    RegisterInfo* IsPromoted(RegStorage reg);
     bool IsDirty(int reg);
+    bool IsDirty(RegStorage reg);
     void LockTemp(int reg);
+    void LockTemp(RegStorage reg);
     void ResetDef(int reg);
+    void ResetDef(RegStorage reg);
     void NullifyRange(LIR *start, LIR *finish, int s_reg1, int s_reg2);
     void MarkDef(RegLocation rl, LIR *start, LIR *finish);
     void MarkDefWide(RegLocation rl, LIR *start, LIR *finish);
@@ -494,15 +504,19 @@
     void FlushSpecificReg(RegisterInfo* info);
     void FlushAllRegsBody(RegisterInfo* info, int num_regs);
     void FlushAllRegs();
-    bool RegClassMatches(int reg_class, int reg);
-    void MarkLive(int reg, int s_reg);
+    bool RegClassMatches(int reg_class, RegStorage reg);
+    void MarkLive(RegStorage reg, int s_reg);
     void MarkTemp(int reg);
+    void MarkTemp(RegStorage reg);
     void UnmarkTemp(int reg);
+    void UnmarkTemp(RegStorage reg);
     void MarkPair(int low_reg, int high_reg);
     void MarkClean(RegLocation loc);
     void MarkDirty(RegLocation loc);
     void MarkInUse(int reg);
+    void MarkInUse(RegStorage reg);
     void CopyRegInfo(int new_reg, int old_reg);
+    void CopyRegInfo(RegStorage new_reg, RegStorage old_reg);
     bool CheckCorePoolSanity();
     RegLocation UpdateLoc(RegLocation loc);
     virtual RegLocation UpdateLocWide(RegLocation loc);
@@ -546,14 +560,12 @@
     void HandleSlowPaths();
     void GenBarrier();
     LIR* GenCheck(ConditionCode c_code, ThrowKind kind);
-    LIR* GenImmedCheck(ConditionCode c_code, int reg, int imm_val,
-                       ThrowKind kind);
-    LIR* GenNullCheck(int m_reg, int opt_flags);
     void MarkPossibleNullPointerException(int opt_flags);
     void MarkPossibleStackOverflowException();
-    void ForceImplicitNullCheck(int reg, int opt_flags);
-    LIR* GenRegRegCheck(ConditionCode c_code, int reg1, int reg2,
-                        ThrowKind kind);
+    void ForceImplicitNullCheck(RegStorage reg, int opt_flags);
+    LIR* GenImmedCheck(ConditionCode c_code, RegStorage reg, int imm_val, ThrowKind kind);
+    LIR* GenNullCheck(RegStorage m_reg, int opt_flags);
+    LIR* GenRegRegCheck(ConditionCode c_code, RegStorage reg1, RegStorage reg2, ThrowKind kind);
     void GenCompareAndBranch(Instruction::Code opcode, RegLocation rl_src1,
                              RegLocation rl_src2, LIR* taken, LIR* fall_through);
     void GenCompareZeroAndBranch(Instruction::Code opcode, RegLocation rl_src,
@@ -579,10 +591,8 @@
     void GenConstString(uint32_t string_idx, RegLocation rl_dest);
     void GenNewInstance(uint32_t type_idx, RegLocation rl_dest);
     void GenThrow(RegLocation rl_src);
-    void GenInstanceof(uint32_t type_idx, RegLocation rl_dest,
-                       RegLocation rl_src);
-    void GenCheckCast(uint32_t insn_idx, uint32_t type_idx,
-                      RegLocation rl_src);
+    void GenInstanceof(uint32_t type_idx, RegLocation rl_dest, RegLocation rl_src);
+    void GenCheckCast(uint32_t insn_idx, uint32_t type_idx, RegLocation rl_src);
     void GenLong3Addr(OpKind first_op, OpKind second_op, RegLocation rl_dest,
                       RegLocation rl_src1, RegLocation rl_src2);
     void GenShiftOpLong(Instruction::Code opcode, RegLocation rl_dest,
@@ -602,10 +612,11 @@
                        RegLocation rl_src1, RegLocation rl_src2);
 
     // Shared by all targets - implemented in gen_invoke.cc.
-    int CallHelperSetup(ThreadOffset helper_offset);
-    LIR* CallHelper(int r_tgt, ThreadOffset helper_offset, bool safepoint_pc, bool use_link = true);
+    LIR* CallHelper(RegStorage r_tgt, ThreadOffset helper_offset, bool safepoint_pc,
+                    bool use_link = true);
+    RegStorage CallHelperSetup(ThreadOffset helper_offset);
     void CallRuntimeHelperImm(ThreadOffset helper_offset, int arg0, bool safepoint_pc);
-    void CallRuntimeHelperReg(ThreadOffset helper_offset, int arg0, bool safepoint_pc);
+    void CallRuntimeHelperReg(ThreadOffset helper_offset, RegStorage arg0, bool safepoint_pc);
     void CallRuntimeHelperRegLocation(ThreadOffset helper_offset, RegLocation arg0,
                                       bool safepoint_pc);
     void CallRuntimeHelperImmImm(ThreadOffset helper_offset, int arg0, int arg1,
@@ -614,21 +625,21 @@
                                          RegLocation arg1, bool safepoint_pc);
     void CallRuntimeHelperRegLocationImm(ThreadOffset helper_offset, RegLocation arg0,
                                          int arg1, bool safepoint_pc);
-    void CallRuntimeHelperImmReg(ThreadOffset helper_offset, int arg0, int arg1,
+    void CallRuntimeHelperImmReg(ThreadOffset helper_offset, int arg0, RegStorage arg1,
                                  bool safepoint_pc);
-    void CallRuntimeHelperRegImm(ThreadOffset helper_offset, int arg0, int arg1,
+    void CallRuntimeHelperRegImm(ThreadOffset helper_offset, RegStorage arg0, int arg1,
                                  bool safepoint_pc);
     void CallRuntimeHelperImmMethod(ThreadOffset helper_offset, int arg0,
                                     bool safepoint_pc);
-    void CallRuntimeHelperRegMethod(ThreadOffset helper_offset, int arg0, bool safepoint_pc);
-    void CallRuntimeHelperRegMethodRegLocation(ThreadOffset helper_offset, int arg0,
+    void CallRuntimeHelperRegMethod(ThreadOffset helper_offset, RegStorage arg0, bool safepoint_pc);
+    void CallRuntimeHelperRegMethodRegLocation(ThreadOffset helper_offset, RegStorage arg0,
                                                RegLocation arg2, bool safepoint_pc);
     void CallRuntimeHelperRegLocationRegLocation(ThreadOffset helper_offset,
                                                  RegLocation arg0, RegLocation arg1,
                                                  bool safepoint_pc);
-    void CallRuntimeHelperRegReg(ThreadOffset helper_offset, int arg0, int arg1,
+    void CallRuntimeHelperRegReg(ThreadOffset helper_offset, RegStorage arg0, RegStorage arg1,
                                  bool safepoint_pc);
-    void CallRuntimeHelperRegRegImm(ThreadOffset helper_offset, int arg0, int arg1,
+    void CallRuntimeHelperRegRegImm(ThreadOffset helper_offset, RegStorage arg0, RegStorage arg1,
                                     int arg2, bool safepoint_pc);
     void CallRuntimeHelperImmMethodRegLocation(ThreadOffset helper_offset, int arg0,
                                                RegLocation arg2, bool safepoint_pc);
@@ -698,16 +709,16 @@
 
     // Shared by all targets - implemented in gen_loadstore.cc.
     RegLocation LoadCurrMethod();
-    void LoadCurrMethodDirect(int r_tgt);
-    LIR* LoadConstant(int r_dest, int value);
-    LIR* LoadWordDisp(int rBase, int displacement, int r_dest);
+    void LoadCurrMethodDirect(RegStorage r_tgt);
+    LIR* LoadConstant(RegStorage r_dest, int value);
+    LIR* LoadWordDisp(RegStorage r_base, int displacement, RegStorage r_dest);
     RegLocation LoadValue(RegLocation rl_src, RegisterClass op_kind);
     RegLocation LoadValueWide(RegLocation rl_src, RegisterClass op_kind);
-    void LoadValueDirect(RegLocation rl_src, int r_dest);
-    void LoadValueDirectFixed(RegLocation rl_src, int r_dest);
-    void LoadValueDirectWide(RegLocation rl_src, int reg_lo, int reg_hi);
-    void LoadValueDirectWideFixed(RegLocation rl_src, int reg_lo, int reg_hi);
-    LIR* StoreWordDisp(int rBase, int displacement, int r_src);
+    void LoadValueDirect(RegLocation rl_src, RegStorage r_dest);
+    void LoadValueDirectFixed(RegLocation rl_src, RegStorage r_dest);
+    void LoadValueDirectWide(RegLocation rl_src, RegStorage r_dest);
+    void LoadValueDirectWideFixed(RegLocation rl_src, RegStorage r_dest);
+    LIR* StoreWordDisp(RegStorage r_base, int displacement, RegStorage r_src);
 
     /**
      * @brief Used to do the final store in the destination as per bytecode semantics.
@@ -794,49 +805,58 @@
      * @param check_value The immediate to compare to.
      * @returns The branch instruction that was generated.
      */
-    virtual LIR* OpCmpMemImmBranch(ConditionCode cond, int temp_reg, int base_reg,
+    virtual LIR* OpCmpMemImmBranch(ConditionCode cond, RegStorage temp_reg, RegStorage base_reg,
                                    int offset, int check_value, LIR* target);
 
     // Required for target - codegen helpers.
     virtual bool SmallLiteralDivRem(Instruction::Code dalvik_opcode, bool is_div,
                                     RegLocation rl_src, RegLocation rl_dest, int lit) = 0;
-    virtual int LoadHelper(ThreadOffset offset) = 0;
     virtual LIR* CheckSuspendUsingLoad() = 0;
-    virtual LIR* LoadBaseDisp(int rBase, int displacement, int r_dest, OpSize size, int s_reg) = 0;
-    virtual LIR* LoadBaseDispWide(int rBase, int displacement, int r_dest_lo, int r_dest_hi,
+    virtual RegStorage LoadHelper(ThreadOffset offset) = 0;
+    virtual LIR* LoadBaseDisp(RegStorage r_base, int displacement, RegStorage r_dest, OpSize size,
+                              int s_reg) = 0;
+    virtual LIR* LoadBaseDispWide(RegStorage r_base, int displacement, RegStorage r_dest,
                                   int s_reg) = 0;
-    virtual LIR* LoadBaseIndexed(int rBase, int r_index, int r_dest, int scale, OpSize size) = 0;
-    virtual LIR* LoadBaseIndexedDisp(int rBase, int r_index, int scale, int displacement,
-                                     int r_dest, int r_dest_hi, OpSize size, int s_reg) = 0;
-    virtual LIR* LoadConstantNoClobber(int r_dest, int value) = 0;
-    virtual LIR* LoadConstantWide(int r_dest_lo, int r_dest_hi, int64_t value) = 0;
-    virtual LIR* StoreBaseDisp(int rBase, int displacement, int r_src, OpSize size) = 0;
-    virtual LIR* StoreBaseDispWide(int rBase, int displacement, int r_src_lo, int r_src_hi) = 0;
-    virtual LIR* StoreBaseIndexed(int rBase, int r_index, int r_src, int scale, OpSize size) = 0;
-    virtual LIR* StoreBaseIndexedDisp(int rBase, int r_index, int scale, int displacement,
-                                      int r_src, int r_src_hi, OpSize size, int s_reg) = 0;
-    virtual void MarkGCCard(int val_reg, int tgt_addr_reg) = 0;
+    virtual LIR* LoadBaseIndexed(RegStorage r_base, RegStorage r_index, RegStorage r_dest,
+                                 int scale, OpSize size) = 0;
+    virtual LIR* LoadBaseIndexedDisp(RegStorage r_base, RegStorage r_index, int scale,
+                                     int displacement, RegStorage r_dest, RegStorage r_dest_hi,
+                                     OpSize size, int s_reg) = 0;
+    virtual LIR* LoadConstantNoClobber(RegStorage r_dest, int value) = 0;
+    virtual LIR* LoadConstantWide(RegStorage r_dest, int64_t value) = 0;
+    virtual LIR* StoreBaseDisp(RegStorage r_base, int displacement, RegStorage r_src,
+                               OpSize size) = 0;
+    virtual LIR* StoreBaseDispWide(RegStorage r_base, int displacement, RegStorage r_src) = 0;
+    virtual LIR* StoreBaseIndexed(RegStorage r_base, RegStorage r_index, RegStorage r_src,
+                                  int scale, OpSize size) = 0;
+    virtual LIR* StoreBaseIndexedDisp(RegStorage r_base, RegStorage r_index, int scale,
+                                      int displacement, RegStorage r_src, RegStorage r_src_hi,
+                                      OpSize size, int s_reg) = 0;
+    virtual void MarkGCCard(RegStorage val_reg, RegStorage tgt_addr_reg) = 0;
 
     // Required for target - register utilities.
     virtual bool IsFpReg(int reg) = 0;
+    virtual bool IsFpReg(RegStorage reg) = 0;
     virtual bool SameRegType(int reg1, int reg2) = 0;
-    virtual int AllocTypedTemp(bool fp_hint, int reg_class) = 0;
+    virtual RegStorage AllocTypedTemp(bool fp_hint, int reg_class) = 0;
     virtual RegStorage AllocTypedTempWide(bool fp_hint, int reg_class) = 0;
+    // TODO: elminate S2d.
     virtual int S2d(int low_reg, int high_reg) = 0;
-    virtual int TargetReg(SpecialTargetRegister reg) = 0;
-    virtual int GetArgMappingToPhysicalReg(int arg_num) = 0;
+    virtual RegStorage TargetReg(SpecialTargetRegister reg) = 0;
+    virtual RegStorage GetArgMappingToPhysicalReg(int arg_num) = 0;
     virtual RegLocation GetReturnAlt() = 0;
     virtual RegLocation GetReturnWideAlt() = 0;
     virtual RegLocation LocCReturn() = 0;
     virtual RegLocation LocCReturnDouble() = 0;
     virtual RegLocation LocCReturnFloat() = 0;
     virtual RegLocation LocCReturnWide() = 0;
+    // TODO: use to reduce/eliminate xx_FPREG() macro use.
     virtual uint32_t FpRegMask() = 0;
     virtual uint64_t GetRegMaskCommon(int reg) = 0;
     virtual void AdjustSpillMask() = 0;
     virtual void ClobberCallerSave() = 0;
-    virtual void FlushReg(int reg) = 0;
-    virtual void FlushRegWide(int reg1, int reg2) = 0;
+    virtual void FlushReg(RegStorage reg) = 0;
+    virtual void FlushRegWide(RegStorage reg) = 0;
     virtual void FreeCallTemps() = 0;
     virtual void FreeRegLocTemps(RegLocation rl_keep, RegLocation rl_free) = 0;
     virtual void LockCallTemps() = 0;
@@ -893,20 +913,17 @@
     virtual bool GenInlinedPeek(CallInfo* info, OpSize size) = 0;
     virtual bool GenInlinedPoke(CallInfo* info, OpSize size) = 0;
     virtual void GenNegLong(RegLocation rl_dest, RegLocation rl_src) = 0;
-    virtual void GenOrLong(Instruction::Code,
-                           RegLocation rl_dest, RegLocation rl_src1,
+    virtual void GenOrLong(Instruction::Code, RegLocation rl_dest, RegLocation rl_src1,
                            RegLocation rl_src2) = 0;
-    virtual void GenSubLong(Instruction::Code,
-                            RegLocation rl_dest, RegLocation rl_src1,
+    virtual void GenSubLong(Instruction::Code, RegLocation rl_dest, RegLocation rl_src1,
                             RegLocation rl_src2) = 0;
-    virtual void GenXorLong(Instruction::Code,
-                            RegLocation rl_dest, RegLocation rl_src1,
+    virtual void GenXorLong(Instruction::Code, RegLocation rl_dest, RegLocation rl_src1,
                             RegLocation rl_src2) = 0;
-    virtual LIR* GenRegMemCheck(ConditionCode c_code, int reg1, int base,
+    virtual LIR* GenRegMemCheck(ConditionCode c_code, RegStorage reg1, RegStorage base,
                                 int offset, ThrowKind kind) = 0;
-    virtual RegLocation GenDivRem(RegLocation rl_dest, int reg_lo, int reg_hi,
+    virtual RegLocation GenDivRem(RegLocation rl_dest, RegStorage reg_lo, RegStorage reg_hi,
                                   bool is_div) = 0;
-    virtual RegLocation GenDivRemLit(RegLocation rl_dest, int reg_lo, int lit,
+    virtual RegLocation GenDivRemLit(RegLocation rl_dest, RegStorage reg_lo, int lit,
                                      bool is_div) = 0;
     /*
      * @brief Generate an integer div or rem operation by a literal.
@@ -925,10 +942,9 @@
      * @param lit Divisor.
      * @param is_div 'true' if this is a division, 'false' for a remainder.
      */
-    virtual RegLocation GenDivRemLit(RegLocation rl_dest, RegLocation rl_src1,
-                                     int lit, bool is_div) = 0;
-    virtual void GenCmpLong(RegLocation rl_dest, RegLocation rl_src1,
-                            RegLocation rl_src2) = 0;
+    virtual RegLocation GenDivRemLit(RegLocation rl_dest, RegLocation rl_src1, int lit,
+                                     bool is_div) = 0;
+    virtual void GenCmpLong(RegLocation rl_dest, RegLocation rl_src1, RegLocation rl_src2) = 0;
 
     /**
      * @brief Used for generating code that throws ArithmeticException if both registers are zero.
@@ -936,15 +952,12 @@
      * @param reg_lo The register holding the lower 32-bits.
      * @param reg_hi The register holding the upper 32-bits.
      */
-    virtual void GenDivZeroCheck(int reg_lo, int reg_hi) = 0;
+    virtual void GenDivZeroCheck(RegStorage reg) = 0;
 
-    virtual void GenEntrySequence(RegLocation* ArgLocs,
-                                  RegLocation rl_method) = 0;
+    virtual void GenEntrySequence(RegLocation* ArgLocs, RegLocation rl_method) = 0;
     virtual void GenExitSequence() = 0;
-    virtual void GenFillArrayData(DexOffset table_offset,
-                                  RegLocation rl_src) = 0;
-    virtual void GenFusedFPCmpBranch(BasicBlock* bb, MIR* mir, bool gt_bias,
-                                     bool is_double) = 0;
+    virtual void GenFillArrayData(DexOffset table_offset, RegLocation rl_src) = 0;
+    virtual void GenFusedFPCmpBranch(BasicBlock* bb, MIR* mir, bool gt_bias, bool is_double) = 0;
     virtual void GenFusedLongCmpBranch(BasicBlock* bb, MIR* mir) = 0;
 
     /**
@@ -965,40 +978,37 @@
     virtual void GenMemBarrier(MemBarrierKind barrier_kind) = 0;
 
     virtual void GenMoveException(RegLocation rl_dest) = 0;
-    virtual void GenMultiplyByTwoBitMultiplier(RegLocation rl_src,
-                                               RegLocation rl_result, int lit, int first_bit,
-                                               int second_bit) = 0;
+    virtual void GenMultiplyByTwoBitMultiplier(RegLocation rl_src, RegLocation rl_result, int lit,
+                                               int first_bit, int second_bit) = 0;
     virtual void GenNegDouble(RegLocation rl_dest, RegLocation rl_src) = 0;
     virtual void GenNegFloat(RegLocation rl_dest, RegLocation rl_src) = 0;
-    virtual void GenPackedSwitch(MIR* mir, DexOffset table_offset,
-                                 RegLocation rl_src) = 0;
-    virtual void GenSparseSwitch(MIR* mir, DexOffset table_offset,
-                                 RegLocation rl_src) = 0;
+    virtual void GenPackedSwitch(MIR* mir, DexOffset table_offset, RegLocation rl_src) = 0;
+    virtual void GenSparseSwitch(MIR* mir, DexOffset table_offset, RegLocation rl_src) = 0;
     virtual void GenArrayGet(int opt_flags, OpSize size, RegLocation rl_array,
                              RegLocation rl_index, RegLocation rl_dest, int scale) = 0;
     virtual void GenArrayPut(int opt_flags, OpSize size, RegLocation rl_array,
                              RegLocation rl_index, RegLocation rl_src, int scale,
                              bool card_mark) = 0;
-    virtual void GenShiftImmOpLong(Instruction::Code opcode,
-                                   RegLocation rl_dest, RegLocation rl_src1,
-                                   RegLocation rl_shift) = 0;
+    virtual void GenShiftImmOpLong(Instruction::Code opcode, RegLocation rl_dest,
+                                   RegLocation rl_src1, RegLocation rl_shift) = 0;
 
     // Required for target - single operation generators.
     virtual LIR* OpUnconditionalBranch(LIR* target) = 0;
-    virtual LIR* OpCmpBranch(ConditionCode cond, int src1, int src2, LIR* target) = 0;
-    virtual LIR* OpCmpImmBranch(ConditionCode cond, int reg, int check_value, LIR* target) = 0;
+    virtual LIR* OpCmpBranch(ConditionCode cond, RegStorage src1, RegStorage src2, LIR* target) = 0;
+    virtual LIR* OpCmpImmBranch(ConditionCode cond, RegStorage reg, int check_value,
+                                LIR* target) = 0;
     virtual LIR* OpCondBranch(ConditionCode cc, LIR* target) = 0;
-    virtual LIR* OpDecAndBranch(ConditionCode c_code, int reg, LIR* target) = 0;
-    virtual LIR* OpFpRegCopy(int r_dest, int r_src) = 0;
+    virtual LIR* OpDecAndBranch(ConditionCode c_code, RegStorage reg, LIR* target) = 0;
+    virtual LIR* OpFpRegCopy(RegStorage r_dest, RegStorage r_src) = 0;
     virtual LIR* OpIT(ConditionCode cond, const char* guide) = 0;
-    virtual LIR* OpMem(OpKind op, int rBase, int disp) = 0;
-    virtual LIR* OpPcRelLoad(int reg, LIR* target) = 0;
-    virtual LIR* OpReg(OpKind op, int r_dest_src) = 0;
-    virtual LIR* OpRegCopy(int r_dest, int r_src) = 0;
-    virtual LIR* OpRegCopyNoInsert(int r_dest, int r_src) = 0;
-    virtual LIR* OpRegImm(OpKind op, int r_dest_src1, int value) = 0;
-    virtual LIR* OpRegMem(OpKind op, int r_dest, int rBase, int offset) = 0;
-    virtual LIR* OpRegReg(OpKind op, int r_dest_src1, int r_src2) = 0;
+    virtual LIR* OpMem(OpKind op, RegStorage r_base, int disp) = 0;
+    virtual LIR* OpPcRelLoad(RegStorage reg, LIR* target) = 0;
+    virtual LIR* OpReg(OpKind op, RegStorage r_dest_src) = 0;
+    virtual LIR* OpRegCopy(RegStorage r_dest, RegStorage r_src) = 0;
+    virtual LIR* OpRegCopyNoInsert(RegStorage r_dest, RegStorage r_src) = 0;
+    virtual LIR* OpRegImm(OpKind op, RegStorage r_dest_src1, int value) = 0;
+    virtual LIR* OpRegMem(OpKind op, RegStorage r_dest, RegStorage r_base, int offset) = 0;
+    virtual LIR* OpRegReg(OpKind op, RegStorage r_dest_src1, RegStorage r_src2) = 0;
 
     /**
      * @brief Used to generate an LIR that does a load from mem to reg.
@@ -1008,7 +1018,8 @@
      * @param move_type Specification on the move desired (size, alignment, register kind).
      * @return Returns the generate move LIR.
      */
-    virtual LIR* OpMovRegMem(int r_dest, int r_base, int offset, MoveType move_type) = 0;
+    virtual LIR* OpMovRegMem(RegStorage r_dest, RegStorage r_base, int offset,
+                             MoveType move_type) = 0;
 
     /**
      * @brief Used to generate an LIR that does a store from reg to mem.
@@ -1019,7 +1030,8 @@
      * @param is_aligned Whether the memory location is known to be aligned.
      * @return Returns the generate move LIR.
      */
-    virtual LIR* OpMovMemReg(int r_base, int offset, int r_src, MoveType move_type) = 0;
+    virtual LIR* OpMovMemReg(RegStorage r_base, int offset, RegStorage r_src,
+                             MoveType move_type) = 0;
 
     /**
      * @brief Used for generating a conditional register to register operation.
@@ -1029,16 +1041,18 @@
      * @param r_src The source physical register.
      * @return Returns the newly created LIR or null in case of creation failure.
      */
-    virtual LIR* OpCondRegReg(OpKind op, ConditionCode cc, int r_dest, int r_src) = 0;
+    virtual LIR* OpCondRegReg(OpKind op, ConditionCode cc, RegStorage r_dest, RegStorage r_src) = 0;
 
-    virtual LIR* OpRegRegImm(OpKind op, int r_dest, int r_src1, int value) = 0;
-    virtual LIR* OpRegRegReg(OpKind op, int r_dest, int r_src1, int r_src2) = 0;
+    virtual LIR* OpRegRegImm(OpKind op, RegStorage r_dest, RegStorage r_src1, int value) = 0;
+    virtual LIR* OpRegRegReg(OpKind op, RegStorage r_dest, RegStorage r_src1,
+                             RegStorage r_src2) = 0;
     virtual LIR* OpTestSuspend(LIR* target) = 0;
     virtual LIR* OpThreadMem(OpKind op, ThreadOffset thread_offset) = 0;
-    virtual LIR* OpVldm(int rBase, int count) = 0;
-    virtual LIR* OpVstm(int rBase, int count) = 0;
-    virtual void OpLea(int rBase, int reg1, int reg2, int scale, int offset) = 0;
-    virtual void OpRegCopyWide(int dest_lo, int dest_hi, int src_lo, int src_hi) = 0;
+    virtual LIR* OpVldm(RegStorage r_base, int count) = 0;
+    virtual LIR* OpVstm(RegStorage r_base, int count) = 0;
+    virtual void OpLea(RegStorage r_base, RegStorage reg1, RegStorage reg2, int scale,
+                       int offset) = 0;
+    virtual void OpRegCopyWide(RegStorage dest, RegStorage src) = 0;
     virtual void OpTlsCmp(ThreadOffset offset, int val) = 0;
     virtual bool InexpensiveConstantInt(int32_t value) = 0;
     virtual bool InexpensiveConstantFloat(int32_t value) = 0;
@@ -1050,7 +1064,7 @@
     virtual void GenMonitorExit(int opt_flags, RegLocation rl_src);
 
     // Temp workaround
-    void Workaround7250540(RegLocation rl_dest, int value);
+    void Workaround7250540(RegLocation rl_dest, RegStorage zero_reg);
 
   protected:
     Mir2Lir(CompilationUnit* cu, MIRGraph* mir_graph, ArenaAllocator* arena);
@@ -1163,7 +1177,7 @@
      * @param wide Whether the argument is 64-bit or not.
      * @return Returns the register (or register pair) for the loaded argument.
      */
-    int LoadArg(int in_position, bool wide = false);
+    RegStorage LoadArg(int in_position, bool wide = false);
 
     /**
      * @brief Used to load a VR argument directly to a specified register location.
diff --git a/compiler/dex/quick/ralloc_util.cc b/compiler/dex/quick/ralloc_util.cc
index 3cb6fd0..3c49756 100644
--- a/compiler/dex/quick/ralloc_util.cc
+++ b/compiler/dex/quick/ralloc_util.cc
@@ -81,6 +81,15 @@
   DumpRegPool(reg_pool_->FPRegs, reg_pool_->num_fp_regs);
 }
 
+void Mir2Lir::Clobber(RegStorage reg) {
+  if (reg.IsPair()) {
+    ClobberBody(GetRegInfo(reg.GetLowReg()));
+    ClobberBody(GetRegInfo(reg.GetHighReg()));
+  } else {
+    ClobberBody(GetRegInfo(reg.GetReg()));
+  }
+}
+
 void Mir2Lir::ClobberSRegBody(RegisterInfo* p, int num_regs, int s_reg) {
   for (int i = 0; i< num_regs; i++) {
     if (p[i].s_reg == s_reg) {
@@ -144,25 +153,26 @@
   }
 }
 
-void Mir2Lir::RecordCorePromotion(int reg, int s_reg) {
+void Mir2Lir::RecordCorePromotion(RegStorage reg, int s_reg) {
   int p_map_idx = SRegToPMap(s_reg);
   int v_reg = mir_graph_->SRegToVReg(s_reg);
-  GetRegInfo(reg)->in_use = true;
-  core_spill_mask_ |= (1 << reg);
+  int reg_num = reg.GetReg();
+  GetRegInfo(reg_num)->in_use = true;
+  core_spill_mask_ |= (1 << reg_num);
   // Include reg for later sort
-  core_vmap_table_.push_back(reg << VREG_NUM_WIDTH | (v_reg & ((1 << VREG_NUM_WIDTH) - 1)));
+  core_vmap_table_.push_back(reg_num << VREG_NUM_WIDTH | (v_reg & ((1 << VREG_NUM_WIDTH) - 1)));
   num_core_spills_++;
   promotion_map_[p_map_idx].core_location = kLocPhysReg;
-  promotion_map_[p_map_idx].core_reg = reg;
+  promotion_map_[p_map_idx].core_reg = reg_num;
 }
 
 /* Reserve a callee-save register.  Return -1 if none available */
-int Mir2Lir::AllocPreservedCoreReg(int s_reg) {
-  int res = -1;
+RegStorage Mir2Lir::AllocPreservedCoreReg(int s_reg) {
+  RegStorage res;
   RegisterInfo* core_regs = reg_pool_->core_regs;
   for (int i = 0; i < reg_pool_->num_core_regs; i++) {
     if (!core_regs[i].is_temp && !core_regs[i].in_use) {
-      res = core_regs[i].reg;
+      res = RegStorage::Solo32(core_regs[i].reg);
       RecordCorePromotion(res, s_reg);
       break;
     }
@@ -170,22 +180,23 @@
   return res;
 }
 
-void Mir2Lir::RecordFpPromotion(int reg, int s_reg) {
+void Mir2Lir::RecordFpPromotion(RegStorage reg, int s_reg) {
   int p_map_idx = SRegToPMap(s_reg);
   int v_reg = mir_graph_->SRegToVReg(s_reg);
-  GetRegInfo(reg)->in_use = true;
-  MarkPreservedSingle(v_reg, reg);
+  int reg_num = reg.GetReg();
+  GetRegInfo(reg_num)->in_use = true;
+  MarkPreservedSingle(v_reg, reg_num);
   promotion_map_[p_map_idx].fp_location = kLocPhysReg;
-  promotion_map_[p_map_idx].FpReg = reg;
+  promotion_map_[p_map_idx].FpReg = reg_num;
 }
 
 // Reserve a callee-save fp single register.
-int Mir2Lir::AllocPreservedSingle(int s_reg) {
-  int res = -1;  // Return code if none available.
+RegStorage Mir2Lir::AllocPreservedSingle(int s_reg) {
+  RegStorage res;
   RegisterInfo* FPRegs = reg_pool_->FPRegs;
   for (int i = 0; i < reg_pool_->num_fp_regs; i++) {
     if (!FPRegs[i].is_temp && !FPRegs[i].in_use) {
-      res = FPRegs[i].reg;
+      res = RegStorage::Solo32(FPRegs[i].reg);
       RecordFpPromotion(res, s_reg);
       break;
     }
@@ -201,8 +212,9 @@
  * allocate if we can't meet the requirements for the pair of
  * s_reg<=sX[even] & (s_reg+1)<= sX+1.
  */
-int Mir2Lir::AllocPreservedDouble(int s_reg) {
-  int res = -1;  // Assume failure
+// TODO: needs rewrite to support non-backed 64-bit float regs.
+RegStorage Mir2Lir::AllocPreservedDouble(int s_reg) {
+  RegStorage res;
   int v_reg = mir_graph_->SRegToVReg(s_reg);
   int p_map_idx = SRegToPMap(s_reg);
   if (promotion_map_[p_map_idx+1].fp_location == kLocPhysReg) {
@@ -210,19 +222,19 @@
     int high_reg = promotion_map_[p_map_idx+1].FpReg;
     if ((high_reg & 1) == 0) {
       // High reg is even - fail.
-      return res;
+      return res;  // Invalid.
     }
     // Is the low reg of the pair free?
     RegisterInfo* p = GetRegInfo(high_reg-1);
     if (p->in_use || p->is_temp) {
       // Already allocated or not preserved - fail.
-      return res;
+      return res;  // Invalid.
     }
     // OK - good to go.
-    res = p->reg;
+    res = RegStorage(RegStorage::k64BitPair, p->reg, p->reg + 1);
     p->in_use = true;
-    DCHECK_EQ((res & 1), 0);
-    MarkPreservedSingle(v_reg, res);
+    DCHECK_EQ((res.GetReg() & 1), 0);
+    MarkPreservedSingle(v_reg, res.GetReg());
   } else {
     RegisterInfo* FPRegs = reg_pool_->FPRegs;
     for (int i = 0; i < reg_pool_->num_fp_regs; i++) {
@@ -231,27 +243,27 @@
         !FPRegs[i+1].is_temp && !FPRegs[i+1].in_use &&
         ((FPRegs[i+1].reg & 0x1) == 0x1) &&
         (FPRegs[i].reg + 1) == FPRegs[i+1].reg) {
-        res = FPRegs[i].reg;
+        res = RegStorage(RegStorage::k64BitPair, FPRegs[i].reg, FPRegs[i].reg+1);
         FPRegs[i].in_use = true;
-        MarkPreservedSingle(v_reg, res);
+        MarkPreservedSingle(v_reg, res.GetLowReg());
         FPRegs[i+1].in_use = true;
-        DCHECK_EQ(res + 1, FPRegs[i+1].reg);
-        MarkPreservedSingle(v_reg+1, res+1);
+        DCHECK_EQ(res.GetLowReg() + 1, FPRegs[i+1].reg);
+        MarkPreservedSingle(v_reg+1, res.GetLowReg() + 1);
         break;
       }
     }
   }
-  if (res != -1) {
+  if (res.Valid()) {
     promotion_map_[p_map_idx].fp_location = kLocPhysReg;
-    promotion_map_[p_map_idx].FpReg = res;
+    promotion_map_[p_map_idx].FpReg = res.GetLowReg();
     promotion_map_[p_map_idx+1].fp_location = kLocPhysReg;
-    promotion_map_[p_map_idx+1].FpReg = res + 1;
+    promotion_map_[p_map_idx+1].FpReg = res.GetLowReg() + 1;
   }
   return res;
 }
 
-int Mir2Lir::AllocTempBody(RegisterInfo* p, int num_regs, int* next_temp,
-                           bool required) {
+RegStorage Mir2Lir::AllocTempBody(RegisterInfo* p, int num_regs, int* next_temp,
+                                  bool required) {
   int next = *next_temp;
   for (int i = 0; i< num_regs; i++) {
     if (next >= num_regs)
@@ -261,7 +273,7 @@
       p[next].in_use = true;
       p[next].pair = false;
       *next_temp = next + 1;
-      return p[next].reg;
+      return RegStorage::Solo32(p[next].reg);
     }
     next++;
   }
@@ -274,7 +286,7 @@
       p[next].in_use = true;
       p[next].pair = false;
       *next_temp = next + 1;
-      return p[next].reg;
+      return RegStorage::Solo32(p[next].reg);
     }
     next++;
   }
@@ -284,11 +296,12 @@
           reg_pool_->num_core_regs);
     LOG(FATAL) << "No free temp registers";
   }
-  return -1;  // No register available
+  return RegStorage::InvalidReg();  // No register available
 }
 
 // REDO: too many assumptions.
-int Mir2Lir::AllocTempDouble() {
+// Virtualize - this is target dependent.
+RegStorage Mir2Lir::AllocTempDouble() {
   RegisterInfo* p = reg_pool_->FPRegs;
   int num_regs = reg_pool_->num_fp_regs;
   /* Start looking at an even reg */
@@ -310,7 +323,8 @@
       if (reg_pool_->next_fp_reg >= num_regs) {
         reg_pool_->next_fp_reg = 0;
       }
-      return p[next].reg;
+      // FIXME: should return k64BitSolo.
+      return RegStorage(RegStorage::k64BitPair, p[next].reg, p[next+1].reg);
     }
     next += 2;
   }
@@ -332,28 +346,28 @@
       if (reg_pool_->next_fp_reg >= num_regs) {
         reg_pool_->next_fp_reg = 0;
       }
-      return p[next].reg;
+      return RegStorage(RegStorage::k64BitPair, p[next].reg, p[next+1].reg);
     }
     next += 2;
   }
   LOG(FATAL) << "No free temp registers (pair)";
-  return -1;
+  return RegStorage::InvalidReg();
 }
 
 /* Return a temp if one is available, -1 otherwise */
-int Mir2Lir::AllocFreeTemp() {
+RegStorage Mir2Lir::AllocFreeTemp() {
   return AllocTempBody(reg_pool_->core_regs,
              reg_pool_->num_core_regs,
              &reg_pool_->next_core_reg, false);
 }
 
-int Mir2Lir::AllocTemp() {
+RegStorage Mir2Lir::AllocTemp() {
   return AllocTempBody(reg_pool_->core_regs,
              reg_pool_->num_core_regs,
              &reg_pool_->next_core_reg, true);
 }
 
-int Mir2Lir::AllocTempFloat() {
+RegStorage Mir2Lir::AllocTempFloat() {
   return AllocTempBody(reg_pool_->FPRegs,
              reg_pool_->num_fp_regs,
              &reg_pool_->next_fp_reg, true);
@@ -403,26 +417,71 @@
   p->pair = false;
 }
 
+void Mir2Lir::FreeTemp(RegStorage reg) {
+  if (reg.IsPair()) {
+    FreeTemp(reg.GetLowReg());
+    FreeTemp(reg.GetHighReg());
+  } else {
+    FreeTemp(reg.GetReg());
+  }
+}
+
 Mir2Lir::RegisterInfo* Mir2Lir::IsLive(int reg) {
   RegisterInfo* p = GetRegInfo(reg);
   return p->live ? p : NULL;
 }
 
+Mir2Lir::RegisterInfo* Mir2Lir::IsLive(RegStorage reg) {
+  if (reg.IsPair()) {
+    DCHECK_EQ(IsLive(reg.GetLowReg()) == nullptr, IsLive(reg.GetHighReg()) == nullptr);
+    return IsLive(reg.GetLowReg());
+  } else {
+    return IsLive(reg.GetReg());
+  }
+}
+
 Mir2Lir::RegisterInfo* Mir2Lir::IsTemp(int reg) {
   RegisterInfo* p = GetRegInfo(reg);
   return (p->is_temp) ? p : NULL;
 }
 
+Mir2Lir::RegisterInfo* Mir2Lir::IsTemp(RegStorage reg) {
+  if (reg.IsPair()) {
+    DCHECK_EQ(IsTemp(reg.GetLowReg()) == nullptr, IsTemp(reg.GetHighReg()) == nullptr);
+    return IsTemp(reg.GetLowReg());
+  } else {
+    return IsTemp(reg.GetReg());
+  }
+}
+
 Mir2Lir::RegisterInfo* Mir2Lir::IsPromoted(int reg) {
   RegisterInfo* p = GetRegInfo(reg);
   return (p->is_temp) ? NULL : p;
 }
 
+Mir2Lir::RegisterInfo* Mir2Lir::IsPromoted(RegStorage reg) {
+  if (reg.IsPair()) {
+    DCHECK_EQ(IsPromoted(reg.GetLowReg()) == nullptr, IsPromoted(reg.GetHighReg()) == nullptr);
+    return IsPromoted(reg.GetLowReg());
+  } else {
+    return IsPromoted(reg.GetReg());
+  }
+}
+
 bool Mir2Lir::IsDirty(int reg) {
   RegisterInfo* p = GetRegInfo(reg);
   return p->dirty;
 }
 
+bool Mir2Lir::IsDirty(RegStorage reg) {
+  if (reg.IsPair()) {
+    DCHECK_EQ(IsDirty(reg.GetLowReg()), IsDirty(reg.GetHighReg()));
+    return IsDirty(reg.GetLowReg());
+  } else {
+    return IsDirty(reg.GetReg());
+  }
+}
+
 /*
  * Similar to AllocTemp(), but forces the allocation of a specific
  * register.  No check is made to see if the register was previously
@@ -435,10 +494,20 @@
   p->live = false;
 }
 
+void Mir2Lir::LockTemp(RegStorage reg) {
+  DCHECK(!reg.IsPair());
+  LockTemp(reg.GetReg());
+}
+
 void Mir2Lir::ResetDef(int reg) {
   ResetDefBody(GetRegInfo(reg));
 }
 
+void Mir2Lir::ResetDef(RegStorage reg) {
+  DCHECK(!reg.IsPair());  // Is this done?  If so, do on both low and high.
+  ResetDef(reg.GetReg());
+}
+
 void Mir2Lir::NullifyRange(LIR *start, LIR *finish, int s_reg1, int s_reg2) {
   if (start && finish) {
     LIR *p;
@@ -474,7 +543,7 @@
   DCHECK(rl.wide);
   DCHECK(start && start->next);
   DCHECK(finish);
-  RegisterInfo* p = GetRegInfo(rl.reg.GetReg());
+  RegisterInfo* p = GetRegInfo(rl.reg.GetLowReg());
   ResetDef(rl.reg.GetHighReg());  // Only track low of pair
   p->def_start = start->next;
   p->def_end = finish;
@@ -483,7 +552,7 @@
 RegLocation Mir2Lir::WideToNarrow(RegLocation rl) {
   DCHECK(rl.wide);
   if (rl.location == kLocPhysReg) {
-    RegisterInfo* info_lo = GetRegInfo(rl.reg.GetReg());
+    RegisterInfo* info_lo = GetRegInfo(rl.reg.GetLowReg());
     RegisterInfo* info_hi = GetRegInfo(rl.reg.GetHighReg());
     if (info_lo->is_temp) {
       info_lo->pair = false;
@@ -495,6 +564,7 @@
       info_hi->def_start = NULL;
       info_hi->def_end = NULL;
     }
+    rl.reg = RegStorage::Solo32(rl.reg.GetLowReg());
   }
   rl.wide = false;
   return rl;
@@ -512,7 +582,7 @@
 
 void Mir2Lir::ResetDefLocWide(RegLocation rl) {
   DCHECK(rl.wide);
-  RegisterInfo* p_low = IsTemp(rl.reg.GetReg());
+  RegisterInfo* p_low = IsTemp(rl.reg.GetLowReg());
   RegisterInfo* p_high = IsTemp(rl.reg.GetHighReg());
   if (p_low && !(cu_->disable_opt & (1 << kSuppressLoads))) {
     DCHECK(p_low->pair);
@@ -521,7 +591,7 @@
   if (p_high && !(cu_->disable_opt & (1 << kSuppressLoads))) {
     DCHECK(p_high->pair);
   }
-  ResetDef(rl.reg.GetReg());
+  ResetDef(rl.reg.GetLowReg());
   ResetDef(rl.reg.GetHighReg());
 }
 
@@ -547,9 +617,9 @@
 
 void Mir2Lir::FlushSpecificReg(RegisterInfo* info) {
   if (info->pair) {
-    FlushRegWide(info->reg, info->partner);
+    FlushRegWide(RegStorage(RegStorage::k64BitPair, info->reg, info->partner));
   } else {
-    FlushReg(info->reg);
+    FlushReg(RegStorage::Solo32(info->reg));
   }
 }
 
@@ -572,19 +642,21 @@
 
 
 // TUNING: rewrite all of this reg stuff.  Probably use an attribute table
-bool Mir2Lir::RegClassMatches(int reg_class, int reg) {
+bool Mir2Lir::RegClassMatches(int reg_class, RegStorage reg) {
+  int reg_num = reg.IsPair() ? reg.GetLowReg() : reg.GetReg();
   if (reg_class == kAnyReg) {
     return true;
   } else if (reg_class == kCoreReg) {
-    return !IsFpReg(reg);
+    return !IsFpReg(reg_num);
   } else {
-    return IsFpReg(reg);
+    return IsFpReg(reg_num);
   }
 }
 
-void Mir2Lir::MarkLive(int reg, int s_reg) {
-  RegisterInfo* info = GetRegInfo(reg);
-  if ((info->reg == reg) && (info->s_reg == s_reg) && info->live) {
+void Mir2Lir::MarkLive(RegStorage reg, int s_reg) {
+  DCHECK(!reg.IsPair());   // Could be done - but would that be meaningful?
+  RegisterInfo* info = GetRegInfo(reg.GetReg());
+  if ((info->s_reg == s_reg) && info->live) {
     return;  /* already live */
   } else if (s_reg != INVALID_SREG) {
     ClobberSReg(s_reg);
@@ -605,12 +677,22 @@
   info->is_temp = true;
 }
 
+void Mir2Lir::MarkTemp(RegStorage reg) {
+  DCHECK(!reg.IsPair());
+  MarkTemp(reg.GetReg());
+}
+
 void Mir2Lir::UnmarkTemp(int reg) {
   RegisterInfo* info = GetRegInfo(reg);
   tempreg_info_.Delete(info);
   info->is_temp = false;
 }
 
+void Mir2Lir::UnmarkTemp(RegStorage reg) {
+  DCHECK(!reg.IsPair());
+  UnmarkTemp(reg.GetReg());
+}
+
 void Mir2Lir::MarkPair(int low_reg, int high_reg) {
   DCHECK_NE(low_reg, high_reg);
   RegisterInfo* info_lo = GetRegInfo(low_reg);
@@ -621,11 +703,14 @@
 }
 
 void Mir2Lir::MarkClean(RegLocation loc) {
-  RegisterInfo* info = GetRegInfo(loc.reg.GetReg());
-  info->dirty = false;
   if (loc.wide) {
+    RegisterInfo* info = GetRegInfo(loc.reg.GetLowReg());
+    info->dirty = false;
     info = GetRegInfo(loc.reg.GetHighReg());
     info->dirty = false;
+  } else {
+    RegisterInfo* info = GetRegInfo(loc.reg.GetReg());
+    info->dirty = false;
   }
 }
 
@@ -634,11 +719,14 @@
     // If already home, can't be dirty
     return;
   }
-  RegisterInfo* info = GetRegInfo(loc.reg.GetReg());
-  info->dirty = true;
   if (loc.wide) {
+    RegisterInfo* info = GetRegInfo(loc.reg.GetLowReg());
+    info->dirty = true;
     info = GetRegInfo(loc.reg.GetHighReg());
     info->dirty = true;
+  } else {
+    RegisterInfo* info = GetRegInfo(loc.reg.GetReg());
+    info->dirty = true;
   }
 }
 
@@ -647,6 +735,15 @@
     info->in_use = true;
 }
 
+void Mir2Lir::MarkInUse(RegStorage reg) {
+  if (reg.IsPair()) {
+    MarkInUse(reg.GetLowReg());
+    MarkInUse(reg.GetHighReg());
+  } else {
+    MarkInUse(reg.GetReg());
+  }
+}
+
 void Mir2Lir::CopyRegInfo(int new_reg, int old_reg) {
   RegisterInfo* new_info = GetRegInfo(new_reg);
   RegisterInfo* old_info = GetRegInfo(old_reg);
@@ -658,6 +755,12 @@
   new_info->reg = new_reg;
 }
 
+void Mir2Lir::CopyRegInfo(RegStorage new_reg, RegStorage old_reg) {
+  DCHECK(!new_reg.IsPair());
+  DCHECK(!old_reg.IsPair());
+  CopyRegInfo(new_reg.GetReg(), old_reg.GetReg());
+}
+
 bool Mir2Lir::CheckCorePoolSanity() {
   for (static int i = 0; i < reg_pool_->num_core_regs; i++) {
     if (reg_pool_->core_regs[i].pair) {
@@ -707,12 +810,11 @@
         Clobber(info_lo->partner);
         FreeTemp(info_lo->reg);
       } else {
-        loc.reg = RegStorage(RegStorage::k32BitSolo, info_lo->reg);
+        loc.reg = RegStorage::Solo32(info_lo->reg);
         loc.location = kLocPhysReg;
       }
     }
   }
-
   return loc;
 }
 
@@ -746,8 +848,8 @@
       // Can reuse - update the register usage info
       loc.location = kLocPhysReg;
       loc.reg = RegStorage(RegStorage::k64BitPair, info_lo->reg, info_hi->reg);
-      MarkPair(loc.reg.GetReg(), loc.reg.GetHighReg());
-      DCHECK(!IsFpReg(loc.reg.GetReg()) || ((loc.reg.GetReg() & 0x1) == 0));
+      MarkPair(loc.reg.GetLowReg(), loc.reg.GetHighReg());
+      DCHECK(!IsFpReg(loc.reg.GetLowReg()) || ((loc.reg.GetLowReg() & 0x1) == 0));
       return loc;
     }
     // Can't easily reuse - clobber and free any overlaps
@@ -778,28 +880,23 @@
 
 RegLocation Mir2Lir::EvalLocWide(RegLocation loc, int reg_class, bool update) {
   DCHECK(loc.wide);
-  int32_t low_reg;
-  int32_t high_reg;
 
   loc = UpdateLocWide(loc);
 
   /* If already in registers, we can assume proper form.  Right reg class? */
   if (loc.location == kLocPhysReg) {
-    DCHECK_EQ(IsFpReg(loc.reg.GetReg()), IsFpReg(loc.reg.GetHighReg()));
-    DCHECK(!IsFpReg(loc.reg.GetReg()) || ((loc.reg.GetReg() & 0x1) == 0));
-    if (!RegClassMatches(reg_class, loc.reg.GetReg())) {
+    DCHECK_EQ(IsFpReg(loc.reg.GetLowReg()), IsFpReg(loc.reg.GetHighReg()));
+    DCHECK(!IsFpReg(loc.reg.GetLowReg()) || ((loc.reg.GetLowReg() & 0x1) == 0));
+    if (!RegClassMatches(reg_class, loc.reg)) {
       /* Wrong register class.  Reallocate and copy */
       RegStorage new_regs = AllocTypedTempWide(loc.fp, reg_class);
-      low_reg = new_regs.GetReg();
-      high_reg = new_regs.GetHighReg();
-      OpRegCopyWide(low_reg, high_reg, loc.reg.GetReg(), loc.reg.GetHighReg());
-      CopyRegInfo(low_reg, loc.reg.GetReg());
-      CopyRegInfo(high_reg, loc.reg.GetHighReg());
-      Clobber(loc.reg.GetReg());
-      Clobber(loc.reg.GetHighReg());
+      OpRegCopyWide(new_regs, loc.reg);
+      CopyRegInfo(new_regs.GetLowReg(), loc.reg.GetLowReg());
+      CopyRegInfo(new_regs.GetHighReg(), loc.reg.GetHighReg());
+      Clobber(loc.reg);
       loc.reg = new_regs;
-      MarkPair(loc.reg.GetReg(), loc.reg.GetHighReg());
-      DCHECK(!IsFpReg(loc.reg.GetReg()) || ((loc.reg.GetReg() & 0x1) == 0));
+      MarkPair(loc.reg.GetLowReg(), loc.reg.GetHighReg());
+      DCHECK(!IsFpReg(loc.reg.GetLowReg()) || ((loc.reg.GetLowReg() & 0x1) == 0));
     }
     return loc;
   }
@@ -809,47 +906,44 @@
 
   loc.reg = AllocTypedTempWide(loc.fp, reg_class);
 
-  MarkPair(loc.reg.GetReg(), loc.reg.GetHighReg());
+  MarkPair(loc.reg.GetLowReg(), loc.reg.GetHighReg());
   if (update) {
     loc.location = kLocPhysReg;
-    MarkLive(loc.reg.GetReg(), loc.s_reg_low);
+    MarkLive(loc.reg.GetLow(), loc.s_reg_low);
     // Does this wide value live in two registers or one vector register?
-    if (loc.reg.GetReg() != loc.reg.GetHighReg()) {
-      MarkLive(loc.reg.GetHighReg(), GetSRegHi(loc.s_reg_low));
+    if (loc.reg.GetLowReg() != loc.reg.GetHighReg()) {
+      MarkLive(loc.reg.GetHigh(), GetSRegHi(loc.s_reg_low));
     }
   }
-  DCHECK(!IsFpReg(loc.reg.GetReg()) || ((loc.reg.GetReg() & 0x1) == 0));
+  DCHECK(!IsFpReg(loc.reg.GetLowReg()) || ((loc.reg.GetLowReg() & 0x1) == 0));
   return loc;
 }
 
 RegLocation Mir2Lir::EvalLoc(RegLocation loc, int reg_class, bool update) {
-  int new_reg;
-
   if (loc.wide)
     return EvalLocWide(loc, reg_class, update);
 
   loc = UpdateLoc(loc);
 
   if (loc.location == kLocPhysReg) {
-    if (!RegClassMatches(reg_class, loc.reg.GetReg())) {
+    if (!RegClassMatches(reg_class, loc.reg)) {
       /* Wrong register class.  Realloc, copy and transfer ownership */
-      new_reg = AllocTypedTemp(loc.fp, reg_class);
-      OpRegCopy(new_reg, loc.reg.GetReg());
-      CopyRegInfo(new_reg, loc.reg.GetReg());
-      Clobber(loc.reg.GetReg());
-      loc.reg = RegStorage(RegStorage::k32BitSolo, new_reg);
+      RegStorage new_reg = AllocTypedTemp(loc.fp, reg_class);
+      OpRegCopy(new_reg, loc.reg);
+      CopyRegInfo(new_reg, loc.reg);
+      Clobber(loc.reg);
+      loc.reg = new_reg;
     }
     return loc;
   }
 
   DCHECK_NE(loc.s_reg_low, INVALID_SREG);
 
-  new_reg = AllocTypedTemp(loc.fp, reg_class);
-  loc.reg = RegStorage(RegStorage::k32BitSolo, new_reg);
+  loc.reg = AllocTypedTemp(loc.fp, reg_class);
 
   if (update) {
     loc.location = kLocPhysReg;
-    MarkLive(loc.reg.GetReg(), loc.s_reg_low);
+    MarkLive(loc.reg, loc.s_reg_low);
   }
   return loc;
 }
@@ -972,8 +1066,8 @@
           AllocPreservedDouble(low_sreg);
         }
       } else if (promotion_map_[p_map_idx].fp_location != kLocPhysReg) {
-        int reg = AllocPreservedSingle(FpRegs[i].s_reg);
-        if (reg < 0) {
+        RegStorage reg = AllocPreservedSingle(FpRegs[i].s_reg);
+        if (!reg.Valid()) {
           break;  // No more left.
         }
       }
@@ -985,8 +1079,8 @@
       int p_map_idx = SRegToPMap(core_regs[i].s_reg);
       if (promotion_map_[p_map_idx].core_location !=
           kLocPhysReg) {
-        int reg = AllocPreservedCoreReg(core_regs[i].s_reg);
-        if (reg < 0) {
+        RegStorage reg = AllocPreservedCoreReg(core_regs[i].s_reg);
+        if (!reg.Valid()) {
            break;  // No more left
         }
       }
@@ -1001,13 +1095,13 @@
       if (curr->fp) {
         if (promotion_map_[p_map_idx].fp_location == kLocPhysReg) {
           curr->location = kLocPhysReg;
-          curr->reg = RegStorage(RegStorage::k32BitSolo, promotion_map_[p_map_idx].FpReg);
+          curr->reg = RegStorage::Solo32(promotion_map_[p_map_idx].FpReg);
           curr->home = true;
         }
       } else {
         if (promotion_map_[p_map_idx].core_location == kLocPhysReg) {
           curr->location = kLocPhysReg;
-          curr->reg = RegStorage(RegStorage::k32BitSolo, promotion_map_[p_map_idx].core_reg);
+          curr->reg = RegStorage::Solo32(promotion_map_[p_map_idx].core_reg);
           curr->home = true;
         }
       }
@@ -1060,13 +1154,13 @@
   RegLocation gpr_res = LocCReturnWide();
   RegLocation fpr_res = LocCReturnDouble();
   RegLocation res = is_double ? fpr_res : gpr_res;
-  Clobber(res.reg.GetReg());
+  Clobber(res.reg.GetLowReg());
   Clobber(res.reg.GetHighReg());
-  LockTemp(res.reg.GetReg());
+  LockTemp(res.reg.GetLowReg());
   LockTemp(res.reg.GetHighReg());
   // Does this wide value live in two registers or one vector register?
-  if (res.reg.GetReg() != res.reg.GetHighReg()) {
-    MarkPair(res.reg.GetReg(), res.reg.GetHighReg());
+  if (res.reg.GetLowReg() != res.reg.GetHighReg()) {
+    MarkPair(res.reg.GetLowReg(), res.reg.GetHighReg());
   }
   return res;
 }
diff --git a/compiler/dex/quick/x86/call_x86.cc b/compiler/dex/quick/x86/call_x86.cc
index 68e2b6d..d97cf4d 100644
--- a/compiler/dex/quick/x86/call_x86.cc
+++ b/compiler/dex/quick/x86/call_x86.cc
@@ -40,8 +40,7 @@
     int key = keys[i];
     BasicBlock* case_block =
         mir_graph_->FindBlock(current_dalvik_offset_ + targets[i]);
-    OpCmpImmBranch(kCondEq, rl_src.reg.GetReg(), key,
-                   &block_label_list_[case_block->id]);
+    OpCmpImmBranch(kCondEq, rl_src.reg, key, &block_label_list_[case_block->id]);
   }
 }
 
@@ -82,37 +81,37 @@
   // NewLIR0(kX86Bkpt);
 
   // Materialize a pointer to the switch table
-  int start_of_method_reg;
+  RegStorage start_of_method_reg;
   if (base_of_code_ != nullptr) {
     // We can use the saved value.
     RegLocation rl_method = mir_graph_->GetRegLocation(base_of_code_->s_reg_low);
     rl_method = LoadValue(rl_method, kCoreReg);
-    start_of_method_reg = rl_method.reg.GetReg();
+    start_of_method_reg = rl_method.reg;
     store_method_addr_used_ = true;
   } else {
     start_of_method_reg = AllocTemp();
-    NewLIR1(kX86StartOfMethod, start_of_method_reg);
+    NewLIR1(kX86StartOfMethod, start_of_method_reg.GetReg());
   }
   int low_key = s4FromSwitchData(&table[2]);
-  int keyReg;
+  RegStorage keyReg;
   // Remove the bias, if necessary
   if (low_key == 0) {
-    keyReg = rl_src.reg.GetReg();
+    keyReg = rl_src.reg;
   } else {
     keyReg = AllocTemp();
-    OpRegRegImm(kOpSub, keyReg, rl_src.reg.GetReg(), low_key);
+    OpRegRegImm(kOpSub, keyReg, rl_src.reg, low_key);
   }
   // Bounds check - if < 0 or >= size continue following switch
   OpRegImm(kOpCmp, keyReg, size-1);
   LIR* branch_over = OpCondBranch(kCondHi, NULL);
 
   // Load the displacement from the switch table
-  int disp_reg = AllocTemp();
-  NewLIR5(kX86PcRelLoadRA, disp_reg, start_of_method_reg, keyReg, 2, WrapPointer(tab_rec));
+  RegStorage disp_reg = AllocTemp();
+  NewLIR5(kX86PcRelLoadRA, disp_reg.GetReg(), start_of_method_reg.GetReg(), keyReg.GetReg(), 2, WrapPointer(tab_rec));
   // Add displacement to start of method
   OpRegReg(kOpAdd, start_of_method_reg, disp_reg);
   // ..and go!
-  LIR* switch_branch = NewLIR1(kX86JmpR, start_of_method_reg);
+  LIR* switch_branch = NewLIR1(kX86JmpR, start_of_method_reg.GetReg());
   tab_rec->anchor = switch_branch;
 
   /* branch_over target here */
@@ -145,20 +144,20 @@
 
   // Making a call - use explicit registers
   FlushAllRegs();   /* Everything to home location */
-  LoadValueDirectFixed(rl_src, rX86_ARG0);
+  LoadValueDirectFixed(rl_src, rs_rX86_ARG0);
   // Materialize a pointer to the fill data image
   if (base_of_code_ != nullptr) {
     // We can use the saved value.
     RegLocation rl_method = mir_graph_->GetRegLocation(base_of_code_->s_reg_low);
-    LoadValueDirect(rl_method, rX86_ARG2);
+    LoadValueDirect(rl_method, rs_rX86_ARG2);
     store_method_addr_used_ = true;
   } else {
     NewLIR1(kX86StartOfMethod, rX86_ARG2);
   }
   NewLIR2(kX86PcRelAdr, rX86_ARG1, WrapPointer(tab_rec));
   NewLIR2(kX86Add32RR, rX86_ARG1, rX86_ARG2);
-  CallRuntimeHelperRegReg(QUICK_ENTRYPOINT_OFFSET(pHandleFillArrayData), rX86_ARG0,
-                          rX86_ARG1, true);
+  CallRuntimeHelperRegReg(QUICK_ENTRYPOINT_OFFSET(pHandleFillArrayData), rs_rX86_ARG0,
+                          rs_rX86_ARG1, true);
 }
 
 void X86Mir2Lir::GenMoveException(RegLocation rl_dest) {
@@ -172,14 +171,13 @@
 /*
  * Mark garbage collection card. Skip if the value we're storing is null.
  */
-void X86Mir2Lir::MarkGCCard(int val_reg, int tgt_addr_reg) {
-  int reg_card_base = AllocTemp();
-  int reg_card_no = AllocTemp();
+void X86Mir2Lir::MarkGCCard(RegStorage val_reg, RegStorage tgt_addr_reg) {
+  RegStorage reg_card_base = AllocTemp();
+  RegStorage reg_card_no = AllocTemp();
   LIR* branch_over = OpCmpImmBranch(kCondEq, val_reg, 0, NULL);
-  NewLIR2(kX86Mov32RT, reg_card_base, Thread::CardTableOffset().Int32Value());
+  NewLIR2(kX86Mov32RT, reg_card_base.GetReg(), Thread::CardTableOffset().Int32Value());
   OpRegRegImm(kOpLsr, reg_card_no, tgt_addr_reg, gc::accounting::CardTable::kCardShift);
-  StoreBaseIndexed(reg_card_base, reg_card_no, reg_card_base, 0,
-                   kUnsignedByte);
+  StoreBaseIndexed(reg_card_base, reg_card_no, reg_card_base, 0, kUnsignedByte);
   LIR* target = NewLIR0(kPseudoTargetLabel);
   branch_over->target = target;
   FreeTemp(reg_card_base);
@@ -199,7 +197,7 @@
 
   /* Build frame, return address already on stack */
   // TODO: 64 bit.
-  stack_decrement_ = OpRegImm(kOpSub, rX86_SP, frame_size_ - 4);
+  stack_decrement_ = OpRegImm(kOpSub, rs_rX86_SP, frame_size_ - 4);
 
   /*
    * We can safely skip the stack overflow check if we're
@@ -222,11 +220,12 @@
         m2l_->ResetRegPool();
         m2l_->ResetDefTracking();
         GenerateTargetLabel();
-        m2l_->OpRegImm(kOpAdd, kX86RegSP, sp_displace_);
+        m2l_->OpRegImm(kOpAdd, rs_rX86_SP, sp_displace_);
         m2l_->ClobberCallerSave();
         ThreadOffset func_offset = QUICK_ENTRYPOINT_OFFSET(pThrowStackOverflow);
         // Assumes codegen and target are in thumb2 mode.
-        m2l_->CallHelper(0, func_offset, false /* MarkSafepointPC */, false /* UseLink */);
+        m2l_->CallHelper(RegStorage::InvalidReg(), func_offset, false /* MarkSafepointPC */,
+                         false /* UseLink */);
       }
 
      private:
@@ -252,7 +251,7 @@
     // 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(rX86_SP, displacement, rX86_ARG0, kWord);
+    setup_method_address_[1] = StoreBaseDisp(rs_rX86_SP, displacement, rs_rX86_ARG0, kWord);
   }
 
   FreeTemp(rX86_ARG0);
@@ -271,7 +270,7 @@
   NewLIR0(kPseudoMethodExit);
   UnSpillCoreRegs();
   /* Remove frame except for return address */
-  stack_increment_ = OpRegImm(kOpAdd, rX86_SP, frame_size_ - 4);
+  stack_increment_ = OpRegImm(kOpAdd, rs_rX86_SP, frame_size_ - 4);
   NewLIR0(kX86Ret);
 }
 
diff --git a/compiler/dex/quick/x86/codegen_x86.h b/compiler/dex/quick/x86/codegen_x86.h
index f2654b9..6d427e7 100644
--- a/compiler/dex/quick/x86/codegen_x86.h
+++ b/compiler/dex/quick/x86/codegen_x86.h
@@ -28,33 +28,37 @@
 
     // Required for target - codegen helpers.
     bool SmallLiteralDivRem(Instruction::Code dalvik_opcode, bool is_div, RegLocation rl_src,
-                                    RegLocation rl_dest, int lit);
-    int LoadHelper(ThreadOffset offset);
+                            RegLocation rl_dest, int lit);
     LIR* CheckSuspendUsingLoad() OVERRIDE;
-    LIR* LoadBaseDisp(int rBase, int displacement, int r_dest, OpSize size, int s_reg);
-    LIR* LoadBaseDispWide(int rBase, int displacement, int r_dest_lo, int r_dest_hi,
-                                  int s_reg);
-    LIR* LoadBaseIndexed(int rBase, int r_index, int r_dest, int scale, OpSize size);
-    LIR* LoadBaseIndexedDisp(int rBase, int r_index, int scale, int displacement,
-                                     int r_dest, int r_dest_hi, OpSize size, int s_reg);
-    LIR* LoadConstantNoClobber(int r_dest, int value);
-    LIR* LoadConstantWide(int r_dest_lo, int r_dest_hi, int64_t value);
-    LIR* StoreBaseDisp(int rBase, int displacement, int r_src, OpSize size);
-    LIR* StoreBaseDispWide(int rBase, int displacement, int r_src_lo, int r_src_hi);
-    LIR* StoreBaseIndexed(int rBase, int r_index, int r_src, int scale, OpSize size);
-    LIR* StoreBaseIndexedDisp(int rBase, int r_index, int scale, int displacement,
-                                      int r_src, int r_src_hi, OpSize size, int s_reg);
-    void MarkGCCard(int val_reg, int tgt_addr_reg);
+    RegStorage LoadHelper(ThreadOffset offset);
+    LIR* LoadBaseDisp(RegStorage r_base, int displacement, RegStorage r_dest, OpSize size,
+                      int s_reg);
+    LIR* LoadBaseDispWide(RegStorage r_base, int displacement, RegStorage r_dest, int s_reg);
+    LIR* LoadBaseIndexed(RegStorage r_base, RegStorage r_index, RegStorage r_dest, int scale,
+                         OpSize size);
+    // TODO: collapse r_dest, r_dest_hi
+    LIR* LoadBaseIndexedDisp(RegStorage r_base, RegStorage r_index, int scale, int displacement,
+                             RegStorage r_dest, RegStorage r_dest_hi, OpSize size, int s_reg);
+    LIR* LoadConstantNoClobber(RegStorage r_dest, int value);
+    LIR* LoadConstantWide(RegStorage r_dest, int64_t value);
+    LIR* StoreBaseDisp(RegStorage r_base, int displacement, RegStorage r_src, OpSize size);
+    LIR* StoreBaseDispWide(RegStorage r_base, int displacement, RegStorage r_src);
+    LIR* StoreBaseIndexed(RegStorage r_base, RegStorage r_index, RegStorage r_src, int scale,
+                          OpSize size);
+    // TODO: collapse r_src, r_src_hi
+    LIR* StoreBaseIndexedDisp(RegStorage r_base, RegStorage r_index, int scale, int displacement,
+                              RegStorage r_src, RegStorage r_src_hi, OpSize size, int s_reg);
+    void MarkGCCard(RegStorage val_reg, RegStorage tgt_addr_reg);
 
     // Required for target - register utilities.
     bool IsFpReg(int reg);
+    bool IsFpReg(RegStorage reg);
     bool SameRegType(int reg1, int reg2);
-    // TODO: for consistency, make this return a RegStorage as well?
-    int AllocTypedTemp(bool fp_hint, int reg_class);
+    RegStorage AllocTypedTemp(bool fp_hint, int reg_class);
     RegStorage AllocTypedTempWide(bool fp_hint, int reg_class);
     int S2d(int low_reg, int high_reg);
-    int TargetReg(SpecialTargetRegister reg);
-    int GetArgMappingToPhysicalReg(int arg_num);
+    RegStorage TargetReg(SpecialTargetRegister reg);
+    RegStorage GetArgMappingToPhysicalReg(int arg_num);
     RegLocation GetReturnAlt();
     RegLocation GetReturnWideAlt();
     RegLocation LocCReturn();
@@ -65,8 +69,8 @@
     uint64_t GetRegMaskCommon(int reg);
     void AdjustSpillMask();
     void ClobberCallerSave();
-    void FlushReg(int reg);
-    void FlushRegWide(int reg1, int reg2);
+    void FlushReg(RegStorage reg);
+    void FlushRegWide(RegStorage reg);
     void FreeCallTemps();
     void FreeRegLocTemps(RegLocation rl_keep, RegLocation rl_free);
     void LockCallTemps();
@@ -89,23 +93,26 @@
     bool IsUnconditionalBranch(LIR* lir);
 
     // Required for target - Dalvik-level generators.
-    void GenArithImmOpLong(Instruction::Code opcode, RegLocation rl_dest,
-                                   RegLocation rl_src1, RegLocation rl_src2);
-    void GenArrayGet(int opt_flags, OpSize size, RegLocation rl_array,
-                             RegLocation rl_index, RegLocation rl_dest, int scale);
+    void GenArithImmOpLong(Instruction::Code opcode, RegLocation rl_dest, RegLocation rl_src1,
+                           RegLocation rl_src2);
+    void GenArrayGet(int opt_flags, OpSize size, RegLocation rl_array, RegLocation rl_index,
+                     RegLocation rl_dest, int scale);
     void GenArrayPut(int opt_flags, OpSize size, RegLocation rl_array,
                      RegLocation rl_index, RegLocation rl_src, int scale, bool card_mark);
     void GenShiftImmOpLong(Instruction::Code opcode, RegLocation rl_dest,
                            RegLocation rl_src1, RegLocation rl_shift);
-    void GenMulLong(Instruction::Code opcode, RegLocation rl_dest, RegLocation rl_src1, RegLocation rl_src2);
-    void GenAddLong(Instruction::Code opcode, RegLocation rl_dest, RegLocation rl_src1, RegLocation rl_src2);
-    void GenAndLong(Instruction::Code opcode, RegLocation rl_dest, RegLocation rl_src1, RegLocation rl_src2);
-    void GenArithOpDouble(Instruction::Code opcode, RegLocation rl_dest,
-                                  RegLocation rl_src1, RegLocation rl_src2);
-    void GenArithOpFloat(Instruction::Code opcode, RegLocation rl_dest,
-                                 RegLocation rl_src1, RegLocation rl_src2);
-    void GenCmpFP(Instruction::Code opcode, RegLocation rl_dest, RegLocation rl_src1,
+    void GenMulLong(Instruction::Code opcode, RegLocation rl_dest, RegLocation rl_src1,
+                    RegLocation rl_src2);
+    void GenAddLong(Instruction::Code opcode, RegLocation rl_dest, RegLocation rl_src1,
+                    RegLocation rl_src2);
+    void GenAndLong(Instruction::Code opcode, RegLocation rl_dest, RegLocation rl_src1,
+                    RegLocation rl_src2);
+    void GenArithOpDouble(Instruction::Code opcode, RegLocation rl_dest, RegLocation rl_src1,
                           RegLocation rl_src2);
+    void GenArithOpFloat(Instruction::Code opcode, RegLocation rl_dest, RegLocation rl_src1,
+                         RegLocation rl_src2);
+    void GenCmpFP(Instruction::Code opcode, RegLocation rl_dest, RegLocation rl_src1,
+                  RegLocation rl_src2);
     void GenConversion(Instruction::Code opcode, RegLocation rl_dest, RegLocation rl_src);
     bool GenInlinedCas(CallInfo* info, bool is_long, bool is_object);
     bool GenInlinedMinMaxInt(CallInfo* info, bool is_min);
@@ -113,17 +120,21 @@
     bool GenInlinedPeek(CallInfo* info, OpSize size);
     bool GenInlinedPoke(CallInfo* info, OpSize size);
     void GenNegLong(RegLocation rl_dest, RegLocation rl_src);
-    void GenOrLong(Instruction::Code opcode, RegLocation rl_dest, RegLocation rl_src1, RegLocation rl_src2);
-    void GenSubLong(Instruction::Code opcode, RegLocation rl_dest, RegLocation rl_src1, RegLocation rl_src2);
-    void GenXorLong(Instruction::Code opcode, RegLocation rl_dest, RegLocation rl_src1, RegLocation rl_src2);
-    LIR* GenRegMemCheck(ConditionCode c_code, int reg1, int base, int offset,
-                                ThrowKind kind);
-    LIR* GenMemImmedCheck(ConditionCode c_code, int base, int offset, int check_value,
+    void GenOrLong(Instruction::Code opcode, RegLocation rl_dest, RegLocation rl_src1,
+                   RegLocation rl_src2);
+    void GenSubLong(Instruction::Code opcode, RegLocation rl_dest, RegLocation rl_src1,
+                    RegLocation rl_src2);
+    void GenXorLong(Instruction::Code opcode, RegLocation rl_dest, RegLocation rl_src1,
+                    RegLocation rl_src2);
+    LIR* GenRegMemCheck(ConditionCode c_code, RegStorage reg1, RegStorage base, int offset,
+                        ThrowKind kind);
+    LIR* GenMemImmedCheck(ConditionCode c_code, RegStorage base, int offset, int check_value,
                           ThrowKind kind);
-    RegLocation GenDivRem(RegLocation rl_dest, int reg_lo, int reg_hi, bool is_div);
-    RegLocation GenDivRemLit(RegLocation rl_dest, int reg_lo, int lit, bool is_div);
+    // TODO: collapse reg_lo, reg_hi
+    RegLocation GenDivRem(RegLocation rl_dest, RegStorage reg_lo, RegStorage reg_hi, bool is_div);
+    RegLocation GenDivRemLit(RegLocation rl_dest, RegStorage reg_lo, int lit, bool is_div);
     void GenCmpLong(RegLocation rl_dest, RegLocation rl_src1, RegLocation rl_src2);
-    void GenDivZeroCheck(int reg_lo, int reg_hi);
+    void GenDivZeroCheck(RegStorage reg);
     void GenEntrySequence(RegLocation* ArgLocs, RegLocation rl_method);
     void GenExitSequence();
     void GenSpecialExitSequence();
@@ -133,8 +144,8 @@
     void GenSelect(BasicBlock* bb, MIR* mir);
     void GenMemBarrier(MemBarrierKind barrier_kind);
     void GenMoveException(RegLocation rl_dest);
-    void GenMultiplyByTwoBitMultiplier(RegLocation rl_src, RegLocation rl_result,
-                                               int lit, int first_bit, int second_bit);
+    void GenMultiplyByTwoBitMultiplier(RegLocation rl_src, RegLocation rl_result, int lit,
+                                       int first_bit, int second_bit);
     void GenNegDouble(RegLocation rl_dest, RegLocation rl_src);
     void GenNegFloat(RegLocation rl_dest, RegLocation rl_src);
     void GenPackedSwitch(MIR* mir, DexOffset table_offset, RegLocation rl_src);
@@ -154,8 +165,8 @@
      * @param rl_src2 constant source operand
      * @param op Opcode to be generated
      */
-    void GenLongLongImm(RegLocation rl_dest, RegLocation rl_src1,
-                        RegLocation rl_src2, Instruction::Code op);
+    void GenLongLongImm(RegLocation rl_dest, RegLocation rl_src1, RegLocation rl_src2,
+                        Instruction::Code op);
 
     /**
       * @brief Generate a long arithmetic operation.
@@ -165,8 +176,8 @@
       * @param op The DEX opcode for the operation.
       * @param is_commutative The sources can be swapped if needed.
       */
-    void GenLongArith(RegLocation rl_dest, RegLocation rl_src1,
-                      RegLocation rl_src2, Instruction::Code op, bool is_commutative);
+    void GenLongArith(RegLocation rl_dest, RegLocation rl_src1, RegLocation rl_src2,
+                      Instruction::Code op, bool is_commutative);
 
     /**
       * @brief Generate a two operand long arithmetic operation.
@@ -191,8 +202,8 @@
      * @param rl_dest Result to be set to 0 or 1.
      * @param rl_src Object to be tested.
      */
-    void GenInstanceofFinal(bool use_declaring_class, uint32_t type_idx,
-                            RegLocation rl_dest, RegLocation rl_src);
+    void GenInstanceofFinal(bool use_declaring_class, uint32_t type_idx, RegLocation rl_dest,
+                            RegLocation rl_src);
     /*
      *
      * @brief Implement Set up instanceof a class with x86 specific code.
@@ -208,38 +219,37 @@
     void GenInstanceofCallingHelper(bool needs_access_check, bool type_known_final,
                                     bool type_known_abstract, bool use_declaring_class,
                                     bool can_assume_type_is_in_dex_cache,
-                                    uint32_t type_idx, RegLocation rl_dest,
-                                    RegLocation rl_src);
+                                    uint32_t type_idx, RegLocation rl_dest, RegLocation rl_src);
 
     // Single operation generators.
     LIR* OpUnconditionalBranch(LIR* target);
-    LIR* OpCmpBranch(ConditionCode cond, int src1, int src2, LIR* target);
-    LIR* OpCmpImmBranch(ConditionCode cond, int reg, int check_value, LIR* target);
+    LIR* OpCmpBranch(ConditionCode cond, RegStorage src1, RegStorage src2, LIR* target);
+    LIR* OpCmpImmBranch(ConditionCode cond, RegStorage reg, int check_value, LIR* target);
     LIR* OpCondBranch(ConditionCode cc, LIR* target);
-    LIR* OpDecAndBranch(ConditionCode c_code, int reg, LIR* target);
-    LIR* OpFpRegCopy(int r_dest, int r_src);
+    LIR* OpDecAndBranch(ConditionCode c_code, RegStorage reg, LIR* target);
+    LIR* OpFpRegCopy(RegStorage r_dest, RegStorage r_src);
     LIR* OpIT(ConditionCode cond, const char* guide);
-    LIR* OpMem(OpKind op, int rBase, int disp);
-    LIR* OpPcRelLoad(int reg, LIR* target);
-    LIR* OpReg(OpKind op, int r_dest_src);
-    LIR* OpRegCopy(int r_dest, int r_src);
-    LIR* OpRegCopyNoInsert(int r_dest, int r_src);
-    LIR* OpRegImm(OpKind op, int r_dest_src1, int value);
-    LIR* OpRegMem(OpKind op, int r_dest, int rBase, int offset);
+    LIR* OpMem(OpKind op, RegStorage r_base, int disp);
+    LIR* OpPcRelLoad(RegStorage reg, LIR* target);
+    LIR* OpReg(OpKind op, RegStorage r_dest_src);
+    LIR* OpRegCopy(RegStorage r_dest, RegStorage r_src);
+    LIR* OpRegCopyNoInsert(RegStorage r_dest, RegStorage r_src);
+    LIR* OpRegImm(OpKind op, RegStorage r_dest_src1, int value);
+    LIR* OpRegMem(OpKind op, RegStorage r_dest, RegStorage r_base, int offset);
+    LIR* OpRegMem(OpKind op, RegStorage r_dest, RegLocation value);
     LIR* OpMemReg(OpKind op, RegLocation rl_dest, int value);
-    LIR* OpRegMem(OpKind op, int r_dest, RegLocation value);
-    LIR* OpRegReg(OpKind op, int r_dest_src1, int r_src2);
-    LIR* OpMovRegMem(int r_dest, int r_base, int offset, MoveType move_type);
-    LIR* OpMovMemReg(int r_base, int offset, int r_src, MoveType move_type);
-    LIR* OpCondRegReg(OpKind op, ConditionCode cc, int r_dest, int r_src);
-    LIR* OpRegRegImm(OpKind op, int r_dest, int r_src1, int value);
-    LIR* OpRegRegReg(OpKind op, int r_dest, int r_src1, int r_src2);
+    LIR* OpRegReg(OpKind op, RegStorage r_dest_src1, RegStorage r_src2);
+    LIR* OpMovRegMem(RegStorage r_dest, RegStorage r_base, int offset, MoveType move_type);
+    LIR* OpMovMemReg(RegStorage r_base, int offset, RegStorage r_src, MoveType move_type);
+    LIR* OpCondRegReg(OpKind op, ConditionCode cc, RegStorage r_dest, RegStorage r_src);
+    LIR* OpRegRegImm(OpKind op, RegStorage r_dest, RegStorage r_src1, int value);
+    LIR* OpRegRegReg(OpKind op, RegStorage r_dest, RegStorage r_src1, RegStorage r_src2);
     LIR* OpTestSuspend(LIR* target);
     LIR* OpThreadMem(OpKind op, ThreadOffset thread_offset);
-    LIR* OpVldm(int rBase, int count);
-    LIR* OpVstm(int rBase, int count);
-    void OpLea(int rBase, int reg1, int reg2, int scale, int offset);
-    void OpRegCopyWide(int dest_lo, int dest_hi, int src_lo, int src_hi);
+    LIR* OpVldm(RegStorage r_base, int count);
+    LIR* OpVstm(RegStorage r_base, int count);
+    void OpLea(RegStorage r_base, RegStorage reg1, RegStorage reg2, int scale, int offset);
+    void OpRegCopyWide(RegStorage dest, RegStorage src);
     void OpTlsCmp(ThreadOffset offset, int val);
 
     void OpRegThreadMem(OpKind op, int r_dest, ThreadOffset thread_offset);
@@ -254,7 +264,7 @@
     RegLocation UpdateLocWide(RegLocation loc);
     RegLocation EvalLocWide(RegLocation loc, int reg_class, bool update);
     RegLocation EvalLoc(RegLocation loc, int reg_class, bool update);
-    int AllocTempDouble();
+    RegStorage AllocTempDouble();
     void ResetDefLocWide(RegLocation rl);
 
     /*
@@ -264,8 +274,8 @@
      * @param rl_lhs Left hand operand.
      * @param rl_rhs Right hand operand.
      */
-    void GenArithOpInt(Instruction::Code opcode, RegLocation rl_dest,
-                       RegLocation rl_lhs, RegLocation rl_rhs);
+    void GenArithOpInt(Instruction::Code opcode, RegLocation rl_dest, RegLocation rl_lhs,
+                       RegLocation rl_rhs);
 
     /*
      * @brief Dump a RegLocation using printf
@@ -327,8 +337,7 @@
     void EmitOpRegOpcode(const X86EncodingMap* entry, uint8_t reg);
     void EmitOpReg(const X86EncodingMap* entry, uint8_t reg);
     void EmitOpMem(const X86EncodingMap* entry, uint8_t base, int disp);
-    void EmitOpArray(const X86EncodingMap* entry, uint8_t base, uint8_t index,
-                     int scale, int disp);
+    void EmitOpArray(const X86EncodingMap* entry, uint8_t base, uint8_t index, int scale, int disp);
     void EmitMemReg(const X86EncodingMap* entry, uint8_t base, int disp, uint8_t reg);
     void EmitMemImm(const X86EncodingMap* entry, uint8_t base, int disp, int32_t imm);
     void EmitRegMem(const X86EncodingMap* entry, uint8_t reg, uint8_t base, int disp);
@@ -340,7 +349,8 @@
     void EmitRegReg(const X86EncodingMap* entry, uint8_t reg1, uint8_t reg2);
     void EmitRegRegImm(const X86EncodingMap* entry, uint8_t reg1, uint8_t reg2, int32_t imm);
     void EmitRegRegImmRev(const X86EncodingMap* entry, uint8_t reg1, uint8_t reg2, int32_t imm);
-    void EmitRegMemImm(const X86EncodingMap* entry, uint8_t reg1, uint8_t base, int disp, int32_t imm);
+    void EmitRegMemImm(const X86EncodingMap* entry, uint8_t reg1, uint8_t base, int disp,
+                       int32_t imm);
     void EmitRegImm(const X86EncodingMap* entry, uint8_t reg, int imm);
     void EmitThreadImm(const X86EncodingMap* entry, int disp, int imm);
     void EmitMovRegImm(const X86EncodingMap* entry, uint8_t reg, int imm);
@@ -429,8 +439,8 @@
      * @param is_div 'true' if this is a division, 'false' for a remainder.
      * @param check_zero 'true' if an exception should be generated if the divisor is 0.
      */
-    RegLocation GenDivRem(RegLocation rl_dest, RegLocation rl_src1,
-                                  RegLocation rl_src2, bool is_div, bool check_zero);
+    RegLocation GenDivRem(RegLocation rl_dest, RegLocation rl_src1, RegLocation rl_src2,
+                          bool is_div, bool check_zero);
 
     /*
      * @brief Generate an integer div or rem operation by a literal.
@@ -457,7 +467,7 @@
      * @param src Source Register.
      * @param val Constant multiplier.
      */
-    void GenImulRegImm(int dest, int src, int val);
+    void GenImulRegImm(RegStorage dest, RegStorage src, int val);
 
     /*
      * Generate an imul of a memory location by a constant or a better sequence.
@@ -466,7 +476,7 @@
      * @param displacement Displacement on stack of Symbolic Register.
      * @param val Constant multiplier.
      */
-    void GenImulMemImm(int dest, int sreg, int displacement, int val);
+    void GenImulMemImm(RegStorage dest, int sreg, int displacement, int val);
 
     /*
      * @brief Compare memory to immediate, and branch if condition true.
@@ -477,7 +487,7 @@
      * @param offset The offset from the base.
      * @param check_value The immediate to compare to.
      */
-    LIR* OpCmpMemImmBranch(ConditionCode cond, int temp_reg, int base_reg,
+    LIR* OpCmpMemImmBranch(ConditionCode cond, RegStorage temp_reg, RegStorage base_reg,
                            int offset, int check_value, LIR* target);
 
     /*
diff --git a/compiler/dex/quick/x86/fp_x86.cc b/compiler/dex/quick/x86/fp_x86.cc
index b745207..ec4d9db 100644
--- a/compiler/dex/quick/x86/fp_x86.cc
+++ b/compiler/dex/quick/x86/fp_x86.cc
@@ -63,15 +63,15 @@
   rl_src1 = LoadValue(rl_src1, kFPReg);
   rl_src2 = LoadValue(rl_src2, kFPReg);
   rl_result = EvalLoc(rl_dest, kFPReg, true);
-  int r_dest = rl_result.reg.GetReg();
-  int r_src1 = rl_src1.reg.GetReg();
-  int r_src2 = rl_src2.reg.GetReg();
+  RegStorage r_dest = rl_result.reg;
+  RegStorage r_src1 = rl_src1.reg;
+  RegStorage r_src2 = rl_src2.reg;
   if (r_dest == r_src2) {
     r_src2 = AllocTempFloat();
     OpRegCopy(r_src2, r_dest);
   }
   OpRegCopy(r_dest, r_src1);
-  NewLIR2(op, r_dest, r_src2);
+  NewLIR2(op, r_dest.GetReg(), r_src2.GetReg());
   StoreValue(rl_dest, rl_result);
 }
 
@@ -118,14 +118,15 @@
   rl_result = EvalLoc(rl_dest, kFPReg, true);
   DCHECK(rl_dest.wide);
   DCHECK(rl_result.wide);
-  int r_dest = S2d(rl_result.reg.GetReg(), rl_result.reg.GetHighReg());
-  int r_src1 = S2d(rl_src1.reg.GetReg(), rl_src1.reg.GetHighReg());
-  int r_src2 = S2d(rl_src2.reg.GetReg(), rl_src2.reg.GetHighReg());
+  // TODO: update with direct 64-bit reg.
+  int r_dest = S2d(rl_result.reg.GetLowReg(), rl_result.reg.GetHighReg());
+  int r_src1 = S2d(rl_src1.reg.GetLowReg(), rl_src1.reg.GetHighReg());
+  int r_src2 = S2d(rl_src2.reg.GetLowReg(), rl_src2.reg.GetHighReg());
   if (r_dest == r_src2) {
-    r_src2 = AllocTempDouble() | X86_FP_DOUBLE;
-    OpRegCopy(r_src2, r_dest);
+    r_src2 = AllocTempDouble().GetLowReg() | X86_FP_DOUBLE;
+    OpRegCopy(RegStorage::Solo64(r_src2), RegStorage::Solo64(r_dest));
   }
-  OpRegCopy(r_dest, r_src1);
+  OpRegCopy(RegStorage::Solo64(r_dest), RegStorage::Solo64(r_src1));
   NewLIR2(op, r_dest, r_src2);
   StoreValueWide(rl_dest, rl_result);
 }
@@ -140,7 +141,7 @@
 
   // If the source is in physical register, then put it in its location on stack.
   if (rl_src.location == kLocPhysReg) {
-    RegisterInfo* lo_info = GetRegInfo(rl_src.reg.GetReg());
+    RegisterInfo* lo_info = GetRegInfo(rl_src.reg.GetLowReg());
 
     if (lo_info != nullptr && lo_info->is_temp) {
       // Calling FlushSpecificReg because it will only write back VR if it is dirty.
@@ -148,19 +149,19 @@
     } else {
       // It must have been register promoted if it is not a temp but is still in physical
       // register. Since we need it to be in memory to convert, we place it there now.
-      StoreBaseDispWide(TargetReg(kSp), src_v_reg_offset, rl_src.reg.GetReg(), rl_src.reg.GetHighReg());
+      StoreBaseDispWide(TargetReg(kSp), src_v_reg_offset, rl_src.reg);
     }
   }
 
   // Push the source virtual register onto the x87 stack.
-  LIR *fild64 = NewLIR2NoDest(kX86Fild64M, TargetReg(kSp), src_v_reg_offset + LOWORD_OFFSET);
+  LIR *fild64 = NewLIR2NoDest(kX86Fild64M, TargetReg(kSp).GetReg(), src_v_reg_offset + LOWORD_OFFSET);
   AnnotateDalvikRegAccess(fild64, (src_v_reg_offset + LOWORD_OFFSET) >> 2,
       true /* is_load */, true /* is64bit */);
 
   // Now pop off x87 stack and store it in the destination VR's stack location.
   int opcode = is_double ? kX86Fstp64M : kX86Fstp32M;
   int displacement = is_double ? dest_v_reg_offset + LOWORD_OFFSET : dest_v_reg_offset;
-  LIR *fstp = NewLIR2NoDest(opcode, TargetReg(kSp), displacement);
+  LIR *fstp = NewLIR2NoDest(opcode, TargetReg(kSp).GetReg(), displacement);
   AnnotateDalvikRegAccess(fstp, displacement >> 2, false /* is_load */, is_double);
 
   /*
@@ -181,13 +182,13 @@
     if (is_double) {
       rl_result = EvalLocWide(rl_dest, kFPReg, true);
 
-      LoadBaseDispWide(TargetReg(kSp), dest_v_reg_offset, rl_result.reg.GetReg(), rl_result.reg.GetHighReg(), INVALID_SREG);
+      LoadBaseDispWide(TargetReg(kSp), dest_v_reg_offset, rl_result.reg, INVALID_SREG);
 
       StoreFinalValueWide(rl_dest, rl_result);
     } else {
       rl_result = EvalLoc(rl_dest, kFPReg, true);
 
-      LoadWordDisp(TargetReg(kSp), dest_v_reg_offset, rl_result.reg.GetReg());
+      LoadWordDisp(TargetReg(kSp), dest_v_reg_offset, rl_result.reg);
 
       StoreFinalValue(rl_dest, rl_result);
     }
@@ -223,9 +224,9 @@
       // In case result vreg is also src vreg, break association to avoid useless copy by EvalLoc()
       ClobberSReg(rl_dest.s_reg_low);
       rl_result = EvalLoc(rl_dest, kCoreReg, true);
-      int temp_reg = AllocTempFloat();
+      int temp_reg = AllocTempFloat().GetReg();
 
-      LoadConstant(rl_result.reg.GetReg(), 0x7fffffff);
+      LoadConstant(rl_result.reg, 0x7fffffff);
       NewLIR2(kX86Cvtsi2ssRR, temp_reg, rl_result.reg.GetReg());
       NewLIR2(kX86ComissRR, src_reg, temp_reg);
       LIR* branch_pos_overflow = NewLIR2(kX86Jcc8, 0, kX86CondA);
@@ -241,13 +242,13 @@
     }
     case Instruction::DOUBLE_TO_INT: {
       rl_src = LoadValueWide(rl_src, kFPReg);
-      src_reg = rl_src.reg.GetReg();
+      src_reg = rl_src.reg.GetLowReg();
       // In case result vreg is also src vreg, break association to avoid useless copy by EvalLoc()
       ClobberSReg(rl_dest.s_reg_low);
       rl_result = EvalLoc(rl_dest, kCoreReg, true);
-      int temp_reg = AllocTempDouble() | X86_FP_DOUBLE;
+      int temp_reg = AllocTempDouble().GetLowReg() | X86_FP_DOUBLE;
 
-      LoadConstant(rl_result.reg.GetReg(), 0x7fffffff);
+      LoadConstant(rl_result.reg, 0x7fffffff);
       NewLIR2(kX86Cvtsi2sdRR, temp_reg, rl_result.reg.GetReg());
       NewLIR2(kX86ComisdRR, src_reg, temp_reg);
       LIR* branch_pos_overflow = NewLIR2(kX86Jcc8, 0, kX86CondA);
@@ -278,14 +279,14 @@
   }
   if (rl_src.wide) {
     rl_src = LoadValueWide(rl_src, rcSrc);
-    src_reg = S2d(rl_src.reg.GetReg(), rl_src.reg.GetHighReg());
+    src_reg = S2d(rl_src.reg.GetLowReg(), rl_src.reg.GetHighReg());
   } else {
     rl_src = LoadValue(rl_src, rcSrc);
     src_reg = rl_src.reg.GetReg();
   }
   if (rl_dest.wide) {
     rl_result = EvalLoc(rl_dest, kFPReg, true);
-    NewLIR2(op, S2d(rl_result.reg.GetReg(), rl_result.reg.GetHighReg()), src_reg);
+    NewLIR2(op, S2d(rl_result.reg.GetLowReg(), rl_result.reg.GetHighReg()), src_reg);
     StoreValueWide(rl_dest, rl_result);
   } else {
     rl_result = EvalLoc(rl_dest, kFPReg, true);
@@ -307,14 +308,14 @@
     src_reg2 = rl_src2.reg.GetReg();
   } else {
     rl_src1 = LoadValueWide(rl_src1, kFPReg);
-    src_reg1 = S2d(rl_src1.reg.GetReg(), rl_src1.reg.GetHighReg());
+    src_reg1 = S2d(rl_src1.reg.GetLowReg(), rl_src1.reg.GetHighReg());
     rl_src2 = LoadValueWide(rl_src2, kFPReg);
-    src_reg2 = S2d(rl_src2.reg.GetReg(), rl_src2.reg.GetHighReg());
+    src_reg2 = S2d(rl_src2.reg.GetLowReg(), rl_src2.reg.GetHighReg());
   }
   // In case result vreg is also src vreg, break association to avoid useless copy by EvalLoc()
   ClobberSReg(rl_dest.s_reg_low);
   RegLocation rl_result = EvalLoc(rl_dest, kCoreReg, true);
-  LoadConstantNoClobber(rl_result.reg.GetReg(), unordered_gt ? 1 : 0);
+  LoadConstantNoClobber(rl_result.reg, unordered_gt ? 1 : 0);
   if (single) {
     NewLIR2(kX86UcomissRR, src_reg1, src_reg2);
   } else {
@@ -357,8 +358,8 @@
     rl_src2 = mir_graph_->GetSrcWide(mir, 2);
     rl_src1 = LoadValueWide(rl_src1, kFPReg);
     rl_src2 = LoadValueWide(rl_src2, kFPReg);
-    NewLIR2(kX86UcomisdRR, S2d(rl_src1.reg.GetReg(), rl_src1.reg.GetHighReg()),
-            S2d(rl_src2.reg.GetReg(), rl_src2.reg.GetHighReg()));
+    NewLIR2(kX86UcomisdRR, S2d(rl_src1.reg.GetLowReg(), rl_src1.reg.GetHighReg()),
+            S2d(rl_src2.reg.GetLowReg(), rl_src2.reg.GetHighReg()));
   } else {
     rl_src1 = mir_graph_->GetSrc(mir, 0);
     rl_src2 = mir_graph_->GetSrc(mir, 1);
@@ -418,7 +419,7 @@
   RegLocation rl_result;
   rl_src = LoadValue(rl_src, kCoreReg);
   rl_result = EvalLoc(rl_dest, kCoreReg, true);
-  OpRegRegImm(kOpAdd, rl_result.reg.GetReg(), rl_src.reg.GetReg(), 0x80000000);
+  OpRegRegImm(kOpAdd, rl_result.reg, rl_src.reg, 0x80000000);
   StoreValue(rl_dest, rl_result);
 }
 
@@ -426,8 +427,8 @@
   RegLocation rl_result;
   rl_src = LoadValueWide(rl_src, kCoreReg);
   rl_result = EvalLoc(rl_dest, kCoreReg, true);
-  OpRegRegImm(kOpAdd, rl_result.reg.GetHighReg(), rl_src.reg.GetHighReg(), 0x80000000);
-  OpRegCopy(rl_result.reg.GetReg(), rl_src.reg.GetReg());
+  OpRegRegImm(kOpAdd, rl_result.reg.GetHigh(), rl_src.reg.GetHigh(), 0x80000000);
+  OpRegCopy(rl_result.reg, rl_src.reg);
   StoreValueWide(rl_dest, rl_result);
 }
 
@@ -436,8 +437,8 @@
   RegLocation rl_dest = InlineTargetWide(info);  // double place for result
   rl_src = LoadValueWide(rl_src, kFPReg);
   RegLocation rl_result = EvalLoc(rl_dest, kFPReg, true);
-  NewLIR2(kX86SqrtsdRR, S2d(rl_result.reg.GetReg(), rl_result.reg.GetHighReg()),
-          S2d(rl_src.reg.GetReg(), rl_src.reg.GetHighReg()));
+  NewLIR2(kX86SqrtsdRR, S2d(rl_result.reg.GetLowReg(), rl_result.reg.GetHighReg()),
+          S2d(rl_src.reg.GetLowReg(), rl_src.reg.GetHighReg()));
   StoreValueWide(rl_dest, rl_result);
   return true;
 }
diff --git a/compiler/dex/quick/x86/int_x86.cc b/compiler/dex/quick/x86/int_x86.cc
index 14278a4..37b2b37 100644
--- a/compiler/dex/quick/x86/int_x86.cc
+++ b/compiler/dex/quick/x86/int_x86.cc
@@ -26,10 +26,10 @@
 /*
  * Perform register memory operation.
  */
-LIR* X86Mir2Lir::GenRegMemCheck(ConditionCode c_code,
-                                int reg1, int base, int offset, ThrowKind kind) {
+LIR* X86Mir2Lir::GenRegMemCheck(ConditionCode c_code, RegStorage reg1, RegStorage base,
+                                int offset, ThrowKind kind) {
   LIR* tgt = RawLIR(0, kPseudoThrowTarget, kind,
-                    current_dalvik_offset_, reg1, base, offset);
+                    current_dalvik_offset_, reg1.GetReg(), base.GetReg(), offset);
   OpRegMem(kOpCmp, reg1, base, offset);
   LIR* branch = OpCondBranch(c_code, tgt);
   // Remember branch target - will process later
@@ -40,11 +40,11 @@
 /*
  * Perform a compare of memory to immediate value
  */
-LIR* X86Mir2Lir::GenMemImmedCheck(ConditionCode c_code,
-                                int base, int offset, int check_value, ThrowKind kind) {
+LIR* X86Mir2Lir::GenMemImmedCheck(ConditionCode c_code, RegStorage base, int offset,
+                                  int check_value, ThrowKind kind) {
   LIR* tgt = RawLIR(0, kPseudoThrowTarget, kind,
-                    current_dalvik_offset_, base, check_value, 0);
-  NewLIR3(IS_SIMM8(check_value) ? kX86Cmp32MI8 : kX86Cmp32MI, base, offset, check_value);
+                    current_dalvik_offset_, base.GetReg(), check_value, 0);
+  NewLIR3(IS_SIMM8(check_value) ? kX86Cmp32MI8 : kX86Cmp32MI, base.GetReg(), offset, check_value);
   LIR* branch = OpCondBranch(c_code, tgt);
   // Remember branch target - will process later
   throw_launchpads_.Insert(tgt);
@@ -61,18 +61,20 @@
                             RegLocation rl_src2) {
   FlushAllRegs();
   LockCallTemps();  // Prepare for explicit register usage
-  LoadValueDirectWideFixed(rl_src1, r0, r1);
-  LoadValueDirectWideFixed(rl_src2, r2, r3);
+  RegStorage r_tmp1(RegStorage::k64BitPair, r0, r1);
+  RegStorage r_tmp2(RegStorage::k64BitPair, r2, r3);
+  LoadValueDirectWideFixed(rl_src1, r_tmp1);
+  LoadValueDirectWideFixed(rl_src2, r_tmp2);
   // Compute (r1:r0) = (r1:r0) - (r3:r2)
-  OpRegReg(kOpSub, r0, r2);  // r0 = r0 - r2
-  OpRegReg(kOpSbc, r1, r3);  // r1 = r1 - r3 - CF
+  OpRegReg(kOpSub, rs_r0, rs_r2);  // r0 = r0 - r2
+  OpRegReg(kOpSbc, rs_r1, rs_r3);  // r1 = r1 - r3 - CF
   NewLIR2(kX86Set8R, r2, kX86CondL);  // r2 = (r1:r0) < (r3:r2) ? 1 : 0
   NewLIR2(kX86Movzx8RR, r2, r2);
-  OpReg(kOpNeg, r2);         // r2 = -r2
-  OpRegReg(kOpOr, r0, r1);   // r0 = high | low - sets ZF
+  OpReg(kOpNeg, rs_r2);         // r2 = -r2
+  OpRegReg(kOpOr, rs_r0, rs_r1);   // r0 = high | low - sets ZF
   NewLIR2(kX86Set8R, r0, kX86CondNz);  // r0 = (r1:r0) != (r3:r2) ? 1 : 0
   NewLIR2(kX86Movzx8RR, r0, r0);
-  OpRegReg(kOpOr, r0, r2);   // r0 = r0 | r2
+  OpRegReg(kOpOr, rs_r0, rs_r2);   // r0 = r0 | r2
   RegLocation rl_result = LocCReturn();
   StoreValue(rl_dest, rl_result);
 }
@@ -101,9 +103,8 @@
   return kX86CondO;
 }
 
-LIR* X86Mir2Lir::OpCmpBranch(ConditionCode cond, int src1, int src2,
-                             LIR* target) {
-  NewLIR2(kX86Cmp32RR, src1, src2);
+LIR* X86Mir2Lir::OpCmpBranch(ConditionCode cond, RegStorage src1, RegStorage src2, LIR* target) {
+  NewLIR2(kX86Cmp32RR, src1.GetReg(), src2.GetReg());
   X86ConditionCode cc = X86ConditionEncoding(cond);
   LIR* branch = NewLIR2(kX86Jcc8, 0 /* lir operand for Jcc offset */ ,
                         cc);
@@ -111,13 +112,13 @@
   return branch;
 }
 
-LIR* X86Mir2Lir::OpCmpImmBranch(ConditionCode cond, int reg,
+LIR* X86Mir2Lir::OpCmpImmBranch(ConditionCode cond, RegStorage reg,
                                 int check_value, LIR* target) {
   if ((check_value == 0) && (cond == kCondEq || cond == kCondNe)) {
     // TODO: when check_value == 0 and reg is rCX, use the jcxz/nz opcode
-    NewLIR2(kX86Test32RR, reg, reg);
+    NewLIR2(kX86Test32RR, reg.GetReg(), reg.GetReg());
   } else {
-    NewLIR2(IS_SIMM8(check_value) ? kX86Cmp32RI8 : kX86Cmp32RI, reg, check_value);
+    NewLIR2(IS_SIMM8(check_value) ? kX86Cmp32RI8 : kX86Cmp32RI, reg.GetReg(), check_value);
   }
   X86ConditionCode cc = X86ConditionEncoding(cond);
   LIR* branch = NewLIR2(kX86Jcc8, 0 /* lir operand for Jcc offset */ , cc);
@@ -125,61 +126,70 @@
   return branch;
 }
 
-LIR* X86Mir2Lir::OpRegCopyNoInsert(int r_dest, int r_src) {
-  if (X86_FPREG(r_dest) || X86_FPREG(r_src))
+LIR* X86Mir2Lir::OpRegCopyNoInsert(RegStorage r_dest, RegStorage r_src) {
+  // If src or dest is a pair, we'll be using low reg.
+  if (r_dest.IsPair()) {
+    r_dest = r_dest.GetLow();
+  }
+  if (r_src.IsPair()) {
+    r_src = r_src.GetLow();
+  }
+  if (X86_FPREG(r_dest.GetReg()) || X86_FPREG(r_src.GetReg()))
     return OpFpRegCopy(r_dest, r_src);
   LIR* res = RawLIR(current_dalvik_offset_, kX86Mov32RR,
-                    r_dest, r_src);
+                    r_dest.GetReg(), r_src.GetReg());
   if (!(cu_->disable_opt & (1 << kSafeOptimizations)) && r_dest == r_src) {
     res->flags.is_nop = true;
   }
   return res;
 }
 
-LIR* X86Mir2Lir::OpRegCopy(int r_dest, int r_src) {
+LIR* X86Mir2Lir::OpRegCopy(RegStorage r_dest, RegStorage r_src) {
   LIR *res = OpRegCopyNoInsert(r_dest, r_src);
   AppendLIR(res);
   return res;
 }
 
-void X86Mir2Lir::OpRegCopyWide(int dest_lo, int dest_hi,
-                               int src_lo, int src_hi) {
-  bool dest_fp = X86_FPREG(dest_lo) && X86_FPREG(dest_hi);
-  bool src_fp = X86_FPREG(src_lo) && X86_FPREG(src_hi);
-  assert(X86_FPREG(src_lo) == X86_FPREG(src_hi));
-  assert(X86_FPREG(dest_lo) == X86_FPREG(dest_hi));
+void X86Mir2Lir::OpRegCopyWide(RegStorage r_dest, RegStorage r_src) {
+  // FIXME: handle k64BitSolo when we start using them.
+  DCHECK(r_dest.IsPair());
+  DCHECK(r_src.IsPair());
+  bool dest_fp = X86_FPREG(r_dest.GetLowReg());
+  bool src_fp = X86_FPREG(r_src.GetLowReg());
   if (dest_fp) {
     if (src_fp) {
-      OpRegCopy(S2d(dest_lo, dest_hi), S2d(src_lo, src_hi));
+      // TODO: we ought to handle this case here - reserve OpRegCopy for 32-bit copies.
+      OpRegCopy(RegStorage::Solo64(S2d(r_dest.GetLowReg(), r_dest.GetHighReg())),
+                RegStorage::Solo64(S2d(r_src.GetLowReg(), r_src.GetHighReg())));
     } else {
       // TODO: Prevent this from happening in the code. The result is often
       // unused or could have been loaded more easily from memory.
-      NewLIR2(kX86MovdxrRR, dest_lo, src_lo);
-      dest_hi = AllocTempDouble();
-      NewLIR2(kX86MovdxrRR, dest_hi, src_hi);
-      NewLIR2(kX86PunpckldqRR, dest_lo, dest_hi);
-      FreeTemp(dest_hi);
+      NewLIR2(kX86MovdxrRR, r_dest.GetLowReg(), r_src.GetLowReg());
+      RegStorage r_tmp = AllocTempDouble();
+      NewLIR2(kX86MovdxrRR, r_tmp.GetLowReg(), r_src.GetHighReg());
+      NewLIR2(kX86PunpckldqRR, r_dest.GetLowReg(), r_tmp.GetLowReg());
+      FreeTemp(r_tmp);
     }
   } else {
     if (src_fp) {
-      NewLIR2(kX86MovdrxRR, dest_lo, src_lo);
-      NewLIR2(kX86PsrlqRI, src_lo, 32);
-      NewLIR2(kX86MovdrxRR, dest_hi, src_lo);
+      NewLIR2(kX86MovdrxRR, r_dest.GetLowReg(), r_src.GetLowReg());
+      NewLIR2(kX86PsrlqRI, r_src.GetLowReg(), 32);
+      NewLIR2(kX86MovdrxRR, r_dest.GetHighReg(), r_src.GetLowReg());
     } else {
       // Handle overlap
-      if (src_hi == dest_lo && src_lo == dest_hi) {
+      if (r_src.GetHighReg() == r_dest.GetLowReg() && r_src.GetLowReg() == r_dest.GetHighReg()) {
         // Deal with cycles.
-        int temp_reg = AllocTemp();
-        OpRegCopy(temp_reg, dest_hi);
-        OpRegCopy(dest_hi, dest_lo);
-        OpRegCopy(dest_lo, temp_reg);
+        RegStorage temp_reg = AllocTemp();
+        OpRegCopy(temp_reg, r_dest.GetHigh());
+        OpRegCopy(r_dest.GetHigh(), r_dest.GetLow());
+        OpRegCopy(r_dest.GetLow(), temp_reg);
         FreeTemp(temp_reg);
-      } else if (src_hi == dest_lo) {
-        OpRegCopy(dest_hi, src_hi);
-        OpRegCopy(dest_lo, src_lo);
+      } else if (r_src.GetHighReg() == r_dest.GetLowReg()) {
+        OpRegCopy(r_dest.GetHigh(), r_src.GetHigh());
+        OpRegCopy(r_dest.GetLow(), r_src.GetLow());
       } else {
-        OpRegCopy(dest_lo, src_lo);
-        OpRegCopy(dest_hi, src_hi);
+        OpRegCopy(r_dest.GetLow(), r_src.GetLow());
+        OpRegCopy(r_dest.GetHigh(), r_src.GetHigh());
       }
     }
   }
@@ -219,30 +229,31 @@
      *     mov t1, $true_case
      *     cmovz result_reg, t1
      */
-    const bool result_reg_same_as_src = (rl_src.location == kLocPhysReg && rl_src.reg.GetReg() == rl_result.reg.GetReg());
+    const bool result_reg_same_as_src =
+        (rl_src.location == kLocPhysReg && rl_src.reg.GetReg() == rl_result.reg.GetReg());
     const bool true_zero_case = (true_val == 0 && false_val != 0 && !result_reg_same_as_src);
     const bool false_zero_case = (false_val == 0 && true_val != 0 && !result_reg_same_as_src);
     const bool catch_all_case = !(true_zero_case || false_zero_case);
 
     if (true_zero_case || false_zero_case) {
-      OpRegReg(kOpXor, rl_result.reg.GetReg(), rl_result.reg.GetReg());
+      OpRegReg(kOpXor, rl_result.reg, rl_result.reg);
     }
 
     if (true_zero_case || false_zero_case || catch_all_case) {
-      OpRegImm(kOpCmp, rl_src.reg.GetReg(), 0);
+      OpRegImm(kOpCmp, rl_src.reg, 0);
     }
 
     if (catch_all_case) {
-      OpRegImm(kOpMov, rl_result.reg.GetReg(), false_val);
+      OpRegImm(kOpMov, rl_result.reg, false_val);
     }
 
     if (true_zero_case || false_zero_case || catch_all_case) {
       ConditionCode cc = true_zero_case ? NegateComparison(ccode) : ccode;
       int immediateForTemp = true_zero_case ? false_val : true_val;
-      int temp1_reg = AllocTemp();
+      RegStorage temp1_reg = AllocTemp();
       OpRegImm(kOpMov, temp1_reg, immediateForTemp);
 
-      OpCondRegReg(kOpCmov, cc, rl_result.reg.GetReg(), temp1_reg);
+      OpCondRegReg(kOpCmov, cc, rl_result.reg, temp1_reg);
 
       FreeTemp(temp1_reg);
     }
@@ -269,15 +280,15 @@
      */
 
     // kMirOpSelect is generated just for conditional cases when comparison is done with zero.
-    OpRegImm(kOpCmp, rl_src.reg.GetReg(), 0);
+    OpRegImm(kOpCmp, rl_src.reg, 0);
 
     if (rl_result.reg.GetReg() == rl_true.reg.GetReg()) {
-      OpCondRegReg(kOpCmov, NegateComparison(ccode), rl_result.reg.GetReg(), rl_false.reg.GetReg());
+      OpCondRegReg(kOpCmov, NegateComparison(ccode), rl_result.reg, rl_false.reg);
     } else if (rl_result.reg.GetReg() == rl_false.reg.GetReg()) {
-      OpCondRegReg(kOpCmov, ccode, rl_result.reg.GetReg(), rl_true.reg.GetReg());
+      OpCondRegReg(kOpCmov, ccode, rl_result.reg, rl_true.reg);
     } else {
-      OpRegCopy(rl_result.reg.GetReg(), rl_false.reg.GetReg());
-      OpCondRegReg(kOpCmov, ccode, rl_result.reg.GetReg(), rl_true.reg.GetReg());
+      OpRegCopy(rl_result.reg, rl_false.reg);
+      OpCondRegReg(kOpCmov, ccode, rl_result.reg, rl_true.reg);
     }
   }
 
@@ -303,22 +314,24 @@
 
   FlushAllRegs();
   LockCallTemps();  // Prepare for explicit register usage
-  LoadValueDirectWideFixed(rl_src1, r0, r1);
-  LoadValueDirectWideFixed(rl_src2, r2, r3);
+  RegStorage r_tmp1(RegStorage::k64BitPair, r0, r1);
+  RegStorage r_tmp2(RegStorage::k64BitPair, r2, r3);
+  LoadValueDirectWideFixed(rl_src1, r_tmp1);
+  LoadValueDirectWideFixed(rl_src2, r_tmp2);
   // Swap operands and condition code to prevent use of zero flag.
   if (ccode == kCondLe || ccode == kCondGt) {
     // Compute (r3:r2) = (r3:r2) - (r1:r0)
-    OpRegReg(kOpSub, r2, r0);  // r2 = r2 - r0
-    OpRegReg(kOpSbc, r3, r1);  // r3 = r3 - r1 - CF
+    OpRegReg(kOpSub, rs_r2, rs_r0);  // r2 = r2 - r0
+    OpRegReg(kOpSbc, rs_r3, rs_r1);  // r3 = r3 - r1 - CF
   } else {
     // Compute (r1:r0) = (r1:r0) - (r3:r2)
-    OpRegReg(kOpSub, r0, r2);  // r0 = r0 - r2
-    OpRegReg(kOpSbc, r1, r3);  // r1 = r1 - r3 - CF
+    OpRegReg(kOpSub, rs_r0, rs_r2);  // r0 = r0 - r2
+    OpRegReg(kOpSbc, rs_r1, rs_r3);  // r1 = r1 - r3 - CF
   }
   switch (ccode) {
     case kCondEq:
     case kCondNe:
-      OpRegReg(kOpOr, r0, r1);  // r0 = r0 | r1
+      OpRegReg(kOpOr, rs_r0, rs_r1);  // r0 = r0 | r1
       break;
     case kCondLe:
       ccode = kCondGe;
@@ -342,11 +355,11 @@
   LIR* taken = &block_label_list_[bb->taken];
   LIR* not_taken = &block_label_list_[bb->fall_through];
   rl_src1 = LoadValueWide(rl_src1, kCoreReg);
-  int32_t low_reg = rl_src1.reg.GetReg();
-  int32_t high_reg = rl_src1.reg.GetHighReg();
+  RegStorage low_reg = rl_src1.reg.GetLow();
+  RegStorage high_reg = rl_src1.reg.GetHigh();
 
   if (val == 0 && (ccode == kCondEq || ccode == kCondNe)) {
-    int t_reg = AllocTemp();
+    RegStorage t_reg = AllocTemp();
     OpRegRegReg(kOpOr, t_reg, low_reg, high_reg);
     FreeTemp(t_reg);
     OpCondBranch(ccode, taken);
@@ -450,8 +463,7 @@
   shift = p - 32;
 }
 
-RegLocation X86Mir2Lir::GenDivRemLit(RegLocation rl_dest, int reg_lo,
-                                     int lit, bool is_div) {
+RegLocation X86Mir2Lir::GenDivRemLit(RegLocation rl_dest, RegStorage reg_lo, int lit, bool is_div) {
   LOG(FATAL) << "Unexpected use of GenDivRemLit for x86";
   return rl_dest;
 }
@@ -465,8 +477,8 @@
   LockCallTemps();  // Prepare for explicit register usage.
 
   // Assume that the result will be in EDX.
-  RegLocation rl_result = {kLocPhysReg, 0, 0, 0, 0, 0, 0, 0, 1, kVectorNotUsed,
-                           RegStorage(RegStorage::k32BitSolo, r2), INVALID_SREG, INVALID_SREG};
+  RegLocation rl_result = {kLocPhysReg, 0, 0, 0, 0, 0, 0, 0, 1, kVectorNotUsed, rs_r2,
+                           INVALID_SREG, INVALID_SREG};
 
   // handle div/rem by 1 special case.
   if (imm == 1) {
@@ -475,15 +487,15 @@
       StoreValue(rl_result, rl_src);
     } else {
       // x % 1 == 0.
-      LoadConstantNoClobber(r0, 0);
+      LoadConstantNoClobber(rs_r0, 0);
       // For this case, return the result in EAX.
       rl_result.reg.SetReg(r0);
     }
   } else if (imm == -1) {  // handle 0x80000000 / -1 special case.
     if (is_div) {
       LIR *minint_branch = 0;
-      LoadValueDirectFixed(rl_src, r0);
-      OpRegImm(kOpCmp, r0, 0x80000000);
+      LoadValueDirectFixed(rl_src, rs_r0);
+      OpRegImm(kOpCmp, rs_r0, 0x80000000);
       minint_branch = NewLIR2(kX86Jcc8, 0, kX86CondEq);
 
       // for x != MIN_INT, x / -1 == -x.
@@ -496,7 +508,7 @@
       branch_around->target = NewLIR0(kPseudoTargetLabel);
     } else {
       // x % -1 == 0.
-      LoadConstantNoClobber(r0, 0);
+      LoadConstantNoClobber(rs_r0, 0);
     }
     // For this case, return the result in EAX.
     rl_result.reg.SetReg(r0);
@@ -524,36 +536,36 @@
      */
 
     // Numerator into EAX.
-    int numerator_reg = -1;
+    RegStorage numerator_reg;
     if (!is_div || (imm > 0 && magic < 0) || (imm < 0 && magic > 0)) {
       // We will need the value later.
       if (rl_src.location == kLocPhysReg) {
         // We can use it directly.
         DCHECK(rl_src.reg.GetReg() != r0 && rl_src.reg.GetReg() != r2);
-        numerator_reg = rl_src.reg.GetReg();
+        numerator_reg = rl_src.reg;
       } else {
-        LoadValueDirectFixed(rl_src, r1);
-        numerator_reg = r1;
+        numerator_reg = rs_r1;
+        LoadValueDirectFixed(rl_src, numerator_reg);
       }
-      OpRegCopy(r0, numerator_reg);
+      OpRegCopy(rs_r0, numerator_reg);
     } else {
       // Only need this once.  Just put it into EAX.
-      LoadValueDirectFixed(rl_src, r0);
+      LoadValueDirectFixed(rl_src, rs_r0);
     }
 
     // EDX = magic.
-    LoadConstantNoClobber(r2, magic);
+    LoadConstantNoClobber(rs_r2, magic);
 
     // EDX:EAX = magic & dividend.
     NewLIR1(kX86Imul32DaR, r2);
 
     if (imm > 0 && magic < 0) {
       // Add numerator to EDX.
-      DCHECK_NE(numerator_reg, -1);
-      NewLIR2(kX86Add32RR, r2, numerator_reg);
+      DCHECK(numerator_reg.Valid());
+      NewLIR2(kX86Add32RR, r2, numerator_reg.GetReg());
     } else if (imm < 0 && magic > 0) {
-      DCHECK_NE(numerator_reg, -1);
-      NewLIR2(kX86Sub32RR, r2, numerator_reg);
+      DCHECK(numerator_reg.Valid());
+      NewLIR2(kX86Sub32RR, r2, numerator_reg.GetReg());
     }
 
     // Do we need the shift?
@@ -565,7 +577,7 @@
     // Add 1 to EDX if EDX < 0.
 
     // Move EDX to EAX.
-    OpRegCopy(r0, r2);
+    OpRegCopy(rs_r0, rs_r2);
 
     // Move sign bit to bit 0, zeroing the rest.
     NewLIR2(kX86Shr32RI, r2, 31);
@@ -577,11 +589,11 @@
     if (!is_div) {
       // We need to compute the remainder.
       // Remainder is divisor - (quotient * imm).
-      DCHECK_NE(numerator_reg, -1);
-      OpRegCopy(r0, numerator_reg);
+      DCHECK(numerator_reg.Valid());
+      OpRegCopy(rs_r0, numerator_reg);
 
       // EAX = numerator * imm.
-      OpRegRegImm(kOpMul, r2, r2, imm);
+      OpRegRegImm(kOpMul, rs_r2, rs_r2, imm);
 
       // EDX -= EAX.
       NewLIR2(kX86Sub32RR, r0, r2);
@@ -594,8 +606,8 @@
   return rl_result;
 }
 
-RegLocation X86Mir2Lir::GenDivRem(RegLocation rl_dest, int reg_lo,
-                                  int reg_hi, bool is_div) {
+RegLocation X86Mir2Lir::GenDivRem(RegLocation rl_dest, RegStorage reg_lo, RegStorage reg_hi,
+                                  bool is_div) {
   LOG(FATAL) << "Unexpected use of GenDivRem for x86";
   return rl_dest;
 }
@@ -607,31 +619,31 @@
   LockCallTemps();  // Prepare for explicit register usage.
 
   // Load LHS into EAX.
-  LoadValueDirectFixed(rl_src1, r0);
+  LoadValueDirectFixed(rl_src1, rs_r0);
 
   // Load RHS into EBX.
-  LoadValueDirectFixed(rl_src2, r1);
+  LoadValueDirectFixed(rl_src2, rs_r1);
 
   // Copy LHS sign bit into EDX.
   NewLIR0(kx86Cdq32Da);
 
   if (check_zero) {
     // Handle division by zero case.
-    GenImmedCheck(kCondEq, r1, 0, kThrowDivZero);
+    GenImmedCheck(kCondEq, rs_r1, 0, kThrowDivZero);
   }
 
   // Have to catch 0x80000000/-1 case, or we will get an exception!
-  OpRegImm(kOpCmp, r1, -1);
+  OpRegImm(kOpCmp, rs_r1, -1);
   LIR *minus_one_branch = NewLIR2(kX86Jcc8, 0, kX86CondNe);
 
   // RHS is -1.
-  OpRegImm(kOpCmp, r0, 0x80000000);
+  OpRegImm(kOpCmp, rs_r0, 0x80000000);
   LIR * minint_branch = NewLIR2(kX86Jcc8, 0, kX86CondNe);
 
   // In 0x80000000/-1 case.
   if (!is_div) {
     // For DIV, EAX is already right. For REM, we need EDX 0.
-    LoadConstantNoClobber(r2, 0);
+    LoadConstantNoClobber(rs_r2, 0);
   }
   LIR* done = NewLIR1(kX86Jmp8, 0);
 
@@ -642,8 +654,8 @@
   done->target = NewLIR0(kPseudoTargetLabel);
 
   // Result is in EAX for div and EDX for rem.
-  RegLocation rl_result = {kLocPhysReg, 0, 0, 0, 0, 0, 0, 0, 1, kVectorNotUsed,
-                           RegStorage(RegStorage::k32BitSolo, r0), INVALID_SREG, INVALID_SREG};
+  RegLocation rl_result = {kLocPhysReg, 0, 0, 0, 0, 0, 0, 0, 1, kVectorNotUsed, rs_r0,
+                           INVALID_SREG, INVALID_SREG};
   if (!is_div) {
     rl_result.reg.SetReg(r2);
   }
@@ -672,17 +684,17 @@
   }
 
   // Pick the first integer as min/max.
-  OpRegCopy(rl_result.reg.GetReg(), rl_src1.reg.GetReg());
+  OpRegCopy(rl_result.reg, rl_src1.reg);
 
   // If the integers are both in the same register, then there is nothing else to do
   // because they are equal and we have already moved one into the result.
   if (rl_src1.reg.GetReg() != rl_src2.reg.GetReg()) {
     // It is possible we didn't pick correctly so do the actual comparison now.
-    OpRegReg(kOpCmp, rl_src1.reg.GetReg(), rl_src2.reg.GetReg());
+    OpRegReg(kOpCmp, rl_src1.reg, rl_src2.reg);
 
     // Conditionally move the other integer into the destination register.
     ConditionCode condition_code = is_min ? kCondGt : kCondLt;
-    OpCondRegReg(kOpCmov, condition_code, rl_result.reg.GetReg(), rl_src2.reg.GetReg());
+    OpCondRegReg(kOpCmov, condition_code, rl_result.reg, rl_src2.reg);
   }
 
   StoreValue(rl_dest, rl_result);
@@ -691,18 +703,18 @@
 
 bool X86Mir2Lir::GenInlinedPeek(CallInfo* info, OpSize size) {
   RegLocation rl_src_address = info->args[0];  // long address
-  rl_src_address.wide = 0;  // ignore high half in info->args[1]
+  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_address = LoadValue(rl_src_address, kCoreReg);
   RegLocation rl_result = EvalLoc(rl_dest, kCoreReg, true);
   if (size == kLong) {
     // Unaligned access is allowed on x86.
-    LoadBaseDispWide(rl_address.reg.GetReg(), 0, rl_result.reg.GetReg(), rl_result.reg.GetHighReg(), INVALID_SREG);
+    LoadBaseDispWide(rl_address.reg, 0, rl_result.reg, INVALID_SREG);
     StoreValueWide(rl_dest, rl_result);
   } else {
     DCHECK(size == kSignedByte || size == kSignedHalf || size == kWord);
     // Unaligned access is allowed on x86.
-    LoadBaseDisp(rl_address.reg.GetReg(), 0, rl_result.reg.GetReg(), size, INVALID_SREG);
+    LoadBaseDisp(rl_address.reg, 0, rl_result.reg, size, INVALID_SREG);
     StoreValue(rl_dest, rl_result);
   }
   return true;
@@ -710,32 +722,32 @@
 
 bool X86Mir2Lir::GenInlinedPoke(CallInfo* info, OpSize size) {
   RegLocation rl_src_address = info->args[0];  // long address
-  rl_src_address.wide = 0;  // ignore high half in info->args[1]
+  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) {
     // Unaligned access is allowed on x86.
     RegLocation rl_value = LoadValueWide(rl_src_value, kCoreReg);
-    StoreBaseDispWide(rl_address.reg.GetReg(), 0, rl_value.reg.GetReg(), rl_value.reg.GetHighReg());
+    StoreBaseDispWide(rl_address.reg, 0, rl_value.reg);
   } else {
     DCHECK(size == kSignedByte || size == kSignedHalf || size == kWord);
     // Unaligned access is allowed on x86.
     RegLocation rl_value = LoadValue(rl_src_value, kCoreReg);
-    StoreBaseDisp(rl_address.reg.GetReg(), 0, rl_value.reg.GetReg(), size);
+    StoreBaseDisp(rl_address.reg, 0, rl_value.reg, size);
   }
   return true;
 }
 
-void X86Mir2Lir::OpLea(int rBase, int reg1, int reg2, int scale, int offset) {
-  NewLIR5(kX86Lea32RA, rBase, reg1, reg2, scale, offset);
+void X86Mir2Lir::OpLea(RegStorage r_base, RegStorage reg1, RegStorage reg2, int scale, int offset) {
+  NewLIR5(kX86Lea32RA, r_base.GetReg(), reg1.GetReg(), reg2.GetReg(), scale, offset);
 }
 
 void X86Mir2Lir::OpTlsCmp(ThreadOffset offset, int val) {
   NewLIR2(kX86Cmp16TI8, offset.Int32Value(), val);
 }
 
-static bool IsInReg(X86Mir2Lir *pMir2Lir, const RegLocation &rl, int reg) {
-  return !rl.reg.IsInvalid() && rl.reg.GetReg() == reg && (pMir2Lir->IsLive(reg) || rl.home);
+static bool IsInReg(X86Mir2Lir *pMir2Lir, const RegLocation &rl, RegStorage reg) {
+  return rl.reg.Valid() && rl.reg.GetReg() == reg.GetReg() && (pMir2Lir->IsLive(reg) || rl.home);
 }
 
 bool X86Mir2Lir::GenInlinedCas(CallInfo* info, bool is_long, bool is_object) {
@@ -743,7 +755,7 @@
   // Unused - RegLocation rl_src_unsafe = info->args[0];
   RegLocation rl_src_obj = info->args[1];  // Object - known non-null
   RegLocation rl_src_offset = info->args[2];  // long low
-  rl_src_offset.wide = 0;  // ignore high half in info->args[3]
+  rl_src_offset = NarrowRegLoc(rl_src_offset);  // ignore high half in info->args[3]
   RegLocation rl_src_expected = info->args[4];  // int, long or Object
   // If is_long, high half is in info->args[5]
   RegLocation rl_src_new_value = info->args[is_long ? 6 : 5];  // int, long or Object
@@ -754,8 +766,10 @@
     // TODO: CFI support.
     FlushAllRegs();
     LockCallTemps();
-    LoadValueDirectWideFixed(rl_src_expected, rAX, rDX);
-    LoadValueDirectWideFixed(rl_src_new_value, rBX, rCX);
+    RegStorage r_tmp1(RegStorage::k64BitPair, rAX, rDX);
+    RegStorage r_tmp2(RegStorage::k64BitPair, rBX, rCX);
+    LoadValueDirectWideFixed(rl_src_expected, r_tmp1);
+    LoadValueDirectWideFixed(rl_src_new_value, r_tmp2);
     NewLIR1(kX86Push32R, rDI);
     MarkTemp(rDI);
     LockTemp(rDI);
@@ -763,14 +777,14 @@
     MarkTemp(rSI);
     LockTemp(rSI);
     const int push_offset = 4 /* push edi */ + 4 /* push esi */;
-    int srcObjSp = IsInReg(this, rl_src_obj, rSI) ? 0
-                : (IsInReg(this, rl_src_obj, rDI) ? 4
+    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));
-    LoadWordDisp(TargetReg(kSp), srcObjSp, rDI);
-    int srcOffsetSp = IsInReg(this, rl_src_offset, rSI) ? 0
-                   : (IsInReg(this, rl_src_offset, rDI) ? 4
+    LoadWordDisp(TargetReg(kSp), srcObjSp, rs_rDI);
+    int srcOffsetSp = IsInReg(this, rl_src_offset, rs_rSI) ? 0
+                   : (IsInReg(this, rl_src_offset, rs_rDI) ? 4
                    : (SRegOffset(rl_src_offset.s_reg_low) + push_offset));
-    LoadWordDisp(TargetReg(kSp), srcOffsetSp, rSI);
+    LoadWordDisp(TargetReg(kSp), srcOffsetSp, rs_rSI);
     NewLIR4(kX86LockCmpxchg8bA, rDI, rSI, 0, 0);
 
     // After a store we need to insert barrier in case of potential load. Since the
@@ -786,8 +800,8 @@
     FreeCallTemps();
   } else {
     // EAX must hold expected for CMPXCHG. Neither rl_new_value, nor r_ptr may be in EAX.
-    FlushReg(r0);
-    LockTemp(r0);
+    FlushReg(rs_r0);
+    LockTemp(rs_r0);
 
     RegLocation rl_object = LoadValue(rl_src_obj, kCoreReg);
     RegLocation rl_new_value = LoadValue(rl_src_new_value, kCoreReg);
@@ -795,12 +809,12 @@
     if (is_object && !mir_graph_->IsConstantNullRef(rl_new_value)) {
       // Mark card for object assuming new value is stored.
       FreeTemp(r0);  // Temporarily release EAX for MarkGCCard().
-      MarkGCCard(rl_new_value.reg.GetReg(), rl_object.reg.GetReg());
+      MarkGCCard(rl_new_value.reg, rl_object.reg);
       LockTemp(r0);
     }
 
     RegLocation rl_offset = LoadValue(rl_src_offset, kCoreReg);
-    LoadValueDirect(rl_src_expected, r0);
+    LoadValueDirect(rl_src_expected, rs_r0);
     NewLIR5(kX86LockCmpxchgAR, rl_object.reg.GetReg(), rl_offset.reg.GetReg(), 0, 0, rl_new_value.reg.GetReg());
 
     // After a store we need to insert barrier in case of potential load. Since the
@@ -819,7 +833,7 @@
   return true;
 }
 
-LIR* X86Mir2Lir::OpPcRelLoad(int reg, LIR* target) {
+LIR* X86Mir2Lir::OpPcRelLoad(RegStorage reg, LIR* target) {
   CHECK(base_of_code_ != nullptr);
 
   // Address the start of the method
@@ -831,7 +845,8 @@
   // We don't know the proper offset for the value, so pick one that will force
   // 4 byte offset.  We will fix this up in the assembler later to have the right
   // value.
-  LIR *res = RawLIR(current_dalvik_offset_, kX86Mov32RM, reg, reg, 256, 0, 0, target);
+  LIR *res = RawLIR(current_dalvik_offset_, kX86Mov32RM, reg.GetReg(), reg.GetReg(), 256,
+                    0, 0, target);
   res->target = target;
   res->flags.fixup = kFixupLoad;
   SetMemRefType(res, true, kLiteral);
@@ -839,12 +854,12 @@
   return res;
 }
 
-LIR* X86Mir2Lir::OpVldm(int rBase, int count) {
+LIR* X86Mir2Lir::OpVldm(RegStorage r_base, int count) {
   LOG(FATAL) << "Unexpected use of OpVldm for x86";
   return NULL;
 }
 
-LIR* X86Mir2Lir::OpVstm(int rBase, int count) {
+LIR* X86Mir2Lir::OpVstm(RegStorage r_base, int count) {
   LOG(FATAL) << "Unexpected use of OpVstm for x86";
   return NULL;
 }
@@ -852,22 +867,22 @@
 void X86Mir2Lir::GenMultiplyByTwoBitMultiplier(RegLocation rl_src,
                                                RegLocation rl_result, int lit,
                                                int first_bit, int second_bit) {
-  int t_reg = AllocTemp();
-  OpRegRegImm(kOpLsl, t_reg, rl_src.reg.GetReg(), second_bit - first_bit);
-  OpRegRegReg(kOpAdd, rl_result.reg.GetReg(), rl_src.reg.GetReg(), t_reg);
+  RegStorage t_reg = AllocTemp();
+  OpRegRegImm(kOpLsl, t_reg, rl_src.reg, second_bit - first_bit);
+  OpRegRegReg(kOpAdd, rl_result.reg, rl_src.reg, t_reg);
   FreeTemp(t_reg);
   if (first_bit != 0) {
-    OpRegRegImm(kOpLsl, rl_result.reg.GetReg(), rl_result.reg.GetReg(), first_bit);
+    OpRegRegImm(kOpLsl, rl_result.reg, rl_result.reg, first_bit);
   }
 }
 
-void X86Mir2Lir::GenDivZeroCheck(int reg_lo, int reg_hi) {
-  // We are not supposed to clobber either of the provided registers, so allocate
-  // a temporary to use for the check.
-  int t_reg = AllocTemp();
+void X86Mir2Lir::GenDivZeroCheck(RegStorage reg) {
+  DCHECK(reg.IsPair());  // TODO: allow 64BitSolo.
+  // We are not supposed to clobber the incoming storage, so allocate a temporary.
+  RegStorage t_reg = AllocTemp();
 
   // Doing an OR is a quick way to check if both registers are zero. This will set the flags.
-  OpRegRegReg(kOpOr, t_reg, reg_lo, reg_hi);
+  OpRegRegReg(kOpOr, t_reg, reg.GetLow(), reg.GetHigh());
 
   // In case of zero, throw ArithmeticException.
   GenCheck(kCondEq, kThrowDivZero);
@@ -883,7 +898,7 @@
 }
 
 // Decrement register and branch on condition
-LIR* X86Mir2Lir::OpDecAndBranch(ConditionCode c_code, int reg, LIR* target) {
+LIR* X86Mir2Lir::OpDecAndBranch(ConditionCode c_code, RegStorage reg, LIR* target) {
   OpRegImm(kOpSub, reg, 1);
   return OpCondBranch(c_code, target);
 }
@@ -899,10 +914,10 @@
   return NULL;
 }
 
-void X86Mir2Lir::GenImulRegImm(int dest, int src, int val) {
+void X86Mir2Lir::GenImulRegImm(RegStorage dest, RegStorage src, int val) {
   switch (val) {
     case 0:
-      NewLIR2(kX86Xor32RR, dest, dest);
+      NewLIR2(kX86Xor32RR, dest.GetReg(), dest.GetReg());
       break;
     case 1:
       OpRegCopy(dest, src);
@@ -913,17 +928,17 @@
   }
 }
 
-void X86Mir2Lir::GenImulMemImm(int dest, int sreg, int displacement, int val) {
+void X86Mir2Lir::GenImulMemImm(RegStorage dest, int sreg, int displacement, int val) {
   LIR *m;
   switch (val) {
     case 0:
-      NewLIR2(kX86Xor32RR, dest, dest);
+      NewLIR2(kX86Xor32RR, dest.GetReg(), dest.GetReg());
       break;
     case 1:
-      LoadBaseDisp(rX86_SP, displacement, dest, kWord, sreg);
+      LoadBaseDisp(rs_rX86_SP, displacement, dest, kWord, sreg);
       break;
     default:
-      m = NewLIR4(IS_SIMM8(val) ? kX86Imul32RMI8 : kX86Imul32RMI, dest, rX86_SP,
+      m = NewLIR4(IS_SIMM8(val) ? kX86Imul32RMI8 : kX86Imul32RMI, dest.GetReg(), rX86_SP,
                   displacement, val);
       AnnotateDalvikRegAccess(m, displacement >> 2, true /* is_load */, true /* is_64bit */);
       break;
@@ -941,8 +956,8 @@
     int64_t val = mir_graph_->ConstantValueWide(rl_src2);
     if (val == 0) {
       RegLocation rl_result = EvalLocWide(rl_dest, kCoreReg, true);
-      OpRegReg(kOpXor, rl_result.reg.GetReg(), rl_result.reg.GetReg());
-      OpRegReg(kOpXor, rl_result.reg.GetHighReg(), rl_result.reg.GetHighReg());
+      OpRegReg(kOpXor, rl_result.reg.GetLow(), rl_result.reg.GetLow());
+      OpRegReg(kOpXor, rl_result.reg.GetHigh(), rl_result.reg.GetHigh());
       StoreValueWide(rl_dest, rl_result);
       return;
     } else if (val == 1) {
@@ -974,22 +989,22 @@
     // ECX <- 1H * 2L
     // EAX <- 1L * 2H
     if (src1_in_reg) {
-      GenImulRegImm(r1, rl_src1.reg.GetHighReg(), val_lo);
-      GenImulRegImm(r0, rl_src1.reg.GetReg(), val_hi);
+      GenImulRegImm(rs_r1, rl_src1.reg.GetHigh(), val_lo);
+      GenImulRegImm(rs_r0, rl_src1.reg.GetLow(), val_hi);
     } else {
-      GenImulMemImm(r1, GetSRegHi(rl_src1.s_reg_low), displacement + HIWORD_OFFSET, val_lo);
-      GenImulMemImm(r0, rl_src1.s_reg_low, displacement + LOWORD_OFFSET, val_hi);
+      GenImulMemImm(rs_r1, GetSRegHi(rl_src1.s_reg_low), displacement + HIWORD_OFFSET, val_lo);
+      GenImulMemImm(rs_r0, rl_src1.s_reg_low, displacement + LOWORD_OFFSET, val_hi);
     }
 
     // ECX <- ECX + EAX  (2H * 1L) + (1H * 2L)
     NewLIR2(kX86Add32RR, r1, r0);
 
     // EAX <- 2L
-    LoadConstantNoClobber(r0, val_lo);
+    LoadConstantNoClobber(rs_r0, val_lo);
 
     // EDX:EAX <- 2L * 1L (double precision)
     if (src1_in_reg) {
-      NewLIR1(kX86Mul32DaR, rl_src1.reg.GetReg());
+      NewLIR1(kX86Mul32DaR, rl_src1.reg.GetLowReg());
     } else {
       LIR *m = NewLIR2(kX86Mul32DaM, rX86_SP, displacement + LOWORD_OFFSET);
       AnnotateDalvikRegAccess(m, (displacement + LOWORD_OFFSET) >> 2,
@@ -1001,7 +1016,7 @@
 
     // Result is EDX:EAX
     RegLocation rl_result = {kLocPhysReg, 1, 0, 0, 0, 0, 0, 0, 1, kVectorNotUsed,
-                             RegStorage(RegStorage::k64BitPair, r0, r2),
+                             RegStorage::MakeRegPair(rs_r0, rs_r2),
                              INVALID_SREG, INVALID_SREG};
     StoreValueWide(rl_dest, rl_result);
     return;
@@ -1025,7 +1040,7 @@
   if (src1_in_reg) {
     NewLIR2(kX86Mov32RR, r1, rl_src1.reg.GetHighReg());
   } else {
-    LoadBaseDisp(rX86_SP, SRegOffset(rl_src1.s_reg_low) + HIWORD_OFFSET, r1,
+    LoadBaseDisp(rs_rX86_SP, SRegOffset(rl_src1.s_reg_low) + HIWORD_OFFSET, rs_r1,
                  kWord, GetSRegHi(rl_src1.s_reg_low));
   }
 
@@ -1033,7 +1048,7 @@
     // Take advantage of the fact that the values are the same.
     // ECX <- ECX * 2L  (1H * 2L)
     if (src2_in_reg) {
-      NewLIR2(kX86Imul32RR, r1, rl_src2.reg.GetReg());
+      NewLIR2(kX86Imul32RR, r1, rl_src2.reg.GetLowReg());
     } else {
       int displacement = SRegOffset(rl_src2.s_reg_low);
       LIR *m = NewLIR3(kX86Imul32RM, r1, rX86_SP, displacement + LOWORD_OFFSET);
@@ -1048,13 +1063,13 @@
     if (src2_in_reg) {
       NewLIR2(kX86Mov32RR, r0, rl_src2.reg.GetHighReg());
     } else {
-      LoadBaseDisp(rX86_SP, SRegOffset(rl_src2.s_reg_low) + HIWORD_OFFSET, r0,
+      LoadBaseDisp(rs_rX86_SP, SRegOffset(rl_src2.s_reg_low) + HIWORD_OFFSET, rs_r0,
                    kWord, GetSRegHi(rl_src2.s_reg_low));
     }
 
     // EAX <- EAX * 1L  (2H * 1L)
     if (src1_in_reg) {
-      NewLIR2(kX86Imul32RR, r0, rl_src1.reg.GetReg());
+      NewLIR2(kX86Imul32RR, r0, rl_src1.reg.GetLowReg());
     } else {
       int displacement = SRegOffset(rl_src1.s_reg_low);
       LIR *m = NewLIR3(kX86Imul32RM, r0, rX86_SP, displacement + LOWORD_OFFSET);
@@ -1064,7 +1079,7 @@
 
     // ECX <- ECX * 2L  (1H * 2L)
     if (src2_in_reg) {
-      NewLIR2(kX86Imul32RR, r1, rl_src2.reg.GetReg());
+      NewLIR2(kX86Imul32RR, r1, rl_src2.reg.GetLowReg());
     } else {
       int displacement = SRegOffset(rl_src2.s_reg_low);
       LIR *m = NewLIR3(kX86Imul32RM, r1, rX86_SP, displacement + LOWORD_OFFSET);
@@ -1078,15 +1093,15 @@
 
   // EAX <- 2L
   if (src2_in_reg) {
-    NewLIR2(kX86Mov32RR, r0, rl_src2.reg.GetReg());
+    NewLIR2(kX86Mov32RR, r0, rl_src2.reg.GetLowReg());
   } else {
-    LoadBaseDisp(rX86_SP, SRegOffset(rl_src2.s_reg_low) + LOWORD_OFFSET, r0,
+    LoadBaseDisp(rs_rX86_SP, SRegOffset(rl_src2.s_reg_low) + LOWORD_OFFSET, rs_r0,
                  kWord, rl_src2.s_reg_low);
   }
 
   // EDX:EAX <- 2L * 1L (double precision)
   if (src1_in_reg) {
-    NewLIR1(kX86Mul32DaR, rl_src1.reg.GetReg());
+    NewLIR1(kX86Mul32DaR, rl_src1.reg.GetLowReg());
   } else {
     int displacement = SRegOffset(rl_src1.s_reg_low);
     LIR *m = NewLIR2(kX86Mul32DaM, rX86_SP, displacement + LOWORD_OFFSET);
@@ -1099,7 +1114,7 @@
 
   // Result is EDX:EAX
   RegLocation rl_result = {kLocPhysReg, 1, 0, 0, 0, 0, 0, 0, 1, kVectorNotUsed,
-                           RegStorage(RegStorage::k64BitPair, r0, r2), INVALID_SREG, INVALID_SREG};
+                           RegStorage::MakeRegPair(rs_r0, rs_r2), INVALID_SREG, INVALID_SREG};
   StoreValueWide(rl_dest, rl_result);
 }
 
@@ -1111,32 +1126,31 @@
     // Both operands are in registers.
     // But we must ensure that rl_src is in pair
     rl_src = EvalLocWide(rl_src, kCoreReg, true);
-    if (rl_dest.reg.GetReg() == rl_src.reg.GetHighReg()) {
+    if (rl_dest.reg.GetLowReg() == rl_src.reg.GetHighReg()) {
       // The registers are the same, so we would clobber it before the use.
-      int temp_reg = AllocTemp();
-      OpRegCopy(temp_reg, rl_dest.reg.GetReg());
-      rl_src.reg.SetHighReg(temp_reg);
+      RegStorage temp_reg = AllocTemp();
+      OpRegCopy(temp_reg, rl_dest.reg);
+      rl_src.reg.SetHighReg(temp_reg.GetReg());
     }
-    NewLIR2(x86op, rl_dest.reg.GetReg(), rl_src.reg.GetReg());
+    NewLIR2(x86op, rl_dest.reg.GetLowReg(), rl_src.reg.GetLowReg());
 
     x86op = GetOpcode(op, rl_dest, rl_src, true);
     NewLIR2(x86op, rl_dest.reg.GetHighReg(), rl_src.reg.GetHighReg());
-    FreeTemp(rl_src.reg.GetReg());
-    FreeTemp(rl_src.reg.GetHighReg());
+    FreeTemp(rl_src.reg);
     return;
   }
 
   // RHS is in memory.
   DCHECK((rl_src.location == kLocDalvikFrame) ||
          (rl_src.location == kLocCompilerTemp));
-  int rBase = TargetReg(kSp);
+  int r_base = TargetReg(kSp).GetReg();
   int displacement = SRegOffset(rl_src.s_reg_low);
 
-  LIR *lir = NewLIR3(x86op, rl_dest.reg.GetReg(), rBase, displacement + LOWORD_OFFSET);
+  LIR *lir = NewLIR3(x86op, rl_dest.reg.GetLowReg(), r_base, displacement + LOWORD_OFFSET);
   AnnotateDalvikRegAccess(lir, (displacement + LOWORD_OFFSET) >> 2,
                           true /* is_load */, true /* is64bit */);
   x86op = GetOpcode(op, rl_dest, rl_src, true);
-  lir = NewLIR3(x86op, rl_dest.reg.GetHighReg(), rBase, displacement + HIWORD_OFFSET);
+  lir = NewLIR3(x86op, rl_dest.reg.GetHighReg(), r_base, displacement + HIWORD_OFFSET);
   AnnotateDalvikRegAccess(lir, (displacement + HIWORD_OFFSET) >> 2,
                           true /* is_load */, true /* is64bit */);
 }
@@ -1160,18 +1174,17 @@
 
   // Operate directly into memory.
   X86OpCode x86op = GetOpcode(op, rl_dest, rl_src, false);
-  int rBase = TargetReg(kSp);
+  int r_base = TargetReg(kSp).GetReg();
   int displacement = SRegOffset(rl_dest.s_reg_low);
 
-  LIR *lir = NewLIR3(x86op, rBase, displacement + LOWORD_OFFSET, rl_src.reg.GetReg());
+  LIR *lir = NewLIR3(x86op, r_base, displacement + LOWORD_OFFSET, rl_src.reg.GetLowReg());
   AnnotateDalvikRegAccess(lir, (displacement + LOWORD_OFFSET) >> 2,
                           false /* is_load */, true /* is64bit */);
   x86op = GetOpcode(op, rl_dest, rl_src, true);
-  lir = NewLIR3(x86op, rBase, displacement + HIWORD_OFFSET, rl_src.reg.GetHighReg());
+  lir = NewLIR3(x86op, r_base, displacement + HIWORD_OFFSET, rl_src.reg.GetHighReg());
   AnnotateDalvikRegAccess(lir, (displacement + HIWORD_OFFSET) >> 2,
                           false /* is_load */, true /* is64bit */);
-  FreeTemp(rl_src.reg.GetReg());
-  FreeTemp(rl_src.reg.GetHighReg());
+  FreeTemp(rl_src.reg);
 }
 
 void X86Mir2Lir::GenLongArith(RegLocation rl_dest, RegLocation rl_src1,
@@ -1213,12 +1226,12 @@
 
   // Get one of the source operands into temporary register.
   rl_src1 = LoadValueWide(rl_src1, kCoreReg);
-  if (IsTemp(rl_src1.reg.GetReg()) && IsTemp(rl_src1.reg.GetHighReg())) {
+  if (IsTemp(rl_src1.reg.GetLowReg()) && IsTemp(rl_src1.reg.GetHighReg())) {
     GenLongRegOrMemOp(rl_src1, rl_src2, op);
   } else if (is_commutative) {
     rl_src2 = LoadValueWide(rl_src2, kCoreReg);
     // We need at least one of them to be a temporary.
-    if (!(IsTemp(rl_src2.reg.GetReg()) && IsTemp(rl_src2.reg.GetHighReg()))) {
+    if (!(IsTemp(rl_src2.reg.GetLowReg()) && IsTemp(rl_src2.reg.GetHighReg()))) {
       rl_src1 = ForceTempWide(rl_src1);
       GenLongRegOrMemOp(rl_src1, rl_src2, op);
     } else {
@@ -1264,15 +1277,15 @@
   rl_src = LoadValueWide(rl_src, kCoreReg);
   RegLocation rl_result = ForceTempWide(rl_src);
   if (((rl_dest.location == kLocPhysReg) && (rl_src.location == kLocPhysReg)) &&
-      ((rl_dest.reg.GetReg() == rl_src.reg.GetHighReg()))) {
+      ((rl_dest.reg.GetLowReg() == rl_src.reg.GetHighReg()))) {
     // The registers are the same, so we would clobber it before the use.
-    int temp_reg = AllocTemp();
-    OpRegCopy(temp_reg, rl_result.reg.GetReg());
-    rl_result.reg.SetHighReg(temp_reg);
+    RegStorage temp_reg = AllocTemp();
+    OpRegCopy(temp_reg, rl_result.reg);
+    rl_result.reg.SetHighReg(temp_reg.GetReg());
   }
-  OpRegReg(kOpNeg, rl_result.reg.GetReg(), rl_result.reg.GetReg());    // rLow = -rLow
-  OpRegImm(kOpAdc, rl_result.reg.GetHighReg(), 0);                   // rHigh = rHigh + CF
-  OpRegReg(kOpNeg, rl_result.reg.GetHighReg(), rl_result.reg.GetHighReg());  // rHigh = -rHigh
+  OpRegReg(kOpNeg, rl_result.reg.GetLow(), rl_result.reg.GetLow());    // rLow = -rLow
+  OpRegImm(kOpAdc, rl_result.reg.GetHigh(), 0);                   // rHigh = rHigh + CF
+  OpRegReg(kOpNeg, rl_result.reg.GetHigh(), rl_result.reg.GetHigh());  // rHigh = -rHigh
   StoreValueWide(rl_dest, rl_result);
 }
 
@@ -1314,30 +1327,28 @@
     // If index is constant, just fold it into the data offset
     data_offset += constant_index_value << scale;
     // treat as non array below
-    rl_index.reg = RegStorage(RegStorage::k32BitSolo, INVALID_REG);
+    rl_index.reg = RegStorage::InvalidReg();
   }
 
   /* null object? */
-  GenNullCheck(rl_array.reg.GetReg(), opt_flags);
+  GenNullCheck(rl_array.reg, opt_flags);
 
   if (!(opt_flags & MIR_IGNORE_RANGE_CHECK)) {
     if (constant_index) {
-      GenMemImmedCheck(kCondLs, rl_array.reg.GetReg(), len_offset,
+      GenMemImmedCheck(kCondLs, rl_array.reg, len_offset,
                        constant_index_value, kThrowConstantArrayBounds);
     } else {
-      GenRegMemCheck(kCondUge, rl_index.reg.GetReg(), rl_array.reg.GetReg(),
-                     len_offset, kThrowArrayBounds);
+      GenRegMemCheck(kCondUge, rl_index.reg, rl_array.reg, len_offset, kThrowArrayBounds);
     }
   }
   rl_result = EvalLoc(rl_dest, reg_class, true);
   if ((size == kLong) || (size == kDouble)) {
-    LoadBaseIndexedDisp(rl_array.reg.GetReg(), rl_index.reg.GetReg(), scale, data_offset, rl_result.reg.GetReg(),
-                        rl_result.reg.GetHighReg(), size, INVALID_SREG);
+    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);
   } else {
-    LoadBaseIndexedDisp(rl_array.reg.GetReg(), rl_index.reg.GetReg(), scale,
-                        data_offset, rl_result.reg.GetReg(), INVALID_REG, size,
-                        INVALID_SREG);
+    LoadBaseIndexedDisp(rl_array.reg, rl_index.reg, scale, data_offset, rl_result.reg,
+                        RegStorage::InvalidReg(), size, INVALID_SREG);
     StoreValue(rl_dest, rl_result);
   }
 }
@@ -1368,19 +1379,18 @@
     constant_index_value = mir_graph_->ConstantValue(rl_index);
     data_offset += constant_index_value << scale;
     // treat as non array below
-    rl_index.reg = RegStorage(RegStorage::k32BitSolo, INVALID_REG);
+    rl_index.reg = RegStorage::InvalidReg();
   }
 
   /* null object? */
-  GenNullCheck(rl_array.reg.GetReg(), opt_flags);
+  GenNullCheck(rl_array.reg, opt_flags);
 
   if (!(opt_flags & MIR_IGNORE_RANGE_CHECK)) {
     if (constant_index) {
-      GenMemImmedCheck(kCondLs, rl_array.reg.GetReg(), len_offset,
+      GenMemImmedCheck(kCondLs, rl_array.reg, len_offset,
                        constant_index_value, kThrowConstantArrayBounds);
     } else {
-      GenRegMemCheck(kCondUge, rl_index.reg.GetReg(), rl_array.reg.GetReg(),
-                     len_offset, kThrowArrayBounds);
+      GenRegMemCheck(kCondUge, rl_index.reg, rl_array.reg, len_offset, kThrowArrayBounds);
     }
   }
   if ((size == kLong) || (size == kDouble)) {
@@ -1390,20 +1400,25 @@
   }
   // If the src reg can't be byte accessed, move it to a temp first.
   if ((size == kSignedByte || size == kUnsignedByte) && rl_src.reg.GetReg() >= 4) {
-    int temp = AllocTemp();
-    OpRegCopy(temp, rl_src.reg.GetReg());
-    StoreBaseIndexedDisp(rl_array.reg.GetReg(), rl_index.reg.GetReg(), scale, data_offset, temp,
-                         INVALID_REG, size, INVALID_SREG);
+    RegStorage temp = AllocTemp();
+    OpRegCopy(temp, rl_src.reg);
+    StoreBaseIndexedDisp(rl_array.reg, rl_index.reg, scale, data_offset, temp,
+                         RegStorage::InvalidReg(), size, INVALID_SREG);
   } else {
-    StoreBaseIndexedDisp(rl_array.reg.GetReg(), rl_index.reg.GetReg(), scale, data_offset, rl_src.reg.GetReg(),
-                         rl_src.wide ? rl_src.reg.GetHighReg() : INVALID_REG, size, INVALID_SREG);
+    if (rl_src.wide) {
+      StoreBaseIndexedDisp(rl_array.reg, rl_index.reg, scale, data_offset, rl_src.reg.GetLow(),
+                           rl_src.reg.GetHigh(), size, INVALID_SREG);
+    } else {
+      StoreBaseIndexedDisp(rl_array.reg, rl_index.reg, scale, data_offset, rl_src.reg,
+                           RegStorage::InvalidReg(), size, INVALID_SREG);
+    }
   }
   if (card_mark) {
     // Free rl_index if its a temp. Ensures there are 2 free regs for card mark.
     if (!constant_index) {
       FreeTemp(rl_index.reg.GetReg());
     }
-    MarkGCCard(rl_src.reg.GetReg(), rl_array.reg.GetReg());
+    MarkGCCard(rl_src.reg, rl_array.reg);
   }
 }
 
@@ -1415,51 +1430,51 @@
     case Instruction::SHL_LONG_2ADDR:
       DCHECK_NE(shift_amount, 1);  // Prevent a double store from happening.
       if (shift_amount == 32) {
-        OpRegCopy(rl_result.reg.GetHighReg(), rl_src.reg.GetReg());
-        LoadConstant(rl_result.reg.GetReg(), 0);
+        OpRegCopy(rl_result.reg.GetHigh(), rl_src.reg.GetLow());
+        LoadConstant(rl_result.reg.GetLow(), 0);
       } else if (shift_amount > 31) {
-        OpRegCopy(rl_result.reg.GetHighReg(), rl_src.reg.GetReg());
+        OpRegCopy(rl_result.reg.GetHigh(), rl_src.reg.GetLow());
         FreeTemp(rl_src.reg.GetHighReg());
         NewLIR2(kX86Sal32RI, rl_result.reg.GetHighReg(), shift_amount - 32);
-        LoadConstant(rl_result.reg.GetReg(), 0);
+        LoadConstant(rl_result.reg.GetLow(), 0);
       } else {
-        OpRegCopy(rl_result.reg.GetReg(), rl_src.reg.GetReg());
-        OpRegCopy(rl_result.reg.GetHighReg(), rl_src.reg.GetHighReg());
-        NewLIR3(kX86Shld32RRI, rl_result.reg.GetHighReg(), rl_result.reg.GetReg(), shift_amount);
-        NewLIR2(kX86Sal32RI, rl_result.reg.GetReg(), shift_amount);
+        OpRegCopy(rl_result.reg, rl_src.reg);
+        OpRegCopy(rl_result.reg.GetHigh(), rl_src.reg.GetHigh());
+        NewLIR3(kX86Shld32RRI, rl_result.reg.GetHighReg(), rl_result.reg.GetLowReg(), shift_amount);
+        NewLIR2(kX86Sal32RI, rl_result.reg.GetLowReg(), shift_amount);
       }
       break;
     case Instruction::SHR_LONG:
     case Instruction::SHR_LONG_2ADDR:
       if (shift_amount == 32) {
-        OpRegCopy(rl_result.reg.GetReg(), rl_src.reg.GetHighReg());
-        OpRegCopy(rl_result.reg.GetHighReg(), rl_src.reg.GetHighReg());
+        OpRegCopy(rl_result.reg.GetLow(), rl_src.reg.GetHigh());
+        OpRegCopy(rl_result.reg.GetHigh(), rl_src.reg.GetHigh());
         NewLIR2(kX86Sar32RI, rl_result.reg.GetHighReg(), 31);
       } else if (shift_amount > 31) {
-        OpRegCopy(rl_result.reg.GetReg(), rl_src.reg.GetHighReg());
-        OpRegCopy(rl_result.reg.GetHighReg(), rl_src.reg.GetHighReg());
-        NewLIR2(kX86Sar32RI, rl_result.reg.GetReg(), shift_amount - 32);
+        OpRegCopy(rl_result.reg.GetLow(), rl_src.reg.GetHigh());
+        OpRegCopy(rl_result.reg.GetHigh(), rl_src.reg.GetHigh());
+        NewLIR2(kX86Sar32RI, rl_result.reg.GetLowReg(), shift_amount - 32);
         NewLIR2(kX86Sar32RI, rl_result.reg.GetHighReg(), 31);
       } else {
-        OpRegCopy(rl_result.reg.GetReg(), rl_src.reg.GetReg());
-        OpRegCopy(rl_result.reg.GetHighReg(), rl_src.reg.GetHighReg());
-        NewLIR3(kX86Shrd32RRI, rl_result.reg.GetReg(), rl_result.reg.GetHighReg(), shift_amount);
+        OpRegCopy(rl_result.reg, rl_src.reg);
+        OpRegCopy(rl_result.reg.GetHigh(), rl_src.reg.GetHigh());
+        NewLIR3(kX86Shrd32RRI, rl_result.reg.GetLowReg(), rl_result.reg.GetHighReg(), shift_amount);
         NewLIR2(kX86Sar32RI, rl_result.reg.GetHighReg(), shift_amount);
       }
       break;
     case Instruction::USHR_LONG:
     case Instruction::USHR_LONG_2ADDR:
       if (shift_amount == 32) {
-        OpRegCopy(rl_result.reg.GetReg(), rl_src.reg.GetHighReg());
-        LoadConstant(rl_result.reg.GetHighReg(), 0);
+        OpRegCopy(rl_result.reg.GetLow(), rl_src.reg.GetHigh());
+        LoadConstant(rl_result.reg.GetHigh(), 0);
       } else if (shift_amount > 31) {
-        OpRegCopy(rl_result.reg.GetReg(), rl_src.reg.GetHighReg());
-        NewLIR2(kX86Shr32RI, rl_result.reg.GetReg(), shift_amount - 32);
-        LoadConstant(rl_result.reg.GetHighReg(), 0);
+        OpRegCopy(rl_result.reg.GetLow(), rl_src.reg.GetHigh());
+        NewLIR2(kX86Shr32RI, rl_result.reg.GetLowReg(), shift_amount - 32);
+        LoadConstant(rl_result.reg.GetHigh(), 0);
       } else {
-        OpRegCopy(rl_result.reg.GetReg(), rl_src.reg.GetReg());
-        OpRegCopy(rl_result.reg.GetHighReg(), rl_src.reg.GetHighReg());
-        NewLIR3(kX86Shrd32RRI, rl_result.reg.GetReg(), rl_result.reg.GetHighReg(), shift_amount);
+        OpRegCopy(rl_result.reg, rl_src.reg);
+        OpRegCopy(rl_result.reg.GetHigh(), rl_src.reg.GetHigh());
+        NewLIR3(kX86Shrd32RRI, rl_result.reg.GetLowReg(), rl_result.reg.GetHighReg(), shift_amount);
         NewLIR2(kX86Shr32RI, rl_result.reg.GetHighReg(), shift_amount);
       }
       break;
@@ -1597,7 +1612,7 @@
                                 int32_t value) {
   bool in_mem = loc.location != kLocPhysReg;
   bool byte_imm = IS_SIMM8(value);
-  DCHECK(in_mem || !IsFpReg(loc.reg.GetReg()));
+  DCHECK(in_mem || !IsFpReg(loc.reg));
   switch (op) {
     case Instruction::ADD_LONG:
     case Instruction::ADD_LONG_2ADDR:
@@ -1657,18 +1672,18 @@
   // Can we just do this into memory?
   if ((rl_dest.location == kLocDalvikFrame) ||
       (rl_dest.location == kLocCompilerTemp)) {
-    int rBase = TargetReg(kSp);
+    int r_base = TargetReg(kSp).GetReg();
     int displacement = SRegOffset(rl_dest.s_reg_low);
 
     if (!IsNoOp(op, val_lo)) {
       X86OpCode x86op = GetOpcode(op, rl_dest, false, val_lo);
-      LIR *lir = NewLIR3(x86op, rBase, displacement + LOWORD_OFFSET, val_lo);
+      LIR *lir = NewLIR3(x86op, r_base, displacement + LOWORD_OFFSET, val_lo);
       AnnotateDalvikRegAccess(lir, (displacement + LOWORD_OFFSET) >> 2,
                               false /* is_load */, true /* is64bit */);
     }
     if (!IsNoOp(op, val_hi)) {
       X86OpCode x86op = GetOpcode(op, rl_dest, true, val_hi);
-      LIR *lir = NewLIR3(x86op, rBase, displacement + HIWORD_OFFSET, val_hi);
+      LIR *lir = NewLIR3(x86op, r_base, displacement + HIWORD_OFFSET, val_hi);
       AnnotateDalvikRegAccess(lir, (displacement + HIWORD_OFFSET) >> 2,
                                 false /* is_load */, true /* is64bit */);
     }
@@ -1677,11 +1692,11 @@
 
   RegLocation rl_result = EvalLocWide(rl_dest, kCoreReg, true);
   DCHECK_EQ(rl_result.location, kLocPhysReg);
-  DCHECK(!IsFpReg(rl_result.reg.GetReg()));
+  DCHECK(!IsFpReg(rl_result.reg));
 
   if (!IsNoOp(op, val_lo)) {
     X86OpCode x86op = GetOpcode(op, rl_result, false, val_lo);
-    NewLIR2(x86op, rl_result.reg.GetReg(), val_lo);
+    NewLIR2(x86op, rl_result.reg.GetLowReg(), val_lo);
   }
   if (!IsNoOp(op, val_hi)) {
     X86OpCode x86op = GetOpcode(op, rl_result, true, val_hi);
@@ -1701,11 +1716,12 @@
 
   // Can we do this directly into the destination registers?
   if (rl_dest.location == kLocPhysReg && rl_src1.location == kLocPhysReg &&
-      rl_dest.reg.GetReg() == rl_src1.reg.GetReg() && rl_dest.reg.GetHighReg() == rl_src1.reg.GetHighReg() &&
-      !IsFpReg(rl_dest.reg.GetReg())) {
+      rl_dest.reg.GetLowReg() == rl_src1.reg.GetLowReg() &&
+      rl_dest.reg.GetHighReg() == rl_src1.reg.GetHighReg() &&
+      !IsFpReg(rl_dest.reg)) {
     if (!IsNoOp(op, val_lo)) {
       X86OpCode x86op = GetOpcode(op, rl_dest, false, val_lo);
-      NewLIR2(x86op, rl_dest.reg.GetReg(), val_lo);
+      NewLIR2(x86op, rl_dest.reg.GetLowReg(), val_lo);
     }
     if (!IsNoOp(op, val_hi)) {
       X86OpCode x86op = GetOpcode(op, rl_dest, true, val_hi);
@@ -1723,7 +1739,7 @@
   RegLocation rl_result = ForceTempWide(rl_src1);
   if (!IsNoOp(op, val_lo)) {
     X86OpCode x86op = GetOpcode(op, rl_result, false, val_lo);
-    NewLIR2(x86op, rl_result.reg.GetReg(), val_lo);
+    NewLIR2(x86op, rl_result.reg.GetLowReg(), val_lo);
   }
   if (!IsNoOp(op, val_hi)) {
     X86OpCode x86op = GetOpcode(op, rl_result, true, val_hi);
@@ -1739,19 +1755,19 @@
                                     RegLocation rl_dest, RegLocation rl_src) {
   RegLocation object = LoadValue(rl_src, kCoreReg);
   RegLocation rl_result = EvalLoc(rl_dest, kCoreReg, true);
-  int result_reg = rl_result.reg.GetReg();
+  RegStorage result_reg = rl_result.reg;
 
   // SETcc only works with EAX..EDX.
-  if (result_reg == object.reg.GetReg() || result_reg >= 4) {
+  if (result_reg == object.reg || result_reg.GetReg() >= 4) {
     result_reg = AllocTypedTemp(false, kCoreReg);
-    DCHECK_LT(result_reg, 4);
+    DCHECK_LT(result_reg.GetReg(), 4);
   }
 
   // Assume that there is no match.
   LoadConstant(result_reg, 0);
-  LIR* null_branchover = OpCmpImmBranch(kCondEq, object.reg.GetReg(), 0, NULL);
+  LIR* null_branchover = OpCmpImmBranch(kCondEq, object.reg, 0, NULL);
 
-  int check_class = AllocTypedTemp(false, kCoreReg);
+  RegStorage check_class = AllocTypedTemp(false, kCoreReg);
 
   // If Method* is already in a register, we can save a copy.
   RegLocation rl_method = mir_graph_->GetMethodLoc();
@@ -1760,24 +1776,20 @@
 
   if (rl_method.location == kLocPhysReg) {
     if (use_declaring_class) {
-      LoadWordDisp(rl_method.reg.GetReg(),
-                   mirror::ArtMethod::DeclaringClassOffset().Int32Value(),
+      LoadWordDisp(rl_method.reg, mirror::ArtMethod::DeclaringClassOffset().Int32Value(),
                    check_class);
     } else {
-      LoadWordDisp(rl_method.reg.GetReg(),
-                   mirror::ArtMethod::DexCacheResolvedTypesOffset().Int32Value(),
+      LoadWordDisp(rl_method.reg, mirror::ArtMethod::DexCacheResolvedTypesOffset().Int32Value(),
                    check_class);
       LoadWordDisp(check_class, offset_of_type, check_class);
     }
   } else {
     LoadCurrMethodDirect(check_class);
     if (use_declaring_class) {
-      LoadWordDisp(check_class,
-                   mirror::ArtMethod::DeclaringClassOffset().Int32Value(),
+      LoadWordDisp(check_class, mirror::ArtMethod::DeclaringClassOffset().Int32Value(),
                    check_class);
     } else {
-      LoadWordDisp(check_class,
-                   mirror::ArtMethod::DexCacheResolvedTypesOffset().Int32Value(),
+      LoadWordDisp(check_class, mirror::ArtMethod::DexCacheResolvedTypesOffset().Int32Value(),
                    check_class);
       LoadWordDisp(check_class, offset_of_type, check_class);
     }
@@ -1785,17 +1797,16 @@
 
   // Compare the computed class to the class in the object.
   DCHECK_EQ(object.location, kLocPhysReg);
-  OpRegMem(kOpCmp, check_class, object.reg.GetReg(),
-           mirror::Object::ClassOffset().Int32Value());
+  OpRegMem(kOpCmp, check_class, object.reg, mirror::Object::ClassOffset().Int32Value());
 
   // Set the low byte of the result to 0 or 1 from the compare condition code.
-  NewLIR2(kX86Set8R, result_reg, kX86CondEq);
+  NewLIR2(kX86Set8R, result_reg.GetReg(), kX86CondEq);
 
   LIR* target = NewLIR0(kPseudoTargetLabel);
   null_branchover->target = target;
   FreeTemp(check_class);
   if (IsTemp(result_reg)) {
-    OpRegCopy(rl_result.reg.GetReg(), result_reg);
+    OpRegCopy(rl_result.reg, result_reg);
     FreeTemp(result_reg);
   }
   StoreValue(rl_dest, rl_result);
@@ -1810,7 +1821,7 @@
   // May generate a call - use explicit registers.
   LockCallTemps();
   LoadCurrMethodDirect(TargetReg(kArg1));  // kArg1 gets current Method*.
-  int class_reg = TargetReg(kArg2);  // kArg2 will hold the Class*.
+  RegStorage class_reg = TargetReg(kArg2);  // kArg2 will hold the Class*.
   // Reference must end up in kArg0.
   if (needs_access_check) {
     // Check we have access to type_idx and if not throw IllegalAccessError,
@@ -1821,13 +1832,13 @@
     LoadValueDirectFixed(rl_src, TargetReg(kArg0));
   } else if (use_declaring_class) {
     LoadValueDirectFixed(rl_src, TargetReg(kArg0));
-    LoadWordDisp(TargetReg(kArg1),
-                 mirror::ArtMethod::DeclaringClassOffset().Int32Value(), class_reg);
+    LoadWordDisp(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(), class_reg);
+    LoadWordDisp(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);
@@ -1860,13 +1871,13 @@
   LIR* branchover = nullptr;
   if (type_known_final) {
     // Ensure top 3 bytes of result are 0.
-    LoadConstant(rl_result.reg.GetReg(), 0);
+    LoadConstant(rl_result.reg, 0);
     OpRegReg(kOpCmp, TargetReg(kArg1), TargetReg(kArg2));
     // Set the low byte of the result to 0 or 1 from the compare condition code.
     NewLIR2(kX86Set8R, rl_result.reg.GetReg(), kX86CondEq);
   } else {
     if (!type_known_abstract) {
-      LoadConstant(rl_result.reg.GetReg(), 1);     // Assume result succeeds.
+      LoadConstant(rl_result.reg, 1);     // Assume result succeeds.
       branchover = OpCmpBranch(kCondEq, TargetReg(kArg1), TargetReg(kArg2), NULL);
     }
     OpRegCopy(TargetReg(kArg0), TargetReg(kArg2));
@@ -1994,11 +2005,11 @@
     rl_lhs = LoadValue(rl_lhs, kCoreReg);
     rl_result = UpdateLoc(rl_dest);
     rl_result = EvalLoc(rl_dest, kCoreReg, true);
-    OpRegReg(op, rl_result.reg.GetReg(), rl_lhs.reg.GetReg());
+    OpRegReg(op, rl_result.reg, rl_lhs.reg);
   } else {
     if (shift_op) {
       // X86 doesn't require masking and must use ECX.
-      int t_reg = TargetReg(kCount);  // rCX
+      RegStorage t_reg = TargetReg(kCount);  // rCX
       LoadValueDirectFixed(rl_rhs, t_reg);
       if (is_two_addr) {
         // Can we do this directly into memory?
@@ -2006,12 +2017,12 @@
         rl_rhs = LoadValue(rl_rhs, kCoreReg);
         if (rl_result.location != kLocPhysReg) {
           // Okay, we can do this into memory
-          OpMemReg(op, rl_result, t_reg);
+          OpMemReg(op, rl_result, t_reg.GetReg());
           FreeTemp(t_reg);
           return;
         } else if (!IsFpReg(rl_result.reg.GetReg())) {
           // Can do this directly into the result register
-          OpRegReg(op, rl_result.reg.GetReg(), t_reg);
+          OpRegReg(op, rl_result.reg, t_reg);
           FreeTemp(t_reg);
           StoreFinalValue(rl_dest, rl_result);
           return;
@@ -2020,7 +2031,7 @@
       // Three address form, or we can't do directly.
       rl_lhs = LoadValue(rl_lhs, kCoreReg);
       rl_result = EvalLoc(rl_dest, kCoreReg, true);
-      OpRegRegReg(op, rl_result.reg.GetReg(), rl_lhs.reg.GetReg(), t_reg);
+      OpRegRegReg(op, rl_result.reg, rl_lhs.reg, t_reg);
       FreeTemp(t_reg);
     } else {
       // Multiply is 3 operand only (sort of).
@@ -2031,11 +2042,11 @@
           // Can we do this from memory directly?
           rl_rhs = UpdateLoc(rl_rhs);
           if (rl_rhs.location != kLocPhysReg) {
-            OpRegMem(op, rl_result.reg.GetReg(), rl_rhs);
+            OpRegMem(op, rl_result.reg, rl_rhs);
             StoreFinalValue(rl_dest, rl_result);
             return;
-          } else if (!IsFpReg(rl_rhs.reg.GetReg())) {
-            OpRegReg(op, rl_result.reg.GetReg(), rl_rhs.reg.GetReg());
+          } else if (!IsFpReg(rl_rhs.reg)) {
+            OpRegReg(op, rl_result.reg, rl_rhs.reg);
             StoreFinalValue(rl_dest, rl_result);
             return;
           }
@@ -2045,15 +2056,15 @@
           // Okay, we can do this into memory.
           OpMemReg(op, rl_result, rl_rhs.reg.GetReg());
           return;
-        } else if (!IsFpReg(rl_result.reg.GetReg())) {
+        } else if (!IsFpReg(rl_result.reg)) {
           // Can do this directly into the result register.
-          OpRegReg(op, rl_result.reg.GetReg(), rl_rhs.reg.GetReg());
+          OpRegReg(op, rl_result.reg, rl_rhs.reg);
           StoreFinalValue(rl_dest, rl_result);
           return;
         } else {
           rl_lhs = LoadValue(rl_lhs, kCoreReg);
           rl_result = EvalLoc(rl_dest, kCoreReg, true);
-          OpRegRegReg(op, rl_result.reg.GetReg(), rl_lhs.reg.GetReg(), rl_rhs.reg.GetReg());
+          OpRegRegReg(op, rl_result.reg, rl_lhs.reg, rl_rhs.reg);
         }
       } else {
         // Try to use reg/memory instructions.
@@ -2065,7 +2076,7 @@
           rl_lhs = LoadValue(rl_lhs, kCoreReg);
           rl_rhs = LoadValue(rl_rhs, kCoreReg);
           rl_result = EvalLoc(rl_dest, kCoreReg, true);
-          OpRegRegReg(op, rl_result.reg.GetReg(), rl_lhs.reg.GetReg(), rl_rhs.reg.GetReg());
+          OpRegRegReg(op, rl_result.reg, rl_lhs.reg, rl_rhs.reg);
         } else {
           // We can optimize by moving to result and using memory operands.
           if (rl_rhs.location != kLocPhysReg) {
@@ -2078,29 +2089,29 @@
               rl_result = EvalLoc(rl_dest, kCoreReg, true);
             } else {
               rl_result = EvalLoc(rl_dest, kCoreReg, true);
-              LoadValueDirect(rl_lhs, rl_result.reg.GetReg());
+              LoadValueDirect(rl_lhs, rl_result.reg);
             }
-            OpRegMem(op, rl_result.reg.GetReg(), rl_rhs);
+            OpRegMem(op, rl_result.reg, rl_rhs);
           } else if (rl_lhs.location != kLocPhysReg) {
             // RHS is in a register; LHS is in memory.
             if (op != kOpSub) {
               // Force RHS into result and operate on memory.
               rl_result = EvalLoc(rl_dest, kCoreReg, true);
-              OpRegCopy(rl_result.reg.GetReg(), rl_rhs.reg.GetReg());
-              OpRegMem(op, rl_result.reg.GetReg(), rl_lhs);
+              OpRegCopy(rl_result.reg, rl_rhs.reg);
+              OpRegMem(op, rl_result.reg, rl_lhs);
             } else {
               // Subtraction isn't commutative.
               rl_lhs = LoadValue(rl_lhs, kCoreReg);
               rl_rhs = LoadValue(rl_rhs, kCoreReg);
               rl_result = EvalLoc(rl_dest, kCoreReg, true);
-              OpRegRegReg(op, rl_result.reg.GetReg(), rl_lhs.reg.GetReg(), rl_rhs.reg.GetReg());
+              OpRegRegReg(op, rl_result.reg, rl_lhs.reg, rl_rhs.reg);
             }
           } else {
             // Both are in registers.
             rl_lhs = LoadValue(rl_lhs, kCoreReg);
             rl_rhs = LoadValue(rl_rhs, kCoreReg);
             rl_result = EvalLoc(rl_dest, kCoreReg, true);
-            OpRegRegReg(op, rl_result.reg.GetReg(), rl_lhs.reg.GetReg(), rl_rhs.reg.GetReg());
+            OpRegRegReg(op, rl_result.reg, rl_lhs.reg, rl_rhs.reg);
           }
         }
       }
diff --git a/compiler/dex/quick/x86/target_x86.cc b/compiler/dex/quick/x86/target_x86.cc
index 9588b17..da64250 100644
--- a/compiler/dex/quick/x86/target_x86.cc
+++ b/compiler/dex/quick/x86/target_x86.cc
@@ -65,44 +65,44 @@
 }
 
 // Return a target-dependent special register.
-int X86Mir2Lir::TargetReg(SpecialTargetRegister reg) {
-  int res = INVALID_REG;
+RegStorage X86Mir2Lir::TargetReg(SpecialTargetRegister reg) {
+  int res_reg = RegStorage::kInvalidRegVal;
   switch (reg) {
-    case kSelf: res = rX86_SELF; break;
-    case kSuspend: res =  rX86_SUSPEND; break;
-    case kLr: res =  rX86_LR; break;
-    case kPc: res =  rX86_PC; break;
-    case kSp: res =  rX86_SP; break;
-    case kArg0: res = rX86_ARG0; break;
-    case kArg1: res = rX86_ARG1; break;
-    case kArg2: res = rX86_ARG2; break;
-    case kArg3: res = rX86_ARG3; break;
-    case kFArg0: res = rX86_FARG0; break;
-    case kFArg1: res = rX86_FARG1; break;
-    case kFArg2: res = rX86_FARG2; break;
-    case kFArg3: res = rX86_FARG3; break;
-    case kRet0: res = rX86_RET0; break;
-    case kRet1: res = rX86_RET1; break;
-    case kInvokeTgt: res = rX86_INVOKE_TGT; break;
-    case kHiddenArg: res = rAX; break;
-    case kHiddenFpArg: res = fr0; break;
-    case kCount: res = rX86_COUNT; break;
+    case kSelf: res_reg = rX86_SELF; break;
+    case kSuspend: res_reg =  rX86_SUSPEND; break;
+    case kLr: res_reg =  rX86_LR; break;
+    case kPc: res_reg =  rX86_PC; break;
+    case kSp: res_reg =  rX86_SP; break;
+    case kArg0: res_reg = rX86_ARG0; break;
+    case kArg1: res_reg = rX86_ARG1; break;
+    case kArg2: res_reg = rX86_ARG2; break;
+    case kArg3: res_reg = rX86_ARG3; break;
+    case kFArg0: res_reg = rX86_FARG0; break;
+    case kFArg1: res_reg = rX86_FARG1; break;
+    case kFArg2: res_reg = rX86_FARG2; break;
+    case kFArg3: res_reg = rX86_FARG3; break;
+    case kRet0: res_reg = rX86_RET0; break;
+    case kRet1: res_reg = rX86_RET1; break;
+    case kInvokeTgt: res_reg = rX86_INVOKE_TGT; break;
+    case kHiddenArg: res_reg = rAX; break;
+    case kHiddenFpArg: res_reg = fr0; break;
+    case kCount: res_reg = rX86_COUNT; break;
   }
-  return res;
+  return RegStorage::Solo32(res_reg);
 }
 
-int X86Mir2Lir::GetArgMappingToPhysicalReg(int arg_num) {
+RegStorage X86Mir2Lir::GetArgMappingToPhysicalReg(int arg_num) {
   // For the 32-bit internal ABI, the first 3 arguments are passed in registers.
   // TODO: This is not 64-bit compliant and depends on new internal ABI.
   switch (arg_num) {
     case 0:
-      return rX86_ARG1;
+      return rs_rX86_ARG1;
     case 1:
-      return rX86_ARG2;
+      return rs_rX86_ARG2;
     case 2:
-      return rX86_ARG3;
+      return rs_rX86_ARG3;
     default:
-      return INVALID_REG;
+      return RegStorage::InvalidReg();
   }
 }
 
@@ -346,9 +346,9 @@
 #endif
 }
 
-void X86Mir2Lir::FlushRegWide(int reg1, int reg2) {
-  RegisterInfo* info1 = GetRegInfo(reg1);
-  RegisterInfo* info2 = GetRegInfo(reg2);
+void X86Mir2Lir::FlushRegWide(RegStorage reg) {
+  RegisterInfo* info1 = GetRegInfo(reg.GetLowReg());
+  RegisterInfo* info2 = GetRegInfo(reg.GetHighReg());
   DCHECK(info1 && info2 && info1->pair && info2->pair &&
          (info1->partner == info2->reg) &&
          (info2->partner == info1->reg));
@@ -363,16 +363,18 @@
     if (mir_graph_->SRegToVReg(info2->s_reg) < mir_graph_->SRegToVReg(info1->s_reg))
       info1 = info2;
     int v_reg = mir_graph_->SRegToVReg(info1->s_reg);
-    StoreBaseDispWide(rX86_SP, VRegOffset(v_reg), info1->reg, info1->partner);
+    StoreBaseDispWide(rs_rX86_SP, VRegOffset(v_reg),
+                      RegStorage(RegStorage::k64BitPair, info1->reg, info1->partner));
   }
 }
 
-void X86Mir2Lir::FlushReg(int reg) {
-  RegisterInfo* info = GetRegInfo(reg);
+void X86Mir2Lir::FlushReg(RegStorage 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(rX86_SP, VRegOffset(v_reg), reg, kWord);
+    StoreBaseDisp(rs_rX86_SP, VRegOffset(v_reg), reg, kWord);
   }
 }
 
@@ -381,6 +383,10 @@
   return X86_FPREG(reg);
 }
 
+bool X86Mir2Lir::IsFpReg(RegStorage reg) {
+  return IsFpReg(reg.IsPair() ? reg.GetLowReg() : reg.GetReg());
+}
+
 /* Clobber all regs that might be used by an external C call */
 void X86Mir2Lir::ClobberCallerSave() {
   Clobber(rAX);
@@ -391,13 +397,13 @@
 
 RegLocation X86Mir2Lir::GetReturnWideAlt() {
   RegLocation res = LocCReturnWide();
-  CHECK(res.reg.GetReg() == rAX);
+  CHECK(res.reg.GetLowReg() == rAX);
   CHECK(res.reg.GetHighReg() == rDX);
   Clobber(rAX);
   Clobber(rDX);
   MarkInUse(rAX);
   MarkInUse(rDX);
-  MarkPair(res.reg.GetReg(), res.reg.GetHighReg());
+  MarkPair(res.reg.GetLowReg(), res.reg.GetHighReg());
   return res;
 }
 
@@ -478,21 +484,15 @@
 
 // Alloc a pair of core registers, or a double.
 RegStorage X86Mir2Lir::AllocTypedTempWide(bool fp_hint, int reg_class) {
-  int high_reg;
-  int low_reg;
-
   if (((reg_class == kAnyReg) && fp_hint) || (reg_class == kFPReg)) {
-    low_reg = AllocTempDouble();
-    high_reg = low_reg;  // only one allocated!
-    // TODO: take advantage of 64-bit notation.
-    return RegStorage(RegStorage::k64BitPair, low_reg, high_reg);
+    return AllocTempDouble();
   }
-  low_reg = AllocTemp();
-  high_reg = AllocTemp();
-  return RegStorage(RegStorage::k64BitPair, low_reg, high_reg);
+  RegStorage low_reg = AllocTemp();
+  RegStorage high_reg = AllocTemp();
+  return RegStorage::MakeRegPair(low_reg, high_reg);
 }
 
-int X86Mir2Lir::AllocTypedTemp(bool fp_hint, int reg_class) {
+RegStorage X86Mir2Lir::AllocTypedTemp(bool fp_hint, int reg_class) {
   if (((reg_class == kAnyReg) && fp_hint) || (reg_class == kFPReg)) {
     return AllocTempFloat();
   }
@@ -530,13 +530,18 @@
   }
 }
 
-void X86Mir2Lir::FreeRegLocTemps(RegLocation rl_keep,
-                     RegLocation rl_free) {
-  if ((rl_free.reg.GetReg() != rl_keep.reg.GetReg()) && (rl_free.reg.GetReg() != rl_keep.reg.GetHighReg()) &&
-      (rl_free.reg.GetHighReg() != rl_keep.reg.GetReg()) && (rl_free.reg.GetHighReg() != rl_keep.reg.GetHighReg())) {
+void X86Mir2Lir::FreeRegLocTemps(RegLocation rl_keep, RegLocation rl_free) {
+  DCHECK(rl_keep.wide);
+  DCHECK(rl_free.wide);
+  int free_low = rl_free.reg.GetLowReg();
+  int free_high = rl_free.reg.GetHighReg();
+  int keep_low = rl_keep.reg.GetLowReg();
+  int keep_high = rl_keep.reg.GetHighReg();
+  if ((free_low != keep_low) && (free_low != keep_high) &&
+      (free_high != keep_low) && (free_high != keep_high)) {
     // No overlap, free both
-    FreeTemp(rl_free.reg.GetReg());
-    FreeTemp(rl_free.reg.GetHighReg());
+    FreeTemp(free_low);
+    FreeTemp(free_high);
   }
 }
 
@@ -549,7 +554,7 @@
   int offset = frame_size_ - (4 * num_core_spills_);
   for (int reg = 0; mask; mask >>= 1, reg++) {
     if (mask & 0x1) {
-      StoreWordDisp(rX86_SP, offset, reg);
+      StoreWordDisp(rs_rX86_SP, offset, RegStorage::Solo32(reg));
       offset += 4;
     }
   }
@@ -564,7 +569,7 @@
   int offset = frame_size_ - (4 * num_core_spills_);
   for (int reg = 0; mask; mask >>= 1, reg++) {
     if (mask & 0x1) {
-      LoadWordDisp(rX86_SP, offset, reg);
+      LoadWordDisp(rs_rX86_SP, offset, RegStorage::Solo32(reg));
       offset += 4;
     }
   }
@@ -596,9 +601,9 @@
 }
 
 // Not used in x86
-int X86Mir2Lir::LoadHelper(ThreadOffset offset) {
+RegStorage X86Mir2Lir::LoadHelper(ThreadOffset offset) {
   LOG(FATAL) << "Unexpected use of LoadHelper in x86";
-  return INVALID_REG;
+  return RegStorage::InvalidReg();
 }
 
 LIR* X86Mir2Lir::CheckSuspendUsingLoad() {
@@ -650,7 +655,7 @@
         loc.vec_len = kVectorLength8;
         // TODO: use k64BitVector
         loc.reg = RegStorage(RegStorage::k64BitPair, info_lo->reg, info_lo->reg);
-        DCHECK(IsFpReg(loc.reg.GetReg()));
+        DCHECK(IsFpReg(loc.reg.GetLowReg()));
         return loc;
       }
       // We can't easily reuse; clobber and free any overlaps.
@@ -682,8 +687,8 @@
         // Can reuse - update the register usage info
         loc.reg = RegStorage(RegStorage::k64BitPair, info_lo->reg, info_hi->reg);
         loc.location = kLocPhysReg;
-        MarkPair(loc.reg.GetReg(), loc.reg.GetHighReg());
-        DCHECK(!IsFpReg(loc.reg.GetReg()) || ((loc.reg.GetReg() & 0x1) == 0));
+        MarkPair(loc.reg.GetLowReg(), loc.reg.GetHighReg());
+        DCHECK(!IsFpReg(loc.reg.GetLowReg()) || ((loc.reg.GetLowReg() & 0x1) == 0));
         return loc;
       }
       // Can't easily reuse - clobber and free any overlaps
@@ -707,44 +712,37 @@
 // TODO: Reunify with common code after 'pair mess' has been fixed
 RegLocation X86Mir2Lir::EvalLocWide(RegLocation loc, int reg_class, bool update) {
   DCHECK(loc.wide);
-  int32_t low_reg;
-  int32_t high_reg;
 
   loc = UpdateLocWide(loc);
 
   /* If it is already in a register, we can assume proper form.  Is it the right reg class? */
   if (loc.location == kLocPhysReg) {
-    DCHECK_EQ(IsFpReg(loc.reg.GetReg()), loc.IsVectorScalar());
-    if (!RegClassMatches(reg_class, loc.reg.GetReg())) {
+    DCHECK_EQ(IsFpReg(loc.reg.GetLowReg()), loc.IsVectorScalar());
+    if (!RegClassMatches(reg_class, loc.reg)) {
       /* It is the wrong register class.  Reallocate and copy. */
-      if (!IsFpReg(loc.reg.GetReg())) {
+      if (!IsFpReg(loc.reg.GetLowReg())) {
         // We want this in a FP reg, and it is in core registers.
         DCHECK(reg_class != kCoreReg);
         // Allocate this into any FP reg, and mark it with the right size.
-        low_reg = AllocTypedTemp(true, reg_class);
-        OpVectorRegCopyWide(low_reg, loc.reg.GetReg(), loc.reg.GetHighReg());
-        CopyRegInfo(low_reg, loc.reg.GetReg());
-        Clobber(loc.reg.GetReg());
-        Clobber(loc.reg.GetHighReg());
+        int32_t low_reg = AllocTypedTemp(true, reg_class).GetReg();
+        OpVectorRegCopyWide(low_reg, loc.reg.GetLowReg(), loc.reg.GetHighReg());
+        CopyRegInfo(low_reg, loc.reg.GetLowReg());
+        Clobber(loc.reg);
         loc.reg.SetReg(low_reg);
         loc.reg.SetHighReg(low_reg);  // Play nice with existing code.
         loc.vec_len = kVectorLength8;
       } else {
         // The value is in a FP register, and we want it in a pair of core registers.
         DCHECK_EQ(reg_class, kCoreReg);
-        DCHECK_EQ(loc.reg.GetReg(), loc.reg.GetHighReg());
+        DCHECK_EQ(loc.reg.GetLowReg(), loc.reg.GetHighReg());
         RegStorage new_regs = AllocTypedTempWide(false, kCoreReg);  // Force to core registers.
-        low_reg = new_regs.GetReg();
-        high_reg = new_regs.GetHighReg();
-        DCHECK_NE(low_reg, high_reg);
-        OpRegCopyWide(low_reg, high_reg, loc.reg.GetReg(), loc.reg.GetHighReg());
-        CopyRegInfo(low_reg, loc.reg.GetReg());
-        CopyRegInfo(high_reg, loc.reg.GetHighReg());
-        Clobber(loc.reg.GetReg());
-        Clobber(loc.reg.GetHighReg());
+        OpRegCopyWide(new_regs, loc.reg);
+        CopyRegInfo(new_regs.GetLowReg(), loc.reg.GetLowReg());
+        CopyRegInfo(new_regs.GetHighReg(), loc.reg.GetHighReg());
+        Clobber(loc.reg);
         loc.reg = new_regs;
-        MarkPair(loc.reg.GetReg(), loc.reg.GetHighReg());
-        DCHECK(!IsFpReg(loc.reg.GetReg()) || ((loc.reg.GetReg() & 0x1) == 0));
+        MarkPair(loc.reg.GetLowReg(), loc.reg.GetHighReg());
+        DCHECK(!IsFpReg(loc.reg.GetLowReg()) || ((loc.reg.GetLowReg() & 0x1) == 0));
       }
     }
     return loc;
@@ -756,17 +754,17 @@
   loc.reg = AllocTypedTempWide(loc.fp, reg_class);
 
   // FIXME: take advantage of RegStorage notation.
-  if (loc.reg.GetReg() == loc.reg.GetHighReg()) {
-    DCHECK(IsFpReg(loc.reg.GetReg()));
+  if (loc.reg.GetLowReg() == loc.reg.GetHighReg()) {
+    DCHECK(IsFpReg(loc.reg.GetLowReg()));
     loc.vec_len = kVectorLength8;
   } else {
-    MarkPair(loc.reg.GetReg(), loc.reg.GetHighReg());
+    MarkPair(loc.reg.GetLowReg(), loc.reg.GetHighReg());
   }
   if (update) {
     loc.location = kLocPhysReg;
-    MarkLive(loc.reg.GetReg(), loc.s_reg_low);
-    if (loc.reg.GetReg() != loc.reg.GetHighReg()) {
-      MarkLive(loc.reg.GetHighReg(), GetSRegHi(loc.s_reg_low));
+    MarkLive(loc.reg.GetLow(), loc.s_reg_low);
+    if (loc.reg.GetLowReg() != loc.reg.GetHighReg()) {
+      MarkLive(loc.reg.GetHigh(), GetSRegHi(loc.s_reg_low));
     }
   }
   return loc;
@@ -774,21 +772,19 @@
 
 // TODO: Reunify with common code after 'pair mess' has been fixed
 RegLocation X86Mir2Lir::EvalLoc(RegLocation loc, int reg_class, bool update) {
-  int new_reg;
-
   if (loc.wide)
     return EvalLocWide(loc, reg_class, update);
 
   loc = UpdateLoc(loc);
 
   if (loc.location == kLocPhysReg) {
-    if (!RegClassMatches(reg_class, loc.reg.GetReg())) {
+    if (!RegClassMatches(reg_class, loc.reg)) {
       /* Wrong register class.  Realloc, copy and transfer ownership. */
-      new_reg = AllocTypedTemp(loc.fp, reg_class);
-      OpRegCopy(new_reg, loc.reg.GetReg());
-      CopyRegInfo(new_reg, loc.reg.GetReg());
-      Clobber(loc.reg.GetReg());
-      loc.reg.SetReg(new_reg);
+      RegStorage new_reg = AllocTypedTemp(loc.fp, reg_class);
+      OpRegCopy(new_reg, loc.reg);
+      CopyRegInfo(new_reg, loc.reg);
+      Clobber(loc.reg);
+      loc.reg = new_reg;
       if (IsFpReg(loc.reg.GetReg()) && reg_class != kCoreReg)
         loc.vec_len = kVectorLength4;
     }
@@ -797,32 +793,34 @@
 
   DCHECK_NE(loc.s_reg_low, INVALID_SREG);
 
-  loc.reg = RegStorage(RegStorage::k32BitSolo, AllocTypedTemp(loc.fp, reg_class));
+  loc.reg = AllocTypedTemp(loc.fp, reg_class);
   if (IsFpReg(loc.reg.GetReg()) && reg_class != kCoreReg)
     loc.vec_len = kVectorLength4;
 
   if (update) {
     loc.location = kLocPhysReg;
-    MarkLive(loc.reg.GetReg(), loc.s_reg_low);
+    MarkLive(loc.reg, loc.s_reg_low);
   }
   return loc;
 }
 
-int X86Mir2Lir::AllocTempDouble() {
+RegStorage X86Mir2Lir::AllocTempDouble() {
   // We really don't need a pair of registers.
-  return AllocTempFloat();
+  // FIXME - update to double
+  int reg = AllocTempFloat().GetReg();
+  return RegStorage(RegStorage::k64BitPair, reg, reg);
 }
 
 // TODO: Reunify with common code after 'pair mess' has been fixed
 void X86Mir2Lir::ResetDefLocWide(RegLocation rl) {
   DCHECK(rl.wide);
-  RegisterInfo* p_low = IsTemp(rl.reg.GetReg());
-  if (IsFpReg(rl.reg.GetReg())) {
+  RegisterInfo* p_low = IsTemp(rl.reg.GetLowReg());
+  if (IsFpReg(rl.reg.GetLowReg())) {
     // We are using only the low register.
     if (p_low && !(cu_->disable_opt & (1 << kSuppressLoads))) {
       NullifyRange(p_low->def_start, p_low->def_end, p_low->s_reg, rl.s_reg_low);
     }
-    ResetDef(rl.reg.GetReg());
+    ResetDef(rl.reg.GetLowReg());
   } else {
     RegisterInfo* p_high = IsTemp(rl.reg.GetHighReg());
     if (p_low && !(cu_->disable_opt & (1 << kSuppressLoads))) {
@@ -832,7 +830,7 @@
     if (p_high && !(cu_->disable_opt & (1 << kSuppressLoads))) {
       DCHECK(p_high->pair);
     }
-    ResetDef(rl.reg.GetReg());
+    ResetDef(rl.reg.GetLowReg());
     ResetDef(rl.reg.GetHighReg());
   }
 }
@@ -844,13 +842,13 @@
       (rl_dest.location == kLocCompilerTemp)) {
     int32_t val_lo = Low32Bits(value);
     int32_t val_hi = High32Bits(value);
-    int rBase = TargetReg(kSp);
+    int r_base = TargetReg(kSp).GetReg();
     int displacement = SRegOffset(rl_dest.s_reg_low);
 
-    LIR * store = NewLIR3(kX86Mov32MI, rBase, displacement + LOWORD_OFFSET, val_lo);
+    LIR * store = NewLIR3(kX86Mov32MI, r_base, displacement + LOWORD_OFFSET, val_lo);
     AnnotateDalvikRegAccess(store, (displacement + LOWORD_OFFSET) >> 2,
                               false /* is_load */, true /* is64bit */);
-    store = NewLIR3(kX86Mov32MI, rBase, displacement + HIWORD_OFFSET, val_hi);
+    store = NewLIR3(kX86Mov32MI, r_base, displacement + HIWORD_OFFSET, val_hi);
     AnnotateDalvikRegAccess(store, (displacement + HIWORD_OFFSET) >> 2,
                               false /* is_load */, true /* is64bit */);
     return;
@@ -872,7 +870,7 @@
              << (loc.high_word ? " h" : "  ")
              << (loc.home ? " H" : "  ")
              << " vec_len: " << loc.vec_len
-             << ", low: " << static_cast<int>(loc.reg.GetReg())
+             << ", low: " << static_cast<int>(loc.reg.GetLowReg())
              << ", high: " << static_cast<int>(loc.reg.GetHighReg())
              << ", s_reg: " << loc.s_reg_low
              << ", orig: " << loc.orig_sreg;
@@ -899,7 +897,7 @@
   uintptr_t target_method_id_ptr = reinterpret_cast<uintptr_t>(&target_method_id);
 
   // Generate the move instruction with the unique pointer and save index, dex_file, and type.
-  LIR *move = RawLIR(current_dalvik_offset_, kX86Mov32RI, TargetReg(symbolic_reg),
+  LIR *move = RawLIR(current_dalvik_offset_, kX86Mov32RI, TargetReg(symbolic_reg).GetReg(),
                      static_cast<int>(target_method_id_ptr), target_method_idx,
                      WrapPointer(const_cast<DexFile*>(target_dex_file)), type);
   AppendLIR(move);
@@ -916,7 +914,7 @@
   uintptr_t ptr = reinterpret_cast<uintptr_t>(&id);
 
   // Generate the move instruction with the unique pointer and save index and type.
-  LIR *move = RawLIR(current_dalvik_offset_, kX86Mov32RI, TargetReg(symbolic_reg),
+  LIR *move = RawLIR(current_dalvik_offset_, kX86Mov32RI, TargetReg(symbolic_reg).GetReg(),
                      static_cast<int>(ptr), type_idx);
   AppendLIR(move);
   class_type_address_insns_.Insert(move);
@@ -1028,19 +1026,19 @@
   RegLocation rl_dest = InlineTarget(info);
 
   // Is the string non-NULL?
-  LoadValueDirectFixed(rl_obj, rDX);
-  GenNullCheck(rDX, info->opt_flags);
+  LoadValueDirectFixed(rl_obj, rs_rDX);
+  GenNullCheck(rs_rDX, info->opt_flags);
   info->opt_flags |= MIR_IGNORE_NULL_CHECK;  // Record that we've null checked.
 
   // Does the character fit in 16 bits?
   LIR* launchpad_branch = nullptr;
   if (rl_char.is_const) {
     // We need the value in EAX.
-    LoadConstantNoClobber(rAX, char_value);
+    LoadConstantNoClobber(rs_rAX, char_value);
   } else {
     // Character is not a constant; compare at runtime.
-    LoadValueDirectFixed(rl_char, rAX);
-    launchpad_branch = OpCmpImmBranch(kCondGt, rAX, 0xFFFF, nullptr);
+    LoadValueDirectFixed(rl_char, rs_rAX);
+    launchpad_branch = OpCmpImmBranch(kCondGt, rs_rAX, 0xFFFF, nullptr);
   }
 
   // From here down, we know that we are looking for a char that fits in 16 bits.
@@ -1061,7 +1059,7 @@
   NewLIR1(kX86Push32R, rDI);
 
   // Compute the number of words to search in to rCX.
-  LoadWordDisp(rDX, count_offset, rCX);
+  LoadWordDisp(rs_rDX, count_offset, rs_rCX);
   LIR *length_compare = nullptr;
   int start_value = 0;
   if (zero_based) {
@@ -1075,23 +1073,23 @@
       start_value = std::max(start_value, 0);
 
       // Is the start > count?
-      length_compare = OpCmpImmBranch(kCondLe, rCX, start_value, nullptr);
+      length_compare = OpCmpImmBranch(kCondLe, rs_rCX, start_value, nullptr);
 
       if (start_value != 0) {
-        OpRegImm(kOpSub, rCX, start_value);
+        OpRegImm(kOpSub, rs_rCX, start_value);
       }
     } else {
       // Runtime start index.
       rl_start = UpdateLoc(rl_start);
       if (rl_start.location == kLocPhysReg) {
-        length_compare = OpCmpBranch(kCondLe, rCX, rl_start.reg.GetReg(), nullptr);
-        OpRegReg(kOpSub, rCX, rl_start.reg.GetReg());
+        length_compare = OpCmpBranch(kCondLe, rs_rCX, rl_start.reg, nullptr);
+        OpRegReg(kOpSub, rs_rCX, rl_start.reg);
       } else {
         // Compare to memory to avoid a register load.  Handle pushed EDI.
         int displacement = SRegOffset(rl_start.s_reg_low) + sizeof(uint32_t);
-        OpRegMem(kOpCmp, rCX, rX86_SP, displacement);
+        OpRegMem(kOpCmp, rs_rCX, rs_rX86_SP, displacement);
         length_compare = NewLIR2(kX86Jcc8, 0, kX86CondLe);
-        OpRegMem(kOpSub, rCX, rX86_SP, displacement);
+        OpRegMem(kOpSub, rs_rCX, rs_rX86_SP, displacement);
       }
     }
   }
@@ -1101,14 +1099,14 @@
 
   // Load the address of the string into EBX.
   // The string starts at VALUE(String) + 2 * OFFSET(String) + DATA_OFFSET.
-  LoadWordDisp(rDX, value_offset, rDI);
-  LoadWordDisp(rDX, offset_offset, rBX);
-  OpLea(rBX, rDI, rBX, 1, data_offset);
+  LoadWordDisp(rs_rDX, value_offset, rs_rDI);
+  LoadWordDisp(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.
   if (zero_based || rl_start.is_const) {
     if (start_value == 0) {
-      OpRegCopy(rDI, rBX);
+      OpRegCopy(rs_rDI, rs_rBX);
     } else {
       NewLIR3(kX86Lea32RM, rDI, rBX, 2 * start_value);
     }
@@ -1117,17 +1115,17 @@
       if (rl_start.reg.GetReg() == rDI) {
         // We have a slight problem here.  We are already using RDI!
         // Grab the value from the stack.
-        LoadWordDisp(rX86_SP, 0, rDX);
-        OpLea(rDI, rBX, rDX, 1, 0);
+        LoadWordDisp(rs_rX86_SP, 0, rs_rDX);
+        OpLea(rs_rDI, rs_rBX, rs_rDX, 1, 0);
       } else {
-        OpLea(rDI, rBX, rl_start.reg.GetReg(), 1, 0);
+        OpLea(rs_rDI, rs_rBX, rl_start.reg, 1, 0);
       }
     } else {
-      OpRegCopy(rDI, rBX);
+      OpRegCopy(rs_rDI, rs_rBX);
       // Load the start index from stack, remembering that we pushed EDI.
       int displacement = SRegOffset(rl_start.s_reg_low) + sizeof(uint32_t);
-      LoadWordDisp(rX86_SP, displacement, rDX);
-      OpLea(rDI, rBX, rDX, 1, 0);
+      LoadWordDisp(rs_rX86_SP, displacement, rs_rDX);
+      OpLea(rs_rDI, rs_rBX, rs_rDX, 1, 0);
     }
   }
 
@@ -1140,8 +1138,8 @@
 
   // yes, we matched.  Compute the index of the result.
   // index = ((curr_ptr - orig_ptr) / 2) - 1.
-  OpRegReg(kOpSub, rDI, rBX);
-  OpRegImm(kOpAsr, rDI, 1);
+  OpRegReg(kOpSub, rs_rDI, rs_rBX);
+  OpRegImm(kOpAsr, rs_rDI, 1);
   NewLIR3(kX86Lea32RM, rl_return.reg.GetReg(), rDI, -1);
   LIR *all_done = NewLIR1(kX86Jmp8, 0);
 
@@ -1149,7 +1147,7 @@
   LIR *not_found = NewLIR0(kPseudoTargetLabel);
   length_compare->target = not_found;
   failed_branch->target = not_found;
-  LoadConstantNoClobber(rl_return.reg.GetReg(), -1);
+  LoadConstantNoClobber(rl_return.reg, -1);
 
   // And join up at the end.
   all_done->target = NewLIR0(kPseudoTargetLabel);
diff --git a/compiler/dex/quick/x86/utility_x86.cc b/compiler/dex/quick/x86/utility_x86.cc
index bd82bf6..013c40b 100644
--- a/compiler/dex/quick/x86/utility_x86.cc
+++ b/compiler/dex/quick/x86/utility_x86.cc
@@ -23,26 +23,26 @@
 
 /* This file contains codegen for the X86 ISA */
 
-LIR* X86Mir2Lir::OpFpRegCopy(int r_dest, int r_src) {
+LIR* X86Mir2Lir::OpFpRegCopy(RegStorage r_dest, RegStorage r_src) {
   int opcode;
   /* must be both DOUBLE or both not DOUBLE */
-  DCHECK_EQ(X86_DOUBLEREG(r_dest), X86_DOUBLEREG(r_src));
-  if (X86_DOUBLEREG(r_dest)) {
+  DCHECK_EQ(X86_DOUBLEREG(r_dest.GetReg()), X86_DOUBLEREG(r_src.GetReg()));
+  if (X86_DOUBLEREG(r_dest.GetReg())) {
     opcode = kX86MovsdRR;
   } else {
-    if (X86_SINGLEREG(r_dest)) {
-      if (X86_SINGLEREG(r_src)) {
+    if (X86_SINGLEREG(r_dest.GetReg())) {
+      if (X86_SINGLEREG(r_src.GetReg())) {
         opcode = kX86MovssRR;
       } else {  // Fpr <- Gpr
         opcode = kX86MovdxrRR;
       }
     } else {  // Gpr <- Fpr
-      DCHECK(X86_SINGLEREG(r_src));
+      DCHECK(X86_SINGLEREG(r_src.GetReg()));
       opcode = kX86MovdrxRR;
     }
   }
   DCHECK_NE((EncodingMap[opcode].flags & IS_BINARY_OP), 0ULL);
-  LIR* res = RawLIR(current_dalvik_offset_, opcode, r_dest, r_src);
+  LIR* res = RawLIR(current_dalvik_offset_, opcode, r_dest.GetReg(), r_src.GetReg());
   if (r_dest == r_src) {
     res->flags.is_nop = true;
   }
@@ -74,26 +74,26 @@
  * 1) r_dest is freshly returned from AllocTemp or
  * 2) The codegen is under fixed register usage
  */
-LIR* X86Mir2Lir::LoadConstantNoClobber(int r_dest, int value) {
-  int r_dest_save = r_dest;
-  if (X86_FPREG(r_dest)) {
+LIR* X86Mir2Lir::LoadConstantNoClobber(RegStorage r_dest, int value) {
+  RegStorage r_dest_save = r_dest;
+  if (X86_FPREG(r_dest.GetReg())) {
     if (value == 0) {
-      return NewLIR2(kX86XorpsRR, r_dest, r_dest);
+      return NewLIR2(kX86XorpsRR, r_dest.GetReg(), r_dest.GetReg());
     }
-    DCHECK(X86_SINGLEREG(r_dest));
+    DCHECK(X86_SINGLEREG(r_dest.GetReg()));
     r_dest = AllocTemp();
   }
 
   LIR *res;
   if (value == 0) {
-    res = NewLIR2(kX86Xor32RR, r_dest, r_dest);
+    res = NewLIR2(kX86Xor32RR, r_dest.GetReg(), r_dest.GetReg());
   } else {
     // Note, there is no byte immediate form of a 32 bit immediate move.
-    res = NewLIR2(kX86Mov32RI, r_dest, value);
+    res = NewLIR2(kX86Mov32RI, r_dest.GetReg(), value);
   }
 
-  if (X86_FPREG(r_dest_save)) {
-    NewLIR2(kX86MovdxrRR, r_dest_save, r_dest);
+  if (X86_FPREG(r_dest_save.GetReg())) {
+    NewLIR2(kX86MovdxrRR, r_dest_save.GetReg(), r_dest.GetReg());
     FreeTemp(r_dest);
   }
 
@@ -113,7 +113,7 @@
   return branch;
 }
 
-LIR* X86Mir2Lir::OpReg(OpKind op, int r_dest_src) {
+LIR* X86Mir2Lir::OpReg(OpKind op, RegStorage r_dest_src) {
   X86OpCode opcode = kX86Bkpt;
   switch (op) {
     case kOpNeg: opcode = kX86Neg32R; break;
@@ -123,13 +123,13 @@
     default:
       LOG(FATAL) << "Bad case in OpReg " << op;
   }
-  return NewLIR1(opcode, r_dest_src);
+  return NewLIR1(opcode, r_dest_src.GetReg());
 }
 
-LIR* X86Mir2Lir::OpRegImm(OpKind op, int r_dest_src1, int value) {
+LIR* X86Mir2Lir::OpRegImm(OpKind op, RegStorage r_dest_src1, int value) {
   X86OpCode opcode = kX86Bkpt;
   bool byte_imm = IS_SIMM8(value);
-  DCHECK(!X86_FPREG(r_dest_src1));
+  DCHECK(!X86_FPREG(r_dest_src1.GetReg()));
   switch (op) {
     case kOpLsl: opcode = kX86Sal32RI; break;
     case kOpLsr: opcode = kX86Shr32RI; break;
@@ -152,14 +152,14 @@
       break;
     case kOpMul:
       opcode = byte_imm ? kX86Imul32RRI8 : kX86Imul32RRI;
-      return NewLIR3(opcode, r_dest_src1, r_dest_src1, value);
+      return NewLIR3(opcode, r_dest_src1.GetReg(), r_dest_src1.GetReg(), value);
     default:
       LOG(FATAL) << "Bad case in OpRegImm " << op;
   }
-  return NewLIR2(opcode, r_dest_src1, value);
+  return NewLIR2(opcode, r_dest_src1.GetReg(), value);
 }
 
-LIR* X86Mir2Lir::OpRegReg(OpKind op, int r_dest_src1, int r_src2) {
+LIR* X86Mir2Lir::OpRegReg(OpKind op, RegStorage r_dest_src1, RegStorage r_src2) {
     X86OpCode opcode = kX86Nop;
     bool src2_must_be_cx = false;
     switch (op) {
@@ -192,10 +192,10 @@
       case kOpXor: opcode = kX86Xor32RR; break;
       case kOp2Byte:
         // Use shifts instead of a byte operand if the source can't be byte accessed.
-        if (r_src2 >= 4) {
-          NewLIR2(kX86Mov32RR, r_dest_src1, r_src2);
-          NewLIR2(kX86Sal32RI, r_dest_src1, 24);
-          return NewLIR2(kX86Sar32RI, r_dest_src1, 24);
+        if (r_src2.GetReg() >= 4) {
+          NewLIR2(kX86Mov32RR, r_dest_src1.GetReg(), r_src2.GetReg());
+          NewLIR2(kX86Sal32RI, r_dest_src1.GetReg(), 24);
+          return NewLIR2(kX86Sar32RI, r_dest_src1.GetReg(), 24);
         } else {
           opcode = kX86Movsx8RR;
         }
@@ -207,49 +207,49 @@
         LOG(FATAL) << "Bad case in OpRegReg " << op;
         break;
     }
-    CHECK(!src2_must_be_cx || r_src2 == rCX);
-    return NewLIR2(opcode, r_dest_src1, r_src2);
+    CHECK(!src2_must_be_cx || r_src2.GetReg() == rCX);
+    return NewLIR2(opcode, r_dest_src1.GetReg(), r_src2.GetReg());
 }
 
-LIR* X86Mir2Lir::OpMovRegMem(int r_dest, int r_base, int offset, MoveType move_type) {
-  DCHECK(!(X86_FPREG(r_base)));
-
+LIR* X86Mir2Lir::OpMovRegMem(RegStorage r_dest, RegStorage r_base, int offset, MoveType move_type) {
+  DCHECK(!(X86_FPREG(r_base.GetReg())));
   X86OpCode opcode = kX86Nop;
+  int dest = r_dest.IsPair() ? r_dest.GetLowReg() : r_dest.GetReg();
   switch (move_type) {
     case kMov8GP:
-      CHECK(!X86_FPREG(r_dest));
+      CHECK(!X86_FPREG(dest));
       opcode = kX86Mov8RM;
       break;
     case kMov16GP:
-      CHECK(!X86_FPREG(r_dest));
+      CHECK(!X86_FPREG(dest));
       opcode = kX86Mov16RM;
       break;
     case kMov32GP:
-      CHECK(!X86_FPREG(r_dest));
+      CHECK(!X86_FPREG(dest));
       opcode = kX86Mov32RM;
       break;
     case kMov32FP:
-      CHECK(X86_FPREG(r_dest));
+      CHECK(X86_FPREG(dest));
       opcode = kX86MovssRM;
       break;
     case kMov64FP:
-      CHECK(X86_FPREG(r_dest));
+      CHECK(X86_FPREG(dest));
       opcode = kX86MovsdRM;
       break;
     case kMovU128FP:
-      CHECK(X86_FPREG(r_dest));
+      CHECK(X86_FPREG(dest));
       opcode = kX86MovupsRM;
       break;
     case kMovA128FP:
-      CHECK(X86_FPREG(r_dest));
+      CHECK(X86_FPREG(dest));
       opcode = kX86MovapsRM;
       break;
     case kMovLo128FP:
-      CHECK(X86_FPREG(r_dest));
+      CHECK(X86_FPREG(dest));
       opcode = kX86MovlpsRM;
       break;
     case kMovHi128FP:
-      CHECK(X86_FPREG(r_dest));
+      CHECK(X86_FPREG(dest));
       opcode = kX86MovhpsRM;
       break;
     case kMov64GP:
@@ -260,48 +260,49 @@
       break;
   }
 
-  return NewLIR3(opcode, r_dest, r_base, offset);
+  return NewLIR3(opcode, dest, r_base.GetReg(), offset);
 }
 
-LIR* X86Mir2Lir::OpMovMemReg(int r_base, int offset, int r_src, MoveType move_type) {
-  DCHECK(!(X86_FPREG(r_base)));
+LIR* X86Mir2Lir::OpMovMemReg(RegStorage r_base, int offset, RegStorage r_src, MoveType move_type) {
+  DCHECK(!(X86_FPREG(r_base.GetReg())));
+  int src = r_src.IsPair() ? r_src.GetLowReg() : r_src.GetReg();
 
   X86OpCode opcode = kX86Nop;
   switch (move_type) {
     case kMov8GP:
-      CHECK(!X86_FPREG(r_src));
+      CHECK(!X86_FPREG(src));
       opcode = kX86Mov8MR;
       break;
     case kMov16GP:
-      CHECK(!X86_FPREG(r_src));
+      CHECK(!X86_FPREG(src));
       opcode = kX86Mov16MR;
       break;
     case kMov32GP:
-      CHECK(!X86_FPREG(r_src));
+      CHECK(!X86_FPREG(src));
       opcode = kX86Mov32MR;
       break;
     case kMov32FP:
-      CHECK(X86_FPREG(r_src));
+      CHECK(X86_FPREG(src));
       opcode = kX86MovssMR;
       break;
     case kMov64FP:
-      CHECK(X86_FPREG(r_src));
+      CHECK(X86_FPREG(src));
       opcode = kX86MovsdMR;
       break;
     case kMovU128FP:
-      CHECK(X86_FPREG(r_src));
+      CHECK(X86_FPREG(src));
       opcode = kX86MovupsMR;
       break;
     case kMovA128FP:
-      CHECK(X86_FPREG(r_src));
+      CHECK(X86_FPREG(src));
       opcode = kX86MovapsMR;
       break;
     case kMovLo128FP:
-      CHECK(X86_FPREG(r_src));
+      CHECK(X86_FPREG(src));
       opcode = kX86MovlpsMR;
       break;
     case kMovHi128FP:
-      CHECK(X86_FPREG(r_src));
+      CHECK(X86_FPREG(src));
       opcode = kX86MovhpsMR;
       break;
     case kMov64GP:
@@ -312,17 +313,16 @@
       break;
   }
 
-  return NewLIR3(opcode, r_base, offset, r_src);
+  return NewLIR3(opcode, r_base.GetReg(), offset, src);
 }
 
-LIR* X86Mir2Lir::OpCondRegReg(OpKind op, ConditionCode cc, int r_dest, int r_src) {
+LIR* X86Mir2Lir::OpCondRegReg(OpKind op, ConditionCode cc, RegStorage r_dest, RegStorage r_src) {
   // The only conditional reg to reg operation supported is Cmov
   DCHECK_EQ(op, kOpCmov);
-  return NewLIR3(kX86Cmov32RRC, r_dest, r_src, X86ConditionEncoding(cc));
+  return NewLIR3(kX86Cmov32RRC, r_dest.GetReg(), r_src.GetReg(), X86ConditionEncoding(cc));
 }
 
-LIR* X86Mir2Lir::OpRegMem(OpKind op, int r_dest, int rBase,
-              int offset) {
+LIR* X86Mir2Lir::OpRegMem(OpKind op, RegStorage r_dest, RegStorage r_base, int offset) {
   X86OpCode opcode = kX86Nop;
   switch (op) {
       // X86 binary opcodes
@@ -341,8 +341,8 @@
       LOG(FATAL) << "Bad case in OpRegMem " << op;
       break;
   }
-  LIR *l = NewLIR3(opcode, r_dest, rBase, offset);
-  if (rBase == rX86_SP) {
+  LIR *l = NewLIR3(opcode, r_dest.GetReg(), r_base.GetReg(), offset);
+  if (r_base == rs_rX86_SP) {
     AnnotateDalvikRegAccess(l, offset >> 2, true /* is_load */, false /* is_64bit */);
   }
   return l;
@@ -372,7 +372,7 @@
   return l;
 }
 
-LIR* X86Mir2Lir::OpRegMem(OpKind op, int r_dest, RegLocation rl_value) {
+LIR* X86Mir2Lir::OpRegMem(OpKind op, RegStorage r_dest, RegLocation rl_value) {
   DCHECK_NE(rl_value.location, kLocPhysReg);
   int displacement = SRegOffset(rl_value.s_reg_low);
   X86OpCode opcode = kX86Nop;
@@ -389,24 +389,24 @@
       LOG(FATAL) << "Bad case in OpRegMem " << op;
       break;
   }
-  LIR *l = NewLIR3(opcode, r_dest, rX86_SP, displacement);
+  LIR *l = NewLIR3(opcode, r_dest.GetReg(), rX86_SP, displacement);
   AnnotateDalvikRegAccess(l, displacement >> 2, true /* is_load */, false /* is_64bit */);
   return l;
 }
 
-LIR* X86Mir2Lir::OpRegRegReg(OpKind op, int r_dest, int r_src1,
-                 int r_src2) {
+LIR* X86Mir2Lir::OpRegRegReg(OpKind op, RegStorage r_dest, RegStorage r_src1,
+                             RegStorage r_src2) {
   if (r_dest != r_src1 && r_dest != r_src2) {
     if (op == kOpAdd) {  // lea special case, except can't encode rbp as base
       if (r_src1 == r_src2) {
         OpRegCopy(r_dest, r_src1);
         return OpRegImm(kOpLsl, r_dest, 1);
-      } else if (r_src1 != rBP) {
-        return NewLIR5(kX86Lea32RA, r_dest, r_src1 /* base */,
-                       r_src2 /* index */, 0 /* scale */, 0 /* disp */);
+      } else if (r_src1 != rs_rBP) {
+        return NewLIR5(kX86Lea32RA, r_dest.GetReg(), r_src1.GetReg() /* base */,
+                       r_src2.GetReg() /* index */, 0 /* scale */, 0 /* disp */);
       } else {
-        return NewLIR5(kX86Lea32RA, r_dest, r_src2 /* base */,
-                       r_src1 /* index */, 0 /* scale */, 0 /* disp */);
+        return NewLIR5(kX86Lea32RA, r_dest.GetReg(), r_src2.GetReg() /* base */,
+                       r_src1.GetReg() /* index */, 0 /* scale */, 0 /* disp */);
       }
     } else {
       OpRegCopy(r_dest, r_src1);
@@ -422,7 +422,7 @@
         break;
       case kOpSbc:
       case kOpLsl: case kOpLsr: case kOpAsr: case kOpRor: {
-        int t_reg = AllocTemp();
+        RegStorage t_reg = AllocTemp();
         OpRegCopy(t_reg, r_src1);
         OpRegReg(op, t_reg, r_src2);
         LIR* res = OpRegCopy(r_dest, t_reg);
@@ -442,25 +442,24 @@
   }
 }
 
-LIR* X86Mir2Lir::OpRegRegImm(OpKind op, int r_dest, int r_src,
-                 int value) {
+LIR* X86Mir2Lir::OpRegRegImm(OpKind op, RegStorage r_dest, RegStorage r_src, int value) {
   if (op == kOpMul) {
     X86OpCode opcode = IS_SIMM8(value) ? kX86Imul32RRI8 : kX86Imul32RRI;
-    return NewLIR3(opcode, r_dest, r_src, value);
+    return NewLIR3(opcode, r_dest.GetReg(), r_src.GetReg(), value);
   } else if (op == kOpAnd) {
-    if (value == 0xFF && r_src < 4) {
-      return NewLIR2(kX86Movzx8RR, r_dest, r_src);
+    if (value == 0xFF && r_src.GetReg() < 4) {
+      return NewLIR2(kX86Movzx8RR, r_dest.GetReg(), r_src.GetReg());
     } else if (value == 0xFFFF) {
-      return NewLIR2(kX86Movzx16RR, r_dest, r_src);
+      return NewLIR2(kX86Movzx16RR, r_dest.GetReg(), r_src.GetReg());
     }
   }
   if (r_dest != r_src) {
     if (false && op == kOpLsl && value >= 0 && value <= 3) {  // lea shift special case
       // TODO: fix bug in LEA encoding when disp == 0
-      return NewLIR5(kX86Lea32RA, r_dest,  r5sib_no_base /* base */,
-                     r_src /* index */, value /* scale */, 0 /* disp */);
+      return NewLIR5(kX86Lea32RA, r_dest.GetReg(),  r5sib_no_base /* base */,
+                     r_src.GetReg() /* index */, value /* scale */, 0 /* disp */);
     } else if (op == kOpAdd) {  // lea add special case
-      return NewLIR5(kX86Lea32RA, r_dest, r_src /* base */,
+      return NewLIR5(kX86Lea32RA, r_dest.GetReg(), r_src.GetReg() /* base */,
                      r4sib_no_index /* index */, 0 /* scale */, value /* disp */);
     }
     OpRegCopy(r_dest, r_src);
@@ -480,7 +479,7 @@
   return NewLIR1(opcode, thread_offset.Int32Value());
 }
 
-LIR* X86Mir2Lir::OpMem(OpKind op, int rBase, int disp) {
+LIR* X86Mir2Lir::OpMem(OpKind op, RegStorage r_base, int disp) {
   X86OpCode opcode = kX86Bkpt;
   switch (op) {
     case kOpBlx: opcode = kX86CallM;  break;
@@ -488,18 +487,19 @@
       LOG(FATAL) << "Bad opcode: " << op;
       break;
   }
-  return NewLIR2(opcode, rBase, disp);
+  return NewLIR2(opcode, r_base.GetReg(), disp);
 }
 
-LIR* X86Mir2Lir::LoadConstantWide(int r_dest_lo, int r_dest_hi, int64_t value) {
+LIR* X86Mir2Lir::LoadConstantWide(RegStorage r_dest, int64_t value) {
     int32_t val_lo = Low32Bits(value);
     int32_t val_hi = High32Bits(value);
+    int32_t low_reg_val = r_dest.IsPair() ? r_dest.GetLowReg() : r_dest.GetReg();
     LIR *res;
-    if (X86_FPREG(r_dest_lo)) {
-      DCHECK(X86_FPREG(r_dest_hi));  // ignore r_dest_hi
-      DCHECK_EQ(r_dest_lo, r_dest_hi);
+    bool is_fp = X86_FPREG(low_reg_val);
+    // TODO: clean this up once we fully recognize 64-bit storage containers.
+    if (is_fp) {
       if (value == 0) {
-        return NewLIR2(kX86XorpsRR, r_dest_lo, r_dest_lo);
+        return NewLIR2(kX86XorpsRR, low_reg_val, low_reg_val);
       } else if (base_of_code_ != nullptr) {
         // We will load the value from the literal area.
         LIR* data_target = ScanLiteralPoolWide(literal_list_, val_lo, val_hi);
@@ -515,45 +515,49 @@
         // We don't know the proper offset for the value, so pick one that will force
         // 4 byte offset.  We will fix this up in the assembler later to have the right
         // value.
-        res = LoadBaseDisp(rl_method.reg.GetReg(), 256 /* bogus */, r_dest_lo, kDouble, INVALID_SREG);
+        res = LoadBaseDisp(rl_method.reg, 256 /* bogus */, RegStorage::Solo64(low_reg_val),
+                           kDouble, INVALID_SREG);
         res->target = data_target;
         res->flags.fixup = kFixupLoad;
         SetMemRefType(res, true, kLiteral);
         store_method_addr_used_ = true;
       } else {
         if (val_lo == 0) {
-          res = NewLIR2(kX86XorpsRR, r_dest_lo, r_dest_lo);
+          res = NewLIR2(kX86XorpsRR, low_reg_val, low_reg_val);
         } else {
-          res = LoadConstantNoClobber(r_dest_lo, val_lo);
+          res = LoadConstantNoClobber(RegStorage::Solo32(low_reg_val), val_lo);
         }
         if (val_hi != 0) {
-          r_dest_hi = AllocTempDouble();
-          LoadConstantNoClobber(r_dest_hi, val_hi);
-          NewLIR2(kX86PunpckldqRR, r_dest_lo, r_dest_hi);
+          // FIXME: clean up when AllocTempDouble no longer returns a pair.
+          RegStorage r_dest_hi = AllocTempDouble();
+          LoadConstantNoClobber(RegStorage::Solo32(r_dest_hi.GetLowReg()), val_hi);
+          NewLIR2(kX86PunpckldqRR, low_reg_val, r_dest_hi.GetLowReg());
           FreeTemp(r_dest_hi);
         }
       }
     } else {
-      res = LoadConstantNoClobber(r_dest_lo, val_lo);
-      LoadConstantNoClobber(r_dest_hi, val_hi);
+      res = LoadConstantNoClobber(r_dest.GetLow(), val_lo);
+      LoadConstantNoClobber(r_dest.GetHigh(), val_hi);
     }
     return res;
 }
 
-LIR* X86Mir2Lir::LoadBaseIndexedDisp(int rBase, int r_index, int scale,
-                                     int displacement, int r_dest, int r_dest_hi, OpSize size,
-                                     int s_reg) {
+// FIXME: don't split r_dest into two storage units.
+LIR* X86Mir2Lir::LoadBaseIndexedDisp(RegStorage r_base, RegStorage r_index, int scale,
+                                     int displacement, RegStorage r_dest, RegStorage r_dest_hi,
+                                     OpSize size, int s_reg) {
   LIR *load = NULL;
   LIR *load2 = NULL;
-  bool is_array = r_index != INVALID_REG;
+  bool is_array = r_index.Valid();
   bool pair = false;
   bool is64bit = false;
   X86OpCode opcode = kX86Nop;
   switch (size) {
     case kLong:
     case kDouble:
+      // TODO: use regstorage attributes here.
       is64bit = true;
-      if (X86_FPREG(r_dest)) {
+      if (X86_FPREG(r_dest.GetReg())) {
         opcode = is_array ? kX86MovsdRA : kX86MovsdRM;
       } else {
         pair = true;
@@ -565,9 +569,9 @@
     case kWord:
     case kSingle:
       opcode = is_array ? kX86Mov32RA : kX86Mov32RM;
-      if (X86_FPREG(r_dest)) {
+      if (X86_FPREG(r_dest.GetReg())) {
         opcode = is_array ? kX86MovssRA : kX86MovssRM;
-        DCHECK(X86_SINGLEREG(r_dest));
+        DCHECK(X86_SINGLEREG(r_dest.GetReg()));
       }
       DCHECK_EQ((displacement & 0x3), 0);
       break;
@@ -591,19 +595,19 @@
 
   if (!is_array) {
     if (!pair) {
-      load = NewLIR3(opcode, r_dest, rBase, displacement + LOWORD_OFFSET);
+      load = NewLIR3(opcode, r_dest.GetReg(), r_base.GetReg(), displacement + LOWORD_OFFSET);
     } else {
-      if (rBase == r_dest) {
-        load2 = NewLIR3(opcode, r_dest_hi, rBase,
+      if (r_base == r_dest) {
+        load2 = NewLIR3(opcode, r_dest_hi.GetReg(), r_base.GetReg(),
                         displacement + HIWORD_OFFSET);
-        load = NewLIR3(opcode, r_dest, rBase, displacement + LOWORD_OFFSET);
+        load = NewLIR3(opcode, r_dest.GetReg(), r_base.GetReg(), displacement + LOWORD_OFFSET);
       } else {
-        load = NewLIR3(opcode, r_dest, rBase, displacement + LOWORD_OFFSET);
-        load2 = NewLIR3(opcode, r_dest_hi, rBase,
+        load = NewLIR3(opcode, r_dest.GetReg(), r_base.GetReg(), displacement + LOWORD_OFFSET);
+        load2 = NewLIR3(opcode, r_dest_hi.GetReg(), r_base.GetReg(),
                         displacement + HIWORD_OFFSET);
       }
     }
-    if (rBase == rX86_SP) {
+    if (r_base == rs_rX86_SP) {
       AnnotateDalvikRegAccess(load, (displacement + (pair ? LOWORD_OFFSET : 0)) >> 2,
                               true /* is_load */, is64bit);
       if (pair) {
@@ -613,39 +617,39 @@
     }
   } else {
     if (!pair) {
-      load = NewLIR5(opcode, r_dest, rBase, r_index, scale,
+      load = NewLIR5(opcode, r_dest.GetReg(), r_base.GetReg(), r_index.GetReg(), scale,
                      displacement + LOWORD_OFFSET);
     } else {
-      if (rBase == r_dest) {
+      if (r_base == r_dest) {
         if (r_dest_hi == r_index) {
           // We can't use either register for the first load.
-          int temp = AllocTemp();
-          load2 = NewLIR5(opcode, temp, rBase, r_index, scale,
+          RegStorage temp = AllocTemp();
+          load2 = NewLIR5(opcode, temp.GetReg(), r_base.GetReg(), r_index.GetReg(), scale,
                           displacement + HIWORD_OFFSET);
-          load = NewLIR5(opcode, r_dest, rBase, r_index, scale,
+          load = NewLIR5(opcode, r_dest.GetReg(), r_base.GetReg(), r_index.GetReg(), scale,
                          displacement + LOWORD_OFFSET);
           OpRegCopy(r_dest_hi, temp);
           FreeTemp(temp);
         } else {
-          load2 = NewLIR5(opcode, r_dest_hi, rBase, r_index, scale,
+          load2 = NewLIR5(opcode, r_dest_hi.GetReg(), r_base.GetReg(), r_index.GetReg(), scale,
                           displacement + HIWORD_OFFSET);
-          load = NewLIR5(opcode, r_dest, rBase, r_index, scale,
+          load = NewLIR5(opcode, r_dest.GetReg(), r_base.GetReg(), r_index.GetReg(), scale,
                          displacement + LOWORD_OFFSET);
         }
       } else {
         if (r_dest == r_index) {
           // We can't use either register for the first load.
-          int temp = AllocTemp();
-          load = NewLIR5(opcode, temp, rBase, r_index, scale,
+          RegStorage temp = AllocTemp();
+          load = NewLIR5(opcode, temp.GetReg(), r_base.GetReg(), r_index.GetReg(), scale,
                          displacement + LOWORD_OFFSET);
-          load2 = NewLIR5(opcode, r_dest_hi, rBase, r_index, scale,
+          load2 = NewLIR5(opcode, r_dest_hi.GetReg(), r_base.GetReg(), r_index.GetReg(), scale,
                           displacement + HIWORD_OFFSET);
           OpRegCopy(r_dest, temp);
           FreeTemp(temp);
         } else {
-          load = NewLIR5(opcode, r_dest, rBase, r_index, scale,
+          load = NewLIR5(opcode, r_dest.GetReg(), r_base.GetReg(), r_index.GetReg(), scale,
                          displacement + LOWORD_OFFSET);
-          load2 = NewLIR5(opcode, r_dest_hi, rBase, r_index, scale,
+          load2 = NewLIR5(opcode, r_dest_hi.GetReg(), r_base.GetReg(), r_index.GetReg(), scale,
                           displacement + HIWORD_OFFSET);
         }
       }
@@ -656,30 +660,31 @@
 }
 
 /* Load value from base + scaled index. */
-LIR* X86Mir2Lir::LoadBaseIndexed(int rBase,
-                     int r_index, int r_dest, int scale, OpSize size) {
-  return LoadBaseIndexedDisp(rBase, r_index, scale, 0,
-                             r_dest, INVALID_REG, size, INVALID_SREG);
+LIR* X86Mir2Lir::LoadBaseIndexed(RegStorage r_base, RegStorage r_index, RegStorage r_dest,
+                                 int scale, OpSize size) {
+  return LoadBaseIndexedDisp(r_base, r_index, scale, 0,
+                             r_dest, RegStorage::InvalidReg(), size, INVALID_SREG);
 }
 
-LIR* X86Mir2Lir::LoadBaseDisp(int rBase, int displacement,
-                  int r_dest, OpSize size, int s_reg) {
-  return LoadBaseIndexedDisp(rBase, INVALID_REG, 0, displacement,
-                             r_dest, INVALID_REG, size, s_reg);
+LIR* X86Mir2Lir::LoadBaseDisp(RegStorage r_base, int displacement,
+                  RegStorage r_dest, OpSize size, int s_reg) {
+  return LoadBaseIndexedDisp(r_base, RegStorage::InvalidReg(), 0, displacement,
+                             r_dest, RegStorage::InvalidReg(), size, s_reg);
 }
 
-LIR* X86Mir2Lir::LoadBaseDispWide(int rBase, int displacement,
-                      int r_dest_lo, int r_dest_hi, int s_reg) {
-  return LoadBaseIndexedDisp(rBase, INVALID_REG, 0, displacement,
-                             r_dest_lo, r_dest_hi, kLong, s_reg);
+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);
 }
 
-LIR* X86Mir2Lir::StoreBaseIndexedDisp(int rBase, int r_index, int scale,
-                                      int displacement, int r_src, int r_src_hi, OpSize size,
-                                      int s_reg) {
+LIR* X86Mir2Lir::StoreBaseIndexedDisp(RegStorage r_base, RegStorage r_index, int scale,
+                                      int displacement, RegStorage r_src, RegStorage r_src_hi,
+                                      OpSize size, int s_reg) {
   LIR *store = NULL;
   LIR *store2 = NULL;
-  bool is_array = r_index != INVALID_REG;
+  bool is_array = r_index.Valid();
+  // FIXME: use regstorage attributes in place of these.
   bool pair = false;
   bool is64bit = false;
   X86OpCode opcode = kX86Nop;
@@ -687,7 +692,7 @@
     case kLong:
     case kDouble:
       is64bit = true;
-      if (X86_FPREG(r_src)) {
+      if (X86_FPREG(r_src.GetReg())) {
         opcode = is_array ? kX86MovsdAR : kX86MovsdMR;
       } else {
         pair = true;
@@ -699,9 +704,9 @@
     case kWord:
     case kSingle:
       opcode = is_array ? kX86Mov32AR : kX86Mov32MR;
-      if (X86_FPREG(r_src)) {
+      if (X86_FPREG(r_src.GetReg())) {
         opcode = is_array ? kX86MovssAR : kX86MovssMR;
-        DCHECK(X86_SINGLEREG(r_src));
+        DCHECK(X86_SINGLEREG(r_src.GetReg()));
       }
       DCHECK_EQ((displacement & 0x3), 0);
       break;
@@ -720,12 +725,12 @@
 
   if (!is_array) {
     if (!pair) {
-      store = NewLIR3(opcode, rBase, displacement + LOWORD_OFFSET, r_src);
+      store = NewLIR3(opcode, r_base.GetReg(), displacement + LOWORD_OFFSET, r_src.GetReg());
     } else {
-      store = NewLIR3(opcode, rBase, displacement + LOWORD_OFFSET, r_src);
-      store2 = NewLIR3(opcode, rBase, displacement + HIWORD_OFFSET, r_src_hi);
+      store = NewLIR3(opcode, r_base.GetReg(), displacement + LOWORD_OFFSET, r_src.GetReg());
+      store2 = NewLIR3(opcode, r_base.GetReg(), displacement + HIWORD_OFFSET, r_src_hi.GetReg());
     }
-    if (rBase == rX86_SP) {
+    if (r_base == rs_rX86_SP) {
       AnnotateDalvikRegAccess(store, (displacement + (pair ? LOWORD_OFFSET : 0)) >> 2,
                               false /* is_load */, is64bit);
       if (pair) {
@@ -735,13 +740,13 @@
     }
   } else {
     if (!pair) {
-      store = NewLIR5(opcode, rBase, r_index, scale,
-                      displacement + LOWORD_OFFSET, r_src);
+      store = NewLIR5(opcode, r_base.GetReg(), r_index.GetReg(), scale,
+                      displacement + LOWORD_OFFSET, r_src.GetReg());
     } else {
-      store = NewLIR5(opcode, rBase, r_index, scale,
-                      displacement + LOWORD_OFFSET, r_src);
-      store2 = NewLIR5(opcode, rBase, r_index, scale,
-                       displacement + HIWORD_OFFSET, r_src_hi);
+      store = NewLIR5(opcode, r_base.GetReg(), r_index.GetReg(), scale,
+                      displacement + LOWORD_OFFSET, r_src.GetReg());
+      store2 = NewLIR5(opcode, r_base.GetReg(), r_index.GetReg(), scale,
+                       displacement + HIWORD_OFFSET, r_src_hi.GetReg());
     }
   }
 
@@ -749,23 +754,21 @@
 }
 
 /* store value base base + scaled index. */
-LIR* X86Mir2Lir::StoreBaseIndexed(int rBase, int r_index, int r_src,
+LIR* X86Mir2Lir::StoreBaseIndexed(RegStorage r_base, RegStorage r_index, RegStorage r_src,
                       int scale, OpSize size) {
-  return StoreBaseIndexedDisp(rBase, r_index, scale, 0,
-                              r_src, INVALID_REG, size, INVALID_SREG);
+  return StoreBaseIndexedDisp(r_base, r_index, scale, 0,
+                              r_src, RegStorage::InvalidReg(), size, INVALID_SREG);
 }
 
-LIR* X86Mir2Lir::StoreBaseDisp(int rBase, int displacement,
-                               int r_src, OpSize size) {
-    return StoreBaseIndexedDisp(rBase, INVALID_REG, 0,
-                                displacement, r_src, INVALID_REG, size,
-                                INVALID_SREG);
+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);
 }
 
-LIR* X86Mir2Lir::StoreBaseDispWide(int rBase, int displacement,
-                                   int r_src_lo, int r_src_hi) {
-  return StoreBaseIndexedDisp(rBase, INVALID_REG, 0, displacement,
-                              r_src_lo, r_src_hi, kLong, 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);
 }
 
 /*
@@ -774,15 +777,15 @@
  */
 void X86Mir2Lir::OpVectorRegCopyWide(uint8_t fp_reg, uint8_t low_reg, uint8_t high_reg) {
   NewLIR2(kX86MovdxrRR, fp_reg, low_reg);
-  int tmp_reg = AllocTempDouble();
+  int tmp_reg = AllocTempDouble().GetLowReg();
   NewLIR2(kX86MovdxrRR, tmp_reg, high_reg);
   NewLIR2(kX86PunpckldqRR, fp_reg, tmp_reg);
   FreeTemp(tmp_reg);
 }
 
-LIR* X86Mir2Lir::OpCmpMemImmBranch(ConditionCode cond, int temp_reg, int base_reg,
+LIR* X86Mir2Lir::OpCmpMemImmBranch(ConditionCode cond, RegStorage temp_reg, RegStorage base_reg,
                                    int offset, int check_value, LIR* target) {
-    NewLIR3(IS_SIMM8(check_value) ? kX86Cmp32MI8 : kX86Cmp32MI, base_reg, offset,
+    NewLIR3(IS_SIMM8(check_value) ? kX86Cmp32MI8 : kX86Cmp32MI, base_reg.GetReg(), offset,
             check_value);
     LIR* branch = OpCondBranch(cond, target);
     return branch;
diff --git a/compiler/dex/quick/x86/x86_lir.h b/compiler/dex/quick/x86/x86_lir.h
index b72e60d..797bc82 100644
--- a/compiler/dex/quick/x86/x86_lir.h
+++ b/compiler/dex/quick/x86/x86_lir.h
@@ -189,22 +189,52 @@
   fr15 = 15 + X86_FP_REG_OFFSET,
 };
 
+const RegStorage rs_r0(RegStorage::k32BitSolo, r0);
+const RegStorage rs_rAX = rs_r0;
+const RegStorage rs_r1(RegStorage::k32BitSolo, r1);
+const RegStorage rs_rCX = rs_r1;
+const RegStorage rs_r2(RegStorage::k32BitSolo, r2);
+const RegStorage rs_rDX = rs_r2;
+const RegStorage rs_r3(RegStorage::k32BitSolo, r3);
+const RegStorage rs_rBX = rs_r3;
+const RegStorage rs_r4sp(RegStorage::k32BitSolo, r4sp);
+const RegStorage rs_rX86_SP = rs_r4sp;
+const RegStorage rs_r5(RegStorage::k32BitSolo, r5);
+const RegStorage rs_rBP = rs_r5;
+const RegStorage rs_r6(RegStorage::k32BitSolo, r6);
+const RegStorage rs_rSI = rs_r6;
+const RegStorage rs_r7(RegStorage::k32BitSolo, r7);
+const RegStorage rs_rDI = rs_r7;
+
+// TODO: elminate these #defines?
 #define rX86_ARG0 rAX
+#define rs_rX86_ARG0 rs_rAX
 #define rX86_ARG1 rCX
+#define rs_rX86_ARG1 rs_rCX
 #define rX86_ARG2 rDX
+#define rs_rX86_ARG2 rs_rDX
 #define rX86_ARG3 rBX
+#define rs_rX86_ARG3 rs_rBX
 #define rX86_FARG0 rAX
+#define rs_rX86_FARG0 rs_rAX
 #define rX86_FARG1 rCX
+#define rs_rX86_FARG1 rs_rCX
 #define rX86_FARG2 rDX
+#define rs_rX86_FARG2 rs_rDX
 #define rX86_FARG3 rBX
+#define rs_rX86_FARG3 rs_rBX
 #define rX86_RET0 rAX
+#define rs_rX86_RET0 rs_rAX
 #define rX86_RET1 rDX
+#define rs_rX86_RET1 rs_rDX
 #define rX86_INVOKE_TGT rAX
-#define rX86_LR INVALID_REG
-#define rX86_SUSPEND INVALID_REG
-#define rX86_SELF INVALID_REG
+#define rs_rX86_INVOKE_TGT rs_rAX
+#define rX86_LR RegStorage::kInvalidRegVal
+#define rX86_SUSPEND RegStorage::kInvalidRegVal
+#define rX86_SELF RegStorage::kInvalidRegVal
 #define rX86_COUNT rCX
-#define rX86_PC INVALID_REG
+#define rs_rX86_COUNT rs_rCX
+#define rX86_PC RegStorage::kInvalidRegVal
 
 // RegisterLocation templates return values (r_V0, or r_V0/r_V1).
 const RegLocation x86_loc_c_return
diff --git a/compiler/dex/reg_storage.h b/compiler/dex/reg_storage.h
index c59617e..11bec99 100644
--- a/compiler/dex/reg_storage.h
+++ b/compiler/dex/reg_storage.h
@@ -72,6 +72,7 @@
   };
 
   static const uint16_t kRegValMask = 0x007f;
+  static const uint16_t kInvalidRegVal = 0x007f;
   static const uint16_t kHighRegShift = 7;
   static const uint16_t kHighRegMask = kRegValMask << kHighRegShift;
 
@@ -92,45 +93,64 @@
   RegStorage() : reg_(kInvalid) {}
   ~RegStorage() {}
 
-  bool IsInvalid() const {
-    return ((reg_ & kShapeMask) == kInvalid);
+  bool operator==(const RegStorage rhs) const {
+    return (reg_ == rhs.GetRawBits());
+  }
+
+  bool operator!=(const RegStorage rhs) const {
+    return (reg_ != rhs.GetRawBits());
+  }
+
+  bool Valid() const {
+    return ((reg_ & kShapeMask) != kInvalid);
   }
 
   bool Is32Bit() const {
-    DCHECK(!IsInvalid());
     return ((reg_ & kSizeMask) == k32Bit);
   }
 
   bool Is64Bit() const {
-    DCHECK(!IsInvalid());
     return ((reg_ & kSizeMask) == k64Bit);
   }
 
   bool IsPair() const {
-    DCHECK(!IsInvalid());
     return ((reg_ & kPairMask) == kPair);
   }
 
   bool IsSolo() const {
-    DCHECK(!IsInvalid());
     return ((reg_ & kVectorMask) == kSolo);
   }
 
   bool IsVector() const {
-    DCHECK(!IsInvalid());
     return ((reg_ & kVectorMask) == kVector);
   }
 
   // Used to retrieve either the low register of a pair, or the only register.
   int GetReg() const {
-    DCHECK(!IsInvalid());
-    return (reg_ & kRegValMask);
+    DCHECK(!IsPair());
+    return Valid() ? (reg_ & kRegValMask) : kInvalidRegVal;
   }
 
   void SetReg(int reg) {
-    DCHECK(!IsInvalid());
+    DCHECK(Valid());
     reg_ = (reg_ & ~kRegValMask) | reg;
-    DCHECK_EQ(GetReg(), reg);
+  }
+
+  void SetLowReg(int reg) {
+    DCHECK(IsPair());
+    reg_ = (reg_ & ~kRegValMask) | reg;
+  }
+
+  // Retrieve the least significant register of a pair.
+  int GetLowReg() const {
+    DCHECK(IsPair());
+    return (reg_ & kRegValMask);
+  }
+
+  // Create a stand-alone RegStorage from the low reg of a pair.
+  RegStorage GetLow() const {
+    DCHECK(IsPair());
+    return RegStorage(k32BitSolo, reg_ & kRegValMask);
   }
 
   // Retrieve the most significant register of a pair.
@@ -139,12 +159,41 @@
     return (reg_ & kHighRegMask) >> kHighRegShift;
   }
 
+  // Create a stand-alone RegStorage from the high reg of a pair.
+  RegStorage GetHigh() const {
+    DCHECK(IsPair());
+    return RegStorage(k32BitSolo, (reg_ & kHighRegMask) >> kHighRegShift);
+  }
+
   void SetHighReg(int reg) {
     DCHECK(IsPair());
     reg_ = (reg_ & ~kHighRegMask) | (reg << kHighRegShift);
     DCHECK_EQ(GetHighReg(), reg);
   }
 
+  // Combine 2 32-bit solo regs into a pair.
+  static RegStorage MakeRegPair(RegStorage low, RegStorage high) {
+    DCHECK(!low.IsPair());
+    DCHECK(low.Is32Bit());
+    DCHECK(!high.IsPair());
+    DCHECK(high.Is32Bit());
+    return RegStorage(k64BitPair, low.GetReg(), high.GetReg());
+  }
+
+  // Create a 32-bit solo.
+  static RegStorage Solo32(int reg_num) {
+    return RegStorage(k32BitSolo, reg_num);
+  }
+
+  // Create a 64-bit solo.
+  static RegStorage Solo64(int reg_num) {
+    return RegStorage(k64BitSolo, reg_num);
+  }
+
+  static RegStorage InvalidReg() {
+    return RegStorage(kInvalid);
+  }
+
   int GetRawBits() const {
     return reg_;
   }