mirror of
https://github.com/dolphin-emu/dolphin.git
synced 2025-01-08 15:20:45 +01:00
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.)
This commit is contained in:
parent
c528a70e64
commit
2aa00e15db
@ -489,7 +489,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;
|
||||
}
|
||||
@ -565,7 +565,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);
|
||||
|
@ -182,7 +182,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,
|
||||
|
@ -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)
|
||||
@ -279,7 +280,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);
|
||||
|
||||
@ -586,7 +587,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);
|
||||
|
||||
|
@ -650,7 +650,7 @@ void FifoPlayer::LoadMemory()
|
||||
HID4(ppc_state).SBE = 1;
|
||||
}
|
||||
|
||||
PowerPC::MSRUpdated(ppc_state);
|
||||
m_system.GetPowerPC().MSRUpdated();
|
||||
|
||||
auto& mmu = m_system.GetMMU();
|
||||
mmu.DBATUpdated();
|
||||
|
@ -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.");
|
||||
|
||||
|
@ -661,7 +661,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));
|
||||
|
@ -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;
|
||||
}
|
||||
|
@ -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);
|
||||
|
@ -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)
|
||||
|
@ -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)
|
||||
|
@ -235,7 +235,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{{
|
||||
@ -369,7 +370,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},
|
||||
|
@ -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
|
||||
|
@ -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];
|
||||
|
@ -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; }
|
||||
@ -335,6 +337,8 @@ void CheckExceptionsFromJIT(PowerPCManager& power_pc);
|
||||
void CheckExternalExceptionsFromJIT(PowerPCManager& power_pc);
|
||||
void CheckAndHandleBreakPointsFromJIT(PowerPCManager& power_pc);
|
||||
|
||||
void MSRUpdated(PowerPCManager& power_pc);
|
||||
|
||||
// Easy register access macros.
|
||||
#define HID0(ppc_state) ((UReg_HID0&)(ppc_state).spr[SPR_HID0])
|
||||
#define HID2(ppc_state) ((UReg_HID2&)(ppc_state).spr[SPR_HID2])
|
||||
@ -356,7 +360,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);
|
||||
|
||||
|
@ -451,7 +451,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
|
||||
|
Loading…
Reference in New Issue
Block a user