Compare commits

...

5 commits

Author SHA1 Message Date
GhostlyDark d8cb2faa9e Fixed rsp_core.c related porting mistakes 2024-05-03 16:52:54 +02:00
GhostlyDark b272296ba6 Fixed contents of DMA related registers after a DMA completes
Co-Authored-By: Matt Pharoah <mtpharoah@gmail.com>
2024-05-03 16:52:54 +02:00
GhostlyDark d6a2668b6e Fixed behaviour when both setting and clearing STATUS bits at the same time
Co-Authored-By: Matt Pharoah <mtpharoah@gmail.com>
2024-05-03 16:52:54 +02:00
GhostlyDark c65c330381 Fixed read/write to RSP PC register from CPU
Co-Authored-By: Matt Pharoah <mtpharoah@gmail.com>
2024-05-03 16:52:54 +02:00
GhostlyDark 07d85c1b21 Fixed incorrect handling of BREAK bit in the RSP status register
Co-Authored-By: Matt Pharoah <mtpharoah@gmail.com>
2024-05-03 16:52:54 +02:00

View file

@ -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);
}