From: Toni Wilen Date: Sun, 30 Oct 2022 15:56:27 +0000 (+0200) Subject: 68000 IPL fix X-Git-Tag: 41000~94 X-Git-Url: https://git.unchartedbackwaters.co.uk/w/?a=commitdiff_plain;h=5715469411c4482d607cb1848398e5d34d74fc40;p=francis%2Fwinuae.git 68000 IPL fix --- diff --git a/custom.cpp b/custom.cpp index d72ff789..05e47b76 100644 --- a/custom.cpp +++ b/custom.cpp @@ -14890,7 +14890,6 @@ extern int cpu_tracer; static int dma_cycle(uaecptr addr, uae_u32 value, int *mode, int *ipl) { int hpos_next, hpos_old; - int ws = 0; blt_info.nasty_cnt = 1; blt_info.wait_nasty = 0; @@ -14927,10 +14926,7 @@ static int dma_cycle(uaecptr addr, uae_u32 value, int *mode, int *ipl) if (blt_info.nasty_cnt > 0) { blt_info.nasty_cnt++; } - if (!ws) { - *ipl = regs.ipl_pin; - ws = 1; - } + *ipl = regs.ipl_pin; do_cycles(1 * CYCLE_UNIT); /* bus was allocated to dma channel, wait for next cycle.. */ } @@ -14963,7 +14959,7 @@ uae_u32 wait_cpu_cycle_read(uaecptr addr, int mode) { uae_u32 v = 0; int hpos; - int ipl = regs.ipl_pin; + int ipl = regs.ipl[0]; evt_t now = get_cycles(); sync_cycles(); @@ -15031,7 +15027,7 @@ uae_u32 wait_cpu_cycle_read(uaecptr addr, int mode) void wait_cpu_cycle_write(uaecptr addr, int mode, uae_u32 v) { int hpos; - int ipl = regs.ipl_pin; + int ipl = regs.ipl[0]; evt_t now = get_cycles(); sync_cycles(); diff --git a/gencpu.cpp b/gencpu.cpp index 141cfd98..06fbbbbf 100644 --- a/gencpu.cpp +++ b/gencpu.cpp @@ -1390,6 +1390,7 @@ static void fill_prefetch_full_ntx(int beopcode) out("if(t1) opcode |= 0x10000;\n"); } next_level_000(); + set_ipl(); fill_prefetch_1(2); } else { fill_prefetch_1_empty(2); @@ -6799,12 +6800,10 @@ static void gen_opcode (unsigned int opcode) addcycles000(4); out("MakeSR();\nregs.sr &= 0xFF00;\nregs.sr |= src & 0xFF;\n"); makefromsr(); - set_ipl(); } else { // MOVE TO SR check_trace(); addcycles000(4); - set_ipl(); out("regs.sr = src;\n"); makefromsr_t0(); } @@ -7258,6 +7257,7 @@ static void gen_opcode (unsigned int opcode) } else { addop_ce020(curi, 0, 0); // smode must be first in case it is A7. Except if 68040! + set_ipl(); if (cpu_level == 4) { genamode(NULL, Apdi, "7", sz_long, "old", 2, 0, GF_AA | GF_NOEXC3); genamode(NULL, curi->smode, "srcreg", sz_long, "src", 1, 0, GF_AA); @@ -7276,7 +7276,7 @@ static void gen_opcode (unsigned int opcode) write_return_cycles(0); out("}\n"); } - genastore_2("src", Apdi, "7", sz_long, "old", 0, GF_IPLMID); + genastore_2("src", Apdi, "7", sz_long, "old", 0, 0); genastore("m68k_areg(regs, 7)", curi->smode, "srcreg", sz_long, "src"); out("m68k_areg(regs, 7) += offs;\n"); fill_prefetch_next_t(); @@ -7293,8 +7293,9 @@ static void gen_opcode (unsigned int opcode) out("m68k_areg(regs, srcreg) = old;\n"); } else { m68k_pc_offset = 4; + set_ipl(); genamode(curi, curi->smode, "srcreg", curi->size, "src", 1, 0, 0); - genamode(NULL, am_unknown, "src", sz_long, "old", 1, 0, GF_IPLMID); + genamode(NULL, am_unknown, "src", sz_long, "old", 1, 0, 0); out("m68k_areg(regs, 7) = src + 4;\n"); m68k_pc_offset = 2; genastore("old", curi->smode, "srcreg", curi->size, "src"); diff --git a/include/newcpu.h b/include/newcpu.h index 28da2183..e29f0277 100644 --- a/include/newcpu.h +++ b/include/newcpu.h @@ -206,8 +206,8 @@ struct regstruct int halted; int exception; int intmask; - int ipl[2], ipl_pin; - evt_t ipl_pin_change_evt; + int ipl[2], ipl_pin, ipl_pin_p; + evt_t ipl_pin_change_evt, ipl_pin_change_evt_p; evt_t ipl_evt, ipl_evt_pre; int ipl_evt_pre_mode; diff --git a/newcpu.cpp b/newcpu.cpp index 4f4ec968..60d1432a 100644 --- a/newcpu.cpp +++ b/newcpu.cpp @@ -2376,16 +2376,18 @@ static void MakeFromSR_x(int t0trace) SET_ZFLG((regs.sr >> 2) & 1); SET_VFLG((regs.sr >> 1) & 1); SET_CFLG(regs.sr & 1); + if (regs.t1 == ((regs.sr >> 15) & 1) && regs.t0 == ((regs.sr >> 14) & 1) && regs.s == ((regs.sr >> 13) & 1) && regs.m == ((regs.sr >> 12) & 1) && regs.intmask == ((regs.sr >> 8) & 7)) return; + regs.t1 = (regs.sr >> 15) & 1; regs.t0 = (regs.sr >> 14) & 1; regs.s = (regs.sr >> 13) & 1; - regs.m = (regs.sr >> 12) & 1; + regs.m = (regs.sr >> 12) & 1; if (regs.intmask != ((regs.sr >> 8) & 7)) { int newimask = (regs.sr >> 8) & 7; @@ -2394,11 +2396,12 @@ static void MakeFromSR_x(int t0trace) if (t0trace < 0 && regs.ipl[0] <= regs.intmask && regs.ipl[0] > newimask && regs.ipl[0] < 7) { regs.ipl[0] = 0; } + } else { + if (regs.ipl[0] <= regs.intmask && regs.ipl_pin > newimask) { + set_special(SPCFLAG_INT); + } } regs.intmask = newimask; - if (regs.ipl_pin > regs.intmask) { - set_special(SPCFLAG_INT); - } } if (currprefs.cpu_model >= 68020) { @@ -2865,11 +2868,8 @@ kludge_me_do: return; } regs.ird = regs.ir; - if (m68k_accurate_ipl && interrupt) { - ipl_fetch_now(); - } x_do_cycles(2 * cpucycleunit); - if (m68k_accurate_ipl && !interrupt) { + if (m68k_accurate_ipl) { ipl_fetch_next(); } regs.irc = x_get_word(m68k_getpc() + 2); // prefetch 2 @@ -4416,13 +4416,14 @@ static int time_for_interrupt(void) // ipl check mid next memory cycle void ipl_fetch_next_pre(void) { + ipl_fetch_next(); regs.ipl_evt_pre = get_cycles(); regs.ipl_evt_pre_mode = 1; } void ipl_fetch_now_pre(void) { - regs.ipl[1] = regs.ipl_pin; + ipl_fetch_now(); regs.ipl_evt_pre = get_cycles(); regs.ipl_evt_pre_mode = 0; } @@ -4431,6 +4432,7 @@ void ipl_fetch_now_pre(void) void ipl_fetch_now(void) { evt_t c = get_cycles(); + regs.ipl_evt = c; regs.ipl[0] = regs.ipl_pin; regs.ipl[1] = 0; @@ -4442,9 +4444,13 @@ void ipl_fetch_now(void) void ipl_fetch_next(void) { evt_t c = get_cycles(); + if (c - regs.ipl_pin_change_evt >= cpuipldelay4) { regs.ipl[0] = regs.ipl_pin; regs.ipl[1] = 0; + } else if (c - regs.ipl_pin_change_evt_p >= cpuipldelay2) { + regs.ipl[0] = regs.ipl_pin_p; + regs.ipl[1] = 0; } else { regs.ipl[1] = regs.ipl_pin; } @@ -4458,6 +4464,36 @@ void intlev_load(void) doint(); } +static void update_ipl(int ipl) +{ + evt_t c = get_cycles(); + regs.ipl_pin_change_evt_p = regs.ipl_pin_change_evt; + regs.ipl_pin_p = regs.ipl_pin; + regs.ipl_pin_change_evt = c; + regs.ipl_pin = ipl; + if (m68k_accurate_ipl) { + // check if 68000/010 interrupt was detected mid memory access, + // 2 cycles from start of memory cycle + if (ipl > 0 && c == regs.ipl_evt_pre + cpuipldelay2) { + if (regs.ipl_evt_pre_mode) { + ipl_fetch_next(); + } else { + ipl_fetch_now(); + } + } + } +#ifdef DEBUGGER + if (debug_dma) { + record_dma_ipl(current_hpos(), vpos); + } +#endif +} + +static void doint_delayed(uae_u32 v) +{ + update_ipl(v); +} + void doint(void) { #ifdef WITH_PPC @@ -4466,26 +4502,23 @@ void doint(void) return; } #endif - int il = intlev(); - if (regs.ipl_pin != il) { - regs.ipl_pin = il; - regs.ipl_pin_change_evt = get_cycles(); - if (m68k_accurate_ipl) { - // check if 68000/010 interrupt was detected mid memory access, - // 2 cycles from start of memory cycle - if (il > 0 && get_cycles() == regs.ipl_evt_pre + cpuipldelay2) { - if (regs.ipl_evt_pre_mode) { - ipl_fetch_next(); - } else { - ipl_fetch_now(); - } - } - } -#ifdef DEBUGGER - if (debug_dma) { - record_dma_ipl(current_hpos(), vpos); + int ipl = intlev(); + + if (regs.ipl_pin != ipl) { + + // Paula does low to high IPL changes about 1.5 CPU clocks later than high to low. + // -> CPU detects IPL change 1 CCK later if any IPL pin has high to low transition. + // (In real world IPL is active low and delay is added if 0 to 1 transition) + if (m68k_accurate_ipl && regs.ipl_pin >= 0 && ipl >= 0 && ( + ((regs.ipl_pin & 1) && !(ipl & 1)) || + ((regs.ipl_pin & 2) && !(ipl & 2)) || + ((regs.ipl_pin & 4) && !(ipl & 4)) + )) { + event2_newevent_xx(-1, CYCLE_UNIT, ipl, doint_delayed); + return; } -#endif + + update_ipl(ipl); } if (m68k_interrupt_delay) { if (!m68k_accurate_ipl && regs.ipl_pin > regs.intmask) { @@ -4801,7 +4834,7 @@ static void m68k_run_1 (void) cpu_cycles = adjust_cycles (cpu_cycles); do_cycles(cpu_cycles); regs.instruction_cnt++; - if (r->spcflags || regs.ipl[0]) { + if (r->spcflags || regs.ipl[0] > 0) { if (do_specialties (cpu_cycles)) exit = true; } @@ -4931,7 +4964,7 @@ cont: log_dma_record (); } - if (r->spcflags || regs.ipl[0]) { + if (r->spcflags || regs.ipl[0] > 0) { if (do_specialties (0)) exit = true; } @@ -5997,7 +6030,7 @@ static void m68k_run_2ce (void) regs.instruction_cnt++; cont: - if (r->spcflags || regs.ipl[0]) { + if (r->spcflags || regs.ipl[0] > 0) { if (do_specialties (0)) exit = true; } @@ -6140,7 +6173,7 @@ static void m68k_run_2p (void) x_do_cycles(cpu_cycles); cont: - if (r->spcflags || regs.ipl[0]) { + if (r->spcflags || regs.ipl[0] > 0) { if (do_specialties (cpu_cycles)) exit = true; } @@ -6919,9 +6952,11 @@ uae_u8 *restore_cpu (uae_u8 *src) regs.ipl[0] = restore_u8(); regs.ipl[1] = restore_u8(); regs.ipl_pin = (uae_s32)restore_u8(); + regs.ipl_pin_p = (uae_s32)restore_u8(); regs.ipl_evt = restore_u64(); regs.ipl_evt_pre = restore_u64(); regs.ipl_pin_change_evt = restore_u64(); + regs.ipl_pin_change_evt_p = restore_u64(); } } @@ -7359,9 +7394,11 @@ uae_u8 *save_cpu(size_t *len, uae_u8 *dstptr) save_u8(regs.ipl[0]); save_u8(regs.ipl[1]); save_u8(regs.ipl_pin); + save_u8(regs.ipl_pin_p); save_u64(regs.ipl_evt); save_u64(regs.ipl_evt_pre); save_u64(regs.ipl_pin_change_evt); + save_u64(regs.ipl_pin_change_evt_p); } *len = dst - dstbak; return dstbak;