From 46ca03de7a834044f243cef6904a4ac8615314e8 Mon Sep 17 00:00:00 2001 From: Toni Wilen Date: Mon, 6 Jun 2022 18:44:50 +0300 Subject: [PATCH] STOP cycle-accuracy fix, stop state/wakeup added to DMA debugger. --- debug.cpp | 9 ++++++- gencpu.cpp | 18 +++++++++++--- include/debug.h | 3 +++ include/newcpu.h | 2 ++ newcpu.cpp | 61 +++++++++++++++++++++++++++++++++++++++++------- 5 files changed, 81 insertions(+), 12 deletions(-) diff --git a/debug.cpp b/debug.cpp index a87a7915..ab61b718 100644 --- a/debug.cpp +++ b/debug.cpp @@ -2221,6 +2221,10 @@ static bool get_record_dma_info(struct dma_rec *dr, int hpos, int vpos, evt_t cy } if (dr->evt & DMA_EVENT_CPUIRQ) l3[cl2++] = 'I'; + if (dr->evt & DMA_EVENT_CPUSTOP) + l3[cl2++] = '|'; + if (dr->evt & DMA_EVENT_CPUSTOPIPL) + l3[cl2++] = '+'; if (dr->evt & DMA_EVENT_INTREQ) l3[cl2++] = 'i'; if (dr->evt & DMA_EVENT_SPECIAL) @@ -6246,7 +6250,7 @@ static bool debug_line (TCHAR *input) lastframes = history[temp].fp; lastvpos = history[temp].vpos; lasthpos = history[temp].hpos; - console_out_f(_T("%2d "), regs.intmask ? regs.intmask : (regs.s ? -1 : 0)); + console_out_f(_T("%2d %03d/%03d "), regs.intmask ? regs.intmask : (regs.s ? -1 : 0), lasthpos, lastvpos); m68k_disasm (regs.pc, NULL, 0xffffffff, 1); } if (addr && regs.pc == addr) @@ -6544,6 +6548,9 @@ static void debug_1 (void) static void addhistory (void) { + if (regs.stopped) + return; + uae_u32 pc = currprefs.cpu_model >= 68020 && currprefs.cpu_compatible ? regs.instruction_pc : m68k_getpc(); history[lasthist].regs = regs; history[lasthist].regs.pc = pc; diff --git a/gencpu.cpp b/gencpu.cpp index 78e9fde8..3d4c04fb 100644 --- a/gencpu.cpp +++ b/gencpu.cpp @@ -6656,6 +6656,7 @@ static void gen_opcode (unsigned int opcode) trace_t0_68040_only(); break; case i_STOP: + { if (using_prefetch) { out("uae_u16 sr = regs.irc;\n"); m68k_pc_offset += 2; @@ -6675,11 +6676,21 @@ static void gen_opcode (unsigned int opcode) write_return_cycles(0); out("}\n"); } + bool accstop = (cpu_level == 0 || cpu_level == 1) && (using_ce || using_prefetch); + if (accstop) { + // if interrupt is pending before SR change: STOP finishes in 4 cycles + out("bool irq = stop_interrupt_pending();\n"); + } out("regs.sr = sr;\n"); + check_ipl_always(); makefromsr(); - out("m68k_setstopped();\n"); - if ((cpu_level == 0 || cpu_level == 1) && (using_ce || using_prefetch)) { - out("%s(4);\n", do_cycles); + if (accstop) { + out("do_cycles_stop(4);\n"); + out("if (!irq) {\n"); + out("m68k_setstopped();\n"); + out("}\n"); + } else { + out("m68k_setstopped();\n"); } sync_m68k_pc(); // STOP does not prefetch anything @@ -6687,6 +6698,7 @@ static void gen_opcode (unsigned int opcode) next_cpu_level = cpu_level - 1; next_level_000(); break; + } case i_LPSTOP: /* 68060 */ out("uae_u16 sw = %s;\n", gen_nextiword(0)); out("if (sw != 0x01c0) {\n"); diff --git a/include/debug.h b/include/debug.h index 0669af0b..1acbda9c 100644 --- a/include/debug.h +++ b/include/debug.h @@ -264,6 +264,9 @@ extern struct dma_rec *last_dma_rec; #define DMA_EVENT_HSE 0x04000000 #define DMA_EVENT_CIAA_IRQ 0x08000000 #define DMA_EVENT_CIAB_IRQ 0x10000000 +#define DMA_EVENT_CPUSTOP 0x20000000 +#define DMA_EVENT_CPUSTOPIPL 0x40000000 + #define DMARECORD_REFRESH 1 #define DMARECORD_CPU 2 diff --git a/include/newcpu.h b/include/newcpu.h index 63746225..6a6c59a0 100644 --- a/include/newcpu.h +++ b/include/newcpu.h @@ -661,6 +661,7 @@ extern void REGPARAM3 x_put_bitfield (uae_u32 dst, uae_u32 bdata[2], uae_u32 val extern void m68k_setstopped(void); extern void m68k_resumestopped(void); extern void m68k_cancel_idle(void); +extern void do_cycles_stop(int); extern uae_u32 REGPARAM3 get_disp_ea_020 (uae_u32 base, int idx) REGPARAM; extern uae_u32 REGPARAM3 get_bitfield (uae_u32 src, uae_u32 bdata[2], uae_s32 offset, int width) REGPARAM; @@ -690,6 +691,7 @@ extern void IRQ_forced(int, int); extern void prepare_interrupt (uae_u32); extern void doint (void); extern void intlev_load(void); +extern bool stop_interrupt_pending(void); extern void dump_counts (void); extern int m68k_move2c (int, uae_u32 *); extern int m68k_movec2 (int, uae_u32 *); diff --git a/newcpu.cpp b/newcpu.cpp index 90d14a7f..291ea226 100644 --- a/newcpu.cpp +++ b/newcpu.cpp @@ -60,7 +60,7 @@ bool check_prefs_changed_comp (bool checkonly) { return false; } #endif /* For faster JIT cycles handling */ -uae_s32 pissoff = 0; +int pissoff = 0; /* Opcode of faulting instruction */ static uae_u32 last_op_for_exception_3; @@ -4355,6 +4355,20 @@ void intlev_load(void) doint(); } +bool stop_interrupt_pending(void) +{ + if (m68k_interrupt_delay) { + int il = intlev(); + regs.ipl_pin = il; + if (regs.ipl_pin > regs.intmask || regs.ipl_pin == 7) { + if (regs.spcflags & SPCFLAG_INT) { + return true; + } + } + } + return false; +} + void doint(void) { #ifdef WITH_PPC @@ -4389,6 +4403,14 @@ static void check_debugger(void) } } +static void debug_cpu_stop(void) +{ + record_dma_event(DMA_EVENT_CPUSTOP, current_hpos(), vpos); + if (time_for_interrupt()) { + record_dma_event(DMA_EVENT_CPUSTOPIPL, current_hpos(), vpos); + } +} + static int do_specialties (int cycles) { bool stopped_debug = false; @@ -4493,7 +4515,6 @@ static int do_specialties (int cycles) Exception (3); } - bool first = true; while (regs.spcflags & SPCFLAG_STOP) { if (regs.s == 0 && currprefs.cpu_model <= 68010) { @@ -4527,9 +4548,13 @@ static int do_specialties (int cycles) if (m68k_interrupt_delay) { unset_special(SPCFLAG_INT); if (time_for_interrupt()) { - if (!first) { - // extra loop because even after higher ipl detection, - // stop needs to do one more loop before it exits. + // extra STOP "round" + if (debug_dma) { + debug_cpu_stop(); + x_do_cycles(2 * cpucycleunit); + debug_cpu_stop(); + x_do_cycles(2 * cpucycleunit); + } else { x_do_cycles(4 * cpucycleunit); } do_interrupt(regs.ipl); @@ -4556,12 +4581,20 @@ static int do_specialties (int cycles) } } - first = false; ipl_fetch(); - x_do_cycles(4 * cpucycleunit); - if (regs.spcflags & SPCFLAG_COPPER) + if (debug_dma) { + debug_cpu_stop(); + x_do_cycles(2 * cpucycleunit); + debug_cpu_stop(); + x_do_cycles(2 * cpucycleunit); + } else { + x_do_cycles(4 * cpucycleunit); + } + + if (regs.spcflags & SPCFLAG_COPPER) { do_copper(); + } if (regs.spcflags & SPCFLAG_MODE_CHANGE) { m68k_resumestopped(); @@ -7637,6 +7670,18 @@ bool cpureset (void) return false; } +void do_cycles_stop(int c) +{ + if (debug_dma) { + while (c >= 2) { + debug_cpu_stop(); + do_cycles_ce000_internal(2); + c -= 2; + } + } else { + do_cycles_ce000_internal(c); + } +} void m68k_setstopped (void) { -- 2.47.3