From 4ea707e1e38b7ca204a5012f617018d0ea5eced2 Mon Sep 17 00:00:00 2001 From: notaz Date: Sun, 20 Sep 2009 18:13:06 +0000 Subject: [PATCH] 32x: sh2 irqs (irls), preliminary DMAC implementation git-svn-id: file:///home/notaz/opt/svn/PicoDrive@786 be3aeb3a-fb24-0410-a615-afba39da0efa --- cpu/sh2mame/sh2.h | 7 +- cpu/sh2mame/sh2pico.c | 62 ++++++++--- pico/32x/32x.c | 59 +++++++++- pico/32x/memory.c | 246 +++++++++++++++++++++++++++++++++--------- pico/debug.c | 5 +- pico/pico_int.h | 41 +++++-- 6 files changed, 336 insertions(+), 84 deletions(-) diff --git a/cpu/sh2mame/sh2.h b/cpu/sh2mame/sh2.h index 6684d11..97520f3 100644 --- a/cpu/sh2mame/sh2.h +++ b/cpu/sh2mame/sh2.h @@ -39,13 +39,15 @@ typedef struct UINT32 sr; UINT32 gbr, vbr; UINT32 mach, macl; + UINT32 ea; UINT32 delay; UINT32 test_irq; + int pending_irq; + void (*irq_callback)(int level); + // XXX: unused, will we ever use? - void (*irq_callback)(void); - int nmi_line_state; int internal_irq_level; int is_slave; } SH2; @@ -55,5 +57,6 @@ extern int sh2_icount; void sh2_init(SH2 *sh2); void sh2_reset(SH2 *sh2); int sh2_execute(SH2 *sh2_, int cycles); +void sh2_irl_irq(SH2 *sh2, int level); #endif /* __SH2_H__ */ diff --git a/cpu/sh2mame/sh2pico.c b/cpu/sh2mame/sh2pico.c index e77329c..ac3df3e 100644 --- a/cpu/sh2mame/sh2pico.c +++ b/cpu/sh2mame/sh2pico.c @@ -9,19 +9,19 @@ typedef unsigned short UINT16; typedef unsigned char UINT8; // pico memhandlers -unsigned int pico32x_read8(unsigned int a); -unsigned int pico32x_read16(unsigned int a); -unsigned int pico32x_read32(unsigned int a); -void pico32x_write8(unsigned int a, unsigned int d); -void pico32x_write16(unsigned int a, unsigned int d); -void pico32x_write32(unsigned int a, unsigned int d); - -#define RB pico32x_read8 -#define RW pico32x_read16 -#define RL pico32x_read32 -#define WB pico32x_write8 -#define WW pico32x_write16 -#define WL pico32x_write32 +unsigned int p32x_sh2_read8(unsigned int a); +unsigned int p32x_sh2_read16(unsigned int a); +unsigned int p32x_sh2_read32(unsigned int a); +void p32x_sh2_write8(unsigned int a, unsigned int d); +void p32x_sh2_write16(unsigned int a, unsigned int d); +void p32x_sh2_write32(unsigned int a, unsigned int d); + +#define RB p32x_sh2_read8 +#define RW p32x_sh2_read16 +#define RL p32x_sh2_read32 +#define WB p32x_sh2_write8 +#define WW p32x_sh2_write16 +#define WL p32x_sh2_write32 // some stuff from sh2comn.h #define T 0x00000001 @@ -42,15 +42,15 @@ void pico32x_write32(unsigned int a, unsigned int d); void sh2_reset(SH2 *sh2) { int save_is_slave; -// cpu_irq_callback save_irqcallback; + void *save_irqcallback; -// save_irqcallback = sh2->irq_callback; + save_irqcallback = sh2->irq_callback; save_is_slave = sh2->is_slave; memset(sh2, 0, sizeof(SH2)); sh2->is_slave = save_is_slave; -// sh2->irq_callback = save_irqcallback; + sh2->irq_callback = save_irqcallback; sh2->pc = RL(0); sh2->r[15] = RL(4); @@ -103,7 +103,8 @@ int sh2_execute(SH2 *sh2_, int cycles) if (sh2->test_irq && !sh2->delay) { -// CHECK_PENDING_IRQ("mame_sh2_execute"); + if (sh2->pending_irq) + sh2_irl_irq(sh2, sh2->pending_irq); sh2->test_irq = 0; } sh2_icount--; @@ -118,4 +119,31 @@ void sh2_init(SH2 *sh2) memset(sh2, 0, sizeof(*sh2)); } +void sh2_irl_irq(SH2 *sh2, int level) +{ + int vector; + + sh2->pending_irq = level; + + if (level <= ((sh2->sr >> 4) & 0x0f)) + /* masked */ + return; + + sh2->irq_callback(level); + vector = 64 + level/2; + + sh2->r[15] -= 4; + WL(sh2->r[15], sh2->sr); /* push SR onto stack */ + sh2->r[15] -= 4; + WL(sh2->r[15], sh2->pc); /* push PC onto stack */ + + /* set I flags in SR */ + sh2->sr = (sh2->sr & ~I) | (level << 4); + + /* fetch PC */ + sh2->pc = RL(sh2->vbr + vector * 4); + + /* 13 cycles at best */ + sh2_icount -= 13; +} diff --git a/pico/32x/32x.c b/pico/32x/32x.c index 8e3553a..ee561ae 100644 --- a/pico/32x/32x.c +++ b/pico/32x/32x.c @@ -3,6 +3,35 @@ struct Pico32x Pico32x; +static void sh2_irq_cb(int level) +{ + // diagnostic for now + elprintf(EL_32X, "sh2 ack %d @ %08x", level, ash2_pc()); +} + +void p32x_update_irls(void) +{ + int irqs, mlvl = 0, slvl = 0; + + // msh2 + irqs = (Pico32x.sh2irqs | Pico32x.sh2irqi[0]) & ((Pico32x.sh2irq_mask[0] << 3) | P32XI_VRES); + while ((irqs >>= 1)) + mlvl++; + mlvl *= 2; + + // ssh2 + irqs = (Pico32x.sh2irqs | Pico32x.sh2irqi[1]) & ((Pico32x.sh2irq_mask[1] << 3) | P32XI_VRES); + while ((irqs >>= 1)) + slvl++; + slvl *= 2; + + elprintf(EL_32X, "update_irls: m %d, s %d", mlvl, slvl); + sh2_irl_irq(&msh2, mlvl); + if (mlvl) + p32x_poll_event(0); + sh2_irl_irq(&ssh2, slvl); +} + void Pico32xStartup(void) { elprintf(EL_STATUS|EL_32X, "32X startup"); @@ -11,9 +40,11 @@ void Pico32xStartup(void) PicoMemSetup32x(); sh2_init(&msh2); + msh2.irq_callback = sh2_irq_cb; sh2_reset(&msh2); sh2_init(&ssh2); + ssh2.irq_callback = sh2_irq_cb; sh2_reset(&ssh2); if (!Pico.m.pal) @@ -54,20 +85,27 @@ static void p32x_start_blank(void) // enter vblank Pico32x.vdp_regs[0x0a/2] |= P32XV_VBLK|P32XV_PEN; - // swap waits until vblank + // FB swap waits until vblank if ((Pico32x.vdp_regs[0x0a/2] ^ Pico32x.pending_fb) & P32XV_FS) { Pico32x.vdp_regs[0x0a/2] &= ~P32XV_FS; Pico32x.vdp_regs[0x0a/2] |= Pico32x.pending_fb; Pico32xSwapDRAM(Pico32x.pending_fb ^ 1); } + + p32x_poll_event(1); } // FIXME.. static __inline void SekRunM68k(int cyc) { int cyc_do; - SekCycleAim+=cyc; - if ((cyc_do=SekCycleAim-SekCycleCnt) <= 0) return; + SekCycleAim += cyc; + if (Pico32x.emu_flags & P32XF_68KPOLL) { + SekCycleCnt = SekCycleAim; + return; + } + if ((cyc_do = SekCycleAim - SekCycleCnt) <= 0) + return; #if defined(EMU_CORE_DEBUG) // this means we do run-compare SekCycleCnt+=CM_compareRun(cyc_do, 0); @@ -88,16 +126,27 @@ static __inline void SekRunM68k(int cyc) #define PICO_32X #define RUN_SH2S \ - if (!(Pico32x.emu_flags & P32XF_MSH2POLL)) \ + if (!(Pico32x.emu_flags & (P32XF_MSH2POLL|P32XF_MSH2VPOLL))) \ sh2_execute(&msh2, SH2_LINE_CYCLES); #include "../pico_cmn.c" void PicoFrame32x(void) { + Pico32x.vdp_regs[0x0a/2] &= ~P32XV_VBLK; // get out of vblank if ((Pico32x.vdp_regs[0] & 3 ) != 0) // no forced blanking - Pico32x.vdp_regs[0x0a/2] &= ~(P32XV_VBLK|P32XV_PEN); // get out of vblank + Pico32x.vdp_regs[0x0a/2] &= ~P32XV_PEN; // no pal access + + p32x_poll_event(1); PicoFrameStart(); PicoFrameHints(); + + // hack + if (Pico.m.frame_count == 83) { + Pico32xMem->sdram[0x3610 ^ 1] = 'R'; + Pico32xMem->sdram[0x3611 ^ 1] = 'E'; + Pico32xMem->sdram[0x3612 ^ 1] = 'D'; + Pico32xMem->sdram[0x3613 ^ 1] = 'Y'; + } } diff --git a/pico/32x/memory.c b/pico/32x/memory.c index 886799c..7e2f2bd 100644 --- a/pico/32x/memory.c +++ b/pico/32x/memory.c @@ -10,15 +10,14 @@ static void bank_switch(int b); #define MSB8(x) ((x) >> 8) // poll detection +#define POLL_THRESHOLD 6 + struct poll_det { int addr, pc, cnt; }; -static struct poll_det m68k_poll; -static struct poll_det msh2_poll; - -#define POLL_THRESHOLD 6 +static struct poll_det m68k_poll, msh2_poll; -static int poll_detect(struct poll_det *pd, u32 a, u32 pc, int flag) +static int p32x_poll_detect(struct poll_det *pd, u32 a, u32 pc, int flag) { int ret = 0; @@ -41,7 +40,7 @@ static int poll_detect(struct poll_det *pd, u32 a, u32 pc, int flag) return ret; } -static int poll_undetect(struct poll_det *pd, int flag) +static int p32x_poll_undetect(struct poll_det *pd, int flag) { int ret = 0; if (pd->cnt > POLL_THRESHOLD) @@ -51,6 +50,11 @@ static int poll_undetect(struct poll_det *pd, int flag) return ret; } +void p32x_poll_event(int is_vdp) +{ + p32x_poll_undetect(&msh2_poll, is_vdp ? P32XF_MSH2VPOLL : P32XF_MSH2POLL); +} + // SH2 faking #define FAKE_SH2 int p32x_csum_faked; @@ -80,6 +84,44 @@ static u32 sh2_comm_faker(u32 a) } #endif +// DMAC handling +static struct { + unsigned int sar0, dar0, tcr0; // src addr, dst addr, transfer count + unsigned int chcr0; // chan ctl + unsigned int sar1, dar1, tcr1; // same for chan 1 + unsigned int chcr1; + int pad[4]; + unsigned int dmaor; +} * dmac0; + +static void dma_68k2sh2_do(void) +{ + unsigned short *dreqlen = &Pico32x.regs[0x10 / 2]; + int i; + + if (dmac0->tcr0 != *dreqlen) + elprintf(EL_32X|EL_ANOMALY, "tcr0 and dreq len differ: %d != %d", dmac0->tcr0, *dreqlen); + + for (i = 0; i < Pico32x.dmac_ptr && dmac0->tcr0 > 0; i++) { + extern void p32x_sh2_write16(u32 a, u32 d); + elprintf(EL_32X|EL_ANOMALY, "dmaw [%08x] %04x, left %d", dmac0->dar0, Pico32x.dmac_fifo[i], *dreqlen); + p32x_sh2_write16(dmac0->dar0, Pico32x.dmac_fifo[i]); + dmac0->dar0 += 2; + dmac0->tcr0--; + (*dreqlen)--; + } + + Pico32x.dmac_ptr = 0; // HACK + Pico32x.regs[6 / 2] &= ~P32XS_FULL; + if (*dreqlen == 0) + Pico32x.regs[6 / 2] &= ~P32XS_68S; // transfer complete + if (dmac0->tcr0 == 0) + dmac0->chcr0 |= 2; // DMA has ended normally + p32x_poll_undetect(&m68k_poll, P32XF_68KPOLL); +} + +// ------------------------------------------------------------------ + static u32 p32x_reg_read16(u32 a) { a &= 0x3e; @@ -88,8 +130,7 @@ static u32 p32x_reg_read16(u32 a) if ((a & 0x30) == 0x20) return sh2_comm_faker(a); #else - if (poll_detect(&m68k_poll, a, SekPc, P32XF_68KPOLL)) { - SekSetStop(1); + if (p32x_poll_detect(&m68k_poll, a, SekPc, P32XF_68KPOLL)) { SekEndRun(16); } #endif @@ -117,16 +158,25 @@ static void p32x_reg_write8(u32 a, u32 d) return; switch (a) { - case 0: + case 0: // adapter ctl r[0] = (r[0] & 0x83) | ((d << 8) & P32XS_FM); break; - case 5: + case 3: // irq ctl + if ((d & 1) && !(Pico32x.sh2irqi[0] & P32XI_CMD)) { + Pico32x.sh2irqi[0] |= P32XI_CMD; + p32x_update_irls(); + } + break; + case 5: // bank d &= 7; - if (r[4/2] != d) { - r[4/2] = d; + if (r[4 / 2] != d) { + r[4 / 2] = d; bank_switch(d); } break; + case 7: // DREQ ctl + r[6 / 2] = (r[6 / 2] & P32XS_FULL) | (d & (P32XS_68S|P32XS_RV)); + break; } } @@ -135,15 +185,40 @@ static void p32x_reg_write16(u32 a, u32 d) u16 *r = Pico32x.regs; a &= 0x3e; + // for write loops with FIFO checks.. + m68k_poll.cnt = 0; + switch (a) { - case 0: + case 0x00: // adapter ctl r[0] = (r[0] & 0x83) | (d & P32XS_FM); return; + case 0x10: // DREQ len + r[a / 2] = d & ~3; + return; + case 0x12: // FIFO reg + if (!(r[6 / 2] & P32XS_68S)) { + elprintf(EL_32X|EL_ANOMALY, "DREQ FIFO w16 without 68S?"); + return; + } + if (Pico32x.dmac_ptr < DMAC_FIFO_LEN) { + Pico32x.dmac_fifo[Pico32x.dmac_ptr++] = d; + if ((Pico32x.dmac_ptr & 3) == 0 && (dmac0->chcr0 & 3) == 1 && (dmac0->dmaor & 1)) + dma_68k2sh2_do(); + if (Pico32x.dmac_ptr == DMAC_FIFO_LEN) + r[6 / 2] |= P32XS_FULL; + } + break; } - if ((a & 0x30) == 0x20 && r[a / 2] != d) { + // DREQ src, dst + if ((a & 0x38) == 0x08) { + r[a / 2] = d; + return; + } + // comm port + else if ((a & 0x30) == 0x20 && r[a / 2] != d) { r[a / 2] = d; - if (poll_undetect(&msh2_poll, P32XF_MSH2POLL)) + if (p32x_poll_undetect(&msh2_poll, P32XF_MSH2POLL)) // if SH2 is busy waiting, it needs to see the result ASAP SekEndRun(16); return; @@ -152,6 +227,7 @@ static void p32x_reg_write16(u32 a, u32 d) p32x_reg_write8(a + 1, d); } +// ------------------------------------------------------------------ // VDP regs static u32 p32x_vdp_read16(u32 a) { @@ -165,15 +241,12 @@ static void p32x_vdp_write8(u32 a, u32 d) u16 *r = Pico32x.vdp_regs; a &= 0x0f; + // for FEN checks between writes + msh2_poll.cnt = 0; + // TODO: verify what's writeable switch (a) { case 0x01: - if (((r[0] & 3) == 0) != ((d & 3) == 0)) { // forced blanking changed - if (Pico.video.status & 8) - r[0x0a/2] |= P32XV_VBLK; - else - r[0x0a/2] &= ~P32XV_VBLK; - } // priority inversion is handled in palette if ((r[0] ^ d) & P32XV_PRI) Pico32x.dirty_pal = 1; @@ -183,7 +256,7 @@ static void p32x_vdp_write8(u32 a, u32 d) d &= 1; Pico32x.pending_fb = d; // if we are blanking and FS bit is changing - if ((r[0x0a/2] & P32XV_VBLK) && ((r[0x0a/2] ^ d) & P32XV_FS)) { + if (((r[0x0a/2] & P32XV_VBLK) || (r[0] & P32XV_Mx) == 0) && ((r[0x0a/2] ^ d) & P32XV_FS)) { r[0x0a/2] ^= 1; Pico32xSwapDRAM(d ^ 1); elprintf(EL_32X, "VDP FS: %d", r[0x0a/2] & P32XV_FS); @@ -197,43 +270,93 @@ static void p32x_vdp_write16(u32 a, u32 d) p32x_vdp_write8(a | 1, d); } +// ------------------------------------------------------------------ // SH2 regs static u32 p32x_sh2reg_read16(u32 a) { - a &= 0xff; // ? - - if (poll_detect(&msh2_poll, a, ash2_pc(), P32XF_MSH2POLL)) - ash2_end_run(8); + u16 *r = Pico32x.regs; + a &= 0xfe; // ? - if (a == 0) { - return (Pico32x.regs[0] & P32XS_FM) | P32XS2_ADEN; + switch (a) { + case 0x00: // adapter/irq ctl + return (r[0] & P32XS_FM) | P32XS2_ADEN | Pico32x.sh2irq_mask[0]; + case 0x10: // DREQ len + return r[a / 2]; } - if ((a & 0x30) == 0x20) - return Pico32x.regs[a / 2]; + + // DREQ src, dst; comm port + if ((a & 0x38) == 0x08 || (a & 0x30) == 0x20) + return r[a / 2]; return 0; } static void p32x_sh2reg_write8(u32 a, u32 d) { + a &= 0xff; + if (a == 1) { + Pico32x.sh2irq_mask[0] = d & 0x0f; + p32x_update_irls(); + } } static void p32x_sh2reg_write16(u32 a, u32 d) { - a &= 0xff; + a &= 0xfe; - if ((a & 0x30) == 0x20) { + if ((a & 0x30) == 0x20 && Pico32x.regs[a/2] != d) { Pico32x.regs[a/2] = d; - if (poll_undetect(&m68k_poll, P32XF_68KPOLL)) - // dangerous, but let's just assume 68k program - // didn't issue STOP itself. - SekSetStop(0); + p32x_poll_undetect(&m68k_poll, P32XF_68KPOLL); return; } + switch (a) { + case 0x14: Pico32x.sh2irqs &= ~P32XI_VRES; goto irls; + case 0x16: Pico32x.sh2irqs &= ~P32XI_VINT; goto irls; + case 0x18: Pico32x.sh2irqs &= ~P32XI_HINT; goto irls; + case 0x1a: Pico32x.sh2irqi[0] &= ~P32XI_CMD; goto irls; + case 0x1c: Pico32x.sh2irqs &= ~P32XI_PWM; goto irls; + } + p32x_sh2reg_write8(a | 1, d); + return; + +irls: + p32x_update_irls(); +} + +static u32 sh2_peripheral_read(u32 a) +{ + u32 d; + a &= 0x1fc; + d = Pico32xMem->sh2_peri_regs[0][a / 4]; + + elprintf(EL_32X, "sh2 peri r32 [%08x] %08x @%06x", a, d, ash2_pc()); + return d; } +static void sh2_peripheral_write(u32 a, u32 d) +{ + unsigned int *r = Pico32xMem->sh2_peri_regs[0]; + elprintf(EL_32X, "sh2 peri w32 [%08x] %08x @%06x", a, d, ash2_pc()); + + a &= 0x1fc; + r[a / 4] = d; + + if ((a == 0x1b0 || a == 0x18c) && (dmac0->chcr0 & 3) == 1 && (dmac0->dmaor & 1)) { + elprintf(EL_32X, "sh2 DMA %08x -> %08x, cnt %d, chcr %04x @%06x", + dmac0->sar0, dmac0->dar0, dmac0->tcr0, dmac0->chcr0, ash2_pc()); + dmac0->tcr0 &= 0xffffff; + // DREQ is only sent after first 4 words are written. + // we do multiple of 4 words to avoid messing up alignment + if (dmac0->sar0 == 0x20004012 && Pico32x.dmac_ptr && (Pico32x.dmac_ptr & 3) == 0) { + elprintf(EL_32X, "68k -> sh2 DMA"); + dma_68k2sh2_do(); + } + } +} + +// ------------------------------------------------------------------ // default 32x handlers u32 PicoRead8_32x(u32 a) { @@ -423,9 +546,11 @@ static void bank_switch(int b) // SH2 // ----------------------------------------------------------------- -u32 pico32x_read8(u32 a) +u32 p32x_sh2_read8(u32 a) { + int pd = 0; u32 d = 0; + if (a < sizeof(Pico32xMem->sh2_rom_m)) return Pico32xMem->sh2_rom_m[a ^ 1]; @@ -438,12 +563,14 @@ u32 pico32x_read8(u32 a) if ((a & 0x0fffff00) == 0x4000) { d = p32x_sh2reg_read16(a); - goto out_16to8; + pd = P32XF_MSH2POLL; + goto out_pd; } if ((a & 0x0fffff00) == 0x4100) { d = p32x_vdp_read16(a); - goto out_16to8; + pd = P32XF_MSH2VPOLL; + goto out_pd; } if ((a & 0x0fffff00) == 0x4200) { @@ -454,6 +581,10 @@ u32 pico32x_read8(u32 a) elprintf(EL_UIO, "sh2 unmapped r8 [%08x] %02x @%06x", a, d, ash2_pc()); return d; +out_pd: + if (p32x_poll_detect(&msh2_poll, a, ash2_pc(), pd)) + ash2_end_run(8); + out_16to8: if (a & 1) d &= 0xff; @@ -464,8 +595,9 @@ out_16to8: return d; } -u32 pico32x_read16(u32 a) +u32 p32x_sh2_read16(u32 a) { + int pd = 0; u32 d = 0; if (a < sizeof(Pico32xMem->sh2_rom_m)) @@ -480,12 +612,14 @@ u32 pico32x_read16(u32 a) if ((a & 0x0fffff00) == 0x4000) { d = p32x_sh2reg_read16(a); - goto out; + pd = P32XF_MSH2POLL; + goto out_pd; } if ((a & 0x0fffff00) == 0x4100) { d = p32x_vdp_read16(a); - goto out; + pd = P32XF_MSH2VPOLL; + goto out_pd; } if ((a & 0x0fffff00) == 0x4200) { @@ -496,18 +630,25 @@ u32 pico32x_read16(u32 a) elprintf(EL_UIO, "sh2 unmapped r16 [%08x] %04x @%06x", a, d, ash2_pc()); return d; +out_pd: + if (p32x_poll_detect(&msh2_poll, a, ash2_pc(), pd)) + ash2_end_run(8); + out: elprintf(EL_32X, "sh2 r16 [%08x] %04x @%06x", a, d, ash2_pc()); return d; } -u32 pico32x_read32(u32 a) +u32 p32x_sh2_read32(u32 a) { + if ((a & 0xfffffe00) == 0xfffffe00) + return sh2_peripheral_read(a); + // elprintf(EL_UIO, "sh2 r32 [%08x] %08x @%06x", a, d, ash2_pc()); - return (pico32x_read16(a) << 16) | pico32x_read16(a + 2); + return (p32x_sh2_read16(a) << 16) | p32x_sh2_read16(a + 2); } -void pico32x_write8(u32 a, u32 d) +void p32x_sh2_write8(u32 a, u32 d) { if ((a & 0x0ffffc00) == 0x4000) elprintf(EL_32X, "sh2 w8 [%08x] %02x @%06x", a, d & 0xff, ash2_pc()); @@ -536,7 +677,7 @@ void pico32x_write8(u32 a, u32 d) elprintf(EL_UIO, "sh2 unmapped w8 [%08x] %02x @%06x", a, d & 0xff, ash2_pc()); } -void pico32x_write16(u32 a, u32 d) +void p32x_sh2_write16(u32 a, u32 d) { if ((a & 0x0ffffc00) == 0x4000) elprintf(EL_32X, "sh2 w16 [%08x] %04x @%06x", a, d & 0xffff, ash2_pc()); @@ -570,11 +711,16 @@ void pico32x_write16(u32 a, u32 d) elprintf(EL_UIO, "sh2 unmapped w16 [%08x] %04x @%06x", a, d & 0xffff, ash2_pc()); } -void pico32x_write32(u32 a, u32 d) +void p32x_sh2_write32(u32 a, u32 d) { + if ((a & 0xfffffe00) == 0xfffffe00) { + sh2_peripheral_write(a, d); + return; + } + // elprintf(EL_UIO, "sh2 w32 [%08x] %08x @%06x", a, d, ash2_pc()); - pico32x_write16(a, d >> 16); - pico32x_write16(a + 2, d); + p32x_sh2_write16(a, d >> 16); + p32x_sh2_write16(a + 2, d); } #define HWSWAP(x) (((x) << 16) | ((x) >> 16)) @@ -591,6 +737,8 @@ void PicoMemSetup32x(void) return; } + dmac0 = (void *)&Pico32xMem->sh2_peri_regs[0][0x180 / 4]; + // generate 68k ROM ps = (unsigned short *)Pico32xMem->m68k_rom; pl = (unsigned int *)Pico32xMem->m68k_rom; diff --git a/pico/debug.c b/pico/debug.c index 5bbf8c4..26ec862 100644 --- a/pico/debug.c +++ b/pico/debug.c @@ -79,11 +79,12 @@ char *PDebug32x(void) i*2, r[i+0], r[i+1], r[i+2], r[i+3], r[i+4], r[i+5], r[i+6], r[i+7]); MVP; sprintf(dstrp, " mSH2 sSH2\n"); MVP; - sprintf(dstrp, "PC: %08x %08x\n", msh2_pc(), ssh2_pc()); MVP; + sprintf(dstrp, "PC,SR %08x, %03x %08x, %03x\n", sh2_pc(0), sh2_sr(0), sh2_pc(1), sh2_sr(1)); MVP; for (i = 0; i < 16/2; i++) { sprintf(dstrp, "R%d,%2d %08x,%08x %08x,%08x\n", i, i + 8, - msh2_reg(i), msh2_reg(i+8), ssh2_reg(i), ssh2_reg(i+8)); MVP; + sh2_reg(0,i), sh2_reg(0,i+8), sh2_reg(1,i), sh2_reg(1,i+8)); MVP; } + sprintf(dstrp, "gb,vb %08x,%08x %08x,%08x\n", sh2_gbr(0), sh2_vbr(0), sh2_gbr(1), sh2_vbr(1)); return dstr; } diff --git a/pico/pico_int.h b/pico/pico_int.h index d73041e..afcc838 100644 --- a/pico/pico_int.h +++ b/pico/pico_int.h @@ -234,11 +234,11 @@ SH2 msh2, ssh2; #define ash2_pc() msh2.ppc #define ash2_end_run(after) sh2_icount = after -#define msh2_pc() msh2.ppc -#define ssh2_pc() ssh2.ppc - -#define msh2_reg(x) msh2.r[x] -#define ssh2_reg(x) ssh2.r[x] +#define sh2_pc(c) (c) ? ssh2.ppc : msh2.ppc +#define sh2_reg(c, x) (c) ? ssh2.r[x] : msh2.r[x] +#define sh2_gbr(c) (c) ? ssh2.gbr : msh2.gbr +#define sh2_vbr(c) (c) ? ssh2.vbr : msh2.vbr +#define sh2_sr(c) (c) ? ssh2.sr : msh2.sr // --------------------------------------------------------- @@ -405,10 +405,13 @@ typedef struct // 32X #define P32XS_FM (1<<15) #define P32XS2_ADEN (1<< 9) +#define P32XS_FULL (1<< 7) +#define P32XS_68S (1<< 2) +#define P32XS_RV (1<< 0) #define P32XV_nPAL (1<<15) #define P32XV_PRI (1<< 7) -#define P32XV_Mx (3<< 0) +#define P32XV_Mx (3<< 0) // display mode mask #define P32XV_VBLK (1<<15) #define P32XV_HBLK (1<<14) @@ -416,9 +419,21 @@ typedef struct #define P32XV_nFEN (1<< 1) #define P32XV_FS (1<< 0) -#define P32XF_68KPOLL (1 << 0) -#define P32XF_MSH2POLL (1 << 1) -#define P32XF_SSH2POLL (1 << 2) +#define P32XF_68KPOLL (1 << 0) +#define P32XF_MSH2POLL (1 << 1) +#define P32XF_SSH2POLL (1 << 2) +#define P32XF_68KVPOLL (1 << 3) +#define P32XF_MSH2VPOLL (1 << 4) +#define P32XF_SSH2VPOLL (1 << 5) + +#define P32XI_VRES (1 << 14/2) // IRL/2 +#define P32XI_VINT (1 << 12/2) +#define P32XI_HINT (1 << 10/2) +#define P32XI_CMD (1 << 8/2) +#define P32XI_PWM (1 << 6/2) + +// real one is 4*2, but we use more because we don't lockstep +#define DMAC_FIFO_LEN (4*4) struct Pico32x { @@ -428,6 +443,11 @@ struct Pico32x unsigned char dirty_pal; unsigned char pad[2]; unsigned int emu_flags; + unsigned char sh2irq_mask[2]; + unsigned char sh2irqi[2]; // individual + unsigned int sh2irqs; // common irqs + unsigned short dmac_fifo[DMAC_FIFO_LEN]; + unsigned int dmac_ptr; }; struct Pico32xMem @@ -439,6 +459,7 @@ struct Pico32xMem unsigned char sh2_rom_s[0x400]; unsigned short pal[0x100]; unsigned short pal_native[0x100]; // converted to native (for renderer) + unsigned int sh2_peri_regs[2][0x200/4]; // periphereal regs of SH2s }; // area.c @@ -634,6 +655,7 @@ void PicoReset32x(void); void Pico32xStartup(void); void PicoUnload32x(void); void PicoFrame32x(void); +void p32x_update_irls(void); // 32x/memory.c struct Pico32xMem *Pico32xMem; @@ -643,6 +665,7 @@ void PicoWrite8_32x(unsigned int a, unsigned int d); void PicoWrite16_32x(unsigned int a, unsigned int d); void PicoMemSetup32x(void); void Pico32xSwapDRAM(int b); +void p32x_poll_event(int is_vdp); // 32x/draw.c void FinalizeLine32xRGB555(int sh, int line); -- 2.39.2