mirror of
https://github.com/c64scene-ar/llvm-6502.git
synced 2024-12-14 11:32:34 +00:00
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
This commit is contained in:
parent
4d83b79c76
commit
566f233ba6
@ -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:
|
||||
|
@ -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);
|
||||
|
@ -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.
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
@ -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
|
||||
|
@ -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
test/MC/X86/x86_64-bmi-encoding.s
Normal file
57
test/MC/X86/x86_64-bmi-encoding.s
Normal file
@ -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
|
@ -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:
|
||||
|
Loading…
Reference in New Issue
Block a user