Numerous fixes to MIPS. Basic oatexec works.

- Fixed reversed base and destination reg in genConstString
- Changed compiler to use T9 to hold address to jump to
- Fixed compilation of instruction getting current PC
- Prevented T9 from being used as a compiler temp
- Fixed loadBaseDispBody for long form single loads
- Fixed stack setup for SaveAll callee methods to save rSELF & rSUSPEND
- Added .cpload directive to assembly to regenerate $gp when overwritten
- Fixed passing of extra arguments on the stack to account for space
    reserved for $a0-$a3
- Fixed resolution trampoline to properly setup and restore stack
- Created mips stubs for interface trampoline and unresolved direct
    method trampoline

Change-Id: I63a3fd0366bdfabdebebf58ec4b8bc9443cec355
diff --git a/src/compiler/codegen/GenCommon.cc b/src/compiler/codegen/GenCommon.cc
index d948d2d..c1d4661 100644
--- a/src/compiler/codegen/GenCommon.cc
+++ b/src/compiler/codegen/GenCommon.cc
@@ -1202,7 +1202,7 @@
 #if !defined(TARGET_X86)
     int rTgt = loadHelper(cUnit, ENTRYPOINT_OFFSET(pResolveStringFromCode));
 #endif
-    loadWordDisp(cUnit, rRET0, offset_of_string, rARG0);
+    loadWordDisp(cUnit, rARG0, offset_of_string, rRET0);
     loadConstant(cUnit, rARG1, string_idx);
 #if defined(TARGET_ARM)
     opRegImm(cUnit, kOpCmp, rRET0, 0);  // Is resolved?
diff --git a/src/compiler/codegen/mips/ArchFactory.cc b/src/compiler/codegen/mips/ArchFactory.cc
index 4a61efb..f51e722 100644
--- a/src/compiler/codegen/mips/ArchFactory.cc
+++ b/src/compiler/codegen/mips/ArchFactory.cc
@@ -107,9 +107,8 @@
  */
 int loadHelper(CompilationUnit* cUnit, int offset)
 {
-  int tReg = oatAllocTemp(cUnit);
-  loadWordDisp(cUnit, rSELF, offset, tReg);
-  return tReg;
+  loadWordDisp(cUnit, rSELF, offset, r_T9);
+  return r_T9;
 }
 
 void spillCoreRegs(CompilationUnit* cUnit)
diff --git a/src/compiler/codegen/mips/Assemble.cc b/src/compiler/codegen/mips/Assemble.cc
index 8c906cc..f19c1f1 100644
--- a/src/compiler/codegen/mips/Assemble.cc
+++ b/src/compiler/codegen/mips/Assemble.cc
@@ -400,7 +400,7 @@
     ENCODING_MAP(kMipsDelta, 0x27e00000,
                  kFmtBitBlt, 20, 16, kFmtBitBlt, 15, 0, kFmtUnused, 15, 0,
                  kFmtUnused, -1, -1, IS_QUAD_OP | REG_DEF0 | REG_USE_LR |
-                 NEEDS_FIXUP, "addiu", "!0r,r_ra,0x!1h(!1d)", 4),
+                 NEEDS_FIXUP, "addiu", "!0r,ra,0x!1h(!1d)", 4),
     ENCODING_MAP(kMipsDeltaHi, 0x3C000000,
                  kFmtBitBlt, 20, 16, kFmtBitBlt, 15, 0, kFmtUnused, -1, -1,
                  kFmtUnused, -1, -1, IS_QUAD_OP | REG_DEF0 | NEEDS_FIXUP,
@@ -409,10 +409,10 @@
                  kFmtBlt5_2, 16, 21, kFmtBitBlt, 15, 0, kFmtUnused, -1, -1,
                  kFmtUnused, -1, -1, IS_QUAD_OP | REG_DEF0_USE0 | NEEDS_FIXUP,
                  "ori", "!0r,!0r,0x!1h(!1d)", 4),
-    ENCODING_MAP(kMipsCurrPC, 0x04110020,
+    ENCODING_MAP(kMipsCurrPC, 0x04110001,
                  kFmtUnused, -1, -1, kFmtUnused, -1, -1, kFmtUnused, -1, -1,
                  kFmtUnused, -1, -1, NO_OPERAND | IS_BRANCH | REG_DEF_LR,
-                 "pc2ra", "; r_ra <- .+8", 4),
+                 "addiu", "ra,pc,8", 4),
     ENCODING_MAP(kMipsSync, 0x0000000f,
                  kFmtBitBlt, 10, 6, kFmtUnused, -1, -1, kFmtUnused, -1, -1,
                  kFmtUnused, -1, -1, IS_UNARY_OP,
diff --git a/src/compiler/codegen/mips/Mips32/Factory.cc b/src/compiler/codegen/mips/Mips32/Factory.cc
index ad220f8..63c92eb 100644
--- a/src/compiler/codegen/mips/Mips32/Factory.cc
+++ b/src/compiler/codegen/mips/Mips32/Factory.cc
@@ -31,7 +31,7 @@
 static int reservedRegs[] = {r_ZERO, r_AT, r_S0, r_S1, r_K0, r_K1, r_GP, r_SP,
                              r_RA};
 static int coreTemps[] = {r_V0, r_V1, r_A0, r_A1, r_A2, r_A3, r_T0, r_T1, r_T2,
-                          r_T3, r_T4, r_T5, r_T6, r_T7, r_T8, r_T9};
+                          r_T3, r_T4, r_T5, r_T6, r_T7, r_T8};
 #ifdef __mips_hard_float
 static int fpRegs[] = {r_F0, r_F1, r_F2, r_F3, r_F4, r_F5, r_F6, r_F7,
                        r_F8, r_F9, r_F10, r_F11, r_F12, r_F13, r_F14, r_F15};
@@ -607,8 +607,8 @@
       oatFreeTemp(cUnit, rTmp);
     } else {
       int rTmp = (rBase == rDest) ? oatAllocFreeTemp(cUnit) : rDest;
-      res = loadConstant(cUnit, rTmp, displacement);
-      load = newLIR3(cUnit, opcode, rDest, rBase, rTmp);
+      res = opRegRegImm(cUnit, kOpAdd, rTmp, rBase, displacement);
+      load = newLIR3(cUnit, opcode, rDest, 0, rTmp);
       if (rTmp != rDest)
         oatFreeTemp(cUnit, rTmp);
     }
diff --git a/src/compiler/codegen/mips/MipsLIR.h b/src/compiler/codegen/mips/MipsLIR.h
index ab4f844..5e5147a 100644
--- a/src/compiler/codegen/mips/MipsLIR.h
+++ b/src/compiler/codegen/mips/MipsLIR.h
@@ -301,7 +301,7 @@
 #define rARG3 r_ARG3
 #define rRET0 r_RESULT0
 #define rRET1 r_RESULT1
-#define rINVOKE_TGT r_V0
+#define rINVOKE_TGT r_T9
 
 /* Shift encodings */
 enum MipsShiftEncodings {
diff --git a/src/oat/runtime/mips/runtime_support_mips.S b/src/oat/runtime/mips/runtime_support_mips.S
index 2f7d120..cbf895a 100644
--- a/src/oat/runtime/mips/runtime_support_mips.S
+++ b/src/oat/runtime/mips/runtime_support_mips.S
@@ -32,19 +32,21 @@
     /*
      * Macro that sets up the callee save frame to conform with
      * Runtime::CreateCalleeSaveMethod(kSaveAll)
-     * callee-save: $s2-$s8 + $ra, 8 total + 2 words
+     * callee-save: $s0-$s8 + $ra, 10 total + 4 words
      */
 .macro SETUP_SAVE_ALL_CALLEE_SAVE_FRAME
-    addiu  $sp, $sp, -48
-    sw     $ra, 44($sp)
-    sw     $s8, 40($sp)
-    sw     $s7, 36($sp)
-    sw     $s6, 32($sp)
-    sw     $s5, 28($sp)
-    sw     $s4, 24($sp)
-    sw     $s3, 20($sp)
-    sw     $s2, 16($sp)
-    # 4 open words, bottom will hold Method*
+    addiu  $sp, $sp, -64
+    sw     $ra, 60($sp)
+    sw     $s8, 56($sp)
+    sw     $s7, 52($sp)
+    sw     $s6, 48($sp)
+    sw     $s5, 44($sp)
+    sw     $s4, 40($sp)
+    sw     $s3, 36($sp)
+    sw     $s2, 32($sp)
+    sw     $s1, 28($sp)
+    sw     $s0, 24($sp)
+    # 2 words for alignment, 4 open words for args $a0-$a3, bottom will hold Method*
 .endm
 
     /*
@@ -63,7 +65,7 @@
     sw     $s4, 24($sp)
     sw     $s3, 20($sp)
     sw     $s2, 16($sp)
-    # 4 open words, bottom will hold Method*
+    # 4 open words for args $a0-$a3, bottom will hold Method*
 .endm
 
 .macro RESTORE_REF_ONLY_CALLEE_SAVE_FRAME
@@ -80,7 +82,7 @@
     /*
      * Macro that sets up the callee save frame to conform with
      * Runtime::CreateCalleeSaveMethod(kRefsAndArgs). Restoration assumes non-moving GC.
-     * $a1-$a3, $s2-$s8, $ra, 11 total + 1
+     * $a1-$a3, $s2-$s8, $ra, 11 total + Method*
      */
 .macro SETUP_REF_AND_ARGS_CALLEE_SAVE_FRAME
     addiu  $sp, $sp, -48
@@ -95,7 +97,7 @@
     sw     $a3, 12($sp)
     sw     $a2, 8($sp)
     sw     $a1, 4($sp)
-    # 1 open word, bottom will hold Method*
+    # bottom will hold Method*
 .endm
 
 .macro RESTORE_REF_AND_ARGS_CALLEE_SAVE_FRAME
@@ -155,6 +157,7 @@
      */
     ALIGN_FUNCTION_ENTRY
 art_update_debugger:
+    .cpload $25
     move    $a3, $a0        # stash away $a0 so that it's saved as if it were an argument
     SETUP_REF_AND_ARGS_CALLEE_SAVE_FRAME
     move    $a0, $a2        # arg0 is dex PC
@@ -247,6 +250,7 @@
      */
     ALIGN_FUNCTION_ENTRY
 art_deliver_exception_from_code:
+    .cpload $25
     SETUP_SAVE_ALL_CALLEE_SAVE_FRAME
     move $a1, rSELF                     # pass Thread::Current
     jal  artDeliverExceptionFromCode    # artDeliverExceptionFromCode(Throwable*, Thread*, $sp)
@@ -259,6 +263,7 @@
      */
     ALIGN_FUNCTION_ENTRY
 art_throw_null_pointer_exception_from_code:
+    .cpload $25
     SETUP_SAVE_ALL_CALLEE_SAVE_FRAME
     move $a0, rSELF                           # pass Thread::Current
     jal  artThrowNullPointerExceptionFromCode  # artThrowNullPointerExceptionFromCode(Thread*, $sp)
@@ -271,6 +276,7 @@
      */
     ALIGN_FUNCTION_ENTRY
 art_throw_div_zero_from_code:
+    .cpload $25
     SETUP_SAVE_ALL_CALLEE_SAVE_FRAME
     move $a0, rSELF                 # pass Thread::Current
     jal  artThrowDivZeroFromCode     # artThrowDivZeroFromCode(Thread*, $sp)
@@ -283,6 +289,7 @@
      */
     ALIGN_FUNCTION_ENTRY
 art_throw_array_bounds_from_code:
+    .cpload $25
     SETUP_SAVE_ALL_CALLEE_SAVE_FRAME
     move $a2, rSELF                  # pass Thread::Current
     jal artThrowArrayBoundsFromCode  # artThrowArrayBoundsFromCode(index, limit, Thread*, $sp)
@@ -295,6 +302,7 @@
      */
     ALIGN_FUNCTION_ENTRY
 art_throw_stack_overflow_from_code:
+    .cpload $25
     SETUP_SAVE_ALL_CALLEE_SAVE_FRAME
     move $a1, rSELF                    # pass Thread::Current
     jal artThrowStackOverflowFromCode  # artThrowStackOverflowFromCode(method, Thread*, $sp)
@@ -307,6 +315,7 @@
      */
     ALIGN_FUNCTION_ENTRY
 art_throw_no_such_method_from_code:
+    .cpload $25
     SETUP_SAVE_ALL_CALLEE_SAVE_FRAME
     move $a1, rSELF                       # pass Thread::Current
     jal artThrowNoSuchMethodFromCode      # artThrowNoSuchMethodFromCode(method_idx, Thread*, $sp)
@@ -322,7 +331,7 @@
      * The helper will attempt to locate the target and return a 64-bit result in $v0/$v1 consisting
      * of the target Method* in $v0 and method->code_ in $v1.
      *
-     * If unsuccessful, the helper will return NULL/NULL. There will bea pending exception in the
+     * If unsuccessful, the helper will return NULL/NULL. There will be a pending exception in the
      * thread and we branch to another stub to deliver it.
      *
      * On success this wrapper will restore arguments and *jump* to the target, leaving the lr
@@ -332,16 +341,21 @@
     .global \c_name
     .extern \cxx_name
 \c_name:
+    .cpload $25
     SETUP_REF_AND_ARGS_CALLEE_SAVE_FRAME  # save callee saves in case allocation triggers GC
     lw    $a2, 48($sp)                    # pass caller Method*
+    move  $t0, $sp                        # save $sp
+    addiu $sp, $sp, -16                   # make space for extra args
     move  $a3, rSELF                      # pass Thread::Current
-    sw    $sp, 0($sp)                     # pass $sp
     jal   \cxx_name                       # (method_idx, this, caller, Thread*, $sp)
-    move   $t0, $v1                       # save $v0->code_
+    sw    $t0, 16($sp)                    # pass $sp
+    addiu $sp, $sp, 16                    # release out args
+    move  $a0, $v0                        # save target Method*
+    move  $t0, $v1                        # save $v0->code_
     RESTORE_REF_AND_ARGS_CALLEE_SAVE_FRAME
-    bnez   $v0, 1f
+    beqz  $v0, 1f
     nop
-    jr     $t0
+    jr    $t0
     nop
 1:
     DELIVER_PENDING_EXCEPTION
@@ -362,22 +376,23 @@
      */
     ALIGN_FUNCTION_ENTRY
 art_work_around_app_jni_bugs:
+    .cpload $25
     # save registers that may contain arguments and LR that will be crushed by a call
     addiu    $sp, $sp, -32
-    sw       $a0, 28($sp)
-    sw       $a1, 24($sp)
+    sw       $ra, 28($sp)
+    sw       $a3, 24($sp)
     sw       $a2, 20($sp)
-    sw       $a3, 16($sp)
-    sw       $ra, 12($sp)
+    sw       $a1, 16($sp)
+    sw       $a0, 12($sp)
     move     $a0, rSELF       # pass Thread::Current
     jal      artWorkAroundAppJniBugs  # (Thread*, $sp)
     move     $a1, $sp         # pass $sp
     move     $t0, $v0         # save target address
-    lw       $a0, 28($sp)
-    lw       $a1, 24($sp)
+    lw       $a0, 12($sp)
+    lw       $a1, 16($sp)
     lw       $a2, 20($sp)
-    lw       $a3, 16($sp)
-    lw       $ra, 12($sp)
+    lw       $a3, 24($sp)
+    lw       $ra, 28($sp)
     jr       $t0              # tail call into JNI routine
     addiu    $sp, $sp, 32
 
@@ -389,6 +404,7 @@
      */
     ALIGN_FUNCTION_ENTRY
 art_handle_fill_data_from_code:
+    .cpload $25
     SETUP_REF_ONLY_CALLEE_SAVE_FRAME  # save callee saves in case exception allocation triggers GC
     move    $a2, rSELF                         # pass Thread::Current
     jal     artHandleFillArrayDataFromCode     # (Array*, const DexFile::Payload*, Thread*, $sp)
@@ -408,6 +424,7 @@
      */
     ALIGN_FUNCTION_ENTRY
 art_lock_object_from_code:
+    .cpload $25
     SETUP_REF_ONLY_CALLEE_SAVE_FRAME      # save callee saves in case we block
     move    $a1, rSELF                    # pass Thread::Current
     jal     artLockObjectFromCode         # (Object* obj, Thread*, $sp)
@@ -421,6 +438,7 @@
      */
     ALIGN_FUNCTION_ENTRY
 art_unlock_object_from_code:
+    .cpload $25
     SETUP_REF_ONLY_CALLEE_SAVE_FRAME  # save callee saves in case exception allocation triggers GC
     move    $a1, rSELF                # pass Thread::Current
     jal     artUnlockObjectFromCode   # (Object* obj, Thread*, $sp)
@@ -434,6 +452,7 @@
      */
     ALIGN_FUNCTION_ENTRY
 art_check_cast_from_code:
+    .cpload $25
     SETUP_REF_ONLY_CALLEE_SAVE_FRAME  # save callee saves in case exception allocation triggers GC
     move    $a2, rSELF                # pass Thread::Current
     jal     artCheckCastFromCode      # (Class* a, Class* b, Thread*, $sp)
@@ -448,6 +467,7 @@
      */
     ALIGN_FUNCTION_ENTRY
 art_can_put_array_element_from_code:
+    .cpload $25
     SETUP_REF_ONLY_CALLEE_SAVE_FRAME    # save callee saves in case exception allocation triggers GC
     move    $a2, rSELF                     # pass Thread::Current
     jal     artCanPutArrayElementFromCode  # (Object* element, Class* array_class, Thread*, $sp)
@@ -463,6 +483,7 @@
      */
     ALIGN_FUNCTION_ENTRY
 art_initialize_static_storage_from_code:
+    .cpload $25
     SETUP_REF_ONLY_CALLEE_SAVE_FRAME            # save callee saves in case of GC
     move    $a2, rSELF                          # pass Thread::Current
     # artInitializeStaticStorageFromCode(uint32_t type_idx, Method* referrer, Thread*, $sp)
@@ -477,6 +498,7 @@
      */
     ALIGN_FUNCTION_ENTRY
 art_initialize_type_from_code:
+    .cpload $25
     SETUP_REF_ONLY_CALLEE_SAVE_FRAME           # save callee saves in case of GC
     move    $a2, rSELF                         # pass Thread::Current
     # artInitializeTypeFromCode(uint32_t type_idx, Method* referrer, Thread*, $sp)
@@ -492,6 +514,7 @@
      */
     ALIGN_FUNCTION_ENTRY
 art_initialize_type_and_verify_access_from_code:
+    .cpload $25
     SETUP_REF_ONLY_CALLEE_SAVE_FRAME           # save callee saves in case of GC
     move    $a2, rSELF                         # pass Thread::Current
     # artInitializeTypeFromCode(uint32_t type_idx, Method* referrer, Thread*, $sp)
@@ -506,10 +529,11 @@
      */
     ALIGN_FUNCTION_ENTRY
 art_get32_static_from_code:
+    .cpload $25
     SETUP_REF_ONLY_CALLEE_SAVE_FRAME     # save callee saves in case of GC
     lw     $a1, 48($sp)                  # pass referrer's Method*
     move   $a2, rSELF                    # pass Thread::Current
-    jal     artGet32StaticFromCode       # (uint32_t field_idx, const Method* referrer, Thread*, $sp)
+    jal    artGet32StaticFromCode        # (uint32_t field_idx, const Method* referrer, Thread*, $sp)
     move   $a3, $sp                      # pass $sp
     RETURN_IF_NO_EXCEPTION
 
@@ -520,10 +544,11 @@
      */
     ALIGN_FUNCTION_ENTRY
 art_get64_static_from_code:
+    .cpload $25
     SETUP_REF_ONLY_CALLEE_SAVE_FRAME     # save callee saves in case of GC
     lw     $a1, 48($sp)                  # pass referrer's Method*
     move   $a2, rSELF                    # pass Thread::Current
-    jal     artGet64StaticFromCode       # (uint32_t field_idx, const Method* referrer, Thread*, $sp)
+    jal    artGet64StaticFromCode        # (uint32_t field_idx, const Method* referrer, Thread*, $sp)
     move   $a3, $sp                      # pass $sp
     RETURN_IF_NO_EXCEPTION
 
@@ -534,10 +559,11 @@
      */
     ALIGN_FUNCTION_ENTRY
 art_get_obj_static_from_code:
+    .cpload $25
     SETUP_REF_ONLY_CALLEE_SAVE_FRAME     # save callee saves in case of GC
     lw     $a1, 48($sp)                  # pass referrer's Method*
     move   $a2, rSELF                    # pass Thread::Current
-    jal     artGetObjStaticFromCode      # (uint32_t field_idx, const Method* referrer, Thread*, $sp)
+    jal    artGetObjStaticFromCode       # (uint32_t field_idx, const Method* referrer, Thread*, $sp)
     move   $a3, $sp                      # pass $sp
     RETURN_IF_NO_EXCEPTION
 
@@ -548,11 +574,15 @@
      */
     ALIGN_FUNCTION_ENTRY
 art_get32_instance_from_code:
+    .cpload $25
     SETUP_REF_ONLY_CALLEE_SAVE_FRAME     # save callee saves in case of GC
     lw     $a2, 48($sp)                  # pass referrer's Method*
+    move   $t0, $sp                      # save $sp
+    addiu  $sp, $sp, -16                 # make space for extra args
     move   $a3, rSELF                    # pass Thread::Current
-    jal     artGet32InstanceFromCode     # (field_idx, Object*, referrer, Thread*, $sp)
-    sw     $sp, 0($sp)                   # pass $sp
+    jal    artGet32InstanceFromCode      # (field_idx, Object*, referrer, Thread*, $sp)
+    sw     $t0, 16($sp)                  # pass $sp
+    addiu  $sp, $sp, 16                  # release out args
     RETURN_IF_NO_EXCEPTION
 
     .global art_get64_instance_from_code
@@ -562,11 +592,15 @@
      */
     ALIGN_FUNCTION_ENTRY
 art_get64_instance_from_code:
+    .cpload $25
     SETUP_REF_ONLY_CALLEE_SAVE_FRAME     # save callee saves in case of GC
     lw     $a2, 48($sp)                  # pass referrer's Method*
+    move   $t0, $sp                      # save $sp
+    addiu  $sp, $sp, -16                 # make space for extra args
     move   $a3, rSELF                    # pass Thread::Current
-    jal     artGet64InstanceFromCode     # (field_idx, Object*, referrer, Thread*, $sp)
-    sw     $sp, 0($sp)                   # pass $sp
+    jal    artGet64InstanceFromCode      # (field_idx, Object*, referrer, Thread*, $sp)
+    sw     $t0, 16($sp)                  # pass $sp
+    addiu  $sp, $sp, 16                  # release out args
     RETURN_IF_NO_EXCEPTION
 
     .global art_get_obj_instance_from_code
@@ -576,11 +610,15 @@
      */
     ALIGN_FUNCTION_ENTRY
 art_get_obj_instance_from_code:
+    .cpload $25
     SETUP_REF_ONLY_CALLEE_SAVE_FRAME     # save callee saves in case of GC
     lw     $a2, 48($sp)                  # pass referrer's Method*
+    move   $t0, $sp                      # save $sp
+    addiu  $sp, $sp, -16                 # make space for extra args
     move   $a3, rSELF                    # pass Thread::Current
-    jal     artGetObjInstanceFromCode    # (field_idx, Object*, referrer, Thread*, $sp)
-    sw     $sp, 0($sp)                   # pass $sp
+    jal    artGetObjInstanceFromCode     # (field_idx, Object*, referrer, Thread*, $sp)
+    sw     $t0, 16($sp)                  # pass $sp
+    addiu  $sp, $sp, 16                  # release out args
     RETURN_IF_NO_EXCEPTION
 
     .global art_set32_static_from_code
@@ -590,11 +628,15 @@
      */
     ALIGN_FUNCTION_ENTRY
 art_set32_static_from_code:
+    .cpload $25
     SETUP_REF_ONLY_CALLEE_SAVE_FRAME     # save callee saves in case of GC
     lw     $a2, 48($sp)                  # pass referrer's Method*
+    move   $t0, $sp                      # save $sp
+    addiu  $sp, $sp, -16                 # make space for extra args
     move   $a3, rSELF                    # pass Thread::Current
-    jal     artSet32StaticFromCode       # (field_idx, new_val, referrer, Thread*, $sp)
-    sw     $sp, 0($sp)                   # pass $sp
+    jal    artSet32StaticFromCode        # (field_idx, new_val, referrer, Thread*, $sp)
+    sw     $t0, 16($sp)                  # pass $sp
+    addiu  $sp, $sp, 16                  # release out args
     RETURN_IF_ZERO
 
     .global art_set64_static_from_code
@@ -604,14 +646,15 @@
      */
     ALIGN_FUNCTION_ENTRY
 art_set64_static_from_code:
+    .cpload $25
     SETUP_REF_ONLY_CALLEE_SAVE_FRAME     # save callee saves in case of GC
     lw     $a1, 48($sp)                  # pass referrer's Method*
     move   $t0, $sp                      # save $sp
-    addiu  $sp, $sp, -16
-    sw     rSELF, 0($sp)                 # pass Thread::Current and $sp
+    addiu  $sp, $sp, -16                 # make space for extra args
+    sw     rSELF, 16($sp)                # pass Thread::Current
     jal    artSet64StaticFromCode        # (field_idx, referrer, new_val, Thread*, $sp)
-    sw     $t0, 4($sp)
-    addiu  $sp, #16                      # release out args
+    sw     $t0, 20($sp)                  # pass $sp
+    addiu  $sp, $sp, 16                  # release out args
     RETURN_IF_ZERO
 
     .global art_set_obj_static_from_code
@@ -621,11 +664,15 @@
      */
     ALIGN_FUNCTION_ENTRY
 art_set_obj_static_from_code:
+    .cpload $25
     SETUP_REF_ONLY_CALLEE_SAVE_FRAME     # save callee saves in case of GC
     lw     $a2, 48($sp)                  # pass referrer's Method*
+    move   $t0, $sp                      # save $sp
+    addiu  $sp, $sp, -16                 # make space for extra args
     move   $a3, rSELF                    # pass Thread::Current
-    jal     artSetObjStaticFromCode      # (field_idx, new_val, referrer, Thread*, $sp)
-    sw     $sp, 0($sp)                   # pass $sp
+    jal    artSetObjStaticFromCode       # (field_idx, new_val, referrer, Thread*, $sp)
+    sw     $t0, 16($sp)                  # pass $sp
+    addiu  $sp, $sp, 16                  # release out args
     RETURN_IF_ZERO
 
     .global art_set32_instance_from_code
@@ -635,13 +682,14 @@
      */
     ALIGN_FUNCTION_ENTRY
 art_set32_instance_from_code:
+    .cpload $25
     SETUP_REF_ONLY_CALLEE_SAVE_FRAME     # save callee saves in case of GC
     lw     $a3, 48($sp)                  # pass referrer's Method*
     move   $t0, $sp                      # save $sp
-    addiu  $sp, $sp, -16
-    sw     rSELF, 0($sp)                 # pass Thread::Current and $sp
+    addiu  $sp, $sp, -16                 # make space for extra args
+    sw     rSELF, 16($sp)                # pass Thread::Current
     jal    artSet32InstanceFromCode      # (field_idx, Object*, new_val, referrer, Thread*, $sp)
-    sw     $t0, 4($sp)
+    sw     $t0, 20($sp)                  # pass $sp
     addiu  $sp, $sp, 16                  # release out args
     RETURN_IF_ZERO
 
@@ -652,12 +700,13 @@
      */
     ALIGN_FUNCTION_ENTRY
 art_set64_instance_from_code:
+    .cpload $25
     SETUP_REF_ONLY_CALLEE_SAVE_FRAME     # save callee saves in case of GC
     move   $t0, $sp                      # save $sp
-    addiu  $sp, $sp, -16
-    sw     rSELF, 0($sp)                 # pass Thread::Current and $sp
-    jal     artSet64InstanceFromCode     # (field_idx, Object*, new_val, Thread*, $sp)
-    sw     $t0, 4($sp)
+    addiu  $sp, $sp, -16                 # make space for extra args
+    sw     rSELF, 16($sp)                # pass Thread::Current
+    jal    artSet64InstanceFromCode      # (field_idx, Object*, new_val, Thread*, $sp)
+    sw     $t0, 20($sp)                  # pass $sp
     addiu  $sp, $sp, 16                  # release out args
     RETURN_IF_ZERO
 
@@ -668,13 +717,14 @@
      */
     ALIGN_FUNCTION_ENTRY
 art_set_obj_instance_from_code:
+    .cpload $25
     SETUP_REF_ONLY_CALLEE_SAVE_FRAME     # save callee saves in case of GC
     lw     $a3, 48($sp)                  # pass referrer's Method*
     move   $t0, $sp                      # save $sp
-    addiu  $sp, $sp, -16
-    sw     rSELF, 0($sp)                 # pass Thread::Current and $sp
-    jal     artSetObjInstanceFromCode    # (field_idx, Object*, new_val, referrer, Thread*, $sp)
-    sw     $t0, 4($sp)
+    addiu  $sp, $sp, -16                 # make space for extra args
+    sw     rSELF, 16($sp)                # pass Thread::Current
+    jal    artSetObjInstanceFromCode     # (field_idx, Object*, new_val, referrer, Thread*, $sp)
+    sw     $t0, 20($sp)                  # pass $sp
     addiu  $sp, $sp, 16                  # release out args
     RETURN_IF_ZERO
 
@@ -688,12 +738,13 @@
      */
     ALIGN_FUNCTION_ENTRY
 art_resolve_string_from_code:
+    .cpload $25
     SETUP_REF_ONLY_CALLEE_SAVE_FRAME  # save callee saves in case of GC
     move    $a2, rSELF                # pass Thread::Current
     # artResolveStringFromCode(Method* referrer, uint32_t string_idx, Thread*, $sp)
     jal     artResolveStringFromCode
     move    $a3, $sp                  # pass $sp
-    RETURN_IF_ZERO
+    RETURN_IF_NONZERO
 
     .global art_alloc_object_from_code
     .extern artAllocObjectFromCode
@@ -702,6 +753,7 @@
      */
     ALIGN_FUNCTION_ENTRY
 art_alloc_object_from_code:
+    .cpload $25
     SETUP_REF_ONLY_CALLEE_SAVE_FRAME  # save callee saves in case of GC
     move    $a2, rSELF                # pass Thread::Current
     jal     artAllocObjectFromCode    # (uint32_t type_idx, Method* method, Thread*, $sp)
@@ -716,6 +768,7 @@
      */
     ALIGN_FUNCTION_ENTRY
 art_alloc_object_from_code_with_access_check:
+    .cpload $25
     SETUP_REF_ONLY_CALLEE_SAVE_FRAME  # save callee saves in case of GC
     move    $a2, rSELF                # pass Thread::Current
     jal     artAllocObjectFromCodeWithAccessCheck  # (uint32_t type_idx, Method* method, Thread*, $sp)
@@ -729,11 +782,15 @@
      */
     ALIGN_FUNCTION_ENTRY
 art_alloc_array_from_code:
+    .cpload $25
     SETUP_REF_ONLY_CALLEE_SAVE_FRAME  # save callee saves in case of GC
     move    $a3, rSELF                # pass Thread::Current
+    move    $t0, $sp                  # save $sp
+    addiu   $sp, $sp, -16             # make space for extra args
     # artAllocArrayFromCode(uint32_t type_idx, Method* method, int32_t component_count, Thread*, $sp)
     jal     artAllocArrayFromCode
-    sw    $sp, 0($sp)                 # pass $sp
+    sw      $t0, 16($sp)              # pass $sp
+    addiu   $sp, $sp, 16              # release out args
     RETURN_IF_NONZERO
 
     .global art_alloc_array_from_code_with_access_check
@@ -744,11 +801,15 @@
      */
     ALIGN_FUNCTION_ENTRY
 art_alloc_array_from_code_with_access_check:
+    .cpload $25
     SETUP_REF_ONLY_CALLEE_SAVE_FRAME  # save callee saves in case of GC
     move    $a3, rSELF                # pass Thread::Current
+    move    $t0, $sp                  # save $sp
+    addiu   $sp, $sp, -16             # make space for extra args
     # artAllocArrayFromCodeWithAccessCheck(type_idx, method, component_count, Thread*, $sp)
     jal     artAllocArrayFromCodeWithAccessCheck
-    sw      $sp, 0($sp)               # pass $sp
+    sw      $t0, 16($sp)              # pass $sp
+    addiu   $sp, $sp, 16              # release out args
     RETURN_IF_NONZERO
 
     .global art_check_and_alloc_array_from_code
@@ -758,11 +819,15 @@
      */
     ALIGN_FUNCTION_ENTRY
 art_check_and_alloc_array_from_code:
+    .cpload $25
     SETUP_REF_ONLY_CALLEE_SAVE_FRAME  # save callee saves in case of GC
     move    $a3, rSELF                # pass Thread::Current
+    move    $t0, $sp                  # save $sp
+    addiu   $sp, $sp, -16             # make space for extra args
     # artCheckAndAllocArrayFromCode(uint32_t type_idx, Method* method, int32_t count, Thread* , $sp)
     jal     artCheckAndAllocArrayFromCode
-    sw      $sp, 0($sp)               # pass $sp
+    sw      $t0, 16($sp)              # pass $sp
+    addiu   $sp, $sp, 16              # release out args
     RETURN_IF_NONZERO
 
     .global art_check_and_alloc_array_from_code_with_access_check
@@ -772,11 +837,15 @@
      */
     ALIGN_FUNCTION_ENTRY
 art_check_and_alloc_array_from_code_with_access_check:
+    .cpload $25
     SETUP_REF_ONLY_CALLEE_SAVE_FRAME  # save callee saves in case of GC
-    move   $a3, rSELF                 # pass Thread::Current
+    move    $a3, rSELF                # pass Thread::Current
+    move    $t0, $sp                  # save $sp
+    addiu   $sp, $sp, -16             # make space for extra args
     # artCheckAndAllocArrayFromCodeWithAccessCheck(type_idx, method, count, Thread* , $sp)
     jal     artCheckAndAllocArrayFromCodeWithAccessCheck
-    sw     $sp, 0($sp)                # pass $sp
+    sw      $t0, 16($sp)              # pass $sp
+    addiu   $sp, $sp, 16              # release out args
     RETURN_IF_NONZERO
 
     .global art_test_suspend
@@ -806,16 +875,16 @@
      */
     ALIGN_FUNCTION_ENTRY
 art_proxy_invoke_handler:
+    .cpload $25
     SETUP_REF_AND_ARGS_CALLEE_SAVE_FRAME
     sw      $a0, 0($sp)            # place proxy method at bottom of frame
     move    $a2, rSELF             # pass Thread::Current
     jal     artProxyInvokeHandler  # (Method* proxy method, receiver, Thread*, args...)
-    addiu   $a3, $sp, 12           # pointer to r2/r3/LR/caller's Method**/out-args as second arg
+    addiu   $a3, $sp, 8            # pointer to a2/a3/ra/caller's Method**/out-args as second arg
     lw      $t0, THREAD_EXCEPTION_OFFSET(rSELF) # load Thread::Current()->exception_
-#FIXME - offsets here are probably wrong
     lw      $ra, 44($sp)           # restore $ra
-    lw      $v0, 12($sp)
-    lw      $v1, 14($sp)
+    lw      $v0, 8($sp)
+    lw      $v1, 12($sp)
     bnez    $t0, 1f
     addiu   $sp, $sp, 48           # pop frame
     jr      $ra
@@ -830,6 +899,7 @@
      */
     ALIGN_FUNCTION_ENTRY
 art_trace_entry_from_code:
+    .cpload $25
     addiu    $sp, $sp, -16
     sw       $a0, 0($sp)
     sw       $a1, 4($sp)
@@ -854,6 +924,7 @@
      */
     ALIGN_FUNCTION_ENTRY
 art_trace_exit_from_code:
+    .cpload $25
     addiu    $sp, $sp, -16
     sw       $v0, 0($sp)
     jal      artTraceMethodExitFromCode  # ()
diff --git a/src/oat/runtime/mips/stub_mips.cc b/src/oat/runtime/mips/stub_mips.cc
index 9691308..9fd65c8 100644
--- a/src/oat/runtime/mips/stub_mips.cc
+++ b/src/oat/runtime/mips/stub_mips.cc
@@ -30,28 +30,27 @@
 ByteArray* MipsCreateResolutionTrampoline(Runtime::TrampolineType type) {
   UniquePtr<MipsAssembler> assembler(static_cast<MipsAssembler*>(Assembler::Create(kMips)));
 #if !defined(ART_USE_LLVM_COMPILER)
-  // | Out args |
-  // | Method*  | <- SP on entry
-  // | RA       |    return address into caller
-  // | ...      |    callee saves
-  // | A3       |    possible argument
-  // | A2       |    possible argument
-  // | A1       |    possible argument
-  // | A0       |    junk on call to UnresolvedDirectMethodTrampolineFromCode, holds result Method*
-  // | Method*  |    Callee save Method* set up by UnresolvedDirectMethodTrampolineFromCode
+  // | Out args   |
+  // | Method*    | <- SP on entry
+  // | RA         |    return address into caller
+  // | ...        |    callee saves
+  // | A3         |    possible argument
+  // | A2         |    possible argument
+  // | A1         |    possible argument
+  // | A0/Method* |    Callee save Method* set up by UnresolvedDirectMethodTrampolineFromCode
   // Save callee saves and ready frame for exception delivery
-  __ AddConstant(SP, SP, -64);
-  __ StoreToOffset(kStoreWord, RA, SP, 60);
-  __ StoreToOffset(kStoreWord, FP, SP, 56);
-  __ StoreToOffset(kStoreWord, S7, SP, 52);
-  __ StoreToOffset(kStoreWord, S6, SP, 48);
-  __ StoreToOffset(kStoreWord, S5, SP, 44);
-  __ StoreToOffset(kStoreWord, S4, SP, 40);
-  __ StoreToOffset(kStoreWord, S3, SP, 36);
-  __ StoreToOffset(kStoreWord, S2, SP, 32);
-  __ StoreToOffset(kStoreWord, A3, SP, 28);
-  __ StoreToOffset(kStoreWord, A2, SP, 24);
-  __ StoreToOffset(kStoreWord, A1, SP, 20);
+  __ AddConstant(SP, SP, -48);
+  __ StoreToOffset(kStoreWord, RA, SP, 44);
+  __ StoreToOffset(kStoreWord, FP, SP, 40);
+  __ StoreToOffset(kStoreWord, S7, SP, 36);
+  __ StoreToOffset(kStoreWord, S6, SP, 32);
+  __ StoreToOffset(kStoreWord, S5, SP, 28);
+  __ StoreToOffset(kStoreWord, S4, SP, 24);
+  __ StoreToOffset(kStoreWord, S3, SP, 20);
+  __ StoreToOffset(kStoreWord, S2, SP, 16);
+  __ StoreToOffset(kStoreWord, A3, SP, 12);
+  __ StoreToOffset(kStoreWord, A2, SP, 8);
+  __ StoreToOffset(kStoreWord, A1, SP, 4);
 
   __ LoadFromOffset(kLoadWord, T9, S1,
                     ENTRYPOINT_OFFSET(pUnresolvedDirectMethodTrampolineFromCode));
@@ -61,20 +60,20 @@
   __ Jalr(T9); // Call to unresolved direct method trampoline (method_idx, sp, Thread*, is_static)
 
   // Restore registers which may have been modified by GC
-  __ LoadFromOffset(kLoadWord, A1, SP, 20);
-  __ LoadFromOffset(kLoadWord, A2, SP, 24);
-  __ LoadFromOffset(kLoadWord, A3, SP, 28);
-  __ LoadFromOffset(kLoadWord, S2, SP, 32);
-  __ LoadFromOffset(kLoadWord, S3, SP, 36);
-  __ LoadFromOffset(kLoadWord, S4, SP, 40);
-  __ LoadFromOffset(kLoadWord, S5, SP, 44);
-  __ LoadFromOffset(kLoadWord, S6, SP, 48);
-  __ LoadFromOffset(kLoadWord, S7, SP, 52);
-  __ LoadFromOffset(kLoadWord, FP, SP, 56);
-  __ LoadFromOffset(kLoadWord, RA, SP, 60);
-  __ AddConstant(SP, SP, 64);
+  __ LoadFromOffset(kLoadWord, A0, SP, 0);
+  __ LoadFromOffset(kLoadWord, A1, SP, 4);
+  __ LoadFromOffset(kLoadWord, A2, SP, 8);
+  __ LoadFromOffset(kLoadWord, A3, SP, 12);
+  __ LoadFromOffset(kLoadWord, S2, SP, 16);
+  __ LoadFromOffset(kLoadWord, S3, SP, 20);
+  __ LoadFromOffset(kLoadWord, S4, SP, 24);
+  __ LoadFromOffset(kLoadWord, S5, SP, 28);
+  __ LoadFromOffset(kLoadWord, S6, SP, 32);
+  __ LoadFromOffset(kLoadWord, S7, SP, 36);
+  __ LoadFromOffset(kLoadWord, FP, SP, 40);
+  __ LoadFromOffset(kLoadWord, RA, SP, 44);
+  __ AddConstant(SP, SP, 48);
 
-  __ Move(A0, V0); // Put returned Method* into A0
   __ Jr(V0);  // Leaf call to method's code
 
   __ Break();
diff --git a/src/oat/runtime/support_invoke.cc b/src/oat/runtime/support_invoke.cc
index e66749d..4f16afe 100644
--- a/src/oat/runtime/support_invoke.cc
+++ b/src/oat/runtime/support_invoke.cc
@@ -74,6 +74,24 @@
     DCHECK_EQ(32U, Runtime::Current()->GetCalleeSaveMethod(Runtime::kRefsAndArgs)->GetFrameSizeInBytes());
     uintptr_t* regs = reinterpret_cast<uintptr_t*>(reinterpret_cast<byte*>(sp));
     uintptr_t caller_pc = regs[7];
+#elif defined(__mips__)
+    // On entry the stack pointed by sp is:
+    // | argN       |  |
+    // | ...        |  |
+    // | arg4       |  |
+    // | arg3 spill |  |  Caller's frame
+    // | arg2 spill |  |
+    // | arg1 spill |  |
+    // | Method*    | ---
+    // | RA         |
+    // | ...        |    callee saves
+    // | A3         |    arg3
+    // | A2         |    arg2
+    // | A1         |    arg1
+    // | A0/Method* |  <- sp
+    DCHECK_EQ(48U, Runtime::Current()->GetCalleeSaveMethod(Runtime::kRefsAndArgs)->GetFrameSizeInBytes());
+    uintptr_t* regs = reinterpret_cast<uintptr_t*>(reinterpret_cast<byte*>(sp));
+    uintptr_t caller_pc = regs[11];
 #else
     UNIMPLEMENTED(FATAL);
     uintptr_t caller_pc = 0;
diff --git a/src/oat/runtime/support_stubs.cc b/src/oat/runtime/support_stubs.cc
index fa8356e..9e33c43 100644
--- a/src/oat/runtime/support_stubs.cc
+++ b/src/oat/runtime/support_stubs.cc
@@ -54,7 +54,8 @@
   DCHECK_EQ(48U, Runtime::Current()->GetCalleeSaveMethod(Runtime::kRefsAndArgs)->GetFrameSizeInBytes());
   AbstractMethod** caller_sp = reinterpret_cast<AbstractMethod**>(reinterpret_cast<byte*>(sp) + 48);
   uintptr_t* regs = reinterpret_cast<uintptr_t*>(reinterpret_cast<byte*>(sp) + kPointerSize);
-  uintptr_t caller_pc = regs[10];
+  uint32_t pc_offset = 10;
+  uintptr_t caller_pc = regs[pc_offset];
 #elif defined(__i386__)
   // On entry the stack pointed by sp is:
   // | argN        |  |
@@ -74,6 +75,26 @@
   AbstractMethod** caller_sp = reinterpret_cast<AbstractMethod**>(reinterpret_cast<byte*>(sp) + 32);
   uintptr_t* regs = reinterpret_cast<uintptr_t*>(reinterpret_cast<byte*>(sp));
   uintptr_t caller_pc = regs[7];
+#elif defined(__mips__)
+  // On entry the stack pointed by sp is:
+  // | argN       |  |
+  // | ...        |  |
+  // | arg4       |  |
+  // | arg3 spill |  |  Caller's frame
+  // | arg2 spill |  |
+  // | arg1 spill |  |
+  // | Method*    | ---
+  // | RA         |
+  // | ...        |    callee saves
+  // | A3         |    arg3
+  // | A2         |    arg2
+  // | A1         |    arg1
+  // | A0/Method* |  <- sp
+  DCHECK_EQ(48U, Runtime::Current()->GetCalleeSaveMethod(Runtime::kRefsAndArgs)->GetFrameSizeInBytes());
+  AbstractMethod** caller_sp = reinterpret_cast<AbstractMethod**>(reinterpret_cast<byte*>(sp) + 48);
+  uintptr_t* regs = reinterpret_cast<uintptr_t*>(reinterpret_cast<byte*>(sp));
+  uint32_t pc_offset = 11;
+  uintptr_t caller_pc = regs[pc_offset];
 #else
   UNIMPLEMENTED(FATAL);
   AbstractMethod** caller_sp = NULL;
@@ -173,7 +194,7 @@
     cur_arg = cur_arg + (c == 'J' || c == 'D' ? 2 : 1);
   }
   // Place into local references incoming arguments from the caller's stack arguments
-  cur_arg += 11;  // skip LR, Method* and spills for R1 to R3 and callee saves
+  cur_arg += pc_offset + 1;  // skip LR/RA, Method* and spills for R1-R3/A1-A3 and callee saves
   while (shorty_index < shorty_len) {
     char c = shorty[shorty_index];
     shorty_index++;
diff --git a/src/runtime.cc b/src/runtime.cc
index 62447df..e3384df 100644
--- a/src/runtime.cc
+++ b/src/runtime.cc
@@ -1014,8 +1014,8 @@
                           (1 << art::arm::R8) | (1 << art::arm::R10) | (1 << art::arm::R11);
     uint32_t arg_spills = (1 << art::arm::R1) | (1 << art::arm::R2) | (1 << art::arm::R3);
     uint32_t all_spills = (1 << art::arm::R4) | (1 << art::arm::R9);
-    uint32_t core_spills = ref_spills | (type == kRefsAndArgs ? arg_spills :0) |
-                           (type == kSaveAll ? all_spills :0) | (1 << art::arm::LR);
+    uint32_t core_spills = ref_spills | (type == kRefsAndArgs ? arg_spills : 0) |
+                           (type == kSaveAll ? all_spills : 0) | (1 << art::arm::LR);
     uint32_t fp_all_spills = (1 << art::arm::S0)  | (1 << art::arm::S1)  | (1 << art::arm::S2) |
                              (1 << art::arm::S3)  | (1 << art::arm::S4)  | (1 << art::arm::S5) |
                              (1 << art::arm::S6)  | (1 << art::arm::S7)  | (1 << art::arm::S8) |
@@ -1039,9 +1039,11 @@
                           (1 << art::mips::S5) | (1 << art::mips::S6) | (1 << art::mips::S7) |
                           (1 << art::mips::FP);
     uint32_t arg_spills = (1 << art::mips::A1) | (1 << art::mips::A2) | (1 << art::mips::A3);
+    uint32_t all_spills = (1 << art::mips::S0) | (1 << art::mips::S1);
     uint32_t core_spills = ref_spills | (type == kRefsAndArgs ? arg_spills : 0) |
-                           (1 << art::mips::RA);
+                           (type == kSaveAll ? all_spills : 0) | (1 << art::mips::RA);
     size_t frame_size = RoundUp((__builtin_popcount(core_spills) /* gprs */ +
+                                 (type == kRefsAndArgs ? 0 : 3) /* always reserve arg space */ +
                                  1 /* Method* */) * kPointerSize, kStackAlignment);
     method->SetFrameSizeInBytes(frame_size);
     method->SetCoreSpillMask(core_spills);