From 98f21a2a28792a27a25340387a7f939f69b76a34 Mon Sep 17 00:00:00 2001 From: Ryan Houdek Date: Fri, 8 Dec 2023 08:06:59 -0800 Subject: [PATCH] X86Tables: Converts tables to be mostly consteval Reduces the ELF's VM size from 9.8MB down to 9.37MB and should reduce initialization time a smidge. Slammed this out while waiting for other PRs to get reviewed. --- FEXCore/Source/Interface/Core/X86Tables.cpp | 35 -------- .../Interface/Core/X86Tables/BaseTables.cpp | 14 ++- .../Interface/Core/X86Tables/DDDTables.cpp | 11 ++- .../Interface/Core/X86Tables/EVEXTables.cpp | 13 +-- .../Interface/Core/X86Tables/H0F38Tables.cpp | 11 ++- .../Interface/Core/X86Tables/H0F3ATables.cpp | 17 ++-- .../Core/X86Tables/PrimaryGroupTables.cpp | 13 +-- .../Core/X86Tables/SecondaryGroupTables.cpp | 11 +-- .../Core/X86Tables/SecondaryModRMTables.cpp | 12 +-- .../Core/X86Tables/SecondaryTables.cpp | 85 +++++++++++++------ .../Interface/Core/X86Tables/VEXTables.cpp | 22 +++-- .../Interface/Core/X86Tables/X86Tables.h | 37 ++++++-- .../Interface/Core/X86Tables/X87Tables.cpp | 12 +-- .../Interface/Core/X86Tables/XOPTables.cpp | 22 +++-- 14 files changed, 189 insertions(+), 126 deletions(-) diff --git a/FEXCore/Source/Interface/Core/X86Tables.cpp b/FEXCore/Source/Interface/Core/X86Tables.cpp index 6ce9dc96d4..430de34730 100644 --- a/FEXCore/Source/Interface/Core/X86Tables.cpp +++ b/FEXCore/Source/Interface/Core/X86Tables.cpp @@ -12,51 +12,16 @@ tags: frontend|x86-tables namespace FEXCore::X86Tables { -std::array BaseOps{}; -std::array SecondBaseOps{}; -std::array RepModOps{}; -std::array RepNEModOps{}; -std::array OpSizeModOps{}; - -std::array PrimaryInstGroupOps{}; -std::array SecondInstGroupOps{}; -std::array SecondModRMTableOps{}; -std::array X87Ops{}; -std::array DDDNowOps{}; -std::array H0F38TableOps{}; -std::array H0F3ATableOps{}; -std::array VEXTableOps{}; -std::array VEXTableGroupOps{}; -std::array XOPTableOps{}; -std::array XOPTableGroupOps{}; -std::array EVEXTableOps{}; - void InitializeBaseTables(Context::OperatingMode Mode); void InitializeSecondaryTables(Context::OperatingMode Mode); void InitializePrimaryGroupTables(Context::OperatingMode Mode); -void InitializeSecondaryGroupTables(); -void InitializeSecondaryModRMTables(); -void InitializeX87Tables(); -void InitializeDDDTables(); -void InitializeH0F38Tables(); void InitializeH0F3ATables(Context::OperatingMode Mode); -void InitializeVEXTables(); -void InitializeXOPTables(); -void InitializeEVEXTables(); void InitializeInfoTables(Context::OperatingMode Mode) { InitializeBaseTables(Mode); InitializeSecondaryTables(Mode); InitializePrimaryGroupTables(Mode); - InitializeSecondaryGroupTables(); - InitializeSecondaryModRMTables(); - InitializeX87Tables(); - InitializeDDDTables(); - InitializeH0F38Tables(); InitializeH0F3ATables(Mode); - InitializeVEXTables(); - InitializeXOPTables(); - InitializeEVEXTables(); } } diff --git a/FEXCore/Source/Interface/Core/X86Tables/BaseTables.cpp b/FEXCore/Source/Interface/Core/X86Tables/BaseTables.cpp index 2361b28c50..e72b8876e1 100644 --- a/FEXCore/Source/Interface/Core/X86Tables/BaseTables.cpp +++ b/FEXCore/Source/Interface/Core/X86Tables/BaseTables.cpp @@ -14,8 +14,10 @@ tags: frontend|x86-tables namespace FEXCore::X86Tables { using namespace InstFlags; -void InitializeBaseTables(Context::OperatingMode Mode) { - static constexpr U8U8InfoStruct BaseOpTable[] = { +std::array BaseOps = []() consteval { + std::array Table{}; + + constexpr U8U8InfoStruct BaseOpTable[] = { // Prefixes // Operand size overide {0x66, 1, X86InstInfo{"", TYPE_PREFIX, FLAGS_NONE, 0, nullptr}}, @@ -233,6 +235,12 @@ void InitializeBaseTables(Context::OperatingMode Mode) { {0xC4, 2, X86InstInfo{"", TYPE_VEX_TABLE_PREFIX, FLAGS_NONE, 0, nullptr}}, }; + GenerateTable(&Table.at(0), BaseOpTable, std::size(BaseOpTable)); + + return Table; +}(); + +void InitializeBaseTables(Context::OperatingMode Mode) { static constexpr U8U8InfoStruct BaseOpTable_64[] = { {0x06, 2, X86InstInfo{"[INV]", TYPE_INVALID, FLAGS_NONE, 0, nullptr}}, {0x0E, 1, X86InstInfo{"[INV]", TYPE_INVALID, FLAGS_NONE, 0, nullptr}}, @@ -291,8 +299,6 @@ void InitializeBaseTables(Context::OperatingMode Mode) { {0xEA, 1, X86InstInfo{"JMPF", TYPE_INST, FLAGS_NONE, 0, nullptr}}, }; - GenerateTable(&BaseOps.at(0), BaseOpTable, std::size(BaseOpTable)); - if (Mode == Context::MODE_64BIT) { GenerateTable(&BaseOps.at(0), BaseOpTable_64, std::size(BaseOpTable_64)); } diff --git a/FEXCore/Source/Interface/Core/X86Tables/DDDTables.cpp b/FEXCore/Source/Interface/Core/X86Tables/DDDTables.cpp index 6124967529..7bd69351e6 100644 --- a/FEXCore/Source/Interface/Core/X86Tables/DDDTables.cpp +++ b/FEXCore/Source/Interface/Core/X86Tables/DDDTables.cpp @@ -12,8 +12,9 @@ tags: frontend|x86-tables namespace FEXCore::X86Tables { using namespace InstFlags; -void InitializeDDDTables() { - static constexpr U8U8InfoStruct DDDNowOpTable[] = { +std::array DDDNowOps = []() consteval { + std::array Table{}; + constexpr U8U8InfoStruct DDDNowOpTable[] = { {0x0C, 1, X86InstInfo{"PI2FW", TYPE_INST, GenFlagsSameSize(SIZE_64BIT) | FLAGS_MODRM | FLAGS_XMM_FLAGS | FLAGS_SF_MMX, 0, nullptr}}, {0x0D, 1, X86InstInfo{"PI2FD", TYPE_INST, GenFlagsSameSize(SIZE_64BIT) | FLAGS_MODRM | FLAGS_XMM_FLAGS | FLAGS_SF_MMX, 0, nullptr}}, {0x1C, 1, X86InstInfo{"PF2IW", TYPE_INST, GenFlagsSameSize(SIZE_64BIT) | FLAGS_MODRM | FLAGS_XMM_FLAGS | FLAGS_SF_MMX, 0, nullptr}}, @@ -52,6 +53,8 @@ void InitializeDDDTables() { {0xBF, 1, X86InstInfo{"PAVGUSB", TYPE_INST, GenFlagsSameSize(SIZE_64BIT) | FLAGS_MODRM | FLAGS_XMM_FLAGS | FLAGS_SF_MMX, 0, nullptr}}, }; - GenerateTable(&DDDNowOps.at(0), DDDNowOpTable, std::size(DDDNowOpTable)); -} + GenerateTable(&Table.at(0), DDDNowOpTable, std::size(DDDNowOpTable)); + return Table; +}(); + } diff --git a/FEXCore/Source/Interface/Core/X86Tables/EVEXTables.cpp b/FEXCore/Source/Interface/Core/X86Tables/EVEXTables.cpp index 2a51872f37..f3c23be0f3 100644 --- a/FEXCore/Source/Interface/Core/X86Tables/EVEXTables.cpp +++ b/FEXCore/Source/Interface/Core/X86Tables/EVEXTables.cpp @@ -11,9 +11,9 @@ tags: frontend|x86-tables namespace FEXCore::X86Tables { using namespace InstFlags; - -void InitializeEVEXTables() { - static constexpr U16U8InfoStruct EVEXTable[] = { +std::array EVEXTableOps = []() consteval { + std::array Table{}; + constexpr U16U8InfoStruct EVEXTable[] = { {0x10, 1, X86InstInfo{"VMOVUPS", TYPE_INST, FLAGS_MODRM | FLAGS_XMM_FLAGS, 0, nullptr}}, {0x11, 1, X86InstInfo{"VMOVUPS", TYPE_INST, FLAGS_MODRM | FLAGS_SF_MOD_DST | FLAGS_XMM_FLAGS, 0, nullptr}}, {0x18, 1, X86InstInfo{"VBROADCASTSS", TYPE_INST, FLAGS_MODRM | FLAGS_XMM_FLAGS, 0, nullptr}}, @@ -29,6 +29,9 @@ void InitializeEVEXTables() { {0xE7, 1, X86InstInfo{"VMOVNTDQ", TYPE_INST, FLAGS_MODRM | FLAGS_SF_MOD_DST | FLAGS_XMM_FLAGS, 0, nullptr}}, }; - GenerateTable(&EVEXTableOps.at(0), EVEXTable, std::size(EVEXTable)); -} + GenerateTable(&Table.at(0), EVEXTable, std::size(EVEXTable)); + + return Table; +}(); + } diff --git a/FEXCore/Source/Interface/Core/X86Tables/H0F38Tables.cpp b/FEXCore/Source/Interface/Core/X86Tables/H0F38Tables.cpp index 621ec8475a..af8a5bf457 100644 --- a/FEXCore/Source/Interface/Core/X86Tables/H0F38Tables.cpp +++ b/FEXCore/Source/Interface/Core/X86Tables/H0F38Tables.cpp @@ -12,15 +12,16 @@ tags: frontend|x86-tables namespace FEXCore::X86Tables { using namespace InstFlags; +std::array H0F38TableOps = []() consteval { + std::array Table{}; -void InitializeH0F38Tables() { #define OPD(prefix, opcode) (((prefix) << 8) | opcode) constexpr uint16_t PF_38_NONE = 0; constexpr uint16_t PF_38_66 = (1U << 0); constexpr uint16_t PF_38_F2 = (1U << 1); constexpr uint16_t PF_38_F3 = (1U << 2); - static constexpr U16U8InfoStruct H0F38Table[] = { + constexpr U16U8InfoStruct H0F38Table[] = { {OPD(PF_38_NONE, 0x00), 1, X86InstInfo{"PSHUFB", TYPE_INST, GenFlagsSameSize(SIZE_64BIT) | FLAGS_MODRM | FLAGS_XMM_FLAGS | FLAGS_SF_MMX, 0, nullptr}}, {OPD(PF_38_66, 0x00), 1, X86InstInfo{"PSHUFB", TYPE_INST, GenFlagsSameSize(SIZE_128BIT) | FLAGS_MODRM | FLAGS_XMM_FLAGS, 0, nullptr}}, {OPD(PF_38_NONE, 0x01), 1, X86InstInfo{"PHADDW", TYPE_INST, GenFlagsSameSize(SIZE_64BIT) | FLAGS_MODRM | FLAGS_XMM_FLAGS | FLAGS_SF_MMX, 0, nullptr}}, @@ -117,6 +118,8 @@ void InitializeH0F38Tables() { }; #undef OPD - GenerateTable(&H0F38TableOps.at(0), H0F38Table, std::size(H0F38Table)); -} + GenerateTable(&Table.at(0), H0F38Table, std::size(H0F38Table)); + return Table; +}(); + } diff --git a/FEXCore/Source/Interface/Core/X86Tables/H0F3ATables.cpp b/FEXCore/Source/Interface/Core/X86Tables/H0F3ATables.cpp index bee92b64d7..bfb12ed7f3 100644 --- a/FEXCore/Source/Interface/Core/X86Tables/H0F3ATables.cpp +++ b/FEXCore/Source/Interface/Core/X86Tables/H0F3ATables.cpp @@ -14,13 +14,13 @@ tags: frontend|x86-tables namespace FEXCore::X86Tables { using namespace InstFlags; - -void InitializeH0F3ATables(Context::OperatingMode Mode) { #define OPD(REX, prefix, opcode) ((REX << 9) | (prefix << 8) | opcode) - constexpr uint16_t PF_3A_NONE = 0; - constexpr uint16_t PF_3A_66 = 1; +constexpr uint16_t PF_3A_NONE = 0; +constexpr uint16_t PF_3A_66 = 1; - static constexpr U16U8InfoStruct H0F3ATable[] = { +std::array H0F3ATableOps = []() consteval { + std::array Table{}; + constexpr U16U8InfoStruct H0F3ATable[] = { {OPD(0, PF_3A_NONE, 0x0F), 1, X86InstInfo{"PALIGNR", TYPE_INST, GenFlagsSameSize(SIZE_64BIT) | FLAGS_MODRM | FLAGS_XMM_FLAGS | FLAGS_SF_MMX, 1, nullptr}}, {OPD(0, PF_3A_66, 0x08), 1, X86InstInfo{"ROUNDPS", TYPE_INST, GenFlagsSameSize(SIZE_128BIT) | FLAGS_MODRM | FLAGS_XMM_FLAGS, 1, nullptr}}, {OPD(0, PF_3A_66, 0x09), 1, X86InstInfo{"ROUNDPD", TYPE_INST, GenFlagsSameSize(SIZE_128BIT) | FLAGS_MODRM | FLAGS_XMM_FLAGS, 1, nullptr}}, @@ -54,6 +54,11 @@ void InitializeH0F3ATables(Context::OperatingMode Mode) { {OPD(0, PF_3A_66, 0xDF), 1, X86InstInfo{"AESKEYGENASSIST", TYPE_INST, GenFlagsSameSize(SIZE_128BIT) | FLAGS_MODRM | FLAGS_XMM_FLAGS, 1, nullptr}}, }; + GenerateTable(&Table.at(0), H0F3ATable, std::size(H0F3ATable)); + return Table; +}(); + +void InitializeH0F3ATables(Context::OperatingMode Mode) { static constexpr U16U8InfoStruct H0F3ATable_64[] = { {OPD(1, PF_3A_66, 0x0F), 1, X86InstInfo{"PALIGNR", TYPE_INST, GenFlagsSameSize(SIZE_128BIT) | FLAGS_MODRM | FLAGS_XMM_FLAGS, 1, nullptr}}, {OPD(1, PF_3A_66, 0x16), 1, X86InstInfo{"PEXTRQ", TYPE_INST, GenFlagsSizes(SIZE_64BIT, SIZE_128BIT) | FLAGS_MODRM | FLAGS_SF_MOD_DST | FLAGS_SF_DST_GPR | FLAGS_XMM_FLAGS, 1, nullptr}}, @@ -62,8 +67,6 @@ void InitializeH0F3ATables(Context::OperatingMode Mode) { #undef OPD - GenerateTable(&H0F3ATableOps.at(0), H0F3ATable, std::size(H0F3ATable)); - if (Mode == Context::MODE_64BIT) { GenerateTable(&H0F3ATableOps.at(0), H0F3ATable_64, std::size(H0F3ATable_64)); } diff --git a/FEXCore/Source/Interface/Core/X86Tables/PrimaryGroupTables.cpp b/FEXCore/Source/Interface/Core/X86Tables/PrimaryGroupTables.cpp index 2ffb90942e..9d2206564d 100644 --- a/FEXCore/Source/Interface/Core/X86Tables/PrimaryGroupTables.cpp +++ b/FEXCore/Source/Interface/Core/X86Tables/PrimaryGroupTables.cpp @@ -13,10 +13,10 @@ tags: frontend|x86-tables namespace FEXCore::X86Tables { using namespace InstFlags; - -void InitializePrimaryGroupTables(Context::OperatingMode Mode) { +std::array PrimaryInstGroupOps = []() consteval { + std::array Table{}; #define OPD(group, prefix, Reg) (((group - FEXCore::X86Tables::TYPE_GROUP_1) << 6) | (prefix) << 3 | (Reg)) - const U16U8InfoStruct PrimaryGroupOpTable[] = { + constexpr U16U8InfoStruct PrimaryGroupOpTable[] = { // GROUP_1 | 0x80 | reg {OPD(TYPE_GROUP_1, OpToIndex(0x80), 0), 1, X86InstInfo{"ADD", TYPE_INST, GenFlagsSameSize(SIZE_8BIT) | FLAGS_MODRM | FLAGS_SF_MOD_DST, 1, nullptr}}, {OPD(TYPE_GROUP_1, OpToIndex(0x80), 1), 1, X86InstInfo{"OR", TYPE_INST, GenFlagsSameSize(SIZE_8BIT) | FLAGS_MODRM | FLAGS_SF_MOD_DST, 1, nullptr}}, @@ -141,9 +141,13 @@ void InitializePrimaryGroupTables(Context::OperatingMode Mode) { {OPD(TYPE_GROUP_11, OpToIndex(0xC7), 0), 1, X86InstInfo{"MOV", TYPE_INST, FLAGS_MODRM | FLAGS_SF_MOD_DST | FLAGS_SRC_SEXT | FLAGS_DISPLACE_SIZE_DIV_2, 4, nullptr}}, {OPD(TYPE_GROUP_11, OpToIndex(0xC7), 1), 5, X86InstInfo{"", TYPE_INVALID, FLAGS_NONE, 0, nullptr}}, {OPD(TYPE_GROUP_11, OpToIndex(0xC7), 7), 1, X86InstInfo{"XBEGIN", TYPE_INST, FLAGS_MODRM | FLAGS_SRC_SEXT | FLAGS_SETS_RIP | FLAGS_DISPLACE_SIZE_DIV_2, 4, nullptr}}, - }; + GenerateTable(&Table.at(0), PrimaryGroupOpTable, std::size(PrimaryGroupOpTable)); + return Table; +}(); + +void InitializePrimaryGroupTables(Context::OperatingMode Mode) { const U16U8InfoStruct PrimaryGroupOpTable_64[] = { // Invalid in 64bit mode {OPD(TYPE_GROUP_1, OpToIndex(0x82), 0), 8, X86InstInfo{"", TYPE_INVALID, FLAGS_NONE, 0, nullptr}}, @@ -163,7 +167,6 @@ void InitializePrimaryGroupTables(Context::OperatingMode Mode) { #undef OPD - GenerateTable(&PrimaryInstGroupOps.at(0), PrimaryGroupOpTable, std::size(PrimaryGroupOpTable)); if (Mode == Context::MODE_64BIT) { GenerateTable(&PrimaryInstGroupOps.at(0), PrimaryGroupOpTable_64, std::size(PrimaryGroupOpTable_64)); } diff --git a/FEXCore/Source/Interface/Core/X86Tables/SecondaryGroupTables.cpp b/FEXCore/Source/Interface/Core/X86Tables/SecondaryGroupTables.cpp index 3a0ac7dfb6..4965b81d3d 100644 --- a/FEXCore/Source/Interface/Core/X86Tables/SecondaryGroupTables.cpp +++ b/FEXCore/Source/Interface/Core/X86Tables/SecondaryGroupTables.cpp @@ -12,15 +12,15 @@ tags: frontend|x86-tables namespace FEXCore::X86Tables { using namespace InstFlags; - -void InitializeSecondaryGroupTables() { +std::array SecondInstGroupOps = []() consteval { + std::array Table{}; #define OPD(group, prefix, Reg) (((group - FEXCore::X86Tables::TYPE_GROUP_6) << 5) | (prefix) << 3 | (Reg)) constexpr uint16_t PF_NONE = 0; constexpr uint16_t PF_F3 = 1; constexpr uint16_t PF_66 = 2; constexpr uint16_t PF_F2 = 3; - static constexpr U16U8InfoStruct SecondaryExtensionOpTable[] = { + constexpr U16U8InfoStruct SecondaryExtensionOpTable[] = { // GROUP 1 // GROUP 2 // GROUP 3 @@ -487,7 +487,8 @@ void InitializeSecondaryGroupTables() { }; #undef OPD - GenerateTable(&SecondInstGroupOps.at(0), SecondaryExtensionOpTable, std::size(SecondaryExtensionOpTable)); -} + GenerateTable(&Table.at(0), SecondaryExtensionOpTable, std::size(SecondaryExtensionOpTable)); + return Table; +}(); } diff --git a/FEXCore/Source/Interface/Core/X86Tables/SecondaryModRMTables.cpp b/FEXCore/Source/Interface/Core/X86Tables/SecondaryModRMTables.cpp index 324596536b..71df4a44e2 100644 --- a/FEXCore/Source/Interface/Core/X86Tables/SecondaryModRMTables.cpp +++ b/FEXCore/Source/Interface/Core/X86Tables/SecondaryModRMTables.cpp @@ -11,9 +11,9 @@ tags: frontend|x86-tables namespace FEXCore::X86Tables { using namespace InstFlags; - -void InitializeSecondaryModRMTables() { - static constexpr U8U8InfoStruct SecondaryModRMExtensionOpTable[] = { +std::array SecondModRMTableOps = []() consteval { + std::array Table{}; + constexpr U8U8InfoStruct SecondaryModRMExtensionOpTable[] = { // REG /1 {((0 << 3) | 0), 1, X86InstInfo{"MONITOR", TYPE_PRIV, FLAGS_NONE, 0, nullptr}}, {((0 << 3) | 1), 1, X86InstInfo{"MWAIT", TYPE_PRIV, FLAGS_NONE, 0, nullptr}}, @@ -55,6 +55,8 @@ void InitializeSecondaryModRMTables() { {((3 << 3) | 7), 1, X86InstInfo{"", TYPE_INVALID, FLAGS_NONE, 0, nullptr}}, }; - GenerateTable(&SecondModRMTableOps.at(0), SecondaryModRMExtensionOpTable, std::size(SecondaryModRMExtensionOpTable)); -} + GenerateTable(&Table.at(0), SecondaryModRMExtensionOpTable, std::size(SecondaryModRMExtensionOpTable)); + return Table; +}(); + } diff --git a/FEXCore/Source/Interface/Core/X86Tables/SecondaryTables.cpp b/FEXCore/Source/Interface/Core/X86Tables/SecondaryTables.cpp index a1bd438954..60091b2d13 100644 --- a/FEXCore/Source/Interface/Core/X86Tables/SecondaryTables.cpp +++ b/FEXCore/Source/Interface/Core/X86Tables/SecondaryTables.cpp @@ -13,9 +13,10 @@ tags: frontend|x86-tables namespace FEXCore::X86Tables { using namespace InstFlags; +auto BaseOpsLambda = []() consteval { + std::array Table{}; -void InitializeSecondaryTables(Context::OperatingMode Mode) { - static constexpr U8U8InfoStruct TwoByteOpTable[] = { + constexpr U8U8InfoStruct TwoByteOpTable[] = { // Instructions {0x00, 1, X86InstInfo{"", TYPE_GROUP_6, FLAGS_MODRM | FLAGS_NO_OVERLAY, 0, nullptr}}, {0x01, 1, X86InstInfo{"", TYPE_GROUP_7, FLAGS_NO_OVERLAY, 0, nullptr}}, @@ -166,11 +167,13 @@ void InitializeSecondaryTables(Context::OperatingMode Mode) { {0x9E, 1, X86InstInfo{"SETLE", TYPE_INST, GenFlagsSameSize(SIZE_8BIT) | FLAGS_MODRM | FLAGS_SF_MOD_DST | FLAGS_NO_OVERLAY, 0, nullptr}}, {0x9F, 1, X86InstInfo{"SETNLE", TYPE_INST, GenFlagsSameSize(SIZE_8BIT) | FLAGS_MODRM | FLAGS_SF_MOD_DST | FLAGS_NO_OVERLAY, 0, nullptr}}, + {0xA0, 2, X86InstInfo{"", TYPE_COPY_OTHER, FLAGS_NONE, 0, nullptr}}, {0xA2, 1, X86InstInfo{"CPUID", TYPE_INST, FLAGS_SF_SRC_RAX | FLAGS_NO_OVERLAY, 0, nullptr}}, {0xA3, 1, X86InstInfo{"BT", TYPE_INST, FLAGS_DEBUG_MEM_ACCESS | FLAGS_MODRM | FLAGS_SF_MOD_DST | FLAGS_NO_OVERLAY, 0, nullptr}}, {0xA4, 1, X86InstInfo{"SHLD", TYPE_INST, FLAGS_MODRM | FLAGS_SF_MOD_DST | FLAGS_NO_OVERLAY, 1, nullptr}}, {0xA5, 1, X86InstInfo{"SHLD", TYPE_INST, FLAGS_MODRM | FLAGS_SF_MOD_DST | FLAGS_SF_SRC_RCX | FLAGS_NO_OVERLAY, 0, nullptr}}, {0xA6, 2, X86InstInfo{"", TYPE_INVALID, FLAGS_NO_OVERLAY, 0, nullptr}}, + {0xA8, 2, X86InstInfo{"", TYPE_COPY_OTHER, FLAGS_NONE, 0, nullptr}}, {0xAA, 1, X86InstInfo{"RSM", TYPE_PRIV, FLAGS_NO_OVERLAY, 0, nullptr}}, {0xAB, 1, X86InstInfo{"BTS", TYPE_INST, FLAGS_DEBUG_MEM_ACCESS | FLAGS_MODRM | FLAGS_SF_MOD_DST | FLAGS_NO_OVERLAY, 0, nullptr}}, {0xAC, 1, X86InstInfo{"SHRD", TYPE_INST, FLAGS_MODRM | FLAGS_SF_MOD_DST | FLAGS_NO_OVERLAY, 1, nullptr}}, @@ -265,23 +268,16 @@ void InitializeSecondaryTables(Context::OperatingMode Mode) { {0x3F, 1, X86InstInfo{"ALTINST", TYPE_INST, FLAGS_BLOCK_END | FLAGS_NO_OVERLAY | FLAGS_SETS_RIP, 0, nullptr}}, }; - static constexpr U8U8InfoStruct TwoByteOpTable_32[] = { - {0xA0, 1, X86InstInfo{"PUSH FS", TYPE_INST, GenFlagsSrcSize(SIZE_16BIT) | FLAGS_DEBUG_MEM_ACCESS | FLAGS_NO_OVERLAY, 0, nullptr}}, - {0xA1, 1, X86InstInfo{"POP FS", TYPE_INST, GenFlagsSizes(SIZE_16BIT, SIZE_DEF) | FLAGS_DEBUG_MEM_ACCESS | FLAGS_NO_OVERLAY, 0, nullptr}}, - - {0xA8, 1, X86InstInfo{"PUSH GS", TYPE_INST, GenFlagsSrcSize(SIZE_16BIT) | FLAGS_DEBUG_MEM_ACCESS | FLAGS_NO_OVERLAY, 0, nullptr}}, - {0xA9, 1, X86InstInfo{"POP GS", TYPE_INST, GenFlagsSizes(SIZE_16BIT, SIZE_DEF) | FLAGS_DEBUG_MEM_ACCESS | FLAGS_NO_OVERLAY, 0, nullptr}}, - }; + GenerateTable(&Table.at(0), TwoByteOpTable, std::size(TwoByteOpTable)); - static constexpr U8U8InfoStruct TwoByteOpTable_64[] = { - {0xA0, 1, X86InstInfo{"PUSH FS", TYPE_INST, GenFlagsSameSize(SIZE_64BIT) | FLAGS_DEBUG_MEM_ACCESS | FLAGS_NO_OVERLAY, 0, nullptr}}, - {0xA1, 1, X86InstInfo{"POP FS", TYPE_INST, GenFlagsSizes(SIZE_16BIT, SIZE_64BIT) | FLAGS_DEBUG_MEM_ACCESS | FLAGS_NO_OVERLAY, 0, nullptr}}, + return Table; +}; - {0xA8, 1, X86InstInfo{"PUSH GS", TYPE_INST, GenFlagsSameSize(SIZE_64BIT) | FLAGS_DEBUG_MEM_ACCESS | FLAGS_NO_OVERLAY, 0, nullptr}}, - {0xA9, 1, X86InstInfo{"POP GS", TYPE_INST, GenFlagsSizes(SIZE_16BIT, SIZE_64BIT) | FLAGS_DEBUG_MEM_ACCESS | FLAGS_NO_OVERLAY, 0, nullptr}}, - }; +std::array SecondBaseOps = BaseOpsLambda(); +std::array RepModOps = []() consteval { + std::array Table{}; - static constexpr U8U8InfoStruct RepModOpTable[] = { + constexpr U8U8InfoStruct RepModOpTable[] = { {0x0, 16, X86InstInfo{"", TYPE_COPY_OTHER, FLAGS_NONE, 0, nullptr}}, {0x10, 1, X86InstInfo{"MOVSS", TYPE_INST, GenFlagsSameSize(SIZE_128BIT) | FLAGS_MODRM | FLAGS_XMM_FLAGS, 0, nullptr}}, @@ -361,7 +357,15 @@ void InitializeSecondaryTables(Context::OperatingMode Mode) { {0xFF, 1, X86InstInfo{"", TYPE_COPY_OTHER, FLAGS_NONE, 0, nullptr}}, }; - static constexpr U8U8InfoStruct RepNEModOpTable[] = { + GenerateTableWithCopy(&Table.at(0), RepModOpTable, std::size(RepModOpTable), &BaseOpsLambda().at(0)); + + return Table; +}(); + +std::array RepNEModOps = []() consteval { + std::array Table{}; + + constexpr U8U8InfoStruct RepNEModOpTable[] = { {0x0, 16, X86InstInfo{"", TYPE_COPY_OTHER, FLAGS_NONE, 0, nullptr}}, {0x10, 1, X86InstInfo{"MOVSD", TYPE_INST, GenFlagsSameSize(SIZE_128BIT) | FLAGS_MODRM | FLAGS_XMM_FLAGS, 0, nullptr}}, @@ -434,7 +438,15 @@ void InitializeSecondaryTables(Context::OperatingMode Mode) { {0xF8, 8, X86InstInfo{"", TYPE_INVALID, FLAGS_NONE, 0, nullptr}}, }; - static constexpr U8U8InfoStruct OpSizeModOpTable[] = { + GenerateTableWithCopy(&Table.at(0), RepNEModOpTable, std::size(RepNEModOpTable), &BaseOpsLambda().at(0)); + + return Table; +}(); + +std::array OpSizeModOps = []() consteval { + std::array Table{}; + + constexpr U8U8InfoStruct OpSizeModOpTable[] = { {0x0, 16, X86InstInfo{"", TYPE_COPY_OTHER, FLAGS_NONE, 0, nullptr}}, {0x10, 1, X86InstInfo{"MOVUPD", TYPE_INST, GenFlagsSameSize(SIZE_128BIT) | FLAGS_MODRM | FLAGS_XMM_FLAGS, 0, nullptr}}, @@ -581,19 +593,40 @@ void InitializeSecondaryTables(Context::OperatingMode Mode) { {0xFF, 1, X86InstInfo{"", TYPE_COPY_OTHER, FLAGS_NONE, 0, nullptr}}, }; - GenerateTable(&SecondBaseOps.at(0), TwoByteOpTable, std::size(TwoByteOpTable)); + GenerateTableWithCopy(&Table.at(0), OpSizeModOpTable, std::size(OpSizeModOpTable), &BaseOpsLambda().at(0)); + + return Table; +}(); + +void InitializeSecondaryTables(Context::OperatingMode Mode) { + static constexpr U8U8InfoStruct TwoByteOpTable_32[] = { + {0xA0, 1, X86InstInfo{"PUSH FS", TYPE_INST, GenFlagsSrcSize(SIZE_16BIT) | FLAGS_DEBUG_MEM_ACCESS | FLAGS_NO_OVERLAY, 0, nullptr}}, + {0xA1, 1, X86InstInfo{"POP FS", TYPE_INST, GenFlagsSizes(SIZE_16BIT, SIZE_DEF) | FLAGS_DEBUG_MEM_ACCESS | FLAGS_NO_OVERLAY, 0, nullptr}}, + + {0xA8, 1, X86InstInfo{"PUSH GS", TYPE_INST, GenFlagsSrcSize(SIZE_16BIT) | FLAGS_DEBUG_MEM_ACCESS | FLAGS_NO_OVERLAY, 0, nullptr}}, + {0xA9, 1, X86InstInfo{"POP GS", TYPE_INST, GenFlagsSizes(SIZE_16BIT, SIZE_DEF) | FLAGS_DEBUG_MEM_ACCESS | FLAGS_NO_OVERLAY, 0, nullptr}}, + }; + + static constexpr U8U8InfoStruct TwoByteOpTable_64[] = { + {0xA0, 1, X86InstInfo{"PUSH FS", TYPE_INST, GenFlagsSameSize(SIZE_64BIT) | FLAGS_DEBUG_MEM_ACCESS | FLAGS_NO_OVERLAY, 0, nullptr}}, + {0xA1, 1, X86InstInfo{"POP FS", TYPE_INST, GenFlagsSizes(SIZE_16BIT, SIZE_64BIT) | FLAGS_DEBUG_MEM_ACCESS | FLAGS_NO_OVERLAY, 0, nullptr}}, + + {0xA8, 1, X86InstInfo{"PUSH GS", TYPE_INST, GenFlagsSameSize(SIZE_64BIT) | FLAGS_DEBUG_MEM_ACCESS | FLAGS_NO_OVERLAY, 0, nullptr}}, + {0xA9, 1, X86InstInfo{"POP GS", TYPE_INST, GenFlagsSizes(SIZE_16BIT, SIZE_64BIT) | FLAGS_DEBUG_MEM_ACCESS | FLAGS_NO_OVERLAY, 0, nullptr}}, + }; if (Mode == Context::MODE_64BIT) { - GenerateTable(&SecondBaseOps.at(0), TwoByteOpTable_64, std::size(TwoByteOpTable_64)); + LateInitCopyTable(&SecondBaseOps.at(0), TwoByteOpTable_64, std::size(TwoByteOpTable_64)); + LateInitCopyTable(&RepModOps.at(0), TwoByteOpTable_64, std::size(TwoByteOpTable_64)); + LateInitCopyTable(&RepNEModOps.at(0), TwoByteOpTable_64, std::size(TwoByteOpTable_64)); + LateInitCopyTable(&OpSizeModOps.at(0), TwoByteOpTable_64, std::size(TwoByteOpTable_64)); } else { - GenerateTable(&SecondBaseOps.at(0), TwoByteOpTable_32, std::size(TwoByteOpTable_32)); + LateInitCopyTable(&SecondBaseOps.at(0), TwoByteOpTable_32, std::size(TwoByteOpTable_32)); + LateInitCopyTable(&RepModOps.at(0), TwoByteOpTable_32, std::size(TwoByteOpTable_32)); + LateInitCopyTable(&RepNEModOps.at(0), TwoByteOpTable_32, std::size(TwoByteOpTable_32)); + LateInitCopyTable(&OpSizeModOps.at(0), TwoByteOpTable_32, std::size(TwoByteOpTable_32)); } - - GenerateTableWithCopy(&RepModOps.at(0), RepModOpTable, std::size(RepModOpTable), &SecondBaseOps.at(0)); - GenerateTableWithCopy(&RepNEModOps.at(0), RepNEModOpTable, std::size(RepNEModOpTable), &SecondBaseOps.at(0)); - GenerateTableWithCopy(&OpSizeModOps.at(0), OpSizeModOpTable, std::size(OpSizeModOpTable), &SecondBaseOps.at(0)); - } } diff --git a/FEXCore/Source/Interface/Core/X86Tables/VEXTables.cpp b/FEXCore/Source/Interface/Core/X86Tables/VEXTables.cpp index a3add169ca..f9ec12e431 100644 --- a/FEXCore/Source/Interface/Core/X86Tables/VEXTables.cpp +++ b/FEXCore/Source/Interface/Core/X86Tables/VEXTables.cpp @@ -11,10 +11,10 @@ tags: frontend|x86-tables namespace FEXCore::X86Tables { using namespace InstFlags; - -void InitializeVEXTables() { +std::array VEXTableOps = []() consteval { + std::array Table{}; #define OPD(map_select, pp, opcode) (((map_select - 1) << 10) | (pp << 8) | (opcode)) - static constexpr U16U8InfoStruct VEXTable[] = { + constexpr U16U8InfoStruct VEXTable[] = { // Map 0 (Reserved) // VEX Map 1 {OPD(1, 0b00, 0x10), 1, X86InstInfo{"VMOVUPS", TYPE_INST, GenFlagsSameSize(SIZE_128BIT) | FLAGS_MODRM | FLAGS_XMM_FLAGS, 0, nullptr}}, @@ -488,8 +488,15 @@ void InitializeVEXTables() { }; #undef OPD + GenerateTable(&Table.at(0), VEXTable, std::size(VEXTable)); + return Table; +}(); + +std::array VEXTableGroupOps = []() consteval { + std::array Table{}; + #define OPD(group, pp, opcode) (((group - TYPE_VEX_GROUP_12) << 4) | (pp << 3) | (opcode)) - static constexpr U8U8InfoStruct VEXGroupTable[] = { + constexpr U8U8InfoStruct VEXGroupTable[] = { {OPD(TYPE_VEX_GROUP_12, 1, 0b010), 1, X86InstInfo{"VPSRLW", TYPE_INST, GenFlagsSameSize(SIZE_128BIT) | FLAGS_MODRM | FLAGS_VEX_DST | FLAGS_XMM_FLAGS, 1, nullptr}}, {OPD(TYPE_VEX_GROUP_12, 1, 0b100), 1, X86InstInfo{"VPSRAW", TYPE_INST, GenFlagsSameSize(SIZE_128BIT) | FLAGS_MODRM | FLAGS_VEX_DST | FLAGS_XMM_FLAGS, 1, nullptr}}, {OPD(TYPE_VEX_GROUP_12, 1, 0b110), 1, X86InstInfo{"VPSLLW", TYPE_INST, GenFlagsSameSize(SIZE_128BIT) | FLAGS_MODRM | FLAGS_VEX_DST | FLAGS_XMM_FLAGS, 1, nullptr}}, @@ -512,7 +519,8 @@ void InitializeVEXTables() { }; #undef OPD - GenerateTable(&VEXTableOps.at(0), VEXTable, std::size(VEXTable)); - GenerateTable(&VEXTableGroupOps.at(0), VEXGroupTable, std::size(VEXGroupTable)); -} + GenerateTable(&Table.at(0), VEXGroupTable, std::size(VEXGroupTable)); + + return Table; +}(); } diff --git a/FEXCore/Source/Interface/Core/X86Tables/X86Tables.h b/FEXCore/Source/Interface/Core/X86Tables/X86Tables.h index d8ef96bf22..54e186f45c 100644 --- a/FEXCore/Source/Interface/Core/X86Tables/X86Tables.h +++ b/FEXCore/Source/Interface/Core/X86Tables/X86Tables.h @@ -507,26 +507,30 @@ using U8U8InfoStruct = X86TablesInfoStruct; using U16U8InfoStruct = X86TablesInfoStruct; template -static inline void GenerateTable(X86InstInfo *FinalTable, X86TablesInfoStruct const *LocalTable, size_t TableSize) { +constexpr static inline void GenerateTable(X86InstInfo *FinalTable, X86TablesInfoStruct const *LocalTable, size_t TableSize) { for (size_t j = 0; j < TableSize; ++j) { X86TablesInfoStruct const &Op = LocalTable[j]; auto OpNum = Op.first; X86InstInfo const &Info = Op.Info; for (uint32_t i = 0; i < Op.second; ++i) { - LOGMAN_THROW_AA_FMT(FinalTable[OpNum + i].Type == TYPE_UNKNOWN, "Duplicate Entry {}->{}", FinalTable[OpNum + i].Name, Info.Name); + if (FinalTable[OpNum + i].Type != TYPE_UNKNOWN) { + ERROR_AND_DIE_FMT("Duplicate Entry {}->{}", FinalTable[OpNum + i].Name, Info.Name); + } FinalTable[OpNum + i] = Info; } } }; template -static inline void GenerateTableWithCopy(X86InstInfo *FinalTable, X86TablesInfoStruct const *LocalTable, size_t TableSize, X86InstInfo *OtherLocal) { +constexpr static inline void GenerateTableWithCopy(X86InstInfo *FinalTable, X86TablesInfoStruct const *LocalTable, size_t TableSize, X86InstInfo *OtherLocal) { for (size_t j = 0; j < TableSize; ++j) { X86TablesInfoStruct const &Op = LocalTable[j]; auto OpNum = Op.first; X86InstInfo const &Info = Op.Info; for (uint32_t i = 0; i < Op.second; ++i) { - LOGMAN_THROW_AA_FMT(FinalTable[OpNum + i].Type == TYPE_UNKNOWN, "Duplicate Entry {}->{}", FinalTable[OpNum + i].Name, Info.Name); + if (FinalTable[OpNum + i].Type != TYPE_UNKNOWN) { + ERROR_AND_DIE_FMT("Duplicate Entry {}->{}", FinalTable[OpNum + i].Name, Info.Name); + } if (Info.Type == TYPE_COPY_OTHER) { FinalTable[OpNum + i] = OtherLocal[OpNum + i]; } @@ -538,13 +542,30 @@ static inline void GenerateTableWithCopy(X86InstInfo *FinalTable, X86TablesInfoS }; template -static inline void GenerateX87Table(X86InstInfo *FinalTable, X86TablesInfoStruct const *LocalTable, size_t TableSize) { +static inline void LateInitCopyTable(X86InstInfo *FinalTable, X86TablesInfoStruct const *OtherLocal, size_t OtherTableSize) { + for (size_t j = 0; j < OtherTableSize; ++j) { + X86TablesInfoStruct const &OtherOp = OtherLocal[j]; + auto OtherOpNum = OtherOp.first; + X86InstInfo const &OtherInfo = OtherOp.Info; + for (uint32_t i = 0; i < OtherOp.second; ++i) { + X86InstInfo &FinalOp = FinalTable[OtherOpNum + i]; + if (FinalOp.Type == TYPE_COPY_OTHER) { + FinalOp = OtherInfo; + } + } + } +} + +template +constexpr static inline void GenerateX87Table(X86InstInfo *FinalTable, X86TablesInfoStruct const *LocalTable, size_t TableSize) { for (size_t j = 0; j < TableSize; ++j) { X86TablesInfoStruct const &Op = LocalTable[j]; auto OpNum = Op.first; X86InstInfo const &Info = Op.Info; for (uint32_t i = 0; i < Op.second; ++i) { - LOGMAN_THROW_AA_FMT(FinalTable[OpNum + i].Type == TYPE_UNKNOWN, "Duplicate Entry {}->{}", FinalTable[OpNum + i].Name, Info.Name); + if (FinalTable[OpNum + i].Type != TYPE_UNKNOWN) { + ERROR_AND_DIE_FMT("Duplicate Entry {}->{}", FinalTable[OpNum + i].Name, Info.Name); + } if ((OpNum & 0b11'000'000) == 0b11'000'000) { // If the mod field is 0b11 then it is a regular op FinalTable[OpNum + i] = Info; @@ -552,7 +573,9 @@ static inline void GenerateX87Table(X86InstInfo *FinalTable, X86TablesInfoStruct else { // If the mod field is !0b11 then this instruction is duplicated through the whole mod [0b00, 0b10] range // and the modrm.rm space because that is used part of the instruction encoding - LOGMAN_THROW_AA_FMT((OpNum & 0b11'000'000) == 0, "Only support mod field of zero in this path"); + if ((OpNum & 0b11'000'000) != 0) { + ERROR_AND_DIE_FMT("Only support mod field of zero in this path"); + } for (uint16_t mod = 0b00'000'000; mod < 0b11'000'000; mod += 0b01'000'000) { for (uint16_t rm = 0b000; rm < 0b1'000; ++rm) { FinalTable[(OpNum | mod | rm) + i] = Info; diff --git a/FEXCore/Source/Interface/Core/X86Tables/X87Tables.cpp b/FEXCore/Source/Interface/Core/X86Tables/X87Tables.cpp index d52147d9c8..e204829e39 100644 --- a/FEXCore/Source/Interface/Core/X86Tables/X87Tables.cpp +++ b/FEXCore/Source/Interface/Core/X86Tables/X87Tables.cpp @@ -11,11 +11,11 @@ tags: frontend|x86-tables namespace FEXCore::X86Tables { using namespace InstFlags; - -void InitializeX87Tables() { +std::array X87Ops = []() consteval { + std::array Table{}; #define OPD(op, modrmop) (((op - 0xD8) << 8) | modrmop) #define OPDReg(op, reg) (((op - 0xD8) << 8) | (reg << 3)) - static constexpr U16U8InfoStruct X87OpTable[] = { + constexpr U16U8InfoStruct X87OpTable[] = { // 0xD8 {OPDReg(0xD8, 0), 1, X86InstInfo{"FADD", TYPE_X87, FLAGS_MODRM, 0, nullptr}}, {OPDReg(0xD8, 1), 1, X86InstInfo{"FMUL", TYPE_X87, FLAGS_MODRM, 0, nullptr}}, @@ -263,6 +263,8 @@ void InitializeX87Tables() { #undef OPD #undef OPDReg - GenerateX87Table(&X87Ops.at(0), X87OpTable, std::size(X87OpTable)); -} + GenerateX87Table(&Table.at(0), X87OpTable, std::size(X87OpTable)); + return Table; +}(); + } diff --git a/FEXCore/Source/Interface/Core/X86Tables/XOPTables.cpp b/FEXCore/Source/Interface/Core/X86Tables/XOPTables.cpp index 79a8339efe..0dda9ba553 100644 --- a/FEXCore/Source/Interface/Core/X86Tables/XOPTables.cpp +++ b/FEXCore/Source/Interface/Core/X86Tables/XOPTables.cpp @@ -12,14 +12,14 @@ tags: frontend|x86-tables namespace FEXCore::X86Tables { using namespace InstFlags; - -void InitializeXOPTables() { +std::array XOPTableOps = []() consteval { + std::array Table{}; #define OPD(group, pp, opcode) ( (group << 10) | (pp << 8) | (opcode)) constexpr uint16_t XOP_GROUP_8 = 0; constexpr uint16_t XOP_GROUP_9 = 1; constexpr uint16_t XOP_GROUP_A = 2; - static constexpr U16U8InfoStruct XOPTable[] = { + constexpr U16U8InfoStruct XOPTable[] = { // Group 8 {OPD(XOP_GROUP_8, 0, 0x85), 1, X86InstInfo{"VPMAXSSWW", TYPE_UNDEC, FLAGS_NONE, 0, nullptr}}, {OPD(XOP_GROUP_8, 0, 0x86), 1, X86InstInfo{"VPMACSSWD", TYPE_UNDEC, FLAGS_NONE, 0, nullptr}}, @@ -104,8 +104,15 @@ void InitializeXOPTables() { }; #undef OPD + GenerateTable(&Table.at(0), XOPTable, std::size(XOPTable)); + + return Table; +}(); + +std::array XOPTableGroupOps = []() consteval { + std::array Table{}; #define OPD(subgroup, opcode) (((subgroup - 1) << 3) | (opcode)) - static constexpr U8U8InfoStruct XOPGroupTable[] = { + constexpr U8U8InfoStruct XOPGroupTable[] = { // Group 1 {OPD(1, 1), 1, X86InstInfo{"BLCFILL", TYPE_UNDEC, FLAGS_NONE, 0, nullptr}}, {OPD(1, 2), 1, X86InstInfo{"BLSFILL", TYPE_UNDEC, FLAGS_NONE, 0, nullptr}}, @@ -129,7 +136,8 @@ void InitializeXOPTables() { }; #undef OPD - GenerateTable(&XOPTableOps.at(0), XOPTable, std::size(XOPTable)); - GenerateTable(&XOPTableGroupOps.at(0), XOPGroupTable, std::size(XOPGroupTable)); -} + GenerateTable(&Table.at(0), XOPGroupTable, std::size(XOPGroupTable)); + return Table; +}(); + }