Add disassembler support for VPERMIL2PD and VPERMIL2PS.
authorCraig Topper <craig.topper@gmail.com>
Fri, 30 Dec 2011 06:23:39 +0000 (06:23 +0000)
committerCraig Topper <craig.topper@gmail.com>
Fri, 30 Dec 2011 06:23:39 +0000 (06:23 +0000)
git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@147368 91177308-0d34-0410-b5e6-96231b3b80d8

lib/Target/X86/Disassembler/X86DisassemblerDecoder.c
lib/Target/X86/X86InstrXOP.td
test/MC/Disassembler/X86/simple-tests.txt
utils/TableGen/X86RecognizableInstr.cpp

index 1a248073392895bfce924165223be93f6c8603a5..c915df0049f8d61b264beb5fd744d6c76b04cce0 100644 (file)
@@ -1472,6 +1472,7 @@ static int readVVVV(struct InternalInstruction* insn) {
 static int readOperands(struct InternalInstruction* insn) {
   int index;
   int hasVVVV, needVVVV;
+  int sawRegImm = 0;
   
   dbgprintf(insn, "readOperands()");
 
@@ -1500,11 +1501,20 @@ static int readOperands(struct InternalInstruction* insn) {
       dbgprintf(insn, "We currently don't hande code-offset encodings");
       return -1;
     case ENCODING_IB:
+      if (sawRegImm) {
+        // saw a register immediate so don't read again and instead split the previous immediate
+        // FIXME: This is a hack
+        insn->immediates[insn->numImmediatesConsumed++] = insn->immediates[insn->numImmediatesConsumed - 1] & 0xf;
+        break;
+      }
       if (readImmediate(insn, 1))
         return -1;
       if (insn->spec->operands[index].type == TYPE_IMM3 &&
           insn->immediates[insn->numImmediatesConsumed - 1] > 7)
         return -1;
+      if (insn->spec->operands[index].type == TYPE_XMM128 ||
+          insn->spec->operands[index].type == TYPE_XMM256)
+        sawRegImm = 1;
       break;
     case ENCODING_IW:
       if (readImmediate(insn, 2))
index 9ab5a50bd4f1b76631696b24ea5f2430ccb11d47..aef2c3ac880ae4fd6bf43e8e429e680427650e21 100644 (file)
@@ -237,7 +237,5 @@ multiclass xop5op<bits<8> opc, string OpcodeStr> {
         []>;
 }
 
-let isAsmParserOnly = 1 in {
-  defm VPERMIL2PD : xop5op<0x49, "vpermil2pd">;
-  defm VPERMIL2PS : xop5op<0x48, "vpermil2ps">;
-}
+defm VPERMIL2PD : xop5op<0x49, "vpermil2pd">;
+defm VPERMIL2PS : xop5op<0x48, "vpermil2ps">;
index 03d64f4159032f6c35c7b8dcb5ae758a5e38fe9b..4f55068733a5c26c265826a8d2e65101d2fffb77 100644 (file)
 # CHECK: vfmadd132sd (%rax), %xmm12, %xmm10
 0xc4 0x62 0x99 0x99 0x10
 
-# CHEDCK: vfmaddss (%rcx), %xmm1, %xmm0, %xmm0
+# CHECK: vfmaddss (%rcx), %xmm1, %xmm0, %xmm0
 0xc4 0xe3 0xf9 0x6a 0x01 0x10
 
-# CHEDCK: vfmaddss %xmm1, (%rcx), %xmm0, %xmm0
+# CHECK: vfmaddss %xmm1, (%rcx), %xmm0, %xmm0
 0xc4 0xe3 0x79 0x6a 0x01 0x10
+
+# CHECK: vpermil2ps $1, 4(%rax), %xmm2, %xmm3, %xmm0
+0xc4 0xe3 0xe1 0x48 0x40 0x04 0x21
index b8b282a7a6a0e87abeab7bc27e8c4f32956122a6..385e5797519a41c70fe1f03db8fa2c0314217738 100644 (file)
@@ -559,7 +559,7 @@ void RecognizableInstr::emitInstructionSpecifier(DisassemblerTables &tables) {
   
   bool hasFROperands = false;
   
-  assert(numOperands < X86_MAX_OPERANDS && "X86_MAX_OPERANDS is not large enough");
+  assert(numOperands <= X86_MAX_OPERANDS && "X86_MAX_OPERANDS is not large enough");
   
   for (operandIndex = 0; operandIndex < numOperands; ++operandIndex) {
     if (OperandList[operandIndex].Constraints.size()) {
@@ -678,7 +678,7 @@ void RecognizableInstr::emitInstructionSpecifier(DisassemblerTables &tables) {
     // Operand 3 (optional) is an immediate.
 
     if (HasVEX_4VPrefix || HasVEX_4VOp3Prefix)
-      assert(numPhysicalOperands >= 3 && numPhysicalOperands <= 4 &&
+      assert(numPhysicalOperands >= 3 && numPhysicalOperands <= 5 &&
              "Unexpected number of operands for MRMSrcRegFrm with VEX_4V"); 
     else
       assert(numPhysicalOperands >= 2 && numPhysicalOperands <= 3 &&
@@ -699,7 +699,9 @@ void RecognizableInstr::emitInstructionSpecifier(DisassemblerTables &tables) {
     if (HasVEX_4VOp3Prefix)
       HANDLE_OPERAND(vvvvRegister)
 
-    HANDLE_OPTIONAL(immediate)
+    if (!HasMemOp4Prefix)
+      HANDLE_OPTIONAL(immediate)
+    HANDLE_OPTIONAL(immediate) // above might be a register in 7:4
     break;
   case X86Local::MRMSrcMem:
     // Operand 1 is a register operand in the Reg/Opcode field.
@@ -708,7 +710,7 @@ void RecognizableInstr::emitInstructionSpecifier(DisassemblerTables &tables) {
     // Operand 3 (optional) is an immediate.
 
     if (HasVEX_4VPrefix || HasVEX_4VOp3Prefix)
-      assert(numPhysicalOperands >= 3 && numPhysicalOperands <= 4 &&
+      assert(numPhysicalOperands >= 3 && numPhysicalOperands <= 5 &&
              "Unexpected number of operands for MRMSrcMemFrm with VEX_4V"); 
     else
       assert(numPhysicalOperands >= 2 && numPhysicalOperands <= 3 &&
@@ -729,7 +731,9 @@ void RecognizableInstr::emitInstructionSpecifier(DisassemblerTables &tables) {
     if (HasVEX_4VOp3Prefix)
       HANDLE_OPERAND(vvvvRegister)
 
-    HANDLE_OPTIONAL(immediate)
+    if (!HasMemOp4Prefix)
+      HANDLE_OPTIONAL(immediate)
+    HANDLE_OPTIONAL(immediate) // above might be a register in 7:4
     break;
   case X86Local::MRM0r:
   case X86Local::MRM1r: