Merge pull request #11400 from Pokechu22/better-ppc-tables

Use C++20 features to create opcode tables at compile time
This commit is contained in:
Admiral H. Curtiss
2023-03-17 04:13:25 +01:00
committed by GitHub
15 changed files with 1240 additions and 735 deletions
+13
View File
@@ -83,4 +83,17 @@ static_assert(!IsNOf<int, 1, int, int>::value);
static_assert(IsNOf<int, 2, int, int>::value);
static_assert(IsNOf<int, 2, int, short>::value); // Type conversions ARE allowed
static_assert(!IsNOf<int, 2, int, char*>::value);
// TODO: This can be replaced with std::array's fill() once C++20 is fully supported.
// Prior to C++20, std::array's fill() function is, unfortunately, not constexpr.
// Ditto for <algorithm>'s std::fill. Although Dolphin targets C++20, Android doesn't
// seem to properly support constexpr fill(), so we need this for now.
template <typename T1, size_t N, typename T2>
constexpr void Fill(std::array<T1, N>& array, const T2& value)
{
for (auto& entry : array)
{
entry = value;
}
}
} // namespace Common
@@ -270,7 +270,7 @@ void CachedInterpreter::Jit(u32 address)
{
PPCAnalyst::CodeOp& op = m_code_buffer[i];
js.downcountAmount += op.opinfo->numCycles;
js.downcountAmount += op.opinfo->num_cycles;
if (op.opinfo->flags & FL_LOADSTORE)
++js.numLoadStoreInst;
if (op.opinfo->flags & FL_USE_FPU)
@@ -301,7 +301,7 @@ void CachedInterpreter::Jit(u32 address)
js.firstFPInstructionFound = true;
}
m_code.emplace_back(PPCTables::GetInterpreterOp(op.inst), op.inst);
m_code.emplace_back(Interpreter::GetInterpreterOp(op.inst), op.inst);
if (memcheck)
m_code.emplace_back(CheckDSI, js.downcountAmount);
if (check_program_exception)
@@ -34,14 +34,6 @@ u32 last_pc;
bool Interpreter::m_end_block;
// function tables
std::array<Interpreter::Instruction, 64> Interpreter::m_op_table;
std::array<Interpreter::Instruction, 1024> Interpreter::m_op_table4;
std::array<Interpreter::Instruction, 1024> Interpreter::m_op_table19;
std::array<Interpreter::Instruction, 1024> Interpreter::m_op_table31;
std::array<Interpreter::Instruction, 32> Interpreter::m_op_table59;
std::array<Interpreter::Instruction, 1024> Interpreter::m_op_table63;
namespace
{
// Determines whether or not the given instruction is one where its execution
@@ -79,30 +71,8 @@ void UpdatePC()
}
} // Anonymous namespace
void Interpreter::RunTable4(UGeckoInstruction inst)
{
m_op_table4[inst.SUBOP10](inst);
}
void Interpreter::RunTable19(UGeckoInstruction inst)
{
m_op_table19[inst.SUBOP10](inst);
}
void Interpreter::RunTable31(UGeckoInstruction inst)
{
m_op_table31[inst.SUBOP10](inst);
}
void Interpreter::RunTable59(UGeckoInstruction inst)
{
m_op_table59[inst.SUBOP5](inst);
}
void Interpreter::RunTable63(UGeckoInstruction inst)
{
m_op_table63[inst.SUBOP10](inst);
}
void Interpreter::Init()
{
InitializeInstructionTables();
m_end_block = false;
}
@@ -150,12 +120,17 @@ int Interpreter::SingleStepInner()
if (HandleFunctionHooking(PowerPC::ppcState.pc))
{
UpdatePC();
return PPCTables::GetOpInfo(m_prev_inst)->numCycles;
// TODO: Does it make sense to use m_prev_inst here?
// It seems like we should use the num_cycles for the instruction at PC instead
// (m_prev_inst has not yet been updated)
return PPCTables::GetOpInfo(m_prev_inst)->num_cycles;
}
PowerPC::ppcState.npc = PowerPC::ppcState.pc + sizeof(UGeckoInstruction);
m_prev_inst.hex = PowerPC::Read_Opcode(PowerPC::ppcState.pc);
const GekkoOPInfo* opinfo = PPCTables::GetOpInfo(m_prev_inst);
// Uncomment to trace the interpreter
// if ((PowerPC::ppcState.pc & 0x00FFFFFF) >= 0x000AB54C &&
// (PowerPC::ppcState.pc & 0x00FFFFFF) <= 0x000AB624)
@@ -181,7 +156,7 @@ int Interpreter::SingleStepInner()
}
else if (PowerPC::ppcState.msr.FP)
{
m_op_table[m_prev_inst.OPCD](m_prev_inst);
RunInterpreterOp(m_prev_inst);
if ((PowerPC::ppcState.Exceptions & EXCEPTION_DSI) != 0)
{
CheckExceptions();
@@ -190,14 +165,14 @@ int Interpreter::SingleStepInner()
else
{
// check if we have to generate a FPU unavailable exception or a program exception.
if (PPCTables::UsesFPU(m_prev_inst))
if ((opinfo->flags & FL_USE_FPU) != 0)
{
PowerPC::ppcState.Exceptions |= EXCEPTION_FPU_UNAVAILABLE;
CheckExceptions();
}
else
{
m_op_table[m_prev_inst.OPCD](m_prev_inst);
RunInterpreterOp(m_prev_inst);
if ((PowerPC::ppcState.Exceptions & EXCEPTION_DSI) != 0)
{
CheckExceptions();
@@ -213,10 +188,9 @@ int Interpreter::SingleStepInner()
UpdatePC();
const GekkoOPInfo* opinfo = PPCTables::GetOpInfo(m_prev_inst);
PowerPC::UpdatePerformanceMonitor(opinfo->numCycles, (opinfo->flags & FL_LOADSTORE) != 0,
PowerPC::UpdatePerformanceMonitor(opinfo->num_cycles, (opinfo->flags & FL_LOADSTORE) != 0,
(opinfo->flags & FL_USE_FPU) != 0, PowerPC::ppcState);
return opinfo->numCycles;
return opinfo->num_cycles;
}
void Interpreter::SingleStep()
@@ -262,12 +262,9 @@ public:
static void isync(UGeckoInstruction inst);
using Instruction = void (*)(UGeckoInstruction inst);
static std::array<Instruction, 64> m_op_table;
static std::array<Instruction, 1024> m_op_table4;
static std::array<Instruction, 1024> m_op_table19;
static std::array<Instruction, 1024> m_op_table31;
static std::array<Instruction, 32> m_op_table59;
static std::array<Instruction, 1024> m_op_table63;
static Instruction GetInterpreterOp(UGeckoInstruction inst);
static void RunInterpreterOp(UGeckoInstruction inst);
// singleton
static Interpreter* getInstance();
@@ -283,8 +280,6 @@ public:
private:
void CheckExceptions();
static void InitializeInstructionTables();
static bool HandleFunctionHooking(u32 address);
// flag helper
File diff suppressed because it is too large Load Diff
+2 -2
View File
@@ -342,7 +342,7 @@ void Jit64::FallBackToInterpreter(UGeckoInstruction inst)
MOV(32, PPCSTATE(npc), Imm32(js.compilerPC + 4));
}
Interpreter::Instruction instr = PPCTables::GetInterpreterOp(inst);
Interpreter::Instruction instr = Interpreter::GetInterpreterOp(inst);
ABI_PushRegistersAndAdjustStack({}, 0);
ABI_CallFunctionC(instr, inst.hex);
ABI_PopRegistersAndAdjustStack({}, 0);
@@ -921,7 +921,7 @@ bool Jit64::DoJit(u32 em_address, JitBlock* b, u32 nextPC)
js.instructionNumber = i;
js.instructionsLeft = (code_block.m_num_instructions - 1) - i;
const GekkoOPInfo* opinfo = op.opinfo;
js.downcountAmount += opinfo->numCycles;
js.downcountAmount += opinfo->num_cycles;
js.fastmemLoadStore = nullptr;
js.fixupExceptionHandler = false;
+55 -64
View File
@@ -5,17 +5,19 @@
#include <array>
#include "Common/Assert.h"
#include "Common/TypeUtils.h"
#include "Core/PowerPC/Gekko.h"
namespace
{
struct GekkoOPTemplate
struct Jit64OpTemplate
{
u32 opcode;
Jit64::Instruction fn;
};
constexpr std::array<GekkoOPTemplate, 54> s_primary_table{{
constexpr std::array<Jit64OpTemplate, 54> s_primary_table{{
{4, &Jit64::DynaRunTable4}, // RunTable4
{19, &Jit64::DynaRunTable19}, // RunTable19
{31, &Jit64::DynaRunTable31}, // RunTable31
@@ -85,7 +87,7 @@ constexpr std::array<GekkoOPTemplate, 54> s_primary_table{{
// missing: 0, 1, 2, 5, 6, 9, 22, 30, 62, 58
}};
constexpr std::array<GekkoOPTemplate, 13> s_table4{{
constexpr std::array<Jit64OpTemplate, 13> s_table4{{
// SUBOP10
{0, &Jit64::ps_cmpXX}, // ps_cmpu0
{32, &Jit64::ps_cmpXX}, // ps_cmpo0
@@ -103,7 +105,7 @@ constexpr std::array<GekkoOPTemplate, 13> s_table4{{
{1014, &Jit64::FallBackToInterpreter}, // dcbz_l
}};
constexpr std::array<GekkoOPTemplate, 17> s_table4_2{{
constexpr std::array<Jit64OpTemplate, 17> s_table4_2{{
{10, &Jit64::ps_sum}, // ps_sum0
{11, &Jit64::ps_sum}, // ps_sum1
{12, &Jit64::ps_muls}, // ps_muls0
@@ -123,14 +125,14 @@ constexpr std::array<GekkoOPTemplate, 17> s_table4_2{{
{31, &Jit64::fmaddXX}, // ps_nmadd
}};
constexpr std::array<GekkoOPTemplate, 4> s_table4_3{{
constexpr std::array<Jit64OpTemplate, 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
}};
constexpr std::array<GekkoOPTemplate, 13> s_table19{{
constexpr std::array<Jit64OpTemplate, 13> s_table19{{
{528, &Jit64::bcctrx}, // bcctrx
{16, &Jit64::bclrx}, // bclrx
{257, &Jit64::crXXX}, // crand
@@ -148,7 +150,7 @@ constexpr std::array<GekkoOPTemplate, 13> s_table19{{
{50, &Jit64::rfi}, // rfi
}};
constexpr std::array<GekkoOPTemplate, 107> s_table31{{
constexpr std::array<Jit64OpTemplate, 107> s_table31{{
{266, &Jit64::addx}, // addx
{778, &Jit64::addx}, // addox
{10, &Jit64::addx}, // addcx
@@ -290,7 +292,7 @@ constexpr std::array<GekkoOPTemplate, 107> s_table31{{
{566, &Jit64::DoNothing}, // tlbsync
}};
constexpr std::array<GekkoOPTemplate, 9> s_table59{{
constexpr std::array<Jit64OpTemplate, 9> s_table59{{
{18, &Jit64::fp_arith}, // fdivsx
{20, &Jit64::fp_arith}, // fsubsx
{21, &Jit64::fp_arith}, // faddsx
@@ -302,7 +304,7 @@ constexpr std::array<GekkoOPTemplate, 9> s_table59{{
{31, &Jit64::fmaddXX}, // fnmaddsx
}};
constexpr std::array<GekkoOPTemplate, 15> s_table63{{
constexpr std::array<Jit64OpTemplate, 15> s_table63{{
{264, &Jit64::fsign}, // fabsx
{32, &Jit64::fcmpX}, // fcmpo
{0, &Jit64::fcmpX}, // fcmpu
@@ -321,7 +323,7 @@ constexpr std::array<GekkoOPTemplate, 15> s_table63{{
{711, &Jit64::mtfsfx}, // mtfsfx
}};
constexpr std::array<GekkoOPTemplate, 10> s_table63_2{{
constexpr std::array<Jit64OpTemplate, 10> s_table63_2{{
{18, &Jit64::fp_arith}, // fdivx
{20, &Jit64::fp_arith}, // fsubx
{21, &Jit64::fp_arith}, // faddx
@@ -334,38 +336,25 @@ constexpr std::array<GekkoOPTemplate, 10> s_table63_2{{
{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 <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)
constexpr std::array<Jit64::Instruction, 64> s_dyna_op_table = []() consteval
{
for (auto& entry : table)
{
entry = &Jit64::FallBackToInterpreter;
}
}
constexpr std::array<Jit64::Instruction, 64> s_dyna_op_table = [] {
std::array<Jit64::Instruction, 64> table{};
FillWithFallbacks(table);
Common::Fill(table, &Jit64::FallBackToInterpreter);
for (auto& tpl : s_primary_table)
{
ASSERT(table[tpl.opcode] == &Jit64::FallBackToInterpreter);
table[tpl.opcode] = tpl.fn;
}
return table;
}();
}
();
constexpr std::array<Jit64::Instruction, 1024> s_dyna_op_table4 = [] {
constexpr std::array<Jit64::Instruction, 1024> s_dyna_op_table4 = []() consteval
{
std::array<Jit64::Instruction, 1024> table{};
FillWithFallbacks(table);
Common::Fill(table, &Jit64::FallBackToInterpreter);
for (u32 i = 0; i < 32; i++)
{
@@ -373,6 +362,7 @@ constexpr std::array<Jit64::Instruction, 1024> s_dyna_op_table4 = [] {
for (const auto& tpl : s_table4_2)
{
const u32 op = fill + tpl.opcode;
ASSERT(table[op] == &Jit64::FallBackToInterpreter);
table[op] = tpl.fn;
}
}
@@ -383,6 +373,7 @@ constexpr std::array<Jit64::Instruction, 1024> s_dyna_op_table4 = [] {
for (const auto& tpl : s_table4_3)
{
const u32 op = fill + tpl.opcode;
ASSERT(table[op] == &Jit64::FallBackToInterpreter);
table[op] = tpl.fn;
}
}
@@ -390,59 +381,68 @@ constexpr std::array<Jit64::Instruction, 1024> s_dyna_op_table4 = [] {
for (const auto& tpl : s_table4)
{
const u32 op = tpl.opcode;
ASSERT(table[op] == &Jit64::FallBackToInterpreter);
table[op] = tpl.fn;
}
return table;
}();
}
();
constexpr std::array<Jit64::Instruction, 1024> s_dyna_op_table19 = [] {
constexpr std::array<Jit64::Instruction, 1024> s_dyna_op_table19 = []() consteval
{
std::array<Jit64::Instruction, 1024> table{};
FillWithFallbacks(table);
Common::Fill(table, &Jit64::FallBackToInterpreter);
for (const auto& tpl : s_table19)
{
const u32 op = tpl.opcode;
table[op] = tpl.fn;
ASSERT(table[tpl.opcode] == &Jit64::FallBackToInterpreter);
table[tpl.opcode] = tpl.fn;
}
return table;
}();
}
();
constexpr std::array<Jit64::Instruction, 1024> s_dyna_op_table31 = [] {
constexpr std::array<Jit64::Instruction, 1024> s_dyna_op_table31 = []() consteval
{
std::array<Jit64::Instruction, 1024> table{};
FillWithFallbacks(table);
Common::Fill(table, &Jit64::FallBackToInterpreter);
for (const auto& tpl : s_table31)
{
const u32 op = tpl.opcode;
table[op] = tpl.fn;
ASSERT(table[tpl.opcode] == &Jit64::FallBackToInterpreter);
table[tpl.opcode] = tpl.fn;
}
return table;
}();
}
();
constexpr std::array<Jit64::Instruction, 32> s_dyna_op_table59 = [] {
constexpr std::array<Jit64::Instruction, 32> s_dyna_op_table59 = []() consteval
{
std::array<Jit64::Instruction, 32> table{};
FillWithFallbacks(table);
Common::Fill(table, &Jit64::FallBackToInterpreter);
for (const auto& tpl : s_table59)
{
const u32 op = tpl.opcode;
table[op] = tpl.fn;
ASSERT(table[tpl.opcode] == &Jit64::FallBackToInterpreter);
table[tpl.opcode] = tpl.fn;
}
return table;
}();
}
();
constexpr std::array<Jit64::Instruction, 1024> s_dyna_op_table63 = [] {
constexpr std::array<Jit64::Instruction, 1024> s_dyna_op_table63 = []() consteval
{
std::array<Jit64::Instruction, 1024> table{};
FillWithFallbacks(table);
Common::Fill(table, &Jit64::FallBackToInterpreter);
for (const auto& tpl : s_table63)
{
const u32 op = tpl.opcode;
table[op] = tpl.fn;
ASSERT(table[tpl.opcode] == &Jit64::FallBackToInterpreter);
table[tpl.opcode] = tpl.fn;
}
for (u32 i = 0; i < 32; i++)
@@ -451,12 +451,14 @@ constexpr std::array<Jit64::Instruction, 1024> s_dyna_op_table63 = [] {
for (const auto& tpl : s_table63_2)
{
const u32 op = fill + tpl.opcode;
ASSERT(table[op] == &Jit64::FallBackToInterpreter);
table[op] = tpl.fn;
}
}
return table;
}();
}
();
} // Anonymous namespace
@@ -489,16 +491,5 @@ 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;
}
PPCTables::CountInstructionCompile(op.opinfo, js.compilerPC);
}
@@ -267,7 +267,7 @@ void Jit64::dcbx(UGeckoInstruction inst)
// Alright, now figure out how many loops we want to do.
const u8 cycle_count_per_loop =
js.op[0].opinfo->numCycles + js.op[1].opinfo->numCycles + js.op[2].opinfo->numCycles;
js.op[0].opinfo->num_cycles + js.op[1].opinfo->num_cycles + js.op[2].opinfo->num_cycles;
// This is both setting the adjusted loop count to 0 for the downcount <= 0 case and clearing
// the upper bits for the DIV instruction in the downcount > 0 case.
+2 -2
View File
@@ -197,7 +197,7 @@ void JitArm64::FallBackToInterpreter(UGeckoInstruction inst)
gpr.Unlock(WA);
}
Interpreter::Instruction instr = PPCTables::GetInterpreterOp(inst);
Interpreter::Instruction instr = Interpreter::GetInterpreterOp(inst);
MOVP2R(ARM64Reg::X8, instr);
MOVI2R(ARM64Reg::W0, inst.hex);
BLR(ARM64Reg::X8);
@@ -903,7 +903,7 @@ bool JitArm64::DoJit(u32 em_address, JitBlock* b, u32 nextPC)
js.instructionNumber = i;
js.instructionsLeft = (code_block.m_num_instructions - 1) - i;
const GekkoOPInfo* opinfo = op.opinfo;
js.downcountAmount += opinfo->numCycles;
js.downcountAmount += opinfo->num_cycles;
js.isLastInstruction = i == (code_block.m_num_instructions - 1);
if (!m_enable_debugging)
@@ -677,7 +677,7 @@ void JitArm64::dcbx(UGeckoInstruction inst)
// Figure out how many loops we want to do.
const u8 cycle_count_per_loop =
js.op[0].opinfo->numCycles + js.op[1].opinfo->numCycles + js.op[2].opinfo->numCycles;
js.op[0].opinfo->num_cycles + js.op[1].opinfo->num_cycles + js.op[2].opinfo->num_cycles;
LDR(IndexType::Unsigned, reg_downcount, PPC_REG, PPCSTATE_OFF(downcount));
MOVI2R(WA, 0);
@@ -5,19 +5,19 @@
#include <array>
#include "Common/Assert.h"
#include "Common/TypeUtils.h"
#include "Core/PowerPC/Gekko.h"
#include "Core/PowerPC/PPCTables.h"
namespace
{
struct GekkoOPTemplate
struct JitArm64OpTemplate
{
int opcode;
u32 opcode;
JitArm64::Instruction fn;
// GekkoOPInfo opinfo; // Doesn't need opinfo, Interpreter fills it out
};
constexpr std::array<GekkoOPTemplate, 54> primarytable{{
constexpr std::array<JitArm64OpTemplate, 54> s_primary_table{{
{4, &JitArm64::DynaRunTable4}, // RunTable4
{19, &JitArm64::DynaRunTable19}, // RunTable19
{31, &JitArm64::DynaRunTable31}, // RunTable31
@@ -87,7 +87,7 @@ constexpr std::array<GekkoOPTemplate, 54> primarytable{{
// missing: 0, 1, 2, 5, 6, 9, 22, 30, 58, 62
}};
constexpr std::array<GekkoOPTemplate, 13> table4{{
constexpr std::array<JitArm64OpTemplate, 13> s_table4{{
// SUBOP10
{0, &JitArm64::ps_cmpXX}, // ps_cmpu0
{32, &JitArm64::ps_cmpXX}, // ps_cmpo0
@@ -105,7 +105,7 @@ constexpr std::array<GekkoOPTemplate, 13> table4{{
{1014, &JitArm64::FallBackToInterpreter}, // dcbz_l
}};
constexpr std::array<GekkoOPTemplate, 17> table4_2{{
constexpr std::array<JitArm64OpTemplate, 17> s_table4_2{{
{10, &JitArm64::ps_sumX}, // ps_sum0
{11, &JitArm64::ps_sumX}, // ps_sum1
{12, &JitArm64::ps_arith}, // ps_muls0
@@ -125,14 +125,14 @@ constexpr std::array<GekkoOPTemplate, 17> table4_2{{
{31, &JitArm64::ps_arith}, // ps_nmadd
}};
constexpr std::array<GekkoOPTemplate, 4> table4_3{{
constexpr std::array<JitArm64OpTemplate, 4> s_table4_3{{
{6, &JitArm64::psq_lXX}, // psq_lx
{7, &JitArm64::psq_stXX}, // psq_stx
{38, &JitArm64::psq_lXX}, // psq_lux
{39, &JitArm64::psq_stXX}, // psq_stux
}};
constexpr std::array<GekkoOPTemplate, 13> table19{{
constexpr std::array<JitArm64OpTemplate, 13> s_table19{{
{528, &JitArm64::bcctrx}, // bcctrx
{16, &JitArm64::bclrx}, // bclrx
{257, &JitArm64::crXXX}, // crand
@@ -150,7 +150,7 @@ constexpr std::array<GekkoOPTemplate, 13> table19{{
{50, &JitArm64::rfi}, // rfi
}};
constexpr std::array<GekkoOPTemplate, 107> table31{{
constexpr std::array<JitArm64OpTemplate, 107> s_table31{{
{266, &JitArm64::addx}, // addx
{778, &JitArm64::addx}, // addox
{10, &JitArm64::addcx}, // addcx
@@ -292,7 +292,7 @@ constexpr std::array<GekkoOPTemplate, 107> table31{{
{566, &JitArm64::DoNothing}, // tlbsync
}};
constexpr std::array<GekkoOPTemplate, 9> table59{{
constexpr std::array<JitArm64OpTemplate, 9> s_table59{{
{18, &JitArm64::fp_arith}, // fdivsx
{20, &JitArm64::fp_arith}, // fsubsx
{21, &JitArm64::fp_arith}, // faddsx
@@ -304,7 +304,7 @@ constexpr std::array<GekkoOPTemplate, 9> table59{{
{31, &JitArm64::fp_arith}, // fnmaddsx
}};
constexpr std::array<GekkoOPTemplate, 15> table63{{
constexpr std::array<JitArm64OpTemplate, 15> s_table63{{
{264, &JitArm64::fp_logic}, // fabsx
{32, &JitArm64::fcmpX}, // fcmpo
{0, &JitArm64::fcmpX}, // fcmpu
@@ -323,7 +323,7 @@ constexpr std::array<GekkoOPTemplate, 15> table63{{
{711, &JitArm64::mtfsfx}, // mtfsfx
}};
constexpr std::array<GekkoOPTemplate, 10> table63_2{{
constexpr std::array<JitArm64OpTemplate, 10> s_table63_2{{
{18, &JitArm64::fp_arith}, // fdivx
{20, &JitArm64::fp_arith}, // fsubx
{21, &JitArm64::fp_arith}, // faddx
@@ -336,172 +336,160 @@ constexpr std::array<GekkoOPTemplate, 10> table63_2{{
{31, &JitArm64::fp_arith}, // fnmaddx
}};
constexpr std::array<JitArm64::Instruction, 64> dynaOpTable = [] {
constexpr std::array<JitArm64::Instruction, 64> s_dyna_op_table = []() consteval
{
std::array<JitArm64::Instruction, 64> table{};
Common::Fill(table, &JitArm64::FallBackToInterpreter);
for (auto& tpl : table)
{
tpl = &JitArm64::FallBackToInterpreter;
}
for (const auto& tpl : primarytable)
for (auto& tpl : s_primary_table)
{
ASSERT(table[tpl.opcode] == &JitArm64::FallBackToInterpreter);
table[tpl.opcode] = tpl.fn;
}
return table;
}();
}
();
constexpr std::array<JitArm64::Instruction, 1024> dynaOpTable4 = [] {
constexpr std::array<JitArm64::Instruction, 1024> s_dyna_op_table4 = []() consteval
{
std::array<JitArm64::Instruction, 1024> table{};
Common::Fill(table, &JitArm64::FallBackToInterpreter);
for (auto& entry : table)
for (u32 i = 0; i < 32; i++)
{
entry = &JitArm64::FallBackToInterpreter;
}
for (int i = 0; i < 32; i++)
{
const int fill = i << 5;
for (const auto& tpl : table4_2)
const u32 fill = i << 5;
for (const auto& tpl : s_table4_2)
{
const int op = fill + tpl.opcode;
const u32 op = fill + tpl.opcode;
ASSERT(table[op] == &JitArm64::FallBackToInterpreter);
table[op] = tpl.fn;
}
}
for (int i = 0; i < 16; i++)
for (u32 i = 0; i < 16; i++)
{
const int fill = i << 6;
for (const auto& tpl : table4_3)
const u32 fill = i << 6;
for (const auto& tpl : s_table4_3)
{
const int op = fill + tpl.opcode;
const u32 op = fill + tpl.opcode;
ASSERT(table[op] == &JitArm64::FallBackToInterpreter);
table[op] = tpl.fn;
}
}
for (const auto& tpl : table4)
for (const auto& tpl : s_table4)
{
table[tpl.opcode] = tpl.fn;
const u32 op = tpl.opcode;
ASSERT(table[op] == &JitArm64::FallBackToInterpreter);
table[op] = tpl.fn;
}
return table;
}();
}
();
constexpr std::array<JitArm64::Instruction, 1024> dynaOpTable19 = [] {
constexpr std::array<JitArm64::Instruction, 1024> s_dyna_op_table19 = []() consteval
{
std::array<JitArm64::Instruction, 1024> table{};
Common::Fill(table, &JitArm64::FallBackToInterpreter);
for (auto& entry : table)
{
entry = &JitArm64::FallBackToInterpreter;
}
for (const auto& tpl : table19)
for (const auto& tpl : s_table19)
{
ASSERT(table[tpl.opcode] == &JitArm64::FallBackToInterpreter);
table[tpl.opcode] = tpl.fn;
}
return table;
}();
}
();
constexpr std::array<JitArm64::Instruction, 1024> dynaOpTable31 = [] {
constexpr std::array<JitArm64::Instruction, 1024> s_dyna_op_table31 = []() consteval
{
std::array<JitArm64::Instruction, 1024> table{};
Common::Fill(table, &JitArm64::FallBackToInterpreter);
for (auto& entry : table)
{
entry = &JitArm64::FallBackToInterpreter;
}
for (const auto& tpl : table31)
for (const auto& tpl : s_table31)
{
ASSERT(table[tpl.opcode] == &JitArm64::FallBackToInterpreter);
table[tpl.opcode] = tpl.fn;
}
return table;
}();
}
();
constexpr std::array<JitArm64::Instruction, 32> dynaOpTable59 = [] {
constexpr std::array<JitArm64::Instruction, 32> s_dyna_op_table59 = []() consteval
{
std::array<JitArm64::Instruction, 32> table{};
Common::Fill(table, &JitArm64::FallBackToInterpreter);
for (auto& entry : table)
{
entry = &JitArm64::FallBackToInterpreter;
}
for (const auto& tpl : table59)
for (const auto& tpl : s_table59)
{
ASSERT(table[tpl.opcode] == &JitArm64::FallBackToInterpreter);
table[tpl.opcode] = tpl.fn;
}
return table;
}();
}
();
constexpr std::array<JitArm64::Instruction, 1024> dynaOpTable63 = [] {
constexpr std::array<JitArm64::Instruction, 1024> s_dyna_op_table63 = []() consteval
{
std::array<JitArm64::Instruction, 1024> table{};
Common::Fill(table, &JitArm64::FallBackToInterpreter);
for (auto& entry : table)
{
entry = &JitArm64::FallBackToInterpreter;
}
for (const auto& tpl : table63)
for (const auto& tpl : s_table63)
{
ASSERT(table[tpl.opcode] == &JitArm64::FallBackToInterpreter);
table[tpl.opcode] = tpl.fn;
}
for (int i = 0; i < 32; i++)
for (u32 i = 0; i < 32; i++)
{
const int fill = i << 5;
for (const auto& tpl : table63_2)
const u32 fill = i << 5;
for (const auto& tpl : s_table63_2)
{
const int op = fill + tpl.opcode;
const u32 op = fill + tpl.opcode;
ASSERT(table[op] == &JitArm64::FallBackToInterpreter);
table[op] = tpl.fn;
}
}
return table;
}();
}
();
} // Anonymous namespace
void JitArm64::DynaRunTable4(UGeckoInstruction inst)
{
(this->*dynaOpTable4[inst.SUBOP10])(inst);
(this->*s_dyna_op_table4[inst.SUBOP10])(inst);
}
void JitArm64::DynaRunTable19(UGeckoInstruction inst)
{
(this->*dynaOpTable19[inst.SUBOP10])(inst);
(this->*s_dyna_op_table19[inst.SUBOP10])(inst);
}
void JitArm64::DynaRunTable31(UGeckoInstruction inst)
{
(this->*dynaOpTable31[inst.SUBOP10])(inst);
(this->*s_dyna_op_table31[inst.SUBOP10])(inst);
}
void JitArm64::DynaRunTable59(UGeckoInstruction inst)
{
(this->*dynaOpTable59[inst.SUBOP5])(inst);
(this->*s_dyna_op_table59[inst.SUBOP5])(inst);
}
void JitArm64::DynaRunTable63(UGeckoInstruction inst)
{
(this->*dynaOpTable63[inst.SUBOP10])(inst);
(this->*s_dyna_op_table63[inst.SUBOP10])(inst);
}
void JitArm64::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)
{
#ifdef OPLOG
if (!strcmp(info->opname, OP_TO_LOG))
{ ///"mcrfs"
rsplocations.push_back(js.compilerPC);
}
#endif
info->compileCount++;
info->lastUse = js.compilerPC;
}
PPCTables::CountInstructionCompile(op.opinfo, js.compilerPC);
}
+2 -2
View File
@@ -770,13 +770,13 @@ u32 PPCAnalyzer::Analyze(u32 address, CodeBlock* block, CodeBuffer* buffer,
num_inst++;
const UGeckoInstruction inst = result.hex;
GekkoOPInfo* opinfo = PPCTables::GetOpInfo(inst);
const GekkoOPInfo* opinfo = PPCTables::GetOpInfo(inst);
code[i] = {};
code[i].opinfo = opinfo;
code[i].address = address;
code[i].inst = inst;
code[i].skip = false;
block->m_stats->numCycles += opinfo->numCycles;
block->m_stats->numCycles += opinfo->num_cycles;
block->m_physical_addresses.insert(result.physical_address);
SetInstructionStats(block, &code[i], opinfo);
+1 -1
View File
@@ -29,7 +29,7 @@ namespace PPCAnalyst
struct CodeOp // 16B
{
UGeckoInstruction inst;
GekkoOPInfo* opinfo = nullptr;
const GekkoOPInfo* opinfo = nullptr;
u32 address = 0;
u32 branchTo = 0; // if UINT32_MAX, not a branch
BitSet32 regsOut;
File diff suppressed because it is too large Load Diff
+13 -16
View File
@@ -5,6 +5,7 @@
#include <array>
#include <cstddef>
#include <utility>
#include "Common/CommonTypes.h"
#include "Core/PowerPC/Gekko.h"
@@ -98,35 +99,31 @@ enum class OpType
Unknown,
};
struct GekkoOPStats
{
u64 run_count;
u32 compile_count;
u32 last_use;
};
struct GekkoOPInfo
{
const char* opname;
OpType type;
u32 num_cycles;
u64 flags;
int numCycles;
u64 runCount;
int compileCount;
u32 lastUse;
// Mutable
GekkoOPStats* stats;
};
extern std::array<GekkoOPInfo*, 64> m_infoTable;
extern std::array<GekkoOPInfo*, 1024> m_infoTable4;
extern std::array<GekkoOPInfo*, 1024> m_infoTable19;
extern std::array<GekkoOPInfo*, 1024> m_infoTable31;
extern std::array<GekkoOPInfo*, 32> m_infoTable59;
extern std::array<GekkoOPInfo*, 1024> m_infoTable63;
extern std::array<GekkoOPInfo*, 512> m_allInstructions;
extern size_t m_numInstructions;
namespace PPCTables
{
GekkoOPInfo* GetOpInfo(UGeckoInstruction inst);
Interpreter::Instruction GetInterpreterOp(UGeckoInstruction inst);
const GekkoOPInfo* GetOpInfo(UGeckoInstruction inst);
bool IsValidInstruction(UGeckoInstruction inst);
bool UsesFPU(UGeckoInstruction inst);
void CountInstruction(UGeckoInstruction inst);
void CountInstructionCompile(const GekkoOPInfo* info, u32 pc);
void PrintInstructionRunCounts();
void LogCompiledInstructions();
const char* GetInstructionName(UGeckoInstruction inst);