aboutsummaryrefslogtreecommitdiff
path: root/llvm/lib/Target/X86/Disassembler
diff options
context:
space:
mode:
authorDimitry Andric <dim@FreeBSD.org>2023-12-09 13:28:42 +0000
committerDimitry Andric <dim@FreeBSD.org>2023-12-09 13:28:42 +0000
commitb1c73532ee8997fe5dfbeb7d223027bdf99758a0 (patch)
tree7d6e51c294ab6719475d660217aa0c0ad0526292 /llvm/lib/Target/X86/Disassembler
parent7fa27ce4a07f19b07799a767fc29416f3b625afb (diff)
Diffstat (limited to 'llvm/lib/Target/X86/Disassembler')
-rw-r--r--llvm/lib/Target/X86/Disassembler/X86Disassembler.cpp151
-rw-r--r--llvm/lib/Target/X86/Disassembler/X86DisassemblerDecoder.h495
2 files changed, 430 insertions, 216 deletions
diff --git a/llvm/lib/Target/X86/Disassembler/X86Disassembler.cpp b/llvm/lib/Target/X86/Disassembler/X86Disassembler.cpp
index 49651da63ecf..d50e6514b86d 100644
--- a/llvm/lib/Target/X86/Disassembler/X86Disassembler.cpp
+++ b/llvm/lib/Target/X86/Disassembler/X86Disassembler.cpp
@@ -150,12 +150,18 @@ static InstrUID decode(OpcodeType type, InstructionContext insnContext,
dec =
&THREEDNOW_MAP_SYM.opcodeDecisions[insnContext].modRMDecisions[opcode];
break;
+ case MAP4:
+ dec = &MAP4_SYM.opcodeDecisions[insnContext].modRMDecisions[opcode];
+ break;
case MAP5:
dec = &MAP5_SYM.opcodeDecisions[insnContext].modRMDecisions[opcode];
break;
case MAP6:
dec = &MAP6_SYM.opcodeDecisions[insnContext].modRMDecisions[opcode];
break;
+ case MAP7:
+ dec = &MAP7_SYM.opcodeDecisions[insnContext].modRMDecisions[opcode];
+ break;
}
switch (dec->modrm_type) {
@@ -194,7 +200,7 @@ template <typename T> static bool consume(InternalInstruction *insn, T &ptr) {
uint64_t offset = insn->readerCursor - insn->startLocation;
if (offset + sizeof(T) > r.size())
return true;
- ptr = support::endian::read<T>(&r[offset], support::little);
+ ptr = support::endian::read<T>(&r[offset], llvm::endianness::little);
insn->readerCursor += sizeof(T);
return false;
}
@@ -203,6 +209,10 @@ static bool isREX(struct InternalInstruction *insn, uint8_t prefix) {
return insn->mode == MODE_64BIT && prefix >= 0x40 && prefix <= 0x4f;
}
+static bool isREX2(struct InternalInstruction *insn, uint8_t prefix) {
+ return insn->mode == MODE_64BIT && prefix == 0xd5;
+}
+
// Consumes all of an instruction's prefix bytes, and marks the
// instruction as having them. Also sets the instruction's default operand,
// address, and other relevant data sizes to report operands correctly.
@@ -334,8 +344,7 @@ static int readPrefixes(struct InternalInstruction *insn) {
return -1;
}
- if ((insn->mode == MODE_64BIT || (byte1 & 0xc0) == 0xc0) &&
- ((~byte1 & 0x8) == 0x8) && ((byte2 & 0x4) == 0x4)) {
+ if ((insn->mode == MODE_64BIT || (byte1 & 0xc0) == 0xc0)) {
insn->vectorExtensionType = TYPE_EVEX;
} else {
--insn->readerCursor; // unconsume byte1
@@ -354,13 +363,19 @@ static int readPrefixes(struct InternalInstruction *insn) {
return -1;
}
- // We simulate the REX prefix for simplicity's sake
if (insn->mode == MODE_64BIT) {
+ // We simulate the REX prefix for simplicity's sake
insn->rexPrefix = 0x40 |
(wFromEVEX3of4(insn->vectorExtensionPrefix[2]) << 3) |
(rFromEVEX2of4(insn->vectorExtensionPrefix[1]) << 2) |
(xFromEVEX2of4(insn->vectorExtensionPrefix[1]) << 1) |
(bFromEVEX2of4(insn->vectorExtensionPrefix[1]) << 0);
+
+ // We simulate the REX2 prefix for simplicity's sake
+ insn->rex2ExtensionPrefix[1] =
+ (r2FromEVEX2of4(insn->vectorExtensionPrefix[1]) << 6) |
+ (x2FromEVEX3of4(insn->vectorExtensionPrefix[2]) << 5) |
+ (b2FromEVEX2of4(insn->vectorExtensionPrefix[1]) << 4);
}
LLVM_DEBUG(
@@ -471,6 +486,23 @@ static int readPrefixes(struct InternalInstruction *insn) {
insn->vectorExtensionPrefix[1],
insn->vectorExtensionPrefix[2]));
}
+ } else if (isREX2(insn, byte)) {
+ uint8_t byte1;
+ if (peek(insn, byte1)) {
+ LLVM_DEBUG(dbgs() << "Couldn't read second byte of REX2");
+ return -1;
+ }
+ insn->rex2ExtensionPrefix[0] = byte;
+ consume(insn, insn->rex2ExtensionPrefix[1]);
+
+ // We simulate the REX prefix for simplicity's sake
+ insn->rexPrefix = 0x40 | (wFromREX2(insn->rex2ExtensionPrefix[1]) << 3) |
+ (rFromREX2(insn->rex2ExtensionPrefix[1]) << 2) |
+ (xFromREX2(insn->rex2ExtensionPrefix[1]) << 1) |
+ (bFromREX2(insn->rex2ExtensionPrefix[1]) << 0);
+ LLVM_DEBUG(dbgs() << format("Found REX2 prefix 0x%hhx 0x%hhx",
+ insn->rex2ExtensionPrefix[0],
+ insn->rex2ExtensionPrefix[1]));
} else if (isREX(insn, byte)) {
if (peek(insn, nextByte))
return -1;
@@ -529,7 +561,8 @@ static int readSIB(struct InternalInstruction *insn) {
if (consume(insn, insn->sib))
return -1;
- index = indexFromSIB(insn->sib) | (xFromREX(insn->rexPrefix) << 3);
+ index = indexFromSIB(insn->sib) | (xFromREX(insn->rexPrefix) << 3) |
+ (x2FromREX2(insn->rex2ExtensionPrefix[1]) << 4);
if (index == 0x4) {
insn->sibIndex = SIB_INDEX_NONE;
@@ -539,7 +572,8 @@ static int readSIB(struct InternalInstruction *insn) {
insn->sibScale = 1 << scaleFromSIB(insn->sib);
- base = baseFromSIB(insn->sib) | (bFromREX(insn->rexPrefix) << 3);
+ base = baseFromSIB(insn->sib) | (bFromREX(insn->rexPrefix) << 3) |
+ (b2FromREX2(insn->rex2ExtensionPrefix[1]) << 4);
switch (base) {
case 0x5:
@@ -601,7 +635,7 @@ static int readDisplacement(struct InternalInstruction *insn) {
// Consumes all addressing information (ModR/M byte, SIB byte, and displacement.
static int readModRM(struct InternalInstruction *insn) {
- uint8_t mod, rm, reg, evexrm;
+ uint8_t mod, rm, reg;
LLVM_DEBUG(dbgs() << "readModRM()");
if (insn->consumedModRM)
@@ -633,14 +667,13 @@ static int readModRM(struct InternalInstruction *insn) {
break;
}
- reg |= rFromREX(insn->rexPrefix) << 3;
- rm |= bFromREX(insn->rexPrefix) << 3;
+ reg |= (rFromREX(insn->rexPrefix) << 3) |
+ (r2FromREX2(insn->rex2ExtensionPrefix[1]) << 4);
+ rm |= (bFromREX(insn->rexPrefix) << 3) |
+ (b2FromREX2(insn->rex2ExtensionPrefix[1]) << 4);
- evexrm = 0;
- if (insn->vectorExtensionType == TYPE_EVEX && insn->mode == MODE_64BIT) {
+ if (insn->vectorExtensionType == TYPE_EVEX && insn->mode == MODE_64BIT)
reg |= r2FromEVEX2of4(insn->vectorExtensionPrefix[1]) << 4;
- evexrm = xFromEVEX2of4(insn->vectorExtensionPrefix[1]) << 4;
- }
insn->reg = (Reg)(insn->regBase + reg);
@@ -728,7 +761,7 @@ static int readModRM(struct InternalInstruction *insn) {
break;
case 0x3:
insn->eaDisplacement = EA_DISP_NONE;
- insn->eaBase = (EABase)(insn->eaRegBase + rm + evexrm);
+ insn->eaBase = (EABase)(insn->eaRegBase + rm);
break;
}
break;
@@ -738,7 +771,7 @@ static int readModRM(struct InternalInstruction *insn) {
return 0;
}
-#define GENERIC_FIXUP_FUNC(name, base, prefix, mask) \
+#define GENERIC_FIXUP_FUNC(name, base, prefix) \
static uint16_t name(struct InternalInstruction *insn, OperandType type, \
uint8_t index, uint8_t *valid) { \
*valid = 1; \
@@ -750,28 +783,15 @@ 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) { \
+ if (insn->rexPrefix && index >= 4 && index <= 7) \
return prefix##_SPL + (index - 4); \
- } else { \
+ else \
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; \
@@ -821,8 +841,8 @@ static int readModRM(struct InternalInstruction *insn) {
// @param valid - The address of a uint8_t. The target is set to 1 if the
// field is valid for the register class; 0 if not.
// @return - The proper value.
-GENERIC_FIXUP_FUNC(fixupRegValue, insn->regBase, MODRM_REG, 0x1f)
-GENERIC_FIXUP_FUNC(fixupRMValue, insn->eaRegBase, EA_REG, 0xf)
+GENERIC_FIXUP_FUNC(fixupRegValue, insn->regBase, MODRM_REG)
+GENERIC_FIXUP_FUNC(fixupRMValue, insn->eaRegBase, EA_REG)
// Consult an operand specifier to determine which of the fixup*Value functions
// to use in correcting readModRM()'ss interpretation.
@@ -852,8 +872,31 @@ static int fixupReg(struct InternalInstruction *insn,
if (!valid)
return -1;
break;
- case ENCODING_SIB:
CASE_ENCODING_RM:
+ if (insn->vectorExtensionType == TYPE_EVEX && insn->mode == MODE_64BIT &&
+ modFromModRM(insn->modRM) == 3) {
+ // EVEX_X can extend the register id to 32 for a non-GPR register that is
+ // encoded in RM.
+ // mode : MODE_64_BIT
+ // Only 8 vector registers are available in 32 bit mode
+ // mod : 3
+ // RM encodes a register
+ switch (op->type) {
+ case TYPE_Rv:
+ case TYPE_R8:
+ case TYPE_R16:
+ case TYPE_R32:
+ case TYPE_R64:
+ break;
+ default:
+ insn->eaBase =
+ (EABase)(insn->eaBase +
+ (xFromEVEX2of4(insn->vectorExtensionPrefix[1]) << 4));
+ break;
+ }
+ }
+ [[fallthrough]];
+ case ENCODING_SIB:
if (insn->eaBase >= insn->eaRegBase) {
insn->eaBase = (EABase)fixupRMValue(
insn, (OperandType)op->type, insn->eaBase - insn->eaRegBase, &valid);
@@ -889,6 +932,9 @@ static bool readOpcode(struct InternalInstruction *insn) {
case VEX_LOB_0F3A:
insn->opcodeType = THREEBYTE_3A;
return consume(insn, insn->opcode);
+ case VEX_LOB_MAP4:
+ insn->opcodeType = MAP4;
+ return consume(insn, insn->opcode);
case VEX_LOB_MAP5:
insn->opcodeType = MAP5;
return consume(insn, insn->opcode);
@@ -918,6 +964,9 @@ static bool readOpcode(struct InternalInstruction *insn) {
case VEX_LOB_MAP6:
insn->opcodeType = MAP6;
return consume(insn, insn->opcode);
+ case VEX_LOB_MAP7:
+ insn->opcodeType = MAP7;
+ return consume(insn, insn->opcode);
}
} else if (insn->vectorExtensionType == TYPE_VEX_2B) {
insn->opcodeType = TWOBYTE;
@@ -939,6 +988,10 @@ static bool readOpcode(struct InternalInstruction *insn) {
insn->opcodeType = XOPA_MAP;
return consume(insn, insn->opcode);
}
+ } else if (mFromREX2(insn->rex2ExtensionPrefix[1])) {
+ // m bit indicates opcode map 1
+ insn->opcodeType = TWOBYTE;
+ return consume(insn, insn->opcode);
}
if (consume(insn, current))
@@ -1053,12 +1106,18 @@ static int getInstructionIDWithAttrMask(uint16_t *instructionID,
case THREEDNOW_MAP:
decision = &THREEDNOW_MAP_SYM;
break;
+ case MAP4:
+ decision = &MAP4_SYM;
+ break;
case MAP5:
decision = &MAP5_SYM;
break;
case MAP6:
decision = &MAP6_SYM;
break;
+ case MAP7:
+ decision = &MAP7_SYM;
+ break;
}
if (decision->opcodeDecisions[insnCtx]
@@ -1207,6 +1266,11 @@ static int getInstructionID(struct InternalInstruction *insn,
attrMask &= ~ATTR_ADSIZE;
}
+ // Absolute jump and pushp/popp need special handling
+ if (insn->rex2ExtensionPrefix[0] == 0xd5 && insn->opcodeType == ONEBYTE &&
+ (insn->opcode == 0xA1 || (insn->opcode & 0xf0) == 0x50))
+ attrMask |= ATTR_REX2;
+
if (insn->mode == MODE_16BIT) {
// JCXZ/JECXZ need special handling for 16-bit mode because the meaning
// of the AdSize prefix is inverted w.r.t. 32-bit mode.
@@ -1379,10 +1443,16 @@ static int readOpcodeRegister(struct InternalInstruction *insn, uint8_t size) {
if (size == 0)
size = insn->registerSize;
+ auto setOpcodeRegister = [&](unsigned base) {
+ insn->opcodeRegister =
+ (Reg)(base + ((bFromREX(insn->rexPrefix) << 3) |
+ (b2FromREX2(insn->rex2ExtensionPrefix[1]) << 4) |
+ (insn->opcode & 7)));
+ };
+
switch (size) {
case 1:
- insn->opcodeRegister = (Reg)(
- MODRM_REG_AL + ((bFromREX(insn->rexPrefix) << 3) | (insn->opcode & 7)));
+ setOpcodeRegister(MODRM_REG_AL);
if (insn->rexPrefix && insn->opcodeRegister >= MODRM_REG_AL + 0x4 &&
insn->opcodeRegister < MODRM_REG_AL + 0x8) {
insn->opcodeRegister =
@@ -1391,18 +1461,13 @@ static int readOpcodeRegister(struct InternalInstruction *insn, uint8_t size) {
break;
case 2:
- insn->opcodeRegister = (Reg)(
- MODRM_REG_AX + ((bFromREX(insn->rexPrefix) << 3) | (insn->opcode & 7)));
+ setOpcodeRegister(MODRM_REG_AX);
break;
case 4:
- insn->opcodeRegister =
- (Reg)(MODRM_REG_EAX +
- ((bFromREX(insn->rexPrefix) << 3) | (insn->opcode & 7)));
+ setOpcodeRegister(MODRM_REG_EAX);
break;
case 8:
- insn->opcodeRegister =
- (Reg)(MODRM_REG_RAX +
- ((bFromREX(insn->rexPrefix) << 3) | (insn->opcode & 7)));
+ setOpcodeRegister(MODRM_REG_RAX);
break;
}
diff --git a/llvm/lib/Target/X86/Disassembler/X86DisassemblerDecoder.h b/llvm/lib/Target/X86/Disassembler/X86DisassemblerDecoder.h
index 95d3c8ede366..decc45091941 100644
--- a/llvm/lib/Target/X86/Disassembler/X86DisassemblerDecoder.h
+++ b/llvm/lib/Target/X86/Disassembler/X86DisassemblerDecoder.h
@@ -20,187 +20,332 @@
namespace llvm {
namespace X86Disassembler {
-
-// Accessor functions for various fields of an Intel instruction
-#define modFromModRM(modRM) (((modRM) & 0xc0) >> 6)
-#define regFromModRM(modRM) (((modRM) & 0x38) >> 3)
-#define rmFromModRM(modRM) ((modRM) & 0x7)
-#define scaleFromSIB(sib) (((sib) & 0xc0) >> 6)
-#define indexFromSIB(sib) (((sib) & 0x38) >> 3)
-#define baseFromSIB(sib) ((sib) & 0x7)
-#define wFromREX(rex) (((rex) & 0x8) >> 3)
-#define rFromREX(rex) (((rex) & 0x4) >> 2)
-#define xFromREX(rex) (((rex) & 0x2) >> 1)
-#define bFromREX(rex) ((rex) & 0x1)
-
-#define rFromEVEX2of4(evex) (((~(evex)) & 0x80) >> 7)
-#define xFromEVEX2of4(evex) (((~(evex)) & 0x40) >> 6)
-#define bFromEVEX2of4(evex) (((~(evex)) & 0x20) >> 5)
-#define r2FromEVEX2of4(evex) (((~(evex)) & 0x10) >> 4)
-#define mmmFromEVEX2of4(evex) ((evex) & 0x7)
-#define wFromEVEX3of4(evex) (((evex) & 0x80) >> 7)
-#define vvvvFromEVEX3of4(evex) (((~(evex)) & 0x78) >> 3)
-#define ppFromEVEX3of4(evex) ((evex) & 0x3)
-#define zFromEVEX4of4(evex) (((evex) & 0x80) >> 7)
-#define l2FromEVEX4of4(evex) (((evex) & 0x40) >> 6)
-#define lFromEVEX4of4(evex) (((evex) & 0x20) >> 5)
-#define bFromEVEX4of4(evex) (((evex) & 0x10) >> 4)
-#define v2FromEVEX4of4(evex) (((~evex) & 0x8) >> 3)
-#define aaaFromEVEX4of4(evex) ((evex) & 0x7)
-
-#define rFromVEX2of3(vex) (((~(vex)) & 0x80) >> 7)
-#define xFromVEX2of3(vex) (((~(vex)) & 0x40) >> 6)
-#define bFromVEX2of3(vex) (((~(vex)) & 0x20) >> 5)
-#define mmmmmFromVEX2of3(vex) ((vex) & 0x1f)
-#define wFromVEX3of3(vex) (((vex) & 0x80) >> 7)
-#define vvvvFromVEX3of3(vex) (((~(vex)) & 0x78) >> 3)
-#define lFromVEX3of3(vex) (((vex) & 0x4) >> 2)
-#define ppFromVEX3of3(vex) ((vex) & 0x3)
-
-#define rFromVEX2of2(vex) (((~(vex)) & 0x80) >> 7)
-#define vvvvFromVEX2of2(vex) (((~(vex)) & 0x78) >> 3)
-#define lFromVEX2of2(vex) (((vex) & 0x4) >> 2)
-#define ppFromVEX2of2(vex) ((vex) & 0x3)
-
-#define rFromXOP2of3(xop) (((~(xop)) & 0x80) >> 7)
-#define xFromXOP2of3(xop) (((~(xop)) & 0x40) >> 6)
-#define bFromXOP2of3(xop) (((~(xop)) & 0x20) >> 5)
-#define mmmmmFromXOP2of3(xop) ((xop) & 0x1f)
-#define wFromXOP3of3(xop) (((xop) & 0x80) >> 7)
-#define vvvvFromXOP3of3(vex) (((~(vex)) & 0x78) >> 3)
-#define lFromXOP3of3(xop) (((xop) & 0x4) >> 2)
-#define ppFromXOP3of3(xop) ((xop) & 0x3)
+// Helper macros
+#define bitFromOffset0(val) ((val) & 0x1)
+#define bitFromOffset1(val) (((val) >> 1) & 0x1)
+#define bitFromOffset2(val) (((val) >> 2) & 0x1)
+#define bitFromOffset3(val) (((val) >> 3) & 0x1)
+#define bitFromOffset4(val) (((val) >> 4) & 0x1)
+#define bitFromOffset5(val) (((val) >> 5) & 0x1)
+#define bitFromOffset6(val) (((val) >> 6) & 0x1)
+#define bitFromOffset7(val) (((val) >> 7) & 0x1)
+#define twoBitsFromOffset0(val) ((val) & 0x3)
+#define twoBitsFromOffset6(val) (((val) >> 6) & 0x3)
+#define threeBitsFromOffset0(val) ((val) & 0x7)
+#define threeBitsFromOffset3(val) (((val) >> 3) & 0x7)
+#define fiveBitsFromOffset0(val) ((val) & 0x1f)
+#define invertedBitFromOffset2(val) (((~(val)) >> 2) & 0x1)
+#define invertedBitFromOffset3(val) (((~(val)) >> 3) & 0x1)
+#define invertedBitFromOffset4(val) (((~(val)) >> 4) & 0x1)
+#define invertedBitFromOffset5(val) (((~(val)) >> 5) & 0x1)
+#define invertedBitFromOffset6(val) (((~(val)) >> 6) & 0x1)
+#define invertedBitFromOffset7(val) (((~(val)) >> 7) & 0x1)
+#define invertedFourBitsFromOffset3(val) (((~(val)) >> 3) & 0xf)
+// MOD/RM
+#define modFromModRM(modRM) twoBitsFromOffset6(modRM)
+#define regFromModRM(modRM) threeBitsFromOffset3(modRM)
+#define rmFromModRM(modRM) threeBitsFromOffset0(modRM)
+// SIB
+#define scaleFromSIB(sib) twoBitsFromOffset6(sib)
+#define indexFromSIB(sib) threeBitsFromOffset3(sib)
+#define baseFromSIB(sib) threeBitsFromOffset0(sib)
+// REX
+#define wFromREX(rex) bitFromOffset3(rex)
+#define rFromREX(rex) bitFromOffset2(rex)
+#define xFromREX(rex) bitFromOffset1(rex)
+#define bFromREX(rex) bitFromOffset0(rex)
+// REX2
+#define mFromREX2(rex2) bitFromOffset7(rex2)
+#define r2FromREX2(rex2) bitFromOffset6(rex2)
+#define x2FromREX2(rex2) bitFromOffset5(rex2)
+#define b2FromREX2(rex2) bitFromOffset4(rex2)
+#define wFromREX2(rex2) bitFromOffset3(rex2)
+#define rFromREX2(rex2) bitFromOffset2(rex2)
+#define xFromREX2(rex2) bitFromOffset1(rex2)
+#define bFromREX2(rex2) bitFromOffset0(rex2)
+// XOP
+#define rFromXOP2of3(xop) invertedBitFromOffset7(xop)
+#define xFromXOP2of3(xop) invertedBitFromOffset6(xop)
+#define bFromXOP2of3(xop) invertedBitFromOffset5(xop)
+#define mmmmmFromXOP2of3(xop) fiveBitsFromOffset0(xop)
+#define wFromXOP3of3(xop) bitFromOffset7(xop)
+#define vvvvFromXOP3of3(xop) invertedFourBitsFromOffset3(xop)
+#define lFromXOP3of3(xop) bitFromOffset2(xop)
+#define ppFromXOP3of3(xop) twoBitsFromOffset0(xop)
+// VEX2
+#define rFromVEX2of2(vex) invertedBitFromOffset7(vex)
+#define vvvvFromVEX2of2(vex) invertedFourBitsFromOffset3(vex)
+#define lFromVEX2of2(vex) bitFromOffset2(vex)
+#define ppFromVEX2of2(vex) twoBitsFromOffset0(vex)
+// VEX3
+#define rFromVEX2of3(vex) invertedBitFromOffset7(vex)
+#define xFromVEX2of3(vex) invertedBitFromOffset6(vex)
+#define bFromVEX2of3(vex) invertedBitFromOffset5(vex)
+#define mmmmmFromVEX2of3(vex) fiveBitsFromOffset0(vex)
+#define wFromVEX3of3(vex) bitFromOffset7(vex)
+#define vvvvFromVEX3of3(vex) invertedFourBitsFromOffset3(vex)
+#define lFromVEX3of3(vex) bitFromOffset2(vex)
+#define ppFromVEX3of3(vex) twoBitsFromOffset0(vex)
+// EVEX
+#define rFromEVEX2of4(evex) invertedBitFromOffset7(evex)
+#define xFromEVEX2of4(evex) invertedBitFromOffset6(evex)
+#define bFromEVEX2of4(evex) invertedBitFromOffset5(evex)
+#define r2FromEVEX2of4(evex) invertedBitFromOffset4(evex)
+#define b2FromEVEX2of4(evex) bitFromOffset3(evex)
+#define mmmFromEVEX2of4(evex) threeBitsFromOffset0(evex)
+#define wFromEVEX3of4(evex) bitFromOffset7(evex)
+#define vvvvFromEVEX3of4(evex) invertedFourBitsFromOffset3(evex)
+#define x2FromEVEX3of4(evex) invertedBitFromOffset2(evex)
+#define ppFromEVEX3of4(evex) twoBitsFromOffset0(evex)
+#define zFromEVEX4of4(evex) bitFromOffset7(evex)
+#define l2FromEVEX4of4(evex) bitFromOffset6(evex)
+#define lFromEVEX4of4(evex) bitFromOffset5(evex)
+#define bFromEVEX4of4(evex) bitFromOffset4(evex)
+#define v2FromEVEX4of4(evex) invertedBitFromOffset3(evex)
+#define aaaFromEVEX4of4(evex) threeBitsFromOffset0(evex)
// These enums represent Intel registers for use by the decoder.
-#define REGS_8BIT \
- ENTRY(AL) \
- ENTRY(CL) \
- ENTRY(DL) \
- ENTRY(BL) \
- ENTRY(AH) \
- ENTRY(CH) \
- ENTRY(DH) \
- ENTRY(BH) \
- ENTRY(R8B) \
- ENTRY(R9B) \
- ENTRY(R10B) \
- ENTRY(R11B) \
- ENTRY(R12B) \
- ENTRY(R13B) \
- ENTRY(R14B) \
- ENTRY(R15B) \
- ENTRY(SPL) \
- ENTRY(BPL) \
- ENTRY(SIL) \
+#define REGS_8BIT \
+ ENTRY(AL) \
+ ENTRY(CL) \
+ ENTRY(DL) \
+ ENTRY(BL) \
+ ENTRY(AH) \
+ ENTRY(CH) \
+ ENTRY(DH) \
+ ENTRY(BH) \
+ ENTRY(R8B) \
+ ENTRY(R9B) \
+ ENTRY(R10B) \
+ ENTRY(R11B) \
+ ENTRY(R12B) \
+ ENTRY(R13B) \
+ ENTRY(R14B) \
+ ENTRY(R15B) \
+ ENTRY(R16B) \
+ ENTRY(R17B) \
+ ENTRY(R18B) \
+ ENTRY(R19B) \
+ ENTRY(R20B) \
+ ENTRY(R21B) \
+ ENTRY(R22B) \
+ ENTRY(R23B) \
+ ENTRY(R24B) \
+ ENTRY(R25B) \
+ ENTRY(R26B) \
+ ENTRY(R27B) \
+ ENTRY(R28B) \
+ ENTRY(R29B) \
+ ENTRY(R30B) \
+ ENTRY(R31B) \
+ ENTRY(SPL) \
+ ENTRY(BPL) \
+ ENTRY(SIL) \
ENTRY(DIL)
-#define EA_BASES_16BIT \
- ENTRY(BX_SI) \
- ENTRY(BX_DI) \
- ENTRY(BP_SI) \
- ENTRY(BP_DI) \
- ENTRY(SI) \
- ENTRY(DI) \
- ENTRY(BP) \
- ENTRY(BX) \
- ENTRY(R8W) \
- ENTRY(R9W) \
- ENTRY(R10W) \
- ENTRY(R11W) \
- ENTRY(R12W) \
- ENTRY(R13W) \
- ENTRY(R14W) \
- ENTRY(R15W)
+#define EA_BASES_16BIT \
+ ENTRY(BX_SI) \
+ ENTRY(BX_DI) \
+ ENTRY(BP_SI) \
+ ENTRY(BP_DI) \
+ ENTRY(SI) \
+ ENTRY(DI) \
+ ENTRY(BP) \
+ ENTRY(BX) \
+ ENTRY(R8W) \
+ ENTRY(R9W) \
+ ENTRY(R10W) \
+ ENTRY(R11W) \
+ ENTRY(R12W) \
+ ENTRY(R13W) \
+ ENTRY(R14W) \
+ ENTRY(R15W) \
+ ENTRY(R16W) \
+ ENTRY(R17W) \
+ ENTRY(R18W) \
+ ENTRY(R19W) \
+ ENTRY(R20W) \
+ ENTRY(R21W) \
+ ENTRY(R22W) \
+ ENTRY(R23W) \
+ ENTRY(R24W) \
+ ENTRY(R25W) \
+ ENTRY(R26W) \
+ ENTRY(R27W) \
+ ENTRY(R28W) \
+ ENTRY(R29W) \
+ ENTRY(R30W) \
+ ENTRY(R31W)
-#define REGS_16BIT \
- ENTRY(AX) \
- ENTRY(CX) \
- ENTRY(DX) \
- ENTRY(BX) \
- ENTRY(SP) \
- ENTRY(BP) \
- ENTRY(SI) \
- ENTRY(DI) \
- ENTRY(R8W) \
- ENTRY(R9W) \
- ENTRY(R10W) \
- ENTRY(R11W) \
- ENTRY(R12W) \
- ENTRY(R13W) \
- ENTRY(R14W) \
- ENTRY(R15W)
+#define REGS_16BIT \
+ ENTRY(AX) \
+ ENTRY(CX) \
+ ENTRY(DX) \
+ ENTRY(BX) \
+ ENTRY(SP) \
+ ENTRY(BP) \
+ ENTRY(SI) \
+ ENTRY(DI) \
+ ENTRY(R8W) \
+ ENTRY(R9W) \
+ ENTRY(R10W) \
+ ENTRY(R11W) \
+ ENTRY(R12W) \
+ ENTRY(R13W) \
+ ENTRY(R14W) \
+ ENTRY(R15W) \
+ ENTRY(R16W) \
+ ENTRY(R17W) \
+ ENTRY(R18W) \
+ ENTRY(R19W) \
+ ENTRY(R20W) \
+ ENTRY(R21W) \
+ ENTRY(R22W) \
+ ENTRY(R23W) \
+ ENTRY(R24W) \
+ ENTRY(R25W) \
+ ENTRY(R26W) \
+ ENTRY(R27W) \
+ ENTRY(R28W) \
+ ENTRY(R29W) \
+ ENTRY(R30W) \
+ ENTRY(R31W)
-#define EA_BASES_32BIT \
- ENTRY(EAX) \
- ENTRY(ECX) \
- ENTRY(EDX) \
- ENTRY(EBX) \
- ENTRY(sib) \
- ENTRY(EBP) \
- ENTRY(ESI) \
- ENTRY(EDI) \
- ENTRY(R8D) \
- ENTRY(R9D) \
- ENTRY(R10D) \
- ENTRY(R11D) \
- ENTRY(R12D) \
- ENTRY(R13D) \
- ENTRY(R14D) \
- ENTRY(R15D)
+#define EA_BASES_32BIT \
+ ENTRY(EAX) \
+ ENTRY(ECX) \
+ ENTRY(EDX) \
+ ENTRY(EBX) \
+ ENTRY(sib) \
+ ENTRY(EBP) \
+ ENTRY(ESI) \
+ ENTRY(EDI) \
+ ENTRY(R8D) \
+ ENTRY(R9D) \
+ ENTRY(R10D) \
+ ENTRY(R11D) \
+ ENTRY(R12D) \
+ ENTRY(R13D) \
+ ENTRY(R14D) \
+ ENTRY(R15D) \
+ ENTRY(R16D) \
+ ENTRY(R17D) \
+ ENTRY(R18D) \
+ ENTRY(R19D) \
+ ENTRY(R20D) \
+ ENTRY(R21D) \
+ ENTRY(R22D) \
+ ENTRY(R23D) \
+ ENTRY(R24D) \
+ ENTRY(R25D) \
+ ENTRY(R26D) \
+ ENTRY(R27D) \
+ ENTRY(R28D) \
+ ENTRY(R29D) \
+ ENTRY(R30D) \
+ ENTRY(R31D)
-#define REGS_32BIT \
- ENTRY(EAX) \
- ENTRY(ECX) \
- ENTRY(EDX) \
- ENTRY(EBX) \
- ENTRY(ESP) \
- ENTRY(EBP) \
- ENTRY(ESI) \
- ENTRY(EDI) \
- ENTRY(R8D) \
- ENTRY(R9D) \
- ENTRY(R10D) \
- ENTRY(R11D) \
- ENTRY(R12D) \
- ENTRY(R13D) \
- ENTRY(R14D) \
- ENTRY(R15D)
+#define REGS_32BIT \
+ ENTRY(EAX) \
+ ENTRY(ECX) \
+ ENTRY(EDX) \
+ ENTRY(EBX) \
+ ENTRY(ESP) \
+ ENTRY(EBP) \
+ ENTRY(ESI) \
+ ENTRY(EDI) \
+ ENTRY(R8D) \
+ ENTRY(R9D) \
+ ENTRY(R10D) \
+ ENTRY(R11D) \
+ ENTRY(R12D) \
+ ENTRY(R13D) \
+ ENTRY(R14D) \
+ ENTRY(R15D) \
+ ENTRY(R16D) \
+ ENTRY(R17D) \
+ ENTRY(R18D) \
+ ENTRY(R19D) \
+ ENTRY(R20D) \
+ ENTRY(R21D) \
+ ENTRY(R22D) \
+ ENTRY(R23D) \
+ ENTRY(R24D) \
+ ENTRY(R25D) \
+ ENTRY(R26D) \
+ ENTRY(R27D) \
+ ENTRY(R28D) \
+ ENTRY(R29D) \
+ ENTRY(R30D) \
+ ENTRY(R31D)
-#define EA_BASES_64BIT \
- ENTRY(RAX) \
- ENTRY(RCX) \
- ENTRY(RDX) \
- ENTRY(RBX) \
- ENTRY(sib64) \
- ENTRY(RBP) \
- ENTRY(RSI) \
- ENTRY(RDI) \
- ENTRY(R8) \
- ENTRY(R9) \
- ENTRY(R10) \
- ENTRY(R11) \
- ENTRY(R12) \
- ENTRY(R13) \
- ENTRY(R14) \
- ENTRY(R15)
+#define EA_BASES_64BIT \
+ ENTRY(RAX) \
+ ENTRY(RCX) \
+ ENTRY(RDX) \
+ ENTRY(RBX) \
+ ENTRY(sib64) \
+ ENTRY(RBP) \
+ ENTRY(RSI) \
+ ENTRY(RDI) \
+ ENTRY(R8) \
+ ENTRY(R9) \
+ ENTRY(R10) \
+ ENTRY(R11) \
+ ENTRY(R12) \
+ ENTRY(R13) \
+ ENTRY(R14) \
+ ENTRY(R15) \
+ ENTRY(R16) \
+ ENTRY(R17) \
+ ENTRY(R18) \
+ ENTRY(R19) \
+ ENTRY(R20) \
+ ENTRY(R21) \
+ ENTRY(R22) \
+ ENTRY(R23) \
+ ENTRY(R24) \
+ ENTRY(R25) \
+ ENTRY(R26) \
+ ENTRY(R27) \
+ ENTRY(R28) \
+ ENTRY(R29) \
+ ENTRY(R30) \
+ ENTRY(R31)
-#define REGS_64BIT \
- ENTRY(RAX) \
- ENTRY(RCX) \
- ENTRY(RDX) \
- ENTRY(RBX) \
- ENTRY(RSP) \
- ENTRY(RBP) \
- ENTRY(RSI) \
- ENTRY(RDI) \
- ENTRY(R8) \
- ENTRY(R9) \
- ENTRY(R10) \
- ENTRY(R11) \
- ENTRY(R12) \
- ENTRY(R13) \
- ENTRY(R14) \
- ENTRY(R15)
+#define REGS_64BIT \
+ ENTRY(RAX) \
+ ENTRY(RCX) \
+ ENTRY(RDX) \
+ ENTRY(RBX) \
+ ENTRY(RSP) \
+ ENTRY(RBP) \
+ ENTRY(RSI) \
+ ENTRY(RDI) \
+ ENTRY(R8) \
+ ENTRY(R9) \
+ ENTRY(R10) \
+ ENTRY(R11) \
+ ENTRY(R12) \
+ ENTRY(R13) \
+ ENTRY(R14) \
+ ENTRY(R15) \
+ ENTRY(R16) \
+ ENTRY(R17) \
+ ENTRY(R18) \
+ ENTRY(R19) \
+ ENTRY(R20) \
+ ENTRY(R21) \
+ ENTRY(R22) \
+ ENTRY(R23) \
+ ENTRY(R24) \
+ ENTRY(R25) \
+ ENTRY(R26) \
+ ENTRY(R27) \
+ ENTRY(R28) \
+ ENTRY(R29) \
+ ENTRY(R30) \
+ ENTRY(R31)
#define REGS_MMX \
ENTRY(MM0) \
@@ -483,8 +628,10 @@ enum VEXLeadingOpcodeByte {
VEX_LOB_0F = 0x1,
VEX_LOB_0F38 = 0x2,
VEX_LOB_0F3A = 0x3,
+ VEX_LOB_MAP4 = 0x4,
VEX_LOB_MAP5 = 0x5,
- VEX_LOB_MAP6 = 0x6
+ VEX_LOB_MAP6 = 0x6,
+ VEX_LOB_MAP7 = 0x7
};
enum XOPMapSelect {
@@ -539,6 +686,8 @@ struct InternalInstruction {
uint8_t vectorExtensionPrefix[4];
// The type of the vector extension prefix
VectorExtensionType vectorExtensionType;
+ // The value of the REX2 prefix, if present
+ uint8_t rex2ExtensionPrefix[2];
// The value of the REX prefix, if present
uint8_t rexPrefix;
// The segment override type