1201360Srdivacky//===- X86RecognizableInstr.h - Disassembler instruction spec ----*- C++ -*-===// 2201360Srdivacky// 3353358Sdim// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. 4353358Sdim// See https://llvm.org/LICENSE.txt for license information. 5353358Sdim// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception 6201360Srdivacky// 7201360Srdivacky//===----------------------------------------------------------------------===// 8201360Srdivacky// 9201360Srdivacky// This file is part of the X86 Disassembler Emitter. 10201360Srdivacky// It contains the interface of a single recognizable instruction. 11201360Srdivacky// Documentation for the disassembler emitter in general can be found in 12321369Sdim// X86DisassemblerEmitter.h. 13201360Srdivacky// 14201360Srdivacky//===----------------------------------------------------------------------===// 15201360Srdivacky 16280031Sdim#ifndef LLVM_UTILS_TABLEGEN_X86RECOGNIZABLEINSTR_H 17280031Sdim#define LLVM_UTILS_TABLEGEN_X86RECOGNIZABLEINSTR_H 18201360Srdivacky 19249423Sdim#include "CodeGenTarget.h" 20201360Srdivacky#include "X86DisassemblerTables.h" 21249423Sdim#include "llvm/Support/DataTypes.h" 22226633Sdim#include "llvm/TableGen/Record.h" 23201360Srdivacky 24201360Srdivackynamespace llvm { 25201360Srdivacky 26321369Sdim#define X86_INSTR_MRM_MAPPING \ 27321369Sdim MAP(C0, 64) \ 28321369Sdim MAP(C1, 65) \ 29321369Sdim MAP(C2, 66) \ 30321369Sdim MAP(C3, 67) \ 31321369Sdim MAP(C4, 68) \ 32321369Sdim MAP(C5, 69) \ 33321369Sdim MAP(C6, 70) \ 34321369Sdim MAP(C7, 71) \ 35321369Sdim MAP(C8, 72) \ 36321369Sdim MAP(C9, 73) \ 37321369Sdim MAP(CA, 74) \ 38321369Sdim MAP(CB, 75) \ 39321369Sdim MAP(CC, 76) \ 40321369Sdim MAP(CD, 77) \ 41321369Sdim MAP(CE, 78) \ 42321369Sdim MAP(CF, 79) \ 43321369Sdim MAP(D0, 80) \ 44321369Sdim MAP(D1, 81) \ 45321369Sdim MAP(D2, 82) \ 46321369Sdim MAP(D3, 83) \ 47321369Sdim MAP(D4, 84) \ 48321369Sdim MAP(D5, 85) \ 49321369Sdim MAP(D6, 86) \ 50321369Sdim MAP(D7, 87) \ 51321369Sdim MAP(D8, 88) \ 52321369Sdim MAP(D9, 89) \ 53321369Sdim MAP(DA, 90) \ 54321369Sdim MAP(DB, 91) \ 55321369Sdim MAP(DC, 92) \ 56321369Sdim MAP(DD, 93) \ 57321369Sdim MAP(DE, 94) \ 58321369Sdim MAP(DF, 95) \ 59321369Sdim MAP(E0, 96) \ 60321369Sdim MAP(E1, 97) \ 61321369Sdim MAP(E2, 98) \ 62321369Sdim MAP(E3, 99) \ 63321369Sdim MAP(E4, 100) \ 64321369Sdim MAP(E5, 101) \ 65321369Sdim MAP(E6, 102) \ 66321369Sdim MAP(E7, 103) \ 67321369Sdim MAP(E8, 104) \ 68321369Sdim MAP(E9, 105) \ 69321369Sdim MAP(EA, 106) \ 70321369Sdim MAP(EB, 107) \ 71321369Sdim MAP(EC, 108) \ 72321369Sdim MAP(ED, 109) \ 73321369Sdim MAP(EE, 110) \ 74321369Sdim MAP(EF, 111) \ 75321369Sdim MAP(F0, 112) \ 76321369Sdim MAP(F1, 113) \ 77321369Sdim MAP(F2, 114) \ 78321369Sdim MAP(F3, 115) \ 79321369Sdim MAP(F4, 116) \ 80321369Sdim MAP(F5, 117) \ 81321369Sdim MAP(F6, 118) \ 82321369Sdim MAP(F7, 119) \ 83321369Sdim MAP(F8, 120) \ 84321369Sdim MAP(F9, 121) \ 85321369Sdim MAP(FA, 122) \ 86321369Sdim MAP(FB, 123) \ 87321369Sdim MAP(FC, 124) \ 88321369Sdim MAP(FD, 125) \ 89321369Sdim MAP(FE, 126) \ 90321369Sdim MAP(FF, 127) 91321369Sdim 92321369Sdim// A clone of X86 since we can't depend on something that is generated. 93321369Sdimnamespace X86Local { 94321369Sdim enum { 95321369Sdim Pseudo = 0, 96321369Sdim RawFrm = 1, 97321369Sdim AddRegFrm = 2, 98321369Sdim RawFrmMemOffs = 3, 99321369Sdim RawFrmSrc = 4, 100321369Sdim RawFrmDst = 5, 101321369Sdim RawFrmDstSrc = 6, 102321369Sdim RawFrmImm8 = 7, 103321369Sdim RawFrmImm16 = 8, 104353358Sdim AddCCFrm = 9, 105321369Sdim MRMDestMem = 32, 106321369Sdim MRMSrcMem = 33, 107321369Sdim MRMSrcMem4VOp3 = 34, 108321369Sdim MRMSrcMemOp4 = 35, 109353358Sdim MRMSrcMemCC = 36, 110353358Sdim MRMXmCC = 38, MRMXm = 39, 111321369Sdim MRM0m = 40, MRM1m = 41, MRM2m = 42, MRM3m = 43, 112321369Sdim MRM4m = 44, MRM5m = 45, MRM6m = 46, MRM7m = 47, 113321369Sdim MRMDestReg = 48, 114321369Sdim MRMSrcReg = 49, 115321369Sdim MRMSrcReg4VOp3 = 50, 116321369Sdim MRMSrcRegOp4 = 51, 117353358Sdim MRMSrcRegCC = 52, 118353358Sdim MRMXrCC = 54, MRMXr = 55, 119321369Sdim MRM0r = 56, MRM1r = 57, MRM2r = 58, MRM3r = 59, 120321369Sdim MRM4r = 60, MRM5r = 61, MRM6r = 62, MRM7r = 63, 121321369Sdim#define MAP(from, to) MRM_##from = to, 122321369Sdim X86_INSTR_MRM_MAPPING 123321369Sdim#undef MAP 124321369Sdim }; 125321369Sdim 126321369Sdim enum { 127341825Sdim OB = 0, TB = 1, T8 = 2, TA = 3, XOP8 = 4, XOP9 = 5, XOPA = 6, ThreeDNow = 7 128321369Sdim }; 129321369Sdim 130321369Sdim enum { 131341825Sdim PD = 1, XS = 2, XD = 3, PS = 4 132321369Sdim }; 133321369Sdim 134321369Sdim enum { 135321369Sdim VEX = 1, XOP = 2, EVEX = 3 136321369Sdim }; 137321369Sdim 138321369Sdim enum { 139321369Sdim OpSize16 = 1, OpSize32 = 2 140321369Sdim }; 141321369Sdim 142321369Sdim enum { 143321369Sdim AdSize16 = 1, AdSize32 = 2, AdSize64 = 3 144321369Sdim }; 145321369Sdim} 146321369Sdim 147201360Srdivackynamespace X86Disassembler { 148201360Srdivacky 149201360Srdivacky/// RecognizableInstr - Encapsulates all information required to decode a single 150201360Srdivacky/// instruction, as extracted from the LLVM instruction tables. Has methods 151201360Srdivacky/// to interpret the information available in the LLVM tables, and to emit the 152201360Srdivacky/// instruction into DisassemblerTables. 153201360Srdivackyclass RecognizableInstr { 154201360Srdivackyprivate: 155201360Srdivacky /// The opcode of the instruction, as used in an MCInst 156201360Srdivacky InstrUID UID; 157201360Srdivacky /// The record from the .td files corresponding to this instruction 158201360Srdivacky const Record* Rec; 159276479Sdim /// The OpPrefix field from the record 160276479Sdim uint8_t OpPrefix; 161276479Sdim /// The OpMap field from the record 162276479Sdim uint8_t OpMap; 163201360Srdivacky /// The opcode field from the record; this is the opcode used in the Intel 164201360Srdivacky /// encoding and therefore distinct from the UID 165201360Srdivacky uint8_t Opcode; 166201360Srdivacky /// The form field from the record 167201360Srdivacky uint8_t Form; 168276479Sdim // The encoding field from the record 169276479Sdim uint8_t Encoding; 170276479Sdim /// The OpSize field from the record 171276479Sdim uint8_t OpSize; 172280031Sdim /// The AdSize field from the record 173280031Sdim uint8_t AdSize; 174201360Srdivacky /// The hasREX_WPrefix field from the record 175201360Srdivacky bool HasREX_WPrefix; 176276479Sdim /// The hasVEX_4V field from the record 177276479Sdim bool HasVEX_4V; 178353358Sdim /// The HasVEX_WPrefix field from the record 179353358Sdim bool HasVEX_W; 180353358Sdim /// The IgnoresVEX_W field from the record 181353358Sdim bool IgnoresVEX_W; 182221345Sdim /// Inferred from the operands; indicates whether the L bit in the VEX prefix is set 183221345Sdim bool HasVEX_LPrefix; 184234353Sdim /// The ignoreVEX_L field from the record 185226633Sdim bool IgnoresVEX_L; 186261991Sdim /// The hasEVEX_L2Prefix field from the record 187261991Sdim bool HasEVEX_L2Prefix; 188261991Sdim /// The hasEVEX_K field from the record 189261991Sdim bool HasEVEX_K; 190261991Sdim /// The hasEVEX_KZ field from the record 191261991Sdim bool HasEVEX_KZ; 192261991Sdim /// The hasEVEX_B field from the record 193261991Sdim bool HasEVEX_B; 194327952Sdim /// Indicates that the instruction uses the L and L' fields for RC. 195327952Sdim bool EncodeRC; 196276479Sdim /// The isCodeGenOnly field from the record 197201360Srdivacky bool IsCodeGenOnly; 198276479Sdim /// The ForceDisassemble field from the record 199276479Sdim bool ForceDisassemble; 200276479Sdim // The CD8_Scale field from the record 201276479Sdim uint8_t CD8_Scale; 202226633Sdim // Whether the instruction has the predicate "In64BitMode" 203224145Sdim bool Is64Bit; 204226633Sdim // Whether the instruction has the predicate "In32BitMode" 205226633Sdim bool Is32Bit; 206234353Sdim 207201360Srdivacky /// The instruction name as listed in the tables 208201360Srdivacky std::string Name; 209276479Sdim 210201360Srdivacky /// Indicates whether the instruction should be emitted into the decode 211201360Srdivacky /// tables; regardless, it will be emitted into the instruction info table 212201360Srdivacky bool ShouldBeEmitted; 213341825Sdim 214201360Srdivacky /// The operands of the instruction, as listed in the CodeGenInstruction. 215201360Srdivacky /// They are not one-to-one with operands listed in the MCInst; for example, 216201360Srdivacky /// memory operands expand to 5 operands in the MCInst 217218893Sdim const std::vector<CGIOperandList::OperandInfo>* Operands; 218341825Sdim 219201360Srdivacky /// The description of the instruction that is emitted into the instruction 220201360Srdivacky /// info table 221201360Srdivacky InstructionSpecifier* Spec; 222201360Srdivacky 223201360Srdivacky /// insnContext - Returns the primary context in which the instruction is 224201360Srdivacky /// valid. 225201360Srdivacky /// 226201360Srdivacky /// @return - The context in which the instruction is valid. 227201360Srdivacky InstructionContext insnContext() const; 228221345Sdim 229201360Srdivacky /// typeFromString - Translates an operand type from the string provided in 230201360Srdivacky /// the LLVM tables to an OperandType for use in the operand specifier. 231201360Srdivacky /// 232201360Srdivacky /// @param s - The string, as extracted by calling Rec->getName() 233201360Srdivacky /// on a CodeGenInstruction::OperandInfo. 234201360Srdivacky /// @param hasREX_WPrefix - Indicates whether the instruction has a REX.W 235201360Srdivacky /// prefix. If it does, 32-bit register operands stay 236201360Srdivacky /// 32-bit regardless of the operand size. 237276479Sdim /// @param OpSize Indicates the operand size of the instruction. 238276479Sdim /// If register size does not match OpSize, then 239276479Sdim /// register sizes keep their size. 240201360Srdivacky /// @return - The operand's type. 241276479Sdim static OperandType typeFromString(const std::string& s, 242276479Sdim bool hasREX_WPrefix, uint8_t OpSize); 243276479Sdim 244201360Srdivacky /// immediateEncodingFromString - Translates an immediate encoding from the 245201360Srdivacky /// string provided in the LLVM tables to an OperandEncoding for use in 246201360Srdivacky /// the operand specifier. 247201360Srdivacky /// 248276479Sdim /// @param s - See typeFromString(). 249276479Sdim /// @param OpSize - Indicates whether this is an OpSize16 instruction. 250276479Sdim /// If it is not, then 16-bit immediate operands stay 16-bit. 251276479Sdim /// @return - The operand's encoding. 252201360Srdivacky static OperandEncoding immediateEncodingFromString(const std::string &s, 253276479Sdim uint8_t OpSize); 254276479Sdim 255201360Srdivacky /// rmRegisterEncodingFromString - Like immediateEncodingFromString, but 256201360Srdivacky /// handles operands that are in the REG field of the ModR/M byte. 257201360Srdivacky static OperandEncoding rmRegisterEncodingFromString(const std::string &s, 258276479Sdim uint8_t OpSize); 259276479Sdim 260201360Srdivacky /// rmRegisterEncodingFromString - Like immediateEncodingFromString, but 261201360Srdivacky /// handles operands that are in the REG field of the ModR/M byte. 262201360Srdivacky static OperandEncoding roRegisterEncodingFromString(const std::string &s, 263276479Sdim uint8_t OpSize); 264201360Srdivacky static OperandEncoding memoryEncodingFromString(const std::string &s, 265276479Sdim uint8_t OpSize); 266201360Srdivacky static OperandEncoding relocationEncodingFromString(const std::string &s, 267276479Sdim uint8_t OpSize); 268201360Srdivacky static OperandEncoding opcodeModifierEncodingFromString(const std::string &s, 269276479Sdim uint8_t OpSize); 270221345Sdim static OperandEncoding vvvvRegisterEncodingFromString(const std::string &s, 271276479Sdim uint8_t OpSize); 272261991Sdim static OperandEncoding writemaskRegisterEncodingFromString(const std::string &s, 273276479Sdim uint8_t OpSize); 274276479Sdim 275341825Sdim /// Adjust the encoding type for an operand based on the instruction. 276276479Sdim void adjustOperandEncoding(OperandEncoding &encoding); 277276479Sdim 278201360Srdivacky /// handleOperand - Converts a single operand from the LLVM table format to 279201360Srdivacky /// the emitted table format, handling any duplicate operands it encounters 280201360Srdivacky /// and then one non-duplicate. 281201360Srdivacky /// 282201360Srdivacky /// @param optional - Determines whether to assert that the 283201360Srdivacky /// operand exists. 284201360Srdivacky /// @param operandIndex - The index into the generated operand table. 285201360Srdivacky /// Incremented by this function one or more 286341825Sdim /// times to reflect possible duplicate 287201360Srdivacky /// operands). 288201360Srdivacky /// @param physicalOperandIndex - The index of the current operand into the 289201360Srdivacky /// set of non-duplicate ('physical') operands. 290201360Srdivacky /// Incremented by this function once. 291201360Srdivacky /// @param numPhysicalOperands - The number of non-duplicate operands in the 292201360Srdivacky /// instructions. 293201360Srdivacky /// @param operandMapping - The operand mapping, which has an entry for 294201360Srdivacky /// each operand that indicates whether it is a 295201360Srdivacky /// duplicate, and of what. 296201360Srdivacky void handleOperand(bool optional, 297201360Srdivacky unsigned &operandIndex, 298201360Srdivacky unsigned &physicalOperandIndex, 299309124Sdim unsigned numPhysicalOperands, 300239462Sdim const unsigned *operandMapping, 301201360Srdivacky OperandEncoding (*encodingFromString) 302201360Srdivacky (const std::string&, 303276479Sdim uint8_t OpSize)); 304276479Sdim 305201360Srdivacky /// shouldBeEmitted - Returns the shouldBeEmitted field. Although filter() 306201360Srdivacky /// filters out many instructions, at various points in decoding we 307201360Srdivacky /// determine that the instruction should not actually be decodable. In 308201360Srdivacky /// particular, MMX MOV instructions aren't emitted, but they're only 309201360Srdivacky /// identified during operand parsing. 310201360Srdivacky /// 311201360Srdivacky /// @return - true if at this point we believe the instruction should be 312201360Srdivacky /// emitted; false if not. This will return false if filter() returns false 313201360Srdivacky /// once emitInstructionSpecifier() has been called. 314201360Srdivacky bool shouldBeEmitted() const { 315201360Srdivacky return ShouldBeEmitted; 316201360Srdivacky } 317341825Sdim 318201360Srdivacky /// emitInstructionSpecifier - Loads the instruction specifier for the current 319201360Srdivacky /// instruction into a DisassemblerTables. 320201360Srdivacky /// 321276479Sdim void emitInstructionSpecifier(); 322341825Sdim 323201360Srdivacky /// emitDecodePath - Populates the proper fields in the decode tables 324201360Srdivacky /// corresponding to the decode paths for this instruction. 325201360Srdivacky /// 326243830Sdim /// \param tables The DisassemblerTables to populate with the decode 327201360Srdivacky /// decode information for the current instruction. 328201360Srdivacky void emitDecodePath(DisassemblerTables &tables) const; 329201360Srdivacky 330201360Srdivacky /// Constructor - Initializes a RecognizableInstr with the appropriate fields 331201360Srdivacky /// from a CodeGenInstruction. 332201360Srdivacky /// 333243830Sdim /// \param tables The DisassemblerTables that the specifier will be added to. 334243830Sdim /// \param insn The CodeGenInstruction to extract information from. 335243830Sdim /// \param uid The unique ID of the current instruction. 336201360Srdivacky RecognizableInstr(DisassemblerTables &tables, 337201360Srdivacky const CodeGenInstruction &insn, 338201360Srdivacky InstrUID uid); 339201360Srdivackypublic: 340201360Srdivacky /// processInstr - Accepts a CodeGenInstruction and loads decode information 341201360Srdivacky /// for it into a DisassemblerTables if appropriate. 342201360Srdivacky /// 343243830Sdim /// \param tables The DiassemblerTables to be populated with decode 344201360Srdivacky /// information. 345243830Sdim /// \param insn The CodeGenInstruction to be used as a source for this 346201360Srdivacky /// information. 347243830Sdim /// \param uid The unique ID of the instruction. 348201360Srdivacky static void processInstr(DisassemblerTables &tables, 349201360Srdivacky const CodeGenInstruction &insn, 350201360Srdivacky InstrUID uid); 351201360Srdivacky}; 352341825Sdim 353201360Srdivacky} // namespace X86Disassembler 354201360Srdivacky 355201360Srdivacky} // namespace llvm 356201360Srdivacky 357201360Srdivacky#endif 358