am 856d111c: am b6d37288: JIT: Fix for 2813841, use core regs for sub-word data

Merge commit '856d111c4c87e4b47c71954dc6548e636295ea50' into gingerbread-plus-aosp

* commit '856d111c4c87e4b47c71954dc6548e636295ea50':
  JIT: Fix for 2813841, use core regs for sub-word data
diff --git a/vm/compiler/codegen/arm/CodegenDriver.c b/vm/compiler/codegen/arm/CodegenDriver.c
index e9f00dd..c84128e 100644
--- a/vm/compiler/codegen/arm/CodegenDriver.c
+++ b/vm/compiler/codegen/arm/CodegenDriver.c
@@ -289,11 +289,11 @@
 {
     int regPtr;
     RegLocation rlResult;
-    DecodedInstruction *dInsn = &mir->dalvikInsn;
+    RegisterClass regClass = dvmCompilerRegClassBySize(size);
     RegLocation rlObj = dvmCompilerGetSrc(cUnit, mir, 0);
     RegLocation rlDest = dvmCompilerGetDest(cUnit, mir, 0);
     rlObj = loadValue(cUnit, rlObj, kCoreReg);
-    rlResult = dvmCompilerEvalLoc(cUnit, rlDest, kAnyReg, true);
+    rlResult = dvmCompilerEvalLoc(cUnit, rlDest, regClass, true);
     genNullCheck(cUnit, rlObj.sRegLow, rlObj.lowReg, mir->offset,
                  NULL);/* null object? */
 
@@ -312,12 +312,11 @@
 static void genIPut(CompilationUnit *cUnit, MIR *mir, OpSize size,
                     int fieldOffset)
 {
-    DecodedInstruction *dInsn = &mir->dalvikInsn;
+    RegisterClass regClass = dvmCompilerRegClassBySize(size);
     RegLocation rlSrc = dvmCompilerGetSrc(cUnit, mir, 0);
     RegLocation rlObj = dvmCompilerGetSrc(cUnit, mir, 1);
     rlObj = loadValue(cUnit, rlObj, kCoreReg);
-    rlSrc = loadValue(cUnit, rlSrc, kAnyReg);
-    int regPtr;
+    rlSrc = loadValue(cUnit, rlSrc, regClass);
     genNullCheck(cUnit, rlObj.sRegLow, rlObj.lowReg, mir->offset,
                  NULL);/* null object? */
 
@@ -334,6 +333,7 @@
                         RegLocation rlArray, RegLocation rlIndex,
                         RegLocation rlDest, int scale)
 {
+    RegisterClass regClass = dvmCompilerRegClassBySize(size);
     int lenOffset = offsetof(ArrayObject, length);
     int dataOffset = offsetof(ArrayObject, contents);
     RegLocation rlResult;
@@ -373,7 +373,7 @@
         } else {
             opRegReg(cUnit, kOpAdd, regPtr, rlIndex.lowReg);
         }
-        rlResult = dvmCompilerEvalLoc(cUnit, rlDest, kAnyReg, true);
+        rlResult = dvmCompilerEvalLoc(cUnit, rlDest, regClass, true);
 
         HEAP_ACCESS_SHADOW(true);
         loadPair(cUnit, regPtr, rlResult.lowReg, rlResult.highReg);
@@ -382,7 +382,7 @@
         dvmCompilerFreeTemp(cUnit, regPtr);
         storeValueWide(cUnit, rlDest, rlResult);
     } else {
-        rlResult = dvmCompilerEvalLoc(cUnit, rlDest, kAnyReg, true);
+        rlResult = dvmCompilerEvalLoc(cUnit, rlDest, regClass, true);
 
         HEAP_ACCESS_SHADOW(true);
         loadBaseIndexed(cUnit, regPtr, rlIndex.lowReg, rlResult.lowReg,
@@ -402,6 +402,7 @@
                         RegLocation rlArray, RegLocation rlIndex,
                         RegLocation rlSrc, int scale)
 {
+    RegisterClass regClass = dvmCompilerRegClassBySize(size);
     int lenOffset = offsetof(ArrayObject, length);
     int dataOffset = offsetof(ArrayObject, contents);
 
@@ -450,7 +451,7 @@
         } else {
             opRegReg(cUnit, kOpAdd, regPtr, rlIndex.lowReg);
         }
-        rlSrc = loadValueWide(cUnit, rlSrc, kAnyReg);
+        rlSrc = loadValueWide(cUnit, rlSrc, regClass);
 
         HEAP_ACCESS_SHADOW(true);
         storePair(cUnit, regPtr, rlSrc.lowReg, rlSrc.highReg);
@@ -458,7 +459,7 @@
 
         dvmCompilerFreeTemp(cUnit, regPtr);
     } else {
-        rlSrc = loadValue(cUnit, rlSrc, kAnyReg);
+        rlSrc = loadValue(cUnit, rlSrc, regClass);
 
         HEAP_ACCESS_SHADOW(true);
         storeBaseIndexed(cUnit, regPtr, rlIndex.lowReg, rlSrc.lowReg,
diff --git a/vm/compiler/codegen/arm/Ralloc.h b/vm/compiler/codegen/arm/Ralloc.h
index 6c7dfaa..cc3e605 100644
--- a/vm/compiler/codegen/arm/Ralloc.h
+++ b/vm/compiler/codegen/arm/Ralloc.h
@@ -27,6 +27,20 @@
 #include "compiler/Dataflow.h"
 #include "compiler/codegen/arm/ArmLIR.h"
 
+/*
+ * Return most flexible allowed register class based on size.
+ * Bug: 2813841
+ * Must use a core register for data types narrower than word (due
+ * to possible unaligned load/store.
+ */
+static inline RegisterClass dvmCompilerRegClassBySize(OpSize size)
+{
+    return (size == kUnsignedHalf ||
+            size == kSignedHalf ||
+            size == kUnsignedByte ||
+            size == kSignedByte ) ? kCoreReg : kAnyReg;
+}
+
 static inline int dvmCompilerS2VReg(CompilationUnit *cUnit, int sReg)
 {
     assert(sReg != INVALID_SREG);
diff --git a/vm/compiler/codegen/arm/Thumb2/Factory.c b/vm/compiler/codegen/arm/Thumb2/Factory.c
index 360b2c1..0141a0f 100644
--- a/vm/compiler/codegen/arm/Thumb2/Factory.c
+++ b/vm/compiler/codegen/arm/Thumb2/Factory.c
@@ -751,15 +751,9 @@
 
     if (FPREG(rSrc)) {
         assert(SINGLEREG(rSrc));
-        if ((size != kWord) && (size != kSingle)) {
-           /* Move float value into core register */
-           int tReg = dvmCompilerAllocTemp(cUnit);
-           dvmCompilerRegCopy(cUnit, tReg, rSrc);
-           rSrc = tReg;
-        } else {
-            opCode = kThumb2Vstrs;
-            size = kSingle;
-        }
+        assert((size == kWord) || (size == kSingle));
+        opCode = kThumb2Vstrs;
+        size = kSingle;
     } else {
         if (size == kSingle)
             size = kWord;
diff --git a/vm/compiler/codegen/arm/Thumb2/Ralloc.c b/vm/compiler/codegen/arm/Thumb2/Ralloc.c
index bfd7f3f..6adfd62 100644
--- a/vm/compiler/codegen/arm/Thumb2/Ralloc.c
+++ b/vm/compiler/codegen/arm/Thumb2/Ralloc.c
@@ -22,6 +22,9 @@
  *
  */
 
+/* Stress mode for testing: if defined will reverse corereg/floatreg hint */
+//#define REGCLASS_STRESS_MODE
+
 /*
  * Alloc a pair of core registers, or a double.  Low reg in low byte,
  * high reg in next byte.
@@ -32,6 +35,11 @@
     int highReg;
     int lowReg;
     int res = 0;
+
+#if defined(REGCLASS_STRESS_MODE)
+    fpHint = !fpHint;
+#endif
+
     if (((regClass == kAnyReg) && fpHint) || (regClass == kFPReg)) {
         lowReg = dvmCompilerAllocTempDouble(cUnit);
         highReg = lowReg + 1;
@@ -46,6 +54,9 @@
 int dvmCompilerAllocTypedTemp(CompilationUnit *cUnit, bool fpHint,
                                      int regClass)
 {
+#if defined(REGCLASS_STRESS_MODE)
+    fpHint = !fpHint;
+#endif
     if (((regClass == kAnyReg) && fpHint) || (regClass == kFPReg))
         return dvmCompilerAllocTempFloat(cUnit);
     return dvmCompilerAllocTemp(cUnit);