CPU: Use table lookup for mfc0

pull/3750/head
Stenzek 1 month ago
parent 2f8e9a8510
commit c660f85320
No known key found for this signature in database

@ -590,6 +590,55 @@ ALWAYS_INLINE_RELEASE void CPU::Cop0DataBreakpointCheck(VirtualMemoryAddress add
DispatchCop0Breakpoint(true);
}
namespace CPU {
static constexpr const std::array<std::pair<u32*, u32>, 32> s_cop0_table = {{
{nullptr, 0x00000000u},
{nullptr, 0x00000000u},
{nullptr, 0x00000000u},
{&g_state.cop0_regs.BPC, 0xffffffffu},
{nullptr, 0},
{&g_state.cop0_regs.BDA, 0xffffffffu},
{&g_state.cop0_regs.TAR, 0x00000000u},
{&g_state.cop0_regs.dcic.bits, Cop0Registers::DCIC::WRITE_MASK},
{&g_state.cop0_regs.BadVaddr, 0x00000000u},
{&g_state.cop0_regs.BDAM, 0xffffffffu},
{nullptr, 0x00000000u},
{&g_state.cop0_regs.BPCM, 0xffffffffu},
{&g_state.cop0_regs.sr.bits, Cop0Registers::SR::WRITE_MASK},
{&g_state.cop0_regs.cause.bits, Cop0Registers::CAUSE::WRITE_MASK},
{&g_state.cop0_regs.EPC, 0x00000000u},
{&g_state.cop0_regs.PRID, 0x00000000u},
{nullptr, 0x00000000u},
{nullptr, 0x00000000u},
{nullptr, 0x00000000u},
{nullptr, 0x00000000u},
{nullptr, 0x00000000u},
{nullptr, 0x00000000u},
{nullptr, 0x00000000u},
{nullptr, 0x00000000u},
{nullptr, 0x00000000u},
{nullptr, 0x00000000u},
{nullptr, 0x00000000u},
{nullptr, 0x00000000u},
{nullptr, 0x00000000u},
{nullptr, 0x00000000u},
{nullptr, 0x00000000u},
{nullptr, 0x00000000u},
}};
} // namespace CPU
u32* CPU::GetCop0RegPtr(Cop0Reg reg)
{
DebugAssert(static_cast<u8>(reg) < std::size(s_cop0_table));
return s_cop0_table[static_cast<u8>(reg)].first;
}
u32 CPU::GetCop0RegWriteMask(Cop0Reg reg)
{
DebugAssert(static_cast<u8>(reg) < std::size(s_cop0_table));
return s_cop0_table[static_cast<u8>(reg)].second;
}
#ifdef _DEBUG
void CPU::TracePrintInstruction()
@ -1723,63 +1772,18 @@ restart_instruction:
{
case CopCommonInstruction::mfcn:
{
u32 value;
switch (static_cast<Cop0Reg>(inst.r.rd.GetValue()))
if (const u32* value = GetCop0RegPtr(static_cast<Cop0Reg>(inst.r.rd.GetValue()))) [[likely]]
{
case Cop0Reg::BPC:
value = g_state.cop0_regs.BPC;
break;
case Cop0Reg::BPCM:
value = g_state.cop0_regs.BPCM;
break;
WriteRegDelayed(inst.r.rt, *value);
case Cop0Reg::BDA:
value = g_state.cop0_regs.BDA;
break;
case Cop0Reg::BDAM:
value = g_state.cop0_regs.BDAM;
break;
case Cop0Reg::DCIC:
value = g_state.cop0_regs.dcic.bits;
break;
case Cop0Reg::JUMPDEST:
value = g_state.cop0_regs.TAR;
break;
case Cop0Reg::BadVaddr:
value = g_state.cop0_regs.BadVaddr;
break;
case Cop0Reg::SR:
value = g_state.cop0_regs.sr.bits;
break;
case Cop0Reg::CAUSE:
value = g_state.cop0_regs.cause.bits;
break;
case Cop0Reg::EPC:
value = g_state.cop0_regs.EPC;
break;
case Cop0Reg::PRID:
value = g_state.cop0_regs.PRID;
break;
default:
RaiseException(Exception::RI);
return;
if constexpr (pgxp_mode == PGXPMode::CPU)
PGXP::CPU_MFC0(inst, *value);
}
else
{
RaiseException(Exception::RI);
return;
}
WriteRegDelayed(inst.r.rt, value);
if constexpr (pgxp_mode == PGXPMode::CPU)
PGXP::CPU_MFC0(inst, value);
}
break;
@ -2103,6 +2107,10 @@ restart_instruction:
}
}
#undef END_INSTRUCTION
#undef BEGIN_FUNCT_INSTRUCTION
#undef BEGIN_INSTRUCTION
void CPU::DispatchInterrupt()
{
// The GTE is a co-processor, therefore it executes the instruction even if we're servicing an exception.

@ -24,6 +24,9 @@ void RaiseException(Exception excode);
void RaiseException(u32 CAUSE_bits, u32 EPC);
void RaiseBreakException(u32 CAUSE_bits, u32 EPC, u32 instruction_bits);
u32* GetCop0RegPtr(Cop0Reg reg);
u32 GetCop0RegWriteMask(Cop0Reg reg);
ALWAYS_INLINE bool HasPendingInterrupt()
{
return g_state.cop0_regs.sr.IEc &&

@ -2183,34 +2183,6 @@ void CPU::Recompiler::Recompiler::Compile_lui()
GeneratePGXPCallWithMIPSRegs(reinterpret_cast<const void*>(&PGXP::CPU_LUI), inst->bits);
}
static constexpr const std::array<std::pair<u32*, u32>, 16> s_cop0_table = {
{{nullptr, 0x00000000u},
{nullptr, 0x00000000u},
{nullptr, 0x00000000u},
{&CPU::g_state.cop0_regs.BPC, 0xffffffffu},
{nullptr, 0},
{&CPU::g_state.cop0_regs.BDA, 0xffffffffu},
{&CPU::g_state.cop0_regs.TAR, 0x00000000u},
{&CPU::g_state.cop0_regs.dcic.bits, CPU::Cop0Registers::DCIC::WRITE_MASK},
{&CPU::g_state.cop0_regs.BadVaddr, 0x00000000u},
{&CPU::g_state.cop0_regs.BDAM, 0xffffffffu},
{nullptr, 0x00000000u},
{&CPU::g_state.cop0_regs.BPCM, 0xffffffffu},
{&CPU::g_state.cop0_regs.sr.bits, CPU::Cop0Registers::SR::WRITE_MASK},
{&CPU::g_state.cop0_regs.cause.bits, CPU::Cop0Registers::CAUSE::WRITE_MASK},
{&CPU::g_state.cop0_regs.EPC, 0x00000000u},
{&CPU::g_state.cop0_regs.PRID, 0x00000000u}}};
u32* CPU::Recompiler::Recompiler::GetCop0RegPtr(Cop0Reg reg)
{
return (static_cast<u8>(reg) < s_cop0_table.size()) ? s_cop0_table[static_cast<u8>(reg)].first : nullptr;
}
u32 CPU::Recompiler::Recompiler::GetCop0RegWriteMask(Cop0Reg reg)
{
return (static_cast<u8>(reg) < s_cop0_table.size()) ? s_cop0_table[static_cast<u8>(reg)].second : 0;
}
void CPU::Recompiler::Recompiler::Compile_mfc0(CompileFlags cf)
{
const Cop0Reg r = static_cast<Cop0Reg>(MipsD());

@ -443,9 +443,6 @@ protected:
virtual void Compile_swc2(CompileFlags cf, MemoryAccessSize size, bool sign, bool use_fastmem,
const std::optional<VirtualMemoryAddress>& address) = 0;
static u32* GetCop0RegPtr(Cop0Reg reg);
static u32 GetCop0RegWriteMask(Cop0Reg reg);
static void MIPSSignedDivide(s32 num, s32 denom, u32* lo, u32* hi);
static void MIPSUnsignedDivide(u32 num, u32 denom, u32* lo, u32* hi);

Loading…
Cancel
Save