diff options
Diffstat (limited to 'llvm/lib/Target/X86/Disassembler/X86DisassemblerDecoder.cpp')
-rw-r--r-- | llvm/lib/Target/X86/Disassembler/X86DisassemblerDecoder.cpp | 59 |
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); |