401 lines · c
1//===- X86RecognizableInstr.h - Disassembler instruction spec ---*- C++ -*-===//2//3// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.4// See https://llvm.org/LICENSE.txt for license information.5// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception6//7//===----------------------------------------------------------------------===//8//9// This file is part of the X86 Disassembler Emitter.10// It contains the interface of a single recognizable instruction.11// Documentation for the disassembler emitter in general can be found in12// X86DisassemblerEmitter.h.13//14//===----------------------------------------------------------------------===//15 16#ifndef LLVM_UTILS_TABLEGEN_X86RECOGNIZABLEINSTR_H17#define LLVM_UTILS_TABLEGEN_X86RECOGNIZABLEINSTR_H18 19#include "Common/CodeGenInstruction.h"20#include "llvm/Support/X86DisassemblerDecoderCommon.h"21#include <cstdint>22#include <string>23#include <vector>24 25namespace llvm {26class Record;27#define X86_INSTR_MRM_MAPPING \28 MAP(C0, 64) \29 MAP(C1, 65) \30 MAP(C2, 66) \31 MAP(C3, 67) \32 MAP(C4, 68) \33 MAP(C5, 69) \34 MAP(C6, 70) \35 MAP(C7, 71) \36 MAP(C8, 72) \37 MAP(C9, 73) \38 MAP(CA, 74) \39 MAP(CB, 75) \40 MAP(CC, 76) \41 MAP(CD, 77) \42 MAP(CE, 78) \43 MAP(CF, 79) \44 MAP(D0, 80) \45 MAP(D1, 81) \46 MAP(D2, 82) \47 MAP(D3, 83) \48 MAP(D4, 84) \49 MAP(D5, 85) \50 MAP(D6, 86) \51 MAP(D7, 87) \52 MAP(D8, 88) \53 MAP(D9, 89) \54 MAP(DA, 90) \55 MAP(DB, 91) \56 MAP(DC, 92) \57 MAP(DD, 93) \58 MAP(DE, 94) \59 MAP(DF, 95) \60 MAP(E0, 96) \61 MAP(E1, 97) \62 MAP(E2, 98) \63 MAP(E3, 99) \64 MAP(E4, 100) \65 MAP(E5, 101) \66 MAP(E6, 102) \67 MAP(E7, 103) \68 MAP(E8, 104) \69 MAP(E9, 105) \70 MAP(EA, 106) \71 MAP(EB, 107) \72 MAP(EC, 108) \73 MAP(ED, 109) \74 MAP(EE, 110) \75 MAP(EF, 111) \76 MAP(F0, 112) \77 MAP(F1, 113) \78 MAP(F2, 114) \79 MAP(F3, 115) \80 MAP(F4, 116) \81 MAP(F5, 117) \82 MAP(F6, 118) \83 MAP(F7, 119) \84 MAP(F8, 120) \85 MAP(F9, 121) \86 MAP(FA, 122) \87 MAP(FB, 123) \88 MAP(FC, 124) \89 MAP(FD, 125) \90 MAP(FE, 126) \91 MAP(FF, 127)92 93// A clone of X86 since we can't depend on something that is generated.94namespace X86Local {95enum {96 Pseudo = 0,97 RawFrm = 1,98 AddRegFrm = 2,99 RawFrmMemOffs = 3,100 RawFrmSrc = 4,101 RawFrmDst = 5,102 RawFrmDstSrc = 6,103 RawFrmImm8 = 7,104 RawFrmImm16 = 8,105 AddCCFrm = 9,106 PrefixByte = 10,107 MRMDestRegCC = 18,108 MRMDestMemCC = 19,109 MRMDestMem4VOp3CC = 20,110 MRMr0 = 21,111 MRMSrcMemFSIB = 22,112 MRMDestMemFSIB = 23,113 MRMDestMem = 24,114 MRMSrcMem = 25,115 MRMSrcMem4VOp3 = 26,116 MRMSrcMemOp4 = 27,117 MRMSrcMemCC = 28,118 MRMXmCC = 30,119 MRMXm = 31,120 MRM0m = 32,121 MRM1m = 33,122 MRM2m = 34,123 MRM3m = 35,124 MRM4m = 36,125 MRM5m = 37,126 MRM6m = 38,127 MRM7m = 39,128 MRMDestReg = 40,129 MRMSrcReg = 41,130 MRMSrcReg4VOp3 = 42,131 MRMSrcRegOp4 = 43,132 MRMSrcRegCC = 44,133 MRMXrCC = 46,134 MRMXr = 47,135 MRM0r = 48,136 MRM1r = 49,137 MRM2r = 50,138 MRM3r = 51,139 MRM4r = 52,140 MRM5r = 53,141 MRM6r = 54,142 MRM7r = 55,143 MRM0X = 56,144 MRM1X = 57,145 MRM2X = 58,146 MRM3X = 59,147 MRM4X = 60,148 MRM5X = 61,149 MRM6X = 62,150 MRM7X = 63,151#define MAP(from, to) MRM_##from = to,152 X86_INSTR_MRM_MAPPING153#undef MAP154};155 156enum {157 OB = 0,158 TB = 1,159 T8 = 2,160 TA = 3,161 XOP8 = 4,162 XOP9 = 5,163 XOPA = 6,164 ThreeDNow = 7,165 T_MAP4 = 8,166 T_MAP5 = 9,167 T_MAP6 = 10,168 T_MAP7 = 11169};170 171enum { PD = 1, XS = 2, XD = 3, PS = 4 };172enum { VEX = 1, XOP = 2, EVEX = 3 };173enum { OpSize16 = 1, OpSize32 = 2 };174enum { AdSize16 = 1, AdSize32 = 2, AdSize64 = 3 };175enum { ExplicitREX2 = 1, ExplicitEVEX = 3 };176} // namespace X86Local177 178namespace X86Disassembler {179class DisassemblerTables;180struct InstructionSpecifier;181 182/// Extract common fields of a single X86 instruction from a CodeGenInstruction183struct RecognizableInstrBase {184 /// The OpPrefix field from the record185 uint8_t OpPrefix;186 /// The OpMap field from the record187 uint8_t OpMap;188 /// The opcode field from the record; this is the opcode used in the Intel189 /// encoding and therefore distinct from the UID190 uint8_t Opcode;191 /// The form field from the record192 uint8_t Form;193 // The encoding field from the record194 uint8_t Encoding;195 /// The OpSize field from the record196 uint8_t OpSize;197 /// The AdSize field from the record198 uint8_t AdSize;199 /// The hasREX_W field from the record200 bool HasREX_W;201 /// The hasVEX_4V field from the record202 bool HasVEX_4V;203 /// The IgnoresW field from the record204 bool IgnoresW;205 /// The hasVEX_L field from the record206 bool HasVEX_L;207 /// The ignoreVEX_L field from the record208 bool IgnoresVEX_L;209 /// The hasEVEX_L2Prefix field from the record210 bool HasEVEX_L2;211 /// The hasEVEX_K field from the record212 bool HasEVEX_K;213 /// The hasEVEX_KZ field from the record214 bool HasEVEX_KZ;215 /// The hasEVEX_B field from the record216 bool HasEVEX_B;217 /// The hasEVEX_U field from the record218 bool HasEVEX_U;219 /// The hasEVEX_NF field from the record220 bool HasEVEX_NF;221 /// The hasTwoConditionalOps field from the record222 bool HasTwoConditionalOps;223 /// Indicates that the instruction uses the L and L' fields for RC.224 bool EncodeRC;225 /// The isCodeGenOnly field from the record226 bool IsCodeGenOnly;227 /// The isAsmParserOnly field from the record228 bool IsAsmParserOnly;229 /// The ForceDisassemble field from the record230 bool ForceDisassemble;231 // The CD8_Scale field from the record232 uint8_t CD8_Scale;233 /// If explicitOpPrefix field from the record equals ExplicitREX2234 bool ExplicitREX2Prefix;235 /// \param insn The CodeGenInstruction to extract information from.236 RecognizableInstrBase(const CodeGenInstruction &insn);237 /// \returns true if this instruction should be emitted238 bool shouldBeEmitted() const;239};240 241/// RecognizableInstr - Encapsulates all information required to decode a single242/// instruction, as extracted from the LLVM instruction tables. Has methods243/// to interpret the information available in the LLVM tables, and to emit the244/// instruction into DisassemblerTables.245class RecognizableInstr : public RecognizableInstrBase {246private:247 /// The record from the .td files corresponding to this instruction248 const Record *Rec;249 /// The instruction name as listed in the tables250 std::string Name;251 // Whether the instruction has the predicate "In32BitMode"252 bool Is32Bit;253 // Whether the instruction has the predicate "In64BitMode"254 bool Is64Bit;255 /// The operands of the instruction, as listed in the CodeGenInstruction.256 /// They are not one-to-one with operands listed in the MCInst; for example,257 /// memory operands expand to 5 operands in the MCInst258 const std::vector<CGIOperandList::OperandInfo> *Operands;259 260 /// The opcode of the instruction, as used in an MCInst261 InstrUID UID;262 /// The description of the instruction that is emitted into the instruction263 /// info table264 InstructionSpecifier *Spec;265 266 /// insnContext - Returns the primary context in which the instruction is267 /// valid.268 ///269 /// @return - The context in which the instruction is valid.270 InstructionContext insnContext() const;271 272 /// typeFromString - Translates an operand type from the string provided in273 /// the LLVM tables to an OperandType for use in the operand specifier.274 ///275 /// @param s - The string, as extracted by calling Rec->getName()276 /// on a CodeGenInstruction::OperandInfo.277 /// @param hasREX_W - Indicates whether the instruction has a REX.W278 /// prefix. If it does, 32-bit register operands stay279 /// 32-bit regardless of the operand size.280 /// @param OpSize Indicates the operand size of the instruction.281 /// If register size does not match OpSize, then282 /// register sizes keep their size.283 /// @return - The operand's type.284 static OperandType typeFromString(StringRef Str, bool hasREX_W,285 uint8_t OpSize);286 287 /// immediateEncodingFromString - Translates an immediate encoding from the288 /// string provided in the LLVM tables to an OperandEncoding for use in289 /// the operand specifier.290 ///291 /// @param s - See typeFromString().292 /// @param OpSize - Indicates whether this is an OpSize16 instruction.293 /// If it is not, then 16-bit immediate operands stay 16-bit.294 /// @return - The operand's encoding.295 static OperandEncoding immediateEncodingFromString(StringRef Str,296 uint8_t OpSize);297 298 /// rmRegisterEncodingFromString - Like immediateEncodingFromString, but299 /// handles operands that are in the REG field of the ModR/M byte.300 static OperandEncoding rmRegisterEncodingFromString(StringRef Str,301 uint8_t OpSize);302 303 /// rmRegisterEncodingFromString - Like immediateEncodingFromString, but304 /// handles operands that are in the REG field of the ModR/M byte.305 static OperandEncoding roRegisterEncodingFromString(StringRef Str,306 uint8_t OpSize);307 static OperandEncoding memoryEncodingFromString(StringRef Str,308 uint8_t OpSize);309 static OperandEncoding relocationEncodingFromString(StringRef Str,310 uint8_t OpSize);311 static OperandEncoding opcodeModifierEncodingFromString(StringRef Str,312 uint8_t OpSize);313 static OperandEncoding vvvvRegisterEncodingFromString(StringRef Str,314 uint8_t OpSize);315 static OperandEncoding writemaskRegisterEncodingFromString(StringRef Str,316 uint8_t OpSize);317 318 /// Adjust the encoding type for an operand based on the instruction.319 void adjustOperandEncoding(OperandEncoding &encoding);320 321 /// handleOperand - Converts a single operand from the LLVM table format to322 /// the emitted table format, handling any duplicate operands it encounters323 /// and then one non-duplicate.324 ///325 /// @param optional - Determines whether to assert that the326 /// operand exists.327 /// @param operandIndex - The index into the generated operand table.328 /// Incremented by this function one or more329 /// times to reflect possible duplicate330 /// operands).331 /// @param physicalOperandIndex - The index of the current operand into the332 /// set of non-duplicate ('physical') operands.333 /// Incremented by this function once.334 /// @param numPhysicalOperands - The number of non-duplicate operands in the335 /// instructions.336 /// @param operandMapping - The operand mapping, which has an entry for337 /// each operand that indicates whether it is a338 /// duplicate, and of what.339 using EncodingFn =340 llvm::function_ref<OperandEncoding(StringRef s, uint8_t OpSize)>;341 void handleOperand(bool optional, unsigned &operandIndex,342 unsigned &physicalOperandIndex,343 unsigned numPhysicalOperands,344 const unsigned *operandMapping,345 EncodingFn encodingFromString);346 347 /// emitInstructionSpecifier - Loads the instruction specifier for the current348 /// instruction into a DisassemblerTables.349 ///350 void emitInstructionSpecifier();351 352 /// emitDecodePath - Populates the proper fields in the decode tables353 /// corresponding to the decode paths for this instruction.354 ///355 /// \param tables The DisassemblerTables to populate with the decode356 /// decode information for the current instruction.357 void emitDecodePath(DisassemblerTables &tables) const;358 359public:360 /// Constructor - Initializes a RecognizableInstr with the appropriate fields361 /// from a CodeGenInstruction.362 ///363 /// \param tables The DisassemblerTables that the specifier will be added to.364 /// \param insn The CodeGenInstruction to extract information from.365 /// \param uid The unique ID of the current instruction.366 RecognizableInstr(DisassemblerTables &tables, const CodeGenInstruction &insn,367 InstrUID uid);368 /// processInstr - Accepts a CodeGenInstruction and loads decode information369 /// for it into a DisassemblerTables if appropriate.370 ///371 /// \param tables The DiassemblerTables to be populated with decode372 /// information.373 /// \param insn The CodeGenInstruction to be used as a source for this374 /// information.375 /// \param uid The unique ID of the instruction.376 static void processInstr(DisassemblerTables &tables,377 const CodeGenInstruction &insn, InstrUID uid);378};379 380std::string getMnemonic(const CodeGenInstruction *I, unsigned Variant);381bool isRegisterOperand(const Record *Rec);382bool isMemoryOperand(const Record *Rec);383bool isImmediateOperand(const Record *Rec);384unsigned getRegOperandSize(const Record *RegRec);385unsigned getMemOperandSize(const Record *MemRec);386 387/// byteFromBitsInit - Extracts a value at most 8 bits in width from a BitsInit.388/// Useful for switch statements and the like.389///390/// @param B - A pointer to the BitsInit to be decoded.391/// @return - The field, with the first bit in the BitsInit as the lowest392/// order bit.393inline uint8_t byteFromBitsInit(const BitsInit *B) {394 assert(B->getNumBits() <= 8 && "Field is too large for uint8_t!");395 return static_cast<uint8_t>(*B->convertInitializerToInt());396}397 398} // namespace X86Disassembler399} // namespace llvm400#endif401