23 #include "X86GenDisassemblerTables.inc"
29 #define debug(s) do { x86DisassemblerDebug(__FILE__, __LINE__, s); } while (0)
31 #define debug(s) do { } while (0)
94 modrm_type != MODRM_ONEENTRY;
115 dec = &
ONEBYTE_SYM.opcodeDecisions[insnContext].modRMDecisions[opcode];
118 dec = &
TWOBYTE_SYM.opcodeDecisions[insnContext].modRMDecisions[opcode];
121 dec = &
THREEBYTE38_SYM.opcodeDecisions[insnContext].modRMDecisions[opcode];
124 dec = &
THREEBYTE3A_SYM.opcodeDecisions[insnContext].modRMDecisions[opcode];
127 dec = &
THREEBYTEA6_SYM.opcodeDecisions[insnContext].modRMDecisions[opcode];
130 dec = &
THREEBYTEA7_SYM.opcodeDecisions[insnContext].modRMDecisions[opcode];
133 dec = &
XOP8_MAP_SYM.opcodeDecisions[insnContext].modRMDecisions[opcode];
136 dec = &
XOP9_MAP_SYM.opcodeDecisions[insnContext].modRMDecisions[opcode];
139 dec = &
XOPA_MAP_SYM.opcodeDecisions[insnContext].modRMDecisions[opcode];
145 debug(
"Corrupt table! Unknown modrm_type");
148 return modRMTable[dec->instructionIDs];
151 return modRMTable[dec->instructionIDs+1];
152 return modRMTable[dec->instructionIDs];
155 return modRMTable[dec->instructionIDs+((modRM & 0x38) >> 3)+8];
156 return modRMTable[dec->instructionIDs+((modRM & 0x38) >> 3)];
157 case MODRM_SPLITMISC:
159 return modRMTable[dec->instructionIDs+(modRM & 0x3f)+8];
160 return modRMTable[dec->instructionIDs+((modRM & 0x38) >> 3)];
162 return modRMTable[dec->instructionIDs+modRM];
212 #define CONSUME_FUNC(name, type) \
213 static int name(struct InternalInstruction* insn, type* ptr) { \
216 for (offset = 0; offset < sizeof(type); ++offset) { \
218 int ret = insn->reader(insn->readerArg, \
220 insn->readerCursor + offset); \
223 combined = combined | ((uint64_t)byte << (offset * 8)); \
226 insn->readerCursor += sizeof(type); \
264 va_start(ap, format);
268 insn->dlog(insn->dlogArg, buffer);
322 uint64_t prefixLocation;
346 && (byte == 0xf2 || byte == 0xf3)
356 if ((byte == 0xf2 || byte == 0xf3) &&
357 ((nextByte == 0xf0) |
358 ((nextByte & 0xfe) == 0x86 || (nextByte & 0xf8) == 0x90)))
367 (nextByte == 0x88 || nextByte == 0x89 ||
368 nextByte == 0xc6 || nextByte == 0xc7))
377 if (nextByte != 0x0f && nextByte != 0x90)
386 dbgprintf(insn,
"Redundant Group 1 prefix");
387 prefixGroups[0] =
TRUE;
416 debug(
"Unhandled override");
420 dbgprintf(insn,
"Redundant Group 2 prefix");
421 prefixGroups[1] =
TRUE;
426 dbgprintf(insn,
"Redundant Group 3 prefix");
427 prefixGroups[2] =
TRUE;
433 dbgprintf(insn,
"Redundant Group 4 prefix");
434 prefixGroups[3] =
TRUE;
444 dbgprintf(insn,
"Found prefix 0x%hhx", byte);
453 dbgprintf(insn,
"Couldn't read second byte of VEX");
490 dbgprintf(insn,
"Found VEX prefix 0x%hhx 0x%hhx 0x%hhx",
495 else if (byte == 0xc5) {
499 dbgprintf(insn,
"Couldn't read second byte of VEX");
531 else if (byte == 0x8f) {
535 dbgprintf(insn,
"Couldn't read second byte of XOP");
539 if ((byte1 & 0x38) != 0x0) {
572 dbgprintf(insn,
"Found XOP prefix 0x%hhx 0x%hhx 0x%hhx",
579 if ((byte & 0xf0) == 0x40) {
582 if (
lookAtByte(insn, &opcodeByte) || ((opcodeByte & 0xf0) == 0x40)) {
590 dbgprintf(insn,
"Found REX prefix 0x%hhx", byte);
654 dbgprintf(insn,
"Unhandled m-mmmm field for instruction (0x%hhx)",
678 dbgprintf(insn,
"Unhandled m-mmmm field for instruction (0x%hhx)",
696 if (current == 0x0f) {
697 dbgprintf(insn,
"Found a two-byte escape prefix (0x%hhx)", current);
702 if (current == 0x38) {
703 dbgprintf(insn,
"Found a three-byte escape prefix (0x%hhx)", current);
709 }
else if (current == 0x3a) {
710 dbgprintf(insn,
"Found a three-byte escape prefix (0x%hhx)", current);
716 }
else if (current == 0xa6) {
717 dbgprintf(insn,
"Found a three-byte escape prefix (0x%hhx)", current);
723 }
else if (current == 0xa7) {
724 dbgprintf(insn,
"Found a three-byte escape prefix (0x%hhx)", current);
731 dbgprintf(insn,
"Didn't find a three-byte escape prefix");
764 BOOL hasModRMExtension;
766 uint8_t instructionClass;
774 if (hasModRMExtension) {
803 if (orig[i] ==
'\0' && equiv[i] ==
'\0')
805 if (orig[i] ==
'\0' || equiv[i] ==
'\0')
807 if (orig[i] != equiv[i]) {
808 if ((orig[i] ==
'Q' || orig[i] ==
'L') && equiv[i] ==
'W')
810 if ((orig[i] ==
'6' || orig[i] ==
'3') && equiv[i] ==
'1')
812 if ((orig[i] ==
'4' || orig[i] ==
'2') && equiv[i] ==
'6')
830 uint16_t instructionID;
834 attrMask = ATTR_NONE;
837 attrMask |= ATTR_64BIT;
840 attrMask |= ATTR_VEX;
845 attrMask |= ATTR_OPSIZE;
856 attrMask |= ATTR_VEXL;
861 attrMask |= ATTR_OPSIZE;
872 attrMask |= ATTR_VEXL;
877 attrMask |= ATTR_OPSIZE;
888 attrMask |= ATTR_VEXL;
896 attrMask |= ATTR_OPSIZE;
898 attrMask |= ATTR_ADSIZE;
906 attrMask |= ATTR_REXW;
913 if (insn->
prefixPresent[0x66] && !(attrMask & ATTR_OPSIZE)) {
923 uint16_t instructionIDWithOpsize;
924 const char *specName, *specWithOpSizeName;
930 attrMask | ATTR_OPSIZE)) {
963 uint16_t instructionIDWithNewOpcode;
987 insn->
spec = specWithNewOpcode;
1008 uint8_t index, base;
1019 dbgprintf(insn,
"SIB-based addressing doesn't work in 16-bit mode");
1023 sibIndexBase = SIB_INDEX_EAX;
1024 sibBaseBase = SIB_BASE_EAX;
1027 sibIndexBase = SIB_INDEX_RAX;
1028 sibBaseBase = SIB_BASE_RAX;
1043 if (insn->
sibIndex == SIB_INDEX_sib ||
1076 SIB_BASE_EBP : SIB_BASE_RBP);
1081 SIB_BASE_EBP : SIB_BASE_RBP);
1084 debug(
"Cannot have Mod = 0b11 and a SIB byte");
1121 if (consumeInt8(insn, &d8))
1126 if (consumeInt16(insn, &d16))
1131 if (consumeInt32(insn, &d32))
1149 uint8_t mod, rm, reg;
1175 insn->
regBase = MODRM_REG_EAX;
1179 insn->
regBase = MODRM_REG_RAX;
1235 EA_BASE_sib : EA_BASE_sib64);
1257 insn->
eaBase = EA_BASE_sib;
1280 #define GENERIC_FIXUP_FUNC(name, base, prefix) \
1281 static uint8_t name(struct InternalInstruction *insn, \
1288 debug("Unhandled register type"); \
1292 return base + index; \
1294 if (insn->rexPrefix && \
1295 index >= 4 && index <= 7) { \
1296 return prefix##_SPL + (index - 4); \
1298 return prefix##_AL + index; \
1301 return prefix##_AX + index; \
1303 return prefix##_EAX + index; \
1305 return prefix##_RAX + index; \
1307 return prefix##_ZMM0 + index; \
1309 return prefix##_YMM0 + index; \
1314 return prefix##_XMM0 + index; \
1320 return prefix##_MM0 + index; \
1321 case TYPE_SEGMENTREG: \
1324 return prefix##_ES + index; \
1325 case TYPE_DEBUGREG: \
1328 return prefix##_DR0 + index; \
1329 case TYPE_CONTROLREG: \
1332 return prefix##_CR0 + index; \
1369 debug(
"Expected a REG or R/M encoding in fixupReg");
1372 insn->vvvv = (
Reg)fixupRegValue(insn,
1380 insn->reg = (
Reg)fixupRegValue(insn,
1382 insn->reg - insn->regBase,
1388 if (insn->eaBase >= insn->eaRegBase) {
1389 insn->eaBase = (
EABase)fixupRMValue(insn,
1391 insn->eaBase - insn->eaRegBase,
1412 dbgprintf(insn,
"readOpcodeModifier()");
1421 debug(
"Unknown modifier type.");
1424 debug(
"No modifier but an operand expects one.");
1426 case MODIFIER_OPCODE:
1429 case MODIFIER_MODRM:
1447 dbgprintf(insn,
"readOpcodeRegister()");
1505 debug(
"Already consumed two immediates");
1522 if (consumeUInt16(insn, &imm16))
1527 if (consumeUInt32(insn, &imm32))
1532 if (consumeUInt64(insn, &imm64))
1577 int hasVVVV, needVVVV;
1585 needVVVV = hasVVVV && (insn->
vvvv != 0);
1588 switch (x86OperandSets[insn->
spec->operands][index].encoding) {
1595 if (
fixupReg(insn, &x86OperandSets[insn->
spec->operands][index]))
1604 dbgprintf(insn,
"We currently don't hande code-offset encodings");
1617 if (x86OperandSets[insn->
spec->operands][index].type == TYPE_IMM3 &&
1620 if (x86OperandSets[insn->
spec->operands][index].type == TYPE_IMM5 &&
1623 if (x86OperandSets[insn->
spec->operands][index].type == TYPE_XMM128 ||
1624 x86OperandSets[insn->
spec->operands][index].type == TYPE_XMM256)
1675 if (
fixupReg(insn, &x86OperandSets[insn->
spec->operands][index]))
1681 dbgprintf(insn,
"Encountered an operand with an unknown encoding.");
1687 if (needVVVV)
return -1;
1714 const void* readerArg,
1733 getID(insn, miiArg) ||
1738 insn->
operands = &x86OperandSets[insn->
spec->operands][0];
1742 dbgprintf(insn,
"Read from 0x%llx to 0x%llx: length %zu",
1746 dbgprintf(insn,
"Instruction exceeds 15-byte limit");
void(* dlog_t)(void *arg, const char *log)
static int readSIB(struct InternalInstruction *insn)
static int getIDWithAttrMask(uint16_t *instructionID, struct InternalInstruction *insn, uint8_t attrMask)
#define bFromVEX2of3(vex)
BOOL consumedDisplacement
#define rmFromModRM(modRM)
int(* byteReader_t)(const void *arg, uint8_t *byte, uint64_t address)
uint8_t displacementOffset
static int readVVVV(struct InternalInstruction *insn)
#define vvvvFromVEX2of2(vex)
static const struct InstructionSpecifier * specifierForUID(InstrUID uid)
uint64_t prefixLocations[0x100]
const struct InstructionSpecifier * spec
struct OpcodeDecision opcodeDecisions[IC_max]
uint8_t prefixPresent[0x100]
#define rFromVEX2of2(vex)
static int readModRM(struct InternalInstruction *insn)
static BOOL isPrefixAtLocation(struct InternalInstruction *insn, uint8_t prefix, uint64_t location)
#define lFromVEX2of2(vex)
#define GENERIC_FIXUP_FUNC(name, base, prefix)
static int readPrefixes(struct InternalInstruction *insn)
static int modRMRequired(OpcodeType type, InstructionContext insnContext, uint8_t opcode)
#define xFromXOP2of3(xop)
format_object1< T > format(const char *Fmt, const T &Val)
#define CONSUME_FUNC(name, type)
uint8_t numImmediatesConsumed
static void setPrefixPresent(struct InternalInstruction *insn, uint8_t prefix, uint64_t location)
#define ppFromVEX3of3(vex)
#define mmmmmFromXOP2of3(xop)
#define vvvvFromVEX3of3(vex)
static int readImmediate(struct InternalInstruction *insn, uint8_t size)
int vsnprintf(char *s, size_t n, const char *format, va_list ap);
static BOOL is16BitEquivalent(const char *orig, const char *equiv)
static void dbgprintf(struct InternalInstruction *insn, const char *format,...)
static int consumeByte(struct InternalInstruction *insn, uint8_t *byte)
const struct OperandSpecifier * operands
#define bFromXOP2of3(xop)
static InstructionContext contextForAttrs(uint8_t attrMask)
static int readOpcodeRegister(struct InternalInstruction *insn, uint8_t size)
#define lFromVEX3of3(vex)
#define ppFromVEX2of2(vex)
static int readOperands(struct InternalInstruction *insn)
#define lFromXOP3of3(xop)
#define mmmmmFromVEX2of3(vex)
static int readOpcodeModifier(struct InternalInstruction *insn)
#define scaleFromSIB(sib)
#define xFromVEX2of3(vex)
#define rFromXOP2of3(xop)
static int getID(struct InternalInstruction *insn, const void *miiArg)
struct ModRMDecision modRMDecisions[256]
static void unconsumeByte(struct InternalInstruction *insn)
static InstrUID decode(OpcodeType type, InstructionContext insnContext, uint8_t opcode, uint8_t modRM)
#define wFromVEX3of3(vex)
#define wFromXOP3of3(xop)
EADisplacement eaDisplacement
#define indexFromSIB(sib)
static int readDisplacement(struct InternalInstruction *insn)
static void logger(void *arg, const char *log)
#define rFromVEX2of3(vex)
#define regFromModRM(modRM)
#define modFromModRM(modRM)
static int fixupReg(struct InternalInstruction *insn, const struct OperandSpecifier *op)
const char * x86DisassemblerGetInstrName(unsigned Opcode, const void *mii)
static int readOpcode(struct InternalInstruction *insn)
uint64_t necessaryPrefixLocation
#define vvvvFromXOP3of3(vex)
static int lookAtByte(struct InternalInstruction *insn, uint8_t *byte)
LocationClass< Ty > location(Ty &L)
#define ppFromXOP3of3(xop)
SegmentOverride segmentOverride
BOOL consumedOpcodeModifier
int decodeInstruction(struct InternalInstruction *insn, byteReader_t reader, const void *readerArg, dlog_t logger, void *loggerArg, const void *miiArg, uint64_t startLoc, DisassemblerMode mode)