X-Git-Url: http://demsky.eecs.uci.edu/git/?a=blobdiff_plain;f=utils%2FTableGen%2FX86DisassemblerTables.cpp;h=40a0c1b260b726b1ecffd5a4d286be777b2eeeeb;hb=7a88b655ccad0f128ea1a5e8ca433a8827a24ff3;hp=2875168a108373e16f9f31a7734583058b8107f1;hpb=991271d9c454c9d599b63e4ebdd27b546e1782a1;p=oota-llvm.git diff --git a/utils/TableGen/X86DisassemblerTables.cpp b/utils/TableGen/X86DisassemblerTables.cpp index 2875168a108..40a0c1b260b 100644 --- a/utils/TableGen/X86DisassemblerTables.cpp +++ b/utils/TableGen/X86DisassemblerTables.cpp @@ -14,17 +14,17 @@ // //===----------------------------------------------------------------------===// -#include "X86DisassemblerShared.h" #include "X86DisassemblerTables.h" - -#include "llvm/TableGen/TableGenBackend.h" +#include "X86DisassemblerShared.h" #include "llvm/ADT/STLExtras.h" #include "llvm/Support/ErrorHandling.h" #include "llvm/Support/Format.h" +#include "llvm/TableGen/TableGenBackend.h" +#include using namespace llvm; using namespace X86Disassembler; - + /// inheritsFrom - Indicates whether all instructions in one class also belong /// to another class. /// @@ -36,7 +36,7 @@ static inline bool inheritsFrom(InstructionContext child, bool VEX_LIG = false) { if (child == parent) return true; - + switch (parent) { case IC: return(inheritsFrom(child, IC_64BIT) || @@ -117,17 +117,17 @@ static inline bool inheritsFrom(InstructionContext child, /// @param upper - The class that may be preferable /// @param lower - The class that may be less preferable /// @return - True if upper is to be preferred, false otherwise. -static inline bool outranks(InstructionContext upper, +static inline bool outranks(InstructionContext upper, InstructionContext lower) { assert(upper < IC_max); assert(lower < IC_max); - + #define ENUM_ENTRY(n, r, d) r, static int ranks[IC_max] = { INSTRUCTION_CONTEXTS }; #undef ENUM_ENTRY - + return (ranks[upper] > ranks[lower]); } @@ -170,24 +170,22 @@ static inline const char* stringForOperandEncoding(OperandEncoding encoding) { } } -void DisassemblerTables::emitOneID(raw_ostream &o, - uint32_t &i, - InstrUID id, +void DisassemblerTables::emitOneID(raw_ostream &o, unsigned &i, InstrUID id, bool addComma) const { if (id) o.indent(i * 2) << format("0x%hx", id); else o.indent(i * 2) << 0; - + if (addComma) o << ", "; else o << " "; - + o << "/* "; o << InstructionSpecifiers[id].name; o << "*/"; - + o << "\n"; } @@ -197,8 +195,7 @@ void DisassemblerTables::emitOneID(raw_ostream &o, /// /// @param o - The output stream on which to emit the table. /// @param i - The indentation level for that output stream. -static void emitEmptyTable(raw_ostream &o, uint32_t &i) -{ +static void emitEmptyTable(raw_ostream &o, unsigned &i) { o.indent(i * 2) << "0x0, /* EmptyTable */\n"; } @@ -207,15 +204,13 @@ static void emitEmptyTable(raw_ostream &o, uint32_t &i) /// /// @param decision - The decision to be compacted. /// @return - The compactest available representation for the decision. -static ModRMDecisionType getDecisionType(ModRMDecision &decision) -{ +static ModRMDecisionType getDecisionType(ModRMDecision &decision) { bool satisfiesOneEntry = true; bool satisfiesSplitRM = true; bool satisfiesSplitReg = true; + bool satisfiesSplitMisc = true; - uint16_t index; - - for (index = 0; index < 256; ++index) { + for (unsigned index = 0; index < 256; ++index) { if (decision.instructionIDs[index] != decision.instructionIDs[0]) satisfiesOneEntry = false; @@ -233,7 +228,7 @@ static ModRMDecisionType getDecisionType(ModRMDecision &decision) if (((index & 0xc0) != 0xc0) && (decision.instructionIDs[index] != decision.instructionIDs[index&0x38])) - satisfiesSplitReg = false; + satisfiesSplitMisc = false; } if (satisfiesOneEntry) @@ -242,9 +237,12 @@ static ModRMDecisionType getDecisionType(ModRMDecision &decision) if (satisfiesSplitRM) return MODRM_SPLITRM; - if (satisfiesSplitReg) + if (satisfiesSplitReg && satisfiesSplitMisc) return MODRM_SPLITREG; + if (satisfiesSplitMisc) + return MODRM_SPLITMISC; + return MODRM_FULL; } @@ -252,27 +250,25 @@ static ModRMDecisionType getDecisionType(ModRMDecision &decision) /// to a particular decision type. /// /// @param dt - The decision type. -/// @return - A pointer to the statically-allocated string (e.g., +/// @return - A pointer to the statically-allocated string (e.g., /// "MODRM_ONEENTRY" for MODRM_ONEENTRY). -static const char* stringForDecisionType(ModRMDecisionType dt) -{ +static const char* stringForDecisionType(ModRMDecisionType dt) { #define ENUM_ENTRY(n) case n: return #n; switch (dt) { default: - llvm_unreachable("Unknown decision type"); + llvm_unreachable("Unknown decision type"); MODRMTYPES - }; + }; #undef ENUM_ENTRY } - + /// stringForModifierType - Returns a statically-allocated string corresponding /// to an opcode modifier type. /// /// @param mt - The modifier type. /// @return - A pointer to the statically-allocated string (e.g., /// "MODIFIER_NONE" for MODIFIER_NONE). -static const char* stringForModifierType(ModifierType mt) -{ +static const char* stringForModifierType(ModifierType mt) { #define ENUM_ENTRY(n) case n: return #n; switch(mt) { default: @@ -281,35 +277,31 @@ static const char* stringForModifierType(ModifierType mt) }; #undef ENUM_ENTRY } - + DisassemblerTables::DisassemblerTables() { unsigned i; - + for (i = 0; i < array_lengthof(Tables); i++) { Tables[i] = new ContextDecision; memset(Tables[i], 0, sizeof(ContextDecision)); } - + HasConflicts = false; } - + DisassemblerTables::~DisassemblerTables() { unsigned i; - + for (i = 0; i < array_lengthof(Tables); i++) delete Tables[i]; } - -void DisassemblerTables::emitModRMDecision(raw_ostream &o1, - raw_ostream &o2, - uint32_t &i1, - uint32_t &i2, - ModRMDecision &decision) - const { - static uint64_t sTableNumber = 0; - static uint64_t sEntryNumber = 1; + +void DisassemblerTables::emitModRMDecision(raw_ostream &o1, raw_ostream &o2, + unsigned &i1, unsigned &i2, + ModRMDecision &decision) const { + static uint32_t sTableNumber = 0; + static uint32_t sEntryNumber = 1; ModRMDecisionType dt = getDecisionType(decision); - uint16_t index; if (dt == MODRM_ONEENTRY && decision.instructionIDs[0] == 0) { @@ -338,13 +330,19 @@ void DisassemblerTables::emitModRMDecision(raw_ostream &o1, emitOneID(o1, i1, decision.instructionIDs[0xc0], true); // mod = 0b11 break; case MODRM_SPLITREG: - for (index = 0; index < 64; index += 8) + for (unsigned index = 0; index < 64; index += 8) + emitOneID(o1, i1, decision.instructionIDs[index], true); + for (unsigned index = 0xc0; index < 256; index += 8) emitOneID(o1, i1, decision.instructionIDs[index], true); - for (index = 0xc0; index < 256; index += 8) + break; + case MODRM_SPLITMISC: + for (unsigned index = 0; index < 64; index += 8) + emitOneID(o1, i1, decision.instructionIDs[index], true); + for (unsigned index = 0xc0; index < 256; ++index) emitOneID(o1, i1, decision.instructionIDs[index], true); break; case MODRM_FULL: - for (index = 0; index < 256; ++index) + for (unsigned index = 0; index < 256; ++index) emitOneID(o1, i1, decision.instructionIDs[index], true); break; } @@ -372,28 +370,30 @@ void DisassemblerTables::emitModRMDecision(raw_ostream &o1, case MODRM_SPLITREG: sEntryNumber += 16; break; + case MODRM_SPLITMISC: + sEntryNumber += 8 + 64; + break; case MODRM_FULL: sEntryNumber += 256; break; } + // We assume that the index can fit into uint16_t. + assert(sEntryNumber < 65536U && + "Index into ModRMDecision is too large for uint16_t!"); + ++sTableNumber; } -void DisassemblerTables::emitOpcodeDecision( - raw_ostream &o1, - raw_ostream &o2, - uint32_t &i1, - uint32_t &i2, - OpcodeDecision &decision) const { - uint16_t index; - +void DisassemblerTables::emitOpcodeDecision(raw_ostream &o1, raw_ostream &o2, + unsigned &i1, unsigned &i2, + OpcodeDecision &decision) const { o2.indent(i2) << "{ /* struct OpcodeDecision */" << "\n"; i2++; o2.indent(i2) << "{" << "\n"; i2++; - for (index = 0; index < 256; ++index) { + for (unsigned index = 0; index < 256; ++index) { o2.indent(i2); o2 << "/* 0x" << format("%02hhx", index) << " */" << "\n"; @@ -412,21 +412,16 @@ void DisassemblerTables::emitOpcodeDecision( o2.indent(i2) << "}" << "\n"; } -void DisassemblerTables::emitContextDecision( - raw_ostream &o1, - raw_ostream &o2, - uint32_t &i1, - uint32_t &i2, - ContextDecision &decision, - const char* name) const { +void DisassemblerTables::emitContextDecision(raw_ostream &o1, raw_ostream &o2, + unsigned &i1, unsigned &i2, + ContextDecision &decision, + const char* name) const { o2.indent(i2) << "static const struct ContextDecision " << name << " = {\n"; i2++; o2.indent(i2) << "{ /* opcodeDecisions */" << "\n"; i2++; - unsigned index; - - for (index = 0; index < IC_max; ++index) { + for (unsigned index = 0; index < IC_max; ++index) { o2.indent(i2) << "/* "; o2 << stringForContext((InstructionContext)index); o2 << " */"; @@ -444,58 +439,81 @@ void DisassemblerTables::emitContextDecision( o2.indent(i2) << "};" << "\n"; } -void DisassemblerTables::emitInstructionInfo(raw_ostream &o, uint32_t &i) - const { +void DisassemblerTables::emitInstructionInfo(raw_ostream &o, + unsigned &i) const { + unsigned NumInstructions = InstructionSpecifiers.size(); + + o << "static const struct OperandSpecifier x86OperandSets[][" + << X86_MAX_OPERANDS << "] = {\n"; + + typedef std::vector > OperandListTy; + std::map OperandSets; + + unsigned OperandSetNum = 0; + for (unsigned Index = 0; Index < NumInstructions; ++Index) { + OperandListTy OperandList; + + for (unsigned OperandIndex = 0; OperandIndex < X86_MAX_OPERANDS; + ++OperandIndex) { + const char *Encoding = + stringForOperandEncoding((OperandEncoding)InstructionSpecifiers[Index] + .operands[OperandIndex].encoding); + const char *Type = + stringForOperandType((OperandType)InstructionSpecifiers[Index] + .operands[OperandIndex].type); + OperandList.push_back(std::make_pair(Encoding, Type)); + } + unsigned &N = OperandSets[OperandList]; + if (N != 0) continue; + + N = ++OperandSetNum; + + o << " { /* " << (OperandSetNum - 1) << " */\n"; + for (unsigned i = 0, e = OperandList.size(); i != e; ++i) { + o << " { " << OperandList[i].first << ", " + << OperandList[i].second << " },\n"; + } + o << " },\n"; + } + o << "};" << "\n\n"; + o.indent(i * 2) << "static const struct InstructionSpecifier "; o << INSTRUCTIONS_STR "[" << InstructionSpecifiers.size() << "] = {\n"; - - i++; - uint16_t numInstructions = InstructionSpecifiers.size(); - uint16_t index, operandIndex; + i++; - for (index = 0; index < numInstructions; ++index) { + for (unsigned index = 0; index < NumInstructions; ++index) { o.indent(i * 2) << "{ /* " << index << " */" << "\n"; i++; o.indent(i * 2) << stringForModifierType( (ModifierType)InstructionSpecifiers[index].modifierType); - o << "," << "\n"; + o << ",\n"; o.indent(i * 2) << "0x"; o << format("%02hhx", (uint16_t)InstructionSpecifiers[index].modifierBase); - o << "," << "\n"; - - o.indent(i * 2) << "{" << "\n"; - i++; - - for (operandIndex = 0; operandIndex < X86_MAX_OPERANDS; ++operandIndex) { - o.indent(i * 2) << "{ "; - o <