static void p32x_sh2reg_write16(u32 a, u32 d, SH2 *sh2) { a &= 0x3e; sh2->poll_addr = 0; // comm if ((a & 0x30) == 0x20) { int comreg; if (Pico32x.regs[a / 2] == d) return; Pico32x.regs[a / 2] = d; p32x_m68k_poll_event(P32XF_68KCPOLL); p32x_sh2_poll_event(sh2->other_sh2, SH2_STATE_CPOLL, sh2_cycles_done_m68k(sh2)); comreg = 1 << (a & 0x0f) / 2; Pico32x.comm_dirty_sh2 |= comreg; return; } // PWM else if ((a & 0x30) == 0x30) { p32x_pwm_write16(a, d, sh2, sh2_cycles_done_m68k(sh2)); return; } switch (a) { case 0: // FM Pico32x.regs[0] &= ~P32XS_FM; Pico32x.regs[0] |= d & P32XS_FM; break; case 0x14: Pico32x.sh2irqs &= ~P32XI_VRES; goto irls; case 0x16: Pico32x.sh2irqi[sh2->is_slave] &= ~P32XI_VINT; goto irls; case 0x18: Pico32x.sh2irqi[sh2->is_slave] &= ~P32XI_HINT; goto irls; case 0x1a: Pico32x.regs[2 / 2] &= ~(1 << sh2->is_slave); p32x_update_cmd_irq(sh2, 0); return; case 0x1c: p32x_pwm_sync_to_sh2(sh2); Pico32x.sh2irqi[sh2->is_slave] &= ~P32XI_PWM; p32x_pwm_schedule_sh2(sh2); goto irls; } p32x_sh2reg_write8(a | 1, d, sh2); return; irls: p32x_update_irls(sh2, 0); }
static u32 p32x_sh2reg_read16(u32 a, SH2 *sh2) { u16 *r = Pico32x.regs; a &= 0x3e; switch (a) { case 0x00: // adapter/irq ctl return (r[0] & P32XS_FM) | Pico32x.sh2_regs[0] | Pico32x.sh2irq_mask[sh2->is_slave]; case 0x04: // H count (often as comm too) sh2_poll_detect(sh2, a, SH2_STATE_CPOLL, 3); sh2s_sync_on_read(sh2); return Pico32x.sh2_regs[4 / 2]; case 0x06: return (r[a / 2] & ~P32XS_FULL) | 0x4000; case 0x08: // DREQ src case 0x0a: case 0x0c: // DREQ dst case 0x0e: case 0x10: // DREQ len return r[a / 2]; case 0x12: // DREQ FIFO - does this work on hw? if (Pico32x.dmac0_fifo_ptr > 0) { Pico32x.dmac0_fifo_ptr--; r[a / 2] = Pico32x.dmac_fifo[0]; memmove(&Pico32x.dmac_fifo[0], &Pico32x.dmac_fifo[1], Pico32x.dmac0_fifo_ptr * 2); } return r[a / 2]; case 0x14: case 0x16: case 0x18: case 0x1a: case 0x1c: return 0; // ? } // comm port if ((a & 0x30) == 0x20) { int comreg = 1 << (a & 0x0f) / 2; if (Pico32x.comm_dirty_68k & comreg) Pico32x.comm_dirty_68k &= ~comreg; else sh2_poll_detect(sh2, a, SH2_STATE_CPOLL, 3); sh2s_sync_on_read(sh2); return r[a / 2]; } if ((a & 0x30) == 0x30) return p32x_pwm_read16(a, sh2, sh2_cycles_done_m68k(sh2)); elprintf_sh2(sh2, EL_32X|EL_ANOMALY, "unhandled sysreg r16 [%02x] @%08x", a, sh2_pc(sh2)); return 0; }
void p32x_pwm_sync_to_sh2(SH2 *sh2) { int m68k_cycles = sh2_cycles_done_m68k(sh2); consume_fifo(sh2, m68k_cycles); }
void p32x_pwm_schedule_sh2(SH2 *sh2) { int after = p32x_pwm_schedule_(sh2, sh2_cycles_done_m68k(sh2)); if (after != 0) p32x_event_schedule_sh2(sh2, P32X_EVENT_PWM, after); }
static void p32x_sh2reg_write8(u32 a, u32 d, SH2 *sh2) { u16 *r = Pico32x.regs; u32 old; a &= 0x3f; sh2->poll_addr = 0; switch (a) { case 0x00: // FM r[0] &= ~P32XS_FM; r[0] |= (d << 8) & P32XS_FM; return; case 0x01: // HEN/irq masks old = Pico32x.sh2irq_mask[sh2->is_slave]; if ((d ^ old) & 1) p32x_pwm_sync_to_sh2(sh2); Pico32x.sh2irq_mask[sh2->is_slave] = d & 0x0f; Pico32x.sh2_regs[0] &= ~0x80; Pico32x.sh2_regs[0] |= d & 0x80; if ((d ^ old) & 1) p32x_pwm_schedule_sh2(sh2); if ((old ^ d) & 2) p32x_update_cmd_irq(sh2, 0); if ((old ^ d) & 4) p32x_schedule_hint(sh2, 0); return; case 0x04: // ignored? return; case 0x05: // H count d &= 0xff; if (Pico32x.sh2_regs[4 / 2] != d) { Pico32x.sh2_regs[4 / 2] = d; p32x_sh2_poll_event(sh2->other_sh2, SH2_STATE_CPOLL, sh2_cycles_done_m68k(sh2)); sh2_end_run(sh2, 4); } return; case 0x30: REG8IN16(r, a) = d & 0x0f; d = r[0x30 / 2]; goto pwm_write; case 0x31: // PWM control REG8IN16(r, a) = d & 0x8f; d = r[0x30 / 2]; goto pwm_write; case 0x32: // PWM cycle REG8IN16(r, a) = d & 0x0f; d = r[0x32 / 2]; goto pwm_write; case 0x33: REG8IN16(r, a) = d; d = r[0x32 / 2]; goto pwm_write; // PWM pulse regs.. Only writes to odd address send a value // to FIFO; reads are 0 (except status bits) case 0x34: case 0x36: case 0x38: REG8IN16(r, a) = d; return; case 0x35: case 0x37: case 0x39: d = (REG8IN16(r, a ^ 1) << 8) | (d & 0xff); REG8IN16(r, a ^ 1) = 0; goto pwm_write; case 0x3a: // ignored, always 0? case 0x3b: case 0x3c: case 0x3d: case 0x3e: case 0x3f: return; pwm_write: p32x_pwm_write16(a & ~1, d, sh2, 0); return; } if ((a & 0x30) == 0x20) { int comreg; if (REG8IN16(r, a) == d) return; REG8IN16(r, a) = d; p32x_m68k_poll_event(P32XF_68KCPOLL); p32x_sh2_poll_event(sh2->other_sh2, SH2_STATE_CPOLL, sh2_cycles_done_m68k(sh2)); comreg = 1 << (a & 0x0f) / 2; Pico32x.comm_dirty_sh2 |= comreg; return; } elprintf(EL_32X|EL_ANOMALY, "unhandled sysreg w8 [%02x] %02x @%08x", a, d, sh2_pc(sh2)); }