Add X86 PEXTR and PDEP instructions.
authorCraig Topper <craig.topper@gmail.com>
Sun, 16 Oct 2011 16:50:08 +0000 (16:50 +0000)
committerCraig Topper <craig.topper@gmail.com>
Sun, 16 Oct 2011 16:50:08 +0000 (16:50 +0000)
git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@142141 91177308-0d34-0410-b5e6-96231b3b80d8

lib/Target/X86/MCTargetDesc/X86BaseInfo.h
lib/Target/X86/MCTargetDesc/X86MCCodeEmitter.cpp
lib/Target/X86/X86CodeEmitter.cpp
lib/Target/X86/X86InstrFormats.td
lib/Target/X86/X86InstrInfo.td
test/MC/Disassembler/X86/simple-tests.txt
test/MC/Disassembler/X86/x86-32.txt
test/MC/X86/x86_64-bmi-encoding.s
utils/TableGen/X86RecognizableInstr.cpp

index 30ff1fd4aa9e85d35a0185754c643b44cbb1724f..007e620cae3672c6879d22385ad1d84de263d78f 100644 (file)
@@ -295,8 +295,11 @@ namespace X86II {
     T8 = 13 << Op0Shift,  TA = 14 << Op0Shift,
     A6 = 15 << Op0Shift,  A7 = 16 << Op0Shift,
 
-    // TF - Prefix before and after 0x0F
-    TF = 17 << Op0Shift,
+    // T8XD - Prefix before and after 0x0F. Combination of T8 and XD.
+    T8XD = 17 << Op0Shift,
+
+    // T8XS - Prefix before and after 0x0F. Combination of T8 and XS.
+    T8XS = 18 << Op0Shift,
 
     //===------------------------------------------------------------------===//
     // REX_W - REX prefixes are instruction prefixes used in 64-bit mode.
index 91f672b1e4599e713da893dd929b280b68096423..8ae7a3c42af23143957cade1ac33499286389e0d 100644 (file)
@@ -464,7 +464,11 @@ void X86MCCodeEmitter::EmitVEXOpcodePrefix(uint64_t TSFlags, unsigned &CurByte,
   case X86II::TA:  // 0F 3A
     VEX_5M = 0x3;
     break;
-  case X86II::TF:  // F2 0F 38
+  case X86II::T8XS: // F3 0F 38
+    VEX_PP = 0x2;
+    VEX_5M = 0x2;
+    break;
+  case X86II::T8XD: // F2 0F 38
     VEX_PP = 0x3;
     VEX_5M = 0x2;
     break;
@@ -790,7 +794,11 @@ void X86MCCodeEmitter::EmitOpcodePrefix(uint64_t TSFlags, unsigned &CurByte,
   case X86II::A7:  // 0F A7
     Need0FPrefix = true;
     break;
-  case X86II::TF: // F2 0F 38
+  case X86II::T8XS: // F3 0F 38
+    EmitByte(0xF3, CurByte, OS);
+    Need0FPrefix = true;
+    break;
+  case X86II::T8XD: // F2 0F 38
     EmitByte(0xF2, CurByte, OS);
     Need0FPrefix = true;
     break;
@@ -825,7 +833,8 @@ void X86MCCodeEmitter::EmitOpcodePrefix(uint64_t TSFlags, unsigned &CurByte,
 
   // FIXME: Pull this up into previous switch if REX can be moved earlier.
   switch (TSFlags & X86II::Op0Mask) {
-  case X86II::TF:    // F2 0F 38
+  case X86II::T8XS:  // F3 0F 38
+  case X86II::T8XD:  // F2 0F 38
   case X86II::T8:    // 0F 38
     EmitByte(0x38, CurByte, OS);
     break;
index aeff03a89ec9bc08a15d0011273c62faafdd061c..a15060462e5fc705bb88804c3e1d44597c7926a3 100644 (file)
@@ -649,15 +649,13 @@ void Emitter<CodeEmitter>::emitInstruction(MachineInstr &MI,
   case X86II::A7:  // 0F A7
     Need0FPrefix = true;
     break;
-  case X86II::TF: // F2 0F 38
-    MCE.emitByte(0xF2);
-    Need0FPrefix = true;
-    break;
   case X86II::REP: break; // already handled.
+  case X86II::T8XS: // F3 0F 38
   case X86II::XS:   // F3 0F
     MCE.emitByte(0xF3);
     Need0FPrefix = true;
     break;
+  case X86II::T8XD: // F2 0F 38
   case X86II::XD:   // F2 0F
     MCE.emitByte(0xF2);
     Need0FPrefix = true;
@@ -683,7 +681,8 @@ void Emitter<CodeEmitter>::emitInstruction(MachineInstr &MI,
     MCE.emitByte(0x0F);
 
   switch (Desc->TSFlags & X86II::Op0Mask) {
-  case X86II::TF:    // F2 0F 38
+  case X86II::T8XD:  // F2 0F 38
+  case X86II::T8XS:  // F3 0F 38
   case X86II::T8:    // 0F 38
     MCE.emitByte(0x38);
     break;
index d291e4385f9f7a43b2ab611e5d85995c72d0a6d8..5b7adf311bd73fa8fbec30bca0a0463cb49c4a3a 100644 (file)
@@ -107,7 +107,8 @@ class T8     { bits<5> Prefix = 13; }
 class TA     { bits<5> Prefix = 14; }
 class A6     { bits<5> Prefix = 15; }
 class A7     { bits<5> Prefix = 16; }
-class TF     { bits<5> Prefix = 17; }
+class T8XD   { bits<5> Prefix = 17; }
+class T8XS   { bits<5> Prefix = 18; }
 class VEX    { bit hasVEXPrefix = 1; }
 class VEX_W  { bit hasVEX_WPrefix = 1; }
 class VEX_4V : VEX { bit hasVEX_4VPrefix = 1; }
@@ -424,10 +425,10 @@ class SS428I<bits<8> o, Format F, dag outs, dag ins, string asm,
       : I<o, F, outs, ins, asm, pattern, SSEPackedInt>, T8,
         Requires<[HasSSE42]>;
 
-//   SS42FI - SSE 4.2 instructions with TF prefix.
+//   SS42FI - SSE 4.2 instructions with T8XD prefix.
 class SS42FI<bits<8> o, Format F, dag outs, dag ins, string asm,
               list<dag> pattern>
-      : I<o, F, outs, ins, asm, pattern>, TF, Requires<[HasSSE42]>;
+      : I<o, F, outs, ins, asm, pattern>, T8XD, Requires<[HasSSE42]>;
       
 //   SS42AI = SSE 4.2 instructions with TA prefix
 class SS42AI<bits<8> o, Format F, dag outs, dag ins, string asm,
index 4a5912dc36f9254d1c9d55370ac27cb672687aa2..1151b022f77aa992b3b77cb56d22302bc48023b6 100644 (file)
@@ -1443,6 +1443,23 @@ let Predicates = [HasBMI2], Defs = [EFLAGS] in {
   defm BZHI64 : bmi_bextr_bzhi<0xF5, "bzhi{q}", GR64, i64mem>, VEX_W;
 }
 
+multiclass bmi_pdep_pextr<string mnemonic, RegisterClass RC,
+                          X86MemOperand x86memop> {
+  def rr : I<0xF5, MRMSrcReg, (outs RC:$dst), (ins RC:$src1, RC:$src2),
+             !strconcat(mnemonic, "\t{$src2, $src1, $dst|$dst, $src1, $src2}"),
+             []>, VEX_4V;
+  def rm : I<0xF5, MRMSrcMem, (outs RC:$dst), (ins RC:$src1, x86memop:$src2),
+             !strconcat(mnemonic, "\t{$src2, $src1, $dst|$dst, $src1, $src2}"),
+             []>, VEX_4V;
+}
+
+let Predicates = [HasBMI2] in {
+  defm PDEP32 : bmi_pdep_pextr<"pdep{l}", GR32, i32mem>, T8XD;
+  defm PDEP64 : bmi_pdep_pextr<"pdep{q}", GR64, i64mem>, T8XD, VEX_W;
+  defm PEXTR32 : bmi_pdep_pextr<"pextr{l}", GR32, i32mem>, T8XS;
+  defm PEXTR64 : bmi_pdep_pextr<"pextr{q}", GR64, i64mem>, T8XS, VEX_W;
+}
+
 //===----------------------------------------------------------------------===//
 // Subsystems.
 //===----------------------------------------------------------------------===//
index 03a9db6257ef9e22a60d04c7da6fc19bec8d3f13..d540bfbd67c98ea72d54084960bd01b536d62547 100644 (file)
 
 # CHECK: bzhiq %r12, %r11, %r10
 0xc4 0x42 0x98 0xf5 0xd3
+
+# CHECK: pextrl %r12d, %r11d, %r10d
+0xc4 0x42 0x22 0xf5 0xd4
+
+# CHECK: pextrl (%rax), %r11d, %r10d
+0xc4 0x62 0x22 0xf5 0x10
+
+# CHECK: pextrq %r12, %r11, %r10
+0xc4 0x42 0xa2 0xf5 0xd4
+
+# CHECK: pextrq (%rax), %r11, %r10
+0xc4 0x62 0xa2 0xf5 0x10
+
+# CHECK: pdepl %r12d, %r11d, %r10d
+0xc4 0x42 0x23 0xf5 0xd4
+
+# CHECK: pdepl (%rax), %r11d, %r10d
+0xc4 0x62 0x23 0xf5 0x10
+
+# CHECK: pdepq %r12, %r11, %r10
+0xc4 0x42 0xa3 0xf5 0xd4
+
+# CHECK: pdepq (%rax), %r11, %r10
+0xc4 0x62 0xa3 0xf5 0x10
index 7e4e7083c3a11228b90eafb2a68952c2aecdf945..d78232bbd675616e306544c4edebcf1f98d709fc 100644 (file)
 
 # CHECK: bzhil %esi, %ebx, %edx
 0xc4 0xe2 0x08 0xf5 0xd3
+
+# CHECK: pextrl %esp, %ecx, %edx
+0xc4 0xe2 0x72 0xf5 0xd4
+
+# CHECK: pextrl (%eax), %ecx, %edx
+0xc4 0xe2 0x72 0xf5 0x10
+
+# CHECK: pdepl %esp, %ecx, %edx
+0xc4 0xe2 0x73 0xf5 0xd4
+
+# CHECK: pdepl (%eax), %ecx, %edx
+0xc4 0xe2 0x73 0xf5 0x10
index ba931d53d07dac8d43768908a181b29a3c40df8f..24acb01b6790172d278d6b7fc335c732959fa165 100644 (file)
 // CHECK: bzhiq %r12, %r11, %r10
 // CHECK: encoding: [0xc4,0x42,0x98,0xf5,0xd3]
           bzhiq %r12, %r11, %r10
+
+// CHECK: pextrl %r12d, %r11d, %r10d
+// CHECK: encoding: [0xc4,0x42,0x22,0xf5,0xd4]
+          pextrl %r12d, %r11d, %r10d
+
+// CHECK: pextrl (%rax), %r11d, %r10d
+// CHECK: encoding: [0xc4,0x62,0x22,0xf5,0x10]
+          pextrl (%rax), %r11d, %r10d
+
+// CHECK: pextrq %r12, %r11, %r10
+// CHECK: encoding: [0xc4,0x42,0xa2,0xf5,0xd4]
+          pextrq %r12, %r11, %r10
+
+// CHECK: pextrq (%rax), %r11, %r10
+// CHECK: encoding: [0xc4,0x62,0xa2,0xf5,0x10]
+          pextrq (%rax), %r11, %r10
+
+// CHECK: pdepl %r12d, %r11d, %r10d
+// CHECK: encoding: [0xc4,0x42,0x23,0xf5,0xd4]
+          pdepl %r12d, %r11d, %r10d
+
+// CHECK: pdepl (%rax), %r11d, %r10d
+// CHECK: encoding: [0xc4,0x62,0x23,0xf5,0x10]
+          pdepl (%rax), %r11d, %r10d
+
+// CHECK: pdepq %r12, %r11, %r10
+// CHECK: encoding: [0xc4,0x42,0xa3,0xf5,0xd4]
+          pdepq %r12, %r11, %r10
+
+// CHECK: pdepq (%rax), %r11, %r10
+// CHECK: encoding: [0xc4,0x62,0xa3,0xf5,0x10]
+          pdepq (%rax), %r11, %r10
index b3a316d6c7047ce43c14781d3877b4d6a59186ac..68e03738cff4028fd6096421e4e434c754f915ad 100644 (file)
@@ -68,7 +68,7 @@ namespace X86Local {
     DC = 7, DD = 8, DE = 9, DF = 10,
     XD = 11,  XS = 12,
     T8 = 13,  P_TA = 14,
-    A6 = 15,  A7 = 16, TF = 17
+    A6 = 15,  A7 = 16, T8XD = 17, T8XS = 18
   };
 }
 
@@ -293,21 +293,25 @@ InstructionContext RecognizableInstr::insnContext() const {
       insnContext = IC_VEX_W_OPSIZE;
     else if (HasOpSizePrefix)
       insnContext = IC_VEX_OPSIZE;
-    else if (HasVEX_LPrefix && Prefix == X86Local::XS)
+    else if (HasVEX_LPrefix &&
+             (Prefix == X86Local::XS || Prefix == X86Local::T8XS))
       insnContext = IC_VEX_L_XS;
-    else if (HasVEX_LPrefix && Prefix == X86Local::XD)
+    else if (HasVEX_LPrefix &&
+             (Prefix == X86Local::XD || Prefix == X86Local::T8XD))
       insnContext = IC_VEX_L_XD;
-    else if (HasVEX_WPrefix && Prefix == X86Local::XS)
+    else if (HasVEX_WPrefix &&
+             (Prefix == X86Local::XS || Prefix == X86Local::T8XS))
       insnContext = IC_VEX_W_XS;
-    else if (HasVEX_WPrefix && Prefix == X86Local::XD)
+    else if (HasVEX_WPrefix &&
+             (Prefix == X86Local::XD || Prefix == X86Local::T8XD))
       insnContext = IC_VEX_W_XD;
     else if (HasVEX_WPrefix)
       insnContext = IC_VEX_W;
     else if (HasVEX_LPrefix)
       insnContext = IC_VEX_L;
-    else if (Prefix == X86Local::XD)
+    else if (Prefix == X86Local::XD || Prefix == X86Local::T8XD)
       insnContext = IC_VEX_XD;
-    else if (Prefix == X86Local::XS)
+    else if (Prefix == X86Local::XS || Prefix == X86Local::T8XS)
       insnContext = IC_VEX_XS;
     else
       insnContext = IC_VEX;
@@ -315,20 +319,22 @@ InstructionContext RecognizableInstr::insnContext() const {
     if (HasREX_WPrefix && HasOpSizePrefix)
       insnContext = IC_64BIT_REXW_OPSIZE;
     else if (HasOpSizePrefix &&
-             (Prefix == X86Local::XD || Prefix == X86Local::TF))
+             (Prefix == X86Local::XD || Prefix == X86Local::T8XD))
       insnContext = IC_64BIT_XD_OPSIZE;
-    else if (HasOpSizePrefix && Prefix == X86Local::XS)
+    else if (HasOpSizePrefix &&
+             (Prefix == X86Local::XS || Prefix == X86Local::T8XS))
       insnContext = IC_64BIT_XS_OPSIZE;
     else if (HasOpSizePrefix)
       insnContext = IC_64BIT_OPSIZE;
-    else if (HasREX_WPrefix && Prefix == X86Local::XS)
+    else if (HasREX_WPrefix &&
+             (Prefix == X86Local::XS || Prefix == X86Local::T8XS))
       insnContext = IC_64BIT_REXW_XS;
     else if (HasREX_WPrefix &&
-             (Prefix == X86Local::XD || Prefix == X86Local::TF))
+             (Prefix == X86Local::XD || Prefix == X86Local::T8XD))
       insnContext = IC_64BIT_REXW_XD;
-    else if (Prefix == X86Local::XD || Prefix == X86Local::TF)
+    else if (Prefix == X86Local::XD || Prefix == X86Local::T8XD)
       insnContext = IC_64BIT_XD;
-    else if (Prefix == X86Local::XS)
+    else if (Prefix == X86Local::XS || Prefix == X86Local::T8XS)
       insnContext = IC_64BIT_XS;
     else if (HasREX_WPrefix)
       insnContext = IC_64BIT_REXW;
@@ -336,15 +342,17 @@ InstructionContext RecognizableInstr::insnContext() const {
       insnContext = IC_64BIT;
   } else {
     if (HasOpSizePrefix &&
-        (Prefix == X86Local::XD || Prefix == X86Local::TF))
+        (Prefix == X86Local::XD || Prefix == X86Local::T8XD))
       insnContext = IC_XD_OPSIZE;
-    else if (HasOpSizePrefix && Prefix == X86Local::XS)
+    else if (HasOpSizePrefix &&
+             (Prefix == X86Local::XS || Prefix == X86Local::T8XS))
       insnContext = IC_XS_OPSIZE;
     else if (HasOpSizePrefix)
       insnContext = IC_OPSIZE;
-    else if (Prefix == X86Local::XD || Prefix == X86Local::TF)
+    else if (Prefix == X86Local::XD || Prefix == X86Local::T8XD)
       insnContext = IC_XD;
-    else if (Prefix == X86Local::XS || Prefix == X86Local::REP)
+    else if (Prefix == X86Local::XS || Prefix == X86Local::T8XS ||
+             Prefix == X86Local::REP)
       insnContext = IC_XS;
     else
       insnContext = IC;
@@ -857,7 +865,8 @@ void RecognizableInstr::emitDecodePath(DisassemblerTables &tables) const {
     opcodeToSet = Opcode;
     break;
   case X86Local::T8:
-  case X86Local::TF:
+  case X86Local::T8XD:
+  case X86Local::T8XS:
     opcodeType = THREEBYTE_38;
     switch (Opcode) {
     default: