MIPS switch table support

And 64-bit neg/add/sub (ouch! Mips has no carry bit...)

Change-Id: Ifb94324a0052d6069977fb8f22679b95890445d8
diff --git a/src/compiler/codegen/arm/ArchFactory.cc b/src/compiler/codegen/arm/ArchFactory.cc
index b47fae1..8a23d5c 100644
--- a/src/compiler/codegen/arm/ArchFactory.cc
+++ b/src/compiler/codegen/arm/ArchFactory.cc
@@ -26,6 +26,32 @@
 
 void genDebuggerUpdate(CompilationUnit* cUnit, int32_t offset);
 
+bool genNegLong(CompilationUnit* cUnit, MIR* mir, RegLocation rlDest,
+                RegLocation rlSrc)
+{
+    rlSrc = loadValueWide(cUnit, rlSrc, kCoreReg);
+    RegLocation rlResult = oatEvalLoc(cUnit, rlDest, kCoreReg, true);
+    int zReg = oatAllocTemp(cUnit);
+    loadConstantNoClobber(cUnit, zReg, 0);
+    // Check for destructive overlap
+    if (rlResult.lowReg == rlSrc.highReg) {
+        int tReg = oatAllocTemp(cUnit);
+        opRegRegReg(cUnit, kOpSub, rlResult.lowReg,
+                    zReg, rlSrc.lowReg);
+        opRegRegReg(cUnit, kOpSbc, rlResult.highReg,
+                    zReg, tReg);
+        oatFreeTemp(cUnit, tReg);
+    } else {
+        opRegRegReg(cUnit, kOpSub, rlResult.lowReg,
+                    zReg, rlSrc.lowReg);
+        opRegRegReg(cUnit, kOpSbc, rlResult.highReg,
+                    zReg, rlSrc.highReg);
+    }
+    oatFreeTemp(cUnit, zReg);
+    storeValueWide(cUnit, rlDest, rlResult);
+    return false;
+}
+
 int loadHelper(CompilationUnit* cUnit, int offset)
 {
     loadWordDisp(cUnit, rSELF, offset, rLR);
diff --git a/src/compiler/codegen/arm/Codegen.h b/src/compiler/codegen/arm/Codegen.h
index b985e1b..3b866ce 100644
--- a/src/compiler/codegen/arm/Codegen.h
+++ b/src/compiler/codegen/arm/Codegen.h
@@ -31,6 +31,8 @@
 LIR *opRegReg(CompilationUnit* cUnit, OpKind op, int rDestSrc1, int rSrc2);
 LIR* opCmpImmBranch(CompilationUnit* cUnit, ConditionCode cond, int reg,
                     int checkValue, LIR* target);
+bool genNegLong(CompilationUnit* cUnit, MIR* mir, RegLocation rlDest,
+                RegLocation rlSrc);
 
 /* Forward declaraton the portable versions due to circular dependency */
 bool genArithOpFloatPortable(CompilationUnit* cUnit, MIR* mir,
diff --git a/src/compiler/codegen/arm/Thumb2/Gen.cc b/src/compiler/codegen/arm/Thumb2/Gen.cc
index 838fcaf..cba37b7 100644
--- a/src/compiler/codegen/arm/Thumb2/Gen.cc
+++ b/src/compiler/codegen/arm/Thumb2/Gen.cc
@@ -119,14 +119,13 @@
     loadConstant(cUnit, rIdx, size);
     // Establish loop branch target
     LIR* target = newLIR0(cUnit, kPseudoTargetLabel);
-    target->defMask = ENCODE_ALL;
     // Load next key/disp
     newLIR2(cUnit, kThumb2LdmiaWB, rBase, (1 << rKey) | (1 << rDisp));
     opRegReg(cUnit, kOpCmp, rKey, rlSrc.lowReg);
     // Go if match. NOTE: No instruction set switch here - must stay Thumb2
     opIT(cUnit, kArmCondEq, "");
     LIR* switchBranch = newLIR1(cUnit, kThumb2AddPCR, rDisp);
-    tabRec->bxInst = switchBranch;
+    tabRec->anchor = switchBranch;
     // Needs to use setflags encoding here
     newLIR3(cUnit, kThumb2SubsRRI12, rIdx, rIdx, 1);
     opCondBranch(cUnit, kCondNe, target);
@@ -173,11 +172,10 @@
 
     // ..and go! NOTE: No instruction set switch here - must stay Thumb2
     LIR* switchBranch = newLIR1(cUnit, kThumb2AddPCR, dispReg);
-    tabRec->bxInst = switchBranch;
+    tabRec->anchor = switchBranch;
 
     /* branchOver target here */
     LIR* target = newLIR0(cUnit, kPseudoTargetLabel);
-    target->defMask = ENCODE_ALL;
     branchOver->target = (LIR*)target;
 }
 
@@ -287,7 +285,6 @@
     branch = newLIR2(cUnit, kThumb2Cbz, r1, 0);
 
     hopTarget = newLIR0(cUnit, kPseudoTargetLabel);
-    hopTarget->defMask = ENCODE_ALL;
     hopBranch->target = (LIR*)hopTarget;
 
     // Go expensive route - artLockObjectFromCode(self, obj);
@@ -297,7 +294,6 @@
 
     // Resume here
     target = newLIR0(cUnit, kPseudoTargetLabel);
-    target->defMask = ENCODE_ALL;
     branch->target = (LIR*)target;
 }
 
@@ -333,7 +329,6 @@
     branch = opNone(cUnit, kOpUncondBr);
 
     hopTarget = newLIR0(cUnit, kPseudoTargetLabel);
-    hopTarget->defMask = ENCODE_ALL;
     hopBranch->target = (LIR*)hopTarget;
 
     // Go expensive route - UnlockObjectFromCode(obj);
@@ -343,7 +338,6 @@
 
     // Resume here
     target = newLIR0(cUnit, kPseudoTargetLabel);
-    target->defMask = ENCODE_ALL;
     branch->target = (LIR*)target;
 }
 
@@ -383,11 +377,9 @@
     genBarrier(cUnit);
 
     target2 = newLIR0(cUnit, kPseudoTargetLabel);
-    target2->defMask = -1;
     opRegReg(cUnit, kOpNeg, tReg, tReg);
 
     target1 = newLIR0(cUnit, kPseudoTargetLabel);
-    target1->defMask = -1;
 
     RegLocation rlTemp = LOC_C_RETURN; // Just using as template, will change
     rlTemp.lowReg = tReg;