Fix quick mode bugs for Mips.

This patch enable quick mode for Mips and allows the emulator to boot.
However the emulator is still not 100% functional. It still have problems
launching some apps.

Change-Id: Id46a39a649a2fd431a9f13b06ecf34cbd1d20930
Signed-off-by: Douglas Leung <douglas@mips.com>
diff --git a/compiler/dex/quick/mips/target_mips.cc b/compiler/dex/quick/mips/target_mips.cc
index 76b5243..1d02cf7 100644
--- a/compiler/dex/quick/mips/target_mips.cc
+++ b/compiler/dex/quick/mips/target_mips.cc
@@ -75,6 +75,13 @@
   return mips_loc_c_return_double;
 }
 
+// Convert k64BitSolo into k64BitPair
+RegStorage MipsMir2Lir::Solo64ToPair64(RegStorage reg) {
+    DCHECK(reg.IsDouble());
+    int reg_num = (reg.GetRegNum() & ~1) | RegStorage::kFloatingPoint;
+    return RegStorage(RegStorage::k64BitPair, reg_num, reg_num + 1);
+}
+
 // Return a target-dependent special register.
 RegStorage MipsMir2Lir::TargetReg(SpecialTargetRegister reg) {
   RegStorage res_reg;
@@ -123,7 +130,11 @@
 ResourceMask MipsMir2Lir::GetRegMaskCommon(const RegStorage& reg) const {
   return reg.IsDouble()
       /* Each double register is equal to a pair of single-precision FP registers */
+#if (FR_BIT == 0)
+      ? ResourceMask::TwoBits((reg.GetRegNum() & ~1) + kMipsFPReg0)
+#else
       ? ResourceMask::TwoBits(reg.GetRegNum() * 2 + kMipsFPReg0)
+#endif
       : ResourceMask::Bit(reg.IsSingle() ? reg.GetRegNum() + kMipsFPReg0 : reg.GetRegNum());
 }
 
@@ -443,7 +454,11 @@
   GrowableArray<RegisterInfo*>::Iterator it(&reg_pool_->sp_regs_);
   for (RegisterInfo* info = it.Next(); info != nullptr; info = it.Next()) {
     int sp_reg_num = info->GetReg().GetRegNum();
+#if (FR_BIT == 0)
+    int dp_reg_num = sp_reg_num & ~1;
+#else
     int dp_reg_num = sp_reg_num >> 1;
+#endif
     RegStorage dp_reg = RegStorage::Solo64(RegStorage::kFloatingPoint | dp_reg_num);
     RegisterInfo* dp_reg_info = GetRegInfo(dp_reg);
     // Double precision register's master storage should refer to itself.
@@ -462,7 +477,11 @@
   // TODO: adjust when we roll to hard float calling convention.
   reg_pool_->next_core_reg_ = 2;
   reg_pool_->next_sp_reg_ = 2;
+#if (FR_BIT == 0)
+  reg_pool_->next_dp_reg_ = 2;
+#else
   reg_pool_->next_dp_reg_ = 1;
+#endif
 }
 
 /*
@@ -531,8 +550,13 @@
 }
 
 RegisterClass MipsMir2Lir::RegClassForFieldLoadStore(OpSize size, bool is_volatile) {
-  // No support for 64-bit atomic load/store on mips.
-  DCHECK(size != k64 && size != kDouble);
+  if (UNLIKELY(is_volatile)) {
+    // On Mips, atomic 64-bit load/store requires an fp register.
+    // Smaller aligned load/store is atomic for both core and fp registers.
+    if (size == k64 || size == kDouble) {
+      return kFPReg;
+    }
+  }
   // TODO: Verify that both core and fp registers are suitable for smaller sizes.
   return RegClassBySize(size);
 }