diff options
-rw-r--r-- | lib/Target/X86/MCTargetDesc/X86BaseInfo.h | 9 | ||||
-rw-r--r-- | lib/Target/X86/MCTargetDesc/X86MCCodeEmitter.cpp | 32 | ||||
-rw-r--r-- | lib/Target/X86/X86InstrInfo.td | 22 | ||||
-rw-r--r-- | test/MC/Disassembler/X86/simple-tests.txt | 18 | ||||
-rw-r--r-- | test/MC/Disassembler/X86/x86-32.txt | 9 | ||||
-rw-r--r-- | test/MC/X86/x86_64-bmi-encoding.s | 57 | ||||
-rw-r--r-- | utils/TableGen/X86RecognizableInstr.cpp | 58 |
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: |