123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292 |
- //===- 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 <map>
- #include <memory>
- #include <vector>
- 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<ContextDecision> Tables[10];
- // Table of ModRM encodings.
- typedef std::map<std::vector<unsigned>, unsigned> ModRMMapTy;
- mutable ModRMMapTy ModRMTable;
- /// The instruction information table
- std::vector<InstructionSpecifier> 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
|