// Continually cycles the device until setjmp returns. int device_debug_spin(struct cen64_device *device) { struct vr4300_stats vr4300_stats; // Prepare stats, set a breakpoint @ VR4300 IPL vector. memset(&vr4300_stats, 0, sizeof(vr4300_stats)); netapi_debug_wait(device->debug_sfd, device); if (setjmp(device->bus.unwind_data)) return 1; while (1) { unsigned i; for (i = 0; i < 2; i++) { vr4300_cycle(&device->vr4300); rsp_cycle(&device->rsp); ai_cycle(&device->ai); vi_cycle(&device->vi); vr4300_cycle_extra(&device->vr4300, &vr4300_stats); } vr4300_cycle(&device->vr4300); vr4300_cycle_extra(&device->vr4300, &vr4300_stats); } return 0; }
CEN64_THREAD_RETURN_TYPE run_vr4300_thread(void *opaque) { struct cen64_device *device = (struct cen64_device *) opaque; while (1) { unsigned i, j; for (i = 0; i < 6250 / 10; i++) { for (j = 0; j < 10; j++) ai_cycle(&device->ai); for (j = 0; j < 15; j++) vr4300_cycle(&device->vr4300); } // Sync up with the RCP thread. cen64_mutex_lock(&device->sync_mutex); if (!device->other_thread_is_waiting) { device->other_thread_is_waiting = true; cen64_cv_wait(&device->sync_cv, &device->sync_mutex); } else { device->other_thread_is_waiting = false; cen64_mutex_unlock(&device->sync_mutex); cen64_cv_signal(&device->sync_cv); } } return CEN64_THREAD_RETURN_VAL; }
// Continually cycles the device until setjmp returns. int device_spin(struct cen64_device *device) { if (setjmp(device->bus.unwind_data)) return 1; while (1) { unsigned i; for (i = 0; i < 2; i++) { vr4300_cycle(&device->vr4300); rsp_cycle(&device->rsp); ai_cycle(&device->ai); vi_cycle(&device->vi); } vr4300_cycle(&device->vr4300); } return 0; }
void * runCen64(void * p) { struct bus_controller *bus = (struct bus_controller *) p; struct vr4300 vr4300; vr4300_init(&vr4300, bus); vr4300.pipeline.icrf_latch.pc = 0xFFFFFFFF801E4B10ULL; // Prime the pipeline... while (vr4300.pipeline.dcwb_latch.common.pc != 0xFFFFFFFF801E4B10ULL || (vr4300.pipeline.dcwb_latch.common.fault || vr4300.pipeline.dcwb_latch.common.killed)) vr4300_cycle(&vr4300); //printf("cmips starts at 0x%.8X... PRIMED!!\n",bus->emu->pc); unsigned steps_compld = 0; uint8_t *mem_at_wb = malloc(64 * 1024 * 1024); uint8_t *mem_at_commit = malloc(64 * 1024 * 1024); if (mem_at_wb == NULL || mem_at_commit == NULL) { printf("MOAR mammaries required!!\n"); abort(); } memcpy(mem_at_wb, bus->emu->mem, 64 * 1024 * 1024); memcpy(mem_at_commit, bus->emu->mem, 64 * 1024 *1024); while (1) { int i; if(pthread_mutex_lock(&emu_mutex)) { puts("mutex failed lock, exiting"); exit(1); } for (i = 0; i < 10000; i++) { #if 0 //printf("."); //fflush(stdout); // printf("step_mips, pc: 0x%.8X\n", bus->emu->pc); uint32_t cmp_pc = bus->emu->pc; step_mips(bus->emu); do { vr4300_cycle(&vr4300); } while(vr4300.pipeline.last_pipe_result.fault || vr4300.pipeline.last_pipe_result.killed); vr4300.pipeline.last_pipe_result.fault = ~0; if (cmp_pc != (uint32_t) vr4300.pipeline.last_pipe_result.pc) { printf("PC mismatch detected @ %u steps!\n", steps_compld); printf("cmips: 0x%.8X, cen64: 0x%.8X\n", bus->emu->pc, vr4300.pipeline.last_pipe_result.pc); abort(); } size_t ri; for (ri = 1; ri < 32; ri++) { if ((uint32_t) vr4300.regs[ri] != bus->emu->regs[ri]) { printf("GPR[%u] mismatch detected @ 0x%.8X/%u steps!\n", ri, cmp_pc, steps_compld); printf("cmips: 0x%.8X, cen64: 0x%.8X\n", bus->emu->regs[ri], vr4300.regs[ri]); abort(); } } #if 0 else { printf("cmips: 0x%.8X, cen64: 0x%.8X\n", bus->emu->pc, vr4300.pipeline.last_pipe_result.pc); } #endif // this is too slow #if 1 if (steps_compld > 242180) { //memcpy(mem_at_commit, bus->mem, 64 * 1024 * 1024); if (steps_compld > 242182 && memcmp(mem_at_commit, bus->emu->mem, 64 * 1024 * 1024)) { size_t k; bool false_alarm; for (k = 0; k < 64 * 1024 * 1024 / 4; k++) { uint32_t cm, cm1, cm2; memcpy(&cm, mem_at_commit + k * 4, sizeof(cm)); memcpy(&cm1, mem_at_wb + k * 4, sizeof(cm1)); memcpy(&cm2, bus->mem + k * 4, sizeof(cm2)); if (cm != bus->emu->mem[k] && cm1 != bus->emu->mem[k] && cm2 != bus->emu->mem[k]) { printf("Memory mismatch detected @ %u steps!\n", steps_compld); printf(" -> @addr=0x%.8X ... cmips=0x%.8X, cen64=0x%.8X\n", (unsigned) (k * 4), bus->emu->mem[k], cm); false_alarm = false; break; } else { false_alarm = true; break; } } if (!false_alarm) abort(); } memcpy(mem_at_commit, mem_at_wb, 64 * 1024 * 1024); memcpy(mem_at_wb, bus->mem, 64 * 1024 * 1024); } #endif steps_compld++; #else vr4300_cycle(&vr4300); #endif } if(pthread_mutex_unlock(&emu_mutex)) { puts("mutex failed unlock, exiting"); exit(1); } }