More MIPS support

Working through the unimps.

Change-Id: Ie088d2061ca9a77f42ebd75e2936159465deed10
diff --git a/src/compiler/codegen/GenCommon.cc b/src/compiler/codegen/GenCommon.cc
index 66950d2..4d80a69 100644
--- a/src/compiler/codegen/GenCommon.cc
+++ b/src/compiler/codegen/GenCommon.cc
@@ -584,9 +584,9 @@
 // Debugging routine - if null target, branch to DebugMe
 void genShowTarget(CompilationUnit* cUnit)
 {
-    LIR* branchOver = opCmpImmBranch(cUnit, kCondNe, rLINK, 0, NULL);
+    LIR* branchOver = opCmpImmBranch(cUnit, kCondNe, rINVOKE_TGT, 0, NULL);
     loadWordDisp(cUnit, rSELF,
-                 OFFSETOF_MEMBER(Thread, pDebugMe), rLINK);
+                 OFFSETOF_MEMBER(Thread, pDebugMe), rINVOKE_TGT);
     LIR* target = newLIR0(cUnit, kPseudoTargetLabel);
     target->defMask = -1;
     branchOver->target = (LIR*)target;
@@ -703,6 +703,7 @@
         }
         int rTgt = loadHelper(cUnit, funcOffset);
         callRuntimeHelper(cUnit, rTgt);
+        oatFreeTemp(cUnit, rTgt);
     }
 }
 
@@ -1022,28 +1023,34 @@
     DCHECK_EQ(Object::ClassOffset().Int32Value(), 0);
     loadWordDisp(cUnit, rARG0,  Object::ClassOffset().Int32Value(), rARG1);
     /* rARG0 is ref, rARG1 is ref->clazz, rARG2 is class */
+#if defined(TARGET_ARM)
+    /* Uses conditional nullification */
     int rTgt = loadHelper(cUnit, OFFSETOF_MEMBER(Thread,
                           pInstanceofNonTrivialFromCode));
-#if defined(TARGET_ARM)
     opRegReg(cUnit, kOpCmp, rARG1, rARG2);  // Same?
-    genBarrier(cUnit);
     opIT(cUnit, kArmCondEq, "EE");   // if-convert the test
     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)
-    genBarrier(cUnit);
-    oatClobberCalleeSave(cUnit);
 #else
-    (void)rTgt;
-    // Perhaps a general-purpose kOpSelect operator?
-    UNIMPLEMENTED(FATAL) << "Need non IT implementation";
+    /* Uses branchovers */
+    loadConstant(cUnit, rARG0, 1);       // assume true
+    LIR* branchover = opCmpBranch(cUnit, kCondEq, rARG1, rARG2, NULL);
+    int rTgt = loadHelper(cUnit, OFFSETOF_MEMBER(Thread,
+                          pInstanceofNonTrivialFromCode));
+    opRegCopy(cUnit, rARG0, rARG2);        // .ne case - arg0 <= class
+    opReg(cUnit, kOpBlx, rTgt);        // .ne case: helper(class, ref->class)
 #endif
-    /* branch target here */
+    oatClobberCalleeSave(cUnit);
+    /* branch targets here */
     LIR* target = newLIR0(cUnit, kPseudoTargetLabel);
     target->defMask = ENCODE_ALL;
     RegLocation rlResult = oatGetReturn(cUnit);
     storeValue(cUnit, rlDest, rlResult);
-    branch1->target = (LIR*)target;
+    branch1->target = target;
+#if !defined(TARGET_ARM)
+    branchover->target = target;
+#endif
 }
 
 void genCheckCast(CompilationUnit* cUnit, MIR* mir, RegLocation rlSrc)
@@ -1616,11 +1623,14 @@
                                    RegLocation rlResult, int lit,
                                    int firstBit, int secondBit)
 {
-#if defined(TARGET_MIPS)
-    UNIMPLEMENTED(FATAL) << "Need shift & add primative";
-#else
+#if defined(TARGET_ARM)
     opRegRegRegShift(cUnit, kOpAdd, rlResult.lowReg, rlSrc.lowReg, rlSrc.lowReg,
                      encodeShift(kArmLsl, secondBit - firstBit));
+#else
+    int tReg = oatAllocTemp(cUnit);
+    opRegRegImm(cUnit, kOpLsl, tReg, rlSrc.lowReg, secondBit - firstBit);
+    opRegRegReg(cUnit, kOpAdd, rlResult.lowReg, rlSrc.lowReg, tReg);
+    oatFreeTemp(cUnit, tReg);
 #endif
     if (firstBit != 0) {
         opRegRegImm(cUnit, kOpLsl, rlResult.lowReg, rlResult.lowReg, firstBit);
diff --git a/src/compiler/codegen/GenInvoke.cc b/src/compiler/codegen/GenInvoke.cc
index 69df8fc..4698868 100644
--- a/src/compiler/codegen/GenInvoke.cc
+++ b/src/compiler/codegen/GenInvoke.cc
@@ -103,7 +103,7 @@
             break;
         case 3:  // Grab the code from the method*
             loadWordDisp(cUnit, rARG0, Method::GetCodeOffset().Int32Value(),
-                         rLINK);
+                         rINVOKE_TGT);
             break;
         default:
             return -1;
@@ -133,22 +133,22 @@
             break;
         case 1: // Is "this" null? [use rARG1]
             genNullCheck(cUnit, oatSSASrc(mir,0), rARG1, mir);
-            // get this->klass_ [use rARG1, set rLINK]
+            // get this->klass_ [use rARG1, set rINVOKE_TGT]
             loadWordDisp(cUnit, rARG1, Object::ClassOffset().Int32Value(),
-                         rLINK);
+                         rINVOKE_TGT);
             break;
-        case 2: // Get this->klass_->vtable [usr rLINK, set rLINK]
-            loadWordDisp(cUnit, rLINK, Class::VTableOffset().Int32Value(),
-                         rLINK);
+        case 2: // Get this->klass_->vtable [usr rINVOKE_TGT, set rINVOKE_TGT]
+            loadWordDisp(cUnit, rINVOKE_TGT, Class::VTableOffset().Int32Value(),
+                         rINVOKE_TGT);
             break;
-        case 3: // Get target method [use rLINK, set rARG0]
-            loadWordDisp(cUnit, rLINK, (methodIdx * 4) +
+        case 3: // Get target method [use rINVOKE_TGT, set rARG0]
+            loadWordDisp(cUnit, rINVOKE_TGT, (methodIdx * 4) +
                          Array::DataOffset(sizeof(Object*)).Int32Value(),
                          rARG0);
             break;
-        case 4: // Get the target compiled code address [uses rARG0, sets rLINK]
+        case 4: // Get the compiled code address [uses rARG0, sets rINVOKE_TGT]
             loadWordDisp(cUnit, rARG0, Method::GetCodeOffset().Int32Value(),
-                         rLINK);
+                         rINVOKE_TGT);
             break;
         default:
             return -1;
@@ -176,29 +176,29 @@
             // Load "this" [set rARG1]
             rlArg = oatGetSrc(cUnit, mir, 0);
             loadValueDirectFixed(cUnit, rlArg, rARG1);
-            // Get method->declaring_class_ [use rARG0, set rLINK]
+            // Get method->declaring_class_ [use rARG0, set rINVOKE_TGT]
             loadWordDisp(cUnit, rARG0,
                          Method::DeclaringClassOffset().Int32Value(),
-                         rLINK);
+                         rINVOKE_TGT);
             // Is "this" null? [use rARG1]
             genNullCheck(cUnit, oatSSASrc(mir,0), rARG1, mir);
             break;
-        case 1: // Get method->declaring_class_->super_class [use/set rLINK]
-            loadWordDisp(cUnit, rLINK,
-                         Class::SuperClassOffset().Int32Value(), rLINK);
+        case 1: // method->declaring_class_->super_class [use/set rINVOKE_TGT]
+            loadWordDisp(cUnit, rINVOKE_TGT,
+                         Class::SuperClassOffset().Int32Value(), rINVOKE_TGT);
             break;
-        case 2: // Get ...->super_class_->vtable [u/s rLINK]
-            loadWordDisp(cUnit, rLINK,
-                         Class::VTableOffset().Int32Value(), rLINK);
+        case 2: // Get ...->super_class_->vtable [u/s rINVOKE_TGT]
+            loadWordDisp(cUnit, rINVOKE_TGT,
+                         Class::VTableOffset().Int32Value(), rINVOKE_TGT);
             break;
-        case 3: // Get target method [use rLINK, set rARG0]
-            loadWordDisp(cUnit, rLINK, (methodIdx * 4) +
+        case 3: // Get target method [use rINVOKE_TGT, set rARG0]
+            loadWordDisp(cUnit, rINVOKE_TGT, (methodIdx * 4) +
                          Array::DataOffset(sizeof(Object*)).Int32Value(),
                          rARG0);
             break;
-        case 4: // Get the target compiled code address [uses rARG0, sets rLINK]
+        case 4: // target compiled code address [uses rARG0, sets rINVOKE_TGT]
             loadWordDisp(cUnit, rARG0, Method::GetCodeOffset().Int32Value(),
-                         rLINK);
+                         rINVOKE_TGT);
             break;
         default:
             return -1;
@@ -215,7 +215,7 @@
      */
     if (state == 0) {
         // Load trampoline target
-        loadWordDisp(cUnit, rSELF, trampoline, rLINK);
+        loadWordDisp(cUnit, rSELF, trampoline, rINVOKE_TGT);
         // Load rARG0 with method index
         loadConstant(cUnit, rARG0, dexIdx);
         return 1;
diff --git a/src/compiler/codegen/MethodCodegenDriver.cc b/src/compiler/codegen/MethodCodegenDriver.cc
index a1eeeae..42dae0f 100644
--- a/src/compiler/codegen/MethodCodegenDriver.cc
+++ b/src/compiler/codegen/MethodCodegenDriver.cc
@@ -102,11 +102,7 @@
     if (DISPLAY_MISSING_TARGETS) {
         genShowTarget(cUnit);
     }
-#if defined(TARGET_MIPS)
-    UNIMPLEMENTED(WARNING) << "Need to handle common target register";
-#else
-    opReg(cUnit, kOpBlx, rLR);
-#endif
+    opReg(cUnit, kOpBlx, rINVOKE_TGT);
     oatClobberCalleeSave(cUnit);
 }
 
diff --git a/src/compiler/codegen/arm/ArmLIR.h b/src/compiler/codegen/arm/ArmLIR.h
index cafc993..db2d6e8 100644
--- a/src/compiler/codegen/arm/ArmLIR.h
+++ b/src/compiler/codegen/arm/ArmLIR.h
@@ -251,7 +251,7 @@
 #define rARG3 r3
 #define rRET0 r0
 #define rRET1 r1
-#define rLINK rLR
+#define rINVOKE_TGT rLR
 
 /* Shift encodings */
 typedef enum ArmShiftEncodings {
diff --git a/src/compiler/codegen/mips/ArchFactory.cc b/src/compiler/codegen/mips/ArchFactory.cc
index aaaa50f..963427d 100644
--- a/src/compiler/codegen/mips/ArchFactory.cc
+++ b/src/compiler/codegen/mips/ArchFactory.cc
@@ -145,7 +145,7 @@
         genDebuggerUpdate(cUnit, DEBUGGER_METHOD_EXIT);
     }
     unSpillCoreRegs(cUnit);
-    opReg(cUnit, kOpBx, rLINK);
+    opReg(cUnit, kOpBx, r_RA);
 }
 
 /*
diff --git a/src/compiler/codegen/mips/Assemble.cc b/src/compiler/codegen/mips/Assemble.cc
index 4deb8f5..0021318 100644
--- a/src/compiler/codegen/mips/Assemble.cc
+++ b/src/compiler/codegen/mips/Assemble.cc
@@ -527,7 +527,6 @@
                                << (int)encoder->fieldLoc[i].kind;
             }
         }
-        DCHECK_EQ(encoder->size, 4);
         // FIXME: need multi-endian handling here
         cUnit->codeBuffer.push_back((bits >> 16) & 0xffff);
         cUnit->codeBuffer.push_back(bits & 0xffff);
diff --git a/src/compiler/codegen/mips/Mips32/Gen.cc b/src/compiler/codegen/mips/Mips32/Gen.cc
index db34ce3..155675c 100644
--- a/src/compiler/codegen/mips/Mips32/Gen.cc
+++ b/src/compiler/codegen/mips/Mips32/Gen.cc
@@ -274,45 +274,54 @@
 LIR* opCmpBranch(CompilationUnit* cUnit, ConditionCode cond, int src1,
                  int src2, LIR* target)
 {
-   LIR* branch;
-    if (cond == kCondEq) {
-        branch = newLIR2(cUnit, kMipsBeq, src1, src2);
-    } else if (cond == kCondNe) {
-        branch = newLIR2(cUnit, kMipsBne, src1, src2);
+    LIR* branch;
+    MipsOpCode sltOp;
+    MipsOpCode brOp;
+    bool cmpZero = false;
+    bool swapped = false;
+    switch(cond) {
+        case kCondEq:
+            brOp = kMipsBeq;
+            cmpZero = true;
+            break;
+        case kCondNe:
+            brOp = kMipsBne;
+            cmpZero = true;
+            break;
+        case kCondCc:
+            sltOp = kMipsSltu;
+            brOp = kMipsBnez;
+            break;
+        case kCondCs:
+            sltOp = kMipsSltu;
+            brOp = kMipsBeqz;
+            break;
+        case kCondGe:
+            sltOp = kMipsSlt;
+            brOp = kMipsBeqz;
+            break;
+        case kCondGt:
+            sltOp = kMipsSlt;
+            brOp = kMipsBnez;
+            swapped = true;
+            break;
+        case kCondLe:
+            sltOp = kMipsSlt;
+            brOp = kMipsBeqz;
+            swapped = true;
+            break;
+        case kCondLt:
+            sltOp = kMipsSlt;
+            brOp = kMipsBnez;
+            break;
+        default:
+            UNIMPLEMENTED(FATAL) << "No support for ConditionCode: "
+                                 << (int) cond;
+            return NULL;
+    }
+    if (cmpZero) {
+        branch = newLIR2(cUnit, brOp, src1, src2);
     } else {
-        MipsOpCode sltOp;
-        MipsOpCode brOp;
-        bool swapped = false;
-        switch(cond) {
-            case kCondEq: return newLIR2(cUnit, kMipsBeq, src1, src2);
-            case kCondNe: return newLIR2(cUnit, kMipsBne, src1, src2);
-            case kCondCc:
-                sltOp = kMipsSltu;
-                brOp = kMipsBnez;
-                break;
-            case kCondGe:
-                sltOp = kMipsSlt;
-                brOp = kMipsBeqz;
-                break;
-            case kCondGt:
-                sltOp = kMipsSlt;
-                brOp = kMipsBnez;
-                swapped = true;
-                break;
-            case kCondLe:
-                sltOp = kMipsSlt;
-                brOp = kMipsBeqz;
-                swapped = true;
-                break;
-            case kCondLt:
-                sltOp = kMipsSlt;
-                brOp = kMipsBnez;
-                break;
-            default:
-                UNIMPLEMENTED(FATAL) << "No support for ConditionCode: "
-                                     << (int) cond;
-                return NULL;
-        }
         int tReg = oatAllocTemp(cUnit);
         if (swapped) {
             newLIR3(cUnit, sltOp, tReg, src2, src1);
@@ -320,8 +329,9 @@
             newLIR3(cUnit, sltOp, tReg, src1, src2);
         }
         branch = newLIR1(cUnit, brOp, tReg);
-        branch->target = target;
+        oatFreeTemp(cUnit, tReg);
     }
+    branch->target = target;
     return branch;
 }
 
diff --git a/src/compiler/codegen/mips/MipsLIR.h b/src/compiler/codegen/mips/MipsLIR.h
index 67f3131..b2cfdbe 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 rLINK r_RA
+#define rINVOKE_TGT r_V0
 
 /* Shift encodings */
 typedef enum MipsShiftEncodings {