diff options
Diffstat (limited to 'llvm/lib/Target/X86/Disassembler')
3 files changed, 49 insertions, 5 deletions
diff --git a/llvm/lib/Target/X86/Disassembler/X86DisassemblerDecoder.cpp b/llvm/lib/Target/X86/Disassembler/X86DisassemblerDecoder.cpp index 843d037ad3c..50d10feaae3 100644 --- a/llvm/lib/Target/X86/Disassembler/X86DisassemblerDecoder.cpp +++ b/llvm/lib/Target/X86/Disassembler/X86DisassemblerDecoder.cpp @@ -588,11 +588,44 @@ static int readPrefixes(struct InternalInstruction* insn) { insn->vectorExtensionPrefix[0], insn->vectorExtensionPrefix[1], insn->vectorExtensionPrefix[2]); } + } else if (byte == 0x0f) { + uint8_t byte1; + + // Check for AMD 3DNow without a REX prefix + if (consumeByte(insn, &byte1)) { + unconsumeByte(insn); + } else { + if (byte1 != 0x0f) { + unconsumeByte(insn); + unconsumeByte(insn); + } else { + dbgprintf(insn, "Found AMD 3DNow prefix 0f0f"); + insn->vectorExtensionType = TYPE_3DNOW; + } + } } else if (isREX(insn, byte)) { if (lookAtByte(insn, &nextByte)) return -1; insn->rexPrefix = byte; dbgprintf(insn, "Found REX prefix 0x%hhx", byte); + + // Check for AMD 3DNow with a REX prefix + if (nextByte == 0x0f) { + consumeByte(insn, &nextByte); + uint8_t byte1; + + if (consumeByte(insn, &byte1)) { + unconsumeByte(insn); + } else { + if (byte1 != 0x0f) { + unconsumeByte(insn); + unconsumeByte(insn); + } else { + dbgprintf(insn, "Found AMD 3DNow prefix 0f0f"); + insn->vectorExtensionType = TYPE_3DNOW; + } + } + } } else unconsumeByte(insn); @@ -623,6 +656,8 @@ static int readPrefixes(struct InternalInstruction* insn) { return 0; } +static int readModRM(struct InternalInstruction* insn); + /* * readOpcode - Reads the opcode (excepting the ModR/M byte in the case of * extended or escape opcodes). @@ -690,6 +725,12 @@ static int readOpcode(struct InternalInstruction* insn) { insn->opcodeType = XOPA_MAP; return consumeByte(insn, &insn->opcode); } + } else if (insn->vectorExtensionType == TYPE_3DNOW) { + // Consume operands before the opcode to comply with the 3DNow encoding + if (readModRM(insn)) + return -1; + insn->opcodeType = TWOBYTE; + return consumeByte(insn, &insn->opcode); } if (consumeByte(insn, ¤t)) @@ -735,8 +776,6 @@ static int readOpcode(struct InternalInstruction* insn) { return 0; } -static int readModRM(struct InternalInstruction* insn); - /* * getIDWithAttrMask - Determines the ID of an instruction, consuming * the ModR/M byte as appropriate for extended and escape opcodes, @@ -912,6 +951,8 @@ static int getID(struct InternalInstruction* insn, const void *miiArg) { if (lFromXOP3of3(insn->vectorExtensionPrefix[2])) attrMask |= ATTR_VEXL; + } else if (insn->vectorExtensionType == TYPE_3DNOW) { + attrMask |= ATTR_3DNOW; } else { return -1; } diff --git a/llvm/lib/Target/X86/Disassembler/X86DisassemblerDecoder.h b/llvm/lib/Target/X86/Disassembler/X86DisassemblerDecoder.h index ecd9d8dccaf..1be3c43a6d3 100644 --- a/llvm/lib/Target/X86/Disassembler/X86DisassemblerDecoder.h +++ b/llvm/lib/Target/X86/Disassembler/X86DisassemblerDecoder.h @@ -493,7 +493,8 @@ enum VectorExtensionType { TYPE_VEX_2B = 0x1, TYPE_VEX_3B = 0x2, TYPE_EVEX = 0x3, - TYPE_XOP = 0x4 + TYPE_XOP = 0x4, + TYPE_3DNOW = 0x5 }; /// \brief Type for the byte reader that the consumer must provide to diff --git a/llvm/lib/Target/X86/Disassembler/X86DisassemblerDecoderCommon.h b/llvm/lib/Target/X86/Disassembler/X86DisassemblerDecoderCommon.h index ad1404860fb..ffac6c9c440 100644 --- a/llvm/lib/Target/X86/Disassembler/X86DisassemblerDecoderCommon.h +++ b/llvm/lib/Target/X86/Disassembler/X86DisassemblerDecoderCommon.h @@ -60,7 +60,8 @@ namespace X86Disassembler { ENUM_ENTRY(ATTR_EVEXL2, (0x1 << 10)) \ ENUM_ENTRY(ATTR_EVEXK, (0x1 << 11)) \ ENUM_ENTRY(ATTR_EVEXKZ, (0x1 << 12)) \ - ENUM_ENTRY(ATTR_EVEXB, (0x1 << 13)) + ENUM_ENTRY(ATTR_EVEXB, (0x1 << 13)) \ + ENUM_ENTRY(ATTR_3DNOW, (0x1 << 14)) #define ENUM_ENTRY(n, v) n = v, enum attributeBits { @@ -270,7 +271,8 @@ enum attributeBits { ENUM_ENTRY(IC_EVEX_L2_W_KZ, 3, "requires EVEX_KZ, L2 and W") \ ENUM_ENTRY(IC_EVEX_L2_W_XS_KZ, 4, "requires EVEX_KZ, L2, W and XS prefix") \ ENUM_ENTRY(IC_EVEX_L2_W_XD_KZ, 4, "requires EVEX_KZ, L2, W and XD prefix") \ - ENUM_ENTRY(IC_EVEX_L2_W_OPSIZE_KZ, 4, "requires EVEX_KZ, L2, W and OpSize") + ENUM_ENTRY(IC_EVEX_L2_W_OPSIZE_KZ, 4, "requires EVEX_KZ, L2, W and OpSize") \ + ENUM_ENTRY(IC_3DNOW, 8, "requires AMD 3DNow prefix 0f0f") #define ENUM_ENTRY(n, r, d) n, enum InstructionContext { |