From b53fa8bf19a51f0c49a9f8b6ede3e2ff3bdfb961 Mon Sep 17 00:00:00 2001 From: Craig Topper Date: Sun, 16 Oct 2011 07:55:05 +0000 Subject: [PATCH] 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 --- lib/Target/X86/MCTargetDesc/X86BaseInfo.h | 17 ++++---- .../X86/MCTargetDesc/X86MCCodeEmitter.cpp | 42 ++++++------------- lib/Target/X86/X86.td | 4 +- lib/Target/X86/X86InstrFormats.td | 12 ++++-- lib/Target/X86/X86InstrInfo.td | 22 ++++++---- lib/Target/X86/X86Subtarget.cpp | 5 +++ lib/Target/X86/X86Subtarget.h | 4 ++ test/MC/Disassembler/X86/simple-tests.txt | 12 ++++++ test/MC/Disassembler/X86/x86-32.txt | 6 +++ test/MC/X86/x86_64-bmi-encoding.s | 16 +++++++ utils/TableGen/X86RecognizableInstr.cpp | 22 ++++------ utils/TableGen/X86RecognizableInstr.h | 4 +- 12 files changed, 101 insertions(+), 65 deletions(-) diff --git a/lib/Target/X86/MCTargetDesc/X86BaseInfo.h b/lib/Target/X86/MCTargetDesc/X86BaseInfo.h index ce24904f508..30ff1fd4aa9 100644 --- a/lib/Target/X86/MCTargetDesc/X86BaseInfo.h +++ b/lib/Target/X86/MCTargetDesc/X86BaseInfo.h @@ -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. diff --git a/lib/Target/X86/MCTargetDesc/X86MCCodeEmitter.cpp b/lib/Target/X86/MCTargetDesc/X86MCCodeEmitter.cpp index 55c6010ddde..91f672b1e45 100644 --- a/lib/Target/X86/MCTargetDesc/X86MCCodeEmitter.cpp +++ b/lib/Target/X86/MCTargetDesc/X86MCCodeEmitter.cpp @@ -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; } diff --git a/lib/Target/X86/X86.td b/lib/Target/X86/X86.td index 104b91fd353..7ee7df5de86 100644 --- a/lib/Target/X86/X86.td +++ b/lib/Target/X86/X86.td @@ -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]>; diff --git a/lib/Target/X86/X86InstrFormats.td b/lib/Target/X86/X86InstrFormats.td index 0a1590b3e0a..d291e4385f9 100644 --- a/lib/Target/X86/X86InstrFormats.td +++ b/lib/Target/X86/X86InstrFormats.td @@ -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 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 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 pattern> diff --git a/lib/Target/X86/X86InstrInfo.td b/lib/Target/X86/X86InstrInfo.td index fd4ecd4d94f..4a5912dc36f 100644 --- a/lib/Target/X86/X86InstrInfo.td +++ b/lib/Target/X86/X86InstrInfo.td @@ -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 { - def rr : I<0xF7, MRMSrcReg, (outs RC:$dst), (ins RC:$src1, RC:$src2), +multiclass bmi_bextr_bzhi opc, string mnemonic, RegisterClass RC, + X86MemOperand x86memop> { + def rr : I, T8, VEX_4V; - def rm : I<0xF7, MRMSrcMem, (outs RC:$dst), (ins x86memop:$src1, RC:$src2), + []>, T8, VEX_4VOp3; + def rm : I, 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; } //===----------------------------------------------------------------------===// diff --git a/lib/Target/X86/X86Subtarget.cpp b/lib/Target/X86/X86Subtarget.cpp index 670073a07bb..c08dac9f999 100644 --- a/lib/Target/X86/X86Subtarget.cpp +++ b/lib/Target/X86/X86Subtarget.cpp @@ -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) diff --git a/lib/Target/X86/X86Subtarget.h b/lib/Target/X86/X86Subtarget.h index 3258d3d0ada..81fa176bd07 100644 --- a/lib/Target/X86/X86Subtarget.h +++ b/lib/Target/X86/X86Subtarget.h @@ -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; } diff --git a/test/MC/Disassembler/X86/simple-tests.txt b/test/MC/Disassembler/X86/simple-tests.txt index b82cac69557..03a9db6257e 100644 --- a/test/MC/Disassembler/X86/simple-tests.txt +++ b/test/MC/Disassembler/X86/simple-tests.txt @@ -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 diff --git a/test/MC/Disassembler/X86/x86-32.txt b/test/MC/Disassembler/X86/x86-32.txt index 7e02b395e41..7e4e7083c3a 100644 --- a/test/MC/Disassembler/X86/x86-32.txt +++ b/test/MC/Disassembler/X86/x86-32.txt @@ -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 diff --git a/test/MC/X86/x86_64-bmi-encoding.s b/test/MC/X86/x86_64-bmi-encoding.s index ac08260b111..ba931d53d07 100644 --- a/test/MC/X86/x86_64-bmi-encoding.s +++ b/test/MC/X86/x86_64-bmi-encoding.s @@ -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 diff --git a/utils/TableGen/X86RecognizableInstr.cpp b/utils/TableGen/X86RecognizableInstr.cpp index 6c4c584651a..b3a316d6c70 100644 --- a/utils/TableGen/X86RecognizableInstr.cpp +++ b/utils/TableGen/X86RecognizableInstr.cpp @@ -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) diff --git a/utils/TableGen/X86RecognizableInstr.h b/utils/TableGen/X86RecognizableInstr.h index 7ed820b80dd..42a5fec1d35 100644 --- a/utils/TableGen/X86RecognizableInstr.h +++ b/utils/TableGen/X86RecognizableInstr.h @@ -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;