diff --git a/src/device/rcp/rsp/rsp_core.c b/src/device/rcp/rsp/rsp_core.c index cbdfa32f0..270fd6520 100644 --- a/src/device/rcp/rsp/rsp_core.c +++ b/src/device/rcp/rsp/rsp_core.c @@ -64,6 +64,10 @@ static void do_sp_dma(struct rsp_core* sp, const struct sp_dma* dma) post_framebuffer_write(&sp->dp->fb, dramaddr - length, length); dramaddr+=skip; } + + sp->regs[SP_MEM_ADDR_REG] = memaddr & 0xfff; + sp->regs[SP_DRAM_ADDR_REG] = dramaddr & 0xffffff; + sp->regs[SP_RD_LEN_REG] = 0xff8; } else { @@ -77,6 +81,10 @@ static void do_sp_dma(struct rsp_core* sp, const struct sp_dma* dma) } dramaddr+=skip; } + + sp->regs[SP_MEM_ADDR_REG] = memaddr & 0xfff; + sp->regs[SP_DRAM_ADDR_REG] = dramaddr & 0xffffff; + sp->regs[SP_RD_LEN_REG] = 0xff8; } /* schedule end of dma event */ @@ -137,68 +145,68 @@ static void fifo_pop(struct rsp_core* sp) static void update_sp_status(struct rsp_core* sp, uint32_t w) { /* clear / set halt */ - if (w & 0x1) sp->regs[SP_STATUS_REG] &= ~SP_STATUS_HALT; - if (w & 0x2) sp->regs[SP_STATUS_REG] |= SP_STATUS_HALT; + if ((w & 0x3) == 0x1) sp->regs[SP_STATUS_REG] &= ~SP_STATUS_HALT; + if ((w & 0x3) == 0x2) sp->regs[SP_STATUS_REG] |= SP_STATUS_HALT; /* clear broke */ if (w & 0x4) sp->regs[SP_STATUS_REG] &= ~SP_STATUS_BROKE; /* clear SP interrupt */ - if (w & 0x8) + if ((w & 0x18) == 0x8) { clear_rcp_interrupt(sp->mi, MI_INTR_SP); } /* set SP interrupt */ - if (w & 0x10) + if ((w & 0x18) == 0x10) { signal_rcp_interrupt(sp->mi, MI_INTR_SP); } /* clear / set single step */ - if (w & 0x20) sp->regs[SP_STATUS_REG] &= ~SP_STATUS_SSTEP; - if (w & 0x40) sp->regs[SP_STATUS_REG] |= SP_STATUS_SSTEP; + if ((w & 0x60) == 0x20) sp->regs[SP_STATUS_REG] &= ~SP_STATUS_SSTEP; + if ((w & 0x60) == 0x40) sp->regs[SP_STATUS_REG] |= SP_STATUS_SSTEP; /* clear / set interrupt on break */ - if (w & 0x80) sp->regs[SP_STATUS_REG] &= ~SP_STATUS_INTR_BREAK; - if (w & 0x100) sp->regs[SP_STATUS_REG] |= SP_STATUS_INTR_BREAK; + if ((w & 0x180) == 0x80) sp->regs[SP_STATUS_REG] &= ~SP_STATUS_INTR_BREAK; + if ((w & 0x180) == 0x100) sp->regs[SP_STATUS_REG] |= SP_STATUS_INTR_BREAK; /* clear / set signal 0 */ - if (w & 0x200) sp->regs[SP_STATUS_REG] &= ~SP_STATUS_SIG0; - if (w & 0x400) sp->regs[SP_STATUS_REG] |= SP_STATUS_SIG0; + if ((w & 0x600) == 0x200) sp->regs[SP_STATUS_REG] &= ~SP_STATUS_SIG0; + if ((w & 0x600) == 0x400) sp->regs[SP_STATUS_REG] |= SP_STATUS_SIG0; /* clear / set signal 1 */ - if (w & 0x800) sp->regs[SP_STATUS_REG] &= ~SP_STATUS_SIG1; - if (w & 0x1000) sp->regs[SP_STATUS_REG] |= SP_STATUS_SIG1; + if ((w & 0x1800) == 0x800) sp->regs[SP_STATUS_REG] &= ~SP_STATUS_SIG1; + if ((w & 0x1800) == 0x1000) sp->regs[SP_STATUS_REG] |= SP_STATUS_SIG1; /* clear / set signal 2 */ - if (w & 0x2000) sp->regs[SP_STATUS_REG] &= ~SP_STATUS_SIG2; - if (w & 0x4000) sp->regs[SP_STATUS_REG] |= SP_STATUS_SIG2; + if ((w & 0x6000) == 0x2000) sp->regs[SP_STATUS_REG] &= ~SP_STATUS_SIG2; + if ((w & 0x6000) == 0x4000) sp->regs[SP_STATUS_REG] |= SP_STATUS_SIG2; /* clear / set signal 3 */ - if (w & 0x8000) sp->regs[SP_STATUS_REG] &= ~SP_STATUS_SIG3; - if (w & 0x10000) sp->regs[SP_STATUS_REG] |= SP_STATUS_SIG3; + if ((w & 0x18000) == 0x8000) sp->regs[SP_STATUS_REG] &= ~SP_STATUS_SIG3; + if ((w & 0x18000) == 0x10000) sp->regs[SP_STATUS_REG] |= SP_STATUS_SIG3; /* clear / set signal 4 */ - if (w & 0x20000) sp->regs[SP_STATUS_REG] &= ~SP_STATUS_SIG4; - if (w & 0x40000) sp->regs[SP_STATUS_REG] |= SP_STATUS_SIG4; + if ((w & 0x60000) == 0x20000) sp->regs[SP_STATUS_REG] &= ~SP_STATUS_SIG4; + if ((w & 0x60000) == 0x40000) sp->regs[SP_STATUS_REG] |= SP_STATUS_SIG4; /* clear / set signal 5 */ - if (w & 0x80000) sp->regs[SP_STATUS_REG] &= ~SP_STATUS_SIG5; - if (w & 0x100000) sp->regs[SP_STATUS_REG] |= SP_STATUS_SIG5; + if ((w & 0x180000) == 0x80000) sp->regs[SP_STATUS_REG] &= ~SP_STATUS_SIG5; + if ((w & 0x180000) == 0x100000) sp->regs[SP_STATUS_REG] |= SP_STATUS_SIG5; /* clear / set signal 6 */ - if (w & 0x200000) sp->regs[SP_STATUS_REG] &= ~SP_STATUS_SIG6; - if (w & 0x400000) sp->regs[SP_STATUS_REG] |= SP_STATUS_SIG6; + if ((w & 0x600000) == 0x200000) sp->regs[SP_STATUS_REG] &= ~SP_STATUS_SIG6; + if ((w & 0x600000) == 0x400000) sp->regs[SP_STATUS_REG] |= SP_STATUS_SIG6; /* clear / set signal 7 */ - if (w & 0x800000) sp->regs[SP_STATUS_REG] &= ~SP_STATUS_SIG7; - if (w & 0x1000000) sp->regs[SP_STATUS_REG] |= SP_STATUS_SIG7; + if ((w & 0x1800000) == 0x800000) sp->regs[SP_STATUS_REG] &= ~SP_STATUS_SIG7; + if ((w & 0x1800000) == 0x1000000) sp->regs[SP_STATUS_REG] |= SP_STATUS_SIG7; if (sp->rsp_task_locked && (get_event(&sp->mi->r4300->cp0.q, SP_INT))) return; - if (!(w & 0x1) && !(w & 0x4) && !sp->rsp_task_locked) + if (!((w & 0x3) == 1) && !(w & 0x4) && !sp->rsp_task_locked) return; - if (!(sp->regs[SP_STATUS_REG] & (SP_STATUS_HALT | SP_STATUS_BROKE))) + if (!(sp->regs[SP_STATUS_REG] & SP_STATUS_HALT)) do_SP_Task(sp); } @@ -224,6 +232,8 @@ void poweron_rsp(struct rsp_core* sp) sp->rsp_task_locked = 0; sp->mi->r4300->cp0.interrupt_unsafe_state &= ~INTR_UNSAFE_RSP; sp->regs[SP_STATUS_REG] = 1; + sp->regs[SP_RD_LEN_REG] = 0xff8; + sp->regs[SP_WR_LEN_REG] = 0xff8; } @@ -294,6 +304,10 @@ void read_rsp_regs2(void* opaque, uint32_t address, uint32_t* value) uint32_t reg = rsp_reg2(address); *value = sp->regs2[reg]; + + if (reg == SP_PC_REG) + *value &= 0xffc; + } void write_rsp_regs2(void* opaque, uint32_t address, uint32_t value, uint32_t mask) @@ -301,6 +315,9 @@ void write_rsp_regs2(void* opaque, uint32_t address, uint32_t value, uint32_t ma struct rsp_core* sp = (struct rsp_core*)opaque; uint32_t reg = rsp_reg2(address); + if (reg == SP_PC_REG) + mask &= 0xffc; + masked_write(&sp->regs2[reg], value, mask); }