forked from OSchip/llvm-project
[X86][tablgen] Add class RecognizableInstrBase to simplify X86 code, NFCI
This commit is contained in:
parent
392bb8cf1f
commit
bf11ed293a
|
@ -13,6 +13,7 @@
|
|||
|
||||
#include "CodeGenInstruction.h"
|
||||
#include "CodeGenTarget.h"
|
||||
#include "X86RecognizableInstr.h"
|
||||
#include "llvm/TableGen/Error.h"
|
||||
#include "llvm/TableGen/TableGenBackend.h"
|
||||
|
||||
|
@ -109,28 +110,25 @@ public:
|
|||
IsMatch(const CodeGenInstruction *EVEXInst) : EVEXInst(EVEXInst) {}
|
||||
|
||||
bool operator()(const CodeGenInstruction *VEXInst) {
|
||||
Record *RecE = EVEXInst->TheDef;
|
||||
Record *RecV = VEXInst->TheDef;
|
||||
bool EVEX_W = RecE->getValueAsBit("HasVEX_W");
|
||||
bool VEX_W = RecV->getValueAsBit("HasVEX_W");
|
||||
bool VEX_WIG = RecV->getValueAsBit("IgnoresVEX_W");
|
||||
bool EVEX_WIG = RecE->getValueAsBit("IgnoresVEX_W");
|
||||
bool EVEX_W1_VEX_W0 = RecE->getValueAsBit("EVEX_W1_VEX_W0");
|
||||
X86Disassembler::RecognizableInstrBase VEXRI(*VEXInst);
|
||||
X86Disassembler::RecognizableInstrBase EVEXRI(*EVEXInst);
|
||||
bool VEX_W = VEXRI.HasVEX_W;
|
||||
bool EVEX_W = EVEXRI.HasVEX_W;
|
||||
bool VEX_WIG = VEXRI.IgnoresVEX_W;
|
||||
bool EVEX_WIG = EVEXRI.IgnoresVEX_W;
|
||||
bool EVEX_W1_VEX_W0 = EVEXRI.Rec->getValueAsBit("EVEX_W1_VEX_W0");
|
||||
|
||||
if (RecV->getValueAsDef("OpEnc")->getName().str() != "EncVEX" ||
|
||||
RecV->getValueAsBit("isCodeGenOnly") != RecE->getValueAsBit("isCodeGenOnly") ||
|
||||
if (VEXRI.IsCodeGenOnly != EVEXRI.IsCodeGenOnly ||
|
||||
// VEX/EVEX fields
|
||||
RecV->getValueAsDef("OpPrefix") != RecE->getValueAsDef("OpPrefix") ||
|
||||
RecV->getValueAsDef("OpMap") != RecE->getValueAsDef("OpMap") ||
|
||||
RecV->getValueAsBit("hasVEX_4V") != RecE->getValueAsBit("hasVEX_4V") ||
|
||||
RecV->getValueAsBit("hasEVEX_L2") != RecE->getValueAsBit("hasEVEX_L2") ||
|
||||
RecV->getValueAsBit("hasVEX_L") != RecE->getValueAsBit("hasVEX_L") ||
|
||||
VEXRI.OpPrefix != EVEXRI.OpPrefix || VEXRI.OpMap != EVEXRI.OpMap ||
|
||||
VEXRI.HasVEX_4V != EVEXRI.HasVEX_4V ||
|
||||
VEXRI.HasVEX_LPrefix != EVEXRI.HasVEX_LPrefix ||
|
||||
// Match is allowed if either is VEX_WIG, or they match, or EVEX
|
||||
// is VEX_W1X and VEX is VEX_W0.
|
||||
(!(VEX_WIG || (!EVEX_WIG && EVEX_W == VEX_W) ||
|
||||
(EVEX_W1_VEX_W0 && EVEX_W && !VEX_W))) ||
|
||||
// Instruction's format
|
||||
RecV->getValueAsDef("Form") != RecE->getValueAsDef("Form"))
|
||||
VEXRI.Form != EVEXRI.Form)
|
||||
return false;
|
||||
|
||||
// This is needed for instructions with intrinsic version (_Int).
|
||||
|
@ -207,23 +205,19 @@ void X86EVEX2VEXTablesEmitter::run(raw_ostream &OS) {
|
|||
Target.getInstructionsByEnumValue();
|
||||
|
||||
for (const CodeGenInstruction *Inst : NumberedInstructions) {
|
||||
X86Disassembler::RecognizableInstrBase RI(*Inst);
|
||||
const Record *Def = RI.Rec;
|
||||
// Filter non-X86 instructions.
|
||||
if (!Inst->TheDef->isSubClassOf("X86Inst"))
|
||||
if (!Def->isSubClassOf("X86Inst"))
|
||||
continue;
|
||||
|
||||
// Add VEX encoded instructions to one of VEXInsts vectors according to
|
||||
// it's opcode.
|
||||
if (Inst->TheDef->getValueAsDef("OpEnc")->getName() == "EncVEX") {
|
||||
uint64_t Opcode = getValueFromBitsInit(Inst->TheDef->
|
||||
getValueAsBitsInit("Opcode"));
|
||||
VEXInsts[Opcode].push_back(Inst);
|
||||
}
|
||||
if (RI.Encoding == X86Local::VEX)
|
||||
VEXInsts[RI.Opcode].push_back(Inst);
|
||||
// Add relevant EVEX encoded instructions to EVEXInsts
|
||||
else if (Inst->TheDef->getValueAsDef("OpEnc")->getName() == "EncEVEX" &&
|
||||
!Inst->TheDef->getValueAsBit("hasEVEX_K") &&
|
||||
!Inst->TheDef->getValueAsBit("hasEVEX_B") &&
|
||||
!Inst->TheDef->getValueAsBit("hasEVEX_L2") &&
|
||||
!Inst->TheDef->getValueAsBit("notEVEX2VEXConvertible"))
|
||||
else if (RI.Encoding == X86Local::EVEX && !RI.HasEVEX_K && !RI.HasEVEX_B &&
|
||||
!RI.HasEVEX_L2Prefix && !Def->getValueAsBit("notEVEX2VEXConvertible"))
|
||||
EVEXInsts.push_back(Inst);
|
||||
}
|
||||
|
||||
|
|
|
@ -212,20 +212,6 @@ static inline uint64_t getValueFromBitsInit(const BitsInit *B) {
|
|||
return Value;
|
||||
}
|
||||
|
||||
// Returns true if the two given BitsInits represent the same integer value
|
||||
static inline bool equalBitsInits(const BitsInit *B1, const BitsInit *B2) {
|
||||
if (B1->getNumBits() != B2->getNumBits())
|
||||
PrintFatalError("Comparing two BitsInits with different sizes!");
|
||||
|
||||
for (unsigned i = 0, e = B1->getNumBits(); i != e; ++i) {
|
||||
BitInit *Bit1 = cast<BitInit>(B1->getBit(i));
|
||||
BitInit *Bit2 = cast<BitInit>(B2->getBit(i));
|
||||
if (Bit1->getValue() != Bit2->getValue())
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
// Return the size of the register operand
|
||||
static inline unsigned int getRegOperandSize(const Record *RegRec) {
|
||||
if (RegRec->isSubClassOf("RegisterOperand"))
|
||||
|
@ -323,53 +309,42 @@ public:
|
|||
: MemInst(Inst) {}
|
||||
|
||||
bool operator()(const CodeGenInstruction *RegInst) {
|
||||
Record *MemRec = MemInst->TheDef;
|
||||
Record *RegRec = RegInst->TheDef;
|
||||
X86Disassembler::RecognizableInstrBase RegRI(*RegInst);
|
||||
X86Disassembler::RecognizableInstrBase MemRI(*MemInst);
|
||||
const Record *RegRec = RegRI.Rec;
|
||||
const Record *MemRec = MemRI.Rec;
|
||||
|
||||
// EVEX_B means different things for memory and register forms.
|
||||
if (RegRI.HasEVEX_B != 0 || MemRI.HasEVEX_B != 0)
|
||||
return false;
|
||||
|
||||
// Instruction's format - The register form's "Form" field should be
|
||||
// the opposite of the memory form's "Form" field.
|
||||
if (!areOppositeForms(RegRI.Form, MemRI.Form))
|
||||
return false;
|
||||
|
||||
// Return false if one (at least) of the encoding fields of both
|
||||
// instructions do not match.
|
||||
if (RegRec->getValueAsDef("OpEnc") != MemRec->getValueAsDef("OpEnc") ||
|
||||
!equalBitsInits(RegRec->getValueAsBitsInit("Opcode"),
|
||||
MemRec->getValueAsBitsInit("Opcode")) ||
|
||||
// VEX/EVEX fields
|
||||
RegRec->getValueAsDef("OpPrefix") !=
|
||||
MemRec->getValueAsDef("OpPrefix") ||
|
||||
RegRec->getValueAsDef("OpMap") != MemRec->getValueAsDef("OpMap") ||
|
||||
RegRec->getValueAsDef("OpSize") != MemRec->getValueAsDef("OpSize") ||
|
||||
RegRec->getValueAsDef("AdSize") != MemRec->getValueAsDef("AdSize") ||
|
||||
RegRec->getValueAsBit("hasVEX_4V") !=
|
||||
MemRec->getValueAsBit("hasVEX_4V") ||
|
||||
RegRec->getValueAsBit("hasEVEX_K") !=
|
||||
MemRec->getValueAsBit("hasEVEX_K") ||
|
||||
RegRec->getValueAsBit("hasEVEX_Z") !=
|
||||
MemRec->getValueAsBit("hasEVEX_Z") ||
|
||||
// EVEX_B means different things for memory and register forms.
|
||||
RegRec->getValueAsBit("hasEVEX_B") != 0 ||
|
||||
MemRec->getValueAsBit("hasEVEX_B") != 0 ||
|
||||
if (RegRI.Encoding != MemRI.Encoding || RegRI.Opcode != MemRI.Opcode ||
|
||||
RegRI.OpPrefix != MemRI.OpPrefix || RegRI.OpMap != MemRI.OpMap ||
|
||||
RegRI.OpSize != MemRI.OpSize || RegRI.AdSize != MemRI.AdSize ||
|
||||
RegRI.HasREX_WPrefix != MemRI.HasREX_WPrefix ||
|
||||
RegRI.HasVEX_4V != MemRI.HasVEX_4V ||
|
||||
RegRI.HasVEX_LPrefix != MemRI.HasVEX_LPrefix ||
|
||||
RegRI.HasVEX_W != MemRI.HasVEX_W ||
|
||||
RegRI.IgnoresVEX_L != MemRI.IgnoresVEX_L ||
|
||||
RegRI.IgnoresVEX_W != MemRI.IgnoresVEX_W ||
|
||||
RegRI.HasEVEX_K != MemRI.HasEVEX_K ||
|
||||
RegRI.HasEVEX_KZ != MemRI.HasEVEX_KZ ||
|
||||
RegRI.HasEVEX_L2Prefix != MemRI.HasEVEX_L2Prefix ||
|
||||
RegRec->getValueAsBit("hasEVEX_RC") !=
|
||||
MemRec->getValueAsBit("hasEVEX_RC") ||
|
||||
RegRec->getValueAsBit("hasREX_WPrefix") !=
|
||||
MemRec->getValueAsBit("hasREX_WPrefix") ||
|
||||
RegRec->getValueAsBit("hasLockPrefix") !=
|
||||
MemRec->getValueAsBit("hasLockPrefix") ||
|
||||
RegRec->getValueAsBit("hasNoTrackPrefix") !=
|
||||
MemRec->getValueAsBit("hasNoTrackPrefix") ||
|
||||
RegRec->getValueAsBit("hasVEX_L") !=
|
||||
MemRec->getValueAsBit("hasVEX_L") ||
|
||||
RegRec->getValueAsBit("hasEVEX_L2") !=
|
||||
MemRec->getValueAsBit("hasEVEX_L2") ||
|
||||
RegRec->getValueAsBit("ignoresVEX_L") !=
|
||||
MemRec->getValueAsBit("ignoresVEX_L") ||
|
||||
RegRec->getValueAsBit("HasVEX_W") !=
|
||||
MemRec->getValueAsBit("HasVEX_W") ||
|
||||
RegRec->getValueAsBit("IgnoresVEX_W") !=
|
||||
MemRec->getValueAsBit("IgnoresVEX_W") ||
|
||||
RegRec->getValueAsBit("EVEX_W1_VEX_W0") !=
|
||||
MemRec->getValueAsBit("EVEX_W1_VEX_W0") ||
|
||||
// Instruction's format - The register form's "Form" field should be
|
||||
// the opposite of the memory form's "Form" field.
|
||||
!areOppositeForms(RegRec->getValueAsBitsInit("FormBits"),
|
||||
MemRec->getValueAsBitsInit("FormBits")) ||
|
||||
RegRec->getValueAsBit("isAsmParserOnly") !=
|
||||
MemRec->getValueAsBit("isAsmParserOnly"))
|
||||
return false;
|
||||
|
@ -424,31 +399,24 @@ public:
|
|||
|
||||
private:
|
||||
// Return true of the 2 given forms are the opposite of each other.
|
||||
bool areOppositeForms(const BitsInit *RegFormBits,
|
||||
const BitsInit *MemFormBits) {
|
||||
uint64_t MemFormNum = getValueFromBitsInit(MemFormBits);
|
||||
uint64_t RegFormNum = getValueFromBitsInit(RegFormBits);
|
||||
|
||||
if ((MemFormNum == X86Local::MRM0m && RegFormNum == X86Local::MRM0r) ||
|
||||
(MemFormNum == X86Local::MRM1m && RegFormNum == X86Local::MRM1r) ||
|
||||
(MemFormNum == X86Local::MRM2m && RegFormNum == X86Local::MRM2r) ||
|
||||
(MemFormNum == X86Local::MRM3m && RegFormNum == X86Local::MRM3r) ||
|
||||
(MemFormNum == X86Local::MRM4m && RegFormNum == X86Local::MRM4r) ||
|
||||
(MemFormNum == X86Local::MRM5m && RegFormNum == X86Local::MRM5r) ||
|
||||
(MemFormNum == X86Local::MRM6m && RegFormNum == X86Local::MRM6r) ||
|
||||
(MemFormNum == X86Local::MRM7m && RegFormNum == X86Local::MRM7r) ||
|
||||
(MemFormNum == X86Local::MRMXm && RegFormNum == X86Local::MRMXr) ||
|
||||
(MemFormNum == X86Local::MRMXmCC && RegFormNum == X86Local::MRMXrCC) ||
|
||||
(MemFormNum == X86Local::MRMDestMem &&
|
||||
RegFormNum == X86Local::MRMDestReg) ||
|
||||
(MemFormNum == X86Local::MRMSrcMem &&
|
||||
RegFormNum == X86Local::MRMSrcReg) ||
|
||||
(MemFormNum == X86Local::MRMSrcMem4VOp3 &&
|
||||
RegFormNum == X86Local::MRMSrcReg4VOp3) ||
|
||||
(MemFormNum == X86Local::MRMSrcMemOp4 &&
|
||||
RegFormNum == X86Local::MRMSrcRegOp4) ||
|
||||
(MemFormNum == X86Local::MRMSrcMemCC &&
|
||||
RegFormNum == X86Local::MRMSrcRegCC))
|
||||
bool areOppositeForms(unsigned RegForm, unsigned MemForm) {
|
||||
if ((MemForm == X86Local::MRM0m && RegForm == X86Local::MRM0r) ||
|
||||
(MemForm == X86Local::MRM1m && RegForm == X86Local::MRM1r) ||
|
||||
(MemForm == X86Local::MRM2m && RegForm == X86Local::MRM2r) ||
|
||||
(MemForm == X86Local::MRM3m && RegForm == X86Local::MRM3r) ||
|
||||
(MemForm == X86Local::MRM4m && RegForm == X86Local::MRM4r) ||
|
||||
(MemForm == X86Local::MRM5m && RegForm == X86Local::MRM5r) ||
|
||||
(MemForm == X86Local::MRM6m && RegForm == X86Local::MRM6r) ||
|
||||
(MemForm == X86Local::MRM7m && RegForm == X86Local::MRM7r) ||
|
||||
(MemForm == X86Local::MRMXm && RegForm == X86Local::MRMXr) ||
|
||||
(MemForm == X86Local::MRMXmCC && RegForm == X86Local::MRMXrCC) ||
|
||||
(MemForm == X86Local::MRMDestMem && RegForm == X86Local::MRMDestReg) ||
|
||||
(MemForm == X86Local::MRMSrcMem && RegForm == X86Local::MRMSrcReg) ||
|
||||
(MemForm == X86Local::MRMSrcMem4VOp3 &&
|
||||
RegForm == X86Local::MRMSrcReg4VOp3) ||
|
||||
(MemForm == X86Local::MRMSrcMemOp4 &&
|
||||
RegForm == X86Local::MRMSrcRegOp4) ||
|
||||
(MemForm == X86Local::MRMSrcMemCC && RegForm == X86Local::MRMSrcRegCC))
|
||||
return true;
|
||||
|
||||
return false;
|
||||
|
|
|
@ -13,7 +13,6 @@
|
|||
|
||||
#include "CodeGenInstruction.h"
|
||||
#include "CodeGenTarget.h"
|
||||
#include "X86DisassemblerTables.h"
|
||||
#include "X86RecognizableInstr.h"
|
||||
#include "llvm/TableGen/Error.h"
|
||||
#include "llvm/TableGen/TableGenBackend.h"
|
||||
|
@ -41,23 +40,17 @@ void X86MnemonicTablesEmitter::run(raw_ostream &OS) {
|
|||
// Hold all instructions grouped by mnemonic
|
||||
StringMap<SmallVector<const CodeGenInstruction *, 0>> MnemonicToCGInstrMap;
|
||||
|
||||
// Unused
|
||||
X86Disassembler::DisassemblerTables Tables;
|
||||
ArrayRef<const CodeGenInstruction *> NumberedInstructions =
|
||||
Target.getInstructionsByEnumValue();
|
||||
for (unsigned II = 0, IE = NumberedInstructions.size(); II != IE; ++II) {
|
||||
const CodeGenInstruction *I = NumberedInstructions[II];
|
||||
X86Disassembler::RecognizableInstr RI(Tables, *I, II);
|
||||
Record *Def = I->TheDef;
|
||||
if ( // Filter non-X86 instructions
|
||||
!Def->isSubClassOf("X86Inst") ||
|
||||
// Skip pseudo instructions as they may contain non-alnum characters in
|
||||
// mnemonic
|
||||
(RI.IsCodeGenOnly && !RI.ForceDisassemble) ||
|
||||
// Non-parsable instruction defs contain prefix as part of AsmString
|
||||
for (const CodeGenInstruction *I : NumberedInstructions) {
|
||||
X86Disassembler::RecognizableInstrBase RI(*I);
|
||||
const Record *Def = RI.Rec;
|
||||
if (!RI.ShouldBeEmitted)
|
||||
continue;
|
||||
if ( // Non-parsable instruction defs contain prefix as part of AsmString
|
||||
Def->getValueAsString("AsmVariantName") == "NonParsable" ||
|
||||
// Skip CodeGenInstructions that are not real standalone instructions
|
||||
RI.Form == X86Local::PrefixByte || RI.Form == X86Local::Pseudo)
|
||||
// Skip prefix byte
|
||||
RI.Form == X86Local::PrefixByte)
|
||||
continue;
|
||||
std::string Mnemonic = X86Disassembler::getMnemonic(I, Variant);
|
||||
MnemonicToCGInstrMap[Mnemonic].push_back(I);
|
||||
|
|
|
@ -75,14 +75,9 @@ static uint8_t byteFromRec(const Record* rec, StringRef name) {
|
|||
return byteFromBitsInit(*bits);
|
||||
}
|
||||
|
||||
RecognizableInstr::RecognizableInstr(DisassemblerTables &tables,
|
||||
const CodeGenInstruction &insn,
|
||||
InstrUID uid) {
|
||||
UID = uid;
|
||||
|
||||
RecognizableInstrBase::RecognizableInstrBase(const CodeGenInstruction &insn) {
|
||||
Rec = insn.TheDef;
|
||||
Name = std::string(Rec->getName());
|
||||
Spec = &tables.specForUID(UID);
|
||||
|
||||
if (!Rec->isSubClassOf("X86Inst")) {
|
||||
ShouldBeEmitted = false;
|
||||
|
@ -144,6 +139,14 @@ RecognizableInstr::RecognizableInstr(DisassemblerTables &tables,
|
|||
ShouldBeEmitted = true;
|
||||
}
|
||||
|
||||
RecognizableInstr::RecognizableInstr(DisassemblerTables &tables,
|
||||
const CodeGenInstruction &insn,
|
||||
InstrUID uid)
|
||||
: RecognizableInstrBase(insn) {
|
||||
UID = uid;
|
||||
Spec = &tables.specForUID(UID);
|
||||
}
|
||||
|
||||
void RecognizableInstr::processInstr(DisassemblerTables &tables,
|
||||
const CodeGenInstruction &insn,
|
||||
InstrUID uid)
|
||||
|
|
|
@ -158,14 +158,8 @@ namespace X86Disassembler {
|
|||
|
||||
class DisassemblerTables;
|
||||
|
||||
/// RecognizableInstr - Encapsulates all information required to decode a single
|
||||
/// instruction, as extracted from the LLVM instruction tables. Has methods
|
||||
/// to interpret the information available in the LLVM tables, and to emit the
|
||||
/// instruction into DisassemblerTables.
|
||||
class RecognizableInstr {
|
||||
public:
|
||||
/// The opcode of the instruction, as used in an MCInst
|
||||
InstrUID UID;
|
||||
/// Extract common fields of a single X86 instruction from a CodeGenInstruction
|
||||
struct RecognizableInstrBase {
|
||||
/// The record from the .td files corresponding to this instruction
|
||||
const Record* Rec;
|
||||
/// The OpPrefix field from the record
|
||||
|
@ -228,6 +222,18 @@ public:
|
|||
/// memory operands expand to 5 operands in the MCInst
|
||||
const std::vector<CGIOperandList::OperandInfo>* Operands;
|
||||
|
||||
/// \param insn The CodeGenInstruction to extract information from.
|
||||
RecognizableInstrBase(const CodeGenInstruction &insn);
|
||||
};
|
||||
|
||||
/// RecognizableInstr - Encapsulates all information required to decode a single
|
||||
/// instruction, as extracted from the LLVM instruction tables. Has methods
|
||||
/// to interpret the information available in the LLVM tables, and to emit the
|
||||
/// instruction into DisassemblerTables.
|
||||
class RecognizableInstr : public RecognizableInstrBase {
|
||||
public:
|
||||
/// The opcode of the instruction, as used in an MCInst
|
||||
InstrUID UID;
|
||||
/// The description of the instruction that is emitted into the instruction
|
||||
/// info table
|
||||
InstructionSpecifier* Spec;
|
||||
|
|
Loading…
Reference in New Issue