From d8a897a6db31a69d2f177a792972f6936f8c62c8 Mon Sep 17 00:00:00 2001 From: kub Date: Sat, 3 Jun 2023 07:49:17 +0000 Subject: [PATCH] 32x, improve poll detection --- pico/32x/32x.c | 22 +++++++++++----------- pico/32x/memory.c | 46 ++++++++++++++++++++++++++-------------------- pico/32x/sh2soc.c | 8 ++++---- pico/pico_int.h | 4 ++-- 4 files changed, 43 insertions(+), 37 deletions(-) diff --git a/pico/32x/32x.c b/pico/32x/32x.c index b630904e..8b91c7b4 100644 --- a/pico/32x/32x.c +++ b/pico/32x/32x.c @@ -54,14 +54,14 @@ void p32x_update_irls(SH2 *active_sh2, unsigned int m68k_cycles) mrun = sh2_irl_irq(&msh2, mlvl, msh2.state & SH2_STATE_RUN); if (mrun) { - p32x_sh2_poll_event(&msh2, SH2_IDLE_STATES & ~SH2_STATE_SLEEP, m68k_cycles); + p32x_sh2_poll_event(msh2.poll_addr, &msh2, SH2_IDLE_STATES & ~SH2_STATE_SLEEP, m68k_cycles); if (msh2.state & SH2_STATE_RUN) sh2_end_run(&msh2, 0); } srun = sh2_irl_irq(&ssh2, slvl, ssh2.state & SH2_STATE_RUN); if (srun) { - p32x_sh2_poll_event(&ssh2, SH2_IDLE_STATES & ~SH2_STATE_SLEEP, m68k_cycles); + p32x_sh2_poll_event(ssh2.poll_addr, &ssh2, SH2_IDLE_STATES & ~SH2_STATE_SLEEP, m68k_cycles); if (ssh2.state & SH2_STATE_RUN) sh2_end_run(&ssh2, 0); } @@ -207,8 +207,8 @@ void PicoReset32x(void) { if (PicoIn.AHW & PAHW_32X) { p32x_trigger_irq(NULL, SekCyclesDone(), P32XI_VRES); - p32x_sh2_poll_event(&msh2, SH2_IDLE_STATES, SekCyclesDone()); - p32x_sh2_poll_event(&ssh2, SH2_IDLE_STATES, SekCyclesDone()); + p32x_sh2_poll_event(msh2.poll_addr, &msh2, SH2_IDLE_STATES, SekCyclesDone()); + p32x_sh2_poll_event(ssh2.poll_addr, &ssh2, SH2_IDLE_STATES, SekCyclesDone()); p32x_pwm_ctl_changed(); p32x_timers_recalc(); Pico32x.vdp_regs[0] &= ~P32XV_Mx; // 32X graphics disabled @@ -256,8 +256,8 @@ static void p32x_start_blank(void) } p32x_trigger_irq(NULL, Pico.t.m68c_aim, P32XI_VINT); - p32x_sh2_poll_event(&msh2, SH2_STATE_VPOLL, Pico.t.m68c_aim); - p32x_sh2_poll_event(&ssh2, SH2_STATE_VPOLL, Pico.t.m68c_aim); + p32x_sh2_poll_event(msh2.poll_addr, &msh2, SH2_STATE_VPOLL, Pico.t.m68c_aim); + p32x_sh2_poll_event(ssh2.poll_addr, &ssh2, SH2_STATE_VPOLL, Pico.t.m68c_aim); } static void p32x_end_blank(void) @@ -267,10 +267,10 @@ static void p32x_end_blank(void) if ((Pico32x.vdp_regs[0] & P32XV_Mx) != 0) // no forced blanking Pico32x.vdp_regs[0x0a/2] &= ~P32XV_PEN; // no palette access if (!(Pico32x.sh2_regs[0] & 0x80)) - p32x_schedule_hint(NULL, SekCyclesDone()); + p32x_schedule_hint(NULL, Pico.t.m68c_aim); - p32x_sh2_poll_event(&msh2, SH2_STATE_VPOLL, Pico.t.m68c_aim); - p32x_sh2_poll_event(&ssh2, SH2_STATE_VPOLL, Pico.t.m68c_aim); + p32x_sh2_poll_event(msh2.poll_addr, &msh2, SH2_STATE_VPOLL, Pico.t.m68c_aim); + p32x_sh2_poll_event(ssh2.poll_addr, &ssh2, SH2_STATE_VPOLL, Pico.t.m68c_aim); } void p32x_schedule_hint(SH2 *sh2, unsigned int m68k_cycles) @@ -293,8 +293,8 @@ void p32x_schedule_hint(SH2 *sh2, unsigned int m68k_cycles) static void fillend_event(unsigned int now) { Pico32x.vdp_regs[0x0a/2] &= ~P32XV_nFEN; - p32x_sh2_poll_event(&msh2, SH2_STATE_VPOLL, now); - p32x_sh2_poll_event(&ssh2, SH2_STATE_VPOLL, now); + p32x_sh2_poll_event(msh2.poll_addr, &msh2, SH2_STATE_VPOLL, now); + p32x_sh2_poll_event(ssh2.poll_addr, &ssh2, SH2_STATE_VPOLL, now); } static void hint_event(unsigned int now) diff --git a/pico/32x/memory.c b/pico/32x/memory.c index 21381c96..a8d2e60b 100644 --- a/pico/32x/memory.c +++ b/pico/32x/memory.c @@ -70,7 +70,7 @@ static int m68k_poll_detect(u32 a, u32 cycles, u32 flags) { int ret = 0; // support polling on 2 addresses - seen in Wolfenstein - int match = (a - m68k_poll.addr1 <= 2 || a - m68k_poll.addr2 <= 2); + int match = (a - m68k_poll.addr1 <= 3 || a - m68k_poll.addr2 <= 3); if (match && cycles - m68k_poll.cycles <= 64 && !SekNotPolling) { @@ -91,7 +91,7 @@ static int m68k_poll_detect(u32 a, u32 cycles, u32 flags) m68k_poll.cnt = 0; if (!match) { m68k_poll.addr2 = m68k_poll.addr1; - m68k_poll.addr1 = a; + m68k_poll.addr1 = a & ~1; } SekNotPolling = 0; } @@ -100,15 +100,19 @@ static int m68k_poll_detect(u32 a, u32 cycles, u32 flags) return ret; } -void p32x_m68k_poll_event(u32 flags) +void p32x_m68k_poll_event(u32 a, u32 flags) { - if (Pico32x.emu_flags & flags) { + int match = (a - m68k_poll.addr1 <= 3 || a - m68k_poll.addr2 <= 3); + + if ((Pico32x.emu_flags & flags) && match) { elprintf(EL_32X, "m68k poll %02x -> %02x", Pico32x.emu_flags, Pico32x.emu_flags & ~flags); Pico32x.emu_flags &= ~flags; SekSetStop(0); } - m68k_poll.addr1 = m68k_poll.addr2 = m68k_poll.cnt = 0; + + if (!(Pico32x.emu_flags & (P32XF_68KCPOLL|P32XF_68KVPOLL))) + m68k_poll.addr1 = m68k_poll.addr2 = m68k_poll.cnt = 0; } void NOINLINE p32x_sh2_poll_detect(u32 a, SH2 *sh2, u32 flags, int maxcnt) @@ -116,10 +120,11 @@ void NOINLINE p32x_sh2_poll_detect(u32 a, SH2 *sh2, u32 flags, int maxcnt) u32 cycles_done = sh2_cycles_done_t(sh2); u32 cycles_diff = cycles_done - sh2->poll_cycles; + a &= ~0x20000000; // reading 2 consecutive 16bit values is probably a 32bit access. detect this // by checking address (max 2 bytes away) and cycles (max 2 cycles later). // no polling if more than 20 cycles have passed since last detect call. - if (a - sh2->poll_addr <= 2 && CYCLES_GE(20, cycles_diff)) { + if (a - sh2->poll_addr <= 3 && CYCLES_GE(20, cycles_diff)) { if (!sh2_not_polling(sh2) && CYCLES_GT(cycles_diff, 2) && ++sh2->poll_cnt >= maxcnt) { if (!(sh2->state & flags)) @@ -142,15 +147,16 @@ void NOINLINE p32x_sh2_poll_detect(u32 a, SH2 *sh2, u32 flags, int maxcnt) } else if (!(sh2->state & (SH2_STATE_CPOLL|SH2_STATE_VPOLL|SH2_STATE_RPOLL))) { sh2->poll_cnt = 0; - sh2->poll_addr = a; + sh2->poll_addr = a & ~1; } sh2->poll_cycles = cycles_done; sh2_set_polling(sh2); } -void NOINLINE p32x_sh2_poll_event(SH2 *sh2, u32 flags, u32 m68k_cycles) +void NOINLINE p32x_sh2_poll_event(u32 a, SH2 *sh2, u32 flags, u32 m68k_cycles) { - if (sh2->state & flags) { + a &= ~0x20000000; + if ((sh2->state & flags) && a - sh2->poll_addr <= 3) { elprintf_sh2(sh2, EL_32X, "state: %02x->%02x", sh2->state, sh2->state & ~flags); @@ -518,8 +524,8 @@ static void p32x_reg_write8(u32 a, u32 d) if (REG8IN16(r, a) != (u8)d) { REG8IN16(r, a) = d; - p32x_sh2_poll_event(&sh2s[0], SH2_STATE_CPOLL, cycles); - p32x_sh2_poll_event(&sh2s[1], SH2_STATE_CPOLL, cycles); + p32x_sh2_poll_event(a, &sh2s[0], SH2_STATE_CPOLL, cycles); + p32x_sh2_poll_event(a, &sh2s[1], SH2_STATE_CPOLL, cycles); sh2_poll_write(a & ~1, r[a / 2], cycles, NULL); } } @@ -616,8 +622,8 @@ static void p32x_reg_write16(u32 a, u32 d) if (r[a / 2] != (u16)d) { r[a / 2] = d; - p32x_sh2_poll_event(&sh2s[0], SH2_STATE_CPOLL, cycles); - p32x_sh2_poll_event(&sh2s[1], SH2_STATE_CPOLL, cycles); + p32x_sh2_poll_event(a, &sh2s[0], SH2_STATE_CPOLL, cycles); + p32x_sh2_poll_event(a, &sh2s[1], SH2_STATE_CPOLL, cycles); sh2_poll_write(a, (u16)d, cycles, NULL); } } @@ -772,7 +778,7 @@ static u32 p32x_sh2reg_read16(u32 a, SH2 *sh2) case 0x2a/2: case 0x2c/2: case 0x2e/2: - p32x_sh2_poll_detect(a, sh2, SH2_STATE_CPOLL, 5); + p32x_sh2_poll_detect(a, sh2, SH2_STATE_CPOLL, 9); cycles = sh2_cycles_done_m68k(sh2); sh2s_sync_on_read(sh2, cycles); return sh2_poll_read(a, r[a / 2], cycles, sh2); @@ -828,7 +834,7 @@ static void p32x_sh2reg_write8(u32 a, u32 d, SH2 *sh2) if (Pico32x.sh2_regs[4 / 2] != (u8)d) { unsigned int cycles = sh2_cycles_done_m68k(sh2); Pico32x.sh2_regs[4 / 2] = d; - p32x_sh2_poll_event(sh2->other_sh2, SH2_STATE_CPOLL, cycles); + p32x_sh2_poll_event(a, sh2->other_sh2, SH2_STATE_CPOLL, cycles); if (p32x_sh2_ready(sh2->other_sh2, cycles+8)) sh2_end_run(sh2, 4); sh2_poll_write(a & ~1, d, cycles, sh2); @@ -854,8 +860,8 @@ static void p32x_sh2reg_write8(u32 a, u32 d, SH2 *sh2) unsigned int cycles = sh2_cycles_done_m68k(sh2); REG8IN16(r, a) = d; - p32x_m68k_poll_event(P32XF_68KCPOLL); - p32x_sh2_poll_event(sh2->other_sh2, SH2_STATE_CPOLL, cycles); + p32x_m68k_poll_event(a, P32XF_68KCPOLL); + p32x_sh2_poll_event(a, sh2->other_sh2, SH2_STATE_CPOLL, cycles); if (p32x_sh2_ready(sh2->other_sh2, cycles+8)) sh2_end_run(sh2, 0); sh2_poll_write(a & ~1, r[a / 2], cycles, sh2); @@ -947,8 +953,8 @@ static void p32x_sh2reg_write16(u32 a, u32 d, SH2 *sh2) unsigned int cycles = sh2_cycles_done_m68k(sh2); Pico32x.regs[a / 2] = d; - p32x_m68k_poll_event(P32XF_68KCPOLL); - p32x_sh2_poll_event(sh2->other_sh2, SH2_STATE_CPOLL, cycles); + p32x_m68k_poll_event(a, P32XF_68KCPOLL); + p32x_sh2_poll_event(a, sh2->other_sh2, SH2_STATE_CPOLL, cycles); if (p32x_sh2_ready(sh2->other_sh2, cycles+8)) sh2_end_run(sh2, 0); sh2_poll_write(a, d, cycles, sh2); @@ -1579,7 +1585,7 @@ static void sh2_sdram_poll(u32 a, u32 d, SH2 *sh2) DRC_SAVE_SR(sh2); cycles = sh2_cycles_done_m68k(sh2); sh2_poll_write(a, d, cycles, sh2); - p32x_sh2_poll_event(sh2->other_sh2, SH2_STATE_RPOLL, cycles); + p32x_sh2_poll_event(a, sh2->other_sh2, SH2_STATE_RPOLL, cycles); if (p32x_sh2_ready(sh2->other_sh2, cycles+8)) sh2_end_run(sh2, 0); DRC_RESTORE_SR(sh2); diff --git a/pico/32x/sh2soc.c b/pico/32x/sh2soc.c index 852f3942..fb1cf1e9 100644 --- a/pico/32x/sh2soc.c +++ b/pico/32x/sh2soc.c @@ -76,7 +76,7 @@ static void dmac_transfer_complete(SH2 *sh2, struct dma_chan *chan) { chan->chcr |= DMA_TE; // DMA has ended normally - p32x_sh2_poll_event(sh2, SH2_STATE_SLEEP, SekCyclesDone()); + p32x_sh2_poll_event(sh2->poll_addr, sh2, SH2_STATE_SLEEP, SekCyclesDone()); if (chan->chcr & DMA_IE) dmac_te_irq(sh2, chan); } @@ -390,7 +390,7 @@ void REGPARM(3) sh2_peripheral_write8(u32 a, u32 d, SH2 *sh2) break; default: if ((a & 0x1c0) == 0x140) - p32x_sh2_poll_event(sh2, SH2_STATE_CPOLL, SekCyclesDone()); + p32x_sh2_poll_event(a, sh2, SH2_STATE_CPOLL, SekCyclesDone()); } DRC_RESTORE_SR(sh2); } @@ -416,7 +416,7 @@ void REGPARM(3) sh2_peripheral_write16(u32 a, u32 d, SH2 *sh2) } else { r[MEM_BE2(a / 2)] = d; if ((a & 0x1c0) == 0x140) - p32x_sh2_poll_event(sh2, SH2_STATE_CPOLL, SekCyclesDone()); + p32x_sh2_poll_event(a, sh2, SH2_STATE_CPOLL, SekCyclesDone()); } DRC_RESTORE_SR(sh2); } @@ -484,7 +484,7 @@ void REGPARM(3) sh2_peripheral_write32(u32 a, u32 d, SH2 *sh2) break; default: if ((a & 0x1c0) == 0x140) - p32x_sh2_poll_event(sh2, SH2_STATE_CPOLL, SekCyclesDone()); + p32x_sh2_poll_event(a, sh2, SH2_STATE_CPOLL, SekCyclesDone()); } DRC_RESTORE_SR(sh2); diff --git a/pico/pico_int.h b/pico/pico_int.h index ad018fa9..7a697ed3 100644 --- a/pico/pico_int.h +++ b/pico/pico_int.h @@ -1020,14 +1020,14 @@ void PicoMemSetup32x(void); void Pico32xSwapDRAM(int b); void Pico32xMemStateLoaded(void); void p32x_update_banks(void); -void p32x_m68k_poll_event(u32 flags); +void p32x_m68k_poll_event(u32 a, u32 flags); u32 REGPARM(3) p32x_sh2_poll_memory8(u32 a, u32 d, SH2 *sh2); u32 REGPARM(3) p32x_sh2_poll_memory16(u32 a, u32 d, SH2 *sh2); u32 REGPARM(3) p32x_sh2_poll_memory32(u32 a, u32 d, SH2 *sh2); void *p32x_sh2_get_mem_ptr(u32 a, u32 *mask, SH2 *sh2); int p32x_sh2_mem_is_rom(u32 a, SH2 *sh2); void p32x_sh2_poll_detect(u32 a, SH2 *sh2, u32 flags, int maxcnt); -void p32x_sh2_poll_event(SH2 *sh2, u32 flags, u32 m68k_cycles); +void p32x_sh2_poll_event(u32 a, SH2 *sh2, u32 flags, u32 m68k_cycles); int p32x_sh2_memcpy(u32 dst, u32 src, int count, int size, SH2 *sh2); // 32x/draw.c -- 2.39.5