void DisassemblerTables::emitInstructionInfo(raw_ostream &o,
        unsigned &i) const {
    unsigned NumInstructions = InstructionSpecifiers.size();

    o << "static const struct OperandSpecifier x86OperandSets[]["
      << X86_MAX_OPERANDS << "] = {\n";

    typedef SmallVector<std::pair<OperandEncoding, OperandType>,
            X86_MAX_OPERANDS> OperandListTy;
    std::map<OperandListTy, unsigned> OperandSets;

    unsigned OperandSetNum = 0;
    for (unsigned Index = 0; Index < NumInstructions; ++Index) {
        OperandListTy OperandList;

        for (unsigned OperandIndex = 0; OperandIndex < X86_MAX_OPERANDS;
                ++OperandIndex) {
            OperandEncoding Encoding = (OperandEncoding)InstructionSpecifiers[Index]
                                       .operands[OperandIndex].encoding;
            OperandType Type = (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) {
            const char *Encoding = stringForOperandEncoding(OperandList[i].first);
            const char *Type     = stringForOperandType(OperandList[i].second);
            o << "    { " << Encoding << ", " << Type << " },\n";
        }
        o << "  },\n";
    }
    o << "};" << "\n\n";

    o.indent(i * 2) << "static const struct InstructionSpecifier ";
    o << INSTRUCTIONS_STR "[" << InstructionSpecifiers.size() << "] = {\n";

    i++;

    for (unsigned index = 0; index < NumInstructions; ++index) {
        o.indent(i * 2) << "{ /* " << index << " */\n";
        i++;

        OperandListTy OperandList;
        for (unsigned OperandIndex = 0; OperandIndex < X86_MAX_OPERANDS;
                ++OperandIndex) {
            OperandEncoding Encoding = (OperandEncoding)InstructionSpecifiers[index]
                                       .operands[OperandIndex].encoding;
            OperandType Type = (OperandType)InstructionSpecifiers[index]
                               .operands[OperandIndex].type;
            OperandList.push_back(std::make_pair(Encoding, Type));
        }
        o.indent(i * 2) << (OperandSets[OperandList] - 1) << ",\n";

        o.indent(i * 2) << "/* " << InstructionSpecifiers[index].name << " */\n";

        i--;
        o.indent(i * 2) << "},\n";
    }

    i--;
    o.indent(i * 2) << "};" << "\n";
}
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<std::pair<const char *, const char *> > OperandListTy;
  std::map<OperandListTy, unsigned> 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++;

  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.indent(i * 2) << "0x";
    o << format("%02hhx", (uint16_t)InstructionSpecifiers[index].modifierBase);
    o << ",\n";

    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));
    }
    o.indent(i * 2) << (OperandSets[OperandList] - 1) << ",\n";

    o.indent(i * 2) << "/* " << InstructionSpecifiers[index].name << " */";
    o << "\n";

    i--;
    o.indent(i * 2) << "}";

    if (index + 1 < NumInstructions)
      o << ",";

    o << "\n";
  }

  i--;
  o.indent(i * 2) << "};" << "\n";
}