Add BIC(register) and BIC(immediate) to ARM integrated assembler.

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

Review URL: https://codereview.chromium.org/1415943009 .
diff --git a/src/DartARM32/assembler_arm.cc b/src/DartARM32/assembler_arm.cc
index 180a182..410edcd 100644
--- a/src/DartARM32/assembler_arm.cc
+++ b/src/DartARM32/assembler_arm.cc
@@ -301,15 +301,17 @@
 }
 
 
+#if 0
+// Moved to ARM32::AssemblerARM32::bic();
 void Assembler::bic(Register rd, Register rn, Operand o, Condition cond) {
   EmitType01(cond, o.type(), BIC, 0, rn, rd, o);
 }
 
-
+// Moved to ARM32::AssemblerARM32::bic();
 void Assembler::bics(Register rd, Register rn, Operand o, Condition cond) {
   EmitType01(cond, o.type(), BIC, 1, rn, rd, o);
 }
-
+#endif
 
 void Assembler::mvn(Register rd, Operand o, Condition cond) {
   EmitType01(cond, o.type(), MVN, 0, R0, rd, o);
diff --git a/src/DartARM32/assembler_arm.h b/src/DartARM32/assembler_arm.h
index ffc360b..1cedcbc 100644
--- a/src/DartARM32/assembler_arm.h
+++ b/src/DartARM32/assembler_arm.h
@@ -501,8 +501,11 @@
   void movs(Register rd, Operand o, Condition cond = AL);
 #endif
 
+#if 0
+  // Moved to ARM32::IceAssemblerARM32::bic()
   void bic(Register rd, Register rn, Operand o, Condition cond = AL);
   void bics(Register rd, Register rn, Operand o, Condition cond = AL);
+#endif
 
   void mvn(Register rd, Operand o, Condition cond = AL);
   void mvns(Register rd, Operand o, Condition cond = AL);
diff --git a/src/IceAssemblerARM32.cpp b/src/IceAssemblerARM32.cpp
index b6a4fc8..99be795 100644
--- a/src/IceAssemblerARM32.cpp
+++ b/src/IceAssemblerARM32.cpp
@@ -563,6 +563,24 @@
   emitInst(Encoding);
 }
 
+void AssemblerARM32::bic(const Operand *OpRd, const Operand *OpRn,
+                         const Operand *OpSrc1, bool SetFlags,
+                         CondARM32::Cond Cond) {
+  // BIC (register) - ARM section A8.8.22, encoding A1:
+  //   bic{s}<c> <Rd>, <Rn>, <Rm>{, <shift>}
+  //
+  // cccc0001110snnnnddddiiiiitt0mmmm where cccc=Cond, dddd=Rd, nnnn=Rn,
+  // mmmm=Rm, iiiii=Shift, tt=ShiftKind, and s=SetFlags.
+  //
+  // BIC (immediate) - ARM section A8.8.21, encoding A1:
+  //   bic{s}<c> <Rd>, <Rn>, #<RotatedImm8>
+  //
+  // cccc0011110snnnnddddiiiiiiiiiiii where cccc=Cond, dddd=Rn, nnnn=Rn,
+  // s=SetFlags, and iiiiiiiiiiii=Src1Value defining RotatedImm8.
+  IValueT Opcode = B3 | B2 | B1; // i.e. 1110
+  emitType01(Opcode, OpRd, OpRn, OpSrc1, SetFlags, Cond);
+}
+
 void AssemblerARM32::bx(RegARM32::GPRRegister Rm, CondARM32::Cond Cond) {
   // BX - ARM section A8.8.27, encoding A1:
   //   bx<c> <Rm>
diff --git a/src/IceAssemblerARM32.h b/src/IceAssemblerARM32.h
index 514cb78..1a8edf1 100644
--- a/src/IceAssemblerARM32.h
+++ b/src/IceAssemblerARM32.h
@@ -152,6 +152,9 @@
 
   void cmp(const Operand *OpRn, const Operand *OpSrc1, CondARM32::Cond Cond);
 
+  void bic(const Operand *OpRd, const Operand *OpRn, const Operand *OpSrc1,
+           bool SetFlags, CondARM32::Cond Cond);
+
   void eor(const Operand *OpRd, const Operand *OpRn, const Operand *OpSrc1,
            bool SetFlags, CondARM32::Cond Cond);
 
diff --git a/src/IceInstARM32.cpp b/src/IceInstARM32.cpp
index 1697ee8..a5edfc9 100644
--- a/src/IceInstARM32.cpp
+++ b/src/IceInstARM32.cpp
@@ -365,6 +365,13 @@
     emitUsingTextFixup(Func);
 }
 
+template <> void InstARM32Bic::emitIAS(const Cfg *Func) const {
+  ARM32::AssemblerARM32 *Asm = Func->getAssembler<ARM32::AssemblerARM32>();
+  Asm->bic(getDest(), getSrc(0), getSrc(1), SetFlags, getPredicate());
+  if (Asm->needsTextFixup())
+    emitUsingTextFixup(Func);
+}
+
 template <> void InstARM32Eor::emitIAS(const Cfg *Func) const {
   ARM32::AssemblerARM32 *Asm = Func->getAssembler<ARM32::AssemblerARM32>();
   Asm->eor(getDest(), getSrc(0), getSrc(1), SetFlags, getPredicate());
diff --git a/tests_lit/assembler/arm32/bic.ll b/tests_lit/assembler/arm32/bic.ll
new file mode 100644
index 0000000..d30a087
--- /dev/null
+++ b/tests_lit/assembler/arm32/bic.ll
@@ -0,0 +1,89 @@
+; Show that we know how to translate bic.
+
+; NOTE: We use -O2 to get rid of memory stores.
+
+; REQUIRES: allow_dump
+
+; Compile using standalone assembler.
+; RUN: %p2i --filetype=asm -i %s --target=arm32 --args -O2 \
+; RUN:   | FileCheck %s --check-prefix=ASM
+
+; Show bytes in assembled standalone code.
+; RUN: %p2i --filetype=asm -i %s --target=arm32 --assemble --disassemble \
+; RUN:   --args -O2 | FileCheck %s --check-prefix=DIS
+
+; Compile using integrated assembler.
+; RUN: %p2i --filetype=iasm -i %s --target=arm32 --args -O2 \
+; RUN:   | FileCheck %s --check-prefix=IASM
+
+; Show bytes in assembled integrated code.
+; RUN: %p2i --filetype=iasm -i %s --target=arm32 --assemble --disassemble \
+; RUN:   --args -O2 | FileCheck %s --check-prefix=DIS
+
+define internal i32 @AllocBigAlign() {
+  %addr = alloca i8, align 32
+  %v = ptrtoint i8* %addr to i32
+  ret i32 %v
+}
+
+; ASM-LABEL:AllocBigAlign:
+; ASM:.LAllocBigAlign$__0:
+; ASM:  push    {fp}
+; ASM:  mov     fp, sp
+; ASM:  sub     sp, sp, #12
+; ASM:  bic     sp, sp, #31
+; ASM:  sub     sp, sp, #32
+; ASM:  mov     r0, sp
+; ASM:  mov     sp, fp
+; ASM:  pop     {fp}
+; ASM:  # fp = def.pseudo 
+; ASM:  bx      lr
+
+; DIS-LABEL:00000000 <AllocBigAlign>:
+; DIS-NEXT:   0:        e52db004
+; DIS-NEXT:   4:        e1a0b00d
+; DIS-NEXT:   8:        e24dd00c
+; DIS-NEXT:   c:        e3cdd01f
+; DIS-NEXT:  10:        e24dd020
+; DIS-NEXT:  14:        e1a0000d
+; DIS-NEXT:  18:        e1a0d00b
+; DIS-NEXT:  1c:        e49db004
+; DIS-NEXT:  20:        e12fff1e
+
+; IASM-LABEL:AllocBigAlign:
+; IASM-NEXT:.LAllocBigAlign$__0:
+; IASM:         push    {fp}
+; IASM:         .byte 0xd
+; IASM-NEXT:    .byte 0xb0
+; IASM-NEXT:    .byte 0xa0
+; IASM-NEXT:    .byte 0xe1
+
+; IASM:         .byte 0xc
+; IASM-NEXT:    .byte 0xd0
+; IASM-NEXT:    .byte 0x4d
+; IASM-NEXT:    .byte 0xe2
+
+; IASM:         .byte 0x1f
+; IASM-NEXT:    .byte 0xd0
+; IASM-NEXT:    .byte 0xcd
+; IASM-NEXT:    .byte 0xe3
+
+; IASM:         .byte 0x20
+; IASM-NEXT:    .byte 0xd0
+; IASM-NEXT:    .byte 0x4d
+; IASM-NEXT:    .byte 0xe2
+
+; IASM:         .byte 0xd
+; IASM-NEXT:    .byte 0x0
+; IASM-NEXT:    .byte 0xa0
+; IASM-NEXT:    .byte 0xe1
+
+; IASM:         .byte 0xb
+; IASM-NEXT:    .byte 0xd0
+; IASM-NEXT:    .byte 0xa0
+; IASM-NEXT:    .byte 0xe1
+; IASM:         pop     {fp}
+; IASM:         .byte 0x1e
+; IASM-NEXT:    .byte 0xff
+; IASM-NEXT:    .byte 0x2f
+; IASM-NEXT:    .byte 0xe1