Add "sub immediate" instruction to the ARM integrated assembler.

BUG= https://code.google.com/p/nativeclient/issues/detail?id=4334
R=stichnot@chromium.org

Review URL: https://codereview.chromium.org/1388323003 .
diff --git a/src/IceAssemblerARM32.cpp b/src/IceAssemblerARM32.cpp
index 2195d4d..9972b44 100644
--- a/src/IceAssemblerARM32.cpp
+++ b/src/IceAssemblerARM32.cpp
@@ -28,6 +28,7 @@
 
 // The following define individual bits.
 static constexpr uint32_t B0 = 1;
+static constexpr uint32_t B1 = 1 << 1;
 static constexpr uint32_t B2 = 1 << 2;
 static constexpr uint32_t B3 = 1 << 3;
 static constexpr uint32_t B4 = 1 << 4;
@@ -220,4 +221,34 @@
   UnimplementedError(Ctx->getFlags());
 }
 
+void ARM32::AssemblerARM32::sub(const Operand *OpRd, const Operand *OpRn,
+                                const Operand *OpSrc1, bool SetFlags,
+                                CondARM32::Cond Cond) {
+  // Note: Loop is used so that we can short circuit using break;
+  do {
+    uint32_t Rd;
+    if (decode(OpRd, Rd) != DecodedAsRegister)
+      break;
+    uint32_t Rn;
+    if (decode(OpRn, Rn) != DecodedAsRegister)
+      break;
+    uint32_t Src1Value;
+    // TODO(kschimpf) Other possible decodings of add.
+    if (decode(OpSrc1, Src1Value) == DecodedAsRotatedImm8) {
+      // Sub (Immediate): See ARM section A8.8.222, rule A1.
+      // cccc0010010snnnnddddiiiiiiiiiiii where cccc=Cond, dddd=Rd, nnnn=Rn,
+      // s=SetFlags and iiiiiiiiiiii=Src1Value
+      if (!isConditionDefined(Cond) || (Rd == RegARM32::Reg_pc && SetFlags) ||
+          (Rn == RegARM32::Reg_lr) || (Rn == RegARM32::Reg_pc && SetFlags))
+        // Conditions of rule violated.
+        break;
+      uint32_t Add = B1; // 0010
+      uint32_t InstType = 1;
+      emitType01(Cond, InstType, Add, SetFlags, Rn, Rd, Src1Value);
+      return;
+    }
+  } while (0);
+  UnimplementedError(Ctx->getFlags());
+}
+
 } // end of namespace Ice
diff --git a/src/IceAssemblerARM32.h b/src/IceAssemblerARM32.h
index 839b30e..d4e2c0a 100644
--- a/src/IceAssemblerARM32.h
+++ b/src/IceAssemblerARM32.h
@@ -107,6 +107,9 @@
 
   void bx(RegARM32::GPRRegister Rm, CondARM32::Cond Cond = CondARM32::AL);
 
+  void sub(const Operand *OpRd, const Operand *OpRn, const Operand *OpSrc1,
+           bool SetFlags, CondARM32::Cond Cond);
+
   static bool classof(const Assembler *Asm) {
     return Asm->getKind() == Asm_ARM32;
   }
diff --git a/src/IceInstARM32.cpp b/src/IceInstARM32.cpp
index b637472..c4d9ebc 100644
--- a/src/IceInstARM32.cpp
+++ b/src/IceInstARM32.cpp
@@ -330,6 +330,12 @@
   Asm->add(getDest(), getSrc(0), getSrc(1), SetFlags, getPredicate());
 }
 
+template <>
+void InstARM32ThreeAddrGPR<InstARM32::Sub>::emitIAS(const Cfg *Func) const {
+  ARM32::AssemblerARM32 *Asm = Func->getAssembler<ARM32::AssemblerARM32>();
+  Asm->sub(getDest(), getSrc(0), getSrc(1), SetFlags, getPredicate());
+}
+
 InstARM32Call::InstARM32Call(Cfg *Func, Variable *Dest, Operand *CallTarget)
     : InstARM32(Func, InstARM32::Call, 1, Dest) {
   HasSideEffects = true;
diff --git a/tests_lit/assembler/arm32/add.ll b/tests_lit/assembler/arm32/add.ll
index 656137c..c6b7d28 100644
--- a/tests_lit/assembler/arm32/add.ll
+++ b/tests_lit/assembler/arm32/add.ll
@@ -14,11 +14,11 @@
 }
 
 ; ASM-LABEL: add1ToR0:
-; ASM:	add	r0, r0, #1
-; ASM:	bx	lr
+; ASM:  add     r0, r0, #1
+; ASM:  bx      lr
 
 ; IASM-LABEL: add1ToR0:
-; IASM:	     .byte 0x1
+; IASM:      .byte 0x1
 ; IASM-NEXT: .byte 0x0
 ; IASM-NEXT: .byte 0x80
 ; IASM-NEXT: .byte 0xe2
diff --git a/tests_lit/assembler/arm32/sub.ll b/tests_lit/assembler/arm32/sub.ll
new file mode 100644
index 0000000..e319333
--- /dev/null
+++ b/tests_lit/assembler/arm32/sub.ll
@@ -0,0 +1,25 @@
+; Show that we know how to translate instruction sub.
+; TODO(kschimpf) Currently only know how to test subtract 1 from R0.
+
+; NOTE: We use -O2 to get rid of memory stores.
+
+; RUN: %p2i --filetype=asm -i %s --target=arm32 --args -O2 \
+; RUN:   | FileCheck %s --check-prefix=ASM
+; RUN: %p2i --filetype=iasm -i %s --target=arm32 --args -O2 \
+; RUN:   | FileCheck %s --check-prefix=IASM
+
+define internal i32 @sub1FromR0(i32 %p) {
+  %v = sub i32 %p, 1
+  ret i32 %v
+}
+
+; ASM-LABEL: sub1FromR0:
+; ASM:	sub	r0, r0, #1
+; ASM:	bx	lr
+
+; IASM-LABEL: sub1FromR0:
+; IASM:	     .byte 0x1
+; IASM-NEXT: .byte 0x0
+; IASM-NEXT: .byte 0x40
+; IASM-NEXT: .byte 0xe2
+