Skip to content

Commit

Permalink
Merge pull request #11400 from Pokechu22/better-ppc-tables
Browse files Browse the repository at this point in the history
Use C++20 features to create opcode tables at compile time
  • Loading branch information
AdmiralCurtiss committed Mar 17, 2023
2 parents 6b545ea + 4dd658f commit 49b495f
Show file tree
Hide file tree
Showing 15 changed files with 1,243 additions and 738 deletions.
13 changes: 13 additions & 0 deletions Source/Core/Common/TypeUtils.h
Original file line number Diff line number Diff line change
Expand Up @@ -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
Original file line number Diff line number Diff line change
Expand Up @@ -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)
Expand Down Expand Up @@ -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)
Expand Down
48 changes: 11 additions & 37 deletions Source/Core/Core/PowerPC/Interpreter/Interpreter.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down Expand Up @@ -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;
}

Expand Down Expand Up @@ -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)
Expand All @@ -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();
Expand All @@ -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();
Expand All @@ -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()
Expand Down
11 changes: 3 additions & 8 deletions Source/Core/Core/PowerPC/Interpreter/Interpreter.h
Original file line number Diff line number Diff line change
Expand Up @@ -262,12 +262,9 @@ class Interpreter : public CPUCoreBase
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();
Expand All @@ -283,8 +280,6 @@ class Interpreter : public CPUCoreBase
private:
void CheckExceptions();

static void InitializeInstructionTables();

static bool HandleFunctionHooking(u32 address);

// flag helper
Expand Down
Loading

0 comments on commit 49b495f

Please sign in to comment.