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

Also does some bikeshed clean ups. In particualr, the (ARM)
instruction method emitIAS only needs to choose the applicable ARM
instruction, and then passes the corresponding operands to the
corresponding instruction method of the assembler. The assembler
method then extracts the appropriate data from the operands, and
decides which rule to apply for the corresponding arm instruction.

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

Review URL: https://codereview.chromium.org/1407613002 .
diff --git a/src/DartARM32/assembler_arm.cc b/src/DartARM32/assembler_arm.cc
index ec942d0..91c8d88 100644
--- a/src/DartARM32/assembler_arm.cc
+++ b/src/DartARM32/assembler_arm.cc
@@ -208,6 +208,8 @@
 }
 
 
+#if 0
+// Moved to IceAssemberARM32::add.
 void Assembler::add(Register rd, Register rn, Operand o, Condition cond) {
   EmitType01(cond, o.type(), ADD, 0, rn, rd, o);
 }
@@ -216,6 +218,7 @@
 void Assembler::adds(Register rd, Register rn, Operand o, Condition cond) {
   EmitType01(cond, o.type(), ADD, 1, rn, rd, o);
 }
+#endif
 
 
 void Assembler::subs(Register rd, Register rn, Operand o, Condition cond) {
diff --git a/src/DartARM32/assembler_arm.h b/src/DartARM32/assembler_arm.h
index 31c93c4..d5a405f 100644
--- a/src/DartARM32/assembler_arm.h
+++ b/src/DartARM32/assembler_arm.h
@@ -140,7 +140,7 @@
   }
 
 #if 0
-  // Moved to AssemblerARM32::encodeImm12FromFlexImm.
+  // Moved to decode in IceAssemblerARM32.cpp
   // Data-processing operands - Rotated immediate.
   Operand(uint32_t rotate, uint32_t immed8) {
     ASSERT((rotate < (1 << kRotateBits)) && (immed8 < (1 << kImmed8Bits)));
@@ -149,11 +149,14 @@
   }
 #endif
 
+#if 0
+  // Moved to decode in IceAssemblerARM32.cpp
   // Data-processing operands - Register.
   explicit Operand(Register rm) {
     type_ = 0;
     encoding_ = static_cast<uint32_t>(rm);
   }
+#endif
 
   // Data-processing operands - Logical shift/rotate by immediate.
   Operand(Register rm, Shift shift, uint32_t shift_imm) {
@@ -443,9 +446,12 @@
   void rsb(Register rd, Register rn, Operand o, Condition cond = AL);
   void rsbs(Register rd, Register rn, Operand o, Condition cond = AL);
 
+#if 0
+  // Moved to IceAssemblerARM32::mov
   void add(Register rd, Register rn, Operand o, Condition cond = AL);
 
   void adds(Register rd, Register rn, Operand o, Condition cond = AL);
+#endif
 
   void adc(Register rd, Register rn, Operand o, Condition cond = AL);
 
@@ -469,11 +475,10 @@
   void orrs(Register rd, Register rn, Operand o, Condition cond = AL);
 
 #if 0
-  // Moved to IceAssemblerARM32::mov(..FlexImm..)
-  // TODO(kschimpf) other forms of move.
+  // Moved to IceAssemblerARM32::mov
   void mov(Register rd, Operand o, Condition cond = AL);
-#endif
   void movs(Register rd, Operand o, Condition cond = AL);
+#endif
 
   void bic(Register rd, Register rn, Operand o, Condition cond = AL);
   void bics(Register rd, Register rn, Operand o, Condition cond = AL);
diff --git a/src/IceAssemblerARM32.cpp b/src/IceAssemblerARM32.cpp
index 16f1e4a..2195d4d 100644
--- a/src/IceAssemblerARM32.cpp
+++ b/src/IceAssemblerARM32.cpp
@@ -22,7 +22,9 @@
 
 #include "IceAssemblerARM32.h"
 
-namespace Ice {
+namespace {
+
+using namespace Ice;
 
 // The following define individual bits.
 static constexpr uint32_t B0 = 1;
@@ -50,9 +52,6 @@
 static constexpr uint32_t kRotateBits = 4;
 static constexpr uint32_t kRotateShift = 8;
 
-// Types of instructions.
-static constexpr uint32_t kInstTypeImmediate = 1;
-
 inline uint32_t encodeBool(bool b) { return b ? 1 : 0; }
 
 inline uint32_t encodeGPRRegister(RegARM32::GPRRegister Rn) {
@@ -75,14 +74,33 @@
   return static_cast<uint32_t>(Cond);
 }
 
-// Converts rotated immediate into imm12.
-inline uint32_t encodeImm12FromFlexImm(const OperandARM32FlexImm &FlexImm) {
-  uint32_t Immed8 = FlexImm.getImm();
-  uint32_t Rotate = FlexImm.getRotateAmt();
-  assert((Rotate < (1 << kRotateBits)) && (Immed8 < (1 << kImmed8Bits)));
-  return (Rotate << kRotateShift) | (Immed8 << kImmed8Shift);
+// The way an operand was decoded in function decode below.
+enum DecodedResult {
+  CantDecode = 0, // I.e. will fail in test.
+  DecodedAsRegister,
+  DecodedAsRotatedImm8
+};
+
+DecodedResult decode(const Operand *Opnd, uint32_t &Value) {
+  if (const auto *Var = llvm::dyn_cast<Variable>(Opnd)) {
+    if (Var->hasReg()) {
+      Value = Var->getRegNum();
+      return DecodedAsRegister;
+    }
+  } else if (const auto *FlexImm = llvm::dyn_cast<OperandARM32FlexImm>(Opnd)) {
+    uint32_t Immed8 = FlexImm->getImm();
+    uint32_t Rotate = FlexImm->getRotateAmt();
+    assert((Rotate < (1 << kRotateBits)) && (Immed8 < (1 << kImmed8Bits)));
+    Value = (Rotate << kRotateShift) | (Immed8 << kImmed8Shift);
+    return DecodedAsRotatedImm8;
+  }
+  return CantDecode;
 }
 
+} // end of anonymous namespace
+
+namespace Ice {
+
 Label *ARM32::AssemblerARM32::getOrCreateLabel(SizeT Number,
                                                LabelVector &Labels) {
   Label *L = nullptr;
@@ -120,6 +138,7 @@
                                        uint32_t Rd, uint32_t Imm12) {
   assert(isGPRRegisterDefined(Rd));
   assert(Cond != CondARM32::kNone);
+  AssemblerBuffer::EnsureCapacity ensured(&Buffer);
   uint32_t Encoding = encodeCondition(Cond) << kConditionShift |
                       (Type << kTypeShift) | (Opcode << kOpcodeShift) |
                       (encodeBool(SetCc) << kSShift) | (Rn << kRnShift) |
@@ -127,6 +146,36 @@
   emitInst(Encoding);
 }
 
+void ARM32::AssemblerARM32::add(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) {
+      // ADD (Immediate): See ARM section A8.8.5, rule A1.
+      // cccc0010100snnnnddddiiiiiiiiiiii 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 = B2; // 0100
+      uint32_t InstType = 1;
+      emitType01(Cond, InstType, Add, SetFlags, Rn, Rd, Src1Value);
+      return;
+    }
+  } while (0);
+  UnimplementedError(Ctx->getFlags());
+}
+
 void ARM32::AssemblerARM32::bkpt(uint16_t imm16) {
   AssemblerBuffer::EnsureCapacity ensured(&Buffer);
   uint32_t Encoding = (CondARM32::AL << kConditionShift) | B24 | B21 |
@@ -145,17 +194,30 @@
   emitInst(Encoding);
 }
 
-void ARM32::AssemblerARM32::mov(RegARM32::GPRRegister Rd,
-                                const OperandARM32FlexImm &FlexImm,
+void ARM32::AssemblerARM32::mov(const Operand *OpRd, const Operand *OpSrc,
                                 CondARM32::Cond Cond) {
-  // cccc0011101s0000ddddiiiiiiiiiiii (ARM section A8.8.102, encoding A1)
-  assert(isConditionDefined(Cond));
-  AssemblerBuffer::EnsureCapacity ensured(&Buffer);
-  bool SetCc = false; // Note: We don't use movs in this assembler.
-  uint32_t Rn = 0;
-  uint32_t Mov = B3 | B2 | B0; // 1101.
-  emitType01(Cond, kInstTypeImmediate, Mov, SetCc, Rn, encodeGPRRegister(Rd),
-             encodeImm12FromFlexImm(FlexImm));
+  // Note: Loop is used so that we can short ciruit using break;
+  do {
+    uint32_t Rd;
+    if (decode(OpRd, Rd) != DecodedAsRegister)
+      break;
+    uint32_t Src;
+    // TODO(kschimpf) Handle other forms of mov.
+    if (decode(OpSrc, Src) == DecodedAsRotatedImm8) {
+      // cccc0011101s0000ddddiiiiiiiiiiii (ARM section A8.8.102, encoding A1)
+      // Note: We don't use movs in this assembler.
+      constexpr bool SetFlags = false;
+      if (!isConditionDefined(Cond) || (Rd == RegARM32::Reg_pc && SetFlags))
+        // Conditions of rule violated.
+        break;
+      uint32_t Rn = 0;
+      uint32_t Mov = B3 | B2 | B0; // 1101.
+      uint32_t InstType = 1;
+      emitType01(Cond, InstType, Mov, SetFlags, Rn, Rd, Src);
+      return;
+    }
+  } while (0);
+  UnimplementedError(Ctx->getFlags());
 }
 
 } // end of namespace Ice
diff --git a/src/IceAssemblerARM32.h b/src/IceAssemblerARM32.h
index f3885bf..839b30e 100644
--- a/src/IceAssemblerARM32.h
+++ b/src/IceAssemblerARM32.h
@@ -93,12 +93,17 @@
     (void)Kind;
     llvm_unreachable("Not yet implemented.");
   }
+
   void bind(Label *label);
 
+  // List of instructions implemented by integrated assembler.
+
+  void add(const Operand *OpRd, const Operand *OpRn, const Operand *OpSrc1,
+           bool SetFlags, CondARM32::Cond Cond);
+
   void bkpt(uint16_t Imm16);
 
-  void mov(RegARM32::GPRRegister Rd, const OperandARM32FlexImm &FlexImm,
-           CondARM32::Cond Cond);
+  void mov(const Operand *OpRd, const Operand *OpSrc, CondARM32::Cond Cond);
 
   void bx(RegARM32::GPRRegister Rm, CondARM32::Cond Cond = CondARM32::AL);
 
diff --git a/src/IceInstARM32.cpp b/src/IceInstARM32.cpp
index 7e510ca..b637472 100644
--- a/src/IceInstARM32.cpp
+++ b/src/IceInstARM32.cpp
@@ -318,6 +318,18 @@
   return Found;
 }
 
+template <InstARM32::InstKindARM32 K>
+void InstARM32ThreeAddrGPR<K>::emitIAS(const Cfg *Func) const {
+  (void)Func;
+  UnimplementedError(Func->getContext()->getFlags());
+}
+
+template <>
+void InstARM32ThreeAddrGPR<InstARM32::Add>::emitIAS(const Cfg *Func) const {
+  ARM32::AssemblerARM32 *Asm = Func->getAssembler<ARM32::AssemblerARM32>();
+  Asm->add(getDest(), getSrc(0), getSrc(1), SetFlags, getPredicate());
+}
+
 InstARM32Call::InstARM32Call(Cfg *Func, Variable *Dest, Operand *CallTarget)
     : InstARM32(Func, InstARM32::Call, 1, Dest) {
   HasSideEffects = true;
@@ -605,11 +617,8 @@
       const bool CoreVFPMove = isMoveBetweenCoreAndVFPRegisters(Dest, Src0);
       if (DestIsVector || DestIsScalarFP || CoreVFPMove)
         break;
-      if (const auto *FlexImm = llvm::dyn_cast<OperandARM32FlexImm>(Src0)) {
-        Asm->mov(static_cast<RegARM32::GPRRegister>(Dest->getRegNum()),
-                 *FlexImm, getPredicate());
-        return;
-      }
+      Asm->mov(Dest, Src0, getPredicate());
+      return;
     }
   } while (0);
   llvm_unreachable("not yet implemented");
@@ -1423,4 +1432,25 @@
   }
 }
 
+// Force instantition of template classes
+template class InstARM32ThreeAddrGPR<InstARM32::Adc>;
+template class InstARM32ThreeAddrGPR<InstARM32::Add>;
+template class InstARM32ThreeAddrGPR<InstARM32::And>;
+template class InstARM32ThreeAddrGPR<InstARM32::Asr>;
+template class InstARM32ThreeAddrGPR<InstARM32::Bic>;
+template class InstARM32ThreeAddrGPR<InstARM32::Eor>;
+template class InstARM32ThreeAddrGPR<InstARM32::Lsl>;
+template class InstARM32ThreeAddrGPR<InstARM32::Lsr>;
+template class InstARM32ThreeAddrGPR<InstARM32::Mul>;
+template class InstARM32ThreeAddrGPR<InstARM32::Orr>;
+template class InstARM32ThreeAddrGPR<InstARM32::Rsb>;
+template class InstARM32ThreeAddrGPR<InstARM32::Sbc>;
+template class InstARM32ThreeAddrGPR<InstARM32::Sdiv>;
+template class InstARM32ThreeAddrGPR<InstARM32::Sub>;
+template class InstARM32ThreeAddrGPR<InstARM32::Udiv>;
+template class InstARM32ThreeAddrFP<InstARM32::Vadd>;
+template class InstARM32ThreeAddrFP<InstARM32::Vdiv>;
+template class InstARM32ThreeAddrFP<InstARM32::Vmul>;
+template class InstARM32ThreeAddrFP<InstARM32::Vsub>;
+
 } // end of namespace Ice
diff --git a/src/IceInstARM32.h b/src/IceInstARM32.h
index 680c30a..461fa48 100644
--- a/src/IceInstARM32.h
+++ b/src/IceInstARM32.h
@@ -588,10 +588,7 @@
       return;
     emitThreeAddr(Opcode, this, Func, SetFlags);
   }
-  void emitIAS(const Cfg *Func) const override {
-    (void)Func;
-    llvm::report_fatal_error("Not yet implemented");
-  }
+  void emitIAS(const Cfg *Func) const override;
   void dump(const Cfg *Func) const override {
     if (!BuildDefs::dump())
       return;
diff --git a/tests_lit/assembler/arm32/add.ll b/tests_lit/assembler/arm32/add.ll
new file mode 100644
index 0000000..656137c
--- /dev/null
+++ b/tests_lit/assembler/arm32/add.ll
@@ -0,0 +1,25 @@
+; Show that we know how to translate add.
+; TODO(kschimpf) Currently only know how to test add 1 to 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 @add1ToR0(i32 %p) {
+  %v = add i32 %p, 1
+  ret i32 %v
+}
+
+; ASM-LABEL: add1ToR0:
+; ASM:	add	r0, r0, #1
+; ASM:	bx	lr
+
+; IASM-LABEL: add1ToR0:
+; IASM:	     .byte 0x1
+; IASM-NEXT: .byte 0x0
+; IASM-NEXT: .byte 0x80
+; IASM-NEXT: .byte 0xe2
+