Add VAND to the integrated ARM assembler.

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

Review URL: https://codereview.chromium.org/1657353002 .
diff --git a/src/DartARM32/assembler_arm.cc b/src/DartARM32/assembler_arm.cc
index 0ad735c..54bc3d8 100644
--- a/src/DartARM32/assembler_arm.cc
+++ b/src/DartARM32/assembler_arm.cc
@@ -1316,11 +1316,12 @@
   EmitSIMDqqq(B21 | B20 | B8 | B4, kByte, qd, qn, qm);
 }
 
-
+#if 0
+// Moved to ARM32::AssemblerARM32::vandq()
 void Assembler::vandq(QRegister qd, QRegister qn, QRegister qm) {
   EmitSIMDqqq(B8 | B4, kByte, qd, qn, qm);
 }
-
+#endif
 
 void Assembler::vmvnq(QRegister qd, QRegister qm) {
   EmitSIMDqqq(B25 | B24 | B23 | B10 | B8 | B7, kWordPair, qd, Q0, qm);
diff --git a/src/DartARM32/assembler_arm.h b/src/DartARM32/assembler_arm.h
index 8c1b901..a933214 100644
--- a/src/DartARM32/assembler_arm.h
+++ b/src/DartARM32/assembler_arm.h
@@ -719,7 +719,10 @@
   void veorq(QRegister qd, QRegister qn, QRegister qm);
   void vorrq(QRegister qd, QRegister qn, QRegister qm);
   void vornq(QRegister qd, QRegister qn, QRegister qm);
+#if 0
+  // Moved to Arm32::AssemblerARM32::vandq().
   void vandq(QRegister qd, QRegister qn, QRegister qm);
+#endif
   void vmvnq(QRegister qd, QRegister qm);
 
   void vceqqi(OperandSize sz, QRegister qd, QRegister qn, QRegister qm);
diff --git a/src/IceAssemblerARM32.cpp b/src/IceAssemblerARM32.cpp
index 9325b4e..4049920 100644
--- a/src/IceAssemblerARM32.cpp
+++ b/src/IceAssemblerARM32.cpp
@@ -2188,6 +2188,18 @@
   emitVFPddd(Cond, VadddOpcode, OpDd, OpDn, OpDm, Vaddd);
 }
 
+void AssemblerARM32::vandq(const Operand *OpQd, const Operand *OpQm,
+                           const Operand *OpQn) {
+  // VAND (register) - ARM section A8.8.287, encoding A1:
+  //   vand.<dt> <Qd>, <Qn>, <Qm>
+  //
+  // 111100100D00nnn0ddd00001N1M1mmm0 where Dddd=OpQd, Nnnn=OpQm, and Mmmm=OpQm.
+  constexpr const char *Vandqi = "vandqi";
+  constexpr IValueT VandqiOpcode = B8 | B4;
+  constexpr Type ElmtTy = IceType_i8;
+  emitSIMDqqq(VandqiOpcode, ElmtTy, OpQd, OpQm, OpQn, Vandqi);
+}
+
 void AssemblerARM32::vcmpd(const Operand *OpDd, const Operand *OpDm,
                            CondARM32::Cond Cond) {
   constexpr const char *Vcmpd = "vcmpd";
diff --git a/src/IceAssemblerARM32.h b/src/IceAssemblerARM32.h
index 488f84e..ee5e9c0 100644
--- a/src/IceAssemblerARM32.h
+++ b/src/IceAssemblerARM32.h
@@ -325,6 +325,8 @@
   // Float vector add.
   void vaddqf(const Operand *OpQd, const Operand *OpQm, const Operand *OpQn);
 
+  void vandq(const Operand *OpQd, const Operand *OpQm, const Operand *OpQn);
+
   void vcmpd(const Operand *OpDd, const Operand *OpDm, CondARM32::Cond cond);
 
   // Second argument of compare is zero (+0.0).
diff --git a/src/IceInstARM32.cpp b/src/IceInstARM32.cpp
index 5a829d7..843e0f5 100644
--- a/src/IceInstARM32.cpp
+++ b/src/IceInstARM32.cpp
@@ -629,7 +629,7 @@
   case IceType_v16i1:
   case IceType_NUM:
     llvm::report_fatal_error("Vadd not defined on type " +
-                             std::string(typeString(DestTy)));
+                             typeIceString(DestTy));
     break;
   case IceType_v16i8:
   case IceType_v8i16:
@@ -640,10 +640,10 @@
     Asm->vaddqf(Dest, getSrc(0), getSrc(1));
     break;
   case IceType_f32:
-    Asm->vadds(getDest(), getSrc(0), getSrc(1), CondARM32::AL);
+    Asm->vadds(Dest, getSrc(0), getSrc(1), CondARM32::AL);
     break;
   case IceType_f64:
-    Asm->vaddd(getDest(), getSrc(0), getSrc(1), CondARM32::AL);
+    Asm->vaddd(Dest, getSrc(0), getSrc(1), CondARM32::AL);
     break;
   }
   assert(!Asm->needsTextFixup());
@@ -651,7 +651,21 @@
 
 template <> void InstARM32Vand::emitIAS(const Cfg *Func) const {
   // TODO(kschimpf): add support for these instructions
-  emitUsingTextFixup(Func);
+  auto *Asm = Func->getAssembler<ARM32::AssemblerARM32>();
+  const Variable *Dest = getDest();
+  switch (Dest->getType()) {
+  default:
+    llvm::report_fatal_error("Vand not defined on type " +
+                             typeIceString(Dest->getType()));
+  case IceType_v4i1:
+  case IceType_v8i1:
+  case IceType_v16i1:
+  case IceType_v16i8:
+  case IceType_v8i16:
+  case IceType_v4i32:
+    Asm->vandq(Dest, getSrc(0), getSrc(1));
+  }
+  assert(!Asm->needsTextFixup());
 }
 
 template <> void InstARM32Vdiv::emitIAS(const Cfg *Func) const {
@@ -748,8 +762,7 @@
   case IceType_v16i1:
   case IceType_NUM:
     llvm::report_fatal_error("Vsub not defined on type " +
-                             std::string(typeString(DestTy)));
-    break;
+                             typeIceString(DestTy));
   case IceType_v16i8:
   case IceType_v8i16:
   case IceType_v4i32:
diff --git a/src/IceTargetLoweringARM32.cpp b/src/IceTargetLoweringARM32.cpp
index f284f4d..7a19f11 100644
--- a/src/IceTargetLoweringARM32.cpp
+++ b/src/IceTargetLoweringARM32.cpp
@@ -2962,6 +2962,7 @@
         return;
       }
     }
+    assert(isIntegerType(DestTy));
     Variable *Src0R = Srcs.src0R(this);
     if (isVectorType(DestTy)) {
       Variable *Src1R = legalizeToReg(Src1);
diff --git a/src/IceTypes.h b/src/IceTypes.h
index 1ef3df7..e6e6f40 100644
--- a/src/IceTypes.h
+++ b/src/IceTypes.h
@@ -82,6 +82,7 @@
 size_t typeNumElements(Type Ty);
 Type typeElementType(Type Ty);
 const char *typeString(Type Ty);
+inline IceString typeIceString(Type Ty) { return typeString(Ty); }
 const char *regClassString(RegClass C);
 
 inline Type getPointerType() { return IceType_i32; }
diff --git a/tests_lit/assembler/arm32/and-vec.ll b/tests_lit/assembler/arm32/and-vec.ll
index e4d9625..48f28a5 100644
--- a/tests_lit/assembler/arm32/and-vec.ll
+++ b/tests_lit/assembler/arm32/and-vec.ll
@@ -30,7 +30,7 @@
 
 ; ASM:     vand.i32        q0, q0, q1
 ; DIS:   0:       f2000152
-; IASM:     vand.i32
+; IASM-NOT:     vand
 
   ret <4 x i32> %res
 }
@@ -45,7 +45,7 @@
 
 ; ASM:     vand.i16        q0, q0, q1
 ; DIS:   10:       f2000152
-; IASM:     vand.i16
+; IASM-NOT:     vand
 
   ret <8 x i16> %res
 }
@@ -60,7 +60,7 @@
 
 ; ASM:     vand.i8        q0, q0, q1
 ; DIS:   20:       f2000152
-; IASM:     vand.i8
+; IASM-NOT:     vand
 
   ret <16 x i8> %res
 }
@@ -79,7 +79,7 @@
 
 ; ASM:     vand.i32        q0, q0, q1
 ; DIS:   30:       f2000152
-; IASM:     vand.i32
+; IASM-NOT:     vand
 
   ret <4 x i1> %res
 }
@@ -94,7 +94,7 @@
 
 ; ASM:     vand.i16        q0, q0, q1
 ; DIS:   40:       f2000152
-; IASM:     vand.i16
+; IASM-NOT:     vand
 
   ret <8 x i1> %res
 }
@@ -109,7 +109,7 @@
 
 ; ASM:     vand.i8        q0, q0, q1
 ; DIS:   50:       f2000152
-; IASM:     vand.i8
+; IASM-NOT:     vand
 
   ret <16 x i1> %res
 }