diff options
Diffstat (limited to 'llvm/utils/TableGen/X86RecognizableInstr.cpp')
| -rw-r--r-- | llvm/utils/TableGen/X86RecognizableInstr.cpp | 192 |
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) |
