Merge "ART: Add 16-bit Thumb2 ROR, NEGS and CMP for high registers."
diff --git a/compiler/optimizing/code_generator_arm.cc b/compiler/optimizing/code_generator_arm.cc
index 62026f3..9de9abf 100644
--- a/compiler/optimizing/code_generator_arm.cc
+++ b/compiler/optimizing/code_generator_arm.cc
@@ -2731,11 +2731,9 @@
         Register temp = locations->GetTemp(0).AsRegister<Register>();
 
         // temp = reg1 / reg2  (integer division)
-        // temp = temp * reg2
-        // dest = reg1 - temp
+        // dest = reg1 - temp * reg2
         __ sdiv(temp, reg1, reg2);
-        __ mul(temp, temp, reg2);
-        __ sub(out.AsRegister<Register>(), reg1, ShifterOperand(temp));
+        __ mls(out.AsRegister<Register>(), temp, reg2, reg1);
       } else {
         InvokeRuntimeCallingConvention calling_convention;
         DCHECK_EQ(calling_convention.GetRegisterAt(0), first.AsRegister<Register>());
@@ -2905,7 +2903,7 @@
         // If the shift is > 32 bits, override the high part
         __ subs(temp, o_l, ShifterOperand(kArmBitsPerWord));
         __ it(PL);
-        __ Lsl(o_h, low, temp, false, PL);
+        __ Lsl(o_h, low, temp, PL);
         // Shift the low part
         __ Lsl(o_l, low, o_l);
       } else if (op->IsShr()) {
@@ -2919,7 +2917,7 @@
         // If the shift is > 32 bits, override the low part
         __ subs(temp, o_h, ShifterOperand(kArmBitsPerWord));
         __ it(PL);
-        __ Asr(o_l, high, temp, false, PL);
+        __ Asr(o_l, high, temp, PL);
         // Shift the high part
         __ Asr(o_h, high, o_h);
       } else {
@@ -2931,7 +2929,7 @@
         __ orr(o_l, o_l, ShifterOperand(temp));
         __ subs(temp, o_h, ShifterOperand(kArmBitsPerWord));
         __ it(PL);
-        __ Lsr(o_l, high, temp, false, PL);
+        __ Lsr(o_l, high, temp, PL);
         __ Lsr(o_h, high, o_h);
       }
       break;
diff --git a/compiler/utils/arm/assembler_arm.cc b/compiler/utils/arm/assembler_arm.cc
index 0e3e08c..807beda 100644
--- a/compiler/utils/arm/assembler_arm.cc
+++ b/compiler/utils/arm/assembler_arm.cc
@@ -137,10 +137,14 @@
         if (rs_ == kNoRegister) {
           // Immediate shift.
           if (shift_ == RRX) {
+            DCHECK_EQ(immed_, 0u);
             // RRX is encoded as an ROR with imm 0.
             return ROR << 4 | static_cast<uint32_t>(rm_);
           } else {
-            uint32_t imm3 = immed_ >> 2;
+            DCHECK((1 <= immed_ && immed_ <= 31) ||
+                   (immed_ == 0u && shift_ == LSL) ||
+                   (immed_ == 32u && (shift_ == ASR || shift_ == LSR)));
+            uint32_t imm3 = (immed_ >> 2) & 7 /* 0b111*/;
             uint32_t imm2 = immed_ & 3U /* 0b11 */;
 
             return imm3 << 12 | imm2 << 6 | shift_ << 4 |
diff --git a/compiler/utils/arm/assembler_arm.h b/compiler/utils/arm/assembler_arm.h
index ef60fef..7825457 100644
--- a/compiler/utils/arm/assembler_arm.h
+++ b/compiler/utils/arm/assembler_arm.h
@@ -375,6 +375,13 @@
   kItE = kItElse
 };
 
+// Set condition codes request.
+enum SetCc {
+  kCcDontCare,  // Allows prioritizing 16-bit instructions on Thumb2 whether they set CCs or not.
+  kCcSet,
+  kCcKeep,
+};
+
 constexpr uint32_t kNoItCondition = 3;
 constexpr uint32_t kInvalidModifiedImmediate = -1;
 
@@ -392,25 +399,61 @@
   virtual bool IsThumb() const = 0;
 
   // Data-processing instructions.
-  virtual void and_(Register rd, Register rn, const ShifterOperand& so, Condition cond = AL) = 0;
+  virtual void and_(Register rd, Register rn, const ShifterOperand& so,
+                    Condition cond = AL, SetCc set_cc = kCcDontCare) = 0;
 
-  virtual void eor(Register rd, Register rn, const ShifterOperand& so, Condition cond = AL) = 0;
+  virtual void ands(Register rd, Register rn, const ShifterOperand& so, Condition cond = AL) {
+    and_(rd, rn, so, cond, kCcSet);
+  }
 
-  virtual void sub(Register rd, Register rn, const ShifterOperand& so, Condition cond = AL) = 0;
-  virtual void subs(Register rd, Register rn, const ShifterOperand& so, Condition cond = AL) = 0;
+  virtual void eor(Register rd, Register rn, const ShifterOperand& so,
+                   Condition cond = AL, SetCc set_cc = kCcDontCare) = 0;
 
-  virtual void rsb(Register rd, Register rn, const ShifterOperand& so, Condition cond = AL) = 0;
-  virtual void rsbs(Register rd, Register rn, const ShifterOperand& so, Condition cond = AL) = 0;
+  virtual void eors(Register rd, Register rn, const ShifterOperand& so, Condition cond = AL) {
+    eor(rd, rn, so, cond, kCcSet);
+  }
 
-  virtual void add(Register rd, Register rn, const ShifterOperand& so, Condition cond = AL) = 0;
+  virtual void sub(Register rd, Register rn, const ShifterOperand& so,
+                   Condition cond = AL, SetCc set_cc = kCcDontCare) = 0;
 
-  virtual void adds(Register rd, Register rn, const ShifterOperand& so, Condition cond = AL) = 0;
+  virtual void subs(Register rd, Register rn, const ShifterOperand& so, Condition cond = AL) {
+    sub(rd, rn, so, cond, kCcSet);
+  }
 
-  virtual void adc(Register rd, Register rn, const ShifterOperand& so, Condition cond = AL) = 0;
+  virtual void rsb(Register rd, Register rn, const ShifterOperand& so,
+                   Condition cond = AL, SetCc set_cc = kCcDontCare) = 0;
 
-  virtual void sbc(Register rd, Register rn, const ShifterOperand& so, Condition cond = AL) = 0;
+  virtual void rsbs(Register rd, Register rn, const ShifterOperand& so, Condition cond = AL) {
+    rsb(rd, rn, so, cond, kCcSet);
+  }
 
-  virtual void rsc(Register rd, Register rn, const ShifterOperand& so, Condition cond = AL) = 0;
+  virtual void add(Register rd, Register rn, const ShifterOperand& so,
+                   Condition cond = AL, SetCc set_cc = kCcDontCare) = 0;
+
+  virtual void adds(Register rd, Register rn, const ShifterOperand& so, Condition cond = AL) {
+    add(rd, rn, so, cond, kCcSet);
+  }
+
+  virtual void adc(Register rd, Register rn, const ShifterOperand& so,
+                   Condition cond = AL, SetCc set_cc = kCcDontCare) = 0;
+
+  virtual void adcs(Register rd, Register rn, const ShifterOperand& so, Condition cond = AL) {
+    adc(rd, rn, so, cond, kCcSet);
+  }
+
+  virtual void sbc(Register rd, Register rn, const ShifterOperand& so,
+                   Condition cond = AL, SetCc set_cc = kCcDontCare) = 0;
+
+  virtual void sbcs(Register rd, Register rn, const ShifterOperand& so, Condition cond = AL) {
+    sbc(rd, rn, so, cond, kCcSet);
+  }
+
+  virtual void rsc(Register rd, Register rn, const ShifterOperand& so,
+                   Condition cond = AL, SetCc set_cc = kCcDontCare) = 0;
+
+  virtual void rscs(Register rd, Register rn, const ShifterOperand& so, Condition cond = AL) {
+    rsc(rd, rn, so, cond, kCcSet);
+  }
 
   virtual void tst(Register rn, const ShifterOperand& so, Condition cond = AL) = 0;
 
@@ -420,16 +463,33 @@
 
   virtual void cmn(Register rn, const ShifterOperand& so, Condition cond = AL) = 0;
 
-  virtual void orr(Register rd, Register rn, const ShifterOperand& so, Condition cond = AL) = 0;
-  virtual void orrs(Register rd, Register rn, const ShifterOperand& so, Condition cond = AL) = 0;
+  virtual void orr(Register rd, Register rn, const ShifterOperand& so,
+                   Condition cond = AL, SetCc set_cc = kCcDontCare) = 0;
 
-  virtual void mov(Register rd, const ShifterOperand& so, Condition cond = AL) = 0;
-  virtual void movs(Register rd, const ShifterOperand& so, Condition cond = AL) = 0;
+  virtual void orrs(Register rd, Register rn, const ShifterOperand& so, Condition cond = AL) {
+    orr(rd, rn, so, cond, kCcSet);
+  }
 
-  virtual void bic(Register rd, Register rn, const ShifterOperand& so, Condition cond = AL) = 0;
+  virtual void mov(Register rd, const ShifterOperand& so,
+                   Condition cond = AL, SetCc set_cc = kCcDontCare) = 0;
 
-  virtual void mvn(Register rd, const ShifterOperand& so, Condition cond = AL) = 0;
-  virtual void mvns(Register rd, const ShifterOperand& so, Condition cond = AL) = 0;
+  virtual void movs(Register rd, const ShifterOperand& so, Condition cond = AL) {
+    mov(rd, so, cond, kCcSet);
+  }
+
+  virtual void bic(Register rd, Register rn, const ShifterOperand& so,
+                   Condition cond = AL, SetCc set_cc = kCcDontCare) = 0;
+
+  virtual void bics(Register rd, Register rn, const ShifterOperand& so, Condition cond = AL) {
+    bic(rd, rn, so, cond, kCcSet);
+  }
+
+  virtual void mvn(Register rd, const ShifterOperand& so,
+                   Condition cond = AL, SetCc set_cc = kCcDontCare) = 0;
+
+  virtual void mvns(Register rd, const ShifterOperand& so, Condition cond = AL) {
+    mvn(rd, so, cond, kCcSet);
+  }
 
   // Miscellaneous data-processing instructions.
   virtual void clz(Register rd, Register rm, Condition cond = AL) = 0;
@@ -697,25 +757,68 @@
 
   // Convenience shift instructions. Use mov instruction with shifter operand
   // for variants setting the status flags or using a register shift count.
-  virtual void Lsl(Register rd, Register rm, uint32_t shift_imm, bool setcc = false,
-                   Condition cond = AL) = 0;
-  virtual void Lsr(Register rd, Register rm, uint32_t shift_imm, bool setcc = false,
-                   Condition cond = AL) = 0;
-  virtual void Asr(Register rd, Register rm, uint32_t shift_imm, bool setcc = false,
-                   Condition cond = AL) = 0;
-  virtual void Ror(Register rd, Register rm, uint32_t shift_imm, bool setcc = false,
-                   Condition cond = AL) = 0;
-  virtual void Rrx(Register rd, Register rm, bool setcc = false,
-                   Condition cond = AL) = 0;
+  virtual void Lsl(Register rd, Register rm, uint32_t shift_imm,
+                   Condition cond = AL, SetCc set_cc = kCcDontCare) = 0;
 
-  virtual void Lsl(Register rd, Register rm, Register rn, bool setcc = false,
-                   Condition cond = AL) = 0;
-  virtual void Lsr(Register rd, Register rm, Register rn, bool setcc = false,
-                   Condition cond = AL) = 0;
-  virtual void Asr(Register rd, Register rm, Register rn, bool setcc = false,
-                   Condition cond = AL) = 0;
-  virtual void Ror(Register rd, Register rm, Register rn, bool setcc = false,
-                   Condition cond = AL) = 0;
+  void Lsls(Register rd, Register rm, uint32_t shift_imm, Condition cond = AL) {
+    Lsl(rd, rm, shift_imm, cond, kCcSet);
+  }
+
+  virtual void Lsr(Register rd, Register rm, uint32_t shift_imm,
+                   Condition cond = AL, SetCc set_cc = kCcDontCare) = 0;
+
+  void Lsrs(Register rd, Register rm, uint32_t shift_imm, Condition cond = AL) {
+    Lsr(rd, rm, shift_imm, cond, kCcSet);
+  }
+
+  virtual void Asr(Register rd, Register rm, uint32_t shift_imm,
+                   Condition cond = AL, SetCc set_cc = kCcDontCare) = 0;
+
+  void Asrs(Register rd, Register rm, uint32_t shift_imm, Condition cond = AL) {
+    Asr(rd, rm, shift_imm, cond, kCcSet);
+  }
+
+  virtual void Ror(Register rd, Register rm, uint32_t shift_imm,
+                   Condition cond = AL, SetCc set_cc = kCcDontCare) = 0;
+
+  void Rors(Register rd, Register rm, uint32_t shift_imm, Condition cond = AL) {
+    Ror(rd, rm, shift_imm, cond, kCcSet);
+  }
+
+  virtual void Rrx(Register rd, Register rm,
+                   Condition cond = AL, SetCc set_cc = kCcDontCare) = 0;
+
+  void Rrxs(Register rd, Register rm, Condition cond = AL) {
+    Rrx(rd, rm, cond, kCcSet);
+  }
+
+  virtual void Lsl(Register rd, Register rm, Register rn,
+                   Condition cond = AL, SetCc set_cc = kCcDontCare) = 0;
+
+  void Lsls(Register rd, Register rm, Register rn, Condition cond = AL) {
+    Lsl(rd, rm, rn, cond, kCcSet);
+  }
+
+  virtual void Lsr(Register rd, Register rm, Register rn,
+                   Condition cond = AL, SetCc set_cc = kCcDontCare) = 0;
+
+  void Lsrs(Register rd, Register rm, Register rn, Condition cond = AL) {
+    Lsr(rd, rm, rn, cond, kCcSet);
+  }
+
+  virtual void Asr(Register rd, Register rm, Register rn,
+                   Condition cond = AL, SetCc set_cc = kCcDontCare) = 0;
+
+  void Asrs(Register rd, Register rm, Register rn, Condition cond = AL) {
+    Asr(rd, rm, rn, cond, kCcSet);
+  }
+
+  virtual void Ror(Register rd, Register rm, Register rn,
+                   Condition cond = AL, SetCc set_cc = kCcDontCare) = 0;
+
+  void Rors(Register rd, Register rm, Register rn, Condition cond = AL) {
+    Ror(rd, rm, rn, cond, kCcSet);
+  }
 
   // Returns whether the `immediate` can fit in a `ShifterOperand`. If yes,
   // `shifter_op` contains the operand.
diff --git a/compiler/utils/arm/assembler_arm32.cc b/compiler/utils/arm/assembler_arm32.cc
index 6e60ddc..d91ddee 100644
--- a/compiler/utils/arm/assembler_arm32.cc
+++ b/compiler/utils/arm/assembler_arm32.cc
@@ -57,126 +57,94 @@
 }
 
 void Arm32Assembler::and_(Register rd, Register rn, const ShifterOperand& so,
-                        Condition cond) {
-  EmitType01(cond, so.type(), AND, 0, rn, rd, so);
+                          Condition cond, SetCc set_cc) {
+  EmitType01(cond, so.type(), AND, set_cc, rn, rd, so);
 }
 
 
 void Arm32Assembler::eor(Register rd, Register rn, const ShifterOperand& so,
-                       Condition cond) {
-  EmitType01(cond, so.type(), EOR, 0, rn, rd, so);
+                         Condition cond, SetCc set_cc) {
+  EmitType01(cond, so.type(), EOR, set_cc, rn, rd, so);
 }
 
 
 void Arm32Assembler::sub(Register rd, Register rn, const ShifterOperand& so,
-                       Condition cond) {
-  EmitType01(cond, so.type(), SUB, 0, rn, rd, so);
+                         Condition cond, SetCc set_cc) {
+  EmitType01(cond, so.type(), SUB, set_cc, rn, rd, so);
 }
 
 void Arm32Assembler::rsb(Register rd, Register rn, const ShifterOperand& so,
-                       Condition cond) {
-  EmitType01(cond, so.type(), RSB, 0, rn, rd, so);
+                         Condition cond, SetCc set_cc) {
+  EmitType01(cond, so.type(), RSB, set_cc, rn, rd, so);
 }
 
-void Arm32Assembler::rsbs(Register rd, Register rn, const ShifterOperand& so,
-                        Condition cond) {
-  EmitType01(cond, so.type(), RSB, 1, rn, rd, so);
-}
-
-
 void Arm32Assembler::add(Register rd, Register rn, const ShifterOperand& so,
-                       Condition cond) {
-  EmitType01(cond, so.type(), ADD, 0, rn, rd, so);
-}
-
-
-void Arm32Assembler::adds(Register rd, Register rn, const ShifterOperand& so,
-                        Condition cond) {
-  EmitType01(cond, so.type(), ADD, 1, rn, rd, so);
-}
-
-
-void Arm32Assembler::subs(Register rd, Register rn, const ShifterOperand& so,
-                        Condition cond) {
-  EmitType01(cond, so.type(), SUB, 1, rn, rd, so);
+                         Condition cond, SetCc set_cc) {
+  EmitType01(cond, so.type(), ADD, set_cc, rn, rd, so);
 }
 
 
 void Arm32Assembler::adc(Register rd, Register rn, const ShifterOperand& so,
-                       Condition cond) {
-  EmitType01(cond, so.type(), ADC, 0, rn, rd, so);
+                         Condition cond, SetCc set_cc) {
+  EmitType01(cond, so.type(), ADC, set_cc, rn, rd, so);
 }
 
 
 void Arm32Assembler::sbc(Register rd, Register rn, const ShifterOperand& so,
-                       Condition cond) {
-  EmitType01(cond, so.type(), SBC, 0, rn, rd, so);
+                         Condition cond, SetCc set_cc) {
+  EmitType01(cond, so.type(), SBC, set_cc, rn, rd, so);
 }
 
 
 void Arm32Assembler::rsc(Register rd, Register rn, const ShifterOperand& so,
-                       Condition cond) {
-  EmitType01(cond, so.type(), RSC, 0, rn, rd, so);
+                         Condition cond, SetCc set_cc) {
+  EmitType01(cond, so.type(), RSC, set_cc, rn, rd, so);
 }
 
 
 void Arm32Assembler::tst(Register rn, const ShifterOperand& so, Condition cond) {
   CHECK_NE(rn, PC);  // Reserve tst pc instruction for exception handler marker.
-  EmitType01(cond, so.type(), TST, 1, rn, R0, so);
+  EmitType01(cond, so.type(), TST, kCcSet, rn, R0, so);
 }
 
 
 void Arm32Assembler::teq(Register rn, const ShifterOperand& so, Condition cond) {
   CHECK_NE(rn, PC);  // Reserve teq pc instruction for exception handler marker.
-  EmitType01(cond, so.type(), TEQ, 1, rn, R0, so);
+  EmitType01(cond, so.type(), TEQ, kCcSet, rn, R0, so);
 }
 
 
 void Arm32Assembler::cmp(Register rn, const ShifterOperand& so, Condition cond) {
-  EmitType01(cond, so.type(), CMP, 1, rn, R0, so);
+  EmitType01(cond, so.type(), CMP, kCcSet, rn, R0, so);
 }
 
 
 void Arm32Assembler::cmn(Register rn, const ShifterOperand& so, Condition cond) {
-  EmitType01(cond, so.type(), CMN, 1, rn, R0, so);
+  EmitType01(cond, so.type(), CMN, kCcSet, rn, R0, so);
 }
 
 
-void Arm32Assembler::orr(Register rd, Register rn,
-                    const ShifterOperand& so, Condition cond) {
-  EmitType01(cond, so.type(), ORR, 0, rn, rd, so);
+void Arm32Assembler::orr(Register rd, Register rn, const ShifterOperand& so,
+                         Condition cond, SetCc set_cc) {
+  EmitType01(cond, so.type(), ORR, set_cc, rn, rd, so);
 }
 
 
-void Arm32Assembler::orrs(Register rd, Register rn,
-                        const ShifterOperand& so, Condition cond) {
-  EmitType01(cond, so.type(), ORR, 1, rn, rd, so);
-}
-
-
-void Arm32Assembler::mov(Register rd, const ShifterOperand& so, Condition cond) {
-  EmitType01(cond, so.type(), MOV, 0, R0, rd, so);
-}
-
-
-void Arm32Assembler::movs(Register rd, const ShifterOperand& so, Condition cond) {
-  EmitType01(cond, so.type(), MOV, 1, R0, rd, so);
+void Arm32Assembler::mov(Register rd, const ShifterOperand& so,
+                         Condition cond, SetCc set_cc) {
+  EmitType01(cond, so.type(), MOV, set_cc, R0, rd, so);
 }
 
 
 void Arm32Assembler::bic(Register rd, Register rn, const ShifterOperand& so,
-                       Condition cond) {
-  EmitType01(cond, so.type(), BIC, 0, rn, rd, so);
+                         Condition cond, SetCc set_cc) {
+  EmitType01(cond, so.type(), BIC, set_cc, rn, rd, so);
 }
 
 
-void Arm32Assembler::mvn(Register rd, const ShifterOperand& so, Condition cond) {
-  EmitType01(cond, so.type(), MVN, 0, R0, rd, so);
-}
-
-
-void Arm32Assembler::mvns(Register rd, const ShifterOperand& so, Condition cond) {
-  EmitType01(cond, so.type(), MVN, 1, R0, rd, so);
+void Arm32Assembler::mvn(Register rd, const ShifterOperand& so,
+                         Condition cond, SetCc set_cc) {
+  EmitType01(cond, so.type(), MVN, set_cc, R0, rd, so);
 }
 
 
@@ -573,7 +541,7 @@
 
 
 void Arm32Assembler::MarkExceptionHandler(Label* label) {
-  EmitType01(AL, 1, TST, 1, PC, R0, ShifterOperand(0));
+  EmitType01(AL, 1, TST, kCcSet, PC, R0, ShifterOperand(0));
   Label l;
   b(&l);
   EmitBranch(AL, label, false);
@@ -590,7 +558,7 @@
 void Arm32Assembler::EmitType01(Condition cond,
                                 int type,
                                 Opcode opcode,
-                                int set_cc,
+                                SetCc set_cc,
                                 Register rn,
                                 Register rd,
                                 const ShifterOperand& so) {
@@ -599,7 +567,7 @@
   int32_t encoding = static_cast<int32_t>(cond) << kConditionShift |
                      type << kTypeShift |
                      static_cast<int32_t>(opcode) << kOpcodeShift |
-                     set_cc << kSShift |
+                     (set_cc == kCcSet ? 1 : 0) << kSShift |
                      static_cast<int32_t>(rn) << kRnShift |
                      static_cast<int32_t>(rd) << kRdShift |
                      so.encodingArm();
@@ -1158,96 +1126,60 @@
 
 
 void Arm32Assembler::Lsl(Register rd, Register rm, uint32_t shift_imm,
-                         bool setcc, Condition cond) {
+                         Condition cond, SetCc set_cc) {
   CHECK_LE(shift_imm, 31u);
-  if (setcc) {
-    movs(rd, ShifterOperand(rm, LSL, shift_imm), cond);
-  } else {
-    mov(rd, ShifterOperand(rm, LSL, shift_imm), cond);
-  }
+  mov(rd, ShifterOperand(rm, LSL, shift_imm), cond, set_cc);
 }
 
 
 void Arm32Assembler::Lsr(Register rd, Register rm, uint32_t shift_imm,
-                         bool setcc, Condition cond) {
+                         Condition cond, SetCc set_cc) {
   CHECK(1u <= shift_imm && shift_imm <= 32u);
   if (shift_imm == 32) shift_imm = 0;  // Comply to UAL syntax.
-  if (setcc) {
-    movs(rd, ShifterOperand(rm, LSR, shift_imm), cond);
-  } else {
-    mov(rd, ShifterOperand(rm, LSR, shift_imm), cond);
-  }
+  mov(rd, ShifterOperand(rm, LSR, shift_imm), cond, set_cc);
 }
 
 
 void Arm32Assembler::Asr(Register rd, Register rm, uint32_t shift_imm,
-                         bool setcc, Condition cond) {
+                         Condition cond, SetCc set_cc) {
   CHECK(1u <= shift_imm && shift_imm <= 32u);
   if (shift_imm == 32) shift_imm = 0;  // Comply to UAL syntax.
-  if (setcc) {
-    movs(rd, ShifterOperand(rm, ASR, shift_imm), cond);
-  } else {
-    mov(rd, ShifterOperand(rm, ASR, shift_imm), cond);
-  }
+  mov(rd, ShifterOperand(rm, ASR, shift_imm), cond, set_cc);
 }
 
 
 void Arm32Assembler::Ror(Register rd, Register rm, uint32_t shift_imm,
-                         bool setcc, Condition cond) {
+                         Condition cond, SetCc set_cc) {
   CHECK(1u <= shift_imm && shift_imm <= 31u);
-  if (setcc) {
-    movs(rd, ShifterOperand(rm, ROR, shift_imm), cond);
-  } else {
-    mov(rd, ShifterOperand(rm, ROR, shift_imm), cond);
-  }
+  mov(rd, ShifterOperand(rm, ROR, shift_imm), cond, set_cc);
 }
 
-void Arm32Assembler::Rrx(Register rd, Register rm, bool setcc, Condition cond) {
-  if (setcc) {
-    movs(rd, ShifterOperand(rm, ROR, 0), cond);
-  } else {
-    mov(rd, ShifterOperand(rm, ROR, 0), cond);
-  }
+void Arm32Assembler::Rrx(Register rd, Register rm, Condition cond, SetCc set_cc) {
+  mov(rd, ShifterOperand(rm, ROR, 0), cond, set_cc);
 }
 
 
 void Arm32Assembler::Lsl(Register rd, Register rm, Register rn,
-                         bool setcc, Condition cond) {
-  if (setcc) {
-    movs(rd, ShifterOperand(rm, LSL, rn), cond);
-  } else {
-    mov(rd, ShifterOperand(rm, LSL, rn), cond);
-  }
+                         Condition cond, SetCc set_cc) {
+  mov(rd, ShifterOperand(rm, LSL, rn), cond, set_cc);
 }
 
 
 void Arm32Assembler::Lsr(Register rd, Register rm, Register rn,
-                         bool setcc, Condition cond) {
-  if (setcc) {
-    movs(rd, ShifterOperand(rm, LSR, rn), cond);
-  } else {
-    mov(rd, ShifterOperand(rm, LSR, rn), cond);
-  }
+                         Condition cond, SetCc set_cc) {
+  mov(rd, ShifterOperand(rm, LSR, rn), cond, set_cc);
 }
 
 
 void Arm32Assembler::Asr(Register rd, Register rm, Register rn,
-                         bool setcc, Condition cond) {
-  if (setcc) {
-    movs(rd, ShifterOperand(rm, ASR, rn), cond);
-  } else {
-    mov(rd, ShifterOperand(rm, ASR, rn), cond);
-  }
+                         Condition cond, SetCc set_cc) {
+  mov(rd, ShifterOperand(rm, ASR, rn), cond, set_cc);
 }
 
 
 void Arm32Assembler::Ror(Register rd, Register rm, Register rn,
-                         bool setcc, Condition cond) {
-  if (setcc) {
-    movs(rd, ShifterOperand(rm, ROR, rn), cond);
-  } else {
-    mov(rd, ShifterOperand(rm, ROR, rn), cond);
-  }
+                         Condition cond, SetCc set_cc) {
+  mov(rd, ShifterOperand(rm, ROR, rn), cond, set_cc);
 }
 
 void Arm32Assembler::vmstat(Condition cond) {  // VMRS APSR_nzcv, FPSCR
@@ -1434,24 +1366,24 @@
                                          Condition cond) {
   ShifterOperand shifter_op;
   if (ShifterOperandCanHoldArm32(value, &shifter_op)) {
-    adds(rd, rn, shifter_op, cond);
+    add(rd, rn, shifter_op, cond, kCcSet);
   } else if (ShifterOperandCanHoldArm32(-value, &shifter_op)) {
-    subs(rd, rn, shifter_op, cond);
+    sub(rd, rn, shifter_op, cond, kCcSet);
   } else {
     CHECK(rn != IP);
     if (ShifterOperandCanHoldArm32(~value, &shifter_op)) {
       mvn(IP, shifter_op, cond);
-      adds(rd, rn, ShifterOperand(IP), cond);
+      add(rd, rn, ShifterOperand(IP), cond, kCcSet);
     } else if (ShifterOperandCanHoldArm32(~(-value), &shifter_op)) {
       mvn(IP, shifter_op, cond);
-      subs(rd, rn, ShifterOperand(IP), cond);
+      sub(rd, rn, ShifterOperand(IP), cond, kCcSet);
     } else {
       movw(IP, Low16Bits(value), cond);
       uint16_t value_high = High16Bits(value);
       if (value_high != 0) {
         movt(IP, value_high, cond);
       }
-      adds(rd, rn, ShifterOperand(IP), cond);
+      add(rd, rn, ShifterOperand(IP), cond, kCcSet);
     }
   }
 }
diff --git a/compiler/utils/arm/assembler_arm32.h b/compiler/utils/arm/assembler_arm32.h
index 1c38eec..b96bb74 100644
--- a/compiler/utils/arm/assembler_arm32.h
+++ b/compiler/utils/arm/assembler_arm32.h
@@ -39,25 +39,29 @@
   }
 
   // Data-processing instructions.
-  void and_(Register rd, Register rn, const ShifterOperand& so, Condition cond = AL) OVERRIDE;
+  virtual void and_(Register rd, Register rn, const ShifterOperand& so,
+                    Condition cond = AL, SetCc set_cc = kCcDontCare) OVERRIDE;
 
-  void eor(Register rd, Register rn, const ShifterOperand& so, Condition cond = AL) OVERRIDE;
+  virtual void eor(Register rd, Register rn, const ShifterOperand& so,
+                   Condition cond = AL, SetCc set_cc = kCcDontCare) OVERRIDE;
 
-  void sub(Register rd, Register rn, const ShifterOperand& so, Condition cond = AL) OVERRIDE;
-  void subs(Register rd, Register rn, const ShifterOperand& so, Condition cond = AL) OVERRIDE;
+  virtual void sub(Register rd, Register rn, const ShifterOperand& so,
+                   Condition cond = AL, SetCc set_cc = kCcDontCare) OVERRIDE;
 
-  void rsb(Register rd, Register rn, const ShifterOperand& so, Condition cond = AL) OVERRIDE;
-  void rsbs(Register rd, Register rn, const ShifterOperand& so, Condition cond = AL) OVERRIDE;
+  virtual void rsb(Register rd, Register rn, const ShifterOperand& so,
+                   Condition cond = AL, SetCc set_cc = kCcDontCare) OVERRIDE;
 
-  void add(Register rd, Register rn, const ShifterOperand& so, Condition cond = AL) OVERRIDE;
+  virtual void add(Register rd, Register rn, const ShifterOperand& so,
+                   Condition cond = AL, SetCc set_cc = kCcDontCare) OVERRIDE;
 
-  void adds(Register rd, Register rn, const ShifterOperand& so, Condition cond = AL) OVERRIDE;
+  virtual void adc(Register rd, Register rn, const ShifterOperand& so,
+                   Condition cond = AL, SetCc set_cc = kCcDontCare) OVERRIDE;
 
-  void adc(Register rd, Register rn, const ShifterOperand& so, Condition cond = AL) OVERRIDE;
+  virtual void sbc(Register rd, Register rn, const ShifterOperand& so,
+                   Condition cond = AL, SetCc set_cc = kCcDontCare) OVERRIDE;
 
-  void sbc(Register rd, Register rn, const ShifterOperand& so, Condition cond = AL) OVERRIDE;
-
-  void rsc(Register rd, Register rn, const ShifterOperand& so, Condition cond = AL) OVERRIDE;
+  virtual void rsc(Register rd, Register rn, const ShifterOperand& so,
+                   Condition cond = AL, SetCc set_cc = kCcDontCare) OVERRIDE;
 
   void tst(Register rn, const ShifterOperand& so, Condition cond = AL) OVERRIDE;
 
@@ -67,16 +71,17 @@
 
   void cmn(Register rn, const ShifterOperand& so, Condition cond = AL) OVERRIDE;
 
-  void orr(Register rd, Register rn, const ShifterOperand& so, Condition cond = AL) OVERRIDE;
-  void orrs(Register rd, Register rn, const ShifterOperand& so, Condition cond = AL) OVERRIDE;
+  virtual void orr(Register rd, Register rn, const ShifterOperand& so,
+                   Condition cond = AL, SetCc set_cc = kCcDontCare) OVERRIDE;
 
-  void mov(Register rd, const ShifterOperand& so, Condition cond = AL) OVERRIDE;
-  void movs(Register rd, const ShifterOperand& so, Condition cond = AL) OVERRIDE;
+  virtual void mov(Register rd, const ShifterOperand& so,
+                   Condition cond = AL, SetCc set_cc = kCcDontCare) OVERRIDE;
 
-  void bic(Register rd, Register rn, const ShifterOperand& so, Condition cond = AL) OVERRIDE;
+  virtual void bic(Register rd, Register rn, const ShifterOperand& so,
+                   Condition cond = AL, SetCc set_cc = kCcDontCare) OVERRIDE;
 
-  void mvn(Register rd, const ShifterOperand& so, Condition cond = AL) OVERRIDE;
-  void mvns(Register rd, const ShifterOperand& so, Condition cond = AL) OVERRIDE;
+  virtual void mvn(Register rd, const ShifterOperand& so,
+                   Condition cond = AL, SetCc set_cc = kCcDontCare) OVERRIDE;
 
   // Miscellaneous data-processing instructions.
   void clz(Register rd, Register rm, Condition cond = AL) OVERRIDE;
@@ -204,25 +209,25 @@
   void bl(Label* label, Condition cond = AL) OVERRIDE;
   void blx(Register rm, Condition cond = AL) OVERRIDE;
   void bx(Register rm, Condition cond = AL) OVERRIDE;
-  void Lsl(Register rd, Register rm, uint32_t shift_imm, bool setcc = false,
-           Condition cond = AL) OVERRIDE;
-  void Lsr(Register rd, Register rm, uint32_t shift_imm, bool setcc = false,
-           Condition cond = AL) OVERRIDE;
-  void Asr(Register rd, Register rm, uint32_t shift_imm, bool setcc = false,
-           Condition cond = AL) OVERRIDE;
-  void Ror(Register rd, Register rm, uint32_t shift_imm, bool setcc = false,
-           Condition cond = AL) OVERRIDE;
-  void Rrx(Register rd, Register rm, bool setcc = false,
-           Condition cond = AL) OVERRIDE;
+  virtual void Lsl(Register rd, Register rm, uint32_t shift_imm,
+                   Condition cond = AL, SetCc set_cc = kCcDontCare) OVERRIDE;
+  virtual void Lsr(Register rd, Register rm, uint32_t shift_imm,
+                   Condition cond = AL, SetCc set_cc = kCcDontCare) OVERRIDE;
+  virtual void Asr(Register rd, Register rm, uint32_t shift_imm,
+                   Condition cond = AL, SetCc set_cc = kCcDontCare) OVERRIDE;
+  virtual void Ror(Register rd, Register rm, uint32_t shift_imm,
+                   Condition cond = AL, SetCc set_cc = kCcDontCare) OVERRIDE;
+  virtual void Rrx(Register rd, Register rm,
+                   Condition cond = AL, SetCc set_cc = kCcDontCare) OVERRIDE;
 
-  void Lsl(Register rd, Register rm, Register rn, bool setcc = false,
-           Condition cond = AL) OVERRIDE;
-  void Lsr(Register rd, Register rm, Register rn, bool setcc = false,
-           Condition cond = AL) OVERRIDE;
-  void Asr(Register rd, Register rm, Register rn, bool setcc = false,
-           Condition cond = AL) OVERRIDE;
-  void Ror(Register rd, Register rm, Register rn, bool setcc = false,
-           Condition cond = AL) OVERRIDE;
+  virtual void Lsl(Register rd, Register rm, Register rn,
+                   Condition cond = AL, SetCc set_cc = kCcDontCare) OVERRIDE;
+  virtual void Lsr(Register rd, Register rm, Register rn,
+                   Condition cond = AL, SetCc set_cc = kCcDontCare) OVERRIDE;
+  virtual void Asr(Register rd, Register rm, Register rn,
+                   Condition cond = AL, SetCc set_cc = kCcDontCare) OVERRIDE;
+  virtual void Ror(Register rd, Register rm, Register rn,
+                   Condition cond = AL, SetCc set_cc = kCcDontCare) OVERRIDE;
 
   void Push(Register rd, Condition cond = AL) OVERRIDE;
   void Pop(Register rd, Condition cond = AL) OVERRIDE;
@@ -305,7 +310,7 @@
   void EmitType01(Condition cond,
                   int type,
                   Opcode opcode,
-                  int set_cc,
+                  SetCc set_cc,
                   Register rn,
                   Register rd,
                   const ShifterOperand& so);
diff --git a/compiler/utils/arm/assembler_arm32_test.cc b/compiler/utils/arm/assembler_arm32_test.cc
index efd517b..e6412ac 100644
--- a/compiler/utils/arm/assembler_arm32_test.cc
+++ b/compiler/utils/arm/assembler_arm32_test.cc
@@ -42,7 +42,8 @@
 
 class AssemblerArm32Test : public AssemblerArmTest<arm::Arm32Assembler,
                                                    arm::Register, arm::SRegister,
-                                                   uint32_t, arm::ShifterOperand, arm::Condition> {
+                                                   uint32_t, arm::ShifterOperand, arm::Condition,
+                                                   arm::SetCc> {
  protected:
   std::string GetArchitectureString() OVERRIDE {
     return "arm";
@@ -125,6 +126,10 @@
       conditions_.push_back(arm::Condition::AL);
     }
 
+    set_ccs_.push_back(arm::kCcDontCare);
+    set_ccs_.push_back(arm::kCcSet);
+    set_ccs_.push_back(arm::kCcKeep);
+
     shifter_operands_.push_back(arm::ShifterOperand(0));
     shifter_operands_.push_back(arm::ShifterOperand(1));
     shifter_operands_.push_back(arm::ShifterOperand(2));
@@ -240,6 +245,15 @@
     return oss.str();
   }
 
+  std::vector<arm::SetCc>& GetSetCcs() OVERRIDE {
+    return set_ccs_;
+  }
+
+  std::string GetSetCcString(arm::SetCc s) OVERRIDE {
+    // For arm32, kCcDontCare defaults to not setting condition codes.
+    return s == arm::kCcSet ? "s" : "";
+  }
+
   arm::Register GetPCRegister() OVERRIDE {
     return arm::R15;
   }
@@ -369,12 +383,12 @@
 
       size_t cond_index = after_cond.find(COND_TOKEN);
       if (cond_index != std::string::npos) {
-        after_cond.replace(cond_index, ConstexprStrLen(IMM1_TOKEN), GetConditionString(c));
+        after_cond.replace(cond_index, ConstexprStrLen(COND_TOKEN), GetConditionString(c));
       }
 
       cond_index = after_cond_filter.find(COND_TOKEN);
       if (cond_index != std::string::npos) {
-        after_cond_filter.replace(cond_index, ConstexprStrLen(IMM1_TOKEN), GetConditionString(c));
+        after_cond_filter.replace(cond_index, ConstexprStrLen(COND_TOKEN), GetConditionString(c));
       }
       if (EvalFilterString(after_cond_filter)) {
         continue;
@@ -384,6 +398,30 @@
     }
   }
 
+  void TemplateHelper(std::function<void(arm::SetCc)> f, int depth ATTRIBUTE_UNUSED,
+                      bool without_pc ATTRIBUTE_UNUSED, std::string fmt, std::string filter,
+                      std::ostringstream& oss) {
+    for (arm::SetCc s : GetSetCcs()) {
+      std::string after_cond = fmt;
+      std::string after_cond_filter = filter;
+
+      size_t cond_index = after_cond.find(SET_CC_TOKEN);
+      if (cond_index != std::string::npos) {
+        after_cond.replace(cond_index, ConstexprStrLen(SET_CC_TOKEN), GetSetCcString(s));
+      }
+
+      cond_index = after_cond_filter.find(SET_CC_TOKEN);
+      if (cond_index != std::string::npos) {
+        after_cond_filter.replace(cond_index, ConstexprStrLen(SET_CC_TOKEN), GetSetCcString(s));
+      }
+      if (EvalFilterString(after_cond_filter)) {
+        continue;
+      }
+
+      ExecuteAndPrint([&] () { f(s); }, after_cond, oss);
+    }
+  }
+
   template <typename... Args>
   void TemplateHelper(std::function<void(arm::Register, Args...)> f, int depth, bool without_pc,
                       std::string fmt, std::string filter, std::ostringstream& oss) {
@@ -449,12 +487,12 @@
 
       size_t cond_index = after_cond.find(COND_TOKEN);
       if (cond_index != std::string::npos) {
-        after_cond.replace(cond_index, ConstexprStrLen(IMM1_TOKEN), GetConditionString(c));
+        after_cond.replace(cond_index, ConstexprStrLen(COND_TOKEN), GetConditionString(c));
       }
 
       cond_index = after_cond_filter.find(COND_TOKEN);
       if (cond_index != std::string::npos) {
-        after_cond_filter.replace(cond_index, ConstexprStrLen(IMM1_TOKEN), GetConditionString(c));
+        after_cond_filter.replace(cond_index, ConstexprStrLen(COND_TOKEN), GetConditionString(c));
       }
       if (EvalFilterString(after_cond_filter)) {
         continue;
@@ -466,25 +504,51 @@
     }
   }
 
-  template <typename T1, typename T2>
-  std::function<void(T1, T2)> GetBoundFunction2(void (arm::Arm32Assembler::*f)(T1, T2)) {
+  template <typename... Args>
+  void TemplateHelper(std::function<void(arm::SetCc, Args...)> f, int depth, bool without_pc,
+                      std::string fmt, std::string filter, std::ostringstream& oss) {
+    for (arm::SetCc s : GetSetCcs()) {
+      std::string after_cond = fmt;
+      std::string after_cond_filter = filter;
+
+      size_t cond_index = after_cond.find(SET_CC_TOKEN);
+      if (cond_index != std::string::npos) {
+        after_cond.replace(cond_index, ConstexprStrLen(SET_CC_TOKEN), GetSetCcString(s));
+      }
+
+      cond_index = after_cond_filter.find(SET_CC_TOKEN);
+      if (cond_index != std::string::npos) {
+        after_cond_filter.replace(cond_index, ConstexprStrLen(SET_CC_TOKEN), GetSetCcString(s));
+      }
+      if (EvalFilterString(after_cond_filter)) {
+        continue;
+      }
+
+      auto lambda = [&] (Args... args) { f(s, args...); };  // NOLINT [readability/braces] [4]
+      TemplateHelper(std::function<void(Args...)>(lambda), depth, without_pc,
+          after_cond, after_cond_filter, oss);
+    }
+  }
+
+  template <typename Assembler, typename T1, typename T2>
+  std::function<void(T1, T2)> GetBoundFunction2(void (Assembler::*f)(T1, T2)) {
     return std::bind(f, GetAssembler(), _1, _2);
   }
 
-  template <typename T1, typename T2, typename T3>
-  std::function<void(T1, T2, T3)> GetBoundFunction3(void (arm::Arm32Assembler::*f)(T1, T2, T3)) {
+  template <typename Assembler, typename T1, typename T2, typename T3>
+  std::function<void(T1, T2, T3)> GetBoundFunction3(void (Assembler::*f)(T1, T2, T3)) {
     return std::bind(f, GetAssembler(), _1, _2, _3);
   }
 
-  template <typename T1, typename T2, typename T3, typename T4>
+  template <typename Assembler, typename T1, typename T2, typename T3, typename T4>
   std::function<void(T1, T2, T3, T4)> GetBoundFunction4(
-      void (arm::Arm32Assembler::*f)(T1, T2, T3, T4)) {
+      void (Assembler::*f)(T1, T2, T3, T4)) {
     return std::bind(f, GetAssembler(), _1, _2, _3, _4);
   }
 
-  template <typename T1, typename T2, typename T3, typename T4, typename T5>
+  template <typename Assembler, typename T1, typename T2, typename T3, typename T4, typename T5>
   std::function<void(T1, T2, T3, T4, T5)> GetBoundFunction5(
-      void (arm::Arm32Assembler::*f)(T1, T2, T3, T4, T5)) {
+      void (Assembler::*f)(T1, T2, T3, T4, T5)) {
     return std::bind(f, GetAssembler(), _1, _2, _3, _4, _5);
   }
 
@@ -503,26 +567,26 @@
     DriverStr(oss.str(), test_name);
   }
 
-  template <typename... Args>
-  void T2Helper(void (arm::Arm32Assembler::*f)(Args...), bool without_pc, std::string fmt,
+  template <typename Assembler, typename... Args>
+  void T2Helper(void (Assembler::*f)(Args...), bool without_pc, std::string fmt,
                 std::string test_name, std::string filter = "") {
     GenericTemplateHelper(GetBoundFunction2(f), without_pc, fmt, test_name, filter);
   }
 
-  template <typename... Args>
-  void T3Helper(void (arm::Arm32Assembler::*f)(Args...), bool without_pc, std::string fmt,
+  template <typename Assembler, typename... Args>
+  void T3Helper(void (Assembler::*f)(Args...), bool without_pc, std::string fmt,
       std::string test_name, std::string filter = "") {
     GenericTemplateHelper(GetBoundFunction3(f), without_pc, fmt, test_name, filter);
   }
 
-  template <typename... Args>
-  void T4Helper(void (arm::Arm32Assembler::*f)(Args...), bool without_pc, std::string fmt,
+  template <typename Assembler, typename... Args>
+  void T4Helper(void (Assembler::*f)(Args...), bool without_pc, std::string fmt,
       std::string test_name, std::string filter = "") {
     GenericTemplateHelper(GetBoundFunction4(f), without_pc, fmt, test_name, filter);
   }
 
-  template <typename... Args>
-  void T5Helper(void (arm::Arm32Assembler::*f)(Args...), bool without_pc, std::string fmt,
+  template <typename Assembler, typename... Args>
+  void T5Helper(void (Assembler::*f)(Args...), bool without_pc, std::string fmt,
       std::string test_name, std::string filter = "") {
     GenericTemplateHelper(GetBoundFunction5(f), without_pc, fmt, test_name, filter);
   }
@@ -573,6 +637,7 @@
 
   std::vector<arm::Register*> registers_;
   std::vector<arm::Condition> conditions_;
+  std::vector<arm::SetCc> set_ccs_;
   std::vector<arm::ShifterOperand> shifter_operands_;
 };
 
@@ -656,15 +721,23 @@
 }
 
 TEST_F(AssemblerArm32Test, And) {
-  T4Helper(&arm::Arm32Assembler::and_, true, "and{cond} {reg1}, {reg2}, {shift}", "and");
+  T5Helper(&arm::Arm32Assembler::and_, true, "and{cond}{s} {reg1}, {reg2}, {shift}", "and");
+}
+
+TEST_F(AssemblerArm32Test, Ands) {
+  T4Helper(&arm::Arm32Assembler::ands, true, "and{cond}s {reg1}, {reg2}, {shift}", "ands");
 }
 
 TEST_F(AssemblerArm32Test, Eor) {
-  T4Helper(&arm::Arm32Assembler::eor, true, "eor{cond} {reg1}, {reg2}, {shift}", "eor");
+  T5Helper(&arm::Arm32Assembler::eor, true, "eor{cond}{s} {reg1}, {reg2}, {shift}", "eor");
+}
+
+TEST_F(AssemblerArm32Test, Eors) {
+  T4Helper(&arm::Arm32Assembler::eors, true, "eor{cond}s {reg1}, {reg2}, {shift}", "eors");
 }
 
 TEST_F(AssemblerArm32Test, Orr) {
-  T4Helper(&arm::Arm32Assembler::orr, true, "orr{cond} {reg1}, {reg2}, {shift}", "orr");
+  T5Helper(&arm::Arm32Assembler::orr, true, "orr{cond}{s} {reg1}, {reg2}, {shift}", "orr");
 }
 
 TEST_F(AssemblerArm32Test, Orrs) {
@@ -672,11 +745,15 @@
 }
 
 TEST_F(AssemblerArm32Test, Bic) {
-  T4Helper(&arm::Arm32Assembler::bic, true, "bic{cond} {reg1}, {reg2}, {shift}", "bic");
+  T5Helper(&arm::Arm32Assembler::bic, true, "bic{cond}{s} {reg1}, {reg2}, {shift}", "bic");
+}
+
+TEST_F(AssemblerArm32Test, Bics) {
+  T4Helper(&arm::Arm32Assembler::bics, true, "bic{cond}s {reg1}, {reg2}, {shift}", "bics");
 }
 
 TEST_F(AssemblerArm32Test, Mov) {
-  T3Helper(&arm::Arm32Assembler::mov, true, "mov{cond} {reg1}, {shift}", "mov");
+  T4Helper(&arm::Arm32Assembler::mov, true, "mov{cond}{s} {reg1}, {shift}", "mov");
 }
 
 TEST_F(AssemblerArm32Test, Movs) {
@@ -684,7 +761,7 @@
 }
 
 TEST_F(AssemblerArm32Test, Mvn) {
-  T3Helper(&arm::Arm32Assembler::mvn, true, "mvn{cond} {reg1}, {shift}", "mvn");
+  T4Helper(&arm::Arm32Assembler::mvn, true, "mvn{cond}{s} {reg1}, {shift}", "mvn");
 }
 
 TEST_F(AssemblerArm32Test, Mvns) {
@@ -692,7 +769,7 @@
 }
 
 TEST_F(AssemblerArm32Test, Add) {
-  T4Helper(&arm::Arm32Assembler::add, false, "add{cond} {reg1}, {reg2}, {shift}", "add");
+  T5Helper(&arm::Arm32Assembler::add, false, "add{cond}{s} {reg1}, {reg2}, {shift}", "add");
 }
 
 TEST_F(AssemblerArm32Test, Adds) {
@@ -700,11 +777,15 @@
 }
 
 TEST_F(AssemblerArm32Test, Adc) {
-  T4Helper(&arm::Arm32Assembler::adc, false, "adc{cond} {reg1}, {reg2}, {shift}", "adc");
+  T5Helper(&arm::Arm32Assembler::adc, false, "adc{cond}{s} {reg1}, {reg2}, {shift}", "adc");
+}
+
+TEST_F(AssemblerArm32Test, Adcs) {
+  T4Helper(&arm::Arm32Assembler::adcs, false, "adc{cond}s {reg1}, {reg2}, {shift}", "adcs");
 }
 
 TEST_F(AssemblerArm32Test, Sub) {
-  T4Helper(&arm::Arm32Assembler::sub, false, "sub{cond} {reg1}, {reg2}, {shift}", "sub");
+  T5Helper(&arm::Arm32Assembler::sub, false, "sub{cond}{s} {reg1}, {reg2}, {shift}", "sub");
 }
 
 TEST_F(AssemblerArm32Test, Subs) {
@@ -712,11 +793,15 @@
 }
 
 TEST_F(AssemblerArm32Test, Sbc) {
-  T4Helper(&arm::Arm32Assembler::sbc, false, "sbc{cond} {reg1}, {reg2}, {shift}", "sbc");
+  T5Helper(&arm::Arm32Assembler::sbc, false, "sbc{cond}{s} {reg1}, {reg2}, {shift}", "sbc");
+}
+
+TEST_F(AssemblerArm32Test, Sbcs) {
+  T4Helper(&arm::Arm32Assembler::sbcs, false, "sbc{cond}s {reg1}, {reg2}, {shift}", "sbcs");
 }
 
 TEST_F(AssemblerArm32Test, Rsb) {
-  T4Helper(&arm::Arm32Assembler::rsb, true, "rsb{cond} {reg1}, {reg2}, {shift}", "rsb");
+  T5Helper(&arm::Arm32Assembler::rsb, true, "rsb{cond}{s} {reg1}, {reg2}, {shift}", "rsb");
 }
 
 TEST_F(AssemblerArm32Test, Rsbs) {
@@ -724,7 +809,11 @@
 }
 
 TEST_F(AssemblerArm32Test, Rsc) {
-  T4Helper(&arm::Arm32Assembler::rsc, true, "rsc{cond} {reg1}, {reg2}, {shift}", "rsc");
+  T5Helper(&arm::Arm32Assembler::rsc, true, "rsc{cond}{s} {reg1}, {reg2}, {shift}", "rsc");
+}
+
+TEST_F(AssemblerArm32Test, Rscs) {
+  T4Helper(&arm::Arm32Assembler::rscs, false, "rsc{cond}s {reg1}, {reg2}, {shift}", "rscs");
 }
 
 /* TODO: Need better filter support.
diff --git a/compiler/utils/arm/assembler_arm_test.h b/compiler/utils/arm/assembler_arm_test.h
index 838abb6..a85a05e 100644
--- a/compiler/utils/arm/assembler_arm_test.h
+++ b/compiler/utils/arm/assembler_arm_test.h
@@ -21,7 +21,13 @@
 
 namespace art {
 
-template<typename Ass, typename Reg, typename FPReg, typename Imm, typename SOp, typename Cond>
+template<typename Ass,
+         typename Reg,
+         typename FPReg,
+         typename Imm,
+         typename SOp,
+         typename Cond,
+         typename SetCc>
 class AssemblerArmTest : public AssemblerTest<Ass, Reg, FPReg, Imm> {
  public:
   typedef AssemblerTest<Ass, Reg, FPReg, Imm> Base;
@@ -94,7 +100,7 @@
 
       size_t cond_index = after_cond.find(COND_TOKEN);
       if (cond_index != std::string::npos) {
-        after_cond.replace(cond_index, ConstexprStrLen(IMM1_TOKEN), GetConditionString(c));
+        after_cond.replace(cond_index, ConstexprStrLen(COND_TOKEN), GetConditionString(c));
       }
 
       for (Imm i : immediates1) {
@@ -185,7 +191,7 @@
 
       size_t cond_index = after_cond.find(COND_TOKEN);
       if (cond_index != std::string::npos) {
-        after_cond.replace(cond_index, ConstexprStrLen(IMM1_TOKEN), GetConditionString(c));
+        after_cond.replace(cond_index, ConstexprStrLen(COND_TOKEN), GetConditionString(c));
       }
 
       for (std::pair<Imm, Imm>& pair : immediates) {
@@ -271,7 +277,7 @@
 
       size_t cond_index = after_cond.find(COND_TOKEN);
       if (cond_index != std::string::npos) {
-        after_cond.replace(cond_index, ConstexprStrLen(IMM1_TOKEN), GetConditionString(c));
+        after_cond.replace(cond_index, ConstexprStrLen(COND_TOKEN), GetConditionString(c));
       }
 
       for (auto reg1 : reg1_registers) {
@@ -337,7 +343,7 @@
 
       size_t cond_index = after_cond.find(COND_TOKEN);
       if (cond_index != std::string::npos) {
-        after_cond.replace(cond_index, ConstexprStrLen(IMM1_TOKEN), GetConditionString(c));
+        after_cond.replace(cond_index, ConstexprStrLen(COND_TOKEN), GetConditionString(c));
       }
 
       for (auto reg1 : reg1_registers) {
@@ -401,7 +407,7 @@
 
       size_t cond_index = after_cond.find(COND_TOKEN);
       if (cond_index != std::string::npos) {
-        after_cond.replace(cond_index, ConstexprStrLen(IMM1_TOKEN), GetConditionString(c));
+        after_cond.replace(cond_index, ConstexprStrLen(COND_TOKEN), GetConditionString(c));
       }
 
       for (const SOp& shift : shifts) {
@@ -457,7 +463,7 @@
 
       size_t cond_index = after_cond.find(COND_TOKEN);
       if (cond_index != std::string::npos) {
-        after_cond.replace(cond_index, ConstexprStrLen(IMM1_TOKEN), GetConditionString(c));
+        after_cond.replace(cond_index, ConstexprStrLen(COND_TOKEN), GetConditionString(c));
       }
 
       for (const SOp& shift : shifts) {
@@ -511,6 +517,9 @@
   virtual std::vector<Cond>& GetConditions() = 0;
   virtual std::string GetConditionString(Cond c) = 0;
 
+  virtual std::vector<SetCc>& GetSetCcs() = 0;
+  virtual std::string GetSetCcString(SetCc s) = 0;
+
   virtual std::vector<SOp>& GetShiftOperands() = 0;
   virtual std::string GetShiftString(SOp sop) = 0;
 
@@ -534,6 +543,7 @@
   static constexpr const char* REG3_TOKEN = "{reg3}";
   static constexpr const char* REG4_TOKEN = "{reg4}";
   static constexpr const char* COND_TOKEN = "{cond}";
+  static constexpr const char* SET_CC_TOKEN = "{s}";
   static constexpr const char* SHIFT_TOKEN = "{shift}";
 
  private:
diff --git a/compiler/utils/arm/assembler_thumb2.cc b/compiler/utils/arm/assembler_thumb2.cc
index 4e918e9..90ed10c 100644
--- a/compiler/utils/arm/assembler_thumb2.cc
+++ b/compiler/utils/arm/assembler_thumb2.cc
@@ -417,128 +417,96 @@
 }
 
 void Thumb2Assembler::and_(Register rd, Register rn, const ShifterOperand& so,
-                           Condition cond) {
-  EmitDataProcessing(cond, AND, 0, rn, rd, so);
+                           Condition cond, SetCc set_cc) {
+  EmitDataProcessing(cond, AND, set_cc, rn, rd, so);
 }
 
 
 void Thumb2Assembler::eor(Register rd, Register rn, const ShifterOperand& so,
-                          Condition cond) {
-  EmitDataProcessing(cond, EOR, 0, rn, rd, so);
+                          Condition cond, SetCc set_cc) {
+  EmitDataProcessing(cond, EOR, set_cc, rn, rd, so);
 }
 
 
 void Thumb2Assembler::sub(Register rd, Register rn, const ShifterOperand& so,
-                          Condition cond) {
-  EmitDataProcessing(cond, SUB, 0, rn, rd, so);
+                          Condition cond, SetCc set_cc) {
+  EmitDataProcessing(cond, SUB, set_cc, rn, rd, so);
 }
 
 
 void Thumb2Assembler::rsb(Register rd, Register rn, const ShifterOperand& so,
-                          Condition cond) {
-  EmitDataProcessing(cond, RSB, 0, rn, rd, so);
-}
-
-
-void Thumb2Assembler::rsbs(Register rd, Register rn, const ShifterOperand& so,
-                           Condition cond) {
-  EmitDataProcessing(cond, RSB, 1, rn, rd, so);
+                          Condition cond, SetCc set_cc) {
+  EmitDataProcessing(cond, RSB, set_cc, rn, rd, so);
 }
 
 
 void Thumb2Assembler::add(Register rd, Register rn, const ShifterOperand& so,
-                          Condition cond) {
-  EmitDataProcessing(cond, ADD, 0, rn, rd, so);
-}
-
-
-void Thumb2Assembler::adds(Register rd, Register rn, const ShifterOperand& so,
-                           Condition cond) {
-  EmitDataProcessing(cond, ADD, 1, rn, rd, so);
-}
-
-
-void Thumb2Assembler::subs(Register rd, Register rn, const ShifterOperand& so,
-                           Condition cond) {
-  EmitDataProcessing(cond, SUB, 1, rn, rd, so);
+                          Condition cond, SetCc set_cc) {
+  EmitDataProcessing(cond, ADD, set_cc, rn, rd, so);
 }
 
 
 void Thumb2Assembler::adc(Register rd, Register rn, const ShifterOperand& so,
-                          Condition cond) {
-  EmitDataProcessing(cond, ADC, 0, rn, rd, so);
+                          Condition cond, SetCc set_cc) {
+  EmitDataProcessing(cond, ADC, set_cc, rn, rd, so);
 }
 
 
 void Thumb2Assembler::sbc(Register rd, Register rn, const ShifterOperand& so,
-                          Condition cond) {
-  EmitDataProcessing(cond, SBC, 0, rn, rd, so);
+                          Condition cond, SetCc set_cc) {
+  EmitDataProcessing(cond, SBC, set_cc, rn, rd, so);
 }
 
 
 void Thumb2Assembler::rsc(Register rd, Register rn, const ShifterOperand& so,
-                          Condition cond) {
-  EmitDataProcessing(cond, RSC, 0, rn, rd, so);
+                          Condition cond, SetCc set_cc) {
+  EmitDataProcessing(cond, RSC, set_cc, rn, rd, so);
 }
 
 
 void Thumb2Assembler::tst(Register rn, const ShifterOperand& so, Condition cond) {
   CHECK_NE(rn, PC);  // Reserve tst pc instruction for exception handler marker.
-  EmitDataProcessing(cond, TST, 1, rn, R0, so);
+  EmitDataProcessing(cond, TST, kCcSet, rn, R0, so);
 }
 
 
 void Thumb2Assembler::teq(Register rn, const ShifterOperand& so, Condition cond) {
   CHECK_NE(rn, PC);  // Reserve teq pc instruction for exception handler marker.
-  EmitDataProcessing(cond, TEQ, 1, rn, R0, so);
+  EmitDataProcessing(cond, TEQ, kCcSet, rn, R0, so);
 }
 
 
 void Thumb2Assembler::cmp(Register rn, const ShifterOperand& so, Condition cond) {
-  EmitDataProcessing(cond, CMP, 1, rn, R0, so);
+  EmitDataProcessing(cond, CMP, kCcSet, rn, R0, so);
 }
 
 
 void Thumb2Assembler::cmn(Register rn, const ShifterOperand& so, Condition cond) {
-  EmitDataProcessing(cond, CMN, 1, rn, R0, so);
+  EmitDataProcessing(cond, CMN, kCcSet, rn, R0, so);
 }
 
 
-void Thumb2Assembler::orr(Register rd, Register rn,
-                          const ShifterOperand& so, Condition cond) {
-  EmitDataProcessing(cond, ORR, 0, rn, rd, so);
+void Thumb2Assembler::orr(Register rd, Register rn, const ShifterOperand& so,
+                          Condition cond, SetCc set_cc) {
+  EmitDataProcessing(cond, ORR, set_cc, rn, rd, so);
 }
 
 
-void Thumb2Assembler::orrs(Register rd, Register rn,
-                           const ShifterOperand& so, Condition cond) {
-  EmitDataProcessing(cond, ORR, 1, rn, rd, so);
-}
-
-
-void Thumb2Assembler::mov(Register rd, const ShifterOperand& so, Condition cond) {
-  EmitDataProcessing(cond, MOV, 0, R0, rd, so);
-}
-
-
-void Thumb2Assembler::movs(Register rd, const ShifterOperand& so, Condition cond) {
-  EmitDataProcessing(cond, MOV, 1, R0, rd, so);
+void Thumb2Assembler::mov(Register rd, const ShifterOperand& so,
+                          Condition cond, SetCc set_cc) {
+  EmitDataProcessing(cond, MOV, set_cc, R0, rd, so);
 }
 
 
 void Thumb2Assembler::bic(Register rd, Register rn, const ShifterOperand& so,
-                       Condition cond) {
-  EmitDataProcessing(cond, BIC, 0, rn, rd, so);
+                          Condition cond, SetCc set_cc) {
+  EmitDataProcessing(cond, BIC, set_cc, rn, rd, so);
 }
 
 
-void Thumb2Assembler::mvn(Register rd, const ShifterOperand& so, Condition cond) {
-  EmitDataProcessing(cond, MVN, 0, R0, rd, so);
-}
-
-
-void Thumb2Assembler::mvns(Register rd, const ShifterOperand& so, Condition cond) {
-  EmitDataProcessing(cond, MVN, 1, R0, rd, so);
+void Thumb2Assembler::mvn(Register rd, const ShifterOperand& so,
+                          Condition cond, SetCc set_cc) {
+  EmitDataProcessing(cond, MVN, set_cc, R0, rd, so);
 }
 
 
@@ -1054,7 +1022,7 @@
 
 
 void Thumb2Assembler::MarkExceptionHandler(Label* label) {
-  EmitDataProcessing(AL, TST, 1, PC, R0, ShifterOperand(0));
+  EmitDataProcessing(AL, TST, kCcSet, PC, R0, ShifterOperand(0));
   Label l;
   b(&l);
   EmitBranch(AL, label, false, false);
@@ -1075,9 +1043,9 @@
 }
 
 
-bool Thumb2Assembler::Is32BitDataProcessing(Condition cond ATTRIBUTE_UNUSED,
+bool Thumb2Assembler::Is32BitDataProcessing(Condition cond,
                                             Opcode opcode,
-                                            bool set_cc,
+                                            SetCc set_cc,
                                             Register rn,
                                             Register rd,
                                             const ShifterOperand& so) {
@@ -1086,7 +1054,7 @@
   }
 
   // Check special case for SP relative ADD and SUB immediate.
-  if ((opcode == ADD || opcode == SUB) && rn == SP && so.IsImmediate()) {
+  if ((opcode == ADD || opcode == SUB) && rn == SP && so.IsImmediate() && set_cc != kCcSet) {
     // If the immediate is in range, use 16 bit.
     if (rd == SP) {
       if (so.GetImmediate() < (1 << 9)) {    // 9 bit immediate.
@@ -1099,8 +1067,10 @@
     }
   }
 
-  bool can_contain_high_register = (opcode == MOV)
-      || ((opcode == ADD) && (rn == rd) && !set_cc);
+  bool can_contain_high_register =
+      (opcode == CMP) ||
+      (opcode == MOV && set_cc != kCcSet) ||
+      ((opcode == ADD) && (rn == rd) && set_cc != kCcSet);
 
   if (IsHighRegister(rd) || IsHighRegister(rn)) {
     if (!can_contain_high_register) {
@@ -1146,39 +1116,80 @@
   }
 
   if (so.IsImmediate()) {
-    if (rn_is_valid && rn != rd) {
-      // The only thumb1 instruction with a register and an immediate are ADD and SUB.  The
-      // immediate must be 3 bits.
-      if (opcode != ADD && opcode != SUB) {
+    if (opcode == RSB) {
+      DCHECK(rn_is_valid);
+      if (so.GetImmediate() != 0u) {
         return true;
-      } else {
-        // Check that the immediate is 3 bits for ADD and SUB.
-        if (so.GetImmediate() >= 8) {
+      }
+    } else if (rn_is_valid && rn != rd) {
+      // The only thumb1 instructions with a register and an immediate are ADD and SUB
+      // with a 3-bit immediate, and RSB with zero immediate.
+      if (opcode == ADD || opcode == SUB) {
+        if (!IsUint<3>(so.GetImmediate())) {
           return true;
         }
+      } else {
+        return true;
       }
     } else {
       // ADD, SUB, CMP and MOV may be thumb1 only if the immediate is 8 bits.
       if (!(opcode == ADD || opcode == SUB || opcode == MOV || opcode == CMP)) {
         return true;
       } else {
-        if (so.GetImmediate() > 255) {
+        if (!IsUint<8>(so.GetImmediate())) {
           return true;
         }
       }
     }
-  }
-
-  // Check for register shift operand.
-  if (so.IsRegister() && so.IsShift()) {
-    if (opcode != MOV) {
-      return true;
-    }
-    // Check for MOV with an ROR.
-    if (so.GetShift() == ROR) {
-      if (so.GetImmediate() != 0) {
+  } else {
+    DCHECK(so.IsRegister());
+    if (so.IsShift()) {
+      // Shift operand - check if it is a MOV convertible to a 16-bit shift instruction.
+      if (opcode != MOV) {
         return true;
       }
+      // Check for MOV with an ROR/RRX. There is no 16-bit ROR immediate and no 16-bit RRX.
+      if (so.GetShift() == ROR || so.GetShift() == RRX) {
+        return true;
+      }
+      // 16-bit shifts set condition codes if and only if outside IT block,
+      // i.e. if and only if cond == AL.
+      if ((cond == AL) ? set_cc == kCcKeep : set_cc == kCcSet) {
+        return true;
+      }
+    } else {
+      // Register operand without shift.
+      switch (opcode) {
+        case ADD:
+          // The 16-bit ADD that cannot contain high registers can set condition codes
+          // if and only if outside IT block, i.e. if and only if cond == AL.
+          if (!can_contain_high_register &&
+              ((cond == AL) ? set_cc == kCcKeep : set_cc == kCcSet)) {
+            return true;
+          }
+          break;
+        case AND:
+        case BIC:
+        case EOR:
+        case ORR:
+        case MVN:
+        case ADC:
+        case SUB:
+        case SBC:
+          // These 16-bit opcodes set condition codes if and only if outside IT block,
+          // i.e. if and only if cond == AL.
+          if ((cond == AL) ? set_cc == kCcKeep : set_cc == kCcSet) {
+            return true;
+          }
+          break;
+        case RSB:
+        case RSC:
+          // No 16-bit RSB/RSC Rd, Rm, Rn. It would be equivalent to SUB/SBC Rd, Rn, Rm.
+          return true;
+        case CMP:
+        default:
+          break;
+      }
     }
   }
 
@@ -1189,7 +1200,7 @@
 
 void Thumb2Assembler::Emit32BitDataProcessing(Condition cond ATTRIBUTE_UNUSED,
                                               Opcode opcode,
-                                              bool set_cc,
+                                              SetCc set_cc,
                                               Register rn,
                                               Register rd,
                                               const ShifterOperand& so) {
@@ -1203,10 +1214,10 @@
     case ADC: thumb_opcode = 10U /* 0b1010 */; break;
     case SBC: thumb_opcode = 11U /* 0b1011 */; break;
     case RSC: break;
-    case TST: thumb_opcode =  0U /* 0b0000 */; set_cc = true; rd = PC; break;
-    case TEQ: thumb_opcode =  4U /* 0b0100 */; set_cc = true; rd = PC; break;
-    case CMP: thumb_opcode = 13U /* 0b1101 */; set_cc = true; rd = PC; break;
-    case CMN: thumb_opcode =  8U /* 0b1000 */; set_cc = true; rd = PC; break;
+    case TST: thumb_opcode =  0U /* 0b0000 */; DCHECK(set_cc == kCcSet); rd = PC; break;
+    case TEQ: thumb_opcode =  4U /* 0b0100 */; DCHECK(set_cc == kCcSet); rd = PC; break;
+    case CMP: thumb_opcode = 13U /* 0b1101 */; DCHECK(set_cc == kCcSet); rd = PC; break;
+    case CMN: thumb_opcode =  8U /* 0b1000 */; DCHECK(set_cc == kCcSet); rd = PC; break;
     case ORR: thumb_opcode =  2U /* 0b0010 */; break;
     case MOV: thumb_opcode =  2U /* 0b0010 */; rn = PC; break;
     case BIC: thumb_opcode =  1U /* 0b0001 */; break;
@@ -1224,7 +1235,7 @@
   if (so.IsImmediate()) {
     // Check special cases.
     if ((opcode == SUB || opcode == ADD) && (so.GetImmediate() < (1u << 12))) {
-      if (!set_cc) {
+      if (set_cc != kCcSet) {
         if (opcode == SUB) {
           thumb_opcode = 5U;
         } else if (opcode == ADD) {
@@ -1238,7 +1249,7 @@
       uint32_t imm8 = imm & 0xff;
 
       encoding = B31 | B30 | B29 | B28 |
-          (set_cc ? B20 : B25) |
+          (set_cc == kCcSet ? B20 : B25) |
           thumb_opcode << 21 |
           rn << 16 |
           rd << 8 |
@@ -1254,7 +1265,7 @@
       }
       encoding = B31 | B30 | B29 | B28 |
           thumb_opcode << 21 |
-          (set_cc ? B20 : 0) |
+          (set_cc == kCcSet ? B20 : 0) |
           rn << 16 |
           rd << 8 |
           imm;
@@ -1263,7 +1274,7 @@
     // Register (possibly shifted)
     encoding = B31 | B30 | B29 | B27 | B25 |
         thumb_opcode << 21 |
-        (set_cc ? B20 : 0) |
+        (set_cc == kCcSet ? B20 : 0) |
         rn << 16 |
         rd << 8 |
         so.encodingThumb();
@@ -1274,7 +1285,7 @@
 
 void Thumb2Assembler::Emit16BitDataProcessing(Condition cond,
                                               Opcode opcode,
-                                              bool set_cc,
+                                              SetCc set_cc,
                                               Register rn,
                                               Register rd,
                                               const ShifterOperand& so) {
@@ -1304,19 +1315,25 @@
     rn = so.GetRegister();
 
     switch (so.GetShift()) {
-    case LSL: thumb_opcode = 0U /* 0b00 */; break;
-    case LSR: thumb_opcode = 1U /* 0b01 */; break;
-    case ASR: thumb_opcode = 2U /* 0b10 */; break;
-    case ROR:
-      // ROR doesn't allow immediates.
-      thumb_opcode = 7U /* 0b111 */;
-      dp_opcode = 1U /* 0b01 */;
-      opcode_shift = 6;
-      use_immediate = false;
+    case LSL:
+      DCHECK_LE(immediate, 31u);
+      thumb_opcode = 0U /* 0b00 */;
       break;
-    case RRX: break;
+    case LSR:
+      DCHECK(1 <= immediate && immediate <= 32);
+      immediate &= 31;  // 32 is encoded as 0.
+      thumb_opcode = 1U /* 0b01 */;
+      break;
+    case ASR:
+      DCHECK(1 <= immediate && immediate <= 32);
+      immediate &= 31;  // 32 is encoded as 0.
+      thumb_opcode = 2U /* 0b10 */;
+      break;
+    case ROR:  // No 16-bit ROR immediate.
+    case RRX:  // No 16-bit RRX.
     default:
-     break;
+      LOG(FATAL) << "Unexpected shift: " << so.GetShift();
+      UNREACHABLE();
     }
   } else {
     if (so.IsImmediate()) {
@@ -1334,6 +1351,9 @@
         case ADC:
         case SBC:
         case BIC: {
+          // Sets condition codes if and only if outside IT block,
+          // check that it complies with set_cc.
+          DCHECK((cond == AL) ? set_cc != kCcKeep : set_cc != kCcSet);
           if (rn == rd) {
             rn = so.GetRegister();
           } else {
@@ -1348,9 +1368,17 @@
           rn = so.GetRegister();
           break;
         }
-        case TST:
-        case TEQ:
         case MVN: {
+          // Sets condition codes if and only if outside IT block,
+          // check that it complies with set_cc.
+          DCHECK((cond == AL) ? set_cc != kCcKeep : set_cc != kCcSet);
+          CHECK_EQ(rn, 0);
+          rn = so.GetRegister();
+          break;
+        }
+        case TST:
+        case TEQ: {
+          DCHECK(set_cc == kCcSet);
           CHECK_EQ(rn, 0);
           rn = so.GetRegister();
           break;
@@ -1371,6 +1399,7 @@
       case TST: thumb_opcode = 8U /* 0b1000 */; CHECK(!use_immediate); break;
       case MVN: thumb_opcode = 15U /* 0b1111 */; CHECK(!use_immediate); break;
       case CMP: {
+        DCHECK(set_cc == kCcSet);
         if (use_immediate) {
           // T2 encoding.
           dp_opcode = 0;
@@ -1378,6 +1407,13 @@
           thumb_opcode = 5U /* 0b101 */;
           rd_shift = 8;
           rn_shift = 8;
+        } else if (IsHighRegister(rd) || IsHighRegister(rn)) {
+          // Special cmp for high registers.
+          dp_opcode = 1U /* 0b01 */;
+          opcode_shift = 7;
+          // Put the top bit of rd into the bottom bit of the opcode.
+          thumb_opcode = 10U /* 0b0001010 */ | static_cast<uint32_t>(rd) >> 3;
+          rd = static_cast<Register>(static_cast<uint32_t>(rd) & 7U /* 0b111 */);
         } else {
           thumb_opcode = 10U /* 0b1010 */;
         }
@@ -1399,7 +1435,7 @@
           rn_shift = 8;
         } else {
           rn = so.GetRegister();
-          if (IsHighRegister(rn) || IsHighRegister(rd)) {
+          if (set_cc != kCcSet) {
             // Special mov for high registers.
             dp_opcode = 1U /* 0b01 */;
             opcode_shift = 7;
@@ -1407,6 +1443,8 @@
             thumb_opcode = 12U /* 0b0001100 */ | static_cast<uint32_t>(rd) >> 3;
             rd = static_cast<Register>(static_cast<uint32_t>(rd) & 7U /* 0b111 */);
           } else {
+            DCHECK(!IsHighRegister(rn));
+            DCHECK(!IsHighRegister(rd));
             thumb_opcode = 0;
           }
         }
@@ -1436,9 +1474,9 @@
 
 
 // ADD and SUB are complex enough to warrant their own emitter.
-void Thumb2Assembler::Emit16BitAddSub(Condition cond ATTRIBUTE_UNUSED,
+void Thumb2Assembler::Emit16BitAddSub(Condition cond,
                                       Opcode opcode,
-                                      bool set_cc,
+                                      SetCc set_cc,
                                       Register rn,
                                       Register rd,
                                       const ShifterOperand& so) {
@@ -1449,7 +1487,7 @@
   uint8_t immediate_shift = 0;
   bool use_immediate = false;
   uint32_t immediate = 0;  // Should be at most 9 bits but keep the full immediate for CHECKs.
-  uint8_t thumb_opcode;;
+  uint8_t thumb_opcode;
 
   if (so.IsImmediate()) {
     use_immediate = true;
@@ -1460,7 +1498,7 @@
     case ADD:
       if (so.IsRegister()) {
         Register rm = so.GetRegister();
-        if (rn == rd && !set_cc) {
+        if (rn == rd && set_cc != kCcSet) {
           // Can use T2 encoding (allows 4 bit registers)
           dp_opcode = 1U /* 0b01 */;
           opcode_shift = 10;
@@ -1471,6 +1509,12 @@
           rd = static_cast<Register>(static_cast<uint32_t>(rd) & 7U /* 0b111 */);
         } else {
           // T1.
+          DCHECK(!IsHighRegister(rd));
+          DCHECK(!IsHighRegister(rn));
+          DCHECK(!IsHighRegister(rm));
+          // Sets condition codes if and only if outside IT block,
+          // check that it complies with set_cc.
+          DCHECK((cond == AL) ? set_cc != kCcKeep : set_cc != kCcSet);
           opcode_shift = 9;
           thumb_opcode = 12U /* 0b01100 */;
           immediate = static_cast<uint32_t>(so.GetRegister());
@@ -1523,40 +1567,47 @@
 
     case SUB:
       if (so.IsRegister()) {
-         // T1.
-         opcode_shift = 9;
-         thumb_opcode = 13U /* 0b01101 */;
-         immediate = static_cast<uint32_t>(so.GetRegister());
-         use_immediate = true;
-         immediate_shift = 6;
-       } else {
-         if (rd == SP && rn == SP) {
-           // SUB sp, sp, #imm
-           dp_opcode = 2U /* 0b10 */;
-           thumb_opcode = 0x61 /* 0b1100001 */;
-           opcode_shift = 7;
-           CHECK_LT(immediate, (1u << 9));
-           CHECK_ALIGNED(immediate, 4);
+        // T1.
+        Register rm = so.GetRegister();
+        DCHECK(!IsHighRegister(rd));
+        DCHECK(!IsHighRegister(rn));
+        DCHECK(!IsHighRegister(rm));
+        // Sets condition codes if and only if outside IT block,
+        // check that it complies with set_cc.
+        DCHECK((cond == AL) ? set_cc != kCcKeep : set_cc != kCcSet);
+        opcode_shift = 9;
+        thumb_opcode = 13U /* 0b01101 */;
+        immediate = static_cast<uint32_t>(rm);
+        use_immediate = true;
+        immediate_shift = 6;
+      } else {
+        if (rd == SP && rn == SP) {
+          // SUB sp, sp, #imm
+          dp_opcode = 2U /* 0b10 */;
+          thumb_opcode = 0x61 /* 0b1100001 */;
+          opcode_shift = 7;
+          CHECK_LT(immediate, (1u << 9));
+          CHECK_ALIGNED(immediate, 4);
 
-           // Remove rd and rn from instruction by orring it with immed and clearing bits.
-           rn = R0;
-           rd = R0;
-           rd_shift = 0;
-           rn_shift = 0;
-           immediate >>= 2;
-         } else if (rn != rd) {
-           // Must use T1.
-           opcode_shift = 9;
-           thumb_opcode = 15U /* 0b01111 */;
-           immediate_shift = 6;
-         } else {
-           // T2 encoding.
-           opcode_shift = 11;
-           thumb_opcode = 7U /* 0b111 */;
-           rd_shift = 8;
-           rn_shift = 8;
-         }
-       }
+          // Remove rd and rn from instruction by orring it with immed and clearing bits.
+          rn = R0;
+          rd = R0;
+          rd_shift = 0;
+          rn_shift = 0;
+          immediate >>= 2;
+        } else if (rn != rd) {
+          // Must use T1.
+          opcode_shift = 9;
+          thumb_opcode = 15U /* 0b01111 */;
+          immediate_shift = 6;
+        } else {
+          // T2 encoding.
+          opcode_shift = 11;
+          thumb_opcode = 7U /* 0b111 */;
+          rd_shift = 8;
+          rn_shift = 8;
+        }
+      }
       break;
     default:
       LOG(FATAL) << "This opcode is not an ADD or SUB: " << opcode;
@@ -1575,7 +1626,7 @@
 
 void Thumb2Assembler::EmitDataProcessing(Condition cond,
                                          Opcode opcode,
-                                         bool set_cc,
+                                         SetCc set_cc,
                                          Register rn,
                                          Register rd,
                                          const ShifterOperand& so) {
@@ -1589,9 +1640,15 @@
   }
 }
 
-void Thumb2Assembler::EmitShift(Register rd, Register rm, Shift shift, uint8_t amount, bool setcc) {
+void Thumb2Assembler::EmitShift(Register rd,
+                                Register rm,
+                                Shift shift,
+                                uint8_t amount,
+                                Condition cond,
+                                SetCc set_cc) {
   CHECK_LT(amount, (1 << 5));
-  if (IsHighRegister(rd) || IsHighRegister(rm) || shift == ROR || shift == RRX) {
+  if ((IsHighRegister(rd) || IsHighRegister(rm) || shift == ROR || shift == RRX) ||
+      ((cond == AL) ? set_cc == kCcKeep : set_cc == kCcSet)) {
     uint16_t opcode = 0;
     switch (shift) {
       case LSL: opcode = 0U /* 0b00 */; break;
@@ -1605,7 +1662,7 @@
     }
     // 32 bit.
     int32_t encoding = B31 | B30 | B29 | B27 | B25 | B22 |
-        0xf << 16 | (setcc ? B20 : 0);
+        0xf << 16 | (set_cc == kCcSet ? B20 : 0);
     uint32_t imm3 = amount >> 2;
     uint32_t imm2 = amount & 3U /* 0b11 */;
     encoding |= imm3 << 12 | imm2 << 6 | static_cast<int16_t>(rm) |
@@ -1628,10 +1685,16 @@
   }
 }
 
-void Thumb2Assembler::EmitShift(Register rd, Register rn, Shift shift, Register rm, bool setcc) {
+void Thumb2Assembler::EmitShift(Register rd,
+                                Register rn,
+                                Shift shift,
+                                Register rm,
+                                Condition cond,
+                                SetCc set_cc) {
   CHECK_NE(shift, RRX);
   bool must_be_32bit = false;
-  if (IsHighRegister(rd) || IsHighRegister(rm) || IsHighRegister(rn) || rd != rn) {
+  if (IsHighRegister(rd) || IsHighRegister(rm) || IsHighRegister(rn) || rd != rn ||
+      ((cond == AL) ? set_cc == kCcKeep : set_cc == kCcSet)) {
     must_be_32bit = true;
   }
 
@@ -1648,7 +1711,7 @@
      }
      // 32 bit.
      int32_t encoding = B31 | B30 | B29 | B28 | B27 | B25 |
-         0xf << 12 | (setcc ? B20 : 0);
+         0xf << 12 | (set_cc == kCcSet ? B20 : 0);
      encoding |= static_cast<int16_t>(rn) << 16 | static_cast<int16_t>(rm) |
          static_cast<int16_t>(rd) << 8 | opcode << 21;
      Emit32(encoding);
@@ -1658,6 +1721,7 @@
       case LSL: opcode = 2U /* 0b0010 */; break;
       case LSR: opcode = 3U /* 0b0011 */; break;
       case ASR: opcode = 4U /* 0b0100 */; break;
+      case ROR: opcode = 7U /* 0b0111 */; break;
       default:
         LOG(FATAL) << "Unsupported thumb2 shift opcode";
         UNREACHABLE();
@@ -2915,70 +2979,70 @@
 
 
 void Thumb2Assembler::Lsl(Register rd, Register rm, uint32_t shift_imm,
-                          bool setcc, Condition cond) {
+                          Condition cond, SetCc set_cc) {
   CHECK_LE(shift_imm, 31u);
   CheckCondition(cond);
-  EmitShift(rd, rm, LSL, shift_imm, setcc);
+  EmitShift(rd, rm, LSL, shift_imm, cond, set_cc);
 }
 
 
 void Thumb2Assembler::Lsr(Register rd, Register rm, uint32_t shift_imm,
-                          bool setcc, Condition cond) {
+                          Condition cond, SetCc set_cc) {
   CHECK(1u <= shift_imm && shift_imm <= 32u);
   if (shift_imm == 32) shift_imm = 0;  // Comply to UAL syntax.
   CheckCondition(cond);
-  EmitShift(rd, rm, LSR, shift_imm, setcc);
+  EmitShift(rd, rm, LSR, shift_imm, cond, set_cc);
 }
 
 
 void Thumb2Assembler::Asr(Register rd, Register rm, uint32_t shift_imm,
-                          bool setcc, Condition cond) {
+                          Condition cond, SetCc set_cc) {
   CHECK(1u <= shift_imm && shift_imm <= 32u);
   if (shift_imm == 32) shift_imm = 0;  // Comply to UAL syntax.
   CheckCondition(cond);
-  EmitShift(rd, rm, ASR, shift_imm, setcc);
+  EmitShift(rd, rm, ASR, shift_imm, cond, set_cc);
 }
 
 
 void Thumb2Assembler::Ror(Register rd, Register rm, uint32_t shift_imm,
-                          bool setcc, Condition cond) {
+                          Condition cond, SetCc set_cc) {
   CHECK(1u <= shift_imm && shift_imm <= 31u);
   CheckCondition(cond);
-  EmitShift(rd, rm, ROR, shift_imm, setcc);
+  EmitShift(rd, rm, ROR, shift_imm, cond, set_cc);
 }
 
 
-void Thumb2Assembler::Rrx(Register rd, Register rm, bool setcc, Condition cond) {
+void Thumb2Assembler::Rrx(Register rd, Register rm, Condition cond, SetCc set_cc) {
   CheckCondition(cond);
-  EmitShift(rd, rm, RRX, rm, setcc);
+  EmitShift(rd, rm, RRX, rm, cond, set_cc);
 }
 
 
 void Thumb2Assembler::Lsl(Register rd, Register rm, Register rn,
-                          bool setcc, Condition cond) {
+                          Condition cond, SetCc set_cc) {
   CheckCondition(cond);
-  EmitShift(rd, rm, LSL, rn, setcc);
+  EmitShift(rd, rm, LSL, rn, cond, set_cc);
 }
 
 
 void Thumb2Assembler::Lsr(Register rd, Register rm, Register rn,
-                          bool setcc, Condition cond) {
+                          Condition cond, SetCc set_cc) {
   CheckCondition(cond);
-  EmitShift(rd, rm, LSR, rn, setcc);
+  EmitShift(rd, rm, LSR, rn, cond, set_cc);
 }
 
 
 void Thumb2Assembler::Asr(Register rd, Register rm, Register rn,
-                          bool setcc, Condition cond) {
+                          Condition cond, SetCc set_cc) {
   CheckCondition(cond);
-  EmitShift(rd, rm, ASR, rn, setcc);
+  EmitShift(rd, rm, ASR, rn, cond, set_cc);
 }
 
 
 void Thumb2Assembler::Ror(Register rd, Register rm, Register rn,
-                          bool setcc, Condition cond) {
+                          Condition cond, SetCc set_cc) {
   CheckCondition(cond);
-  EmitShift(rd, rm, ROR, rn, setcc);
+  EmitShift(rd, rm, ROR, rn, cond, set_cc);
 }
 
 
@@ -3173,24 +3237,24 @@
                                           Condition cond) {
   ShifterOperand shifter_op;
   if (ShifterOperandCanHold(rd, rn, ADD, value, &shifter_op)) {
-    adds(rd, rn, shifter_op, cond);
+    add(rd, rn, shifter_op, cond, kCcSet);
   } else if (ShifterOperandCanHold(rd, rn, ADD, -value, &shifter_op)) {
-    subs(rd, rn, shifter_op, cond);
+    sub(rd, rn, shifter_op, cond, kCcSet);
   } else {
     CHECK(rn != IP);
     if (ShifterOperandCanHold(rd, rn, MVN, ~value, &shifter_op)) {
       mvn(IP, shifter_op, cond);
-      adds(rd, rn, ShifterOperand(IP), cond);
+      add(rd, rn, ShifterOperand(IP), cond, kCcSet);
     } else if (ShifterOperandCanHold(rd, rn, MVN, ~(-value), &shifter_op)) {
       mvn(IP, shifter_op, cond);
-      subs(rd, rn, ShifterOperand(IP), cond);
+      sub(rd, rn, ShifterOperand(IP), cond, kCcSet);
     } else {
       movw(IP, Low16Bits(value), cond);
       uint16_t value_high = High16Bits(value);
       if (value_high != 0) {
         movt(IP, value_high, cond);
       }
-      adds(rd, rn, ShifterOperand(IP), cond);
+      add(rd, rn, ShifterOperand(IP), cond, kCcSet);
     }
   }
 }
@@ -3316,7 +3380,7 @@
       }
     }
     LoadImmediate(tmp_reg, offset, cond);
-    add(tmp_reg, tmp_reg, ShifterOperand(base), cond);
+    add(tmp_reg, tmp_reg, ShifterOperand(base), AL);
     base = tmp_reg;
     offset = 0;
   }
diff --git a/compiler/utils/arm/assembler_thumb2.h b/compiler/utils/arm/assembler_thumb2.h
index 41eb5d3..c802c27 100644
--- a/compiler/utils/arm/assembler_thumb2.h
+++ b/compiler/utils/arm/assembler_thumb2.h
@@ -63,25 +63,29 @@
   void FinalizeCode() OVERRIDE;
 
   // Data-processing instructions.
-  void and_(Register rd, Register rn, const ShifterOperand& so, Condition cond = AL) OVERRIDE;
+  virtual void and_(Register rd, Register rn, const ShifterOperand& so,
+                    Condition cond = AL, SetCc set_cc = kCcDontCare) OVERRIDE;
 
-  void eor(Register rd, Register rn, const ShifterOperand& so, Condition cond = AL) OVERRIDE;
+  virtual void eor(Register rd, Register rn, const ShifterOperand& so,
+                   Condition cond = AL, SetCc set_cc = kCcDontCare) OVERRIDE;
 
-  void sub(Register rd, Register rn, const ShifterOperand& so, Condition cond = AL) OVERRIDE;
-  void subs(Register rd, Register rn, const ShifterOperand& so, Condition cond = AL) OVERRIDE;
+  virtual void sub(Register rd, Register rn, const ShifterOperand& so,
+                   Condition cond = AL, SetCc set_cc = kCcDontCare) OVERRIDE;
 
-  void rsb(Register rd, Register rn, const ShifterOperand& so, Condition cond = AL) OVERRIDE;
-  void rsbs(Register rd, Register rn, const ShifterOperand& so, Condition cond = AL) OVERRIDE;
+  virtual void rsb(Register rd, Register rn, const ShifterOperand& so,
+                   Condition cond = AL, SetCc set_cc = kCcDontCare) OVERRIDE;
 
-  void add(Register rd, Register rn, const ShifterOperand& so, Condition cond = AL) OVERRIDE;
+  virtual void add(Register rd, Register rn, const ShifterOperand& so,
+                   Condition cond = AL, SetCc set_cc = kCcDontCare) OVERRIDE;
 
-  void adds(Register rd, Register rn, const ShifterOperand& so, Condition cond = AL) OVERRIDE;
+  virtual void adc(Register rd, Register rn, const ShifterOperand& so,
+                   Condition cond = AL, SetCc set_cc = kCcDontCare) OVERRIDE;
 
-  void adc(Register rd, Register rn, const ShifterOperand& so, Condition cond = AL) OVERRIDE;
+  virtual void sbc(Register rd, Register rn, const ShifterOperand& so,
+                   Condition cond = AL, SetCc set_cc = kCcDontCare) OVERRIDE;
 
-  void sbc(Register rd, Register rn, const ShifterOperand& so, Condition cond = AL) OVERRIDE;
-
-  void rsc(Register rd, Register rn, const ShifterOperand& so, Condition cond = AL) OVERRIDE;
+  virtual void rsc(Register rd, Register rn, const ShifterOperand& so,
+                   Condition cond = AL, SetCc set_cc = kCcDontCare) OVERRIDE;
 
   void tst(Register rn, const ShifterOperand& so, Condition cond = AL) OVERRIDE;
 
@@ -91,16 +95,17 @@
 
   void cmn(Register rn, const ShifterOperand& so, Condition cond = AL) OVERRIDE;
 
-  void orr(Register rd, Register rn, const ShifterOperand& so, Condition cond = AL) OVERRIDE;
-  void orrs(Register rd, Register rn, const ShifterOperand& so, Condition cond = AL) OVERRIDE;
+  virtual void orr(Register rd, Register rn, const ShifterOperand& so,
+                   Condition cond = AL, SetCc set_cc = kCcDontCare) OVERRIDE;
 
-  void mov(Register rd, const ShifterOperand& so, Condition cond = AL) OVERRIDE;
-  void movs(Register rd, const ShifterOperand& so, Condition cond = AL) OVERRIDE;
+  virtual void mov(Register rd, const ShifterOperand& so,
+                   Condition cond = AL, SetCc set_cc = kCcDontCare) OVERRIDE;
 
-  void bic(Register rd, Register rn, const ShifterOperand& so, Condition cond = AL) OVERRIDE;
+  virtual void bic(Register rd, Register rn, const ShifterOperand& so,
+                   Condition cond = AL, SetCc set_cc = kCcDontCare) OVERRIDE;
 
-  void mvn(Register rd, const ShifterOperand& so, Condition cond = AL) OVERRIDE;
-  void mvns(Register rd, const ShifterOperand& so, Condition cond = AL) OVERRIDE;
+  virtual void mvn(Register rd, const ShifterOperand& so,
+                   Condition cond = AL, SetCc set_cc = kCcDontCare) OVERRIDE;
 
   // Miscellaneous data-processing instructions.
   void clz(Register rd, Register rm, Condition cond = AL) OVERRIDE;
@@ -245,25 +250,25 @@
   void blx(Register rm, Condition cond = AL) OVERRIDE;
   void bx(Register rm, Condition cond = AL) OVERRIDE;
 
-  void Lsl(Register rd, Register rm, uint32_t shift_imm, bool setcc = false,
-           Condition cond = AL) OVERRIDE;
-  void Lsr(Register rd, Register rm, uint32_t shift_imm, bool setcc = false,
-           Condition cond = AL) OVERRIDE;
-  void Asr(Register rd, Register rm, uint32_t shift_imm, bool setcc = false,
-           Condition cond = AL) OVERRIDE;
-  void Ror(Register rd, Register rm, uint32_t shift_imm, bool setcc = false,
-           Condition cond = AL) OVERRIDE;
-  void Rrx(Register rd, Register rm, bool setcc = false,
-           Condition cond = AL) OVERRIDE;
+  virtual void Lsl(Register rd, Register rm, uint32_t shift_imm,
+                   Condition cond = AL, SetCc set_cc = kCcDontCare) OVERRIDE;
+  virtual void Lsr(Register rd, Register rm, uint32_t shift_imm,
+                   Condition cond = AL, SetCc set_cc = kCcDontCare) OVERRIDE;
+  virtual void Asr(Register rd, Register rm, uint32_t shift_imm,
+                   Condition cond = AL, SetCc set_cc = kCcDontCare) OVERRIDE;
+  virtual void Ror(Register rd, Register rm, uint32_t shift_imm,
+                   Condition cond = AL, SetCc set_cc = kCcDontCare) OVERRIDE;
+  virtual void Rrx(Register rd, Register rm,
+                   Condition cond = AL, SetCc set_cc = kCcDontCare) OVERRIDE;
 
-  void Lsl(Register rd, Register rm, Register rn, bool setcc = false,
-           Condition cond = AL) OVERRIDE;
-  void Lsr(Register rd, Register rm, Register rn, bool setcc = false,
-           Condition cond = AL) OVERRIDE;
-  void Asr(Register rd, Register rm, Register rn, bool setcc = false,
-           Condition cond = AL) OVERRIDE;
-  void Ror(Register rd, Register rm, Register rn, bool setcc = false,
-           Condition cond = AL) OVERRIDE;
+  virtual void Lsl(Register rd, Register rm, Register rn,
+                   Condition cond = AL, SetCc set_cc = kCcDontCare) OVERRIDE;
+  virtual void Lsr(Register rd, Register rm, Register rn,
+                   Condition cond = AL, SetCc set_cc = kCcDontCare) OVERRIDE;
+  virtual void Asr(Register rd, Register rm, Register rn,
+                   Condition cond = AL, SetCc set_cc = kCcDontCare) OVERRIDE;
+  virtual void Ror(Register rd, Register rm, Register rn,
+                   Condition cond = AL, SetCc set_cc = kCcDontCare) OVERRIDE;
 
   void Push(Register rd, Condition cond = AL) OVERRIDE;
   void Pop(Register rd, Condition cond = AL) OVERRIDE;
@@ -600,7 +605,7 @@
   // Emit a single 32 or 16 bit data processing instruction.
   void EmitDataProcessing(Condition cond,
                           Opcode opcode,
-                          bool set_cc,
+                          SetCc set_cc,
                           Register rn,
                           Register rd,
                           const ShifterOperand& so);
@@ -609,7 +614,7 @@
   // in 16 bits?
   bool Is32BitDataProcessing(Condition cond,
                              Opcode opcode,
-                             bool set_cc,
+                             SetCc set_cc,
                              Register rn,
                              Register rd,
                              const ShifterOperand& so);
@@ -617,7 +622,7 @@
   // Emit a 32 bit data processing instruction.
   void Emit32BitDataProcessing(Condition cond,
                                Opcode opcode,
-                               bool set_cc,
+                               SetCc set_cc,
                                Register rn,
                                Register rd,
                                const ShifterOperand& so);
@@ -625,14 +630,14 @@
   // Emit a 16 bit data processing instruction.
   void Emit16BitDataProcessing(Condition cond,
                                Opcode opcode,
-                               bool set_cc,
+                               SetCc set_cc,
                                Register rn,
                                Register rd,
                                const ShifterOperand& so);
 
   void Emit16BitAddSub(Condition cond,
                        Opcode opcode,
-                       bool set_cc,
+                       SetCc set_cc,
                        Register rn,
                        Register rd,
                        const ShifterOperand& so);
@@ -694,8 +699,10 @@
   static int DecodeBranchOffset(int32_t inst);
   int32_t EncodeTstOffset(int offset, int32_t inst);
   int DecodeTstOffset(int32_t inst);
-  void EmitShift(Register rd, Register rm, Shift shift, uint8_t amount, bool setcc = false);
-  void EmitShift(Register rd, Register rn, Shift shift, Register rm, bool setcc = false);
+  void EmitShift(Register rd, Register rm, Shift shift, uint8_t amount,
+                 Condition cond = AL, SetCc set_cc = kCcDontCare);
+  void EmitShift(Register rd, Register rn, Shift shift, Register rm,
+                 Condition cond = AL, SetCc set_cc = kCcDontCare);
 
   // Whether the assembler can relocate branches. If false, unresolved branches will be
   // emitted on 32bits.
diff --git a/compiler/utils/assembler_thumb_test.cc b/compiler/utils/assembler_thumb_test.cc
index cb01cea..b2a354b 100644
--- a/compiler/utils/assembler_thumb_test.cc
+++ b/compiler/utils/assembler_thumb_test.cc
@@ -199,6 +199,7 @@
 TEST(Thumb2AssemblerTest, SimpleMov) {
   arm::Thumb2Assembler assembler;
 
+  __ movs(R0, ShifterOperand(R1));
   __ mov(R0, ShifterOperand(R1));
   __ mov(R8, ShifterOperand(R9));
 
@@ -222,8 +223,8 @@
   arm::Thumb2Assembler assembler;
 
   __ mov(R0, ShifterOperand(R1));
-  __ add(R0, R1, ShifterOperand(R2));
-  __ add(R0, R1, ShifterOperand());
+  __ adds(R0, R1, ShifterOperand(R2));
+  __ add(R0, R1, ShifterOperand(0));
 
   EmitAndCheck(&assembler, "SimpleMovAdd");
 }
@@ -231,41 +232,132 @@
 TEST(Thumb2AssemblerTest, DataProcessingRegister) {
   arm::Thumb2Assembler assembler;
 
+  // 32 bit variants using low registers.
+  __ mvn(R0, ShifterOperand(R1), AL, kCcKeep);
+  __ add(R0, R1, ShifterOperand(R2), AL, kCcKeep);
+  __ sub(R0, R1, ShifterOperand(R2), AL, kCcKeep);
+  __ and_(R0, R1, ShifterOperand(R2), AL, kCcKeep);
+  __ orr(R0, R1, ShifterOperand(R2), AL, kCcKeep);
+  __ eor(R0, R1, ShifterOperand(R2), AL, kCcKeep);
+  __ bic(R0, R1, ShifterOperand(R2), AL, kCcKeep);
+  __ adc(R0, R1, ShifterOperand(R2), AL, kCcKeep);
+  __ sbc(R0, R1, ShifterOperand(R2), AL, kCcKeep);
+  __ rsb(R0, R1, ShifterOperand(R2), AL, kCcKeep);
+  __ teq(R0, ShifterOperand(R1));
+
+  // 16 bit variants using low registers.
+  __ movs(R0, ShifterOperand(R1));
+  __ mov(R0, ShifterOperand(R1), AL, kCcKeep);
+  __ mvns(R0, ShifterOperand(R1));
+  __ add(R0, R0, ShifterOperand(R1), AL, kCcKeep);
+  __ adds(R0, R1, ShifterOperand(R2));
+  __ subs(R0, R1, ShifterOperand(R2));
+  __ adcs(R0, R0, ShifterOperand(R1));
+  __ sbcs(R0, R0, ShifterOperand(R1));
+  __ ands(R0, R0, ShifterOperand(R1));
+  __ orrs(R0, R0, ShifterOperand(R1));
+  __ eors(R0, R0, ShifterOperand(R1));
+  __ bics(R0, R0, ShifterOperand(R1));
+  __ tst(R0, ShifterOperand(R1));
+  __ cmp(R0, ShifterOperand(R1));
+  __ cmn(R0, ShifterOperand(R1));
+
+  // 16-bit variants using high registers.
+  __ mov(R1, ShifterOperand(R8), AL, kCcKeep);
+  __ mov(R9, ShifterOperand(R0), AL, kCcKeep);
+  __ mov(R8, ShifterOperand(R9), AL, kCcKeep);
+  __ add(R1, R1, ShifterOperand(R8), AL, kCcKeep);
+  __ add(R9, R9, ShifterOperand(R0), AL, kCcKeep);
+  __ add(R8, R8, ShifterOperand(R9), AL, kCcKeep);
+  __ cmp(R0, ShifterOperand(R9));
+  __ cmp(R8, ShifterOperand(R1));
+  __ cmp(R9, ShifterOperand(R8));
+
+  // The 16-bit RSBS Rd, Rn, #0, also known as NEGS Rd, Rn is specified using
+  // an immediate (0) but emitted without any, so we test it here.
+  __ rsbs(R0, R1, ShifterOperand(0));
+  __ rsbs(R0, R0, ShifterOperand(0));  // Check Rd == Rn code path.
+
+  // 32 bit variants using high registers that would be 16-bit if using low registers.
+  __ movs(R0, ShifterOperand(R8));
+  __ mvns(R0, ShifterOperand(R8));
+  __ add(R0, R1, ShifterOperand(R8), AL, kCcKeep);
+  __ adds(R0, R1, ShifterOperand(R8));
+  __ subs(R0, R1, ShifterOperand(R8));
+  __ adcs(R0, R0, ShifterOperand(R8));
+  __ sbcs(R0, R0, ShifterOperand(R8));
+  __ ands(R0, R0, ShifterOperand(R8));
+  __ orrs(R0, R0, ShifterOperand(R8));
+  __ eors(R0, R0, ShifterOperand(R8));
+  __ bics(R0, R0, ShifterOperand(R8));
+  __ tst(R0, ShifterOperand(R8));
+  __ cmn(R0, ShifterOperand(R8));
+  __ rsbs(R0, R8, ShifterOperand(0));  // Check that this is not emitted as 16-bit.
+  __ rsbs(R8, R8, ShifterOperand(0));  // Check that this is not emitted as 16-bit (Rd == Rn).
+
+  // 32-bit variants of instructions that would be 16-bit outside IT block.
+  __ it(arm::EQ);
+  __ mvns(R0, ShifterOperand(R1), arm::EQ);
+  __ it(arm::EQ);
+  __ adds(R0, R1, ShifterOperand(R2), arm::EQ);
+  __ it(arm::EQ);
+  __ subs(R0, R1, ShifterOperand(R2), arm::EQ);
+  __ it(arm::EQ);
+  __ adcs(R0, R0, ShifterOperand(R1), arm::EQ);
+  __ it(arm::EQ);
+  __ sbcs(R0, R0, ShifterOperand(R1), arm::EQ);
+  __ it(arm::EQ);
+  __ ands(R0, R0, ShifterOperand(R1), arm::EQ);
+  __ it(arm::EQ);
+  __ orrs(R0, R0, ShifterOperand(R1), arm::EQ);
+  __ it(arm::EQ);
+  __ eors(R0, R0, ShifterOperand(R1), arm::EQ);
+  __ it(arm::EQ);
+  __ bics(R0, R0, ShifterOperand(R1), arm::EQ);
+
+  // 16-bit variants of instructions that would be 32-bit outside IT block.
+  __ it(arm::EQ);
+  __ mvn(R0, ShifterOperand(R1), arm::EQ, kCcKeep);
+  __ it(arm::EQ);
+  __ add(R0, R1, ShifterOperand(R2), arm::EQ, kCcKeep);
+  __ it(arm::EQ);
+  __ sub(R0, R1, ShifterOperand(R2), arm::EQ, kCcKeep);
+  __ it(arm::EQ);
+  __ adc(R0, R0, ShifterOperand(R1), arm::EQ, kCcKeep);
+  __ it(arm::EQ);
+  __ sbc(R0, R0, ShifterOperand(R1), arm::EQ, kCcKeep);
+  __ it(arm::EQ);
+  __ and_(R0, R0, ShifterOperand(R1), arm::EQ, kCcKeep);
+  __ it(arm::EQ);
+  __ orr(R0, R0, ShifterOperand(R1), arm::EQ, kCcKeep);
+  __ it(arm::EQ);
+  __ eor(R0, R0, ShifterOperand(R1), arm::EQ, kCcKeep);
+  __ it(arm::EQ);
+  __ bic(R0, R0, ShifterOperand(R1), arm::EQ, kCcKeep);
+
+  // 16 bit variants selected for the default kCcDontCare.
   __ mov(R0, ShifterOperand(R1));
   __ mvn(R0, ShifterOperand(R1));
-
-  // 32 bit variants.
+  __ add(R0, R0, ShifterOperand(R1));
   __ add(R0, R1, ShifterOperand(R2));
   __ sub(R0, R1, ShifterOperand(R2));
-  __ and_(R0, R1, ShifterOperand(R2));
-  __ orr(R0, R1, ShifterOperand(R2));
-  __ eor(R0, R1, ShifterOperand(R2));
-  __ bic(R0, R1, ShifterOperand(R2));
-  __ adc(R0, R1, ShifterOperand(R2));
-  __ sbc(R0, R1, ShifterOperand(R2));
-  __ rsb(R0, R1, ShifterOperand(R2));
-
-  // 16 bit variants.
-  __ add(R0, R1, ShifterOperand());
-  __ sub(R0, R1, ShifterOperand());
+  __ adc(R0, R0, ShifterOperand(R1));
+  __ sbc(R0, R0, ShifterOperand(R1));
   __ and_(R0, R0, ShifterOperand(R1));
   __ orr(R0, R0, ShifterOperand(R1));
   __ eor(R0, R0, ShifterOperand(R1));
   __ bic(R0, R0, ShifterOperand(R1));
-  __ adc(R0, R0, ShifterOperand(R1));
-  __ sbc(R0, R0, ShifterOperand(R1));
-  __ rsb(R0, R0, ShifterOperand(R1));
+  __ mov(R1, ShifterOperand(R8));
+  __ mov(R9, ShifterOperand(R0));
+  __ mov(R8, ShifterOperand(R9));
+  __ add(R1, R1, ShifterOperand(R8));
+  __ add(R9, R9, ShifterOperand(R0));
+  __ add(R8, R8, ShifterOperand(R9));
+  __ rsb(R0, R1, ShifterOperand(0));
+  __ rsb(R0, R0, ShifterOperand(0));
 
-  __ tst(R0, ShifterOperand(R1));
-  __ teq(R0, ShifterOperand(R1));
-  __ cmp(R0, ShifterOperand(R1));
-  __ cmn(R0, ShifterOperand(R1));
-
-  __ movs(R0, ShifterOperand(R1));
-  __ mvns(R0, ShifterOperand(R1));
-
-  // 32 bit variants.
-  __ add(R12, R1, ShifterOperand(R0));
+  // And an arbitrary 32-bit instruction using IP.
+  __ add(R12, R1, ShifterOperand(R0), AL, kCcKeep);
 
   EmitAndCheck(&assembler, "DataProcessingRegister");
 }
@@ -296,6 +388,9 @@
   __ movs(R0, ShifterOperand(0x55));
   __ mvns(R0, ShifterOperand(0x55));
 
+  __ adds(R0, R1, ShifterOperand(5));
+  __ subs(R0, R1, ShifterOperand(5));
+
   EmitAndCheck(&assembler, "DataProcessingImmediate");
 }
 
@@ -340,18 +435,30 @@
 TEST(Thumb2AssemblerTest, DataProcessingShiftedRegister) {
   arm::Thumb2Assembler assembler;
 
-  __ mov(R3, ShifterOperand(R4, LSL, 4));
-  __ mov(R3, ShifterOperand(R4, LSR, 5));
-  __ mov(R3, ShifterOperand(R4, ASR, 6));
-  __ mov(R3, ShifterOperand(R4, ROR, 7));
-  __ mov(R3, ShifterOperand(R4, ROR));
+  // 16-bit variants.
+  __ movs(R3, ShifterOperand(R4, LSL, 4));
+  __ movs(R3, ShifterOperand(R4, LSR, 5));
+  __ movs(R3, ShifterOperand(R4, ASR, 6));
 
-  // 32 bit variants.
-  __ mov(R8, ShifterOperand(R4, LSL, 4));
-  __ mov(R8, ShifterOperand(R4, LSR, 5));
-  __ mov(R8, ShifterOperand(R4, ASR, 6));
-  __ mov(R8, ShifterOperand(R4, ROR, 7));
-  __ mov(R8, ShifterOperand(R4, RRX));
+  // 32-bit ROR because ROR immediate doesn't have the same 16-bit version as other shifts.
+  __ movs(R3, ShifterOperand(R4, ROR, 7));
+
+  // 32-bit RRX because RRX has no 16-bit version.
+  __ movs(R3, ShifterOperand(R4, RRX));
+
+  // 32 bit variants (not setting condition codes).
+  __ mov(R3, ShifterOperand(R4, LSL, 4), AL, kCcKeep);
+  __ mov(R3, ShifterOperand(R4, LSR, 5), AL, kCcKeep);
+  __ mov(R3, ShifterOperand(R4, ASR, 6), AL, kCcKeep);
+  __ mov(R3, ShifterOperand(R4, ROR, 7), AL, kCcKeep);
+  __ mov(R3, ShifterOperand(R4, RRX), AL, kCcKeep);
+
+  // 32 bit variants (high registers).
+  __ movs(R8, ShifterOperand(R4, LSL, 4));
+  __ movs(R8, ShifterOperand(R4, LSR, 5));
+  __ movs(R8, ShifterOperand(R4, ASR, 6));
+  __ movs(R8, ShifterOperand(R4, ROR, 7));
+  __ movs(R8, ShifterOperand(R4, RRX));
 
   EmitAndCheck(&assembler, "DataProcessingShiftedRegister");
 }
@@ -1023,7 +1130,7 @@
 TEST(Thumb2AssemblerTest, Shifts) {
   arm::Thumb2Assembler assembler;
 
-  // 16 bit
+  // 16 bit selected for CcDontCare.
   __ Lsl(R0, R1, 5);
   __ Lsr(R0, R1, 5);
   __ Asr(R0, R1, 5);
@@ -1031,6 +1138,32 @@
   __ Lsl(R0, R0, R1);
   __ Lsr(R0, R0, R1);
   __ Asr(R0, R0, R1);
+  __ Ror(R0, R0, R1);
+
+  // 16 bit with kCcSet.
+  __ Lsls(R0, R1, 5);
+  __ Lsrs(R0, R1, 5);
+  __ Asrs(R0, R1, 5);
+
+  __ Lsls(R0, R0, R1);
+  __ Lsrs(R0, R0, R1);
+  __ Asrs(R0, R0, R1);
+  __ Rors(R0, R0, R1);
+
+  // 32-bit with kCcKeep.
+  __ Lsl(R0, R1, 5, AL, kCcKeep);
+  __ Lsr(R0, R1, 5, AL, kCcKeep);
+  __ Asr(R0, R1, 5, AL, kCcKeep);
+
+  __ Lsl(R0, R0, R1, AL, kCcKeep);
+  __ Lsr(R0, R0, R1, AL, kCcKeep);
+  __ Asr(R0, R0, R1, AL, kCcKeep);
+  __ Ror(R0, R0, R1, AL, kCcKeep);
+
+  // 32-bit because ROR immediate doesn't have a 16-bit version like the other shifts.
+  __ Ror(R0, R1, 5);
+  __ Rors(R0, R1, 5);
+  __ Ror(R0, R1, 5, AL, kCcKeep);
 
   // 32 bit due to high registers.
   __ Lsl(R8, R1, 5);
@@ -1052,21 +1185,21 @@
   // S bit (all 32 bit)
 
   // 32 bit due to high registers.
-  __ Lsl(R8, R1, 5, true);
-  __ Lsr(R0, R8, 5, true);
-  __ Asr(R8, R1, 5, true);
-  __ Ror(R0, R8, 5, true);
+  __ Lsls(R8, R1, 5);
+  __ Lsrs(R0, R8, 5);
+  __ Asrs(R8, R1, 5);
+  __ Rors(R0, R8, 5);
 
   // 32 bit due to different Rd and Rn.
-  __ Lsl(R0, R1, R2, true);
-  __ Lsr(R0, R1, R2, true);
-  __ Asr(R0, R1, R2, true);
-  __ Ror(R0, R1, R2, true);
+  __ Lsls(R0, R1, R2);
+  __ Lsrs(R0, R1, R2);
+  __ Asrs(R0, R1, R2);
+  __ Rors(R0, R1, R2);
 
   // 32 bit due to use of high registers.
-  __ Lsl(R8, R1, R2, true);
-  __ Lsr(R0, R8, R2, true);
-  __ Asr(R0, R1, R8, true);
+  __ Lsls(R8, R1, R2);
+  __ Lsrs(R0, R8, R2);
+  __ Asrs(R0, R1, R8);
 
   EmitAndCheck(&assembler, "Shifts");
 }
diff --git a/compiler/utils/assembler_thumb_test_expected.cc.inc b/compiler/utils/assembler_thumb_test_expected.cc.inc
index 280ed77..82ad642 100644
--- a/compiler/utils/assembler_thumb_test_expected.cc.inc
+++ b/compiler/utils/assembler_thumb_test_expected.cc.inc
@@ -1,8 +1,9 @@
 const char* SimpleMovResults[] = {
   "   0:	0008      	movs	r0, r1\n",
-  "   2:	46c8      	mov	r8, r9\n",
-  "   4:	2001      	movs	r0, #1\n",
-  "   6:	f04f 0809 	mov.w	r8, #9\n",
+  "   2:	4608      	mov	r0, r1\n",
+  "   4:	46c8      	mov	r8, r9\n",
+  "   6:	2001      	movs	r0, #1\n",
+  "   8:	f04f 0809 	mov.w	r8, #9\n",
   nullptr
 };
 const char* SimpleMov32Results[] = {
@@ -11,39 +12,120 @@
   nullptr
 };
 const char* SimpleMovAddResults[] = {
-  "   0:	0008      	movs	r0, r1\n",
+  "   0:	4608      	mov	r0, r1\n",
   "   2:	1888      	adds	r0, r1, r2\n",
   "   4:	1c08      	adds	r0, r1, #0\n",
   nullptr
 };
 const char* DataProcessingRegisterResults[] = {
-  "   0:	0008      	movs	r0, r1\n",
-  "   2:	43c8      	mvns	r0, r1\n",
-  "   4:	1888      	adds	r0, r1, r2\n",
-  "   6:	1a88      	subs	r0, r1, r2\n",
-  "   8:	ea01 0002 	and.w	r0, r1, r2\n",
-  "   c:	ea41 0002 	orr.w	r0, r1, r2\n",
-  "  10:	ea81 0002 	eor.w	r0, r1, r2\n",
-  "  14:	ea21 0002 	bic.w	r0, r1, r2\n",
-  "  18:	eb41 0002 	adc.w	r0, r1, r2\n",
-  "  1c:	eb61 0002 	sbc.w	r0, r1, r2\n",
-  "  20:	ebc1 0002 	rsb	r0, r1, r2\n",
-  "  24:	1c08      	adds	r0, r1, #0\n",
-  "  26:	1e08      	subs	r0, r1, #0\n",
-  "  28:	4008      	ands	r0, r1\n",
-  "  2a:	4308      	orrs	r0, r1\n",
-  "  2c:	4048      	eors	r0, r1\n",
-  "  2e:	4388      	bics	r0, r1\n",
-  "  30:	4148      	adcs	r0, r1\n",
-  "  32:	4188      	sbcs	r0, r1\n",
-  "  34:	4248      	negs	r0, r1\n",
-  "  36:	4208      	tst	r0, r1\n",
-  "  38:	ea90 0f01 	teq	r0, r1\n",
-  "  3c:	4288      	cmp	r0, r1\n",
-  "  3e:	42c8      	cmn	r0, r1\n",
-  "  40:	0008      	movs	r0, r1\n",
-  "  42:	43c8      	mvns	r0, r1\n",
-  "  44:	eb01 0c00   add.w	ip, r1, r0\n",
+  "   0:	ea6f 0001 	mvn.w	r0, r1\n",
+  "   4:	eb01 0002 	add.w	r0, r1, r2\n",
+  "   8:	eba1 0002 	sub.w	r0, r1, r2\n",
+  "   c:	ea01 0002 	and.w	r0, r1, r2\n",
+  "  10:	ea41 0002 	orr.w	r0, r1, r2\n",
+  "  14:	ea81 0002 	eor.w	r0, r1, r2\n",
+  "  18:	ea21 0002 	bic.w	r0, r1, r2\n",
+  "  1c:	eb41 0002 	adc.w	r0, r1, r2\n",
+  "  20:	eb61 0002 	sbc.w	r0, r1, r2\n",
+  "  24:	ebc1 0002 	rsb	r0, r1, r2\n",
+  "  28:	ea90 0f01 	teq	r0, r1\n",
+  "  2c:	0008      	movs	r0, r1\n",
+  "  2e:	4608      	mov	r0, r1\n",
+  "  30:	43c8      	mvns	r0, r1\n",
+  "  32:	4408      	add	r0, r1\n",
+  "  34:	1888      	adds	r0, r1, r2\n",
+  "  36:	1a88      	subs	r0, r1, r2\n",
+  "  38:	4148      	adcs	r0, r1\n",
+  "  3a:	4188      	sbcs	r0, r1\n",
+  "  3c:	4008      	ands	r0, r1\n",
+  "  3e:	4308      	orrs	r0, r1\n",
+  "  40:	4048      	eors	r0, r1\n",
+  "  42:	4388      	bics	r0, r1\n",
+  "  44:	4208      	tst	r0, r1\n",
+  "  46:	4288      	cmp	r0, r1\n",
+  "  48:	42c8      	cmn	r0, r1\n",
+  "  4a:	4641		mov	r1, r8\n",
+  "  4c:	4681		mov	r9, r0\n",
+  "  4e:	46c8		mov	r8, r9\n",
+  "  50:	4441		add	r1, r8\n",
+  "  52:	4481		add	r9, r0\n",
+  "  54:	44c8		add	r8, r9\n",
+  "  56:	4548		cmp	r0, r9\n",
+  "  58:	4588		cmp	r8, r1\n",
+  "  5a:	45c1		cmp	r9, r8\n",
+  "  5c:	4248   	   	negs	r0, r1\n",
+  "  5e:	4240   	   	negs	r0, r0\n",
+  "  60:	ea5f 0008  	movs.w	r0, r8\n",
+  "  64:	ea7f 0008  	mvns.w	r0, r8\n",
+  "  68:	eb01 0008 	add.w	r0, r1, r8\n",
+  "  6c:	eb11 0008 	adds.w	r0, r1, r8\n",
+  "  70:	ebb1 0008 	subs.w	r0, r1, r8\n",
+  "  74:	eb50 0008 	adcs.w	r0, r0, r8\n",
+  "  78:	eb70 0008 	sbcs.w	r0, r0, r8\n",
+  "  7c:	ea10 0008 	ands.w	r0, r0, r8\n",
+  "  80:	ea50 0008 	orrs.w	r0, r0, r8\n",
+  "  84:	ea90 0008 	eors.w	r0, r0, r8\n",
+  "  88:	ea30 0008 	bics.w	r0, r0, r8\n",
+  "  8c:	ea10 0f08 	tst.w	r0, r8\n",
+  "  90:	eb10 0f08 	cmn.w	r0, r8\n",
+  "  94:	f1d8 0000 	rsbs	r0, r8, #0\n",
+  "  98:	f1d8 0800 	rsbs	r8, r8, #0\n",
+  "  9c:	bf08       	it	eq\n",
+  "  9e:	ea7f 0001  	mvnseq.w	r0, r1\n",
+  "  a2:	bf08       	it	eq\n",
+  "  a4:	eb11 0002 	addseq.w	r0, r1, r2\n",
+  "  a8:	bf08       	it	eq\n",
+  "  aa:	ebb1 0002 	subseq.w	r0, r1, r2\n",
+  "  ae:	bf08       	it	eq\n",
+  "  b0:	eb50 0001 	adcseq.w	r0, r0, r1\n",
+  "  b4:	bf08       	it	eq\n",
+  "  b6:	eb70 0001 	sbcseq.w	r0, r0, r1\n",
+  "  ba:	bf08       	it	eq\n",
+  "  bc:	ea10 0001 	andseq.w	r0, r0, r1\n",
+  "  c0:	bf08       	it	eq\n",
+  "  c2:	ea50 0001 	orrseq.w	r0, r0, r1\n",
+  "  c6:	bf08       	it	eq\n",
+  "  c8:	ea90 0001 	eorseq.w	r0, r0, r1\n",
+  "  cc:	bf08       	it	eq\n",
+  "  ce:	ea30 0001 	bicseq.w	r0, r0, r1\n",
+  "  d2:	bf08       	it	eq\n",
+  "  d4:	43c8      	mvneq	r0, r1\n",
+  "  d6:	bf08       	it	eq\n",
+  "  d8:	1888      	addeq	r0, r1, r2\n",
+  "  da:	bf08       	it	eq\n",
+  "  dc:	1a88      	subeq	r0, r1, r2\n",
+  "  de:	bf08       	it	eq\n",
+  "  e0:	4148      	adceq	r0, r1\n",
+  "  e2:	bf08       	it	eq\n",
+  "  e4:	4188      	sbceq	r0, r1\n",
+  "  e6:	bf08       	it	eq\n",
+  "  e8:	4008      	andeq	r0, r1\n",
+  "  ea:	bf08       	it	eq\n",
+  "  ec:	4308      	orreq	r0, r1\n",
+  "  ee:	bf08       	it	eq\n",
+  "  f0:	4048      	eoreq	r0, r1\n",
+  "  f2:	bf08       	it	eq\n",
+  "  f4:	4388      	biceq	r0, r1\n",
+  "  f6:	4608      	mov	r0, r1\n",
+  "  f8:	43c8      	mvns	r0, r1\n",
+  "  fa:	4408      	add	r0, r1\n",
+  "  fc:	1888      	adds	r0, r1, r2\n",
+  "  fe:	1a88      	subs	r0, r1, r2\n",
+  " 100:	4148      	adcs	r0, r1\n",
+  " 102:	4188      	sbcs	r0, r1\n",
+  " 104:	4008      	ands	r0, r1\n",
+  " 106:	4308      	orrs	r0, r1\n",
+  " 108:	4048      	eors	r0, r1\n",
+  " 10a:	4388      	bics	r0, r1\n",
+  " 10c:	4641		mov	r1, r8\n",
+  " 10e:	4681		mov	r9, r0\n",
+  " 110:	46c8		mov	r8, r9\n",
+  " 112:	4441		add	r1, r8\n",
+  " 114:	4481		add	r9, r0\n",
+  " 116:	44c8		add	r8, r9\n",
+  " 118:	4248   	   	negs	r0, r1\n",
+  " 11a:	4240   	   	negs	r0, r0\n",
+  " 11c:	eb01 0c00 	add.w	ip, r1, r0\n",
   nullptr
 };
 const char* DataProcessingImmediateResults[] = {
@@ -66,6 +148,8 @@
   "  3a:	1f48      	subs	r0, r1, #5\n",
   "  3c:	2055      	movs	r0, #85	; 0x55\n",
   "  3e:	f07f 0055 	mvns.w	r0, #85	; 0x55\n",
+  "  42:	1d48      	adds  r0, r1, #5\n",
+  "  44:	1f48      	subs  r0, r1, #5\n",
   nullptr
 };
 const char* DataProcessingModifiedImmediateResults[] = {
@@ -100,13 +184,18 @@
   "   0:	0123      	lsls	r3, r4, #4\n",
   "   2:	0963      	lsrs	r3, r4, #5\n",
   "   4:	11a3      	asrs	r3, r4, #6\n",
-  "   6:	ea4f 13f4 	mov.w	r3, r4, ror #7\n",
-  "   a:	41e3      	rors	r3, r4\n",
-  "   c:	ea4f 1804 	mov.w	r8, r4, lsl #4\n",
-  "  10:	ea4f 1854 	mov.w	r8, r4, lsr #5\n",
-  "  14:	ea4f 18a4 	mov.w	r8, r4, asr #6\n",
-  "  18:	ea4f 18f4 	mov.w	r8, r4, ror #7\n",
-  "  1c:	ea4f 0834 	mov.w	r8, r4, rrx\n",
+  "   6:	ea5f 13f4 	movs.w	r3, r4, ror #7\n",
+  "   a:	ea5f 0334 	movs.w	r3, r4, rrx\n",
+  "   e:	ea4f 1304 	mov.w	r3, r4, lsl #4\n",
+  "  12:	ea4f 1354 	mov.w	r3, r4, lsr #5\n",
+  "  16:	ea4f 13a4 	mov.w	r3, r4, asr #6\n",
+  "  1a:	ea4f 13f4 	mov.w	r3, r4, ror #7\n",
+  "  1e:	ea4f 0334 	mov.w	r3, r4, rrx\n",
+  "  22:	ea5f 1804 	movs.w	r8, r4, lsl #4\n",
+  "  26:	ea5f 1854 	movs.w	r8, r4, lsr #5\n",
+  "  2a:	ea5f 18a4 	movs.w	r8, r4, asr #6\n",
+  "  2e:	ea5f 18f4 	movs.w	r8, r4, ror #7\n",
+  "  32:	ea5f 0834 	movs.w	r8, r4, rrx\n",
   nullptr
 };
 const char* BasicLoadResults[] = {
@@ -1511,7 +1600,7 @@
   " 7fc:	23fa      	movs	r3, #250	; 0xfa\n",
   " 7fe:	23fc      	movs	r3, #252	; 0xfc\n",
   " 800:	23fe      	movs	r3, #254	; 0xfe\n",
-  " 802:	0011      	movs	r1, r2\n",
+  " 802:	4611      	mov	r1, r2\n",
   nullptr
 };
 const char* Branch32Results[] = {
@@ -2541,7 +2630,7 @@
   " 800:	23fc      	movs	r3, #252	; 0xfc\n",
   " 802:	23fe      	movs	r3, #254	; 0xfe\n",
   " 804:	2300      	movs	r3, #0\n",
-  " 806:	0011      	movs	r1, r2\n",
+  " 806:	4611      	mov	r1, r2\n",
   nullptr
 };
 const char* CompareAndBranchMaxResults[] = {
@@ -2610,7 +2699,7 @@
   "  7c:	237a      	movs	r3, #122	; 0x7a\n",
   "  7e:	237c      	movs	r3, #124	; 0x7c\n",
   "  80:	237e      	movs	r3, #126	; 0x7e\n",
-  "  82:	0011      	movs	r1, r2\n",
+  "  82:	4611      	mov	r1, r2\n",
   nullptr
 };
 const char* CompareAndBranchRelocation16Results[] = {
@@ -2681,7 +2770,7 @@
   "  80:	237c      	movs	r3, #124	; 0x7c\n",
   "  82:	237e      	movs	r3, #126	; 0x7e\n",
   "  84:	2380      	movs	r3, #128	; 0x80\n",
-  "  86:	0011      	movs	r1, r2\n",
+  "  86:	4611      	mov	r1, r2\n",
   nullptr
 };
 const char* CompareAndBranchRelocation32Results[] = {
@@ -3712,7 +3801,7 @@
   " 802:	23fc      	movs	r3, #252	; 0xfc\n",
   " 804:	23fe      	movs	r3, #254	; 0xfe\n",
   " 806:	2300      	movs	r3, #0\n",
-  " 808:	0011      	movs	r1, r2\n",
+  " 808:	4611      	mov	r1, r2\n",
   nullptr
 };
 const char* MixedBranch32Results[] = {
@@ -4743,7 +4832,7 @@
   " 802:	23fe      	movs	r3, #254	; 0xfe\n",
   " 804:	2300      	movs	r3, #0\n",
   " 806:	f7ff bbfd 	b.w	4 <MixedBranch32+0x4>\n",
-  " 80a:	0011      	movs	r1, r2\n",
+  " 80a:	4611      	mov	r1, r2\n",
   nullptr
 };
 const char* ShiftsResults[] = {
@@ -4753,28 +4842,46 @@
   "   6:	4088      	lsls	r0, r1\n",
   "   8:	40c8      	lsrs	r0, r1\n",
   "   a:	4108      	asrs	r0, r1\n",
-  "   c:	ea4f 1841 	mov.w	r8, r1, lsl #5\n",
-  "  10:	ea4f 1058 	mov.w	r0, r8, lsr #5\n",
-  "  14:	ea4f 1861 	mov.w	r8, r1, asr #5\n",
-  "  18:	ea4f 1078 	mov.w	r0, r8, ror #5\n",
-  "  1c:	fa01 f002 	lsl.w	r0, r1, r2\n",
-  "  20:	fa21 f002 	lsr.w	r0, r1, r2\n",
-  "  24:	fa41 f002 	asr.w	r0, r1, r2\n",
-  "  28:	fa61 f002 	ror.w	r0, r1, r2\n",
-  "  2c:	fa01 f802 	lsl.w	r8, r1, r2\n",
-  "  30:	fa28 f002 	lsr.w	r0, r8, r2\n",
-  "  34:	fa41 f008 	asr.w	r0, r1, r8\n",
-  "  38:	ea5f 1841 	movs.w	r8, r1, lsl #5\n",
-  "  3c:	ea5f 1058 	movs.w	r0, r8, lsr #5\n",
-  "  40:	ea5f 1861 	movs.w	r8, r1, asr #5\n",
-  "  44:	ea5f 1078 	movs.w	r0, r8, ror #5\n",
-  "  48:	fa11 f002 	lsls.w	r0, r1, r2\n",
-  "  4c:	fa31 f002 	lsrs.w	r0, r1, r2\n",
-  "  50:	fa51 f002 	asrs.w	r0, r1, r2\n",
-  "  54:	fa71 f002 	rors.w	r0, r1, r2\n",
-  "  58:	fa11 f802 	lsls.w	r8, r1, r2\n",
-  "  5c:	fa38 f002 	lsrs.w	r0, r8, r2\n",
-  "  60:	fa51 f008 	asrs.w	r0, r1, r8\n",
+  "   c:	41c8      	rors	r0, r1\n",
+  "   e:	0148      	lsls	r0, r1, #5\n",
+  "  10:	0948      	lsrs	r0, r1, #5\n",
+  "  12:	1148      	asrs	r0, r1, #5\n",
+  "  14:	4088      	lsls	r0, r1\n",
+  "  16:	40c8      	lsrs	r0, r1\n",
+  "  18:	4108      	asrs	r0, r1\n",
+  "  1a:	41c8      	rors	r0, r1\n",
+  "  1c:	ea4f 1041 	mov.w	r0, r1, lsl #5\n",
+  "  20:	ea4f 1051 	mov.w	r0, r1, lsr #5\n",
+  "  24:	ea4f 1061 	mov.w	r0, r1, asr #5\n",
+  "  28:	fa00 f001 	lsl.w	r0, r0, r1\n",
+  "  2c:	fa20 f001 	lsr.w	r0, r0, r1\n",
+  "  30:	fa40 f001 	asr.w	r0, r0, r1\n",
+  "  34:	fa60 f001 	ror.w	r0, r0, r1\n",
+  "  38:	ea4f 1071 	mov.w	r0, r1, ror #5\n",
+  "  3c:	ea5f 1071 	movs.w	r0, r1, ror #5\n",
+  "  40:	ea4f 1071 	mov.w	r0, r1, ror #5\n",
+  "  44:	ea4f 1841 	mov.w	r8, r1, lsl #5\n",
+  "  48:	ea4f 1058 	mov.w	r0, r8, lsr #5\n",
+  "  4c:	ea4f 1861 	mov.w	r8, r1, asr #5\n",
+  "  50:	ea4f 1078 	mov.w	r0, r8, ror #5\n",
+  "  54:	fa01 f002 	lsl.w	r0, r1, r2\n",
+  "  58:	fa21 f002 	lsr.w	r0, r1, r2\n",
+  "  5c:	fa41 f002 	asr.w	r0, r1, r2\n",
+  "  60:	fa61 f002 	ror.w	r0, r1, r2\n",
+  "  64:	fa01 f802 	lsl.w	r8, r1, r2\n",
+  "  68:	fa28 f002 	lsr.w	r0, r8, r2\n",
+  "  6c:	fa41 f008 	asr.w	r0, r1, r8\n",
+  "  70:	ea5f 1841 	movs.w	r8, r1, lsl #5\n",
+  "  74:	ea5f 1058 	movs.w	r0, r8, lsr #5\n",
+  "  78:	ea5f 1861 	movs.w	r8, r1, asr #5\n",
+  "  7c:	ea5f 1078 	movs.w	r0, r8, ror #5\n",
+  "  80:	fa11 f002 	lsls.w	r0, r1, r2\n",
+  "  84:	fa31 f002 	lsrs.w	r0, r1, r2\n",
+  "  88:	fa51 f002 	asrs.w	r0, r1, r2\n",
+  "  8c:	fa71 f002 	rors.w	r0, r1, r2\n",
+  "  90:	fa11 f802 	lsls.w	r8, r1, r2\n",
+  "  94:	fa38 f002 	lsrs.w	r0, r8, r2\n",
+  "  98:	fa51 f008 	asrs.w	r0, r1, r8\n",
   nullptr
 };
 const char* LoadStoreRegOffsetResults[] = {