Skip to content

Commit

Permalink
Add support for X86 blsr, blsmsk, and blsi instructions. Required ext…
Browse files Browse the repository at this point in the history
…ra 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
  • Loading branch information
topperc committed Oct 15, 2011
1 parent 4d83b79 commit 566f233
Show file tree
Hide file tree
Showing 7 changed files with 180 additions and 25 deletions.
9 changes: 7 additions & 2 deletions lib/Target/X86/MCTargetDesc/X86BaseInfo.h
Original file line number Diff line number Diff line change
Expand Up @@ -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:
Expand Down
32 changes: 18 additions & 14 deletions lib/Target/X86/MCTargetDesc/X86MCCodeEmitter.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -63,9 +63,8 @@ class X86MCCodeEmitter : public MCCodeEmitter {
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.
Expand Down Expand Up @@ -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
Expand All @@ -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)
Expand Down Expand Up @@ -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);
Expand Down
22 changes: 21 additions & 1 deletion lib/Target/X86/X86InstrInfo.td
Original file line number Diff line number Diff line change
Expand Up @@ -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),
Expand Down Expand Up @@ -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.
//===----------------------------------------------------------------------===//
Expand Down
18 changes: 18 additions & 0 deletions test/MC/Disassembler/X86/simple-tests.txt
Original file line number Diff line number Diff line change
Expand Up @@ -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
9 changes: 9 additions & 0 deletions test/MC/Disassembler/X86/x86-32.txt
Original file line number Diff line number Diff line change
Expand Up @@ -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
57 changes: 57 additions & 0 deletions test/MC/X86/x86_64-bmi-encoding.s
Original file line number Diff line number Diff line change
@@ -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
58 changes: 50 additions & 8 deletions utils/TableGen/X86RecognizableInstr.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down Expand Up @@ -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;
Expand All @@ -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;
Expand Down Expand Up @@ -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:
Expand Down

0 comments on commit 566f233

Please sign in to comment.