mirror of
https://github.com/RetroDECK/Duckstation.git
synced 2024-11-23 14:25:37 +00:00
CPU/Recompiler: Check interrupts after mtc0 sr/cause
Fixes Jackie Chan Stuntmaster in Recompiler mode.
This commit is contained in:
parent
b00f50c927
commit
ad727c7991
|
@ -1545,7 +1545,9 @@ bool CodeGenerator::Compile_cop0(const CodeBlockInstruction& cbi)
|
||||||
{
|
{
|
||||||
u32 offset;
|
u32 offset;
|
||||||
u32 write_mask = UINT32_C(0xFFFFFFFF);
|
u32 write_mask = UINT32_C(0xFFFFFFFF);
|
||||||
switch (static_cast<Cop0Reg>(cbi.instruction.r.rd.GetValue()))
|
|
||||||
|
const Cop0Reg reg = static_cast<Cop0Reg>(cbi.instruction.r.rd.GetValue());
|
||||||
|
switch (reg)
|
||||||
{
|
{
|
||||||
case Cop0Reg::BPC:
|
case Cop0Reg::BPC:
|
||||||
offset = offsetof(Core, m_cop0_regs.BPC);
|
offset = offsetof(Core, m_cop0_regs.BPC);
|
||||||
|
@ -1627,6 +1629,37 @@ bool CodeGenerator::Compile_cop0(const CodeBlockInstruction& cbi)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (cbi.instruction.cop.CommonOp() == CopCommonInstruction::mtcn &&
|
||||||
|
(reg == Cop0Reg::CAUSE || reg == Cop0Reg::SR))
|
||||||
|
{
|
||||||
|
// Emit an interrupt check on load of CAUSE/SR.
|
||||||
|
Value sr_value = m_register_cache.AllocateScratch(RegSize_32);
|
||||||
|
Value cause_value = m_register_cache.AllocateScratch(RegSize_32);
|
||||||
|
|
||||||
|
// m_cop0_regs.sr.IEc && ((m_cop0_regs.cause.Ip & m_cop0_regs.sr.Im) != 0)
|
||||||
|
LabelType no_interrupt;
|
||||||
|
EmitLoadCPUStructField(sr_value.host_reg, sr_value.size, offsetof(Core, m_cop0_regs.sr.bits));
|
||||||
|
EmitLoadCPUStructField(cause_value.host_reg, cause_value.size, offsetof(Core, m_cop0_regs.cause.bits));
|
||||||
|
EmitBranchIfBitClear(sr_value.host_reg, sr_value.size, 0, &no_interrupt);
|
||||||
|
EmitAnd(sr_value.host_reg, sr_value.host_reg, cause_value);
|
||||||
|
EmitTest(sr_value.host_reg, Value::FromConstantU32(0xFF00));
|
||||||
|
sr_value.ReleaseAndClear();
|
||||||
|
cause_value.ReleaseAndClear();
|
||||||
|
EmitConditionalBranch(Condition::Zero, false, &no_interrupt);
|
||||||
|
|
||||||
|
EmitBranch(GetCurrentFarCodePointer());
|
||||||
|
SwitchToFarCode();
|
||||||
|
|
||||||
|
// we want to flush pc here
|
||||||
|
m_register_cache.PushState();
|
||||||
|
m_register_cache.FlushAllGuestRegisters(false, true);
|
||||||
|
EmitExceptionExit();
|
||||||
|
m_register_cache.PopState();
|
||||||
|
|
||||||
|
SwitchToNearCode();
|
||||||
|
EmitBindLabel(&no_interrupt);
|
||||||
|
}
|
||||||
|
|
||||||
InstructionEpilogue(cbi);
|
InstructionEpilogue(cbi);
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in a new issue