aboutsummaryrefslogtreecommitdiff
path: root/llvm/lib/Target/X86/Disassembler/X86DisassemblerDecoder.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'llvm/lib/Target/X86/Disassembler/X86DisassemblerDecoder.cpp')
-rw-r--r--llvm/lib/Target/X86/Disassembler/X86DisassemblerDecoder.cpp59
1 files changed, 37 insertions, 22 deletions
diff --git a/llvm/lib/Target/X86/Disassembler/X86DisassemblerDecoder.cpp b/llvm/lib/Target/X86/Disassembler/X86DisassemblerDecoder.cpp
index 85244647..6884f2a 100644
--- a/llvm/lib/Target/X86/Disassembler/X86DisassemblerDecoder.cpp
+++ b/llvm/lib/Target/X86/Disassembler/X86DisassemblerDecoder.cpp
@@ -1156,7 +1156,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;
@@ -1172,11 +1171,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;
}
@@ -1186,26 +1185,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);
@@ -1481,6 +1464,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; \
} \
}
@@ -1536,7 +1525,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,
@@ -1734,8 +1722,35 @@ static int readOperands(struct InternalInstruction* insn) {
needVVVV = hasVVVV & ((insn->vvvv & 0xf) != 0);
if (readModRM(insn))
return -1;
- if (fixupReg(insn, &Op))
+
+ // 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);