//===- X86DisassemblerTables.h - Disassembler tables ------------*- C++ -*-===// // // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. // See https://llvm.org/LICENSE.txt for license information. // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception // //===----------------------------------------------------------------------===// // // This file is part of the X86 Disassembler Emitter. // It contains the interface of the disassembler tables. // Documentation for the disassembler emitter in general can be found in // X86DisassemblerEmitter.h. // //===----------------------------------------------------------------------===// #ifndef LLVM_UTILS_TABLEGEN_X86DISASSEMBLERTABLES_H #define LLVM_UTILS_TABLEGEN_X86DISASSEMBLERTABLES_H #include "X86DisassemblerShared.h" #include "llvm/Support/X86DisassemblerDecoderCommon.h" #include #include #include namespace llvm { class raw_ostream; namespace X86Disassembler { class ModRMFilter; /// DisassemblerTables - Encapsulates all the decode tables being generated by /// the table emitter. Contains functions to populate the tables as well as /// to emit them as hierarchical C structures suitable for consumption by the /// runtime. class DisassemblerTables { private: /// The decoder tables. There is one for each opcode type: /// [0] one-byte opcodes /// [1] two-byte opcodes of the form 0f __ /// [2] three-byte opcodes of the form 0f 38 __ /// [3] three-byte opcodes of the form 0f 3a __ /// [4] XOP8 map opcode /// [5] XOP9 map opcode /// [6] XOPA map opcode /// [7] 3dnow map opcode /// [8] fixed length MAP5 opcode /// [9] fixed length MAP6 opcode std::unique_ptr Tables[10]; // Table of ModRM encodings. typedef std::map, unsigned> ModRMMapTy; mutable ModRMMapTy ModRMTable; /// The instruction information table std::vector InstructionSpecifiers; /// True if there are primary decode conflicts in the instruction set bool HasConflicts; /// emitModRMDecision - Emits a table of entries corresponding to a single /// ModR/M decision. Compacts the ModR/M decision if possible. ModR/M /// decisions are printed as: /// /// { /* struct ModRMDecision */ /// TYPE, /// modRMTablennnn /// } /// /// where nnnn is a unique ID for the corresponding table of IDs. /// TYPE indicates whether the table has one entry that is the same /// regardless of ModR/M byte, two entries - one for bytes 0x00-0xbf and one /// for bytes 0xc0-0xff -, or 256 entries, one for each possible byte. /// nnnn is the number of a table for looking up these values. The tables /// are written separately so that tables consisting entirely of zeros will /// not be duplicated. (These all have the name modRMEmptyTable.) A table /// is printed as: /// /// InstrUID modRMTablennnn[k] = { /// nnnn, /* MNEMONIC */ /// ... /// nnnn /* MNEMONIC */ /// }; /// /// @param o1 - The output stream to print the ID table to. /// @param o2 - The output stream to print the decision structure to. /// @param i1 - The indentation level to use with stream o1. /// @param i2 - The indentation level to use with stream o2. /// @param ModRMTableNum - next table number for adding to ModRMTable. /// @param decision - The ModR/M decision to emit. This decision has 256 /// entries - emitModRMDecision decides how to compact it. void emitModRMDecision(raw_ostream &o1, raw_ostream &o2, unsigned &i1, unsigned &i2, unsigned &ModRMTableNum, ModRMDecision &decision) const; /// emitOpcodeDecision - Emits an OpcodeDecision and all its subsidiary ModR/M /// decisions. An OpcodeDecision is printed as: /// /// { /* struct OpcodeDecision */ /// /* 0x00 */ /// { /* struct ModRMDecision */ /// ... /// } /// ... /// } /// /// where the ModRMDecision structure is printed as described in the /// documentation for emitModRMDecision(). emitOpcodeDecision() passes on a /// stream and indent level for the UID tables generated by /// emitModRMDecision(), but does not use them itself. /// /// @param o1 - The output stream to print the ID tables generated by /// emitModRMDecision() to. /// @param o2 - The output stream for the decision structure itself. /// @param i1 - The indent level to use with stream o1. /// @param i2 - The indent level to use with stream o2. /// @param ModRMTableNum - next table number for adding to ModRMTable. /// @param decision - The OpcodeDecision to emit along with its subsidiary /// structures. void emitOpcodeDecision(raw_ostream &o1, raw_ostream &o2, unsigned &i1, unsigned &i2, unsigned &ModRMTableNum, OpcodeDecision &decision) const; /// emitContextDecision - Emits a ContextDecision and all its subsidiary /// Opcode and ModRMDecisions. A ContextDecision is printed as: /// /// struct ContextDecision NAME = { /// { /* OpcodeDecisions */ /// /* IC */ /// { /* struct OpcodeDecision */ /// ... /// }, /// ... /// } /// } /// /// NAME is the name of the ContextDecision (typically one of the four names /// ONEBYTE_SYM, TWOBYTE_SYM, THREEBYTE38_SYM, THREEBYTE3A_SYM from /// X86DisassemblerDecoderCommon.h). /// IC is one of the contexts in InstructionContext. There is an opcode /// decision for each possible context. /// The OpcodeDecision structures are printed as described in the /// documentation for emitOpcodeDecision. /// /// @param o1 - The output stream to print the ID tables generated by /// emitModRMDecision() to. /// @param o2 - The output stream to print the decision structure to. /// @param i1 - The indent level to use with stream o1. /// @param i2 - The indent level to use with stream o2. /// @param ModRMTableNum - next table number for adding to ModRMTable. /// @param decision - The ContextDecision to emit along with its subsidiary /// structures. /// @param name - The name for the ContextDecision. void emitContextDecision(raw_ostream &o1, raw_ostream &o2, unsigned &i1, unsigned &i2, unsigned &ModRMTableNum, ContextDecision &decision, const char* name) const; /// emitInstructionInfo - Prints the instruction specifier table, which has /// one entry for each instruction, and contains name and operand /// information. This table is printed as: /// /// struct InstructionSpecifier CONTEXTS_SYM[k] = { /// { /// /* nnnn */ /// "MNEMONIC", /// 0xnn, /// { /// { /// ENCODING, /// TYPE /// }, /// ... /// } /// }, /// }; /// /// k is the total number of instructions. /// nnnn is the ID of the current instruction (0-based). This table /// includes entries for non-instructions like PHINODE. /// 0xnn is the lowest possible opcode for the current instruction, used for /// AddRegFrm instructions to compute the operand's value. /// ENCODING and TYPE describe the encoding and type for a single operand. /// /// @param o - The output stream to which the instruction table should be /// written. /// @param i - The indent level for use with the stream. void emitInstructionInfo(raw_ostream &o, unsigned &i) const; /// emitContextTable - Prints the table that is used to translate from an /// instruction attribute mask to an instruction context. This table is /// printed as: /// /// InstructionContext CONTEXTS_STR[256] = { /// IC, /* 0x00 */ /// ... /// }; /// /// IC is the context corresponding to the mask 0x00, and there are 256 /// possible masks. /// /// @param o - The output stream to which the context table should be written. /// @param i - The indent level for use with the stream. void emitContextTable(raw_ostream &o, uint32_t &i) const; /// emitContextDecisions - Prints all four ContextDecision structures using /// emitContextDecision(). /// /// @param o1 - The output stream to print the ID tables generated by /// emitModRMDecision() to. /// @param o2 - The output stream to print the decision structures to. /// @param i1 - The indent level to use with stream o1. /// @param i2 - The indent level to use with stream o2. /// @param ModRMTableNum - next table number for adding to ModRMTable. void emitContextDecisions(raw_ostream &o1, raw_ostream &o2, unsigned &i1, unsigned &i2, unsigned &ModRMTableNum) const; /// setTableFields - Uses a ModRMFilter to set the appropriate entries in a /// ModRMDecision to refer to a particular instruction ID. /// /// @param decision - The ModRMDecision to populate. /// @param filter - The filter to use in deciding which entries to populate. /// @param uid - The unique ID to set matching entries to. /// @param opcode - The opcode of the instruction, for error reporting. void setTableFields(ModRMDecision &decision, const ModRMFilter &filter, InstrUID uid, uint8_t opcode); public: /// Constructor - Allocates space for the class decisions and clears them. DisassemblerTables(); ~DisassemblerTables(); /// emit - Emits the instruction table, context table, and class decisions. /// /// @param o - The output stream to print the tables to. void emit(raw_ostream &o) const; /// setTableFields - Uses the opcode type, instruction context, opcode, and a /// ModRMFilter as criteria to set a particular set of entries in the /// decode tables to point to a specific uid. /// /// @param type - The opcode type (ONEBYTE, TWOBYTE, etc.) /// @param insnContext - The context to use (IC, IC_64BIT, etc.) /// @param opcode - The last byte of the opcode (not counting any escape /// or extended opcodes). /// @param filter - The ModRMFilter that decides which ModR/M byte values /// correspond to the desired instruction. /// @param uid - The unique ID of the instruction. /// @param is32bit - Instructon is only 32-bit /// @param noPrefix - Instruction record has no prefix. /// @param ignoresVEX_L - Instruction ignores VEX.L /// @param ignoresVEX_W - Instruction ignores VEX.W /// @param AddrSize - Instructions address size 16/32/64. 0 is unspecified void setTableFields(OpcodeType type, InstructionContext insnContext, uint8_t opcode, const ModRMFilter &filter, InstrUID uid, bool is32bit, bool noPrefix, bool ignoresVEX_L, bool ignoresVEX_W, unsigned AddrSize); /// specForUID - Returns the instruction specifier for a given unique /// instruction ID. Used when resolving collisions. /// /// @param uid - The unique ID of the instruction. /// @return - A reference to the instruction specifier. InstructionSpecifier& specForUID(InstrUID uid) { if (uid >= InstructionSpecifiers.size()) InstructionSpecifiers.resize(uid + 1); return InstructionSpecifiers[uid]; } // hasConflicts - Reports whether there were primary decode conflicts // from any instructions added to the tables. // @return - true if there were; false otherwise. bool hasConflicts() { return HasConflicts; } }; } // namespace X86Disassembler } // namespace llvm #endif