Home | History | Annotate | Download | only in TableGen
      1 //===- X86DisassemblerTables.cpp - Disassembler tables ----------*- C++ -*-===//
      2 //
      3 //                     The LLVM Compiler Infrastructure
      4 //
      5 // This file is distributed under the University of Illinois Open Source
      6 // License. See LICENSE.TXT for details.
      7 //
      8 //===----------------------------------------------------------------------===//
      9 //
     10 // This file is part of the X86 Disassembler Emitter.
     11 // It contains the implementation of the disassembler tables.
     12 // Documentation for the disassembler emitter in general can be found in
     13 //  X86DisasemblerEmitter.h.
     14 //
     15 //===----------------------------------------------------------------------===//
     16 
     17 #include "X86DisassemblerTables.h"
     18 #include "X86DisassemblerShared.h"
     19 #include "llvm/ADT/STLExtras.h"
     20 #include "llvm/Support/ErrorHandling.h"
     21 #include "llvm/Support/Format.h"
     22 #include "llvm/TableGen/TableGenBackend.h"
     23 #include <map>
     24 
     25 using namespace llvm;
     26 using namespace X86Disassembler;
     27 
     28 /// inheritsFrom - Indicates whether all instructions in one class also belong
     29 ///   to another class.
     30 ///
     31 /// @param child  - The class that may be the subset
     32 /// @param parent - The class that may be the superset
     33 /// @return       - True if child is a subset of parent, false otherwise.
     34 static inline bool inheritsFrom(InstructionContext child,
     35                                 InstructionContext parent,
     36                                 bool VEX_LIG = false) {
     37   if (child == parent)
     38     return true;
     39 
     40   switch (parent) {
     41   case IC:
     42     return(inheritsFrom(child, IC_64BIT) ||
     43            inheritsFrom(child, IC_OPSIZE) ||
     44            inheritsFrom(child, IC_ADSIZE) ||
     45            inheritsFrom(child, IC_XD) ||
     46            inheritsFrom(child, IC_XS));
     47   case IC_64BIT:
     48     return(inheritsFrom(child, IC_64BIT_REXW)   ||
     49            inheritsFrom(child, IC_64BIT_OPSIZE) ||
     50            inheritsFrom(child, IC_64BIT_ADSIZE) ||
     51            inheritsFrom(child, IC_64BIT_XD)     ||
     52            inheritsFrom(child, IC_64BIT_XS));
     53   case IC_OPSIZE:
     54     return inheritsFrom(child, IC_64BIT_OPSIZE);
     55   case IC_ADSIZE:
     56   case IC_64BIT_ADSIZE:
     57     return false;
     58   case IC_XD:
     59     return inheritsFrom(child, IC_64BIT_XD);
     60   case IC_XS:
     61     return inheritsFrom(child, IC_64BIT_XS);
     62   case IC_XD_OPSIZE:
     63     return inheritsFrom(child, IC_64BIT_XD_OPSIZE);
     64   case IC_XS_OPSIZE:
     65     return inheritsFrom(child, IC_64BIT_XS_OPSIZE);
     66   case IC_64BIT_REXW:
     67     return(inheritsFrom(child, IC_64BIT_REXW_XS) ||
     68            inheritsFrom(child, IC_64BIT_REXW_XD) ||
     69            inheritsFrom(child, IC_64BIT_REXW_OPSIZE));
     70   case IC_64BIT_OPSIZE:
     71     return(inheritsFrom(child, IC_64BIT_REXW_OPSIZE));
     72   case IC_64BIT_XD:
     73     return(inheritsFrom(child, IC_64BIT_REXW_XD));
     74   case IC_64BIT_XS:
     75     return(inheritsFrom(child, IC_64BIT_REXW_XS));
     76   case IC_64BIT_XD_OPSIZE:
     77   case IC_64BIT_XS_OPSIZE:
     78     return false;
     79   case IC_64BIT_REXW_XD:
     80   case IC_64BIT_REXW_XS:
     81   case IC_64BIT_REXW_OPSIZE:
     82     return false;
     83   case IC_VEX:
     84     return inheritsFrom(child, IC_VEX_W) ||
     85            (VEX_LIG && inheritsFrom(child, IC_VEX_L));
     86   case IC_VEX_XS:
     87     return inheritsFrom(child, IC_VEX_W_XS) ||
     88            (VEX_LIG && inheritsFrom(child, IC_VEX_L_XS));
     89   case IC_VEX_XD:
     90     return inheritsFrom(child, IC_VEX_W_XD) ||
     91            (VEX_LIG && inheritsFrom(child, IC_VEX_L_XD));
     92   case IC_VEX_OPSIZE:
     93     return inheritsFrom(child, IC_VEX_W_OPSIZE) ||
     94            (VEX_LIG && inheritsFrom(child, IC_VEX_L_OPSIZE));
     95   case IC_VEX_W:
     96   case IC_VEX_W_XS:
     97   case IC_VEX_W_XD:
     98   case IC_VEX_W_OPSIZE:
     99     return false;
    100   case IC_VEX_L:
    101   case IC_VEX_L_XS:
    102   case IC_VEX_L_XD:
    103     return false;
    104   case IC_VEX_L_OPSIZE:
    105     return inheritsFrom(child, IC_VEX_L_W_OPSIZE);
    106   case IC_VEX_L_W_OPSIZE:
    107     return false;
    108   default:
    109     llvm_unreachable("Unknown instruction class");
    110   }
    111 }
    112 
    113 /// outranks - Indicates whether, if an instruction has two different applicable
    114 ///   classes, which class should be preferred when performing decode.  This
    115 ///   imposes a total ordering (ties are resolved toward "lower")
    116 ///
    117 /// @param upper  - The class that may be preferable
    118 /// @param lower  - The class that may be less preferable
    119 /// @return       - True if upper is to be preferred, false otherwise.
    120 static inline bool outranks(InstructionContext upper,
    121                             InstructionContext lower) {
    122   assert(upper < IC_max);
    123   assert(lower < IC_max);
    124 
    125 #define ENUM_ENTRY(n, r, d) r,
    126   static int ranks[IC_max] = {
    127     INSTRUCTION_CONTEXTS
    128   };
    129 #undef ENUM_ENTRY
    130 
    131   return (ranks[upper] > ranks[lower]);
    132 }
    133 
    134 /// stringForContext - Returns a string containing the name of a particular
    135 ///   InstructionContext, usually for diagnostic purposes.
    136 ///
    137 /// @param insnContext  - The instruction class to transform to a string.
    138 /// @return           - A statically-allocated string constant that contains the
    139 ///                     name of the instruction class.
    140 static inline const char* stringForContext(InstructionContext insnContext) {
    141   switch (insnContext) {
    142   default:
    143     llvm_unreachable("Unhandled instruction class");
    144 #define ENUM_ENTRY(n, r, d)   case n: return #n; break;
    145   INSTRUCTION_CONTEXTS
    146 #undef ENUM_ENTRY
    147   }
    148 }
    149 
    150 /// stringForOperandType - Like stringForContext, but for OperandTypes.
    151 static inline const char* stringForOperandType(OperandType type) {
    152   switch (type) {
    153   default:
    154     llvm_unreachable("Unhandled type");
    155 #define ENUM_ENTRY(i, d) case i: return #i;
    156   TYPES
    157 #undef ENUM_ENTRY
    158   }
    159 }
    160 
    161 /// stringForOperandEncoding - like stringForContext, but for
    162 ///   OperandEncodings.
    163 static inline const char* stringForOperandEncoding(OperandEncoding encoding) {
    164   switch (encoding) {
    165   default:
    166     llvm_unreachable("Unhandled encoding");
    167 #define ENUM_ENTRY(i, d) case i: return #i;
    168   ENCODINGS
    169 #undef ENUM_ENTRY
    170   }
    171 }
    172 
    173 void DisassemblerTables::emitOneID(raw_ostream &o, unsigned &i, InstrUID id,
    174                                    bool addComma) const {
    175   if (id)
    176     o.indent(i * 2) << format("0x%hx", id);
    177   else
    178     o.indent(i * 2) << 0;
    179 
    180   if (addComma)
    181     o << ", ";
    182   else
    183     o << "  ";
    184 
    185   o << "/* ";
    186   o << InstructionSpecifiers[id].name;
    187   o << "*/";
    188 
    189   o << "\n";
    190 }
    191 
    192 /// emitEmptyTable - Emits the modRMEmptyTable, which is used as a ID table by
    193 ///   all ModR/M decisions for instructions that are invalid for all possible
    194 ///   ModR/M byte values.
    195 ///
    196 /// @param o        - The output stream on which to emit the table.
    197 /// @param i        - The indentation level for that output stream.
    198 static void emitEmptyTable(raw_ostream &o, unsigned &i) {
    199   o.indent(i * 2) << "0x0, /* EmptyTable */\n";
    200 }
    201 
    202 /// getDecisionType - Determines whether a ModRM decision with 255 entries can
    203 ///   be compacted by eliminating redundant information.
    204 ///
    205 /// @param decision - The decision to be compacted.
    206 /// @return         - The compactest available representation for the decision.
    207 static ModRMDecisionType getDecisionType(ModRMDecision &decision) {
    208   bool satisfiesOneEntry = true;
    209   bool satisfiesSplitRM = true;
    210   bool satisfiesSplitReg = true;
    211   bool satisfiesSplitMisc = true;
    212 
    213   for (unsigned index = 0; index < 256; ++index) {
    214     if (decision.instructionIDs[index] != decision.instructionIDs[0])
    215       satisfiesOneEntry = false;
    216 
    217     if (((index & 0xc0) == 0xc0) &&
    218        (decision.instructionIDs[index] != decision.instructionIDs[0xc0]))
    219       satisfiesSplitRM = false;
    220 
    221     if (((index & 0xc0) != 0xc0) &&
    222        (decision.instructionIDs[index] != decision.instructionIDs[0x00]))
    223       satisfiesSplitRM = false;
    224 
    225     if (((index & 0xc0) == 0xc0) &&
    226        (decision.instructionIDs[index] != decision.instructionIDs[index&0xf8]))
    227       satisfiesSplitReg = false;
    228 
    229     if (((index & 0xc0) != 0xc0) &&
    230        (decision.instructionIDs[index] != decision.instructionIDs[index&0x38]))
    231       satisfiesSplitMisc = false;
    232   }
    233 
    234   if (satisfiesOneEntry)
    235     return MODRM_ONEENTRY;
    236 
    237   if (satisfiesSplitRM)
    238     return MODRM_SPLITRM;
    239 
    240   if (satisfiesSplitReg && satisfiesSplitMisc)
    241     return MODRM_SPLITREG;
    242 
    243   if (satisfiesSplitMisc)
    244     return MODRM_SPLITMISC;
    245 
    246   return MODRM_FULL;
    247 }
    248 
    249 /// stringForDecisionType - Returns a statically-allocated string corresponding
    250 ///   to a particular decision type.
    251 ///
    252 /// @param dt - The decision type.
    253 /// @return   - A pointer to the statically-allocated string (e.g.,
    254 ///             "MODRM_ONEENTRY" for MODRM_ONEENTRY).
    255 static const char* stringForDecisionType(ModRMDecisionType dt) {
    256 #define ENUM_ENTRY(n) case n: return #n;
    257   switch (dt) {
    258     default:
    259       llvm_unreachable("Unknown decision type");
    260     MODRMTYPES
    261   };
    262 #undef ENUM_ENTRY
    263 }
    264 
    265 /// stringForModifierType - Returns a statically-allocated string corresponding
    266 ///   to an opcode modifier type.
    267 ///
    268 /// @param mt - The modifier type.
    269 /// @return   - A pointer to the statically-allocated string (e.g.,
    270 ///             "MODIFIER_NONE" for MODIFIER_NONE).
    271 static const char* stringForModifierType(ModifierType mt) {
    272 #define ENUM_ENTRY(n) case n: return #n;
    273   switch(mt) {
    274     default:
    275       llvm_unreachable("Unknown modifier type");
    276     MODIFIER_TYPES
    277   };
    278 #undef ENUM_ENTRY
    279 }
    280 
    281 DisassemblerTables::DisassemblerTables() {
    282   unsigned i;
    283 
    284   for (i = 0; i < array_lengthof(Tables); i++) {
    285     Tables[i] = new ContextDecision;
    286     memset(Tables[i], 0, sizeof(ContextDecision));
    287   }
    288 
    289   HasConflicts = false;
    290 }
    291 
    292 DisassemblerTables::~DisassemblerTables() {
    293   unsigned i;
    294 
    295   for (i = 0; i < array_lengthof(Tables); i++)
    296     delete Tables[i];
    297 }
    298 
    299 void DisassemblerTables::emitModRMDecision(raw_ostream &o1, raw_ostream &o2,
    300                                            unsigned &i1, unsigned &i2,
    301                                            ModRMDecision &decision) const {
    302   static uint32_t sTableNumber = 0;
    303   static uint32_t sEntryNumber = 1;
    304   ModRMDecisionType dt = getDecisionType(decision);
    305 
    306   if (dt == MODRM_ONEENTRY && decision.instructionIDs[0] == 0)
    307   {
    308     o2.indent(i2) << "{ /* ModRMDecision */" << "\n";
    309     i2++;
    310 
    311     o2.indent(i2) << stringForDecisionType(dt) << "," << "\n";
    312     o2.indent(i2) << 0 << " /* EmptyTable */\n";
    313 
    314     i2--;
    315     o2.indent(i2) << "}";
    316     return;
    317   }
    318 
    319   o1 << "/* Table" << sTableNumber << " */\n";
    320   i1++;
    321 
    322   switch (dt) {
    323     default:
    324       llvm_unreachable("Unknown decision type");
    325     case MODRM_ONEENTRY:
    326       emitOneID(o1, i1, decision.instructionIDs[0], true);
    327       break;
    328     case MODRM_SPLITRM:
    329       emitOneID(o1, i1, decision.instructionIDs[0x00], true); // mod = 0b00
    330       emitOneID(o1, i1, decision.instructionIDs[0xc0], true); // mod = 0b11
    331       break;
    332     case MODRM_SPLITREG:
    333       for (unsigned index = 0; index < 64; index += 8)
    334         emitOneID(o1, i1, decision.instructionIDs[index], true);
    335       for (unsigned index = 0xc0; index < 256; index += 8)
    336         emitOneID(o1, i1, decision.instructionIDs[index], true);
    337       break;
    338     case MODRM_SPLITMISC:
    339       for (unsigned index = 0; index < 64; index += 8)
    340         emitOneID(o1, i1, decision.instructionIDs[index], true);
    341       for (unsigned index = 0xc0; index < 256; ++index)
    342         emitOneID(o1, i1, decision.instructionIDs[index], true);
    343       break;
    344     case MODRM_FULL:
    345       for (unsigned index = 0; index < 256; ++index)
    346         emitOneID(o1, i1, decision.instructionIDs[index], true);
    347       break;
    348   }
    349 
    350   i1--;
    351 
    352   o2.indent(i2) << "{ /* struct ModRMDecision */" << "\n";
    353   i2++;
    354 
    355   o2.indent(i2) << stringForDecisionType(dt) << "," << "\n";
    356   o2.indent(i2) << sEntryNumber << " /* Table" << sTableNumber << " */\n";
    357 
    358   i2--;
    359   o2.indent(i2) << "}";
    360 
    361   switch (dt) {
    362     default:
    363       llvm_unreachable("Unknown decision type");
    364     case MODRM_ONEENTRY:
    365       sEntryNumber += 1;
    366       break;
    367     case MODRM_SPLITRM:
    368       sEntryNumber += 2;
    369       break;
    370     case MODRM_SPLITREG:
    371       sEntryNumber += 16;
    372       break;
    373     case MODRM_SPLITMISC:
    374       sEntryNumber += 8 + 64;
    375       break;
    376     case MODRM_FULL:
    377       sEntryNumber += 256;
    378       break;
    379   }
    380 
    381   // We assume that the index can fit into uint16_t.
    382   assert(sEntryNumber < 65536U &&
    383          "Index into ModRMDecision is too large for uint16_t!");
    384 
    385   ++sTableNumber;
    386 }
    387 
    388 void DisassemblerTables::emitOpcodeDecision(raw_ostream &o1, raw_ostream &o2,
    389                                             unsigned &i1, unsigned &i2,
    390                                             OpcodeDecision &decision) const {
    391   o2.indent(i2) << "{ /* struct OpcodeDecision */" << "\n";
    392   i2++;
    393   o2.indent(i2) << "{" << "\n";
    394   i2++;
    395 
    396   for (unsigned index = 0; index < 256; ++index) {
    397     o2.indent(i2);
    398 
    399     o2 << "/* 0x" << format("%02hhx", index) << " */" << "\n";
    400 
    401     emitModRMDecision(o1, o2, i1, i2, decision.modRMDecisions[index]);
    402 
    403     if (index <  255)
    404       o2 << ",";
    405 
    406     o2 << "\n";
    407   }
    408 
    409   i2--;
    410   o2.indent(i2) << "}" << "\n";
    411   i2--;
    412   o2.indent(i2) << "}" << "\n";
    413 }
    414 
    415 void DisassemblerTables::emitContextDecision(raw_ostream &o1, raw_ostream &o2,
    416                                              unsigned &i1, unsigned &i2,
    417                                              ContextDecision &decision,
    418                                              const char* name) const {
    419   o2.indent(i2) << "static const struct ContextDecision " << name << " = {\n";
    420   i2++;
    421   o2.indent(i2) << "{ /* opcodeDecisions */" << "\n";
    422   i2++;
    423 
    424   for (unsigned index = 0; index < IC_max; ++index) {
    425     o2.indent(i2) << "/* ";
    426     o2 << stringForContext((InstructionContext)index);
    427     o2 << " */";
    428     o2 << "\n";
    429 
    430     emitOpcodeDecision(o1, o2, i1, i2, decision.opcodeDecisions[index]);
    431 
    432     if (index + 1 < IC_max)
    433       o2 << ", ";
    434   }
    435 
    436   i2--;
    437   o2.indent(i2) << "}" << "\n";
    438   i2--;
    439   o2.indent(i2) << "};" << "\n";
    440 }
    441 
    442 void DisassemblerTables::emitInstructionInfo(raw_ostream &o,
    443                                              unsigned &i) const {
    444   unsigned NumInstructions = InstructionSpecifiers.size();
    445 
    446   o << "static const struct OperandSpecifier x86OperandSets[]["
    447     << X86_MAX_OPERANDS << "] = {\n";
    448 
    449   typedef std::vector<std::pair<const char *, const char *> > OperandListTy;
    450   std::map<OperandListTy, unsigned> OperandSets;
    451 
    452   unsigned OperandSetNum = 0;
    453   for (unsigned Index = 0; Index < NumInstructions; ++Index) {
    454     OperandListTy OperandList;
    455 
    456     for (unsigned OperandIndex = 0; OperandIndex < X86_MAX_OPERANDS;
    457          ++OperandIndex) {
    458       const char *Encoding =
    459         stringForOperandEncoding((OperandEncoding)InstructionSpecifiers[Index]
    460                                  .operands[OperandIndex].encoding);
    461       const char *Type =
    462         stringForOperandType((OperandType)InstructionSpecifiers[Index]
    463                              .operands[OperandIndex].type);
    464       OperandList.push_back(std::make_pair(Encoding, Type));
    465     }
    466     unsigned &N = OperandSets[OperandList];
    467     if (N != 0) continue;
    468 
    469     N = ++OperandSetNum;
    470 
    471     o << "  { /* " << (OperandSetNum - 1) << " */\n";
    472     for (unsigned i = 0, e = OperandList.size(); i != e; ++i) {
    473       o << "    { " << OperandList[i].first << ", "
    474         << OperandList[i].second << " },\n";
    475     }
    476     o << "  },\n";
    477   }
    478   o << "};" << "\n\n";
    479 
    480   o.indent(i * 2) << "static const struct InstructionSpecifier ";
    481   o << INSTRUCTIONS_STR "[" << InstructionSpecifiers.size() << "] = {\n";
    482 
    483   i++;
    484 
    485   for (unsigned index = 0; index < NumInstructions; ++index) {
    486     o.indent(i * 2) << "{ /* " << index << " */" << "\n";
    487     i++;
    488 
    489     o.indent(i * 2) << stringForModifierType(
    490                        (ModifierType)InstructionSpecifiers[index].modifierType);
    491     o << ",\n";
    492 
    493     o.indent(i * 2) << "0x";
    494     o << format("%02hhx", (uint16_t)InstructionSpecifiers[index].modifierBase);
    495     o << ",\n";
    496 
    497     OperandListTy OperandList;
    498     for (unsigned OperandIndex = 0; OperandIndex < X86_MAX_OPERANDS;
    499          ++OperandIndex) {
    500       const char *Encoding =
    501         stringForOperandEncoding((OperandEncoding)InstructionSpecifiers[index]
    502                                  .operands[OperandIndex].encoding);
    503       const char *Type =
    504         stringForOperandType((OperandType)InstructionSpecifiers[index]
    505                              .operands[OperandIndex].type);
    506       OperandList.push_back(std::make_pair(Encoding, Type));
    507     }
    508     o.indent(i * 2) << (OperandSets[OperandList] - 1) << ",\n";
    509 
    510     o.indent(i * 2) << "/* " << InstructionSpecifiers[index].name << " */";
    511     o << "\n";
    512 
    513     i--;
    514     o.indent(i * 2) << "}";
    515 
    516     if (index + 1 < NumInstructions)
    517       o << ",";
    518 
    519     o << "\n";
    520   }
    521 
    522   i--;
    523   o.indent(i * 2) << "};" << "\n";
    524 }
    525 
    526 void DisassemblerTables::emitContextTable(raw_ostream &o, unsigned &i) const {
    527   o.indent(i * 2) << "static const uint8_t " CONTEXTS_STR
    528                      "[256] = {\n";
    529   i++;
    530 
    531   for (unsigned index = 0; index < 256; ++index) {
    532     o.indent(i * 2);
    533 
    534     if ((index & ATTR_VEXL) && (index & ATTR_REXW) && (index & ATTR_OPSIZE))
    535       o << "IC_VEX_L_W_OPSIZE";
    536     else if ((index & ATTR_VEXL) && (index & ATTR_OPSIZE))
    537       o << "IC_VEX_L_OPSIZE";
    538     else if ((index & ATTR_VEXL) && (index & ATTR_XD))
    539       o << "IC_VEX_L_XD";
    540     else if ((index & ATTR_VEXL) && (index & ATTR_XS))
    541       o << "IC_VEX_L_XS";
    542     else if ((index & ATTR_VEX) && (index & ATTR_REXW) && (index & ATTR_OPSIZE))
    543       o << "IC_VEX_W_OPSIZE";
    544     else if ((index & ATTR_VEX) && (index & ATTR_REXW) && (index & ATTR_XD))
    545       o << "IC_VEX_W_XD";
    546     else if ((index & ATTR_VEX) && (index & ATTR_REXW) && (index & ATTR_XS))
    547       o << "IC_VEX_W_XS";
    548     else if (index & ATTR_VEXL)
    549       o << "IC_VEX_L";
    550     else if ((index & ATTR_VEX) && (index & ATTR_REXW))
    551       o << "IC_VEX_W";
    552     else if ((index & ATTR_VEX) && (index & ATTR_OPSIZE))
    553       o << "IC_VEX_OPSIZE";
    554     else if ((index & ATTR_VEX) && (index & ATTR_XD))
    555       o << "IC_VEX_XD";
    556     else if ((index & ATTR_VEX) && (index & ATTR_XS))
    557       o << "IC_VEX_XS";
    558     else if (index & ATTR_VEX)
    559       o << "IC_VEX";
    560     else if ((index & ATTR_64BIT) && (index & ATTR_REXW) && (index & ATTR_XS))
    561       o << "IC_64BIT_REXW_XS";
    562     else if ((index & ATTR_64BIT) && (index & ATTR_REXW) && (index & ATTR_XD))
    563       o << "IC_64BIT_REXW_XD";
    564     else if ((index & ATTR_64BIT) && (index & ATTR_REXW) &&
    565              (index & ATTR_OPSIZE))
    566       o << "IC_64BIT_REXW_OPSIZE";
    567     else if ((index & ATTR_64BIT) && (index & ATTR_XD) && (index & ATTR_OPSIZE))
    568       o << "IC_64BIT_XD_OPSIZE";
    569     else if ((index & ATTR_64BIT) && (index & ATTR_XS) && (index & ATTR_OPSIZE))
    570       o << "IC_64BIT_XS_OPSIZE";
    571     else if ((index & ATTR_64BIT) && (index & ATTR_XS))
    572       o << "IC_64BIT_XS";
    573     else if ((index & ATTR_64BIT) && (index & ATTR_XD))
    574       o << "IC_64BIT_XD";
    575     else if ((index & ATTR_64BIT) && (index & ATTR_OPSIZE))
    576       o << "IC_64BIT_OPSIZE";
    577     else if ((index & ATTR_64BIT) && (index & ATTR_ADSIZE))
    578       o << "IC_64BIT_ADSIZE";
    579     else if ((index & ATTR_64BIT) && (index & ATTR_REXW))
    580       o << "IC_64BIT_REXW";
    581     else if ((index & ATTR_64BIT))
    582       o << "IC_64BIT";
    583     else if ((index & ATTR_XS) && (index & ATTR_OPSIZE))
    584       o << "IC_XS_OPSIZE";
    585     else if ((index & ATTR_XD) && (index & ATTR_OPSIZE))
    586       o << "IC_XD_OPSIZE";
    587     else if (index & ATTR_XS)
    588       o << "IC_XS";
    589     else if (index & ATTR_XD)
    590       o << "IC_XD";
    591     else if (index & ATTR_OPSIZE)
    592       o << "IC_OPSIZE";
    593     else if (index & ATTR_ADSIZE)
    594       o << "IC_ADSIZE";
    595     else
    596       o << "IC";
    597 
    598     if (index < 255)
    599       o << ",";
    600     else
    601       o << " ";
    602 
    603     o << " /* " << index << " */";
    604 
    605     o << "\n";
    606   }
    607 
    608   i--;
    609   o.indent(i * 2) << "};" << "\n";
    610 }
    611 
    612 void DisassemblerTables::emitContextDecisions(raw_ostream &o1, raw_ostream &o2,
    613                                              unsigned &i1, unsigned &i2) const {
    614   emitContextDecision(o1, o2, i1, i2, *Tables[0], ONEBYTE_STR);
    615   emitContextDecision(o1, o2, i1, i2, *Tables[1], TWOBYTE_STR);
    616   emitContextDecision(o1, o2, i1, i2, *Tables[2], THREEBYTE38_STR);
    617   emitContextDecision(o1, o2, i1, i2, *Tables[3], THREEBYTE3A_STR);
    618   emitContextDecision(o1, o2, i1, i2, *Tables[4], THREEBYTEA6_STR);
    619   emitContextDecision(o1, o2, i1, i2, *Tables[5], THREEBYTEA7_STR);
    620 }
    621 
    622 void DisassemblerTables::emit(raw_ostream &o) const {
    623   unsigned i1 = 0;
    624   unsigned i2 = 0;
    625 
    626   std::string s1;
    627   std::string s2;
    628 
    629   raw_string_ostream o1(s1);
    630   raw_string_ostream o2(s2);
    631 
    632   emitInstructionInfo(o, i2);
    633   o << "\n";
    634 
    635   emitContextTable(o, i2);
    636   o << "\n";
    637 
    638   o << "static const InstrUID modRMTable[] = {\n";
    639   i1++;
    640   emitEmptyTable(o1, i1);
    641   i1--;
    642   emitContextDecisions(o1, o2, i1, i2);
    643 
    644   o << o1.str();
    645   o << "  0x0\n";
    646   o << "};\n";
    647   o << "\n";
    648   o << o2.str();
    649   o << "\n";
    650   o << "\n";
    651 }
    652 
    653 void DisassemblerTables::setTableFields(ModRMDecision     &decision,
    654                                         const ModRMFilter &filter,
    655                                         InstrUID          uid,
    656                                         uint8_t           opcode) {
    657   for (unsigned index = 0; index < 256; ++index) {
    658     if (filter.accepts(index)) {
    659       if (decision.instructionIDs[index] == uid)
    660         continue;
    661 
    662       if (decision.instructionIDs[index] != 0) {
    663         InstructionSpecifier &newInfo =
    664           InstructionSpecifiers[uid];
    665         InstructionSpecifier &previousInfo =
    666           InstructionSpecifiers[decision.instructionIDs[index]];
    667 
    668         if(newInfo.filtered)
    669           continue; // filtered instructions get lowest priority
    670 
    671         if(previousInfo.name == "NOOP" && (newInfo.name == "XCHG16ar" ||
    672                                            newInfo.name == "XCHG32ar" ||
    673                                            newInfo.name == "XCHG32ar64" ||
    674                                            newInfo.name == "XCHG64ar"))
    675           continue; // special case for XCHG*ar and NOOP
    676 
    677         if (outranks(previousInfo.insnContext, newInfo.insnContext))
    678           continue;
    679 
    680         if (previousInfo.insnContext == newInfo.insnContext &&
    681             !previousInfo.filtered) {
    682           errs() << "Error: Primary decode conflict: ";
    683           errs() << newInfo.name << " would overwrite " << previousInfo.name;
    684           errs() << "\n";
    685           errs() << "ModRM   " << index << "\n";
    686           errs() << "Opcode  " << (uint16_t)opcode << "\n";
    687           errs() << "Context " << stringForContext(newInfo.insnContext) << "\n";
    688           HasConflicts = true;
    689         }
    690       }
    691 
    692       decision.instructionIDs[index] = uid;
    693     }
    694   }
    695 }
    696 
    697 void DisassemblerTables::setTableFields(OpcodeType          type,
    698                                         InstructionContext  insnContext,
    699                                         uint8_t             opcode,
    700                                         const ModRMFilter   &filter,
    701                                         InstrUID            uid,
    702                                         bool                is32bit,
    703                                         bool                ignoresVEX_L) {
    704   ContextDecision &decision = *Tables[type];
    705 
    706   for (unsigned index = 0; index < IC_max; ++index) {
    707     if (is32bit && inheritsFrom((InstructionContext)index, IC_64BIT))
    708       continue;
    709 
    710     if (inheritsFrom((InstructionContext)index,
    711                      InstructionSpecifiers[uid].insnContext, ignoresVEX_L))
    712       setTableFields(decision.opcodeDecisions[index].modRMDecisions[opcode],
    713                      filter,
    714                      uid,
    715                      opcode);
    716   }
    717 }
    718