Fixes to make jni_compiler_test work on MIPS.

Fixed the jni compiler in numerous ways:
- Added NOP for delay slot of branches/jumps
- Made calling convention match registers pushed by stubs
- Fixes to assembly and added noreorder directive

Change-Id: I32bc55985fbbc58b5b5358149766b8738b3ac955
diff --git a/src/oat/jni/jni_compiler.cc b/src/oat/jni/jni_compiler.cc
index 7b710c5..585d60e 100644
--- a/src/oat/jni/jni_compiler.cc
+++ b/src/oat/jni/jni_compiler.cc
@@ -288,6 +288,11 @@
   // 11. Save return value
   FrameOffset return_save_location = main_jni_conv->ReturnValueSaveLocation();
   if (main_jni_conv->SizeOfReturnValue() != 0 && !reference_return) {
+    if (instruction_set == kMips && main_jni_conv->GetReturnType() == Primitive::kPrimDouble &&
+        return_save_location.Uint32Value() % 8 != 0) {
+      // Ensure doubles are 8-byte aligned for MIPS
+      return_save_location = FrameOffset(return_save_location.Uint32Value() + kPointerSize);
+    }
     CHECK_LT(return_save_location.Uint32Value(), frame_size+main_out_arg_size);
     __ Store(return_save_location, main_jni_conv->ReturnRegister(), main_jni_conv->SizeOfReturnValue());
   }
diff --git a/src/oat/jni/mips/calling_convention_mips.cc b/src/oat/jni/mips/calling_convention_mips.cc
index 09cc16d..606c05a 100644
--- a/src/oat/jni/mips/calling_convention_mips.cc
+++ b/src/oat/jni/mips/calling_convention_mips.cc
@@ -59,7 +59,7 @@
 // Managed runtime calling convention
 
 ManagedRegister MipsManagedRuntimeCallingConvention::MethodRegister() {
-  return MipsManagedRegister::FromCoreRegister(V0);
+  return MipsManagedRegister::FromCoreRegister(A0);
 }
 
 bool MipsManagedRuntimeCallingConvention::IsCurrentParamInRegister() {
@@ -107,7 +107,7 @@
                                                  const char* shorty)
     : JniCallingConvention(is_static, is_synchronized, shorty) {
   // Compute padding to ensure longs and doubles are not split in AAPCS. Ignore the 'this' jobject
-  // or jclass for static methods and the JNIEnv. We start at the aligned register r2.
+  // or jclass for static methods and the JNIEnv. We start at the aligned register A2.
   size_t padding = 0;
   for (size_t cur_arg = IsStatic() ? 0 : 1, cur_reg = 2; cur_arg < NumArgs(); cur_arg++) {
     if (IsParamALongOrDouble(cur_arg)) {
@@ -198,7 +198,7 @@
 
 FrameOffset MipsJniCallingConvention::CurrentParamStackOffset() {
   CHECK_GE(itr_slots_, 4u);
-  size_t offset = displacement_.Int32Value() - OutArgSize() + ((itr_slots_ - 4) * kPointerSize);
+  size_t offset = displacement_.Int32Value() - OutArgSize() + (itr_slots_ * kPointerSize);
   CHECK_LT(offset, OutArgSize());
   return FrameOffset(offset);
 }
@@ -207,8 +207,8 @@
   size_t static_args = IsStatic() ? 1 : 0;  // count jclass
   // regular argument parameters and this
   size_t param_args = NumArgs() + NumLongOrDoubleArgs();
-  // count JNIEnv* less arguments in registers
-  return static_args + param_args + 1 - 4;
+  // count JNIEnv*
+  return static_args + param_args + 1;
 }
 }  // namespace mips
 }  // namespace art
diff --git a/src/oat/jni/mips/jni_internal_mips.cc b/src/oat/jni/mips/jni_internal_mips.cc
index ea2d7a1..6021cc1 100644
--- a/src/oat/jni/mips/jni_internal_mips.cc
+++ b/src/oat/jni/mips/jni_internal_mips.cc
@@ -73,6 +73,9 @@
     reg_bytes = num_arg_array_bytes;
   }
 
+  // Method* at bottom of frame is null thereby terminating managed stack crawls
+  __ StoreToOffset(kStoreWord, ZERO, SP, 0);
+
   // Copy values onto the stack.
   size_t src_offset = 0;
   size_t dst_offset = (is_static ? 1 : 2) * kPointerSize;
@@ -131,7 +134,7 @@
   // If the method returns a value, store it to the result pointer.
   if (shorty[0] != 'V') {
     // Load the result JValue pointer of the stub caller's out args.
-    __ LoadFromOffset(kLoadWord, T9, SP, frame_size);
+    __ LoadFromOffset(kLoadWord, T9, SP, frame_size + 16);
     switch (shorty[0]) {
       case 'D':
         __ StoreDToOffset(D0, T9, 0);
diff --git a/src/oat/runtime/mips/context_mips.cc b/src/oat/runtime/mips/context_mips.cc
index 1a4cb5d..dc13c63 100644
--- a/src/oat/runtime/mips/context_mips.cc
+++ b/src/oat/runtime/mips/context_mips.cc
@@ -30,7 +30,6 @@
   for (int i = 0; i < 32; i++) {
     fprs_[i] = kBadGprBase + i;
   }
-  pc_ = 0xEBAD601F;
 #endif
 }
 
@@ -56,7 +55,7 @@
     int j = 1;
     for (int i = 0; i < 32; i++) {
       if (((fp_core_spills >> i) & 1) != 0) {
-        fprs_[i] = fr.LoadCalleeSave(spill_count +fp_spill_count - j, frame_size);
+        fprs_[i] = fr.LoadCalleeSave(spill_count + fp_spill_count - j, frame_size);
         j++;
       }
     }
@@ -69,7 +68,6 @@
   gprs_[A1] = kBadGprBase + A1;
   gprs_[A2] = kBadGprBase + A2;
   gprs_[A3] = kBadGprBase + A3;
-  gprs_[RA] = kBadGprBase + RA;
 }
 
 extern "C" void art_do_long_jump(uint32_t*, uint32_t*);
diff --git a/src/oat/runtime/mips/context_mips.h b/src/oat/runtime/mips/context_mips.h
index da4fc6a..1a86ca3 100644
--- a/src/oat/runtime/mips/context_mips.h
+++ b/src/oat/runtime/mips/context_mips.h
@@ -36,7 +36,7 @@
   }
 
   virtual void SetPC(uintptr_t new_pc) {
-    pc_ = new_pc;
+    gprs_[RA] = new_pc;
   }
 
   virtual uintptr_t GetGPR(uint32_t reg) {
@@ -51,7 +51,6 @@
  private:
   uintptr_t gprs_[32];
   uint32_t fprs_[32];
-  uintptr_t pc_;
 };
 }  // namespace mips
 }  // namespace art
diff --git a/src/oat/runtime/mips/runtime_support_mips.S b/src/oat/runtime/mips/runtime_support_mips.S
index 6946825..2f7d120 100644
--- a/src/oat/runtime/mips/runtime_support_mips.S
+++ b/src/oat/runtime/mips/runtime_support_mips.S
@@ -16,6 +16,7 @@
 
 #include "asm_support.h"
 
+    .set noreorder
     .balign 4
 
     /* Deliver the given exception */
@@ -31,10 +32,10 @@
     /*
      * Macro that sets up the callee save frame to conform with
      * Runtime::CreateCalleeSaveMethod(kSaveAll)
-     * callee-save: $s0-$s8 + $ra, 10 total + 2 words
+     * callee-save: $s2-$s8 + $ra, 8 total + 2 words
      */
 .macro SETUP_SAVE_ALL_CALLEE_SAVE_FRAME
-    addiu  $sp, $sp, 48
+    addiu  $sp, $sp, -48
     sw     $ra, 44($sp)
     sw     $s8, 40($sp)
     sw     $s7, 36($sp)
@@ -43,9 +44,7 @@
     sw     $s4, 24($sp)
     sw     $s3, 20($sp)
     sw     $s2, 16($sp)
-    sw     $s1, 12($sp)
-    sw     $s0, 8($sp)
-    # 2 open words, bottom will hold Method*
+    # 4 open words, bottom will hold Method*
 .endm
 
     /*
@@ -55,7 +54,7 @@
      * callee-save: $s2-$s8 + $ra, 8 total + 4 words
      */
 .macro SETUP_REF_ONLY_CALLEE_SAVE_FRAME
-    addiu  $sp, $sp, 48
+    addiu  $sp, $sp, -48
     sw     $ra, 44($sp)
     sw     $s8, 40($sp)
     sw     $s7, 36($sp)
@@ -84,7 +83,7 @@
      * $a1-$a3, $s2-$s8, $ra, 11 total + 1
      */
 .macro SETUP_REF_AND_ARGS_CALLEE_SAVE_FRAME
-    addiu  $sp, $sp, 48
+    addiu  $sp, $sp, -48
     sw     $ra, 44($sp)
     sw     $s8, 40($sp)
     sw     $s7, 36($sp)
@@ -945,8 +944,10 @@
     ALIGN_FUNCTION_ENTRY
 art_indexof:
     jr $ra
+    nop
 
     .global art_string_compareto
     ALIGN_FUNCTION_ENTRY
 art_string_compareto:
     jr $ra
+    nop
diff --git a/src/oat/runtime/mips/stub_mips.cc b/src/oat/runtime/mips/stub_mips.cc
index 8ab3f8d..4865c59 100644
--- a/src/oat/runtime/mips/stub_mips.cc
+++ b/src/oat/runtime/mips/stub_mips.cc
@@ -131,36 +131,20 @@
   UniquePtr<MipsAssembler> assembler(static_cast<MipsAssembler*>(Assembler::Create(kMips)));
 #if !defined(ART_USE_LLVM_COMPILER)
   // Save callee saves and ready frame for exception delivery
-  __ AddConstant(SP, SP, -176);
-  __ StoreToOffset(kStoreWord, RA, SP, 172);
-  __ StoreToOffset(kStoreWord, T9, SP, 168);
-  __ StoreToOffset(kStoreWord, T8, SP, 164);
-  __ StoreToOffset(kStoreWord, T7, SP, 160);
-  __ StoreToOffset(kStoreWord, T6, SP, 156);
-  __ StoreToOffset(kStoreWord, T5, SP, 152);
-  __ StoreToOffset(kStoreWord, T4, SP, 148);
-  __ StoreToOffset(kStoreWord, T3, SP, 144);
-  __ StoreToOffset(kStoreWord, T2, SP, 140);
-  __ StoreToOffset(kStoreWord, T1, SP, 136);
-  __ StoreToOffset(kStoreWord, T0, SP, 132);
-  __ StoreDToOffset(D15, SP, 124);
-  __ StoreDToOffset(D14, SP, 116);
-  __ StoreDToOffset(D13, SP, 108);
-  __ StoreDToOffset(D12, SP, 100);
-  __ StoreDToOffset(D11, SP, 92);
-  __ StoreDToOffset(D10, SP, 84);
-  __ StoreDToOffset(D9, SP, 76);
-  __ StoreDToOffset(D8, SP, 68);
-  __ StoreDToOffset(D7, SP, 60);
-  __ StoreDToOffset(D6, SP, 52);
-  __ StoreDToOffset(D5, SP, 44);
-  __ StoreDToOffset(D4, SP, 36);
-  __ StoreDToOffset(D3, SP, 28);
-  __ StoreDToOffset(D2, SP, 20);
-  __ StoreDToOffset(D1, SP, 12);
-  __ StoreDToOffset(D0, SP, 4);
+  __ AddConstant(SP, SP, -48);
+  __ StoreToOffset(kStoreWord, RA, SP, 44);
+  __ StoreToOffset(kStoreWord, T9, SP, 40);
+  __ StoreToOffset(kStoreWord, T8, SP, 36);
+  __ StoreToOffset(kStoreWord, T7, SP, 32);
+  __ StoreToOffset(kStoreWord, T6, SP, 28);
+  __ StoreToOffset(kStoreWord, T5, SP, 24);
+  __ StoreToOffset(kStoreWord, T4, SP, 20);
+  __ StoreToOffset(kStoreWord, T3, SP, 16);
+  __ StoreToOffset(kStoreWord, T2, SP, 12);
+  __ StoreToOffset(kStoreWord, T1, SP, 8);
+  __ StoreToOffset(kStoreWord, T0, SP, 4);
 
-  // R0 is the Method* already
+  // A0 is the Method* already
   __ Move(A1, S1);  // Pass Thread::Current() in A1
   __ Move(A2, SP);  // Pass SP in A2
   // Call to throw AbstractMethodError
diff --git a/src/oat/utils/mips/assembler_mips.cc b/src/oat/utils/mips/assembler_mips.cc
index e164241..be1aceb 100644
--- a/src/oat/utils/mips/assembler_mips.cc
+++ b/src/oat/utils/mips/assembler_mips.cc
@@ -349,26 +349,32 @@
 
 void MipsAssembler::Beq(Register rt, Register rs, uint16_t imm16) {
   EmitI(0x4, rs, rt, imm16);
+  Nop();
 }
 
 void MipsAssembler::Bne(Register rt, Register rs, uint16_t imm16) {
   EmitI(0x5, rs, rt, imm16);
+  Nop();
 }
 
 void MipsAssembler::J(uint32_t address) {
   EmitJ(0x2, address);
+  Nop();
 }
 
 void MipsAssembler::Jal(uint32_t address) {
   EmitJ(0x2, address);
+  Nop();
 }
 
 void MipsAssembler::Jr(Register rs) {
   EmitR(0, rs, static_cast<Register>(0), static_cast<Register>(0), 0, 0x08);
+  Nop();
 }
 
 void MipsAssembler::Jalr(Register rs) {
-  EmitR(0, rs, static_cast<Register>(0), static_cast<Register>(0), 0, 0x09);
+  EmitR(0, rs, static_cast<Register>(0), RA, 0, 0x09);
+  Nop();
 }
 
 void MipsAssembler::AddS(FRegister fd, FRegister fs, FRegister ft) {
@@ -445,6 +451,10 @@
         static_cast<Register>(0), 0, 0xD);
 }
 
+void MipsAssembler::Nop() {
+  EmitR(0x0, static_cast<Register>(0), static_cast<Register>(0), static_cast<Register>(0), 0, 0x0);
+}
+
 void MipsAssembler::Move(Register rt, Register rs) {
   EmitI(0x8, rs, rt, 0);
 }
@@ -604,6 +614,9 @@
 
   // Decrease frame to required size.
   DecreaseFrameSize(frame_size);
+
+  // Then jump to the return address.
+  Jr(RA);
 }
 
 void MipsAssembler::IncreaseFrameSize(size_t adjust) {
diff --git a/src/oat/utils/mips/assembler_mips.h b/src/oat/utils/mips/assembler_mips.h
index 8483e39..73937aa 100644
--- a/src/oat/utils/mips/assembler_mips.h
+++ b/src/oat/utils/mips/assembler_mips.h
@@ -296,6 +296,7 @@
   void Sdc1(DRegister ft, Register rs, uint16_t imm16);
 
   void Break();
+  void Nop();
   void Move(Register rt, Register rs);
   void Clear(Register rt);
   void Not(Register rt, Register rs);
diff --git a/src/oat/utils/mips/managed_register_mips.cc b/src/oat/utils/mips/managed_register_mips.cc
index b48c959..195dafb 100644
--- a/src/oat/utils/mips/managed_register_mips.cc
+++ b/src/oat/utils/mips/managed_register_mips.cc
@@ -69,9 +69,9 @@
     low = (r * 2) + kNumberOfCoreRegIds;  // Return an FRegister.
   } else {
     CHECK(IsRegisterPair());
-    low = (r - kNumberOfDRegIds) * 2;  // Return a Register.
-    if (low > 24) {
-      // we got a pair higher than T8_T9, must be the dalvik special case
+    low = (r - kNumberOfDRegIds) * 2 + 2;  // Return a Register.
+    if (low >= 24) {
+      // we got a pair higher than S6_S7, must be the dalvik special case
       low = 5;
     }
   }
diff --git a/src/runtime.cc b/src/runtime.cc
index 9983c7d..b4dfcfe 100644
--- a/src/runtime.cc
+++ b/src/runtime.cc
@@ -1009,27 +1009,13 @@
                           (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::S1) | (1 << art::mips::SP);
     uint32_t core_spills = ref_spills | (type == kRefsAndArgs ? arg_spills : 0) |
-                           (type == kSaveAll ? all_spills : 0) | (1 << art::mips::RA);
-    uint32_t fp_all_spills = (1 << art::mips::F0)  | (1 << art::mips::F1)  | (1 << art::mips::F2) |
-                             (1 << art::mips::F3)  | (1 << art::mips::F4)  | (1 << art::mips::F5) |
-                             (1 << art::mips::F6)  | (1 << art::mips::F7)  | (1 << art::mips::F8) |
-                             (1 << art::mips::F9)  | (1 << art::mips::F10) | (1 << art::mips::F11) |
-                             (1 << art::mips::F12) | (1 << art::mips::F13) | (1 << art::mips::F14) |
-                             (1 << art::mips::F15) | (1 << art::mips::F16) | (1 << art::mips::F17) |
-                             (1 << art::mips::F18) | (1 << art::mips::F19) | (1 << art::mips::F20) |
-                             (1 << art::mips::F21) | (1 << art::mips::F22) | (1 << art::mips::F23) |
-                             (1 << art::mips::F24) | (1 << art::mips::F25) | (1 << art::mips::F26) |
-                             (1 << art::mips::F27) | (1 << art::mips::F28) | (1 << art::mips::F29) |
-                             (1 << art::mips::F30) | (1 << art::mips::F31);
-    uint32_t fp_spills = type == kSaveAll ? fp_all_spills : 0;
+                           (1 << art::mips::RA);
     size_t frame_size = RoundUp((__builtin_popcount(core_spills) /* gprs */ +
-                                 __builtin_popcount(fp_spills) /* fprs */ +
                                  1 /* Method* */) * kPointerSize, kStackAlignment);
     method->SetFrameSizeInBytes(frame_size);
     method->SetCoreSpillMask(core_spills);
-    method->SetFpSpillMask(fp_spills);
+    method->SetFpSpillMask(0);
   } else if (instruction_set == kX86) {
     uint32_t ref_spills = (1 << art::x86::EBP) | (1 << art::x86::ESI) | (1 << art::x86::EDI);
     uint32_t arg_spills = (1 << art::x86::ECX) | (1 << art::x86::EDX) | (1 << art::x86::EBX);
diff --git a/src/thread_mips.cc b/src/thread_mips.cc
index b3e6454..bc343ed 100644
--- a/src/thread_mips.cc
+++ b/src/thread_mips.cc
@@ -22,7 +22,7 @@
 namespace art {
 
 void Thread::InitCpu() {
-  CHECK_EQ(THREAD_SUSPEND_COUNT_OFFSET, OFFSETOF_MEMBER(Thread, suspend_count_));
+  CHECK_EQ(THREAD_FLAGS_OFFSET, OFFSETOF_MEMBER(Thread, state_and_flags_));
   CHECK_EQ(THREAD_EXCEPTION_OFFSET, OFFSETOF_MEMBER(Thread, exception_));
 }