Merge "ART: Add another special case to GenSelect for ARM64"
diff --git a/compiler/dex/compiler_enums.h b/compiler/dex/compiler_enums.h
index bdedadb..69adb35 100644
--- a/compiler/dex/compiler_enums.h
+++ b/compiler/dex/compiler_enums.h
@@ -548,6 +548,14 @@
 
 std::ostream& operator<<(std::ostream& os, const VolatileKind& kind);
 
+enum WideKind {
+  kNotWide,      // Non-wide view
+  kWide,         // Wide view
+  kRef           // Ref width
+};
+
+std::ostream& operator<<(std::ostream& os, const WideKind& kind);
+
 }  // namespace art
 
 #endif  // ART_COMPILER_DEX_COMPILER_ENUMS_H_
diff --git a/compiler/dex/quick/arm64/arm64_lir.h b/compiler/dex/quick/arm64/arm64_lir.h
index ef4c0de..d0633af 100644
--- a/compiler/dex/quick/arm64/arm64_lir.h
+++ b/compiler/dex/quick/arm64/arm64_lir.h
@@ -319,6 +319,7 @@
   kA64Scvtf2fx,      // scvtf  [100111100s100010000000] rn[9-5] rd[4-0].
   kA64Sdiv3rrr,      // sdiv[s0011010110] rm[20-16] [000011] rn[9-5] rd[4-0].
   kA64Smaddl4xwwx,   // smaddl [10011011001] rm[20-16] [0] ra[14-10] rn[9-5] rd[4-0].
+  kA64Smulh3xxx,     // smulh [10011011010] rm[20-16] [011111] rn[9-5] rd[4-0].
   kA64Stp4ffXD,      // stp [0s10110100] imm_7[21-15] rt2[14-10] rn[9-5] rt[4-0].
   kA64Stp4rrXD,      // stp [s010100100] imm_7[21-15] rt2[14-10] rn[9-5] rt[4-0].
   kA64StpPost4rrXD,  // stp [s010100010] imm_7[21-15] rt2[14-10] rn[9-5] rt[4-0].
diff --git a/compiler/dex/quick/arm64/assemble_arm64.cc b/compiler/dex/quick/arm64/assemble_arm64.cc
index 416a13e..083277d 100644
--- a/compiler/dex/quick/arm64/assemble_arm64.cc
+++ b/compiler/dex/quick/arm64/assemble_arm64.cc
@@ -502,6 +502,10 @@
                  kFmtRegX, 4, 0, kFmtRegW, 9, 5, kFmtRegW, 20, 16,
                  kFmtRegX, 14, 10, IS_QUAD_OP | REG_DEF0_USE123,
                  "smaddl", "!0x, !1w, !2w, !3x", kFixupNone),
+    ENCODING_MAP(kA64Smulh3xxx, NO_VARIANTS(0x9b407c00),
+                 kFmtRegX, 4, 0, kFmtRegX, 9, 5, kFmtRegX, 20, 16,
+                 kFmtUnused, -1, -1, IS_TERTIARY_OP | REG_DEF0_USE12,
+                 "smulh", "!0x, !1x, !2x", kFixupNone),
     ENCODING_MAP(WIDE(kA64Stp4ffXD), CUSTOM_VARIANTS(0x2d000000, 0x6d000000),
                  kFmtRegF, 4, 0, kFmtRegF, 14, 10, kFmtRegXOrSp, 9, 5,
                  kFmtBitBlt, 21, 15, IS_QUAD_OP | REG_USE012 | IS_STORE,
diff --git a/compiler/dex/quick/arm64/call_arm64.cc b/compiler/dex/quick/arm64/call_arm64.cc
index d24f419..8117c62 100644
--- a/compiler/dex/quick/arm64/call_arm64.cc
+++ b/compiler/dex/quick/arm64/call_arm64.cc
@@ -195,7 +195,7 @@
   // TUNING: How much performance we get when we inline this?
   // Since we've already flush all register.
   FlushAllRegs();
-  LoadValueDirectFixed(rl_src, rs_x0);  // = TargetRefReg(kArg0)
+  LoadValueDirectFixed(rl_src, rs_x0);  // = TargetReg(kArg0, kRef)
   LockCallTemps();  // Prepare for explicit register usage
   LIR* null_check_branch = nullptr;
   if ((opt_flags & MIR_IGNORE_NULL_CHECK) && !(cu_->disable_opt & (1 << kNullCheckElimination))) {
diff --git a/compiler/dex/quick/arm64/codegen_arm64.h b/compiler/dex/quick/arm64/codegen_arm64.h
index 060509b..e4eeeaf 100644
--- a/compiler/dex/quick/arm64/codegen_arm64.h
+++ b/compiler/dex/quick/arm64/codegen_arm64.h
@@ -65,8 +65,12 @@
     // Required for target - codegen helpers.
     bool SmallLiteralDivRem(Instruction::Code dalvik_opcode, bool is_div, RegLocation rl_src,
                             RegLocation rl_dest, int lit) OVERRIDE;
+    bool SmallLiteralDivRem64(Instruction::Code dalvik_opcode, bool is_div, RegLocation rl_src,
+                              RegLocation rl_dest, int64_t lit);
     bool HandleEasyDivRem(Instruction::Code dalvik_opcode, bool is_div,
                           RegLocation rl_src, RegLocation rl_dest, int lit) OVERRIDE;
+    bool HandleEasyDivRem64(Instruction::Code dalvik_opcode, bool is_div,
+                            RegLocation rl_src, RegLocation rl_dest, int64_t lit);
     bool EasyMultiply(RegLocation rl_src, RegLocation rl_dest, int lit) OVERRIDE;
     LIR* CheckSuspendUsingLoad() OVERRIDE;
     RegStorage LoadHelper(ThreadOffset<4> offset) OVERRIDE;
@@ -100,18 +104,14 @@
 
     // Required for target - register utilities.
     RegStorage TargetReg(SpecialTargetRegister reg) OVERRIDE;
-    RegStorage TargetReg(SpecialTargetRegister symbolic_reg, bool is_wide) OVERRIDE {
+    RegStorage TargetReg(SpecialTargetRegister symbolic_reg, WideKind wide_kind) OVERRIDE {
       RegStorage reg = TargetReg(symbolic_reg);
-      if (is_wide) {
+      if (wide_kind == kWide || wide_kind == kRef) {
         return (reg.Is64Bit()) ? reg : As64BitReg(reg);
       } else {
         return (reg.Is32Bit()) ? reg : As32BitReg(reg);
       }
     }
-    RegStorage TargetRefReg(SpecialTargetRegister symbolic_reg) OVERRIDE {
-      RegStorage reg = TargetReg(symbolic_reg);
-      return (reg.Is64Bit() ? reg : As64BitReg(reg));
-    }
     RegStorage TargetPtrReg(SpecialTargetRegister symbolic_reg) OVERRIDE {
       RegStorage reg = TargetReg(symbolic_reg);
       return (reg.Is64Bit() ? reg : As64BitReg(reg));
diff --git a/compiler/dex/quick/arm64/int_arm64.cc b/compiler/dex/quick/arm64/int_arm64.cc
index abc239f..2650892 100644
--- a/compiler/dex/quick/arm64/int_arm64.cc
+++ b/compiler/dex/quick/arm64/int_arm64.cc
@@ -370,28 +370,31 @@
 
 // Table of magic divisors
 struct MagicTable {
-  uint32_t magic;
+  int magic64_base;
+  int magic64_eor;
+  uint64_t magic64;
+  uint32_t magic32;
   uint32_t shift;
   DividePattern pattern;
 };
 
 static const MagicTable magic_table[] = {
-  {0, 0, DivideNone},        // 0
-  {0, 0, DivideNone},        // 1
-  {0, 0, DivideNone},        // 2
-  {0x55555556, 0, Divide3},  // 3
-  {0, 0, DivideNone},        // 4
-  {0x66666667, 1, Divide5},  // 5
-  {0x2AAAAAAB, 0, Divide3},  // 6
-  {0x92492493, 2, Divide7},  // 7
-  {0, 0, DivideNone},        // 8
-  {0x38E38E39, 1, Divide5},  // 9
-  {0x66666667, 2, Divide5},  // 10
-  {0x2E8BA2E9, 1, Divide5},  // 11
-  {0x2AAAAAAB, 1, Divide5},  // 12
-  {0x4EC4EC4F, 2, Divide5},  // 13
-  {0x92492493, 3, Divide7},  // 14
-  {0x88888889, 3, Divide7},  // 15
+  {   0,      0,                  0,          0, 0, DivideNone},  // 0
+  {   0,      0,                  0,          0, 0, DivideNone},  // 1
+  {   0,      0,                  0,          0, 0, DivideNone},  // 2
+  {0x3c,     -1, 0x5555555555555556, 0x55555556, 0, Divide3},     // 3
+  {   0,      0,                  0,          0, 0, DivideNone},  // 4
+  {0xf9,     -1, 0x6666666666666667, 0x66666667, 1, Divide5},     // 5
+  {0x7c, 0x1041, 0x2AAAAAAAAAAAAAAB, 0x2AAAAAAB, 0, Divide3},     // 6
+  {  -1,     -1, 0x924924924924924A, 0x92492493, 2, Divide7},     // 7
+  {   0,      0,                  0,          0, 0, DivideNone},  // 8
+  {  -1,     -1, 0x38E38E38E38E38E4, 0x38E38E39, 1, Divide5},     // 9
+  {0xf9,     -1, 0x6666666666666667, 0x66666667, 2, Divide5},     // 10
+  {  -1,     -1, 0x2E8BA2E8BA2E8BA3, 0x2E8BA2E9, 1, Divide5},     // 11
+  {0x7c, 0x1041, 0x2AAAAAAAAAAAAAAB, 0x2AAAAAAB, 1, Divide5},     // 12
+  {  -1,     -1, 0x4EC4EC4EC4EC4EC5, 0x4EC4EC4F, 2, Divide5},     // 13
+  {  -1,     -1, 0x924924924924924A, 0x92492493, 3, Divide7},     // 14
+  {0x78,     -1, 0x8888888888888889, 0x88888889, 3, Divide7},     // 15
 };
 
 // Integer division by constant via reciprocal multiply (Hacker's Delight, 10-4)
@@ -410,7 +413,7 @@
   }
 
   RegStorage r_magic = AllocTemp();
-  LoadConstant(r_magic, magic_table[lit].magic);
+  LoadConstant(r_magic, magic_table[lit].magic32);
   rl_src = LoadValue(rl_src, kCoreReg);
   RegLocation rl_result = EvalLoc(rl_dest, kCoreReg, true);
   RegStorage r_long_mul = AllocTemp();
@@ -439,49 +442,144 @@
   return true;
 }
 
+bool Arm64Mir2Lir::SmallLiteralDivRem64(Instruction::Code dalvik_opcode, bool is_div,
+                                        RegLocation rl_src, RegLocation rl_dest, int64_t lit) {
+  if ((lit < 0) || (lit >= static_cast<int>(arraysize(magic_table)))) {
+    return false;
+  }
+  DividePattern pattern = magic_table[lit].pattern;
+  if (pattern == DivideNone) {
+    return false;
+  }
+  // Tuning: add rem patterns
+  if (!is_div) {
+    return false;
+  }
+
+  RegStorage r_magic = AllocTempWide();
+  rl_src = LoadValueWide(rl_src, kCoreReg);
+  RegLocation rl_result = EvalLocWide(rl_dest, kCoreReg, true);
+  RegStorage r_long_mul = AllocTempWide();
+
+  if (magic_table[lit].magic64_base >= 0) {
+    // Check that the entry in the table is correct.
+    if (kIsDebugBuild) {
+      uint64_t reconstructed_imm;
+      uint64_t base = DecodeLogicalImmediate(/*is_wide*/true, magic_table[lit].magic64_base);
+      if (magic_table[lit].magic64_eor >= 0) {
+        uint64_t eor = DecodeLogicalImmediate(/*is_wide*/true, magic_table[lit].magic64_eor);
+        reconstructed_imm = base ^ eor;
+      } else {
+        reconstructed_imm = base + 1;
+      }
+      DCHECK_EQ(reconstructed_imm, magic_table[lit].magic64) << " for literal " << lit;
+    }
+
+    // Load the magic constant in two instructions.
+    NewLIR3(WIDE(kA64Orr3Rrl), r_magic.GetReg(), rxzr, magic_table[lit].magic64_base);
+    if (magic_table[lit].magic64_eor >= 0) {
+      NewLIR3(WIDE(kA64Eor3Rrl), r_magic.GetReg(), r_magic.GetReg(),
+              magic_table[lit].magic64_eor);
+    } else {
+      NewLIR4(WIDE(kA64Add4RRdT), r_magic.GetReg(), r_magic.GetReg(), 1, 0);
+    }
+  } else {
+    LoadConstantWide(r_magic, magic_table[lit].magic64);
+  }
+
+  NewLIR3(kA64Smulh3xxx, r_long_mul.GetReg(), r_magic.GetReg(), rl_src.reg.GetReg());
+  switch (pattern) {
+    case Divide3:
+      OpRegRegRegShift(kOpSub, rl_result.reg, r_long_mul, rl_src.reg, EncodeShift(kA64Asr, 63));
+      break;
+    case Divide5:
+      OpRegRegImm(kOpAsr, r_long_mul, r_long_mul, magic_table[lit].shift);
+      OpRegRegRegShift(kOpSub, rl_result.reg, r_long_mul, rl_src.reg, EncodeShift(kA64Asr, 63));
+      break;
+    case Divide7:
+      OpRegRegReg(kOpAdd, r_long_mul, rl_src.reg, r_long_mul);
+      OpRegRegImm(kOpAsr, r_long_mul, r_long_mul, magic_table[lit].shift);
+      OpRegRegRegShift(kOpSub, rl_result.reg, r_long_mul, rl_src.reg, EncodeShift(kA64Asr, 63));
+      break;
+    default:
+      LOG(FATAL) << "Unexpected pattern: " << pattern;
+  }
+  StoreValueWide(rl_dest, rl_result);
+  return true;
+}
+
 // Returns true if it added instructions to 'cu' to divide 'rl_src' by 'lit'
 // and store the result in 'rl_dest'.
 bool Arm64Mir2Lir::HandleEasyDivRem(Instruction::Code dalvik_opcode, bool is_div,
                                     RegLocation rl_src, RegLocation rl_dest, int lit) {
+  return HandleEasyDivRem64(dalvik_opcode, is_div, rl_src, rl_dest, static_cast<int>(lit));
+}
+
+// Returns true if it added instructions to 'cu' to divide 'rl_src' by 'lit'
+// and store the result in 'rl_dest'.
+bool Arm64Mir2Lir::HandleEasyDivRem64(Instruction::Code dalvik_opcode, bool is_div,
+                                      RegLocation rl_src, RegLocation rl_dest, int64_t lit) {
+  const bool is_64bit = rl_dest.wide;
+  const int nbits = (is_64bit) ? 64 : 32;
+
   if (lit < 2) {
     return false;
   }
   if (!IsPowerOfTwo(lit)) {
-    return SmallLiteralDivRem(dalvik_opcode, is_div, rl_src, rl_dest, lit);
+    if (is_64bit) {
+      return SmallLiteralDivRem64(dalvik_opcode, is_div, rl_src, rl_dest, lit);
+    } else {
+      return SmallLiteralDivRem(dalvik_opcode, is_div, rl_src, rl_dest, static_cast<int32_t>(lit));
+    }
   }
   int k = LowestSetBit(lit);
-  if (k >= 30) {
+  if (k >= nbits - 2) {
     // Avoid special cases.
     return false;
   }
-  rl_src = LoadValue(rl_src, kCoreReg);
-  RegLocation rl_result = EvalLoc(rl_dest, kCoreReg, true);
+
+  RegLocation rl_result;
+  RegStorage t_reg;
+  if (is_64bit) {
+    rl_src = LoadValueWide(rl_src, kCoreReg);
+    rl_result = EvalLocWide(rl_dest, kCoreReg, true);
+    t_reg = AllocTempWide();
+  } else {
+    rl_src = LoadValue(rl_src, kCoreReg);
+    rl_result = EvalLoc(rl_dest, kCoreReg, true);
+    t_reg = AllocTemp();
+  }
+
+  int shift = EncodeShift(kA64Lsr, nbits - k);
   if (is_div) {
-    RegStorage t_reg = AllocTemp();
     if (lit == 2) {
       // Division by 2 is by far the most common division by constant.
-      OpRegRegRegShift(kOpAdd, t_reg, rl_src.reg, rl_src.reg, EncodeShift(kA64Lsr, 32 - k));
+      OpRegRegRegShift(kOpAdd, t_reg, rl_src.reg, rl_src.reg, shift);
       OpRegRegImm(kOpAsr, rl_result.reg, t_reg, k);
     } else {
-      OpRegRegImm(kOpAsr, t_reg, rl_src.reg, 31);
-      OpRegRegRegShift(kOpAdd, t_reg, rl_src.reg, t_reg, EncodeShift(kA64Lsr, 32 - k));
+      OpRegRegImm(kOpAsr, t_reg, rl_src.reg, nbits - 1);
+      OpRegRegRegShift(kOpAdd, t_reg, rl_src.reg, t_reg, shift);
       OpRegRegImm(kOpAsr, rl_result.reg, t_reg, k);
     }
   } else {
-    RegStorage t_reg = AllocTemp();
     if (lit == 2) {
-      OpRegRegRegShift(kOpAdd, t_reg, rl_src.reg, rl_src.reg, EncodeShift(kA64Lsr, 32 - k));
-      OpRegRegImm(kOpAnd, t_reg, t_reg, lit - 1);
-      OpRegRegRegShift(kOpSub, rl_result.reg, t_reg, rl_src.reg, EncodeShift(kA64Lsr, 32 - k));
+      OpRegRegRegShift(kOpAdd, t_reg, rl_src.reg, rl_src.reg, shift);
+      OpRegRegImm64(kOpAnd, t_reg, t_reg, lit - 1);
+      OpRegRegRegShift(kOpSub, rl_result.reg, t_reg, rl_src.reg, shift);
     } else {
-      RegStorage t_reg2 = AllocTemp();
-      OpRegRegImm(kOpAsr, t_reg, rl_src.reg, 31);
-      OpRegRegRegShift(kOpAdd, t_reg2, rl_src.reg, t_reg, EncodeShift(kA64Lsr, 32 - k));
-      OpRegRegImm(kOpAnd, t_reg2, t_reg2, lit - 1);
-      OpRegRegRegShift(kOpSub, rl_result.reg, t_reg2, t_reg, EncodeShift(kA64Lsr, 32 - k));
+      RegStorage t_reg2 = (is_64bit) ? AllocTempWide() : AllocTemp();
+      OpRegRegImm(kOpAsr, t_reg, rl_src.reg, nbits - 1);
+      OpRegRegRegShift(kOpAdd, t_reg2, rl_src.reg, t_reg, shift);
+      OpRegRegImm64(kOpAnd, t_reg2, t_reg2, lit - 1);
+      OpRegRegRegShift(kOpSub, rl_result.reg, t_reg2, t_reg, shift);
     }
   }
-  StoreValue(rl_dest, rl_result);
+
+  if (is_64bit) {
+    StoreValueWide(rl_dest, rl_result);
+  } else {
+    StoreValue(rl_dest, rl_result);
+  }
   return true;
 }
 
@@ -490,12 +588,6 @@
   return false;
 }
 
-RegLocation Arm64Mir2Lir::GenDivRem(RegLocation rl_dest, RegLocation rl_src1,
-                                    RegLocation rl_src2, bool is_div, bool check_zero) {
-  LOG(FATAL) << "Unexpected use of GenDivRem for Arm64";
-  return rl_dest;
-}
-
 RegLocation Arm64Mir2Lir::GenDivRemLit(RegLocation rl_dest, RegLocation rl_src1, int lit, bool is_div) {
   LOG(FATAL) << "Unexpected use of GenDivRemLit for Arm64";
   return rl_dest;
@@ -515,8 +607,14 @@
   return rl_result;
 }
 
+RegLocation Arm64Mir2Lir::GenDivRem(RegLocation rl_dest, RegLocation rl_src1,
+                                    RegLocation rl_src2, bool is_div, bool check_zero) {
+  LOG(FATAL) << "Unexpected use of GenDivRem for Arm64";
+  return rl_dest;
+}
+
 RegLocation Arm64Mir2Lir::GenDivRem(RegLocation rl_dest, RegStorage r_src1, RegStorage r_src2,
-                                  bool is_div) {
+                                    bool is_div) {
   CHECK_EQ(r_src1.Is64Bit(), r_src2.Is64Bit());
 
   RegLocation rl_result = EvalLoc(rl_dest, kCoreReg, true);
@@ -798,6 +896,14 @@
 
 void Arm64Mir2Lir::GenDivRemLong(Instruction::Code opcode, RegLocation rl_dest,
                                  RegLocation rl_src1, RegLocation rl_src2, bool is_div) {
+  if (rl_src2.is_const) {
+    DCHECK(rl_src2.wide);
+    int64_t lit = mir_graph_->ConstantValueWide(rl_src2);
+    if (HandleEasyDivRem64(opcode, is_div, rl_src1, rl_dest, lit)) {
+      return;
+    }
+  }
+
   RegLocation rl_result;
   rl_src1 = LoadValueWide(rl_src1, kCoreReg);
   rl_src2 = LoadValueWide(rl_src2, kCoreReg);
@@ -1063,7 +1169,7 @@
 }
 
 void Arm64Mir2Lir::GenShiftImmOpLong(Instruction::Code opcode,
-                                   RegLocation rl_dest, RegLocation rl_src, RegLocation rl_shift) {
+                                     RegLocation rl_dest, RegLocation rl_src, RegLocation rl_shift) {
   OpKind op = kOpBkpt;
   // Per spec, we only care about low 6 bits of shift amount.
   int shift_amount = mir_graph_->ConstantValue(rl_shift) & 0x3f;
diff --git a/compiler/dex/quick/arm64/target_arm64.cc b/compiler/dex/quick/arm64/target_arm64.cc
index 8264a06..2212380 100644
--- a/compiler/dex/quick/arm64/target_arm64.cc
+++ b/compiler/dex/quick/arm64/target_arm64.cc
@@ -1111,7 +1111,7 @@
 
       // Instead of allocating a new temp, simply reuse one of the registers being used
       // for argument passing.
-      RegStorage temp = TargetReg(kArg3, false);
+      RegStorage temp = TargetReg(kArg3, kNotWide);
 
       // Now load the argument VR and store to the outs.
       Load32Disp(TargetReg(kSp), current_src_offset, temp);
diff --git a/compiler/dex/quick/arm64/utility_arm64.cc b/compiler/dex/quick/arm64/utility_arm64.cc
index 097fcdc..fdebb92 100644
--- a/compiler/dex/quick/arm64/utility_arm64.cc
+++ b/compiler/dex/quick/arm64/utility_arm64.cc
@@ -488,7 +488,9 @@
       break;
     case kOpRevsh:
       // Binary, but rm is encoded twice.
-      return NewLIR2(kA64Rev162rr | wide, r_dest_src1.GetReg(), r_src2.GetReg());
+      NewLIR2(kA64Rev162rr | wide, r_dest_src1.GetReg(), r_src2.GetReg());
+      // "sxth r1, r2" is "sbfm r1, r2, #0, #15"
+      return NewLIR4(kA64Sbfm4rrdd | wide, r_dest_src1.GetReg(), r_dest_src1.GetReg(), 0, 15);
       break;
     case kOp2Byte:
       DCHECK_EQ(shift, ENCODE_NO_SHIFT);
diff --git a/compiler/dex/quick/codegen_util.cc b/compiler/dex/quick/codegen_util.cc
index 048aca3..60d2589 100644
--- a/compiler/dex/quick/codegen_util.cc
+++ b/compiler/dex/quick/codegen_util.cc
@@ -1212,7 +1212,7 @@
     data_target->operands[2] = type;
   }
   // Loads an ArtMethod pointer, which is a reference as it lives in the heap.
-  LIR* load_pc_rel = OpPcRelLoad(TargetRefReg(symbolic_reg), data_target);
+  LIR* load_pc_rel = OpPcRelLoad(TargetReg(symbolic_reg, kRef), data_target);
   AppendLIR(load_pc_rel);
   DCHECK_NE(cu_->instruction_set, kMips) << reinterpret_cast<void*>(data_target);
 }
@@ -1224,7 +1224,7 @@
     data_target = AddWordData(&class_literal_list_, type_idx);
   }
   // Loads a Class pointer, which is a reference as it lives in the heap.
-  LIR* load_pc_rel = OpPcRelLoad(TargetRefReg(symbolic_reg), data_target);
+  LIR* load_pc_rel = OpPcRelLoad(TargetReg(symbolic_reg, kRef), data_target);
   AppendLIR(load_pc_rel);
 }
 
diff --git a/compiler/dex/quick/gen_common.cc b/compiler/dex/quick/gen_common.cc
index c266a3c..1fc0cff 100644
--- a/compiler/dex/quick/gen_common.cc
+++ b/compiler/dex/quick/gen_common.cc
@@ -127,8 +127,8 @@
       m2l_->ResetDefTracking();
       GenerateTargetLabel(kPseudoThrowTarget);
 
-      RegStorage arg1_32 = m2l_->TargetReg(kArg1, false);
-      RegStorage arg0_32 = m2l_->TargetReg(kArg0, false);
+      RegStorage arg1_32 = m2l_->TargetReg(kArg1, kNotWide);
+      RegStorage arg0_32 = m2l_->TargetReg(kArg0, kNotWide);
 
       m2l_->OpRegCopy(arg1_32, length_);
       m2l_->LoadConstant(arg0_32, index_);
@@ -368,7 +368,8 @@
       if (!use_direct_type_ptr) {
         mir_to_lir->LoadClassType(type_idx, kArg0);
         func_offset = QUICK_ENTRYPOINT_OFFSET(pointer_size, pAllocArrayResolved);
-        mir_to_lir->CallRuntimeHelperRegMethodRegLocation(func_offset, mir_to_lir->TargetReg(kArg0, false),
+        mir_to_lir->CallRuntimeHelperRegMethodRegLocation(func_offset,
+                                                          mir_to_lir->TargetReg(kArg0, kNotWide),
                                                           rl_src, true);
       } else {
         // Use the direct pointer.
@@ -431,8 +432,8 @@
   } else {
     GenFilledNewArrayCall<4>(this, cu_, elems, type_idx);
   }
-  FreeTemp(TargetReg(kArg2, false));
-  FreeTemp(TargetReg(kArg1, false));
+  FreeTemp(TargetReg(kArg2, kNotWide));
+  FreeTemp(TargetReg(kArg1, kNotWide));
   /*
    * NOTE: the implicit target for Instruction::FILLED_NEW_ARRAY is the
    * return region.  Because AllocFromCode placed the new array
@@ -440,7 +441,7 @@
    * added, it may be necessary to additionally copy all return
    * values to a home location in thread-local storage
    */
-  RegStorage ref_reg = TargetRefReg(kRet0);
+  RegStorage ref_reg = TargetReg(kRet0, kRef);
   LockTemp(ref_reg);
 
   // TODO: use the correct component size, currently all supported types
@@ -477,7 +478,7 @@
     switch (cu_->instruction_set) {
       case kThumb2:
       case kArm64:
-        r_val = TargetReg(kLr, false);
+        r_val = TargetReg(kLr, kNotWide);
         break;
       case kX86:
       case kX86_64:
@@ -553,7 +554,7 @@
                                  storage_index_, true);
     }
     // Copy helper's result into r_base, a no-op on all but MIPS.
-    m2l_->OpRegCopy(r_base_,  m2l_->TargetRefReg(kRet0));
+    m2l_->OpRegCopy(r_base_,  m2l_->TargetReg(kRet0, kRef));
 
     m2l_->OpUnconditionalBranch(cont_);
   }
@@ -601,10 +602,10 @@
       // May do runtime call so everything to home locations.
       FlushAllRegs();
       // Using fixed register to sync with possible call to runtime support.
-      RegStorage r_method = TargetRefReg(kArg1);
+      RegStorage r_method = TargetReg(kArg1, kRef);
       LockTemp(r_method);
       LoadCurrMethodDirect(r_method);
-      r_base = TargetRefReg(kArg0);
+      r_base = TargetReg(kArg0, kRef);
       LockTemp(r_base);
       LoadRefDisp(r_method, mirror::ArtMethod::DexCacheResolvedTypesOffset().Int32Value(), r_base,
                   kNotVolatile);
@@ -618,7 +619,7 @@
         // 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);
-        RegStorage r_tmp = TargetReg(kArg2, false);
+        RegStorage r_tmp = TargetReg(kArg2, kNotWide);
         LockTemp(r_tmp);
         LIR* uninit_branch = OpCmpMemImmBranch(kCondLt, r_tmp, r_base,
                                           mirror::Class::StatusOffset().Int32Value(),
@@ -698,10 +699,10 @@
       // May do runtime call so everything to home locations.
       FlushAllRegs();
       // Using fixed register to sync with possible call to runtime support.
-      RegStorage r_method = TargetRefReg(kArg1);
+      RegStorage r_method = TargetReg(kArg1, kRef);
       LockTemp(r_method);
       LoadCurrMethodDirect(r_method);
-      r_base = TargetRefReg(kArg0);
+      r_base = TargetReg(kArg0, kRef);
       LockTemp(r_base);
       LoadRefDisp(r_method, mirror::ArtMethod::DexCacheResolvedTypesOffset().Int32Value(), r_base,
                   kNotVolatile);
@@ -715,7 +716,7 @@
         // 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);
-        RegStorage r_tmp = TargetReg(kArg2, false);
+        RegStorage r_tmp = TargetReg(kArg2, kNotWide);
         LockTemp(r_tmp);
         LIR* uninit_branch = OpCmpMemImmBranch(kCondLt, r_tmp, r_base,
                                           mirror::Class::StatusOffset().Int32Value(),
@@ -961,7 +962,7 @@
             m2l_->CallRuntimeHelperImmReg(QUICK_ENTRYPOINT_OFFSET(4, pInitializeType), type_idx_,
                                                       rl_method_.reg, true);
           }
-          m2l_->OpRegCopy(rl_result_.reg,  m2l_->TargetRefReg(kRet0));
+          m2l_->OpRegCopy(rl_result_.reg,  m2l_->TargetReg(kRet0, kRef));
 
           m2l_->OpUnconditionalBranch(cont_);
         }
@@ -1001,15 +1002,15 @@
       DCHECK(!IsTemp(rl_method.reg));
       r_method = rl_method.reg;
     } else {
-      r_method = TargetRefReg(kArg2);
+      r_method = TargetReg(kArg2, kRef);
       LoadCurrMethodDirect(r_method);
     }
     LoadRefDisp(r_method, mirror::ArtMethod::DexCacheStringsOffset().Int32Value(),
-                TargetRefReg(kArg0), kNotVolatile);
+                TargetReg(kArg0, kRef), kNotVolatile);
 
     // Might call out to helper, which will return resolved string in kRet0
-    LoadRefDisp(TargetRefReg(kArg0), offset_of_string, TargetRefReg(kRet0), kNotVolatile);
-    LIR* fromfast = OpCmpImmBranch(kCondEq, TargetRefReg(kRet0), 0, NULL);
+    LoadRefDisp(TargetReg(kArg0, kRef), offset_of_string, TargetReg(kRet0, kRef), kNotVolatile);
+    LIR* fromfast = OpCmpImmBranch(kCondEq, TargetReg(kRet0, kRef), 0, NULL);
     LIR* cont = NewLIR0(kPseudoTargetLabel);
 
     {
@@ -1078,10 +1079,12 @@
         mir_to_lir->LoadClassType(type_idx, kArg0);
         if (!is_type_initialized) {
           func_offset = QUICK_ENTRYPOINT_OFFSET(pointer_size, pAllocObjectResolved);
-          mir_to_lir->CallRuntimeHelperRegMethod(func_offset, mir_to_lir->TargetRefReg(kArg0), true);
+          mir_to_lir->CallRuntimeHelperRegMethod(func_offset, mir_to_lir->TargetReg(kArg0, kRef),
+                                                 true);
         } else {
           func_offset = QUICK_ENTRYPOINT_OFFSET(pointer_size, pAllocObjectInitialized);
-          mir_to_lir->CallRuntimeHelperRegMethod(func_offset, mir_to_lir->TargetRefReg(kArg0), true);
+          mir_to_lir->CallRuntimeHelperRegMethod(func_offset, mir_to_lir->TargetReg(kArg0, kRef),
+                                                 true);
         }
       } else {
         // Use the direct pointer.
@@ -1200,9 +1203,9 @@
   FlushAllRegs();
   // May generate a call - use explicit registers
   LockCallTemps();
-  RegStorage method_reg = TargetRefReg(kArg1);
+  RegStorage method_reg = TargetReg(kArg1, kRef);
   LoadCurrMethodDirect(method_reg);   // kArg1 <= current Method*
-  RegStorage class_reg = TargetRefReg(kArg2);  // kArg2 will hold the Class*
+  RegStorage class_reg = TargetReg(kArg2, kRef);  // 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
@@ -1213,15 +1216,15 @@
       CallRuntimeHelperImm(QUICK_ENTRYPOINT_OFFSET(4, pInitializeTypeAndVerifyAccess),
                            type_idx, true);
     }
-    OpRegCopy(class_reg, TargetRefReg(kRet0));  // Align usage with fast path
-    LoadValueDirectFixed(rl_src, TargetRefReg(kArg0));  // kArg0 <= ref
+    OpRegCopy(class_reg, TargetReg(kRet0, kRef));  // Align usage with fast path
+    LoadValueDirectFixed(rl_src, TargetReg(kArg0, kRef));  // kArg0 <= ref
   } else if (use_declaring_class) {
-    LoadValueDirectFixed(rl_src, TargetRefReg(kArg0));  // kArg0 <= ref
+    LoadValueDirectFixed(rl_src, TargetReg(kArg0, kRef));  // kArg0 <= ref
     LoadRefDisp(method_reg, mirror::ArtMethod::DeclaringClassOffset().Int32Value(),
                 class_reg, kNotVolatile);
   } else {
     // Load dex cache entry into class_reg (kArg2)
-    LoadValueDirectFixed(rl_src, TargetRefReg(kArg0));  // kArg0 <= ref
+    LoadValueDirectFixed(rl_src, TargetReg(kArg0, kRef));  // kArg0 <= ref
     LoadRefDisp(method_reg, mirror::ArtMethod::DexCacheResolvedTypesOffset().Int32Value(),
                 class_reg, kNotVolatile);
     int32_t offset_of_type = ClassArray::OffsetOfElement(type_idx).Int32Value();
@@ -1236,8 +1239,8 @@
       } else {
         CallRuntimeHelperImm(QUICK_ENTRYPOINT_OFFSET(4, pInitializeType), type_idx, true);
       }
-      OpRegCopy(TargetRefReg(kArg2), TargetRefReg(kRet0));  // Align usage with fast path
-      LoadValueDirectFixed(rl_src, TargetRefReg(kArg0));  /* reload Ref */
+      OpRegCopy(TargetReg(kArg2, kRef), TargetReg(kRet0, kRef));  // Align usage with fast path
+      LoadValueDirectFixed(rl_src, TargetReg(kArg0, kRef));  /* reload Ref */
       // Rejoin code paths
       LIR* hop_target = NewLIR0(kPseudoTargetLabel);
       hop_branch->target = hop_target;
@@ -1249,25 +1252,25 @@
     // On MIPS rArg0 != rl_result, place false in result if branch is taken.
     LoadConstant(rl_result.reg, 0);
   }
-  LIR* branch1 = OpCmpImmBranch(kCondEq, TargetRefReg(kArg0), 0, NULL);
+  LIR* branch1 = OpCmpImmBranch(kCondEq, TargetReg(kArg0, kRef), 0, NULL);
 
   /* load object->klass_ */
   DCHECK_EQ(mirror::Object::ClassOffset().Int32Value(), 0);
-  LoadRefDisp(TargetRefReg(kArg0), mirror::Object::ClassOffset().Int32Value(), TargetRefReg(kArg1),
-              kNotVolatile);
+  LoadRefDisp(TargetReg(kArg0, kRef), mirror::Object::ClassOffset().Int32Value(),
+              TargetReg(kArg1, kRef), kNotVolatile);
   /* kArg0 is ref, kArg1 is ref->klass_, kArg2 is class */
   LIR* branchover = NULL;
   if (type_known_final) {
     // rl_result == ref == null == 0.
     if (cu_->instruction_set == kThumb2) {
-      OpRegReg(kOpCmp, TargetRefReg(kArg1), TargetRefReg(kArg2));  // Same?
+      OpRegReg(kOpCmp, TargetReg(kArg1, kRef), TargetReg(kArg2, kRef));  // Same?
       LIR* it = OpIT(kCondEq, "E");   // if-convert the test
       LoadConstant(rl_result.reg, 1);     // .eq case - load true
       LoadConstant(rl_result.reg, 0);     // .ne case - load false
       OpEndIT(it);
     } else {
       LoadConstant(rl_result.reg, 0);     // ne case - load false
-      branchover = OpCmpBranch(kCondNe, TargetRefReg(kArg1), TargetRefReg(kArg2), NULL);
+      branchover = OpCmpBranch(kCondNe, TargetReg(kArg1, kRef), TargetReg(kArg2, kRef), NULL);
       LoadConstant(rl_result.reg, 1);     // eq case - load true
     }
   } else {
@@ -1278,11 +1281,11 @@
       LIR* it = nullptr;
       if (!type_known_abstract) {
       /* Uses conditional nullification */
-        OpRegReg(kOpCmp, TargetRefReg(kArg1), TargetRefReg(kArg2));  // Same?
+        OpRegReg(kOpCmp, TargetReg(kArg1, kRef), TargetReg(kArg2, kRef));  // Same?
         it = OpIT(kCondEq, "EE");   // if-convert the test
-        LoadConstant(TargetReg(kArg0, false), 1);     // .eq case - load true
+        LoadConstant(TargetReg(kArg0, kNotWide), 1);     // .eq case - load true
       }
-      OpRegCopy(TargetRefReg(kArg0), TargetRefReg(kArg2));    // .ne case - arg0 <= class
+      OpRegCopy(TargetReg(kArg0, kRef), TargetReg(kArg2, kRef));    // .ne case - arg0 <= class
       OpReg(kOpBlx, r_tgt);    // .ne case: helper(class, ref->class)
       if (it != nullptr) {
         OpEndIT(it);
@@ -1292,12 +1295,12 @@
       if (!type_known_abstract) {
         /* Uses branchovers */
         LoadConstant(rl_result.reg, 1);     // assume true
-        branchover = OpCmpBranch(kCondEq, TargetRefReg(kArg1), TargetRefReg(kArg2), NULL);
+        branchover = OpCmpBranch(kCondEq, TargetReg(kArg1, kRef), TargetReg(kArg2, kRef), NULL);
       }
       RegStorage r_tgt = cu_->target64 ?
           LoadHelper(QUICK_ENTRYPOINT_OFFSET(8, pInstanceofNonTrivial)) :
           LoadHelper(QUICK_ENTRYPOINT_OFFSET(4, pInstanceofNonTrivial));
-      OpRegCopy(TargetRefReg(kArg0), TargetRefReg(kArg2));    // .ne case - arg0 <= class
+      OpRegCopy(TargetReg(kArg0, kRef), TargetReg(kArg2, kRef));    // .ne case - arg0 <= class
       OpReg(kOpBlx, r_tgt);    // .ne case: helper(class, ref->class)
       FreeTemp(r_tgt);
     }
@@ -1351,9 +1354,9 @@
   FlushAllRegs();
   // May generate a call - use explicit registers
   LockCallTemps();
-  RegStorage method_reg = TargetRefReg(kArg1);
+  RegStorage method_reg = TargetReg(kArg1, kRef);
   LoadCurrMethodDirect(method_reg);  // kArg1 <= current Method*
-  RegStorage class_reg = TargetRefReg(kArg2);  // kArg2 will hold the Class*
+  RegStorage class_reg = TargetReg(kArg2, kRef);  // 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
@@ -1365,7 +1368,7 @@
       CallRuntimeHelperImm(QUICK_ENTRYPOINT_OFFSET(4, pInitializeTypeAndVerifyAccess),
                            type_idx, true);
     }
-    OpRegCopy(class_reg, TargetRefReg(kRet0));  // Align usage with fast path
+    OpRegCopy(class_reg, TargetReg(kRet0, kRef));  // Align usage with fast path
   } else if (use_declaring_class) {
     LoadRefDisp(method_reg, mirror::ArtMethod::DeclaringClassOffset().Int32Value(),
                 class_reg, kNotVolatile);
@@ -1396,12 +1399,12 @@
           // InitializeTypeFromCode(idx, method)
           if (m2l_->cu_->target64) {
             m2l_->CallRuntimeHelperImmReg(QUICK_ENTRYPOINT_OFFSET(8, pInitializeType), type_idx_,
-                                          m2l_->TargetRefReg(kArg1), true);
+                                          m2l_->TargetReg(kArg1, kRef), true);
           } else {
             m2l_->CallRuntimeHelperImmReg(QUICK_ENTRYPOINT_OFFSET(4, pInitializeType), type_idx_,
-                                          m2l_->TargetRefReg(kArg1), true);
+                                          m2l_->TargetReg(kArg1, kRef), true);
           }
-          m2l_->OpRegCopy(class_reg_, m2l_->TargetRefReg(kRet0));  // Align usage with fast path
+          m2l_->OpRegCopy(class_reg_, m2l_->TargetReg(kRet0, kRef));  // Align usage with fast path
           m2l_->OpUnconditionalBranch(cont_);
         }
 
@@ -1414,7 +1417,7 @@
     }
   }
   // At this point, class_reg (kArg2) has class
-  LoadValueDirectFixed(rl_src, TargetRefReg(kArg0));  // kArg0 <= ref
+  LoadValueDirectFixed(rl_src, TargetReg(kArg0, kRef));  // kArg0 <= ref
 
   // Slow path for the case where the classes are not equal.  In this case we need
   // to call a helper function to do the check.
@@ -1428,15 +1431,17 @@
       GenerateTargetLabel();
 
       if (load_) {
-        m2l_->LoadRefDisp(m2l_->TargetRefReg(kArg0), mirror::Object::ClassOffset().Int32Value(),
-                          m2l_->TargetRefReg(kArg1), kNotVolatile);
+        m2l_->LoadRefDisp(m2l_->TargetReg(kArg0, kRef), mirror::Object::ClassOffset().Int32Value(),
+                          m2l_->TargetReg(kArg1, kRef), kNotVolatile);
       }
       if (m2l_->cu_->target64) {
-        m2l_->CallRuntimeHelperRegReg(QUICK_ENTRYPOINT_OFFSET(8, pCheckCast), m2l_->TargetRefReg(kArg2),
-                                      m2l_->TargetRefReg(kArg1), true);
+        m2l_->CallRuntimeHelperRegReg(QUICK_ENTRYPOINT_OFFSET(8, pCheckCast),
+                                      m2l_->TargetReg(kArg2, kRef), m2l_->TargetReg(kArg1, kRef),
+                                      true);
       } else {
-        m2l_->CallRuntimeHelperRegReg(QUICK_ENTRYPOINT_OFFSET(4, pCheckCast), m2l_->TargetRefReg(kArg2),
-                                              m2l_->TargetRefReg(kArg1), true);
+        m2l_->CallRuntimeHelperRegReg(QUICK_ENTRYPOINT_OFFSET(4, pCheckCast),
+                                      m2l_->TargetReg(kArg2, kRef), m2l_->TargetReg(kArg1, kRef),
+                                      true);
       }
 
       m2l_->OpUnconditionalBranch(cont_);
@@ -1448,7 +1453,7 @@
 
   if (type_known_abstract) {
     // Easier case, run slow path if target is non-null (slow path will load from target)
-    LIR* branch = OpCmpImmBranch(kCondNe, TargetRefReg(kArg0), 0, nullptr);
+    LIR* branch = OpCmpImmBranch(kCondNe, TargetReg(kArg0, kRef), 0, nullptr);
     LIR* cont = NewLIR0(kPseudoTargetLabel);
     AddSlowPath(new (arena_) SlowPath(this, branch, cont, true));
   } else {
@@ -1457,13 +1462,13 @@
     // slow path if the classes are not equal.
 
     /* Null is OK - continue */
-    LIR* branch1 = OpCmpImmBranch(kCondEq, TargetRefReg(kArg0), 0, nullptr);
+    LIR* branch1 = OpCmpImmBranch(kCondEq, TargetReg(kArg0, kRef), 0, nullptr);
     /* load object->klass_ */
     DCHECK_EQ(mirror::Object::ClassOffset().Int32Value(), 0);
-    LoadRefDisp(TargetRefReg(kArg0), mirror::Object::ClassOffset().Int32Value(),
-                TargetRefReg(kArg1), kNotVolatile);
+    LoadRefDisp(TargetReg(kArg0, kRef), mirror::Object::ClassOffset().Int32Value(),
+                TargetReg(kArg1, kRef), kNotVolatile);
 
-    LIR* branch2 = OpCmpBranch(kCondNe, TargetRefReg(kArg1), class_reg, nullptr);
+    LIR* branch2 = OpCmpBranch(kCondNe, TargetReg(kArg1, kRef), class_reg, nullptr);
     LIR* cont = NewLIR0(kPseudoTargetLabel);
 
     // Add the slow path that will not perform load since this is already done.
@@ -1486,8 +1491,8 @@
      * lr is used explicitly elsewhere in the code generator and cannot
      * normally be used as a general temp register.
      */
-    MarkTemp(TargetReg(kLr));   // Add lr to the temp pool
-    FreeTemp(TargetReg(kLr));   // and make it available
+    MarkTemp(TargetReg(kLr, kNotWide));   // Add lr to the temp pool
+    FreeTemp(TargetReg(kLr, kNotWide));   // and make it available
   }
   rl_src1 = LoadValueWide(rl_src1, kCoreReg);
   rl_src2 = LoadValueWide(rl_src2, kCoreReg);
@@ -1514,8 +1519,8 @@
   FreeRegLocTemps(rl_result, rl_src2);
   StoreValueWide(rl_dest, rl_result);
   if (cu_->instruction_set == kThumb2) {
-    Clobber(TargetReg(kLr));
-    UnmarkTemp(TargetReg(kLr));  // Remove lr from the temp pool
+    Clobber(TargetReg(kLr, kNotWide));
+    UnmarkTemp(TargetReg(kLr, kNotWide));  // Remove lr from the temp pool
   }
 }
 
@@ -1679,13 +1684,13 @@
     // If we haven't already generated the code use the callout function.
     if (!done) {
       FlushAllRegs();   /* Send everything to home location */
-      LoadValueDirectFixed(rl_src2, TargetReg(kArg1, false));
+      LoadValueDirectFixed(rl_src2, TargetReg(kArg1, kNotWide));
       RegStorage r_tgt = cu_->target64 ?
           CallHelperSetup(QUICK_ENTRYPOINT_OFFSET(8, pIdivmod)) :
           CallHelperSetup(QUICK_ENTRYPOINT_OFFSET(4, pIdivmod));
-      LoadValueDirectFixed(rl_src1, TargetReg(kArg0, false));
+      LoadValueDirectFixed(rl_src1, TargetReg(kArg0, kNotWide));
       if (check_zero) {
-        GenDivZeroCheck(TargetReg(kArg1, false));
+        GenDivZeroCheck(TargetReg(kArg1, kNotWide));
       }
       // NOTE: callout here is not a safepoint.
       if (cu_->target64) {
@@ -1949,14 +1954,14 @@
 
       if (!done) {
         FlushAllRegs();   /* Everything to home location. */
-        LoadValueDirectFixed(rl_src, TargetReg(kArg0, false));
-        Clobber(TargetReg(kArg0, false));
+        LoadValueDirectFixed(rl_src, TargetReg(kArg0, kNotWide));
+        Clobber(TargetReg(kArg0, kNotWide));
         if (cu_->target64) {
-          CallRuntimeHelperRegImm(QUICK_ENTRYPOINT_OFFSET(8, pIdivmod), TargetReg(kArg0, false), lit,
-                                  false);
+          CallRuntimeHelperRegImm(QUICK_ENTRYPOINT_OFFSET(8, pIdivmod), TargetReg(kArg0, kNotWide),
+                                  lit, false);
         } else {
-          CallRuntimeHelperRegImm(QUICK_ENTRYPOINT_OFFSET(4, pIdivmod), TargetReg(kArg0, false), lit,
-                                  false);
+          CallRuntimeHelperRegImm(QUICK_ENTRYPOINT_OFFSET(4, pIdivmod), TargetReg(kArg0, kNotWide),
+                                  lit, false);
         }
         if (is_div)
           rl_result = GetReturn(kCoreReg);
@@ -1989,7 +1994,7 @@
   bool call_out = false;
   bool check_zero = false;
   ThreadOffset<pointer_size> func_offset(-1);
-  int ret_reg = mir_to_lir->TargetReg(kRet0, false).GetReg();
+  int ret_reg = mir_to_lir->TargetReg(kRet0, kNotWide).GetReg();
 
   switch (opcode) {
     case Instruction::NOT_LONG:
@@ -2037,7 +2042,7 @@
         return;
       } else {
         call_out = true;
-        ret_reg = mir_to_lir->TargetReg(kRet0, false).GetReg();
+        ret_reg = mir_to_lir->TargetReg(kRet0, kNotWide).GetReg();
         func_offset = QUICK_ENTRYPOINT_OFFSET(pointer_size, pLmul);
       }
       break;
@@ -2049,7 +2054,7 @@
       }
       call_out = true;
       check_zero = true;
-      ret_reg = mir_to_lir->TargetReg(kRet0, false).GetReg();
+      ret_reg = mir_to_lir->TargetReg(kRet0, kNotWide).GetReg();
       func_offset = QUICK_ENTRYPOINT_OFFSET(pointer_size, pLdiv);
       break;
     case Instruction::REM_LONG:
@@ -2062,8 +2067,8 @@
       check_zero = true;
       func_offset = QUICK_ENTRYPOINT_OFFSET(pointer_size, pLmod);
       /* NOTE - for Arm, result is in kArg2/kArg3 instead of kRet0/kRet1 */
-      ret_reg = (cu->instruction_set == kThumb2) ? mir_to_lir->TargetReg(kArg2, false).GetReg() :
-          mir_to_lir->TargetReg(kRet0, false).GetReg();
+      ret_reg = (cu->instruction_set == kThumb2) ? mir_to_lir->TargetReg(kArg2, kNotWide).GetReg() :
+          mir_to_lir->TargetReg(kRet0, kNotWide).GetReg();
       break;
     case Instruction::AND_LONG_2ADDR:
     case Instruction::AND_LONG:
@@ -2106,11 +2111,11 @@
   } else {
     mir_to_lir->FlushAllRegs();   /* Send everything to home location */
     if (check_zero) {
-      RegStorage r_tmp1 = mir_to_lir->TargetReg(kArg0, kArg1);
-      RegStorage r_tmp2 = mir_to_lir->TargetReg(kArg2, kArg3);
+      RegStorage r_tmp1 = mir_to_lir->TargetReg(kArg0, kWide);
+      RegStorage r_tmp2 = mir_to_lir->TargetReg(kArg2, kWide);
       mir_to_lir->LoadValueDirectWideFixed(rl_src2, r_tmp2);
       RegStorage r_tgt = mir_to_lir->CallHelperSetup(func_offset);
-      mir_to_lir->GenDivZeroCheckWide(mir_to_lir->TargetReg(kArg2, kArg3));
+      mir_to_lir->GenDivZeroCheckWide(r_tmp2);
       mir_to_lir->LoadValueDirectWideFixed(rl_src1, r_tmp1);
       // NOTE: callout here is not a safepoint
       mir_to_lir->CallHelper(r_tgt, func_offset, false /* not safepoint */);
@@ -2118,7 +2123,7 @@
       mir_to_lir->CallRuntimeHelperRegLocationRegLocation(func_offset, rl_src1, rl_src2, false);
     }
     // Adjust return regs in to handle case of rem returning kArg2/kArg3
-    if (ret_reg == mir_to_lir->TargetReg(kRet0, false).GetReg())
+    if (ret_reg == mir_to_lir->TargetReg(kRet0, kNotWide).GetReg())
       rl_result = mir_to_lir->GetReturnWide(kCoreReg);
     else
       rl_result = mir_to_lir->GetReturnWideAlt();
diff --git a/compiler/dex/quick/gen_invoke.cc b/compiler/dex/quick/gen_invoke.cc
index 3a30430..79065b3 100755
--- a/compiler/dex/quick/gen_invoke.cc
+++ b/compiler/dex/quick/gen_invoke.cc
@@ -131,9 +131,10 @@
 INSTANTIATE(void Mir2Lir::CallRuntimeHelper, bool safepoint_pc)
 
 template <size_t pointer_size>
-void Mir2Lir::CallRuntimeHelperImm(ThreadOffset<pointer_size> helper_offset, int arg0, bool safepoint_pc) {
+void Mir2Lir::CallRuntimeHelperImm(ThreadOffset<pointer_size> helper_offset, int arg0,
+                                   bool safepoint_pc) {
   RegStorage r_tgt = CallHelperSetup(helper_offset);
-  LoadConstant(TargetReg(kArg0, false), arg0);
+  LoadConstant(TargetReg(kArg0, kNotWide), arg0);
   ClobberCallerSave();
   CallHelper<pointer_size>(r_tgt, helper_offset, safepoint_pc);
 }
@@ -143,7 +144,7 @@
 void Mir2Lir::CallRuntimeHelperReg(ThreadOffset<pointer_size> helper_offset, RegStorage arg0,
                                    bool safepoint_pc) {
   RegStorage r_tgt = CallHelperSetup(helper_offset);
-  OpRegCopy(TargetReg(kArg0, arg0.Is64Bit()), arg0);
+  OpRegCopy(TargetReg(kArg0, arg0.GetWideKind()), arg0);
   ClobberCallerSave();
   CallHelper<pointer_size>(r_tgt, helper_offset, safepoint_pc);
 }
@@ -156,13 +157,7 @@
   if (arg0.wide == 0) {
     LoadValueDirectFixed(arg0, TargetReg(arg0.fp ? kFArg0 : kArg0, arg0));
   } else {
-    RegStorage r_tmp;
-    if (cu_->target64) {
-      r_tmp = TargetReg(kArg0, true);
-    } else {
-      r_tmp = TargetReg(arg0.fp ? kFArg0 : kArg0, arg0.fp ? kFArg1 : kArg1);
-    }
-    LoadValueDirectWideFixed(arg0, r_tmp);
+    LoadValueDirectWideFixed(arg0, TargetReg(arg0.fp ? kFArg0 : kArg0, kWide));
   }
   ClobberCallerSave();
   CallHelper<pointer_size>(r_tgt, helper_offset, safepoint_pc);
@@ -173,8 +168,8 @@
 void Mir2Lir::CallRuntimeHelperImmImm(ThreadOffset<pointer_size> helper_offset, int arg0, int arg1,
                                       bool safepoint_pc) {
   RegStorage r_tgt = CallHelperSetup(helper_offset);
-  LoadConstant(TargetReg(kArg0, false), arg0);
-  LoadConstant(TargetReg(kArg1, false), arg1);
+  LoadConstant(TargetReg(kArg0, kNotWide), arg0);
+  LoadConstant(TargetReg(kArg1, kNotWide), arg1);
   ClobberCallerSave();
   CallHelper<pointer_size>(r_tgt, helper_offset, safepoint_pc);
 }
@@ -184,23 +179,14 @@
 void Mir2Lir::CallRuntimeHelperImmRegLocation(ThreadOffset<pointer_size> helper_offset, int arg0,
                                               RegLocation arg1, bool safepoint_pc) {
   RegStorage r_tgt = CallHelperSetup(helper_offset);
+  DCHECK(!arg1.fp);
   if (arg1.wide == 0) {
     LoadValueDirectFixed(arg1, TargetReg(kArg1, arg1));
   } else {
-    RegStorage r_tmp;
-    if (cu_->target64) {
-      r_tmp = TargetReg(kArg1, true);
-    } else {
-      if (cu_->instruction_set == kMips) {
-        // skip kArg1 for stack alignment.
-        r_tmp = TargetReg(kArg2, kArg3);
-      } else {
-        r_tmp = TargetReg(kArg1, kArg2);
-      }
-    }
+    RegStorage r_tmp = TargetReg(cu_->instruction_set == kMips ? kArg2 : kArg1, kWide);
     LoadValueDirectWideFixed(arg1, r_tmp);
   }
-  LoadConstant(TargetReg(kArg0, false), arg0);
+  LoadConstant(TargetReg(kArg0, kNotWide), arg0);
   ClobberCallerSave();
   CallHelper<pointer_size>(r_tgt, helper_offset, safepoint_pc);
 }
@@ -213,7 +199,7 @@
   RegStorage r_tgt = CallHelperSetup(helper_offset);
   DCHECK(!arg0.wide);
   LoadValueDirectFixed(arg0, TargetReg(kArg0, arg0));
-  LoadConstant(TargetReg(kArg1, false), arg1);
+  LoadConstant(TargetReg(kArg1, kNotWide), arg1);
   ClobberCallerSave();
   CallHelper<pointer_size>(r_tgt, helper_offset, safepoint_pc);
 }
@@ -224,8 +210,8 @@
 void Mir2Lir::CallRuntimeHelperImmReg(ThreadOffset<pointer_size> helper_offset, int arg0,
                                       RegStorage arg1, bool safepoint_pc) {
   RegStorage r_tgt = CallHelperSetup(helper_offset);
-  OpRegCopy(TargetReg(kArg1, arg1.Is64Bit()), arg1);
-  LoadConstant(TargetReg(kArg0, false), arg0);
+  OpRegCopy(TargetReg(kArg1, arg1.GetWideKind()), arg1);
+  LoadConstant(TargetReg(kArg0, kNotWide), arg0);
   ClobberCallerSave();
   CallHelper<pointer_size>(r_tgt, helper_offset, safepoint_pc);
 }
@@ -235,8 +221,8 @@
 void Mir2Lir::CallRuntimeHelperRegImm(ThreadOffset<pointer_size> helper_offset, RegStorage arg0,
                                       int arg1, bool safepoint_pc) {
   RegStorage r_tgt = CallHelperSetup(helper_offset);
-  OpRegCopy(TargetReg(kArg0, arg0.Is64Bit()), arg0);
-  LoadConstant(TargetReg(kArg1, false), arg1);
+  OpRegCopy(TargetReg(kArg0, arg0.GetWideKind()), arg0);
+  LoadConstant(TargetReg(kArg1, kNotWide), arg1);
   ClobberCallerSave();
   CallHelper<pointer_size>(r_tgt, helper_offset, safepoint_pc);
 }
@@ -246,8 +232,8 @@
 void Mir2Lir::CallRuntimeHelperImmMethod(ThreadOffset<pointer_size> helper_offset, int arg0,
                                          bool safepoint_pc) {
   RegStorage r_tgt = CallHelperSetup(helper_offset);
-  LoadCurrMethodDirect(TargetRefReg(kArg1));
-  LoadConstant(TargetReg(kArg0, false), arg0);
+  LoadCurrMethodDirect(TargetReg(kArg1, kRef));
+  LoadConstant(TargetReg(kArg0, kNotWide), arg0);
   ClobberCallerSave();
   CallHelper<pointer_size>(r_tgt, helper_offset, safepoint_pc);
 }
@@ -257,11 +243,12 @@
 void Mir2Lir::CallRuntimeHelperRegMethod(ThreadOffset<pointer_size> helper_offset, RegStorage arg0,
                                          bool safepoint_pc) {
   RegStorage r_tgt = CallHelperSetup(helper_offset);
-  DCHECK(!IsSameReg(TargetReg(kArg1, arg0.Is64Bit()), arg0));
-  if (TargetReg(kArg0, arg0.Is64Bit()).NotExactlyEquals(arg0)) {
-    OpRegCopy(TargetReg(kArg0, arg0.Is64Bit()), arg0);
+  DCHECK(!IsSameReg(TargetReg(kArg1, arg0.GetWideKind()), arg0));
+  RegStorage r_tmp = TargetReg(kArg0, arg0.GetWideKind());
+  if (r_tmp.NotExactlyEquals(arg0)) {
+    OpRegCopy(r_tmp, arg0);
   }
-  LoadCurrMethodDirect(TargetRefReg(kArg1));
+  LoadCurrMethodDirect(TargetReg(kArg1, kRef));
   ClobberCallerSave();
   CallHelper<pointer_size>(r_tgt, helper_offset, safepoint_pc);
 }
@@ -272,11 +259,12 @@
                                                     RegStorage arg0, RegLocation arg2,
                                                     bool safepoint_pc) {
   RegStorage r_tgt = CallHelperSetup(helper_offset);
-  DCHECK(!IsSameReg(TargetReg(kArg1, arg0.Is64Bit()), arg0));
-  if (TargetReg(kArg0, arg0.Is64Bit()).NotExactlyEquals(arg0)) {
-    OpRegCopy(TargetReg(kArg0, arg0.Is64Bit()), arg0);
+  DCHECK(!IsSameReg(TargetReg(kArg1, arg0.GetWideKind()), arg0));
+  RegStorage r_tmp = TargetReg(kArg0, arg0.GetWideKind());
+  if (r_tmp.NotExactlyEquals(arg0)) {
+    OpRegCopy(r_tmp, arg0);
   }
-  LoadCurrMethodDirect(TargetRefReg(kArg1));
+  LoadCurrMethodDirect(TargetReg(kArg1, kRef));
   LoadValueDirectFixed(arg2, TargetReg(kArg2, arg2));
   ClobberCallerSave();
   CallHelper<pointer_size>(r_tgt, helper_offset, safepoint_pc);
@@ -313,47 +301,26 @@
   } else {
     DCHECK(!cu_->target64);
     if (arg0.wide == 0) {
-      LoadValueDirectFixed(arg0, arg0.fp ? TargetReg(kFArg0, false) : TargetReg(kArg0, false));
+      LoadValueDirectFixed(arg0, TargetReg(arg0.fp ? kFArg0 : kArg0, kNotWide));
       if (arg1.wide == 0) {
         if (cu_->instruction_set == kMips) {
-          LoadValueDirectFixed(arg1, arg1.fp ? TargetReg(kFArg2, false) : TargetReg(kArg1, false));
+          LoadValueDirectFixed(arg1, TargetReg(arg1.fp ? kFArg2 : kArg1, kNotWide));
         } else {
-          LoadValueDirectFixed(arg1, TargetReg(kArg1, false));
+          LoadValueDirectFixed(arg1, TargetReg(kArg1, kNotWide));
         }
       } else {
         if (cu_->instruction_set == kMips) {
-          RegStorage r_tmp;
-          if (arg1.fp) {
-            r_tmp = TargetReg(kFArg2, kFArg3);
-          } else {
-            // skip kArg1 for stack alignment.
-            r_tmp = TargetReg(kArg2, kArg3);
-          }
-          LoadValueDirectWideFixed(arg1, r_tmp);
+          LoadValueDirectWideFixed(arg1, TargetReg(arg1.fp ? kFArg2 : kArg2, kWide));
         } else {
-          RegStorage r_tmp;
-          r_tmp = TargetReg(kArg1, kArg2);
-          LoadValueDirectWideFixed(arg1, r_tmp);
+          LoadValueDirectWideFixed(arg1, TargetReg(kArg1, kWide));
         }
       }
     } else {
-      RegStorage r_tmp;
-      if (arg0.fp) {
-        r_tmp = TargetReg(kFArg0, kFArg1);
-      } else {
-        r_tmp = TargetReg(kArg0, kArg1);
-      }
-      LoadValueDirectWideFixed(arg0, r_tmp);
+      LoadValueDirectWideFixed(arg0, TargetReg(arg0.fp ? kFArg0 : kArg0, kWide));
       if (arg1.wide == 0) {
-        LoadValueDirectFixed(arg1, arg1.fp ? TargetReg(kFArg2, false) : TargetReg(kArg2, false));
+        LoadValueDirectFixed(arg1, TargetReg(arg1.fp ? kFArg2 : kArg2, kNotWide));
       } else {
-        RegStorage r_tmp;
-        if (arg1.fp) {
-          r_tmp = TargetReg(kFArg2, kFArg3);
-        } else {
-          r_tmp = TargetReg(kArg2, kArg3);
-        }
-        LoadValueDirectWideFixed(arg1, r_tmp);
+        LoadValueDirectWideFixed(arg1, TargetReg(arg1.fp ? kFArg2 : kArg2, kWide));
       }
     }
   }
@@ -364,19 +331,21 @@
             RegLocation arg1, bool safepoint_pc)
 
 void Mir2Lir::CopyToArgumentRegs(RegStorage arg0, RegStorage arg1) {
-  if (IsSameReg(arg1, TargetReg(kArg0, arg1.Is64Bit()))) {
-    if (IsSameReg(arg0, TargetReg(kArg1, arg0.Is64Bit()))) {
+  WideKind arg0_kind = arg0.GetWideKind();
+  WideKind arg1_kind = arg1.GetWideKind();
+  if (IsSameReg(arg1, TargetReg(kArg0, arg1_kind))) {
+    if (IsSameReg(arg0, TargetReg(kArg1, arg0_kind))) {
       // Swap kArg0 and kArg1 with kArg2 as temp.
-      OpRegCopy(TargetReg(kArg2, arg1.Is64Bit()), arg1);
-      OpRegCopy(TargetReg(kArg0, arg0.Is64Bit()), arg0);
-      OpRegCopy(TargetReg(kArg1, arg1.Is64Bit()), TargetReg(kArg2, arg1.Is64Bit()));
+      OpRegCopy(TargetReg(kArg2, arg1_kind), arg1);
+      OpRegCopy(TargetReg(kArg0, arg0_kind), arg0);
+      OpRegCopy(TargetReg(kArg1, arg1_kind), TargetReg(kArg2, arg1_kind));
     } else {
-      OpRegCopy(TargetReg(kArg1, arg1.Is64Bit()), arg1);
-      OpRegCopy(TargetReg(kArg0, arg0.Is64Bit()), arg0);
+      OpRegCopy(TargetReg(kArg1, arg1_kind), arg1);
+      OpRegCopy(TargetReg(kArg0, arg0_kind), arg0);
     }
   } else {
-    OpRegCopy(TargetReg(kArg0, arg0.Is64Bit()), arg0);
-    OpRegCopy(TargetReg(kArg1, arg1.Is64Bit()), arg1);
+    OpRegCopy(TargetReg(kArg0, arg0_kind), arg0);
+    OpRegCopy(TargetReg(kArg1, arg1_kind), arg1);
   }
 }
 
@@ -396,7 +365,7 @@
                                          RegStorage arg1, int arg2, bool safepoint_pc) {
   RegStorage r_tgt = CallHelperSetup(helper_offset);
   CopyToArgumentRegs(arg0, arg1);
-  LoadConstant(TargetReg(kArg2, false), arg2);
+  LoadConstant(TargetReg(kArg2, kNotWide), arg2);
   ClobberCallerSave();
   CallHelper<pointer_size>(r_tgt, helper_offset, safepoint_pc);
 }
@@ -408,8 +377,8 @@
                                                     int arg0, RegLocation arg2, bool safepoint_pc) {
   RegStorage r_tgt = CallHelperSetup(helper_offset);
   LoadValueDirectFixed(arg2, TargetReg(kArg2, arg2));
-  LoadCurrMethodDirect(TargetRefReg(kArg1));
-  LoadConstant(TargetReg(kArg0, false), arg0);
+  LoadCurrMethodDirect(TargetReg(kArg1, kRef));
+  LoadConstant(TargetReg(kArg0, kNotWide), arg0);
   ClobberCallerSave();
   CallHelper<pointer_size>(r_tgt, helper_offset, safepoint_pc);
 }
@@ -420,9 +389,9 @@
 void Mir2Lir::CallRuntimeHelperImmMethodImm(ThreadOffset<pointer_size> helper_offset, int arg0,
                                             int arg2, bool safepoint_pc) {
   RegStorage r_tgt = CallHelperSetup(helper_offset);
-  LoadCurrMethodDirect(TargetRefReg(kArg1));
-  LoadConstant(TargetReg(kArg2, false), arg2);
-  LoadConstant(TargetReg(kArg0, false), arg0);
+  LoadCurrMethodDirect(TargetReg(kArg1, kRef));
+  LoadConstant(TargetReg(kArg2, kNotWide), arg2);
+  LoadConstant(TargetReg(kArg0, kNotWide), arg0);
   ClobberCallerSave();
   CallHelper<pointer_size>(r_tgt, helper_offset, safepoint_pc);
 }
@@ -439,15 +408,9 @@
   if (arg2.wide == 0) {
     LoadValueDirectFixed(arg2, TargetReg(kArg2, arg2));
   } else {
-    RegStorage r_tmp;
-    if (cu_->target64) {
-      r_tmp = TargetReg(kArg2, true);
-    } else {
-      r_tmp = TargetReg(kArg2, kArg3);
-    }
-    LoadValueDirectWideFixed(arg2, r_tmp);
+    LoadValueDirectWideFixed(arg2, TargetReg(kArg2, kWide));
   }
-  LoadConstant(TargetReg(kArg0, false), arg0);
+  LoadConstant(TargetReg(kArg0, kNotWide), arg0);
   ClobberCallerSave();
   CallHelper<pointer_size>(r_tgt, helper_offset, safepoint_pc);
 }
@@ -455,10 +418,12 @@
             RegLocation arg2, bool safepoint_pc)
 
 template <size_t pointer_size>
-void Mir2Lir::CallRuntimeHelperRegLocationRegLocationRegLocation(ThreadOffset<pointer_size> helper_offset,
-                                                                 RegLocation arg0, RegLocation arg1,
-                                                                 RegLocation arg2,
-                                                                 bool safepoint_pc) {
+void Mir2Lir::CallRuntimeHelperRegLocationRegLocationRegLocation(
+    ThreadOffset<pointer_size> helper_offset,
+    RegLocation arg0,
+    RegLocation arg1,
+    RegLocation arg2,
+    bool safepoint_pc) {
   RegStorage r_tgt = CallHelperSetup(helper_offset);
   LoadValueDirectFixed(arg0, TargetReg(kArg0, arg0));
   LoadValueDirectFixed(arg1, TargetReg(kArg1, arg1));
@@ -485,7 +450,7 @@
    */
   RegLocation rl_src = rl_method;
   rl_src.location = kLocPhysReg;
-  rl_src.reg = TargetRefReg(kArg0);
+  rl_src.reg = TargetReg(kArg0, kRef);
   rl_src.home = false;
   MarkLive(rl_src);
   StoreValue(rl_method, rl_src);
@@ -559,15 +524,44 @@
     } else {
       // If arriving in frame & promoted
       if (v_map->core_location == kLocPhysReg) {
-        Load32Disp(TargetPtrReg(kSp), SRegOffset(start_vreg + i), RegStorage::Solo32(v_map->core_reg));
+        Load32Disp(TargetPtrReg(kSp), SRegOffset(start_vreg + i),
+                   RegStorage::Solo32(v_map->core_reg));
       }
       if (v_map->fp_location == kLocPhysReg) {
-        Load32Disp(TargetPtrReg(kSp), SRegOffset(start_vreg + i), RegStorage::Solo32(v_map->fp_reg));
+        Load32Disp(TargetPtrReg(kSp), SRegOffset(start_vreg + i),
+                   RegStorage::Solo32(v_map->fp_reg));
       }
     }
   }
 }
 
+static void CommonCallCodeLoadThisIntoArg1(const CallInfo* info, Mir2Lir* cg) {
+  RegLocation rl_arg = info->args[0];
+  cg->LoadValueDirectFixed(rl_arg, cg->TargetReg(kArg1, kRef));
+}
+
+static void CommonCallCodeLoadClassIntoArg0(const CallInfo* info, Mir2Lir* cg) {
+  cg->GenNullCheck(cg->TargetReg(kArg1, kRef), info->opt_flags);
+  // get this->klass_ [use kArg1, set kArg0]
+  cg->LoadRefDisp(cg->TargetReg(kArg1, kRef), mirror::Object::ClassOffset().Int32Value(),
+                  cg->TargetReg(kArg0, kRef),
+                  kNotVolatile);
+  cg->MarkPossibleNullPointerException(info->opt_flags);
+}
+
+static bool CommonCallCodeLoadCodePointerIntoInvokeTgt(const CallInfo* info,
+                                                       const RegStorage* alt_from,
+                                                       const CompilationUnit* cu, Mir2Lir* cg) {
+  if (cu->instruction_set != kX86 && cu->instruction_set != kX86_64) {
+    // Get the compiled code address [use *alt_from or kArg0, set kInvokeTgt]
+    cg->LoadWordDisp(alt_from == nullptr ? cg->TargetReg(kArg0, kRef) : *alt_from,
+                     mirror::ArtMethod::EntryPointFromQuickCompiledCodeOffset().Int32Value(),
+                     cg->TargetPtrReg(kInvokeTgt));
+    return true;
+  }
+  return false;
+}
+
 /*
  * Bit of a hack here - in the absence of a real scheduling pass,
  * emit the next instruction in static & direct invoke sequences.
@@ -589,7 +583,7 @@
         cg->LoadCodeAddress(target_method, type, kInvokeTgt);
       }
       if (direct_method != static_cast<uintptr_t>(-1)) {
-        cg->LoadConstant(cg->TargetRefReg(kArg0), direct_method);
+        cg->LoadConstant(cg->TargetReg(kArg0, kRef), direct_method);
       } else {
         cg->LoadMethodAddress(target_method, type, kArg0);
       }
@@ -598,7 +592,7 @@
       return -1;
     }
   } else {
-    RegStorage arg0_ref = cg->TargetRefReg(kArg0);
+    RegStorage arg0_ref = cg->TargetReg(kArg0, kRef);
     switch (state) {
     case 0:  // Get the current Method* [sets kArg0]
       // TUNING: we can save a reg copy if Method* has been promoted.
@@ -627,12 +621,11 @@
                       kNotVolatile);
       break;
     case 3:  // Grab the code from the method*
-      if (cu->instruction_set != kX86 && cu->instruction_set != kX86_64) {
-        if (direct_code == 0) {
-          cg->LoadWordDisp(arg0_ref,
-                           mirror::ArtMethod::EntryPointFromQuickCompiledCodeOffset().Int32Value(),
-                           cg->TargetPtrReg(kInvokeTgt));
+      if (direct_code == 0) {
+        if (CommonCallCodeLoadCodePointerIntoInvokeTgt(info, &arg0_ref, cu, cg)) {
+          break;                                    // kInvokeTgt := arg0_ref->entrypoint
         }
+      } else if (cu->instruction_set != kX86 && cu->instruction_set != kX86_64) {
         break;
       }
       // Intentional fallthrough for x86
@@ -660,34 +653,24 @@
    * fully resolved at compile time.
    */
   switch (state) {
-    case 0: {  // Get "this" [set kArg1]
-      RegLocation  rl_arg = info->args[0];
-      cg->LoadValueDirectFixed(rl_arg, cg->TargetRefReg(kArg1));
+    case 0:
+      CommonCallCodeLoadThisIntoArg1(info, cg);   // kArg1 := this
       break;
-    }
-    case 1:  // Is "this" null? [use kArg1]
-      cg->GenNullCheck(cg->TargetRefReg(kArg1), info->opt_flags);
-      // get this->klass_ [use kArg1, set kArg0]
-      cg->LoadRefDisp(cg->TargetRefReg(kArg1), mirror::Object::ClassOffset().Int32Value(),
-                      cg->TargetRefReg(kArg0),
-                      kNotVolatile);
-      cg->MarkPossibleNullPointerException(info->opt_flags);
+    case 1:
+      CommonCallCodeLoadClassIntoArg0(info, cg);  // kArg0 := kArg1->class
+                                                  // Includes a null-check.
       break;
     case 2: {
       // Get this->klass_.embedded_vtable[method_idx] [usr kArg0, set kArg0]
       int32_t offset = mirror::Class::EmbeddedVTableOffset().Uint32Value() +
           method_idx * sizeof(mirror::Class::VTableEntry);
       // Load target method from embedded vtable to kArg0 [use kArg0, set kArg0]
-      cg->LoadRefDisp(cg->TargetRefReg(kArg0), offset, cg->TargetRefReg(kArg0), kNotVolatile);
+      cg->LoadRefDisp(cg->TargetReg(kArg0, kRef), offset, cg->TargetReg(kArg0, kRef), kNotVolatile);
       break;
     }
     case 3:
-      if (cu->instruction_set != kX86 && cu->instruction_set != kX86_64) {
-        // Get the compiled code address [use kArg0, set kInvokeTgt]
-        cg->LoadWordDisp(cg->TargetRefReg(kArg0),
-                         mirror::ArtMethod::EntryPointFromQuickCompiledCodeOffset().Int32Value(),
-                         cg->TargetPtrReg(kInvokeTgt));
-        break;
+      if (CommonCallCodeLoadCodePointerIntoInvokeTgt(info, nullptr, cu, cg)) {
+        break;                                    // kInvokeTgt := kArg0->entrypoint
       }
       // Intentional fallthrough for X86
     default:
@@ -711,40 +694,28 @@
   switch (state) {
     case 0:  // Set target method index in case of conflict [set kHiddenArg, kHiddenFpArg (x86)]
       CHECK_LT(target_method.dex_method_index, target_method.dex_file->NumMethodIds());
-      cg->LoadConstant(cg->TargetReg(kHiddenArg, false), target_method.dex_method_index);
+      cg->LoadConstant(cg->TargetReg(kHiddenArg, kNotWide), target_method.dex_method_index);
       if (cu->instruction_set == kX86) {
-        cg->OpRegCopy(cg->TargetReg(kHiddenFpArg, false), cg->TargetReg(kHiddenArg, false));
+        cg->OpRegCopy(cg->TargetReg(kHiddenFpArg, kNotWide), cg->TargetReg(kHiddenArg, kNotWide));
       }
       break;
-    case 1: {  // Get "this" [set kArg1]
-      RegLocation  rl_arg = info->args[0];
-      cg->LoadValueDirectFixed(rl_arg, cg->TargetRefReg(kArg1));
+    case 1:
+      CommonCallCodeLoadThisIntoArg1(info, cg);   // kArg1 := this
       break;
-    }
-    case 2:  // Is "this" null? [use kArg1]
-      cg->GenNullCheck(cg->TargetRefReg(kArg1), info->opt_flags);
-      // Get this->klass_ [use kArg1, set kArg0]
-      cg->LoadRefDisp(cg->TargetRefReg(kArg1), mirror::Object::ClassOffset().Int32Value(),
-                      cg->TargetRefReg(kArg0),
-                      kNotVolatile);
-      cg->MarkPossibleNullPointerException(info->opt_flags);
+    case 2:
+      CommonCallCodeLoadClassIntoArg0(info, cg);  // kArg0 := kArg1->class
+                                                  // Includes a null-check.
       break;
     case 3: {  // Get target method [use kInvokeTgt, set kArg0]
       int32_t offset = mirror::Class::EmbeddedImTableOffset().Uint32Value() +
           (method_idx % mirror::Class::kImtSize) * sizeof(mirror::Class::ImTableEntry);
       // Load target method from embedded imtable to kArg0 [use kArg0, set kArg0]
-      cg->LoadRefDisp(cg->TargetRefReg(kArg0), offset,
-                      cg->TargetRefReg(kArg0),
-                      kNotVolatile);
+      cg->LoadRefDisp(cg->TargetReg(kArg0, kRef), offset, cg->TargetReg(kArg0, kRef), kNotVolatile);
       break;
     }
     case 4:
-      if (cu->instruction_set != kX86 && cu->instruction_set != kX86_64) {
-        // Get the compiled code address [use kArg0, set kInvokeTgt]
-        cg->LoadWordDisp(cg->TargetRefReg(kArg0),
-                         mirror::ArtMethod::EntryPointFromQuickCompiledCodeOffset().Int32Value(),
-                         cg->TargetPtrReg(kInvokeTgt));
-        break;
+      if (CommonCallCodeLoadCodePointerIntoInvokeTgt(info, nullptr, cu, cg)) {
+        break;                                    // kInvokeTgt := kArg0->entrypoint
       }
       // Intentional fallthrough for X86
     default:
@@ -754,9 +725,9 @@
 }
 
 template <size_t pointer_size>
-static int NextInvokeInsnSP(CompilationUnit* cu, CallInfo* info, ThreadOffset<pointer_size> trampoline,
-                            int state, const MethodReference& target_method,
-                            uint32_t method_idx) {
+static int NextInvokeInsnSP(CompilationUnit* cu, CallInfo* info,
+                            ThreadOffset<pointer_size> trampoline, int state,
+                            const MethodReference& target_method, uint32_t method_idx) {
   Mir2Lir* cg = static_cast<Mir2Lir*>(cu->cg.get());
   /*
    * This handles the case in which the base method is not fully
@@ -765,11 +736,12 @@
   if (state == 0) {
     if (cu->instruction_set != kX86 && cu->instruction_set != kX86_64) {
       // Load trampoline target
-      cg->LoadWordDisp(cg->TargetPtrReg(kSelf), trampoline.Int32Value(), cg->TargetPtrReg(kInvokeTgt));
+      cg->LoadWordDisp(cg->TargetPtrReg(kSelf), trampoline.Int32Value(),
+                       cg->TargetPtrReg(kInvokeTgt));
     }
     // Load kArg0 with method index
     CHECK_EQ(cu->dex_file, target_method.dex_file);
-    cg->LoadConstant(cg->TargetReg(kArg0, false), target_method.dex_method_index);
+    cg->LoadConstant(cg->TargetReg(kArg0, kNotWide), target_method.dex_method_index);
     return 1;
   }
   return -1;
@@ -820,10 +792,12 @@
                            uint32_t unused, uintptr_t unused2,
                            uintptr_t unused3, InvokeType unused4) {
   if (cu->target64) {
-    ThreadOffset<8> trampoline = QUICK_ENTRYPOINT_OFFSET(8, pInvokeVirtualTrampolineWithAccessCheck);
+    ThreadOffset<8> trampoline = QUICK_ENTRYPOINT_OFFSET(8,
+        pInvokeVirtualTrampolineWithAccessCheck);
     return NextInvokeInsnSP<8>(cu, info, trampoline, state, target_method, 0);
   } else {
-    ThreadOffset<4> trampoline = QUICK_ENTRYPOINT_OFFSET(4, pInvokeVirtualTrampolineWithAccessCheck);
+    ThreadOffset<4> trampoline = QUICK_ENTRYPOINT_OFFSET(4,
+        pInvokeVirtualTrampolineWithAccessCheck);
     return NextInvokeInsnSP<4>(cu, info, trampoline, state, target_method, 0);
   }
 }
@@ -834,10 +808,12 @@
                                                 uint32_t unused, uintptr_t unused2,
                                                 uintptr_t unused3, InvokeType unused4) {
   if (cu->target64) {
-      ThreadOffset<8> trampoline = QUICK_ENTRYPOINT_OFFSET(8, pInvokeInterfaceTrampolineWithAccessCheck);
+      ThreadOffset<8> trampoline = QUICK_ENTRYPOINT_OFFSET(8,
+          pInvokeInterfaceTrampolineWithAccessCheck);
       return NextInvokeInsnSP<8>(cu, info, trampoline, state, target_method, 0);
     } else {
-      ThreadOffset<4> trampoline = QUICK_ENTRYPOINT_OFFSET(4, pInvokeInterfaceTrampolineWithAccessCheck);
+      ThreadOffset<4> trampoline = QUICK_ENTRYPOINT_OFFSET(4,
+          pInvokeInterfaceTrampolineWithAccessCheck);
       return NextInvokeInsnSP<4>(cu, info, trampoline, state, target_method, 0);
     }
 }
@@ -848,7 +824,8 @@
                          uint32_t vtable_idx, uintptr_t direct_code,
                          uintptr_t direct_method, InvokeType type, bool skip_this) {
   int last_arg_reg = 3 - 1;
-  int arg_regs[3] = {TargetReg(kArg1, false).GetReg(), TargetReg(kArg2, false).GetReg(), TargetReg(kArg3, false).GetReg()};
+  int arg_regs[3] = {TargetReg(kArg1, kNotWide).GetReg(), TargetReg(kArg2, kNotWide).GetReg(),
+                     TargetReg(kArg3, kNotWide).GetReg()};
 
   int next_reg = 0;
   int next_arg = 0;
@@ -923,7 +900,7 @@
         }
       } else {
         // kArg2 & rArg3 can safely be used here
-        reg = TargetReg(kArg3, false);
+        reg = TargetReg(kArg3, kNotWide);
         {
           ScopedMemRefType mem_ref_type(this, ResourceMask::kDalvikReg);
           Load32Disp(TargetPtrReg(kSp), SRegOffset(rl_arg.s_reg_low) + 4, reg);
@@ -947,7 +924,7 @@
       if (rl_arg.location == kLocPhysReg) {
         arg_reg = rl_arg.reg;
       } else {
-        arg_reg = rl_arg.wide ? TargetReg(kArg2, kArg3) : TargetReg(kArg2, false);
+        arg_reg = TargetReg(kArg2, rl_arg.wide ? kWide : kNotWide);
         if (rl_arg.wide) {
           LoadValueDirectWideFixed(rl_arg, arg_reg);
         } else {
@@ -978,13 +955,13 @@
 
   if (pcrLabel) {
     if (cu_->compiler_driver->GetCompilerOptions().GetExplicitNullChecks()) {
-      *pcrLabel = GenExplicitNullCheck(TargetRefReg(kArg1), info->opt_flags);
+      *pcrLabel = GenExplicitNullCheck(TargetReg(kArg1, kRef), info->opt_flags);
     } else {
       *pcrLabel = nullptr;
       // In lieu of generating a check for kArg1 being null, we need to
       // perform a load when doing implicit checks.
       RegStorage tmp = AllocTemp();
-      Load32Disp(TargetRefReg(kArg1), 0, tmp);
+      Load32Disp(TargetReg(kArg1, kRef), 0, tmp);
       MarkPossibleNullPointerException(info->opt_flags);
       FreeTemp(tmp);
     }
@@ -1058,23 +1035,23 @@
     // Use vldm/vstm pair using kArg3 as a temp
     call_state = next_call_insn(cu_, info, call_state, target_method, vtable_idx,
                              direct_code, direct_method, type);
-    OpRegRegImm(kOpAdd, TargetRefReg(kArg3), TargetPtrReg(kSp), start_offset);
+    OpRegRegImm(kOpAdd, TargetReg(kArg3, kRef), TargetPtrReg(kSp), start_offset);
     LIR* ld = nullptr;
     {
       ScopedMemRefType mem_ref_type(this, ResourceMask::kDalvikReg);
-      ld = OpVldm(TargetRefReg(kArg3), regs_left_to_pass_via_stack);
+      ld = OpVldm(TargetReg(kArg3, kRef), regs_left_to_pass_via_stack);
     }
     // TUNING: loosen barrier
     ld->u.m.def_mask = &kEncodeAll;
     call_state = next_call_insn(cu_, info, call_state, target_method, vtable_idx,
                              direct_code, direct_method, type);
-    OpRegRegImm(kOpAdd, TargetRefReg(kArg3), TargetPtrReg(kSp), 4 /* Method* */ + (3 * 4));
+    OpRegRegImm(kOpAdd, TargetReg(kArg3, kRef), TargetPtrReg(kSp), 4 /* Method* */ + (3 * 4));
     call_state = next_call_insn(cu_, info, call_state, target_method, vtable_idx,
                              direct_code, direct_method, type);
     LIR* st = nullptr;
     {
       ScopedMemRefType mem_ref_type(this, ResourceMask::kDalvikReg);
-      st = OpVstm(TargetRefReg(kArg3), regs_left_to_pass_via_stack);
+      st = OpVstm(TargetReg(kArg3, kRef), regs_left_to_pass_via_stack);
     }
     st->u.m.def_mask = &kEncodeAll;
     call_state = next_call_insn(cu_, info, call_state, target_method, vtable_idx,
@@ -1148,7 +1125,8 @@
           if (ld2 != nullptr) {
             // For 64-bit load we can actually set up the aliasing information.
             AnnotateDalvikRegAccess(ld1, current_src_offset >> 2, true, true);
-            AnnotateDalvikRegAccess(ld2, (current_src_offset + (bytes_to_move >> 1)) >> 2, true, true);
+            AnnotateDalvikRegAccess(ld2, (current_src_offset + (bytes_to_move >> 1)) >> 2, true,
+                                    true);
           } else {
             // Set barrier for 128-bit load.
             ld1->u.m.def_mask = &kEncodeAll;
@@ -1158,7 +1136,8 @@
           if (st2 != nullptr) {
             // For 64-bit store we can actually set up the aliasing information.
             AnnotateDalvikRegAccess(st1, current_dest_offset >> 2, false, true);
-            AnnotateDalvikRegAccess(st2, (current_dest_offset + (bytes_to_move >> 1)) >> 2, false, true);
+            AnnotateDalvikRegAccess(st2, (current_dest_offset + (bytes_to_move >> 1)) >> 2, false,
+                                    true);
           } else {
             // Set barrier for 128-bit store.
             st1->u.m.def_mask = &kEncodeAll;
@@ -1173,7 +1152,7 @@
 
         // Instead of allocating a new temp, simply reuse one of the registers being used
         // for argument passing.
-        RegStorage temp = TargetReg(kArg3, false);
+        RegStorage temp = TargetReg(kArg3, kNotWide);
 
         // Now load the argument VR and store to the outs.
         Load32Disp(TargetPtrReg(kSp), current_src_offset, temp);
@@ -1186,14 +1165,14 @@
     }
   } else {
     // Generate memcpy
-    OpRegRegImm(kOpAdd, TargetRefReg(kArg0), TargetPtrReg(kSp), outs_offset);
-    OpRegRegImm(kOpAdd, TargetRefReg(kArg1), TargetPtrReg(kSp), start_offset);
+    OpRegRegImm(kOpAdd, TargetReg(kArg0, kRef), TargetPtrReg(kSp), outs_offset);
+    OpRegRegImm(kOpAdd, TargetReg(kArg1, kRef), TargetPtrReg(kSp), start_offset);
     if (cu_->target64) {
-      CallRuntimeHelperRegRegImm(QUICK_ENTRYPOINT_OFFSET(8, pMemcpy), TargetRefReg(kArg0),
-                                 TargetRefReg(kArg1), (info->num_arg_words - 3) * 4, false);
+      CallRuntimeHelperRegRegImm(QUICK_ENTRYPOINT_OFFSET(8, pMemcpy), TargetReg(kArg0, kRef),
+                                 TargetReg(kArg1, kRef), (info->num_arg_words - 3) * 4, false);
     } else {
-      CallRuntimeHelperRegRegImm(QUICK_ENTRYPOINT_OFFSET(4, pMemcpy), TargetRefReg(kArg0),
-                                 TargetRefReg(kArg1), (info->num_arg_words - 3) * 4, false);
+      CallRuntimeHelperRegRegImm(QUICK_ENTRYPOINT_OFFSET(4, pMemcpy), TargetReg(kArg0, kRef),
+                                 TargetReg(kArg1, kRef), (info->num_arg_words - 3) * 4, false);
     }
   }
 
@@ -1205,13 +1184,13 @@
                            direct_code, direct_method, type);
   if (pcrLabel) {
     if (cu_->compiler_driver->GetCompilerOptions().GetExplicitNullChecks()) {
-      *pcrLabel = GenExplicitNullCheck(TargetRefReg(kArg1), info->opt_flags);
+      *pcrLabel = GenExplicitNullCheck(TargetReg(kArg1, kRef), info->opt_flags);
     } else {
       *pcrLabel = nullptr;
       // In lieu of generating a check for kArg1 being null, we need to
       // perform a load when doing implicit checks.
       RegStorage tmp = AllocTemp();
-      Load32Disp(TargetRefReg(kArg1), 0, tmp);
+      Load32Disp(TargetReg(kArg1, kRef), 0, tmp);
       MarkPossibleNullPointerException(info->opt_flags);
       FreeTemp(tmp);
     }
@@ -1363,8 +1342,8 @@
 }
 
 bool Mir2Lir::GenInlinedReverseBytes(CallInfo* info, OpSize size) {
-  if (cu_->instruction_set == kMips || cu_->instruction_set == kArm64) {
-    // TODO - add Mips implementation; Enable Arm64.
+  if (cu_->instruction_set == kMips) {
+    // TODO - add Mips implementation.
     return false;
   }
   RegLocation rl_src_i = info->args[0];
@@ -1550,9 +1529,9 @@
 
   ClobberCallerSave();
   LockCallTemps();  // Using fixed registers
-  RegStorage reg_ptr = TargetRefReg(kArg0);
-  RegStorage reg_char = TargetReg(kArg1, false);
-  RegStorage reg_start = TargetReg(kArg2, false);
+  RegStorage reg_ptr = TargetReg(kArg0, kRef);
+  RegStorage reg_char = TargetReg(kArg1, kNotWide);
+  RegStorage reg_start = TargetReg(kArg2, kNotWide);
 
   LoadValueDirectFixed(rl_obj, reg_ptr);
   LoadValueDirectFixed(rl_char, reg_char);
@@ -1594,8 +1573,8 @@
   }
   ClobberCallerSave();
   LockCallTemps();  // Using fixed registers
-  RegStorage reg_this = TargetRefReg(kArg0);
-  RegStorage reg_cmp = TargetRefReg(kArg1);
+  RegStorage reg_this = TargetReg(kArg0, kRef);
+  RegStorage reg_cmp = TargetReg(kArg1, kRef);
 
   RegLocation rl_this = info->args[0];
   RegLocation rl_cmp = info->args[1];
@@ -1877,7 +1856,7 @@
         call_inst =
           reinterpret_cast<X86Mir2Lir*>(this)->CallWithLinkerFixup(target_method, info->type);
       } else {
-        call_inst = OpMem(kOpBlx, TargetRefReg(kArg0),
+        call_inst = OpMem(kOpBlx, TargetReg(kArg0, kRef),
                           mirror::ArtMethod::EntryPointFromQuickCompiledCodeOffset().Int32Value());
       }
     } else {
diff --git a/compiler/dex/quick/mir_to_lir.h b/compiler/dex/quick/mir_to_lir.h
index d6fb090..634ab94 100644
--- a/compiler/dex/quick/mir_to_lir.h
+++ b/compiler/dex/quick/mir_to_lir.h
@@ -1198,29 +1198,28 @@
     /**
      * @brief Portable way of getting special registers from the backend.
      * @param reg Enumeration describing the purpose of the register.
-     * @param is_wide Whether the view should be 64-bit (rather than 32-bit).
+     * @param wide_kind What kind of view of the special register is required.
      * @return Return the #RegStorage corresponding to the given purpose @p reg.
+     *
+     * Note: For 32b system, wide (kWide) views only make sense for the argument registers and the
+     *       return. In that case, this function should return a pair where the first component of
+     *       the result will be the indicated special register.
      */
-    virtual RegStorage TargetReg(SpecialTargetRegister reg, bool is_wide) {
-      return TargetReg(reg);
-    }
-
-    /**
-     * @brief Portable way of getting special register pair from the backend.
-     * @param reg Enumeration describing the purpose of the first register.
-     * @param reg Enumeration describing the purpose of the second register.
-     * @return Return the #RegStorage corresponding to the given purpose @p reg.
-     */
-    virtual RegStorage TargetReg(SpecialTargetRegister reg1, SpecialTargetRegister reg2) {
-      return RegStorage::MakeRegPair(TargetReg(reg1, false), TargetReg(reg2, false));
-    }
-
-    /**
-     * @brief Portable way of getting a special register for storing a reference.
-     * @see TargetReg()
-     */
-    virtual RegStorage TargetRefReg(SpecialTargetRegister reg) {
-      return TargetReg(reg);
+    virtual RegStorage TargetReg(SpecialTargetRegister reg, WideKind wide_kind) {
+      if (wide_kind == kWide) {
+        DCHECK((kArg0 <= reg && reg < kArg7) || (kFArg0 <= reg && reg < kFArg7) || (kRet0 == reg));
+        COMPILE_ASSERT((kArg1 == kArg0 + 1) && (kArg2 == kArg1 + 1) && (kArg3 == kArg2 + 1) &&
+                       (kArg4 == kArg3 + 1) && (kArg5 == kArg4 + 1) && (kArg6 == kArg5 + 1) &&
+                       (kArg7 == kArg6 + 1), kargs_range_unexpected);
+        COMPILE_ASSERT((kFArg1 == kFArg0 + 1) && (kFArg2 == kFArg1 + 1) && (kFArg3 == kFArg2 + 1) &&
+                       (kFArg4 == kFArg3 + 1) && (kFArg5 == kFArg4 + 1) && (kFArg6 == kFArg5 + 1) &&
+                       (kFArg7 == kFArg6 + 1), kfargs_range_unexpected);
+        COMPILE_ASSERT(kRet1 == kRet0 + 1, kret_range_unexpected);
+        return RegStorage::MakeRegPair(TargetReg(reg),
+                                       TargetReg(static_cast<SpecialTargetRegister>(reg + 1)));
+      } else {
+        return TargetReg(reg);
+      }
     }
 
     /**
@@ -1234,9 +1233,9 @@
     // Get a reg storage corresponding to the wide & ref flags of the reg location.
     virtual RegStorage TargetReg(SpecialTargetRegister reg, RegLocation loc) {
       if (loc.ref) {
-        return TargetRefReg(reg);
+        return TargetReg(reg, kRef);
       } else {
-        return TargetReg(reg, loc.wide);
+        return TargetReg(reg, loc.wide ? kWide : kNotWide);
       }
     }
 
diff --git a/compiler/dex/quick/x86/call_x86.cc b/compiler/dex/quick/x86/call_x86.cc
index 8e2a1e3..b7441d7 100644
--- a/compiler/dex/quick/x86/call_x86.cc
+++ b/compiler/dex/quick/x86/call_x86.cc
@@ -151,7 +151,7 @@
 
   // Making a call - use explicit registers
   FlushAllRegs();   /* Everything to home location */
-  RegStorage array_ptr = TargetRefReg(kArg0);
+  RegStorage array_ptr = TargetReg(kArg0, kRef);
   RegStorage payload = TargetPtrReg(kArg1);
   RegStorage method_start = TargetPtrReg(kArg2);
 
diff --git a/compiler/dex/quick/x86/codegen_x86.h b/compiler/dex/quick/x86/codegen_x86.h
index 6655a59..f4fa1b4 100644
--- a/compiler/dex/quick/x86/codegen_x86.h
+++ b/compiler/dex/quick/x86/codegen_x86.h
@@ -89,19 +89,26 @@
   // Required for target - register utilities.
   RegStorage TargetReg(SpecialTargetRegister reg) OVERRIDE;
   RegStorage TargetReg32(SpecialTargetRegister reg);
-  RegStorage TargetReg(SpecialTargetRegister symbolic_reg, bool is_wide) OVERRIDE {
-    RegStorage reg = TargetReg32(symbolic_reg);
-    if (is_wide) {
-      return (reg.Is64Bit()) ? reg : As64BitReg(reg);
+  RegStorage TargetReg(SpecialTargetRegister symbolic_reg, WideKind wide_kind) OVERRIDE {
+    if (wide_kind == kWide) {
+      if (cu_->target64) {
+        return As64BitReg(TargetReg32(symbolic_reg));
+      } else {
+        // x86: construct a pair.
+        DCHECK((kArg0 <= symbolic_reg && symbolic_reg < kArg3) ||
+               (kFArg0 <= symbolic_reg && symbolic_reg < kFArg3) ||
+               (kRet0 == symbolic_reg));
+        return RegStorage::MakeRegPair(TargetReg32(symbolic_reg),
+                                 TargetReg32(static_cast<SpecialTargetRegister>(symbolic_reg + 1)));
+      }
+    } else if (wide_kind == kRef && cu_->target64) {
+      return As64BitReg(TargetReg32(symbolic_reg));
     } else {
-      return (reg.Is32Bit()) ? reg : As32BitReg(reg);
+      return TargetReg32(symbolic_reg);
     }
   }
-  RegStorage TargetRefReg(SpecialTargetRegister symbolic_reg) OVERRIDE {
-    return TargetReg(symbolic_reg, cu_->target64);
-  }
   RegStorage TargetPtrReg(SpecialTargetRegister symbolic_reg) OVERRIDE {
-    return TargetReg(symbolic_reg, cu_->target64);
+    return TargetReg(symbolic_reg, cu_->target64 ? kWide : kNotWide);
   }
   RegStorage GetArgMappingToPhysicalReg(int arg_num);
   RegStorage GetCoreArgMappingToPhysicalReg(int core_arg_num);
diff --git a/compiler/dex/quick/x86/int_x86.cc b/compiler/dex/quick/x86/int_x86.cc
index 1c63da4..2f27482 100755
--- a/compiler/dex/quick/x86/int_x86.cc
+++ b/compiler/dex/quick/x86/int_x86.cc
@@ -858,7 +858,8 @@
     RegLocation rl_new_value = LoadValueWide(rl_src_new_value, kCoreReg);
     RegLocation rl_offset = LoadValueWide(rl_src_offset, kCoreReg);
     LoadValueDirectWide(rl_src_expected, rs_r0q);
-    NewLIR5(kX86LockCmpxchg64AR, rl_object.reg.GetReg(), rl_offset.reg.GetReg(), 0, 0, rl_new_value.reg.GetReg());
+    NewLIR5(kX86LockCmpxchg64AR, 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
     // locked cmpxchg has full barrier semantics, only a scheduling barrier will be generated.
@@ -954,7 +955,8 @@
       rl_offset = LoadValue(rl_src_offset, kCoreReg);
     }
     LoadValueDirect(rl_src_expected, rs_r0);
-    NewLIR5(kX86LockCmpxchgAR, rl_object.reg.GetReg(), rl_offset.reg.GetReg(), 0, 0, rl_new_value.reg.GetReg());
+    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 to prevent reordering with either
     // earlier or later memory accesses.  Since
@@ -1069,23 +1071,23 @@
       RegStorage new_index = index_;
       // Move index out of kArg1, either directly to kArg0, or to kArg2.
       // TODO: clean-up to check not a number but with type
-      if (index_ == m2l_->TargetReg(kArg1, false)) {
-        if (array_base_ == m2l_->TargetRefReg(kArg0)) {
-          m2l_->OpRegCopy(m2l_->TargetReg(kArg2, false), index_);
-          new_index = m2l_->TargetReg(kArg2, false);
+      if (index_ == m2l_->TargetReg(kArg1, kNotWide)) {
+        if (array_base_ == m2l_->TargetReg(kArg0, kRef)) {
+          m2l_->OpRegCopy(m2l_->TargetReg(kArg2, kNotWide), index_);
+          new_index = m2l_->TargetReg(kArg2, kNotWide);
         } else {
-          m2l_->OpRegCopy(m2l_->TargetReg(kArg0, false), index_);
-          new_index = m2l_->TargetReg(kArg0, false);
+          m2l_->OpRegCopy(m2l_->TargetReg(kArg0, kNotWide), index_);
+          new_index = m2l_->TargetReg(kArg0, kNotWide);
         }
       }
       // Load array length to kArg1.
-      m2l_->OpRegMem(kOpMov, m2l_->TargetReg(kArg1, false), array_base_, len_offset_);
+      m2l_->OpRegMem(kOpMov, m2l_->TargetReg(kArg1, kNotWide), array_base_, len_offset_);
       if (cu_->target64) {
         m2l_->CallRuntimeHelperRegReg(QUICK_ENTRYPOINT_OFFSET(8, pThrowArrayBounds),
-                                      new_index, m2l_->TargetReg(kArg1, false), true);
+                                      new_index, m2l_->TargetReg(kArg1, kNotWide), true);
       } else {
         m2l_->CallRuntimeHelperRegReg(QUICK_ENTRYPOINT_OFFSET(4, pThrowArrayBounds),
-                                      new_index, m2l_->TargetReg(kArg1, false), true);
+                                      new_index, m2l_->TargetReg(kArg1, kNotWide), true);
       }
     }
 
@@ -1118,14 +1120,16 @@
       GenerateTargetLabel(kPseudoThrowTarget);
 
       // Load array length to kArg1.
-      m2l_->OpRegMem(kOpMov, m2l_->TargetReg(kArg1, false), array_base_, len_offset_);
-      m2l_->LoadConstant(m2l_->TargetReg(kArg0, false), index_);
+      m2l_->OpRegMem(kOpMov, m2l_->TargetReg(kArg1, kNotWide), array_base_, len_offset_);
+      m2l_->LoadConstant(m2l_->TargetReg(kArg0, kNotWide), index_);
       if (cu_->target64) {
         m2l_->CallRuntimeHelperRegReg(QUICK_ENTRYPOINT_OFFSET(8, pThrowArrayBounds),
-                                      m2l_->TargetReg(kArg0, false), m2l_->TargetReg(kArg1, false), true);
+                                      m2l_->TargetReg(kArg0, kNotWide),
+                                      m2l_->TargetReg(kArg1, kNotWide), true);
       } else {
         m2l_->CallRuntimeHelperRegReg(QUICK_ENTRYPOINT_OFFSET(4, pThrowArrayBounds),
-                                      m2l_->TargetReg(kArg0, false), m2l_->TargetReg(kArg1, false), true);
+                                      m2l_->TargetReg(kArg0, kNotWide),
+                                      m2l_->TargetReg(kArg1, kNotWide), true);
       }
     }
 
@@ -1471,7 +1475,8 @@
   int displacement = SRegOffset(rl_src.s_reg_low);
 
   ScopedMemRefType mem_ref_type(this, ResourceMask::kDalvikReg);
-  LIR *lir = NewLIR3(x86op, cu_->target64 ? rl_dest.reg.GetReg() : rl_dest.reg.GetLowReg(), r_base, displacement + LOWORD_OFFSET);
+  LIR *lir = NewLIR3(x86op, cu_->target64 ? rl_dest.reg.GetReg() : rl_dest.reg.GetLowReg(),
+                     r_base, displacement + LOWORD_OFFSET);
   AnnotateDalvikRegAccess(lir, (displacement + LOWORD_OFFSET) >> 2,
                           true /* is_load */, true /* is64bit */);
   if (!cu_->target64) {
@@ -2350,8 +2355,9 @@
 
   // If Method* is already in a register, we can save a copy.
   RegLocation rl_method = mir_graph_->GetMethodLoc();
-  int32_t offset_of_type = mirror::Array::DataOffset(sizeof(mirror::HeapReference<mirror::Class*>)).Int32Value() +
-    (sizeof(mirror::HeapReference<mirror::Class*>) * type_idx);
+  int32_t offset_of_type = mirror::Array::DataOffset(
+      sizeof(mirror::HeapReference<mirror::Class*>)).Int32Value() +
+      (sizeof(mirror::HeapReference<mirror::Class*>) * type_idx);
 
   if (rl_method.location == kLocPhysReg) {
     if (use_declaring_class) {
@@ -2399,10 +2405,10 @@
   FlushAllRegs();
   // May generate a call - use explicit registers.
   LockCallTemps();
-  RegStorage method_reg = TargetRefReg(kArg1);  // kArg1 gets current Method*.
+  RegStorage method_reg = TargetReg(kArg1, kRef);  // kArg1 gets current Method*.
   LoadCurrMethodDirect(method_reg);
-  RegStorage class_reg = TargetRefReg(kArg2);  // kArg2 will hold the Class*.
-  RegStorage ref_reg = TargetRefReg(kArg0);  // kArg2 will hold the ref.
+  RegStorage class_reg = TargetReg(kArg2, kRef);  // kArg2 will hold the Class*.
+  RegStorage ref_reg = TargetReg(kArg0, kRef);  // kArg2 will hold the ref.
   // Reference must end up in kArg0.
   if (needs_access_check) {
     // Check we have access to type_idx and if not throw IllegalAccessError,
@@ -2414,7 +2420,7 @@
       CallRuntimeHelperImm(QUICK_ENTRYPOINT_OFFSET(4, pInitializeTypeAndVerifyAccess),
                            type_idx, true);
     }
-    OpRegCopy(class_reg, TargetRefReg(kRet0));
+    OpRegCopy(class_reg, TargetReg(kRet0, kRef));
     LoadValueDirectFixed(rl_src, ref_reg);
   } else if (use_declaring_class) {
     LoadValueDirectFixed(rl_src, ref_reg);
@@ -2438,7 +2444,7 @@
       } else {
         CallRuntimeHelperImm(QUICK_ENTRYPOINT_OFFSET(4, pInitializeType), type_idx, true);
       }
-      OpRegCopy(class_reg, TargetRefReg(kRet0));  // Align usage with fast path.
+      OpRegCopy(class_reg, TargetReg(kRet0, kRef));  // Align usage with fast path.
       LoadValueDirectFixed(rl_src, ref_reg);  /* Reload Ref. */
       // Rejoin code paths
       LIR* hop_target = NewLIR0(kPseudoTargetLabel);
@@ -2459,7 +2465,7 @@
   // Is the class NULL?
   LIR* branch1 = OpCmpImmBranch(kCondEq, ref_reg, 0, NULL);
 
-  RegStorage ref_class_reg = TargetRefReg(kArg1);  // kArg2 will hold the Class*.
+  RegStorage ref_class_reg = TargetReg(kArg1, kRef);  // kArg2 will hold the Class*.
   /* Load object->klass_. */
   DCHECK_EQ(mirror::Object::ClassOffset().Int32Value(), 0);
   LoadRefDisp(ref_reg,  mirror::Object::ClassOffset().Int32Value(), ref_class_reg,
@@ -2477,7 +2483,7 @@
       LoadConstant(rl_result.reg, 1);     // Assume result succeeds.
       branchover = OpCmpBranch(kCondEq, ref_class_reg, class_reg, NULL);
     }
-    OpRegCopy(TargetRefReg(kArg0), class_reg);
+    OpRegCopy(TargetReg(kArg0, kRef), class_reg);
     if (cu_->target64) {
       OpThreadMem(kOpBlx, QUICK_ENTRYPOINT_OFFSET(8, pInstanceofNonTrivial));
     } else {
@@ -2617,7 +2623,7 @@
   } else {
     if (shift_op) {
       // X86 doesn't require masking and must use ECX.
-      RegStorage t_reg = TargetReg(kCount, false);  // rCX
+      RegStorage t_reg = TargetReg(kCount, kNotWide);  // rCX
       LoadValueDirectFixed(rl_rhs, t_reg);
       if (is_two_addr) {
         // Can we do this directly into memory?
@@ -2805,7 +2811,7 @@
   }
 
   // X86 doesn't require masking and must use ECX.
-  RegStorage t_reg = TargetReg(kCount, false);  // rCX
+  RegStorage t_reg = TargetReg(kCount, kNotWide);  // rCX
   LoadValueDirectFixed(rl_shift, t_reg);
   if (is_two_addr) {
     // Can we do this directly into memory?
diff --git a/compiler/dex/quick/x86/target_x86.cc b/compiler/dex/quick/x86/target_x86.cc
index 0083128..bb1f379 100755
--- a/compiler/dex/quick/x86/target_x86.cc
+++ b/compiler/dex/quick/x86/target_x86.cc
@@ -204,7 +204,8 @@
     case kSuspend: res_reg =  RegStorage::InvalidReg(); break;
     case kLr: res_reg =  RegStorage::InvalidReg(); break;
     case kPc: res_reg =  RegStorage::InvalidReg(); break;
-    case kSp: res_reg =  rs_rX86_SP; break;
+    case kSp: res_reg =  rs_rX86_SP_32; break;  // This must be the concrete one, as _SP is target-
+                                                // specific size.
     case kArg0: res_reg = rs_rX86_ARG0; break;
     case kArg1: res_reg = rs_rX86_ARG1; break;
     case kArg2: res_reg = rs_rX86_ARG2; break;
@@ -968,7 +969,8 @@
   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, false).GetReg(),
+  LIR *move = RawLIR(current_dalvik_offset_, kX86Mov32RI,
+                     TargetReg(symbolic_reg, kNotWide).GetReg(),
                      static_cast<int>(target_method_id_ptr), target_method_idx,
                      WrapPointer(const_cast<DexFile*>(target_dex_file)), type);
   AppendLIR(move);
@@ -985,7 +987,8 @@
   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, false).GetReg(),
+  LIR *move = RawLIR(current_dalvik_offset_, kX86Mov32RI,
+                     TargetReg(symbolic_reg, kNotWide).GetReg(),
                      static_cast<int>(ptr), type_idx);
   AppendLIR(move);
   class_type_address_insns_.Insert(move);
@@ -1321,7 +1324,8 @@
         }
       } else {
         // Load the start index from stack, remembering that we pushed EDI.
-        int displacement = SRegOffset(rl_start.s_reg_low) + (cu_->target64 ? 2 : 1) * sizeof(uint32_t);
+        int displacement = SRegOffset(rl_start.s_reg_low) +
+                           (cu_->target64 ? 2 : 1) * sizeof(uint32_t);
         {
           ScopedMemRefType mem_ref_type(this, ResourceMask::kDalvikReg);
           Load32Disp(rs_rX86_SP, displacement, tmpReg);
@@ -2241,21 +2245,24 @@
 }
 
 // ------------ ABI support: mapping of args to physical registers -------------
-RegStorage X86Mir2Lir::InToRegStorageX86_64Mapper::GetNextReg(bool is_double_or_float, bool is_wide, bool is_ref) {
+RegStorage X86Mir2Lir::InToRegStorageX86_64Mapper::GetNextReg(bool is_double_or_float, bool is_wide,
+                                                              bool is_ref) {
   const SpecialTargetRegister coreArgMappingToPhysicalReg[] = {kArg1, kArg2, kArg3, kArg4, kArg5};
-  const int coreArgMappingToPhysicalRegSize = sizeof(coreArgMappingToPhysicalReg) / sizeof(SpecialTargetRegister);
+  const int coreArgMappingToPhysicalRegSize = sizeof(coreArgMappingToPhysicalReg) /
+      sizeof(SpecialTargetRegister);
   const SpecialTargetRegister fpArgMappingToPhysicalReg[] = {kFArg0, kFArg1, kFArg2, kFArg3,
-                                                  kFArg4, kFArg5, kFArg6, kFArg7};
-  const int fpArgMappingToPhysicalRegSize = sizeof(fpArgMappingToPhysicalReg) / sizeof(SpecialTargetRegister);
+                                                             kFArg4, kFArg5, kFArg6, kFArg7};
+  const int fpArgMappingToPhysicalRegSize = sizeof(fpArgMappingToPhysicalReg) /
+      sizeof(SpecialTargetRegister);
 
   if (is_double_or_float) {
     if (cur_fp_reg_ < fpArgMappingToPhysicalRegSize) {
-      return ml_->TargetReg(fpArgMappingToPhysicalReg[cur_fp_reg_++], is_wide);
+      return ml_->TargetReg(fpArgMappingToPhysicalReg[cur_fp_reg_++], is_wide ? kWide : kNotWide);
     }
   } else {
     if (cur_core_reg_ < coreArgMappingToPhysicalRegSize) {
-      return is_ref ? ml_->TargetRefReg(coreArgMappingToPhysicalReg[cur_core_reg_++]) :
-                      ml_->TargetReg(coreArgMappingToPhysicalReg[cur_core_reg_++], is_wide);
+      return ml_->TargetReg(coreArgMappingToPhysicalReg[cur_core_reg_++],
+                            is_ref ? kRef : (is_wide ? kWide : kNotWide));
     }
   }
   return RegStorage::InvalidReg();
@@ -2267,7 +2274,8 @@
   return res != mapping_.end() ? res->second : RegStorage::InvalidReg();
 }
 
-void X86Mir2Lir::InToRegStorageMapping::Initialize(RegLocation* arg_locs, int count, InToRegStorageMapper* mapper) {
+void X86Mir2Lir::InToRegStorageMapping::Initialize(RegLocation* arg_locs, int count,
+                                                   InToRegStorageMapper* mapper) {
   DCHECK(mapper != nullptr);
   max_mapped_in_ = -1;
   is_there_stack_mapped_ = false;
@@ -2338,13 +2346,13 @@
 
   RegLocation rl_src = rl_method;
   rl_src.location = kLocPhysReg;
-  rl_src.reg = TargetRefReg(kArg0);
+  rl_src.reg = TargetReg(kArg0, kRef);
   rl_src.home = false;
   MarkLive(rl_src);
   StoreValue(rl_method, rl_src);
   // If Method* has been promoted, explicitly flush
   if (rl_method.location == kLocPhysReg) {
-    StoreRefDisp(rs_rX86_SP, 0, As32BitReg(TargetRefReg(kArg0)), kNotVolatile);
+    StoreRefDisp(rs_rX86_SP, 0, As32BitReg(TargetReg(kArg0, kRef)), kNotVolatile);
   }
 
   if (cu_->num_ins == 0) {
@@ -2502,7 +2510,8 @@
 
     // The rest can be copied together
     int start_offset = SRegOffset(info->args[last_mapped_in + size_of_the_last_mapped].s_reg_low);
-    int outs_offset = StackVisitor::GetOutVROffset(last_mapped_in + size_of_the_last_mapped, cu_->instruction_set);
+    int outs_offset = StackVisitor::GetOutVROffset(last_mapped_in + size_of_the_last_mapped,
+                                                   cu_->instruction_set);
 
     int current_src_offset = start_offset;
     int current_dest_offset = outs_offset;
@@ -2598,7 +2607,7 @@
 
         // Instead of allocating a new temp, simply reuse one of the registers being used
         // for argument passing.
-        RegStorage temp = TargetReg(kArg3, false);
+        RegStorage temp = TargetReg(kArg3, kNotWide);
 
         // Now load the argument VR and store to the outs.
         Load32Disp(rs_rX86_SP, current_src_offset, temp);
@@ -2614,8 +2623,8 @@
 
   // Now handle rest not registers if they are
   if (in_to_reg_storage_mapping.IsThereStackMapped()) {
-    RegStorage regSingle = TargetReg(kArg2, false);
-    RegStorage regWide = TargetReg(kArg3, true);
+    RegStorage regSingle = TargetReg(kArg2, kNotWide);
+    RegStorage regWide = TargetReg(kArg3, kWide);
     for (int i = start_index;
          i < last_mapped_in + size_of_the_last_mapped + regs_left_to_pass_via_stack; i++) {
       RegLocation rl_arg = info->args[i];
@@ -2674,13 +2683,13 @@
                            direct_code, direct_method, type);
   if (pcrLabel) {
     if (cu_->compiler_driver->GetCompilerOptions().GetExplicitNullChecks()) {
-      *pcrLabel = GenExplicitNullCheck(TargetRefReg(kArg1), info->opt_flags);
+      *pcrLabel = GenExplicitNullCheck(TargetReg(kArg1, kRef), info->opt_flags);
     } else {
       *pcrLabel = nullptr;
       // In lieu of generating a check for kArg1 being null, we need to
       // perform a load when doing implicit checks.
       RegStorage tmp = AllocTemp();
-      Load32Disp(TargetRefReg(kArg1), 0, tmp);
+      Load32Disp(TargetReg(kArg1, kRef), 0, tmp);
       MarkPossibleNullPointerException(info->opt_flags);
       FreeTemp(tmp);
     }
diff --git a/compiler/dex/reg_storage.h b/compiler/dex/reg_storage.h
index 8ed3adc..addd628 100644
--- a/compiler/dex/reg_storage.h
+++ b/compiler/dex/reg_storage.h
@@ -18,6 +18,7 @@
 #define ART_COMPILER_DEX_REG_STORAGE_H_
 
 #include "base/logging.h"
+#include "compiler_enums.h"  // For WideKind
 
 namespace art {
 
@@ -149,6 +150,10 @@
     return ((reg_ & k64BitMask) == k64Bits);
   }
 
+  constexpr WideKind GetWideKind() const {
+    return Is64Bit() ? kWide : kNotWide;
+  }
+
   constexpr bool Is64BitSolo() const {
     return ((reg_ & kShapeMask) == k64BitSolo);
   }
diff --git a/disassembler/disassembler_x86.cc b/disassembler/disassembler_x86.cc
index a6f9a8a..101a55d 100644
--- a/disassembler/disassembler_x86.cc
+++ b/disassembler/disassembler_x86.cc
@@ -125,10 +125,11 @@
   DumpAddrReg(os, rex, reg_num);
 }
 
-static void DumpOpcodeReg(std::ostream& os, uint8_t rex, uint8_t reg) {
+static void DumpOpcodeReg(std::ostream& os, uint8_t rex, uint8_t reg,
+                          bool byte_operand, uint8_t size_override) {
   bool rex_b = (rex & REX_B) != 0;
   size_t reg_num = rex_b ? (reg + 8) : reg;
-  DumpReg0(os, rex, reg_num, false, 0);
+  DumpReg0(os, rex, reg_num, byte_operand, size_override);
 }
 
 enum SegmentPrefix {
@@ -955,6 +956,7 @@
     immediate_bytes = 1;
     byte_operand = true;
     reg_in_opcode = true;
+    byte_operand = true;
     break;
   case 0xB8: case 0xB9: case 0xBA: case 0xBB: case 0xBC: case 0xBD: case 0xBE: case 0xBF:
     if (rex == 0x48) {
@@ -1079,7 +1081,7 @@
   uint8_t rex_w = (supports_rex_ && target_specific) ? (rex | 0x48) : rex;
   if (reg_in_opcode) {
     DCHECK(!has_modrm);
-    DumpOpcodeReg(args, rex_w, *instr & 0x7);
+    DumpOpcodeReg(args, rex_w, *instr & 0x7, byte_operand, prefix[2]);
   }
   instr++;
   uint32_t address_bits = 0;
diff --git a/test/082-inline-execute/src/Main.java b/test/082-inline-execute/src/Main.java
index 739dbf8..1c3c89e 100644
--- a/test/082-inline-execute/src/Main.java
+++ b/test/082-inline-execute/src/Main.java
@@ -34,6 +34,9 @@
     test_Math_max_F();
     test_Math_min_D();
     test_Math_max_D();
+    test_Short_reverseBytes();
+    test_Integer_reverseBytes();
+    test_Long_reverseBytes();
     test_Integer_reverse();
     test_Long_reverse();
     test_StrictMath_abs_I();
@@ -499,6 +502,34 @@
     Assert.assertEquals(Double.longBitsToDouble(0xfff0000000000000L), Double.NEGATIVE_INFINITY);
   }
 
+  public static void test_Short_reverseBytes() {
+      Assert.assertEquals(Short.reverseBytes((short)0x0000), (short)0x0000);
+      Assert.assertEquals(Short.reverseBytes((short)0xffff), (short)0xffff);
+      Assert.assertEquals(Short.reverseBytes((short)0x8000), (short)0x0080);
+      Assert.assertEquals(Short.reverseBytes((short)0x0080), (short)0x8000);
+      Assert.assertEquals(Short.reverseBytes((short)0x0123), (short)0x2301);
+      Assert.assertEquals(Short.reverseBytes((short)0x4567), (short)0x6745);
+      Assert.assertEquals(Short.reverseBytes((short)0x89ab), (short)0xab89);
+      Assert.assertEquals(Short.reverseBytes((short)0xcdef), (short)0xefcd);
+  }
+
+  public static void test_Integer_reverseBytes() {
+      Assert.assertEquals(Integer.reverseBytes(0x00000000), 0x00000000);
+      Assert.assertEquals(Integer.reverseBytes(0xffffffff), 0xffffffff);
+      Assert.assertEquals(Integer.reverseBytes(0x80000000), 0x00000080);
+      Assert.assertEquals(Integer.reverseBytes(0x00000080), 0x80000000);
+      Assert.assertEquals(Integer.reverseBytes(0x01234567), 0x67452301);
+      Assert.assertEquals(Integer.reverseBytes(0x89abcdef), 0xefcdab89);
+  }
+
+  public static void test_Long_reverseBytes() {
+      Assert.assertEquals(Long.reverseBytes(0x0000000000000000L), 0x0000000000000000L);
+      Assert.assertEquals(Long.reverseBytes(0xffffffffffffffffL), 0xffffffffffffffffL);
+      Assert.assertEquals(Long.reverseBytes(0x8000000000000000L), 0x0000000000000080L);
+      Assert.assertEquals(Long.reverseBytes(0x0000000000000080L), 0x8000000000000000L);
+      Assert.assertEquals(Long.reverseBytes(0x0123456789abcdefL), 0xefcdab8967452301L);
+  }
+
   public static void test_Integer_reverse() {
     Assert.assertEquals(Integer.reverse(1), 0x80000000);
     Assert.assertEquals(Integer.reverse(-1), 0xffffffff);
@@ -513,11 +544,9 @@
     Assert.assertEquals(Long.reverse(1L), 0x8000000000000000L);
     Assert.assertEquals(Long.reverse(-1L), 0xffffffffffffffffL);
     Assert.assertEquals(Long.reverse(0L), 0L);
-    // FIXME: This asserts fail with or without this patch. I have collected
-    // the expected results on my host machine.
-    // Assert.assertEquals(Long.reverse(0x1234567812345678L), 0x1e6a2c481e6a2c48L);
-    // Assert.assertEquals(Long.reverse(0x8765432187654321L), 0x84c2a6e184c2a6e1L);
-    // Assert.assertEquals(Long.reverse(Long.MAX_VALUE), 0xfffffffffffffffeL);
+    Assert.assertEquals(Long.reverse(0x1234567812345678L), 0x1e6a2c481e6a2c48L);
+    Assert.assertEquals(Long.reverse(0x8765432187654321L), 0x84c2a6e184c2a6e1L);
+    Assert.assertEquals(Long.reverse(Long.MAX_VALUE), 0xfffffffffffffffeL);
     Assert.assertEquals(Long.reverse(Long.MIN_VALUE), 1L);
   }
 
diff --git a/test/701-easy-div-rem/expected.txt b/test/701-easy-div-rem/expected.txt
new file mode 100644
index 0000000..97be343
--- /dev/null
+++ b/test/701-easy-div-rem/expected.txt
@@ -0,0 +1,8 @@
+Begin
+Int: checking some equally spaced dividends...
+Int: checking small dividends...
+Int: checking big dividends...
+Long: checking some equally spaced dividends...
+Long: checking small dividends...
+Long: checking big dividends...
+End
diff --git a/test/701-easy-div-rem/genMain.py b/test/701-easy-div-rem/genMain.py
new file mode 100644
index 0000000..80eac34
--- /dev/null
+++ b/test/701-easy-div-rem/genMain.py
@@ -0,0 +1,155 @@
+# Copyright (C) 2014 The Android Open Source Project
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+#      http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+
+all_tests = [
+    ({'@INT@': 'int', '@SUFFIX@':''},
+     [('CheckDiv', 'idiv_by_pow2_', [2**i for i in range(31)]),
+      ('CheckDiv', 'idiv_by_small_', [i for i in range(3, 16) if i not in (4, 8)]),
+      ('CheckRem', 'irem_by_pow2_', [2**i for i in range(31)])]),
+    ({'@INT@': 'long', '@SUFFIX@': 'l'},
+     [('CheckDiv', 'ldiv_by_pow2_', [2**i for i in range(63)]),
+      ('CheckDiv', 'ldiv_by_small_', [i for i in range(3, 16) if i not in (4, 8)]),
+      ('CheckRem', 'lrem_by_pow2_', [2**i for i in range(63)])])
+]
+
+def subst_vars(variables, text):
+    '''Substitute variables in text.'''
+    for key, value in variables.iteritems():
+        text = text.replace(str(key), str(value))
+    return text
+
+# Generate all the function bodies (in decls) and all the function calls (in calls).
+decls, calls = '', {}
+for default_vars, tests in all_tests:
+    local_vars = default_vars.copy()
+    int_type = local_vars['@INT@']
+    for checker, name, values in tests:
+        local_vars['@CHECKER@'] = checker
+        for i, value in enumerate(values):
+            local_vars['@NAME@'] = name + str(i)
+            local_vars['@VALUE@'] = value
+            local_vars['@OP@'] = '/' if 'div' in name else '%'
+
+            # Function body.
+            decls += subst_vars(local_vars, '''
+    public static @INT@ @NAME@(@INT@ x) {return x @OP@ @VALUE@@SUFFIX@;}''')
+
+            # Function call and test.
+            calls[int_type] = calls.get(int_type, '') + subst_vars(local_vars, '''
+        @INT@@CHECKER@("@NAME@", @NAME@(x), x, @VALUE@@SUFFIX@);''')
+
+# Generate the checkers.
+checkers = ''
+local_vars = {}
+for int_type in ('int', 'long'):
+    local_vars['@INT@'] = int_type
+    for op, op_name in (('/', 'Div'), ('%', 'Rem')):
+        local_vars['@OP@'] = op
+        local_vars['@OP_NAME@'] = op_name
+        checkers += subst_vars(local_vars, '''
+    public static void @INT@Check@OP_NAME@(String desc, @INT@ result, @INT@ dividend, @INT@ divisor) {
+        @INT@ correct_result = dividend @OP@ divisor;
+        if (result != correct_result) {
+            reportError(desc + "(" + dividend + ") == " + result +
+                        " should be " + correct_result);
+        }
+    }''')
+
+
+code = \
+'''/*
+ * Copyright (C) 2014 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+public class Main {
+    public static int num_errors = 0;
+
+    public static void reportError(String message) {
+        if (num_errors == 10) {
+            System.out.println("Omitting other error messages...");
+        } else if (num_errors < 10) {
+            System.out.println(message);
+        }
+        num_errors += 1;
+    }
+%s
+%s
+
+    public static void intCheckAll(int x) {%s
+    }
+
+    public static void longCheckAll(long x) {%s
+    }
+
+    public static void main(String[] args) {
+      int i;
+      long l;
+
+      System.out.println("Begin");
+
+      System.out.println("Int: checking some equally spaced dividends...");
+      for (i = -1000; i < 1000; i += 300) {
+          intCheckAll(i);
+          intCheckAll(-i);
+      }
+
+      System.out.println("Int: checking small dividends...");
+      for (i = 1; i < 100; i += 1) {
+          intCheckAll(i);
+          intCheckAll(-i);
+      }
+
+      System.out.println("Int: checking big dividends...");
+      for (i = 0; i < 100; i += 1) {
+          intCheckAll(Integer.MAX_VALUE - i);
+          intCheckAll(Integer.MIN_VALUE + i);
+      }
+
+      System.out.println("Long: checking some equally spaced dividends...");
+      for (l = 0l; l < 1000000000000l; l += 300000000000l) {
+          longCheckAll(l);
+          longCheckAll(-l);
+      }
+
+      System.out.println("Long: checking small dividends...");
+      for (l = 1l; l < 100l; l += 1l) {
+          longCheckAll(l);
+          longCheckAll(-l);
+      }
+
+      System.out.println("Long: checking big dividends...");
+      for (l = 0l; l < 100l; l += 1l) {
+          longCheckAll(Long.MAX_VALUE - l);
+          longCheckAll(Long.MIN_VALUE + l);
+      }
+
+      System.out.println("End");
+    }
+}
+''' % (checkers, decls, calls['int'], calls['long'])
+
+with open('src/Main.java', 'w') as f:
+    f.write(code)
diff --git a/test/701-easy-div-rem/info.txt b/test/701-easy-div-rem/info.txt
new file mode 100644
index 0000000..56d1786
--- /dev/null
+++ b/test/701-easy-div-rem/info.txt
@@ -0,0 +1 @@
+Simple tests for checking easy division/reminder for int and longs.
diff --git a/test/701-easy-div-rem/src/Main.java b/test/701-easy-div-rem/src/Main.java
new file mode 100644
index 0000000..f995f61
--- /dev/null
+++ b/test/701-easy-div-rem/src/Main.java
@@ -0,0 +1,529 @@
+/*
+ * Copyright (C) 2014 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+public class Main {
+    public static int num_errors = 0;
+
+    public static void reportError(String message) {
+        if (num_errors == 10) {
+            System.out.println("Omitting other error messages...");
+        } else if (num_errors < 10) {
+            System.out.println(message);
+        }
+        num_errors += 1;
+    }
+
+    public static void intCheckDiv(String desc, int result, int dividend, int divisor) {
+        int correct_result = dividend / divisor;
+        if (result != correct_result) {
+            reportError(desc + "(" + dividend + ") == " + result +
+                        " should be " + correct_result);
+        }
+    }
+    public static void intCheckRem(String desc, int result, int dividend, int divisor) {
+        int correct_result = dividend % divisor;
+        if (result != correct_result) {
+            reportError(desc + "(" + dividend + ") == " + result +
+                        " should be " + correct_result);
+        }
+    }
+    public static void longCheckDiv(String desc, long result, long dividend, long divisor) {
+        long correct_result = dividend / divisor;
+        if (result != correct_result) {
+            reportError(desc + "(" + dividend + ") == " + result +
+                        " should be " + correct_result);
+        }
+    }
+    public static void longCheckRem(String desc, long result, long dividend, long divisor) {
+        long correct_result = dividend % divisor;
+        if (result != correct_result) {
+            reportError(desc + "(" + dividend + ") == " + result +
+                        " should be " + correct_result);
+        }
+    }
+
+    public static int idiv_by_pow2_0(int x) {return x / 1;}
+    public static int idiv_by_pow2_1(int x) {return x / 2;}
+    public static int idiv_by_pow2_2(int x) {return x / 4;}
+    public static int idiv_by_pow2_3(int x) {return x / 8;}
+    public static int idiv_by_pow2_4(int x) {return x / 16;}
+    public static int idiv_by_pow2_5(int x) {return x / 32;}
+    public static int idiv_by_pow2_6(int x) {return x / 64;}
+    public static int idiv_by_pow2_7(int x) {return x / 128;}
+    public static int idiv_by_pow2_8(int x) {return x / 256;}
+    public static int idiv_by_pow2_9(int x) {return x / 512;}
+    public static int idiv_by_pow2_10(int x) {return x / 1024;}
+    public static int idiv_by_pow2_11(int x) {return x / 2048;}
+    public static int idiv_by_pow2_12(int x) {return x / 4096;}
+    public static int idiv_by_pow2_13(int x) {return x / 8192;}
+    public static int idiv_by_pow2_14(int x) {return x / 16384;}
+    public static int idiv_by_pow2_15(int x) {return x / 32768;}
+    public static int idiv_by_pow2_16(int x) {return x / 65536;}
+    public static int idiv_by_pow2_17(int x) {return x / 131072;}
+    public static int idiv_by_pow2_18(int x) {return x / 262144;}
+    public static int idiv_by_pow2_19(int x) {return x / 524288;}
+    public static int idiv_by_pow2_20(int x) {return x / 1048576;}
+    public static int idiv_by_pow2_21(int x) {return x / 2097152;}
+    public static int idiv_by_pow2_22(int x) {return x / 4194304;}
+    public static int idiv_by_pow2_23(int x) {return x / 8388608;}
+    public static int idiv_by_pow2_24(int x) {return x / 16777216;}
+    public static int idiv_by_pow2_25(int x) {return x / 33554432;}
+    public static int idiv_by_pow2_26(int x) {return x / 67108864;}
+    public static int idiv_by_pow2_27(int x) {return x / 134217728;}
+    public static int idiv_by_pow2_28(int x) {return x / 268435456;}
+    public static int idiv_by_pow2_29(int x) {return x / 536870912;}
+    public static int idiv_by_pow2_30(int x) {return x / 1073741824;}
+    public static int idiv_by_small_0(int x) {return x / 3;}
+    public static int idiv_by_small_1(int x) {return x / 5;}
+    public static int idiv_by_small_2(int x) {return x / 6;}
+    public static int idiv_by_small_3(int x) {return x / 7;}
+    public static int idiv_by_small_4(int x) {return x / 9;}
+    public static int idiv_by_small_5(int x) {return x / 10;}
+    public static int idiv_by_small_6(int x) {return x / 11;}
+    public static int idiv_by_small_7(int x) {return x / 12;}
+    public static int idiv_by_small_8(int x) {return x / 13;}
+    public static int idiv_by_small_9(int x) {return x / 14;}
+    public static int idiv_by_small_10(int x) {return x / 15;}
+    public static int irem_by_pow2_0(int x) {return x % 1;}
+    public static int irem_by_pow2_1(int x) {return x % 2;}
+    public static int irem_by_pow2_2(int x) {return x % 4;}
+    public static int irem_by_pow2_3(int x) {return x % 8;}
+    public static int irem_by_pow2_4(int x) {return x % 16;}
+    public static int irem_by_pow2_5(int x) {return x % 32;}
+    public static int irem_by_pow2_6(int x) {return x % 64;}
+    public static int irem_by_pow2_7(int x) {return x % 128;}
+    public static int irem_by_pow2_8(int x) {return x % 256;}
+    public static int irem_by_pow2_9(int x) {return x % 512;}
+    public static int irem_by_pow2_10(int x) {return x % 1024;}
+    public static int irem_by_pow2_11(int x) {return x % 2048;}
+    public static int irem_by_pow2_12(int x) {return x % 4096;}
+    public static int irem_by_pow2_13(int x) {return x % 8192;}
+    public static int irem_by_pow2_14(int x) {return x % 16384;}
+    public static int irem_by_pow2_15(int x) {return x % 32768;}
+    public static int irem_by_pow2_16(int x) {return x % 65536;}
+    public static int irem_by_pow2_17(int x) {return x % 131072;}
+    public static int irem_by_pow2_18(int x) {return x % 262144;}
+    public static int irem_by_pow2_19(int x) {return x % 524288;}
+    public static int irem_by_pow2_20(int x) {return x % 1048576;}
+    public static int irem_by_pow2_21(int x) {return x % 2097152;}
+    public static int irem_by_pow2_22(int x) {return x % 4194304;}
+    public static int irem_by_pow2_23(int x) {return x % 8388608;}
+    public static int irem_by_pow2_24(int x) {return x % 16777216;}
+    public static int irem_by_pow2_25(int x) {return x % 33554432;}
+    public static int irem_by_pow2_26(int x) {return x % 67108864;}
+    public static int irem_by_pow2_27(int x) {return x % 134217728;}
+    public static int irem_by_pow2_28(int x) {return x % 268435456;}
+    public static int irem_by_pow2_29(int x) {return x % 536870912;}
+    public static int irem_by_pow2_30(int x) {return x % 1073741824;}
+    public static long ldiv_by_pow2_0(long x) {return x / 1l;}
+    public static long ldiv_by_pow2_1(long x) {return x / 2l;}
+    public static long ldiv_by_pow2_2(long x) {return x / 4l;}
+    public static long ldiv_by_pow2_3(long x) {return x / 8l;}
+    public static long ldiv_by_pow2_4(long x) {return x / 16l;}
+    public static long ldiv_by_pow2_5(long x) {return x / 32l;}
+    public static long ldiv_by_pow2_6(long x) {return x / 64l;}
+    public static long ldiv_by_pow2_7(long x) {return x / 128l;}
+    public static long ldiv_by_pow2_8(long x) {return x / 256l;}
+    public static long ldiv_by_pow2_9(long x) {return x / 512l;}
+    public static long ldiv_by_pow2_10(long x) {return x / 1024l;}
+    public static long ldiv_by_pow2_11(long x) {return x / 2048l;}
+    public static long ldiv_by_pow2_12(long x) {return x / 4096l;}
+    public static long ldiv_by_pow2_13(long x) {return x / 8192l;}
+    public static long ldiv_by_pow2_14(long x) {return x / 16384l;}
+    public static long ldiv_by_pow2_15(long x) {return x / 32768l;}
+    public static long ldiv_by_pow2_16(long x) {return x / 65536l;}
+    public static long ldiv_by_pow2_17(long x) {return x / 131072l;}
+    public static long ldiv_by_pow2_18(long x) {return x / 262144l;}
+    public static long ldiv_by_pow2_19(long x) {return x / 524288l;}
+    public static long ldiv_by_pow2_20(long x) {return x / 1048576l;}
+    public static long ldiv_by_pow2_21(long x) {return x / 2097152l;}
+    public static long ldiv_by_pow2_22(long x) {return x / 4194304l;}
+    public static long ldiv_by_pow2_23(long x) {return x / 8388608l;}
+    public static long ldiv_by_pow2_24(long x) {return x / 16777216l;}
+    public static long ldiv_by_pow2_25(long x) {return x / 33554432l;}
+    public static long ldiv_by_pow2_26(long x) {return x / 67108864l;}
+    public static long ldiv_by_pow2_27(long x) {return x / 134217728l;}
+    public static long ldiv_by_pow2_28(long x) {return x / 268435456l;}
+    public static long ldiv_by_pow2_29(long x) {return x / 536870912l;}
+    public static long ldiv_by_pow2_30(long x) {return x / 1073741824l;}
+    public static long ldiv_by_pow2_31(long x) {return x / 2147483648l;}
+    public static long ldiv_by_pow2_32(long x) {return x / 4294967296l;}
+    public static long ldiv_by_pow2_33(long x) {return x / 8589934592l;}
+    public static long ldiv_by_pow2_34(long x) {return x / 17179869184l;}
+    public static long ldiv_by_pow2_35(long x) {return x / 34359738368l;}
+    public static long ldiv_by_pow2_36(long x) {return x / 68719476736l;}
+    public static long ldiv_by_pow2_37(long x) {return x / 137438953472l;}
+    public static long ldiv_by_pow2_38(long x) {return x / 274877906944l;}
+    public static long ldiv_by_pow2_39(long x) {return x / 549755813888l;}
+    public static long ldiv_by_pow2_40(long x) {return x / 1099511627776l;}
+    public static long ldiv_by_pow2_41(long x) {return x / 2199023255552l;}
+    public static long ldiv_by_pow2_42(long x) {return x / 4398046511104l;}
+    public static long ldiv_by_pow2_43(long x) {return x / 8796093022208l;}
+    public static long ldiv_by_pow2_44(long x) {return x / 17592186044416l;}
+    public static long ldiv_by_pow2_45(long x) {return x / 35184372088832l;}
+    public static long ldiv_by_pow2_46(long x) {return x / 70368744177664l;}
+    public static long ldiv_by_pow2_47(long x) {return x / 140737488355328l;}
+    public static long ldiv_by_pow2_48(long x) {return x / 281474976710656l;}
+    public static long ldiv_by_pow2_49(long x) {return x / 562949953421312l;}
+    public static long ldiv_by_pow2_50(long x) {return x / 1125899906842624l;}
+    public static long ldiv_by_pow2_51(long x) {return x / 2251799813685248l;}
+    public static long ldiv_by_pow2_52(long x) {return x / 4503599627370496l;}
+    public static long ldiv_by_pow2_53(long x) {return x / 9007199254740992l;}
+    public static long ldiv_by_pow2_54(long x) {return x / 18014398509481984l;}
+    public static long ldiv_by_pow2_55(long x) {return x / 36028797018963968l;}
+    public static long ldiv_by_pow2_56(long x) {return x / 72057594037927936l;}
+    public static long ldiv_by_pow2_57(long x) {return x / 144115188075855872l;}
+    public static long ldiv_by_pow2_58(long x) {return x / 288230376151711744l;}
+    public static long ldiv_by_pow2_59(long x) {return x / 576460752303423488l;}
+    public static long ldiv_by_pow2_60(long x) {return x / 1152921504606846976l;}
+    public static long ldiv_by_pow2_61(long x) {return x / 2305843009213693952l;}
+    public static long ldiv_by_pow2_62(long x) {return x / 4611686018427387904l;}
+    public static long ldiv_by_small_0(long x) {return x / 3l;}
+    public static long ldiv_by_small_1(long x) {return x / 5l;}
+    public static long ldiv_by_small_2(long x) {return x / 6l;}
+    public static long ldiv_by_small_3(long x) {return x / 7l;}
+    public static long ldiv_by_small_4(long x) {return x / 9l;}
+    public static long ldiv_by_small_5(long x) {return x / 10l;}
+    public static long ldiv_by_small_6(long x) {return x / 11l;}
+    public static long ldiv_by_small_7(long x) {return x / 12l;}
+    public static long ldiv_by_small_8(long x) {return x / 13l;}
+    public static long ldiv_by_small_9(long x) {return x / 14l;}
+    public static long ldiv_by_small_10(long x) {return x / 15l;}
+    public static long lrem_by_pow2_0(long x) {return x % 1l;}
+    public static long lrem_by_pow2_1(long x) {return x % 2l;}
+    public static long lrem_by_pow2_2(long x) {return x % 4l;}
+    public static long lrem_by_pow2_3(long x) {return x % 8l;}
+    public static long lrem_by_pow2_4(long x) {return x % 16l;}
+    public static long lrem_by_pow2_5(long x) {return x % 32l;}
+    public static long lrem_by_pow2_6(long x) {return x % 64l;}
+    public static long lrem_by_pow2_7(long x) {return x % 128l;}
+    public static long lrem_by_pow2_8(long x) {return x % 256l;}
+    public static long lrem_by_pow2_9(long x) {return x % 512l;}
+    public static long lrem_by_pow2_10(long x) {return x % 1024l;}
+    public static long lrem_by_pow2_11(long x) {return x % 2048l;}
+    public static long lrem_by_pow2_12(long x) {return x % 4096l;}
+    public static long lrem_by_pow2_13(long x) {return x % 8192l;}
+    public static long lrem_by_pow2_14(long x) {return x % 16384l;}
+    public static long lrem_by_pow2_15(long x) {return x % 32768l;}
+    public static long lrem_by_pow2_16(long x) {return x % 65536l;}
+    public static long lrem_by_pow2_17(long x) {return x % 131072l;}
+    public static long lrem_by_pow2_18(long x) {return x % 262144l;}
+    public static long lrem_by_pow2_19(long x) {return x % 524288l;}
+    public static long lrem_by_pow2_20(long x) {return x % 1048576l;}
+    public static long lrem_by_pow2_21(long x) {return x % 2097152l;}
+    public static long lrem_by_pow2_22(long x) {return x % 4194304l;}
+    public static long lrem_by_pow2_23(long x) {return x % 8388608l;}
+    public static long lrem_by_pow2_24(long x) {return x % 16777216l;}
+    public static long lrem_by_pow2_25(long x) {return x % 33554432l;}
+    public static long lrem_by_pow2_26(long x) {return x % 67108864l;}
+    public static long lrem_by_pow2_27(long x) {return x % 134217728l;}
+    public static long lrem_by_pow2_28(long x) {return x % 268435456l;}
+    public static long lrem_by_pow2_29(long x) {return x % 536870912l;}
+    public static long lrem_by_pow2_30(long x) {return x % 1073741824l;}
+    public static long lrem_by_pow2_31(long x) {return x % 2147483648l;}
+    public static long lrem_by_pow2_32(long x) {return x % 4294967296l;}
+    public static long lrem_by_pow2_33(long x) {return x % 8589934592l;}
+    public static long lrem_by_pow2_34(long x) {return x % 17179869184l;}
+    public static long lrem_by_pow2_35(long x) {return x % 34359738368l;}
+    public static long lrem_by_pow2_36(long x) {return x % 68719476736l;}
+    public static long lrem_by_pow2_37(long x) {return x % 137438953472l;}
+    public static long lrem_by_pow2_38(long x) {return x % 274877906944l;}
+    public static long lrem_by_pow2_39(long x) {return x % 549755813888l;}
+    public static long lrem_by_pow2_40(long x) {return x % 1099511627776l;}
+    public static long lrem_by_pow2_41(long x) {return x % 2199023255552l;}
+    public static long lrem_by_pow2_42(long x) {return x % 4398046511104l;}
+    public static long lrem_by_pow2_43(long x) {return x % 8796093022208l;}
+    public static long lrem_by_pow2_44(long x) {return x % 17592186044416l;}
+    public static long lrem_by_pow2_45(long x) {return x % 35184372088832l;}
+    public static long lrem_by_pow2_46(long x) {return x % 70368744177664l;}
+    public static long lrem_by_pow2_47(long x) {return x % 140737488355328l;}
+    public static long lrem_by_pow2_48(long x) {return x % 281474976710656l;}
+    public static long lrem_by_pow2_49(long x) {return x % 562949953421312l;}
+    public static long lrem_by_pow2_50(long x) {return x % 1125899906842624l;}
+    public static long lrem_by_pow2_51(long x) {return x % 2251799813685248l;}
+    public static long lrem_by_pow2_52(long x) {return x % 4503599627370496l;}
+    public static long lrem_by_pow2_53(long x) {return x % 9007199254740992l;}
+    public static long lrem_by_pow2_54(long x) {return x % 18014398509481984l;}
+    public static long lrem_by_pow2_55(long x) {return x % 36028797018963968l;}
+    public static long lrem_by_pow2_56(long x) {return x % 72057594037927936l;}
+    public static long lrem_by_pow2_57(long x) {return x % 144115188075855872l;}
+    public static long lrem_by_pow2_58(long x) {return x % 288230376151711744l;}
+    public static long lrem_by_pow2_59(long x) {return x % 576460752303423488l;}
+    public static long lrem_by_pow2_60(long x) {return x % 1152921504606846976l;}
+    public static long lrem_by_pow2_61(long x) {return x % 2305843009213693952l;}
+    public static long lrem_by_pow2_62(long x) {return x % 4611686018427387904l;}
+
+    public static void intCheckAll(int x) {
+        intCheckDiv("idiv_by_pow2_0", idiv_by_pow2_0(x), x, 1);
+        intCheckDiv("idiv_by_pow2_1", idiv_by_pow2_1(x), x, 2);
+        intCheckDiv("idiv_by_pow2_2", idiv_by_pow2_2(x), x, 4);
+        intCheckDiv("idiv_by_pow2_3", idiv_by_pow2_3(x), x, 8);
+        intCheckDiv("idiv_by_pow2_4", idiv_by_pow2_4(x), x, 16);
+        intCheckDiv("idiv_by_pow2_5", idiv_by_pow2_5(x), x, 32);
+        intCheckDiv("idiv_by_pow2_6", idiv_by_pow2_6(x), x, 64);
+        intCheckDiv("idiv_by_pow2_7", idiv_by_pow2_7(x), x, 128);
+        intCheckDiv("idiv_by_pow2_8", idiv_by_pow2_8(x), x, 256);
+        intCheckDiv("idiv_by_pow2_9", idiv_by_pow2_9(x), x, 512);
+        intCheckDiv("idiv_by_pow2_10", idiv_by_pow2_10(x), x, 1024);
+        intCheckDiv("idiv_by_pow2_11", idiv_by_pow2_11(x), x, 2048);
+        intCheckDiv("idiv_by_pow2_12", idiv_by_pow2_12(x), x, 4096);
+        intCheckDiv("idiv_by_pow2_13", idiv_by_pow2_13(x), x, 8192);
+        intCheckDiv("idiv_by_pow2_14", idiv_by_pow2_14(x), x, 16384);
+        intCheckDiv("idiv_by_pow2_15", idiv_by_pow2_15(x), x, 32768);
+        intCheckDiv("idiv_by_pow2_16", idiv_by_pow2_16(x), x, 65536);
+        intCheckDiv("idiv_by_pow2_17", idiv_by_pow2_17(x), x, 131072);
+        intCheckDiv("idiv_by_pow2_18", idiv_by_pow2_18(x), x, 262144);
+        intCheckDiv("idiv_by_pow2_19", idiv_by_pow2_19(x), x, 524288);
+        intCheckDiv("idiv_by_pow2_20", idiv_by_pow2_20(x), x, 1048576);
+        intCheckDiv("idiv_by_pow2_21", idiv_by_pow2_21(x), x, 2097152);
+        intCheckDiv("idiv_by_pow2_22", idiv_by_pow2_22(x), x, 4194304);
+        intCheckDiv("idiv_by_pow2_23", idiv_by_pow2_23(x), x, 8388608);
+        intCheckDiv("idiv_by_pow2_24", idiv_by_pow2_24(x), x, 16777216);
+        intCheckDiv("idiv_by_pow2_25", idiv_by_pow2_25(x), x, 33554432);
+        intCheckDiv("idiv_by_pow2_26", idiv_by_pow2_26(x), x, 67108864);
+        intCheckDiv("idiv_by_pow2_27", idiv_by_pow2_27(x), x, 134217728);
+        intCheckDiv("idiv_by_pow2_28", idiv_by_pow2_28(x), x, 268435456);
+        intCheckDiv("idiv_by_pow2_29", idiv_by_pow2_29(x), x, 536870912);
+        intCheckDiv("idiv_by_pow2_30", idiv_by_pow2_30(x), x, 1073741824);
+        intCheckDiv("idiv_by_small_0", idiv_by_small_0(x), x, 3);
+        intCheckDiv("idiv_by_small_1", idiv_by_small_1(x), x, 5);
+        intCheckDiv("idiv_by_small_2", idiv_by_small_2(x), x, 6);
+        intCheckDiv("idiv_by_small_3", idiv_by_small_3(x), x, 7);
+        intCheckDiv("idiv_by_small_4", idiv_by_small_4(x), x, 9);
+        intCheckDiv("idiv_by_small_5", idiv_by_small_5(x), x, 10);
+        intCheckDiv("idiv_by_small_6", idiv_by_small_6(x), x, 11);
+        intCheckDiv("idiv_by_small_7", idiv_by_small_7(x), x, 12);
+        intCheckDiv("idiv_by_small_8", idiv_by_small_8(x), x, 13);
+        intCheckDiv("idiv_by_small_9", idiv_by_small_9(x), x, 14);
+        intCheckDiv("idiv_by_small_10", idiv_by_small_10(x), x, 15);
+        intCheckRem("irem_by_pow2_0", irem_by_pow2_0(x), x, 1);
+        intCheckRem("irem_by_pow2_1", irem_by_pow2_1(x), x, 2);
+        intCheckRem("irem_by_pow2_2", irem_by_pow2_2(x), x, 4);
+        intCheckRem("irem_by_pow2_3", irem_by_pow2_3(x), x, 8);
+        intCheckRem("irem_by_pow2_4", irem_by_pow2_4(x), x, 16);
+        intCheckRem("irem_by_pow2_5", irem_by_pow2_5(x), x, 32);
+        intCheckRem("irem_by_pow2_6", irem_by_pow2_6(x), x, 64);
+        intCheckRem("irem_by_pow2_7", irem_by_pow2_7(x), x, 128);
+        intCheckRem("irem_by_pow2_8", irem_by_pow2_8(x), x, 256);
+        intCheckRem("irem_by_pow2_9", irem_by_pow2_9(x), x, 512);
+        intCheckRem("irem_by_pow2_10", irem_by_pow2_10(x), x, 1024);
+        intCheckRem("irem_by_pow2_11", irem_by_pow2_11(x), x, 2048);
+        intCheckRem("irem_by_pow2_12", irem_by_pow2_12(x), x, 4096);
+        intCheckRem("irem_by_pow2_13", irem_by_pow2_13(x), x, 8192);
+        intCheckRem("irem_by_pow2_14", irem_by_pow2_14(x), x, 16384);
+        intCheckRem("irem_by_pow2_15", irem_by_pow2_15(x), x, 32768);
+        intCheckRem("irem_by_pow2_16", irem_by_pow2_16(x), x, 65536);
+        intCheckRem("irem_by_pow2_17", irem_by_pow2_17(x), x, 131072);
+        intCheckRem("irem_by_pow2_18", irem_by_pow2_18(x), x, 262144);
+        intCheckRem("irem_by_pow2_19", irem_by_pow2_19(x), x, 524288);
+        intCheckRem("irem_by_pow2_20", irem_by_pow2_20(x), x, 1048576);
+        intCheckRem("irem_by_pow2_21", irem_by_pow2_21(x), x, 2097152);
+        intCheckRem("irem_by_pow2_22", irem_by_pow2_22(x), x, 4194304);
+        intCheckRem("irem_by_pow2_23", irem_by_pow2_23(x), x, 8388608);
+        intCheckRem("irem_by_pow2_24", irem_by_pow2_24(x), x, 16777216);
+        intCheckRem("irem_by_pow2_25", irem_by_pow2_25(x), x, 33554432);
+        intCheckRem("irem_by_pow2_26", irem_by_pow2_26(x), x, 67108864);
+        intCheckRem("irem_by_pow2_27", irem_by_pow2_27(x), x, 134217728);
+        intCheckRem("irem_by_pow2_28", irem_by_pow2_28(x), x, 268435456);
+        intCheckRem("irem_by_pow2_29", irem_by_pow2_29(x), x, 536870912);
+        intCheckRem("irem_by_pow2_30", irem_by_pow2_30(x), x, 1073741824);
+    }
+
+    public static void longCheckAll(long x) {
+        longCheckDiv("ldiv_by_pow2_0", ldiv_by_pow2_0(x), x, 1l);
+        longCheckDiv("ldiv_by_pow2_1", ldiv_by_pow2_1(x), x, 2l);
+        longCheckDiv("ldiv_by_pow2_2", ldiv_by_pow2_2(x), x, 4l);
+        longCheckDiv("ldiv_by_pow2_3", ldiv_by_pow2_3(x), x, 8l);
+        longCheckDiv("ldiv_by_pow2_4", ldiv_by_pow2_4(x), x, 16l);
+        longCheckDiv("ldiv_by_pow2_5", ldiv_by_pow2_5(x), x, 32l);
+        longCheckDiv("ldiv_by_pow2_6", ldiv_by_pow2_6(x), x, 64l);
+        longCheckDiv("ldiv_by_pow2_7", ldiv_by_pow2_7(x), x, 128l);
+        longCheckDiv("ldiv_by_pow2_8", ldiv_by_pow2_8(x), x, 256l);
+        longCheckDiv("ldiv_by_pow2_9", ldiv_by_pow2_9(x), x, 512l);
+        longCheckDiv("ldiv_by_pow2_10", ldiv_by_pow2_10(x), x, 1024l);
+        longCheckDiv("ldiv_by_pow2_11", ldiv_by_pow2_11(x), x, 2048l);
+        longCheckDiv("ldiv_by_pow2_12", ldiv_by_pow2_12(x), x, 4096l);
+        longCheckDiv("ldiv_by_pow2_13", ldiv_by_pow2_13(x), x, 8192l);
+        longCheckDiv("ldiv_by_pow2_14", ldiv_by_pow2_14(x), x, 16384l);
+        longCheckDiv("ldiv_by_pow2_15", ldiv_by_pow2_15(x), x, 32768l);
+        longCheckDiv("ldiv_by_pow2_16", ldiv_by_pow2_16(x), x, 65536l);
+        longCheckDiv("ldiv_by_pow2_17", ldiv_by_pow2_17(x), x, 131072l);
+        longCheckDiv("ldiv_by_pow2_18", ldiv_by_pow2_18(x), x, 262144l);
+        longCheckDiv("ldiv_by_pow2_19", ldiv_by_pow2_19(x), x, 524288l);
+        longCheckDiv("ldiv_by_pow2_20", ldiv_by_pow2_20(x), x, 1048576l);
+        longCheckDiv("ldiv_by_pow2_21", ldiv_by_pow2_21(x), x, 2097152l);
+        longCheckDiv("ldiv_by_pow2_22", ldiv_by_pow2_22(x), x, 4194304l);
+        longCheckDiv("ldiv_by_pow2_23", ldiv_by_pow2_23(x), x, 8388608l);
+        longCheckDiv("ldiv_by_pow2_24", ldiv_by_pow2_24(x), x, 16777216l);
+        longCheckDiv("ldiv_by_pow2_25", ldiv_by_pow2_25(x), x, 33554432l);
+        longCheckDiv("ldiv_by_pow2_26", ldiv_by_pow2_26(x), x, 67108864l);
+        longCheckDiv("ldiv_by_pow2_27", ldiv_by_pow2_27(x), x, 134217728l);
+        longCheckDiv("ldiv_by_pow2_28", ldiv_by_pow2_28(x), x, 268435456l);
+        longCheckDiv("ldiv_by_pow2_29", ldiv_by_pow2_29(x), x, 536870912l);
+        longCheckDiv("ldiv_by_pow2_30", ldiv_by_pow2_30(x), x, 1073741824l);
+        longCheckDiv("ldiv_by_pow2_31", ldiv_by_pow2_31(x), x, 2147483648l);
+        longCheckDiv("ldiv_by_pow2_32", ldiv_by_pow2_32(x), x, 4294967296l);
+        longCheckDiv("ldiv_by_pow2_33", ldiv_by_pow2_33(x), x, 8589934592l);
+        longCheckDiv("ldiv_by_pow2_34", ldiv_by_pow2_34(x), x, 17179869184l);
+        longCheckDiv("ldiv_by_pow2_35", ldiv_by_pow2_35(x), x, 34359738368l);
+        longCheckDiv("ldiv_by_pow2_36", ldiv_by_pow2_36(x), x, 68719476736l);
+        longCheckDiv("ldiv_by_pow2_37", ldiv_by_pow2_37(x), x, 137438953472l);
+        longCheckDiv("ldiv_by_pow2_38", ldiv_by_pow2_38(x), x, 274877906944l);
+        longCheckDiv("ldiv_by_pow2_39", ldiv_by_pow2_39(x), x, 549755813888l);
+        longCheckDiv("ldiv_by_pow2_40", ldiv_by_pow2_40(x), x, 1099511627776l);
+        longCheckDiv("ldiv_by_pow2_41", ldiv_by_pow2_41(x), x, 2199023255552l);
+        longCheckDiv("ldiv_by_pow2_42", ldiv_by_pow2_42(x), x, 4398046511104l);
+        longCheckDiv("ldiv_by_pow2_43", ldiv_by_pow2_43(x), x, 8796093022208l);
+        longCheckDiv("ldiv_by_pow2_44", ldiv_by_pow2_44(x), x, 17592186044416l);
+        longCheckDiv("ldiv_by_pow2_45", ldiv_by_pow2_45(x), x, 35184372088832l);
+        longCheckDiv("ldiv_by_pow2_46", ldiv_by_pow2_46(x), x, 70368744177664l);
+        longCheckDiv("ldiv_by_pow2_47", ldiv_by_pow2_47(x), x, 140737488355328l);
+        longCheckDiv("ldiv_by_pow2_48", ldiv_by_pow2_48(x), x, 281474976710656l);
+        longCheckDiv("ldiv_by_pow2_49", ldiv_by_pow2_49(x), x, 562949953421312l);
+        longCheckDiv("ldiv_by_pow2_50", ldiv_by_pow2_50(x), x, 1125899906842624l);
+        longCheckDiv("ldiv_by_pow2_51", ldiv_by_pow2_51(x), x, 2251799813685248l);
+        longCheckDiv("ldiv_by_pow2_52", ldiv_by_pow2_52(x), x, 4503599627370496l);
+        longCheckDiv("ldiv_by_pow2_53", ldiv_by_pow2_53(x), x, 9007199254740992l);
+        longCheckDiv("ldiv_by_pow2_54", ldiv_by_pow2_54(x), x, 18014398509481984l);
+        longCheckDiv("ldiv_by_pow2_55", ldiv_by_pow2_55(x), x, 36028797018963968l);
+        longCheckDiv("ldiv_by_pow2_56", ldiv_by_pow2_56(x), x, 72057594037927936l);
+        longCheckDiv("ldiv_by_pow2_57", ldiv_by_pow2_57(x), x, 144115188075855872l);
+        longCheckDiv("ldiv_by_pow2_58", ldiv_by_pow2_58(x), x, 288230376151711744l);
+        longCheckDiv("ldiv_by_pow2_59", ldiv_by_pow2_59(x), x, 576460752303423488l);
+        longCheckDiv("ldiv_by_pow2_60", ldiv_by_pow2_60(x), x, 1152921504606846976l);
+        longCheckDiv("ldiv_by_pow2_61", ldiv_by_pow2_61(x), x, 2305843009213693952l);
+        longCheckDiv("ldiv_by_pow2_62", ldiv_by_pow2_62(x), x, 4611686018427387904l);
+        longCheckDiv("ldiv_by_small_0", ldiv_by_small_0(x), x, 3l);
+        longCheckDiv("ldiv_by_small_1", ldiv_by_small_1(x), x, 5l);
+        longCheckDiv("ldiv_by_small_2", ldiv_by_small_2(x), x, 6l);
+        longCheckDiv("ldiv_by_small_3", ldiv_by_small_3(x), x, 7l);
+        longCheckDiv("ldiv_by_small_4", ldiv_by_small_4(x), x, 9l);
+        longCheckDiv("ldiv_by_small_5", ldiv_by_small_5(x), x, 10l);
+        longCheckDiv("ldiv_by_small_6", ldiv_by_small_6(x), x, 11l);
+        longCheckDiv("ldiv_by_small_7", ldiv_by_small_7(x), x, 12l);
+        longCheckDiv("ldiv_by_small_8", ldiv_by_small_8(x), x, 13l);
+        longCheckDiv("ldiv_by_small_9", ldiv_by_small_9(x), x, 14l);
+        longCheckDiv("ldiv_by_small_10", ldiv_by_small_10(x), x, 15l);
+        longCheckRem("lrem_by_pow2_0", lrem_by_pow2_0(x), x, 1l);
+        longCheckRem("lrem_by_pow2_1", lrem_by_pow2_1(x), x, 2l);
+        longCheckRem("lrem_by_pow2_2", lrem_by_pow2_2(x), x, 4l);
+        longCheckRem("lrem_by_pow2_3", lrem_by_pow2_3(x), x, 8l);
+        longCheckRem("lrem_by_pow2_4", lrem_by_pow2_4(x), x, 16l);
+        longCheckRem("lrem_by_pow2_5", lrem_by_pow2_5(x), x, 32l);
+        longCheckRem("lrem_by_pow2_6", lrem_by_pow2_6(x), x, 64l);
+        longCheckRem("lrem_by_pow2_7", lrem_by_pow2_7(x), x, 128l);
+        longCheckRem("lrem_by_pow2_8", lrem_by_pow2_8(x), x, 256l);
+        longCheckRem("lrem_by_pow2_9", lrem_by_pow2_9(x), x, 512l);
+        longCheckRem("lrem_by_pow2_10", lrem_by_pow2_10(x), x, 1024l);
+        longCheckRem("lrem_by_pow2_11", lrem_by_pow2_11(x), x, 2048l);
+        longCheckRem("lrem_by_pow2_12", lrem_by_pow2_12(x), x, 4096l);
+        longCheckRem("lrem_by_pow2_13", lrem_by_pow2_13(x), x, 8192l);
+        longCheckRem("lrem_by_pow2_14", lrem_by_pow2_14(x), x, 16384l);
+        longCheckRem("lrem_by_pow2_15", lrem_by_pow2_15(x), x, 32768l);
+        longCheckRem("lrem_by_pow2_16", lrem_by_pow2_16(x), x, 65536l);
+        longCheckRem("lrem_by_pow2_17", lrem_by_pow2_17(x), x, 131072l);
+        longCheckRem("lrem_by_pow2_18", lrem_by_pow2_18(x), x, 262144l);
+        longCheckRem("lrem_by_pow2_19", lrem_by_pow2_19(x), x, 524288l);
+        longCheckRem("lrem_by_pow2_20", lrem_by_pow2_20(x), x, 1048576l);
+        longCheckRem("lrem_by_pow2_21", lrem_by_pow2_21(x), x, 2097152l);
+        longCheckRem("lrem_by_pow2_22", lrem_by_pow2_22(x), x, 4194304l);
+        longCheckRem("lrem_by_pow2_23", lrem_by_pow2_23(x), x, 8388608l);
+        longCheckRem("lrem_by_pow2_24", lrem_by_pow2_24(x), x, 16777216l);
+        longCheckRem("lrem_by_pow2_25", lrem_by_pow2_25(x), x, 33554432l);
+        longCheckRem("lrem_by_pow2_26", lrem_by_pow2_26(x), x, 67108864l);
+        longCheckRem("lrem_by_pow2_27", lrem_by_pow2_27(x), x, 134217728l);
+        longCheckRem("lrem_by_pow2_28", lrem_by_pow2_28(x), x, 268435456l);
+        longCheckRem("lrem_by_pow2_29", lrem_by_pow2_29(x), x, 536870912l);
+        longCheckRem("lrem_by_pow2_30", lrem_by_pow2_30(x), x, 1073741824l);
+        longCheckRem("lrem_by_pow2_31", lrem_by_pow2_31(x), x, 2147483648l);
+        longCheckRem("lrem_by_pow2_32", lrem_by_pow2_32(x), x, 4294967296l);
+        longCheckRem("lrem_by_pow2_33", lrem_by_pow2_33(x), x, 8589934592l);
+        longCheckRem("lrem_by_pow2_34", lrem_by_pow2_34(x), x, 17179869184l);
+        longCheckRem("lrem_by_pow2_35", lrem_by_pow2_35(x), x, 34359738368l);
+        longCheckRem("lrem_by_pow2_36", lrem_by_pow2_36(x), x, 68719476736l);
+        longCheckRem("lrem_by_pow2_37", lrem_by_pow2_37(x), x, 137438953472l);
+        longCheckRem("lrem_by_pow2_38", lrem_by_pow2_38(x), x, 274877906944l);
+        longCheckRem("lrem_by_pow2_39", lrem_by_pow2_39(x), x, 549755813888l);
+        longCheckRem("lrem_by_pow2_40", lrem_by_pow2_40(x), x, 1099511627776l);
+        longCheckRem("lrem_by_pow2_41", lrem_by_pow2_41(x), x, 2199023255552l);
+        longCheckRem("lrem_by_pow2_42", lrem_by_pow2_42(x), x, 4398046511104l);
+        longCheckRem("lrem_by_pow2_43", lrem_by_pow2_43(x), x, 8796093022208l);
+        longCheckRem("lrem_by_pow2_44", lrem_by_pow2_44(x), x, 17592186044416l);
+        longCheckRem("lrem_by_pow2_45", lrem_by_pow2_45(x), x, 35184372088832l);
+        longCheckRem("lrem_by_pow2_46", lrem_by_pow2_46(x), x, 70368744177664l);
+        longCheckRem("lrem_by_pow2_47", lrem_by_pow2_47(x), x, 140737488355328l);
+        longCheckRem("lrem_by_pow2_48", lrem_by_pow2_48(x), x, 281474976710656l);
+        longCheckRem("lrem_by_pow2_49", lrem_by_pow2_49(x), x, 562949953421312l);
+        longCheckRem("lrem_by_pow2_50", lrem_by_pow2_50(x), x, 1125899906842624l);
+        longCheckRem("lrem_by_pow2_51", lrem_by_pow2_51(x), x, 2251799813685248l);
+        longCheckRem("lrem_by_pow2_52", lrem_by_pow2_52(x), x, 4503599627370496l);
+        longCheckRem("lrem_by_pow2_53", lrem_by_pow2_53(x), x, 9007199254740992l);
+        longCheckRem("lrem_by_pow2_54", lrem_by_pow2_54(x), x, 18014398509481984l);
+        longCheckRem("lrem_by_pow2_55", lrem_by_pow2_55(x), x, 36028797018963968l);
+        longCheckRem("lrem_by_pow2_56", lrem_by_pow2_56(x), x, 72057594037927936l);
+        longCheckRem("lrem_by_pow2_57", lrem_by_pow2_57(x), x, 144115188075855872l);
+        longCheckRem("lrem_by_pow2_58", lrem_by_pow2_58(x), x, 288230376151711744l);
+        longCheckRem("lrem_by_pow2_59", lrem_by_pow2_59(x), x, 576460752303423488l);
+        longCheckRem("lrem_by_pow2_60", lrem_by_pow2_60(x), x, 1152921504606846976l);
+        longCheckRem("lrem_by_pow2_61", lrem_by_pow2_61(x), x, 2305843009213693952l);
+        longCheckRem("lrem_by_pow2_62", lrem_by_pow2_62(x), x, 4611686018427387904l);
+    }
+
+    public static void main(String[] args) {
+      int i;
+      long l;
+
+      System.out.println("Begin");
+
+      System.out.println("Int: checking some equally spaced dividends...");
+      for (i = -1000; i < 1000; i += 300) {
+          intCheckAll(i);
+          intCheckAll(-i);
+      }
+
+      System.out.println("Int: checking small dividends...");
+      for (i = 1; i < 100; i += 1) {
+          intCheckAll(i);
+          intCheckAll(-i);
+      }
+
+      System.out.println("Int: checking big dividends...");
+      for (i = 0; i < 100; i += 1) {
+          intCheckAll(Integer.MAX_VALUE - i);
+          intCheckAll(Integer.MIN_VALUE + i);
+      }
+
+      System.out.println("Long: checking some equally spaced dividends...");
+      for (l = 0l; l < 1000000000000l; l += 300000000000l) {
+          longCheckAll(l);
+          longCheckAll(-l);
+      }
+
+      System.out.println("Long: checking small dividends...");
+      for (l = 1l; l < 100l; l += 1l) {
+          longCheckAll(l);
+          longCheckAll(-l);
+      }
+
+      System.out.println("Long: checking big dividends...");
+      for (l = 0l; l < 100l; l += 1l) {
+          longCheckAll(Long.MAX_VALUE - l);
+          longCheckAll(Long.MIN_VALUE + l);
+      }
+
+      System.out.println("End");
+    }
+}