summaryrefslogtreecommitdiffstats
path: root/llvm/lib
diff options
context:
space:
mode:
authorRafael Auler <rafaelauler@fb.com>2018-02-15 21:20:31 +0000
committerRafael Auler <rafaelauler@fb.com>2018-02-15 21:20:31 +0000
commitde9ad4ba848729f0826131a947fdbaae98df6d05 (patch)
tree235da52f857bfe603877b4767a9494b868cb6ab7 /llvm/lib
parent775c7af4f9ff934a85d4b6d521fffc7f5ac26cc0 (diff)
downloadbcm5719-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')
-rw-r--r--llvm/lib/Target/X86/Disassembler/X86DisassemblerDecoder.cpp45
-rw-r--r--llvm/lib/Target/X86/Disassembler/X86DisassemblerDecoder.h3
-rw-r--r--llvm/lib/Target/X86/Disassembler/X86DisassemblerDecoderCommon.h6
-rw-r--r--llvm/lib/Target/X86/X86Instr3DNow.td7
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, &current))
@@ -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 = ""> {
OpenPOWER on IntegriCloud