From: Toni Wilen Date: Sun, 28 Sep 2014 14:43:52 +0000 (+0300) Subject: Interrupt handling updates. X-Git-Tag: 3000~29 X-Git-Url: https://git.unchartedbackwaters.co.uk/w/?a=commitdiff_plain;h=9951541b2cbc4f943070324ff9cb1aca699a56a0;p=francis%2Fwinuae.git Interrupt handling updates. --- diff --git a/cpuboard.cpp b/cpuboard.cpp index c4151b50..b4de8bb1 100644 --- a/cpuboard.cpp +++ b/cpuboard.cpp @@ -151,47 +151,44 @@ static int csmk2_flashaddressing; static bool blizzardmaprom_bank_mapped, blizzardmaprom2_bank_mapped; static bool cpuboard_non_byte_ea; -static int ppc_irq_pending; +static bool ppc_irq_pending; -static void set_ppc_interrupt(int level) +static void set_ppc_interrupt(void) { - if (ppc_irq_pending > level) + if (ppc_irq_pending) return; -#if CPUBOARD_IRQ_LOG > 0 - if (ppc_irq_pending != level) - write_log(_T("PPC interrupt set (%d)\n"), level); -#endif uae_ppc_interrupt(true); - ppc_irq_pending = level; + ppc_irq_pending = true; } static void clear_ppc_interrupt(void) { if (!ppc_irq_pending) return; -#if CPUBOARD_IRQ_LOG > 0 - write_log(_T("PPC interrupt clear\n")); -#endif uae_ppc_interrupt(false); - ppc_irq_pending = 0; + ppc_irq_pending = false; } static void check_ppc_int_lvl(void) { - if (!(io_reg[CSIII_REG_INT] & P5_ENABLE_IPL)) { - uae_u8 ipl = (~io_reg[CSIII_REG_IPL_EMU]) & P5_PPC_IPL_MASK; - if (ipl < 7) { - uae_u8 il = (~io_reg[CSIII_REG_INT_LVL]) & 0x7f; - if (il) { - for (int i = ipl; i < 7; i++) { - if (il & (1 << i)) { - set_ppc_interrupt(i + 1); + bool m68kint = (io_reg[CSIII_REG_INT] & P5_INT_MASTER) != 0; + bool active = (io_reg[CSIII_REG_IPL_EMU] & P5_DISABLE_INT) == 0; + bool iplemu = (io_reg[CSIII_REG_INT] & P5_ENABLE_IPL) == 0; + + if (m68kint && iplemu && active) { + uae_u8 ppcipl = (~io_reg[CSIII_REG_IPL_EMU]) & P5_PPC_IPL_MASK; + if (ppcipl < 7) { + uae_u8 ilvl = (~io_reg[CSIII_REG_INT_LVL]) & 0x7f; + if (ilvl) { + for (int i = ppcipl; i < 7; i++) { + if (ilvl & (1 << i)) { + set_ppc_interrupt(); return; } } } } + clear_ppc_interrupt(); } - clear_ppc_interrupt(); } bool ppc_interrupt(int new_m68k_ipl) @@ -199,24 +196,21 @@ bool ppc_interrupt(int new_m68k_ipl) bool m68kint = (io_reg[CSIII_REG_INT] & P5_INT_MASTER) != 0; bool active = (io_reg[CSIII_REG_IPL_EMU] & P5_DISABLE_INT) == 0; bool iplemu = (io_reg[CSIII_REG_INT] & P5_ENABLE_IPL) == 0; - uae_u8 ppcipl = (~io_reg[CSIII_REG_IPL_EMU]) & P5_PPC_IPL_MASK; if (!active) return false; - if (new_m68k_ipl < 0) - new_m68k_ipl = 0; - - //bool xirq = !(io_reg[CSIII_REG_IRQ] & P5_IRQ_PPC_2) && (io_reg[CSIII_REG_IRQ] & P5_IRQ_PPC_3); - if (!m68kint && iplemu && active) { + uae_u8 ppcipl = (~io_reg[CSIII_REG_IPL_EMU]) & P5_PPC_IPL_MASK; + if (new_m68k_ipl < 0) + new_m68k_ipl = 0; + io_reg[CSIII_REG_IPL_EMU] &= ~P5_M68k_IPL_MASK; + io_reg[CSIII_REG_IPL_EMU] |= (new_m68k_ipl << 3) ^ P5_M68k_IPL_MASK; if (new_m68k_ipl > ppcipl) { - set_ppc_interrupt(new_m68k_ipl); - } else if (!new_m68k_ipl) { + set_ppc_interrupt(); + } else { clear_ppc_interrupt(); } - io_reg[CSIII_REG_IPL_EMU] &= ~P5_M68k_IPL_MASK; - io_reg[CSIII_REG_IPL_EMU] |= (new_m68k_ipl << 3) ^ P5_M68k_IPL_MASK; } return m68kint; @@ -261,7 +255,7 @@ static addrbank blizzardio_bank = { blizzardio_lget, blizzardio_wget, blizzardio_bget, blizzardio_lput, blizzardio_wput, blizzardio_bput, default_xlate, default_check, NULL, NULL, _T("CPUBoard IO"), - blizzardio_wget, blizzardio_bget, ABFLAG_IO | ABFLAG_THREADSAFE + blizzardio_wget, blizzardio_bget, ABFLAG_IO }; DECLARE_MEMORY_FUNCTIONS(blizzardram); @@ -796,10 +790,10 @@ void cpuboard_rethink(void) { if (is_csmk3() || is_blizzardppc()) { if (!(io_reg[CSIII_REG_IRQ] & (P5_IRQ_SCSI_EN | P5_IRQ_SCSI))) { - INTREQ(0x8000 | 0x0008); + INTREQ_0(0x8000 | 0x0008); } if (!(io_reg[CSIII_REG_IRQ] & (P5_IRQ_PPC_1 | P5_IRQ_PPC_2))) { - INTREQ(0x8000 | 0x0008); + INTREQ_0(0x8000 | 0x0008); } check_ppc_int_lvl(); ppc_interrupt(intlev()); @@ -1063,10 +1057,14 @@ static void REGPARAM2 blizzardio_bput(uaecptr addr, uae_u32 v) io_reg[CSIII_REG_RESET] |= oldval & P5_AMIGA_RESET; } } else if (addr == CSIII_REG_IPL_EMU) { -#if CPUBOARD_IRQ_LOG > 0 + // M68K_IPL_MASK is read-only regval &= ~P5_M68k_IPL_MASK; regval |= oldval & P5_M68k_IPL_MASK; + bool active = (regval & P5_DISABLE_INT) == 0; + if (!active) + clear_ppc_interrupt(); io_reg[addr] = regval; +#if CPUBOARD_IRQ_LOG > 0 if ((regval & P5_DISABLE_INT) != (oldval & P5_DISABLE_INT)) write_log(_T("CS: interrupt state: %s\n"), (regval & P5_DISABLE_INT) ? _T("disabled") : _T("enabled")); if ((regval & P5_PPC_IPL_MASK) != (oldval & P5_PPC_IPL_MASK)) diff --git a/custom.cpp b/custom.cpp index fe7d7497..8072c19a 100644 --- a/custom.cpp +++ b/custom.cpp @@ -4631,8 +4631,9 @@ static void rethink_intreq (void) #ifdef NCR9X ncr9x_rethink(); #endif - cpuboard_rethink(); rethink_gayle (); + /* cpuboard_rethink must be last */ + cpuboard_rethink(); } static void send_interrupt_do (uae_u32 v) @@ -8173,6 +8174,7 @@ void dumpcustom (void) { console_out_f (_T("DMACON: %04x INTENA: %04x (%04x) INTREQ: %04x (%04x) VPOS: %x HPOS: %x\n"), DMACONR (current_hpos ()), intena, intena_internal, intreq, intreq_internal, vpos, current_hpos ()); + console_out_f (_T("INT: %04x IPL: %d\n"), intena & intreq, intlev()); console_out_f (_T("COP1LC: %08lx, COP2LC: %08lx COPPTR: %08lx\n"), (unsigned long)cop1lc, (unsigned long)cop2lc, cop_state.ip); console_out_f (_T("DIWSTRT: %04x DIWSTOP: %04x DDFSTRT: %04x DDFSTOP: %04x\n"), (unsigned int)diwstrt, (unsigned int)diwstop, (unsigned int)ddfstrt, (unsigned int)ddfstop); diff --git a/include/uae/ppc.h b/include/uae/ppc.h index 51020983..f05b9872 100644 --- a/include/uae/ppc.h +++ b/include/uae/ppc.h @@ -98,7 +98,7 @@ typedef struct PPCMemoryRegion { void PPCCALL ppc_cpu_version(int *major, int *minor, int *revision); bool PPCCALL ppc_cpu_init(const char *model, uint32_t hid1); bool PPCCALL ppc_cpu_init_pvr(uint32_t pvr); -void PPCCALL ppc_cpu_free(void); +void PPCCALL ppc_cpu_close(void); void PPCCALL ppc_cpu_stop(void); void PPCCALL ppc_cpu_atomic_raise_ext_exception(void); void PPCCALL ppc_cpu_atomic_cancel_ext_exception(void); diff --git a/ncr9x_scsi.cpp b/ncr9x_scsi.cpp index 132a0108..f42435aa 100644 --- a/ncr9x_scsi.cpp +++ b/ncr9x_scsi.cpp @@ -148,7 +148,7 @@ void ncr9x_rethink(void) { for (int i = 0; ncrs[i]; i++) { if (ncrs[i]->boardirq) - INTREQ(0x8000 | 0x0008); + INTREQ_0(0x8000 | 0x0008); } } diff --git a/ncr_scsi.cpp b/ncr_scsi.cpp index 9979264c..d3db8fb0 100644 --- a/ncr_scsi.cpp +++ b/ncr_scsi.cpp @@ -112,7 +112,7 @@ void ncr_rethink(void) { for (int i = 0; ncrs[i]; i++) { if (ncrs[i]->irq) - INTREQ(0x8000 | 0x0008); + INTREQ_0(0x8000 | 0x0008); } if (ncr_cs.irq) cyberstorm_irq(1); diff --git a/newcpu.cpp b/newcpu.cpp index 8d2c6e94..836bd4f2 100644 --- a/newcpu.cpp +++ b/newcpu.cpp @@ -3174,22 +3174,22 @@ void cpu_sleep_millis(int ms) static bool haltloop(void) { +#ifdef WITH_PPC if (regs.halted < 0) { - - int vsynctimeline = vsynctimebase / (maxvpos_display + 1); int rpt_end = 0; int ovpos = vpos; while (regs.halted) { + int vsynctimeline = vsynctimebase / (maxvpos_display + 1); int lines; + int rpt_scanline = read_processor_time(); + int rpt_end = rpt_scanline + vsynctimeline; if (currprefs.ppc_cpu_idle) { int maxlines = 100 - (currprefs.ppc_cpu_idle - 1) * 10; int i; - int rpt_scanline = read_processor_time(); - event_wait = false; for (i = 0; i < ev_max; i++) { if (i == ev_hsync) @@ -3204,6 +3204,7 @@ static bool haltloop(void) if (currprefs.ppc_cpu_idle >= 10 || (i == ev_max && vpos > 0 && vpos < maxvpos - maxlines)) { cpu_sleep_millis(1); } + uae_ppc_execute_check(); lines = (read_processor_time() - rpt_scanline) / vsynctimeline + 1; @@ -3214,28 +3215,45 @@ static bool haltloop(void) } + if (lines > maxvpos / 2) + lines = maxvpos / 2; + while (lines-- >= 0) { ovpos = vpos; while (ovpos == vpos) { - x_do_cycles(4 * CYCLE_UNIT); - if (regs.spcflags) { - if (regs.spcflags & SPCFLAG_COPPER) - do_copper(); - if (regs.spcflags & (SPCFLAG_BRK | SPCFLAG_MODE_CHANGE)) - return true; + x_do_cycles(8 * CYCLE_UNIT); + uae_ppc_execute_check(); + if (regs.spcflags & SPCFLAG_COPPER) + do_copper(); + if (regs.spcflags & (SPCFLAG_BRK | SPCFLAG_MODE_CHANGE)) { + if (regs.spcflags & SPCFLAG_BRK) { + unset_special(SPCFLAG_BRK); +#ifdef DEBUGGER + if (debugging) + debug(); +#endif + } + return true; } } + + // sync chipset with real time + for (;;) { + ppc_interrupt(intlev()); + uae_ppc_execute_check(); + if (event_wait) + break; + int d = read_processor_time() - rpt_end; + if (d < -2 * vsynctimeline || d >= 0) + break; + } } -#ifdef WITH_PPC - if (regs.halted < 0) - uae_ppc_emulate(); -#endif } } else { - +#endif while (regs.halted) { static int prevvpos; if (vpos == 0 && prevvpos) { @@ -3254,7 +3272,9 @@ static bool haltloop(void) return true; } } +#ifdef WITH_PPC } +#endif return false; } @@ -4683,6 +4703,9 @@ void m68k_go (int may_quit) protect_roms (true); } startup = 0; + event_wait = true; + unset_special(SPCFLAG_MODE_CHANGE); + if (regs.halted) { cpu_halt (regs.halted); if (regs.halted < 0) @@ -4714,8 +4737,6 @@ void m68k_go (int may_quit) #if 0 } #endif - event_wait = true; - unset_special(SPCFLAG_MODE_CHANGE); run_func(); } protect_roms (false); diff --git a/ppc/ppc.cpp b/ppc/ppc.cpp index b0c76a0f..a16e34a4 100644 --- a/ppc/ppc.cpp +++ b/ppc/ppc.cpp @@ -112,6 +112,7 @@ static volatile int ppc_cpu_lock_state; static bool ppc_init_done; static bool ppc_cpu_init_done; static int ppc_implementation; +static bool ppc_paused; #define CSPPC_PVR 0x00090204 #define BLIZZPPC_PVR 0x00070101 @@ -121,7 +122,7 @@ static int ppc_implementation; /* Dummy PPC implementation */ -static void PPCCALL dummy_ppc_cpu_free(void) { } +static void PPCCALL dummy_ppc_cpu_close(void) { } static void PPCCALL dummy_ppc_cpu_stop(void) { } static void PPCCALL dummy_ppc_cpu_atomic_raise_ext_exception(void) { } static void PPCCALL dummy_ppc_cpu_atomic_cancel_ext_exception(void) { } @@ -148,7 +149,7 @@ static void PPCCALL dummy_ppc_cpu_pause(int pause) typedef void (PPCCALL *ppc_cpu_version_function)(int *major, int *minor, int *revision); typedef bool (PPCCALL *ppc_cpu_init_function)(const char *model, uint32_t hid1); typedef bool (PPCCALL *ppc_cpu_init_pvr_function)(uint32_t pvr); -typedef void (PPCCALL *ppc_cpu_free_function)(void); +typedef void (PPCCALL *ppc_cpu_close_function)(void); typedef void (PPCCALL *ppc_cpu_stop_function)(void); typedef void (PPCCALL *ppc_cpu_atomic_raise_ext_exception_function)(void); typedef void (PPCCALL *ppc_cpu_atomic_cancel_ext_exception_function)(void); @@ -165,7 +166,7 @@ typedef void (PPCCALL *ppc_cpu_reset_function)(void); /* Function pointers to active PPC implementation */ -static struct { +static struct impl { /* Common */ ppc_cpu_atomic_raise_ext_exception_function atomic_raise_ext_exception; ppc_cpu_atomic_cancel_ext_exception_function atomic_cancel_ext_exception; @@ -174,7 +175,7 @@ static struct { /* PearPC */ ppc_cpu_init_pvr_function init_pvr; ppc_cpu_pause_function pause; - ppc_cpu_free_function free; + ppc_cpu_close_function close; ppc_cpu_stop_function stop; ppc_cpu_set_pc_function set_pc; ppc_cpu_run_single_function run_single; @@ -194,7 +195,7 @@ static void load_dummy_implementation() { write_log(_T("PPC: Loading dummy implementation\n")); memset(&impl, 0, sizeof(impl)); - impl.free = dummy_ppc_cpu_free; + impl.close = dummy_ppc_cpu_close; impl.stop = dummy_ppc_cpu_stop; impl.atomic_raise_ext_exception = dummy_ppc_cpu_atomic_raise_ext_exception; impl.atomic_cancel_ext_exception = dummy_ppc_cpu_atomic_cancel_ext_exception; @@ -295,7 +296,7 @@ static bool load_pearpc_implementation() memset(&impl, 0, sizeof(impl)); impl.init_pvr = ppc_cpu_init; - impl.free = ppc_cpu_free; + impl.close = ppc_cpu_close; impl.stop = ppc_cpu_stop; impl.atomic_raise_ext_exception = ppc_cpu_atomic_raise_ext_exception; impl.atomic_cancel_ext_exception = ppc_cpu_atomic_cancel_ext_exception; @@ -387,6 +388,17 @@ static void map_banks(void) static void set_and_wait_for_state(int state, int unlock) { + if (state == PPC_CPU_STATE_PAUSED) { + if (ppc_paused) + return; + ppc_paused = true; + } else if (state == PPC_CPU_STATE_RUNNING) { + if (!ppc_paused) + return; + ppc_paused = false; + } else { + return; + } if (using_qemu()) { impl.set_state(state); if (unlock) @@ -560,13 +572,6 @@ bool UAECALL uae_ppc_io_mem_write(uint32_t addr, uint32_t data, int size) #endif locked = spinlock_pre(addr); - if (addr >= 0xdff000 && addr < 0xe00000) { - // shortcuts for common registers - if (addr == 0xdff09c) { // INTREQ - INTREQ_0(data); - size = 0; - } - } switch (size) { case 4: @@ -724,7 +729,7 @@ void uae_ppc_reset(bool hardreset) uae_ppc_cpu_stop(); if (hardreset) { if (ppc_init_done) - impl.free(); + impl.close(); ppc_init_done = false; } }