Enable all JNI internal compiler tests on the host.

Change-Id: Ie1d96270413fc3950cbc9b9ed53793f5b364e924
diff --git a/src/compiler/codegen/x86/ArchFactory.cc b/src/compiler/codegen/x86/ArchFactory.cc
index 2d15318..f2c9c71 100644
--- a/src/compiler/codegen/x86/ArchFactory.cc
+++ b/src/compiler/codegen/x86/ArchFactory.cc
@@ -27,54 +27,36 @@
 bool genAddLong(CompilationUnit* cUnit, MIR* mir, RegLocation rlDest,
                 RegLocation rlSrc1, RegLocation rlSrc2)
 {
-    UNIMPLEMENTED(WARNING) << "genAddLong";
-#if 0
     rlSrc1 = loadValueWide(cUnit, rlSrc1, kCoreReg);
     rlSrc2 = loadValueWide(cUnit, rlSrc2, kCoreReg);
     RegLocation rlResult = oatEvalLoc(cUnit, rlDest, kCoreReg, true);
     /*
      *  [v1 v0] =  [a1 a0] + [a3 a2];
-     *    addu v0,a2,a0
-     *    addu t1,a3,a1
-     *    sltu v1,v0,a2
-     *    addu v1,v1,t1
+     *    add v0,a2,a0
+     *    adc v1,a3,a1
      */
 
     opRegRegReg(cUnit, kOpAdd, rlResult.lowReg, rlSrc2.lowReg, rlSrc1.lowReg);
-    int tReg = oatAllocTemp(cUnit);
-    opRegRegReg(cUnit, kOpAdd, tReg, rlSrc2.highReg, rlSrc1.highReg);
-    newLIR3(cUnit, kX86Sltu, rlResult.highReg, rlResult.lowReg, rlSrc2.lowReg);
-    opRegRegReg(cUnit, kOpAdd, rlResult.highReg, rlResult.highReg, tReg);
-    oatFreeTemp(cUnit, tReg);
+    opRegRegReg(cUnit, kOpAdc, rlResult.highReg, rlSrc2.highReg, rlSrc1.highReg);
     storeValueWide(cUnit, rlDest, rlResult);
-#endif
     return false;
 }
 
 bool genSubLong(CompilationUnit* cUnit, MIR* mir, RegLocation rlDest,
                 RegLocation rlSrc1, RegLocation rlSrc2)
 {
-    UNIMPLEMENTED(WARNING) << "genSubLong";
-#if 0
     rlSrc1 = loadValueWide(cUnit, rlSrc1, kCoreReg);
     rlSrc2 = loadValueWide(cUnit, rlSrc2, kCoreReg);
     RegLocation rlResult = oatEvalLoc(cUnit, rlDest, kCoreReg, true);
     /*
      *  [v1 v0] =  [a1 a0] - [a3 a2];
-     *    subu    v0,a0,a2
-     *    subu    v1,a1,a3
-     *    sltu    t1,a0,v0
-     *    subu    v1,v1,t1
+     *    sub    v0,a0,a2
+     *    sbb    v1,a1,a3
      */
 
     opRegRegReg(cUnit, kOpSub, rlResult.lowReg, rlSrc1.lowReg, rlSrc2.lowReg);
-    opRegRegReg(cUnit, kOpSub, rlResult.highReg, rlSrc1.highReg, rlSrc2.highReg);
-    int tReg = oatAllocTemp(cUnit);
-    newLIR3(cUnit, kX86Sltu, tReg, rlSrc1.lowReg, rlResult.lowReg);
-    opRegRegReg(cUnit, kOpSub, rlResult.highReg, rlResult.highReg, tReg);
-    oatFreeTemp(cUnit, tReg);
+    opRegRegReg(cUnit, kOpSbc, rlResult.highReg, rlSrc1.highReg, rlSrc2.highReg);
     storeValueWide(cUnit, rlDest, rlResult);
-#endif
     return false;
 }
 
@@ -123,34 +105,34 @@
 #endif
 }
 
-void spillCoreRegs(CompilationUnit* cUnit)
-{
-    if (cUnit->numCoreSpills == 0) {
-        return;
+void spillCoreRegs(CompilationUnit* cUnit) {
+  if (cUnit->numCoreSpills == 0) {
+    return;
+  }
+  // Spill mask not including fake return address register
+  uint32_t mask = cUnit->coreSpillMask & ~(1 << rRET);
+  int offset = cUnit->frameSize - 4;
+  for (int reg = 0; mask; mask >>= 1, reg++) {
+    if (mask & 0x1) {
+      offset -= 4;
+      storeWordDisp(cUnit, rSP, offset, reg);
     }
-    uint32_t mask = cUnit->coreSpillMask;
-    int offset = cUnit->frameSize - 4;
-    for (int reg = 0; mask; mask >>= 1, reg++) {
-        if (mask & 0x1) {
-            offset -= 4;
-            storeWordDisp(cUnit, rSP, offset, reg);
-        }
-    }
+  }
 }
 
-void unSpillCoreRegs(CompilationUnit* cUnit)
-{
-    if (cUnit->numCoreSpills == 0) {
-        return;
+void unSpillCoreRegs(CompilationUnit* cUnit) {
+  if (cUnit->numCoreSpills == 0) {
+    return;
+  }
+  // Spill mask not including fake return address register
+  uint32_t mask = cUnit->coreSpillMask & ~(1 << rRET);
+  int offset = cUnit->frameSize - 4;
+  for (int reg = 0; mask; mask >>= 1, reg++) {
+    if (mask & 0x1) {
+      offset -= 4;
+      loadWordDisp(cUnit, rSP, offset, reg);
     }
-    uint32_t mask = cUnit->coreSpillMask;
-    int offset = cUnit->frameSize - 4;
-    for (int reg = 0; mask; mask >>= 1, reg++) {
-        if (mask & 0x1) {
-            offset -= 4;
-            loadWordDisp(cUnit, rSP, offset, reg);
-        }
-    }
+  }
 }
 
 void opRegThreadMem(CompilationUnit* cUnit, OpKind op, int rDest, int threadOffset) {
@@ -280,19 +262,17 @@
 
 
 /* Common initialization routine for an architecture family */
-bool oatArchInit()
-{
-    int i;
+bool oatArchInit() {
+  int i;
 
-    for (i = 0; i < kX86Last; i++) {
-        if (EncodingMap[i].opcode != i) {
-            LOG(FATAL) << "Encoding order for " << EncodingMap[i].name <<
-               " is wrong: expecting " << i << ", seeing " <<
-               (int)EncodingMap[i].opcode;
-        }
+  for (i = 0; i < kX86Last; i++) {
+    if (EncodingMap[i].opcode != i) {
+      LOG(FATAL) << "Encoding order for " << EncodingMap[i].name
+          << " is wrong: expecting " << i << ", seeing " << (int)EncodingMap[i].opcode;
     }
+  }
 
-    return oatArchVariantInit();
+  return oatArchVariantInit();
 }
 
 }  // namespace art
diff --git a/src/compiler/codegen/x86/Assemble.cc b/src/compiler/codegen/x86/Assemble.cc
index cb06776..3d2b0e5 100644
--- a/src/compiler/codegen/x86/Assemble.cc
+++ b/src/compiler/codegen/x86/Assemble.cc
@@ -468,6 +468,9 @@
     DCHECK_EQ(0, entry->skeleton.extra_opcode1);
     DCHECK_EQ(0, entry->skeleton.extra_opcode2);
   }
+  if (FPREG(reg)) {
+    reg = reg & FP_REG_MASK;
+  }
   DCHECK_LT(reg, 8);
   uint8_t modrm = (3 << 6) | (entry->skeleton.modrm_opcode << 3) | reg;
   cUnit->codeBuffer.push_back(modrm);
@@ -518,6 +521,9 @@
     DCHECK_EQ(0, entry->skeleton.extra_opcode1);
     DCHECK_EQ(0, entry->skeleton.extra_opcode2);
   }
+  if (FPREG(reg)) {
+    reg = reg & FP_REG_MASK;
+  }
   DCHECK_LT(reg, 8);
   DCHECK_LT(base, 8);
   uint8_t modrm = (modrmForDisp(disp) << 6) | (reg << 3) | base;
@@ -560,6 +566,9 @@
     DCHECK_EQ(0, entry->skeleton.extra_opcode1);
     DCHECK_EQ(0, entry->skeleton.extra_opcode2);
   }
+  if (FPREG(reg)) {
+    reg = reg & FP_REG_MASK;
+  }
   DCHECK_LT(reg, 8);
   uint8_t modrm = (modrmForDisp(disp) << 6) | (reg << 3) | rSP;
   cUnit->codeBuffer.push_back(modrm);
@@ -596,6 +605,14 @@
     DCHECK_EQ(0, entry->skeleton.extra_opcode1);
     DCHECK_EQ(0, entry->skeleton.extra_opcode2);
   }
+  if (FPREG(reg1)) {
+    reg1 = reg1 & FP_REG_MASK;
+  }
+  if (FPREG(reg2)) {
+    reg2 = reg2 & FP_REG_MASK;
+  }
+  DCHECK_LT(reg1, 8);
+  DCHECK_LT(reg2, 8);
   uint8_t modrm = (3 << 6) | (reg1 << 3) | reg2;
   cUnit->codeBuffer.push_back(modrm);
   DCHECK_EQ(0, entry->skeleton.modrm_opcode);
diff --git a/src/compiler/codegen/x86/X86/Factory.cc b/src/compiler/codegen/x86/X86/Factory.cc
index c28bae9..f3fc84a 100644
--- a/src/compiler/codegen/x86/X86/Factory.cc
+++ b/src/compiler/codegen/x86/X86/Factory.cc
@@ -76,7 +76,7 @@
         }
     }
     DCHECK((EncodingMap[opcode].flags & IS_BINARY_OP) != 0);
-    LIR* res = rawLIR(cUnit, cUnit->currentDalvikOffset, opcode, rSrc, rDest);
+    LIR* res = rawLIR(cUnit, cUnit->currentDalvikOffset, opcode, rDest, rSrc);
     if (rDest == rSrc) {
         res->flags.isNop = true;
     }
@@ -502,7 +502,7 @@
           rDest = rDest - FP_DOUBLE;
         } else {
           DCHECK(FPREG(rDestHi));
-          DCHECK(rDest == (rDestHi - 1));
+          DCHECK_EQ(rDest, (rDestHi - 1));
         }
         rDestHi = rDest + 1;
       } else {
@@ -549,7 +549,7 @@
     if (rBase == rSP) {
       annotateDalvikRegAccess(load, (displacement + (pair ? LOWORD_OFFSET : 0)) >> 2,
                               true /* isLoad */, is64bit);
-      if (is64bit) {
+      if (pair) {
         annotateDalvikRegAccess(load2, (displacement + HIWORD_OFFSET) >> 2,
                                 true /* isLoad */, is64bit);
       }
diff --git a/src/compiler/codegen/x86/X86/Gen.cc b/src/compiler/codegen/x86/X86/Gen.cc
index f3b8aa0..e7f18ca 100644
--- a/src/compiler/codegen/x86/X86/Gen.cc
+++ b/src/compiler/codegen/x86/X86/Gen.cc
@@ -437,51 +437,39 @@
 LIR* opRegCopy(CompilationUnit *cUnit, int rDest, int rSrc)
 {
     LIR *res = opRegCopyNoInsert(cUnit, rDest, rSrc);
-    oatAppendLIR(cUnit, (LIR*)res);
+    oatAppendLIR(cUnit, res);
     return res;
 }
 
 void opRegCopyWide(CompilationUnit *cUnit, int destLo, int destHi,
-                    int srcLo, int srcHi)
-{
-    UNIMPLEMENTED(WARNING) << "opRegCopyWide";
-#if 0
-    bool destFP = FPREG(destLo) && FPREG(destHi);
-    bool srcFP = FPREG(srcLo) && FPREG(srcHi);
-    assert(FPREG(srcLo) == FPREG(srcHi));
-    assert(FPREG(destLo) == FPREG(destHi));
-    if (destFP) {
-        if (srcFP) {
-            opRegCopy(cUnit, S2D(destLo, destHi), S2D(srcLo, srcHi));
-        } else {
-           /* note the operands are swapped for the mtc1 instr */
-            newLIR2(cUnit, kX86Mtc1, srcLo, destLo);
-            newLIR2(cUnit, kX86Mtc1, srcHi, destHi);
-        }
+                   int srcLo, int srcHi) {
+  bool destFP = FPREG(destLo) && FPREG(destHi);
+  bool srcFP = FPREG(srcLo) && FPREG(srcHi);
+  assert(FPREG(srcLo) == FPREG(srcHi));
+  assert(FPREG(destLo) == FPREG(destHi));
+  LOG(INFO) << "RegCopyWide: destLo=" << destLo << " destHi=" << destHi
+      << " srcLo=" << srcLo << " srcHi=" << srcHi
+      << " dFP=" << destFP << " sFP=" << srcFP;
+  if (destFP) {
+    if (srcFP) {
+      opRegCopy(cUnit, S2D(destLo, destHi), S2D(srcLo, srcHi));
     } else {
-        if (srcFP) {
-            newLIR2(cUnit, kX86Mfc1, destLo, srcLo);
-            newLIR2(cUnit, kX86Mfc1, destHi, srcHi);
-        } else {
-            // Handle overlap
-            if (srcHi == destLo) {
-                opRegCopy(cUnit, destHi, srcHi);
-                opRegCopy(cUnit, destLo, srcLo);
-            } else {
-                opRegCopy(cUnit, destLo, srcLo);
-                opRegCopy(cUnit, destHi, srcHi);
-            }
-        }
+      UNIMPLEMENTED(WARNING);
     }
-    // Handle overlap
-    if (srcHi == destLo) {
+  } else {
+    if (srcFP) {
+      UNIMPLEMENTED(WARNING);
+    } else {
+      // Handle overlap
+      if (srcHi == destLo) {
         opRegCopy(cUnit, destHi, srcHi);
         opRegCopy(cUnit, destLo, srcLo);
-    } else {
+      } else {
         opRegCopy(cUnit, destLo, srcLo);
         opRegCopy(cUnit, destHi, srcHi);
+      }
     }
-#endif
+  }
 }
 
 }  // namespace art
diff --git a/src/compiler/codegen/x86/X86/Ralloc.cc b/src/compiler/codegen/x86/X86/Ralloc.cc
index c7985e5..38b9df8 100644
--- a/src/compiler/codegen/x86/X86/Ralloc.cc
+++ b/src/compiler/codegen/x86/X86/Ralloc.cc
@@ -29,97 +29,88 @@
  * high reg in next byte.
  */
 int oatAllocTypedTempPair(CompilationUnit *cUnit, bool fpHint,
-                                  int regClass)
-{
-    UNIMPLEMENTED(WARNING) << "oatAllocTypedTemp";
-    return 0;
-#if 0
-    int highReg;
-    int lowReg;
-    int res = 0;
+                          int regClass) {
+  int highReg;
+  int lowReg;
+  int res = 0;
 
-    if (((regClass == kAnyReg) && fpHint) || (regClass == kFPReg)) {
-        lowReg = oatAllocTempDouble(cUnit);
-        highReg = lowReg + 1;
-        res = (lowReg & 0xff) | ((highReg & 0xff) << 8);
-        return res;
-    }
-
-    lowReg = oatAllocTemp(cUnit);
-    highReg = oatAllocTemp(cUnit);
+  if (((regClass == kAnyReg) && fpHint) || (regClass == kFPReg)) {
+    lowReg = oatAllocTempDouble(cUnit);
+    highReg = lowReg + 1;
     res = (lowReg & 0xff) | ((highReg & 0xff) << 8);
     return res;
-#endif
+  }
+
+  lowReg = oatAllocTemp(cUnit);
+  highReg = oatAllocTemp(cUnit);
+  res = (lowReg & 0xff) | ((highReg & 0xff) << 8);
+  return res;
 }
 
-int oatAllocTypedTemp(CompilationUnit *cUnit, bool fpHint, int regClass)
-{
-    if (((regClass == kAnyReg) && fpHint) || (regClass == kFPReg))
-{
-        return oatAllocTempFloat(cUnit);
-}
-    return oatAllocTemp(cUnit);
+int oatAllocTypedTemp(CompilationUnit *cUnit, bool fpHint, int regClass) {
+  if (((regClass == kAnyReg) && fpHint) || (regClass == kFPReg)) {
+    return oatAllocTempFloat(cUnit);
+  }
+  return oatAllocTemp(cUnit);
 }
 
-void oatInitializeRegAlloc(CompilationUnit* cUnit)
-{
-    int numRegs = sizeof(coreRegs)/sizeof(*coreRegs);
-    int numReserved = sizeof(reservedRegs)/sizeof(*reservedRegs);
-    int numTemps = sizeof(coreTemps)/sizeof(*coreTemps);
-    int numFPRegs = sizeof(fpRegs)/sizeof(*fpRegs);
-    int numFPTemps = sizeof(fpTemps)/sizeof(*fpTemps);
-    RegisterPool *pool = (RegisterPool *)oatNew(cUnit, sizeof(*pool), true,
-                                                kAllocRegAlloc);
-    cUnit->regPool = pool;
-    pool->numCoreRegs = numRegs;
-    pool->coreRegs = (RegisterInfo *)
-            oatNew(cUnit, numRegs * sizeof(*cUnit->regPool->coreRegs),
-                   true, kAllocRegAlloc);
-    pool->numFPRegs = numFPRegs;
-    pool->FPRegs = (RegisterInfo *)
-            oatNew(cUnit, numFPRegs * sizeof(*cUnit->regPool->FPRegs), true,
-                   kAllocRegAlloc);
-    oatInitPool(pool->coreRegs, coreRegs, pool->numCoreRegs);
-    oatInitPool(pool->FPRegs, fpRegs, pool->numFPRegs);
-    // Keep special registers from being allocated
-    for (int i = 0; i < numReserved; i++) {
-        oatMarkInUse(cUnit, reservedRegs[i]);
-    }
-    // Mark temp regs - all others not in use can be used for promotion
-    for (int i = 0; i < numTemps; i++) {
-        oatMarkTemp(cUnit, coreTemps[i]);
-    }
-    for (int i = 0; i < numFPTemps; i++) {
-        oatMarkTemp(cUnit, fpTemps[i]);
-    }
-    // Construct the alias map.
-    cUnit->phiAliasMap = (int*)oatNew(cUnit, cUnit->numSSARegs *
-                                      sizeof(cUnit->phiAliasMap[0]), false,
-                                      kAllocDFInfo);
-    for (int i = 0; i < cUnit->numSSARegs; i++) {
-        cUnit->phiAliasMap[i] = i;
-    }
-    for (MIR* phi = cUnit->phiList; phi; phi = phi->meta.phiNext) {
-        int defReg = phi->ssaRep->defs[0];
-        for (int i = 0; i < phi->ssaRep->numUses; i++) {
-           for (int j = 0; j < cUnit->numSSARegs; j++) {
-               if (cUnit->phiAliasMap[j] == phi->ssaRep->uses[i]) {
-                   cUnit->phiAliasMap[j] = defReg;
-               }
-           }
+void oatInitializeRegAlloc(CompilationUnit* cUnit) {
+  int numRegs = sizeof(coreRegs)/sizeof(*coreRegs);
+  int numReserved = sizeof(reservedRegs)/sizeof(*reservedRegs);
+  int numTemps = sizeof(coreTemps)/sizeof(*coreTemps);
+  int numFPRegs = sizeof(fpRegs)/sizeof(*fpRegs);
+  int numFPTemps = sizeof(fpTemps)/sizeof(*fpTemps);
+  RegisterPool *pool = (RegisterPool *)oatNew(cUnit, sizeof(*pool), true,
+                                              kAllocRegAlloc);
+  cUnit->regPool = pool;
+  pool->numCoreRegs = numRegs;
+  pool->coreRegs = (RegisterInfo *)
+                oatNew(cUnit, numRegs * sizeof(*cUnit->regPool->coreRegs),
+                       true, kAllocRegAlloc);
+  pool->numFPRegs = numFPRegs;
+  pool->FPRegs = (RegisterInfo *)
+                oatNew(cUnit, numFPRegs * sizeof(*cUnit->regPool->FPRegs), true,
+                       kAllocRegAlloc);
+  oatInitPool(pool->coreRegs, coreRegs, pool->numCoreRegs);
+  oatInitPool(pool->FPRegs, fpRegs, pool->numFPRegs);
+  // Keep special registers from being allocated
+  for (int i = 0; i < numReserved; i++) {
+    oatMarkInUse(cUnit, reservedRegs[i]);
+  }
+  // Mark temp regs - all others not in use can be used for promotion
+  for (int i = 0; i < numTemps; i++) {
+    oatMarkTemp(cUnit, coreTemps[i]);
+  }
+  for (int i = 0; i < numFPTemps; i++) {
+    oatMarkTemp(cUnit, fpTemps[i]);
+  }
+  // Construct the alias map.
+  cUnit->phiAliasMap = (int*)oatNew(cUnit, cUnit->numSSARegs *
+                                    sizeof(cUnit->phiAliasMap[0]), false,
+                                    kAllocDFInfo);
+  for (int i = 0; i < cUnit->numSSARegs; i++) {
+    cUnit->phiAliasMap[i] = i;
+  }
+  for (MIR* phi = cUnit->phiList; phi; phi = phi->meta.phiNext) {
+    int defReg = phi->ssaRep->defs[0];
+    for (int i = 0; i < phi->ssaRep->numUses; i++) {
+      for (int j = 0; j < cUnit->numSSARegs; j++) {
+        if (cUnit->phiAliasMap[j] == phi->ssaRep->uses[i]) {
+          cUnit->phiAliasMap[j] = defReg;
         }
+      }
     }
+  }
 }
 
 void freeRegLocTemps(CompilationUnit* cUnit, RegLocation rlKeep,
-                     RegLocation rlFree)
-{
-    if ((rlFree.lowReg != rlKeep.lowReg) && (rlFree.lowReg != rlKeep.highReg) &&
-        (rlFree.highReg != rlKeep.lowReg) && (rlFree.highReg != rlKeep.highReg)) {
-        // No overlap, free both
-        oatFreeTemp(cUnit, rlFree.lowReg);
-        oatFreeTemp(cUnit, rlFree.highReg);
-    }
+                     RegLocation rlFree) {
+  if ((rlFree.lowReg != rlKeep.lowReg) && (rlFree.lowReg != rlKeep.highReg) &&
+      (rlFree.highReg != rlKeep.lowReg) && (rlFree.highReg != rlKeep.highReg)) {
+    // No overlap, free both
+    oatFreeTemp(cUnit, rlFree.lowReg);
+    oatFreeTemp(cUnit, rlFree.highReg);
+  }
 }
 
 
diff --git a/src/compiler/codegen/x86/X86LIR.h b/src/compiler/codegen/x86/X86LIR.h
index 65f07cf..c805333 100644
--- a/src/compiler/codegen/x86/X86LIR.h
+++ b/src/compiler/codegen/x86/X86LIR.h
@@ -106,11 +106,11 @@
  */
 
 /* Offset to distingish FP regs */
-#define FP_REG_OFFSET 16
+#define FP_REG_OFFSET 32
 /* Offset to distinguish DP FP regs */
-#define FP_DOUBLE 32
+#define FP_DOUBLE (FP_REG_OFFSET + 16)
 /* Offset to distingish the extra regs */
-#define EXTRA_REG_OFFSET 64
+#define EXTRA_REG_OFFSET (FP_DOUBLE + 16)
 /* Reg types */
 #define REGTYPE(x) (x & (FP_REG_OFFSET | FP_DOUBLE))
 #define FPREG(x) ((x & FP_REG_OFFSET) == FP_REG_OFFSET)
@@ -128,15 +128,18 @@
  */
 #define S2D(x,y) ((x) | FP_DOUBLE)
 /* Mask to strip off fp flags */
-#define FP_REG_MASK (FP_REG_OFFSET-1)
+#define FP_REG_MASK 0xF
 /* non-existent Dalvik register */
 #define vNone   (-1)
 /* non-existant physical register */
 #define rNone   (-1)
 
-/* RegisterLocation templates return values (rAX, or rAX/rDX) */
-#define LOC_C_RETURN      {kLocPhysReg, 0, 0, 0, 0, 0, 1, rAX, INVALID_REG, INVALID_SREG}
-#define LOC_C_RETURN_WIDE {kLocPhysReg, 1, 0, 0, 0, 0, 1, rAX, rDX,         INVALID_SREG}
+/* RegisterLocation templates return values (rAX, rAX/rDX or XMM0) */
+//                               location,     wide, defined, fp, core, highWord, home, lowReg, highReg,     sRegLow
+#define LOC_C_RETURN             {kLocPhysReg, 0,    0,       0,  0,    0,        1,    rAX,    INVALID_REG, INVALID_SREG}
+#define LOC_C_RETURN_WIDE        {kLocPhysReg, 1,    0,       0,  0,    0,        1,    rAX,    rDX,         INVALID_SREG}
+#define LOC_C_RETURN_FLOAT       {kLocPhysReg, 0,    0,       1,  0,    0,        1,    fr0,    INVALID_REG, INVALID_SREG}
+#define LOC_C_RETURN_WIDE_DOUBLE {kLocPhysReg, 1,    0,       1,  0,    0,        1,    fr0,    fr1,         INVALID_SREG}
 
 enum ResourceEncodingPos {
     kGPReg0     = 0,
@@ -201,6 +204,7 @@
   r13    = 13,
   r14    = 14,
   r15    = 15,
+  rRET   = 16,  // fake return address register for core spill mask
   fr0  =  0 + FP_REG_OFFSET,
   fr1  =  1 + FP_REG_OFFSET,
   fr2  =  2 + FP_REG_OFFSET,
diff --git a/src/compiler/codegen/x86/X86RallocUtil.cc b/src/compiler/codegen/x86/X86RallocUtil.cc
index 1b4eca4..ff5391d 100644
--- a/src/compiler/codegen/x86/X86RallocUtil.cc
+++ b/src/compiler/codegen/x86/X86RallocUtil.cc
@@ -29,6 +29,8 @@
 
 void oatAdjustSpillMask(CompilationUnit* cUnit) {
   // Adjustment for LR spilling, x86 has no LR so nothing to do here
+  cUnit->coreSpillMask |= (1 << rRET);
+  cUnit->numCoreSpills++;
 }
 
 /*
@@ -138,17 +140,16 @@
 #endif
 }
 
-extern RegLocation oatGetReturnWideAlt(CompilationUnit* cUnit)
-{
-    RegLocation res = LOC_C_RETURN_WIDE;
-    res.lowReg = rAX;
-    res.highReg = rDX;
-    oatClobber(cUnit, rAX);
-    oatClobber(cUnit, rDX);
-    oatMarkInUse(cUnit, rAX);
-    oatMarkInUse(cUnit, rDX);
-    oatMarkPair(cUnit, res.lowReg, res.highReg);
-    return res;
+extern RegLocation oatGetReturnWideAlt(CompilationUnit* cUnit) {
+  RegLocation res = LOC_C_RETURN_WIDE;
+  CHECK(res.lowReg == rAX);
+  CHECK(res.highReg == rDX);
+  oatClobber(cUnit, rAX);
+  oatClobber(cUnit, rDX);
+  oatMarkInUse(cUnit, rAX);
+  oatMarkInUse(cUnit, rDX);
+  oatMarkPair(cUnit, res.lowReg, res.highReg);
+  return res;
 }
 
 extern RegLocation oatGetReturnAlt(CompilationUnit* cUnit)