ARM assembly parsing and encoding for VMOV.i64.

git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@142356 91177308-0d34-0410-b5e6-96231b3b80d8
diff --git a/lib/Target/ARM/ARMInstrNEON.td b/lib/Target/ARM/ARMInstrNEON.td
index ebff734a..a9a8041 100644
--- a/lib/Target/ARM/ARMInstrNEON.td
+++ b/lib/Target/ARM/ARMInstrNEON.td
@@ -39,6 +39,11 @@
   let PrintMethod = "printNEONModImmOperand";
   let ParserMatchClass = nImmVMOVI32AsmOperand;
 }
+def nImmSplatI64AsmOperand : AsmOperandClass { let Name = "NEONi64splat"; }
+def nImmSplatI64 : Operand<i32> {
+  let PrintMethod = "printNEONModImmOperand";
+  let ParserMatchClass = nImmSplatI64AsmOperand;
+}
 
 def VectorIndex8Operand  : AsmOperandClass { let Name = "VectorIndex8"; }
 def VectorIndex16Operand : AsmOperandClass { let Name = "VectorIndex16"; }
@@ -4372,11 +4377,11 @@
 }
 
 def VMOVv1i64 : N1ModImm<1, 0b000, 0b1110, 0, 0, 1, 1, (outs DPR:$Vd),
-                         (ins nModImm:$SIMM), IIC_VMOVImm,
+                         (ins nImmSplatI64:$SIMM), IIC_VMOVImm,
                          "vmov", "i64", "$Vd, $SIMM", "",
                          [(set DPR:$Vd, (v1i64 (NEONvmovImm timm:$SIMM)))]>;
 def VMOVv2i64 : N1ModImm<1, 0b000, 0b1110, 0, 1, 1, 1, (outs QPR:$Vd),
-                         (ins nModImm:$SIMM), IIC_VMOVImm,
+                         (ins nImmSplatI64:$SIMM), IIC_VMOVImm,
                          "vmov", "i64", "$Vd, $SIMM", "",
                          [(set QPR:$Vd, (v2i64 (NEONvmovImm timm:$SIMM)))]>;
 } // isReMaterializable
diff --git a/lib/Target/ARM/AsmParser/ARMAsmParser.cpp b/lib/Target/ARM/AsmParser/ARMAsmParser.cpp
index 752d351..4f904aa 100644
--- a/lib/Target/ARM/AsmParser/ARMAsmParser.cpp
+++ b/lib/Target/ARM/AsmParser/ARMAsmParser.cpp
@@ -966,6 +966,19 @@
       (Value >= 0x01ffff && Value <= 0xffffff && (Value & 0xffff) == 0xffff);
   }
 
+  bool isNEONi64splat() const {
+    if (Kind != k_Immediate)
+      return false;
+    const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
+    // Must be a constant.
+    if (!CE) return false;
+    uint64_t Value = CE->getValue();
+    // i64 value with each byte being either 0 or 0xff.
+    for (unsigned i = 0; i < 8; ++i)
+      if ((Value & 0xff) != 0 && (Value & 0xff) != 0xff) return false;
+    return true;
+  }
+
   void addExpr(MCInst &Inst, const MCExpr *Expr) const {
     // Add as immediates when possible.  Null MCExpr = 0.
     if (Expr == 0)
@@ -1536,6 +1549,18 @@
     Inst.addOperand(MCOperand::CreateImm(Value));
   }
 
+  void addNEONi64splatOperands(MCInst &Inst, unsigned N) const {
+    assert(N == 1 && "Invalid number of operands!");
+    // The immediate encodes the type of constant as well as the value.
+    const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
+    uint64_t Value = CE->getValue();
+    unsigned Imm = 0;
+    for (unsigned i = 0; i < 8; ++i, Value >>= 8) {
+      Imm |= (Value & 1) << i;
+    }
+    Inst.addOperand(MCOperand::CreateImm(Imm | 0x1e00));
+  }
+
   virtual void print(raw_ostream &OS) const;
 
   static ARMOperand *CreateITMask(unsigned Mask, SMLoc S) {
diff --git a/test/MC/ARM/neon-mov-encoding.s b/test/MC/ARM/neon-mov-encoding.s
index 709e515..c6f3f5d 100644
--- a/test/MC/ARM/neon-mov-encoding.s
+++ b/test/MC/ARM/neon-mov-encoding.s
@@ -9,7 +9,7 @@
 	vmov.i32	d16, #0x20000000
 	vmov.i32	d16, #0x20FF
 	vmov.i32	d16, #0x20FFFF
-@	vmov.i64	d16, #0xFF0000FF0000FFFF
+	vmov.i64	d16, #0xFF0000FF0000FFFF
 
 @ CHECK: vmov.i8	d16, #0x8       @ encoding: [0x18,0x0e,0xc0,0xf2]
 @ CHECK: vmov.i16	d16, #0x10      @ encoding: [0x10,0x08,0xc1,0xf2]
@@ -20,7 +20,7 @@
 @ CHECK: vmov.i32	d16, #0x20000000 @ encoding: [0x10,0x06,0xc2,0xf2]
 @ CHECK: vmov.i32	d16, #0x20FF    @ encoding: [0x10,0x0c,0xc2,0xf2]
 @ CHECK: vmov.i32	d16, #0x20FFFF  @ encoding: [0x10,0x0d,0xc2,0xf2]
-@ FIXME: vmov.i64 d16, #0xFF0000FF0000FFFF @ encoding: [0x33,0x0e,0xc1,0xf3]
+@ CHECK: vmov.i64 d16, #0xFF0000FF0000FFFF @ encoding: [0x33,0x0e,0xc1,0xf3]
 
 
 
@@ -33,7 +33,7 @@
 	vmov.i32	q8, #0x20000000
 	vmov.i32	q8, #0x20FF
 	vmov.i32	q8, #0x20FFFF
-@	vmov.i64	q8, #0xFF0000FF0000FFFF
+	vmov.i64	q8, #0xFF0000FF0000FFFF
 
 @ CHECK: vmov.i8 q8, #0x8               @ encoding: [0x58,0x0e,0xc0,0xf2]
 @ CHECK: vmov.i16	q8, #0x10       @ encoding: [0x50,0x08,0xc1,0xf2]
@@ -44,7 +44,7 @@
 @ CHECK: vmov.i32	q8, #0x20000000 @ encoding: [0x50,0x06,0xc2,0xf2]
 @ CHECK: vmov.i32	q8, #0x20FF     @ encoding: [0x50,0x0c,0xc2,0xf2]
 @ CHECK: vmov.i32	q8, #0x20FFFF   @ encoding: [0x50,0x0d,0xc2,0xf2]
-@ FIXME: vmov.i64 q8, #0xFF0000FF0000FFFF @ encoding: [0x73,0x0e,0xc1,0xf3]
+@ CHECK: vmov.i64 q8, #0xFF0000FF0000FFFF @ encoding: [0x73,0x0e,0xc1,0xf3]
 
 	vmvn.i16	d16, #0x10
 	vmvn.i16	d16, #0x1000
diff --git a/test/MC/ARM/neont2-mov-encoding.s b/test/MC/ARM/neont2-mov-encoding.s
index 822660d..db929c8 100644
--- a/test/MC/ARM/neont2-mov-encoding.s
+++ b/test/MC/ARM/neont2-mov-encoding.s
@@ -11,7 +11,7 @@
 	vmov.i32	d16, #0x20000000
 	vmov.i32	d16, #0x20FF
 	vmov.i32	d16, #0x20FFFF
-@	vmov.i64	d16, #0xFF0000FF0000FFFF
+	vmov.i64	d16, #0xFF0000FF0000FFFF
 
 @ CHECK: vmov.i8	d16, #0x8       @ encoding: [0xc0,0xef,0x18,0x0e]
 @ CHECK: vmov.i16	d16, #0x10      @ encoding: [0xc1,0xef,0x10,0x08]
@@ -22,7 +22,7 @@
 @ CHECK: vmov.i32	d16, #0x20000000 @ encoding: [0xc2,0xef,0x10,0x06]
 @ CHECK: vmov.i32	d16, #0x20FF    @ encoding: [0xc2,0xef,0x10,0x0c]
 @ CHECK: vmov.i32	d16, #0x20FFFF  @ encoding: [0xc2,0xef,0x10,0x0d]
-@ FIXME: vmov.i64 d16, #0xFF0000FF0000FFFF @ encoding: [0xc1,0xff,0x33,0x0e]
+@ CHECK: vmov.i64 d16, #0xFF0000FF0000FFFF @ encoding: [0xc1,0xff,0x33,0x0e]
 
 
 	vmov.i8	q8, #0x8
@@ -34,7 +34,7 @@
 	vmov.i32	q8, #0x20000000
 	vmov.i32	q8, #0x20FF
 	vmov.i32	q8, #0x20FFFF
-@	vmov.i64	q8, #0xFF0000FF0000FFFF
+	vmov.i64	q8, #0xFF0000FF0000FFFF
 
 @ CHECK: vmov.i8	q8, #0x8        @ encoding: [0xc0,0xef,0x58,0x0e]
 @ CHECK: vmov.i16	q8, #0x10       @ encoding: [0xc1,0xef,0x50,0x08]
@@ -45,7 +45,7 @@
 @ CHECK: vmov.i32	q8, #0x20000000 @ encoding: [0xc2,0xef,0x50,0x06]
 @ CHECK: vmov.i32	q8, #0x20FF     @ encoding: [0xc2,0xef,0x50,0x0c]
 @ CHECK: vmov.i32	q8, #0x20FFFF   @ encoding: [0xc2,0xef,0x50,0x0d]
-@ FIXME: vmov.i64 q8, #0xFF0000FF0000FFFF @ encoding: [0xc1,0xff,0x73,0x0e]
+@ CHECK: vmov.i64 q8, #0xFF0000FF0000FFFF @ encoding: [0xc1,0xff,0x73,0x0e]
 
 
 	vmvn.i16	d16, #0x10
diff --git a/utils/TableGen/EDEmitter.cpp b/utils/TableGen/EDEmitter.cpp
index cdfb983..e9edfe4 100644
--- a/utils/TableGen/EDEmitter.cpp
+++ b/utils/TableGen/EDEmitter.cpp
@@ -600,6 +600,7 @@
   IMM("nImmSplatI8");
   IMM("nImmSplatI16");
   IMM("nImmSplatI32");
+  IMM("nImmSplatI64");
   IMM("nImmVMOVI32");
   IMM("imm0_7");
   IMM("imm0_15");