From 0be6d4eaca09acdb838c0c6ea45c57267c8f4cce Mon Sep 17 00:00:00 2001 From: Toni Wilen Date: Thu, 28 Dec 2023 11:59:31 +0200 Subject: [PATCH] If interrupt level increased during 68040/060 MMU fault handler execution, interrupt's first instruction was "restarted", if both original and exception's instruction were MOVEM, things went horribly wrong. --- cpummu.cpp | 3 ++ include/custom.h | 18 -------- include/newcpu.h | 19 +++++++++ newcpu.cpp | 106 +++++++++++++++++++++++++++-------------------- 4 files changed, 83 insertions(+), 63 deletions(-) diff --git a/cpummu.cpp b/cpummu.cpp index aa1fc95c..4123a5a2 100644 --- a/cpummu.cpp +++ b/cpummu.cpp @@ -1563,6 +1563,9 @@ void m68k_do_rte_mmu040 (uaecptr a7) write_log (_T("MMU restarted MOVEM EA=%08X\n"), mmu040_movem_ea); #endif } + if (currprefs.mmu_model == 68060 || mmu_restart) { + set_special(SPCFLAG_MMURESTART); + } } void m68k_do_rte_mmu060 (uaecptr a7) diff --git a/include/custom.h b/include/custom.h index 16dca1b0..4ba4b806 100644 --- a/include/custom.h +++ b/include/custom.h @@ -85,24 +85,6 @@ STATIC_INLINE int dmaen(unsigned int dmamask) return (dmamask & dmacon) && (dmacon & 0x200); } -#define SPCFLAG_CPUINRESET 2 -#define SPCFLAG_COPPER 4 -#define SPCFLAG_INT 8 -#define SPCFLAG_BRK 16 -#define SPCFLAG_UAEINT 32 -#define SPCFLAG_TRACE 64 -#define SPCFLAG_DOTRACE 128 -#define SPCFLAG_DOINT 256 /* arg, JIT fails without this.. */ -#define SPCFLAG_BLTNASTY 512 -#define SPCFLAG_EXEC 1024 -#define SPCFLAG_ACTION_REPLAY 2048 -#define SPCFLAG_TRAP 4096 /* enforcer-hack */ -#define SPCFLAG_MODE_CHANGE 8192 -#ifdef JIT -#define SPCFLAG_END_COMPILE 16384 -#endif -#define SPCFLAG_CHECK 32768 - extern uae_u16 adkcon; extern unsigned int joy0dir, joy1dir; diff --git a/include/newcpu.h b/include/newcpu.h index d7259166..6eac8ff1 100644 --- a/include/newcpu.h +++ b/include/newcpu.h @@ -321,6 +321,25 @@ extern bool m68k_interrupt_delay; extern void safe_interrupt_set(int, int, bool); +#define SPCFLAG_CPUINRESET 2 +#define SPCFLAG_COPPER 4 +#define SPCFLAG_INT 8 +#define SPCFLAG_BRK 16 +#define SPCFLAG_UAEINT 32 +#define SPCFLAG_TRACE 64 +#define SPCFLAG_DOTRACE 128 +#define SPCFLAG_DOINT 256 /* arg, JIT fails without this.. */ +#define SPCFLAG_BLTNASTY 512 +#define SPCFLAG_EXEC 1024 +#define SPCFLAG_ACTION_REPLAY 2048 +#define SPCFLAG_TRAP 4096 /* enforcer-hack */ +#define SPCFLAG_MODE_CHANGE 8192 +#ifdef JIT +#define SPCFLAG_END_COMPILE 16384 +#endif +#define SPCFLAG_CHECK 32768 +#define SPCFLAG_MMURESTART 65536 + STATIC_INLINE void set_special_exter(uae_u32 x) { atomic_or(®s.spcflags, x); diff --git a/newcpu.cpp b/newcpu.cpp index 3e74ce3f..f803237c 100644 --- a/newcpu.cpp +++ b/newcpu.cpp @@ -4614,11 +4614,12 @@ static void debug_cpu_stop(void) static int do_specialties (int cycles) { uaecptr pc = m68k_getpc(); + uae_atomic spcflags = regs.spcflags; - if (regs.spcflags & SPCFLAG_MODE_CHANGE) + if (spcflags & SPCFLAG_MODE_CHANGE) return 1; - if (regs.spcflags & SPCFLAG_CHECK) { + if (spcflags & SPCFLAG_CHECK) { if (regs.halted) { if (regs.halted == CPU_HALT_ACCELERATOR_CPU_FALLBACK) { return 1; @@ -4632,8 +4633,10 @@ static int do_specialties (int cycles) int vsyncstate = -1; while (vsynccnt > 0 && !quit_program) { x_do_cycles(8 * CYCLE_UNIT); - if (regs.spcflags & SPCFLAG_COPPER) + spcflags = regs.spcflags; + if (spcflags & SPCFLAG_COPPER) { do_copper(); + } if (vsync_counter != vsyncstate) { vsyncstate = vsync_counter; vsynccnt--; @@ -4646,7 +4649,7 @@ static int do_specialties (int cycles) #ifdef ACTION_REPLAY #ifdef ACTION_REPLAY_HRTMON - if ((regs.spcflags & SPCFLAG_ACTION_REPLAY) && hrtmon_flag != ACTION_REPLAY_INACTIVE) { + if ((spcflags & SPCFLAG_ACTION_REPLAY) && hrtmon_flag != ACTION_REPLAY_INACTIVE) { int isinhrt = pc >= hrtmem_start && pc < hrtmem_start + hrtmem_size; /* exit from HRTMon? */ if (hrtmon_flag == ACTION_REPLAY_ACTIVE && !isinhrt) @@ -4658,7 +4661,7 @@ static int do_specialties (int cycles) hrtmon_enter(); } #endif - if ((regs.spcflags & SPCFLAG_ACTION_REPLAY) && action_replay_flag != ACTION_REPLAY_INACTIVE) { + if ((spcflags & SPCFLAG_ACTION_REPLAY) && action_replay_flag != ACTION_REPLAY_INACTIVE) { /*if (action_replay_flag == ACTION_REPLAY_ACTIVE && !is_ar_pc_in_rom ())*/ /* write_log (_T("PC:%p\n"), m68k_getpc ());*/ @@ -4677,26 +4680,28 @@ static int do_specialties (int cycles) } #endif - if (regs.spcflags & SPCFLAG_COPPER) + if (spcflags & SPCFLAG_COPPER) { do_copper(); + } #ifdef JIT - if (regs.spcflags & SPCFLAG_END_COMPILE) { + if (spcflags & SPCFLAG_END_COMPILE) { unset_special(SPCFLAG_END_COMPILE); } #endif - while ((regs.spcflags & SPCFLAG_CPUINRESET)) { + while (spcflags & SPCFLAG_CPUINRESET) { x_do_cycles(4 * CYCLE_UNIT); - if (regs.spcflags & SPCFLAG_COPPER) { + spcflags = regs.spcflags; + if (spcflags & SPCFLAG_COPPER) { do_copper(); } - if (!(regs.spcflags & SPCFLAG_CPUINRESET) || (regs.spcflags & SPCFLAG_BRK) || (regs.spcflags & SPCFLAG_MODE_CHANGE)) { + if (!(spcflags & SPCFLAG_CPUINRESET) || (spcflags & SPCFLAG_BRK) || (spcflags & SPCFLAG_MODE_CHANGE)) { break; } } - while ((regs.spcflags & SPCFLAG_BLTNASTY) && dmaen (DMA_BLITTER) && cycles > 0 && ((currprefs.waiting_blits && currprefs.cpu_model >= 68020) || !currprefs.blitter_cycle_exact)) { + while ((spcflags & SPCFLAG_BLTNASTY) && dmaen (DMA_BLITTER) && cycles > 0 && ((currprefs.waiting_blits && currprefs.cpu_model >= 68020) || !currprefs.blitter_cycle_exact)) { int c = blitnasty(); if (c < 0) { break; @@ -4708,7 +4713,8 @@ static int do_specialties (int cycles) c = 4; } x_do_cycles(c * CYCLE_UNIT); - if (regs.spcflags & SPCFLAG_COPPER) + spcflags = regs.spcflags; + if (spcflags & SPCFLAG_COPPER) do_copper(); #ifdef WITH_PPC if (ppc_state) { @@ -4719,43 +4725,51 @@ static int do_specialties (int cycles) #endif } - if (regs.spcflags & SPCFLAG_DOTRACE) - Exception(9); + if (spcflags & SPCFLAG_MMURESTART) { + // can't have interrupt when 040/060 CPU reruns faulted instruction + unset_special(SPCFLAG_MMURESTART); + } else { - if (regs.spcflags & SPCFLAG_TRAP) { - unset_special (SPCFLAG_TRAP); - Exception(3); - } + if (spcflags & SPCFLAG_DOTRACE) { + Exception(9); + } - if (regs.spcflags & SPCFLAG_TRACE) - do_trace(); + if (spcflags & SPCFLAG_TRAP) { + unset_special (SPCFLAG_TRAP); + Exception(3); + } - if (regs.spcflags & SPCFLAG_UAEINT) { - check_uae_int_request(); - unset_special(SPCFLAG_UAEINT); - } + if (spcflags & SPCFLAG_TRACE) { + do_trace(); + } - if (m68k_interrupt_delay) { - int ipl = time_for_interrupt(); - if (ipl) { - unset_special(SPCFLAG_INT); - do_interrupt(ipl); + if (spcflags & SPCFLAG_UAEINT) { + check_uae_int_request(); + unset_special(SPCFLAG_UAEINT); } - } else { - if (regs.spcflags & SPCFLAG_INT) { - int intr = intlev(); - unset_special (SPCFLAG_INT | SPCFLAG_DOINT); - if (intr > 0 && (intr > regs.intmask || intr == 7)) - do_interrupt(intr); + + if (m68k_interrupt_delay) { + int ipl = time_for_interrupt(); + if (ipl) { + unset_special(SPCFLAG_INT); + do_interrupt(ipl); + } + } else { + if (spcflags & SPCFLAG_INT) { + int intr = intlev(); + unset_special (SPCFLAG_INT | SPCFLAG_DOINT); + if (intr > 0 && (intr > regs.intmask || intr == 7)) + do_interrupt(intr); + } } - } - if (regs.spcflags & SPCFLAG_DOINT) { - unset_special(SPCFLAG_DOINT); - set_special(SPCFLAG_INT); + if (spcflags & SPCFLAG_DOINT) { + unset_special(SPCFLAG_DOINT); + set_special(SPCFLAG_INT); + } } - if (regs.spcflags & SPCFLAG_BRK) { + if (spcflags & SPCFLAG_BRK) { unset_special(SPCFLAG_BRK); #ifdef DEBUGGER if (debugging) { @@ -5117,7 +5131,9 @@ static bool m68k_cs_initialized; static int do_specialties_thread(void) { - if (regs.spcflags & SPCFLAG_MODE_CHANGE) + uae_atomic spcflags = regs.spcflags; + + if (spcflags & SPCFLAG_MODE_CHANGE) return 1; #ifdef JIT @@ -5126,20 +5142,20 @@ static int do_specialties_thread(void) } #endif - if (regs.spcflags & SPCFLAG_DOTRACE) + if (spcflags & SPCFLAG_DOTRACE) Exception(9); - if (regs.spcflags & SPCFLAG_TRAP) { + if (spcflags & SPCFLAG_TRAP) { unset_special(SPCFLAG_TRAP); Exception(3); } - if (regs.spcflags & SPCFLAG_TRACE) + if (spcflags & SPCFLAG_TRACE) do_trace(); for (;;) { - if (regs.spcflags & (SPCFLAG_BRK | SPCFLAG_MODE_CHANGE)) { + if (spcflags & (SPCFLAG_BRK | SPCFLAG_MODE_CHANGE)) { return 1; } -- 2.47.3