summaryrefslogtreecommitdiff
path: root/Source/Core
diff options
context:
space:
mode:
authorJosJuice <josjuice@gmail.com>2024-12-24 16:43:38 +0100
committerJosJuice <josjuice@gmail.com>2025-11-02 21:18:07 +0100
commit874985564363dc97858809d46e798dbe0bfe696b (patch)
treeae4e9fd0e27bc2948386117eba138a385397daf7 /Source/Core
parent249f999c6a11aef91c5541b5f1736cb1df7ea0b5 (diff)
Call JitInterface::UpdateMembase from PowerPC::MSRUpdated
When the interpreter calls MSRUpdated, we should update the membase variable. Not because the interpreter itself needs it, but because the JIT needs it if it's falling back to the interpreter for an instruction that sets the MSR. Additionally, the JIT's FallBackToInterpreter needs to read back the new membase value afterwards. This fixes games crashing on JitArm64 if mtmsr is set to fall back to interpreter. I was unable to reproduce the issue on Jit64, presumably due to a fortunate series of coincidences (instructions that set MSR are always followed by an exception exit, and PowerPCManager::CheckExternalExceptions was always calling JitInterface::UpdateMembase, and Jit64::WriteExceptionExit was always calling Jit64::EmitUpdateMembase.)
Diffstat (limited to 'Source/Core')
-rw-r--r--Source/Core/Core/Boot/Boot.cpp4
-rw-r--r--Source/Core/Core/Boot/Boot.h2
-rw-r--r--Source/Core/Core/Boot/Boot_BS2Emu.cpp9
-rw-r--r--Source/Core/Core/FifoPlayer/FifoPlayer.cpp2
-rw-r--r--Source/Core/Core/IOS/MIOS.cpp2
-rw-r--r--Source/Core/Core/PowerPC/Expression.cpp2
-rw-r--r--Source/Core/Core/PowerPC/GDBStub.cpp2
-rw-r--r--Source/Core/Core/PowerPC/Interpreter/Interpreter_Branch.cpp2
-rw-r--r--Source/Core/Core/PowerPC/Interpreter/Interpreter_SystemRegisters.cpp2
-rw-r--r--Source/Core/Core/PowerPC/Jit64/Jit.cpp3
-rw-r--r--Source/Core/Core/PowerPC/JitArm64/Jit.cpp3
-rw-r--r--Source/Core/Core/PowerPC/PPCTables.cpp5
-rw-r--r--Source/Core/Core/PowerPC/PPCTables.h1
-rw-r--r--Source/Core/Core/PowerPC/PowerPC.cpp31
-rw-r--r--Source/Core/Core/PowerPC/PowerPC.h3
-rw-r--r--Source/Core/DolphinQt/Debugger/RegisterWidget.cpp2
16 files changed, 42 insertions, 33 deletions
diff --git a/Source/Core/Core/Boot/Boot.cpp b/Source/Core/Core/Boot/Boot.cpp
index e43ffc52d4..755ed0427a 100644
--- a/Source/Core/Core/Boot/Boot.cpp
+++ b/Source/Core/Core/Boot/Boot.cpp
@@ -460,7 +460,7 @@ bool CBoot::Load_BS2(Core::System& system, const std::string& boot_rom_filename)
ppc_state.pc = 0x81200150;
- PowerPC::MSRUpdated(ppc_state);
+ system.GetPowerPC().MSRUpdated();
return true;
}
@@ -530,7 +530,7 @@ bool CBoot::BootUp(Core::System& system, const Core::CPUThreadGuard& guard,
auto& ppc_state = system.GetPPCState();
- SetupMSR(ppc_state);
+ SetupMSR(system);
SetupHID(ppc_state, system.IsWii());
SetupBAT(system, system.IsWii());
CopyDefaultExceptionHandlers(system);
diff --git a/Source/Core/Core/Boot/Boot.h b/Source/Core/Core/Boot/Boot.h
index f892ee7c75..087245ee0f 100644
--- a/Source/Core/Core/Boot/Boot.h
+++ b/Source/Core/Core/Boot/Boot.h
@@ -169,7 +169,7 @@ private:
static bool Boot_WiiWAD(Core::System& system, const DiscIO::VolumeWAD& wad);
static bool BootNANDTitle(Core::System& system, u64 title_id);
- static void SetupMSR(PowerPC::PowerPCState& ppc_state);
+ static void SetupMSR(Core::System& system);
static void SetupHID(PowerPC::PowerPCState& ppc_state, bool is_wii);
static void SetupBAT(Core::System& system, bool is_wii);
static bool RunApploader(Core::System& system, const Core::CPUThreadGuard& guard, bool is_wii,
diff --git a/Source/Core/Core/Boot/Boot_BS2Emu.cpp b/Source/Core/Core/Boot/Boot_BS2Emu.cpp
index 149f92f7c1..c65177975a 100644
--- a/Source/Core/Core/Boot/Boot_BS2Emu.cpp
+++ b/Source/Core/Core/Boot/Boot_BS2Emu.cpp
@@ -68,14 +68,15 @@ void CBoot::RunFunction(Core::System& system, u32 address)
power_pc.SingleStep();
}
-void CBoot::SetupMSR(PowerPC::PowerPCState& ppc_state)
+void CBoot::SetupMSR(Core::System& system)
{
// 0x0002032
+ auto& ppc_state = system.GetPPCState();
ppc_state.msr.RI = 1;
ppc_state.msr.DR = 1;
ppc_state.msr.IR = 1;
ppc_state.msr.FP = 1;
- PowerPC::MSRUpdated(ppc_state);
+ system.GetPowerPC().MSRUpdated();
}
void CBoot::SetupHID(PowerPC::PowerPCState& ppc_state, bool is_wii)
@@ -287,7 +288,7 @@ bool CBoot::EmulatedBS2_GC(Core::System& system, const Core::CPUThreadGuard& gua
auto& ppc_state = system.GetPPCState();
- SetupMSR(ppc_state);
+ SetupMSR(system);
SetupHID(ppc_state, /*is_wii*/ false);
SetupBAT(system, /*is_wii*/ false);
@@ -594,7 +595,7 @@ bool CBoot::EmulatedBS2_Wii(Core::System& system, const Core::CPUThreadGuard& gu
auto& ppc_state = system.GetPPCState();
- SetupMSR(ppc_state);
+ SetupMSR(system);
SetupHID(ppc_state, /*is_wii*/ true);
SetupBAT(system, /*is_wii*/ true);
diff --git a/Source/Core/Core/FifoPlayer/FifoPlayer.cpp b/Source/Core/Core/FifoPlayer/FifoPlayer.cpp
index a4b08dc0d2..57ff28d7fd 100644
--- a/Source/Core/Core/FifoPlayer/FifoPlayer.cpp
+++ b/Source/Core/Core/FifoPlayer/FifoPlayer.cpp
@@ -644,7 +644,7 @@ void FifoPlayer::LoadMemory()
HID4(ppc_state).SBE = 1;
}
- PowerPC::MSRUpdated(ppc_state);
+ m_system.GetPowerPC().MSRUpdated();
auto& mmu = m_system.GetMMU();
mmu.DBATUpdated();
diff --git a/Source/Core/Core/IOS/MIOS.cpp b/Source/Core/Core/IOS/MIOS.cpp
index d47400c9d2..56c27c6a78 100644
--- a/Source/Core/Core/IOS/MIOS.cpp
+++ b/Source/Core/Core/IOS/MIOS.cpp
@@ -89,7 +89,7 @@ bool Load(Core::System& system)
PowerPC::PowerPCState& ppc_state = power_pc.GetPPCState();
ppc_state.msr.Hex = 0;
ppc_state.pc = 0x3400;
- PowerPC::MSRUpdated(ppc_state);
+ power_pc.MSRUpdated();
NOTICE_LOG_FMT(IOS, "Loaded MIOS and bootstrapped PPC.");
diff --git a/Source/Core/Core/PowerPC/Expression.cpp b/Source/Core/Core/PowerPC/Expression.cpp
index 4fd946c393..dd477a5f43 100644
--- a/Source/Core/Core/PowerPC/Expression.cpp
+++ b/Source/Core/Core/PowerPC/Expression.cpp
@@ -428,7 +428,7 @@ void Expression::SynchronizeBindings(Core::System& system, SynchronizeDirection
else
{
ppc_state.msr.Hex = static_cast<u32>(static_cast<s64>(v->value));
- PowerPC::MSRUpdated(ppc_state);
+ system.GetPowerPC().MSRUpdated();
}
break;
}
diff --git a/Source/Core/Core/PowerPC/GDBStub.cpp b/Source/Core/Core/PowerPC/GDBStub.cpp
index b8b607d592..fb5a9a99c1 100644
--- a/Source/Core/Core/PowerPC/GDBStub.cpp
+++ b/Source/Core/Core/PowerPC/GDBStub.cpp
@@ -662,7 +662,7 @@ static void WriteRegister()
break;
case 65:
ppc_state.msr.Hex = re32hex(bufptr);
- PowerPC::MSRUpdated(ppc_state);
+ system.GetPowerPC().MSRUpdated();
break;
case 66:
ppc_state.cr.Set(re32hex(bufptr));
diff --git a/Source/Core/Core/PowerPC/Interpreter/Interpreter_Branch.cpp b/Source/Core/Core/PowerPC/Interpreter/Interpreter_Branch.cpp
index 1d57d971b4..e64de461cc 100644
--- a/Source/Core/Core/PowerPC/Interpreter/Interpreter_Branch.cpp
+++ b/Source/Core/Core/PowerPC/Interpreter/Interpreter_Branch.cpp
@@ -161,7 +161,7 @@ void Interpreter::rfi(Interpreter& interpreter, UGeckoInstruction inst)
// set NPC to saved offset and resume
ppc_state.npc = SRR0(ppc_state);
- PowerPC::MSRUpdated(ppc_state);
+ interpreter.m_system.GetPowerPC().MSRUpdated();
interpreter.m_end_block = true;
}
diff --git a/Source/Core/Core/PowerPC/Interpreter/Interpreter_SystemRegisters.cpp b/Source/Core/Core/PowerPC/Interpreter/Interpreter_SystemRegisters.cpp
index a28a968653..e632ab403d 100644
--- a/Source/Core/Core/PowerPC/Interpreter/Interpreter_SystemRegisters.cpp
+++ b/Source/Core/Core/PowerPC/Interpreter/Interpreter_SystemRegisters.cpp
@@ -181,7 +181,7 @@ void Interpreter::mtmsr(Interpreter& interpreter, UGeckoInstruction inst)
ppc_state.msr.Hex = ppc_state.gpr[inst.RS];
- PowerPC::MSRUpdated(ppc_state);
+ interpreter.m_system.GetPowerPC().MSRUpdated();
// FE0/FE1 may have been set
CheckFPExceptions(ppc_state);
diff --git a/Source/Core/Core/PowerPC/Jit64/Jit.cpp b/Source/Core/Core/PowerPC/Jit64/Jit.cpp
index ae37f2b45d..377b4388fb 100644
--- a/Source/Core/Core/PowerPC/Jit64/Jit.cpp
+++ b/Source/Core/Core/PowerPC/Jit64/Jit.cpp
@@ -369,6 +369,9 @@ void Jit64::FallBackToInterpreter(UGeckoInstruction inst)
gpr.Reset(js.op->regsOut);
fpr.Reset(js.op->GetFregsOut());
+ if (js.op->opinfo->flags & FL_SET_MSR)
+ EmitUpdateMembase();
+
if (js.op->canEndBlock)
{
if (js.isLastInstruction)
diff --git a/Source/Core/Core/PowerPC/JitArm64/Jit.cpp b/Source/Core/Core/PowerPC/JitArm64/Jit.cpp
index 65a452ceca..1eda45c58e 100644
--- a/Source/Core/Core/PowerPC/JitArm64/Jit.cpp
+++ b/Source/Core/Core/PowerPC/JitArm64/Jit.cpp
@@ -278,6 +278,9 @@ void JitArm64::FallBackToInterpreter(UGeckoInstruction inst)
fpr.ResetRegisters(js.op->GetFregsOut());
gpr.ResetCRRegisters(js.op->crOut);
+ if (js.op->opinfo->flags & FL_SET_MSR)
+ EmitUpdateMembase();
+
if (js.op->canEndBlock)
{
if (js.isLastInstruction)
diff --git a/Source/Core/Core/PowerPC/PPCTables.cpp b/Source/Core/Core/PowerPC/PPCTables.cpp
index 6cc84121a3..6673f14513 100644
--- a/Source/Core/Core/PowerPC/PPCTables.cpp
+++ b/Source/Core/Core/PowerPC/PPCTables.cpp
@@ -236,7 +236,8 @@ constexpr std::array<GekkoOPTemplate, 13> s_table19{{
{150, "isync", OpType::InstructionCache, 1, FL_NO_REORDER},
{0, "mcrf", OpType::System, 1, FL_SET_CRn | FL_READ_CRn},
- {50, "rfi", OpType::System, 2, FL_ENDBLOCK | FL_CHECKEXCEPTIONS | FL_PROGRAMEXCEPTION},
+ {50, "rfi", OpType::System, 2,
+ FL_ENDBLOCK | FL_CHECKEXCEPTIONS | FL_PROGRAMEXCEPTION | FL_SET_MSR},
}};
constexpr std::array<GekkoOPTemplate, 107> s_table31{{
@@ -370,7 +371,7 @@ constexpr std::array<GekkoOPTemplate, 107> s_table31{{
{83, "mfmsr", OpType::System, 1, FL_OUT_D | FL_PROGRAMEXCEPTION},
{144, "mtcrf", OpType::System, 1, FL_IN_S | FL_SET_ALL_CR | FL_READ_ALL_CR},
{146, "mtmsr", OpType::System, 1,
- FL_IN_S | FL_ENDBLOCK | FL_PROGRAMEXCEPTION | FL_FLOAT_EXCEPTION},
+ FL_IN_S | FL_ENDBLOCK | FL_PROGRAMEXCEPTION | FL_FLOAT_EXCEPTION | FL_SET_MSR},
{210, "mtsr", OpType::System, 1, FL_IN_S | FL_PROGRAMEXCEPTION},
{242, "mtsrin", OpType::System, 1, FL_IN_SB | FL_PROGRAMEXCEPTION},
{339, "mfspr", OpType::SPR, 1, FL_OUT_D | FL_PROGRAMEXCEPTION},
diff --git a/Source/Core/Core/PowerPC/PPCTables.h b/Source/Core/Core/PowerPC/PPCTables.h
index afb265f840..847eaf40c2 100644
--- a/Source/Core/Core/PowerPC/PPCTables.h
+++ b/Source/Core/Core/PowerPC/PPCTables.h
@@ -67,6 +67,7 @@ enum InstructionFlags : u64
FL_READ_ALL_CR = (1ull << 38), // Reads every CR.
FL_SET_CRx = FL_SET_CR0 | FL_SET_CR1 | FL_SET_CRn | FL_SET_ALL_CR,
FL_READ_CRx = FL_READ_CRn | FL_READ_CR_BI | FL_READ_ALL_CR,
+ FL_SET_MSR = (1ull << 39),
};
enum class OpType
diff --git a/Source/Core/Core/PowerPC/PowerPC.cpp b/Source/Core/Core/PowerPC/PowerPC.cpp
index 3cc1112bd7..59f1e3d1bf 100644
--- a/Source/Core/Core/PowerPC/PowerPC.cpp
+++ b/Source/Core/Core/PowerPC/PowerPC.cpp
@@ -568,8 +568,7 @@ void PowerPCManager::CheckExceptions()
return;
}
- m_system.GetJitInterface().UpdateMembase();
- MSRUpdated(m_ppc_state);
+ MSRUpdated();
}
void PowerPCManager::CheckExternalExceptions()
@@ -622,10 +621,8 @@ void PowerPCManager::CheckExternalExceptions()
ERROR_LOG_FMT(POWERPC, "Unknown EXTERNAL INTERRUPT exception: Exceptions == {:08x}",
exceptions);
}
- MSRUpdated(m_ppc_state);
+ MSRUpdated();
}
-
- m_system.GetJitInterface().UpdateMembase();
}
bool PowerPCManager::CheckBreakPoints()
@@ -662,6 +659,19 @@ bool PowerPCManager::CheckAndHandleBreakPoints()
return false;
}
+void PowerPCManager::MSRUpdated()
+{
+ static_assert(UReg_MSR{}.DR.StartBit() == 4);
+ static_assert(UReg_MSR{}.IR.StartBit() == 5);
+ static_assert(FEATURE_FLAG_MSR_DR == 1 << 0);
+ static_assert(FEATURE_FLAG_MSR_IR == 1 << 1);
+
+ m_ppc_state.feature_flags = static_cast<CPUEmuFeatureFlags>(
+ (m_ppc_state.feature_flags & FEATURE_FLAG_PERFMON) | ((m_ppc_state.msr.Hex >> 4) & 0x3));
+
+ m_system.GetJitInterface().UpdateMembase();
+}
+
void PowerPCState::SetSR(u32 index, u32 value)
{
DEBUG_LOG_FMT(POWERPC, "{:08x}: MMU: Segment register {} set to {:08x}", pc, index, value);
@@ -688,17 +698,6 @@ void RoundingModeUpdated(PowerPCState& ppc_state)
Common::FPU::SetSIMDMode(ppc_state.fpscr.RN, ppc_state.fpscr.NI);
}
-void MSRUpdated(PowerPCState& ppc_state)
-{
- static_assert(UReg_MSR{}.DR.StartBit() == 4);
- static_assert(UReg_MSR{}.IR.StartBit() == 5);
- static_assert(FEATURE_FLAG_MSR_DR == 1 << 0);
- static_assert(FEATURE_FLAG_MSR_IR == 1 << 1);
-
- ppc_state.feature_flags = static_cast<CPUEmuFeatureFlags>(
- (ppc_state.feature_flags & FEATURE_FLAG_PERFMON) | ((ppc_state.msr.Hex >> 4) & 0x3));
-}
-
void MMCRUpdated(PowerPCState& ppc_state)
{
const bool perfmon = ppc_state.spr[SPR_MMCR0] || ppc_state.spr[SPR_MMCR1];
diff --git a/Source/Core/Core/PowerPC/PowerPC.h b/Source/Core/Core/PowerPC/PowerPC.h
index 662507697e..ea972590cb 100644
--- a/Source/Core/Core/PowerPC/PowerPC.h
+++ b/Source/Core/Core/PowerPC/PowerPC.h
@@ -290,6 +290,8 @@ public:
u64 ReadFullTimeBaseValue() const;
void WriteFullTimeBaseValue(u64 value);
+ void MSRUpdated();
+
PowerPCState& GetPPCState() { return m_ppc_state; }
const PowerPCState& GetPPCState() const { return m_ppc_state; }
BreakPoints& GetBreakPoints() { return m_breakpoints; }
@@ -356,7 +358,6 @@ void CheckAndHandleBreakPointsFromJIT(PowerPCManager& power_pc);
#define TU(ppc_state) (ppc_state).spr[SPR_TU]
void RoundingModeUpdated(PowerPCState& ppc_state);
-void MSRUpdated(PowerPCState& ppc_state);
void MMCRUpdated(PowerPCState& ppc_state);
void RecalculateAllFeatureFlags(PowerPCState& ppc_state);
diff --git a/Source/Core/DolphinQt/Debugger/RegisterWidget.cpp b/Source/Core/DolphinQt/Debugger/RegisterWidget.cpp
index 01ff696d83..8bb9d88291 100644
--- a/Source/Core/DolphinQt/Debugger/RegisterWidget.cpp
+++ b/Source/Core/DolphinQt/Debugger/RegisterWidget.cpp
@@ -449,7 +449,7 @@ void RegisterWidget::PopulateTable()
23, 5, RegisterType::msr, "MSR", [this] { return m_system.GetPPCState().msr.Hex; },
[this](u64 value) {
m_system.GetPPCState().msr.Hex = value;
- PowerPC::MSRUpdated(m_system.GetPPCState());
+ m_system.GetPowerPC().MSRUpdated();
});
// SRR 0-1