Lower a few basic ARM binops for i{8,16,32,64}.

Do basic lowering for add, sub, and, or, xor, mul.
We don't yet take advantage of commuting immediate operands
(e.g., use rsb to reverse subtract instead of sub) or
inverting immediate operands (use bic to bit clear instead
of using and).

The binary operations can set the flags register (e.g., to
have the carry bit for use with a subsequent adc
instruction). That is optional for the "data processing"
instructions.

I'm not yet able to compile 8bit.pnacl.ll and
64bit.pnacl.ll so 8-bit and 64-bit are not well tested yet.
Only tests are in the arith.ll file (like arith-opt.ll, but
assembled instead of testing the "verbose inst" output).

Not doing divide yet. ARM divide by 0 does not trap, but
PNaCl requires uniform behavior for such bad code. Thus,
in LLVM we insert a 0 check and would have to do the same.

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

Review URL: https://codereview.chromium.org/1127003003
diff --git a/src/IceTargetLoweringARM32.h b/src/IceTargetLoweringARM32.h
index 0c21c7c..88a8eb1 100644
--- a/src/IceTargetLoweringARM32.h
+++ b/src/IceTargetLoweringARM32.h
@@ -130,9 +130,28 @@
   // with minimal syntactic overhead, so that the lowering code can
   // look as close to assembly as practical.
 
+  void _add(Variable *Dest, Variable *Src0, Operand *Src1) {
+    Context.insert(InstARM32Add::create(Func, Dest, Src0, Src1));
+  }
+  void _adds(Variable *Dest, Variable *Src0, Operand *Src1) {
+    const bool SetFlags = true;
+    Context.insert(InstARM32Add::create(Func, Dest, Src0, Src1, SetFlags));
+  }
+  void _adc(Variable *Dest, Variable *Src0, Operand *Src1) {
+    Context.insert(InstARM32Adc::create(Func, Dest, Src0, Src1));
+  }
+  void _and(Variable *Dest, Variable *Src0, Operand *Src1) {
+    Context.insert(InstARM32And::create(Func, Dest, Src0, Src1));
+  }
+  void _eor(Variable *Dest, Variable *Src0, Operand *Src1) {
+    Context.insert(InstARM32Eor::create(Func, Dest, Src0, Src1));
+  }
   void _ldr(Variable *Dest, OperandARM32Mem *Addr) {
     Context.insert(InstARM32Ldr::create(Func, Dest, Addr));
   }
+  void _mla(Variable *Dest, Variable *Src0, Variable *Src1, Variable *Acc) {
+    Context.insert(InstARM32Mla::create(Func, Dest, Src0, Src1, Acc));
+  }
   // If Dest=nullptr is passed in, then a new variable is created,
   // marked as infinite register allocation weight, and returned
   // through the in/out Dest argument.
@@ -144,18 +163,40 @@
   }
   // The Operand can only be a 16-bit immediate or a ConstantRelocatable
   // (with an upper16 relocation).
-  void _movt(Variable *&Dest, Operand *Src0) {
+  void _movt(Variable *Dest, Operand *Src0) {
     Context.insert(InstARM32Movt::create(Func, Dest, Src0));
   }
-  void _movw(Variable *&Dest, Operand *Src0) {
+  void _movw(Variable *Dest, Operand *Src0) {
     Context.insert(InstARM32Movw::create(Func, Dest, Src0));
   }
-  void _mvn(Variable *&Dest, Operand *Src0) {
+  void _mul(Variable *Dest, Variable *Src0, Variable *Src1) {
+    Context.insert(InstARM32Mul::create(Func, Dest, Src0, Src1));
+  }
+  void _mvn(Variable *Dest, Operand *Src0) {
     Context.insert(InstARM32Mvn::create(Func, Dest, Src0));
   }
+  void _orr(Variable *Dest, Variable *Src0, Operand *Src1) {
+    Context.insert(InstARM32Orr::create(Func, Dest, Src0, Src1));
+  }
+  void _sbc(Variable *Dest, Variable *Src0, Operand *Src1) {
+    Context.insert(InstARM32Sbc::create(Func, Dest, Src0, Src1));
+  }
+  void _sub(Variable *Dest, Variable *Src0, Operand *Src1) {
+    Context.insert(InstARM32Sub::create(Func, Dest, Src0, Src1));
+  }
+  void _subs(Variable *Dest, Variable *Src0, Operand *Src1) {
+    const bool SetFlags = true;
+    Context.insert(InstARM32Sub::create(Func, Dest, Src0, Src1, SetFlags));
+  }
   void _ret(Variable *LR, Variable *Src0 = nullptr) {
     Context.insert(InstARM32Ret::create(Func, LR, Src0));
   }
+  void _umull(Variable *DestLo, Variable *DestHi, Variable *Src0,
+              Variable *Src1) {
+    Context.insert(InstARM32Umull::create(Func, DestLo, DestHi, Src0, Src1));
+    // Model the modification to the second dest as a fake def.
+    Context.insert(InstFakeDef::create(Func, DestHi, DestLo));
+  }
 
   bool UsesFramePointer;
   bool NeedsStackAlignment;