Merge "Various assembly fixes." into dalvik-dev
diff --git a/src/compiler/codegen/arm/ArmLIR.h b/src/compiler/codegen/arm/ArmLIR.h
index daa1396..1e4022e 100644
--- a/src/compiler/codegen/arm/ArmLIR.h
+++ b/src/compiler/codegen/arm/ArmLIR.h
@@ -693,6 +693,8 @@
     kThumb2SubsRRI12,    /* setflags encoding */
     kThumb2OrrRRRs,      /* orrx [111010100101] rn[19..16] [0000] rd[11..8]
                                    [0000] rm[3..0] */
+    kThumb2Push1,        /* t3 encoding of push */
+    kThumb2Pop1,         /* t3 encoding of pop */
     kArmLast,
 } ArmOpcode;
 
diff --git a/src/compiler/codegen/arm/Assemble.cc b/src/compiler/codegen/arm/Assemble.cc
index bbd97b4..af71efe 100644
--- a/src/compiler/codegen/arm/Assemble.cc
+++ b/src/compiler/codegen/arm/Assemble.cc
@@ -953,6 +953,16 @@
                  kFmtBitBlt, 11, 8, kFmtBitBlt, 19, 16, kFmtBitBlt, 3, 0,
                  kFmtShift, -1, -1, IS_QUAD_OP | REG_DEF0_USE12 | SETS_CCODES,
                  "orrs", "!0C, !1C, !2C!3H", 2),
+    ENCODING_MAP(kThumb2Push1,    0xf84d0d04,
+                 kFmtBitBlt, 15, 12, kFmtUnused, -1, -1, kFmtUnused, -1, -1,
+                 kFmtUnused, -1, -1,
+                 IS_UNARY_OP | REG_DEF_SP | REG_USE_SP | REG_USE0
+                 | IS_STORE, "push1", "!0C", 2),
+    ENCODING_MAP(kThumb2Pop1,    0xf85d0b04,
+                 kFmtBitBlt, 15, 12, kFmtUnused, -1, -1, kFmtUnused, -1, -1,
+                 kFmtUnused, -1, -1,
+                 IS_UNARY_OP | REG_DEF_SP | REG_USE_SP | REG_DEF0
+                 | IS_LOAD, "pop1", "!0C", 2),
 
 };
 
@@ -1167,6 +1177,30 @@
             } else {
                 lir->operands[1] = delta >> 1;
             }
+        } else if (lir->opcode == kThumb2Push ||
+                   lir->opcode == kThumb2Pop) {
+            if (__builtin_popcount(lir->operands[0]) == 1) {
+                /*
+                 * The standard push/pop multiple instruction
+                 * requires at least two registers in the list.
+                 * If we've got just one, switch to the single-reg
+                 * encoding.
+                 */
+                lir->opcode = (lir->opcode == kThumb2Push)
+                    ? kThumb2Push1 : kThumb2Pop1;
+                int reg = 0;
+                while (lir->operands[0]) {
+                    if (lir->operands[0] & 0x1) {
+                        break;
+                    } else {
+                        reg++;
+                        lir->operands[0] >>= 1;
+                    }
+                }
+                lir->operands[0] = reg;
+                oatSetupResourceMasks(lir);
+                res = kRetryAll;
+            }
         } else if (lir->opcode == kThumbBCond ||
                    lir->opcode == kThumb2BCond) {
             ArmLIR *targetLIR = (ArmLIR *) lir->generic.target;