diff options
author | Dimitry Andric <dim@FreeBSD.org> | 2018-07-28 10:51:19 +0000 |
---|---|---|
committer | Dimitry Andric <dim@FreeBSD.org> | 2018-07-28 10:51:19 +0000 |
commit | eb11fae6d08f479c0799db45860a98af528fa6e7 (patch) | |
tree | 44d492a50c8c1a7eb8e2d17ea3360ec4d066f042 /lib/Target/X86/Disassembler | |
parent | b8a2042aa938069e862750553db0e4d82d25822c (diff) | |
download | src-eb11fae6d08f479c0799db45860a98af528fa6e7.tar.gz src-eb11fae6d08f479c0799db45860a98af528fa6e7.zip |
Vendor import of llvm trunk r338150:vendor/llvm/llvm-trunk-r338150
Notes
Notes:
svn path=/vendor/llvm/dist/; revision=336809
svn path=/vendor/llvm/llvm-trunk-r338150/; revision=336814; tag=vendor/llvm/llvm-trunk-r338150
Diffstat (limited to 'lib/Target/X86/Disassembler')
4 files changed, 115 insertions, 519 deletions
diff --git a/lib/Target/X86/Disassembler/X86Disassembler.cpp b/lib/Target/X86/Disassembler/X86Disassembler.cpp index c58254ae38c1..62312777318e 100644 --- a/lib/Target/X86/Disassembler/X86Disassembler.cpp +++ b/lib/Target/X86/Disassembler/X86Disassembler.cpp @@ -103,7 +103,7 @@ StringRef llvm::X86Disassembler::GetInstrName(unsigned Opcode, return MII->getName(Opcode); } -#define debug(s) DEBUG(Debug(__FILE__, __LINE__, s)); +#define debug(s) LLVM_DEBUG(Debug(__FILE__, __LINE__, s)); namespace llvm { @@ -247,6 +247,8 @@ MCDisassembler::DecodeStatus X86GenericDisassembler::getInstruction( // It should not be 'pause' f3 90 InternalInstr.opcode != 0x90) Flags |= X86::IP_HAS_REPEAT; + if (InternalInstr.hasLockPrefix) + Flags |= X86::IP_HAS_LOCK; } Instr.setFlags(Flags); } @@ -265,13 +267,10 @@ MCDisassembler::DecodeStatus X86GenericDisassembler::getInstruction( /// @param reg - The Reg to append. static void translateRegister(MCInst &mcInst, Reg reg) { #define ENTRY(x) X86::x, - uint8_t llvmRegnums[] = { - ALL_REGS - 0 - }; + static constexpr MCPhysReg llvmRegnums[] = {ALL_REGS}; #undef ENTRY - uint8_t llvmRegnum = llvmRegnums[reg]; + MCPhysReg llvmRegnum = llvmRegnums[reg]; mcInst.addOperand(MCOperand::createReg(llvmRegnum)); } @@ -664,8 +663,6 @@ static void translateImmediate(MCInst &mcInst, uint64_t immediate, case TYPE_ZMM: mcInst.addOperand(MCOperand::createReg(X86::ZMM0 + (immediate >> 4))); return; - case TYPE_BNDR: - mcInst.addOperand(MCOperand::createReg(X86::BND0 + (immediate >> 4))); default: // operand is 64 bits wide. Do nothing. break; @@ -761,7 +758,7 @@ static bool translateRMMemory(MCInst &mcInst, InternalInstruction &insn, #undef ENTRY } } else { - baseReg = MCOperand::createReg(0); + baseReg = MCOperand::createReg(X86::NoRegister); } if (insn.sibIndex != SIB_INDEX_NONE) { @@ -780,7 +777,22 @@ static bool translateRMMemory(MCInst &mcInst, InternalInstruction &insn, #undef ENTRY } } else { - indexReg = MCOperand::createReg(0); + // Use EIZ/RIZ for a few ambiguous cases where the SIB byte is present, + // but no index is used and modrm alone should have been enough. + // -No base register in 32-bit mode. In 64-bit mode this is used to + // avoid rip-relative addressing. + // -Any base register used other than ESP/RSP/R12D/R12. Using these as a + // base always requires a SIB byte. + // -A scale other than 1 is used. + if (insn.sibScale != 1 || + (insn.sibBase == SIB_BASE_NONE && insn.mode != MODE_64BIT) || + (insn.sibBase != SIB_BASE_NONE && + insn.sibBase != SIB_BASE_ESP && insn.sibBase != SIB_BASE_RSP && + insn.sibBase != SIB_BASE_R12D && insn.sibBase != SIB_BASE_R12)) { + indexReg = MCOperand::createReg(insn.addressSize == 4 ? X86::EIZ : + X86::RIZ); + } else + indexReg = MCOperand::createReg(X86::NoRegister); } scaleAmount = MCOperand::createImm(insn.sibScale); @@ -797,12 +809,14 @@ static bool translateRMMemory(MCInst &mcInst, InternalInstruction &insn, tryAddingPcLoadReferenceComment(insn.startLocation + insn.displacementOffset, insn.displacement + pcrel, Dis); - baseReg = MCOperand::createReg(X86::RIP); // Section 2.2.1.6 + // Section 2.2.1.6 + baseReg = MCOperand::createReg(insn.addressSize == 4 ? X86::EIP : + X86::RIP); } else - baseReg = MCOperand::createReg(0); + baseReg = MCOperand::createReg(X86::NoRegister); - indexReg = MCOperand::createReg(0); + indexReg = MCOperand::createReg(X86::NoRegister); break; case EA_BASE_BX_SI: baseReg = MCOperand::createReg(X86::BX); @@ -821,7 +835,7 @@ static bool translateRMMemory(MCInst &mcInst, InternalInstruction &insn, indexReg = MCOperand::createReg(X86::DI); break; default: - indexReg = MCOperand::createReg(0); + indexReg = MCOperand::createReg(X86::NoRegister); switch (insn.eaBase) { default: debug("Unexpected eaBase"); diff --git a/lib/Target/X86/Disassembler/X86DisassemblerDecoder.cpp b/lib/Target/X86/Disassembler/X86DisassemblerDecoder.cpp index 843d037ad3cd..1ac304f3be03 100644 --- a/lib/Target/X86/Disassembler/X86DisassemblerDecoder.cpp +++ b/lib/Target/X86/Disassembler/X86DisassemblerDecoder.cpp @@ -103,6 +103,9 @@ static int modRMRequired(OpcodeType type, case XOPA_MAP: decision = &XOPA_MAP_SYM; break; + case THREEDNOW_MAP: + decision = &THREEDNOW_MAP_SYM; + break; } return decision->opcodeDecisions[insnContext].modRMDecisions[opcode]. @@ -147,6 +150,9 @@ static InstrUID decode(OpcodeType type, case XOPA_MAP: dec = &XOPA_MAP_SYM.opcodeDecisions[insnContext].modRMDecisions[opcode]; break; + case THREEDNOW_MAP: + dec = &THREEDNOW_MAP_SYM.opcodeDecisions[insnContext].modRMDecisions[opcode]; + break; } switch (dec->modrm_type) { @@ -292,6 +298,9 @@ static bool isREX(struct InternalInstruction *insn, uint8_t prefix) { static void setPrefixPresent(struct InternalInstruction *insn, uint8_t prefix) { uint8_t nextByte; switch (prefix) { + case 0xf0: + insn->hasLockPrefix = true; + break; case 0xf2: case 0xf3: if (lookAtByte(insn, &nextByte)) @@ -623,6 +632,8 @@ static int readPrefixes(struct InternalInstruction* insn) { return 0; } +static int readModRM(struct InternalInstruction* insn); + /* * readOpcode - Reads the opcode (excepting the ModR/M byte in the case of * extended or escape opcodes). @@ -715,6 +726,17 @@ static int readOpcode(struct InternalInstruction* insn) { return -1; insn->opcodeType = THREEBYTE_3A; + } else if (current == 0x0f) { + dbgprintf(insn, "Found a 3dnow escape prefix (0x%hhx)", current); + + // Consume operands before the opcode to comply with the 3DNow encoding + if (readModRM(insn)) + return -1; + + if (consumeByte(insn, ¤t)) + return -1; + + insn->opcodeType = THREEDNOW_MAP; } else { dbgprintf(insn, "Didn't find a three-byte escape prefix"); @@ -735,8 +757,6 @@ static int readOpcode(struct InternalInstruction* insn) { return 0; } -static int readModRM(struct InternalInstruction* insn); - /* * getIDWithAttrMask - Determines the ID of an instruction, consuming * the ModR/M byte as appropriate for extended and escape opcodes, @@ -947,6 +967,7 @@ static int getID(struct InternalInstruction* insn, const void *miiArg) { attrMask |= ATTR_ADSIZE; break; } + } if (insn->rexPrefix & 0x08) { @@ -1039,13 +1060,15 @@ static int getID(struct InternalInstruction* insn, const void *miiArg) { } /* - * Absolute moves need special handling. + * Absolute moves, umonitor, and movdir64b need special handling. * -For 16-bit mode because the meaning of the AdSize and OpSize prefixes are * inverted w.r.t. * -For 32-bit mode we need to ensure the ADSIZE prefix is observed in * any position. */ - if (insn->opcodeType == ONEBYTE && ((insn->opcode & 0xFC) == 0xA0)) { + if ((insn->opcodeType == ONEBYTE && ((insn->opcode & 0xFC) == 0xA0)) || + (insn->opcodeType == TWOBYTE && (insn->opcode == 0xAE)) || + (insn->opcodeType == THREEBYTE_38 && insn->opcode == 0xF8)) { /* Make sure we observed the prefixes in any position. */ if (insn->hasAdSize) attrMask |= ATTR_ADSIZE; @@ -1053,8 +1076,13 @@ static int getID(struct InternalInstruction* insn, const void *miiArg) { attrMask |= ATTR_OPSIZE; /* In 16-bit, invert the attributes. */ - if (insn->mode == MODE_16BIT) - attrMask ^= ATTR_ADSIZE | ATTR_OPSIZE; + if (insn->mode == MODE_16BIT) { + attrMask ^= ATTR_ADSIZE; + + /* The OpSize attribute is only valid with the absolute moves. */ + if (insn->opcodeType == ONEBYTE && ((insn->opcode & 0xFC) == 0xA0)) + attrMask ^= ATTR_OPSIZE; + } if (getIDWithAttrMask(&instructionID, insn, attrMask)) return -1; @@ -1279,7 +1307,7 @@ static int readDisplacement(struct InternalInstruction* insn) { * @return - 0 if the information was successfully read; nonzero otherwise. */ static int readModRM(struct InternalInstruction* insn) { - uint8_t mod, rm, reg; + uint8_t mod, rm, reg, evexrm; dbgprintf(insn, "readModRM()"); @@ -1316,16 +1344,18 @@ static int readModRM(struct InternalInstruction* insn) { reg |= rFromREX(insn->rexPrefix) << 3; rm |= bFromREX(insn->rexPrefix) << 3; - if (insn->vectorExtensionType == TYPE_EVEX) { + + evexrm = 0; + if (insn->vectorExtensionType == TYPE_EVEX && insn->mode == MODE_64BIT) { reg |= r2FromEVEX2of4(insn->vectorExtensionPrefix[1]) << 4; - rm |= xFromEVEX2of4(insn->vectorExtensionPrefix[1]) << 4; + evexrm = xFromEVEX2of4(insn->vectorExtensionPrefix[1]) << 4; } insn->reg = (Reg)(insn->regBase + reg); switch (insn->addressSize) { - case 2: - insn->eaBaseBase = EA_BASE_BX_SI; + case 2: { + EABase eaBaseBase = EA_BASE_BX_SI; switch (mod) { case 0x0: @@ -1335,19 +1365,19 @@ static int readModRM(struct InternalInstruction* insn) { if (readDisplacement(insn)) return -1; } else { - insn->eaBase = (EABase)(insn->eaBaseBase + rm); + insn->eaBase = (EABase)(eaBaseBase + rm); insn->eaDisplacement = EA_DISP_NONE; } break; case 0x1: - insn->eaBase = (EABase)(insn->eaBaseBase + rm); + insn->eaBase = (EABase)(eaBaseBase + rm); insn->eaDisplacement = EA_DISP_8; insn->displacementSize = 1; if (readDisplacement(insn)) return -1; break; case 0x2: - insn->eaBase = (EABase)(insn->eaBaseBase + rm); + insn->eaBase = (EABase)(eaBaseBase + rm); insn->eaDisplacement = EA_DISP_16; if (readDisplacement(insn)) return -1; @@ -1359,9 +1389,10 @@ static int readModRM(struct InternalInstruction* insn) { break; } break; + } case 4: - case 8: - insn->eaBaseBase = (insn->addressSize == 4 ? EA_BASE_EAX : EA_BASE_RAX); + case 8: { + EABase eaBaseBase = (insn->addressSize == 4 ? EA_BASE_EAX : EA_BASE_RAX); switch (mod) { case 0x0: @@ -1383,7 +1414,7 @@ static int readModRM(struct InternalInstruction* insn) { return -1; break; default: - insn->eaBase = (EABase)(insn->eaBaseBase + rm); + insn->eaBase = (EABase)(eaBaseBase + rm); break; } break; @@ -1399,7 +1430,7 @@ static int readModRM(struct InternalInstruction* insn) { return -1; break; default: - insn->eaBase = (EABase)(insn->eaBaseBase + rm); + insn->eaBase = (EABase)(eaBaseBase + rm); if (readDisplacement(insn)) return -1; break; @@ -1407,16 +1438,17 @@ static int readModRM(struct InternalInstruction* insn) { break; case 0x3: insn->eaDisplacement = EA_DISP_NONE; - insn->eaBase = (EABase)(insn->eaRegBase + rm); + insn->eaBase = (EABase)(insn->eaRegBase + rm + evexrm); break; } break; + } } /* switch (insn->addressSize) */ return 0; } -#define GENERIC_FIXUP_FUNC(name, base, prefix) \ +#define GENERIC_FIXUP_FUNC(name, base, prefix, mask) \ static uint16_t name(struct InternalInstruction *insn, \ OperandType type, \ uint8_t index, \ @@ -1430,6 +1462,9 @@ static int readModRM(struct InternalInstruction* insn) { case TYPE_Rv: \ return base + index; \ case TYPE_R8: \ + index &= mask; \ + if (index > 0xf) \ + *valid = 0; \ if (insn->rexPrefix && \ index >= 4 && index <= 7) { \ return prefix##_SPL + (index - 4); \ @@ -1437,10 +1472,19 @@ static int readModRM(struct InternalInstruction* insn) { return prefix##_AL + index; \ } \ case TYPE_R16: \ + index &= mask; \ + if (index > 0xf) \ + *valid = 0; \ return prefix##_AX + index; \ case TYPE_R32: \ + index &= mask; \ + if (index > 0xf) \ + *valid = 0; \ return prefix##_EAX + index; \ case TYPE_R64: \ + index &= mask; \ + if (index > 0xf) \ + *valid = 0; \ return prefix##_RAX + index; \ case TYPE_ZMM: \ return prefix##_ZMM0 + index; \ @@ -1449,6 +1493,7 @@ static int readModRM(struct InternalInstruction* insn) { case TYPE_XMM: \ return prefix##_XMM0 + index; \ case TYPE_VK: \ + index &= 0xf; \ if (index > 7) \ *valid = 0; \ return prefix##_K0 + index; \ @@ -1488,8 +1533,8 @@ static int readModRM(struct InternalInstruction* insn) { * field is valid for the register class; 0 if not. * @return - The proper value. */ -GENERIC_FIXUP_FUNC(fixupRegValue, insn->regBase, MODRM_REG) -GENERIC_FIXUP_FUNC(fixupRMValue, insn->eaRegBase, EA_REG) +GENERIC_FIXUP_FUNC(fixupRegValue, insn->regBase, MODRM_REG, 0x1f) +GENERIC_FIXUP_FUNC(fixupRMValue, insn->eaRegBase, EA_REG, 0xf) /* * fixupReg - Consults an operand specifier to determine which of the @@ -1670,7 +1715,7 @@ static int readVVVV(struct InternalInstruction* insn) { return -1; if (insn->mode != MODE_64BIT) - vvvv &= 0x7; + vvvv &= 0xf; // Can only clear bit 4. Bit 3 must be cleared later. insn->vvvv = static_cast<Reg>(vvvv); return 0; @@ -1731,10 +1776,10 @@ static int readOperands(struct InternalInstruction* insn) { // If sibIndex was set to SIB_INDEX_NONE, index offset is 4. if (insn->sibIndex == SIB_INDEX_NONE) - insn->sibIndex = (SIBIndex)4; + insn->sibIndex = (SIBIndex)(insn->sibIndexBase + 4); // If EVEX.v2 is set this is one of the 16-31 registers. - if (insn->vectorExtensionType == TYPE_EVEX && + if (insn->vectorExtensionType == TYPE_EVEX && insn->mode == MODE_64BIT && v2FromEVEX4of4(insn->vectorExtensionPrefix[3])) insn->sibIndex = (SIBIndex)(insn->sibIndex + 16); @@ -1835,6 +1880,8 @@ static int readOperands(struct InternalInstruction* insn) { needVVVV = 0; /* Mark that we have found a VVVV operand. */ if (!hasVVVV) return -1; + if (insn->mode != MODE_64BIT) + insn->vvvv = static_cast<Reg>(insn->vvvv & 0x7); if (fixupReg(insn, &Op)) return -1; break; diff --git a/lib/Target/X86/Disassembler/X86DisassemblerDecoder.h b/lib/Target/X86/Disassembler/X86DisassemblerDecoder.h index ecd9d8dccafa..3b8a4f732eed 100644 --- a/lib/Target/X86/Disassembler/X86DisassemblerDecoder.h +++ b/lib/Target/X86/Disassembler/X86DisassemblerDecoder.h @@ -16,8 +16,8 @@ #ifndef LLVM_LIB_TARGET_X86_DISASSEMBLER_X86DISASSEMBLERDECODER_H #define LLVM_LIB_TARGET_X86_DISASSEMBLER_X86DISASSEMBLERDECODER_H -#include "X86DisassemblerDecoderCommon.h" #include "llvm/ADT/ArrayRef.h" +#include "llvm/Support/X86DisassemblerDecoderCommon.h" namespace llvm { namespace X86Disassembler { @@ -400,7 +400,7 @@ namespace X86Disassembler { REGS_BOUND \ ENTRY(RIP) -/// \brief All possible values of the base field for effective-address +/// All possible values of the base field for effective-address /// computations, a.k.a. the Mod and R/M fields of the ModR/M byte. /// We distinguish between bases (EA_BASE_*) and registers that just happen /// to be referred to when Mod == 0b11 (EA_REG_*). @@ -415,7 +415,7 @@ enum EABase { EA_max }; -/// \brief All possible values of the SIB index field. +/// All possible values of the SIB index field. /// borrows entries from ALL_EA_BASES with the special case that /// sib is synonymous with NONE. /// Vector SIB: index can be XMM or YMM. @@ -430,7 +430,7 @@ enum SIBIndex { SIB_INDEX_max }; -/// \brief All possible values of the SIB base field. +/// All possible values of the SIB base field. enum SIBBase { SIB_BASE_NONE, #define ENTRY(x) SIB_BASE_##x, @@ -439,7 +439,7 @@ enum SIBBase { SIB_BASE_max }; -/// \brief Possible displacement types for effective-address computations. +/// Possible displacement types for effective-address computations. typedef enum { EA_DISP_NONE, EA_DISP_8, @@ -447,7 +447,7 @@ typedef enum { EA_DISP_32 } EADisplacement; -/// \brief All possible values of the reg field in the ModR/M byte. +/// All possible values of the reg field in the ModR/M byte. enum Reg { #define ENTRY(x) MODRM_REG_##x, ALL_REGS @@ -455,7 +455,7 @@ enum Reg { MODRM_REG_max }; -/// \brief All possible segment overrides. +/// All possible segment overrides. enum SegmentOverride { SEG_OVERRIDE_NONE, SEG_OVERRIDE_CS, @@ -467,7 +467,7 @@ enum SegmentOverride { SEG_OVERRIDE_max }; -/// \brief Possible values for the VEX.m-mmmm field +/// Possible values for the VEX.m-mmmm field enum VEXLeadingOpcodeByte { VEX_LOB_0F = 0x1, VEX_LOB_0F38 = 0x2, @@ -480,7 +480,7 @@ enum XOPMapSelect { XOP_MAP_SELECT_A = 0xA }; -/// \brief Possible values for the VEX.pp/EVEX.pp field +/// Possible values for the VEX.pp/EVEX.pp field enum VEXPrefixCode { VEX_PREFIX_NONE = 0x0, VEX_PREFIX_66 = 0x1, @@ -496,7 +496,7 @@ enum VectorExtensionType { TYPE_XOP = 0x4 }; -/// \brief Type for the byte reader that the consumer must provide to +/// Type for the byte reader that the consumer must provide to /// the decoder. Reads a single byte from the instruction's address space. /// \param arg A baton that the consumer can associate with any internal /// state that it needs. @@ -507,7 +507,7 @@ enum VectorExtensionType { /// \return -1 if the byte cannot be read for any reason; 0 otherwise. typedef int (*byteReader_t)(const void *arg, uint8_t *byte, uint64_t address); -/// \brief Type for the logging function that the consumer can provide to +/// Type for the logging function that the consumer can provide to /// get debugging output from the decoder. /// \param arg A baton that the consumer can associate with any internal /// state that it needs. @@ -563,6 +563,8 @@ struct InternalInstruction { bool hasAdSize; // Operand-size override bool hasOpSize; + // Lock prefix + bool hasLockPrefix; // The repeat prefix if any uint8_t repeatPrefix; @@ -627,7 +629,6 @@ struct InternalInstruction { // These fields determine the allowable values for the ModR/M fields, which // depend on operand and address widths. - EABase eaBaseBase; EABase eaRegBase; Reg regBase; @@ -650,7 +651,7 @@ struct InternalInstruction { ArrayRef<OperandSpecifier> operands; }; -/// \brief Decode one instruction and store the decoding results in +/// Decode one instruction and store the decoding results in /// a buffer provided by the consumer. /// \param insn The buffer to store the instruction in. Allocated by the /// consumer. @@ -674,7 +675,7 @@ int decodeInstruction(InternalInstruction *insn, uint64_t startLoc, DisassemblerMode mode); -/// \brief Print a message to debugs() +/// Print a message to debugs() /// \param file The name of the file printing the debug message. /// \param line The line number that printed the debug message. /// \param s The message to print. diff --git a/lib/Target/X86/Disassembler/X86DisassemblerDecoderCommon.h b/lib/Target/X86/Disassembler/X86DisassemblerDecoderCommon.h deleted file mode 100644 index ad1404860fb6..000000000000 --- a/lib/Target/X86/Disassembler/X86DisassemblerDecoderCommon.h +++ /dev/null @@ -1,466 +0,0 @@ -//===-- X86DisassemblerDecoderCommon.h - Disassembler decoder ---*- C++ -*-===// -// -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. -// -//===----------------------------------------------------------------------===// -// -// This file is part of the X86 Disassembler. -// It contains common definitions used by both the disassembler and the table -// generator. -// Documentation for the disassembler can be found in X86Disassembler.h. -// -//===----------------------------------------------------------------------===// - -#ifndef LLVM_LIB_TARGET_X86_DISASSEMBLER_X86DISASSEMBLERDECODERCOMMON_H -#define LLVM_LIB_TARGET_X86_DISASSEMBLER_X86DISASSEMBLERDECODERCOMMON_H - -#include "llvm/Support/DataTypes.h" - -namespace llvm { -namespace X86Disassembler { - -#define INSTRUCTIONS_SYM x86DisassemblerInstrSpecifiers -#define CONTEXTS_SYM x86DisassemblerContexts -#define ONEBYTE_SYM x86DisassemblerOneByteOpcodes -#define TWOBYTE_SYM x86DisassemblerTwoByteOpcodes -#define THREEBYTE38_SYM x86DisassemblerThreeByte38Opcodes -#define THREEBYTE3A_SYM x86DisassemblerThreeByte3AOpcodes -#define XOP8_MAP_SYM x86DisassemblerXOP8Opcodes -#define XOP9_MAP_SYM x86DisassemblerXOP9Opcodes -#define XOPA_MAP_SYM x86DisassemblerXOPAOpcodes - -#define INSTRUCTIONS_STR "x86DisassemblerInstrSpecifiers" -#define CONTEXTS_STR "x86DisassemblerContexts" -#define ONEBYTE_STR "x86DisassemblerOneByteOpcodes" -#define TWOBYTE_STR "x86DisassemblerTwoByteOpcodes" -#define THREEBYTE38_STR "x86DisassemblerThreeByte38Opcodes" -#define THREEBYTE3A_STR "x86DisassemblerThreeByte3AOpcodes" -#define XOP8_MAP_STR "x86DisassemblerXOP8Opcodes" -#define XOP9_MAP_STR "x86DisassemblerXOP9Opcodes" -#define XOPA_MAP_STR "x86DisassemblerXOPAOpcodes" - -// Attributes of an instruction that must be known before the opcode can be -// processed correctly. Most of these indicate the presence of particular -// prefixes, but ATTR_64BIT is simply an attribute of the decoding context. -#define ATTRIBUTE_BITS \ - ENUM_ENTRY(ATTR_NONE, 0x00) \ - ENUM_ENTRY(ATTR_64BIT, (0x1 << 0)) \ - ENUM_ENTRY(ATTR_XS, (0x1 << 1)) \ - ENUM_ENTRY(ATTR_XD, (0x1 << 2)) \ - ENUM_ENTRY(ATTR_REXW, (0x1 << 3)) \ - ENUM_ENTRY(ATTR_OPSIZE, (0x1 << 4)) \ - ENUM_ENTRY(ATTR_ADSIZE, (0x1 << 5)) \ - ENUM_ENTRY(ATTR_VEX, (0x1 << 6)) \ - ENUM_ENTRY(ATTR_VEXL, (0x1 << 7)) \ - ENUM_ENTRY(ATTR_EVEX, (0x1 << 8)) \ - ENUM_ENTRY(ATTR_EVEXL, (0x1 << 9)) \ - ENUM_ENTRY(ATTR_EVEXL2, (0x1 << 10)) \ - ENUM_ENTRY(ATTR_EVEXK, (0x1 << 11)) \ - ENUM_ENTRY(ATTR_EVEXKZ, (0x1 << 12)) \ - ENUM_ENTRY(ATTR_EVEXB, (0x1 << 13)) - -#define ENUM_ENTRY(n, v) n = v, -enum attributeBits { - ATTRIBUTE_BITS - ATTR_max -}; -#undef ENUM_ENTRY - -// Combinations of the above attributes that are relevant to instruction -// decode. Although other combinations are possible, they can be reduced to -// these without affecting the ultimately decoded instruction. - -// Class name Rank Rationale for rank assignment -#define INSTRUCTION_CONTEXTS \ - ENUM_ENTRY(IC, 0, "says nothing about the instruction") \ - ENUM_ENTRY(IC_64BIT, 1, "says the instruction applies in " \ - "64-bit mode but no more") \ - ENUM_ENTRY(IC_OPSIZE, 3, "requires an OPSIZE prefix, so " \ - "operands change width") \ - ENUM_ENTRY(IC_ADSIZE, 3, "requires an ADSIZE prefix, so " \ - "operands change width") \ - ENUM_ENTRY(IC_OPSIZE_ADSIZE, 4, "requires ADSIZE and OPSIZE prefixes") \ - ENUM_ENTRY(IC_XD, 2, "may say something about the opcode " \ - "but not the operands") \ - ENUM_ENTRY(IC_XS, 2, "may say something about the opcode " \ - "but not the operands") \ - ENUM_ENTRY(IC_XD_OPSIZE, 3, "requires an OPSIZE prefix, so " \ - "operands change width") \ - ENUM_ENTRY(IC_XS_OPSIZE, 3, "requires an OPSIZE prefix, so " \ - "operands change width") \ - ENUM_ENTRY(IC_64BIT_REXW, 5, "requires a REX.W prefix, so operands "\ - "change width; overrides IC_OPSIZE") \ - ENUM_ENTRY(IC_64BIT_REXW_ADSIZE, 6, "requires a REX.W prefix and 0x67 " \ - "prefix") \ - ENUM_ENTRY(IC_64BIT_OPSIZE, 3, "Just as meaningful as IC_OPSIZE") \ - ENUM_ENTRY(IC_64BIT_ADSIZE, 3, "Just as meaningful as IC_ADSIZE") \ - ENUM_ENTRY(IC_64BIT_OPSIZE_ADSIZE, 4, "Just as meaningful as IC_OPSIZE/" \ - "IC_ADSIZE") \ - ENUM_ENTRY(IC_64BIT_XD, 6, "XD instructions are SSE; REX.W is " \ - "secondary") \ - ENUM_ENTRY(IC_64BIT_XS, 6, "Just as meaningful as IC_64BIT_XD") \ - ENUM_ENTRY(IC_64BIT_XD_OPSIZE, 3, "Just as meaningful as IC_XD_OPSIZE") \ - ENUM_ENTRY(IC_64BIT_XS_OPSIZE, 3, "Just as meaningful as IC_XS_OPSIZE") \ - ENUM_ENTRY(IC_64BIT_REXW_XS, 7, "OPSIZE could mean a different " \ - "opcode") \ - ENUM_ENTRY(IC_64BIT_REXW_XD, 7, "Just as meaningful as " \ - "IC_64BIT_REXW_XS") \ - ENUM_ENTRY(IC_64BIT_REXW_OPSIZE, 8, "The Dynamic Duo! Prefer over all " \ - "else because this changes most " \ - "operands' meaning") \ - ENUM_ENTRY(IC_VEX, 1, "requires a VEX prefix") \ - ENUM_ENTRY(IC_VEX_XS, 2, "requires VEX and the XS prefix") \ - ENUM_ENTRY(IC_VEX_XD, 2, "requires VEX and the XD prefix") \ - ENUM_ENTRY(IC_VEX_OPSIZE, 2, "requires VEX and the OpSize prefix") \ - ENUM_ENTRY(IC_VEX_W, 3, "requires VEX and the W prefix") \ - ENUM_ENTRY(IC_VEX_W_XS, 4, "requires VEX, W, and XS prefix") \ - ENUM_ENTRY(IC_VEX_W_XD, 4, "requires VEX, W, and XD prefix") \ - ENUM_ENTRY(IC_VEX_W_OPSIZE, 4, "requires VEX, W, and OpSize") \ - ENUM_ENTRY(IC_VEX_L, 3, "requires VEX and the L prefix") \ - ENUM_ENTRY(IC_VEX_L_XS, 4, "requires VEX and the L and XS prefix")\ - ENUM_ENTRY(IC_VEX_L_XD, 4, "requires VEX and the L and XD prefix")\ - ENUM_ENTRY(IC_VEX_L_OPSIZE, 4, "requires VEX, L, and OpSize") \ - ENUM_ENTRY(IC_VEX_L_W, 4, "requires VEX, L and W") \ - ENUM_ENTRY(IC_VEX_L_W_XS, 5, "requires VEX, L, W and XS prefix") \ - ENUM_ENTRY(IC_VEX_L_W_XD, 5, "requires VEX, L, W and XD prefix") \ - ENUM_ENTRY(IC_VEX_L_W_OPSIZE, 5, "requires VEX, L, W and OpSize") \ - ENUM_ENTRY(IC_EVEX, 1, "requires an EVEX prefix") \ - ENUM_ENTRY(IC_EVEX_XS, 2, "requires EVEX and the XS prefix") \ - ENUM_ENTRY(IC_EVEX_XD, 2, "requires EVEX and the XD prefix") \ - ENUM_ENTRY(IC_EVEX_OPSIZE, 2, "requires EVEX and the OpSize prefix") \ - ENUM_ENTRY(IC_EVEX_W, 3, "requires EVEX and the W prefix") \ - ENUM_ENTRY(IC_EVEX_W_XS, 4, "requires EVEX, W, and XS prefix") \ - ENUM_ENTRY(IC_EVEX_W_XD, 4, "requires EVEX, W, and XD prefix") \ - ENUM_ENTRY(IC_EVEX_W_OPSIZE, 4, "requires EVEX, W, and OpSize") \ - ENUM_ENTRY(IC_EVEX_L, 3, "requires EVEX and the L prefix") \ - ENUM_ENTRY(IC_EVEX_L_XS, 4, "requires EVEX and the L and XS prefix")\ - ENUM_ENTRY(IC_EVEX_L_XD, 4, "requires EVEX and the L and XD prefix")\ - ENUM_ENTRY(IC_EVEX_L_OPSIZE, 4, "requires EVEX, L, and OpSize") \ - ENUM_ENTRY(IC_EVEX_L_W, 3, "requires EVEX, L and W") \ - ENUM_ENTRY(IC_EVEX_L_W_XS, 4, "requires EVEX, L, W and XS prefix") \ - ENUM_ENTRY(IC_EVEX_L_W_XD, 4, "requires EVEX, L, W and XD prefix") \ - ENUM_ENTRY(IC_EVEX_L_W_OPSIZE, 4, "requires EVEX, L, W and OpSize") \ - ENUM_ENTRY(IC_EVEX_L2, 3, "requires EVEX and the L2 prefix") \ - ENUM_ENTRY(IC_EVEX_L2_XS, 4, "requires EVEX and the L2 and XS prefix")\ - ENUM_ENTRY(IC_EVEX_L2_XD, 4, "requires EVEX and the L2 and XD prefix")\ - ENUM_ENTRY(IC_EVEX_L2_OPSIZE, 4, "requires EVEX, L2, and OpSize") \ - ENUM_ENTRY(IC_EVEX_L2_W, 3, "requires EVEX, L2 and W") \ - ENUM_ENTRY(IC_EVEX_L2_W_XS, 4, "requires EVEX, L2, W and XS prefix") \ - ENUM_ENTRY(IC_EVEX_L2_W_XD, 4, "requires EVEX, L2, W and XD prefix") \ - ENUM_ENTRY(IC_EVEX_L2_W_OPSIZE, 4, "requires EVEX, L2, W and OpSize") \ - ENUM_ENTRY(IC_EVEX_K, 1, "requires an EVEX_K prefix") \ - ENUM_ENTRY(IC_EVEX_XS_K, 2, "requires EVEX_K and the XS prefix") \ - ENUM_ENTRY(IC_EVEX_XD_K, 2, "requires EVEX_K and the XD prefix") \ - ENUM_ENTRY(IC_EVEX_OPSIZE_K, 2, "requires EVEX_K and the OpSize prefix") \ - ENUM_ENTRY(IC_EVEX_W_K, 3, "requires EVEX_K and the W prefix") \ - ENUM_ENTRY(IC_EVEX_W_XS_K, 4, "requires EVEX_K, W, and XS prefix") \ - ENUM_ENTRY(IC_EVEX_W_XD_K, 4, "requires EVEX_K, W, and XD prefix") \ - ENUM_ENTRY(IC_EVEX_W_OPSIZE_K, 4, "requires EVEX_K, W, and OpSize") \ - ENUM_ENTRY(IC_EVEX_L_K, 3, "requires EVEX_K and the L prefix") \ - ENUM_ENTRY(IC_EVEX_L_XS_K, 4, "requires EVEX_K and the L and XS prefix")\ - ENUM_ENTRY(IC_EVEX_L_XD_K, 4, "requires EVEX_K and the L and XD prefix")\ - ENUM_ENTRY(IC_EVEX_L_OPSIZE_K, 4, "requires EVEX_K, L, and OpSize") \ - ENUM_ENTRY(IC_EVEX_L_W_K, 3, "requires EVEX_K, L and W") \ - ENUM_ENTRY(IC_EVEX_L_W_XS_K, 4, "requires EVEX_K, L, W and XS prefix") \ - ENUM_ENTRY(IC_EVEX_L_W_XD_K, 4, "requires EVEX_K, L, W and XD prefix") \ - ENUM_ENTRY(IC_EVEX_L_W_OPSIZE_K, 4, "requires EVEX_K, L, W and OpSize") \ - ENUM_ENTRY(IC_EVEX_L2_K, 3, "requires EVEX_K and the L2 prefix") \ - ENUM_ENTRY(IC_EVEX_L2_XS_K, 4, "requires EVEX_K and the L2 and XS prefix")\ - ENUM_ENTRY(IC_EVEX_L2_XD_K, 4, "requires EVEX_K and the L2 and XD prefix")\ - ENUM_ENTRY(IC_EVEX_L2_OPSIZE_K, 4, "requires EVEX_K, L2, and OpSize") \ - ENUM_ENTRY(IC_EVEX_L2_W_K, 3, "requires EVEX_K, L2 and W") \ - ENUM_ENTRY(IC_EVEX_L2_W_XS_K, 4, "requires EVEX_K, L2, W and XS prefix") \ - ENUM_ENTRY(IC_EVEX_L2_W_XD_K, 4, "requires EVEX_K, L2, W and XD prefix") \ - ENUM_ENTRY(IC_EVEX_L2_W_OPSIZE_K, 4, "requires EVEX_K, L2, W and OpSize") \ - ENUM_ENTRY(IC_EVEX_B, 1, "requires an EVEX_B prefix") \ - ENUM_ENTRY(IC_EVEX_XS_B, 2, "requires EVEX_B and the XS prefix") \ - ENUM_ENTRY(IC_EVEX_XD_B, 2, "requires EVEX_B and the XD prefix") \ - ENUM_ENTRY(IC_EVEX_OPSIZE_B, 2, "requires EVEX_B and the OpSize prefix") \ - ENUM_ENTRY(IC_EVEX_W_B, 3, "requires EVEX_B and the W prefix") \ - ENUM_ENTRY(IC_EVEX_W_XS_B, 4, "requires EVEX_B, W, and XS prefix") \ - ENUM_ENTRY(IC_EVEX_W_XD_B, 4, "requires EVEX_B, W, and XD prefix") \ - ENUM_ENTRY(IC_EVEX_W_OPSIZE_B, 4, "requires EVEX_B, W, and OpSize") \ - ENUM_ENTRY(IC_EVEX_L_B, 3, "requires EVEX_B and the L prefix") \ - ENUM_ENTRY(IC_EVEX_L_XS_B, 4, "requires EVEX_B and the L and XS prefix")\ - ENUM_ENTRY(IC_EVEX_L_XD_B, 4, "requires EVEX_B and the L and XD prefix")\ - ENUM_ENTRY(IC_EVEX_L_OPSIZE_B, 4, "requires EVEX_B, L, and OpSize") \ - ENUM_ENTRY(IC_EVEX_L_W_B, 3, "requires EVEX_B, L and W") \ - ENUM_ENTRY(IC_EVEX_L_W_XS_B, 4, "requires EVEX_B, L, W and XS prefix") \ - ENUM_ENTRY(IC_EVEX_L_W_XD_B, 4, "requires EVEX_B, L, W and XD prefix") \ - ENUM_ENTRY(IC_EVEX_L_W_OPSIZE_B, 4, "requires EVEX_B, L, W and OpSize") \ - ENUM_ENTRY(IC_EVEX_L2_B, 3, "requires EVEX_B and the L2 prefix") \ - ENUM_ENTRY(IC_EVEX_L2_XS_B, 4, "requires EVEX_B and the L2 and XS prefix")\ - ENUM_ENTRY(IC_EVEX_L2_XD_B, 4, "requires EVEX_B and the L2 and XD prefix")\ - ENUM_ENTRY(IC_EVEX_L2_OPSIZE_B, 4, "requires EVEX_B, L2, and OpSize") \ - ENUM_ENTRY(IC_EVEX_L2_W_B, 3, "requires EVEX_B, L2 and W") \ - ENUM_ENTRY(IC_EVEX_L2_W_XS_B, 4, "requires EVEX_B, L2, W and XS prefix") \ - ENUM_ENTRY(IC_EVEX_L2_W_XD_B, 4, "requires EVEX_B, L2, W and XD prefix") \ - ENUM_ENTRY(IC_EVEX_L2_W_OPSIZE_B, 4, "requires EVEX_B, L2, W and OpSize") \ - ENUM_ENTRY(IC_EVEX_K_B, 1, "requires EVEX_B and EVEX_K prefix") \ - ENUM_ENTRY(IC_EVEX_XS_K_B, 2, "requires EVEX_B, EVEX_K and the XS prefix") \ - ENUM_ENTRY(IC_EVEX_XD_K_B, 2, "requires EVEX_B, EVEX_K and the XD prefix") \ - ENUM_ENTRY(IC_EVEX_OPSIZE_K_B, 2, "requires EVEX_B, EVEX_K and the OpSize prefix") \ - ENUM_ENTRY(IC_EVEX_W_K_B, 3, "requires EVEX_B, EVEX_K and the W prefix") \ - ENUM_ENTRY(IC_EVEX_W_XS_K_B, 4, "requires EVEX_B, EVEX_K, W, and XS prefix") \ - ENUM_ENTRY(IC_EVEX_W_XD_K_B, 4, "requires EVEX_B, EVEX_K, W, and XD prefix") \ - ENUM_ENTRY(IC_EVEX_W_OPSIZE_K_B, 4, "requires EVEX_B, EVEX_K, W, and OpSize") \ - ENUM_ENTRY(IC_EVEX_L_K_B, 3, "requires EVEX_B, EVEX_K and the L prefix") \ - ENUM_ENTRY(IC_EVEX_L_XS_K_B, 4, "requires EVEX_B, EVEX_K and the L and XS prefix")\ - ENUM_ENTRY(IC_EVEX_L_XD_K_B, 4, "requires EVEX_B, EVEX_K and the L and XD prefix")\ - ENUM_ENTRY(IC_EVEX_L_OPSIZE_K_B, 4, "requires EVEX_B, EVEX_K, L, and OpSize") \ - ENUM_ENTRY(IC_EVEX_L_W_K_B, 3, "requires EVEX_B, EVEX_K, L and W") \ - ENUM_ENTRY(IC_EVEX_L_W_XS_K_B, 4, "requires EVEX_B, EVEX_K, L, W and XS prefix") \ - ENUM_ENTRY(IC_EVEX_L_W_XD_K_B, 4, "requires EVEX_B, EVEX_K, L, W and XD prefix") \ - ENUM_ENTRY(IC_EVEX_L_W_OPSIZE_K_B,4, "requires EVEX_B, EVEX_K, L, W and OpSize") \ - ENUM_ENTRY(IC_EVEX_L2_K_B, 3, "requires EVEX_B, EVEX_K and the L2 prefix") \ - ENUM_ENTRY(IC_EVEX_L2_XS_K_B, 4, "requires EVEX_B, EVEX_K and the L2 and XS prefix")\ - ENUM_ENTRY(IC_EVEX_L2_XD_K_B, 4, "requires EVEX_B, EVEX_K and the L2 and XD prefix")\ - ENUM_ENTRY(IC_EVEX_L2_OPSIZE_K_B, 4, "requires EVEX_B, EVEX_K, L2, and OpSize") \ - ENUM_ENTRY(IC_EVEX_L2_W_K_B, 3, "requires EVEX_B, EVEX_K, L2 and W") \ - ENUM_ENTRY(IC_EVEX_L2_W_XS_K_B, 4, "requires EVEX_B, EVEX_K, L2, W and XS prefix") \ - ENUM_ENTRY(IC_EVEX_L2_W_XD_K_B, 4, "requires EVEX_B, EVEX_K, L2, W and XD prefix") \ - ENUM_ENTRY(IC_EVEX_L2_W_OPSIZE_K_B,4, "requires EVEX_B, EVEX_K, L2, W and OpSize") \ - ENUM_ENTRY(IC_EVEX_KZ_B, 1, "requires EVEX_B and EVEX_KZ prefix") \ - ENUM_ENTRY(IC_EVEX_XS_KZ_B, 2, "requires EVEX_B, EVEX_KZ and the XS prefix") \ - ENUM_ENTRY(IC_EVEX_XD_KZ_B, 2, "requires EVEX_B, EVEX_KZ and the XD prefix") \ - ENUM_ENTRY(IC_EVEX_OPSIZE_KZ_B, 2, "requires EVEX_B, EVEX_KZ and the OpSize prefix") \ - ENUM_ENTRY(IC_EVEX_W_KZ_B, 3, "requires EVEX_B, EVEX_KZ and the W prefix") \ - ENUM_ENTRY(IC_EVEX_W_XS_KZ_B, 4, "requires EVEX_B, EVEX_KZ, W, and XS prefix") \ - ENUM_ENTRY(IC_EVEX_W_XD_KZ_B, 4, "requires EVEX_B, EVEX_KZ, W, and XD prefix") \ - ENUM_ENTRY(IC_EVEX_W_OPSIZE_KZ_B, 4, "requires EVEX_B, EVEX_KZ, W, and OpSize") \ - ENUM_ENTRY(IC_EVEX_L_KZ_B, 3, "requires EVEX_B, EVEX_KZ and the L prefix") \ - ENUM_ENTRY(IC_EVEX_L_XS_KZ_B, 4, "requires EVEX_B, EVEX_KZ and the L and XS prefix")\ - ENUM_ENTRY(IC_EVEX_L_XD_KZ_B, 4, "requires EVEX_B, EVEX_KZ and the L and XD prefix")\ - ENUM_ENTRY(IC_EVEX_L_OPSIZE_KZ_B, 4, "requires EVEX_B, EVEX_KZ, L, and OpSize") \ - ENUM_ENTRY(IC_EVEX_L_W_KZ_B, 3, "requires EVEX_B, EVEX_KZ, L and W") \ - ENUM_ENTRY(IC_EVEX_L_W_XS_KZ_B, 4, "requires EVEX_B, EVEX_KZ, L, W and XS prefix") \ - ENUM_ENTRY(IC_EVEX_L_W_XD_KZ_B, 4, "requires EVEX_B, EVEX_KZ, L, W and XD prefix") \ - ENUM_ENTRY(IC_EVEX_L_W_OPSIZE_KZ_B, 4, "requires EVEX_B, EVEX_KZ, L, W and OpSize") \ - ENUM_ENTRY(IC_EVEX_L2_KZ_B, 3, "requires EVEX_B, EVEX_KZ and the L2 prefix") \ - ENUM_ENTRY(IC_EVEX_L2_XS_KZ_B, 4, "requires EVEX_B, EVEX_KZ and the L2 and XS prefix")\ - ENUM_ENTRY(IC_EVEX_L2_XD_KZ_B, 4, "requires EVEX_B, EVEX_KZ and the L2 and XD prefix")\ - ENUM_ENTRY(IC_EVEX_L2_OPSIZE_KZ_B, 4, "requires EVEX_B, EVEX_KZ, L2, and OpSize") \ - ENUM_ENTRY(IC_EVEX_L2_W_KZ_B, 3, "requires EVEX_B, EVEX_KZ, L2 and W") \ - ENUM_ENTRY(IC_EVEX_L2_W_XS_KZ_B, 4, "requires EVEX_B, EVEX_KZ, L2, W and XS prefix") \ - ENUM_ENTRY(IC_EVEX_L2_W_XD_KZ_B, 4, "requires EVEX_B, EVEX_KZ, L2, W and XD prefix") \ - ENUM_ENTRY(IC_EVEX_L2_W_OPSIZE_KZ_B, 4, "requires EVEX_B, EVEX_KZ, L2, W and OpSize") \ - ENUM_ENTRY(IC_EVEX_KZ, 1, "requires an EVEX_KZ prefix") \ - ENUM_ENTRY(IC_EVEX_XS_KZ, 2, "requires EVEX_KZ and the XS prefix") \ - ENUM_ENTRY(IC_EVEX_XD_KZ, 2, "requires EVEX_KZ and the XD prefix") \ - ENUM_ENTRY(IC_EVEX_OPSIZE_KZ, 2, "requires EVEX_KZ and the OpSize prefix") \ - ENUM_ENTRY(IC_EVEX_W_KZ, 3, "requires EVEX_KZ and the W prefix") \ - ENUM_ENTRY(IC_EVEX_W_XS_KZ, 4, "requires EVEX_KZ, W, and XS prefix") \ - ENUM_ENTRY(IC_EVEX_W_XD_KZ, 4, "requires EVEX_KZ, W, and XD prefix") \ - ENUM_ENTRY(IC_EVEX_W_OPSIZE_KZ, 4, "requires EVEX_KZ, W, and OpSize") \ - ENUM_ENTRY(IC_EVEX_L_KZ, 3, "requires EVEX_KZ and the L prefix") \ - ENUM_ENTRY(IC_EVEX_L_XS_KZ, 4, "requires EVEX_KZ and the L and XS prefix")\ - ENUM_ENTRY(IC_EVEX_L_XD_KZ, 4, "requires EVEX_KZ and the L and XD prefix")\ - ENUM_ENTRY(IC_EVEX_L_OPSIZE_KZ, 4, "requires EVEX_KZ, L, and OpSize") \ - ENUM_ENTRY(IC_EVEX_L_W_KZ, 3, "requires EVEX_KZ, L and W") \ - ENUM_ENTRY(IC_EVEX_L_W_XS_KZ, 4, "requires EVEX_KZ, L, W and XS prefix") \ - ENUM_ENTRY(IC_EVEX_L_W_XD_KZ, 4, "requires EVEX_KZ, L, W and XD prefix") \ - ENUM_ENTRY(IC_EVEX_L_W_OPSIZE_KZ, 4, "requires EVEX_KZ, L, W and OpSize") \ - ENUM_ENTRY(IC_EVEX_L2_KZ, 3, "requires EVEX_KZ and the L2 prefix") \ - ENUM_ENTRY(IC_EVEX_L2_XS_KZ, 4, "requires EVEX_KZ and the L2 and XS prefix")\ - ENUM_ENTRY(IC_EVEX_L2_XD_KZ, 4, "requires EVEX_KZ and the L2 and XD prefix")\ - ENUM_ENTRY(IC_EVEX_L2_OPSIZE_KZ, 4, "requires EVEX_KZ, L2, and OpSize") \ - ENUM_ENTRY(IC_EVEX_L2_W_KZ, 3, "requires EVEX_KZ, L2 and W") \ - ENUM_ENTRY(IC_EVEX_L2_W_XS_KZ, 4, "requires EVEX_KZ, L2, W and XS prefix") \ - ENUM_ENTRY(IC_EVEX_L2_W_XD_KZ, 4, "requires EVEX_KZ, L2, W and XD prefix") \ - ENUM_ENTRY(IC_EVEX_L2_W_OPSIZE_KZ, 4, "requires EVEX_KZ, L2, W and OpSize") - -#define ENUM_ENTRY(n, r, d) n, -enum InstructionContext { - INSTRUCTION_CONTEXTS - IC_max -}; -#undef ENUM_ENTRY - -// Opcode types, which determine which decode table to use, both in the Intel -// manual and also for the decoder. -enum OpcodeType { - ONEBYTE = 0, - TWOBYTE = 1, - THREEBYTE_38 = 2, - THREEBYTE_3A = 3, - XOP8_MAP = 4, - XOP9_MAP = 5, - XOPA_MAP = 6 -}; - -// The following structs are used for the hierarchical decode table. After -// determining the instruction's class (i.e., which IC_* constant applies to -// it), the decoder reads the opcode. Some instructions require specific -// values of the ModR/M byte, so the ModR/M byte indexes into the final table. -// -// If a ModR/M byte is not required, "required" is left unset, and the values -// for each instructionID are identical. -typedef uint16_t InstrUID; - -// ModRMDecisionType - describes the type of ModR/M decision, allowing the -// consumer to determine the number of entries in it. -// -// MODRM_ONEENTRY - No matter what the value of the ModR/M byte is, the decoded -// instruction is the same. -// MODRM_SPLITRM - If the ModR/M byte is between 0x00 and 0xbf, the opcode -// corresponds to one instruction; otherwise, it corresponds to -// a different instruction. -// MODRM_SPLITMISC- If the ModR/M byte is between 0x00 and 0xbf, ModR/M byte -// divided by 8 is used to select instruction; otherwise, each -// value of the ModR/M byte could correspond to a different -// instruction. -// MODRM_SPLITREG - ModR/M byte divided by 8 is used to select instruction. This -// corresponds to instructions that use reg field as opcode -// MODRM_FULL - Potentially, each value of the ModR/M byte could correspond -// to a different instruction. -#define MODRMTYPES \ - ENUM_ENTRY(MODRM_ONEENTRY) \ - ENUM_ENTRY(MODRM_SPLITRM) \ - ENUM_ENTRY(MODRM_SPLITMISC) \ - ENUM_ENTRY(MODRM_SPLITREG) \ - ENUM_ENTRY(MODRM_FULL) - -#define ENUM_ENTRY(n) n, -enum ModRMDecisionType { - MODRMTYPES - MODRM_max -}; -#undef ENUM_ENTRY - -#define CASE_ENCODING_RM \ - case ENCODING_RM: \ - case ENCODING_RM_CD2: \ - case ENCODING_RM_CD4: \ - case ENCODING_RM_CD8: \ - case ENCODING_RM_CD16: \ - case ENCODING_RM_CD32: \ - case ENCODING_RM_CD64 - -#define CASE_ENCODING_VSIB \ - case ENCODING_VSIB: \ - case ENCODING_VSIB_CD2: \ - case ENCODING_VSIB_CD4: \ - case ENCODING_VSIB_CD8: \ - case ENCODING_VSIB_CD16: \ - case ENCODING_VSIB_CD32: \ - case ENCODING_VSIB_CD64 - -// Physical encodings of instruction operands. -#define ENCODINGS \ - ENUM_ENTRY(ENCODING_NONE, "") \ - ENUM_ENTRY(ENCODING_REG, "Register operand in ModR/M byte.") \ - ENUM_ENTRY(ENCODING_RM, "R/M operand in ModR/M byte.") \ - ENUM_ENTRY(ENCODING_RM_CD2, "R/M operand with CDisp scaling of 2") \ - ENUM_ENTRY(ENCODING_RM_CD4, "R/M operand with CDisp scaling of 4") \ - ENUM_ENTRY(ENCODING_RM_CD8, "R/M operand with CDisp scaling of 8") \ - ENUM_ENTRY(ENCODING_RM_CD16,"R/M operand with CDisp scaling of 16") \ - ENUM_ENTRY(ENCODING_RM_CD32,"R/M operand with CDisp scaling of 32") \ - ENUM_ENTRY(ENCODING_RM_CD64,"R/M operand with CDisp scaling of 64") \ - ENUM_ENTRY(ENCODING_VSIB, "VSIB operand in ModR/M byte.") \ - ENUM_ENTRY(ENCODING_VSIB_CD2, "VSIB operand with CDisp scaling of 2") \ - ENUM_ENTRY(ENCODING_VSIB_CD4, "VSIB operand with CDisp scaling of 4") \ - ENUM_ENTRY(ENCODING_VSIB_CD8, "VSIB operand with CDisp scaling of 8") \ - ENUM_ENTRY(ENCODING_VSIB_CD16,"VSIB operand with CDisp scaling of 16") \ - ENUM_ENTRY(ENCODING_VSIB_CD32,"VSIB operand with CDisp scaling of 32") \ - ENUM_ENTRY(ENCODING_VSIB_CD64,"VSIB operand with CDisp scaling of 64") \ - ENUM_ENTRY(ENCODING_VVVV, "Register operand in VEX.vvvv byte.") \ - ENUM_ENTRY(ENCODING_WRITEMASK, "Register operand in EVEX.aaa byte.") \ - ENUM_ENTRY(ENCODING_IB, "1-byte immediate") \ - ENUM_ENTRY(ENCODING_IW, "2-byte") \ - ENUM_ENTRY(ENCODING_ID, "4-byte") \ - ENUM_ENTRY(ENCODING_IO, "8-byte") \ - ENUM_ENTRY(ENCODING_RB, "(AL..DIL, R8L..R15L) Register code added to " \ - "the opcode byte") \ - ENUM_ENTRY(ENCODING_RW, "(AX..DI, R8W..R15W)") \ - ENUM_ENTRY(ENCODING_RD, "(EAX..EDI, R8D..R15D)") \ - ENUM_ENTRY(ENCODING_RO, "(RAX..RDI, R8..R15)") \ - ENUM_ENTRY(ENCODING_FP, "Position on floating-point stack in ModR/M " \ - "byte.") \ - \ - ENUM_ENTRY(ENCODING_Iv, "Immediate of operand size") \ - ENUM_ENTRY(ENCODING_Ia, "Immediate of address size") \ - ENUM_ENTRY(ENCODING_IRC, "Immediate for static rounding control") \ - ENUM_ENTRY(ENCODING_Rv, "Register code of operand size added to the " \ - "opcode byte") \ - ENUM_ENTRY(ENCODING_DUP, "Duplicate of another operand; ID is encoded " \ - "in type") \ - ENUM_ENTRY(ENCODING_SI, "Source index; encoded in OpSize/Adsize prefix") \ - ENUM_ENTRY(ENCODING_DI, "Destination index; encoded in prefixes") - -#define ENUM_ENTRY(n, d) n, -enum OperandEncoding { - ENCODINGS - ENCODING_max -}; -#undef ENUM_ENTRY - -// Semantic interpretations of instruction operands. -#define TYPES \ - ENUM_ENTRY(TYPE_NONE, "") \ - ENUM_ENTRY(TYPE_REL, "immediate address") \ - ENUM_ENTRY(TYPE_R8, "1-byte register operand") \ - ENUM_ENTRY(TYPE_R16, "2-byte") \ - ENUM_ENTRY(TYPE_R32, "4-byte") \ - ENUM_ENTRY(TYPE_R64, "8-byte") \ - ENUM_ENTRY(TYPE_IMM, "immediate operand") \ - ENUM_ENTRY(TYPE_IMM3, "1-byte immediate operand between 0 and 7") \ - ENUM_ENTRY(TYPE_IMM5, "1-byte immediate operand between 0 and 31") \ - ENUM_ENTRY(TYPE_AVX512ICC, "1-byte immediate operand for AVX512 icmp") \ - ENUM_ENTRY(TYPE_UIMM8, "1-byte unsigned immediate operand") \ - ENUM_ENTRY(TYPE_M, "Memory operand") \ - ENUM_ENTRY(TYPE_MVSIBX, "Memory operand using XMM index") \ - ENUM_ENTRY(TYPE_MVSIBY, "Memory operand using YMM index") \ - ENUM_ENTRY(TYPE_MVSIBZ, "Memory operand using ZMM index") \ - ENUM_ENTRY(TYPE_SRCIDX, "memory at source index") \ - ENUM_ENTRY(TYPE_DSTIDX, "memory at destination index") \ - ENUM_ENTRY(TYPE_MOFFS, "memory offset (relative to segment base)") \ - ENUM_ENTRY(TYPE_ST, "Position on the floating-point stack") \ - ENUM_ENTRY(TYPE_MM64, "8-byte MMX register") \ - ENUM_ENTRY(TYPE_XMM, "16-byte") \ - ENUM_ENTRY(TYPE_YMM, "32-byte") \ - ENUM_ENTRY(TYPE_ZMM, "64-byte") \ - ENUM_ENTRY(TYPE_VK, "mask register") \ - ENUM_ENTRY(TYPE_SEGMENTREG, "Segment register operand") \ - ENUM_ENTRY(TYPE_DEBUGREG, "Debug register operand") \ - ENUM_ENTRY(TYPE_CONTROLREG, "Control register operand") \ - ENUM_ENTRY(TYPE_BNDR, "MPX bounds register") \ - \ - ENUM_ENTRY(TYPE_Rv, "Register operand of operand size") \ - ENUM_ENTRY(TYPE_RELv, "Immediate address of operand size") \ - ENUM_ENTRY(TYPE_DUP0, "Duplicate of operand 0") \ - ENUM_ENTRY(TYPE_DUP1, "operand 1") \ - ENUM_ENTRY(TYPE_DUP2, "operand 2") \ - ENUM_ENTRY(TYPE_DUP3, "operand 3") \ - ENUM_ENTRY(TYPE_DUP4, "operand 4") \ - -#define ENUM_ENTRY(n, d) n, -enum OperandType { - TYPES - TYPE_max -}; -#undef ENUM_ENTRY - -/// \brief The specification for how to extract and interpret one operand. -struct OperandSpecifier { - uint8_t encoding; - uint8_t type; -}; - -static const unsigned X86_MAX_OPERANDS = 6; - -/// Decoding mode for the Intel disassembler. 16-bit, 32-bit, and 64-bit mode -/// are supported, and represent real mode, IA-32e, and IA-32e in 64-bit mode, -/// respectively. -enum DisassemblerMode { - MODE_16BIT, - MODE_32BIT, - MODE_64BIT -}; - -} // namespace X86Disassembler -} // namespace llvm - -#endif |