Fix endianness of compiled code and stacks of stubs for MIPS.

The gtests now all work on MIPS.

Change-Id: I2883ce002f23d75e700366014517c863fb626d09
diff --git a/src/compiler/codegen/GenCommon.cc b/src/compiler/codegen/GenCommon.cc
index 6868d0b..d948d2d 100644
--- a/src/compiler/codegen/GenCommon.cc
+++ b/src/compiler/codegen/GenCommon.cc
@@ -1784,13 +1784,11 @@
            RegLocation rlSrc1, RegLocation rlSrc2)
 {
   OpKind op = kOpBkpt;
-  bool callOut = false;
+  bool isDivRem = false;
   bool checkZero = false;
   bool unary = false;
   RegLocation rlResult;
   bool shiftOp = false;
-  int funcOffset;
-  int retReg = rRET0;
   switch (opcode) {
     case Instruction::NEG_INT:
       op = kOpNeg;
@@ -1816,18 +1814,14 @@
     case Instruction::DIV_INT_2ADDR:
       checkZero = true;
       op = kOpDiv;
-      callOut = true;
-      funcOffset = ENTRYPOINT_OFFSET(pIdivmod);
-      retReg = rRET0;
+      isDivRem = true;
       break;
     /* NOTE: returns in rARG1 */
     case Instruction::REM_INT:
     case Instruction::REM_INT_2ADDR:
       checkZero = true;
       op = kOpRem;
-      callOut = true;
-      funcOffset = ENTRYPOINT_OFFSET(pIdivmod);
-      retReg = rRET1;
+      isDivRem = true;
       break;
     case Instruction::AND_INT:
     case Instruction::AND_INT_2ADDR:
@@ -1860,7 +1854,7 @@
       LOG(FATAL) << "Invalid word arith op: " <<
         (int)opcode;
   }
-  if (!callOut) {
+  if (!isDivRem) {
     if (unary) {
       rlSrc1 = loadValue(cUnit, rlSrc1, kCoreReg);
       rlResult = oatEvalLoc(cUnit, rlDest, kCoreReg, true);
@@ -1889,10 +1883,24 @@
     }
     storeValue(cUnit, rlDest, rlResult);
   } else {
+#if defined(TARGET_MIPS)
+    rlSrc2 = loadValue(cUnit, rlSrc2, kCoreReg);
+    if (checkZero) {
+        genNullCheck(cUnit, rlSrc2.sRegLow, rlSrc2.lowReg, 0);
+    }
+    newLIR4(cUnit, kMipsDiv, r_HI, r_LO, rlSrc1.lowReg, rlSrc2.lowReg);
+    rlResult = oatEvalLoc(cUnit, rlDest, kCoreReg, true);
+    if (op == kOpDiv) {
+      newLIR2(cUnit, kMipsMflo, rlResult.lowReg, r_LO);
+    } else {
+      newLIR2(cUnit, kMipsMfhi, rlResult.lowReg, r_HI);
+    }
+#else
+    int funcOffset = ENTRYPOINT_OFFSET(pIdivmod);
     RegLocation rlResult;
     oatFlushAllRegs(cUnit);   /* Send everything to home location */
     loadValueDirectFixed(cUnit, rlSrc2, rARG1);
-#if !defined(TARGET_X86)
+#if defined(TARGET_ARM)
     int rTgt = loadHelper(cUnit, funcOffset);
 #endif
     loadValueDirectFixed(cUnit, rlSrc1, rARG0);
@@ -1900,17 +1908,18 @@
       genImmedCheck(cUnit, kCondEq, rARG1, 0, kThrowDivZero);
     }
     // NOTE: callout here is not a safepoint
-#if !defined(TARGET_X86)
+#if defined(TARGET_ARM)
     opReg(cUnit, kOpBlx, rTgt);
     oatFreeTemp(cUnit, rTgt);
 #else
     opThreadMem(cUnit, kOpBlx, funcOffset);
 #endif
-    if (retReg == rRET0)
+    if (op == kOpDiv)
       rlResult = oatGetReturn(cUnit, false);
     else
       rlResult = oatGetReturnAlt(cUnit);
     storeValue(cUnit, rlDest, rlResult);
+#endif
   }
   return false;
 }
@@ -2077,7 +2086,6 @@
   OpKind op = (OpKind)0;    /* Make gcc happy */
   int shiftOp = false;
   bool isDiv = false;
-  int funcOffset;
 
   switch (opcode) {
     case Instruction::RSUB_INT_LIT8:
@@ -2140,7 +2148,7 @@
     case Instruction::DIV_INT_LIT8:
     case Instruction::DIV_INT_LIT16:
     case Instruction::REM_INT_LIT8:
-    case Instruction::REM_INT_LIT16:
+    case Instruction::REM_INT_LIT16: {
       if (lit == 0) {
         genImmedCheck(cUnit, kCondAl, 0, 0, kThrowDivZero);
         return false;
@@ -2148,24 +2156,39 @@
       if (handleEasyDivide(cUnit, opcode, rlSrc, rlDest, lit)) {
         return false;
       }
-      oatFlushAllRegs(cUnit);   /* Everything to home location */
-      loadValueDirectFixed(cUnit, rlSrc, rARG0);
-      oatClobber(cUnit, rARG0);
-      funcOffset = ENTRYPOINT_OFFSET(pIdivmod);
       if ((opcode == Instruction::DIV_INT_LIT8) ||
           (opcode == Instruction::DIV_INT_LIT16)) {
         isDiv = true;
       } else {
         isDiv = false;
       }
+#if defined(TARGET_MIPS)
+      rlSrc = loadValue(cUnit, rlSrc, kCoreReg);
+      int tReg = oatAllocTemp(cUnit);
+      newLIR3(cUnit, kMipsAddiu, tReg, r_ZERO, lit);
+      newLIR4(cUnit, kMipsDiv, r_HI, r_LO, rlSrc.lowReg, tReg);
+      rlResult = oatEvalLoc(cUnit, rlDest, kCoreReg, true);
+      if (isDiv) {
+        newLIR2(cUnit, kMipsMflo, rlResult.lowReg, r_LO);
+      } else {
+        newLIR2(cUnit, kMipsMfhi, rlResult.lowReg, r_HI);
+      }
+      oatFreeTemp(cUnit, tReg);
+#else
+      oatFlushAllRegs(cUnit);   /* Everything to home location */
+      loadValueDirectFixed(cUnit, rlSrc, rARG0);
+      oatClobber(cUnit, rARG0);
+      int funcOffset = ENTRYPOINT_OFFSET(pIdivmod);
       callRuntimeHelperRegImm(cUnit, funcOffset, rARG0, lit, false);
       if (isDiv)
         rlResult = oatGetReturn(cUnit, false);
       else
         rlResult = oatGetReturnAlt(cUnit);
+#endif
       storeValue(cUnit, rlDest, rlResult);
       return false;
       break;
+    }
     default:
       return true;
   }
diff --git a/src/compiler/codegen/mips/Assemble.cc b/src/compiler/codegen/mips/Assemble.cc
index 25e13d7..8c906cc 100644
--- a/src/compiler/codegen/mips/Assemble.cc
+++ b/src/compiler/codegen/mips/Assemble.cc
@@ -691,19 +691,19 @@
                      << (int)encoder->fieldLoc[i].kind;
       }
     }
-    // FIXME: need multi-endian handling here
-    cUnit->codeBuffer.push_back((bits >> 24) & 0xff);
-    cUnit->codeBuffer.push_back((bits >> 16) & 0xff);
-    cUnit->codeBuffer.push_back((bits >> 8) & 0xff);
+    // We only support little-endian MIPS.
     cUnit->codeBuffer.push_back(bits & 0xff);
+    cUnit->codeBuffer.push_back((bits >> 8) & 0xff);
+    cUnit->codeBuffer.push_back((bits >> 16) & 0xff);
+    cUnit->codeBuffer.push_back((bits >> 24) & 0xff);
     // TUNING: replace with proper delay slot handling
     if (encoder->size == 8) {
       const MipsEncodingMap *encoder = &EncodingMap[kMipsNop];
       u4 bits = encoder->skeleton;
-      cUnit->codeBuffer.push_back((bits >> 24) & 0xff);
-      cUnit->codeBuffer.push_back((bits >> 16) & 0xff);
-      cUnit->codeBuffer.push_back((bits >> 8) & 0xff);
       cUnit->codeBuffer.push_back(bits & 0xff);
+      cUnit->codeBuffer.push_back((bits >> 8) & 0xff);
+      cUnit->codeBuffer.push_back((bits >> 16) & 0xff);
+      cUnit->codeBuffer.push_back((bits >> 24) & 0xff);
     }
   }
   return res;
diff --git a/src/compiler/codegen/mips/MipsLIR.h b/src/compiler/codegen/mips/MipsLIR.h
index 0f6226f..ab4f844 100644
--- a/src/compiler/codegen/mips/MipsLIR.h
+++ b/src/compiler/codegen/mips/MipsLIR.h
@@ -147,14 +147,12 @@
 /* RegisterLocation templates return values (r_V0, or r_V0/r_V1) */
 #define LOC_C_RETURN {kLocPhysReg, 0, 0, 0, 0, 0, 0, 0, 1, r_V0, INVALID_REG, \
                       INVALID_SREG, INVALID_SREG}
-#define LOC_C_RETURN_FLOAT  LOC_C_RETURN
-#define LOC_C_RETURN_ALT {kLocPhysReg, 0, 0, 0, 0, 0, 0, 0, 1, r_V1, \
-                          INVALID_REG, INVALID_SREG, INVALID_SREG}
+#define LOC_C_RETURN_FLOAT {kLocPhysReg, 0, 0, 0, 0, 0, 0, 0, 1, r_FRESULT0, \
+                            INVALID_REG, INVALID_SREG, INVALID_SREG}
 #define LOC_C_RETURN_WIDE {kLocPhysReg, 1, 0, 0, 0, 0, 0, 0, 1, r_RESULT0, \
                            r_RESULT1, INVALID_SREG, INVALID_SREG}
-#define LOC_C_RETURN_WIDE_DOUBLE  LOC_C_RETURN_WIDE
-#define LOC_C_RETURN_WIDE_ALT {kLocPhysReg, 1, 0, 0, 0, 0, 0, 0, 1, r_FRESULT0,\
-                               r_FRESULT1, INVALID_SREG, INVALID_SREG}
+#define LOC_C_RETURN_WIDE_DOUBLE {kLocPhysReg, 1, 0, 0, 0, 0, 0, 0, 1, r_FRESULT0,\
+                                  r_FRESULT1, INVALID_SREG, INVALID_SREG}
 
 enum ResourceEncodingPos {
   kGPReg0   = 0,
diff --git a/src/compiler/codegen/mips/MipsRallocUtil.cc b/src/compiler/codegen/mips/MipsRallocUtil.cc
index 43fcc07..bd9f97e 100644
--- a/src/compiler/codegen/mips/MipsRallocUtil.cc
+++ b/src/compiler/codegen/mips/MipsRallocUtil.cc
@@ -138,20 +138,15 @@
 
 extern RegLocation oatGetReturnWideAlt(CompilationUnit* cUnit)
 {
-  RegLocation res = LOC_C_RETURN_WIDE_ALT;
-  oatClobber(cUnit, res.lowReg);
-  oatClobber(cUnit, res.highReg);
-  oatMarkInUse(cUnit, res.lowReg);
-  oatMarkInUse(cUnit, res.highReg);
-  oatMarkPair(cUnit, res.lowReg, res.highReg);
+  UNIMPLEMENTED(FATAL) << "No oatGetReturnWideAlt for MIPS";
+  RegLocation res = LOC_C_RETURN_WIDE;
   return res;
 }
 
 extern RegLocation oatGetReturnAlt(CompilationUnit* cUnit)
 {
-  RegLocation res = LOC_C_RETURN_ALT;
-  oatClobber(cUnit, res.lowReg);
-  oatMarkInUse(cUnit, res.lowReg);
+  UNIMPLEMENTED(FATAL) << "No oatGetReturnAlt for MIPS";
+  RegLocation res = LOC_C_RETURN;
   return res;
 }