X86DisassemblerTables.cpp revision 239462
14Srgrimes//===- X86DisassemblerTables.cpp - Disassembler tables ----------*- C++ -*-===//
24Srgrimes//
34Srgrimes//                     The LLVM Compiler Infrastructure
44Srgrimes//
54Srgrimes// This file is distributed under the University of Illinois Open Source
64Srgrimes// License. See LICENSE.TXT for details.
74Srgrimes//
84Srgrimes//===----------------------------------------------------------------------===//
94Srgrimes//
104Srgrimes// This file is part of the X86 Disassembler Emitter.
114Srgrimes// It contains the implementation of the disassembler tables.
124Srgrimes// Documentation for the disassembler emitter in general can be found in
134Srgrimes//  X86DisasemblerEmitter.h.
144Srgrimes//
154Srgrimes//===----------------------------------------------------------------------===//
164Srgrimes
174Srgrimes#include "X86DisassemblerShared.h"
184Srgrimes#include "X86DisassemblerTables.h"
194Srgrimes
204Srgrimes#include "llvm/TableGen/TableGenBackend.h"
214Srgrimes#include "llvm/ADT/STLExtras.h"
224Srgrimes#include "llvm/Support/ErrorHandling.h"
234Srgrimes#include "llvm/Support/Format.h"
244Srgrimes#include <map>
254Srgrimes
264Srgrimesusing namespace llvm;
274Srgrimesusing namespace X86Disassembler;
284Srgrimes
294Srgrimes/// inheritsFrom - Indicates whether all instructions in one class also belong
304Srgrimes///   to another class.
314Srgrimes///
32619Srgrimes/// @param child  - The class that may be the subset
3350477Speter/// @param parent - The class that may be the superset
344Srgrimes/// @return       - True if child is a subset of parent, false otherwise.
354Srgrimesstatic inline bool inheritsFrom(InstructionContext child,
36720Swollman                                InstructionContext parent,
37720Swollman                                bool VEX_LIG = false) {
38720Swollman  if (child == parent)
394Srgrimes    return true;
4037556Sphk
414Srgrimes  switch (parent) {
424Srgrimes  case IC:
434Srgrimes    return(inheritsFrom(child, IC_64BIT) ||
444Srgrimes           inheritsFrom(child, IC_OPSIZE) ||
454Srgrimes           inheritsFrom(child, IC_ADSIZE) ||
464Srgrimes           inheritsFrom(child, IC_XD) ||
474Srgrimes           inheritsFrom(child, IC_XS));
484Srgrimes  case IC_64BIT:
494Srgrimes    return(inheritsFrom(child, IC_64BIT_REXW)   ||
504Srgrimes           inheritsFrom(child, IC_64BIT_OPSIZE) ||
514Srgrimes           inheritsFrom(child, IC_64BIT_ADSIZE) ||
524Srgrimes           inheritsFrom(child, IC_64BIT_XD)     ||
532074Swollman           inheritsFrom(child, IC_64BIT_XS));
544Srgrimes  case IC_OPSIZE:
554Srgrimes    return inheritsFrom(child, IC_64BIT_OPSIZE);
5637556Sphk  case IC_ADSIZE:
572074Swollman  case IC_64BIT_ADSIZE:
5837556Sphk    return false;
592074Swollman  case IC_XD:
602074Swollman    return inheritsFrom(child, IC_64BIT_XD);
612074Swollman  case IC_XS:
622074Swollman    return inheritsFrom(child, IC_64BIT_XS);
632074Swollman  case IC_XD_OPSIZE:
642074Swollman    return inheritsFrom(child, IC_64BIT_XD_OPSIZE);
652074Swollman  case IC_XS_OPSIZE:
662074Swollman    return inheritsFrom(child, IC_64BIT_XS_OPSIZE);
672074Swollman  case IC_64BIT_REXW:
682074Swollman    return(inheritsFrom(child, IC_64BIT_REXW_XS) ||
692074Swollman           inheritsFrom(child, IC_64BIT_REXW_XD) ||
7037556Sphk           inheritsFrom(child, IC_64BIT_REXW_OPSIZE));
714Srgrimes  case IC_64BIT_OPSIZE:
724Srgrimes    return(inheritsFrom(child, IC_64BIT_REXW_OPSIZE));
7337556Sphk  case IC_64BIT_XD:
742913Sache    return(inheritsFrom(child, IC_64BIT_REXW_XD));
752913Sache  case IC_64BIT_XS:
762913Sache    return(inheritsFrom(child, IC_64BIT_REXW_XS));
772913Sache  case IC_64BIT_XD_OPSIZE:
782913Sache  case IC_64BIT_XS_OPSIZE:
792913Sache    return false;
802074Swollman  case IC_64BIT_REXW_XD:
814Srgrimes  case IC_64BIT_REXW_XS:
824Srgrimes  case IC_64BIT_REXW_OPSIZE:
834Srgrimes    return false;
844Srgrimes  case IC_VEX:
854Srgrimes    return inheritsFrom(child, IC_VEX_W) ||
864Srgrimes           (VEX_LIG && inheritsFrom(child, IC_VEX_L));
874Srgrimes  case IC_VEX_XS:
884Srgrimes    return inheritsFrom(child, IC_VEX_W_XS) ||
8937556Sphk           (VEX_LIG && inheritsFrom(child, IC_VEX_L_XS));
904Srgrimes  case IC_VEX_XD:
914Srgrimes    return inheritsFrom(child, IC_VEX_W_XD) ||
924Srgrimes           (VEX_LIG && inheritsFrom(child, IC_VEX_L_XD));
934Srgrimes  case IC_VEX_OPSIZE:
944Srgrimes    return inheritsFrom(child, IC_VEX_W_OPSIZE) ||
954Srgrimes           (VEX_LIG && inheritsFrom(child, IC_VEX_L_OPSIZE));
964Srgrimes  case IC_VEX_W:
974Srgrimes  case IC_VEX_W_XS:
984Srgrimes  case IC_VEX_W_XD:
994Srgrimes  case IC_VEX_W_OPSIZE:
1004Srgrimes    return false;
1014Srgrimes  case IC_VEX_L:
102873Sache  case IC_VEX_L_XS:
1034Srgrimes  case IC_VEX_L_XD:
10411375Sjoerg    return false;
1054968Sjoerg  case IC_VEX_L_OPSIZE:
1064Srgrimes    return inheritsFrom(child, IC_VEX_L_W_OPSIZE);
1074Srgrimes  case IC_VEX_L_W_OPSIZE:
1084Srgrimes    return false;
1094Srgrimes  default:
1104Srgrimes    llvm_unreachable("Unknown instruction class");
1114Srgrimes  }
1122913Sache}
113178192Sphk
114178192Sphk/// outranks - Indicates whether, if an instruction has two different applicable
115178192Sphk///   classes, which class should be preferred when performing decode.  This
116191766Smav///   imposes a total ordering (ties are resolved toward "lower")
117191766Smav///
118178192Sphk/// @param upper  - The class that may be preferable
119178192Sphk/// @param lower  - The class that may be less preferable
120178192Sphk/// @return       - True if upper is to be preferred, false otherwise.
121178192Sphkstatic inline bool outranks(InstructionContext upper,
122178192Sphk                            InstructionContext lower) {
123178192Sphk  assert(upper < IC_max);
124178192Sphk  assert(lower < IC_max);
125178192Sphk
126720Swollman#define ENUM_ENTRY(n, r, d) r,
127  static int ranks[IC_max] = {
128    INSTRUCTION_CONTEXTS
129  };
130#undef ENUM_ENTRY
131
132  return (ranks[upper] > ranks[lower]);
133}
134
135/// stringForContext - Returns a string containing the name of a particular
136///   InstructionContext, usually for diagnostic purposes.
137///
138/// @param insnContext  - The instruction class to transform to a string.
139/// @return           - A statically-allocated string constant that contains the
140///                     name of the instruction class.
141static inline const char* stringForContext(InstructionContext insnContext) {
142  switch (insnContext) {
143  default:
144    llvm_unreachable("Unhandled instruction class");
145#define ENUM_ENTRY(n, r, d)   case n: return #n; break;
146  INSTRUCTION_CONTEXTS
147#undef ENUM_ENTRY
148  }
149}
150
151/// stringForOperandType - Like stringForContext, but for OperandTypes.
152static inline const char* stringForOperandType(OperandType type) {
153  switch (type) {
154  default:
155    llvm_unreachable("Unhandled type");
156#define ENUM_ENTRY(i, d) case i: return #i;
157  TYPES
158#undef ENUM_ENTRY
159  }
160}
161
162/// stringForOperandEncoding - like stringForContext, but for
163///   OperandEncodings.
164static inline const char* stringForOperandEncoding(OperandEncoding encoding) {
165  switch (encoding) {
166  default:
167    llvm_unreachable("Unhandled encoding");
168#define ENUM_ENTRY(i, d) case i: return #i;
169  ENCODINGS
170#undef ENUM_ENTRY
171  }
172}
173
174void DisassemblerTables::emitOneID(raw_ostream &o, unsigned &i, InstrUID id,
175                                   bool addComma) const {
176  if (id)
177    o.indent(i * 2) << format("0x%hx", id);
178  else
179    o.indent(i * 2) << 0;
180
181  if (addComma)
182    o << ", ";
183  else
184    o << "  ";
185
186  o << "/* ";
187  o << InstructionSpecifiers[id].name;
188  o << "*/";
189
190  o << "\n";
191}
192
193/// emitEmptyTable - Emits the modRMEmptyTable, which is used as a ID table by
194///   all ModR/M decisions for instructions that are invalid for all possible
195///   ModR/M byte values.
196///
197/// @param o        - The output stream on which to emit the table.
198/// @param i        - The indentation level for that output stream.
199static void emitEmptyTable(raw_ostream &o, unsigned &i) {
200  o.indent(i * 2) << "0x0, /* EmptyTable */\n";
201}
202
203/// getDecisionType - Determines whether a ModRM decision with 255 entries can
204///   be compacted by eliminating redundant information.
205///
206/// @param decision - The decision to be compacted.
207/// @return         - The compactest available representation for the decision.
208static ModRMDecisionType getDecisionType(ModRMDecision &decision) {
209  bool satisfiesOneEntry = true;
210  bool satisfiesSplitRM = true;
211  bool satisfiesSplitReg = 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      satisfiesSplitReg = false;
232  }
233
234  if (satisfiesOneEntry)
235    return MODRM_ONEENTRY;
236
237  if (satisfiesSplitRM)
238    return MODRM_SPLITRM;
239
240  if (satisfiesSplitReg)
241    return MODRM_SPLITREG;
242
243  return MODRM_FULL;
244}
245
246/// stringForDecisionType - Returns a statically-allocated string corresponding
247///   to a particular decision type.
248///
249/// @param dt - The decision type.
250/// @return   - A pointer to the statically-allocated string (e.g.,
251///             "MODRM_ONEENTRY" for MODRM_ONEENTRY).
252static const char* stringForDecisionType(ModRMDecisionType dt) {
253#define ENUM_ENTRY(n) case n: return #n;
254  switch (dt) {
255    default:
256      llvm_unreachable("Unknown decision type");
257    MODRMTYPES
258  };
259#undef ENUM_ENTRY
260}
261
262/// stringForModifierType - Returns a statically-allocated string corresponding
263///   to an opcode modifier type.
264///
265/// @param mt - The modifier type.
266/// @return   - A pointer to the statically-allocated string (e.g.,
267///             "MODIFIER_NONE" for MODIFIER_NONE).
268static const char* stringForModifierType(ModifierType mt) {
269#define ENUM_ENTRY(n) case n: return #n;
270  switch(mt) {
271    default:
272      llvm_unreachable("Unknown modifier type");
273    MODIFIER_TYPES
274  };
275#undef ENUM_ENTRY
276}
277
278DisassemblerTables::DisassemblerTables() {
279  unsigned i;
280
281  for (i = 0; i < array_lengthof(Tables); i++) {
282    Tables[i] = new ContextDecision;
283    memset(Tables[i], 0, sizeof(ContextDecision));
284  }
285
286  HasConflicts = false;
287}
288
289DisassemblerTables::~DisassemblerTables() {
290  unsigned i;
291
292  for (i = 0; i < array_lengthof(Tables); i++)
293    delete Tables[i];
294}
295
296void DisassemblerTables::emitModRMDecision(raw_ostream &o1, raw_ostream &o2,
297                                           unsigned &i1, unsigned &i2,
298                                           ModRMDecision &decision) const {
299  static uint32_t sTableNumber = 0;
300  static uint32_t sEntryNumber = 1;
301  ModRMDecisionType dt = getDecisionType(decision);
302
303  if (dt == MODRM_ONEENTRY && decision.instructionIDs[0] == 0)
304  {
305    o2.indent(i2) << "{ /* ModRMDecision */" << "\n";
306    i2++;
307
308    o2.indent(i2) << stringForDecisionType(dt) << "," << "\n";
309    o2.indent(i2) << 0 << " /* EmptyTable */\n";
310
311    i2--;
312    o2.indent(i2) << "}";
313    return;
314  }
315
316  o1 << "/* Table" << sTableNumber << " */\n";
317  i1++;
318
319  switch (dt) {
320    default:
321      llvm_unreachable("Unknown decision type");
322    case MODRM_ONEENTRY:
323      emitOneID(o1, i1, decision.instructionIDs[0], true);
324      break;
325    case MODRM_SPLITRM:
326      emitOneID(o1, i1, decision.instructionIDs[0x00], true); // mod = 0b00
327      emitOneID(o1, i1, decision.instructionIDs[0xc0], true); // mod = 0b11
328      break;
329    case MODRM_SPLITREG:
330      for (unsigned index = 0; index < 64; index += 8)
331        emitOneID(o1, i1, decision.instructionIDs[index], true);
332      for (unsigned index = 0xc0; index < 256; index += 8)
333        emitOneID(o1, i1, decision.instructionIDs[index], true);
334      break;
335    case MODRM_FULL:
336      for (unsigned index = 0; index < 256; ++index)
337        emitOneID(o1, i1, decision.instructionIDs[index], true);
338      break;
339  }
340
341  i1--;
342
343  o2.indent(i2) << "{ /* struct ModRMDecision */" << "\n";
344  i2++;
345
346  o2.indent(i2) << stringForDecisionType(dt) << "," << "\n";
347  o2.indent(i2) << sEntryNumber << " /* Table" << sTableNumber << " */\n";
348
349  i2--;
350  o2.indent(i2) << "}";
351
352  switch (dt) {
353    default:
354      llvm_unreachable("Unknown decision type");
355    case MODRM_ONEENTRY:
356      sEntryNumber += 1;
357      break;
358    case MODRM_SPLITRM:
359      sEntryNumber += 2;
360      break;
361    case MODRM_SPLITREG:
362      sEntryNumber += 16;
363      break;
364    case MODRM_FULL:
365      sEntryNumber += 256;
366      break;
367  }
368
369  ++sTableNumber;
370}
371
372void DisassemblerTables::emitOpcodeDecision(raw_ostream &o1, raw_ostream &o2,
373                                            unsigned &i1, unsigned &i2,
374                                            OpcodeDecision &decision) const {
375  o2.indent(i2) << "{ /* struct OpcodeDecision */" << "\n";
376  i2++;
377  o2.indent(i2) << "{" << "\n";
378  i2++;
379
380  for (unsigned index = 0; index < 256; ++index) {
381    o2.indent(i2);
382
383    o2 << "/* 0x" << format("%02hhx", index) << " */" << "\n";
384
385    emitModRMDecision(o1, o2, i1, i2, decision.modRMDecisions[index]);
386
387    if (index <  255)
388      o2 << ",";
389
390    o2 << "\n";
391  }
392
393  i2--;
394  o2.indent(i2) << "}" << "\n";
395  i2--;
396  o2.indent(i2) << "}" << "\n";
397}
398
399void DisassemblerTables::emitContextDecision(raw_ostream &o1, raw_ostream &o2,
400                                             unsigned &i1, unsigned &i2,
401                                             ContextDecision &decision,
402                                             const char* name) const {
403  o2.indent(i2) << "static const struct ContextDecision " << name << " = {\n";
404  i2++;
405  o2.indent(i2) << "{ /* opcodeDecisions */" << "\n";
406  i2++;
407
408  for (unsigned index = 0; index < IC_max; ++index) {
409    o2.indent(i2) << "/* ";
410    o2 << stringForContext((InstructionContext)index);
411    o2 << " */";
412    o2 << "\n";
413
414    emitOpcodeDecision(o1, o2, i1, i2, decision.opcodeDecisions[index]);
415
416    if (index + 1 < IC_max)
417      o2 << ", ";
418  }
419
420  i2--;
421  o2.indent(i2) << "}" << "\n";
422  i2--;
423  o2.indent(i2) << "};" << "\n";
424}
425
426void DisassemblerTables::emitInstructionInfo(raw_ostream &o,
427                                             unsigned &i) const {
428  unsigned NumInstructions = InstructionSpecifiers.size();
429
430  o << "static const struct OperandSpecifier x86OperandSets[]["
431    << X86_MAX_OPERANDS << "] = {\n";
432
433  typedef std::vector<std::pair<const char *, const char *> > OperandListTy;
434  std::map<OperandListTy, unsigned> OperandSets;
435
436  unsigned OperandSetNum = 0;
437  for (unsigned Index = 0; Index < NumInstructions; ++Index) {
438    OperandListTy OperandList;
439
440    for (unsigned OperandIndex = 0; OperandIndex < X86_MAX_OPERANDS;
441         ++OperandIndex) {
442      const char *Encoding =
443        stringForOperandEncoding((OperandEncoding)InstructionSpecifiers[Index]
444                                 .operands[OperandIndex].encoding);
445      const char *Type =
446        stringForOperandType((OperandType)InstructionSpecifiers[Index]
447                             .operands[OperandIndex].type);
448      OperandList.push_back(std::make_pair(Encoding, Type));
449    }
450    unsigned &N = OperandSets[OperandList];
451    if (N != 0) continue;
452
453    N = ++OperandSetNum;
454
455    o << "  { /* " << (OperandSetNum - 1) << " */\n";
456    for (unsigned i = 0, e = OperandList.size(); i != e; ++i) {
457      o << "    { " << OperandList[i].first << ", "
458        << OperandList[i].second << " },\n";
459    }
460    o << "  },\n";
461  }
462  o << "};" << "\n\n";
463
464  o.indent(i * 2) << "static const struct InstructionSpecifier ";
465  o << INSTRUCTIONS_STR "[" << InstructionSpecifiers.size() << "] = {\n";
466
467  i++;
468
469  for (unsigned index = 0; index < NumInstructions; ++index) {
470    o.indent(i * 2) << "{ /* " << index << " */" << "\n";
471    i++;
472
473    o.indent(i * 2) << stringForModifierType(
474                       (ModifierType)InstructionSpecifiers[index].modifierType);
475    o << ",\n";
476
477    o.indent(i * 2) << "0x";
478    o << format("%02hhx", (uint16_t)InstructionSpecifiers[index].modifierBase);
479    o << ",\n";
480
481    OperandListTy OperandList;
482    for (unsigned OperandIndex = 0; OperandIndex < X86_MAX_OPERANDS;
483         ++OperandIndex) {
484      const char *Encoding =
485        stringForOperandEncoding((OperandEncoding)InstructionSpecifiers[index]
486                                 .operands[OperandIndex].encoding);
487      const char *Type =
488        stringForOperandType((OperandType)InstructionSpecifiers[index]
489                             .operands[OperandIndex].type);
490      OperandList.push_back(std::make_pair(Encoding, Type));
491    }
492    o.indent(i * 2) << (OperandSets[OperandList] - 1) << ",\n";
493
494    o.indent(i * 2) << "/* " << InstructionSpecifiers[index].name << " */";
495    o << "\n";
496
497    i--;
498    o.indent(i * 2) << "}";
499
500    if (index + 1 < NumInstructions)
501      o << ",";
502
503    o << "\n";
504  }
505
506  i--;
507  o.indent(i * 2) << "};" << "\n";
508}
509
510void DisassemblerTables::emitContextTable(raw_ostream &o, unsigned &i) const {
511  o.indent(i * 2) << "static const uint8_t " CONTEXTS_STR
512                     "[256] = {\n";
513  i++;
514
515  for (unsigned index = 0; index < 256; ++index) {
516    o.indent(i * 2);
517
518    if ((index & ATTR_VEXL) && (index & ATTR_REXW) && (index & ATTR_OPSIZE))
519      o << "IC_VEX_L_W_OPSIZE";
520    else if ((index & ATTR_VEXL) && (index & ATTR_OPSIZE))
521      o << "IC_VEX_L_OPSIZE";
522    else if ((index & ATTR_VEXL) && (index & ATTR_XD))
523      o << "IC_VEX_L_XD";
524    else if ((index & ATTR_VEXL) && (index & ATTR_XS))
525      o << "IC_VEX_L_XS";
526    else if ((index & ATTR_VEX) && (index & ATTR_REXW) && (index & ATTR_OPSIZE))
527      o << "IC_VEX_W_OPSIZE";
528    else if ((index & ATTR_VEX) && (index & ATTR_REXW) && (index & ATTR_XD))
529      o << "IC_VEX_W_XD";
530    else if ((index & ATTR_VEX) && (index & ATTR_REXW) && (index & ATTR_XS))
531      o << "IC_VEX_W_XS";
532    else if (index & ATTR_VEXL)
533      o << "IC_VEX_L";
534    else if ((index & ATTR_VEX) && (index & ATTR_REXW))
535      o << "IC_VEX_W";
536    else if ((index & ATTR_VEX) && (index & ATTR_OPSIZE))
537      o << "IC_VEX_OPSIZE";
538    else if ((index & ATTR_VEX) && (index & ATTR_XD))
539      o << "IC_VEX_XD";
540    else if ((index & ATTR_VEX) && (index & ATTR_XS))
541      o << "IC_VEX_XS";
542    else if (index & ATTR_VEX)
543      o << "IC_VEX";
544    else if ((index & ATTR_64BIT) && (index & ATTR_REXW) && (index & ATTR_XS))
545      o << "IC_64BIT_REXW_XS";
546    else if ((index & ATTR_64BIT) && (index & ATTR_REXW) && (index & ATTR_XD))
547      o << "IC_64BIT_REXW_XD";
548    else if ((index & ATTR_64BIT) && (index & ATTR_REXW) &&
549             (index & ATTR_OPSIZE))
550      o << "IC_64BIT_REXW_OPSIZE";
551    else if ((index & ATTR_64BIT) && (index & ATTR_XD) && (index & ATTR_OPSIZE))
552      o << "IC_64BIT_XD_OPSIZE";
553    else if ((index & ATTR_64BIT) && (index & ATTR_XS) && (index & ATTR_OPSIZE))
554      o << "IC_64BIT_XS_OPSIZE";
555    else if ((index & ATTR_64BIT) && (index & ATTR_XS))
556      o << "IC_64BIT_XS";
557    else if ((index & ATTR_64BIT) && (index & ATTR_XD))
558      o << "IC_64BIT_XD";
559    else if ((index & ATTR_64BIT) && (index & ATTR_OPSIZE))
560      o << "IC_64BIT_OPSIZE";
561    else if ((index & ATTR_64BIT) && (index & ATTR_ADSIZE))
562      o << "IC_64BIT_ADSIZE";
563    else if ((index & ATTR_64BIT) && (index & ATTR_REXW))
564      o << "IC_64BIT_REXW";
565    else if ((index & ATTR_64BIT))
566      o << "IC_64BIT";
567    else if ((index & ATTR_XS) && (index & ATTR_OPSIZE))
568      o << "IC_XS_OPSIZE";
569    else if ((index & ATTR_XD) && (index & ATTR_OPSIZE))
570      o << "IC_XD_OPSIZE";
571    else if (index & ATTR_XS)
572      o << "IC_XS";
573    else if (index & ATTR_XD)
574      o << "IC_XD";
575    else if (index & ATTR_OPSIZE)
576      o << "IC_OPSIZE";
577    else if (index & ATTR_ADSIZE)
578      o << "IC_ADSIZE";
579    else
580      o << "IC";
581
582    if (index < 255)
583      o << ",";
584    else
585      o << " ";
586
587    o << " /* " << index << " */";
588
589    o << "\n";
590  }
591
592  i--;
593  o.indent(i * 2) << "};" << "\n";
594}
595
596void DisassemblerTables::emitContextDecisions(raw_ostream &o1, raw_ostream &o2,
597                                             unsigned &i1, unsigned &i2) const {
598  emitContextDecision(o1, o2, i1, i2, *Tables[0], ONEBYTE_STR);
599  emitContextDecision(o1, o2, i1, i2, *Tables[1], TWOBYTE_STR);
600  emitContextDecision(o1, o2, i1, i2, *Tables[2], THREEBYTE38_STR);
601  emitContextDecision(o1, o2, i1, i2, *Tables[3], THREEBYTE3A_STR);
602  emitContextDecision(o1, o2, i1, i2, *Tables[4], THREEBYTEA6_STR);
603  emitContextDecision(o1, o2, i1, i2, *Tables[5], THREEBYTEA7_STR);
604}
605
606void DisassemblerTables::emit(raw_ostream &o) const {
607  unsigned i1 = 0;
608  unsigned i2 = 0;
609
610  std::string s1;
611  std::string s2;
612
613  raw_string_ostream o1(s1);
614  raw_string_ostream o2(s2);
615
616  emitInstructionInfo(o, i2);
617  o << "\n";
618
619  emitContextTable(o, i2);
620  o << "\n";
621
622  o << "static const InstrUID modRMTable[] = {\n";
623  i1++;
624  emitEmptyTable(o1, i1);
625  i1--;
626  emitContextDecisions(o1, o2, i1, i2);
627
628  o << o1.str();
629  o << "  0x0\n";
630  o << "};\n";
631  o << "\n";
632  o << o2.str();
633  o << "\n";
634  o << "\n";
635}
636
637void DisassemblerTables::setTableFields(ModRMDecision     &decision,
638                                        const ModRMFilter &filter,
639                                        InstrUID          uid,
640                                        uint8_t           opcode) {
641  for (unsigned index = 0; index < 256; ++index) {
642    if (filter.accepts(index)) {
643      if (decision.instructionIDs[index] == uid)
644        continue;
645
646      if (decision.instructionIDs[index] != 0) {
647        InstructionSpecifier &newInfo =
648          InstructionSpecifiers[uid];
649        InstructionSpecifier &previousInfo =
650          InstructionSpecifiers[decision.instructionIDs[index]];
651
652        if(newInfo.filtered)
653          continue; // filtered instructions get lowest priority
654
655        if(previousInfo.name == "NOOP" && (newInfo.name == "XCHG16ar" ||
656                                           newInfo.name == "XCHG32ar" ||
657                                           newInfo.name == "XCHG32ar64" ||
658                                           newInfo.name == "XCHG64ar"))
659          continue; // special case for XCHG*ar and NOOP
660
661        if (outranks(previousInfo.insnContext, newInfo.insnContext))
662          continue;
663
664        if (previousInfo.insnContext == newInfo.insnContext &&
665            !previousInfo.filtered) {
666          errs() << "Error: Primary decode conflict: ";
667          errs() << newInfo.name << " would overwrite " << previousInfo.name;
668          errs() << "\n";
669          errs() << "ModRM   " << index << "\n";
670          errs() << "Opcode  " << (uint16_t)opcode << "\n";
671          errs() << "Context " << stringForContext(newInfo.insnContext) << "\n";
672          HasConflicts = true;
673        }
674      }
675
676      decision.instructionIDs[index] = uid;
677    }
678  }
679}
680
681void DisassemblerTables::setTableFields(OpcodeType          type,
682                                        InstructionContext  insnContext,
683                                        uint8_t             opcode,
684                                        const ModRMFilter   &filter,
685                                        InstrUID            uid,
686                                        bool                is32bit,
687                                        bool                ignoresVEX_L) {
688  ContextDecision &decision = *Tables[type];
689
690  for (unsigned index = 0; index < IC_max; ++index) {
691    if (is32bit && inheritsFrom((InstructionContext)index, IC_64BIT))
692      continue;
693
694    if (inheritsFrom((InstructionContext)index,
695                     InstructionSpecifiers[uid].insnContext, ignoresVEX_L))
696      setTableFields(decision.opcodeDecisions[index].modRMDecisions[opcode],
697                     filter,
698                     uid,
699                     opcode);
700  }
701}
702