Add interrupt controller emulation

This commit is contained in:
Connor McLaughlin
2019-09-17 16:26:00 +10:00
parent c615e007c0
commit 2128a2984b
13 changed files with 271 additions and 19 deletions

View File

@ -36,6 +36,7 @@ void Core::Reset()
m_cop0_regs.BPCM = 0;
m_cop0_regs.EPC = 0;
m_cop0_regs.sr.bits = 0;
m_cop0_regs.cause.bits = 0;
SetPC(RESET_VECTOR);
}
@ -60,10 +61,13 @@ bool Core::DoState(StateWrapper& sw)
sw.Do(&m_cop0_regs.cause.bits);
sw.Do(&m_cop0_regs.dcic.bits);
sw.Do(&m_next_instruction.bits);
sw.Do(&m_in_branch_delay_slot);
sw.Do(&m_branched);
sw.Do(&m_current_instruction_pc);
sw.Do(&m_load_delay_reg);
sw.Do(&m_load_delay_old_value);
sw.Do(&m_next_load_delay_reg);
sw.Do(&m_next_load_delay_old_value);
sw.Do(&m_in_branch_delay_slot);
sw.Do(&m_branched);
sw.Do(&m_cache_control);
sw.DoBytes(m_dcache.data(), m_dcache.size());
return !sw.HasError();
@ -197,6 +201,28 @@ void Core::RaiseException(Exception excode, u8 coprocessor /* = 0 */)
FlushPipeline();
}
void Core::SetExternalInterrupt(u8 bit)
{
m_cop0_regs.cause.Ip |= static_cast<u8>(1u << bit);
}
void Core::ClearExternalInterrupt(u8 bit)
{
m_cop0_regs.cause.Ip &= static_cast<u8>(~(1u << bit));
}
bool Core::DispatchInterrupts()
{
// const bool do_interrupt = m_cop0_regs.sr.IEc && ((m_cop0_regs.cause.Ip & m_cop0_regs.sr.Im) != 0);
const bool do_interrupt =
m_cop0_regs.sr.IEc && (((m_cop0_regs.cause.bits & m_cop0_regs.sr.bits) & (UINT32_C(0xFF) << 8)) != 0);
if (!do_interrupt)
return false;
RaiseException(Exception::INT);
return true;
}
void Core::FlushLoadDelay()
{
m_load_delay_reg = Reg::count;
@ -284,7 +310,7 @@ TickCount Core::Execute()
m_current_instruction_pc = m_regs.pc;
// fetch the next instruction
if (!FetchInstruction())
if (DispatchInterrupts() || !FetchInstruction())
continue;
// handle branch delays - we are now in a delay slot if we just branched
@ -300,7 +326,7 @@ TickCount Core::Execute()
m_load_delay_old_value = m_next_load_delay_old_value;
m_next_load_delay_old_value = 0;
}
// reset slice ticks, it'll be updated when the components execute
m_slice_ticks = MAX_CPU_SLICE_SIZE;
return executed_ticks;