diff --git a/mupen64plus-core/src/device/device.c b/mupen64plus-core/src/device/device.c index 4a5988e..8b997ff 100644 --- a/mupen64plus-core/src/device/device.c +++ b/mupen64plus-core/src/device/device.c @@ -124,6 +124,7 @@ void init_device(struct device* dev, { &dev->dd, dd_mecha_int_handler }, /* DD MECHA */ { &dev->dd, dd_bm_int_handler }, /* DD BM */ { &dev->dd, dd_dv_int_handler }, /* DD DRIVE */ + { &dev->sp, rsp_task_event }, }; #define R(x) read_ ## x diff --git a/mupen64plus-core/src/device/r4300/cached_interp.c b/mupen64plus-core/src/device/r4300/cached_interp.c index 17283c6..f197609 100644 --- a/mupen64plus-core/src/device/r4300/cached_interp.c +++ b/mupen64plus-core/src/device/r4300/cached_interp.c @@ -150,13 +150,8 @@ void cached_interp_##name##_IDLE(void) \ { \ if(*cp0_cycle_count < 0) \ { \ - int target = *cp0_cycle_count; \ - if (target < r4300->sp->next_rsp_run && r4300->sp->next_rsp_run < 0) \ - { \ - target = r4300->sp->next_rsp_run; \ - } \ - cp0_regs[CP0_COUNT_REG] -= target; \ - *cp0_cycle_count -= target; \ + cp0_regs[CP0_COUNT_REG] -= *cp0_cycle_count; \ + *cp0_cycle_count = 0; \ } \ } \ cached_interp_##name(); \ diff --git a/mupen64plus-core/src/device/r4300/cp0.h b/mupen64plus-core/src/device/r4300/cp0.h index f1c915a..fa236af 100644 --- a/mupen64plus-core/src/device/r4300/cp0.h +++ b/mupen64plus-core/src/device/r4300/cp0.h @@ -173,7 +173,7 @@ struct interrupt_handler void (*callback)(void*); }; -enum { CP0_INTERRUPT_HANDLERS_COUNT = 16 }; +enum { CP0_INTERRUPT_HANDLERS_COUNT = 17 }; enum { INTR_UNSAFE_R4300 = 0x01, diff --git a/mupen64plus-core/src/device/r4300/icache.c b/mupen64plus-core/src/device/r4300/icache.c index bbd3517..a3d9dc1 100644 --- a/mupen64plus-core/src/device/r4300/icache.c +++ b/mupen64plus-core/src/device/r4300/icache.c @@ -25,7 +25,6 @@ #include "device/rdram/rdram.h" #include "device/r4300/cached_interp.h" #include "device/memory/memory.h" -#include "device/rcp/rsp/rsp_core.h" void poweron_icache(struct instcache *lines) { @@ -72,8 +71,6 @@ void icache_fill(struct instcache *line, struct r4300_core* r4300, uint32_t addr // This code is performance critical, so for the cached interpreter, we used a version that doesn't need to return anything in order to save some CPU void icache_step(struct r4300_core* r4300) { - if (!r4300->sp->rsp_wait) - do_SP_Task(r4300->sp); cp0_base_cycle(r4300); struct precomp_instr *inst = (*r4300_pc_struct(r4300)); uint32_t address = inst->phys_addr; @@ -92,8 +89,6 @@ void icache_step(struct r4300_core* r4300) uint32_t* icache_fetch(struct r4300_core* r4300, uint32_t address) { - if (!r4300->sp->rsp_wait) - do_SP_Task(r4300->sp); cp0_base_cycle(r4300); if (r4300_translate_address(r4300, &address, &r4300->cached, 2)) return NULL; diff --git a/mupen64plus-core/src/device/r4300/interrupt.c b/mupen64plus-core/src/device/r4300/interrupt.c index abfc122..9ca90fe 100644 --- a/mupen64plus-core/src/device/r4300/interrupt.c +++ b/mupen64plus-core/src/device/r4300/interrupt.c @@ -656,6 +656,11 @@ void gen_interrupt(struct r4300_core* r4300) call_interrupt_handler(&r4300->cp0, 15); break; + case RSP_TSK_EVT: + remove_interrupt_event(&r4300->cp0); + call_interrupt_handler(&r4300->cp0, 16); + break; + default: DebugMessage(M64MSG_ERROR, "Unknown interrupt queue event type %.8X.", r4300->cp0.q.first->data.type); remove_interrupt_event(&r4300->cp0); diff --git a/mupen64plus-core/src/device/r4300/interrupt.h b/mupen64plus-core/src/device/r4300/interrupt.h index 3963cdc..bf8631b 100644 --- a/mupen64plus-core/src/device/r4300/interrupt.h +++ b/mupen64plus-core/src/device/r4300/interrupt.h @@ -69,5 +69,6 @@ void nmi_int_handler(void* opaque); #define DD_MC_INT 0x1000 #define DD_BM_INT 0x2000 #define DD_DV_INT 0x4000 +#define RSP_TSK_EVT 0x8000 #endif /* M64P_DEVICE_R4300_INTERRUPT_H */ diff --git a/mupen64plus-core/src/device/r4300/pure_interp.c b/mupen64plus-core/src/device/r4300/pure_interp.c index fb4460c..c6951b1 100644 --- a/mupen64plus-core/src/device/r4300/pure_interp.c +++ b/mupen64plus-core/src/device/r4300/pure_interp.c @@ -85,16 +85,11 @@ static void InterpretOpcode(struct r4300_core* r4300); if (cop1 && check_cop1_unusable(r4300)) return; \ if (take_jump) \ { \ - if(*cp0_cycle_count < 0) \ - { \ - int target = *cp0_cycle_count; \ - if (target < r4300->sp->next_rsp_run && r4300->sp->next_rsp_run < 0) \ - { \ - target = r4300->sp->next_rsp_run; \ - } \ - cp0_regs[CP0_COUNT_REG] -= target; \ - *cp0_cycle_count -= target; \ - } \ + if(*cp0_cycle_count < 0) \ + { \ + cp0_regs[CP0_COUNT_REG] -= *cp0_cycle_count; \ + *cp0_cycle_count = 0; \ + } \ } \ name(r4300, op); \ } diff --git a/mupen64plus-core/src/device/rcp/rdp/rdp_core.c b/mupen64plus-core/src/device/rcp/rdp/rdp_core.c index 749f0c5..ef87166 100644 --- a/mupen64plus-core/src/device/rcp/rdp/rdp_core.c +++ b/mupen64plus-core/src/device/rcp/rdp/rdp_core.c @@ -44,8 +44,9 @@ static void update_dpc_status(struct rdp_core* dp, uint32_t w) { gfx.fullSync(); dp->mi->r4300->cp0.interrupt_unsafe_state &= ~INTR_UNSAFE_RDP; - dp->sp->rsp_wait &= ~WAIT_PENDING_DP_SYNC; signal_rcp_interrupt(dp->mi, MI_INTR_DP); + + clear_rsp_wait(dp->sp, WAIT_PENDING_DP_SYNC); } if (dp->do_on_unfreeze & DELAY_UPDATESCREEN) gfx.updateScreen(); @@ -189,7 +190,8 @@ void rdp_interrupt_event(void* opaque) gfx.fullSync(); dp->mi->r4300->cp0.interrupt_unsafe_state &= ~INTR_UNSAFE_RDP; - dp->sp->rsp_wait &= ~WAIT_PENDING_DP_SYNC; raise_rcp_interrupt(dp->mi, MI_INTR_DP); + + clear_rsp_wait(dp->sp, WAIT_PENDING_DP_SYNC); } diff --git a/mupen64plus-core/src/device/rcp/rsp/rsp_core.c b/mupen64plus-core/src/device/rcp/rsp/rsp_core.c index 56a9087..c18a58e 100644 --- a/mupen64plus-core/src/device/rcp/rsp/rsp_core.c +++ b/mupen64plus-core/src/device/rcp/rsp/rsp_core.c @@ -147,7 +147,6 @@ static void update_sp_status(struct rsp_core* sp, uint32_t w) remove_event(&sp->mi->r4300->cp0.q, SP_INT); sp->rsp_status = 0; sp->first_run = 1; - sp->next_rsp_run = 0; sp->rsp_wait |= WAIT_HALTED; sp->regs[SP_STATUS_REG] |= SP_STATUS_HALT; } @@ -217,6 +216,8 @@ static void update_sp_status(struct rsp_core* sp, uint32_t w) /* clear / set signal 7 */ if ((w & SP_CLR_SIG7) && !(w & SP_SET_SIG7)) sp->regs[SP_STATUS_REG] &= ~SP_STATUS_SIG7; if ((w & SP_SET_SIG7) && !(w & SP_CLR_SIG7)) sp->regs[SP_STATUS_REG] |= SP_STATUS_SIG7; + + do_SP_Task(sp); } void init_rsp(struct rsp_core* sp, @@ -240,8 +241,6 @@ void poweron_rsp(struct rsp_core* sp) sp->rsp_status = 0; sp->first_run = 1; - sp->next_rsp_run = 0; - sp->last_cp0_count = 0; sp->rsp_wait = 0; sp->mi->r4300->cp0.interrupt_unsafe_state &= ~INTR_UNSAFE_RSP; sp->regs[SP_STATUS_REG] = 1; @@ -337,10 +336,9 @@ void write_rsp_regs2(void* opaque, uint32_t address, uint32_t value, uint32_t ma void do_SP_Task(struct rsp_core* sp) { - const uint32_t* cp0_regs = r4300_cp0_regs(&sp->mi->r4300->cp0); - sp->next_rsp_run += cp0_regs[CP0_COUNT_REG] - sp->last_cp0_count; - sp->last_cp0_count = cp0_regs[CP0_COUNT_REG]; - if (sp->next_rsp_run < 0) + if (sp->rsp_wait) + return; + if (get_event(&sp->mi->r4300->cp0.q, RSP_TSK_EVT)) return; uint32_t saved_status = sp->regs[SP_STATUS_REG]; @@ -366,13 +364,12 @@ void do_SP_Task(struct rsp_core* sp) sp->rsp_status = sp->regs[SP_STATUS_REG]; if ((sp->regs[SP_STATUS_REG] & SP_STATUS_HALT) == 0) { - sp->next_rsp_run = rsp_cycles * -1; + add_interrupt_event(&sp->mi->r4300->cp0, RSP_TSK_EVT, rsp_cycles); sp->first_run = 0; } else { sp->rsp_wait |= WAIT_HALTED; - sp->next_rsp_run = 0; sp->first_run = 1; } if ((sp->regs[SP_STATUS_REG] & SP_STATUS_BROKE) && (sp->regs[SP_STATUS_REG] & SP_STATUS_INTR_BREAK)) @@ -399,7 +396,8 @@ void rsp_interrupt_event(void* opaque) sp->rsp_status = 0; sp->mi->r4300->cp0.interrupt_unsafe_state &= ~INTR_UNSAFE_RSP; raise_rcp_interrupt(sp->mi, MI_INTR_SP); - sp->rsp_wait &= ~(WAIT_PENDING_SP_INT | WAIT_PENDING_SP_INT_BROKE); + + clear_rsp_wait(sp, WAIT_PENDING_SP_INT | WAIT_PENDING_SP_INT_BROKE); } void rsp_end_of_dma_event(void* opaque) @@ -407,3 +405,17 @@ void rsp_end_of_dma_event(void* opaque) struct rsp_core* sp = (struct rsp_core*)opaque; fifo_pop(sp); } + +void rsp_task_event(void* opaque) +{ + struct rsp_core* sp = (struct rsp_core*)opaque; + + do_SP_Task(sp); +} + +void clear_rsp_wait(struct rsp_core* sp, uint32_t value) +{ + sp->rsp_wait &= ~value; + + do_SP_Task(sp); +} diff --git a/mupen64plus-core/src/device/rcp/rsp/rsp_core.h b/mupen64plus-core/src/device/rcp/rsp/rsp_core.h index 4c65267..40c77c5 100644 --- a/mupen64plus-core/src/device/rcp/rsp/rsp_core.h +++ b/mupen64plus-core/src/device/rcp/rsp/rsp_core.h @@ -136,8 +136,6 @@ struct rsp_core uint32_t regs2[SP_REGS2_COUNT]; uint32_t rsp_status; uint32_t first_run; - uint32_t last_cp0_count; - int32_t next_rsp_run; uint32_t rsp_wait; struct mi_controller* mi; @@ -183,4 +181,7 @@ void do_SP_Task(struct rsp_core* sp); void rsp_interrupt_event(void* opaque); void rsp_end_of_dma_event(void* opaque); +void rsp_task_event(void* opaque); +void clear_rsp_wait(struct rsp_core* sp, uint32_t value); + #endif diff --git a/mupen64plus-core/src/main/savestates.c b/mupen64plus-core/src/main/savestates.c index 0fc1664..c236bed 100644 --- a/mupen64plus-core/src/main/savestates.c +++ b/mupen64plus-core/src/main/savestates.c @@ -200,7 +200,7 @@ static int savestates_load_m64p(struct device* dev, char *filepath) char queue[1024]; unsigned char using_tlb_data[4]; unsigned char data_0001_0200[4096]; // 4k for extra state from v1.2 - unsigned char data_0001_0900[2129960]; // extra state from v1.9 + unsigned char data_0001_0900[2129952]; // extra state from v1.9 uint32_t* cp0_regs = r4300_cp0_regs(&dev->r4300.cp0); @@ -911,8 +911,6 @@ static int savestates_load_m64p(struct device* dev, char *filepath) /* extra sp state */ dev->sp.rsp_status = GETDATA(curr, uint32_t); dev->sp.first_run = GETDATA(curr, uint32_t); - dev->sp.last_cp0_count = GETDATA(curr, uint32_t); - dev->sp.next_rsp_run = GETDATA(curr, int32_t); dev->sp.rsp_wait = GETDATA(curr, uint32_t); /* extra fpu state */ @@ -1153,7 +1151,7 @@ static int savestates_save_m64p(const struct device* dev, char *filepath) save_eventqueue_infos(&dev->r4300.cp0, queue); // Allocate memory for the save state data - save->size = 16788288 + sizeof(queue) + 4 + 4096 + 2129960; + save->size = 16788288 + sizeof(queue) + 4 + 4096 + 2129952; save->data = curr = malloc(save->size); if (save->data == NULL) { @@ -1546,8 +1544,6 @@ static int savestates_save_m64p(const struct device* dev, char *filepath) /* extra sp state */ PUTDATA(curr, uint32_t, dev->sp.rsp_status); PUTDATA(curr, uint32_t, dev->sp.first_run); - PUTDATA(curr, uint32_t, dev->sp.last_cp0_count); - PUTDATA(curr, int32_t, dev->sp.next_rsp_run); PUTDATA(curr, uint32_t, dev->sp.rsp_wait); /* extra fpu state */