void load_eventqueue_infos(char *buf) { int len = 0; int i=0; clear_queue(); //load the stack with the addresses of available slots for (i =0; i < QUEUE_SIZE; i++) { qstack[i] = &qbase[i]; } while (*((unsigned int*)&buf[len]) != 0xFFFFFFFF) { int type = *((unsigned int*)&buf[len]); unsigned int count = *((unsigned int*)&buf[len+4]); switch (type) { #ifdef USE_COMPARE case COMPARE_INT: add_interupt_event_count(COMPARE_INT, count); break; #endif #ifdef USE_SPECIAL case SPECIAL_INT: add_interupt_event_count(SPECIAL_INT, count); break; #endif #ifdef USE_CHECK case CHECK_INT: add_interupt_event_count(CHECK_INT, count); break; #endif default: add_interupt_event_count(type, count); } len += 8; } }
void init_interupt(void) { if (qbase != NULL) free(qbase); qbase = (interupt_queue *) malloc(sizeof(interupt_queue) * QUEUE_SIZE ); memset(qbase,0,sizeof(interupt_queue) * QUEUE_SIZE ); qstackindex=0; int i=0; //load the stack with the addresses of available slots for (i =0; i < QUEUE_SIZE; i++) { qstack[i] = &qbase[i]; } #ifdef USE_SPECIAL SPECIAL_done = 1; #endif next_vi = next_interupt = 5000; vi_register.vi_delay = next_vi; vi_field = 0; //clear_queue(); add_interupt_event_count(VI_INT, next_vi); #ifdef USE_SPECIAL add_interupt_event_count(SPECIAL_INT, 0); #endif }
void init_interupt(usf_state_t * state) { state->SPECIAL_done = 1; state->g_vi.delay = state->g_vi.next_vi = 5000; clear_queue(state); add_interupt_event_count(state, VI_INT, state->g_vi.next_vi); add_interupt_event_count(state, SPECIAL_INT, 0); }
void init_interupt(void) { SPECIAL_done = 1; g_vi.delay = g_vi.next_vi = 5000; clear_queue(); add_interupt_event_count(VI_INT, g_vi.next_vi); add_interupt_event_count(SPECIAL_INT, 0); }
void init_interupt() { SPECIAL_done = 1; next_vi = next_interupt = 5000; vi_register.vi_delay = next_vi; vi_field = 0; clear_queue(); add_interupt_event_count(VI_INT, next_vi); add_interupt_event_count(SPECIAL_INT, 0); }
void translate_event_queue(unsigned long base) { interupt_queue *aux; remove_event(COMPARE_INT); remove_event(SPECIAL_INT); aux=q; while (aux != NULL) { aux->count = (aux->count - Count)+base; aux = aux->next; } add_interupt_event_count(COMPARE_INT, Compare); add_interupt_event_count(SPECIAL_INT, 0); }
void translate_event_queue(unsigned int base) { struct node *e; remove_event(COMPARE_INT); remove_event(SPECIAL_INT); for(e = q.first; e != NULL; e = e->next) e->data.count = (e->data.count - g_cp0_regs[CP0_COUNT_REG]) + base; add_interupt_event_count(COMPARE_INT, g_cp0_regs[CP0_COMPARE_REG]); add_interupt_event_count(SPECIAL_INT, 0); }
void init_interupt() { SPECIAL_done = 1; next_vi = next_interupt = 5000; vi_register.vi_delay = next_vi; vi_field = 0; if (qbase != NULL) free(qbase); qbase = (interupt_queue *) malloc(sizeof(interupt_queue) * QUEUE_SIZE ); memset(qbase,0,sizeof(interupt_queue) * QUEUE_SIZE ); qstackindex=0; clear_queue(); add_interupt_event_count(VI_INT, next_vi); add_interupt_event_count(SPECIAL_INT, 0); }
void translate_event_queue(usf_state_t * state, unsigned int base) { struct node* e; remove_event(state, COMPARE_INT); remove_event(state, SPECIAL_INT); for(e = state->q.first; e != NULL; e = e->next) { e->data.count = (e->data.count - state->g_cp0_regs[CP0_COUNT_REG]) + base; } add_interupt_event_count(state, COMPARE_INT, state->g_cp0_regs[CP0_COMPARE_REG]); add_interupt_event_count(state, SPECIAL_INT, 0); }
void load_eventqueue_infos(char *buf) { int len = 0; //clear_queue(); if (qbase != NULL) free(qbase); qbase = (interupt_queue *) malloc(sizeof(interupt_queue) * QUEUE_SIZE ); memset(qbase,0,sizeof(interupt_queue) * QUEUE_SIZE ); qstackindex=0; int i=0; //load the stack with the addresses of available slots for (i =0; i < QUEUE_SIZE; i++) { qstack[i] = &qbase[i]; } while (*((unsigned int*)&buf[len]) != 0xFFFFFFFF) { int type = *((unsigned int*)&buf[len]); unsigned int count = *((unsigned int*)&buf[len+4]); add_interupt_event_count(type, count); len += 8; } }
static void special_int_handler(void) { if (g_cp0_regs[CP0_COUNT_REG] > UINT32_C(0x10000000)) return; SPECIAL_done = 1; remove_interupt_event(); add_interupt_event_count(SPECIAL_INT, 0); }
static void compare_int_handler(void) { remove_interupt_event(); g_cp0_regs[CP0_COUNT_REG]+=count_per_op; add_interupt_event_count(COMPARE_INT, g_cp0_regs[CP0_COMPARE_REG]); g_cp0_regs[CP0_COUNT_REG]-=count_per_op; raise_maskable_interrupt(UINT32_C(0x8000)); }
static void special_int_handler(usf_state_t * state) { if (state->g_cp0_regs[CP0_COUNT_REG] > 0x10000000) return; state->SPECIAL_done = 1; remove_interupt_event(state); add_interupt_event_count(state, SPECIAL_INT, 0); }
static void compare_int_handler(usf_state_t * state) { remove_interupt_event(state); state->g_cp0_regs[CP0_COUNT_REG]+=state->count_per_op; add_interupt_event_count(state, COMPARE_INT, state->g_cp0_regs[CP0_COMPARE_REG]); state->g_cp0_regs[CP0_COUNT_REG]-=state->count_per_op; if (state->enablecompare) raise_maskable_interrupt(state, 0x8000); }
// load the queue (for save states) void load_eventqueue_infos(char *buf) { unsigned int len = 0, type = 0, count = 0; clear_queue(); while (*((unsigned long*)&buf[len]) != 0xFFFFFFFF) { type = *((unsigned long*)&buf[len]); count = *((unsigned long*)&buf[len+4]); add_interupt_event_count(type, count); len += 8; } }
void load_eventqueue_infos(usf_state_t * state, char *buf) { int len = 0; clear_queue(state); while (*((unsigned int*)&buf[len]) != 0xFFFFFFFF) { int type = *((unsigned int*)&buf[len]); unsigned int count = *((unsigned int*)&buf[len+4]); add_interupt_event_count(state, type, count); len += 8; } }
void translate_event_queue(unsigned int base) { interupt_queue *aux; remove_event(COMPARE_INT); remove_event(SPECIAL_INT); aux=q; while (aux != NULL) { #ifdef NEW_COUNT aux->count = ((aux->count - Count)+base)& 0x7FFFFFFF; #else aux->count = (aux->count - Count)+base; #endif aux = aux->next; } #ifdef USE_COMPARE add_interupt_event_count(COMPARE_INT, Compare); #endif #ifdef USE_SPECIAL add_interupt_event_count(SPECIAL_INT, 0); #endif }
void ai_end_of_dma_event(struct ai_controller* ai, unsigned int ai_event) { if (ai->regs[AI_STATUS_REG] & 0x80000000) // full { ai->regs[AI_STATUS_REG] &= ~0x80000000; ai->fifo[0].delay = ai->fifo[1].delay; ai->fifo[0].length = ai->fifo[1].length; add_interupt_event_count(AI_INT, ai_event+ai->fifo[1].delay); } else { ai->regs[AI_STATUS_REG] &= ~0x40000000; } raise_rcp_interrupt(ai->r4300, MI_INTR_AI); }
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 MTC0(void) { switch(PC->f.r.nrd) { case 0: // Index Index = rrt & 0x8000003F; if ((Index & 0x3F) > 31) { DebugMessage(M64MSG_ERROR, "MTC0 instruction writing Index register with TLB index > 31"); stop=1; } break; case 1: // Random break; case 2: // EntryLo0 EntryLo0 = rrt & 0x3FFFFFFF; break; case 3: // EntryLo1 EntryLo1 = rrt & 0x3FFFFFFF; break; case 4: // Context Context = (rrt & 0xFF800000) | (Context & 0x007FFFF0); break; case 5: // PageMask PageMask = rrt & 0x01FFE000; break; case 6: // Wired Wired = rrt; Random = 31; break; case 8: // BadVAddr break; case 9: // Count update_count(); if (next_interupt <= Count) gen_interupt(); debug_count += Count; translate_event_queue(rrt & 0xFFFFFFFF); Count = rrt & 0xFFFFFFFF; debug_count -= Count; break; case 10: // EntryHi EntryHi = rrt & 0xFFFFE0FF; break; case 11: // Compare update_count(); remove_event(COMPARE_INT); add_interupt_event_count(COMPARE_INT, (unsigned int)rrt); Compare = rrt; Cause = Cause & 0xFFFF7FFF; //Timer interupt is clear break; case 12: // Status if((rrt & 0x04000000) != (Status & 0x04000000)) { shuffle_fpr_data(Status, rrt); set_fpr_pointers(rrt); } Status = rrt; PC++; check_interupt(); update_count(); if (next_interupt <= Count) gen_interupt(); PC--; break; case 13: // Cause if (rrt!=0) { DebugMessage(M64MSG_ERROR, "MTC0 instruction trying to write Cause register with non-0 value"); stop = 1; } else Cause = rrt; break; case 14: // EPC EPC = rrt; break; case 15: // PRevID break; case 16: // Config Config = rrt; break; case 18: // WatchLo WatchLo = rrt & 0xFFFFFFFF; break; case 19: // WatchHi WatchHi = rrt & 0xFFFFFFFF; break; case 27: // CacheErr break; case 28: // TagLo TagLo = rrt & 0x0FFFFFC0; break; case 29: // TagHi TagHi =0; break; default: DebugMessage(M64MSG_ERROR, "Unknown MTC0 write: %d", PC->f.r.nrd); stop=1; } PC++; }
void gen_interupt() { //if (!skip_jump) //printf("interrupt:%x (%x)\n", q->type, Count); if (stop == 1) dyna_stop(); if (savestates_job & LOADSTATE) { savestates_load(); savestates_job &= ~LOADSTATE; return; } if (skip_jump /*&& !dynacore*/) { if (q->count > Count || (Count - q->count) < 0x80000000) next_interupt = q->count; else next_interupt = 0; if (interpcore) { /*if ((Cause & (2 << 2)) && (Cause & 0x80000000)) interp_addr = skip_jump+4; else*/ interp_addr = skip_jump; last_addr = interp_addr; } else { /*if ((Cause & (2 << 2)) && (Cause & 0x80000000)) jump_to(skip_jump+4); else*/ unsigned long dest = skip_jump; skip_jump=0; jump_to(dest); last_addr = PC->addr; } skip_jump=0; 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: #ifdef VCR_SUPPORT VCR_updateScreen(); #else updateScreen(); #endif #ifndef __WIN32__ SDL_PumpEvents(); refresh_stat(); #endif 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+=2; add_interupt_event_count(COMPARE_INT, Compare); Count-=2; 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: #ifndef __WIN32__ SDL_PumpEvents(); #endif PIF_RAMb[0x3F] = 0x0; remove_interupt_event(); MI_register.mi_intr_reg |= 0x02; si_register.si_status |= 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 long 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(AI_INT, ai_register.next_delay/**2*/); 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; //return; } break; case SP_INT: remove_interupt_event(); sp_register.sp_status_reg |= 0x303; //sp_register.signal1 = 1; sp_register.signal2 = 1; sp_register.broke = 1; sp_register.halt = 1; if (!sp_register.intr_break) return; 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; default: remove_interupt_event(); break; } exception_general(); if (savestates_job & SAVESTATE) { savestates_save(); savestates_job &= ~SAVESTATE; } #ifdef __WIN32__ extern BOOL emu_paused; while(emu_paused) { Sleep(10); // viStatusChanged(); //// processDList(); // processRDPList(); // updateScreen(); processLuaMessages(); } #endif }
void gen_interupt() { if (stop == 1) { dyna_stop(); } if (savestates_job & LOADSTATE) { savestates_load(); savestates_job &= ~LOADSTATE; return; } if (skip_jump) { if (q->count > Count || (Count - q->count) < 0x80000000) { next_interupt = q->count; } else { next_interupt = 0; } interp_addr = skip_jump; last_addr = interp_addr; skip_jump=0; 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: updateScreen(); #ifdef PROFILE refresh_stat(); #endif new_vi(); vi_register.vi_delay = (vi_register.vi_v_sync == 0) ? 500000 : ((vi_register.vi_v_sync + 1)*1500); next_vi += vi_register.vi_delay; vi_field = (vi_register.vi_status&0x40) ? 1-vi_field : 0; remove_interupt_event(); add_interupt_event_count(VI_INT, next_vi); MI_register.mi_intr_reg |= 0x08; if(!chk_status(1)) { return; } break; case COMPARE_INT: remove_interupt_event(); Count+=2; add_interupt_event_count(COMPARE_INT, Compare); Count-=2; Cause = (Cause | 0x8000) & 0xFFFFFF83; if(!chk_status(0)) { return; } break; case CHECK_INT: remove_interupt_event(); break; case SI_INT: PIF_RAMb[0x3F] = 0x0; remove_interupt_event(); MI_register.mi_intr_reg |= 0x02; si_register.si_status |= 0x1000; if(!chk_status(1)) { return; } break; case PI_INT: remove_interupt_event(); MI_register.mi_intr_reg |= 0x10; pi_register.read_pi_status_reg &= ~3; if(!chk_status(1)) { return; } break; case AI_INT: if (ai_register.ai_status & 0x80000000) { // full unsigned long 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); } else { remove_interupt_event(); ai_register.ai_status &= ~0x40000000; } MI_register.mi_intr_reg |= 0x04; if(!chk_status(1)) { return; } break; default: remove_interupt_event(); break; } exception_general(); if (savestates_job & SAVESTATE) { savestates_save(); savestates_job &= ~SAVESTATE; } }
void MTC0(void) { switch(PC->f.r.nrd) { case 0: // Index Index = rrt & 0x8000003F; if ((Index & 0x3F) > 31) { printf ("il y a plus de 32 TLB\n"); stop=1; } break; case 1: // Random break; case 2: // EntryLo0 EntryLo0 = rrt & 0x3FFFFFFF; break; case 3: // EntryLo1 EntryLo1 = rrt & 0x3FFFFFFF; break; case 4: // Context Context = (rrt & 0xFF800000) | (Context & 0x007FFFF0); break; case 5: // PageMask PageMask = rrt & 0x01FFE000; break; case 6: // Wired Wired = rrt; Random = 31; break; case 8: // BadVAddr break; case 9: // Count update_count(); //if (next_interupt <= Count) gen_interupt(); debug_count += Count; translate_event_queue(rrt & 0xFFFFFFFF); Count = rrt & 0xFFFFFFFF; debug_count -= Count; break; case 10: // EntryHi EntryHi = rrt & 0xFFFFE0FF; break; case 11: // Compare update_count(); remove_event(COMPARE_INT); add_interupt_event_count(COMPARE_INT, (unsigned int)rrt); Compare = rrt; Cause = Cause & 0xFFFF7FFF; //Timer interupt is clear break; case 12: // Status if((rrt & 0x04000000) != (Status & 0x04000000)) { if (rrt & 0x04000000) { int i; for (i=0; i<32; i++) { reg_cop1_double[i]=(double*)®_cop1_fgr_64[i]; reg_cop1_simple[i]=(float*)®_cop1_fgr_64[i]; } } else { int i; for (i=0; i<32; i++) { if(!(i&1)) reg_cop1_double[i]=(double*)®_cop1_fgr_64[i>>1]; #ifndef _BIG_ENDIAN reg_cop1_simple[i]=(float*)®_cop1_fgr_64[i>>1]+(i&1); #else reg_cop1_simple[i]=(float*)®_cop1_fgr_64[i>>1]+(1-(i&1)); #endif } } } Status = rrt; //WTF? This screws up the count... //PC++; check_interupt(); update_count(); //if (next_interupt <= Count) gen_interupt(); //PC--; break; case 13: // Cause if (rrt!=0) { printf("écriture dans Cause\n"); stop = 1; } else Cause = rrt; break; case 14: // EPC EPC = rrt; break; case 15: // PRevID break; case 16: // Config Config = rrt; break; case 18: // WatchLo WatchLo = rrt & 0xFFFFFFFF; break; case 19: // WatchHi WatchHi = rrt & 0xFFFFFFFF; break; case 27: // CacheErr break; case 28: // TagLo TagLo = rrt & 0x0FFFFFC0; break; case 29: // TagHi TagHi =0; break; default: printf("unknown mtc0 write : %d\n", PC->f.r.nrd); stop=1; } PC++; }
void MTC0() { switch(PC->f.r.nrd) { case 0: // Index Index = rrt & 0x8000003F; if ((Index & 0x3F) > 31) { printf ("il y a plus de 32 TLB\n"); stop=1; } break; case 1: // Random break; case 2: // EntryLo0 EntryLo0 = rrt & 0x3FFFFFFF; break; case 3: // EntryLo1 EntryLo1 = rrt & 0x3FFFFFFF; break; case 4: // Context Context = (rrt & 0xFF800000) | (Context & 0x007FFFF0); break; case 5: // PageMask PageMask = rrt & 0x01FFE000; break; case 6: // Wired Wired = rrt; Random = 31; break; case 8: // BadVAddr break; case 9: // Count update_count(); if (next_interupt <= Count) gen_interupt(); translate_event_queue(rrt & 0xFFFFFFFF); Count = rrt & 0xFFFFFFFF; break; case 10: // EntryHi EntryHi = rrt & 0xFFFFE0FF; break; case 11: // Compare update_count(); remove_event(COMPARE_INT); add_interupt_event_count(COMPARE_INT, (unsigned long)rrt); Compare = rrt; Cause = Cause & 0xFFFF7FFF; //Timer interupt is clear break; case 12: // Status if((rrt & 0x04000000) != (Status & 0x04000000)) { shuffle_fpr_data(Status, rrt); set_fpr_pointers(rrt); } Status = rrt; update_count(); PC++; check_interupt(); if (next_interupt <= Count) gen_interupt(); PC--; break; case 13: // Cause if (rrt!=0) { printf("écriture dans Cause\n"); stop = 1; } else Cause = rrt; break; case 14: // EPC EPC = rrt; break; case 15: // PRevID break; case 16: // Config Config = rrt; break; case 18: // WatchLo WatchLo = rrt & 0xFFFFFFFF; break; case 19: // WatchHi WatchHi = rrt & 0xFFFFFFFF; break; case 27: // CacheErr break; case 28: // TagLo TagLo = rrt & 0x0FFFFFC0; break; case 29: // TagHi TagHi =0; break; default: printf("unknown mtc0 write : %d\n", PC->f.r.nrd); stop=1; } PC++; }
void add_interupt_event(int type, unsigned int delay) { add_interupt_event_count(type, g_cp0_regs[CP0_COUNT_REG] + delay); }
void gen_interupt() { if(!__emulation_run) stop = 1; if (stop == 1) { vi_counter = 0; // debug dyna_stop(); } if (savestates_job & LOADSTATE) { savestates_load(); savestates_job &= ~LOADSTATE; return; } if (skip_jump) { if (q->count > Count || (Count - q->count) < 0x80000000) next_interupt = q->count; else next_interupt = 0; if (interpcore) { interp_addr = skip_jump; last_addr = interp_addr; } else { unsigned int dest = skip_jump; skip_jump=0; jump_to(dest); last_addr = PC->addr; } skip_jump=0; 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); } 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 updateScreen didn't do it SDL_GL_SwapBuffers(); while(rompause) { #ifdef __WIN32__ Sleep(10); #else struct timespec ts; ts.tv_sec = 0; ts.tv_nsec = 10000000; nanosleep(&ts, NULL); // sleep for 10 milliseconds #endif 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+=2; add_interupt_event_count(COMPARE_INT, Compare); Count-=2; 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 |= 0x303; //sp_register.signal1 = 1; sp_register.signal2 = 1; sp_register.broke = 1; sp_register.halt = 1; if (!sp_register.intr_break) return; 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; // reset the r4300 internal state if (interpcore) /* pure interpreter only */ { // set ErrorEPC with last instruction address and set next instruction address to reset vector ErrorEPC = interp_addr; interp_addr = 0xa4000040; last_addr = interp_addr; } else /* decode-cached interpreter or dynamic recompiler */ { int i; // clear all the compiled instruction blocks for (i=0; i<0x100000; i++) { if (blocks[i]) { if (blocks[i]->block) { free(blocks[i]->block); blocks[i]->block = NULL; } if (blocks[i]->code) { free(blocks[i]->code); blocks[i]->code = NULL; } if (blocks[i]->jumps_table) { free(blocks[i]->jumps_table); blocks[i]->jumps_table = NULL; } if (blocks[i]->riprel_table) { free(blocks[i]->riprel_table); blocks[i]->riprel_table = NULL; } free(blocks[i]); blocks[i] = NULL; } } // re-initialize init_blocks(); // jump to the start ErrorEPC = PC->addr; jump_to(0xa4000040); last_addr = PC->addr; } // 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; return; default: remove_interupt_event(); break; } #ifdef NEW_DYNAREC EPC = pcaddr; pcaddr = 0x80000180; Status |= 2; Cause &= 0x7FFFFFFF; pending_exception=1; #else exception_general(); #endif if (savestates_job & SAVESTATE) { savestates_save(); savestates_job &= ~SAVESTATE; } }
void add_interupt_event(usf_state_t * state, int type, unsigned int delay) { add_interupt_event_count(state, type, state->g_cp0_regs[CP0_COUNT_REG] + delay); }