CPU/NewRec: Handle mtc0 rt, sr
This commit is contained in:
@ -367,14 +367,14 @@ void CPU::NewRec::AArch32Compiler::EndBlock(const std::optional<u32>& newpc, boo
|
||||
|
||||
// flush regs
|
||||
Flush(FLUSH_END_BLOCK);
|
||||
EndAndLinkBlock(newpc, do_event_test);
|
||||
EndAndLinkBlock(newpc, do_event_test, false);
|
||||
}
|
||||
|
||||
void CPU::NewRec::AArch32Compiler::EndBlockWithException(Exception excode)
|
||||
{
|
||||
// flush regs, but not pc, it's going to get overwritten
|
||||
// flush cycles because of the GTE instruction stuff...
|
||||
Flush(FLUSH_END_BLOCK | FLUSH_FOR_EXCEPTION);
|
||||
Flush(FLUSH_END_BLOCK | FLUSH_FOR_EXCEPTION | FLUSH_FOR_C_CALL);
|
||||
|
||||
// TODO: flush load delay
|
||||
// TODO: break for pcdrv
|
||||
@ -385,14 +385,16 @@ void CPU::NewRec::AArch32Compiler::EndBlockWithException(Exception excode)
|
||||
EmitCall(reinterpret_cast<const void*>(static_cast<void (*)(u32, u32)>(&CPU::RaiseException)));
|
||||
m_dirty_pc = false;
|
||||
|
||||
EndAndLinkBlock(std::nullopt, true);
|
||||
EndAndLinkBlock(std::nullopt, true, false);
|
||||
}
|
||||
|
||||
void CPU::NewRec::AArch32Compiler::EndAndLinkBlock(const std::optional<u32>& newpc, bool do_event_test)
|
||||
void CPU::NewRec::AArch32Compiler::EndAndLinkBlock(const std::optional<u32>& newpc, bool do_event_test,
|
||||
bool force_run_events)
|
||||
{
|
||||
// event test
|
||||
// pc should've been flushed
|
||||
DebugAssert(!m_dirty_pc);
|
||||
DebugAssert(!m_dirty_pc && !force_run_events);
|
||||
m_block_ended = true;
|
||||
|
||||
// TODO: try extracting this to a function
|
||||
|
||||
@ -420,7 +422,11 @@ void CPU::NewRec::AArch32Compiler::EndAndLinkBlock(const std::optional<u32>& new
|
||||
armEmitCondBranch(armAsm, ge, CodeCache::g_run_events_and_dispatch);
|
||||
|
||||
// jump to dispatcher or next block
|
||||
if (!newpc.has_value())
|
||||
if (force_run_events)
|
||||
{
|
||||
armEmitJmp(armAsm, CodeCache::g_run_events_and_dispatch, false);
|
||||
}
|
||||
else if (!newpc.has_value())
|
||||
{
|
||||
armEmitJmp(armAsm, CodeCache::g_dispatcher, false);
|
||||
}
|
||||
@ -438,8 +444,6 @@ void CPU::NewRec::AArch32Compiler::EndAndLinkBlock(const std::optional<u32>& new
|
||||
armEmitJmp(armAsm, target, true);
|
||||
}
|
||||
}
|
||||
|
||||
m_block_ended = true;
|
||||
}
|
||||
|
||||
const void* CPU::NewRec::AArch32Compiler::EndCompile(u32* code_size, u32* far_code_size)
|
||||
@ -1979,9 +1983,31 @@ void CPU::NewRec::AArch32Compiler::TestInterrupts(const vixl::aarch32::Register&
|
||||
|
||||
SwitchToFarCode(true, ne);
|
||||
BackupHostState();
|
||||
Flush(FLUSH_FLUSH_MIPS_REGISTERS | FLUSH_FOR_EXCEPTION | FLUSH_FOR_C_CALL);
|
||||
EmitCall(reinterpret_cast<const void*>(&DispatchInterrupt));
|
||||
EndBlock(std::nullopt, true);
|
||||
Flush(FLUSH_END_BLOCK | FLUSH_FOR_EXCEPTION | FLUSH_FOR_C_CALL);
|
||||
|
||||
// Can't use EndBlockWithException() here, because it'll use the wrong PC.
|
||||
// Can't use RaiseException() on the fast path if we're the last instruction, because the next PC is unknown.
|
||||
if (!iinfo->is_last_instruction)
|
||||
{
|
||||
EmitMov(RARG1, Cop0Registers::CAUSE::MakeValueForException(Exception::INT, iinfo->is_branch_instruction, false,
|
||||
(inst + 1)->cop.cop_n));
|
||||
EmitMov(RARG2, m_compiler_pc);
|
||||
EmitCall(reinterpret_cast<const void*>(static_cast<void (*)(u32, u32)>(&CPU::RaiseException)));
|
||||
m_dirty_pc = false;
|
||||
EndAndLinkBlock(std::nullopt, true, false);
|
||||
}
|
||||
else
|
||||
{
|
||||
EmitMov(RARG1, 0);
|
||||
if (m_dirty_pc)
|
||||
EmitMov(RARG2, m_compiler_pc);
|
||||
armAsm->str(RARG1, PTR(&g_state.downcount));
|
||||
if (m_dirty_pc)
|
||||
armAsm->str(RARG2, m_compiler_pc);
|
||||
m_dirty_pc = false;
|
||||
EndAndLinkBlock(std::nullopt, false, true);
|
||||
}
|
||||
|
||||
RestoreHostState();
|
||||
SwitchToNearCode(false);
|
||||
|
||||
|
||||
Reference in New Issue
Block a user