aboutsummaryrefslogtreecommitdiff
path: root/llvm/utils/TableGen/X86RecognizableInstr.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'llvm/utils/TableGen/X86RecognizableInstr.cpp')
-rw-r--r--llvm/utils/TableGen/X86RecognizableInstr.cpp192
1 files changed, 108 insertions, 84 deletions
diff --git a/llvm/utils/TableGen/X86RecognizableInstr.cpp b/llvm/utils/TableGen/X86RecognizableInstr.cpp
index 4023d8f57318..9afde66fe6f3 100644
--- a/llvm/utils/TableGen/X86RecognizableInstr.cpp
+++ b/llvm/utils/TableGen/X86RecognizableInstr.cpp
@@ -24,6 +24,51 @@
using namespace llvm;
using namespace X86Disassembler;
+std::string X86Disassembler::getMnemonic(const CodeGenInstruction *I, unsigned Variant) {
+ std::string AsmString = I->FlattenAsmStringVariants(I->AsmString, Variant);
+ StringRef Mnemonic(AsmString);
+ // Extract a mnemonic assuming it's separated by \t
+ Mnemonic = Mnemonic.take_until([](char C) { return C == '\t'; });
+
+ // Special case: CMOVCC, JCC, SETCC have "${cond}" in mnemonic.
+ // Replace it with "CC" in-place.
+ size_t CondPos = Mnemonic.find("${cond}");
+ if (CondPos != StringRef::npos)
+ Mnemonic = AsmString.replace(CondPos, StringRef::npos, "CC");
+ return Mnemonic.upper();
+}
+
+bool X86Disassembler::isRegisterOperand(const Record *Rec) {
+ return Rec->isSubClassOf("RegisterClass") ||
+ Rec->isSubClassOf("RegisterOperand");
+}
+
+bool X86Disassembler::isMemoryOperand(const Record *Rec) {
+ return Rec->isSubClassOf("Operand") &&
+ Rec->getValueAsString("OperandType") == "OPERAND_MEMORY";
+}
+
+bool X86Disassembler::isImmediateOperand(const Record *Rec) {
+ return Rec->isSubClassOf("Operand") &&
+ Rec->getValueAsString("OperandType") == "OPERAND_IMMEDIATE";
+}
+
+unsigned X86Disassembler::getRegOperandSize(const Record *RegRec) {
+ if (RegRec->isSubClassOf("RegisterClass"))
+ return RegRec->getValueAsInt("Alignment");
+ if (RegRec->isSubClassOf("RegisterOperand"))
+ return RegRec->getValueAsDef("RegClass")->getValueAsInt("Alignment");
+
+ llvm_unreachable("Register operand's size not known!");
+}
+
+unsigned X86Disassembler::getMemOperandSize(const Record *MemRec) {
+ if (MemRec->isSubClassOf("X86MemOperand"))
+ return MemRec->getValueAsInt("Size");
+
+ llvm_unreachable("Memory operand's size not known!");
+}
+
/// byteFromBitsInit - Extracts a value at most 8 bits in width from a BitsInit.
/// Useful for switch statements and the like.
///
@@ -61,55 +106,49 @@ static uint8_t byteFromRec(const Record* rec, StringRef name) {
return byteFromBitsInit(*bits);
}
-RecognizableInstr::RecognizableInstr(DisassemblerTables &tables,
- const CodeGenInstruction &insn,
- InstrUID uid) {
- UID = uid;
-
- Rec = insn.TheDef;
- Name = std::string(Rec->getName());
- Spec = &tables.specForUID(UID);
-
- if (!Rec->isSubClassOf("X86Inst")) {
- ShouldBeEmitted = false;
- return;
- }
-
+RecognizableInstrBase::RecognizableInstrBase(const CodeGenInstruction &insn) {
+ const Record *Rec = insn.TheDef;
+ assert(Rec->isSubClassOf("X86Inst") && "Not a X86 Instruction");
OpPrefix = byteFromRec(Rec, "OpPrefixBits");
- OpMap = byteFromRec(Rec, "OpMapBits");
- Opcode = byteFromRec(Rec, "Opcode");
- Form = byteFromRec(Rec, "FormBits");
+ OpMap = byteFromRec(Rec, "OpMapBits");
+ Opcode = byteFromRec(Rec, "Opcode");
+ Form = byteFromRec(Rec, "FormBits");
Encoding = byteFromRec(Rec, "OpEncBits");
-
- OpSize = byteFromRec(Rec, "OpSizeBits");
- AdSize = byteFromRec(Rec, "AdSizeBits");
- HasREX_WPrefix = Rec->getValueAsBit("hasREX_WPrefix");
- HasVEX_4V = Rec->getValueAsBit("hasVEX_4V");
- HasVEX_W = Rec->getValueAsBit("HasVEX_W");
- IgnoresVEX_W = Rec->getValueAsBit("IgnoresVEX_W");
- IgnoresVEX_L = Rec->getValueAsBit("ignoresVEX_L");
- HasEVEX_L2Prefix = Rec->getValueAsBit("hasEVEX_L2");
- HasEVEX_K = Rec->getValueAsBit("hasEVEX_K");
- HasEVEX_KZ = Rec->getValueAsBit("hasEVEX_Z");
- HasEVEX_B = Rec->getValueAsBit("hasEVEX_B");
- IsCodeGenOnly = Rec->getValueAsBit("isCodeGenOnly");
- ForceDisassemble = Rec->getValueAsBit("ForceDisassemble");
- CD8_Scale = byteFromRec(Rec, "CD8_Scale");
-
- Name = std::string(Rec->getName());
-
- Operands = &insn.Operands.OperandList;
-
- HasVEX_LPrefix = Rec->getValueAsBit("hasVEX_L");
+ OpSize = byteFromRec(Rec, "OpSizeBits");
+ AdSize = byteFromRec(Rec, "AdSizeBits");
+ HasREX_W = Rec->getValueAsBit("hasREX_W");
+ HasVEX_4V = Rec->getValueAsBit("hasVEX_4V");
+ HasVEX_W = Rec->getValueAsBit("HasVEX_W");
+ IgnoresVEX_W = Rec->getValueAsBit("IgnoresVEX_W");
+ IgnoresVEX_L = Rec->getValueAsBit("ignoresVEX_L");
+ HasEVEX_L2 = Rec->getValueAsBit("hasEVEX_L2");
+ HasEVEX_K = Rec->getValueAsBit("hasEVEX_K");
+ HasEVEX_KZ = Rec->getValueAsBit("hasEVEX_Z");
+ HasEVEX_B = Rec->getValueAsBit("hasEVEX_B");
+ IsCodeGenOnly = Rec->getValueAsBit("isCodeGenOnly");
+ IsAsmParserOnly = Rec->getValueAsBit("isAsmParserOnly");
+ ForceDisassemble = Rec->getValueAsBit("ForceDisassemble");
+ CD8_Scale = byteFromRec(Rec, "CD8_Scale");
+ HasVEX_L = Rec->getValueAsBit("hasVEX_L");
EncodeRC = HasEVEX_B &&
(Form == X86Local::MRMDestReg || Form == X86Local::MRMSrcReg);
+}
+
+bool RecognizableInstrBase::shouldBeEmitted() const {
+ return Form != X86Local::Pseudo && (!IsCodeGenOnly || ForceDisassemble) &&
+ !IsAsmParserOnly;
+}
+RecognizableInstr::RecognizableInstr(DisassemblerTables &tables,
+ const CodeGenInstruction &insn,
+ InstrUID uid)
+ : RecognizableInstrBase(insn), Rec(insn.TheDef), Name(Rec->getName().str()),
+ Is32Bit(false), Is64Bit(false), Operands(&insn.Operands.OperandList),
+ UID(uid), Spec(&tables.specForUID(uid)) {
// Check for 64-bit inst which does not require REX
- Is32Bit = false;
- Is64Bit = false;
// FIXME: Is there some better way to check for In64BitMode?
- std::vector<Record*> Predicates = Rec->getValueAsListOfDefs("Predicates");
+ std::vector<Record *> Predicates = Rec->getValueAsListOfDefs("Predicates");
for (unsigned i = 0, e = Predicates.size(); i != e; ++i) {
if (Predicates[i]->getName().contains("Not64Bit") ||
Predicates[i]->getName().contains("In32Bit")) {
@@ -121,29 +160,19 @@ RecognizableInstr::RecognizableInstr(DisassemblerTables &tables,
break;
}
}
-
- if (Form == X86Local::Pseudo || (IsCodeGenOnly && !ForceDisassemble)) {
- ShouldBeEmitted = false;
- return;
- }
-
- ShouldBeEmitted = true;
}
void RecognizableInstr::processInstr(DisassemblerTables &tables,
const CodeGenInstruction &insn,
- InstrUID uid)
-{
- // Ignore "asm parser only" instructions.
- if (insn.TheDef->getValueAsBit("isAsmParserOnly"))
+ InstrUID uid) {
+ if (!insn.TheDef->isSubClassOf("X86Inst"))
return;
-
RecognizableInstr recogInstr(tables, insn, uid);
- if (recogInstr.shouldBeEmitted()) {
- recogInstr.emitInstructionSpecifier();
- recogInstr.emitDecodePath(tables);
- }
+ if (!recogInstr.shouldBeEmitted())
+ return;
+ recogInstr.emitInstructionSpecifier();
+ recogInstr.emitDecodePath(tables);
}
#define EVEX_KB(n) (HasEVEX_KZ && HasEVEX_B ? n##_KZ_B : \
@@ -155,12 +184,12 @@ InstructionContext RecognizableInstr::insnContext() const {
InstructionContext insnContext;
if (Encoding == X86Local::EVEX) {
- if (HasVEX_LPrefix && HasEVEX_L2Prefix) {
+ if (HasVEX_L && HasEVEX_L2) {
errs() << "Don't support VEX.L if EVEX_L2 is enabled: " << Name << "\n";
llvm_unreachable("Don't support VEX.L if EVEX_L2 is enabled");
}
// VEX_L & VEX_W
- if (!EncodeRC && HasVEX_LPrefix && HasVEX_W) {
+ if (!EncodeRC && HasVEX_L && HasVEX_W) {
if (OpPrefix == X86Local::PD)
insnContext = EVEX_KB(IC_EVEX_L_W_OPSIZE);
else if (OpPrefix == X86Local::XS)
@@ -173,7 +202,7 @@ InstructionContext RecognizableInstr::insnContext() const {
errs() << "Instruction does not use a prefix: " << Name << "\n";
llvm_unreachable("Invalid prefix");
}
- } else if (!EncodeRC && HasVEX_LPrefix) {
+ } else if (!EncodeRC && HasVEX_L) {
// VEX_L
if (OpPrefix == X86Local::PD)
insnContext = EVEX_KB(IC_EVEX_L_OPSIZE);
@@ -187,7 +216,7 @@ InstructionContext RecognizableInstr::insnContext() const {
errs() << "Instruction does not use a prefix: " << Name << "\n";
llvm_unreachable("Invalid prefix");
}
- } else if (!EncodeRC && HasEVEX_L2Prefix && HasVEX_W) {
+ } else if (!EncodeRC && HasEVEX_L2 && HasVEX_W) {
// EVEX_L2 & VEX_W
if (OpPrefix == X86Local::PD)
insnContext = EVEX_KB(IC_EVEX_L2_W_OPSIZE);
@@ -201,7 +230,7 @@ InstructionContext RecognizableInstr::insnContext() const {
errs() << "Instruction does not use a prefix: " << Name << "\n";
llvm_unreachable("Invalid prefix");
}
- } else if (!EncodeRC && HasEVEX_L2Prefix) {
+ } else if (!EncodeRC && HasEVEX_L2) {
// EVEX_L2
if (OpPrefix == X86Local::PD)
insnContext = EVEX_KB(IC_EVEX_L2_OPSIZE);
@@ -246,7 +275,7 @@ InstructionContext RecognizableInstr::insnContext() const {
}
/// eof EVEX
} else if (Encoding == X86Local::VEX || Encoding == X86Local::XOP) {
- if (HasVEX_LPrefix && HasVEX_W) {
+ if (HasVEX_L && HasVEX_W) {
if (OpPrefix == X86Local::PD)
insnContext = IC_VEX_L_W_OPSIZE;
else if (OpPrefix == X86Local::XS)
@@ -259,20 +288,15 @@ InstructionContext RecognizableInstr::insnContext() const {
errs() << "Instruction does not use a prefix: " << Name << "\n";
llvm_unreachable("Invalid prefix");
}
- } else if (OpPrefix == X86Local::PD && HasVEX_LPrefix)
+ } else if (OpPrefix == X86Local::PD && HasVEX_L)
insnContext = IC_VEX_L_OPSIZE;
else if (OpPrefix == X86Local::PD && HasVEX_W)
insnContext = IC_VEX_W_OPSIZE;
- else if (OpPrefix == X86Local::PD && Is64Bit &&
- AdSize == X86Local::AdSize32)
- insnContext = IC_64BIT_VEX_OPSIZE_ADSIZE;
- else if (OpPrefix == X86Local::PD && Is64Bit)
- insnContext = IC_64BIT_VEX_OPSIZE;
else if (OpPrefix == X86Local::PD)
insnContext = IC_VEX_OPSIZE;
- else if (HasVEX_LPrefix && OpPrefix == X86Local::XS)
+ else if (HasVEX_L && OpPrefix == X86Local::XS)
insnContext = IC_VEX_L_XS;
- else if (HasVEX_LPrefix && OpPrefix == X86Local::XD)
+ else if (HasVEX_L && OpPrefix == X86Local::XD)
insnContext = IC_VEX_L_XD;
else if (HasVEX_W && OpPrefix == X86Local::XS)
insnContext = IC_VEX_W_XS;
@@ -280,7 +304,7 @@ InstructionContext RecognizableInstr::insnContext() const {
insnContext = IC_VEX_W_XD;
else if (HasVEX_W && OpPrefix == X86Local::PS)
insnContext = IC_VEX_W;
- else if (HasVEX_LPrefix && OpPrefix == X86Local::PS)
+ else if (HasVEX_L && OpPrefix == X86Local::PS)
insnContext = IC_VEX_L;
else if (OpPrefix == X86Local::XD)
insnContext = IC_VEX_XD;
@@ -292,10 +316,10 @@ InstructionContext RecognizableInstr::insnContext() const {
errs() << "Instruction does not use a prefix: " << Name << "\n";
llvm_unreachable("Invalid prefix");
}
- } else if (Is64Bit || HasREX_WPrefix || AdSize == X86Local::AdSize64) {
- if (HasREX_WPrefix && (OpSize == X86Local::OpSize16 || OpPrefix == X86Local::PD))
+ } else if (Is64Bit || HasREX_W || AdSize == X86Local::AdSize64) {
+ if (HasREX_W && (OpSize == X86Local::OpSize16 || OpPrefix == X86Local::PD))
insnContext = IC_64BIT_REXW_OPSIZE;
- else if (HasREX_WPrefix && AdSize == X86Local::AdSize32)
+ else if (HasREX_W && AdSize == X86Local::AdSize32)
insnContext = IC_64BIT_REXW_ADSIZE;
else if (OpSize == X86Local::OpSize16 && OpPrefix == X86Local::XD)
insnContext = IC_64BIT_XD_OPSIZE;
@@ -309,15 +333,15 @@ InstructionContext RecognizableInstr::insnContext() const {
insnContext = IC_64BIT_OPSIZE;
else if (AdSize == X86Local::AdSize32)
insnContext = IC_64BIT_ADSIZE;
- else if (HasREX_WPrefix && OpPrefix == X86Local::XS)
+ else if (HasREX_W && OpPrefix == X86Local::XS)
insnContext = IC_64BIT_REXW_XS;
- else if (HasREX_WPrefix && OpPrefix == X86Local::XD)
+ else if (HasREX_W && OpPrefix == X86Local::XD)
insnContext = IC_64BIT_REXW_XD;
else if (OpPrefix == X86Local::XD)
insnContext = IC_64BIT_XD;
else if (OpPrefix == X86Local::XS)
insnContext = IC_64BIT_XS;
- else if (HasREX_WPrefix)
+ else if (HasREX_W)
insnContext = IC_64BIT_REXW;
else
insnContext = IC_64BIT;
@@ -392,7 +416,7 @@ void RecognizableInstr::handleOperand(bool optional, unsigned &operandIndex,
adjustOperandEncoding(encoding);
Spec->operands[operandIndex].encoding = encoding;
Spec->operands[operandIndex].type =
- typeFromString(std::string(typeName), HasREX_WPrefix, OpSize);
+ typeFromString(std::string(typeName), HasREX_W, OpSize);
++operandIndex;
++physicalOperandIndex;
@@ -835,13 +859,13 @@ void RecognizableInstr::emitDecodePath(DisassemblerTables &tables) const {
if (Form == X86Local::AddRegFrm || Form == X86Local::MRMSrcRegCC ||
Form == X86Local::MRMSrcMemCC || Form == X86Local::MRMXrCC ||
Form == X86Local::MRMXmCC || Form == X86Local::AddCCFrm) {
- unsigned Count = Form == X86Local::AddRegFrm ? 8 : 16;
+ uint8_t Count = Form == X86Local::AddRegFrm ? 8 : 16;
assert(((opcodeToSet % Count) == 0) && "ADDREG_FRM opcode not aligned");
uint8_t currentOpcode;
- for (currentOpcode = opcodeToSet; currentOpcode < opcodeToSet + Count;
- ++currentOpcode)
+ for (currentOpcode = opcodeToSet;
+ currentOpcode < (uint8_t)(opcodeToSet + Count); ++currentOpcode)
tables.setTableFields(*opcodeType, insnContext(), currentOpcode, *filter,
UID, Is32Bit, OpPrefix == 0,
IgnoresVEX_L || EncodeRC,
@@ -857,9 +881,9 @@ void RecognizableInstr::emitDecodePath(DisassemblerTables &tables) const {
#define TYPE(str, type) if (s == str) return type;
OperandType RecognizableInstr::typeFromString(const std::string &s,
- bool hasREX_WPrefix,
+ bool hasREX_W,
uint8_t OpSize) {
- if(hasREX_WPrefix) {
+ if(hasREX_W) {
// For instructions with a REX_W prefix, a declared 32-bit register encoding
// is special.
TYPE("GR32", TYPE_R32)