From 5971c0ef26d85a71f689461f1623036e60de7072 Mon Sep 17 00:00:00 2001 From: Patrick Mackinlay Date: Thu, 15 Aug 2019 17:46:53 +0700 Subject: [PATCH] r4000: interrupt/exception changes (nw) Rework interrupt handling to address two issues: * clean up software interrupt detection * prioritize instruction fetch tlb miss exceptions over interrupts when interrupt occurs while PC is unmapped The second issue is speculative but reasonably likely, and brings r4000 into line with mips1, where the need for this logic was discovered. --- src/devices/cpu/mips/r4000.cpp | 23 ++++++----------------- 1 file changed, 6 insertions(+), 17 deletions(-) diff --git a/src/devices/cpu/mips/r4000.cpp b/src/devices/cpu/mips/r4000.cpp index 27ef059b04c..7e6ad52f5a0 100644 --- a/src/devices/cpu/mips/r4000.cpp +++ b/src/devices/cpu/mips/r4000.cpp @@ -20,7 +20,6 @@ * - it's very very very slow * * TODO - * - find a better way to deal with software interrupts * - enforce mode checks for cp1 * - cache instructions * - check/improve instruction timing @@ -257,18 +256,18 @@ std::unique_ptr r4000_base_device::create_disassembler() void r4000_base_device::execute_run() { - // check interrupts - if ((CAUSE & SR & CAUSE_IP) && (SR & SR_IE) && !(SR & (SR_EXL | SR_ERL))) - cpu_exception(EXCEPTION_INT); - - while (m_icount > 0) + while (m_icount-- > 0) { debugger_instruction_hook(m_pc); fetch(m_pc, [this](u32 const op) { - cpu_execute(op); + // check interrupts + if ((CAUSE & SR & CAUSE_IP) && (SR & SR_IE) && !(SR & (SR_EXL | SR_ERL))) + cpu_exception(EXCEPTION_INT); + else + cpu_execute(op); // zero register zero m_r[0] = 0; @@ -300,8 +299,6 @@ void r4000_base_device::execute_run() m_pc += 8; break; } - - m_icount--; } } @@ -1408,19 +1405,11 @@ void r4000_base_device::cp0_set(unsigned const reg, u64 const data) case CP0_Status: m_cp0[CP0_Status] = u32(data) & ~u32(0x01a80000); - // FIXME: software interrupt check - if (CAUSE & SR & SR_IMSW) - m_icount = 0; - if (data & SR_RE) fatalerror("unimplemented reverse endian mode enabled (%s)\n", machine().describe_context().c_str()); break; case CP0_Cause: m_cp0[CP0_Cause] = (m_cp0[CP0_Cause] & ~CAUSE_IPSW) | (data & CAUSE_IPSW); - - // FIXME: software interrupt check - if (CAUSE & SR & SR_IMSW) - m_icount = 0; break; case CP0_EPC: m_cp0[CP0_EPC] = data;