summaryrefslogtreecommitdiffstats
path: root/llvm/lib/Target
diff options
context:
space:
mode:
Diffstat (limited to 'llvm/lib/Target')
-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