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)
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;
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);
{
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());
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))
#ifdef NCR9X
ncr9x_rethink();
#endif
- cpuboard_rethink();
rethink_gayle ();
+ /* cpuboard_rethink must be last */
+ cpuboard_rethink();
}
static void send_interrupt_do (uae_u32 v)
{
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);
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);
{
for (int i = 0; ncrs[i]; i++) {
if (ncrs[i]->boardirq)
- INTREQ(0x8000 | 0x0008);
+ INTREQ_0(0x8000 | 0x0008);
}
}
{
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);
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)
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;
}
+ 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) {
return true;
}
}
+#ifdef WITH_PPC
}
+#endif
return false;
}
protect_roms (true);
}
startup = 0;
+ event_wait = true;
+ unset_special(SPCFLAG_MODE_CHANGE);
+
if (regs.halted) {
cpu_halt (regs.halted);
if (regs.halted < 0)
#if 0
}
#endif
- event_wait = true;
- unset_special(SPCFLAG_MODE_CHANGE);
run_func();
}
protect_roms (false);
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
/* 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) { }
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);
/* 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;
/* 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;
{
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;
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;
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)
#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:
uae_ppc_cpu_stop();
if (hardreset) {
if (ppc_init_done)
- impl.free();
+ impl.close();
ppc_init_done = false;
}
}