diff options
author | Craig Topper <craig.topper@intel.com> | 2018-03-24 07:48:54 +0000 |
---|---|---|
committer | Craig Topper <craig.topper@intel.com> | 2018-03-24 07:48:54 +0000 |
commit | 097b47a0fcc499ff735dc8a78273b8a226541c9f (patch) | |
tree | 5a87bf8d4671598c7c62609faee2c3d5da936476 | |
parent | 86163630174961f1ab91c2a48a012b79fa7ce6ad (diff) | |
download | llvm-097b47a0fcc499ff735dc8a78273b8a226541c9f.zip llvm-097b47a0fcc499ff735dc8a78273b8a226541c9f.tar.gz llvm-097b47a0fcc499ff735dc8a78273b8a226541c9f.tar.bz2 |
[X86] Add a new disassembler opcode map for 3DNow. Stop treating 3DNow as an attribute.
This reduces the size of llvm-mc by at least 150k since we no longer have to multiply the attribute across 7 tables.
llvm-svn: 328416
6 files changed, 37 insertions, 65 deletions
diff --git a/llvm/include/llvm/Support/X86DisassemblerDecoderCommon.h b/llvm/include/llvm/Support/X86DisassemblerDecoderCommon.h index ffac6c9..eeffb9c 100644 --- a/llvm/include/llvm/Support/X86DisassemblerDecoderCommon.h +++ b/llvm/include/llvm/Support/X86DisassemblerDecoderCommon.h @@ -31,6 +31,7 @@ namespace X86Disassembler { #define XOP8_MAP_SYM x86DisassemblerXOP8Opcodes #define XOP9_MAP_SYM x86DisassemblerXOP9Opcodes #define XOPA_MAP_SYM x86DisassemblerXOPAOpcodes +#define THREEDNOW_MAP_SYM x86Disassembler3DNowOpcodes #define INSTRUCTIONS_STR "x86DisassemblerInstrSpecifiers" #define CONTEXTS_STR "x86DisassemblerContexts" @@ -41,6 +42,7 @@ namespace X86Disassembler { #define XOP8_MAP_STR "x86DisassemblerXOP8Opcodes" #define XOP9_MAP_STR "x86DisassemblerXOP9Opcodes" #define XOPA_MAP_STR "x86DisassemblerXOPAOpcodes" +#define THREEDNOW_MAP_STR "x86Disassembler3DNowOpcodes" // Attributes of an instruction that must be known before the opcode can be // processed correctly. Most of these indicate the presence of particular @@ -60,8 +62,7 @@ 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_3DNOW, (0x1 << 14)) + ENUM_ENTRY(ATTR_EVEXB, (0x1 << 13)) #define ENUM_ENTRY(n, v) n = v, enum attributeBits { @@ -271,8 +272,7 @@ 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_3DNOW, 8, "requires AMD 3DNow prefix 0f0f") + ENUM_ENTRY(IC_EVEX_L2_W_OPSIZE_KZ, 4, "requires EVEX_KZ, L2, W and OpSize") #define ENUM_ENTRY(n, r, d) n, enum InstructionContext { @@ -290,7 +290,8 @@ enum OpcodeType { THREEBYTE_3A = 3, XOP8_MAP = 4, XOP9_MAP = 5, - XOPA_MAP = 6 + XOPA_MAP = 6, + THREEDNOW_MAP = 7 }; // The following structs are used for the hierarchical decode table. After diff --git a/llvm/lib/Target/X86/Disassembler/X86DisassemblerDecoder.cpp b/llvm/lib/Target/X86/Disassembler/X86DisassemblerDecoder.cpp index 50d10fe..6a10278 100644 --- a/llvm/lib/Target/X86/Disassembler/X86DisassemblerDecoder.cpp +++ b/llvm/lib/Target/X86/Disassembler/X86DisassemblerDecoder.cpp @@ -103,6 +103,9 @@ static int modRMRequired(OpcodeType type, case XOPA_MAP: decision = &XOPA_MAP_SYM; break; + case THREEDNOW_MAP: + decision = &THREEDNOW_MAP_SYM; + break; } return decision->opcodeDecisions[insnContext].modRMDecisions[opcode]. @@ -147,6 +150,9 @@ static InstrUID decode(OpcodeType type, case XOPA_MAP: dec = &XOPA_MAP_SYM.opcodeDecisions[insnContext].modRMDecisions[opcode]; break; + case THREEDNOW_MAP: + dec = &THREEDNOW_MAP_SYM.opcodeDecisions[insnContext].modRMDecisions[opcode]; + break; } switch (dec->modrm_type) { @@ -588,44 +594,11 @@ 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); @@ -725,12 +698,6 @@ 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)) @@ -756,6 +723,17 @@ static int readOpcode(struct InternalInstruction* insn) { return -1; insn->opcodeType = THREEBYTE_3A; + } else if (current == 0x0f) { + dbgprintf(insn, "Found a 3dnow escape prefix (0x%hhx)", current); + + // Consume operands before the opcode to comply with the 3DNow encoding + if (readModRM(insn)) + return -1; + + if (consumeByte(insn, ¤t)) + return -1; + + insn->opcodeType = THREEDNOW_MAP; } else { dbgprintf(insn, "Didn't find a three-byte escape prefix"); @@ -951,8 +929,6 @@ 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 2c2b7dc..44422a9 100644 --- a/llvm/lib/Target/X86/Disassembler/X86DisassemblerDecoder.h +++ b/llvm/lib/Target/X86/Disassembler/X86DisassemblerDecoder.h @@ -493,8 +493,7 @@ enum VectorExtensionType { TYPE_VEX_2B = 0x1, TYPE_VEX_3B = 0x2, TYPE_EVEX = 0x3, - TYPE_XOP = 0x4, - TYPE_3DNOW = 0x5 + TYPE_XOP = 0x4 }; /// \brief Type for the byte reader that the consumer must provide to diff --git a/llvm/utils/TableGen/X86DisassemblerTables.cpp b/llvm/utils/TableGen/X86DisassemblerTables.cpp index 91f15e2..9e01eaa 100644 --- a/llvm/utils/TableGen/X86DisassemblerTables.cpp +++ b/llvm/utils/TableGen/X86DisassemblerTables.cpp @@ -546,8 +546,6 @@ static inline bool inheritsFrom(InstructionContext child, case IC_EVEX_L2_W_XD_KZ_B: case IC_EVEX_L2_W_OPSIZE_KZ_B: return false; - case IC_3DNOW: - return false; default: errs() << "Unknown instruction class: " << stringForContext((InstructionContext)parent) << "\n"; @@ -882,7 +880,7 @@ void DisassemblerTables::emitInstructionInfo(raw_ostream &o, } void DisassemblerTables::emitContextTable(raw_ostream &o, unsigned &i) const { - const unsigned int tableSize = 32768; + const unsigned int tableSize = 16384; o.indent(i * 2) << "static const uint8_t " CONTEXTS_STR "[" << tableSize << "] = {\n"; i++; @@ -890,9 +888,7 @@ void DisassemblerTables::emitContextTable(raw_ostream &o, unsigned &i) const { for (unsigned index = 0; index < tableSize; ++index) { o.indent(i * 2); - if (index & ATTR_3DNOW) - o << "IC_3DNOW"; - else if (index & ATTR_EVEX) { + if (index & ATTR_EVEX) { o << "IC_EVEX"; if (index & ATTR_EVEXL2) o << "_L2"; @@ -1015,6 +1011,7 @@ void DisassemblerTables::emitContextDecisions(raw_ostream &o1, raw_ostream &o2, emitContextDecision(o1, o2, i1, i2, ModRMTableNum, *Tables[4], XOP8_MAP_STR); emitContextDecision(o1, o2, i1, i2, ModRMTableNum, *Tables[5], XOP9_MAP_STR); emitContextDecision(o1, o2, i1, i2, ModRMTableNum, *Tables[6], XOPA_MAP_STR); + emitContextDecision(o1, o2, i1, i2, ModRMTableNum, *Tables[7], THREEDNOW_MAP_STR); } void DisassemblerTables::emit(raw_ostream &o) const { diff --git a/llvm/utils/TableGen/X86DisassemblerTables.h b/llvm/utils/TableGen/X86DisassemblerTables.h index bea9427..b0ea9c2 100644 --- a/llvm/utils/TableGen/X86DisassemblerTables.h +++ b/llvm/utils/TableGen/X86DisassemblerTables.h @@ -41,7 +41,8 @@ private: /// [4] XOP8 map opcode /// [5] XOP9 map opcode /// [6] XOPA map opcode - std::unique_ptr<ContextDecision> Tables[7]; + /// [7] 3dnow map opcode + std::unique_ptr<ContextDecision> Tables[8]; // Table of ModRM encodings. typedef std::map<std::vector<unsigned>, unsigned> ModRMMapTy; diff --git a/llvm/utils/TableGen/X86RecognizableInstr.cpp b/llvm/utils/TableGen/X86RecognizableInstr.cpp index e0aef75..44b798c 100644 --- a/llvm/utils/TableGen/X86RecognizableInstr.cpp +++ b/llvm/utils/TableGen/X86RecognizableInstr.cpp @@ -288,8 +288,6 @@ InstructionContext RecognizableInstr::insnContext() const { errs() << "Instruction does not use a prefix: " << Name << "\n"; llvm_unreachable("Invalid prefix"); } - } else if (OpMap == X86Local::ThreeDNow) { - insnContext = IC_3DNOW; } else if (Is64Bit || HasREX_WPrefix || AdSize == X86Local::AdSize64) { if (HasREX_WPrefix && (OpSize == X86Local::OpSize16 || OpPrefix == X86Local::PD)) insnContext = IC_64BIT_REXW_OPSIZE; @@ -685,14 +683,14 @@ void RecognizableInstr::emitDecodePath(DisassemblerTables &tables) const { llvm::Optional<OpcodeType> opcodeType; switch (OpMap) { default: llvm_unreachable("Invalid map!"); - case X86Local::OB: opcodeType = ONEBYTE; break; - case X86Local::TB: opcodeType = TWOBYTE; break; - case X86Local::T8: opcodeType = THREEBYTE_38; break; - case X86Local::TA: opcodeType = THREEBYTE_3A; break; - case X86Local::XOP8: opcodeType = XOP8_MAP; break; - case X86Local::XOP9: opcodeType = XOP9_MAP; break; - case X86Local::XOPA: opcodeType = XOPA_MAP; break; - case X86Local::ThreeDNow: opcodeType = TWOBYTE; break; + case X86Local::OB: opcodeType = ONEBYTE; break; + case X86Local::TB: opcodeType = TWOBYTE; break; + case X86Local::T8: opcodeType = THREEBYTE_38; break; + case X86Local::TA: opcodeType = THREEBYTE_3A; break; + case X86Local::XOP8: opcodeType = XOP8_MAP; break; + case X86Local::XOP9: opcodeType = XOP9_MAP; break; + case X86Local::XOPA: opcodeType = XOPA_MAP; break; + case X86Local::ThreeDNow: opcodeType = THREEDNOW_MAP; break; } std::unique_ptr<ModRMFilter> filter; |