diff options
author | Rafael Auler <rafaelauler@fb.com> | 2018-02-15 21:20:31 +0000 |
---|---|---|
committer | Rafael Auler <rafaelauler@fb.com> | 2018-02-15 21:20:31 +0000 |
commit | de9ad4ba848729f0826131a947fdbaae98df6d05 (patch) | |
tree | 235da52f857bfe603877b4767a9494b868cb6ab7 /llvm/lib | |
parent | 775c7af4f9ff934a85d4b6d521fffc7f5ac26cc0 (diff) | |
download | bcm5719-llvm-de9ad4ba848729f0826131a947fdbaae98df6d05.tar.gz bcm5719-llvm-de9ad4ba848729f0826131a947fdbaae98df6d05.zip |
[X86][3DNOW] Teach decoder about AMD 3DNow! instrs
Summary:
This patch makes the decoder understand old AMD 3DNow!
instructions that have never been properly supported in the X86
disassembler, despite being supported in other subsystems. Hopefully
this should make the X86 decoder more complete with respect to binaries
containing legacy code.
Reviewers: craig.topper
Reviewed By: craig.topper
Subscribers: llvm-commits, maksfb, bruno
Differential Revision: https://reviews.llvm.org/D43311
llvm-svn: 325295
Diffstat (limited to 'llvm/lib')
4 files changed, 50 insertions, 11 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 { diff --git a/llvm/lib/Target/X86/X86Instr3DNow.td b/llvm/lib/Target/X86/X86Instr3DNow.td index d2e5980718e..edb7dd619fb 100644 --- a/llvm/lib/Target/X86/X86Instr3DNow.td +++ b/llvm/lib/Target/X86/X86Instr3DNow.td @@ -52,8 +52,6 @@ class I3DNow_binop<bits<8> o, Format F, dag ins, string Mnemonic, list<dag> pat, : I3DNow<o, F, (outs VR64:$dst), ins, !strconcat(Mnemonic, "\t{$src2, $dst|$dst, $src2}"), pat, itin>, Has3DNow0F0FOpcode { - // FIXME: The disassembler doesn't support Has3DNow0F0FOpcode yet. - let isAsmParserOnly = 1; let Constraints = "$src1 = $dst"; } @@ -61,10 +59,7 @@ class I3DNow_conv<bits<8> o, Format F, dag ins, string Mnemonic, list<dag> pat, InstrItinClass itin> : I3DNow<o, F, (outs VR64:$dst), ins, !strconcat(Mnemonic, "\t{$src, $dst|$dst, $src}"), pat, itin>, - Has3DNow0F0FOpcode { - // FIXME: The disassembler doesn't support Has3DNow0F0FOpcode yet. - let isAsmParserOnly = 1; -} + Has3DNow0F0FOpcode; multiclass I3DNow_binop_rm_int<bits<8> opc, string Mn, OpndItins itins, bit Commutable = 0, string Ver = ""> { |