mirror of
https://github.com/RPCSX/llvm.git
synced 2024-11-26 13:10:34 +00:00
Add X86 BZHI instruction as well as BMI2 feature detection.
git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@142122 91177308-0d34-0410-b5e6-96231b3b80d8
This commit is contained in:
parent
dc479c4a89
commit
b53fa8bf19
@ -387,20 +387,24 @@ namespace X86II {
|
||||
/// and the additional register is encoded in VEX_VVVV prefix.
|
||||
VEX_4V = 1U << 2,
|
||||
|
||||
/// VEX_4VOp3 - Similar to VEX_4V, but used on instructions that encode
|
||||
/// operand 3 with VEX.vvvv.
|
||||
VEX_4VOp3 = 1U << 3,
|
||||
|
||||
/// VEX_I8IMM - Specifies that the last register used in a AVX instruction,
|
||||
/// must be encoded in the i8 immediate field. This usually happens in
|
||||
/// instructions with 4 operands.
|
||||
VEX_I8IMM = 1U << 3,
|
||||
VEX_I8IMM = 1U << 4,
|
||||
|
||||
/// VEX_L - Stands for a bit in the VEX opcode prefix meaning the current
|
||||
/// instruction uses 256-bit wide registers. This is usually auto detected
|
||||
/// if a VR256 register is used, but some AVX instructions also have this
|
||||
/// field marked when using a f256 memory references.
|
||||
VEX_L = 1U << 4,
|
||||
VEX_L = 1U << 5,
|
||||
|
||||
// VEX_LIG - Specifies that this instruction ignores the L-bit in the VEX
|
||||
// prefix. Usually used for scalar instructions. Needed by disassembler.
|
||||
VEX_LIG = 1U << 5,
|
||||
VEX_LIG = 1U << 6,
|
||||
|
||||
/// Has3DNow0F0FOpcode - This flag indicates that the instruction uses the
|
||||
/// wacky 0x0F 0x0F prefix for 3DNow! instructions. The manual documents
|
||||
@ -408,7 +412,7 @@ namespace X86II {
|
||||
/// storing a classifier in the imm8 field. To simplify our implementation,
|
||||
/// we handle this by storeing the classifier in the opcode field and using
|
||||
/// this flag to indicate that the encoder should do the wacky 3DNow! thing.
|
||||
Has3DNow0F0FOpcode = 1U << 6
|
||||
Has3DNow0F0FOpcode = 1U << 7
|
||||
};
|
||||
|
||||
// getBaseOpcodeFor - This function returns the "base" X86 opcode for the
|
||||
@ -477,12 +481,9 @@ 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 && !IsBEXTR)
|
||||
if (HasVEX_4V)
|
||||
++FirstMemOp;// Skip the register source (which is encoded in VEX_VVVV).
|
||||
|
||||
// FIXME: Maybe lea should have its own form? This is a horrible hack.
|
||||
|
@ -386,9 +386,8 @@ void X86MCCodeEmitter::EmitVEXOpcodePrefix(uint64_t TSFlags, unsigned &CurByte,
|
||||
int MemOperand, const MCInst &MI,
|
||||
const MCInstrDesc &Desc,
|
||||
raw_ostream &OS) const {
|
||||
bool HasVEX_4V = false;
|
||||
if ((TSFlags >> X86II::VEXShift) & X86II::VEX_4V)
|
||||
HasVEX_4V = true;
|
||||
bool HasVEX_4V = (TSFlags >> X86II::VEXShift) & X86II::VEX_4V;
|
||||
bool HasVEX_4VOp3 = (TSFlags >> X86II::VEXShift) & X86II::VEX_4VOp3;
|
||||
|
||||
// VEX_R: opcode externsion equivalent to REX.R in
|
||||
// 1's complement (inverted) form
|
||||
@ -447,11 +446,6 @@ 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;
|
||||
@ -530,8 +524,7 @@ void X86MCCodeEmitter::EmitVEXOpcodePrefix(uint64_t TSFlags, unsigned &CurByte,
|
||||
if (X86II::isX86_64ExtendedReg(MI.getOperand(0).getReg()))
|
||||
VEX_R = 0x0;
|
||||
|
||||
// FIXME: BEXTR uses VEX.vvvv for Operand 3
|
||||
if (HasVEX_4V && !IsBEXTR)
|
||||
if (HasVEX_4V)
|
||||
VEX_4V = getVEXRegisterEncoding(MI, 1);
|
||||
|
||||
if (X86II::isX86_64ExtendedReg(
|
||||
@ -541,7 +534,7 @@ void X86MCCodeEmitter::EmitVEXOpcodePrefix(uint64_t TSFlags, unsigned &CurByte,
|
||||
MI.getOperand(MemOperand+X86::AddrIndexReg).getReg()))
|
||||
VEX_X = 0x0;
|
||||
|
||||
if (IsBEXTR)
|
||||
if (HasVEX_4VOp3)
|
||||
VEX_4V = getVEXRegisterEncoding(MI, X86::AddrNumOperands+1);
|
||||
break;
|
||||
case X86II::MRM0m: case X86II::MRM1m:
|
||||
@ -572,13 +565,12 @@ void X86MCCodeEmitter::EmitVEXOpcodePrefix(uint64_t TSFlags, unsigned &CurByte,
|
||||
VEX_R = 0x0;
|
||||
CurOp++;
|
||||
|
||||
// FIXME: BEXTR uses VEX.vvvv for Operand 3
|
||||
if (HasVEX_4V && !IsBEXTR)
|
||||
if (HasVEX_4V)
|
||||
VEX_4V = getVEXRegisterEncoding(MI, CurOp++);
|
||||
if (X86II::isX86_64ExtendedReg(MI.getOperand(CurOp).getReg()))
|
||||
VEX_B = 0x0;
|
||||
CurOp++;
|
||||
if (IsBEXTR)
|
||||
if (HasVEX_4VOp3)
|
||||
VEX_4V = getVEXRegisterEncoding(MI, CurOp);
|
||||
break;
|
||||
case X86II::MRMDestReg:
|
||||
@ -874,15 +866,11 @@ EncodeInstruction(const MCInst &MI, raw_ostream &OS,
|
||||
unsigned CurByte = 0;
|
||||
|
||||
// Is this instruction encoded using the AVX VEX prefix?
|
||||
bool HasVEXPrefix = false;
|
||||
bool HasVEXPrefix = (TSFlags >> X86II::VEXShift) & X86II::VEX;
|
||||
|
||||
// It uses the VEX.VVVV field?
|
||||
bool HasVEX_4V = false;
|
||||
|
||||
if ((TSFlags >> X86II::VEXShift) & X86II::VEX)
|
||||
HasVEXPrefix = true;
|
||||
if ((TSFlags >> X86II::VEXShift) & X86II::VEX_4V)
|
||||
HasVEX_4V = true;
|
||||
bool HasVEX_4V = (TSFlags >> X86II::VEXShift) & X86II::VEX_4V;
|
||||
bool HasVEX_4VOp3 = (TSFlags >> X86II::VEXShift) & X86II::VEX_4VOp3;
|
||||
|
||||
// Determine where the memory operand starts, if present.
|
||||
int MemoryOperand = X86II::getMemoryOperandNo(TSFlags, Opcode);
|
||||
@ -898,10 +886,6 @@ 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:
|
||||
@ -956,20 +940,20 @@ EncodeInstruction(const MCInst &MI, raw_ostream &OS,
|
||||
EmitByte(BaseOpcode, CurByte, OS);
|
||||
SrcRegNum = CurOp + 1;
|
||||
|
||||
if (HasVEX_4V && !IsBEXTR) // Skip 1st src (which is encoded in VEX_VVVV)
|
||||
if (HasVEX_4V) // 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)
|
||||
if (HasVEX_4VOp3)
|
||||
++CurOp;
|
||||
break;
|
||||
|
||||
case X86II::MRMSrcMem: {
|
||||
int AddrOperands = X86::AddrNumOperands;
|
||||
unsigned FirstMemOp = CurOp+1;
|
||||
if (HasVEX_4V && !IsBEXTR) {
|
||||
if (HasVEX_4V) {
|
||||
++AddrOperands;
|
||||
++FirstMemOp; // Skip the register source (which is encoded in VEX_VVVV).
|
||||
}
|
||||
@ -979,7 +963,7 @@ EncodeInstruction(const MCInst &MI, raw_ostream &OS,
|
||||
EmitMemModRMByte(MI, FirstMemOp, GetX86RegNum(MI.getOperand(CurOp)),
|
||||
TSFlags, CurByte, OS, Fixups);
|
||||
CurOp += AddrOperands + 1;
|
||||
if (IsBEXTR)
|
||||
if (HasVEX_4VOp3)
|
||||
++CurOp;
|
||||
break;
|
||||
}
|
||||
|
@ -106,6 +106,8 @@ def FeatureLZCNT : SubtargetFeature<"lzcnt", "HasLZCNT", "true",
|
||||
"Support LZCNT instruction">;
|
||||
def FeatureBMI : SubtargetFeature<"bmi", "HasBMI", "true",
|
||||
"Support BMI instructions">;
|
||||
def FeatureBMI2 : SubtargetFeature<"bmi2", "HasBMI2", "true",
|
||||
"Support BMI2 instructions">;
|
||||
|
||||
//===----------------------------------------------------------------------===//
|
||||
// X86 processors supported.
|
||||
@ -164,7 +166,7 @@ def : Proc<"core-avx-i", [FeatureSSE42, FeatureCMPXCHG16B,
|
||||
def : Proc<"core-avx2", [FeatureSSE42, FeatureCMPXCHG16B, FeatureAES,
|
||||
FeatureCLMUL, FeatureRDRAND, FeatureF16C,
|
||||
FeatureFMA3, FeatureMOVBE, FeatureLZCNT,
|
||||
FeatureBMI]>;
|
||||
FeatureBMI, FeatureBMI2]>;
|
||||
|
||||
def : Proc<"k6", [FeatureMMX]>;
|
||||
def : Proc<"k6-2", [Feature3DNow]>;
|
||||
|
@ -111,6 +111,7 @@ class TF { bits<5> Prefix = 17; }
|
||||
class VEX { bit hasVEXPrefix = 1; }
|
||||
class VEX_W { bit hasVEX_WPrefix = 1; }
|
||||
class VEX_4V : VEX { bit hasVEX_4VPrefix = 1; }
|
||||
class VEX_4VOp3 : VEX { bit hasVEX_4VOp3Prefix = 1; }
|
||||
class VEX_I8IMM { bit hasVEX_i8ImmReg = 1; }
|
||||
class VEX_L { bit hasVEX_L = 1; }
|
||||
class VEX_LIG { bit ignoresVEX_L = 1; }
|
||||
@ -148,6 +149,8 @@ class X86Inst<bits<8> opcod, Format f, ImmType i, dag outs, dag ins,
|
||||
bit hasVEXPrefix = 0; // Does this inst require a VEX prefix?
|
||||
bit hasVEX_WPrefix = 0; // Does this inst set the VEX_W field?
|
||||
bit hasVEX_4VPrefix = 0; // Does this inst require the VEX.VVVV field?
|
||||
bit hasVEX_4VOp3Prefix = 0; // Does this inst require the VEX.VVVV field to
|
||||
// encode the third operand?
|
||||
bit hasVEX_i8ImmReg = 0; // Does this inst require the last source register
|
||||
// to be encoded in a immediate field?
|
||||
bit hasVEX_L = 0; // Does this inst use large (256-bit) registers?
|
||||
@ -169,10 +172,11 @@ class X86Inst<bits<8> opcod, Format f, ImmType i, dag outs, dag ins,
|
||||
let TSFlags{33} = hasVEXPrefix;
|
||||
let TSFlags{34} = hasVEX_WPrefix;
|
||||
let TSFlags{35} = hasVEX_4VPrefix;
|
||||
let TSFlags{36} = hasVEX_i8ImmReg;
|
||||
let TSFlags{37} = hasVEX_L;
|
||||
let TSFlags{38} = ignoresVEX_L;
|
||||
let TSFlags{39} = has3DNow0F0FOpcode;
|
||||
let TSFlags{36} = hasVEX_4VOp3Prefix;
|
||||
let TSFlags{37} = hasVEX_i8ImmReg;
|
||||
let TSFlags{38} = hasVEX_L;
|
||||
let TSFlags{39} = ignoresVEX_L;
|
||||
let TSFlags{40} = has3DNow0F0FOpcode;
|
||||
}
|
||||
|
||||
class PseudoI<dag oops, dag iops, list<dag> pattern>
|
||||
|
@ -480,6 +480,7 @@ def HasRDRAND : Predicate<"Subtarget->hasRDRAND()">;
|
||||
def HasF16C : Predicate<"Subtarget->hasF16C()">;
|
||||
def HasLZCNT : Predicate<"Subtarget->hasLZCNT()">;
|
||||
def HasBMI : Predicate<"Subtarget->hasBMI()">;
|
||||
def HasBMI2 : Predicate<"Subtarget->hasBMI2()">;
|
||||
def FPStackf32 : Predicate<"!Subtarget->hasXMM()">;
|
||||
def FPStackf64 : Predicate<"!Subtarget->hasXMMInt()">;
|
||||
def HasCmpxchg16b: Predicate<"Subtarget->hasCmpxchg16b()">;
|
||||
@ -1422,19 +1423,24 @@ let Predicates = [HasBMI], Defs = [EFLAGS] in {
|
||||
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),
|
||||
multiclass bmi_bextr_bzhi<bits<8> opc, string mnemonic, RegisterClass RC,
|
||||
X86MemOperand x86memop> {
|
||||
def rr : I<opc, 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),
|
||||
[]>, T8, VEX_4VOp3;
|
||||
def rm : I<opc, MRMSrcMem, (outs RC:$dst), (ins x86memop:$src1, RC:$src2),
|
||||
!strconcat(mnemonic, "\t{$src2, $src1, $dst|$dst, $src1, $src2}"),
|
||||
[]>, T8, VEX_4V;
|
||||
[]>, T8, VEX_4VOp3;
|
||||
}
|
||||
|
||||
let Predicates = [HasBMI], Defs = [EFLAGS] in {
|
||||
defm BEXTR32 : bmi_bextr<"bextr{l}", GR32, i32mem>;
|
||||
defm BEXTR64 : bmi_bextr<"bextr{q}", GR64, i64mem>, VEX_W;
|
||||
defm BEXTR32 : bmi_bextr_bzhi<0xF7, "bextr{l}", GR32, i32mem>;
|
||||
defm BEXTR64 : bmi_bextr_bzhi<0xF7, "bextr{q}", GR64, i64mem>, VEX_W;
|
||||
}
|
||||
|
||||
let Predicates = [HasBMI2], Defs = [EFLAGS] in {
|
||||
defm BZHI32 : bmi_bextr_bzhi<0xF5, "bzhi{l}", GR32, i32mem>;
|
||||
defm BZHI64 : bmi_bextr_bzhi<0xF5, "bzhi{q}", GR64, i64mem>, VEX_W;
|
||||
}
|
||||
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
@ -283,6 +283,10 @@ void X86Subtarget::AutoDetectSubtargetFeatures() {
|
||||
HasBMI = true;
|
||||
ToggleFeature(X86::FeatureBMI);
|
||||
}
|
||||
if ((EBX >> 8) & 0x1) {
|
||||
HasBMI2 = true;
|
||||
ToggleFeature(X86::FeatureBMI2);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@ -307,6 +311,7 @@ X86Subtarget::X86Subtarget(const std::string &TT, const std::string &CPU,
|
||||
, HasF16C(false)
|
||||
, HasLZCNT(false)
|
||||
, HasBMI(false)
|
||||
, HasBMI2(false)
|
||||
, IsBTMemSlow(false)
|
||||
, IsUAMemFast(false)
|
||||
, HasVectorUAMem(false)
|
||||
|
@ -105,6 +105,9 @@ protected:
|
||||
/// HasBMI - Processor has BMI1 instructions.
|
||||
bool HasBMI;
|
||||
|
||||
/// HasBMI2 - Processor has BMI2 instructions.
|
||||
bool HasBMI2;
|
||||
|
||||
/// IsBTMemSlow - True if BT (bit test) of memory instructions are slow.
|
||||
bool IsBTMemSlow;
|
||||
|
||||
@ -192,6 +195,7 @@ public:
|
||||
bool hasF16C() const { return HasF16C; }
|
||||
bool hasLZCNT() const { return HasLZCNT; }
|
||||
bool hasBMI() const { return HasBMI; }
|
||||
bool hasBMI2() const { return HasBMI2; }
|
||||
bool isBTMemSlow() const { return IsBTMemSlow; }
|
||||
bool isUnalignedMemAccessFast() const { return IsUAMemFast; }
|
||||
bool hasVectorUAMem() const { return HasVectorUAMem; }
|
||||
|
@ -551,3 +551,15 @@
|
||||
|
||||
# CHECK: bextrq %r12, %r11, %r10
|
||||
0xc4 0x42 0x98 0xf7 0xd3
|
||||
|
||||
# CHECK: bzhil %r12d, (%rax), %r10d
|
||||
0xc4 0x62 0x18 0xf5 0x10
|
||||
|
||||
# CHECK: bzhil %r12d, %r11d, %r10d
|
||||
0xc4 0x42 0x18 0xf5 0xd3
|
||||
|
||||
# CHECK: bzhiq %r12, (%rax), %r10
|
||||
0xc4 0x62 0x98 0xf5 0x10
|
||||
|
||||
# CHECK: bzhiq %r12, %r11, %r10
|
||||
0xc4 0x42 0x98 0xf5 0xd3
|
||||
|
@ -513,3 +513,9 @@
|
||||
|
||||
# CHECK: bextrl %esi, %ebx, %edx
|
||||
0xc4 0xe2 0x08 0xf7 0xd3
|
||||
|
||||
# CHECK: bzhil %esi, (%eax), %edx
|
||||
0xc4 0xe2 0x08 0xf5 0x10
|
||||
|
||||
# CHECK: bzhil %esi, %ebx, %edx
|
||||
0xc4 0xe2 0x08 0xf5 0xd3
|
||||
|
@ -71,3 +71,19 @@
|
||||
// CHECK: bextrq %r12, %r11, %r10
|
||||
// CHECK: encoding: [0xc4,0x42,0x98,0xf7,0xd3]
|
||||
bextrq %r12, %r11, %r10
|
||||
|
||||
// CHECK: bzhil %r12d, (%rax), %r10d
|
||||
// CHECK: encoding: [0xc4,0x62,0x18,0xf5,0x10]
|
||||
bzhil %r12d, (%rax), %r10d
|
||||
|
||||
// CHECK: bzhil %r12d, %r11d, %r10d
|
||||
// CHECK: encoding: [0xc4,0x42,0x18,0xf5,0xd3]
|
||||
bzhil %r12d, %r11d, %r10d
|
||||
|
||||
// CHECK: bzhiq %r12, (%rax), %r10
|
||||
// CHECK: encoding: [0xc4,0x62,0x98,0xf5,0x10]
|
||||
bzhiq %r12, (%rax), %r10
|
||||
|
||||
// CHECK: bzhiq %r12, %r11, %r10
|
||||
// CHECK: encoding: [0xc4,0x42,0x98,0xf5,0xd3]
|
||||
bzhiq %r12, %r11, %r10
|
||||
|
@ -219,6 +219,7 @@ RecognizableInstr::RecognizableInstr(DisassemblerTables &tables,
|
||||
HasREX_WPrefix = Rec->getValueAsBit("hasREX_WPrefix");
|
||||
HasVEXPrefix = Rec->getValueAsBit("hasVEXPrefix");
|
||||
HasVEX_4VPrefix = Rec->getValueAsBit("hasVEX_4VPrefix");
|
||||
HasVEX_4VOp3Prefix = Rec->getValueAsBit("hasVEX_4VOp3Prefix");
|
||||
HasVEX_WPrefix = Rec->getValueAsBit("hasVEX_WPrefix");
|
||||
IgnoresVEX_L = Rec->getValueAsBit("ignoresVEX_L");
|
||||
HasLockPrefix = Rec->getValueAsBit("hasLockPrefix");
|
||||
@ -261,9 +262,6 @@ 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;
|
||||
}
|
||||
|
||||
@ -286,7 +284,7 @@ void RecognizableInstr::processInstr(DisassemblerTables &tables,
|
||||
InstructionContext RecognizableInstr::insnContext() const {
|
||||
InstructionContext insnContext;
|
||||
|
||||
if (HasVEX_4VPrefix || HasVEXPrefix) {
|
||||
if (HasVEX_4VPrefix || HasVEX_4VOp3Prefix|| HasVEXPrefix) {
|
||||
if (HasVEX_LPrefix && HasVEX_WPrefix)
|
||||
llvm_unreachable("Don't support VEX.L and VEX.W together");
|
||||
else if (HasOpSizePrefix && HasVEX_LPrefix)
|
||||
@ -686,7 +684,7 @@ void RecognizableInstr::emitInstructionSpecifier(DisassemblerTables &tables) {
|
||||
// - In AVX, there is a register operand in the VEX.vvvv field here -
|
||||
// Operand 3 (optional) is an immediate.
|
||||
|
||||
if (HasVEX_4VPrefix)
|
||||
if (HasVEX_4VPrefix || HasVEX_4VOp3Prefix)
|
||||
assert(numPhysicalOperands >= 3 && numPhysicalOperands <= 4 &&
|
||||
"Unexpected number of operands for MRMSrcRegFrm with VEX_4V");
|
||||
else
|
||||
@ -695,15 +693,14 @@ void RecognizableInstr::emitInstructionSpecifier(DisassemblerTables &tables) {
|
||||
|
||||
HANDLE_OPERAND(roRegister)
|
||||
|
||||
if (HasVEX_4VPrefix && !IsBEXTR)
|
||||
if (HasVEX_4VPrefix)
|
||||
// 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)
|
||||
if (HasVEX_4VOp3Prefix)
|
||||
HANDLE_OPERAND(vvvvRegister)
|
||||
|
||||
HANDLE_OPTIONAL(immediate)
|
||||
@ -713,8 +710,8 @@ void RecognizableInstr::emitInstructionSpecifier(DisassemblerTables &tables) {
|
||||
// Operand 2 is a memory operand (possibly SIB-extended)
|
||||
// - In AVX, there is a register operand in the VEX.vvvv field here -
|
||||
// Operand 3 (optional) is an immediate.
|
||||
|
||||
if (HasVEX_4VPrefix)
|
||||
|
||||
if (HasVEX_4VPrefix || HasVEX_4VOp3Prefix)
|
||||
assert(numPhysicalOperands >= 3 && numPhysicalOperands <= 4 &&
|
||||
"Unexpected number of operands for MRMSrcMemFrm with VEX_4V");
|
||||
else
|
||||
@ -723,15 +720,14 @@ void RecognizableInstr::emitInstructionSpecifier(DisassemblerTables &tables) {
|
||||
|
||||
HANDLE_OPERAND(roRegister)
|
||||
|
||||
if (HasVEX_4VPrefix && !IsBEXTR)
|
||||
if (HasVEX_4VPrefix)
|
||||
// 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)
|
||||
if (HasVEX_4VOp3Prefix)
|
||||
HANDLE_OPERAND(vvvvRegister)
|
||||
|
||||
HANDLE_OPTIONAL(immediate)
|
||||
|
@ -56,6 +56,8 @@ private:
|
||||
bool HasVEXPrefix;
|
||||
/// The hasVEX_4VPrefix field from the record
|
||||
bool HasVEX_4VPrefix;
|
||||
/// The hasVEX_4VOp3Prefix field from the record
|
||||
bool HasVEX_4VOp3Prefix;
|
||||
/// The hasVEX_WPrefix field from the record
|
||||
bool HasVEX_WPrefix;
|
||||
/// Inferred from the operands; indicates whether the L bit in the VEX prefix is set
|
||||
@ -70,8 +72,6 @@ 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;
|
||||
|
Loading…
Reference in New Issue
Block a user