]> git.unchartedbackwaters.co.uk Git - francis/winuae.git/commitdiff
Interrupt handling updates.
authorToni Wilen <twilen@winuae.net>
Sun, 28 Sep 2014 14:43:52 +0000 (17:43 +0300)
committerToni Wilen <twilen@winuae.net>
Sun, 28 Sep 2014 14:43:52 +0000 (17:43 +0300)
cpuboard.cpp
custom.cpp
include/uae/ppc.h
ncr9x_scsi.cpp
ncr_scsi.cpp
newcpu.cpp
ppc/ppc.cpp

index c4151b5037ea9cf37b09101c0f0a9abee733d2b3..b4de8bb135f6e9685beb33abf1042e9df615524d 100644 (file)
@@ -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))
index fe7d7497e13bfd04bc6e99094f4febb1eb505b08..8072c19aa9eab3ca9bc16ecde6541ee464799622 100644 (file)
@@ -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);
index 51020983b04a6d5f85126878c9896be127b8e30e..f05b9872a467b914e1563c7f36af6e61464deba1 100644 (file)
@@ -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);
index 132a0108cef80547b95e2363f9a792d3129b85b0..f42435aaca49d08b6c1db103e6fb203970b375fb 100644 (file)
@@ -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);
        }
 }
 
index 9979264c3691a6ed9a75362543f3314de7e92579..d3db8fb03081aebdb64eaf0da9ba695d3b175287 100644 (file)
@@ -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);
index 8d2c6e94734cbb1d4fc881dc672ef2eb722926f3..836bd4f24bc081ba69c461271ff7d47890e8418d 100644 (file)
@@ -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);
index b0c76a0f8b60d79b493faaab20e6763bc0a424c6..a16e34a44602c98c9ec29828a05dd428a4d3ca4d 100644 (file)
@@ -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;
                }
        }