2 * (C) GraÅžvydas "notaz" Ignotas, 2010-2011
4 * This work is licensed under the terms of GNU GPL version 2 or later.
5 * See the COPYING file in the top-level directory.
12 #include "../psxhle.h"
13 #include "../psxinterpreter.h"
14 #include "../r3000a.h"
16 #include "../psxdma.h"
18 #include "../gte_arm.h"
19 #include "../gte_neon.h"
23 #define ARRAY_SIZE(x) (sizeof(x) / sizeof(x[0]))
25 //#define evprintf printf
28 char invalid_code[0x100000];
29 u32 event_cycles[PSXINT_COUNT];
31 static void schedule_timeslice(void)
33 u32 i, c = psxRegs.cycle;
34 u32 irqs = psxRegs.interrupt;
38 for (i = 0; irqs != 0; i++, irqs >>= 1) {
41 dif = event_cycles[i] - c;
42 //evprintf(" ev %d\n", dif);
43 if (0 < dif && dif < min)
46 next_interupt = c + min;
49 static void unusedInterrupt()
53 typedef void (irq_func)();
55 static irq_func * const irq_funcs[] = {
56 [PSXINT_SIO] = sioInterrupt,
57 [PSXINT_CDR] = cdrInterrupt,
58 [PSXINT_CDREAD] = cdrPlaySeekReadInterrupt,
59 [PSXINT_GPUDMA] = gpuInterrupt,
60 [PSXINT_MDECOUTDMA] = mdec1Interrupt,
61 [PSXINT_SPUDMA] = spuInterrupt,
62 [PSXINT_MDECINDMA] = mdec0Interrupt,
63 [PSXINT_GPUOTCDMA] = gpuotcInterrupt,
64 [PSXINT_CDRDMA] = cdrDmaInterrupt,
65 [PSXINT_CDRLID] = cdrLidSeekInterrupt,
66 [PSXINT_CDRPLAY_OLD] = unusedInterrupt,
67 [PSXINT_SPU_UPDATE] = spuUpdate,
68 [PSXINT_RCNT] = psxRcntUpdate,
71 /* local dupe of psxBranchTest, using event_cycles */
72 static void irq_test(void)
74 u32 cycle = psxRegs.cycle;
77 for (irq = 0, irq_bits = psxRegs.interrupt; irq_bits != 0; irq++, irq_bits >>= 1) {
80 if ((s32)(cycle - event_cycles[irq]) >= 0) {
81 // note: irq_funcs() also modify psxRegs.interrupt
82 psxRegs.interrupt &= ~(1u << irq);
87 if ((psxHu32(0x1070) & psxHu32(0x1074)) && (Status & 0x401) == 0x401) {
88 psxException(0x400, 0);
89 pending_exception = 1;
95 evprintf(" +ge %08x, %u->%u (%d)\n", psxRegs.pc, psxRegs.cycle,
96 next_interupt, next_interupt - psxRegs.cycle);
100 //pending_exception = 1;
102 schedule_timeslice();
104 evprintf(" -ge %08x, %u->%u (%d)\n", psxRegs.pc, psxRegs.cycle,
105 next_interupt, next_interupt - psxRegs.cycle);
109 extern void MTC0(int reg, u32 val);
111 void pcsx_mtc0(u32 reg, u32 val)
113 evprintf("MTC0 %d #%x @%08x %u\n", reg, val, psxRegs.pc, psxRegs.cycle);
116 if (Cause & Status & 0x0300) // possible sw irq
117 pending_exception = 1;
120 void pcsx_mtc0_ds(u32 reg, u32 val)
122 evprintf("MTC0 %d #%x @%08x %u\n", reg, val, psxRegs.pc, psxRegs.cycle);
126 void new_dyna_before_save(void)
128 psxRegs.interrupt &= ~(1 << PSXINT_RCNT); // old savestate compat
130 // psxRegs.intCycle is always maintained, no need to convert
133 void new_dyna_after_save(void)
135 psxRegs.interrupt |= 1 << PSXINT_RCNT;
138 static void new_dyna_restore(void)
141 for (i = 0; i < PSXINT_COUNT; i++)
142 event_cycles[i] = psxRegs.intCycle[i].sCycle + psxRegs.intCycle[i].cycle;
144 event_cycles[PSXINT_RCNT] = psxNextsCounter + psxNextCounter;
145 psxRegs.interrupt |= 1 << PSXINT_RCNT;
146 psxRegs.interrupt &= (1 << PSXINT_COUNT) - 1;
148 new_dyna_pcsx_mem_load_state();
151 void new_dyna_freeze(void *f, int mode)
153 const char header_save[8] = "ariblks";
154 uint32_t addrs[1024 * 4];
159 if (mode != 0) { // save
160 size = new_dynarec_save_blocks(addrs, sizeof(addrs));
164 SaveFuncs.write(f, header_save, sizeof(header_save));
165 SaveFuncs.write(f, &size, sizeof(size));
166 SaveFuncs.write(f, addrs, size);
171 bytes = SaveFuncs.read(f, header, sizeof(header));
172 if (bytes != sizeof(header) || strcmp(header, header_save)) {
174 SaveFuncs.seek(f, -bytes, SEEK_CUR);
177 SaveFuncs.read(f, &size, sizeof(size));
180 if (size > sizeof(addrs)) {
181 bytes = size - sizeof(addrs);
182 SaveFuncs.seek(f, bytes, SEEK_CUR);
183 size = sizeof(addrs);
185 bytes = SaveFuncs.read(f, addrs, size);
189 if (psxCpu != &psxInt)
190 new_dynarec_load_blocks(addrs, size);
193 //printf("drc: %d block info entries %s\n", size/8, mode ? "saved" : "loaded");
196 #if !defined(DRC_DISABLE) && !defined(LIGHTREC)
199 void *gte_handlers[64];
201 void *gte_handlers_nf[64] = {
202 NULL , gteRTPS_nf , NULL , NULL , NULL , NULL , gteNCLIP_nf, NULL , // 00
203 NULL , NULL , NULL , NULL , gteOP_nf , NULL , NULL , NULL , // 08
204 gteDPCS_nf, gteINTPL_nf, gteMVMVA_nf, gteNCDS_nf, gteCDP_nf, NULL , gteNCDT_nf , NULL , // 10
205 NULL , NULL , NULL , gteNCCS_nf, gteCC_nf , NULL , gteNCS_nf , NULL , // 18
206 gteNCT_nf , NULL , NULL , NULL , NULL , NULL , NULL , NULL , // 20
207 gteSQR_nf , gteDCPL_nf , gteDPCT_nf , NULL , NULL , gteAVSZ3_nf, gteAVSZ4_nf, NULL , // 28
208 gteRTPT_nf, NULL , NULL , NULL , NULL , NULL , NULL , NULL , // 30
209 NULL , NULL , NULL , NULL , NULL , gteGPF_nf , gteGPL_nf , gteNCCT_nf, // 38
212 const char *gte_regnames[64] = {
213 NULL , "RTPS" , NULL , NULL , NULL , NULL , "NCLIP", NULL , // 00
214 NULL , NULL , NULL , NULL , "OP" , NULL , NULL , NULL , // 08
215 "DPCS", "INTPL", "MVMVA", "NCDS", "CDP", NULL , "NCDT" , NULL , // 10
216 NULL , NULL , NULL , "NCCS", "CC" , NULL , "NCS" , NULL , // 18
217 "NCT" , NULL , NULL , NULL , NULL , NULL , NULL , NULL , // 20
218 "SQR" , "DCPL" , "DPCT" , NULL , NULL , "AVSZ3", "AVSZ4", NULL , // 28
219 "RTPT", NULL , NULL , NULL , NULL , NULL , NULL , NULL , // 30
220 NULL , NULL , NULL , NULL , NULL , "GPF" , "GPL" , "NCCT", // 38
227 #define GCBITS3(b0,b1,b2) \
228 (GCBIT(b0) | GCBIT(b1) | GCBIT(b2))
229 #define GDBITS2(b0,b1) \
230 (GDBIT(b0) | GDBIT(b1))
231 #define GDBITS3(b0,b1,b2) \
232 (GDBITS2(b0,b1) | GDBIT(b2))
233 #define GDBITS4(b0,b1,b2,b3) \
234 (GDBITS3(b0,b1,b2) | GDBIT(b3))
235 #define GDBITS5(b0,b1,b2,b3,b4) \
236 (GDBITS4(b0,b1,b2,b3) | GDBIT(b4))
237 #define GDBITS6(b0,b1,b2,b3,b4,b5) \
238 (GDBITS5(b0,b1,b2,b3,b4) | GDBIT(b5))
239 #define GDBITS7(b0,b1,b2,b3,b4,b5,b6) \
240 (GDBITS6(b0,b1,b2,b3,b4,b5) | GDBIT(b6))
241 #define GDBITS8(b0,b1,b2,b3,b4,b5,b6,b7) \
242 (GDBITS7(b0,b1,b2,b3,b4,b5,b6) | GDBIT(b7))
243 #define GDBITS9(b0,b1,b2,b3,b4,b5,b6,b7,b8) \
244 (GDBITS8(b0,b1,b2,b3,b4,b5,b6,b7) | GDBIT(b8))
245 #define GDBITS10(b0,b1,b2,b3,b4,b5,b6,b7,b8,b9) \
246 (GDBITS9(b0,b1,b2,b3,b4,b5,b6,b7,b8) | GDBIT(b9))
248 const uint64_t gte_reg_reads[64] = {
249 [GTE_RTPS] = 0x1f0000ff00000000ll | GDBITS7(0,1,13,14,17,18,19),
250 [GTE_NCLIP] = GDBITS3(12,13,14),
251 [GTE_OP] = GCBITS3(0,2,4) | GDBITS3(9,10,11),
252 [GTE_DPCS] = GCBITS3(21,22,23) | GDBITS4(6,8,21,22),
253 [GTE_INTPL] = GCBITS3(21,22,23) | GDBITS7(6,8,9,10,11,21,22),
254 [GTE_MVMVA] = 0x00ffffff00000000ll | GDBITS9(0,1,2,3,4,5,9,10,11), // XXX: maybe decode further?
255 [GTE_NCDS] = 0x00ffff0000000000ll | GDBITS6(0,1,6,8,21,22),
256 [GTE_CDP] = 0x00ffe00000000000ll | GDBITS7(6,8,9,10,11,21,22),
257 [GTE_NCDT] = 0x00ffff0000000000ll | GDBITS8(0,1,2,3,4,5,6,8),
258 [GTE_NCCS] = 0x001fff0000000000ll | GDBITS5(0,1,6,21,22),
259 [GTE_CC] = 0x001fe00000000000ll | GDBITS6(6,9,10,11,21,22),
260 [GTE_NCS] = 0x001fff0000000000ll | GDBITS5(0,1,6,21,22),
261 [GTE_NCT] = 0x001fff0000000000ll | GDBITS7(0,1,2,3,4,5,6),
262 [GTE_SQR] = GDBITS3(9,10,11),
263 [GTE_DCPL] = GCBITS3(21,22,23) | GDBITS7(6,8,9,10,11,21,22),
264 [GTE_DPCT] = GCBITS3(21,22,23) | GDBITS4(8,20,21,22),
265 [GTE_AVSZ3] = GCBIT(29) | GDBITS3(17,18,19),
266 [GTE_AVSZ4] = GCBIT(30) | GDBITS4(16,17,18,19),
267 [GTE_RTPT] = 0x1f0000ff00000000ll | GDBITS7(0,1,2,3,4,5,19),
268 [GTE_GPF] = GDBITS7(6,8,9,10,11,21,22),
269 [GTE_GPL] = GDBITS10(6,8,9,10,11,21,22,25,26,27),
270 [GTE_NCCT] = 0x001fff0000000000ll | GDBITS7(0,1,2,3,4,5,6),
273 // note: this excludes gteFLAG that is always written to
274 const uint64_t gte_reg_writes[64] = {
275 [GTE_RTPS] = 0x0f0f7f00ll,
276 [GTE_NCLIP] = GDBIT(24),
277 [GTE_OP] = GDBITS6(9,10,11,25,26,27),
278 [GTE_DPCS] = GDBITS9(9,10,11,20,21,22,25,26,27),
279 [GTE_INTPL] = GDBITS9(9,10,11,20,21,22,25,26,27),
280 [GTE_MVMVA] = GDBITS6(9,10,11,25,26,27),
281 [GTE_NCDS] = GDBITS9(9,10,11,20,21,22,25,26,27),
282 [GTE_CDP] = GDBITS9(9,10,11,20,21,22,25,26,27),
283 [GTE_NCDT] = GDBITS9(9,10,11,20,21,22,25,26,27),
284 [GTE_NCCS] = GDBITS9(9,10,11,20,21,22,25,26,27),
285 [GTE_CC] = GDBITS9(9,10,11,20,21,22,25,26,27),
286 [GTE_NCS] = GDBITS9(9,10,11,20,21,22,25,26,27),
287 [GTE_NCT] = GDBITS9(9,10,11,20,21,22,25,26,27),
288 [GTE_SQR] = GDBITS6(9,10,11,25,26,27),
289 [GTE_DCPL] = GDBITS9(9,10,11,20,21,22,25,26,27),
290 [GTE_DPCT] = GDBITS9(9,10,11,20,21,22,25,26,27),
291 [GTE_AVSZ3] = GDBITS2(7,24),
292 [GTE_AVSZ4] = GDBITS2(7,24),
293 [GTE_RTPT] = 0x0f0f7f00ll,
294 [GTE_GPF] = GDBITS9(9,10,11,20,21,22,25,26,27),
295 [GTE_GPL] = GDBITS9(9,10,11,20,21,22,25,26,27),
296 [GTE_NCCT] = GDBITS9(9,10,11,20,21,22,25,26,27),
299 static int ari64_init()
301 static u32 scratch_buf[8*8*2] __attribute__((aligned(64)));
302 extern void (*psxCP2[64])();
303 extern void psxNULL();
307 new_dyna_pcsx_mem_init();
309 for (i = 0; i < ARRAY_SIZE(gte_handlers); i++)
310 if (psxCP2[i] != psxNULL)
311 gte_handlers[i] = psxCP2[i];
313 #if defined(__arm__) && !defined(DRC_DBG)
314 gte_handlers[0x06] = gteNCLIP_arm;
316 gte_handlers_nf[0x01] = gteRTPS_nf_arm;
317 gte_handlers_nf[0x30] = gteRTPT_nf_arm;
320 // compiler's _nf version is still a lot slower than neon
321 // _nf_arm RTPS is roughly the same, RTPT slower
322 gte_handlers[0x01] = gte_handlers_nf[0x01] = gteRTPS_neon;
323 gte_handlers[0x30] = gte_handlers_nf[0x30] = gteRTPT_neon;
327 memcpy(gte_handlers_nf, gte_handlers, sizeof(gte_handlers_nf));
330 zeromem_ptr = zero_mem;
331 scratch_buf_ptr = scratch_buf;
336 static void ari64_reset()
338 printf("ari64_reset\n");
339 new_dyna_pcsx_mem_reset();
340 new_dynarec_invalidate_all_pages();
342 pending_exception = 1;
345 // execute until predefined leave points
346 // (HLE softcall exit and BIOS fastboot end)
347 static void ari64_execute_until()
349 schedule_timeslice();
351 evprintf("ari64_execute %08x, %u->%u (%d)\n", psxRegs.pc,
352 psxRegs.cycle, next_interupt, next_interupt - psxRegs.cycle);
354 new_dyna_start(dynarec_local);
356 evprintf("ari64_execute end %08x, %u->%u (%d)\n", psxRegs.pc,
357 psxRegs.cycle, next_interupt, next_interupt - psxRegs.cycle);
360 static void ari64_execute()
363 ari64_execute_until();
364 evprintf("drc left @%08x\n", psxRegs.pc);
368 static void ari64_clear(u32 addr, u32 size)
370 size *= 4; /* PCSX uses DMA units (words) */
372 evprintf("ari64_clear %08x %04x\n", addr, size);
374 new_dynarec_invalidate_range(addr, addr + size);
377 static void ari64_notify(int note, void *data) {
379 Should be fixed when ARM dynarec has proper icache emulation.
382 case R3000ACPU_NOTIFY_CACHE_UNISOLATED:
384 case R3000ACPU_NOTIFY_CACHE_ISOLATED:
386 case R3000ACPU_NOTIFY_DMA3_EXE_LOAD:
393 static void ari64_apply_config()
397 if (Config.DisableStalls)
398 new_dynarec_hacks |= NDHACK_NO_STALLS;
400 new_dynarec_hacks &= ~NDHACK_NO_STALLS;
402 if (cycle_multiplier != cycle_multiplier_old
403 || new_dynarec_hacks != new_dynarec_hacks_old)
405 new_dynarec_clear_full();
409 static void ari64_shutdown()
411 new_dynarec_cleanup();
412 new_dyna_pcsx_mem_shutdown();
426 #else // if DRC_DISABLE
428 unsigned int address;
429 int pending_exception, stop;
430 unsigned int next_interupt;
431 int new_dynarec_did_compile;
432 int cycle_multiplier;
433 int cycle_multiplier_override;
434 int cycle_multiplier_old;
435 int new_dynarec_hacks_pergame;
436 int new_dynarec_hacks_old;
437 int new_dynarec_hacks;
442 void *scratch_buf_ptr;
443 void new_dynarec_init() {}
444 void new_dyna_start(void *context) {}
445 void new_dynarec_cleanup() {}
446 void new_dynarec_clear_full() {}
447 void new_dynarec_invalidate_all_pages() {}
448 void new_dynarec_invalidate_range(unsigned int start, unsigned int end) {}
449 void new_dyna_pcsx_mem_init(void) {}
450 void new_dyna_pcsx_mem_reset(void) {}
451 void new_dyna_pcsx_mem_load_state(void) {}
452 void new_dyna_pcsx_mem_shutdown(void) {}
453 int new_dynarec_save_blocks(void *save, int size) { return 0; }
454 void new_dynarec_load_blocks(const void *save, int size) {}
465 void dump_mem(const char *fname, void *mem, size_t size)
467 FILE *f1 = fopen(fname, "wb");
469 f1 = fopen(strrchr(fname, '/') + 1, "wb");
470 fwrite(mem, 1, size, f1);
474 static u32 memcheck_read(u32 a)
476 if ((a >> 16) == 0x1f80)
478 return *(u32 *)(psxH + (a & 0xfffc));
480 if ((a >> 16) == 0x1f00)
482 return *(u32 *)(psxP + (a & 0xfffc));
484 // if ((a & ~0xe0600000) < 0x200000)
486 return *(u32 *)(psxM + (a & 0x1ffffc));
490 void do_insn_trace(void)
492 static psxRegisters oldregs;
493 static u32 event_cycles_o[PSXINT_COUNT];
494 u32 *allregs_p = (void *)&psxRegs;
495 u32 *allregs_o = (void *)&oldregs;
500 //last_io_addr = 0x5e2c8;
502 f = fopen("tracelog", "wb");
505 oldregs.code = psxRegs.code; // don't care
506 for (i = 0; i < offsetof(psxRegisters, intCycle) / 4; i++) {
507 if (allregs_p[i] != allregs_o[i]) {
509 fwrite(&allregs_p[i], 1, 4, f);
510 allregs_o[i] = allregs_p[i];
514 for (i = 0; i < PSXINT_COUNT; i++) {
515 if (event_cycles[i] != event_cycles_o[i]) {
517 fwrite(&byte, 1, 1, f);
519 fwrite(&event_cycles[i], 1, 4, f);
520 event_cycles_o[i] = event_cycles[i];
523 #define SAVE_IF_CHANGED(code_, name_) { \
524 static u32 old_##name_ = 0xbad0c0de; \
525 if (old_##name_ != name_) { \
527 fwrite(&byte, 1, 1, f); \
528 fwrite(&name_, 1, 4, f); \
529 old_##name_ = name_; \
532 SAVE_IF_CHANGED(0xfb, irq_test_cycle);
533 SAVE_IF_CHANGED(0xfc, handler_cycle);
534 SAVE_IF_CHANGED(0xfd, last_io_addr);
535 io_data = memcheck_read(last_io_addr);
536 SAVE_IF_CHANGED(0xfe, io_data);
538 fwrite(&byte, 1, 1, f);
541 if (psxRegs.cycle == 190230) {
542 dump_mem("/mnt/ntz/dev/pnd/tmp/psxram_i.dump", psxM, 0x200000);
543 dump_mem("/mnt/ntz/dev/pnd/tmp/psxregs_i.dump", psxH, 0x10000);
551 static const char *regnames[offsetof(psxRegisters, intCycle) / 4] = {
552 "r0", "r1", "r2", "r3", "r4", "r5", "r6", "r7",
553 "r8", "r9", "r10", "r11", "r12", "r13", "r14", "r15",
554 "r16", "r17", "r18", "r19", "r20", "r21", "r22", "r23",
555 "r24", "r25", "r26", "r27", "r28", "r29", "r30", "r31",
557 "C0_0", "C0_1", "C0_2", "C0_3", "C0_4", "C0_5", "C0_6", "C0_7",
558 "C0_8", "C0_9", "C0_10", "C0_11", "C0_12", "C0_13", "C0_14", "C0_15",
559 "C0_16", "C0_17", "C0_18", "C0_19", "C0_20", "C0_21", "C0_22", "C0_23",
560 "C0_24", "C0_25", "C0_26", "C0_27", "C0_28", "C0_29", "C0_30", "C0_31",
562 "C2D0", "C2D1", "C2D2", "C2D3", "C2D4", "C2D5", "C2D6", "C2D7",
563 "C2D8", "C2D9", "C2D10", "C2D11", "C2D12", "C2D13", "C2D14", "C2D15",
564 "C2D16", "C2D17", "C2D18", "C2D19", "C2D20", "C2D21", "C2D22", "C2D23",
565 "C2D24", "C2D25", "C2D26", "C2D27", "C2D28", "C2D29", "C2D30", "C2D31",
567 "C2C0", "C2C1", "C2C2", "C2C3", "C2C4", "C2C5", "C2C6", "C2C7",
568 "C2C8", "C2C9", "C2C10", "C2C11", "C2C12", "C2C13", "C2C14", "C2C15",
569 "C2C16", "C2C17", "C2C18", "C2C19", "C2C20", "C2C21", "C2C22", "C2C23",
570 "C2C24", "C2C25", "C2C26", "C2C27", "C2C28", "C2C29", "C2C30", "C2C31",
572 "PC", "code", "cycle", "interrupt",
580 static int miss_log_i;
581 #define miss_log_len (sizeof(miss_log)/sizeof(miss_log[0]))
582 #define miss_log_mask (miss_log_len-1)
584 static void miss_log_add(int reg, u32 val, u32 val_expect, u32 pc, u32 cycle)
586 miss_log[miss_log_i].reg = reg;
587 miss_log[miss_log_i].val = val;
588 miss_log[miss_log_i].val_expect = val_expect;
589 miss_log[miss_log_i].pc = pc;
590 miss_log[miss_log_i].cycle = cycle;
591 miss_log_i = (miss_log_i + 1) & miss_log_mask;
596 void do_insn_cmp(void)
598 extern int last_count;
599 static psxRegisters rregs;
600 static u32 mem_addr, mem_val;
601 static u32 irq_test_cycle_intr;
602 static u32 handler_cycle_intr;
603 u32 *allregs_p = (void *)&psxRegs;
604 u32 *allregs_e = (void *)&rregs;
605 static u32 ppc, failcount;
606 int i, ret, bad = 0, fatal = 0, which_event = -1;
611 f = fopen("tracelog", "rb");
614 if ((ret = fread(&code, 1, 1, f)) <= 0)
623 fread(&which_event, 1, 1, f);
624 fread(&ev_cycles, 1, 4, f);
627 fread(&irq_test_cycle_intr, 1, 4, f);
630 fread(&handler_cycle_intr, 1, 4, f);
633 fread(&mem_addr, 1, 4, f);
636 fread(&mem_val, 1, 4, f);
639 assert(code < offsetof(psxRegisters, intCycle) / 4);
640 fread(&allregs_e[code], 1, 4, f);
648 psxRegs.code = rregs.code; // don't care
649 psxRegs.cycle += last_count;
650 //psxRegs.cycle = rregs.cycle; // needs reload in _cmp
651 psxRegs.CP0.r[9] = rregs.CP0.r[9]; // Count
653 //if (psxRegs.cycle == 166172) breakme();
655 if (which_event >= 0 && event_cycles[which_event] != ev_cycles) {
656 printf("bad ev_cycles #%d: %u %u / %u\n", which_event,
657 event_cycles[which_event], ev_cycles, psxRegs.cycle);
661 if (irq_test_cycle > irq_test_cycle_intr) {
662 printf("bad irq_test_cycle: %u %u\n", irq_test_cycle, irq_test_cycle_intr);
666 if (handler_cycle != handler_cycle_intr) {
667 printf("bad handler_cycle: %u %u\n", handler_cycle, handler_cycle_intr);
671 if (mem_val != memcheck_read(mem_addr)) {
672 printf("bad mem @%08x: %08x %08x\n", mem_addr, memcheck_read(mem_addr), mem_val);
676 if (!fatal && !memcmp(&psxRegs, &rregs, offsetof(psxRegisters, intCycle))) {
681 for (i = 0; i < offsetof(psxRegisters, intCycle) / 4; i++) {
682 if (allregs_p[i] != allregs_e[i]) {
683 miss_log_add(i, allregs_p[i], allregs_e[i], psxRegs.pc, psxRegs.cycle);
690 if (!fatal && psxRegs.pc == rregs.pc && bad < 6 && failcount < 32) {
691 static int last_mcycle;
692 if (last_mcycle != psxRegs.cycle >> 20) {
693 printf("%u\n", psxRegs.cycle);
694 last_mcycle = psxRegs.cycle >> 20;
700 for (i = 0; i < miss_log_len; i++, miss_log_i = (miss_log_i + 1) & miss_log_mask)
701 printf("bad %5s: %08x %08x, pc=%08x, cycle %u\n",
702 regnames[miss_log[miss_log_i].reg], miss_log[miss_log_i].val,
703 miss_log[miss_log_i].val_expect, miss_log[miss_log_i].pc, miss_log[miss_log_i].cycle);
704 printf("-- %d\n", bad);
705 for (i = 0; i < 8; i++)
706 printf("r%d=%08x r%2d=%08x r%2d=%08x r%2d=%08x\n", i, allregs_p[i],
707 i+8, allregs_p[i+8], i+16, allregs_p[i+16], i+24, allregs_p[i+24]);
708 printf("PC: %08x/%08x, cycle %u, next %u\n", psxRegs.pc, ppc, psxRegs.cycle, next_interupt);
709 //dump_mem("/tmp/psxram.dump", psxM, 0x200000);
710 //dump_mem("/mnt/ntz/dev/pnd/tmp/psxregs.dump", psxH, 0x10000);
713 //psxRegs.cycle = rregs.cycle + 2; // sync timing