diff options
author | Elena Demikhovsky <elena.demikhovsky@intel.com> | 2013-07-28 08:28:38 +0000 |
---|---|---|
committer | Elena Demikhovsky <elena.demikhovsky@intel.com> | 2013-07-28 08:28:38 +0000 |
commit | c18f4efc5dd24adcc653806455fc7ae8508e9c66 (patch) | |
tree | 3dca274ff506109f68d12ab1debb35f0d37fbb45 /utils | |
parent | cea60aff34ada256a77f5760863218a976786f45 (diff) | |
download | llvm-c18f4efc5dd24adcc653806455fc7ae8508e9c66.tar.gz llvm-c18f4efc5dd24adcc653806455fc7ae8508e9c66.tar.bz2 llvm-c18f4efc5dd24adcc653806455fc7ae8508e9c66.tar.xz |
Added encoding prefixes for KNL instructions (EVEX).
Added 512-bit operands printing.
Added instruction formats for KNL instructions.
git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@187324 91177308-0d34-0410-b5e6-96231b3b80d8
Diffstat (limited to 'utils')
-rw-r--r-- | utils/TableGen/X86DisassemblerTables.cpp | 101 | ||||
-rw-r--r-- | utils/TableGen/X86RecognizableInstr.cpp | 160 | ||||
-rw-r--r-- | utils/TableGen/X86RecognizableInstr.h | 10 |
3 files changed, 261 insertions, 10 deletions
diff --git a/utils/TableGen/X86DisassemblerTables.cpp b/utils/TableGen/X86DisassemblerTables.cpp index 40a0c1b260..0838ac412e 100644 --- a/utils/TableGen/X86DisassemblerTables.cpp +++ b/utils/TableGen/X86DisassemblerTables.cpp @@ -81,16 +81,20 @@ static inline bool inheritsFrom(InstructionContext child, case IC_64BIT_REXW_OPSIZE: return false; case IC_VEX: - return inheritsFrom(child, IC_VEX_W) || + return inheritsFrom(child, IC_VEX_L_W) || + inheritsFrom(child, IC_VEX_W) || (VEX_LIG && inheritsFrom(child, IC_VEX_L)); case IC_VEX_XS: - return inheritsFrom(child, IC_VEX_W_XS) || + return inheritsFrom(child, IC_VEX_L_W_XS) || + inheritsFrom(child, IC_VEX_W_XS) || (VEX_LIG && inheritsFrom(child, IC_VEX_L_XS)); case IC_VEX_XD: - return inheritsFrom(child, IC_VEX_W_XD) || + return inheritsFrom(child, IC_VEX_L_W_XD) || + inheritsFrom(child, IC_VEX_W_XD) || (VEX_LIG && inheritsFrom(child, IC_VEX_L_XD)); case IC_VEX_OPSIZE: - return inheritsFrom(child, IC_VEX_W_OPSIZE) || + return inheritsFrom(child, IC_VEX_L_W_OPSIZE) || + inheritsFrom(child, IC_VEX_W_OPSIZE) || (VEX_LIG && inheritsFrom(child, IC_VEX_L_OPSIZE)); case IC_VEX_W: case IC_VEX_W_XS: @@ -100,11 +104,90 @@ static inline bool inheritsFrom(InstructionContext child, case IC_VEX_L: case IC_VEX_L_XS: case IC_VEX_L_XD: - return false; case IC_VEX_L_OPSIZE: - return inheritsFrom(child, IC_VEX_L_W_OPSIZE); + return false; + case IC_VEX_L_W: + case IC_VEX_L_W_XS: + case IC_VEX_L_W_XD: case IC_VEX_L_W_OPSIZE: return false; + case IC_EVEX: + return inheritsFrom(child, IC_EVEX_W) || + inheritsFrom(child, IC_EVEX_L_W); + case IC_EVEX_XS: + return inheritsFrom(child, IC_EVEX_W_XS) || + inheritsFrom(child, IC_EVEX_L_W_XS); + case IC_EVEX_XD: + return inheritsFrom(child, IC_EVEX_W_XD) || + inheritsFrom(child, IC_EVEX_L_W_XD); + case IC_EVEX_OPSIZE: + return inheritsFrom(child, IC_EVEX_W_OPSIZE) || + inheritsFrom(child, IC_EVEX_W_OPSIZE); + case IC_EVEX_W: + case IC_EVEX_W_XS: + case IC_EVEX_W_XD: + case IC_EVEX_W_OPSIZE: + return false; + case IC_EVEX_L: + case IC_EVEX_L_XS: + case IC_EVEX_L_XD: + case IC_EVEX_L_OPSIZE: + return false; + case IC_EVEX_L_W: + case IC_EVEX_L_W_XS: + case IC_EVEX_L_W_XD: + case IC_EVEX_L_W_OPSIZE: + return false; + case IC_EVEX_L2: + case IC_EVEX_L2_XS: + case IC_EVEX_L2_XD: + case IC_EVEX_L2_OPSIZE: + return false; + case IC_EVEX_L2_W: + case IC_EVEX_L2_W_XS: + case IC_EVEX_L2_W_XD: + case IC_EVEX_L2_W_OPSIZE: + return false; + case IC_EVEX_K: + return inheritsFrom(child, IC_EVEX_W_K) || + inheritsFrom(child, IC_EVEX_L_W_K); + case IC_EVEX_XS_K: + return inheritsFrom(child, IC_EVEX_W_XS_K) || + inheritsFrom(child, IC_EVEX_L_W_XS_K); + case IC_EVEX_XD_K: + return inheritsFrom(child, IC_EVEX_W_XD_K) || + inheritsFrom(child, IC_EVEX_L_W_XD_K); + case IC_EVEX_OPSIZE_K: + return inheritsFrom(child, IC_EVEX_W_OPSIZE_K) || + inheritsFrom(child, IC_EVEX_W_OPSIZE_K); + case IC_EVEX_W_K: + case IC_EVEX_W_XS_K: + case IC_EVEX_W_XD_K: + case IC_EVEX_W_OPSIZE_K: + return false; + case IC_EVEX_L_K: + case IC_EVEX_L_XS_K: + case IC_EVEX_L_XD_K: + case IC_EVEX_L_OPSIZE_K: + return false; + case IC_EVEX_L_W_K: + case IC_EVEX_L_W_XS_K: + case IC_EVEX_L_W_XD_K: + case IC_EVEX_L_W_OPSIZE_K: + return false; + case IC_EVEX_L2_K: + case IC_EVEX_L2_B: + case IC_EVEX_L2_XS_K: + case IC_EVEX_L2_XD_K: + case IC_EVEX_L2_OPSIZE_K: + case IC_EVEX_L2_OPSIZE_B: + return false; + case IC_EVEX_L2_W_K: + case IC_EVEX_L2_W_XS_K: + case IC_EVEX_L2_W_XD_K: + case IC_EVEX_L2_W_OPSIZE_K: + case IC_EVEX_L2_W_OPSIZE_B: + return false; default: llvm_unreachable("Unknown instruction class"); } @@ -123,10 +206,13 @@ static inline bool outranks(InstructionContext upper, assert(lower < IC_max); #define ENUM_ENTRY(n, r, d) r, +#define ENUM_ENTRY_K_B(n, r, d) ENUM_ENTRY(n, r, d) \ + ENUM_ENTRY(n##_K_B, r, d) ENUM_ENTRY(n##_K, r, d) ENUM_ENTRY(n##_B, r, d) static int ranks[IC_max] = { INSTRUCTION_CONTEXTS }; #undef ENUM_ENTRY +#undef ENUM_ENTRY_K_B return (ranks[upper] > ranks[lower]); } @@ -142,8 +228,11 @@ static inline const char* stringForContext(InstructionContext insnContext) { default: llvm_unreachable("Unhandled instruction class"); #define ENUM_ENTRY(n, r, d) case n: return #n; break; +#define ENUM_ENTRY_K_B(n, r, d) ENUM_ENTRY(n, r, d) ENUM_ENTRY(n##_K_B, r, d)\ + ENUM_ENTRY(n##_K, r, d) ENUM_ENTRY(n##_B, r, d) INSTRUCTION_CONTEXTS #undef ENUM_ENTRY +#undef ENUM_ENTRY_K_B } } diff --git a/utils/TableGen/X86RecognizableInstr.cpp b/utils/TableGen/X86RecognizableInstr.cpp index 76d986b1c1..4fe3a07664 100644 --- a/utils/TableGen/X86RecognizableInstr.cpp +++ b/utils/TableGen/X86RecognizableInstr.cpp @@ -236,6 +236,10 @@ RecognizableInstr::RecognizableInstr(DisassemblerTables &tables, HasVEX_WPrefix = Rec->getValueAsBit("hasVEX_WPrefix"); HasMemOp4Prefix = Rec->getValueAsBit("hasMemOp4Prefix"); IgnoresVEX_L = Rec->getValueAsBit("ignoresVEX_L"); + HasEVEXPrefix = Rec->getValueAsBit("hasEVEXPrefix"); + HasEVEX_L2Prefix = Rec->getValueAsBit("hasEVEX_L2"); + HasEVEX_K = Rec->getValueAsBit("hasEVEX_K"); + HasEVEX_B = Rec->getValueAsBit("hasEVEX_B"); HasLockPrefix = Rec->getValueAsBit("hasLockPrefix"); IsCodeGenOnly = Rec->getValueAsBit("isCodeGenOnly"); @@ -295,15 +299,98 @@ void RecognizableInstr::processInstr(DisassemblerTables &tables, recogInstr.emitDecodePath(tables); } +#define EVEX_KB(n) (HasEVEX_K && HasEVEX_B? n##_K_B : \ + (HasEVEX_K? n##_K : (HasEVEX_B ? n##_B : n))) + InstructionContext RecognizableInstr::insnContext() const { InstructionContext insnContext; - if (HasVEX_4VPrefix || HasVEX_4VOp3Prefix|| HasVEXPrefix) { + if (HasEVEXPrefix) { + if (HasVEX_LPrefix && HasEVEX_L2Prefix) { + char msg[200]; + sprintf(msg, "Don't support VEX.L if EVEX_L2 is enabled: %s", Name.c_str()); + llvm_unreachable(msg); + } + // VEX_L & VEX_W + if (HasVEX_LPrefix && HasVEX_WPrefix) { + if (HasOpSizePrefix) + insnContext = EVEX_KB(IC_EVEX_L_W_OPSIZE); + else if (Prefix == X86Local::XS || Prefix == X86Local::T8XS) + insnContext = EVEX_KB(IC_EVEX_L_W_XS); + else if (Prefix == X86Local::XD || Prefix == X86Local::T8XD || + Prefix == X86Local::TAXD) + insnContext = EVEX_KB(IC_EVEX_L_W_XD); + else + insnContext = EVEX_KB(IC_EVEX_L_W); + } else if (HasVEX_LPrefix) { + // VEX_L + if (HasOpSizePrefix) + insnContext = EVEX_KB(IC_EVEX_L_OPSIZE); + else if (Prefix == X86Local::XS || Prefix == X86Local::T8XS) + insnContext = EVEX_KB(IC_EVEX_L_XS); + else if (Prefix == X86Local::XD || Prefix == X86Local::T8XD || + Prefix == X86Local::TAXD) + insnContext = EVEX_KB(IC_EVEX_L_XD); + else + insnContext = EVEX_KB(IC_EVEX_L); + } + else if (HasEVEX_L2Prefix && HasVEX_WPrefix) { + // EVEX_L2 & VEX_W + if (HasOpSizePrefix) + insnContext = EVEX_KB(IC_EVEX_L2_W_OPSIZE); + else if (Prefix == X86Local::XS || Prefix == X86Local::T8XS) + insnContext = EVEX_KB(IC_EVEX_L2_W_XS); + else if (Prefix == X86Local::XD || Prefix == X86Local::T8XD || + Prefix == X86Local::TAXD) + insnContext = EVEX_KB(IC_EVEX_L2_W_XD); + else + insnContext = EVEX_KB(IC_EVEX_L2_W); + } else if (HasEVEX_L2Prefix) { + // EVEX_L2 + if (HasOpSizePrefix) + insnContext = EVEX_KB(IC_EVEX_L2_OPSIZE); + else if (Prefix == X86Local::XD || Prefix == X86Local::T8XD || + Prefix == X86Local::TAXD) + insnContext = EVEX_KB(IC_EVEX_L2_XD); + else if (Prefix == X86Local::XS || Prefix == X86Local::T8XS) + insnContext = EVEX_KB(IC_EVEX_L2_XS); + else + insnContext = EVEX_KB(IC_EVEX_L2); + } + else if (HasVEX_WPrefix) { + // VEX_W + if (HasOpSizePrefix) + insnContext = EVEX_KB(IC_EVEX_W_OPSIZE); + else if (Prefix == X86Local::XS || Prefix == X86Local::T8XS) + insnContext = EVEX_KB(IC_EVEX_W_XS); + else if (Prefix == X86Local::XD || Prefix == X86Local::T8XD || + Prefix == X86Local::TAXD) + insnContext = EVEX_KB(IC_EVEX_W_XD); + else + insnContext = EVEX_KB(IC_EVEX_W); + } + // No L, no W + else if (HasOpSizePrefix) + insnContext = EVEX_KB(IC_EVEX_OPSIZE); + else if (Prefix == X86Local::XD || Prefix == X86Local::T8XD || + Prefix == X86Local::TAXD) + insnContext = EVEX_KB(IC_EVEX_XD); + else if (Prefix == X86Local::XS || Prefix == X86Local::T8XS) + insnContext = EVEX_KB(IC_EVEX_XS); + else + insnContext = EVEX_KB(IC_EVEX); + /// eof EVEX + } else if (HasVEX_4VPrefix || HasVEX_4VOp3Prefix|| HasVEXPrefix) { if (HasVEX_LPrefix && HasVEX_WPrefix) { if (HasOpSizePrefix) insnContext = IC_VEX_L_W_OPSIZE; + else if (Prefix == X86Local::XS || Prefix == X86Local::T8XS) + insnContext = IC_VEX_L_W_XS; + else if (Prefix == X86Local::XD || Prefix == X86Local::T8XD || + Prefix == X86Local::TAXD) + insnContext = IC_VEX_L_W_XD; else - llvm_unreachable("Don't support VEX.L and VEX.W together"); + insnContext = IC_VEX_L_W; } else if (HasOpSizePrefix && HasVEX_LPrefix) insnContext = IC_VEX_L_OPSIZE; else if (HasOpSizePrefix && HasVEX_WPrefix) @@ -641,6 +728,9 @@ void RecognizableInstr::emitInstructionSpecifier(DisassemblerTables &tables) { "Unexpected number of operands for MRMDestMemFrm"); HANDLE_OPERAND(memory) + if (HasEVEX_K) + HANDLE_OPERAND(writemaskRegister) + if (HasVEX_4VPrefix) // FIXME: In AVX, the register below becomes the one encoded // in ModRMVEX and the one above the one in the VEX.VVVV field @@ -665,6 +755,9 @@ void RecognizableInstr::emitInstructionSpecifier(DisassemblerTables &tables) { HANDLE_OPERAND(roRegister) + if (HasEVEX_K) + HANDLE_OPERAND(writemaskRegister) + if (HasVEX_4VPrefix) // FIXME: In AVX, the register below becomes the one encoded // in ModRMVEX and the one above the one in the VEX.VVVV field @@ -698,6 +791,9 @@ void RecognizableInstr::emitInstructionSpecifier(DisassemblerTables &tables) { HANDLE_OPERAND(roRegister) + if (HasEVEX_K) + HANDLE_OPERAND(writemaskRegister) + if (HasVEX_4VPrefix) // FIXME: In AVX, the register below becomes the one encoded // in ModRMVEX and the one above the one in the VEX.VVVV field @@ -1079,17 +1175,22 @@ OperandType RecognizableInstr::typeFromString(const std::string &s, TYPE("i8imm", TYPE_IMM8) TYPE("GR8", TYPE_R8) TYPE("VR128", TYPE_XMM128) + TYPE("VR128X", TYPE_XMM128) TYPE("f128mem", TYPE_M128) TYPE("f256mem", TYPE_M256) + TYPE("f512mem", TYPE_M512) TYPE("FR64", TYPE_XMM64) + TYPE("FR64X", TYPE_XMM64) TYPE("f64mem", TYPE_M64FP) TYPE("sdmem", TYPE_M64FP) TYPE("FR32", TYPE_XMM32) + TYPE("FR32X", TYPE_XMM32) TYPE("f32mem", TYPE_M32FP) TYPE("ssmem", TYPE_M32FP) TYPE("RST", TYPE_ST) TYPE("i128mem", TYPE_M128) TYPE("i256mem", TYPE_M256) + TYPE("i512mem", TYPE_M512) TYPE("i64i32imm_pcrel", TYPE_REL64) TYPE("i16imm_pcrel", TYPE_REL16) TYPE("i32imm_pcrel", TYPE_REL32) @@ -1116,13 +1217,22 @@ OperandType RecognizableInstr::typeFromString(const std::string &s, TYPE("offset32", TYPE_MOFFS32) TYPE("offset64", TYPE_MOFFS64) TYPE("VR256", TYPE_XMM256) + TYPE("VR256X", TYPE_XMM256) + TYPE("VR512", TYPE_XMM512) + TYPE("VK8", TYPE_VK8) + TYPE("VK8WM", TYPE_VK8) + TYPE("VK16", TYPE_VK16) + TYPE("VK16WM", TYPE_VK16) TYPE("GR16_NOAX", TYPE_Rv) TYPE("GR32_NOAX", TYPE_Rv) TYPE("GR64_NOAX", TYPE_R64) TYPE("vx32mem", TYPE_M32) TYPE("vy32mem", TYPE_M32) + TYPE("vz32mem", TYPE_M32) TYPE("vx64mem", TYPE_M64) TYPE("vy64mem", TYPE_M64) + TYPE("vy64xmem", TYPE_M64) + TYPE("vz64mem", TYPE_M64) errs() << "Unhandled type string " << s << "\n"; llvm_unreachable("Unhandled type string"); } @@ -1149,10 +1259,15 @@ OperandEncoding RecognizableInstr::immediateEncodingFromString ENCODING("i8imm", ENCODING_IB) // This is not a typo. Instructions like BLENDVPD put // register IDs in 8-bit immediates nowadays. - ENCODING("VR256", ENCODING_IB) - ENCODING("VR128", ENCODING_IB) ENCODING("FR32", ENCODING_IB) ENCODING("FR64", ENCODING_IB) + ENCODING("VR128", ENCODING_IB) + ENCODING("VR256", ENCODING_IB) + ENCODING("FR32X", ENCODING_IB) + ENCODING("FR64X", ENCODING_IB) + ENCODING("VR128X", ENCODING_IB) + ENCODING("VR256X", ENCODING_IB) + ENCODING("VR512", ENCODING_IB) errs() << "Unhandled immediate encoding " << s << "\n"; llvm_unreachable("Unhandled immediate encoding"); } @@ -1165,10 +1280,17 @@ OperandEncoding RecognizableInstr::rmRegisterEncodingFromString ENCODING("GR64", ENCODING_RM) ENCODING("GR8", ENCODING_RM) ENCODING("VR128", ENCODING_RM) + ENCODING("VR128X", ENCODING_RM) ENCODING("FR64", ENCODING_RM) ENCODING("FR32", ENCODING_RM) + ENCODING("FR64X", ENCODING_RM) + ENCODING("FR32X", ENCODING_RM) ENCODING("VR64", ENCODING_RM) ENCODING("VR256", ENCODING_RM) + ENCODING("VR256X", ENCODING_RM) + ENCODING("VR512", ENCODING_RM) + ENCODING("VK8", ENCODING_RM) + ENCODING("VK16", ENCODING_RM) errs() << "Unhandled R/M register encoding " << s << "\n"; llvm_unreachable("Unhandled R/M register encoding"); } @@ -1188,6 +1310,15 @@ OperandEncoding RecognizableInstr::roRegisterEncodingFromString ENCODING("DEBUG_REG", ENCODING_REG) ENCODING("CONTROL_REG", ENCODING_REG) ENCODING("VR256", ENCODING_REG) + ENCODING("VR256X", ENCODING_REG) + ENCODING("VR128X", ENCODING_REG) + ENCODING("FR64X", ENCODING_REG) + ENCODING("FR32X", ENCODING_REG) + ENCODING("VR512", ENCODING_REG) + ENCODING("VK8", ENCODING_REG) + ENCODING("VK16", ENCODING_REG) + ENCODING("VK8WM", ENCODING_REG) + ENCODING("VK16WM", ENCODING_REG) errs() << "Unhandled reg/opcode register encoding " << s << "\n"; llvm_unreachable("Unhandled reg/opcode register encoding"); } @@ -1201,10 +1332,26 @@ OperandEncoding RecognizableInstr::vvvvRegisterEncodingFromString ENCODING("FR64", ENCODING_VVVV) ENCODING("VR128", ENCODING_VVVV) ENCODING("VR256", ENCODING_VVVV) + ENCODING("FR32X", ENCODING_VVVV) + ENCODING("FR64X", ENCODING_VVVV) + ENCODING("VR128X", ENCODING_VVVV) + ENCODING("VR256X", ENCODING_VVVV) + ENCODING("VR512", ENCODING_VVVV) + ENCODING("VK8", ENCODING_VVVV) + ENCODING("VK16", ENCODING_VVVV) errs() << "Unhandled VEX.vvvv register encoding " << s << "\n"; llvm_unreachable("Unhandled VEX.vvvv register encoding"); } +OperandEncoding RecognizableInstr::writemaskRegisterEncodingFromString + (const std::string &s, + bool hasOpSizePrefix) { + ENCODING("VK8WM", ENCODING_WRITEMASK) + ENCODING("VK16WM", ENCODING_WRITEMASK) + errs() << "Unhandled mask register encoding " << s << "\n"; + llvm_unreachable("Unhandled mask register encoding"); +} + OperandEncoding RecognizableInstr::memoryEncodingFromString (const std::string &s, bool hasOpSizePrefix) { @@ -1216,10 +1363,12 @@ OperandEncoding RecognizableInstr::memoryEncodingFromString ENCODING("sdmem", ENCODING_RM) ENCODING("f128mem", ENCODING_RM) ENCODING("f256mem", ENCODING_RM) + ENCODING("f512mem", ENCODING_RM) ENCODING("f64mem", ENCODING_RM) ENCODING("f32mem", ENCODING_RM) ENCODING("i128mem", ENCODING_RM) ENCODING("i256mem", ENCODING_RM) + ENCODING("i512mem", ENCODING_RM) ENCODING("f80mem", ENCODING_RM) ENCODING("lea32mem", ENCODING_RM) ENCODING("lea64_32mem", ENCODING_RM) @@ -1230,8 +1379,11 @@ OperandEncoding RecognizableInstr::memoryEncodingFromString ENCODING("opaque512mem", ENCODING_RM) ENCODING("vx32mem", ENCODING_RM) ENCODING("vy32mem", ENCODING_RM) + ENCODING("vz32mem", ENCODING_RM) ENCODING("vx64mem", ENCODING_RM) ENCODING("vy64mem", ENCODING_RM) + ENCODING("vy64xmem", ENCODING_RM) + ENCODING("vz64mem", ENCODING_RM) errs() << "Unhandled memory encoding " << s << "\n"; llvm_unreachable("Unhandled memory encoding"); } diff --git a/utils/TableGen/X86RecognizableInstr.h b/utils/TableGen/X86RecognizableInstr.h index 9ec36a39df..7e1d362e6a 100644 --- a/utils/TableGen/X86RecognizableInstr.h +++ b/utils/TableGen/X86RecognizableInstr.h @@ -66,6 +66,14 @@ private: bool HasMemOp4Prefix; /// The ignoreVEX_L field from the record bool IgnoresVEX_L; + /// The hasEVEXPrefix field from the record + bool HasEVEXPrefix; + /// The hasEVEX_L2Prefix field from the record + bool HasEVEX_L2Prefix; + /// The hasEVEX_K field from the record + bool HasEVEX_K; + /// The hasEVEX_B field from the record + bool HasEVEX_B; /// The hasLockPrefix field from the record bool HasLockPrefix; /// The isCodeGenOnly filed from the record @@ -176,6 +184,8 @@ private: bool hasOpSizePrefix); static OperandEncoding vvvvRegisterEncodingFromString(const std::string &s, bool HasOpSizePrefix); + static OperandEncoding writemaskRegisterEncodingFromString(const std::string &s, + bool HasOpSizePrefix); /// handleOperand - Converts a single operand from the LLVM table format to /// the emitted table format, handling any duplicate operands it encounters |