mirror of
https://github.com/c64scene-ar/llvm-6502.git
synced 2025-02-12 03:32:10 +00:00
Add X86 BEXTR instruction. This instruction uses VEX.vvvv to encode Operand 3 instead of Operand 2 so needs special casing in the disassembler and code emitter. Ultimately, should pass this information from tablegen
git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@142105 91177308-0d34-0410-b5e6-96231b3b80d8
This commit is contained in:
parent
4025061b8a
commit
17730847d5
@ -462,7 +462,7 @@ namespace X86II {
|
||||
/// is duplicated in the MCInst (e.g. "EAX = addl EAX, [mem]") it is only
|
||||
/// counted as one operand.
|
||||
///
|
||||
static inline int getMemoryOperandNo(uint64_t TSFlags) {
|
||||
static inline int getMemoryOperandNo(uint64_t TSFlags, unsigned Opcode) {
|
||||
switch (TSFlags & X86II::FormMask) {
|
||||
case X86II::MRMInitReg: assert(0 && "FIXME: Remove this form");
|
||||
default: assert(0 && "Unknown FormMask value in getMemoryOperandNo!");
|
||||
@ -477,9 +477,12 @@ namespace X86II {
|
||||
case X86II::MRMDestMem:
|
||||
return 0;
|
||||
case X86II::MRMSrcMem: {
|
||||
// FIXME: BEXTR uses VEX.vvvv for Operand 3
|
||||
bool IsBEXTR = (Opcode == X86::BEXTR32rr || Opcode == X86::BEXTR32rm ||
|
||||
Opcode == X86::BEXTR64rr || Opcode == X86::BEXTR64rm);
|
||||
bool HasVEX_4V = (TSFlags >> X86II::VEXShift) & X86II::VEX_4V;
|
||||
unsigned FirstMemOp = 1;
|
||||
if (HasVEX_4V)
|
||||
if (HasVEX_4V && !IsBEXTR)
|
||||
++FirstMemOp;// Skip the register source (which is encoded in VEX_VVVV).
|
||||
|
||||
// FIXME: Maybe lea should have its own form? This is a horrible hack.
|
||||
|
@ -447,6 +447,11 @@ void X86MCCodeEmitter::EmitVEXOpcodePrefix(uint64_t TSFlags, unsigned &CurByte,
|
||||
//
|
||||
unsigned char VEX_PP = 0;
|
||||
|
||||
// FIXME: BEXTR uses VEX.vvvv for Operand 3 instead of Operand 2
|
||||
unsigned Opcode = MI.getOpcode();
|
||||
bool IsBEXTR = (Opcode == X86::BEXTR32rr || Opcode == X86::BEXTR32rm ||
|
||||
Opcode == X86::BEXTR64rr || Opcode == X86::BEXTR64rm);
|
||||
|
||||
// Encode the operand size opcode prefix as needed.
|
||||
if (TSFlags & X86II::OpSize)
|
||||
VEX_PP = 0x01;
|
||||
@ -525,7 +530,8 @@ void X86MCCodeEmitter::EmitVEXOpcodePrefix(uint64_t TSFlags, unsigned &CurByte,
|
||||
if (X86II::isX86_64ExtendedReg(MI.getOperand(0).getReg()))
|
||||
VEX_R = 0x0;
|
||||
|
||||
if (HasVEX_4V)
|
||||
// FIXME: BEXTR uses VEX.vvvv for Operand 3
|
||||
if (HasVEX_4V && !IsBEXTR)
|
||||
VEX_4V = getVEXRegisterEncoding(MI, 1);
|
||||
|
||||
if (X86II::isX86_64ExtendedReg(
|
||||
@ -534,6 +540,9 @@ void X86MCCodeEmitter::EmitVEXOpcodePrefix(uint64_t TSFlags, unsigned &CurByte,
|
||||
if (X86II::isX86_64ExtendedReg(
|
||||
MI.getOperand(MemOperand+X86::AddrIndexReg).getReg()))
|
||||
VEX_X = 0x0;
|
||||
|
||||
if (IsBEXTR)
|
||||
VEX_4V = getVEXRegisterEncoding(MI, X86::AddrNumOperands+1);
|
||||
break;
|
||||
case X86II::MRM0m: case X86II::MRM1m:
|
||||
case X86II::MRM2m: case X86II::MRM3m:
|
||||
@ -563,10 +572,14 @@ void X86MCCodeEmitter::EmitVEXOpcodePrefix(uint64_t TSFlags, unsigned &CurByte,
|
||||
VEX_R = 0x0;
|
||||
CurOp++;
|
||||
|
||||
if (HasVEX_4V)
|
||||
// FIXME: BEXTR uses VEX.vvvv for Operand 3
|
||||
if (HasVEX_4V && !IsBEXTR)
|
||||
VEX_4V = getVEXRegisterEncoding(MI, CurOp++);
|
||||
if (X86II::isX86_64ExtendedReg(MI.getOperand(CurOp).getReg()))
|
||||
VEX_B = 0x0;
|
||||
CurOp++;
|
||||
if (IsBEXTR)
|
||||
VEX_4V = getVEXRegisterEncoding(MI, CurOp);
|
||||
break;
|
||||
case X86II::MRMDestReg:
|
||||
// MRMDestReg instructions forms:
|
||||
@ -872,7 +885,7 @@ EncodeInstruction(const MCInst &MI, raw_ostream &OS,
|
||||
HasVEX_4V = true;
|
||||
|
||||
// Determine where the memory operand starts, if present.
|
||||
int MemoryOperand = X86II::getMemoryOperandNo(TSFlags);
|
||||
int MemoryOperand = X86II::getMemoryOperandNo(TSFlags, Opcode);
|
||||
if (MemoryOperand != -1) MemoryOperand += CurOp;
|
||||
|
||||
if (!HasVEXPrefix)
|
||||
@ -885,6 +898,10 @@ EncodeInstruction(const MCInst &MI, raw_ostream &OS,
|
||||
if ((TSFlags >> X86II::VEXShift) & X86II::Has3DNow0F0FOpcode)
|
||||
BaseOpcode = 0x0F; // Weird 3DNow! encoding.
|
||||
|
||||
// FIXME: BEXTR uses VEX.vvvv for Operand 3 instead of Operand 2
|
||||
bool IsBEXTR = (Opcode == X86::BEXTR32rr || Opcode == X86::BEXTR32rm ||
|
||||
Opcode == X86::BEXTR64rr || Opcode == X86::BEXTR64rm);
|
||||
|
||||
unsigned SrcRegNum = 0;
|
||||
switch (TSFlags & X86II::FormMask) {
|
||||
case X86II::MRMInitReg:
|
||||
@ -939,18 +956,20 @@ EncodeInstruction(const MCInst &MI, raw_ostream &OS,
|
||||
EmitByte(BaseOpcode, CurByte, OS);
|
||||
SrcRegNum = CurOp + 1;
|
||||
|
||||
if (HasVEX_4V) // Skip 1st src (which is encoded in VEX_VVVV)
|
||||
if (HasVEX_4V && !IsBEXTR) // Skip 1st src (which is encoded in VEX_VVVV)
|
||||
SrcRegNum++;
|
||||
|
||||
EmitRegModRMByte(MI.getOperand(SrcRegNum),
|
||||
GetX86RegNum(MI.getOperand(CurOp)), CurByte, OS);
|
||||
CurOp = SrcRegNum + 1;
|
||||
if (IsBEXTR)
|
||||
++CurOp;
|
||||
break;
|
||||
|
||||
case X86II::MRMSrcMem: {
|
||||
int AddrOperands = X86::AddrNumOperands;
|
||||
unsigned FirstMemOp = CurOp+1;
|
||||
if (HasVEX_4V) {
|
||||
if (HasVEX_4V && !IsBEXTR) {
|
||||
++AddrOperands;
|
||||
++FirstMemOp; // Skip the register source (which is encoded in VEX_VVVV).
|
||||
}
|
||||
@ -960,6 +979,8 @@ EncodeInstruction(const MCInst &MI, raw_ostream &OS,
|
||||
EmitMemModRMByte(MI, FirstMemOp, GetX86RegNum(MI.getOperand(CurOp)),
|
||||
TSFlags, CurByte, OS, Fixups);
|
||||
CurOp += AddrOperands + 1;
|
||||
if (IsBEXTR)
|
||||
++CurOp;
|
||||
break;
|
||||
}
|
||||
|
||||
|
@ -1408,21 +1408,33 @@ let Predicates = [HasBMI], Defs = [EFLAGS] in {
|
||||
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}"), []>;
|
||||
!strconcat(mnemonic, "\t{$src, $dst|$dst, $src}"), []>, T8, VEX_4V;
|
||||
def rm : I<0xF3, MemMRM, (outs RC:$dst), (ins x86memop:$src),
|
||||
!strconcat(mnemonic, "\t{$src, $dst|$dst, $src}"), []>;
|
||||
!strconcat(mnemonic, "\t{$src, $dst|$dst, $src}"), []>, T8, VEX_4V;
|
||||
}
|
||||
|
||||
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;
|
||||
defm BLSR32 : bmi_bls<"blsr{l}", MRM1r, MRM1m, GR32, i32mem>;
|
||||
defm BLSR64 : bmi_bls<"blsr{q}", MRM1r, MRM1m, GR64, i64mem>, VEX_W;
|
||||
defm BLSMSK32 : bmi_bls<"blsmsk{l}", MRM2r, MRM2m, GR32, i32mem>;
|
||||
defm BLSMSK64 : bmi_bls<"blsmsk{q}", MRM2r, MRM2m, GR64, i64mem>, VEX_W;
|
||||
defm BLSI32 : bmi_bls<"blsi{l}", MRM3r, MRM3m, GR32, i32mem>;
|
||||
defm BLSI64 : bmi_bls<"blsi{q}", MRM3r, MRM3m, GR64, i64mem>, VEX_W;
|
||||
}
|
||||
|
||||
multiclass bmi_bextr<string mnemonic, RegisterClass RC,
|
||||
X86MemOperand x86memop> {
|
||||
def rr : I<0xF7, MRMSrcReg, (outs RC:$dst), (ins RC:$src1, RC:$src2),
|
||||
!strconcat(mnemonic, "\t{$src2, $src1, $dst|$dst, $src1, $src2}"),
|
||||
[]>, T8, VEX_4V;
|
||||
def rm : I<0xF7, MRMSrcMem, (outs RC:$dst), (ins x86memop:$src1, RC:$src2),
|
||||
!strconcat(mnemonic, "\t{$src2, $src1, $dst|$dst, $src1, $src2}"),
|
||||
[]>, T8, VEX_4V;
|
||||
}
|
||||
|
||||
let Predicates = [HasBMI], Defs = [EFLAGS] in {
|
||||
defm BEXTR32 : bmi_bextr<"bextr{l}", GR32, i32mem>;
|
||||
defm BEXTR64 : bmi_bextr<"bextr{q}", GR64, i64mem>, VEX_W;
|
||||
}
|
||||
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
@ -536,3 +536,15 @@
|
||||
|
||||
# CHECK: blsiq (%rax), %r15
|
||||
0xc4 0xe2 0x80 0xf3 0x18
|
||||
|
||||
# CHECK: bextrl %r12d, (%rax), %r10d
|
||||
0xc4 0x62 0x18 0xf7 0x10
|
||||
|
||||
# CHECK: bextrl %r12d, %r11d, %r10d
|
||||
0xc4 0x42 0x18 0xf7 0xd3
|
||||
|
||||
# CHECK: bextrq %r12, (%rax), %r10
|
||||
0xc4 0x62 0x98 0xf7 0x10
|
||||
|
||||
# CHECK: bextrq %r12, %r11, %r10
|
||||
0xc4 0x42 0x98 0xf7 0xd3
|
||||
|
@ -504,3 +504,9 @@
|
||||
|
||||
# CHECK: blsil (%eax), %edi
|
||||
0xc4 0xe2 0x40 0xf3 0x18
|
||||
|
||||
# CHECK: bextrl %esi, (%eax), %edx
|
||||
0xc4 0xe2 0x08 0xf7 0x10
|
||||
|
||||
# CHECK: bextrl %esi, %ebx, %edx
|
||||
0xc4 0xe2 0x08 0xf7 0xd3
|
||||
|
@ -55,3 +55,19 @@
|
||||
// CHECK: andnq (%rax), %r11, %r10
|
||||
// CHECK: encoding: [0xc4,0x62,0xa0,0xf2,0x10]
|
||||
andnq (%rax), %r11, %r10
|
||||
|
||||
// CHECK: bextrl %r12d, (%rax), %r10d
|
||||
// CHECK: encoding: [0xc4,0x62,0x18,0xf7,0x10]
|
||||
bextrl %r12d, (%rax), %r10d
|
||||
|
||||
// CHECK: bextrl %r12d, %r11d, %r10d
|
||||
// CHECK: encoding: [0xc4,0x42,0x18,0xf7,0xd3]
|
||||
bextrl %r12d, %r11d, %r10d
|
||||
|
||||
// CHECK: bextrq %r12, (%rax), %r10
|
||||
// CHECK: encoding: [0xc4,0x62,0x98,0xf7,0x10]
|
||||
bextrq %r12, (%rax), %r10
|
||||
|
||||
// CHECK: bextrq %r12, %r11, %r10
|
||||
// CHECK: encoding: [0xc4,0x42,0x98,0xf7,0xd3]
|
||||
bextrq %r12, %r11, %r10
|
||||
|
@ -233,7 +233,7 @@ RecognizableInstr::RecognizableInstr(DisassemblerTables &tables,
|
||||
(Name.find("CRC32") != Name.npos);
|
||||
HasFROperands = hasFROperands();
|
||||
HasVEX_LPrefix = has256BitOperands() || Rec->getValueAsBit("hasVEX_L");
|
||||
|
||||
|
||||
// Check for 64-bit inst which does not require REX
|
||||
Is32Bit = false;
|
||||
Is64Bit = false;
|
||||
@ -265,6 +265,9 @@ RecognizableInstr::RecognizableInstr(DisassemblerTables &tables,
|
||||
Rec->getName().find("PUSH64") != Name.npos ||
|
||||
Rec->getName().find("POP64") != Name.npos;
|
||||
|
||||
// FIXME: BEXTR uses VEX.vvvv to encode its third operand
|
||||
IsBEXTR = Rec->getName().find("BEXTR") != Name.npos;
|
||||
|
||||
ShouldBeEmitted = true;
|
||||
}
|
||||
|
||||
@ -695,13 +698,18 @@ void RecognizableInstr::emitInstructionSpecifier(DisassemblerTables &tables) {
|
||||
"Unexpected number of operands for MRMSrcRegFrm");
|
||||
|
||||
HANDLE_OPERAND(roRegister)
|
||||
|
||||
if (HasVEX_4VPrefix)
|
||||
|
||||
if (HasVEX_4VPrefix && !IsBEXTR)
|
||||
// FIXME: In AVX, the register below becomes the one encoded
|
||||
// in ModRMVEX and the one above the one in the VEX.VVVV field
|
||||
HANDLE_OPERAND(vvvvRegister)
|
||||
|
||||
|
||||
HANDLE_OPERAND(rmRegister)
|
||||
|
||||
// FIXME: BEXTR uses VEX.vvvv for Operand 3
|
||||
if (IsBEXTR)
|
||||
HANDLE_OPERAND(vvvvRegister)
|
||||
|
||||
HANDLE_OPTIONAL(immediate)
|
||||
break;
|
||||
case X86Local::MRMSrcMem:
|
||||
@ -719,12 +727,17 @@ void RecognizableInstr::emitInstructionSpecifier(DisassemblerTables &tables) {
|
||||
|
||||
HANDLE_OPERAND(roRegister)
|
||||
|
||||
if (HasVEX_4VPrefix)
|
||||
if (HasVEX_4VPrefix && !IsBEXTR)
|
||||
// FIXME: In AVX, the register below becomes the one encoded
|
||||
// in ModRMVEX and the one above the one in the VEX.VVVV field
|
||||
HANDLE_OPERAND(vvvvRegister)
|
||||
|
||||
HANDLE_OPERAND(memory)
|
||||
|
||||
// FIXME: BEXTR uses VEX.vvvv for Operand 3
|
||||
if (IsBEXTR)
|
||||
HANDLE_OPERAND(vvvvRegister)
|
||||
|
||||
HANDLE_OPTIONAL(immediate)
|
||||
break;
|
||||
case X86Local::MRM0r:
|
||||
|
@ -70,7 +70,9 @@ private:
|
||||
bool Is64Bit;
|
||||
// Whether the instruction has the predicate "In32BitMode"
|
||||
bool Is32Bit;
|
||||
|
||||
// Whether the instruction is BEXTR
|
||||
bool IsBEXTR;
|
||||
|
||||
/// The instruction name as listed in the tables
|
||||
std::string Name;
|
||||
/// The AT&T AsmString for the instruction
|
||||
|
Loading…
x
Reference in New Issue
Block a user