CPU/Recompiler: Exit block early on DCIC/BPCM change

Fixes booting Xplorer cartridge with recompiler.
This commit is contained in:
Stenzek 2024-12-23 23:10:20 +10:00
parent 307bd86b72
commit 18c509a679
No known key found for this signature in database
5 changed files with 43 additions and 16 deletions

View File

@ -105,6 +105,8 @@ protected:
FLUSH_FOR_BRANCH = (FLUSH_FLUSH_MIPS_REGISTERS),
FLUSH_FOR_EXCEPTION =
(FLUSH_CYCLES | FLUSH_GTE_DONE_CYCLE), // GTE cycles needed because it stalls when a GTE instruction is next.
FLUSH_FOR_EARLY_BLOCK_EXIT =
(FLUSH_FLUSH_MIPS_REGISTERS | FLUSH_CYCLES | FLUSH_GTE_DONE_CYCLE | FLUSH_PC | FLUSH_LOAD_DELAY),
FLUSH_FOR_INTERPRETER = (FLUSH_FLUSH_MIPS_REGISTERS | FLUSH_INVALIDATE_MIPS_REGISTERS |
FLUSH_FREE_CALLER_SAVED_REGISTERS | FLUSH_PC | FLUSH_CYCLES | FLUSH_INSTRUCTION_BITS |
FLUSH_LOAD_DELAY | FLUSH_GTE_DONE_CYCLE | FLUSH_INVALIDATE_SPECULATIVE_CONSTANTS),

View File

@ -2286,11 +2286,17 @@ void CPU::ARM32Recompiler::Compile_mtc0(CompileFlags cf)
armAsm->ldr(RARG1, PTR(&g_state.cop0_regs.sr.bits));
TestInterrupts(RARG1);
}
if (reg == Cop0Reg::DCIC && g_settings.cpu_recompiler_memory_exceptions)
else if (reg == Cop0Reg::DCIC || reg == Cop0Reg::BPCM)
{
// TODO: DCIC handling for debug breakpoints
WARNING_LOG("TODO: DCIC handling for debug breakpoints");
// need to check whether we're switching to debug mode
Flush(FLUSH_FOR_C_CALL);
EmitCall(reinterpret_cast<const void*>(&CPU::UpdateDebugDispatcherFlag));
SwitchToFarCodeIfRegZeroOrNonZero(RRET, true);
BackupHostState();
Flush(FLUSH_FOR_EARLY_BLOCK_EXIT);
EmitCall(reinterpret_cast<const void*>(&CPU::ExitExecution)); // does not return
RestoreHostState();
SwitchToNearCode(false);
}
}

View File

@ -2443,11 +2443,17 @@ void CPU::ARM64Recompiler::Compile_mtc0(CompileFlags cf)
armAsm->ldr(RWARG1, PTR(&g_state.cop0_regs.sr.bits));
TestInterrupts(RWARG1);
}
if (reg == Cop0Reg::DCIC && g_settings.cpu_recompiler_memory_exceptions)
else if (reg == Cop0Reg::DCIC || reg == Cop0Reg::BPCM)
{
// TODO: DCIC handling for debug breakpoints
WARNING_LOG("TODO: DCIC handling for debug breakpoints");
// need to check whether we're switching to debug mode
Flush(FLUSH_FOR_C_CALL);
EmitCall(reinterpret_cast<const void*>(&CPU::UpdateDebugDispatcherFlag));
SwitchToFarCodeIfRegZeroOrNonZero(RWRET, true);
BackupHostState();
Flush(FLUSH_FOR_EARLY_BLOCK_EXIT);
EmitCall(reinterpret_cast<const void*>(&CPU::ExitExecution)); // does not return
RestoreHostState();
SwitchToNearCode(false);
}
}

View File

@ -2300,11 +2300,17 @@ void CPU::RISCV64Recompiler::Compile_mtc0(CompileFlags cf)
rvAsm->LW(RARG1, PTR(&g_state.cop0_regs.sr.bits));
TestInterrupts(RARG1);
}
if (reg == Cop0Reg::DCIC && g_settings.cpu_recompiler_memory_exceptions)
else if (reg == Cop0Reg::DCIC || reg == Cop0Reg::BPCM)
{
// TODO: DCIC handling for debug breakpoints
WARNING_LOG("TODO: DCIC handling for debug breakpoints");
// need to check whether we're switching to debug mode
Flush(FLUSH_FOR_C_CALL);
EmitCall(reinterpret_cast<const void*>(&CPU::UpdateDebugDispatcherFlag));
SwitchToFarCode(true, &Assembler::BEQ, RRET, zero);
BackupHostState();
Flush(FLUSH_FOR_EARLY_BLOCK_EXIT);
EmitCall(reinterpret_cast<const void*>(&CPU::ExitExecution)); // does not return
RestoreHostState();
SwitchToNearCode(false);
}
}

View File

@ -2259,11 +2259,18 @@ void CPU::X64Recompiler::Compile_mtc0(CompileFlags cf)
cg->mov(RWARG1, cg->dword[PTR(&g_state.cop0_regs.sr.bits)]);
TestInterrupts(RWARG1);
}
if (reg == Cop0Reg::DCIC && g_settings.cpu_recompiler_memory_exceptions)
else if (reg == Cop0Reg::DCIC || reg == Cop0Reg::BPCM)
{
// TODO: DCIC handling for debug breakpoints
WARNING_LOG("TODO: DCIC handling for debug breakpoints");
// need to check whether we're switching to debug mode
Flush(FLUSH_FOR_C_CALL);
cg->call(&CPU::UpdateDebugDispatcherFlag);
cg->test(cg->al, cg->al);
SwitchToFarCode(true, &Xbyak::CodeGenerator::jnz);
BackupHostState();
Flush(FLUSH_FOR_EARLY_BLOCK_EXIT);
cg->call(&CPU::ExitExecution); // does not return
RestoreHostState();
SwitchToNearCode(false);
}
}