From 8ed9cec84b7ca07f23129e84995c74c78460ddac Mon Sep 17 00:00:00 2001 From: GhostlyDark <31742919+GhostlyDark@users.noreply.github.com> Date: Fri, 26 Jan 2024 16:54:55 +0100 Subject: [PATCH 1/5] Fixed incorrect handling of BREAK bit in the RSP status register Co-Authored-By: Matt Pharoah --- src/device/rcp/rsp/rsp_core.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/device/rcp/rsp/rsp_core.c b/src/device/rcp/rsp/rsp_core.c index cbdfa32f0..5792c5920 100644 --- a/src/device/rcp/rsp/rsp_core.c +++ b/src/device/rcp/rsp/rsp_core.c @@ -198,7 +198,7 @@ static void update_sp_status(struct rsp_core* sp, uint32_t w) if (!(w & 0x1) && !(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); } @@ -266,6 +266,7 @@ void write_rsp_regs(void* opaque, uint32_t address, uint32_t value, uint32_t mas { case SP_STATUS_REG: update_sp_status(sp, value & mask); + return; case SP_DMA_FULL_REG: case SP_DMA_BUSY_REG: return; From 49871d4e34f0ee726598dd61e68c1e443a87c10c Mon Sep 17 00:00:00 2001 From: GhostlyDark <31742919+GhostlyDark@users.noreply.github.com> Date: Fri, 26 Jan 2024 16:57:24 +0100 Subject: [PATCH 2/5] Fixed read/write to RSP PC register from CPU Co-Authored-By: Matt Pharoah --- src/device/rcp/rsp/rsp_core.c | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/src/device/rcp/rsp/rsp_core.c b/src/device/rcp/rsp/rsp_core.c index 5792c5920..fb0f5ac5a 100644 --- a/src/device/rcp/rsp/rsp_core.c +++ b/src/device/rcp/rsp/rsp_core.c @@ -295,6 +295,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) @@ -302,6 +306,10 @@ 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); } From 6f7320aee08b406186ba05151595148c890f62ef Mon Sep 17 00:00:00 2001 From: GhostlyDark <31742919+GhostlyDark@users.noreply.github.com> Date: Fri, 26 Jan 2024 17:01:44 +0100 Subject: [PATCH 3/5] Fixed behaviour when both setting and clearing STATUS bits at the same time Co-Authored-By: Matt Pharoah --- src/device/rcp/rsp/rsp_core.c | 50 +++++++++++++++++------------------ 1 file changed, 25 insertions(+), 25 deletions(-) diff --git a/src/device/rcp/rsp/rsp_core.c b/src/device/rcp/rsp/rsp_core.c index fb0f5ac5a..f96dae19f 100644 --- a/src/device/rcp/rsp/rsp_core.c +++ b/src/device/rcp/rsp/rsp_core.c @@ -137,65 +137,65 @@ 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) /* 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)) From 4dab3e2315dfa8edaa48da27a8bcccddba32c988 Mon Sep 17 00:00:00 2001 From: GhostlyDark <31742919+GhostlyDark@users.noreply.github.com> Date: Fri, 26 Jan 2024 17:08:10 +0100 Subject: [PATCH 4/5] Fixed contents of DMA related registers after a DMA completes Co-Authored-By: Matt Pharoah --- src/device/rcp/rsp/rsp_core.c | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/src/device/rcp/rsp/rsp_core.c b/src/device/rcp/rsp/rsp_core.c index f96dae19f..47d91178a 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 */ @@ -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; } From d0e3dc85740094009ca4810699f70c5321a23cdc Mon Sep 17 00:00:00 2001 From: GhostlyDark <31742919+GhostlyDark@users.noreply.github.com> Date: Sat, 27 Jan 2024 22:50:08 +0100 Subject: [PATCH 5/5] Fixed rsp_core.c related porting mistakes --- src/device/rcp/rsp/rsp_core.c | 16 +++++++--------- 1 file changed, 7 insertions(+), 9 deletions(-) diff --git a/src/device/rcp/rsp/rsp_core.c b/src/device/rcp/rsp/rsp_core.c index 47d91178a..270fd6520 100644 --- a/src/device/rcp/rsp/rsp_core.c +++ b/src/device/rcp/rsp/rsp_core.c @@ -65,9 +65,9 @@ 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; + sp->regs[SP_MEM_ADDR_REG] = memaddr & 0xfff; + sp->regs[SP_DRAM_ADDR_REG] = dramaddr & 0xffffff; + sp->regs[SP_RD_LEN_REG] = 0xff8; } else { @@ -82,9 +82,9 @@ 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; + 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 */ @@ -172,7 +172,7 @@ static void update_sp_status(struct rsp_core* sp, uint32_t w) /* clear / set signal 0 */ if ((w & 0x600) == 0x200) sp->regs[SP_STATUS_REG] &= ~SP_STATUS_SIG0; - if ((w & 0x600) == 0x400) + if ((w & 0x600) == 0x400) sp->regs[SP_STATUS_REG] |= SP_STATUS_SIG0; /* clear / set signal 1 */ if ((w & 0x1800) == 0x800) sp->regs[SP_STATUS_REG] &= ~SP_STATUS_SIG1; @@ -276,7 +276,6 @@ void write_rsp_regs(void* opaque, uint32_t address, uint32_t value, uint32_t mas { case SP_STATUS_REG: update_sp_status(sp, value & mask); - return; case SP_DMA_FULL_REG: case SP_DMA_BUSY_REG: return; @@ -319,7 +318,6 @@ void write_rsp_regs2(void* opaque, uint32_t address, uint32_t value, uint32_t ma if (reg == SP_PC_REG) mask &= 0xffc; - masked_write(&sp->regs2[reg], value, mask); }