diff options
| author | Léo Lam <leo@leolam.fr> | 2020-04-28 18:03:07 +0200 |
|---|---|---|
| committer | GitHub <noreply@github.com> | 2020-04-28 18:03:07 +0200 |
| commit | 401b582b401b3e767f7422fa8d4fd2e7c7eabc39 (patch) | |
| tree | 2ad8a9b47c64f1abed2cf6e98c87dd3e8fab83d0 | |
| parent | 82012c4cd6778c3ebb1bc48c50a76e07667f359c (diff) | |
| parent | ee200d09eba5061cf85f185b7238ef2652e68514 (diff) | |
Merge pull request #8151 from lioncash/jit_tables
Jit64/Jit64_Tables: Construct tables at compile-time
| -rw-r--r-- | Source/Core/Core/PowerPC/Jit64/Jit.cpp | 1 | ||||
| -rw-r--r-- | Source/Core/Core/PowerPC/Jit64/Jit.h | 11 | ||||
| -rw-r--r-- | Source/Core/Core/PowerPC/Jit64/Jit64_Tables.cpp | 267 |
3 files changed, 154 insertions, 125 deletions
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 <array> + #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<GekkoOPTemplate, 54> 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<GekkoOPTemplate, 13> 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<GekkoOPTemplate, 17> 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<GekkoOPTemplate, 4> 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<GekkoOPTemplate, 13> 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<GekkoOPTemplate, 107> 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<GekkoOPTemplate, 9> 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<GekkoOPTemplate, 15> 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<GekkoOPTemplate, 10> s_table63_2{{ {18, &Jit64::fp_arith}, // fdivx {20, &Jit64::fp_arith}, // fsubx {21, &Jit64::fp_arith}, // faddx @@ -358,116 +332,173 @@ const GekkoOPTemplate table63_2[] = { {29, &Jit64::fmaddXX}, // fmaddx {30, &Jit64::fmaddXX}, // fnmsubx {31, &Jit64::fmaddXX}, // fnmaddx -}; - -void Jit64::CompileInstruction(PPCAnalyst::CodeOp& op) +}}; + +// 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 <algorithm>'s std::fill. Thus, this function exists +// to bridge the gap. +template <size_t N> +constexpr void FillWithFallbacks(std::array<Jit64::Instruction, N>& table) { - (this->*dynaOpTable[op.inst.OPCD])(op.inst); - - GekkoOPInfo* info = op.opinfo; - if (info) + for (auto& entry : table) { -#ifdef OPLOG - if (!strcmp(info->opname, OP_TO_LOG)) // "mcrfs" - { - rsplocations.push_back(js.compilerPC); - } -#endif - info->compileCount++; - info->lastUse = js.compilerPC; + entry = &Jit64::FallBackToInterpreter; } } -void Jit64::InitializeInstructionTables() -{ - // once initialized, tables are read-only - static bool initialized = false; - if (initialized) - return; - - // clear - for (auto& tpl : dynaOpTable) - { - tpl = &Jit64::FallBackToInterpreter; - } +constexpr std::array<Jit64::Instruction, 64> s_dyna_op_table = [] { + std::array<Jit64::Instruction, 64> table{}; + FillWithFallbacks(table); - for (auto& tpl : dynaOpTable59) + for (auto& tpl : s_primary_table) { - tpl = &Jit64::FallBackToInterpreter; + table[tpl.opcode] = tpl.fn; } - for (int i = 0; i < 1024; i++) - { - dynaOpTable4[i] = &Jit64::FallBackToInterpreter; - dynaOpTable19[i] = &Jit64::FallBackToInterpreter; - dynaOpTable31[i] = &Jit64::FallBackToInterpreter; - dynaOpTable63[i] = &Jit64::FallBackToInterpreter; - } + return table; +}(); - for (auto& tpl : primarytable) - { - dynaOpTable[tpl.opcode] = tpl.Inst; - } +constexpr std::array<Jit64::Instruction, 1024> s_dyna_op_table4 = [] { + std::array<Jit64::Instruction, 1024> table{}; + FillWithFallbacks(table); - for (int i = 0; i < 32; i++) + for (u32 i = 0; i < 32; i++) { - int fill = i << 5; - for (const auto& tpl : table4_2) + const u32 fill = i << 5; + for (const auto& tpl : s_table4_2) { - int op = fill + tpl.opcode; - dynaOpTable4[op] = tpl.Inst; + const u32 op = fill + tpl.opcode; + table[op] = tpl.fn; } } - for (int i = 0; i < 16; i++) + for (u32 i = 0; i < 16; i++) { - int fill = i << 6; - for (const auto& tpl : table4_3) + const u32 fill = i << 6; + for (const auto& tpl : s_table4_3) { - int op = fill + tpl.opcode; - dynaOpTable4[op] = tpl.Inst; + const u32 op = fill + tpl.opcode; + table[op] = tpl.fn; } } - for (const auto& tpl : table4) + for (const auto& tpl : s_table4) { - int op = tpl.opcode; - dynaOpTable4[op] = tpl.Inst; + const u32 op = tpl.opcode; + table[op] = tpl.fn; } - for (const auto& tpl : table31) + return table; +}(); + +constexpr std::array<Jit64::Instruction, 1024> s_dyna_op_table19 = [] { + std::array<Jit64::Instruction, 1024> table{}; + FillWithFallbacks(table); + + for (const auto& tpl : s_table19) { - int op = tpl.opcode; - dynaOpTable31[op] = tpl.Inst; + const u32 op = tpl.opcode; + table[op] = tpl.fn; } - for (const auto& tpl : table19) + return table; +}(); + +constexpr std::array<Jit64::Instruction, 1024> s_dyna_op_table31 = [] { + std::array<Jit64::Instruction, 1024> table{}; + FillWithFallbacks(table); + + for (const auto& tpl : s_table31) { - int op = tpl.opcode; - dynaOpTable19[op] = tpl.Inst; + const u32 op = tpl.opcode; + table[op] = tpl.fn; } - for (const auto& tpl : table59) + return table; +}(); + +constexpr std::array<Jit64::Instruction, 32> s_dyna_op_table59 = [] { + std::array<Jit64::Instruction, 32> table{}; + FillWithFallbacks(table); + + for (const auto& tpl : s_table59) { - int op = tpl.opcode; - dynaOpTable59[op] = tpl.Inst; + const u32 op = tpl.opcode; + table[op] = tpl.fn; } - for (const auto& tpl : table63) + return table; +}(); + +constexpr std::array<Jit64::Instruction, 1024> s_dyna_op_table63 = [] { + std::array<Jit64::Instruction, 1024> table{}; + FillWithFallbacks(table); + + for (const auto& tpl : s_table63) { - int op = tpl.opcode; - dynaOpTable63[op] = tpl.Inst; + const u32 op = tpl.opcode; + table[op] = tpl.fn; } - for (int i = 0; i < 32; i++) + for (u32 i = 0; i < 32; i++) { - int fill = i << 5; - for (const auto& tpl : table63_2) + const u32 fill = i << 5; + for (const auto& tpl : s_table63_2) { - int op = fill + tpl.opcode; - dynaOpTable63[op] = tpl.Inst; + const u32 op = fill + tpl.opcode; + table[op] = tpl.fn; } } - initialized = true; + 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->*s_dyna_op_table[op.inst.OPCD])(op.inst); + + GekkoOPInfo* info = op.opinfo; + if (info) + { +#ifdef OPLOG + if (!strcmp(info->opname, OP_TO_LOG)) // "mcrfs" + { + rsplocations.push_back(js.compilerPC); + } +#endif + info->compileCount++; + info->lastUse = js.compilerPC; + } } |
