diff --git a/Source/Core/Core/PowerPC/Jit64/Jit.cpp b/Source/Core/Core/PowerPC/Jit64/Jit.cpp index d34eb55680..827c56dea5 100644 --- a/Source/Core/Core/PowerPC/Jit64/Jit.cpp +++ b/Source/Core/Core/PowerPC/Jit64/Jit.cpp @@ -330,7 +330,6 @@ bool Jit64::BackPatch(u32 emAddress, SContext* ctx) void Jit64::Init() { - InitializeInstructionTables(); EnableBlockLink(); jo.fastmem_arena = SConfig::GetInstance().bFastmem && Memory::InitFastmemArena(); diff --git a/Source/Core/Core/PowerPC/Jit64/Jit.h b/Source/Core/Core/PowerPC/Jit64/Jit.h index d2baa32c8a..33263547da 100644 --- a/Source/Core/Core/PowerPC/Jit64/Jit.h +++ b/Source/Core/Core/PowerPC/Jit64/Jit.h @@ -131,11 +131,11 @@ public: void DoNothing(UGeckoInstruction _inst); void HLEFunction(UGeckoInstruction _inst); - void DynaRunTable4(UGeckoInstruction _inst); - void DynaRunTable19(UGeckoInstruction _inst); - void DynaRunTable31(UGeckoInstruction _inst); - void DynaRunTable59(UGeckoInstruction _inst); - void DynaRunTable63(UGeckoInstruction _inst); + void DynaRunTable4(UGeckoInstruction inst); + void DynaRunTable19(UGeckoInstruction inst); + void DynaRunTable31(UGeckoInstruction inst); + void DynaRunTable59(UGeckoInstruction inst); + void DynaRunTable63(UGeckoInstruction inst); void addx(UGeckoInstruction inst); void arithcx(UGeckoInstruction inst); @@ -236,7 +236,6 @@ public: void eieio(UGeckoInstruction inst); private: - static void InitializeInstructionTables(); void CompileInstruction(PPCAnalyst::CodeOp& op); bool HandleFunctionHooking(u32 address); diff --git a/Source/Core/Core/PowerPC/Jit64/Jit64_Tables.cpp b/Source/Core/Core/PowerPC/Jit64/Jit64_Tables.cpp index 9dc1380dba..f394d4ab14 100644 --- a/Source/Core/Core/PowerPC/Jit64/Jit64_Tables.cpp +++ b/Source/Core/Core/PowerPC/Jit64/Jit64_Tables.cpp @@ -2,46 +2,20 @@ // Licensed under GPLv2+ // Refer to the license.txt file included. +#include + #include "Core/PowerPC/Gekko.h" #include "Core/PowerPC/Jit64/Jit.h" -static Jit64::Instruction dynaOpTable[64]; -static Jit64::Instruction dynaOpTable4[1024]; -static Jit64::Instruction dynaOpTable19[1024]; -static Jit64::Instruction dynaOpTable31[1024]; -static Jit64::Instruction dynaOpTable59[32]; -static Jit64::Instruction dynaOpTable63[1024]; -void Jit64::DynaRunTable4(UGeckoInstruction _inst) -{ - (this->*dynaOpTable4[_inst.SUBOP10])(_inst); -} -void Jit64::DynaRunTable19(UGeckoInstruction _inst) -{ - (this->*dynaOpTable19[_inst.SUBOP10])(_inst); -} -void Jit64::DynaRunTable31(UGeckoInstruction _inst) -{ - (this->*dynaOpTable31[_inst.SUBOP10])(_inst); -} -void Jit64::DynaRunTable59(UGeckoInstruction _inst) -{ - (this->*dynaOpTable59[_inst.SUBOP5])(_inst); -} -void Jit64::DynaRunTable63(UGeckoInstruction _inst) -{ - (this->*dynaOpTable63[_inst.SUBOP10])(_inst); -} - namespace { struct GekkoOPTemplate { - int opcode; - Jit64::Instruction Inst; + u32 opcode; + Jit64::Instruction fn; }; -} // namespace -const GekkoOPTemplate primarytable[] = { +constexpr std::array s_primary_table{{ {4, &Jit64::DynaRunTable4}, // RunTable4 {19, &Jit64::DynaRunTable19}, // RunTable19 {31, &Jit64::DynaRunTable31}, // RunTable31 @@ -109,9 +83,9 @@ const GekkoOPTemplate primarytable[] = { {61, &Jit64::psq_stXX}, // psq_stu // missing: 0, 1, 2, 5, 6, 9, 22, 30, 62, 58 -}; +}}; -const GekkoOPTemplate table4[] = { +constexpr std::array s_table4{{ // SUBOP10 {0, &Jit64::ps_cmpXX}, // ps_cmpu0 {32, &Jit64::ps_cmpXX}, // ps_cmpo0 @@ -127,9 +101,9 @@ const GekkoOPTemplate table4[] = { {624, &Jit64::ps_mergeXX}, // ps_merge11 {1014, &Jit64::FallBackToInterpreter}, // dcbz_l -}; +}}; -const GekkoOPTemplate table4_2[] = { +constexpr std::array s_table4_2{{ {10, &Jit64::ps_sum}, // ps_sum0 {11, &Jit64::ps_sum}, // ps_sum1 {12, &Jit64::ps_muls}, // ps_muls0 @@ -147,16 +121,16 @@ const GekkoOPTemplate table4_2[] = { {29, &Jit64::fmaddXX}, // ps_madd {30, &Jit64::fmaddXX}, // ps_nmsub {31, &Jit64::fmaddXX}, // ps_nmadd -}; +}}; -const GekkoOPTemplate table4_3[] = { +constexpr std::array s_table4_3{{ {6, &Jit64::psq_lXX}, // psq_lx {7, &Jit64::psq_stXX}, // psq_stx {38, &Jit64::psq_lXX}, // psq_lux {39, &Jit64::psq_stXX}, // psq_stux -}; +}}; -const GekkoOPTemplate table19[] = { +constexpr std::array s_table19{{ {528, &Jit64::bcctrx}, // bcctrx {16, &Jit64::bclrx}, // bclrx {257, &Jit64::crXXX}, // crand @@ -172,9 +146,9 @@ const GekkoOPTemplate table19[] = { {0, &Jit64::mcrf}, // mcrf {50, &Jit64::rfi}, // rfi -}; +}}; -const GekkoOPTemplate table31[] = { +constexpr std::array s_table31{{ {266, &Jit64::addx}, // addx {778, &Jit64::addx}, // addox {10, &Jit64::arithcx}, // addcx @@ -314,9 +288,9 @@ const GekkoOPTemplate table31[] = { {854, &Jit64::eieio}, // eieio {306, &Jit64::FallBackToInterpreter}, // tlbie {566, &Jit64::DoNothing}, // tlbsync -}; +}}; -const GekkoOPTemplate table59[] = { +constexpr std::array s_table59{{ {18, &Jit64::fp_arith}, // fdivsx {20, &Jit64::fp_arith}, // fsubsx {21, &Jit64::fp_arith}, // faddsx @@ -326,9 +300,9 @@ const GekkoOPTemplate table59[] = { {29, &Jit64::fmaddXX}, // fmaddsx {30, &Jit64::fmaddXX}, // fnmsubsx {31, &Jit64::fmaddXX}, // fnmaddsx -}; +}}; -const GekkoOPTemplate table63[] = { +constexpr std::array s_table63{{ {264, &Jit64::fsign}, // fabsx {32, &Jit64::fcmpX}, // fcmpo {0, &Jit64::fcmpX}, // fcmpu @@ -345,9 +319,9 @@ const GekkoOPTemplate table63[] = { {38, &Jit64::mtfsb1x}, // mtfsb1x {134, &Jit64::mtfsfix}, // mtfsfix {711, &Jit64::mtfsfx}, // mtfsfx -}; +}}; -const GekkoOPTemplate table63_2[] = { +constexpr std::array s_table63_2{{ {18, &Jit64::fp_arith}, // fdivx {20, &Jit64::fp_arith}, // fsubx {21, &Jit64::fp_arith}, // faddx @@ -358,11 +332,162 @@ const GekkoOPTemplate table63_2[] = { {29, &Jit64::fmaddXX}, // fmaddx {30, &Jit64::fmaddXX}, // fnmsubx {31, &Jit64::fmaddXX}, // fnmaddx -}; +}}; + +// TODO: This can be replaced with: +// +// table.fill(&Jit64::FallbackToInterpreter); +// +// whenever we end up migrating to C++20. Prior to C++20, +// std::array's fill() function is, unfortunately, not constexpr. +// Ditto for 's std::fill. Thus, this function exists +// to bridge the gap. +template +constexpr void FillWithFallbacks(std::array& table) +{ + for (auto& entry : table) + { + entry = &Jit64::FallBackToInterpreter; + } +} + +constexpr std::array s_dyna_op_table = [] { + std::array table{}; + FillWithFallbacks(table); + + for (auto& tpl : s_primary_table) + { + table[tpl.opcode] = tpl.fn; + } + + return table; +}(); + +constexpr std::array s_dyna_op_table4 = [] { + std::array table{}; + FillWithFallbacks(table); + + for (u32 i = 0; i < 32; i++) + { + const u32 fill = i << 5; + for (const auto& tpl : s_table4_2) + { + const u32 op = fill + tpl.opcode; + table[op] = tpl.fn; + } + } + + for (u32 i = 0; i < 16; i++) + { + const u32 fill = i << 6; + for (const auto& tpl : s_table4_3) + { + const u32 op = fill + tpl.opcode; + table[op] = tpl.fn; + } + } + + for (const auto& tpl : s_table4) + { + const u32 op = tpl.opcode; + table[op] = tpl.fn; + } + + return table; +}(); + +constexpr std::array s_dyna_op_table19 = [] { + std::array table{}; + FillWithFallbacks(table); + + for (const auto& tpl : s_table19) + { + const u32 op = tpl.opcode; + table[op] = tpl.fn; + } + + return table; +}(); + +constexpr std::array s_dyna_op_table31 = [] { + std::array table{}; + FillWithFallbacks(table); + + for (const auto& tpl : s_table31) + { + const u32 op = tpl.opcode; + table[op] = tpl.fn; + } + + return table; +}(); + +constexpr std::array s_dyna_op_table59 = [] { + std::array table{}; + FillWithFallbacks(table); + + for (const auto& tpl : s_table59) + { + const u32 op = tpl.opcode; + table[op] = tpl.fn; + } + + return table; +}(); + +constexpr std::array s_dyna_op_table63 = [] { + std::array table{}; + FillWithFallbacks(table); + + for (const auto& tpl : s_table63) + { + const u32 op = tpl.opcode; + table[op] = tpl.fn; + } + + for (u32 i = 0; i < 32; i++) + { + const u32 fill = i << 5; + for (const auto& tpl : s_table63_2) + { + const u32 op = fill + tpl.opcode; + table[op] = tpl.fn; + } + } + + return table; +}(); + +} // Anonymous namespace + +void Jit64::DynaRunTable4(UGeckoInstruction inst) +{ + (this->*s_dyna_op_table4[inst.SUBOP10])(inst); +} + +void Jit64::DynaRunTable19(UGeckoInstruction inst) +{ + (this->*s_dyna_op_table19[inst.SUBOP10])(inst); +} + +void Jit64::DynaRunTable31(UGeckoInstruction inst) +{ + (this->*s_dyna_op_table31[inst.SUBOP10])(inst); +} + +void Jit64::DynaRunTable59(UGeckoInstruction inst) +{ + (this->*s_dyna_op_table59[inst.SUBOP5])(inst); +} + +void Jit64::DynaRunTable63(UGeckoInstruction inst) +{ + (this->*s_dyna_op_table63[inst.SUBOP10])(inst); +} void Jit64::CompileInstruction(PPCAnalyst::CodeOp& op) { - (this->*dynaOpTable[op.inst.OPCD])(op.inst); + (this->*s_dyna_op_table[op.inst.OPCD])(op.inst); GekkoOPInfo* info = op.opinfo; if (info) @@ -377,97 +502,3 @@ void Jit64::CompileInstruction(PPCAnalyst::CodeOp& op) info->lastUse = js.compilerPC; } } - -void Jit64::InitializeInstructionTables() -{ - // once initialized, tables are read-only - static bool initialized = false; - if (initialized) - return; - - // clear - for (auto& tpl : dynaOpTable) - { - tpl = &Jit64::FallBackToInterpreter; - } - - for (auto& tpl : dynaOpTable59) - { - tpl = &Jit64::FallBackToInterpreter; - } - - for (int i = 0; i < 1024; i++) - { - dynaOpTable4[i] = &Jit64::FallBackToInterpreter; - dynaOpTable19[i] = &Jit64::FallBackToInterpreter; - dynaOpTable31[i] = &Jit64::FallBackToInterpreter; - dynaOpTable63[i] = &Jit64::FallBackToInterpreter; - } - - for (auto& tpl : primarytable) - { - dynaOpTable[tpl.opcode] = tpl.Inst; - } - - for (int i = 0; i < 32; i++) - { - int fill = i << 5; - for (const auto& tpl : table4_2) - { - int op = fill + tpl.opcode; - dynaOpTable4[op] = tpl.Inst; - } - } - - for (int i = 0; i < 16; i++) - { - int fill = i << 6; - for (const auto& tpl : table4_3) - { - int op = fill + tpl.opcode; - dynaOpTable4[op] = tpl.Inst; - } - } - - for (const auto& tpl : table4) - { - int op = tpl.opcode; - dynaOpTable4[op] = tpl.Inst; - } - - for (const auto& tpl : table31) - { - int op = tpl.opcode; - dynaOpTable31[op] = tpl.Inst; - } - - for (const auto& tpl : table19) - { - int op = tpl.opcode; - dynaOpTable19[op] = tpl.Inst; - } - - for (const auto& tpl : table59) - { - int op = tpl.opcode; - dynaOpTable59[op] = tpl.Inst; - } - - for (const auto& tpl : table63) - { - int op = tpl.opcode; - dynaOpTable63[op] = tpl.Inst; - } - - for (int i = 0; i < 32; i++) - { - int fill = i << 5; - for (const auto& tpl : table63_2) - { - int op = fill + tpl.opcode; - dynaOpTable63[op] = tpl.Inst; - } - } - - initialized = true; -}