From f0f23e29a17009df41d67d97e8d41d616d423a74 Mon Sep 17 00:00:00 2001 From: Patrick Mackinlay Date: Wed, 3 Oct 2018 19:03:04 +0700 Subject: [PATCH] mips3: exception handling fixes (nw) * nested exceptions shouldn't overwrite the EPC * nested tlb exceptions go to the general exception vector * remove breakpoint for tlb exceptions and branch to proper vector --- src/devices/cpu/mips/mips3.cpp | 44 +++++++++++++++------------------- 1 file changed, 19 insertions(+), 25 deletions(-) diff --git a/src/devices/cpu/mips/mips3.cpp b/src/devices/cpu/mips/mips3.cpp index 039d4259e02..6989e262492 100644 --- a/src/devices/cpu/mips/mips3.cpp +++ b/src/devices/cpu/mips/mips3.cpp @@ -288,7 +288,9 @@ void mips3_device::generate_exception(int exception, int backup) /* translate our fake fill exceptions into real exceptions */ if (exception == EXCEPTION_TLBLOAD_FILL || exception == EXCEPTION_TLBSTORE_FILL) { - offset = 0; + /* don't use the tlb exception offset if within another exception */ + if (!(SR & SR_EXL)) + offset = 0; exception = (exception - EXCEPTION_TLBLOAD_FILL) + EXCEPTION_TLBLOAD; } else if (exception == EXCEPTION_INTERRUPT && m_flavor == MIPS3_TYPE_R5900) @@ -296,9 +298,6 @@ void mips3_device::generate_exception(int exception, int backup) offset = 0x200; } - /* set the exception PC */ - m_core->cpr[0][COP0_EPC] = m_core->pc; - /* put the cause in the low 8 bits and clear the branch delay flag */ CAUSE = (CAUSE & ~0x800000ff) | (exception << 2); @@ -308,31 +307,26 @@ void mips3_device::generate_exception(int exception, int backup) CAUSE |= m_badcop_value << 28; } - /* if we were in a branch delay slot, adjust */ - if ((m_nextpc != ~0) || (m_delayslot)) + /* check if exception within another exception */ + if (!(SR & SR_EXL)) { - m_delayslot = false; - m_nextpc = ~0; - m_core->cpr[0][COP0_EPC] -= 4; - CAUSE |= 0x80000000; - } + /* if we were in a branch delay slot, adjust */ + if ((m_nextpc != ~0) || (m_delayslot)) + { + m_delayslot = false; + m_nextpc = ~0; + m_core->cpr[0][COP0_EPC] = m_core->pc - 4; + CAUSE |= 0x80000000; + } + else + m_core->cpr[0][COP0_EPC] = m_core->pc; - /* set the exception level */ - SR |= SR_EXL; + /* set the exception level */ + SR |= SR_EXL; + } /* based on the BEV bit, we either go to ROM or RAM */ - m_core->pc = (SR & SR_BEV) ? 0xbfc00200 : 0x80000000; - - /* most exceptions go to offset 0x180, except for TLB stuff */ - if (exception >= EXCEPTION_TLBMOD && exception <= EXCEPTION_TLBSTORE) - { - fprintf(stderr, "TLB miss @ %08X\n", (uint32_t)m_core->cpr[0][COP0_BadVAddr]); - machine().debug_break(); - } - else - { - m_core->pc += offset; - } + m_core->pc = ((SR & SR_BEV) ? 0xbfc00200 : 0x80000000) + offset; /* useful for tracking interrupts