summaryrefslogtreecommitdiff
path: root/lib/Target/X86/Disassembler
diff options
context:
space:
mode:
Diffstat (limited to 'lib/Target/X86/Disassembler')
-rw-r--r--lib/Target/X86/Disassembler/X86Disassembler.cpp134
-rw-r--r--lib/Target/X86/Disassembler/X86DisassemblerDecoder.cpp340
-rw-r--r--lib/Target/X86/Disassembler/X86DisassemblerDecoder.h20
-rw-r--r--lib/Target/X86/Disassembler/X86DisassemblerDecoderCommon.h4
4 files changed, 224 insertions, 274 deletions
diff --git a/lib/Target/X86/Disassembler/X86Disassembler.cpp b/lib/Target/X86/Disassembler/X86Disassembler.cpp
index 4ce908b1da64..c58254ae38c1 100644
--- a/lib/Target/X86/Disassembler/X86Disassembler.cpp
+++ b/lib/Target/X86/Disassembler/X86Disassembler.cpp
@@ -74,6 +74,7 @@
//
//===----------------------------------------------------------------------===//
+#include "MCTargetDesc/X86BaseInfo.h"
#include "MCTargetDesc/X86MCTargetDesc.h"
#include "X86DisassemblerDecoder.h"
#include "llvm/MC/MCContext.h"
@@ -232,7 +233,24 @@ MCDisassembler::DecodeStatus X86GenericDisassembler::getInstruction(
return Fail;
} else {
Size = InternalInstr.length;
- return (!translateInstruction(Instr, InternalInstr, this)) ? Success : Fail;
+ bool Ret = translateInstruction(Instr, InternalInstr, this);
+ if (!Ret) {
+ unsigned Flags = X86::IP_NO_PREFIX;
+ if (InternalInstr.hasAdSize)
+ Flags |= X86::IP_HAS_AD_SIZE;
+ if (!InternalInstr.mandatoryPrefix) {
+ if (InternalInstr.hasOpSize)
+ Flags |= X86::IP_HAS_OP_SIZE;
+ if (InternalInstr.repeatPrefix == 0xf2)
+ Flags |= X86::IP_HAS_REPEAT_NE;
+ else if (InternalInstr.repeatPrefix == 0xf3 &&
+ // It should not be 'pause' f3 90
+ InternalInstr.opcode != 0x90)
+ Flags |= X86::IP_HAS_REPEAT;
+ }
+ Instr.setFlags(Flags);
+ }
+ return (!Ret) ? Success : Fail;
}
}
@@ -315,12 +333,12 @@ static bool translateSrcIndex(MCInst &mcInst, InternalInstruction &insn) {
unsigned baseRegNo;
if (insn.mode == MODE_64BIT)
- baseRegNo = insn.prefixPresent[0x67] ? X86::ESI : X86::RSI;
+ baseRegNo = insn.hasAdSize ? X86::ESI : X86::RSI;
else if (insn.mode == MODE_32BIT)
- baseRegNo = insn.prefixPresent[0x67] ? X86::SI : X86::ESI;
+ baseRegNo = insn.hasAdSize ? X86::SI : X86::ESI;
else {
assert(insn.mode == MODE_16BIT);
- baseRegNo = insn.prefixPresent[0x67] ? X86::ESI : X86::SI;
+ baseRegNo = insn.hasAdSize ? X86::ESI : X86::SI;
}
MCOperand baseReg = MCOperand::createReg(baseRegNo);
mcInst.addOperand(baseReg);
@@ -340,12 +358,12 @@ static bool translateDstIndex(MCInst &mcInst, InternalInstruction &insn) {
unsigned baseRegNo;
if (insn.mode == MODE_64BIT)
- baseRegNo = insn.prefixPresent[0x67] ? X86::EDI : X86::RDI;
+ baseRegNo = insn.hasAdSize ? X86::EDI : X86::RDI;
else if (insn.mode == MODE_32BIT)
- baseRegNo = insn.prefixPresent[0x67] ? X86::DI : X86::EDI;
+ baseRegNo = insn.hasAdSize ? X86::DI : X86::EDI;
else {
assert(insn.mode == MODE_16BIT);
- baseRegNo = insn.prefixPresent[0x67] ? X86::EDI : X86::DI;
+ baseRegNo = insn.hasAdSize ? X86::EDI : X86::DI;
}
MCOperand baseReg = MCOperand::createReg(baseRegNo);
mcInst.addOperand(baseReg);
@@ -746,102 +764,6 @@ static bool translateRMMemory(MCInst &mcInst, InternalInstruction &insn,
baseReg = MCOperand::createReg(0);
}
- // Check whether we are handling VSIB addressing mode for GATHER.
- // If sibIndex was set to SIB_INDEX_NONE, index offset is 4 and
- // we should use SIB_INDEX_XMM4|YMM4 for VSIB.
- // I don't see a way to get the correct IndexReg in readSIB:
- // We can tell whether it is VSIB or SIB after instruction ID is decoded,
- // but instruction ID may not be decoded yet when calling readSIB.
- uint32_t Opcode = mcInst.getOpcode();
- bool IndexIs128 = (Opcode == X86::VGATHERDPDrm ||
- Opcode == X86::VGATHERDPDYrm ||
- Opcode == X86::VGATHERQPDrm ||
- Opcode == X86::VGATHERDPSrm ||
- Opcode == X86::VGATHERQPSrm ||
- Opcode == X86::VPGATHERDQrm ||
- Opcode == X86::VPGATHERDQYrm ||
- Opcode == X86::VPGATHERQQrm ||
- Opcode == X86::VPGATHERDDrm ||
- Opcode == X86::VPGATHERQDrm ||
- Opcode == X86::VGATHERDPDZ128rm ||
- Opcode == X86::VGATHERDPDZ256rm ||
- Opcode == X86::VGATHERDPSZ128rm ||
- Opcode == X86::VGATHERQPDZ128rm ||
- Opcode == X86::VGATHERQPSZ128rm ||
- Opcode == X86::VPGATHERDDZ128rm ||
- Opcode == X86::VPGATHERDQZ128rm ||
- Opcode == X86::VPGATHERDQZ256rm ||
- Opcode == X86::VPGATHERQDZ128rm ||
- Opcode == X86::VPGATHERQQZ128rm ||
- Opcode == X86::VSCATTERDPDZ128mr ||
- Opcode == X86::VSCATTERDPDZ256mr ||
- Opcode == X86::VSCATTERDPSZ128mr ||
- Opcode == X86::VSCATTERQPDZ128mr ||
- Opcode == X86::VSCATTERQPSZ128mr ||
- Opcode == X86::VPSCATTERDDZ128mr ||
- Opcode == X86::VPSCATTERDQZ128mr ||
- Opcode == X86::VPSCATTERDQZ256mr ||
- Opcode == X86::VPSCATTERQDZ128mr ||
- Opcode == X86::VPSCATTERQQZ128mr);
- bool IndexIs256 = (Opcode == X86::VGATHERQPDYrm ||
- Opcode == X86::VGATHERDPSYrm ||
- Opcode == X86::VGATHERQPSYrm ||
- Opcode == X86::VGATHERDPDZrm ||
- Opcode == X86::VPGATHERDQZrm ||
- Opcode == X86::VPGATHERQQYrm ||
- Opcode == X86::VPGATHERDDYrm ||
- Opcode == X86::VPGATHERQDYrm ||
- Opcode == X86::VGATHERDPSZ256rm ||
- Opcode == X86::VGATHERQPDZ256rm ||
- Opcode == X86::VGATHERQPSZ256rm ||
- Opcode == X86::VPGATHERDDZ256rm ||
- Opcode == X86::VPGATHERQQZ256rm ||
- Opcode == X86::VPGATHERQDZ256rm ||
- Opcode == X86::VSCATTERDPDZmr ||
- Opcode == X86::VPSCATTERDQZmr ||
- Opcode == X86::VSCATTERDPSZ256mr ||
- Opcode == X86::VSCATTERQPDZ256mr ||
- Opcode == X86::VSCATTERQPSZ256mr ||
- Opcode == X86::VPSCATTERDDZ256mr ||
- Opcode == X86::VPSCATTERQQZ256mr ||
- Opcode == X86::VPSCATTERQDZ256mr ||
- Opcode == X86::VGATHERPF0DPDm ||
- Opcode == X86::VGATHERPF1DPDm ||
- Opcode == X86::VSCATTERPF0DPDm ||
- Opcode == X86::VSCATTERPF1DPDm);
- bool IndexIs512 = (Opcode == X86::VGATHERQPDZrm ||
- Opcode == X86::VGATHERDPSZrm ||
- Opcode == X86::VGATHERQPSZrm ||
- Opcode == X86::VPGATHERQQZrm ||
- Opcode == X86::VPGATHERDDZrm ||
- Opcode == X86::VPGATHERQDZrm ||
- Opcode == X86::VSCATTERQPDZmr ||
- Opcode == X86::VSCATTERDPSZmr ||
- Opcode == X86::VSCATTERQPSZmr ||
- Opcode == X86::VPSCATTERQQZmr ||
- Opcode == X86::VPSCATTERDDZmr ||
- Opcode == X86::VPSCATTERQDZmr ||
- Opcode == X86::VGATHERPF0DPSm ||
- Opcode == X86::VGATHERPF0QPDm ||
- Opcode == X86::VGATHERPF0QPSm ||
- Opcode == X86::VGATHERPF1DPSm ||
- Opcode == X86::VGATHERPF1QPDm ||
- Opcode == X86::VGATHERPF1QPSm ||
- Opcode == X86::VSCATTERPF0DPSm ||
- Opcode == X86::VSCATTERPF0QPDm ||
- Opcode == X86::VSCATTERPF0QPSm ||
- Opcode == X86::VSCATTERPF1DPSm ||
- Opcode == X86::VSCATTERPF1QPDm ||
- Opcode == X86::VSCATTERPF1QPSm);
- if (IndexIs128 || IndexIs256 || IndexIs512) {
- unsigned IndexOffset = insn.sibIndex -
- (insn.addressSize == 8 ? SIB_INDEX_RAX:SIB_INDEX_EAX);
- SIBIndex IndexBase = IndexIs512 ? SIB_INDEX_ZMM0 :
- IndexIs256 ? SIB_INDEX_YMM0 : SIB_INDEX_XMM0;
- insn.sibIndex = (SIBIndex)(IndexBase +
- (insn.sibIndex == SIB_INDEX_NONE ? 4 : IndexOffset));
- }
-
if (insn.sibIndex != SIB_INDEX_NONE) {
switch (insn.sibIndex) {
default:
@@ -969,6 +891,9 @@ static bool translateRM(MCInst &mcInst, const OperandSpecifier &operand,
case TYPE_BNDR:
return translateRMRegister(mcInst, insn);
case TYPE_M:
+ case TYPE_MVSIBX:
+ case TYPE_MVSIBY:
+ case TYPE_MVSIBZ:
return translateRMMemory(mcInst, insn, Dis);
}
}
@@ -1034,6 +959,9 @@ static bool translateOperand(MCInst &mcInst, const OperandSpecifier &operand,
insn,
Dis);
return false;
+ case ENCODING_IRC:
+ mcInst.addOperand(MCOperand::createImm(insn.RC));
+ return false;
case ENCODING_SI:
return translateSrcIndex(mcInst, insn);
case ENCODING_DI:
diff --git a/lib/Target/X86/Disassembler/X86DisassemblerDecoder.cpp b/lib/Target/X86/Disassembler/X86DisassemblerDecoder.cpp
index 577b7a776c6d..843d037ad3cd 100644
--- a/lib/Target/X86/Disassembler/X86DisassemblerDecoder.cpp
+++ b/lib/Target/X86/Disassembler/X86DisassemblerDecoder.cpp
@@ -277,38 +277,44 @@ static void dbgprintf(struct InternalInstruction* insn,
insn->dlog(insn->dlogArg, buffer);
}
-/*
- * setPrefixPresent - Marks that a particular prefix is present at a particular
- * location.
- *
- * @param insn - The instruction to be marked as having the prefix.
- * @param prefix - The prefix that is present.
- * @param location - The location where the prefix is located (in the address
- * space of the instruction's reader).
- */
-static void setPrefixPresent(struct InternalInstruction* insn,
- uint8_t prefix,
- uint64_t location)
-{
- insn->prefixPresent[prefix] = 1;
- insn->prefixLocations[prefix] = location;
+static bool isREX(struct InternalInstruction *insn, uint8_t prefix) {
+ if (insn->mode == MODE_64BIT)
+ return prefix >= 0x40 && prefix <= 0x4f;
+ return false;
}
/*
- * isPrefixAtLocation - Queries an instruction to determine whether a prefix is
- * present at a given location.
+ * setPrefixPresent - Marks that a particular prefix is present as mandatory
*
- * @param insn - The instruction to be queried.
- * @param prefix - The prefix.
- * @param location - The location to query.
- * @return - Whether the prefix is at that location.
+ * @param insn - The instruction to be marked as having the prefix.
+ * @param prefix - The prefix that is present.
*/
-static bool isPrefixAtLocation(struct InternalInstruction* insn,
- uint8_t prefix,
- uint64_t location)
-{
- return insn->prefixPresent[prefix] == 1 &&
- insn->prefixLocations[prefix] == location;
+static void setPrefixPresent(struct InternalInstruction *insn, uint8_t prefix) {
+ uint8_t nextByte;
+ switch (prefix) {
+ case 0xf2:
+ case 0xf3:
+ if (lookAtByte(insn, &nextByte))
+ break;
+ // TODO:
+ // 1. There could be several 0x66
+ // 2. if (nextByte == 0x66) and nextNextByte != 0x0f then
+ // it's not mandatory prefix
+ // 3. if (nextByte >= 0x40 && nextByte <= 0x4f) it's REX and we need
+ // 0x0f exactly after it to be mandatory prefix
+ if (isREX(insn, nextByte) || nextByte == 0x0f || nextByte == 0x66)
+ // The last of 0xf2 /0xf3 is mandatory prefix
+ insn->mandatoryPrefix = prefix;
+ insn->repeatPrefix = prefix;
+ break;
+ case 0x66:
+ if (lookAtByte(insn, &nextByte))
+ break;
+ // 0x66 can't overwrite existing mandatory prefix and should be ignored
+ if (!insn->mandatoryPrefix && (nextByte == 0x0f || isREX(insn, nextByte)))
+ insn->mandatoryPrefix = prefix;
+ break;
+ }
}
/*
@@ -322,19 +328,12 @@ static bool isPrefixAtLocation(struct InternalInstruction* insn,
*/
static int readPrefixes(struct InternalInstruction* insn) {
bool isPrefix = true;
- bool prefixGroups[4] = { false };
- uint64_t prefixLocation;
uint8_t byte = 0;
uint8_t nextByte;
- bool hasAdSize = false;
- bool hasOpSize = false;
-
dbgprintf(insn, "readPrefixes()");
while (isPrefix) {
- prefixLocation = insn->readerCursor;
-
/* If we fail reading prefixes, just stop here and let the opcode reader deal with it */
if (consumeByte(insn, &byte))
break;
@@ -343,13 +342,10 @@ static int readPrefixes(struct InternalInstruction* insn) {
* If the byte is a LOCK/REP/REPNE prefix and not a part of the opcode, then
* break and let it be disassembled as a normal "instruction".
*/
- if (insn->readerCursor - 1 == insn->startLocation && byte == 0xf0)
+ if (insn->readerCursor - 1 == insn->startLocation && byte == 0xf0) // LOCK
break;
- if (insn->readerCursor - 1 == insn->startLocation
- && (byte == 0xf2 || byte == 0xf3)
- && !lookAtByte(insn, &nextByte))
- {
+ if ((byte == 0xf2 || byte == 0xf3) && !lookAtByte(insn, &nextByte)) {
/*
* If the byte is 0xf2 or 0xf3, and any of the following conditions are
* met:
@@ -357,39 +353,41 @@ static int readPrefixes(struct InternalInstruction* insn) {
* - it is followed by an xchg instruction
* then it should be disassembled as a xacquire/xrelease not repne/rep.
*/
- if ((byte == 0xf2 || byte == 0xf3) &&
- ((nextByte == 0xf0) ||
- ((nextByte & 0xfe) == 0x86 || (nextByte & 0xf8) == 0x90)))
+ if (((nextByte == 0xf0) ||
+ ((nextByte & 0xfe) == 0x86 || (nextByte & 0xf8) == 0x90))) {
insn->xAcquireRelease = true;
+ if (!(byte == 0xf3 && nextByte == 0x90)) // PAUSE instruction support
+ break;
+ }
/*
* Also if the byte is 0xf3, and the following condition is met:
* - it is followed by a "mov mem, reg" (opcode 0x88/0x89) or
* "mov mem, imm" (opcode 0xc6/0xc7) instructions.
* then it should be disassembled as an xrelease not rep.
*/
- if (byte == 0xf3 &&
- (nextByte == 0x88 || nextByte == 0x89 ||
- nextByte == 0xc6 || nextByte == 0xc7))
+ if (byte == 0xf3 && (nextByte == 0x88 || nextByte == 0x89 ||
+ nextByte == 0xc6 || nextByte == 0xc7)) {
insn->xAcquireRelease = true;
- if (insn->mode == MODE_64BIT && (nextByte & 0xf0) == 0x40) {
- if (consumeByte(insn, &nextByte))
+ if (nextByte != 0x90) // PAUSE instruction support
+ break;
+ }
+ if (isREX(insn, nextByte)) {
+ uint8_t nnextByte;
+ // Go to REX prefix after the current one
+ if (consumeByte(insn, &nnextByte))
return -1;
- if (lookAtByte(insn, &nextByte))
+ // We should be able to read next byte after REX prefix
+ if (lookAtByte(insn, &nnextByte))
return -1;
unconsumeByte(insn);
}
- if (nextByte != 0x0f && nextByte != 0x90)
- break;
}
switch (byte) {
case 0xf0: /* LOCK */
case 0xf2: /* REPNE/REPNZ */
case 0xf3: /* REP or REPE/REPZ */
- if (prefixGroups[0])
- dbgprintf(insn, "Redundant Group 1 prefix");
- prefixGroups[0] = true;
- setPrefixPresent(insn, byte, prefixLocation);
+ setPrefixPresent(insn, byte);
break;
case 0x2e: /* CS segment override -OR- Branch not taken */
case 0x36: /* SS segment override -OR- Branch taken */
@@ -420,24 +418,15 @@ static int readPrefixes(struct InternalInstruction* insn) {
debug("Unhandled override");
return -1;
}
- if (prefixGroups[1])
- dbgprintf(insn, "Redundant Group 2 prefix");
- prefixGroups[1] = true;
- setPrefixPresent(insn, byte, prefixLocation);
+ setPrefixPresent(insn, byte);
break;
case 0x66: /* Operand-size override */
- if (prefixGroups[2])
- dbgprintf(insn, "Redundant Group 3 prefix");
- prefixGroups[2] = true;
- hasOpSize = true;
- setPrefixPresent(insn, byte, prefixLocation);
+ insn->hasOpSize = true;
+ setPrefixPresent(insn, byte);
break;
case 0x67: /* Address-size override */
- if (prefixGroups[3])
- dbgprintf(insn, "Redundant Group 4 prefix");
- prefixGroups[3] = true;
- hasAdSize = true;
- setPrefixPresent(insn, byte, prefixLocation);
+ insn->hasAdSize = true;
+ setPrefixPresent(insn, byte);
break;
default: /* Not a prefix byte */
isPrefix = false;
@@ -469,7 +458,6 @@ static int readPrefixes(struct InternalInstruction* insn) {
} else {
unconsumeByte(insn); /* unconsume byte1 */
unconsumeByte(insn); /* unconsume byte */
- insn->necessaryPrefixLocation = insn->readerCursor - 2;
}
if (insn->vectorExtensionType == TYPE_EVEX) {
@@ -505,13 +493,10 @@ static int readPrefixes(struct InternalInstruction* insn) {
return -1;
}
- if (insn->mode == MODE_64BIT || (byte1 & 0xc0) == 0xc0) {
+ if (insn->mode == MODE_64BIT || (byte1 & 0xc0) == 0xc0)
insn->vectorExtensionType = TYPE_VEX_3B;
- insn->necessaryPrefixLocation = insn->readerCursor - 1;
- } else {
+ else
unconsumeByte(insn);
- insn->necessaryPrefixLocation = insn->readerCursor - 1;
- }
if (insn->vectorExtensionType == TYPE_VEX_3B) {
insn->vectorExtensionPrefix[0] = byte;
@@ -520,13 +505,12 @@ static int readPrefixes(struct InternalInstruction* insn) {
/* We simulate the REX prefix for simplicity's sake */
- if (insn->mode == MODE_64BIT) {
+ if (insn->mode == MODE_64BIT)
insn->rexPrefix = 0x40
| (wFromVEX3of3(insn->vectorExtensionPrefix[2]) << 3)
| (rFromVEX2of3(insn->vectorExtensionPrefix[1]) << 2)
| (xFromVEX2of3(insn->vectorExtensionPrefix[1]) << 1)
| (bFromVEX2of3(insn->vectorExtensionPrefix[1]) << 0);
- }
dbgprintf(insn, "Found VEX prefix 0x%hhx 0x%hhx 0x%hhx",
insn->vectorExtensionPrefix[0], insn->vectorExtensionPrefix[1],
@@ -540,26 +524,24 @@ static int readPrefixes(struct InternalInstruction* insn) {
return -1;
}
- if (insn->mode == MODE_64BIT || (byte1 & 0xc0) == 0xc0) {
+ if (insn->mode == MODE_64BIT || (byte1 & 0xc0) == 0xc0)
insn->vectorExtensionType = TYPE_VEX_2B;
- } else {
+ else
unconsumeByte(insn);
- }
if (insn->vectorExtensionType == TYPE_VEX_2B) {
insn->vectorExtensionPrefix[0] = byte;
consumeByte(insn, &insn->vectorExtensionPrefix[1]);
- if (insn->mode == MODE_64BIT) {
+ if (insn->mode == MODE_64BIT)
insn->rexPrefix = 0x40
| (rFromVEX2of2(insn->vectorExtensionPrefix[1]) << 2);
- }
switch (ppFromVEX2of2(insn->vectorExtensionPrefix[1])) {
default:
break;
case VEX_PREFIX_66:
- hasOpSize = true;
+ insn->hasOpSize = true;
break;
}
@@ -575,13 +557,10 @@ static int readPrefixes(struct InternalInstruction* insn) {
return -1;
}
- if ((byte1 & 0x38) != 0x0) { /* 0 in these 3 bits is a POP instruction. */
+ if ((byte1 & 0x38) != 0x0) /* 0 in these 3 bits is a POP instruction. */
insn->vectorExtensionType = TYPE_XOP;
- insn->necessaryPrefixLocation = insn->readerCursor - 1;
- } else {
+ else
unconsumeByte(insn);
- insn->necessaryPrefixLocation = insn->readerCursor - 1;
- }
if (insn->vectorExtensionType == TYPE_XOP) {
insn->vectorExtensionPrefix[0] = byte;
@@ -590,19 +569,18 @@ static int readPrefixes(struct InternalInstruction* insn) {
/* We simulate the REX prefix for simplicity's sake */
- if (insn->mode == MODE_64BIT) {
+ if (insn->mode == MODE_64BIT)
insn->rexPrefix = 0x40
| (wFromXOP3of3(insn->vectorExtensionPrefix[2]) << 3)
| (rFromXOP2of3(insn->vectorExtensionPrefix[1]) << 2)
| (xFromXOP2of3(insn->vectorExtensionPrefix[1]) << 1)
| (bFromXOP2of3(insn->vectorExtensionPrefix[1]) << 0);
- }
switch (ppFromXOP3of3(insn->vectorExtensionPrefix[2])) {
default:
break;
case VEX_PREFIX_66:
- hasOpSize = true;
+ insn->hasOpSize = true;
break;
}
@@ -610,51 +588,35 @@ static int readPrefixes(struct InternalInstruction* insn) {
insn->vectorExtensionPrefix[0], insn->vectorExtensionPrefix[1],
insn->vectorExtensionPrefix[2]);
}
- } else {
- if (insn->mode == MODE_64BIT) {
- if ((byte & 0xf0) == 0x40) {
- uint8_t opcodeByte;
-
- if (lookAtByte(insn, &opcodeByte) || ((opcodeByte & 0xf0) == 0x40)) {
- dbgprintf(insn, "Redundant REX prefix");
- return -1;
- }
-
- insn->rexPrefix = byte;
- insn->necessaryPrefixLocation = insn->readerCursor - 2;
-
- dbgprintf(insn, "Found REX prefix 0x%hhx", byte);
- } else {
- unconsumeByte(insn);
- insn->necessaryPrefixLocation = insn->readerCursor - 1;
- }
- } else {
- unconsumeByte(insn);
- insn->necessaryPrefixLocation = insn->readerCursor - 1;
- }
- }
+ } else if (isREX(insn, byte)) {
+ if (lookAtByte(insn, &nextByte))
+ return -1;
+ insn->rexPrefix = byte;
+ dbgprintf(insn, "Found REX prefix 0x%hhx", byte);
+ } else
+ unconsumeByte(insn);
if (insn->mode == MODE_16BIT) {
- insn->registerSize = (hasOpSize ? 4 : 2);
- insn->addressSize = (hasAdSize ? 4 : 2);
- insn->displacementSize = (hasAdSize ? 4 : 2);
- insn->immediateSize = (hasOpSize ? 4 : 2);
+ insn->registerSize = (insn->hasOpSize ? 4 : 2);
+ insn->addressSize = (insn->hasAdSize ? 4 : 2);
+ insn->displacementSize = (insn->hasAdSize ? 4 : 2);
+ insn->immediateSize = (insn->hasOpSize ? 4 : 2);
} else if (insn->mode == MODE_32BIT) {
- insn->registerSize = (hasOpSize ? 2 : 4);
- insn->addressSize = (hasAdSize ? 2 : 4);
- insn->displacementSize = (hasAdSize ? 2 : 4);
- insn->immediateSize = (hasOpSize ? 2 : 4);
+ insn->registerSize = (insn->hasOpSize ? 2 : 4);
+ insn->addressSize = (insn->hasAdSize ? 2 : 4);
+ insn->displacementSize = (insn->hasAdSize ? 2 : 4);
+ insn->immediateSize = (insn->hasOpSize ? 2 : 4);
} else if (insn->mode == MODE_64BIT) {
if (insn->rexPrefix && wFromREX(insn->rexPrefix)) {
insn->registerSize = 8;
- insn->addressSize = (hasAdSize ? 4 : 8);
+ insn->addressSize = (insn->hasAdSize ? 4 : 8);
insn->displacementSize = 4;
insn->immediateSize = 4;
} else {
- insn->registerSize = (hasOpSize ? 2 : 4);
- insn->addressSize = (hasAdSize ? 4 : 8);
- insn->displacementSize = (hasOpSize ? 2 : 4);
- insn->immediateSize = (hasOpSize ? 2 : 4);
+ insn->registerSize = (insn->hasOpSize ? 2 : 4);
+ insn->addressSize = (insn->hasAdSize ? 4 : 8);
+ insn->displacementSize = (insn->hasOpSize ? 2 : 4);
+ insn->immediateSize = (insn->hasOpSize ? 2 : 4);
}
}
@@ -758,7 +720,10 @@ static int readOpcode(struct InternalInstruction* insn) {
insn->opcodeType = TWOBYTE;
}
- }
+ } else if (insn->mandatoryPrefix)
+ // The opcode with mandatory prefix must start with opcode escape.
+ // If not it's legacy repeat prefix
+ insn->mandatoryPrefix = 0;
/*
* At this point we have consumed the full opcode.
@@ -950,19 +915,44 @@ static int getID(struct InternalInstruction* insn, const void *miiArg) {
} else {
return -1;
}
- } else {
- if (insn->mode != MODE_16BIT && isPrefixAtLocation(insn, 0x66, insn->necessaryPrefixLocation))
+ } else if (!insn->mandatoryPrefix) {
+ // If we don't have mandatory prefix we should use legacy prefixes here
+ if (insn->hasOpSize && (insn->mode != MODE_16BIT))
attrMask |= ATTR_OPSIZE;
- else if (isPrefixAtLocation(insn, 0x67, insn->necessaryPrefixLocation))
+ if (insn->hasAdSize)
attrMask |= ATTR_ADSIZE;
- else if (isPrefixAtLocation(insn, 0xf3, insn->necessaryPrefixLocation))
- attrMask |= ATTR_XS;
- else if (isPrefixAtLocation(insn, 0xf2, insn->necessaryPrefixLocation))
+ if (insn->opcodeType == ONEBYTE) {
+ if (insn->repeatPrefix == 0xf3 && (insn->opcode == 0x90))
+ // Special support for PAUSE
+ attrMask |= ATTR_XS;
+ } else {
+ if (insn->repeatPrefix == 0xf2)
+ attrMask |= ATTR_XD;
+ else if (insn->repeatPrefix == 0xf3)
+ attrMask |= ATTR_XS;
+ }
+ } else {
+ switch (insn->mandatoryPrefix) {
+ case 0xf2:
attrMask |= ATTR_XD;
+ break;
+ case 0xf3:
+ attrMask |= ATTR_XS;
+ break;
+ case 0x66:
+ if (insn->mode != MODE_16BIT)
+ attrMask |= ATTR_OPSIZE;
+ break;
+ case 0x67:
+ attrMask |= ATTR_ADSIZE;
+ break;
+ }
}
- if (insn->rexPrefix & 0x08)
+ if (insn->rexPrefix & 0x08) {
attrMask |= ATTR_REXW;
+ attrMask &= ~ATTR_ADSIZE;
+ }
/*
* JCXZ/JECXZ need special handling for 16-bit mode because the meaning
@@ -977,8 +967,7 @@ static int getID(struct InternalInstruction* insn, const void *miiArg) {
* CALL/JMP/JCC instructions need to ignore 0x66 and consume 4 bytes
*/
- if (insn->mode == MODE_64BIT &&
- isPrefixAtLocation(insn, 0x66, insn->necessaryPrefixLocation)) {
+ if ((insn->mode == MODE_64BIT) && insn->hasOpSize) {
switch (insn->opcode) {
case 0xE8:
case 0xE9:
@@ -1058,9 +1047,9 @@ static int getID(struct InternalInstruction* insn, const void *miiArg) {
*/
if (insn->opcodeType == ONEBYTE && ((insn->opcode & 0xFC) == 0xA0)) {
/* Make sure we observed the prefixes in any position. */
- if (insn->prefixPresent[0x67])
+ if (insn->hasAdSize)
attrMask |= ATTR_ADSIZE;
- if (insn->prefixPresent[0x66])
+ if (insn->hasOpSize)
attrMask |= ATTR_OPSIZE;
/* In 16-bit, invert the attributes. */
@@ -1075,7 +1064,7 @@ static int getID(struct InternalInstruction* insn, const void *miiArg) {
return 0;
}
- if ((insn->mode == MODE_16BIT || insn->prefixPresent[0x66]) &&
+ if ((insn->mode == MODE_16BIT || insn->hasOpSize) &&
!(attrMask & ATTR_OPSIZE)) {
/*
* The instruction tables make no distinction between instructions that
@@ -1108,7 +1097,7 @@ static int getID(struct InternalInstruction* insn, const void *miiArg) {
specWithOpSizeName = GetInstrName(instructionIDWithOpsize, miiArg);
if (is16BitEquivalent(specName.data(), specWithOpSizeName.data()) &&
- (insn->mode == MODE_16BIT) ^ insn->prefixPresent[0x66]) {
+ (insn->mode == MODE_16BIT) ^ insn->hasOpSize) {
insn->instructionID = instructionIDWithOpsize;
insn->spec = specifierForUID(instructionIDWithOpsize);
} else {
@@ -1169,7 +1158,6 @@ static int getID(struct InternalInstruction* insn, const void *miiArg) {
* @return - 0 if the SIB byte was successfully read; nonzero otherwise.
*/
static int readSIB(struct InternalInstruction* insn) {
- SIBIndex sibIndexBase = SIB_INDEX_NONE;
SIBBase sibBaseBase = SIB_BASE_NONE;
uint8_t index, base;
@@ -1185,11 +1173,11 @@ static int readSIB(struct InternalInstruction* insn) {
dbgprintf(insn, "SIB-based addressing doesn't work in 16-bit mode");
return -1;
case 4:
- sibIndexBase = SIB_INDEX_EAX;
+ insn->sibIndexBase = SIB_INDEX_EAX;
sibBaseBase = SIB_BASE_EAX;
break;
case 8:
- sibIndexBase = SIB_INDEX_RAX;
+ insn->sibIndexBase = SIB_INDEX_RAX;
sibBaseBase = SIB_BASE_RAX;
break;
}
@@ -1199,26 +1187,10 @@ static int readSIB(struct InternalInstruction* insn) {
index = indexFromSIB(insn->sib) | (xFromREX(insn->rexPrefix) << 3);
- // FIXME: The fifth bit (bit index 4) is only to be used for instructions
- // that understand VSIB indexing. ORing the bit in here is mildy dangerous
- // because performing math on an 'enum SIBIndex' can produce garbage.
- // Excluding the "none" value, it should cover 6 spaces of register names:
- // - 16 possibilities for 16-bit GPR starting at SIB_INDEX_BX_SI
- // - 16 possibilities for 32-bit GPR starting at SIB_INDEX_EAX
- // - 16 possibilities for 64-bit GPR starting at SIB_INDEX_RAX
- // - 32 possibilities for each of XMM, YMM, ZMM registers
- // When sibIndexBase gets assigned SIB_INDEX_RAX as it does in 64-bit mode,
- // summing in a fully decoded index between 0 and 31 can end up with a value
- // that looks like something in the low half of the XMM range.
- // translateRMMemory() tries to reverse the damage, with only partial success,
- // as evidenced by known bugs in "test/MC/Disassembler/X86/x86-64.txt"
- if (insn->vectorExtensionType == TYPE_EVEX)
- index |= v2FromEVEX4of4(insn->vectorExtensionPrefix[3]) << 4;
-
if (index == 0x4) {
insn->sibIndex = SIB_INDEX_NONE;
} else {
- insn->sibIndex = (SIBIndex)(sibIndexBase + index);
+ insn->sibIndex = (SIBIndex)(insn->sibIndexBase + index);
}
insn->sibScale = 1 << scaleFromSIB(insn->sib);
@@ -1483,9 +1455,9 @@ static int readModRM(struct InternalInstruction* insn) {
case TYPE_MM64: \
return prefix##_MM0 + (index & 0x7); \
case TYPE_SEGMENTREG: \
- if (index > 5) \
+ if ((index & 7) > 5) \
*valid = 0; \
- return prefix##_ES + index; \
+ return prefix##_ES + (index & 7); \
case TYPE_DEBUGREG: \
return prefix##_DR0 + index; \
case TYPE_CONTROLREG: \
@@ -1494,6 +1466,12 @@ static int readModRM(struct InternalInstruction* insn) {
if (index > 3) \
*valid = 0; \
return prefix##_BND0 + index; \
+ case TYPE_MVSIBX: \
+ return prefix##_XMM0 + index; \
+ case TYPE_MVSIBY: \
+ return prefix##_YMM0 + index; \
+ case TYPE_MVSIBZ: \
+ return prefix##_ZMM0 + index; \
} \
}
@@ -1549,7 +1527,6 @@ static int fixupReg(struct InternalInstruction *insn,
return -1;
break;
CASE_ENCODING_RM:
- CASE_ENCODING_VSIB:
if (insn->eaBase >= insn->eaRegBase) {
insn->eaBase = (EABase)fixupRMValue(insn,
(OperandType)op->type,
@@ -1747,8 +1724,39 @@ static int readOperands(struct InternalInstruction* insn) {
needVVVV = hasVVVV & ((insn->vvvv & 0xf) != 0);
if (readModRM(insn))
return -1;
- if (fixupReg(insn, &Op))
+
+ // Reject if SIB wasn't used.
+ if (insn->eaBase != EA_BASE_sib && insn->eaBase != EA_BASE_sib64)
+ return -1;
+
+ // If sibIndex was set to SIB_INDEX_NONE, index offset is 4.
+ if (insn->sibIndex == SIB_INDEX_NONE)
+ insn->sibIndex = (SIBIndex)4;
+
+ // If EVEX.v2 is set this is one of the 16-31 registers.
+ if (insn->vectorExtensionType == TYPE_EVEX &&
+ v2FromEVEX4of4(insn->vectorExtensionPrefix[3]))
+ insn->sibIndex = (SIBIndex)(insn->sibIndex + 16);
+
+ // Adjust the index register to the correct size.
+ switch ((OperandType)Op.type) {
+ default:
+ debug("Unhandled VSIB index type");
return -1;
+ case TYPE_MVSIBX:
+ insn->sibIndex = (SIBIndex)(SIB_INDEX_XMM0 +
+ (insn->sibIndex - insn->sibIndexBase));
+ break;
+ case TYPE_MVSIBY:
+ insn->sibIndex = (SIBIndex)(SIB_INDEX_YMM0 +
+ (insn->sibIndex - insn->sibIndexBase));
+ break;
+ case TYPE_MVSIBZ:
+ insn->sibIndex = (SIBIndex)(SIB_INDEX_ZMM0 +
+ (insn->sibIndex - insn->sibIndexBase));
+ break;
+ }
+
// Apply the AVX512 compressed displacement scaling factor.
if (Op.encoding != ENCODING_REG && insn->eaDisplacement == EA_DISP_8)
insn->displacement *= 1 << (Op.encoding - ENCODING_VSIB);
@@ -1797,6 +1805,10 @@ static int readOperands(struct InternalInstruction* insn) {
if (readImmediate(insn, insn->addressSize))
return -1;
break;
+ case ENCODING_IRC:
+ insn->RC = (l2FromEVEX4of4(insn->vectorExtensionPrefix[3]) << 1) |
+ lFromEVEX4of4(insn->vectorExtensionPrefix[3]);
+ break;
case ENCODING_RB:
if (readOpcodeRegister(insn, 1))
return -1;
diff --git a/lib/Target/X86/Disassembler/X86DisassemblerDecoder.h b/lib/Target/X86/Disassembler/X86DisassemblerDecoder.h
index b07fd0b17d35..ecd9d8dccafa 100644
--- a/lib/Target/X86/Disassembler/X86DisassemblerDecoder.h
+++ b/lib/Target/X86/Disassembler/X86DisassemblerDecoder.h
@@ -546,24 +546,26 @@ struct InternalInstruction {
// Prefix state
- // 1 if the prefix byte corresponding to the entry is present; 0 if not
- uint8_t prefixPresent[0x100];
- // contains the location (for use with the reader) of the prefix byte
- uint64_t prefixLocations[0x100];
+ // The possible mandatory prefix
+ uint8_t mandatoryPrefix;
// The value of the vector extension prefix(EVEX/VEX/XOP), if present
uint8_t vectorExtensionPrefix[4];
// The type of the vector extension prefix
VectorExtensionType vectorExtensionType;
// The value of the REX prefix, if present
uint8_t rexPrefix;
- // The location where a mandatory prefix would have to be (i.e., right before
- // the opcode, or right before the REX prefix if one is present).
- uint64_t necessaryPrefixLocation;
// The segment override type
SegmentOverride segmentOverride;
// 1 if the prefix byte, 0xf2 or 0xf3 is xacquire or xrelease
bool xAcquireRelease;
+ // Address-size override
+ bool hasAdSize;
+ // Operand-size override
+ bool hasOpSize;
+ // The repeat prefix if any
+ uint8_t repeatPrefix;
+
// Sizes of various critical pieces of data, in bytes
uint8_t registerSize;
uint8_t addressSize;
@@ -637,10 +639,14 @@ struct InternalInstruction {
Reg reg;
// SIB state
+ SIBIndex sibIndexBase;
SIBIndex sibIndex;
uint8_t sibScale;
SIBBase sibBase;
+ // Embedded rounding control.
+ uint8_t RC;
+
ArrayRef<OperandSpecifier> operands;
};
diff --git a/lib/Target/X86/Disassembler/X86DisassemblerDecoderCommon.h b/lib/Target/X86/Disassembler/X86DisassemblerDecoderCommon.h
index e0f4399b3687..ad1404860fb6 100644
--- a/lib/Target/X86/Disassembler/X86DisassemblerDecoderCommon.h
+++ b/lib/Target/X86/Disassembler/X86DisassemblerDecoderCommon.h
@@ -382,6 +382,7 @@ enum ModRMDecisionType {
\
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 " \
@@ -410,6 +411,9 @@ enum OperandEncoding {
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)") \