static void nmi_int_handler(void) { // Non Maskable Interrupt -- remove interrupt event from queue remove_interupt_event(); // setup r4300 Status flags: reset TS and SR, set BEV, ERL, and SR g_cp0_regs[CP0_STATUS_REG] = (g_cp0_regs[CP0_STATUS_REG] & ~UINT32_C(0x00380000)) | UINT32_C(0x00500004); g_cp0_regs[CP0_CAUSE_REG] = 0x00000000; // simulate the soft reset code which would run from the PIF ROM r4300_reset_soft(); // clear all interrupts, reset interrupt counters back to 0 g_cp0_regs[CP0_COUNT_REG] = 0; g_gs_vi_counter = 0; init_interupt(); // clear the audio status register so that subsequent write_ai() calls will work properly g_ai.regs[AI_STATUS_REG] = 0; // set ErrorEPC with the last instruction address g_cp0_regs[CP0_ERROREPC_REG] = PC->addr; // reset the r4300 internal state if (r4300emu != CORE_PURE_INTERPRETER) { // clear all the compiled instruction blocks and re-initialize free_blocks(); init_blocks(); } // adjust ErrorEPC if we were in a delay slot, and clear the delay_slot and dyna_interp flags if(delay_slot==1 || delay_slot==3) { g_cp0_regs[CP0_ERROREPC_REG]-=4; } delay_slot = 0; dyna_interp = 0; // set next instruction address to reset vector last_addr = UINT32_C(0xa4000040); generic_jump_to(UINT32_C(0xa4000040)); }
static void nmi_int_handler(void) { /* Non Maskable Interrupt -- remove interrupt event from queue */ remove_interrupt_event(); /* setup r4300 Status flags: reset TS and SR, set BEV, ERL, and SR */ g_cp0_regs[CP0_STATUS_REG] = (g_cp0_regs[CP0_STATUS_REG] & ~(CP0_STATUS_SR | CP0_STATUS_TS | UINT32_C(0x00080000))) | (CP0_STATUS_ERL | CP0_STATUS_BEV | CP0_STATUS_SR); g_cp0_regs[CP0_CAUSE_REG] = 0x00000000; /* simulate the soft reset code which would run from the PIF ROM */ pifbootrom_hle_execute(&g_dev); /* clear all interrupts, reset interrupt counters back to 0 */ g_cp0_regs[CP0_COUNT_REG] = 0; g_gs_vi_counter = 0; init_interrupt(); g_dev.vi.delay = g_dev.vi.next_vi = 5000; add_interrupt_event_count(VI_INT, g_dev.vi.next_vi); /* clear the audio status register so that subsequent write_ai() calls will work properly */ g_dev.ai.regs[AI_STATUS_REG] = 0; /* set ErrorEPC with the last instruction address */ g_cp0_regs[CP0_ERROREPC_REG] = PC->addr; /* reset the r4300 internal state */ if (r4300emu != CORE_PURE_INTERPRETER) { /* clear all the compiled instruction blocks and re-initialize */ free_blocks(); init_blocks(); } /* adjust ErrorEPC if we were in a delay slot, and clear the delay_slot and dyna_interp flags */ if(g_dev.r4300.delay_slot==1 || g_dev.r4300.delay_slot==3) { g_cp0_regs[CP0_ERROREPC_REG]-=4; } g_dev.r4300.delay_slot = 0; dyna_interp = 0; /* set next instruction address to reset vector */ last_addr = UINT32_C(0xa4000040); generic_jump_to(UINT32_C(0xa4000040)); #ifdef NEW_DYNAREC if (r4300emu == CORE_DYNAREC) { g_cp0_regs[CP0_ERROREPC_REG]=(pcaddr&~3)-(pcaddr&1)*4; pcaddr = 0xa4000040; pending_exception = 1; invalidate_all_pages(); } #endif }
void reset_hard(void) { poweron_device(&g_dev); pifbootrom_hle_execute(&g_dev); last_addr = UINT32_C(0xa4000040); next_interrupt = 624999; init_interrupt(); g_dev.vi.delay = g_dev.vi.next_vi = 5000; add_interrupt_event_count(VI_INT, g_dev.vi.next_vi); if(r4300emu != CORE_PURE_INTERPRETER) { free_blocks(); init_blocks(); } generic_jump_to(last_addr); }
void gen_interupt(void) { if (stop == 1) { vi_counter = 0; // debug dyna_stop(); } if (!interupt_unsafe_state) { if (savestates_get_job() == savestates_job_load) { savestates_load(); return; } if (reset_hard_job) { reset_hard(); reset_hard_job = 0; return; } } if (skip_jump) { unsigned int dest = skip_jump; skip_jump = 0; if (q->count > Count || (Count - q->count) < 0x80000000) next_interupt = q->count; else next_interupt = 0; last_addr = dest; generic_jump_to(dest); return; } switch(q->type) { case SPECIAL_INT: if (Count > 0x10000000) return; remove_interupt_event(); add_interupt_event_count(SPECIAL_INT, 0); return; break; case VI_INT: if(vi_counter < 60) { if (vi_counter == 0) cheat_apply_cheats(ENTRY_BOOT); vi_counter++; } else { cheat_apply_cheats(ENTRY_VI); } gfx.updateScreen(); #ifdef WITH_LIRC lircCheckInput(); #endif SDL_PumpEvents(); refresh_stat(); // if paused, poll for input events if(rompause) { osd_render(); // draw Paused message in case gfx.updateScreen didn't do it VidExt_GL_SwapBuffers(); while(rompause) { SDL_Delay(10); SDL_PumpEvents(); #ifdef WITH_LIRC lircCheckInput(); #endif //WITH_LIRC } } new_vi(); if (vi_register.vi_v_sync == 0) vi_register.vi_delay = 500000; else vi_register.vi_delay = ((vi_register.vi_v_sync + 1)*1500); next_vi += vi_register.vi_delay; if (vi_register.vi_status&0x40) vi_field=1-vi_field; else vi_field=0; remove_interupt_event(); add_interupt_event_count(VI_INT, next_vi); MI_register.mi_intr_reg |= 0x08; if (MI_register.mi_intr_reg & MI_register.mi_intr_mask_reg) Cause = (Cause | 0x400) & 0xFFFFFF83; else return; if ((Status & 7) != 1) return; if (!(Status & Cause & 0xFF00)) return; break; case COMPARE_INT: remove_interupt_event(); Count+=count_per_op; add_interupt_event_count(COMPARE_INT, Compare); Count-=count_per_op; Cause = (Cause | 0x8000) & 0xFFFFFF83; if ((Status & 7) != 1) return; if (!(Status & Cause & 0xFF00)) return; break; case CHECK_INT: remove_interupt_event(); break; case SI_INT: #ifdef WITH_LIRC lircCheckInput(); #endif //WITH_LIRC SDL_PumpEvents(); PIF_RAMb[0x3F] = 0x0; remove_interupt_event(); MI_register.mi_intr_reg |= 0x02; si_register.si_stat |= 0x1000; if (MI_register.mi_intr_reg & MI_register.mi_intr_mask_reg) Cause = (Cause | 0x400) & 0xFFFFFF83; else return; if ((Status & 7) != 1) return; if (!(Status & Cause & 0xFF00)) return; break; case PI_INT: remove_interupt_event(); MI_register.mi_intr_reg |= 0x10; pi_register.read_pi_status_reg &= ~3; if (MI_register.mi_intr_reg & MI_register.mi_intr_mask_reg) Cause = (Cause | 0x400) & 0xFFFFFF83; else return; if ((Status & 7) != 1) return; if (!(Status & Cause & 0xFF00)) return; break; case AI_INT: if (ai_register.ai_status & 0x80000000) // full { unsigned int ai_event = get_event(AI_INT); remove_interupt_event(); ai_register.ai_status &= ~0x80000000; ai_register.current_delay = ai_register.next_delay; ai_register.current_len = ai_register.next_len; add_interupt_event_count(AI_INT, ai_event+ai_register.next_delay); MI_register.mi_intr_reg |= 0x04; if (MI_register.mi_intr_reg & MI_register.mi_intr_mask_reg) Cause = (Cause | 0x400) & 0xFFFFFF83; else return; if ((Status & 7) != 1) return; if (!(Status & Cause & 0xFF00)) return; } else { remove_interupt_event(); ai_register.ai_status &= ~0x40000000; //------- MI_register.mi_intr_reg |= 0x04; if (MI_register.mi_intr_reg & MI_register.mi_intr_mask_reg) Cause = (Cause | 0x400) & 0xFFFFFF83; else return; if ((Status & 7) != 1) return; if (!(Status & Cause & 0xFF00)) return; } break; case SP_INT: remove_interupt_event(); sp_register.sp_status_reg |= 0x203; // sp_register.sp_status_reg |= 0x303; if (!(sp_register.sp_status_reg & 0x40)) return; // !intr_on_break MI_register.mi_intr_reg |= 0x01; if (MI_register.mi_intr_reg & MI_register.mi_intr_mask_reg) Cause = (Cause | 0x400) & 0xFFFFFF83; else return; if ((Status & 7) != 1) return; if (!(Status & Cause & 0xFF00)) return; break; case DP_INT: remove_interupt_event(); dpc_register.dpc_status &= ~2; dpc_register.dpc_status |= 0x81; MI_register.mi_intr_reg |= 0x20; if (MI_register.mi_intr_reg & MI_register.mi_intr_mask_reg) Cause = (Cause | 0x400) & 0xFFFFFF83; else return; if ((Status & 7) != 1) return; if (!(Status & Cause & 0xFF00)) return; break; case HW2_INT: // Hardware Interrupt 2 -- remove interrupt event from queue remove_interupt_event(); // setup r4300 Status flags: reset TS, and SR, set IM2 Status = (Status & ~0x00380000) | 0x1000; Cause = (Cause | 0x1000) & 0xFFFFFF83; /* the exception_general() call below will jump to the interrupt vector (0x80000180) and setup the * interpreter or dynarec */ break; case NMI_INT: // Non Maskable Interrupt -- remove interrupt event from queue remove_interupt_event(); // setup r4300 Status flags: reset TS and SR, set BEV, ERL, and SR Status = (Status & ~0x00380000) | 0x00500004; Cause = 0x00000000; // simulate the soft reset code which would run from the PIF ROM r4300_reset_soft(); // clear all interrupts, reset interrupt counters back to 0 Count = 0; vi_counter = 0; init_interupt(); // clear the audio status register so that subsequent write_ai() calls will work properly ai_register.ai_status = 0; // set ErrorEPC with the last instruction address ErrorEPC = PC->addr; // reset the r4300 internal state if (r4300emu != CORE_PURE_INTERPRETER) { // clear all the compiled instruction blocks and re-initialize free_blocks(); init_blocks(); } // adjust ErrorEPC if we were in a delay slot, and clear the delay_slot and dyna_interp flags if(delay_slot==1 || delay_slot==3) { ErrorEPC-=4; } delay_slot = 0; dyna_interp = 0; // set next instruction address to reset vector last_addr = 0xa4000040; generic_jump_to(0xa4000040); return; default: DebugMessage(M64MSG_ERROR, "Unknown interrupt queue event type %.8X.", q->type); remove_interupt_event(); break; } #ifdef NEW_DYNAREC if (r4300emu == CORE_DYNAREC) { EPC = pcaddr; pcaddr = 0x80000180; Status |= 2; Cause &= 0x7FFFFFFF; pending_exception=1; } else { exception_general(); } #else exception_general(); #endif if (!interupt_unsafe_state) { if (savestates_get_job() == savestates_job_save) { savestates_save(); return; } } }
void gen_interrupt(void) { if (stop == 1) { g_gs_vi_counter = 0; /* debug */ dyna_stop(); } if (!interrupt_unsafe_state) { if (reset_hard_job) { reset_hard(); reset_hard_job = 0; return; } } if (skip_jump) { uint32_t dest = skip_jump; uint32_t count = g_cp0_regs[CP0_COUNT_REG]; skip_jump = 0; next_interrupt = (q.first->data.count > count || (count - q.first->data.count) < UINT32_C(0x80000000)) ? q.first->data.count : 0; last_addr = dest; generic_jump_to(dest); return; } switch(q.first->data.type) { case SPECIAL_INT: special_int_handler(); break; case VI_INT: remove_interrupt_event(); vi_vertical_interrupt_event(&g_dev.vi); retro_return(false); break; case COMPARE_INT: compare_int_handler(); break; case CHECK_INT: remove_interrupt_event(); wrapped_exception_general(); break; case SI_INT: remove_interrupt_event(); si_end_of_dma_event(&g_dev.si); break; case PI_INT: remove_interrupt_event(); pi_end_of_dma_event(&g_dev.pi); break; case AI_INT: remove_interrupt_event(); ai_end_of_dma_event(&g_dev.ai); break; case SP_INT: remove_interrupt_event(); rsp_interrupt_event(&g_dev.sp); break; case DP_INT: remove_interrupt_event(); rdp_interrupt_event(&g_dev.dp); break; case HW2_INT: hw2_int_handler(); break; case NMI_INT: nmi_int_handler(); break; case CART_INT: g_cp0_regs[CP0_CAUSE_REG] |= 0x00000800; /* set IP3 */ g_cp0_regs[CP0_CAUSE_REG] &= 0xFFFFFF83; /* mask out old exception code */ remove_interrupt_event(); #if 0 if (dd_end_of_dma_event(&g_dd) == 1) { remove_interrupt_event(); g_cp0_regs[CP0_CAUSE_REG] &= ~0x00000800; } #endif break; default: DebugMessage(M64MSG_ERROR, "Unknown interrupt queue event type %.8X.", q.first->data.type); remove_interrupt_event(); wrapped_exception_general(); break; } }
void gen_interupt(void) { if (stop == 1) { g_gs_vi_counter = 0; // debug dyna_stop(); } if (!interupt_unsafe_state) { if (savestates_get_job() == savestates_job_load) { savestates_load(); return; } if (reset_hard_job) { reset_hard(); reset_hard_job = 0; return; } } if (skip_jump) { uint32_t dest = skip_jump; skip_jump = 0; next_interupt = (q.first->data.count > g_cp0_regs[CP0_COUNT_REG] || (g_cp0_regs[CP0_COUNT_REG] - q.first->data.count) < UINT32_C(0x80000000)) ? q.first->data.count : 0; last_addr = dest; generic_jump_to(dest); return; } switch(q.first->data.type) { case SPECIAL_INT: special_int_handler(); break; case VI_INT: remove_interupt_event(); vi_vertical_interrupt_event(&g_vi); break; case COMPARE_INT: compare_int_handler(); break; case CHECK_INT: remove_interupt_event(); wrapped_exception_general(); break; case SI_INT: remove_interupt_event(); si_end_of_dma_event(&g_si); break; case PI_INT: remove_interupt_event(); pi_end_of_dma_event(&g_pi); break; case AI_INT: remove_interupt_event(); ai_end_of_dma_event(&g_ai); break; case SP_INT: remove_interupt_event(); rsp_interrupt_event(&g_sp); break; case DP_INT: remove_interupt_event(); rdp_interrupt_event(&g_dp); break; case HW2_INT: hw2_int_handler(); break; case NMI_INT: nmi_int_handler(); break; default: DebugMessage(M64MSG_ERROR, "Unknown interrupt queue event type %.8X.", q.first->data.type); remove_interupt_event(); wrapped_exception_general(); break; } if (!interupt_unsafe_state) { if (savestates_get_job() == savestates_job_save) { savestates_save(); return; } } }
void osal_fastcall gen_interupt(usf_state_t * state) { if (state->stop == 1) { state->g_gs_vi_counter = 0; // debug dyna_stop(state); } if (!state->interupt_unsafe_state) { if (state->reset_hard_job) { reset_hard(state); state->reset_hard_job = 0; return; } } if (state->skip_jump) { unsigned int dest = state->skip_jump; state->skip_jump = 0; state->next_interupt = (state->q.first->data.count > state->g_cp0_regs[CP0_COUNT_REG] || (state->g_cp0_regs[CP0_COUNT_REG] - state->q.first->data.count) < 0x80000000) ? state->q.first->data.count : 0; state->last_addr = dest; generic_jump_to(state, dest); return; } switch(state->q.first->data.type) { case SPECIAL_INT: special_int_handler(state); break; case VI_INT: remove_interupt_event(state); vi_vertical_interrupt_event(&state->g_vi); break; case COMPARE_INT: compare_int_handler(state); break; case CHECK_INT: remove_interupt_event(state); wrapped_exception_general(state); break; case SI_INT: remove_interupt_event(state); si_end_of_dma_event(&state->g_si); break; case PI_INT: remove_interupt_event(state); pi_end_of_dma_event(&state->g_pi); break; case AI_INT: remove_interupt_event(state); ai_end_of_dma_event(&state->g_ai); break; case SP_INT: remove_interupt_event(state); rsp_interrupt_event(&state->g_sp); break; case DP_INT: remove_interupt_event(state); rdp_interrupt_event(&state->g_dp); break; case HW2_INT: hw2_int_handler(state); break; case NMI_INT: nmi_int_handler(state); break; default: DebugMessage(state, M64MSG_ERROR, "Unknown interrupt queue event type %.8X.", state->q.first->data.type); remove_interupt_event(state); wrapped_exception_general(state); break; } }