More target-independence

Continuing to move target-specific code from the Arm
code generator into the independent realm.  This will be
done in multiple small steps.

In this CL, the focus is on unifying the LIR data structure and
various enums that don't really need to be target specific. Also
creates two new shared source files: GenCommon.cc (to hold
top-level code generation functions) and GenInvoke.cc (which
is likely to be shared only by the Arm and Mips targets).

Also added is a makefile hack to build for Mips (which we'll
eventually remove when the compiler support multiple targets
via the command line) and various minor cleanups.

Overall, this CL moves more than 3,000 lines of code from
target dependent to target independent.

Change-Id: I431ca4ae728100ed7d0e9d83a966a3f789f731b1
diff --git a/build/Android.common.mk b/build/Android.common.mk
index 3f6b84b..05228c7 100644
--- a/build/Android.common.mk
+++ b/build/Android.common.mk
@@ -21,6 +21,13 @@
 ART_USE_LLVM_COMPILER := false
 endif
 
+# Build for MIPS target (temporary)
+ifneq ($(wildcard art/MIPS_TARGET),)
+ART_MIPS_TARGET := true
+else
+ART_MIPS_TARGET := false
+endif
+
 ifeq ($(ART_USE_LLVM_COMPILER),true)
 LLVM_ROOT_PATH := external/llvm
 include $(LLVM_ROOT_PATH)/llvm.mk
@@ -60,6 +67,11 @@
 art_cflags += -DART_USE_LLVM_COMPILER=1
 endif
 
+# (temp) for testing
+ifeq ($(ART_MIPS_TARGET),true)
+art_cflags += -D__mips_hard_float
+endif
+
 ifeq ($(HOST_OS),linux)
   art_non_debug_cflags := \
 	-Wframe-larger-than=1728
@@ -224,12 +236,21 @@
 	src/compiler/SSATransformation.cc \
 	src/compiler/Utility.cc \
 	src/compiler/codegen/RallocUtil.cc \
+	src/jni_internal_arm.cc \
+	src/jni_internal_x86.cc
+ifeq ($(ART_MIPS_TARGET),true)
+LIBART_COMMON_SRC_FILES += \
+	src/compiler/codegen/mips/ArchUtility.cc \
+	src/compiler/codegen/mips/MipsRallocUtil.cc \
+	src/compiler/codegen/mips/Assemble.cc \
+	src/compiler/codegen/mips/mips/Codegen.cc
+else
+LIBART_COMMON_SRC_FILES += \
 	src/compiler/codegen/arm/ArchUtility.cc \
 	src/compiler/codegen/arm/ArmRallocUtil.cc \
 	src/compiler/codegen/arm/Assemble.cc \
-	src/compiler/codegen/arm/armv7-a/Codegen.cc \
-	src/jni_internal_arm.cc \
-	src/jni_internal_x86.cc
+	src/compiler/codegen/arm/armv7-a/Codegen.cc
+endif
 endif
 
 LIBART_TARGET_SRC_FILES := \
diff --git a/src/compiler/Compiler.h b/src/compiler/Compiler.h
index d07fe18..c7a1ac3 100644
--- a/src/compiler/Compiler.h
+++ b/src/compiler/Compiler.h
@@ -178,13 +178,11 @@
 
 void oatInit(CompilationUnit* cUnit, const Compiler& compiler);
 bool oatArchInit(void);
-void oatArchDump(void);
 bool oatStartup(void);
 void oatShutdown(void);
 CompiledMethod* oatCompileMethod(Compiler& compiler, bool is_direct,
                                  uint32_t method_idx, const ClassLoader* class_loader,
                                  const DexFile& dex_file, OatInstructionSetType);
-void oatDumpStats(void);
 void oatScanAllClassPointers(void (*callback)(void* ptr));
 void oatInitializeSSAConversion(struct CompilationUnit* cUnit);
 int oatConvertSSARegToDalvik(const struct CompilationUnit* cUnit, int ssaReg);
diff --git a/src/compiler/CompilerIR.h b/src/compiler/CompilerIR.h
index 66cc322..34ccfb4 100644
--- a/src/compiler/CompilerIR.h
+++ b/src/compiler/CompilerIR.h
@@ -20,9 +20,21 @@
 #include "codegen/Optimizer.h"
 #include "CompilerUtility.h"
 #include <vector>
+#include "oat_compilation_unit.h"
 
 namespace art {
 
+#define SLOW_FIELD_PATH (cUnit->enableDebug & (1 << kDebugSlowFieldPath))
+#define SLOW_INVOKE_PATH (cUnit->enableDebug & (1 << kDebugSlowInvokePath))
+#define SLOW_STRING_PATH (cUnit->enableDebug & (1 << kDebugSlowStringPath))
+#define SLOW_TYPE_PATH (cUnit->enableDebug & (1 << kDebugSlowTypePath))
+#define EXERCISE_SLOWEST_FIELD_PATH (cUnit->enableDebug & \
+    (1 << kDebugSlowestFieldPath))
+#define EXERCISE_SLOWEST_STRING_PATH (cUnit->enableDebug & \
+    (1 << kDebugSlowestStringPath))
+#define EXERCISE_RESOLVE_METHOD (cUnit->enableDebug & \
+    (1 << kDebugExerciseResolveMethod))
+
 typedef enum RegisterClass {
     kCoreReg,
     kFPReg,
@@ -108,12 +120,31 @@
     kCatchEntry,
 } BBType;
 
+/* Utility macros to traverse the LIR list */
+#define NEXT_LIR(lir) (lir->next)
+#define PREV_LIR(lir) (lir->prev)
+
+#define NEXT_LIR_LVALUE(lir) (lir)->next
+#define PREV_LIR_LVALUE(lir) (lir)->prev
+
 typedef struct LIR {
     int offset;                        // Offset of this instruction
     int dalvikOffset;                  // Offset of Dalvik opcode
     struct LIR* next;
     struct LIR* prev;
     struct LIR* target;
+    int opcode;
+    int operands[4];            // [0..3] = [dest, src1, src2, extra]
+    struct {
+        bool isNop:1;           // LIR is optimized away
+        bool pcRelFixup:1;      // May need pc-relative fixup
+        unsigned int age:4;     // default is 0, set lazily by the optimizer
+        unsigned int size:4;    // in bytes
+        unsigned int unused:22;
+    } flags;
+    int aliasInfo;              // For Dalvik register & litpool disambiguation
+    u8 useMask;                 // Resource mask for use
+    u8 defMask;                 // Resource mask for def
 } LIR;
 
 enum ExtendedMIROpcode {
@@ -381,6 +412,71 @@
     kSignedByte,
 } OpSize;
 
+typedef enum OpKind {
+    kOpMov,
+    kOpMvn,
+    kOpCmp,
+    kOpLsl,
+    kOpLsr,
+    kOpAsr,
+    kOpRor,
+    kOpNot,
+    kOpAnd,
+    kOpOr,
+    kOpXor,
+    kOpNeg,
+    kOpAdd,
+    kOpAdc,
+    kOpSub,
+    kOpSbc,
+    kOpRsub,
+    kOpMul,
+    kOpDiv,
+    kOpRem,
+    kOpBic,
+    kOpCmn,
+    kOpTst,
+    kOpBkpt,
+    kOpBlx,
+    kOpPush,
+    kOpPop,
+    kOp2Char,
+    kOp2Short,
+    kOp2Byte,
+    kOpCondBr,
+    kOpUncondBr,
+    kOpInvalid,
+} OpKind;
+
+typedef enum ConditionCode {
+    kCondEq,
+    kCondNe,
+    kCondCs,
+    kCondCc,
+    kCondMi,
+    kCondPl,
+    kCondVs,
+    kCondVc,
+    kCondHi,
+    kCondLs,
+    kCondGe,
+    kCondLt,
+    kCondGt,
+    kCondLe,
+    kCondAl,
+    kCondNv,
+} ConditionCode;
+
+typedef enum ThrowKind {
+    kThrowNullPointer,
+    kThrowDivZero,
+    kThrowArrayBounds,
+    kThrowVerificationError,
+    kThrowNegArraySize,
+    kThrowNoSuchMethod,
+    kThrowStackOverflow,
+} ThrowKind;
+
 BasicBlock* oatNewBB(CompilationUnit* cUnit, BBType blockType, int blockId);
 
 void oatAppendMIR(BasicBlock* bb, MIR* mir);
diff --git a/src/compiler/Dalvik.h b/src/compiler/Dalvik.h
index 4753910..9af49aa 100644
--- a/src/compiler/Dalvik.h
+++ b/src/compiler/Dalvik.h
@@ -55,13 +55,6 @@
 #include "DexOpcodes.h"
 #include "InstrUtils.h"
 
-// use to switch visibility on DCHECK tracebacks
-#if 1
-#define STATIC
-#else
-#define STATIC static
-#endif
-
 #include "Compiler.h"
 
 #endif
diff --git a/src/compiler/Dataflow.cc b/src/compiler/Dataflow.cc
index 4572857..733552c 100644
--- a/src/compiler/Dataflow.cc
+++ b/src/compiler/Dataflow.cc
@@ -917,8 +917,7 @@
 /*
  * Dalvik instruction disassembler with optional SSA printing.
  */
-char* oatFullDisassembler(CompilationUnit* cUnit,
-                          const MIR* mir)
+char* oatFullDisassembler(CompilationUnit* cUnit, const MIR* mir)
 {
     char buffer[256];
     char operand0[32], operand1[32];
@@ -1084,9 +1083,9 @@
 }
 
 /* Any register that is used before being defined is considered live-in */
-STATIC inline void handleLiveInUse(CompilationUnit* cUnit, ArenaBitVector* useV,
-                                   ArenaBitVector* defV,
-                                   ArenaBitVector* liveInV, int dalvikRegId)
+inline void handleLiveInUse(CompilationUnit* cUnit, ArenaBitVector* useV,
+                            ArenaBitVector* defV, ArenaBitVector* liveInV,
+                            int dalvikRegId)
 {
     oatSetBit(cUnit, useV, dalvikRegId);
     if (!oatIsBitSet(defV, dalvikRegId)) {
@@ -1095,8 +1094,8 @@
 }
 
 /* Mark a reg as being defined */
-STATIC inline void handleDef(CompilationUnit* cUnit, ArenaBitVector* defV,
-                             int dalvikRegId)
+inline void handleDef(CompilationUnit* cUnit, ArenaBitVector* defV,
+                      int dalvikRegId)
 {
     oatSetBit(cUnit, defV, dalvikRegId);
 }
@@ -1166,8 +1165,8 @@
 }
 
 /* Find out the latest SSA register for a given Dalvik register */
-STATIC void handleSSAUse(CompilationUnit* cUnit, int* uses, int dalvikReg,
-                         int regIndex)
+void handleSSAUse(CompilationUnit* cUnit, int* uses, int dalvikReg,
+                  int regIndex)
 {
     int encodedValue = cUnit->dalvikToSSAMap[dalvikReg];
     int ssaReg = DECODE_REG(encodedValue);
@@ -1175,8 +1174,8 @@
 }
 
 /* Setup a new SSA register for a given Dalvik register */
-STATIC void handleSSADef(CompilationUnit* cUnit, int* defs, int dalvikReg,
-                         int regIndex)
+void handleSSADef(CompilationUnit* cUnit, int* defs, int dalvikReg,
+                  int regIndex)
 {
     int ssaReg = cUnit->numSSARegs++;
     /* Bump up the subscript */
@@ -1192,7 +1191,7 @@
 }
 
 /* Look up new SSA names for format_35c instructions */
-STATIC void dataFlowSSAFormat35C(CompilationUnit* cUnit, MIR* mir)
+void dataFlowSSAFormat35C(CompilationUnit* cUnit, MIR* mir)
 {
     DecodedInstruction *dInsn = &mir->dalvikInsn;
     int numUses = dInsn->vA;
@@ -1211,7 +1210,7 @@
 }
 
 /* Look up new SSA names for format_3rc instructions */
-STATIC void dataFlowSSAFormat3RC(CompilationUnit* cUnit, MIR* mir)
+void dataFlowSSAFormat3RC(CompilationUnit* cUnit, MIR* mir)
 {
     DecodedInstruction *dInsn = &mir->dalvikInsn;
     int numUses = dInsn->vA;
@@ -1370,7 +1369,7 @@
 }
 
 /* Setup a constant value for opcodes thare have the DF_SETS_CONST attribute */
-STATIC void setConstant(CompilationUnit* cUnit, int ssaReg, int value)
+void setConstant(CompilationUnit* cUnit, int ssaReg, int value)
 {
     oatSetBit(cUnit, cUnit->isConstantV, ssaReg);
     cUnit->constantValues[ssaReg] = value;
@@ -1515,8 +1514,7 @@
 }
 
 /* Clear the visited flag for each BB */
-bool oatClearVisitedFlag(struct CompilationUnit* cUnit,
-                                 struct BasicBlock* bb)
+bool oatClearVisitedFlag(struct CompilationUnit* cUnit, struct BasicBlock* bb)
 {
     bb->visited = false;
     return true;
@@ -1636,8 +1634,8 @@
     }
 }
 
-STATIC bool nullCheckEliminationInit(struct CompilationUnit* cUnit,
-                                     struct BasicBlock* bb)
+bool nullCheckEliminationInit(struct CompilationUnit* cUnit,
+                              struct BasicBlock* bb)
 {
     if (bb->dataFlowInfo == NULL) return false;
     bb->dataFlowInfo->endingNullCheckV =
@@ -1647,8 +1645,7 @@
 }
 
 /* Eliminate unnecessary null checks for a basic block. */
-STATIC bool eliminateNullChecks( struct CompilationUnit* cUnit,
-                                 struct BasicBlock* bb)
+bool eliminateNullChecks( struct CompilationUnit* cUnit, struct BasicBlock* bb)
 {
     if (bb->dataFlowInfo == NULL) return false;
 
diff --git a/src/compiler/Frontend.cc b/src/compiler/Frontend.cc
index 701e245..92ffefc 100644
--- a/src/compiler/Frontend.cc
+++ b/src/compiler/Frontend.cc
@@ -49,7 +49,7 @@
      //(1 << kDebugShowMemoryUsage) |
      0;
 
-STATIC inline bool contentIsInsn(const u2* codePtr) {
+inline bool contentIsInsn(const u2* codePtr) {
     u2 instr = *codePtr;
     Opcode opcode = (Opcode)(instr & 0xff);
 
@@ -63,7 +63,7 @@
 /*
  * Parse an instruction, return the length of the instruction
  */
-STATIC inline int parseInsn(CompilationUnit* cUnit, const u2* codePtr,
+inline int parseInsn(CompilationUnit* cUnit, const u2* codePtr,
                             DecodedInstruction* decInsn, bool printMe)
 {
     // Don't parse instruction data
@@ -85,7 +85,7 @@
 
 #define UNKNOWN_TARGET 0xffffffff
 
-STATIC inline bool isGoto(MIR* insn)
+inline bool isGoto(MIR* insn)
 {
     switch (insn->dalvikInsn.opcode) {
         case OP_GOTO:
@@ -100,7 +100,7 @@
 /*
  * Identify unconditional branch instructions
  */
-STATIC inline bool isUnconditionalBranch(MIR* insn)
+inline bool isUnconditionalBranch(MIR* insn)
 {
     switch (insn->dalvikInsn.opcode) {
         case OP_RETURN_VOID:
@@ -114,10 +114,8 @@
 }
 
 /* Split an existing block from the specified code offset into two */
-STATIC BasicBlock *splitBlock(CompilationUnit* cUnit,
-                              unsigned int codeOffset,
-                              BasicBlock* origBlock,
-                              BasicBlock** immedPredBlockP)
+BasicBlock *splitBlock(CompilationUnit* cUnit, unsigned int codeOffset,
+                       BasicBlock* origBlock, BasicBlock** immedPredBlockP)
 {
     MIR* insn = origBlock->firstMIRInsn;
     while (insn) {
@@ -205,10 +203,8 @@
  * (by the caller)
  * Utilizes a map for fast lookup of the typical cases.
  */
-STATIC BasicBlock *findBlock(CompilationUnit* cUnit,
-                             unsigned int codeOffset,
-                             bool split, bool create,
-                             BasicBlock** immedPredBlockP)
+BasicBlock *findBlock(CompilationUnit* cUnit, unsigned int codeOffset,
+                      bool split, bool create, BasicBlock** immedPredBlockP)
 {
     GrowableList* blockList = &cUnit->blockList;
     BasicBlock* bb;
@@ -404,7 +400,7 @@
 }
 
 /* Verify if all the successor is connected with all the claimed predecessors */
-STATIC bool verifyPredInfo(CompilationUnit* cUnit, BasicBlock* bb)
+bool verifyPredInfo(CompilationUnit* cUnit, BasicBlock* bb)
 {
     GrowableListIterator iter;
 
@@ -446,7 +442,7 @@
 }
 
 /* Identify code range in try blocks and set up the empty catch blocks */
-STATIC void processTryCatchBlocks(CompilationUnit* cUnit)
+void processTryCatchBlocks(CompilationUnit* cUnit)
 {
     const DexFile::CodeItem* code_item = cUnit->code_item;
     int triesSize = code_item->tries_size_;
@@ -484,10 +480,9 @@
 }
 
 /* Process instructions with the kInstrCanBranch flag */
-STATIC BasicBlock* processCanBranch(CompilationUnit* cUnit,
-                                    BasicBlock* curBlock, MIR* insn,
-                                    int curOffset, int width, int flags,
-                                    const u2* codePtr, const u2* codeEnd)
+BasicBlock* processCanBranch(CompilationUnit* cUnit, BasicBlock* curBlock,
+                             MIR* insn, int curOffset, int width, int flags,
+                             const u2* codePtr, const u2* codeEnd)
 {
     int target = curOffset;
     switch (insn->dalvikInsn.opcode) {
@@ -566,8 +561,8 @@
 }
 
 /* Process instructions with the kInstrCanSwitch flag */
-STATIC void processCanSwitch(CompilationUnit* cUnit, BasicBlock* curBlock,
-                             MIR* insn, int curOffset, int width, int flags)
+void processCanSwitch(CompilationUnit* cUnit, BasicBlock* curBlock,
+                      MIR* insn, int curOffset, int width, int flags)
 {
     u2* switchData= (u2 *) (cUnit->insns + curOffset +
                             insn->dalvikInsn.vB);
@@ -654,10 +649,10 @@
 }
 
 /* Process instructions with the kInstrCanThrow flag */
-STATIC void processCanThrow(CompilationUnit* cUnit, BasicBlock* curBlock,
-                            MIR* insn, int curOffset, int width, int flags,
-                            ArenaBitVector* tryBlockAddr, const u2* codePtr,
-                            const u2* codeEnd)
+void processCanThrow(CompilationUnit* cUnit, BasicBlock* curBlock, MIR* insn,
+                     int curOffset, int width, int flags,
+                     ArenaBitVector* tryBlockAddr, const u2* codePtr,
+                     const u2* codeEnd)
 {
     const DexFile::CodeItem* code_item = cUnit->code_item;
 
@@ -735,10 +730,12 @@
 /*
  * Compile a method.
  */
-CompiledMethod* oatCompileMethod(Compiler& compiler, const DexFile::CodeItem* code_item,
+CompiledMethod* oatCompileMethod(Compiler& compiler,
+                                 const DexFile::CodeItem* code_item,
                                  uint32_t access_flags, uint32_t method_idx,
                                  const ClassLoader* class_loader,
-                                 const DexFile& dex_file, InstructionSet insnSet)
+                                 const DexFile& dex_file,
+                                 InstructionSet insnSet)
 {
     VLOG(compiler) << "Compiling " << PrettyMethod(method_idx, dex_file) << "...";
 
diff --git a/src/compiler/Ralloc.cc b/src/compiler/Ralloc.cc
index bf9cb6a7..09c2b7e 100644
--- a/src/compiler/Ralloc.cc
+++ b/src/compiler/Ralloc.cc
@@ -21,7 +21,7 @@
 
 namespace art {
 
-STATIC bool setFp(CompilationUnit* cUnit, int index, bool isFP) {
+bool setFp(CompilationUnit* cUnit, int index, bool isFP) {
     bool change = false;
     if (cUnit->regLocation[index].highWord) {
         return change;
@@ -34,7 +34,7 @@
     return change;
 }
 
-STATIC bool setCore(CompilationUnit* cUnit, int index, bool isCore) {
+bool setCore(CompilationUnit* cUnit, int index, bool isCore) {
     bool change = false;
     if (cUnit->regLocation[index].highWord) {
         return change;
@@ -47,7 +47,7 @@
     return change;
 }
 
-STATIC bool remapNames(CompilationUnit* cUnit, BasicBlock* bb)
+bool remapNames(CompilationUnit* cUnit, BasicBlock* bb)
 {
     if (bb->blockType != kDalvikByteCode && bb->blockType != kEntryBlock &&
         bb->blockType != kExitBlock)
@@ -68,7 +68,7 @@
 }
 
 // Try to find the next move result which might have an FP target
-STATIC SSARepresentation* findMoveResult(MIR* mir)
+SSARepresentation* findMoveResult(MIR* mir)
 {
     SSARepresentation* res = NULL;
     for (; mir; mir = mir->next) {
@@ -86,7 +86,7 @@
  * as it doesn't propagate.  We're guaranteed at least one pass through
  * the cfg.
  */
-STATIC bool inferTypeAndSize(CompilationUnit* cUnit, BasicBlock* bb)
+bool inferTypeAndSize(CompilationUnit* cUnit, BasicBlock* bb)
 {
     MIR *mir;
     bool changed = false;   // Did anything change?
diff --git a/src/compiler/SSATransformation.cc b/src/compiler/SSATransformation.cc
index 99de0a7..352828f 100644
--- a/src/compiler/SSATransformation.cc
+++ b/src/compiler/SSATransformation.cc
@@ -20,7 +20,7 @@
 namespace art {
 
 /* Enter the node to the dfsOrder list then visit its successors */
-STATIC void recordDFSOrders(CompilationUnit* cUnit, BasicBlock* block)
+void recordDFSOrders(CompilationUnit* cUnit, BasicBlock* block)
 {
 
     if (block->visited || block->hidden) return;
@@ -51,7 +51,7 @@
 }
 
 /* Sort the blocks by the Depth-First-Search */
-STATIC void computeDFSOrders(CompilationUnit* cUnit)
+void computeDFSOrders(CompilationUnit* cUnit)
 {
     /* Initialize or reset the DFS preOrder list */
     if (cUnit->dfsOrder.elemList == NULL) {
@@ -83,7 +83,7 @@
  * Mark block bit on the per-Dalvik register vector to denote that Dalvik
  * register idx is defined in BasicBlock bb.
  */
-STATIC bool fillDefBlockMatrix(CompilationUnit* cUnit, BasicBlock* bb)
+bool fillDefBlockMatrix(CompilationUnit* cUnit, BasicBlock* bb)
 {
     if (bb->dataFlowInfo == NULL) return false;
 
@@ -99,7 +99,7 @@
     return true;
 }
 
-STATIC void computeDefBlockMatrix(CompilationUnit* cUnit)
+void computeDefBlockMatrix(CompilationUnit* cUnit)
 {
     int numRegisters = cUnit->numDalvikRegisters;
     /* Allocate numDalvikRegisters bit vector pointers */
@@ -132,7 +132,7 @@
 }
 
 /* Compute the post-order traversal of the CFG */
-STATIC void computeDomPostOrderTraversal(CompilationUnit* cUnit, BasicBlock* bb)
+void computeDomPostOrderTraversal(CompilationUnit* cUnit, BasicBlock* bb)
 {
     ArenaBitVectorIterator bvIterator;
     oatBitVectorIteratorInit(bb->iDominated, &bvIterator);
@@ -157,8 +157,8 @@
     }
 }
 
-STATIC void checkForDominanceFrontier(CompilationUnit* cUnit, BasicBlock* domBB,
-                                      const BasicBlock* succBB)
+void checkForDominanceFrontier(CompilationUnit* cUnit, BasicBlock* domBB,
+                               const BasicBlock* succBB)
 {
     /*
      * TODO - evaluate whether phi will ever need to be inserted into exit
@@ -172,7 +172,7 @@
 }
 
 /* Worker function to compute the dominance frontier */
-STATIC bool computeDominanceFrontier(CompilationUnit* cUnit, BasicBlock* bb)
+bool computeDominanceFrontier(CompilationUnit* cUnit, BasicBlock* bb)
 {
     GrowableList* blockList = &cUnit->blockList;
 
@@ -221,7 +221,7 @@
 }
 
 /* Worker function for initializing domination-related data structures */
-STATIC bool initializeDominationInfo(CompilationUnit* cUnit, BasicBlock* bb)
+bool initializeDominationInfo(CompilationUnit* cUnit, BasicBlock* bb)
 {
     int numTotalBlocks = cUnit->blockList.numUsed;
 
@@ -251,7 +251,7 @@
  * is only used when kDebugVerifyDataflow is active and should compute
  * the same dominator sets as computeBlockDominators.
  */
-STATIC bool slowComputeBlockDominators(CompilationUnit* cUnit, BasicBlock* bb)
+bool slowComputeBlockDominators(CompilationUnit* cUnit, BasicBlock* bb)
 {
     GrowableList* blockList = &cUnit->blockList;
     int numTotalBlocks = blockList->numUsed;
@@ -289,7 +289,7 @@
  * used when kDebugVerifyDataflow is active and should compute the
  * same iDom as computeBlockIDom.
  */
-STATIC bool slowComputeBlockIDom(CompilationUnit* cUnit, BasicBlock* bb)
+bool slowComputeBlockIDom(CompilationUnit* cUnit, BasicBlock* bb)
 {
     GrowableList* blockList = &cUnit->blockList;
     ArenaBitVector* tempBlockV = cUnit->tempBlockV;
@@ -352,7 +352,7 @@
 }
 
 /* Worker function to compute each block's immediate dominator */
-STATIC bool computeBlockIDom(CompilationUnit* cUnit, BasicBlock* bb)
+bool computeBlockIDom(CompilationUnit* cUnit, BasicBlock* bb)
 {
     GrowableListIterator iter;
     int idom = -1;
@@ -397,7 +397,7 @@
 }
 
 /* Worker function to compute each block's domintors */
-STATIC bool computeBlockDominators(CompilationUnit* cUnit, BasicBlock* bb)
+bool computeBlockDominators(CompilationUnit* cUnit, BasicBlock* bb)
 {
     if (bb == cUnit->entryBlock) {
         oatClearAllBits(bb->dominators);
@@ -408,7 +408,7 @@
     return false;
 }
 
-STATIC bool setDominators(CompilationUnit* cUnit, BasicBlock* bb)
+bool setDominators(CompilationUnit* cUnit, BasicBlock* bb)
 {
     if (bb != cUnit->entryBlock) {
         int iDomDFSIdx = cUnit->iDomList[bb->dfsId];
@@ -427,7 +427,7 @@
 }
 
 /* Compute dominators, immediate dominator, and dominance fronter */
-STATIC void computeDominators(CompilationUnit* cUnit)
+void computeDominators(CompilationUnit* cUnit)
 {
     int numReachableBlocks = cUnit->numReachableBlocks;
     int numTotalBlocks = cUnit->blockList.numUsed;
@@ -513,7 +513,7 @@
  * Perform dest U= src1 ^ ~src2
  * This is probably not general enough to be placed in BitVector.[ch].
  */
-STATIC void computeSuccLiveIn(ArenaBitVector* dest,
+void computeSuccLiveIn(ArenaBitVector* dest,
                               const ArenaBitVector* src1,
                               const ArenaBitVector* src2)
 {
@@ -535,7 +535,7 @@
  * The calculated result is used for phi-node pruning - where we only need to
  * insert a phi node if the variable is live-in to the block.
  */
-STATIC bool computeBlockLiveIns(CompilationUnit* cUnit, BasicBlock* bb)
+bool computeBlockLiveIns(CompilationUnit* cUnit, BasicBlock* bb)
 {
     ArenaBitVector* tempDalvikRegisterV = cUnit->tempDalvikRegisterV;
 
@@ -572,7 +572,7 @@
 }
 
 /* Insert phi nodes to for each variable to the dominance frontiers */
-STATIC void insertPhiNodes(CompilationUnit* cUnit)
+void insertPhiNodes(CompilationUnit* cUnit)
 {
     int dalvikReg;
     const GrowableList* blockList = &cUnit->blockList;
@@ -658,7 +658,7 @@
  * Worker function to insert phi-operands with latest SSA names from
  * predecessor blocks
  */
-STATIC bool insertPhiNodeOperands(CompilationUnit* cUnit, BasicBlock* bb)
+bool insertPhiNodeOperands(CompilationUnit* cUnit, BasicBlock* bb)
 {
     ArenaBitVector* ssaRegV = cUnit->tempSSARegisterV;
     GrowableListIterator iter;
@@ -711,7 +711,7 @@
     return true;
 }
 
-STATIC void doDFSPreOrderSSARename(CompilationUnit* cUnit, BasicBlock* block)
+void doDFSPreOrderSSARename(CompilationUnit* cUnit, BasicBlock* block)
 {
 
     if (block->visited || block->hidden) return;
diff --git a/src/compiler/Utility.cc b/src/compiler/Utility.cc
index defd647..f86b72c 100644
--- a/src/compiler/Utility.cc
+++ b/src/compiler/Utility.cc
@@ -188,7 +188,7 @@
 }
 
 /* Expand the capacity of a growable list */
-STATIC void expandGrowableList(CompilationUnit* cUnit, GrowableList* gList)
+void expandGrowableList(CompilationUnit* cUnit, GrowableList* gList)
 {
     int newLength = gList->numAllocated;
     if (newLength < 128) {
@@ -341,14 +341,6 @@
     }
 }
 
-/*
- * Dump the current stats of the compiler.
- */
-void oatDumpStats(void)
-{
-    oatArchDump();
-}
-
 static uint32_t checkMasks[32] = {
     0x00000001, 0x00000002, 0x00000004, 0x00000008, 0x00000010,
     0x00000020, 0x00000040, 0x00000080, 0x00000100, 0x00000200,
@@ -518,7 +510,7 @@
 /*
  * If the vector sizes don't match, log an error and abort.
  */
-STATIC void checkSizes(const ArenaBitVector* bv1, const ArenaBitVector* bv2)
+void checkSizes(const ArenaBitVector* bv1, const ArenaBitVector* bv2)
 {
     if (bv1->storageSize != bv2->storageSize) {
         LOG(FATAL) << "Mismatched vector sizes (" << bv1->storageSize <<
diff --git a/src/compiler/codegen/CodegenFactory.cc b/src/compiler/codegen/CodegenFactory.cc
index d141156..232cbf5 100644
--- a/src/compiler/codegen/CodegenFactory.cc
+++ b/src/compiler/codegen/CodegenFactory.cc
@@ -25,26 +25,31 @@
  * which combines this common code with specific support found in the
  * applicable directories below this one.
  *
- * Prior to including this file, TGT_LIR should be #defined.
- * For example, for arm:
- *    #define TGT_LIR ArmLIR
- * for MIPS:
- *    #define TGT_LIR MipsLIR
- * and for x86:
- *    #define TGT_LIR X86LIR
  */
 
+/*
+ * Load an immediate value into a fixed or temp register.  Target
+ * register is clobbered, and marked inUse.
+ */
+LIR* loadConstant(CompilationUnit* cUnit, int rDest, int value)
+{
+    if (oatIsTemp(cUnit, rDest)) {
+        oatClobber(cUnit, rDest);
+        oatMarkInUse(cUnit, rDest);
+    }
+    return loadConstantNoClobber(cUnit, rDest, value);
+}
 
 /* Load a word at base + displacement.  Displacement must be word multiple */
-STATIC TGT_LIR* loadWordDisp(CompilationUnit* cUnit, int rBase,
-                             int displacement, int rDest)
+LIR* loadWordDisp(CompilationUnit* cUnit, int rBase, int displacement,
+                  int rDest)
 {
     return loadBaseDisp(cUnit, NULL, rBase, displacement, rDest, kWord,
                         INVALID_SREG);
 }
 
-STATIC TGT_LIR* storeWordDisp(CompilationUnit* cUnit, int rBase,
-                             int displacement, int rSrc)
+LIR* storeWordDisp(CompilationUnit* cUnit, int rBase, int displacement,
+                   int rSrc)
 {
     return storeBaseDisp(cUnit, rBase, displacement, rSrc, kWord);
 }
@@ -54,8 +59,7 @@
  * using this routine, as it doesn't perform any bookkeeping regarding
  * register liveness.  That is the responsibility of the caller.
  */
-STATIC void loadValueDirect(CompilationUnit* cUnit, RegLocation rlSrc,
-                            int reg1)
+void loadValueDirect(CompilationUnit* cUnit, RegLocation rlSrc, int reg1)
 {
     rlSrc = oatUpdateLoc(cUnit, rlSrc);
     if (rlSrc.location == kLocPhysReg) {
@@ -71,8 +75,7 @@
  * register.  Should be used when loading to a fixed register (for example,
  * loading arguments to an out of line call.
  */
-STATIC void loadValueDirectFixed(CompilationUnit* cUnit, RegLocation rlSrc,
-                                 int reg1)
+void loadValueDirectFixed(CompilationUnit* cUnit, RegLocation rlSrc, int reg1)
 {
     oatClobber(cUnit, reg1);
     oatMarkInUse(cUnit, reg1);
@@ -84,8 +87,8 @@
  * using this routine, as it doesn't perform any bookkeeping regarding
  * register liveness.  That is the responsibility of the caller.
  */
-STATIC void loadValueDirectWide(CompilationUnit* cUnit, RegLocation rlSrc,
-                                int regLo, int regHi)
+void loadValueDirectWide(CompilationUnit* cUnit, RegLocation rlSrc, int regLo,
+                         int regHi)
 {
     rlSrc = oatUpdateLocWide(cUnit, rlSrc);
     if (rlSrc.location == kLocPhysReg) {
@@ -103,8 +106,8 @@
  * registers.  Should be used when loading to a fixed registers (for example,
  * loading arguments to an out of line call.
  */
-STATIC void loadValueDirectWideFixed(CompilationUnit* cUnit, RegLocation rlSrc,
-                                     int regLo, int regHi)
+void loadValueDirectWideFixed(CompilationUnit* cUnit, RegLocation rlSrc,
+                              int regLo, int regHi)
 {
     oatClobber(cUnit, regLo);
     oatClobber(cUnit, regHi);
@@ -113,8 +116,8 @@
     loadValueDirectWide(cUnit, rlSrc, regLo, regHi);
 }
 
-STATIC RegLocation loadValue(CompilationUnit* cUnit, RegLocation rlSrc,
-                             RegisterClass opKind)
+RegLocation loadValue(CompilationUnit* cUnit, RegLocation rlSrc,
+                      RegisterClass opKind)
 {
     rlSrc = oatEvalLoc(cUnit, rlSrc, opKind, false);
     if (rlSrc.location == kLocDalvikFrame) {
@@ -125,8 +128,7 @@
     return rlSrc;
 }
 
-STATIC void storeValue(CompilationUnit* cUnit, RegLocation rlDest,
-                       RegLocation rlSrc)
+void storeValue(CompilationUnit* cUnit, RegLocation rlDest, RegLocation rlSrc)
 {
     LIR* defStart;
     LIR* defEnd;
@@ -169,8 +171,8 @@
     }
 }
 
-STATIC RegLocation loadValueWide(CompilationUnit* cUnit, RegLocation rlSrc,
-                                 RegisterClass opKind)
+RegLocation loadValueWide(CompilationUnit* cUnit, RegLocation rlSrc,
+                          RegisterClass opKind)
 {
     DCHECK(rlSrc.wide);
     rlSrc = oatEvalLoc(cUnit, rlSrc, opKind, false);
@@ -184,8 +186,8 @@
     return rlSrc;
 }
 
-STATIC void storeValueWide(CompilationUnit* cUnit, RegLocation rlDest,
-                           RegLocation rlSrc)
+void storeValueWide(CompilationUnit* cUnit, RegLocation rlDest,
+                    RegLocation rlSrc)
 {
     LIR* defStart;
     LIR* defEnd;
@@ -240,4 +242,50 @@
     }
 }
 
+/*
+ * Mark garbage collection card. Skip if the value we're storing is null.
+ */
+void markGCCard(CompilationUnit* cUnit, int valReg, int tgtAddrReg)
+{
+    int regCardBase = oatAllocTemp(cUnit);
+    int regCardNo = oatAllocTemp(cUnit);
+    LIR* branchOver = genCmpImmBranch(cUnit, kCondEq, valReg, 0);
+    loadWordDisp(cUnit, rSELF, Thread::CardTableOffset().Int32Value(),
+                 regCardBase);
+    opRegRegImm(cUnit, kOpLsr, regCardNo, tgtAddrReg, GC_CARD_SHIFT);
+    storeBaseIndexed(cUnit, regCardBase, regCardNo, regCardBase, 0,
+                     kUnsignedByte);
+    LIR* target = newLIR0(cUnit, kPseudoTargetLabel);
+    target->defMask = ENCODE_ALL;
+    branchOver->target = (LIR*)target;
+    oatFreeTemp(cUnit, regCardBase);
+    oatFreeTemp(cUnit, regCardNo);
+}
+
+/*
+ * Utiltiy to load the current Method*.  Broken out
+ * to allow easy change between placing the current Method* in a
+ * dedicated register or its home location in the frame.
+ */
+void loadCurrMethodDirect(CompilationUnit *cUnit, int rTgt)
+{
+#if defined(METHOD_IN_REG)
+    genRegCopy(cUnit, rTgt, rMETHOD);
+#else
+    loadWordDisp(cUnit, rSP, 0, rTgt);
+#endif
+}
+
+int loadCurrMethod(CompilationUnit *cUnit)
+{
+#if defined(METHOD_IN_REG)
+    return rMETHOD;
+#else
+    int mReg = oatAllocTemp(cUnit);
+    loadCurrMethodDirect(cUnit, mReg);
+    return mReg;
+#endif
+}
+
+
 }  // namespace art
diff --git a/src/compiler/codegen/CodegenUtil.cc b/src/compiler/codegen/CodegenUtil.cc
index 1f05a17..4eccf04 100644
--- a/src/compiler/codegen/CodegenUtil.cc
+++ b/src/compiler/codegen/CodegenUtil.cc
@@ -16,7 +16,378 @@
 
 namespace art {
 
-STATIC void pushWord(std::vector<uint16_t>&buf, int data) {
+void setMemRefType(LIR* lir, bool isLoad, int memType)
+{
+    u8 *maskPtr;
+    u8 mask = ENCODE_MEM;;
+    DCHECK(EncodingMap[lir->opcode].flags & (IS_LOAD | IS_STORE));
+    if (isLoad) {
+        maskPtr = &lir->useMask;
+    } else {
+        maskPtr = &lir->defMask;
+    }
+    /* Clear out the memref flags */
+    *maskPtr &= ~mask;
+    /* ..and then add back the one we need */
+    switch(memType) {
+        case kLiteral:
+            DCHECK(isLoad);
+            *maskPtr |= ENCODE_LITERAL;
+            break;
+        case kDalvikReg:
+            *maskPtr |= ENCODE_DALVIK_REG;
+            break;
+        case kHeapRef:
+            *maskPtr |= ENCODE_HEAP_REF;
+            break;
+        case kMustNotAlias:
+            /* Currently only loads can be marked as kMustNotAlias */
+            DCHECK(!(EncodingMap[lir->opcode].flags & IS_STORE));
+            *maskPtr |= ENCODE_MUST_NOT_ALIAS;
+            break;
+        default:
+            LOG(FATAL) << "Oat: invalid memref kind - " << memType;
+    }
+}
+
+/*
+ * Mark load/store instructions that access Dalvik registers through r5FP +
+ * offset.
+ */
+void annotateDalvikRegAccess(LIR* lir, int regId, bool isLoad)
+{
+    setMemRefType(lir, isLoad, kDalvikReg);
+
+    /*
+     * Store the Dalvik register id in aliasInfo. Mark he MSB if it is a 64-bit
+     * access.
+     */
+    lir->aliasInfo = regId;
+    if (DOUBLEREG(lir->operands[0])) {
+        lir->aliasInfo |= 0x80000000;
+    }
+}
+
+/*
+ * Decode the register id.
+ */
+inline u8 getRegMaskCommon(int reg)
+{
+    u8 seed;
+    int shift;
+    int regId = reg & 0x1f;
+
+    /*
+     * Each double register is equal to a pair of single-precision FP registers
+     */
+    seed = DOUBLEREG(reg) ? 3 : 1;
+    /* FP register starts at bit position 16 */
+    shift = FPREG(reg) ? kFPReg0 : 0;
+    /* Expand the double register id into single offset */
+    shift += regId;
+    return (seed << shift);
+}
+
+/*
+ * Mark the corresponding bit(s).
+ */
+inline void setupRegMask(u8* mask, int reg)
+{
+    *mask |= getRegMaskCommon(reg);
+}
+
+/*
+ * Set up the proper fields in the resource mask
+ */
+void setupResourceMasks(LIR* lir)
+{
+    int opcode = lir->opcode;
+    int flags;
+
+    if (opcode <= 0) {
+        lir->useMask = lir->defMask = 0;
+        return;
+    }
+
+    flags = EncodingMap[lir->opcode].flags;
+
+    if (flags & NEEDS_FIXUP) {
+        lir->flags.pcRelFixup = true;
+    }
+
+    /* Set up the mask for resources that are updated */
+    if (flags & (IS_LOAD | IS_STORE)) {
+        /* Default to heap - will catch specialized classes later */
+        setMemRefType(lir, flags & IS_LOAD, kHeapRef);
+    }
+
+    /*
+     * Conservatively assume the branch here will call out a function that in
+     * turn will trash everything.
+     */
+    if (flags & IS_BRANCH) {
+        lir->defMask = lir->useMask = ENCODE_ALL;
+        return;
+    }
+
+    if (flags & REG_DEF0) {
+        setupRegMask(&lir->defMask, lir->operands[0]);
+    }
+
+    if (flags & REG_DEF1) {
+        setupRegMask(&lir->defMask, lir->operands[1]);
+    }
+
+    if (flags & REG_DEF_SP) {
+        lir->defMask |= ENCODE_REG_SP;
+    }
+
+    if (flags & REG_DEF_LR) {
+        lir->defMask |= ENCODE_REG_LR;
+    }
+
+    if (flags & REG_DEF_LIST0) {
+        lir->defMask |= ENCODE_REG_LIST(lir->operands[0]);
+    }
+
+    if (flags & REG_DEF_LIST1) {
+        lir->defMask |= ENCODE_REG_LIST(lir->operands[1]);
+    }
+
+    if (flags & REG_DEF_FPCS_LIST0) {
+        lir->defMask |= ENCODE_REG_FPCS_LIST(lir->operands[0]);
+    }
+
+    if (flags & REG_DEF_FPCS_LIST2) {
+        for (int i = 0; i < lir->operands[2]; i++) {
+            setupRegMask(&lir->defMask, lir->operands[1] + i);
+        }
+    }
+
+    if (flags & SETS_CCODES) {
+        lir->defMask |= ENCODE_CCODE;
+    }
+
+#if defined(TARGET_ARM)
+    /* Conservatively treat the IT block */
+    if (flags & IS_IT) {
+        lir->defMask = ENCODE_ALL;
+    }
+#endif
+
+    if (flags & (REG_USE0 | REG_USE1 | REG_USE2 | REG_USE3)) {
+        int i;
+
+        for (i = 0; i < 4; i++) {
+            if (flags & (1 << (kRegUse0 + i))) {
+                setupRegMask(&lir->useMask, lir->operands[i]);
+            }
+        }
+    }
+
+    if (flags & REG_USE_PC) {
+        lir->useMask |= ENCODE_REG_PC;
+    }
+
+    if (flags & REG_USE_SP) {
+        lir->useMask |= ENCODE_REG_SP;
+    }
+
+    if (flags & REG_USE_LIST0) {
+        lir->useMask |= ENCODE_REG_LIST(lir->operands[0]);
+    }
+
+    if (flags & REG_USE_LIST1) {
+        lir->useMask |= ENCODE_REG_LIST(lir->operands[1]);
+    }
+
+    if (flags & REG_USE_FPCS_LIST0) {
+        lir->useMask |= ENCODE_REG_FPCS_LIST(lir->operands[0]);
+    }
+
+    if (flags & REG_USE_FPCS_LIST2) {
+        for (int i = 0; i < lir->operands[2]; i++) {
+            setupRegMask(&lir->useMask, lir->operands[1] + i);
+        }
+    }
+
+    if (flags & USES_CCODES) {
+        lir->useMask |= ENCODE_CCODE;
+    }
+
+#if defined(TARGET_ARM)
+    /* Fixup for kThumbPush/lr and kThumbPop/pc */
+    if (opcode == kThumbPush || opcode == kThumbPop) {
+        u8 r8Mask = getRegMaskCommon(r8);
+        if ((opcode == kThumbPush) && (lir->useMask & r8Mask)) {
+            lir->useMask &= ~r8Mask;
+            lir->useMask |= ENCODE_REG_LR;
+        } else if ((opcode == kThumbPop) && (lir->defMask & r8Mask)) {
+            lir->defMask &= ~r8Mask;
+            lir->defMask |= ENCODE_REG_PC;
+        }
+    }
+#endif
+}
+
+/*
+ * The following are building blocks to construct low-level IRs with 0 - 4
+ * operands.
+ */
+LIR* newLIR0(CompilationUnit* cUnit, ArmOpcode opcode)
+{
+    LIR* insn = (LIR* ) oatNew(cUnit, sizeof(LIR), true, kAllocLIR);
+    DCHECK(isPseudoOpcode(opcode) || (EncodingMap[opcode].flags & NO_OPERAND));
+    insn->opcode = opcode;
+    setupResourceMasks(insn);
+    insn->dalvikOffset = cUnit->currentDalvikOffset;
+    oatAppendLIR(cUnit, (LIR*) insn);
+    return insn;
+}
+
+LIR* newLIR1(CompilationUnit* cUnit, ArmOpcode opcode,
+                           int dest)
+{
+    LIR* insn = (LIR* ) oatNew(cUnit, sizeof(LIR), true, kAllocLIR);
+    DCHECK(isPseudoOpcode(opcode) || (EncodingMap[opcode].flags & IS_UNARY_OP));
+    insn->opcode = opcode;
+    insn->operands[0] = dest;
+    setupResourceMasks(insn);
+    insn->dalvikOffset = cUnit->currentDalvikOffset;
+    oatAppendLIR(cUnit, (LIR*) insn);
+    return insn;
+}
+
+LIR* newLIR2(CompilationUnit* cUnit, ArmOpcode opcode,
+                           int dest, int src1)
+{
+    LIR* insn = (LIR* ) oatNew(cUnit, sizeof(LIR), true, kAllocLIR);
+    DCHECK(isPseudoOpcode(opcode) ||
+           (EncodingMap[opcode].flags & IS_BINARY_OP));
+    insn->opcode = opcode;
+    insn->operands[0] = dest;
+    insn->operands[1] = src1;
+    setupResourceMasks(insn);
+    insn->dalvikOffset = cUnit->currentDalvikOffset;
+    oatAppendLIR(cUnit, (LIR*) insn);
+    return insn;
+}
+
+LIR* newLIR3(CompilationUnit* cUnit, ArmOpcode opcode,
+                           int dest, int src1, int src2)
+{
+    LIR* insn = (LIR* ) oatNew(cUnit, sizeof(LIR), true, kAllocLIR);
+    DCHECK(isPseudoOpcode(opcode) ||
+           (EncodingMap[opcode].flags & IS_TERTIARY_OP))
+            << (int)opcode << " "
+            << PrettyMethod(cUnit->method_idx, *cUnit->dex_file) << " "
+            << cUnit->currentDalvikOffset;
+    insn->opcode = opcode;
+    insn->operands[0] = dest;
+    insn->operands[1] = src1;
+    insn->operands[2] = src2;
+    setupResourceMasks(insn);
+    insn->dalvikOffset = cUnit->currentDalvikOffset;
+    oatAppendLIR(cUnit, (LIR*) insn);
+    return insn;
+}
+
+#if defined(TARGET_ARM)
+LIR* newLIR4(CompilationUnit* cUnit, ArmOpcode opcode,
+                           int dest, int src1, int src2, int info)
+{
+    LIR* insn = (LIR* ) oatNew(cUnit, sizeof(LIR), true, kAllocLIR);
+    DCHECK(isPseudoOpcode(opcode) ||
+           (EncodingMap[opcode].flags & IS_QUAD_OP));
+    insn->opcode = opcode;
+    insn->operands[0] = dest;
+    insn->operands[1] = src1;
+    insn->operands[2] = src2;
+    insn->operands[3] = info;
+    setupResourceMasks(insn);
+    insn->dalvikOffset = cUnit->currentDalvikOffset;
+    oatAppendLIR(cUnit, (LIR*) insn);
+    return insn;
+}
+#endif
+
+/*
+ * Search the existing constants in the literal pool for an exact or close match
+ * within specified delta (greater or equal to 0).
+ */
+LIR* scanLiteralPool(LIR* dataTarget, int value, unsigned int delta)
+{
+    while (dataTarget) {
+        if (((unsigned) (value - ((LIR* ) dataTarget)->operands[0])) <=
+            delta)
+            return (LIR* ) dataTarget;
+        dataTarget = dataTarget->next;
+    }
+    return NULL;
+}
+
+/* Search the existing constants in the literal pool for an exact wide match */
+LIR* scanLiteralPoolWide(LIR* dataTarget, int valLo, int valHi)
+{
+    bool loMatch = false;
+    LIR* loTarget = NULL;
+    while (dataTarget) {
+        if (loMatch && (((LIR*)dataTarget)->operands[0] == valHi)) {
+            return (LIR*)loTarget;
+        }
+        loMatch = false;
+        if (((LIR*)dataTarget)->operands[0] == valLo) {
+            loMatch = true;
+            loTarget = dataTarget;
+        }
+        dataTarget = dataTarget->next;
+    }
+    return NULL;
+}
+
+/*
+ * The following are building blocks to insert constants into the pool or
+ * instruction streams.
+ */
+
+/* Add a 32-bit constant either in the constant pool or mixed with code */
+LIR* addWordData(CompilationUnit* cUnit, LIR* *constantListP,
+                           int value)
+{
+    /* Add the constant to the literal pool */
+    if (constantListP) {
+        LIR* newValue = (LIR* ) oatNew(cUnit, sizeof(LIR), true,
+                                             kAllocData);
+        newValue->operands[0] = value;
+        newValue->next = *constantListP;
+        *constantListP = (LIR*) newValue;
+        return newValue;
+    } else {
+        /* Add the constant in the middle of code stream */
+        newLIR1(cUnit, kArm16BitData, (value & 0xffff));
+        newLIR1(cUnit, kArm16BitData, (value >> 16));
+    }
+    return NULL;
+}
+
+/* Add a 64-bit constant to the constant pool or mixed with code */
+LIR* addWideData(CompilationUnit* cUnit, LIR* *constantListP,
+                           int valLo, int valHi)
+{
+    LIR* res;
+    //FIXME: hard-coded little endian, need BE variant
+    if (constantListP == NULL) {
+        res = addWordData(cUnit, NULL, valLo);
+        addWordData(cUnit, NULL, valHi);
+    } else {
+        // Insert high word into list first
+        addWordData(cUnit, constantListP, valHi);
+        res = addWordData(cUnit, constantListP, valLo);
+    }
+    return res;
+}
+
+void pushWord(std::vector<uint16_t>&buf, int data) {
     buf.push_back( data & 0xffff);
     buf.push_back( (data >> 16) & 0xffff);
 }
@@ -27,10 +398,10 @@
 }
 
 /* Write the literal pool to the output stream */
-STATIC void installLiteralPools(CompilationUnit* cUnit)
+void installLiteralPools(CompilationUnit* cUnit)
 {
     alignBuffer(cUnit->codeBuffer, cUnit->dataOffset);
-    TGT_LIR* dataLIR = (TGT_LIR*) cUnit->literalList;
+    LIR* dataLIR = (LIR*) cUnit->literalList;
     while (dataLIR != NULL) {
         pushWord(cUnit->codeBuffer, dataLIR->operands[0]);
         dataLIR = NEXT_LIR(dataLIR);
@@ -38,7 +409,7 @@
 }
 
 /* Write the switch tables to the output stream */
-STATIC void installSwitchTables(CompilationUnit* cUnit)
+void installSwitchTables(CompilationUnit* cUnit)
 {
     GrowableListIterator iterator;
     oatGrowableListIteratorInit(&cUnit->switchTables, &iterator);
@@ -47,14 +418,14 @@
              &iterator);
         if (tabRec == NULL) break;
         alignBuffer(cUnit->codeBuffer, tabRec->offset);
-        int bxOffset = tabRec->bxInst->generic.offset + 4;
+        int bxOffset = tabRec->bxInst->offset + 4;
         if (cUnit->printMe) {
             LOG(INFO) << "Switch table for offset 0x" << std::hex << bxOffset;
         }
         if (tabRec->table[0] == kSparseSwitchSignature) {
             int* keys = (int*)&(tabRec->table[2]);
             for (int elems = 0; elems < tabRec->table[1]; elems++) {
-                int disp = tabRec->targets[elems]->generic.offset - bxOffset;
+                int disp = tabRec->targets[elems]->offset - bxOffset;
                 if (cUnit->printMe) {
                     LOG(INFO) << "    Case[" << elems << "] key: 0x" <<
                         std::hex << keys[elems] << ", disp: 0x" <<
@@ -62,25 +433,25 @@
                 }
                 pushWord(cUnit->codeBuffer, keys[elems]);
                 pushWord(cUnit->codeBuffer,
-                    tabRec->targets[elems]->generic.offset - bxOffset);
+                    tabRec->targets[elems]->offset - bxOffset);
             }
         } else {
             DCHECK_EQ(tabRec->table[0], kPackedSwitchSignature);
             for (int elems = 0; elems < tabRec->table[1]; elems++) {
-                int disp = tabRec->targets[elems]->generic.offset - bxOffset;
+                int disp = tabRec->targets[elems]->offset - bxOffset;
                 if (cUnit->printMe) {
                     LOG(INFO) << "    Case[" << elems << "] disp: 0x" <<
                         std::hex << disp;
                 }
                 pushWord(cUnit->codeBuffer,
-                         tabRec->targets[elems]->generic.offset - bxOffset);
+                         tabRec->targets[elems]->offset - bxOffset);
             }
         }
     }
 }
 
 /* Write the fill array dta to the output stream */
-STATIC void installFillArrayData(CompilationUnit* cUnit)
+void installFillArrayData(CompilationUnit* cUnit)
 {
     GrowableListIterator iterator;
     oatGrowableListIteratorInit(&cUnit->fillArrayData, &iterator);
@@ -95,7 +466,7 @@
     }
 }
 
-STATIC int assignLiteralOffsetCommon(LIR* lir, int offset)
+int assignLiteralOffsetCommon(LIR* lir, int offset)
 {
     for (;lir != NULL; lir = lir->next) {
         lir->offset = offset;
@@ -104,32 +475,32 @@
     return offset;
 }
 
-STATIC void createMappingTable(CompilationUnit* cUnit)
+void createMappingTable(CompilationUnit* cUnit)
 {
-    TGT_LIR* tgtLIR;
+    LIR* tgtLIR;
     int currentDalvikOffset = -1;
 
-    for (tgtLIR = (TGT_LIR *) cUnit->firstLIRInsn;
+    for (tgtLIR = (LIR *) cUnit->firstLIRInsn;
          tgtLIR;
          tgtLIR = NEXT_LIR(tgtLIR)) {
         if ((tgtLIR->opcode >= 0) && !tgtLIR->flags.isNop &&
-            (currentDalvikOffset != tgtLIR->generic.dalvikOffset)) {
+            (currentDalvikOffset != tgtLIR->dalvikOffset)) {
             // Changed - need to emit a record
-            cUnit->mappingTable.push_back(tgtLIR->generic.offset);
-            cUnit->mappingTable.push_back(tgtLIR->generic.dalvikOffset);
-            currentDalvikOffset = tgtLIR->generic.dalvikOffset;
+            cUnit->mappingTable.push_back(tgtLIR->offset);
+            cUnit->mappingTable.push_back(tgtLIR->dalvikOffset);
+            currentDalvikOffset = tgtLIR->dalvikOffset;
         }
     }
 }
 
 /* Determine the offset of each literal field */
-STATIC int assignLiteralOffset(CompilationUnit* cUnit, int offset)
+int assignLiteralOffset(CompilationUnit* cUnit, int offset)
 {
     offset = assignLiteralOffsetCommon(cUnit->literalList, offset);
     return offset;
 }
 
-STATIC int assignSwitchTablesOffset(CompilationUnit* cUnit, int offset)
+int assignSwitchTablesOffset(CompilationUnit* cUnit, int offset)
 {
     GrowableListIterator iterator;
     oatGrowableListIteratorInit(&cUnit->switchTables, &iterator);
@@ -148,7 +519,7 @@
     return offset;
 }
 
-STATIC int assignFillArrayDataOffset(CompilationUnit* cUnit, int offset)
+int assignFillArrayDataOffset(CompilationUnit* cUnit, int offset)
 {
     GrowableListIterator iterator;
     oatGrowableListIteratorInit(&cUnit->fillArrayData, &iterator);
@@ -230,6 +601,119 @@
     createMappingTable(cUnit);
 }
 
+/*
+ * Insert a kPseudoCaseLabel at the beginning of the Dalvik
+ * offset vaddr.  This label will be used to fix up the case
+ * branch table during the assembly phase.  Be sure to set
+ * all resource flags on this to prevent code motion across
+ * target boundaries.  KeyVal is just there for debugging.
+ */
+LIR* insertCaseLabel(CompilationUnit* cUnit, int vaddr, int keyVal)
+{
+    std::map<unsigned int, LIR*>::iterator it;
+    it = cUnit->boundaryMap.find(vaddr);
+    if (it == cUnit->boundaryMap.end()) {
+        LOG(FATAL) << "Error: didn't find vaddr 0x" << std::hex << vaddr;
+    }
+    LIR* newLabel = (LIR*)oatNew(cUnit, sizeof(LIR), true, kAllocLIR);
+    newLabel->dalvikOffset = vaddr;
+    newLabel->opcode = kPseudoCaseLabel;
+    newLabel->operands[0] = keyVal;
+    oatInsertLIRAfter(it->second, (LIR*)newLabel);
+    return newLabel;
+}
+
+void markPackedCaseLabels(CompilationUnit* cUnit, SwitchTable *tabRec)
+{
+    const u2* table = tabRec->table;
+    int baseVaddr = tabRec->vaddr;
+    int *targets = (int*)&table[4];
+    int entries = table[1];
+    int lowKey = s4FromSwitchData(&table[2]);
+    for (int i = 0; i < entries; i++) {
+        tabRec->targets[i] = insertCaseLabel(cUnit, baseVaddr + targets[i],
+                                             i + lowKey);
+    }
+}
+
+void markSparseCaseLabels(CompilationUnit* cUnit, SwitchTable *tabRec)
+{
+    const u2* table = tabRec->table;
+    int baseVaddr = tabRec->vaddr;
+    int entries = table[1];
+    int* keys = (int*)&table[2];
+    int* targets = &keys[entries];
+    for (int i = 0; i < entries; i++) {
+        tabRec->targets[i] = insertCaseLabel(cUnit, baseVaddr + targets[i],
+                                             keys[i]);
+    }
+}
+
+void oatProcessSwitchTables(CompilationUnit* cUnit)
+{
+    GrowableListIterator iterator;
+    oatGrowableListIteratorInit(&cUnit->switchTables, &iterator);
+    while (true) {
+        SwitchTable *tabRec = (SwitchTable *) oatGrowableListIteratorNext(
+             &iterator);
+        if (tabRec == NULL) break;
+        if (tabRec->table[0] == kPackedSwitchSignature)
+            markPackedCaseLabels(cUnit, tabRec);
+        else if (tabRec->table[0] == kSparseSwitchSignature)
+            markSparseCaseLabels(cUnit, tabRec);
+        else {
+            LOG(FATAL) << "Invalid switch table";
+        }
+    }
+}
+
+//FIXME: Do we have endian issues here?
+
+void dumpSparseSwitchTable(const u2* table)
+    /*
+     * Sparse switch data format:
+     *  ushort ident = 0x0200   magic value
+     *  ushort size             number of entries in the table; > 0
+     *  int keys[size]          keys, sorted low-to-high; 32-bit aligned
+     *  int targets[size]       branch targets, relative to switch opcode
+     *
+     * Total size is (2+size*4) 16-bit code units.
+     */
+{
+    u2 ident = table[0];
+    int entries = table[1];
+    int* keys = (int*)&table[2];
+    int* targets = &keys[entries];
+    LOG(INFO) <<  "Sparse switch table - ident:0x" << std::hex << ident <<
+       ", entries: " << std::dec << entries;
+    for (int i = 0; i < entries; i++) {
+        LOG(INFO) << "    Key[" << keys[i] << "] -> 0x" << std::hex <<
+        targets[i];
+    }
+}
+
+void dumpPackedSwitchTable(const u2* table)
+    /*
+     * Packed switch data format:
+     *  ushort ident = 0x0100   magic value
+     *  ushort size             number of entries in the table
+     *  int first_key           first (and lowest) switch case value
+     *  int targets[size]       branch targets, relative to switch opcode
+     *
+     * Total size is (4+size*2) 16-bit code units.
+     */
+{
+    u2 ident = table[0];
+    int* targets = (int*)&table[4];
+    int entries = table[1];
+    int lowKey = s4FromSwitchData(&table[2]);
+    LOG(INFO) << "Packed switch table - ident:0x" << std::hex << ident <<
+        ", entries: " << std::dec << entries << ", lowKey: " << lowKey;
+    for (int i = 0; i < entries; i++) {
+        LOG(INFO) << "    Key[" << (i + lowKey) << "] -> 0x" << std::hex <<
+            targets[i];
+    }
+}
 
 
 }  // namespace art
diff --git a/src/compiler/codegen/GenCommon.cc b/src/compiler/codegen/GenCommon.cc
new file mode 100644
index 0000000..7af1aa0
--- /dev/null
+++ b/src/compiler/codegen/GenCommon.cc
@@ -0,0 +1,2133 @@
+/*
+ * Copyright (C) 2012 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.
+ */
+
+namespace art {
+
+/*
+ * This source files contains "gen" codegen routines that should
+ * be applicable to most targets.  Only mid-level support utilities
+ * and "op" calls may be used here.
+ */
+
+#if defined(TARGET_ARM)
+LIR* genIT(CompilationUnit* cUnit, ArmConditionCode cond, const char* guide);
+#endif
+
+LIR* callRuntimeHelper(CompilationUnit* cUnit, int reg)
+{
+    oatClobberCalleeSave(cUnit);
+    return opReg(cUnit, kOpBlx, reg);
+}
+
+/*
+ * Generate an kPseudoBarrier marker to indicate the boundary of special
+ * blocks.
+ */
+void genBarrier(CompilationUnit* cUnit)
+{
+    LIR* barrier = newLIR0(cUnit, kPseudoBarrier);
+    /* Mark all resources as being clobbered */
+    barrier->defMask = -1;
+}
+
+/* Generate conditional branch instructions */
+LIR* genConditionalBranch(CompilationUnit* cUnit, ConditionCode cond,
+                          LIR* target)
+{
+    LIR* branch = opCondBranch(cUnit, cond);
+    branch->target = (LIR*) target;
+    return branch;
+}
+
+/* Generate unconditional branch instructions */
+LIR* genUnconditionalBranch(CompilationUnit* cUnit, LIR* target)
+{
+    LIR* branch = opNone(cUnit, kOpUncondBr);
+    branch->target = (LIR*) target;
+    return branch;
+}
+
+LIR* genCheck(CompilationUnit* cUnit, ConditionCode cCode, MIR* mir,
+              ThrowKind kind)
+{
+    LIR* tgt = (LIR*)oatNew(cUnit, sizeof(LIR), true, kAllocLIR);
+    tgt->opcode = kPseudoThrowTarget;
+    tgt->operands[0] = kind;
+    tgt->operands[1] = mir ? mir->offset : 0;
+    LIR* branch = genConditionalBranch(cUnit, cCode, tgt);
+    // Remember branch target - will process later
+    oatInsertGrowableList(cUnit, &cUnit->throwLaunchpads, (intptr_t)tgt);
+    return branch;
+}
+
+LIR* genImmedCheck(CompilationUnit* cUnit, ConditionCode cCode,
+                   int reg, int immVal, MIR* mir, ThrowKind kind)
+{
+    LIR* tgt = (LIR*)oatNew(cUnit, sizeof(LIR), true, kAllocLIR);
+    tgt->opcode = kPseudoThrowTarget;
+    tgt->operands[0] = kind;
+    tgt->operands[1] = mir->offset;
+    LIR* branch;
+    if (cCode == kCondAl) {
+        branch = genUnconditionalBranch(cUnit, tgt);
+    } else {
+        branch = genCmpImmBranch(cUnit, cCode, reg, immVal);
+        branch->target = (LIR*)tgt;
+    }
+    // Remember branch target - will process later
+    oatInsertGrowableList(cUnit, &cUnit->throwLaunchpads, (intptr_t)tgt);
+    return branch;
+}
+
+/* Perform null-check on a register.  */
+LIR* genNullCheck(CompilationUnit* cUnit, int sReg, int mReg, MIR* mir)
+{
+    if (!(cUnit->disableOpt & (1 << kNullCheckElimination)) &&
+        mir->optimizationFlags & MIR_IGNORE_NULL_CHECK) {
+        return NULL;
+    }
+    return genImmedCheck(cUnit, kCondEq, mReg, 0, mir, kThrowNullPointer);
+}
+
+/* Perform check on two registers */
+LIR* genRegRegCheck(CompilationUnit* cUnit, ConditionCode cCode,
+                        int reg1, int reg2, MIR* mir, ThrowKind kind)
+{
+    LIR* tgt = (LIR*)oatNew(cUnit, sizeof(LIR), true, kAllocLIR);
+    tgt->opcode = kPseudoThrowTarget;
+    tgt->operands[0] = kind;
+    tgt->operands[1] = mir ? mir->offset : 0;
+    tgt->operands[2] = reg1;
+    tgt->operands[3] = reg2;
+    opRegReg(cUnit, kOpCmp, reg1, reg2);
+    LIR* branch = genConditionalBranch(cUnit, cCode, tgt);
+    // Remember branch target - will process later
+    oatInsertGrowableList(cUnit, &cUnit->throwLaunchpads, (intptr_t)tgt);
+    return branch;
+}
+
+void genCompareAndBranch(CompilationUnit* cUnit, BasicBlock* bb, MIR* mir,
+                         RegLocation rlSrc1, RegLocation rlSrc2, LIR* labelList)
+{
+    ConditionCode cond;
+    rlSrc1 = loadValue(cUnit, rlSrc1, kCoreReg);
+    rlSrc2 = loadValue(cUnit, rlSrc2, kCoreReg);
+    opRegReg(cUnit, kOpCmp, rlSrc1.lowReg, rlSrc2.lowReg);
+    Opcode opcode = mir->dalvikInsn.opcode;
+    switch(opcode) {
+        case OP_IF_EQ:
+            cond = kCondEq;
+            break;
+        case OP_IF_NE:
+            cond = kCondNe;
+            break;
+        case OP_IF_LT:
+            cond = kCondLt;
+            break;
+        case OP_IF_GE:
+            cond = kCondGe;
+            break;
+        case OP_IF_GT:
+            cond = kCondGt;
+            break;
+        case OP_IF_LE:
+            cond = kCondLe;
+            break;
+        default:
+            cond = (ConditionCode)0;
+            LOG(FATAL) << "Unexpected opcode " << (int)opcode;
+    }
+    genConditionalBranch(cUnit, cond, &labelList[bb->taken->id]);
+    genUnconditionalBranch(cUnit, &labelList[bb->fallThrough->id]);
+}
+
+void genCompareZeroAndBranch(CompilationUnit* cUnit, BasicBlock* bb, MIR* mir,
+                             RegLocation rlSrc, LIR* labelList)
+{
+    ConditionCode cond;
+    rlSrc = loadValue(cUnit, rlSrc, kCoreReg);
+    opRegImm(cUnit, kOpCmp, rlSrc.lowReg, 0);
+    Opcode opcode = mir->dalvikInsn.opcode;
+    switch(opcode) {
+        case OP_IF_EQZ:
+            cond = kCondEq;
+            break;
+        case OP_IF_NEZ:
+            cond = kCondNe;
+            break;
+        case OP_IF_LTZ:
+            cond = kCondLt;
+            break;
+        case OP_IF_GEZ:
+            cond = kCondGe;
+            break;
+        case OP_IF_GTZ:
+            cond = kCondGt;
+            break;
+        case OP_IF_LEZ:
+            cond = kCondLe;
+            break;
+        default:
+            cond = (ConditionCode)0;
+            LOG(FATAL) << "Unexpected opcode " << (int)opcode;
+    }
+    genConditionalBranch(cUnit, cond, &labelList[bb->taken->id]);
+    genUnconditionalBranch(cUnit, &labelList[bb->fallThrough->id]);
+}
+
+void genIntToLong(CompilationUnit* cUnit, MIR* mir, RegLocation rlDest,
+                  RegLocation rlSrc)
+{
+    RegLocation rlResult = oatEvalLoc(cUnit, rlDest, kCoreReg, true);
+    if (rlSrc.location == kLocPhysReg) {
+        genRegCopy(cUnit, rlResult.lowReg, rlSrc.lowReg);
+    } else {
+        loadValueDirect(cUnit, rlSrc, rlResult.lowReg);
+    }
+    opRegRegImm(cUnit, kOpAsr, rlResult.highReg,
+                rlResult.lowReg, 31);
+    storeValueWide(cUnit, rlDest, rlResult);
+}
+
+void genIntNarrowing(CompilationUnit* cUnit, MIR* mir, RegLocation rlDest,
+                     RegLocation rlSrc)
+{
+     rlSrc = loadValue(cUnit, rlSrc, kCoreReg);
+     RegLocation rlResult = oatEvalLoc(cUnit, rlDest, kCoreReg, true);
+     OpKind op = kOpInvalid;
+     switch(mir->dalvikInsn.opcode) {
+         case OP_INT_TO_BYTE:
+             op = kOp2Byte;
+             break;
+         case OP_INT_TO_SHORT:
+              op = kOp2Short;
+              break;
+         case OP_INT_TO_CHAR:
+              op = kOp2Char;
+              break;
+         default:
+             LOG(ERROR) << "Bad int conversion type";
+     }
+     opRegReg(cUnit, op, rlResult.lowReg, rlSrc.lowReg);
+     storeValue(cUnit, rlDest, rlResult);
+}
+
+/*
+ * Let helper function take care of everything.  Will call
+ * Array::AllocFromCode(type_idx, method, count);
+ * Note: AllocFromCode will handle checks for errNegativeArraySize.
+ */
+void genNewArray(CompilationUnit* cUnit, MIR* mir, RegLocation rlDest,
+                 RegLocation rlSrc)
+{
+    oatFlushAllRegs(cUnit);    /* Everything to home location */
+    uint32_t type_idx = mir->dalvikInsn.vC;
+    int rTgt;
+    if (cUnit->compiler->CanAccessTypeWithoutChecks(cUnit->method_idx,
+                                                    cUnit->dex_cache,
+                                                    *cUnit->dex_file,
+                                                    type_idx)) {
+        rTgt = loadHelper(cUnit, OFFSETOF_MEMBER(Thread, pAllocArrayFromCode));
+    } else {
+        rTgt = loadHelper(cUnit, OFFSETOF_MEMBER(Thread,
+                          pAllocArrayFromCodeWithAccessCheck));
+    }
+    loadCurrMethodDirect(cUnit, rARG1);              // arg1 <- Method*
+    loadConstant(cUnit, rARG0, type_idx);            // arg0 <- type_id
+    loadValueDirectFixed(cUnit, rlSrc, rARG2);       // arg2 <- count
+    callRuntimeHelper(cUnit, rTgt);
+    RegLocation rlResult = oatGetReturn(cUnit);
+    storeValue(cUnit, rlDest, rlResult);
+}
+
+/*
+ * Similar to genNewArray, but with post-allocation initialization.
+ * Verifier guarantees we're dealing with an array class.  Current
+ * code throws runtime exception "bad Filled array req" for 'D' and 'J'.
+ * Current code also throws internal unimp if not 'L', '[' or 'I'.
+ */
+void genFilledNewArray(CompilationUnit* cUnit, MIR* mir, bool isRange)
+{
+    DecodedInstruction* dInsn = &mir->dalvikInsn;
+    int elems = dInsn->vA;
+    int typeId = dInsn->vB;
+    oatFlushAllRegs(cUnit);    /* Everything to home location */
+    int rTgt;
+    if (cUnit->compiler->CanAccessTypeWithoutChecks(cUnit->method_idx,
+                                                    cUnit->dex_cache,
+                                                    *cUnit->dex_file,
+                                                    typeId)) {
+        rTgt = loadHelper(cUnit, OFFSETOF_MEMBER(Thread,
+                          pCheckAndAllocArrayFromCode));
+    } else {
+        rTgt = loadHelper(cUnit, OFFSETOF_MEMBER(Thread,
+                          pCheckAndAllocArrayFromCodeWithAccessCheck));
+    }
+    loadCurrMethodDirect(cUnit, rARG1);              // arg1 <- Method*
+    loadConstant(cUnit, rARG0, typeId);              // arg0 <- type_id
+    loadConstant(cUnit, rARG2, elems);               // arg2 <- count
+    callRuntimeHelper(cUnit, rTgt);
+    /*
+     * NOTE: the implicit target for OP_FILLED_NEW_ARRAY is the
+     * return region.  Because AllocFromCode placed the new array
+     * in rRET0, we'll just lock it into place.  When debugger support is
+     * added, it may be necessary to additionally copy all return
+     * values to a home location in thread-local storage
+     */
+    oatLockTemp(cUnit, rRET0);
+
+    // TODO: use the correct component size, currently all supported types
+    // share array alignment with ints (see comment at head of function)
+    size_t component_size = sizeof(int32_t);
+
+    // Having a range of 0 is legal
+    if (isRange && (dInsn->vA > 0)) {
+        /*
+         * Bit of ugliness here.  We're going generate a mem copy loop
+         * on the register range, but it is possible that some regs
+         * in the range have been promoted.  This is unlikely, but
+         * before generating the copy, we'll just force a flush
+         * of any regs in the source range that have been promoted to
+         * home location.
+         */
+        for (unsigned int i = 0; i < dInsn->vA; i++) {
+            RegLocation loc = oatUpdateLoc(cUnit,
+                oatGetSrc(cUnit, mir, i));
+            if (loc.location == kLocPhysReg) {
+                storeBaseDisp(cUnit, rSP, oatSRegOffset(cUnit, loc.sRegLow),
+                              loc.lowReg, kWord);
+            }
+        }
+        /*
+         * TUNING note: generated code here could be much improved, but
+         * this is an uncommon operation and isn't especially performance
+         * critical.
+         */
+        int rSrc = oatAllocTemp(cUnit);
+        int rDst = oatAllocTemp(cUnit);
+        int rIdx = oatAllocTemp(cUnit);
+        int rVal = rLR;  // Using a lot of temps, rLR is known free here
+        // Set up source pointer
+        RegLocation rlFirst = oatGetSrc(cUnit, mir, 0);
+        opRegRegImm(cUnit, kOpAdd, rSrc, rSP,
+                    oatSRegOffset(cUnit, rlFirst.sRegLow));
+        // Set up the target pointer
+        opRegRegImm(cUnit, kOpAdd, rDst, rRET0,
+                    Array::DataOffset(component_size).Int32Value());
+        // Set up the loop counter (known to be > 0)
+        loadConstant(cUnit, rIdx, dInsn->vA - 1);
+        // Generate the copy loop.  Going backwards for convenience
+        LIR* target = newLIR0(cUnit, kPseudoTargetLabel);
+        target->defMask = ENCODE_ALL;
+        // Copy next element
+        loadBaseIndexed(cUnit, rSrc, rIdx, rVal, 2, kWord);
+        storeBaseIndexed(cUnit, rDst, rIdx, rVal, 2, kWord);
+#if defined(TARGET_ARM)
+        // Combine sub & test using sub setflags encoding here
+        newLIR3(cUnit, kThumb2SubsRRI12, rIdx, rIdx, 1);
+        LIR* branch = opCondBranch(cUnit, kCondGe);
+#else
+        opRegImm(cUnit, kOpSub, rIdx, 1);
+        LIR* branch = opCompareBranchImm(cUnit, kCondGe, rIdx, 0);
+#endif
+        branch->target = (LIR*)target;
+    } else if (!isRange) {
+        // TUNING: interleave
+        for (unsigned int i = 0; i < dInsn->vA; i++) {
+            RegLocation rlArg = loadValue(cUnit,
+                oatGetSrc(cUnit, mir, i), kCoreReg);
+            storeBaseDisp(cUnit, rRET0,
+                          Array::DataOffset(component_size).Int32Value() +
+                          i * 4, rlArg.lowReg, kWord);
+            // If the loadValue caused a temp to be allocated, free it
+            if (oatIsTemp(cUnit, rlArg.lowReg)) {
+                oatFreeTemp(cUnit, rlArg.lowReg);
+            }
+        }
+    }
+}
+
+void genSput(CompilationUnit* cUnit, MIR* mir, RegLocation rlSrc,
+             bool isLongOrDouble, bool isObject)
+{
+    int fieldOffset;
+    int ssbIndex;
+    bool isVolatile;
+    bool isReferrersClass;
+    uint32_t fieldIdx = mir->dalvikInsn.vB;
+
+    OatCompilationUnit mUnit(cUnit->class_loader, cUnit->class_linker,
+                             *cUnit->dex_file, *cUnit->dex_cache,
+                             cUnit->code_item, cUnit->method_idx,
+                             cUnit->access_flags);
+
+    bool fastPath =
+        cUnit->compiler->ComputeStaticFieldInfo(fieldIdx, &mUnit,
+                                                fieldOffset, ssbIndex,
+                                                isReferrersClass, isVolatile, true);
+    if (fastPath && !SLOW_FIELD_PATH) {
+        DCHECK_GE(fieldOffset, 0);
+        int rBase;
+        int rMethod;
+        if (isReferrersClass) {
+            // Fast path, static storage base is this method's class
+            rMethod  = loadCurrMethod(cUnit);
+            rBase = oatAllocTemp(cUnit);
+            loadWordDisp(cUnit, rMethod,
+                         Method::DeclaringClassOffset().Int32Value(), rBase);
+        } else {
+            // Medium path, static storage base in a different class which
+            // requires checks that the other class is initialized.
+            DCHECK_GE(ssbIndex, 0);
+            // May do runtime call so everything to home locations.
+            oatFlushAllRegs(cUnit);
+            // Using fixed register to sync with possible call to runtime
+            // support.
+            rMethod = rARG1;
+            oatLockTemp(cUnit, rMethod);
+            loadCurrMethodDirect(cUnit, rMethod);
+            rBase = rARG0;
+            oatLockTemp(cUnit, rBase);
+            loadWordDisp(cUnit, rMethod,
+                Method::DexCacheInitializedStaticStorageOffset().Int32Value(),
+                rBase);
+            loadWordDisp(cUnit, rBase,
+                         Array::DataOffset(sizeof(Object*)).Int32Value() + sizeof(int32_t*) *
+                         ssbIndex, rBase);
+            // rBase now points at appropriate static storage base (Class*)
+            // or NULL if not initialized. Check for NULL and call helper if NULL.
+            // TUNING: fast path should fall through
+            LIR* branchOver = genCmpImmBranch(cUnit, kCondNe, rBase, 0);
+            int rTgt = loadHelper(cUnit, OFFSETOF_MEMBER(Thread,
+                                  pInitializeStaticStorage));
+            loadConstant(cUnit, rARG0, ssbIndex);
+            callRuntimeHelper(cUnit, rTgt);
+#if defined(TARGET_MIPS)
+            // For Arm, rRET0 = rARG0 = rBASE, for Mips, we need to copy
+            genRegCopy(cUnit, rBase, rRET0);
+#endif
+            LIR* skipTarget = newLIR0(cUnit, kPseudoTargetLabel);
+            skipTarget->defMask = ENCODE_ALL;
+            branchOver->target = (LIR*)skipTarget;
+        }
+        // rBase now holds static storage base
+        oatFreeTemp(cUnit, rMethod);
+        if (isLongOrDouble) {
+            rlSrc = oatGetSrcWide(cUnit, mir, 0, 1);
+            rlSrc = loadValueWide(cUnit, rlSrc, kAnyReg);
+        } else {
+            rlSrc = oatGetSrc(cUnit, mir, 0);
+            rlSrc = loadValue(cUnit, rlSrc, kAnyReg);
+        }
+//FIXME: need to generalize the barrier call
+        if (isVolatile) {
+            oatGenMemBarrier(cUnit, kST);
+        }
+        if (isLongOrDouble) {
+            storeBaseDispWide(cUnit, rBase, fieldOffset, rlSrc.lowReg,
+                              rlSrc.highReg);
+        } else {
+            storeWordDisp(cUnit, rBase, fieldOffset, rlSrc.lowReg);
+        }
+        if (isVolatile) {
+            oatGenMemBarrier(cUnit, kSY);
+        }
+        if (isObject) {
+            markGCCard(cUnit, rlSrc.lowReg, rBase);
+        }
+        oatFreeTemp(cUnit, rBase);
+    } else {
+        oatFlushAllRegs(cUnit);  // Everything to home locations
+        int setterOffset = isLongOrDouble ? OFFSETOF_MEMBER(Thread, pSet64Static) :
+                           (isObject ? OFFSETOF_MEMBER(Thread, pSetObjStatic)
+                                     : OFFSETOF_MEMBER(Thread, pSet32Static));
+        int rTgt = loadHelper(cUnit, setterOffset);
+        loadConstant(cUnit, rARG0, fieldIdx);
+        if (isLongOrDouble) {
+            loadValueDirectWideFixed(cUnit, rlSrc, rARG2, rARG3);
+        } else {
+            loadValueDirect(cUnit, rlSrc, rARG1);
+        }
+        callRuntimeHelper(cUnit, rTgt);
+    }
+}
+
+void genSget(CompilationUnit* cUnit, MIR* mir, RegLocation rlDest,
+             bool isLongOrDouble, bool isObject)
+{
+    int fieldOffset;
+    int ssbIndex;
+    bool isVolatile;
+    bool isReferrersClass;
+    uint32_t fieldIdx = mir->dalvikInsn.vB;
+
+    OatCompilationUnit mUnit(cUnit->class_loader, cUnit->class_linker,
+                             *cUnit->dex_file, *cUnit->dex_cache,
+                             cUnit->code_item, cUnit->method_idx,
+                             cUnit->access_flags);
+
+    bool fastPath =
+        cUnit->compiler->ComputeStaticFieldInfo(fieldIdx, &mUnit,
+                                                fieldOffset, ssbIndex,
+                                                isReferrersClass, isVolatile,
+                                                false);
+    if (fastPath && !SLOW_FIELD_PATH) {
+        DCHECK_GE(fieldOffset, 0);
+        int rBase;
+        int rMethod;
+        if (isReferrersClass) {
+            // Fast path, static storage base is this method's class
+            rMethod  = loadCurrMethod(cUnit);
+            rBase = oatAllocTemp(cUnit);
+            loadWordDisp(cUnit, rMethod,
+                         Method::DeclaringClassOffset().Int32Value(), rBase);
+        } else {
+            // Medium path, static storage base in a different class which
+            // requires checks that the other class is initialized
+            DCHECK_GE(ssbIndex, 0);
+            // May do runtime call so everything to home locations.
+            oatFlushAllRegs(cUnit);
+            // Using fixed register to sync with possible call to runtime
+            // support
+            rMethod = rARG1;
+            oatLockTemp(cUnit, rMethod);
+            loadCurrMethodDirect(cUnit, rMethod);
+            rBase = rARG0;
+            oatLockTemp(cUnit, rBase);
+            loadWordDisp(cUnit, rMethod,
+                Method::DexCacheInitializedStaticStorageOffset().Int32Value(),
+                rBase);
+            loadWordDisp(cUnit, rBase,
+                         Array::DataOffset(sizeof(Object*)).Int32Value() +
+                         sizeof(int32_t*) * ssbIndex,
+                         rBase);
+            // rBase now points at appropriate static storage base (Class*)
+            // or NULL if not initialized. Check for NULL and call helper if NULL.
+            // TUNING: fast path should fall through
+            LIR* branchOver = genCmpImmBranch(cUnit, kCondNe, rBase, 0);
+            int rTgt = loadHelper(cUnit, OFFSETOF_MEMBER(Thread,
+                                  pInitializeStaticStorage));
+            loadConstant(cUnit, rARG0, ssbIndex);
+            callRuntimeHelper(cUnit, rTgt);
+#if defined(TARGET_MIPS)
+            // For Arm, rRET0 = rARG0 = rBASE, for Mips, we need to copy
+            genRegCopy(cUnit, rBase, rRET0);
+#endif
+            LIR* skipTarget = newLIR0(cUnit, kPseudoTargetLabel);
+            skipTarget->defMask = ENCODE_ALL;
+            branchOver->target = (LIR*)skipTarget;
+        }
+        // rBase now holds static storage base
+        oatFreeTemp(cUnit, rMethod);
+        rlDest = isLongOrDouble ? oatGetDestWide(cUnit, mir, 0, 1)
+                                : oatGetDest(cUnit, mir, 0);
+        RegLocation rlResult = oatEvalLoc(cUnit, rlDest, kAnyReg, true);
+        if (isVolatile) {
+            oatGenMemBarrier(cUnit, kSY);
+        }
+        if (isLongOrDouble) {
+            loadBaseDispWide(cUnit, NULL, rBase, fieldOffset, rlResult.lowReg,
+                             rlResult.highReg, INVALID_SREG);
+        } else {
+            loadWordDisp(cUnit, rBase, fieldOffset, rlResult.lowReg);
+        }
+        oatFreeTemp(cUnit, rBase);
+        if (isLongOrDouble) {
+            storeValueWide(cUnit, rlDest, rlResult);
+        } else {
+            storeValue(cUnit, rlDest, rlResult);
+        }
+    } else {
+        oatFlushAllRegs(cUnit);  // Everything to home locations
+        int getterOffset = isLongOrDouble ? OFFSETOF_MEMBER(Thread, pGet64Static) :
+                           (isObject ? OFFSETOF_MEMBER(Thread, pGetObjStatic)
+                                     : OFFSETOF_MEMBER(Thread, pGet32Static));
+        int rTgt = loadHelper(cUnit, getterOffset);
+        loadConstant(cUnit, rARG0, fieldIdx);
+        callRuntimeHelper(cUnit, rTgt);
+        if (isLongOrDouble) {
+            RegLocation rlResult = oatGetReturnWide(cUnit);
+            storeValueWide(cUnit, rlDest, rlResult);
+        } else {
+            RegLocation rlResult = oatGetReturn(cUnit);
+            storeValue(cUnit, rlDest, rlResult);
+        }
+    }
+}
+
+
+// Debugging routine - if null target, branch to DebugMe
+void genShowTarget(CompilationUnit* cUnit)
+{
+    LIR* branchOver = genCmpImmBranch(cUnit, kCondNe, rLINK, 0);
+    loadWordDisp(cUnit, rSELF,
+                 OFFSETOF_MEMBER(Thread, pDebugMe), rLINK);
+    LIR* target = newLIR0(cUnit, kPseudoTargetLabel);
+    target->defMask = -1;
+    branchOver->target = (LIR*)target;
+}
+
+void genThrowVerificationError(CompilationUnit* cUnit, MIR* mir)
+{
+    int rTgt = loadHelper(cUnit, OFFSETOF_MEMBER(Thread,
+                          pThrowVerificationErrorFromCode));
+    loadConstant(cUnit, rARG0, mir->dalvikInsn.vA);
+    loadConstant(cUnit, rARG1, mir->dalvikInsn.vB);
+    callRuntimeHelper(cUnit, rTgt);
+}
+
+void handleSuspendLaunchpads(CompilationUnit *cUnit)
+{
+    LIR** suspendLabel =
+        (LIR **) cUnit->suspendLaunchpads.elemList;
+    int numElems = cUnit->suspendLaunchpads.numUsed;
+
+    for (int i = 0; i < numElems; i++) {
+        /* TUNING: move suspend count load into helper */
+        LIR* lab = suspendLabel[i];
+        LIR* resumeLab = (LIR*)lab->operands[0];
+        cUnit->currentDalvikOffset = lab->operands[1];
+        oatAppendLIR(cUnit, (LIR *)lab);
+        int rTgt = loadHelper(cUnit, OFFSETOF_MEMBER(Thread,
+                              pTestSuspendFromCode));
+        if (!cUnit->genDebugger) {
+            // use rSUSPEND for suspend count
+            loadWordDisp(cUnit, rSELF,
+                         Thread::SuspendCountOffset().Int32Value(), rSUSPEND);
+        }
+        opReg(cUnit, kOpBlx, rTgt);
+        if ( cUnit->genDebugger) {
+            // use rSUSPEND for update debugger
+            loadWordDisp(cUnit, rSELF,
+                         OFFSETOF_MEMBER(Thread, pUpdateDebuggerFromCode),
+                         rSUSPEND);
+        }
+        genUnconditionalBranch(cUnit, resumeLab);
+    }
+}
+
+void handleThrowLaunchpads(CompilationUnit *cUnit)
+{
+    LIR** throwLabel = (LIR **) cUnit->throwLaunchpads.elemList;
+    int numElems = cUnit->throwLaunchpads.numUsed;
+    int i;
+
+    for (i = 0; i < numElems; i++) {
+        LIR* lab = throwLabel[i];
+        cUnit->currentDalvikOffset = lab->operands[1];
+        oatAppendLIR(cUnit, (LIR *)lab);
+        int funcOffset = 0;
+        int v1 = lab->operands[2];
+        int v2 = lab->operands[3];
+        switch(lab->operands[0]) {
+            case kThrowNullPointer:
+                funcOffset = OFFSETOF_MEMBER(Thread, pThrowNullPointerFromCode);
+                break;
+            case kThrowArrayBounds:
+                if (v2 != r0) {
+                    genRegCopy(cUnit, rARG0, v1);
+                    genRegCopy(cUnit, rARG1, v2);
+                } else {
+                    if (v1 == r1) {
+#if defined(TARGET_ARM)
+                        int rTmp = r12;
+#else
+                        int rTmp = oatAllocTemp(cUnit);
+#endif
+                        genRegCopy(cUnit, rTmp, v1);
+                        genRegCopy(cUnit, rARG1, v2);
+                        genRegCopy(cUnit, rARG0, rTmp);
+#if !(defined(TARGET_ARM))
+                        oatFreeTemp(cUnit, rTmp);
+#endif
+                    } else {
+                        genRegCopy(cUnit, rARG1, v2);
+                        genRegCopy(cUnit, rARG0, v1);
+                    }
+                }
+                funcOffset = OFFSETOF_MEMBER(Thread, pThrowArrayBoundsFromCode);
+                break;
+            case kThrowDivZero:
+                funcOffset = OFFSETOF_MEMBER(Thread, pThrowDivZeroFromCode);
+                break;
+            case kThrowVerificationError:
+                loadConstant(cUnit, rARG0, v1);
+                loadConstant(cUnit, rARG1, v2);
+                funcOffset =
+                    OFFSETOF_MEMBER(Thread, pThrowVerificationErrorFromCode);
+                break;
+            case kThrowNegArraySize:
+                genRegCopy(cUnit, rARG0, v1);
+                funcOffset =
+                    OFFSETOF_MEMBER(Thread, pThrowNegArraySizeFromCode);
+                break;
+            case kThrowNoSuchMethod:
+                genRegCopy(cUnit, rARG0, v1);
+                funcOffset =
+                    OFFSETOF_MEMBER(Thread, pThrowNoSuchMethodFromCode);
+                break;
+            case kThrowStackOverflow:
+                funcOffset =
+                    OFFSETOF_MEMBER(Thread, pThrowStackOverflowFromCode);
+                // Restore stack alignment
+                opRegImm(cUnit, kOpAdd, rSP,
+                         (cUnit->numCoreSpills + cUnit->numFPSpills) * 4);
+                break;
+            default:
+                LOG(FATAL) << "Unexpected throw kind: " << lab->operands[0];
+        }
+        int rTgt = loadHelper(cUnit, funcOffset);
+        callRuntimeHelper(cUnit, rTgt);
+    }
+}
+
+/* Needed by the Assembler */
+void oatSetupResourceMasks(LIR* lir)
+{
+    setupResourceMasks(lir);
+}
+
+void genIGet(CompilationUnit* cUnit, MIR* mir, OpSize size,
+             RegLocation rlDest, RegLocation rlObj,
+                    bool isLongOrDouble, bool isObject)
+{
+    int fieldOffset;
+    bool isVolatile;
+    uint32_t fieldIdx = mir->dalvikInsn.vC;
+
+    OatCompilationUnit mUnit(cUnit->class_loader, cUnit->class_linker,
+                             *cUnit->dex_file, *cUnit->dex_cache,
+                             cUnit->code_item, cUnit->method_idx,
+                             cUnit->access_flags);
+
+    bool fastPath = cUnit->compiler->ComputeInstanceFieldInfo(fieldIdx, &mUnit,
+                    fieldOffset, isVolatile, false);
+
+    if (fastPath && !SLOW_FIELD_PATH) {
+        RegLocation rlResult;
+        RegisterClass regClass = oatRegClassBySize(size);
+        DCHECK_GE(fieldOffset, 0);
+        rlObj = loadValue(cUnit, rlObj, kCoreReg);
+        if (isLongOrDouble) {
+            DCHECK(rlDest.wide);
+            genNullCheck(cUnit, rlObj.sRegLow, rlObj.lowReg, mir);/* null? */
+            int regPtr = oatAllocTemp(cUnit);
+            opRegRegImm(cUnit, kOpAdd, regPtr, rlObj.lowReg, fieldOffset);
+            rlResult = oatEvalLoc(cUnit, rlDest, regClass, true);
+            loadPair(cUnit, regPtr, rlResult.lowReg, rlResult.highReg);
+            if (isVolatile) {
+                oatGenMemBarrier(cUnit, kSY);
+            }
+            oatFreeTemp(cUnit, regPtr);
+            storeValueWide(cUnit, rlDest, rlResult);
+        } else {
+            rlResult = oatEvalLoc(cUnit, rlDest, regClass, true);
+            genNullCheck(cUnit, rlObj.sRegLow, rlObj.lowReg, mir);/* null? */
+            loadBaseDisp(cUnit, mir, rlObj.lowReg, fieldOffset, rlResult.lowReg,
+                         kWord, rlObj.sRegLow);
+            if (isVolatile) {
+                oatGenMemBarrier(cUnit, kSY);
+            }
+            storeValue(cUnit, rlDest, rlResult);
+        }
+    } else {
+        int getterOffset = isLongOrDouble ? OFFSETOF_MEMBER(Thread, pGet64Instance) :
+                           (isObject ? OFFSETOF_MEMBER(Thread, pGetObjInstance)
+                                     : OFFSETOF_MEMBER(Thread, pGet32Instance));
+        int rTgt = loadHelper(cUnit, getterOffset);
+        loadValueDirect(cUnit, rlObj, rARG1);
+        loadConstant(cUnit, rARG0, fieldIdx);
+        callRuntimeHelper(cUnit, rTgt);
+        if (isLongOrDouble) {
+            RegLocation rlResult = oatGetReturnWide(cUnit);
+            storeValueWide(cUnit, rlDest, rlResult);
+        } else {
+            RegLocation rlResult = oatGetReturn(cUnit);
+            storeValue(cUnit, rlDest, rlResult);
+        }
+    }
+}
+
+void genIPut(CompilationUnit* cUnit, MIR* mir, OpSize size, RegLocation rlSrc,
+             RegLocation rlObj, bool isLongOrDouble, bool isObject)
+{
+    int fieldOffset;
+    bool isVolatile;
+    uint32_t fieldIdx = mir->dalvikInsn.vC;
+
+    OatCompilationUnit mUnit(cUnit->class_loader, cUnit->class_linker,
+                             *cUnit->dex_file, *cUnit->dex_cache,
+                             cUnit->code_item, cUnit->method_idx,
+                             cUnit->access_flags);
+
+    bool fastPath = cUnit->compiler->ComputeInstanceFieldInfo(fieldIdx, &mUnit,
+                    fieldOffset, isVolatile, true);
+    if (fastPath && !SLOW_FIELD_PATH) {
+        RegisterClass regClass = oatRegClassBySize(size);
+        DCHECK_GE(fieldOffset, 0);
+        rlObj = loadValue(cUnit, rlObj, kCoreReg);
+        if (isLongOrDouble) {
+            int regPtr;
+            rlSrc = loadValueWide(cUnit, rlSrc, kAnyReg);
+            genNullCheck(cUnit, rlObj.sRegLow, rlObj.lowReg, mir);/* null? */
+            regPtr = oatAllocTemp(cUnit);
+            opRegRegImm(cUnit, kOpAdd, regPtr, rlObj.lowReg, fieldOffset);
+            if (isVolatile) {
+                oatGenMemBarrier(cUnit, kST);
+            }
+            storePair(cUnit, regPtr, rlSrc.lowReg, rlSrc.highReg);
+            if (isVolatile) {
+                oatGenMemBarrier(cUnit, kSY);
+            }
+            oatFreeTemp(cUnit, regPtr);
+        } else {
+            rlSrc = loadValue(cUnit, rlSrc, regClass);
+            genNullCheck(cUnit, rlObj.sRegLow, rlObj.lowReg, mir);/* null? */
+            if (isVolatile) {
+                oatGenMemBarrier(cUnit, kST);
+            }
+            storeBaseDisp(cUnit, rlObj.lowReg, fieldOffset, rlSrc.lowReg, kWord);
+            if (isVolatile) {
+                oatGenMemBarrier(cUnit, kSY);
+            }
+        }
+    } else {
+        int setterOffset = isLongOrDouble ? OFFSETOF_MEMBER(Thread, pSet64Instance) :
+                           (isObject ? OFFSETOF_MEMBER(Thread, pSetObjInstance)
+                                     : OFFSETOF_MEMBER(Thread, pSet32Instance));
+        int rTgt = loadHelper(cUnit, setterOffset);
+        loadValueDirect(cUnit, rlObj, rARG1);
+        if (isLongOrDouble) {
+            loadValueDirectWide(cUnit, rlSrc, rARG2, rARG3);
+        } else {
+            loadValueDirect(cUnit, rlSrc, rARG2);
+        }
+        loadConstant(cUnit, rARG0, fieldIdx);
+        callRuntimeHelper(cUnit, rTgt);
+    }
+}
+
+void genConstClass(CompilationUnit* cUnit, MIR* mir, RegLocation rlDest,
+                   RegLocation rlSrc)
+{
+    uint32_t type_idx = mir->dalvikInsn.vB;
+    int mReg = loadCurrMethod(cUnit);
+    int resReg = oatAllocTemp(cUnit);
+    RegLocation rlResult = oatEvalLoc(cUnit, rlDest, kCoreReg, true);
+    if (!cUnit->compiler->CanAccessTypeWithoutChecks(cUnit->method_idx,
+                                                     cUnit->dex_cache,
+                                                     *cUnit->dex_file,
+                                                     type_idx)) {
+        // Call out to helper which resolves type and verifies access.
+        // Resolved type returned in rRET0.
+        int rTgt = loadHelper(cUnit, OFFSETOF_MEMBER(Thread,
+                              pInitializeTypeAndVerifyAccessFromCode));
+        genRegCopy(cUnit, rARG1, mReg);
+        loadConstant(cUnit, rARG0, type_idx);
+        callRuntimeHelper(cUnit, rTgt);
+        RegLocation rlResult = oatGetReturn(cUnit);
+        storeValue(cUnit, rlDest, rlResult);
+    } else {
+        // We're don't need access checks, load type from dex cache
+        int32_t dex_cache_offset =
+            Method::DexCacheResolvedTypesOffset().Int32Value();
+        loadWordDisp(cUnit, mReg, dex_cache_offset, resReg);
+        int32_t offset_of_type =
+            Array::DataOffset(sizeof(Class*)).Int32Value() + (sizeof(Class*)
+                              * type_idx);
+        loadWordDisp(cUnit, resReg, offset_of_type, rlResult.lowReg);
+        if (!cUnit->compiler->CanAssumeTypeIsPresentInDexCache(cUnit->dex_cache,
+                type_idx) || SLOW_TYPE_PATH) {
+            // Slow path, at runtime test if type is null and if so initialize
+            oatFlushAllRegs(cUnit);
+            LIR* branch1 = genCmpImmBranch(cUnit, kCondEq, rlResult.lowReg, 0);
+            // Resolved, store and hop over following code
+            storeValue(cUnit, rlDest, rlResult);
+            LIR* branch2 = genUnconditionalBranch(cUnit,0);
+            // TUNING: move slow path to end & remove unconditional branch
+            LIR* target1 = newLIR0(cUnit, kPseudoTargetLabel);
+            target1->defMask = ENCODE_ALL;
+            // Call out to helper, which will return resolved type in r0
+            int rTgt = loadHelper(cUnit, OFFSETOF_MEMBER(Thread,
+                                  pInitializeTypeFromCode));
+            genRegCopy(cUnit, rARG1, mReg);
+            loadConstant(cUnit, rARG0, type_idx);
+            callRuntimeHelper(cUnit, rTgt);
+            RegLocation rlResult = oatGetReturn(cUnit);
+            storeValue(cUnit, rlDest, rlResult);
+            // Rejoin code paths
+            LIR* target2 = newLIR0(cUnit, kPseudoTargetLabel);
+            target2->defMask = ENCODE_ALL;
+            branch1->target = (LIR*)target1;
+            branch2->target = (LIR*)target2;
+        } else {
+            // Fast path, we're done - just store result
+            storeValue(cUnit, rlDest, rlResult);
+        }
+    }
+}
+void genConstString(CompilationUnit* cUnit, MIR* mir, RegLocation rlDest,
+                    RegLocation rlSrc)
+{
+    /* NOTE: Most strings should be available at compile time */
+    uint32_t string_idx = mir->dalvikInsn.vB;
+    int32_t offset_of_string = Array::DataOffset(sizeof(String*)).Int32Value() +
+                               (sizeof(String*) * string_idx);
+    if (!cUnit->compiler->CanAssumeStringIsPresentInDexCache(
+            cUnit->dex_cache, string_idx) || SLOW_STRING_PATH) {
+        // slow path, resolve string if not in dex cache
+        oatFlushAllRegs(cUnit);
+        oatLockCallTemps(cUnit); // Using explicit registers
+        loadCurrMethodDirect(cUnit, rARG2);
+        loadWordDisp(cUnit, rARG2,
+                     Method::DexCacheStringsOffset().Int32Value(), rARG0);
+        // Might call out to helper, which will return resolved string in rRET0
+        int rTgt = loadHelper(cUnit, OFFSETOF_MEMBER(Thread,
+                              pResolveStringFromCode));
+        loadWordDisp(cUnit, rRET0, offset_of_string, rARG0);
+        loadConstant(cUnit, rARG1, string_idx);
+#if defined(TARGET_ARM)
+        opRegImm(cUnit, kOpCmp, rRET0, 0);  // Is resolved?
+        genBarrier(cUnit);
+        // For testing, always force through helper
+        if (!EXERCISE_SLOWEST_STRING_PATH) {
+            genIT(cUnit, kArmCondEq, "T");
+        }
+        genRegCopy(cUnit, rARG0, rARG2);   // .eq
+        opReg(cUnit, kOpBlx, rTgt);        // .eq, helper(Method*, string_idx)
+#else
+        LIR* branch = genCmpImmBranch(cUnit, kCondNe, 0);
+        genRegCopy(cUnit, rARG0, rARG2);   // .eq
+        opReg(cUnit, kOpBlx, rTgt);
+        LIR* target = newLIR0(cUnit, kPseudoTargetLabel);
+        target->defMask = ENCODE_ALL;
+        branch->target = target;
+#endif
+        genBarrier(cUnit);
+        storeValue(cUnit, rlDest, getRetLoc(cUnit));
+    } else {
+        int mReg = loadCurrMethod(cUnit);
+        int resReg = oatAllocTemp(cUnit);
+        RegLocation rlResult = oatEvalLoc(cUnit, rlDest, kCoreReg, true);
+        loadWordDisp(cUnit, mReg,
+                     Method::DexCacheStringsOffset().Int32Value(), resReg);
+        loadWordDisp(cUnit, resReg, offset_of_string, rlResult.lowReg);
+        storeValue(cUnit, rlDest, rlResult);
+    }
+}
+
+/*
+ * Let helper function take care of everything.  Will
+ * call Class::NewInstanceFromCode(type_idx, method);
+ */
+void genNewInstance(CompilationUnit* cUnit, MIR* mir, RegLocation rlDest)
+{
+    oatFlushAllRegs(cUnit);    /* Everything to home location */
+    uint32_t type_idx = mir->dalvikInsn.vB;
+    // alloc will always check for resolution, do we also need to verify
+    // access because the verifier was unable to?
+    int rTgt;
+    if (cUnit->compiler->CanAccessInstantiableTypeWithoutChecks(
+            cUnit->method_idx, cUnit->dex_cache, *cUnit->dex_file, type_idx)) {
+        rTgt = loadHelper(cUnit, OFFSETOF_MEMBER(Thread, pAllocObjectFromCode));
+    } else {
+        rTgt = loadHelper(cUnit, OFFSETOF_MEMBER(Thread,
+                          pAllocObjectFromCodeWithAccessCheck));
+    }
+    loadCurrMethodDirect(cUnit, rARG1);    // arg1 <= Method*
+    loadConstant(cUnit, rARG0, type_idx);  // arg0 <- type_idx
+    callRuntimeHelper(cUnit, rTgt);
+    RegLocation rlResult = oatGetReturn(cUnit);
+    storeValue(cUnit, rlDest, rlResult);
+}
+
+void genInstanceof(CompilationUnit* cUnit, MIR* mir, RegLocation rlDest,
+                   RegLocation rlSrc)
+{
+    oatFlushAllRegs(cUnit);
+    // May generate a call - use explicit registers
+    oatLockCallTemps(cUnit);
+    uint32_t type_idx = mir->dalvikInsn.vC;
+    loadCurrMethodDirect(cUnit, rARG1);  // r1 <= current Method*
+    int classReg = rARG2;  // rARG2 will hold the Class*
+    if (!cUnit->compiler->CanAccessTypeWithoutChecks(cUnit->method_idx,
+                                                     cUnit->dex_cache,
+                                                     *cUnit->dex_file,
+                                                     type_idx)) {
+        // Check we have access to type_idx and if not throw IllegalAccessError,
+        // returns Class* in r0
+        int rTgt = loadHelper(cUnit, OFFSETOF_MEMBER(Thread,
+                              pInitializeTypeAndVerifyAccessFromCode));
+        loadConstant(cUnit, rARG0, type_idx);
+        callRuntimeHelper(cUnit, rTgt);  // InitializeTypeAndVerifyAccess(idx, method)
+        genRegCopy(cUnit, classReg, rRET0);  // Align usage with fast path
+        loadValueDirectFixed(cUnit, rlSrc, rARG0);  // r0 <= ref
+    } else {
+        // Load dex cache entry into classReg (r2)
+        loadValueDirectFixed(cUnit, rlSrc, rARG0);  // rARG0 <= ref
+        loadWordDisp(cUnit, rARG1,
+                     Method::DexCacheResolvedTypesOffset().Int32Value(),
+                     classReg);
+        int32_t offset_of_type =
+            Array::DataOffset(sizeof(Class*)).Int32Value() + (sizeof(Class*)
+            * type_idx);
+        loadWordDisp(cUnit, classReg, offset_of_type, classReg);
+        if (!cUnit->compiler->CanAssumeTypeIsPresentInDexCache(
+                cUnit->dex_cache, type_idx)) {
+            // Need to test presence of type in dex cache at runtime
+            LIR* hopBranch = genCmpImmBranch(cUnit, kCondNe, classReg, 0);
+            // Not resolved
+            // Call out to helper, which will return resolved type in rRET0
+            int rTgt = loadHelper(cUnit, OFFSETOF_MEMBER(Thread,
+                                  pInitializeTypeFromCode));
+            loadConstant(cUnit, rARG0, type_idx);
+            callRuntimeHelper(cUnit, rTgt);  // InitializeTypeFromCode(idx, method)
+            genRegCopy(cUnit, r2, rRET0); // Align usage with fast path
+            loadValueDirectFixed(cUnit, rlSrc, rARG0);  /* reload Ref */
+            // Rejoin code paths
+            LIR* hopTarget = newLIR0(cUnit, kPseudoTargetLabel);
+            hopTarget->defMask = ENCODE_ALL;
+            hopBranch->target = (LIR*)hopTarget;
+        }
+    }
+    /* rARG0 is ref, rARG2 is class. If ref==null, use directly as bool result */
+    LIR* branch1 = genCmpImmBranch(cUnit, kCondEq, rARG0, 0);
+    /* load object->clazz */
+    DCHECK_EQ(Object::ClassOffset().Int32Value(), 0);
+    loadWordDisp(cUnit, rARG0,  Object::ClassOffset().Int32Value(), rARG1);
+    /* rARG0 is ref, rARG1 is ref->clazz, rARG2 is class */
+    int rTgt = loadHelper(cUnit, OFFSETOF_MEMBER(Thread,
+                          pInstanceofNonTrivialFromCode));
+#if defined(TARGET_ARM)
+    opRegReg(cUnit, kOpCmp, rARG1, rARG2);  // Same?
+    genBarrier(cUnit);
+    genIT(cUnit, kArmCondEq, "EE");   // if-convert the test
+    loadConstant(cUnit, rARG0, 1);       // .eq case - load true
+    genRegCopy(cUnit, rARG0, rARG2);        // .ne case - arg0 <= class
+    opReg(cUnit, kOpBlx, rTgt);        // .ne case: helper(class, ref->class)
+    genBarrier(cUnit);
+    oatClobberCalleeSave(cUnit);
+#else
+    // Perhaps a general-purpose kOpSelect operator?
+    UNIMPLEMENTED(FATAL) << "Need non IT implementation";
+#endif
+    /* branch target here */
+    LIR* target = newLIR0(cUnit, kPseudoTargetLabel);
+    target->defMask = ENCODE_ALL;
+    RegLocation rlResult = oatGetReturn(cUnit);
+    storeValue(cUnit, rlDest, rlResult);
+    branch1->target = (LIR*)target;
+}
+
+void genCheckCast(CompilationUnit* cUnit, MIR* mir, RegLocation rlSrc)
+{
+    oatFlushAllRegs(cUnit);
+    // May generate a call - use explicit registers
+    oatLockCallTemps(cUnit);
+    uint32_t type_idx = mir->dalvikInsn.vB;
+    loadCurrMethodDirect(cUnit, rARG1);  // rARG1 <= current Method*
+    int classReg = rARG2;  // rARG2 will hold the Class*
+    if (!cUnit->compiler->CanAccessTypeWithoutChecks(cUnit->method_idx,
+                                                     cUnit->dex_cache,
+                                                     *cUnit->dex_file,
+                                                     type_idx)) {
+        // Check we have access to type_idx and if not throw IllegalAccessError,
+        // returns Class* in rRET0
+        int rTgt = loadHelper(cUnit, OFFSETOF_MEMBER(Thread,
+                              pInitializeTypeAndVerifyAccessFromCode));
+        loadConstant(cUnit, rARG0, type_idx);
+        callRuntimeHelper(cUnit, rTgt);  // InitializeTypeAndVerifyAccess(idx, method)
+        genRegCopy(cUnit, classReg, rRET0);  // Align usage with fast path
+    } else {
+        // Load dex cache entry into classReg (rARG2)
+        loadWordDisp(cUnit, rARG1,
+                     Method::DexCacheResolvedTypesOffset().Int32Value(),
+                     classReg);
+        int32_t offset_of_type =
+                Array::DataOffset(sizeof(Class*)).Int32Value() +
+                (sizeof(Class*) * type_idx);
+        loadWordDisp(cUnit, classReg, offset_of_type, classReg);
+        if (!cUnit->compiler->CanAssumeTypeIsPresentInDexCache(
+                cUnit->dex_cache, type_idx)) {
+            // Need to test presence of type in dex cache at runtime
+            LIR* hopBranch = genCmpImmBranch(cUnit, kCondNe, classReg, 0);
+            // Not resolved
+            // Call out to helper, which will return resolved type in r0
+            loadWordDisp(cUnit, rSELF, OFFSETOF_MEMBER(Thread, pInitializeTypeFromCode), rLR);
+            loadConstant(cUnit, r0, type_idx);
+            callRuntimeHelper(cUnit, rLR);  // InitializeTypeFromCode(idx, method)
+            genRegCopy(cUnit, classReg, r0); // Align usage with fast path
+            // Rejoin code paths
+            LIR* hopTarget = newLIR0(cUnit, kPseudoTargetLabel);
+            hopTarget->defMask = ENCODE_ALL;
+            hopBranch->target = (LIR*)hopTarget;
+        }
+    }
+    // At this point, classReg (r2) has class
+    loadValueDirectFixed(cUnit, rlSrc, rARG0);  // rARG0 <= ref
+    /* Null is OK - continue */
+    LIR* branch1 = genCmpImmBranch(cUnit, kCondEq, rARG0, 0);
+    /* load object->clazz */
+    DCHECK_EQ(Object::ClassOffset().Int32Value(), 0);
+    loadWordDisp(cUnit, rARG0,  Object::ClassOffset().Int32Value(), rARG1);
+    /* rARG1 now contains object->clazz */
+    int rTgt = loadHelper(cUnit, OFFSETOF_MEMBER(Thread,
+                          pCheckCastFromCode));
+    opRegReg(cUnit, kOpCmp, rARG1, classReg);
+    LIR* branch2 = opCondBranch(cUnit, kCondEq); /* If equal, trivial yes */
+    genRegCopy(cUnit, rARG0, rARG1);
+    genRegCopy(cUnit, rARG1, rARG2);
+    callRuntimeHelper(cUnit, rTgt);
+    /* branch target here */
+    LIR* target = newLIR0(cUnit, kPseudoTargetLabel);
+    target->defMask = ENCODE_ALL;
+    branch1->target = (LIR*)target;
+    branch2->target = (LIR*)target;
+}
+
+
+void genThrow(CompilationUnit* cUnit, MIR* mir, RegLocation rlSrc)
+{
+    oatFlushAllRegs(cUnit);
+    int rTgt = loadHelper(cUnit, OFFSETOF_MEMBER(Thread, pDeliverException));
+    loadValueDirectFixed(cUnit, rlSrc, rARG0);  // Get exception object
+    callRuntimeHelper(cUnit, rTgt);  // art_deliver_exception(exception);
+}
+
+/*
+ * Generate array store
+ *
+ */
+void genArrayObjPut(CompilationUnit* cUnit, MIR* mir, RegLocation rlArray,
+                    RegLocation rlIndex, RegLocation rlSrc, int scale)
+{
+    RegisterClass regClass = oatRegClassBySize(kWord);
+    int lenOffset = Array::LengthOffset().Int32Value();
+    int dataOffset = Array::DataOffset(sizeof(Object*)).Int32Value();
+
+    oatFlushAllRegs(cUnit);
+    /* Make sure it's a legal object Put. Use direct regs at first */
+    loadValueDirectFixed(cUnit, rlArray, rARG1);
+    loadValueDirectFixed(cUnit, rlSrc, rARG0);
+
+    /* null array object? */
+    genNullCheck(cUnit, rlArray.sRegLow, rARG1, mir);
+    int rTgt = loadHelper(cUnit, OFFSETOF_MEMBER(Thread,
+                          pCanPutArrayElementFromCode));
+    /* Get the array's clazz */
+    loadWordDisp(cUnit, rARG1, Object::ClassOffset().Int32Value(), rARG1);
+    callRuntimeHelper(cUnit, rTgt);
+    oatFreeTemp(cUnit, rARG0);
+    oatFreeTemp(cUnit, rARG1);
+
+    // Now, redo loadValues in case they didn't survive the call
+
+    int regPtr;
+    rlArray = loadValue(cUnit, rlArray, kCoreReg);
+    rlIndex = loadValue(cUnit, rlIndex, kCoreReg);
+
+    if (oatIsTemp(cUnit, rlArray.lowReg)) {
+        oatClobber(cUnit, rlArray.lowReg);
+        regPtr = rlArray.lowReg;
+    } else {
+        regPtr = oatAllocTemp(cUnit);
+        genRegCopy(cUnit, regPtr, rlArray.lowReg);
+    }
+
+    if (!(mir->optimizationFlags & MIR_IGNORE_RANGE_CHECK)) {
+        int regLen = oatAllocTemp(cUnit);
+        //NOTE: max live temps(4) here.
+        /* Get len */
+        loadWordDisp(cUnit, rlArray.lowReg, lenOffset, regLen);
+        /* regPtr -> array data */
+        opRegImm(cUnit, kOpAdd, regPtr, dataOffset);
+        genRegRegCheck(cUnit, kCondCs, rlIndex.lowReg, regLen, mir,
+                       kThrowArrayBounds);
+        oatFreeTemp(cUnit, regLen);
+    } else {
+        /* regPtr -> array data */
+        opRegImm(cUnit, kOpAdd, regPtr, dataOffset);
+    }
+    /* at this point, regPtr points to array, 2 live temps */
+    rlSrc = loadValue(cUnit, rlSrc, regClass);
+    storeBaseIndexed(cUnit, regPtr, rlIndex.lowReg, rlSrc.lowReg,
+                     scale, kWord);
+}
+
+/*
+ * Generate array load
+ */
+void genArrayGet(CompilationUnit* cUnit, MIR* mir, OpSize size,
+                 RegLocation rlArray, RegLocation rlIndex,
+                 RegLocation rlDest, int scale)
+{
+    RegisterClass regClass = oatRegClassBySize(size);
+    int lenOffset = Array::LengthOffset().Int32Value();
+    int dataOffset;
+    RegLocation rlResult;
+    rlArray = loadValue(cUnit, rlArray, kCoreReg);
+    rlIndex = loadValue(cUnit, rlIndex, kCoreReg);
+    int regPtr;
+
+    if (size == kLong || size == kDouble) {
+      dataOffset = Array::DataOffset(sizeof(int64_t)).Int32Value();
+    } else {
+      dataOffset = Array::DataOffset(sizeof(int32_t)).Int32Value();
+    }
+
+    /* null object? */
+    genNullCheck(cUnit, rlArray.sRegLow, rlArray.lowReg, mir);
+
+    regPtr = oatAllocTemp(cUnit);
+
+    if (!(mir->optimizationFlags & MIR_IGNORE_RANGE_CHECK)) {
+        int regLen = oatAllocTemp(cUnit);
+        /* Get len */
+        loadWordDisp(cUnit, rlArray.lowReg, lenOffset, regLen);
+        /* regPtr -> array data */
+        opRegRegImm(cUnit, kOpAdd, regPtr, rlArray.lowReg, dataOffset);
+        genRegRegCheck(cUnit, kCondCs, rlIndex.lowReg, regLen, mir,
+                       kThrowArrayBounds);
+        oatFreeTemp(cUnit, regLen);
+    } else {
+        /* regPtr -> array data */
+        opRegRegImm(cUnit, kOpAdd, regPtr, rlArray.lowReg, dataOffset);
+    }
+    oatFreeTemp(cUnit, rlArray.lowReg);
+    if ((size == kLong) || (size == kDouble)) {
+        if (scale) {
+            int rNewIndex = oatAllocTemp(cUnit);
+            opRegRegImm(cUnit, kOpLsl, rNewIndex, rlIndex.lowReg, scale);
+            opRegReg(cUnit, kOpAdd, regPtr, rNewIndex);
+            oatFreeTemp(cUnit, rNewIndex);
+        } else {
+            opRegReg(cUnit, kOpAdd, regPtr, rlIndex.lowReg);
+        }
+        oatFreeTemp(cUnit, rlIndex.lowReg);
+        rlResult = oatEvalLoc(cUnit, rlDest, regClass, true);
+
+        loadPair(cUnit, regPtr, rlResult.lowReg, rlResult.highReg);
+
+        oatFreeTemp(cUnit, regPtr);
+        storeValueWide(cUnit, rlDest, rlResult);
+    } else {
+        rlResult = oatEvalLoc(cUnit, rlDest, regClass, true);
+
+        loadBaseIndexed(cUnit, regPtr, rlIndex.lowReg, rlResult.lowReg,
+                        scale, size);
+
+        oatFreeTemp(cUnit, regPtr);
+        storeValue(cUnit, rlDest, rlResult);
+    }
+}
+
+/*
+ * Generate array store
+ *
+ */
+void genArrayPut(CompilationUnit* cUnit, MIR* mir, OpSize size,
+                 RegLocation rlArray, RegLocation rlIndex,
+                 RegLocation rlSrc, int scale)
+{
+    RegisterClass regClass = oatRegClassBySize(size);
+    int lenOffset = Array::LengthOffset().Int32Value();
+    int dataOffset;
+
+    if (size == kLong || size == kDouble) {
+      dataOffset = Array::DataOffset(sizeof(int64_t)).Int32Value();
+    } else {
+      dataOffset = Array::DataOffset(sizeof(int32_t)).Int32Value();
+    }
+
+    int regPtr;
+    rlArray = loadValue(cUnit, rlArray, kCoreReg);
+    rlIndex = loadValue(cUnit, rlIndex, kCoreReg);
+
+    if (oatIsTemp(cUnit, rlArray.lowReg)) {
+        oatClobber(cUnit, rlArray.lowReg);
+        regPtr = rlArray.lowReg;
+    } else {
+        regPtr = oatAllocTemp(cUnit);
+        genRegCopy(cUnit, regPtr, rlArray.lowReg);
+    }
+
+    /* null object? */
+    genNullCheck(cUnit, rlArray.sRegLow, rlArray.lowReg, mir);
+
+    if (!(mir->optimizationFlags & MIR_IGNORE_RANGE_CHECK)) {
+        int regLen = oatAllocTemp(cUnit);
+        //NOTE: max live temps(4) here.
+        /* Get len */
+        loadWordDisp(cUnit, rlArray.lowReg, lenOffset, regLen);
+        /* regPtr -> array data */
+        opRegImm(cUnit, kOpAdd, regPtr, dataOffset);
+        genRegRegCheck(cUnit, kCondCs, rlIndex.lowReg, regLen, mir,
+                       kThrowArrayBounds);
+        oatFreeTemp(cUnit, regLen);
+    } else {
+        /* regPtr -> array data */
+        opRegImm(cUnit, kOpAdd, regPtr, dataOffset);
+    }
+    /* at this point, regPtr points to array, 2 live temps */
+    if ((size == kLong) || (size == kDouble)) {
+        //TUNING: specific wide routine that can handle fp regs
+        if (scale) {
+            int rNewIndex = oatAllocTemp(cUnit);
+            opRegRegImm(cUnit, kOpLsl, rNewIndex, rlIndex.lowReg, scale);
+            opRegReg(cUnit, kOpAdd, regPtr, rNewIndex);
+            oatFreeTemp(cUnit, rNewIndex);
+        } else {
+            opRegReg(cUnit, kOpAdd, regPtr, rlIndex.lowReg);
+        }
+        rlSrc = loadValueWide(cUnit, rlSrc, regClass);
+
+        storePair(cUnit, regPtr, rlSrc.lowReg, rlSrc.highReg);
+
+        oatFreeTemp(cUnit, regPtr);
+    } else {
+        rlSrc = loadValue(cUnit, rlSrc, regClass);
+
+        storeBaseIndexed(cUnit, regPtr, rlIndex.lowReg, rlSrc.lowReg,
+                         scale, size);
+    }
+}
+
+void genLong3Addr(CompilationUnit* cUnit, MIR* mir, OpKind firstOp,
+                  OpKind secondOp, RegLocation rlDest,
+                         RegLocation rlSrc1, RegLocation rlSrc2)
+{
+    RegLocation rlResult;
+#if defined(TARGET_ARM)
+    /*
+     * NOTE:  This is the one place in the code in which we might have
+     * as many as six live temporary registers.  There are 5 in the normal
+     * set for Arm.  Until we have spill capabilities, temporarily add
+     * lr to the temp set.  It is safe to do this locally, but note that
+     * lr is used explicitly elsewhere in the code generator and cannot
+     * normally be used as a general temp register.
+     */
+    oatMarkTemp(cUnit, rLR);   // Add lr to the temp pool
+    oatFreeTemp(cUnit, rLR);   // and make it available
+#endif
+    rlSrc1 = loadValueWide(cUnit, rlSrc1, kCoreReg);
+    rlSrc2 = loadValueWide(cUnit, rlSrc2, kCoreReg);
+    rlResult = oatEvalLoc(cUnit, rlDest, kCoreReg, true);
+    // The longs may overlap - use intermediate temp if so
+    if (rlResult.lowReg == rlSrc1.highReg) {
+        int tReg = oatAllocTemp(cUnit);
+        genRegCopy(cUnit, tReg, rlSrc1.highReg);
+        opRegRegReg(cUnit, firstOp, rlResult.lowReg, rlSrc1.lowReg,
+                    rlSrc2.lowReg);
+        opRegRegReg(cUnit, secondOp, rlResult.highReg, tReg,
+                    rlSrc2.highReg);
+        oatFreeTemp(cUnit, tReg);
+    } else {
+        opRegRegReg(cUnit, firstOp, rlResult.lowReg, rlSrc1.lowReg,
+                    rlSrc2.lowReg);
+        opRegRegReg(cUnit, secondOp, rlResult.highReg, rlSrc1.highReg,
+                    rlSrc2.highReg);
+    }
+    /*
+     * NOTE: If rlDest refers to a frame variable in a large frame, the
+     * following storeValueWide might need to allocate a temp register.
+     * To further work around the lack of a spill capability, explicitly
+     * free any temps from rlSrc1 & rlSrc2 that aren't still live in rlResult.
+     * Remove when spill is functional.
+     */
+    freeRegLocTemps(cUnit, rlResult, rlSrc1);
+    freeRegLocTemps(cUnit, rlResult, rlSrc2);
+    storeValueWide(cUnit, rlDest, rlResult);
+#if defined(TARGET_ARM)
+    oatClobber(cUnit, rLR);
+    oatUnmarkTemp(cUnit, rLR);  // Remove lr from the temp pool
+#endif
+}
+
+
+bool genShiftOpLong(CompilationUnit* cUnit, MIR* mir, RegLocation rlDest,
+                    RegLocation rlSrc1, RegLocation rlShift)
+{
+    int funcOffset;
+
+    switch( mir->dalvikInsn.opcode) {
+        case OP_SHL_LONG:
+        case OP_SHL_LONG_2ADDR:
+            funcOffset = OFFSETOF_MEMBER(Thread, pShlLong);
+            break;
+        case OP_SHR_LONG:
+        case OP_SHR_LONG_2ADDR:
+            funcOffset = OFFSETOF_MEMBER(Thread, pShrLong);
+            break;
+        case OP_USHR_LONG:
+        case OP_USHR_LONG_2ADDR:
+            funcOffset = OFFSETOF_MEMBER(Thread, pUshrLong);
+            break;
+        default:
+            LOG(FATAL) << "Unexpected case";
+            return true;
+    }
+    oatFlushAllRegs(cUnit);   /* Send everything to home location */
+    int rTgt = loadHelper(cUnit, funcOffset);
+    loadValueDirectWideFixed(cUnit, rlSrc1, rARG0, rARG1);
+    loadValueDirect(cUnit, rlShift, rARG2);
+    callRuntimeHelper(cUnit, rTgt);
+    RegLocation rlResult = oatGetReturnWide(cUnit);
+    storeValueWide(cUnit, rlDest, rlResult);
+    return false;
+}
+
+
+bool genArithOpInt(CompilationUnit* cUnit, MIR* mir, RegLocation rlDest,
+                   RegLocation rlSrc1, RegLocation rlSrc2)
+{
+    OpKind op = kOpBkpt;
+    bool callOut = false;
+    bool checkZero = false;
+    bool unary = false;
+    int retReg = rRET0;
+    int funcOffset;
+    RegLocation rlResult;
+    bool shiftOp = false;
+
+    switch (mir->dalvikInsn.opcode) {
+        case OP_NEG_INT:
+            op = kOpNeg;
+            unary = true;
+            break;
+        case OP_NOT_INT:
+            op = kOpMvn;
+            unary = true;
+            break;
+        case OP_ADD_INT:
+        case OP_ADD_INT_2ADDR:
+            op = kOpAdd;
+            break;
+        case OP_SUB_INT:
+        case OP_SUB_INT_2ADDR:
+            op = kOpSub;
+            break;
+        case OP_MUL_INT:
+        case OP_MUL_INT_2ADDR:
+            op = kOpMul;
+            break;
+        case OP_DIV_INT:
+        case OP_DIV_INT_2ADDR:
+            callOut = true;
+            checkZero = true;
+            funcOffset = OFFSETOF_MEMBER(Thread, pIdiv);
+            retReg = rRET0;
+            break;
+        /* NOTE: returns in r1 */
+        case OP_REM_INT:
+        case OP_REM_INT_2ADDR:
+            callOut = true;
+            checkZero = true;
+            funcOffset = OFFSETOF_MEMBER(Thread, pIdivmod);
+            retReg = rRET1;
+            break;
+        case OP_AND_INT:
+        case OP_AND_INT_2ADDR:
+            op = kOpAnd;
+            break;
+        case OP_OR_INT:
+        case OP_OR_INT_2ADDR:
+            op = kOpOr;
+            break;
+        case OP_XOR_INT:
+        case OP_XOR_INT_2ADDR:
+            op = kOpXor;
+            break;
+        case OP_SHL_INT:
+        case OP_SHL_INT_2ADDR:
+            shiftOp = true;
+            op = kOpLsl;
+            break;
+        case OP_SHR_INT:
+        case OP_SHR_INT_2ADDR:
+            shiftOp = true;
+            op = kOpAsr;
+            break;
+        case OP_USHR_INT:
+        case OP_USHR_INT_2ADDR:
+            shiftOp = true;
+            op = kOpLsr;
+            break;
+        default:
+            LOG(FATAL) << "Invalid word arith op: " <<
+                (int)mir->dalvikInsn.opcode;
+    }
+    if (!callOut) {
+        rlSrc1 = loadValue(cUnit, rlSrc1, kCoreReg);
+        if (unary) {
+            rlResult = oatEvalLoc(cUnit, rlDest, kCoreReg, true);
+            opRegReg(cUnit, op, rlResult.lowReg,
+                     rlSrc1.lowReg);
+        } else {
+            rlSrc2 = loadValue(cUnit, rlSrc2, kCoreReg);
+            if (shiftOp) {
+                int tReg = oatAllocTemp(cUnit);
+                opRegRegImm(cUnit, kOpAnd, tReg, rlSrc2.lowReg, 31);
+                rlResult = oatEvalLoc(cUnit, rlDest, kCoreReg, true);
+                opRegRegReg(cUnit, op, rlResult.lowReg,
+                            rlSrc1.lowReg, tReg);
+                oatFreeTemp(cUnit, tReg);
+            } else {
+                rlResult = oatEvalLoc(cUnit, rlDest, kCoreReg, true);
+                opRegRegReg(cUnit, op, rlResult.lowReg,
+                            rlSrc1.lowReg, rlSrc2.lowReg);
+            }
+        }
+        storeValue(cUnit, rlDest, rlResult);
+    } else {
+        RegLocation rlResult;
+        oatFlushAllRegs(cUnit);   /* Send everything to home location */
+        loadValueDirectFixed(cUnit, rlSrc2, rRET1);
+        int rTgt = loadHelper(cUnit, funcOffset);
+        loadValueDirectFixed(cUnit, rlSrc1, rARG0);
+        if (checkZero) {
+            genImmedCheck(cUnit, kCondEq, rARG1, 0, mir, kThrowDivZero);
+        }
+        callRuntimeHelper(cUnit, rTgt);
+        if (retReg == rRET0)
+            rlResult = oatGetReturn(cUnit);
+        else
+            rlResult = oatGetReturnAlt(cUnit);
+        storeValue(cUnit, rlDest, rlResult);
+    }
+    return false;
+}
+
+/*
+ * The following are the first-level codegen routines that analyze the format
+ * of each bytecode then either dispatch special purpose codegen routines
+ * or produce corresponding Thumb instructions directly.
+ */
+
+bool isPowerOfTwo(int x)
+{
+    return (x & (x - 1)) == 0;
+}
+
+// Returns true if no more than two bits are set in 'x'.
+bool isPopCountLE2(unsigned int x)
+{
+    x &= x - 1;
+    return (x & (x - 1)) == 0;
+}
+
+// Returns the index of the lowest set bit in 'x'.
+int lowestSetBit(unsigned int x) {
+    int bit_posn = 0;
+    while ((x & 0xf) == 0) {
+        bit_posn += 4;
+        x >>= 4;
+    }
+    while ((x & 1) == 0) {
+        bit_posn++;
+        x >>= 1;
+    }
+    return bit_posn;
+}
+
+// Returns true if it added instructions to 'cUnit' to divide 'rlSrc' by 'lit'
+// and store the result in 'rlDest'.
+bool handleEasyDivide(CompilationUnit* cUnit, Opcode dalvikOpcode,
+                      RegLocation rlSrc, RegLocation rlDest, int lit)
+{
+    if (lit < 2 || !isPowerOfTwo(lit)) {
+        return false;
+    }
+    int k = lowestSetBit(lit);
+    if (k >= 30) {
+        // Avoid special cases.
+        return false;
+    }
+    bool div = (dalvikOpcode == OP_DIV_INT_LIT8 ||
+                dalvikOpcode == OP_DIV_INT_LIT16);
+    rlSrc = loadValue(cUnit, rlSrc, kCoreReg);
+    RegLocation rlResult = oatEvalLoc(cUnit, rlDest, kCoreReg, true);
+    if (div) {
+        int tReg = oatAllocTemp(cUnit);
+        if (lit == 2) {
+            // Division by 2 is by far the most common division by constant.
+            opRegRegImm(cUnit, kOpLsr, tReg, rlSrc.lowReg, 32 - k);
+            opRegRegReg(cUnit, kOpAdd, tReg, tReg, rlSrc.lowReg);
+            opRegRegImm(cUnit, kOpAsr, rlResult.lowReg, tReg, k);
+        } else {
+            opRegRegImm(cUnit, kOpAsr, tReg, rlSrc.lowReg, 31);
+            opRegRegImm(cUnit, kOpLsr, tReg, tReg, 32 - k);
+            opRegRegReg(cUnit, kOpAdd, tReg, tReg, rlSrc.lowReg);
+            opRegRegImm(cUnit, kOpAsr, rlResult.lowReg, tReg, k);
+        }
+    } else {
+        int cReg = oatAllocTemp(cUnit);
+        loadConstant(cUnit, cReg, lit - 1);
+        int tReg1 = oatAllocTemp(cUnit);
+        int tReg2 = oatAllocTemp(cUnit);
+        if (lit == 2) {
+            opRegRegImm(cUnit, kOpLsr, tReg1, rlSrc.lowReg, 32 - k);
+            opRegRegReg(cUnit, kOpAdd, tReg2, tReg1, rlSrc.lowReg);
+            opRegRegReg(cUnit, kOpAnd, tReg2, tReg2, cReg);
+            opRegRegReg(cUnit, kOpSub, rlResult.lowReg, tReg2, tReg1);
+        } else {
+            opRegRegImm(cUnit, kOpAsr, tReg1, rlSrc.lowReg, 31);
+            opRegRegImm(cUnit, kOpLsr, tReg1, tReg1, 32 - k);
+            opRegRegReg(cUnit, kOpAdd, tReg2, tReg1, rlSrc.lowReg);
+            opRegRegReg(cUnit, kOpAnd, tReg2, tReg2, cReg);
+            opRegRegReg(cUnit, kOpSub, rlResult.lowReg, tReg2, tReg1);
+        }
+    }
+    storeValue(cUnit, rlDest, rlResult);
+    return true;
+}
+
+void genMultiplyByTwoBitMultiplier(CompilationUnit* cUnit, RegLocation rlSrc,
+                                   RegLocation rlResult, int lit,
+                                   int firstBit, int secondBit)
+{
+    opRegRegRegShift(cUnit, kOpAdd, rlResult.lowReg, rlSrc.lowReg, rlSrc.lowReg,
+                     encodeShift(kArmLsl, secondBit - firstBit));
+    if (firstBit != 0) {
+        opRegRegImm(cUnit, kOpLsl, rlResult.lowReg, rlResult.lowReg, firstBit);
+    }
+}
+
+// Returns true if it added instructions to 'cUnit' to multiply 'rlSrc' by 'lit'
+// and store the result in 'rlDest'.
+bool handleEasyMultiply(CompilationUnit* cUnit, RegLocation rlSrc,
+                        RegLocation rlDest, int lit)
+{
+    // Can we simplify this multiplication?
+    bool powerOfTwo = false;
+    bool popCountLE2 = false;
+    bool powerOfTwoMinusOne = false;
+    if (lit < 2) {
+        // Avoid special cases.
+        return false;
+    } else if (isPowerOfTwo(lit)) {
+        powerOfTwo = true;
+    } else if (isPopCountLE2(lit)) {
+        popCountLE2 = true;
+    } else if (isPowerOfTwo(lit + 1)) {
+        powerOfTwoMinusOne = true;
+    } else {
+        return false;
+    }
+    rlSrc = loadValue(cUnit, rlSrc, kCoreReg);
+    RegLocation rlResult = oatEvalLoc(cUnit, rlDest, kCoreReg, true);
+    if (powerOfTwo) {
+        // Shift.
+        opRegRegImm(cUnit, kOpLsl, rlResult.lowReg, rlSrc.lowReg,
+                    lowestSetBit(lit));
+    } else if (popCountLE2) {
+        // Shift and add and shift.
+        int firstBit = lowestSetBit(lit);
+        int secondBit = lowestSetBit(lit ^ (1 << firstBit));
+        genMultiplyByTwoBitMultiplier(cUnit, rlSrc, rlResult, lit,
+                                      firstBit, secondBit);
+    } else {
+        // Reverse subtract: (src << (shift + 1)) - src.
+        DCHECK(powerOfTwoMinusOne);
+        // TUNING: rsb dst, src, src lsl#lowestSetBit(lit + 1)
+        int tReg = oatAllocTemp(cUnit);
+        opRegRegImm(cUnit, kOpLsl, tReg, rlSrc.lowReg, lowestSetBit(lit + 1));
+        opRegRegReg(cUnit, kOpSub, rlResult.lowReg, tReg, rlSrc.lowReg);
+    }
+    storeValue(cUnit, rlDest, rlResult);
+    return true;
+}
+
+bool genArithOpIntLit(CompilationUnit* cUnit, MIR* mir, RegLocation rlDest,
+                      RegLocation rlSrc, int lit)
+{
+    Opcode dalvikOpcode = mir->dalvikInsn.opcode;
+    RegLocation rlResult;
+    OpKind op = (OpKind)0;      /* Make gcc happy */
+    int shiftOp = false;
+    bool isDiv = false;
+    int funcOffset;
+    int rTgt;
+
+    switch (dalvikOpcode) {
+        case OP_RSUB_INT_LIT8:
+        case OP_RSUB_INT: {
+            int tReg;
+            //TUNING: add support for use of Arm rsub op
+            rlSrc = loadValue(cUnit, rlSrc, kCoreReg);
+            tReg = oatAllocTemp(cUnit);
+            loadConstant(cUnit, tReg, lit);
+            rlResult = oatEvalLoc(cUnit, rlDest, kCoreReg, true);
+            opRegRegReg(cUnit, kOpSub, rlResult.lowReg,
+                        tReg, rlSrc.lowReg);
+            storeValue(cUnit, rlDest, rlResult);
+            return false;
+            break;
+        }
+
+        case OP_ADD_INT_LIT8:
+        case OP_ADD_INT_LIT16:
+            op = kOpAdd;
+            break;
+        case OP_MUL_INT_LIT8:
+        case OP_MUL_INT_LIT16: {
+            if (handleEasyMultiply(cUnit, rlSrc, rlDest, lit)) {
+                return false;
+            }
+            op = kOpMul;
+            break;
+        }
+        case OP_AND_INT_LIT8:
+        case OP_AND_INT_LIT16:
+            op = kOpAnd;
+            break;
+        case OP_OR_INT_LIT8:
+        case OP_OR_INT_LIT16:
+            op = kOpOr;
+            break;
+        case OP_XOR_INT_LIT8:
+        case OP_XOR_INT_LIT16:
+            op = kOpXor;
+            break;
+        case OP_SHL_INT_LIT8:
+            lit &= 31;
+            shiftOp = true;
+            op = kOpLsl;
+            break;
+        case OP_SHR_INT_LIT8:
+            lit &= 31;
+            shiftOp = true;
+            op = kOpAsr;
+            break;
+        case OP_USHR_INT_LIT8:
+            lit &= 31;
+            shiftOp = true;
+            op = kOpLsr;
+            break;
+
+        case OP_DIV_INT_LIT8:
+        case OP_DIV_INT_LIT16:
+        case OP_REM_INT_LIT8:
+        case OP_REM_INT_LIT16:
+            if (lit == 0) {
+                genImmedCheck(cUnit, kCondAl, 0, 0, mir, kThrowDivZero);
+                return false;
+            }
+            if (handleEasyDivide(cUnit, dalvikOpcode, rlSrc, rlDest, lit)) {
+                return false;
+            }
+            oatFlushAllRegs(cUnit);   /* Everything to home location */
+            loadValueDirectFixed(cUnit, rlSrc, rARG0);
+            oatClobber(cUnit, rARG0);
+            if ((dalvikOpcode == OP_DIV_INT_LIT8) ||
+                (dalvikOpcode == OP_DIV_INT_LIT16)) {
+                funcOffset = OFFSETOF_MEMBER(Thread, pIdiv);
+                isDiv = true;
+            } else {
+                funcOffset = OFFSETOF_MEMBER(Thread, pIdivmod);
+                isDiv = false;
+            }
+            rTgt = loadHelper(cUnit, funcOffset);
+            loadConstant(cUnit, rARG1, lit);
+            callRuntimeHelper(cUnit, rTgt);
+            if (isDiv)
+                rlResult = oatGetReturn(cUnit);
+            else
+                rlResult = oatGetReturnAlt(cUnit);
+            storeValue(cUnit, rlDest, rlResult);
+            return false;
+            break;
+        default:
+            return true;
+    }
+    rlSrc = loadValue(cUnit, rlSrc, kCoreReg);
+    rlResult = oatEvalLoc(cUnit, rlDest, kCoreReg, true);
+    // Avoid shifts by literal 0 - no support in Thumb.  Change to copy
+    if (shiftOp && (lit == 0)) {
+        genRegCopy(cUnit, rlResult.lowReg, rlSrc.lowReg);
+    } else {
+        opRegRegImm(cUnit, op, rlResult.lowReg, rlSrc.lowReg, lit);
+    }
+    storeValue(cUnit, rlDest, rlResult);
+    return false;
+}
+
+bool genArithOpLong(CompilationUnit* cUnit, MIR* mir, RegLocation rlDest,
+                    RegLocation rlSrc1, RegLocation rlSrc2)
+{
+    RegLocation rlResult;
+    OpKind firstOp = kOpBkpt;
+    OpKind secondOp = kOpBkpt;
+    bool callOut = false;
+    bool checkZero = false;
+    int funcOffset;
+    int retReg = rRET0;
+
+    switch (mir->dalvikInsn.opcode) {
+        case OP_NOT_LONG:
+            rlSrc2 = loadValueWide(cUnit, rlSrc2, kCoreReg);
+            rlResult = oatEvalLoc(cUnit, rlDest, kCoreReg, true);
+            // Check for destructive overlap
+            if (rlResult.lowReg == rlSrc2.highReg) {
+                int tReg = oatAllocTemp(cUnit);
+                genRegCopy(cUnit, tReg, rlSrc2.highReg);
+                opRegReg(cUnit, kOpMvn, rlResult.lowReg, rlSrc2.lowReg);
+                opRegReg(cUnit, kOpMvn, rlResult.highReg, tReg);
+                oatFreeTemp(cUnit, tReg);
+            } else {
+                opRegReg(cUnit, kOpMvn, rlResult.lowReg, rlSrc2.lowReg);
+                opRegReg(cUnit, kOpMvn, rlResult.highReg, rlSrc2.highReg);
+            }
+            storeValueWide(cUnit, rlDest, rlResult);
+            return false;
+            break;
+        case OP_ADD_LONG:
+        case OP_ADD_LONG_2ADDR:
+            firstOp = kOpAdd;
+            secondOp = kOpAdc;
+            break;
+        case OP_SUB_LONG:
+        case OP_SUB_LONG_2ADDR:
+            firstOp = kOpSub;
+            secondOp = kOpSbc;
+            break;
+        case OP_MUL_LONG:
+        case OP_MUL_LONG_2ADDR:
+            callOut = true;
+            retReg = rRET0;
+            funcOffset = OFFSETOF_MEMBER(Thread, pLmul);
+            break;
+        case OP_DIV_LONG:
+        case OP_DIV_LONG_2ADDR:
+            callOut = true;
+            checkZero = true;
+            retReg = rRET0;
+            funcOffset = OFFSETOF_MEMBER(Thread, pLdivmod);
+            break;
+        /* NOTE - result is in rARG2/rARG3 instead of rRET0/rRET1 */
+        // FIXME: is true, or could be made true, or other targets?
+        case OP_REM_LONG:
+        case OP_REM_LONG_2ADDR:
+            callOut = true;
+            checkZero = true;
+            funcOffset = OFFSETOF_MEMBER(Thread, pLdivmod);
+            retReg = rARG2;
+            break;
+        case OP_AND_LONG_2ADDR:
+        case OP_AND_LONG:
+            firstOp = kOpAnd;
+            secondOp = kOpAnd;
+            break;
+        case OP_OR_LONG:
+        case OP_OR_LONG_2ADDR:
+            firstOp = kOpOr;
+            secondOp = kOpOr;
+            break;
+        case OP_XOR_LONG:
+        case OP_XOR_LONG_2ADDR:
+            firstOp = kOpXor;
+            secondOp = kOpXor;
+            break;
+        case OP_NEG_LONG: {
+            rlSrc2 = loadValueWide(cUnit, rlSrc2, kCoreReg);
+            rlResult = oatEvalLoc(cUnit, rlDest, kCoreReg, true);
+            int zReg = oatAllocTemp(cUnit);
+            loadConstantNoClobber(cUnit, zReg, 0);
+            // Check for destructive overlap
+            if (rlResult.lowReg == rlSrc2.highReg) {
+                int tReg = oatAllocTemp(cUnit);
+                opRegRegReg(cUnit, kOpSub, rlResult.lowReg,
+                            zReg, rlSrc2.lowReg);
+                opRegRegReg(cUnit, kOpSbc, rlResult.highReg,
+                            zReg, tReg);
+                oatFreeTemp(cUnit, tReg);
+            } else {
+                opRegRegReg(cUnit, kOpSub, rlResult.lowReg,
+                            zReg, rlSrc2.lowReg);
+                opRegRegReg(cUnit, kOpSbc, rlResult.highReg,
+                            zReg, rlSrc2.highReg);
+            }
+            oatFreeTemp(cUnit, zReg);
+            storeValueWide(cUnit, rlDest, rlResult);
+            return false;
+        }
+        default:
+            LOG(FATAL) << "Invalid long arith op";
+    }
+    if (!callOut) {
+        genLong3Addr(cUnit, mir, firstOp, secondOp, rlDest, rlSrc1, rlSrc2);
+    } else {
+        int rTgt;
+        oatFlushAllRegs(cUnit);   /* Send everything to home location */
+        if (checkZero) {
+            loadValueDirectWideFixed(cUnit, rlSrc2, rARG2, rARG3);
+            rTgt = loadHelper(cUnit, funcOffset);
+            loadValueDirectWideFixed(cUnit, rlSrc1, rARG0, rARG1);
+            int tReg = oatAllocTemp(cUnit);
+#if defined(TARGET_ARM)
+            newLIR4(cUnit, kThumb2OrrRRRs, tReg, rARG2, rARG3, 0);
+            oatFreeTemp(cUnit, tReg);
+            genCheck(cUnit, kCondEq, mir, kThrowDivZero);
+#else
+            opRegRegReg(cUnit, kOpOr, tReg, rARG2, rARG3);
+            genImmedCheck(cUnit, kCondEq, mir, tReg, 0, mir, kThrowDivZero);
+            oatFreeTemp(cUnit, tReg);
+#endif
+        } else {
+            rTgt = loadHelper(cUnit, funcOffset);
+            loadValueDirectWideFixed(cUnit, rlSrc1, rARG0, rARG1);
+            loadValueDirectWideFixed(cUnit, rlSrc2, rARG2, rARG3);
+        }
+        callRuntimeHelper(cUnit, rTgt);
+        // Adjust return regs in to handle case of rem returning rARG2/rARG3
+        if (retReg == rRET0)
+            rlResult = oatGetReturnWide(cUnit);
+        else
+            rlResult = oatGetReturnWideAlt(cUnit);
+        storeValueWide(cUnit, rlDest, rlResult);
+    }
+    return false;
+}
+
+bool genConversionCall(CompilationUnit* cUnit, MIR* mir, int funcOffset,
+                       int srcSize, int tgtSize)
+{
+    /*
+     * Don't optimize the register usage since it calls out to support
+     * functions
+     */
+    RegLocation rlSrc;
+    RegLocation rlDest;
+    oatFlushAllRegs(cUnit);   /* Send everything to home location */
+    int rTgt = loadHelper(cUnit, funcOffset);
+    if (srcSize == 1) {
+        rlSrc = oatGetSrc(cUnit, mir, 0);
+        loadValueDirectFixed(cUnit, rlSrc, rARG0);
+    } else {
+        rlSrc = oatGetSrcWide(cUnit, mir, 0, 1);
+        loadValueDirectWideFixed(cUnit, rlSrc, rARG0, rARG1);
+    }
+    callRuntimeHelper(cUnit, rTgt);
+    if (tgtSize == 1) {
+        RegLocation rlResult;
+        rlDest = oatGetDest(cUnit, mir, 0);
+        rlResult = oatGetReturn(cUnit);
+        storeValue(cUnit, rlDest, rlResult);
+    } else {
+        RegLocation rlResult;
+        rlDest = oatGetDestWide(cUnit, mir, 0, 1);
+        rlResult = oatGetReturnWide(cUnit);
+        storeValueWide(cUnit, rlDest, rlResult);
+    }
+    return false;
+}
+
+void genNegFloat(CompilationUnit* cUnit, RegLocation rlDest, RegLocation rlSrc);
+bool genArithOpFloatPortable(CompilationUnit* cUnit, MIR* mir,
+                             RegLocation rlDest, RegLocation rlSrc1,
+                             RegLocation rlSrc2)
+{
+    RegLocation rlResult;
+    int funcOffset;
+
+    switch (mir->dalvikInsn.opcode) {
+        case OP_ADD_FLOAT_2ADDR:
+        case OP_ADD_FLOAT:
+            funcOffset = OFFSETOF_MEMBER(Thread, pFadd);
+            break;
+        case OP_SUB_FLOAT_2ADDR:
+        case OP_SUB_FLOAT:
+            funcOffset = OFFSETOF_MEMBER(Thread, pFsub);
+            break;
+        case OP_DIV_FLOAT_2ADDR:
+        case OP_DIV_FLOAT:
+            funcOffset = OFFSETOF_MEMBER(Thread, pFdiv);
+            break;
+        case OP_MUL_FLOAT_2ADDR:
+        case OP_MUL_FLOAT:
+            funcOffset = OFFSETOF_MEMBER(Thread, pFmul);
+            break;
+        case OP_REM_FLOAT_2ADDR:
+        case OP_REM_FLOAT:
+            funcOffset = OFFSETOF_MEMBER(Thread, pFmodf);
+            break;
+        case OP_NEG_FLOAT: {
+            genNegFloat(cUnit, rlDest, rlSrc1);
+            return false;
+        }
+        default:
+            return true;
+    }
+    oatFlushAllRegs(cUnit);   /* Send everything to home location */
+    int rTgt = loadHelper(cUnit, funcOffset);
+    loadValueDirectFixed(cUnit, rlSrc1, rARG0);
+    loadValueDirectFixed(cUnit, rlSrc2, rARG1);
+    callRuntimeHelper(cUnit, rTgt);
+    rlResult = oatGetReturn(cUnit);
+    storeValue(cUnit, rlDest, rlResult);
+    return false;
+}
+
+void genNegDouble(CompilationUnit* cUnit, RegLocation rlDst, RegLocation rlSrc);
+bool genArithOpDoublePortable(CompilationUnit* cUnit, MIR* mir,
+                              RegLocation rlDest, RegLocation rlSrc1,
+                              RegLocation rlSrc2)
+{
+    RegLocation rlResult;
+    int funcOffset;
+
+    switch (mir->dalvikInsn.opcode) {
+        case OP_ADD_DOUBLE_2ADDR:
+        case OP_ADD_DOUBLE:
+            funcOffset = OFFSETOF_MEMBER(Thread, pDadd);
+            break;
+        case OP_SUB_DOUBLE_2ADDR:
+        case OP_SUB_DOUBLE:
+            funcOffset = OFFSETOF_MEMBER(Thread, pDsub);
+            break;
+        case OP_DIV_DOUBLE_2ADDR:
+        case OP_DIV_DOUBLE:
+            funcOffset = OFFSETOF_MEMBER(Thread, pDdiv);
+            break;
+        case OP_MUL_DOUBLE_2ADDR:
+        case OP_MUL_DOUBLE:
+            funcOffset = OFFSETOF_MEMBER(Thread, pDmul);
+            break;
+        case OP_REM_DOUBLE_2ADDR:
+        case OP_REM_DOUBLE:
+            funcOffset = OFFSETOF_MEMBER(Thread, pFmod);
+            break;
+        case OP_NEG_DOUBLE: {
+            genNegDouble(cUnit, rlDest, rlSrc1);
+            return false;
+        }
+        default:
+            return true;
+    }
+    oatFlushAllRegs(cUnit);   /* Send everything to home location */
+    int rTgt = loadHelper(cUnit, funcOffset);
+    loadValueDirectWideFixed(cUnit, rlSrc1, rARG0, rARG1);
+    loadValueDirectWideFixed(cUnit, rlSrc2, rARG2, rARG3);
+    callRuntimeHelper(cUnit, rTgt);
+    rlResult = oatGetReturnWide(cUnit);
+    storeValueWide(cUnit, rlDest, rlResult);
+    return false;
+}
+
+bool genConversionPortable(CompilationUnit* cUnit, MIR* mir)
+{
+    Opcode opcode = mir->dalvikInsn.opcode;
+
+    switch (opcode) {
+        case OP_INT_TO_FLOAT:
+            return genConversionCall(cUnit, mir, OFFSETOF_MEMBER(Thread, pI2f),
+                                     1, 1);
+        case OP_FLOAT_TO_INT:
+            return genConversionCall(cUnit, mir, OFFSETOF_MEMBER(Thread, pF2iz),
+                                     1, 1);
+        case OP_DOUBLE_TO_FLOAT:
+            return genConversionCall(cUnit, mir, OFFSETOF_MEMBER(Thread, pD2f),
+                                     2, 1);
+        case OP_FLOAT_TO_DOUBLE:
+            return genConversionCall(cUnit, mir, OFFSETOF_MEMBER(Thread, pF2d),
+                                     1, 2);
+        case OP_INT_TO_DOUBLE:
+            return genConversionCall(cUnit, mir, OFFSETOF_MEMBER(Thread, pI2d),
+                                     1, 2);
+        case OP_DOUBLE_TO_INT:
+            return genConversionCall(cUnit, mir, OFFSETOF_MEMBER(Thread, pD2iz),
+                                     2, 1);
+        case OP_FLOAT_TO_LONG:
+            return genConversionCall(cUnit, mir, OFFSETOF_MEMBER(Thread,
+                                     pF2l), 1, 2);
+        case OP_LONG_TO_FLOAT:
+            return genConversionCall(cUnit, mir, OFFSETOF_MEMBER(Thread, pL2f),
+                                     2, 1);
+        case OP_DOUBLE_TO_LONG:
+            return genConversionCall(cUnit, mir, OFFSETOF_MEMBER(Thread,
+                                     pD2l), 2, 2);
+        case OP_LONG_TO_DOUBLE:
+            return genConversionCall(cUnit, mir, OFFSETOF_MEMBER(Thread, pL2d),
+                                     2, 2);
+        default:
+            return true;
+    }
+    return false;
+}
+
+/*
+ * Generate callout to updateDebugger. Note that we're overloading
+ * the use of rSUSPEND here.  When the debugger is active, this
+ * register holds the address of the update function.  So, if it's
+ * non-null, we call out to it.
+ *
+ * Note also that rRET0 and rRET1 must be preserved across this
+ * code.  This must be handled by the stub.
+ */
+void genDebuggerUpdate(CompilationUnit* cUnit, int32_t offset)
+{
+    // Following DCHECK verifies that dPC is in range of single load immediate
+    DCHECK((offset == DEBUGGER_METHOD_ENTRY) ||
+           (offset == DEBUGGER_METHOD_EXIT) || ((offset & 0xffff) == offset));
+    oatClobberCalleeSave(cUnit);
+#if defined(TARGET_ARM)
+    opRegImm(cUnit, kOpCmp, rSUSPEND, 0);
+    genIT(cUnit, kArmCondNe, "T");
+    loadConstant(cUnit, rARG2, offset);     // arg2 <- Entry code
+    opReg(cUnit, kOpBlx, rSUSPEND);
+#else
+    LIR* branch = genCmpImmBranch(cUnit, kCondEq, rSUSPEND, 0);
+    loadConstant(cUnit, rARG2, offset);
+    opReg(cUnit, kOpBlx, rSUSPEND);
+    LIR* target = newLIR0(cUnit, kPseudoTargetLabel);
+    target->defMask = ENCODE_ALL;
+    branch->target = (LIR*)target;
+#endif
+    oatFreeTemp(cUnit, rARG2);
+}
+
+/* Check if we need to check for pending suspend request */
+void genSuspendTest(CompilationUnit* cUnit, MIR* mir)
+{
+    if (NO_SUSPEND || (mir->optimizationFlags & MIR_IGNORE_SUSPEND_CHECK)) {
+        return;
+    }
+    oatFlushAllRegs(cUnit);
+    LIR* branch;
+    if (cUnit->genDebugger) {
+        // If generating code for the debugger, always check for suspension
+        branch = genUnconditionalBranch(cUnit, NULL);
+    } else {
+#if defined(TARGET_ARM)
+        // In non-debug case, only check periodically
+        newLIR2(cUnit, kThumbSubRI8, rSUSPEND, 1);
+        branch = opCondBranch(cUnit, kCondEq);
+#else
+        opRegImm(cUnit, kOpSub, rSUSPEND, 1);
+        branch = opCompareBranchImm(cUnit, kCondEq, rSUSPEND, 0);
+#endif
+    }
+    LIR* retLab = newLIR0(cUnit, kPseudoTargetLabel);
+    retLab->defMask = ENCODE_ALL;
+    LIR* target = (LIR*)oatNew(cUnit, sizeof(LIR), true, kAllocLIR);
+    target->dalvikOffset = cUnit->currentDalvikOffset;
+    target->opcode = kPseudoSuspendTarget;
+    target->operands[0] = (intptr_t)retLab;
+    target->operands[1] = mir->offset;
+    branch->target = (LIR*)target;
+    oatInsertGrowableList(cUnit, &cUnit->suspendLaunchpads, (intptr_t)target);
+}
+
+}  // namespace art
diff --git a/src/compiler/codegen/GenInvoke.cc b/src/compiler/codegen/GenInvoke.cc
new file mode 100644
index 0000000..a201010
--- /dev/null
+++ b/src/compiler/codegen/GenInvoke.cc
@@ -0,0 +1,506 @@
+/*
+ * Copyright (C) 2012 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.
+ */
+
+namespace art {
+
+/*
+ * This source files contains "gen" codegen routines that should
+ * be applicable to most targets.  Only mid-level support utilities
+ * and "op" calls may be used here.
+ */
+
+
+/*
+ * x86 targets will likely be different enough to need their own
+ * invoke gen routies.
+ */
+#if defined(TARGET_ARM) || defined (TARGET_MIPS)
+typedef int (*NextCallInsn)(CompilationUnit*, MIR*, int, uint32_t dexIdx,
+                            uint32_t methodIdx);
+/*
+ * If there are any ins passed in registers that have not been promoted
+ * to a callee-save register, flush them to the frame.  Perform intial
+ * assignment of promoted arguments.
+ */
+void flushIns(CompilationUnit* cUnit)
+{
+    if (cUnit->numIns == 0)
+        return;
+    int firstArgReg = rARG1;
+    int lastArgReg = rARG3;
+    int startVReg = cUnit->numDalvikRegisters - cUnit->numIns;
+    /*
+     * Arguments passed in registers should be flushed
+     * to their backing locations in the frame for now.
+     * Also, we need to do initial assignment for promoted
+     * arguments.  NOTE: an older version of dx had an issue
+     * in which it would reuse static method argument registers.
+     * This could result in the same Dalvik virtual register
+     * being promoted to both core and fp regs.  In those
+     * cases, copy argument to both.  This will be uncommon
+     * enough that it isn't worth attempting to optimize.
+     */
+    for (int i = 0; i < cUnit->numIns; i++) {
+        PromotionMap vMap = cUnit->promotionMap[startVReg + i];
+        if (i <= (lastArgReg - firstArgReg)) {
+            // If arriving in register
+            if (vMap.coreLocation == kLocPhysReg) {
+                genRegCopy(cUnit, vMap.coreReg, firstArgReg + i);
+            }
+            if (vMap.fpLocation == kLocPhysReg) {
+                genRegCopy(cUnit, vMap.fpReg, firstArgReg + i);
+            }
+            // Also put a copy in memory in case we're partially promoted
+            storeBaseDisp(cUnit, rSP, oatSRegOffset(cUnit, startVReg + i),
+                          firstArgReg + i, kWord);
+        } else {
+            // If arriving in frame & promoted
+            if (vMap.coreLocation == kLocPhysReg) {
+                loadWordDisp(cUnit, rSP, oatSRegOffset(cUnit, startVReg + i),
+                             vMap.coreReg);
+            }
+            if (vMap.fpLocation == kLocPhysReg) {
+                loadWordDisp(cUnit, rSP, oatSRegOffset(cUnit, startVReg + i),
+                             vMap.fpReg);
+            }
+        }
+    }
+}
+
+/*
+ * Bit of a hack here - in leiu of a real scheduling pass,
+ * emit the next instruction in static & direct invoke sequences.
+ */
+int nextSDCallInsn(CompilationUnit* cUnit, MIR* mir,
+                   int state, uint32_t dexIdx, uint32_t unused)
+{
+    switch(state) {
+        case 0:  // Get the current Method* [sets rARG0]
+            loadCurrMethodDirect(cUnit, rARG0);
+            break;
+        case 1:  // Get method->dex_cache_resolved_methods_
+            loadWordDisp(cUnit, rARG0,
+                Method::DexCacheResolvedMethodsOffset().Int32Value(),
+                rARG0);
+            break;
+        case 2:  // Grab target method*
+            loadWordDisp(cUnit, rARG0,
+                Array::DataOffset(sizeof(Object*)).Int32Value() + dexIdx * 4,
+                rARG0);
+            break;
+        case 3:  // Grab the code from the method*
+            loadWordDisp(cUnit, rARG0, Method::GetCodeOffset().Int32Value(),
+                         rLINK);
+            break;
+        default:
+            return -1;
+    }
+    return state + 1;
+}
+
+/*
+ * Bit of a hack here - in leiu of a real scheduling pass,
+ * emit the next instruction in a virtual invoke sequence.
+ * We can use rLR as a temp prior to target address loading
+ * Note also that we'll load the first argument ("this") into
+ * rARG1 here rather than the standard loadArgRegs.
+ */
+int nextVCallInsn(CompilationUnit* cUnit, MIR* mir,
+                  int state, uint32_t dexIdx, uint32_t methodIdx)
+{
+    RegLocation rlArg;
+    /*
+     * This is the fast path in which the target virtual method is
+     * fully resolved at compile time.
+     */
+    switch(state) {
+        case 0:  // Get "this" [set rARG1]
+            rlArg = oatGetSrc(cUnit, mir, 0);
+            loadValueDirectFixed(cUnit, rlArg, rARG1);
+            break;
+        case 1: // Is "this" null? [use rARG1]
+            genNullCheck(cUnit, oatSSASrc(mir,0), rARG1, mir);
+            // get this->klass_ [use rARG1, set rLINK]
+            loadWordDisp(cUnit, rARG1, Object::ClassOffset().Int32Value(),
+                         rLINK);
+            break;
+        case 2: // Get this->klass_->vtable [usr rLINK, set rLINK]
+            loadWordDisp(cUnit, rLINK, Class::VTableOffset().Int32Value(),
+                         rLINK);
+            break;
+        case 3: // Get target method [use rLINK, set rARG0]
+            loadWordDisp(cUnit, rLINK, (methodIdx * 4) +
+                         Array::DataOffset(sizeof(Object*)).Int32Value(),
+                         rARG0);
+            break;
+        case 4: // Get the target compiled code address [uses rARG0, sets rLINK]
+            loadWordDisp(cUnit, rARG0, Method::GetCodeOffset().Int32Value(),
+                         rLINK);
+            break;
+        default:
+            return -1;
+    }
+    return state + 1;
+}
+
+/*
+ * Interleave launch code for INVOKE_SUPER.  See comments
+ * for nextVCallIns.
+ */
+int nextSuperCallInsn(CompilationUnit* cUnit, MIR* mir,
+                      int state, uint32_t dexIdx, uint32_t methodIdx)
+{
+    /*
+     * This is the fast path in which the target virtual method is
+     * fully resolved at compile time.  Note also that this path assumes
+     * that the check to verify that the target method index falls
+     * within the size of the super's vtable has been done at compile-time.
+     */
+    RegLocation rlArg;
+    switch(state) {
+        case 0: // Get current Method* [set rARG0]
+            loadCurrMethodDirect(cUnit, rARG0);
+            // Load "this" [set rARG1]
+            rlArg = oatGetSrc(cUnit, mir, 0);
+            loadValueDirectFixed(cUnit, rlArg, rARG1);
+            // Get method->declaring_class_ [use rARG0, set rLINK]
+            loadWordDisp(cUnit, rARG0,
+                         Method::DeclaringClassOffset().Int32Value(),
+                         rLINK);
+            // Is "this" null? [use rARG1]
+            genNullCheck(cUnit, oatSSASrc(mir,0), rARG1, mir);
+            break;
+        case 1: // Get method->declaring_class_->super_class [use/set rLINK]
+            loadWordDisp(cUnit, rLINK,
+                         Class::SuperClassOffset().Int32Value(), rLINK);
+            break;
+        case 2: // Get ...->super_class_->vtable [u/s rLINK]
+            loadWordDisp(cUnit, rLINK,
+                         Class::VTableOffset().Int32Value(), rLINK);
+            break;
+        case 3: // Get target method [use rLINK, set rARG0]
+            loadWordDisp(cUnit, rLINK, (methodIdx * 4) +
+                         Array::DataOffset(sizeof(Object*)).Int32Value(),
+                         rARG0);
+            break;
+        case 4: // Get the target compiled code address [uses rARG0, sets rLINK]
+            loadWordDisp(cUnit, rARG0, Method::GetCodeOffset().Int32Value(),
+                         rLINK);
+            break;
+        default:
+            return -1;
+    }
+    return state + 1;
+}
+
+int nextInvokeInsnSP(CompilationUnit* cUnit, MIR* mir, int trampoline,
+                     int state, uint32_t dexIdx, uint32_t methodIdx)
+{
+    /*
+     * This handles the case in which the base method is not fully
+     * resolved at compile time, we bail to a runtime helper.
+     */
+    if (state == 0) {
+        // Load trampoline target
+        loadWordDisp(cUnit, rSELF, trampoline, rLINK);
+        // Load rARG0 with method index
+        loadConstant(cUnit, rARG0, dexIdx);
+        return 1;
+    }
+    return -1;
+}
+
+int nextStaticCallInsnSP(CompilationUnit* cUnit, MIR* mir,
+                         int state, uint32_t dexIdx, uint32_t methodIdx)
+{
+  int trampoline = OFFSETOF_MEMBER(Thread, pInvokeStaticTrampolineWithAccessCheck);
+  return nextInvokeInsnSP(cUnit, mir, trampoline, state, dexIdx, 0);
+}
+
+int nextDirectCallInsnSP(CompilationUnit* cUnit, MIR* mir, int state,
+                         uint32_t dexIdx, uint32_t methodIdx)
+{
+  int trampoline = OFFSETOF_MEMBER(Thread, pInvokeDirectTrampolineWithAccessCheck);
+  return nextInvokeInsnSP(cUnit, mir, trampoline, state, dexIdx, 0);
+}
+
+int nextSuperCallInsnSP(CompilationUnit* cUnit, MIR* mir, int state,
+                        uint32_t dexIdx, uint32_t methodIdx)
+{
+  int trampoline = OFFSETOF_MEMBER(Thread, pInvokeSuperTrampolineWithAccessCheck);
+  return nextInvokeInsnSP(cUnit, mir, trampoline, state, dexIdx, 0);
+}
+
+int nextVCallInsnSP(CompilationUnit* cUnit, MIR* mir, int state,
+                    uint32_t dexIdx, uint32_t methodIdx)
+{
+  int trampoline = OFFSETOF_MEMBER(Thread, pInvokeVirtualTrampolineWithAccessCheck);
+  return nextInvokeInsnSP(cUnit, mir, trampoline, state, dexIdx, 0);
+}
+
+/*
+ * All invoke-interface calls bounce off of art_invoke_interface_trampoline,
+ * which will locate the target and continue on via a tail call.
+ */
+int nextInterfaceCallInsn(CompilationUnit* cUnit, MIR* mir, int state,
+                          uint32_t dexIdx, uint32_t unused)
+{
+  int trampoline = OFFSETOF_MEMBER(Thread, pInvokeInterfaceTrampoline);
+  return nextInvokeInsnSP(cUnit, mir, trampoline, state, dexIdx, 0);
+}
+
+int nextInterfaceCallInsnWithAccessCheck(CompilationUnit* cUnit, MIR* mir,
+                                         int state, uint32_t dexIdx,
+                                         uint32_t unused)
+{
+  int trampoline = OFFSETOF_MEMBER(Thread, pInvokeInterfaceTrampolineWithAccessCheck);
+  return nextInvokeInsnSP(cUnit, mir, trampoline, state, dexIdx, 0);
+}
+
+int loadArgRegs(CompilationUnit* cUnit, MIR* mir, DecodedInstruction* dInsn,
+                int callState, NextCallInsn nextCallInsn, uint32_t dexIdx,
+                uint32_t methodIdx, bool skipThis)
+{
+    int nextReg = rARG1;
+    int nextArg = 0;
+    if (skipThis) {
+        nextReg++;
+        nextArg++;
+    }
+    for (; (nextReg <= rARG3) && (nextArg < mir->ssaRep->numUses); nextReg++) {
+        RegLocation rlArg = oatGetRawSrc(cUnit, mir, nextArg++);
+        rlArg = oatUpdateRawLoc(cUnit, rlArg);
+        if (rlArg.wide && (nextReg <= rARG2)) {
+            loadValueDirectWideFixed(cUnit, rlArg, nextReg, nextReg + 1);
+            nextReg++;
+            nextArg++;
+        } else {
+            rlArg.wide = false;
+            loadValueDirectFixed(cUnit, rlArg, nextReg);
+        }
+        callState = nextCallInsn(cUnit, mir, callState, dexIdx, methodIdx);
+    }
+    return callState;
+}
+
+/*
+ * Load up to 5 arguments, the first three of which will be in
+ * rARG1 .. rARG3.  On entry rARG0 contains the current method pointer,
+ * and as part of the load sequence, it must be replaced with
+ * the target method pointer.  Note, this may also be called
+ * for "range" variants if the number of arguments is 5 or fewer.
+ */
+int genDalvikArgsNoRange(CompilationUnit* cUnit, MIR* mir,
+                         DecodedInstruction* dInsn, int callState,
+                         LIR** pcrLabel, NextCallInsn nextCallInsn,
+                         uint32_t dexIdx, uint32_t methodIdx, bool skipThis)
+{
+    RegLocation rlArg;
+
+    /* If no arguments, just return */
+    if (dInsn->vA == 0)
+        return callState;
+
+    callState = nextCallInsn(cUnit, mir, callState, dexIdx, methodIdx);
+
+    DCHECK_LE(dInsn->vA, 5U);
+    if (dInsn->vA > 3) {
+        uint32_t nextUse = 3;
+        //Detect special case of wide arg spanning arg3/arg4
+        RegLocation rlUse0 = oatGetRawSrc(cUnit, mir, 0);
+        RegLocation rlUse1 = oatGetRawSrc(cUnit, mir, 1);
+        RegLocation rlUse2 = oatGetRawSrc(cUnit, mir, 2);
+        if (((!rlUse0.wide && !rlUse1.wide) || rlUse0.wide) &&
+            rlUse2.wide) {
+            int reg;
+            // Wide spans, we need the 2nd half of uses[2].
+            rlArg = oatUpdateLocWide(cUnit, rlUse2);
+            if (rlArg.location == kLocPhysReg) {
+                reg = rlArg.highReg;
+            } else {
+                // rARG2 & rARG3 can safely be used here
+                reg = rARG3;
+                loadWordDisp(cUnit, rSP,
+                             oatSRegOffset(cUnit, rlArg.sRegLow) + 4, reg);
+                callState = nextCallInsn(cUnit, mir, callState, dexIdx,
+                                         methodIdx);
+            }
+            storeBaseDisp(cUnit, rSP, (nextUse + 1) * 4, reg, kWord);
+            storeBaseDisp(cUnit, rSP, 16 /* (3+1)*4 */, reg, kWord);
+            callState = nextCallInsn(cUnit, mir, callState, dexIdx, methodIdx);
+            nextUse++;
+        }
+        // Loop through the rest
+        while (nextUse < dInsn->vA) {
+            int lowReg;
+            int highReg;
+            rlArg = oatGetRawSrc(cUnit, mir, nextUse);
+            rlArg = oatUpdateRawLoc(cUnit, rlArg);
+            if (rlArg.location == kLocPhysReg) {
+                lowReg = rlArg.lowReg;
+                highReg = rlArg.highReg;
+            } else {
+                lowReg = rARG2;
+                highReg = rARG3;
+                if (rlArg.wide) {
+                    loadValueDirectWideFixed(cUnit, rlArg, lowReg, highReg);
+                } else {
+                    loadValueDirectFixed(cUnit, rlArg, lowReg);
+                }
+                callState = nextCallInsn(cUnit, mir, callState, dexIdx,
+                                         methodIdx);
+            }
+            int outsOffset = (nextUse + 1) * 4;
+            if (rlArg.wide) {
+                storeBaseDispWide(cUnit, rSP, outsOffset, lowReg, highReg);
+                nextUse += 2;
+            } else {
+                storeWordDisp(cUnit, rSP, outsOffset, lowReg);
+                nextUse++;
+            }
+            callState = nextCallInsn(cUnit, mir, callState, dexIdx, methodIdx);
+        }
+    }
+
+    callState = loadArgRegs(cUnit, mir, dInsn, callState, nextCallInsn,
+                            dexIdx, methodIdx, skipThis);
+
+    if (pcrLabel) {
+        *pcrLabel = genNullCheck(cUnit, oatSSASrc(mir,0), rARG1, mir);
+    }
+    return callState;
+}
+
+/*
+ * May have 0+ arguments (also used for jumbo).  Note that
+ * source virtual registers may be in physical registers, so may
+ * need to be flushed to home location before copying.  This
+ * applies to arg3 and above (see below).
+ *
+ * Two general strategies:
+ *    If < 20 arguments
+ *       Pass args 3-18 using vldm/vstm block copy
+ *       Pass arg0, arg1 & arg2 in rARG1-rARG3
+ *    If 20+ arguments
+ *       Pass args arg19+ using memcpy block copy
+ *       Pass arg0, arg1 & arg2 in rARG1-rARG3
+ *
+ */
+int genDalvikArgsRange(CompilationUnit* cUnit, MIR* mir,
+                       DecodedInstruction* dInsn, int callState,
+                       LIR** pcrLabel, NextCallInsn nextCallInsn,
+                       uint32_t dexIdx, uint32_t methodIdx, bool skipThis)
+{
+    int firstArg = dInsn->vC;
+    int numArgs = dInsn->vA;
+
+    // If we can treat it as non-range (Jumbo ops will use range form)
+    if (numArgs <= 5)
+        return genDalvikArgsNoRange(cUnit, mir, dInsn, callState, pcrLabel,
+                                    nextCallInsn, dexIdx, methodIdx,
+                                    skipThis);
+    /*
+     * Make sure range list doesn't span the break between in normal
+     * Dalvik vRegs and the ins.
+     */
+    int highestArg = oatGetSrc(cUnit, mir, numArgs-1).sRegLow;
+    int boundaryReg = cUnit->numDalvikRegisters - cUnit->numIns;
+    if ((firstArg < boundaryReg) && (highestArg >= boundaryReg)) {
+        LOG(FATAL) << "Argument list spanned locals & args";
+    }
+
+    /*
+     * First load the non-register arguments.  Both forms expect all
+     * of the source arguments to be in their home frame location, so
+     * scan the sReg names and flush any that have been promoted to
+     * frame backing storage.
+     */
+    // Scan the rest of the args - if in physReg flush to memory
+    for (int nextArg = 0; nextArg < numArgs;) {
+        RegLocation loc = oatGetRawSrc(cUnit, mir, nextArg);
+        if (loc.wide) {
+            loc = oatUpdateLocWide(cUnit, loc);
+            if ((nextArg >= 2) && (loc.location == kLocPhysReg)) {
+                storeBaseDispWide(cUnit, rSP,
+                                  oatSRegOffset(cUnit, loc.sRegLow),
+                                  loc.lowReg, loc.highReg);
+            }
+            nextArg += 2;
+        } else {
+            loc = oatUpdateLoc(cUnit, loc);
+            if ((nextArg >= 3) && (loc.location == kLocPhysReg)) {
+                storeBaseDisp(cUnit, rSP, oatSRegOffset(cUnit, loc.sRegLow),
+                              loc.lowReg, kWord);
+            }
+            nextArg++;
+        }
+    }
+
+    int startOffset = oatSRegOffset(cUnit,
+        cUnit->regLocation[mir->ssaRep->uses[3]].sRegLow);
+    int outsOffset = 4 /* Method* */ + (3 * 4);
+#if defined(TARGET_MIPS)
+    // Generate memcpy
+    opRegRegImm(cUnit, kOpAdd, rARG0, rSP, outsOffset);
+    opRegRegImm(cUnit, kOpAdd, rARG1, rSP, startOffset);
+    int rTgt = loadHelper(cUnit, OFFSETOF_MEMBER(Thread, pMemcpy));
+    loadConstant(cUnit, rARG2, (numArgs - 3) * 4);
+    callRuntimeHelper(cUnit, rTgt);
+    // Restore Method*
+    loadCurrMethodDirect(cUnit, rARG0);
+#else
+    if (numArgs >= 20) {
+        // Generate memcpy
+        opRegRegImm(cUnit, kOpAdd, rARG0, rSP, outsOffset);
+        opRegRegImm(cUnit, kOpAdd, rARG1, rSP, startOffset);
+        int rTgt = loadHelper(cUnit, OFFSETOF_MEMBER(Thread, pMemcpy));
+        loadConstant(cUnit, rARG2, (numArgs - 3) * 4);
+        callRuntimeHelper(cUnit, rTgt);
+        // Restore Method*
+        loadCurrMethodDirect(cUnit, rARG0);
+    } else {
+        // Use vldm/vstm pair using rARG3 as a temp
+        int regsLeft = std::min(numArgs - 3, 16);
+        callState = nextCallInsn(cUnit, mir, callState, dexIdx, methodIdx);
+        opRegRegImm(cUnit, kOpAdd, rARG3, rSP, startOffset);
+        LIR* ld = newLIR3(cUnit, kThumb2Vldms, rARG3, fr0, regsLeft);
+        //TUNING: loosen barrier
+        ld->defMask = ENCODE_ALL;
+        setMemRefType(ld, true /* isLoad */, kDalvikReg);
+        callState = nextCallInsn(cUnit, mir, callState, dexIdx, methodIdx);
+        opRegRegImm(cUnit, kOpAdd, rARG3, rSP, 4 /* Method* */ + (3 * 4));
+        callState = nextCallInsn(cUnit, mir, callState, dexIdx, methodIdx);
+        LIR* st = newLIR3(cUnit, kThumb2Vstms, rARG3, fr0, regsLeft);
+        setMemRefType(st, false /* isLoad */, kDalvikReg);
+        st->defMask = ENCODE_ALL;
+        callState = nextCallInsn(cUnit, mir, callState, dexIdx, methodIdx);
+    }
+#endif
+
+    callState = loadArgRegs(cUnit, mir, dInsn, callState, nextCallInsn,
+                            dexIdx, methodIdx, skipThis);
+
+    callState = nextCallInsn(cUnit, mir, callState, dexIdx, methodIdx);
+    if (pcrLabel) {
+        *pcrLabel = genNullCheck(cUnit, oatSSASrc(mir,0), rARG1, mir);
+    }
+    return callState;
+}
+
+#endif  // TARGET_ARM || TARGET_MIPS
+
+
+}  // namespace art
diff --git a/src/compiler/codegen/LocalOptimizations.cc b/src/compiler/codegen/LocalOptimizations.cc
index cc276f2..19b41e7 100644
--- a/src/compiler/codegen/LocalOptimizations.cc
+++ b/src/compiler/codegen/LocalOptimizations.cc
@@ -27,7 +27,7 @@
 #define LDLD_DISTANCE 4
 #define LD_LATENCY 2
 
-STATIC inline bool isDalvikRegisterClobbered(TGT_LIR* lir1, TGT_LIR* lir2)
+inline bool isDalvikRegisterClobbered(LIR* lir1, LIR* lir2)
 {
     int reg1Lo = DECODE_ALIAS_INFO_REG(lir1->aliasInfo);
     int reg1Hi = reg1Lo + DECODE_ALIAS_INFO_WIDE(lir1->aliasInfo);
@@ -38,11 +38,11 @@
 }
 
 /* Convert a more expensive instruction (ie load) into a move */
-STATIC void convertMemOpIntoMove(CompilationUnit* cUnit, TGT_LIR* origLIR,
-                                 int dest, int src)
+void convertMemOpIntoMove(CompilationUnit* cUnit, LIR* origLIR, int dest,
+                          int src)
 {
     /* Insert a move to replace the load */
-    TGT_LIR* moveLIR;
+    LIR* moveLIR;
     moveLIR = oatRegCopyNoInsert( cUnit, dest, src);
     /*
      * Insert the converted instruction after the original since the
@@ -71,11 +71,10 @@
  *   1) They are must-aliases
  *   2) The memory location is not written to in between
  */
-STATIC void applyLoadStoreElimination(CompilationUnit* cUnit,
-                                      TGT_LIR* headLIR,
-                                      TGT_LIR* tailLIR)
+void applyLoadStoreElimination(CompilationUnit* cUnit, LIR* headLIR,
+                               LIR* tailLIR)
 {
-    TGT_LIR* thisLIR;
+    LIR* thisLIR;
 
     if (headLIR == tailLIR) return;
 
@@ -93,7 +92,7 @@
 
         int nativeRegId = thisLIR->operands[0];
         bool isThisLIRLoad = EncodingMap[thisLIR->opcode].flags & IS_LOAD;
-        TGT_LIR* checkLIR;
+        LIR* checkLIR;
         /* Use the mem mask to determine the rough memory location */
         u8 thisMemMask = (thisLIR->useMask | thisLIR->defMask) & ENCODE_MEM;
 
@@ -230,9 +229,9 @@
                                                 "REG CLOBBERED"));
                 /* Only sink store instructions */
                 if (sinkDistance && !isThisLIRLoad) {
-                    TGT_LIR* newStoreLIR =
-                        (TGT_LIR* ) oatNew(cUnit, sizeof(TGT_LIR), true,
-                                          kAllocLIR);
+                    LIR* newStoreLIR =
+                        (LIR* ) oatNew(cUnit, sizeof(LIR), true,
+                                       kAllocLIR);
                     *newStoreLIR = *thisLIR;
                     /*
                      * Stop point found - insert *before* the checkLIR
@@ -255,16 +254,14 @@
  * Perform a pass of bottom-up walk, from the second instruction in the
  * superblock, to try to hoist loads to earlier slots.
  */
-STATIC void applyLoadHoisting(CompilationUnit* cUnit,
-                              TGT_LIR* headLIR,
-                              TGT_LIR* tailLIR)
+void applyLoadHoisting(CompilationUnit* cUnit, LIR* headLIR, LIR* tailLIR)
 {
-    TGT_LIR* thisLIR, *checkLIR;
+    LIR* thisLIR, *checkLIR;
     /*
      * Store the list of independent instructions that can be hoisted past.
      * Will decide the best place to insert later.
      */
-    TGT_LIR* prevInstList[MAX_HOIST_DISTANCE];
+    LIR* prevInstList[MAX_HOIST_DISTANCE];
 
     /* Empty block */
     if (headLIR == tailLIR) return;
@@ -373,7 +370,7 @@
         if (nextSlot >= 2) {
             int firstSlot = nextSlot - 2;
             int slot;
-            TGT_LIR* depLIR = prevInstList[nextSlot-1];
+            LIR* depLIR = prevInstList[nextSlot-1];
             /* If there is ld-ld dependency, wait LDLD_DISTANCE cycles */
             if (!isPseudoOpcode(depLIR->opcode) &&
                 (EncodingMap[depLIR->opcode].flags & IS_LOAD)) {
@@ -384,8 +381,8 @@
              * when the loop is first entered.
              */
             for (slot = firstSlot; slot >= 0; slot--) {
-                TGT_LIR* curLIR = prevInstList[slot];
-                TGT_LIR* prevLIR = prevInstList[slot+1];
+                LIR* curLIR = prevInstList[slot];
+                LIR* prevLIR = prevInstList[slot+1];
 
                 /* Check the highest instruction */
                 if (prevLIR->defMask == ENCODE_ALL) {
@@ -418,8 +415,8 @@
 
             /* Found a slot to hoist to */
             if (slot >= 0) {
-                TGT_LIR* curLIR = prevInstList[slot];
-                TGT_LIR* newLoadLIR = (TGT_LIR* ) oatNew(cUnit, sizeof(TGT_LIR),
+                LIR* curLIR = prevInstList[slot];
+                LIR* newLoadLIR = (LIR* ) oatNew(cUnit, sizeof(LIR),
                                                        true, kAllocLIR);
                 *newLoadLIR = *thisLIR;
                 /*
@@ -437,11 +434,11 @@
                                         LIR* tailLIR)
 {
     if (!(cUnit->disableOpt & (1 << kLoadStoreElimination))) {
-        applyLoadStoreElimination(cUnit, (TGT_LIR* ) headLIR,
-                                  (TGT_LIR* ) tailLIR);
+        applyLoadStoreElimination(cUnit, (LIR* ) headLIR,
+                                  (LIR* ) tailLIR);
     }
     if (!(cUnit->disableOpt & (1 << kLoadHoisting))) {
-        applyLoadHoisting(cUnit, (TGT_LIR* ) headLIR, (TGT_LIR* ) tailLIR);
+        applyLoadHoisting(cUnit, (LIR* ) headLIR, (LIR* ) tailLIR);
     }
 }
 
diff --git a/src/compiler/codegen/MethodCodegenDriver.cc b/src/compiler/codegen/MethodCodegenDriver.cc
index ce8cfda..6de3a9c 100644
--- a/src/compiler/codegen/MethodCodegenDriver.cc
+++ b/src/compiler/codegen/MethodCodegenDriver.cc
@@ -21,11 +21,11 @@
 #define DISPLAY_MISSING_TARGETS (cUnit->enableDebug & \
     (1 << kDebugDisplayMissingTargets))
 
-STATIC const RegLocation badLoc = {kLocDalvikFrame, 0, 0, 0, 0, 0, 0,
-                                   INVALID_REG, INVALID_REG, INVALID_SREG};
+const RegLocation badLoc = {kLocDalvikFrame, 0, 0, 0, 0, 0, 0,
+                            INVALID_REG, INVALID_REG, INVALID_SREG};
 
 /* Mark register usage state and return long retloc */
-STATIC RegLocation getRetLocWide(CompilationUnit* cUnit)
+RegLocation getRetLocWide(CompilationUnit* cUnit)
 {
     RegLocation res = LOC_C_RETURN_WIDE;
     oatLockTemp(cUnit, res.lowReg);
@@ -34,28 +34,28 @@
     return res;
 }
 
-STATIC RegLocation getRetLoc(CompilationUnit* cUnit)
+RegLocation getRetLoc(CompilationUnit* cUnit)
 {
     RegLocation res = LOC_C_RETURN;
     oatLockTemp(cUnit, res.lowReg);
     return res;
 }
 
-STATIC void genInvoke(CompilationUnit* cUnit, MIR* mir,
-                      InvokeType type, bool isRange)
+void genInvoke(CompilationUnit* cUnit, MIR* mir, InvokeType type, bool isRange)
 {
     DecodedInstruction* dInsn = &mir->dalvikInsn;
     int callState = 0;
-    TGT_LIR* nullCk;
-    TGT_LIR** pNullCk = NULL;
+    LIR* nullCk;
+    LIR** pNullCk = NULL;
     NextCallInsn nextCallInsn;
     oatFlushAllRegs(cUnit);    /* Everything to home location */
     // Explicit register usage
     oatLockCallTemps(cUnit);
 
     OatCompilationUnit mUnit(cUnit->class_loader, cUnit->class_linker,
-                             *cUnit->dex_file, *cUnit->dex_cache, cUnit->code_item,
-                             cUnit->method_idx, cUnit->access_flags);
+                             *cUnit->dex_file, *cUnit->dex_cache,
+                             cUnit->code_item, cUnit->method_idx,
+                             cUnit->access_flags);
 
     uint32_t dexMethodIdx = dInsn->vB;
     int vtableIdx;
@@ -111,8 +111,8 @@
  * load/store utilities here, or target-dependent genXX() handlers
  * when necessary.
  */
-STATIC bool compileDalvikInstruction(CompilationUnit* cUnit, MIR* mir,
-                                     BasicBlock* bb, TGT_LIR* labelList)
+bool compileDalvikInstruction(CompilationUnit* cUnit, MIR* mir,
+                              BasicBlock* bb, LIR* labelList)
 {
     bool res = false;   // Assume success
     RegLocation rlSrc[3];
@@ -690,7 +690,7 @@
     return res;
 }
 
-STATIC const char* extendedMIROpNames[kMirOpLast - kMirOpFirst] = {
+const char* extendedMIROpNames[kMirOpLast - kMirOpFirst] = {
     "kMirOpPhi",
     "kMirOpNullNRangeUpCheck",
     "kMirOpNullNRangeDownCheck",
@@ -700,7 +700,7 @@
 };
 
 /* Extended MIR instructions like PHI */
-STATIC void handleExtendedMethodMIR(CompilationUnit* cUnit, MIR* mir)
+void handleExtendedMethodMIR(CompilationUnit* cUnit, MIR* mir)
 {
     int opOffset = mir->dalvikInsn.opcode - kMirOpFirst;
     char* msg = NULL;
@@ -709,7 +709,7 @@
                             false, kAllocDebugInfo);
         strcpy(msg, extendedMIROpNames[opOffset]);
     }
-    TGT_LIR* op = newLIR1(cUnit, kArmPseudoExtended, (int) msg);
+    LIR* op = newLIR1(cUnit, kPseudoExtended, (int) msg);
 
     switch ((ExtendedMIROpcode)mir->dalvikInsn.opcode) {
         case kMirOpPhi: {
@@ -718,7 +718,7 @@
                 ssaString = oatGetSSAString(cUnit, mir->ssaRep);
             }
             op->flags.isNop = true;
-            newLIR1(cUnit, kArmPseudoSSARep, (int) ssaString);
+            newLIR1(cUnit, kPseudoSSARep, (int) ssaString);
             break;
         }
         default:
@@ -727,17 +727,17 @@
 }
 
 /* Handle the content in each basic block */
-STATIC bool methodBlockCodeGen(CompilationUnit* cUnit, BasicBlock* bb)
+bool methodBlockCodeGen(CompilationUnit* cUnit, BasicBlock* bb)
 {
     MIR* mir;
-    TGT_LIR* labelList = (TGT_LIR*) cUnit->blockLabelList;
+    LIR* labelList = (LIR*) cUnit->blockLabelList;
     int blockId = bb->id;
 
     cUnit->curBlock = bb;
     labelList[blockId].operands[0] = bb->startOffset;
 
     /* Insert the block label */
-    labelList[blockId].opcode = kArmPseudoNormalBlockLabel;
+    labelList[blockId].opcode = kPseudoNormalBlockLabel;
     oatAppendLIR(cUnit, (LIR*) &labelList[blockId]);
 
     /* Reset local optimization data on block boundaries */
@@ -745,7 +745,7 @@
     oatClobberAllRegs(cUnit);
     oatResetDefTracking(cUnit);
 
-    TGT_LIR* headLIR = NULL;
+    LIR* headLIR = NULL;
 
     if (bb->blockType == kEntryBlock) {
         genEntrySequence(cUnit, bb);
@@ -775,12 +775,12 @@
         InstructionFormat dalvikFormat =
             dexGetFormatFromOpcode(dalvikOpcode);
 
-        TGT_LIR* boundaryLIR;
+        LIR* boundaryLIR;
 
         /* Mark the beginning of a Dalvik instruction for line tracking */
         char* instStr = cUnit->printMe ?
            oatGetDalvikDisassembly(cUnit, &mir->dalvikInsn, "") : NULL;
-        boundaryLIR = newLIR1(cUnit, kArmPseudoDalvikByteCodeBoundary,
+        boundaryLIR = newLIR1(cUnit, kPseudoDalvikByteCodeBoundary,
                               (intptr_t) instStr);
         cUnit->boundaryMap.insert(std::make_pair(mir->offset,
                                  (LIR*)boundaryLIR));
@@ -799,7 +799,7 @@
         /* Don't generate the SSA annotation unless verbose mode is on */
         if (cUnit->printMe && mir->ssaRep) {
             char* ssaString = oatGetSSAString(cUnit, mir->ssaRep);
-            newLIR1(cUnit, kArmPseudoSSARep, (int) ssaString);
+            newLIR1(cUnit, kPseudoSSARep, (int) ssaString);
         }
 
         bool notHandled = compileDalvikInstruction(cUnit, mir, bb, labelList);
@@ -837,7 +837,7 @@
 {
     /* Used to hold the labels of each block */
     cUnit->blockLabelList =
-        (void *) oatNew(cUnit, sizeof(TGT_LIR) * cUnit->numBlocks, true,
+        (void *) oatNew(cUnit, sizeof(LIR) * cUnit->numBlocks, true,
                         kAllocLIR);
 
     oatDataFlowAnalysisDispatcher(cUnit, methodBlockCodeGen,
@@ -850,7 +850,7 @@
 }
 
 /* Needed by the ld/st optmizatons */
-TGT_LIR* oatRegCopyNoInsert(CompilationUnit* cUnit, int rDest, int rSrc)
+LIR* oatRegCopyNoInsert(CompilationUnit* cUnit, int rDest, int rSrc)
 {
     return genRegCopyNoInsert(cUnit, rDest, rSrc);
 }
diff --git a/src/compiler/codegen/RallocUtil.cc b/src/compiler/codegen/RallocUtil.cc
index 77fb23b..bb2abba 100644
--- a/src/compiler/codegen/RallocUtil.cc
+++ b/src/compiler/codegen/RallocUtil.cc
@@ -76,7 +76,7 @@
     }
 }
 
-STATIC void dumpRegPool(RegisterInfo* p, int numRegs)
+void dumpRegPool(RegisterInfo* p, int numRegs)
 {
     int i;
     LOG(INFO) << "================================================";
@@ -124,7 +124,7 @@
     clobberBody(cUnit, oatGetRegInfo(cUnit, reg));
 }
 
-STATIC void clobberSRegBody(RegisterInfo* p, int numRegs, int sReg)
+void clobberSRegBody(RegisterInfo* p, int numRegs, int sReg)
 {
     int i;
     for (i=0; i< numRegs; i++) {
@@ -174,7 +174,7 @@
  * even/odd  allocation, but go ahead and allocate anything if not
  * available.  If nothing's available, return -1.
  */
-STATIC int allocPreservedSingle(CompilationUnit* cUnit, int sReg, bool even)
+int allocPreservedSingle(CompilationUnit* cUnit, int sReg, bool even)
 {
     int res = -1;
     RegisterInfo* FPRegs = cUnit->regPool->FPRegs;
@@ -202,7 +202,7 @@
  * allocate if we can't meet the requirements for the pair of
  * sReg<=sX[even] & (sReg+1)<= sX+1.
  */
-STATIC int allocPreservedDouble(CompilationUnit* cUnit, int sReg)
+int allocPreservedDouble(CompilationUnit* cUnit, int sReg)
 {
     int res = -1; // Assume failure
     //  Should be promoting based on initial sReg set
@@ -274,8 +274,8 @@
     return res;
 }
 
-STATIC int allocTempBody(CompilationUnit* cUnit, RegisterInfo* p, int numRegs,
-                         int* nextTemp, bool required)
+int allocTempBody(CompilationUnit* cUnit, RegisterInfo* p, int numRegs,
+                  int* nextTemp, bool required)
 {
     int i;
     int next = *nextTemp;
@@ -389,7 +389,7 @@
                          &cUnit->regPool->nextFPReg, true);
 }
 
-STATIC RegisterInfo* allocLiveBody(RegisterInfo* p, int numRegs, int sReg)
+RegisterInfo* allocLiveBody(RegisterInfo* p, int numRegs, int sReg)
 {
     int i;
     if (sReg == -1)
@@ -404,8 +404,7 @@
     return NULL;
 }
 
-STATIC RegisterInfo* allocLive(CompilationUnit* cUnit, int sReg,
-                               int regClass)
+RegisterInfo* allocLive(CompilationUnit* cUnit, int sReg, int regClass)
 {
     RegisterInfo* res = NULL;
     switch(regClass) {
@@ -537,7 +536,7 @@
     resetDefBody(oatGetRegInfo(cUnit, reg));
 }
 
-STATIC void nullifyRange(CompilationUnit* cUnit, LIR *start, LIR *finish,
+void nullifyRange(CompilationUnit* cUnit, LIR *start, LIR *finish,
                          int sReg1, int sReg2)
 {
     if (start && finish) {
@@ -557,7 +556,7 @@
  * sequence.
  */
 extern void oatMarkDef(CompilationUnit* cUnit, RegLocation rl,
-                    LIR *start, LIR *finish)
+                       LIR *start, LIR *finish)
 {
     DCHECK(!rl.wide);
     DCHECK(start && start->next);
@@ -573,7 +572,7 @@
  * sequence.
  */
 extern void oatMarkDefWide(CompilationUnit* cUnit, RegLocation rl,
-                        LIR *start, LIR *finish)
+                           LIR *start, LIR *finish)
 {
     DCHECK(rl.wide);
     DCHECK(start && start->next);
@@ -584,8 +583,7 @@
     p->defEnd = finish;
 }
 
-extern RegLocation oatWideToNarrow(CompilationUnit* cUnit,
-                                           RegLocation rl)
+extern RegLocation oatWideToNarrow(CompilationUnit* cUnit, RegLocation rl)
 {
     DCHECK(rl.wide);
     if (rl.location == kLocPhysReg) {
@@ -658,7 +656,7 @@
 }
 
 // Make sure nothing is live and dirty
-STATIC void flushAllRegsBody(CompilationUnit* cUnit, RegisterInfo* info,
+void flushAllRegsBody(CompilationUnit* cUnit, RegisterInfo* info,
                              int numRegs)
 {
     int i;
@@ -684,7 +682,7 @@
 
 
 //TUNING: rewrite all of this reg stuff.  Probably use an attribute table
-STATIC bool regClassMatches(int regClass, int reg)
+bool regClassMatches(int regClass, int reg)
 {
     if (regClass == kAnyReg) {
         return true;
@@ -764,7 +762,7 @@
       info->inUse = true;
 }
 
-STATIC void copyRegInfo(CompilationUnit* cUnit, int newReg, int oldReg)
+void copyRegInfo(CompilationUnit* cUnit, int newReg, int oldReg)
 {
     RegisterInfo* newInfo = oatGetRegInfo(cUnit, newReg);
     RegisterInfo* oldInfo = oatGetRegInfo(cUnit, oldReg);
@@ -835,8 +833,7 @@
 }
 
 /* see comments for updateLoc */
-extern RegLocation oatUpdateLocWide(CompilationUnit* cUnit,
-                                    RegLocation loc)
+extern RegLocation oatUpdateLocWide(CompilationUnit* cUnit, RegLocation loc)
 {
     DCHECK(loc.wide);
     DCHECK(oatCheckCorePoolSanity(cUnit));
@@ -889,8 +886,7 @@
 
 
 /* For use in cases we don't know (or care) width */
-extern RegLocation oatUpdateRawLoc(CompilationUnit* cUnit,
-                                   RegLocation loc)
+extern RegLocation oatUpdateRawLoc(CompilationUnit* cUnit, RegLocation loc)
 {
     if (loc.wide)
         return oatUpdateLocWide(cUnit, loc);
@@ -898,8 +894,8 @@
         return oatUpdateLoc(cUnit, loc);
 }
 
-STATIC RegLocation evalLocWide(CompilationUnit* cUnit, RegLocation loc,
-                               int regClass, bool update)
+RegLocation evalLocWide(CompilationUnit* cUnit, RegLocation loc,
+                        int regClass, bool update)
 {
     DCHECK(loc.wide);
     int newRegs;
@@ -1017,7 +1013,7 @@
 
 /* USE SSA names to count references of base Dalvik vRegs. */
 void oatCountRefs(CompilationUnit *cUnit, BasicBlock* bb,
-                      RefCounts* coreCounts, RefCounts* fpCounts)
+                  RefCounts* coreCounts, RefCounts* fpCounts)
 {
     MIR* mir;
     if (bb->blockType != kDalvikByteCode && bb->blockType != kEntryBlock &&
diff --git a/src/compiler/codegen/arm/ArchFactory.cc b/src/compiler/codegen/arm/ArchFactory.cc
index c3de5ff..5f75ef8 100644
--- a/src/compiler/codegen/arm/ArchFactory.cc
+++ b/src/compiler/codegen/arm/ArchFactory.cc
@@ -22,1063 +22,17 @@
  *
  */
 
-#include "oat_compilation_unit.h"
-
-#define SLOW_FIELD_PATH (cUnit->enableDebug & (1 << kDebugSlowFieldPath))
-#define SLOW_INVOKE_PATH (cUnit->enableDebug & (1 << kDebugSlowInvokePath))
-#define SLOW_STRING_PATH (cUnit->enableDebug & (1 << kDebugSlowStringPath))
-#define SLOW_TYPE_PATH (cUnit->enableDebug & (1 << kDebugSlowTypePath))
-#define EXERCISE_SLOWEST_FIELD_PATH (cUnit->enableDebug & \
-    (1 << kDebugSlowestFieldPath))
-#define EXERCISE_SLOWEST_STRING_PATH (cUnit->enableDebug & \
-    (1 << kDebugSlowestStringPath))
-#define EXERCISE_RESOLVE_METHOD (cUnit->enableDebug & \
-    (1 << kDebugExerciseResolveMethod))
-
 namespace art {
 
-STATIC void genDebuggerUpdate(CompilationUnit* cUnit, int32_t offset);
+void genDebuggerUpdate(CompilationUnit* cUnit, int32_t offset);
 
-/* Generate conditional branch instructions */
-STATIC ArmLIR* genConditionalBranch(CompilationUnit* cUnit,
-                                    ArmConditionCode cond,
-                                    ArmLIR* target)
+int loadHelper(CompilationUnit* cUnit, int offset)
 {
-    ArmLIR* branch = opCondBranch(cUnit, cond);
-    branch->generic.target = (LIR*) target;
-    return branch;
+    loadWordDisp(cUnit, rSELF, offset, rLR);
+    return rLR;
 }
 
-/* Generate unconditional branch instructions */
-STATIC ArmLIR* genUnconditionalBranch(CompilationUnit* cUnit, ArmLIR* target)
-{
-    ArmLIR* branch = opNone(cUnit, kOpUncondBr);
-    branch->generic.target = (LIR*) target;
-    return branch;
-}
-
-STATIC ArmLIR* callRuntimeHelper(CompilationUnit* cUnit, int reg)
-{
-    oatClobberCalleeSave(cUnit);
-    return opReg(cUnit, kOpBlx, reg);
-}
-
-/*
- * Mark garbage collection card. Skip if the value we're storing is null.
- */
-STATIC void markGCCard(CompilationUnit* cUnit, int valReg, int tgtAddrReg)
-{
-    int regCardBase = oatAllocTemp(cUnit);
-    int regCardNo = oatAllocTemp(cUnit);
-    ArmLIR* branchOver = genCmpImmBranch(cUnit, kArmCondEq, valReg, 0);
-    loadWordDisp(cUnit, rSELF, Thread::CardTableOffset().Int32Value(),
-                 regCardBase);
-    opRegRegImm(cUnit, kOpLsr, regCardNo, tgtAddrReg, GC_CARD_SHIFT);
-    storeBaseIndexed(cUnit, regCardBase, regCardNo, regCardBase, 0,
-                     kUnsignedByte);
-    ArmLIR* target = newLIR0(cUnit, kArmPseudoTargetLabel);
-    target->defMask = ENCODE_ALL;
-    branchOver->generic.target = (LIR*)target;
-    oatFreeTemp(cUnit, regCardBase);
-    oatFreeTemp(cUnit, regCardNo);
-}
-
-/*
- * Utiltiy to load the current Method*.  Broken out
- * to allow easy change between placing the current Method* in a
- * dedicated register or its home location in the frame.
- */
-STATIC void loadCurrMethodDirect(CompilationUnit *cUnit, int rTgt)
-{
-#if defined(METHOD_IN_REG)
-    genRegCopy(cUnit, rTgt, rMETHOD);
-#else
-    loadWordDisp(cUnit, rSP, 0, rTgt);
-#endif
-}
-
-STATIC int loadCurrMethod(CompilationUnit *cUnit)
-{
-#if defined(METHOD_IN_REG)
-    return rMETHOD;
-#else
-    int mReg = oatAllocTemp(cUnit);
-    loadCurrMethodDirect(cUnit, mReg);
-    return mReg;
-#endif
-}
-
-STATIC ArmLIR* genCheck(CompilationUnit* cUnit, ArmConditionCode cCode,
-                        MIR* mir, ArmThrowKind kind)
-{
-    ArmLIR* tgt = (ArmLIR*)oatNew(cUnit, sizeof(ArmLIR), true, kAllocLIR);
-    tgt->opcode = kArmPseudoThrowTarget;
-    tgt->operands[0] = kind;
-    tgt->operands[1] = mir ? mir->offset : 0;
-    ArmLIR* branch = genConditionalBranch(cUnit, cCode, tgt);
-    // Remember branch target - will process later
-    oatInsertGrowableList(cUnit, &cUnit->throwLaunchpads, (intptr_t)tgt);
-    return branch;
-}
-
-STATIC ArmLIR* genImmedCheck(CompilationUnit* cUnit, ArmConditionCode cCode,
-                             int reg, int immVal, MIR* mir, ArmThrowKind kind)
-{
-    ArmLIR* tgt = (ArmLIR*)oatNew(cUnit, sizeof(ArmLIR), true, kAllocLIR);
-    tgt->opcode = kArmPseudoThrowTarget;
-    tgt->operands[0] = kind;
-    tgt->operands[1] = mir->offset;
-    ArmLIR* branch;
-    if (cCode == kArmCondAl) {
-        branch = genUnconditionalBranch(cUnit, tgt);
-    } else {
-        branch = genCmpImmBranch(cUnit, cCode, reg, immVal);
-        branch->generic.target = (LIR*)tgt;
-    }
-    // Remember branch target - will process later
-    oatInsertGrowableList(cUnit, &cUnit->throwLaunchpads, (intptr_t)tgt);
-    return branch;
-}
-
-/* Perform null-check on a register.  */
-STATIC ArmLIR* genNullCheck(CompilationUnit* cUnit, int sReg, int mReg,
-                             MIR* mir)
-{
-    if (!(cUnit->disableOpt & (1 << kNullCheckElimination)) &&
-        mir->optimizationFlags & MIR_IGNORE_NULL_CHECK) {
-        return NULL;
-    }
-    return genImmedCheck(cUnit, kArmCondEq, mReg, 0, mir, kArmThrowNullPointer);
-}
-
-/* Perform check on two registers */
-STATIC TGT_LIR* genRegRegCheck(CompilationUnit* cUnit, ArmConditionCode cCode,
-                               int reg1, int reg2, MIR* mir, ArmThrowKind kind)
-{
-    ArmLIR* tgt = (ArmLIR*)oatNew(cUnit, sizeof(ArmLIR), true, kAllocLIR);
-    tgt->opcode = kArmPseudoThrowTarget;
-    tgt->operands[0] = kind;
-    tgt->operands[1] = mir ? mir->offset : 0;
-    tgt->operands[2] = reg1;
-    tgt->operands[3] = reg2;
-    opRegReg(cUnit, kOpCmp, reg1, reg2);
-    ArmLIR* branch = genConditionalBranch(cUnit, cCode, tgt);
-    // Remember branch target - will process later
-    oatInsertGrowableList(cUnit, &cUnit->throwLaunchpads, (intptr_t)tgt);
-    return branch;
-}
-
-/*
- * Let helper function take care of everything.  Will call
- * Array::AllocFromCode(type_idx, method, count);
- * Note: AllocFromCode will handle checks for errNegativeArraySize.
- */
-STATIC void genNewArray(CompilationUnit* cUnit, MIR* mir, RegLocation rlDest,
-                        RegLocation rlSrc)
-{
-    oatFlushAllRegs(cUnit);    /* Everything to home location */
-    uint32_t type_idx = mir->dalvikInsn.vC;
-    if (cUnit->compiler->CanAccessTypeWithoutChecks(cUnit->method_idx,
-                                                    cUnit->dex_cache,
-                                                    *cUnit->dex_file,
-                                                    type_idx)) {
-        loadWordDisp(cUnit, rSELF,
-                     OFFSETOF_MEMBER(Thread, pAllocArrayFromCode), rLR);
-    } else {
-        loadWordDisp(cUnit, rSELF,
-                     OFFSETOF_MEMBER(Thread, pAllocArrayFromCodeWithAccessCheck), rLR);
-    }
-    loadCurrMethodDirect(cUnit, r1);              // arg1 <- Method*
-    loadConstant(cUnit, r0, type_idx);            // arg0 <- type_id
-    loadValueDirectFixed(cUnit, rlSrc, r2);       // arg2 <- count
-    callRuntimeHelper(cUnit, rLR);
-    RegLocation rlResult = oatGetReturn(cUnit);
-    storeValue(cUnit, rlDest, rlResult);
-}
-
-/*
- * Similar to genNewArray, but with post-allocation initialization.
- * Verifier guarantees we're dealing with an array class.  Current
- * code throws runtime exception "bad Filled array req" for 'D' and 'J'.
- * Current code also throws internal unimp if not 'L', '[' or 'I'.
- */
-STATIC void genFilledNewArray(CompilationUnit* cUnit, MIR* mir, bool isRange)
-{
-    DecodedInstruction* dInsn = &mir->dalvikInsn;
-    int elems = dInsn->vA;
-    int typeId = dInsn->vB;
-    oatFlushAllRegs(cUnit);    /* Everything to home location */
-    if (cUnit->compiler->CanAccessTypeWithoutChecks(cUnit->method_idx,
-                                                    cUnit->dex_cache,
-                                                    *cUnit->dex_file,
-                                                    typeId)) {
-        loadWordDisp(cUnit, rSELF,
-                     OFFSETOF_MEMBER(Thread, pCheckAndAllocArrayFromCode), rLR);
-    } else {
-        loadWordDisp(cUnit, rSELF,
-                     OFFSETOF_MEMBER(Thread, pCheckAndAllocArrayFromCodeWithAccessCheck), rLR);
-    }
-    loadCurrMethodDirect(cUnit, r1);              // arg1 <- Method*
-    loadConstant(cUnit, r0, typeId);              // arg0 <- type_id
-    loadConstant(cUnit, r2, elems);               // arg2 <- count
-    callRuntimeHelper(cUnit, rLR);
-    /*
-     * NOTE: the implicit target for OP_FILLED_NEW_ARRAY is the
-     * return region.  Because AllocFromCode placed the new array
-     * in r0, we'll just lock it into place.  When debugger support is
-     * added, it may be necessary to additionally copy all return
-     * values to a home location in thread-local storage
-     */
-    oatLockTemp(cUnit, r0);
-
-    // TODO: use the correct component size, currently all supported types share array alignment
-    // with ints (see comment at head of function)
-    size_t component_size = sizeof(int32_t);
-
-    // Having a range of 0 is legal
-    if (isRange && (dInsn->vA > 0)) {
-        /*
-         * Bit of ugliness here.  We're going generate a mem copy loop
-         * on the register range, but it is possible that some regs
-         * in the range have been promoted.  This is unlikely, but
-         * before generating the copy, we'll just force a flush
-         * of any regs in the source range that have been promoted to
-         * home location.
-         */
-        for (unsigned int i = 0; i < dInsn->vA; i++) {
-            RegLocation loc = oatUpdateLoc(cUnit,
-                oatGetSrc(cUnit, mir, i));
-            if (loc.location == kLocPhysReg) {
-                storeBaseDisp(cUnit, rSP, oatSRegOffset(cUnit, loc.sRegLow),
-                              loc.lowReg, kWord);
-            }
-        }
-        /*
-         * TUNING note: generated code here could be much improved, but
-         * this is an uncommon operation and isn't especially performance
-         * critical.
-         */
-        int rSrc = oatAllocTemp(cUnit);
-        int rDst = oatAllocTemp(cUnit);
-        int rIdx = oatAllocTemp(cUnit);
-        int rVal = rLR;  // Using a lot of temps, rLR is known free here
-        // Set up source pointer
-        RegLocation rlFirst = oatGetSrc(cUnit, mir, 0);
-        opRegRegImm(cUnit, kOpAdd, rSrc, rSP,
-                    oatSRegOffset(cUnit, rlFirst.sRegLow));
-        // Set up the target pointer
-        opRegRegImm(cUnit, kOpAdd, rDst, r0,
-                    Array::DataOffset(component_size).Int32Value());
-        // Set up the loop counter (known to be > 0)
-        loadConstant(cUnit, rIdx, dInsn->vA - 1);
-        // Generate the copy loop.  Going backwards for convenience
-        ArmLIR* target = newLIR0(cUnit, kArmPseudoTargetLabel);
-        target->defMask = ENCODE_ALL;
-        // Copy next element
-        loadBaseIndexed(cUnit, rSrc, rIdx, rVal, 2, kWord);
-        storeBaseIndexed(cUnit, rDst, rIdx, rVal, 2, kWord);
-        // Use setflags encoding here
-        newLIR3(cUnit, kThumb2SubsRRI12, rIdx, rIdx, 1);
-        ArmLIR* branch = opCondBranch(cUnit, kArmCondGe);
-        branch->generic.target = (LIR*)target;
-    } else if (!isRange) {
-        // TUNING: interleave
-        for (unsigned int i = 0; i < dInsn->vA; i++) {
-            RegLocation rlArg = loadValue(cUnit,
-                oatGetSrc(cUnit, mir, i), kCoreReg);
-            storeBaseDisp(cUnit, r0,
-                          Array::DataOffset(component_size).Int32Value() +
-                          i * 4, rlArg.lowReg, kWord);
-            // If the loadValue caused a temp to be allocated, free it
-            if (oatIsTemp(cUnit, rlArg.lowReg)) {
-                oatFreeTemp(cUnit, rlArg.lowReg);
-            }
-        }
-    }
-}
-
-STATIC void genSput(CompilationUnit* cUnit, MIR* mir, RegLocation rlSrc,
-                    bool isLongOrDouble, bool isObject)
-{
-    int fieldOffset;
-    int ssbIndex;
-    bool isVolatile;
-    bool isReferrersClass;
-    uint32_t fieldIdx = mir->dalvikInsn.vB;
-
-    OatCompilationUnit mUnit(cUnit->class_loader, cUnit->class_linker,
-                             *cUnit->dex_file, *cUnit->dex_cache, cUnit->code_item,
-                             cUnit->method_idx, cUnit->access_flags);
-
-    bool fastPath =
-        cUnit->compiler->ComputeStaticFieldInfo(fieldIdx, &mUnit,
-                                                fieldOffset, ssbIndex,
-                                                isReferrersClass, isVolatile, true);
-    if (fastPath && !SLOW_FIELD_PATH) {
-        DCHECK_GE(fieldOffset, 0);
-        int rBase;
-        int rMethod;
-        if (isReferrersClass) {
-            // Fast path, static storage base is this method's class
-            rMethod  = loadCurrMethod(cUnit);
-            rBase = oatAllocTemp(cUnit);
-            loadWordDisp(cUnit, rMethod,
-                         Method::DeclaringClassOffset().Int32Value(), rBase);
-        } else {
-            // Medium path, static storage base in a different class which
-            // requires checks that the other class is initialized.
-            DCHECK_GE(ssbIndex, 0);
-            // May do runtime call so everything to home locations.
-            oatFlushAllRegs(cUnit);
-            // Using fixed register to sync with possible call to runtime
-            // support.
-            rMethod = r1;
-            oatLockTemp(cUnit, rMethod);
-            loadCurrMethodDirect(cUnit, rMethod);
-            rBase = r0;
-            oatLockTemp(cUnit, rBase);
-            loadWordDisp(cUnit, rMethod,
-                Method::DexCacheInitializedStaticStorageOffset().Int32Value(),
-                rBase);
-            loadWordDisp(cUnit, rBase,
-                         Array::DataOffset(sizeof(Object*)).Int32Value() + sizeof(int32_t*) *
-                         ssbIndex, rBase);
-            // rBase now points at appropriate static storage base (Class*)
-            // or NULL if not initialized. Check for NULL and call helper if NULL.
-            // TUNING: fast path should fall through
-            ArmLIR* branchOver = genCmpImmBranch(cUnit, kArmCondNe, rBase, 0);
-            loadWordDisp(cUnit, rSELF,
-                         OFFSETOF_MEMBER(Thread, pInitializeStaticStorage), rLR);
-            loadConstant(cUnit, r0, ssbIndex);
-            callRuntimeHelper(cUnit, rLR);
-            ArmLIR* skipTarget = newLIR0(cUnit, kArmPseudoTargetLabel);
-            skipTarget->defMask = ENCODE_ALL;
-            branchOver->generic.target = (LIR*)skipTarget;
-        }
-        // rBase now holds static storage base
-        oatFreeTemp(cUnit, rMethod);
-        if (isLongOrDouble) {
-            rlSrc = oatGetSrcWide(cUnit, mir, 0, 1);
-            rlSrc = loadValueWide(cUnit, rlSrc, kAnyReg);
-        } else {
-            rlSrc = oatGetSrc(cUnit, mir, 0);
-            rlSrc = loadValue(cUnit, rlSrc, kAnyReg);
-        }
-        if (isVolatile) {
-            oatGenMemBarrier(cUnit, kST);
-        }
-        if (isLongOrDouble) {
-            storeBaseDispWide(cUnit, rBase, fieldOffset, rlSrc.lowReg,
-                              rlSrc.highReg);
-        } else {
-            storeWordDisp(cUnit, rBase, fieldOffset, rlSrc.lowReg);
-        }
-        if (isVolatile) {
-            oatGenMemBarrier(cUnit, kSY);
-        }
-        if (isObject) {
-            markGCCard(cUnit, rlSrc.lowReg, rBase);
-        }
-        oatFreeTemp(cUnit, rBase);
-    } else {
-        oatFlushAllRegs(cUnit);  // Everything to home locations
-        int setterOffset = isLongOrDouble ? OFFSETOF_MEMBER(Thread, pSet64Static) :
-                           (isObject ? OFFSETOF_MEMBER(Thread, pSetObjStatic)
-                                     : OFFSETOF_MEMBER(Thread, pSet32Static));
-        loadWordDisp(cUnit, rSELF, setterOffset, rLR);
-        loadConstant(cUnit, r0, fieldIdx);
-        if (isLongOrDouble) {
-            loadValueDirectWideFixed(cUnit, rlSrc, r2, r3);
-        } else {
-            loadValueDirect(cUnit, rlSrc, r1);
-        }
-        callRuntimeHelper(cUnit, rLR);
-    }
-}
-
-STATIC void genSget(CompilationUnit* cUnit, MIR* mir, RegLocation rlDest,
-                    bool isLongOrDouble, bool isObject)
-{
-    int fieldOffset;
-    int ssbIndex;
-    bool isVolatile;
-    bool isReferrersClass;
-    uint32_t fieldIdx = mir->dalvikInsn.vB;
-
-    OatCompilationUnit mUnit(cUnit->class_loader, cUnit->class_linker,
-                             *cUnit->dex_file, *cUnit->dex_cache, cUnit->code_item,
-                             cUnit->method_idx, cUnit->access_flags);
-
-    bool fastPath =
-        cUnit->compiler->ComputeStaticFieldInfo(fieldIdx, &mUnit,
-                                                fieldOffset, ssbIndex,
-                                                isReferrersClass, isVolatile, false);
-    if (fastPath && !SLOW_FIELD_PATH) {
-        DCHECK_GE(fieldOffset, 0);
-        int rBase;
-        int rMethod;
-        if (isReferrersClass) {
-            // Fast path, static storage base is this method's class
-            rMethod  = loadCurrMethod(cUnit);
-            rBase = oatAllocTemp(cUnit);
-            loadWordDisp(cUnit, rMethod,
-                         Method::DeclaringClassOffset().Int32Value(), rBase);
-        } else {
-            // Medium path, static storage base in a different class which
-            // requires checks that the other class is initialized
-            DCHECK_GE(ssbIndex, 0);
-            // May do runtime call so everything to home locations.
-            oatFlushAllRegs(cUnit);
-            // Using fixed register to sync with possible call to runtime
-            // support
-            rMethod = r1;
-            oatLockTemp(cUnit, rMethod);
-            loadCurrMethodDirect(cUnit, rMethod);
-            rBase = r0;
-            oatLockTemp(cUnit, rBase);
-            loadWordDisp(cUnit, rMethod,
-                Method::DexCacheInitializedStaticStorageOffset().Int32Value(),
-                rBase);
-            loadWordDisp(cUnit, rBase,
-                         Array::DataOffset(sizeof(Object*)).Int32Value() +
-                         sizeof(int32_t*) * ssbIndex,
-                         rBase);
-            // rBase now points at appropriate static storage base (Class*)
-            // or NULL if not initialized. Check for NULL and call helper if NULL.
-            // TUNING: fast path should fall through
-            ArmLIR* branchOver = genCmpImmBranch(cUnit, kArmCondNe, rBase, 0);
-            loadWordDisp(cUnit, rSELF,
-                         OFFSETOF_MEMBER(Thread, pInitializeStaticStorage), rLR);
-            loadConstant(cUnit, r0, ssbIndex);
-            callRuntimeHelper(cUnit, rLR);
-            ArmLIR* skipTarget = newLIR0(cUnit, kArmPseudoTargetLabel);
-            skipTarget->defMask = ENCODE_ALL;
-            branchOver->generic.target = (LIR*)skipTarget;
-        }
-        // rBase now holds static storage base
-        oatFreeTemp(cUnit, rMethod);
-        rlDest = isLongOrDouble ? oatGetDestWide(cUnit, mir, 0, 1)
-                                : oatGetDest(cUnit, mir, 0);
-        RegLocation rlResult = oatEvalLoc(cUnit, rlDest, kAnyReg, true);
-        if (isVolatile) {
-            oatGenMemBarrier(cUnit, kSY);
-        }
-        if (isLongOrDouble) {
-            loadBaseDispWide(cUnit, NULL, rBase, fieldOffset, rlResult.lowReg,
-                             rlResult.highReg, INVALID_SREG);
-        } else {
-            loadWordDisp(cUnit, rBase, fieldOffset, rlResult.lowReg);
-        }
-        oatFreeTemp(cUnit, rBase);
-        if (isLongOrDouble) {
-            storeValueWide(cUnit, rlDest, rlResult);
-        } else {
-            storeValue(cUnit, rlDest, rlResult);
-        }
-    } else {
-        oatFlushAllRegs(cUnit);  // Everything to home locations
-        int getterOffset = isLongOrDouble ? OFFSETOF_MEMBER(Thread, pGet64Static) :
-                           (isObject ? OFFSETOF_MEMBER(Thread, pGetObjStatic)
-                                     : OFFSETOF_MEMBER(Thread, pGet32Static));
-        loadWordDisp(cUnit, rSELF, getterOffset, rLR);
-        loadConstant(cUnit, r0, fieldIdx);
-        callRuntimeHelper(cUnit, rLR);
-        if (isLongOrDouble) {
-            RegLocation rlResult = oatGetReturnWide(cUnit);
-            storeValueWide(cUnit, rlDest, rlResult);
-        } else {
-            RegLocation rlResult = oatGetReturn(cUnit);
-            storeValue(cUnit, rlDest, rlResult);
-        }
-    }
-}
-
-typedef int (*NextCallInsn)(CompilationUnit*, MIR*, int, uint32_t dexIdx,
-                            uint32_t methodIdx);
-
-/*
- * Bit of a hack here - in leiu of a real scheduling pass,
- * emit the next instruction in static & direct invoke sequences.
- */
-STATIC int nextSDCallInsn(CompilationUnit* cUnit, MIR* mir,
-                          int state, uint32_t dexIdx, uint32_t unused)
-{
-    switch(state) {
-        case 0:  // Get the current Method* [sets r0]
-            loadCurrMethodDirect(cUnit, r0);
-            break;
-        case 1:  // Get method->dex_cache_resolved_methods_
-            loadWordDisp(cUnit, r0,
-                Method::DexCacheResolvedMethodsOffset().Int32Value(),
-                r0);
-            break;
-        case 2:  // Grab target method*
-            loadWordDisp(cUnit, r0,
-                Array::DataOffset(sizeof(Object*)).Int32Value() + dexIdx * 4,
-                r0);
-            break;
-        case 3:  // Grab the code from the method*
-            loadWordDisp(cUnit, r0, Method::GetCodeOffset().Int32Value(), rLR);
-            break;
-        default:
-            return -1;
-    }
-    return state + 1;
-}
-
-/*
- * Bit of a hack here - in leiu of a real scheduling pass,
- * emit the next instruction in a virtual invoke sequence.
- * We can use rLR as a temp prior to target address loading
- * Note also that we'll load the first argument ("this") into
- * r1 here rather than the standard loadArgRegs.
- */
-STATIC int nextVCallInsn(CompilationUnit* cUnit, MIR* mir,
-                         int state, uint32_t dexIdx, uint32_t methodIdx)
-{
-    RegLocation rlArg;
-    /*
-     * This is the fast path in which the target virtual method is
-     * fully resolved at compile time.
-     */
-    switch(state) {
-        case 0:  // Get "this" [set r1]
-            rlArg = oatGetSrc(cUnit, mir, 0);
-            loadValueDirectFixed(cUnit, rlArg, r1);
-            break;
-        case 1: // Is "this" null? [use r1]
-            genNullCheck(cUnit, oatSSASrc(mir,0), r1, mir);
-            // get this->klass_ [use r1, set rLR]
-            loadWordDisp(cUnit, r1, Object::ClassOffset().Int32Value(), rLR);
-            break;
-        case 2: // Get this->klass_->vtable [usr rLR, set rLR]
-            loadWordDisp(cUnit, rLR, Class::VTableOffset().Int32Value(), rLR);
-            break;
-        case 3: // Get target method [use rLR, set r0]
-            loadWordDisp(cUnit, rLR, (methodIdx * 4) +
-                         Array::DataOffset(sizeof(Object*)).Int32Value(), r0);
-            break;
-        case 4: // Get the target compiled code address [uses r0, sets rLR]
-            loadWordDisp(cUnit, r0, Method::GetCodeOffset().Int32Value(), rLR);
-            break;
-        default:
-            return -1;
-    }
-    return state + 1;
-}
-
-/*
- * Interleave launch code for INVOKE_SUPER.  See comments
- * for nextVCallIns.
- */
-STATIC int nextSuperCallInsn(CompilationUnit* cUnit, MIR* mir,
-                             int state, uint32_t dexIdx, uint32_t methodIdx)
-{
-    /*
-     * This is the fast path in which the target virtual method is
-     * fully resolved at compile time.  Note also that this path assumes
-     * that the check to verify that the target method index falls
-     * within the size of the super's vtable has been done at compile-time.
-     */
-    RegLocation rlArg;
-    switch(state) {
-        case 0: // Get current Method* [set r0]
-            loadCurrMethodDirect(cUnit, r0);
-            // Load "this" [set r1]
-            rlArg = oatGetSrc(cUnit, mir, 0);
-            loadValueDirectFixed(cUnit, rlArg, r1);
-            // Get method->declaring_class_ [use r0, set rLR]
-            loadWordDisp(cUnit, r0, Method::DeclaringClassOffset().Int32Value(),
-                         rLR);
-            // Is "this" null? [use r1]
-            genNullCheck(cUnit, oatSSASrc(mir,0), r1, mir);
-            break;
-        case 1: // Get method->declaring_class_->super_class [usr rLR, set rLR]
-            loadWordDisp(cUnit, rLR, Class::SuperClassOffset().Int32Value(),
-                         rLR);
-            break;
-        case 2: // Get ...->super_class_->vtable [u/s rLR]
-            loadWordDisp(cUnit, rLR, Class::VTableOffset().Int32Value(), rLR);
-            break;
-        case 3: // Get target method [use rLR, set r0]
-            loadWordDisp(cUnit, rLR, (methodIdx * 4) +
-                         Array::DataOffset(sizeof(Object*)).Int32Value(), r0);
-            break;
-        case 4: // Get the target compiled code address [uses r0, sets rLR]
-            loadWordDisp(cUnit, r0, Method::GetCodeOffset().Int32Value(), rLR);
-            break;
-        default:
-            return -1;
-    }
-    return state + 1;
-}
-
-STATIC int nextInvokeInsnSP(CompilationUnit* cUnit, MIR* mir, int trampoline,
-                            int state, uint32_t dexIdx, uint32_t methodIdx)
-{
-    /*
-     * This handles the case in which the base method is not fully
-     * resolved at compile time, we bail to a runtime helper.
-     */
-    if (state == 0) {
-        // Load trampoline target
-        loadWordDisp(cUnit, rSELF, trampoline, rLR);
-        // Load r0 with method index
-        loadConstant(cUnit, r0, dexIdx);
-        return 1;
-    }
-    return -1;
-}
-
-STATIC int nextStaticCallInsnSP(CompilationUnit* cUnit, MIR* mir,
-                                int state, uint32_t dexIdx, uint32_t methodIdx)
-{
-  int trampoline = OFFSETOF_MEMBER(Thread, pInvokeStaticTrampolineWithAccessCheck);
-  return nextInvokeInsnSP(cUnit, mir, trampoline, state, dexIdx, 0);
-}
-
-STATIC int nextDirectCallInsnSP(CompilationUnit* cUnit, MIR* mir,
-                                int state, uint32_t dexIdx, uint32_t methodIdx)
-{
-  int trampoline = OFFSETOF_MEMBER(Thread, pInvokeDirectTrampolineWithAccessCheck);
-  return nextInvokeInsnSP(cUnit, mir, trampoline, state, dexIdx, 0);
-}
-
-STATIC int nextSuperCallInsnSP(CompilationUnit* cUnit, MIR* mir,
-                               int state, uint32_t dexIdx, uint32_t methodIdx)
-{
-  int trampoline = OFFSETOF_MEMBER(Thread, pInvokeSuperTrampolineWithAccessCheck);
-  return nextInvokeInsnSP(cUnit, mir, trampoline, state, dexIdx, 0);
-}
-
-STATIC int nextVCallInsnSP(CompilationUnit* cUnit, MIR* mir,
-                           int state, uint32_t dexIdx, uint32_t methodIdx)
-{
-  int trampoline = OFFSETOF_MEMBER(Thread, pInvokeVirtualTrampolineWithAccessCheck);
-  return nextInvokeInsnSP(cUnit, mir, trampoline, state, dexIdx, 0);
-}
-
-/*
- * All invoke-interface calls bounce off of art_invoke_interface_trampoline,
- * which will locate the target and continue on via a tail call.
- */
-STATIC int nextInterfaceCallInsn(CompilationUnit* cUnit, MIR* mir,
-                                 int state, uint32_t dexIdx, uint32_t unused)
-{
-  int trampoline = OFFSETOF_MEMBER(Thread, pInvokeInterfaceTrampoline);
-  return nextInvokeInsnSP(cUnit, mir, trampoline, state, dexIdx, 0);
-}
-
-STATIC int nextInterfaceCallInsnWithAccessCheck(CompilationUnit* cUnit,
-                                                MIR* mir, int state,
-                                                uint32_t dexIdx,
-                                                uint32_t unused)
-{
-  int trampoline = OFFSETOF_MEMBER(Thread, pInvokeInterfaceTrampolineWithAccessCheck);
-  return nextInvokeInsnSP(cUnit, mir, trampoline, state, dexIdx, 0);
-}
-
-STATIC int loadArgRegs(CompilationUnit* cUnit, MIR* mir,
-                          DecodedInstruction* dInsn, int callState,
-                          NextCallInsn nextCallInsn, uint32_t dexIdx,
-                          uint32_t methodIdx, bool skipThis)
-{
-    int nextReg = r1;
-    int nextArg = 0;
-    if (skipThis) {
-        nextReg++;
-        nextArg++;
-    }
-    for (; (nextReg <= r3) && (nextArg < mir->ssaRep->numUses); nextReg++) {
-        RegLocation rlArg = oatGetRawSrc(cUnit, mir, nextArg++);
-        rlArg = oatUpdateRawLoc(cUnit, rlArg);
-        if (rlArg.wide && (nextReg <= r2)) {
-            loadValueDirectWideFixed(cUnit, rlArg, nextReg, nextReg + 1);
-            nextReg++;
-            nextArg++;
-        } else {
-            rlArg.wide = false;
-            loadValueDirectFixed(cUnit, rlArg, nextReg);
-        }
-        callState = nextCallInsn(cUnit, mir, callState, dexIdx, methodIdx);
-    }
-    return callState;
-}
-
-/*
- * Load up to 5 arguments, the first three of which will be in
- * r1 .. r3.  On entry r0 contains the current method pointer,
- * and as part of the load sequence, it must be replaced with
- * the target method pointer.  Note, this may also be called
- * for "range" variants if the number of arguments is 5 or fewer.
- */
-STATIC int genDalvikArgsNoRange(CompilationUnit* cUnit, MIR* mir,
-                                DecodedInstruction* dInsn, int callState,
-                                ArmLIR** pcrLabel, NextCallInsn nextCallInsn,
-                                uint32_t dexIdx, uint32_t methodIdx,
-                                bool skipThis)
-{
-    RegLocation rlArg;
-
-    /* If no arguments, just return */
-    if (dInsn->vA == 0)
-        return callState;
-
-    callState = nextCallInsn(cUnit, mir, callState, dexIdx, methodIdx);
-
-    DCHECK_LE(dInsn->vA, 5U);
-    if (dInsn->vA > 3) {
-        uint32_t nextUse = 3;
-        //Detect special case of wide arg spanning arg3/arg4
-        RegLocation rlUse0 = oatGetRawSrc(cUnit, mir, 0);
-        RegLocation rlUse1 = oatGetRawSrc(cUnit, mir, 1);
-        RegLocation rlUse2 = oatGetRawSrc(cUnit, mir, 2);
-        if (((!rlUse0.wide && !rlUse1.wide) || rlUse0.wide) &&
-            rlUse2.wide) {
-            int reg;
-            // Wide spans, we need the 2nd half of uses[2].
-            rlArg = oatUpdateLocWide(cUnit, rlUse2);
-            if (rlArg.location == kLocPhysReg) {
-                reg = rlArg.highReg;
-            } else {
-                // r2 & r3 can safely be used here
-                reg = r3;
-                loadWordDisp(cUnit, rSP,
-                             oatSRegOffset(cUnit, rlArg.sRegLow) + 4, reg);
-                callState = nextCallInsn(cUnit, mir, callState, dexIdx,
-                                         methodIdx);
-            }
-            storeBaseDisp(cUnit, rSP, (nextUse + 1) * 4, reg, kWord);
-            storeBaseDisp(cUnit, rSP, 16 /* (3+1)*4 */, reg, kWord);
-            callState = nextCallInsn(cUnit, mir, callState, dexIdx, methodIdx);
-            nextUse++;
-        }
-        // Loop through the rest
-        while (nextUse < dInsn->vA) {
-            int lowReg;
-            int highReg;
-            rlArg = oatGetRawSrc(cUnit, mir, nextUse);
-            rlArg = oatUpdateRawLoc(cUnit, rlArg);
-            if (rlArg.location == kLocPhysReg) {
-                lowReg = rlArg.lowReg;
-                highReg = rlArg.highReg;
-            } else {
-                lowReg = r2;
-                highReg = r3;
-                if (rlArg.wide) {
-                    loadValueDirectWideFixed(cUnit, rlArg, lowReg, highReg);
-                } else {
-                    loadValueDirectFixed(cUnit, rlArg, lowReg);
-                }
-                callState = nextCallInsn(cUnit, mir, callState, dexIdx,
-                                         methodIdx);
-            }
-            int outsOffset = (nextUse + 1) * 4;
-            if (rlArg.wide) {
-                storeBaseDispWide(cUnit, rSP, outsOffset, lowReg, highReg);
-                nextUse += 2;
-            } else {
-                storeWordDisp(cUnit, rSP, outsOffset, lowReg);
-                nextUse++;
-            }
-            callState = nextCallInsn(cUnit, mir, callState, dexIdx, methodIdx);
-        }
-    }
-
-    callState = loadArgRegs(cUnit, mir, dInsn, callState, nextCallInsn,
-                            dexIdx, methodIdx, skipThis);
-
-    if (pcrLabel) {
-        *pcrLabel = genNullCheck(cUnit, oatSSASrc(mir,0), r1, mir);
-    }
-    return callState;
-}
-
-/*
- * May have 0+ arguments (also used for jumbo).  Note that
- * source virtual registers may be in physical registers, so may
- * need to be flushed to home location before copying.  This
- * applies to arg3 and above (see below).
- *
- * Two general strategies:
- *    If < 20 arguments
- *       Pass args 3-18 using vldm/vstm block copy
- *       Pass arg0, arg1 & arg2 in r1-r3
- *    If 20+ arguments
- *       Pass args arg19+ using memcpy block copy
- *       Pass arg0, arg1 & arg2 in r1-r3
- *
- */
-STATIC int genDalvikArgsRange(CompilationUnit* cUnit, MIR* mir,
-                              DecodedInstruction* dInsn, int callState,
-                              ArmLIR** pcrLabel, NextCallInsn nextCallInsn,
-                              uint32_t dexIdx, uint32_t methodIdx,
-                              bool skipThis)
-{
-    int firstArg = dInsn->vC;
-    int numArgs = dInsn->vA;
-
-    // If we can treat it as non-range (Jumbo ops will use range form)
-    if (numArgs <= 5)
-        return genDalvikArgsNoRange(cUnit, mir, dInsn, callState, pcrLabel,
-                                    nextCallInsn, dexIdx, methodIdx,
-                                    skipThis);
-    /*
-     * Make sure range list doesn't span the break between in normal
-     * Dalvik vRegs and the ins.
-     */
-    int highestArg = oatGetSrc(cUnit, mir, numArgs-1).sRegLow;
-    int boundaryReg = cUnit->numDalvikRegisters - cUnit->numIns;
-    if ((firstArg < boundaryReg) && (highestArg >= boundaryReg)) {
-        LOG(FATAL) << "Argument list spanned locals & args";
-    }
-
-    /*
-     * First load the non-register arguments.  Both forms expect all
-     * of the source arguments to be in their home frame location, so
-     * scan the sReg names and flush any that have been promoted to
-     * frame backing storage.
-     */
-    // Scan the rest of the args - if in physReg flush to memory
-    for (int nextArg = 0; nextArg < numArgs;) {
-        RegLocation loc = oatGetRawSrc(cUnit, mir, nextArg);
-        if (loc.wide) {
-            loc = oatUpdateLocWide(cUnit, loc);
-            if ((nextArg >= 2) && (loc.location == kLocPhysReg)) {
-                storeBaseDispWide(cUnit, rSP,
-                                  oatSRegOffset(cUnit, loc.sRegLow),
-                                  loc.lowReg, loc.highReg);
-            }
-            nextArg += 2;
-        } else {
-            loc = oatUpdateLoc(cUnit, loc);
-            if ((nextArg >= 3) && (loc.location == kLocPhysReg)) {
-                storeBaseDisp(cUnit, rSP, oatSRegOffset(cUnit, loc.sRegLow),
-                              loc.lowReg, kWord);
-            }
-            nextArg++;
-        }
-    }
-
-    int startOffset = oatSRegOffset(cUnit,
-        cUnit->regLocation[mir->ssaRep->uses[3]].sRegLow);
-    int outsOffset = 4 /* Method* */ + (3 * 4);
-    if (numArgs >= 20) {
-        // Generate memcpy
-        opRegRegImm(cUnit, kOpAdd, r0, rSP, outsOffset);
-        opRegRegImm(cUnit, kOpAdd, r1, rSP, startOffset);
-        loadWordDisp(cUnit, rSELF, OFFSETOF_MEMBER(Thread, pMemcpy), rLR);
-        loadConstant(cUnit, r2, (numArgs - 3) * 4);
-        callRuntimeHelper(cUnit, rLR);
-        // Restore Method*
-        loadCurrMethodDirect(cUnit, r0);
-    } else {
-        // Use vldm/vstm pair using r3 as a temp
-        int regsLeft = std::min(numArgs - 3, 16);
-        callState = nextCallInsn(cUnit, mir, callState, dexIdx, methodIdx);
-        opRegRegImm(cUnit, kOpAdd, r3, rSP, startOffset);
-        ArmLIR* ld = newLIR3(cUnit, kThumb2Vldms, r3, fr0, regsLeft);
-        //TUNING: loosen barrier
-        ld->defMask = ENCODE_ALL;
-        setMemRefType(ld, true /* isLoad */, kDalvikReg);
-        callState = nextCallInsn(cUnit, mir, callState, dexIdx, methodIdx);
-        opRegRegImm(cUnit, kOpAdd, r3, rSP, 4 /* Method* */ + (3 * 4));
-        callState = nextCallInsn(cUnit, mir, callState, dexIdx, methodIdx);
-        ArmLIR* st = newLIR3(cUnit, kThumb2Vstms, r3, fr0, regsLeft);
-        setMemRefType(st, false /* isLoad */, kDalvikReg);
-        st->defMask = ENCODE_ALL;
-        callState = nextCallInsn(cUnit, mir, callState, dexIdx, methodIdx);
-    }
-
-    callState = loadArgRegs(cUnit, mir, dInsn, callState, nextCallInsn,
-                            dexIdx, methodIdx, skipThis);
-
-    callState = nextCallInsn(cUnit, mir, callState, dexIdx, methodIdx);
-    if (pcrLabel) {
-        *pcrLabel = genNullCheck(cUnit, oatSSASrc(mir,0), r1, mir);
-    }
-    return callState;
-}
-
-// Debugging routine - if null target, branch to DebugMe
-STATIC void genShowTarget(CompilationUnit* cUnit)
-{
-    ArmLIR* branchOver = genCmpImmBranch(cUnit, kArmCondNe, rLR, 0);
-    loadWordDisp(cUnit, rSELF,
-                 OFFSETOF_MEMBER(Thread, pDebugMe), rLR);
-    ArmLIR* target = newLIR0(cUnit, kArmPseudoTargetLabel);
-    target->defMask = -1;
-    branchOver->generic.target = (LIR*)target;
-}
-
-STATIC void genThrowVerificationError(CompilationUnit* cUnit, MIR* mir)
-{
-    loadWordDisp(cUnit, rSELF,
-                 OFFSETOF_MEMBER(Thread, pThrowVerificationErrorFromCode), rLR);
-    loadConstant(cUnit, r0, mir->dalvikInsn.vA);
-    loadConstant(cUnit, r1, mir->dalvikInsn.vB);
-    callRuntimeHelper(cUnit, rLR);
-}
-
-STATIC void genCompareAndBranch(CompilationUnit* cUnit, BasicBlock* bb,
-                                MIR* mir, RegLocation rlSrc1,
-                                RegLocation rlSrc2, ArmLIR* labelList)
-{
-    ArmConditionCode cond;
-    rlSrc1 = loadValue(cUnit, rlSrc1, kCoreReg);
-    rlSrc2 = loadValue(cUnit, rlSrc2, kCoreReg);
-    opRegReg(cUnit, kOpCmp, rlSrc1.lowReg, rlSrc2.lowReg);
-    Opcode opcode = mir->dalvikInsn.opcode;
-    switch(opcode) {
-        case OP_IF_EQ:
-            cond = kArmCondEq;
-            break;
-        case OP_IF_NE:
-            cond = kArmCondNe;
-            break;
-        case OP_IF_LT:
-            cond = kArmCondLt;
-            break;
-        case OP_IF_GE:
-            cond = kArmCondGe;
-            break;
-        case OP_IF_GT:
-            cond = kArmCondGt;
-            break;
-        case OP_IF_LE:
-            cond = kArmCondLe;
-            break;
-        default:
-            cond = (ArmConditionCode)0;
-            LOG(FATAL) << "Unexpected opcode " << (int)opcode;
-    }
-    genConditionalBranch(cUnit, cond, &labelList[bb->taken->id]);
-    genUnconditionalBranch(cUnit, &labelList[bb->fallThrough->id]);
-}
-
-STATIC void genCompareZeroAndBranch(CompilationUnit* cUnit, BasicBlock* bb,
-                                   MIR* mir, RegLocation rlSrc,
-                                   ArmLIR* labelList)
-{
-    ArmConditionCode cond;
-    rlSrc = loadValue(cUnit, rlSrc, kCoreReg);
-    opRegImm(cUnit, kOpCmp, rlSrc.lowReg, 0);
-    Opcode opcode = mir->dalvikInsn.opcode;
-    switch(opcode) {
-        case OP_IF_EQZ:
-            cond = kArmCondEq;
-            break;
-        case OP_IF_NEZ:
-            cond = kArmCondNe;
-            break;
-        case OP_IF_LTZ:
-            cond = kArmCondLt;
-            break;
-        case OP_IF_GEZ:
-            cond = kArmCondGe;
-            break;
-        case OP_IF_GTZ:
-            cond = kArmCondGt;
-            break;
-        case OP_IF_LEZ:
-            cond = kArmCondLe;
-            break;
-        default:
-            cond = (ArmConditionCode)0;
-            LOG(FATAL) << "Unexpected opcode " << (int)opcode;
-    }
-    genConditionalBranch(cUnit, cond, &labelList[bb->taken->id]);
-    genUnconditionalBranch(cUnit, &labelList[bb->fallThrough->id]);
-}
-
-STATIC void genIntToLong(CompilationUnit* cUnit, MIR* mir, RegLocation rlDest,
-                         RegLocation rlSrc)
-{
-    RegLocation rlResult = oatEvalLoc(cUnit, rlDest, kCoreReg, true);
-    if (rlSrc.location == kLocPhysReg) {
-        genRegCopy(cUnit, rlResult.lowReg, rlSrc.lowReg);
-    } else {
-        loadValueDirect(cUnit, rlSrc, rlResult.lowReg);
-    }
-    opRegRegImm(cUnit, kOpAsr, rlResult.highReg,
-                rlResult.lowReg, 31);
-    storeValueWide(cUnit, rlDest, rlResult);
-}
-
-STATIC void genIntNarrowing(CompilationUnit* cUnit, MIR* mir,
-                            RegLocation rlDest, RegLocation rlSrc)
-{
-     rlSrc = loadValue(cUnit, rlSrc, kCoreReg);
-     RegLocation rlResult = oatEvalLoc(cUnit, rlDest, kCoreReg, true);
-     OpKind op = kOpInvalid;
-     switch(mir->dalvikInsn.opcode) {
-         case OP_INT_TO_BYTE:
-             op = kOp2Byte;
-             break;
-         case OP_INT_TO_SHORT:
-              op = kOp2Short;
-              break;
-         case OP_INT_TO_CHAR:
-              op = kOp2Char;
-              break;
-         default:
-             LOG(ERROR) << "Bad int conversion type";
-     }
-     opRegReg(cUnit, op, rlResult.lowReg, rlSrc.lowReg);
-     storeValue(cUnit, rlDest, rlResult);
-}
-
-/*
- * If there are any ins passed in registers that have not been promoted
- * to a callee-save register, flush them to the frame.  Perform intial
- * assignment of promoted arguments.
- */
-STATIC void flushIns(CompilationUnit* cUnit)
-{
-    if (cUnit->numIns == 0)
-        return;
-    int firstArgReg = r1;
-    int lastArgReg = r3;
-    int startVReg = cUnit->numDalvikRegisters - cUnit->numIns;
-    /*
-     * Arguments passed in registers should be flushed
-     * to their backing locations in the frame for now.
-     * Also, we need to do initial assignment for promoted
-     * arguments.  NOTE: an older version of dx had an issue
-     * in which it would reuse static method argument registers.
-     * This could result in the same Dalvik virtual register
-     * being promoted to both core and fp regs.  In those
-     * cases, copy argument to both.  This will be uncommon
-     * enough that it isn't worth attempting to optimize.
-     */
-    for (int i = 0; i < cUnit->numIns; i++) {
-        PromotionMap vMap = cUnit->promotionMap[startVReg + i];
-        if (i <= (lastArgReg - firstArgReg)) {
-            // If arriving in register
-            if (vMap.coreLocation == kLocPhysReg) {
-                genRegCopy(cUnit, vMap.coreReg, firstArgReg + i);
-            }
-            if (vMap.fpLocation == kLocPhysReg) {
-                genRegCopy(cUnit, vMap.fpReg, firstArgReg + i);
-            }
-            // Also put a copy in memory in case we're partially promoted
-            storeBaseDisp(cUnit, rSP, oatSRegOffset(cUnit, startVReg + i),
-                          firstArgReg + i, kWord);
-        } else {
-            // If arriving in frame & promoted
-            if (vMap.coreLocation == kLocPhysReg) {
-                loadWordDisp(cUnit, rSP, oatSRegOffset(cUnit, startVReg + i),
-                             vMap.coreReg);
-            }
-            if (vMap.fpLocation == kLocPhysReg) {
-                loadWordDisp(cUnit, rSP, oatSRegOffset(cUnit, startVReg + i),
-                             vMap.fpReg);
-            }
-        }
-    }
-}
-
-STATIC void genEntrySequence(CompilationUnit* cUnit, BasicBlock* bb)
+void genEntrySequence(CompilationUnit* cUnit, BasicBlock* bb)
 {
     int spillCount = cUnit->numCoreSpills + cUnit->numFPSpills;
     /*
@@ -1099,7 +53,7 @@
     bool skipOverflowCheck = ((cUnit->attrs & METHOD_IS_LEAF) &&
                               ((size_t)cUnit->frameSize <
                               Thread::kStackOverflowReservedBytes));
-    newLIR0(cUnit, kArmPseudoMethodEntry);
+    newLIR0(cUnit, kPseudoMethodEntry);
     if (!skipOverflowCheck) {
         /* Load stack limit */
         loadWordDisp(cUnit, rSELF,
@@ -1119,8 +73,8 @@
     if (!skipOverflowCheck) {
         opRegRegImm(cUnit, kOpSub, rLR, rSP,
                     cUnit->frameSize - (spillCount * 4));
-        genRegRegCheck(cUnit, kArmCondCc, rLR, r12, NULL,
-                       kArmThrowStackOverflow);
+        genRegRegCheck(cUnit, kCondCc, rLR, r12, NULL,
+                       kThrowStackOverflow);
         genRegCopy(cUnit, rSP, rLR);         // Establish stack
     } else {
         opRegImm(cUnit, kOpSub, rSP,
@@ -1142,7 +96,7 @@
     oatFreeTemp(cUnit, r3);
 }
 
-STATIC void genExitSequence(CompilationUnit* cUnit, BasicBlock* bb)
+void genExitSequence(CompilationUnit* cUnit, BasicBlock* bb)
 {
     int spillCount = cUnit->numCoreSpills + cUnit->numFPSpills;
     /*
@@ -1152,7 +106,7 @@
     oatLockTemp(cUnit, r0);
     oatLockTemp(cUnit, r1);
 
-    newLIR0(cUnit, kArmPseudoMethodExit);
+    newLIR0(cUnit, kPseudoMethodExit);
     /* If we're compiling for the debugger, generate an update callout */
     if (cUnit->genDebugger) {
         genDebuggerUpdate(cUnit, DEBUGGER_METHOD_EXIT);
@@ -1181,16 +135,16 @@
  */
 void removeRedundantBranches(CompilationUnit* cUnit)
 {
-    ArmLIR* thisLIR;
+    LIR* thisLIR;
 
-    for (thisLIR = (ArmLIR*) cUnit->firstLIRInsn;
-         thisLIR != (ArmLIR*) cUnit->lastLIRInsn;
+    for (thisLIR = (LIR*) cUnit->firstLIRInsn;
+         thisLIR != (LIR*) cUnit->lastLIRInsn;
          thisLIR = NEXT_LIR(thisLIR)) {
 
         /* Branch to the next instruction */
         if ((thisLIR->opcode == kThumbBUncond) ||
             (thisLIR->opcode == kThumb2BUncond)) {
-            ArmLIR* nextLIR = thisLIR;
+            LIR* nextLIR = thisLIR;
 
             while (true) {
                 nextLIR = NEXT_LIR(nextLIR);
@@ -1198,7 +152,7 @@
                 /*
                  * Is the branch target the next instruction?
                  */
-                if (nextLIR == (ArmLIR*) thisLIR->generic.target) {
+                if (nextLIR == (LIR*) thisLIR->target) {
                     thisLIR->flags.isNop = true;
                     break;
                 }
@@ -1209,109 +163,13 @@
                  * might be the last real instruction.
                  */
                 if (!isPseudoOpcode(nextLIR->opcode) ||
-                    (nextLIR = (ArmLIR*) cUnit->lastLIRInsn))
+                    (nextLIR = (LIR*) cUnit->lastLIRInsn))
                     break;
             }
         }
     }
 }
 
-STATIC void handleSuspendLaunchpads(CompilationUnit *cUnit)
-{
-    ArmLIR** suspendLabel =
-        (ArmLIR **) cUnit->suspendLaunchpads.elemList;
-    int numElems = cUnit->suspendLaunchpads.numUsed;
-
-    for (int i = 0; i < numElems; i++) {
-        /* TUNING: move suspend count load into helper */
-        ArmLIR* lab = suspendLabel[i];
-        ArmLIR* resumeLab = (ArmLIR*)lab->operands[0];
-        cUnit->currentDalvikOffset = lab->operands[1];
-        oatAppendLIR(cUnit, (LIR *)lab);
-        loadWordDisp(cUnit, rSELF,
-                     OFFSETOF_MEMBER(Thread, pTestSuspendFromCode), rLR);
-        if (!cUnit->genDebugger) {
-            // use rSUSPEND for suspend count
-            loadWordDisp(cUnit, rSELF,
-                         Thread::SuspendCountOffset().Int32Value(), rSUSPEND);
-        }
-        opReg(cUnit, kOpBlx, rLR);
-        if ( cUnit->genDebugger) {
-            // use rSUSPEND for update debugger
-            loadWordDisp(cUnit, rSELF,
-                         OFFSETOF_MEMBER(Thread, pUpdateDebuggerFromCode), rSUSPEND);
-        }
-        genUnconditionalBranch(cUnit, resumeLab);
-    }
-}
-
-STATIC void handleThrowLaunchpads(CompilationUnit *cUnit)
-{
-    ArmLIR** throwLabel =
-        (ArmLIR **) cUnit->throwLaunchpads.elemList;
-    int numElems = cUnit->throwLaunchpads.numUsed;
-    int i;
-
-    for (i = 0; i < numElems; i++) {
-        ArmLIR* lab = throwLabel[i];
-        cUnit->currentDalvikOffset = lab->operands[1];
-        oatAppendLIR(cUnit, (LIR *)lab);
-        int funcOffset = 0;
-        int v1 = lab->operands[2];
-        int v2 = lab->operands[3];
-        switch(lab->operands[0]) {
-            case kArmThrowNullPointer:
-                funcOffset = OFFSETOF_MEMBER(Thread, pThrowNullPointerFromCode);
-                break;
-            case kArmThrowArrayBounds:
-                if (v2 != r0) {
-                    genRegCopy(cUnit, r0, v1);
-                    genRegCopy(cUnit, r1, v2);
-                } else {
-                    if (v1 == r1) {
-                        genRegCopy(cUnit, r12, v1);
-                        genRegCopy(cUnit, r1, v2);
-                        genRegCopy(cUnit, r0, r12);
-                    } else {
-                        genRegCopy(cUnit, r1, v2);
-                        genRegCopy(cUnit, r0, v1);
-                    }
-                }
-                funcOffset = OFFSETOF_MEMBER(Thread, pThrowArrayBoundsFromCode);
-                break;
-            case kArmThrowDivZero:
-                funcOffset = OFFSETOF_MEMBER(Thread, pThrowDivZeroFromCode);
-                break;
-            case kArmThrowVerificationError:
-                loadConstant(cUnit, r0, v1);
-                loadConstant(cUnit, r1, v2);
-                funcOffset =
-                    OFFSETOF_MEMBER(Thread, pThrowVerificationErrorFromCode);
-                break;
-            case kArmThrowNegArraySize:
-                genRegCopy(cUnit, r0, v1);
-                funcOffset =
-                    OFFSETOF_MEMBER(Thread, pThrowNegArraySizeFromCode);
-                break;
-            case kArmThrowNoSuchMethod:
-                genRegCopy(cUnit, r0, v1);
-                funcOffset =
-                    OFFSETOF_MEMBER(Thread, pThrowNoSuchMethodFromCode);
-                break;
-            case kArmThrowStackOverflow:
-                funcOffset =
-                    OFFSETOF_MEMBER(Thread, pThrowStackOverflowFromCode);
-                // Restore stack alignment
-                opRegImm(cUnit, kOpAdd, rSP,
-                         (cUnit->numCoreSpills + cUnit->numFPSpills) * 4);
-                break;
-            default:
-                LOG(FATAL) << "Unexpected throw kind: " << lab->operands[0];
-        }
-        loadWordDisp(cUnit, rSELF, funcOffset, rLR);
-        callRuntimeHelper(cUnit, rLR);
-    }
-}
 
 /* Common initialization routine for an architecture family */
 bool oatArchInit()
@@ -1328,11 +186,4 @@
 
     return oatArchVariantInit();
 }
-
-/* Needed by the Assembler */
-void oatSetupResourceMasks(ArmLIR* lir)
-{
-    setupResourceMasks(lir);
-}
-
 }  // namespace art
diff --git a/src/compiler/codegen/arm/ArchUtility.cc b/src/compiler/codegen/arm/ArchUtility.cc
index 75ae456..e1eba44 100644
--- a/src/compiler/codegen/arm/ArchUtility.cc
+++ b/src/compiler/codegen/arm/ArchUtility.cc
@@ -22,6 +22,33 @@
 
 namespace art {
 
+ArmConditionCode oatArmConditionEncoding(ConditionCode code)
+{
+    ArmConditionCode res;
+    switch(code) {
+        case kCondEq: res = kArmCondEq; break;
+        case kCondNe: res = kArmCondNe; break;
+        case kCondCs: res = kArmCondCs; break;
+        case kCondCc: res = kArmCondCc; break;
+        case kCondMi: res = kArmCondMi; break;
+        case kCondPl: res = kArmCondPl; break;
+        case kCondVs: res = kArmCondVs; break;
+        case kCondVc: res = kArmCondVc; break;
+        case kCondHi: res = kArmCondHi; break;
+        case kCondLs: res = kArmCondLs; break;
+        case kCondGe: res = kArmCondGe; break;
+        case kCondLt: res = kArmCondLt; break;
+        case kCondGt: res = kArmCondGt; break;
+        case kCondLe: res = kArmCondLe; break;
+        case kCondAl: res = kArmCondAl; break;
+        case kCondNv: res = kArmCondNv; break;
+        default:
+            LOG(FATAL) << "Bad condition code" << (int)code;
+            res = (ArmConditionCode)0;  // Quiet gcc
+    }
+    return res;
+}
+
 static const char* coreRegNames[16] = {
     "r0",
     "r1",
@@ -49,7 +76,7 @@
     "ror"};
 
 /* Decode and print a ARM register name */
-STATIC char* decodeRegList(ArmOpcode opcode, int vector, char* buf)
+char* decodeRegList(int opcode, int vector, char* buf)
 {
     int i;
     bool printed = false;
@@ -73,7 +100,7 @@
     return buf;
 }
 
-STATIC char*  decodeFPCSRegList(int count, int base, char* buf)
+char*  decodeFPCSRegList(int count, int base, char* buf)
 {
     sprintf(buf, "s%d", base);
     for (int i = 1; i < count; i++) {
@@ -82,7 +109,7 @@
     return buf;
 }
 
-STATIC int expandImmediate(int value)
+int expandImmediate(int value)
 {
     int mode = (value & 0xf00) >> 8;
     u4 bits = value & 0xff;
@@ -108,7 +135,8 @@
  * Interpret a format string and build a string no longer than size
  * See format key in Assemble.c.
  */
-STATIC std::string buildInsnString(const char* fmt, ArmLIR* lir, unsigned char* baseAddr)
+std::string buildInsnString(const char* fmt, LIR* lir,
+                            unsigned char* baseAddr)
 {
     std::string buf;
     int i;
@@ -205,15 +233,15 @@
                        break;
                    case 't':
                        sprintf(tbuf,"0x%08x (L%p)",
-                               (int) baseAddr + lir->generic.offset + 4 +
+                               (int) baseAddr + lir->offset + 4 +
                                (operand << 1),
-                               lir->generic.target);
+                               lir->target);
                        break;
                    case 'u': {
                        int offset_1 = lir->operands[0];
                        int offset_2 = NEXT_LIR(lir)->operands[0];
                        intptr_t target =
-                           ((((intptr_t) baseAddr + lir->generic.offset + 4) &
+                           ((((intptr_t) baseAddr + lir->offset + 4) &
                             ~3) + (offset_1 << 21 >> 9) + (offset_2 << 1)) &
                            0xfffffffc;
                        sprintf(tbuf, "%p", (void *) target);
@@ -250,7 +278,7 @@
 {
     char buf[256];
     buf[0] = 0;
-    ArmLIR* armLIR = (ArmLIR*) lir;
+    LIR* armLIR = (LIR*) lir;
 
     if (mask == ENCODE_ALL) {
         strcpy(buf, "all");
@@ -302,57 +330,57 @@
 /* Pretty-print a LIR instruction */
 void oatDumpLIRInsn(CompilationUnit* cUnit, LIR* arg, unsigned char* baseAddr)
 {
-    ArmLIR* lir = (ArmLIR*) arg;
-    int offset = lir->generic.offset;
+    LIR* lir = (LIR*) arg;
+    int offset = lir->offset;
     int dest = lir->operands[0];
     const bool dumpNop = false;
 
     /* Handle pseudo-ops individually, and all regular insns as a group */
     switch(lir->opcode) {
-        case kArmPseudoMethodEntry:
+        case kPseudoMethodEntry:
             LOG(INFO) << "-------- method entry " <<
                 PrettyMethod(cUnit->method_idx, *cUnit->dex_file);
             break;
-        case kArmPseudoMethodExit:
+        case kPseudoMethodExit:
             LOG(INFO) << "-------- Method_Exit";
             break;
-        case kArmPseudoBarrier:
+        case kPseudoBarrier:
             LOG(INFO) << "-------- BARRIER";
             break;
-        case kArmPseudoExtended:
+        case kPseudoExtended:
             LOG(INFO) << "-------- " << (char* ) dest;
             break;
-        case kArmPseudoSSARep:
+        case kPseudoSSARep:
             DUMP_SSA_REP(LOG(INFO) << "-------- kMirOpPhi: " <<  (char* ) dest);
             break;
-        case kArmPseudoEntryBlock:
+        case kPseudoEntryBlock:
             LOG(INFO) << "-------- entry offset: 0x" << std::hex << dest;
             break;
-        case kArmPseudoDalvikByteCodeBoundary:
+        case kPseudoDalvikByteCodeBoundary:
             LOG(INFO) << "-------- dalvik offset: 0x" << std::hex <<
-                 lir->generic.dalvikOffset << " @ " << (char* )lir->operands[0];
+                 lir->dalvikOffset << " @ " << (char* )lir->operands[0];
             break;
-        case kArmPseudoExitBlock:
+        case kPseudoExitBlock:
             LOG(INFO) << "-------- exit offset: 0x" << std::hex << dest;
             break;
-        case kArmPseudoPseudoAlign4:
+        case kPseudoPseudoAlign4:
             LOG(INFO) << (intptr_t)baseAddr + offset << " (0x" << std::hex <<
                 offset << "): .align4";
             break;
-        case kArmPseudoEHBlockLabel:
+        case kPseudoEHBlockLabel:
             LOG(INFO) << "Exception_Handling:";
             break;
-        case kArmPseudoTargetLabel:
-        case kArmPseudoNormalBlockLabel:
+        case kPseudoTargetLabel:
+        case kPseudoNormalBlockLabel:
             LOG(INFO) << "L" << (intptr_t)lir << ":";
             break;
-        case kArmPseudoThrowTarget:
+        case kPseudoThrowTarget:
             LOG(INFO) << "LT" << (intptr_t)lir << ":";
             break;
-        case kArmPseudoSuspendTarget:
+        case kPseudoSuspendTarget:
             LOG(INFO) << "LS" << (intptr_t)lir << ":";
             break;
-        case kArmPseudoCaseLabel:
+        case kPseudoCaseLabel:
             LOG(INFO) << "LC" << (intptr_t)lir << ": Case target 0x" <<
                 std::hex << lir->operands[0] << "|" << std::dec <<
                 lir->operands[0];
@@ -416,7 +444,7 @@
     LOG(INFO) << "Dumping LIR insns for "
         << PrettyMethod(cUnit->method_idx, *cUnit->dex_file);
     LIR* lirInsn;
-    ArmLIR* armLIR;
+    LIR* armLIR;
     int insnsSize = cUnit->insnsSize;
 
     LOG(INFO) << "Regs (excluding ins) : " << cUnit->numRegs;
@@ -437,15 +465,15 @@
         oatDumpLIRInsn(cUnit, lirInsn, 0);
     }
     for (lirInsn = cUnit->classPointerList; lirInsn; lirInsn = lirInsn->next) {
-        armLIR = (ArmLIR*) lirInsn;
+        armLIR = (LIR*) lirInsn;
         LOG(INFO) << StringPrintf("%x (%04x): .class (%s)",
-            armLIR->generic.offset, armLIR->generic.offset,
+            armLIR->offset, armLIR->offset,
             ((CallsiteInfo *) armLIR->operands[0])->classDescriptor);
     }
     for (lirInsn = cUnit->literalList; lirInsn; lirInsn = lirInsn->next) {
-        armLIR = (ArmLIR*) lirInsn;
+        armLIR = (LIR*) lirInsn;
         LOG(INFO) << StringPrintf("%x (%04x): .word (%#x)",
-            armLIR->generic.offset, armLIR->generic.offset, armLIR->operands[0]);
+            armLIR->offset, armLIR->offset, armLIR->operands[0]);
     }
 
     const DexFile::MethodId& method_id =
diff --git a/src/compiler/codegen/arm/ArmLIR.h b/src/compiler/codegen/arm/ArmLIR.h
index a9c8286..196bddb 100644
--- a/src/compiler/codegen/arm/ArmLIR.h
+++ b/src/compiler/codegen/arm/ArmLIR.h
@@ -167,42 +167,6 @@
 #define DECODE_ALIAS_INFO_REG(X)        (X & 0xffff)
 #define DECODE_ALIAS_INFO_WIDE(X)       ((X & 0x80000000) ? 1 : 0)
 
-typedef enum OpKind {
-    kOpMov,
-    kOpMvn,
-    kOpCmp,
-    kOpLsl,
-    kOpLsr,
-    kOpAsr,
-    kOpRor,
-    kOpNot,
-    kOpAnd,
-    kOpOr,
-    kOpXor,
-    kOpNeg,
-    kOpAdd,
-    kOpAdc,
-    kOpSub,
-    kOpSbc,
-    kOpRsub,
-    kOpMul,
-    kOpDiv,
-    kOpRem,
-    kOpBic,
-    kOpCmn,
-    kOpTst,
-    kOpBkpt,
-    kOpBlx,
-    kOpPush,
-    kOpPop,
-    kOp2Char,
-    kOp2Short,
-    kOp2Byte,
-    kOpCondBr,
-    kOpUncondBr,
-    kOpInvalid,
-} OpKind;
-
 /*
  * Annotate special-purpose core registers:
  *   - VM: r6SELF
@@ -280,6 +244,15 @@
     dr15 = fr30 + FP_DOUBLE,
 } NativeRegisterPool;
 
+/* Target-independent aliases */
+#define rARG0 r0
+#define rARG1 r1
+#define rARG2 r2
+#define rARG3 r3
+#define rRET0 r0
+#define rRET1 r1
+#define rLINK rLR
+
 /* Shift encodings */
 typedef enum ArmShiftEncodings {
     kArmLsl = 0x0,
@@ -308,16 +281,6 @@
     kArmCondNv = 0xf,    /* 1111 */
 } ArmConditionCode;
 
-typedef enum ArmThrowKind {
-    kArmThrowNullPointer,
-    kArmThrowDivZero,
-    kArmThrowArrayBounds,
-    kArmThrowVerificationError,
-    kArmThrowNegArraySize,
-    kArmThrowNoSuchMethod,
-    kArmThrowStackOverflow,
-} ArmThrowKind;
-
 #define isPseudoOpcode(opcode) ((int)(opcode) < 0)
 
 /*
@@ -326,21 +289,21 @@
  * Assemble.c.
  */
 typedef enum ArmOpcode {
-    kArmPseudoSuspendTarget = -15,
-    kArmPseudoThrowTarget = -14,
-    kArmPseudoCaseLabel = -13,
-    kArmPseudoMethodEntry = -12,
-    kArmPseudoMethodExit = -11,
-    kArmPseudoBarrier = -10,
-    kArmPseudoExtended = -9,
-    kArmPseudoSSARep = -8,
-    kArmPseudoEntryBlock = -7,
-    kArmPseudoExitBlock = -6,
-    kArmPseudoTargetLabel = -5,
-    kArmPseudoDalvikByteCodeBoundary = -4,
-    kArmPseudoPseudoAlign4 = -3,
-    kArmPseudoEHBlockLabel = -2,
-    kArmPseudoNormalBlockLabel = -1,
+    kPseudoSuspendTarget = -15,
+    kPseudoThrowTarget = -14,
+    kPseudoCaseLabel = -13,
+    kPseudoMethodEntry = -12,
+    kPseudoMethodExit = -11,
+    kPseudoBarrier = -10,
+    kPseudoExtended = -9,
+    kPseudoSSARep = -8,
+    kPseudoEntryBlock = -7,
+    kPseudoExitBlock = -6,
+    kPseudoTargetLabel = -5,
+    kPseudoDalvikByteCodeBoundary = -4,
+    kPseudoPseudoAlign4 = -3,
+    kPseudoEHBlockLabel = -2,
+    kPseudoNormalBlockLabel = -1,
     /************************************************************************/
     kArm16BitData,       /* DATA   [0] rd[15..0] */
     kThumbAdcRR,         /* adc     [0100000101] rm[5..3] rd[2..0] */
@@ -782,42 +745,12 @@
 
 extern const ArmEncodingMap EncodingMap[kArmLast];
 
-/*
- * Each instance of this struct holds a pseudo or real LIR instruction:
- * - pseudo ones (eg labels and marks) and will be discarded by the assembler.
- * - real ones will be assembled into Thumb instructions.
- *
- * Machine resources are encoded into a 64-bit vector, where the encodings are
- * as following:
- * - [ 0..15]: general purpose registers including PC, SP, and LR
- * - [16..47]: floating-point registers where d0 is expanded to s[01] and s0
- *   starts at bit 16
- * - [48]: IT block
- * - [49]: integer condition code
- * - [50]: floatint-point status word
- */
-typedef struct ArmLIR {
-    LIR generic;
-    ArmOpcode opcode;
-    int operands[4];            // [0..3] = [dest, src1, src2, extra]
-    struct {
-        bool isNop:1;           // LIR is optimized away
-        bool pcRelFixup:1;      // May need pc-relative fixup
-        unsigned int age:4;     // default is 0, set lazily by the optimizer
-        unsigned int size:3;    // bytes (2 for thumb, 2/4 for thumb2)
-        unsigned int unused:23;
-    } flags;
-    int aliasInfo;              // For Dalvik register & litpool disambiguation
-    u8 useMask;                 // Resource mask for use
-    u8 defMask;                 // Resource mask for def
-} ArmLIR;
-
 typedef struct SwitchTable {
     int offset;
     const u2* table;            // Original dex table
     int vaddr;                  // Dalvik offset of switch opcode
-    ArmLIR* bxInst;             // Switch indirect branch instruction
-    ArmLIR** targets;           // Array of case targets
+    LIR* bxInst;                // Switch indirect branch instruction
+    LIR** targets;              // Array of case targets
 } SwitchTable;
 
 typedef struct FillArrayData {
@@ -827,12 +760,6 @@
     int vaddr;                 // Dalvik offset of OP_FILL_ARRAY_DATA opcode
 } FillArrayData;
 
-/* Utility macros to traverse the LIR/ArmLIR list */
-#define NEXT_LIR(lir) ((ArmLIR *) lir->generic.next)
-#define PREV_LIR(lir) ((ArmLIR *) lir->generic.prev)
-
-#define NEXT_LIR_LVALUE(lir) (lir)->generic.next
-#define PREV_LIR_LVALUE(lir) (lir)->generic.prev
 
 }  // namespace art
 
diff --git a/src/compiler/codegen/arm/ArmRallocUtil.cc b/src/compiler/codegen/arm/ArmRallocUtil.cc
index 38f1b88..a020687 100644
--- a/src/compiler/codegen/arm/ArmRallocUtil.cc
+++ b/src/compiler/codegen/arm/ArmRallocUtil.cc
@@ -184,9 +184,9 @@
 }
 
 /* Convert an instruction to a NOP */
-STATIC void oatNopLIR( LIR* lir)
+void oatNopLIR( LIR* lir)
 {
-    ((ArmLIR*)lir)->flags.isNop = true;
+    ((LIR*)lir)->flags.isNop = true;
 }
 
 }  // namespace art
diff --git a/src/compiler/codegen/arm/Assemble.cc b/src/compiler/codegen/arm/Assemble.cc
index 0cd7605..53f9494 100644
--- a/src/compiler/codegen/arm/Assemble.cc
+++ b/src/compiler/codegen/arm/Assemble.cc
@@ -77,7 +77,7 @@
  *
  *  [!] escape.  To insert "!", use "!!"
  */
-/* NOTE: must be kept in sync with enum ArmOpcode from ArmLIR.h */
+/* NOTE: must be kept in sync with enum ArmOpcode from LIR.h */
 const ArmEncodingMap EncodingMap[kArmLast] = {
     ENCODING_MAP(kArm16BitData,    0x0000,
                  kFmtBitBlt, 15, 0, kFmtUnused, -1, -1, kFmtUnused, -1, -1,
@@ -983,13 +983,13 @@
 AssemblerStatus oatAssembleInstructions(CompilationUnit* cUnit,
                                         intptr_t startAddr)
 {
-    ArmLIR* lir;
+    LIR* lir;
     AssemblerStatus res = kSuccess;  // Assume success
 
-    for (lir = (ArmLIR *) cUnit->firstLIRInsn; lir; lir = NEXT_LIR(lir)) {
+    for (lir = (LIR *) cUnit->firstLIRInsn; lir; lir = NEXT_LIR(lir)) {
 
         if (lir->opcode < 0) {
-            if ((lir->opcode == kArmPseudoPseudoAlign4) &&
+            if ((lir->opcode == kPseudoPseudoAlign4) &&
                 /* 1 means padding is needed */
                 (lir->operands[0] == 1)) {
                 cUnit->codeBuffer.push_back(PADDING_MOV_R5_R5);
@@ -1024,9 +1024,9 @@
                  * However, if the load displacement exceeds the limit,
                  * we revert to a 2-instruction materialization sequence.
                  */
-                ArmLIR *lirTarget = (ArmLIR *) lir->generic.target;
-                intptr_t pc = (lir->generic.offset + 4) & ~3;
-                intptr_t target = lirTarget->generic.offset;
+                LIR *lirTarget = (LIR *) lir->target;
+                intptr_t pc = (lir->offset + 4) & ~3;
+                intptr_t target = lirTarget->offset;
                 int delta = target - pc;
                 if (delta & 0x3) {
                     LOG(FATAL) << "PC-rel offset not multiple of 4: " << delta;
@@ -1050,10 +1050,10 @@
                         lir->operands[0] : rLR;
 
                     // Add new Adr to generate the address
-                    ArmLIR *newAdr = (ArmLIR *)oatNew(cUnit, sizeof(ArmLIR),
+                    LIR *newAdr = (LIR *)oatNew(cUnit, sizeof(LIR),
                         true, kAllocLIR);
-                    newAdr->generic.dalvikOffset = lir->generic.dalvikOffset;
-                    newAdr->generic.target = lir->generic.target;
+                    newAdr->dalvikOffset = lir->dalvikOffset;
+                    newAdr->target = lir->target;
                     newAdr->opcode = kThumb2Adr;
                     newAdr->operands[0] = baseReg;
                     oatSetupResourceMasks(newAdr);
@@ -1078,28 +1078,28 @@
                     }
                 }
             } else if (lir->opcode == kThumb2Cbnz || lir->opcode == kThumb2Cbz) {
-                ArmLIR *targetLIR = (ArmLIR *) lir->generic.target;
-                intptr_t pc = lir->generic.offset + 4;
-                intptr_t target = targetLIR->generic.offset;
+                LIR *targetLIR = (LIR *) lir->target;
+                intptr_t pc = lir->offset + 4;
+                intptr_t target = targetLIR->offset;
                 int delta = target - pc;
                 if (delta > 126 || delta < 0) {
                     /* Convert to cmp rx,#0 / b[eq/ne] tgt pair */
-                    ArmLIR *newInst = (ArmLIR *)oatNew(cUnit, sizeof(ArmLIR),
+                    LIR *newInst = (LIR *)oatNew(cUnit, sizeof(LIR),
                         true, kAllocLIR);
                     /* Make new branch instruction and insert after */
-                    newInst->generic.dalvikOffset = lir->generic.dalvikOffset;
+                    newInst->dalvikOffset = lir->dalvikOffset;
                     newInst->opcode = kThumbBCond;
                     newInst->operands[0] = 0;
                     newInst->operands[1] = (lir->opcode == kThumb2Cbz) ?
                                             kArmCondEq : kArmCondNe;
-                    newInst->generic.target = lir->generic.target;
+                    newInst->target = lir->target;
                     oatSetupResourceMasks(newInst);
                     oatInsertLIRAfter((LIR *)lir, (LIR *)newInst);
                     /* Convert the cb[n]z to a cmp rx, #0 ] */
                     lir->opcode = kThumbCmpRI8;
                     /* operand[0] is src1 in both cb[n]z & CmpRI8 */
                     lir->operands[1] = 0;
-                    lir->generic.target = 0;
+                    lir->target = 0;
                     oatSetupResourceMasks(lir);
                     res = kRetryAll;
                 } else {
@@ -1131,11 +1131,11 @@
                 }
             } else if (lir->opcode == kThumbBCond ||
                        lir->opcode == kThumb2BCond) {
-                ArmLIR *targetLIR = (ArmLIR *) lir->generic.target;
+                LIR *targetLIR = (LIR *) lir->target;
                 int delta = 0;
                 DCHECK(targetLIR);
-                intptr_t pc = lir->generic.offset + 4;
-                intptr_t target = targetLIR->generic.offset;
+                intptr_t pc = lir->offset + 4;
+                intptr_t target = targetLIR->offset;
                 delta = target - pc;
                 if ((lir->opcode == kThumbBCond) &&
                     (delta > 254 || delta < -256)) {
@@ -1145,9 +1145,9 @@
                 }
                 lir->operands[0] = delta >> 1;
             } else if (lir->opcode == kThumb2BUncond) {
-                ArmLIR *targetLIR = (ArmLIR *) lir->generic.target;
-                intptr_t pc = lir->generic.offset + 4;
-                intptr_t target = targetLIR->generic.offset;
+                LIR *targetLIR = (LIR *) lir->target;
+                intptr_t pc = lir->offset + 4;
+                intptr_t target = targetLIR->offset;
                 int delta = target - pc;
                 lir->operands[0] = delta >> 1;
                 if (lir->operands[0] == 0) {  // Useless branch?
@@ -1155,9 +1155,9 @@
                     res = kRetryAll;
                 }
             } else if (lir->opcode == kThumbBUncond) {
-                ArmLIR *targetLIR = (ArmLIR *) lir->generic.target;
-                intptr_t pc = lir->generic.offset + 4;
-                intptr_t target = targetLIR->generic.offset;
+                LIR *targetLIR = (LIR *) lir->target;
+                intptr_t pc = lir->offset + 4;
+                intptr_t target = targetLIR->offset;
                 int delta = target - pc;
                 if (delta > 2046 || delta < -2048) {
                     // Convert to Thumb2BCond w/ kArmCondAl
@@ -1175,7 +1175,7 @@
             } else if (lir->opcode == kThumbBlx1) {
                 DCHECK(NEXT_LIR(lir)->opcode == kThumbBlx2);
                 /* curPC is Thumb */
-                intptr_t curPC = (startAddr + lir->generic.offset + 4) & ~3;
+                intptr_t curPC = (startAddr + lir->offset + 4) & ~3;
                 intptr_t target = lir->operands[1];
 
                 /* Match bit[1] in target with base */
@@ -1190,7 +1190,7 @@
             } else if (lir->opcode == kThumbBl1) {
                 DCHECK(NEXT_LIR(lir)->opcode == kThumbBl2);
                 /* Both curPC and target are Thumb */
-                intptr_t curPC = startAddr + lir->generic.offset + 4;
+                intptr_t curPC = startAddr + lir->offset + 4;
                 intptr_t target = lir->operands[1];
 
                 int delta = target - curPC;
@@ -1200,30 +1200,30 @@
                 NEXT_LIR(lir)->operands[0] = (delta>> 1) & 0x7ff;
             } else if (lir->opcode == kThumb2Adr) {
                 SwitchTable *tabRec = (SwitchTable*)lir->operands[2];
-                ArmLIR* target = (ArmLIR*)lir->generic.target;
+                LIR* target = (LIR*)lir->target;
                 int targetDisp = tabRec ? tabRec->offset
-                                        : target->generic.offset;
-                int disp = targetDisp - ((lir->generic.offset + 4) & ~3);
+                                        : target->offset;
+                int disp = targetDisp - ((lir->offset + 4) & ~3);
                 if (disp < 4096) {
                     lir->operands[1] = disp;
                 } else {
                     // convert to ldimm16l, ldimm16h, add tgt, pc, operands[0]
-                    ArmLIR *newMov16L =
-                        (ArmLIR *)oatNew(cUnit, sizeof(ArmLIR), true,
+                    LIR *newMov16L =
+                        (LIR *)oatNew(cUnit, sizeof(LIR), true,
                         kAllocLIR);
-                    newMov16L->generic.dalvikOffset = lir->generic.dalvikOffset;
-                    newMov16L->generic.target = lir->generic.target;
+                    newMov16L->dalvikOffset = lir->dalvikOffset;
+                    newMov16L->target = lir->target;
                     newMov16L->opcode = kThumb2MovImm16LST;
                     newMov16L->operands[0] = lir->operands[0];
                     newMov16L->operands[2] = (intptr_t)lir;
                     newMov16L->operands[3] = (intptr_t)tabRec;
                     oatSetupResourceMasks(newMov16L);
                     oatInsertLIRBefore((LIR*)lir, (LIR*)newMov16L);
-                    ArmLIR *newMov16H =
-                        (ArmLIR *)oatNew(cUnit, sizeof(ArmLIR), true,
+                    LIR *newMov16H =
+                        (LIR *)oatNew(cUnit, sizeof(LIR), true,
                         kAllocLIR);
-                    newMov16H->generic.dalvikOffset = lir->generic.dalvikOffset;
-                    newMov16H->generic.target = lir->generic.target;
+                    newMov16H->dalvikOffset = lir->dalvikOffset;
+                    newMov16H->target = lir->target;
                     newMov16H->opcode = kThumb2MovImm16HST;
                     newMov16H->operands[0] = lir->operands[0];
                     newMov16H->operands[2] = (intptr_t)lir;
@@ -1238,24 +1238,24 @@
                 }
             } else if (lir->opcode == kThumb2MovImm16LST) {
                 // operands[1] should hold disp, [2] has add, [3] has tabRec
-                ArmLIR *addPCInst = (ArmLIR*)lir->operands[2];
+                LIR *addPCInst = (LIR*)lir->operands[2];
                 SwitchTable *tabRec = (SwitchTable*)lir->operands[3];
-                // If tabRec is null, this is a literal load. Use generic.target
-                ArmLIR* target = (ArmLIR*)lir->generic.target;
+                // If tabRec is null, this is a literal load. Use target
+                LIR* target = (LIR*)lir->target;
                 int targetDisp = tabRec ? tabRec->offset
-                                        : target->generic.offset;
+                                        : target->offset;
                 lir->operands[1] = (targetDisp -
-                    (addPCInst->generic.offset + 4)) & 0xffff;
+                    (addPCInst->offset + 4)) & 0xffff;
             } else if (lir->opcode == kThumb2MovImm16HST) {
                 // operands[1] should hold disp, [2] has add, [3] has tabRec
-                ArmLIR *addPCInst = (ArmLIR*)lir->operands[2];
+                LIR *addPCInst = (LIR*)lir->operands[2];
                 SwitchTable *tabRec = (SwitchTable*)lir->operands[3];
-                // If tabRec is null, this is a literal load. Use generic.target
-                ArmLIR* target = (ArmLIR*)lir->generic.target;
+                // If tabRec is null, this is a literal load. Use target
+                LIR* target = (LIR*)lir->target;
                 int targetDisp = tabRec ? tabRec->offset
-                                        : target->generic.offset;
+                                        : target->offset;
                 lir->operands[1] = ((targetDisp -
-                    (addPCInst->generic.offset + 4)) >> 16) & 0xffff;
+                    (addPCInst->offset + 4)) >> 16) & 0xffff;
             }
         }
         /*
@@ -1387,19 +1387,19 @@
  */
 int oatAssignInsnOffsets(CompilationUnit* cUnit)
 {
-    ArmLIR* armLIR;
+    LIR* armLIR;
     int offset = 0;
 
-    for (armLIR = (ArmLIR *) cUnit->firstLIRInsn;
+    for (armLIR = (LIR *) cUnit->firstLIRInsn;
          armLIR;
          armLIR = NEXT_LIR(armLIR)) {
-        armLIR->generic.offset = offset;
+        armLIR->offset = offset;
         if (armLIR->opcode >= 0) {
             if (!armLIR->flags.isNop) {
                 armLIR->flags.size = EncodingMap[armLIR->opcode].size * 2;
                 offset += armLIR->flags.size;
             }
-        } else if (armLIR->opcode == kArmPseudoPseudoAlign4) {
+        } else if (armLIR->opcode == kPseudoPseudoAlign4) {
             if (offset & 0x2) {
                 offset += 2;
                 armLIR->operands[0] = 1;
diff --git a/src/compiler/codegen/arm/Codegen.h b/src/compiler/codegen/arm/Codegen.h
index 8d3c425..a565cb1 100644
--- a/src/compiler/codegen/arm/Codegen.h
+++ b/src/compiler/codegen/arm/Codegen.h
@@ -27,30 +27,72 @@
 namespace art {
 
 #if defined(_CODEGEN_C)
-/*
- * loadConstant() sometimes needs to add a small imm to a pre-existing constant
- */
-STATIC ArmLIR *opRegImm(CompilationUnit* cUnit, OpKind op, int rDestSrc1,
-                        int value);
-STATIC ArmLIR *opRegReg(CompilationUnit* cUnit, OpKind op, int rDestSrc1,
-                        int rSrc2);
+LIR *opRegImm(CompilationUnit* cUnit, OpKind op, int rDestSrc1, int value);
+LIR *opRegReg(CompilationUnit* cUnit, OpKind op, int rDestSrc1, int rSrc2);
 
-/* Forward decalraton the portable versions due to circular dependency */
-STATIC bool genArithOpFloatPortable(CompilationUnit* cUnit, MIR* mir,
+/* Forward declaraton the portable versions due to circular dependency */
+bool genArithOpFloatPortable(CompilationUnit* cUnit, MIR* mir,
                                     RegLocation rlDest, RegLocation rlSrc1,
                                     RegLocation rlSrc2);
 
-STATIC bool genArithOpDoublePortable(CompilationUnit* cUnit, MIR* mir,
+bool genArithOpDoublePortable(CompilationUnit* cUnit, MIR* mir,
                                      RegLocation rlDest, RegLocation rlSrc1,
                                      RegLocation rlSrc2);
 
-STATIC bool genConversionPortable(CompilationUnit* cUnit, MIR* mir);
+bool genConversionPortable(CompilationUnit* cUnit, MIR* mir);
+
+ArmConditionCode oatArmConditionEncoding(ConditionCode code);
+
+int loadHelper(CompilationUnit* cUnit, int offset);
+LIR* callRuntimeHelper(CompilationUnit* cUnit, int reg);
+RegLocation getRetLoc(CompilationUnit* cUnit);
+LIR* loadConstant(CompilationUnit* cUnit, int reg, int immVal);
+void genRegCopyWide(CompilationUnit* cUnit, int destLo, int destHi,
+                    int srcLo, int srcHi);
+LIR* genRegCopy(CompilationUnit* cUnit, int rDest, int rSrc);
+LIR* genCmpImmBranch(CompilationUnit* cUnit, ConditionCode cond, int reg,
+                     int checkValue);
+void freeRegLocTemps(CompilationUnit* cUnit, RegLocation rlKeep,
+                     RegLocation rlFree);
+
+
+/*
+ * Return most flexible allowed register class based on size.
+ * Bug: 2813841
+ * Must use a core register for data types narrower than word (due
+ * to possible unaligned load/store.
+ */
+inline RegisterClass oatRegClassBySize(OpSize size)
+{
+    return (size == kUnsignedHalf ||
+            size == kSignedHalf ||
+            size == kUnsignedByte ||
+            size == kSignedByte ) ? kCoreReg : kAnyReg;
+}
+
+/*
+ * Construct an s4 from two consecutive half-words of switch data.
+ * This needs to check endianness because the DEX optimizer only swaps
+ * half-words in instruction stream.
+ *
+ * "switchData" must be 32-bit aligned.
+ */
+#if __BYTE_ORDER == __LITTLE_ENDIAN
+inline s4 s4FromSwitchData(const void* switchData) {
+    return *(s4*) switchData;
+}
+#else
+inline s4 s4FromSwitchData(const void* switchData) {
+    u2* data = switchData;
+    return data[0] | (((s4) data[1]) << 16);
+}
+#endif
 
 #endif
 
-extern void oatSetupResourceMasks(ArmLIR* lir);
+extern void oatSetupResourceMasks(LIR* lir);
 
-extern ArmLIR* oatRegCopyNoInsert(CompilationUnit* cUnit, int rDest,
+extern LIR* oatRegCopyNoInsert(CompilationUnit* cUnit, int rDest,
                                           int rSrc);
 
 }  // namespace art
diff --git a/src/compiler/codegen/arm/CodegenCommon.cc b/src/compiler/codegen/arm/CodegenCommon.cc
deleted file mode 100644
index fb6ad30..0000000
--- a/src/compiler/codegen/arm/CodegenCommon.cc
+++ /dev/null
@@ -1,410 +0,0 @@
-/*
- * Copyright (C) 2011 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.
- */
-
-namespace art {
-
-/*
- * This file contains codegen and support common to all supported
- * ARM variants.  It is included by:
- *
- *        Codegen-$(TARGET_ARCH_VARIANT).c
- *
- * which combines this common code with specific support found in the
- * applicable directory below this one.
- */
-
-/* Track exercised opcodes */
-static int opcodeCoverage[kNumPackedOpcodes];
-
-STATIC void setMemRefType(ArmLIR* lir, bool isLoad, int memType)
-{
-    u8 *maskPtr;
-    u8 mask = ENCODE_MEM;;
-    DCHECK(EncodingMap[lir->opcode].flags & (IS_LOAD | IS_STORE));
-    if (isLoad) {
-        maskPtr = &lir->useMask;
-    } else {
-        maskPtr = &lir->defMask;
-    }
-    /* Clear out the memref flags */
-    *maskPtr &= ~mask;
-    /* ..and then add back the one we need */
-    switch(memType) {
-        case kLiteral:
-            DCHECK(isLoad);
-            *maskPtr |= ENCODE_LITERAL;
-            break;
-        case kDalvikReg:
-            *maskPtr |= ENCODE_DALVIK_REG;
-            break;
-        case kHeapRef:
-            *maskPtr |= ENCODE_HEAP_REF;
-            break;
-        case kMustNotAlias:
-            /* Currently only loads can be marked as kMustNotAlias */
-            DCHECK(!(EncodingMap[lir->opcode].flags & IS_STORE));
-            *maskPtr |= ENCODE_MUST_NOT_ALIAS;
-            break;
-        default:
-            LOG(FATAL) << "Oat: invalid memref kind - " << memType;
-    }
-}
-
-/*
- * Mark load/store instructions that access Dalvik registers through r5FP +
- * offset.
- */
-STATIC void annotateDalvikRegAccess(ArmLIR* lir, int regId, bool isLoad)
-{
-    setMemRefType(lir, isLoad, kDalvikReg);
-
-    /*
-     * Store the Dalvik register id in aliasInfo. Mark he MSB if it is a 64-bit
-     * access.
-     */
-    lir->aliasInfo = regId;
-    if (DOUBLEREG(lir->operands[0])) {
-        lir->aliasInfo |= 0x80000000;
-    }
-}
-
-/*
- * Decode the register id.
- */
-STATIC inline u8 getRegMaskCommon(int reg)
-{
-    u8 seed;
-    int shift;
-    int regId = reg & 0x1f;
-
-    /*
-     * Each double register is equal to a pair of single-precision FP registers
-     */
-    seed = DOUBLEREG(reg) ? 3 : 1;
-    /* FP register starts at bit position 16 */
-    shift = FPREG(reg) ? kFPReg0 : 0;
-    /* Expand the double register id into single offset */
-    shift += regId;
-    return (seed << shift);
-}
-
-/*
- * Mark the corresponding bit(s).
- */
-STATIC inline void setupRegMask(u8* mask, int reg)
-{
-    *mask |= getRegMaskCommon(reg);
-}
-
-/*
- * Set up the proper fields in the resource mask
- */
-STATIC void setupResourceMasks(ArmLIR* lir)
-{
-    int opcode = lir->opcode;
-    int flags;
-
-    if (opcode <= 0) {
-        lir->useMask = lir->defMask = 0;
-        return;
-    }
-
-    flags = EncodingMap[lir->opcode].flags;
-
-    if (flags & NEEDS_FIXUP) {
-        lir->flags.pcRelFixup = true;
-    }
-
-    /* Set up the mask for resources that are updated */
-    if (flags & (IS_LOAD | IS_STORE)) {
-        /* Default to heap - will catch specialized classes later */
-        setMemRefType(lir, flags & IS_LOAD, kHeapRef);
-    }
-
-    /*
-     * Conservatively assume the branch here will call out a function that in
-     * turn will trash everything.
-     */
-    if (flags & IS_BRANCH) {
-        lir->defMask = lir->useMask = ENCODE_ALL;
-        return;
-    }
-
-    if (flags & REG_DEF0) {
-        setupRegMask(&lir->defMask, lir->operands[0]);
-    }
-
-    if (flags & REG_DEF1) {
-        setupRegMask(&lir->defMask, lir->operands[1]);
-    }
-
-    if (flags & REG_DEF_SP) {
-        lir->defMask |= ENCODE_REG_SP;
-    }
-
-    if (flags & REG_DEF_LR) {
-        lir->defMask |= ENCODE_REG_LR;
-    }
-
-    if (flags & REG_DEF_LIST0) {
-        lir->defMask |= ENCODE_REG_LIST(lir->operands[0]);
-    }
-
-    if (flags & REG_DEF_LIST1) {
-        lir->defMask |= ENCODE_REG_LIST(lir->operands[1]);
-    }
-
-    if (flags & REG_DEF_FPCS_LIST0) {
-        lir->defMask |= ENCODE_REG_FPCS_LIST(lir->operands[0]);
-    }
-
-    if (flags & REG_DEF_FPCS_LIST2) {
-        for (int i = 0; i < lir->operands[2]; i++) {
-            setupRegMask(&lir->defMask, lir->operands[1] + i);
-        }
-    }
-
-    if (flags & SETS_CCODES) {
-        lir->defMask |= ENCODE_CCODE;
-    }
-
-    /* Conservatively treat the IT block */
-    if (flags & IS_IT) {
-        lir->defMask = ENCODE_ALL;
-    }
-
-    if (flags & (REG_USE0 | REG_USE1 | REG_USE2 | REG_USE3)) {
-        int i;
-
-        for (i = 0; i < 4; i++) {
-            if (flags & (1 << (kRegUse0 + i))) {
-                setupRegMask(&lir->useMask, lir->operands[i]);
-            }
-        }
-    }
-
-    if (flags & REG_USE_PC) {
-        lir->useMask |= ENCODE_REG_PC;
-    }
-
-    if (flags & REG_USE_SP) {
-        lir->useMask |= ENCODE_REG_SP;
-    }
-
-    if (flags & REG_USE_LIST0) {
-        lir->useMask |= ENCODE_REG_LIST(lir->operands[0]);
-    }
-
-    if (flags & REG_USE_LIST1) {
-        lir->useMask |= ENCODE_REG_LIST(lir->operands[1]);
-    }
-
-    if (flags & REG_USE_FPCS_LIST0) {
-        lir->useMask |= ENCODE_REG_FPCS_LIST(lir->operands[0]);
-    }
-
-    if (flags & REG_USE_FPCS_LIST2) {
-        for (int i = 0; i < lir->operands[2]; i++) {
-            setupRegMask(&lir->useMask, lir->operands[1] + i);
-        }
-    }
-
-    if (flags & USES_CCODES) {
-        lir->useMask |= ENCODE_CCODE;
-    }
-
-    /* Fixup for kThumbPush/lr and kThumbPop/pc */
-    if (opcode == kThumbPush || opcode == kThumbPop) {
-        u8 r8Mask = getRegMaskCommon(r8);
-        if ((opcode == kThumbPush) && (lir->useMask & r8Mask)) {
-            lir->useMask &= ~r8Mask;
-            lir->useMask |= ENCODE_REG_LR;
-        } else if ((opcode == kThumbPop) && (lir->defMask & r8Mask)) {
-            lir->defMask &= ~r8Mask;
-            lir->defMask |= ENCODE_REG_PC;
-        }
-    }
-}
-
-/*
- * The following are building blocks to construct low-level IRs with 0 - 4
- * operands.
- */
-STATIC ArmLIR* newLIR0(CompilationUnit* cUnit, ArmOpcode opcode)
-{
-    ArmLIR* insn = (ArmLIR* ) oatNew(cUnit, sizeof(ArmLIR), true, kAllocLIR);
-    DCHECK(isPseudoOpcode(opcode) || (EncodingMap[opcode].flags & NO_OPERAND));
-    insn->opcode = opcode;
-    setupResourceMasks(insn);
-    insn->generic.dalvikOffset = cUnit->currentDalvikOffset;
-    oatAppendLIR(cUnit, (LIR*) insn);
-    return insn;
-}
-
-STATIC ArmLIR* newLIR1(CompilationUnit* cUnit, ArmOpcode opcode,
-                           int dest)
-{
-    ArmLIR* insn = (ArmLIR* ) oatNew(cUnit, sizeof(ArmLIR), true, kAllocLIR);
-    DCHECK(isPseudoOpcode(opcode) || (EncodingMap[opcode].flags & IS_UNARY_OP));
-    insn->opcode = opcode;
-    insn->operands[0] = dest;
-    setupResourceMasks(insn);
-    insn->generic.dalvikOffset = cUnit->currentDalvikOffset;
-    oatAppendLIR(cUnit, (LIR*) insn);
-    return insn;
-}
-
-STATIC ArmLIR* newLIR2(CompilationUnit* cUnit, ArmOpcode opcode,
-                           int dest, int src1)
-{
-    ArmLIR* insn = (ArmLIR* ) oatNew(cUnit, sizeof(ArmLIR), true, kAllocLIR);
-    DCHECK(isPseudoOpcode(opcode) ||
-           (EncodingMap[opcode].flags & IS_BINARY_OP));
-    insn->opcode = opcode;
-    insn->operands[0] = dest;
-    insn->operands[1] = src1;
-    setupResourceMasks(insn);
-    insn->generic.dalvikOffset = cUnit->currentDalvikOffset;
-    oatAppendLIR(cUnit, (LIR*) insn);
-    return insn;
-}
-
-STATIC ArmLIR* newLIR3(CompilationUnit* cUnit, ArmOpcode opcode,
-                           int dest, int src1, int src2)
-{
-    ArmLIR* insn = (ArmLIR* ) oatNew(cUnit, sizeof(ArmLIR), true, kAllocLIR);
-    DCHECK(isPseudoOpcode(opcode) ||
-           (EncodingMap[opcode].flags & IS_TERTIARY_OP))
-            << (int)opcode << " "
-            << PrettyMethod(cUnit->method_idx, *cUnit->dex_file) << " "
-            << cUnit->currentDalvikOffset;
-    insn->opcode = opcode;
-    insn->operands[0] = dest;
-    insn->operands[1] = src1;
-    insn->operands[2] = src2;
-    setupResourceMasks(insn);
-    insn->generic.dalvikOffset = cUnit->currentDalvikOffset;
-    oatAppendLIR(cUnit, (LIR*) insn);
-    return insn;
-}
-
-#if defined(_ARMV7_A) || defined(_ARMV7_A_NEON)
-STATIC ArmLIR* newLIR4(CompilationUnit* cUnit, ArmOpcode opcode,
-                           int dest, int src1, int src2, int info)
-{
-    ArmLIR* insn = (ArmLIR* ) oatNew(cUnit, sizeof(ArmLIR), true, kAllocLIR);
-    DCHECK(isPseudoOpcode(opcode) ||
-           (EncodingMap[opcode].flags & IS_QUAD_OP));
-    insn->opcode = opcode;
-    insn->operands[0] = dest;
-    insn->operands[1] = src1;
-    insn->operands[2] = src2;
-    insn->operands[3] = info;
-    setupResourceMasks(insn);
-    insn->generic.dalvikOffset = cUnit->currentDalvikOffset;
-    oatAppendLIR(cUnit, (LIR*) insn);
-    return insn;
-}
-#endif
-
-/*
- * Search the existing constants in the literal pool for an exact or close match
- * within specified delta (greater or equal to 0).
- */
-STATIC ArmLIR* scanLiteralPool(LIR* dataTarget, int value, unsigned int delta)
-{
-    while (dataTarget) {
-        if (((unsigned) (value - ((ArmLIR* ) dataTarget)->operands[0])) <=
-            delta)
-            return (ArmLIR* ) dataTarget;
-        dataTarget = dataTarget->next;
-    }
-    return NULL;
-}
-
-/* Search the existing constants in the literal pool for an exact wide match */
-STATIC ArmLIR* scanLiteralPoolWide(LIR* dataTarget, int valLo, int valHi)
-{
-    bool loMatch = false;
-    LIR* loTarget = NULL;
-    while (dataTarget) {
-        if (loMatch && (((ArmLIR*)dataTarget)->operands[0] == valHi)) {
-            return (ArmLIR*)loTarget;
-        }
-        loMatch = false;
-        if (((ArmLIR*)dataTarget)->operands[0] == valLo) {
-            loMatch = true;
-            loTarget = dataTarget;
-        }
-        dataTarget = dataTarget->next;
-    }
-    return NULL;
-}
-
-/*
- * The following are building blocks to insert constants into the pool or
- * instruction streams.
- */
-
-/* Add a 32-bit constant either in the constant pool or mixed with code */
-STATIC ArmLIR* addWordData(CompilationUnit* cUnit, LIR* *constantListP,
-                           int value)
-{
-    /* Add the constant to the literal pool */
-    if (constantListP) {
-        ArmLIR* newValue = (ArmLIR* ) oatNew(cUnit, sizeof(ArmLIR), true,
-                                             kAllocData);
-        newValue->operands[0] = value;
-        newValue->generic.next = *constantListP;
-        *constantListP = (LIR*) newValue;
-        return newValue;
-    } else {
-        /* Add the constant in the middle of code stream */
-        newLIR1(cUnit, kArm16BitData, (value & 0xffff));
-        newLIR1(cUnit, kArm16BitData, (value >> 16));
-    }
-    return NULL;
-}
-
-/* Add a 64-bit constant to the constant pool or mixed with code */
-STATIC ArmLIR* addWideData(CompilationUnit* cUnit, LIR* *constantListP,
-                           int valLo, int valHi)
-{
-    ArmLIR* res;
-    //NOTE: hard-coded little endian
-    if (constantListP == NULL) {
-        res = addWordData(cUnit, NULL, valLo);
-        addWordData(cUnit, NULL, valHi);
-    } else {
-        // Insert high word into list first
-        addWordData(cUnit, constantListP, valHi);
-        res = addWordData(cUnit, constantListP, valLo);
-    }
-    return res;
-}
-
-/*
- * Generate an kArmPseudoBarrier marker to indicate the boundary of special
- * blocks.
- */
-STATIC void genBarrier(CompilationUnit* cUnit)
-{
-    ArmLIR* barrier = newLIR0(cUnit, kArmPseudoBarrier);
-    /* Mark all resources as being clobbered */
-    barrier->defMask = -1;
-}
-
-}  // namespace art
diff --git a/src/compiler/codegen/arm/FP/Thumb2VFP.cc b/src/compiler/codegen/arm/FP/Thumb2VFP.cc
index 494e09f..094b952 100644
--- a/src/compiler/codegen/arm/FP/Thumb2VFP.cc
+++ b/src/compiler/codegen/arm/FP/Thumb2VFP.cc
@@ -16,9 +16,8 @@
 
 namespace art {
 
-STATIC bool genArithOpFloat(CompilationUnit* cUnit, MIR* mir,
-                            RegLocation rlDest, RegLocation rlSrc1,
-                            RegLocation rlSrc2)
+bool genArithOpFloat(CompilationUnit* cUnit, MIR* mir, RegLocation rlDest,
+                     RegLocation rlSrc1, RegLocation rlSrc2)
 {
     int op = kThumbBkpt;
     RegLocation rlResult;
@@ -62,9 +61,8 @@
     return false;
 }
 
-STATIC bool genArithOpDouble(CompilationUnit* cUnit, MIR* mir,
-                             RegLocation rlDest, RegLocation rlSrc1,
-                             RegLocation rlSrc2)
+bool genArithOpDouble(CompilationUnit* cUnit, MIR* mir, RegLocation rlDest,
+                      RegLocation rlSrc1, RegLocation rlSrc2)
 {
     int op = kThumbBkpt;
     RegLocation rlResult;
@@ -110,7 +108,7 @@
     return false;
 }
 
-STATIC bool genConversion(CompilationUnit* cUnit, MIR* mir)
+bool genConversion(CompilationUnit* cUnit, MIR* mir)
 {
     Opcode opcode = mir->dalvikInsn.opcode;
     int op = kThumbBkpt;
@@ -184,8 +182,8 @@
     return false;
 }
 
-STATIC bool genCmpFP(CompilationUnit* cUnit, MIR* mir, RegLocation rlDest,
-                     RegLocation rlSrc1, RegLocation rlSrc2)
+bool genCmpFP(CompilationUnit* cUnit, MIR* mir, RegLocation rlDest,
+              RegLocation rlSrc1, RegLocation rlSrc2)
 {
     bool isDouble;
     int defaultResult;
diff --git a/src/compiler/codegen/arm/Thumb2/Factory.cc b/src/compiler/codegen/arm/Thumb2/Factory.cc
index 0a43aae..77d6066 100644
--- a/src/compiler/codegen/arm/Thumb2/Factory.cc
+++ b/src/compiler/codegen/arm/Thumb2/Factory.cc
@@ -35,7 +35,7 @@
 static int fpTemps[] = {fr0, fr1, fr2, fr3, fr4, fr5, fr6, fr7,
                         fr8, fr9, fr10, fr11, fr12, fr13, fr14, fr15};
 
-STATIC int encodeImmSingle(int value)
+int encodeImmSingle(int value)
 {
     int res;
     int bitA =    (value & 0x80000000) >> 31;
@@ -57,23 +57,22 @@
     return res;
 }
 
-STATIC ArmLIR* loadFPConstantValue(CompilationUnit* cUnit, int rDest,
-                                   int value)
+LIR* loadFPConstantValue(CompilationUnit* cUnit, int rDest, int value)
 {
     int encodedImm = encodeImmSingle(value);
     DCHECK(SINGLEREG(rDest));
     if (encodedImm >= 0) {
         return newLIR2(cUnit, kThumb2Vmovs_IMM8, rDest, encodedImm);
     }
-    ArmLIR* dataTarget = scanLiteralPool(cUnit->literalList, value, 0);
+    LIR* dataTarget = scanLiteralPool(cUnit->literalList, value, 0);
     if (dataTarget == NULL) {
         dataTarget = addWordData(cUnit, &cUnit->literalList, value);
     }
-    ArmLIR* loadPcRel = (ArmLIR* ) oatNew(cUnit, sizeof(ArmLIR), true,
+    LIR* loadPcRel = (LIR* ) oatNew(cUnit, sizeof(LIR), true,
                                           kAllocLIR);
-    loadPcRel->generic.dalvikOffset = cUnit->currentDalvikOffset;
+    loadPcRel->dalvikOffset = cUnit->currentDalvikOffset;
     loadPcRel->opcode = kThumb2Vldrs;
-    loadPcRel->generic.target = (LIR* ) dataTarget;
+    loadPcRel->target = (LIR* ) dataTarget;
     loadPcRel->operands[0] = rDest;
     loadPcRel->operands[1] = r15pc;
     setupResourceMasks(loadPcRel);
@@ -83,7 +82,7 @@
     return loadPcRel;
 }
 
-STATIC int leadingZeros(u4 val)
+int leadingZeros(u4 val)
 {
     u4 alt;
     int n;
@@ -106,7 +105,7 @@
  * Determine whether value can be encoded as a Thumb2 modified
  * immediate.  If not, return -1.  If so, return i:imm3:a:bcdefgh form.
  */
-STATIC int modifiedImmediate(u4 value)
+int modifiedImmediate(u4 value)
 {
    int zLeading;
    int zTrailing;
@@ -144,10 +143,9 @@
  * 1) rDest is freshly returned from oatAllocTemp or
  * 2) The codegen is under fixed register usage
  */
-STATIC ArmLIR* loadConstantNoClobber(CompilationUnit* cUnit, int rDest,
-                                     int value)
+LIR* loadConstantNoClobber(CompilationUnit* cUnit, int rDest, int value)
 {
-    ArmLIR* res;
+    LIR* res;
     int modImm;
 
     if (FPREG(rDest)) {
@@ -175,15 +173,15 @@
         return res;
     }
     /* No shortcut - go ahead and use literal pool */
-    ArmLIR* dataTarget = scanLiteralPool(cUnit->literalList, value, 0);
+    LIR* dataTarget = scanLiteralPool(cUnit->literalList, value, 0);
     if (dataTarget == NULL) {
         dataTarget = addWordData(cUnit, &cUnit->literalList, value);
     }
-    ArmLIR* loadPcRel = (ArmLIR* ) oatNew(cUnit, sizeof(ArmLIR), true,
+    LIR* loadPcRel = (LIR* ) oatNew(cUnit, sizeof(LIR), true,
                                           kAllocLIR);
     loadPcRel->opcode = kThumb2LdrPcRel12;
-    loadPcRel->generic.target = (LIR* ) dataTarget;
-    loadPcRel->generic.dalvikOffset = cUnit->currentDalvikOffset;
+    loadPcRel->target = (LIR* ) dataTarget;
+    loadPcRel->dalvikOffset = cUnit->currentDalvikOffset;
     loadPcRel->operands[0] = rDest;
     setupResourceMasks(loadPcRel);
     setMemRefType(loadPcRel, true, kLiteral);
@@ -201,20 +199,7 @@
     return res;
 }
 
-/*
- * Load an immediate value into a fixed or temp register.  Target
- * register is clobbered, and marked inUse.
- */
-STATIC ArmLIR* loadConstant(CompilationUnit* cUnit, int rDest, int value)
-{
-    if (oatIsTemp(cUnit, rDest)) {
-        oatClobber(cUnit, rDest);
-        oatMarkInUse(cUnit, rDest);
-    }
-    return loadConstantNoClobber(cUnit, rDest, value);
-}
-
-STATIC ArmLIR* opNone(CompilationUnit* cUnit, OpKind op)
+LIR* opNone(CompilationUnit* cUnit, OpKind op)
 {
     ArmOpcode opcode = kThumbBkpt;
     switch (op) {
@@ -227,12 +212,13 @@
     return newLIR0(cUnit, opcode);
 }
 
-STATIC ArmLIR* opCondBranch(CompilationUnit* cUnit, ArmConditionCode cc)
+LIR* opCondBranch(CompilationUnit* cUnit, ConditionCode cc)
 {
-    return newLIR2(cUnit, kThumb2BCond, 0 /* offset to be patched */, cc);
+    return newLIR2(cUnit, kThumb2BCond, 0 /* offset to be patched */,
+                   oatArmConditionEncoding(cc));
 }
 
-STATIC ArmLIR* opReg(CompilationUnit* cUnit, OpKind op, int rDestSrc)
+LIR* opReg(CompilationUnit* cUnit, OpKind op, int rDestSrc)
 {
     ArmOpcode opcode = kThumbBkpt;
     switch (op) {
@@ -245,8 +231,8 @@
     return newLIR1(cUnit, opcode, rDestSrc);
 }
 
-STATIC ArmLIR* opRegRegShift(CompilationUnit* cUnit, OpKind op, int rDestSrc1,
-                             int rSrc2, int shift)
+LIR* opRegRegShift(CompilationUnit* cUnit, OpKind op, int rDestSrc1,
+                   int rSrc2, int shift)
 {
     bool thumbForm = ((shift == 0) && LOWREG(rDestSrc1) && LOWREG(rSrc2));
     ArmOpcode opcode = kThumbBkpt;
@@ -361,14 +347,13 @@
     }
 }
 
-STATIC ArmLIR* opRegReg(CompilationUnit* cUnit, OpKind op, int rDestSrc1,
-                        int rSrc2)
+LIR* opRegReg(CompilationUnit* cUnit, OpKind op, int rDestSrc1, int rSrc2)
 {
     return opRegRegShift(cUnit, op, rDestSrc1, rSrc2, 0);
 }
 
-STATIC ArmLIR* opRegRegRegShift(CompilationUnit* cUnit, OpKind op,
-                                int rDest, int rSrc1, int rSrc2, int shift)
+LIR* opRegRegRegShift(CompilationUnit* cUnit, OpKind op, int rDest, int rSrc1,
+                      int rSrc2, int shift)
 {
     ArmOpcode opcode = kThumbBkpt;
     bool thumbForm = (shift == 0) && LOWREG(rDest) && LOWREG(rSrc1) &&
@@ -431,16 +416,16 @@
     }
 }
 
-STATIC ArmLIR* opRegRegReg(CompilationUnit* cUnit, OpKind op, int rDest,
-                           int rSrc1, int rSrc2)
+LIR* opRegRegReg(CompilationUnit* cUnit, OpKind op, int rDest, int rSrc1,
+                 int rSrc2)
 {
     return opRegRegRegShift(cUnit, op, rDest, rSrc1, rSrc2, 0);
 }
 
-STATIC ArmLIR* opRegRegImm(CompilationUnit* cUnit, OpKind op, int rDest,
-                           int rSrc1, int value)
+LIR* opRegRegImm(CompilationUnit* cUnit, OpKind op, int rDest, int rSrc1,
+                 int value)
 {
-    ArmLIR* res;
+    LIR* res;
     bool neg = (value < 0);
     int absValue = (neg) ? -value : value;
     ArmOpcode opcode = kThumbBkpt;
@@ -531,7 +516,7 @@
             break;
         case kOpCmp: {
             int modImm = modifiedImmediate(value);
-            ArmLIR* res;
+            LIR* res;
             if (modImm >= 0) {
                 res = newLIR2(cUnit, kThumb2CmpRI8, rSrc1, modImm);
             } else {
@@ -561,8 +546,7 @@
 }
 
 /* Handle Thumb-only variants here - otherwise punt to opRegRegImm */
-STATIC ArmLIR* opRegImm(CompilationUnit* cUnit, OpKind op, int rDestSrc1,
-                        int value)
+LIR* opRegImm(CompilationUnit* cUnit, OpKind op, int rDestSrc1, int value)
 {
     bool neg = (value < 0);
     int absValue = (neg) ? -value : value;
@@ -611,7 +595,7 @@
  * Determine whether value can be encoded as a Thumb2 floating point
  * immediate.  If not, return -1.  If so return encoded 8-bit value.
  */
-STATIC int encodeImmDoubleHigh(int value)
+int encodeImmDoubleHigh(int value)
 {
     int res;
     int bitA =    (value & 0x80000000) >> 31;
@@ -633,7 +617,7 @@
     return res;
 }
 
-STATIC int encodeImmDouble(int valLo, int valHi)
+int encodeImmDouble(int valLo, int valHi)
 {
     int res = -1;
     if (valLo == 0)
@@ -641,27 +625,27 @@
     return res;
 }
 
-STATIC ArmLIR* loadConstantValueWide(CompilationUnit* cUnit, int rDestLo,
-                                     int rDestHi, int valLo, int valHi)
+LIR* loadConstantValueWide(CompilationUnit* cUnit, int rDestLo, int rDestHi,
+                           int valLo, int valHi)
 {
     int encodedImm = encodeImmDouble(valLo, valHi);
-    ArmLIR* res;
+    LIR* res;
     if (FPREG(rDestLo)) {
         if (encodedImm >= 0) {
             res = newLIR2(cUnit, kThumb2Vmovd_IMM8, S2D(rDestLo, rDestHi),
                           encodedImm);
         } else {
-            ArmLIR* dataTarget = scanLiteralPoolWide(cUnit->literalList, valLo,
+            LIR* dataTarget = scanLiteralPoolWide(cUnit->literalList, valLo,
                valHi);
             if (dataTarget == NULL) {
                 dataTarget = addWideData(cUnit, &cUnit->literalList, valLo,
                                          valHi);
             }
-            ArmLIR* loadPcRel = (ArmLIR* ) oatNew(cUnit, sizeof(ArmLIR), true,
+            LIR* loadPcRel = (LIR* ) oatNew(cUnit, sizeof(LIR), true,
                                                   kAllocLIR);
-            loadPcRel->generic.dalvikOffset = cUnit->currentDalvikOffset;
+            loadPcRel->dalvikOffset = cUnit->currentDalvikOffset;
             loadPcRel->opcode = kThumb2Vldrd;
-            loadPcRel->generic.target = (LIR* ) dataTarget;
+            loadPcRel->target = (LIR* ) dataTarget;
             loadPcRel->operands[0] = S2D(rDestLo, rDestHi);
             loadPcRel->operands[1] = r15pc;
             setupResourceMasks(loadPcRel);
@@ -677,15 +661,15 @@
     return res;
 }
 
-STATIC int encodeShift(int code, int amount) {
+int encodeShift(int code, int amount) {
     return ((amount & 0x1f) << 2) | code;
 }
 
-STATIC ArmLIR* loadBaseIndexed(CompilationUnit* cUnit, int rBase,
-                               int rIndex, int rDest, int scale, OpSize size)
+LIR* loadBaseIndexed(CompilationUnit* cUnit, int rBase, int rIndex, int rDest,
+                     int scale, OpSize size)
 {
     bool allLowRegs = LOWREG(rBase) && LOWREG(rIndex) && LOWREG(rDest);
-    ArmLIR* load;
+    LIR* load;
     ArmOpcode opcode = kThumbBkpt;
     bool thumbForm = (allLowRegs && (scale == 0));
     int regPtr;
@@ -745,11 +729,11 @@
     return load;
 }
 
-STATIC ArmLIR* storeBaseIndexed(CompilationUnit* cUnit, int rBase,
-                                int rIndex, int rSrc, int scale, OpSize size)
+LIR* storeBaseIndexed(CompilationUnit* cUnit, int rBase, int rIndex, int rSrc,
+                      int scale, OpSize size)
 {
     bool allLowRegs = LOWREG(rBase) && LOWREG(rIndex) && LOWREG(rSrc);
-    ArmLIR* store;
+    LIR* store;
     ArmOpcode opcode = kThumbBkpt;
     bool thumbForm = (allLowRegs && (scale == 0));
     int regPtr;
@@ -810,12 +794,12 @@
  * on base (which must have an associated sReg and MIR).  If not
  * performing null check, incoming MIR can be null.
  */
-STATIC ArmLIR* loadBaseDispBody(CompilationUnit* cUnit, MIR* mir, int rBase,
-                                int displacement, int rDest, int rDestHi,
-                                OpSize size, int sReg)
+LIR* loadBaseDispBody(CompilationUnit* cUnit, MIR* mir, int rBase,
+                      int displacement, int rDest, int rDestHi, OpSize size,
+                      int sReg)
 {
-    ArmLIR* res;
-    ArmLIR* load;
+    LIR* res;
+    LIR* load;
     ArmOpcode opcode = kThumbBkpt;
     bool shortForm = false;
     bool thumb2Form = (displacement < 4092 && displacement >= 0);
@@ -925,28 +909,25 @@
     return load;
 }
 
-STATIC ArmLIR* loadBaseDisp(CompilationUnit* cUnit, MIR* mir, int rBase,
-                            int displacement, int rDest, OpSize size,
-                            int sReg)
+LIR* loadBaseDisp(CompilationUnit* cUnit, MIR* mir, int rBase,
+                  int displacement, int rDest, OpSize size, int sReg)
 {
     return loadBaseDispBody(cUnit, mir, rBase, displacement, rDest, -1,
                             size, sReg);
 }
 
-STATIC  ArmLIR* loadBaseDispWide(CompilationUnit* cUnit, MIR* mir, int rBase,
-                                 int displacement, int rDestLo, int rDestHi,
-                                 int sReg)
+ LIR* loadBaseDispWide(CompilationUnit* cUnit, MIR* mir, int rBase,
+                       int displacement, int rDestLo, int rDestHi, int sReg)
 {
     return loadBaseDispBody(cUnit, mir, rBase, displacement, rDestLo, rDestHi,
                             kLong, sReg);
 }
 
 
-STATIC ArmLIR* storeBaseDispBody(CompilationUnit* cUnit, int rBase,
-                                 int displacement, int rSrc, int rSrcHi,
-                                 OpSize size)
+LIR* storeBaseDispBody(CompilationUnit* cUnit, int rBase, int displacement,
+                       int rSrc, int rSrcHi, OpSize size)
 {
-    ArmLIR* res, *store;
+    LIR* res, *store;
     ArmOpcode opcode = kThumbBkpt;
     bool shortForm = false;
     bool thumb2Form = (displacement < 4092 && displacement >= 0);
@@ -1035,63 +1016,32 @@
     return res;
 }
 
-STATIC ArmLIR* storeBaseDisp(CompilationUnit* cUnit, int rBase,
-                             int displacement, int rSrc, OpSize size)
+LIR* storeBaseDisp(CompilationUnit* cUnit, int rBase, int displacement,
+                   int rSrc, OpSize size)
 {
     return storeBaseDispBody(cUnit, rBase, displacement, rSrc, -1, size);
 }
 
-STATIC ArmLIR* storeBaseDispWide(CompilationUnit* cUnit, int rBase,
-                                 int displacement, int rSrcLo, int rSrcHi)
+LIR* storeBaseDispWide(CompilationUnit* cUnit, int rBase, int displacement,
+                       int rSrcLo, int rSrcHi)
 {
     return storeBaseDispBody(cUnit, rBase, displacement, rSrcLo, rSrcHi, kLong);
 }
 
-STATIC void storePair(CompilationUnit* cUnit, int base, int lowReg, int highReg)
+void storePair(CompilationUnit* cUnit, int base, int lowReg, int highReg)
 {
     storeBaseDispWide(cUnit, base, 0, lowReg, highReg);
 }
 
-STATIC void loadPair(CompilationUnit* cUnit, int base, int lowReg, int highReg)
+void loadPair(CompilationUnit* cUnit, int base, int lowReg, int highReg)
 {
     loadBaseDispWide(cUnit, NULL, base, 0, lowReg, highReg, INVALID_SREG);
 }
 
-/*
- * Generate a register comparison to an immediate and branch.  Caller
- * is responsible for setting branch target field.
- */
-STATIC ArmLIR* genCmpImmBranch(CompilationUnit* cUnit,
-                              ArmConditionCode cond, int reg,
-                              int checkValue)
+LIR* fpRegCopy(CompilationUnit* cUnit, int rDest, int rSrc)
 {
-    ArmLIR* branch;
-    int modImm;
-    if ((LOWREG(reg)) && (checkValue == 0) &&
-       ((cond == kArmCondEq) || (cond == kArmCondNe))) {
-        branch = newLIR2(cUnit,
-                         (cond == kArmCondEq) ? kThumb2Cbz : kThumb2Cbnz,
-                         reg, 0);
-    } else {
-        modImm = modifiedImmediate(checkValue);
-        if (LOWREG(reg) && ((checkValue & 0xff) == checkValue)) {
-            newLIR2(cUnit, kThumbCmpRI8, reg, checkValue);
-        } else if (modImm >= 0) {
-            newLIR2(cUnit, kThumb2CmpRI8, reg, modImm);
-        } else {
-            int tReg = oatAllocTemp(cUnit);
-            loadConstant(cUnit, tReg, checkValue);
-            opRegReg(cUnit, kOpCmp, reg, tReg);
-        }
-        branch = newLIR2(cUnit, kThumbBCond, 0, cond);
-    }
-    return branch;
-}
-
-STATIC ArmLIR* fpRegCopy(CompilationUnit* cUnit, int rDest, int rSrc)
-{
-    ArmLIR* res = (ArmLIR* ) oatNew(cUnit, sizeof(ArmLIR), true, kAllocLIR);
-    res->generic.dalvikOffset = cUnit->currentDalvikOffset;
+    LIR* res = (LIR* ) oatNew(cUnit, sizeof(LIR), true, kAllocLIR);
+    res->dalvikOffset = cUnit->currentDalvikOffset;
     res->operands[0] = rDest;
     res->operands[1] = rSrc;
     if (rDest == rSrc) {
@@ -1115,67 +1065,6 @@
     return res;
 }
 
-STATIC ArmLIR* genRegCopyNoInsert(CompilationUnit* cUnit, int rDest, int rSrc)
-{
-    ArmLIR* res;
-    ArmOpcode opcode;
-    if (FPREG(rDest) || FPREG(rSrc))
-        return fpRegCopy(cUnit, rDest, rSrc);
-    res = (ArmLIR* ) oatNew(cUnit, sizeof(ArmLIR), true, kAllocLIR);
-    res->generic.dalvikOffset = cUnit->currentDalvikOffset;
-    if (LOWREG(rDest) && LOWREG(rSrc))
-        opcode = kThumbMovRR;
-    else if (!LOWREG(rDest) && !LOWREG(rSrc))
-         opcode = kThumbMovRR_H2H;
-    else if (LOWREG(rDest))
-         opcode = kThumbMovRR_H2L;
-    else
-         opcode = kThumbMovRR_L2H;
 
-    res->operands[0] = rDest;
-    res->operands[1] = rSrc;
-    res->opcode = opcode;
-    setupResourceMasks(res);
-    if (rDest == rSrc) {
-        res->flags.isNop = true;
-    }
-    return res;
-}
-
-STATIC ArmLIR* genRegCopy(CompilationUnit* cUnit, int rDest, int rSrc)
-{
-    ArmLIR* res = genRegCopyNoInsert(cUnit, rDest, rSrc);
-    oatAppendLIR(cUnit, (LIR*)res);
-    return res;
-}
-
-STATIC void genRegCopyWide(CompilationUnit* cUnit, int destLo, int destHi,
-                           int srcLo, int srcHi)
-{
-    bool destFP = FPREG(destLo) && FPREG(destHi);
-    bool srcFP = FPREG(srcLo) && FPREG(srcHi);
-    DCHECK_EQ(FPREG(srcLo), FPREG(srcHi));
-    DCHECK_EQ(FPREG(destLo), FPREG(destHi));
-    if (destFP) {
-        if (srcFP) {
-            genRegCopy(cUnit, S2D(destLo, destHi), S2D(srcLo, srcHi));
-        } else {
-            newLIR3(cUnit, kThumb2Fmdrr, S2D(destLo, destHi), srcLo, srcHi);
-        }
-    } else {
-        if (srcFP) {
-            newLIR3(cUnit, kThumb2Fmrrd, destLo, destHi, S2D(srcLo, srcHi));
-        } else {
-            // Handle overlap
-            if (srcHi == destLo) {
-                genRegCopy(cUnit, destHi, srcHi);
-                genRegCopy(cUnit, destLo, srcLo);
-            } else {
-                genRegCopy(cUnit, destLo, srcLo);
-                genRegCopy(cUnit, destHi, srcHi);
-            }
-        }
-    }
-}
 
 }  // namespace art
diff --git a/src/compiler/codegen/arm/Thumb2/Gen.cc b/src/compiler/codegen/arm/Thumb2/Gen.cc
index e20e19b..1dfb90d 100644
--- a/src/compiler/codegen/arm/Thumb2/Gen.cc
+++ b/src/compiler/codegen/arm/Thumb2/Gen.cc
@@ -26,51 +26,6 @@
 
 namespace art {
 
-/*
- * Return most flexible allowed register class based on size.
- * Bug: 2813841
- * Must use a core register for data types narrower than word (due
- * to possible unaligned load/store.
- */
-STATIC inline RegisterClass oatRegClassBySize(OpSize size)
-{
-    return (size == kUnsignedHalf ||
-            size == kSignedHalf ||
-            size == kUnsignedByte ||
-            size == kSignedByte ) ? kCoreReg : kAnyReg;
-}
-
-STATIC RegLocation getRetLoc(CompilationUnit* cUnit);
-
-void warnIfUnresolved(CompilationUnit* cUnit, int fieldIdx, Field* field) {
-  if (field == NULL) {
-    const DexFile::FieldId& field_id = cUnit->dex_file->GetFieldId(fieldIdx);
-    std::string class_name(cUnit->dex_file->GetFieldDeclaringClassDescriptor(field_id));
-    std::string field_name(cUnit->dex_file->GetFieldName(field_id));
-    LOG(INFO) << "Field " << PrettyDescriptor(class_name) << "." << field_name
-              << " unresolved at compile time";
-  } else {
-    // We also use the slow path for wide volatile fields.
-  }
-}
-
-/*
- * Construct an s4 from two consecutive half-words of switch data.
- * This needs to check endianness because the DEX optimizer only swaps
- * half-words in instruction stream.
- *
- * "switchData" must be 32-bit aligned.
- */
-#if __BYTE_ORDER == __LITTLE_ENDIAN
-STATIC inline s4 s4FromSwitchData(const void* switchData) {
-    return *(s4*) switchData;
-}
-#else
-STATIC inline s4 s4FromSwitchData(const void* switchData) {
-    u2* data = switchData;
-    return data[0] | (((s4) data[1]) << 16);
-}
-#endif
 
 /*
  * Generate a Thumb2 IT instruction, which can nullify up to
@@ -82,8 +37,7 @@
  * met, and an "E" means the instruction is executed if the condition
  * is not met.
  */
-STATIC ArmLIR* genIT(CompilationUnit* cUnit, ArmConditionCode code,
-                     const char* guide)
+LIR* genIT(CompilationUnit* cUnit, ArmConditionCode code, const char* guide)
 {
     int mask;
     int condBit = code & 1;
@@ -112,118 +66,6 @@
 }
 
 /*
- * Insert a kArmPseudoCaseLabel at the beginning of the Dalvik
- * offset vaddr.  This label will be used to fix up the case
- * branch table during the assembly phase.  Be sure to set
- * all resource flags on this to prevent code motion across
- * target boundaries.  KeyVal is just there for debugging.
- */
-STATIC ArmLIR* insertCaseLabel(CompilationUnit* cUnit, int vaddr, int keyVal)
-{
-    std::map<unsigned int, LIR*>::iterator it;
-    it = cUnit->boundaryMap.find(vaddr);
-    if (it == cUnit->boundaryMap.end()) {
-        LOG(FATAL) << "Error: didn't find vaddr 0x" << std::hex << vaddr;
-    }
-    ArmLIR* newLabel = (ArmLIR*)oatNew(cUnit, sizeof(ArmLIR), true, kAllocLIR);
-    newLabel->generic.dalvikOffset = vaddr;
-    newLabel->opcode = kArmPseudoCaseLabel;
-    newLabel->operands[0] = keyVal;
-    oatInsertLIRAfter(it->second, (LIR*)newLabel);
-    return newLabel;
-}
-
-STATIC void markPackedCaseLabels(CompilationUnit* cUnit, SwitchTable *tabRec)
-{
-    const u2* table = tabRec->table;
-    int baseVaddr = tabRec->vaddr;
-    int *targets = (int*)&table[4];
-    int entries = table[1];
-    int lowKey = s4FromSwitchData(&table[2]);
-    for (int i = 0; i < entries; i++) {
-        tabRec->targets[i] = insertCaseLabel(cUnit, baseVaddr + targets[i],
-                                             i + lowKey);
-    }
-}
-
-STATIC void markSparseCaseLabels(CompilationUnit* cUnit, SwitchTable *tabRec)
-{
-    const u2* table = tabRec->table;
-    int baseVaddr = tabRec->vaddr;
-    int entries = table[1];
-    int* keys = (int*)&table[2];
-    int* targets = &keys[entries];
-    for (int i = 0; i < entries; i++) {
-        tabRec->targets[i] = insertCaseLabel(cUnit, baseVaddr + targets[i],
-                                             keys[i]);
-    }
-}
-
-void oatProcessSwitchTables(CompilationUnit* cUnit)
-{
-    GrowableListIterator iterator;
-    oatGrowableListIteratorInit(&cUnit->switchTables, &iterator);
-    while (true) {
-        SwitchTable *tabRec = (SwitchTable *) oatGrowableListIteratorNext(
-             &iterator);
-        if (tabRec == NULL) break;
-        if (tabRec->table[0] == kPackedSwitchSignature)
-            markPackedCaseLabels(cUnit, tabRec);
-        else if (tabRec->table[0] == kSparseSwitchSignature)
-            markSparseCaseLabels(cUnit, tabRec);
-        else {
-            LOG(FATAL) << "Invalid switch table";
-        }
-    }
-}
-
-STATIC void dumpSparseSwitchTable(const u2* table)
-    /*
-     * Sparse switch data format:
-     *  ushort ident = 0x0200   magic value
-     *  ushort size             number of entries in the table; > 0
-     *  int keys[size]          keys, sorted low-to-high; 32-bit aligned
-     *  int targets[size]       branch targets, relative to switch opcode
-     *
-     * Total size is (2+size*4) 16-bit code units.
-     */
-{
-    u2 ident = table[0];
-    int entries = table[1];
-    int* keys = (int*)&table[2];
-    int* targets = &keys[entries];
-    LOG(INFO) <<  "Sparse switch table - ident:0x" << std::hex << ident <<
-       ", entries: " << std::dec << entries;
-    for (int i = 0; i < entries; i++) {
-        LOG(INFO) << "    Key[" << keys[i] << "] -> 0x" << std::hex <<
-        targets[i];
-    }
-}
-
-STATIC void dumpPackedSwitchTable(const u2* table)
-    /*
-     * Packed switch data format:
-     *  ushort ident = 0x0100   magic value
-     *  ushort size             number of entries in the table
-     *  int first_key           first (and lowest) switch case value
-     *  int targets[size]       branch targets, relative to switch opcode
-     *
-     * Total size is (4+size*2) 16-bit code units.
-     */
-{
-    u2 ident = table[0];
-    int* targets = (int*)&table[4];
-    int entries = table[1];
-    int lowKey = s4FromSwitchData(&table[2]);
-    LOG(INFO) << "Packed switch table - ident:0x" << std::hex << ident <<
-        ", entries: " << std::dec << entries << ", lowKey: " << lowKey;
-    for (int i = 0; i < entries; i++) {
-        LOG(INFO) << "    Key[" << (i + lowKey) << "] -> 0x" << std::hex <<
-            targets[i];
-    }
-}
-
-/*
  * The sparse table in the literal pool is an array of <key,displacement>
  * pairs.  For each set, we'll load them as a pair using ldmia.
  * This means that the register number of the temp we use for the key
@@ -242,8 +84,7 @@
  *   add   rPC, rDisp   ; This is the branch from which we compute displacement
  *   cbnz  rIdx, lp
  */
-STATIC void genSparseSwitch(CompilationUnit* cUnit, MIR* mir,
-                            RegLocation rlSrc)
+void genSparseSwitch(CompilationUnit* cUnit, MIR* mir, RegLocation rlSrc)
 {
     const u2* table = cUnit->insns + mir->offset + mir->dalvikInsn.vB;
     if (cUnit->printMe) {
@@ -255,8 +96,8 @@
     tabRec->table = table;
     tabRec->vaddr = mir->offset;
     int size = table[1];
-    tabRec->targets = (ArmLIR* *)oatNew(cUnit, size * sizeof(ArmLIR*), true,
-                                        kAllocLIR);
+    tabRec->targets = (LIR* *)oatNew(cUnit, size * sizeof(LIR*), true,
+                                     kAllocLIR);
     oatInsertGrowableList(cUnit, &cUnit->switchTables, (intptr_t)tabRec);
 
     // Get the switch value
@@ -277,24 +118,23 @@
     int rIdx = oatAllocTemp(cUnit);
     loadConstant(cUnit, rIdx, size);
     // Establish loop branch target
-    ArmLIR* target = newLIR0(cUnit, kArmPseudoTargetLabel);
+    LIR* target = newLIR0(cUnit, kPseudoTargetLabel);
     target->defMask = ENCODE_ALL;
     // Load next key/disp
     newLIR2(cUnit, kThumb2LdmiaWB, rBase, (1 << rKey) | (1 << rDisp));
     opRegReg(cUnit, kOpCmp, rKey, rlSrc.lowReg);
     // Go if match. NOTE: No instruction set switch here - must stay Thumb2
     genIT(cUnit, kArmCondEq, "");
-    ArmLIR* switchBranch = newLIR1(cUnit, kThumb2AddPCR, rDisp);
+    LIR* switchBranch = newLIR1(cUnit, kThumb2AddPCR, rDisp);
     tabRec->bxInst = switchBranch;
     // Needs to use setflags encoding here
     newLIR3(cUnit, kThumb2SubsRRI12, rIdx, rIdx, 1);
-    ArmLIR* branch = opCondBranch(cUnit, kArmCondNe);
-    branch->generic.target = (LIR*)target;
+    LIR* branch = opCondBranch(cUnit, kCondNe);
+    branch->target = (LIR*)target;
 }
 
 
-STATIC void genPackedSwitch(CompilationUnit* cUnit, MIR* mir,
-                            RegLocation rlSrc)
+void genPackedSwitch(CompilationUnit* cUnit, MIR* mir, RegLocation rlSrc)
 {
     const u2* table = cUnit->insns + mir->offset + mir->dalvikInsn.vB;
     if (cUnit->printMe) {
@@ -306,7 +146,7 @@
     tabRec->table = table;
     tabRec->vaddr = mir->offset;
     int size = table[1];
-    tabRec->targets = (ArmLIR* *)oatNew(cUnit, size * sizeof(ArmLIR*), true,
+    tabRec->targets = (LIR* *)oatNew(cUnit, size * sizeof(LIR*), true,
                                         kAllocLIR);
     oatInsertGrowableList(cUnit, &cUnit->switchTables, (intptr_t)tabRec);
 
@@ -326,20 +166,20 @@
     }
     // Bounds check - if < 0 or >= size continue following switch
     opRegImm(cUnit, kOpCmp, keyReg, size-1);
-    ArmLIR* branchOver = opCondBranch(cUnit, kArmCondHi);
+    LIR* branchOver = opCondBranch(cUnit, kCondHi);
 
     // Load the displacement from the switch table
     int dispReg = oatAllocTemp(cUnit);
     loadBaseIndexed(cUnit, tableBase, keyReg, dispReg, 2, kWord);
 
     // ..and go! NOTE: No instruction set switch here - must stay Thumb2
-    ArmLIR* switchBranch = newLIR1(cUnit, kThumb2AddPCR, dispReg);
+    LIR* switchBranch = newLIR1(cUnit, kThumb2AddPCR, dispReg);
     tabRec->bxInst = switchBranch;
 
     /* branchOver target here */
-    ArmLIR* target = newLIR0(cUnit, kArmPseudoTargetLabel);
+    LIR* target = newLIR0(cUnit, kPseudoTargetLabel);
     target->defMask = ENCODE_ALL;
-    branchOver->generic.target = (LIR*)target;
+    branchOver->target = (LIR*)target;
 }
 
 /*
@@ -352,8 +192,7 @@
  *
  * Total size is 4+(width * size + 1)/2 16-bit code units.
  */
-STATIC void genFillArrayData(CompilationUnit* cUnit, MIR* mir,
-                              RegLocation rlSrc)
+void genFillArrayData(CompilationUnit* cUnit, MIR* mir, RegLocation rlSrc)
 {
     const u2* table = cUnit->insns + mir->offset + mir->dalvikInsn.vB;
     // Add the table to the list - we'll process it later
@@ -377,413 +216,7 @@
     callRuntimeHelper(cUnit, rLR);
 }
 
-STATIC void genIGet(CompilationUnit* cUnit, MIR* mir, OpSize size,
-                    RegLocation rlDest, RegLocation rlObj,
-                    bool isLongOrDouble, bool isObject)
-{
-    int fieldOffset;
-    bool isVolatile;
-    uint32_t fieldIdx = mir->dalvikInsn.vC;
-
-    OatCompilationUnit mUnit(cUnit->class_loader, cUnit->class_linker,
-                             *cUnit->dex_file, *cUnit->dex_cache, cUnit->code_item,
-                             cUnit->method_idx, cUnit->access_flags);
-
-    bool fastPath =
-        cUnit->compiler->ComputeInstanceFieldInfo(fieldIdx, &mUnit,
-                                                  fieldOffset, isVolatile, false);
-    if (fastPath && !SLOW_FIELD_PATH) {
-        RegLocation rlResult;
-        RegisterClass regClass = oatRegClassBySize(size);
-        DCHECK_GE(fieldOffset, 0);
-        rlObj = loadValue(cUnit, rlObj, kCoreReg);
-        if (isLongOrDouble) {
-            DCHECK(rlDest.wide);
-            genNullCheck(cUnit, rlObj.sRegLow, rlObj.lowReg, mir);/* null obj? */
-            int regPtr = oatAllocTemp(cUnit);
-            opRegRegImm(cUnit, kOpAdd, regPtr, rlObj.lowReg, fieldOffset);
-            rlResult = oatEvalLoc(cUnit, rlDest, regClass, true);
-            loadPair(cUnit, regPtr, rlResult.lowReg, rlResult.highReg);
-            if (isVolatile) {
-                oatGenMemBarrier(cUnit, kSY);
-            }
-            oatFreeTemp(cUnit, regPtr);
-            storeValueWide(cUnit, rlDest, rlResult);
-        } else {
-            rlResult = oatEvalLoc(cUnit, rlDest, regClass, true);
-            genNullCheck(cUnit, rlObj.sRegLow, rlObj.lowReg, mir);/* null object? */
-            loadBaseDisp(cUnit, mir, rlObj.lowReg, fieldOffset, rlResult.lowReg,
-                         kWord, rlObj.sRegLow);
-            if (isVolatile) {
-                oatGenMemBarrier(cUnit, kSY);
-            }
-            storeValue(cUnit, rlDest, rlResult);
-        }
-    } else {
-        int getterOffset = isLongOrDouble ? OFFSETOF_MEMBER(Thread, pGet64Instance) :
-                           (isObject ? OFFSETOF_MEMBER(Thread, pGetObjInstance)
-                                     : OFFSETOF_MEMBER(Thread, pGet32Instance));
-        loadWordDisp(cUnit, rSELF, getterOffset, rLR);
-        loadValueDirect(cUnit, rlObj, r1);
-        loadConstant(cUnit, r0, fieldIdx);
-        callRuntimeHelper(cUnit, rLR);
-        if (isLongOrDouble) {
-            RegLocation rlResult = oatGetReturnWide(cUnit);
-            storeValueWide(cUnit, rlDest, rlResult);
-        } else {
-            RegLocation rlResult = oatGetReturn(cUnit);
-            storeValue(cUnit, rlDest, rlResult);
-        }
-    }
-}
-
-STATIC void genIPut(CompilationUnit* cUnit, MIR* mir, OpSize size,
-                    RegLocation rlSrc, RegLocation rlObj,
-                    bool isLongOrDouble, bool isObject)
-{
-    int fieldOffset;
-    bool isVolatile;
-    uint32_t fieldIdx = mir->dalvikInsn.vC;
-
-    OatCompilationUnit mUnit(cUnit->class_loader, cUnit->class_linker,
-                             *cUnit->dex_file, *cUnit->dex_cache, cUnit->code_item,
-                             cUnit->method_idx, cUnit->access_flags);
-
-    bool fastPath =
-        cUnit->compiler->ComputeInstanceFieldInfo(fieldIdx, &mUnit,
-                                                  fieldOffset, isVolatile, true);
-    if (fastPath && !SLOW_FIELD_PATH) {
-        RegisterClass regClass = oatRegClassBySize(size);
-        DCHECK_GE(fieldOffset, 0);
-        rlObj = loadValue(cUnit, rlObj, kCoreReg);
-        if (isLongOrDouble) {
-            int regPtr;
-            rlSrc = loadValueWide(cUnit, rlSrc, kAnyReg);
-            genNullCheck(cUnit, rlObj.sRegLow, rlObj.lowReg, mir);/* null obj? */
-            regPtr = oatAllocTemp(cUnit);
-            opRegRegImm(cUnit, kOpAdd, regPtr, rlObj.lowReg, fieldOffset);
-            if (isVolatile) {
-                oatGenMemBarrier(cUnit, kST);
-            }
-            storePair(cUnit, regPtr, rlSrc.lowReg, rlSrc.highReg);
-            if (isVolatile) {
-                oatGenMemBarrier(cUnit, kSY);
-            }
-            oatFreeTemp(cUnit, regPtr);
-        } else {
-            rlSrc = loadValue(cUnit, rlSrc, regClass);
-            genNullCheck(cUnit, rlObj.sRegLow, rlObj.lowReg, mir);/* null obj? */
-            if (isVolatile) {
-                oatGenMemBarrier(cUnit, kST);
-            }
-            storeBaseDisp(cUnit, rlObj.lowReg, fieldOffset, rlSrc.lowReg, kWord);
-            if (isVolatile) {
-                oatGenMemBarrier(cUnit, kSY);
-            }
-        }
-    } else {
-        int setterOffset = isLongOrDouble ? OFFSETOF_MEMBER(Thread, pSet64Instance) :
-                           (isObject ? OFFSETOF_MEMBER(Thread, pSetObjInstance)
-                                     : OFFSETOF_MEMBER(Thread, pSet32Instance));
-        loadWordDisp(cUnit, rSELF, setterOffset, rLR);
-        loadValueDirect(cUnit, rlObj, r1);
-        if (isLongOrDouble) {
-            loadValueDirectWide(cUnit, rlSrc, r2, r3);
-        } else {
-            loadValueDirect(cUnit, rlSrc, r2);
-        }
-        loadConstant(cUnit, r0, fieldIdx);
-        callRuntimeHelper(cUnit, rLR);
-    }
-}
-
-STATIC void genConstClass(CompilationUnit* cUnit, MIR* mir,
-                          RegLocation rlDest, RegLocation rlSrc)
-{
-    uint32_t type_idx = mir->dalvikInsn.vB;
-    int mReg = loadCurrMethod(cUnit);
-    int resReg = oatAllocTemp(cUnit);
-    RegLocation rlResult = oatEvalLoc(cUnit, rlDest, kCoreReg, true);
-    if (!cUnit->compiler->CanAccessTypeWithoutChecks(cUnit->method_idx,
-                                                     cUnit->dex_cache,
-                                                     *cUnit->dex_file,
-                                                     type_idx)) {
-        // Call out to helper which resolves type and verifies access.
-        // Resolved type returned in r0.
-        loadWordDisp(cUnit, rSELF,
-                     OFFSETOF_MEMBER(Thread, pInitializeTypeAndVerifyAccessFromCode),
-                     rLR);
-        genRegCopy(cUnit, r1, mReg);
-        loadConstant(cUnit, r0, type_idx);
-        callRuntimeHelper(cUnit, rLR);
-        RegLocation rlResult = oatGetReturn(cUnit);
-        storeValue(cUnit, rlDest, rlResult);
-    } else {
-        // We're don't need access checks, load type from dex cache
-        int32_t dex_cache_offset = Method::DexCacheResolvedTypesOffset().Int32Value();
-        loadWordDisp(cUnit, mReg, dex_cache_offset, resReg);
-        int32_t offset_of_type = Array::DataOffset(sizeof(Class*)).Int32Value() +
-                                 (sizeof(Class*) * type_idx);
-        loadWordDisp(cUnit, resReg, offset_of_type, rlResult.lowReg);
-        if (!cUnit->compiler->CanAssumeTypeIsPresentInDexCache(cUnit->dex_cache,
-                                                               type_idx) ||
-            SLOW_TYPE_PATH) {
-            // Slow path, at runtime test if the type is null and if so initialize
-            oatFlushAllRegs(cUnit);
-            ArmLIR* branch1 = genCmpImmBranch(cUnit, kArmCondEq, rlResult.lowReg, 0);
-            // Resolved, store and hop over following code
-            storeValue(cUnit, rlDest, rlResult);
-            ArmLIR* branch2 = genUnconditionalBranch(cUnit,0);
-            // TUNING: move slow path to end & remove unconditional branch
-            ArmLIR* target1 = newLIR0(cUnit, kArmPseudoTargetLabel);
-            target1->defMask = ENCODE_ALL;
-            // Call out to helper, which will return resolved type in r0
-            loadWordDisp(cUnit, rSELF, OFFSETOF_MEMBER(Thread, pInitializeTypeFromCode), rLR);
-            genRegCopy(cUnit, r1, mReg);
-            loadConstant(cUnit, r0, type_idx);
-            callRuntimeHelper(cUnit, rLR);
-            RegLocation rlResult = oatGetReturn(cUnit);
-            storeValue(cUnit, rlDest, rlResult);
-            // Rejoin code paths
-            ArmLIR* target2 = newLIR0(cUnit, kArmPseudoTargetLabel);
-            target2->defMask = ENCODE_ALL;
-            branch1->generic.target = (LIR*)target1;
-            branch2->generic.target = (LIR*)target2;
-        } else {
-            // Fast path, we're done - just store result
-            storeValue(cUnit, rlDest, rlResult);
-        }
-    }
-}
-
-/*
- * Generate callout to updateDebugger. Note: genIT will automatically
- * create a scheduling barrier, which we need to prevent code motion that
- * might confuse the debugger.  Note: Return registers r0/r1 are
- * handled specially during code generation following function calls.
- * Typically, temp registers are not live between opcodes, but we keep
- * r0/r1 live following invokes, where they are consumed by the immediately
- * following op_move_result_xxx.  Thus, we must preserve and restore r0/r1
- * when making a call to update the debugger.  This is handled by the stub.
- */
-STATIC void genDebuggerUpdate(CompilationUnit* cUnit, int32_t offset)
-{
-    // Following DCHECK verifies that dPC is in range of single load immediate
-    DCHECK((offset == DEBUGGER_METHOD_ENTRY) ||
-           (offset == DEBUGGER_METHOD_EXIT) || ((offset & 0xffff) == offset));
-    oatClobberCalleeSave(cUnit);
-    opRegImm(cUnit, kOpCmp, rSUSPEND, 0);
-    genIT(cUnit, kArmCondNe, "T");
-    loadConstant(cUnit, r2, offset);     // arg2 <- Entry code
-    opReg(cUnit, kOpBlx, rSUSPEND);
-    oatFreeTemp(cUnit, r2);
-}
-
-STATIC void genConstString(CompilationUnit* cUnit, MIR* mir,
-                           RegLocation rlDest, RegLocation rlSrc)
-{
-    /* NOTE: Most strings should be available at compile time */
-    uint32_t string_idx = mir->dalvikInsn.vB;
-    int32_t offset_of_string = Array::DataOffset(sizeof(String*)).Int32Value() +
-                               (sizeof(String*) * string_idx);
-    if (!cUnit->compiler->CanAssumeStringIsPresentInDexCache(cUnit->dex_cache, string_idx) ||
-        SLOW_STRING_PATH) {
-        // slow path, resolve string if not in dex cache
-        oatFlushAllRegs(cUnit);
-        oatLockCallTemps(cUnit); // Using explicit registers
-        loadCurrMethodDirect(cUnit, r2);
-        loadWordDisp(cUnit, r2, Method::DexCacheStringsOffset().Int32Value(), r0);
-        // Might call out to helper, which will return resolved string in r0
-        loadWordDisp(cUnit, rSELF, OFFSETOF_MEMBER(Thread, pResolveStringFromCode), rLR);
-        loadWordDisp(cUnit, r0, offset_of_string, r0);
-        loadConstant(cUnit, r1, string_idx);
-        opRegImm(cUnit, kOpCmp, r0, 0);  // Is resolved?
-        genBarrier(cUnit);
-        // For testing, always force through helper
-        if (!EXERCISE_SLOWEST_STRING_PATH) {
-            genIT(cUnit, kArmCondEq, "T");
-        }
-        genRegCopy(cUnit, r0, r2);       // .eq
-        opReg(cUnit, kOpBlx, rLR);       // .eq, helper(Method*, string_idx)
-        genBarrier(cUnit);
-        storeValue(cUnit, rlDest, getRetLoc(cUnit));
-    } else {
-        int mReg = loadCurrMethod(cUnit);
-        int resReg = oatAllocTemp(cUnit);
-        RegLocation rlResult = oatEvalLoc(cUnit, rlDest, kCoreReg, true);
-        loadWordDisp(cUnit, mReg, Method::DexCacheStringsOffset().Int32Value(), resReg);
-        loadWordDisp(cUnit, resReg, offset_of_string, rlResult.lowReg);
-        storeValue(cUnit, rlDest, rlResult);
-    }
-}
-
-/*
- * Let helper function take care of everything.  Will
- * call Class::NewInstanceFromCode(type_idx, method);
- */
-STATIC void genNewInstance(CompilationUnit* cUnit, MIR* mir,
-                           RegLocation rlDest)
-{
-    oatFlushAllRegs(cUnit);    /* Everything to home location */
-    uint32_t type_idx = mir->dalvikInsn.vB;
-    // alloc will always check for resolution, do we also need to verify access because the
-    // verifier was unable to?
-    if (cUnit->compiler->CanAccessInstantiableTypeWithoutChecks(cUnit->method_idx,
-                                                                cUnit->dex_cache,
-                                                                *cUnit->dex_file,
-                                                                type_idx)) {
-        loadWordDisp(cUnit, rSELF, OFFSETOF_MEMBER(Thread, pAllocObjectFromCode), rLR);
-    } else {
-        loadWordDisp(cUnit, rSELF,
-                     OFFSETOF_MEMBER(Thread, pAllocObjectFromCodeWithAccessCheck), rLR);
-    }
-    loadCurrMethodDirect(cUnit, r1);    // arg1 <= Method*
-    loadConstant(cUnit, r0, type_idx);  // arg0 <- type_idx
-    callRuntimeHelper(cUnit, rLR);
-    RegLocation rlResult = oatGetReturn(cUnit);
-    storeValue(cUnit, rlDest, rlResult);
-}
-
-void genThrow(CompilationUnit* cUnit, MIR* mir, RegLocation rlSrc)
-{
-    oatFlushAllRegs(cUnit);
-    loadWordDisp(cUnit, rSELF, OFFSETOF_MEMBER(Thread, pDeliverException), rLR);
-    loadValueDirectFixed(cUnit, rlSrc, r0);  // Get exception object
-    callRuntimeHelper(cUnit, rLR);  // art_deliver_exception(exception);
-}
-
-STATIC void genInstanceof(CompilationUnit* cUnit, MIR* mir, RegLocation rlDest,
-                          RegLocation rlSrc)
-{
-    oatFlushAllRegs(cUnit);
-    // May generate a call - use explicit registers
-    oatLockCallTemps(cUnit);
-    uint32_t type_idx = mir->dalvikInsn.vC;
-    loadCurrMethodDirect(cUnit, r1);  // r1 <= current Method*
-    int classReg = r2;  // r2 will hold the Class*
-    if (!cUnit->compiler->CanAccessTypeWithoutChecks(cUnit->method_idx,
-                                                     cUnit->dex_cache,
-                                                     *cUnit->dex_file,
-                                                     type_idx)) {
-        // Check we have access to type_idx and if not throw IllegalAccessError,
-        // returns Class* in r0
-        loadWordDisp(cUnit, rSELF,
-                     OFFSETOF_MEMBER(Thread, pInitializeTypeAndVerifyAccessFromCode),
-                     rLR);
-        loadConstant(cUnit, r0, type_idx);
-        callRuntimeHelper(cUnit, rLR);  // InitializeTypeAndVerifyAccess(idx, method)
-        genRegCopy(cUnit, classReg, r0);  // Align usage with fast path
-        loadValueDirectFixed(cUnit, rlSrc, r0);  // r0 <= ref
-    } else {
-        // Load dex cache entry into classReg (r2)
-        loadValueDirectFixed(cUnit, rlSrc, r0);  // r0 <= ref
-        loadWordDisp(cUnit, r1, Method::DexCacheResolvedTypesOffset().Int32Value(), classReg);
-        int32_t offset_of_type = Array::DataOffset(sizeof(Class*)).Int32Value() +
-                                 (sizeof(Class*) * type_idx);
-        loadWordDisp(cUnit, classReg, offset_of_type, classReg);
-        if (!cUnit->compiler->CanAssumeTypeIsPresentInDexCache(cUnit->dex_cache, type_idx)) {
-            // Need to test presence of type in dex cache at runtime
-            ArmLIR* hopBranch = genCmpImmBranch(cUnit, kArmCondNe, classReg, 0);
-            // Not resolved
-            // Call out to helper, which will return resolved type in r0
-            loadWordDisp(cUnit, rSELF, OFFSETOF_MEMBER(Thread, pInitializeTypeFromCode), rLR);
-            loadConstant(cUnit, r0, type_idx);
-            callRuntimeHelper(cUnit, rLR);  // InitializeTypeFromCode(idx, method)
-            genRegCopy(cUnit, r2, r0); // Align usage with fast path
-            loadValueDirectFixed(cUnit, rlSrc, r0);  /* reload Ref */
-            // Rejoin code paths
-            ArmLIR* hopTarget = newLIR0(cUnit, kArmPseudoTargetLabel);
-            hopTarget->defMask = ENCODE_ALL;
-            hopBranch->generic.target = (LIR*)hopTarget;
-        }
-    }
-    /* r0 is ref, r2 is class.  If ref==null, use directly as bool result */
-    ArmLIR* branch1 = genCmpImmBranch(cUnit, kArmCondEq, r0, 0);
-    /* load object->clazz */
-    DCHECK_EQ(Object::ClassOffset().Int32Value(), 0);
-    loadWordDisp(cUnit, r0,  Object::ClassOffset().Int32Value(), r1);
-    /* r0 is ref, r1 is ref->clazz, r2 is class */
-    loadWordDisp(cUnit, rSELF, OFFSETOF_MEMBER(Thread, pInstanceofNonTrivialFromCode), rLR);
-    opRegReg(cUnit, kOpCmp, r1, r2);  // Same?
-    genBarrier(cUnit);
-    genIT(cUnit, kArmCondEq, "EE");   // if-convert the test
-    loadConstant(cUnit, r0, 1);       // .eq case - load true
-    genRegCopy(cUnit, r0, r2);        // .ne case - arg0 <= class
-    opReg(cUnit, kOpBlx, rLR);        // .ne case: helper(class, ref->class)
-    genBarrier(cUnit);
-    oatClobberCalleeSave(cUnit);
-    /* branch target here */
-    ArmLIR* target = newLIR0(cUnit, kArmPseudoTargetLabel);
-    target->defMask = ENCODE_ALL;
-    RegLocation rlResult = oatGetReturn(cUnit);
-    storeValue(cUnit, rlDest, rlResult);
-    branch1->generic.target = (LIR*)target;
-}
-
-STATIC void genCheckCast(CompilationUnit* cUnit, MIR* mir, RegLocation rlSrc)
-{
-    oatFlushAllRegs(cUnit);
-    // May generate a call - use explicit registers
-    oatLockCallTemps(cUnit);
-    uint32_t type_idx = mir->dalvikInsn.vB;
-    loadCurrMethodDirect(cUnit, r1);  // r1 <= current Method*
-    int classReg = r2;  // r2 will hold the Class*
-    if (!cUnit->compiler->CanAccessTypeWithoutChecks(cUnit->method_idx,
-                                                     cUnit->dex_cache,
-                                                     *cUnit->dex_file,
-                                                     type_idx)) {
-        // Check we have access to type_idx and if not throw IllegalAccessError,
-        // returns Class* in r0
-        loadWordDisp(cUnit, rSELF,
-                     OFFSETOF_MEMBER(Thread, pInitializeTypeAndVerifyAccessFromCode),
-                     rLR);
-        loadConstant(cUnit, r0, type_idx);
-        callRuntimeHelper(cUnit, rLR);  // InitializeTypeAndVerifyAccess(idx, method)
-        genRegCopy(cUnit, classReg, r0);  // Align usage with fast path
-    } else {
-        // Load dex cache entry into classReg (r2)
-        loadWordDisp(cUnit, r1, Method::DexCacheResolvedTypesOffset().Int32Value(), classReg);
-        int32_t offset_of_type = Array::DataOffset(sizeof(Class*)).Int32Value() +
-                                 (sizeof(Class*) * type_idx);
-        loadWordDisp(cUnit, classReg, offset_of_type, classReg);
-        if (!cUnit->compiler->CanAssumeTypeIsPresentInDexCache(cUnit->dex_cache, type_idx)) {
-            // Need to test presence of type in dex cache at runtime
-            ArmLIR* hopBranch = genCmpImmBranch(cUnit, kArmCondNe, classReg, 0);
-            // Not resolved
-            // Call out to helper, which will return resolved type in r0
-            loadWordDisp(cUnit, rSELF, OFFSETOF_MEMBER(Thread, pInitializeTypeFromCode), rLR);
-            loadConstant(cUnit, r0, type_idx);
-            callRuntimeHelper(cUnit, rLR);  // InitializeTypeFromCode(idx, method)
-            genRegCopy(cUnit, classReg, r0); // Align usage with fast path
-            // Rejoin code paths
-            ArmLIR* hopTarget = newLIR0(cUnit, kArmPseudoTargetLabel);
-            hopTarget->defMask = ENCODE_ALL;
-            hopBranch->generic.target = (LIR*)hopTarget;
-        }
-    }
-    // At this point, classReg (r2) has class
-    loadValueDirectFixed(cUnit, rlSrc, r0);  // r0 <= ref
-    /* Null is OK - continue */
-    ArmLIR* branch1 = genCmpImmBranch(cUnit, kArmCondEq, r0, 0);
-    /* load object->clazz */
-    DCHECK_EQ(Object::ClassOffset().Int32Value(), 0);
-    loadWordDisp(cUnit, r0,  Object::ClassOffset().Int32Value(), r1);
-    /* r1 now contains object->clazz */
-    loadWordDisp(cUnit, rSELF, OFFSETOF_MEMBER(Thread, pCheckCastFromCode), rLR);
-    opRegReg(cUnit, kOpCmp, r1, classReg);
-    ArmLIR* branch2 = opCondBranch(cUnit, kArmCondEq); /* If equal, trivial yes */
-    genRegCopy(cUnit, r0, r1);
-    genRegCopy(cUnit, r1, r2);
-    callRuntimeHelper(cUnit, rLR);
-    /* branch target here */
-    ArmLIR* target = newLIR0(cUnit, kArmPseudoTargetLabel);
-    target->defMask = ENCODE_ALL;
-    branch1->generic.target = (LIR*)target;
-    branch2->generic.target = (LIR*)target;
-}
-
-STATIC void genNegFloat(CompilationUnit* cUnit, RegLocation rlDest,
-                        RegLocation rlSrc)
+void genNegFloat(CompilationUnit* cUnit, RegLocation rlDest, RegLocation rlSrc)
 {
     RegLocation rlResult;
     rlSrc = loadValue(cUnit, rlSrc, kFPReg);
@@ -792,8 +225,7 @@
     storeValue(cUnit, rlDest, rlResult);
 }
 
-STATIC void genNegDouble(CompilationUnit* cUnit, RegLocation rlDest,
-                         RegLocation rlSrc)
+void genNegDouble(CompilationUnit* cUnit, RegLocation rlDest, RegLocation rlSrc)
 {
     RegLocation rlResult;
     rlSrc = loadValueWide(cUnit, rlSrc, kFPReg);
@@ -803,119 +235,6 @@
     storeValueWide(cUnit, rlDest, rlResult);
 }
 
-STATIC void freeRegLocTemps(CompilationUnit* cUnit, RegLocation rlKeep,
-                        RegLocation rlFree)
-{
-    if ((rlFree.lowReg != rlKeep.lowReg) && (rlFree.lowReg != rlKeep.highReg) &&
-        (rlFree.highReg != rlKeep.lowReg) && (rlFree.highReg != rlKeep.highReg)) {
-        // No overlap, free both
-        oatFreeTemp(cUnit, rlFree.lowReg);
-        oatFreeTemp(cUnit, rlFree.highReg);
-    }
-}
-
-STATIC void genLong3Addr(CompilationUnit* cUnit, MIR* mir, OpKind firstOp,
-                         OpKind secondOp, RegLocation rlDest,
-                         RegLocation rlSrc1, RegLocation rlSrc2)
-{
-    /*
-     * NOTE:  This is the one place in the code in which we might have
-     * as many as six live temporary registers.  There are 5 in the normal
-     * set for Arm.  Until we have spill capabilities, temporarily add
-     * lr to the temp set.  It is safe to do this locally, but note that
-     * lr is used explicitly elsewhere in the code generator and cannot
-     * normally be used as a general temp register.
-     */
-    RegLocation rlResult;
-    oatMarkTemp(cUnit, rLR);   // Add lr to the temp pool
-    oatFreeTemp(cUnit, rLR);   // and make it available
-    rlSrc1 = loadValueWide(cUnit, rlSrc1, kCoreReg);
-    rlSrc2 = loadValueWide(cUnit, rlSrc2, kCoreReg);
-    rlResult = oatEvalLoc(cUnit, rlDest, kCoreReg, true);
-    // The longs may overlap - use intermediate temp if so
-    if (rlResult.lowReg == rlSrc1.highReg) {
-        int tReg = oatAllocTemp(cUnit);
-        genRegCopy(cUnit, tReg, rlSrc1.highReg);
-        opRegRegReg(cUnit, firstOp, rlResult.lowReg, rlSrc1.lowReg,
-                    rlSrc2.lowReg);
-        opRegRegReg(cUnit, secondOp, rlResult.highReg, tReg,
-                    rlSrc2.highReg);
-        oatFreeTemp(cUnit, tReg);
-    } else {
-        opRegRegReg(cUnit, firstOp, rlResult.lowReg, rlSrc1.lowReg,
-                    rlSrc2.lowReg);
-        opRegRegReg(cUnit, secondOp, rlResult.highReg, rlSrc1.highReg,
-                    rlSrc2.highReg);
-    }
-    /*
-     * NOTE: If rlDest refers to a frame variable in a large frame, the
-     * following storeValueWide might need to allocate a temp register.
-     * To further work around the lack of a spill capability, explicitly
-     * free any temps from rlSrc1 & rlSrc2 that aren't still live in rlResult.
-     * Remove when spill is functional.
-     */
-    freeRegLocTemps(cUnit, rlResult, rlSrc1);
-    freeRegLocTemps(cUnit, rlResult, rlSrc2);
-    storeValueWide(cUnit, rlDest, rlResult);
-    oatClobber(cUnit, rLR);
-    oatUnmarkTemp(cUnit, rLR);  // Remove lr from the temp pool
-}
-
-void oatInitializeRegAlloc(CompilationUnit* cUnit)
-{
-    int numRegs = sizeof(coreRegs)/sizeof(*coreRegs);
-    int numReserved = sizeof(reservedRegs)/sizeof(*reservedRegs);
-    int numTemps = sizeof(coreTemps)/sizeof(*coreTemps);
-    int numFPRegs = sizeof(fpRegs)/sizeof(*fpRegs);
-    int numFPTemps = sizeof(fpTemps)/sizeof(*fpTemps);
-    RegisterPool *pool = (RegisterPool *)oatNew(cUnit, sizeof(*pool), true,
-                                                kAllocRegAlloc);
-    cUnit->regPool = pool;
-    pool->numCoreRegs = numRegs;
-    pool->coreRegs = (RegisterInfo *)
-            oatNew(cUnit, numRegs * sizeof(*cUnit->regPool->coreRegs),
-                   true, kAllocRegAlloc);
-    pool->numFPRegs = numFPRegs;
-    pool->FPRegs = (RegisterInfo *)
-            oatNew(cUnit, numFPRegs * sizeof(*cUnit->regPool->FPRegs), true,
-                   kAllocRegAlloc);
-    oatInitPool(pool->coreRegs, coreRegs, pool->numCoreRegs);
-    oatInitPool(pool->FPRegs, fpRegs, pool->numFPRegs);
-    // Keep special registers from being allocated
-    for (int i = 0; i < numReserved; i++) {
-        if (NO_SUSPEND && !cUnit->genDebugger &&
-            (reservedRegs[i] == rSUSPEND)) {
-            //To measure cost of suspend check
-            continue;
-        }
-        oatMarkInUse(cUnit, reservedRegs[i]);
-    }
-    // Mark temp regs - all others not in use can be used for promotion
-    for (int i = 0; i < numTemps; i++) {
-        oatMarkTemp(cUnit, coreTemps[i]);
-    }
-    for (int i = 0; i < numFPTemps; i++) {
-        oatMarkTemp(cUnit, fpTemps[i]);
-    }
-    // Construct the alias map.
-    cUnit->phiAliasMap = (int*)oatNew(cUnit, cUnit->numSSARegs *
-                                      sizeof(cUnit->phiAliasMap[0]), false,
-                                      kAllocDFInfo);
-    for (int i = 0; i < cUnit->numSSARegs; i++) {
-        cUnit->phiAliasMap[i] = i;
-    }
-    for (MIR* phi = cUnit->phiList; phi; phi = phi->meta.phiNext) {
-        int defReg = phi->ssaRep->defs[0];
-        for (int i = 0; i < phi->ssaRep->numUses; i++) {
-           for (int j = 0; j < cUnit->numSSARegs; j++) {
-               if (cUnit->phiAliasMap[j] == phi->ssaRep->uses[i]) {
-                   cUnit->phiAliasMap[j] = defReg;
-               }
-           }
-        }
-    }
-}
-
 /*
  * Handle simple case (thin lock) inline.  If it's complicated, bail
  * out to the heavyweight lock/unlock routines.  We'll use dedicated
@@ -942,13 +261,12 @@
  * preserved.
  *
  */
-STATIC void genMonitorEnter(CompilationUnit* cUnit, MIR* mir,
-                            RegLocation rlSrc)
+void genMonitorEnter(CompilationUnit* cUnit, MIR* mir, RegLocation rlSrc)
 {
-    ArmLIR* target;
-    ArmLIR* hopTarget;
-    ArmLIR* branch;
-    ArmLIR* hopBranch;
+    LIR* target;
+    LIR* hopTarget;
+    LIR* branch;
+    LIR* hopBranch;
 
     oatFlushAllRegs(cUnit);
     DCHECK_EQ(LW_SHAPE_THIN, 0);
@@ -969,9 +287,9 @@
     oatGenMemBarrier(cUnit, kSY);
     branch = newLIR2(cUnit, kThumb2Cbz, r1, 0);
 
-    hopTarget = newLIR0(cUnit, kArmPseudoTargetLabel);
+    hopTarget = newLIR0(cUnit, kPseudoTargetLabel);
     hopTarget->defMask = ENCODE_ALL;
-    hopBranch->generic.target = (LIR*)hopTarget;
+    hopBranch->target = (LIR*)hopTarget;
 
     // Go expensive route - artLockObjectFromCode(self, obj);
     loadWordDisp(cUnit, rSELF, OFFSETOF_MEMBER(Thread, pLockObjectFromCode),
@@ -979,9 +297,9 @@
     callRuntimeHelper(cUnit, rLR);
 
     // Resume here
-    target = newLIR0(cUnit, kArmPseudoTargetLabel);
+    target = newLIR0(cUnit, kPseudoTargetLabel);
     target->defMask = ENCODE_ALL;
-    branch->generic.target = (LIR*)target;
+    branch->target = (LIR*)target;
 }
 
 /*
@@ -990,13 +308,12 @@
  * a zero recursion count, it's safe to punch it back to the
  * initial, unlock thin state with a store word.
  */
-STATIC void genMonitorExit(CompilationUnit* cUnit, MIR* mir,
-                           RegLocation rlSrc)
+void genMonitorExit(CompilationUnit* cUnit, MIR* mir, RegLocation rlSrc)
 {
-    ArmLIR* target;
-    ArmLIR* branch;
-    ArmLIR* hopTarget;
-    ArmLIR* hopBranch;
+    LIR* target;
+    LIR* branch;
+    LIR* hopTarget;
+    LIR* hopBranch;
 
     DCHECK_EQ(LW_SHAPE_THIN, 0);
     oatFlushAllRegs(cUnit);
@@ -1011,14 +328,14 @@
     opRegImm(cUnit, kOpLsl, r2, LW_LOCK_OWNER_SHIFT);
     newLIR3(cUnit, kThumb2Bfc, r1, LW_HASH_STATE_SHIFT, LW_LOCK_OWNER_SHIFT - 1);
     opRegReg(cUnit, kOpSub, r1, r2);
-    hopBranch = opCondBranch(cUnit, kArmCondNe);
+    hopBranch = opCondBranch(cUnit, kCondNe);
     oatGenMemBarrier(cUnit, kSY);
     storeWordDisp(cUnit, r0, Object::MonitorOffset().Int32Value(), r3);
     branch = opNone(cUnit, kOpUncondBr);
 
-    hopTarget = newLIR0(cUnit, kArmPseudoTargetLabel);
+    hopTarget = newLIR0(cUnit, kPseudoTargetLabel);
     hopTarget->defMask = ENCODE_ALL;
-    hopBranch->generic.target = (LIR*)hopTarget;
+    hopBranch->target = (LIR*)hopTarget;
 
     // Go expensive route - UnlockObjectFromCode(obj);
     loadWordDisp(cUnit, rSELF, OFFSETOF_MEMBER(Thread, pUnlockObjectFromCode),
@@ -1026,9 +343,9 @@
     callRuntimeHelper(cUnit, rLR);
 
     // Resume here
-    target = newLIR0(cUnit, kArmPseudoTargetLabel);
+    target = newLIR0(cUnit, kPseudoTargetLabel);
     target->defMask = ENCODE_ALL;
-    branch->generic.target = (LIR*)target;
+    branch->target = (LIR*)target;
 }
 
 /*
@@ -1046,32 +363,31 @@
  *     neg   rX
  * done:
  */
-STATIC void genCmpLong(CompilationUnit* cUnit, MIR* mir,
-                       RegLocation rlDest, RegLocation rlSrc1,
-                       RegLocation rlSrc2)
+void genCmpLong(CompilationUnit* cUnit, MIR* mir, RegLocation rlDest,
+                RegLocation rlSrc1, RegLocation rlSrc2)
 {
-    ArmLIR* target1;
-    ArmLIR* target2;
+    LIR* target1;
+    LIR* target2;
     rlSrc1 = loadValueWide(cUnit, rlSrc1, kCoreReg);
     rlSrc2 = loadValueWide(cUnit, rlSrc2, kCoreReg);
     int tReg = oatAllocTemp(cUnit);
     loadConstant(cUnit, tReg, -1);
     opRegReg(cUnit, kOpCmp, rlSrc1.highReg, rlSrc2.highReg);
-    ArmLIR* branch1 = opCondBranch(cUnit, kArmCondLt);
-    ArmLIR* branch2 = opCondBranch(cUnit, kArmCondGt);
+    LIR* branch1 = opCondBranch(cUnit, kCondLt);
+    LIR* branch2 = opCondBranch(cUnit, kCondGt);
     opRegRegReg(cUnit, kOpSub, tReg, rlSrc1.lowReg, rlSrc2.lowReg);
-    ArmLIR* branch3 = opCondBranch(cUnit, kArmCondEq);
+    LIR* branch3 = opCondBranch(cUnit, kCondEq);
 
     genIT(cUnit, kArmCondHi, "E");
     newLIR2(cUnit, kThumb2MovImmShift, tReg, modifiedImmediate(-1));
     loadConstant(cUnit, tReg, 1);
     genBarrier(cUnit);
 
-    target2 = newLIR0(cUnit, kArmPseudoTargetLabel);
+    target2 = newLIR0(cUnit, kPseudoTargetLabel);
     target2->defMask = -1;
     opRegReg(cUnit, kOpNeg, tReg, tReg);
 
-    target1 = newLIR0(cUnit, kArmPseudoTargetLabel);
+    target1 = newLIR0(cUnit, kPseudoTargetLabel);
     target1->defMask = -1;
 
     RegLocation rlTemp = LOC_C_RETURN; // Just using as template, will change
@@ -1079,982 +395,103 @@
     storeValue(cUnit, rlDest, rlTemp);
     oatFreeTemp(cUnit, tReg);
 
-    branch1->generic.target = (LIR*)target1;
-    branch2->generic.target = (LIR*)target2;
-    branch3->generic.target = branch1->generic.target;
-}
-
-STATIC void genMultiplyByTwoBitMultiplier(CompilationUnit* cUnit,
-        RegLocation rlSrc, RegLocation rlResult, int lit,
-        int firstBit, int secondBit)
-{
-    opRegRegRegShift(cUnit, kOpAdd, rlResult.lowReg, rlSrc.lowReg, rlSrc.lowReg,
-                     encodeShift(kArmLsl, secondBit - firstBit));
-    if (firstBit != 0) {
-        opRegRegImm(cUnit, kOpLsl, rlResult.lowReg, rlResult.lowReg, firstBit);
-    }
-}
-
-STATIC bool genConversionCall(CompilationUnit* cUnit, MIR* mir, int funcOffset,
-                                     int srcSize, int tgtSize)
-{
-    /*
-     * Don't optimize the register usage since it calls out to support
-     * functions
-     */
-    RegLocation rlSrc;
-    RegLocation rlDest;
-    oatFlushAllRegs(cUnit);   /* Send everything to home location */
-    loadWordDisp(cUnit, rSELF, funcOffset, rLR);
-    if (srcSize == 1) {
-        rlSrc = oatGetSrc(cUnit, mir, 0);
-        loadValueDirectFixed(cUnit, rlSrc, r0);
-    } else {
-        rlSrc = oatGetSrcWide(cUnit, mir, 0, 1);
-        loadValueDirectWideFixed(cUnit, rlSrc, r0, r1);
-    }
-    callRuntimeHelper(cUnit, rLR);
-    if (tgtSize == 1) {
-        RegLocation rlResult;
-        rlDest = oatGetDest(cUnit, mir, 0);
-        rlResult = oatGetReturn(cUnit);
-        storeValue(cUnit, rlDest, rlResult);
-    } else {
-        RegLocation rlResult;
-        rlDest = oatGetDestWide(cUnit, mir, 0, 1);
-        rlResult = oatGetReturnWide(cUnit);
-        storeValueWide(cUnit, rlDest, rlResult);
-    }
-    return false;
-}
-
-STATIC bool genArithOpFloatPortable(CompilationUnit* cUnit, MIR* mir,
-                                    RegLocation rlDest, RegLocation rlSrc1,
-                                    RegLocation rlSrc2)
-{
-    RegLocation rlResult;
-    int funcOffset;
-
-    switch (mir->dalvikInsn.opcode) {
-        case OP_ADD_FLOAT_2ADDR:
-        case OP_ADD_FLOAT:
-            funcOffset = OFFSETOF_MEMBER(Thread, pFadd);
-            break;
-        case OP_SUB_FLOAT_2ADDR:
-        case OP_SUB_FLOAT:
-            funcOffset = OFFSETOF_MEMBER(Thread, pFsub);
-            break;
-        case OP_DIV_FLOAT_2ADDR:
-        case OP_DIV_FLOAT:
-            funcOffset = OFFSETOF_MEMBER(Thread, pFdiv);
-            break;
-        case OP_MUL_FLOAT_2ADDR:
-        case OP_MUL_FLOAT:
-            funcOffset = OFFSETOF_MEMBER(Thread, pFmul);
-            break;
-        case OP_REM_FLOAT_2ADDR:
-        case OP_REM_FLOAT:
-            funcOffset = OFFSETOF_MEMBER(Thread, pFmodf);
-            break;
-        case OP_NEG_FLOAT: {
-            genNegFloat(cUnit, rlDest, rlSrc1);
-            return false;
-        }
-        default:
-            return true;
-    }
-    oatFlushAllRegs(cUnit);   /* Send everything to home location */
-    loadWordDisp(cUnit, rSELF, funcOffset, rLR);
-    loadValueDirectFixed(cUnit, rlSrc1, r0);
-    loadValueDirectFixed(cUnit, rlSrc2, r1);
-    callRuntimeHelper(cUnit, rLR);
-    rlResult = oatGetReturn(cUnit);
-    storeValue(cUnit, rlDest, rlResult);
-    return false;
-}
-
-STATIC bool genArithOpDoublePortable(CompilationUnit* cUnit, MIR* mir,
-                                     RegLocation rlDest, RegLocation rlSrc1,
-                                     RegLocation rlSrc2)
-{
-    RegLocation rlResult;
-    int funcOffset;
-
-    switch (mir->dalvikInsn.opcode) {
-        case OP_ADD_DOUBLE_2ADDR:
-        case OP_ADD_DOUBLE:
-            funcOffset = OFFSETOF_MEMBER(Thread, pDadd);
-            break;
-        case OP_SUB_DOUBLE_2ADDR:
-        case OP_SUB_DOUBLE:
-            funcOffset = OFFSETOF_MEMBER(Thread, pDsub);
-            break;
-        case OP_DIV_DOUBLE_2ADDR:
-        case OP_DIV_DOUBLE:
-            funcOffset = OFFSETOF_MEMBER(Thread, pDdiv);
-            break;
-        case OP_MUL_DOUBLE_2ADDR:
-        case OP_MUL_DOUBLE:
-            funcOffset = OFFSETOF_MEMBER(Thread, pDmul);
-            break;
-        case OP_REM_DOUBLE_2ADDR:
-        case OP_REM_DOUBLE:
-            funcOffset = OFFSETOF_MEMBER(Thread, pFmod);
-            break;
-        case OP_NEG_DOUBLE: {
-            genNegDouble(cUnit, rlDest, rlSrc1);
-            return false;
-        }
-        default:
-            return true;
-    }
-    oatFlushAllRegs(cUnit);   /* Send everything to home location */
-    loadWordDisp(cUnit, rSELF, funcOffset, rLR);
-    loadValueDirectWideFixed(cUnit, rlSrc1, r0, r1);
-    loadValueDirectWideFixed(cUnit, rlSrc2, r2, r3);
-    callRuntimeHelper(cUnit, rLR);
-    rlResult = oatGetReturnWide(cUnit);
-    storeValueWide(cUnit, rlDest, rlResult);
-    return false;
-}
-
-STATIC bool genConversionPortable(CompilationUnit* cUnit, MIR* mir)
-{
-    Opcode opcode = mir->dalvikInsn.opcode;
-
-    switch (opcode) {
-        case OP_INT_TO_FLOAT:
-            return genConversionCall(cUnit, mir, OFFSETOF_MEMBER(Thread, pI2f),
-                                     1, 1);
-        case OP_FLOAT_TO_INT:
-            return genConversionCall(cUnit, mir, OFFSETOF_MEMBER(Thread, pF2iz),
-                                     1, 1);
-        case OP_DOUBLE_TO_FLOAT:
-            return genConversionCall(cUnit, mir, OFFSETOF_MEMBER(Thread, pD2f),
-                                     2, 1);
-        case OP_FLOAT_TO_DOUBLE:
-            return genConversionCall(cUnit, mir, OFFSETOF_MEMBER(Thread, pF2d),
-                                     1, 2);
-        case OP_INT_TO_DOUBLE:
-            return genConversionCall(cUnit, mir, OFFSETOF_MEMBER(Thread, pI2d),
-                                     1, 2);
-        case OP_DOUBLE_TO_INT:
-            return genConversionCall(cUnit, mir, OFFSETOF_MEMBER(Thread, pD2iz),
-                                     2, 1);
-        case OP_FLOAT_TO_LONG:
-            return genConversionCall(cUnit, mir, OFFSETOF_MEMBER(Thread,
-                                     pF2l), 1, 2);
-        case OP_LONG_TO_FLOAT:
-            return genConversionCall(cUnit, mir, OFFSETOF_MEMBER(Thread, pL2f),
-                                     2, 1);
-        case OP_DOUBLE_TO_LONG:
-            return genConversionCall(cUnit, mir, OFFSETOF_MEMBER(Thread,
-                                     pD2l), 2, 2);
-        case OP_LONG_TO_DOUBLE:
-            return genConversionCall(cUnit, mir, OFFSETOF_MEMBER(Thread, pL2d),
-                                     2, 2);
-        default:
-            return true;
-    }
-    return false;
+    branch1->target = (LIR*)target1;
+    branch2->target = (LIR*)target2;
+    branch3->target = branch1->target;
 }
 
 /*
- * Generate array store
- *
+ * Generate a register comparison to an immediate and branch.  Caller
+ * is responsible for setting branch target field.
  */
-STATIC void genArrayObjPut(CompilationUnit* cUnit, MIR* mir,
-                           RegLocation rlArray, RegLocation rlIndex,
-                           RegLocation rlSrc, int scale)
+LIR* genCmpImmBranch(CompilationUnit* cUnit, ConditionCode cond, int reg,
+                        int checkValue)
 {
-    RegisterClass regClass = oatRegClassBySize(kWord);
-    int lenOffset = Array::LengthOffset().Int32Value();
-    int dataOffset = Array::DataOffset(sizeof(Object*)).Int32Value();
-
-    oatFlushAllRegs(cUnit);
-    /* Make sure it's a legal object Put. Use direct regs at first */
-    loadValueDirectFixed(cUnit, rlArray, r1);
-    loadValueDirectFixed(cUnit, rlSrc, r0);
-
-    /* null array object? */
-    genNullCheck(cUnit, rlArray.sRegLow, r1, mir);
-    loadWordDisp(cUnit, rSELF,
-                 OFFSETOF_MEMBER(Thread, pCanPutArrayElementFromCode), rLR);
-    /* Get the array's clazz */
-    loadWordDisp(cUnit, r1, Object::ClassOffset().Int32Value(), r1);
-    callRuntimeHelper(cUnit, rLR);
-    oatFreeTemp(cUnit, r0);
-    oatFreeTemp(cUnit, r1);
-
-    // Now, redo loadValues in case they didn't survive the call
-
-    int regPtr;
-    rlArray = loadValue(cUnit, rlArray, kCoreReg);
-    rlIndex = loadValue(cUnit, rlIndex, kCoreReg);
-
-    if (oatIsTemp(cUnit, rlArray.lowReg)) {
-        oatClobber(cUnit, rlArray.lowReg);
-        regPtr = rlArray.lowReg;
+    LIR* branch;
+    int modImm;
+    ArmConditionCode armCond = oatArmConditionEncoding(cond);
+    if ((LOWREG(reg)) && (checkValue == 0) &&
+       ((armCond == kArmCondEq) || (armCond == kArmCondNe))) {
+        branch = newLIR2(cUnit,
+                         (armCond == kArmCondEq) ? kThumb2Cbz : kThumb2Cbnz,
+                         reg, 0);
     } else {
-        regPtr = oatAllocTemp(cUnit);
-        genRegCopy(cUnit, regPtr, rlArray.lowReg);
-    }
-
-    if (!(mir->optimizationFlags & MIR_IGNORE_RANGE_CHECK)) {
-        int regLen = oatAllocTemp(cUnit);
-        //NOTE: max live temps(4) here.
-        /* Get len */
-        loadWordDisp(cUnit, rlArray.lowReg, lenOffset, regLen);
-        /* regPtr -> array data */
-        opRegImm(cUnit, kOpAdd, regPtr, dataOffset);
-        genRegRegCheck(cUnit, kArmCondCs, rlIndex.lowReg, regLen, mir,
-                       kArmThrowArrayBounds);
-        oatFreeTemp(cUnit, regLen);
-    } else {
-        /* regPtr -> array data */
-        opRegImm(cUnit, kOpAdd, regPtr, dataOffset);
-    }
-    /* at this point, regPtr points to array, 2 live temps */
-    rlSrc = loadValue(cUnit, rlSrc, regClass);
-    storeBaseIndexed(cUnit, regPtr, rlIndex.lowReg, rlSrc.lowReg,
-                     scale, kWord);
-}
-
-/*
- * Generate array load
- */
-STATIC void genArrayGet(CompilationUnit* cUnit, MIR* mir, OpSize size,
-                        RegLocation rlArray, RegLocation rlIndex,
-                        RegLocation rlDest, int scale)
-{
-    RegisterClass regClass = oatRegClassBySize(size);
-    int lenOffset = Array::LengthOffset().Int32Value();
-    int dataOffset;
-    RegLocation rlResult;
-    rlArray = loadValue(cUnit, rlArray, kCoreReg);
-    rlIndex = loadValue(cUnit, rlIndex, kCoreReg);
-    int regPtr;
-
-    if (size == kLong || size == kDouble) {
-      dataOffset = Array::DataOffset(sizeof(int64_t)).Int32Value();
-    } else {
-      dataOffset = Array::DataOffset(sizeof(int32_t)).Int32Value();
-    }
-
-    /* null object? */
-    genNullCheck(cUnit, rlArray.sRegLow, rlArray.lowReg, mir);
-
-    regPtr = oatAllocTemp(cUnit);
-
-    if (!(mir->optimizationFlags & MIR_IGNORE_RANGE_CHECK)) {
-        int regLen = oatAllocTemp(cUnit);
-        /* Get len */
-        loadWordDisp(cUnit, rlArray.lowReg, lenOffset, regLen);
-        /* regPtr -> array data */
-        opRegRegImm(cUnit, kOpAdd, regPtr, rlArray.lowReg, dataOffset);
-        genRegRegCheck(cUnit, kArmCondCs, rlIndex.lowReg, regLen, mir,
-                       kArmThrowArrayBounds);
-        oatFreeTemp(cUnit, regLen);
-    } else {
-        /* regPtr -> array data */
-        opRegRegImm(cUnit, kOpAdd, regPtr, rlArray.lowReg, dataOffset);
-    }
-    oatFreeTemp(cUnit, rlArray.lowReg);
-    if ((size == kLong) || (size == kDouble)) {
-        if (scale) {
-            int rNewIndex = oatAllocTemp(cUnit);
-            opRegRegImm(cUnit, kOpLsl, rNewIndex, rlIndex.lowReg, scale);
-            opRegReg(cUnit, kOpAdd, regPtr, rNewIndex);
-            oatFreeTemp(cUnit, rNewIndex);
+        modImm = modifiedImmediate(checkValue);
+        if (LOWREG(reg) && ((checkValue & 0xff) == checkValue)) {
+            newLIR2(cUnit, kThumbCmpRI8, reg, checkValue);
+        } else if (modImm >= 0) {
+            newLIR2(cUnit, kThumb2CmpRI8, reg, modImm);
         } else {
-            opRegReg(cUnit, kOpAdd, regPtr, rlIndex.lowReg);
-        }
-        oatFreeTemp(cUnit, rlIndex.lowReg);
-        rlResult = oatEvalLoc(cUnit, rlDest, regClass, true);
-
-        loadPair(cUnit, regPtr, rlResult.lowReg, rlResult.highReg);
-
-        oatFreeTemp(cUnit, regPtr);
-        storeValueWide(cUnit, rlDest, rlResult);
-    } else {
-        rlResult = oatEvalLoc(cUnit, rlDest, regClass, true);
-
-        loadBaseIndexed(cUnit, regPtr, rlIndex.lowReg, rlResult.lowReg,
-                        scale, size);
-
-        oatFreeTemp(cUnit, regPtr);
-        storeValue(cUnit, rlDest, rlResult);
-    }
-}
-
-/*
- * Generate array store
- *
- */
-STATIC void genArrayPut(CompilationUnit* cUnit, MIR* mir, OpSize size,
-                        RegLocation rlArray, RegLocation rlIndex,
-                        RegLocation rlSrc, int scale)
-{
-    RegisterClass regClass = oatRegClassBySize(size);
-    int lenOffset = Array::LengthOffset().Int32Value();
-    int dataOffset;
-
-    if (size == kLong || size == kDouble) {
-      dataOffset = Array::DataOffset(sizeof(int64_t)).Int32Value();
-    } else {
-      dataOffset = Array::DataOffset(sizeof(int32_t)).Int32Value();
-    }
-
-    int regPtr;
-    rlArray = loadValue(cUnit, rlArray, kCoreReg);
-    rlIndex = loadValue(cUnit, rlIndex, kCoreReg);
-
-    if (oatIsTemp(cUnit, rlArray.lowReg)) {
-        oatClobber(cUnit, rlArray.lowReg);
-        regPtr = rlArray.lowReg;
-    } else {
-        regPtr = oatAllocTemp(cUnit);
-        genRegCopy(cUnit, regPtr, rlArray.lowReg);
-    }
-
-    /* null object? */
-    genNullCheck(cUnit, rlArray.sRegLow, rlArray.lowReg, mir);
-
-    if (!(mir->optimizationFlags & MIR_IGNORE_RANGE_CHECK)) {
-        int regLen = oatAllocTemp(cUnit);
-        //NOTE: max live temps(4) here.
-        /* Get len */
-        loadWordDisp(cUnit, rlArray.lowReg, lenOffset, regLen);
-        /* regPtr -> array data */
-        opRegImm(cUnit, kOpAdd, regPtr, dataOffset);
-        genRegRegCheck(cUnit, kArmCondCs, rlIndex.lowReg, regLen, mir,
-                       kArmThrowArrayBounds);
-        oatFreeTemp(cUnit, regLen);
-    } else {
-        /* regPtr -> array data */
-        opRegImm(cUnit, kOpAdd, regPtr, dataOffset);
-    }
-    /* at this point, regPtr points to array, 2 live temps */
-    if ((size == kLong) || (size == kDouble)) {
-        //TUNING: specific wide routine that can handle fp regs
-        if (scale) {
-            int rNewIndex = oatAllocTemp(cUnit);
-            opRegRegImm(cUnit, kOpLsl, rNewIndex, rlIndex.lowReg, scale);
-            opRegReg(cUnit, kOpAdd, regPtr, rNewIndex);
-            oatFreeTemp(cUnit, rNewIndex);
-        } else {
-            opRegReg(cUnit, kOpAdd, regPtr, rlIndex.lowReg);
-        }
-        rlSrc = loadValueWide(cUnit, rlSrc, regClass);
-
-        storePair(cUnit, regPtr, rlSrc.lowReg, rlSrc.highReg);
-
-        oatFreeTemp(cUnit, regPtr);
-    } else {
-        rlSrc = loadValue(cUnit, rlSrc, regClass);
-
-        storeBaseIndexed(cUnit, regPtr, rlIndex.lowReg, rlSrc.lowReg,
-                         scale, size);
-    }
-}
-
-STATIC bool genShiftOpLong(CompilationUnit* cUnit, MIR* mir,
-                           RegLocation rlDest, RegLocation rlSrc1,
-                           RegLocation rlShift)
-{
-    int funcOffset;
-
-    switch( mir->dalvikInsn.opcode) {
-        case OP_SHL_LONG:
-        case OP_SHL_LONG_2ADDR:
-            funcOffset = OFFSETOF_MEMBER(Thread, pShlLong);
-            break;
-        case OP_SHR_LONG:
-        case OP_SHR_LONG_2ADDR:
-            funcOffset = OFFSETOF_MEMBER(Thread, pShrLong);
-            break;
-        case OP_USHR_LONG:
-        case OP_USHR_LONG_2ADDR:
-            funcOffset = OFFSETOF_MEMBER(Thread, pUshrLong);
-            break;
-        default:
-            LOG(FATAL) << "Unexpected case";
-            return true;
-    }
-    oatFlushAllRegs(cUnit);   /* Send everything to home location */
-    loadWordDisp(cUnit, rSELF, funcOffset, rLR);
-    loadValueDirectWideFixed(cUnit, rlSrc1, r0, r1);
-    loadValueDirect(cUnit, rlShift, r2);
-    callRuntimeHelper(cUnit, rLR);
-    RegLocation rlResult = oatGetReturnWide(cUnit);
-    storeValueWide(cUnit, rlDest, rlResult);
-    return false;
-}
-
-STATIC bool genArithOpLong(CompilationUnit* cUnit, MIR* mir,
-                           RegLocation rlDest, RegLocation rlSrc1,
-                           RegLocation rlSrc2)
-{
-    RegLocation rlResult;
-    OpKind firstOp = kOpBkpt;
-    OpKind secondOp = kOpBkpt;
-    bool callOut = false;
-    bool checkZero = false;
-    int funcOffset;
-    int retReg = r0;
-
-    switch (mir->dalvikInsn.opcode) {
-        case OP_NOT_LONG:
-            rlSrc2 = loadValueWide(cUnit, rlSrc2, kCoreReg);
-            rlResult = oatEvalLoc(cUnit, rlDest, kCoreReg, true);
-            // Check for destructive overlap
-            if (rlResult.lowReg == rlSrc2.highReg) {
-                int tReg = oatAllocTemp(cUnit);
-                genRegCopy(cUnit, tReg, rlSrc2.highReg);
-                opRegReg(cUnit, kOpMvn, rlResult.lowReg, rlSrc2.lowReg);
-                opRegReg(cUnit, kOpMvn, rlResult.highReg, tReg);
-                oatFreeTemp(cUnit, tReg);
-            } else {
-                opRegReg(cUnit, kOpMvn, rlResult.lowReg, rlSrc2.lowReg);
-                opRegReg(cUnit, kOpMvn, rlResult.highReg, rlSrc2.highReg);
-            }
-            storeValueWide(cUnit, rlDest, rlResult);
-            return false;
-            break;
-        case OP_ADD_LONG:
-        case OP_ADD_LONG_2ADDR:
-            firstOp = kOpAdd;
-            secondOp = kOpAdc;
-            break;
-        case OP_SUB_LONG:
-        case OP_SUB_LONG_2ADDR:
-            firstOp = kOpSub;
-            secondOp = kOpSbc;
-            break;
-        case OP_MUL_LONG:
-        case OP_MUL_LONG_2ADDR:
-            callOut = true;
-            retReg = r0;
-            funcOffset = OFFSETOF_MEMBER(Thread, pLmul);
-            break;
-        case OP_DIV_LONG:
-        case OP_DIV_LONG_2ADDR:
-            callOut = true;
-            checkZero = true;
-            retReg = r0;
-            funcOffset = OFFSETOF_MEMBER(Thread, pLdivmod);
-            break;
-        /* NOTE - result is in r2/r3 instead of r0/r1 */
-        case OP_REM_LONG:
-        case OP_REM_LONG_2ADDR:
-            callOut = true;
-            checkZero = true;
-            funcOffset = OFFSETOF_MEMBER(Thread, pLdivmod);
-            retReg = r2;
-            break;
-        case OP_AND_LONG_2ADDR:
-        case OP_AND_LONG:
-            firstOp = kOpAnd;
-            secondOp = kOpAnd;
-            break;
-        case OP_OR_LONG:
-        case OP_OR_LONG_2ADDR:
-            firstOp = kOpOr;
-            secondOp = kOpOr;
-            break;
-        case OP_XOR_LONG:
-        case OP_XOR_LONG_2ADDR:
-            firstOp = kOpXor;
-            secondOp = kOpXor;
-            break;
-        case OP_NEG_LONG: {
-            rlSrc2 = loadValueWide(cUnit, rlSrc2, kCoreReg);
-            rlResult = oatEvalLoc(cUnit, rlDest, kCoreReg, true);
-            int zReg = oatAllocTemp(cUnit);
-            loadConstantNoClobber(cUnit, zReg, 0);
-            // Check for destructive overlap
-            if (rlResult.lowReg == rlSrc2.highReg) {
-                int tReg = oatAllocTemp(cUnit);
-                opRegRegReg(cUnit, kOpSub, rlResult.lowReg,
-                            zReg, rlSrc2.lowReg);
-                opRegRegReg(cUnit, kOpSbc, rlResult.highReg,
-                            zReg, tReg);
-                oatFreeTemp(cUnit, tReg);
-            } else {
-                opRegRegReg(cUnit, kOpSub, rlResult.lowReg,
-                            zReg, rlSrc2.lowReg);
-                opRegRegReg(cUnit, kOpSbc, rlResult.highReg,
-                            zReg, rlSrc2.highReg);
-            }
-            oatFreeTemp(cUnit, zReg);
-            storeValueWide(cUnit, rlDest, rlResult);
-            return false;
-        }
-        default:
-            LOG(FATAL) << "Invalid long arith op";
-    }
-    if (!callOut) {
-        genLong3Addr(cUnit, mir, firstOp, secondOp, rlDest, rlSrc1, rlSrc2);
-    } else {
-        oatFlushAllRegs(cUnit);   /* Send everything to home location */
-        if (checkZero) {
-            loadValueDirectWideFixed(cUnit, rlSrc2, r2, r3);
-            loadWordDisp(cUnit, rSELF, funcOffset, rLR);
-            loadValueDirectWideFixed(cUnit, rlSrc1, r0, r1);
             int tReg = oatAllocTemp(cUnit);
-            newLIR4(cUnit, kThumb2OrrRRRs, tReg, r2, r3, 0);
-            oatFreeTemp(cUnit, tReg);
-            genCheck(cUnit, kArmCondEq, mir, kArmThrowDivZero);
-        } else {
-            loadWordDisp(cUnit, rSELF, funcOffset, rLR);
-            loadValueDirectWideFixed(cUnit, rlSrc1, r0, r1);
-            loadValueDirectWideFixed(cUnit, rlSrc2, r2, r3);
+            loadConstant(cUnit, tReg, checkValue);
+            opRegReg(cUnit, kOpCmp, reg, tReg);
         }
-        callRuntimeHelper(cUnit, rLR);
-        // Adjust return regs in to handle case of rem returning r2/r3
-        if (retReg == r0)
-            rlResult = oatGetReturnWide(cUnit);
-        else
-            rlResult = oatGetReturnWideAlt(cUnit);
-        storeValueWide(cUnit, rlDest, rlResult);
+        branch = newLIR2(cUnit, kThumbBCond, 0, armCond);
     }
-    return false;
+    return branch;
+}
+LIR* genRegCopyNoInsert(CompilationUnit* cUnit, int rDest, int rSrc)
+{
+    LIR* res;
+    ArmOpcode opcode;
+    if (FPREG(rDest) || FPREG(rSrc))
+        return fpRegCopy(cUnit, rDest, rSrc);
+    res = (LIR* ) oatNew(cUnit, sizeof(LIR), true, kAllocLIR);
+    res->dalvikOffset = cUnit->currentDalvikOffset;
+    if (LOWREG(rDest) && LOWREG(rSrc))
+        opcode = kThumbMovRR;
+    else if (!LOWREG(rDest) && !LOWREG(rSrc))
+         opcode = kThumbMovRR_H2H;
+    else if (LOWREG(rDest))
+         opcode = kThumbMovRR_H2L;
+    else
+         opcode = kThumbMovRR_L2H;
+
+    res->operands[0] = rDest;
+    res->operands[1] = rSrc;
+    res->opcode = opcode;
+    setupResourceMasks(res);
+    if (rDest == rSrc) {
+        res->flags.isNop = true;
+    }
+    return res;
 }
 
-STATIC bool genArithOpInt(CompilationUnit* cUnit, MIR* mir,
-                          RegLocation rlDest, RegLocation rlSrc1,
-                          RegLocation rlSrc2)
+LIR* genRegCopy(CompilationUnit* cUnit, int rDest, int rSrc)
 {
-    OpKind op = kOpBkpt;
-    bool callOut = false;
-    bool checkZero = false;
-    bool unary = false;
-    int retReg = r0;
-    int funcOffset;
-    RegLocation rlResult;
-    bool shiftOp = false;
+    LIR* res = genRegCopyNoInsert(cUnit, rDest, rSrc);
+    oatAppendLIR(cUnit, (LIR*)res);
+    return res;
+}
 
-    switch (mir->dalvikInsn.opcode) {
-        case OP_NEG_INT:
-            op = kOpNeg;
-            unary = true;
-            break;
-        case OP_NOT_INT:
-            op = kOpMvn;
-            unary = true;
-            break;
-        case OP_ADD_INT:
-        case OP_ADD_INT_2ADDR:
-            op = kOpAdd;
-            break;
-        case OP_SUB_INT:
-        case OP_SUB_INT_2ADDR:
-            op = kOpSub;
-            break;
-        case OP_MUL_INT:
-        case OP_MUL_INT_2ADDR:
-            op = kOpMul;
-            break;
-        case OP_DIV_INT:
-        case OP_DIV_INT_2ADDR:
-            callOut = true;
-            checkZero = true;
-            funcOffset = OFFSETOF_MEMBER(Thread, pIdiv);
-            retReg = r0;
-            break;
-        /* NOTE: returns in r1 */
-        case OP_REM_INT:
-        case OP_REM_INT_2ADDR:
-            callOut = true;
-            checkZero = true;
-            funcOffset = OFFSETOF_MEMBER(Thread, pIdivmod);
-            retReg = r1;
-            break;
-        case OP_AND_INT:
-        case OP_AND_INT_2ADDR:
-            op = kOpAnd;
-            break;
-        case OP_OR_INT:
-        case OP_OR_INT_2ADDR:
-            op = kOpOr;
-            break;
-        case OP_XOR_INT:
-        case OP_XOR_INT_2ADDR:
-            op = kOpXor;
-            break;
-        case OP_SHL_INT:
-        case OP_SHL_INT_2ADDR:
-            shiftOp = true;
-            op = kOpLsl;
-            break;
-        case OP_SHR_INT:
-        case OP_SHR_INT_2ADDR:
-            shiftOp = true;
-            op = kOpAsr;
-            break;
-        case OP_USHR_INT:
-        case OP_USHR_INT_2ADDR:
-            shiftOp = true;
-            op = kOpLsr;
-            break;
-        default:
-            LOG(FATAL) << "Invalid word arith op: " <<
-                (int)mir->dalvikInsn.opcode;
-    }
-    if (!callOut) {
-        rlSrc1 = loadValue(cUnit, rlSrc1, kCoreReg);
-        if (unary) {
-            rlResult = oatEvalLoc(cUnit, rlDest, kCoreReg, true);
-            opRegReg(cUnit, op, rlResult.lowReg,
-                     rlSrc1.lowReg);
+void genRegCopyWide(CompilationUnit* cUnit, int destLo, int destHi,
+                           int srcLo, int srcHi)
+{
+    bool destFP = FPREG(destLo) && FPREG(destHi);
+    bool srcFP = FPREG(srcLo) && FPREG(srcHi);
+    DCHECK_EQ(FPREG(srcLo), FPREG(srcHi));
+    DCHECK_EQ(FPREG(destLo), FPREG(destHi));
+    if (destFP) {
+        if (srcFP) {
+            genRegCopy(cUnit, S2D(destLo, destHi), S2D(srcLo, srcHi));
         } else {
-            rlSrc2 = loadValue(cUnit, rlSrc2, kCoreReg);
-            if (shiftOp) {
-                int tReg = oatAllocTemp(cUnit);
-                opRegRegImm(cUnit, kOpAnd, tReg, rlSrc2.lowReg, 31);
-                rlResult = oatEvalLoc(cUnit, rlDest, kCoreReg, true);
-                opRegRegReg(cUnit, op, rlResult.lowReg,
-                            rlSrc1.lowReg, tReg);
-                oatFreeTemp(cUnit, tReg);
+            newLIR3(cUnit, kThumb2Fmdrr, S2D(destLo, destHi), srcLo, srcHi);
+        }
+    } else {
+        if (srcFP) {
+            newLIR3(cUnit, kThumb2Fmrrd, destLo, destHi, S2D(srcLo, srcHi));
+        } else {
+            // Handle overlap
+            if (srcHi == destLo) {
+                genRegCopy(cUnit, destHi, srcHi);
+                genRegCopy(cUnit, destLo, srcLo);
             } else {
-                rlResult = oatEvalLoc(cUnit, rlDest, kCoreReg, true);
-                opRegRegReg(cUnit, op, rlResult.lowReg,
-                            rlSrc1.lowReg, rlSrc2.lowReg);
-            }
-        }
-        storeValue(cUnit, rlDest, rlResult);
-    } else {
-        RegLocation rlResult;
-        oatFlushAllRegs(cUnit);   /* Send everything to home location */
-        loadValueDirectFixed(cUnit, rlSrc2, r1);
-        loadWordDisp(cUnit, rSELF, funcOffset, rLR);
-        loadValueDirectFixed(cUnit, rlSrc1, r0);
-        if (checkZero) {
-            genImmedCheck(cUnit, kArmCondEq, r1, 0, mir, kArmThrowDivZero);
-        }
-        callRuntimeHelper(cUnit, rLR);
-        if (retReg == r0)
-            rlResult = oatGetReturn(cUnit);
-        else
-            rlResult = oatGetReturnAlt(cUnit);
-        storeValue(cUnit, rlDest, rlResult);
-    }
-    return false;
-}
-
-/* Check if we need to check for pending suspend request */
-STATIC void genSuspendTest(CompilationUnit* cUnit, MIR* mir)
-{
-    if (NO_SUSPEND || (mir->optimizationFlags & MIR_IGNORE_SUSPEND_CHECK)) {
-        return;
-    }
-    oatFlushAllRegs(cUnit);
-    ArmLIR* branch;
-    if (cUnit->genDebugger) {
-        // If generating code for the debugger, always check for suspension
-        branch = genUnconditionalBranch(cUnit, NULL);
-    } else {
-        // In non-debug case, only check periodically
-        newLIR2(cUnit, kThumbSubRI8, rSUSPEND, 1);
-        branch = opCondBranch(cUnit, kArmCondEq);
-    }
-    ArmLIR* retLab = newLIR0(cUnit, kArmPseudoTargetLabel);
-    retLab->defMask = ENCODE_ALL;
-    ArmLIR* target = (ArmLIR*)oatNew(cUnit, sizeof(ArmLIR), true, kAllocLIR);
-    target->generic.dalvikOffset = cUnit->currentDalvikOffset;
-    target->opcode = kArmPseudoSuspendTarget;
-    target->operands[0] = (intptr_t)retLab;
-    target->operands[1] = mir->offset;
-    branch->generic.target = (LIR*)target;
-    oatInsertGrowableList(cUnit, &cUnit->suspendLaunchpads, (intptr_t)target);
-}
-
-/*
- * The following are the first-level codegen routines that analyze the format
- * of each bytecode then either dispatch special purpose codegen routines
- * or produce corresponding Thumb instructions directly.
- */
-
-STATIC bool isPowerOfTwo(int x)
-{
-    return (x & (x - 1)) == 0;
-}
-
-// Returns true if no more than two bits are set in 'x'.
-STATIC bool isPopCountLE2(unsigned int x)
-{
-    x &= x - 1;
-    return (x & (x - 1)) == 0;
-}
-
-// Returns the index of the lowest set bit in 'x'.
-STATIC int lowestSetBit(unsigned int x) {
-    int bit_posn = 0;
-    while ((x & 0xf) == 0) {
-        bit_posn += 4;
-        x >>= 4;
-    }
-    while ((x & 1) == 0) {
-        bit_posn++;
-        x >>= 1;
-    }
-    return bit_posn;
-}
-
-// Returns true if it added instructions to 'cUnit' to divide 'rlSrc' by 'lit'
-// and store the result in 'rlDest'.
-STATIC bool handleEasyDivide(CompilationUnit* cUnit, Opcode dalvikOpcode,
-                             RegLocation rlSrc, RegLocation rlDest, int lit)
-{
-    if (lit < 2 || !isPowerOfTwo(lit)) {
-        return false;
-    }
-    int k = lowestSetBit(lit);
-    if (k >= 30) {
-        // Avoid special cases.
-        return false;
-    }
-    bool div = (dalvikOpcode == OP_DIV_INT_LIT8 ||
-                dalvikOpcode == OP_DIV_INT_LIT16);
-    rlSrc = loadValue(cUnit, rlSrc, kCoreReg);
-    RegLocation rlResult = oatEvalLoc(cUnit, rlDest, kCoreReg, true);
-    if (div) {
-        int tReg = oatAllocTemp(cUnit);
-        if (lit == 2) {
-            // Division by 2 is by far the most common division by constant.
-            opRegRegImm(cUnit, kOpLsr, tReg, rlSrc.lowReg, 32 - k);
-            opRegRegReg(cUnit, kOpAdd, tReg, tReg, rlSrc.lowReg);
-            opRegRegImm(cUnit, kOpAsr, rlResult.lowReg, tReg, k);
-        } else {
-            opRegRegImm(cUnit, kOpAsr, tReg, rlSrc.lowReg, 31);
-            opRegRegImm(cUnit, kOpLsr, tReg, tReg, 32 - k);
-            opRegRegReg(cUnit, kOpAdd, tReg, tReg, rlSrc.lowReg);
-            opRegRegImm(cUnit, kOpAsr, rlResult.lowReg, tReg, k);
-        }
-    } else {
-        int cReg = oatAllocTemp(cUnit);
-        loadConstant(cUnit, cReg, lit - 1);
-        int tReg1 = oatAllocTemp(cUnit);
-        int tReg2 = oatAllocTemp(cUnit);
-        if (lit == 2) {
-            opRegRegImm(cUnit, kOpLsr, tReg1, rlSrc.lowReg, 32 - k);
-            opRegRegReg(cUnit, kOpAdd, tReg2, tReg1, rlSrc.lowReg);
-            opRegRegReg(cUnit, kOpAnd, tReg2, tReg2, cReg);
-            opRegRegReg(cUnit, kOpSub, rlResult.lowReg, tReg2, tReg1);
-        } else {
-            opRegRegImm(cUnit, kOpAsr, tReg1, rlSrc.lowReg, 31);
-            opRegRegImm(cUnit, kOpLsr, tReg1, tReg1, 32 - k);
-            opRegRegReg(cUnit, kOpAdd, tReg2, tReg1, rlSrc.lowReg);
-            opRegRegReg(cUnit, kOpAnd, tReg2, tReg2, cReg);
-            opRegRegReg(cUnit, kOpSub, rlResult.lowReg, tReg2, tReg1);
-        }
-    }
-    storeValue(cUnit, rlDest, rlResult);
-    return true;
-}
-
-// Returns true if it added instructions to 'cUnit' to multiply 'rlSrc' by 'lit'
-// and store the result in 'rlDest'.
-STATIC bool handleEasyMultiply(CompilationUnit* cUnit,
-                               RegLocation rlSrc, RegLocation rlDest, int lit)
-{
-    // Can we simplify this multiplication?
-    bool powerOfTwo = false;
-    bool popCountLE2 = false;
-    bool powerOfTwoMinusOne = false;
-    if (lit < 2) {
-        // Avoid special cases.
-        return false;
-    } else if (isPowerOfTwo(lit)) {
-        powerOfTwo = true;
-    } else if (isPopCountLE2(lit)) {
-        popCountLE2 = true;
-    } else if (isPowerOfTwo(lit + 1)) {
-        powerOfTwoMinusOne = true;
-    } else {
-        return false;
-    }
-    rlSrc = loadValue(cUnit, rlSrc, kCoreReg);
-    RegLocation rlResult = oatEvalLoc(cUnit, rlDest, kCoreReg, true);
-    if (powerOfTwo) {
-        // Shift.
-        opRegRegImm(cUnit, kOpLsl, rlResult.lowReg, rlSrc.lowReg,
-                    lowestSetBit(lit));
-    } else if (popCountLE2) {
-        // Shift and add and shift.
-        int firstBit = lowestSetBit(lit);
-        int secondBit = lowestSetBit(lit ^ (1 << firstBit));
-        genMultiplyByTwoBitMultiplier(cUnit, rlSrc, rlResult, lit,
-                                      firstBit, secondBit);
-    } else {
-        // Reverse subtract: (src << (shift + 1)) - src.
-        DCHECK(powerOfTwoMinusOne);
-        // TUNING: rsb dst, src, src lsl#lowestSetBit(lit + 1)
-        int tReg = oatAllocTemp(cUnit);
-        opRegRegImm(cUnit, kOpLsl, tReg, rlSrc.lowReg, lowestSetBit(lit + 1));
-        opRegRegReg(cUnit, kOpSub, rlResult.lowReg, tReg, rlSrc.lowReg);
-    }
-    storeValue(cUnit, rlDest, rlResult);
-    return true;
-}
-
-STATIC bool genArithOpIntLit(CompilationUnit* cUnit, MIR* mir,
-                             RegLocation rlDest, RegLocation rlSrc,
-                             int lit)
-{
-    Opcode dalvikOpcode = mir->dalvikInsn.opcode;
-    RegLocation rlResult;
-    OpKind op = (OpKind)0;      /* Make gcc happy */
-    int shiftOp = false;
-    bool isDiv = false;
-    int funcOffset;
-
-    switch (dalvikOpcode) {
-        case OP_RSUB_INT_LIT8:
-        case OP_RSUB_INT: {
-            int tReg;
-            //TUNING: add support for use of Arm rsub op
-            rlSrc = loadValue(cUnit, rlSrc, kCoreReg);
-            tReg = oatAllocTemp(cUnit);
-            loadConstant(cUnit, tReg, lit);
-            rlResult = oatEvalLoc(cUnit, rlDest, kCoreReg, true);
-            opRegRegReg(cUnit, kOpSub, rlResult.lowReg,
-                        tReg, rlSrc.lowReg);
-            storeValue(cUnit, rlDest, rlResult);
-            return false;
-            break;
-        }
-
-        case OP_ADD_INT_LIT8:
-        case OP_ADD_INT_LIT16:
-            op = kOpAdd;
-            break;
-        case OP_MUL_INT_LIT8:
-        case OP_MUL_INT_LIT16: {
-            if (handleEasyMultiply(cUnit, rlSrc, rlDest, lit)) {
-                return false;
-            }
-            op = kOpMul;
-            break;
-        }
-        case OP_AND_INT_LIT8:
-        case OP_AND_INT_LIT16:
-            op = kOpAnd;
-            break;
-        case OP_OR_INT_LIT8:
-        case OP_OR_INT_LIT16:
-            op = kOpOr;
-            break;
-        case OP_XOR_INT_LIT8:
-        case OP_XOR_INT_LIT16:
-            op = kOpXor;
-            break;
-        case OP_SHL_INT_LIT8:
-            lit &= 31;
-            shiftOp = true;
-            op = kOpLsl;
-            break;
-        case OP_SHR_INT_LIT8:
-            lit &= 31;
-            shiftOp = true;
-            op = kOpAsr;
-            break;
-        case OP_USHR_INT_LIT8:
-            lit &= 31;
-            shiftOp = true;
-            op = kOpLsr;
-            break;
-
-        case OP_DIV_INT_LIT8:
-        case OP_DIV_INT_LIT16:
-        case OP_REM_INT_LIT8:
-        case OP_REM_INT_LIT16:
-            if (lit == 0) {
-                genImmedCheck(cUnit, kArmCondAl, 0, 0, mir, kArmThrowDivZero);
-                return false;
-            }
-            if (handleEasyDivide(cUnit, dalvikOpcode, rlSrc, rlDest, lit)) {
-                return false;
-            }
-            oatFlushAllRegs(cUnit);   /* Everything to home location */
-            loadValueDirectFixed(cUnit, rlSrc, r0);
-            oatClobber(cUnit, r0);
-            if ((dalvikOpcode == OP_DIV_INT_LIT8) ||
-                (dalvikOpcode == OP_DIV_INT_LIT16)) {
-                funcOffset = OFFSETOF_MEMBER(Thread, pIdiv);
-                isDiv = true;
-            } else {
-                funcOffset = OFFSETOF_MEMBER(Thread, pIdivmod);
-                isDiv = false;
-            }
-            loadWordDisp(cUnit, rSELF, funcOffset, rLR);
-            loadConstant(cUnit, r1, lit);
-            callRuntimeHelper(cUnit, rLR);
-            if (isDiv)
-                rlResult = oatGetReturn(cUnit);
-            else
-                rlResult = oatGetReturnAlt(cUnit);
-            storeValue(cUnit, rlDest, rlResult);
-            return false;
-            break;
-        default:
-            return true;
-    }
-    rlSrc = loadValue(cUnit, rlSrc, kCoreReg);
-    rlResult = oatEvalLoc(cUnit, rlDest, kCoreReg, true);
-    // Avoid shifts by literal 0 - no support in Thumb.  Change to copy
-    if (shiftOp && (lit == 0)) {
-        genRegCopy(cUnit, rlResult.lowReg, rlSrc.lowReg);
-    } else {
-        opRegRegImm(cUnit, op, rlResult.lowReg, rlSrc.lowReg, lit);
-    }
-    storeValue(cUnit, rlDest, rlResult);
-    return false;
-}
-
-/* Architectural-specific debugging helpers go here */
-void oatArchDump(void)
-{
-    /* Print compiled opcode in this VM instance */
-    int i, start, streak;
-    std::string buf;
-
-    streak = i = 0;
-    while (opcodeCoverage[i] == 0 && i < kNumPackedOpcodes) {
-        i++;
-    }
-    if (i == kNumPackedOpcodes) {
-        return;
-    }
-    for (start = i++, streak = 1; i < kNumPackedOpcodes; i++) {
-        if (opcodeCoverage[i]) {
-            streak++;
-        } else {
-            if (streak == 1) {
-                StringAppendF(&buf, "%x,", start);
-            } else {
-                StringAppendF(&buf, "%x-%x,", start, start + streak - 1);
-            }
-            streak = 0;
-            while (opcodeCoverage[i] == 0 && i < kNumPackedOpcodes) {
-                i++;
-            }
-            if (i < kNumPackedOpcodes) {
-                streak = 1;
-                start = i;
+                genRegCopy(cUnit, destLo, srcLo);
+                genRegCopy(cUnit, destHi, srcHi);
             }
         }
     }
-    if (streak) {
-        if (streak == 1) {
-            StringAppendF(&buf, "%x", start);
-        } else {
-            StringAppendF(&buf, "%x-%x", start, start + streak - 1);
-        }
-    }
-    if (!buf.empty()) {
-        LOG(INFO) << "dalvik.vm.oat.op = " << buf;
-    }
 }
 
+
 }  // namespace art
diff --git a/src/compiler/codegen/arm/Thumb2/Ralloc.cc b/src/compiler/codegen/arm/Thumb2/Ralloc.cc
index 59c1aa6..c0f2c77 100644
--- a/src/compiler/codegen/arm/Thumb2/Ralloc.cc
+++ b/src/compiler/codegen/arm/Thumb2/Ralloc.cc
@@ -52,4 +52,71 @@
     return oatAllocTemp(cUnit);
 }
 
+void oatInitializeRegAlloc(CompilationUnit* cUnit)
+{
+    int numRegs = sizeof(coreRegs)/sizeof(*coreRegs);
+    int numReserved = sizeof(reservedRegs)/sizeof(*reservedRegs);
+    int numTemps = sizeof(coreTemps)/sizeof(*coreTemps);
+    int numFPRegs = sizeof(fpRegs)/sizeof(*fpRegs);
+    int numFPTemps = sizeof(fpTemps)/sizeof(*fpTemps);
+    RegisterPool *pool = (RegisterPool *)oatNew(cUnit, sizeof(*pool), true,
+                                                kAllocRegAlloc);
+    cUnit->regPool = pool;
+    pool->numCoreRegs = numRegs;
+    pool->coreRegs = (RegisterInfo *)
+            oatNew(cUnit, numRegs * sizeof(*cUnit->regPool->coreRegs),
+                   true, kAllocRegAlloc);
+    pool->numFPRegs = numFPRegs;
+    pool->FPRegs = (RegisterInfo *)
+            oatNew(cUnit, numFPRegs * sizeof(*cUnit->regPool->FPRegs), true,
+                   kAllocRegAlloc);
+    oatInitPool(pool->coreRegs, coreRegs, pool->numCoreRegs);
+    oatInitPool(pool->FPRegs, fpRegs, pool->numFPRegs);
+    // Keep special registers from being allocated
+    for (int i = 0; i < numReserved; i++) {
+        if (NO_SUSPEND && !cUnit->genDebugger &&
+            (reservedRegs[i] == rSUSPEND)) {
+            //To measure cost of suspend check
+            continue;
+        }
+        oatMarkInUse(cUnit, reservedRegs[i]);
+    }
+    // Mark temp regs - all others not in use can be used for promotion
+    for (int i = 0; i < numTemps; i++) {
+        oatMarkTemp(cUnit, coreTemps[i]);
+    }
+    for (int i = 0; i < numFPTemps; i++) {
+        oatMarkTemp(cUnit, fpTemps[i]);
+    }
+    // Construct the alias map.
+    cUnit->phiAliasMap = (int*)oatNew(cUnit, cUnit->numSSARegs *
+                                      sizeof(cUnit->phiAliasMap[0]), false,
+                                      kAllocDFInfo);
+    for (int i = 0; i < cUnit->numSSARegs; i++) {
+        cUnit->phiAliasMap[i] = i;
+    }
+    for (MIR* phi = cUnit->phiList; phi; phi = phi->meta.phiNext) {
+        int defReg = phi->ssaRep->defs[0];
+        for (int i = 0; i < phi->ssaRep->numUses; i++) {
+           for (int j = 0; j < cUnit->numSSARegs; j++) {
+               if (cUnit->phiAliasMap[j] == phi->ssaRep->uses[i]) {
+                   cUnit->phiAliasMap[j] = defReg;
+               }
+           }
+        }
+    }
+}
+
+void freeRegLocTemps(CompilationUnit* cUnit, RegLocation rlKeep,
+                     RegLocation rlFree)
+{
+    if ((rlFree.lowReg != rlKeep.lowReg) && (rlFree.lowReg != rlKeep.highReg) &&
+        (rlFree.highReg != rlKeep.lowReg) && (rlFree.highReg != rlKeep.highReg)) {
+        // No overlap, free both
+        oatFreeTemp(cUnit, rlFree.lowReg);
+        oatFreeTemp(cUnit, rlFree.highReg);
+    }
+}
+
+
 }  // namespace art
diff --git a/src/compiler/codegen/arm/armv7-a-neon/ArchVariant.cc b/src/compiler/codegen/arm/armv7-a-neon/ArchVariant.cc
index eafe5ed..77844fc 100644
--- a/src/compiler/codegen/arm/armv7-a-neon/ArchVariant.cc
+++ b/src/compiler/codegen/arm/armv7-a-neon/ArchVariant.cc
@@ -47,7 +47,7 @@
 void oatGenMemBarrier(CompilationUnit* cUnit, int barrierKind)
 {
 #if ANDROID_SMP != 0
-    ArmLIR* dmb = newLIR1(cUnit, kThumb2Dmb, barrierKind);
+    LIR* dmb = newLIR1(cUnit, kThumb2Dmb, barrierKind);
     dmb->defMask = ENCODE_ALL;
 #endif
 }
diff --git a/src/compiler/codegen/arm/armv7-a-neon/Codegen.cc b/src/compiler/codegen/arm/armv7-a-neon/Codegen.cc
index f042d5d..f7132ab 100644
--- a/src/compiler/codegen/arm/armv7-a-neon/Codegen.cc
+++ b/src/compiler/codegen/arm/armv7-a-neon/Codegen.cc
@@ -15,7 +15,7 @@
  */
 #define _CODEGEN_C
 #define _ARMV7_A_NEON
-#define TGT_LIR ArmLIR
+#define TARGET_ARM
 
 #include "../../../Dalvik.h"
 #include "../../../CompilerInternals.h"
@@ -23,13 +23,17 @@
 #include "../../Ralloc.h"
 #include "../Codegen.h"
 
-/* Arm codegen building blocks */
-#include "../CodegenCommon.cc"
+/* Common codegen utility code */
+#include "../../CodegenUtil.cc"
 
 /* Thumb2-specific factory utilities */
 #include "../Thumb2/Factory.cc"
 /* Target indepedent factory utilities */
 #include "../../CodegenFactory.cc"
+/* Target independent gen routines */
+#include "../../GenCommon.cc"
+/* Shared invoke gen routines */
+#include "../../GenInvoke.cc"
 /* Arm-specific factory utilities */
 #include "../ArchFactory.cc"
 
@@ -47,8 +51,5 @@
 /* Target-independent local optimizations */
 #include "../../LocalOptimizations.cc"
 
-/* Common codegen utility code */
-#include "../../CodegenUtil.cc"
-
 /* Architecture manifest */
 #include "ArchVariant.cc"
diff --git a/src/compiler/codegen/arm/armv7-a/ArchVariant.cc b/src/compiler/codegen/arm/armv7-a/ArchVariant.cc
index eafe5ed..77844fc 100644
--- a/src/compiler/codegen/arm/armv7-a/ArchVariant.cc
+++ b/src/compiler/codegen/arm/armv7-a/ArchVariant.cc
@@ -47,7 +47,7 @@
 void oatGenMemBarrier(CompilationUnit* cUnit, int barrierKind)
 {
 #if ANDROID_SMP != 0
-    ArmLIR* dmb = newLIR1(cUnit, kThumb2Dmb, barrierKind);
+    LIR* dmb = newLIR1(cUnit, kThumb2Dmb, barrierKind);
     dmb->defMask = ENCODE_ALL;
 #endif
 }
diff --git a/src/compiler/codegen/arm/armv7-a/Codegen.cc b/src/compiler/codegen/arm/armv7-a/Codegen.cc
index 633ab1e..6f62ccf 100644
--- a/src/compiler/codegen/arm/armv7-a/Codegen.cc
+++ b/src/compiler/codegen/arm/armv7-a/Codegen.cc
@@ -15,7 +15,7 @@
  */
 #define _CODEGEN_C
 #define _ARMV7_A
-#define TGT_LIR ArmLIR
+#define TARGET_ARM
 
 #include "../../../Dalvik.h"
 #include "../../../CompilerInternals.h"
@@ -23,13 +23,17 @@
 #include "../../Ralloc.h"
 #include "../Codegen.h"
 
-/* Arm codegen building blocks */
-#include "../CodegenCommon.cc"
+/* Common codegen utility code */
+#include "../../CodegenUtil.cc"
 
 /* Thumb2-specific factory utilities */
 #include "../Thumb2/Factory.cc"
 /* Target independent factory utilities */
 #include "../../CodegenFactory.cc"
+/* Target independent gen routines */
+#include "../../GenCommon.cc"
+/* Shared invoke gen routines */
+#include "../../GenInvoke.cc"
 /* Arm-specific factory utilities */
 #include "../ArchFactory.cc"
 
@@ -47,8 +51,5 @@
 /* Target-independent local optimizations */
 #include "../../LocalOptimizations.cc"
 
-/* Common codegen utility code */
-#include "../../CodegenUtil.cc"
-
 /* Architecture manifest */
 #include "ArchVariant.cc"
diff --git a/src/compiler/codegen/mips/ArchFactory.cc b/src/compiler/codegen/mips/ArchFactory.cc
index 6a3e667..cb9645d 100644
--- a/src/compiler/codegen/mips/ArchFactory.cc
+++ b/src/compiler/codegen/mips/ArchFactory.cc
@@ -39,20 +39,6 @@
 
 STATIC void genDebuggerUpdate(CompilationUnit* cUnit, int32_t offset);
 
-/* Generate conditional branch instructions */
-STATIC MipsLIR* genConditionalBranch(CompilationUnit* cUnit,
-                                    MipsConditionCode cond,
-                                    MipsLIR* target)
-{
-    UNIMPLEMENTED(FATAL) << "Needs mips version";
-    return NULL;
-#if 0
-    MipsLIR* branch = opCondBranch(cUnit, cond);
-    branch->generic.target = (LIR*) target;
-    return branch;
-#endif
-}
-
 /* Generate unconditional branch instructions */
 STATIC MipsLIR* genUnconditionalBranch(CompilationUnit* cUnit, MipsLIR* target)
 {
@@ -72,22 +58,19 @@
  */
 STATIC void markGCCard(CompilationUnit* cUnit, int valReg, int tgtAddrReg)
 {
-    UNIMPLEMENTED(FATAL) << "Needs mips version";
-#if 0
     int regCardBase = oatAllocTemp(cUnit);
     int regCardNo = oatAllocTemp(cUnit);
-    MipsLIR* branchOver = genCmpImmBranch(cUnit, kMipsCondEq, valReg, 0);
+    MipsLIR* branchOver = opCompareBranchCC(cUnit, kMipsCondEq, valReg, r_ZERO);
     loadWordDisp(cUnit, rSELF, Thread::CardTableOffset().Int32Value(),
                  regCardBase);
     opRegRegImm(cUnit, kOpLsr, regCardNo, tgtAddrReg, GC_CARD_SHIFT);
     storeBaseIndexed(cUnit, regCardBase, regCardNo, regCardBase, 0,
                      kUnsignedByte);
-    MipsLIR* target = newLIR0(cUnit, kMipsPseudoTargetLabel);
+    MipsLIR* target = newLIR0(cUnit, kPseudoTargetLabel);
     target->defMask = ENCODE_ALL;
     branchOver->generic.target = (LIR*)target;
     oatFreeTemp(cUnit, regCardBase);
     oatFreeTemp(cUnit, regCardNo);
-#endif
 }
 
 /*
@@ -97,14 +80,11 @@
  */
 STATIC void loadCurrMethodDirect(CompilationUnit *cUnit, int rTgt)
 {
-    UNIMPLEMENTED(FATAL) << "Needs mips version";
-#if 0
 #if defined(METHOD_IN_REG)
     genRegCopy(cUnit, rTgt, rMETHOD);
 #else
     loadWordDisp(cUnit, rSP, 0, rTgt);
 #endif
-#endif
 }
 
 STATIC int loadCurrMethod(CompilationUnit *cUnit)
@@ -118,70 +98,49 @@
 #endif
 }
 
-STATIC MipsLIR* genCheck(CompilationUnit* cUnit, MipsConditionCode cCode,
-                        MIR* mir, MipsThrowKind kind)
-{
-    UNIMPLEMENTED(FATAL) << "Needs mips version";
-    return 0;
-#if 0
-    MipsLIR* tgt = (MipsLIR*)oatNew(cUnit, sizeof(MipsLIR), true, kAllocLIR);
-    tgt->opcode = kMipsPseudoThrowTarget;
-    tgt->operands[0] = kind;
-    tgt->operands[1] = mir ? mir->offset : 0;
-    MipsLIR* branch = genConditionalBranch(cUnit, cCode, tgt);
-    // Remember branch target - will process later
-    oatInsertGrowableList(cUnit, &cUnit->throwLaunchpads, (intptr_t)tgt);
-    return branch;
-#endif
-}
-
 STATIC MipsLIR* genImmedCheck(CompilationUnit* cUnit, MipsConditionCode cCode,
                              int reg, int immVal, MIR* mir, MipsThrowKind kind)
 {
-    UNIMPLEMENTED(FATAL) << "Needs mips version";
-    return 0;
-#if 0
     MipsLIR* tgt = (MipsLIR*)oatNew(cUnit, sizeof(MipsLIR), true, kAllocLIR);
-    tgt->opcode = kMipsPseudoThrowTarget;
+    tgt->opcode = kPseudoThrowTarget;
     tgt->operands[0] = kind;
     tgt->operands[1] = mir->offset;
     MipsLIR* branch;
     if (cCode == kMipsCondAl) {
         branch = genUnconditionalBranch(cUnit, tgt);
     } else {
-        branch = genCmpImmBranch(cUnit, cCode, reg, immVal);
+        int tReg;
+        if (immVal == 0) {
+            tReg = r_ZERO;
+        } else {
+            tReg = oatAllocTemp(cUnit);
+            loadConstant(cUnit, tReg, immVal);
+        }
+        branch = opCompareBranchCC(cUnit, cCode, reg, tReg);
         branch->generic.target = (LIR*)tgt;
     }
     // Remember branch target - will process later
     oatInsertGrowableList(cUnit, &cUnit->throwLaunchpads, (intptr_t)tgt);
     return branch;
-#endif
 }
 
 /* Perform null-check on a register.  */
 STATIC MipsLIR* genNullCheck(CompilationUnit* cUnit, int sReg, int mReg,
                              MIR* mir)
 {
-    UNIMPLEMENTED(FATAL) << "Needs mips version";
-    return 0;
-#if 0
     if (!(cUnit->disableOpt & (1 << kNullCheckElimination)) &&
         mir->optimizationFlags & MIR_IGNORE_NULL_CHECK) {
         return NULL;
     }
     return genImmedCheck(cUnit, kMipsCondEq, mReg, 0, mir, kMipsThrowNullPointer);
-#endif
 }
 
 /* Perform check on two registers */
 STATIC TGT_LIR* genRegRegCheck(CompilationUnit* cUnit, MipsConditionCode cCode,
                                int reg1, int reg2, MIR* mir, MipsThrowKind kind)
 {
-    UNIMPLEMENTED(FATAL) << "Needs mips version";
-    return 0;
-#if 0
     MipsLIR* tgt = (MipsLIR*)oatNew(cUnit, sizeof(MipsLIR), true, kAllocLIR);
-    tgt->opcode = kMipsPseudoThrowTarget;
+    tgt->opcode = kPseudoThrowTarget;
     tgt->operands[0] = kind;
     tgt->operands[1] = mir ? mir->offset : 0;
     tgt->operands[2] = reg1;
@@ -191,7 +150,6 @@
     // Remember branch target - will process later
     oatInsertGrowableList(cUnit, &cUnit->throwLaunchpads, (intptr_t)tgt);
     return branch;
-#endif
 }
 
 /*
@@ -202,27 +160,26 @@
 STATIC void genNewArray(CompilationUnit* cUnit, MIR* mir, RegLocation rlDest,
                         RegLocation rlSrc)
 {
-    UNIMPLEMENTED(FATAL) << "Needs mips version";
-#if 0
     oatFlushAllRegs(cUnit);    /* Everything to home location */
+    oatLockCallTemps(cUnit);
+    int addrReg = oatAllocTemp(cUnit);
     uint32_t type_idx = mir->dalvikInsn.vC;
     if (cUnit->compiler->CanAccessTypeWithoutChecks(cUnit->method_idx,
                                                     cUnit->dex_cache,
                                                     *cUnit->dex_file,
                                                     type_idx)) {
         loadWordDisp(cUnit, rSELF,
-                     OFFSETOF_MEMBER(Thread, pAllocArrayFromCode), rLR);
+                     OFFSETOF_MEMBER(Thread, pAllocArrayFromCode), addrReg);
     } else {
         loadWordDisp(cUnit, rSELF,
-                     OFFSETOF_MEMBER(Thread, pAllocArrayFromCodeWithAccessCheck), rLR);
+                     OFFSETOF_MEMBER(Thread, pAllocArrayFromCodeWithAccessCheck), addrReg);
     }
-    loadCurrMethodDirect(cUnit, r1);              // arg1 <- Method*
-    loadConstant(cUnit, r0, type_idx);            // arg0 <- type_id
-    loadValueDirectFixed(cUnit, rlSrc, r2);       // arg2 <- count
-    callRuntimeHelper(cUnit, rLR);
+    loadCurrMethodDirect(cUnit, r_ARG1);              // arg1 <- Method*
+    loadConstant(cUnit, r_ARG0, type_idx);            // arg0 <- type_id
+    loadValueDirectFixed(cUnit, rlSrc, r_ARG2);       // arg2 <- count
+    callRuntimeHelper(cUnit, addrReg);
     RegLocation rlResult = oatGetReturn(cUnit);
     storeValue(cUnit, rlDest, rlResult);
-#endif
 }
 
 /*
@@ -233,34 +190,36 @@
  */
 STATIC void genFilledNewArray(CompilationUnit* cUnit, MIR* mir, bool isRange)
 {
-    UNIMPLEMENTED(FATAL) << "Needs mips version";
-#if 0
     DecodedInstruction* dInsn = &mir->dalvikInsn;
     int elems = dInsn->vA;
     int typeId = dInsn->vB;
     oatFlushAllRegs(cUnit);    /* Everything to home location */
+    oatLockCallTemps(cUnit);
+    int addrReg = oatAllocTemp(cUnit);
     if (cUnit->compiler->CanAccessTypeWithoutChecks(cUnit->method_idx,
                                                     cUnit->dex_cache,
                                                     *cUnit->dex_file,
                                                     typeId)) {
         loadWordDisp(cUnit, rSELF,
-                     OFFSETOF_MEMBER(Thread, pCheckAndAllocArrayFromCode), rLR);
+                     OFFSETOF_MEMBER(Thread, pCheckAndAllocArrayFromCode),
+                                     addrReg);
     } else {
         loadWordDisp(cUnit, rSELF,
-                     OFFSETOF_MEMBER(Thread, pCheckAndAllocArrayFromCodeWithAccessCheck), rLR);
+                     OFFSETOF_MEMBER(Thread,
+                     pCheckAndAllocArrayFromCodeWithAccessCheck), addrReg);
     }
-    loadCurrMethodDirect(cUnit, r1);              // arg1 <- Method*
-    loadConstant(cUnit, r0, typeId);              // arg0 <- type_id
-    loadConstant(cUnit, r2, elems);               // arg2 <- count
-    callRuntimeHelper(cUnit, rLR);
+    loadCurrMethodDirect(cUnit, r_ARG1);              // arg1 <- Method*
+    loadConstant(cUnit, r_ARG0, typeId);              // arg0 <- type_id
+    loadConstant(cUnit, r_ARG2, elems);               // arg2 <- count
+    callRuntimeHelper(cUnit, addrReg);
     /*
      * NOTE: the implicit target for OP_FILLED_NEW_ARRAY is the
      * return region.  Because AllocFromCode placed the new array
-     * in r0, we'll just lock it into place.  When debugger support is
+     * in r_V0, we'll just lock it into place.  When debugger support is
      * added, it may be necessary to additionally copy all return
      * values to a home location in thread-local storage
      */
-    oatLockTemp(cUnit, r0);
+    oatLockTemp(cUnit, r_V0);
 
     // Having a range of 0 is legal
     if (isRange && (dInsn->vA > 0)) {
@@ -288,32 +247,31 @@
         int rSrc = oatAllocTemp(cUnit);
         int rDst = oatAllocTemp(cUnit);
         int rIdx = oatAllocTemp(cUnit);
-        int rVal = rLR;  // Using a lot of temps, rLR is known free here
+        int rVal = oatAllocTemp(cUnit);
         // Set up source pointer
         RegLocation rlFirst = oatGetSrc(cUnit, mir, 0);
         opRegRegImm(cUnit, kOpAdd, rSrc, rSP,
                     oatSRegOffset(cUnit, rlFirst.sRegLow));
         // Set up the target pointer
-        opRegRegImm(cUnit, kOpAdd, rDst, r0,
+        opRegRegImm(cUnit, kOpAdd, rDst, r_V0,
                     Array::DataOffset().Int32Value());
         // Set up the loop counter (known to be > 0)
         loadConstant(cUnit, rIdx, dInsn->vA - 1);
         // Generate the copy loop.  Going backwards for convenience
-        MipsLIR* target = newLIR0(cUnit, kMipsPseudoTargetLabel);
+        MipsLIR* target = newLIR0(cUnit, kPseudoTargetLabel);
         target->defMask = ENCODE_ALL;
         // Copy next element
         loadBaseIndexed(cUnit, rSrc, rIdx, rVal, 2, kWord);
         storeBaseIndexed(cUnit, rDst, rIdx, rVal, 2, kWord);
-        // Use setflags encoding here
-        newLIR3(cUnit, kThumb2SubsRRI12, rIdx, rIdx, 1);
-        MipsLIR* branch = opCondBranch(cUnit, kMipsCondGe);
+        opRegImm(cUnit, kOpSub, rIdx, 1);
+        MipsLIR* branch = opCompareBranchCC(cUnit, kMipsCondGe, rIdx, r_ZERO);
         branch->generic.target = (LIR*)target;
     } else if (!isRange) {
         // TUNING: interleave
         for (unsigned int i = 0; i < dInsn->vA; i++) {
             RegLocation rlArg = loadValue(cUnit,
                 oatGetSrc(cUnit, mir, i), kCoreReg);
-            storeBaseDisp(cUnit, r0,
+            storeBaseDisp(cUnit, r_V0,
                           Array::DataOffset().Int32Value() +
                           i * 4, rlArg.lowReg, kWord);
             // If the loadValue caused a temp to be allocated, free it
@@ -322,14 +280,11 @@
             }
         }
     }
-#endif
 }
 
 STATIC void genSput(CompilationUnit* cUnit, MIR* mir, RegLocation rlSrc,
                     bool isLongOrDouble, bool isObject)
 {
-    UNIMPLEMENTED(FATAL) << "Needs mips version";
-#if 0
     int fieldOffset;
     int ssbIndex;
     bool isVolatile;
@@ -357,6 +312,7 @@
             oatFlushAllRegs(cUnit);
             // Using fixed register to sync with possible call to runtime
             // support.
+            oatLockCallTemps(cUnit);
             rMethod = r1;
             oatLockTemp(cUnit, rMethod);
             loadCurrMethodDirect(cUnit, rMethod);
@@ -371,12 +327,13 @@
             // rBase now points at appropriate static storage base (Class*)
             // or NULL if not initialized. Check for NULL and call helper if NULL.
             // TUNING: fast path should fall through
-            MipsLIR* branchOver = genCmpImmBranch(cUnit, kMipsCondNe, rBase, 0);
+            MipsLIR* branchOver = opCmpImmBranchCC(cUnit, kMipsCondNe,
+                                                   rBase, 0);
             loadWordDisp(cUnit, rSELF,
                          OFFSETOF_MEMBER(Thread, pInitializeStaticStorage), rLR);
             loadConstant(cUnit, r0, ssbIndex);
             callRuntimeHelper(cUnit, rLR);
-            MipsLIR* skipTarget = newLIR0(cUnit, kMipsPseudoTargetLabel);
+            MipsLIR* skipTarget = newLIR0(cUnit, kPseudoTargetLabel);
             skipTarget->defMask = ENCODE_ALL;
             branchOver->generic.target = (LIR*)skipTarget;
         }
@@ -419,7 +376,6 @@
         }
         callRuntimeHelper(cUnit, rLR);
     }
-#endif
 }
 
 STATIC void genSget(CompilationUnit* cUnit, MIR* mir, RegLocation rlDest,
@@ -468,12 +424,12 @@
             // rBase now points at appropriate static storage base (Class*)
             // or NULL if not initialized. Check for NULL and call helper if NULL.
             // TUNING: fast path should fall through
-            MipsLIR* branchOver = genCmpImmBranch(cUnit, kMipsCondNe, rBase, 0);
+            MipsLIR* branchOver = opCmpImmBranchCC(cUnit, kMipsCondNe, rBase, 0);
             loadWordDisp(cUnit, rSELF,
                          OFFSETOF_MEMBER(Thread, pInitializeStaticStorage), rLR);
             loadConstant(cUnit, r0, ssbIndex);
             callRuntimeHelper(cUnit, rLR);
-            MipsLIR* skipTarget = newLIR0(cUnit, kMipsPseudoTargetLabel);
+            MipsLIR* skipTarget = newLIR0(cUnit, kPseudoTargetLabel);
             skipTarget->defMask = ENCODE_ALL;
             branchOver->generic.target = (LIR*)skipTarget;
         }
@@ -947,10 +903,10 @@
 {
     UNIMPLEMENTED(FATAL) << "Needs mips version";
 #if 0
-    MipsLIR* branchOver = genCmpImmBranch(cUnit, kMipsCondNe, rLR, 0);
+    MipsLIR* branchOver = opCmpImmBranch(cUnit, kMipsCondNe, rLR, 0);
     loadWordDisp(cUnit, rSELF,
                  OFFSETOF_MEMBER(Thread, pDebugMe), rLR);
-    MipsLIR* target = newLIR0(cUnit, kMipsPseudoTargetLabel);
+    MipsLIR* target = newLIR0(cUnit, kPseudoTargetLabel);
     target->defMask = -1;
     branchOver->generic.target = (LIR*)target;
 #endif
@@ -1164,7 +1120,7 @@
     bool skipOverflowCheck = ((cUnit->attrs & METHOD_IS_LEAF) &&
                               ((size_t)cUnit->frameSize <
                               Thread::kStackOverflowReservedBytes));
-    newLIR0(cUnit, kMipsPseudoMethodEntry);
+    newLIR0(cUnit, kPseudoMethodEntry);
     if (!skipOverflowCheck) {
         /* Load stack limit */
         loadWordDisp(cUnit, rSELF,
@@ -1220,7 +1176,7 @@
     oatLockTemp(cUnit, r0);
     oatLockTemp(cUnit, r1);
 
-    newLIR0(cUnit, kMipsPseudoMethodExit);
+    newLIR0(cUnit, kPseudoMethodExit);
     /* If we're compiling for the debugger, generate an update callout */
     if (cUnit->genDebugger) {
         genDebuggerUpdate(cUnit, DEBUGGER_METHOD_EXIT);
diff --git a/src/compiler/codegen/mips/ArchUtility.cc b/src/compiler/codegen/mips/ArchUtility.cc
index f218436..2e8d417 100644
--- a/src/compiler/codegen/mips/ArchUtility.cc
+++ b/src/compiler/codegen/mips/ArchUtility.cc
@@ -221,50 +221,50 @@
 
     /* Handle pseudo-ops individually, and all regular insns as a group */
     switch(lir->opcode) {
-        case kMipsPseudoMethodEntry:
+        case kPseudoMethodEntry:
             LOG(INFO) << "-------- method entry " <<
                 PrettyMethod(cUnit->method_idx, *cUnit->dex_file);
             break;
-        case kMipsPseudoMethodExit:
+        case kPseudoMethodExit:
             LOG(INFO) << "-------- Method_Exit";
             break;
-        case kMipsPseudoBarrier:
+        case kPseudoBarrier:
             LOG(INFO) << "-------- BARRIER";
             break;
-        case kMipsPseudoExtended:
+        case kPseudoExtended:
             LOG(INFO) << "-------- " << (char* ) dest;
             break;
-        case kMipsPseudoSSARep:
+        case kPseudoSSARep:
             DUMP_SSA_REP(LOG(INFO) << "-------- kMirOpPhi: " <<  (char* ) dest);
             break;
-        case kMipsPseudoEntryBlock:
+        case kPseudoEntryBlock:
             LOG(INFO) << "-------- entry offset: 0x" << std::hex << dest;
             break;
-        case kMipsPseudoDalvikByteCodeBoundary:
+        case kPseudoDalvikByteCodeBoundary:
             LOG(INFO) << "-------- dalvik offset: 0x" << std::hex <<
                  lir->generic.dalvikOffset << " @ " << (char* )lir->operands[0];
             break;
-        case kMipsPseudoExitBlock:
+        case kPseudoExitBlock:
             LOG(INFO) << "-------- exit offset: 0x" << std::hex << dest;
             break;
-        case kMipsPseudoPseudoAlign4:
+        case kPseudoPseudoAlign4:
             LOG(INFO) << (intptr_t)baseAddr + offset << " (0x" << std::hex <<
                 offset << "): .align4";
             break;
-        case kMipsPseudoEHBlockLabel:
+        case kPseudoEHBlockLabel:
             LOG(INFO) << "Exception_Handling:";
             break;
-        case kMipsPseudoTargetLabel:
-        case kMipsPseudoNormalBlockLabel:
+        case kPseudoTargetLabel:
+        case kPseudoNormalBlockLabel:
             LOG(INFO) << "L" << (intptr_t)lir << ":";
             break;
-        case kMipsPseudoThrowTarget:
+        case kPseudoThrowTarget:
             LOG(INFO) << "LT" << (intptr_t)lir << ":";
             break;
-        case kMipsPseudoSuspendTarget:
+        case kPseudoSuspendTarget:
             LOG(INFO) << "LS" << (intptr_t)lir << ":";
             break;
-        case kMipsPseudoCaseLabel:
+        case kPseudoCaseLabel:
             LOG(INFO) << "LC" << (intptr_t)lir << ": Case target 0x" <<
                 std::hex << lir->operands[0] << "|" << std::dec <<
                 lir->operands[0];
diff --git a/src/compiler/codegen/mips/Assemble.cc b/src/compiler/codegen/mips/Assemble.cc
index 9e8af2a..5b6e6ed 100644
--- a/src/compiler/codegen/mips/Assemble.cc
+++ b/src/compiler/codegen/mips/Assemble.cc
@@ -540,7 +540,7 @@
                 mipsLIR->flags.size = EncodingMap[mipsLIR->opcode].size * 2;
                 offset += mipsLIR->flags.size;
             }
-        } else if (mipsLIR->opcode == kMipsPseudoPseudoAlign4) {
+        } else if (mipsLIR->opcode == kPseudoPseudoAlign4) {
             if (offset & 0x2) {
                 offset += 2;
                 mipsLIR->operands[0] = 1;
diff --git a/src/compiler/codegen/mips/CodegenCommon.cc b/src/compiler/codegen/mips/CodegenCommon.cc
index 3645643..8dbb9a3 100644
--- a/src/compiler/codegen/mips/CodegenCommon.cc
+++ b/src/compiler/codegen/mips/CodegenCommon.cc
@@ -26,9 +26,6 @@
  * applicable directory below this one.
  */
 
-/* Track exercised opcodes */
-static int opcodeCoverage[kNumPackedOpcodes];
-
 static void setMemRefType(MipsLIR *lir, bool isLoad, int memType)
 {
     /* MIPSTODO simplify setMemRefType() */
@@ -230,46 +227,13 @@
 }
 
 /*
- * Set up the accurate resource mask for branch instructions
- */
-static void relaxBranchMasks(MipsLIR *lir)
-{
-    int flags = EncodingMap[lir->opcode].flags;
-
-    /* Make sure only branch instructions are passed here */
-    DCHECK(flags & IS_BRANCH);
-
-    lir->defMask |= ENCODE_REG_PC;
-    lir->useMask |= ENCODE_REG_PC;
-
-
-    if (flags & REG_DEF_LR) {
-        lir->defMask |= ENCODE_REG_LR;
-    }
-
-    if (flags & (REG_USE0 | REG_USE1 | REG_USE2 | REG_USE3)) {
-        int i;
-
-        for (i = 0; i < 4; i++) {
-            if (flags & (1 << (kRegUse0 + i))) {
-                setupRegMask(&lir->useMask, lir->operands[i]);
-            }
-        }
-    }
-
-    if (flags & USES_CCODES) {
-        lir->useMask |= ENCODE_CCODE;
-    }
-}
-
-/*
  * The following are building blocks to construct low-level IRs with 0 - 4
  * operands.
  */
-static MipsLIR *newLIR0(CompilationUnit *cUnit, MipsOpCode opcode)
+MipsLIR *newLIR0(CompilationUnit *cUnit, MipsOpCode opcode)
 {
     MipsLIR *insn = (MipsLIR *) oatNew(cUnit, sizeof(MipsLIR), true, kAllocLIR);
-    DCHECK(isPseudoOpCode(opcode) || (EncodingMap[opcode].flags & NO_OPERAND));
+    DCHECK(isPseudoOpcode(opcode) || (EncodingMap[opcode].flags & NO_OPERAND));
     insn->opcode = opcode;
     setupResourceMasks(insn);
     insn->generic.dalvikOffset = cUnit->currentDalvikOffset;
@@ -277,11 +241,11 @@
     return insn;
 }
 
-static MipsLIR *newLIR1(CompilationUnit *cUnit, MipsOpCode opcode,
+MipsLIR *newLIR1(CompilationUnit *cUnit, MipsOpCode opcode,
                            int dest)
 {
     MipsLIR *insn = (MipsLIR *) oatNew(cUnit, sizeof(MipsLIR), true, kAllocLIR);
-    DCHECK(isPseudoOpCode(opcode) || (EncodingMap[opcode].flags & IS_UNARY_OP));
+    DCHECK(isPseudoOpcode(opcode) || (EncodingMap[opcode].flags & IS_UNARY_OP));
     insn->opcode = opcode;
     insn->operands[0] = dest;
     setupResourceMasks(insn);
@@ -290,11 +254,11 @@
     return insn;
 }
 
-static MipsLIR *newLIR2(CompilationUnit *cUnit, MipsOpCode opcode,
+MipsLIR *newLIR2(CompilationUnit *cUnit, MipsOpCode opcode,
                            int dest, int src1)
 {
     MipsLIR *insn = (MipsLIR *) oatNew(cUnit, sizeof(MipsLIR), true, kAllocLIR);
-    DCHECK(isPseudoOpCode(opcode) ||
+    DCHECK(isPseudoOpcode(opcode) ||
            (EncodingMap[opcode].flags & IS_BINARY_OP));
     insn->opcode = opcode;
     insn->operands[0] = dest;
@@ -305,14 +269,14 @@
     return insn;
 }
 
-static MipsLIR *newLIR3(CompilationUnit *cUnit, MipsOpCode opcode,
+MipsLIR *newLIR3(CompilationUnit *cUnit, MipsOpCode opcode,
                            int dest, int src1, int src2)
 {
     MipsLIR *insn = (MipsLIR *) oatNew(cUnit, sizeof(MipsLIR), true, kAllocLIR);
     if (!(EncodingMap[opcode].flags & IS_TERTIARY_OP)) {
         LOG(FATAL) << "Bad LIR3: " << EncodingMap[opcode].name;
     }
-    DCHECK(isPseudoOpCode(opcode) ||
+    DCHECK(isPseudoOpcode(opcode) ||
            (EncodingMap[opcode].flags & IS_TERTIARY_OP));
     insn->opcode = opcode;
     insn->operands[0] = dest;
@@ -324,11 +288,11 @@
     return insn;
 }
 
-static MipsLIR *newLIR4(CompilationUnit *cUnit, MipsOpCode opcode,
+MipsLIR *newLIR4(CompilationUnit *cUnit, MipsOpCode opcode,
                            int dest, int src1, int src2, int info)
 {
     MipsLIR *insn = (MipsLIR *) oatNew(cUnit, sizeof(MipsLIR), true, kAllocLIR);
-    DCHECK(isPseudoOpCode(opcode) ||
+    DCHECK(isPseudoOpcode(opcode) ||
            (EncodingMap[opcode].flags & IS_QUAD_OP));
     insn->opcode = opcode;
     insn->operands[0] = dest;
@@ -342,36 +306,12 @@
 }
 
 /*
- * The following are building blocks to insert constants into the pool or
- * instruction streams.
- */
-
-/* Add a 32-bit constant either in the constant pool or mixed with code */
-static MipsLIR *addWordData(CompilationUnit *cUnit, LIR **constantListP,
-                           int value)
-{
-    /* Add the constant to the literal pool */
-    if (constantListP) {
-        MipsLIR *newValue = (MipsLIR *) oatNew(cUnit, sizeof(MipsLIR), true,
-                                               kAllocData);
-        newValue->operands[0] = value;
-        newValue->generic.next = *constantListP;
-        *constantListP = (LIR *) newValue;
-        return newValue;
-    } else {
-        /* Add the constant in the middle of code stream */
-        newLIR1(cUnit, kMips32BitData, value);
-    }
-    return NULL;
-}
-
-/*
- * Generate an kMipsPseudoBarrier marker to indicate the boundary of special
+ * Generate an kPseudoBarrier marker to indicate the boundary of special
  * blocks.
  */
 static void genBarrier(CompilationUnit *cUnit)
 {
-    MipsLIR *barrier = newLIR0(cUnit, kMipsPseudoBarrier);
+    MipsLIR *barrier = newLIR0(cUnit, kPseudoBarrier);
     /* Mark all resources as being clobbered */
     barrier->defMask = -1;
 }
diff --git a/src/compiler/codegen/mips/FP/MipsFP.cc b/src/compiler/codegen/mips/FP/MipsFP.cc
index fd07a34..7eb2a1a 100644
--- a/src/compiler/codegen/mips/FP/MipsFP.cc
+++ b/src/compiler/codegen/mips/FP/MipsFP.cc
@@ -21,7 +21,7 @@
 extern void oatFlushRegForV5TEVFP(CompilationUnit *cUnit, int reg);
 
 /* First, flush any registers associated with this value */
-static void loadValueAddress(CompilationUnit *cUnit, RegLocation rlSrc,
+void loadValueAddress(CompilationUnit *cUnit, RegLocation rlSrc,
                              int rDest)
 {
     UNIMPLEMENTED(FATAL) << "Need Mips implementation";
@@ -253,7 +253,6 @@
     int op = kMipsNop;
     int srcReg;
     RegLocation rlResult;
-
     switch (opcode) {
         case OP_INT_TO_FLOAT:
             longSrc = false;
diff --git a/src/compiler/codegen/mips/Mips32/Factory.cc b/src/compiler/codegen/mips/Mips32/Factory.cc
index ffbb223..f76adff 100644
--- a/src/compiler/codegen/mips/Mips32/Factory.cc
+++ b/src/compiler/codegen/mips/Mips32/Factory.cc
@@ -38,21 +38,17 @@
                         r_F8, r_F9, r_F10, r_F11, r_F12, r_F13, r_F14, r_F15};
 #endif
 
-static void storePair(CompilationUnit *cUnit, int base, int lowReg,
-                      int highReg);
-static void loadPair(CompilationUnit *cUnit, int base, int lowReg, int highReg);
-static MipsLIR *loadWordDisp(CompilationUnit *cUnit, int rBase, int displacement,
-                            int rDest);
-static MipsLIR *storeWordDisp(CompilationUnit *cUnit, int rBase,
-                             int displacement, int rSrc);
-static MipsLIR *genRegRegCheck(CompilationUnit *cUnit,
-                              MipsConditionCode cond,
-                              int reg1, int reg2, int dOffset,
-                              MipsLIR *pcrLabel);
-static MipsLIR *loadConstant(CompilationUnit *cUnit, int rDest, int value);
+void storePair(CompilationUnit *cUnit, int base, int lowReg,
+               int highReg);
+void loadPair(CompilationUnit *cUnit, int base, int lowReg, int highReg);
+MipsLIR *loadWordDisp(CompilationUnit *cUnit, int rBase, int displacement,
+                      int rDest);
+MipsLIR *storeWordDisp(CompilationUnit *cUnit, int rBase,
+                       int displacement, int rSrc);
+MipsLIR *loadConstant(CompilationUnit *cUnit, int rDest, int value);
 
 #ifdef __mips_hard_float
-static MipsLIR *fpRegCopy(CompilationUnit *cUnit, int rDest, int rSrc)
+MipsLIR *fpRegCopy(CompilationUnit *cUnit, int rDest, int rSrc)
 {
     MipsLIR* res = (MipsLIR *) oatNew(cUnit, sizeof(MipsLIR), true, kAllocLIR);
     res->operands[0] = rDest;
@@ -94,8 +90,8 @@
  * 1) rDest is freshly returned from oatAllocTemp or
  * 2) The codegen is under fixed register usage
  */
-static MipsLIR *loadConstantNoClobber(CompilationUnit *cUnit, int rDest,
-                                     int value)
+MipsLIR *loadConstantNoClobber(CompilationUnit *cUnit, int rDest,
+                               int value)
 {
     MipsLIR *res;
 
@@ -135,7 +131,7 @@
  * Load an immediate value into a fixed or temp register.  Target
  * register is clobbered, and marked inUse.
  */
-static MipsLIR *loadConstant(CompilationUnit *cUnit, int rDest, int value)
+MipsLIR *loadConstant(CompilationUnit *cUnit, int rDest, int value)
 {
     if (oatIsTemp(cUnit, rDest)) {
         oatClobber(cUnit, rDest);
@@ -144,24 +140,7 @@
     return loadConstantNoClobber(cUnit, rDest, value);
 }
 
-/*
- * Load a class pointer value into a fixed or temp register.  Target
- * register is clobbered, and marked inUse.
- */
-static MipsLIR *loadClassPointer(CompilationUnit *cUnit, int rDest, int value)
-{
-    MipsLIR *res;
-    if (oatIsTemp(cUnit, rDest)) {
-        oatClobber(cUnit, rDest);
-        oatMarkInUse(cUnit, rDest);
-    }
-    res = newLIR2(cUnit, kMipsLui, rDest, value>>16);
-    if (value & 0xffff)
-        newLIR3(cUnit, kMipsOri, rDest, rDest, value);
-    return res;
-}
-
-static MipsLIR *opNone(CompilationUnit *cUnit, OpKind op)
+MipsLIR *opNone(CompilationUnit *cUnit, OpKind op)
 {
     MipsLIR *res;
     MipsOpCode opcode = kMipsNop;
@@ -176,7 +155,27 @@
     return res;
 }
 
-static MipsLIR *opCompareBranch(CompilationUnit *cUnit, MipsOpCode opc, int rs, int rt)
+
+MipsLIR *opCmpBranchCC(CompilationUnit *cUnit, MipsConditionCode cc,
+                           int rs, int rt)
+{
+    UNIMPLEMENTED(FATAL);
+    return 0;
+}
+MipsLIR *opCmpImmBranchCC(CompilationUnit *cUnit, MipsConditionCode cc,
+                           int rs, int immVal)
+{
+    UNIMPLEMENTED(FATAL);
+    return 0;
+}
+MipsLIR *opCmpImmBranch(CompilationUnit *cUnit, MipsOpCode cc,
+                           int rs, int immVal)
+{
+    UNIMPLEMENTED(FATAL);
+    return 0;
+}
+
+MipsLIR *opCmpBranch(CompilationUnit *cUnit, MipsOpCode opc, int rs, int rt)
 {
     MipsLIR *res;
     if (rt < 0) {
@@ -189,9 +188,9 @@
     return res;
 }
 
-static MipsLIR *loadMultiple(CompilationUnit *cUnit, int rBase, int rMask);
+MipsLIR *loadMultiple(CompilationUnit *cUnit, int rBase, int rMask);
 
-static MipsLIR *opReg(CompilationUnit *cUnit, OpKind op, int rDestSrc)
+MipsLIR *opReg(CompilationUnit *cUnit, OpKind op, int rDestSrc)
 {
     MipsOpCode opcode = kMipsNop;
     switch (op) {
@@ -204,8 +203,8 @@
     return newLIR2(cUnit, opcode, r_RA, rDestSrc);
 }
 
-static MipsLIR *opRegRegImm(CompilationUnit *cUnit, OpKind op, int rDest,
-                           int rSrc1, int value);
+MipsLIR *opRegRegImm(CompilationUnit *cUnit, OpKind op, int rDest,
+                     int rSrc1, int value);
 MipsLIR *opRegImm(CompilationUnit *cUnit, OpKind op, int rDestSrc1,
                   int value)
 {
@@ -238,7 +237,7 @@
     return res;
 }
 
-static MipsLIR *opRegRegReg(CompilationUnit *cUnit, OpKind op, int rDest,
+MipsLIR *opRegRegReg(CompilationUnit *cUnit, OpKind op, int rDest,
                            int rSrc1, int rSrc2)
 {
     MipsOpCode opcode = kMipsNop;
@@ -277,7 +276,7 @@
     return newLIR3(cUnit, opcode, rDest, rSrc1, rSrc2);
 }
 
-static MipsLIR *opRegRegImm(CompilationUnit *cUnit, OpKind op, int rDest,
+MipsLIR *opRegRegImm(CompilationUnit *cUnit, OpKind op, int rDest,
                            int rSrc1, int value)
 {
     MipsLIR *res;
@@ -412,7 +411,7 @@
     return newLIR2(cUnit, opcode, rDestSrc1, rSrc2);
 }
 
-static MipsLIR *loadConstantValueWide(CompilationUnit *cUnit, int rDestLo,
+MipsLIR *loadConstantValueWide(CompilationUnit *cUnit, int rDestLo,
                                      int rDestHi, int valLo, int valHi)
 {
     MipsLIR *res;
@@ -422,7 +421,7 @@
 }
 
 /* Load value from base + scaled index. */
-static MipsLIR *loadBaseIndexed(CompilationUnit *cUnit, int rBase,
+MipsLIR *loadBaseIndexed(CompilationUnit *cUnit, int rBase,
                                int rIndex, int rDest, int scale, OpSize size)
 {
     MipsLIR *first = NULL;
@@ -479,7 +478,7 @@
 }
 
 /* store value base base + scaled index. */
-static MipsLIR *storeBaseIndexed(CompilationUnit *cUnit, int rBase,
+MipsLIR *storeBaseIndexed(CompilationUnit *cUnit, int rBase,
                                 int rIndex, int rSrc, int scale, OpSize size)
 {
     MipsLIR *first = NULL;
@@ -531,7 +530,7 @@
     return first;
 }
 
-static MipsLIR *loadMultiple(CompilationUnit *cUnit, int rBase, int rMask)
+MipsLIR *loadMultiple(CompilationUnit *cUnit, int rBase, int rMask)
 {
     int i;
     int loadCnt = 0;
@@ -553,7 +552,7 @@
     return res; /* NULL always returned which should be ok since no callers use it */
 }
 
-static MipsLIR *storeMultiple(CompilationUnit *cUnit, int rBase, int rMask)
+MipsLIR *storeMultiple(CompilationUnit *cUnit, int rBase, int rMask)
 {
     int i;
     int storeCnt = 0;
@@ -575,7 +574,7 @@
     return res; /* NULL always returned which should be ok since no callers use it */
 }
 
-static MipsLIR *loadBaseDispBody(CompilationUnit *cUnit, MIR *mir, int rBase,
+MipsLIR *loadBaseDispBody(CompilationUnit *cUnit, MIR *mir, int rBase,
                                 int displacement, int rDest, int rDestHi,
                                 OpSize size, int sReg)
 /*
@@ -681,7 +680,7 @@
     return load;
 }
 
-static MipsLIR *loadBaseDisp(CompilationUnit *cUnit, MIR *mir, int rBase,
+MipsLIR *loadBaseDisp(CompilationUnit *cUnit, MIR *mir, int rBase,
                             int displacement, int rDest, OpSize size,
                             int sReg)
 {
@@ -689,15 +688,15 @@
                             size, sReg);
 }
 
-static MipsLIR *loadBaseDispWide(CompilationUnit *cUnit, MIR *mir, int rBase,
-                                int displacement, int rDestLo, int rDestHi,
+MipsLIR *loadBaseDispWide(CompilationUnit *cUnit, MIR *mir, int rBase,
+                          int displacement, int rDestLo, int rDestHi,
                                 int sReg)
 {
     return loadBaseDispBody(cUnit, mir, rBase, displacement, rDestLo, rDestHi,
                             kLong, sReg);
 }
 
-static MipsLIR *storeBaseDispBody(CompilationUnit *cUnit, int rBase,
+MipsLIR *storeBaseDispBody(CompilationUnit *cUnit, int rBase,
                                  int displacement, int rSrc, int rSrcHi,
                                  OpSize size)
 {
@@ -786,31 +785,25 @@
     return res;
 }
 
-static MipsLIR *storeBaseDisp(CompilationUnit *cUnit, int rBase,
-                             int displacement, int rSrc, OpSize size)
+MipsLIR *storeBaseDisp(CompilationUnit *cUnit, int rBase,
+                       int displacement, int rSrc, OpSize size)
 {
     return storeBaseDispBody(cUnit, rBase, displacement, rSrc, -1, size);
 }
 
-static MipsLIR *storeBaseDispWide(CompilationUnit *cUnit, int rBase,
-                                 int displacement, int rSrcLo, int rSrcHi)
+MipsLIR *storeBaseDispWide(CompilationUnit *cUnit, int rBase,
+                           int displacement, int rSrcLo, int rSrcHi)
 {
     return storeBaseDispBody(cUnit, rBase, displacement, rSrcLo, rSrcHi, kLong);
 }
 
-static void storePair(CompilationUnit *cUnit, int base, int lowReg, int highReg)
-{
-    storeWordDisp(cUnit, base, LOWORD_OFFSET, lowReg);
-    storeWordDisp(cUnit, base, HIWORD_OFFSET, highReg);
-}
-
-static void loadPair(CompilationUnit *cUnit, int base, int lowReg, int highReg)
+void loadPair(CompilationUnit *cUnit, int base, int lowReg, int highReg)
 {
     loadWordDisp(cUnit, base, LOWORD_OFFSET , lowReg);
     loadWordDisp(cUnit, base, HIWORD_OFFSET , highReg);
 }
 
-static MipsLIR* genRegCopyNoInsert(CompilationUnit *cUnit, int rDest, int rSrc)
+MipsLIR* genRegCopyNoInsert(CompilationUnit *cUnit, int rDest, int rSrc)
 {
     MipsLIR* res;
     MipsOpCode opcode;
@@ -831,14 +824,14 @@
     return res;
 }
 
-static MipsLIR* genRegCopy(CompilationUnit *cUnit, int rDest, int rSrc)
+MipsLIR* genRegCopy(CompilationUnit *cUnit, int rDest, int rSrc)
 {
     MipsLIR *res = genRegCopyNoInsert(cUnit, rDest, rSrc);
     oatAppendLIR(cUnit, (LIR*)res);
     return res;
 }
 
-static void genRegCopyWide(CompilationUnit *cUnit, int destLo, int destHi,
+void genRegCopyWide(CompilationUnit *cUnit, int destLo, int destHi,
                            int srcLo, int srcHi)
 {
 #ifdef __mips_hard_float
@@ -881,10 +874,10 @@
 #endif
 }
 
-static inline MipsLIR *genRegImmCheck(CompilationUnit *cUnit,
-                                     MipsConditionCode cond, int reg,
-                                     int checkValue, int dOffset,
-                                     MipsLIR *pcrLabel)
+inline MipsLIR *genRegImmCheck(CompilationUnit *cUnit,
+                               MipsConditionCode cond, int reg,
+                               int checkValue, int dOffset,
+                               MipsLIR *pcrLabel)
 {
     MipsLIR *branch = NULL;
 
diff --git a/src/compiler/codegen/mips/Mips32/Gen.cc b/src/compiler/codegen/mips/Mips32/Gen.cc
index f49cdab..8801692 100644
--- a/src/compiler/codegen/mips/Mips32/Gen.cc
+++ b/src/compiler/codegen/mips/Mips32/Gen.cc
@@ -62,10 +62,192 @@
 bool genArithOpIntLit(CompilationUnit* cUnit, MIR* mir,
                              RegLocation rlDest, RegLocation rlSrc,
                              int lit) { return 0; }
+void oatArchDump(void) {};
+void genDebuggerUpdate(CompilationUnit* cUnit, int32_t offset) {};
 
 
 
 
+STATIC bool genConversionCall(CompilationUnit* cUnit, MIR* mir, int funcOffset,
+                                     int srcSize, int tgtSize)
+{
+    UNIMPLEMENTED(FATAL) << "Need Mips implementation";
+    return 0;
+#if 0
+    /*
+     * Don't optimize the register usage since it calls out to support
+     * functions
+     */
+    RegLocation rlSrc;
+    RegLocation rlDest;
+    oatFlushAllRegs(cUnit);   /* Send everything to home location */
+    loadWordDisp(cUnit, rSELF, funcOffset, rLR);
+    if (srcSize == 1) {
+        rlSrc = oatGetSrc(cUnit, mir, 0);
+        loadValueDirectFixed(cUnit, rlSrc, r0);
+    } else {
+        rlSrc = oatGetSrcWide(cUnit, mir, 0, 1);
+        loadValueDirectWideFixed(cUnit, rlSrc, r0, r1);
+    }
+    callRuntimeHelper(cUnit, rLR);
+    if (tgtSize == 1) {
+        RegLocation rlResult;
+        rlDest = oatGetDest(cUnit, mir, 0);
+        rlResult = oatGetReturn(cUnit);
+        storeValue(cUnit, rlDest, rlResult);
+    } else {
+        RegLocation rlResult;
+        rlDest = oatGetDestWide(cUnit, mir, 0, 1);
+        rlResult = oatGetReturnWide(cUnit);
+        storeValueWide(cUnit, rlDest, rlResult);
+    }
+    return false;
+#endif
+}
+
+bool genArithOpFloatPortable(CompilationUnit* cUnit, MIR* mir,
+                                    RegLocation rlDest, RegLocation rlSrc1,
+                                    RegLocation rlSrc2)
+{
+    UNIMPLEMENTED(FATAL) << "Need Mips implementation";
+    return 0;
+#if 0
+    RegLocation rlResult;
+    int funcOffset;
+
+    switch (mir->dalvikInsn.opcode) {
+        case OP_ADD_FLOAT_2ADDR:
+        case OP_ADD_FLOAT:
+            funcOffset = OFFSETOF_MEMBER(Thread, pFadd);
+            break;
+        case OP_SUB_FLOAT_2ADDR:
+        case OP_SUB_FLOAT:
+            funcOffset = OFFSETOF_MEMBER(Thread, pFsub);
+            break;
+        case OP_DIV_FLOAT_2ADDR:
+        case OP_DIV_FLOAT:
+            funcOffset = OFFSETOF_MEMBER(Thread, pFdiv);
+            break;
+        case OP_MUL_FLOAT_2ADDR:
+        case OP_MUL_FLOAT:
+            funcOffset = OFFSETOF_MEMBER(Thread, pFmul);
+            break;
+        case OP_REM_FLOAT_2ADDR:
+        case OP_REM_FLOAT:
+            funcOffset = OFFSETOF_MEMBER(Thread, pFmodf);
+            break;
+        case OP_NEG_FLOAT: {
+            genNegFloat(cUnit, rlDest, rlSrc1);
+            return false;
+        }
+        default:
+            return true;
+    }
+    oatFlushAllRegs(cUnit);   /* Send everything to home location */
+    loadWordDisp(cUnit, rSELF, funcOffset, rLR);
+    loadValueDirectFixed(cUnit, rlSrc1, r0);
+    loadValueDirectFixed(cUnit, rlSrc2, r1);
+    callRuntimeHelper(cUnit, rLR);
+    rlResult = oatGetReturn(cUnit);
+    storeValue(cUnit, rlDest, rlResult);
+    return false;
+#endif
+}
+
+bool genArithOpDoublePortable(CompilationUnit* cUnit, MIR* mir,
+                                     RegLocation rlDest, RegLocation rlSrc1,
+                                     RegLocation rlSrc2)
+{
+    UNIMPLEMENTED(FATAL) << "Need Mips implementation";
+    return 0;
+#if 0
+    RegLocation rlResult;
+    int funcOffset;
+
+    switch (mir->dalvikInsn.opcode) {
+        case OP_ADD_DOUBLE_2ADDR:
+        case OP_ADD_DOUBLE:
+            funcOffset = OFFSETOF_MEMBER(Thread, pDadd);
+            break;
+        case OP_SUB_DOUBLE_2ADDR:
+        case OP_SUB_DOUBLE:
+            funcOffset = OFFSETOF_MEMBER(Thread, pDsub);
+            break;
+        case OP_DIV_DOUBLE_2ADDR:
+        case OP_DIV_DOUBLE:
+            funcOffset = OFFSETOF_MEMBER(Thread, pDdiv);
+            break;
+        case OP_MUL_DOUBLE_2ADDR:
+        case OP_MUL_DOUBLE:
+            funcOffset = OFFSETOF_MEMBER(Thread, pDmul);
+            break;
+        case OP_REM_DOUBLE_2ADDR:
+        case OP_REM_DOUBLE:
+            funcOffset = OFFSETOF_MEMBER(Thread, pFmod);
+            break;
+        case OP_NEG_DOUBLE: {
+            genNegDouble(cUnit, rlDest, rlSrc1);
+            return false;
+        }
+        default:
+            return true;
+    }
+    oatFlushAllRegs(cUnit);   /* Send everything to home location */
+    loadWordDisp(cUnit, rSELF, funcOffset, rLR);
+    loadValueDirectWideFixed(cUnit, rlSrc1, r0, r1);
+    loadValueDirectWideFixed(cUnit, rlSrc2, r2, r3);
+    callRuntimeHelper(cUnit, rLR);
+    rlResult = oatGetReturnWide(cUnit);
+    storeValueWide(cUnit, rlDest, rlResult);
+    return false;
+#endif
+}
+
+bool genConversionPortable(CompilationUnit* cUnit, MIR* mir)
+{
+    UNIMPLEMENTED(FATAL) << "Need Mips implementation";
+    return 0;
+#if 0
+    Opcode opcode = mir->dalvikInsn.opcode;
+
+    switch (opcode) {
+        case OP_INT_TO_FLOAT:
+            return genConversionCall(cUnit, mir, OFFSETOF_MEMBER(Thread, pI2f),
+                                     1, 1);
+        case OP_FLOAT_TO_INT:
+            return genConversionCall(cUnit, mir, OFFSETOF_MEMBER(Thread, pF2iz),
+                                     1, 1);
+        case OP_DOUBLE_TO_FLOAT:
+            return genConversionCall(cUnit, mir, OFFSETOF_MEMBER(Thread, pD2f),
+                                     2, 1);
+        case OP_FLOAT_TO_DOUBLE:
+            return genConversionCall(cUnit, mir, OFFSETOF_MEMBER(Thread, pF2d),
+                                     1, 2);
+        case OP_INT_TO_DOUBLE:
+            return genConversionCall(cUnit, mir, OFFSETOF_MEMBER(Thread, pI2d),
+                                     1, 2);
+        case OP_DOUBLE_TO_INT:
+            return genConversionCall(cUnit, mir, OFFSETOF_MEMBER(Thread, pD2iz),
+                                     2, 1);
+        case OP_FLOAT_TO_LONG:
+            return genConversionCall(cUnit, mir, OFFSETOF_MEMBER(Thread,
+                                     pF2l), 1, 2);
+        case OP_LONG_TO_FLOAT:
+            return genConversionCall(cUnit, mir, OFFSETOF_MEMBER(Thread, pL2f),
+                                     2, 1);
+        case OP_DOUBLE_TO_LONG:
+            return genConversionCall(cUnit, mir, OFFSETOF_MEMBER(Thread,
+                                     pD2l), 2, 2);
+        case OP_LONG_TO_DOUBLE:
+            return genConversionCall(cUnit, mir, OFFSETOF_MEMBER(Thread, pL2d),
+                                     2, 2);
+        default:
+            return true;
+    }
+    return false;
+#endif
+}
+
 
 
 
@@ -102,7 +284,7 @@
 }
 #endif
 /*
- * Insert a kMipsPseudoCaseLabel at the beginning of the Dalvik
+ * Insert a kPseudoCaseLabel at the beginning of the Dalvik
  * offset vaddr.  This label will be used to fix up the case
  * branch table during the assembly phase.  Be sure to set
  * all resource flags on this to prevent code motion across
@@ -117,7 +299,7 @@
     }
     MipsLIR* newLabel = (MipsLIR*)oatNew(cUnit, sizeof(MipsLIR), true, kAllocLIR);
     newLabel->generic.dalvikOffset = vaddr;
-    newLabel->opcode = kMipsPseudoCaseLabel;
+    newLabel->opcode = kPseudoCaseLabel;
     newLabel->operands[0] = keyVal;
     oatInsertLIRAfter(it->second, (LIR*)newLabel);
     return newLabel;
@@ -269,7 +451,7 @@
     int rIdx = oatAllocTemp(cUnit);
     loadConstant(cUnit, rIdx, size);
     // Establish loop branch target
-    MipsLIR* target = newLIR0(cUnit, kMipsPseudoTargetLabel);
+    MipsLIR* target = newLIR0(cUnit, kPseudoTargetLabel);
     target->defMask = ENCODE_ALL;
     // Load next key/disp
     newLIR2(cUnit, kThumb2LdmiaWB, rBase, (1 << rKey) | (1 << rDisp));
@@ -331,7 +513,7 @@
     tabRec->bxInst = switchBranch;
 
     /* branchOver target here */
-    MipsLIR* target = newLIR0(cUnit, kMipsPseudoTargetLabel);
+    MipsLIR* target = newLIR0(cUnit, kPseudoTargetLabel);
     target->defMask = ENCODE_ALL;
     branchOver->generic.target = (LIR*)target;
 #endif
diff --git a/src/compiler/codegen/mips/MipsLIR.h b/src/compiler/codegen/mips/MipsLIR.h
index a6f426e..44f0c5a 100644
--- a/src/compiler/codegen/mips/MipsLIR.h
+++ b/src/compiler/codegen/mips/MipsLIR.h
@@ -193,42 +193,6 @@
 #define DECODE_ALIAS_INFO_REG(X)        (X & 0xffff)
 #define DECODE_ALIAS_INFO_WIDE(X)       ((X & 0x80000000) ? 1 : 0)
 
-typedef enum OpKind {
-    kOpMov,
-    kOpMvn,
-    kOpCmp,
-    kOpLsl,
-    kOpLsr,
-    kOpAsr,
-    kOpRor,
-    kOpNot,
-    kOpAnd,
-    kOpOr,
-    kOpXor,
-    kOpNeg,
-    kOpAdd,
-    kOpAdc,
-    kOpSub,
-    kOpSbc,
-    kOpRsub,
-    kOpMul,
-    kOpDiv,
-    kOpRem,
-    kOpBic,
-    kOpCmn,
-    kOpTst,
-    kOpBkpt,
-    kOpBlx,
-    kOpPush,
-    kOpPop,
-    kOp2Char,
-    kOp2Short,
-    kOp2Byte,
-    kOpCondBr,
-    kOpUncondBr,
-    kOpInvalid,
-} OpKind;
-
 /*
  * FIXME:
  * Originally had r4PC as r_S0, rFP as r_S1, rSELF as r_S2, rINST as r_S4
@@ -240,8 +204,13 @@
 #define rSELF r_S1
 #define rSP r_SP
 
-/* FIXME: don't do this - find and fix all rLR's */
-#define rLR r_RA
+#define rARG0 r_ARG0
+#define rARG1 r_ARG1
+#define rARG2 r_ARG2
+#define rARG3 r_ARG3
+
+#define rRET0 r_V0
+#define rRET1 r_V1
 
 /*
  * Annotate special-purpose core registers:
@@ -376,7 +345,7 @@
     kMipsThrowStackOverflow,
 } MipsThrowKind;
 
-#define isPseudoOpCode(opCode) ((int)(opCode) < 0)
+#define isPseudoOpcode(opCode) ((int)(opCode) < 0)
 
 /*
  * The following enum defines the list of supported Thumb instructions by the
@@ -384,21 +353,21 @@
  * Assemble.c.
  */
 typedef enum MipsOpCode {
-    kMipsPseudoSuspendTarget = -15,
-    kMipsPseudoThrowTarget = -14,
-    kMipsPseudoCaseLabel = -13,
-    kMipsPseudoMethodEntry = -12,
-    kMipsPseudoMethodExit = -11,
-    kMipsPseudoBarrier = -10,
-    kMipsPseudoExtended = -9,
-    kMipsPseudoSSARep = -8,
-    kMipsPseudoEntryBlock = -7,
-    kMipsPseudoExitBlock = -6,
-    kMipsPseudoTargetLabel = -5,
-    kMipsPseudoDalvikByteCodeBoundary = -4,
-    kMipsPseudoPseudoAlign4 = -3,
-    kMipsPseudoEHBlockLabel = -2,
-    kMipsPseudoNormalBlockLabel = -1,
+    kPseudoSuspendTarget = -15,
+    kPseudoThrowTarget = -14,
+    kPseudoCaseLabel = -13,
+    kPseudoMethodEntry = -12,
+    kPseudoMethodExit = -11,
+    kPseudoBarrier = -10,
+    kPseudoExtended = -9,
+    kPseudoSSARep = -8,
+    kPseudoEntryBlock = -7,
+    kPseudoExitBlock = -6,
+    kPseudoTargetLabel = -5,
+    kPseudoDalvikByteCodeBoundary = -4,
+    kPseudoPseudoAlign4 = -3,
+    kPseudoEHBlockLabel = -2,
+    kPseudoNormalBlockLabel = -1,
 
     kMipsFirst,
     kMips32BitData = kMipsFirst, /* data [31..0] */
diff --git a/src/compiler/codegen/mips/MipsRallocUtil.cc b/src/compiler/codegen/mips/MipsRallocUtil.cc
index a243415..0dfbfa5 100644
--- a/src/compiler/codegen/mips/MipsRallocUtil.cc
+++ b/src/compiler/codegen/mips/MipsRallocUtil.cc
@@ -28,12 +28,24 @@
 namespace art {
 
 /*
+ * TUNING: is leaf?  Can't just use "hasInvoke" to determine as some
+ * instructions might call out to C/assembly helper functions.  Until
+ * machinery is in place, always spill lr.
+ */
+
+void oatAdjustSpillMask(CompilationUnit* cUnit)
+{
+    cUnit->coreSpillMask |= (1 << r_RA);
+    cUnit->numCoreSpills++;
+}
+
+/*
  * Mark a callee-save fp register as promoted.  Note that
  * vpush/vpop uses contiguous register lists so we must
  * include any holes in the mask.  Associate holes with
  * Dalvik register INVALID_VREG (0xFFFFU).
  */
-STATIC void markPreservedSingle(CompilationUnit* cUnit, int sReg, int reg)
+void oatMarkPreservedSingle(CompilationUnit* cUnit, int sReg, int reg)
 {
     UNIMPLEMENTED(FATAL) << "No support yet for promoted FP regs";
 #if 0
@@ -206,4 +218,10 @@
     oatFreeTemp(cUnit, r_A3);
 }
 
+/* Convert an instruction to a NOP */
+STATIC void oatNopLIR( LIR* lir)
+{
+    ((MipsLIR*)lir)->flags.isNop = true;
+}
+
 }  // namespace art
diff --git a/src/compiler/codegen/mips/mips/ArchVariant.cc b/src/compiler/codegen/mips/mips/ArchVariant.cc
index 5eca74b..dd46f24 100644
--- a/src/compiler/codegen/mips/mips/ArchVariant.cc
+++ b/src/compiler/codegen/mips/mips/ArchVariant.cc
@@ -25,9 +25,9 @@
  * Determine the initial instruction set to be used for this trace.
  * Later components may decide to change this.
  */
-JitInstructionSetType oatInstructionSet(void)
+OatInstructionSetType oatInstructionSet(void)
 {
-    return DALVIK_OAT_MIPS;
+    return DALVIK_OAT_MIPS32;
 }
 
 /* Architecture-specific initializations and checks go here */
diff --git a/src/compiler/codegen/mips/mips/Codegen.cc b/src/compiler/codegen/mips/mips/Codegen.cc
index 2b71b04..22a7c94 100644
--- a/src/compiler/codegen/mips/mips/Codegen.cc
+++ b/src/compiler/codegen/mips/mips/Codegen.cc
@@ -17,9 +17,6 @@
 #define _CODEGEN_C
 #define TGT_LIR MipsLIR
 
-/* For testing */
-#define __mips_hard_float
-
 #include "../../../Dalvik.h"
 #include "../../../CompilerInternals.h"
 #include "../MipsLIR.h"