aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorCraig Topper <craig.topper@gmail.com>2011-10-15 20:46:47 +0000
committerCraig Topper <craig.topper@gmail.com>2011-10-15 20:46:47 +0000
commit566f233ba64c0bb2773b5717cb18753c7564f4b7 (patch)
treebefeba913e8cabb5cdec9d4aa59a6b9700178645
parent4d83b79c76044e3f3cefd2a6c1b0b792266935c8 (diff)
Add support for X86 blsr, blsmsk, and blsi instructions. Required extra work because these are the first VEX encoded instructions to use the reg field as an opcode extension.
git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@142082 91177308-0d34-0410-b5e6-96231b3b80d8
-rw-r--r--lib/Target/X86/MCTargetDesc/X86BaseInfo.h9
-rw-r--r--lib/Target/X86/MCTargetDesc/X86MCCodeEmitter.cpp32
-rw-r--r--lib/Target/X86/X86InstrInfo.td22
-rw-r--r--test/MC/Disassembler/X86/simple-tests.txt18
-rw-r--r--test/MC/Disassembler/X86/x86-32.txt9
-rw-r--r--test/MC/X86/x86_64-bmi-encoding.s57
-rw-r--r--utils/TableGen/X86RecognizableInstr.cpp58
7 files changed, 180 insertions, 25 deletions
diff --git a/lib/Target/X86/MCTargetDesc/X86BaseInfo.h b/lib/Target/X86/MCTargetDesc/X86BaseInfo.h
index e6ba705d4d..555ca17f42 100644
--- a/lib/Target/X86/MCTargetDesc/X86BaseInfo.h
+++ b/lib/Target/X86/MCTargetDesc/X86BaseInfo.h
@@ -495,8 +495,13 @@ namespace X86II {
case X86II::MRM0m: case X86II::MRM1m:
case X86II::MRM2m: case X86II::MRM3m:
case X86II::MRM4m: case X86II::MRM5m:
- case X86II::MRM6m: case X86II::MRM7m:
- return 0;
+ case X86II::MRM6m: case X86II::MRM7m: {
+ bool HasVEX_4V = (TSFlags >> X86II::VEXShift) & X86II::VEX_4V;
+ unsigned FirstMemOp = 0;
+ if (HasVEX_4V)
+ ++FirstMemOp;// Skip the register dest (which is encoded in VEX_VVVV).
+ return FirstMemOp;
+ }
case X86II::MRM_C1:
case X86II::MRM_C2:
case X86II::MRM_C3:
diff --git a/lib/Target/X86/MCTargetDesc/X86MCCodeEmitter.cpp b/lib/Target/X86/MCTargetDesc/X86MCCodeEmitter.cpp
index 2eee112811..918d4a0474 100644
--- a/lib/Target/X86/MCTargetDesc/X86MCCodeEmitter.cpp
+++ b/lib/Target/X86/MCTargetDesc/X86MCCodeEmitter.cpp
@@ -63,9 +63,8 @@ public:
unsigned OpNum) {
unsigned SrcReg = MI.getOperand(OpNum).getReg();
unsigned SrcRegNum = GetX86RegNum(MI.getOperand(OpNum));
- if ((SrcReg >= X86::XMM8 && SrcReg <= X86::XMM15) ||
- (SrcReg >= X86::YMM8 && SrcReg <= X86::YMM15))
- SrcRegNum += 8;
+ if (X86II::isX86_64ExtendedReg(SrcReg))
+ SrcRegNum |= 8;
// The registers represented through VEX_VVVV should
// be encoded in 1's complement form.
@@ -516,7 +515,7 @@ void X86MCCodeEmitter::EmitVEXOpcodePrefix(uint64_t TSFlags, unsigned &CurByte,
VEX_R = 0x0;
break;
}
- case X86II::MRMSrcMem: {
+ case X86II::MRMSrcMem:
// MRMSrcMem instructions forms:
// src1(ModR/M), MemAddr
// src1(ModR/M), src2(VEX_4V), MemAddr
@@ -526,31 +525,34 @@ void X86MCCodeEmitter::EmitVEXOpcodePrefix(uint64_t TSFlags, unsigned &CurByte,
if (X86II::isX86_64ExtendedReg(MI.getOperand(0).getReg()))
VEX_R = 0x0;
- unsigned MemAddrOffset = 1;
- if (HasVEX_4V) {
+ if (HasVEX_4V)
VEX_4V = getVEXRegisterEncoding(MI, 1);
- MemAddrOffset++;
- }
if (X86II::isX86_64ExtendedReg(
- MI.getOperand(MemAddrOffset+X86::AddrBaseReg).getReg()))
+ MI.getOperand(MemOperand+X86::AddrBaseReg).getReg()))
VEX_B = 0x0;
if (X86II::isX86_64ExtendedReg(
- MI.getOperand(MemAddrOffset+X86::AddrIndexReg).getReg()))
+ MI.getOperand(MemOperand+X86::AddrIndexReg).getReg()))
VEX_X = 0x0;
break;
- }
case X86II::MRM0m: case X86II::MRM1m:
case X86II::MRM2m: case X86II::MRM3m:
case X86II::MRM4m: case X86II::MRM5m:
- case X86II::MRM6m: case X86II::MRM7m:
+ case X86II::MRM6m: case X86II::MRM7m: {
// MRM[0-9]m instructions forms:
// MemAddr
- if (X86II::isX86_64ExtendedReg(MI.getOperand(X86::AddrBaseReg).getReg()))
+ // src1(VEX_4V), MemAddr
+ if (HasVEX_4V)
+ VEX_4V = getVEXRegisterEncoding(MI, 0);
+
+ if (X86II::isX86_64ExtendedReg(
+ MI.getOperand(MemOperand+X86::AddrBaseReg).getReg()))
VEX_B = 0x0;
- if (X86II::isX86_64ExtendedReg(MI.getOperand(X86::AddrIndexReg).getReg()))
+ if (X86II::isX86_64ExtendedReg(
+ MI.getOperand(MemOperand+X86::AddrIndexReg).getReg()))
VEX_X = 0x0;
break;
+ }
case X86II::MRMSrcReg:
// MRMSrcReg instructions forms:
// dst(ModR/M), src1(VEX_4V), src2(ModR/M), src3(VEX_I8IMM)
@@ -976,6 +978,8 @@ EncodeInstruction(const MCInst &MI, raw_ostream &OS,
case X86II::MRM2m: case X86II::MRM3m:
case X86II::MRM4m: case X86II::MRM5m:
case X86II::MRM6m: case X86II::MRM7m:
+ if (HasVEX_4V) // Skip the register dst (which is encoded in VEX_VVVV).
+ CurOp++;
EmitByte(BaseOpcode, CurByte, OS);
EmitMemModRMByte(MI, CurOp, (TSFlags & X86II::FormMask)-X86II::MRM0m,
TSFlags, CurByte, OS, Fixups);
diff --git a/lib/Target/X86/X86InstrInfo.td b/lib/Target/X86/X86InstrInfo.td
index d54bf275c0..a9b59d7c42 100644
--- a/lib/Target/X86/X86InstrInfo.td
+++ b/lib/Target/X86/X86InstrInfo.td
@@ -1375,7 +1375,7 @@ let Predicates = [HasLZCNT], Defs = [EFLAGS] in {
}
//===----------------------------------------------------------------------===//
-// TZCNT Instruction
+// BMI Instructions
//
let Predicates = [HasBMI], Defs = [EFLAGS] in {
def TZCNT16rr : I<0xBC, MRMSrcReg, (outs GR16:$dst), (ins GR16:$src),
@@ -1405,6 +1405,26 @@ let Predicates = [HasBMI], Defs = [EFLAGS] in {
(implicit EFLAGS)]>, XS;
}
+multiclass bmi_bls<string mnemonic, Format RegMRM, Format MemMRM,
+ RegisterClass RC, X86MemOperand x86memop> {
+ def rr : I<0xF3, RegMRM, (outs RC:$dst), (ins RC:$src),
+ !strconcat(mnemonic, "\t{$src, $dst|$dst, $src}"), []>;
+ def rm : I<0xF3, MemMRM, (outs RC:$dst), (ins x86memop:$src),
+ !strconcat(mnemonic, "\t{$src, $dst|$dst, $src}"), []>;
+}
+
+let Predicates = [HasBMI], Defs = [EFLAGS] in {
+ defm BLSR32 : bmi_bls<"blsr{l}", MRM1r, MRM1m, GR32, i32mem>, T8, VEX_4V;
+ defm BLSR64 : bmi_bls<"blsr{q}", MRM1r, MRM1m, GR64, i64mem>, T8, VEX_4V,
+ VEX_W;
+ defm BLSMSK32 : bmi_bls<"blsmsk{l}", MRM2r, MRM2m, GR32, i32mem>, T8, VEX_4V;
+ defm BLSMSK64 : bmi_bls<"blsmsk{q}", MRM2r, MRM2m, GR64, i64mem>, T8, VEX_4V,
+ VEX_W;
+ defm BLSI32 : bmi_bls<"blsi{l}", MRM3r, MRM3m, GR32, i32mem>, T8, VEX_4V;
+ defm BLSI64 : bmi_bls<"blsi{q}", MRM3r, MRM3m, GR64, i64mem>, T8, VEX_4V,
+ VEX_W;
+}
+
//===----------------------------------------------------------------------===//
// Subsystems.
//===----------------------------------------------------------------------===//
diff --git a/test/MC/Disassembler/X86/simple-tests.txt b/test/MC/Disassembler/X86/simple-tests.txt
index 2dc918cb0d..93154f6a98 100644
--- a/test/MC/Disassembler/X86/simple-tests.txt
+++ b/test/MC/Disassembler/X86/simple-tests.txt
@@ -518,3 +518,21 @@
# CHECK: andnq (%rax), %r15, %rax
0xc4 0xe2 0x80 0xf2 0x00
+
+# CHECK: blsrl (%rax), %r15d
+0xc4 0xe2 0x00 0xf3 0x08
+
+# CHECK: blsrq (%rax), %r15
+0xc4 0xe2 0x80 0xf3 0x08
+
+# CHECK: blsmskl (%rax), %r15d
+0xc4 0xe2 0x00 0xf3 0x10
+
+# CHECK: blsmskq (%rax), %r15
+0xc4 0xe2 0x80 0xf3 0x10
+
+# CHECK: blsil (%rax), %r15d
+0xc4 0xe2 0x00 0xf3 0x18
+
+# CHECK: blsiq (%rax), %r15
+0xc4 0xe2 0x80 0xf3 0x18
diff --git a/test/MC/Disassembler/X86/x86-32.txt b/test/MC/Disassembler/X86/x86-32.txt
index c4437ba35d..46d93ce717 100644
--- a/test/MC/Disassembler/X86/x86-32.txt
+++ b/test/MC/Disassembler/X86/x86-32.txt
@@ -495,3 +495,12 @@
# CHECK: andnl (%eax), %edi, %eax
0xc4 0xe2 0x80 0xf2 0x00
+
+# CHECK: blsrl (%eax), %edi
+0xc4 0xe2 0x40 0xf3 0x08
+
+# CHECK: blsmskl (%eax), %edi
+0xc4 0xe2 0x40 0xf3 0x10
+
+# CHECK: blsil (%eax), %edi
+0xc4 0xe2 0x40 0xf3 0x18
diff --git a/test/MC/X86/x86_64-bmi-encoding.s b/test/MC/X86/x86_64-bmi-encoding.s
new file mode 100644
index 0000000000..f02bc0ec48
--- /dev/null
+++ b/test/MC/X86/x86_64-bmi-encoding.s
@@ -0,0 +1,57 @@
+// RUN: llvm-mc -triple x86_64-unknown-unknown --show-encoding %s | FileCheck %s
+
+// CHECK: blsmskl %r11d, %r10d
+// CHECK: encoding: [0xc4,0xc2,0x28,0xf3,0xd3]
+ blsmskl %r11d, %r10d
+
+// CHECK: blsmskq %r11, %r10
+// CHECK: encoding: [0xc4,0xc2,0xa8,0xf3,0xd3]
+ blsmskq %r11, %r10
+
+// CHECK: blsmskl (%rax), %r10d
+// CHECK: encoding: [0xc4,0xe2,0x28,0xf3,0x10]
+ blsmskl (%rax), %r10d
+
+// CHECK: blsmskq (%rax), %r10
+// CHECK: encoding: [0xc4,0xe2,0xa8,0xf3,0x10]
+ blsmskq (%rax), %r10
+
+// CHECK: blsil %r11d, %r10d
+// CHECK: encoding: [0xc4,0xc2,0x28,0xf3,0xdb]
+ blsil %r11d, %r10d
+
+// CHECK: blsiq %r11, %r10
+// CHECK: encoding: [0xc4,0xc2,0xa8,0xf3,0xdb]
+ blsiq %r11, %r10
+
+// CHECK: blsil (%rax), %r10d
+// CHECK: encoding: [0xc4,0xe2,0x28,0xf3,0x18]
+ blsil (%rax), %r10d
+
+// CHECK: blsiq (%rax), %r10
+// CHECK: encoding: [0xc4,0xe2,0xa8,0xf3,0x18]
+ blsiq (%rax), %r10
+
+// CHECK: blsrl %r11d, %r10d
+// CHECK: encoding: [0xc4,0xc2,0x28,0xf3,0xcb]
+ blsrl %r11d, %r10d
+
+// CHECK: blsrq %r11, %r10
+// CHECK: encoding: [0xc4,0xc2,0xa8,0xf3,0xcb]
+ blsrq %r11, %r10
+
+// CHECK: blsrl (%rax), %r10d
+// CHECK: encoding: [0xc4,0xe2,0x28,0xf3,0x08]
+ blsrl (%rax), %r10d
+
+// CHECK: blsrq (%rax), %r10
+// CHECK: encoding: [0xc4,0xe2,0xa8,0xf3,0x08]
+ blsrq (%rax), %r10
+
+// CHECK: andnl (%rax), %r11d, %r10d
+// CHECK: encoding: [0xc4,0x62,0x20,0xf2,0x10]
+ andnl (%rax), %r11d, %r10d
+
+// CHECK: andnq (%rax), %r11, %r10
+// CHECK: encoding: [0xc4,0x62,0xa0,0xf2,0x10]
+ andnq (%rax), %r11, %r10
diff --git a/utils/TableGen/X86RecognizableInstr.cpp b/utils/TableGen/X86RecognizableInstr.cpp
index cae8237492..a3647c1f0e 100644
--- a/utils/TableGen/X86RecognizableInstr.cpp
+++ b/utils/TableGen/X86RecognizableInstr.cpp
@@ -119,6 +119,9 @@ namespace X86Local {
EXTENSION_TABLE(ba) \
EXTENSION_TABLE(c7)
+#define THREE_BYTE_38_EXTENSION_TABLES \
+ EXTENSION_TABLE(F3)
+
using namespace X86Disassembler;
/// needsModRMForDecode - Indicates whether a particular instruction requires a
@@ -736,12 +739,12 @@ void RecognizableInstr::emitInstructionSpecifier(DisassemblerTables &tables) {
// Operand 2 (optional) is an immediate or relocation.
if (HasVEX_4VPrefix)
assert(numPhysicalOperands <= 3 &&
- "Unexpected number of operands for MRMSrcMemFrm with VEX_4V");
+ "Unexpected number of operands for MRMnRFrm with VEX_4V");
else
assert(numPhysicalOperands <= 2 &&
"Unexpected number of operands for MRMnRFrm");
if (HasVEX_4VPrefix)
- HANDLE_OPERAND(vvvvRegister);
+ HANDLE_OPERAND(vvvvRegister)
HANDLE_OPTIONAL(rmRegister)
HANDLE_OPTIONAL(relocation)
break;
@@ -755,8 +758,14 @@ void RecognizableInstr::emitInstructionSpecifier(DisassemblerTables &tables) {
case X86Local::MRM7m:
// Operand 1 is a memory operand (possibly SIB-extended)
// Operand 2 (optional) is an immediate or relocation.
- assert(numPhysicalOperands >= 1 && numPhysicalOperands <= 2 &&
- "Unexpected number of operands for MRMnMFrm");
+ if (HasVEX_4VPrefix)
+ assert(numPhysicalOperands >= 2 && numPhysicalOperands <= 3 &&
+ "Unexpected number of operands for MRMnMFrm");
+ else
+ assert(numPhysicalOperands >= 1 && numPhysicalOperands <= 2 &&
+ "Unexpected number of operands for MRMnMFrm");
+ if (HasVEX_4VPrefix)
+ HANDLE_OPERAND(vvvvRegister)
HANDLE_OPERAND(memory)
HANDLE_OPTIONAL(relocation)
break;
@@ -845,10 +854,43 @@ void RecognizableInstr::emitDecodePath(DisassemblerTables &tables) const {
case X86Local::T8:
case X86Local::TF:
opcodeType = THREEBYTE_38;
- if (needsModRMForDecode(Form))
- filter = new ModFilter(isRegFormat(Form));
- else
- filter = new DumbFilter();
+ switch (Opcode) {
+ default:
+ if (needsModRMForDecode(Form))
+ filter = new ModFilter(isRegFormat(Form));
+ else
+ filter = new DumbFilter();
+ break;
+#define EXTENSION_TABLE(n) case 0x##n:
+ THREE_BYTE_38_EXTENSION_TABLES
+#undef EXTENSION_TABLE
+ switch (Form) {
+ default:
+ llvm_unreachable("Unhandled two-byte extended opcode");
+ case X86Local::MRM0r:
+ case X86Local::MRM1r:
+ case X86Local::MRM2r:
+ case X86Local::MRM3r:
+ case X86Local::MRM4r:
+ case X86Local::MRM5r:
+ case X86Local::MRM6r:
+ case X86Local::MRM7r:
+ filter = new ExtendedFilter(true, Form - X86Local::MRM0r);
+ break;
+ case X86Local::MRM0m:
+ case X86Local::MRM1m:
+ case X86Local::MRM2m:
+ case X86Local::MRM3m:
+ case X86Local::MRM4m:
+ case X86Local::MRM5m:
+ case X86Local::MRM6m:
+ case X86Local::MRM7m:
+ filter = new ExtendedFilter(false, Form - X86Local::MRM0m);
+ break;
+ MRM_MAPPING
+ } // switch (Form)
+ break;
+ } // switch (Opcode)
opcodeToSet = Opcode;
break;
case X86Local::P_TA: