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 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 savestates_load() { gzFile f = NULL; char *filename, buf[1024]; int len, i; /* fix the filename to %s.st%d format */ filename = malloc(1024); sprintf(filename, "%s%s%s%s.st%d",(saveStateDevice==SAVESTATEDEVICE_USB)?"usb:":"sd:", statespath, ROM_SETTINGS.goodname, saveregionstr(),savestates_slot); f = gzopen(filename, "rb"); free(filename); if (!f) { return; } if(stop) { pauseRemovalThread(); } else { pauseAudio(); } gzread(f, &rdram_register, sizeof(RDRAM_register)); gzread(f, &MI_register, sizeof(mips_register)); gzread(f, &pi_register, sizeof(PI_register)); gzread(f, &sp_register, sizeof(SP_register)); gzread(f, &rsp_register, sizeof(RSP_register)); gzread(f, &si_register, sizeof(SI_register)); gzread(f, &vi_register, sizeof(VI_register)); gzread(f, &ri_register, sizeof(RI_register)); gzread(f, &ai_register, sizeof(AI_register)); gzread(f, &dpc_register, sizeof(DPC_register)); gzread(f, &dps_register, sizeof(DPS_register)); #ifdef USE_EXPANSION gzread(f, rdram, 0x800000); #else gzread(f, rdram, 0x400000); #endif gzread(f, SP_DMEM, 0x1000); gzread(f, SP_IMEM, 0x1000); gzread(f, PIF_RAM, 0x40); gzread(f, buf, 24); load_flashram_infos(buf); #ifndef USE_TLB_CACHE gzread(f, tlb_LUT_r, 0x100000); gzread(f, tlb_LUT_w, 0x100000); #else int numNodesWritten_r=0,numNodesWritten_w=0,cntr,tlbpage,tlbvalue; TLBCache_deinit(); TLBCache_init(); //Load number of them.. gzread(f, &numNodesWritten_r, 4); for(cntr=0;cntr<numNodesWritten_r;cntr++) { gzread(f, &tlbpage, 4); gzread(f, &tlbvalue, 4); TLBCache_set_r(tlbpage,tlbvalue); } gzread(f, &numNodesWritten_w, 4); for(cntr=0;cntr<numNodesWritten_w;cntr++) { gzread(f, &tlbpage, 4); gzread(f, &tlbvalue, 4); TLBCache_set_w(tlbpage,tlbvalue); } #endif gzread(f, &llbit, 4); gzread(f, reg, 32*8); for (i=0; i<32; i++) { gzread(f, reg_cop0+i, 4); gzread(f, buf, 4); // for compatibility with old versions purpose } set_fpr_pointers(Status); // Status is reg_cop0[12] gzread(f, &lo, 8); gzread(f, &hi, 8); gzread(f, reg_cop1_fgr_64, 32*8); if ((Status & 0x04000000) == 0) // 32-bit FPR mode requires data shuffling because 64-bit layout is always stored in savestate file shuffle_fpr_data(0x04000000, 0); gzread(f, &FCR0, 4); gzread(f, &FCR31, 4); gzread(f, tlb_e, 32*sizeof(tlb)); for (i=0; i<0x100000; i++) invalid_code_set(i, 1); gzread(f, &interp_addr, 4); //dynarec should be ok with just this gzread(f, &next_interupt, 4); gzread(f, &next_vi, 4); gzread(f, &vi_field, 4); len = 0; while(1) { gzread(f, buf+len, 4); if (*((unsigned long*)&buf[len]) == 0xFFFFFFFF) break; gzread(f, buf+len+4, 4); len += 8; } load_eventqueue_infos(buf); gzclose(f); last_addr = interp_addr; if(stop) { continueRemovalThread(); } else { resumeAudio(); } }
void savestates_save() { gzFile f; char *filename, buf[1024]; int len, i; /* fix the filename to %s.st%d format */ filename = malloc(1024); sprintf(filename, "%s%s%s%s.st%d",(saveStateDevice==SAVESTATEDEVICE_USB)?"usb:":"sd:", statespath, ROM_SETTINGS.goodname, saveregionstr(),savestates_slot); f = gzopen(filename, "wb"); free(filename); if(!f) { return; } if(stop) { pauseRemovalThread(); } else { pauseAudio(); } gzwrite(f, &rdram_register, sizeof(RDRAM_register)); gzwrite(f, &MI_register, sizeof(mips_register)); gzwrite(f, &pi_register, sizeof(PI_register)); gzwrite(f, &sp_register, sizeof(SP_register)); gzwrite(f, &rsp_register, sizeof(RSP_register)); gzwrite(f, &si_register, sizeof(SI_register)); gzwrite(f, &vi_register, sizeof(VI_register)); gzwrite(f, &ri_register, sizeof(RI_register)); gzwrite(f, &ai_register, sizeof(AI_register)); gzwrite(f, &dpc_register, sizeof(DPC_register)); gzwrite(f, &dps_register, sizeof(DPS_register)); #ifdef USE_EXPANSION gzwrite(f, rdram, 0x800000); #else gzwrite(f, rdram, 0x400000); #endif gzwrite(f, SP_DMEM, 0x1000); gzwrite(f, SP_IMEM, 0x1000); gzwrite(f, PIF_RAM, 0x40); save_flashram_infos(buf); gzwrite(f, buf, 24); #ifndef USE_TLB_CACHE gzwrite(f, tlb_LUT_r, 0x100000); gzwrite(f, tlb_LUT_w, 0x100000); #else //Traverse the TLB cache hash and dump it TLBCache_dump_r(f); TLBCache_dump_w(f); #endif gzwrite(f, &llbit, 4); gzwrite(f, reg, 32*8); for (i=0; i<32; i++) gzwrite(f, reg_cop0+i, 8); // *8 for compatibility with old versions purpose gzwrite(f, &lo, 8); gzwrite(f, &hi, 8); if ((Status & 0x04000000) == 0) { // FR bit == 0 means 32-bit (MIPS I) FGR mode shuffle_fpr_data(0, 0x04000000); // shuffle data into 64-bit register format for storage gzwrite(f, reg_cop1_fgr_64, 32*8); shuffle_fpr_data(0x04000000, 0); // put it back in 32-bit mode } else { gzwrite(f, reg_cop1_fgr_64, 32*8); } gzwrite(f, &FCR0, 4); gzwrite(f, &FCR31, 4); gzwrite(f, tlb_e, 32*sizeof(tlb)); gzwrite(f, &interp_addr, 4); //Dynarec should be ok with just this gzwrite(f, &next_interupt, 4); gzwrite(f, &next_vi, 4); gzwrite(f, &vi_field, 4); len = save_eventqueue_infos(buf); gzwrite(f, buf, len); gzclose(f); if(stop) { continueRemovalThread(); } else { resumeAudio(); } }
int savestates_load_m64p(const unsigned char *data, size_t size) { unsigned char header[44]; int version; int i; unsigned char *curr = (unsigned char*)data; // < HACK char queue[1024]; /* Read and check Mupen64Plus magic number. */ if(strncmp((char *)curr, savestate_magic, 8)!=0) { return 0; } curr += 8; version = *curr++; version = (version << 8) | *curr++; version = (version << 8) | *curr++; version = (version << 8) | *curr++; if(version != 0x00010000) { return 0; } if(memcmp((char *)curr, ROM_SETTINGS.MD5, 32)) { return 0; } curr += 32; // Parse savestate rdram_register.rdram_config = GETDATA(curr, unsigned int); rdram_register.rdram_device_id = GETDATA(curr, unsigned int); rdram_register.rdram_delay = GETDATA(curr, unsigned int); rdram_register.rdram_mode = GETDATA(curr, unsigned int); rdram_register.rdram_ref_interval = GETDATA(curr, unsigned int); rdram_register.rdram_ref_row = GETDATA(curr, unsigned int); rdram_register.rdram_ras_interval = GETDATA(curr, unsigned int); rdram_register.rdram_min_interval = GETDATA(curr, unsigned int); rdram_register.rdram_addr_select = GETDATA(curr, unsigned int); rdram_register.rdram_device_manuf = GETDATA(curr, unsigned int); MI_register.w_mi_init_mode_reg = GETDATA(curr, unsigned int); MI_register.mi_init_mode_reg = GETDATA(curr, unsigned int); curr += 4; // Duplicate MI init mode flags from old implementation MI_register.mi_version_reg = GETDATA(curr, unsigned int); MI_register.mi_intr_reg = GETDATA(curr, unsigned int); MI_register.mi_intr_mask_reg = GETDATA(curr, unsigned int); MI_register.w_mi_intr_mask_reg = GETDATA(curr, unsigned int); curr += 8; // Duplicated MI intr flags and padding from old implementation pi_register.pi_dram_addr_reg = GETDATA(curr, unsigned int); pi_register.pi_cart_addr_reg = GETDATA(curr, unsigned int); pi_register.pi_rd_len_reg = GETDATA(curr, unsigned int); pi_register.pi_wr_len_reg = GETDATA(curr, unsigned int); pi_register.read_pi_status_reg = GETDATA(curr, unsigned int); pi_register.pi_bsd_dom1_lat_reg = GETDATA(curr, unsigned int); pi_register.pi_bsd_dom1_pwd_reg = GETDATA(curr, unsigned int); pi_register.pi_bsd_dom1_pgs_reg = GETDATA(curr, unsigned int); pi_register.pi_bsd_dom1_rls_reg = GETDATA(curr, unsigned int); pi_register.pi_bsd_dom2_lat_reg = GETDATA(curr, unsigned int); pi_register.pi_bsd_dom2_pwd_reg = GETDATA(curr, unsigned int); pi_register.pi_bsd_dom2_pgs_reg = GETDATA(curr, unsigned int); pi_register.pi_bsd_dom2_rls_reg = GETDATA(curr, unsigned int); sp_register.sp_mem_addr_reg = GETDATA(curr, unsigned int); sp_register.sp_dram_addr_reg = GETDATA(curr, unsigned int); sp_register.sp_rd_len_reg = GETDATA(curr, unsigned int); sp_register.sp_wr_len_reg = GETDATA(curr, unsigned int); sp_register.w_sp_status_reg = GETDATA(curr, unsigned int); sp_register.sp_status_reg = GETDATA(curr, unsigned int); curr += 16; // Duplicated SP flags and padding from old implementation sp_register.sp_dma_full_reg = GETDATA(curr, unsigned int); sp_register.sp_dma_busy_reg = GETDATA(curr, unsigned int); sp_register.sp_semaphore_reg = GETDATA(curr, unsigned int); rsp_register.rsp_pc = GETDATA(curr, unsigned int); rsp_register.rsp_ibist = GETDATA(curr, unsigned int); si_register.si_dram_addr = GETDATA(curr, unsigned int); si_register.si_pif_addr_rd64b = GETDATA(curr, unsigned int); si_register.si_pif_addr_wr64b = GETDATA(curr, unsigned int); si_register.si_stat = GETDATA(curr, unsigned int); vi_register.vi_status = GETDATA(curr, unsigned int); vi_register.vi_origin = GETDATA(curr, unsigned int); vi_register.vi_width = GETDATA(curr, unsigned int); vi_register.vi_v_intr = GETDATA(curr, unsigned int); vi_register.vi_current = GETDATA(curr, unsigned int); vi_register.vi_burst = GETDATA(curr, unsigned int); vi_register.vi_v_sync = GETDATA(curr, unsigned int); vi_register.vi_h_sync = GETDATA(curr, unsigned int); vi_register.vi_leap = GETDATA(curr, unsigned int); vi_register.vi_h_start = GETDATA(curr, unsigned int); vi_register.vi_v_start = GETDATA(curr, unsigned int); vi_register.vi_v_burst = GETDATA(curr, unsigned int); vi_register.vi_x_scale = GETDATA(curr, unsigned int); vi_register.vi_y_scale = GETDATA(curr, unsigned int); vi_register.vi_delay = GETDATA(curr, unsigned int); update_vi_status(vi_register.vi_status); update_vi_width(vi_register.vi_width); ri_register.ri_mode = GETDATA(curr, unsigned int); ri_register.ri_config = GETDATA(curr, unsigned int); ri_register.ri_current_load = GETDATA(curr, unsigned int); ri_register.ri_select = GETDATA(curr, unsigned int); ri_register.ri_refresh = GETDATA(curr, unsigned int); ri_register.ri_latency = GETDATA(curr, unsigned int); ri_register.ri_error = GETDATA(curr, unsigned int); ri_register.ri_werror = GETDATA(curr, unsigned int); ai_register.ai_dram_addr = GETDATA(curr, unsigned int); ai_register.ai_len = GETDATA(curr, unsigned int); ai_register.ai_control = GETDATA(curr, unsigned int); ai_register.ai_status = GETDATA(curr, unsigned int); ai_register.ai_dacrate = GETDATA(curr, unsigned int); ai_register.ai_bitrate = GETDATA(curr, unsigned int); ai_register.next_delay = GETDATA(curr, unsigned int); ai_register.next_len = GETDATA(curr, unsigned int); ai_register.current_delay = GETDATA(curr, unsigned int); ai_register.current_len = GETDATA(curr, unsigned int); update_ai_dacrate(ai_register.ai_dacrate); dpc_register.dpc_start = GETDATA(curr, unsigned int); dpc_register.dpc_end = GETDATA(curr, unsigned int); dpc_register.dpc_current = GETDATA(curr, unsigned int); dpc_register.w_dpc_status = GETDATA(curr, unsigned int); dpc_register.dpc_status = GETDATA(curr, unsigned int); curr += 12; // Duplicated DPC flags and padding from old implementation dpc_register.dpc_clock = GETDATA(curr, unsigned int); dpc_register.dpc_bufbusy = GETDATA(curr, unsigned int); dpc_register.dpc_pipebusy = GETDATA(curr, unsigned int); dpc_register.dpc_tmem = GETDATA(curr, unsigned int); dps_register.dps_tbist = GETDATA(curr, unsigned int); dps_register.dps_test_mode = GETDATA(curr, unsigned int); dps_register.dps_buftest_addr = GETDATA(curr, unsigned int); dps_register.dps_buftest_data = GETDATA(curr, unsigned int); COPYARRAY(rdram, curr, unsigned int, 0x800000/4); COPYARRAY(SP_DMEM, curr, unsigned int, 0x1000/4); COPYARRAY(SP_IMEM, curr, unsigned int, 0x1000/4); COPYARRAY(PIF_RAM, curr, unsigned char, 0x40); flashram_info.use_flashram = GETDATA(curr, int); flashram_info.mode = GETDATA(curr, int); flashram_info.status = GETDATA(curr, unsigned long long); flashram_info.erase_offset = GETDATA(curr, unsigned int); flashram_info.write_pointer = GETDATA(curr, unsigned int); COPYARRAY(tlb_LUT_r, curr, unsigned int, 0x100000); COPYARRAY(tlb_LUT_w, curr, unsigned int, 0x100000); llbit = GETDATA(curr, unsigned int); COPYARRAY(reg, curr, long long int, 32); COPYARRAY(reg_cop0, curr, unsigned int, 32); set_fpr_pointers(Status); // Status is reg_cop0[12] lo = GETDATA(curr, long long int); hi = GETDATA(curr, long long int); COPYARRAY(reg_cop1_fgr_64, curr, long long int, 32); if ((Status & 0x04000000) == 0) // 32-bit FPR mode requires data shuffling because 64-bit layout is always stored in savestate file shuffle_fpr_data(0x04000000, 0); FCR0 = GETDATA(curr, int); FCR31 = GETDATA(curr, int); for (i = 0; i < 32; i++) { tlb_e[i].mask = GETDATA(curr, short); curr += 2; tlb_e[i].vpn2 = GETDATA(curr, int); tlb_e[i].g = GETDATA(curr, char); tlb_e[i].asid = GETDATA(curr, unsigned char); curr += 2; tlb_e[i].pfn_even = GETDATA(curr, int); tlb_e[i].c_even = GETDATA(curr, char); tlb_e[i].d_even = GETDATA(curr, char); tlb_e[i].v_even = GETDATA(curr, char); curr++; tlb_e[i].pfn_odd = GETDATA(curr, int); tlb_e[i].c_odd = GETDATA(curr, char); tlb_e[i].d_odd = GETDATA(curr, char); tlb_e[i].v_odd = GETDATA(curr, char); tlb_e[i].r = GETDATA(curr, char); tlb_e[i].start_even = GETDATA(curr, unsigned int); tlb_e[i].end_even = GETDATA(curr, unsigned int); tlb_e[i].phys_even = GETDATA(curr, unsigned int); tlb_e[i].start_odd = GETDATA(curr, unsigned int); tlb_e[i].end_odd = GETDATA(curr, unsigned int); tlb_e[i].phys_odd = GETDATA(curr, unsigned int); } #ifdef NEW_DYNAREC if (r4300emu == CORE_DYNAREC) { pcaddr = GETDATA(curr, unsigned int); pending_exception = 1; invalidate_all_pages(); } else {