Merge "Cortex-A53 Erratum 843419 workaround in OatWriter."
diff --git a/Android.mk b/Android.mk
index 216e865..9360355 100644
--- a/Android.mk
+++ b/Android.mk
@@ -42,27 +42,7 @@
 
 .PHONY: clean-oat-host
 clean-oat-host:
-	rm -f $(HOST_CORE_IMG_OUTS)
-	rm -f $(HOST_CORE_OAT_OUTS)
-	rm -f $(HOST_OUT_JAVA_LIBRARIES)/$(ART_HOST_ARCH)/*.odex
-ifneq ($(HOST_PREFER_32_BIT),true)
-	rm -f $(HOST_OUT_JAVA_LIBRARIES)/$(2ND_ART_HOST_ARCH)/*.odex
-endif
-	rm -f $(TARGET_CORE_IMG_OUTS)
-	rm -f $(TARGET_CORE_OAT_OUTS)
-	rm -rf $(DEXPREOPT_PRODUCT_DIR_FULL_PATH)
-	rm -f $(TARGET_OUT_UNSTRIPPED)/system/framework/*.odex
-	rm -f $(TARGET_OUT_UNSTRIPPED)/system/framework/*/*.oat
-	rm -f $(TARGET_OUT_UNSTRIPPED)/system/framework/*/*.art
-	rm -f $(TARGET_OUT)/framework/*/*.oat
-	rm -f $(TARGET_OUT)/framework/*/*.art
-	rm -f $(TARGET_OUT_APPS)/*.odex
-	rm -f $(TARGET_OUT_INTERMEDIATES)/JAVA_LIBRARIES/*_intermediates/javalib.odex
-	rm -f $(TARGET_OUT_INTERMEDIATES)/APPS/*_intermediates/*.odex
-ifdef TARGET_2ND_ARCH
-	rm -f $(2ND_TARGET_OUT_INTERMEDIATES)/JAVA_LIBRARIES/*_intermediates/javalib.odex
-	rm -f $(2ND_TARGET_OUT_INTERMEDIATES)/APPS/*_intermediates/*.odex
-endif
+	find $(OUT_DIR) -name "*.oat" -o -name "*.odex" -o -name "*.art" | xargs rm -f
 ifneq ($(TMPDIR),)
 	rm -rf $(TMPDIR)/$(USER)/test-*/dalvik-cache/*
 	rm -rf $(TMPDIR)/android-data/dalvik-cache/*
diff --git a/build/Android.gtest.mk b/build/Android.gtest.mk
index 91998fa..1a4c30c 100644
--- a/build/Android.gtest.mk
+++ b/build/Android.gtest.mk
@@ -60,7 +60,7 @@
 	$(call dexpreopt-remove-classes.dex,$@)
 
 # Dex file dependencies for each gtest.
-ART_GTEST_class_linker_test_DEX_DEPS := Interfaces MyClass Nested Statics StaticsFromCode
+ART_GTEST_class_linker_test_DEX_DEPS := Interfaces MultiDex MyClass Nested Statics StaticsFromCode
 ART_GTEST_compiler_driver_test_DEX_DEPS := AbstractMethod
 ART_GTEST_dex_file_test_DEX_DEPS := GetMethodSignature Main Nested
 ART_GTEST_exception_test_DEX_DEPS := ExceptionHandle
@@ -188,6 +188,7 @@
   compiler/dex/local_value_numbering_test.cc \
   compiler/dex/mir_graph_test.cc \
   compiler/dex/mir_optimization_test.cc \
+  compiler/dwarf/dwarf_test.cc \
   compiler/driver/compiler_driver_test.cc \
   compiler/elf_writer_test.cc \
   compiler/image_test.cc \
diff --git a/compiler/Android.mk b/compiler/Android.mk
index 0247c9d..904f117 100644
--- a/compiler/Android.mk
+++ b/compiler/Android.mk
@@ -48,12 +48,6 @@
 	dex/quick/mips/int_mips.cc \
 	dex/quick/mips/target_mips.cc \
 	dex/quick/mips/utility_mips.cc \
-	dex/quick/mips64/assemble_mips64.cc \
-	dex/quick/mips64/call_mips64.cc \
-	dex/quick/mips64/fp_mips64.cc \
-	dex/quick/mips64/int_mips64.cc \
-	dex/quick/mips64/target_mips64.cc \
-	dex/quick/mips64/utility_mips64.cc \
 	dex/quick/mir_to_lir.cc \
 	dex/quick/quick_compiler.cc \
 	dex/quick/ralloc_util.cc \
@@ -163,7 +157,6 @@
   dex/quick/arm/arm_lir.h \
   dex/quick/arm64/arm64_lir.h \
   dex/quick/mips/mips_lir.h \
-  dex/quick/mips64/mips64_lir.h \
   dex/quick/resource_mask.h \
   dex/compiler_enums.h \
   dex/global_value_numbering.h \
diff --git a/compiler/common_compiler_test.cc b/compiler/common_compiler_test.cc
index dab28bc..96d90bb 100644
--- a/compiler/common_compiler_test.cc
+++ b/compiler/common_compiler_test.cc
@@ -179,8 +179,8 @@
   verification_results_.reset(new VerificationResults(compiler_options_.get()));
   method_inliner_map_.reset(new DexFileToMethodInlinerMap);
   callbacks_.reset(new QuickCompilerCallbacks(verification_results_.get(),
-                                              method_inliner_map_.get()));
-  options->push_back(std::make_pair("compilercallbacks", callbacks_.get()));
+                                              method_inliner_map_.get(),
+                                              CompilerCallbacks::CallbackMode::kCompileApp));
 }
 
 void CommonCompilerTest::TearDown() {
diff --git a/compiler/common_compiler_test.h b/compiler/common_compiler_test.h
index 9cffbc8..d7b210d 100644
--- a/compiler/common_compiler_test.h
+++ b/compiler/common_compiler_test.h
@@ -78,7 +78,6 @@
   std::unique_ptr<CompilerOptions> compiler_options_;
   std::unique_ptr<VerificationResults> verification_results_;
   std::unique_ptr<DexFileToMethodInlinerMap> method_inliner_map_;
-  std::unique_ptr<CompilerCallbacks> callbacks_;
   std::unique_ptr<CompilerDriver> compiler_driver_;
   std::unique_ptr<CumulativeLogger> timer_;
   std::unique_ptr<const InstructionSetFeatures> instruction_set_features_;
diff --git a/compiler/dex/quick/mips/assemble_mips.cc b/compiler/dex/quick/mips/assemble_mips.cc
index ed72d67..936ff42 100644
--- a/compiler/dex/quick/mips/assemble_mips.cc
+++ b/compiler/dex/quick/mips/assemble_mips.cc
@@ -77,7 +77,7 @@
  *
  *  [!] escape.  To insert "!", use "!!"
  */
-/* NOTE: must be kept in sync with enum MipsOpcode from LIR.h */
+/* NOTE: must be kept in sync with enum MipsOpcode from mips_lir.h */
 /*
  * TUNING: We're currently punting on the branch delay slots.  All branch
  * instructions in this map are given a size of 8, which during assembly
@@ -85,6 +85,7 @@
  * an assembler pass to fill those slots when possible.
  */
 const MipsEncodingMap MipsMir2Lir::EncodingMap[kMipsLast] = {
+    // The following are common mips32r2, mips32r6 and mips64r6 instructions.
     ENCODING_MAP(kMips32BitData, 0x00000000,
                  kFmtBitBlt, 31, 0, kFmtUnused, -1, -1, kFmtUnused, -1, -1,
                  kFmtUnused, -1, -1, IS_UNARY_OP,
@@ -117,7 +118,7 @@
                  kFmtBitBlt, 25, 21, kFmtBitBlt, 20, 16, kFmtBitBlt, 15, 0,
                  kFmtUnused, -1, -1, IS_BINARY_OP | IS_BRANCH | REG_USE01 |
                  NEEDS_FIXUP, "beq", "!0r,!1r,!2t!0N", 8),
-    ENCODING_MAP(kMipsBeqz, 0x10000000, /* same as beq above with t = $zero */
+    ENCODING_MAP(kMipsBeqz, 0x10000000,  // Same as beq above with t = $zero.
                  kFmtBitBlt, 25, 21, kFmtBitBlt, 15, 0, kFmtUnused, -1, -1,
                  kFmtUnused, -1, -1, IS_UNARY_OP | IS_BRANCH | REG_USE0 |
                  NEEDS_FIXUP, "beqz", "!0r,!1t!0N", 8),
@@ -137,7 +138,7 @@
                  kFmtBitBlt, 25, 21, kFmtBitBlt, 15, 0, kFmtUnused, -1, -1,
                  kFmtUnused, -1, -1, IS_UNARY_OP | IS_BRANCH | REG_USE0 |
                  NEEDS_FIXUP, "bltz", "!0r,!1t!0N", 8),
-    ENCODING_MAP(kMipsBnez, 0x14000000, /* same as bne below with t = $zero */
+    ENCODING_MAP(kMipsBnez, 0x14000000,  // Same as bne below with t = $zero.
                  kFmtBitBlt, 25, 21, kFmtBitBlt, 15, 0, kFmtUnused, -1, -1,
                  kFmtUnused, -1, -1, IS_UNARY_OP | IS_BRANCH | REG_USE0 |
                  NEEDS_FIXUP, "bnez", "!0r,!1t!0N", 8),
@@ -145,14 +146,98 @@
                  kFmtBitBlt, 25, 21, kFmtBitBlt, 20, 16, kFmtBitBlt, 15, 0,
                  kFmtUnused, -1, -1, IS_BINARY_OP | IS_BRANCH | REG_USE01 |
                  NEEDS_FIXUP, "bne", "!0r,!1r,!2t!0N", 8),
-    ENCODING_MAP(kMipsDiv, 0x0000001a,
-                 kFmtBitBlt, 25, 21, kFmtBitBlt, 20, 16, kFmtUnused, -1, -1,
-                 kFmtUnused, -1, -1, IS_BINARY_OP | REG_DEF_HI | REG_DEF_LO | REG_USE01,
-                 "div", "!0r,!1r", 4),
     ENCODING_MAP(kMipsExt, 0x7c000000,
                  kFmtBitBlt, 20, 16, kFmtBitBlt, 25, 21, kFmtBitBlt, 10, 6,
                  kFmtBitBlt, 15, 11, IS_QUAD_OP | REG_DEF0 | REG_USE1,
                  "ext", "!0r,!1r,!2d,!3D", 4),
+    ENCODING_MAP(kMipsFaddd, 0x46200000,
+                 kFmtDfp, 10, 6, kFmtDfp, 15, 11, kFmtDfp, 20, 16,
+                 kFmtUnused, -1, -1, IS_TERTIARY_OP | REG_DEF0_USE12,
+                 "add.d", "!0S,!1S,!2S", 4),
+    ENCODING_MAP(kMipsFadds, 0x46000000,
+                 kFmtSfp, 10, 6, kFmtSfp, 15, 11, kFmtSfp, 20, 16,
+                 kFmtUnused, -1, -1, IS_TERTIARY_OP | REG_DEF0_USE12,
+                 "add.s", "!0s,!1s,!2s", 4),
+    ENCODING_MAP(kMipsFsubd, 0x46200001,
+                 kFmtDfp, 10, 6, kFmtDfp, 15, 11, kFmtDfp, 20, 16,
+                 kFmtUnused, -1, -1, IS_TERTIARY_OP | REG_DEF0_USE12,
+                 "sub.d", "!0S,!1S,!2S", 4),
+    ENCODING_MAP(kMipsFsubs, 0x46000001,
+                 kFmtSfp, 10, 6, kFmtSfp, 15, 11, kFmtSfp, 20, 16,
+                 kFmtUnused, -1, -1, IS_TERTIARY_OP | REG_DEF0_USE12,
+                 "sub.s", "!0s,!1s,!2s", 4),
+    ENCODING_MAP(kMipsFdivd, 0x46200003,
+                 kFmtDfp, 10, 6, kFmtDfp, 15, 11, kFmtDfp, 20, 16,
+                 kFmtUnused, -1, -1, IS_TERTIARY_OP | REG_DEF0_USE12,
+                 "div.d", "!0S,!1S,!2S", 4),
+    ENCODING_MAP(kMipsFdivs, 0x46000003,
+                 kFmtSfp, 10, 6, kFmtSfp, 15, 11, kFmtSfp, 20, 16,
+                 kFmtUnused, -1, -1, IS_TERTIARY_OP | REG_DEF0_USE12,
+                 "div.s", "!0s,!1s,!2s", 4),
+    ENCODING_MAP(kMipsFmuld, 0x46200002,
+                 kFmtDfp, 10, 6, kFmtDfp, 15, 11, kFmtDfp, 20, 16,
+                 kFmtUnused, -1, -1, IS_TERTIARY_OP | REG_DEF0_USE12,
+                 "mul.d", "!0S,!1S,!2S", 4),
+    ENCODING_MAP(kMipsFmuls, 0x46000002,
+                 kFmtSfp, 10, 6, kFmtSfp, 15, 11, kFmtSfp, 20, 16,
+                 kFmtUnused, -1, -1, IS_TERTIARY_OP | REG_DEF0_USE12,
+                 "mul.s", "!0s,!1s,!2s", 4),
+    ENCODING_MAP(kMipsFcvtsd, 0x46200020,
+                 kFmtSfp, 10, 6, kFmtDfp, 15, 11, kFmtUnused, -1, -1,
+                 kFmtUnused, -1, -1, IS_BINARY_OP | REG_DEF0_USE1,
+                 "cvt.s.d", "!0s,!1S", 4),
+    ENCODING_MAP(kMipsFcvtsw, 0x46800020,
+                 kFmtSfp, 10, 6, kFmtSfp, 15, 11, kFmtUnused, -1, -1,
+                 kFmtUnused, -1, -1, IS_BINARY_OP | REG_DEF0_USE1,
+                 "cvt.s.w", "!0s,!1s", 4),
+    ENCODING_MAP(kMipsFcvtds, 0x46000021,
+                 kFmtDfp, 10, 6, kFmtSfp, 15, 11, kFmtUnused, -1, -1,
+                 kFmtUnused, -1, -1, IS_BINARY_OP | REG_DEF0_USE1,
+                 "cvt.d.s", "!0S,!1s", 4),
+    ENCODING_MAP(kMipsFcvtdw, 0x46800021,
+                 kFmtDfp, 10, 6, kFmtSfp, 15, 11, kFmtUnused, -1, -1,
+                 kFmtUnused, -1, -1, IS_BINARY_OP | REG_DEF0_USE1,
+                 "cvt.d.w", "!0S,!1s", 4),
+    ENCODING_MAP(kMipsFcvtwd, 0x46200024,
+                 kFmtSfp, 10, 6, kFmtDfp, 15, 11, kFmtUnused, -1, -1,
+                 kFmtUnused, -1, -1, IS_BINARY_OP | REG_DEF0_USE1,
+                 "cvt.w.d", "!0s,!1S", 4),
+    ENCODING_MAP(kMipsFcvtws, 0x46000024,
+                 kFmtSfp, 10, 6, kFmtSfp, 15, 11, kFmtUnused, -1, -1,
+                 kFmtUnused, -1, -1, IS_BINARY_OP | REG_DEF0_USE1,
+                 "cvt.w.s", "!0s,!1s", 4),
+    ENCODING_MAP(kMipsFmovd, 0x46200006,
+                 kFmtDfp, 10, 6, kFmtDfp, 15, 11, kFmtUnused, -1, -1,
+                 kFmtUnused, -1, -1, IS_BINARY_OP | REG_DEF0_USE1,
+                 "mov.d", "!0S,!1S", 4),
+    ENCODING_MAP(kMipsFmovs, 0x46000006,
+                 kFmtSfp, 10, 6, kFmtSfp, 15, 11, kFmtUnused, -1, -1,
+                 kFmtUnused, -1, -1, IS_BINARY_OP | REG_DEF0_USE1,
+                 "mov.s", "!0s,!1s", 4),
+    ENCODING_MAP(kMipsFnegd, 0x46200007,
+                 kFmtDfp, 10, 6, kFmtDfp, 15, 11, kFmtUnused, -1, -1,
+                 kFmtUnused, -1, -1, IS_BINARY_OP | REG_DEF0_USE1,
+                 "neg.d", "!0S,!1S", 4),
+    ENCODING_MAP(kMipsFnegs, 0x46000007,
+                 kFmtSfp, 10, 6, kFmtSfp, 15, 11, kFmtUnused, -1, -1,
+                 kFmtUnused, -1, -1, IS_BINARY_OP | REG_DEF0_USE1,
+                 "neg.s", "!0s,!1s", 4),
+    ENCODING_MAP(kMipsFldc1, 0xd4000000,
+                 kFmtDfp, 20, 16, kFmtBitBlt, 15, 0, kFmtBitBlt, 25, 21,
+                 kFmtUnused, -1, -1, IS_TERTIARY_OP | REG_DEF0_USE2 | IS_LOAD,
+                 "ldc1", "!0S,!1d(!2r)", 4),
+    ENCODING_MAP(kMipsFlwc1, 0xc4000000,
+                 kFmtSfp, 20, 16, kFmtBitBlt, 15, 0, kFmtBitBlt, 25, 21,
+                 kFmtUnused, -1, -1, IS_TERTIARY_OP | REG_DEF0_USE2 | IS_LOAD,
+                 "lwc1", "!0s,!1d(!2r)", 4),
+    ENCODING_MAP(kMipsFsdc1, 0xf4000000,
+                 kFmtDfp, 20, 16, kFmtBitBlt, 15, 0, kFmtBitBlt, 25, 21,
+                 kFmtUnused, -1, -1, IS_TERTIARY_OP | REG_USE02 | IS_STORE,
+                 "sdc1", "!0S,!1d(!2r)", 4),
+    ENCODING_MAP(kMipsFswc1, 0xe4000000,
+                 kFmtSfp, 20, 16, kFmtBitBlt, 15, 0, kFmtBitBlt, 25, 21,
+                 kFmtUnused, -1, -1, IS_TERTIARY_OP | REG_USE02 | IS_STORE,
+                 "swc1", "!0s,!1d(!2r)", 4),
     ENCODING_MAP(kMipsJal, 0x0c000000,
                  kFmtBitBlt, 25, 0, kFmtUnused, -1, -1, kFmtUnused, -1, -1,
                  kFmtUnused, -1, -1, IS_UNARY_OP | IS_BRANCH | REG_DEF_LR,
@@ -197,31 +282,31 @@
                  kFmtBitBlt, 20, 16, kFmtBitBlt, 15, 0, kFmtBitBlt, 25, 21,
                  kFmtUnused, -1, -1, IS_TERTIARY_OP | REG_DEF0_USE2 | IS_LOAD,
                  "lw", "!0r,!1d(!2r)", 4),
-    ENCODING_MAP(kMipsMfhi, 0x00000010,
-                 kFmtBitBlt, 15, 11, kFmtUnused, -1, -1, kFmtUnused, -1, -1,
-                 kFmtUnused, -1, -1, IS_UNARY_OP | REG_DEF0 | REG_USE_HI,
-                 "mfhi", "!0r", 4),
-    ENCODING_MAP(kMipsMflo, 0x00000012,
-                 kFmtBitBlt, 15, 11, kFmtUnused, -1, -1, kFmtUnused, -1, -1,
-                 kFmtUnused, -1, -1, IS_UNARY_OP | REG_DEF0 | REG_USE_LO,
-                 "mflo", "!0r", 4),
-    ENCODING_MAP(kMipsMove, 0x00000025, /* or using zero reg */
+    ENCODING_MAP(kMipsMove, 0x00000025,  // Or using zero reg.
                  kFmtBitBlt, 15, 11, kFmtBitBlt, 25, 21, kFmtUnused, -1, -1,
                  kFmtUnused, -1, -1, IS_BINARY_OP | REG_DEF0_USE1,
                  "move", "!0r,!1r", 4),
-    ENCODING_MAP(kMipsMovz, 0x0000000a,
-                 kFmtBitBlt, 15, 11, kFmtBitBlt, 25, 21, kFmtBitBlt, 20, 16,
-                 kFmtUnused, -1, -1, IS_TERTIARY_OP | REG_DEF0_USE12,
-                 "movz", "!0r,!1r,!2r", 4),
-    ENCODING_MAP(kMipsMul, 0x70000002,
-                 kFmtBitBlt, 15, 11, kFmtBitBlt, 25, 21, kFmtBitBlt, 20, 16,
-                 kFmtUnused, -1, -1, IS_TERTIARY_OP | REG_DEF0_USE12,
-                 "mul", "!0r,!1r,!2r", 4),
+    ENCODING_MAP(kMipsMfc1, 0x44000000,
+                 kFmtBitBlt, 20, 16, kFmtSfp, 15, 11, kFmtUnused, -1, -1,
+                 kFmtUnused, -1, -1, IS_BINARY_OP | REG_DEF0_USE1,
+                 "mfc1", "!0r,!1s", 4),
+    ENCODING_MAP(kMipsMtc1, 0x44800000,
+                 kFmtBitBlt, 20, 16, kFmtSfp, 15, 11, kFmtUnused, -1, -1,
+                 kFmtUnused, -1, -1, IS_BINARY_OP | REG_USE0 | REG_DEF1,
+                 "mtc1", "!0r,!1s", 4),
+    ENCODING_MAP(kMipsMfhc1, 0x44600000,
+                 kFmtBitBlt, 20, 16, kFmtSfp, 15, 11, kFmtUnused, -1, -1,
+                 kFmtUnused, -1, -1, IS_BINARY_OP | REG_DEF0_USE1,
+                 "mfhc1", "!0r,!1s", 4),
+    ENCODING_MAP(kMipsMthc1, 0x44e00000,
+                 kFmtBitBlt, 20, 16, kFmtSfp, 15, 11, kFmtUnused, -1, -1,
+                 kFmtUnused, -1, -1, IS_BINARY_OP | REG_USE0 | REG_DEF1,
+                 "mthc1", "!0r,!1s", 4),
     ENCODING_MAP(kMipsNop, 0x00000000,
                  kFmtUnused, -1, -1, kFmtUnused, -1, -1, kFmtUnused, -1, -1,
                  kFmtUnused, -1, -1, NO_OPERAND,
                  "nop", ";", 4),
-    ENCODING_MAP(kMipsNor, 0x00000027, /* used for "not" too */
+    ENCODING_MAP(kMipsNor, 0x00000027,  // Used for "not" too.
                  kFmtBitBlt, 15, 11, kFmtBitBlt, 25, 21, kFmtBitBlt, 20, 16,
                  kFmtUnused, -1, -1, IS_TERTIARY_OP | REG_DEF0_USE12,
                  "nor", "!0r,!1r,!2r", 4),
@@ -289,7 +374,7 @@
                  kFmtBitBlt, 15, 11, kFmtBitBlt, 20, 16, kFmtBitBlt, 25, 21,
                  kFmtUnused, -1, -1, IS_TERTIARY_OP | REG_DEF0_USE12,
                  "srlv", "!0r,!1r,!2r", 4),
-    ENCODING_MAP(kMipsSubu, 0x00000023, /* used for "neg" too */
+    ENCODING_MAP(kMipsSubu, 0x00000023,  // Used for "neg" too.
                  kFmtBitBlt, 15, 11, kFmtBitBlt, 25, 21, kFmtBitBlt, 20, 16,
                  kFmtUnused, -1, -1, IS_TERTIARY_OP | REG_DEF0_USE12,
                  "subu", "!0r,!1r,!2r", 4),
@@ -297,6 +382,10 @@
                  kFmtBitBlt, 20, 16, kFmtBitBlt, 15, 0, kFmtBitBlt, 25, 21,
                  kFmtUnused, -1, -1, IS_TERTIARY_OP | REG_USE02 | IS_STORE,
                  "sw", "!0r,!1d(!2r)", 4),
+    ENCODING_MAP(kMipsSync, 0x0000000f,
+                 kFmtBitBlt, 10, 6, kFmtUnused, -1, -1, kFmtUnused, -1, -1,
+                 kFmtUnused, -1, -1, IS_UNARY_OP,
+                 "sync", ";", 4),
     ENCODING_MAP(kMipsXor, 0x00000026,
                  kFmtBitBlt, 15, 11, kFmtBitBlt, 25, 21, kFmtBitBlt, 20, 16,
                  kFmtUnused, -1, -1, IS_TERTIARY_OP | REG_DEF0_USE12,
@@ -305,103 +394,143 @@
                  kFmtBitBlt, 20, 16, kFmtBitBlt, 25, 21, kFmtBitBlt, 15, 0,
                  kFmtUnused, -1, -1, IS_TERTIARY_OP | REG_DEF0_USE1,
                  "xori", "!0r,!1r,0x!2h(!2d)", 4),
-    ENCODING_MAP(kMipsFadds, 0x46000000,
-                 kFmtSfp, 10, 6, kFmtSfp, 15, 11, kFmtSfp, 20, 16,
+
+    // The following are mips32r2 instructions.
+    ENCODING_MAP(kMipsR2Div, 0x0000001a,
+                 kFmtBitBlt, 25, 21, kFmtBitBlt, 20, 16, kFmtUnused, -1, -1,
+                 kFmtUnused, -1, -1, IS_BINARY_OP | REG_DEF_HI | REG_DEF_LO | REG_USE01,
+                 "div", "!0r,!1r", 4),
+    ENCODING_MAP(kMipsR2Mul, 0x70000002,
+                 kFmtBitBlt, 15, 11, kFmtBitBlt, 25, 21, kFmtBitBlt, 20, 16,
                  kFmtUnused, -1, -1, IS_TERTIARY_OP | REG_DEF0_USE12,
-                 "add.s", "!0s,!1s,!2s", 4),
-    ENCODING_MAP(kMipsFsubs, 0x46000001,
-                 kFmtSfp, 10, 6, kFmtSfp, 15, 11, kFmtSfp, 20, 16,
+                 "mul", "!0r,!1r,!2r", 4),
+    ENCODING_MAP(kMipsR2Mfhi, 0x00000010,
+                 kFmtBitBlt, 15, 11, kFmtUnused, -1, -1, kFmtUnused, -1, -1,
+                 kFmtUnused, -1, -1, IS_UNARY_OP | REG_DEF0 | REG_USE_HI,
+                 "mfhi", "!0r", 4),
+    ENCODING_MAP(kMipsR2Mflo, 0x00000012,
+                 kFmtBitBlt, 15, 11, kFmtUnused, -1, -1, kFmtUnused, -1, -1,
+                 kFmtUnused, -1, -1, IS_UNARY_OP | REG_DEF0 | REG_USE_LO,
+                 "mflo", "!0r", 4),
+    ENCODING_MAP(kMipsR2Movz, 0x0000000a,
+                 kFmtBitBlt, 15, 11, kFmtBitBlt, 25, 21, kFmtBitBlt, 20, 16,
                  kFmtUnused, -1, -1, IS_TERTIARY_OP | REG_DEF0_USE12,
-                 "sub.s", "!0s,!1s,!2s", 4),
-    ENCODING_MAP(kMipsFmuls, 0x46000002,
-                 kFmtSfp, 10, 6, kFmtSfp, 15, 11, kFmtSfp, 20, 16,
+                 "movz", "!0r,!1r,!2r", 4),
+
+    // The following are mips32r6 and mips64r6 instructions.
+    ENCODING_MAP(kMipsR6Div, 0x0000009a,
+                 kFmtBitBlt, 15, 11, kFmtBitBlt, 25, 21, kFmtBitBlt, 20, 16,
                  kFmtUnused, -1, -1, IS_TERTIARY_OP | REG_DEF0_USE12,
-                 "mul.s", "!0s,!1s,!2s", 4),
-    ENCODING_MAP(kMipsFdivs, 0x46000003,
-                 kFmtSfp, 10, 6, kFmtSfp, 15, 11, kFmtSfp, 20, 16,
+                 "div", "!0r,!1r,!2r", 4),
+    ENCODING_MAP(kMipsR6Mod, 0x000000da,
+                 kFmtBitBlt, 15, 11, kFmtBitBlt, 25, 21, kFmtBitBlt, 20, 16,
                  kFmtUnused, -1, -1, IS_TERTIARY_OP | REG_DEF0_USE12,
-                 "div.s", "!0s,!1s,!2s", 4),
-    ENCODING_MAP(kMipsFaddd, 0x46200000,
-                 kFmtDfp, 10, 6, kFmtDfp, 15, 11, kFmtDfp, 20, 16,
+                 "mod", "!0r,!1r,!2r", 4),
+    ENCODING_MAP(kMipsR6Mul, 0x00000098,
+                 kFmtBitBlt, 15, 11, kFmtBitBlt, 25, 21, kFmtBitBlt, 20, 16,
                  kFmtUnused, -1, -1, IS_TERTIARY_OP | REG_DEF0_USE12,
-                 "add.d", "!0S,!1S,!2S", 4),
-    ENCODING_MAP(kMipsFsubd, 0x46200001,
-                 kFmtDfp, 10, 6, kFmtDfp, 15, 11, kFmtDfp, 20, 16,
+                 "mul", "!0r,!1r,!2r", 4),
+
+    // The following are mips64r6 instructions.
+    ENCODING_MAP(kMips64Daddiu, 0x64000000,
+                 kFmtBitBlt, 20, 16, kFmtBitBlt, 25, 21, kFmtBitBlt, 15, 0,
+                 kFmtUnused, -1, -1, IS_TERTIARY_OP | REG_DEF0_USE1,
+                 "daddiu", "!0r,!1r,0x!2h(!2d)", 4),
+    ENCODING_MAP(kMips64Daddu, 0x0000002d,
+                 kFmtBitBlt, 15, 11, kFmtBitBlt, 25, 21, kFmtBitBlt, 20, 16,
                  kFmtUnused, -1, -1, IS_TERTIARY_OP | REG_DEF0_USE12,
-                 "sub.d", "!0S,!1S,!2S", 4),
-    ENCODING_MAP(kMipsFmuld, 0x46200002,
-                 kFmtDfp, 10, 6, kFmtDfp, 15, 11, kFmtDfp, 20, 16,
+                 "daddu", "!0r,!1r,!2r", 4),
+    ENCODING_MAP(kMips64Dahi, 0x04060000,
+                 kFmtBitBlt, 25, 21, kFmtBitBlt, 15, 0, kFmtUnused, -1, -1,
+                 kFmtUnused, -1, -1, IS_BINARY_OP | REG_DEF0_USE0,
+                 "dahi", "!0r,0x!1h(!1d)", 4),
+    ENCODING_MAP(kMips64Dati, 0x041E0000,
+                 kFmtBitBlt, 25, 21, kFmtBitBlt, 15, 0, kFmtUnused, -1, -1,
+                 kFmtUnused, -1, -1, IS_BINARY_OP | REG_DEF0_USE0,
+                 "dati", "!0r,0x!1h(!1d)", 4),
+    ENCODING_MAP(kMips64Daui, 0x74000000,
+                 kFmtBitBlt, 20, 16, kFmtBitBlt, 25, 21, kFmtBitBlt, 15, 0,
+                 kFmtUnused, -1, -1, IS_TERTIARY_OP | REG_DEF0_USE1,
+                 "daui", "!0r,!1r,0x!2h(!2d)", 4),
+    ENCODING_MAP(kMips64Ddiv, 0x0000009e,
+                 kFmtBitBlt, 15, 11, kFmtBitBlt, 25, 21, kFmtBitBlt, 20, 16,
                  kFmtUnused, -1, -1, IS_TERTIARY_OP | REG_DEF0_USE12,
-                 "mul.d", "!0S,!1S,!2S", 4),
-    ENCODING_MAP(kMipsFdivd, 0x46200003,
-                 kFmtDfp, 10, 6, kFmtDfp, 15, 11, kFmtDfp, 20, 16,
+                 "ddiv", "!0r,!1r,!2r", 4),
+    ENCODING_MAP(kMips64Dmod, 0x000000de,
+                 kFmtBitBlt, 15, 11, kFmtBitBlt, 25, 21, kFmtBitBlt, 20, 16,
                  kFmtUnused, -1, -1, IS_TERTIARY_OP | REG_DEF0_USE12,
-                 "div.d", "!0S,!1S,!2S", 4),
-    ENCODING_MAP(kMipsFcvtsd, 0x46200020,
-                 kFmtSfp, 10, 6, kFmtDfp, 15, 11, kFmtUnused, -1, -1,
+                 "dmod", "!0r,!1r,!2r", 4),
+    ENCODING_MAP(kMips64Dmul, 0x0000009c,
+                 kFmtBitBlt, 15, 11, kFmtBitBlt, 25, 21, kFmtBitBlt, 20, 16,
+                 kFmtUnused, -1, -1, IS_TERTIARY_OP | REG_DEF0_USE12,
+                 "dmul", "!0r,!1r,!2r", 4),
+    ENCODING_MAP(kMips64Dmfc1, 0x44200000,
+                 kFmtBitBlt, 20, 16, kFmtDfp, 15, 11, kFmtUnused, -1, -1,
                  kFmtUnused, -1, -1, IS_BINARY_OP | REG_DEF0_USE1,
-                 "cvt.s.d", "!0s,!1S", 4),
-    ENCODING_MAP(kMipsFcvtsw, 0x46800020,
-                 kFmtSfp, 10, 6, kFmtSfp, 15, 11, kFmtUnused, -1, -1,
-                 kFmtUnused, -1, -1, IS_BINARY_OP | REG_DEF0_USE1,
-                 "cvt.s.w", "!0s,!1s", 4),
-    ENCODING_MAP(kMipsFcvtds, 0x46000021,
-                 kFmtDfp, 10, 6, kFmtSfp, 15, 11, kFmtUnused, -1, -1,
-                 kFmtUnused, -1, -1, IS_BINARY_OP | REG_DEF0_USE1,
-                 "cvt.d.s", "!0S,!1s", 4),
-    ENCODING_MAP(kMipsFcvtdw, 0x46800021,
-                 kFmtDfp, 10, 6, kFmtSfp, 15, 11, kFmtUnused, -1, -1,
-                 kFmtUnused, -1, -1, IS_BINARY_OP | REG_DEF0_USE1,
-                 "cvt.d.w", "!0S,!1s", 4),
-    ENCODING_MAP(kMipsFcvtws, 0x46000024,
-                 kFmtSfp, 10, 6, kFmtSfp, 15, 11, kFmtUnused, -1, -1,
-                 kFmtUnused, -1, -1, IS_BINARY_OP | REG_DEF0_USE1,
-                 "cvt.w.s", "!0s,!1s", 4),
-    ENCODING_MAP(kMipsFcvtwd, 0x46200024,
-                 kFmtSfp, 10, 6, kFmtDfp, 15, 11, kFmtUnused, -1, -1,
-                 kFmtUnused, -1, -1, IS_BINARY_OP | REG_DEF0_USE1,
-                 "cvt.w.d", "!0s,!1S", 4),
-    ENCODING_MAP(kMipsFmovs, 0x46000006,
-                 kFmtSfp, 10, 6, kFmtSfp, 15, 11, kFmtUnused, -1, -1,
-                 kFmtUnused, -1, -1, IS_BINARY_OP | REG_DEF0_USE1,
-                 "mov.s", "!0s,!1s", 4),
-    ENCODING_MAP(kMipsFmovd, 0x46200006,
-                 kFmtDfp, 10, 6, kFmtDfp, 15, 11, kFmtUnused, -1, -1,
-                 kFmtUnused, -1, -1, IS_BINARY_OP | REG_DEF0_USE1,
-                 "mov.d", "!0S,!1S", 4),
-    ENCODING_MAP(kMipsFlwc1, 0xC4000000,
-                 kFmtSfp, 20, 16, kFmtBitBlt, 15, 0, kFmtBitBlt, 25, 21,
-                 kFmtUnused, -1, -1, IS_TERTIARY_OP | REG_DEF0_USE2 | IS_LOAD,
-                 "lwc1", "!0s,!1d(!2r)", 4),
-    ENCODING_MAP(kMipsFldc1, 0xD4000000,
-                 kFmtDfp, 20, 16, kFmtBitBlt, 15, 0, kFmtBitBlt, 25, 21,
-                 kFmtUnused, -1, -1, IS_TERTIARY_OP | REG_DEF0_USE2 | IS_LOAD,
-                 "ldc1", "!0S,!1d(!2r)", 4),
-    ENCODING_MAP(kMipsFswc1, 0xE4000000,
-                 kFmtSfp, 20, 16, kFmtBitBlt, 15, 0, kFmtBitBlt, 25, 21,
-                 kFmtUnused, -1, -1, IS_TERTIARY_OP | REG_USE02 | IS_STORE,
-                 "swc1", "!0s,!1d(!2r)", 4),
-    ENCODING_MAP(kMipsFsdc1, 0xF4000000,
-                 kFmtDfp, 20, 16, kFmtBitBlt, 15, 0, kFmtBitBlt, 25, 21,
-                 kFmtUnused, -1, -1, IS_TERTIARY_OP | REG_USE02 | IS_STORE,
-                 "sdc1", "!0S,!1d(!2r)", 4),
-    ENCODING_MAP(kMipsMfc1, 0x44000000,
-                 kFmtBitBlt, 20, 16, kFmtSfp, 15, 11, kFmtUnused, -1, -1,
-                 kFmtUnused, -1, -1, IS_BINARY_OP | REG_DEF0_USE1,
-                 "mfc1", "!0r,!1s", 4),
-    ENCODING_MAP(kMipsMtc1, 0x44800000,
-                 kFmtBitBlt, 20, 16, kFmtSfp, 15, 11, kFmtUnused, -1, -1,
+                 "dmfc1", "!0r,!1s", 4),
+    ENCODING_MAP(kMips64Dmtc1, 0x44a00000,
+                 kFmtBitBlt, 20, 16, kFmtDfp, 15, 11, kFmtUnused, -1, -1,
                  kFmtUnused, -1, -1, IS_BINARY_OP | REG_USE0 | REG_DEF1,
-                 "mtc1", "!0r,!1s", 4),
-    ENCODING_MAP(kMipsMfhc1, 0x44600000,
-                 kFmtBitBlt, 20, 16, kFmtSfp, 15, 11, kFmtUnused, -1, -1,
-                 kFmtUnused, -1, -1, IS_BINARY_OP | REG_DEF0_USE1,
-                 "mfhc1", "!0r,!1s", 4),
-    ENCODING_MAP(kMipsMthc1, 0x44e00000,
-                 kFmtBitBlt, 20, 16, kFmtSfp, 15, 11, kFmtUnused, -1, -1,
-                 kFmtUnused, -1, -1, IS_BINARY_OP | REG_USE0 | REG_DEF1,
-                 "mthc1", "!0r,!1s", 4),
-    ENCODING_MAP(kMipsDelta, 0x27e00000,
+                 "dmtc1", "!0r,!1s", 4),
+    ENCODING_MAP(kMips64Drotr32, 0x0000003e | (1 << 21),
+                 kFmtBitBlt, 15, 11, kFmtBitBlt, 20, 16, kFmtBitBlt, 10, 6,
+                 kFmtUnused, -1, -1, IS_TERTIARY_OP | REG_DEF0_USE1,
+                 "drotr32", "!0r,!1r,0x!2h(!2d)", 4),
+    ENCODING_MAP(kMips64Dsll, 0x00000038,
+                 kFmtBitBlt, 15, 11, kFmtBitBlt, 20, 16, kFmtBitBlt, 10, 6,
+                 kFmtUnused, -1, -1, IS_TERTIARY_OP | REG_DEF0_USE1,
+                 "dsll", "!0r,!1r,0x!2h(!2d)", 4),
+    ENCODING_MAP(kMips64Dsll32, 0x0000003c,
+                 kFmtBitBlt, 15, 11, kFmtBitBlt, 20, 16, kFmtBitBlt, 10, 6,
+                 kFmtUnused, -1, -1, IS_TERTIARY_OP | REG_DEF0_USE1,
+                 "dsll32", "!0r,!1r,0x!2h(!2d)", 4),
+    ENCODING_MAP(kMips64Dsrl, 0x0000003a,
+                 kFmtBitBlt, 15, 11, kFmtBitBlt, 20, 16, kFmtBitBlt, 10, 6,
+                 kFmtUnused, -1, -1, IS_TERTIARY_OP | REG_DEF0_USE1,
+                 "dsrl", "!0r,!1r,0x!2h(!2d)", 4),
+    ENCODING_MAP(kMips64Dsrl32, 0x0000003e,
+                 kFmtBitBlt, 15, 11, kFmtBitBlt, 20, 16, kFmtBitBlt, 10, 6,
+                 kFmtUnused, -1, -1, IS_TERTIARY_OP | REG_DEF0_USE1,
+                 "dsrl32", "!0r,!1r,0x!2h(!2d)", 4),
+    ENCODING_MAP(kMips64Dsra, 0x0000003b,
+                 kFmtBitBlt, 15, 11, kFmtBitBlt, 20, 16, kFmtBitBlt, 10, 6,
+                 kFmtUnused, -1, -1, IS_TERTIARY_OP | REG_DEF0_USE1,
+                 "dsra", "!0r,!1r,0x!2h(!2d)", 4),
+    ENCODING_MAP(kMips64Dsra32, 0x0000003f,
+                 kFmtBitBlt, 15, 11, kFmtBitBlt, 20, 16, kFmtBitBlt, 10, 6,
+                 kFmtUnused, -1, -1, IS_TERTIARY_OP | REG_DEF0_USE1,
+                 "dsra32", "!0r,!1r,0x!2h(!2d)", 4),
+    ENCODING_MAP(kMips64Dsllv, 0x00000014,
+                 kFmtBitBlt, 15, 11, kFmtBitBlt, 20, 16, kFmtBitBlt, 25, 21,
+                 kFmtUnused, -1, -1, IS_TERTIARY_OP | REG_DEF0_USE12,
+                 "dsllv", "!0r,!1r,!2r", 4),
+    ENCODING_MAP(kMips64Dsrlv, 0x00000016,
+                 kFmtBitBlt, 15, 11, kFmtBitBlt, 20, 16, kFmtBitBlt, 25, 21,
+                 kFmtUnused, -1, -1, IS_TERTIARY_OP | REG_DEF0_USE12,
+                 "dsrlv", "!0r,!1r,!2r", 4),
+    ENCODING_MAP(kMips64Dsrav, 0x00000017,
+                 kFmtBitBlt, 15, 11, kFmtBitBlt, 20, 16, kFmtBitBlt, 25, 21,
+                 kFmtUnused, -1, -1, IS_TERTIARY_OP | REG_DEF0_USE12,
+                 "dsrav", "!0r,!1r,!2r", 4),
+    ENCODING_MAP(kMips64Dsubu, 0x0000002f,
+                 kFmtBitBlt, 15, 11, kFmtBitBlt, 25, 21, kFmtBitBlt, 20, 16,
+                 kFmtUnused, -1, -1, IS_TERTIARY_OP | REG_DEF0_USE12,
+                 "dsubu", "!0r,!1r,!2r", 4),
+    ENCODING_MAP(kMips64Ld, 0xdc000000,
+                 kFmtBitBlt, 20, 16, kFmtBitBlt, 15, 0, kFmtBitBlt, 25, 21,
+                 kFmtUnused, -1, -1, IS_TERTIARY_OP | REG_DEF0_USE2 | IS_LOAD,
+                 "ld", "!0r,!1d(!2r)", 4),
+    ENCODING_MAP(kMips64Lwu, 0x9c000000,
+                 kFmtBitBlt, 20, 16, kFmtBitBlt, 15, 0, kFmtBitBlt, 25, 21,
+                 kFmtUnused, -1, -1, IS_TERTIARY_OP | REG_DEF0_USE2 | IS_LOAD,
+                 "lwu", "!0r,!1d(!2r)", 4),
+    ENCODING_MAP(kMips64Sd, 0xfc000000,
+                 kFmtBitBlt, 20, 16, kFmtBitBlt, 15, 0, kFmtBitBlt, 25, 21,
+                 kFmtUnused, -1, -1, IS_TERTIARY_OP | REG_USE02 | IS_STORE,
+                 "sd", "!0r,!1d(!2r)", 4),
+
+    // The following are pseudoinstructions.
+    ENCODING_MAP(kMipsDelta, 0x27e00000,  // It is implemented as daddiu for mips64.
                  kFmtBitBlt, 20, 16, kFmtBitBlt, 15, 0, kFmtUnused, 15, 0,
                  kFmtUnused, -1, -1, IS_QUAD_OP | REG_DEF0 | REG_USE_LR |
                  NEEDS_FIXUP, "addiu", "!0r,ra,0x!1h(!1d)", 4),
@@ -417,25 +546,6 @@
                  kFmtUnused, -1, -1, kFmtUnused, -1, -1, kFmtUnused, -1, -1,
                  kFmtUnused, -1, -1, NO_OPERAND | IS_BRANCH | REG_DEF_LR,
                  "addiu", "ra,pc,8", 4),
-    ENCODING_MAP(kMipsSync, 0x0000000f,
-                 kFmtBitBlt, 10, 6, kFmtUnused, -1, -1, kFmtUnused, -1, -1,
-                 kFmtUnused, -1, -1, IS_UNARY_OP,
-                 "sync", ";", 4),
-
-    // The following are mips32r6 instructions.
-    ENCODING_MAP(kMipsR6Div, 0x0000009a,
-                 kFmtBitBlt, 15, 11, kFmtBitBlt, 25, 21, kFmtBitBlt, 20, 16,
-                 kFmtUnused, -1, -1, IS_TERTIARY_OP | REG_DEF0_USE12,
-                 "div", "!0r,!1r,!2r", 4),
-    ENCODING_MAP(kMipsR6Mod, 0x000000da,
-                 kFmtBitBlt, 15, 11, kFmtBitBlt, 25, 21, kFmtBitBlt, 20, 16,
-                 kFmtUnused, -1, -1, IS_TERTIARY_OP | REG_DEF0_USE12,
-                 "mod", "!0r,!1r,!2r", 4),
-    ENCODING_MAP(kMipsR6Mul, 0x00000098,
-                 kFmtBitBlt, 15, 11, kFmtBitBlt, 25, 21, kFmtBitBlt, 20, 16,
-                 kFmtUnused, -1, -1, IS_TERTIARY_OP | REG_DEF0_USE12,
-                 "mul", "!0r,!1r,!2r", 4),
-
     ENCODING_MAP(kMipsUndefined, 0x64000000,
                  kFmtUnused, -1, -1, kFmtUnused, -1, -1, kFmtUnused, -1, -1,
                  kFmtUnused, -1, -1, NO_OPERAND,
@@ -538,14 +648,13 @@
  */
 AssemblerStatus MipsMir2Lir::AssembleInstructions(CodeOffset start_addr) {
   LIR *lir;
-  AssemblerStatus res = kSuccess;  // Assume success
+  AssemblerStatus res = kSuccess;  // Assume success.
 
   for (lir = first_lir_insn_; lir != NULL; lir = NEXT_LIR(lir)) {
     if (lir->opcode < 0) {
       continue;
     }
 
-
     if (lir->flags.is_nop) {
       continue;
     }
@@ -567,23 +676,31 @@
         int offset2 = tab_rec ? tab_rec->offset : lir->target->offset;
         int delta = offset2 - offset1;
         if ((delta & 0xffff) == delta && ((delta & 0x8000) == 0)) {
-          // Fits
+          // Fits.
           lir->operands[1] = delta;
+          if (cu_->target64) {
+            LIR *new_addiu = RawLIR(lir->dalvik_offset, kMips64Daddiu, lir->operands[0], rRAd,
+                                    delta);
+            InsertLIRBefore(lir, new_addiu);
+            NopLIR(lir);
+            res = kRetryAll;
+          }
         } else {
-          // Doesn't fit - must expand to kMipsDelta[Hi|Lo] pair
-          LIR *new_delta_hi =
-              RawLIR(lir->dalvik_offset, kMipsDeltaHi,
-                     lir->operands[0], 0, lir->operands[2],
-                     lir->operands[3], 0, lir->target);
+          // Doesn't fit - must expand to kMipsDelta[Hi|Lo] pair.
+          LIR *new_delta_hi = RawLIR(lir->dalvik_offset, kMipsDeltaHi, lir->operands[0], 0,
+                                     lir->operands[2], lir->operands[3], 0, lir->target);
           InsertLIRBefore(lir, new_delta_hi);
-          LIR *new_delta_lo =
-              RawLIR(lir->dalvik_offset, kMipsDeltaLo,
-                     lir->operands[0], 0, lir->operands[2],
-                     lir->operands[3], 0, lir->target);
+          LIR *new_delta_lo = RawLIR(lir->dalvik_offset, kMipsDeltaLo, lir->operands[0], 0,
+                                     lir->operands[2], lir->operands[3], 0, lir->target);
           InsertLIRBefore(lir, new_delta_lo);
-          LIR *new_addu =
-              RawLIR(lir->dalvik_offset, kMipsAddu,
-                     lir->operands[0], lir->operands[0], rRA);
+          LIR *new_addu;
+          if (cu_->target64) {
+            new_addu = RawLIR(lir->dalvik_offset, kMips64Daddu, lir->operands[0], lir->operands[0],
+                              rRAd);
+          } else {
+            new_addu = RawLIR(lir->dalvik_offset, kMipsAddu, lir->operands[0], lir->operands[0],
+                              rRA);
+          }
           InsertLIRBefore(lir, new_addu);
           NopLIR(lir);
           res = kRetryAll;
@@ -698,7 +815,9 @@
         case kFmtDfp: {
           // TODO: do we need to adjust now that we're using 64BitSolo?
           DCHECK(RegStorage::IsDouble(operand)) << ", Operand = 0x" << std::hex << operand;
-          DCHECK_EQ((operand & 0x1), 0U);
+          if (!cu_->target64) {
+            DCHECK_EQ((operand & 0x1), 0U);  // May only use even numbered registers for mips32.
+          }
           value = (RegStorage::RegNum(operand) << encoder->field_loc[i].start) &
               ((1 << (encoder->field_loc[i].end + 1)) - 1);
           bits |= value;
@@ -719,7 +838,7 @@
     code_buffer_.push_back((bits >> 8) & 0xff);
     code_buffer_.push_back((bits >> 16) & 0xff);
     code_buffer_.push_back((bits >> 24) & 0xff);
-    // TUNING: replace with proper delay slot handling
+    // TUNING: replace with proper delay slot handling.
     if (encoder->size == 8) {
       DCHECK(!IsPseudoLirOp(lir->opcode));
       const MipsEncodingMap *encoder2 = &EncodingMap[kMipsNop];
@@ -758,7 +877,7 @@
         lir->operands[0] = 0;
       }
     }
-    /* Pseudo opcodes don't consume space */
+    // Pseudo opcodes don't consume space.
   }
   return offset;
 }
@@ -771,10 +890,10 @@
 void MipsMir2Lir::AssignOffsets() {
   int offset = AssignInsnOffsets();
 
-  /* Const values have to be word aligned */
+  // Const values have to be word aligned.
   offset = RoundUp(offset, 4);
 
-  /* Set up offsets for literals */
+  // Set up offsets for literals.
   data_offset_ = offset;
 
   offset = AssignLiteralOffset(offset);
@@ -811,19 +930,19 @@
         CodegenDump();
         LOG(FATAL) << "Assembler error - too many retries";
       }
-      // Redo offsets and try again
+      // Redo offsets and try again.
       AssignOffsets();
       code_buffer_.clear();
     }
   }
 
-  // Install literals
+  // Install literals.
   InstallLiteralPools();
 
-  // Install switch tables
+  // Install switch tables.
   InstallSwitchTables();
 
-  // Install fill array data
+  // Install fill array data.
   InstallFillArrayData();
 
   // Create the mapping table and native offset to reference map.
diff --git a/compiler/dex/quick/mips/call_mips.cc b/compiler/dex/quick/mips/call_mips.cc
index b067221..de66b35 100644
--- a/compiler/dex/quick/mips/call_mips.cc
+++ b/compiler/dex/quick/mips/call_mips.cc
@@ -68,7 +68,7 @@
  */
 void MipsMir2Lir::GenLargeSparseSwitch(MIR* mir, DexOffset table_offset, RegLocation rl_src) {
   const uint16_t* table = mir_graph_->GetTable(mir, table_offset);
-  // Add the table to the list - we'll process it later
+  // Add the table to the list - we'll process it later.
   SwitchTable* tab_rec =
       static_cast<SwitchTable*>(arena_->Alloc(sizeof(SwitchTable), kArenaAllocData));
   tab_rec->switch_mir = mir;
@@ -77,39 +77,39 @@
   int elements = table[1];
   switch_tables_.push_back(tab_rec);
 
-  // The table is composed of 8-byte key/disp pairs
+  // The table is composed of 8-byte key/disp pairs.
   int byte_size = elements * 8;
 
   int size_hi = byte_size >> 16;
   int size_lo = byte_size & 0xffff;
 
-  RegStorage r_end = AllocTemp();
+  RegStorage r_end = AllocPtrSizeTemp();
   if (size_hi) {
     NewLIR2(kMipsLui, r_end.GetReg(), size_hi);
   }
-  // Must prevent code motion for the curr pc pair
+  // Must prevent code motion for the curr pc pair.
   GenBarrier();  // Scheduling barrier
-  NewLIR0(kMipsCurrPC);  // Really a jal to .+8
-  // Now, fill the branch delay slot
+  NewLIR0(kMipsCurrPC);  // Really a jal to .+8.
+  // Now, fill the branch delay slot.
   if (size_hi) {
     NewLIR3(kMipsOri, r_end.GetReg(), r_end.GetReg(), size_lo);
   } else {
     NewLIR3(kMipsOri, r_end.GetReg(), rZERO, size_lo);
   }
-  GenBarrier();  // Scheduling barrier
+  GenBarrier();  // Scheduling barrier.
 
-  // Construct BaseLabel and set up table base register
+  // Construct BaseLabel and set up table base register.
   LIR* base_label = NewLIR0(kPseudoTargetLabel);
-  // Remember base label so offsets can be computed later
+  // Remember base label so offsets can be computed later.
   tab_rec->anchor = base_label;
-  RegStorage r_base = AllocTemp();
+  RegStorage r_base = AllocPtrSizeTemp();
   NewLIR4(kMipsDelta, r_base.GetReg(), 0, WrapPointer(base_label), WrapPointer(tab_rec));
   OpRegRegReg(kOpAdd, r_end, r_end, r_base);
 
-  // Grab switch test value
+  // Grab switch test value.
   rl_src = LoadValue(rl_src, kCoreReg);
 
-  // Test loop
+  // Test loop.
   RegStorage r_key = AllocTemp();
   LIR* loop_label = NewLIR0(kPseudoTargetLabel);
   LIR* exit_branch = OpCmpBranch(kCondEq, r_base, r_end, NULL);
@@ -118,10 +118,10 @@
   OpCmpBranch(kCondNe, rl_src.reg, r_key, loop_label);
   RegStorage r_disp = AllocTemp();
   Load32Disp(r_base, -4, r_disp);
-  OpRegRegReg(kOpAdd, rs_rRA, rs_rRA, r_disp);
-  OpReg(kOpBx, rs_rRA);
-
-  // Loop exit
+  const RegStorage rs_ra = TargetPtrReg(kLr);
+  OpRegRegReg(kOpAdd, rs_ra, rs_ra, r_disp);
+  OpReg(kOpBx, rs_ra);
+  // Loop exit.
   LIR* exit_label = NewLIR0(kPseudoTargetLabel);
   exit_branch->target = exit_label;
 }
@@ -141,7 +141,7 @@
  */
 void MipsMir2Lir::GenLargePackedSwitch(MIR* mir, DexOffset table_offset, RegLocation rl_src) {
   const uint16_t* table = mir_graph_->GetTable(mir, table_offset);
-  // Add the table to the list - we'll process it later
+  // Add the table to the list - we'll process it later.
   SwitchTable* tab_rec =
       static_cast<SwitchTable*>(arena_->Alloc(sizeof(SwitchTable), kArenaAllocData));
   tab_rec->switch_mir = mir;
@@ -150,10 +150,10 @@
   int size = table[1];
   switch_tables_.push_back(tab_rec);
 
-  // Get the switch value
+  // Get the switch value.
   rl_src = LoadValue(rl_src, kCoreReg);
 
-  // Prepare the bias.  If too big, handle 1st stage here
+  // Prepare the bias.  If too big, handle 1st stage here.
   int low_key = s4FromSwitchData(&table[2]);
   bool large_bias = false;
   RegStorage r_key;
@@ -167,10 +167,10 @@
     r_key = AllocTemp();
   }
 
-  // Must prevent code motion for the curr pc pair
+  // Must prevent code motion for the curr pc pair.
   GenBarrier();
-  NewLIR0(kMipsCurrPC);  // Really a jal to .+8
-  // Now, fill the branch delay slot with bias strip
+  NewLIR0(kMipsCurrPC);  // Really a jal to .+8.
+  // Now, fill the branch delay slot with bias strip.
   if (low_key == 0) {
     NewLIR0(kMipsNop);
   } else {
@@ -180,51 +180,60 @@
       OpRegRegImm(kOpSub, r_key, rl_src.reg, low_key);
     }
   }
-  GenBarrier();  // Scheduling barrier
+  GenBarrier();  // Scheduling barrier.
 
-  // Construct BaseLabel and set up table base register
+  // Construct BaseLabel and set up table base register.
   LIR* base_label = NewLIR0(kPseudoTargetLabel);
-  // Remember base label so offsets can be computed later
+  // Remember base label so offsets can be computed later.
   tab_rec->anchor = base_label;
 
-  // Bounds check - if < 0 or >= size continue following switch
+  // Bounds check - if < 0 or >= size continue following switch.
   LIR* branch_over = OpCmpImmBranch(kCondHi, r_key, size-1, NULL);
 
-  // Materialize the table base pointer
-  RegStorage r_base = AllocTemp();
+  // Materialize the table base pointer.
+  RegStorage r_base = AllocPtrSizeTemp();
   NewLIR4(kMipsDelta, r_base.GetReg(), 0, WrapPointer(base_label), WrapPointer(tab_rec));
 
-  // Load the displacement from the switch table
+  // Load the displacement from the switch table.
   RegStorage r_disp = AllocTemp();
   LoadBaseIndexed(r_base, r_key, r_disp, 2, k32);
 
-  // Add to rAP and go
-  OpRegRegReg(kOpAdd, rs_rRA, rs_rRA, r_disp);
-  OpReg(kOpBx, rs_rRA);
+  // Add to rRA and go.
+  const RegStorage rs_ra = TargetPtrReg(kLr);
+  OpRegRegReg(kOpAdd, rs_ra, rs_ra, r_disp);
+  OpReg(kOpBx, rs_ra);
 
-  /* branch_over target here */
+  // Branch_over target here.
   LIR* target = NewLIR0(kPseudoTargetLabel);
   branch_over->target = target;
 }
 
 void MipsMir2Lir::GenMoveException(RegLocation rl_dest) {
-  int ex_offset = Thread::ExceptionOffset<4>().Int32Value();
+  int ex_offset = cu_->target64 ? Thread::ExceptionOffset<8>().Int32Value() :
+      Thread::ExceptionOffset<4>().Int32Value();
   RegLocation rl_result = EvalLoc(rl_dest, kRefReg, true);
   RegStorage reset_reg = AllocTempRef();
-  LoadRefDisp(rs_rMIPS_SELF, ex_offset, rl_result.reg, kNotVolatile);
+  LoadRefDisp(TargetPtrReg(kSelf), ex_offset, rl_result.reg, kNotVolatile);
   LoadConstant(reset_reg, 0);
-  StoreRefDisp(rs_rMIPS_SELF, ex_offset, reset_reg, kNotVolatile);
+  StoreRefDisp(TargetPtrReg(kSelf), ex_offset, reset_reg, kNotVolatile);
   FreeTemp(reset_reg);
   StoreValue(rl_dest, rl_result);
 }
 
 void MipsMir2Lir::UnconditionallyMarkGCCard(RegStorage tgt_addr_reg) {
-  RegStorage reg_card_base = AllocTemp();
-  RegStorage reg_card_no = AllocTemp();
-  // NOTE: native pointer.
-  LoadWordDisp(rs_rMIPS_SELF, Thread::CardTableOffset<4>().Int32Value(), reg_card_base);
-  OpRegRegImm(kOpLsr, reg_card_no, tgt_addr_reg, gc::accounting::CardTable::kCardShift);
-  StoreBaseIndexed(reg_card_base, reg_card_no, reg_card_base, 0, kUnsignedByte);
+  RegStorage reg_card_base = AllocPtrSizeTemp();
+  RegStorage reg_card_no = AllocPtrSizeTemp();
+  if (cu_->target64) {
+    // NOTE: native pointer.
+    LoadWordDisp(TargetPtrReg(kSelf), Thread::CardTableOffset<8>().Int32Value(), reg_card_base);
+    OpRegRegImm(kOpLsr, reg_card_no, tgt_addr_reg, gc::accounting::CardTable::kCardShift);
+    StoreBaseIndexed(reg_card_base, reg_card_no, As32BitReg(reg_card_base), 0, kUnsignedByte);
+  } else {
+    // NOTE: native pointer.
+    LoadWordDisp(TargetPtrReg(kSelf), Thread::CardTableOffset<4>().Int32Value(), reg_card_base);
+    OpRegRegImm(kOpLsr, reg_card_no, tgt_addr_reg, gc::accounting::CardTable::kCardShift);
+    StoreBaseIndexed(reg_card_base, reg_card_no, reg_card_base, 0, kUnsignedByte);
+  }
   FreeTemp(reg_card_base);
   FreeTemp(reg_card_no);
 }
@@ -232,33 +241,57 @@
 void MipsMir2Lir::GenEntrySequence(RegLocation* ArgLocs, RegLocation rl_method) {
   int spill_count = num_core_spills_ + num_fp_spills_;
   /*
-   * On entry, rMIPS_ARG0, rMIPS_ARG1, rMIPS_ARG2 & rMIPS_ARG3 are live.  Let the register
-   * allocation mechanism know so it doesn't try to use any of them when
-   * expanding the frame or flushing.  This leaves the utility
-   * code with a single temp: r12.  This should be enough.
+   * On entry, A0, A1, A2 & A3 are live. On Mips64, A4, A5, A6 & A7 are also live.
+   * Let the register allocation mechanism know so it doesn't try to use any of them when
+   * expanding the frame or flushing.
    */
-  LockTemp(rs_rMIPS_ARG0);
-  LockTemp(rs_rMIPS_ARG1);
-  LockTemp(rs_rMIPS_ARG2);
-  LockTemp(rs_rMIPS_ARG3);
+  const RegStorage arg0 = TargetReg(kArg0);
+  const RegStorage arg1 = TargetReg(kArg1);
+  const RegStorage arg2 = TargetReg(kArg2);
+  const RegStorage arg3 = TargetReg(kArg3);
+  const RegStorage arg4 = TargetReg(kArg4);
+  const RegStorage arg5 = TargetReg(kArg5);
+  const RegStorage arg6 = TargetReg(kArg6);
+  const RegStorage arg7 = TargetReg(kArg7);
+
+  LockTemp(arg0);
+  LockTemp(arg1);
+  LockTemp(arg2);
+  LockTemp(arg3);
+  if (cu_->target64) {
+    LockTemp(arg4);
+    LockTemp(arg5);
+    LockTemp(arg6);
+    LockTemp(arg7);
+  }
+
+  bool skip_overflow_check;
+  InstructionSet target = (cu_->target64) ? kMips64 : kMips;
+  int ptr_size = cu_->target64 ? 8 : 4;
 
   /*
    * We can safely skip the stack overflow check if we're
    * a leaf *and* our frame size < fudge factor.
    */
-  bool skip_overflow_check = mir_graph_->MethodIsLeaf() && !FrameNeedsStackCheck(frame_size_, kMips);
+
+  skip_overflow_check = mir_graph_->MethodIsLeaf() && !FrameNeedsStackCheck(frame_size_, target);
   NewLIR0(kPseudoMethodEntry);
-  RegStorage check_reg = AllocTemp();
-  RegStorage new_sp = AllocTemp();
+  RegStorage check_reg = AllocPtrSizeTemp();
+  RegStorage new_sp = AllocPtrSizeTemp();
+  const RegStorage rs_sp = TargetPtrReg(kSp);
   if (!skip_overflow_check) {
-    /* Load stack limit */
-    Load32Disp(rs_rMIPS_SELF, Thread::StackEndOffset<4>().Int32Value(), check_reg);
+    // Load stack limit.
+    if (cu_->target64) {
+      LoadWordDisp(TargetPtrReg(kSelf), Thread::StackEndOffset<8>().Int32Value(), check_reg);
+    } else {
+      Load32Disp(TargetPtrReg(kSelf), Thread::StackEndOffset<4>().Int32Value(), check_reg);
+    }
   }
-  /* Spill core callee saves */
+  // Spill core callee saves.
   SpillCoreRegs();
-  /* NOTE: promotion of FP regs currently unsupported, thus no FP spill */
+  // NOTE: promotion of FP regs currently unsupported, thus no FP spill.
   DCHECK_EQ(num_fp_spills_, 0);
-  const int frame_sub = frame_size_ - spill_count * 4;
+  const int frame_sub = frame_size_ - spill_count * ptr_size;
   if (!skip_overflow_check) {
     class StackOverflowSlowPath : public LIRSlowPath {
      public:
@@ -269,9 +302,9 @@
         m2l_->ResetRegPool();
         m2l_->ResetDefTracking();
         GenerateTargetLabel(kPseudoThrowTarget);
-        // LR is offset 0 since we push in reverse order.
-        m2l_->Load32Disp(rs_rMIPS_SP, 0, rs_rRA);
-        m2l_->OpRegImm(kOpAdd, rs_rMIPS_SP, sp_displace_);
+        // RA is offset 0 since we push in reverse order.
+        m2l_->LoadWordDisp(m2l_->TargetPtrReg(kSp), 0, m2l_->TargetPtrReg(kLr));
+        m2l_->OpRegImm(kOpAdd, m2l_->TargetPtrReg(kSp), sp_displace_);
         m2l_->ClobberCallerSave();
         RegStorage r_tgt = m2l_->CallHelperSetup(kQuickThrowStackOverflow);  // Doesn't clobber LR.
         m2l_->CallHelper(r_tgt, kQuickThrowStackOverflow, false /* MarkSafepointPC */,
@@ -281,21 +314,27 @@
      private:
       const size_t sp_displace_;
     };
-    OpRegRegImm(kOpSub, new_sp, rs_rMIPS_SP, frame_sub);
+    OpRegRegImm(kOpSub, new_sp, rs_sp, frame_sub);
     LIR* branch = OpCmpBranch(kCondUlt, new_sp, check_reg, nullptr);
-    AddSlowPath(new(arena_)StackOverflowSlowPath(this, branch, spill_count * 4));
+    AddSlowPath(new(arena_)StackOverflowSlowPath(this, branch, spill_count * ptr_size));
     // TODO: avoid copy for small frame sizes.
-    OpRegCopy(rs_rMIPS_SP, new_sp);     // Establish stack
+    OpRegCopy(rs_sp, new_sp);  // Establish stack.
   } else {
-    OpRegImm(kOpSub, rs_rMIPS_SP, frame_sub);
+    OpRegImm(kOpSub, rs_sp, frame_sub);
   }
 
   FlushIns(ArgLocs, rl_method);
 
-  FreeTemp(rs_rMIPS_ARG0);
-  FreeTemp(rs_rMIPS_ARG1);
-  FreeTemp(rs_rMIPS_ARG2);
-  FreeTemp(rs_rMIPS_ARG3);
+  FreeTemp(arg0);
+  FreeTemp(arg1);
+  FreeTemp(arg2);
+  FreeTemp(arg3);
+  if (cu_->target64) {
+    FreeTemp(arg4);
+    FreeTemp(arg5);
+    FreeTemp(arg6);
+    FreeTemp(arg7);
+  }
 }
 
 void MipsMir2Lir::GenExitSequence() {
@@ -303,58 +342,67 @@
    * In the exit path, rMIPS_RET0/rMIPS_RET1 are live - make sure they aren't
    * allocated by the register utilities as temps.
    */
-  LockTemp(rs_rMIPS_RET0);
-  LockTemp(rs_rMIPS_RET1);
+  LockTemp(TargetPtrReg(kRet0));
+  LockTemp(TargetPtrReg(kRet1));
 
   NewLIR0(kPseudoMethodExit);
   UnSpillCoreRegs();
-  OpReg(kOpBx, rs_rRA);
+  OpReg(kOpBx, TargetPtrReg(kLr));
 }
 
 void MipsMir2Lir::GenSpecialExitSequence() {
-  OpReg(kOpBx, rs_rRA);
+  OpReg(kOpBx, TargetPtrReg(kLr));
 }
 
 void MipsMir2Lir::GenSpecialEntryForSuspend() {
-  // Keep 16-byte stack alignment - push A0, i.e. ArtMethod*, 2 filler words and RA.
-  core_spill_mask_ = (1u << rs_rRA.GetRegNum());
+  // Keep 16-byte stack alignment - push A0, i.e. ArtMethod*, 2 filler words and RA for mips32,
+  // but A0 and RA for mips64.
+  core_spill_mask_ = (1u << TargetPtrReg(kLr).GetRegNum());
   num_core_spills_ = 1u;
   fp_spill_mask_ = 0u;
   num_fp_spills_ = 0u;
   frame_size_ = 16u;
   core_vmap_table_.clear();
   fp_vmap_table_.clear();
-  OpRegImm(kOpSub, rs_rMIPS_SP, frame_size_);
-  Store32Disp(rs_rMIPS_SP, frame_size_ - 4, rs_rRA);
-  Store32Disp(rs_rMIPS_SP, 0, rs_rA0);
+  const RegStorage rs_sp = TargetPtrReg(kSp);
+  OpRegImm(kOpSub, rs_sp, frame_size_);
+  StoreWordDisp(rs_sp, frame_size_ - (cu_->target64 ? 8 : 4), TargetPtrReg(kLr));
+  StoreWordDisp(rs_sp, 0, TargetPtrReg(kArg0));
 }
 
 void MipsMir2Lir::GenSpecialExitForSuspend() {
   // Pop the frame. Don't pop ArtMethod*, it's no longer needed.
-  Load32Disp(rs_rMIPS_SP, frame_size_ - 4, rs_rRA);
-  OpRegImm(kOpAdd, rs_rMIPS_SP, frame_size_);
+  const RegStorage rs_sp = TargetPtrReg(kSp);
+  LoadWordDisp(rs_sp, frame_size_ - (cu_->target64 ? 8 : 4), TargetPtrReg(kLr));
+  OpRegImm(kOpAdd, rs_sp, frame_size_);
 }
 
 /*
  * Bit of a hack here - in the absence of a real scheduling pass,
  * emit the next instruction in static & direct invoke sequences.
  */
-static int NextSDCallInsn(CompilationUnit* cu, CallInfo* info ATTRIBUTE_UNUSED,
-                          int state, const MethodReference& target_method,
-                          uint32_t,
-                          uintptr_t direct_code, uintptr_t direct_method,
-                          InvokeType type) {
+static int NextSDCallInsn(CompilationUnit* cu, CallInfo* info ATTRIBUTE_UNUSED, int state,
+                          const MethodReference& target_method, uint32_t, uintptr_t direct_code,
+                          uintptr_t direct_method, InvokeType type) {
   Mir2Lir* cg = static_cast<Mir2Lir*>(cu->cg.get());
   if (direct_code != 0 && direct_method != 0) {
     switch (state) {
     case 0:  // Get the current Method* [sets kArg0]
       if (direct_code != static_cast<uintptr_t>(-1)) {
-        cg->LoadConstant(cg->TargetPtrReg(kInvokeTgt), direct_code);
+        if (cu->target64) {
+          cg->LoadConstantWide(cg->TargetPtrReg(kInvokeTgt), direct_code);
+        } else {
+          cg->LoadConstant(cg->TargetPtrReg(kInvokeTgt), direct_code);
+        }
       } else {
         cg->LoadCodeAddress(target_method, type, kInvokeTgt);
       }
       if (direct_method != static_cast<uintptr_t>(-1)) {
-        cg->LoadConstant(cg->TargetReg(kArg0, kRef), direct_method);
+        if (cu->target64) {
+          cg->LoadConstantWide(cg->TargetReg(kArg0, kRef), direct_method);
+        } else {
+          cg->LoadConstant(cg->TargetReg(kArg0, kRef), direct_method);
+        }
       } else {
         cg->LoadMethodAddress(target_method, type, kArg0);
       }
@@ -377,7 +425,11 @@
       // Set up direct code if known.
       if (direct_code != 0) {
         if (direct_code != static_cast<uintptr_t>(-1)) {
-          cg->LoadConstant(cg->TargetPtrReg(kInvokeTgt), direct_code);
+          if (cu->target64) {
+            cg->LoadConstantWide(cg->TargetPtrReg(kInvokeTgt), direct_code);
+          } else {
+            cg->LoadConstant(cg->TargetPtrReg(kInvokeTgt), direct_code);
+          }
         } else {
           CHECK_LT(target_method.dex_method_index, target_method.dex_file->NumMethodIds());
           cg->LoadCodeAddress(target_method, type, kInvokeTgt);
diff --git a/compiler/dex/quick/mips/codegen_mips.h b/compiler/dex/quick/mips/codegen_mips.h
index 649b6c9..713264e 100644
--- a/compiler/dex/quick/mips/codegen_mips.h
+++ b/compiler/dex/quick/mips/codegen_mips.h
@@ -17,6 +17,7 @@
 #ifndef ART_COMPILER_DEX_QUICK_MIPS_CODEGEN_MIPS_H_
 #define ART_COMPILER_DEX_QUICK_MIPS_CODEGEN_MIPS_H_
 
+#include "dex/compiler_ir.h"
 #include "dex/quick/mir_to_lir.h"
 #include "mips_lir.h"
 
@@ -39,215 +40,303 @@
     size_t cur_core_reg_;
   };
 
+  class InToRegStorageMips64Mapper : public InToRegStorageMapper {
+   public:
+    explicit InToRegStorageMips64Mapper(Mir2Lir* m2l) : m2l_(m2l), cur_arg_reg_(0) {}
+    virtual RegStorage GetNextReg(ShortyArg arg);
+    virtual void Reset() OVERRIDE {
+      cur_arg_reg_ = 0;
+    }
+   protected:
+    Mir2Lir* m2l_;
+   private:
+    size_t cur_arg_reg_;
+  };
+
+  InToRegStorageMips64Mapper in_to_reg_storage_mips64_mapper_;
   InToRegStorageMipsMapper in_to_reg_storage_mips_mapper_;
   InToRegStorageMapper* GetResetedInToRegStorageMapper() OVERRIDE {
-    in_to_reg_storage_mips_mapper_.Reset();
-    return &in_to_reg_storage_mips_mapper_;
+    InToRegStorageMapper* res;
+    if (cu_->target64) {
+      res = &in_to_reg_storage_mips64_mapper_;
+    } else {
+      res = &in_to_reg_storage_mips_mapper_;
+    }
+    res->Reset();
+    return res;
   }
 
-  public:
-    MipsMir2Lir(CompilationUnit* cu, MIRGraph* mir_graph, ArenaAllocator* arena);
+ public:
+  MipsMir2Lir(CompilationUnit* cu, MIRGraph* mir_graph, ArenaAllocator* arena);
 
-    // Required for target - codegen utilities.
-    bool SmallLiteralDivRem(Instruction::Code dalvik_opcode, bool is_div, RegLocation rl_src,
-                            RegLocation rl_dest, int lit);
-    bool EasyMultiply(RegLocation rl_src, RegLocation rl_dest, int lit) OVERRIDE;
-    void GenMultiplyByConstantFloat(RegLocation rl_dest, RegLocation rl_src1,
-                                    int32_t constant) OVERRIDE;
-    void GenMultiplyByConstantDouble(RegLocation rl_dest, RegLocation rl_src1,
-                                     int64_t constant) OVERRIDE;
-    LIR* CheckSuspendUsingLoad() OVERRIDE;
-    RegStorage LoadHelper(QuickEntrypointEnum trampoline) OVERRIDE;
-    LIR* LoadBaseDisp(RegStorage r_base, int displacement, RegStorage r_dest,
-                      OpSize size, VolatileKind is_volatile) OVERRIDE;
-    LIR* LoadBaseIndexed(RegStorage r_base, RegStorage r_index, RegStorage r_dest, int scale,
-                         OpSize size) OVERRIDE;
-    LIR* LoadConstantNoClobber(RegStorage r_dest, int value);
-    LIR* LoadConstantWide(RegStorage r_dest, int64_t value);
-    LIR* StoreBaseDisp(RegStorage r_base, int displacement, RegStorage r_src,
-                       OpSize size, VolatileKind is_volatile) OVERRIDE;
-    LIR* StoreBaseIndexed(RegStorage r_base, RegStorage r_index, RegStorage r_src, int scale,
-                          OpSize size) OVERRIDE;
-    LIR* GenAtomic64Load(RegStorage r_base, int displacement, RegStorage r_dest);
-    LIR* GenAtomic64Store(RegStorage r_base, int displacement, RegStorage r_src);
+  // Required for target - codegen utilities.
+  bool SmallLiteralDivRem(Instruction::Code dalvik_opcode, bool is_div, RegLocation rl_src,
+                          RegLocation rl_dest, int lit);
+  bool EasyMultiply(RegLocation rl_src, RegLocation rl_dest, int lit) OVERRIDE;
+  void GenMultiplyByConstantFloat(RegLocation rl_dest, RegLocation rl_src1, int32_t constant)
+  OVERRIDE;
+  void GenMultiplyByConstantDouble(RegLocation rl_dest, RegLocation rl_src1, int64_t constant)
+  OVERRIDE;
+  LIR* CheckSuspendUsingLoad() OVERRIDE;
+  RegStorage LoadHelper(QuickEntrypointEnum trampoline) OVERRIDE;
+  LIR* LoadBaseDisp(RegStorage r_base, int displacement, RegStorage r_dest, OpSize size,
+                    VolatileKind is_volatile) OVERRIDE;
+  LIR* LoadBaseIndexed(RegStorage r_base, RegStorage r_index, RegStorage r_dest, int scale,
+                       OpSize size) OVERRIDE;
+  LIR* LoadConstantNoClobber(RegStorage r_dest, int value);
+  LIR* LoadConstantWideNoClobber(RegStorage r_dest, int64_t value);
+  LIR* LoadConstantWide(RegStorage r_dest, int64_t value);
+  LIR* StoreBaseDisp(RegStorage r_base, int displacement, RegStorage r_src, OpSize size,
+                     VolatileKind is_volatile) OVERRIDE;
+  LIR* StoreBaseIndexed(RegStorage r_base, RegStorage r_index, RegStorage r_src, int scale,
+                        OpSize size) OVERRIDE;
+  LIR* GenAtomic64Load(RegStorage r_base, int displacement, RegStorage r_dest);
+  LIR* GenAtomic64Store(RegStorage r_base, int displacement, RegStorage r_src);
 
-    /// @copydoc Mir2Lir::UnconditionallyMarkGCCard(RegStorage)
-    void UnconditionallyMarkGCCard(RegStorage tgt_addr_reg) OVERRIDE;
+  /// @copydoc Mir2Lir::UnconditionallyMarkGCCard(RegStorage)
+  void UnconditionallyMarkGCCard(RegStorage tgt_addr_reg) OVERRIDE;
 
-    // Required for target - register utilities.
-    RegStorage Solo64ToPair64(RegStorage reg);
-    RegStorage Fp64ToSolo32(RegStorage reg);
-    RegStorage TargetReg(SpecialTargetRegister reg);
-    RegStorage TargetReg(SpecialTargetRegister reg, WideKind wide_kind) OVERRIDE;
-    RegLocation GetReturnAlt();
-    RegLocation GetReturnWideAlt();
-    RegLocation LocCReturn();
-    RegLocation LocCReturnRef();
-    RegLocation LocCReturnDouble();
-    RegLocation LocCReturnFloat();
-    RegLocation LocCReturnWide();
-    ResourceMask GetRegMaskCommon(const RegStorage& reg) const OVERRIDE;
-    void AdjustSpillMask();
-    void ClobberCallerSave();
-    void FreeCallTemps();
-    void LockCallTemps();
-    void CompilerInitializeRegAlloc();
+  // Required for target - register utilities.
+  RegStorage Solo64ToPair64(RegStorage reg);
+  RegStorage Fp64ToSolo32(RegStorage reg);
+  RegStorage TargetReg(SpecialTargetRegister reg);
+  RegStorage TargetReg(SpecialTargetRegister reg, WideKind wide_kind) OVERRIDE;
+  RegStorage TargetPtrReg(SpecialTargetRegister reg) OVERRIDE {
+    return TargetReg(reg, cu_->target64 ? kWide : kNotWide);
+  }
+  RegLocation GetReturnAlt();
+  RegLocation GetReturnWideAlt();
+  RegLocation LocCReturn();
+  RegLocation LocCReturnRef();
+  RegLocation LocCReturnDouble();
+  RegLocation LocCReturnFloat();
+  RegLocation LocCReturnWide();
+  ResourceMask GetRegMaskCommon(const RegStorage& reg) const OVERRIDE;
+  void AdjustSpillMask();
+  void ClobberCallerSave();
+  void FreeCallTemps();
+  void LockCallTemps();
+  void CompilerInitializeRegAlloc();
 
-    // Required for target - miscellaneous.
-    void AssembleLIR();
-    int AssignInsnOffsets();
-    void AssignOffsets();
-    AssemblerStatus AssembleInstructions(CodeOffset start_addr);
-    void DumpResourceMask(LIR* lir, const ResourceMask& mask, const char* prefix) OVERRIDE;
-    void SetupTargetResourceMasks(LIR* lir, uint64_t flags,
-                                  ResourceMask* use_mask, ResourceMask* def_mask) OVERRIDE;
-    const char* GetTargetInstFmt(int opcode);
-    const char* GetTargetInstName(int opcode);
-    std::string BuildInsnString(const char* fmt, LIR* lir, unsigned char* base_addr);
-    ResourceMask GetPCUseDefEncoding() const OVERRIDE;
-    uint64_t GetTargetInstFlags(int opcode);
-    size_t GetInsnSize(LIR* lir) OVERRIDE;
-    bool IsUnconditionalBranch(LIR* lir);
+  // Required for target - miscellaneous.
+  void AssembleLIR();
+  int AssignInsnOffsets();
+  void AssignOffsets();
+  AssemblerStatus AssembleInstructions(CodeOffset start_addr);
+  void DumpResourceMask(LIR* lir, const ResourceMask& mask, const char* prefix) OVERRIDE;
+  void SetupTargetResourceMasks(LIR* lir, uint64_t flags, ResourceMask* use_mask,
+                                ResourceMask* def_mask) OVERRIDE;
+  const char* GetTargetInstFmt(int opcode);
+  const char* GetTargetInstName(int opcode);
+  std::string BuildInsnString(const char* fmt, LIR* lir, unsigned char* base_addr);
+  ResourceMask GetPCUseDefEncoding() const OVERRIDE;
+  uint64_t GetTargetInstFlags(int opcode);
+  size_t GetInsnSize(LIR* lir) OVERRIDE;
+  bool IsUnconditionalBranch(LIR* lir);
 
-    // Get the register class for load/store of a field.
-    RegisterClass RegClassForFieldLoadStore(OpSize size, bool is_volatile) OVERRIDE;
+  // Get the register class for load/store of a field.
+  RegisterClass RegClassForFieldLoadStore(OpSize size, bool is_volatile) OVERRIDE;
 
-    // Required for target - Dalvik-level generators.
-    void GenArithImmOpLong(Instruction::Code opcode, RegLocation rl_dest,
-                           RegLocation rl_src1, RegLocation rl_src2, int flags);
-    void GenArrayGet(int opt_flags, OpSize size, RegLocation rl_array,
-                     RegLocation rl_index, RegLocation rl_dest, int scale);
-    void GenArrayPut(int opt_flags, OpSize size, RegLocation rl_array,
-                     RegLocation rl_index, RegLocation rl_src, int scale, bool card_mark);
-    void GenShiftImmOpLong(Instruction::Code opcode, RegLocation rl_dest, RegLocation rl_src1,
-                           RegLocation rl_shift, int flags);
-    void GenArithOpDouble(Instruction::Code opcode, RegLocation rl_dest, RegLocation rl_src1,
-                          RegLocation rl_src2);
-    void GenArithOpFloat(Instruction::Code opcode, RegLocation rl_dest, RegLocation rl_src1,
-                         RegLocation rl_src2);
-    void GenCmpFP(Instruction::Code opcode, RegLocation rl_dest, RegLocation rl_src1,
-                  RegLocation rl_src2);
-    void GenConversion(Instruction::Code opcode, RegLocation rl_dest, RegLocation rl_src);
-    bool GenInlinedAbsFloat(CallInfo* info) OVERRIDE;
-    bool GenInlinedAbsDouble(CallInfo* info) OVERRIDE;
-    bool GenInlinedCas(CallInfo* info, bool is_long, bool is_object);
-    bool GenInlinedMinMax(CallInfo* info, bool is_min, bool is_long);
-    bool GenInlinedSqrt(CallInfo* info);
-    bool GenInlinedPeek(CallInfo* info, OpSize size);
-    bool GenInlinedPoke(CallInfo* info, OpSize size);
-    void GenArithOpLong(Instruction::Code opcode, RegLocation rl_dest, RegLocation rl_src1,
-                        RegLocation rl_src2, int flags) OVERRIDE;
-    RegLocation GenDivRem(RegLocation rl_dest, RegStorage reg_lo, RegStorage reg_hi, bool is_div);
-    RegLocation GenDivRemLit(RegLocation rl_dest, RegStorage reg_lo, int lit, bool is_div);
-    void GenCmpLong(RegLocation rl_dest, RegLocation rl_src1, RegLocation rl_src2);
-    void GenDivZeroCheckWide(RegStorage reg);
-    void GenEntrySequence(RegLocation* ArgLocs, RegLocation rl_method);
-    void GenExitSequence();
-    void GenSpecialExitSequence() OVERRIDE;
-    void GenSpecialEntryForSuspend() OVERRIDE;
-    void GenSpecialExitForSuspend() OVERRIDE;
-    void GenFusedFPCmpBranch(BasicBlock* bb, MIR* mir, bool gt_bias, bool is_double);
-    void GenFusedLongCmpBranch(BasicBlock* bb, MIR* mir);
-    void GenSelect(BasicBlock* bb, MIR* mir);
-    void GenSelectConst32(RegStorage left_op, RegStorage right_op, ConditionCode code,
-                          int32_t true_val, int32_t false_val, RegStorage rs_dest,
-                          RegisterClass dest_reg_class) OVERRIDE;
-    bool GenMemBarrier(MemBarrierKind barrier_kind);
-    void GenMoveException(RegLocation rl_dest);
-    void GenMultiplyByTwoBitMultiplier(RegLocation rl_src, RegLocation rl_result, int lit,
-                                       int first_bit, int second_bit);
-    void GenNegDouble(RegLocation rl_dest, RegLocation rl_src);
-    void GenNegFloat(RegLocation rl_dest, RegLocation rl_src);
-    void GenLargePackedSwitch(MIR* mir, uint32_t table_offset, RegLocation rl_src);
-    void GenLargeSparseSwitch(MIR* mir, uint32_t table_offset, RegLocation rl_src);
-    bool GenSpecialCase(BasicBlock* bb, MIR* mir, const InlineMethod& special);
+  // Required for target - Dalvik-level generators.
+  void GenShiftOpLong(Instruction::Code opcode, RegLocation rl_dest, RegLocation rl_src1,
+                      RegLocation lr_shift);
+  void GenArithImmOpLong(Instruction::Code opcode, RegLocation rl_dest, RegLocation rl_src1,
+                         RegLocation rl_src2, int flags);
+  void GenArrayGet(int opt_flags, OpSize size, RegLocation rl_array, RegLocation rl_index,
+                   RegLocation rl_dest, int scale);
+  void GenArrayPut(int opt_flags, OpSize size, RegLocation rl_array, RegLocation rl_index,
+                   RegLocation rl_src, int scale, bool card_mark);
+  void GenShiftImmOpLong(Instruction::Code opcode, RegLocation rl_dest, RegLocation rl_src1,
+                         RegLocation rl_shift, int flags);
+  void GenArithOpDouble(Instruction::Code opcode, RegLocation rl_dest, RegLocation rl_src1,
+                        RegLocation rl_src2);
+  void GenArithOpFloat(Instruction::Code opcode, RegLocation rl_dest, RegLocation rl_src1,
+                       RegLocation rl_src2);
+  void GenCmpFP(Instruction::Code opcode, RegLocation rl_dest, RegLocation rl_src1,
+                RegLocation rl_src2);
+  void GenConversion(Instruction::Code opcode, RegLocation rl_dest, RegLocation rl_src);
+  bool GenInlinedAbsFloat(CallInfo* info) OVERRIDE;
+  bool GenInlinedAbsDouble(CallInfo* info) OVERRIDE;
+  bool GenInlinedCas(CallInfo* info, bool is_long, bool is_object);
+  bool GenInlinedMinMax(CallInfo* info, bool is_min, bool is_long);
+  bool GenInlinedSqrt(CallInfo* info);
+  bool GenInlinedPeek(CallInfo* info, OpSize size);
+  bool GenInlinedPoke(CallInfo* info, OpSize size);
+  void GenIntToLong(RegLocation rl_dest, RegLocation rl_src) OVERRIDE;
+  void GenArithOpLong(Instruction::Code opcode, RegLocation rl_dest, RegLocation rl_src1,
+                      RegLocation rl_src2, int flags) OVERRIDE;
+  RegLocation GenDivRem(RegLocation rl_dest, RegStorage reg_lo, RegStorage reg_hi, bool is_div);
+  RegLocation GenDivRemLit(RegLocation rl_dest, RegStorage reg_lo, int lit, bool is_div);
+  void GenCmpLong(RegLocation rl_dest, RegLocation rl_src1, RegLocation rl_src2);
+  void GenDivZeroCheckWide(RegStorage reg);
+  void GenEntrySequence(RegLocation* ArgLocs, RegLocation rl_method);
+  void GenExitSequence();
+  void GenSpecialExitSequence() OVERRIDE;
+  void GenSpecialEntryForSuspend() OVERRIDE;
+  void GenSpecialExitForSuspend() OVERRIDE;
+  void GenFusedFPCmpBranch(BasicBlock* bb, MIR* mir, bool gt_bias, bool is_double);
+  void GenFusedLongCmpBranch(BasicBlock* bb, MIR* mir);
+  void GenSelect(BasicBlock* bb, MIR* mir);
+  void GenSelectConst32(RegStorage left_op, RegStorage right_op, ConditionCode code,
+                        int32_t true_val, int32_t false_val, RegStorage rs_dest,
+                        RegisterClass dest_reg_class) OVERRIDE;
+  bool GenMemBarrier(MemBarrierKind barrier_kind);
+  void GenMoveException(RegLocation rl_dest);
+  void GenMultiplyByTwoBitMultiplier(RegLocation rl_src, RegLocation rl_result, int lit,
+                                     int first_bit, int second_bit);
+  void GenNegDouble(RegLocation rl_dest, RegLocation rl_src);
+  void GenNegFloat(RegLocation rl_dest, RegLocation rl_src);
+  void GenLargePackedSwitch(MIR* mir, uint32_t table_offset, RegLocation rl_src);
+  void GenLargeSparseSwitch(MIR* mir, uint32_t table_offset, RegLocation rl_src);
+  bool GenSpecialCase(BasicBlock* bb, MIR* mir, const InlineMethod& special);
 
-    // Required for target - single operation generators.
-    LIR* OpUnconditionalBranch(LIR* target);
-    LIR* OpCmpBranch(ConditionCode cond, RegStorage src1, RegStorage src2, LIR* target);
-    LIR* OpCmpImmBranch(ConditionCode cond, RegStorage reg, int check_value, LIR* target);
-    LIR* OpCondBranch(ConditionCode cc, LIR* target);
-    LIR* OpDecAndBranch(ConditionCode c_code, RegStorage reg, LIR* target);
-    LIR* OpFpRegCopy(RegStorage r_dest, RegStorage r_src);
-    LIR* OpIT(ConditionCode cond, const char* guide);
-    void OpEndIT(LIR* it);
-    LIR* OpMem(OpKind op, RegStorage r_base, int disp);
-    void OpPcRelLoad(RegStorage reg, LIR* target);
-    LIR* OpReg(OpKind op, RegStorage r_dest_src);
-    void OpRegCopy(RegStorage r_dest, RegStorage r_src);
-    LIR* OpRegCopyNoInsert(RegStorage r_dest, RegStorage r_src);
-    LIR* OpRegImm(OpKind op, RegStorage r_dest_src1, int value);
-    LIR* OpRegReg(OpKind op, RegStorage r_dest_src1, RegStorage r_src2);
-    LIR* OpMovRegMem(RegStorage r_dest, RegStorage r_base, int offset, MoveType move_type);
-    LIR* OpMovMemReg(RegStorage r_base, int offset, RegStorage r_src, MoveType move_type);
-    LIR* OpCondRegReg(OpKind op, ConditionCode cc, RegStorage r_dest, RegStorage r_src);
-    LIR* OpRegRegImm(OpKind op, RegStorage r_dest, RegStorage r_src1, int value);
-    LIR* OpRegRegReg(OpKind op, RegStorage r_dest, RegStorage r_src1, RegStorage r_src2);
-    LIR* OpTestSuspend(LIR* target);
-    LIR* OpVldm(RegStorage r_base, int count);
-    LIR* OpVstm(RegStorage r_base, int count);
-    void OpRegCopyWide(RegStorage dest, RegStorage src);
+  // Required for target - single operation generators.
+  LIR* OpUnconditionalBranch(LIR* target);
+  LIR* OpCmpBranch(ConditionCode cond, RegStorage src1, RegStorage src2, LIR* target);
+  LIR* OpCmpImmBranch(ConditionCode cond, RegStorage reg, int check_value, LIR* target);
+  LIR* OpCondBranch(ConditionCode cc, LIR* target);
+  LIR* OpDecAndBranch(ConditionCode c_code, RegStorage reg, LIR* target);
+  LIR* OpFpRegCopy(RegStorage r_dest, RegStorage r_src);
+  LIR* OpIT(ConditionCode cond, const char* guide);
+  void OpEndIT(LIR* it);
+  LIR* OpMem(OpKind op, RegStorage r_base, int disp);
+  void OpPcRelLoad(RegStorage reg, LIR* target);
+  LIR* OpReg(OpKind op, RegStorage r_dest_src);
+  void OpRegCopy(RegStorage r_dest, RegStorage r_src);
+  LIR* OpRegCopyNoInsert(RegStorage r_dest, RegStorage r_src);
+  LIR* OpRegImm(OpKind op, RegStorage r_dest_src1, int value);
+  LIR* OpRegReg(OpKind op, RegStorage r_dest_src1, RegStorage r_src2);
+  LIR* OpMovRegMem(RegStorage r_dest, RegStorage r_base, int offset, MoveType move_type);
+  LIR* OpMovMemReg(RegStorage r_base, int offset, RegStorage r_src, MoveType move_type);
+  LIR* OpCondRegReg(OpKind op, ConditionCode cc, RegStorage r_dest, RegStorage r_src);
+  LIR* OpRegRegImm(OpKind op, RegStorage r_dest, RegStorage r_src1, int value);
+  LIR* OpRegRegReg(OpKind op, RegStorage r_dest, RegStorage r_src1, RegStorage r_src2);
+  LIR* OpTestSuspend(LIR* target);
+  LIR* OpVldm(RegStorage r_base, int count);
+  LIR* OpVstm(RegStorage r_base, int count);
+  void OpRegCopyWide(RegStorage dest, RegStorage src);
 
-    // TODO: collapse r_dest.
-    LIR* LoadBaseDispBody(RegStorage r_base, int displacement, RegStorage r_dest,
-                          OpSize size);
-    // TODO: collapse r_src.
-    LIR* StoreBaseDispBody(RegStorage r_base, int displacement, RegStorage r_src,
-                           OpSize size);
-    void SpillCoreRegs();
-    void UnSpillCoreRegs();
-    static const MipsEncodingMap EncodingMap[kMipsLast];
-    bool InexpensiveConstantInt(int32_t value);
-    bool InexpensiveConstantFloat(int32_t value);
-    bool InexpensiveConstantLong(int64_t value);
-    bool InexpensiveConstantDouble(int64_t value);
+  // TODO: collapse r_dest.
+  LIR* LoadBaseDispBody(RegStorage r_base, int displacement, RegStorage r_dest, OpSize size);
+  // TODO: collapse r_src.
+  LIR* StoreBaseDispBody(RegStorage r_base, int displacement, RegStorage r_src, OpSize size);
+  void SpillCoreRegs();
+  void UnSpillCoreRegs();
+  static const MipsEncodingMap EncodingMap[kMipsLast];
+  bool InexpensiveConstantInt(int32_t value);
+  bool InexpensiveConstantFloat(int32_t value);
+  bool InexpensiveConstantLong(int64_t value);
+  bool InexpensiveConstantDouble(int64_t value);
 
-    bool WideGPRsAreAliases() const OVERRIDE {
-      return false;  // Wide GPRs are formed by pairing.
+  bool WideGPRsAreAliases() const OVERRIDE {
+    return cu_->target64;  // Wide GPRs are formed by pairing on mips32.
+  }
+  bool WideFPRsAreAliases() const OVERRIDE {
+    return cu_->target64;  // Wide FPRs are formed by pairing on mips32.
+  }
+
+  LIR* InvokeTrampoline(OpKind op, RegStorage r_tgt, QuickEntrypointEnum trampoline) OVERRIDE;
+
+  RegLocation GenDivRem(RegLocation rl_dest, RegLocation rl_src1, RegLocation rl_src2, bool is_div,
+                        int flags) OVERRIDE;
+  RegLocation GenDivRemLit(RegLocation rl_dest, RegLocation rl_src1, int lit, bool is_div) OVERRIDE;
+  NextCallInsn GetNextSDCallInsn() OVERRIDE;
+  LIR* GenCallInsn(const MirMethodLoweringInfo& method_info) OVERRIDE;
+
+  // Unimplemented intrinsics.
+  bool GenInlinedCharAt(CallInfo* info ATTRIBUTE_UNUSED) OVERRIDE {
+    return false;
+  }
+  bool GenInlinedAbsInt(CallInfo* info ATTRIBUTE_UNUSED) OVERRIDE {
+    return false;
+  }
+  bool GenInlinedAbsLong(CallInfo* info ATTRIBUTE_UNUSED) OVERRIDE {
+    return false;
+  }
+  bool GenInlinedIndexOf(CallInfo* info ATTRIBUTE_UNUSED, bool zero_based ATTRIBUTE_UNUSED)
+  OVERRIDE {
+    return false;
+  }
+
+  // True if isa is rev R6.
+  const bool isaIsR6_;
+
+  // True if floating point unit is 32bits.
+  const bool fpuIs32Bit_;
+
+ private:
+  void GenNegLong(RegLocation rl_dest, RegLocation rl_src);
+  void GenAddLong(RegLocation rl_dest, RegLocation rl_src1, RegLocation rl_src2);
+  void GenSubLong(RegLocation rl_dest, RegLocation rl_src1, RegLocation rl_src2);
+
+  void ConvertShortToLongBranch(LIR* lir);
+
+  // Mips64 specific long gen methods:
+  void GenLongOp(OpKind op, RegLocation rl_dest, RegLocation rl_src1, RegLocation rl_src2);
+  void GenNotLong(RegLocation rl_dest, RegLocation rl_src);
+  void GenMulLong(RegLocation rl_dest, RegLocation rl_src1, RegLocation rl_src2);
+  void GenDivRemLong(Instruction::Code opcode, RegLocation rl_dest, RegLocation rl_src1,
+                     RegLocation rl_src2, bool is_div, int flags);
+  void GenConversionCall(QuickEntrypointEnum trampoline, RegLocation rl_dest, RegLocation rl_src,
+                         RegisterClass reg_class);
+  RegStorage AllocPtrSizeTemp(bool required = true);
+
+  /**
+   * @param reg #RegStorage containing a Solo64 input register (e.g. @c a1 or @c d0).
+   * @return A Solo32 with the same register number as the @p reg (e.g. @c a1 or @c f0).
+   * @see As64BitReg
+   */
+  RegStorage As32BitReg(RegStorage reg) {
+    DCHECK(!reg.IsPair());
+    if ((kFailOnSizeError || kReportSizeError) && !reg.Is64Bit()) {
+      if (kFailOnSizeError) {
+        LOG(FATAL) << "Expected 64b register";
+      } else {
+        LOG(WARNING) << "Expected 64b register";
+        return reg;
+      }
     }
-    bool WideFPRsAreAliases() const OVERRIDE {
-      return false;  // Wide FPRs are formed by pairing.
+    RegStorage ret_val = RegStorage(RegStorage::k32BitSolo,
+                                    reg.GetRawBits() & RegStorage::kRegTypeMask);
+    DCHECK_EQ(GetRegInfo(reg)->FindMatchingView(RegisterInfo::k32SoloStorageMask)
+              ->GetReg().GetReg(),
+              ret_val.GetReg());
+    return ret_val;
+  }
+
+  /**
+   * @param reg #RegStorage containing a Solo32 input register (e.g. @c a1 or @c f0).
+   * @return A Solo64 with the same register number as the @p reg (e.g. @c a1 or @c d0).
+   */
+  RegStorage As64BitReg(RegStorage reg) {
+    DCHECK(!reg.IsPair());
+    if ((kFailOnSizeError || kReportSizeError) && !reg.Is32Bit()) {
+      if (kFailOnSizeError) {
+        LOG(FATAL) << "Expected 32b register";
+      } else {
+        LOG(WARNING) << "Expected 32b register";
+        return reg;
+      }
     }
+    RegStorage ret_val = RegStorage(RegStorage::k64BitSolo,
+                                    reg.GetRawBits() & RegStorage::kRegTypeMask);
+    DCHECK_EQ(GetRegInfo(reg)->FindMatchingView(RegisterInfo::k64SoloStorageMask)
+              ->GetReg().GetReg(),
+              ret_val.GetReg());
+    return ret_val;
+  }
 
-    LIR* InvokeTrampoline(OpKind op, RegStorage r_tgt, QuickEntrypointEnum trampoline) OVERRIDE;
-
-    RegLocation GenDivRem(RegLocation rl_dest, RegLocation rl_src1,
-                          RegLocation rl_src2, bool is_div, int flags) OVERRIDE;
-    RegLocation GenDivRemLit(RegLocation rl_dest, RegLocation rl_src1, int lit, bool is_div)
-        OVERRIDE;
-
-    NextCallInsn GetNextSDCallInsn() OVERRIDE;
-    LIR* GenCallInsn(const MirMethodLoweringInfo& method_info) OVERRIDE;
-
-    // Unimplemented intrinsics.
-    bool GenInlinedCharAt(CallInfo* info ATTRIBUTE_UNUSED) OVERRIDE {
-      return false;
+  RegStorage Check64BitReg(RegStorage reg) {
+    if ((kFailOnSizeError || kReportSizeError) && !reg.Is64Bit()) {
+      if (kFailOnSizeError) {
+        LOG(FATAL) << "Checked for 64b register";
+      } else {
+        LOG(WARNING) << "Checked for 64b register";
+        return As64BitReg(reg);
+      }
     }
-    bool GenInlinedAbsInt(CallInfo* info ATTRIBUTE_UNUSED) OVERRIDE {
-      return false;
-    }
-    bool GenInlinedAbsLong(CallInfo* info ATTRIBUTE_UNUSED) OVERRIDE {
-      return false;
-    }
-    bool GenInlinedIndexOf(CallInfo* info ATTRIBUTE_UNUSED, bool zero_based ATTRIBUTE_UNUSED)
-        OVERRIDE {
-      return false;
-    }
-
-    // True if isa is rev R6.
-    const bool isaIsR6_;
-
-    // True if floating point unit is 32bits.
-    const bool fpuIs32Bit_;
-
-  private:
-    void GenNegLong(RegLocation rl_dest, RegLocation rl_src);
-    void GenAddLong(Instruction::Code opcode, RegLocation rl_dest, RegLocation rl_src1,
-                    RegLocation rl_src2);
-    void GenSubLong(Instruction::Code opcode, RegLocation rl_dest, RegLocation rl_src1,
-                    RegLocation rl_src2);
-
-    void ConvertShortToLongBranch(LIR* lir);
+    return reg;
+  }
 };
 
 }  // namespace art
diff --git a/compiler/dex/quick/mips/fp_mips.cc b/compiler/dex/quick/mips/fp_mips.cc
index 37bf1a6..45fd1a9 100644
--- a/compiler/dex/quick/mips/fp_mips.cc
+++ b/compiler/dex/quick/mips/fp_mips.cc
@@ -23,8 +23,8 @@
 
 namespace art {
 
-void MipsMir2Lir::GenArithOpFloat(Instruction::Code opcode,
-                                  RegLocation rl_dest, RegLocation rl_src1, RegLocation rl_src2) {
+void MipsMir2Lir::GenArithOpFloat(Instruction::Code opcode, RegLocation rl_dest,
+                                  RegLocation rl_src1, RegLocation rl_src2) {
   int op = kMipsNop;
   RegLocation rl_result;
 
@@ -51,7 +51,7 @@
       break;
     case Instruction::REM_FLOAT_2ADDR:
     case Instruction::REM_FLOAT:
-      FlushAllRegs();   // Send everything to home location
+      FlushAllRegs();   // Send everything to home location.
       CallRuntimeHelperRegLocationRegLocation(kQuickFmodf, rl_src1, rl_src2, false);
       rl_result = GetReturn(kFPReg);
       StoreValue(rl_dest, rl_result);
@@ -69,8 +69,8 @@
   StoreValue(rl_dest, rl_result);
 }
 
-void MipsMir2Lir::GenArithOpDouble(Instruction::Code opcode,
-                                   RegLocation rl_dest, RegLocation rl_src1, RegLocation rl_src2) {
+void MipsMir2Lir::GenArithOpDouble(Instruction::Code opcode, RegLocation rl_dest,
+                                   RegLocation rl_src1, RegLocation rl_src2) {
   int op = kMipsNop;
   RegLocation rl_result;
 
@@ -93,7 +93,7 @@
       break;
     case Instruction::REM_DOUBLE_2ADDR:
     case Instruction::REM_DOUBLE:
-      FlushAllRegs();   // Send everything to home location
+      FlushAllRegs();   // Send everything to home location.
       CallRuntimeHelperRegLocationRegLocation(kQuickFmod, rl_src1, rl_src2, false);
       rl_result = GetReturnWide(kFPReg);
       StoreValueWide(rl_dest, rl_result);
@@ -147,22 +147,22 @@
       op = kMipsFcvtdw;
       break;
     case Instruction::FLOAT_TO_INT:
-      GenConversionCall(kQuickF2iz, rl_dest, rl_src);
+      GenConversionCall(kQuickF2iz, rl_dest, rl_src, kCoreReg);
       return;
     case Instruction::DOUBLE_TO_INT:
-      GenConversionCall(kQuickD2iz, rl_dest, rl_src);
+      GenConversionCall(kQuickD2iz, rl_dest, rl_src, kCoreReg);
       return;
     case Instruction::LONG_TO_DOUBLE:
-      GenConversionCall(kQuickL2d, rl_dest, rl_src);
+      GenConversionCall(kQuickL2d, rl_dest, rl_src, kFPReg);
       return;
     case Instruction::FLOAT_TO_LONG:
-      GenConversionCall(kQuickF2l, rl_dest, rl_src);
+      GenConversionCall(kQuickF2l, rl_dest, rl_src, kCoreReg);
       return;
     case Instruction::LONG_TO_FLOAT:
-      GenConversionCall(kQuickL2f, rl_dest, rl_src);
+      GenConversionCall(kQuickL2f, rl_dest, rl_src, kFPReg);
       return;
     case Instruction::DOUBLE_TO_LONG:
-      GenConversionCall(kQuickD2l, rl_dest, rl_src);
+      GenConversionCall(kQuickD2l, rl_dest, rl_src, kCoreReg);
       return;
     default:
       LOG(FATAL) << "Unexpected opcode: " << opcode;
@@ -189,24 +189,24 @@
   if (fpuIs32Bit) {
     switch (base) {
       case 0:
-        return RegStorage(RegStorage::k64BitPair, rMIPS_FARG0, rMIPS_FARG1);
+        return RegStorage(RegStorage::k64BitPair, rFARG0, rFARG1);
       case 2:
-        return RegStorage(RegStorage::k64BitPair, rMIPS_FARG2, rMIPS_FARG3);
+        return RegStorage(RegStorage::k64BitPair, rFARG2, rFARG3);
     }
   } else {
     switch (base) {
       case 0:
-        return RegStorage(RegStorage::k64BitSolo, rMIPS_FARG0);
+        return RegStorage(RegStorage::k64BitSolo, rFARG0);
       case 2:
-        return RegStorage(RegStorage::k64BitSolo, rMIPS_FARG2);
+        return RegStorage(RegStorage::k64BitSolo, rFARG2);
     }
   }
   LOG(FATAL) << "Unsupported Mips.GetWideFP: " << fpuIs32Bit << " " << base;
   UNREACHABLE();
 }
 
-void MipsMir2Lir::GenCmpFP(Instruction::Code opcode, RegLocation rl_dest,
-                           RegLocation rl_src1, RegLocation rl_src2) {
+void MipsMir2Lir::GenCmpFP(Instruction::Code opcode, RegLocation rl_dest, RegLocation rl_src1,
+                           RegLocation rl_src2) {
   bool wide = true;
   QuickEntrypointEnum target;
 
@@ -232,16 +232,23 @@
   FlushAllRegs();
   LockCallTemps();
   if (wide) {
-    RegStorage r_tmp1 = GetWideArgFP(fpuIs32Bit_, 0);
-    RegStorage r_tmp2 = GetWideArgFP(fpuIs32Bit_, 2);
+    RegStorage r_tmp1;
+    RegStorage r_tmp2;
+    if (cu_->target64) {
+      r_tmp1 = RegStorage(RegStorage::k64BitSolo, rFARG0);
+      r_tmp2 = RegStorage(RegStorage::k64BitSolo, rFARG1);
+    } else {
+      r_tmp1 = GetWideArgFP(fpuIs32Bit_, 0);
+      r_tmp2 = GetWideArgFP(fpuIs32Bit_, 2);
+    }
     LoadValueDirectWideFixed(rl_src1, r_tmp1);
     LoadValueDirectWideFixed(rl_src2, r_tmp2);
   } else {
-    LoadValueDirectFixed(rl_src1, rs_rMIPS_FARG0);
-    LoadValueDirectFixed(rl_src2, rs_rMIPS_FARG2);
+    LoadValueDirectFixed(rl_src1, rs_rFARG0);
+    LoadValueDirectFixed(rl_src2, cu_->target64 ? rs_rFARG1 : rs_rFARG2);
   }
   RegStorage r_tgt = LoadHelper(target);
-  // NOTE: not a safepoint
+  // NOTE: not a safepoint.
   OpReg(kOpBlx, r_tgt);
   RegLocation rl_result = GetReturn(kCoreReg);
   StoreValue(rl_dest, rl_result);
@@ -254,18 +261,30 @@
 
 void MipsMir2Lir::GenNegFloat(RegLocation rl_dest, RegLocation rl_src) {
   RegLocation rl_result;
-  rl_src = LoadValue(rl_src, kCoreReg);
-  rl_result = EvalLoc(rl_dest, kCoreReg, true);
-  OpRegRegImm(kOpAdd, rl_result.reg, rl_src.reg, 0x80000000);
+  if (cu_->target64) {
+    rl_src = LoadValue(rl_src, kFPReg);
+    rl_result = EvalLoc(rl_dest, kFPReg, true);
+    NewLIR2(kMipsFnegs, rl_result.reg.GetReg(), rl_src.reg.GetReg());
+  } else {
+    rl_src = LoadValue(rl_src, kCoreReg);
+    rl_result = EvalLoc(rl_dest, kCoreReg, true);
+    OpRegRegImm(kOpAdd, rl_result.reg, rl_src.reg, 0x80000000);
+  }
   StoreValue(rl_dest, rl_result);
 }
 
 void MipsMir2Lir::GenNegDouble(RegLocation rl_dest, RegLocation rl_src) {
   RegLocation rl_result;
-  rl_src = LoadValueWide(rl_src, kCoreReg);
-  rl_result = EvalLoc(rl_dest, kCoreReg, true);
-  OpRegRegImm(kOpAdd, rl_result.reg.GetHigh(), rl_src.reg.GetHigh(), 0x80000000);
-  OpRegCopy(rl_result.reg, rl_src.reg);
+  if (cu_->target64) {
+    rl_src = LoadValueWide(rl_src, kFPReg);
+    rl_result = EvalLocWide(rl_dest, kFPReg, true);
+    NewLIR2(kMipsFnegd, rl_result.reg.GetReg(), rl_src.reg.GetReg());
+  } else {
+    rl_src = LoadValueWide(rl_src, kCoreReg);
+    rl_result = EvalLoc(rl_dest, kCoreReg, true);
+    OpRegRegImm(kOpAdd, rl_result.reg.GetHigh(), rl_src.reg.GetHigh(), 0x80000000);
+    OpRegCopy(rl_result.reg, rl_src.reg);
+  }
   StoreValueWide(rl_dest, rl_result);
 }
 
diff --git a/compiler/dex/quick/mips/int_mips.cc b/compiler/dex/quick/mips/int_mips.cc
index 8093c97..626b36e 100644
--- a/compiler/dex/quick/mips/int_mips.cc
+++ b/compiler/dex/quick/mips/int_mips.cc
@@ -34,6 +34,7 @@
  *    x < y     return -1
  *    x > y     return  1
  *
+ * Mips32 implementation
  *    slt   t0,  x.hi, y.hi;        # (x.hi < y.hi) ? 1:0
  *    sgt   t1,  x.hi, y.hi;        # (y.hi > x.hi) ? 1:0
  *    subu  res, t0, t1             # res = -1:1:0 for [ < > = ]
@@ -43,26 +44,40 @@
  *    subu  res, t0, t1
  * finish:
  *
+ * Mips64 implementation
+ *    slt   temp, x, y;             # (x < y) ? 1:0
+ *    slt   res, y, x;              # (x > y) ? 1:0
+ *    subu  res, res, temp;         # res = -1:1:0 for [ < > = ]
+ *
  */
-void MipsMir2Lir::GenCmpLong(RegLocation rl_dest, RegLocation rl_src1,
-                             RegLocation rl_src2) {
+void MipsMir2Lir::GenCmpLong(RegLocation rl_dest, RegLocation rl_src1, RegLocation rl_src2) {
   rl_src1 = LoadValueWide(rl_src1, kCoreReg);
   rl_src2 = LoadValueWide(rl_src2, kCoreReg);
-  RegStorage t0 = AllocTemp();
-  RegStorage t1 = AllocTemp();
-  RegLocation rl_result = EvalLoc(rl_dest, kCoreReg, true);
-  NewLIR3(kMipsSlt, t0.GetReg(), rl_src1.reg.GetHighReg(), rl_src2.reg.GetHighReg());
-  NewLIR3(kMipsSlt, t1.GetReg(), rl_src2.reg.GetHighReg(), rl_src1.reg.GetHighReg());
-  NewLIR3(kMipsSubu, rl_result.reg.GetReg(), t1.GetReg(), t0.GetReg());
-  LIR* branch = OpCmpImmBranch(kCondNe, rl_result.reg, 0, NULL);
-  NewLIR3(kMipsSltu, t0.GetReg(), rl_src1.reg.GetLowReg(), rl_src2.reg.GetLowReg());
-  NewLIR3(kMipsSltu, t1.GetReg(), rl_src2.reg.GetLowReg(), rl_src1.reg.GetLowReg());
-  NewLIR3(kMipsSubu, rl_result.reg.GetReg(), t1.GetReg(), t0.GetReg());
-  FreeTemp(t0);
-  FreeTemp(t1);
-  LIR* target = NewLIR0(kPseudoTargetLabel);
-  branch->target = target;
-  StoreValue(rl_dest, rl_result);
+  if (cu_->target64) {
+    RegStorage temp = AllocTempWide();
+    RegLocation rl_result = EvalLoc(rl_dest, kCoreReg, true);
+    NewLIR3(kMipsSlt, temp.GetReg(), rl_src1.reg.GetReg(), rl_src2.reg.GetReg());
+    NewLIR3(kMipsSlt, rl_result.reg.GetReg(), rl_src2.reg.GetReg(), rl_src1.reg.GetReg());
+    NewLIR3(kMipsSubu, rl_result.reg.GetReg(), rl_result.reg.GetReg(), temp.GetReg());
+    FreeTemp(temp);
+    StoreValue(rl_dest, rl_result);
+  } else {
+    RegStorage t0 = AllocTemp();
+    RegStorage t1 = AllocTemp();
+    RegLocation rl_result = EvalLoc(rl_dest, kCoreReg, true);
+    NewLIR3(kMipsSlt, t0.GetReg(), rl_src1.reg.GetHighReg(), rl_src2.reg.GetHighReg());
+    NewLIR3(kMipsSlt, t1.GetReg(), rl_src2.reg.GetHighReg(), rl_src1.reg.GetHighReg());
+    NewLIR3(kMipsSubu, rl_result.reg.GetReg(), t1.GetReg(), t0.GetReg());
+    LIR* branch = OpCmpImmBranch(kCondNe, rl_result.reg, 0, NULL);
+    NewLIR3(kMipsSltu, t0.GetReg(), rl_src1.reg.GetLowReg(), rl_src2.reg.GetLowReg());
+    NewLIR3(kMipsSltu, t1.GetReg(), rl_src2.reg.GetLowReg(), rl_src1.reg.GetLowReg());
+    NewLIR3(kMipsSubu, rl_result.reg.GetReg(), t1.GetReg(), t0.GetReg());
+    FreeTemp(t0);
+    FreeTemp(t1);
+    LIR* target = NewLIR0(kPseudoTargetLabel);
+    branch->target = target;
+    StoreValue(rl_dest, rl_result);
+  }
 }
 
 LIR* MipsMir2Lir::OpCmpBranch(ConditionCode cond, RegStorage src1, RegStorage src2, LIR* target) {
@@ -134,7 +149,7 @@
 LIR* MipsMir2Lir::OpCmpImmBranch(ConditionCode cond, RegStorage reg, int check_value, LIR* target) {
   LIR* branch;
   if (check_value != 0) {
-    // TUNING: handle s16 & kCondLt/Mi case using slti
+    // TUNING: handle s16 & kCondLt/Mi case using slti.
     RegStorage t_reg = AllocTemp();
     LoadConstant(t_reg, check_value);
     branch = OpCmpBranch(cond, reg, t_reg, target);
@@ -164,17 +179,34 @@
 }
 
 LIR* MipsMir2Lir::OpRegCopyNoInsert(RegStorage r_dest, RegStorage r_src) {
-  // If src or dest is a pair, we'll be using low reg.
-  if (r_dest.IsPair()) {
-    r_dest = r_dest.GetLow();
+  LIR* res;
+  MipsOpCode opcode;
+
+  if (!cu_->target64) {
+    // If src or dest is a pair, we'll be using low reg.
+    if (r_dest.IsPair()) {
+      r_dest = r_dest.GetLow();
+    }
+    if (r_src.IsPair()) {
+      r_src = r_src.GetLow();
+    }
+  } else {
+    DCHECK(!r_dest.IsPair() && !r_src.IsPair());
   }
-  if (r_src.IsPair()) {
-    r_src = r_src.GetLow();
-  }
+
   if (r_dest.IsFloat() || r_src.IsFloat())
     return OpFpRegCopy(r_dest, r_src);
-  LIR* res = RawLIR(current_dalvik_offset_, kMipsMove,
-                    r_dest.GetReg(), r_src.GetReg());
+  if (cu_->target64) {
+    // TODO: Check that r_src and r_dest are both 32 or both 64 bits length on Mips64.
+    if (r_dest.Is64Bit() || r_src.Is64Bit()) {
+      opcode = kMipsMove;
+    } else {
+      opcode = kMipsSll;
+    }
+  } else {
+    opcode = kMipsMove;
+  }
+  res = RawLIR(current_dalvik_offset_, opcode, r_dest.GetReg(), r_src.GetReg());
   if (!(cu_->disable_opt & (1 << kSafeOptimizations)) && r_dest == r_src) {
     res->flags.is_nop = true;
   }
@@ -189,6 +221,10 @@
 }
 
 void MipsMir2Lir::OpRegCopyWide(RegStorage r_dest, RegStorage r_src) {
+  if (cu_->target64) {
+    OpRegCopy(r_dest, r_src);
+    return;
+  }
   if (r_dest != r_src) {
     bool dest_fp = r_dest.IsFloat();
     bool src_fp = r_src.IsFloat();
@@ -213,16 +249,16 @@
       if (src_fp) {
         // Here if dest is core reg and src is fp reg.
         if (fpuIs32Bit_) {
-            NewLIR2(kMipsMfc1, r_dest.GetLowReg(), r_src.GetLowReg());
-            NewLIR2(kMipsMfc1, r_dest.GetHighReg(), r_src.GetHighReg());
+          NewLIR2(kMipsMfc1, r_dest.GetLowReg(), r_src.GetLowReg());
+          NewLIR2(kMipsMfc1, r_dest.GetHighReg(), r_src.GetHighReg());
         } else {
-            r_src = Fp64ToSolo32(r_src);
-            NewLIR2(kMipsMfc1, r_dest.GetLowReg(), r_src.GetReg());
-            NewLIR2(kMipsMfhc1, r_dest.GetHighReg(), r_src.GetReg());
+          r_src = Fp64ToSolo32(r_src);
+          NewLIR2(kMipsMfc1, r_dest.GetLowReg(), r_src.GetReg());
+          NewLIR2(kMipsMfhc1, r_dest.GetHighReg(), r_src.GetReg());
         }
       } else {
         // Here if both src and dest are core registers.
-        // Handle overlap
+        // Handle overlap.
         if (r_src.GetHighReg() == r_dest.GetLowReg()) {
           OpRegCopy(r_dest.GetHigh(), r_src.GetHigh());
           OpRegCopy(r_dest.GetLow(), r_src.GetLow());
@@ -263,17 +299,15 @@
   RegLocation rl_result = EvalLoc(rl_dest, kCoreReg, true);
 
   if (isaIsR6_) {
-      NewLIR3(is_div ? kMipsR6Div : kMipsR6Mod,
-          rl_result.reg.GetReg(), reg1.GetReg(), reg2.GetReg());
+    NewLIR3(is_div ? kMipsR6Div : kMipsR6Mod, rl_result.reg.GetReg(), reg1.GetReg(), reg2.GetReg());
   } else {
-      NewLIR2(kMipsDiv, reg1.GetReg(), reg2.GetReg());
-      NewLIR1(is_div ? kMipsMflo : kMipsMfhi, rl_result.reg.GetReg());
+    NewLIR2(kMipsR2Div, reg1.GetReg(), reg2.GetReg());
+    NewLIR1(is_div ? kMipsR2Mflo : kMipsR2Mfhi, rl_result.reg.GetReg());
   }
   return rl_result;
 }
 
-RegLocation MipsMir2Lir::GenDivRemLit(RegLocation rl_dest, RegStorage reg1, int lit,
-                                      bool is_div) {
+RegLocation MipsMir2Lir::GenDivRemLit(RegLocation rl_dest, RegStorage reg1, int lit, bool is_div) {
   RegStorage t_reg = AllocTemp();
   NewLIR3(kMipsAddiu, t_reg.GetReg(), rZERO, lit);
   RegLocation rl_result = GenDivRem(rl_dest, reg1, t_reg, is_div);
@@ -322,10 +356,17 @@
     // MIPS supports only aligned access. Defer unaligned access to JNI implementation.
     return false;
   }
-  RegLocation rl_src_address = info->args[0];  // long address
-  rl_src_address = NarrowRegLoc(rl_src_address);  // ignore high half in info->args[1]
+  RegLocation rl_src_address = info->args[0];       // Long address.
+  if (!cu_->target64) {
+    rl_src_address = NarrowRegLoc(rl_src_address);  // Ignore high half in info->args[1].
+  }
   RegLocation rl_dest = InlineTarget(info);
-  RegLocation rl_address = LoadValue(rl_src_address, kCoreReg);
+  RegLocation rl_address;
+  if (cu_->target64) {
+    rl_address = LoadValueWide(rl_src_address, kCoreReg);
+  } else {
+    rl_address = LoadValue(rl_src_address, kCoreReg);
+  }
   RegLocation rl_result = EvalLoc(rl_dest, kCoreReg, true);
   DCHECK(size == kSignedByte);
   LoadBaseDisp(rl_address.reg, 0, rl_result.reg, size, kNotVolatile);
@@ -338,10 +379,17 @@
     // MIPS supports only aligned access. Defer unaligned access to JNI implementation.
     return false;
   }
-  RegLocation rl_src_address = info->args[0];  // long address
-  rl_src_address = NarrowRegLoc(rl_src_address);  // ignore high half in info->args[1]
-  RegLocation rl_src_value = info->args[2];  // [size] value
-  RegLocation rl_address = LoadValue(rl_src_address, kCoreReg);
+  RegLocation rl_src_address = info->args[0];       // Long address.
+  if (!cu_->target64) {
+    rl_src_address = NarrowRegLoc(rl_src_address);  // Ignore high half in info->args[1].
+  }
+  RegLocation rl_src_value = info->args[2];         // [size] value.
+  RegLocation rl_address;
+  if (cu_->target64) {
+    rl_address = LoadValueWide(rl_src_address, kCoreReg);
+  } else {
+    rl_address = LoadValue(rl_src_address, kCoreReg);
+  }
   DCHECK(size == kSignedByte);
   RegLocation rl_value = LoadValue(rl_src_value, kCoreReg);
   StoreBaseDisp(rl_address.reg, 0, rl_value.reg, size, kNotVolatile);
@@ -366,8 +414,7 @@
   UNREACHABLE();
 }
 
-void MipsMir2Lir::GenMultiplyByTwoBitMultiplier(RegLocation rl_src,
-                                                RegLocation rl_result, int lit,
+void MipsMir2Lir::GenMultiplyByTwoBitMultiplier(RegLocation rl_src, RegLocation rl_result, int lit,
                                                 int first_bit, int second_bit) {
   UNUSED(lit);
   RegStorage t_reg = AllocTemp();
@@ -380,20 +427,24 @@
 }
 
 void MipsMir2Lir::GenDivZeroCheckWide(RegStorage reg) {
-  DCHECK(reg.IsPair());   // TODO: support k64BitSolo.
-  RegStorage t_reg = AllocTemp();
-  OpRegRegReg(kOpOr, t_reg, reg.GetLow(), reg.GetHigh());
-  GenDivZeroCheck(t_reg);
-  FreeTemp(t_reg);
+  if (cu_->target64) {
+    GenDivZeroCheck(reg);
+  } else {
+    DCHECK(reg.IsPair());   // TODO: support k64BitSolo.
+    RegStorage t_reg = AllocTemp();
+    OpRegRegReg(kOpOr, t_reg, reg.GetLow(), reg.GetHigh());
+    GenDivZeroCheck(t_reg);
+    FreeTemp(t_reg);
+  }
 }
 
-// Test suspend flag, return target of taken suspend branch
+// Test suspend flag, return target of taken suspend branch.
 LIR* MipsMir2Lir::OpTestSuspend(LIR* target) {
-  OpRegImm(kOpSub, rs_rMIPS_SUSPEND, 1);
-  return OpCmpImmBranch((target == NULL) ? kCondEq : kCondNe, rs_rMIPS_SUSPEND, 0, target);
+  OpRegImm(kOpSub, TargetPtrReg(kSuspend), 1);
+  return OpCmpImmBranch((target == NULL) ? kCondEq : kCondNe, TargetPtrReg(kSuspend), 0, target);
 }
 
-// Decrement register and branch on condition
+// Decrement register and branch on condition.
 LIR* MipsMir2Lir::OpDecAndBranch(ConditionCode c_code, RegStorage reg, LIR* target) {
   OpRegImm(kOpSub, reg, 1);
   return OpCmpImmBranch(c_code, reg, 0, target);
@@ -423,9 +474,7 @@
   LOG(FATAL) << "Unexpected use of OpEndIT in Mips";
 }
 
-void MipsMir2Lir::GenAddLong(Instruction::Code opcode, RegLocation rl_dest,
-                             RegLocation rl_src1, RegLocation rl_src2) {
-  UNUSED(opcode);
+void MipsMir2Lir::GenAddLong(RegLocation rl_dest, RegLocation rl_src1, RegLocation rl_src2) {
   rl_src1 = LoadValueWide(rl_src1, kCoreReg);
   rl_src2 = LoadValueWide(rl_src2, kCoreReg);
   RegLocation rl_result = EvalLoc(rl_dest, kCoreReg, true);
@@ -440,15 +489,14 @@
   OpRegRegReg(kOpAdd, rl_result.reg.GetLow(), rl_src2.reg.GetLow(), rl_src1.reg.GetLow());
   RegStorage t_reg = AllocTemp();
   OpRegRegReg(kOpAdd, t_reg, rl_src2.reg.GetHigh(), rl_src1.reg.GetHigh());
-  NewLIR3(kMipsSltu, rl_result.reg.GetHighReg(), rl_result.reg.GetLowReg(), rl_src2.reg.GetLowReg());
+  NewLIR3(kMipsSltu, rl_result.reg.GetHighReg(), rl_result.reg.GetLowReg(),
+          rl_src2.reg.GetLowReg());
   OpRegRegReg(kOpAdd, rl_result.reg.GetHigh(), rl_result.reg.GetHigh(), t_reg);
   FreeTemp(t_reg);
   StoreValueWide(rl_dest, rl_result);
 }
 
-void MipsMir2Lir::GenSubLong(Instruction::Code opcode, RegLocation rl_dest,
-                             RegLocation rl_src1, RegLocation rl_src2) {
-  UNUSED(opcode);
+void MipsMir2Lir::GenSubLong(RegLocation rl_dest, RegLocation rl_src1, RegLocation rl_src2) {
   rl_src1 = LoadValueWide(rl_src1, kCoreReg);
   rl_src2 = LoadValueWide(rl_src2, kCoreReg);
   RegLocation rl_result = EvalLoc(rl_dest, kCoreReg, true);
@@ -471,45 +519,134 @@
 
 void MipsMir2Lir::GenArithOpLong(Instruction::Code opcode, RegLocation rl_dest, RegLocation rl_src1,
                                  RegLocation rl_src2, int flags) {
-  switch (opcode) {
-    case Instruction::ADD_LONG:
-    case Instruction::ADD_LONG_2ADDR:
-      GenAddLong(opcode, rl_dest, rl_src1, rl_src2);
-      return;
-    case Instruction::SUB_LONG:
-    case Instruction::SUB_LONG_2ADDR:
-      GenSubLong(opcode, rl_dest, rl_src1, rl_src2);
-      return;
-    case Instruction::NEG_LONG:
-      GenNegLong(rl_dest, rl_src2);
-      return;
+  if (cu_->target64) {
+    switch (opcode) {
+      case Instruction::NOT_LONG:
+        GenNotLong(rl_dest, rl_src2);
+        return;
+      case Instruction::ADD_LONG:
+      case Instruction::ADD_LONG_2ADDR:
+        GenLongOp(kOpAdd, rl_dest, rl_src1, rl_src2);
+        return;
+      case Instruction::SUB_LONG:
+      case Instruction::SUB_LONG_2ADDR:
+        GenLongOp(kOpSub, rl_dest, rl_src1, rl_src2);
+        return;
+      case Instruction::MUL_LONG:
+      case Instruction::MUL_LONG_2ADDR:
+        GenMulLong(rl_dest, rl_src1, rl_src2);
+        return;
+      case Instruction::DIV_LONG:
+      case Instruction::DIV_LONG_2ADDR:
+        GenDivRemLong(opcode, rl_dest, rl_src1, rl_src2, /*is_div*/ true, flags);
+        return;
+      case Instruction::REM_LONG:
+      case Instruction::REM_LONG_2ADDR:
+        GenDivRemLong(opcode, rl_dest, rl_src1, rl_src2, /*is_div*/ false, flags);
+        return;
+      case Instruction::AND_LONG:
+      case Instruction::AND_LONG_2ADDR:
+        GenLongOp(kOpAnd, rl_dest, rl_src1, rl_src2);
+        return;
+      case Instruction::OR_LONG:
+      case Instruction::OR_LONG_2ADDR:
+        GenLongOp(kOpOr, rl_dest, rl_src1, rl_src2);
+        return;
+      case Instruction::XOR_LONG:
+      case Instruction::XOR_LONG_2ADDR:
+        GenLongOp(kOpXor, rl_dest, rl_src1, rl_src2);
+        return;
+      case Instruction::NEG_LONG:
+        GenNegLong(rl_dest, rl_src2);
+        return;
 
-    default:
-      break;
+      default:
+        LOG(FATAL) << "Invalid long arith op";
+        return;
+    }
+  } else {
+    switch (opcode) {
+      case Instruction::ADD_LONG:
+      case Instruction::ADD_LONG_2ADDR:
+        GenAddLong(rl_dest, rl_src1, rl_src2);
+        return;
+      case Instruction::SUB_LONG:
+      case Instruction::SUB_LONG_2ADDR:
+        GenSubLong(rl_dest, rl_src1, rl_src2);
+        return;
+      case Instruction::NEG_LONG:
+        GenNegLong(rl_dest, rl_src2);
+        return;
+      default:
+        break;
+    }
+    // Fallback for all other ops.
+    Mir2Lir::GenArithOpLong(opcode, rl_dest, rl_src1, rl_src2, flags);
   }
+}
 
-  // Fallback for all other ops.
-  Mir2Lir::GenArithOpLong(opcode, rl_dest, rl_src1, rl_src2, flags);
+void MipsMir2Lir::GenLongOp(OpKind op, RegLocation rl_dest, RegLocation rl_src1,
+                            RegLocation rl_src2) {
+  rl_src1 = LoadValueWide(rl_src1, kCoreReg);
+  rl_src2 = LoadValueWide(rl_src2, kCoreReg);
+  RegLocation rl_result = EvalLocWide(rl_dest, kCoreReg, true);
+  OpRegRegReg(op, rl_result.reg, rl_src1.reg, rl_src2.reg);
+  StoreValueWide(rl_dest, rl_result);
+}
+
+void MipsMir2Lir::GenNotLong(RegLocation rl_dest, RegLocation rl_src) {
+  rl_src = LoadValueWide(rl_src, kCoreReg);
+  RegLocation rl_result = EvalLocWide(rl_dest, kCoreReg, true);
+  OpRegReg(kOpMvn, rl_result.reg, rl_src.reg);
+  StoreValueWide(rl_dest, rl_result);
+}
+
+void MipsMir2Lir::GenMulLong(RegLocation rl_dest, RegLocation rl_src1, RegLocation rl_src2) {
+  rl_src1 = LoadValueWide(rl_src1, kCoreReg);
+  rl_src2 = LoadValueWide(rl_src2, kCoreReg);
+  RegLocation rl_result = EvalLocWide(rl_dest, kCoreReg, true);
+  NewLIR3(kMips64Dmul, rl_result.reg.GetReg(), rl_src1.reg.GetReg(), rl_src2.reg.GetReg());
+  StoreValueWide(rl_dest, rl_result);
+}
+
+void MipsMir2Lir::GenDivRemLong(Instruction::Code opcode, RegLocation rl_dest, RegLocation rl_src1,
+                                RegLocation rl_src2, bool is_div, int flags) {
+  UNUSED(opcode);
+  // TODO: Implement easy div/rem?
+  rl_src1 = LoadValueWide(rl_src1, kCoreReg);
+  rl_src2 = LoadValueWide(rl_src2, kCoreReg);
+  if ((flags & MIR_IGNORE_DIV_ZERO_CHECK) == 0) {
+    GenDivZeroCheckWide(rl_src2.reg);
+  }
+  RegLocation rl_result = EvalLocWide(rl_dest, kCoreReg, true);
+  NewLIR3(is_div ? kMips64Ddiv : kMips64Dmod, rl_result.reg.GetReg(), rl_src1.reg.GetReg(),
+          rl_src2.reg.GetReg());
+  StoreValueWide(rl_dest, rl_result);
 }
 
 void MipsMir2Lir::GenNegLong(RegLocation rl_dest, RegLocation rl_src) {
   rl_src = LoadValueWide(rl_src, kCoreReg);
-  RegLocation rl_result = EvalLoc(rl_dest, kCoreReg, true);
-  /*
-   *  [v1 v0] =  -[a1 a0]
-   *  negu  v0,a0
-   *  negu  v1,a1
-   *  sltu  t1,r_zero
-   *  subu  v1,v1,t1
-   */
+  RegLocation rl_result;
 
-  OpRegReg(kOpNeg, rl_result.reg.GetLow(), rl_src.reg.GetLow());
-  OpRegReg(kOpNeg, rl_result.reg.GetHigh(), rl_src.reg.GetHigh());
-  RegStorage t_reg = AllocTemp();
-  NewLIR3(kMipsSltu, t_reg.GetReg(), rZERO, rl_result.reg.GetLowReg());
-  OpRegRegReg(kOpSub, rl_result.reg.GetHigh(), rl_result.reg.GetHigh(), t_reg);
-  FreeTemp(t_reg);
-  StoreValueWide(rl_dest, rl_result);
+  if (cu_->target64) {
+    rl_result = EvalLocWide(rl_dest, kCoreReg, true);
+    OpRegReg(kOpNeg, rl_result.reg, rl_src.reg);
+    StoreValueWide(rl_dest, rl_result);
+  } else {
+    rl_result = EvalLoc(rl_dest, kCoreReg, true);
+    //  [v1 v0] =  -[a1 a0]
+    //  negu  v0,a0
+    //  negu  v1,a1
+    //  sltu  t1,r_zero
+    //  subu  v1,v1,t1
+    OpRegReg(kOpNeg, rl_result.reg.GetLow(), rl_src.reg.GetLow());
+    OpRegReg(kOpNeg, rl_result.reg.GetHigh(), rl_src.reg.GetHigh());
+    RegStorage t_reg = AllocTemp();
+    NewLIR3(kMipsSltu, t_reg.GetReg(), rZERO, rl_result.reg.GetLowReg());
+    OpRegRegReg(kOpSub, rl_result.reg.GetHigh(), rl_result.reg.GetHigh(), t_reg);
+    FreeTemp(t_reg);
+    StoreValueWide(rl_dest, rl_result);
+  }
 }
 
 /*
@@ -532,18 +669,18 @@
     data_offset = mirror::Array::DataOffset(sizeof(int32_t)).Int32Value();
   }
 
-  /* null object? */
+  // Null object?
   GenNullCheck(rl_array.reg, opt_flags);
 
-  RegStorage reg_ptr = AllocTemp();
+  RegStorage reg_ptr = (cu_->target64) ? AllocTempRef() : AllocTemp();
   bool needs_range_check = (!(opt_flags & MIR_IGNORE_RANGE_CHECK));
   RegStorage reg_len;
   if (needs_range_check) {
     reg_len = AllocTemp();
-    /* Get len */
+    // Get len.
     Load32Disp(rl_array.reg, len_offset, reg_len);
   }
-  /* reg_ptr -> array data */
+  // reg_ptr -> array data.
   OpRegRegImm(kOpAdd, reg_ptr, rl_array.reg, data_offset);
   FreeTemp(rl_array.reg);
   if ((size == k64) || (size == kDouble)) {
@@ -573,7 +710,17 @@
       GenArrayBoundsCheck(rl_index.reg, reg_len);
       FreeTemp(reg_len);
     }
-    LoadBaseIndexed(reg_ptr, rl_index.reg, rl_result.reg, scale, size);
+
+    if (cu_->target64) {
+      if (rl_result.ref) {
+        LoadBaseIndexed(reg_ptr, As64BitReg(rl_index.reg), As32BitReg(rl_result.reg), scale,
+                        kReference);
+      } else {
+        LoadBaseIndexed(reg_ptr, As64BitReg(rl_index.reg), rl_result.reg, scale, size);
+      }
+    } else {
+      LoadBaseIndexed(reg_ptr, rl_index.reg, rl_result.reg, scale, size);
+    }
 
     FreeTemp(reg_ptr);
     StoreValue(rl_dest, rl_result);
@@ -612,7 +759,7 @@
     allocated_reg_ptr_temp = true;
   }
 
-  /* null object? */
+  // Null object?
   GenNullCheck(rl_array.reg, opt_flags);
 
   bool needs_range_check = (!(opt_flags & MIR_IGNORE_RANGE_CHECK));
@@ -620,14 +767,14 @@
   if (needs_range_check) {
     reg_len = AllocTemp();
     // NOTE: max live temps(4) here.
-    /* Get len */
+    // Get len.
     Load32Disp(rl_array.reg, len_offset, reg_len);
   }
-  /* reg_ptr -> array data */
+  // reg_ptr -> array data.
   OpRegImm(kOpAdd, reg_ptr, data_offset);
-  /* at this point, reg_ptr points to array, 2 live temps */
+  // At this point, reg_ptr points to array, 2 live temps.
   if ((size == k64) || (size == kDouble)) {
-    // TUNING: specific wide routine that can handle fp regs
+    // TUNING: specific wide routine that can handle fp regs.
     if (scale) {
       RegStorage r_new_index = AllocTemp();
       OpRegRegImm(kOpLsl, r_new_index, rl_index.reg, scale);
@@ -660,18 +807,104 @@
   }
 }
 
+void MipsMir2Lir::GenShiftOpLong(Instruction::Code opcode, RegLocation rl_dest, RegLocation rl_src1,
+                                 RegLocation rl_shift) {
+  if (!cu_->target64) {
+    Mir2Lir::GenShiftOpLong(opcode, rl_dest, rl_src1, rl_shift);
+    return;
+  }
+  OpKind op = kOpBkpt;
+  switch (opcode) {
+  case Instruction::SHL_LONG:
+  case Instruction::SHL_LONG_2ADDR:
+    op = kOpLsl;
+    break;
+  case Instruction::SHR_LONG:
+  case Instruction::SHR_LONG_2ADDR:
+    op = kOpAsr;
+    break;
+  case Instruction::USHR_LONG:
+  case Instruction::USHR_LONG_2ADDR:
+    op = kOpLsr;
+    break;
+  default:
+    LOG(FATAL) << "Unexpected case: " << opcode;
+  }
+  rl_shift = LoadValue(rl_shift, kCoreReg);
+  rl_src1 = LoadValueWide(rl_src1, kCoreReg);
+  RegLocation rl_result = EvalLocWide(rl_dest, kCoreReg, true);
+  OpRegRegReg(op, rl_result.reg, rl_src1.reg, As64BitReg(rl_shift.reg));
+  StoreValueWide(rl_dest, rl_result);
+}
+
 void MipsMir2Lir::GenShiftImmOpLong(Instruction::Code opcode, RegLocation rl_dest,
                                     RegLocation rl_src1, RegLocation rl_shift, int flags) {
   UNUSED(flags);
-  // Default implementation is just to ignore the constant case.
-  GenShiftOpLong(opcode, rl_dest, rl_src1, rl_shift);
+  if (!cu_->target64) {
+    // Default implementation is just to ignore the constant case.
+    GenShiftOpLong(opcode, rl_dest, rl_src1, rl_shift);
+    return;
+  }
+  OpKind op = kOpBkpt;
+  // Per spec, we only care about low 6 bits of shift amount.
+  int shift_amount = mir_graph_->ConstantValue(rl_shift) & 0x3f;
+  rl_src1 = LoadValueWide(rl_src1, kCoreReg);
+  if (shift_amount == 0) {
+    StoreValueWide(rl_dest, rl_src1);
+    return;
+  }
+
+  RegLocation rl_result = EvalLocWide(rl_dest, kCoreReg, true);
+  switch (opcode) {
+    case Instruction::SHL_LONG:
+    case Instruction::SHL_LONG_2ADDR:
+      op = kOpLsl;
+      break;
+    case Instruction::SHR_LONG:
+    case Instruction::SHR_LONG_2ADDR:
+      op = kOpAsr;
+      break;
+    case Instruction::USHR_LONG:
+    case Instruction::USHR_LONG_2ADDR:
+      op = kOpLsr;
+      break;
+    default:
+      LOG(FATAL) << "Unexpected case";
+  }
+  OpRegRegImm(op, rl_result.reg, rl_src1.reg, shift_amount);
+  StoreValueWide(rl_dest, rl_result);
 }
 
-void MipsMir2Lir::GenArithImmOpLong(Instruction::Code opcode,
-                                    RegLocation rl_dest, RegLocation rl_src1, RegLocation rl_src2,
-                                    int flags) {
+void MipsMir2Lir::GenArithImmOpLong(Instruction::Code opcode, RegLocation rl_dest,
+                                    RegLocation rl_src1, RegLocation rl_src2, int flags) {
   // Default - bail to non-const handler.
   GenArithOpLong(opcode, rl_dest, rl_src1, rl_src2, flags);
 }
 
+void MipsMir2Lir::GenIntToLong(RegLocation rl_dest, RegLocation rl_src) {
+  if (!cu_->target64) {
+    Mir2Lir::GenIntToLong(rl_dest, rl_src);
+    return;
+  }
+  rl_src = LoadValue(rl_src, kCoreReg);
+  RegLocation rl_result = EvalLocWide(rl_dest, kCoreReg, true);
+  NewLIR3(kMipsSll, rl_result.reg.GetReg(), As64BitReg(rl_src.reg).GetReg(), 0);
+  StoreValueWide(rl_dest, rl_result);
+}
+
+void MipsMir2Lir::GenConversionCall(QuickEntrypointEnum trampoline, RegLocation rl_dest,
+                                    RegLocation rl_src, RegisterClass reg_class) {
+  FlushAllRegs();   // Send everything to home location.
+  CallRuntimeHelperRegLocation(trampoline, rl_src, false);
+  if (rl_dest.wide) {
+    RegLocation rl_result;
+    rl_result = GetReturnWide(reg_class);
+    StoreValueWide(rl_dest, rl_result);
+  } else {
+    RegLocation rl_result;
+    rl_result = GetReturn(reg_class);
+    StoreValue(rl_dest, rl_result);
+  }
+}
+
 }  // namespace art
diff --git a/compiler/dex/quick/mips/mips_lir.h b/compiler/dex/quick/mips/mips_lir.h
index 7037055..078ac0a 100644
--- a/compiler/dex/quick/mips/mips_lir.h
+++ b/compiler/dex/quick/mips/mips_lir.h
@@ -25,25 +25,29 @@
 /*
  * Runtime register conventions.
  *
- * zero is always the value 0
- * at is scratch (normally used as temp reg by assembler)
- * v0, v1 are scratch (normally hold subroutine return values)
- * a0-a3 are scratch (normally hold subroutine arguments)
- * t0-t8 are scratch
- * t9 is scratch (normally used for function calls)
- * s0 (rMIPS_SUSPEND) is reserved [holds suspend-check counter]
- * s1 (rMIPS_SELF) is reserved [holds current &Thread]
- * s2-s7 are callee save (promotion target)
- * k0, k1 are reserved for use by interrupt handlers
- * gp is reserved for global pointer
- * sp is reserved
- * s8 is callee save (promotion target)
- * ra is scratch (normally holds the return addr)
+ *          mips32            | mips64
+ * $0:      zero is always the value 0
+ * $1:      at is scratch (normally used as temp reg by assembler)
+ * $2,$3:   v0, v1 are scratch (normally hold subroutine return values)
+ * $4-$7:   a0-a3 are scratch (normally hold subroutine arguments)
+ * $8-$11:  t0-t3 are scratch | a4-a7 are scratch (normally hold subroutine arguments)
+ * $12-$15: t4-t7 are scratch | t0-t3 are scratch
+ * $16:     s0 (rSUSPEND) is reserved [holds suspend-check counter]
+ * $17:     s1 (rSELF) is reserved [holds current &Thread]
+ * $18-$23: s2-s7 are callee save (promotion target)
+ * $24:     t8 is scratch
+ * $25:     t9 is scratch (normally used for function calls)
+ * $26,$27: k0, k1 are reserved for use by interrupt handlers
+ * $28:     gp is reserved for global pointer
+ * $29:     sp is reserved
+ * $30:     s8 is callee save (promotion target)
+ * $31:     ra is scratch (normally holds the return addr)
  *
  * Preserved across C calls: s0-s8
- * Trashed across C calls: at, v0-v1, a0-a3, t0-t9, gp, ra
+ * Trashed across C calls (mips32): at, v0-v1, a0-a3, t0-t9, gp, ra
+ * Trashed across C calls (mips64): at, v0-v1, a0-a7, t0-t3, t8, t9, gp, ra
  *
- * Floating pointer registers
+ * Floating pointer registers (mips32)
  * NOTE: there are 32 fp registers (16 df pairs), but currently
  *       only support 16 fp registers (8 df pairs).
  * f0-f15
@@ -51,14 +55,23 @@
  *
  * f0-f15 (df0-df7) trashed across C calls
  *
+ * Floating pointer registers (mips64)
+ * NOTE: there are 32 fp registers.
+ * f0-f31
+ *
  * For mips32 code use:
  *      a0-a3 to hold operands
  *      v0-v1 to hold results
  *      t0-t9 for temps
  *
+ * For mips64 code use:
+ *      a0-a7 to hold operands
+ *      v0-v1 to hold results
+ *      t0-t3, t8-t9 for temps
+ *
  * All jump/branch instructions have a delay slot after it.
  *
- *  Stack frame diagram (stack grows down, higher addresses at top):
+ * Stack frame diagram (stack grows down, higher addresses at top):
  *
  * +------------------------+
  * | IN[ins-1]              |  {Note: resides in caller's frame}
@@ -90,18 +103,6 @@
 
 #define LOWORD_OFFSET 0
 #define HIWORD_OFFSET 4
-#define rARG0 rA0
-#define rs_rARG0 rs_rA0
-#define rARG1 rA1
-#define rs_rARG1 rs_rA1
-#define rARG2 rA2
-#define rs_rARG2 rs_rA2
-#define rARG3 rA3
-#define rs_rARG3 rs_rA3
-#define rRESULT0 rV0
-#define rs_rRESULT0 rs_rV0
-#define rRESULT1 rV1
-#define rs_rRESULT1 rs_rV1
 
 #define rFARG0 rF12
 #define rs_rFARG0 rs_rF12
@@ -111,14 +112,6 @@
 #define rs_rFARG2 rs_rF14
 #define rFARG3 rF15
 #define rs_rFARG3 rs_rF15
-#define rFRESULT0 rF0
-#define rs_rFRESULT0 rs_rF0
-#define rFRESULT1 rF1
-#define rs_rFRESULT1 rs_rF1
-
-// Regs not used for Mips.
-#define rMIPS_LR RegStorage::kInvalidRegVal
-#define rMIPS_PC RegStorage::kInvalidRegVal
 
 enum MipsResourceEncodingPos {
   kMipsGPReg0   = 0,
@@ -130,6 +123,10 @@
   kMipsRegLO,
   kMipsRegPC,
   kMipsRegEnd   = 51,
+  // Mips64 related:
+  kMips64FPRegEnd = 64,
+  kMips64RegPC    = kMips64FPRegEnd,
+  kMips64RegEnd   = 65,
 };
 
 #define ENCODE_MIPS_REG_LIST(N)      (static_cast<uint64_t>(N))
@@ -144,38 +141,78 @@
 #define FR_BIT   0
 
 enum MipsNativeRegisterPool {  // private marker to avoid generate-operator-out.py from processing.
-  rZERO = RegStorage::k32BitSolo | RegStorage::kCoreRegister |  0,
-  rAT   = RegStorage::k32BitSolo | RegStorage::kCoreRegister |  1,
-  rV0   = RegStorage::k32BitSolo | RegStorage::kCoreRegister |  2,
-  rV1   = RegStorage::k32BitSolo | RegStorage::kCoreRegister |  3,
-  rA0   = RegStorage::k32BitSolo | RegStorage::kCoreRegister |  4,
-  rA1   = RegStorage::k32BitSolo | RegStorage::kCoreRegister |  5,
-  rA2   = RegStorage::k32BitSolo | RegStorage::kCoreRegister |  6,
-  rA3   = RegStorage::k32BitSolo | RegStorage::kCoreRegister |  7,
-  rT0   = RegStorage::k32BitSolo | RegStorage::kCoreRegister |  8,
-  rT1   = RegStorage::k32BitSolo | RegStorage::kCoreRegister |  9,
-  rT2   = RegStorage::k32BitSolo | RegStorage::kCoreRegister | 10,
-  rT3   = RegStorage::k32BitSolo | RegStorage::kCoreRegister | 11,
-  rT4   = RegStorage::k32BitSolo | RegStorage::kCoreRegister | 12,
-  rT5   = RegStorage::k32BitSolo | RegStorage::kCoreRegister | 13,
-  rT6   = RegStorage::k32BitSolo | RegStorage::kCoreRegister | 14,
-  rT7   = RegStorage::k32BitSolo | RegStorage::kCoreRegister | 15,
-  rS0   = RegStorage::k32BitSolo | RegStorage::kCoreRegister | 16,
-  rS1   = RegStorage::k32BitSolo | RegStorage::kCoreRegister | 17,
-  rS2   = RegStorage::k32BitSolo | RegStorage::kCoreRegister | 18,
-  rS3   = RegStorage::k32BitSolo | RegStorage::kCoreRegister | 19,
-  rS4   = RegStorage::k32BitSolo | RegStorage::kCoreRegister | 20,
-  rS5   = RegStorage::k32BitSolo | RegStorage::kCoreRegister | 21,
-  rS6   = RegStorage::k32BitSolo | RegStorage::kCoreRegister | 22,
-  rS7   = RegStorage::k32BitSolo | RegStorage::kCoreRegister | 23,
-  rT8   = RegStorage::k32BitSolo | RegStorage::kCoreRegister | 24,
-  rT9   = RegStorage::k32BitSolo | RegStorage::kCoreRegister | 25,
-  rK0   = RegStorage::k32BitSolo | RegStorage::kCoreRegister | 26,
-  rK1   = RegStorage::k32BitSolo | RegStorage::kCoreRegister | 27,
-  rGP   = RegStorage::k32BitSolo | RegStorage::kCoreRegister | 28,
-  rSP   = RegStorage::k32BitSolo | RegStorage::kCoreRegister | 29,
-  rFP   = RegStorage::k32BitSolo | RegStorage::kCoreRegister | 30,
-  rRA   = RegStorage::k32BitSolo | RegStorage::kCoreRegister | 31,
+  rZERO  = RegStorage::k32BitSolo | RegStorage::kCoreRegister |  0,
+  rZEROd = RegStorage::k64BitSolo | RegStorage::kCoreRegister |  0,
+  rAT    = RegStorage::k32BitSolo | RegStorage::kCoreRegister |  1,
+  rATd   = RegStorage::k64BitSolo | RegStorage::kCoreRegister |  1,
+  rV0    = RegStorage::k32BitSolo | RegStorage::kCoreRegister |  2,
+  rV0d   = RegStorage::k64BitSolo | RegStorage::kCoreRegister |  2,
+  rV1    = RegStorage::k32BitSolo | RegStorage::kCoreRegister |  3,
+  rV1d   = RegStorage::k64BitSolo | RegStorage::kCoreRegister |  3,
+  rA0    = RegStorage::k32BitSolo | RegStorage::kCoreRegister |  4,
+  rA0d   = RegStorage::k64BitSolo | RegStorage::kCoreRegister |  4,
+  rA1    = RegStorage::k32BitSolo | RegStorage::kCoreRegister |  5,
+  rA1d   = RegStorage::k64BitSolo | RegStorage::kCoreRegister |  5,
+  rA2    = RegStorage::k32BitSolo | RegStorage::kCoreRegister |  6,
+  rA2d   = RegStorage::k64BitSolo | RegStorage::kCoreRegister |  6,
+  rA3    = RegStorage::k32BitSolo | RegStorage::kCoreRegister |  7,
+  rA3d   = RegStorage::k64BitSolo | RegStorage::kCoreRegister |  7,
+  rT0_32 = RegStorage::k32BitSolo | RegStorage::kCoreRegister |  8,
+  rA4    = rT0_32,
+  rA4d   = RegStorage::k64BitSolo | RegStorage::kCoreRegister |  8,
+  rT1_32 = RegStorage::k32BitSolo | RegStorage::kCoreRegister |  9,
+  rA5    = rT1_32,
+  rA5d   = RegStorage::k64BitSolo | RegStorage::kCoreRegister |  9,
+  rT2_32 = RegStorage::k32BitSolo | RegStorage::kCoreRegister | 10,
+  rA6    = rT2_32,
+  rA6d   = RegStorage::k64BitSolo | RegStorage::kCoreRegister | 10,
+  rT3_32 = RegStorage::k32BitSolo | RegStorage::kCoreRegister | 11,
+  rA7    = rT3_32,
+  rA7d   = RegStorage::k64BitSolo | RegStorage::kCoreRegister | 11,
+  rT4_32 = RegStorage::k32BitSolo | RegStorage::kCoreRegister | 12,
+  rT0    = rT4_32,
+  rT0d   = RegStorage::k64BitSolo | RegStorage::kCoreRegister | 12,
+  rT5_32 = RegStorage::k32BitSolo | RegStorage::kCoreRegister | 13,
+  rT1    = rT5_32,
+  rT1d   = RegStorage::k64BitSolo | RegStorage::kCoreRegister | 13,
+  rT6_32 = RegStorage::k32BitSolo | RegStorage::kCoreRegister | 14,
+  rT2    = rT6_32,
+  rT2d   = RegStorage::k64BitSolo | RegStorage::kCoreRegister | 14,
+  rT7_32 = RegStorage::k32BitSolo | RegStorage::kCoreRegister | 15,
+  rT3    = rT7_32,
+  rT3d   = RegStorage::k64BitSolo | RegStorage::kCoreRegister | 15,
+  rS0    = RegStorage::k32BitSolo | RegStorage::kCoreRegister | 16,
+  rS0d   = RegStorage::k64BitSolo | RegStorage::kCoreRegister | 16,
+  rS1    = RegStorage::k32BitSolo | RegStorage::kCoreRegister | 17,
+  rS1d   = RegStorage::k64BitSolo | RegStorage::kCoreRegister | 17,
+  rS2    = RegStorage::k32BitSolo | RegStorage::kCoreRegister | 18,
+  rS2d   = RegStorage::k64BitSolo | RegStorage::kCoreRegister | 18,
+  rS3    = RegStorage::k32BitSolo | RegStorage::kCoreRegister | 19,
+  rS3d   = RegStorage::k64BitSolo | RegStorage::kCoreRegister | 19,
+  rS4    = RegStorage::k32BitSolo | RegStorage::kCoreRegister | 20,
+  rS4d   = RegStorage::k64BitSolo | RegStorage::kCoreRegister | 20,
+  rS5    = RegStorage::k32BitSolo | RegStorage::kCoreRegister | 21,
+  rS5d   = RegStorage::k64BitSolo | RegStorage::kCoreRegister | 21,
+  rS6    = RegStorage::k32BitSolo | RegStorage::kCoreRegister | 22,
+  rS6d   = RegStorage::k64BitSolo | RegStorage::kCoreRegister | 22,
+  rS7    = RegStorage::k32BitSolo | RegStorage::kCoreRegister | 23,
+  rS7d   = RegStorage::k64BitSolo | RegStorage::kCoreRegister | 23,
+  rT8    = RegStorage::k32BitSolo | RegStorage::kCoreRegister | 24,
+  rT8d   = RegStorage::k64BitSolo | RegStorage::kCoreRegister | 24,
+  rT9    = RegStorage::k32BitSolo | RegStorage::kCoreRegister | 25,
+  rT9d   = RegStorage::k64BitSolo | RegStorage::kCoreRegister | 25,
+  rK0    = RegStorage::k32BitSolo | RegStorage::kCoreRegister | 26,
+  rK0d   = RegStorage::k64BitSolo | RegStorage::kCoreRegister | 26,
+  rK1    = RegStorage::k32BitSolo | RegStorage::kCoreRegister | 27,
+  rK1d   = RegStorage::k64BitSolo | RegStorage::kCoreRegister | 27,
+  rGP    = RegStorage::k32BitSolo | RegStorage::kCoreRegister | 28,
+  rGPd   = RegStorage::k64BitSolo | RegStorage::kCoreRegister | 28,
+  rSP    = RegStorage::k32BitSolo | RegStorage::kCoreRegister | 29,
+  rSPd   = RegStorage::k64BitSolo | RegStorage::kCoreRegister | 29,
+  rFP    = RegStorage::k32BitSolo | RegStorage::kCoreRegister | 30,
+  rFPd   = RegStorage::k64BitSolo | RegStorage::kCoreRegister | 30,
+  rRA    = RegStorage::k32BitSolo | RegStorage::kCoreRegister | 31,
+  rRAd   = RegStorage::k64BitSolo | RegStorage::kCoreRegister | 31,
 
   rF0  = RegStorage::k32BitSolo | RegStorage::kFloatingPoint |  0,
   rF1  = RegStorage::k32BitSolo | RegStorage::kFloatingPoint |  1,
@@ -193,6 +230,24 @@
   rF13 = RegStorage::k32BitSolo | RegStorage::kFloatingPoint | 13,
   rF14 = RegStorage::k32BitSolo | RegStorage::kFloatingPoint | 14,
   rF15 = RegStorage::k32BitSolo | RegStorage::kFloatingPoint | 15,
+
+  rF16 = RegStorage::k32BitSolo | RegStorage::kFloatingPoint | 16,
+  rF17 = RegStorage::k32BitSolo | RegStorage::kFloatingPoint | 17,
+  rF18 = RegStorage::k32BitSolo | RegStorage::kFloatingPoint | 18,
+  rF19 = RegStorage::k32BitSolo | RegStorage::kFloatingPoint | 19,
+  rF20 = RegStorage::k32BitSolo | RegStorage::kFloatingPoint | 20,
+  rF21 = RegStorage::k32BitSolo | RegStorage::kFloatingPoint | 21,
+  rF22 = RegStorage::k32BitSolo | RegStorage::kFloatingPoint | 22,
+  rF23 = RegStorage::k32BitSolo | RegStorage::kFloatingPoint | 23,
+  rF24 = RegStorage::k32BitSolo | RegStorage::kFloatingPoint | 24,
+  rF25 = RegStorage::k32BitSolo | RegStorage::kFloatingPoint | 25,
+  rF26 = RegStorage::k32BitSolo | RegStorage::kFloatingPoint | 26,
+  rF27 = RegStorage::k32BitSolo | RegStorage::kFloatingPoint | 27,
+  rF28 = RegStorage::k32BitSolo | RegStorage::kFloatingPoint | 28,
+  rF29 = RegStorage::k32BitSolo | RegStorage::kFloatingPoint | 29,
+  rF30 = RegStorage::k32BitSolo | RegStorage::kFloatingPoint | 30,
+  rF31 = RegStorage::k32BitSolo | RegStorage::kFloatingPoint | 31,
+
 #if 0
   /*
    * TODO: The shared resource mask doesn't have enough bit positions to describe all
@@ -253,6 +308,39 @@
   rD14_fr1 = RegStorage::k64BitSolo | RegStorage::kFloatingPoint | 28,
   rD15_fr1 = RegStorage::k64BitSolo | RegStorage::kFloatingPoint | 30,
 #endif
+
+  rD0  = RegStorage::k64BitSolo | RegStorage::kFloatingPoint |  0,
+  rD1  = RegStorage::k64BitSolo | RegStorage::kFloatingPoint |  1,
+  rD2  = RegStorage::k64BitSolo | RegStorage::kFloatingPoint |  2,
+  rD3  = RegStorage::k64BitSolo | RegStorage::kFloatingPoint |  3,
+  rD4  = RegStorage::k64BitSolo | RegStorage::kFloatingPoint |  4,
+  rD5  = RegStorage::k64BitSolo | RegStorage::kFloatingPoint |  5,
+  rD6  = RegStorage::k64BitSolo | RegStorage::kFloatingPoint |  6,
+  rD7  = RegStorage::k64BitSolo | RegStorage::kFloatingPoint |  7,
+  rD8  = RegStorage::k64BitSolo | RegStorage::kFloatingPoint |  8,
+  rD9  = RegStorage::k64BitSolo | RegStorage::kFloatingPoint |  9,
+  rD10 = RegStorage::k64BitSolo | RegStorage::kFloatingPoint | 10,
+  rD11 = RegStorage::k64BitSolo | RegStorage::kFloatingPoint | 11,
+  rD12 = RegStorage::k64BitSolo | RegStorage::kFloatingPoint | 12,
+  rD13 = RegStorage::k64BitSolo | RegStorage::kFloatingPoint | 13,
+  rD14 = RegStorage::k64BitSolo | RegStorage::kFloatingPoint | 14,
+  rD15 = RegStorage::k64BitSolo | RegStorage::kFloatingPoint | 15,
+  rD16 = RegStorage::k64BitSolo | RegStorage::kFloatingPoint | 16,
+  rD17 = RegStorage::k64BitSolo | RegStorage::kFloatingPoint | 17,
+  rD18 = RegStorage::k64BitSolo | RegStorage::kFloatingPoint | 18,
+  rD19 = RegStorage::k64BitSolo | RegStorage::kFloatingPoint | 19,
+  rD20 = RegStorage::k64BitSolo | RegStorage::kFloatingPoint | 20,
+  rD21 = RegStorage::k64BitSolo | RegStorage::kFloatingPoint | 21,
+  rD22 = RegStorage::k64BitSolo | RegStorage::kFloatingPoint | 22,
+  rD23 = RegStorage::k64BitSolo | RegStorage::kFloatingPoint | 23,
+  rD24 = RegStorage::k64BitSolo | RegStorage::kFloatingPoint | 24,
+  rD25 = RegStorage::k64BitSolo | RegStorage::kFloatingPoint | 25,
+  rD26 = RegStorage::k64BitSolo | RegStorage::kFloatingPoint | 26,
+  rD27 = RegStorage::k64BitSolo | RegStorage::kFloatingPoint | 27,
+  rD28 = RegStorage::k64BitSolo | RegStorage::kFloatingPoint | 28,
+  rD29 = RegStorage::k64BitSolo | RegStorage::kFloatingPoint | 29,
+  rD30 = RegStorage::k64BitSolo | RegStorage::kFloatingPoint | 30,
+  rD31 = RegStorage::k64BitSolo | RegStorage::kFloatingPoint | 31,
 };
 
 constexpr RegStorage rs_rZERO(RegStorage::kValid | rZERO);
@@ -263,14 +351,22 @@
 constexpr RegStorage rs_rA1(RegStorage::kValid | rA1);
 constexpr RegStorage rs_rA2(RegStorage::kValid | rA2);
 constexpr RegStorage rs_rA3(RegStorage::kValid | rA3);
-constexpr RegStorage rs_rT0(RegStorage::kValid | rT0);
-constexpr RegStorage rs_rT1(RegStorage::kValid | rT1);
-constexpr RegStorage rs_rT2(RegStorage::kValid | rT2);
-constexpr RegStorage rs_rT3(RegStorage::kValid | rT3);
-constexpr RegStorage rs_rT4(RegStorage::kValid | rT4);
-constexpr RegStorage rs_rT5(RegStorage::kValid | rT5);
-constexpr RegStorage rs_rT6(RegStorage::kValid | rT6);
-constexpr RegStorage rs_rT7(RegStorage::kValid | rT7);
+constexpr RegStorage rs_rT0_32(RegStorage::kValid | rT0_32);
+constexpr RegStorage rs_rA4 = rs_rT0_32;
+constexpr RegStorage rs_rT1_32(RegStorage::kValid | rT1_32);
+constexpr RegStorage rs_rA5 = rs_rT1_32;
+constexpr RegStorage rs_rT2_32(RegStorage::kValid | rT2_32);
+constexpr RegStorage rs_rA6 = rs_rT2_32;
+constexpr RegStorage rs_rT3_32(RegStorage::kValid | rT3_32);
+constexpr RegStorage rs_rA7 = rs_rT3_32;
+constexpr RegStorage rs_rT4_32(RegStorage::kValid | rT4_32);
+constexpr RegStorage rs_rT0 = rs_rT4_32;
+constexpr RegStorage rs_rT5_32(RegStorage::kValid | rT5_32);
+constexpr RegStorage rs_rT1 = rs_rT5_32;
+constexpr RegStorage rs_rT6_32(RegStorage::kValid | rT6_32);
+constexpr RegStorage rs_rT2 = rs_rT6_32;
+constexpr RegStorage rs_rT7_32(RegStorage::kValid | rT7_32);
+constexpr RegStorage rs_rT3 = rs_rT7_32;
 constexpr RegStorage rs_rS0(RegStorage::kValid | rS0);
 constexpr RegStorage rs_rS1(RegStorage::kValid | rS1);
 constexpr RegStorage rs_rS2(RegStorage::kValid | rS2);
@@ -288,9 +384,38 @@
 constexpr RegStorage rs_rFP(RegStorage::kValid | rFP);
 constexpr RegStorage rs_rRA(RegStorage::kValid | rRA);
 
-constexpr RegStorage rs_rMIPS_LR(RegStorage::kInvalid);     // Not used for MIPS.
-constexpr RegStorage rs_rMIPS_PC(RegStorage::kInvalid);     // Not used for MIPS.
-constexpr RegStorage rs_rMIPS_COUNT(RegStorage::kInvalid);  // Not used for MIPS.
+constexpr RegStorage rs_rZEROd(RegStorage::kValid | rZEROd);
+constexpr RegStorage rs_rATd(RegStorage::kValid | rATd);
+constexpr RegStorage rs_rV0d(RegStorage::kValid | rV0d);
+constexpr RegStorage rs_rV1d(RegStorage::kValid | rV1d);
+constexpr RegStorage rs_rA0d(RegStorage::kValid | rA0d);
+constexpr RegStorage rs_rA1d(RegStorage::kValid | rA1d);
+constexpr RegStorage rs_rA2d(RegStorage::kValid | rA2d);
+constexpr RegStorage rs_rA3d(RegStorage::kValid | rA3d);
+constexpr RegStorage rs_rA4d(RegStorage::kValid | rA4d);
+constexpr RegStorage rs_rA5d(RegStorage::kValid | rA5d);
+constexpr RegStorage rs_rA6d(RegStorage::kValid | rA6d);
+constexpr RegStorage rs_rA7d(RegStorage::kValid | rA7d);
+constexpr RegStorage rs_rT0d(RegStorage::kValid | rT0d);
+constexpr RegStorage rs_rT1d(RegStorage::kValid | rT1d);
+constexpr RegStorage rs_rT2d(RegStorage::kValid | rT2d);
+constexpr RegStorage rs_rT3d(RegStorage::kValid | rT3d);
+constexpr RegStorage rs_rS0d(RegStorage::kValid | rS0d);
+constexpr RegStorage rs_rS1d(RegStorage::kValid | rS1d);
+constexpr RegStorage rs_rS2d(RegStorage::kValid | rS2d);
+constexpr RegStorage rs_rS3d(RegStorage::kValid | rS3d);
+constexpr RegStorage rs_rS4d(RegStorage::kValid | rS4d);
+constexpr RegStorage rs_rS5d(RegStorage::kValid | rS5d);
+constexpr RegStorage rs_rS6d(RegStorage::kValid | rS6d);
+constexpr RegStorage rs_rS7d(RegStorage::kValid | rS7d);
+constexpr RegStorage rs_rT8d(RegStorage::kValid | rT8d);
+constexpr RegStorage rs_rT9d(RegStorage::kValid | rT9d);
+constexpr RegStorage rs_rK0d(RegStorage::kValid | rK0d);
+constexpr RegStorage rs_rK1d(RegStorage::kValid | rK1d);
+constexpr RegStorage rs_rGPd(RegStorage::kValid | rGPd);
+constexpr RegStorage rs_rSPd(RegStorage::kValid | rSPd);
+constexpr RegStorage rs_rFPd(RegStorage::kValid | rFPd);
+constexpr RegStorage rs_rRAd(RegStorage::kValid | rRAd);
 
 constexpr RegStorage rs_rF0(RegStorage::kValid | rF0);
 constexpr RegStorage rs_rF1(RegStorage::kValid | rF1);
@@ -309,6 +434,23 @@
 constexpr RegStorage rs_rF14(RegStorage::kValid | rF14);
 constexpr RegStorage rs_rF15(RegStorage::kValid | rF15);
 
+constexpr RegStorage rs_rF16(RegStorage::kValid | rF16);
+constexpr RegStorage rs_rF17(RegStorage::kValid | rF17);
+constexpr RegStorage rs_rF18(RegStorage::kValid | rF18);
+constexpr RegStorage rs_rF19(RegStorage::kValid | rF19);
+constexpr RegStorage rs_rF20(RegStorage::kValid | rF20);
+constexpr RegStorage rs_rF21(RegStorage::kValid | rF21);
+constexpr RegStorage rs_rF22(RegStorage::kValid | rF22);
+constexpr RegStorage rs_rF23(RegStorage::kValid | rF23);
+constexpr RegStorage rs_rF24(RegStorage::kValid | rF24);
+constexpr RegStorage rs_rF25(RegStorage::kValid | rF25);
+constexpr RegStorage rs_rF26(RegStorage::kValid | rF26);
+constexpr RegStorage rs_rF27(RegStorage::kValid | rF27);
+constexpr RegStorage rs_rF28(RegStorage::kValid | rF28);
+constexpr RegStorage rs_rF29(RegStorage::kValid | rF29);
+constexpr RegStorage rs_rF30(RegStorage::kValid | rF30);
+constexpr RegStorage rs_rF31(RegStorage::kValid | rF31);
+
 constexpr RegStorage rs_rD0_fr0(RegStorage::kValid | rD0_fr0);
 constexpr RegStorage rs_rD1_fr0(RegStorage::kValid | rD1_fr0);
 constexpr RegStorage rs_rD2_fr0(RegStorage::kValid | rD2_fr0);
@@ -327,53 +469,65 @@
 constexpr RegStorage rs_rD6_fr1(RegStorage::kValid | rD6_fr1);
 constexpr RegStorage rs_rD7_fr1(RegStorage::kValid | rD7_fr1);
 
-// TODO: reduce/eliminate use of these.
-#define rMIPS_SUSPEND rS0
-#define rs_rMIPS_SUSPEND rs_rS0
-#define rMIPS_SELF rS1
-#define rs_rMIPS_SELF rs_rS1
-#define rMIPS_SP rSP
-#define rs_rMIPS_SP rs_rSP
-#define rMIPS_ARG0 rARG0
-#define rs_rMIPS_ARG0 rs_rARG0
-#define rMIPS_ARG1 rARG1
-#define rs_rMIPS_ARG1 rs_rARG1
-#define rMIPS_ARG2 rARG2
-#define rs_rMIPS_ARG2 rs_rARG2
-#define rMIPS_ARG3 rARG3
-#define rs_rMIPS_ARG3 rs_rARG3
-#define rMIPS_FARG0 rFARG0
-#define rs_rMIPS_FARG0 rs_rFARG0
-#define rMIPS_FARG1 rFARG1
-#define rs_rMIPS_FARG1 rs_rFARG1
-#define rMIPS_FARG2 rFARG2
-#define rs_rMIPS_FARG2 rs_rFARG2
-#define rMIPS_FARG3 rFARG3
-#define rs_rMIPS_FARG3 rs_rFARG3
-#define rMIPS_RET0 rRESULT0
-#define rs_rMIPS_RET0 rs_rRESULT0
-#define rMIPS_RET1 rRESULT1
-#define rs_rMIPS_RET1 rs_rRESULT1
-#define rMIPS_INVOKE_TGT rT9
-#define rs_rMIPS_INVOKE_TGT rs_rT9
-#define rMIPS_COUNT RegStorage::kInvalidRegVal
+constexpr RegStorage rs_rD0(RegStorage::kValid | rD0);
+constexpr RegStorage rs_rD1(RegStorage::kValid | rD1);
+constexpr RegStorage rs_rD2(RegStorage::kValid | rD2);
+constexpr RegStorage rs_rD3(RegStorage::kValid | rD3);
+constexpr RegStorage rs_rD4(RegStorage::kValid | rD4);
+constexpr RegStorage rs_rD5(RegStorage::kValid | rD5);
+constexpr RegStorage rs_rD6(RegStorage::kValid | rD6);
+constexpr RegStorage rs_rD7(RegStorage::kValid | rD7);
+constexpr RegStorage rs_rD8(RegStorage::kValid | rD8);
+constexpr RegStorage rs_rD9(RegStorage::kValid | rD9);
+constexpr RegStorage rs_rD10(RegStorage::kValid | rD10);
+constexpr RegStorage rs_rD11(RegStorage::kValid | rD11);
+constexpr RegStorage rs_rD12(RegStorage::kValid | rD12);
+constexpr RegStorage rs_rD13(RegStorage::kValid | rD13);
+constexpr RegStorage rs_rD14(RegStorage::kValid | rD14);
+constexpr RegStorage rs_rD15(RegStorage::kValid | rD15);
+constexpr RegStorage rs_rD16(RegStorage::kValid | rD16);
+constexpr RegStorage rs_rD17(RegStorage::kValid | rD17);
+constexpr RegStorage rs_rD18(RegStorage::kValid | rD18);
+constexpr RegStorage rs_rD19(RegStorage::kValid | rD19);
+constexpr RegStorage rs_rD20(RegStorage::kValid | rD20);
+constexpr RegStorage rs_rD21(RegStorage::kValid | rD21);
+constexpr RegStorage rs_rD22(RegStorage::kValid | rD22);
+constexpr RegStorage rs_rD23(RegStorage::kValid | rD23);
+constexpr RegStorage rs_rD24(RegStorage::kValid | rD24);
+constexpr RegStorage rs_rD25(RegStorage::kValid | rD25);
+constexpr RegStorage rs_rD26(RegStorage::kValid | rD26);
+constexpr RegStorage rs_rD27(RegStorage::kValid | rD27);
+constexpr RegStorage rs_rD28(RegStorage::kValid | rD28);
+constexpr RegStorage rs_rD29(RegStorage::kValid | rD29);
+constexpr RegStorage rs_rD30(RegStorage::kValid | rD30);
+constexpr RegStorage rs_rD31(RegStorage::kValid | rD31);
 
 // RegisterLocation templates return values (r_V0, or r_V0/r_V1).
 const RegLocation mips_loc_c_return
     {kLocPhysReg, 0, 0, 0, 0, 0, 0, 0, 1,
      RegStorage(RegStorage::k32BitSolo, rV0), INVALID_SREG, INVALID_SREG};
+const RegLocation mips64_loc_c_return_ref
+    {kLocPhysReg, 0, 0, 0, 0, 0, 1, 0, 1,
+     RegStorage(RegStorage::k64BitSolo, rV0d), INVALID_SREG, INVALID_SREG};
 const RegLocation mips_loc_c_return_wide
     {kLocPhysReg, 1, 0, 0, 0, 0, 0, 0, 1,
      RegStorage(RegStorage::k64BitPair, rV0, rV1), INVALID_SREG, INVALID_SREG};
+const RegLocation mips64_loc_c_return_wide
+    {kLocPhysReg, 1, 0, 0, 0, 0, 0, 0, 1,
+     RegStorage(RegStorage::k64BitSolo, rV0d), INVALID_SREG, INVALID_SREG};
 const RegLocation mips_loc_c_return_float
     {kLocPhysReg, 0, 0, 0, 1, 0, 0, 0, 1,
      RegStorage(RegStorage::k32BitSolo, rF0), INVALID_SREG, INVALID_SREG};
+// FIXME: move MIPS to k64Bitsolo for doubles
 const RegLocation mips_loc_c_return_double_fr0
     {kLocPhysReg, 1, 0, 0, 1, 0, 0, 0, 1,
      RegStorage(RegStorage::k64BitPair, rF0, rF1), INVALID_SREG, INVALID_SREG};
 const RegLocation mips_loc_c_return_double_fr1
     {kLocPhysReg, 1, 0, 0, 1, 0, 0, 0, 1,
      RegStorage(RegStorage::k64BitSolo, rF0), INVALID_SREG, INVALID_SREG};
+const RegLocation mips64_loc_c_return_double
+    {kLocPhysReg, 1, 0, 0, 1, 0, 0, 0, 1,
+     RegStorage(RegStorage::k64BitSolo, rD0), INVALID_SREG, INVALID_SREG};
 
 enum MipsShiftEncodings {
   kMipsLsl = 0x0,
@@ -395,104 +549,136 @@
 #define kSY kSYNC0
 
 /*
- * The following enum defines the list of supported Thumb instructions by the
+ * The following enum defines the list of supported mips instructions by the
  * assembler. Their corresponding EncodingMap positions will be defined in
- * Assemble.cc.
+ * assemble_mips.cc.
  */
 enum MipsOpCode {
   kMipsFirst = 0,
+  // The following are common mips32r2, mips32r6 and mips64r6 instructions.
   kMips32BitData = kMipsFirst,  // data [31..0].
-  kMipsAddiu,  // addiu t,s,imm16 [001001] s[25..21] t[20..16] imm16[15..0].
-  kMipsAddu,  // add d,s,t [000000] s[25..21] t[20..16] d[15..11] [00000100001].
-  kMipsAnd,   // and d,s,t [000000] s[25..21] t[20..16] d[15..11] [00000100100].
-  kMipsAndi,  // andi t,s,imm16 [001100] s[25..21] t[20..16] imm16[15..0].
-  kMipsB,     // b o   [0001000000000000] o[15..0].
-  kMipsBal,   // bal o [0000010000010001] o[15..0].
-  // NOTE: the code tests the range kMipsBeq thru kMipsBne, so adding an instruction in this
-  //       range may require updates.
-  kMipsBeq,   // beq s,t,o [000100] s[25..21] t[20..16] o[15..0].
-  kMipsBeqz,  // beqz s,o [000100] s[25..21] [00000] o[15..0].
-  kMipsBgez,  // bgez s,o [000001] s[25..21] [00001] o[15..0].
-  kMipsBgtz,  // bgtz s,o [000111] s[25..21] [00000] o[15..0].
-  kMipsBlez,  // blez s,o [000110] s[25..21] [00000] o[15..0].
-  kMipsBltz,  // bltz s,o [000001] s[25..21] [00000] o[15..0].
-  kMipsBnez,  // bnez s,o [000101] s[25..21] [00000] o[15..0].
-  kMipsBne,   // bne s,t,o [000101] s[25..21] t[20..16] o[15..0].
-  kMipsDiv,   // div s,t [000000] s[25..21] t[20..16] [0000000000011010].
-  kMipsExt,   // ext t,s,p,z [011111] s[25..21] t[20..16] z[15..11] p[10..6] [000000].
-  kMipsJal,   // jal t [000011] t[25..0].
-  kMipsJalr,  // jalr d,s [000000] s[25..21] [00000] d[15..11] hint[10..6] [001001].
-  kMipsJr,    // jr s [000000] s[25..21] [0000000000] hint[10..6] [001000].
-  kMipsLahi,  // lui t,imm16 [00111100000] t[20..16] imm16[15..0] load addr hi.
-  kMipsLalo,  // ori t,s,imm16 [001001] s[25..21] t[20..16] imm16[15..0] load addr lo.
-  kMipsLui,   // lui t,imm16 [00111100000] t[20..16] imm16[15..0].
-  kMipsLb,    // lb t,o(b) [100000] b[25..21] t[20..16] o[15..0].
-  kMipsLbu,   // lbu t,o(b) [100100] b[25..21] t[20..16] o[15..0].
-  kMipsLh,    // lh t,o(b) [100001] b[25..21] t[20..16] o[15..0].
-  kMipsLhu,   // lhu t,o(b) [100101] b[25..21] t[20..16] o[15..0].
-  kMipsLw,    // lw t,o(b) [100011] b[25..21] t[20..16] o[15..0].
-  kMipsMfhi,  // mfhi d [0000000000000000] d[15..11] [00000010000].
-  kMipsMflo,  // mflo d [0000000000000000] d[15..11] [00000010010].
-  kMipsMove,  // move d,s [000000] s[25..21] [00000] d[15..11] [00000100101].
-  kMipsMovz,  // movz d,s,t [000000] s[25..21] t[20..16] d[15..11] [00000001010].
-  kMipsMul,   // mul d,s,t [011100] s[25..21] t[20..16] d[15..11] [00000000010].
-  kMipsNop,   // nop [00000000000000000000000000000000].
-  kMipsNor,   // nor d,s,t [000000] s[25..21] t[20..16] d[15..11] [00000100111].
-  kMipsOr,    // or d,s,t [000000] s[25..21] t[20..16] d[15..11] [00000100101].
-  kMipsOri,   // ori t,s,imm16 [001001] s[25..21] t[20..16] imm16[15..0].
-  kMipsPref,  // pref h,o(b) [101011] b[25..21] h[20..16] o[15..0].
-  kMipsSb,    // sb t,o(b) [101000] b[25..21] t[20..16] o[15..0].
-  kMipsSeb,   // seb d,t [01111100000] t[20..16] d[15..11] [10000100000].
-  kMipsSeh,   // seh d,t [01111100000] t[20..16] d[15..11] [11000100000].
-  kMipsSh,    // sh t,o(b) [101001] b[25..21] t[20..16] o[15..0].
-  kMipsSll,   // sll d,t,a [00000000000] t[20..16] d[15..11] a[10..6] [000000].
-  kMipsSllv,  // sllv d,t,s [000000] s[25..21] t[20..16] d[15..11] [00000000100].
-  kMipsSlt,   // slt d,s,t [000000] s[25..21] t[20..16] d[15..11] [00000101010].
-  kMipsSlti,  // slti t,s,imm16 [001010] s[25..21] t[20..16] imm16[15..0].
-  kMipsSltu,  // sltu d,s,t [000000] s[25..21] t[20..16] d[15..11] [00000101011].
-  kMipsSra,   // sra d,s,imm5 [00000000000] t[20..16] d[15..11] imm5[10..6] [000011].
-  kMipsSrav,  // srav d,t,s [000000] s[25..21] t[20..16] d[15..11] [00000000111].
-  kMipsSrl,   // srl d,t,a [00000000000] t[20..16] d[20..16] a[10..6] [000010].
-  kMipsSrlv,  // srlv d,t,s [000000] s[25..21] t[20..16] d[15..11] [00000000110].
-  kMipsSubu,  // subu d,s,t [000000] s[25..21] t[20..16] d[15..11] [00000100011].
-  kMipsSw,    // sw t,o(b) [101011] b[25..21] t[20..16] o[15..0].
-  kMipsXor,   // xor d,s,t [000000] s[25..21] t[20..16] d[15..11] [00000100110].
-  kMipsXori,  // xori t,s,imm16 [001110] s[25..21] t[20..16] imm16[15..0].
-  kMipsFadds,  // add.s d,s,t [01000110000] t[20..16] s[15..11] d[10..6] [000000].
-  kMipsFsubs,  // sub.s d,s,t [01000110000] t[20..16] s[15..11] d[10..6] [000001].
-  kMipsFmuls,  // mul.s d,s,t [01000110000] t[20..16] s[15..11] d[10..6] [000010].
-  kMipsFdivs,  // div.s d,s,t [01000110000] t[20..16] s[15..11] d[10..6] [000011].
-  kMipsFaddd,  // add.d d,s,t [01000110001] t[20..16] s[15..11] d[10..6] [000000].
-  kMipsFsubd,  // sub.d d,s,t [01000110001] t[20..16] s[15..11] d[10..6] [000001].
-  kMipsFmuld,  // mul.d d,s,t [01000110001] t[20..16] s[15..11] d[10..6] [000010].
-  kMipsFdivd,  // div.d d,s,t [01000110001] t[20..16] s[15..11] d[10..6] [000011].
-  kMipsFcvtsd,  // cvt.s.d d,s [01000110001] [00000] s[15..11] d[10..6] [100000].
-  kMipsFcvtsw,  // cvt.s.w d,s [01000110100] [00000] s[15..11] d[10..6] [100000].
-  kMipsFcvtds,  // cvt.d.s d,s [01000110000] [00000] s[15..11] d[10..6] [100001].
-  kMipsFcvtdw,  // cvt.d.w d,s [01000110100] [00000] s[15..11] d[10..6] [100001].
-  kMipsFcvtws,  // cvt.w.d d,s [01000110000] [00000] s[15..11] d[10..6] [100100].
-  kMipsFcvtwd,  // cvt.w.d d,s [01000110001] [00000] s[15..11] d[10..6] [100100].
-  kMipsFmovs,  // mov.s d,s [01000110000] [00000] s[15..11] d[10..6] [000110].
-  kMipsFmovd,  // mov.d d,s [01000110001] [00000] s[15..11] d[10..6] [000110].
-  kMipsFlwc1,  // lwc1 t,o(b) [110001] b[25..21] t[20..16] o[15..0].
-  kMipsFldc1,  // ldc1 t,o(b) [110101] b[25..21] t[20..16] o[15..0].
-  kMipsFswc1,  // swc1 t,o(b) [111001] b[25..21] t[20..16] o[15..0].
-  kMipsFsdc1,  // sdc1 t,o(b) [111101] b[25..21] t[20..16] o[15..0].
-  kMipsMfc1,   // mfc1 t,s [01000100000] t[20..16] s[15..11] [00000000000].
-  kMipsMtc1,   // mtc1 t,s [01000100100] t[20..16] s[15..11] [00000000000].
-  kMipsMfhc1,  // mfhc1 t,s [01000100011] t[20..16] s[15..11] [00000000000].
-  kMipsMthc1,  // mthc1 t,s [01000100111] t[20..16] s[15..11] [00000000000].
-  kMipsDelta,  // Psuedo for ori t, s, <label>-<label>.
-  kMipsDeltaHi,  // Pseudo for lui t, high16(<label>-<label>).
-  kMipsDeltaLo,  // Pseudo for ori t, s, low16(<label>-<label>).
-  kMipsCurrPC,  // jal to .+8 to materialize pc.
-  kMipsSync,    // sync kind [000000] [0000000000000000] s[10..6] [001111].
+  kMipsAddiu,      // addiu t,s,imm16 [001001] s[25..21] t[20..16] imm16[15..0].
+  kMipsAddu,       // add d,s,t [000000] s[25..21] t[20..16] d[15..11] [00000100001].
+  kMipsAnd,        // and d,s,t [000000] s[25..21] t[20..16] d[15..11] [00000100100].
+  kMipsAndi,       // andi t,s,imm16 [001100] s[25..21] t[20..16] imm16[15..0].
+  kMipsB,          // b o   [0001000000000000] o[15..0].
+  kMipsBal,        // bal o [0000010000010001] o[15..0].
+  // NOTE : the code tests the range kMipsBeq thru kMipsBne, so adding an instruction in this
+  // range may require updates.
+  kMipsBeq,        // beq s,t,o [000100] s[25..21] t[20..16] o[15..0].
+  kMipsBeqz,       // beqz s,o [000100] s[25..21] [00000] o[15..0].
+  kMipsBgez,       // bgez s,o [000001] s[25..21] [00001] o[15..0].
+  kMipsBgtz,       // bgtz s,o [000111] s[25..21] [00000] o[15..0].
+  kMipsBlez,       // blez s,o [000110] s[25..21] [00000] o[15..0].
+  kMipsBltz,       // bltz s,o [000001] s[25..21] [00000] o[15..0].
+  kMipsBnez,       // bnez s,o [000101] s[25..21] [00000] o[15..0].
+  kMipsBne,        // bne s,t,o [000101] s[25..21] t[20..16] o[15..0].
+  kMipsExt,        // ext t,s,p,z [011111] s[25..21] t[20..16] z[15..11] p[10..6] [000000].
+  kMipsFaddd,      // add.d d,s,t [01000110001] t[20..16] s[15..11] d[10..6] [000000].
+  kMipsFadds,      // add.s d,s,t [01000110000] t[20..16] s[15..11] d[10..6] [000000].
+  kMipsFsubd,      // sub.d d,s,t [01000110001] t[20..16] s[15..11] d[10..6] [000001].
+  kMipsFsubs,      // sub.s d,s,t [01000110000] t[20..16] s[15..11] d[10..6] [000001].
+  kMipsFdivd,      // div.d d,s,t [01000110001] t[20..16] s[15..11] d[10..6] [000011].
+  kMipsFdivs,      // div.s d,s,t [01000110000] t[20..16] s[15..11] d[10..6] [000011].
+  kMipsFmuld,      // mul.d d,s,t [01000110000] t[20..16] s[15..11] d[10..6] [000010].
+  kMipsFmuls,      // mul.s d,s,t [01000110001] t[20..16] s[15..11] d[10..6] [000010].
+  kMipsFcvtsd,     // cvt.s.d d,s [01000110001] [00000] s[15..11] d[10..6] [100000].
+  kMipsFcvtsw,     // cvt.s.w d,s [01000110100] [00000] s[15..11] d[10..6] [100000].
+  kMipsFcvtds,     // cvt.d.s d,s [01000110000] [00000] s[15..11] d[10..6] [100001].
+  kMipsFcvtdw,     // cvt.d.w d,s [01000110100] [00000] s[15..11] d[10..6] [100001].
+  kMipsFcvtwd,     // cvt.w.d d,s [01000110001] [00000] s[15..11] d[10..6] [100100].
+  kMipsFcvtws,     // cvt.w.s d,s [01000110000] [00000] s[15..11] d[10..6] [100100].
+  kMipsFmovd,      // mov.d d,s [01000110001] [00000] s[15..11] d[10..6] [000110].
+  kMipsFmovs,      // mov.s d,s [01000110000] [00000] s[15..11] d[10..6] [000110].
+  kMipsFnegd,      // neg.d d,s [01000110001] [00000] s[15..11] d[10..6] [000111].
+  kMipsFnegs,      // neg.s d,s [01000110000] [00000] s[15..11] d[10..6] [000111].
+  kMipsFldc1,      // ldc1 t,o(b) [110101] b[25..21] t[20..16] o[15..0].
+  kMipsFlwc1,      // lwc1 t,o(b) [110001] b[25..21] t[20..16] o[15..0].
+  kMipsFsdc1,      // sdc1 t,o(b) [111101] b[25..21] t[20..16] o[15..0].
+  kMipsFswc1,      // swc1 t,o(b) [111001] b[25..21] t[20..16] o[15..0].
+  kMipsJal,        // jal t [000011] t[25..0].
+  kMipsJalr,       // jalr d,s [000000] s[25..21] [00000] d[15..11] hint[10..6] [001001].
+  kMipsJr,         // jr s [000000] s[25..21] [0000000000] hint[10..6] [001000].
+  kMipsLahi,       // lui t,imm16 [00111100000] t[20..16] imm16[15..0] load addr hi.
+  kMipsLalo,       // ori t,s,imm16 [001001] s[25..21] t[20..16] imm16[15..0] load addr lo.
+  kMipsLui,        // lui t,imm16 [00111100000] t[20..16] imm16[15..0].
+  kMipsLb,         // lb t,o(b) [100000] b[25..21] t[20..16] o[15..0].
+  kMipsLbu,        // lbu t,o(b) [100100] b[25..21] t[20..16] o[15..0].
+  kMipsLh,         // lh t,o(b) [100001] b[25..21] t[20..16] o[15..0].
+  kMipsLhu,        // lhu t,o(b) [100101] b[25..21] t[20..16] o[15..0].
+  kMipsLw,         // lw t,o(b) [100011] b[25..21] t[20..16] o[15..0].
+  kMipsMove,       // move d,s [000000] s[25..21] [00000] d[15..11] [00000100101].
+  kMipsMfc1,       // mfc1 t,s [01000100000] t[20..16] s[15..11] [00000000000].
+  kMipsMtc1,       // mtc1 t,s [01000100100] t[20..16] s[15..11] [00000000000].
+  kMipsMfhc1,      // mfhc1 t,s [01000100011] t[20..16] s[15..11] [00000000000].
+  kMipsMthc1,      // mthc1 t,s [01000100111] t[20..16] s[15..11] [00000000000].
+  kMipsNop,        // nop [00000000000000000000000000000000].
+  kMipsNor,        // nor d,s,t [000000] s[25..21] t[20..16] d[15..11] [00000100111].
+  kMipsOr,         // or d,s,t [000000] s[25..21] t[20..16] d[15..11] [00000100101].
+  kMipsOri,        // ori t,s,imm16 [001001] s[25..21] t[20..16] imm16[15..0].
+  kMipsPref,       // pref h,o(b) [101011] b[25..21] h[20..16] o[15..0].
+  kMipsSb,         // sb t,o(b) [101000] b[25..21] t[20..16] o[15..0].
+  kMipsSeb,        // seb d,t [01111100000] t[20..16] d[15..11] [10000100000].
+  kMipsSeh,        // seh d,t [01111100000] t[20..16] d[15..11] [11000100000].
+  kMipsSh,         // sh t,o(b) [101001] b[25..21] t[20..16] o[15..0].
+  kMipsSll,        // sll d,t,a [00000000000] t[20..16] d[15..11] a[10..6] [000000].
+  kMipsSllv,       // sllv d,t,s [000000] s[25..21] t[20..16] d[15..11] [00000000100].
+  kMipsSlt,        // slt d,s,t [000000] s[25..21] t[20..16] d[15..11] [00000101010].
+  kMipsSlti,       // slti t,s,imm16 [001010] s[25..21] t[20..16] imm16[15..0].
+  kMipsSltu,       // sltu d,s,t [000000] s[25..21] t[20..16] d[15..11] [00000101011].
+  kMipsSra,        // sra d,s,imm5 [00000000000] t[20..16] d[15..11] imm5[10..6] [000011].
+  kMipsSrav,       // srav d,t,s [000000] s[25..21] t[20..16] d[15..11] [00000000111].
+  kMipsSrl,        // srl d,t,a [00000000000] t[20..16] d[20..16] a[10..6] [000010].
+  kMipsSrlv,       // srlv d,t,s [000000] s[25..21] t[20..16] d[15..11] [00000000110].
+  kMipsSubu,       // subu d,s,t [000000] s[25..21] t[20..16] d[15..11] [00000100011].
+  kMipsSw,         // sw t,o(b) [101011] b[25..21] t[20..16] o[15..0].
+  kMipsSync,       // sync kind [000000] [0000000000000000] s[10..6] [001111].
+  kMipsXor,        // xor d,s,t [000000] s[25..21] t[20..16] d[15..11] [00000100110].
+  kMipsXori,       // xori t,s,imm16 [001110] s[25..21] t[20..16] imm16[15..0].
 
-  // The following are mips32r6 instructions.
-  kMipsR6Div,   // div d,s,t [000000] s[25..21] t[20..16] d[15..11] [00010011010].
-  kMipsR6Mod,   // mod d,s,t [000000] s[25..21] t[20..16] d[15..11] [00011011010].
-  kMipsR6Mul,   // mul d,s,t [000000] s[25..21] t[20..16] d[15..11] [00010011000].
+  // The following are mips32r2 instructions.
+  kMipsR2Div,      // div s,t [000000] s[25..21] t[20..16] [0000000000011010].
+  kMipsR2Mul,      // mul d,s,t [011100] s[25..21] t[20..16] d[15..11] [00000000010].
+  kMipsR2Mfhi,     // mfhi d [0000000000000000] d[15..11] [00000010000].
+  kMipsR2Mflo,     // mflo d [0000000000000000] d[15..11] [00000010010].
+  kMipsR2Movz,     // movz d,s,t [000000] s[25..21] t[20..16] d[15..11] [00000001010].
 
+  // The following are mips32r6 and mips64r6 instructions.
+  kMipsR6Div,      // div d,s,t [000000] s[25..21] t[20..16] d[15..11] [00010011010].
+  kMipsR6Mod,      // mod d,s,t [000000] s[25..21] t[20..16] d[15..11] [00011011010].
+  kMipsR6Mul,      // mul d,s,t [000000] s[25..21] t[20..16] d[15..11] [00010011000].
+
+  // The following are mips64r6 instructions.
+  kMips64Daddiu,   // daddiu t,s,imm16 [011001] s[25..21] t[20..16] imm16[15..11].
+  kMips64Daddu,    // daddu d,s,t [000000] s[25..21] t[20..16] d[15..11] [00000101101].
+  kMips64Dahi,     // dahi s,imm16 [000001] s[25..21] [00110] imm16[15..11].
+  kMips64Dati,     // dati s,imm16 [000001] s[25..21] [11110] imm16[15..11].
+  kMips64Daui,     // daui t,s,imm16 [011101] s[25..21] t[20..16] imm16[15..11].
+  kMips64Ddiv,     // ddiv  d,s,t [000000] s[25..21] t[20..16] d[15..11] [00010011110].
+  kMips64Dmod,     // dmod  d,s,t [000000] s[25..21] t[20..16] d[15..11] [00011011110].
+  kMips64Dmul,     // dmul  d,s,t [000000] s[25..21] t[20..16] d[15..11] [00010011100].
+  kMips64Dmfc1,    // dmfc1 t,s [01000100001] t[20..16] s[15..11] [00000000000].
+  kMips64Dmtc1,    // dmtc1 t,s [01000100101] t[20..16] s[15..11] [00000000000].
+  kMips64Drotr32,  // drotr32 d,t,a [00000000001] t[20..16] d[15..11] a[10..6] [111110].
+  kMips64Dsll,     // dsll    d,t,a [00000000000] t[20..16] d[15..11] a[10..6] [111000].
+  kMips64Dsll32,   // dsll32  d,t,a [00000000000] t[20..16] d[15..11] a[10..6] [111100].
+  kMips64Dsrl,     // dsrl    d,t,a [00000000000] t[20..16] d[15..11] a[10..6] [111010].
+  kMips64Dsrl32,   // dsrl32  d,t,a [00000000000] t[20..16] d[15..11] a[10..6] [111110].
+  kMips64Dsra,     // dsra    d,t,a [00000000000] t[20..16] d[15..11] a[10..6] [111011].
+  kMips64Dsra32,   // dsra32  d,t,a [00000000000] t[20..16] d[15..11] a[10..6] [111111].
+  kMips64Dsllv,    // dsllv d,t,s [000000] s[25..21] t[20..16] d[15..11] [00000010100].
+  kMips64Dsrlv,    // dsrlv d,t,s [000000] s[25..21] t[20..16] d[15..11] [00000010110].
+  kMips64Dsrav,    // dsrav d,t,s [000000] s[25..21] t[20..16] d[15..11] [00000010111].
+  kMips64Dsubu,    // dsubu d,s,t [000000] s[25..21] t[20..16] d[15..11] [00000101111].
+  kMips64Ld,       // ld  t,o(b) [110111] b[25..21] t[20..16] o[15..0].
+  kMips64Lwu,      // lwu t,o(b) [100111] b[25..21] t[20..16] o[15..0].
+  kMips64Sd,       // sd t,o(b) [111111] b[25..21] t[20..16] o[15..0].
+
+  // The following are pseudoinstructions.
+  kMipsDelta,      // Psuedo for ori t, s, <label>-<label>.
+  kMipsDeltaHi,    // Pseudo for lui t, high16(<label>-<label>).
+  kMipsDeltaLo,    // Pseudo for ori t, s, low16(<label>-<label>).
+  kMipsCurrPC,     // jal to .+8 to materialize pc.
   kMipsUndefined,  // undefined [011001xxxxxxxxxxxxxxxx].
   kMipsLast
 };
@@ -503,7 +689,7 @@
   kFmtUnused,
   kFmtBitBlt,    // Bit string using end/start.
   kFmtDfp,       // Double FP reg.
-  kFmtSfp,       // Single FP reg
+  kFmtSfp,       // Single FP reg.
   kFmtBlt5_2,    // Same 5-bit field to 2 locations.
 };
 std::ostream& operator<<(std::ostream& os, const MipsEncodingKind& rhs);
diff --git a/compiler/dex/quick/mips/target_mips.cc b/compiler/dex/quick/mips/target_mips.cc
index 830f63a..a94fad7 100644
--- a/compiler/dex/quick/mips/target_mips.cc
+++ b/compiler/dex/quick/mips/target_mips.cc
@@ -30,55 +30,131 @@
 
 namespace art {
 
-static constexpr RegStorage core_regs_arr[] =
-    {rs_rZERO, rs_rAT, rs_rV0, rs_rV1, rs_rA0, rs_rA1, rs_rA2, rs_rA3, rs_rT0, rs_rT1, rs_rT2,
-     rs_rT3, rs_rT4, rs_rT5, rs_rT6, rs_rT7, rs_rS0, rs_rS1, rs_rS2, rs_rS3, rs_rS4, rs_rS5,
-     rs_rS6, rs_rS7, rs_rT8, rs_rT9, rs_rK0, rs_rK1, rs_rGP, rs_rSP, rs_rFP, rs_rRA};
-static constexpr RegStorage sp_regs_arr[] =
+static constexpr RegStorage core_regs_arr_32[] =
+    {rs_rZERO, rs_rAT, rs_rV0, rs_rV1, rs_rA0, rs_rA1, rs_rA2, rs_rA3, rs_rT0_32, rs_rT1_32,
+     rs_rT2_32, rs_rT3_32, rs_rT4_32, rs_rT5_32, rs_rT6_32, rs_rT7_32, rs_rS0, rs_rS1, rs_rS2,
+     rs_rS3, rs_rS4, rs_rS5, rs_rS6, rs_rS7, rs_rT8, rs_rT9, rs_rK0, rs_rK1, rs_rGP, rs_rSP, rs_rFP,
+     rs_rRA};
+static constexpr RegStorage sp_regs_arr_32[] =
     {rs_rF0, rs_rF1, rs_rF2, rs_rF3, rs_rF4, rs_rF5, rs_rF6, rs_rF7, rs_rF8, rs_rF9, rs_rF10,
      rs_rF11, rs_rF12, rs_rF13, rs_rF14, rs_rF15};
-static constexpr RegStorage dp_fr0_regs_arr[] =
+static constexpr RegStorage dp_fr0_regs_arr_32[] =
     {rs_rD0_fr0, rs_rD1_fr0, rs_rD2_fr0, rs_rD3_fr0, rs_rD4_fr0, rs_rD5_fr0, rs_rD6_fr0,
      rs_rD7_fr0};
-static constexpr RegStorage dp_fr1_regs_arr[] =
+static constexpr RegStorage dp_fr1_regs_arr_32[] =
     {rs_rD0_fr1, rs_rD1_fr1, rs_rD2_fr1, rs_rD3_fr1, rs_rD4_fr1, rs_rD5_fr1, rs_rD6_fr1,
      rs_rD7_fr1};
-static constexpr RegStorage reserved_regs_arr[] =
+static constexpr RegStorage reserved_regs_arr_32[] =
     {rs_rZERO, rs_rAT, rs_rS0, rs_rS1, rs_rK0, rs_rK1, rs_rGP, rs_rSP, rs_rRA};
-static constexpr RegStorage core_temps_arr[] =
-    {rs_rV0, rs_rV1, rs_rA0, rs_rA1, rs_rA2, rs_rA3, rs_rT0, rs_rT1, rs_rT2, rs_rT3, rs_rT4,
-     rs_rT5, rs_rT6, rs_rT7, rs_rT8};
-static constexpr RegStorage sp_temps_arr[] =
+static constexpr RegStorage core_temps_arr_32[] =
+    {rs_rV0, rs_rV1, rs_rA0, rs_rA1, rs_rA2, rs_rA3, rs_rT0_32, rs_rT1_32, rs_rT2_32, rs_rT3_32,
+     rs_rT4_32, rs_rT5_32, rs_rT6_32, rs_rT7_32, rs_rT8};
+static constexpr RegStorage sp_temps_arr_32[] =
     {rs_rF0, rs_rF1, rs_rF2, rs_rF3, rs_rF4, rs_rF5, rs_rF6, rs_rF7, rs_rF8, rs_rF9, rs_rF10,
      rs_rF11, rs_rF12, rs_rF13, rs_rF14, rs_rF15};
-static constexpr RegStorage dp_fr0_temps_arr[] =
+static constexpr RegStorage dp_fr0_temps_arr_32[] =
     {rs_rD0_fr0, rs_rD1_fr0, rs_rD2_fr0, rs_rD3_fr0, rs_rD4_fr0, rs_rD5_fr0, rs_rD6_fr0,
      rs_rD7_fr0};
-static constexpr RegStorage dp_fr1_temps_arr[] =
+static constexpr RegStorage dp_fr1_temps_arr_32[] =
     {rs_rD0_fr1, rs_rD1_fr1, rs_rD2_fr1, rs_rD3_fr1, rs_rD4_fr1, rs_rD5_fr1, rs_rD6_fr1,
      rs_rD7_fr1};
 
+static constexpr RegStorage core_regs_arr_64[] =
+    {rs_rZERO, rs_rAT, rs_rV0, rs_rV1, rs_rA0, rs_rA1, rs_rA2, rs_rA3, rs_rA4, rs_rA5, rs_rA6,
+     rs_rA7, rs_rT0, rs_rT1, rs_rT2, rs_rT3, rs_rS0, rs_rS1, rs_rS2, rs_rS3, rs_rS4, rs_rS5, rs_rS6,
+     rs_rS7, rs_rT8, rs_rT9, rs_rK0, rs_rK1, rs_rGP, rs_rSP, rs_rFP, rs_rRA};
+static constexpr RegStorage core_regs_arr_64d[] =
+    {rs_rZEROd, rs_rATd, rs_rV0d, rs_rV1d, rs_rA0d, rs_rA1d, rs_rA2d, rs_rA3d, rs_rA4d, rs_rA5d,
+     rs_rA6d, rs_rA7d, rs_rT0d, rs_rT1d, rs_rT2d, rs_rT3d, rs_rS0d, rs_rS1d, rs_rS2d, rs_rS3d,
+     rs_rS4d, rs_rS5d, rs_rS6d, rs_rS7d, rs_rT8d, rs_rT9d, rs_rK0d, rs_rK1d, rs_rGPd, rs_rSPd,
+     rs_rFPd, rs_rRAd};
+#if 0
+// TODO: f24-f31 must be saved before calls and restored after.
+static constexpr RegStorage sp_regs_arr_64[] =
+    {rs_rF0, rs_rF1, rs_rF2, rs_rF3, rs_rF4, rs_rF5, rs_rF6, rs_rF7, rs_rF8, rs_rF9, rs_rF10,
+     rs_rF11, rs_rF12, rs_rF13, rs_rF14, rs_rF15, rs_rF16, rs_rF17, rs_rF18, rs_rF19, rs_rF20,
+     rs_rF21, rs_rF22, rs_rF23, rs_rF24, rs_rF25, rs_rF26, rs_rF27, rs_rF28, rs_rF29, rs_rF30,
+     rs_rF31};
+static constexpr RegStorage dp_regs_arr_64[] =
+    {rs_rD0, rs_rD1, rs_rD2, rs_rD3, rs_rD4, rs_rD5, rs_rD6, rs_rD7, rs_rD8, rs_rD9, rs_rD10,
+     rs_rD11, rs_rD12, rs_rD13, rs_rD14, rs_rD15, rs_rD16, rs_rD17, rs_rD18, rs_rD19, rs_rD20,
+     rs_rD21, rs_rD22, rs_rD23, rs_rD24, rs_rD25, rs_rD26, rs_rD27, rs_rD28, rs_rD29, rs_rD30,
+     rs_rD31};
+#else
+static constexpr RegStorage sp_regs_arr_64[] =
+    {rs_rF0, rs_rF1, rs_rF2, rs_rF3, rs_rF4, rs_rF5, rs_rF6, rs_rF7, rs_rF8, rs_rF9, rs_rF10,
+     rs_rF11, rs_rF12, rs_rF13, rs_rF14, rs_rF15, rs_rF16, rs_rF17, rs_rF18, rs_rF19, rs_rF20,
+     rs_rF21, rs_rF22, rs_rF23};
+static constexpr RegStorage dp_regs_arr_64[] =
+    {rs_rD0, rs_rD1, rs_rD2, rs_rD3, rs_rD4, rs_rD5, rs_rD6, rs_rD7, rs_rD8, rs_rD9, rs_rD10,
+     rs_rD11, rs_rD12, rs_rD13, rs_rD14, rs_rD15, rs_rD16, rs_rD17, rs_rD18, rs_rD19, rs_rD20,
+     rs_rD21, rs_rD22, rs_rD23};
+#endif
+static constexpr RegStorage reserved_regs_arr_64[] =
+    {rs_rZERO, rs_rAT, rs_rS0, rs_rS1, rs_rT9, rs_rK0, rs_rK1, rs_rGP, rs_rSP, rs_rRA};
+static constexpr RegStorage reserved_regs_arr_64d[] =
+    {rs_rZEROd, rs_rATd, rs_rS0d, rs_rS1d, rs_rT9d, rs_rK0d, rs_rK1d, rs_rGPd, rs_rSPd, rs_rRAd};
+static constexpr RegStorage core_temps_arr_64[] =
+    {rs_rV0, rs_rV1, rs_rA0, rs_rA1, rs_rA2, rs_rA3, rs_rA4, rs_rA5, rs_rA6, rs_rA7, rs_rT0, rs_rT1,
+     rs_rT2, rs_rT3, rs_rT8};
+static constexpr RegStorage core_temps_arr_64d[] =
+    {rs_rV0d, rs_rV1d, rs_rA0d, rs_rA1d, rs_rA2d, rs_rA3d, rs_rA4d, rs_rA5d, rs_rA6d, rs_rA7d,
+     rs_rT0d, rs_rT1d, rs_rT2d, rs_rT3d, rs_rT8d};
+#if 0
+// TODO: f24-f31 must be saved before calls and restored after.
+static constexpr RegStorage sp_temps_arr_64[] =
+    {rs_rF0, rs_rF1, rs_rF2, rs_rF3, rs_rF4, rs_rF5, rs_rF6, rs_rF7, rs_rF8, rs_rF9, rs_rF10,
+     rs_rF11, rs_rF12, rs_rF13, rs_rF14, rs_rF15, rs_rF16, rs_rF17, rs_rF18, rs_rF19, rs_rF20,
+     rs_rF21, rs_rF22, rs_rF23, rs_rF24, rs_rF25, rs_rF26, rs_rF27, rs_rF28, rs_rF29, rs_rF30,
+     rs_rF31};
+static constexpr RegStorage dp_temps_arr_64[] =
+    {rs_rD0, rs_rD1, rs_rD2, rs_rD3, rs_rD4, rs_rD5, rs_rD6, rs_rD7, rs_rD8, rs_rD9, rs_rD10,
+     rs_rD11, rs_rD12, rs_rD13, rs_rD14, rs_rD15, rs_rD16, rs_rD17, rs_rD18, rs_rD19, rs_rD20,
+     rs_rD21, rs_rD22, rs_rD23, rs_rD24, rs_rD25, rs_rD26, rs_rD27, rs_rD28, rs_rD29, rs_rD30,
+     rs_rD31};
+#else
+static constexpr RegStorage sp_temps_arr_64[] =
+    {rs_rF0, rs_rF1, rs_rF2, rs_rF3, rs_rF4, rs_rF5, rs_rF6, rs_rF7, rs_rF8, rs_rF9, rs_rF10,
+     rs_rF11, rs_rF12, rs_rF13, rs_rF14, rs_rF15, rs_rF16, rs_rF17, rs_rF18, rs_rF19, rs_rF20,
+     rs_rF21, rs_rF22, rs_rF23};
+static constexpr RegStorage dp_temps_arr_64[] =
+    {rs_rD0, rs_rD1, rs_rD2, rs_rD3, rs_rD4, rs_rD5, rs_rD6, rs_rD7, rs_rD8, rs_rD9, rs_rD10,
+     rs_rD11, rs_rD12, rs_rD13, rs_rD14, rs_rD15, rs_rD16, rs_rD17, rs_rD18, rs_rD19, rs_rD20,
+     rs_rD21, rs_rD22, rs_rD23};
+#endif
+
 static constexpr ArrayRef<const RegStorage> empty_pool;
-static constexpr ArrayRef<const RegStorage> core_regs(core_regs_arr);
-static constexpr ArrayRef<const RegStorage> sp_regs(sp_regs_arr);
-static constexpr ArrayRef<const RegStorage> dp_fr0_regs(dp_fr0_regs_arr);
-static constexpr ArrayRef<const RegStorage> dp_fr1_regs(dp_fr1_regs_arr);
-static constexpr ArrayRef<const RegStorage> reserved_regs(reserved_regs_arr);
-static constexpr ArrayRef<const RegStorage> core_temps(core_temps_arr);
-static constexpr ArrayRef<const RegStorage> sp_temps(sp_temps_arr);
-static constexpr ArrayRef<const RegStorage> dp_fr0_temps(dp_fr0_temps_arr);
-static constexpr ArrayRef<const RegStorage> dp_fr1_temps(dp_fr1_temps_arr);
+static constexpr ArrayRef<const RegStorage> core_regs_32(core_regs_arr_32);
+static constexpr ArrayRef<const RegStorage> sp_regs_32(sp_regs_arr_32);
+static constexpr ArrayRef<const RegStorage> dp_fr0_regs_32(dp_fr0_regs_arr_32);
+static constexpr ArrayRef<const RegStorage> dp_fr1_regs_32(dp_fr1_regs_arr_32);
+static constexpr ArrayRef<const RegStorage> reserved_regs_32(reserved_regs_arr_32);
+static constexpr ArrayRef<const RegStorage> core_temps_32(core_temps_arr_32);
+static constexpr ArrayRef<const RegStorage> sp_temps_32(sp_temps_arr_32);
+static constexpr ArrayRef<const RegStorage> dp_fr0_temps_32(dp_fr0_temps_arr_32);
+static constexpr ArrayRef<const RegStorage> dp_fr1_temps_32(dp_fr1_temps_arr_32);
+
+static constexpr ArrayRef<const RegStorage> core_regs_64(core_regs_arr_64);
+static constexpr ArrayRef<const RegStorage> core_regs_64d(core_regs_arr_64d);
+static constexpr ArrayRef<const RegStorage> sp_regs_64(sp_regs_arr_64);
+static constexpr ArrayRef<const RegStorage> dp_regs_64(dp_regs_arr_64);
+static constexpr ArrayRef<const RegStorage> reserved_regs_64(reserved_regs_arr_64);
+static constexpr ArrayRef<const RegStorage> reserved_regs_64d(reserved_regs_arr_64d);
+static constexpr ArrayRef<const RegStorage> core_temps_64(core_temps_arr_64);
+static constexpr ArrayRef<const RegStorage> core_temps_64d(core_temps_arr_64d);
+static constexpr ArrayRef<const RegStorage> sp_temps_64(sp_temps_arr_64);
+static constexpr ArrayRef<const RegStorage> dp_temps_64(dp_temps_arr_64);
 
 RegLocation MipsMir2Lir::LocCReturn() {
   return mips_loc_c_return;
 }
 
 RegLocation MipsMir2Lir::LocCReturnRef() {
-  return mips_loc_c_return;
+  return cu_->target64 ? mips64_loc_c_return_ref : mips_loc_c_return;
 }
 
 RegLocation MipsMir2Lir::LocCReturnWide() {
-  return mips_loc_c_return_wide;
+  return cu_->target64 ? mips64_loc_c_return_wide : mips_loc_c_return_wide;
 }
 
 RegLocation MipsMir2Lir::LocCReturnFloat() {
@@ -86,14 +162,16 @@
 }
 
 RegLocation MipsMir2Lir::LocCReturnDouble() {
-  if (fpuIs32Bit_) {
-      return mips_loc_c_return_double_fr0;
+  if (cu_->target64) {
+    return mips64_loc_c_return_double;
+  } else if (fpuIs32Bit_) {
+    return mips_loc_c_return_double_fr0;
   } else {
-      return mips_loc_c_return_double_fr1;
+    return mips_loc_c_return_double_fr1;
   }
 }
 
-// Convert k64BitSolo into k64BitPair
+// Convert k64BitSolo into k64BitPair.
 RegStorage MipsMir2Lir::Solo64ToPair64(RegStorage reg) {
   DCHECK(reg.IsDouble());
   DCHECK_EQ(reg.GetRegNum() & 1, 0);
@@ -113,16 +191,18 @@
 
 // Return a target-dependent special register.
 RegStorage MipsMir2Lir::TargetReg(SpecialTargetRegister reg, WideKind wide_kind) {
-  if (wide_kind == kWide) {
-      DCHECK((kArg0 <= reg && reg < kArg7) || (kFArg0 <= reg && reg < kFArg15) || (kRet0 == reg));
-      RegStorage ret_reg = RegStorage::MakeRegPair(TargetReg(reg),
-                                       TargetReg(static_cast<SpecialTargetRegister>(reg + 1)));
-      if (!fpuIs32Bit_ && ret_reg.IsFloat()) {
-        // convert 64BitPair to 64BitSolo for 64bit FPUs.
-        RegStorage low = ret_reg.GetLow();
-        ret_reg = RegStorage::FloatSolo64(low.GetRegNum());
-      }
-      return ret_reg;
+  if (!cu_->target64 && wide_kind == kWide) {
+    DCHECK((kArg0 <= reg && reg < kArg7) || (kFArg0 <= reg && reg < kFArg15) || (kRet0 == reg));
+    RegStorage ret_reg = RegStorage::MakeRegPair(TargetReg(reg),
+                                     TargetReg(static_cast<SpecialTargetRegister>(reg + 1)));
+    if (!fpuIs32Bit_ && ret_reg.IsFloat()) {
+      // convert 64BitPair to 64BitSolo for 64bit FPUs.
+      RegStorage low = ret_reg.GetLow();
+      ret_reg = RegStorage::FloatSolo64(low.GetRegNum());
+    }
+    return ret_reg;
+  } else if (cu_->target64 && (wide_kind == kWide || wide_kind == kRef)) {
+    return As64BitReg(TargetReg(reg));
   } else {
     return TargetReg(reg);
   }
@@ -132,25 +212,33 @@
 RegStorage MipsMir2Lir::TargetReg(SpecialTargetRegister reg) {
   RegStorage res_reg;
   switch (reg) {
-    case kSelf: res_reg = rs_rMIPS_SELF; break;
-    case kSuspend: res_reg =  rs_rMIPS_SUSPEND; break;
-    case kLr: res_reg =  rs_rMIPS_LR; break;
-    case kPc: res_reg =  rs_rMIPS_PC; break;
-    case kSp: res_reg =  rs_rMIPS_SP; break;
-    case kArg0: res_reg = rs_rMIPS_ARG0; break;
-    case kArg1: res_reg = rs_rMIPS_ARG1; break;
-    case kArg2: res_reg = rs_rMIPS_ARG2; break;
-    case kArg3: res_reg = rs_rMIPS_ARG3; break;
-    case kFArg0: res_reg = rs_rMIPS_FARG0; break;
-    case kFArg1: res_reg = rs_rMIPS_FARG1; break;
-    case kFArg2: res_reg = rs_rMIPS_FARG2; break;
-    case kFArg3: res_reg = rs_rMIPS_FARG3; break;
-    case kRet0: res_reg = rs_rMIPS_RET0; break;
-    case kRet1: res_reg = rs_rMIPS_RET1; break;
-    case kInvokeTgt: res_reg = rs_rMIPS_INVOKE_TGT; break;
-    case kHiddenArg: res_reg = rs_rT0; break;
+    case kSelf: res_reg = rs_rS1; break;
+    case kSuspend: res_reg =  rs_rS0; break;
+    case kLr: res_reg =  rs_rRA; break;
+    case kPc: res_reg = RegStorage::InvalidReg(); break;
+    case kSp: res_reg =  rs_rSP; break;
+    case kArg0: res_reg = rs_rA0; break;
+    case kArg1: res_reg = rs_rA1; break;
+    case kArg2: res_reg = rs_rA2; break;
+    case kArg3: res_reg = rs_rA3; break;
+    case kArg4: res_reg = cu_->target64 ? rs_rA4 : RegStorage::InvalidReg(); break;
+    case kArg5: res_reg = cu_->target64 ? rs_rA5 : RegStorage::InvalidReg(); break;
+    case kArg6: res_reg = cu_->target64 ? rs_rA6 : RegStorage::InvalidReg(); break;
+    case kArg7: res_reg = cu_->target64 ? rs_rA7 : RegStorage::InvalidReg(); break;
+    case kFArg0: res_reg = rs_rF12; break;
+    case kFArg1: res_reg = rs_rF13; break;
+    case kFArg2: res_reg = rs_rF14; break;
+    case kFArg3: res_reg = rs_rF15; break;
+    case kFArg4: res_reg = cu_->target64 ? rs_rF16 : RegStorage::InvalidReg(); break;
+    case kFArg5: res_reg = cu_->target64 ? rs_rF17 : RegStorage::InvalidReg(); break;
+    case kFArg6: res_reg = cu_->target64 ? rs_rF18 : RegStorage::InvalidReg(); break;
+    case kFArg7: res_reg = cu_->target64 ? rs_rF19 : RegStorage::InvalidReg(); break;
+    case kRet0: res_reg = rs_rV0; break;
+    case kRet1: res_reg = rs_rV1; break;
+    case kInvokeTgt: res_reg = rs_rT9; break;
+    case kHiddenArg: res_reg = cu_->target64 ? rs_rT0 : rs_rT0_32; break;
     case kHiddenFpArg: res_reg = RegStorage::InvalidReg(); break;
-    case kCount: res_reg = rs_rMIPS_COUNT; break;
+    case kCount: res_reg = RegStorage::InvalidReg(); break;
     default: res_reg = RegStorage::InvalidReg();
   }
   return res_reg;
@@ -172,27 +260,54 @@
   return result;
 }
 
+RegStorage MipsMir2Lir::InToRegStorageMips64Mapper::GetNextReg(ShortyArg arg) {
+  const SpecialTargetRegister coreArgMappingToPhysicalReg[] =
+      {kArg1, kArg2, kArg3, kArg4, kArg5, kArg6, kArg7};
+  const size_t coreArgMappingToPhysicalRegSize = arraysize(coreArgMappingToPhysicalReg);
+  const SpecialTargetRegister fpArgMappingToPhysicalReg[] =
+      {kFArg1, kFArg2, kFArg3, kFArg4, kFArg5, kFArg6, kFArg7};
+  const size_t fpArgMappingToPhysicalRegSize = arraysize(fpArgMappingToPhysicalReg);
+
+  RegStorage result = RegStorage::InvalidReg();
+  if (arg.IsFP()) {
+    if (cur_arg_reg_ < fpArgMappingToPhysicalRegSize) {
+      DCHECK(!arg.IsRef());
+      result = m2l_->TargetReg(fpArgMappingToPhysicalReg[cur_arg_reg_++],
+                               arg.IsWide() ? kWide : kNotWide);
+    }
+  } else {
+    if (cur_arg_reg_ < coreArgMappingToPhysicalRegSize) {
+      DCHECK(!(arg.IsWide() && arg.IsRef()));
+      result = m2l_->TargetReg(coreArgMappingToPhysicalReg[cur_arg_reg_++],
+                               arg.IsRef() ? kRef : (arg.IsWide() ? kWide : kNotWide));
+    }
+  }
+  return result;
+}
+
 /*
  * Decode the register id.
  */
 ResourceMask MipsMir2Lir::GetRegMaskCommon(const RegStorage& reg) const {
-  if (reg.IsDouble()) {
-    return ResourceMask::TwoBits((reg.GetRegNum() & ~1) + kMipsFPReg0);
-  } else if (reg.IsSingle()) {
-    return ResourceMask::Bit(reg.GetRegNum() + kMipsFPReg0);
+  if (cu_->target64) {
+    return ResourceMask::Bit((reg.IsFloat() ? kMipsFPReg0 : 0) + reg.GetRegNum());
   } else {
-    return ResourceMask::Bit(reg.GetRegNum());
+    if (reg.IsDouble()) {
+      return ResourceMask::TwoBits((reg.GetRegNum() & ~1) + kMipsFPReg0);
+    } else if (reg.IsSingle()) {
+      return ResourceMask::Bit(reg.GetRegNum() + kMipsFPReg0);
+    } else {
+      return ResourceMask::Bit(reg.GetRegNum());
+    }
   }
 }
 
 ResourceMask MipsMir2Lir::GetPCUseDefEncoding() const {
-  return ResourceMask::Bit(kMipsRegPC);
+  return cu_->target64 ? ResourceMask::Bit(kMips64RegPC) : ResourceMask::Bit(kMipsRegPC);
 }
 
-
-void MipsMir2Lir::SetupTargetResourceMasks(LIR* lir, uint64_t flags,
-                                           ResourceMask* use_mask, ResourceMask* def_mask) {
-  DCHECK_EQ(cu_->instruction_set, kMips);
+void MipsMir2Lir::SetupTargetResourceMasks(LIR* lir, uint64_t flags, ResourceMask* use_mask,
+                                           ResourceMask* def_mask) {
   DCHECK(!lir->flags.use_def_invalid);
 
   // Mips-specific resource map setup here.
@@ -208,20 +323,22 @@
     def_mask->SetBit(kMipsRegLR);
   }
 
-  if (flags & REG_DEF_HI) {
-    def_mask->SetBit(kMipsRegHI);
-  }
+  if (!cu_->target64) {
+    if (flags & REG_DEF_HI) {
+      def_mask->SetBit(kMipsRegHI);
+    }
 
-  if (flags & REG_DEF_LO) {
-    def_mask->SetBit(kMipsRegLO);
-  }
+    if (flags & REG_DEF_LO) {
+      def_mask->SetBit(kMipsRegLO);
+    }
 
-  if (flags & REG_USE_HI) {
-    use_mask->SetBit(kMipsRegHI);
-  }
+    if (flags & REG_USE_HI) {
+      use_mask->SetBit(kMipsRegHI);
+    }
 
-  if (flags & REG_USE_LO) {
-    use_mask->SetBit(kMipsRegLO);
+    if (flags & REG_USE_LO) {
+      use_mask->SetBit(kMipsRegLO);
+    }
   }
 }
 
@@ -234,9 +351,16 @@
   "t8", "t9", "k0", "k1", "gp", "sp", "fp", "ra"
 };
 
+static const char *mips64_reg_name[MIPS_REG_COUNT] = {
+  "zero", "at", "v0", "v1", "a0", "a1", "a2", "a3",
+  "a4", "a5", "a6", "a7", "t0", "t1", "t2", "t3",
+  "s0", "s1", "s2", "s3", "s4", "s5", "s6", "s7",
+  "t8", "t9", "k0", "k1", "gp", "sp", "fp", "ra"
+};
+
 /*
  * Interpret a format string and build a string no longer than size
- * See format key in Assemble.c.
+ * See format key in assemble_mips.cc.
  */
 std::string MipsMir2Lir::BuildInsnString(const char *fmt, LIR *lir, unsigned char* base_addr) {
   std::string buf;
@@ -311,7 +435,11 @@
             break;
           case 'r':
             DCHECK(operand >= 0 && operand < MIPS_REG_COUNT);
-            strcpy(tbuf, mips_reg_name[operand]);
+            if (cu_->target64) {
+              strcpy(tbuf, mips64_reg_name[operand]);
+            } else {
+              strcpy(tbuf, mips_reg_name[operand]);
+            }
             break;
           case 'N':
             // Placeholder for delay slot handling
@@ -330,7 +458,7 @@
   return buf;
 }
 
-// FIXME: need to redo resource maps for MIPS - fix this at that time
+// FIXME: need to redo resource maps for MIPS - fix this at that time.
 void MipsMir2Lir::DumpResourceMask(LIR *mips_lir, const ResourceMask& mask, const char *prefix) {
   char buf[256];
   buf[0] = 0;
@@ -341,7 +469,7 @@
     char num[8];
     int i;
 
-    for (i = 0; i < kMipsRegEnd; i++) {
+    for (i = 0; i < (cu_->target64 ? kMips64RegEnd : kMipsRegEnd); i++) {
       if (mask.HasBit(i)) {
         snprintf(num, arraysize(num), "%d ", i);
         strcat(buf, num);
@@ -354,7 +482,7 @@
     if (mask.HasBit(ResourceMask::kFPStatus)) {
       strcat(buf, "fpcc ");
     }
-    /* Memory bits */
+    // Memory bits.
     if (mips_lir && (mask.HasBit(ResourceMask::kDalvikReg))) {
       snprintf(buf + strlen(buf), arraysize(buf) - strlen(buf), "dr%d%s",
                DECODE_ALIAS_INFO_REG(mips_lir->flags.alias_info),
@@ -389,63 +517,114 @@
 
 /* Clobber all regs that might be used by an external C call */
 void MipsMir2Lir::ClobberCallerSave() {
-  Clobber(rs_rZERO);
-  Clobber(rs_rAT);
-  Clobber(rs_rV0);
-  Clobber(rs_rV1);
-  Clobber(rs_rA0);
-  Clobber(rs_rA1);
-  Clobber(rs_rA2);
-  Clobber(rs_rA3);
-  Clobber(rs_rT0);
-  Clobber(rs_rT1);
-  Clobber(rs_rT2);
-  Clobber(rs_rT3);
-  Clobber(rs_rT4);
-  Clobber(rs_rT5);
-  Clobber(rs_rT6);
-  Clobber(rs_rT7);
-  Clobber(rs_rT8);
-  Clobber(rs_rT9);
-  Clobber(rs_rK0);
-  Clobber(rs_rK1);
-  Clobber(rs_rGP);
-  Clobber(rs_rFP);
-  Clobber(rs_rRA);
-  Clobber(rs_rF0);
-  Clobber(rs_rF1);
-  Clobber(rs_rF2);
-  Clobber(rs_rF3);
-  Clobber(rs_rF4);
-  Clobber(rs_rF5);
-  Clobber(rs_rF6);
-  Clobber(rs_rF7);
-  Clobber(rs_rF8);
-  Clobber(rs_rF9);
-  Clobber(rs_rF10);
-  Clobber(rs_rF11);
-  Clobber(rs_rF12);
-  Clobber(rs_rF13);
-  Clobber(rs_rF14);
-  Clobber(rs_rF15);
-  if (fpuIs32Bit_) {
-    Clobber(rs_rD0_fr0);
-    Clobber(rs_rD1_fr0);
-    Clobber(rs_rD2_fr0);
-    Clobber(rs_rD3_fr0);
-    Clobber(rs_rD4_fr0);
-    Clobber(rs_rD5_fr0);
-    Clobber(rs_rD6_fr0);
-    Clobber(rs_rD7_fr0);
+  if (cu_->target64) {
+    Clobber(rs_rZEROd);
+    Clobber(rs_rATd);
+    Clobber(rs_rV0d);
+    Clobber(rs_rV1d);
+    Clobber(rs_rA0d);
+    Clobber(rs_rA1d);
+    Clobber(rs_rA2d);
+    Clobber(rs_rA3d);
+    Clobber(rs_rA4d);
+    Clobber(rs_rA5d);
+    Clobber(rs_rA6d);
+    Clobber(rs_rA7d);
+    Clobber(rs_rT0d);
+    Clobber(rs_rT1d);
+    Clobber(rs_rT2d);
+    Clobber(rs_rT3d);
+    Clobber(rs_rT8d);
+    Clobber(rs_rT9d);
+    Clobber(rs_rK0d);
+    Clobber(rs_rK1d);
+    Clobber(rs_rGPd);
+    Clobber(rs_rFPd);
+    Clobber(rs_rRAd);
+
+    Clobber(rs_rF0);
+    Clobber(rs_rF1);
+    Clobber(rs_rF2);
+    Clobber(rs_rF3);
+    Clobber(rs_rF4);
+    Clobber(rs_rF5);
+    Clobber(rs_rF6);
+    Clobber(rs_rF7);
+    Clobber(rs_rF8);
+    Clobber(rs_rF9);
+    Clobber(rs_rF10);
+    Clobber(rs_rF11);
+    Clobber(rs_rF12);
+    Clobber(rs_rF13);
+    Clobber(rs_rF14);
+    Clobber(rs_rF15);
+    Clobber(rs_rD0);
+    Clobber(rs_rD1);
+    Clobber(rs_rD2);
+    Clobber(rs_rD3);
+    Clobber(rs_rD4);
+    Clobber(rs_rD5);
+    Clobber(rs_rD6);
+    Clobber(rs_rD7);
   } else {
-    Clobber(rs_rD0_fr1);
-    Clobber(rs_rD1_fr1);
-    Clobber(rs_rD2_fr1);
-    Clobber(rs_rD3_fr1);
-    Clobber(rs_rD4_fr1);
-    Clobber(rs_rD5_fr1);
-    Clobber(rs_rD6_fr1);
-    Clobber(rs_rD7_fr1);
+    Clobber(rs_rZERO);
+    Clobber(rs_rAT);
+    Clobber(rs_rV0);
+    Clobber(rs_rV1);
+    Clobber(rs_rA0);
+    Clobber(rs_rA1);
+    Clobber(rs_rA2);
+    Clobber(rs_rA3);
+    Clobber(rs_rT0_32);
+    Clobber(rs_rT1_32);
+    Clobber(rs_rT2_32);
+    Clobber(rs_rT3_32);
+    Clobber(rs_rT4_32);
+    Clobber(rs_rT5_32);
+    Clobber(rs_rT6_32);
+    Clobber(rs_rT7_32);
+    Clobber(rs_rT8);
+    Clobber(rs_rT9);
+    Clobber(rs_rK0);
+    Clobber(rs_rK1);
+    Clobber(rs_rGP);
+    Clobber(rs_rFP);
+    Clobber(rs_rRA);
+    Clobber(rs_rF0);
+    Clobber(rs_rF1);
+    Clobber(rs_rF2);
+    Clobber(rs_rF3);
+    Clobber(rs_rF4);
+    Clobber(rs_rF5);
+    Clobber(rs_rF6);
+    Clobber(rs_rF7);
+    Clobber(rs_rF8);
+    Clobber(rs_rF9);
+    Clobber(rs_rF10);
+    Clobber(rs_rF11);
+    Clobber(rs_rF12);
+    Clobber(rs_rF13);
+    Clobber(rs_rF14);
+    Clobber(rs_rF15);
+    if (fpuIs32Bit_) {
+      Clobber(rs_rD0_fr0);
+      Clobber(rs_rD1_fr0);
+      Clobber(rs_rD2_fr0);
+      Clobber(rs_rD3_fr0);
+      Clobber(rs_rD4_fr0);
+      Clobber(rs_rD5_fr0);
+      Clobber(rs_rD6_fr0);
+      Clobber(rs_rD7_fr0);
+    } else {
+      Clobber(rs_rD0_fr1);
+      Clobber(rs_rD1_fr1);
+      Clobber(rs_rD2_fr1);
+      Clobber(rs_rD3_fr1);
+      Clobber(rs_rD4_fr1);
+      Clobber(rs_rD5_fr1);
+      Clobber(rs_rD6_fr1);
+      Clobber(rs_rD7_fr1);
+    }
   }
 }
 
@@ -463,18 +642,30 @@
 
 /* To be used when explicitly managing register use */
 void MipsMir2Lir::LockCallTemps() {
-  LockTemp(rs_rMIPS_ARG0);
-  LockTemp(rs_rMIPS_ARG1);
-  LockTemp(rs_rMIPS_ARG2);
-  LockTemp(rs_rMIPS_ARG3);
+  LockTemp(TargetReg(kArg0));
+  LockTemp(TargetReg(kArg1));
+  LockTemp(TargetReg(kArg2));
+  LockTemp(TargetReg(kArg3));
+  if (cu_->target64) {
+    LockTemp(TargetReg(kArg4));
+    LockTemp(TargetReg(kArg5));
+    LockTemp(TargetReg(kArg6));
+    LockTemp(TargetReg(kArg7));
+  }
 }
 
 /* To be used when explicitly managing register use */
 void MipsMir2Lir::FreeCallTemps() {
-  FreeTemp(rs_rMIPS_ARG0);
-  FreeTemp(rs_rMIPS_ARG1);
-  FreeTemp(rs_rMIPS_ARG2);
-  FreeTemp(rs_rMIPS_ARG3);
+  FreeTemp(TargetReg(kArg0));
+  FreeTemp(TargetReg(kArg1));
+  FreeTemp(TargetReg(kArg2));
+  FreeTemp(TargetReg(kArg3));
+  if (cu_->target64) {
+    FreeTemp(TargetReg(kArg4));
+    FreeTemp(TargetReg(kArg5));
+    FreeTemp(TargetReg(kArg6));
+    FreeTemp(TargetReg(kArg7));
+  }
   FreeTemp(TargetReg(kHiddenArg));
 }
 
@@ -488,31 +679,63 @@
 }
 
 void MipsMir2Lir::CompilerInitializeRegAlloc() {
-  reg_pool_.reset(new (arena_) RegisterPool(this, arena_, core_regs, empty_pool /* core64 */,
-                                            sp_regs,
-                                            fpuIs32Bit_ ? dp_fr0_regs : dp_fr1_regs,
-                                            reserved_regs, empty_pool /* reserved64 */,
-                                            core_temps, empty_pool /* core64_temps */,
-                                            sp_temps,
-                                            fpuIs32Bit_ ? dp_fr0_temps : dp_fr1_temps));
+  if (cu_->target64) {
+    reg_pool_.reset(new (arena_) RegisterPool(this, arena_, core_regs_64, core_regs_64d, sp_regs_64,
+                                              dp_regs_64, reserved_regs_64, reserved_regs_64d,
+                                              core_temps_64, core_temps_64d, sp_temps_64,
+                                              dp_temps_64));
 
-  // Target-specific adjustments.
+    // Alias single precision floats to appropriate half of overlapping double.
+    for (RegisterInfo* info : reg_pool_->sp_regs_) {
+      int sp_reg_num = info->GetReg().GetRegNum();
+      int dp_reg_num = sp_reg_num;
+      RegStorage dp_reg = RegStorage::Solo64(RegStorage::kFloatingPoint | dp_reg_num);
+      RegisterInfo* dp_reg_info = GetRegInfo(dp_reg);
+      // Double precision register's master storage should refer to itself.
+      DCHECK_EQ(dp_reg_info, dp_reg_info->Master());
+      // Redirect single precision's master storage to master.
+      info->SetMaster(dp_reg_info);
+      // Singles should show a single 32-bit mask bit, at first referring to the low half.
+      DCHECK_EQ(info->StorageMask(), 0x1U);
+    }
 
-  // Alias single precision floats to appropriate half of overlapping double.
-  for (RegisterInfo* info : reg_pool_->sp_regs_) {
-    int sp_reg_num = info->GetReg().GetRegNum();
-    int dp_reg_num = sp_reg_num & ~1;
-    RegStorage dp_reg = RegStorage::Solo64(RegStorage::kFloatingPoint | dp_reg_num);
-    RegisterInfo* dp_reg_info = GetRegInfo(dp_reg);
-    // Double precision register's master storage should refer to itself.
-    DCHECK_EQ(dp_reg_info, dp_reg_info->Master());
-    // Redirect single precision's master storage to master.
-    info->SetMaster(dp_reg_info);
-    // Singles should show a single 32-bit mask bit, at first referring to the low half.
-    DCHECK_EQ(info->StorageMask(), 0x1U);
-    if (sp_reg_num & 1) {
-      // For odd singles, change to user the high word of the backing double.
-      info->SetStorageMask(0x2);
+    // Alias 32bit W registers to corresponding 64bit X registers.
+    for (RegisterInfo* info : reg_pool_->core_regs_) {
+      int d_reg_num = info->GetReg().GetRegNum();
+      RegStorage d_reg = RegStorage::Solo64(d_reg_num);
+      RegisterInfo* d_reg_info = GetRegInfo(d_reg);
+      // 64bit D register's master storage should refer to itself.
+      DCHECK_EQ(d_reg_info, d_reg_info->Master());
+      // Redirect 32bit master storage to 64bit D.
+      info->SetMaster(d_reg_info);
+      // 32bit should show a single 32-bit mask bit, at first referring to the low half.
+      DCHECK_EQ(info->StorageMask(), 0x1U);
+    }
+  } else {
+    reg_pool_.reset(new (arena_) RegisterPool(this, arena_, core_regs_32, empty_pool,  // core64
+                                              sp_regs_32,
+                                              fpuIs32Bit_ ? dp_fr0_regs_32 : dp_fr1_regs_32,
+                                              reserved_regs_32, empty_pool,  // reserved64
+                                              core_temps_32, empty_pool,  // core64_temps
+                                              sp_temps_32,
+                                              fpuIs32Bit_ ? dp_fr0_temps_32 : dp_fr1_temps_32));
+
+    // Alias single precision floats to appropriate half of overlapping double.
+    for (RegisterInfo* info : reg_pool_->sp_regs_) {
+      int sp_reg_num = info->GetReg().GetRegNum();
+      int dp_reg_num = sp_reg_num & ~1;
+      RegStorage dp_reg = RegStorage::Solo64(RegStorage::kFloatingPoint | dp_reg_num);
+      RegisterInfo* dp_reg_info = GetRegInfo(dp_reg);
+      // Double precision register's master storage should refer to itself.
+      DCHECK_EQ(dp_reg_info, dp_reg_info->Master());
+      // Redirect single precision's master storage to master.
+      info->SetMaster(dp_reg_info);
+      // Singles should show a single 32-bit mask bit, at first referring to the low half.
+      DCHECK_EQ(info->StorageMask(), 0x1U);
+      if (sp_reg_num & 1) {
+        // For odd singles, change to user the high word of the backing double.
+        info->SetStorageMask(0x2);
+      }
     }
   }
 
@@ -520,7 +743,11 @@
   // TODO: adjust when we roll to hard float calling convention.
   reg_pool_->next_core_reg_ = 2;
   reg_pool_->next_sp_reg_ = 2;
-  reg_pool_->next_dp_reg_ = 2;
+  if (cu_->target64) {
+    reg_pool_->next_dp_reg_ = 1;
+  } else {
+    reg_pool_->next_dp_reg_ = 2;
+  }
 }
 
 /*
@@ -531,14 +758,24 @@
  */
 RegStorage MipsMir2Lir::LoadHelper(QuickEntrypointEnum trampoline) {
   // NOTE: native pointer.
-  LoadWordDisp(rs_rMIPS_SELF, GetThreadOffset<4>(trampoline).Int32Value(), rs_rT9);
-  return rs_rT9;
+  if (cu_->target64) {
+    LoadWordDisp(TargetPtrReg(kSelf), GetThreadOffset<8>(trampoline).Int32Value(),
+                 TargetPtrReg(kInvokeTgt));
+  } else {
+    LoadWordDisp(TargetPtrReg(kSelf), GetThreadOffset<4>(trampoline).Int32Value(),
+                 TargetPtrReg(kInvokeTgt));
+  }
+  return TargetPtrReg(kInvokeTgt);
 }
 
 LIR* MipsMir2Lir::CheckSuspendUsingLoad() {
   RegStorage tmp = AllocTemp();
   // NOTE: native pointer.
-  LoadWordDisp(rs_rMIPS_SELF, Thread::ThreadSuspendTriggerOffset<4>().Int32Value(), tmp);
+  if (cu_->target64) {
+    LoadWordDisp(TargetPtrReg(kSelf), Thread::ThreadSuspendTriggerOffset<8>().Int32Value(), tmp);
+  } else {
+    LoadWordDisp(TargetPtrReg(kSelf), Thread::ThreadSuspendTriggerOffset<4>().Int32Value(), tmp);
+  }
   LIR *inst = LoadWordDisp(tmp, 0, tmp);
   FreeTemp(tmp);
   return inst;
@@ -546,31 +783,47 @@
 
 LIR* MipsMir2Lir::GenAtomic64Load(RegStorage r_base, int displacement, RegStorage r_dest) {
   DCHECK(!r_dest.IsFloat());  // See RegClassForFieldLoadStore().
-  DCHECK(r_dest.IsPair());
+  if (!cu_->target64) {
+    DCHECK(r_dest.IsPair());
+  }
   ClobberCallerSave();
-  LockCallTemps();  // Using fixed registers
+  LockCallTemps();  // Using fixed registers.
   RegStorage reg_ptr = TargetReg(kArg0);
   OpRegRegImm(kOpAdd, reg_ptr, r_base, displacement);
   RegStorage r_tgt = LoadHelper(kQuickA64Load);
   LIR *ret = OpReg(kOpBlx, r_tgt);
-  RegStorage reg_ret = RegStorage::MakeRegPair(TargetReg(kRet0), TargetReg(kRet1));
-  OpRegCopyWide(r_dest, reg_ret);
+  RegStorage reg_ret;
+  if (cu_->target64) {
+    OpRegCopy(r_dest, TargetReg(kRet0));
+  } else {
+    reg_ret = RegStorage::MakeRegPair(TargetReg(kRet0), TargetReg(kRet1));
+    OpRegCopyWide(r_dest, reg_ret);
+  }
   return ret;
 }
 
 LIR* MipsMir2Lir::GenAtomic64Store(RegStorage r_base, int displacement, RegStorage r_src) {
   DCHECK(!r_src.IsFloat());  // See RegClassForFieldLoadStore().
-  DCHECK(r_src.IsPair());
+  if (cu_->target64) {
+    DCHECK(!r_src.IsPair());
+  } else {
+    DCHECK(r_src.IsPair());
+  }
   ClobberCallerSave();
-  LockCallTemps();  // Using fixed registers
+  LockCallTemps();  // Using fixed registers.
   RegStorage temp_ptr = AllocTemp();
   OpRegRegImm(kOpAdd, temp_ptr, r_base, displacement);
   RegStorage temp_value = AllocTempWide();
   OpRegCopyWide(temp_value, r_src);
-  RegStorage reg_ptr = TargetReg(kArg0);
-  OpRegCopy(reg_ptr, temp_ptr);
-  RegStorage reg_value = RegStorage::MakeRegPair(TargetReg(kArg2), TargetReg(kArg3));
-  OpRegCopyWide(reg_value, temp_value);
+  if (cu_->target64) {
+    OpRegCopyWide(TargetReg(kArg0, kWide), temp_ptr);
+    OpRegCopyWide(TargetReg(kArg1, kWide), temp_value);
+  } else {
+    RegStorage reg_ptr = TargetReg(kArg0);
+    OpRegCopy(reg_ptr, temp_ptr);
+    RegStorage reg_value = RegStorage::MakeRegPair(TargetReg(kArg2), TargetReg(kArg3));
+    OpRegCopyWide(reg_value, temp_value);
+  }
   FreeTemp(temp_ptr);
   FreeTemp(temp_value);
   RegStorage r_tgt = LoadHelper(kQuickA64Store);
@@ -582,12 +835,15 @@
     return;
   }
   uint32_t mask = core_spill_mask_;
-  int offset = num_core_spills_ * 4;
-  OpRegImm(kOpSub, rs_rSP, offset);
+  int ptr_size = cu_->target64 ? 8 : 4;
+  int offset = num_core_spills_ * ptr_size;
+  const RegStorage rs_sp = TargetPtrReg(kSp);
+  OpRegImm(kOpSub, rs_sp, offset);
   for (int reg = 0; mask; mask >>= 1, reg++) {
     if (mask & 0x1) {
-      offset -= 4;
-      Store32Disp(rs_rMIPS_SP, offset, RegStorage::Solo32(reg));
+      offset -= ptr_size;
+      StoreWordDisp(rs_sp, offset,
+                    cu_->target64 ? RegStorage::Solo64(reg) : RegStorage::Solo32(reg));
     }
   }
 }
@@ -597,14 +853,17 @@
     return;
   }
   uint32_t mask = core_spill_mask_;
-  int offset = frame_size_;
+  int offset  = frame_size_;
+  int ptr_size = cu_->target64 ? 8 : 4;
+  const RegStorage rs_sp = TargetPtrReg(kSp);
   for (int reg = 0; mask; mask >>= 1, reg++) {
     if (mask & 0x1) {
-      offset -= 4;
-      Load32Disp(rs_rMIPS_SP, offset, RegStorage::Solo32(reg));
+      offset -= ptr_size;
+      LoadWordDisp(rs_sp, offset,
+                   cu_->target64 ? RegStorage::Solo64(reg) : RegStorage::Solo32(reg));
     }
   }
-  OpRegImm(kOpAdd, rs_rSP, frame_size_);
+  OpRegImm(kOpAdd, rs_sp, frame_size_);
 }
 
 bool MipsMir2Lir::IsUnconditionalBranch(LIR* lir) {
@@ -624,11 +883,12 @@
 }
 
 MipsMir2Lir::MipsMir2Lir(CompilationUnit* cu, MIRGraph* mir_graph, ArenaAllocator* arena)
-    : Mir2Lir(cu, mir_graph, arena), in_to_reg_storage_mips_mapper_(this),
-      isaIsR6_(cu->compiler_driver->GetInstructionSetFeatures()
-                 ->AsMipsInstructionSetFeatures()->IsR6()),
-      fpuIs32Bit_(cu->compiler_driver->GetInstructionSetFeatures()
-                    ->AsMipsInstructionSetFeatures()->Is32BitFloatingPoint()) {
+    : Mir2Lir(cu, mir_graph, arena), in_to_reg_storage_mips64_mapper_(this),
+    in_to_reg_storage_mips_mapper_(this),
+    isaIsR6_(cu_->target64 ? true : cu->compiler_driver->GetInstructionSetFeatures()
+                ->AsMipsInstructionSetFeatures()->IsR6()),
+    fpuIs32Bit_(cu_->target64 ? false : cu->compiler_driver->GetInstructionSetFeatures()
+                   ->AsMipsInstructionSetFeatures()->Is32BitFloatingPoint()) {
   for (int i = 0; i < kMipsLast; i++) {
     DCHECK_EQ(MipsMir2Lir::EncodingMap[i].opcode, i)
         << "Encoding order for " << MipsMir2Lir::EncodingMap[i].name
diff --git a/compiler/dex/quick/mips/utility_mips.cc b/compiler/dex/quick/mips/utility_mips.cc
index 3b7e0ed..bf0e0fc 100644
--- a/compiler/dex/quick/mips/utility_mips.cc
+++ b/compiler/dex/quick/mips/utility_mips.cc
@@ -26,30 +26,70 @@
 
 namespace art {
 
-/* This file contains codegen for the MIPS32 ISA. */
+/* This file contains codegen for the Mips ISA */
 LIR* MipsMir2Lir::OpFpRegCopy(RegStorage r_dest, RegStorage r_src) {
   int opcode;
-  /* must be both DOUBLE or both not DOUBLE */
-  DCHECK_EQ(r_dest.IsDouble(), r_src.IsDouble());
-  if (r_dest.IsDouble()) {
-    opcode = kMipsFmovd;
-  } else {
-    if (r_dest.IsSingle()) {
-      if (r_src.IsSingle()) {
-        opcode = kMipsFmovs;
+  if (cu_->target64) {
+    DCHECK_EQ(r_dest.Is64Bit(), r_src.Is64Bit());
+    if (r_dest.Is64Bit()) {
+      if (r_dest.IsDouble()) {
+        if (r_src.IsDouble()) {
+          opcode = kMipsFmovd;
+        } else {
+          // Note the operands are swapped for the dmtc1 instr.
+          RegStorage t_opnd = r_src;
+          r_src = r_dest;
+          r_dest = t_opnd;
+          opcode = kMips64Dmtc1;
+        }
       } else {
-        /* note the operands are swapped for the mtc1 instr */
-        RegStorage t_opnd = r_src;
-        r_src = r_dest;
-        r_dest = t_opnd;
-        opcode = kMipsMtc1;
+        DCHECK(r_src.IsDouble());
+        opcode = kMips64Dmfc1;
       }
     } else {
-      DCHECK(r_src.IsSingle());
-      opcode = kMipsMfc1;
+      if (r_dest.IsSingle()) {
+        if (r_src.IsSingle()) {
+          opcode = kMipsFmovs;
+        } else {
+          // Note the operands are swapped for the mtc1 instr.
+          RegStorage t_opnd = r_src;
+          r_src = r_dest;
+          r_dest = t_opnd;
+          opcode = kMipsMtc1;
+        }
+      } else {
+        DCHECK(r_src.IsSingle());
+        opcode = kMipsMfc1;
+      }
+    }
+  } else {
+    // Must be both DOUBLE or both not DOUBLE.
+    DCHECK_EQ(r_dest.IsDouble(), r_src.IsDouble());
+    if (r_dest.IsDouble()) {
+      opcode = kMipsFmovd;
+    } else {
+      if (r_dest.IsSingle()) {
+        if (r_src.IsSingle()) {
+          opcode = kMipsFmovs;
+        } else {
+          // Note the operands are swapped for the mtc1 instr.
+          RegStorage t_opnd = r_src;
+          r_src = r_dest;
+          r_dest = t_opnd;
+          opcode = kMipsMtc1;
+        }
+      } else {
+        DCHECK(r_src.IsSingle());
+        opcode = kMipsMfc1;
+      }
     }
   }
-  LIR* res = RawLIR(current_dalvik_offset_, opcode, r_src.GetReg(), r_dest.GetReg());
+  LIR* res;
+  if (cu_->target64) {
+    res = RawLIR(current_dalvik_offset_, opcode, r_dest.GetReg(), r_src.GetReg());
+  } else {
+    res = RawLIR(current_dalvik_offset_, opcode, r_src.GetReg(), r_dest.GetReg());
+  }
   if (!(cu_->disable_opt & (1 << kSafeOptimizations)) && r_dest == r_src) {
     res->flags.is_nop = true;
   }
@@ -95,7 +135,7 @@
     r_dest = AllocTemp();
   }
 
-  /* See if the value can be constructed cheaply */
+  // See if the value can be constructed cheaply.
   if (value == 0) {
     res = NewLIR2(kMipsMove, r_dest.GetReg(), rZERO);
   } else if (IsUint<16>(value)) {
@@ -118,6 +158,117 @@
   return res;
 }
 
+LIR* MipsMir2Lir::LoadConstantWideNoClobber(RegStorage r_dest, int64_t value) {
+  LIR* res = nullptr;
+  DCHECK(r_dest.Is64Bit());
+  RegStorage r_dest_save = r_dest;
+  int is_fp_reg = r_dest.IsFloat();
+  if (is_fp_reg) {
+    DCHECK(r_dest.IsDouble());
+    r_dest = AllocTemp();
+  }
+
+  int bit31 = (value & UINT64_C(0x80000000)) != 0;
+
+  // Loads with 1 instruction.
+  if (IsUint<16>(value)) {
+    res = NewLIR3(kMipsOri, r_dest.GetReg(), rZEROd, value);
+  } else if (IsInt<16>(value)) {
+    res = NewLIR3(kMips64Daddiu, r_dest.GetReg(), rZEROd, value);
+  } else if ((value & 0xFFFF) == 0 && IsInt<16>(value >> 16)) {
+    res = NewLIR2(kMipsLui, r_dest.GetReg(), value >> 16);
+  } else if (IsInt<32>(value)) {
+    // Loads with 2 instructions.
+    res = NewLIR2(kMipsLui, r_dest.GetReg(), value >> 16);
+    NewLIR3(kMipsOri, r_dest.GetReg(), r_dest.GetReg(), value);
+  } else if ((value & 0xFFFF0000) == 0 && IsInt<16>(value >> 32)) {
+    res = NewLIR3(kMipsOri, r_dest.GetReg(), rZEROd, value);
+    NewLIR2(kMips64Dahi, r_dest.GetReg(), value >> 32);
+  } else if ((value & UINT64_C(0xFFFFFFFF0000)) == 0) {
+    res = NewLIR3(kMipsOri, r_dest.GetReg(), rZEROd, value);
+    NewLIR2(kMips64Dati, r_dest.GetReg(), value >> 48);
+  } else if ((value & 0xFFFF) == 0 && (value >> 32) >= (-32768 - bit31) &&
+             (value >> 32) <= (32767 - bit31)) {
+    res = NewLIR2(kMipsLui, r_dest.GetReg(), value >> 16);
+    NewLIR2(kMips64Dahi, r_dest.GetReg(), (value >> 32) + bit31);
+  } else if ((value & 0xFFFF) == 0 && ((value >> 31) & 0x1FFFF) == ((0x20000 - bit31) & 0x1FFFF)) {
+    res = NewLIR2(kMipsLui, r_dest.GetReg(), value >> 16);
+    NewLIR2(kMips64Dati, r_dest.GetReg(), (value >> 48) + bit31);
+  } else {
+    int64_t tmp = value;
+    int shift_cnt = 0;
+    while ((tmp & 1) == 0) {
+      tmp >>= 1;
+      shift_cnt++;
+    }
+
+    if (IsUint<16>(tmp)) {
+      res = NewLIR3(kMipsOri, r_dest.GetReg(), rZEROd, tmp);
+      NewLIR3((shift_cnt < 32) ? kMips64Dsll : kMips64Dsll32, r_dest.GetReg(), r_dest.GetReg(),
+              shift_cnt & 0x1F);
+    } else if (IsInt<16>(tmp)) {
+      res = NewLIR3(kMips64Daddiu, r_dest.GetReg(), rZEROd, tmp);
+      NewLIR3((shift_cnt < 32) ? kMips64Dsll : kMips64Dsll32, r_dest.GetReg(), r_dest.GetReg(),
+              shift_cnt & 0x1F);
+    } else if (IsInt<32>(tmp)) {
+      // Loads with 3 instructions.
+      res = NewLIR2(kMipsLui, r_dest.GetReg(), tmp >> 16);
+      NewLIR3(kMipsOri, r_dest.GetReg(), r_dest.GetReg(), tmp);
+      NewLIR3((shift_cnt < 32) ? kMips64Dsll : kMips64Dsll32, r_dest.GetReg(), r_dest.GetReg(),
+              shift_cnt & 0x1F);
+    } else {
+      tmp = value >> 16;
+      shift_cnt = 16;
+      while ((tmp & 1) == 0) {
+        tmp >>= 1;
+        shift_cnt++;
+      }
+
+      if (IsUint<16>(tmp)) {
+        res = NewLIR3(kMipsOri, r_dest.GetReg(), rZEROd, tmp);
+        NewLIR3((shift_cnt < 32) ? kMips64Dsll : kMips64Dsll32, r_dest.GetReg(), r_dest.GetReg(),
+                shift_cnt & 0x1F);
+        NewLIR3(kMipsOri, r_dest.GetReg(), r_dest.GetReg(), value);
+      } else if (IsInt<16>(tmp)) {
+        res = NewLIR3(kMips64Daddiu, r_dest.GetReg(), rZEROd, tmp);
+        NewLIR3((shift_cnt < 32) ? kMips64Dsll : kMips64Dsll32, r_dest.GetReg(), r_dest.GetReg(),
+                shift_cnt & 0x1F);
+        NewLIR3(kMipsOri, r_dest.GetReg(), r_dest.GetReg(), value);
+      } else {
+        // Loads with 3-4 instructions.
+        uint64_t tmp2 = value;
+        if (((tmp2 >> 16) & 0xFFFF) != 0 || (tmp2 & 0xFFFFFFFF) == 0) {
+          res = NewLIR2(kMipsLui, r_dest.GetReg(), tmp2 >> 16);
+        }
+        if ((tmp2 & 0xFFFF) != 0) {
+          if (res)
+            NewLIR3(kMipsOri, r_dest.GetReg(), r_dest.GetReg(), tmp2);
+          else
+            res = NewLIR3(kMipsOri, r_dest.GetReg(), rZEROd, tmp2);
+        }
+        if (bit31) {
+          tmp2 += UINT64_C(0x100000000);
+        }
+        if (((tmp2 >> 32) & 0xFFFF) != 0) {
+          NewLIR2(kMips64Dahi, r_dest.GetReg(), tmp2 >> 32);
+        }
+        if (tmp2 & UINT64_C(0x800000000000)) {
+          tmp2 += UINT64_C(0x1000000000000);
+        }
+        if ((tmp2 >> 48) != 0) {
+          NewLIR2(kMips64Dati, r_dest.GetReg(), tmp2 >> 48);
+        }
+      }
+    }
+  }
+
+  if (is_fp_reg) {
+    NewLIR2(kMips64Dmtc1, r_dest.GetReg(), r_dest_save.GetReg());
+    FreeTemp(r_dest);
+  }
+  return res;
+}
+
 LIR* MipsMir2Lir::OpUnconditionalBranch(LIR* target) {
   LIR* res = NewLIR1(kMipsB, 0 /* offset to be patched during assembly*/);
   res->target = target;
@@ -136,57 +287,33 @@
     default:
       LOG(FATAL) << "Bad case in OpReg";
   }
-  return NewLIR2(opcode, rRA, r_dest_src.GetReg());
+  return NewLIR2(opcode, cu_->target64 ? rRAd : rRA, r_dest_src.GetReg());
 }
 
 LIR* MipsMir2Lir::OpRegImm(OpKind op, RegStorage r_dest_src1, int value) {
-  LIR *res;
-  bool neg = (value < 0);
-  int abs_value = (neg) ? -value : value;
-  bool short_form = (abs_value & 0xff) == abs_value;
-  MipsOpCode opcode = kMipsNop;
-  switch (op) {
-    case kOpAdd:
-      return OpRegRegImm(op, r_dest_src1, r_dest_src1, value);
-      break;
-    case kOpSub:
-      return OpRegRegImm(op, r_dest_src1, r_dest_src1, value);
-      break;
-    default:
-      LOG(FATAL) << "Bad case in OpRegImm";
-      break;
-  }
-  if (short_form) {
-    res = NewLIR2(opcode, r_dest_src1.GetReg(), abs_value);
+  if ((op == kOpAdd) || (op == kOpSub)) {
+    return OpRegRegImm(op, r_dest_src1, r_dest_src1, value);
   } else {
-    RegStorage r_scratch = AllocTemp();
-    res = LoadConstant(r_scratch, value);
-    if (op == kOpCmp)
-      NewLIR2(opcode, r_dest_src1.GetReg(), r_scratch.GetReg());
-    else
-      NewLIR3(opcode, r_dest_src1.GetReg(), r_dest_src1.GetReg(), r_scratch.GetReg());
+    LOG(FATAL) << "Bad case in OpRegImm";
   }
-  return res;
+  UNREACHABLE();
 }
 
 LIR* MipsMir2Lir::OpRegRegReg(OpKind op, RegStorage r_dest, RegStorage r_src1, RegStorage r_src2) {
   MipsOpCode opcode = kMipsNop;
+  bool is64bit = cu_->target64 && (r_dest.Is64Bit() || r_src1.Is64Bit() || r_src2.Is64Bit());
   switch (op) {
     case kOpAdd:
-      opcode = kMipsAddu;
+      opcode = is64bit ? kMips64Daddu : kMipsAddu;
       break;
     case kOpSub:
-      opcode = kMipsSubu;
+      opcode = is64bit ? kMips64Dsubu : kMipsSubu;
       break;
     case kOpAnd:
       opcode = kMipsAnd;
       break;
     case kOpMul:
-      if (isaIsR6_) {
-          opcode = kMipsR6Mul;
-      } else {
-          opcode = kMipsMul;
-      }
+      opcode = isaIsR6_ ? kMipsR6Mul : kMipsR2Mul;
       break;
     case kOpOr:
       opcode = kMipsOr;
@@ -195,20 +322,20 @@
       opcode = kMipsXor;
       break;
     case kOpLsl:
-      opcode = kMipsSllv;
+      opcode = is64bit ? kMips64Dsllv : kMipsSllv;
       break;
     case kOpLsr:
-      opcode = kMipsSrlv;
+      opcode = is64bit ? kMips64Dsrlv : kMipsSrlv;
       break;
     case kOpAsr:
-      opcode = kMipsSrav;
+      opcode = is64bit ? kMips64Dsrav : kMipsSrav;
       break;
     case kOpAdc:
     case kOpSbc:
       LOG(FATAL) << "No carry bit on MIPS";
       break;
     default:
-      LOG(FATAL) << "bad case in OpRegRegReg";
+      LOG(FATAL) << "Bad case in OpRegRegReg";
       break;
   }
   return NewLIR3(opcode, r_dest.GetReg(), r_src1.GetReg(), r_src2.GetReg());
@@ -218,36 +345,67 @@
   LIR *res;
   MipsOpCode opcode = kMipsNop;
   bool short_form = true;
+  bool is64bit = cu_->target64 && (r_dest.Is64Bit() || r_src1.Is64Bit());
 
   switch (op) {
     case kOpAdd:
       if (IS_SIMM16(value)) {
-        opcode = kMipsAddiu;
+        opcode = is64bit ? kMips64Daddiu : kMipsAddiu;
       } else {
         short_form = false;
-        opcode = kMipsAddu;
+        opcode = is64bit ? kMips64Daddu : kMipsAddu;
       }
       break;
     case kOpSub:
       if (IS_SIMM16((-value))) {
         value = -value;
-        opcode = kMipsAddiu;
+        opcode = is64bit ? kMips64Daddiu : kMipsAddiu;
       } else {
         short_form = false;
-        opcode = kMipsSubu;
+        opcode = is64bit ? kMips64Dsubu : kMipsSubu;
       }
       break;
     case kOpLsl:
-      DCHECK(value >= 0 && value <= 31);
-      opcode = kMipsSll;
+      if (is64bit) {
+        DCHECK(value >= 0 && value <= 63);
+        if (value >= 0 && value <= 31) {
+          opcode = kMips64Dsll;
+        } else {
+          opcode = kMips64Dsll32;
+          value = value - 32;
+        }
+      } else {
+        DCHECK(value >= 0 && value <= 31);
+        opcode = kMipsSll;
+      }
       break;
     case kOpLsr:
-      DCHECK(value >= 0 && value <= 31);
-      opcode = kMipsSrl;
+      if (is64bit) {
+        DCHECK(value >= 0 && value <= 63);
+        if (value >= 0 && value <= 31) {
+          opcode = kMips64Dsrl;
+        } else {
+          opcode = kMips64Dsrl32;
+          value = value - 32;
+        }
+      } else {
+        DCHECK(value >= 0 && value <= 31);
+        opcode = kMipsSrl;
+      }
       break;
     case kOpAsr:
-      DCHECK(value >= 0 && value <= 31);
-      opcode = kMipsSra;
+      if (is64bit) {
+        DCHECK(value >= 0 && value <= 63);
+        if (value >= 0 && value <= 31) {
+          opcode = kMips64Dsra;
+        } else {
+          opcode = kMips64Dsra32;
+          value = value - 32;
+        }
+      } else {
+        DCHECK(value >= 0 && value <= 31);
+        opcode = kMipsSra;
+      }
       break;
     case kOpAnd:
       if (IS_UIMM16((value))) {
@@ -275,11 +433,7 @@
       break;
     case kOpMul:
       short_form = false;
-      if (isaIsR6_) {
-          opcode = kMipsR6Mul;
-      } else {
-          opcode = kMipsMul;
-      }
+      opcode = isaIsR6_ ? kMipsR6Mul : kMipsR2Mul;
       break;
     default:
       LOG(FATAL) << "Bad case in OpRegRegImm";
@@ -293,8 +447,14 @@
       res = LoadConstant(r_dest, value);
       NewLIR3(opcode, r_dest.GetReg(), r_src1.GetReg(), r_dest.GetReg());
     } else {
-      RegStorage r_scratch = AllocTemp();
-      res = LoadConstant(r_scratch, value);
+      RegStorage r_scratch;
+      if (is64bit) {
+        r_scratch = AllocTempWide();
+        res = LoadConstantWide(r_scratch, value);
+      } else {
+        r_scratch = AllocTemp();
+        res = LoadConstant(r_scratch, value);
+      }
       NewLIR3(opcode, r_dest.GetReg(), r_src1.GetReg(), r_scratch.GetReg());
     }
   }
@@ -311,7 +471,11 @@
     case kOpMvn:
       return NewLIR3(kMipsNor, r_dest_src1.GetReg(), r_src2.GetReg(), rZERO);
     case kOpNeg:
-      return NewLIR3(kMipsSubu, r_dest_src1.GetReg(), rZERO, r_src2.GetReg());
+      if (cu_->target64 && r_dest_src1.Is64Bit()) {
+        return NewLIR3(kMips64Dsubu, r_dest_src1.GetReg(), rZEROd, r_src2.GetReg());
+      } else {
+        return NewLIR3(kMipsSubu, r_dest_src1.GetReg(), rZERO, r_src2.GetReg());
+      }
     case kOpAdd:
     case kOpAnd:
     case kOpMul:
@@ -320,21 +484,29 @@
     case kOpXor:
       return OpRegRegReg(op, r_dest_src1, r_dest_src1, r_src2);
     case kOp2Byte:
-      if (cu_->compiler_driver->GetInstructionSetFeatures()->AsMipsInstructionSetFeatures()
-          ->IsMipsIsaRevGreaterThanEqual2()) {
+      if (cu_->target64) {
         res = NewLIR2(kMipsSeb, r_dest_src1.GetReg(), r_src2.GetReg());
       } else {
-        res = OpRegRegImm(kOpLsl, r_dest_src1, r_src2, 24);
-        OpRegRegImm(kOpAsr, r_dest_src1, r_dest_src1, 24);
+        if (cu_->compiler_driver->GetInstructionSetFeatures()->AsMipsInstructionSetFeatures()
+            ->IsMipsIsaRevGreaterThanEqual2()) {
+          res = NewLIR2(kMipsSeb, r_dest_src1.GetReg(), r_src2.GetReg());
+        } else {
+          res = OpRegRegImm(kOpLsl, r_dest_src1, r_src2, 24);
+          OpRegRegImm(kOpAsr, r_dest_src1, r_dest_src1, 24);
+        }
       }
       return res;
     case kOp2Short:
-      if (cu_->compiler_driver->GetInstructionSetFeatures()->AsMipsInstructionSetFeatures()
-          ->IsMipsIsaRevGreaterThanEqual2()) {
+      if (cu_->target64) {
         res = NewLIR2(kMipsSeh, r_dest_src1.GetReg(), r_src2.GetReg());
       } else {
-        res = OpRegRegImm(kOpLsl, r_dest_src1, r_src2, 16);
-        OpRegRegImm(kOpAsr, r_dest_src1, r_dest_src1, 16);
+        if (cu_->compiler_driver->GetInstructionSetFeatures()->AsMipsInstructionSetFeatures()
+            ->IsMipsIsaRevGreaterThanEqual2()) {
+          res = NewLIR2(kMipsSeh, r_dest_src1.GetReg(), r_src2.GetReg());
+        } else {
+          res = OpRegRegImm(kOpLsl, r_dest_src1, r_src2, 16);
+          OpRegRegImm(kOpAsr, r_dest_src1, r_dest_src1, 16);
+        }
       }
       return res;
     case kOp2Char:
@@ -367,10 +539,14 @@
 
 LIR* MipsMir2Lir::LoadConstantWide(RegStorage r_dest, int64_t value) {
   LIR *res;
+  if (cu_->target64) {
+    res = LoadConstantWideNoClobber(r_dest, value);
+    return res;
+  }
   if (fpuIs32Bit_ || !r_dest.IsFloat()) {
     // 32bit FPU (pairs) or loading into GPR.
     if (!r_dest.IsPair()) {
-      // Form 64-bit pair
+      // Form 64-bit pair.
       r_dest = Solo64ToPair64(r_dest);
     }
     res = LoadConstantNoClobber(r_dest.GetLow(), Low32Bits(value));
@@ -393,7 +569,8 @@
   LIR *first = NULL;
   LIR *res;
   MipsOpCode opcode = kMipsNop;
-  RegStorage t_reg = AllocTemp();
+  bool is64bit = cu_->target64 && r_dest.Is64Bit();
+  RegStorage t_reg = is64bit ? AllocTempWide() : AllocTemp();
 
   if (r_dest.IsFloat()) {
     DCHECK(r_dest.IsSingle());
@@ -404,14 +581,34 @@
       size = k32;
   }
 
-  if (!scale) {
-    first = NewLIR3(kMipsAddu, t_reg.GetReg() , r_base.GetReg(), r_index.GetReg());
+  if (cu_->target64) {
+    if (!scale) {
+      if (is64bit) {
+        first = NewLIR3(kMips64Daddu, t_reg.GetReg() , r_base.GetReg(), r_index.GetReg());
+      } else {
+        first = NewLIR3(kMipsAddu, t_reg.GetReg() , r_base.GetReg(), r_index.GetReg());
+      }
+    } else {
+      first = OpRegRegImm(kOpLsl, t_reg, r_index, scale);
+      NewLIR3(kMips64Daddu, t_reg.GetReg() , r_base.GetReg(), t_reg.GetReg());
+    }
   } else {
-    first = OpRegRegImm(kOpLsl, t_reg, r_index, scale);
-    NewLIR3(kMipsAddu, t_reg.GetReg() , r_base.GetReg(), t_reg.GetReg());
+    if (!scale) {
+      first = NewLIR3(kMipsAddu, t_reg.GetReg() , r_base.GetReg(), r_index.GetReg());
+    } else {
+      first = OpRegRegImm(kOpLsl, t_reg, r_index, scale);
+      NewLIR3(kMipsAddu, t_reg.GetReg() , r_base.GetReg(), t_reg.GetReg());
+    }
   }
 
   switch (size) {
+    case k64:
+      if (cu_->target64) {
+        opcode = kMips64Ld;
+      } else {
+        LOG(FATAL) << "Bad case in LoadBaseIndexed";
+      }
+      break;
     case kSingle:
       opcode = kMipsFlwc1;
       break;
@@ -440,7 +637,7 @@
   return (first) ? first : res;
 }
 
-/* store value base base + scaled index. */
+// Store value base base + scaled index.
 LIR* MipsMir2Lir::StoreBaseIndexed(RegStorage r_base, RegStorage r_index, RegStorage r_src,
                                    int scale, OpSize size) {
   LIR *first = NULL;
@@ -456,11 +653,12 @@
       size = k32;
   }
 
+  MipsOpCode add_opcode = cu_->target64 ? kMips64Daddu : kMipsAddu;
   if (!scale) {
-    first = NewLIR3(kMipsAddu, t_reg.GetReg() , r_base.GetReg(), r_index.GetReg());
+    first = NewLIR3(add_opcode, t_reg.GetReg() , r_base.GetReg(), r_index.GetReg());
   } else {
     first = OpRegRegImm(kOpLsl, t_reg, r_index, scale);
-    NewLIR3(kMipsAddu, t_reg.GetReg() , r_base.GetReg(), t_reg.GetReg());
+    NewLIR3(add_opcode, t_reg.GetReg() , r_base.GetReg(), t_reg.GetReg());
   }
 
   switch (size) {
@@ -507,9 +705,19 @@
   switch (size) {
     case k64:
     case kDouble:
+      if (cu_->target64) {
+        r_dest = Check64BitReg(r_dest);
+        if (!r_dest.IsFloat()) {
+          opcode = kMips64Ld;
+        } else {
+          opcode = kMipsFldc1;
+        }
+        DCHECK_EQ((displacement & 0x3), 0);
+        break;
+      }
       is64bit = true;
       if (fpuIs32Bit_ && !r_dest.IsPair()) {
-        // Form 64-bit pair
+        // Form 64-bit pair.
         r_dest = Solo64ToPair64(r_dest);
       }
       short_form = IS_SIMM16_2WORD(displacement);
@@ -546,20 +754,40 @@
       LOG(FATAL) << "Bad case in LoadBaseIndexedBody";
   }
 
+  if (cu_->target64) {
+    if (short_form) {
+      load = res = NewLIR3(opcode, r_dest.GetReg(), displacement, r_base.GetReg());
+    } else {
+      RegStorage r_tmp = (r_base == r_dest) ? AllocTemp() : r_dest;
+      res = OpRegRegImm(kOpAdd, r_tmp, r_base, displacement);
+      load = NewLIR3(opcode, r_dest.GetReg(), 0, r_tmp.GetReg());
+      if (r_tmp != r_dest)
+        FreeTemp(r_tmp);
+    }
+
+    if (mem_ref_type_ == ResourceMask::kDalvikReg) {
+      DCHECK_EQ(r_base, TargetPtrReg(kSp));
+      AnnotateDalvikRegAccess(load, displacement >> 2, true /* is_load */, r_dest.Is64Bit());
+    }
+    return res;
+  }
+
   if (short_form) {
     if (!is64bit) {
       load = res = NewLIR3(opcode, r_dest.GetReg(), displacement, r_base.GetReg());
     } else {
       if (fpuIs32Bit_ || !r_dest.IsFloat()) {
         DCHECK(r_dest.IsPair());
-        load = res = NewLIR3(opcode, r_dest.GetLowReg(), displacement + LOWORD_OFFSET, r_base.GetReg());
+        load = res = NewLIR3(opcode, r_dest.GetLowReg(), displacement + LOWORD_OFFSET,
+                             r_base.GetReg());
         load2 = NewLIR3(opcode, r_dest.GetHighReg(), displacement + HIWORD_OFFSET, r_base.GetReg());
       } else {
         // Here if 64bit fpu and r_dest is a 64bit fp register.
         RegStorage r_tmp = AllocTemp();
         // FIXME: why is r_dest a 64BitPair here???
         r_dest = Fp64ToSolo32(r_dest);
-        load = res = NewLIR3(kMipsFlwc1, r_dest.GetReg(), displacement + LOWORD_OFFSET, r_base.GetReg());
+        load = res = NewLIR3(kMipsFlwc1, r_dest.GetReg(), displacement + LOWORD_OFFSET,
+                             r_base.GetReg());
         load2 = NewLIR3(kMipsLw, r_tmp.GetReg(), displacement + HIWORD_OFFSET, r_base.GetReg());
         NewLIR2(kMipsMthc1, r_tmp.GetReg(), r_dest.GetReg());
         FreeTemp(r_tmp);
@@ -591,7 +819,7 @@
   }
 
   if (mem_ref_type_ == ResourceMask::kDalvikReg) {
-    DCHECK_EQ(r_base, rs_rMIPS_SP);
+    DCHECK_EQ(r_base, TargetPtrReg(kSp));
     AnnotateDalvikRegAccess(load, (displacement + (is64bit ? LOWORD_OFFSET : 0)) >> 2,
                             true /* is_load */, is64bit /* is64bit */);
     if (is64bit) {
@@ -599,19 +827,21 @@
                               true /* is_load */, is64bit /* is64bit */);
     }
   }
-  return load;
+  return res;
 }
 
-LIR* MipsMir2Lir::LoadBaseDisp(RegStorage r_base, int displacement, RegStorage r_dest,
-                               OpSize size, VolatileKind is_volatile) {
-  if (UNLIKELY(is_volatile == kVolatile && (size == k64 || size == kDouble))) {
+LIR* MipsMir2Lir::LoadBaseDisp(RegStorage r_base, int displacement, RegStorage r_dest, OpSize size,
+                               VolatileKind is_volatile) {
+  if (UNLIKELY(is_volatile == kVolatile && (size == k64 || size == kDouble))
+      && (!cu_->target64 || displacement & 0x7)) {
+    // TODO: use lld/scd instructions for Mips64.
     // Do atomic 64-bit load.
     return GenAtomic64Load(r_base, displacement, r_dest);
   }
 
   // TODO: base this on target.
   if (size == kWord) {
-    size = k32;
+    size = cu_->target64 ? k64 : k32;
   }
   LIR* load;
   load = LoadBaseDispBody(r_base, displacement, r_dest, size);
@@ -624,8 +854,8 @@
 }
 
 // FIXME: don't split r_dest into 2 containers.
-LIR* MipsMir2Lir::StoreBaseDispBody(RegStorage r_base, int displacement,
-                                    RegStorage r_src, OpSize size) {
+LIR* MipsMir2Lir::StoreBaseDispBody(RegStorage r_base, int displacement, RegStorage r_src,
+                                    OpSize size) {
   LIR *res;
   LIR *store = NULL;
   LIR *store2 = NULL;
@@ -636,9 +866,19 @@
   switch (size) {
     case k64:
     case kDouble:
+      if (cu_->target64) {
+        r_src = Check64BitReg(r_src);
+        if (!r_src.IsFloat()) {
+          opcode = kMips64Sd;
+        } else {
+          opcode = kMipsFsdc1;
+        }
+        DCHECK_EQ((displacement & 0x3), 0);
+        break;
+      }
       is64bit = true;
       if (fpuIs32Bit_ && !r_src.IsPair()) {
-        // Form 64-bit pair
+        // Form 64-bit pair.
         r_src = Solo64ToPair64(r_src);
       }
       short_form = IS_SIMM16_2WORD(displacement);
@@ -670,19 +910,38 @@
       LOG(FATAL) << "Bad case in StoreBaseDispBody";
   }
 
+  if (cu_->target64) {
+    if (short_form) {
+      store = res = NewLIR3(opcode, r_src.GetReg(), displacement, r_base.GetReg());
+    } else {
+      RegStorage r_scratch = AllocTemp();
+      res = OpRegRegImm(kOpAdd, r_scratch, r_base, displacement);
+      store = NewLIR3(opcode, r_src.GetReg(), 0, r_scratch.GetReg());
+      FreeTemp(r_scratch);
+    }
+
+    if (mem_ref_type_ == ResourceMask::kDalvikReg) {
+      DCHECK_EQ(r_base, TargetPtrReg(kSp));
+      AnnotateDalvikRegAccess(store, displacement >> 2, false /* is_load */, r_src.Is64Bit());
+    }
+    return res;
+  }
+
   if (short_form) {
     if (!is64bit) {
       store = res = NewLIR3(opcode, r_src.GetReg(), displacement, r_base.GetReg());
     } else {
       if (fpuIs32Bit_ || !r_src.IsFloat()) {
         DCHECK(r_src.IsPair());
-        store = res = NewLIR3(opcode, r_src.GetLowReg(), displacement + LOWORD_OFFSET, r_base.GetReg());
+        store = res = NewLIR3(opcode, r_src.GetLowReg(), displacement + LOWORD_OFFSET,
+                              r_base.GetReg());
         store2 = NewLIR3(opcode, r_src.GetHighReg(), displacement + HIWORD_OFFSET, r_base.GetReg());
       } else {
         // Here if 64bit fpu and r_src is a 64bit fp register
         RegStorage r_tmp = AllocTemp();
         r_src = Fp64ToSolo32(r_src);
-        store = res = NewLIR3(kMipsFswc1, r_src.GetReg(), displacement + LOWORD_OFFSET, r_base.GetReg());
+        store = res = NewLIR3(kMipsFswc1, r_src.GetReg(), displacement + LOWORD_OFFSET,
+                              r_base.GetReg());
         NewLIR2(kMipsMfhc1, r_tmp.GetReg(), r_src.GetReg());
         store2 = NewLIR3(kMipsSw, r_tmp.GetReg(), displacement + HIWORD_OFFSET, r_base.GetReg());
         FreeTemp(r_tmp);
@@ -712,7 +971,7 @@
   }
 
   if (mem_ref_type_ == ResourceMask::kDalvikReg) {
-    DCHECK_EQ(r_base, rs_rMIPS_SP);
+    DCHECK_EQ(r_base, TargetPtrReg(kSp));
     AnnotateDalvikRegAccess(store, (displacement + (is64bit ? LOWORD_OFFSET : 0)) >> 2,
                             false /* is_load */, is64bit /* is64bit */);
     if (is64bit) {
@@ -724,21 +983,23 @@
   return res;
 }
 
-LIR* MipsMir2Lir::StoreBaseDisp(RegStorage r_base, int displacement, RegStorage r_src,
-                                OpSize size, VolatileKind is_volatile) {
+LIR* MipsMir2Lir::StoreBaseDisp(RegStorage r_base, int displacement, RegStorage r_src, OpSize size,
+                                VolatileKind is_volatile) {
   if (is_volatile == kVolatile) {
     // Ensure that prior accesses become visible to other threads first.
     GenMemBarrier(kAnyStore);
   }
 
   LIR* store;
-  if (UNLIKELY(is_volatile == kVolatile && (size == k64 || size == kDouble))) {
+  if (UNLIKELY(is_volatile == kVolatile && (size == k64 || size == kDouble) &&
+      (!cu_->target64 || displacement & 0x7))) {
+    // TODO: use lld/scd instructions for Mips64.
     // Do atomic 64-bit load.
     store = GenAtomic64Store(r_base, displacement, r_src);
   } else {
     // TODO: base this on target.
     if (size == kWord) {
-      size = k32;
+      size = cu_->target64 ? k64 : k32;
     }
     store = StoreBaseDispBody(r_base, displacement, r_src, size);
   }
@@ -765,7 +1026,7 @@
 }
 
 LIR* MipsMir2Lir::InvokeTrampoline(OpKind op, RegStorage r_tgt, QuickEntrypointEnum trampoline) {
-  if (IsDirectEntrypoint(trampoline)) {
+  if (!cu_->target64 && IsDirectEntrypoint(trampoline)) {
     // Reserve argument space on stack (for $a0-$a3) for
     // entrypoints that directly reference native implementations.
     // This is not safe in general, as it violates the frame size
@@ -780,4 +1041,8 @@
   return OpReg(op, r_tgt);
 }
 
+RegStorage MipsMir2Lir::AllocPtrSizeTemp(bool required) {
+  return cu_->target64 ? AllocTempWide(required) : AllocTemp(required);
+}
+
 }  // namespace art
diff --git a/compiler/dex/quick/mips64/assemble_mips64.cc b/compiler/dex/quick/mips64/assemble_mips64.cc
deleted file mode 100644
index d96561b..0000000
--- a/compiler/dex/quick/mips64/assemble_mips64.cc
+++ /dev/null
@@ -1,898 +0,0 @@
-/*
- * Copyright (C) 2015 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.
- */
-
-#include "codegen_mips64.h"
-
-#include "base/logging.h"
-#include "dex/compiler_ir.h"
-#include "dex/quick/mir_to_lir-inl.h"
-#include "mips64_lir.h"
-
-namespace art {
-
-#define MAX_ASSEMBLER_RETRIES 50
-
-/*
- * opcode: Mips64OpCode enum
- * skeleton: pre-designated bit-pattern for this opcode
- * k0: key to applying ds/de
- * ds: dest start bit position
- * de: dest end bit position
- * k1: key to applying s1s/s1e
- * s1s: src1 start bit position
- * s1e: src1 end bit position
- * k2: key to applying s2s/s2e
- * s2s: src2 start bit position
- * s2e: src2 end bit position
- * operands: number of operands (for sanity check purposes)
- * name: mnemonic name
- * fmt: for pretty-printing
- */
-#define ENCODING_MAP(opcode, skeleton, k0, ds, de, k1, s1s, s1e, k2, s2s, s2e, \
-                     k3, k3s, k3e, flags, name, fmt, size) \
-        {skeleton, {{k0, ds, de}, {k1, s1s, s1e}, {k2, s2s, s2e}, \
-                    {k3, k3s, k3e}}, opcode, flags, name, fmt, size}
-
-/* Instruction dump string format keys: !pf, where "!" is the start
- * of the key, "p" is which numeric operand to use and "f" is the
- * print format.
- *
- * [p]ositions:
- *     0 -> operands[0] (dest)
- *     1 -> operands[1] (src1)
- *     2 -> operands[2] (src2)
- *     3 -> operands[3] (extra)
- *
- * [f]ormats:
- *     h -> 4-digit hex
- *     d -> decimal
- *     E -> decimal*4
- *     F -> decimal*2
- *     c -> branch condition (beq, bne, etc.)
- *     t -> pc-relative target
- *     T -> pc-region target
- *     u -> 1st half of bl[x] target
- *     v -> 2nd half ob bl[x] target
- *     R -> register list
- *     s -> single precision floating point register
- *     S -> double precision floating point register
- *     m -> Thumb2 modified immediate
- *     n -> complimented Thumb2 modified immediate
- *     M -> Thumb2 16-bit zero-extended immediate
- *     b -> 4-digit binary
- *     N -> append a NOP
- *
- *  [!] escape.  To insert "!", use "!!"
- */
-/* NOTE: must be kept in sync with enum Mips64Opcode from mips64_lir.h */
-/*
- * TUNING: We're currently punting on the branch delay slots.  All branch
- * instructions in this map are given a size of 8, which during assembly
- * is expanded to include a nop.  This scheme should be replaced with
- * an assembler pass to fill those slots when possible.
- */
-const Mips64EncodingMap Mips64Mir2Lir::EncodingMap[kMips64Last] = {
-    ENCODING_MAP(kMips6432BitData, 0x00000000,
-                 kFmtBitBlt, 31, 0, kFmtUnused, -1, -1, kFmtUnused, -1, -1,
-                 kFmtUnused, -1, -1, IS_UNARY_OP,
-                 "data", "0x!0h(!0d)", 4),
-    ENCODING_MAP(kMips64Addiu, 0x24000000,
-                 kFmtBitBlt, 20, 16, kFmtBitBlt, 25, 21, kFmtBitBlt, 15, 0,
-                 kFmtUnused, -1, -1, IS_TERTIARY_OP | REG_DEF0_USE1,
-                 "addiu", "!0r,!1r,0x!2h(!2d)", 4),
-    ENCODING_MAP(kMips64Addu, 0x00000021,
-                 kFmtBitBlt, 15, 11, kFmtBitBlt, 25, 21, kFmtBitBlt, 20, 16,
-                 kFmtUnused, -1, -1, IS_TERTIARY_OP | REG_DEF0_USE12,
-                 "addu", "!0r,!1r,!2r", 4),
-    ENCODING_MAP(kMips64And, 0x00000024,
-                 kFmtBitBlt, 15, 11, kFmtBitBlt, 25, 21, kFmtBitBlt, 20, 16,
-                 kFmtUnused, -1, -1, IS_TERTIARY_OP | REG_DEF0_USE12,
-                 "and", "!0r,!1r,!2r", 4),
-    ENCODING_MAP(kMips64Andi, 0x30000000,
-                 kFmtBitBlt, 20, 16, kFmtBitBlt, 25, 21, kFmtBitBlt, 15, 0,
-                 kFmtUnused, -1, -1, IS_TERTIARY_OP | REG_DEF0_USE1,
-                 "andi", "!0r,!1r,0x!2h(!2d)", 4),
-    ENCODING_MAP(kMips64B, 0x10000000,
-                 kFmtBitBlt, 15, 0, kFmtUnused, -1, -1, kFmtUnused, -1, -1,
-                 kFmtUnused, -1, -1, IS_UNARY_OP | IS_BRANCH | NEEDS_FIXUP,
-                 "b", "!0t!0N", 8),
-    ENCODING_MAP(kMips64Bal, 0x04110000,
-                 kFmtBitBlt, 15, 0, kFmtUnused, -1, -1, kFmtUnused, -1, -1,
-                 kFmtUnused, -1, -1, IS_UNARY_OP | IS_BRANCH | REG_DEF_LR |
-                 NEEDS_FIXUP, "bal", "!0t!0N", 8),
-    ENCODING_MAP(kMips64Beq, 0x10000000,
-                 kFmtBitBlt, 25, 21, kFmtBitBlt, 20, 16, kFmtBitBlt, 15, 0,
-                 kFmtUnused, -1, -1, IS_BINARY_OP | IS_BRANCH | REG_USE01 |
-                 NEEDS_FIXUP, "beq", "!0r,!1r,!2t!0N", 8),
-    ENCODING_MAP(kMips64Beqz, 0x10000000,  // Same as beq above with t = $zero.
-                 kFmtBitBlt, 25, 21, kFmtBitBlt, 15, 0, kFmtUnused, -1, -1,
-                 kFmtUnused, -1, -1, IS_UNARY_OP | IS_BRANCH | REG_USE0 |
-                 NEEDS_FIXUP, "beqz", "!0r,!1t!0N", 8),
-    ENCODING_MAP(kMips64Bgez, 0x04010000,
-                 kFmtBitBlt, 25, 21, kFmtBitBlt, 15, 0, kFmtUnused, -1, -1,
-                 kFmtUnused, -1, -1, IS_UNARY_OP | IS_BRANCH | REG_USE0 |
-                 NEEDS_FIXUP, "bgez", "!0r,!1t!0N", 8),
-    ENCODING_MAP(kMips64Bgtz, 0x1c000000,
-                 kFmtBitBlt, 25, 21, kFmtBitBlt, 15, 0, kFmtUnused, -1, -1,
-                 kFmtUnused, -1, -1, IS_UNARY_OP | IS_BRANCH | REG_USE0 |
-                 NEEDS_FIXUP, "bgtz", "!0r,!1t!0N", 8),
-    ENCODING_MAP(kMips64Blez, 0x18000000,
-                 kFmtBitBlt, 25, 21, kFmtBitBlt, 15, 0, kFmtUnused, -1, -1,
-                 kFmtUnused, -1, -1, IS_UNARY_OP | IS_BRANCH | REG_USE0 |
-                 NEEDS_FIXUP, "blez", "!0r,!1t!0N", 8),
-    ENCODING_MAP(kMips64Bltz, 0x04000000,
-                 kFmtBitBlt, 25, 21, kFmtBitBlt, 15, 0, kFmtUnused, -1, -1,
-                 kFmtUnused, -1, -1, IS_UNARY_OP | IS_BRANCH | REG_USE0 |
-                 NEEDS_FIXUP, "bltz", "!0r,!1t!0N", 8),
-    ENCODING_MAP(kMips64Bnez, 0x14000000,  // Same as bne below with t = $zero.
-                 kFmtBitBlt, 25, 21, kFmtBitBlt, 15, 0, kFmtUnused, -1, -1,
-                 kFmtUnused, -1, -1, IS_UNARY_OP | IS_BRANCH | REG_USE0 |
-                 NEEDS_FIXUP, "bnez", "!0r,!1t!0N", 8),
-    ENCODING_MAP(kMips64Bne, 0x14000000,
-                 kFmtBitBlt, 25, 21, kFmtBitBlt, 20, 16, kFmtBitBlt, 15, 0,
-                 kFmtUnused, -1, -1, IS_BINARY_OP | IS_BRANCH | REG_USE01 |
-                 NEEDS_FIXUP, "bne", "!0r,!1r,!2t!0N", 8),
-    ENCODING_MAP(kMips64Break, 0x0000000d,
-                 kFmtBitBlt, 25, 6, kFmtUnused, -1, -1, kFmtUnused, -1, -1,
-                 kFmtUnused, -1, -1, IS_UNARY_OP, "break", "!0d", 4),
-    ENCODING_MAP(kMips64Daddiu, 0x64000000,
-                 kFmtBitBlt, 20, 16, kFmtBitBlt, 25, 21, kFmtBitBlt, 15, 0,
-                 kFmtUnused, -1, -1, IS_TERTIARY_OP | REG_DEF0_USE1,
-                 "daddiu", "!0r,!1r,0x!2h(!2d)", 4),
-    ENCODING_MAP(kMips64Daddu, 0x0000002d,
-                 kFmtBitBlt, 15, 11, kFmtBitBlt, 25, 21, kFmtBitBlt, 20, 16,
-                 kFmtUnused, -1, -1, IS_TERTIARY_OP | REG_DEF0_USE12,
-                 "daddu", "!0r,!1r,!2r", 4),
-    ENCODING_MAP(kMips64Dahi, 0x04060000,
-                 kFmtBitBlt, 25, 21, kFmtBitBlt, 15, 0, kFmtUnused, -1, -1,
-                 kFmtUnused, -1, -1, IS_BINARY_OP | REG_DEF0_USE0,
-                 "dahi", "!0r,0x!1h(!1d)", 4),
-    ENCODING_MAP(kMips64Dati, 0x041E0000,
-                 kFmtBitBlt, 25, 21, kFmtBitBlt, 15, 0, kFmtUnused, -1, -1,
-                 kFmtUnused, -1, -1, IS_BINARY_OP | REG_DEF0_USE0,
-                 "dati", "!0r,0x!1h(!1d)", 4),
-    ENCODING_MAP(kMips64Daui, 0x74000000,
-                 kFmtBitBlt, 20, 16, kFmtBitBlt, 25, 21, kFmtBitBlt, 15, 0,
-                 kFmtUnused, -1, -1, IS_TERTIARY_OP | REG_DEF0_USE1,
-                 "daui", "!0r,!1r,0x!2h(!2d)", 4),
-    ENCODING_MAP(kMips64Ddiv, 0x0000009e,
-                 kFmtBitBlt, 15, 11, kFmtBitBlt, 25, 21, kFmtBitBlt, 20, 16,
-                 kFmtUnused, -1, -1, IS_TERTIARY_OP | REG_DEF0_USE12,
-                 "ddiv", "!0r,!1r,!2r", 4),
-    ENCODING_MAP(kMips64Div, 0x0000009a,
-                 kFmtBitBlt, 15, 11, kFmtBitBlt, 25, 21, kFmtBitBlt, 20, 16,
-                 kFmtUnused, -1, -1, IS_TERTIARY_OP | REG_DEF0_USE12,
-                 "div", "!0r,!1r,!2r", 4),
-    ENCODING_MAP(kMips64Dmod, 0x000000de,
-                 kFmtBitBlt, 15, 11, kFmtBitBlt, 25, 21, kFmtBitBlt, 20, 16,
-                 kFmtUnused, -1, -1, IS_TERTIARY_OP | REG_DEF0_USE12,
-                 "dmod", "!0r,!1r,!2r", 4),
-    ENCODING_MAP(kMips64Dmul, 0x0000009c,
-                 kFmtBitBlt, 15, 11, kFmtBitBlt, 25, 21, kFmtBitBlt, 20, 16,
-                 kFmtUnused, -1, -1, IS_TERTIARY_OP | REG_DEF0_USE12,
-                 "dmul", "!0r,!1r,!2r", 4),
-    ENCODING_MAP(kMips64Dmfc1, 0x44200000,
-                 kFmtBitBlt, 20, 16, kFmtDfp, 15, 11, kFmtUnused, -1, -1,
-                 kFmtUnused, -1, -1, IS_BINARY_OP | REG_DEF0_USE1,
-                 "dmfc1", "!0r,!1s", 4),
-    ENCODING_MAP(kMips64Dmtc1, 0x44a00000,
-                 kFmtBitBlt, 20, 16, kFmtDfp, 15, 11, kFmtUnused, -1, -1,
-                 kFmtUnused, -1, -1, IS_BINARY_OP | REG_USE0 | REG_DEF1,
-                 "dmtc1", "!0r,!1s", 4),
-    ENCODING_MAP(kMips64Drotr32, 0x0000003e | (1 << 21),
-                 kFmtBitBlt, 15, 11, kFmtBitBlt, 20, 16, kFmtBitBlt, 10, 6,
-                 kFmtUnused, -1, -1, IS_TERTIARY_OP | REG_DEF0_USE1,
-                 "drotr32", "!0r,!1r,0x!2h(!2d)", 4),
-    ENCODING_MAP(kMips64Dsll, 0x00000038,
-                 kFmtBitBlt, 15, 11, kFmtBitBlt, 20, 16, kFmtBitBlt, 10, 6,
-                 kFmtUnused, -1, -1, IS_TERTIARY_OP | REG_DEF0_USE1,
-                 "dsll", "!0r,!1r,0x!2h(!2d)", 4),
-    ENCODING_MAP(kMips64Dsll32, 0x0000003c,
-                 kFmtBitBlt, 15, 11, kFmtBitBlt, 20, 16, kFmtBitBlt, 10, 6,
-                 kFmtUnused, -1, -1, IS_TERTIARY_OP | REG_DEF0_USE1,
-                 "dsll32", "!0r,!1r,0x!2h(!2d)", 4),
-    ENCODING_MAP(kMips64Dsrl, 0x0000003a,
-                 kFmtBitBlt, 15, 11, kFmtBitBlt, 20, 16, kFmtBitBlt, 10, 6,
-                 kFmtUnused, -1, -1, IS_TERTIARY_OP | REG_DEF0_USE1,
-                 "dsrl", "!0r,!1r,0x!2h(!2d)", 4),
-    ENCODING_MAP(kMips64Dsrl32, 0x0000003e,
-                 kFmtBitBlt, 15, 11, kFmtBitBlt, 20, 16, kFmtBitBlt, 10, 6,
-                 kFmtUnused, -1, -1, IS_TERTIARY_OP | REG_DEF0_USE1,
-                 "dsrl32", "!0r,!1r,0x!2h(!2d)", 4),
-    ENCODING_MAP(kMips64Dsra, 0x0000003b,
-                 kFmtBitBlt, 15, 11, kFmtBitBlt, 20, 16, kFmtBitBlt, 10, 6,
-                 kFmtUnused, -1, -1, IS_TERTIARY_OP | REG_DEF0_USE1,
-                 "dsra", "!0r,!1r,0x!2h(!2d)", 4),
-    ENCODING_MAP(kMips64Dsra32, 0x0000003f,
-                 kFmtBitBlt, 15, 11, kFmtBitBlt, 20, 16, kFmtBitBlt, 10, 6,
-                 kFmtUnused, -1, -1, IS_TERTIARY_OP | REG_DEF0_USE1,
-                 "dsra32", "!0r,!1r,0x!2h(!2d)", 4),
-    ENCODING_MAP(kMips64Dsllv, 0x00000014,
-                 kFmtBitBlt, 15, 11, kFmtBitBlt, 20, 16, kFmtBitBlt, 25, 21,
-                 kFmtUnused, -1, -1, IS_TERTIARY_OP | REG_DEF0_USE12,
-                 "dsllv", "!0r,!1r,!2r", 4),
-    ENCODING_MAP(kMips64Dsrlv, 0x00000016,
-                 kFmtBitBlt, 15, 11, kFmtBitBlt, 20, 16, kFmtBitBlt, 25, 21,
-                 kFmtUnused, -1, -1, IS_TERTIARY_OP | REG_DEF0_USE12,
-                 "dsrlv", "!0r,!1r,!2r", 4),
-    ENCODING_MAP(kMips64Dsrav, 0x00000017,
-                 kFmtBitBlt, 15, 11, kFmtBitBlt, 20, 16, kFmtBitBlt, 25, 21,
-                 kFmtUnused, -1, -1, IS_TERTIARY_OP | REG_DEF0_USE12,
-                 "dsrav", "!0r,!1r,!2r", 4),
-    ENCODING_MAP(kMips64Dsubu, 0x0000002f,
-                 kFmtBitBlt, 15, 11, kFmtBitBlt, 25, 21, kFmtBitBlt, 20, 16,
-                 kFmtUnused, -1, -1, IS_TERTIARY_OP | REG_DEF0_USE12,
-                 "dsubu", "!0r,!1r,!2r", 4),
-    ENCODING_MAP(kMips64Ext, 0x7c000000,
-                 kFmtBitBlt, 20, 16, kFmtBitBlt, 25, 21, kFmtBitBlt, 10, 6,
-                 kFmtBitBlt, 15, 11, IS_QUAD_OP | REG_DEF0 | REG_USE1,
-                 "ext", "!0r,!1r,!2d,!3D", 4),
-    ENCODING_MAP(kMips64Faddd, 0x46200000,
-                 kFmtDfp, 10, 6, kFmtDfp, 15, 11, kFmtDfp, 20, 16,
-                 kFmtUnused, -1, -1, IS_TERTIARY_OP | REG_DEF0_USE12,
-                 "add.d", "!0S,!1S,!2S", 4),
-    ENCODING_MAP(kMips64Fadds, 0x46000000,
-                 kFmtSfp, 10, 6, kFmtSfp, 15, 11, kFmtSfp, 20, 16,
-                 kFmtUnused, -1, -1, IS_TERTIARY_OP | REG_DEF0_USE12,
-                 "add.s", "!0s,!1s,!2s", 4),
-    ENCODING_MAP(kMips64Fdivd, 0x46200003,
-                 kFmtDfp, 10, 6, kFmtDfp, 15, 11, kFmtDfp, 20, 16,
-                 kFmtUnused, -1, -1, IS_TERTIARY_OP | REG_DEF0_USE12,
-                 "div.d", "!0S,!1S,!2S", 4),
-    ENCODING_MAP(kMips64Fdivs, 0x46000003,
-                 kFmtSfp, 10, 6, kFmtSfp, 15, 11, kFmtSfp, 20, 16,
-                 kFmtUnused, -1, -1, IS_TERTIARY_OP | REG_DEF0_USE12,
-                 "div.s", "!0s,!1s,!2s", 4),
-    ENCODING_MAP(kMips64Fmuld, 0x46200002,
-                 kFmtDfp, 10, 6, kFmtDfp, 15, 11, kFmtDfp, 20, 16,
-                 kFmtUnused, -1, -1, IS_TERTIARY_OP | REG_DEF0_USE12,
-                 "mul.d", "!0S,!1S,!2S", 4),
-    ENCODING_MAP(kMips64Fmuls, 0x46000002,
-                 kFmtSfp, 10, 6, kFmtSfp, 15, 11, kFmtSfp, 20, 16,
-                 kFmtUnused, -1, -1, IS_TERTIARY_OP | REG_DEF0_USE12,
-                 "mul.s", "!0s,!1s,!2s", 4),
-    ENCODING_MAP(kMips64Fsubd, 0x46200001,
-                 kFmtDfp, 10, 6, kFmtDfp, 15, 11, kFmtDfp, 20, 16,
-                 kFmtUnused, -1, -1, IS_TERTIARY_OP | REG_DEF0_USE12,
-                 "sub.d", "!0S,!1S,!2S", 4),
-    ENCODING_MAP(kMips64Fsubs, 0x46000001,
-                 kFmtSfp, 10, 6, kFmtSfp, 15, 11, kFmtSfp, 20, 16,
-                 kFmtUnused, -1, -1, IS_TERTIARY_OP | REG_DEF0_USE12,
-                 "sub.s", "!0s,!1s,!2s", 4),
-    ENCODING_MAP(kMips64Fcvtsd, 0x46200020,
-                 kFmtSfp, 10, 6, kFmtDfp, 15, 11, kFmtUnused, -1, -1,
-                 kFmtUnused, -1, -1, IS_BINARY_OP | REG_DEF0_USE1,
-                 "cvt.s.d", "!0s,!1S", 4),
-    ENCODING_MAP(kMips64Fcvtsw, 0x46800020,
-                 kFmtSfp, 10, 6, kFmtSfp, 15, 11, kFmtUnused, -1, -1,
-                 kFmtUnused, -1, -1, IS_BINARY_OP | REG_DEF0_USE1,
-                 "cvt.s.w", "!0s,!1s", 4),
-    ENCODING_MAP(kMips64Fcvtds, 0x46000021,
-                 kFmtDfp, 10, 6, kFmtSfp, 15, 11, kFmtUnused, -1, -1,
-                 kFmtUnused, -1, -1, IS_BINARY_OP | REG_DEF0_USE1,
-                 "cvt.d.s", "!0S,!1s", 4),
-    ENCODING_MAP(kMips64Fcvtdw, 0x46800021,
-                 kFmtDfp, 10, 6, kFmtSfp, 15, 11, kFmtUnused, -1, -1,
-                 kFmtUnused, -1, -1, IS_BINARY_OP | REG_DEF0_USE1,
-                 "cvt.d.w", "!0S,!1s", 4),
-    ENCODING_MAP(kMips64Fcvtws, 0x46000024,
-                 kFmtSfp, 10, 6, kFmtSfp, 15, 11, kFmtUnused, -1, -1,
-                 kFmtUnused, -1, -1, IS_BINARY_OP | REG_DEF0_USE1,
-                 "cvt.w.s", "!0s,!1s", 4),
-    ENCODING_MAP(kMips64Fcvtwd, 0x46200024,
-                 kFmtSfp, 10, 6, kFmtDfp, 15, 11, kFmtUnused, -1, -1,
-                 kFmtUnused, -1, -1, IS_BINARY_OP | REG_DEF0_USE1,
-                 "cvt.w.d", "!0s,!1S", 4),
-    ENCODING_MAP(kMips64Fmovd, 0x46200006,
-                 kFmtDfp, 10, 6, kFmtDfp, 15, 11, kFmtUnused, -1, -1,
-                 kFmtUnused, -1, -1, IS_BINARY_OP | REG_DEF0_USE1,
-                 "mov.d", "!0S,!1S", 4),
-    ENCODING_MAP(kMips64Fmovs, 0x46000006,
-                 kFmtSfp, 10, 6, kFmtSfp, 15, 11, kFmtUnused, -1, -1,
-                 kFmtUnused, -1, -1, IS_BINARY_OP | REG_DEF0_USE1,
-                 "mov.s", "!0s,!1s", 4),
-    ENCODING_MAP(kMips64Fnegd, 0x46200007,
-                 kFmtDfp, 10, 6, kFmtDfp, 15, 11, kFmtUnused, -1, -1,
-                 kFmtUnused, -1, -1, IS_BINARY_OP | REG_DEF0_USE1,
-                 "neg.d", "!0S,!1S", 4),
-    ENCODING_MAP(kMips64Fnegs, 0x46000007,
-                 kFmtSfp, 10, 6, kFmtSfp, 15, 11, kFmtUnused, -1, -1,
-                 kFmtUnused, -1, -1, IS_BINARY_OP | REG_DEF0_USE1,
-                 "neg.s", "!0s,!1s", 4),
-    ENCODING_MAP(kMips64Fldc1, 0xd4000000,
-                 kFmtDfp, 20, 16, kFmtBitBlt, 15, 0, kFmtBitBlt, 25, 21,
-                 kFmtUnused, -1, -1, IS_TERTIARY_OP | REG_DEF0_USE2 | IS_LOAD,
-                 "ldc1", "!0S,!1d(!2r)", 4),
-    ENCODING_MAP(kMips64Flwc1, 0xc4000000,
-                 kFmtSfp, 20, 16, kFmtBitBlt, 15, 0, kFmtBitBlt, 25, 21,
-                 kFmtUnused, -1, -1, IS_TERTIARY_OP | REG_DEF0_USE2 | IS_LOAD,
-                 "lwc1", "!0s,!1d(!2r)", 4),
-    ENCODING_MAP(kMips64Fsdc1, 0xf4000000,
-                 kFmtDfp, 20, 16, kFmtBitBlt, 15, 0, kFmtBitBlt, 25, 21,
-                 kFmtUnused, -1, -1, IS_TERTIARY_OP | REG_USE02 | IS_STORE,
-                 "sdc1", "!0S,!1d(!2r)", 4),
-    ENCODING_MAP(kMips64Fswc1, 0xe4000000,
-                 kFmtSfp, 20, 16, kFmtBitBlt, 15, 0, kFmtBitBlt, 25, 21,
-                 kFmtUnused, -1, -1, IS_TERTIARY_OP | REG_USE02 | IS_STORE,
-                 "swc1", "!0s,!1d(!2r)", 4),
-    ENCODING_MAP(kMips64Jal, 0x0c000000,
-                 kFmtBitBlt, 25, 0, kFmtUnused, -1, -1, kFmtUnused, -1, -1,
-                 kFmtUnused, -1, -1, IS_UNARY_OP | IS_BRANCH | REG_DEF_LR,
-                 "jal", "!0T(!0E)!0N", 8),
-    ENCODING_MAP(kMips64Jalr, 0x00000009,
-                 kFmtBitBlt, 15, 11, kFmtBitBlt, 25, 21, kFmtUnused, -1, -1,
-                 kFmtUnused, -1, -1, IS_BINARY_OP | IS_BRANCH | REG_DEF0_USE1,
-                 "jalr", "!0r,!1r!0N", 8),
-    ENCODING_MAP(kMips64Lahi, 0x3c000000,
-                 kFmtBitBlt, 20, 16, kFmtBitBlt, 15, 0, kFmtUnused, -1, -1,
-                 kFmtUnused, -1, -1, IS_BINARY_OP | REG_DEF0,
-                 "lahi/lui", "!0r,0x!1h(!1d)", 4),
-    ENCODING_MAP(kMips64Lalo, 0x34000000,
-                 kFmtBitBlt, 20, 16, kFmtBitBlt, 25, 21, kFmtBitBlt, 15, 0,
-                 kFmtUnused, -1, -1, IS_TERTIARY_OP | REG_DEF0_USE1,
-                 "lalo/ori", "!0r,!1r,0x!2h(!2d)", 4),
-    ENCODING_MAP(kMips64Lb, 0x80000000,
-                 kFmtBitBlt, 20, 16, kFmtBitBlt, 15, 0, kFmtBitBlt, 25, 21,
-                 kFmtUnused, -1, -1, IS_TERTIARY_OP | REG_DEF0_USE2 | IS_LOAD,
-                 "lb", "!0r,!1d(!2r)", 4),
-    ENCODING_MAP(kMips64Lbu, 0x90000000,
-                 kFmtBitBlt, 20, 16, kFmtBitBlt, 15, 0, kFmtBitBlt, 25, 21,
-                 kFmtUnused, -1, -1, IS_TERTIARY_OP | REG_DEF0_USE2 | IS_LOAD,
-                 "lbu", "!0r,!1d(!2r)", 4),
-    ENCODING_MAP(kMips64Ld, 0xdc000000,
-                 kFmtBitBlt, 20, 16, kFmtBitBlt, 15, 0, kFmtBitBlt, 25, 21,
-                 kFmtUnused, -1, -1, IS_TERTIARY_OP | REG_DEF0_USE2 | IS_LOAD,
-                 "ld", "!0r,!1d(!2r)", 4),
-    ENCODING_MAP(kMips64Lh, 0x84000000,
-                 kFmtBitBlt, 20, 16, kFmtBitBlt, 15, 0, kFmtBitBlt, 25, 21,
-                 kFmtUnused, -1, -1, IS_TERTIARY_OP | REG_DEF0_USE2 | IS_LOAD,
-                 "lh", "!0r,!1d(!2r)", 4),
-    ENCODING_MAP(kMips64Lhu, 0x94000000,
-                 kFmtBitBlt, 20, 16, kFmtBitBlt, 15, 0, kFmtBitBlt, 25, 21,
-                 kFmtUnused, -1, -1, IS_TERTIARY_OP | REG_DEF0_USE2 | IS_LOAD,
-                 "lhu", "!0r,!1d(!2r)", 4),
-    ENCODING_MAP(kMips64Lui, 0x3c000000,
-                 kFmtBitBlt, 20, 16, kFmtBitBlt, 15, 0, kFmtUnused, -1, -1,
-                 kFmtUnused, -1, -1, IS_BINARY_OP | REG_DEF0,
-                 "lui", "!0r,0x!1h(!1d)", 4),
-    ENCODING_MAP(kMips64Lw, 0x8c000000,
-                 kFmtBitBlt, 20, 16, kFmtBitBlt, 15, 0, kFmtBitBlt, 25, 21,
-                 kFmtUnused, -1, -1, IS_TERTIARY_OP | REG_DEF0_USE2 | IS_LOAD,
-                 "lw", "!0r,!1d(!2r)", 4),
-    ENCODING_MAP(kMips64Lwu, 0x9c000000,
-                 kFmtBitBlt, 20, 16, kFmtBitBlt, 15, 0, kFmtBitBlt, 25, 21,
-                 kFmtUnused, -1, -1, IS_TERTIARY_OP | REG_DEF0_USE2 | IS_LOAD,
-                 "lwu", "!0r,!1d(!2r)", 4),
-    ENCODING_MAP(kMips64Mfc1, 0x44000000,
-                 kFmtBitBlt, 20, 16, kFmtSfp, 15, 11, kFmtUnused, -1, -1,
-                 kFmtUnused, -1, -1, IS_BINARY_OP | REG_DEF0_USE1,
-                 "mfc1", "!0r,!1s", 4),
-    ENCODING_MAP(kMips64Mtc1, 0x44800000,
-                 kFmtBitBlt, 20, 16, kFmtSfp, 15, 11, kFmtUnused, -1, -1,
-                 kFmtUnused, -1, -1, IS_BINARY_OP | REG_USE0 | REG_DEF1,
-                 "mtc1", "!0r,!1s", 4),
-    ENCODING_MAP(kMips64Move, 0x0000002d,  // Or using zero reg.
-                 kFmtBitBlt, 15, 11, kFmtBitBlt, 25, 21, kFmtUnused, -1, -1,
-                 kFmtUnused, -1, -1, IS_BINARY_OP | REG_DEF0_USE1,
-                 "move", "!0r,!1r", 4),
-    ENCODING_MAP(kMips64Mod, 0x000000da,
-                 kFmtBitBlt, 15, 11, kFmtBitBlt, 25, 21, kFmtBitBlt, 20, 16,
-                 kFmtUnused, -1, -1, IS_TERTIARY_OP | REG_DEF0_USE12,
-                 "mod", "!0r,!1r,!2r", 4),
-    ENCODING_MAP(kMips64Mul, 0x00000098,
-                 kFmtBitBlt, 15, 11, kFmtBitBlt, 25, 21, kFmtBitBlt, 20, 16,
-                 kFmtUnused, -1, -1, IS_TERTIARY_OP | REG_DEF0_USE12,
-                 "mul", "!0r,!1r,!2r", 4),
-    ENCODING_MAP(kMips64Nop, 0x00000000,
-                 kFmtUnused, -1, -1, kFmtUnused, -1, -1, kFmtUnused, -1, -1,
-                 kFmtUnused, -1, -1, NO_OPERAND,
-                 "nop", ";", 4),
-    ENCODING_MAP(kMips64Nor, 0x00000027,  // Used for "not" too.
-                 kFmtBitBlt, 15, 11, kFmtBitBlt, 25, 21, kFmtBitBlt, 20, 16,
-                 kFmtUnused, -1, -1, IS_TERTIARY_OP | REG_DEF0_USE12,
-                 "nor", "!0r,!1r,!2r", 4),
-    ENCODING_MAP(kMips64Or, 0x00000025,
-                 kFmtBitBlt, 15, 11, kFmtBitBlt, 25, 21, kFmtBitBlt, 20, 16,
-                 kFmtUnused, -1, -1, IS_TERTIARY_OP | REG_DEF0_USE12,
-                 "or", "!0r,!1r,!2r", 4),
-    ENCODING_MAP(kMips64Ori, 0x34000000,
-                 kFmtBitBlt, 20, 16, kFmtBitBlt, 25, 21, kFmtBitBlt, 15, 0,
-                 kFmtUnused, -1, -1, IS_TERTIARY_OP | REG_DEF0_USE1,
-                 "ori", "!0r,!1r,0x!2h(!2d)", 4),
-    ENCODING_MAP(kMips64Sb, 0xa0000000,
-                 kFmtBitBlt, 20, 16, kFmtBitBlt, 15, 0, kFmtBitBlt, 25, 21,
-                 kFmtUnused, -1, -1, IS_TERTIARY_OP | REG_USE02 | IS_STORE,
-                 "sb", "!0r,!1d(!2r)", 4),
-    ENCODING_MAP(kMips64Sd, 0xfc000000,
-                 kFmtBitBlt, 20, 16, kFmtBitBlt, 15, 0, kFmtBitBlt, 25, 21,
-                 kFmtUnused, -1, -1, IS_TERTIARY_OP | REG_USE02 | IS_STORE,
-                 "sd", "!0r,!1d(!2r)", 4),
-    ENCODING_MAP(kMips64Seb, 0x7c000420,
-                 kFmtBitBlt, 15, 11, kFmtBitBlt, 20, 16, kFmtUnused, -1, -1,
-                 kFmtUnused, -1, -1, IS_BINARY_OP | REG_DEF0_USE1,
-                 "seb", "!0r,!1r", 4),
-    ENCODING_MAP(kMips64Seh, 0x7c000620,
-                 kFmtBitBlt, 15, 11, kFmtBitBlt, 20, 16, kFmtUnused, -1, -1,
-                 kFmtUnused, -1, -1, IS_BINARY_OP | REG_DEF0_USE1,
-                 "seh", "!0r,!1r", 4),
-    ENCODING_MAP(kMips64Sh, 0xa4000000,
-                 kFmtBitBlt, 20, 16, kFmtBitBlt, 15, 0, kFmtBitBlt, 25, 21,
-                 kFmtUnused, -1, -1, IS_TERTIARY_OP | REG_USE02 | IS_STORE,
-                 "sh", "!0r,!1d(!2r)", 4),
-    ENCODING_MAP(kMips64Sll, 0x00000000,
-                 kFmtBitBlt, 15, 11, kFmtBitBlt, 20, 16, kFmtBitBlt, 10, 6,
-                 kFmtUnused, -1, -1, IS_TERTIARY_OP | REG_DEF0_USE1,
-                 "sll", "!0r,!1r,0x!2h(!2d)", 4),
-    ENCODING_MAP(kMips64Sllv, 0x00000004,
-                 kFmtBitBlt, 15, 11, kFmtBitBlt, 20, 16, kFmtBitBlt, 25, 21,
-                 kFmtUnused, -1, -1, IS_TERTIARY_OP | REG_DEF0_USE12,
-                 "sllv", "!0r,!1r,!2r", 4),
-    ENCODING_MAP(kMips64Slt, 0x0000002a,
-                 kFmtBitBlt, 15, 11, kFmtBitBlt, 25, 21, kFmtBitBlt, 20, 16,
-                 kFmtUnused, -1, -1, IS_TERTIARY_OP | REG_DEF0_USE12,
-                 "slt", "!0r,!1r,!2r", 4),
-    ENCODING_MAP(kMips64Slti, 0x28000000,
-                 kFmtBitBlt, 20, 16, kFmtBitBlt, 25, 21, kFmtBitBlt, 15, 0,
-                 kFmtUnused, -1, -1, IS_TERTIARY_OP | REG_DEF0_USE1,
-                 "slti", "!0r,!1r,0x!2h(!2d)", 4),
-    ENCODING_MAP(kMips64Sltu, 0x0000002b,
-                 kFmtBitBlt, 15, 11, kFmtBitBlt, 25, 21, kFmtBitBlt, 20, 16,
-                 kFmtUnused, -1, -1, IS_TERTIARY_OP | REG_DEF0_USE12,
-                 "sltu", "!0r,!1r,!2r", 4),
-    ENCODING_MAP(kMips64Sra, 0x00000003,
-                 kFmtBitBlt, 15, 11, kFmtBitBlt, 20, 16, kFmtBitBlt, 10, 6,
-                 kFmtUnused, -1, -1, IS_TERTIARY_OP | REG_DEF0_USE1,
-                 "sra", "!0r,!1r,0x!2h(!2d)", 4),
-    ENCODING_MAP(kMips64Srav, 0x00000007,
-                 kFmtBitBlt, 15, 11, kFmtBitBlt, 20, 16, kFmtBitBlt, 25, 21,
-                 kFmtUnused, -1, -1, IS_TERTIARY_OP | REG_DEF0_USE12,
-                 "srav", "!0r,!1r,!2r", 4),
-    ENCODING_MAP(kMips64Srl, 0x00000002,
-                 kFmtBitBlt, 15, 11, kFmtBitBlt, 20, 16, kFmtBitBlt, 10, 6,
-                 kFmtUnused, -1, -1, IS_TERTIARY_OP | REG_DEF0_USE1,
-                 "srl", "!0r,!1r,0x!2h(!2d)", 4),
-    ENCODING_MAP(kMips64Srlv, 0x00000006,
-                 kFmtBitBlt, 15, 11, kFmtBitBlt, 20, 16, kFmtBitBlt, 25, 21,
-                 kFmtUnused, -1, -1, IS_TERTIARY_OP | REG_DEF0_USE12,
-                 "srlv", "!0r,!1r,!2r", 4),
-    ENCODING_MAP(kMips64Subu, 0x00000023,  // Used for "neg" too.
-                 kFmtBitBlt, 15, 11, kFmtBitBlt, 25, 21, kFmtBitBlt, 20, 16,
-                 kFmtUnused, -1, -1, IS_TERTIARY_OP | REG_DEF0_USE12,
-                 "subu", "!0r,!1r,!2r", 4),
-    ENCODING_MAP(kMips64Sw, 0xac000000,
-                 kFmtBitBlt, 20, 16, kFmtBitBlt, 15, 0, kFmtBitBlt, 25, 21,
-                 kFmtUnused, -1, -1, IS_TERTIARY_OP | REG_USE02 | IS_STORE,
-                 "sw", "!0r,!1d(!2r)", 4),
-    ENCODING_MAP(kMips64Sync, 0x0000000f,
-                 kFmtBitBlt, 10, 6, kFmtUnused, -1, -1, kFmtUnused, -1, -1,
-                 kFmtUnused, -1, -1, IS_UNARY_OP,
-                 "sync", ";", 4),
-    ENCODING_MAP(kMips64Xor, 0x00000026,
-                 kFmtBitBlt, 15, 11, kFmtBitBlt, 25, 21, kFmtBitBlt, 20, 16,
-                 kFmtUnused, -1, -1, IS_TERTIARY_OP | REG_DEF0_USE12,
-                 "xor", "!0r,!1r,!2r", 4),
-    ENCODING_MAP(kMips64Xori, 0x38000000,
-                 kFmtBitBlt, 20, 16, kFmtBitBlt, 25, 21, kFmtBitBlt, 15, 0,
-                 kFmtUnused, -1, -1, IS_TERTIARY_OP | REG_DEF0_USE1,
-                 "xori", "!0r,!1r,0x!2h(!2d)", 4),
-    ENCODING_MAP(kMips64CurrPC, 0x04110001,
-                 kFmtUnused, -1, -1, kFmtUnused, -1, -1, kFmtUnused, -1, -1,
-                 kFmtUnused, -1, -1, NO_OPERAND | IS_BRANCH | REG_DEF_LR,
-                 "addiu", "ra,pc,8", 4),
-    ENCODING_MAP(kMips64Delta, 0x67e00000,
-                 kFmtBitBlt, 20, 16, kFmtBitBlt, 15, 0, kFmtUnused, 15, 0,
-                 kFmtUnused, -1, -1, IS_QUAD_OP | REG_DEF0 | REG_USE_LR |
-                 NEEDS_FIXUP, "daddiu", "!0r,ra,0x!1h(!1d)", 4),
-    ENCODING_MAP(kMips64DeltaHi, 0x3c000000,
-                 kFmtBitBlt, 20, 16, kFmtBitBlt, 15, 0, kFmtUnused, -1, -1,
-                 kFmtUnused, -1, -1, IS_QUAD_OP | REG_DEF0 | NEEDS_FIXUP,
-                 "lui", "!0r,0x!1h(!1d)", 4),
-    ENCODING_MAP(kMips64DeltaLo, 0x34000000,
-                 kFmtBlt5_2, 16, 21, kFmtBitBlt, 15, 0, kFmtUnused, -1, -1,
-                 kFmtUnused, -1, -1, IS_QUAD_OP | REG_DEF0_USE0 | NEEDS_FIXUP,
-                 "ori", "!0r,!0r,0x!1h(!1d)", 4),
-    ENCODING_MAP(kMips64Undefined, 0x64000000,
-                 kFmtUnused, -1, -1, kFmtUnused, -1, -1, kFmtUnused, -1, -1,
-                 kFmtUnused, -1, -1, NO_OPERAND,
-                 "undefined", "", 4),
-};
-
-
-/*
- * Convert a short-form branch to long form.  Hopefully, this won't happen
- * very often because the PIC sequence is especially unfortunate.
- *
- * Orig conditional branch
- * -----------------------
- *      beq  rs,rt,target
- *
- * Long conditional branch
- * -----------------------
- *      bne  rs,rt,hop
- *      bal  .+8   ; rRA <- anchor
- *      lui  rAT, ((target-anchor) >> 16)
- * anchor:
- *      ori  rAT, rAT, ((target-anchor) & 0xffff)
- *      addu rAT, rAT, rRA
- *      jalr rZERO, rAT
- * hop:
- *
- * Orig unconditional branch
- * -------------------------
- *      b target
- *
- * Long unconditional branch
- * -----------------------
- *      bal  .+8   ; rRA <- anchor
- *      lui  rAT, ((target-anchor) >> 16)
- * anchor:
- *      ori  rAT, rAT, ((target-anchor) & 0xffff)
- *      addu rAT, rAT, rRA
- *      jalr rZERO, rAT
- *
- *
- * NOTE: An out-of-range bal isn't supported because it should
- * never happen with the current PIC model.
- */
-void Mips64Mir2Lir::ConvertShortToLongBranch(LIR* lir) {
-  // For conditional branches we'll need to reverse the sense
-  bool unconditional = false;
-  int opcode = lir->opcode;
-  int dalvik_offset = lir->dalvik_offset;
-  switch (opcode) {
-    case kMips64Bal:
-      LOG(FATAL) << "long branch and link unsupported";
-      UNREACHABLE();
-    case kMips64B:
-      unconditional = true;
-      break;
-    case kMips64Beq:  opcode = kMips64Bne; break;
-    case kMips64Bne:  opcode = kMips64Beq; break;
-    case kMips64Beqz: opcode = kMips64Bnez; break;
-    case kMips64Bgez: opcode = kMips64Bltz; break;
-    case kMips64Bgtz: opcode = kMips64Blez; break;
-    case kMips64Blez: opcode = kMips64Bgtz; break;
-    case kMips64Bltz: opcode = kMips64Bgez; break;
-    case kMips64Bnez: opcode = kMips64Beqz; break;
-    default:
-      LOG(FATAL) << "Unexpected branch kind " << opcode;
-      UNREACHABLE();
-  }
-  LIR* hop_target = NULL;
-  if (!unconditional) {
-    hop_target = RawLIR(dalvik_offset, kPseudoTargetLabel);
-    LIR* hop_branch = RawLIR(dalvik_offset, opcode, lir->operands[0],
-                             lir->operands[1], 0, 0, 0, hop_target);
-    InsertLIRBefore(lir, hop_branch);
-  }
-  LIR* curr_pc = RawLIR(dalvik_offset, kMips64CurrPC);
-  InsertLIRBefore(lir, curr_pc);
-  LIR* anchor = RawLIR(dalvik_offset, kPseudoTargetLabel);
-  LIR* delta_hi = RawLIR(dalvik_offset, kMips64DeltaHi, rAT, 0, WrapPointer(anchor), 0, 0,
-                         lir->target);
-  InsertLIRBefore(lir, delta_hi);
-  InsertLIRBefore(lir, anchor);
-  LIR* delta_lo = RawLIR(dalvik_offset, kMips64DeltaLo, rAT, 0, WrapPointer(anchor), 0, 0,
-                         lir->target);
-  InsertLIRBefore(lir, delta_lo);
-  LIR* addu = RawLIR(dalvik_offset, kMips64Addu, rAT, rAT, rRA);
-  InsertLIRBefore(lir, addu);
-  LIR* jalr = RawLIR(dalvik_offset, kMips64Jalr, rZERO, rAT);
-  InsertLIRBefore(lir, jalr);
-  if (!unconditional) {
-    InsertLIRBefore(lir, hop_target);
-  }
-  NopLIR(lir);
-}
-
-/*
- * Assemble the LIR into binary instruction format.  Note that we may
- * discover that pc-relative displacements may not fit the selected
- * instruction.  In those cases we will try to substitute a new code
- * sequence or request that the trace be shortened and retried.
- */
-AssemblerStatus Mips64Mir2Lir::AssembleInstructions(CodeOffset start_addr) {
-  LIR *lir;
-  AssemblerStatus res = kSuccess;  // Assume success.
-
-  for (lir = first_lir_insn_; lir != NULL; lir = NEXT_LIR(lir)) {
-    if (lir->opcode < 0) {
-      continue;
-    }
-
-    if (lir->flags.is_nop) {
-      continue;
-    }
-
-    if (lir->flags.fixup != kFixupNone) {
-      if (lir->opcode == kMips64Delta) {
-        /*
-         * The "Delta" pseudo-ops load the difference between
-         * two pc-relative locations into a the target register
-         * found in operands[0].  The delta is determined by
-         * (label2 - label1), where label1 is a standard
-         * kPseudoTargetLabel and is stored in operands[2].
-         * If operands[3] is null, then label2 is a kPseudoTargetLabel
-         * and is found in lir->target.  If operands[3] is non-NULL,
-         * then it is a Switch/Data table.
-         */
-        int offset1 = UnwrapPointer<LIR>(lir->operands[2])->offset;
-        const EmbeddedData* tab_rec = UnwrapPointer<EmbeddedData>(lir->operands[3]);
-        int offset2 = tab_rec ? tab_rec->offset : lir->target->offset;
-        int delta = offset2 - offset1;
-        if ((delta & 0xffff) == delta && ((delta & 0x8000) == 0)) {
-          // Fits.
-          lir->operands[1] = delta;
-        } else {
-          // Doesn't fit - must expand to kMips64Delta[Hi|Lo] pair.
-          LIR *new_delta_hi = RawLIR(lir->dalvik_offset, kMips64DeltaHi, lir->operands[0], 0,
-                                     lir->operands[2], lir->operands[3], 0, lir->target);
-          InsertLIRBefore(lir, new_delta_hi);
-          LIR *new_delta_lo = RawLIR(lir->dalvik_offset, kMips64DeltaLo, lir->operands[0], 0,
-                                     lir->operands[2], lir->operands[3], 0, lir->target);
-          InsertLIRBefore(lir, new_delta_lo);
-          LIR *new_addu = RawLIR(lir->dalvik_offset, kMips64Daddu, lir->operands[0],
-                                 lir->operands[0], rRAd);
-          InsertLIRBefore(lir, new_addu);
-          NopLIR(lir);
-          res = kRetryAll;
-        }
-      } else if (lir->opcode == kMips64DeltaLo) {
-        int offset1 = UnwrapPointer<LIR>(lir->operands[2])->offset;
-        const EmbeddedData* tab_rec = UnwrapPointer<EmbeddedData>(lir->operands[3]);
-        int offset2 = tab_rec ? tab_rec->offset : lir->target->offset;
-        int delta = offset2 - offset1;
-        lir->operands[1] = delta & 0xffff;
-      } else if (lir->opcode == kMips64DeltaHi) {
-        int offset1 = UnwrapPointer<LIR>(lir->operands[2])->offset;
-        const EmbeddedData* tab_rec = UnwrapPointer<EmbeddedData>(lir->operands[3]);
-        int offset2 = tab_rec ? tab_rec->offset : lir->target->offset;
-        int delta = offset2 - offset1;
-        lir->operands[1] = (delta >> 16) & 0xffff;
-      } else if (lir->opcode == kMips64B || lir->opcode == kMips64Bal) {
-        LIR *target_lir = lir->target;
-        CodeOffset pc = lir->offset + 4;
-        CodeOffset target = target_lir->offset;
-        int delta = target - pc;
-        if (delta & 0x3) {
-          LOG(FATAL) << "PC-rel offset not multiple of 4: " << delta;
-        }
-        if (delta > 131068 || delta < -131069) {
-          res = kRetryAll;
-          ConvertShortToLongBranch(lir);
-        } else {
-          lir->operands[0] = delta >> 2;
-        }
-      } else if (lir->opcode >= kMips64Beqz && lir->opcode <= kMips64Bnez) {
-        LIR *target_lir = lir->target;
-        CodeOffset pc = lir->offset + 4;
-        CodeOffset target = target_lir->offset;
-        int delta = target - pc;
-        if (delta & 0x3) {
-          LOG(FATAL) << "PC-rel offset not multiple of 4: " << delta;
-        }
-        if (delta > 131068 || delta < -131069) {
-          res = kRetryAll;
-          ConvertShortToLongBranch(lir);
-        } else {
-          lir->operands[1] = delta >> 2;
-        }
-      } else if (lir->opcode == kMips64Beq || lir->opcode == kMips64Bne) {
-        LIR *target_lir = lir->target;
-        CodeOffset pc = lir->offset + 4;
-        CodeOffset target = target_lir->offset;
-        int delta = target - pc;
-        if (delta & 0x3) {
-          LOG(FATAL) << "PC-rel offset not multiple of 4: " << delta;
-        }
-        if (delta > 131068 || delta < -131069) {
-          res = kRetryAll;
-          ConvertShortToLongBranch(lir);
-        } else {
-          lir->operands[2] = delta >> 2;
-        }
-      } else if (lir->opcode == kMips64Jal) {
-        CodeOffset cur_pc = (start_addr + lir->offset + 4) & ~3;
-        CodeOffset target = lir->operands[0];
-        /* ensure PC-region branch can be used */
-        DCHECK_EQ((cur_pc & 0xF0000000), (target & 0xF0000000));
-        if (target & 0x3) {
-          LOG(FATAL) << "Jump target not multiple of 4: " << target;
-        }
-        lir->operands[0] =  target >> 2;
-      } else if (lir->opcode == kMips64Lahi) { /* ld address hi (via lui) */
-        LIR *target_lir = lir->target;
-        CodeOffset target = start_addr + target_lir->offset;
-        lir->operands[1] = target >> 16;
-      } else if (lir->opcode == kMips64Lalo) { /* ld address lo (via ori) */
-        LIR *target_lir = lir->target;
-        CodeOffset target = start_addr + target_lir->offset;
-        lir->operands[2] = lir->operands[2] + target;
-      }
-    }
-
-    /*
-     * If one of the pc-relative instructions expanded we'll have
-     * to make another pass.  Don't bother to fully assemble the
-     * instruction.
-     */
-    if (res != kSuccess) {
-      continue;
-    }
-    DCHECK(!IsPseudoLirOp(lir->opcode));
-    const Mips64EncodingMap *encoder = &EncodingMap[lir->opcode];
-    uint32_t bits = encoder->skeleton;
-    int i;
-    for (i = 0; i < 4; i++) {
-      uint32_t operand;
-      uint32_t value;
-      operand = lir->operands[i];
-      switch (encoder->field_loc[i].kind) {
-        case kFmtUnused:
-          break;
-        case kFmtBitBlt:
-          if (encoder->field_loc[i].start == 0 && encoder->field_loc[i].end == 31) {
-            value = operand;
-          } else {
-            value = (operand << encoder->field_loc[i].start) &
-                ((1 << (encoder->field_loc[i].end + 1)) - 1);
-          }
-          bits |= value;
-          break;
-        case kFmtBlt5_2:
-          value = (operand & 0x1f);
-          bits |= (value << encoder->field_loc[i].start);
-          bits |= (value << encoder->field_loc[i].end);
-          break;
-        case kFmtDfp: {
-          // TODO: do we need to adjust now that we're using 64BitSolo?
-          DCHECK(RegStorage::IsDouble(operand)) << ", Operand = 0x" << std::hex << operand;
-          value = (RegStorage::RegNum(operand) << encoder->field_loc[i].start) &
-              ((1 << (encoder->field_loc[i].end + 1)) - 1);
-          bits |= value;
-          break;
-        }
-        case kFmtSfp:
-          DCHECK(RegStorage::IsSingle(operand)) << ", Operand = 0x" << std::hex << operand;
-          value = (RegStorage::RegNum(operand) << encoder->field_loc[i].start) &
-              ((1 << (encoder->field_loc[i].end + 1)) - 1);
-          bits |= value;
-          break;
-        default:
-          LOG(FATAL) << "Bad encoder format: " << encoder->field_loc[i].kind;
-      }
-    }
-    // We only support little-endian MIPS64.
-    code_buffer_.push_back(bits & 0xff);
-    code_buffer_.push_back((bits >> 8) & 0xff);
-    code_buffer_.push_back((bits >> 16) & 0xff);
-    code_buffer_.push_back((bits >> 24) & 0xff);
-    // TUNING: replace with proper delay slot handling.
-    if (encoder->size == 8) {
-      DCHECK(!IsPseudoLirOp(lir->opcode));
-      const Mips64EncodingMap *encoder2 = &EncodingMap[kMips64Nop];
-      uint32_t bits2 = encoder2->skeleton;
-      code_buffer_.push_back(bits2 & 0xff);
-      code_buffer_.push_back((bits2 >> 8) & 0xff);
-      code_buffer_.push_back((bits2 >> 16) & 0xff);
-      code_buffer_.push_back((bits2 >> 24) & 0xff);
-    }
-  }
-  return res;
-}
-
-size_t Mips64Mir2Lir::GetInsnSize(LIR* lir) {
-  DCHECK(!IsPseudoLirOp(lir->opcode));
-  return EncodingMap[lir->opcode].size;
-}
-
-// LIR offset assignment.
-// TODO: consolidate w/ Arm assembly mechanism.
-int Mips64Mir2Lir::AssignInsnOffsets() {
-  LIR* lir;
-  int offset = 0;
-
-  for (lir = first_lir_insn_; lir != NULL; lir = NEXT_LIR(lir)) {
-    lir->offset = offset;
-    if (LIKELY(lir->opcode >= 0)) {
-      if (!lir->flags.is_nop) {
-        offset += lir->flags.size;
-      }
-    } else if (UNLIKELY(lir->opcode == kPseudoPseudoAlign4)) {
-      if (offset & 0x2) {
-        offset += 2;
-        lir->operands[0] = 1;
-      } else {
-        lir->operands[0] = 0;
-      }
-    }
-    // Pseudo opcodes don't consume space.
-  }
-  return offset;
-}
-
-/*
- * Walk the compilation unit and assign offsets to instructions
- * and literals and compute the total size of the compiled unit.
- * TODO: consolidate w/ Arm assembly mechanism.
- */
-void Mips64Mir2Lir::AssignOffsets() {
-  int offset = AssignInsnOffsets();
-
-  // Const values have to be word aligned.
-  offset = RoundUp(offset, 4);
-
-  // Set up offsets for literals.
-  data_offset_ = offset;
-
-  offset = AssignLiteralOffset(offset);
-
-  offset = AssignSwitchTablesOffset(offset);
-
-  offset = AssignFillArrayDataOffset(offset);
-
-  total_size_ = offset;
-}
-
-/*
- * Go over each instruction in the list and calculate the offset from the top
- * before sending them off to the assembler. If out-of-range branch distance is
- * seen rearrange the instructions a bit to correct it.
- * TODO: consolidate w/ Arm assembly mechanism.
- */
-void Mips64Mir2Lir::AssembleLIR() {
-  cu_->NewTimingSplit("Assemble");
-  AssignOffsets();
-  int assembler_retries = 0;
-  /*
-   * Assemble here.  Note that we generate code with optimistic assumptions
-   * and if found now to work, we'll have to redo the sequence and retry.
-   */
-
-  while (true) {
-    AssemblerStatus res = AssembleInstructions(0);
-    if (res == kSuccess) {
-      break;
-    } else {
-      assembler_retries++;
-      if (assembler_retries > MAX_ASSEMBLER_RETRIES) {
-        CodegenDump();
-        LOG(FATAL) << "Assembler error - too many retries";
-      }
-      // Redo offsets and try again.
-      AssignOffsets();
-      code_buffer_.clear();
-    }
-  }
-
-  // Install literals.
-  InstallLiteralPools();
-
-  // Install switch tables.
-  InstallSwitchTables();
-
-  // Install fill array data.
-  InstallFillArrayData();
-
-  // Create the mapping table and native offset to reference map.
-  cu_->NewTimingSplit("PcMappingTable");
-  CreateMappingTables();
-
-  cu_->NewTimingSplit("GcMap");
-  CreateNativeGcMap();
-}
-
-}  // namespace art
diff --git a/compiler/dex/quick/mips64/backend_mips64.h b/compiler/dex/quick/mips64/backend_mips64.h
deleted file mode 100644
index cc30ae0..0000000
--- a/compiler/dex/quick/mips64/backend_mips64.h
+++ /dev/null
@@ -1,32 +0,0 @@
-/*
- * Copyright (C) 2015 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.
- */
-
-#ifndef ART_COMPILER_DEX_QUICK_MIPS64_BACKEND_MIPS64_H_
-#define ART_COMPILER_DEX_QUICK_MIPS64_BACKEND_MIPS64_H_
-
-namespace art {
-
-struct CompilationUnit;
-class Mir2Lir;
-class MIRGraph;
-class ArenaAllocator;
-
-Mir2Lir* Mips64CodeGenerator(CompilationUnit* const cu, MIRGraph* const mir_graph,
-                             ArenaAllocator* const arena);
-
-}  // namespace art
-
-#endif  // ART_COMPILER_DEX_QUICK_MIPS64_BACKEND_MIPS64_H_
diff --git a/compiler/dex/quick/mips64/call_mips64.cc b/compiler/dex/quick/mips64/call_mips64.cc
deleted file mode 100644
index 0e58770..0000000
--- a/compiler/dex/quick/mips64/call_mips64.cc
+++ /dev/null
@@ -1,421 +0,0 @@
-/*
- * Copyright (C) 2015 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.
- */
-
-/* This file contains codegen for the Mips64 ISA */
-
-#include "codegen_mips64.h"
-
-#include "base/logging.h"
-#include "dex/mir_graph.h"
-#include "dex/quick/mir_to_lir-inl.h"
-#include "entrypoints/quick/quick_entrypoints.h"
-#include "gc/accounting/card_table.h"
-#include "mips64_lir.h"
-#include "mirror/art_method.h"
-#include "mirror/object_array-inl.h"
-
-namespace art {
-
-bool Mips64Mir2Lir::GenSpecialCase(BasicBlock* bb, MIR* mir, const InlineMethod& special) {
-  // TODO
-  UNUSED(bb, mir, special);
-  return false;
-}
-
-/*
- * The lack of pc-relative loads on Mips64 presents somewhat of a challenge
- * for our PIC switch table strategy.  To materialize the current location
- * we'll do a dummy JAL and reference our tables using rRA as the
- * base register.  Note that rRA will be used both as the base to
- * locate the switch table data and as the reference base for the switch
- * target offsets stored in the table.  We'll use a special pseudo-instruction
- * to represent the jal and trigger the construction of the
- * switch table offsets (which will happen after final assembly and all
- * labels are fixed).
- *
- * The test loop will look something like:
- *
- *   ori   r_end, rZERO, #table_size  ; size in bytes
- *   jal   BaseLabel         ; stores "return address" (BaseLabel) in rRA
- *   nop                     ; opportunistically fill
- * BaseLabel:
- *   addiu r_base, rRA, <table> - <BaseLabel>    ; table relative to BaseLabel
-     addu  r_end, r_end, r_base                   ; end of table
- *   lw    r_val, [rSP, v_reg_off]                ; Test Value
- * loop:
- *   beq   r_base, r_end, done
- *   lw    r_key, 0(r_base)
- *   addu  r_base, 8
- *   bne   r_val, r_key, loop
- *   lw    r_disp, -4(r_base)
- *   addu  rRA, r_disp
- *   jalr  rZERO, rRA
- * done:
- *
- */
-void Mips64Mir2Lir::GenLargeSparseSwitch(MIR* mir, DexOffset table_offset, RegLocation rl_src) {
-  const uint16_t* table = mir_graph_->GetTable(mir, table_offset);
-  // Add the table to the list - we'll process it later.
-  SwitchTable* tab_rec = static_cast<SwitchTable*>(arena_->Alloc(sizeof(SwitchTable),
-                                                   kArenaAllocData));
-  tab_rec->switch_mir = mir;
-  tab_rec->table = table;
-  tab_rec->vaddr = current_dalvik_offset_;
-  int elements = table[1];
-  switch_tables_.push_back(tab_rec);
-
-  // The table is composed of 8-byte key/disp pairs.
-  int byte_size = elements * 8;
-
-  int size_hi = byte_size >> 16;
-  int size_lo = byte_size & 0xffff;
-
-  RegStorage r_end = AllocTempWide();
-  if (size_hi) {
-    NewLIR2(kMips64Lui, r_end.GetReg(), size_hi);
-  }
-  // Must prevent code motion for the curr pc pair.
-  GenBarrier();  // Scheduling barrier.
-  NewLIR0(kMips64CurrPC);  // Really a jal to .+8.
-  // Now, fill the branch delay slot.
-  if (size_hi) {
-    NewLIR3(kMips64Ori, r_end.GetReg(), r_end.GetReg(), size_lo);
-  } else {
-    NewLIR3(kMips64Ori, r_end.GetReg(), rZERO, size_lo);
-  }
-  GenBarrier();  // Scheduling barrier.
-
-  // Construct BaseLabel and set up table base register.
-  LIR* base_label = NewLIR0(kPseudoTargetLabel);
-  // Remember base label so offsets can be computed later.
-  tab_rec->anchor = base_label;
-  RegStorage r_base = AllocTempWide();
-  NewLIR4(kMips64Delta, r_base.GetReg(), 0, WrapPointer(base_label), WrapPointer(tab_rec));
-  OpRegRegReg(kOpAdd, r_end, r_end, r_base);
-
-  // Grab switch test value.
-  rl_src = LoadValue(rl_src, kCoreReg);
-
-  // Test loop.
-  RegStorage r_key = AllocTemp();
-  LIR* loop_label = NewLIR0(kPseudoTargetLabel);
-  LIR* exit_branch = OpCmpBranch(kCondEq, r_base, r_end, NULL);
-  Load32Disp(r_base, 0, r_key);
-  OpRegImm(kOpAdd, r_base, 8);
-  OpCmpBranch(kCondNe, rl_src.reg, r_key, loop_label);
-  RegStorage r_disp = AllocTemp();
-  Load32Disp(r_base, -4, r_disp);
-  OpRegRegReg(kOpAdd, TargetReg(kLr, kWide), TargetReg(kLr, kWide), r_disp);
-  OpReg(kOpBx, TargetReg(kLr, kWide));
-
-  // Loop exit.
-  LIR* exit_label = NewLIR0(kPseudoTargetLabel);
-  exit_branch->target = exit_label;
-}
-
-/*
- * Code pattern will look something like:
- *
- *   lw    r_val
- *   jal   BaseLabel         ; stores "return address" (BaseLabel) in rRA
- *   nop                     ; opportunistically fill
- *   [subiu r_val, bias]      ; Remove bias if low_val != 0
- *   bound check -> done
- *   lw    r_disp, [rRA, r_val]
- *   addu  rRA, r_disp
- *   jalr  rZERO, rRA
- * done:
- */
-void Mips64Mir2Lir::GenLargePackedSwitch(MIR* mir, DexOffset table_offset, RegLocation rl_src) {
-  const uint16_t* table = mir_graph_->GetTable(mir, table_offset);
-  // Add the table to the list - we'll process it later.
-  SwitchTable* tab_rec =
-      static_cast<SwitchTable*>(arena_->Alloc(sizeof(SwitchTable), kArenaAllocData));
-  tab_rec->switch_mir = mir;
-  tab_rec->table = table;
-  tab_rec->vaddr = current_dalvik_offset_;
-  int size = table[1];
-  switch_tables_.push_back(tab_rec);
-
-  // Get the switch value.
-  rl_src = LoadValue(rl_src, kCoreReg);
-
-  // Prepare the bias.  If too big, handle 1st stage here.
-  int low_key = s4FromSwitchData(&table[2]);
-  bool large_bias = false;
-  RegStorage r_key;
-  if (low_key == 0) {
-    r_key = rl_src.reg;
-  } else if ((low_key & 0xffff) != low_key) {
-    r_key = AllocTemp();
-    LoadConstant(r_key, low_key);
-    large_bias = true;
-  } else {
-    r_key = AllocTemp();
-  }
-
-  // Must prevent code motion for the curr pc pair.
-  GenBarrier();
-  NewLIR0(kMips64CurrPC);  // Really a jal to .+8.
-  // Now, fill the branch delay slot with bias strip.
-  if (low_key == 0) {
-    NewLIR0(kMips64Nop);
-  } else {
-    if (large_bias) {
-      OpRegRegReg(kOpSub, r_key, rl_src.reg, r_key);
-    } else {
-      OpRegRegImm(kOpSub, r_key, rl_src.reg, low_key);
-    }
-  }
-  GenBarrier();  // Scheduling barrier.
-
-  // Construct BaseLabel and set up table base register.
-  LIR* base_label = NewLIR0(kPseudoTargetLabel);
-  // Remember base label so offsets can be computed later.
-  tab_rec->anchor = base_label;
-
-  // Bounds check - if < 0 or >= size continue following switch.
-  LIR* branch_over = OpCmpImmBranch(kCondHi, r_key, size-1, NULL);
-
-  // Materialize the table base pointer.
-  RegStorage r_base = AllocTempWide();
-  NewLIR4(kMips64Delta, r_base.GetReg(), 0, WrapPointer(base_label), WrapPointer(tab_rec));
-
-  // Load the displacement from the switch table.
-  RegStorage r_disp = AllocTemp();
-  LoadBaseIndexed(r_base, r_key, r_disp, 2, k32);
-
-  // Add to rAP and go.
-  OpRegRegReg(kOpAdd, TargetReg(kLr, kWide), TargetReg(kLr, kWide), r_disp);
-  OpReg(kOpBx, TargetReg(kLr, kWide));
-
-  // Branch_over target here.
-  LIR* target = NewLIR0(kPseudoTargetLabel);
-  branch_over->target = target;
-}
-
-void Mips64Mir2Lir::GenMoveException(RegLocation rl_dest) {
-  int ex_offset = Thread::ExceptionOffset<8>().Int32Value();
-  RegLocation rl_result = EvalLoc(rl_dest, kRefReg, true);
-  RegStorage reset_reg = AllocTempRef();
-  LoadRefDisp(rs_rMIPS64_SELF, ex_offset, rl_result.reg, kNotVolatile);
-  LoadConstant(reset_reg, 0);
-  StoreRefDisp(rs_rMIPS64_SELF, ex_offset, reset_reg, kNotVolatile);
-  FreeTemp(reset_reg);
-  StoreValue(rl_dest, rl_result);
-}
-
-void Mips64Mir2Lir::UnconditionallyMarkGCCard(RegStorage tgt_addr_reg) {
-  RegStorage reg_card_base = AllocTempWide();
-  RegStorage reg_card_no = AllocTempWide();
-  // NOTE: native pointer.
-  LoadWordDisp(rs_rMIPS64_SELF, Thread::CardTableOffset<8>().Int32Value(), reg_card_base);
-  OpRegRegImm(kOpLsr, reg_card_no, tgt_addr_reg, gc::accounting::CardTable::kCardShift);
-  StoreBaseIndexed(reg_card_base, reg_card_no, As32BitReg(reg_card_base), 0, kUnsignedByte);
-  FreeTemp(reg_card_base);
-  FreeTemp(reg_card_no);
-}
-
-void Mips64Mir2Lir::GenEntrySequence(RegLocation* ArgLocs, RegLocation rl_method) {
-  int spill_count = num_core_spills_ + num_fp_spills_;
-  /*
-   * On entry, rMIPS64_ARG0, rMIPS64_ARG1, rMIPS64_ARG2, rMIPS64_ARG3,
-   * rMIPS64_ARG4, rMIPS64_ARG5, rMIPS64_ARG6 & rMIPS64_ARG7  are live.
-   * Let the register allocation mechanism know so it doesn't try to
-   * use any of them when expanding the frame or flushing.
-   */
-  LockTemp(rs_rMIPS64_ARG0);
-  LockTemp(rs_rMIPS64_ARG1);
-  LockTemp(rs_rMIPS64_ARG2);
-  LockTemp(rs_rMIPS64_ARG3);
-  LockTemp(rs_rMIPS64_ARG4);
-  LockTemp(rs_rMIPS64_ARG5);
-  LockTemp(rs_rMIPS64_ARG6);
-  LockTemp(rs_rMIPS64_ARG7);
-
-  /*
-   * We can safely skip the stack overflow check if we're
-   * a leaf *and* our frame size < fudge factor.
-   */
-  bool skip_overflow_check = mir_graph_->MethodIsLeaf() && !FrameNeedsStackCheck(frame_size_,
-                                                                                 kMips64);
-  NewLIR0(kPseudoMethodEntry);
-  RegStorage check_reg = AllocTempWide();
-  RegStorage new_sp = AllocTempWide();
-  if (!skip_overflow_check) {
-    // Load stack limit.
-    LoadWordDisp(rs_rMIPS64_SELF, Thread::StackEndOffset<8>().Int32Value(), check_reg);
-  }
-  // Spill core callee saves.
-  SpillCoreRegs();
-  // NOTE: promotion of FP regs currently unsupported, thus no FP spill.
-  DCHECK_EQ(num_fp_spills_, 0);
-  const int frame_sub = frame_size_ - spill_count * 8;
-  if (!skip_overflow_check) {
-    class StackOverflowSlowPath : public LIRSlowPath {
-     public:
-      StackOverflowSlowPath(Mir2Lir* m2l, LIR* branch, size_t sp_displace)
-          : LIRSlowPath(m2l, branch), sp_displace_(sp_displace) {
-      }
-      void Compile() OVERRIDE {
-        m2l_->ResetRegPool();
-        m2l_->ResetDefTracking();
-        GenerateTargetLabel(kPseudoThrowTarget);
-        // Load RA from the top of the frame.
-        m2l_->LoadWordDisp(rs_rMIPS64_SP, sp_displace_ - 8, rs_rRAd);
-        m2l_->OpRegImm(kOpAdd, rs_rMIPS64_SP, sp_displace_);
-        m2l_->ClobberCallerSave();
-        RegStorage r_tgt = m2l_->CallHelperSetup(kQuickThrowStackOverflow);  // Doesn't clobber LR.
-        m2l_->CallHelper(r_tgt, kQuickThrowStackOverflow, false /* MarkSafepointPC */,
-                         false /* UseLink */);
-      }
-
-     private:
-      const size_t sp_displace_;
-    };
-    OpRegRegImm(kOpSub, new_sp, rs_rMIPS64_SP, frame_sub);
-    LIR* branch = OpCmpBranch(kCondUlt, new_sp, check_reg, nullptr);
-    AddSlowPath(new(arena_)StackOverflowSlowPath(this, branch, spill_count * 8));
-    // TODO: avoid copy for small frame sizes.
-    OpRegCopy(rs_rMIPS64_SP, new_sp);  // Establish stack.
-  } else {
-    OpRegImm(kOpSub, rs_rMIPS64_SP, frame_sub);
-  }
-
-  FlushIns(ArgLocs, rl_method);
-
-  FreeTemp(rs_rMIPS64_ARG0);
-  FreeTemp(rs_rMIPS64_ARG1);
-  FreeTemp(rs_rMIPS64_ARG2);
-  FreeTemp(rs_rMIPS64_ARG3);
-  FreeTemp(rs_rMIPS64_ARG4);
-  FreeTemp(rs_rMIPS64_ARG5);
-  FreeTemp(rs_rMIPS64_ARG6);
-  FreeTemp(rs_rMIPS64_ARG7);
-}
-
-void Mips64Mir2Lir::GenExitSequence() {
-  /*
-   * In the exit path, rMIPS64_RET0/rMIPS64_RET1 are live - make sure they aren't
-   * allocated by the register utilities as temps.
-   */
-  LockTemp(rs_rMIPS64_RET0);
-  LockTemp(rs_rMIPS64_RET1);
-
-  NewLIR0(kPseudoMethodExit);
-  UnSpillCoreRegs();
-  OpReg(kOpBx, rs_rRAd);
-}
-
-void Mips64Mir2Lir::GenSpecialExitSequence() {
-  OpReg(kOpBx, rs_rRAd);
-}
-
-void Mips64Mir2Lir::GenSpecialEntryForSuspend() {
-  // Keep 16-byte stack alignment - push A0, i.e. ArtMethod* and RA.
-  core_spill_mask_ = (1u << rs_rRAd.GetRegNum());
-  num_core_spills_ = 1u;
-  fp_spill_mask_ = 0u;
-  num_fp_spills_ = 0u;
-  frame_size_ = 16u;
-  core_vmap_table_.clear();
-  fp_vmap_table_.clear();
-  OpRegImm(kOpSub, rs_rMIPS64_SP, frame_size_);
-  StoreWordDisp(rs_rMIPS64_SP, frame_size_ - 8, rs_rRAd);
-  StoreWordDisp(rs_rMIPS64_SP, 0, rs_rA0d);
-}
-
-void Mips64Mir2Lir::GenSpecialExitForSuspend() {
-  // Pop the frame. Don't pop ArtMethod*, it's no longer needed.
-  LoadWordDisp(rs_rMIPS64_SP, frame_size_ - 8, rs_rRAd);
-  OpRegImm(kOpAdd, rs_rMIPS64_SP, frame_size_);
-}
-
-/*
- * Bit of a hack here - in the absence of a real scheduling pass,
- * emit the next instruction in static & direct invoke sequences.
- */
-static int Mips64NextSDCallInsn(CompilationUnit* cu, CallInfo* info ATTRIBUTE_UNUSED, int state,
-                                const MethodReference& target_method, uint32_t,
-                                uintptr_t direct_code, uintptr_t direct_method, InvokeType type) {
-  Mir2Lir* cg = static_cast<Mir2Lir*>(cu->cg.get());
-  if (direct_code != 0 && direct_method != 0) {
-    switch (state) {
-    case 0:  // Get the current Method* [sets kArg0]
-      if (direct_code != static_cast<uintptr_t>(-1)) {
-        cg->LoadConstantWide(cg->TargetPtrReg(kInvokeTgt), direct_code);
-      } else {
-        cg->LoadCodeAddress(target_method, type, kInvokeTgt);
-      }
-      if (direct_method != static_cast<uintptr_t>(-1)) {
-        cg->LoadConstantWide(cg->TargetReg(kArg0, kRef), direct_method);
-      } else {
-        cg->LoadMethodAddress(target_method, type, kArg0);
-      }
-      break;
-    default:
-      return -1;
-    }
-  } else {
-    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.
-      cg->LoadCurrMethodDirect(arg0_ref);
-      break;
-    case 1:  // Get method->dex_cache_resolved_methods_
-      cg->LoadRefDisp(arg0_ref, mirror::ArtMethod::DexCacheResolvedMethodsOffset().Int32Value(),
-                      arg0_ref,       kNotVolatile);
-      // Set up direct code if known.
-      if (direct_code != 0) {
-        if (direct_code != static_cast<uintptr_t>(-1)) {
-          cg->LoadConstantWide(cg->TargetPtrReg(kInvokeTgt), direct_code);
-        } else {
-          CHECK_LT(target_method.dex_method_index, target_method.dex_file->NumMethodIds());
-          cg->LoadCodeAddress(target_method, type, kInvokeTgt);
-        }
-      }
-      break;
-    case 2:  // Grab target method*
-      CHECK_EQ(cu->dex_file, target_method.dex_file);
-      cg->LoadRefDisp(arg0_ref, mirror::ObjectArray<mirror::Object>::
-                          OffsetOfElement(target_method.dex_method_index).Int32Value(), arg0_ref,
-                      kNotVolatile);
-      break;
-    case 3:  // Grab the code from the method*
-      if (direct_code == 0) {
-        int32_t offset = mirror::ArtMethod::EntryPointFromQuickCompiledCodeOffset(
-            InstructionSetPointerSize(cu->instruction_set)).Int32Value();
-        // Get the compiled code address [use *alt_from or kArg0, set kInvokeTgt]
-        cg->LoadWordDisp(arg0_ref, offset, cg->TargetPtrReg(kInvokeTgt));
-      }
-      break;
-    default:
-      return -1;
-    }
-  }
-  return state + 1;
-}
-
-NextCallInsn Mips64Mir2Lir::GetNextSDCallInsn() {
-  return Mips64NextSDCallInsn;
-}
-
-LIR* Mips64Mir2Lir::GenCallInsn(const MirMethodLoweringInfo& method_info ATTRIBUTE_UNUSED) {
-  return OpReg(kOpBlx, TargetPtrReg(kInvokeTgt));
-}
-
-}  // namespace art
diff --git a/compiler/dex/quick/mips64/codegen_mips64.h b/compiler/dex/quick/mips64/codegen_mips64.h
deleted file mode 100644
index c9fd62f..0000000
--- a/compiler/dex/quick/mips64/codegen_mips64.h
+++ /dev/null
@@ -1,328 +0,0 @@
-/*
- * Copyright (C) 2015 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.
- */
-
-#ifndef ART_COMPILER_DEX_QUICK_MIPS64_CODEGEN_MIPS64_H_
-#define ART_COMPILER_DEX_QUICK_MIPS64_CODEGEN_MIPS64_H_
-
-#include "dex/quick/mir_to_lir.h"
-#include "mips64_lir.h"
-
-namespace art {
-
-struct CompilationUnit;
-
-class Mips64Mir2Lir FINAL : public Mir2Lir {
- protected:
-  class InToRegStorageMips64Mapper : public InToRegStorageMapper {
-   public:
-    explicit InToRegStorageMips64Mapper(Mir2Lir* m2l) : m2l_(m2l), cur_arg_reg_(0) {}
-    virtual RegStorage GetNextReg(ShortyArg arg);
-    virtual void Reset() OVERRIDE {
-      cur_arg_reg_ = 0;
-    }
-   protected:
-    Mir2Lir* m2l_;
-   private:
-    size_t cur_arg_reg_;
-  };
-
-  InToRegStorageMips64Mapper in_to_reg_storage_mips64_mapper_;
-  InToRegStorageMapper* GetResetedInToRegStorageMapper() OVERRIDE {
-    in_to_reg_storage_mips64_mapper_.Reset();
-    return &in_to_reg_storage_mips64_mapper_;
-  }
-
- public:
-  Mips64Mir2Lir(CompilationUnit* cu, MIRGraph* mir_graph, ArenaAllocator* arena);
-
-  // Required for target - codegen utilities.
-  bool SmallLiteralDivRem(Instruction::Code dalvik_opcode, bool is_div, RegLocation rl_src,
-                          RegLocation rl_dest, int lit);
-  bool EasyMultiply(RegLocation rl_src, RegLocation rl_dest, int lit) OVERRIDE;
-  void GenMultiplyByConstantFloat(RegLocation rl_dest, RegLocation rl_src1, int32_t constant)
-  OVERRIDE;
-  void GenMultiplyByConstantDouble(RegLocation rl_dest, RegLocation rl_src1, int64_t constant)
-  OVERRIDE;
-  LIR* CheckSuspendUsingLoad() OVERRIDE;
-  RegStorage LoadHelper(QuickEntrypointEnum trampoline) OVERRIDE;
-  LIR* LoadBaseDisp(RegStorage r_base, int displacement, RegStorage r_dest, OpSize size,
-                    VolatileKind is_volatile) OVERRIDE;
-  LIR* LoadBaseIndexed(RegStorage r_base, RegStorage r_index, RegStorage r_dest, int scale,
-                       OpSize size) OVERRIDE;
-  LIR* LoadConstantNoClobber(RegStorage r_dest, int value);
-  LIR* LoadConstantWide(RegStorage r_dest, int64_t value);
-  LIR* StoreBaseDisp(RegStorage r_base, int displacement, RegStorage r_src, OpSize size,
-                     VolatileKind is_volatile) OVERRIDE;
-  LIR* StoreBaseIndexed(RegStorage r_base, RegStorage r_index, RegStorage r_src, int scale,
-                        OpSize size) OVERRIDE;
-  LIR* GenAtomic64Load(RegStorage r_base, int displacement, RegStorage r_dest);
-  LIR* GenAtomic64Store(RegStorage r_base, int displacement, RegStorage r_src);
-
-  /// @copydoc Mir2Lir::UnconditionallyMarkGCCard(RegStorage)
-  void UnconditionallyMarkGCCard(RegStorage tgt_addr_reg) OVERRIDE;
-
-  // Required for target - register utilities.
-  RegStorage TargetReg(SpecialTargetRegister reg) OVERRIDE;
-  RegStorage TargetReg(SpecialTargetRegister reg, WideKind wide_kind) OVERRIDE {
-    if (wide_kind == kWide || wide_kind == kRef) {
-      return As64BitReg(TargetReg(reg));
-    } else {
-      return Check32BitReg(TargetReg(reg));
-    }
-  }
-  RegStorage TargetPtrReg(SpecialTargetRegister reg) OVERRIDE {
-    return As64BitReg(TargetReg(reg));
-  }
-  RegLocation GetReturnAlt();
-  RegLocation GetReturnWideAlt();
-  RegLocation LocCReturn();
-  RegLocation LocCReturnRef();
-  RegLocation LocCReturnDouble();
-  RegLocation LocCReturnFloat();
-  RegLocation LocCReturnWide();
-  ResourceMask GetRegMaskCommon(const RegStorage& reg) const OVERRIDE;
-  void AdjustSpillMask();
-  void ClobberCallerSave();
-  void FreeCallTemps();
-  void LockCallTemps();
-  void CompilerInitializeRegAlloc();
-
-  // Required for target - miscellaneous.
-  void AssembleLIR();
-  int AssignInsnOffsets();
-  void AssignOffsets();
-  AssemblerStatus AssembleInstructions(CodeOffset start_addr);
-  void DumpResourceMask(LIR* lir, const ResourceMask& mask, const char* prefix) OVERRIDE;
-  void SetupTargetResourceMasks(LIR* lir, uint64_t flags, ResourceMask* use_mask,
-                                ResourceMask* def_mask) OVERRIDE;
-  const char* GetTargetInstFmt(int opcode);
-  const char* GetTargetInstName(int opcode);
-  std::string BuildInsnString(const char* fmt, LIR* lir, unsigned char* base_addr);
-  ResourceMask GetPCUseDefEncoding() const OVERRIDE;
-  uint64_t GetTargetInstFlags(int opcode);
-  size_t GetInsnSize(LIR* lir) OVERRIDE;
-  bool IsUnconditionalBranch(LIR* lir);
-
-  // Get the register class for load/store of a field.
-  RegisterClass RegClassForFieldLoadStore(OpSize size, bool is_volatile) OVERRIDE;
-
-  // Required for target - Dalvik-level generators.
-  void GenShiftOpLong(Instruction::Code opcode, RegLocation rl_dest, RegLocation rl_src1,
-                      RegLocation lr_shift);
-  void GenArithImmOpLong(Instruction::Code opcode, RegLocation rl_dest, RegLocation rl_src1,
-                         RegLocation rl_src2, int flags);
-  void GenArrayGet(int opt_flags, OpSize size, RegLocation rl_array, RegLocation rl_index,
-                   RegLocation rl_dest, int scale);
-  void GenArrayPut(int opt_flags, OpSize size, RegLocation rl_array, RegLocation rl_index,
-                   RegLocation rl_src, int scale, bool card_mark);
-  void GenShiftImmOpLong(Instruction::Code opcode, RegLocation rl_dest, RegLocation rl_src1,
-                         RegLocation rl_shift, int flags);
-  void GenArithOpDouble(Instruction::Code opcode, RegLocation rl_dest, RegLocation rl_src1,
-                        RegLocation rl_src2);
-  void GenArithOpFloat(Instruction::Code opcode, RegLocation rl_dest, RegLocation rl_src1,
-                       RegLocation rl_src2);
-  void GenCmpFP(Instruction::Code opcode, RegLocation rl_dest, RegLocation rl_src1,
-                RegLocation rl_src2);
-  void GenConversion(Instruction::Code opcode, RegLocation rl_dest, RegLocation rl_src);
-  bool GenInlinedAbsFloat(CallInfo* info) OVERRIDE;
-  bool GenInlinedAbsDouble(CallInfo* info) OVERRIDE;
-  bool GenInlinedCas(CallInfo* info, bool is_long, bool is_object);
-  bool GenInlinedMinMax(CallInfo* info, bool is_min, bool is_long);
-  bool GenInlinedSqrt(CallInfo* info);
-  bool GenInlinedPeek(CallInfo* info, OpSize size);
-  bool GenInlinedPoke(CallInfo* info, OpSize size);
-  void GenIntToLong(RegLocation rl_dest, RegLocation rl_src) OVERRIDE;
-  void GenArithOpLong(Instruction::Code opcode, RegLocation rl_dest, RegLocation rl_src1,
-                      RegLocation rl_src2, int flags) OVERRIDE;
-  RegLocation GenDivRem(RegLocation rl_dest, RegStorage reg_lo, RegStorage reg_hi, bool is_div);
-  RegLocation GenDivRemLit(RegLocation rl_dest, RegStorage reg_lo, int lit, bool is_div);
-  void GenCmpLong(RegLocation rl_dest, RegLocation rl_src1, RegLocation rl_src2);
-  void GenDivZeroCheckWide(RegStorage reg);
-  void GenEntrySequence(RegLocation* ArgLocs, RegLocation rl_method);
-  void GenExitSequence();
-  void GenSpecialExitSequence() OVERRIDE;
-  void GenSpecialEntryForSuspend() OVERRIDE;
-  void GenSpecialExitForSuspend() OVERRIDE;
-  void GenFusedFPCmpBranch(BasicBlock* bb, MIR* mir, bool gt_bias, bool is_double);
-  void GenFusedLongCmpBranch(BasicBlock* bb, MIR* mir);
-  void GenSelect(BasicBlock* bb, MIR* mir);
-  void GenSelectConst32(RegStorage left_op, RegStorage right_op, ConditionCode code,
-                        int32_t true_val, int32_t false_val, RegStorage rs_dest,
-                        RegisterClass dest_reg_class) OVERRIDE;
-  bool GenMemBarrier(MemBarrierKind barrier_kind);
-  void GenMoveException(RegLocation rl_dest);
-  void GenMultiplyByTwoBitMultiplier(RegLocation rl_src, RegLocation rl_result, int lit,
-                                     int first_bit, int second_bit);
-  void GenNegDouble(RegLocation rl_dest, RegLocation rl_src);
-  void GenNegFloat(RegLocation rl_dest, RegLocation rl_src);
-  void GenLargePackedSwitch(MIR* mir, uint32_t table_offset, RegLocation rl_src);
-  void GenLargeSparseSwitch(MIR* mir, uint32_t table_offset, RegLocation rl_src);
-  bool GenSpecialCase(BasicBlock* bb, MIR* mir, const InlineMethod& special);
-
-  // Required for target - single operation generators.
-  LIR* OpUnconditionalBranch(LIR* target);
-  LIR* OpCmpBranch(ConditionCode cond, RegStorage src1, RegStorage src2, LIR* target);
-  LIR* OpCmpImmBranch(ConditionCode cond, RegStorage reg, int check_value, LIR* target);
-  LIR* OpCondBranch(ConditionCode cc, LIR* target);
-  LIR* OpDecAndBranch(ConditionCode c_code, RegStorage reg, LIR* target);
-  LIR* OpFpRegCopy(RegStorage r_dest, RegStorage r_src);
-  LIR* OpIT(ConditionCode cond, const char* guide);
-  void OpEndIT(LIR* it);
-  LIR* OpMem(OpKind op, RegStorage r_base, int disp);
-  void OpPcRelLoad(RegStorage reg, LIR* target);
-  LIR* OpReg(OpKind op, RegStorage r_dest_src);
-  void OpRegCopy(RegStorage r_dest, RegStorage r_src);
-  LIR* OpRegCopyNoInsert(RegStorage r_dest, RegStorage r_src);
-  LIR* OpRegImm(OpKind op, RegStorage r_dest_src1, int value);
-  LIR* OpRegReg(OpKind op, RegStorage r_dest_src1, RegStorage r_src2);
-  LIR* OpMovRegMem(RegStorage r_dest, RegStorage r_base, int offset, MoveType move_type);
-  LIR* OpMovMemReg(RegStorage r_base, int offset, RegStorage r_src, MoveType move_type);
-  LIR* OpCondRegReg(OpKind op, ConditionCode cc, RegStorage r_dest, RegStorage r_src);
-  LIR* OpRegRegImm(OpKind op, RegStorage r_dest, RegStorage r_src1, int value);
-  LIR* OpRegRegReg(OpKind op, RegStorage r_dest, RegStorage r_src1, RegStorage r_src2);
-  LIR* OpTestSuspend(LIR* target);
-  LIR* OpVldm(RegStorage r_base, int count);
-  LIR* OpVstm(RegStorage r_base, int count);
-  void OpRegCopyWide(RegStorage dest, RegStorage src);
-
-  // TODO: collapse r_dest.
-  LIR* LoadBaseDispBody(RegStorage r_base, int displacement, RegStorage r_dest, OpSize size);
-  // TODO: collapse r_src.
-  LIR* StoreBaseDispBody(RegStorage r_base, int displacement, RegStorage r_src, OpSize size);
-  void SpillCoreRegs();
-  void UnSpillCoreRegs();
-  static const Mips64EncodingMap EncodingMap[kMips64Last];
-  bool InexpensiveConstantInt(int32_t value);
-  bool InexpensiveConstantFloat(int32_t value);
-  bool InexpensiveConstantLong(int64_t value);
-  bool InexpensiveConstantDouble(int64_t value);
-
-  bool WideGPRsAreAliases() const OVERRIDE {
-    return true;  // 64b architecture.
-  }
-  bool WideFPRsAreAliases() const OVERRIDE {
-    return true;  // 64b architecture.
-  }
-
-  LIR* InvokeTrampoline(OpKind op, RegStorage r_tgt, QuickEntrypointEnum trampoline) OVERRIDE;
-  RegLocation GenDivRem(RegLocation rl_dest, RegLocation rl_src1, RegLocation rl_src2,
-                        bool is_div, int flags) OVERRIDE;
-  RegLocation GenDivRemLit(RegLocation rl_dest, RegLocation rl_src1, int lit, bool is_div)
-  OVERRIDE;
-  NextCallInsn GetNextSDCallInsn() OVERRIDE;
-  LIR* GenCallInsn(const MirMethodLoweringInfo& method_info) OVERRIDE;
-  // Unimplemented intrinsics.
-  bool GenInlinedCharAt(CallInfo* info ATTRIBUTE_UNUSED) OVERRIDE {
-    return false;
-  }
-  bool GenInlinedAbsInt(CallInfo* info ATTRIBUTE_UNUSED) OVERRIDE {
-    return false;
-  }
-  bool GenInlinedAbsLong(CallInfo* info ATTRIBUTE_UNUSED) OVERRIDE {
-    return false;
-  }
-  bool GenInlinedIndexOf(CallInfo* info ATTRIBUTE_UNUSED, bool zero_based ATTRIBUTE_UNUSED)
-  OVERRIDE {
-    return false;
-  }
-
- private:
-  void GenLongOp(OpKind op, RegLocation rl_dest, RegLocation rl_src1, RegLocation rl_src2);
-  void GenNotLong(RegLocation rl_dest, RegLocation rl_src);
-  void GenNegLong(RegLocation rl_dest, RegLocation rl_src);
-  void GenMulLong(RegLocation rl_dest, RegLocation rl_src1, RegLocation rl_src2);
-  void GenDivRemLong(Instruction::Code opcode, RegLocation rl_dest, RegLocation rl_src1,
-                     RegLocation rl_src2, bool is_div, int flags);
-  void GenConversionCall(QuickEntrypointEnum trampoline, RegLocation rl_dest, RegLocation rl_src,
-                         RegisterClass reg_class);
-
-  void ConvertShortToLongBranch(LIR* lir);
-
-  /**
-   * @param reg #RegStorage containing a Solo64 input register (e.g. @c a1 or @c d0).
-   * @return A Solo32 with the same register number as the @p reg (e.g. @c a1 or @c f0).
-   * @see As64BitReg
-   */
-  RegStorage As32BitReg(RegStorage reg) {
-    DCHECK(!reg.IsPair());
-    if ((kFailOnSizeError || kReportSizeError) && !reg.Is64Bit()) {
-      if (kFailOnSizeError) {
-        LOG(FATAL) << "Expected 64b register";
-      } else {
-        LOG(WARNING) << "Expected 64b register";
-        return reg;
-      }
-    }
-    RegStorage ret_val = RegStorage(RegStorage::k32BitSolo,
-                                    reg.GetRawBits() & RegStorage::kRegTypeMask);
-    DCHECK_EQ(GetRegInfo(reg)->FindMatchingView(RegisterInfo::k32SoloStorageMask)
-              ->GetReg().GetReg(),
-              ret_val.GetReg());
-    return ret_val;
-  }
-
-  RegStorage Check32BitReg(RegStorage reg) {
-    if ((kFailOnSizeError || kReportSizeError) && !reg.Is32Bit()) {
-      if (kFailOnSizeError) {
-        LOG(FATAL) << "Checked for 32b register";
-      } else {
-        LOG(WARNING) << "Checked for 32b register";
-        return As32BitReg(reg);
-      }
-    }
-    return reg;
-  }
-
-  /**
-   * @param reg #RegStorage containing a Solo32 input register (e.g. @c a1 or @c f0).
-   * @return A Solo64 with the same register number as the @p reg (e.g. @c a1 or @c d0).
-   */
-  RegStorage As64BitReg(RegStorage reg) {
-    DCHECK(!reg.IsPair());
-    if ((kFailOnSizeError || kReportSizeError) && !reg.Is32Bit()) {
-      if (kFailOnSizeError) {
-        LOG(FATAL) << "Expected 32b register";
-      } else {
-        LOG(WARNING) << "Expected 32b register";
-        return reg;
-      }
-    }
-    RegStorage ret_val = RegStorage(RegStorage::k64BitSolo,
-                                    reg.GetRawBits() & RegStorage::kRegTypeMask);
-    DCHECK_EQ(GetRegInfo(reg)->FindMatchingView(RegisterInfo::k64SoloStorageMask)
-              ->GetReg().GetReg(),
-              ret_val.GetReg());
-    return ret_val;
-  }
-
-  RegStorage Check64BitReg(RegStorage reg) {
-    if ((kFailOnSizeError || kReportSizeError) && !reg.Is64Bit()) {
-      if (kFailOnSizeError) {
-        LOG(FATAL) << "Checked for 64b register";
-      } else {
-        LOG(WARNING) << "Checked for 64b register";
-        return As64BitReg(reg);
-      }
-    }
-    return reg;
-  }
-
-  void GenBreakpoint(int code);
-};
-
-}  // namespace art
-
-#endif  // ART_COMPILER_DEX_QUICK_MIPS64_CODEGEN_MIPS64_H_
diff --git a/compiler/dex/quick/mips64/fp_mips64.cc b/compiler/dex/quick/mips64/fp_mips64.cc
deleted file mode 100644
index 5c8ee9c..0000000
--- a/compiler/dex/quick/mips64/fp_mips64.cc
+++ /dev/null
@@ -1,253 +0,0 @@
-/*
- * Copyright (C) 2015 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.
- */
-
-#include "codegen_mips64.h"
-
-#include "base/logging.h"
-#include "dex/quick/mir_to_lir-inl.h"
-#include "entrypoints/quick/quick_entrypoints.h"
-#include "mips64_lir.h"
-
-namespace art {
-
-void Mips64Mir2Lir::GenArithOpFloat(Instruction::Code opcode, RegLocation rl_dest,
-                                    RegLocation rl_src1, RegLocation rl_src2) {
-  int op = kMips64Nop;
-  RegLocation rl_result;
-
-  /*
-   * Don't attempt to optimize register usage since these opcodes call out to
-   * the handlers.
-   */
-  switch (opcode) {
-    case Instruction::ADD_FLOAT_2ADDR:
-    case Instruction::ADD_FLOAT:
-      op = kMips64Fadds;
-      break;
-    case Instruction::SUB_FLOAT_2ADDR:
-    case Instruction::SUB_FLOAT:
-      op = kMips64Fsubs;
-      break;
-    case Instruction::DIV_FLOAT_2ADDR:
-    case Instruction::DIV_FLOAT:
-      op = kMips64Fdivs;
-      break;
-    case Instruction::MUL_FLOAT_2ADDR:
-    case Instruction::MUL_FLOAT:
-      op = kMips64Fmuls;
-      break;
-    case Instruction::REM_FLOAT_2ADDR:
-    case Instruction::REM_FLOAT:
-      FlushAllRegs();   // Send everything to home location.
-      CallRuntimeHelperRegLocationRegLocation(kQuickFmodf, rl_src1, rl_src2, false);
-      rl_result = GetReturn(kFPReg);
-      StoreValue(rl_dest, rl_result);
-      return;
-    case Instruction::NEG_FLOAT:
-      GenNegFloat(rl_dest, rl_src1);
-      return;
-    default:
-      LOG(FATAL) << "Unexpected opcode: " << opcode;
-  }
-  rl_src1 = LoadValue(rl_src1, kFPReg);
-  rl_src2 = LoadValue(rl_src2, kFPReg);
-  rl_result = EvalLoc(rl_dest, kFPReg, true);
-  NewLIR3(op, rl_result.reg.GetReg(), rl_src1.reg.GetReg(), rl_src2.reg.GetReg());
-  StoreValue(rl_dest, rl_result);
-}
-
-void Mips64Mir2Lir::GenArithOpDouble(Instruction::Code opcode, RegLocation rl_dest,
-                                     RegLocation rl_src1, RegLocation rl_src2) {
-  int op = kMips64Nop;
-  RegLocation rl_result;
-
-  switch (opcode) {
-    case Instruction::ADD_DOUBLE_2ADDR:
-    case Instruction::ADD_DOUBLE:
-      op = kMips64Faddd;
-      break;
-    case Instruction::SUB_DOUBLE_2ADDR:
-    case Instruction::SUB_DOUBLE:
-      op = kMips64Fsubd;
-      break;
-    case Instruction::DIV_DOUBLE_2ADDR:
-    case Instruction::DIV_DOUBLE:
-      op = kMips64Fdivd;
-      break;
-    case Instruction::MUL_DOUBLE_2ADDR:
-    case Instruction::MUL_DOUBLE:
-      op = kMips64Fmuld;
-      break;
-    case Instruction::REM_DOUBLE_2ADDR:
-    case Instruction::REM_DOUBLE:
-      FlushAllRegs();   // Send everything to home location.
-      CallRuntimeHelperRegLocationRegLocation(kQuickFmod, rl_src1, rl_src2, false);
-      rl_result = GetReturnWide(kFPReg);
-      StoreValueWide(rl_dest, rl_result);
-      return;
-    case Instruction::NEG_DOUBLE:
-      GenNegDouble(rl_dest, rl_src1);
-      return;
-    default:
-      LOG(FATAL) << "Unpexpected opcode: " << opcode;
-  }
-  rl_src1 = LoadValueWide(rl_src1, kFPReg);
-  DCHECK(rl_src1.wide);
-  rl_src2 = LoadValueWide(rl_src2, kFPReg);
-  DCHECK(rl_src2.wide);
-  rl_result = EvalLoc(rl_dest, kFPReg, true);
-  DCHECK(rl_dest.wide);
-  DCHECK(rl_result.wide);
-  NewLIR3(op, rl_result.reg.GetReg(), rl_src1.reg.GetReg(), rl_src2.reg.GetReg());
-  StoreValueWide(rl_dest, rl_result);
-}
-
-void Mips64Mir2Lir::GenMultiplyByConstantFloat(RegLocation rl_dest, RegLocation rl_src1,
-                                               int32_t constant) {
-  // TODO: need mips64 implementation.
-  UNUSED(rl_dest, rl_src1, constant);
-  LOG(FATAL) << "Unimplemented GenMultiplyByConstantFloat in mips64";
-}
-
-void Mips64Mir2Lir::GenMultiplyByConstantDouble(RegLocation rl_dest, RegLocation rl_src1,
-                                                int64_t constant) {
-  // TODO: need mips64 implementation.
-  UNUSED(rl_dest, rl_src1, constant);
-  LOG(FATAL) << "Unimplemented GenMultiplyByConstantDouble in mips64";
-}
-
-void Mips64Mir2Lir::GenConversion(Instruction::Code opcode, RegLocation rl_dest,
-                                  RegLocation rl_src) {
-  int op = kMips64Nop;
-  RegLocation rl_result;
-  switch (opcode) {
-    case Instruction::INT_TO_FLOAT:
-      op = kMips64Fcvtsw;
-      break;
-    case Instruction::DOUBLE_TO_FLOAT:
-      op = kMips64Fcvtsd;
-      break;
-    case Instruction::FLOAT_TO_DOUBLE:
-      op = kMips64Fcvtds;
-      break;
-    case Instruction::INT_TO_DOUBLE:
-      op = kMips64Fcvtdw;
-      break;
-    case Instruction::FLOAT_TO_INT:
-      GenConversionCall(kQuickF2iz, rl_dest, rl_src, kCoreReg);
-      return;
-    case Instruction::DOUBLE_TO_INT:
-      GenConversionCall(kQuickD2iz, rl_dest, rl_src, kCoreReg);
-      return;
-    case Instruction::LONG_TO_DOUBLE:
-      GenConversionCall(kQuickL2d, rl_dest, rl_src, kFPReg);
-      return;
-    case Instruction::FLOAT_TO_LONG:
-      GenConversionCall(kQuickF2l, rl_dest, rl_src, kCoreReg);
-      return;
-    case Instruction::LONG_TO_FLOAT:
-      GenConversionCall(kQuickL2f, rl_dest, rl_src, kFPReg);
-      return;
-    case Instruction::DOUBLE_TO_LONG:
-      GenConversionCall(kQuickD2l, rl_dest, rl_src, kCoreReg);
-      return;
-    default:
-      LOG(FATAL) << "Unexpected opcode: " << opcode;
-  }
-  if (rl_src.wide) {
-    rl_src = LoadValueWide(rl_src, kFPReg);
-  } else {
-    rl_src = LoadValue(rl_src, kFPReg);
-  }
-  rl_result = EvalLoc(rl_dest, kFPReg, true);
-  NewLIR2(op, rl_result.reg.GetReg(), rl_src.reg.GetReg());
-  if (rl_dest.wide) {
-    StoreValueWide(rl_dest, rl_result);
-  } else {
-    StoreValue(rl_dest, rl_result);
-  }
-}
-
-void Mips64Mir2Lir::GenCmpFP(Instruction::Code opcode, RegLocation rl_dest, RegLocation rl_src1,
-                             RegLocation rl_src2) {
-  bool wide = true;
-  QuickEntrypointEnum target;
-
-  switch (opcode) {
-    case Instruction::CMPL_FLOAT:
-      target = kQuickCmplFloat;
-      wide = false;
-      break;
-    case Instruction::CMPG_FLOAT:
-      target = kQuickCmpgFloat;
-      wide = false;
-      break;
-    case Instruction::CMPL_DOUBLE:
-      target = kQuickCmplDouble;
-      break;
-    case Instruction::CMPG_DOUBLE:
-      target = kQuickCmpgDouble;
-      break;
-    default:
-      LOG(FATAL) << "Unexpected opcode: " << opcode;
-      target = kQuickCmplFloat;
-  }
-  FlushAllRegs();
-  LockCallTemps();
-  if (wide) {
-    RegStorage r_tmp1(RegStorage::k64BitSolo, rMIPS64_FARG0);
-    RegStorage r_tmp2(RegStorage::k64BitSolo, rMIPS64_FARG1);
-    LoadValueDirectWideFixed(rl_src1, r_tmp1);
-    LoadValueDirectWideFixed(rl_src2, r_tmp2);
-  } else {
-    LoadValueDirectFixed(rl_src1, rs_rMIPS64_FARG0);
-    LoadValueDirectFixed(rl_src2, rs_rMIPS64_FARG1);
-  }
-  RegStorage r_tgt = LoadHelper(target);
-  // NOTE: not a safepoint.
-  OpReg(kOpBlx, r_tgt);
-  RegLocation rl_result = GetReturn(kCoreReg);
-  StoreValue(rl_dest, rl_result);
-}
-
-void Mips64Mir2Lir::GenFusedFPCmpBranch(BasicBlock* bb, MIR* mir, bool gt_bias, bool is_double) {
-  UNUSED(bb, mir, gt_bias, is_double);
-  UNIMPLEMENTED(FATAL) << "Need codegen for fused fp cmp branch";
-}
-
-void Mips64Mir2Lir::GenNegFloat(RegLocation rl_dest, RegLocation rl_src) {
-  RegLocation rl_result;
-  rl_src = LoadValue(rl_src, kFPReg);
-  rl_result = EvalLoc(rl_dest, kFPReg, true);
-  NewLIR2(kMips64Fnegs, rl_result.reg.GetReg(), rl_src.reg.GetReg());
-  StoreValue(rl_dest, rl_result);
-}
-
-void Mips64Mir2Lir::GenNegDouble(RegLocation rl_dest, RegLocation rl_src) {
-  RegLocation rl_result;
-  rl_src = LoadValueWide(rl_src, kFPReg);
-  rl_result = EvalLocWide(rl_dest, kFPReg, true);
-  NewLIR2(kMips64Fnegd, rl_result.reg.GetReg(), rl_src.reg.GetReg());
-  StoreValueWide(rl_dest, rl_result);
-}
-
-bool Mips64Mir2Lir::GenInlinedMinMax(CallInfo* info, bool is_min, bool is_long) {
-  // TODO: need Mips64 implementation.
-  UNUSED(info, is_min, is_long);
-  return false;
-}
-
-}  // namespace art
diff --git a/compiler/dex/quick/mips64/int_mips64.cc b/compiler/dex/quick/mips64/int_mips64.cc
deleted file mode 100644
index 5c545bb..0000000
--- a/compiler/dex/quick/mips64/int_mips64.cc
+++ /dev/null
@@ -1,692 +0,0 @@
-/*
- * Copyright (C) 2015 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.
- */
-
-/* This file contains codegen for the Mips64 ISA */
-
-#include "codegen_mips64.h"
-
-#include "base/logging.h"
-#include "dex/mir_graph.h"
-#include "dex/quick/mir_to_lir-inl.h"
-#include "dex/reg_storage_eq.h"
-#include "entrypoints/quick/quick_entrypoints.h"
-#include "mips64_lir.h"
-#include "mirror/array-inl.h"
-
-namespace art {
-
-/*
- * Compare two 64-bit values
- *    x = y     return  0
- *    x < y     return -1
- *    x > y     return  1
- *
- *    slt   temp, x, y;          # (x < y) ? 1:0
- *    slt   res, y, x;           # (x > y) ? 1:0
- *    subu  res, res, temp;      # res = -1:1:0 for [ < > = ]
- *
- */
-void Mips64Mir2Lir::GenCmpLong(RegLocation rl_dest, RegLocation rl_src1, RegLocation rl_src2) {
-  rl_src1 = LoadValueWide(rl_src1, kCoreReg);
-  rl_src2 = LoadValueWide(rl_src2, kCoreReg);
-  RegStorage temp = AllocTempWide();
-  RegLocation rl_result = EvalLoc(rl_dest, kCoreReg, true);
-  NewLIR3(kMips64Slt, temp.GetReg(), rl_src1.reg.GetReg(), rl_src2.reg.GetReg());
-  NewLIR3(kMips64Slt, rl_result.reg.GetReg(), rl_src2.reg.GetReg(), rl_src1.reg.GetReg());
-  NewLIR3(kMips64Subu, rl_result.reg.GetReg(), rl_result.reg.GetReg(), temp.GetReg());
-  FreeTemp(temp);
-  StoreValue(rl_dest, rl_result);
-}
-
-LIR* Mips64Mir2Lir::OpCmpBranch(ConditionCode cond, RegStorage src1, RegStorage src2, LIR* target) {
-  LIR* branch;
-  Mips64OpCode slt_op;
-  Mips64OpCode br_op;
-  bool cmp_zero = false;
-  bool swapped = false;
-  switch (cond) {
-    case kCondEq:
-      br_op = kMips64Beq;
-      cmp_zero = true;
-      break;
-    case kCondNe:
-      br_op = kMips64Bne;
-      cmp_zero = true;
-      break;
-    case kCondUlt:
-      slt_op = kMips64Sltu;
-      br_op = kMips64Bnez;
-      break;
-    case kCondUge:
-      slt_op = kMips64Sltu;
-      br_op = kMips64Beqz;
-      break;
-    case kCondGe:
-      slt_op = kMips64Slt;
-      br_op = kMips64Beqz;
-      break;
-    case kCondGt:
-      slt_op = kMips64Slt;
-      br_op = kMips64Bnez;
-      swapped = true;
-      break;
-    case kCondLe:
-      slt_op = kMips64Slt;
-      br_op = kMips64Beqz;
-      swapped = true;
-      break;
-    case kCondLt:
-      slt_op = kMips64Slt;
-      br_op = kMips64Bnez;
-      break;
-    case kCondHi:  // Gtu
-      slt_op = kMips64Sltu;
-      br_op = kMips64Bnez;
-      swapped = true;
-      break;
-    default:
-      LOG(FATAL) << "No support for ConditionCode: " << cond;
-      return NULL;
-  }
-  if (cmp_zero) {
-    branch = NewLIR2(br_op, src1.GetReg(), src2.GetReg());
-  } else {
-    RegStorage t_reg = AllocTemp();
-    if (swapped) {
-      NewLIR3(slt_op, t_reg.GetReg(), src2.GetReg(), src1.GetReg());
-    } else {
-      NewLIR3(slt_op, t_reg.GetReg(), src1.GetReg(), src2.GetReg());
-    }
-    branch = NewLIR1(br_op, t_reg.GetReg());
-    FreeTemp(t_reg);
-  }
-  branch->target = target;
-  return branch;
-}
-
-LIR* Mips64Mir2Lir::OpCmpImmBranch(ConditionCode cond, RegStorage reg,
-                                   int check_value, LIR* target) {
-  LIR* branch;
-  if (check_value != 0) {
-    // TUNING: handle s16 & kCondLt/Mi case using slti.
-    RegStorage t_reg = AllocTemp();
-    LoadConstant(t_reg, check_value);
-    branch = OpCmpBranch(cond, reg, t_reg, target);
-    FreeTemp(t_reg);
-    return branch;
-  }
-  Mips64OpCode opc;
-  switch (cond) {
-    case kCondEq: opc = kMips64Beqz; break;
-    case kCondGe: opc = kMips64Bgez; break;
-    case kCondGt: opc = kMips64Bgtz; break;
-    case kCondLe: opc = kMips64Blez; break;
-    // case KCondMi:
-    case kCondLt: opc = kMips64Bltz; break;
-    case kCondNe: opc = kMips64Bnez; break;
-    default:
-      // Tuning: use slti when applicable.
-      RegStorage t_reg = AllocTemp();
-      LoadConstant(t_reg, check_value);
-      branch = OpCmpBranch(cond, reg, t_reg, target);
-      FreeTemp(t_reg);
-      return branch;
-  }
-  branch = NewLIR1(opc, reg.GetReg());
-  branch->target = target;
-  return branch;
-}
-
-LIR* Mips64Mir2Lir::OpRegCopyNoInsert(RegStorage r_dest, RegStorage r_src) {
-  DCHECK(!r_dest.IsPair() && !r_src.IsPair());
-  if (r_dest.IsFloat() || r_src.IsFloat())
-    return OpFpRegCopy(r_dest, r_src);
-  // TODO: Check that r_src and r_dest are both 32 or both 64 bits length.
-  LIR* res;
-  if (r_dest.Is64Bit() || r_src.Is64Bit()) {
-    res = RawLIR(current_dalvik_offset_, kMips64Move, r_dest.GetReg(), r_src.GetReg());
-  } else {
-    res = RawLIR(current_dalvik_offset_, kMips64Sll, r_dest.GetReg(), r_src.GetReg(), 0);
-  }
-  if (!(cu_->disable_opt & (1 << kSafeOptimizations)) && r_dest == r_src) {
-    res->flags.is_nop = true;
-  }
-  return res;
-}
-
-void Mips64Mir2Lir::OpRegCopy(RegStorage r_dest, RegStorage r_src) {
-  if (r_dest != r_src) {
-    LIR *res = OpRegCopyNoInsert(r_dest, r_src);
-    AppendLIR(res);
-  }
-}
-
-void Mips64Mir2Lir::OpRegCopyWide(RegStorage r_dest, RegStorage r_src) {
-  OpRegCopy(r_dest, r_src);
-}
-
-void Mips64Mir2Lir::GenSelectConst32(RegStorage left_op, RegStorage right_op, ConditionCode code,
-                                     int32_t true_val, int32_t false_val, RegStorage rs_dest,
-                                     RegisterClass dest_reg_class) {
-  UNUSED(dest_reg_class);
-  // Implement as a branch-over.
-  // TODO: Conditional move?
-  LoadConstant(rs_dest, true_val);
-  LIR* ne_branchover = OpCmpBranch(code, left_op, right_op, NULL);
-  LoadConstant(rs_dest, false_val);
-  LIR* target_label = NewLIR0(kPseudoTargetLabel);
-  ne_branchover->target = target_label;
-}
-
-void Mips64Mir2Lir::GenSelect(BasicBlock* bb, MIR* mir) {
-  UNUSED(bb, mir);
-  UNIMPLEMENTED(FATAL) << "Need codegen for select";
-}
-
-void Mips64Mir2Lir::GenFusedLongCmpBranch(BasicBlock* bb, MIR* mir) {
-  UNUSED(bb, mir);
-  UNIMPLEMENTED(FATAL) << "Need codegen for fused long cmp branch";
-}
-
-RegLocation Mips64Mir2Lir::GenDivRem(RegLocation rl_dest, RegStorage reg1, RegStorage reg2,
-                                     bool is_div) {
-  RegLocation rl_result = EvalLoc(rl_dest, kCoreReg, true);
-  NewLIR3(is_div ? kMips64Div : kMips64Mod, rl_result.reg.GetReg(), reg1.GetReg(), reg2.GetReg());
-  return rl_result;
-}
-
-RegLocation Mips64Mir2Lir::GenDivRemLit(RegLocation rl_dest, RegStorage reg1, int lit,
-                                        bool is_div) {
-  RegStorage t_reg = AllocTemp();
-  NewLIR3(kMips64Addiu, t_reg.GetReg(), rZERO, lit);
-  RegLocation rl_result = EvalLoc(rl_dest, kCoreReg, true);
-  NewLIR3(is_div ? kMips64Div : kMips64Mod, rl_result.reg.GetReg(), reg1.GetReg(), t_reg.GetReg());
-  FreeTemp(t_reg);
-  return rl_result;
-}
-
-RegLocation Mips64Mir2Lir::GenDivRem(RegLocation rl_dest, RegLocation rl_src1, RegLocation rl_src2,
-                                     bool is_div, int flags) {
-  UNUSED(rl_dest, rl_src1, rl_src2, is_div, flags);
-  LOG(FATAL) << "Unexpected use of GenDivRem for Mips64";
-  UNREACHABLE();
-}
-
-RegLocation Mips64Mir2Lir::GenDivRemLit(RegLocation rl_dest, RegLocation rl_src1, int lit,
-                                        bool is_div) {
-  UNUSED(rl_dest, rl_src1, lit, is_div);
-  LOG(FATAL) << "Unexpected use of GenDivRemLit for Mips64";
-  UNREACHABLE();
-}
-
-bool Mips64Mir2Lir::GenInlinedCas(CallInfo* info, bool is_long, bool is_object) {
-  UNUSED(info, is_long, is_object);
-  return false;
-}
-
-bool Mips64Mir2Lir::GenInlinedAbsFloat(CallInfo* info) {
-  UNUSED(info);
-  // TODO: add Mips64 implementation.
-  return false;
-}
-
-bool Mips64Mir2Lir::GenInlinedAbsDouble(CallInfo* info) {
-  UNUSED(info);
-  // TODO: add Mips64 implementation.
-  return false;
-}
-
-bool Mips64Mir2Lir::GenInlinedSqrt(CallInfo* info) {
-  UNUSED(info);
-  return false;
-}
-
-bool Mips64Mir2Lir::GenInlinedPeek(CallInfo* info, OpSize size) {
-  if (size != kSignedByte) {
-    // MIPS64 supports only aligned access. Defer unaligned access to JNI implementation.
-    return false;
-  }
-  RegLocation rl_src_address = info->args[0];     // Long address.
-  RegLocation rl_dest = InlineTarget(info);
-  RegLocation rl_address = LoadValueWide(rl_src_address, kCoreReg);
-  RegLocation rl_result = EvalLoc(rl_dest, kCoreReg, true);
-  DCHECK(size == kSignedByte);
-  LoadBaseDisp(rl_address.reg, 0, rl_result.reg, size, kNotVolatile);
-  StoreValue(rl_dest, rl_result);
-  return true;
-}
-
-bool Mips64Mir2Lir::GenInlinedPoke(CallInfo* info, OpSize size) {
-  if (size != kSignedByte) {
-    // MIPS64 supports only aligned access. Defer unaligned access to JNI implementation.
-    return false;
-  }
-  RegLocation rl_src_address = info->args[0];     // Long address.
-  RegLocation rl_src_value = info->args[2];       // [size] value.
-  RegLocation rl_address = LoadValueWide(rl_src_address, kCoreReg);
-  DCHECK(size == kSignedByte);
-  RegLocation rl_value = LoadValue(rl_src_value, kCoreReg);
-  StoreBaseDisp(rl_address.reg, 0, rl_value.reg, size, kNotVolatile);
-  return true;
-}
-
-void Mips64Mir2Lir::OpPcRelLoad(RegStorage reg, LIR* target) {
-  UNUSED(reg, target);
-  LOG(FATAL) << "Unexpected use of OpPcRelLoad for Mips64";
-  UNREACHABLE();
-}
-
-LIR* Mips64Mir2Lir::OpVldm(RegStorage r_base, int count) {
-  UNUSED(r_base, count);
-  LOG(FATAL) << "Unexpected use of OpVldm for Mips64";
-  UNREACHABLE();
-}
-
-LIR* Mips64Mir2Lir::OpVstm(RegStorage r_base, int count) {
-  UNUSED(r_base, count);
-  LOG(FATAL) << "Unexpected use of OpVstm for Mips64";
-  UNREACHABLE();
-}
-
-void Mips64Mir2Lir::GenMultiplyByTwoBitMultiplier(RegLocation rl_src, RegLocation rl_result,
-                                                  int lit, int first_bit, int second_bit) {
-  UNUSED(lit);
-  RegStorage t_reg = AllocTemp();
-  OpRegRegImm(kOpLsl, t_reg, rl_src.reg, second_bit - first_bit);
-  OpRegRegReg(kOpAdd, rl_result.reg, rl_src.reg, t_reg);
-  FreeTemp(t_reg);
-  if (first_bit != 0) {
-    OpRegRegImm(kOpLsl, rl_result.reg, rl_result.reg, first_bit);
-  }
-}
-
-void Mips64Mir2Lir::GenDivZeroCheckWide(RegStorage reg) {
-  GenDivZeroCheck(reg);
-}
-
-// Test suspend flag, return target of taken suspend branch.
-LIR* Mips64Mir2Lir::OpTestSuspend(LIR* target) {
-  OpRegImm(kOpSub, rs_rMIPS64_SUSPEND, 1);
-  return OpCmpImmBranch((target == NULL) ? kCondEq : kCondNe, rs_rMIPS64_SUSPEND, 0, target);
-}
-
-// Decrement register and branch on condition.
-LIR* Mips64Mir2Lir::OpDecAndBranch(ConditionCode c_code, RegStorage reg, LIR* target) {
-  OpRegImm(kOpSub, reg, 1);
-  return OpCmpImmBranch(c_code, reg, 0, target);
-}
-
-bool Mips64Mir2Lir::SmallLiteralDivRem(Instruction::Code dalvik_opcode, bool is_div,
-                                       RegLocation rl_src, RegLocation rl_dest, int lit) {
-  UNUSED(dalvik_opcode, is_div, rl_src, rl_dest, lit);
-  LOG(FATAL) << "Unexpected use of smallLiteralDive in Mips64";
-  UNREACHABLE();
-}
-
-bool Mips64Mir2Lir::EasyMultiply(RegLocation rl_src, RegLocation rl_dest, int lit) {
-  UNUSED(rl_src, rl_dest, lit);
-  LOG(FATAL) << "Unexpected use of easyMultiply in Mips64";
-  UNREACHABLE();
-}
-
-LIR* Mips64Mir2Lir::OpIT(ConditionCode cond, const char* guide) {
-  UNUSED(cond, guide);
-  LOG(FATAL) << "Unexpected use of OpIT in Mips64";
-  UNREACHABLE();
-}
-
-void Mips64Mir2Lir::OpEndIT(LIR* it) {
-  UNUSED(it);
-  LOG(FATAL) << "Unexpected use of OpEndIT in Mips64";
-}
-
-void Mips64Mir2Lir::GenArithOpLong(Instruction::Code opcode, RegLocation rl_dest,
-                                   RegLocation rl_src1, RegLocation rl_src2, int flags) {
-  switch (opcode) {
-    case Instruction::NOT_LONG:
-      GenNotLong(rl_dest, rl_src2);
-      return;
-    case Instruction::ADD_LONG:
-    case Instruction::ADD_LONG_2ADDR:
-      GenLongOp(kOpAdd, rl_dest, rl_src1, rl_src2);
-      return;
-    case Instruction::SUB_LONG:
-    case Instruction::SUB_LONG_2ADDR:
-      GenLongOp(kOpSub, rl_dest, rl_src1, rl_src2);
-      return;
-    case Instruction::MUL_LONG:
-    case Instruction::MUL_LONG_2ADDR:
-      GenMulLong(rl_dest, rl_src1, rl_src2);
-      return;
-    case Instruction::DIV_LONG:
-    case Instruction::DIV_LONG_2ADDR:
-      GenDivRemLong(opcode, rl_dest, rl_src1, rl_src2, /*is_div*/ true, flags);
-      return;
-    case Instruction::REM_LONG:
-    case Instruction::REM_LONG_2ADDR:
-      GenDivRemLong(opcode, rl_dest, rl_src1, rl_src2, /*is_div*/ false, flags);
-      return;
-    case Instruction::AND_LONG:
-    case Instruction::AND_LONG_2ADDR:
-      GenLongOp(kOpAnd, rl_dest, rl_src1, rl_src2);
-      return;
-    case Instruction::OR_LONG:
-    case Instruction::OR_LONG_2ADDR:
-      GenLongOp(kOpOr, rl_dest, rl_src1, rl_src2);
-      return;
-    case Instruction::XOR_LONG:
-    case Instruction::XOR_LONG_2ADDR:
-      GenLongOp(kOpXor, rl_dest, rl_src1, rl_src2);
-      return;
-    case Instruction::NEG_LONG:
-      GenNegLong(rl_dest, rl_src2);
-      return;
-
-    default:
-      LOG(FATAL) << "Invalid long arith op";
-      return;
-  }
-}
-
-void Mips64Mir2Lir::GenLongOp(OpKind op, RegLocation rl_dest, RegLocation rl_src1,
-                              RegLocation rl_src2) {
-  rl_src1 = LoadValueWide(rl_src1, kCoreReg);
-  rl_src2 = LoadValueWide(rl_src2, kCoreReg);
-  RegLocation rl_result = EvalLocWide(rl_dest, kCoreReg, true);
-  OpRegRegReg(op, rl_result.reg, rl_src1.reg, rl_src2.reg);
-  StoreValueWide(rl_dest, rl_result);
-}
-
-void Mips64Mir2Lir::GenNotLong(RegLocation rl_dest, RegLocation rl_src) {
-  rl_src = LoadValueWide(rl_src, kCoreReg);
-  RegLocation rl_result = EvalLocWide(rl_dest, kCoreReg, true);
-  OpRegReg(kOpMvn, rl_result.reg, rl_src.reg);
-  StoreValueWide(rl_dest, rl_result);
-}
-
-void Mips64Mir2Lir::GenNegLong(RegLocation rl_dest, RegLocation rl_src) {
-  rl_src = LoadValueWide(rl_src, kCoreReg);
-  RegLocation rl_result = EvalLocWide(rl_dest, kCoreReg, true);
-  OpRegReg(kOpNeg, rl_result.reg, rl_src.reg);
-  StoreValueWide(rl_dest, rl_result);
-}
-
-void Mips64Mir2Lir::GenMulLong(RegLocation rl_dest, RegLocation rl_src1, RegLocation rl_src2) {
-  rl_src1 = LoadValueWide(rl_src1, kCoreReg);
-  rl_src2 = LoadValueWide(rl_src2, kCoreReg);
-  RegLocation rl_result = EvalLocWide(rl_dest, kCoreReg, true);
-  NewLIR3(kMips64Dmul, rl_result.reg.GetReg(), rl_src1.reg.GetReg(), rl_src2.reg.GetReg());
-  StoreValueWide(rl_dest, rl_result);
-}
-
-void Mips64Mir2Lir::GenDivRemLong(Instruction::Code opcode, RegLocation rl_dest,
-                                  RegLocation rl_src1, RegLocation rl_src2, bool is_div,
-                                  int flags) {
-  UNUSED(opcode);
-  // TODO: Implement easy div/rem?
-  rl_src1 = LoadValueWide(rl_src1, kCoreReg);
-  rl_src2 = LoadValueWide(rl_src2, kCoreReg);
-  if ((flags & MIR_IGNORE_DIV_ZERO_CHECK) == 0) {
-    GenDivZeroCheckWide(rl_src2.reg);
-  }
-  RegLocation rl_result = EvalLocWide(rl_dest, kCoreReg, true);
-  NewLIR3(is_div ? kMips64Ddiv : kMips64Dmod, rl_result.reg.GetReg(), rl_src1.reg.GetReg(),
-          rl_src2.reg.GetReg());
-  StoreValueWide(rl_dest, rl_result);
-}
-
-/*
- * Generate array load
- */
-void Mips64Mir2Lir::GenArrayGet(int opt_flags, OpSize size, RegLocation rl_array,
-                                RegLocation rl_index, RegLocation rl_dest, int scale) {
-  RegisterClass reg_class = RegClassBySize(size);
-  int len_offset = mirror::Array::LengthOffset().Int32Value();
-  int data_offset;
-  RegLocation rl_result;
-  rl_array = LoadValue(rl_array, kRefReg);
-  rl_index = LoadValue(rl_index, kCoreReg);
-
-  // FIXME: need to add support for rl_index.is_const.
-
-  if (size == k64 || size == kDouble) {
-    data_offset = mirror::Array::DataOffset(sizeof(int64_t)).Int32Value();
-  } else {
-    data_offset = mirror::Array::DataOffset(sizeof(int32_t)).Int32Value();
-  }
-
-  // Null object?
-  GenNullCheck(rl_array.reg, opt_flags);
-
-  RegStorage reg_ptr = AllocTempRef();
-  bool needs_range_check = (!(opt_flags & MIR_IGNORE_RANGE_CHECK));
-  RegStorage reg_len;
-  if (needs_range_check) {
-    reg_len = AllocTemp();
-    // Get len.
-    Load32Disp(rl_array.reg, len_offset, reg_len);
-  }
-  // reg_ptr -> array data.
-  OpRegRegImm(kOpAdd, reg_ptr, rl_array.reg, data_offset);
-  FreeTemp(rl_array.reg);
-  if ((size == k64) || (size == kDouble)) {
-    if (scale) {
-      RegStorage r_new_index = AllocTemp();
-      OpRegRegImm(kOpLsl, r_new_index, rl_index.reg, scale);
-      OpRegReg(kOpAdd, reg_ptr, r_new_index);
-      FreeTemp(r_new_index);
-    } else {
-      OpRegReg(kOpAdd, reg_ptr, rl_index.reg);
-    }
-    FreeTemp(rl_index.reg);
-    rl_result = EvalLoc(rl_dest, reg_class, true);
-
-    if (needs_range_check) {
-      GenArrayBoundsCheck(rl_index.reg, reg_len);
-      FreeTemp(reg_len);
-    }
-    LoadBaseDisp(reg_ptr, 0, rl_result.reg, size, kNotVolatile);
-
-    FreeTemp(reg_ptr);
-    StoreValueWide(rl_dest, rl_result);
-  } else {
-    rl_result = EvalLoc(rl_dest, reg_class, true);
-
-    if (needs_range_check) {
-      GenArrayBoundsCheck(rl_index.reg, reg_len);
-      FreeTemp(reg_len);
-    }
-    if (rl_result.ref) {
-      LoadBaseIndexed(reg_ptr, As64BitReg(rl_index.reg), As32BitReg(rl_result.reg), scale,
-                      kReference);
-    } else {
-      LoadBaseIndexed(reg_ptr, As64BitReg(rl_index.reg), rl_result.reg, scale, size);
-    }
-
-    FreeTemp(reg_ptr);
-    StoreValue(rl_dest, rl_result);
-  }
-}
-
-/*
- * Generate array store
- *
- */
-void Mips64Mir2Lir::GenArrayPut(int opt_flags, OpSize size, RegLocation rl_array,
-                                RegLocation rl_index, RegLocation rl_src, int scale,
-                                bool card_mark) {
-  RegisterClass reg_class = RegClassBySize(size);
-  int len_offset = mirror::Array::LengthOffset().Int32Value();
-  int data_offset;
-
-  if (size == k64 || size == kDouble) {
-    data_offset = mirror::Array::DataOffset(sizeof(int64_t)).Int32Value();
-  } else {
-    data_offset = mirror::Array::DataOffset(sizeof(int32_t)).Int32Value();
-  }
-
-  rl_array = LoadValue(rl_array, kRefReg);
-  rl_index = LoadValue(rl_index, kCoreReg);
-
-  // FIXME: need to add support for rl_index.is_const.
-
-  RegStorage reg_ptr;
-  bool allocated_reg_ptr_temp = false;
-  if (IsTemp(rl_array.reg) && !card_mark) {
-    Clobber(rl_array.reg);
-    reg_ptr = rl_array.reg;
-  } else {
-    reg_ptr = AllocTemp();
-    OpRegCopy(reg_ptr, rl_array.reg);
-    allocated_reg_ptr_temp = true;
-  }
-
-  // Null object?
-  GenNullCheck(rl_array.reg, opt_flags);
-
-  bool needs_range_check = (!(opt_flags & MIR_IGNORE_RANGE_CHECK));
-  RegStorage reg_len;
-  if (needs_range_check) {
-    reg_len = AllocTemp();
-    // NOTE: max live temps(4) here.
-    // Get len.
-    Load32Disp(rl_array.reg, len_offset, reg_len);
-  }
-  // reg_ptr -> array data.
-  OpRegImm(kOpAdd, reg_ptr, data_offset);
-  // At this point, reg_ptr points to array, 2 live temps.
-  if ((size == k64) || (size == kDouble)) {
-    // TUNING: specific wide routine that can handle fp regs.
-    if (scale) {
-      RegStorage r_new_index = AllocTemp();
-      OpRegRegImm(kOpLsl, r_new_index, rl_index.reg, scale);
-      OpRegReg(kOpAdd, reg_ptr, r_new_index);
-      FreeTemp(r_new_index);
-    } else {
-      OpRegReg(kOpAdd, reg_ptr, rl_index.reg);
-    }
-    rl_src = LoadValueWide(rl_src, reg_class);
-
-    if (needs_range_check) {
-      GenArrayBoundsCheck(rl_index.reg, reg_len);
-      FreeTemp(reg_len);
-    }
-
-    StoreBaseDisp(reg_ptr, 0, rl_src.reg, size, kNotVolatile);
-  } else {
-    rl_src = LoadValue(rl_src, reg_class);
-    if (needs_range_check) {
-      GenArrayBoundsCheck(rl_index.reg, reg_len);
-      FreeTemp(reg_len);
-    }
-    StoreBaseIndexed(reg_ptr, rl_index.reg, rl_src.reg, scale, size);
-  }
-  if (allocated_reg_ptr_temp) {
-    FreeTemp(reg_ptr);
-  }
-  if (card_mark) {
-    MarkGCCard(opt_flags, rl_src.reg, rl_array.reg);
-  }
-}
-
-void Mips64Mir2Lir::GenShiftOpLong(Instruction::Code opcode, RegLocation rl_dest,
-                                   RegLocation rl_src1, RegLocation rl_shift) {
-  OpKind op = kOpBkpt;
-  switch (opcode) {
-  case Instruction::SHL_LONG:
-  case Instruction::SHL_LONG_2ADDR:
-    op = kOpLsl;
-    break;
-  case Instruction::SHR_LONG:
-  case Instruction::SHR_LONG_2ADDR:
-    op = kOpAsr;
-    break;
-  case Instruction::USHR_LONG:
-  case Instruction::USHR_LONG_2ADDR:
-    op = kOpLsr;
-    break;
-  default:
-    LOG(FATAL) << "Unexpected case: " << opcode;
-  }
-  rl_shift = LoadValue(rl_shift, kCoreReg);
-  rl_src1 = LoadValueWide(rl_src1, kCoreReg);
-  RegLocation rl_result = EvalLocWide(rl_dest, kCoreReg, true);
-  OpRegRegReg(op, rl_result.reg, rl_src1.reg, As64BitReg(rl_shift.reg));
-  StoreValueWide(rl_dest, rl_result);
-}
-
-void Mips64Mir2Lir::GenShiftImmOpLong(Instruction::Code opcode, RegLocation rl_dest,
-                                      RegLocation rl_src1, RegLocation rl_shift, int flags) {
-  UNUSED(flags);
-  OpKind op = kOpBkpt;
-  // Per spec, we only care about low 6 bits of shift amount.
-  int shift_amount = mir_graph_->ConstantValue(rl_shift) & 0x3f;
-  rl_src1 = LoadValueWide(rl_src1, kCoreReg);
-  if (shift_amount == 0) {
-    StoreValueWide(rl_dest, rl_src1);
-    return;
-  }
-
-  RegLocation rl_result = EvalLocWide(rl_dest, kCoreReg, true);
-  switch (opcode) {
-    case Instruction::SHL_LONG:
-    case Instruction::SHL_LONG_2ADDR:
-      op = kOpLsl;
-      break;
-    case Instruction::SHR_LONG:
-    case Instruction::SHR_LONG_2ADDR:
-      op = kOpAsr;
-      break;
-    case Instruction::USHR_LONG:
-    case Instruction::USHR_LONG_2ADDR:
-      op = kOpLsr;
-      break;
-    default:
-      LOG(FATAL) << "Unexpected case";
-  }
-  OpRegRegImm(op, rl_result.reg, rl_src1.reg, shift_amount);
-  StoreValueWide(rl_dest, rl_result);
-}
-
-void Mips64Mir2Lir::GenArithImmOpLong(Instruction::Code opcode, RegLocation rl_dest,
-                                      RegLocation rl_src1, RegLocation rl_src2, int flags) {
-  // Default - bail to non-const handler.
-  GenArithOpLong(opcode, rl_dest, rl_src1, rl_src2, flags);
-}
-
-void Mips64Mir2Lir::GenIntToLong(RegLocation rl_dest, RegLocation rl_src) {
-  rl_src = LoadValue(rl_src, kCoreReg);
-  RegLocation rl_result = EvalLocWide(rl_dest, kCoreReg, true);
-  NewLIR3(kMips64Sll, rl_result.reg.GetReg(), As64BitReg(rl_src.reg).GetReg(), 0);
-  StoreValueWide(rl_dest, rl_result);
-}
-
-void Mips64Mir2Lir::GenConversionCall(QuickEntrypointEnum trampoline, RegLocation rl_dest,
-                                      RegLocation rl_src, RegisterClass reg_class) {
-  FlushAllRegs();   // Send everything to home location.
-  CallRuntimeHelperRegLocation(trampoline, rl_src, false);
-  if (rl_dest.wide) {
-    RegLocation rl_result;
-    rl_result = GetReturnWide(reg_class);
-    StoreValueWide(rl_dest, rl_result);
-  } else {
-    RegLocation rl_result;
-    rl_result = GetReturn(reg_class);
-    StoreValue(rl_dest, rl_result);
-  }
-}
-
-}  // namespace art
diff --git a/compiler/dex/quick/mips64/mips64_lir.h b/compiler/dex/quick/mips64/mips64_lir.h
deleted file mode 100644
index 4a5c5ce..0000000
--- a/compiler/dex/quick/mips64/mips64_lir.h
+++ /dev/null
@@ -1,648 +0,0 @@
-/*
- * Copyright (C) 2015 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.
- */
-
-#ifndef ART_COMPILER_DEX_QUICK_MIPS64_MIPS64_LIR_H_
-#define ART_COMPILER_DEX_QUICK_MIPS64_MIPS64_LIR_H_
-
-#include "dex/reg_location.h"
-#include "dex/reg_storage.h"
-
-namespace art {
-
-/*
- * Runtime register conventions.
- *
- * zero is always the value 0
- * at is scratch (normally used as temp reg by assembler)
- * v0, v1 are scratch (normally hold subroutine return values)
- * a0-a7 are scratch (normally hold subroutine arguments)
- * t0-t3, t8 are scratch
- * t9 is scratch (normally used for function calls)
- * s0 (rMIPS_SUSPEND) is reserved [holds suspend-check counter]
- * s1 (rMIPS_SELF) is reserved [holds current &Thread]
- * s2-s7 are callee save (promotion target)
- * k0, k1 are reserved for use by interrupt handlers
- * gp is reserved for global pointer
- * sp is reserved
- * s8 is callee save (promotion target)
- * ra is scratch (normally holds the return addr)
- *
- * Preserved across C calls: s0-s8
- * Trashed across C calls: at, v0-v1, a0-a7, t0-t3, t8-t9, gp, ra
- *
- * Floating pointer registers
- * NOTE: there are 32 fp registers.
- * f0-f31
- *
- * f0-f31 trashed across C calls
- *
- * For mips64 code use:
- *      a0-a7 to hold operands
- *      v0-v1 to hold results
- *      t0-t3, t8-t9 for temps
- *
- * All jump/branch instructions have a delay slot after it.
- *
- *  Stack frame diagram (stack grows down, higher addresses at top):
- *
- * +------------------------+
- * | IN[ins-1]              |  {Note: resides in caller's frame}
- * |       .                |
- * | IN[0]                  |
- * | caller's Method*       |
- * +========================+  {Note: start of callee's frame}
- * | spill region           |  {variable sized - will include lr if non-leaf.}
- * +------------------------+
- * | ...filler word...      |  {Note: used as 2nd word of V[locals-1] if long]
- * +------------------------+
- * | V[locals-1]            |
- * | V[locals-2]            |
- * |      .                 |
- * |      .                 |
- * | V[1]                   |
- * | V[0]                   |
- * +------------------------+
- * |  0 to 3 words padding  |
- * +------------------------+
- * | OUT[outs-1]            |
- * | OUT[outs-2]            |
- * |       .                |
- * | OUT[0]                 |
- * | cur_method*            | <<== sp w/ 16-byte alignment
- * +========================+
- */
-
-
-#define rARG0 rA0d
-#define rs_rARG0 rs_rA0d
-#define rARG1 rA1d
-#define rs_rARG1 rs_rA1d
-#define rARG2 rA2d
-#define rs_rARG2 rs_rA2d
-#define rARG3 rA3d
-#define rs_rARG3 rs_rA3d
-#define rARG4 rA4d
-#define rs_rARG4 rs_rA4d
-#define rARG5 rA5d
-#define rs_rARG5 rs_rA5d
-#define rARG6 rA6d
-#define rs_rARG6 rs_rA6d
-#define rARG7 rA7d
-#define rs_rARG7 rs_rA7d
-#define rRESULT0 rV0d
-#define rs_rRESULT0 rs_rV0d
-#define rRESULT1 rV1d
-#define rs_rRESULT1 rs_rV1d
-
-#define rFARG0 rF12
-#define rs_rFARG0 rs_rF12
-#define rFARG1 rF13
-#define rs_rFARG1 rs_rF13
-#define rFARG2 rF14
-#define rs_rFARG2 rs_rF14
-#define rFARG3 rF15
-#define rs_rFARG3 rs_rF15
-#define rFARG4 rF16
-#define rs_rFARG4 rs_rF16
-#define rFARG5 rF17
-#define rs_rFARG5 rs_rF17
-#define rFARG6 rF18
-#define rs_rFARG6 rs_rF18
-#define rFARG7 rF19
-#define rs_rFARG7 rs_rF19
-#define rFRESULT0 rF0
-#define rs_rFRESULT0 rs_rF0
-#define rFRESULT1 rF1
-#define rs_rFRESULT1 rs_rF1
-
-// Regs not used for Mips64.
-#define rMIPS64_LR RegStorage::kInvalidRegVal
-#define rMIPS64_PC RegStorage::kInvalidRegVal
-
-enum Mips64ResourceEncodingPos {
-  kMips64GPReg0   = 0,
-  kMips64RegSP    = 29,
-  kMips64RegLR    = 31,
-  kMips64FPReg0   = 32,
-  kMips64FPRegEnd = 64,
-  kMips64RegPC    = kMips64FPRegEnd,
-  kMips64RegEnd   = 65,
-};
-
-enum Mips64NativeRegisterPool {  // private marker to avoid generate-operator-out.py from processing.
-  rZERO  = RegStorage::k32BitSolo | RegStorage::kCoreRegister |  0,
-  rZEROd = RegStorage::k64BitSolo | RegStorage::kCoreRegister |  0,
-  rAT    = RegStorage::k32BitSolo | RegStorage::kCoreRegister |  1,
-  rATd   = RegStorage::k64BitSolo | RegStorage::kCoreRegister |  1,
-  rV0    = RegStorage::k32BitSolo | RegStorage::kCoreRegister |  2,
-  rV0d   = RegStorage::k64BitSolo | RegStorage::kCoreRegister |  2,
-  rV1    = RegStorage::k32BitSolo | RegStorage::kCoreRegister |  3,
-  rV1d   = RegStorage::k64BitSolo | RegStorage::kCoreRegister |  3,
-  rA0    = RegStorage::k32BitSolo | RegStorage::kCoreRegister |  4,
-  rA0d   = RegStorage::k64BitSolo | RegStorage::kCoreRegister |  4,
-  rA1    = RegStorage::k32BitSolo | RegStorage::kCoreRegister |  5,
-  rA1d   = RegStorage::k64BitSolo | RegStorage::kCoreRegister |  5,
-  rA2    = RegStorage::k32BitSolo | RegStorage::kCoreRegister |  6,
-  rA2d   = RegStorage::k64BitSolo | RegStorage::kCoreRegister |  6,
-  rA3    = RegStorage::k32BitSolo | RegStorage::kCoreRegister |  7,
-  rA3d   = RegStorage::k64BitSolo | RegStorage::kCoreRegister |  7,
-  rA4    = RegStorage::k32BitSolo | RegStorage::kCoreRegister |  8,
-  rA4d   = RegStorage::k64BitSolo | RegStorage::kCoreRegister |  8,
-  rA5    = RegStorage::k32BitSolo | RegStorage::kCoreRegister |  9,
-  rA5d   = RegStorage::k64BitSolo | RegStorage::kCoreRegister |  9,
-  rA6    = RegStorage::k32BitSolo | RegStorage::kCoreRegister | 10,
-  rA6d   = RegStorage::k64BitSolo | RegStorage::kCoreRegister | 10,
-  rA7    = RegStorage::k32BitSolo | RegStorage::kCoreRegister | 11,
-  rA7d   = RegStorage::k64BitSolo | RegStorage::kCoreRegister | 11,
-  rT0    = RegStorage::k32BitSolo | RegStorage::kCoreRegister | 12,
-  rT0d   = RegStorage::k64BitSolo | RegStorage::kCoreRegister | 12,
-  rT1    = RegStorage::k32BitSolo | RegStorage::kCoreRegister | 13,
-  rT1d   = RegStorage::k64BitSolo | RegStorage::kCoreRegister | 13,
-  rT2    = RegStorage::k32BitSolo | RegStorage::kCoreRegister | 14,
-  rT2d   = RegStorage::k64BitSolo | RegStorage::kCoreRegister | 14,
-  rT3    = RegStorage::k32BitSolo | RegStorage::kCoreRegister | 15,
-  rT3d   = RegStorage::k64BitSolo | RegStorage::kCoreRegister | 15,
-  rS0    = RegStorage::k32BitSolo | RegStorage::kCoreRegister | 16,
-  rS0d   = RegStorage::k64BitSolo | RegStorage::kCoreRegister | 16,
-  rS1    = RegStorage::k32BitSolo | RegStorage::kCoreRegister | 17,
-  rS1d   = RegStorage::k64BitSolo | RegStorage::kCoreRegister | 17,
-  rS2    = RegStorage::k32BitSolo | RegStorage::kCoreRegister | 18,
-  rS2d   = RegStorage::k64BitSolo | RegStorage::kCoreRegister | 18,
-  rS3    = RegStorage::k32BitSolo | RegStorage::kCoreRegister | 19,
-  rS3d   = RegStorage::k64BitSolo | RegStorage::kCoreRegister | 19,
-  rS4    = RegStorage::k32BitSolo | RegStorage::kCoreRegister | 20,
-  rS4d   = RegStorage::k64BitSolo | RegStorage::kCoreRegister | 20,
-  rS5    = RegStorage::k32BitSolo | RegStorage::kCoreRegister | 21,
-  rS5d   = RegStorage::k64BitSolo | RegStorage::kCoreRegister | 21,
-  rS6    = RegStorage::k32BitSolo | RegStorage::kCoreRegister | 22,
-  rS6d   = RegStorage::k64BitSolo | RegStorage::kCoreRegister | 22,
-  rS7    = RegStorage::k32BitSolo | RegStorage::kCoreRegister | 23,
-  rS7d   = RegStorage::k64BitSolo | RegStorage::kCoreRegister | 23,
-  rT8    = RegStorage::k32BitSolo | RegStorage::kCoreRegister | 24,
-  rT8d   = RegStorage::k64BitSolo | RegStorage::kCoreRegister | 24,
-  rT9    = RegStorage::k32BitSolo | RegStorage::kCoreRegister | 25,
-  rT9d   = RegStorage::k64BitSolo | RegStorage::kCoreRegister | 25,
-  rK0    = RegStorage::k32BitSolo | RegStorage::kCoreRegister | 26,
-  rK0d   = RegStorage::k64BitSolo | RegStorage::kCoreRegister | 26,
-  rK1    = RegStorage::k32BitSolo | RegStorage::kCoreRegister | 27,
-  rK1d   = RegStorage::k64BitSolo | RegStorage::kCoreRegister | 27,
-  rGP    = RegStorage::k32BitSolo | RegStorage::kCoreRegister | 28,
-  rGPd   = RegStorage::k64BitSolo | RegStorage::kCoreRegister | 28,
-  rSP    = RegStorage::k32BitSolo | RegStorage::kCoreRegister | 29,
-  rSPd   = RegStorage::k64BitSolo | RegStorage::kCoreRegister | 29,
-  rFP    = RegStorage::k32BitSolo | RegStorage::kCoreRegister | 30,
-  rFPd   = RegStorage::k64BitSolo | RegStorage::kCoreRegister | 30,
-  rRA    = RegStorage::k32BitSolo | RegStorage::kCoreRegister | 31,
-  rRAd   = RegStorage::k64BitSolo | RegStorage::kCoreRegister | 31,
-
-  rF0  = RegStorage::k32BitSolo | RegStorage::kFloatingPoint |  0,
-  rF1  = RegStorage::k32BitSolo | RegStorage::kFloatingPoint |  1,
-  rF2  = RegStorage::k32BitSolo | RegStorage::kFloatingPoint |  2,
-  rF3  = RegStorage::k32BitSolo | RegStorage::kFloatingPoint |  3,
-  rF4  = RegStorage::k32BitSolo | RegStorage::kFloatingPoint |  4,
-  rF5  = RegStorage::k32BitSolo | RegStorage::kFloatingPoint |  5,
-  rF6  = RegStorage::k32BitSolo | RegStorage::kFloatingPoint |  6,
-  rF7  = RegStorage::k32BitSolo | RegStorage::kFloatingPoint |  7,
-  rF8  = RegStorage::k32BitSolo | RegStorage::kFloatingPoint |  8,
-  rF9  = RegStorage::k32BitSolo | RegStorage::kFloatingPoint |  9,
-  rF10 = RegStorage::k32BitSolo | RegStorage::kFloatingPoint | 10,
-  rF11 = RegStorage::k32BitSolo | RegStorage::kFloatingPoint | 11,
-  rF12 = RegStorage::k32BitSolo | RegStorage::kFloatingPoint | 12,
-  rF13 = RegStorage::k32BitSolo | RegStorage::kFloatingPoint | 13,
-  rF14 = RegStorage::k32BitSolo | RegStorage::kFloatingPoint | 14,
-  rF15 = RegStorage::k32BitSolo | RegStorage::kFloatingPoint | 15,
-  rF16 = RegStorage::k32BitSolo | RegStorage::kFloatingPoint | 16,
-  rF17 = RegStorage::k32BitSolo | RegStorage::kFloatingPoint | 17,
-  rF18 = RegStorage::k32BitSolo | RegStorage::kFloatingPoint | 18,
-  rF19 = RegStorage::k32BitSolo | RegStorage::kFloatingPoint | 19,
-  rF20 = RegStorage::k32BitSolo | RegStorage::kFloatingPoint | 20,
-  rF21 = RegStorage::k32BitSolo | RegStorage::kFloatingPoint | 21,
-  rF22 = RegStorage::k32BitSolo | RegStorage::kFloatingPoint | 22,
-  rF23 = RegStorage::k32BitSolo | RegStorage::kFloatingPoint | 23,
-  rF24 = RegStorage::k32BitSolo | RegStorage::kFloatingPoint | 24,
-  rF25 = RegStorage::k32BitSolo | RegStorage::kFloatingPoint | 25,
-  rF26 = RegStorage::k32BitSolo | RegStorage::kFloatingPoint | 26,
-  rF27 = RegStorage::k32BitSolo | RegStorage::kFloatingPoint | 27,
-  rF28 = RegStorage::k32BitSolo | RegStorage::kFloatingPoint | 28,
-  rF29 = RegStorage::k32BitSolo | RegStorage::kFloatingPoint | 29,
-  rF30 = RegStorage::k32BitSolo | RegStorage::kFloatingPoint | 30,
-  rF31 = RegStorage::k32BitSolo | RegStorage::kFloatingPoint | 31,
-
-  rD0  = RegStorage::k64BitSolo | RegStorage::kFloatingPoint |  0,
-  rD1  = RegStorage::k64BitSolo | RegStorage::kFloatingPoint |  1,
-  rD2  = RegStorage::k64BitSolo | RegStorage::kFloatingPoint |  2,
-  rD3  = RegStorage::k64BitSolo | RegStorage::kFloatingPoint |  3,
-  rD4  = RegStorage::k64BitSolo | RegStorage::kFloatingPoint |  4,
-  rD5  = RegStorage::k64BitSolo | RegStorage::kFloatingPoint |  5,
-  rD6  = RegStorage::k64BitSolo | RegStorage::kFloatingPoint |  6,
-  rD7  = RegStorage::k64BitSolo | RegStorage::kFloatingPoint |  7,
-  rD8  = RegStorage::k64BitSolo | RegStorage::kFloatingPoint |  8,
-  rD9  = RegStorage::k64BitSolo | RegStorage::kFloatingPoint |  9,
-  rD10 = RegStorage::k64BitSolo | RegStorage::kFloatingPoint | 10,
-  rD11 = RegStorage::k64BitSolo | RegStorage::kFloatingPoint | 11,
-  rD12 = RegStorage::k64BitSolo | RegStorage::kFloatingPoint | 12,
-  rD13 = RegStorage::k64BitSolo | RegStorage::kFloatingPoint | 13,
-  rD14 = RegStorage::k64BitSolo | RegStorage::kFloatingPoint | 14,
-  rD15 = RegStorage::k64BitSolo | RegStorage::kFloatingPoint | 15,
-  rD16 = RegStorage::k64BitSolo | RegStorage::kFloatingPoint | 16,
-  rD17 = RegStorage::k64BitSolo | RegStorage::kFloatingPoint | 17,
-  rD18 = RegStorage::k64BitSolo | RegStorage::kFloatingPoint | 18,
-  rD19 = RegStorage::k64BitSolo | RegStorage::kFloatingPoint | 19,
-  rD20 = RegStorage::k64BitSolo | RegStorage::kFloatingPoint | 20,
-  rD21 = RegStorage::k64BitSolo | RegStorage::kFloatingPoint | 21,
-  rD22 = RegStorage::k64BitSolo | RegStorage::kFloatingPoint | 22,
-  rD23 = RegStorage::k64BitSolo | RegStorage::kFloatingPoint | 23,
-  rD24 = RegStorage::k64BitSolo | RegStorage::kFloatingPoint | 24,
-  rD25 = RegStorage::k64BitSolo | RegStorage::kFloatingPoint | 25,
-  rD26 = RegStorage::k64BitSolo | RegStorage::kFloatingPoint | 26,
-  rD27 = RegStorage::k64BitSolo | RegStorage::kFloatingPoint | 27,
-  rD28 = RegStorage::k64BitSolo | RegStorage::kFloatingPoint | 28,
-  rD29 = RegStorage::k64BitSolo | RegStorage::kFloatingPoint | 29,
-  rD30 = RegStorage::k64BitSolo | RegStorage::kFloatingPoint | 30,
-  rD31 = RegStorage::k64BitSolo | RegStorage::kFloatingPoint | 31,
-};
-
-constexpr RegStorage rs_rZERO(RegStorage::kValid | rZERO);
-constexpr RegStorage rs_rZEROd(RegStorage::kValid | rZEROd);
-constexpr RegStorage rs_rAT(RegStorage::kValid | rAT);
-constexpr RegStorage rs_rATd(RegStorage::kValid | rATd);
-constexpr RegStorage rs_rV0(RegStorage::kValid | rV0);
-constexpr RegStorage rs_rV0d(RegStorage::kValid | rV0d);
-constexpr RegStorage rs_rV1(RegStorage::kValid | rV1);
-constexpr RegStorage rs_rV1d(RegStorage::kValid | rV1d);
-constexpr RegStorage rs_rA0(RegStorage::kValid | rA0);
-constexpr RegStorage rs_rA0d(RegStorage::kValid | rA0d);
-constexpr RegStorage rs_rA1(RegStorage::kValid | rA1);
-constexpr RegStorage rs_rA1d(RegStorage::kValid | rA1d);
-constexpr RegStorage rs_rA2(RegStorage::kValid | rA2);
-constexpr RegStorage rs_rA2d(RegStorage::kValid | rA2d);
-constexpr RegStorage rs_rA3(RegStorage::kValid | rA3);
-constexpr RegStorage rs_rA3d(RegStorage::kValid | rA3d);
-constexpr RegStorage rs_rA4(RegStorage::kValid | rA4);
-constexpr RegStorage rs_rA4d(RegStorage::kValid | rA4d);
-constexpr RegStorage rs_rA5(RegStorage::kValid | rA5);
-constexpr RegStorage rs_rA5d(RegStorage::kValid | rA5d);
-constexpr RegStorage rs_rA6(RegStorage::kValid | rA6);
-constexpr RegStorage rs_rA6d(RegStorage::kValid | rA6d);
-constexpr RegStorage rs_rA7(RegStorage::kValid | rA7);
-constexpr RegStorage rs_rA7d(RegStorage::kValid | rA7d);
-constexpr RegStorage rs_rT0(RegStorage::kValid | rT0);
-constexpr RegStorage rs_rT0d(RegStorage::kValid | rT0d);
-constexpr RegStorage rs_rT1(RegStorage::kValid | rT1);
-constexpr RegStorage rs_rT1d(RegStorage::kValid | rT1d);
-constexpr RegStorage rs_rT2(RegStorage::kValid | rT2);
-constexpr RegStorage rs_rT2d(RegStorage::kValid | rT2d);
-constexpr RegStorage rs_rT3(RegStorage::kValid | rT3);
-constexpr RegStorage rs_rT3d(RegStorage::kValid | rT3d);
-constexpr RegStorage rs_rS0(RegStorage::kValid | rS0);
-constexpr RegStorage rs_rS0d(RegStorage::kValid | rS0d);
-constexpr RegStorage rs_rS1(RegStorage::kValid | rS1);
-constexpr RegStorage rs_rS1d(RegStorage::kValid | rS1d);
-constexpr RegStorage rs_rS2(RegStorage::kValid | rS2);
-constexpr RegStorage rs_rS2d(RegStorage::kValid | rS2d);
-constexpr RegStorage rs_rS3(RegStorage::kValid | rS3);
-constexpr RegStorage rs_rS3d(RegStorage::kValid | rS3d);
-constexpr RegStorage rs_rS4(RegStorage::kValid | rS4);
-constexpr RegStorage rs_rS4d(RegStorage::kValid | rS4d);
-constexpr RegStorage rs_rS5(RegStorage::kValid | rS5);
-constexpr RegStorage rs_rS5d(RegStorage::kValid | rS5d);
-constexpr RegStorage rs_rS6(RegStorage::kValid | rS6);
-constexpr RegStorage rs_rS6d(RegStorage::kValid | rS6d);
-constexpr RegStorage rs_rS7(RegStorage::kValid | rS7);
-constexpr RegStorage rs_rS7d(RegStorage::kValid | rS7d);
-constexpr RegStorage rs_rT8(RegStorage::kValid | rT8);
-constexpr RegStorage rs_rT8d(RegStorage::kValid | rT8d);
-constexpr RegStorage rs_rT9(RegStorage::kValid | rT9);
-constexpr RegStorage rs_rT9d(RegStorage::kValid | rT9d);
-constexpr RegStorage rs_rK0(RegStorage::kValid | rK0);
-constexpr RegStorage rs_rK0d(RegStorage::kValid | rK0d);
-constexpr RegStorage rs_rK1(RegStorage::kValid | rK1);
-constexpr RegStorage rs_rK1d(RegStorage::kValid | rK1d);
-constexpr RegStorage rs_rGP(RegStorage::kValid | rGP);
-constexpr RegStorage rs_rGPd(RegStorage::kValid | rGPd);
-constexpr RegStorage rs_rSP(RegStorage::kValid | rSP);
-constexpr RegStorage rs_rSPd(RegStorage::kValid | rSPd);
-constexpr RegStorage rs_rFP(RegStorage::kValid | rFP);
-constexpr RegStorage rs_rFPd(RegStorage::kValid | rFPd);
-constexpr RegStorage rs_rRA(RegStorage::kValid | rRA);
-constexpr RegStorage rs_rRAd(RegStorage::kValid | rRAd);
-
-constexpr RegStorage rs_rMIPS64_LR(RegStorage::kInvalid);     // Not used for MIPS64.
-constexpr RegStorage rs_rMIPS64_PC(RegStorage::kInvalid);     // Not used for MIPS64.
-constexpr RegStorage rs_rMIPS64_COUNT(RegStorage::kInvalid);  // Not used for MIPS64.
-
-constexpr RegStorage rs_rF0(RegStorage::kValid | rF0);
-constexpr RegStorage rs_rF1(RegStorage::kValid | rF1);
-constexpr RegStorage rs_rF2(RegStorage::kValid | rF2);
-constexpr RegStorage rs_rF3(RegStorage::kValid | rF3);
-constexpr RegStorage rs_rF4(RegStorage::kValid | rF4);
-constexpr RegStorage rs_rF5(RegStorage::kValid | rF5);
-constexpr RegStorage rs_rF6(RegStorage::kValid | rF6);
-constexpr RegStorage rs_rF7(RegStorage::kValid | rF7);
-constexpr RegStorage rs_rF8(RegStorage::kValid | rF8);
-constexpr RegStorage rs_rF9(RegStorage::kValid | rF9);
-constexpr RegStorage rs_rF10(RegStorage::kValid | rF10);
-constexpr RegStorage rs_rF11(RegStorage::kValid | rF11);
-constexpr RegStorage rs_rF12(RegStorage::kValid | rF12);
-constexpr RegStorage rs_rF13(RegStorage::kValid | rF13);
-constexpr RegStorage rs_rF14(RegStorage::kValid | rF14);
-constexpr RegStorage rs_rF15(RegStorage::kValid | rF15);
-constexpr RegStorage rs_rF16(RegStorage::kValid | rF16);
-constexpr RegStorage rs_rF17(RegStorage::kValid | rF17);
-constexpr RegStorage rs_rF18(RegStorage::kValid | rF18);
-constexpr RegStorage rs_rF19(RegStorage::kValid | rF19);
-constexpr RegStorage rs_rF20(RegStorage::kValid | rF20);
-constexpr RegStorage rs_rF21(RegStorage::kValid | rF21);
-constexpr RegStorage rs_rF22(RegStorage::kValid | rF22);
-constexpr RegStorage rs_rF23(RegStorage::kValid | rF23);
-constexpr RegStorage rs_rF24(RegStorage::kValid | rF24);
-constexpr RegStorage rs_rF25(RegStorage::kValid | rF25);
-constexpr RegStorage rs_rF26(RegStorage::kValid | rF26);
-constexpr RegStorage rs_rF27(RegStorage::kValid | rF27);
-constexpr RegStorage rs_rF28(RegStorage::kValid | rF28);
-constexpr RegStorage rs_rF29(RegStorage::kValid | rF29);
-constexpr RegStorage rs_rF30(RegStorage::kValid | rF30);
-constexpr RegStorage rs_rF31(RegStorage::kValid | rF31);
-
-constexpr RegStorage rs_rD0(RegStorage::kValid | rD0);
-constexpr RegStorage rs_rD1(RegStorage::kValid | rD1);
-constexpr RegStorage rs_rD2(RegStorage::kValid | rD2);
-constexpr RegStorage rs_rD3(RegStorage::kValid | rD3);
-constexpr RegStorage rs_rD4(RegStorage::kValid | rD4);
-constexpr RegStorage rs_rD5(RegStorage::kValid | rD5);
-constexpr RegStorage rs_rD6(RegStorage::kValid | rD6);
-constexpr RegStorage rs_rD7(RegStorage::kValid | rD7);
-constexpr RegStorage rs_rD8(RegStorage::kValid | rD8);
-constexpr RegStorage rs_rD9(RegStorage::kValid | rD9);
-constexpr RegStorage rs_rD10(RegStorage::kValid | rD10);
-constexpr RegStorage rs_rD11(RegStorage::kValid | rD11);
-constexpr RegStorage rs_rD12(RegStorage::kValid | rD12);
-constexpr RegStorage rs_rD13(RegStorage::kValid | rD13);
-constexpr RegStorage rs_rD14(RegStorage::kValid | rD14);
-constexpr RegStorage rs_rD15(RegStorage::kValid | rD15);
-constexpr RegStorage rs_rD16(RegStorage::kValid | rD16);
-constexpr RegStorage rs_rD17(RegStorage::kValid | rD17);
-constexpr RegStorage rs_rD18(RegStorage::kValid | rD18);
-constexpr RegStorage rs_rD19(RegStorage::kValid | rD19);
-constexpr RegStorage rs_rD20(RegStorage::kValid | rD20);
-constexpr RegStorage rs_rD21(RegStorage::kValid | rD21);
-constexpr RegStorage rs_rD22(RegStorage::kValid | rD22);
-constexpr RegStorage rs_rD23(RegStorage::kValid | rD23);
-constexpr RegStorage rs_rD24(RegStorage::kValid | rD24);
-constexpr RegStorage rs_rD25(RegStorage::kValid | rD25);
-constexpr RegStorage rs_rD26(RegStorage::kValid | rD26);
-constexpr RegStorage rs_rD27(RegStorage::kValid | rD27);
-constexpr RegStorage rs_rD28(RegStorage::kValid | rD28);
-constexpr RegStorage rs_rD29(RegStorage::kValid | rD29);
-constexpr RegStorage rs_rD30(RegStorage::kValid | rD30);
-constexpr RegStorage rs_rD31(RegStorage::kValid | rD31);
-
-// TODO: reduce/eliminate use of these.
-#define rMIPS64_SUSPEND rS0d
-#define rs_rMIPS64_SUSPEND rs_rS0d
-#define rMIPS64_SELF rS1d
-#define rs_rMIPS64_SELF rs_rS1d
-#define rMIPS64_SP rSPd
-#define rs_rMIPS64_SP rs_rSPd
-#define rMIPS64_ARG0 rARG0
-#define rs_rMIPS64_ARG0 rs_rARG0
-#define rMIPS64_ARG1 rARG1
-#define rs_rMIPS64_ARG1 rs_rARG1
-#define rMIPS64_ARG2 rARG2
-#define rs_rMIPS64_ARG2 rs_rARG2
-#define rMIPS64_ARG3 rARG3
-#define rs_rMIPS64_ARG3 rs_rARG3
-#define rMIPS64_ARG4 rARG4
-#define rs_rMIPS64_ARG4 rs_rARG4
-#define rMIPS64_ARG5 rARG5
-#define rs_rMIPS64_ARG5 rs_rARG5
-#define rMIPS64_ARG6 rARG6
-#define rs_rMIPS64_ARG6 rs_rARG6
-#define rMIPS64_ARG7 rARG7
-#define rs_rMIPS64_ARG7 rs_rARG7
-#define rMIPS64_FARG0 rFARG0
-#define rs_rMIPS64_FARG0 rs_rFARG0
-#define rMIPS64_FARG1 rFARG1
-#define rs_rMIPS64_FARG1 rs_rFARG1
-#define rMIPS64_FARG2 rFARG2
-#define rs_rMIPS64_FARG2 rs_rFARG2
-#define rMIPS64_FARG3 rFARG3
-#define rs_rMIPS64_FARG3 rs_rFARG3
-#define rMIPS64_FARG4 rFARG4
-#define rs_rMIPS64_FARG4 rs_rFARG4
-#define rMIPS64_FARG5 rFARG5
-#define rs_rMIPS64_FARG5 rs_rFARG5
-#define rMIPS64_FARG6 rFARG6
-#define rs_rMIPS64_FARG6 rs_rFARG6
-#define rMIPS64_FARG7 rFARG7
-#define rs_rMIPS64_FARG7 rs_rFARG7
-#define rMIPS64_RET0 rRESULT0
-#define rs_rMIPS64_RET0 rs_rRESULT0
-#define rMIPS64_RET1 rRESULT1
-#define rs_rMIPS64_RET1 rs_rRESULT1
-#define rMIPS64_INVOKE_TGT rT9d
-#define rs_rMIPS64_INVOKE_TGT rs_rT9d
-#define rMIPS64_COUNT RegStorage::kInvalidRegVal
-
-// RegisterLocation templates return values (r_V0).
-const RegLocation mips64_loc_c_return
-    {kLocPhysReg, 0, 0, 0, 0, 0, 0, 0, 1,
-     RegStorage(RegStorage::k32BitSolo, rV0), INVALID_SREG, INVALID_SREG};
-const RegLocation mips64_loc_c_return_ref
-    {kLocPhysReg, 0, 0, 0, 0, 0, 1, 0, 1,
-     RegStorage(RegStorage::k64BitSolo, rV0d), INVALID_SREG, INVALID_SREG};
-const RegLocation mips64_loc_c_return_wide
-    {kLocPhysReg, 1, 0, 0, 0, 0, 0, 0, 1,
-     RegStorage(RegStorage::k64BitSolo, rV0d), INVALID_SREG, INVALID_SREG};
-const RegLocation mips64_loc_c_return_float
-    {kLocPhysReg, 0, 0, 0, 1, 0, 0, 0, 1,
-     RegStorage(RegStorage::k32BitSolo, rF0), INVALID_SREG, INVALID_SREG};
-const RegLocation mips64_loc_c_return_double
-    {kLocPhysReg, 1, 0, 0, 1, 0, 0, 0, 1,
-     RegStorage(RegStorage::k64BitSolo, rD0), INVALID_SREG, INVALID_SREG};
-
-enum Mips64ShiftEncodings {
-  kMips64Lsl = 0x0,
-  kMips64Lsr = 0x1,
-  kMips64Asr = 0x2,
-  kMips64Ror = 0x3
-};
-
-// MIPS64 sync kinds (Note: support for kinds other than kSYNC0 may not exist).
-#define kSYNC0        0x00
-#define kSYNC_WMB     0x04
-#define kSYNC_MB      0x01
-#define kSYNC_ACQUIRE 0x11
-#define kSYNC_RELEASE 0x12
-#define kSYNC_RMB     0x13
-
-// TODO: Use smaller hammer when appropriate for target CPU.
-#define kST kSYNC0
-#define kSY kSYNC0
-
-/*
- * The following enum defines the list of supported Mips64 instructions by the
- * assembler. Their corresponding EncodingMap positions will be defined in
- * assemble_mips64.cc.
- */
-enum Mips64OpCode {
-  kMips64First = 0,
-  kMips6432BitData = kMips64First,  // data [31..0].
-  kMips64Addiu,      // addiu t,s,imm16 [001001] s[25..21] t[20..16] imm16[15..0].
-  kMips64Addu,       // add d,s,t [000000] s[25..21] t[20..16] d[15..11] [00000100001].
-  kMips64And,        // and d,s,t [000000] s[25..21] t[20..16] d[15..11] [00000100100].
-  kMips64Andi,       // andi t,s,imm16 [001100] s[25..21] t[20..16] imm16[15..0].
-  kMips64B,          // b o   [0001000000000000] o[15..0].
-  kMips64Bal,        // bal o [0000010000010001] o[15..0].
-  // NOTE: the code tests the range kMips64Beq thru kMips64Bne, so adding an instruction in this
-  //       range may require updates.
-  kMips64Beq,        // beq s,t,o [000100] s[25..21] t[20..16] o[15..0].
-  kMips64Beqz,       // beqz s,o [000100] s[25..21] [00000] o[15..0].
-  kMips64Bgez,       // bgez s,o [000001] s[25..21] [00001] o[15..0].
-  kMips64Bgtz,       // bgtz s,o [000111] s[25..21] [00000] o[15..0].
-  kMips64Blez,       // blez s,o [000110] s[25..21] [00000] o[15..0].
-  kMips64Bltz,       // bltz s,o [000001] s[25..21] [00000] o[15..0].
-  kMips64Bnez,       // bnez s,o [000101] s[25..21] [00000] o[15..0].
-  kMips64Bne,        // bne s,t,o [000101] s[25..21] t[20..16] o[15..0].
-  kMips64Break,      // break code [000000] code[25..6] [001101].
-  kMips64Daddiu,     // daddiu t,s,imm16 [011001] s[25..21] t[20..16] imm16[15..11].
-  kMips64Daddu,      // daddu d,s,t [000000] s[25..21] t[20..16] d[15..11] [00000101101].
-  kMips64Dahi,       // dahi s,imm16 [000001] s[25..21] [00110] imm16[15..11].
-  kMips64Dati,       // dati s,imm16 [000001] s[25..21] [11110] imm16[15..11].
-  kMips64Daui,       // daui t,s,imm16 [011101] s[25..21] t[20..16] imm16[15..11].
-  kMips64Ddiv,       // ddiv  d,s,t [000000] s[25..21] t[20..16] d[15..11] [00010011110].
-  kMips64Div,        // div   d,s,t [000000] s[25..21] t[20..16] d[15..11] [00010011010].
-  kMips64Dmod,       // dmod  d,s,t [000000] s[25..21] t[20..16] d[15..11] [00011011110].
-  kMips64Dmul,       // dmul  d,s,t [000000] s[25..21] t[20..16] d[15..11] [00010011100].
-  kMips64Dmfc1,      // dmfc1 t,s [01000100001] t[20..16] s[15..11] [00000000000].
-  kMips64Dmtc1,      // dmtc1 t,s [01000100101] t[20..16] s[15..11] [00000000000].
-  kMips64Drotr32,    // drotr32 d,t,a [00000000001] t[20..16] d[15..11] a[10..6] [111110].
-  kMips64Dsll,       // dsll    d,t,a [00000000000] t[20..16] d[15..11] a[10..6] [111000].
-  kMips64Dsll32,     // dsll32  d,t,a [00000000000] t[20..16] d[15..11] a[10..6] [111100].
-  kMips64Dsrl,       // dsrl    d,t,a [00000000000] t[20..16] d[15..11] a[10..6] [111010].
-  kMips64Dsrl32,     // dsrl32  d,t,a [00000000000] t[20..16] d[15..11] a[10..6] [111110].
-  kMips64Dsra,       // dsra    d,t,a [00000000000] t[20..16] d[15..11] a[10..6] [111011].
-  kMips64Dsra32,     // dsra32  d,t,a [00000000000] t[20..16] d[15..11] a[10..6] [111111].
-  kMips64Dsllv,      // dsllv d,t,s [000000] s[25..21] t[20..16] d[15..11] [00000010100].
-  kMips64Dsrlv,      // dsrlv d,t,s [000000] s[25..21] t[20..16] d[15..11] [00000010110].
-  kMips64Dsrav,      // dsrav d,t,s [000000] s[25..21] t[20..16] d[15..11] [00000010111].
-  kMips64Dsubu,      // dsubu d,s,t [000000] s[25..21] t[20..16] d[15..11] [00000101111].
-  kMips64Ext,        // ext t,s,p,z [011111] s[25..21] t[20..16] z[15..11] p[10..6] [000000].
-  kMips64Faddd,      // add.d d,s,t [01000110001] t[20..16] s[15..11] d[10..6] [000000].
-  kMips64Fadds,      // add.s d,s,t [01000110000] t[20..16] s[15..11] d[10..6] [000000].
-  kMips64Fdivd,      // div.d d,s,t [01000110001] t[20..16] s[15..11] d[10..6] [000011].
-  kMips64Fdivs,      // div.s d,s,t [01000110000] t[20..16] s[15..11] d[10..6] [000011].
-  kMips64Fmuld,      // mul.d d,s,t [01000110001] t[20..16] s[15..11] d[10..6] [000010].
-  kMips64Fmuls,      // mul.s d,s,t [01000110000] t[20..16] s[15..11] d[10..6] [000010].
-  kMips64Fsubd,      // sub.d d,s,t [01000110001] t[20..16] s[15..11] d[10..6] [000001].
-  kMips64Fsubs,      // sub.s d,s,t [01000110000] t[20..16] s[15..11] d[10..6] [000001].
-  kMips64Fcvtsd,     // cvt.s.d d,s [01000110001] [00000] s[15..11] d[10..6] [100000].
-  kMips64Fcvtsw,     // cvt.s.w d,s [01000110100] [00000] s[15..11] d[10..6] [100000].
-  kMips64Fcvtds,     // cvt.d.s d,s [01000110000] [00000] s[15..11] d[10..6] [100001].
-  kMips64Fcvtdw,     // cvt.d.w d,s [01000110100] [00000] s[15..11] d[10..6] [100001].
-  kMips64Fcvtws,     // cvt.w.d d,s [01000110000] [00000] s[15..11] d[10..6] [100100].
-  kMips64Fcvtwd,     // cvt.w.d d,s [01000110001] [00000] s[15..11] d[10..6] [100100].
-  kMips64Fmovd,      // mov.d d,s [01000110001] [00000] s[15..11] d[10..6] [000110].
-  kMips64Fmovs,      // mov.s d,s [01000110000] [00000] s[15..11] d[10..6] [000110].
-  kMips64Fnegd,      // neg.d d,s [01000110001] [00000] s[15..11] d[10..6] [000111].
-  kMips64Fnegs,      // neg.s d,s [01000110000] [00000] s[15..11] d[10..6] [000111].
-  kMips64Fldc1,      // ldc1 t,o(b) [110101] b[25..21] t[20..16] o[15..0].
-  kMips64Flwc1,      // lwc1 t,o(b) [110001] b[25..21] t[20..16] o[15..0].
-  kMips64Fsdc1,      // sdc1 t,o(b) [111101] b[25..21] t[20..16] o[15..0].
-  kMips64Fswc1,      // swc1 t,o(b) [111001] b[25..21] t[20..16] o[15..0].
-  kMips64Jal,        // jal t [000011] t[25..0].
-  kMips64Jalr,       // jalr d,s [000000] s[25..21] [00000] d[15..11] hint[10..6] [001001].
-  kMips64Lahi,       // lui t,imm16 [00111100000] t[20..16] imm16[15..0] load addr hi.
-  kMips64Lalo,       // ori t,s,imm16 [001001] s[25..21] t[20..16] imm16[15..0] load addr lo.
-  kMips64Lb,         // lb  t,o(b) [100000] b[25..21] t[20..16] o[15..0].
-  kMips64Lbu,        // lbu t,o(b) [100100] b[25..21] t[20..16] o[15..0].
-  kMips64Ld,         // ld  t,o(b) [110111] b[25..21] t[20..16] o[15..0].
-  kMips64Lh,         // lh  t,o(b) [100001] b[25..21] t[20..16] o[15..0].
-  kMips64Lhu,        // lhu t,o(b) [100101] b[25..21] t[20..16] o[15..0].
-  kMips64Lui,        // lui t,imm16 [00111100000] t[20..16] imm16[15..0].
-  kMips64Lw,         // lw  t,o(b) [100011] b[25..21] t[20..16] o[15..0].
-  kMips64Lwu,        // lwu t,o(b) [100111] b[25..21] t[20..16] o[15..0].
-  kMips64Mfc1,       // mfc1 t,s [01000100000] t[20..16] s[15..11] [00000000000].
-  kMips64Mtc1,       // mtc1 t,s [01000100100] t[20..16] s[15..11] [00000000000].
-  kMips64Move,       // move d,s [000000] s[25..21] [00000] d[15..11] [00000101101].
-  kMips64Mod,        // mod d,s,t [000000] s[25..21] t[20..16] d[15..11] [00011011010].
-  kMips64Mul,        // mul d,s,t [000000] s[25..21] t[20..16] d[15..11] [00010011000].
-  kMips64Nop,        // nop [00000000000000000000000000000000].
-  kMips64Nor,        // nor d,s,t [000000] s[25..21] t[20..16] d[15..11] [00000100111].
-  kMips64Or,         // or  d,s,t [000000] s[25..21] t[20..16] d[15..11] [00000100101].
-  kMips64Ori,        // ori t,s,imm16 [001001] s[25..21] t[20..16] imm16[15..0].
-  kMips64Sb,         // sb t,o(b) [101000] b[25..21] t[20..16] o[15..0].
-  kMips64Sd,         // sd t,o(b) [111111] b[25..21] t[20..16] o[15..0].
-  kMips64Seb,        // seb d,t [01111100000] t[20..16] d[15..11] [10000100000].
-  kMips64Seh,        // seh d,t [01111100000] t[20..16] d[15..11] [11000100000].
-  kMips64Sh,         // sh t,o(b) [101001] b[25..21] t[20..16] o[15..0].
-  kMips64Sll,        // sll d,t,a [00000000000] t[20..16] d[15..11] a[10..6] [000000].
-  kMips64Sllv,       // sllv d,t,s [000000] s[25..21] t[20..16] d[15..11] [00000000100].
-  kMips64Slt,        // slt d,s,t [000000] s[25..21] t[20..16] d[15..11] [00000101010].
-  kMips64Slti,       // slti t,s,imm16 [001010] s[25..21] t[20..16] imm16[15..0].
-  kMips64Sltu,       // sltu d,s,t [000000] s[25..21] t[20..16] d[15..11] [00000101011].
-  kMips64Sra,        // sra d,s,imm5 [00000000000] t[20..16] d[15..11] imm5[10..6] [000011].
-  kMips64Srav,       // srav d,t,s [000000] s[25..21] t[20..16] d[15..11] [00000000111].
-  kMips64Srl,        // srl d,t,a [00000000000] t[20..16] d[20..16] a[10..6] [000010].
-  kMips64Srlv,       // srlv d,t,s [000000] s[25..21] t[20..16] d[15..11] [00000000110].
-  kMips64Subu,       // subu d,s,t [000000] s[25..21] t[20..16] d[15..11] [00000100011].
-  kMips64Sw,         // sw t,o(b) [101011] b[25..21] t[20..16] o[15..0].
-  kMips64Sync,       // sync kind [000000] [0000000000000000] s[10..6] [001111].
-  kMips64Xor,        // xor d,s,t [000000] s[25..21] t[20..16] d[15..11] [00000100110].
-  kMips64Xori,       // xori t,s,imm16 [001110] s[25..21] t[20..16] imm16[15..0].
-  kMips64CurrPC,     // jal to .+8 to materialize pc.
-  kMips64Delta,      // Psuedo for ori t, s, <label>-<label>.
-  kMips64DeltaHi,    // Pseudo for lui t, high16(<label>-<label>).
-  kMips64DeltaLo,    // Pseudo for ori t, s, low16(<label>-<label>).
-  kMips64Undefined,  // undefined [011001xxxxxxxxxxxxxxxx].
-  kMips64Last
-};
-std::ostream& operator<<(std::ostream& os, const Mips64OpCode& rhs);
-
-// Instruction assembly field_loc kind.
-enum Mips64EncodingKind {
-  kFmtUnused,
-  kFmtBitBlt,    // Bit string using end/start.
-  kFmtDfp,       // Double FP reg.
-  kFmtSfp,       // Single FP reg.
-  kFmtBlt5_2,    // Same 5-bit field to 2 locations.
-};
-std::ostream& operator<<(std::ostream& os, const Mips64EncodingKind& rhs);
-
-// Struct used to define the snippet positions for each MIPS64 opcode.
-struct Mips64EncodingMap {
-  uint32_t skeleton;
-  struct {
-    Mips64EncodingKind kind;
-    int end;   // end for kFmtBitBlt, 1-bit slice end for FP regs.
-    int start;  // start for kFmtBitBlt, 4-bit slice end for FP regs.
-  } field_loc[4];
-  Mips64OpCode opcode;
-  uint64_t flags;
-  const char *name;
-  const char* fmt;
-  int size;   // Note: size is in bytes.
-};
-
-extern Mips64EncodingMap EncodingMap[kMips64Last];
-
-#define IS_UIMM16(v) ((0 <= (v)) && ((v) <= 65535))
-#define IS_SIMM16(v) ((-32768 <= (v)) && ((v) <= 32766))
-#define IS_SIMM16_2WORD(v) ((-32764 <= (v)) && ((v) <= 32763))  // 2 offsets must fit.
-
-}  // namespace art
-
-#endif  // ART_COMPILER_DEX_QUICK_MIPS64_MIPS64_LIR_H_
diff --git a/compiler/dex/quick/mips64/target_mips64.cc b/compiler/dex/quick/mips64/target_mips64.cc
deleted file mode 100644
index 6ed9617..0000000
--- a/compiler/dex/quick/mips64/target_mips64.cc
+++ /dev/null
@@ -1,653 +0,0 @@
-/*
- * Copyright (C) 2015 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.
- */
-
-#include "codegen_mips64.h"
-
-#include <inttypes.h>
-
-#include <string>
-
-#include "arch/mips64/instruction_set_features_mips64.h"
-#include "backend_mips64.h"
-#include "base/logging.h"
-#include "dex/compiler_ir.h"
-#include "dex/quick/mir_to_lir-inl.h"
-#include "driver/compiler_driver.h"
-#include "mips64_lir.h"
-
-namespace art {
-
-static constexpr RegStorage core_regs_arr32[] =
-    {rs_rZERO, rs_rAT, rs_rV0, rs_rV1, rs_rA0, rs_rA1, rs_rA2, rs_rA3, rs_rA4, rs_rA5, rs_rA6,
-     rs_rA7, rs_rT0, rs_rT1, rs_rT2, rs_rT3, rs_rS0, rs_rS1, rs_rS2, rs_rS3, rs_rS4, rs_rS5,
-     rs_rS6, rs_rS7, rs_rT8, rs_rT9, rs_rK0, rs_rK1, rs_rGP, rs_rSP, rs_rFP, rs_rRA};
-static constexpr RegStorage core_regs_arr64[] =
-    {rs_rZEROd, rs_rATd, rs_rV0d, rs_rV1d, rs_rA0d, rs_rA1d, rs_rA2d, rs_rA3d, rs_rA4d, rs_rA5d,
-     rs_rA6d, rs_rA7d, rs_rT0d, rs_rT1d, rs_rT2d, rs_rT3d, rs_rS0d, rs_rS1d, rs_rS2d, rs_rS3d,
-     rs_rS4d, rs_rS5d, rs_rS6d, rs_rS7d, rs_rT8d, rs_rT9d, rs_rK0d, rs_rK1d, rs_rGPd, rs_rSPd,
-     rs_rFPd, rs_rRAd};
-#if 0
-// TODO: f24-f31 must be saved before calls and restored after.
-static constexpr RegStorage sp_regs_arr[] =
-    {rs_rF0, rs_rF1, rs_rF2, rs_rF3, rs_rF4, rs_rF5, rs_rF6, rs_rF7, rs_rF8, rs_rF9, rs_rF10,
-     rs_rF11, rs_rF12, rs_rF13, rs_rF14, rs_rF15, rs_rF16, rs_rF17, rs_rF18, rs_rF19, rs_rF20,
-     rs_rF21, rs_rF22, rs_rF23, rs_rF24, rs_rF25, rs_rF26, rs_rF27, rs_rF28, rs_rF29, rs_rF30,
-     rs_rF31};
-static constexpr RegStorage dp_regs_arr[] =
-    {rs_rD0, rs_rD1, rs_rD2, rs_rD3, rs_rD4, rs_rD5, rs_rD6, rs_rD7, rs_rD8, rs_rD9, rs_rD10,
-     rs_rD11, rs_rD12, rs_rD13, rs_rD14, rs_rD15, rs_rD16, rs_rD17, rs_rD18, rs_rD19, rs_rD20,
-     rs_rD21, rs_rD22, rs_rD23, rs_rD24, rs_rD25, rs_rD26, rs_rD27, rs_rD28, rs_rD29, rs_rD30,
-     rs_rD31};
-#else
-static constexpr RegStorage sp_regs_arr[] =
-    {rs_rF0, rs_rF1, rs_rF2, rs_rF3, rs_rF4, rs_rF5, rs_rF6, rs_rF7, rs_rF8, rs_rF9, rs_rF10,
-     rs_rF11, rs_rF12, rs_rF13, rs_rF14, rs_rF15, rs_rF16, rs_rF17, rs_rF18, rs_rF19, rs_rF20,
-     rs_rF21, rs_rF22, rs_rF23};
-static constexpr RegStorage dp_regs_arr[] =
-    {rs_rD0, rs_rD1, rs_rD2, rs_rD3, rs_rD4, rs_rD5, rs_rD6, rs_rD7, rs_rD8, rs_rD9, rs_rD10,
-     rs_rD11, rs_rD12, rs_rD13, rs_rD14, rs_rD15, rs_rD16, rs_rD17, rs_rD18, rs_rD19, rs_rD20,
-     rs_rD21, rs_rD22, rs_rD23};
-#endif
-static constexpr RegStorage reserved_regs_arr32[] =
-    {rs_rZERO, rs_rAT, rs_rS0, rs_rS1, rs_rT9, rs_rK0, rs_rK1, rs_rGP, rs_rSP, rs_rRA};
-static constexpr RegStorage reserved_regs_arr64[] =
-    {rs_rZEROd, rs_rATd, rs_rS0d, rs_rS1d, rs_rT9d, rs_rK0d, rs_rK1d, rs_rGPd, rs_rSPd, rs_rRAd};
-static constexpr RegStorage core_temps_arr32[] =
-    {rs_rV0, rs_rV1, rs_rA0, rs_rA1, rs_rA2, rs_rA3, rs_rA4, rs_rA5, rs_rA6, rs_rA7, rs_rT0,
-     rs_rT1, rs_rT2, rs_rT3, rs_rT8};
-static constexpr RegStorage core_temps_arr64[] =
-    {rs_rV0d, rs_rV1d, rs_rA0d, rs_rA1d, rs_rA2d, rs_rA3d, rs_rA4d, rs_rA5d, rs_rA6d, rs_rA7d,
-     rs_rT0d, rs_rT1d, rs_rT2d, rs_rT3d, rs_rT8d};
-#if 0
-// TODO: f24-f31 must be saved before calls and restored after.
-static constexpr RegStorage sp_temps_arr[] =
-    {rs_rF0, rs_rF1, rs_rF2, rs_rF3, rs_rF4, rs_rF5, rs_rF6, rs_rF7, rs_rF8, rs_rF9, rs_rF10,
-     rs_rF11, rs_rF12, rs_rF13, rs_rF14, rs_rF15, rs_rF16, rs_rF17, rs_rF18, rs_rF19, rs_rF20,
-     rs_rF21, rs_rF22, rs_rF23, rs_rF24, rs_rF25, rs_rF26, rs_rF27, rs_rF28, rs_rF29, rs_rF30,
-     rs_rF31};
-static constexpr RegStorage dp_temps_arr[] =
-    {rs_rD0, rs_rD1, rs_rD2, rs_rD3, rs_rD4, rs_rD5, rs_rD6, rs_rD7, rs_rD8, rs_rD9, rs_rD10,
-     rs_rD11, rs_rD12, rs_rD13, rs_rD14, rs_rD15, rs_rD16, rs_rD17, rs_rD18, rs_rD19, rs_rD20,
-     rs_rD21, rs_rD22, rs_rD23, rs_rD24, rs_rD25, rs_rD26, rs_rD27, rs_rD28, rs_rD29, rs_rD30,
-     rs_rD31};
-#else
-static constexpr RegStorage sp_temps_arr[] =
-    {rs_rF0, rs_rF1, rs_rF2, rs_rF3, rs_rF4, rs_rF5, rs_rF6, rs_rF7, rs_rF8, rs_rF9, rs_rF10,
-     rs_rF11, rs_rF12, rs_rF13, rs_rF14, rs_rF15, rs_rF16, rs_rF17, rs_rF18, rs_rF19, rs_rF20,
-     rs_rF21, rs_rF22, rs_rF23};
-static constexpr RegStorage dp_temps_arr[] =
-    {rs_rD0, rs_rD1, rs_rD2, rs_rD3, rs_rD4, rs_rD5, rs_rD6, rs_rD7, rs_rD8, rs_rD9, rs_rD10,
-     rs_rD11, rs_rD12, rs_rD13, rs_rD14, rs_rD15, rs_rD16, rs_rD17, rs_rD18, rs_rD19, rs_rD20,
-     rs_rD21, rs_rD22, rs_rD23};
-#endif
-
-static constexpr ArrayRef<const RegStorage> empty_pool;
-static constexpr ArrayRef<const RegStorage> core_regs32(core_regs_arr32);
-static constexpr ArrayRef<const RegStorage> core_regs64(core_regs_arr64);
-static constexpr ArrayRef<const RegStorage> sp_regs(sp_regs_arr);
-static constexpr ArrayRef<const RegStorage> dp_regs(dp_regs_arr);
-static constexpr ArrayRef<const RegStorage> reserved_regs32(reserved_regs_arr32);
-static constexpr ArrayRef<const RegStorage> reserved_regs64(reserved_regs_arr64);
-static constexpr ArrayRef<const RegStorage> core_temps32(core_temps_arr32);
-static constexpr ArrayRef<const RegStorage> core_temps64(core_temps_arr64);
-static constexpr ArrayRef<const RegStorage> sp_temps(sp_temps_arr);
-static constexpr ArrayRef<const RegStorage> dp_temps(dp_temps_arr);
-
-RegLocation Mips64Mir2Lir::LocCReturn() {
-  return mips64_loc_c_return;
-}
-
-RegLocation Mips64Mir2Lir::LocCReturnRef() {
-  return mips64_loc_c_return_ref;
-}
-
-RegLocation Mips64Mir2Lir::LocCReturnWide() {
-  return mips64_loc_c_return_wide;
-}
-
-RegLocation Mips64Mir2Lir::LocCReturnFloat() {
-  return mips64_loc_c_return_float;
-}
-
-RegLocation Mips64Mir2Lir::LocCReturnDouble() {
-  return mips64_loc_c_return_double;
-}
-
-// Return a target-dependent special register.
-RegStorage Mips64Mir2Lir::TargetReg(SpecialTargetRegister reg) {
-  RegStorage res_reg;
-  switch (reg) {
-    case kSelf: res_reg = rs_rS1; break;
-    case kSuspend: res_reg =  rs_rS0; break;
-    case kLr: res_reg =  rs_rRA; break;
-    case kPc: res_reg = RegStorage::InvalidReg(); break;
-    case kSp: res_reg =  rs_rSP; break;
-    case kArg0: res_reg = rs_rA0; break;
-    case kArg1: res_reg = rs_rA1; break;
-    case kArg2: res_reg = rs_rA2; break;
-    case kArg3: res_reg = rs_rA3; break;
-    case kArg4: res_reg = rs_rA4; break;
-    case kArg5: res_reg = rs_rA5; break;
-    case kArg6: res_reg = rs_rA6; break;
-    case kArg7: res_reg = rs_rA7; break;
-    case kFArg0: res_reg = rs_rF12; break;
-    case kFArg1: res_reg = rs_rF13; break;
-    case kFArg2: res_reg = rs_rF14; break;
-    case kFArg3: res_reg = rs_rF15; break;
-    case kFArg4: res_reg = rs_rF16; break;
-    case kFArg5: res_reg = rs_rF17; break;
-    case kFArg6: res_reg = rs_rF18; break;
-    case kFArg7: res_reg = rs_rF19; break;
-    case kRet0: res_reg = rs_rV0; break;
-    case kRet1: res_reg = rs_rV1; break;
-    case kInvokeTgt: res_reg = rs_rT9; break;
-    case kHiddenArg: res_reg = rs_rT0; break;
-    case kHiddenFpArg: res_reg = RegStorage::InvalidReg(); break;
-    case kCount: res_reg = RegStorage::InvalidReg(); break;
-    default: res_reg = RegStorage::InvalidReg();
-  }
-  return res_reg;
-}
-
-RegStorage Mips64Mir2Lir::InToRegStorageMips64Mapper::GetNextReg(ShortyArg arg) {
-  const SpecialTargetRegister coreArgMappingToPhysicalReg[] =
-      {kArg1, kArg2, kArg3, kArg4, kArg5, kArg6, kArg7};
-  const size_t coreArgMappingToPhysicalRegSize = arraysize(coreArgMappingToPhysicalReg);
-  const SpecialTargetRegister fpArgMappingToPhysicalReg[] =
-      {kFArg1, kFArg2, kFArg3, kFArg4, kFArg5, kFArg6, kFArg7};
-  const size_t fpArgMappingToPhysicalRegSize = arraysize(fpArgMappingToPhysicalReg);
-
-  RegStorage result = RegStorage::InvalidReg();
-  if (arg.IsFP()) {
-    if (cur_arg_reg_ < fpArgMappingToPhysicalRegSize) {
-      DCHECK(!arg.IsRef());
-      result = m2l_->TargetReg(fpArgMappingToPhysicalReg[cur_arg_reg_++],
-                               arg.IsWide() ? kWide : kNotWide);
-    }
-  } else {
-    if (cur_arg_reg_ < coreArgMappingToPhysicalRegSize) {
-      DCHECK(!(arg.IsWide() && arg.IsRef()));
-      result = m2l_->TargetReg(coreArgMappingToPhysicalReg[cur_arg_reg_++],
-                               arg.IsRef() ? kRef : (arg.IsWide() ? kWide : kNotWide));
-    }
-  }
-  return result;
-}
-
-/*
- * Decode the register id.
- */
-ResourceMask Mips64Mir2Lir::GetRegMaskCommon(const RegStorage& reg) const {
-  return ResourceMask::Bit((reg.IsFloat() ? kMips64FPReg0 : 0) + reg.GetRegNum());
-}
-
-ResourceMask Mips64Mir2Lir::GetPCUseDefEncoding() const {
-  return ResourceMask::Bit(kMips64RegPC);
-}
-
-
-void Mips64Mir2Lir::SetupTargetResourceMasks(LIR* lir, uint64_t flags, ResourceMask* use_mask,
-                                             ResourceMask* def_mask) {
-  DCHECK(!lir->flags.use_def_invalid);
-
-  // Mips64-specific resource map setup here.
-  if (flags & REG_DEF_SP) {
-    def_mask->SetBit(kMips64RegSP);
-  }
-
-  if (flags & REG_USE_SP) {
-    use_mask->SetBit(kMips64RegSP);
-  }
-
-  if (flags & REG_DEF_LR) {
-    def_mask->SetBit(kMips64RegLR);
-  }
-}
-
-/* For dumping instructions */
-#define MIPS64_REG_COUNT 32
-static const char *mips64_reg_name[MIPS64_REG_COUNT] = {
-  "zero", "at", "v0", "v1", "a0", "a1", "a2", "a3",
-  "a4", "a5", "a6", "a7", "t0", "t1", "t2", "t3",
-  "s0", "s1", "s2", "s3", "s4", "s5", "s6", "s7",
-  "t8", "t9", "k0", "k1", "gp", "sp", "fp", "ra"
-};
-
-/*
- * Interpret a format string and build a string no longer than size
- * See format key in assemble_mips64.cc.
- */
-std::string Mips64Mir2Lir::BuildInsnString(const char *fmt, LIR *lir, unsigned char* base_addr) {
-  std::string buf;
-  int i;
-  const char *fmt_end = &fmt[strlen(fmt)];
-  char tbuf[256];
-  char nc;
-  while (fmt < fmt_end) {
-    int operand;
-    if (*fmt == '!') {
-      fmt++;
-      DCHECK_LT(fmt, fmt_end);
-      nc = *fmt++;
-      if (nc == '!') {
-        strcpy(tbuf, "!");
-      } else {
-        DCHECK_LT(fmt, fmt_end);
-        DCHECK_LT(static_cast<unsigned>(nc-'0'), 4u);
-        operand = lir->operands[nc-'0'];
-        switch (*fmt++) {
-          case 'b':
-            strcpy(tbuf, "0000");
-            for (i = 3; i >= 0; i--) {
-              tbuf[i] += operand & 1;
-              operand >>= 1;
-            }
-            break;
-          case 's':
-            snprintf(tbuf, arraysize(tbuf), "$f%d", RegStorage::RegNum(operand));
-            break;
-          case 'S':
-            DCHECK_EQ(RegStorage::RegNum(operand) & 1, 0);
-            snprintf(tbuf, arraysize(tbuf), "$f%d", RegStorage::RegNum(operand));
-            break;
-          case 'h':
-            snprintf(tbuf, arraysize(tbuf), "%04x", operand);
-            break;
-          case 'M':
-          case 'd':
-            snprintf(tbuf, arraysize(tbuf), "%d", operand);
-            break;
-          case 'D':
-            snprintf(tbuf, arraysize(tbuf), "%d", operand+1);
-            break;
-          case 'E':
-            snprintf(tbuf, arraysize(tbuf), "%d", operand*4);
-            break;
-          case 'F':
-            snprintf(tbuf, arraysize(tbuf), "%d", operand*2);
-            break;
-          case 't':
-            snprintf(tbuf, arraysize(tbuf), "0x%08" PRIxPTR " (L%p)",
-                     reinterpret_cast<uintptr_t>(base_addr) + lir->offset + 4 + (operand << 1),
-                     lir->target);
-            break;
-          case 'T':
-            snprintf(tbuf, arraysize(tbuf), "0x%08x", operand << 2);
-            break;
-          case 'u': {
-            int offset_1 = lir->operands[0];
-            int offset_2 = NEXT_LIR(lir)->operands[0];
-            uintptr_t target =
-                (((reinterpret_cast<uintptr_t>(base_addr) + lir->offset + 4) & ~3) +
-                    (offset_1 << 21 >> 9) + (offset_2 << 1)) & 0xfffffffc;
-            snprintf(tbuf, arraysize(tbuf), "%p", reinterpret_cast<void*>(target));
-            break;
-          }
-
-          /* Nothing to print for BLX_2 */
-          case 'v':
-            strcpy(tbuf, "see above");
-            break;
-          case 'r':
-            DCHECK(operand >= 0 && operand < MIPS64_REG_COUNT);
-            strcpy(tbuf, mips64_reg_name[operand]);
-            break;
-          case 'N':
-            // Placeholder for delay slot handling
-            strcpy(tbuf, ";  nop");
-            break;
-          default:
-            strcpy(tbuf, "DecodeError");
-            break;
-        }
-        buf += tbuf;
-      }
-    } else {
-      buf += *fmt++;
-    }
-  }
-  return buf;
-}
-
-// FIXME: need to redo resource maps for MIPS64 - fix this at that time.
-void Mips64Mir2Lir::DumpResourceMask(LIR *mips64_lir, const ResourceMask& mask, const char *prefix) {
-  char buf[256];
-  buf[0] = 0;
-
-  if (mask.Equals(kEncodeAll)) {
-    strcpy(buf, "all");
-  } else {
-    char num[8];
-    int i;
-
-    for (i = 0; i < kMips64RegEnd; i++) {
-      if (mask.HasBit(i)) {
-        snprintf(num, arraysize(num), "%d ", i);
-        strcat(buf, num);
-      }
-    }
-
-    if (mask.HasBit(ResourceMask::kCCode)) {
-      strcat(buf, "cc ");
-    }
-    if (mask.HasBit(ResourceMask::kFPStatus)) {
-      strcat(buf, "fpcc ");
-    }
-    // Memory bits.
-    if (mips64_lir && (mask.HasBit(ResourceMask::kDalvikReg))) {
-      snprintf(buf + strlen(buf), arraysize(buf) - strlen(buf), "dr%d%s",
-               DECODE_ALIAS_INFO_REG(mips64_lir->flags.alias_info),
-               DECODE_ALIAS_INFO_WIDE(mips64_lir->flags.alias_info) ? "(+1)" : "");
-    }
-    if (mask.HasBit(ResourceMask::kLiteral)) {
-      strcat(buf, "lit ");
-    }
-
-    if (mask.HasBit(ResourceMask::kHeapRef)) {
-      strcat(buf, "heap ");
-    }
-    if (mask.HasBit(ResourceMask::kMustNotAlias)) {
-      strcat(buf, "noalias ");
-    }
-  }
-  if (buf[0]) {
-    LOG(INFO) << prefix << ": " <<  buf;
-  }
-}
-
-/*
- * TUNING: is true leaf?  Can't just use METHOD_IS_LEAF to determine as some
- * instructions might call out to C/assembly helper functions.  Until
- * machinery is in place, always spill lr.
- */
-
-void Mips64Mir2Lir::AdjustSpillMask() {
-  core_spill_mask_ |= (1 << rs_rRA.GetRegNum());
-  num_core_spills_++;
-}
-
-/* Clobber all regs that might be used by an external C call */
-void Mips64Mir2Lir::ClobberCallerSave() {
-  Clobber(rs_rZEROd);
-  Clobber(rs_rATd);
-  Clobber(rs_rV0d);
-  Clobber(rs_rV1d);
-  Clobber(rs_rA0d);
-  Clobber(rs_rA1d);
-  Clobber(rs_rA2d);
-  Clobber(rs_rA3d);
-  Clobber(rs_rA4d);
-  Clobber(rs_rA5d);
-  Clobber(rs_rA6d);
-  Clobber(rs_rA7d);
-  Clobber(rs_rT0d);
-  Clobber(rs_rT1d);
-  Clobber(rs_rT2d);
-  Clobber(rs_rT3d);
-  Clobber(rs_rT8d);
-  Clobber(rs_rT9d);
-  Clobber(rs_rK0d);
-  Clobber(rs_rK1d);
-  Clobber(rs_rGPd);
-  Clobber(rs_rFPd);
-  Clobber(rs_rRAd);
-
-  Clobber(rs_rF0);
-  Clobber(rs_rF1);
-  Clobber(rs_rF2);
-  Clobber(rs_rF3);
-  Clobber(rs_rF4);
-  Clobber(rs_rF5);
-  Clobber(rs_rF6);
-  Clobber(rs_rF7);
-  Clobber(rs_rF8);
-  Clobber(rs_rF9);
-  Clobber(rs_rF10);
-  Clobber(rs_rF11);
-  Clobber(rs_rF12);
-  Clobber(rs_rF13);
-  Clobber(rs_rF14);
-  Clobber(rs_rF15);
-  Clobber(rs_rD0);
-  Clobber(rs_rD1);
-  Clobber(rs_rD2);
-  Clobber(rs_rD3);
-  Clobber(rs_rD4);
-  Clobber(rs_rD5);
-  Clobber(rs_rD6);
-  Clobber(rs_rD7);
-}
-
-RegLocation Mips64Mir2Lir::GetReturnWideAlt() {
-  UNIMPLEMENTED(FATAL) << "No GetReturnWideAlt for MIPS64";
-  RegLocation res = LocCReturnWide();
-  return res;
-}
-
-RegLocation Mips64Mir2Lir::GetReturnAlt() {
-  UNIMPLEMENTED(FATAL) << "No GetReturnAlt for MIPS64";
-  RegLocation res = LocCReturn();
-  return res;
-}
-
-/* To be used when explicitly managing register use */
-void Mips64Mir2Lir::LockCallTemps() {
-  LockTemp(rs_rMIPS64_ARG0);
-  LockTemp(rs_rMIPS64_ARG1);
-  LockTemp(rs_rMIPS64_ARG2);
-  LockTemp(rs_rMIPS64_ARG3);
-  LockTemp(rs_rMIPS64_ARG4);
-  LockTemp(rs_rMIPS64_ARG5);
-  LockTemp(rs_rMIPS64_ARG6);
-  LockTemp(rs_rMIPS64_ARG7);
-}
-
-/* To be used when explicitly managing register use */
-void Mips64Mir2Lir::FreeCallTemps() {
-  FreeTemp(rs_rMIPS64_ARG0);
-  FreeTemp(rs_rMIPS64_ARG1);
-  FreeTemp(rs_rMIPS64_ARG2);
-  FreeTemp(rs_rMIPS64_ARG3);
-  FreeTemp(rs_rMIPS64_ARG4);
-  FreeTemp(rs_rMIPS64_ARG5);
-  FreeTemp(rs_rMIPS64_ARG6);
-  FreeTemp(rs_rMIPS64_ARG7);
-  FreeTemp(TargetReg(kHiddenArg));
-}
-
-bool Mips64Mir2Lir::GenMemBarrier(MemBarrierKind barrier_kind ATTRIBUTE_UNUSED) {
-  if (cu_->compiler_driver->GetInstructionSetFeatures()->IsSmp()) {
-    NewLIR1(kMips64Sync, 0 /* Only stype currently supported */);
-    return true;
-  } else {
-    return false;
-  }
-}
-
-void Mips64Mir2Lir::CompilerInitializeRegAlloc() {
-  reg_pool_.reset(new (arena_) RegisterPool(this, arena_, core_regs32, core_regs64 , sp_regs,
-                                        dp_regs, reserved_regs32, reserved_regs64,
-                                        core_temps32, core_temps64, sp_temps,
-                                        dp_temps));
-
-  // Target-specific adjustments.
-
-  // Alias single precision floats to appropriate half of overlapping double.
-  for (RegisterInfo* info : reg_pool_->sp_regs_) {
-    int sp_reg_num = info->GetReg().GetRegNum();
-    int dp_reg_num = sp_reg_num;
-    RegStorage dp_reg = RegStorage::Solo64(RegStorage::kFloatingPoint | dp_reg_num);
-    RegisterInfo* dp_reg_info = GetRegInfo(dp_reg);
-    // Double precision register's master storage should refer to itself.
-    DCHECK_EQ(dp_reg_info, dp_reg_info->Master());
-    // Redirect single precision's master storage to master.
-    info->SetMaster(dp_reg_info);
-    // Singles should show a single 32-bit mask bit, at first referring to the low half.
-    DCHECK_EQ(info->StorageMask(), 0x1U);
-  }
-
-  // Alias 32bit W registers to corresponding 64bit X registers.
-  for (RegisterInfo* info : reg_pool_->core_regs_) {
-    int d_reg_num = info->GetReg().GetRegNum();
-    RegStorage d_reg = RegStorage::Solo64(d_reg_num);
-    RegisterInfo* d_reg_info = GetRegInfo(d_reg);
-    // 64bit D register's master storage should refer to itself.
-    DCHECK_EQ(d_reg_info, d_reg_info->Master());
-    // Redirect 32bit master storage to 64bit D.
-    info->SetMaster(d_reg_info);
-    // 32bit should show a single 32-bit mask bit, at first referring to the low half.
-    DCHECK_EQ(info->StorageMask(), 0x1U);
-  }
-
-  // Don't start allocating temps at r0/s0/d0 or you may clobber return regs in early-exit methods.
-  // TODO: adjust when we roll to hard float calling convention.
-  reg_pool_->next_core_reg_ = 2;
-  reg_pool_->next_sp_reg_ = 2;
-  reg_pool_->next_dp_reg_ = 1;
-}
-
-/*
- * In the Arm code a it is typical to use the link register
- * to hold the target address.  However, for Mips64 we must
- * ensure that all branch instructions can be restarted if
- * there is a trap in the shadow.  Allocate a temp register.
- */
-RegStorage Mips64Mir2Lir::LoadHelper(QuickEntrypointEnum trampoline) {
-  // NOTE: native pointer.
-  LoadWordDisp(rs_rMIPS64_SELF, GetThreadOffset<8>(trampoline).Int32Value(), rs_rT9d);
-  return rs_rT9d;
-}
-
-LIR* Mips64Mir2Lir::CheckSuspendUsingLoad() {
-  RegStorage tmp = AllocTemp();
-  // NOTE: native pointer.
-  LoadWordDisp(rs_rMIPS64_SELF, Thread::ThreadSuspendTriggerOffset<8>().Int32Value(), tmp);
-  LIR *inst = LoadWordDisp(tmp, 0, tmp);
-  FreeTemp(tmp);
-  return inst;
-}
-
-LIR* Mips64Mir2Lir::GenAtomic64Load(RegStorage r_base, int displacement, RegStorage r_dest) {
-  DCHECK(!r_dest.IsFloat());  // See RegClassForFieldLoadStore().
-  ClobberCallerSave();
-  LockCallTemps();  // Using fixed registers.
-  RegStorage reg_ptr = TargetReg(kArg0);
-  OpRegRegImm(kOpAdd, reg_ptr, r_base, displacement);
-  RegStorage r_tgt = LoadHelper(kQuickA64Load);
-  LIR *ret = OpReg(kOpBlx, r_tgt);
-  OpRegCopy(r_dest, TargetReg(kRet0));
-  return ret;
-}
-
-LIR* Mips64Mir2Lir::GenAtomic64Store(RegStorage r_base, int displacement, RegStorage r_src) {
-  DCHECK(!r_src.IsFloat());  // See RegClassForFieldLoadStore().
-  DCHECK(!r_src.IsPair());
-  ClobberCallerSave();
-  LockCallTemps();  // Using fixed registers.
-  RegStorage temp_ptr = AllocTemp();
-  OpRegRegImm(kOpAdd, temp_ptr, r_base, displacement);
-  RegStorage temp_value = AllocTemp();
-  OpRegCopy(temp_value, r_src);
-  OpRegCopy(TargetReg(kArg0), temp_ptr);
-  OpRegCopy(TargetReg(kArg1), temp_value);
-  FreeTemp(temp_ptr);
-  FreeTemp(temp_value);
-  RegStorage r_tgt = LoadHelper(kQuickA64Store);
-  return OpReg(kOpBlx, r_tgt);
-}
-
-void Mips64Mir2Lir::SpillCoreRegs() {
-  if (num_core_spills_ == 0) {
-    return;
-  }
-  uint32_t mask = core_spill_mask_;
-  // Start saving from offset 0 so that ra ends up on the top of the frame.
-  int offset = 0;
-  OpRegImm(kOpSub, rs_rSPd, num_core_spills_ * 8);
-  for (int reg = 0; mask; mask >>= 1, reg++) {
-    if (mask & 0x1) {
-      StoreWordDisp(rs_rMIPS64_SP, offset, RegStorage::Solo64(reg));
-      offset += 8;
-    }
-  }
-}
-
-void Mips64Mir2Lir::UnSpillCoreRegs() {
-  if (num_core_spills_ == 0) {
-    return;
-  }
-  uint32_t mask = core_spill_mask_;
-  int offset = frame_size_ - num_core_spills_ * 8;
-  for (int reg = 0; mask; mask >>= 1, reg++) {
-    if (mask & 0x1) {
-      LoadWordDisp(rs_rMIPS64_SP, offset, RegStorage::Solo64(reg));
-      offset += 8;
-    }
-  }
-  OpRegImm(kOpAdd, rs_rSPd, frame_size_);
-}
-
-bool Mips64Mir2Lir::IsUnconditionalBranch(LIR* lir) {
-  return (lir->opcode == kMips64B);
-}
-
-RegisterClass Mips64Mir2Lir::RegClassForFieldLoadStore(OpSize size, bool is_volatile) {
-  if (UNLIKELY(is_volatile)) {
-    // On Mips64, atomic 64-bit load/store requires a core register.
-    // Smaller aligned load/store is atomic for both core and fp registers.
-    if (size == k64 || size == kDouble) {
-      return kCoreReg;
-    }
-  }
-  // TODO: Verify that both core and fp registers are suitable for smaller sizes.
-  return RegClassBySize(size);
-}
-
-Mips64Mir2Lir::Mips64Mir2Lir(CompilationUnit* cu, MIRGraph* mir_graph, ArenaAllocator* arena)
-    : Mir2Lir(cu, mir_graph, arena), in_to_reg_storage_mips64_mapper_(this) {
-  for (int i = 0; i < kMips64Last; i++) {
-    DCHECK_EQ(Mips64Mir2Lir::EncodingMap[i].opcode, i)
-        << "Encoding order for " << Mips64Mir2Lir::EncodingMap[i].name
-        << " is wrong: expecting " << i << ", seeing "
-        << static_cast<int>(Mips64Mir2Lir::EncodingMap[i].opcode);
-  }
-}
-
-Mir2Lir* Mips64CodeGenerator(CompilationUnit* const cu, MIRGraph* const mir_graph,
-                             ArenaAllocator* const arena) {
-  return new Mips64Mir2Lir(cu, mir_graph, arena);
-}
-
-uint64_t Mips64Mir2Lir::GetTargetInstFlags(int opcode) {
-  DCHECK(!IsPseudoLirOp(opcode));
-  return Mips64Mir2Lir::EncodingMap[opcode].flags;
-}
-
-const char* Mips64Mir2Lir::GetTargetInstName(int opcode) {
-  DCHECK(!IsPseudoLirOp(opcode));
-  return Mips64Mir2Lir::EncodingMap[opcode].name;
-}
-
-const char* Mips64Mir2Lir::GetTargetInstFmt(int opcode) {
-  DCHECK(!IsPseudoLirOp(opcode));
-  return Mips64Mir2Lir::EncodingMap[opcode].fmt;
-}
-
-void Mips64Mir2Lir::GenBreakpoint(int code) {
-    NewLIR1(kMips64Break, code);
-}
-
-}  // namespace art
diff --git a/compiler/dex/quick/mips64/utility_mips64.cc b/compiler/dex/quick/mips64/utility_mips64.cc
deleted file mode 100644
index 38e354c..0000000
--- a/compiler/dex/quick/mips64/utility_mips64.cc
+++ /dev/null
@@ -1,875 +0,0 @@
-/*
- * Copyright (C) 2015 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.
- */
-
-#include "codegen_mips64.h"
-
-#include "arch/mips64/instruction_set_features_mips64.h"
-#include "base/logging.h"
-#include "dex/quick/mir_to_lir-inl.h"
-#include "dex/reg_storage_eq.h"
-#include "driver/compiler_driver.h"
-#include "mips64_lir.h"
-
-namespace art {
-
-/* This file contains codegen for the MIPS64 ISA. */
-
-LIR* Mips64Mir2Lir::OpFpRegCopy(RegStorage r_dest, RegStorage r_src) {
-  int opcode;
-  // Must be both DOUBLE or both not DOUBLE.
-  DCHECK_EQ(r_dest.Is64Bit(), r_src.Is64Bit());
-  if (r_dest.Is64Bit()) {
-    if (r_dest.IsDouble()) {
-      if (r_src.IsDouble()) {
-        opcode = kMips64Fmovd;
-      } else {
-        // Note the operands are swapped for the dmtc1 instr.
-        RegStorage t_opnd = r_src;
-        r_src = r_dest;
-        r_dest = t_opnd;
-        opcode = kMips64Dmtc1;
-      }
-    } else {
-      DCHECK(r_src.IsDouble());
-      opcode = kMips64Dmfc1;
-    }
-  } else {
-    if (r_dest.IsSingle()) {
-      if (r_src.IsSingle()) {
-        opcode = kMips64Fmovs;
-      } else {
-        // Note the operands are swapped for the mtc1 instr.
-        RegStorage t_opnd = r_src;
-        r_src = r_dest;
-        r_dest = t_opnd;
-        opcode = kMips64Mtc1;
-      }
-    } else {
-      DCHECK(r_src.IsSingle());
-      opcode = kMips64Mfc1;
-    }
-  }
-  LIR* res = RawLIR(current_dalvik_offset_, opcode, r_dest.GetReg(), r_src.GetReg());
-  if (!(cu_->disable_opt & (1 << kSafeOptimizations)) && r_dest == r_src) {
-    res->flags.is_nop = true;
-  }
-  return res;
-}
-
-bool Mips64Mir2Lir::InexpensiveConstantInt(int32_t value) {
-  // For encodings, see LoadConstantNoClobber below.
-  return ((value == 0) || IsUint<16>(value) || IsInt<16>(value));
-}
-
-bool Mips64Mir2Lir::InexpensiveConstantFloat(int32_t value) {
-  UNUSED(value);
-  return false;  // TUNING
-}
-
-bool Mips64Mir2Lir::InexpensiveConstantLong(int64_t value) {
-  UNUSED(value);
-  return false;  // TUNING
-}
-
-bool Mips64Mir2Lir::InexpensiveConstantDouble(int64_t value) {
-  UNUSED(value);
-  return false;  // TUNING
-}
-
-/*
- * Load a immediate using a shortcut if possible; otherwise
- * grab from the per-translation literal pool.  If target is
- * a high register, build constant into a low register and copy.
- *
- * No additional register clobbering operation performed. Use this version when
- * 1) r_dest is freshly returned from AllocTemp or
- * 2) The codegen is under fixed register usage
- */
-LIR* Mips64Mir2Lir::LoadConstantNoClobber(RegStorage r_dest, int value) {
-  LIR *res;
-
-  RegStorage r_dest_save = r_dest;
-  int is_fp_reg = r_dest.IsFloat();
-  if (is_fp_reg) {
-    DCHECK(r_dest.IsSingle());
-    r_dest = AllocTemp();
-  }
-
-  // See if the value can be constructed cheaply.
-  if (value == 0) {
-    res = NewLIR2(kMips64Move, r_dest.GetReg(), rZERO);
-  } else if (IsUint<16>(value)) {
-    // Use OR with (unsigned) immediate to encode 16b unsigned int.
-    res = NewLIR3(kMips64Ori, r_dest.GetReg(), rZERO, value);
-  } else if (IsInt<16>(value)) {
-    // Use ADD with (signed) immediate to encode 16b signed int.
-    res = NewLIR3(kMips64Addiu, r_dest.GetReg(), rZERO, value);
-  } else {
-    res = NewLIR2(kMips64Lui, r_dest.GetReg(), value >> 16);
-    if (value & 0xffff)
-      NewLIR3(kMips64Ori, r_dest.GetReg(), r_dest.GetReg(), value);
-  }
-
-  if (is_fp_reg) {
-    NewLIR2(kMips64Mtc1, r_dest.GetReg(), r_dest_save.GetReg());
-    FreeTemp(r_dest);
-  }
-
-  return res;
-}
-
-LIR* Mips64Mir2Lir::OpUnconditionalBranch(LIR* target) {
-  LIR* res = NewLIR1(kMips64B, 0 /* offset to be patched during assembly*/);
-  res->target = target;
-  return res;
-}
-
-LIR* Mips64Mir2Lir::OpReg(OpKind op, RegStorage r_dest_src) {
-  Mips64OpCode opcode = kMips64Nop;
-  switch (op) {
-    case kOpBlx:
-      opcode = kMips64Jalr;
-      break;
-    case kOpBx:
-      return NewLIR2(kMips64Jalr, rZERO, r_dest_src.GetReg());
-      break;
-    default:
-      LOG(FATAL) << "Bad case in OpReg";
-  }
-  return NewLIR2(opcode, rRAd, r_dest_src.GetReg());
-}
-
-LIR* Mips64Mir2Lir::OpRegImm(OpKind op, RegStorage r_dest_src1, int value) {
-  LIR *res;
-  bool neg = (value < 0);
-  int abs_value = (neg) ? -value : value;
-  bool short_form = (abs_value & 0xff) == abs_value;
-  bool is64bit = r_dest_src1.Is64Bit();
-  RegStorage r_scratch;
-  Mips64OpCode opcode = kMips64Nop;
-  switch (op) {
-    case kOpAdd:
-      return OpRegRegImm(op, r_dest_src1, r_dest_src1, value);
-    case kOpSub:
-      return OpRegRegImm(op, r_dest_src1, r_dest_src1, value);
-    default:
-      LOG(FATAL) << "Bad case in OpRegImm";
-  }
-  if (short_form) {
-    res = NewLIR2(opcode, r_dest_src1.GetReg(), abs_value);
-  } else {
-    if (is64bit) {
-      r_scratch = AllocTempWide();
-      res = LoadConstantWide(r_scratch, value);
-    } else {
-      r_scratch = AllocTemp();
-      res = LoadConstant(r_scratch, value);
-    }
-    if (op == kOpCmp) {
-      NewLIR2(opcode, r_dest_src1.GetReg(), r_scratch.GetReg());
-    } else {
-      NewLIR3(opcode, r_dest_src1.GetReg(), r_dest_src1.GetReg(), r_scratch.GetReg());
-    }
-  }
-  return res;
-}
-
-LIR* Mips64Mir2Lir::OpRegRegReg(OpKind op, RegStorage r_dest,
-                                RegStorage r_src1, RegStorage r_src2) {
-  Mips64OpCode opcode = kMips64Nop;
-  bool is64bit = r_dest.Is64Bit() || r_src1.Is64Bit() || r_src2.Is64Bit();
-
-  switch (op) {
-    case kOpAdd:
-      if (is64bit) {
-        opcode = kMips64Daddu;
-      } else {
-        opcode = kMips64Addu;
-      }
-      break;
-    case kOpSub:
-      if (is64bit) {
-        opcode = kMips64Dsubu;
-      } else {
-        opcode = kMips64Subu;
-      }
-      break;
-    case kOpAnd:
-      opcode = kMips64And;
-      break;
-    case kOpMul:
-      opcode = kMips64Mul;
-      break;
-    case kOpOr:
-      opcode = kMips64Or;
-      break;
-    case kOpXor:
-      opcode = kMips64Xor;
-      break;
-    case kOpLsl:
-      if (is64bit) {
-        opcode = kMips64Dsllv;
-      } else {
-        opcode = kMips64Sllv;
-      }
-      break;
-    case kOpLsr:
-      if (is64bit) {
-        opcode = kMips64Dsrlv;
-      } else {
-        opcode = kMips64Srlv;
-      }
-      break;
-    case kOpAsr:
-      if (is64bit) {
-        opcode = kMips64Dsrav;
-      } else {
-        opcode = kMips64Srav;
-      }
-      break;
-    case kOpAdc:
-    case kOpSbc:
-      LOG(FATAL) << "No carry bit on MIPS64";
-      break;
-    default:
-      LOG(FATAL) << "Bad case in OpRegRegReg";
-      break;
-  }
-  return NewLIR3(opcode, r_dest.GetReg(), r_src1.GetReg(), r_src2.GetReg());
-}
-
-LIR* Mips64Mir2Lir::OpRegRegImm(OpKind op, RegStorage r_dest, RegStorage r_src1, int value) {
-  LIR *res;
-  Mips64OpCode opcode = kMips64Nop;
-  bool short_form = true;
-  bool is64bit = r_dest.Is64Bit() || r_src1.Is64Bit();
-
-  switch (op) {
-    case kOpAdd:
-      if (is64bit) {
-        if (IS_SIMM16(value)) {
-          opcode = kMips64Daddiu;
-        } else {
-          short_form = false;
-          opcode = kMips64Daddu;
-        }
-      } else {
-        if (IS_SIMM16(value)) {
-          opcode = kMips64Addiu;
-        } else {
-          short_form = false;
-          opcode = kMips64Addu;
-        }
-      }
-      break;
-    case kOpSub:
-      if (is64bit) {
-        if (IS_SIMM16((-value))) {
-          value = -value;
-          opcode = kMips64Daddiu;
-        } else {
-          short_form = false;
-          opcode = kMips64Dsubu;
-        }
-      } else {
-        if (IS_SIMM16((-value))) {
-          value = -value;
-          opcode = kMips64Addiu;
-        } else {
-          short_form = false;
-          opcode = kMips64Subu;
-        }
-      }
-      break;
-    case kOpLsl:
-      if (is64bit) {
-        DCHECK(value >= 0 && value <= 63);
-        if (value >= 0 && value <= 31) {
-          opcode = kMips64Dsll;
-        } else {
-          opcode = kMips64Dsll32;
-          value = value - 32;
-        }
-      } else {
-        DCHECK(value >= 0 && value <= 31);
-        opcode = kMips64Sll;
-      }
-      break;
-    case kOpLsr:
-      if (is64bit) {
-        DCHECK(value >= 0 && value <= 63);
-        if (value >= 0 && value <= 31) {
-          opcode = kMips64Dsrl;
-        } else {
-          opcode = kMips64Dsrl32;
-          value = value - 32;
-        }
-      } else {
-        DCHECK(value >= 0 && value <= 31);
-        opcode = kMips64Srl;
-      }
-      break;
-    case kOpAsr:
-      if (is64bit) {
-        DCHECK(value >= 0 && value <= 63);
-        if (value >= 0 && value <= 31) {
-          opcode = kMips64Dsra;
-        } else {
-          opcode = kMips64Dsra32;
-          value = value - 32;
-        }
-      } else {
-        DCHECK(value >= 0 && value <= 31);
-        opcode = kMips64Sra;
-      }
-      break;
-    case kOpAnd:
-      if (IS_UIMM16((value))) {
-        opcode = kMips64Andi;
-      } else {
-        short_form = false;
-        opcode = kMips64And;
-      }
-      break;
-    case kOpOr:
-      if (IS_UIMM16((value))) {
-        opcode = kMips64Ori;
-      } else {
-        short_form = false;
-        opcode = kMips64Or;
-      }
-      break;
-    case kOpXor:
-      if (IS_UIMM16((value))) {
-        opcode = kMips64Xori;
-      } else {
-        short_form = false;
-        opcode = kMips64Xor;
-      }
-      break;
-    case kOpMul:
-      short_form = false;
-      opcode = kMips64Mul;
-      break;
-    default:
-      LOG(FATAL) << "Bad case in OpRegRegImm";
-      break;
-  }
-
-  if (short_form) {
-    res = NewLIR3(opcode, r_dest.GetReg(), r_src1.GetReg(), value);
-  } else {
-    if (r_dest != r_src1) {
-      res = LoadConstant(r_dest, value);
-      NewLIR3(opcode, r_dest.GetReg(), r_src1.GetReg(), r_dest.GetReg());
-    } else {
-      if (is64bit) {
-        RegStorage r_scratch = AllocTempWide();
-        res = LoadConstantWide(r_scratch, value);
-        NewLIR3(opcode, r_dest.GetReg(), r_src1.GetReg(), r_scratch.GetReg());
-      } else {
-        RegStorage r_scratch = AllocTemp();
-        res = LoadConstant(r_scratch, value);
-        NewLIR3(opcode, r_dest.GetReg(), r_src1.GetReg(), r_scratch.GetReg());
-      }
-    }
-  }
-  return res;
-}
-
-LIR* Mips64Mir2Lir::OpRegReg(OpKind op, RegStorage r_dest_src1, RegStorage r_src2) {
-  Mips64OpCode opcode = kMips64Nop;
-  LIR *res;
-  switch (op) {
-    case kOpMov:
-      opcode = kMips64Move;
-      break;
-    case kOpMvn:
-      return NewLIR3(kMips64Nor, r_dest_src1.GetReg(), r_src2.GetReg(), rZEROd);
-    case kOpNeg:
-      if (r_dest_src1.Is64Bit())
-        return NewLIR3(kMips64Dsubu, r_dest_src1.GetReg(), rZEROd, r_src2.GetReg());
-      else
-        return NewLIR3(kMips64Subu, r_dest_src1.GetReg(), rZERO, r_src2.GetReg());
-    case kOpAdd:
-    case kOpAnd:
-    case kOpMul:
-    case kOpOr:
-    case kOpSub:
-    case kOpXor:
-      return OpRegRegReg(op, r_dest_src1, r_dest_src1, r_src2);
-    case kOp2Byte:
-      res = NewLIR2(kMips64Seb, r_dest_src1.GetReg(), r_src2.GetReg());
-      return res;
-    case kOp2Short:
-      res = NewLIR2(kMips64Seh, r_dest_src1.GetReg(), r_src2.GetReg());
-      return res;
-    case kOp2Char:
-       return NewLIR3(kMips64Andi, r_dest_src1.GetReg(), r_src2.GetReg(), 0xFFFF);
-    default:
-      LOG(FATAL) << "Bad case in OpRegReg";
-      UNREACHABLE();
-  }
-  return NewLIR2(opcode, r_dest_src1.GetReg(), r_src2.GetReg());
-}
-
-LIR* Mips64Mir2Lir::OpMovRegMem(RegStorage r_dest, RegStorage r_base, int offset,
-                              MoveType move_type) {
-  UNUSED(r_dest, r_base, offset, move_type);
-  UNIMPLEMENTED(FATAL);
-  UNREACHABLE();
-}
-
-LIR* Mips64Mir2Lir::OpMovMemReg(RegStorage r_base, int offset,
-                                RegStorage r_src, MoveType move_type) {
-  UNUSED(r_base, offset, r_src, move_type);
-  UNIMPLEMENTED(FATAL);
-  UNREACHABLE();
-}
-
-LIR* Mips64Mir2Lir::OpCondRegReg(OpKind op, ConditionCode cc,
-                                 RegStorage r_dest, RegStorage r_src) {
-  UNUSED(op, cc, r_dest, r_src);
-  LOG(FATAL) << "Unexpected use of OpCondRegReg for MIPS64";
-  UNREACHABLE();
-}
-
-LIR* Mips64Mir2Lir::LoadConstantWide(RegStorage r_dest, int64_t value) {
-  LIR *res = nullptr;
-  DCHECK(r_dest.Is64Bit());
-  RegStorage r_dest_save = r_dest;
-  int is_fp_reg = r_dest.IsFloat();
-  if (is_fp_reg) {
-    DCHECK(r_dest.IsDouble());
-    r_dest = AllocTemp();
-  }
-
-  int bit31 = (value & UINT64_C(0x80000000)) != 0;
-
-  // Loads with 1 instruction.
-  if (IsUint<16>(value)) {
-    res = NewLIR3(kMips64Ori, r_dest.GetReg(), rZEROd, value);
-  } else if (IsInt<16>(value)) {
-    res = NewLIR3(kMips64Daddiu, r_dest.GetReg(), rZEROd, value);
-  } else if ((value & 0xFFFF) == 0 && IsInt<16>(value >> 16)) {
-    res = NewLIR2(kMips64Lui, r_dest.GetReg(), value >> 16);
-  } else if (IsInt<32>(value)) {
-    // Loads with 2 instructions.
-    res = NewLIR2(kMips64Lui, r_dest.GetReg(), value >> 16);
-    NewLIR3(kMips64Ori, r_dest.GetReg(), r_dest.GetReg(), value);
-  } else if ((value & 0xFFFF0000) == 0 && IsInt<16>(value >> 32)) {
-    res = NewLIR3(kMips64Ori, r_dest.GetReg(), rZEROd, value);
-    NewLIR2(kMips64Dahi, r_dest.GetReg(), value >> 32);
-  } else if ((value & UINT64_C(0xFFFFFFFF0000)) == 0) {
-    res = NewLIR3(kMips64Ori, r_dest.GetReg(), rZEROd, value);
-    NewLIR2(kMips64Dati, r_dest.GetReg(), value >> 48);
-  } else if ((value & 0xFFFF) == 0 && (value >> 32) >= (-32768 - bit31) &&
-             (value >> 32) <= (32767 - bit31)) {
-    res = NewLIR2(kMips64Lui, r_dest.GetReg(), value >> 16);
-    NewLIR2(kMips64Dahi, r_dest.GetReg(), (value >> 32) + bit31);
-  } else if ((value & 0xFFFF) == 0 && ((value >> 31) & 0x1FFFF) == ((0x20000 - bit31) & 0x1FFFF)) {
-    res = NewLIR2(kMips64Lui, r_dest.GetReg(), value >> 16);
-    NewLIR2(kMips64Dati, r_dest.GetReg(), (value >> 48) + bit31);
-  } else {
-    int64_t tmp = value;
-    int shift_cnt = 0;
-    while ((tmp & 1) == 0) {
-      tmp >>= 1;
-      shift_cnt++;
-    }
-
-    if (IsUint<16>(tmp)) {
-      res = NewLIR3(kMips64Ori, r_dest.GetReg(), rZEROd, tmp);
-      NewLIR3((shift_cnt < 32) ? kMips64Dsll : kMips64Dsll32, r_dest.GetReg(), r_dest.GetReg(),
-              shift_cnt & 0x1F);
-    } else if (IsInt<16>(tmp)) {
-      res = NewLIR3(kMips64Daddiu, r_dest.GetReg(), rZEROd, tmp);
-      NewLIR3((shift_cnt < 32) ? kMips64Dsll : kMips64Dsll32, r_dest.GetReg(), r_dest.GetReg(),
-              shift_cnt & 0x1F);
-    } else if (IsInt<32>(tmp)) {
-      // Loads with 3 instructions.
-      res = NewLIR2(kMips64Lui, r_dest.GetReg(), tmp >> 16);
-      NewLIR3(kMips64Ori, r_dest.GetReg(), r_dest.GetReg(), tmp);
-      NewLIR3((shift_cnt < 32) ? kMips64Dsll : kMips64Dsll32, r_dest.GetReg(), r_dest.GetReg(),
-              shift_cnt & 0x1F);
-    } else {
-      tmp = value >> 16;
-      shift_cnt = 16;
-      while ((tmp & 1) == 0) {
-        tmp >>= 1;
-        shift_cnt++;
-      }
-
-      if (IsUint<16>(tmp)) {
-        res = NewLIR3(kMips64Ori, r_dest.GetReg(), rZEROd, tmp);
-        NewLIR3((shift_cnt < 32) ? kMips64Dsll : kMips64Dsll32, r_dest.GetReg(), r_dest.GetReg(),
-                shift_cnt & 0x1F);
-        NewLIR3(kMips64Ori, r_dest.GetReg(), r_dest.GetReg(), value);
-      } else if (IsInt<16>(tmp)) {
-        res = NewLIR3(kMips64Daddiu, r_dest.GetReg(), rZEROd, tmp);
-        NewLIR3((shift_cnt < 32) ? kMips64Dsll : kMips64Dsll32, r_dest.GetReg(), r_dest.GetReg(),
-                shift_cnt & 0x1F);
-        NewLIR3(kMips64Ori, r_dest.GetReg(), r_dest.GetReg(), value);
-      } else {
-        // Loads with 3-4 instructions.
-        uint64_t tmp2 = value;
-        if (((tmp2 >> 16) & 0xFFFF) != 0 || (tmp2 & 0xFFFFFFFF) == 0) {
-          res = NewLIR2(kMips64Lui, r_dest.GetReg(), tmp2 >> 16);
-        }
-        if ((tmp2 & 0xFFFF) != 0) {
-          if (res)
-            NewLIR3(kMips64Ori, r_dest.GetReg(), r_dest.GetReg(), tmp2);
-          else
-            res = NewLIR3(kMips64Ori, r_dest.GetReg(), rZEROd, tmp2);
-        }
-        if (bit31) {
-          tmp2 += UINT64_C(0x100000000);
-        }
-        if (((tmp2 >> 32) & 0xFFFF) != 0) {
-          NewLIR2(kMips64Dahi, r_dest.GetReg(), tmp2 >> 32);
-        }
-        if (tmp2 & UINT64_C(0x800000000000)) {
-          tmp2 += UINT64_C(0x1000000000000);
-        }
-        if ((tmp2 >> 48) != 0) {
-          NewLIR2(kMips64Dati, r_dest.GetReg(), tmp2 >> 48);
-        }
-      }
-    }
-  }
-
-  if (is_fp_reg) {
-    NewLIR2(kMips64Dmtc1, r_dest.GetReg(), r_dest_save.GetReg());
-    FreeTemp(r_dest);
-  }
-
-  return res;
-}
-
-/* Load value from base + scaled index. */
-LIR* Mips64Mir2Lir::LoadBaseIndexed(RegStorage r_base, RegStorage r_index, RegStorage r_dest,
-                                    int scale, OpSize size) {
-  LIR *first = NULL;
-  LIR *res;
-  RegStorage t_reg;
-  Mips64OpCode opcode = kMips64Nop;
-  bool is64bit = r_dest.Is64Bit();
-  if (is64bit) {
-    t_reg = AllocTempWide();
-  } else {
-    t_reg = AllocTemp();
-  }
-
-  if (r_dest.IsFloat()) {
-    DCHECK(r_dest.IsSingle());
-    DCHECK((size == k32) || (size == kSingle) || (size == kReference));
-    size = kSingle;
-  } else if (is64bit) {
-    size = k64;
-  } else {
-    if (size == kSingle)
-      size = k32;
-  }
-
-  if (!scale) {
-    if (is64bit) {
-      first = NewLIR3(kMips64Daddu, t_reg.GetReg() , r_base.GetReg(), r_index.GetReg());
-    } else {
-      first = NewLIR3(kMips64Addu, t_reg.GetReg() , r_base.GetReg(), r_index.GetReg());
-    }
-  } else {
-    first = OpRegRegImm(kOpLsl, t_reg, r_index, scale);
-    NewLIR3(kMips64Daddu, t_reg.GetReg() , r_base.GetReg(), t_reg.GetReg());
-  }
-
-  switch (size) {
-    case k64:
-      opcode = kMips64Ld;
-      break;
-    case kSingle:
-      opcode = kMips64Flwc1;
-      break;
-    case k32:
-    case kReference:
-      opcode = kMips64Lw;
-      break;
-    case kUnsignedHalf:
-      opcode = kMips64Lhu;
-      break;
-    case kSignedHalf:
-      opcode = kMips64Lh;
-      break;
-    case kUnsignedByte:
-      opcode = kMips64Lbu;
-      break;
-    case kSignedByte:
-      opcode = kMips64Lb;
-      break;
-    default:
-      LOG(FATAL) << "Bad case in LoadBaseIndexed";
-  }
-
-  res = NewLIR3(opcode, r_dest.GetReg(), 0, t_reg.GetReg());
-  FreeTemp(t_reg);
-  return (first) ? first : res;
-}
-
-/* Store value base base + scaled index. */
-LIR* Mips64Mir2Lir::StoreBaseIndexed(RegStorage r_base, RegStorage r_index, RegStorage r_src,
-                                     int scale, OpSize size) {
-  LIR *first = NULL;
-  Mips64OpCode opcode = kMips64Nop;
-  RegStorage t_reg = AllocTemp();
-
-  if (r_src.IsFloat()) {
-    DCHECK(r_src.IsSingle());
-    DCHECK((size == k32) || (size == kSingle) || (size == kReference));
-    size = kSingle;
-  } else {
-    if (size == kSingle)
-      size = k32;
-  }
-
-  if (!scale) {
-    first = NewLIR3(kMips64Daddu, t_reg.GetReg() , r_base.GetReg(), r_index.GetReg());
-  } else {
-    first = OpRegRegImm(kOpLsl, t_reg, r_index, scale);
-    NewLIR3(kMips64Daddu, t_reg.GetReg() , r_base.GetReg(), t_reg.GetReg());
-  }
-
-  switch (size) {
-    case kSingle:
-      opcode = kMips64Fswc1;
-      break;
-    case k32:
-    case kReference:
-      opcode = kMips64Sw;
-      break;
-    case kUnsignedHalf:
-    case kSignedHalf:
-      opcode = kMips64Sh;
-      break;
-    case kUnsignedByte:
-    case kSignedByte:
-      opcode = kMips64Sb;
-      break;
-    default:
-      LOG(FATAL) << "Bad case in StoreBaseIndexed";
-  }
-  NewLIR3(opcode, r_src.GetReg(), 0, t_reg.GetReg());
-  return first;
-}
-
-// FIXME: don't split r_dest into 2 containers.
-LIR* Mips64Mir2Lir::LoadBaseDispBody(RegStorage r_base, int displacement, RegStorage r_dest,
-                                     OpSize size) {
-/*
- * Load value from base + displacement.  Optionally perform null check
- * on base (which must have an associated s_reg and MIR).  If not
- * performing null check, incoming MIR can be null. IMPORTANT: this
- * code must not allocate any new temps.  If a new register is needed
- * and base and dest are the same, spill some other register to
- * rlp and then restore.
- */
-  LIR *res;
-  LIR *load = NULL;
-  Mips64OpCode opcode = kMips64Nop;
-  bool short_form = IS_SIMM16(displacement);
-
-  switch (size) {
-    case k64:
-    case kDouble:
-      r_dest = Check64BitReg(r_dest);
-      if (!r_dest.IsFloat())
-        opcode = kMips64Ld;
-      else
-        opcode = kMips64Fldc1;
-      DCHECK_EQ((displacement & 0x3), 0);
-      break;
-    case k32:
-    case kSingle:
-    case kReference:
-      opcode = kMips64Lw;
-      if (r_dest.IsFloat()) {
-        opcode = kMips64Flwc1;
-        DCHECK(r_dest.IsSingle());
-      }
-      DCHECK_EQ((displacement & 0x3), 0);
-      break;
-    case kUnsignedHalf:
-      opcode = kMips64Lhu;
-      DCHECK_EQ((displacement & 0x1), 0);
-      break;
-    case kSignedHalf:
-      opcode = kMips64Lh;
-      DCHECK_EQ((displacement & 0x1), 0);
-      break;
-    case kUnsignedByte:
-      opcode = kMips64Lbu;
-      break;
-    case kSignedByte:
-      opcode = kMips64Lb;
-      break;
-    default:
-      LOG(FATAL) << "Bad case in LoadBaseIndexedBody";
-  }
-
-  if (short_form) {
-    load = res = NewLIR3(opcode, r_dest.GetReg(), displacement, r_base.GetReg());
-  } else {
-    RegStorage r_tmp = (r_base == r_dest) ? AllocTemp() : r_dest;
-    res = OpRegRegImm(kOpAdd, r_tmp, r_base, displacement);
-    load = NewLIR3(opcode, r_dest.GetReg(), 0, r_tmp.GetReg());
-    if (r_tmp != r_dest)
-      FreeTemp(r_tmp);
-  }
-
-  if (mem_ref_type_ == ResourceMask::kDalvikReg) {
-    DCHECK_EQ(r_base, rs_rMIPS64_SP);
-    AnnotateDalvikRegAccess(load, displacement >> 2, true /* is_load */, r_dest.Is64Bit());
-  }
-  return res;
-}
-
-LIR* Mips64Mir2Lir::LoadBaseDisp(RegStorage r_base, int displacement, RegStorage r_dest,
-                                 OpSize size, VolatileKind is_volatile) {
-  if (UNLIKELY(is_volatile == kVolatile && (size == k64 || size == kDouble) &&
-      displacement & 0x7)) {
-    // TODO: use lld/scd instructions for Mips64.
-    // Do atomic 64-bit load.
-    return GenAtomic64Load(r_base, displacement, r_dest);
-  }
-
-  // TODO: base this on target.
-  if (size == kWord) {
-    size = k64;
-  }
-  LIR* load;
-  load = LoadBaseDispBody(r_base, displacement, r_dest, size);
-
-  if (UNLIKELY(is_volatile == kVolatile)) {
-    GenMemBarrier(kLoadAny);
-  }
-
-  return load;
-}
-
-// FIXME: don't split r_dest into 2 containers.
-LIR* Mips64Mir2Lir::StoreBaseDispBody(RegStorage r_base, int displacement, RegStorage r_src,
-                                      OpSize size) {
-  LIR *res;
-  LIR *store = NULL;
-  Mips64OpCode opcode = kMips64Nop;
-  bool short_form = IS_SIMM16(displacement);
-
-  switch (size) {
-    case k64:
-    case kDouble:
-      r_src = Check64BitReg(r_src);
-      if (!r_src.IsFloat())
-        opcode = kMips64Sd;
-      else
-        opcode = kMips64Fsdc1;
-      DCHECK_EQ((displacement & 0x3), 0);
-      break;
-    case k32:
-    case kSingle:
-    case kReference:
-      opcode = kMips64Sw;
-      if (r_src.IsFloat()) {
-        opcode = kMips64Fswc1;
-        DCHECK(r_src.IsSingle());
-      }
-      DCHECK_EQ((displacement & 0x3), 0);
-      break;
-    case kUnsignedHalf:
-    case kSignedHalf:
-      opcode = kMips64Sh;
-      DCHECK_EQ((displacement & 0x1), 0);
-      break;
-    case kUnsignedByte:
-    case kSignedByte:
-      opcode = kMips64Sb;
-      break;
-    default:
-      LOG(FATAL) << "Bad case in StoreBaseDispBody";
-  }
-
-  if (short_form) {
-    store = res = NewLIR3(opcode, r_src.GetReg(), displacement, r_base.GetReg());
-  } else {
-    RegStorage r_scratch = AllocTemp();
-    res = OpRegRegImm(kOpAdd, r_scratch, r_base, displacement);
-    store = NewLIR3(opcode, r_src.GetReg(), 0, r_scratch.GetReg());
-    FreeTemp(r_scratch);
-  }
-
-  if (mem_ref_type_ == ResourceMask::kDalvikReg) {
-    DCHECK_EQ(r_base, rs_rMIPS64_SP);
-    AnnotateDalvikRegAccess(store, displacement >> 2, false /* is_load */, r_src.Is64Bit());
-  }
-
-  return res;
-}
-
-LIR* Mips64Mir2Lir::StoreBaseDisp(RegStorage r_base, int displacement, RegStorage r_src,
-                                  OpSize size, VolatileKind is_volatile) {
-  if (is_volatile == kVolatile) {
-    // Ensure that prior accesses become visible to other threads first.
-    GenMemBarrier(kAnyStore);
-  }
-
-  LIR* store;
-  if (UNLIKELY(is_volatile == kVolatile && (size == k64 || size == kDouble) &&
-      displacement & 0x7)) {
-    // TODO - use lld/scd instructions for Mips64
-    // Do atomic 64-bit load.
-    store = GenAtomic64Store(r_base, displacement, r_src);
-  } else {
-    // TODO: base this on target.
-    if (size == kWord) {
-      size = k64;
-    }
-    store = StoreBaseDispBody(r_base, displacement, r_src, size);
-  }
-
-  if (UNLIKELY(is_volatile == kVolatile)) {
-    // Preserve order with respect to any subsequent volatile loads.
-    // We need StoreLoad, but that generally requires the most expensive barrier.
-    GenMemBarrier(kAnyAny);
-  }
-
-  return store;
-}
-
-LIR* Mips64Mir2Lir::OpMem(OpKind op, RegStorage r_base, int disp) {
-  UNUSED(op, r_base, disp);
-  LOG(FATAL) << "Unexpected use of OpMem for MIPS64";
-  UNREACHABLE();
-}
-
-LIR* Mips64Mir2Lir::OpCondBranch(ConditionCode cc, LIR* target) {
-  UNUSED(cc, target);
-  LOG(FATAL) << "Unexpected use of OpCondBranch for MIPS64";
-  UNREACHABLE();
-}
-
-LIR* Mips64Mir2Lir::InvokeTrampoline(OpKind op, RegStorage r_tgt, QuickEntrypointEnum trampoline) {
-  UNUSED(trampoline);  // The address of the trampoline is already loaded into r_tgt.
-  return OpReg(op, r_tgt);
-}
-
-}  // namespace art
diff --git a/compiler/dex/quick/quick_compiler.cc b/compiler/dex/quick/quick_compiler.cc
index d4ad0c2..8baafc7 100644
--- a/compiler/dex/quick/quick_compiler.cc
+++ b/compiler/dex/quick/quick_compiler.cc
@@ -45,7 +45,6 @@
 #include "dex/quick/arm/backend_arm.h"
 #include "dex/quick/arm64/backend_arm64.h"
 #include "dex/quick/mips/backend_mips.h"
-#include "dex/quick/mips64/backend_mips64.h"
 #include "dex/quick/x86/backend_x86.h"
 
 namespace art {
@@ -814,10 +813,9 @@
       mir_to_lir = Arm64CodeGenerator(cu, cu->mir_graph.get(), &cu->arena);
       break;
     case kMips:
-      mir_to_lir = MipsCodeGenerator(cu, cu->mir_graph.get(), &cu->arena);
-      break;
+      // Fall-through.
     case kMips64:
-      mir_to_lir = Mips64CodeGenerator(cu, cu->mir_graph.get(), &cu->arena);
+      mir_to_lir = MipsCodeGenerator(cu, cu->mir_graph.get(), &cu->arena);
       break;
     case kX86:
       // Fall-through.
diff --git a/compiler/dex/quick_compiler_callbacks.h b/compiler/dex/quick_compiler_callbacks.h
index cdf71b6..d692d26 100644
--- a/compiler/dex/quick_compiler_callbacks.h
+++ b/compiler/dex/quick_compiler_callbacks.h
@@ -27,8 +27,9 @@
 class QuickCompilerCallbacks FINAL : public CompilerCallbacks {
   public:
     QuickCompilerCallbacks(VerificationResults* verification_results,
-                           DexFileToMethodInlinerMap* method_inliner_map)
-        : verification_results_(verification_results),
+                           DexFileToMethodInlinerMap* method_inliner_map,
+                           CompilerCallbacks::CallbackMode mode)
+        : CompilerCallbacks(mode), verification_results_(verification_results),
           method_inliner_map_(method_inliner_map) {
       CHECK(verification_results != nullptr);
       CHECK(method_inliner_map != nullptr);
diff --git a/compiler/driver/compiler_driver_test.cc b/compiler/driver/compiler_driver_test.cc
index a02e25e..5ebc029 100644
--- a/compiler/driver/compiler_driver_test.cc
+++ b/compiler/driver/compiler_driver_test.cc
@@ -41,7 +41,7 @@
     TimingLogger timings("CompilerDriverTest::CompileAll", false, false);
     TimingLogger::ScopedTiming t(__FUNCTION__, &timings);
     compiler_driver_->CompileAll(class_loader,
-                                 Runtime::Current()->GetCompileTimeClassPath(class_loader),
+                                 GetDexFiles(class_loader),
                                  &timings);
     t.NewTiming("MakeAllExecutable");
     MakeAllExecutable(class_loader);
@@ -66,8 +66,7 @@
   }
 
   void MakeAllExecutable(jobject class_loader) {
-    const std::vector<const DexFile*>& class_path
-        = Runtime::Current()->GetCompileTimeClassPath(class_loader);
+    const std::vector<const DexFile*> class_path = GetDexFiles(class_loader);
     for (size_t i = 0; i != class_path.size(); ++i) {
       const DexFile* dex_file = class_path[i];
       CHECK(dex_file != NULL);
diff --git a/compiler/dwarf/debug_frame_opcode_writer.h b/compiler/dwarf/debug_frame_opcode_writer.h
new file mode 100644
index 0000000..cc4ef8f
--- /dev/null
+++ b/compiler/dwarf/debug_frame_opcode_writer.h
@@ -0,0 +1,282 @@
+/*
+ * Copyright (C) 2015 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.
+ */
+
+#ifndef ART_COMPILER_DWARF_DEBUG_FRAME_OPCODE_WRITER_H_
+#define ART_COMPILER_DWARF_DEBUG_FRAME_OPCODE_WRITER_H_
+
+#include "dwarf.h"
+#include "register.h"
+#include "writer.h"
+
+namespace art {
+namespace dwarf {
+
+// Writer for .debug_frame opcodes (DWARF-3).
+// See the DWARF specification for the precise meaning of the opcodes.
+// The writer is very light-weight, however it will do the following for you:
+//  * Choose the most compact encoding of a given opcode.
+//  * Keep track of current state and convert absolute values to deltas.
+//  * Divide by header-defined factors as appropriate.
+template<typename Allocator = std::allocator<uint8_t> >
+class DebugFrameOpCodeWriter : private Writer<Allocator> {
+ public:
+  // To save space, DWARF divides most offsets by header-defined factors.
+  // They are used in integer divisions, so we make them constants.
+  // We usually subtract from stack base pointer, so making the factor
+  // negative makes the encoded values positive and thus easier to encode.
+  static constexpr int kDataAlignmentFactor = -4;
+  static constexpr int kCodeAlignmentFactor = 1;
+
+  // Explicitely advance the program counter to given location.
+  void AdvancePC(int absolute_pc) {
+    DCHECK_GE(absolute_pc, current_pc_);
+    int delta = FactorCodeOffset(absolute_pc - current_pc_);
+    if (delta != 0) {
+      if (delta <= 0x3F) {
+        this->PushUint8(DW_CFA_advance_loc | delta);
+      } else if (delta <= UINT8_MAX) {
+        this->PushUint8(DW_CFA_advance_loc1);
+        this->PushUint8(delta);
+      } else if (delta <= UINT16_MAX) {
+        this->PushUint8(DW_CFA_advance_loc2);
+        this->PushUint16(delta);
+      } else {
+        this->PushUint8(DW_CFA_advance_loc4);
+        this->PushUint32(delta);
+      }
+    }
+    current_pc_ = absolute_pc;
+  }
+
+  // Override this method to automatically advance the PC before each opcode.
+  virtual void ImplicitlyAdvancePC() { }
+
+  // Common alias in assemblers - spill relative to current stack pointer.
+  void RelOffset(Reg reg, int offset) {
+    Offset(reg, offset - current_cfa_offset_);
+  }
+
+  // Common alias in assemblers - increase stack frame size.
+  void AdjustCFAOffset(int delta) {
+    DefCFAOffset(current_cfa_offset_ + delta);
+  }
+
+  // Custom alias - spill many registers based on bitmask.
+  void RelOffsetForMany(Reg reg_base, int offset, uint32_t reg_mask,
+                        int reg_size) {
+    DCHECK(reg_size == 4 || reg_size == 8);
+    for (int i = 0; reg_mask != 0u; reg_mask >>= 1, i++) {
+      if ((reg_mask & 1) != 0u) {
+        RelOffset(Reg(reg_base.num() + i), offset);
+        offset += reg_size;
+      }
+    }
+  }
+
+  // Custom alias - unspill many registers based on bitmask.
+  void RestoreMany(Reg reg_base, uint32_t reg_mask) {
+    for (int i = 0; reg_mask != 0u; reg_mask >>= 1, i++) {
+      if ((reg_mask & 1) != 0u) {
+        Restore(Reg(reg_base.num() + i));
+      }
+    }
+  }
+
+  void Nop() {
+    this->PushUint8(DW_CFA_nop);
+  }
+
+  void Offset(Reg reg, int offset) {
+    ImplicitlyAdvancePC();
+    int factored_offset = FactorDataOffset(offset);  // May change sign.
+    if (factored_offset >= 0) {
+      if (0 <= reg.num() && reg.num() <= 0x3F) {
+        this->PushUint8(DW_CFA_offset | reg.num());
+        this->PushUleb128(factored_offset);
+      } else {
+        this->PushUint8(DW_CFA_offset_extended);
+        this->PushUleb128(reg.num());
+        this->PushUleb128(factored_offset);
+      }
+    } else {
+      uses_dwarf3_features_ = true;
+      this->PushUint8(DW_CFA_offset_extended_sf);
+      this->PushUleb128(reg.num());
+      this->PushSleb128(factored_offset);
+    }
+  }
+
+  void Restore(Reg reg) {
+    ImplicitlyAdvancePC();
+    if (0 <= reg.num() && reg.num() <= 0x3F) {
+      this->PushUint8(DW_CFA_restore | reg.num());
+    } else {
+      this->PushUint8(DW_CFA_restore_extended);
+      this->PushUleb128(reg.num());
+    }
+  }
+
+  void Undefined(Reg reg) {
+    ImplicitlyAdvancePC();
+    this->PushUint8(DW_CFA_undefined);
+    this->PushUleb128(reg.num());
+  }
+
+  void SameValue(Reg reg) {
+    ImplicitlyAdvancePC();
+    this->PushUint8(DW_CFA_same_value);
+    this->PushUleb128(reg.num());
+  }
+
+  // The previous value of "reg" is stored in register "new_reg".
+  void Register(Reg reg, Reg new_reg) {
+    ImplicitlyAdvancePC();
+    this->PushUint8(DW_CFA_register);
+    this->PushUleb128(reg.num());
+    this->PushUleb128(new_reg.num());
+  }
+
+  void RememberState() {
+    // Note that we do not need to advance the PC.
+    this->PushUint8(DW_CFA_remember_state);
+  }
+
+  void RestoreState() {
+    ImplicitlyAdvancePC();
+    this->PushUint8(DW_CFA_restore_state);
+  }
+
+  void DefCFA(Reg reg, int offset) {
+    ImplicitlyAdvancePC();
+    if (offset >= 0) {
+      this->PushUint8(DW_CFA_def_cfa);
+      this->PushUleb128(reg.num());
+      this->PushUleb128(offset);  // Non-factored.
+    } else {
+      uses_dwarf3_features_ = true;
+      this->PushUint8(DW_CFA_def_cfa_sf);
+      this->PushUleb128(reg.num());
+      this->PushSleb128(FactorDataOffset(offset));
+    }
+    current_cfa_offset_ = offset;
+  }
+
+  void DefCFARegister(Reg reg) {
+    ImplicitlyAdvancePC();
+    this->PushUint8(DW_CFA_def_cfa_register);
+    this->PushUleb128(reg.num());
+  }
+
+  void DefCFAOffset(int offset) {
+    if (current_cfa_offset_ != offset) {
+      ImplicitlyAdvancePC();
+      if (offset >= 0) {
+        this->PushUint8(DW_CFA_def_cfa_offset);
+        this->PushUleb128(offset);  // Non-factored.
+      } else {
+        uses_dwarf3_features_ = true;
+        this->PushUint8(DW_CFA_def_cfa_offset_sf);
+        this->PushSleb128(FactorDataOffset(offset));
+      }
+      current_cfa_offset_ = offset;
+    }
+  }
+
+  void ValOffset(Reg reg, int offset) {
+    ImplicitlyAdvancePC();
+    uses_dwarf3_features_ = true;
+    int factored_offset = FactorDataOffset(offset);  // May change sign.
+    if (factored_offset >= 0) {
+      this->PushUint8(DW_CFA_val_offset);
+      this->PushUleb128(reg.num());
+      this->PushUleb128(factored_offset);
+    } else {
+      this->PushUint8(DW_CFA_val_offset_sf);
+      this->PushUleb128(reg.num());
+      this->PushSleb128(factored_offset);
+    }
+  }
+
+  void DefCFAExpression(void* expr, int expr_size) {
+    ImplicitlyAdvancePC();
+    uses_dwarf3_features_ = true;
+    this->PushUint8(DW_CFA_def_cfa_expression);
+    this->PushUleb128(expr_size);
+    this->PushData(expr, expr_size);
+  }
+
+  void Expression(Reg reg, void* expr, int expr_size) {
+    ImplicitlyAdvancePC();
+    uses_dwarf3_features_ = true;
+    this->PushUint8(DW_CFA_expression);
+    this->PushUleb128(reg.num());
+    this->PushUleb128(expr_size);
+    this->PushData(expr, expr_size);
+  }
+
+  void ValExpression(Reg reg, void* expr, int expr_size) {
+    ImplicitlyAdvancePC();
+    uses_dwarf3_features_ = true;
+    this->PushUint8(DW_CFA_val_expression);
+    this->PushUleb128(reg.num());
+    this->PushUleb128(expr_size);
+    this->PushData(expr, expr_size);
+  }
+
+  int GetCurrentCFAOffset() const {
+    return current_cfa_offset_;
+  }
+
+  void SetCurrentCFAOffset(int offset) {
+    current_cfa_offset_ = offset;
+  }
+
+  using Writer<Allocator>::data;
+
+  DebugFrameOpCodeWriter(const Allocator& alloc = Allocator())
+      : Writer<Allocator>(&opcodes_),
+        opcodes_(alloc),
+        current_cfa_offset_(0),
+        current_pc_(0),
+        uses_dwarf3_features_(false) {
+  }
+
+  virtual ~DebugFrameOpCodeWriter() { }
+
+ protected:
+  int FactorDataOffset(int offset) const {
+    DCHECK_EQ(offset % kDataAlignmentFactor, 0);
+    return offset / kDataAlignmentFactor;
+  }
+
+  int FactorCodeOffset(int offset) const {
+    DCHECK_EQ(offset % kCodeAlignmentFactor, 0);
+    return offset / kCodeAlignmentFactor;
+  }
+
+  std::vector<uint8_t, Allocator> opcodes_;
+  int current_cfa_offset_;
+  int current_pc_;
+  bool uses_dwarf3_features_;
+
+ private:
+  DISALLOW_COPY_AND_ASSIGN(DebugFrameOpCodeWriter);
+};
+
+}  // namespace dwarf
+}  // namespace art
+
+#endif  // ART_COMPILER_DWARF_DEBUG_FRAME_OPCODE_WRITER_H_
diff --git a/compiler/dwarf/debug_frame_writer.h b/compiler/dwarf/debug_frame_writer.h
new file mode 100644
index 0000000..6de45f5
--- /dev/null
+++ b/compiler/dwarf/debug_frame_writer.h
@@ -0,0 +1,96 @@
+/*
+ * Copyright (C) 2015 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.
+ */
+
+#ifndef ART_COMPILER_DWARF_DEBUG_FRAME_WRITER_H_
+#define ART_COMPILER_DWARF_DEBUG_FRAME_WRITER_H_
+
+#include "debug_frame_opcode_writer.h"
+#include "dwarf.h"
+#include "writer.h"
+
+namespace art {
+namespace dwarf {
+
+// Writer for the .eh_frame section (which extends .debug_frame specification).
+template<typename Allocator = std::allocator<uint8_t>>
+class DebugFrameWriter FINAL : private Writer<Allocator> {
+ public:
+  void WriteCIE(Reg return_address_register,
+                const uint8_t* initial_opcodes,
+                int initial_opcodes_size) {
+    DCHECK(cie_header_start_ == ~0u);
+    cie_header_start_ = this->data()->size();
+    this->PushUint32(0);  // Length placeholder.
+    this->PushUint32(0);  // CIE id.
+    this->PushUint8(1);   // Version.
+    this->PushString("zR");
+    this->PushUleb128(DebugFrameOpCodeWriter<Allocator>::kCodeAlignmentFactor);
+    this->PushSleb128(DebugFrameOpCodeWriter<Allocator>::kDataAlignmentFactor);
+    this->PushUleb128(return_address_register.num());  // ubyte in DWARF2.
+    this->PushUleb128(1);  // z: Augmentation data size.
+    if (use_64bit_address_) {
+      this->PushUint8(0x04);  // R: ((DW_EH_PE_absptr << 4) | DW_EH_PE_udata8).
+    } else {
+      this->PushUint8(0x03);  // R: ((DW_EH_PE_absptr << 4) | DW_EH_PE_udata4).
+    }
+    this->PushData(initial_opcodes, initial_opcodes_size);
+    this->Pad(use_64bit_address_ ? 8 : 4);
+    this->UpdateUint32(cie_header_start_, this->data()->size() - cie_header_start_ - 4);
+  }
+
+  void WriteCIE(Reg return_address_register,
+                const DebugFrameOpCodeWriter<Allocator>& opcodes) {
+    WriteCIE(return_address_register, opcodes.data()->data(), opcodes.data()->size());
+  }
+
+  void WriteFDE(uint64_t initial_address,
+                uint64_t address_range,
+                const uint8_t* unwind_opcodes,
+                int unwind_opcodes_size) {
+    DCHECK(cie_header_start_ != ~0u);
+    size_t fde_header_start = this->data()->size();
+    this->PushUint32(0);  // Length placeholder.
+    this->PushUint32(this->data()->size() - cie_header_start_);  // 'CIE_pointer'
+    if (use_64bit_address_) {
+      this->PushUint64(initial_address);
+      this->PushUint64(address_range);
+    } else {
+      this->PushUint32(initial_address);
+      this->PushUint32(address_range);
+    }
+    this->PushUleb128(0);  // Augmentation data size.
+    this->PushData(unwind_opcodes, unwind_opcodes_size);
+    this->Pad(use_64bit_address_ ? 8 : 4);
+    this->UpdateUint32(fde_header_start, this->data()->size() - fde_header_start - 4);
+  }
+
+  DebugFrameWriter(std::vector<uint8_t, Allocator>* buffer, bool use_64bit_address)
+      : Writer<Allocator>(buffer),
+        use_64bit_address_(use_64bit_address),
+        cie_header_start_(~0u) {
+  }
+
+ private:
+  bool use_64bit_address_;
+  size_t cie_header_start_;
+
+  DISALLOW_COPY_AND_ASSIGN(DebugFrameWriter);
+};
+
+}  // namespace dwarf
+}  // namespace art
+
+#endif  // ART_COMPILER_DWARF_DEBUG_FRAME_WRITER_H_
diff --git a/compiler/dwarf/debug_line_opcode_writer.h b/compiler/dwarf/debug_line_opcode_writer.h
new file mode 100644
index 0000000..f34acee
--- /dev/null
+++ b/compiler/dwarf/debug_line_opcode_writer.h
@@ -0,0 +1,243 @@
+/*
+ * Copyright (C) 2015 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.
+ */
+
+#ifndef ART_COMPILER_DWARF_DEBUG_LINE_OPCODE_WRITER_H_
+#define ART_COMPILER_DWARF_DEBUG_LINE_OPCODE_WRITER_H_
+
+#include "dwarf.h"
+#include "writer.h"
+
+namespace art {
+namespace dwarf {
+
+// Writer for the .debug_line opcodes (DWARF-3).
+// The writer is very light-weight, however it will do the following for you:
+//  * Choose the most compact encoding of a given opcode.
+//  * Keep track of current state and convert absolute values to deltas.
+//  * Divide by header-defined factors as appropriate.
+template<typename Allocator = std::allocator<uint8_t>>
+class DebugLineOpCodeWriter FINAL : private Writer<Allocator> {
+ public:
+  static constexpr int kOpcodeBase = 13;
+  static constexpr bool kDefaultIsStmt = true;
+  static constexpr int kLineBase = -5;
+  static constexpr int kLineRange = 14;
+
+  void AddRow() {
+    this->PushUint8(DW_LNS_copy);
+  }
+
+  void AdvancePC(uint64_t absolute_address) {
+    DCHECK_NE(current_address_, 0u);  // Use SetAddress for the first advance.
+    DCHECK_GE(absolute_address, current_address_);
+    if (absolute_address != current_address_) {
+      uint64_t delta = FactorCodeOffset(absolute_address - current_address_);
+      if (delta <= INT32_MAX) {
+        this->PushUint8(DW_LNS_advance_pc);
+        this->PushUleb128(static_cast<int>(delta));
+        current_address_ = absolute_address;
+      } else {
+        SetAddress(absolute_address);
+      }
+    }
+  }
+
+  void AdvanceLine(int absolute_line) {
+    int delta = absolute_line - current_line_;
+    if (delta != 0) {
+      this->PushUint8(DW_LNS_advance_line);
+      this->PushSleb128(delta);
+      current_line_ = absolute_line;
+    }
+  }
+
+  void SetFile(int file) {
+    if (current_file_ != file) {
+      this->PushUint8(DW_LNS_set_file);
+      this->PushUleb128(file);
+      current_file_ = file;
+    }
+  }
+
+  void SetColumn(int column) {
+    this->PushUint8(DW_LNS_set_column);
+    this->PushUleb128(column);
+  }
+
+  void NegateStmt() {
+    this->PushUint8(DW_LNS_negate_stmt);
+  }
+
+  void SetBasicBlock() {
+    this->PushUint8(DW_LNS_set_basic_block);
+  }
+
+  void SetPrologueEnd() {
+    uses_dwarf3_features_ = true;
+    this->PushUint8(DW_LNS_set_prologue_end);
+  }
+
+  void SetEpilogueBegin() {
+    uses_dwarf3_features_ = true;
+    this->PushUint8(DW_LNS_set_epilogue_begin);
+  }
+
+  void SetISA(int isa) {
+    uses_dwarf3_features_ = true;
+    this->PushUint8(DW_LNS_set_isa);
+    this->PushUleb128(isa);
+  }
+
+  void EndSequence() {
+    this->PushUint8(0);
+    this->PushUleb128(1);
+    this->PushUint8(DW_LNE_end_sequence);
+    current_address_ = 0;
+    current_file_ = 1;
+    current_line_ = 1;
+  }
+
+  // Uncoditionally set address using the long encoding.
+  // This gives the linker opportunity to relocate the address.
+  void SetAddress(uint64_t absolute_address) {
+    DCHECK_GE(absolute_address, current_address_);
+    FactorCodeOffset(absolute_address);  // Check if it is factorable.
+    this->PushUint8(0);
+    if (use_64bit_address_) {
+      this->PushUleb128(1 + 8);
+      this->PushUint8(DW_LNE_set_address);
+      this->PushUint64(absolute_address);
+    } else {
+      this->PushUleb128(1 + 4);
+      this->PushUint8(DW_LNE_set_address);
+      this->PushUint32(absolute_address);
+    }
+    current_address_ = absolute_address;
+  }
+
+  void DefineFile(const char* filename,
+                  int directory_index,
+                  int modification_time,
+                  int file_size) {
+    int size = 1 +
+               strlen(filename) + 1 +
+               UnsignedLeb128Size(directory_index) +
+               UnsignedLeb128Size(modification_time) +
+               UnsignedLeb128Size(file_size);
+    this->PushUint8(0);
+    this->PushUleb128(size);
+    size_t start = data()->size();
+    this->PushUint8(DW_LNE_define_file);
+    this->PushString(filename);
+    this->PushUleb128(directory_index);
+    this->PushUleb128(modification_time);
+    this->PushUleb128(file_size);
+    DCHECK_EQ(start + size, data()->size());
+  }
+
+  // Compact address and line opcode.
+  void AddRow(uint64_t absolute_address, int absolute_line) {
+    DCHECK_GE(absolute_address, current_address_);
+
+    // If the address is definitely too far, use the long encoding.
+    uint64_t delta_address = FactorCodeOffset(absolute_address - current_address_);
+    if (delta_address > UINT8_MAX) {
+      AdvancePC(absolute_address);
+      delta_address = 0;
+    }
+
+    // If the line is definitely too far, use the long encoding.
+    int delta_line = absolute_line - current_line_;
+    if (!(kLineBase <= delta_line && delta_line < kLineBase + kLineRange)) {
+      AdvanceLine(absolute_line);
+      delta_line = 0;
+    }
+
+    // Both address and line should be reasonable now.  Use the short encoding.
+    int opcode = kOpcodeBase + (delta_line - kLineBase) +
+                 (static_cast<int>(delta_address) * kLineRange);
+    if (opcode > UINT8_MAX) {
+      // If the address is still too far, try to increment it by const amount.
+      int const_advance = (0xFF - kOpcodeBase) / kLineRange;
+      opcode -= (kLineRange * const_advance);
+      if (opcode <= UINT8_MAX) {
+        this->PushUint8(DW_LNS_const_add_pc);
+      } else {
+        // Give up and use long encoding for address.
+        AdvancePC(absolute_address);
+        // Still use the opcode to do line advance and copy.
+        opcode = kOpcodeBase + (delta_line - kLineBase);
+      }
+    }
+    DCHECK(kOpcodeBase <= opcode && opcode <= 0xFF);
+    this->PushUint8(opcode);  // Special opcode.
+    current_line_ = absolute_line;
+    current_address_ = absolute_address;
+  }
+
+  int GetCodeFactorBits() const {
+    return code_factor_bits_;
+  }
+
+  uint64_t CurrentAddress() const {
+    return current_address_;
+  }
+
+  int CurrentFile() const {
+    return current_file_;
+  }
+
+  int CurrentLine() const {
+    return current_line_;
+  }
+
+  using Writer<Allocator>::data;
+
+  DebugLineOpCodeWriter(bool use64bitAddress,
+                        int codeFactorBits,
+                        const Allocator& alloc = Allocator())
+      : Writer<Allocator>(&opcodes_),
+        opcodes_(alloc),
+        uses_dwarf3_features_(false),
+        use_64bit_address_(use64bitAddress),
+        code_factor_bits_(codeFactorBits),
+        current_address_(0),
+        current_file_(1),
+        current_line_(1) {
+  }
+
+ private:
+  uint64_t FactorCodeOffset(uint64_t offset) const {
+    DCHECK_GE(code_factor_bits_, 0);
+    DCHECK_EQ((offset >> code_factor_bits_) << code_factor_bits_, offset);
+    return offset >> code_factor_bits_;
+  }
+
+  std::vector<uint8_t, Allocator> opcodes_;
+  bool uses_dwarf3_features_;
+  bool use_64bit_address_;
+  int code_factor_bits_;
+  uint64_t current_address_;
+  int current_file_;
+  int current_line_;
+
+  DISALLOW_COPY_AND_ASSIGN(DebugLineOpCodeWriter);
+};
+
+}  // namespace dwarf
+}  // namespace art
+
+#endif  // ART_COMPILER_DWARF_DEBUG_LINE_OPCODE_WRITER_H_
diff --git a/compiler/dwarf/debug_line_writer.h b/compiler/dwarf/debug_line_writer.h
new file mode 100644
index 0000000..4b7d8d9
--- /dev/null
+++ b/compiler/dwarf/debug_line_writer.h
@@ -0,0 +1,87 @@
+/*
+ * Copyright (C) 2015 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.
+ */
+
+#ifndef ART_COMPILER_DWARF_DEBUG_LINE_WRITER_H_
+#define ART_COMPILER_DWARF_DEBUG_LINE_WRITER_H_
+
+#include "debug_line_opcode_writer.h"
+#include "dwarf.h"
+#include "writer.h"
+#include <string>
+
+namespace art {
+namespace dwarf {
+
+// Writer for the .debug_line section (DWARF-3).
+template<typename Allocator = std::allocator<uint8_t>>
+class DebugLineWriter FINAL : private Writer<Allocator> {
+ public:
+  struct FileEntry {
+    std::string file_name;
+    int directory_index;
+    int modification_time;
+    int file_size;
+  };
+
+  void WriteTable(const std::vector<std::string>& include_directories,
+                  const std::vector<FileEntry>& files,
+                  const DebugLineOpCodeWriter<Allocator>& opcodes) {
+    size_t header_start = this->data()->size();
+    this->PushUint32(0);  // Section-length placeholder.
+    // Claim DWARF-2 version even though we use some DWARF-3 features.
+    // DWARF-2 consumers will ignore the unknown opcodes.
+    // This is what clang currently does.
+    this->PushUint16(2);  // .debug_line version.
+    size_t header_length_pos = this->data()->size();
+    this->PushUint32(0);  // Header-length placeholder.
+    this->PushUint8(1 << opcodes.GetCodeFactorBits());
+    this->PushUint8(DebugLineOpCodeWriter<Allocator>::kDefaultIsStmt ? 1 : 0);
+    this->PushInt8(DebugLineOpCodeWriter<Allocator>::kLineBase);
+    this->PushUint8(DebugLineOpCodeWriter<Allocator>::kLineRange);
+    this->PushUint8(DebugLineOpCodeWriter<Allocator>::kOpcodeBase);
+    static const int opcode_lengths[DebugLineOpCodeWriter<Allocator>::kOpcodeBase] = {
+        0, 0, 1, 1, 1, 1, 0, 0, 0, 1, 0, 0, 1 };
+    for (int i = 1; i < DebugLineOpCodeWriter<Allocator>::kOpcodeBase; i++) {
+      this->PushUint8(opcode_lengths[i]);
+    }
+    for (const std::string& directory : include_directories) {
+      this->PushData(directory.data(), directory.size() + 1);
+    }
+    this->PushUint8(0);  // Terminate include_directories list.
+    for (const FileEntry& file : files) {
+      this->PushData(file.file_name.data(), file.file_name.size() + 1);
+      this->PushUleb128(file.directory_index);
+      this->PushUleb128(file.modification_time);
+      this->PushUleb128(file.file_size);
+    }
+    this->PushUint8(0);  // Terminate file list.
+    this->UpdateUint32(header_length_pos, this->data()->size() - header_length_pos - 4);
+    this->PushData(opcodes.data()->data(), opcodes.data()->size());
+    this->UpdateUint32(header_start, this->data()->size() - header_start - 4);
+  }
+
+  explicit DebugLineWriter(std::vector<uint8_t, Allocator>* buffer)
+    : Writer<Allocator>(buffer) {
+  }
+
+ private:
+  DISALLOW_COPY_AND_ASSIGN(DebugLineWriter);
+};
+
+}  // namespace dwarf
+}  // namespace art
+
+#endif  // ART_COMPILER_DWARF_DEBUG_LINE_WRITER_H_
diff --git a/compiler/dwarf/dwarf_test.cc b/compiler/dwarf/dwarf_test.cc
new file mode 100644
index 0000000..f3553bc
--- /dev/null
+++ b/compiler/dwarf/dwarf_test.cc
@@ -0,0 +1,235 @@
+/*
+ * Copyright (C) 2015 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.
+ */
+
+#include "dwarf_test.h"
+
+#include "dwarf/debug_frame_opcode_writer.h"
+#include "dwarf/debug_frame_writer.h"
+#include "dwarf/debug_line_opcode_writer.h"
+#include "dwarf/debug_line_writer.h"
+#include "gtest/gtest.h"
+
+namespace art {
+namespace dwarf {
+
+// Run the tests only on host since we need objdump.
+#ifndef HAVE_ANDROID_OS
+
+TEST_F(DwarfTest, DebugFrame) {
+  const bool is64bit = false;
+
+  // Pick offset value which would catch Uleb vs Sleb errors.
+  const int offset = 40000;
+  ASSERT_EQ(UnsignedLeb128Size(offset / 4), 2u);
+  ASSERT_EQ(SignedLeb128Size(offset / 4), 3u);
+  DW_CHECK("Data alignment factor: -4");
+  const Reg reg(6);
+
+  // Test the opcodes in the order mentioned in the spec.
+  // There are usually several encoding variations of each opcode.
+  DebugFrameOpCodeWriter<> opcodes;
+  DW_CHECK("FDE");
+  int pc = 0;
+  for (int i : {0, 1, 0x3F, 0x40, 0xFF, 0x100, 0xFFFF, 0x10000}) {
+    pc += i;
+    opcodes.AdvancePC(pc);
+  }
+  DW_CHECK_NEXT("DW_CFA_advance_loc: 1 to 01000001");
+  DW_CHECK_NEXT("DW_CFA_advance_loc: 63 to 01000040");
+  DW_CHECK_NEXT("DW_CFA_advance_loc1: 64 to 01000080");
+  DW_CHECK_NEXT("DW_CFA_advance_loc1: 255 to 0100017f");
+  DW_CHECK_NEXT("DW_CFA_advance_loc2: 256 to 0100027f");
+  DW_CHECK_NEXT("DW_CFA_advance_loc2: 65535 to 0101027e");
+  DW_CHECK_NEXT("DW_CFA_advance_loc4: 65536 to 0102027e");
+  opcodes.DefCFA(reg, offset);
+  DW_CHECK_NEXT("DW_CFA_def_cfa: r6 (esi) ofs 40000");
+  opcodes.DefCFA(reg, -offset);
+  DW_CHECK_NEXT("DW_CFA_def_cfa_sf: r6 (esi) ofs -40000");
+  opcodes.DefCFARegister(reg);
+  DW_CHECK_NEXT("DW_CFA_def_cfa_register: r6 (esi)");
+  opcodes.DefCFAOffset(offset);
+  DW_CHECK_NEXT("DW_CFA_def_cfa_offset: 40000");
+  opcodes.DefCFAOffset(-offset);
+  DW_CHECK_NEXT("DW_CFA_def_cfa_offset_sf: -40000");
+  uint8_t expr[] = { 0 };
+  opcodes.DefCFAExpression(expr, arraysize(expr));
+  DW_CHECK_NEXT("DW_CFA_def_cfa_expression");
+  opcodes.Undefined(reg);
+  DW_CHECK_NEXT("DW_CFA_undefined: r6 (esi)");
+  opcodes.SameValue(reg);
+  DW_CHECK_NEXT("DW_CFA_same_value: r6 (esi)");
+  opcodes.Offset(Reg(0x3F), -offset);
+  // Bad register likely means that it does not exist on x86,
+  // but we want to test high register numbers anyway.
+  DW_CHECK_NEXT("DW_CFA_offset: bad register: r63 at cfa-40000");
+  opcodes.Offset(Reg(0x40), -offset);
+  DW_CHECK_NEXT("DW_CFA_offset_extended: bad register: r64 at cfa-40000");
+  opcodes.Offset(Reg(0x40), offset);
+  DW_CHECK_NEXT("DW_CFA_offset_extended_sf: bad register: r64 at cfa+40000");
+  opcodes.ValOffset(reg, -offset);
+  DW_CHECK_NEXT("DW_CFA_val_offset: r6 (esi) at cfa-40000");
+  opcodes.ValOffset(reg, offset);
+  DW_CHECK_NEXT("DW_CFA_val_offset_sf: r6 (esi) at cfa+40000");
+  opcodes.Register(reg, Reg(1));
+  DW_CHECK_NEXT("DW_CFA_register: r6 (esi) in r1 (ecx)");
+  opcodes.Expression(reg, expr, arraysize(expr));
+  DW_CHECK_NEXT("DW_CFA_expression: r6 (esi)");
+  opcodes.ValExpression(reg, expr, arraysize(expr));
+  DW_CHECK_NEXT("DW_CFA_val_expression: r6 (esi)");
+  opcodes.Restore(Reg(0x3F));
+  DW_CHECK_NEXT("DW_CFA_restore: bad register: r63");
+  opcodes.Restore(Reg(0x40));
+  DW_CHECK_NEXT("DW_CFA_restore_extended: bad register: r64");
+  opcodes.Restore(reg);
+  DW_CHECK_NEXT("DW_CFA_restore: r6 (esi)");
+  opcodes.RememberState();
+  DW_CHECK_NEXT("DW_CFA_remember_state");
+  opcodes.RestoreState();
+  DW_CHECK_NEXT("DW_CFA_restore_state");
+  opcodes.Nop();
+  DW_CHECK_NEXT("DW_CFA_nop");
+
+  // Also test helpers.
+  opcodes.DefCFA(Reg(4), 100);  // ESP
+  DW_CHECK_NEXT("DW_CFA_def_cfa: r4 (esp) ofs 100");
+  opcodes.AdjustCFAOffset(8);
+  DW_CHECK_NEXT("DW_CFA_def_cfa_offset: 108");
+  opcodes.RelOffset(Reg(0), 0);  // push R0
+  DW_CHECK_NEXT("DW_CFA_offset: r0 (eax) at cfa-108");
+  opcodes.RelOffset(Reg(1), 4);  // push R1
+  DW_CHECK_NEXT("DW_CFA_offset: r1 (ecx) at cfa-104");
+  opcodes.RelOffsetForMany(Reg(2), 8, 1 | (1 << 3), 4);  // push R2 and R5
+  DW_CHECK_NEXT("DW_CFA_offset: r2 (edx) at cfa-100");
+  DW_CHECK_NEXT("DW_CFA_offset: r5 (ebp) at cfa-96");
+  opcodes.RestoreMany(Reg(2), 1 | (1 << 3));  // pop R2 and R5
+  DW_CHECK_NEXT("DW_CFA_restore: r2 (edx)");
+  DW_CHECK_NEXT("DW_CFA_restore: r5 (ebp)");
+
+  DebugFrameWriter<> eh_frame(&eh_frame_data_, is64bit);
+  DebugFrameOpCodeWriter<> initial_opcodes;
+  eh_frame.WriteCIE(Reg(is64bit ? 16 : 8),  // Return address register.
+                    initial_opcodes);  // Initial opcodes.
+  eh_frame.WriteFDE(0x01000000, 0x01000000,
+                    opcodes.data()->data(), opcodes.data()->size());
+  CheckObjdumpOutput(is64bit, "-W");
+}
+
+TEST_F(DwarfTest, DebugFrame64) {
+  const bool is64bit = true;
+  DebugFrameWriter<> eh_frame(&eh_frame_data_, is64bit);
+  DebugFrameOpCodeWriter<> no_opcodes;
+  eh_frame.WriteCIE(Reg(16), no_opcodes);
+  eh_frame.WriteFDE(0x0100000000000000, 0x0200000000000000,
+                    no_opcodes.data()->data(), no_opcodes.data()->size());
+  DW_CHECK("FDE cie=00000000 pc=100000000000000..300000000000000");
+  CheckObjdumpOutput(is64bit, "-W");
+}
+
+TEST_F(DwarfTest, DebugLine) {
+  const bool is64bit = false;
+  const int code_factor_bits = 1;
+  DebugLineOpCodeWriter<> opcodes(is64bit, code_factor_bits);
+
+  std::vector<std::string> include_directories;
+  include_directories.push_back("/path/to/source");
+  DW_CHECK("/path/to/source");
+
+  std::vector<DebugLineWriter<>::FileEntry> files {
+    { "file0.c", 0, 1000, 2000 },
+    { "file1.c", 1, 1000, 2000 },
+    { "file2.c", 1, 1000, 2000 },
+  };
+  DW_CHECK("1\t0\t1000\t2000\tfile0.c");
+  DW_CHECK_NEXT("2\t1\t1000\t2000\tfile1.c");
+  DW_CHECK_NEXT("3\t1\t1000\t2000\tfile2.c");
+
+  DW_CHECK("Line Number Statements");
+  opcodes.SetAddress(0x01000000);
+  DW_CHECK_NEXT("Extended opcode 2: set Address to 0x1000000");
+  opcodes.AddRow();
+  DW_CHECK_NEXT("Copy");
+  opcodes.AdvancePC(0x01000100);
+  DW_CHECK_NEXT("Advance PC by 256 to 0x1000100");
+  opcodes.SetFile(2);
+  DW_CHECK_NEXT("Set File Name to entry 2 in the File Name Table");
+  opcodes.AdvanceLine(3);
+  DW_CHECK_NEXT("Advance Line by 2 to 3");
+  opcodes.SetColumn(4);
+  DW_CHECK_NEXT("Set column to 4");
+  opcodes.NegateStmt();
+  DW_CHECK_NEXT("Set is_stmt to 0");
+  opcodes.SetBasicBlock();
+  DW_CHECK_NEXT("Set basic block");
+  opcodes.SetPrologueEnd();
+  DW_CHECK_NEXT("Set prologue_end to true");
+  opcodes.SetEpilogueBegin();
+  DW_CHECK_NEXT("Set epilogue_begin to true");
+  opcodes.SetISA(5);
+  DW_CHECK_NEXT("Set ISA to 5");
+  opcodes.EndSequence();
+  DW_CHECK_NEXT("Extended opcode 1: End of Sequence");
+  opcodes.DefineFile("file.c", 0, 1000, 2000);
+  DW_CHECK_NEXT("Extended opcode 3: define new File Table entry");
+  DW_CHECK_NEXT("Entry\tDir\tTime\tSize\tName");
+  DW_CHECK_NEXT("1\t0\t1000\t2000\tfile.c");
+
+  DebugLineWriter<> debug_line(&debug_line_data_);
+  debug_line.WriteTable(include_directories, files, opcodes);
+  CheckObjdumpOutput(is64bit, "-W");
+}
+
+// DWARF has special one byte codes which advance PC and line at the same time.
+TEST_F(DwarfTest, DebugLineSpecialOpcodes) {
+  const bool is64bit = false;
+  const int code_factor_bits = 1;
+  uint32_t pc = 0x01000000;
+  int line = 1;
+  DebugLineOpCodeWriter<> opcodes(is64bit, code_factor_bits);
+  opcodes.SetAddress(pc);
+  size_t num_rows = 0;
+  DW_CHECK("Line Number Statements:");
+  DW_CHECK("Special opcode");
+  DW_CHECK("Advance PC by constant");
+  DW_CHECK("Decoded dump of debug contents of section .debug_line:");
+  DW_CHECK("Line number    Starting address");
+  for (int addr_delta = 0; addr_delta < 80; addr_delta += 2) {
+    for (int line_delta = 16; line_delta >= -16; --line_delta) {
+      pc += addr_delta;
+      line += line_delta;
+      opcodes.AddRow(pc, line);
+      num_rows++;
+      ASSERT_EQ(opcodes.CurrentAddress(), pc);
+      ASSERT_EQ(opcodes.CurrentLine(), line);
+      char expected[1024];
+      sprintf(expected, "%i           0x%x", line, pc);
+      DW_CHECK_NEXT(expected);
+    }
+  }
+  EXPECT_LT(opcodes.data()->size(), num_rows * 3);
+
+  std::vector<std::string> directories;
+  std::vector<DebugLineWriter<>::FileEntry> files {
+    { "file.c", 0, 1000, 2000 },
+  };
+  DebugLineWriter<> debug_line(&debug_line_data_);
+  debug_line.WriteTable(directories, files, opcodes);
+  CheckObjdumpOutput(is64bit, "-W -WL");
+}
+
+#endif  // HAVE_ANDROID_OS
+
+}  // namespace dwarf
+}  // namespace art
diff --git a/compiler/dwarf/dwarf_test.h b/compiler/dwarf/dwarf_test.h
new file mode 100644
index 0000000..dd5e0c2
--- /dev/null
+++ b/compiler/dwarf/dwarf_test.h
@@ -0,0 +1,220 @@
+/*
+ * Copyright (C) 2015 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.
+ */
+
+#ifndef ART_COMPILER_DWARF_DWARF_TEST_H_
+#define ART_COMPILER_DWARF_DWARF_TEST_H_
+
+#include <cstring>
+#include <dirent.h>
+#include <memory>
+#include <set>
+#include <stdio.h>
+#include <string>
+#include <sys/types.h>
+
+#include "utils.h"
+#include "base/unix_file/fd_file.h"
+#include "common_runtime_test.h"
+#include "elf_builder.h"
+#include "gtest/gtest.h"
+#include "os.h"
+
+namespace art {
+namespace dwarf {
+
+#define DW_CHECK(substring) Check(substring, false, __FILE__, __LINE__)
+#define DW_CHECK_NEXT(substring) Check(substring, true, __FILE__, __LINE__)
+
+class DwarfTest : public CommonRuntimeTest {
+ public:
+  static constexpr bool kPrintObjdumpOutput = false;  // debugging.
+
+  struct ExpectedLine {
+    std::string substring;
+    bool next;
+    const char* at_file;
+    int at_line;
+  };
+
+  // Check that the objdump output contains given output.
+  // If next is true, it must be the next line.  Otherwise lines are skipped.
+  void Check(const char* substr, bool next, const char* at_file, int at_line) {
+    expected_lines_.push_back(ExpectedLine {substr, next, at_file, at_line});
+  }
+
+  static std::string GetObjdumpPath() {
+    const char* android_build_top = getenv("ANDROID_BUILD_TOP");
+    if (android_build_top != nullptr) {
+      std::string host_prebuilts = std::string(android_build_top) +
+                                   "/prebuilts/gcc/linux-x86/host/";
+      // Read the content of the directory.
+      std::set<std::string> entries;
+      DIR* dir = opendir(host_prebuilts.c_str());
+      if (dir != nullptr) {
+        struct dirent* entry;
+        while ((entry = readdir(dir)) != nullptr) {
+          if (strstr(entry->d_name, "linux-glibc")) {
+            entries.insert(host_prebuilts + entry->d_name);
+          }
+        }
+        closedir(dir);
+      }
+      // Strings are sorted so the last one should be the most recent version.
+      if (!entries.empty()) {
+        std::string path = *entries.rbegin() + "/x86_64-linux/bin/objdump";
+        struct stat st;
+        if (stat(path.c_str(), &st) == 0) {
+          return path;  // File exists.
+        }
+      }
+    }
+    ADD_FAILURE() << "Can not find prebuild objdump.";
+    return "objdump";  // Use the system objdump as fallback.
+  }
+
+  // Pretty-print the generated DWARF data using objdump.
+  template<typename Elf_Word, typename Elf_Sword, typename Elf_Addr, typename Elf_Dyn,
+           typename Elf_Sym, typename Elf_Ehdr, typename Elf_Phdr, typename Elf_Shdr>
+  std::vector<std::string> Objdump(bool is64bit, const char* args) {
+    // Write simple elf file with just the DWARF sections.
+    class NoCode : public CodeOutput {
+      virtual void SetCodeOffset(size_t) { }
+      virtual bool Write(OutputStream*) { return true; }
+    } code;
+    ScratchFile file;
+    InstructionSet isa = is64bit ? kX86_64 : kX86;
+    ElfBuilder<Elf_Word, Elf_Sword, Elf_Addr, Elf_Dyn,
+               Elf_Sym, Elf_Ehdr, Elf_Phdr, Elf_Shdr> builder(
+        &code, file.GetFile(), isa, 0, 0, 0, 0, 0, 0, false, false);
+    typedef ElfRawSectionBuilder<Elf_Word, Elf_Sword, Elf_Shdr> Section;
+    if (!debug_info_data_.empty()) {
+      Section debug_info(".debug_info", SHT_PROGBITS, 0, nullptr, 0, 1, 0);
+      debug_info.SetBuffer(debug_info_data_);
+      builder.RegisterRawSection(debug_info);
+    }
+    if (!debug_abbrev_data_.empty()) {
+      Section debug_abbrev(".debug_abbrev", SHT_PROGBITS, 0, nullptr, 0, 1, 0);
+      debug_abbrev.SetBuffer(debug_abbrev_data_);
+      builder.RegisterRawSection(debug_abbrev);
+    }
+    if (!debug_str_data_.empty()) {
+      Section debug_str(".debug_str", SHT_PROGBITS, 0, nullptr, 0, 1, 0);
+      debug_str.SetBuffer(debug_str_data_);
+      builder.RegisterRawSection(debug_str);
+    }
+    if (!debug_line_data_.empty()) {
+      Section debug_line(".debug_line", SHT_PROGBITS, 0, nullptr, 0, 1, 0);
+      debug_line.SetBuffer(debug_line_data_);
+      builder.RegisterRawSection(debug_line);
+    }
+    if (!eh_frame_data_.empty()) {
+      Section eh_frame(".eh_frame", SHT_PROGBITS, SHF_ALLOC, nullptr, 0, 4, 0);
+      eh_frame.SetBuffer(eh_frame_data_);
+      builder.RegisterRawSection(eh_frame);
+    }
+    builder.Init();
+    builder.Write();
+
+    // Read the elf file back using objdump.
+    std::vector<std::string> lines;
+    std::string cmd = GetObjdumpPath();
+    cmd = cmd + " " + args + " " + file.GetFilename() + " 2>&1";
+    FILE* output = popen(cmd.data(), "r");
+    char buffer[1024];
+    const char* line;
+    while ((line = fgets(buffer, sizeof(buffer), output)) != nullptr) {
+      if (kPrintObjdumpOutput) {
+        printf("%s", line);
+      }
+      if (line[0] != '\0' && line[0] != '\n') {
+        EXPECT_TRUE(strstr(line, "objdump: Error:") == nullptr) << line;
+        EXPECT_TRUE(strstr(line, "objdump: Warning:") == nullptr) << line;
+        std::string str(line);
+        if (str.back() == '\n') {
+          str.pop_back();
+        }
+        lines.push_back(str);
+      }
+    }
+    pclose(output);
+    return lines;
+  }
+
+  std::vector<std::string> Objdump(bool is64bit, const char* args) {
+    if (is64bit) {
+      return Objdump<Elf64_Word, Elf64_Sword, Elf64_Addr, Elf64_Dyn,
+          Elf64_Sym, Elf64_Ehdr, Elf64_Phdr, Elf64_Shdr>(is64bit, args);
+    } else {
+      return Objdump<Elf32_Word, Elf32_Sword, Elf32_Addr, Elf32_Dyn,
+          Elf32_Sym, Elf32_Ehdr, Elf32_Phdr, Elf32_Shdr>(is64bit, args);
+    }
+  }
+
+  // Compare objdump output to the recorded checks.
+  void CheckObjdumpOutput(bool is64bit, const char* args) {
+    std::vector<std::string> actual_lines = Objdump(is64bit, args);
+    auto actual_line = actual_lines.begin();
+    for (const ExpectedLine& expected_line : expected_lines_) {
+      const std::string& substring = expected_line.substring;
+      if (actual_line == actual_lines.end()) {
+        ADD_FAILURE_AT(expected_line.at_file, expected_line.at_line) <<
+            "Expected '" << substring << "'.\n" <<
+            "Seen end of output.";
+      } else if (expected_line.next) {
+        if (actual_line->find(substring) == std::string::npos) {
+          ADD_FAILURE_AT(expected_line.at_file, expected_line.at_line) <<
+            "Expected '" << substring << "'.\n" <<
+            "Seen '" << actual_line->data() << "'.";
+        } else {
+          // printf("Found '%s' in '%s'.\n", substring.data(), actual_line->data());
+        }
+        actual_line++;
+      } else {
+        bool found = false;
+        for (auto it = actual_line; it < actual_lines.end(); it++) {
+          if (it->find(substring) != std::string::npos) {
+            actual_line = it;
+            found = true;
+            break;
+          }
+        }
+        if (!found) {
+          ADD_FAILURE_AT(expected_line.at_file, expected_line.at_line) <<
+            "Expected '" << substring << "'.\n" <<
+            "Not found anywhere in the rest of the output.";
+        } else {
+          // printf("Found '%s' in '%s'.\n", substring.data(), actual_line->data());
+          actual_line++;
+        }
+      }
+    }
+  }
+
+  // Buffers which are going to assembled into ELF file and passed to objdump.
+  std::vector<uint8_t> eh_frame_data_;
+  std::vector<uint8_t> debug_info_data_;
+  std::vector<uint8_t> debug_abbrev_data_;
+  std::vector<uint8_t> debug_str_data_;
+  std::vector<uint8_t> debug_line_data_;
+
+  // The expected output of objdump.
+  std::vector<ExpectedLine> expected_lines_;
+};
+
+}  // namespace dwarf
+}  // namespace art
+
+#endif  // ART_COMPILER_DWARF_DWARF_TEST_H_
diff --git a/compiler/dwarf/register.h b/compiler/dwarf/register.h
new file mode 100644
index 0000000..fa666df
--- /dev/null
+++ b/compiler/dwarf/register.h
@@ -0,0 +1,58 @@
+/*
+ * Copyright (C) 2015 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.
+ */
+
+#ifndef ART_COMPILER_DWARF_REGISTER_H_
+#define ART_COMPILER_DWARF_REGISTER_H_
+
+namespace art {
+namespace dwarf {
+
+// Represents DWARF register.
+class Reg {
+ public:
+  explicit Reg(int reg_num) : num_(reg_num) { }
+  int num() const { return num_; }
+
+  // TODO: Arm S0–S31 register mapping is obsolescent.
+  //   We should use VFP-v3/Neon D0-D31 mapping instead.
+  //   However, D0 is aliased to pair of S0 and S1, so using that
+  //   mapping we can not easily say S0 is spilled and S1 is not.
+  //   There are ways around this in DWARF but they are complex.
+  //   It would be much simpler to always spill whole D registers.
+  //   Arm64 mapping is correct since we already do this there.
+
+  static Reg ArmCore(int num) { return Reg(num); }
+  static Reg ArmFp(int num) { return Reg(64 + num); }  // S0–S31.
+  static Reg Arm64Core(int num) { return Reg(num); }
+  static Reg Arm64Fp(int num) { return Reg(64 + num); }  // V0-V31.
+  static Reg MipsCore(int num) { return Reg(num); }
+  static Reg Mips64Core(int num) { return Reg(num); }
+  static Reg X86Core(int num) { return Reg(num); }
+  static Reg X86Fp(int num) { return Reg(21 + num); }
+  static Reg X86_64Core(int num) {
+    static const int map[8] = {0, 2, 1, 3, 7, 6, 4, 5};
+    return Reg(num < 8 ? map[num] : num);
+  }
+  static Reg X86_64Fp(int num) { return Reg(17 + num); }
+
+ private:
+  int num_;
+};
+
+}  // namespace dwarf
+}  // namespace art
+
+#endif  // ART_COMPILER_DWARF_REGISTER_H_
diff --git a/compiler/dwarf/writer.h b/compiler/dwarf/writer.h
new file mode 100644
index 0000000..d8e29f0
--- /dev/null
+++ b/compiler/dwarf/writer.h
@@ -0,0 +1,159 @@
+/*
+ * Copyright (C) 2015 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.
+ */
+
+#ifndef ART_COMPILER_DWARF_WRITER_H_
+#define ART_COMPILER_DWARF_WRITER_H_
+
+#include <vector>
+#include "leb128.h"
+#include "base/logging.h"
+#include "utils.h"
+
+namespace art {
+namespace dwarf {
+
+// The base class for all DWARF writers.
+template<typename Allocator = std::allocator<uint8_t>>
+class Writer {
+ public:
+  void PushUint8(int value) {
+    DCHECK_GE(value, 0);
+    DCHECK_LE(value, UINT8_MAX);
+    data_->push_back(value & 0xff);
+  }
+
+  void PushUint16(int value) {
+    DCHECK_GE(value, 0);
+    DCHECK_LE(value, UINT16_MAX);
+    data_->push_back((value >> 0) & 0xff);
+    data_->push_back((value >> 8) & 0xff);
+  }
+
+  void PushUint32(uint32_t value) {
+    data_->push_back((value >> 0) & 0xff);
+    data_->push_back((value >> 8) & 0xff);
+    data_->push_back((value >> 16) & 0xff);
+    data_->push_back((value >> 24) & 0xff);
+  }
+
+  void PushUint32(int value) {
+    DCHECK_GE(value, 0);
+    PushUint32(static_cast<uint32_t>(value));
+  }
+
+  void PushUint32(uint64_t value) {
+    DCHECK_LE(value, UINT32_MAX);
+    PushUint32(static_cast<uint32_t>(value));
+  }
+
+  void PushUint64(uint64_t value) {
+    data_->push_back((value >> 0) & 0xff);
+    data_->push_back((value >> 8) & 0xff);
+    data_->push_back((value >> 16) & 0xff);
+    data_->push_back((value >> 24) & 0xff);
+    data_->push_back((value >> 32) & 0xff);
+    data_->push_back((value >> 40) & 0xff);
+    data_->push_back((value >> 48) & 0xff);
+    data_->push_back((value >> 56) & 0xff);
+  }
+
+  void PushInt8(int value) {
+    DCHECK_GE(value, INT8_MIN);
+    DCHECK_LE(value, INT8_MAX);
+    PushUint8(static_cast<uint8_t>(value));
+  }
+
+  void PushInt16(int value) {
+    DCHECK_GE(value, INT16_MIN);
+    DCHECK_LE(value, INT16_MAX);
+    PushUint16(static_cast<uint16_t>(value));
+  }
+
+  void PushInt32(int value) {
+    PushUint32(static_cast<uint32_t>(value));
+  }
+
+  void PushInt64(int64_t value) {
+    PushUint64(static_cast<uint64_t>(value));
+  }
+
+  // Variable-length encoders.
+
+  void PushUleb128(uint32_t value) {
+    EncodeUnsignedLeb128(data_, value);
+  }
+
+  void PushUleb128(int value) {
+    DCHECK_GE(value, 0);
+    EncodeUnsignedLeb128(data_, value);
+  }
+
+  void PushSleb128(int value) {
+    EncodeSignedLeb128(data_, value);
+  }
+
+  // Miscellaneous functions.
+
+  void PushString(const char* value) {
+    data_->insert(data_->end(), value, value + strlen(value) + 1);
+  }
+
+  void PushData(const void* ptr, size_t size) {
+    const char* p = reinterpret_cast<const char*>(ptr);
+    data_->insert(data_->end(), p, p + size);
+  }
+
+  void UpdateUint32(size_t offset, uint32_t value) {
+    DCHECK_LT(offset + 3, data_->size());
+    (*data_)[offset + 0] = (value >> 0) & 0xFF;
+    (*data_)[offset + 1] = (value >> 8) & 0xFF;
+    (*data_)[offset + 2] = (value >> 16) & 0xFF;
+    (*data_)[offset + 3] = (value >> 24) & 0xFF;
+  }
+
+  void UpdateUint64(size_t offset, uint64_t value) {
+    DCHECK_LT(offset + 7, data_->size());
+    (*data_)[offset + 0] = (value >> 0) & 0xFF;
+    (*data_)[offset + 1] = (value >> 8) & 0xFF;
+    (*data_)[offset + 2] = (value >> 16) & 0xFF;
+    (*data_)[offset + 3] = (value >> 24) & 0xFF;
+    (*data_)[offset + 4] = (value >> 32) & 0xFF;
+    (*data_)[offset + 5] = (value >> 40) & 0xFF;
+    (*data_)[offset + 6] = (value >> 48) & 0xFF;
+    (*data_)[offset + 7] = (value >> 56) & 0xFF;
+  }
+
+  void Pad(int alignment) {
+    DCHECK_NE(alignment, 0);
+    data_->resize(RoundUp(data_->size(), alignment), 0);
+  }
+
+  const std::vector<uint8_t, Allocator>* data() const {
+    return data_;
+  }
+
+  explicit Writer(std::vector<uint8_t, Allocator>* buffer) : data_(buffer) { }
+
+ private:
+  std::vector<uint8_t, Allocator>* data_;
+
+  DISALLOW_COPY_AND_ASSIGN(Writer);
+};
+
+}  // namespace dwarf
+}  // namespace art
+
+#endif  // ART_COMPILER_DWARF_WRITER_H_
diff --git a/compiler/elf_writer_test.cc b/compiler/elf_writer_test.cc
index fd3a912..8e2d175 100644
--- a/compiler/elf_writer_test.cc
+++ b/compiler/elf_writer_test.cc
@@ -46,11 +46,7 @@
     EXPECT_EQ(expected_value, ef->FindDynamicSymbolAddress(symbol_name)); \
   } while (false)
 
-#if defined(ART_USE_OPTIMIZING_COMPILER)
-TEST_F(ElfWriterTest, DISABLED_dlsym) {
-#else
 TEST_F(ElfWriterTest, dlsym) {
-#endif
   std::string elf_location = GetCoreOatLocation();
   std::string elf_filename = GetSystemImageFilename(elf_location.c_str(), kRuntimeISA);
   LOG(INFO) << "elf_filename=" << elf_filename;
diff --git a/compiler/jit/jit_compiler.cc b/compiler/jit/jit_compiler.cc
index 8b31154..df5d5cc 100644
--- a/compiler/jit/jit_compiler.cc
+++ b/compiler/jit/jit_compiler.cc
@@ -89,7 +89,8 @@
   verification_results_.reset(new VerificationResults(compiler_options_.get()));
   method_inliner_map_.reset(new DexFileToMethodInlinerMap);
   callbacks_.reset(new QuickCompilerCallbacks(verification_results_.get(),
-                                              method_inliner_map_.get()));
+                                              method_inliner_map_.get(),
+                                              CompilerCallbacks::CallbackMode::kCompileApp));
   compiler_driver_.reset(new CompilerDriver(
       compiler_options_.get(), verification_results_.get(), method_inliner_map_.get(),
       Compiler::kQuick, instruction_set, instruction_set_features_.get(), false,
diff --git a/compiler/oat_test.cc b/compiler/oat_test.cc
index 728da27..503068c 100644
--- a/compiler/oat_test.cc
+++ b/compiler/oat_test.cc
@@ -88,8 +88,6 @@
   compiler_options_.reset(new CompilerOptions);
   verification_results_.reset(new VerificationResults(compiler_options_.get()));
   method_inliner_map_.reset(new DexFileToMethodInlinerMap);
-  callbacks_.reset(new QuickCompilerCallbacks(verification_results_.get(),
-                                              method_inliner_map_.get()));
   timer_.reset(new CumulativeLogger("Compilation times"));
   compiler_driver_.reset(new CompilerDriver(compiler_options_.get(),
                                             verification_results_.get(),
diff --git a/compiler/optimizing/boolean_simplifier.cc b/compiler/optimizing/boolean_simplifier.cc
index e9ca042..be432c5 100644
--- a/compiler/optimizing/boolean_simplifier.cc
+++ b/compiler/optimizing/boolean_simplifier.cc
@@ -59,7 +59,8 @@
       return new (allocator) HGreaterThan(lhs, rhs);
     } else if (cond->IsGreaterThan()) {
       return new (allocator) HLessThanOrEqual(lhs, rhs);
-    } else if (cond->IsGreaterThanOrEqual()) {
+    } else {
+      DCHECK(cond->IsGreaterThanOrEqual());
       return new (allocator) HLessThan(lhs, rhs);
     }
   } else if (cond->IsIntConstant()) {
@@ -70,10 +71,11 @@
       DCHECK(int_const->IsOne());
       return graph->GetIntConstant(0);
     }
+  } else {
+    // General case when 'cond' is another instruction of type boolean.
+    // Negate with 'cond == 0'.
+    return new (allocator) HEqual(cond, graph->GetIntConstant(0));
   }
-
-  LOG(FATAL) << "Instruction " << cond->DebugName() << " used as a condition";
-  UNREACHABLE();
 }
 
 void HBooleanSimplifier::Run() {
diff --git a/compiler/optimizing/code_generator_arm.cc b/compiler/optimizing/code_generator_arm.cc
index 0f79d18..1f95041 100644
--- a/compiler/optimizing/code_generator_arm.cc
+++ b/compiler/optimizing/code_generator_arm.cc
@@ -2087,16 +2087,32 @@
 }
 
 void LocationsBuilderARM::VisitDiv(HDiv* div) {
-  LocationSummary::CallKind call_kind = div->GetResultType() == Primitive::kPrimLong
-      ? LocationSummary::kCall
-      : LocationSummary::kNoCall;
+  LocationSummary::CallKind call_kind = LocationSummary::kNoCall;
+  if (div->GetResultType() == Primitive::kPrimLong) {
+    // pLdiv runtime call.
+    call_kind = LocationSummary::kCall;
+  } else if (div->GetResultType() == Primitive::kPrimInt &&
+             !codegen_->GetInstructionSetFeatures().HasDivideInstruction()) {
+    // pIdivmod runtime call.
+    call_kind = LocationSummary::kCall;
+  }
+
   LocationSummary* locations = new (GetGraph()->GetArena()) LocationSummary(div, call_kind);
 
   switch (div->GetResultType()) {
     case Primitive::kPrimInt: {
-      locations->SetInAt(0, Location::RequiresRegister());
-      locations->SetInAt(1, Location::RequiresRegister());
-      locations->SetOut(Location::RequiresRegister(), Location::kNoOutputOverlap);
+      if (codegen_->GetInstructionSetFeatures().HasDivideInstruction()) {
+        locations->SetInAt(0, Location::RequiresRegister());
+        locations->SetInAt(1, Location::RequiresRegister());
+        locations->SetOut(Location::RequiresRegister(), Location::kNoOutputOverlap);
+      } else {
+        InvokeRuntimeCallingConvention calling_convention;
+        locations->SetInAt(0, Location::RegisterLocation(calling_convention.GetRegisterAt(0)));
+        locations->SetInAt(1, Location::RegisterLocation(calling_convention.GetRegisterAt(1)));
+        // Note: divrem will compute both the quotient and the remainder as the pair R0 and R1, but
+        //       we only need the former.
+        locations->SetOut(Location::RegisterLocation(R0));
+      }
       break;
     }
     case Primitive::kPrimLong: {
@@ -2129,9 +2145,18 @@
 
   switch (div->GetResultType()) {
     case Primitive::kPrimInt: {
-      __ sdiv(out.AsRegister<Register>(),
-              first.AsRegister<Register>(),
-              second.AsRegister<Register>());
+      if (codegen_->GetInstructionSetFeatures().HasDivideInstruction()) {
+        __ sdiv(out.AsRegister<Register>(),
+                first.AsRegister<Register>(),
+                second.AsRegister<Register>());
+      } else {
+        InvokeRuntimeCallingConvention calling_convention;
+        DCHECK_EQ(calling_convention.GetRegisterAt(0), first.AsRegister<Register>());
+        DCHECK_EQ(calling_convention.GetRegisterAt(1), second.AsRegister<Register>());
+        DCHECK_EQ(R0, out.AsRegister<Register>());
+
+        codegen_->InvokeRuntime(QUICK_ENTRY_POINT(pIdivmod), div, div->GetDexPc(), nullptr);
+      }
       break;
     }
 
@@ -2169,17 +2194,32 @@
 
 void LocationsBuilderARM::VisitRem(HRem* rem) {
   Primitive::Type type = rem->GetResultType();
-  LocationSummary::CallKind call_kind = type == Primitive::kPrimInt
-      ? LocationSummary::kNoCall
-      : LocationSummary::kCall;
+
+  // Most remainders are implemented in the runtime.
+  LocationSummary::CallKind call_kind = LocationSummary::kCall;
+  if (rem->GetResultType() == Primitive::kPrimInt &&
+      codegen_->GetInstructionSetFeatures().HasDivideInstruction()) {
+    // Have hardware divide instruction for int, do it with three instructions.
+    call_kind = LocationSummary::kNoCall;
+  }
+
   LocationSummary* locations = new (GetGraph()->GetArena()) LocationSummary(rem, call_kind);
 
   switch (type) {
     case Primitive::kPrimInt: {
-      locations->SetInAt(0, Location::RequiresRegister());
-      locations->SetInAt(1, Location::RequiresRegister());
-      locations->SetOut(Location::RequiresRegister(), Location::kNoOutputOverlap);
-      locations->AddTemp(Location::RequiresRegister());
+      if (codegen_->GetInstructionSetFeatures().HasDivideInstruction()) {
+        locations->SetInAt(0, Location::RequiresRegister());
+        locations->SetInAt(1, Location::RequiresRegister());
+        locations->SetOut(Location::RequiresRegister(), Location::kNoOutputOverlap);
+        locations->AddTemp(Location::RequiresRegister());
+      } else {
+        InvokeRuntimeCallingConvention calling_convention;
+        locations->SetInAt(0, Location::RegisterLocation(calling_convention.GetRegisterAt(0)));
+        locations->SetInAt(1, Location::RegisterLocation(calling_convention.GetRegisterAt(1)));
+        // Note: divrem will compute both the quotient and the remainder as the pair R0 and R1, but
+        //       we only need the latter.
+        locations->SetOut(Location::RegisterLocation(R1));
+      }
       break;
     }
     case Primitive::kPrimLong: {
@@ -2224,16 +2264,25 @@
   Primitive::Type type = rem->GetResultType();
   switch (type) {
     case Primitive::kPrimInt: {
-      Register reg1 = first.AsRegister<Register>();
-      Register reg2 = second.AsRegister<Register>();
-      Register temp = locations->GetTemp(0).AsRegister<Register>();
+      if (codegen_->GetInstructionSetFeatures().HasDivideInstruction()) {
+        Register reg1 = first.AsRegister<Register>();
+        Register reg2 = second.AsRegister<Register>();
+        Register temp = locations->GetTemp(0).AsRegister<Register>();
 
-      // temp = reg1 / reg2  (integer division)
-      // temp = temp * reg2
-      // dest = reg1 - temp
-      __ sdiv(temp, reg1, reg2);
-      __ mul(temp, temp, reg2);
-      __ sub(out.AsRegister<Register>(), reg1, ShifterOperand(temp));
+        // temp = reg1 / reg2  (integer division)
+        // temp = temp * reg2
+        // dest = reg1 - temp
+        __ sdiv(temp, reg1, reg2);
+        __ mul(temp, temp, reg2);
+        __ sub(out.AsRegister<Register>(), reg1, ShifterOperand(temp));
+      } else {
+        InvokeRuntimeCallingConvention calling_convention;
+        DCHECK_EQ(calling_convention.GetRegisterAt(0), first.AsRegister<Register>());
+        DCHECK_EQ(calling_convention.GetRegisterAt(1), second.AsRegister<Register>());
+        DCHECK_EQ(R1, out.AsRegister<Register>());
+
+        codegen_->InvokeRuntime(QUICK_ENTRY_POINT(pIdivmod), rem, rem->GetDexPc(), nullptr);
+      }
       break;
     }
 
diff --git a/compiler/optimizing/code_generator_x86.cc b/compiler/optimizing/code_generator_x86.cc
index 8d0ca0b..0d5fe49 100644
--- a/compiler/optimizing/code_generator_x86.cc
+++ b/compiler/optimizing/code_generator_x86.cc
@@ -3146,7 +3146,7 @@
   Location obj = locations->InAt(0);
 
   if (obj.IsRegister()) {
-    __ cmpl(obj.AsRegister<Register>(), Immediate(0));
+    __ testl(obj.AsRegister<Register>(), obj.AsRegister<Register>());
   } else if (obj.IsStackSlot()) {
     __ cmpl(Address(ESP, obj.GetStackIndex()), Immediate(0));
   } else {
diff --git a/compiler/optimizing/inliner.cc b/compiler/optimizing/inliner.cc
index 4b990f1..2c17a67 100644
--- a/compiler/optimizing/inliner.cc
+++ b/compiler/optimizing/inliner.cc
@@ -49,7 +49,8 @@
     for (HInstruction* instruction = block->GetFirstInstruction(); instruction != nullptr;) {
       HInstruction* next = instruction->GetNext();
       HInvokeStaticOrDirect* call = instruction->AsInvokeStaticOrDirect();
-      if (call != nullptr) {
+      // As long as the call is not intrinsified, it is worth trying to inline.
+      if (call != nullptr && call->GetIntrinsic() == Intrinsics::kNone) {
         // We use the original invoke type to ensure the resolution of the called method
         // works properly.
         if (!TryInline(call, call->GetDexMethodIndex(), call->GetOriginalInvokeType())) {
diff --git a/compiler/optimizing/intrinsics.cc b/compiler/optimizing/intrinsics.cc
index 36cf856..628a844 100644
--- a/compiler/optimizing/intrinsics.cc
+++ b/compiler/optimizing/intrinsics.cc
@@ -191,8 +191,10 @@
     case kIntrinsicCompareTo:
       return Intrinsics::kStringCompareTo;
     case kIntrinsicIsEmptyOrLength:
-      return ((method.d.data & kIntrinsicFlagIsEmpty) == 0) ?
-          Intrinsics::kStringLength : Intrinsics::kStringIsEmpty;
+      // The inliner can handle these two cases - and this is the preferred approach
+      // since after inlining the call is no longer visible (as opposed to waiting
+      // until codegen to handle intrinsic).
+      return Intrinsics::kNone;
     case kIntrinsicIndexOf:
       return ((method.d.data & kIntrinsicFlagBase0) == 0) ?
           Intrinsics::kStringIndexOfAfter : Intrinsics::kStringIndexOf;
diff --git a/compiler/optimizing/intrinsics_arm.cc b/compiler/optimizing/intrinsics_arm.cc
index 3fb6a7d..33176f0 100644
--- a/compiler/optimizing/intrinsics_arm.cc
+++ b/compiler/optimizing/intrinsics_arm.cc
@@ -862,7 +862,7 @@
   ArmAssembler* assembler = GetAssembler();
   LocationSummary* locations = invoke->GetLocations();
 
-  // Note that the null check must have be done earlier.
+  // Note that the null check must have been done earlier.
   DCHECK(!invoke->CanDoImplicitNullCheck());
 
   Register argument = locations->InAt(1).AsRegister<Register>();
@@ -903,8 +903,6 @@
 UNIMPLEMENTED_INTRINSIC(MathRoundFloat)    // Could be done by changing rounding mode, maybe?
 UNIMPLEMENTED_INTRINSIC(UnsafeCASLong)     // High register pressure.
 UNIMPLEMENTED_INTRINSIC(SystemArrayCopyChar)
-UNIMPLEMENTED_INTRINSIC(StringIsEmpty)  // Might not want to do these two anyways, inlining should
-UNIMPLEMENTED_INTRINSIC(StringLength)   // be good enough here.
 UNIMPLEMENTED_INTRINSIC(StringIndexOf)
 UNIMPLEMENTED_INTRINSIC(StringIndexOfAfter)
 UNIMPLEMENTED_INTRINSIC(ReferenceGetReferent)
diff --git a/compiler/optimizing/intrinsics_arm64.cc b/compiler/optimizing/intrinsics_arm64.cc
index 04e8fdc..72d303c 100644
--- a/compiler/optimizing/intrinsics_arm64.cc
+++ b/compiler/optimizing/intrinsics_arm64.cc
@@ -1006,7 +1006,7 @@
   vixl::MacroAssembler* masm = GetVIXLAssembler();
   LocationSummary* locations = invoke->GetLocations();
 
-  // Note that the null check must have be done earlier.
+  // Note that the null check must have been done earlier.
   DCHECK(!invoke->CanDoImplicitNullCheck());
 
   Register argument = WRegisterFrom(locations->InAt(1));
@@ -1030,8 +1030,6 @@
 }
 
 UNIMPLEMENTED_INTRINSIC(SystemArrayCopyChar)
-UNIMPLEMENTED_INTRINSIC(StringIsEmpty)  // Might not want to do these two anyways, inlining should
-UNIMPLEMENTED_INTRINSIC(StringLength)   // be good enough here.
 UNIMPLEMENTED_INTRINSIC(StringIndexOf)
 UNIMPLEMENTED_INTRINSIC(StringIndexOfAfter)
 UNIMPLEMENTED_INTRINSIC(ReferenceGetReferent)
diff --git a/compiler/optimizing/intrinsics_list.h b/compiler/optimizing/intrinsics_list.h
index 9cc77c6..10f6e1d 100644
--- a/compiler/optimizing/intrinsics_list.h
+++ b/compiler/optimizing/intrinsics_list.h
@@ -60,10 +60,8 @@
   V(MemoryPokeShortNative, kStatic) \
   V(StringCharAt, kDirect) \
   V(StringCompareTo, kDirect) \
-  V(StringIsEmpty, kDirect) \
   V(StringIndexOf, kDirect) \
   V(StringIndexOfAfter, kDirect) \
-  V(StringLength, kDirect) \
   V(UnsafeCASInt, kDirect) \
   V(UnsafeCASLong, kDirect) \
   V(UnsafeCASObject, kDirect) \
diff --git a/compiler/optimizing/intrinsics_x86.cc b/compiler/optimizing/intrinsics_x86.cc
index 74edf50..384737f 100644
--- a/compiler/optimizing/intrinsics_x86.cc
+++ b/compiler/optimizing/intrinsics_x86.cc
@@ -790,7 +790,7 @@
   X86Assembler* assembler = GetAssembler();
   LocationSummary* locations = invoke->GetLocations();
 
-  // Note that the null check must have be done earlier.
+  // Note that the null check must have been done earlier.
   DCHECK(!invoke->CanDoImplicitNullCheck());
 
   Register argument = locations->InAt(1).AsRegister<Register>();
@@ -1196,8 +1196,6 @@
 UNIMPLEMENTED_INTRINSIC(MathRint)
 UNIMPLEMENTED_INTRINSIC(MathRoundDouble)
 UNIMPLEMENTED_INTRINSIC(MathRoundFloat)
-UNIMPLEMENTED_INTRINSIC(StringIsEmpty)  // Might not want to do these two anyways, inlining should
-UNIMPLEMENTED_INTRINSIC(StringLength)   // be good enough here.
 UNIMPLEMENTED_INTRINSIC(StringIndexOf)
 UNIMPLEMENTED_INTRINSIC(StringIndexOfAfter)
 UNIMPLEMENTED_INTRINSIC(SystemArrayCopyChar)
diff --git a/compiler/optimizing/intrinsics_x86_64.cc b/compiler/optimizing/intrinsics_x86_64.cc
index e4f2518..736cea8 100644
--- a/compiler/optimizing/intrinsics_x86_64.cc
+++ b/compiler/optimizing/intrinsics_x86_64.cc
@@ -681,7 +681,7 @@
   X86_64Assembler* assembler = GetAssembler();
   LocationSummary* locations = invoke->GetLocations();
 
-  // Note that the null check must have be done earlier.
+  // Note that the null check must have been done earlier.
   DCHECK(!invoke->CanDoImplicitNullCheck());
 
   CpuRegister argument = locations->InAt(1).AsRegister<CpuRegister>();
@@ -1014,8 +1014,6 @@
 UNIMPLEMENTED_INTRINSIC(MathRint)
 UNIMPLEMENTED_INTRINSIC(MathRoundDouble)
 UNIMPLEMENTED_INTRINSIC(MathRoundFloat)
-UNIMPLEMENTED_INTRINSIC(StringIsEmpty)  // Might not want to do these two anyways, inlining should
-UNIMPLEMENTED_INTRINSIC(StringLength)   // be good enough here.
 UNIMPLEMENTED_INTRINSIC(StringIndexOf)
 UNIMPLEMENTED_INTRINSIC(StringIndexOfAfter)
 UNIMPLEMENTED_INTRINSIC(SystemArrayCopyChar)
diff --git a/compiler/optimizing/optimizing_compiler.cc b/compiler/optimizing/optimizing_compiler.cc
index c0df02b..e474c49 100644
--- a/compiler/optimizing/optimizing_compiler.cc
+++ b/compiler/optimizing/optimizing_compiler.cc
@@ -585,8 +585,13 @@
   if (method != nullptr) {
     return method;
   }
-  return delegate_->Compile(code_item, access_flags, invoke_type, class_def_idx, method_idx,
-                            class_loader, dex_file);
+  method = delegate_->Compile(code_item, access_flags, invoke_type, class_def_idx, method_idx,
+                              class_loader, dex_file);
+
+  if (method != nullptr) {
+    compilation_stats_.RecordStat(MethodCompilationStat::kCompiledQuick);
+  }
+  return method;
 }
 
 Compiler* CreateOptimizingCompiler(CompilerDriver* driver) {
diff --git a/compiler/optimizing/optimizing_compiler_stats.h b/compiler/optimizing/optimizing_compiler_stats.h
index 22ec2a5..b97a667 100644
--- a/compiler/optimizing/optimizing_compiler_stats.h
+++ b/compiler/optimizing/optimizing_compiler_stats.h
@@ -28,6 +28,7 @@
   kAttemptCompilation = 0,
   kCompiledBaseline,
   kCompiledOptimized,
+  kCompiledQuick,
   kInlinedInvoke,
   kNotCompiledUnsupportedIsa,
   kNotCompiledPathological,
@@ -65,16 +66,22 @@
           compile_stats_[kCompiledBaseline] * 100 / compile_stats_[kAttemptCompilation];
       size_t optimized_percent =
           compile_stats_[kCompiledOptimized] * 100 / compile_stats_[kAttemptCompilation];
+      size_t quick_percent =
+          compile_stats_[kCompiledQuick] * 100 / compile_stats_[kAttemptCompilation];
       std::ostringstream oss;
-      oss << "Attempted compilation of " << compile_stats_[kAttemptCompilation] << " methods: "
-          << unoptimized_percent << "% (" << compile_stats_[kCompiledBaseline] << ") unoptimized, "
-          << optimized_percent << "% (" << compile_stats_[kCompiledOptimized] << ") optimized.";
+      oss << "Attempted compilation of " << compile_stats_[kAttemptCompilation] << " methods: ";
+
+      oss << unoptimized_percent << "% (" << compile_stats_[kCompiledBaseline] << ") unoptimized, ";
+      oss << optimized_percent << "% (" << compile_stats_[kCompiledOptimized] << ") optimized, ";
+      oss << quick_percent << "% (" << compile_stats_[kCompiledQuick] << ") quick.";
+
+      LOG(INFO) << oss.str();
+
       for (int i = 0; i < kLastStat; i++) {
         if (compile_stats_[i] != 0) {
-          oss << "\n" << PrintMethodCompilationStat(i) << ": " << compile_stats_[i];
+          VLOG(compiler) << PrintMethodCompilationStat(i) << ": " << compile_stats_[i];
         }
       }
-      LOG(INFO) << oss.str();
     }
   }
 
@@ -84,6 +91,7 @@
       case kAttemptCompilation : return "kAttemptCompilation";
       case kCompiledBaseline : return "kCompiledBaseline";
       case kCompiledOptimized : return "kCompiledOptimized";
+      case kCompiledQuick : return "kCompiledQuick";
       case kInlinedInvoke : return "kInlinedInvoke";
       case kNotCompiledUnsupportedIsa : return "kNotCompiledUnsupportedIsa";
       case kNotCompiledPathological : return "kNotCompiledPathological";
diff --git a/compiler/optimizing/parallel_move_resolver.cc b/compiler/optimizing/parallel_move_resolver.cc
index 7d0641e..9df8f56 100644
--- a/compiler/optimizing/parallel_move_resolver.cc
+++ b/compiler/optimizing/parallel_move_resolver.cc
@@ -13,6 +13,7 @@
  * See the License for the specific language governing permissions and
  * limitations under the License.
  */
+#include <iostream>
 
 #include "parallel_move_resolver.h"
 #include "nodes.h"
@@ -63,39 +64,42 @@
   }
 }
 
+Location LowOf(Location location) {
+  if (location.IsRegisterPair()) {
+    return Location::RegisterLocation(location.low());
+  } else if (location.IsFpuRegisterPair()) {
+    return Location::FpuRegisterLocation(location.low());
+  } else if (location.IsDoubleStackSlot()) {
+    return Location::StackSlot(location.GetStackIndex());
+  } else {
+    return Location::NoLocation();
+  }
+}
+
+Location HighOf(Location location) {
+  if (location.IsRegisterPair()) {
+    return Location::RegisterLocation(location.high());
+  } else if (location.IsFpuRegisterPair()) {
+    return Location::FpuRegisterLocation(location.high());
+  } else if (location.IsDoubleStackSlot()) {
+    return Location::StackSlot(location.GetHighStackIndex(4));
+  } else {
+    return Location::NoLocation();
+  }
+}
+
 // Update the source of `move`, knowing that `updated_location` has been swapped
 // with `new_source`. Note that `updated_location` can be a pair, therefore if
 // `move` is non-pair, we need to extract which register to use.
 static void UpdateSourceOf(MoveOperands* move, Location updated_location, Location new_source) {
   Location source = move->GetSource();
-  if (new_source.GetKind() == source.GetKind()) {
-    DCHECK(updated_location.Equals(source));
+  if (LowOf(updated_location).Equals(source)) {
+    move->SetSource(LowOf(new_source));
+  } else if (HighOf(updated_location).Equals(source)) {
+    move->SetSource(HighOf(new_source));
+  } else {
+    DCHECK(updated_location.Equals(source)) << updated_location << " " << source;
     move->SetSource(new_source);
-  } else if (new_source.IsStackSlot()
-             || new_source.IsDoubleStackSlot()
-             || source.IsStackSlot()
-             || source.IsDoubleStackSlot()) {
-    // Stack slots never take part of a pair/non-pair swap.
-    DCHECK(updated_location.Equals(source));
-    move->SetSource(new_source);
-  } else if (source.IsRegister()) {
-    DCHECK(new_source.IsRegisterPair()) << new_source;
-    DCHECK(updated_location.IsRegisterPair()) << updated_location;
-    if (updated_location.low() == source.reg()) {
-      move->SetSource(Location::RegisterLocation(new_source.low()));
-    } else {
-      DCHECK_EQ(updated_location.high(), source.reg());
-      move->SetSource(Location::RegisterLocation(new_source.high()));
-    }
-  } else if (source.IsFpuRegister()) {
-    DCHECK(new_source.IsFpuRegisterPair()) << new_source;
-    DCHECK(updated_location.IsFpuRegisterPair()) << updated_location;
-    if (updated_location.low() == source.reg()) {
-      move->SetSource(Location::FpuRegisterLocation(new_source.low()));
-    } else {
-      DCHECK_EQ(updated_location.high(), source.reg());
-      move->SetSource(Location::FpuRegisterLocation(new_source.high()));
-    }
   }
 }
 
diff --git a/compiler/optimizing/parallel_move_test.cc b/compiler/optimizing/parallel_move_test.cc
index 817a44b..5c502f7 100644
--- a/compiler/optimizing/parallel_move_test.cc
+++ b/compiler/optimizing/parallel_move_test.cc
@@ -31,8 +31,13 @@
       message_ << "C";
     } else if (location.IsPair()) {
       message_ << location.low() << "," << location.high();
-    } else {
+    } else if (location.IsRegister()) {
       message_ << location.reg();
+    } else if (location.IsStackSlot()) {
+      message_ << location.GetStackIndex() << "(sp)";
+    } else {
+      message_ << "2x" << location.GetStackIndex() << "(sp)";
+      DCHECK(location.IsDoubleStackSlot()) << location;
     }
   }
 
@@ -279,6 +284,26 @@
     resolver.EmitNativeCode(moves);
     ASSERT_STREQ("(0,1 <-> 2,3)", resolver.GetMessage().c_str());
   }
+
+  {
+    // Test involving registers used in single context and pair context.
+    TestParallelMoveResolver resolver(&allocator);
+    HParallelMove* moves = new (&allocator) HParallelMove(&allocator);
+    moves->AddMove(
+        Location::RegisterLocation(10),
+        Location::RegisterLocation(5),
+        nullptr);
+    moves->AddMove(
+        Location::RegisterPairLocation(4, 5),
+        Location::DoubleStackSlot(32),
+        nullptr);
+    moves->AddMove(
+        Location::DoubleStackSlot(32),
+        Location::RegisterPairLocation(10, 11),
+        nullptr);
+    resolver.EmitNativeCode(moves);
+    ASSERT_STREQ("(2x32(sp) <-> 10,11) (4,5 <-> 2x32(sp)) (4 -> 5)", resolver.GetMessage().c_str());
+  }
 }
 
 }  // namespace art
diff --git a/compiler/optimizing/register_allocator.cc b/compiler/optimizing/register_allocator.cc
index cecc210..cf38bd3 100644
--- a/compiler/optimizing/register_allocator.cc
+++ b/compiler/optimizing/register_allocator.cc
@@ -213,7 +213,7 @@
           LiveInterval* interval =
               LiveInterval::MakeTempInterval(allocator_, Primitive::kPrimInt);
           temp_intervals_.Add(interval);
-          interval->AddRange(position, position + 1);
+          interval->AddTempUse(instruction, i);
           unhandled_core_intervals_.Add(interval);
           break;
         }
@@ -222,7 +222,7 @@
           LiveInterval* interval =
               LiveInterval::MakeTempInterval(allocator_, Primitive::kPrimDouble);
           temp_intervals_.Add(interval);
-          interval->AddRange(position, position + 1);
+          interval->AddTempUse(instruction, i);
           if (codegen_->NeedsTwoRegisters(Primitive::kPrimDouble)) {
             interval->AddHighInterval(true);
             LiveInterval* high = interval->GetHighInterval();
@@ -851,6 +851,23 @@
   return false;
 }
 
+bool RegisterAllocator::PotentiallyRemoveOtherHalf(LiveInterval* interval,
+                                                   GrowableArray<LiveInterval*>* intervals,
+                                                   size_t index) {
+  if (interval->IsLowInterval()) {
+    DCHECK_EQ(intervals->Get(index), interval->GetHighInterval());
+    intervals->DeleteAt(index);
+    return true;
+  } else if (interval->IsHighInterval()) {
+    DCHECK_GT(index, 0u);
+    DCHECK_EQ(intervals->Get(index - 1), interval->GetLowInterval());
+    intervals->DeleteAt(index - 1);
+    return true;
+  } else {
+    return false;
+  }
+}
+
 // Find the register that is used the last, and spill the interval
 // that holds it. If the first use of `current` is after that register
 // we spill `current` instead.
@@ -974,33 +991,17 @@
       if (active->GetRegister() == reg) {
         DCHECK(!active->IsFixed());
         LiveInterval* split = Split(active, current->GetStart());
-        active_.DeleteAt(i);
         if (split != active) {
           handled_.Add(active);
         }
+        active_.DeleteAt(i);
+        PotentiallyRemoveOtherHalf(active, &active_, i);
         AddSorted(unhandled_, split);
-
-        if (active->IsLowInterval() || active->IsHighInterval()) {
-          LiveInterval* other_half = active->IsLowInterval()
-              ? active->GetHighInterval()
-              : active->GetLowInterval();
-          // We also need to remove the other half from the list of actives.
-          bool found = false;
-          for (size_t j = 0; j < active_.Size(); ++j) {
-            if (active_.Get(j) == other_half) {
-              found = true;
-              active_.DeleteAt(j);
-              handled_.Add(other_half);
-              break;
-            }
-          }
-          DCHECK(found);
-        }
         break;
       }
     }
 
-    for (size_t i = 0, e = inactive_.Size(); i < e; ++i) {
+    for (size_t i = 0; i < inactive_.Size(); ++i) {
       LiveInterval* inactive = inactive_.Get(i);
       if (inactive->GetRegister() == reg) {
         if (!current->IsSplit() && !inactive->IsFixed()) {
@@ -1024,29 +1025,14 @@
             // If it's inactive, it must start before the current interval.
             DCHECK_NE(split, inactive);
             inactive_.DeleteAt(i);
+            if (PotentiallyRemoveOtherHalf(inactive, &inactive_, i) && inactive->IsHighInterval()) {
+              // We have removed an entry prior to `inactive`. So we need to decrement.
+              --i;
+            }
+            // Decrement because we have removed `inactive` from the list.
             --i;
-            --e;
             handled_.Add(inactive);
             AddSorted(unhandled_, split);
-
-            if (inactive->IsLowInterval() || inactive->IsHighInterval()) {
-              LiveInterval* other_half = inactive->IsLowInterval()
-                  ? inactive->GetHighInterval()
-                  : inactive->GetLowInterval();
-
-              // We also need to remove the other half from the list of inactives.
-              bool found = false;
-              for (size_t j = 0; j < inactive_.Size(); ++j) {
-                if (inactive_.Get(j) == other_half) {
-                  found = true;
-                  inactive_.DeleteAt(j);
-                  --e;
-                  handled_.Add(other_half);
-                  break;
-                }
-              }
-              DCHECK(found);
-            }
           }
         }
       }
@@ -1695,8 +1681,6 @@
   }
 
   // Assign temp locations.
-  HInstruction* current = nullptr;
-  size_t temp_index = 0;
   for (size_t i = 0; i < temp_intervals_.Size(); ++i) {
     LiveInterval* temp = temp_intervals_.Get(i);
     if (temp->IsHighInterval()) {
@@ -1704,25 +1688,20 @@
       continue;
     }
     HInstruction* at = liveness_.GetTempUser(temp);
-    if (at != current) {
-      temp_index = 0;
-      current = at;
-    }
+    size_t temp_index = liveness_.GetTempIndex(temp);
     LocationSummary* locations = at->GetLocations();
     switch (temp->GetType()) {
       case Primitive::kPrimInt:
-        locations->SetTempAt(
-            temp_index++, Location::RegisterLocation(temp->GetRegister()));
+        locations->SetTempAt(temp_index, Location::RegisterLocation(temp->GetRegister()));
         break;
 
       case Primitive::kPrimDouble:
         if (codegen_->NeedsTwoRegisters(Primitive::kPrimDouble)) {
           Location location = Location::FpuRegisterPairLocation(
               temp->GetRegister(), temp->GetHighInterval()->GetRegister());
-          locations->SetTempAt(temp_index++, location);
+          locations->SetTempAt(temp_index, location);
         } else {
-          locations->SetTempAt(
-              temp_index++, Location::FpuRegisterLocation(temp->GetRegister()));
+          locations->SetTempAt(temp_index, Location::FpuRegisterLocation(temp->GetRegister()));
         }
         break;
 
diff --git a/compiler/optimizing/register_allocator.h b/compiler/optimizing/register_allocator.h
index fcc6112..717be75 100644
--- a/compiler/optimizing/register_allocator.h
+++ b/compiler/optimizing/register_allocator.h
@@ -144,6 +144,13 @@
                                                 size_t first_register_use,
                                                 size_t* next_use);
 
+  // If `interval` has another half, remove it from the list of `intervals`.
+  // `index` holds the index at which `interval` is in `intervals`.
+  // Returns whether there is another half.
+  bool PotentiallyRemoveOtherHalf(LiveInterval* interval,
+                                  GrowableArray<LiveInterval*>* intervals,
+                                  size_t index);
+
   ArenaAllocator* const allocator_;
   CodeGenerator* const codegen_;
   const SsaLivenessAnalysis& liveness_;
diff --git a/compiler/optimizing/ssa_liveness_analysis.cc b/compiler/optimizing/ssa_liveness_analysis.cc
index 56ccd71..0f3973e 100644
--- a/compiler/optimizing/ssa_liveness_analysis.cc
+++ b/compiler/optimizing/ssa_liveness_analysis.cc
@@ -318,6 +318,8 @@
 
 int LiveInterval::FindFirstRegisterHint(size_t* free_until) const {
   DCHECK(!IsHighInterval());
+  if (IsTemp()) return kNoRegister;
+
   if (GetParent() == this && defined_by_ != nullptr) {
     // This is the first interval for the instruction. Try to find
     // a register based on its definition.
diff --git a/compiler/optimizing/ssa_liveness_analysis.h b/compiler/optimizing/ssa_liveness_analysis.h
index b57029d..bc78dc2 100644
--- a/compiler/optimizing/ssa_liveness_analysis.h
+++ b/compiler/optimizing/ssa_liveness_analysis.h
@@ -180,6 +180,15 @@
   // This interval is the result of a split.
   bool IsSplit() const { return parent_ != this; }
 
+  void AddTempUse(HInstruction* instruction, size_t temp_index) {
+    DCHECK(IsTemp());
+    DCHECK(first_use_ == nullptr) << "A temporary can only have one user";
+    size_t position = instruction->GetLifetimePosition();
+    first_use_ = new (allocator_) UsePosition(
+        instruction, temp_index, /* is_environment */ false, position, first_use_);
+    AddRange(position, position + 1);
+  }
+
   void AddUse(HInstruction* instruction, size_t input_index, bool is_environment) {
     // Set the use within the instruction.
     size_t position = instruction->GetLifetimePosition() + 1;
@@ -856,7 +865,15 @@
   HInstruction* GetTempUser(LiveInterval* temp) const {
     // A temporary shares the same lifetime start as the instruction that requires it.
     DCHECK(temp->IsTemp());
-    return GetInstructionFromPosition(temp->GetStart() / 2);
+    HInstruction* user = GetInstructionFromPosition(temp->GetStart() / 2);
+    DCHECK_EQ(user, temp->GetFirstUse()->GetUser());
+    return user;
+  }
+
+  size_t GetTempIndex(LiveInterval* temp) const {
+    // We use the input index to store the index of the temporary in the user's temporary list.
+    DCHECK(temp->IsTemp());
+    return temp->GetFirstUse()->GetInputIndex();
   }
 
   size_t GetMaxLifetimePosition() const {
diff --git a/compiler/optimizing/stack_map_stream.h b/compiler/optimizing/stack_map_stream.h
index 5818a37..a73c8d7 100644
--- a/compiler/optimizing/stack_map_stream.h
+++ b/compiler/optimizing/stack_map_stream.h
@@ -27,6 +27,32 @@
 
 namespace art {
 
+// Helper to build art::StackMapStream::LocationCatalogEntriesIndices.
+class LocationCatalogEntriesIndicesEmptyFn {
+ public:
+  void MakeEmpty(std::pair<DexRegisterLocation, size_t>& item) const {
+    item.first = DexRegisterLocation::None();
+  }
+  bool IsEmpty(const std::pair<DexRegisterLocation, size_t>& item) const {
+    return item.first == DexRegisterLocation::None();
+  }
+};
+
+// Hash function for art::StackMapStream::LocationCatalogEntriesIndices.
+// This hash function does not create collisions.
+class DexRegisterLocationHashFn {
+ public:
+  size_t operator()(DexRegisterLocation key) const {
+    // Concatenate `key`s fields to create a 64-bit value to be hashed.
+    int64_t kind_and_value =
+        (static_cast<int64_t>(key.kind_) << 32) | static_cast<int64_t>(key.value_);
+    return inner_hash_fn_(kind_and_value);
+  }
+ private:
+  std::hash<int64_t> inner_hash_fn_;
+};
+
+
 /**
  * Collects and builds stack maps for a method. All the stack maps
  * for a method are placed in a CodeInfo object.
@@ -36,11 +62,13 @@
   explicit StackMapStream(ArenaAllocator* allocator)
       : allocator_(allocator),
         stack_maps_(allocator, 10),
+        location_catalog_entries_(allocator, 4),
         dex_register_locations_(allocator, 10 * 4),
         inline_infos_(allocator, 2),
         stack_mask_max_(-1),
         dex_pc_max_(0),
         native_pc_offset_max_(0),
+        register_mask_max_(0),
         number_of_stack_maps_with_inline_info_(0),
         dex_map_hash_to_stack_map_indices_(std::less<uint32_t>(), allocator->Adapter()) {}
 
@@ -101,6 +129,7 @@
 
     dex_pc_max_ = std::max(dex_pc_max_, dex_pc);
     native_pc_offset_max_ = std::max(native_pc_offset_max_, native_pc_offset);
+    register_mask_max_ = std::max(register_mask_max_, register_mask);
   }
 
   void AddInlineInfoEntry(uint32_t method_index) {
@@ -111,6 +140,7 @@
 
   size_t ComputeNeededSize() {
     size_t size = CodeInfo::kFixedSize
+        + ComputeDexRegisterLocationCatalogSize()
         + ComputeStackMapsSize()
         + ComputeDexRegisterMapsSize()
         + ComputeInlineInfoSize();
@@ -128,24 +158,43 @@
         ComputeInlineInfoSize(),
         ComputeDexRegisterMapsSize(),
         dex_pc_max_,
-        native_pc_offset_max_);
+        native_pc_offset_max_,
+        register_mask_max_);
   }
 
-  // Compute the size of the Dex register map of `entry`.
+  // Compute the size of the Dex register location catalog of `entry`.
+  size_t ComputeDexRegisterLocationCatalogSize() const {
+    size_t size = DexRegisterLocationCatalog::kFixedSize;
+    for (size_t location_catalog_entry_index = 0;
+         location_catalog_entry_index < location_catalog_entries_.Size();
+         ++location_catalog_entry_index) {
+      DexRegisterLocation dex_register_location =
+          location_catalog_entries_.Get(location_catalog_entry_index);
+      size += DexRegisterLocationCatalog::EntrySize(dex_register_location);
+    }
+    return size;
+  }
+
   size_t ComputeDexRegisterMapSize(const StackMapEntry& entry) const {
+    // Size of the map in bytes.
     size_t size = DexRegisterMap::kFixedSize;
-    // Add the bit mask for the dex register liveness.
-    size += DexRegisterMap::LiveBitMaskSize(entry.num_dex_registers);
-    for (size_t dex_register_number = 0, index_in_dex_register_locations = 0;
+    // Add the live bit mask for the Dex register liveness.
+    size += DexRegisterMap::GetLiveBitMaskSize(entry.num_dex_registers);
+    // Compute the size of the set of live Dex register entries.
+    size_t number_of_live_dex_registers = 0;
+    for (size_t dex_register_number = 0;
          dex_register_number < entry.num_dex_registers;
          ++dex_register_number) {
       if (entry.live_dex_registers_mask->IsBitSet(dex_register_number)) {
-        DexRegisterLocation dex_register_location = dex_register_locations_.Get(
-            entry.dex_register_locations_start_index + index_in_dex_register_locations);
-        size += DexRegisterMap::EntrySize(dex_register_location);
-        index_in_dex_register_locations++;
+        ++number_of_live_dex_registers;
       }
     }
+    size_t map_entries_size_in_bits =
+        DexRegisterMap::SingleEntrySizeInBits(location_catalog_entries_.Size())
+        * number_of_live_dex_registers;
+    size_t map_entries_size_in_bytes =
+        RoundUp(map_entries_size_in_bits, kBitsPerByte) / kBitsPerByte;
+    size += map_entries_size_in_bytes;
     return size;
   }
 
@@ -168,8 +217,16 @@
       + (number_of_stack_maps_with_inline_info_ * InlineInfo::kFixedSize);
   }
 
+  size_t ComputeDexRegisterLocationCatalogStart() const {
+    return CodeInfo::kFixedSize;
+  }
+
+  size_t ComputeStackMapsStart() const {
+    return ComputeDexRegisterLocationCatalogStart() + ComputeDexRegisterLocationCatalogSize();
+  }
+
   size_t ComputeDexRegisterMapsStart() {
-    return CodeInfo::kFixedSize + ComputeStackMapsSize();
+    return ComputeStackMapsStart() + ComputeStackMapsSize();
   }
 
   size_t ComputeInlineInfoStart() {
@@ -194,11 +251,32 @@
       ComputeInlineInfoStart(),
       inline_info_size);
 
-    code_info.SetEncoding(
-        inline_info_size, dex_register_map_size, dex_pc_max_, native_pc_offset_max_);
+    code_info.SetEncoding(inline_info_size,
+                          dex_register_map_size,
+                          dex_pc_max_,
+                          native_pc_offset_max_,
+                          register_mask_max_);
     code_info.SetNumberOfStackMaps(stack_maps_.Size());
     code_info.SetStackMaskSize(stack_mask_size);
-    DCHECK_EQ(code_info.StackMapsSize(), ComputeStackMapsSize());
+    DCHECK_EQ(code_info.GetStackMapsSize(), ComputeStackMapsSize());
+
+    // Set the Dex register location catalog.
+    code_info.SetNumberOfDexRegisterLocationCatalogEntries(
+        location_catalog_entries_.Size());
+    MemoryRegion dex_register_location_catalog_region = region.Subregion(
+        ComputeDexRegisterLocationCatalogStart(),
+        ComputeDexRegisterLocationCatalogSize());
+    DexRegisterLocationCatalog dex_register_location_catalog(dex_register_location_catalog_region);
+    // Offset in `dex_register_location_catalog` where to store the next
+    // register location.
+    size_t location_catalog_offset = DexRegisterLocationCatalog::kFixedSize;
+    for (size_t i = 0, e = location_catalog_entries_.Size(); i < e; ++i) {
+      DexRegisterLocation dex_register_location = location_catalog_entries_.Get(i);
+      dex_register_location_catalog.SetRegisterInfo(location_catalog_offset, dex_register_location);
+      location_catalog_offset += DexRegisterLocationCatalog::EntrySize(dex_register_location);
+    }
+    // Ensure we reached the end of the Dex registers location_catalog.
+    DCHECK_EQ(location_catalog_offset, dex_register_location_catalog_region.size());
 
     uintptr_t next_dex_register_map_offset = 0;
     uintptr_t next_inline_info_offset = 0;
@@ -234,25 +312,25 @@
           stack_map.SetDexRegisterMapOffset(
             code_info, register_region.start() - dex_register_locations_region.start());
 
-          // Offset in `dex_register_map` where to store the next register entry.
-          size_t offset = DexRegisterMap::kFixedSize;
-          dex_register_map.SetLiveBitMask(offset,
-                                          entry.num_dex_registers,
-                                          *entry.live_dex_registers_mask);
-          offset += DexRegisterMap::LiveBitMaskSize(entry.num_dex_registers);
+          // Set the live bit mask.
+          dex_register_map.SetLiveBitMask(entry.num_dex_registers, *entry.live_dex_registers_mask);
+
+          // Set the dex register location mapping data.
           for (size_t dex_register_number = 0, index_in_dex_register_locations = 0;
                dex_register_number < entry.num_dex_registers;
                ++dex_register_number) {
             if (entry.live_dex_registers_mask->IsBitSet(dex_register_number)) {
-              DexRegisterLocation dex_register_location = dex_register_locations_.Get(
-                  entry.dex_register_locations_start_index + index_in_dex_register_locations);
-              dex_register_map.SetRegisterInfo(offset, dex_register_location);
-              offset += DexRegisterMap::EntrySize(dex_register_location);
+              size_t location_catalog_entry_index =
+                  dex_register_locations_.Get(entry.dex_register_locations_start_index
+                                              + index_in_dex_register_locations);
+              dex_register_map.SetLocationCatalogEntryIndex(
+                  index_in_dex_register_locations,
+                  location_catalog_entry_index,
+                  entry.num_dex_registers,
+                  location_catalog_entries_.Size());
               ++index_in_dex_register_locations;
             }
           }
-          // Ensure we reached the end of the Dex registers region.
-          DCHECK_EQ(offset, register_region.size());
         }
       }
 
@@ -282,12 +360,31 @@
   }
 
   void AddDexRegisterEntry(uint16_t dex_register, DexRegisterLocation::Kind kind, int32_t value) {
+    StackMapEntry entry = stack_maps_.Get(stack_maps_.Size() - 1);
+    DCHECK_LT(dex_register, entry.num_dex_registers);
+
     if (kind != DexRegisterLocation::Kind::kNone) {
       // Ensure we only use non-compressed location kind at this stage.
       DCHECK(DexRegisterLocation::IsShortLocationKind(kind))
           << DexRegisterLocation::PrettyDescriptor(kind);
-      dex_register_locations_.Add(DexRegisterLocation(kind, value));
-      StackMapEntry entry = stack_maps_.Get(stack_maps_.Size() - 1);
+      DexRegisterLocation location(kind, value);
+
+      // Look for Dex register `location` in the location catalog (using the
+      // companion hash map of locations to indices).  Use its index if it
+      // is already in the location catalog.  If not, insert it (in the
+      // location catalog and the hash map) and use the newly created index.
+      auto it = location_catalog_entries_indices_.Find(location);
+      if (it != location_catalog_entries_indices_.end()) {
+        // Retrieve the index from the hash map.
+        dex_register_locations_.Add(it->second);
+      } else {
+        // Create a new entry in the location catalog and the hash map.
+        size_t index = location_catalog_entries_.Size();
+        location_catalog_entries_.Add(location);
+        dex_register_locations_.Add(index);
+        location_catalog_entries_indices_.Insert(std::make_pair(location, index));
+      }
+
       entry.live_dex_registers_mask->SetBit(dex_register);
       entry.dex_register_map_hash += (1 << dex_register);
       entry.dex_register_map_hash += static_cast<uint32_t>(value);
@@ -354,9 +451,9 @@
         return false;
       }
       if (a.live_dex_registers_mask->IsBitSet(i)) {
-        DexRegisterLocation a_loc = dex_register_locations_.Get(
+        size_t a_loc = dex_register_locations_.Get(
             a.dex_register_locations_start_index + index_in_dex_register_locations);
-        DexRegisterLocation b_loc = dex_register_locations_.Get(
+        size_t b_loc = dex_register_locations_.Get(
             b.dex_register_locations_start_index + index_in_dex_register_locations);
         if (a_loc != b_loc) {
           return false;
@@ -369,21 +466,29 @@
 
   ArenaAllocator* allocator_;
   GrowableArray<StackMapEntry> stack_maps_;
-  GrowableArray<DexRegisterLocation> dex_register_locations_;
+
+  // A catalog of unique [location_kind, register_value] pairs (per method).
+  GrowableArray<DexRegisterLocation> location_catalog_entries_;
+  // Map from Dex register location catalog entries to their indices in the
+  // location catalog.
+  typedef HashMap<DexRegisterLocation, size_t, LocationCatalogEntriesIndicesEmptyFn,
+                  DexRegisterLocationHashFn> LocationCatalogEntriesIndices;
+  LocationCatalogEntriesIndices location_catalog_entries_indices_;
+
+  // A set of concatenated maps of Dex register locations indices to
+  // `location_catalog_entries_`.
+  GrowableArray<size_t> dex_register_locations_;
   GrowableArray<InlineInfoEntry> inline_infos_;
   int stack_mask_max_;
   uint32_t dex_pc_max_;
   uint32_t native_pc_offset_max_;
+  uint32_t register_mask_max_;
   size_t number_of_stack_maps_with_inline_info_;
 
   ArenaSafeMap<uint32_t, GrowableArray<uint32_t>> dex_map_hash_to_stack_map_indices_;
 
   static constexpr uint32_t kNoSameDexMapFound = -1;
 
-  ART_FRIEND_TEST(StackMapTest, Test1);
-  ART_FRIEND_TEST(StackMapTest, Test2);
-  ART_FRIEND_TEST(StackMapTest, TestNonLiveDexRegisters);
-
   DISALLOW_COPY_AND_ASSIGN(StackMapStream);
 };
 
diff --git a/compiler/optimizing/stack_map_test.cc b/compiler/optimizing/stack_map_test.cc
index e5a9790..8d160bc 100644
--- a/compiler/optimizing/stack_map_test.cc
+++ b/compiler/optimizing/stack_map_test.cc
@@ -31,6 +31,8 @@
   return true;
 }
 
+using Kind = DexRegisterLocation::Kind;
+
 TEST(StackMapTest, Test1) {
   ArenaPool pool;
   ArenaAllocator arena(&pool);
@@ -39,8 +41,8 @@
   ArenaBitVector sp_mask(&arena, 0, false);
   size_t number_of_dex_registers = 2;
   stream.AddStackMapEntry(0, 64, 0x3, &sp_mask, number_of_dex_registers, 0);
-  stream.AddDexRegisterEntry(0, DexRegisterLocation::Kind::kInStack, 0);
-  stream.AddDexRegisterEntry(1, DexRegisterLocation::Kind::kConstant, -2);
+  stream.AddDexRegisterEntry(0, Kind::kInStack, 0);         // Short location.
+  stream.AddDexRegisterEntry(1, Kind::kConstant, -2);       // Short location.
 
   size_t size = stream.ComputeNeededSize();
   void* memory = arena.Alloc(size, kArenaAllocMisc);
@@ -51,6 +53,16 @@
   ASSERT_EQ(0u, code_info.GetStackMaskSize());
   ASSERT_EQ(1u, code_info.GetNumberOfStackMaps());
 
+  uint32_t number_of_location_catalog_entries =
+      code_info.GetNumberOfDexRegisterLocationCatalogEntries();
+  ASSERT_EQ(2u, number_of_location_catalog_entries);
+  DexRegisterLocationCatalog location_catalog = code_info.GetDexRegisterLocationCatalog();
+  // The Dex register location catalog contains:
+  // - one 1-byte short Dex register location, and
+  // - one 5-byte large Dex register location.
+  size_t expected_location_catalog_size = 1u + 5u;
+  ASSERT_EQ(expected_location_catalog_size, location_catalog.Size());
+
   StackMap stack_map = code_info.GetStackMapAt(0);
   ASSERT_TRUE(stack_map.Equals(code_info.GetStackMapForDexPc(0)));
   ASSERT_TRUE(stack_map.Equals(code_info.GetStackMapForNativePcOffset(64)));
@@ -62,14 +74,40 @@
   ASSERT_TRUE(SameBits(stack_mask, sp_mask));
 
   ASSERT_TRUE(stack_map.HasDexRegisterMap(code_info));
-  DexRegisterMap dex_registers = code_info.GetDexRegisterMapOf(stack_map, number_of_dex_registers);
-  ASSERT_EQ(7u, dex_registers.Size());
-  DexRegisterLocation location0 = dex_registers.GetLocationKindAndValue(0, number_of_dex_registers);
-  DexRegisterLocation location1 = dex_registers.GetLocationKindAndValue(1, number_of_dex_registers);
-  ASSERT_EQ(DexRegisterLocation::Kind::kInStack, location0.GetKind());
-  ASSERT_EQ(DexRegisterLocation::Kind::kConstant, location1.GetKind());
-  ASSERT_EQ(DexRegisterLocation::Kind::kInStack, location0.GetInternalKind());
-  ASSERT_EQ(DexRegisterLocation::Kind::kConstantLargeValue, location1.GetInternalKind());
+  DexRegisterMap dex_register_map =
+      code_info.GetDexRegisterMapOf(stack_map, number_of_dex_registers);
+  ASSERT_TRUE(dex_register_map.IsDexRegisterLive(0));
+  ASSERT_TRUE(dex_register_map.IsDexRegisterLive(1));
+  ASSERT_EQ(2u, dex_register_map.GetNumberOfLiveDexRegisters(number_of_dex_registers));
+  // The Dex register map contains:
+  // - one 1-byte live bit mask, and
+  // - one 1-byte set of location catalog entry indices composed of two 2-bit values.
+  size_t expected_dex_register_map_size = 1u + 1u;
+  ASSERT_EQ(expected_dex_register_map_size, dex_register_map.Size());
+
+  ASSERT_EQ(Kind::kInStack,
+            dex_register_map.GetLocationKind(0, number_of_dex_registers, code_info));
+  ASSERT_EQ(Kind::kConstant,
+            dex_register_map.GetLocationKind(1, number_of_dex_registers, code_info));
+  ASSERT_EQ(Kind::kInStack,
+            dex_register_map.GetLocationInternalKind(0, number_of_dex_registers, code_info));
+  ASSERT_EQ(Kind::kConstantLargeValue,
+            dex_register_map.GetLocationInternalKind(1, number_of_dex_registers, code_info));
+  ASSERT_EQ(0, dex_register_map.GetStackOffsetInBytes(0, number_of_dex_registers, code_info));
+  ASSERT_EQ(-2, dex_register_map.GetConstant(1, number_of_dex_registers, code_info));
+
+  size_t index0 = dex_register_map.GetLocationCatalogEntryIndex(
+      0, number_of_dex_registers, number_of_location_catalog_entries);
+  size_t index1 = dex_register_map.GetLocationCatalogEntryIndex(
+      1, number_of_dex_registers, number_of_location_catalog_entries);
+  ASSERT_EQ(0u, index0);
+  ASSERT_EQ(1u, index1);
+  DexRegisterLocation location0 = location_catalog.GetDexRegisterLocation(index0);
+  DexRegisterLocation location1 = location_catalog.GetDexRegisterLocation(index1);
+  ASSERT_EQ(Kind::kInStack, location0.GetKind());
+  ASSERT_EQ(Kind::kConstant, location1.GetKind());
+  ASSERT_EQ(Kind::kInStack, location0.GetInternalKind());
+  ASSERT_EQ(Kind::kConstantLargeValue, location1.GetInternalKind());
   ASSERT_EQ(0, location0.GetValue());
   ASSERT_EQ(-2, location1.GetValue());
 
@@ -86,8 +124,8 @@
   sp_mask1.SetBit(4);
   size_t number_of_dex_registers = 2;
   stream.AddStackMapEntry(0, 64, 0x3, &sp_mask1, number_of_dex_registers, 2);
-  stream.AddDexRegisterEntry(0, DexRegisterLocation::Kind::kInStack, 0);
-  stream.AddDexRegisterEntry(1, DexRegisterLocation::Kind::kConstant, -2);
+  stream.AddDexRegisterEntry(0, Kind::kInStack, 0);         // Short location.
+  stream.AddDexRegisterEntry(1, Kind::kConstant, -2);       // Large location.
   stream.AddInlineInfoEntry(42);
   stream.AddInlineInfoEntry(82);
 
@@ -95,8 +133,8 @@
   sp_mask2.SetBit(3);
   sp_mask1.SetBit(8);
   stream.AddStackMapEntry(1, 128, 0xFF, &sp_mask2, number_of_dex_registers, 0);
-  stream.AddDexRegisterEntry(0, DexRegisterLocation::Kind::kInRegister, 18);
-  stream.AddDexRegisterEntry(1, DexRegisterLocation::Kind::kInFpuRegister, 3);
+  stream.AddDexRegisterEntry(0, Kind::kInRegister, 18);     // Short location.
+  stream.AddDexRegisterEntry(1, Kind::kInFpuRegister, 3);   // Short location.
 
   size_t size = stream.ComputeNeededSize();
   void* memory = arena.Alloc(size, kArenaAllocMisc);
@@ -107,6 +145,16 @@
   ASSERT_EQ(1u, code_info.GetStackMaskSize());
   ASSERT_EQ(2u, code_info.GetNumberOfStackMaps());
 
+  uint32_t number_of_location_catalog_entries =
+      code_info.GetNumberOfDexRegisterLocationCatalogEntries();
+  ASSERT_EQ(4u, number_of_location_catalog_entries);
+  DexRegisterLocationCatalog location_catalog = code_info.GetDexRegisterLocationCatalog();
+  // The Dex register location catalog contains:
+  // - three 1-byte short Dex register locations, and
+  // - one 5-byte large Dex register location.
+  size_t expected_location_catalog_size = 3u * 1u + 5u;
+  ASSERT_EQ(expected_location_catalog_size, location_catalog.Size());
+
   // First stack map.
   {
     StackMap stack_map = code_info.GetStackMapAt(0);
@@ -120,17 +168,40 @@
     ASSERT_TRUE(SameBits(stack_mask, sp_mask1));
 
     ASSERT_TRUE(stack_map.HasDexRegisterMap(code_info));
-    DexRegisterMap dex_registers =
+    DexRegisterMap dex_register_map =
         code_info.GetDexRegisterMapOf(stack_map, number_of_dex_registers);
-    ASSERT_EQ(7u, dex_registers.Size());
-    DexRegisterLocation location0 =
-        dex_registers.GetLocationKindAndValue(0, number_of_dex_registers);
-    DexRegisterLocation location1 =
-        dex_registers.GetLocationKindAndValue(1, number_of_dex_registers);
-    ASSERT_EQ(DexRegisterLocation::Kind::kInStack, location0.GetKind());
-    ASSERT_EQ(DexRegisterLocation::Kind::kConstant, location1.GetKind());
-    ASSERT_EQ(DexRegisterLocation::Kind::kInStack, location0.GetInternalKind());
-    ASSERT_EQ(DexRegisterLocation::Kind::kConstantLargeValue, location1.GetInternalKind());
+    ASSERT_TRUE(dex_register_map.IsDexRegisterLive(0));
+    ASSERT_TRUE(dex_register_map.IsDexRegisterLive(1));
+    ASSERT_EQ(2u, dex_register_map.GetNumberOfLiveDexRegisters(number_of_dex_registers));
+    // The Dex register map contains:
+    // - one 1-byte live bit mask, and
+    // - one 1-byte set of location catalog entry indices composed of two 2-bit values.
+    size_t expected_dex_register_map_size = 1u + 1u;
+    ASSERT_EQ(expected_dex_register_map_size, dex_register_map.Size());
+
+    ASSERT_EQ(Kind::kInStack,
+              dex_register_map.GetLocationKind(0, number_of_dex_registers, code_info));
+    ASSERT_EQ(Kind::kConstant,
+              dex_register_map.GetLocationKind(1, number_of_dex_registers, code_info));
+    ASSERT_EQ(Kind::kInStack,
+              dex_register_map.GetLocationInternalKind(0, number_of_dex_registers, code_info));
+    ASSERT_EQ(Kind::kConstantLargeValue,
+              dex_register_map.GetLocationInternalKind(1, number_of_dex_registers, code_info));
+    ASSERT_EQ(0, dex_register_map.GetStackOffsetInBytes(0, number_of_dex_registers, code_info));
+    ASSERT_EQ(-2, dex_register_map.GetConstant(1, number_of_dex_registers, code_info));
+
+    size_t index0 = dex_register_map.GetLocationCatalogEntryIndex(
+        0, number_of_dex_registers, number_of_location_catalog_entries);
+    size_t index1 = dex_register_map.GetLocationCatalogEntryIndex(
+        1, number_of_dex_registers, number_of_location_catalog_entries);
+    ASSERT_EQ(0u, index0);
+    ASSERT_EQ(1u, index1);
+    DexRegisterLocation location0 = location_catalog.GetDexRegisterLocation(index0);
+    DexRegisterLocation location1 = location_catalog.GetDexRegisterLocation(index1);
+    ASSERT_EQ(Kind::kInStack, location0.GetKind());
+    ASSERT_EQ(Kind::kConstant, location1.GetKind());
+    ASSERT_EQ(Kind::kInStack, location0.GetInternalKind());
+    ASSERT_EQ(Kind::kConstantLargeValue, location1.GetInternalKind());
     ASSERT_EQ(0, location0.GetValue());
     ASSERT_EQ(-2, location1.GetValue());
 
@@ -154,17 +225,40 @@
     ASSERT_TRUE(SameBits(stack_mask, sp_mask2));
 
     ASSERT_TRUE(stack_map.HasDexRegisterMap(code_info));
-    DexRegisterMap dex_registers =
+    DexRegisterMap dex_register_map =
         code_info.GetDexRegisterMapOf(stack_map, number_of_dex_registers);
-    ASSERT_EQ(3u, dex_registers.Size());
-    DexRegisterLocation location0 =
-        dex_registers.GetLocationKindAndValue(0, number_of_dex_registers);
-    DexRegisterLocation location1 =
-        dex_registers.GetLocationKindAndValue(1, number_of_dex_registers);
-    ASSERT_EQ(DexRegisterLocation::Kind::kInRegister, location0.GetKind());
-    ASSERT_EQ(DexRegisterLocation::Kind::kInFpuRegister, location1.GetKind());
-    ASSERT_EQ(DexRegisterLocation::Kind::kInRegister, location0.GetInternalKind());
-    ASSERT_EQ(DexRegisterLocation::Kind::kInFpuRegister, location1.GetInternalKind());
+    ASSERT_TRUE(dex_register_map.IsDexRegisterLive(0));
+    ASSERT_TRUE(dex_register_map.IsDexRegisterLive(1));
+    ASSERT_EQ(2u, dex_register_map.GetNumberOfLiveDexRegisters(number_of_dex_registers));
+    // The Dex register map contains:
+    // - one 1-byte live bit mask, and
+    // - one 1-byte set of location catalog entry indices composed of two 2-bit values.
+    size_t expected_dex_register_map_size = 1u + 1u;
+    ASSERT_EQ(expected_dex_register_map_size, dex_register_map.Size());
+
+    ASSERT_EQ(Kind::kInRegister,
+              dex_register_map.GetLocationKind(0, number_of_dex_registers, code_info));
+    ASSERT_EQ(Kind::kInFpuRegister,
+              dex_register_map.GetLocationKind(1, number_of_dex_registers, code_info));
+    ASSERT_EQ(Kind::kInRegister,
+              dex_register_map.GetLocationInternalKind(0, number_of_dex_registers, code_info));
+    ASSERT_EQ(Kind::kInFpuRegister,
+              dex_register_map.GetLocationInternalKind(1, number_of_dex_registers, code_info));
+    ASSERT_EQ(18, dex_register_map.GetMachineRegister(0, number_of_dex_registers, code_info));
+    ASSERT_EQ(3, dex_register_map.GetMachineRegister(1, number_of_dex_registers, code_info));
+
+    size_t index0 = dex_register_map.GetLocationCatalogEntryIndex(
+        0, number_of_dex_registers, number_of_location_catalog_entries);
+    size_t index1 = dex_register_map.GetLocationCatalogEntryIndex(
+        1, number_of_dex_registers, number_of_location_catalog_entries);
+    ASSERT_EQ(2u, index0);
+    ASSERT_EQ(3u, index1);
+    DexRegisterLocation location0 = location_catalog.GetDexRegisterLocation(index0);
+    DexRegisterLocation location1 = location_catalog.GetDexRegisterLocation(index1);
+    ASSERT_EQ(Kind::kInRegister, location0.GetKind());
+    ASSERT_EQ(Kind::kInFpuRegister, location1.GetKind());
+    ASSERT_EQ(Kind::kInRegister, location0.GetInternalKind());
+    ASSERT_EQ(Kind::kInFpuRegister, location1.GetInternalKind());
     ASSERT_EQ(18, location0.GetValue());
     ASSERT_EQ(3, location1.GetValue());
 
@@ -180,8 +274,8 @@
   ArenaBitVector sp_mask(&arena, 0, false);
   uint32_t number_of_dex_registers = 2;
   stream.AddStackMapEntry(0, 64, 0x3, &sp_mask, number_of_dex_registers, 0);
-  stream.AddDexRegisterEntry(0, DexRegisterLocation::Kind::kNone, 0);
-  stream.AddDexRegisterEntry(1, DexRegisterLocation::Kind::kConstant, -2);
+  stream.AddDexRegisterEntry(0, Kind::kNone, 0);            // No location.
+  stream.AddDexRegisterEntry(1, Kind::kConstant, -2);       // Large location.
 
   size_t size = stream.ComputeNeededSize();
   void* memory = arena.Alloc(size, kArenaAllocMisc);
@@ -189,14 +283,62 @@
   stream.FillIn(region);
 
   CodeInfo code_info(region);
+  ASSERT_EQ(0u, code_info.GetStackMaskSize());
+  ASSERT_EQ(1u, code_info.GetNumberOfStackMaps());
+
+  uint32_t number_of_location_catalog_entries =
+      code_info.GetNumberOfDexRegisterLocationCatalogEntries();
+  ASSERT_EQ(1u, number_of_location_catalog_entries);
+  DexRegisterLocationCatalog location_catalog = code_info.GetDexRegisterLocationCatalog();
+  // The Dex register location catalog contains:
+  // - one 5-byte large Dex register location.
+  size_t expected_location_catalog_size = 5u;
+  ASSERT_EQ(expected_location_catalog_size, location_catalog.Size());
+
   StackMap stack_map = code_info.GetStackMapAt(0);
+  ASSERT_TRUE(stack_map.Equals(code_info.GetStackMapForDexPc(0)));
+  ASSERT_TRUE(stack_map.Equals(code_info.GetStackMapForNativePcOffset(64)));
+  ASSERT_EQ(0u, stack_map.GetDexPc(code_info));
+  ASSERT_EQ(64u, stack_map.GetNativePcOffset(code_info));
+  ASSERT_EQ(0x3u, stack_map.GetRegisterMask(code_info));
+
   ASSERT_TRUE(stack_map.HasDexRegisterMap(code_info));
-  DexRegisterMap dex_registers = code_info.GetDexRegisterMapOf(stack_map, 2);
-  ASSERT_EQ(DexRegisterLocation::Kind::kNone,
-            dex_registers.GetLocationKind(0, number_of_dex_registers));
-  ASSERT_EQ(DexRegisterLocation::Kind::kConstant,
-            dex_registers.GetLocationKind(1, number_of_dex_registers));
-  ASSERT_EQ(-2, dex_registers.GetConstant(1, number_of_dex_registers));
+  DexRegisterMap dex_register_map =
+      code_info.GetDexRegisterMapOf(stack_map, number_of_dex_registers);
+  ASSERT_FALSE(dex_register_map.IsDexRegisterLive(0));
+  ASSERT_TRUE(dex_register_map.IsDexRegisterLive(1));
+  ASSERT_EQ(1u, dex_register_map.GetNumberOfLiveDexRegisters(number_of_dex_registers));
+  // The Dex register map contains:
+  // - one 1-byte live bit mask.
+  // No space is allocated for the sole location catalog entry index, as it is useless.
+  size_t expected_dex_register_map_size = 1u + 0u;
+  ASSERT_EQ(expected_dex_register_map_size, dex_register_map.Size());
+
+  ASSERT_EQ(Kind::kNone,
+            dex_register_map.GetLocationKind(0, number_of_dex_registers, code_info));
+  ASSERT_EQ(Kind::kConstant,
+            dex_register_map.GetLocationKind(1, number_of_dex_registers, code_info));
+  ASSERT_EQ(Kind::kNone,
+            dex_register_map.GetLocationInternalKind(0, number_of_dex_registers, code_info));
+  ASSERT_EQ(Kind::kConstantLargeValue,
+            dex_register_map.GetLocationInternalKind(1, number_of_dex_registers, code_info));
+  ASSERT_EQ(-2, dex_register_map.GetConstant(1, number_of_dex_registers, code_info));
+
+  size_t index0 = dex_register_map.GetLocationCatalogEntryIndex(
+      0, number_of_dex_registers, number_of_location_catalog_entries);
+  size_t index1 =  dex_register_map.GetLocationCatalogEntryIndex(
+      1, number_of_dex_registers, number_of_location_catalog_entries);
+  ASSERT_EQ(DexRegisterLocationCatalog::kNoLocationEntryIndex, index0);
+  ASSERT_EQ(0u, index1);
+  DexRegisterLocation location0 = location_catalog.GetDexRegisterLocation(index0);
+  DexRegisterLocation location1 = location_catalog.GetDexRegisterLocation(index1);
+  ASSERT_EQ(Kind::kNone, location0.GetKind());
+  ASSERT_EQ(Kind::kConstant, location1.GetKind());
+  ASSERT_EQ(Kind::kNone, location0.GetInternalKind());
+  ASSERT_EQ(Kind::kConstantLargeValue, location1.GetInternalKind());
+  ASSERT_EQ(0, location0.GetValue());
+  ASSERT_EQ(-2, location1.GetValue());
+
   ASSERT_FALSE(stack_map.HasInlineInfo(code_info));
 }
 
@@ -209,14 +351,21 @@
   StackMapStream stream(&arena);
 
   ArenaBitVector sp_mask(&arena, 0, false);
-  uint32_t number_of_dex_registers = 0xEA;
+  uint32_t number_of_dex_registers = 1024;
+  // Create the first stack map (and its Dex register map).
   stream.AddStackMapEntry(0, 64, 0x3, &sp_mask, number_of_dex_registers, 0);
-  for (uint32_t i = 0; i < number_of_dex_registers - 9; ++i) {
-    stream.AddDexRegisterEntry(i, DexRegisterLocation::Kind::kConstant, 0);
+  uint32_t number_of_dex_live_registers_in_dex_register_map_0 = number_of_dex_registers - 8;
+  for (uint32_t i = 0; i < number_of_dex_live_registers_in_dex_register_map_0; ++i) {
+    // Use two different Dex register locations to populate this map,
+    // as using a single value (in the whole CodeInfo object) would
+    // make this Dex register mapping data empty (see
+    // art::DexRegisterMap::SingleEntrySizeInBits).
+    stream.AddDexRegisterEntry(i, Kind::kConstant, i % 2);  // Short location.
   }
+  // Create the second stack map (and its Dex register map).
   stream.AddStackMapEntry(0, 64, 0x3, &sp_mask, number_of_dex_registers, 0);
   for (uint32_t i = 0; i < number_of_dex_registers; ++i) {
-    stream.AddDexRegisterEntry(i, DexRegisterLocation::Kind::kConstant, 0);
+    stream.AddDexRegisterEntry(i, Kind::kConstant, 0);  // Short location.
   }
 
   size_t size = stream.ComputeNeededSize();
@@ -225,10 +374,35 @@
   stream.FillIn(region);
 
   CodeInfo code_info(region);
-  StackMap stack_map = code_info.GetStackMapAt(1);
-  ASSERT_TRUE(stack_map.HasDexRegisterMap(code_info));
-  ASSERT_NE(stack_map.GetDexRegisterMapOffset(code_info), StackMap::kNoDexRegisterMap);
-  ASSERT_EQ(stack_map.GetDexRegisterMapOffset(code_info), StackMap::kNoDexRegisterMapSmallEncoding);
+  // The location catalog contains two entries (DexRegisterLocation(kConstant, 0)
+  // and DexRegisterLocation(kConstant, 1)), therefore the location catalog index
+  // has a size of 1 bit.
+  uint32_t number_of_location_catalog_entries =
+      code_info.GetNumberOfDexRegisterLocationCatalogEntries();
+  ASSERT_EQ(2u, number_of_location_catalog_entries);
+  ASSERT_EQ(1u, DexRegisterMap::SingleEntrySizeInBits(number_of_location_catalog_entries));
+
+  // The first Dex register map contains:
+  // - a live register bit mask for 1024 registers (that is, 128 bytes of
+  //   data); and
+  // - Dex register mapping information for 1016 1-bit Dex (live) register
+  //   locations (that is, 127 bytes of data).
+  // Hence it has a size of 255 bytes, and therefore...
+  ASSERT_EQ(128u, DexRegisterMap::GetLiveBitMaskSize(number_of_dex_registers));
+  StackMap stack_map0 = code_info.GetStackMapAt(0);
+  DexRegisterMap dex_register_map0 =
+      code_info.GetDexRegisterMapOf(stack_map0, number_of_dex_registers);
+  ASSERT_EQ(127u, dex_register_map0.GetLocationMappingDataSize(number_of_dex_registers,
+                                                               number_of_location_catalog_entries));
+  ASSERT_EQ(255u, dex_register_map0.Size());
+
+  StackMap stack_map1 = code_info.GetStackMapAt(1);
+  ASSERT_TRUE(stack_map1.HasDexRegisterMap(code_info));
+  // ...the offset of the second Dex register map (relative to the
+  // beginning of the Dex register maps region) is 255 (i.e.,
+  // kNoDexRegisterMapSmallEncoding).
+  ASSERT_NE(stack_map1.GetDexRegisterMapOffset(code_info), StackMap::kNoDexRegisterMap);
+  ASSERT_EQ(stack_map1.GetDexRegisterMapOffset(code_info), 0xFFu);
 }
 
 TEST(StackMapTest, TestShareDexRegisterMap) {
@@ -240,16 +414,16 @@
   uint32_t number_of_dex_registers = 2;
   // First stack map.
   stream.AddStackMapEntry(0, 64, 0x3, &sp_mask, number_of_dex_registers, 0);
-  stream.AddDexRegisterEntry(0, DexRegisterLocation::Kind::kInRegister, 0);
-  stream.AddDexRegisterEntry(1, DexRegisterLocation::Kind::kConstant, -2);
+  stream.AddDexRegisterEntry(0, Kind::kInRegister, 0);  // Short location.
+  stream.AddDexRegisterEntry(1, Kind::kConstant, -2);   // Large location.
   // Second stack map, which should share the same dex register map.
   stream.AddStackMapEntry(0, 64, 0x3, &sp_mask, number_of_dex_registers, 0);
-  stream.AddDexRegisterEntry(0, DexRegisterLocation::Kind::kInRegister, 0);
-  stream.AddDexRegisterEntry(1, DexRegisterLocation::Kind::kConstant, -2);
+  stream.AddDexRegisterEntry(0, Kind::kInRegister, 0);  // Short location.
+  stream.AddDexRegisterEntry(1, Kind::kConstant, -2);   // Large location.
   // Third stack map (doesn't share the dex register map).
   stream.AddStackMapEntry(0, 64, 0x3, &sp_mask, number_of_dex_registers, 0);
-  stream.AddDexRegisterEntry(0, DexRegisterLocation::Kind::kInRegister, 2);
-  stream.AddDexRegisterEntry(1, DexRegisterLocation::Kind::kConstant, -2);
+  stream.AddDexRegisterEntry(0, Kind::kInRegister, 2);  // Short location.
+  stream.AddDexRegisterEntry(1, Kind::kConstant, -2);   // Large location.
 
   size_t size = stream.ComputeNeededSize();
   void* memory = arena.Alloc(size, kArenaAllocMisc);
@@ -260,20 +434,20 @@
   // Verify first stack map.
   StackMap sm0 = ci.GetStackMapAt(0);
   DexRegisterMap dex_registers0 = ci.GetDexRegisterMapOf(sm0, number_of_dex_registers);
-  ASSERT_EQ(0, dex_registers0.GetMachineRegister(0, number_of_dex_registers));
-  ASSERT_EQ(-2, dex_registers0.GetConstant(1, number_of_dex_registers));
+  ASSERT_EQ(0, dex_registers0.GetMachineRegister(0, number_of_dex_registers, ci));
+  ASSERT_EQ(-2, dex_registers0.GetConstant(1, number_of_dex_registers, ci));
 
   // Verify second stack map.
   StackMap sm1 = ci.GetStackMapAt(1);
   DexRegisterMap dex_registers1 = ci.GetDexRegisterMapOf(sm1, number_of_dex_registers);
-  ASSERT_EQ(0, dex_registers1.GetMachineRegister(0, number_of_dex_registers));
-  ASSERT_EQ(-2, dex_registers1.GetConstant(1, number_of_dex_registers));
+  ASSERT_EQ(0, dex_registers1.GetMachineRegister(0, number_of_dex_registers, ci));
+  ASSERT_EQ(-2, dex_registers1.GetConstant(1, number_of_dex_registers, ci));
 
   // Verify third stack map.
   StackMap sm2 = ci.GetStackMapAt(2);
   DexRegisterMap dex_registers2 = ci.GetDexRegisterMapOf(sm2, number_of_dex_registers);
-  ASSERT_EQ(2, dex_registers2.GetMachineRegister(0, number_of_dex_registers));
-  ASSERT_EQ(-2, dex_registers2.GetConstant(1, number_of_dex_registers));
+  ASSERT_EQ(2, dex_registers2.GetMachineRegister(0, number_of_dex_registers, ci));
+  ASSERT_EQ(-2, dex_registers2.GetConstant(1, number_of_dex_registers, ci));
 
   // Verify dex register map offsets.
   ASSERT_EQ(sm0.GetDexRegisterMapOffset(ci), sm1.GetDexRegisterMapOffset(ci));
@@ -281,4 +455,39 @@
   ASSERT_NE(sm1.GetDexRegisterMapOffset(ci), sm2.GetDexRegisterMapOffset(ci));
 }
 
+TEST(StackMapTest, TestNoDexRegisterMap) {
+  ArenaPool pool;
+  ArenaAllocator arena(&pool);
+  StackMapStream stream(&arena);
+
+  ArenaBitVector sp_mask(&arena, 0, false);
+  uint32_t number_of_dex_registers = 0;
+  stream.AddStackMapEntry(0, 64, 0x3, &sp_mask, number_of_dex_registers, 0);
+
+  size_t size = stream.ComputeNeededSize();
+  void* memory = arena.Alloc(size, kArenaAllocMisc);
+  MemoryRegion region(memory, size);
+  stream.FillIn(region);
+
+  CodeInfo code_info(region);
+  ASSERT_EQ(0u, code_info.GetStackMaskSize());
+  ASSERT_EQ(1u, code_info.GetNumberOfStackMaps());
+
+  uint32_t number_of_location_catalog_entries =
+      code_info.GetNumberOfDexRegisterLocationCatalogEntries();
+  ASSERT_EQ(0u, number_of_location_catalog_entries);
+  DexRegisterLocationCatalog location_catalog = code_info.GetDexRegisterLocationCatalog();
+  ASSERT_EQ(0u, location_catalog.Size());
+
+  StackMap stack_map = code_info.GetStackMapAt(0);
+  ASSERT_TRUE(stack_map.Equals(code_info.GetStackMapForDexPc(0)));
+  ASSERT_TRUE(stack_map.Equals(code_info.GetStackMapForNativePcOffset(64)));
+  ASSERT_EQ(0u, stack_map.GetDexPc(code_info));
+  ASSERT_EQ(64u, stack_map.GetNativePcOffset(code_info));
+  ASSERT_EQ(0x3u, stack_map.GetRegisterMask(code_info));
+
+  ASSERT_FALSE(stack_map.HasDexRegisterMap(code_info));
+  ASSERT_FALSE(stack_map.HasInlineInfo(code_info));
+}
+
 }  // namespace art
diff --git a/dex2oat/Android.mk b/dex2oat/Android.mk
index 3f15964..321cd75 100644
--- a/dex2oat/Android.mk
+++ b/dex2oat/Android.mk
@@ -46,8 +46,8 @@
 
 # We always build dex2oat and dependencies, even if the host build is otherwise disabled, since they are used to cross compile for the target.
 ifeq ($(ART_BUILD_HOST_NDEBUG),true)
-  $(eval $(call build-art-executable,dex2oat,$(DEX2OAT_SRC_FILES),libart-compiler libziparchive-host,art/compiler,host,ndebug,$(dex2oat_host_arch)))
+  $(eval $(call build-art-executable,dex2oat,$(DEX2OAT_SRC_FILES),libcutils libart-compiler libziparchive-host,art/compiler,host,ndebug,$(dex2oat_host_arch)))
 endif
 ifeq ($(ART_BUILD_HOST_DEBUG),true)
-  $(eval $(call build-art-executable,dex2oat,$(DEX2OAT_SRC_FILES),libartd-compiler libziparchive-host,art/compiler,host,debug,$(dex2oat_host_arch)))
+  $(eval $(call build-art-executable,dex2oat,$(DEX2OAT_SRC_FILES),libcutils libartd-compiler libziparchive-host,art/compiler,host,debug,$(dex2oat_host_arch)))
 endif
diff --git a/dex2oat/dex2oat.cc b/dex2oat/dex2oat.cc
index dfea783..2e1b7ae 100644
--- a/dex2oat/dex2oat.cc
+++ b/dex2oat/dex2oat.cc
@@ -1053,7 +1053,12 @@
     }
 
     verification_results_.reset(new VerificationResults(compiler_options_.get()));
-    callbacks_.reset(new QuickCompilerCallbacks(verification_results_.get(), &method_inliner_map_));
+    callbacks_.reset(new QuickCompilerCallbacks(
+        verification_results_.get(),
+        &method_inliner_map_,
+        image_ ?
+            CompilerCallbacks::CallbackMode::kCompileBootImage :
+            CompilerCallbacks::CallbackMode::kCompileApp));
     runtime_options.push_back(std::make_pair("compilercallbacks", callbacks_.get()));
     runtime_options.push_back(
         std::make_pair("imageinstructionset", GetInstructionSetString(instruction_set_)));
@@ -1224,19 +1229,16 @@
       ClassLinker* class_linker = Runtime::Current()->GetClassLinker();
       OpenClassPathFiles(runtime_->GetClassPathString(), dex_files_, &class_path_files_);
       ScopedObjectAccess soa(self);
-      std::vector<const DexFile*> class_path_files(dex_files_);
+
+      // Classpath: first the class-path given.
+      std::vector<const DexFile*> class_path_files;
       for (auto& class_path_file : class_path_files_) {
         class_path_files.push_back(class_path_file.get());
       }
+      // Then the dex files we'll compile. Thus we'll resolve the class-path first.
+      class_path_files.insert(class_path_files.end(), dex_files_.begin(), dex_files_.end());
 
-      for (size_t i = 0; i < class_path_files.size(); i++) {
-        class_linker->RegisterDexFile(*class_path_files[i]);
-      }
-      soa.Env()->AllocObject(WellKnownClasses::dalvik_system_PathClassLoader);
-      ScopedLocalRef<jobject> class_loader_local(soa.Env(),
-          soa.Env()->AllocObject(WellKnownClasses::dalvik_system_PathClassLoader));
-      class_loader = soa.Env()->NewGlobalRef(class_loader_local.get());
-      Runtime::Current()->SetCompileTimeClassPath(class_loader, class_path_files);
+      class_loader = class_linker->CreatePathClassLoader(self, class_path_files);
     }
 
     driver_.reset(new CompilerDriver(compiler_options_.get(),
diff --git a/oatdump/oatdump.cc b/oatdump/oatdump.cc
index daca971..322d3aa 100644
--- a/oatdump/oatdump.cc
+++ b/oatdump/oatdump.cc
@@ -1597,7 +1597,7 @@
           os << StringPrintf("null   %s\n", PrettyDescriptor(field->GetTypeDescriptor()).c_str());
         } else {
           // Grab the field type without causing resolution.
-          mirror::Class* field_type = field->GetType(false);
+          mirror::Class* field_type = field->GetType<false>();
           if (field_type != nullptr) {
             PrettyObjectValue(os, field_type, value);
           } else {
@@ -2158,16 +2158,12 @@
   }
 
   // Need a class loader.
-  soa.Env()->AllocObject(WellKnownClasses::dalvik_system_PathClassLoader);
-  ScopedLocalRef<jobject> class_loader_local(soa.Env(),
-      soa.Env()->AllocObject(WellKnownClasses::dalvik_system_PathClassLoader));
-  jobject class_loader = soa.Env()->NewGlobalRef(class_loader_local.get());
   // Fake that we're a compiler.
   std::vector<const DexFile*> class_path;
   for (auto& dex_file : dex_files) {
     class_path.push_back(dex_file.get());
   }
-  runtime->SetCompileTimeClassPath(class_loader, class_path);
+  jobject class_loader = class_linker->CreatePathClassLoader(self, class_path);
 
   // Use the class loader while dumping.
   StackHandleScope<1> scope(self);
diff --git a/patchoat/Android.mk b/patchoat/Android.mk
index 1e16096..68ca923 100644
--- a/patchoat/Android.mk
+++ b/patchoat/Android.mk
@@ -38,8 +38,8 @@
 
 # We always build patchoat and dependencies, even if the host build is otherwise disabled, since they are used to cross compile for the target.
 ifeq ($(ART_BUILD_HOST_NDEBUG),true)
-  $(eval $(call build-art-executable,patchoat,$(PATCHOAT_SRC_FILES),,art/compiler,host,ndebug))
+  $(eval $(call build-art-executable,patchoat,$(PATCHOAT_SRC_FILES),libcutils,art/compiler,host,ndebug))
 endif
 ifeq ($(ART_BUILD_HOST_DEBUG),true)
-  $(eval $(call build-art-executable,patchoat,$(PATCHOAT_SRC_FILES),,art/compiler,host,debug))
+  $(eval $(call build-art-executable,patchoat,$(PATCHOAT_SRC_FILES),libcutils,art/compiler,host,debug))
 endif
diff --git a/runtime/Android.mk b/runtime/Android.mk
index 5548d94..dde5407 100644
--- a/runtime/Android.mk
+++ b/runtime/Android.mk
@@ -103,6 +103,7 @@
   mirror/array.cc \
   mirror/class.cc \
   mirror/dex_cache.cc \
+  mirror/field.cc \
   mirror/object.cc \
   mirror/reference.cc \
   mirror/stack_trace_element.cc \
diff --git a/runtime/arch/mips/quick_entrypoints_mips.S b/runtime/arch/mips/quick_entrypoints_mips.S
index 16f0e70..0c2250e 100644
--- a/runtime/arch/mips/quick_entrypoints_mips.S
+++ b/runtime/arch/mips/quick_entrypoints_mips.S
@@ -1094,7 +1094,7 @@
     lw      $a0, ARG_SLOT_SIZE($sp)       # load resolved method to $a0
     RESTORE_REFS_AND_ARGS_CALLEE_SAVE_FRAME
     move    $t9, $v0               # code pointer must be in $t9 to generate the global pointer
-    jalr    $zero, $v0             # tail call to method
+    jalr    $zero, $t9             # tail call to method
     nop
 1:
     RESTORE_REFS_AND_ARGS_CALLEE_SAVE_FRAME
@@ -1203,29 +1203,28 @@
     .cpload  $t9
     move     $ra, $zero     # link register is to here, so clobber with 0 for later checks
 
+    SETUP_REFS_ONLY_CALLEE_SAVE_FRAME
     addiu    $sp, $sp, -16  # allocate temp storage on the stack
     .cfi_adjust_cfa_offset 16
-    sw       $v0, 12($sp)
-    .cfi_rel_offset 2, 32
-    sw       $v1, 8($sp)
-    .cfi_rel_offset 3, 36
-    s.d      $f0, 0($sp)
-    SETUP_REFS_ONLY_CALLEE_SAVE_FRAME
+    sw       $v0, ARG_SLOT_SIZE+12($sp)
+    .cfi_rel_offset 2, ARG_SLOT_SIZE+12
+    sw       $v1, ARG_SLOT_SIZE+8($sp)
+    .cfi_rel_offset 3, ARG_SLOT_SIZE+8
+    s.d      $f0, ARG_SLOT_SIZE($sp)
     s.d      $f0, 16($sp)   # pass fpr result
     move     $a2, $v0       # pass gpr result
     move     $a3, $v1
-    addiu    $a1, $sp, ARG_SLOT_SIZE   # pass $sp (remove arg slots)
+    addiu    $a1, $sp, ARG_SLOT_SIZE+16   # pass $sp (remove arg slots and temp storage)
     jal      artInstrumentationMethodExitFromCode  # (Thread*, SP, gpr_res, fpr_res)
     move     $a0, rSELF     # pass Thread::Current
-    move     $t0, $v0       # set aside returned link register
+    move     $t9, $v0       # set aside returned link register
     move     $ra, $v1       # set link register for deoptimization
-    addiu    $sp, $sp, ARG_SLOT_SIZE+FRAME_SIZE_REFS_ONLY_CALLEE_SAVE  # args slot + refs_only callee save frame
-    lw       $v0, 12($sp)   # restore return values
-    lw       $v1, 8($sp)
-    l.d      $f0, 0($sp)
-    jalr     $zero, $t0     # return
-    addiu    $sp, $sp, 16   # remove temp storage from stack
-    .cfi_adjust_cfa_offset -16
+    lw       $v0, ARG_SLOT_SIZE+12($sp)   # restore return values
+    lw       $v1, ARG_SLOT_SIZE+8($sp)
+    l.d      $f0, ARG_SLOT_SIZE($sp)
+    jalr     $zero, $t9     # return
+    addiu    $sp, $sp, ARG_SLOT_SIZE+FRAME_SIZE_REFS_ONLY_CALLEE_SAVE+16  # restore stack 
+    .cfi_adjust_cfa_offset -(ARG_SLOT_SIZE+FRAME_SIZE_REFS_ONLY_CALLEE_SAVE+16)
 END art_quick_instrumentation_exit
 
     /*
diff --git a/runtime/arch/mips64/quick_entrypoints_mips64.S b/runtime/arch/mips64/quick_entrypoints_mips64.S
index 8cb95f1..697bf00 100644
--- a/runtime/arch/mips64/quick_entrypoints_mips64.S
+++ b/runtime/arch/mips64/quick_entrypoints_mips64.S
@@ -1504,11 +1504,11 @@
     move     $a1, $t0          # pass $sp
     jal      artInstrumentationMethodExitFromCode  # (Thread*, SP, gpr_res, fpr_res)
     move     $a0, rSELF        # pass Thread::Current
-    move     $t0, $v0          # set aside returned link register
+    move     $t9, $v0          # set aside returned link register
     move     $ra, $v1          # set link register for deoptimization
     ld       $v0, 0($sp)       # restore return values
     l.d      $f0, 8($sp)
-    jalr     $zero, $t0        # return
+    jalr     $zero, $t9        # return
     daddiu   $sp, $sp, 16+FRAME_SIZE_REFS_ONLY_CALLEE_SAVE  # 16 bytes of saved values + ref_only callee save frame
     .cfi_adjust_cfa_offset -(16+FRAME_SIZE_REFS_ONLY_CALLEE_SAVE)
 END art_quick_instrumentation_exit
diff --git a/runtime/base/hash_map.h b/runtime/base/hash_map.h
index c0f903f..eab80ff 100644
--- a/runtime/base/hash_map.h
+++ b/runtime/base/hash_map.h
@@ -48,7 +48,7 @@
   Fn fn_;
 };
 
-template <class Key, class Value, class EmptyFn = DefaultEmptyFn<Key>,
+template <class Key, class Value, class EmptyFn,
     class HashFn = std::hash<Key>, class Pred = std::equal_to<Key>,
     class Alloc = std::allocator<std::pair<Key, Value>>>
 class HashMap : public HashSet<std::pair<Key, Value>, EmptyFn, HashMapWrapper<HashFn>,
diff --git a/runtime/check_reference_map_visitor.h b/runtime/check_reference_map_visitor.h
index 204546d..5d9cd35 100644
--- a/runtime/check_reference_map_visitor.h
+++ b/runtime/check_reference_map_visitor.h
@@ -75,7 +75,7 @@
       int reg = registers[i];
       CHECK(reg < m->GetCodeItem()->registers_size_);
       DexRegisterLocation location =
-          dex_register_map.GetLocationKindAndValue(reg, number_of_dex_registers);
+          dex_register_map.GetDexRegisterLocation(reg, number_of_dex_registers, code_info);
       switch (location.GetKind()) {
         case DexRegisterLocation::Kind::kNone:
           // Not set, should not be a reference.
diff --git a/runtime/class_linker.cc b/runtime/class_linker.cc
index b0708a6..a89196d 100644
--- a/runtime/class_linker.cc
+++ b/runtime/class_linker.cc
@@ -56,6 +56,7 @@
 #include "mirror/class-inl.h"
 #include "mirror/class_loader.h"
 #include "mirror/dex_cache-inl.h"
+#include "mirror/field.h"
 #include "mirror/iftable-inl.h"
 #include "mirror/object-inl.h"
 #include "mirror/object_array-inl.h"
@@ -313,7 +314,7 @@
   java_lang_String->SetObjectSize(mirror::String::InstanceSize());
   mirror::Class::SetStatus(java_lang_String, mirror::Class::kStatusResolved, self);
 
-  // Setup Reference.
+  // Setup java.lang.ref.Reference.
   Handle<mirror::Class> java_lang_ref_Reference(hs.NewHandle(
       AllocClass(self, java_lang_Class.Get(), mirror::Reference::ClassSize())));
   mirror::Reference::SetClass(java_lang_ref_Reference.Get());
@@ -321,7 +322,7 @@
   mirror::Class::SetStatus(java_lang_ref_Reference, mirror::Class::kStatusResolved, self);
 
   // Create storage for root classes, save away our work so far (requires descriptors).
-  class_roots_ = GcRoot<mirror::ObjectArray<mirror::Class> >(
+  class_roots_ = GcRoot<mirror::ObjectArray<mirror::Class>>(
       mirror::ObjectArray<mirror::Class>::Alloc(self, object_array_class.Get(),
                                                 kClassRootsMax));
   CHECK(!class_roots_.IsNull());
@@ -531,6 +532,19 @@
   mirror::Class* java_lang_reflect_Proxy = FindSystemClass(self, "Ljava/lang/reflect/Proxy;");
   SetClassRoot(kJavaLangReflectProxy, java_lang_reflect_Proxy);
 
+  // Create java.lang.reflect.Field.class root.
+  mirror::Class* java_lang_reflect_Field = FindSystemClass(self, "Ljava/lang/reflect/Field;");
+  CHECK(java_lang_reflect_Field != nullptr);
+  SetClassRoot(kJavaLangReflectField, java_lang_reflect_Field);
+  mirror::Field::SetClass(java_lang_reflect_Field);
+
+  // Create java.lang.reflect.Field array root.
+  mirror::Class* java_lang_reflect_Field_array =
+      FindSystemClass(self, "[Ljava/lang/reflect/Field;");
+  CHECK(java_lang_reflect_Field_array != nullptr);
+  SetClassRoot(kJavaLangReflectFieldArrayClass, java_lang_reflect_Field_array);
+  mirror::Field::SetArrayClass(java_lang_reflect_Field_array);
+
   // java.lang.ref classes need to be specially flagged, but otherwise are normal classes
   // finish initializing Reference class
   mirror::Class::SetStatus(java_lang_ref_Reference, mirror::Class::kStatusNotReady, self);
@@ -818,9 +832,10 @@
   VLOG(startup) << "ClassLinker::InitFromImage entering";
   CHECK(!init_done_);
 
-  Thread* self = Thread::Current();
-  gc::Heap* heap = Runtime::Current()->GetHeap();
-  gc::space::ImageSpace* space = heap->GetImageSpace();
+  Runtime* const runtime = Runtime::Current();
+  Thread* const self = Thread::Current();
+  gc::Heap* const heap = runtime->GetHeap();
+  gc::space::ImageSpace* const space = heap->GetImageSpace();
   dex_cache_image_class_lookup_required_ = true;
   CHECK(space != nullptr);
   OatFile& oat_file = GetImageOatFile(space);
@@ -875,7 +890,7 @@
   // bitmap walk.
   mirror::ArtMethod::SetClass(GetClassRoot(kJavaLangReflectArtMethod));
   size_t art_method_object_size = mirror::ArtMethod::GetJavaLangReflectArtMethod()->GetObjectSize();
-  if (!Runtime::Current()->IsAotCompiler()) {
+  if (!runtime->IsAotCompiler()) {
     // Aot compiler supports having an image with a different pointer size than the runtime. This
     // happens on the host for compile 32 bit tests since we use a 64 bit libart compiler. We may
     // also use 32 bit dex2oat on a system with 64 bit apps.
@@ -890,7 +905,6 @@
   }
 
   // Set entry point to interpreter if in InterpretOnly mode.
-  Runtime* runtime = Runtime::Current();
   if (!runtime->IsAotCompiler() && runtime->GetInstrumentation()->InterpretOnly()) {
     heap->VisitObjects(InitFromImageInterpretOnlyCallback, this);
   }
@@ -903,6 +917,8 @@
   array_iftable_ = GcRoot<mirror::IfTable>(GetClassRoot(kObjectArrayClass)->GetIfTable());
   DCHECK_EQ(array_iftable_.Read(), GetClassRoot(kBooleanArrayClass)->GetIfTable());
   // String class root was set above
+  mirror::Field::SetClass(GetClassRoot(kJavaLangReflectField));
+  mirror::Field::SetArrayClass(GetClassRoot(kJavaLangReflectFieldArrayClass));
   mirror::Reference::SetClass(GetClassRoot(kJavaLangRefReference));
   mirror::ArtField::SetClass(GetClassRoot(kJavaLangReflectArtField));
   mirror::BooleanArray::SetArrayClass(GetClassRoot(kBooleanArrayClass));
@@ -1088,6 +1104,8 @@
   mirror::Reference::ResetClass();
   mirror::ArtField::ResetClass();
   mirror::ArtMethod::ResetClass();
+  mirror::Field::ResetClass();
+  mirror::Field::ResetArrayClass();
   mirror::BooleanArray::ResetArrayClass();
   mirror::ByteArray::ResetArrayClass();
   mirror::CharArray::ResetArrayClass();
@@ -1372,38 +1390,6 @@
       self->SetException(pre_allocated);
       return nullptr;
     }
-  } else if (Runtime::Current()->UseCompileTimeClassPath()) {
-    // First try with the bootstrap class loader.
-    if (class_loader.Get() != nullptr) {
-      klass = LookupClass(self, descriptor, hash, nullptr);
-      if (klass != nullptr) {
-        return EnsureResolved(self, descriptor, klass);
-      }
-    }
-    // If the lookup failed search the boot class path. We don't perform a recursive call to avoid
-    // a NoClassDefFoundError being allocated.
-    ClassPathEntry pair = FindInClassPath(descriptor, hash, boot_class_path_);
-    if (pair.second != nullptr) {
-      return DefineClass(self, descriptor, hash, NullHandle<mirror::ClassLoader>(), *pair.first,
-                         *pair.second);
-    }
-    // Next try the compile time class path.
-    const std::vector<const DexFile*>* class_path;
-    {
-      ScopedObjectAccessUnchecked soa(self);
-      ScopedLocalRef<jobject> jclass_loader(soa.Env(),
-                                            soa.AddLocalReference<jobject>(class_loader.Get()));
-      class_path = &Runtime::Current()->GetCompileTimeClassPath(jclass_loader.get());
-    }
-    pair = FindInClassPath(descriptor, hash, *class_path);
-    if (pair.second != nullptr) {
-      return DefineClass(self, descriptor, hash, class_loader, *pair.first, *pair.second);
-    } else {
-      // Use the pre-allocated NCDFE at compile time to avoid wasting time constructing exceptions.
-      mirror::Throwable* pre_allocated = Runtime::Current()->GetPreAllocatedNoClassDefFoundError();
-      self->SetException(pre_allocated);
-      return nullptr;
-    }
   } else {
     ScopedObjectAccessUnchecked soa(self);
     mirror::Class* cp_klass = FindClassInPathClassLoader(soa, self, descriptor, hash,
@@ -1411,6 +1397,14 @@
     if (cp_klass != nullptr) {
       return cp_klass;
     }
+
+    if (Runtime::Current()->IsAotCompiler()) {
+      // Oops, compile-time, can't run actual class-loader code.
+      mirror::Throwable* pre_allocated = Runtime::Current()->GetPreAllocatedNoClassDefFoundError();
+      self->SetException(pre_allocated);
+      return nullptr;
+    }
+
     ScopedLocalRef<jobject> class_loader_object(soa.Env(),
                                                 soa.AddLocalReference<jobject>(class_loader.Get()));
     std::string class_name_string(DescriptorToDot(descriptor));
@@ -1767,7 +1761,7 @@
     return;  // No direct methods => no static methods.
   }
   Runtime* runtime = Runtime::Current();
-  if (!runtime->IsStarted() || runtime->UseCompileTimeClassPath()) {
+  if (!runtime->IsStarted()) {
     if (runtime->IsAotCompiler() || runtime->GetHeap()->HasImageSpace()) {
       return;  // OAT file unavailable.
     }
@@ -1907,7 +1901,7 @@
 
 
   bool has_oat_class = false;
-  if (Runtime::Current()->IsStarted() && !Runtime::Current()->UseCompileTimeClassPath()) {
+  if (Runtime::Current()->IsStarted() && !Runtime::Current()->IsAotCompiler()) {
     OatFile::OatClass oat_class = FindOatClass(dex_file, klass->GetDexClassDefIndex(),
                                                &has_oat_class);
     if (has_oat_class) {
@@ -2808,7 +2802,7 @@
   // classes.
   if (Runtime::Current()->IsAotCompiler()) {
     // Are we compiling the bootclasspath?
-    if (!Runtime::Current()->UseCompileTimeClassPath()) {
+    if (Runtime::Current()->GetCompilerCallbacks()->IsBootImage()) {
       return false;
     }
     // We are compiling an app (not the image).
@@ -5213,10 +5207,12 @@
     "Ljava/lang/ref/Reference;",
     "Ljava/lang/reflect/ArtField;",
     "Ljava/lang/reflect/ArtMethod;",
+    "Ljava/lang/reflect/Field;",
     "Ljava/lang/reflect/Proxy;",
     "[Ljava/lang/String;",
     "[Ljava/lang/reflect/ArtField;",
     "[Ljava/lang/reflect/ArtMethod;",
+    "[Ljava/lang/reflect/Field;",
     "Ljava/lang/ClassLoader;",
     "Ljava/lang/Throwable;",
     "Ljava/lang/ClassNotFoundException;",
@@ -5319,4 +5315,95 @@
   }
 }
 
+jobject ClassLinker::CreatePathClassLoader(Thread* self, std::vector<const DexFile*>& dex_files) {
+  // SOAAlreadyRunnable is protected, and we need something to add a global reference.
+  // We could move the jobject to the callers, but all call-sites do this...
+  ScopedObjectAccessUnchecked soa(self);
+
+  // Register the dex files.
+  for (const DexFile* dex_file : dex_files) {
+    RegisterDexFile(*dex_file);
+  }
+
+  // For now, create a libcore-level DexFile for each ART DexFile. This "explodes" multidex.
+  StackHandleScope<11> hs(self);
+
+  Handle<mirror::ArtField> h_dex_elements_field =
+      hs.NewHandle(soa.DecodeField(WellKnownClasses::dalvik_system_DexPathList_dexElements));
+
+  mirror::Class* dex_elements_class = h_dex_elements_field->GetType<true>();
+  DCHECK(dex_elements_class != nullptr);
+  DCHECK(dex_elements_class->IsArrayClass());
+  Handle<mirror::ObjectArray<mirror::Object>> h_dex_elements(hs.NewHandle(
+      mirror::ObjectArray<mirror::Object>::Alloc(self, dex_elements_class, dex_files.size())));
+  Handle<mirror::Class> h_dex_element_class =
+      hs.NewHandle(dex_elements_class->GetComponentType());
+
+  Handle<mirror::ArtField> h_element_file_field =
+      hs.NewHandle(
+          soa.DecodeField(WellKnownClasses::dalvik_system_DexPathList__Element_dexFile));
+  DCHECK_EQ(h_dex_element_class.Get(), h_element_file_field->GetDeclaringClass());
+
+  Handle<mirror::ArtField> h_cookie_field =
+      hs.NewHandle(soa.DecodeField(WellKnownClasses::dalvik_system_DexFile_cookie));
+  DCHECK_EQ(h_cookie_field->GetDeclaringClass(), h_element_file_field->GetType<false>());
+
+  // Fill the elements array.
+  int32_t index = 0;
+  for (const DexFile* dex_file : dex_files) {
+    StackHandleScope<3> hs2(self);
+
+    Handle<mirror::LongArray> h_long_array = hs2.NewHandle(mirror::LongArray::Alloc(self, 1));
+    DCHECK(h_long_array.Get() != nullptr);
+    h_long_array->Set(0, reinterpret_cast<intptr_t>(dex_file));
+
+    Handle<mirror::Object> h_dex_file = hs2.NewHandle(
+        h_cookie_field->GetDeclaringClass()->AllocObject(self));
+    DCHECK(h_dex_file.Get() != nullptr);
+    h_cookie_field->SetObject<false>(h_dex_file.Get(), h_long_array.Get());
+
+    Handle<mirror::Object> h_element = hs2.NewHandle(h_dex_element_class->AllocObject(self));
+    DCHECK(h_element.Get() != nullptr);
+    h_element_file_field->SetObject<false>(h_element.Get(), h_dex_file.Get());
+
+    h_dex_elements->Set(index, h_element.Get());
+    index++;
+  }
+  DCHECK_EQ(index, h_dex_elements->GetLength());
+
+  // Create DexPathList.
+  Handle<mirror::Object> h_dex_path_list = hs.NewHandle(
+      h_dex_elements_field->GetDeclaringClass()->AllocObject(self));
+  DCHECK(h_dex_path_list.Get() != nullptr);
+  // Set elements.
+  h_dex_elements_field->SetObject<false>(h_dex_path_list.Get(), h_dex_elements.Get());
+
+  // Create PathClassLoader.
+  Handle<mirror::Class> h_path_class_class = hs.NewHandle(
+      soa.Decode<mirror::Class*>(WellKnownClasses::dalvik_system_PathClassLoader));
+  Handle<mirror::Object> h_path_class_loader = hs.NewHandle(
+      h_path_class_class->AllocObject(self));
+  DCHECK(h_path_class_loader.Get() != nullptr);
+  // Set DexPathList.
+  Handle<mirror::ArtField> h_path_list_field = hs.NewHandle(
+      soa.DecodeField(WellKnownClasses::dalvik_system_PathClassLoader_pathList));
+  DCHECK(h_path_list_field.Get() != nullptr);
+  h_path_list_field->SetObject<false>(h_path_class_loader.Get(), h_dex_path_list.Get());
+
+  // Make a pretend boot-classpath.
+  // TODO: Should we scan the image?
+  Handle<mirror::ArtField> h_parent_field = hs.NewHandle(
+      mirror::Class::FindField(self, hs.NewHandle(h_path_class_loader->GetClass()), "parent",
+                               "Ljava/lang/ClassLoader;"));
+  DCHECK(h_parent_field.Get() != nullptr);
+  mirror::Object* boot_cl =
+      soa.Decode<mirror::Class*>(WellKnownClasses::java_lang_BootClassLoader)->AllocObject(self);
+  h_parent_field->SetObject<false>(h_path_class_loader.Get(), boot_cl);
+
+  // Make it a global ref and return.
+  ScopedLocalRef<jobject> local_ref(
+      soa.Env(), soa.Env()->AddLocalReference<jobject>(h_path_class_loader.Get()));
+  return soa.Env()->NewGlobalRef(local_ref.get());
+}
+
 }  // namespace art
diff --git a/runtime/class_linker.h b/runtime/class_linker.h
index 4ebce3e..ec984cb 100644
--- a/runtime/class_linker.h
+++ b/runtime/class_linker.h
@@ -72,10 +72,12 @@
     kJavaLangRefReference,
     kJavaLangReflectArtField,
     kJavaLangReflectArtMethod,
+    kJavaLangReflectField,
     kJavaLangReflectProxy,
     kJavaLangStringArrayClass,
     kJavaLangReflectArtFieldArrayClass,
     kJavaLangReflectArtMethodArrayClass,
+    kJavaLangReflectFieldArrayClass,
     kJavaLangClassLoader,
     kJavaLangThrowable,
     kJavaLangClassNotFoundException,
@@ -454,6 +456,11 @@
   bool MayBeCalledWithDirectCodePointer(mirror::ArtMethod* m)
       SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
 
+  // Creates a GlobalRef PathClassLoader that can be used to load classes from the given dex files.
+  // Note: the objects are not completely set up. Do not use this outside of tests and the compiler.
+  jobject CreatePathClassLoader(Thread* self, std::vector<const DexFile*>& dex_files)
+      SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
+
  private:
   static void InitFromImageInterpretOnlyCallback(mirror::Object* obj, void* arg)
       SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
diff --git a/runtime/class_linker_test.cc b/runtime/class_linker_test.cc
index 1789ab1..3e727e7 100644
--- a/runtime/class_linker_test.cc
+++ b/runtime/class_linker_test.cc
@@ -24,11 +24,13 @@
 #include "dex_file.h"
 #include "entrypoints/entrypoint_utils-inl.h"
 #include "gc/heap.h"
+#include "mirror/accessible_object.h"
 #include "mirror/art_field-inl.h"
 #include "mirror/art_method.h"
 #include "mirror/art_method-inl.h"
 #include "mirror/class-inl.h"
 #include "mirror/dex_cache.h"
+#include "mirror/field.h"
 #include "mirror/object-inl.h"
 #include "mirror/object_array-inl.h"
 #include "mirror/proxy.h"
@@ -177,7 +179,7 @@
     EXPECT_TRUE(field->GetClass() != nullptr);
     EXPECT_EQ(klass, field->GetDeclaringClass());
     EXPECT_TRUE(field->GetName() != nullptr);
-    EXPECT_TRUE(field->GetType(true) != nullptr);
+    EXPECT_TRUE(field->GetType<true>() != nullptr);
   }
 
   void AssertClass(const std::string& descriptor, Handle<mirror::Class> klass)
@@ -283,7 +285,7 @@
     for (size_t i = 0; i < klass->NumInstanceFields(); i++) {
       mirror::ArtField* field = klass->GetInstanceField(i);
       fhandle.Assign(field);
-      mirror::Class* field_type = fhandle->GetType(true);
+      mirror::Class* field_type = fhandle->GetType<true>();
       ASSERT_TRUE(field_type != nullptr);
       if (!field->IsPrimitiveType()) {
         ASSERT_TRUE(!field_type->IsPrimitive());
@@ -394,7 +396,12 @@
 
     // Art method have a different size due to the padding field.
     if (!klass->IsArtMethodClass() && !klass->IsClassClass() && !is_static) {
-      size_t expected_size = is_static ? klass->GetClassSize(): klass->GetObjectSize();
+      // Currently only required for AccessibleObject since of the padding fields. The class linker
+      // says AccessibleObject is 9 bytes but sizeof(AccessibleObject) is 12 bytes due to padding.
+      // The RoundUp is to get around this case.
+      static constexpr size_t kPackAlignment = 4;
+      size_t expected_size = RoundUp(is_static ? klass->GetClassSize(): klass->GetObjectSize(),
+          kPackAlignment);
       if (sizeof(T) != expected_size) {
         LOG(ERROR) << "Class size mismatch:"
            << " class=" << class_descriptor
@@ -596,6 +603,22 @@
   };
 };
 
+struct AccessibleObjectOffsets : public CheckOffsets<mirror::AccessibleObject> {
+  AccessibleObjectOffsets() : CheckOffsets<mirror::AccessibleObject>(false, "Ljava/lang/reflect/AccessibleObject;") {
+    offsets.push_back(CheckOffset(mirror::AccessibleObject::FlagOffset().Uint32Value(),   "flag"));
+  };
+};
+
+struct FieldOffsets : public CheckOffsets<mirror::Field> {
+  FieldOffsets() : CheckOffsets<mirror::Field>(false, "Ljava/lang/reflect/Field;") {
+    offsets.push_back(CheckOffset(OFFSETOF_MEMBER(mirror::Field, access_flags_),     "accessFlags"));
+    offsets.push_back(CheckOffset(OFFSETOF_MEMBER(mirror::Field, declaring_class_),  "declaringClass"));
+    offsets.push_back(CheckOffset(OFFSETOF_MEMBER(mirror::Field, dex_field_index_),  "dexFieldIndex"));
+    offsets.push_back(CheckOffset(OFFSETOF_MEMBER(mirror::Field, offset_),           "offset"));
+    offsets.push_back(CheckOffset(OFFSETOF_MEMBER(mirror::Field, type_),             "type"));
+  };
+};
+
 // C++ fields must exactly match the fields in the Java classes. If this fails,
 // reorder the fields in the C++ class. Managed class fields are ordered by
 // ClassLinker::LinkFields.
@@ -613,6 +636,8 @@
   EXPECT_TRUE(DexCacheOffsets().Check());
   EXPECT_TRUE(ReferenceOffsets().Check());
   EXPECT_TRUE(FinalizerReferenceOffsets().Check());
+  EXPECT_TRUE(AccessibleObjectOffsets().Check());
+  EXPECT_TRUE(FieldOffsets().Check());
 }
 
 TEST_F(ClassLinkerTest, FindClassNonexistent) {
@@ -621,6 +646,20 @@
   AssertNonExistentClass("LNoSuchClass;");
 }
 
+TEST_F(ClassLinkerTest, GetDexFiles) {
+  ScopedObjectAccess soa(Thread::Current());
+
+  jobject jclass_loader = LoadDex("Nested");
+  std::vector<const DexFile*> dex_files(GetDexFiles(jclass_loader));
+  ASSERT_EQ(dex_files.size(), 1U);
+  EXPECT_TRUE(EndsWith(dex_files[0]->GetLocation(), "Nested.jar"));
+
+  jobject jclass_loader2 = LoadDex("MultiDex");
+  std::vector<const DexFile*> dex_files2(GetDexFiles(jclass_loader2));
+  ASSERT_EQ(dex_files2.size(), 2U);
+  EXPECT_TRUE(EndsWith(dex_files2[0]->GetLocation(), "MultiDex.jar"));
+}
+
 TEST_F(ClassLinkerTest, FindClassNested) {
   ScopedObjectAccess soa(Thread::Current());
   StackHandleScope<1> hs(soa.Self());
@@ -985,11 +1024,10 @@
 
   ScopedObjectAccess soa(Thread::Current());
   jobject jclass_loader = LoadDex("StaticsFromCode");
+  const DexFile* dex_file = GetFirstDexFile(jclass_loader);
   StackHandleScope<1> hs(soa.Self());
   Handle<mirror::ClassLoader> class_loader(
       hs.NewHandle(soa.Decode<mirror::ClassLoader*>(jclass_loader)));
-  const DexFile* dex_file = Runtime::Current()->GetCompileTimeClassPath(jclass_loader)[0];
-  CHECK(dex_file != nullptr);
   mirror::Class* klass = class_linker_->FindClass(soa.Self(), "LStaticsFromCode;", class_loader);
   mirror::ArtMethod* clinit = klass->FindClassInitializer();
   mirror::ArtMethod* getS0 = klass->FindDirectMethod("getS0", "()Ljava/lang/Object;");
diff --git a/runtime/common_runtime_test.cc b/runtime/common_runtime_test.cc
index e0d62d7..d400010 100644
--- a/runtime/common_runtime_test.cc
+++ b/runtime/common_runtime_test.cc
@@ -34,6 +34,7 @@
 #include "gc_root-inl.h"
 #include "gc/heap.h"
 #include "gtest/gtest.h"
+#include "handle_scope-inl.h"
 #include "interpreter/unstarted_runtime.h"
 #include "jni_internal.h"
 #include "mirror/class_loader.h"
@@ -219,7 +220,6 @@
   std::string min_heap_string(StringPrintf("-Xms%zdm", gc::Heap::kDefaultInitialSize / MB));
   std::string max_heap_string(StringPrintf("-Xmx%zdm", gc::Heap::kDefaultMaximumSize / MB));
 
-  callbacks_.reset(new NoopCompilerCallbacks());
 
   RuntimeOptions options;
   std::string boot_class_path_string = "-Xbootclasspath:" + GetLibCoreDexFileName();
@@ -227,9 +227,16 @@
   options.push_back(std::make_pair("-Xcheck:jni", nullptr));
   options.push_back(std::make_pair(min_heap_string, nullptr));
   options.push_back(std::make_pair(max_heap_string, nullptr));
-  options.push_back(std::make_pair("compilercallbacks", callbacks_.get()));
+
+  callbacks_.reset(new NoopCompilerCallbacks());
+
   SetUpRuntimeOptions(&options);
 
+  // Install compiler-callbacks if SetupRuntimeOptions hasn't deleted them.
+  if (callbacks_.get() != nullptr) {
+    options.push_back(std::make_pair("compilercallbacks", callbacks_.get()));
+  }
+
   PreRuntimeCreate();
   if (!Runtime::Create(options, false)) {
     LOG(FATAL) << "Failed to create runtime";
@@ -386,22 +393,89 @@
   return std::move(vector[0]);
 }
 
+std::vector<const DexFile*> CommonRuntimeTest::GetDexFiles(jobject jclass_loader) {
+  std::vector<const DexFile*> ret;
+
+  ScopedObjectAccess soa(Thread::Current());
+
+  StackHandleScope<4> hs(Thread::Current());
+  Handle<mirror::ClassLoader> class_loader = hs.NewHandle(
+      soa.Decode<mirror::ClassLoader*>(jclass_loader));
+
+  DCHECK_EQ(class_loader->GetClass(),
+            soa.Decode<mirror::Class*>(WellKnownClasses::dalvik_system_PathClassLoader));
+  DCHECK_EQ(class_loader->GetParent()->GetClass(),
+            soa.Decode<mirror::Class*>(WellKnownClasses::java_lang_BootClassLoader));
+
+  // The class loader is a PathClassLoader which inherits from BaseDexClassLoader.
+  // We need to get the DexPathList and loop through it.
+  Handle<mirror::ArtField> cookie_field =
+      hs.NewHandle(soa.DecodeField(WellKnownClasses::dalvik_system_DexFile_cookie));
+  Handle<mirror::ArtField> dex_file_field =
+      hs.NewHandle(
+          soa.DecodeField(WellKnownClasses::dalvik_system_DexPathList__Element_dexFile));
+  mirror::Object* dex_path_list =
+      soa.DecodeField(WellKnownClasses::dalvik_system_PathClassLoader_pathList)->
+      GetObject(class_loader.Get());
+  if (dex_path_list != nullptr && dex_file_field.Get() != nullptr &&
+      cookie_field.Get() != nullptr) {
+    // DexPathList has an array dexElements of Elements[] which each contain a dex file.
+    mirror::Object* dex_elements_obj =
+        soa.DecodeField(WellKnownClasses::dalvik_system_DexPathList_dexElements)->
+        GetObject(dex_path_list);
+    // Loop through each dalvik.system.DexPathList$Element's dalvik.system.DexFile and look
+    // at the mCookie which is a DexFile vector.
+    if (dex_elements_obj != nullptr) {
+      Handle<mirror::ObjectArray<mirror::Object>> dex_elements =
+          hs.NewHandle(dex_elements_obj->AsObjectArray<mirror::Object>());
+      for (int32_t i = 0; i < dex_elements->GetLength(); ++i) {
+        mirror::Object* element = dex_elements->GetWithoutChecks(i);
+        if (element == nullptr) {
+          // Should never happen, fall back to java code to throw a NPE.
+          break;
+        }
+        mirror::Object* dex_file = dex_file_field->GetObject(element);
+        if (dex_file != nullptr) {
+          mirror::LongArray* long_array = cookie_field->GetObject(dex_file)->AsLongArray();
+          DCHECK(long_array != nullptr);
+          int32_t long_array_size = long_array->GetLength();
+          for (int32_t j = 0; j < long_array_size; ++j) {
+            const DexFile* cp_dex_file = reinterpret_cast<const DexFile*>(static_cast<uintptr_t>(
+                long_array->GetWithoutChecks(j)));
+            if (cp_dex_file == nullptr) {
+              LOG(WARNING) << "Null DexFile";
+              continue;
+            }
+            ret.push_back(cp_dex_file);
+          }
+        }
+      }
+    }
+  }
+
+  return ret;
+}
+
+const DexFile* CommonRuntimeTest::GetFirstDexFile(jobject jclass_loader) {
+  std::vector<const DexFile*> tmp(GetDexFiles(jclass_loader));
+  DCHECK(!tmp.empty());
+  const DexFile* ret = tmp[0];
+  DCHECK(ret != nullptr);
+  return ret;
+}
+
 jobject CommonRuntimeTest::LoadDex(const char* dex_name) {
   std::vector<std::unique_ptr<const DexFile>> dex_files = OpenTestDexFiles(dex_name);
   std::vector<const DexFile*> class_path;
   CHECK_NE(0U, dex_files.size());
   for (auto& dex_file : dex_files) {
     class_path.push_back(dex_file.get());
-    class_linker_->RegisterDexFile(*dex_file);
     loaded_dex_files_.push_back(std::move(dex_file));
   }
+
   Thread* self = Thread::Current();
-  JNIEnvExt* env = self->GetJniEnv();
-  ScopedLocalRef<jobject> class_loader_local(env,
-      env->AllocObject(WellKnownClasses::dalvik_system_PathClassLoader));
-  jobject class_loader = env->NewGlobalRef(class_loader_local.get());
-  self->SetClassLoaderOverride(class_loader_local.get());
-  Runtime::Current()->SetCompileTimeClassPath(class_loader, class_path);
+  jobject class_loader = Runtime::Current()->GetClassLinker()->CreatePathClassLoader(self,                                                                                   class_path);
+  self->SetClassLoaderOverride(class_loader);
   return class_loader;
 }
 
diff --git a/runtime/common_runtime_test.h b/runtime/common_runtime_test.h
index cce8485..5fbc2ee 100644
--- a/runtime/common_runtime_test.h
+++ b/runtime/common_runtime_test.h
@@ -133,10 +133,18 @@
   const DexFile* java_lang_dex_file_;
   std::vector<const DexFile*> boot_class_path_;
 
+  // Get the dex files from a PathClassLoader. This in order of the dex elements and their dex
+  // arrays.
+  std::vector<const DexFile*> GetDexFiles(jobject jclass_loader);
+
+  // Get the first dex file from a PathClassLoader. Will abort if it is null.
+  const DexFile* GetFirstDexFile(jobject jclass_loader);
+
+  std::unique_ptr<CompilerCallbacks> callbacks_;
+
  private:
   static std::string GetCoreFileLocation(const char* suffix);
 
-  std::unique_ptr<CompilerCallbacks> callbacks_;
   std::vector<std::unique_ptr<const DexFile>> loaded_dex_files_;
 };
 
diff --git a/runtime/compiler_callbacks.h b/runtime/compiler_callbacks.h
index d1a6861..b296e39 100644
--- a/runtime/compiler_callbacks.h
+++ b/runtime/compiler_callbacks.h
@@ -29,19 +29,32 @@
 }  // namespace verifier
 
 class CompilerCallbacks {
-  public:
-    virtual ~CompilerCallbacks() { }
+ public:
+  enum class CallbackMode {  // private
+    kCompileBootImage,
+    kCompileApp
+  };
 
-    virtual bool MethodVerified(verifier::MethodVerifier* verifier)
-        SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) = 0;
-    virtual void ClassRejected(ClassReference ref) = 0;
+  virtual ~CompilerCallbacks() { }
 
-    // Return true if we should attempt to relocate to a random base address if we have not already
-    // done so. Return false if relocating in this way would be problematic.
-    virtual bool IsRelocationPossible() = 0;
+  virtual bool MethodVerified(verifier::MethodVerifier* verifier)
+  SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) = 0;
+  virtual void ClassRejected(ClassReference ref) = 0;
 
-  protected:
-    CompilerCallbacks() { }
+  // Return true if we should attempt to relocate to a random base address if we have not already
+  // done so. Return false if relocating in this way would be problematic.
+  virtual bool IsRelocationPossible() = 0;
+
+  bool IsBootImage() {
+    return mode_ == CallbackMode::kCompileBootImage;
+  }
+
+ protected:
+  explicit CompilerCallbacks(CallbackMode mode) : mode_(mode) { }
+
+ private:
+  // Whether the compiler is creating a boot image.
+  const CallbackMode mode_;
 };
 
 }  // namespace art
diff --git a/runtime/debugger.cc b/runtime/debugger.cc
index a1ae236..a767cf0 100644
--- a/runtime/debugger.cc
+++ b/runtime/debugger.cc
@@ -1451,22 +1451,31 @@
  * Circularly shifts registers so that arguments come last. Reverts
  * slots to dex style argument placement.
  */
-static uint16_t DemangleSlot(uint16_t slot, mirror::ArtMethod* m)
+static uint16_t DemangleSlot(uint16_t slot, mirror::ArtMethod* m, JDWP::JdwpError* error)
     SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
   const DexFile::CodeItem* code_item = m->GetCodeItem();
   if (code_item == nullptr) {
     // We should not get here for a method without code (native, proxy or abstract). Log it and
     // return the slot as is since all registers are arguments.
     LOG(WARNING) << "Trying to demangle slot for method without code " << PrettyMethod(m);
-    return slot;
-  }
-  uint16_t ins_size = code_item->ins_size_;
-  uint16_t locals_size = code_item->registers_size_ - ins_size;
-  if (slot < ins_size) {
-    return slot + locals_size;
+    uint16_t vreg_count = mirror::ArtMethod::NumArgRegisters(m->GetShorty());
+    if (slot < vreg_count) {
+      *error = JDWP::ERR_NONE;
+      return slot;
+    }
   } else {
-    return slot - ins_size;
+    if (slot < code_item->registers_size_) {
+      uint16_t ins_size = code_item->ins_size_;
+      uint16_t locals_size = code_item->registers_size_ - ins_size;
+      *error = JDWP::ERR_NONE;
+      return (slot < ins_size) ? slot + locals_size : slot - ins_size;
+    }
   }
+
+  // Slot is invalid in the method.
+  LOG(ERROR) << "Invalid local slot " << slot << " for method " << PrettyMethod(m);
+  *error = JDWP::ERR_INVALID_SLOT;
+  return DexFile::kDexNoIndex16;
 }
 
 JDWP::JdwpError Dbg::OutputDeclaredFields(JDWP::RefTypeId class_id, bool with_generic, JDWP::ExpandBuf* pReply) {
@@ -1798,7 +1807,7 @@
         HandleWrapper<mirror::Object> h_v(hs.NewHandleWrapper(&v));
         HandleWrapper<mirror::ArtField> h_f(hs.NewHandleWrapper(&f));
         HandleWrapper<mirror::Object> h_o(hs.NewHandleWrapper(&o));
-        field_type = h_f->GetType(true);
+        field_type = h_f->GetType<true>();
       }
       if (!field_type->IsAssignableFrom(v->GetClass())) {
         return JDWP::ERR_INVALID_OBJECT;
@@ -2427,6 +2436,9 @@
     if (error != JDWP::ERR_NONE) {
       return error;
     }
+    if (!IsSuspendedForDebugger(soa, thread)) {
+      return JDWP::ERR_THREAD_NOT_SUSPENDED;
+    }
   }
   // Find the frame with the given frame_id.
   std::unique_ptr<Context> context(Context::Create());
@@ -2455,73 +2467,81 @@
   return JDWP::ERR_NONE;
 }
 
+constexpr JDWP::JdwpError kStackFrameLocalAccessError = JDWP::ERR_ABSENT_INFORMATION;
+
+static std::string GetStackContextAsString(const StackVisitor& visitor)
+    SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
+  return StringPrintf(" at DEX pc 0x%08x in method %s", visitor.GetDexPc(false),
+                      PrettyMethod(visitor.GetMethod()).c_str());
+}
+
+static JDWP::JdwpError FailGetLocalValue(const StackVisitor& visitor, uint16_t vreg,
+                                         JDWP::JdwpTag tag)
+    SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
+  LOG(ERROR) << "Failed to read " << tag << " local from register v" << vreg
+             << GetStackContextAsString(visitor);
+  return kStackFrameLocalAccessError;
+}
+
 JDWP::JdwpError Dbg::GetLocalValue(const StackVisitor& visitor, ScopedObjectAccessUnchecked& soa,
                                    int slot, JDWP::JdwpTag tag, uint8_t* buf, size_t width) {
   mirror::ArtMethod* m = visitor.GetMethod();
-  uint16_t reg = DemangleSlot(slot, m);
+  JDWP::JdwpError error = JDWP::ERR_NONE;
+  uint16_t vreg = DemangleSlot(slot, m, &error);
+  if (error != JDWP::ERR_NONE) {
+    return error;
+  }
   // TODO: check that the tag is compatible with the actual type of the slot!
-  // TODO: check slot is valid for this method or return INVALID_SLOT error.
-  constexpr JDWP::JdwpError kFailureErrorCode = JDWP::ERR_ABSENT_INFORMATION;
   switch (tag) {
     case JDWP::JT_BOOLEAN: {
       CHECK_EQ(width, 1U);
       uint32_t intVal;
-      if (visitor.GetVReg(m, reg, kIntVReg, &intVal)) {
-        VLOG(jdwp) << "get boolean local " << reg << " = " << intVal;
-        JDWP::Set1(buf + 1, intVal != 0);
-      } else {
-        VLOG(jdwp) << "failed to get boolean local " << reg;
-        return kFailureErrorCode;
+      if (!visitor.GetVReg(m, vreg, kIntVReg, &intVal)) {
+        return FailGetLocalValue(visitor, vreg, tag);
       }
+      VLOG(jdwp) << "get boolean local " << vreg << " = " << intVal;
+      JDWP::Set1(buf + 1, intVal != 0);
       break;
     }
     case JDWP::JT_BYTE: {
       CHECK_EQ(width, 1U);
       uint32_t intVal;
-      if (visitor.GetVReg(m, reg, kIntVReg, &intVal)) {
-        VLOG(jdwp) << "get byte local " << reg << " = " << intVal;
-        JDWP::Set1(buf + 1, intVal);
-      } else {
-        VLOG(jdwp) << "failed to get byte local " << reg;
-        return kFailureErrorCode;
+      if (!visitor.GetVReg(m, vreg, kIntVReg, &intVal)) {
+        return FailGetLocalValue(visitor, vreg, tag);
       }
+      VLOG(jdwp) << "get byte local " << vreg << " = " << intVal;
+      JDWP::Set1(buf + 1, intVal);
       break;
     }
     case JDWP::JT_SHORT:
     case JDWP::JT_CHAR: {
       CHECK_EQ(width, 2U);
       uint32_t intVal;
-      if (visitor.GetVReg(m, reg, kIntVReg, &intVal)) {
-        VLOG(jdwp) << "get short/char local " << reg << " = " << intVal;
-        JDWP::Set2BE(buf + 1, intVal);
-      } else {
-        VLOG(jdwp) << "failed to get short/char local " << reg;
-        return kFailureErrorCode;
+      if (!visitor.GetVReg(m, vreg, kIntVReg, &intVal)) {
+        return FailGetLocalValue(visitor, vreg, tag);
       }
+      VLOG(jdwp) << "get short/char local " << vreg << " = " << intVal;
+      JDWP::Set2BE(buf + 1, intVal);
       break;
     }
     case JDWP::JT_INT: {
       CHECK_EQ(width, 4U);
       uint32_t intVal;
-      if (visitor.GetVReg(m, reg, kIntVReg, &intVal)) {
-        VLOG(jdwp) << "get int local " << reg << " = " << intVal;
-        JDWP::Set4BE(buf + 1, intVal);
-      } else {
-        VLOG(jdwp) << "failed to get int local " << reg;
-        return kFailureErrorCode;
+      if (!visitor.GetVReg(m, vreg, kIntVReg, &intVal)) {
+        return FailGetLocalValue(visitor, vreg, tag);
       }
+      VLOG(jdwp) << "get int local " << vreg << " = " << intVal;
+      JDWP::Set4BE(buf + 1, intVal);
       break;
     }
     case JDWP::JT_FLOAT: {
       CHECK_EQ(width, 4U);
       uint32_t intVal;
-      if (visitor.GetVReg(m, reg, kFloatVReg, &intVal)) {
-        VLOG(jdwp) << "get float local " << reg << " = " << intVal;
-        JDWP::Set4BE(buf + 1, intVal);
-      } else {
-        VLOG(jdwp) << "failed to get float local " << reg;
-        return kFailureErrorCode;
+      if (!visitor.GetVReg(m, vreg, kFloatVReg, &intVal)) {
+        return FailGetLocalValue(visitor, vreg, tag);
       }
+      VLOG(jdwp) << "get float local " << vreg << " = " << intVal;
+      JDWP::Set4BE(buf + 1, intVal);
       break;
     }
     case JDWP::JT_ARRAY:
@@ -2533,47 +2553,44 @@
     case JDWP::JT_THREAD_GROUP: {
       CHECK_EQ(width, sizeof(JDWP::ObjectId));
       uint32_t intVal;
-      if (visitor.GetVReg(m, reg, kReferenceVReg, &intVal)) {
-        mirror::Object* o = reinterpret_cast<mirror::Object*>(intVal);
-        VLOG(jdwp) << "get " << tag << " object local " << reg << " = " << o;
-        if (!Runtime::Current()->GetHeap()->IsValidObjectAddress(o)) {
-          LOG(FATAL) << "Register " << reg << " expected to hold " << tag << " object: " << o;
-        }
-        tag = TagFromObject(soa, o);
-        JDWP::SetObjectId(buf + 1, gRegistry->Add(o));
-      } else {
-        VLOG(jdwp) << "failed to get " << tag << " object local " << reg;
-        return kFailureErrorCode;
+      if (!visitor.GetVReg(m, vreg, kReferenceVReg, &intVal)) {
+        return FailGetLocalValue(visitor, vreg, tag);
       }
+      mirror::Object* o = reinterpret_cast<mirror::Object*>(intVal);
+      VLOG(jdwp) << "get " << tag << " object local " << vreg << " = " << o;
+      if (!Runtime::Current()->GetHeap()->IsValidObjectAddress(o)) {
+        LOG(FATAL) << StringPrintf("Found invalid object %#" PRIxPTR " in register v%u",
+                                   reinterpret_cast<uintptr_t>(o), vreg)
+                                   << GetStackContextAsString(visitor);
+        UNREACHABLE();
+      }
+      tag = TagFromObject(soa, o);
+      JDWP::SetObjectId(buf + 1, gRegistry->Add(o));
       break;
     }
     case JDWP::JT_DOUBLE: {
       CHECK_EQ(width, 8U);
       uint64_t longVal;
-      if (visitor.GetVRegPair(m, reg, kDoubleLoVReg, kDoubleHiVReg, &longVal)) {
-        VLOG(jdwp) << "get double local " << reg << " = " << longVal;
-        JDWP::Set8BE(buf + 1, longVal);
-      } else {
-        VLOG(jdwp) << "failed to get double local " << reg;
-        return kFailureErrorCode;
+      if (!visitor.GetVRegPair(m, vreg, kDoubleLoVReg, kDoubleHiVReg, &longVal)) {
+        return FailGetLocalValue(visitor, vreg, tag);
       }
+      VLOG(jdwp) << "get double local " << vreg << " = " << longVal;
+      JDWP::Set8BE(buf + 1, longVal);
       break;
     }
     case JDWP::JT_LONG: {
       CHECK_EQ(width, 8U);
       uint64_t longVal;
-      if (visitor.GetVRegPair(m, reg, kLongLoVReg, kLongHiVReg, &longVal)) {
-        VLOG(jdwp) << "get long local " << reg << " = " << longVal;
-        JDWP::Set8BE(buf + 1, longVal);
-      } else {
-        VLOG(jdwp) << "failed to get long local " << reg;
-        return kFailureErrorCode;
+      if (!visitor.GetVRegPair(m, vreg, kLongLoVReg, kLongHiVReg, &longVal)) {
+        return FailGetLocalValue(visitor, vreg, tag);
       }
+      VLOG(jdwp) << "get long local " << vreg << " = " << longVal;
+      JDWP::Set8BE(buf + 1, longVal);
       break;
     }
     default:
       LOG(FATAL) << "Unknown tag " << tag;
-      break;
+      UNREACHABLE();
   }
 
   // Prepend tag, which may have been updated.
@@ -2594,6 +2611,9 @@
     if (error != JDWP::ERR_NONE) {
       return error;
     }
+    if (!IsSuspendedForDebugger(soa, thread)) {
+      return JDWP::ERR_THREAD_NOT_SUSPENDED;
+    }
   }
   // Find the frame with the given frame_id.
   std::unique_ptr<Context> context(Context::Create());
@@ -2620,46 +2640,50 @@
   return JDWP::ERR_NONE;
 }
 
+template<typename T>
+static JDWP::JdwpError FailSetLocalValue(const StackVisitor& visitor, uint16_t vreg,
+                                         JDWP::JdwpTag tag, T value)
+    SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
+  LOG(ERROR) << "Failed to write " << tag << " local " << value
+             << " (0x" << std::hex << value << ") into register v" << vreg
+             << GetStackContextAsString(visitor);
+  return kStackFrameLocalAccessError;
+}
+
 JDWP::JdwpError Dbg::SetLocalValue(StackVisitor& visitor, int slot, JDWP::JdwpTag tag,
                                    uint64_t value, size_t width) {
   mirror::ArtMethod* m = visitor.GetMethod();
-  uint16_t reg = DemangleSlot(slot, m);
+  JDWP::JdwpError error = JDWP::ERR_NONE;
+  uint16_t vreg = DemangleSlot(slot, m, &error);
+  if (error != JDWP::ERR_NONE) {
+    return error;
+  }
   // TODO: check that the tag is compatible with the actual type of the slot!
-  // TODO: check slot is valid for this method or return INVALID_SLOT error.
-  constexpr JDWP::JdwpError kFailureErrorCode = JDWP::ERR_ABSENT_INFORMATION;
   switch (tag) {
     case JDWP::JT_BOOLEAN:
     case JDWP::JT_BYTE:
       CHECK_EQ(width, 1U);
-      if (!visitor.SetVReg(m, reg, static_cast<uint32_t>(value), kIntVReg)) {
-        VLOG(jdwp) << "failed to set boolean/byte local " << reg << " = "
-                   << static_cast<uint32_t>(value);
-        return kFailureErrorCode;
+      if (!visitor.SetVReg(m, vreg, static_cast<uint32_t>(value), kIntVReg)) {
+        return FailSetLocalValue(visitor, vreg, tag, static_cast<uint32_t>(value));
       }
       break;
     case JDWP::JT_SHORT:
     case JDWP::JT_CHAR:
       CHECK_EQ(width, 2U);
-      if (!visitor.SetVReg(m, reg, static_cast<uint32_t>(value), kIntVReg)) {
-        VLOG(jdwp) << "failed to set short/char local " << reg << " = "
-                   << static_cast<uint32_t>(value);
-        return kFailureErrorCode;
+      if (!visitor.SetVReg(m, vreg, static_cast<uint32_t>(value), kIntVReg)) {
+        return FailSetLocalValue(visitor, vreg, tag, static_cast<uint32_t>(value));
       }
       break;
     case JDWP::JT_INT:
       CHECK_EQ(width, 4U);
-      if (!visitor.SetVReg(m, reg, static_cast<uint32_t>(value), kIntVReg)) {
-        VLOG(jdwp) << "failed to set int local " << reg << " = "
-                   << static_cast<uint32_t>(value);
-        return kFailureErrorCode;
+      if (!visitor.SetVReg(m, vreg, static_cast<uint32_t>(value), kIntVReg)) {
+        return FailSetLocalValue(visitor, vreg, tag, static_cast<uint32_t>(value));
       }
       break;
     case JDWP::JT_FLOAT:
       CHECK_EQ(width, 4U);
-      if (!visitor.SetVReg(m, reg, static_cast<uint32_t>(value), kFloatVReg)) {
-        VLOG(jdwp) << "failed to set float local " << reg << " = "
-                   << static_cast<uint32_t>(value);
-        return kFailureErrorCode;
+      if (!visitor.SetVReg(m, vreg, static_cast<uint32_t>(value), kFloatVReg)) {
+        return FailSetLocalValue(visitor, vreg, tag, static_cast<uint32_t>(value));
       }
       break;
     case JDWP::JT_ARRAY:
@@ -2670,38 +2694,35 @@
     case JDWP::JT_THREAD:
     case JDWP::JT_THREAD_GROUP: {
       CHECK_EQ(width, sizeof(JDWP::ObjectId));
-      JDWP::JdwpError error;
       mirror::Object* o = gRegistry->Get<mirror::Object*>(static_cast<JDWP::ObjectId>(value),
                                                           &error);
       if (error != JDWP::ERR_NONE) {
         VLOG(jdwp) << tag << " object " << o << " is an invalid object";
         return JDWP::ERR_INVALID_OBJECT;
-      } else if (!visitor.SetVReg(m, reg, static_cast<uint32_t>(reinterpret_cast<uintptr_t>(o)),
-                          kReferenceVReg)) {
-        VLOG(jdwp) << "failed to set " << tag << " object local " << reg << " = " << o;
-        return kFailureErrorCode;
+      }
+      if (!visitor.SetVReg(m, vreg, static_cast<uint32_t>(reinterpret_cast<uintptr_t>(o)),
+                                 kReferenceVReg)) {
+        return FailSetLocalValue(visitor, vreg, tag, reinterpret_cast<uintptr_t>(o));
       }
       break;
     }
     case JDWP::JT_DOUBLE: {
       CHECK_EQ(width, 8U);
-      if (!visitor.SetVRegPair(m, reg, value, kDoubleLoVReg, kDoubleHiVReg)) {
-        VLOG(jdwp) << "failed to set double local " << reg << " = " << value;
-        return kFailureErrorCode;
+      if (!visitor.SetVRegPair(m, vreg, value, kDoubleLoVReg, kDoubleHiVReg)) {
+        return FailSetLocalValue(visitor, vreg, tag, value);
       }
       break;
     }
     case JDWP::JT_LONG: {
       CHECK_EQ(width, 8U);
-      if (!visitor.SetVRegPair(m, reg, value, kLongLoVReg, kLongHiVReg)) {
-        VLOG(jdwp) << "failed to set double local " << reg << " = " << value;
-        return kFailureErrorCode;
+      if (!visitor.SetVRegPair(m, vreg, value, kLongLoVReg, kLongHiVReg)) {
+        return FailSetLocalValue(visitor, vreg, tag, value);
       }
       break;
     }
     default:
       LOG(FATAL) << "Unknown tag " << tag;
-      break;
+      UNREACHABLE();
   }
   return JDWP::ERR_NONE;
 }
diff --git a/runtime/interpreter/interpreter_common.cc b/runtime/interpreter/interpreter_common.cc
index a3ab026..a310452 100644
--- a/runtime/interpreter/interpreter_common.cc
+++ b/runtime/interpreter/interpreter_common.cc
@@ -285,7 +285,7 @@
           HandleWrapper<mirror::ArtField> h_f(hs.NewHandleWrapper(&f));
           HandleWrapper<mirror::Object> h_reg(hs.NewHandleWrapper(&reg));
           HandleWrapper<mirror::Object> h_obj(hs.NewHandleWrapper(&obj));
-          field_class = h_f->GetType(true);
+          field_class = h_f->GetType<true>();
         }
         if (!reg->VerifierInstanceOf(field_class)) {
           // This should never happen.
diff --git a/runtime/interpreter/unstarted_runtime.cc b/runtime/interpreter/unstarted_runtime.cc
index 98dfdbd..1b08e80 100644
--- a/runtime/interpreter/unstarted_runtime.cc
+++ b/runtime/interpreter/unstarted_runtime.cc
@@ -29,6 +29,7 @@
 #include "mirror/array-inl.h"
 #include "mirror/art_method-inl.h"
 #include "mirror/class.h"
+#include "mirror/field-inl.h"
 #include "mirror/object-inl.h"
 #include "mirror/object_array-inl.h"
 #include "mirror/string-inl.h"
@@ -219,19 +220,11 @@
                            PrettyDescriptor(klass).c_str());
     return;
   }
-  // TODO: getDeclaredField calls GetType once the field is found to ensure a
-  //       NoClassDefFoundError is thrown if the field's type cannot be resolved.
-  mirror::Class* jlr_Field = self->DecodeJObject(
-      WellKnownClasses::java_lang_reflect_Field)->AsClass();
-  StackHandleScope<1> hs(self);
-  Handle<mirror::Object> field(hs.NewHandle(jlr_Field->AllocNonMovableObject(self)));
-  CHECK(field.Get() != nullptr);
-  mirror::ArtMethod* c = jlr_Field->FindDeclaredDirectMethod("<init>",
-                                                             "(Ljava/lang/reflect/ArtField;)V");
-  uint32_t args[1];
-  args[0] = StackReference<mirror::Object>::FromMirrorPtr(found).AsVRegValue();
-  EnterInterpreterFromInvoke(self, c, field.Get(), args, nullptr);
-  result->SetL(field.Get());
+  if (Runtime::Current()->IsActiveTransaction()) {
+    result->SetL(mirror::Field::CreateFromArtField<true>(self, found, true));
+  } else {
+    result->SetL(mirror::Field::CreateFromArtField<false>(self, found, true));
+  }
 }
 
 static void UnstartedVmClassLoaderFindLoadedClass(
diff --git a/runtime/jni_internal.cc b/runtime/jni_internal.cc
index 6063e1e..5e38470 100644
--- a/runtime/jni_internal.cc
+++ b/runtime/jni_internal.cc
@@ -41,6 +41,7 @@
 #include "mirror/art_method-inl.h"
 #include "mirror/class-inl.h"
 #include "mirror/class_loader.h"
+#include "mirror/field.h"
 #include "mirror/object-inl.h"
 #include "mirror/object_array-inl.h"
 #include "mirror/string-inl.h"
@@ -164,8 +165,10 @@
   // See if the override ClassLoader is set for gtests.
   class_loader = soa.Decode<mirror::ClassLoader*>(soa.Self()->GetClassLoaderOverride());
   if (class_loader != nullptr) {
-    // If so, CommonCompilerTest should have set UseCompileTimeClassPath.
-    CHECK(Runtime::Current()->UseCompileTimeClassPath());
+    // If so, CommonCompilerTest should have marked the runtime as a compiler not compiling an
+    // image.
+    CHECK(Runtime::Current()->IsAotCompiler());
+    CHECK(!Runtime::Current()->IsCompilingBootImage());
     return class_loader;
   }
   // Use the BOOTCLASSPATH.
@@ -344,7 +347,13 @@
   static jfieldID FromReflectedField(JNIEnv* env, jobject jlr_field) {
     CHECK_NON_NULL_ARGUMENT(jlr_field);
     ScopedObjectAccess soa(env);
-    return soa.EncodeField(mirror::ArtField::FromReflectedField(soa, jlr_field));
+    mirror::Object* obj_field = soa.Decode<mirror::Object*>(jlr_field);
+    if (obj_field->GetClass() != mirror::Field::StaticClass()) {
+      // Not even a java.lang.reflect.Field, return nullptr.
+      return nullptr;
+    }
+    auto* field = static_cast<mirror::Field*>(obj_field);
+    return soa.EncodeField(field->GetArtField());
   }
 
   static jobject ToReflectedMethod(JNIEnv* env, jclass, jmethodID mid, jboolean) {
@@ -371,14 +380,7 @@
     CHECK_NON_NULL_ARGUMENT(fid);
     ScopedObjectAccess soa(env);
     mirror::ArtField* f = soa.DecodeField(fid);
-    ScopedLocalRef<jobject> art_field(env, soa.AddLocalReference<jobject>(f));
-    jobject reflect_field = env->AllocObject(WellKnownClasses::java_lang_reflect_Field);
-    if (env->ExceptionCheck()) {
-      return nullptr;
-    }
-    SetObjectField(env, reflect_field,
-                   WellKnownClasses::java_lang_reflect_Field_artField, art_field.get());
-    return reflect_field;
+    return soa.AddLocalReference<jobject>(mirror::Field::CreateFromArtField(soa.Self(), f, true));
   }
 
   static jclass GetObjectClass(JNIEnv* env, jobject java_object) {
diff --git a/runtime/leb128.h b/runtime/leb128.h
index dfb42b8..d36b690 100644
--- a/runtime/leb128.h
+++ b/runtime/leb128.h
@@ -124,6 +124,18 @@
   return dest;
 }
 
+template<typename Allocator>
+static inline void EncodeUnsignedLeb128(std::vector<uint8_t, Allocator>* dest, uint32_t value) {
+  uint8_t out = value & 0x7f;
+  value >>= 7;
+  while (value != 0) {
+    dest->push_back(out | 0x80);
+    out = value & 0x7f;
+    value >>= 7;
+  }
+  dest->push_back(out);
+}
+
 static inline uint8_t* EncodeSignedLeb128(uint8_t* dest, int32_t value) {
   uint32_t extra_bits = static_cast<uint32_t>(value ^ (value >> 31)) >> 6;
   uint8_t out = value & 0x7f;
@@ -137,6 +149,19 @@
   return dest;
 }
 
+template<typename Allocator>
+static inline void EncodeSignedLeb128(std::vector<uint8_t, Allocator>* dest, int32_t value) {
+  uint32_t extra_bits = static_cast<uint32_t>(value ^ (value >> 31)) >> 6;
+  uint8_t out = value & 0x7f;
+  while (extra_bits != 0u) {
+    dest->push_back(out | 0x80);
+    value >>= 7;
+    out = value & 0x7f;
+    extra_bits >>= 7;
+  }
+  dest->push_back(out);
+}
+
 // An encoder that pushed uint32_t data onto the given std::vector.
 class Leb128Encoder {
  public:
@@ -149,14 +174,7 @@
   }
 
   void PushBackUnsigned(uint32_t value) {
-    uint8_t out = value & 0x7f;
-    value >>= 7;
-    while (value != 0) {
-      data_->push_back(out | 0x80);
-      out = value & 0x7f;
-      value >>= 7;
-    }
-    data_->push_back(out);
+    EncodeUnsignedLeb128(data_, value);
   }
 
   template<typename It>
@@ -167,15 +185,7 @@
   }
 
   void PushBackSigned(int32_t value) {
-    uint32_t extra_bits = static_cast<uint32_t>(value ^ (value >> 31)) >> 6;
-    uint8_t out = value & 0x7f;
-    while (extra_bits != 0u) {
-      data_->push_back(out | 0x80);
-      value >>= 7;
-      out = value & 0x7f;
-      extra_bits >>= 7;
-    }
-    data_->push_back(out);
+    EncodeSignedLeb128(data_, value);
   }
 
   template<typename It>
diff --git a/runtime/memory_region.h b/runtime/memory_region.h
index f867f6a..6a784eb 100644
--- a/runtime/memory_region.h
+++ b/runtime/memory_region.h
@@ -48,22 +48,28 @@
   uint8_t* end() const { return start() + size_; }
 
   // Load value of type `T` at `offset`.  The memory address corresponding
-  // to `offset` should be word-aligned.
-  template<typename T> T Load(uintptr_t offset) const {
-    // TODO: DCHECK that the address is word-aligned.
-    return *ComputeInternalPointer<T>(offset);
+  // to `offset` should be word-aligned (on ARM, this is a requirement).
+  template<typename T>
+  ALWAYS_INLINE T Load(uintptr_t offset) const {
+    T* address = ComputeInternalPointer<T>(offset);
+    DCHECK(IsWordAligned(address));
+    return *address;
   }
 
   // Store `value` (of type `T`) at `offset`.  The memory address
-  // corresponding to `offset` should be word-aligned.
-  template<typename T> void Store(uintptr_t offset, T value) const {
-    // TODO: DCHECK that the address is word-aligned.
-    *ComputeInternalPointer<T>(offset) = value;
+  // corresponding to `offset` should be word-aligned (on ARM, this is
+  // a requirement).
+  template<typename T>
+  ALWAYS_INLINE void Store(uintptr_t offset, T value) const {
+    T* address = ComputeInternalPointer<T>(offset);
+    DCHECK(IsWordAligned(address));
+    *address = value;
   }
 
   // Load value of type `T` at `offset`.  The memory address corresponding
   // to `offset` does not need to be word-aligned.
-  template<typename T> T LoadUnaligned(uintptr_t offset) const {
+  template<typename T>
+  ALWAYS_INLINE T LoadUnaligned(uintptr_t offset) const {
     // Equivalent unsigned integer type corresponding to T.
     typedef typename UnsignedIntegerType<sizeof(T)>::type U;
     U equivalent_unsigned_integer_value = 0;
@@ -77,7 +83,8 @@
 
   // Store `value` (of type `T`) at `offset`.  The memory address
   // corresponding to `offset` does not need to be word-aligned.
-  template<typename T> void StoreUnaligned(uintptr_t offset, T value) const {
+  template<typename T>
+  ALWAYS_INLINE void StoreUnaligned(uintptr_t offset, T value) const {
     // Equivalent unsigned integer type corresponding to T.
     typedef typename UnsignedIntegerType<sizeof(T)>::type U;
     U equivalent_unsigned_integer_value = bit_cast<U, T>(value);
@@ -88,19 +95,20 @@
     }
   }
 
-  template<typename T> T* PointerTo(uintptr_t offset) const {
+  template<typename T>
+  ALWAYS_INLINE T* PointerTo(uintptr_t offset) const {
     return ComputeInternalPointer<T>(offset);
   }
 
   // Load a single bit in the region. The bit at offset 0 is the least
   // significant bit in the first byte.
-  bool LoadBit(uintptr_t bit_offset) const {
+  ALWAYS_INLINE bool LoadBit(uintptr_t bit_offset) const {
     uint8_t bit_mask;
     uint8_t byte = *ComputeBitPointer(bit_offset, &bit_mask);
     return byte & bit_mask;
   }
 
-  void StoreBit(uintptr_t bit_offset, bool value) const {
+  ALWAYS_INLINE void StoreBit(uintptr_t bit_offset, bool value) const {
     uint8_t bit_mask;
     uint8_t* byte = ComputeBitPointer(bit_offset, &bit_mask);
     if (value) {
@@ -110,6 +118,31 @@
     }
   }
 
+  // Load `length` bits from the region starting at bit offset `bit_offset`.
+  // The bit at the smallest offset is the least significant bit in the
+  // loaded value.  `length` must not be larger than the number of bits
+  // contained in the return value (32).
+  uint32_t LoadBits(uintptr_t bit_offset, size_t length) const {
+    CHECK_LE(length, sizeof(uint32_t) * kBitsPerByte);
+    uint32_t value = 0u;
+    for (size_t i = 0; i < length; ++i) {
+      value |= LoadBit(bit_offset + i) << i;
+    }
+    return value;
+  }
+
+  // Store `value` on `length` bits in the region starting at bit offset
+  // `bit_offset`.  The bit at the smallest offset is the least significant
+  // bit of the stored `value`.  `value` must not be larger than `length`
+  // bits.
+  void StoreBits(uintptr_t bit_offset, uint32_t value, size_t length) {
+    CHECK_LT(value, 2u << length);
+    for (size_t i = 0; i < length; ++i) {
+      bool ith_bit = value & (1 << i);
+      StoreBit(bit_offset + i, ith_bit);
+    }
+  }
+
   void CopyFrom(size_t offset, const MemoryRegion& from) const;
 
   // Compute a sub memory region based on an existing one.
@@ -126,7 +159,8 @@
   }
 
  private:
-  template<typename T> T* ComputeInternalPointer(size_t offset) const {
+  template<typename T>
+  ALWAYS_INLINE T* ComputeInternalPointer(size_t offset) const {
     CHECK_GE(size(), sizeof(T));
     CHECK_LE(offset, size() - sizeof(T));
     return reinterpret_cast<T*>(start() + offset);
@@ -134,13 +168,20 @@
 
   // Locate the bit with the given offset. Returns a pointer to the byte
   // containing the bit, and sets bit_mask to the bit within that byte.
-  uint8_t* ComputeBitPointer(uintptr_t bit_offset, uint8_t* bit_mask) const {
+  ALWAYS_INLINE uint8_t* ComputeBitPointer(uintptr_t bit_offset, uint8_t* bit_mask) const {
     uintptr_t bit_remainder = (bit_offset & (kBitsPerByte - 1));
     *bit_mask = (1U << bit_remainder);
     uintptr_t byte_offset = (bit_offset >> kBitsPerByteLog2);
     return ComputeInternalPointer<uint8_t>(byte_offset);
   }
 
+  // Is `address` aligned on a machine word?
+  template<typename T> static bool IsWordAligned(const T* address) {
+    // Word alignment in bytes.
+    size_t kWordAlignment = GetInstructionSetPointerSize(kRuntimeISA);
+    return IsAlignedParam(address, kWordAlignment);
+  }
+
   void* pointer_;
   size_t size_;
 };
diff --git a/runtime/mirror/accessible_object.h b/runtime/mirror/accessible_object.h
new file mode 100644
index 0000000..6d4c0f6
--- /dev/null
+++ b/runtime/mirror/accessible_object.h
@@ -0,0 +1,60 @@
+/*
+ * Copyright (C) 2015 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.
+ */
+
+#ifndef ART_RUNTIME_MIRROR_ACCESSIBLE_OBJECT_H_
+#define ART_RUNTIME_MIRROR_ACCESSIBLE_OBJECT_H_
+
+#include "class.h"
+#include "gc_root.h"
+#include "object.h"
+#include "object_callbacks.h"
+#include "read_barrier_option.h"
+#include "thread.h"
+
+namespace art {
+
+namespace mirror {
+
+// C++ mirror of java.lang.reflect.AccessibleObject
+class MANAGED AccessibleObject : public Object {
+ public:
+  static MemberOffset FlagOffset() {
+    return OFFSET_OF_OBJECT_MEMBER(AccessibleObject, flag_);
+  }
+
+  template<bool kTransactionActive>
+  void SetAccessible(bool value) SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
+    UNUSED(padding_);
+    return SetFieldBoolean<kTransactionActive>(FlagOffset(), value ? 1u : 0u);
+  }
+
+  bool IsAccessible() SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
+    return GetFieldBoolean(FlagOffset());
+  }
+
+ private:
+  uint8_t flag_;
+  // Padding required for now since "packed" will cause reflect.Field fields to not be aligned
+  // otherwise.
+  uint8_t padding_[3];
+
+  DISALLOW_IMPLICIT_CONSTRUCTORS(AccessibleObject);
+};
+
+}  // namespace mirror
+}  // namespace art
+
+#endif  // ART_RUNTIME_MIRROR_ACCESSIBLE_OBJECT_H_
diff --git a/runtime/mirror/art_field-inl.h b/runtime/mirror/art_field-inl.h
index 2b406bd..986852f 100644
--- a/runtime/mirror/art_field-inl.h
+++ b/runtime/mirror/art_field-inl.h
@@ -34,7 +34,7 @@
 namespace mirror {
 
 inline uint32_t ArtField::ClassSize() {
-  uint32_t vtable_entries = Object::kVTableLength + 6;
+  uint32_t vtable_entries = Object::kVTableLength;
   return Class::ComputeClassSize(true, vtable_entries, 0, 0, 0, 0, 0);
 }
 
@@ -290,16 +290,19 @@
   return GetTypeAsPrimitiveType() != Primitive::kPrimNot;
 }
 
-inline Class* ArtField::GetType(bool resolve) {
-  uint32_t field_index = GetDexFieldIndex();
-  if (UNLIKELY(GetDeclaringClass()->IsProxyClass())) {
+template <bool kResolve>
+inline Class* ArtField::GetType() {
+  const uint32_t field_index = GetDexFieldIndex();
+  auto* declaring_class = GetDeclaringClass();
+  if (UNLIKELY(declaring_class->IsProxyClass())) {
     return Runtime::Current()->GetClassLinker()->FindSystemClass(Thread::Current(),
                                                                  GetTypeDescriptor());
   }
-  const DexFile* dex_file = GetDexFile();
+  auto* dex_cache = declaring_class->GetDexCache();
+  const DexFile* const dex_file = dex_cache->GetDexFile();
   const DexFile::FieldId& field_id = dex_file->GetFieldId(field_index);
-  mirror::Class* type = GetDexCache()->GetResolvedType(field_id.type_idx_);
-  if (resolve && (type == nullptr)) {
+  mirror::Class* type = dex_cache->GetResolvedType(field_id.type_idx_);
+  if (kResolve && UNLIKELY(type == nullptr)) {
     type = Runtime::Current()->GetClassLinker()->ResolveType(field_id.type_idx_, this);
     CHECK(type != nullptr || Thread::Current()->IsExceptionPending());
   }
@@ -318,12 +321,19 @@
   return GetDexCache()->GetDexFile();
 }
 
-inline ArtField* ArtField::FromReflectedField(const ScopedObjectAccessAlreadyRunnable& soa,
-                                              jobject jlr_field) {
-  mirror::ArtField* f = soa.DecodeField(WellKnownClasses::java_lang_reflect_Field_artField);
-  mirror::ArtField* field = f->GetObject(soa.Decode<mirror::Object*>(jlr_field))->AsArtField();
-  DCHECK(field != nullptr);
-  return field;
+inline String* ArtField::GetStringName(Thread* self, bool resolve) {
+  auto dex_field_index = GetDexFieldIndex();
+  CHECK_NE(dex_field_index, DexFile::kDexNoIndex);
+  auto* dex_cache = GetDexCache();
+  const auto* dex_file = dex_cache->GetDexFile();
+  const auto& field_id = dex_file->GetFieldId(dex_field_index);
+  auto* name = dex_cache->GetResolvedString(field_id.name_idx_);
+  if (resolve && name == nullptr) {
+    StackHandleScope<1> hs(self);
+    name = Runtime::Current()->GetClassLinker()->ResolveString(
+        *dex_file, field_id.name_idx_, hs.NewHandle(dex_cache));
+  }
+  return name;
 }
 
 }  // namespace mirror
diff --git a/runtime/mirror/art_field.cc b/runtime/mirror/art_field.cc
index 3cea4a1..4c36753 100644
--- a/runtime/mirror/art_field.cc
+++ b/runtime/mirror/art_field.cc
@@ -45,7 +45,7 @@
 void ArtField::SetOffset(MemberOffset num_bytes) {
   DCHECK(GetDeclaringClass()->IsLoaded() || GetDeclaringClass()->IsErroneous());
   if (kIsDebugBuild && Runtime::Current()->IsAotCompiler() &&
-      !Runtime::Current()->UseCompileTimeClassPath()) {
+      Runtime::Current()->IsCompilingBootImage()) {
     Primitive::Type type = GetTypeAsPrimitiveType();
     if (type == Primitive::kPrimDouble || type == Primitive::kPrimLong) {
       DCHECK_ALIGNED(num_bytes.Uint32Value(), 8);
diff --git a/runtime/mirror/art_field.h b/runtime/mirror/art_field.h
index a1d8844..d640165 100644
--- a/runtime/mirror/art_field.h
+++ b/runtime/mirror/art_field.h
@@ -47,10 +47,6 @@
     return sizeof(ArtField);
   }
 
-  ALWAYS_INLINE static ArtField* FromReflectedField(const ScopedObjectAccessAlreadyRunnable& soa,
-                                                    jobject jlr_field)
-      SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
-
   Class* GetDeclaringClass() SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
 
   void SetDeclaringClass(Class *new_declaring_class) SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
@@ -155,13 +151,17 @@
 
   const char* GetName() SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
 
+  // Resolves / returns the name from the dex cache.
+  String* GetStringName(Thread* self, bool resolve) SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
+
   const char* GetTypeDescriptor() SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
 
   Primitive::Type GetTypeAsPrimitiveType() SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
 
   bool IsPrimitiveType() SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
 
-  Class* GetType(bool resolve) SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
+  template <bool kResolve>
+  Class* GetType() SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
 
   size_t FieldSize() SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
 
diff --git a/runtime/mirror/field-inl.h b/runtime/mirror/field-inl.h
new file mode 100644
index 0000000..24ebc48
--- /dev/null
+++ b/runtime/mirror/field-inl.h
@@ -0,0 +1,79 @@
+/*
+ * Copyright (C) 2015 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.
+ */
+
+#ifndef ART_RUNTIME_MIRROR_FIELD_INL_H_
+#define ART_RUNTIME_MIRROR_FIELD_INL_H_
+
+#include "field.h"
+
+#include "art_field-inl.h"
+#include "runtime-inl.h"
+
+namespace art {
+
+namespace mirror {
+
+template <bool kTransactionActive>
+inline mirror::Field* Field::CreateFromArtField(Thread* self, mirror::ArtField* field,
+                                                bool force_resolve) {
+  CHECK(!kMovingFields);
+  // Try to resolve type before allocating since this is a thread suspension point.
+  mirror::Class* type = field->GetType<true>();
+
+  if (type == nullptr) {
+    if (force_resolve) {
+      if (kIsDebugBuild) {
+        self->AssertPendingException();
+      }
+      return nullptr;
+    } else {
+      // Can't resolve, clear the exception if it isn't OOME and continue with a null type.
+      mirror::Throwable* exception = self->GetException();
+      if (exception->GetClass()->DescriptorEquals("Ljava/lang/OutOfMemoryError;")) {
+        return nullptr;
+      }
+      self->ClearException();
+    }
+  }
+  StackHandleScope<1> hs(self);
+  auto ret = hs.NewHandle(static_cast<Field*>(StaticClass()->AllocObject(self)));
+  if (ret.Get() == nullptr) {
+    if (kIsDebugBuild) {
+      self->AssertPendingException();
+    }
+    return nullptr;
+  }
+  auto dex_field_index = field->GetDexFieldIndex();
+  auto* resolved_field = field->GetDexCache()->GetResolvedField(dex_field_index);
+  if (resolved_field != nullptr) {
+    DCHECK_EQ(resolved_field, field);
+  } else {
+    // We rely on the field being resolved so that we can back to the ArtField
+    // (i.e. FromReflectedMethod).
+    field->GetDexCache()->SetResolvedField(dex_field_index, field);
+  }
+  ret->SetType<kTransactionActive>(type);
+  ret->SetDeclaringClass<kTransactionActive>(field->GetDeclaringClass());
+  ret->SetAccessFlags<kTransactionActive>(field->GetAccessFlags());
+  ret->SetDexFieldIndex<kTransactionActive>(dex_field_index);
+  ret->SetOffset<kTransactionActive>(field->GetOffset().Int32Value());
+  return ret.Get();
+}
+
+}  // namespace mirror
+}  // namespace art
+
+#endif  // ART_RUNTIME_MIRROR_FIELD_INL_H_
diff --git a/runtime/mirror/field.cc b/runtime/mirror/field.cc
new file mode 100644
index 0000000..1724682
--- /dev/null
+++ b/runtime/mirror/field.cc
@@ -0,0 +1,64 @@
+/*
+ * Copyright (C) 2015 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.
+ */
+
+#include "field-inl.h"
+
+#include "dex_cache-inl.h"
+#include "object_array-inl.h"
+#include "object-inl.h"
+
+namespace art {
+namespace mirror {
+
+GcRoot<Class> Field::static_class_;
+GcRoot<Class> Field::array_class_;
+
+void Field::SetClass(Class* klass) {
+  CHECK(static_class_.IsNull()) << static_class_.Read() << " " << klass;
+  CHECK(klass != nullptr);
+  static_class_ = GcRoot<Class>(klass);
+}
+
+void Field::ResetClass() {
+  CHECK(!static_class_.IsNull());
+  static_class_ = GcRoot<Class>(nullptr);
+}
+
+void Field::SetArrayClass(Class* klass) {
+  CHECK(array_class_.IsNull()) << array_class_.Read() << " " << klass;
+  CHECK(klass != nullptr);
+  array_class_ = GcRoot<Class>(klass);
+}
+
+void Field::ResetArrayClass() {
+  CHECK(!array_class_.IsNull());
+  array_class_ = GcRoot<Class>(nullptr);
+}
+
+void Field::VisitRoots(RootCallback* callback, void* arg) {
+  static_class_.VisitRootIfNonNull(callback, arg, RootInfo(kRootStickyClass));
+  array_class_.VisitRootIfNonNull(callback, arg, RootInfo(kRootStickyClass));
+}
+
+ArtField* Field::GetArtField() {
+  mirror::DexCache* const dex_cache = GetDeclaringClass()->GetDexCache();
+  mirror::ArtField* const art_field = dex_cache->GetResolvedField(GetDexFieldIndex());
+  CHECK(art_field != nullptr);
+  return art_field;
+}
+
+}  // namespace mirror
+}  // namespace art
diff --git a/runtime/mirror/field.h b/runtime/mirror/field.h
new file mode 100644
index 0000000..f54340a
--- /dev/null
+++ b/runtime/mirror/field.h
@@ -0,0 +1,145 @@
+/*
+ * Copyright (C) 2015 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.
+ */
+
+#ifndef ART_RUNTIME_MIRROR_FIELD_H_
+#define ART_RUNTIME_MIRROR_FIELD_H_
+
+#include "accessible_object.h"
+#include "gc_root.h"
+#include "object.h"
+#include "object_callbacks.h"
+#include "read_barrier_option.h"
+
+namespace art {
+
+struct FieldOffsets;
+
+namespace mirror {
+
+class ArtField;
+class Class;
+class String;
+
+// C++ mirror of java.lang.reflect.Field.
+class MANAGED Field : public AccessibleObject {
+ public:
+  static mirror::Class* StaticClass() SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
+    return static_class_.Read();
+  }
+
+  static mirror::Class* ArrayClass() SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
+    return array_class_.Read();
+  }
+
+  ALWAYS_INLINE uint32_t GetDexFieldIndex() SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
+    return GetField32(OFFSET_OF_OBJECT_MEMBER(Field, dex_field_index_));
+  }
+
+  mirror::Class* GetDeclaringClass() SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
+    return GetFieldObject<Class>(OFFSET_OF_OBJECT_MEMBER(Field, declaring_class_));
+  }
+
+  uint32_t GetAccessFlags() SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
+    return GetField32(OFFSET_OF_OBJECT_MEMBER(Field, access_flags_));
+  }
+
+  bool IsStatic() SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
+    return (GetAccessFlags() & kAccStatic) != 0;
+  }
+
+  bool IsFinal() SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
+    return (GetAccessFlags() & kAccFinal) != 0;
+  }
+
+  bool IsVolatile() SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
+    return (GetAccessFlags() & kAccVolatile) != 0;
+  }
+
+  ALWAYS_INLINE Primitive::Type GetTypeAsPrimitiveType()
+      SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
+    return GetType()->GetPrimitiveType();
+  }
+
+  mirror::Class* GetType() SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
+    return GetFieldObject<mirror::Class>(OFFSET_OF_OBJECT_MEMBER(Field, type_));
+  }
+
+  int32_t GetOffset() SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
+    return GetField32(OFFSET_OF_OBJECT_MEMBER(Field, offset_));
+  }
+
+  static void SetClass(Class* klass) SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
+
+  static void SetArrayClass(Class* klass) SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
+
+  static void ResetClass() SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
+
+  static void ResetArrayClass() SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
+
+  static void VisitRoots(RootCallback* callback, void* arg)
+      SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
+
+  // Slow, try to use only for PrettyField and such.
+  mirror::ArtField* GetArtField() SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
+
+  template <bool kTransactionActive = false>
+  static mirror::Field* CreateFromArtField(Thread* self, mirror::ArtField* field,
+                                           bool force_resolve)
+      SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
+
+ private:
+  HeapReference<mirror::Class> declaring_class_;
+  HeapReference<mirror::Class> type_;
+  int32_t access_flags_;
+  int32_t dex_field_index_;
+  int32_t offset_;
+
+  template<bool kTransactionActive>
+  void SetDeclaringClass(mirror::Class* c) SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
+    SetFieldObject<kTransactionActive>(OFFSET_OF_OBJECT_MEMBER(Field, declaring_class_), c);
+  }
+
+  template<bool kTransactionActive>
+  void SetType(mirror::Class* type) SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
+    SetFieldObject<kTransactionActive>(OFFSET_OF_OBJECT_MEMBER(Field, type_), type);
+  }
+
+  template<bool kTransactionActive>
+  void SetAccessFlags(uint32_t flags) SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
+    SetField32<kTransactionActive>(OFFSET_OF_OBJECT_MEMBER(Field, access_flags_), flags);
+  }
+
+  template<bool kTransactionActive>
+  void SetDexFieldIndex(uint32_t idx) SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
+    SetField32<kTransactionActive>(OFFSET_OF_OBJECT_MEMBER(Field, dex_field_index_), idx);
+  }
+
+  template<bool kTransactionActive>
+  void SetOffset(uint32_t offset) SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
+    SetField32<kTransactionActive>(OFFSET_OF_OBJECT_MEMBER(Field, offset_), offset);
+  }
+
+  static GcRoot<Class> static_class_;  // java.lang.reflect.Field.class.
+  static GcRoot<Class> array_class_;  // array of java.lang.reflect.Field.
+
+  friend struct art::FieldOffsets;  // for verifying offset information
+  DISALLOW_IMPLICIT_CONSTRUCTORS(Field);
+};
+
+}  // namespace mirror
+}  // namespace art
+
+#endif  // ART_RUNTIME_MIRROR_FIELD_H_
diff --git a/runtime/mirror/object.cc b/runtime/mirror/object.cc
index bbbdf98..57ac46f 100644
--- a/runtime/mirror/object.cc
+++ b/runtime/mirror/object.cc
@@ -214,7 +214,7 @@
         if (field->GetOffset().Int32Value() == field_offset.Int32Value()) {
           CHECK_NE(field->GetTypeAsPrimitiveType(), Primitive::kPrimNot);
           // TODO: resolve the field type for moving GC.
-          mirror::Class* field_type = field->GetType(!kMovingCollector);
+          mirror::Class* field_type = field->GetType<!kMovingCollector>();
           if (field_type != nullptr) {
             CHECK(field_type->IsAssignableFrom(new_value->GetClass()));
           }
@@ -236,7 +236,7 @@
         if (field->GetOffset().Int32Value() == field_offset.Int32Value()) {
           CHECK_NE(field->GetTypeAsPrimitiveType(), Primitive::kPrimNot);
           // TODO: resolve the field type for moving GC.
-          mirror::Class* field_type = field->GetType(!kMovingCollector);
+          mirror::Class* field_type = field->GetType<!kMovingCollector>();
           if (field_type != nullptr) {
             CHECK(field_type->IsAssignableFrom(new_value->GetClass()));
           }
diff --git a/runtime/mirror/object.h b/runtime/mirror/object.h
index 780c5ae..b730670 100644
--- a/runtime/mirror/object.h
+++ b/runtime/mirror/object.h
@@ -100,7 +100,7 @@
   template<VerifyObjectFlags kVerifyFlags = kDefaultVerifyFlags>
   bool VerifierInstanceOf(Class* klass) SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
   template<VerifyObjectFlags kVerifyFlags = kDefaultVerifyFlags>
-  bool InstanceOf(Class* klass) SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
+  ALWAYS_INLINE bool InstanceOf(Class* klass) SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
 
   template<VerifyObjectFlags kVerifyFlags = kDefaultVerifyFlags,
            ReadBarrierOption kReadBarrierOption = kWithReadBarrier>
diff --git a/runtime/mirror/object_test.cc b/runtime/mirror/object_test.cc
index 21972a1..1ce298d 100644
--- a/runtime/mirror/object_test.cc
+++ b/runtime/mirror/object_test.cc
@@ -360,8 +360,7 @@
   // pretend we are trying to access 'Static.s0' from StaticsFromCode.<clinit>
   ScopedObjectAccess soa(Thread::Current());
   jobject class_loader = LoadDex("StaticsFromCode");
-  const DexFile* dex_file = Runtime::Current()->GetCompileTimeClassPath(class_loader)[0];
-  CHECK(dex_file != NULL);
+  const DexFile* dex_file = GetFirstDexFile(class_loader);
 
   StackHandleScope<2> hs(soa.Self());
   Handle<mirror::ClassLoader> loader(hs.NewHandle(soa.Decode<ClassLoader*>(class_loader)));
diff --git a/runtime/mirror/reference.h b/runtime/mirror/reference.h
index 7345448..69ef69c 100644
--- a/runtime/mirror/reference.h
+++ b/runtime/mirror/reference.h
@@ -99,7 +99,7 @@
     return java_lang_ref_Reference_.Read<kReadBarrierOption>();
   }
   static void SetClass(Class* klass);
-  static void ResetClass(void);
+  static void ResetClass();
   static void VisitRoots(RootCallback* callback, void* arg);
 
  private:
diff --git a/runtime/native/dalvik_system_VMDebug.cc b/runtime/native/dalvik_system_VMDebug.cc
index 57ca2b1..2724d91 100644
--- a/runtime/native/dalvik_system_VMDebug.cc
+++ b/runtime/native/dalvik_system_VMDebug.cc
@@ -79,7 +79,9 @@
 
 static void VMDebug_startMethodTracingDdmsImpl(JNIEnv*, jclass, jint bufferSize, jint flags,
                                                jboolean samplingEnabled, jint intervalUs) {
-  Trace::Start("[DDMS]", -1, bufferSize, flags, true, samplingEnabled, intervalUs);
+  Trace::Start("[DDMS]", -1, bufferSize, flags, Trace::TraceOutputMode::kDDMS,
+               samplingEnabled ? Trace::TraceMode::kSampling : Trace::TraceMode::kMethodTracing,
+               intervalUs);
 }
 
 static void VMDebug_startMethodTracingFd(JNIEnv* env, jclass, jstring javaTraceFilename,
@@ -102,7 +104,9 @@
   if (traceFilename.c_str() == NULL) {
     return;
   }
-  Trace::Start(traceFilename.c_str(), fd, bufferSize, flags, false, samplingEnabled, intervalUs);
+  Trace::Start(traceFilename.c_str(), fd, bufferSize, flags, Trace::TraceOutputMode::kFile,
+               samplingEnabled ? Trace::TraceMode::kSampling : Trace::TraceMode::kMethodTracing,
+               intervalUs);
 }
 
 static void VMDebug_startMethodTracingFilename(JNIEnv* env, jclass, jstring javaTraceFilename,
@@ -112,7 +116,9 @@
   if (traceFilename.c_str() == NULL) {
     return;
   }
-  Trace::Start(traceFilename.c_str(), -1, bufferSize, flags, false, samplingEnabled, intervalUs);
+  Trace::Start(traceFilename.c_str(), -1, bufferSize, flags, Trace::TraceOutputMode::kFile,
+               samplingEnabled ? Trace::TraceMode::kSampling : Trace::TraceMode::kMethodTracing,
+               intervalUs);
 }
 
 static jint VMDebug_getMethodTracingMode(JNIEnv*, jclass) {
diff --git a/runtime/native/java_lang_Class.cc b/runtime/native/java_lang_Class.cc
index 60d14e9..0ca9d24 100644
--- a/runtime/native/java_lang_Class.cc
+++ b/runtime/native/java_lang_Class.cc
@@ -17,21 +17,28 @@
 #include "java_lang_Class.h"
 
 #include "class_linker.h"
+#include "common_throws.h"
 #include "dex_file-inl.h"
 #include "jni_internal.h"
 #include "nth_caller_visitor.h"
+#include "mirror/art_field-inl.h"
 #include "mirror/class-inl.h"
 #include "mirror/class_loader.h"
+#include "mirror/field.h"
 #include "mirror/object-inl.h"
+#include "mirror/object_array-inl.h"
+#include "mirror/string-inl.h"
 #include "scoped_thread_state_change.h"
 #include "scoped_fast_native_object_access.h"
 #include "ScopedLocalRef.h"
 #include "ScopedUtfChars.h"
+#include "utf.h"
 #include "well_known_classes.h"
 
 namespace art {
 
-static mirror::Class* DecodeClass(const ScopedFastNativeObjectAccess& soa, jobject java_class)
+ALWAYS_INLINE static inline mirror::Class* DecodeClass(
+    const ScopedFastNativeObjectAccess& soa, jobject java_class)
     SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
   mirror::Class* c = soa.Decode<mirror::Class*>(java_class);
   DCHECK(c != NULL);
@@ -97,10 +104,173 @@
   return soa.AddLocalReference<jobjectArray>(c->GetInterfaces()->Clone(soa.Self()));
 }
 
+static mirror::ObjectArray<mirror::Field>* GetDeclaredFields(
+    Thread* self, mirror::Class* klass, bool public_only, bool force_resolve)
+      SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
+  StackHandleScope<3> hs(self);
+  auto h_ifields = hs.NewHandle(klass->GetIFields());
+  auto h_sfields = hs.NewHandle(klass->GetSFields());
+  const int32_t num_ifields = h_ifields.Get() != nullptr ? h_ifields->GetLength() : 0;
+  const int32_t num_sfields = h_sfields.Get() != nullptr ? h_sfields->GetLength() : 0;
+  int32_t array_size = num_ifields + num_sfields;
+  if (public_only) {
+    // Lets go subtract all the non public fields.
+    for (int32_t i = 0; i < num_ifields; ++i) {
+      if (!h_ifields->GetWithoutChecks(i)->IsPublic()) {
+        --array_size;
+      }
+    }
+    for (int32_t i = 0; i < num_sfields; ++i) {
+      if (!h_sfields->GetWithoutChecks(i)->IsPublic()) {
+        --array_size;
+      }
+    }
+  }
+  int32_t array_idx = 0;
+  auto object_array = hs.NewHandle(mirror::ObjectArray<mirror::Field>::Alloc(
+      self, mirror::Field::ArrayClass(), array_size));
+  if (object_array.Get() == nullptr) {
+    return nullptr;
+  }
+  for (int32_t i = 0; i < num_ifields; ++i) {
+    auto* art_field = h_ifields->GetWithoutChecks(i);
+    if (!public_only || art_field->IsPublic()) {
+      auto* field = mirror::Field::CreateFromArtField(self, art_field, force_resolve);
+      if (field == nullptr) {
+        if (kIsDebugBuild) {
+          self->AssertPendingException();
+        }
+        // Maybe null due to OOME or type resolving exception.
+        return nullptr;
+      }
+      object_array->SetWithoutChecks<false>(array_idx++, field);
+    }
+  }
+  for (int32_t i = 0; i < num_sfields; ++i) {
+    auto* art_field = h_sfields->GetWithoutChecks(i);
+    if (!public_only || art_field->IsPublic()) {
+      auto* field = mirror::Field::CreateFromArtField(self, art_field, force_resolve);
+      if (field == nullptr) {
+        if (kIsDebugBuild) {
+          self->AssertPendingException();
+        }
+        return nullptr;
+      }
+      object_array->SetWithoutChecks<false>(array_idx++, field);
+    }
+  }
+  CHECK_EQ(array_idx, array_size);
+  return object_array.Get();
+}
+
+static jobjectArray Class_getDeclaredFieldsUnchecked(JNIEnv* env, jobject javaThis,
+                                                     jboolean publicOnly) {
+  ScopedFastNativeObjectAccess soa(env);
+  return soa.AddLocalReference<jobjectArray>(
+      GetDeclaredFields(soa.Self(), DecodeClass(soa, javaThis), publicOnly != JNI_FALSE, false));
+}
+
+static jobjectArray Class_getDeclaredFields(JNIEnv* env, jobject javaThis) {
+  ScopedFastNativeObjectAccess soa(env);
+  return soa.AddLocalReference<jobjectArray>(
+      GetDeclaredFields(soa.Self(), DecodeClass(soa, javaThis), false, true));
+}
+
+static jobjectArray Class_getPublicDeclaredFields(JNIEnv* env, jobject javaThis) {
+  ScopedFastNativeObjectAccess soa(env);
+  return soa.AddLocalReference<jobjectArray>(
+      GetDeclaredFields(soa.Self(), DecodeClass(soa, javaThis), true, true));
+}
+
+// Performs a binary search through an array of fields, TODO: Is this fast enough if we don't use
+// the dex cache for lookups? I think CompareModifiedUtf8ToUtf16AsCodePointValues should be fairly
+// fast.
+ALWAYS_INLINE static inline mirror::ArtField* FindFieldByName(
+    Thread* self ATTRIBUTE_UNUSED, mirror::String* name,
+    mirror::ObjectArray<mirror::ArtField>* fields)
+    SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
+  uint32_t low = 0;
+  uint32_t high = fields->GetLength();
+  const uint16_t* const data = name->GetCharArray()->GetData() + name->GetOffset();
+  const size_t length = name->GetLength();
+  while (low < high) {
+    auto mid = (low + high) / 2;
+    mirror::ArtField* const field = fields->GetWithoutChecks(mid);
+    int result = CompareModifiedUtf8ToUtf16AsCodePointValues(field->GetName(), data, length);
+    // Alternate approach, only a few % faster at the cost of more allocations.
+    // int result = field->GetStringName(self, true)->CompareTo(name);
+    if (result < 0) {
+      low = mid + 1;
+    } else if (result > 0) {
+      high = mid;
+    } else {
+      return field;
+    }
+  }
+  if (kIsDebugBuild) {
+    for (int32_t i = 0; i < fields->GetLength(); ++i) {
+      CHECK_NE(fields->GetWithoutChecks(i)->GetName(), name->ToModifiedUtf8());
+    }
+  }
+  return nullptr;
+}
+
+ALWAYS_INLINE static inline mirror::Field* GetDeclaredField(
+    Thread* self, mirror::Class* c, mirror::String* name)
+    SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
+  auto* instance_fields = c->GetIFields();
+  if (instance_fields != nullptr) {
+    auto* art_field = FindFieldByName(self, name, instance_fields);
+    if (art_field != nullptr) {
+      return mirror::Field::CreateFromArtField(self, art_field, true);
+    }
+  }
+  auto* static_fields = c->GetSFields();
+  if (static_fields != nullptr) {
+    auto* art_field = FindFieldByName(self, name, static_fields);
+    if (art_field != nullptr) {
+      return mirror::Field::CreateFromArtField(self, art_field, true);
+    }
+  }
+  return nullptr;
+}
+
+static jobject Class_getDeclaredFieldInternal(JNIEnv* env, jobject javaThis, jstring name) {
+  ScopedFastNativeObjectAccess soa(env);
+  auto* name_string = soa.Decode<mirror::String*>(name);
+  return soa.AddLocalReference<jobject>(
+      GetDeclaredField(soa.Self(), DecodeClass(soa, javaThis), name_string));
+}
+
+static jobject Class_getDeclaredField(JNIEnv* env, jobject javaThis, jstring name) {
+  ScopedFastNativeObjectAccess soa(env);
+  auto* name_string = soa.Decode<mirror::String*>(name);
+  if (name == nullptr) {
+    ThrowNullPointerException("name == null");
+    return nullptr;
+  }
+  auto* klass = DecodeClass(soa, javaThis);
+  mirror::Field* result = GetDeclaredField(soa.Self(), klass, name_string);
+  if (result == nullptr) {
+    std::string name_str = name_string->ToModifiedUtf8();
+    // We may have a pending exception if we failed to resolve.
+    if (!soa.Self()->IsExceptionPending()) {
+      soa.Self()->ThrowNewException("Ljava/lang/NoSuchFieldException;", name_str.c_str());
+    }
+    return nullptr;
+  }
+  return soa.AddLocalReference<jobject>(result);
+}
+
 static JNINativeMethod gMethods[] = {
   NATIVE_METHOD(Class, classForName, "!(Ljava/lang/String;ZLjava/lang/ClassLoader;)Ljava/lang/Class;"),
   NATIVE_METHOD(Class, getNameNative, "!()Ljava/lang/String;"),
   NATIVE_METHOD(Class, getProxyInterfaces, "!()[Ljava/lang/Class;"),
+  NATIVE_METHOD(Class, getDeclaredFields, "!()[Ljava/lang/reflect/Field;"),
+  NATIVE_METHOD(Class, getPublicDeclaredFields, "!()[Ljava/lang/reflect/Field;"),
+  NATIVE_METHOD(Class, getDeclaredFieldsUnchecked, "!(Z)[Ljava/lang/reflect/Field;"),
+  NATIVE_METHOD(Class, getDeclaredFieldInternal, "!(Ljava/lang/String;)Ljava/lang/reflect/Field;"),
+  NATIVE_METHOD(Class, getDeclaredField, "!(Ljava/lang/String;)Ljava/lang/reflect/Field;"),
 };
 
 void register_java_lang_Class(JNIEnv* env) {
diff --git a/runtime/native/java_lang_reflect_Field.cc b/runtime/native/java_lang_reflect_Field.cc
index 9c5bde9..721b7a3 100644
--- a/runtime/native/java_lang_reflect_Field.cc
+++ b/runtime/native/java_lang_reflect_Field.cc
@@ -21,35 +21,35 @@
 #include "common_throws.h"
 #include "dex_file-inl.h"
 #include "jni_internal.h"
-#include "mirror/art_field-inl.h"
 #include "mirror/art_method-inl.h"
 #include "mirror/class-inl.h"
+#include "mirror/field.h"
 #include "reflection-inl.h"
 #include "scoped_fast_native_object_access.h"
 
 namespace art {
 
 template<bool kIsSet>
-ALWAYS_INLINE inline static bool VerifyFieldAccess(Thread* self, mirror::ArtField* field,
+ALWAYS_INLINE inline static bool VerifyFieldAccess(Thread* self, mirror::Field* field,
                                                    mirror::Object* obj)
     SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
   if (kIsSet && field->IsFinal()) {
     ThrowIllegalAccessException(
             StringPrintf("Cannot set %s field %s of class %s",
                 PrettyJavaAccessFlags(field->GetAccessFlags()).c_str(),
-                PrettyField(field).c_str(),
+                PrettyField(field->GetArtField()).c_str(),
                 field->GetDeclaringClass() == nullptr ? "null" :
                     PrettyClass(field->GetDeclaringClass()).c_str()).c_str());
     return false;
   }
   mirror::Class* calling_class = nullptr;
   if (!VerifyAccess(self, obj, field->GetDeclaringClass(), field->GetAccessFlags(),
-                    &calling_class)) {
+                    &calling_class, 1)) {
     ThrowIllegalAccessException(
             StringPrintf("Class %s cannot access %s field %s of class %s",
                 calling_class == nullptr ? "null" : PrettyClass(calling_class).c_str(),
                 PrettyJavaAccessFlags(field->GetAccessFlags()).c_str(),
-                PrettyField(field).c_str(),
+                PrettyField(field->GetArtField()).c_str(),
                 field->GetDeclaringClass() == nullptr ? "null" :
                     PrettyClass(field->GetDeclaringClass()).c_str()).c_str());
     return false;
@@ -58,38 +58,37 @@
 }
 
 template<bool kAllowReferences>
-ALWAYS_INLINE inline static bool GetFieldValue(mirror::Object* o, mirror::ArtField* f,
+ALWAYS_INLINE inline static bool GetFieldValue(mirror::Object* o, mirror::Field* f,
                                                Primitive::Type field_type, JValue* value)
     SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
   DCHECK_EQ(value->GetJ(), INT64_C(0));
+  MemberOffset offset(f->GetOffset());
+  const bool is_volatile = f->IsVolatile();
   switch (field_type) {
     case Primitive::kPrimBoolean:
-      value->SetZ(f->GetBoolean(o));
+      value->SetZ(is_volatile ? o->GetFieldBooleanVolatile(offset) : o->GetFieldBoolean(offset));
       return true;
     case Primitive::kPrimByte:
-      value->SetB(f->GetByte(o));
+      value->SetB(is_volatile ? o->GetFieldByteVolatile(offset) : o->GetFieldByte(offset));
       return true;
     case Primitive::kPrimChar:
-      value->SetC(f->GetChar(o));
-      return true;
-    case Primitive::kPrimDouble:
-      value->SetD(f->GetDouble(o));
-      return true;
-    case Primitive::kPrimFloat:
-      value->SetF(f->GetFloat(o));
+      value->SetC(is_volatile ? o->GetFieldCharVolatile(offset) : o->GetFieldChar(offset));
       return true;
     case Primitive::kPrimInt:
-      value->SetI(f->GetInt(o));
+    case Primitive::kPrimFloat:
+      value->SetI(is_volatile ? o->GetField32Volatile(offset) : o->GetField32(offset));
       return true;
     case Primitive::kPrimLong:
-      value->SetJ(f->GetLong(o));
+    case Primitive::kPrimDouble:
+      value->SetJ(is_volatile ? o->GetField64Volatile(offset) : o->GetField64(offset));
       return true;
     case Primitive::kPrimShort:
-      value->SetS(f->GetShort(o));
+      value->SetS(is_volatile ? o->GetFieldShortVolatile(offset) : o->GetFieldShort(offset));
       return true;
     case Primitive::kPrimNot:
       if (kAllowReferences) {
-        value->SetL(f->GetObject(o));
+        value->SetL(is_volatile ? o->GetFieldObjectVolatile<mirror::Object>(offset) :
+            o->GetFieldObject<mirror::Object>(offset));
         return true;
       }
       // Else break to report an error.
@@ -98,23 +97,23 @@
       // Never okay.
       break;
   }
-  ThrowIllegalArgumentException(StringPrintf("Not a primitive field: %s",
-                                             PrettyField(f).c_str()).c_str());
+  ThrowIllegalArgumentException(
+      StringPrintf("Not a primitive field: %s", PrettyField(f->GetArtField()).c_str()).c_str());
   return false;
 }
 
 ALWAYS_INLINE inline static bool CheckReceiver(const ScopedFastNativeObjectAccess& soa,
-                                               jobject j_rcvr, mirror::ArtField** f,
+                                               jobject j_rcvr, mirror::Field** f,
                                                mirror::Object** class_or_rcvr)
     SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
   soa.Self()->AssertThreadSuspensionIsAllowable();
   mirror::Class* declaringClass = (*f)->GetDeclaringClass();
   if ((*f)->IsStatic()) {
     if (UNLIKELY(!declaringClass->IsInitialized())) {
-      ClassLinker* class_linker = Runtime::Current()->GetClassLinker();
       StackHandleScope<2> hs(soa.Self());
-      HandleWrapper<mirror::ArtField> h_f(hs.NewHandleWrapper(f));
+      HandleWrapper<mirror::Field> h_f(hs.NewHandleWrapper(f));
       HandleWrapper<mirror::Class> h_klass(hs.NewHandleWrapper(&declaringClass));
+      ClassLinker* const class_linker = Runtime::Current()->GetClassLinker();
       if (UNLIKELY(!class_linker->EnsureInitialized(soa.Self(), h_klass, true, true))) {
         DCHECK(soa.Self()->IsExceptionPending());
         return false;
@@ -131,16 +130,16 @@
   return true;
 }
 
-static jobject Field_get(JNIEnv* env, jobject javaField, jobject javaObj, jboolean accessible) {
+static jobject Field_get(JNIEnv* env, jobject javaField, jobject javaObj) {
   ScopedFastNativeObjectAccess soa(env);
-  mirror::ArtField* f = mirror::ArtField::FromReflectedField(soa, javaField);
+  mirror::Field* f = soa.Decode<mirror::Field*>(javaField);
   mirror::Object* o = nullptr;
   if (!CheckReceiver(soa, javaObj, &f, &o)) {
     DCHECK(soa.Self()->IsExceptionPending());
     return nullptr;
   }
   // If field is not set to be accessible, verify it can be accessed by the caller.
-  if ((accessible == JNI_FALSE) && !VerifyFieldAccess<false>(soa.Self(), f, o)) {
+  if (!f->IsAccessible() && !VerifyFieldAccess<false>(soa.Self(), f, o)) {
     DCHECK(soa.Self()->IsExceptionPending());
     return nullptr;
   }
@@ -157,9 +156,9 @@
 
 template<Primitive::Type kPrimitiveType>
 ALWAYS_INLINE inline static JValue GetPrimitiveField(JNIEnv* env, jobject javaField,
-                                                     jobject javaObj, jboolean accessible) {
+                                                     jobject javaObj) {
   ScopedFastNativeObjectAccess soa(env);
-  mirror::ArtField* f = mirror::ArtField::FromReflectedField(soa, javaField);
+  mirror::Field* f = soa.Decode<mirror::Field*>(javaField);
   mirror::Object* o = nullptr;
   if (!CheckReceiver(soa, javaObj, &f, &o)) {
     DCHECK(soa.Self()->IsExceptionPending());
@@ -167,7 +166,7 @@
   }
 
   // If field is not set to be accessible, verify it can be accessed by the caller.
-  if (accessible == JNI_FALSE && !VerifyFieldAccess<false>(soa.Self(), f, o)) {
+  if (!f->IsAccessible() && !VerifyFieldAccess<false>(soa.Self(), f, o)) {
     DCHECK(soa.Self()->IsExceptionPending());
     return JValue();
   }
@@ -198,72 +197,97 @@
   return wide_value;
 }
 
-static jboolean Field_getBoolean(JNIEnv* env, jobject javaField, jobject javaObj,
-                                 jboolean accessible) {
-  return GetPrimitiveField<Primitive::kPrimBoolean>(env, javaField, javaObj, accessible).GetZ();
+static jboolean Field_getBoolean(JNIEnv* env, jobject javaField, jobject javaObj) {
+  return GetPrimitiveField<Primitive::kPrimBoolean>(env, javaField, javaObj).GetZ();
 }
 
-static jbyte Field_getByte(JNIEnv* env, jobject javaField, jobject javaObj, jboolean accessible) {
-  return GetPrimitiveField<Primitive::kPrimByte>(env, javaField, javaObj, accessible).GetB();
+static jbyte Field_getByte(JNIEnv* env, jobject javaField, jobject javaObj) {
+  return GetPrimitiveField<Primitive::kPrimByte>(env, javaField, javaObj).GetB();
 }
 
-static jchar Field_getChar(JNIEnv* env, jobject javaField, jobject javaObj, jboolean accessible) {
-  return GetPrimitiveField<Primitive::kPrimChar>(env, javaField, javaObj, accessible).GetC();
+static jchar Field_getChar(JNIEnv* env, jobject javaField, jobject javaObj) {
+  return GetPrimitiveField<Primitive::kPrimChar>(env, javaField, javaObj).GetC();
 }
 
-static jdouble Field_getDouble(JNIEnv* env, jobject javaField, jobject javaObj,
-                               jboolean accessible) {
-  return GetPrimitiveField<Primitive::kPrimDouble>(env, javaField, javaObj, accessible).GetD();
+static jdouble Field_getDouble(JNIEnv* env, jobject javaField, jobject javaObj) {
+  return GetPrimitiveField<Primitive::kPrimDouble>(env, javaField, javaObj).GetD();
 }
 
-static jfloat Field_getFloat(JNIEnv* env, jobject javaField, jobject javaObj, jboolean accessible) {
-  return GetPrimitiveField<Primitive::kPrimFloat>(env, javaField, javaObj, accessible).GetF();
+static jfloat Field_getFloat(JNIEnv* env, jobject javaField, jobject javaObj) {
+  return GetPrimitiveField<Primitive::kPrimFloat>(env, javaField, javaObj).GetF();
 }
 
-static jint Field_getInt(JNIEnv* env, jobject javaField, jobject javaObj, jboolean accessible) {
-  return GetPrimitiveField<Primitive::kPrimInt>(env, javaField, javaObj, accessible).GetI();
+static jint Field_getInt(JNIEnv* env, jobject javaField, jobject javaObj) {
+  return GetPrimitiveField<Primitive::kPrimInt>(env, javaField, javaObj).GetI();
 }
 
-static jlong Field_getLong(JNIEnv* env, jobject javaField, jobject javaObj, jboolean accessible) {
-  return GetPrimitiveField<Primitive::kPrimLong>(env, javaField, javaObj, accessible).GetJ();
+static jlong Field_getLong(JNIEnv* env, jobject javaField, jobject javaObj) {
+  return GetPrimitiveField<Primitive::kPrimLong>(env, javaField, javaObj).GetJ();
 }
 
-static jshort Field_getShort(JNIEnv* env, jobject javaField, jobject javaObj, jboolean accessible) {
-  return GetPrimitiveField<Primitive::kPrimShort>(env, javaField, javaObj, accessible).GetS();
+static jshort Field_getShort(JNIEnv* env, jobject javaField, jobject javaObj) {
+  return GetPrimitiveField<Primitive::kPrimShort>(env, javaField, javaObj).GetS();
 }
 
-static void SetFieldValue(mirror::Object* o, mirror::ArtField* f, Primitive::Type field_type,
-                          bool allow_references, const JValue& new_value)
+ALWAYS_INLINE inline static void SetFieldValue(mirror::Object* o, mirror::Field* f,
+                                               Primitive::Type field_type, bool allow_references,
+                                               const JValue& new_value)
     SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
   DCHECK(f->GetDeclaringClass()->IsInitialized());
+  MemberOffset offset(f->GetOffset());
+  const bool is_volatile = f->IsVolatile();
   switch (field_type) {
   case Primitive::kPrimBoolean:
-    f->SetBoolean<false>(o, new_value.GetZ());
+    if (is_volatile) {
+      o->SetFieldBooleanVolatile<false>(offset, new_value.GetZ());
+    } else {
+      o->SetFieldBoolean<false>(offset, new_value.GetZ());
+    }
     break;
   case Primitive::kPrimByte:
-    f->SetByte<false>(o, new_value.GetB());
+    if (is_volatile) {
+      o->SetFieldBooleanVolatile<false>(offset, new_value.GetB());
+    } else {
+      o->SetFieldBoolean<false>(offset, new_value.GetB());
+    }
     break;
   case Primitive::kPrimChar:
-    f->SetChar<false>(o, new_value.GetC());
-    break;
-  case Primitive::kPrimDouble:
-    f->SetDouble<false>(o, new_value.GetD());
-    break;
-  case Primitive::kPrimFloat:
-    f->SetFloat<false>(o, new_value.GetF());
+    if (is_volatile) {
+      o->SetFieldBooleanVolatile<false>(offset, new_value.GetC());
+    } else {
+      o->SetFieldBoolean<false>(offset, new_value.GetC());
+    }
     break;
   case Primitive::kPrimInt:
-    f->SetInt<false>(o, new_value.GetI());
+  case Primitive::kPrimFloat:
+    if (is_volatile) {
+      o->SetField32Volatile<false>(offset, new_value.GetI());
+    } else {
+      o->SetField32<false>(offset, new_value.GetI());
+    }
     break;
   case Primitive::kPrimLong:
-    f->SetLong<false>(o, new_value.GetJ());
+  case Primitive::kPrimDouble:
+    if (is_volatile) {
+      o->SetField64Volatile<false>(offset, new_value.GetJ());
+    } else {
+      o->SetField64<false>(offset, new_value.GetJ());
+    }
     break;
   case Primitive::kPrimShort:
-    f->SetShort<false>(o, new_value.GetS());
+    if (is_volatile) {
+      o->SetFieldShortVolatile<false>(offset, new_value.GetS());
+    } else {
+      o->SetFieldShort<false>(offset, new_value.GetS());
+    }
     break;
   case Primitive::kPrimNot:
     if (allow_references) {
-      f->SetObject<false>(o, new_value.GetL());
+      if (is_volatile) {
+        o->SetFieldObjectVolatile<false>(offset, new_value.GetL());
+      } else {
+        o->SetFieldObject<false>(offset, new_value.GetL());
+      }
       break;
     }
     // Else fall through to report an error.
@@ -271,15 +295,14 @@
   case Primitive::kPrimVoid:
     // Never okay.
     ThrowIllegalArgumentException(StringPrintf("Not a primitive field: %s",
-                                               PrettyField(f).c_str()).c_str());
+                                               PrettyField(f->GetArtField()).c_str()).c_str());
     return;
   }
 }
 
-static void Field_set(JNIEnv* env, jobject javaField, jobject javaObj, jobject javaValue,
-                      jboolean accessible) {
+static void Field_set(JNIEnv* env, jobject javaField, jobject javaObj, jobject javaValue) {
   ScopedFastNativeObjectAccess soa(env);
-  mirror::ArtField* f = mirror::ArtField::FromReflectedField(soa, javaField);
+  mirror::Field* f = soa.Decode<mirror::Field*>(javaField);
   // Check that the receiver is non-null and an instance of the field's declaring class.
   mirror::Object* o = nullptr;
   if (!CheckReceiver(soa, javaObj, &f, &o)) {
@@ -287,18 +310,11 @@
     return;
   }
   mirror::Class* field_type;
-  const char* field_type_desciptor = f->GetTypeDescriptor();
+  const char* field_type_desciptor = f->GetArtField()->GetTypeDescriptor();
   Primitive::Type field_prim_type = Primitive::GetType(field_type_desciptor[0]);
   if (field_prim_type == Primitive::kPrimNot) {
-    StackHandleScope<2> hs(soa.Self());
-    HandleWrapper<mirror::Object> h_o(hs.NewHandleWrapper(&o));
-    HandleWrapper<mirror::ArtField> h_f(hs.NewHandleWrapper(&f));
-    // May cause resolution.
-    field_type = h_f->GetType(true);
-    if (field_type == nullptr) {
-      DCHECK(soa.Self()->IsExceptionPending());
-      return;
-    }
+    field_type = f->GetType();
+    DCHECK(field_type != nullptr);
   } else {
     field_type = Runtime::Current()->GetClassLinker()->FindPrimitiveClass(field_type_desciptor[0]);
   }
@@ -306,12 +322,12 @@
   // Unbox the value, if necessary.
   mirror::Object* boxed_value = soa.Decode<mirror::Object*>(javaValue);
   JValue unboxed_value;
-  if (!UnboxPrimitiveForField(boxed_value, field_type, f, &unboxed_value)) {
+  if (!UnboxPrimitiveForField(boxed_value, field_type, f->GetArtField(), &unboxed_value)) {
     DCHECK(soa.Self()->IsExceptionPending());
     return;
   }
   // If field is not set to be accessible, verify it can be accessed by the caller.
-  if ((accessible == JNI_FALSE) && !VerifyFieldAccess<true>(soa.Self(), f, o)) {
+  if (!f->IsAccessible() && !VerifyFieldAccess<true>(soa.Self(), f, o)) {
     DCHECK(soa.Self()->IsExceptionPending());
     return;
   }
@@ -320,9 +336,9 @@
 
 template<Primitive::Type kPrimitiveType>
 static void SetPrimitiveField(JNIEnv* env, jobject javaField, jobject javaObj,
-                              const JValue& new_value, jboolean accessible) {
+                              const JValue& new_value) {
   ScopedFastNativeObjectAccess soa(env);
-  mirror::ArtField* f = mirror::ArtField::FromReflectedField(soa, javaField);
+  mirror::Field* f = soa.Decode<mirror::Field*>(javaField);
   mirror::Object* o = nullptr;
   if (!CheckReceiver(soa, javaObj, &f, &o)) {
     return;
@@ -330,7 +346,7 @@
   Primitive::Type field_type = f->GetTypeAsPrimitiveType();
   if (UNLIKELY(field_type == Primitive::kPrimNot)) {
     ThrowIllegalArgumentException(StringPrintf("Not a primitive field: %s",
-                                               PrettyField(f).c_str()).c_str());
+                                               PrettyField(f->GetArtField()).c_str()).c_str());
     return;
   }
 
@@ -342,7 +358,7 @@
   }
 
   // If field is not set to be accessible, verify it can be accessed by the caller.
-  if ((accessible == JNI_FALSE) && !VerifyFieldAccess<true>(soa.Self(), f, o)) {
+  if (!f->IsAccessible() && !VerifyFieldAccess<true>(soa.Self(), f, o)) {
     DCHECK(soa.Self()->IsExceptionPending());
     return;
   }
@@ -351,81 +367,73 @@
   SetFieldValue(o, f, field_type, false, wide_value);
 }
 
-static void Field_setBoolean(JNIEnv* env, jobject javaField, jobject javaObj, jboolean z,
-                             jboolean accessible) {
+static void Field_setBoolean(JNIEnv* env, jobject javaField, jobject javaObj, jboolean z) {
   JValue value;
   value.SetZ(z);
-  SetPrimitiveField<Primitive::kPrimBoolean>(env, javaField, javaObj, value, accessible);
+  SetPrimitiveField<Primitive::kPrimBoolean>(env, javaField, javaObj, value);
 }
 
-static void Field_setByte(JNIEnv* env, jobject javaField, jobject javaObj, jbyte b,
-                          jboolean accessible) {
+static void Field_setByte(JNIEnv* env, jobject javaField, jobject javaObj, jbyte b) {
   JValue value;
   value.SetB(b);
-  SetPrimitiveField<Primitive::kPrimByte>(env, javaField, javaObj, value, accessible);
+  SetPrimitiveField<Primitive::kPrimByte>(env, javaField, javaObj, value);
 }
 
-static void Field_setChar(JNIEnv* env, jobject javaField, jobject javaObj, jchar c,
-                          jboolean accessible) {
+static void Field_setChar(JNIEnv* env, jobject javaField, jobject javaObj, jchar c) {
   JValue value;
   value.SetC(c);
-  SetPrimitiveField<Primitive::kPrimChar>(env, javaField, javaObj, value, accessible);
+  SetPrimitiveField<Primitive::kPrimChar>(env, javaField, javaObj, value);
 }
 
-static void Field_setDouble(JNIEnv* env, jobject javaField, jobject javaObj, jdouble d,
-                            jboolean accessible) {
+static void Field_setDouble(JNIEnv* env, jobject javaField, jobject javaObj, jdouble d) {
   JValue value;
   value.SetD(d);
-  SetPrimitiveField<Primitive::kPrimDouble>(env, javaField, javaObj, value, accessible);
+  SetPrimitiveField<Primitive::kPrimDouble>(env, javaField, javaObj, value);
 }
 
-static void Field_setFloat(JNIEnv* env, jobject javaField, jobject javaObj, jfloat f,
-                           jboolean accessible) {
+static void Field_setFloat(JNIEnv* env, jobject javaField, jobject javaObj, jfloat f) {
   JValue value;
   value.SetF(f);
-  SetPrimitiveField<Primitive::kPrimFloat>(env, javaField, javaObj, value, accessible);
+  SetPrimitiveField<Primitive::kPrimFloat>(env, javaField, javaObj, value);
 }
 
-static void Field_setInt(JNIEnv* env, jobject javaField, jobject javaObj, jint i,
-                         jboolean accessible) {
+static void Field_setInt(JNIEnv* env, jobject javaField, jobject javaObj, jint i) {
   JValue value;
   value.SetI(i);
-  SetPrimitiveField<Primitive::kPrimInt>(env, javaField, javaObj, value, accessible);
+  SetPrimitiveField<Primitive::kPrimInt>(env, javaField, javaObj, value);
 }
 
-static void Field_setLong(JNIEnv* env, jobject javaField, jobject javaObj, jlong j,
-                          jboolean accessible) {
+static void Field_setLong(JNIEnv* env, jobject javaField, jobject javaObj, jlong j) {
   JValue value;
   value.SetJ(j);
-  SetPrimitiveField<Primitive::kPrimLong>(env, javaField, javaObj, value, accessible);
+  SetPrimitiveField<Primitive::kPrimLong>(env, javaField, javaObj, value);
 }
 
-static void Field_setShort(JNIEnv* env, jobject javaField, jobject javaObj, jshort s,
-                           jboolean accessible) {
+static void Field_setShort(JNIEnv* env, jobject javaField, jobject javaObj, jshort s) {
   JValue value;
   value.SetS(s);
-  SetPrimitiveField<Primitive::kPrimShort>(env, javaField, javaObj, value, accessible);
+  SetPrimitiveField<Primitive::kPrimShort>(env, javaField, javaObj, value);
 }
 
 static JNINativeMethod gMethods[] = {
-  NATIVE_METHOD(Field, get,        "!(Ljava/lang/Object;Z)Ljava/lang/Object;"),
-  NATIVE_METHOD(Field, getBoolean, "!(Ljava/lang/Object;Z)Z"),
-  NATIVE_METHOD(Field, getByte,    "!(Ljava/lang/Object;Z)B"),
-  NATIVE_METHOD(Field, getChar,    "!(Ljava/lang/Object;Z)C"),
-  NATIVE_METHOD(Field, getDouble,  "!(Ljava/lang/Object;Z)D"),
-  NATIVE_METHOD(Field, getFloat,   "!(Ljava/lang/Object;Z)F"),
-  NATIVE_METHOD(Field, getInt,     "!(Ljava/lang/Object;Z)I"),
-  NATIVE_METHOD(Field, getLong,    "!(Ljava/lang/Object;Z)J"),
-  NATIVE_METHOD(Field, getShort,   "!(Ljava/lang/Object;Z)S"),
-  NATIVE_METHOD(Field, set,        "!(Ljava/lang/Object;Ljava/lang/Object;Z)V"),
-  NATIVE_METHOD(Field, setBoolean, "!(Ljava/lang/Object;ZZ)V"),
-  NATIVE_METHOD(Field, setByte,    "!(Ljava/lang/Object;BZ)V"),
-  NATIVE_METHOD(Field, setChar,    "!(Ljava/lang/Object;CZ)V"),
-  NATIVE_METHOD(Field, setDouble,  "!(Ljava/lang/Object;DZ)V"),
-  NATIVE_METHOD(Field, setFloat,   "!(Ljava/lang/Object;FZ)V"),
-  NATIVE_METHOD(Field, setInt,     "!(Ljava/lang/Object;IZ)V"),
-  NATIVE_METHOD(Field, setLong,    "!(Ljava/lang/Object;JZ)V"),
-  NATIVE_METHOD(Field, setShort,   "!(Ljava/lang/Object;SZ)V"),
+  NATIVE_METHOD(Field, get,        "!(Ljava/lang/Object;)Ljava/lang/Object;"),
+  NATIVE_METHOD(Field, getBoolean, "!(Ljava/lang/Object;)Z"),
+  NATIVE_METHOD(Field, getByte,    "!(Ljava/lang/Object;)B"),
+  NATIVE_METHOD(Field, getChar,    "!(Ljava/lang/Object;)C"),
+  NATIVE_METHOD(Field, getDouble,  "!(Ljava/lang/Object;)D"),
+  NATIVE_METHOD(Field, getFloat,   "!(Ljava/lang/Object;)F"),
+  NATIVE_METHOD(Field, getInt,     "!(Ljava/lang/Object;)I"),
+  NATIVE_METHOD(Field, getLong,    "!(Ljava/lang/Object;)J"),
+  NATIVE_METHOD(Field, getShort,   "!(Ljava/lang/Object;)S"),
+  NATIVE_METHOD(Field, set,        "!(Ljava/lang/Object;Ljava/lang/Object;)V"),
+  NATIVE_METHOD(Field, setBoolean, "!(Ljava/lang/Object;Z)V"),
+  NATIVE_METHOD(Field, setByte,    "!(Ljava/lang/Object;B)V"),
+  NATIVE_METHOD(Field, setChar,    "!(Ljava/lang/Object;C)V"),
+  NATIVE_METHOD(Field, setDouble,  "!(Ljava/lang/Object;D)V"),
+  NATIVE_METHOD(Field, setFloat,   "!(Ljava/lang/Object;F)V"),
+  NATIVE_METHOD(Field, setInt,     "!(Ljava/lang/Object;I)V"),
+  NATIVE_METHOD(Field, setLong,    "!(Ljava/lang/Object;J)V"),
+  NATIVE_METHOD(Field, setShort,   "!(Ljava/lang/Object;S)V"),
 };
 
 void register_java_lang_reflect_Field(JNIEnv* env) {
diff --git a/runtime/noop_compiler_callbacks.h b/runtime/noop_compiler_callbacks.h
index 300abc9..1cbf2bb 100644
--- a/runtime/noop_compiler_callbacks.h
+++ b/runtime/noop_compiler_callbacks.h
@@ -23,7 +23,7 @@
 
 class NoopCompilerCallbacks FINAL : public CompilerCallbacks {
  public:
-  NoopCompilerCallbacks() {}
+  NoopCompilerCallbacks() : CompilerCallbacks(CompilerCallbacks::CallbackMode::kCompileApp) {}
   ~NoopCompilerCallbacks() {}
 
   bool MethodVerified(verifier::MethodVerifier* verifier ATTRIBUTE_UNUSED) OVERRIDE {
diff --git a/runtime/oat_file_assistant_test.cc b/runtime/oat_file_assistant_test.cc
index b2798d3..a8b0876 100644
--- a/runtime/oat_file_assistant_test.cc
+++ b/runtime/oat_file_assistant_test.cc
@@ -27,6 +27,7 @@
 
 #include "class_linker.h"
 #include "common_runtime_test.h"
+#include "compiler_callbacks.h"
 #include "mem_map.h"
 #include "os.h"
 #include "thread-inl.h"
@@ -77,11 +78,7 @@
           nullptr));
     // Make sure compilercallbacks are not set so that relocation will be
     // enabled.
-    for (std::pair<std::string, const void*>& pair : *options) {
-      if (pair.first == "compilercallbacks") {
-        pair.second = nullptr;
-      }
-    }
+    callbacks_.reset();
   }
 
   virtual void PreRuntimeCreate() {
@@ -213,29 +210,29 @@
         // image in case of the GSS collector.
         + 384 * MB;
 
-    std::string error_msg;
     std::unique_ptr<BacktraceMap> map(BacktraceMap::Create(getpid(), true));
     ASSERT_TRUE(map.get() != nullptr) << "Failed to build process map";
     for (BacktraceMap::const_iterator it = map->begin();
         reservation_start < reservation_end && it != map->end(); ++it) {
-      if (it->end <= reservation_start) {
-        continue;
-      }
+      ReserveImageSpaceChunk(reservation_start, std::min(it->start, reservation_end));
+      reservation_start = std::max(reservation_start, it->end);
+    }
+    ReserveImageSpaceChunk(reservation_start, reservation_end);
+  }
 
-      if (it->start < reservation_start) {
-        reservation_start = std::min(reservation_end, it->end);
-      }
-
+  // Reserve a chunk of memory for the image space in the given range.
+  // Only has effect for chunks with a positive number of bytes.
+  void ReserveImageSpaceChunk(uintptr_t start, uintptr_t end) {
+    if (start < end) {
+      std::string error_msg;
       image_reservation_.push_back(std::unique_ptr<MemMap>(
           MemMap::MapAnonymous("image reservation",
-              reinterpret_cast<uint8_t*>(reservation_start),
-              std::min(it->start, reservation_end) - reservation_start,
+              reinterpret_cast<uint8_t*>(start), end - start,
               PROT_NONE, false, false, &error_msg)));
       ASSERT_TRUE(image_reservation_.back().get() != nullptr) << error_msg;
       LOG(INFO) << "Reserved space for image " <<
         reinterpret_cast<void*>(image_reservation_.back()->Begin()) << "-" <<
         reinterpret_cast<void*>(image_reservation_.back()->End());
-      reservation_start = it->end;
     }
   }
 
diff --git a/runtime/proxy_test.cc b/runtime/proxy_test.cc
index 3260992..cb97049 100644
--- a/runtime/proxy_test.cc
+++ b/runtime/proxy_test.cc
@@ -185,7 +185,7 @@
   MutableHandle<mirror::ArtField> fhandle = hs.NewHandle(static_fields->Get(0));
   EXPECT_EQ("interfaces", std::string(fhandle->GetName()));
   EXPECT_EQ("[Ljava/lang/Class;", std::string(fhandle->GetTypeDescriptor()));
-  EXPECT_EQ(interfacesFieldClass.Get(), fhandle->GetType(true));
+  EXPECT_EQ(interfacesFieldClass.Get(), fhandle->GetType<true>());
   std::string temp;
   EXPECT_EQ("L$Proxy1234;", std::string(fhandle->GetDeclaringClass()->GetDescriptor(&temp)));
   EXPECT_FALSE(fhandle->IsPrimitiveType());
@@ -194,7 +194,7 @@
   fhandle.Assign(static_fields->Get(1));
   EXPECT_EQ("throws", std::string(fhandle->GetName()));
   EXPECT_EQ("[[Ljava/lang/Class;", std::string(fhandle->GetTypeDescriptor()));
-  EXPECT_EQ(throwsFieldClass.Get(), fhandle->GetType(true));
+  EXPECT_EQ(throwsFieldClass.Get(), fhandle->GetType<true>());
   EXPECT_EQ("L$Proxy1234;", std::string(fhandle->GetDeclaringClass()->GetDescriptor(&temp)));
   EXPECT_FALSE(fhandle->IsPrimitiveType());
 }
diff --git a/runtime/reflection-inl.h b/runtime/reflection-inl.h
index f21c1a0..f54d4ca 100644
--- a/runtime/reflection-inl.h
+++ b/runtime/reflection-inl.h
@@ -22,6 +22,7 @@
 #include "base/stringprintf.h"
 #include "common_throws.h"
 #include "jvalue.h"
+#include "mirror/object-inl.h"
 #include "primitive.h"
 #include "utils.h"
 
@@ -99,6 +100,17 @@
   return false;
 }
 
+inline bool VerifyObjectIsClass(mirror::Object* o, mirror::Class* c) {
+  if (UNLIKELY(o == nullptr)) {
+    ThrowNullPointerException("null receiver");
+    return false;
+  } else if (UNLIKELY(!o->InstanceOf(c))) {
+    InvalidReceiverError(o, c);
+    return false;
+  }
+  return true;
+}
+
 }  // namespace art
 
 #endif  // ART_RUNTIME_REFLECTION_INL_H_
diff --git a/runtime/reflection.cc b/runtime/reflection.cc
index a54a39d..4e94de4 100644
--- a/runtime/reflection.cc
+++ b/runtime/reflection.cc
@@ -24,7 +24,6 @@
 #include "mirror/art_field-inl.h"
 #include "mirror/art_method-inl.h"
 #include "mirror/class-inl.h"
-#include "mirror/class.h"
 #include "mirror/object_array-inl.h"
 #include "mirror/object_array.h"
 #include "nth_caller_visitor.h"
@@ -588,7 +587,7 @@
   // If method is not set to be accessible, verify it can be accessed by the caller.
   mirror::Class* calling_class = nullptr;
   if (!accessible && !VerifyAccess(soa.Self(), receiver, declaring_class, m->GetAccessFlags(),
-                                   &calling_class)) {
+                                   &calling_class, 2)) {
     ThrowIllegalAccessException(
         StringPrintf("Class %s cannot access %s method %s of class %s",
             calling_class == nullptr ? "null" : PrettyClass(calling_class).c_str(),
@@ -628,21 +627,6 @@
   return soa.AddLocalReference<jobject>(BoxPrimitive(Primitive::GetType(shorty[0]), result));
 }
 
-bool VerifyObjectIsClass(mirror::Object* o, mirror::Class* c) {
-  if (o == nullptr) {
-    ThrowNullPointerException("null receiver");
-    return false;
-  } else if (!o->InstanceOf(c)) {
-    std::string expected_class_name(PrettyDescriptor(c));
-    std::string actual_class_name(PrettyTypeOf(o));
-    ThrowIllegalArgumentException(StringPrintf("Expected receiver of type %s, but got %s",
-                                               expected_class_name.c_str(),
-                                               actual_class_name.c_str()).c_str());
-    return false;
-  }
-  return true;
-}
-
 mirror::Object* BoxPrimitive(Primitive::Type src_class, const JValue& value) {
   if (src_class == Primitive::kPrimNot) {
     return value.GetL();
@@ -810,11 +794,11 @@
 }
 
 bool VerifyAccess(Thread* self, mirror::Object* obj, mirror::Class* declaring_class,
-                  uint32_t access_flags, mirror::Class** calling_class) {
+                  uint32_t access_flags, mirror::Class** calling_class, size_t num_frames) {
   if ((access_flags & kAccPublic) != 0) {
     return true;
   }
-  NthCallerVisitor visitor(self, 2);
+  NthCallerVisitor visitor(self, num_frames);
   visitor.WalkStack();
   if (UNLIKELY(visitor.caller == nullptr)) {
     // The caller is an attached native thread.
@@ -840,4 +824,12 @@
   return declaring_class->IsInSamePackage(caller_class);
 }
 
+void InvalidReceiverError(mirror::Object* o, mirror::Class* c) {
+  std::string expected_class_name(PrettyDescriptor(c));
+  std::string actual_class_name(PrettyTypeOf(o));
+  ThrowIllegalArgumentException(StringPrintf("Expected receiver of type %s, but got %s",
+                                             expected_class_name.c_str(),
+                                             actual_class_name.c_str()).c_str());
+}
+
 }  // namespace art
diff --git a/runtime/reflection.h b/runtime/reflection.h
index 857d63b..ff970e5 100644
--- a/runtime/reflection.h
+++ b/runtime/reflection.h
@@ -69,11 +69,14 @@
                      jobject args, bool accessible)
     SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
 
-bool VerifyObjectIsClass(mirror::Object* o, mirror::Class* c)
+ALWAYS_INLINE bool VerifyObjectIsClass(mirror::Object* o, mirror::Class* c)
     SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
 
 bool VerifyAccess(Thread* self, mirror::Object* obj, mirror::Class* declaring_class,
-                  uint32_t access_flags, mirror::Class** calling_class)
+                  uint32_t access_flags, mirror::Class** calling_class, size_t num_frames)
+    SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
+
+void InvalidReceiverError(mirror::Object* o, mirror::Class* c)
     SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
 
 }  // namespace art
diff --git a/runtime/runtime.cc b/runtime/runtime.cc
index 9ca00b1..23a7db6 100644
--- a/runtime/runtime.cc
+++ b/runtime/runtime.cc
@@ -50,9 +50,11 @@
 #include "arch/x86_64/registers_x86_64.h"
 #include "asm_support.h"
 #include "atomic.h"
+#include "base/arena_allocator.h"
 #include "base/dumpable.h"
 #include "base/unix_file/fd_file.h"
 #include "class_linker.h"
+#include "compiler_callbacks.h"
 #include "debugger.h"
 #include "elf_file.h"
 #include "entrypoints/runtime_asm_entrypoints.h"
@@ -73,6 +75,7 @@
 #include "mirror/art_method-inl.h"
 #include "mirror/class-inl.h"
 #include "mirror/class_loader.h"
+#include "mirror/field.h"
 #include "mirror/stack_trace_element.h"
 #include "mirror/throwable.h"
 #include "monitor.h"
@@ -163,7 +166,6 @@
       method_trace_(false),
       method_trace_file_size_(0),
       instrumentation_(),
-      use_compile_time_class_path_(false),
       main_thread_group_(nullptr),
       system_thread_group_(nullptr),
       system_class_loader_(nullptr),
@@ -405,9 +407,9 @@
   return true;
 }
 
-static jobject CreateSystemClassLoader() {
-  if (Runtime::Current()->UseCompileTimeClassPath()) {
-    return NULL;
+static jobject CreateSystemClassLoader(Runtime* runtime) {
+  if (runtime->IsAotCompiler() && !runtime->GetCompilerCallbacks()->IsBootImage()) {
+    return nullptr;
   }
 
   ScopedObjectAccess soa(Thread::Current());
@@ -505,7 +507,7 @@
 
   Thread::FinishStartup();
 
-  system_class_loader_ = CreateSystemClassLoader();
+  system_class_loader_ = CreateSystemClassLoader(this);
 
   if (is_zygote_) {
     if (!InitZygote()) {
@@ -1011,8 +1013,8 @@
                  -1,
                  static_cast<int>(method_trace_file_size_),
                  0,
-                 false,
-                 false,
+                 Trace::TraceOutputMode::kFile,
+                 Trace::TraceMode::kMethodTracing,
                  0);
   }
 
@@ -1290,6 +1292,7 @@
   mirror::StackTraceElement::VisitRoots(callback, arg);
   mirror::String::VisitRoots(callback, arg);
   mirror::Throwable::VisitRoots(callback, arg);
+  mirror::Field::VisitRoots(callback, arg);
   // Visit all the primitive array types classes.
   mirror::PrimitiveArray<uint8_t>::VisitRoots(callback, arg);   // BooleanArray
   mirror::PrimitiveArray<int8_t>::VisitRoots(callback, arg);    // ByteArray
@@ -1483,23 +1486,6 @@
   callee_save_methods_[type] = GcRoot<mirror::ArtMethod>(method);
 }
 
-const std::vector<const DexFile*>& Runtime::GetCompileTimeClassPath(jobject class_loader) {
-  if (class_loader == NULL) {
-    return GetClassLinker()->GetBootClassPath();
-  }
-  CHECK(UseCompileTimeClassPath());
-  CompileTimeClassPaths::const_iterator it = compile_time_class_paths_.find(class_loader);
-  CHECK(it != compile_time_class_paths_.end());
-  return it->second;
-}
-
-void Runtime::SetCompileTimeClassPath(jobject class_loader,
-                                      std::vector<const DexFile*>& class_path) {
-  CHECK(!IsStarted());
-  use_compile_time_class_path_ = true;
-  compile_time_class_paths_.Put(class_loader, class_path);
-}
-
 void Runtime::StartProfiler(const char* profile_output_filename) {
   profile_output_filename_ = profile_output_filename;
   profiler_started_ =
@@ -1671,4 +1657,12 @@
   }
 }
 
+bool Runtime::CanRelocate() const {
+  return !IsAotCompiler() || compiler_callbacks_->IsRelocationPossible();
+}
+
+bool Runtime::IsCompilingBootImage() const {
+  return IsCompiler() && compiler_callbacks_->IsBootImage();
+}
+
 }  // namespace art
diff --git a/runtime/runtime.h b/runtime/runtime.h
index 9a04835..085335f 100644
--- a/runtime/runtime.h
+++ b/runtime/runtime.h
@@ -27,10 +27,7 @@
 #include <vector>
 
 #include "arch/instruction_set.h"
-#include "base/allocator.h"
-#include "base/arena_allocator.h"
 #include "base/macros.h"
-#include "compiler_callbacks.h"
 #include "gc_root.h"
 #include "instrumentation.h"
 #include "jobject_comparator.h"
@@ -43,6 +40,9 @@
 
 namespace art {
 
+class ArenaPool;
+class CompilerCallbacks;
+
 namespace gc {
   class Heap;
   namespace collector {
@@ -112,9 +112,10 @@
     return compiler_callbacks_ != nullptr;
   }
 
-  bool CanRelocate() const {
-    return !IsAotCompiler() || compiler_callbacks_->IsRelocationPossible();
-  }
+  // If a compiler, are we compiling a boot image?
+  bool IsCompilingBootImage() const;
+
+  bool CanRelocate() const;
 
   bool ShouldRelocate() const {
     return must_relocate_ && CanRelocate();
@@ -452,16 +453,6 @@
     return &instrumentation_;
   }
 
-  bool UseCompileTimeClassPath() const {
-    return use_compile_time_class_path_;
-  }
-
-  const std::vector<const DexFile*>& GetCompileTimeClassPath(jobject class_loader);
-
-  // The caller is responsible for ensuring the class_path DexFiles remain
-  // valid as long as the Runtime object remains valid.
-  void SetCompileTimeClassPath(jobject class_loader, std::vector<const DexFile*>& class_path);
-
   void StartProfiler(const char* profile_output_filename);
   void UpdateProfilerState(int state);
 
@@ -685,12 +676,6 @@
   size_t method_trace_file_size_;
   instrumentation::Instrumentation instrumentation_;
 
-  typedef AllocationTrackingSafeMap<jobject, std::vector<const DexFile*>,
-                                    kAllocatorTagCompileTimeClassPath, JobjectComparator>
-      CompileTimeClassPaths;
-  CompileTimeClassPaths compile_time_class_paths_;
-  bool use_compile_time_class_path_;
-
   jobject main_thread_group_;
   jobject system_thread_group_;
 
diff --git a/runtime/stack.cc b/runtime/stack.cc
index 2d688ee..4ae49dd 100644
--- a/runtime/stack.cc
+++ b/runtime/stack.cc
@@ -206,21 +206,22 @@
   DexRegisterMap dex_register_map =
       code_info.GetDexRegisterMapOf(stack_map, number_of_dex_registers);
   DexRegisterLocation::Kind location_kind =
-      dex_register_map.GetLocationKind(vreg, number_of_dex_registers);
+      dex_register_map.GetLocationKind(vreg, number_of_dex_registers, code_info);
   switch (location_kind) {
     case DexRegisterLocation::Kind::kInStack: {
-      const int32_t offset = dex_register_map.GetStackOffsetInBytes(vreg, number_of_dex_registers);
+      const int32_t offset =
+          dex_register_map.GetStackOffsetInBytes(vreg, number_of_dex_registers, code_info);
       const uint8_t* addr = reinterpret_cast<const uint8_t*>(cur_quick_frame_) + offset;
       *val = *reinterpret_cast<const uint32_t*>(addr);
       return true;
     }
     case DexRegisterLocation::Kind::kInRegister:
     case DexRegisterLocation::Kind::kInFpuRegister: {
-      uint32_t reg = dex_register_map.GetMachineRegister(vreg, number_of_dex_registers);
+      uint32_t reg = dex_register_map.GetMachineRegister(vreg, number_of_dex_registers, code_info);
       return GetRegisterIfAccessible(reg, kind, val);
     }
     case DexRegisterLocation::Kind::kConstant:
-      *val = dex_register_map.GetConstant(vreg, number_of_dex_registers);
+      *val = dex_register_map.GetConstant(vreg, number_of_dex_registers, code_info);
       return true;
     case DexRegisterLocation::Kind::kNone:
       return false;
@@ -228,7 +229,7 @@
       LOG(FATAL)
           << "Unexpected location kind"
           << DexRegisterLocation::PrettyDescriptor(
-                dex_register_map.GetLocationInternalKind(vreg, number_of_dex_registers));
+                dex_register_map.GetLocationInternalKind(vreg, number_of_dex_registers, code_info));
       UNREACHABLE();
   }
 }
@@ -396,18 +397,19 @@
   DexRegisterMap dex_register_map =
       code_info.GetDexRegisterMapOf(stack_map, number_of_dex_registers);
   DexRegisterLocation::Kind location_kind =
-      dex_register_map.GetLocationKind(vreg, number_of_dex_registers);
+      dex_register_map.GetLocationKind(vreg, number_of_dex_registers, code_info);
   uint32_t dex_pc = m->ToDexPc(cur_quick_frame_pc_, false);
   switch (location_kind) {
     case DexRegisterLocation::Kind::kInStack: {
-      const int32_t offset = dex_register_map.GetStackOffsetInBytes(vreg, number_of_dex_registers);
+      const int32_t offset =
+          dex_register_map.GetStackOffsetInBytes(vreg, number_of_dex_registers, code_info);
       uint8_t* addr = reinterpret_cast<uint8_t*>(cur_quick_frame_) + offset;
       *reinterpret_cast<uint32_t*>(addr) = new_value;
       return true;
     }
     case DexRegisterLocation::Kind::kInRegister:
     case DexRegisterLocation::Kind::kInFpuRegister: {
-      uint32_t reg = dex_register_map.GetMachineRegister(vreg, number_of_dex_registers);
+      uint32_t reg = dex_register_map.GetMachineRegister(vreg, number_of_dex_registers, code_info);
       return SetRegisterIfAccessible(reg, new_value, kind);
     }
     case DexRegisterLocation::Kind::kConstant:
diff --git a/runtime/stack_map.cc b/runtime/stack_map.cc
index 020a6e6..11e7e44 100644
--- a/runtime/stack_map.cc
+++ b/runtime/stack_map.cc
@@ -16,133 +16,198 @@
 
 #include "stack_map.h"
 
+#include <stdint.h>
+
 namespace art {
 
-constexpr uint32_t StackMap::kNoDexRegisterMapSmallEncoding;
-constexpr uint32_t StackMap::kNoInlineInfoSmallEncoding;
+constexpr size_t DexRegisterLocationCatalog::kNoLocationEntryIndex;
 constexpr uint32_t StackMap::kNoDexRegisterMap;
 constexpr uint32_t StackMap::kNoInlineInfo;
 
-uint32_t StackMap::GetDexPc(const CodeInfo& info) const {
-  return info.HasSmallDexPc()
-      ? region_.LoadUnaligned<kSmallEncoding>(info.ComputeStackMapDexPcOffset())
-      : region_.LoadUnaligned<kLargeEncoding>(info.ComputeStackMapDexPcOffset());
+DexRegisterLocation::Kind DexRegisterMap::GetLocationInternalKind(uint16_t dex_register_number,
+                                                                  uint16_t number_of_dex_registers,
+                                                                  const CodeInfo& code_info) const {
+  DexRegisterLocationCatalog dex_register_location_catalog =
+      code_info.GetDexRegisterLocationCatalog();
+  size_t location_catalog_entry_index = GetLocationCatalogEntryIndex(
+      dex_register_number,
+      number_of_dex_registers,
+      code_info.GetNumberOfDexRegisterLocationCatalogEntries());
+  return dex_register_location_catalog.GetLocationInternalKind(location_catalog_entry_index);
 }
 
-void StackMap::SetDexPc(const CodeInfo& info, uint32_t dex_pc) {
-  DCHECK(!info.HasSmallDexPc() || IsUint<kBitsForSmallEncoding>(dex_pc)) << dex_pc;
-  info.HasSmallDexPc()
-      ? region_.StoreUnaligned<kSmallEncoding>(info.ComputeStackMapDexPcOffset(), dex_pc)
-      : region_.StoreUnaligned<kLargeEncoding>(info.ComputeStackMapDexPcOffset(), dex_pc);
+DexRegisterLocation DexRegisterMap::GetDexRegisterLocation(uint16_t dex_register_number,
+                                                           uint16_t number_of_dex_registers,
+                                                           const CodeInfo& code_info) const {
+  DexRegisterLocationCatalog dex_register_location_catalog =
+      code_info.GetDexRegisterLocationCatalog();
+  size_t location_catalog_entry_index = GetLocationCatalogEntryIndex(
+      dex_register_number,
+      number_of_dex_registers,
+      code_info.GetNumberOfDexRegisterLocationCatalogEntries());
+  return dex_register_location_catalog.GetDexRegisterLocation(location_catalog_entry_index);
 }
 
-uint32_t StackMap::GetNativePcOffset(const CodeInfo& info) const {
-  return info.HasSmallNativePc()
-      ? region_.LoadUnaligned<kSmallEncoding>(info.ComputeStackMapNativePcOffset())
-      : region_.LoadUnaligned<kLargeEncoding>(info.ComputeStackMapNativePcOffset());
-}
-
-void StackMap::SetNativePcOffset(const CodeInfo& info, uint32_t native_pc_offset) {
-  DCHECK(!info.HasSmallNativePc()
-         || IsUint<kBitsForSmallEncoding>(native_pc_offset)) << native_pc_offset;
-  uint32_t entry = info.ComputeStackMapNativePcOffset();
-  info.HasSmallNativePc()
-      ? region_.StoreUnaligned<kSmallEncoding>(entry, native_pc_offset)
-      : region_.StoreUnaligned<kLargeEncoding>(entry, native_pc_offset);
-}
-
-uint32_t StackMap::GetDexRegisterMapOffset(const CodeInfo& info) const {
-  if (info.HasSmallDexRegisterMap()) {
-    uint8_t value = region_.LoadUnaligned<kSmallEncoding>(
-        info.ComputeStackMapDexRegisterMapOffset());
-    if (value == kNoDexRegisterMapSmallEncoding) {
-      return kNoDexRegisterMap;
+// Loads `number_of_bytes` at the given `offset` and assemble a uint32_t. If `check_max` is true,
+// this method converts a maximum value of size `number_of_bytes` into a uint32_t 0xFFFFFFFF.
+static uint32_t LoadAt(MemoryRegion region,
+                       size_t number_of_bytes,
+                       size_t offset,
+                       bool check_max = false) {
+  if (number_of_bytes == 0u) {
+    DCHECK(!check_max);
+    return 0;
+  } else if (number_of_bytes == 1u) {
+    uint8_t value = region.LoadUnaligned<uint8_t>(offset);
+    if (check_max && value == 0xFF) {
+      return -1;
+    } else {
+      return value;
+    }
+  } else if (number_of_bytes == 2u) {
+    uint16_t value = region.LoadUnaligned<uint16_t>(offset);
+    if (check_max && value == 0xFFFF) {
+      return -1;
+    } else {
+      return value;
+    }
+  } else if (number_of_bytes == 3u) {
+    uint16_t low = region.LoadUnaligned<uint16_t>(offset);
+    uint16_t high = region.LoadUnaligned<uint8_t>(offset + sizeof(uint16_t));
+    uint32_t value = (high << 16) + low;
+    if (check_max && value == 0xFFFFFF) {
+      return -1;
     } else {
       return value;
     }
   } else {
-    return region_.LoadUnaligned<kLargeEncoding>(info.ComputeStackMapDexRegisterMapOffset());
+    DCHECK_EQ(number_of_bytes, 4u);
+    return region.LoadUnaligned<uint32_t>(offset);
   }
 }
 
+static void StoreAt(MemoryRegion region, size_t number_of_bytes, size_t offset, uint32_t value) {
+  if (number_of_bytes == 0u) {
+    DCHECK_EQ(value, 0u);
+  } else if (number_of_bytes == 1u) {
+    region.StoreUnaligned<uint8_t>(offset, value);
+  } else if (number_of_bytes == 2u) {
+    region.StoreUnaligned<uint16_t>(offset, value);
+  } else if (number_of_bytes == 3u) {
+    region.StoreUnaligned<uint16_t>(offset, Low16Bits(value));
+    region.StoreUnaligned<uint8_t>(offset + sizeof(uint16_t), High16Bits(value));
+  } else {
+    region.StoreUnaligned<uint32_t>(offset, value);
+    DCHECK_EQ(number_of_bytes, 4u);
+  }
+}
+
+uint32_t StackMap::GetDexPc(const CodeInfo& info) const {
+  return LoadAt(region_, info.NumberOfBytesForDexPc(), info.ComputeStackMapDexPcOffset());
+}
+
+void StackMap::SetDexPc(const CodeInfo& info, uint32_t dex_pc) {
+  StoreAt(region_, info.NumberOfBytesForDexPc(), info.ComputeStackMapDexPcOffset(), dex_pc);
+}
+
+uint32_t StackMap::GetNativePcOffset(const CodeInfo& info) const {
+  return LoadAt(region_, info.NumberOfBytesForNativePc(), info.ComputeStackMapNativePcOffset());
+}
+
+void StackMap::SetNativePcOffset(const CodeInfo& info, uint32_t native_pc_offset) {
+  StoreAt(region_, info.NumberOfBytesForNativePc(), info.ComputeStackMapNativePcOffset(), native_pc_offset);
+}
+
+uint32_t StackMap::GetDexRegisterMapOffset(const CodeInfo& info) const {
+  return LoadAt(region_,
+                info.NumberOfBytesForDexRegisterMap(),
+                info.ComputeStackMapDexRegisterMapOffset(),
+                /* check_max */ true);
+}
+
 void StackMap::SetDexRegisterMapOffset(const CodeInfo& info, uint32_t offset) {
-  DCHECK(!info.HasSmallDexRegisterMap()
-         || (IsUint<kBitsForSmallEncoding>(offset)
-             || (offset == kNoDexRegisterMap))) << offset;
-  size_t dex_register_map_entry = info.ComputeStackMapDexRegisterMapOffset();
-  info.HasSmallDexRegisterMap()
-      ? region_.StoreUnaligned<kSmallEncoding>(dex_register_map_entry, offset)
-      : region_.StoreUnaligned<kLargeEncoding>(dex_register_map_entry, offset);
+  StoreAt(region_,
+          info.NumberOfBytesForDexRegisterMap(),
+          info.ComputeStackMapDexRegisterMapOffset(),
+          offset);
 }
 
 uint32_t StackMap::GetInlineDescriptorOffset(const CodeInfo& info) const {
   if (!info.HasInlineInfo()) return kNoInlineInfo;
-  if (info.HasSmallInlineInfo()) {
-    uint8_t value = region_.LoadUnaligned<kSmallEncoding>(
-        info.ComputeStackMapInlineInfoOffset());
-    if (value == kNoInlineInfoSmallEncoding) {
-      return kNoInlineInfo;
-    } else {
-      return value;
-    }
-  } else {
-    return region_.LoadUnaligned<kLargeEncoding>(info.ComputeStackMapInlineInfoOffset());
-  }
+  return LoadAt(region_,
+                info.NumberOfBytesForInlineInfo(),
+                info.ComputeStackMapInlineInfoOffset(),
+                /* check_max */ true);
 }
 
 void StackMap::SetInlineDescriptorOffset(const CodeInfo& info, uint32_t offset) {
   DCHECK(info.HasInlineInfo());
-  DCHECK(!info.HasSmallInlineInfo()
-         || (IsUint<kBitsForSmallEncoding>(offset)
-             || (offset == kNoInlineInfo))) << offset;
-  size_t inline_entry = info.ComputeStackMapInlineInfoOffset();
-  info.HasSmallInlineInfo()
-      ? region_.StoreUnaligned<kSmallEncoding>(inline_entry, offset)
-      : region_.StoreUnaligned<kLargeEncoding>(inline_entry, offset);
+  StoreAt(region_,
+          info.NumberOfBytesForInlineInfo(),
+          info.ComputeStackMapInlineInfoOffset(),
+          offset);
 }
 
 uint32_t StackMap::GetRegisterMask(const CodeInfo& info) const {
-  return region_.LoadUnaligned<kLargeEncoding>(info.ComputeStackMapRegisterMaskOffset());
+  return LoadAt(region_,
+                info.NumberOfBytesForRegisterMask(),
+                info.ComputeStackMapRegisterMaskOffset());
 }
 
 void StackMap::SetRegisterMask(const CodeInfo& info, uint32_t mask) {
-  region_.StoreUnaligned<kLargeEncoding>(info.ComputeStackMapRegisterMaskOffset(), mask);
+  StoreAt(region_,
+          info.NumberOfBytesForRegisterMask(),
+          info.ComputeStackMapRegisterMaskOffset(),
+          mask);
 }
 
-size_t StackMap::ComputeStackMapSize(size_t stack_mask_size,
-                                     bool has_inline_info,
-                                     bool is_small_inline_info,
-                                     bool is_small_dex_map,
-                                     bool is_small_dex_pc,
-                                     bool is_small_native_pc) {
-  return StackMap::kFixedSize
-      + stack_mask_size
-      + (has_inline_info ? NumberOfBytesForEntry(is_small_inline_info) : 0)
-      + NumberOfBytesForEntry(is_small_dex_map)
-      + NumberOfBytesForEntry(is_small_dex_pc)
-      + NumberOfBytesForEntry(is_small_native_pc);
+size_t StackMap::ComputeStackMapSizeInternal(size_t stack_mask_size,
+                                             size_t number_of_bytes_for_inline_info,
+                                             size_t number_of_bytes_for_dex_map,
+                                             size_t number_of_bytes_for_dex_pc,
+                                             size_t number_of_bytes_for_native_pc,
+                                             size_t number_of_bytes_for_register_mask) {
+  return stack_mask_size
+      + number_of_bytes_for_inline_info
+      + number_of_bytes_for_dex_map
+      + number_of_bytes_for_dex_pc
+      + number_of_bytes_for_native_pc
+      + number_of_bytes_for_register_mask;
 }
 
 size_t StackMap::ComputeStackMapSize(size_t stack_mask_size,
                                      size_t inline_info_size,
                                      size_t dex_register_map_size,
                                      size_t dex_pc_max,
-                                     size_t native_pc_max) {
-  return ComputeStackMapSize(
+                                     size_t native_pc_max,
+                                     size_t register_mask_max) {
+  return ComputeStackMapSizeInternal(
       stack_mask_size,
-      inline_info_size != 0,
-      // + 1 to also encode kNoInlineInfo.
-      IsUint<kBitsForSmallEncoding>(inline_info_size + dex_register_map_size + 1),
+      inline_info_size == 0
+          ? 0
+            // + 1 to also encode kNoInlineInfo.
+          :  CodeInfo::EncodingSizeInBytes(inline_info_size + dex_register_map_size + 1),
       // + 1 to also encode kNoDexRegisterMap.
-      IsUint<kBitsForSmallEncoding>(dex_register_map_size + 1),
-      IsUint<kBitsForSmallEncoding>(dex_pc_max),
-      IsUint<kBitsForSmallEncoding>(native_pc_max));
+      CodeInfo::EncodingSizeInBytes(dex_register_map_size + 1),
+      CodeInfo::EncodingSizeInBytes(dex_pc_max),
+      CodeInfo::EncodingSizeInBytes(native_pc_max),
+      CodeInfo::EncodingSizeInBytes(register_mask_max));
 }
 
 MemoryRegion StackMap::GetStackMask(const CodeInfo& info) const {
   return region_.Subregion(info.ComputeStackMapStackMaskOffset(), info.GetStackMaskSize());
 }
 
+static void DumpRegisterMapping(std::ostream& os,
+                                size_t dex_register_num,
+                                DexRegisterLocation location,
+                                const std::string& prefix = "v",
+                                const std::string& suffix = "") {
+  os << "      " << prefix << dex_register_num << ": "
+     << DexRegisterLocation::PrettyDescriptor(location.GetInternalKind())
+     << " (" << location.GetValue() << ")" << suffix << '\n';
+}
+
 void CodeInfo::DumpStackMapHeader(std::ostream& os, size_t stack_map_num) const {
   StackMap stack_map = GetStackMapAt(stack_map_num);
   os << "    StackMap " << stack_map_num
@@ -168,13 +233,25 @@
      << ", number_of_dex_registers=" << number_of_dex_registers
      << ", number_of_stack_maps=" << number_of_stack_maps
      << ", has_inline_info=" << HasInlineInfo()
-     << ", has_small_inline_info=" << HasSmallInlineInfo()
-     << ", has_small_dex_register_map=" << HasSmallDexRegisterMap()
-     << ", has_small_dex_pc=" << HasSmallDexPc()
-     << ", has_small_native_pc=" << HasSmallNativePc()
+     << ", number_of_bytes_for_inline_info=" << NumberOfBytesForInlineInfo()
+     << ", number_of_bytes_for_dex_register_map=" << NumberOfBytesForDexRegisterMap()
+     << ", number_of_bytes_for_dex_pc=" << NumberOfBytesForDexPc()
+     << ", number_of_bytes_for_native_pc=" << NumberOfBytesForNativePc()
+     << ", number_of_bytes_for_register_mask=" << NumberOfBytesForRegisterMask()
      << ")\n";
 
-  // Display stack maps along with Dex register maps.
+  // Display the Dex register location catalog.
+  size_t number_of_location_catalog_entries = GetNumberOfDexRegisterLocationCatalogEntries();
+  size_t location_catalog_size_in_bytes = GetDexRegisterLocationCatalogSize();
+  os << "  DexRegisterLocationCatalog (number_of_entries=" << number_of_location_catalog_entries
+     << ", size_in_bytes=" << location_catalog_size_in_bytes << ")\n";
+  DexRegisterLocationCatalog dex_register_location_catalog = GetDexRegisterLocationCatalog();
+  for (size_t i = 0; i < number_of_location_catalog_entries; ++i) {
+    DexRegisterLocation location = dex_register_location_catalog.GetDexRegisterLocation(i);
+    DumpRegisterMapping(os, i, location, "entry ");
+  }
+
+  // Display stack maps along with (live) Dex register maps.
   for (size_t i = 0; i < number_of_stack_maps; ++i) {
     StackMap stack_map = GetStackMapAt(i);
     DumpStackMapHeader(os, i);
@@ -183,11 +260,13 @@
       // TODO: Display the bit mask of live Dex registers.
       for (size_t j = 0; j < number_of_dex_registers; ++j) {
         if (dex_register_map.IsDexRegisterLive(j)) {
+          size_t location_catalog_entry_index = dex_register_map.GetLocationCatalogEntryIndex(
+              j, number_of_dex_registers, number_of_location_catalog_entries);
           DexRegisterLocation location =
-              dex_register_map.GetLocationKindAndValue(j, number_of_dex_registers);
-           os << "      " << "v" << j << ": "
-              << DexRegisterLocation::PrettyDescriptor(location.GetInternalKind())
-              << " (" << location.GetValue() << ")" << '\n';
+              dex_register_map.GetDexRegisterLocation(j, number_of_dex_registers, *this);
+          DumpRegisterMapping(
+              os, j, location, "v",
+              "\t[entry " + std::to_string(static_cast<int>(location_catalog_entry_index)) + "]");
         }
       }
     }
diff --git a/runtime/stack_map.h b/runtime/stack_map.h
index 6ec7cc8..f68cafe 100644
--- a/runtime/stack_map.h
+++ b/runtime/stack_map.h
@@ -26,13 +26,10 @@
 // Size of a frame slot, in bytes.  This constant is a signed value,
 // to please the compiler in arithmetic operations involving int32_t
 // (signed) values.
-static ssize_t constexpr kFrameSlotSize = 4;
-
-// Word alignment required on ARM, in bytes.
-static constexpr size_t kWordAlignment = 4;
+static constexpr ssize_t kFrameSlotSize = 4;
 
 // Size of Dex virtual registers.
-static size_t constexpr kVRegSize = 4;
+static constexpr size_t kVRegSize = 4;
 
 class CodeInfo;
 
@@ -97,9 +94,9 @@
    *
    * In addition, DexRegisterMap also uses these values:
    * - kInStackLargeOffset: value holds a "large" stack offset (greater than
-   *   128 bytes);
-   * - kConstantLargeValue: value holds a "large" constant (lower than or
-   *   equal to -16, or greater than 16).
+   *   or equal to 128 bytes);
+   * - kConstantLargeValue: value holds a "large" constant (lower than 0, or
+   *   or greater than or equal to 32).
    */
   enum class Kind : uint8_t {
     // Short location kinds, for entries fitting on one byte (3 bits
@@ -120,8 +117,7 @@
     kInStackLargeOffset = 5,  // 0b101
 
     // Large constant, that cannot fit on a 5-bit signed integer (i.e.,
-    // lower than -2^(5-1) = -16, or greater than or equal to
-    // 2^(5-1) - 1 = 15).
+    // lower than 0, or greater than or equal to 2^5 = 32).
     kConstantLargeValue = 6,  // 0b110
 
     kLastLocationKind = kConstantLargeValue
@@ -193,8 +189,10 @@
     }
   }
 
-  DexRegisterLocation(Kind kind, int32_t value)
-      : kind_(kind), value_(value) {}
+  // Required by art::StackMapStream::LocationCatalogEntriesIndices.
+  DexRegisterLocation() : kind_(Kind::kNone), value_(0) {}
+
+  DexRegisterLocation(Kind kind, int32_t value) : kind_(kind), value_(value) {}
 
   static DexRegisterLocation None() {
     return DexRegisterLocation(Kind::kNone, 0);
@@ -223,33 +221,23 @@
  private:
   Kind kind_;
   int32_t value_;
+
+  friend class DexRegisterLocationHashFn;
 };
 
 /**
- * Information on dex register values for a specific PC. The information is
- * of the form:
- * [live_bit_mask, DexRegisterLocation+].
+ * Store information on unique Dex register locations used in a method.
+ * The information is of the form:
+ * [DexRegisterLocation+].
  * DexRegisterLocations are either 1- or 5-byte wide (see art::DexRegisterLocation::Kind).
  */
-class DexRegisterMap {
+class DexRegisterLocationCatalog {
  public:
-  explicit DexRegisterMap(MemoryRegion region) : region_(region) {}
+  explicit DexRegisterLocationCatalog(MemoryRegion region) : region_(region) {}
 
   // Short (compressed) location, fitting on one byte.
   typedef uint8_t ShortLocation;
 
-  static size_t LiveBitMaskSize(uint16_t number_of_dex_registers) {
-    return RoundUp(number_of_dex_registers, kBitsPerByte) / kBitsPerByte;
-  }
-
-  void SetLiveBitMask(size_t offset,
-                      uint16_t number_of_dex_registers,
-                      const BitVector& live_dex_registers_mask) {
-    for (uint16_t i = 0; i < number_of_dex_registers; i++) {
-      region_.StoreBit(offset + i, live_dex_registers_mask.IsBitSet(i));
-    }
-  }
-
   void SetRegisterInfo(size_t offset, const DexRegisterLocation& dex_register_location) {
     DexRegisterLocation::Kind kind = ComputeCompressedKind(dex_register_location);
     int32_t value = dex_register_location.GetValue();
@@ -265,12 +253,12 @@
         DCHECK_EQ(value % kFrameSlotSize, 0);
         value /= kFrameSlotSize;
       }
-      DCHECK(IsUint<kValueBits>(value)) << value;
+      DCHECK(IsShortValue(value)) << value;
       region_.StoreUnaligned<ShortLocation>(offset, MakeShortLocation(kind, value));
     } else {
       // Large location.  Write the location on one byte and the value
       // on 4 bytes.
-      DCHECK(!IsUint<kValueBits>(value)) << value;
+      DCHECK(!IsShortValue(value)) << value;
       if (kind == DexRegisterLocation::Kind::kInStackLargeOffset) {
         // Also divide large stack offsets by 4 for the sake of consistency.
         DCHECK_EQ(value % kFrameSlotSize, 0);
@@ -285,63 +273,39 @@
     }
   }
 
-  bool IsDexRegisterLive(uint16_t dex_register_index) const {
+  // Find the offset of the location catalog entry number `location_catalog_entry_index`.
+  size_t FindLocationOffset(size_t location_catalog_entry_index) const {
     size_t offset = kFixedSize;
-    return region_.LoadBit(offset + dex_register_index);
-  }
-
-  static constexpr size_t kNoDexRegisterLocationOffset = -1;
-
-  static size_t GetDexRegisterMapLocationsOffset(uint16_t number_of_dex_registers) {
-    return kLiveBitMaskOffset + LiveBitMaskSize(number_of_dex_registers);
-  }
-
-  // Find the offset of the Dex register location number `dex_register_index`.
-  size_t FindLocationOffset(uint16_t dex_register_index, uint16_t number_of_dex_registers) const {
-    if (!IsDexRegisterLive(dex_register_index)) return kNoDexRegisterLocationOffset;
-    size_t offset = GetDexRegisterMapLocationsOffset(number_of_dex_registers);
-    // Skip the first `dex_register_index - 1` entries.
-    for (uint16_t i = 0; i < dex_register_index; ++i) {
-      if (IsDexRegisterLive(i)) {
-        // Read the first next byte and inspect its first 3 bits to decide
-        // whether it is a short or a large location.
-        DexRegisterLocation::Kind kind = ExtractKindAtOffset(offset);
-        if (DexRegisterLocation::IsShortLocationKind(kind)) {
-          // Short location.  Skip the current byte.
-          offset += SingleShortEntrySize();
-        } else {
-          // Large location.  Skip the 5 next bytes.
-          offset += SingleLargeEntrySize();
-        }
+    // Skip the first `location_catalog_entry_index - 1` entries.
+    for (uint16_t i = 0; i < location_catalog_entry_index; ++i) {
+      // Read the first next byte and inspect its first 3 bits to decide
+      // whether it is a short or a large location.
+      DexRegisterLocation::Kind kind = ExtractKindAtOffset(offset);
+      if (DexRegisterLocation::IsShortLocationKind(kind)) {
+        // Short location.  Skip the current byte.
+        offset += SingleShortEntrySize();
+      } else {
+        // Large location.  Skip the 5 next bytes.
+        offset += SingleLargeEntrySize();
       }
     }
     return offset;
   }
 
-  // Get the surface kind.
-  DexRegisterLocation::Kind GetLocationKind(uint16_t dex_register_index,
-                                            uint16_t number_of_dex_registers) const {
-    return IsDexRegisterLive(dex_register_index)
-        ? DexRegisterLocation::ConvertToSurfaceKind(
-              GetLocationInternalKind(dex_register_index, number_of_dex_registers))
-        : DexRegisterLocation::Kind::kNone;
+  // Get the internal kind of entry at `location_catalog_entry_index`.
+  DexRegisterLocation::Kind GetLocationInternalKind(size_t location_catalog_entry_index) const {
+    if (location_catalog_entry_index == kNoLocationEntryIndex) {
+      return DexRegisterLocation::Kind::kNone;
+    }
+    return ExtractKindAtOffset(FindLocationOffset(location_catalog_entry_index));
   }
 
-  // Get the internal kind.
-  DexRegisterLocation::Kind GetLocationInternalKind(uint16_t dex_register_index,
-                                                    uint16_t number_of_dex_registers) const {
-    return IsDexRegisterLive(dex_register_index)
-        ? ExtractKindAtOffset(FindLocationOffset(dex_register_index, number_of_dex_registers))
-        : DexRegisterLocation::Kind::kNone;
-  }
-
-  // TODO: Rename as GetDexRegisterLocation?
-  DexRegisterLocation GetLocationKindAndValue(uint16_t dex_register_index,
-                                              uint16_t number_of_dex_registers) const {
-    if (!IsDexRegisterLive(dex_register_index)) {
+  // Get the (surface) kind and value of entry at `location_catalog_entry_index`.
+  DexRegisterLocation GetDexRegisterLocation(size_t location_catalog_entry_index) const {
+    if (location_catalog_entry_index == kNoLocationEntryIndex) {
       return DexRegisterLocation::None();
     }
-    size_t offset = FindLocationOffset(dex_register_index, number_of_dex_registers);
+    size_t offset = FindLocationOffset(location_catalog_entry_index);
     // Read the first byte and inspect its first 3 bits to get the location.
     ShortLocation first_byte = region_.LoadUnaligned<ShortLocation>(offset);
     DexRegisterLocation::Kind kind = ExtractKindFromShortLocation(first_byte);
@@ -364,31 +328,6 @@
     }
   }
 
-  int32_t GetStackOffsetInBytes(uint16_t dex_register_index,
-                                uint16_t number_of_dex_registers) const {
-    DexRegisterLocation location =
-        GetLocationKindAndValue(dex_register_index, number_of_dex_registers);
-    DCHECK(location.GetKind() == DexRegisterLocation::Kind::kInStack);
-    // GetLocationKindAndValue returns the offset in bytes.
-    return location.GetValue();
-  }
-
-  int32_t GetConstant(uint16_t dex_register_index, uint16_t number_of_dex_registers) const {
-    DexRegisterLocation location =
-        GetLocationKindAndValue(dex_register_index, number_of_dex_registers);
-    DCHECK(location.GetKind() == DexRegisterLocation::Kind::kConstant);
-    return location.GetValue();
-  }
-
-  int32_t GetMachineRegister(uint16_t dex_register_index, uint16_t number_of_dex_registers) const {
-    DexRegisterLocation location =
-        GetLocationKindAndValue(dex_register_index, number_of_dex_registers);
-    DCHECK(location.GetInternalKind() == DexRegisterLocation::Kind::kInRegister
-           || location.GetInternalKind() == DexRegisterLocation::Kind::kInFpuRegister)
-        << DexRegisterLocation::PrettyDescriptor(location.GetInternalKind());
-    return location.GetValue();
-  }
-
   // Compute the compressed kind of `location`.
   static DexRegisterLocation::Kind ComputeCompressedKind(const DexRegisterLocation& location) {
     switch (location.GetInternalKind()) {
@@ -398,22 +337,21 @@
 
       case DexRegisterLocation::Kind::kInRegister:
         DCHECK_GE(location.GetValue(), 0);
-        DCHECK_LT(location.GetValue(), 1 << DexRegisterMap::kValueBits);
+        DCHECK_LT(location.GetValue(), 1 << kValueBits);
         return DexRegisterLocation::Kind::kInRegister;
 
       case DexRegisterLocation::Kind::kInFpuRegister:
         DCHECK_GE(location.GetValue(), 0);
-        DCHECK_LT(location.GetValue(), 1 << DexRegisterMap::kValueBits);
+        DCHECK_LT(location.GetValue(), 1 << kValueBits);
         return DexRegisterLocation::Kind::kInFpuRegister;
 
       case DexRegisterLocation::Kind::kInStack:
-        DCHECK_EQ(location.GetValue() % kFrameSlotSize, 0);
-        return IsUint<DexRegisterMap::kValueBits>(location.GetValue() / kFrameSlotSize)
+        return IsShortStackOffsetValue(location.GetValue())
             ? DexRegisterLocation::Kind::kInStack
             : DexRegisterLocation::Kind::kInStackLargeOffset;
 
       case DexRegisterLocation::Kind::kConstant:
-        return IsUint<DexRegisterMap::kValueBits>(location.GetValue())
+        return IsShortConstantValue(location.GetValue())
             ? DexRegisterLocation::Kind::kConstant
             : DexRegisterLocation::Kind::kConstantLargeValue;
 
@@ -433,11 +371,10 @@
         return true;
 
       case DexRegisterLocation::Kind::kInStack:
-        DCHECK_EQ(location.GetValue() % kFrameSlotSize, 0);
-        return IsUint<kValueBits>(location.GetValue() / kFrameSlotSize);
+        return IsShortStackOffsetValue(location.GetValue());
 
       case DexRegisterLocation::Kind::kConstant:
-        return IsUint<kValueBits>(location.GetValue());
+        return IsShortConstantValue(location.GetValue());
 
       default:
         UNREACHABLE();
@@ -445,9 +382,7 @@
   }
 
   static size_t EntrySize(const DexRegisterLocation& location) {
-    return CanBeEncodedAsShortLocation(location)
-        ? DexRegisterMap::SingleShortEntrySize()
-        : DexRegisterMap::SingleLargeEntrySize();
+    return CanBeEncodedAsShortLocation(location) ? SingleShortEntrySize() : SingleLargeEntrySize();
   }
 
   static size_t SingleShortEntrySize() {
@@ -462,10 +397,14 @@
     return region_.size();
   }
 
-  static constexpr int kLiveBitMaskOffset = 0;
-  static constexpr int kFixedSize = kLiveBitMaskOffset;
+  // Special (invalid) Dex register location catalog entry index meaning
+  // that there is no location for a given Dex register (i.e., it is
+  // mapped to a DexRegisterLocation::Kind::kNone location).
+  static constexpr size_t kNoLocationEntryIndex = -1;
 
  private:
+  static constexpr int kFixedSize = 0;
+
   // Width of the kind "field" in a short location, in bits.
   static constexpr size_t kKindBits = 3;
   // Width of the value "field" in a short location, in bits.
@@ -476,10 +415,24 @@
   static constexpr size_t kKindOffset = 0;
   static constexpr size_t kValueOffset = kKindBits;
 
+  static bool IsShortStackOffsetValue(int32_t value) {
+    DCHECK_EQ(value % kFrameSlotSize, 0);
+    return IsShortValue(value / kFrameSlotSize);
+  }
+
+  static bool IsShortConstantValue(int32_t value) {
+    return IsShortValue(value);
+  }
+
+  static bool IsShortValue(int32_t value) {
+    return IsUint<kValueBits>(value);
+  }
+
   static ShortLocation MakeShortLocation(DexRegisterLocation::Kind kind, int32_t value) {
-    DCHECK(IsUint<kKindBits>(static_cast<uint8_t>(kind))) << static_cast<uint8_t>(kind);
-    DCHECK(IsUint<kValueBits>(value)) << value;
-    return (static_cast<uint8_t>(kind) & kKindMask) << kKindOffset
+    uint8_t kind_integer_value = static_cast<uint8_t>(kind);
+    DCHECK(IsUint<kKindBits>(kind_integer_value)) << kind_integer_value;
+    DCHECK(IsShortValue(value)) << value;
+    return (kind_integer_value & kKindMask) << kKindOffset
         | (value & kValueMask) << kValueOffset;
   }
 
@@ -507,6 +460,210 @@
   friend class StackMapStream;
 };
 
+/* Information on Dex register locations for a specific PC, mapping a
+ * stack map's Dex register to a location entry in a DexRegisterLocationCatalog.
+ * The information is of the form:
+ * [live_bit_mask, entries*]
+ * where entries are concatenated unsigned integer values encoded on a number
+ * of bits (fixed per DexRegisterMap instances of a CodeInfo object) depending
+ * on the number of entries in the Dex register location catalog
+ * (see DexRegisterMap::SingleEntrySizeInBits).  The map is 1-byte aligned.
+ */
+class DexRegisterMap {
+ public:
+  explicit DexRegisterMap(MemoryRegion region) : region_(region) {}
+
+  // Get the surface kind of Dex register `dex_register_number`.
+  DexRegisterLocation::Kind GetLocationKind(uint16_t dex_register_number,
+                                            uint16_t number_of_dex_registers,
+                                            const CodeInfo& code_info) const {
+    return DexRegisterLocation::ConvertToSurfaceKind(
+        GetLocationInternalKind(dex_register_number, number_of_dex_registers, code_info));
+  }
+
+  // Get the internal kind of Dex register `dex_register_number`.
+  DexRegisterLocation::Kind GetLocationInternalKind(uint16_t dex_register_number,
+                                                    uint16_t number_of_dex_registers,
+                                                    const CodeInfo& code_info) const;
+
+  // Get the Dex register location `dex_register_number`.
+  DexRegisterLocation GetDexRegisterLocation(uint16_t dex_register_number,
+                                             uint16_t number_of_dex_registers,
+                                             const CodeInfo& code_info) const;
+
+  int32_t GetStackOffsetInBytes(uint16_t dex_register_number,
+                                uint16_t number_of_dex_registers,
+                                const CodeInfo& code_info) const {
+    DexRegisterLocation location =
+        GetDexRegisterLocation(dex_register_number, number_of_dex_registers, code_info);
+    DCHECK(location.GetKind() == DexRegisterLocation::Kind::kInStack);
+    // GetDexRegisterLocation returns the offset in bytes.
+    return location.GetValue();
+  }
+
+  int32_t GetConstant(uint16_t dex_register_number,
+                      uint16_t number_of_dex_registers,
+                      const CodeInfo& code_info) const {
+    DexRegisterLocation location =
+        GetDexRegisterLocation(dex_register_number, number_of_dex_registers, code_info);
+    DCHECK(location.GetKind() == DexRegisterLocation::Kind::kConstant);
+    return location.GetValue();
+  }
+
+  int32_t GetMachineRegister(uint16_t dex_register_number,
+                             uint16_t number_of_dex_registers,
+                             const CodeInfo& code_info) const {
+    DexRegisterLocation location =
+        GetDexRegisterLocation(dex_register_number, number_of_dex_registers, code_info);
+    DCHECK(location.GetInternalKind() == DexRegisterLocation::Kind::kInRegister
+           || location.GetInternalKind() == DexRegisterLocation::Kind::kInFpuRegister)
+        << DexRegisterLocation::PrettyDescriptor(location.GetInternalKind());
+    return location.GetValue();
+  }
+
+  // Get the index of the entry in the Dex register location catalog
+  // corresponding to `dex_register_number`.
+  size_t GetLocationCatalogEntryIndex(uint16_t dex_register_number,
+                                      uint16_t number_of_dex_registers,
+                                      size_t number_of_location_catalog_entries) const {
+    if (!IsDexRegisterLive(dex_register_number)) {
+      return DexRegisterLocationCatalog::kNoLocationEntryIndex;
+    }
+
+    if (number_of_location_catalog_entries == 1) {
+      // We do not allocate space for location maps in the case of a
+      // single-entry location catalog, as it is useless.  The only valid
+      // entry index is 0;
+      return 0;
+    }
+
+    // The bit offset of the beginning of the map locations.
+    size_t map_locations_offset_in_bits =
+        GetLocationMappingDataOffset(number_of_dex_registers) * kBitsPerByte;
+    size_t index_in_dex_register_map = GetIndexInDexRegisterMap(dex_register_number);
+    DCHECK_LT(index_in_dex_register_map, GetNumberOfLiveDexRegisters(number_of_dex_registers));
+    // The bit size of an entry.
+    size_t map_entry_size_in_bits = SingleEntrySizeInBits(number_of_location_catalog_entries);
+    // The bit offset where `index_in_dex_register_map` is located.
+    size_t entry_offset_in_bits =
+        map_locations_offset_in_bits + index_in_dex_register_map * map_entry_size_in_bits;
+    size_t location_catalog_entry_index =
+        region_.LoadBits(entry_offset_in_bits, map_entry_size_in_bits);
+    DCHECK_LT(location_catalog_entry_index, number_of_location_catalog_entries);
+    return location_catalog_entry_index;
+  }
+
+  // Map entry at `index_in_dex_register_map` to `location_catalog_entry_index`.
+  void SetLocationCatalogEntryIndex(size_t index_in_dex_register_map,
+                                    size_t location_catalog_entry_index,
+                                    uint16_t number_of_dex_registers,
+                                    size_t number_of_location_catalog_entries) {
+    DCHECK_LT(index_in_dex_register_map, GetNumberOfLiveDexRegisters(number_of_dex_registers));
+    DCHECK_LT(location_catalog_entry_index, number_of_location_catalog_entries);
+
+    if (number_of_location_catalog_entries == 1) {
+      // We do not allocate space for location maps in the case of a
+      // single-entry location catalog, as it is useless.
+      return;
+    }
+
+    // The bit offset of the beginning of the map locations.
+    size_t map_locations_offset_in_bits =
+        GetLocationMappingDataOffset(number_of_dex_registers) * kBitsPerByte;
+    // The bit size of an entry.
+    size_t map_entry_size_in_bits = SingleEntrySizeInBits(number_of_location_catalog_entries);
+    // The bit offset where `index_in_dex_register_map` is located.
+    size_t entry_offset_in_bits =
+        map_locations_offset_in_bits + index_in_dex_register_map * map_entry_size_in_bits;
+    region_.StoreBits(entry_offset_in_bits, location_catalog_entry_index, map_entry_size_in_bits);
+  }
+
+  void SetLiveBitMask(uint16_t number_of_dex_registers,
+                      const BitVector& live_dex_registers_mask) {
+    size_t live_bit_mask_offset_in_bits = GetLiveBitMaskOffset() * kBitsPerByte;
+    for (uint16_t i = 0; i < number_of_dex_registers; ++i) {
+      region_.StoreBit(live_bit_mask_offset_in_bits + i, live_dex_registers_mask.IsBitSet(i));
+    }
+  }
+
+  bool IsDexRegisterLive(uint16_t dex_register_number) const {
+    size_t live_bit_mask_offset_in_bits = GetLiveBitMaskOffset() * kBitsPerByte;
+    return region_.LoadBit(live_bit_mask_offset_in_bits + dex_register_number);
+  }
+
+  size_t GetNumberOfLiveDexRegisters(uint16_t number_of_dex_registers) const {
+    size_t number_of_live_dex_registers = 0;
+    for (size_t i = 0; i < number_of_dex_registers; ++i) {
+      if (IsDexRegisterLive(i)) {
+        ++number_of_live_dex_registers;
+      }
+    }
+    return number_of_live_dex_registers;
+  }
+
+  static size_t GetLiveBitMaskOffset() {
+    return kFixedSize;
+  }
+
+  // Compute the size of the live register bit mask (in bytes), for a
+  // method having `number_of_dex_registers` Dex registers.
+  static size_t GetLiveBitMaskSize(uint16_t number_of_dex_registers) {
+    return RoundUp(number_of_dex_registers, kBitsPerByte) / kBitsPerByte;
+  }
+
+  static size_t GetLocationMappingDataOffset(uint16_t number_of_dex_registers) {
+    return GetLiveBitMaskOffset() + GetLiveBitMaskSize(number_of_dex_registers);
+  }
+
+  size_t GetLocationMappingDataSize(uint16_t number_of_dex_registers,
+                                    size_t number_of_location_catalog_entries) const {
+    size_t location_mapping_data_size_in_bits =
+        GetNumberOfLiveDexRegisters(number_of_dex_registers)
+        * SingleEntrySizeInBits(number_of_location_catalog_entries);
+    return RoundUp(location_mapping_data_size_in_bits, kBitsPerByte) / kBitsPerByte;
+  }
+
+  // Return the size of a map entry in bits.  Note that if
+  // `number_of_location_catalog_entries` equals 1, this function returns 0,
+  // which is fine, as there is no need to allocate a map for a
+  // single-entry location catalog; the only valid location catalog entry index
+  // for a live register in this case is 0 and there is no need to
+  // store it.
+  static size_t SingleEntrySizeInBits(size_t number_of_location_catalog_entries) {
+    // Handle the case of 0, as we cannot pass 0 to art::WhichPowerOf2.
+    return number_of_location_catalog_entries == 0
+        ? 0u
+        : WhichPowerOf2(RoundUpToPowerOfTwo(number_of_location_catalog_entries));
+  }
+
+  // Return the size of the DexRegisterMap object, in bytes.
+  size_t Size() const {
+    return region_.size();
+  }
+
+ private:
+  // Return the index in the Dex register map corresponding to the Dex
+  // register number `dex_register_number`.
+  size_t GetIndexInDexRegisterMap(uint16_t dex_register_number) const {
+    if (!IsDexRegisterLive(dex_register_number)) {
+      return kInvalidIndexInDexRegisterMap;
+    }
+    return GetNumberOfLiveDexRegisters(dex_register_number);
+  }
+
+  // Special (invalid) Dex register map entry index meaning that there
+  // is no index in the map for a given Dex register (i.e., it must
+  // have been mapped to a DexRegisterLocation::Kind::kNone location).
+  static constexpr size_t kInvalidIndexInDexRegisterMap = -1;
+
+  static constexpr int kFixedSize = 0;
+
+  MemoryRegion region_;
+
+  friend class CodeInfo;
+  friend class StackMapStream;
+};
+
 /**
  * A Stack Map holds compilation information for a specific PC necessary for:
  * - Mapping it to a dex PC,
@@ -516,7 +673,8 @@
  * - Knowing the values of dex registers.
  *
  * The information is of the form:
- * [dex_pc, native_pc_offset, dex_register_map_offset, inlining_info_offset, register_mask, stack_mask].
+ * [dex_pc, native_pc_offset, dex_register_map_offset, inlining_info_offset, register_mask,
+ * stack_mask].
  *
  * Note that register_mask is fixed size, but stack_mask is variable size, depending on the
  * stack size of a method.
@@ -568,49 +726,32 @@
   }
 
   static size_t ComputeStackMapSize(size_t stack_mask_size,
-                                    bool has_inline_info,
-                                    bool is_small_inline_info,
-                                    bool is_small_dex_map,
-                                    bool is_small_dex_pc,
-                                    bool is_small_native_pc);
-
-  static size_t ComputeStackMapSize(size_t stack_mask_size,
                                     size_t inline_info_size,
                                     size_t dex_register_map_size,
                                     size_t dex_pc_max,
-                                    size_t native_pc_max);
-
-  // TODO: Revisit this abstraction if we allow 3 bytes encoding.
-  typedef uint8_t kSmallEncoding;
-  typedef uint32_t kLargeEncoding;
-  static constexpr size_t kBytesForSmallEncoding = sizeof(kSmallEncoding);
-  static constexpr size_t kBitsForSmallEncoding = kBitsPerByte * kBytesForSmallEncoding;
-  static constexpr size_t kBytesForLargeEncoding = sizeof(kLargeEncoding);
-  static constexpr size_t kBitsForLargeEncoding = kBitsPerByte * kBytesForLargeEncoding;
+                                    size_t native_pc_max,
+                                    size_t register_mask_max);
 
   // Special (invalid) offset for the DexRegisterMapOffset field meaning
   // that there is no Dex register map for this stack map.
   static constexpr uint32_t kNoDexRegisterMap = -1;
-  static constexpr uint32_t kNoDexRegisterMapSmallEncoding =
-      std::numeric_limits<kSmallEncoding>::max();
 
   // Special (invalid) offset for the InlineDescriptorOffset field meaning
   // that there is no inline info for this stack map.
   static constexpr uint32_t kNoInlineInfo = -1;
-  static constexpr uint32_t kNoInlineInfoSmallEncoding =
-    std::numeric_limits<kSmallEncoding>::max();
-
-  // Returns the number of bytes needed for an entry in the StackMap.
-  static size_t NumberOfBytesForEntry(bool small_encoding) {
-    return small_encoding ? kBytesForSmallEncoding : kBytesForLargeEncoding;
-  }
 
  private:
+  static size_t ComputeStackMapSizeInternal(size_t stack_mask_size,
+                                            size_t number_of_bytes_for_inline_info,
+                                            size_t number_of_bytes_for_dex_map,
+                                            size_t number_of_bytes_for_dex_pc,
+                                            size_t number_of_bytes_for_native_pc,
+                                            size_t number_of_bytes_for_register_mask);
+
   // TODO: Instead of plain types such as "uint32_t", introduce
   // typedefs (and document the memory layout of StackMap).
   static constexpr int kRegisterMaskOffset = 0;
-  static constexpr int kFixedSize = kRegisterMaskOffset + sizeof(uint32_t);
-  static constexpr int kStackMaskOffset = kFixedSize;
+  static constexpr int kFixedSize = 0;
 
   MemoryRegion region_;
 
@@ -622,7 +763,8 @@
 /**
  * Wrapper around all compiler information collected for a method.
  * The information is of the form:
- * [overall_size, number_of_stack_maps, stack_mask_size, StackMap+, DexRegisterInfo+, InlineInfo*].
+ * [overall_size, number_of_location_catalog_entries, number_of_stack_maps, stack_mask_size,
+ * DexRegisterLocationCatalog+, StackMap+, DexRegisterMap+, InlineInfo*].
  */
 class CodeInfo {
  public:
@@ -633,50 +775,77 @@
     region_ = MemoryRegion(const_cast<void*>(data), size);
   }
 
+  static size_t EncodingSizeInBytes(size_t max_element) {
+    DCHECK(IsUint<32>(max_element));
+    return (max_element == 0) ? 0
+         : IsUint<8>(max_element) ? 1
+         : IsUint<16>(max_element) ? 2
+         : IsUint<24>(max_element) ? 3
+         : 4;
+  }
+
   void SetEncoding(size_t inline_info_size,
                    size_t dex_register_map_size,
                    size_t dex_pc_max,
-                   size_t native_pc_max) {
+                   size_t native_pc_max,
+                   size_t register_mask_max) {
     if (inline_info_size != 0) {
       region_.StoreBit(kHasInlineInfoBitOffset, 1);
-      region_.StoreBit(kHasSmallInlineInfoBitOffset, IsUint<StackMap::kBitsForSmallEncoding>(
-          // + 1 to also encode kNoInlineInfo: if an inline info offset
-          // is at 0xFF, we want to overflow to a larger encoding, because it will
-          // conflict with kNoInlineInfo.
-          // The offset is relative to the dex register map. TODO: Change this.
-          inline_info_size + dex_register_map_size + 1));
+      // + 1 to also encode kNoInlineInfo: if an inline info offset
+      // is at 0xFF, we want to overflow to a larger encoding, because it will
+      // conflict with kNoInlineInfo.
+      // The offset is relative to the dex register map. TODO: Change this.
+      SetEncodingAt(kInlineInfoBitOffset,
+                    EncodingSizeInBytes(dex_register_map_size + inline_info_size + 1));
     } else {
       region_.StoreBit(kHasInlineInfoBitOffset, 0);
-      region_.StoreBit(kHasSmallInlineInfoBitOffset, 0);
+      SetEncodingAt(kInlineInfoBitOffset, 0);
     }
-    region_.StoreBit(kHasSmallDexRegisterMapBitOffset,
-                     // + 1 to also encode kNoDexRegisterMap: if a dex register map offset
-                     // is at 0xFF, we want to overflow to a larger encoding, because it will
-                     // conflict with kNoDexRegisterMap.
-                     IsUint<StackMap::kBitsForSmallEncoding>(dex_register_map_size + 1));
-    region_.StoreBit(kHasSmallDexPcBitOffset, IsUint<StackMap::kBitsForSmallEncoding>(dex_pc_max));
-    region_.StoreBit(kHasSmallNativePcBitOffset,
-                     IsUint<StackMap::kBitsForSmallEncoding>(native_pc_max));
+    // + 1 to also encode kNoDexRegisterMap: if a dex register map offset
+    // is at 0xFF, we want to overflow to a larger encoding, because it will
+    // conflict with kNoDexRegisterMap.
+    SetEncodingAt(kDexRegisterMapBitOffset, EncodingSizeInBytes(dex_register_map_size + 1));
+    SetEncodingAt(kDexPcBitOffset, EncodingSizeInBytes(dex_pc_max));
+    SetEncodingAt(kNativePcBitOffset, EncodingSizeInBytes(native_pc_max));
+    SetEncodingAt(kRegisterMaskBitOffset, EncodingSizeInBytes(register_mask_max));
+  }
+
+  void SetEncodingAt(size_t bit_offset, size_t number_of_bytes) {
+    // We encode the number of bytes needed for writing a value on 3 bits,
+    // for values that we know are maximum 32bits.
+    region_.StoreBit(bit_offset, (number_of_bytes & 1));
+    region_.StoreBit(bit_offset + 1, (number_of_bytes & 2));
+    region_.StoreBit(bit_offset + 2, (number_of_bytes & 4));
+  }
+
+  size_t GetNumberOfBytesForEncoding(size_t bit_offset) const {
+    return region_.LoadBit(bit_offset)
+        + (region_.LoadBit(bit_offset + 1) << 1)
+        + (region_.LoadBit(bit_offset + 2) << 2);
   }
 
   bool HasInlineInfo() const {
     return region_.LoadBit(kHasInlineInfoBitOffset);
   }
 
-  bool HasSmallInlineInfo() const {
-    return region_.LoadBit(kHasSmallInlineInfoBitOffset);
+  size_t NumberOfBytesForInlineInfo() const {
+    return GetNumberOfBytesForEncoding(kInlineInfoBitOffset);
   }
 
-  bool HasSmallDexRegisterMap() const {
-    return region_.LoadBit(kHasSmallDexRegisterMapBitOffset);
+  size_t NumberOfBytesForDexRegisterMap() const {
+    return GetNumberOfBytesForEncoding(kDexRegisterMapBitOffset);
   }
 
-  bool HasSmallNativePc() const {
-    return region_.LoadBit(kHasSmallNativePcBitOffset);
+  size_t NumberOfBytesForRegisterMask() const {
+    return GetNumberOfBytesForEncoding(kRegisterMaskBitOffset);
   }
 
-  bool HasSmallDexPc() const {
-    return region_.LoadBit(kHasSmallDexPcBitOffset);
+  size_t NumberOfBytesForNativePc() const {
+    return GetNumberOfBytesForEncoding(kNativePcBitOffset);
+  }
+
+  size_t NumberOfBytesForDexPc() const {
+    return GetNumberOfBytesForEncoding(kDexPcBitOffset);
   }
 
   size_t ComputeStackMapRegisterMaskOffset() const {
@@ -684,7 +853,8 @@
   }
 
   size_t ComputeStackMapStackMaskOffset() const {
-    return StackMap::kStackMaskOffset;
+    return ComputeStackMapRegisterMaskOffset()
+        + (NumberOfBytesForRegisterMask() * sizeof(uint8_t));
   }
 
   size_t ComputeStackMapDexPcOffset() const {
@@ -693,18 +863,28 @@
 
   size_t ComputeStackMapNativePcOffset() const {
     return ComputeStackMapDexPcOffset()
-        + (HasSmallDexPc() ? sizeof(uint8_t) : sizeof(uint32_t));
+        + (NumberOfBytesForDexPc() * sizeof(uint8_t));
   }
 
   size_t ComputeStackMapDexRegisterMapOffset() const {
     return ComputeStackMapNativePcOffset()
-        + (HasSmallNativePc() ? sizeof(uint8_t) : sizeof(uint32_t));
+        + (NumberOfBytesForNativePc() * sizeof(uint8_t));
   }
 
   size_t ComputeStackMapInlineInfoOffset() const {
     CHECK(HasInlineInfo());
     return ComputeStackMapDexRegisterMapOffset()
-        + (HasSmallDexRegisterMap() ? sizeof(uint8_t) : sizeof(uint32_t));
+        + (NumberOfBytesForDexRegisterMap() * sizeof(uint8_t));
+  }
+
+  uint32_t GetDexRegisterLocationCatalogOffset() const {
+    return kFixedSize;
+  }
+
+  DexRegisterLocationCatalog GetDexRegisterLocationCatalog() const {
+    return DexRegisterLocationCatalog(region_.Subregion(
+        GetDexRegisterLocationCatalogOffset(),
+        GetDexRegisterLocationCatalogSize()));
   }
 
   StackMap GetStackMapAt(size_t i) const {
@@ -720,6 +900,19 @@
     region_.StoreUnaligned<uint32_t>(kOverallSizeOffset, size);
   }
 
+  uint32_t GetNumberOfDexRegisterLocationCatalogEntries() const {
+    return region_.LoadUnaligned<uint32_t>(kNumberOfDexRegisterLocationCatalogEntriesOffset);
+  }
+
+  void SetNumberOfDexRegisterLocationCatalogEntries(uint32_t num_entries) {
+    region_.StoreUnaligned<uint32_t>(kNumberOfDexRegisterLocationCatalogEntriesOffset, num_entries);
+  }
+
+  uint32_t GetDexRegisterLocationCatalogSize() const {
+    return ComputeDexRegisterLocationCatalogSize(GetDexRegisterLocationCatalogOffset(),
+                                                 GetNumberOfDexRegisterLocationCatalogEntries());
+  }
+
   uint32_t GetStackMaskSize() const {
     return region_.LoadUnaligned<uint32_t>(kStackMaskSizeOffset);
   }
@@ -739,31 +932,31 @@
   // Get the size of one stack map of this CodeInfo object, in bytes.
   // All stack maps of a CodeInfo have the same size.
   size_t StackMapSize() const {
-    return StackMap::ComputeStackMapSize(GetStackMaskSize(),
-                                         HasInlineInfo(),
-                                         HasSmallInlineInfo(),
-                                         HasSmallDexRegisterMap(),
-                                         HasSmallDexPc(),
-                                         HasSmallNativePc());
+    return StackMap::ComputeStackMapSizeInternal(GetStackMaskSize(),
+                                                 NumberOfBytesForInlineInfo(),
+                                                 NumberOfBytesForDexRegisterMap(),
+                                                 NumberOfBytesForDexPc(),
+                                                 NumberOfBytesForNativePc(),
+                                                 NumberOfBytesForRegisterMask());
   }
 
   // Get the size all the stack maps of this CodeInfo object, in bytes.
-  size_t StackMapsSize() const {
+  size_t GetStackMapsSize() const {
     return StackMapSize() * GetNumberOfStackMaps();
   }
 
   size_t GetDexRegisterMapsOffset() const {
-    return CodeInfo::kFixedSize + StackMapsSize();
+    return GetStackMapsOffset() + GetStackMapsSize();
   }
 
   uint32_t GetStackMapsOffset() const {
-    return kFixedSize;
+    return GetDexRegisterLocationCatalogOffset() + GetDexRegisterLocationCatalogSize();
   }
 
   DexRegisterMap GetDexRegisterMapOf(StackMap stack_map, uint32_t number_of_dex_registers) const {
     DCHECK(stack_map.HasDexRegisterMap(*this));
-    uint32_t offset = stack_map.GetDexRegisterMapOffset(*this) + GetDexRegisterMapsOffset();
-    size_t size = ComputeDexRegisterMapSize(offset, number_of_dex_registers);
+    uint32_t offset = GetDexRegisterMapsOffset() + stack_map.GetDexRegisterMapOffset(*this);
+    size_t size = ComputeDexRegisterMapSizeOf(offset, number_of_dex_registers);
     return DexRegisterMap(region_.Subregion(offset, size));
   }
 
@@ -806,50 +999,73 @@
   // typedefs (and document the memory layout of CodeInfo).
   static constexpr int kOverallSizeOffset = 0;
   static constexpr int kEncodingInfoOffset = kOverallSizeOffset + sizeof(uint32_t);
-  static constexpr int kNumberOfStackMapsOffset = kEncodingInfoOffset + sizeof(uint8_t);
+  static constexpr int kNumberOfDexRegisterLocationCatalogEntriesOffset =
+      kEncodingInfoOffset + sizeof(uint16_t);
+  static constexpr int kNumberOfStackMapsOffset =
+      kNumberOfDexRegisterLocationCatalogEntriesOffset + sizeof(uint32_t);
   static constexpr int kStackMaskSizeOffset = kNumberOfStackMapsOffset + sizeof(uint32_t);
   static constexpr int kFixedSize = kStackMaskSizeOffset + sizeof(uint32_t);
 
   static constexpr int kHasInlineInfoBitOffset = (kEncodingInfoOffset * kBitsPerByte);
-  static constexpr int kHasSmallInlineInfoBitOffset = kHasInlineInfoBitOffset + 1;
-  static constexpr int kHasSmallDexRegisterMapBitOffset = kHasSmallInlineInfoBitOffset + 1;
-  static constexpr int kHasSmallDexPcBitOffset = kHasSmallDexRegisterMapBitOffset + 1;
-  static constexpr int kHasSmallNativePcBitOffset = kHasSmallDexPcBitOffset + 1;
+  static constexpr int kInlineInfoBitOffset = kHasInlineInfoBitOffset + 1;
+  static constexpr int kDexRegisterMapBitOffset = kInlineInfoBitOffset + 3;
+  static constexpr int kDexPcBitOffset = kDexRegisterMapBitOffset + 3;
+  static constexpr int kNativePcBitOffset = kDexPcBitOffset + 3;
+  static constexpr int kRegisterMaskBitOffset = kNativePcBitOffset + 3;
 
   MemoryRegion GetStackMaps() const {
     return region_.size() == 0
         ? MemoryRegion()
-        : region_.Subregion(kFixedSize, StackMapsSize());
+        : region_.Subregion(GetStackMapsOffset(), GetStackMapsSize());
   }
 
-  // Compute the size of a Dex register map starting at offset `origin` in
-  // `region_` and containing `number_of_dex_registers` locations.
-  size_t ComputeDexRegisterMapSize(uint32_t origin, uint32_t number_of_dex_registers) const {
-    // TODO: Ideally, we would like to use art::DexRegisterMap::Size or
-    // art::DexRegisterMap::FindLocationOffset, but the DexRegisterMap is not
-    // yet built.  Try to factor common code.
-    size_t offset =
-        origin + DexRegisterMap::GetDexRegisterMapLocationsOffset(number_of_dex_registers);
+  // Compute the size of the Dex register map associated to the stack map at
+  // `dex_register_map_offset_in_code_info`.
+  size_t ComputeDexRegisterMapSizeOf(uint32_t dex_register_map_offset_in_code_info,
+                                     uint16_t number_of_dex_registers) const {
+    // Offset where the actual mapping data starts within art::DexRegisterMap.
+    size_t location_mapping_data_offset_in_dex_register_map =
+        DexRegisterMap::GetLocationMappingDataOffset(number_of_dex_registers);
+    // Create a temporary art::DexRegisterMap to be able to call
+    // art::DexRegisterMap::GetNumberOfLiveDexRegisters and
+    DexRegisterMap dex_register_map_without_locations(
+        MemoryRegion(region_.Subregion(dex_register_map_offset_in_code_info,
+                                       location_mapping_data_offset_in_dex_register_map)));
+    size_t number_of_live_dex_registers =
+        dex_register_map_without_locations.GetNumberOfLiveDexRegisters(number_of_dex_registers);
+    size_t location_mapping_data_size_in_bits =
+        DexRegisterMap::SingleEntrySizeInBits(GetNumberOfDexRegisterLocationCatalogEntries())
+        * number_of_live_dex_registers;
+    size_t location_mapping_data_size_in_bytes =
+        RoundUp(location_mapping_data_size_in_bits, kBitsPerByte) / kBitsPerByte;
+    size_t dex_register_map_size =
+        location_mapping_data_offset_in_dex_register_map + location_mapping_data_size_in_bytes;
+    return dex_register_map_size;
+  }
 
-    // Create a temporary DexRegisterMap to be able to call DexRegisterMap.IsDexRegisterLive.
-    DexRegisterMap only_live_mask(MemoryRegion(region_.Subregion(origin, offset - origin)));
+  // Compute the size of a Dex register location catalog starting at offset `origin`
+  // in `region_` and containing `number_of_dex_locations` entries.
+  size_t ComputeDexRegisterLocationCatalogSize(uint32_t origin,
+                                               uint32_t number_of_dex_locations) const {
+    // TODO: Ideally, we would like to use art::DexRegisterLocationCatalog::Size or
+    // art::DexRegisterLocationCatalog::FindLocationOffset, but the
+    // DexRegisterLocationCatalog is not yet built.  Try to factor common code.
+    size_t offset = origin + DexRegisterLocationCatalog::kFixedSize;
 
-    // Skip the first `number_of_dex_registers - 1` entries.
-    for (uint16_t i = 0; i < number_of_dex_registers; ++i) {
-      if (only_live_mask.IsDexRegisterLive(i)) {
-        // Read the first next byte and inspect its first 3 bits to decide
-        // whether it is a short or a large location.
-        DexRegisterMap::ShortLocation first_byte =
-            region_.LoadUnaligned<DexRegisterMap::ShortLocation>(offset);
-        DexRegisterLocation::Kind kind =
-            DexRegisterMap::ExtractKindFromShortLocation(first_byte);
-        if (DexRegisterLocation::IsShortLocationKind(kind)) {
-          // Short location.  Skip the current byte.
-          offset += DexRegisterMap::SingleShortEntrySize();
-        } else {
-          // Large location.  Skip the 5 next bytes.
-          offset += DexRegisterMap::SingleLargeEntrySize();
-        }
+    // Skip the first `number_of_dex_locations - 1` entries.
+    for (uint16_t i = 0; i < number_of_dex_locations; ++i) {
+      // Read the first next byte and inspect its first 3 bits to decide
+      // whether it is a short or a large location.
+      DexRegisterLocationCatalog::ShortLocation first_byte =
+          region_.LoadUnaligned<DexRegisterLocationCatalog::ShortLocation>(offset);
+      DexRegisterLocation::Kind kind =
+          DexRegisterLocationCatalog::ExtractKindFromShortLocation(first_byte);
+      if (DexRegisterLocation::IsShortLocationKind(kind)) {
+        // Short location.  Skip the current byte.
+        offset += DexRegisterLocationCatalog::SingleShortEntrySize();
+      } else {
+        // Large location.  Skip the 5 next bytes.
+        offset += DexRegisterLocationCatalog::SingleLargeEntrySize();
       }
     }
     size_t size = offset - origin;
diff --git a/runtime/trace.cc b/runtime/trace.cc
index 3734903..ea0a642 100644
--- a/runtime/trace.cc
+++ b/runtime/trace.cc
@@ -328,7 +328,7 @@
 }
 
 void Trace::Start(const char* trace_filename, int trace_fd, int buffer_size, int flags,
-                  bool direct_to_ddms, bool sampling_enabled, int interval_us) {
+                  TraceOutputMode output_mode, TraceMode trace_mode, int interval_us) {
   Thread* self = Thread::Current();
   {
     MutexLock mu(self, *Locks::trace_lock_);
@@ -339,7 +339,7 @@
   }
 
   // Check interval if sampling is enabled
-  if (sampling_enabled && interval_us <= 0) {
+  if (trace_mode == TraceMode::kSampling && interval_us <= 0) {
     LOG(ERROR) << "Invalid sampling interval: " << interval_us;
     ScopedObjectAccess soa(self);
     ThrowRuntimeException("Invalid sampling interval: %d", interval_us);
@@ -348,7 +348,7 @@
 
   // Open trace file if not going directly to ddms.
   std::unique_ptr<File> trace_file;
-  if (!direct_to_ddms) {
+  if (output_mode != TraceOutputMode::kDDMS) {
     if (trace_fd < 0) {
       trace_file.reset(OS::CreateEmptyFile(trace_filename));
     } else {
@@ -377,8 +377,8 @@
       LOG(ERROR) << "Trace already in progress, ignoring this request";
     } else {
       enable_stats = (flags && kTraceCountAllocs) != 0;
-      the_trace_ = new Trace(trace_file.release(), buffer_size, flags, sampling_enabled);
-      if (sampling_enabled) {
+      the_trace_ = new Trace(trace_file.release(), buffer_size, flags, trace_mode);
+      if (trace_mode == TraceMode::kSampling) {
         CHECK_PTHREAD_CALL(pthread_create, (&sampling_pthread_, NULL, &RunSamplingThread,
                                             reinterpret_cast<void*>(interval_us)),
                                             "Sampling profiler thread");
@@ -427,7 +427,7 @@
     stop_alloc_counting = (the_trace->flags_ & kTraceCountAllocs) != 0;
     the_trace->FinishTracing();
 
-    if (the_trace->sampling_enabled_) {
+    if (the_trace->trace_mode_ == TraceMode::kSampling) {
       MutexLock mu(Thread::Current(), *Locks::thread_list_lock_);
       runtime->GetThreadList()->ForEach(ClearThreadStackTraceAndClockBase, nullptr);
     } else {
@@ -465,16 +465,21 @@
   MutexLock mu(Thread::Current(), *Locks::trace_lock_);
   if (the_trace_ == NULL) {
     return kTracingInactive;
-  } else if (the_trace_->sampling_enabled_) {
-    return kSampleProfilingActive;
   } else {
-    return kMethodTracingActive;
+    switch (the_trace_->trace_mode_) {
+      case TraceMode::kSampling:
+        return kSampleProfilingActive;
+      case TraceMode::kMethodTracing:
+        return kMethodTracingActive;
+    }
+    LOG(FATAL) << "Unreachable";
+    UNREACHABLE();
   }
 }
 
-Trace::Trace(File* trace_file, int buffer_size, int flags, bool sampling_enabled)
+Trace::Trace(File* trace_file, int buffer_size, int flags, TraceMode trace_mode)
     : trace_file_(trace_file), buf_(new uint8_t[buffer_size]()), flags_(flags),
-      sampling_enabled_(sampling_enabled), clock_source_(default_clock_source_),
+      trace_mode_(trace_mode), clock_source_(default_clock_source_),
       buffer_size_(buffer_size), start_time_(MicroTime()),
       clock_overhead_ns_(GetClockOverheadNanoSeconds()), cur_offset_(0), overflow_(false) {
   // Set up the beginning of the trace.
diff --git a/runtime/trace.h b/runtime/trace.h
index dd8186a..80f926f 100644
--- a/runtime/trace.h
+++ b/runtime/trace.h
@@ -51,10 +51,20 @@
     kTraceCountAllocs = 1,
   };
 
+  enum class TraceOutputMode {
+    kFile,
+    kDDMS
+  };
+
+  enum class TraceMode {
+    kMethodTracing,
+    kSampling
+  };
+
   static void SetDefaultClockSource(TraceClockSource clock_source);
 
   static void Start(const char* trace_filename, int trace_fd, int buffer_size, int flags,
-                    bool direct_to_ddms, bool sampling_enabled, int interval_us)
+                    TraceOutputMode output_mode, TraceMode trace_mode, int interval_us)
       LOCKS_EXCLUDED(Locks::mutator_lock_,
                      Locks::thread_list_lock_,
                      Locks::thread_suspend_count_lock_,
@@ -107,7 +117,7 @@
   static void StoreExitingThreadInfo(Thread* thread);
 
  private:
-  explicit Trace(File* trace_file, int buffer_size, int flags, bool sampling_enabled);
+  explicit Trace(File* trace_file, int buffer_size, int flags, TraceMode trace_mode);
 
   // The sampling interval in microseconds is passed as an argument.
   static void* RunSamplingThread(void* arg) LOCKS_EXCLUDED(Locks::trace_lock_);
@@ -148,7 +158,7 @@
   const int flags_;
 
   // True if traceview should sample instead of instrumenting method entry/exit.
-  const bool sampling_enabled_;
+  const TraceMode trace_mode_;
 
   const TraceClockSource clock_source_;
 
diff --git a/runtime/verifier/method_verifier.cc b/runtime/verifier/method_verifier.cc
index 988fc0e..1d04192 100644
--- a/runtime/verifier/method_verifier.cc
+++ b/runtime/verifier/method_verifier.cc
@@ -3919,7 +3919,7 @@
     {
       StackHandleScope<1> hs(self_);
       HandleWrapper<mirror::ArtField> h_field(hs.NewHandleWrapper(&field));
-      field_type_class = h_field->GetType(can_load_classes_);
+      field_type_class = can_load_classes_ ? h_field->GetType<true>() : h_field->GetType<false>();
     }
     if (field_type_class != nullptr) {
       field_type = &reg_types_.FromClass(field->GetTypeDescriptor(), field_type_class,
@@ -4035,7 +4035,7 @@
     {
       StackHandleScope<1> hs(Thread::Current());
       HandleWrapper<mirror::ArtField> h_field(hs.NewHandleWrapper(&field));
-      field_type_class = h_field->GetType(can_load_classes_);
+      field_type_class = can_load_classes_ ? h_field->GetType<true>() : h_field->GetType<false>();
     }
 
     if (field_type_class != nullptr) {
diff --git a/runtime/well_known_classes.cc b/runtime/well_known_classes.cc
index 00b4cef..d389244 100644
--- a/runtime/well_known_classes.cc
+++ b/runtime/well_known_classes.cc
@@ -109,7 +109,6 @@
 jfieldID WellKnownClasses::java_lang_Throwable_stackState;
 jfieldID WellKnownClasses::java_lang_Throwable_suppressedExceptions;
 jfieldID WellKnownClasses::java_lang_reflect_AbstractMethod_artMethod;
-jfieldID WellKnownClasses::java_lang_reflect_Field_artField;
 jfieldID WellKnownClasses::java_lang_reflect_Proxy_h;
 jfieldID WellKnownClasses::java_nio_DirectByteBuffer_capacity;
 jfieldID WellKnownClasses::java_nio_DirectByteBuffer_effectiveDirectAddress;
@@ -244,7 +243,6 @@
   java_lang_Throwable_stackState = CacheField(env, java_lang_Throwable, false, "stackState", "Ljava/lang/Object;");
   java_lang_Throwable_suppressedExceptions = CacheField(env, java_lang_Throwable, false, "suppressedExceptions", "Ljava/util/List;");
   java_lang_reflect_AbstractMethod_artMethod = CacheField(env, java_lang_reflect_AbstractMethod, false, "artMethod", "Ljava/lang/reflect/ArtMethod;");
-  java_lang_reflect_Field_artField = CacheField(env, java_lang_reflect_Field, false, "artField", "Ljava/lang/reflect/ArtField;");
   java_lang_reflect_Proxy_h = CacheField(env, java_lang_reflect_Proxy, false, "h", "Ljava/lang/reflect/InvocationHandler;");
   java_nio_DirectByteBuffer_capacity = CacheField(env, java_nio_DirectByteBuffer, false, "capacity", "I");
   java_nio_DirectByteBuffer_effectiveDirectAddress = CacheField(env, java_nio_DirectByteBuffer, false, "effectiveDirectAddress", "J");
diff --git a/runtime/well_known_classes.h b/runtime/well_known_classes.h
index 1a4f0f8..2df1c0e 100644
--- a/runtime/well_known_classes.h
+++ b/runtime/well_known_classes.h
@@ -103,7 +103,6 @@
   static jfieldID dalvik_system_DexPathList__Element_dexFile;
   static jfieldID dalvik_system_PathClassLoader_pathList;
   static jfieldID java_lang_reflect_AbstractMethod_artMethod;
-  static jfieldID java_lang_reflect_Field_artField;
   static jfieldID java_lang_reflect_Proxy_h;
   static jfieldID java_lang_Thread_daemon;
   static jfieldID java_lang_Thread_group;
diff --git a/test/046-reflect/src/Main.java b/test/046-reflect/src/Main.java
index 3fe3881..59f7001 100644
--- a/test/046-reflect/src/Main.java
+++ b/test/046-reflect/src/Main.java
@@ -696,27 +696,34 @@
     private static void checkGetDeclaredConstructor() {
         try {
             Method.class.getDeclaredConstructor().setAccessible(true);
-            System.out.print("Didn't get an exception from method getDeclaredConstructor");
+            System.out.print("Didn't get an exception from Method.class.getDeclaredConstructor().setAccessible");
+        } catch (SecurityException e) {
         } catch (NoSuchMethodException e) {
         } catch (Exception e) {
             System.out.print(e);
         }
         try {
             Field.class.getDeclaredConstructor().setAccessible(true);
-            System.out.print("Didn't get an exception from field getDeclaredConstructor");
+            System.out.print("Didn't get an exception from Field.class.getDeclaredConstructor().setAccessible");
+        } catch (SecurityException e) {
         } catch (NoSuchMethodException e) {
         } catch (Exception e) {
             System.out.print(e);
         }
         try {
             Class.class.getDeclaredConstructor().setAccessible(true);
-            System.out.print("Didn't get an exception from class getDeclaredConstructor()");
+            System.out.print("Didn't get an exception from Class.class.getDeclaredConstructor().setAccessible");
         } catch (SecurityException e) {
+        } catch (NoSuchMethodException e) {
         } catch (Exception e) {
             System.out.print(e);
         }
     }
 
+    static void checkPrivateFieldAccess() {
+        (new OtherClass()).test();
+    }
+
     public static void main(String[] args) throws Exception {
         Main test = new Main();
         test.run();
@@ -730,6 +737,7 @@
         checkUnique();
         checkParametrizedTypeEqualsAndHashCode();
         checkGenericArrayTypeEqualsAndHashCode();
+        checkPrivateFieldAccess();
     }
 }
 
@@ -801,41 +809,41 @@
 }
 
 class FieldNoisyInit {
-  static {
-    System.out.println("FieldNoisyInit is initializing");
-    //Throwable th = new Throwable();
-    //th.printStackTrace();
-  }
+    static {
+        System.out.println("FieldNoisyInit is initializing");
+        //Throwable th = new Throwable();
+        //th.printStackTrace();
+    }
 }
 
 class FieldNoisyInitUser {
-  static {
-    System.out.println("FieldNoisyInitUser is initializing");
-  }
-  public static int staticField;
-  public static FieldNoisyInit noisy;
+    static {
+        System.out.println("FieldNoisyInitUser is initializing");
+    }
+    public static int staticField;
+    public static FieldNoisyInit noisy;
 }
 
 class MethodNoisyInit {
-  static {
-    System.out.println("MethodNoisyInit is initializing");
-    //Throwable th = new Throwable();
-    //th.printStackTrace();
-  }
+    static {
+        System.out.println("MethodNoisyInit is initializing");
+        //Throwable th = new Throwable();
+        //th.printStackTrace();
+    }
 }
 
 class MethodNoisyInitUser {
-  static {
-    System.out.println("MethodNoisyInitUser is initializing");
-  }
-  public static void staticMethod() {}
-  public void createMethodNoisyInit(MethodNoisyInit ni) {}
+    static {
+        System.out.println("MethodNoisyInitUser is initializing");
+    }
+    public static void staticMethod() {}
+    public void createMethodNoisyInit(MethodNoisyInit ni) {}
 }
 
 class Thrower {
-  public Thrower() throws UnsupportedOperationException {
-    throw new UnsupportedOperationException();
-  }
+    public Thrower() throws UnsupportedOperationException {
+        throw new UnsupportedOperationException();
+    }
 }
 
 class ParametrizedTypeTest {
@@ -847,3 +855,17 @@
     public void aMethod(T[] names) {}
     public void aMethodIdentical(T[] names) {}
 }
+
+class OtherClass {
+    private static final long LONG = 1234;
+    public void test() {
+        try {
+            Field field = getClass().getDeclaredField("LONG");
+            if (1234 != field.getLong(null)) {
+              System.out.println("ERROR: values don't match");
+            }
+        } catch (Exception e) {
+            System.out.println(e);
+        }
+    }
+}
\ No newline at end of file
diff --git a/test/467-regalloc-pair/expected.txt b/test/467-regalloc-pair/expected.txt
new file mode 100644
index 0000000..da39d9d
--- /dev/null
+++ b/test/467-regalloc-pair/expected.txt
@@ -0,0 +1 @@
+In interface
diff --git a/test/467-regalloc-pair/info.txt b/test/467-regalloc-pair/info.txt
new file mode 100644
index 0000000..882a29c
--- /dev/null
+++ b/test/467-regalloc-pair/info.txt
@@ -0,0 +1,2 @@
+Regression test for optimizing's register allocator
+that used to trip when compiling TestCase.testCase on x86.
diff --git a/test/467-regalloc-pair/smali/TestCase.smali b/test/467-regalloc-pair/smali/TestCase.smali
new file mode 100644
index 0000000..a3101fe
--- /dev/null
+++ b/test/467-regalloc-pair/smali/TestCase.smali
@@ -0,0 +1,59 @@
+# Copyright (C) 2015 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.
+
+.class public LTestCase;
+
+.super Ljava/lang/Object;
+
+.method public static testCase([BLMain;)V
+    .registers 12
+    const/4 v2, 0
+    array-length v0, v10
+    div-int/lit8 v0, v0, 7
+    invoke-static {v2, v0}, Ljava/lang/Math;->max(II)I
+    move-result v7
+    move v6, v2
+    move v3, v2
+    :label5
+    if-ge v6, v7, :label1
+    const-wide/16 v0, 0
+    move-wide v4, v0
+    move v1, v2
+    move v0, v3
+    :label4
+    const/4 v3, 6
+    if-ge v1, v3, :label2
+    const/16 v3, 8
+    shl-long/2addr v4, v3
+    add-int/lit8 v3, v0, 1
+    aget-byte v0, v10, v0
+    if-gez v0, :label3
+    add-int/lit16 v0, v0, 256
+    :label3
+    int-to-long v8, v0
+    or-long/2addr v4, v8
+    add-int/lit8 v0, v1, 1
+    move v1, v0
+    move v0, v3
+    goto :label4
+    :label2
+    add-int/lit8 v3, v0, 1
+    aget-byte v0, v10, v0
+    invoke-interface {v11, v4, v5, v0}, LItf;->invokeInterface(JI)V
+    add-int/lit8 v0, v6, 1
+    move v6, v0
+    goto :label5
+    :label1
+    return-void
+.end method
diff --git a/test/467-regalloc-pair/src/Main.java b/test/467-regalloc-pair/src/Main.java
new file mode 100644
index 0000000..aac07fd
--- /dev/null
+++ b/test/467-regalloc-pair/src/Main.java
@@ -0,0 +1,37 @@
+/*
+ * Copyright (C) 2015 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.
+ */
+
+import java.lang.reflect.Method;
+
+interface Itf {
+  public void invokeInterface(long l, int i);
+}
+
+public class Main implements Itf {
+
+  // Workaround for b/18051191.
+  class InnerClass {}
+
+  public static void main(String[] args) throws Exception {
+    Class<?> c = Class.forName("TestCase");
+    Method m = c.getMethod("testCase", byte[].class, Main.class);
+    m.invoke(null, new byte[] { 0, 1, 2, 3, 4, 5, 6, 7 }, new Main());
+  }
+
+  public void invokeInterface(long l, int i) {
+    System.out.println("In interface");
+  }
+}
diff --git a/test/468-bool-simplifier-regression/expected.txt b/test/468-bool-simplifier-regression/expected.txt
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/test/468-bool-simplifier-regression/expected.txt
diff --git a/test/468-bool-simplifier-regression/info.txt b/test/468-bool-simplifier-regression/info.txt
new file mode 100644
index 0000000..0a46584
--- /dev/null
+++ b/test/468-bool-simplifier-regression/info.txt
@@ -0,0 +1,2 @@
+Regression test for optimizing's boolean simplifier
+that used to trip when a boolean value was the input of an If.
diff --git a/test/468-bool-simplifier-regression/smali/TestCase.smali b/test/468-bool-simplifier-regression/smali/TestCase.smali
new file mode 100644
index 0000000..f36304d
--- /dev/null
+++ b/test/468-bool-simplifier-regression/smali/TestCase.smali
@@ -0,0 +1,32 @@
+# Copyright (C) 2015 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.
+
+.class public LTestCase;
+
+.super Ljava/lang/Object;
+
+.field public static value:Z
+
+.method public static testCase()Z
+    .registers 2
+    sget-boolean v0, LTestCase;->value:Z
+    const/4 v1, 1
+    if-eq v0, v1, :label1
+    const/4 v1, 1
+    goto :label2
+    :label1
+    const/4 v1, 0
+    :label2
+    return v1
+.end method
diff --git a/test/468-bool-simplifier-regression/src/Main.java b/test/468-bool-simplifier-regression/src/Main.java
new file mode 100644
index 0000000..1dd27c9
--- /dev/null
+++ b/test/468-bool-simplifier-regression/src/Main.java
@@ -0,0 +1,37 @@
+/*
+ * Copyright (C) 2015 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.
+ */
+
+import java.lang.reflect.*;
+
+public class Main {
+  public static boolean runTest(boolean input) throws Exception {
+    Class<?> c = Class.forName("TestCase");
+    Method m = c.getMethod("testCase");
+    Field f = c.getField("value");
+    f.set(null, (Boolean) input);
+    return (Boolean) m.invoke(null);
+  }
+
+  public static void main(String[] args) throws Exception {
+    if (runTest(true) != false) {
+      throw new Error("Expected false, got true");
+    }
+
+    if (runTest(false) != true) {
+      throw new Error("Expected true, got false");
+    }
+  }
+}
diff --git a/tools/run-jdwp-tests.sh b/tools/run-jdwp-tests.sh
index c51bd20..90c01f5 100755
--- a/tools/run-jdwp-tests.sh
+++ b/tools/run-jdwp-tests.sh
@@ -19,6 +19,11 @@
   exit 1
 fi
 
+if [[ $ANDROID_SERIAL == 03a79ae90ae5889b ]] || [[ $ANDROID_SERIAL == HT4CTJT03670 ]] || [[ $ANDROID_SERIAL == HT49CJT00070 ]]; then
+  echo "Not run because of localhost failures. Investigating."
+  exit 0
+fi
+
 # Jar containing all the tests.
 test_jar=out/host/linux-x86/framework/apache-harmony-jdwp-tests-hostdex.jar
 junit_jar=out/host/linux-x86/framework/junit.jar
@@ -35,13 +40,25 @@
 args=$@
 debuggee_args="-Xcompiler-option --compiler-backend=Optimizing -Xcompiler-option --debuggable"
 device_dir="--device-dir=/data/local/tmp"
+# We use the art script on target to ensure the runner and the debuggee share the same
+# image.
+vm_command="--vm-command=$art"
+image_compiler_option=""
 
 while true; do
   if [[ "$1" == "--mode=host" ]]; then
-    art="art"
+    # Specify bash explicitly since the art script cannot, since it has to run on the device
+    # with mksh.
+    art="bash out/host/linux-x86/bin/art"
     # We force generation of a new image to avoid build-time and run-time classpath differences.
     image="-Ximage:/system/non/existent"
+    # We do not need a device directory on host.
     device_dir=""
+    # Vogar knows which VM to use on host.
+    vm_command=""
+    # We only compile the image on the host. Note that not providing this option
+    # puts us below the adb command limit for vogar.
+    image_compiler_option="--vm-arg -Ximage-compiler-option --vm-arg --debuggable"
     shift
   elif [[ $1 == -Ximage:* ]]; then
     image="$1"
@@ -54,15 +71,16 @@
 done
 
 # Run the tests using vogar.
-vogar --vm-command=$art \
+vogar $vm_command \
       --vm-arg $image \
+      --verbose \
       $args \
       $device_dir \
-      --vm-arg -Ximage-compiler-option \
-      --vm-arg --debuggable \
+      $image_compiler_option \
       --timeout 600 \
       --vm-arg -Djpda.settings.verbose=true \
       --vm-arg -Djpda.settings.syncPort=34016 \
+      --vm-arg -Djpda.settings.transportAddress=127.0.0.1:55107 \
       --vm-arg -Djpda.settings.debuggeeJavaPath="$art $image $debuggee_args" \
       --classpath $test_jar \
       --classpath $junit_jar \