Refactor callRuntimeHelper

Change-Id: I87c5f592a931c98c4b5b693b72216f4e71990162
diff --git a/src/compiler/codegen/GenCommon.cc b/src/compiler/codegen/GenCommon.cc
index 34d9fb9..52ff3d7 100644
--- a/src/compiler/codegen/GenCommon.cc
+++ b/src/compiler/codegen/GenCommon.cc
@@ -26,13 +26,267 @@
 LIR* opIT(CompilationUnit* cUnit, ArmConditionCode cond, const char* guide);
 #endif
 
-LIR* callRuntimeHelper(CompilationUnit* cUnit, int reg_or_offset)
-{
+void callRuntimeHelperImm(CompilationUnit* cUnit, int helperOffset, int arg0) {
+#if !defined(TARGET_X86)
+    int rTgt = loadHelper(cUnit, helperOffset);
+#endif
+    loadConstant(cUnit, rARG0, arg0);
     oatClobberCalleeSave(cUnit);
 #if !defined(TARGET_X86)
-    return opReg(cUnit, kOpBlx, reg_or_offset);
+    opReg(cUnit, kOpBlx, rTgt);
+    oatFreeTemp(cUnit, rTgt);
 #else
-    return opThreadMem(cUnit, kOpBlx, reg_or_offset);
+    opThreadMem(cUnit, kOpBlx, helperOffset);
+#endif
+}
+
+void callRuntimeHelperRegLocation(CompilationUnit* cUnit, int helperOffset,
+                                  RegLocation arg0) {
+#if !defined(TARGET_X86)
+    int rTgt = loadHelper(cUnit, helperOffset);
+#endif
+    if (arg0.wide == 0) {
+        loadValueDirectFixed(cUnit, arg0, rARG0);
+    } else {
+        loadValueDirectWideFixed(cUnit, arg0, rARG0, rARG1);
+    }
+    oatClobberCalleeSave(cUnit);
+#if !defined(TARGET_X86)
+    opReg(cUnit, kOpBlx, rTgt);
+    oatFreeTemp(cUnit, rTgt);
+#else
+    opThreadMem(cUnit, kOpBlx, helperOffset);
+#endif
+}
+
+void callRuntimeHelperImmImm(CompilationUnit* cUnit, int helperOffset,
+                             int arg0, int arg1) {
+#if !defined(TARGET_X86)
+    int rTgt = loadHelper(cUnit, helperOffset);
+#endif
+    loadConstant(cUnit, rARG0, arg0);
+    loadConstant(cUnit, rARG1, arg1);
+    oatClobberCalleeSave(cUnit);
+#if !defined(TARGET_X86)
+    opReg(cUnit, kOpBlx, rTgt);
+    oatFreeTemp(cUnit, rTgt);
+#else
+    opThreadMem(cUnit, kOpBlx, helperOffset);
+#endif
+}
+
+void callRuntimeHelperImmRegLocation(CompilationUnit* cUnit, int helperOffset,
+                                     int arg0, RegLocation arg1) {
+#if !defined(TARGET_X86)
+    int rTgt = loadHelper(cUnit, helperOffset);
+#endif
+    if (arg1.wide == 0) {
+        loadValueDirectFixed(cUnit, arg1, rARG1);
+    } else {
+        loadValueDirectWideFixed(cUnit, arg1, rARG1, rARG2);
+    }
+    loadConstant(cUnit, rARG0, arg0);
+    oatClobberCalleeSave(cUnit);
+#if !defined(TARGET_X86)
+    opReg(cUnit, kOpBlx, rTgt);
+    oatFreeTemp(cUnit, rTgt);
+#else
+    opThreadMem(cUnit, kOpBlx, helperOffset);
+#endif
+}
+
+void callRuntimeHelperRegLocationImm(CompilationUnit* cUnit, int helperOffset,
+                                     RegLocation arg0, int arg1) {
+#if !defined(TARGET_X86)
+    int rTgt = loadHelper(cUnit, helperOffset);
+#endif
+    loadValueDirectFixed(cUnit, arg0, rARG0);
+    loadConstant(cUnit, rARG1, arg1);
+    oatClobberCalleeSave(cUnit);
+#if !defined(TARGET_X86)
+    opReg(cUnit, kOpBlx, rTgt);
+    oatFreeTemp(cUnit, rTgt);
+#else
+    opThreadMem(cUnit, kOpBlx, helperOffset);
+#endif
+}
+
+void callRuntimeHelperImmReg(CompilationUnit* cUnit, int helperOffset,
+                             int arg0, int arg1) {
+#if !defined(TARGET_X86)
+    int rTgt = loadHelper(cUnit, helperOffset);
+#endif
+    opRegCopy(cUnit, rARG1, arg1);
+    loadConstant(cUnit, rARG0, arg0);
+    oatClobberCalleeSave(cUnit);
+#if !defined(TARGET_X86)
+    opReg(cUnit, kOpBlx, rTgt);
+    oatFreeTemp(cUnit, rTgt);
+#else
+    opThreadMem(cUnit, kOpBlx, helperOffset);
+#endif
+}
+
+void callRuntimeHelperRegImm(CompilationUnit* cUnit, int helperOffset,
+                             int arg0, int arg1) {
+#if !defined(TARGET_X86)
+    int rTgt = loadHelper(cUnit, helperOffset);
+#endif
+    opRegCopy(cUnit, rARG0, arg0);
+    loadConstant(cUnit, rARG1, arg1);
+    oatClobberCalleeSave(cUnit);
+#if !defined(TARGET_X86)
+    opReg(cUnit, kOpBlx, rTgt);
+    oatFreeTemp(cUnit, rTgt);
+#else
+    opThreadMem(cUnit, kOpBlx, helperOffset);
+#endif
+}
+
+void callRuntimeHelperImmMethod(CompilationUnit* cUnit, int helperOffset,
+                                int arg0) {
+#if !defined(TARGET_X86)
+    int rTgt = loadHelper(cUnit, helperOffset);
+#endif
+    loadCurrMethodDirect(cUnit, rARG1);
+    loadConstant(cUnit, rARG0, arg0);
+    oatClobberCalleeSave(cUnit);
+#if !defined(TARGET_X86)
+    opReg(cUnit, kOpBlx, rTgt);
+    oatFreeTemp(cUnit, rTgt);
+#else
+    opThreadMem(cUnit, kOpBlx, helperOffset);
+#endif
+}
+
+void callRuntimeHelperRegLocationRegLocation(CompilationUnit* cUnit,
+                                             int helperOffset,
+                                             RegLocation arg0,
+                                             RegLocation arg1) {
+#if !defined(TARGET_X86)
+    int rTgt = loadHelper(cUnit, helperOffset);
+#endif
+    if (arg0.wide == 0) {
+        loadValueDirectFixed(cUnit, arg0, rARG0);
+        if (arg1.wide == 0) {
+            loadValueDirectFixed(cUnit, arg1, rARG1);
+        } else {
+            loadValueDirectWideFixed(cUnit, arg1, rARG1, rARG2);
+        }
+    } else {
+        loadValueDirectWideFixed(cUnit, arg0, rARG0, rARG1);
+        if (arg1.wide == 0) {
+            loadValueDirectFixed(cUnit, arg1, rARG2);
+        } else {
+#if defined(TARGET_X86)
+            UNIMPLEMENTED(FATAL);
+#else
+            loadValueDirectWideFixed(cUnit, arg1, rARG2, rARG3);
+#endif
+        }
+    }
+    oatClobberCalleeSave(cUnit);
+#if !defined(TARGET_X86)
+    opReg(cUnit, kOpBlx, rTgt);
+    oatFreeTemp(cUnit, rTgt);
+#else
+    opThreadMem(cUnit, kOpBlx, helperOffset);
+#endif
+}
+
+void callRuntimeHelperRegReg(CompilationUnit* cUnit, int helperOffset,
+                             int arg0, int arg1) {
+#if !defined(TARGET_X86)
+    int rTgt = loadHelper(cUnit, helperOffset);
+#endif
+    DCHECK_NE((int)rARG0, arg1);  // check copy into arg0 won't clobber arg1
+    opRegCopy(cUnit, rARG0, arg0);
+    opRegCopy(cUnit, rARG1, arg1);
+    oatClobberCalleeSave(cUnit);
+#if !defined(TARGET_X86)
+    opReg(cUnit, kOpBlx, rTgt);
+    oatFreeTemp(cUnit, rTgt);
+#else
+    opThreadMem(cUnit, kOpBlx, helperOffset);
+#endif
+}
+
+void callRuntimeHelperRegRegImm(CompilationUnit* cUnit, int helperOffset,
+                                int arg0, int arg1, int arg2) {
+#if !defined(TARGET_X86)
+    int rTgt = loadHelper(cUnit, helperOffset);
+#endif
+    DCHECK_NE((int)rARG0, arg1);  // check copy into arg0 won't clobber arg1
+    opRegCopy(cUnit, rARG0, arg0);
+    opRegCopy(cUnit, rARG1, arg1);
+    loadConstant(cUnit, rARG2, arg2);
+    oatClobberCalleeSave(cUnit);
+#if !defined(TARGET_X86)
+    opReg(cUnit, kOpBlx, rTgt);
+    oatFreeTemp(cUnit, rTgt);
+#else
+    opThreadMem(cUnit, kOpBlx, helperOffset);
+#endif
+}
+
+void callRuntimeHelperImmMethodRegLocation(CompilationUnit* cUnit, int helperOffset,
+                                           int arg0, RegLocation arg2) {
+#if !defined(TARGET_X86)
+    int rTgt = loadHelper(cUnit, helperOffset);
+#endif
+    loadValueDirectFixed(cUnit, arg2, rARG2);
+    loadCurrMethodDirect(cUnit, rARG1);
+    loadConstant(cUnit, rARG0, arg0);
+    oatClobberCalleeSave(cUnit);
+#if !defined(TARGET_X86)
+    opReg(cUnit, kOpBlx, rTgt);
+    oatFreeTemp(cUnit, rTgt);
+#else
+    opThreadMem(cUnit, kOpBlx, helperOffset);
+#endif
+}
+
+void callRuntimeHelperImmMethodImm(CompilationUnit* cUnit, int helperOffset,
+                                   int arg0, int arg2) {
+#if !defined(TARGET_X86)
+    int rTgt = loadHelper(cUnit, helperOffset);
+#endif
+    loadCurrMethodDirect(cUnit, rARG1);
+    loadConstant(cUnit, rARG2, arg2);
+    loadConstant(cUnit, rARG0, arg0);
+    oatClobberCalleeSave(cUnit);
+#if !defined(TARGET_X86)
+    opReg(cUnit, kOpBlx, rTgt);
+    oatFreeTemp(cUnit, rTgt);
+#else
+    opThreadMem(cUnit, kOpBlx, helperOffset);
+#endif
+}
+
+void callRuntimeHelperImmRegLocationRegLocation(CompilationUnit* cUnit,
+                                                int helperOffset,
+                                                int arg0, RegLocation arg1,
+                                                RegLocation arg2) {
+#if !defined(TARGET_X86)
+    int rTgt = loadHelper(cUnit, helperOffset);
+#endif
+    loadValueDirectFixed(cUnit, arg1, rARG1);
+    if (arg2.wide == 0) {
+        loadValueDirectFixed(cUnit, arg2, rARG2);
+    } else {
+#if defined(TARGET_X86)
+        UNIMPLEMENTED(FATAL);
+#else
+        loadValueDirectWideFixed(cUnit, arg2, rARG2, rARG3);
+#endif
+    }
+    loadConstant(cUnit, rARG0, arg0);
+    oatClobberCalleeSave(cUnit);
+#if !defined(TARGET_X86)
+    opReg(cUnit, kOpBlx, rTgt);
+    oatFreeTemp(cUnit, rTgt);
+#else
+    opThreadMem(cUnit, kOpBlx, helperOffset);
 #endif
 }
 
@@ -247,18 +501,7 @@
     } else {
         funcOffset= OFFSETOF_MEMBER(Thread, pAllocArrayFromCodeWithAccessCheck);
     }
-#if !defined(TARGET_X86)
-    int rTgt = loadHelper(cUnit, funcOffset);
-#endif
-    loadCurrMethodDirect(cUnit, rARG1);              // arg1 <- Method*
-    loadConstant(cUnit, rARG0, type_idx);            // arg0 <- type_id
-    loadValueDirectFixed(cUnit, rlSrc, rARG2);       // arg2 <- count
-#if !defined(TARGET_X86)
-    callRuntimeHelper(cUnit, rTgt);
-    oatFreeTemp(cUnit, rTgt);
-#else
-    callRuntimeHelper(cUnit, funcOffset);
-#endif
+    callRuntimeHelperImmMethodRegLocation(cUnit, funcOffset, type_idx, rlSrc);
     RegLocation rlResult = oatGetReturn(cUnit, false);
     storeValue(cUnit, rlDest, rlResult);
 }
@@ -273,30 +516,19 @@
 {
     DecodedInstruction* dInsn = &mir->dalvikInsn;
     int elems = dInsn->vA;
-    int typeId = dInsn->vB;
+    int typeIdx = dInsn->vB;
     oatFlushAllRegs(cUnit);    /* Everything to home location */
     int funcOffset;
     if (cUnit->compiler->CanAccessTypeWithoutChecks(cUnit->method_idx,
                                                     cUnit->dex_cache,
                                                     *cUnit->dex_file,
-                                                    typeId)) {
+                                                    typeIdx)) {
         funcOffset = OFFSETOF_MEMBER(Thread, pCheckAndAllocArrayFromCode);
     } else {
         funcOffset = OFFSETOF_MEMBER(Thread,
                                   pCheckAndAllocArrayFromCodeWithAccessCheck);
     }
-#if !defined(TARGET_X86)
-    int rTgt = loadHelper(cUnit, funcOffset);
-#endif
-    loadConstant(cUnit, rARG0, typeId);              // arg0 <- type_id
-    loadConstant(cUnit, rARG2, elems);               // arg2 <- count
-    loadCurrMethodDirect(cUnit, rARG1);              // arg1 <- Method*
-#if !defined(TARGET_X86)
-    callRuntimeHelper(cUnit, rTgt);
-    oatFreeTemp(cUnit, rTgt);
-#else
-    callRuntimeHelper(cUnit, funcOffset);
-#endif
+    callRuntimeHelperImmMethodImm(cUnit, funcOffset, typeIdx, elems);
     oatFreeTemp(cUnit, rARG2);
     oatFreeTemp(cUnit, rARG1);
     /*
@@ -436,17 +668,10 @@
             // or NULL if not initialized. Check for NULL and call helper if NULL.
             // TUNING: fast path should fall through
             LIR* branchOver = opCmpImmBranch(cUnit, kCondNe, rBase, 0, NULL);
-#if !defined(TARGET_X86)
-            int rTgt = loadHelper(cUnit, OFFSETOF_MEMBER(Thread,
-                                  pInitializeStaticStorage));
             loadConstant(cUnit, rARG0, ssbIndex);
-            callRuntimeHelper(cUnit, rTgt);
-            oatFreeTemp(cUnit, rTgt);
-#else
-            loadConstant(cUnit, rARG0, ssbIndex);
-            callRuntimeHelper(cUnit,
-                            OFFSETOF_MEMBER(Thread, pInitializeStaticStorage));
-#endif
+            callRuntimeHelperImm(cUnit,
+                                 OFFSETOF_MEMBER(Thread, pInitializeStaticStorage),
+                                 ssbIndex);
 #if defined(TARGET_MIPS)
             // For Arm, rRET0 = rARG0 = rBASE, for Mips, we need to copy
             opRegCopy(cUnit, rBase, rRET0);
@@ -485,25 +710,7 @@
         int setterOffset = isLongOrDouble ? OFFSETOF_MEMBER(Thread, pSet64Static) :
                            (isObject ? OFFSETOF_MEMBER(Thread, pSetObjStatic)
                                      : OFFSETOF_MEMBER(Thread, pSet32Static));
-#if !defined(TARGET_X86)
-        int rTgt = loadHelper(cUnit, setterOffset);
-#endif
-        loadConstant(cUnit, rARG0, fieldIdx);
-        if (isLongOrDouble) {
-#if defined(TARGET_X86)
-            UNIMPLEMENTED(FATAL);
-#else
-            loadValueDirectWideFixed(cUnit, rlSrc, rARG2, rARG3);
-#endif
-        } else {
-            loadValueDirect(cUnit, rlSrc, rARG1);
-        }
-#if !defined(TARGET_X86)
-        callRuntimeHelper(cUnit, rTgt);
-        oatFreeTemp(cUnit, rTgt);
-#else
-        callRuntimeHelper(cUnit, setterOffset);
-#endif
+        callRuntimeHelperImmRegLocation(cUnit, setterOffset, fieldIdx, rlSrc);
     }
 }
 
@@ -559,17 +766,9 @@
             // or NULL if not initialized. Check for NULL and call helper if NULL.
             // TUNING: fast path should fall through
             LIR* branchOver = opCmpImmBranch(cUnit, kCondNe, rBase, 0, NULL);
-#if !defined(TARGET_X86)
-            int rTgt = loadHelper(cUnit, OFFSETOF_MEMBER(Thread,
-                                  pInitializeStaticStorage));
-            loadConstant(cUnit, rARG0, ssbIndex);
-            callRuntimeHelper(cUnit, rTgt);
-            oatFreeTemp(cUnit, rTgt);
-#else
-            loadConstant(cUnit, rARG0, ssbIndex);
-            callRuntimeHelper(cUnit,
-                            OFFSETOF_MEMBER(Thread, pInitializeStaticStorage));
-#endif
+            callRuntimeHelperImm(cUnit,
+                                 OFFSETOF_MEMBER(Thread, pInitializeStaticStorage),
+                                 ssbIndex);
 #if defined(TARGET_MIPS)
             // For Arm, rRET0 = rARG0 = rBASE, for Mips, we need to copy
             opRegCopy(cUnit, rBase, rRET0);
@@ -602,15 +801,7 @@
         int getterOffset = isLongOrDouble ? OFFSETOF_MEMBER(Thread, pGet64Static) :
                            (isObject ? OFFSETOF_MEMBER(Thread, pGetObjStatic)
                                      : OFFSETOF_MEMBER(Thread, pGet32Static));
-#if !defined(TARGET_X86)
-        int rTgt = loadHelper(cUnit, getterOffset);
-        loadConstant(cUnit, rARG0, fieldIdx);
-        callRuntimeHelper(cUnit, rTgt);
-        oatFreeTemp(cUnit, rTgt);
-#else
-        loadConstant(cUnit, rARG0, fieldIdx);
-        callRuntimeHelper(cUnit, getterOffset);
-#endif
+        callRuntimeHelperImm(cUnit, getterOffset, fieldIdx);
         if (isLongOrDouble) {
             RegLocation rlResult = oatGetReturnWide(cUnit, rlDest.fp);
             storeValueWide(cUnit, rlDest, rlResult);
@@ -638,33 +829,21 @@
 
 void genThrowVerificationError(CompilationUnit* cUnit, MIR* mir)
 {
-#if !defined(TARGET_X86)
-    int rTgt = loadHelper(cUnit, OFFSETOF_MEMBER(Thread,
-                          pThrowVerificationErrorFromCode));
-    loadConstant(cUnit, rARG0, mir->dalvikInsn.vA);
-    loadConstant(cUnit, rARG1, mir->dalvikInsn.vB);
-    callRuntimeHelper(cUnit, rTgt);
-    oatFreeTemp(cUnit, rTgt);
-#else
-    loadConstant(cUnit, rARG0, mir->dalvikInsn.vA);
-    loadConstant(cUnit, rARG1, mir->dalvikInsn.vB);
-    callRuntimeHelper(cUnit,
-                     OFFSETOF_MEMBER(Thread, pThrowVerificationErrorFromCode));
-#endif
+    callRuntimeHelperImmImm(cUnit, OFFSETOF_MEMBER(Thread,
+                                              pThrowVerificationErrorFromCode),
+                            mir->dalvikInsn.vA, mir->dalvikInsn.vB);
 }
 
 void handleSuspendLaunchpads(CompilationUnit *cUnit)
 {
-    LIR** suspendLabel =
-        (LIR **) cUnit->suspendLaunchpads.elemList;
+    LIR** suspendLabel = (LIR **)cUnit->suspendLaunchpads.elemList;
     int numElems = cUnit->suspendLaunchpads.numUsed;
-
     for (int i = 0; i < numElems; i++) {
         oatResetRegPool(cUnit);
         LIR* lab = suspendLabel[i];
         LIR* resumeLab = (LIR*)lab->operands[0];
         cUnit->currentDalvikOffset = lab->operands[1];
-        oatAppendLIR(cUnit, (LIR *)lab);
+        oatAppendLIR(cUnit, lab);
 #if defined(TARGET_X86)
         opThreadMem(cUnit, kOpBlx,
                     OFFSETOF_MEMBER(Thread, pTestSuspendFromCode));
@@ -679,15 +858,13 @@
 
 void handleThrowLaunchpads(CompilationUnit *cUnit)
 {
-    LIR** throwLabel = (LIR **) cUnit->throwLaunchpads.elemList;
+    LIR** throwLabel = (LIR **)cUnit->throwLaunchpads.elemList;
     int numElems = cUnit->throwLaunchpads.numUsed;
-    int i;
-
-    for (i = 0; i < numElems; i++) {
+    for (int i = 0; i < numElems; i++) {
         oatResetRegPool(cUnit);
         LIR* lab = throwLabel[i];
         cUnit->currentDalvikOffset = lab->operands[1];
-        oatAppendLIR(cUnit, (LIR *)lab);
+        oatAppendLIR(cUnit, lab);
         int funcOffset = 0;
         int v1 = lab->operands[2];
         int v2 = lab->operands[3];
@@ -745,12 +922,13 @@
             default:
                 LOG(FATAL) << "Unexpected throw kind: " << lab->operands[0];
         }
-#if defined(TARGET_X86)
-        callRuntimeHelper(cUnit, funcOffset);
-#else
+        oatClobberCalleeSave(cUnit);
+#if !defined(TARGET_X86)
         int rTgt = loadHelper(cUnit, funcOffset);
-        callRuntimeHelper(cUnit, rTgt);
+        opReg(cUnit, kOpBlx, rTgt);
         oatFreeTemp(cUnit, rTgt);
+#else
+        opThreadMem(cUnit, kOpBlx, funcOffset);
 #endif
     }
 }
@@ -818,16 +996,7 @@
         int getterOffset = isLongOrDouble ? OFFSETOF_MEMBER(Thread, pGet64Instance) :
                            (isObject ? OFFSETOF_MEMBER(Thread, pGetObjInstance)
                                      : OFFSETOF_MEMBER(Thread, pGet32Instance));
-#if !defined(TARGET_X86)
-        int rTgt = loadHelper(cUnit, getterOffset);
-        loadValueDirect(cUnit, rlObj, rARG1);
-        loadConstant(cUnit, rARG0, fieldIdx);
-        callRuntimeHelper(cUnit, rTgt);
-#else
-        loadValueDirect(cUnit, rlObj, rARG1);
-        loadConstant(cUnit, rARG0, fieldIdx);
-        callRuntimeHelper(cUnit, getterOffset);
-#endif
+        callRuntimeHelperImmRegLocation(cUnit, getterOffset, fieldIdx, rlObj);
         if (isLongOrDouble) {
             RegLocation rlResult = oatGetReturnWide(cUnit, rlDest.fp);
             storeValueWide(cUnit, rlDest, rlResult);
@@ -885,26 +1054,8 @@
         int setterOffset = isLongOrDouble ? OFFSETOF_MEMBER(Thread, pSet64Instance) :
                            (isObject ? OFFSETOF_MEMBER(Thread, pSetObjInstance)
                                      : OFFSETOF_MEMBER(Thread, pSet32Instance));
-#if !defined(TARGET_X86)
-        int rTgt = loadHelper(cUnit, setterOffset);
-#endif
-        loadValueDirect(cUnit, rlObj, rARG1);
-        if (isLongOrDouble) {
-#if defined(TARGET_X86)
-            UNIMPLEMENTED(FATAL);
-#else
-            loadValueDirectWide(cUnit, rlSrc, rARG2, rARG3);
-#endif
-        } else {
-            loadValueDirect(cUnit, rlSrc, rARG2);
-        }
-        loadConstant(cUnit, rARG0, fieldIdx);
-#if !defined(TARGET_X86)
-        callRuntimeHelper(cUnit, rTgt);
-        oatFreeTemp(cUnit, rTgt);
-#else
-        callRuntimeHelper(cUnit, setterOffset);
-#endif
+        callRuntimeHelperImmRegLocationRegLocation(cUnit, setterOffset,
+                                                   fieldIdx, rlObj, rlSrc);
     }
 }
 
@@ -921,19 +1072,10 @@
                                                      type_idx)) {
         // Call out to helper which resolves type and verifies access.
         // Resolved type returned in rRET0.
-#if !defined(TARGET_X86)
-        int rTgt = loadHelper(cUnit, OFFSETOF_MEMBER(Thread,
-                              pInitializeTypeAndVerifyAccessFromCode));
-        opRegCopy(cUnit, rARG1, rlMethod.lowReg);
-        loadConstant(cUnit, rARG0, type_idx);
-        callRuntimeHelper(cUnit, rTgt);
-        oatFreeTemp(cUnit, rTgt);
-#else
-        opRegCopy(cUnit, rARG1, rlMethod.lowReg);
-        loadConstant(cUnit, rARG0, type_idx);
-        callRuntimeHelper(cUnit, OFFSETOF_MEMBER(Thread,
-                                      pInitializeTypeAndVerifyAccessFromCode));
-#endif
+        callRuntimeHelperImmReg(cUnit,
+                                OFFSETOF_MEMBER(Thread,
+                                       pInitializeTypeAndVerifyAccessFromCode),
+                                type_idx, rlMethod.lowReg);
         RegLocation rlResult = oatGetReturn(cUnit, false);
         storeValue(cUnit, rlDest, rlResult);
     } else {
@@ -962,19 +1104,9 @@
             // TUNING: move slow path to end & remove unconditional branch
             LIR* target1 = newLIR0(cUnit, kPseudoTargetLabel);
             // Call out to helper, which will return resolved type in rARG0
-#if !defined(TARGET_X86)
-            int rTgt = loadHelper(cUnit, OFFSETOF_MEMBER(Thread,
-                                  pInitializeTypeFromCode));
-            opRegCopy(cUnit, rARG1, rlMethod.lowReg);
-            loadConstant(cUnit, rARG0, type_idx);
-            callRuntimeHelper(cUnit, rTgt);
-            oatFreeTemp(cUnit, rTgt);
-#else
-            opRegCopy(cUnit, rARG1, rlMethod.lowReg);
-            loadConstant(cUnit, rARG0, type_idx);
-            callRuntimeHelper(cUnit, OFFSETOF_MEMBER(Thread,
-                                                     pInitializeTypeFromCode));
-#endif
+            callRuntimeHelperImmReg(cUnit, OFFSETOF_MEMBER(Thread,
+                                                     pInitializeTypeFromCode),
+                                    type_idx, rlMethod.lowReg);
             RegLocation rlResult = oatGetReturn(cUnit, false);
             storeValue(cUnit, rlDest, rlResult);
             /*
@@ -992,6 +1124,7 @@
         }
     }
 }
+
 void genConstString(CompilationUnit* cUnit, MIR* mir, RegLocation rlDest,
                     RegLocation rlSrc)
 {
@@ -1032,9 +1165,9 @@
         LIR* target = newLIR0(cUnit, kPseudoTargetLabel);
         branch->target = target;
 #else
-        opRegCopy(cUnit, rARG0, rARG2);
-        callRuntimeHelper(cUnit, OFFSETOF_MEMBER(Thread,
-                                                 pResolveStringFromCode));
+        callRuntimeHelperRegReg(cUnit, OFFSETOF_MEMBER(Thread,
+                                                      pResolveStringFromCode),
+                                rARG2, rARG1);
 #endif
         genBarrier(cUnit);
         storeValue(cUnit, rlDest, oatGetReturn(cUnit, false));
@@ -1067,21 +1200,17 @@
         funcOffset =
             OFFSETOF_MEMBER(Thread, pAllocObjectFromCodeWithAccessCheck);
     }
-#if !defined(TARGET_X86)
-    int rTgt = loadHelper(cUnit, funcOffset);
-    loadCurrMethodDirect(cUnit, rARG1);    // arg1 <= Method*
-    loadConstant(cUnit, rARG0, type_idx);  // arg0 <- type_idx
-    callRuntimeHelper(cUnit, rTgt);
-    oatFreeTemp(cUnit, rTgt);
-#else
-    loadCurrMethodDirect(cUnit, rARG1);    // arg1 <= Method*
-    loadConstant(cUnit, rARG0, type_idx);  // arg0 <- type_idx
-    callRuntimeHelper(cUnit, funcOffset);
-#endif
+    callRuntimeHelperImmMethod(cUnit, funcOffset, type_idx);
     RegLocation rlResult = oatGetReturn(cUnit, false);
     storeValue(cUnit, rlDest, rlResult);
 }
 
+void genThrow(CompilationUnit* cUnit, MIR* mir, RegLocation rlSrc)
+{
+    oatFlushAllRegs(cUnit);
+    callRuntimeHelperRegLocation(cUnit, OFFSETOF_MEMBER(Thread, pDeliverException), rlSrc);
+}
+
 void genInstanceof(CompilationUnit* cUnit, MIR* mir, RegLocation rlDest,
                    RegLocation rlSrc)
 {
@@ -1097,17 +1226,9 @@
                                                      type_idx)) {
         // Check we have access to type_idx and if not throw IllegalAccessError,
         // returns Class* in rARG0
-#if !defined(TARGET_X86)
-        int rTgt = loadHelper(cUnit, OFFSETOF_MEMBER(Thread,
-                              pInitializeTypeAndVerifyAccessFromCode));
-        loadConstant(cUnit, rARG0, type_idx);
-        callRuntimeHelper(cUnit, rTgt);
-        oatFreeTemp(cUnit, rTgt);
-#else
-        loadConstant(cUnit, rARG0, type_idx);
-        callRuntimeHelper(cUnit,
-              OFFSETOF_MEMBER(Thread, pInitializeTypeAndVerifyAccessFromCode));
-#endif
+        callRuntimeHelperImm(cUnit,
+              OFFSETOF_MEMBER(Thread, pInitializeTypeAndVerifyAccessFromCode),
+              type_idx);
         opRegCopy(cUnit, classReg, rRET0);  // Align usage with fast path
         loadValueDirectFixed(cUnit, rlSrc, rARG0);  // rARG0 <= ref
     } else {
@@ -1126,17 +1247,9 @@
             LIR* hopBranch = opCmpImmBranch(cUnit, kCondNe, classReg, 0, NULL);
             // Not resolved
             // Call out to helper, which will return resolved type in rRET0
-#if !defined(TARGET_X86)
-            int rTgt = loadHelper(cUnit, OFFSETOF_MEMBER(Thread,
-                                  pInitializeTypeFromCode));
-            loadConstant(cUnit, rARG0, type_idx);
-            callRuntimeHelper(cUnit, rTgt);  // InitializeTypeFromCode(idx, method)
-            oatFreeTemp(cUnit, rTgt);
-#else
-            loadConstant(cUnit, rARG0, type_idx);
-            callRuntimeHelper(cUnit, OFFSETOF_MEMBER(Thread,
-                                                     pInitializeTypeFromCode));
-#endif
+            callRuntimeHelperImm(cUnit, OFFSETOF_MEMBER(Thread,
+                                                     pInitializeTypeFromCode),
+                                 type_idx);
             opRegCopy(cUnit, rARG2, rRET0); // Align usage with fast path
             loadValueDirectFixed(cUnit, rlSrc, rARG0);  /* reload Ref */
             // Rejoin code paths
@@ -1159,6 +1272,7 @@
     loadConstant(cUnit, rARG0, 1);       // .eq case - load true
     opRegCopy(cUnit, rARG0, rARG2);        // .ne case - arg0 <= class
     opReg(cUnit, kOpBlx, rTgt);        // .ne case: helper(class, ref->class)
+    oatFreeTemp(cUnit, rTgt);
 #else
     /* Uses branchovers */
     loadConstant(cUnit, rARG0, 1);       // assume true
@@ -1168,10 +1282,11 @@
                           pInstanceofNonTrivialFromCode));
     opRegCopy(cUnit, rARG0, rARG2);        // .ne case - arg0 <= class
     opReg(cUnit, kOpBlx, rTgt);        // .ne case: helper(class, ref->class)
+    oatFreeTemp(cUnit, rTgt);
 #else
     opRegCopy(cUnit, rARG0, rARG2);
-    opReg(cUnit, kOpBlx,
-          OFFSETOF_MEMBER(Thread, pInstanceofNonTrivialFromCode));
+    opThreadMem(cUnit, kOpBlx,
+                OFFSETOF_MEMBER(Thread, pInstanceofNonTrivialFromCode));
 #endif
 #endif
     oatClobberCalleeSave(cUnit);
@@ -1199,17 +1314,11 @@
                                                      type_idx)) {
         // Check we have access to type_idx and if not throw IllegalAccessError,
         // returns Class* in rRET0
-#if !defined(TARGET_X86)
-        int rTgt = loadHelper(cUnit, OFFSETOF_MEMBER(Thread,
-                              pInitializeTypeAndVerifyAccessFromCode));
-        loadConstant(cUnit, rARG0, type_idx);
-        callRuntimeHelper(cUnit, rTgt);  // InitializeTypeAndVerifyAccess(idx, method)
-        oatFreeTemp(cUnit, rTgt);
-#else
-        loadConstant(cUnit, rARG0, type_idx);
-        callRuntimeHelper(cUnit,
-            OFFSETOF_MEMBER(Thread, pInitializeTypeAndVerifyAccessFromCode));
-#endif
+        // InitializeTypeAndVerifyAccess(idx, method)
+        callRuntimeHelperImmReg(cUnit,
+                                OFFSETOF_MEMBER(Thread,
+                                    pInitializeTypeAndVerifyAccessFromCode),
+                                type_idx, rARG1);
         opRegCopy(cUnit, classReg, rRET0);  // Align usage with fast path
     } else {
         // Load dex cache entry into classReg (rARG2)
@@ -1226,16 +1335,10 @@
             LIR* hopBranch = opCmpImmBranch(cUnit, kCondNe, classReg, 0, NULL);
             // Not resolved
             // Call out to helper, which will return resolved type in rARG0
-#if !defined(TARGET_X86)
-            int rTgt = loadHelper(cUnit, OFFSETOF_MEMBER(Thread, pInitializeTypeFromCode));
-            loadConstant(cUnit, rARG0, type_idx);
-            callRuntimeHelper(cUnit, rTgt);  // InitializeTypeFromCode(idx, method)
-            oatFreeTemp(cUnit, rTgt);
-#else
-            loadConstant(cUnit, rARG0, type_idx);
-            callRuntimeHelper(cUnit,
-                             OFFSETOF_MEMBER(Thread, pInitializeTypeFromCode));
-#endif
+            // InitializeTypeFromCode(idx, method)
+            callRuntimeHelperImmReg(cUnit,
+                                    OFFSETOF_MEMBER(Thread, pInitializeTypeFromCode),
+                                    type_idx, rARG1);
             opRegCopy(cUnit, classReg, rARG0); // Align usage with fast path
             // Rejoin code paths
             LIR* hopTarget = newLIR0(cUnit, kPseudoTargetLabel);
@@ -1250,28 +1353,21 @@
     DCHECK_EQ(Object::ClassOffset().Int32Value(), 0);
     loadWordDisp(cUnit, rARG0,  Object::ClassOffset().Int32Value(), rARG1);
     /* rARG1 now contains object->clazz */
-#if defined(TARGET_MIPS)
-    int rTgt = loadHelper(cUnit, OFFSETOF_MEMBER(Thread,
-                          pCheckCastFromCode));
+#if defined(TARGET_MIPS) || defined(TARGET_X86)
     LIR* branch2 = opCmpBranch(cUnit, kCondEq, rARG1, classReg, NULL);
-    opRegCopy(cUnit, rARG0, rARG1);
-    opRegCopy(cUnit, rARG1, rARG2);
-    callRuntimeHelper(cUnit, rTgt);
-    oatFreeTemp(cUnit, rTgt);
-#elif defined(TARGET_ARM)
+    callRuntimeHelperRegReg(cUnit, OFFSETOF_MEMBER(Thread,
+                                                   pCheckCastFromCode),
+                            rARG1, rARG2);
+#else  // defined(TARGET_ARM)
     int rTgt = loadHelper(cUnit, OFFSETOF_MEMBER(Thread,
                           pCheckCastFromCode));
     opRegReg(cUnit, kOpCmp, rARG1, classReg);
     LIR* branch2 = opCondBranch(cUnit, kCondEq, NULL); /* If eq, trivial yes */
     opRegCopy(cUnit, rARG0, rARG1);
     opRegCopy(cUnit, rARG1, rARG2);
-    callRuntimeHelper(cUnit, rTgt);
+    oatClobberCalleeSave(cUnit);
+    opReg(cUnit, kOpBlx, rTgt);
     oatFreeTemp(cUnit, rTgt);
-#else
-    LIR* branch2 = opCmpBranch(cUnit, kCondEq, rARG1, classReg, NULL);
-    opRegCopy(cUnit, rARG0, rARG1);
-    opRegCopy(cUnit, rARG1, rARG2);
-    callRuntimeHelper(cUnit, OFFSETOF_MEMBER(Thread, pCheckCastFromCode));
 #endif
     /* branch target here */
     LIR* target = newLIR0(cUnit, kPseudoTargetLabel);
@@ -1279,20 +1375,6 @@
     branch2->target = (LIR*)target;
 }
 
-
-void genThrow(CompilationUnit* cUnit, MIR* mir, RegLocation rlSrc)
-{
-    oatFlushAllRegs(cUnit);
-#if !defined(TARGET_X86)
-    int rTgt = loadHelper(cUnit, OFFSETOF_MEMBER(Thread, pDeliverException));
-    loadValueDirectFixed(cUnit, rlSrc, rARG0);  // Get exception object
-    callRuntimeHelper(cUnit, rTgt);  // art_deliver_exception(exception);
-#else
-    loadValueDirectFixed(cUnit, rlSrc, rARG0);  // Get exception object
-    callRuntimeHelper(cUnit, OFFSETOF_MEMBER(Thread, pDeliverException));
-#endif
-}
-
 /*
  * Generate array store
  *
@@ -1311,19 +1393,11 @@
 
     /* null array object? */
     genNullCheck(cUnit, rlArray.sRegLow, rARG1, mir);
-#if !defined(TARGET_X86)
-    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, rTgt);
-#else
-    /* Get the array's clazz */
-    loadWordDisp(cUnit, rARG1, Object::ClassOffset().Int32Value(), rARG1);
-    callRuntimeHelper(cUnit,
-                      OFFSETOF_MEMBER(Thread, pCanPutArrayElementFromCode));
-#endif
+    callRuntimeHelperRegReg(cUnit, OFFSETOF_MEMBER(Thread,
+                                                  pCanPutArrayElementFromCode),
+                            rARG0, rARG1);
     oatFreeTemp(cUnit, rARG0);
     oatFreeTemp(cUnit, rARG1);
 
@@ -1611,17 +1685,7 @@
             return true;
     }
     oatFlushAllRegs(cUnit);   /* Send everything to home location */
-#if !defined(TARGET_X86)
-    int rTgt = loadHelper(cUnit, funcOffset);
-    loadValueDirectWideFixed(cUnit, rlSrc1, rARG0, rARG1);
-    loadValueDirect(cUnit, rlShift, rARG2);
-    callRuntimeHelper(cUnit, rTgt);
-    oatFreeTemp(cUnit, rTgt);
-#else
-    loadValueDirectWideFixed(cUnit, rlSrc1, rARG0, rARG1);
-    loadValueDirect(cUnit, rlShift, rARG2);
-    callRuntimeHelper(cUnit, funcOffset);
-#endif
+    callRuntimeHelperRegLocationRegLocation(cUnit, funcOffset, rlSrc1, rlShift);
     RegLocation rlResult = oatGetReturnWide(cUnit, false);
     storeValueWide(cUnit, rlDest, rlResult);
     return false;
@@ -1742,18 +1806,16 @@
         loadValueDirectFixed(cUnit, rlSrc2, rRET1);
 #if !defined(TARGET_X86)
         int rTgt = loadHelper(cUnit, funcOffset);
+#endif
         loadValueDirectFixed(cUnit, rlSrc1, rARG0);
         if (checkZero) {
             genImmedCheck(cUnit, kCondEq, rARG1, 0, mir, kThrowDivZero);
         }
-        callRuntimeHelper(cUnit, rTgt);
+#if !defined(TARGET_X86)
+        opReg(cUnit, kOpBlx, rTgt);
         oatFreeTemp(cUnit, rTgt);
 #else
-        loadValueDirectFixed(cUnit, rlSrc1, rARG0);
-        if (checkZero) {
-            genImmedCheck(cUnit, kCondEq, rARG1, 0, mir, kThrowDivZero);
-        }
-        callRuntimeHelper(cUnit, funcOffset);
+        opThreadMem(cUnit, kOpBlx, funcOffset);
 #endif
         if (retReg == rRET0)
             rlResult = oatGetReturn(cUnit, false);
@@ -1999,17 +2061,7 @@
                 funcOffset = OFFSETOF_MEMBER(Thread, pIdivmod);
                 isDiv = false;
             }
-#if !defined(TARGET_X86)
-            {
-                int rTgt = loadHelper(cUnit, funcOffset);
-                loadConstant(cUnit, rARG1, lit);
-                callRuntimeHelper(cUnit, rTgt);
-                oatFreeTemp(cUnit, rTgt);
-            }
-#else
-            loadConstant(cUnit, rARG1, lit);
-            callRuntimeHelper(cUnit, funcOffset);
-#endif
+            callRuntimeHelperRegImm(cUnit, funcOffset, rARG0, lit);
             if (isDiv)
                 rlResult = oatGetReturn(cUnit, false);
             else
@@ -2125,14 +2177,13 @@
     if (!callOut) {
         genLong3Addr(cUnit, mir, firstOp, secondOp, rlDest, rlSrc1, rlSrc2);
     } else {
-        int rTgt;
         oatFlushAllRegs(cUnit);   /* Send everything to home location */
         if (checkZero) {
 #if defined(TARGET_X86)
             UNIMPLEMENTED(FATAL);
 #else
             loadValueDirectWideFixed(cUnit, rlSrc2, rARG2, rARG3);
-            rTgt = loadHelper(cUnit, funcOffset);
+            int rTgt = loadHelper(cUnit, funcOffset);
 #endif
             loadValueDirectWideFixed(cUnit, rlSrc1, rARG0, rARG1);
             int tReg = oatAllocTemp(cUnit);
@@ -2143,24 +2194,20 @@
 #else
 #if defined(TARGET_X86)
             UNIMPLEMENTED(FATAL);
-            rTgt = -1;
 #else
             opRegRegReg(cUnit, kOpOr, tReg, rARG2, rARG3);
 #endif
             genImmedCheck(cUnit, kCondEq, tReg, 0, mir, kThrowDivZero);
             oatFreeTemp(cUnit, tReg);
 #endif
-        } else {
-#if defined(TARGET_X86)
-            UNIMPLEMENTED(FATAL);
-            rTgt = -1;
-#else
-            rTgt = loadHelper(cUnit, funcOffset);
-            loadValueDirectWideFixed(cUnit, rlSrc1, rARG0, rARG1);
-            loadValueDirectWideFixed(cUnit, rlSrc2, rARG2, rARG3);
+#if !defined(TARGET_X86)
+            opReg(cUnit, kOpBlx, rTgt);
+            oatFreeTemp(cUnit, rTgt);
 #endif
+        } else {
+            callRuntimeHelperRegLocationRegLocation(cUnit, funcOffset,
+                                                    rlSrc1, rlSrc2);
         }
-        callRuntimeHelper(cUnit, rTgt);
         // Adjust return regs in to handle case of rem returning rARG2/rARG3
         if (retReg == rRET0)
             rlResult = oatGetReturnWide(cUnit, false);
@@ -2181,8 +2228,6 @@
     RegLocation rlSrc;
     RegLocation rlDest;
     oatFlushAllRegs(cUnit);   /* Send everything to home location */
-#if !defined(TARGET_X86)
-    int rTgt = loadHelper(cUnit, funcOffset);
     if (srcSize == 1) {
         rlSrc = oatGetSrc(cUnit, mir, 0);
         loadValueDirectFixed(cUnit, rlSrc, rARG0);
@@ -2190,17 +2235,7 @@
         rlSrc = oatGetSrcWide(cUnit, mir, 0, 1);
         loadValueDirectWideFixed(cUnit, rlSrc, rARG0, rARG1);
     }
-    callRuntimeHelper(cUnit, rTgt);
-#else
-    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, funcOffset);
-#endif
+    callRuntimeHelperRegLocation(cUnit, funcOffset, rlSrc);
     if (tgtSize == 1) {
         RegLocation rlResult;
         rlDest = oatGetDest(cUnit, mir, 0);
@@ -2252,17 +2287,7 @@
             return true;
     }
     oatFlushAllRegs(cUnit);   /* Send everything to home location */
-#if !defined(TARGET_X86)
-    int rTgt = loadHelper(cUnit, funcOffset);
-    loadValueDirectFixed(cUnit, rlSrc1, rARG0);
-    loadValueDirectFixed(cUnit, rlSrc2, rARG1);
-    callRuntimeHelper(cUnit, rTgt);
-    oatFreeTemp(cUnit, rTgt);
-#else
-    loadValueDirectFixed(cUnit, rlSrc1, rARG0);
-    loadValueDirectFixed(cUnit, rlSrc2, rARG1);
-    callRuntimeHelper(cUnit, funcOffset);
-#endif
+    callRuntimeHelperRegLocationRegLocation(cUnit, funcOffset, rlSrc1, rlSrc2);
     rlResult = oatGetReturn(cUnit, true);
     storeValue(cUnit, rlDest, rlResult);
     return false;
@@ -2305,17 +2330,7 @@
             return true;
     }
     oatFlushAllRegs(cUnit);   /* Send everything to home location */
-#if !defined(TARGET_X86)
-    int rTgt = loadHelper(cUnit, funcOffset);
-    loadValueDirectWideFixed(cUnit, rlSrc1, rARG0, rARG1);
-    loadValueDirectWideFixed(cUnit, rlSrc2, rARG2, rARG3);
-    callRuntimeHelper(cUnit, rTgt);
-#else
-    UNIMPLEMENTED(FATAL);
-    loadValueDirectWideFixed(cUnit, rlSrc1, rARG0, rARG1);
-    //loadValueDirectWideFixed(cUnit, rlSrc2, rARG2, rARG3);
-    callRuntimeHelper(cUnit, funcOffset);
-#endif
+    callRuntimeHelperRegLocationRegLocation(cUnit, funcOffset, rlSrc1, rlSrc2);
     rlResult = oatGetReturnWide(cUnit, true);
     storeValueWide(cUnit, rlDest, rlResult);
     return false;