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] = cdrPlayReadInterrupt,
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)) && (psxRegs.CP0.n.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);
108 void pcsx_mtc0(u32 reg, u32 val)
110 evprintf("MTC0 %d #%x @%08x %u\n", reg, val, psxRegs.pc, psxRegs.cycle);
111 MTC0(&psxRegs, reg, val);
113 if (psxRegs.CP0.n.Cause & psxRegs.CP0.n.Status & 0x0300) // possible sw irq
114 pending_exception = 1;
117 void pcsx_mtc0_ds(u32 reg, u32 val)
119 evprintf("MTC0 %d #%x @%08x %u\n", reg, val, psxRegs.pc, psxRegs.cycle);
120 MTC0(&psxRegs, reg, val);
123 static void new_dyna_restore(void)
126 for (i = 0; i < PSXINT_COUNT; i++)
127 event_cycles[i] = psxRegs.intCycle[i].sCycle + psxRegs.intCycle[i].cycle;
129 event_cycles[PSXINT_RCNT] = psxNextsCounter + psxNextCounter;
130 psxRegs.interrupt |= 1 << PSXINT_RCNT;
131 psxRegs.interrupt &= (1 << PSXINT_COUNT) - 1;
133 new_dyna_pcsx_mem_load_state();
136 void new_dyna_freeze(void *f, int mode)
138 const char header_save[8] = "ariblks";
139 uint32_t addrs[1024 * 4];
144 if (mode != 0) { // save
145 size = new_dynarec_save_blocks(addrs, sizeof(addrs));
149 SaveFuncs.write(f, header_save, sizeof(header_save));
150 SaveFuncs.write(f, &size, sizeof(size));
151 SaveFuncs.write(f, addrs, size);
156 bytes = SaveFuncs.read(f, header, sizeof(header));
157 if (bytes != sizeof(header) || strcmp(header, header_save)) {
159 SaveFuncs.seek(f, -bytes, SEEK_CUR);
162 SaveFuncs.read(f, &size, sizeof(size));
165 if (size > sizeof(addrs)) {
166 bytes = size - sizeof(addrs);
167 SaveFuncs.seek(f, bytes, SEEK_CUR);
168 size = sizeof(addrs);
170 bytes = SaveFuncs.read(f, addrs, size);
174 if (psxCpu != &psxInt)
175 new_dynarec_load_blocks(addrs, size);
178 //printf("drc: %d block info entries %s\n", size/8, mode ? "saved" : "loaded");
181 #if !defined(DRC_DISABLE) && !defined(LIGHTREC)
184 void *gte_handlers[64];
186 void *gte_handlers_nf[64] = {
187 NULL , gteRTPS_nf , NULL , NULL , NULL , NULL , gteNCLIP_nf, NULL , // 00
188 NULL , NULL , NULL , NULL , gteOP_nf , NULL , NULL , NULL , // 08
189 gteDPCS_nf, gteINTPL_nf, gteMVMVA_nf, gteNCDS_nf, gteCDP_nf, NULL , gteNCDT_nf , NULL , // 10
190 NULL , NULL , NULL , gteNCCS_nf, gteCC_nf , NULL , gteNCS_nf , NULL , // 18
191 gteNCT_nf , NULL , NULL , NULL , NULL , NULL , NULL , NULL , // 20
192 gteSQR_nf , gteDCPL_nf , gteDPCT_nf , NULL , NULL , gteAVSZ3_nf, gteAVSZ4_nf, NULL , // 28
193 gteRTPT_nf, NULL , NULL , NULL , NULL , NULL , NULL , NULL , // 30
194 NULL , NULL , NULL , NULL , NULL , gteGPF_nf , gteGPL_nf , gteNCCT_nf, // 38
197 const char *gte_regnames[64] = {
198 NULL , "RTPS" , NULL , NULL , NULL , NULL , "NCLIP", NULL , // 00
199 NULL , NULL , NULL , NULL , "OP" , NULL , NULL , NULL , // 08
200 "DPCS", "INTPL", "MVMVA", "NCDS", "CDP", NULL , "NCDT" , NULL , // 10
201 NULL , NULL , NULL , "NCCS", "CC" , NULL , "NCS" , NULL , // 18
202 "NCT" , NULL , NULL , NULL , NULL , NULL , NULL , NULL , // 20
203 "SQR" , "DCPL" , "DPCT" , NULL , NULL , "AVSZ3", "AVSZ4", NULL , // 28
204 "RTPT", NULL , NULL , NULL , NULL , NULL , NULL , NULL , // 30
205 NULL , NULL , NULL , NULL , NULL , "GPF" , "GPL" , "NCCT", // 38
212 #define GCBITS3(b0,b1,b2) \
213 (GCBIT(b0) | GCBIT(b1) | GCBIT(b2))
214 #define GDBITS2(b0,b1) \
215 (GDBIT(b0) | GDBIT(b1))
216 #define GDBITS3(b0,b1,b2) \
217 (GDBITS2(b0,b1) | GDBIT(b2))
218 #define GDBITS4(b0,b1,b2,b3) \
219 (GDBITS3(b0,b1,b2) | GDBIT(b3))
220 #define GDBITS5(b0,b1,b2,b3,b4) \
221 (GDBITS4(b0,b1,b2,b3) | GDBIT(b4))
222 #define GDBITS6(b0,b1,b2,b3,b4,b5) \
223 (GDBITS5(b0,b1,b2,b3,b4) | GDBIT(b5))
224 #define GDBITS7(b0,b1,b2,b3,b4,b5,b6) \
225 (GDBITS6(b0,b1,b2,b3,b4,b5) | GDBIT(b6))
226 #define GDBITS8(b0,b1,b2,b3,b4,b5,b6,b7) \
227 (GDBITS7(b0,b1,b2,b3,b4,b5,b6) | GDBIT(b7))
228 #define GDBITS9(b0,b1,b2,b3,b4,b5,b6,b7,b8) \
229 (GDBITS8(b0,b1,b2,b3,b4,b5,b6,b7) | GDBIT(b8))
230 #define GDBITS10(b0,b1,b2,b3,b4,b5,b6,b7,b8,b9) \
231 (GDBITS9(b0,b1,b2,b3,b4,b5,b6,b7,b8) | GDBIT(b9))
233 const uint64_t gte_reg_reads[64] = {
234 [GTE_RTPS] = 0x1f0000ff00000000ll | GDBITS7(0,1,13,14,17,18,19),
235 [GTE_NCLIP] = GDBITS3(12,13,14),
236 [GTE_OP] = GCBITS3(0,2,4) | GDBITS3(9,10,11),
237 [GTE_DPCS] = GCBITS3(21,22,23) | GDBITS4(6,8,21,22),
238 [GTE_INTPL] = GCBITS3(21,22,23) | GDBITS7(6,8,9,10,11,21,22),
239 [GTE_MVMVA] = 0x00ffffff00000000ll | GDBITS9(0,1,2,3,4,5,9,10,11), // XXX: maybe decode further?
240 [GTE_NCDS] = 0x00ffff0000000000ll | GDBITS6(0,1,6,8,21,22),
241 [GTE_CDP] = 0x00ffe00000000000ll | GDBITS7(6,8,9,10,11,21,22),
242 [GTE_NCDT] = 0x00ffff0000000000ll | GDBITS8(0,1,2,3,4,5,6,8),
243 [GTE_NCCS] = 0x001fff0000000000ll | GDBITS5(0,1,6,21,22),
244 [GTE_CC] = 0x001fe00000000000ll | GDBITS6(6,9,10,11,21,22),
245 [GTE_NCS] = 0x001fff0000000000ll | GDBITS5(0,1,6,21,22),
246 [GTE_NCT] = 0x001fff0000000000ll | GDBITS7(0,1,2,3,4,5,6),
247 [GTE_SQR] = GDBITS3(9,10,11),
248 [GTE_DCPL] = GCBITS3(21,22,23) | GDBITS7(6,8,9,10,11,21,22),
249 [GTE_DPCT] = GCBITS3(21,22,23) | GDBITS4(8,20,21,22),
250 [GTE_AVSZ3] = GCBIT(29) | GDBITS3(17,18,19),
251 [GTE_AVSZ4] = GCBIT(30) | GDBITS4(16,17,18,19),
252 [GTE_RTPT] = 0x1f0000ff00000000ll | GDBITS7(0,1,2,3,4,5,19),
253 [GTE_GPF] = GDBITS7(6,8,9,10,11,21,22),
254 [GTE_GPL] = GDBITS10(6,8,9,10,11,21,22,25,26,27),
255 [GTE_NCCT] = 0x001fff0000000000ll | GDBITS7(0,1,2,3,4,5,6),
258 // note: this excludes gteFLAG that is always written to
259 const uint64_t gte_reg_writes[64] = {
260 [GTE_RTPS] = 0x0f0f7f00ll,
261 [GTE_NCLIP] = GDBIT(24),
262 [GTE_OP] = GDBITS6(9,10,11,25,26,27),
263 [GTE_DPCS] = GDBITS9(9,10,11,20,21,22,25,26,27),
264 [GTE_INTPL] = GDBITS9(9,10,11,20,21,22,25,26,27),
265 [GTE_MVMVA] = GDBITS6(9,10,11,25,26,27),
266 [GTE_NCDS] = GDBITS9(9,10,11,20,21,22,25,26,27),
267 [GTE_CDP] = GDBITS9(9,10,11,20,21,22,25,26,27),
268 [GTE_NCDT] = GDBITS9(9,10,11,20,21,22,25,26,27),
269 [GTE_NCCS] = GDBITS9(9,10,11,20,21,22,25,26,27),
270 [GTE_CC] = GDBITS9(9,10,11,20,21,22,25,26,27),
271 [GTE_NCS] = GDBITS9(9,10,11,20,21,22,25,26,27),
272 [GTE_NCT] = GDBITS9(9,10,11,20,21,22,25,26,27),
273 [GTE_SQR] = GDBITS6(9,10,11,25,26,27),
274 [GTE_DCPL] = GDBITS9(9,10,11,20,21,22,25,26,27),
275 [GTE_DPCT] = GDBITS9(9,10,11,20,21,22,25,26,27),
276 [GTE_AVSZ3] = GDBITS2(7,24),
277 [GTE_AVSZ4] = GDBITS2(7,24),
278 [GTE_RTPT] = 0x0f0f7f00ll,
279 [GTE_GPF] = GDBITS9(9,10,11,20,21,22,25,26,27),
280 [GTE_GPL] = GDBITS9(9,10,11,20,21,22,25,26,27),
281 [GTE_NCCT] = GDBITS9(9,10,11,20,21,22,25,26,27),
284 static int ari64_init()
286 static u32 scratch_buf[8*8*2] __attribute__((aligned(64)));
290 new_dyna_pcsx_mem_init();
292 for (i = 0; i < ARRAY_SIZE(gte_handlers); i++)
293 if (psxCP2[i] != gteNULL)
294 gte_handlers[i] = psxCP2[i];
296 #if defined(__arm__) && !defined(DRC_DBG)
297 gte_handlers[0x06] = gteNCLIP_arm;
299 gte_handlers_nf[0x01] = gteRTPS_nf_arm;
300 gte_handlers_nf[0x30] = gteRTPT_nf_arm;
303 // compiler's _nf version is still a lot slower than neon
304 // _nf_arm RTPS is roughly the same, RTPT slower
305 gte_handlers[0x01] = gte_handlers_nf[0x01] = gteRTPS_neon;
306 gte_handlers[0x30] = gte_handlers_nf[0x30] = gteRTPT_neon;
310 memcpy(gte_handlers_nf, gte_handlers, sizeof(gte_handlers_nf));
313 zeromem_ptr = zero_mem;
314 scratch_buf_ptr = scratch_buf;
319 static void ari64_reset()
321 new_dyna_pcsx_mem_reset();
322 new_dynarec_invalidate_all_pages();
324 pending_exception = 1;
327 // execute until predefined leave points
328 // (HLE softcall exit and BIOS fastboot end)
329 static void ari64_execute_until()
331 schedule_timeslice();
333 evprintf("ari64_execute %08x, %u->%u (%d)\n", psxRegs.pc,
334 psxRegs.cycle, next_interupt, next_interupt - psxRegs.cycle);
336 new_dyna_start(dynarec_local);
338 evprintf("ari64_execute end %08x, %u->%u (%d)\n", psxRegs.pc,
339 psxRegs.cycle, next_interupt, next_interupt - psxRegs.cycle);
342 static void ari64_execute()
345 ari64_execute_until();
346 evprintf("drc left @%08x\n", psxRegs.pc);
350 static void ari64_clear(u32 addr, u32 size)
352 size *= 4; /* PCSX uses DMA units (words) */
354 evprintf("ari64_clear %08x %04x\n", addr, size);
356 new_dynarec_invalidate_range(addr, addr + size);
359 static void ari64_notify(enum R3000Anote note, void *data) {
362 case R3000ACPU_NOTIFY_CACHE_UNISOLATED:
363 case R3000ACPU_NOTIFY_CACHE_ISOLATED:
364 new_dyna_pcsx_mem_isolate(note == R3000ACPU_NOTIFY_CACHE_ISOLATED);
366 case R3000ACPU_NOTIFY_BEFORE_SAVE:
368 case R3000ACPU_NOTIFY_AFTER_LOAD:
374 static void ari64_apply_config()
378 if (Config.DisableStalls)
379 new_dynarec_hacks |= NDHACK_NO_STALLS;
381 new_dynarec_hacks &= ~NDHACK_NO_STALLS;
383 if (Config.cycle_multiplier != cycle_multiplier_old
384 || new_dynarec_hacks != new_dynarec_hacks_old)
386 new_dynarec_clear_full();
390 static void ari64_shutdown()
392 new_dynarec_cleanup();
393 new_dyna_pcsx_mem_shutdown();
407 #else // if DRC_DISABLE
409 unsigned int address;
410 int pending_exception, stop;
411 unsigned int next_interupt;
412 int new_dynarec_did_compile;
413 int cycle_multiplier_old;
414 int new_dynarec_hacks_pergame;
415 int new_dynarec_hacks_old;
416 int new_dynarec_hacks;
419 u32 zero_mem[0x1000/4];
421 void *scratch_buf_ptr;
422 void new_dynarec_init() {}
423 void new_dyna_start(void *context) {}
424 void new_dynarec_cleanup() {}
425 void new_dynarec_clear_full() {}
426 void new_dynarec_invalidate_all_pages() {}
427 void new_dynarec_invalidate_range(unsigned int start, unsigned int end) {}
428 void new_dyna_pcsx_mem_init(void) {}
429 void new_dyna_pcsx_mem_reset(void) {}
430 void new_dyna_pcsx_mem_load_state(void) {}
431 void new_dyna_pcsx_mem_isolate(int enable) {}
432 void new_dyna_pcsx_mem_shutdown(void) {}
433 int new_dynarec_save_blocks(void *save, int size) { return 0; }
434 void new_dynarec_load_blocks(const void *save, int size) {}
445 void dump_mem(const char *fname, void *mem, size_t size)
447 FILE *f1 = fopen(fname, "wb");
449 f1 = fopen(strrchr(fname, '/') + 1, "wb");
450 fwrite(mem, 1, size, f1);
454 static u32 memcheck_read(u32 a)
456 if ((a >> 16) == 0x1f80)
458 return *(u32 *)(psxH + (a & 0xfffc));
460 if ((a >> 16) == 0x1f00)
462 return *(u32 *)(psxP + (a & 0xfffc));
464 // if ((a & ~0xe0600000) < 0x200000)
466 return *(u32 *)(psxM + (a & 0x1ffffc));
470 void do_insn_trace(void)
472 static psxRegisters oldregs;
473 static u32 event_cycles_o[PSXINT_COUNT];
474 u32 *allregs_p = (void *)&psxRegs;
475 u32 *allregs_o = (void *)&oldregs;
480 //last_io_addr = 0x5e2c8;
482 f = fopen("tracelog", "wb");
485 oldregs.code = psxRegs.code; // don't care
486 for (i = 0; i < offsetof(psxRegisters, intCycle) / 4; i++) {
487 if (allregs_p[i] != allregs_o[i]) {
489 fwrite(&allregs_p[i], 1, 4, f);
490 allregs_o[i] = allregs_p[i];
494 for (i = 0; i < PSXINT_COUNT; i++) {
495 if (event_cycles[i] != event_cycles_o[i]) {
497 fwrite(&byte, 1, 1, f);
499 fwrite(&event_cycles[i], 1, 4, f);
500 event_cycles_o[i] = event_cycles[i];
503 #define SAVE_IF_CHANGED(code_, name_) { \
504 static u32 old_##name_ = 0xbad0c0de; \
505 if (old_##name_ != name_) { \
507 fwrite(&byte, 1, 1, f); \
508 fwrite(&name_, 1, 4, f); \
509 old_##name_ = name_; \
512 SAVE_IF_CHANGED(0xfb, irq_test_cycle);
513 SAVE_IF_CHANGED(0xfc, handler_cycle);
514 SAVE_IF_CHANGED(0xfd, last_io_addr);
515 io_data = memcheck_read(last_io_addr);
516 SAVE_IF_CHANGED(0xfe, io_data);
518 fwrite(&byte, 1, 1, f);
521 if (psxRegs.cycle == 190230) {
522 dump_mem("/mnt/ntz/dev/pnd/tmp/psxram_i.dump", psxM, 0x200000);
523 dump_mem("/mnt/ntz/dev/pnd/tmp/psxregs_i.dump", psxH, 0x10000);
531 static const char *regnames[offsetof(psxRegisters, intCycle) / 4] = {
532 "r0", "r1", "r2", "r3", "r4", "r5", "r6", "r7",
533 "r8", "r9", "r10", "r11", "r12", "r13", "r14", "r15",
534 "r16", "r17", "r18", "r19", "r20", "r21", "r22", "r23",
535 "r24", "r25", "r26", "r27", "r28", "r29", "r30", "r31",
537 "C0_0", "C0_1", "C0_2", "C0_3", "C0_4", "C0_5", "C0_6", "C0_7",
538 "C0_8", "C0_9", "C0_10", "C0_11", "C0_12", "C0_13", "C0_14", "C0_15",
539 "C0_16", "C0_17", "C0_18", "C0_19", "C0_20", "C0_21", "C0_22", "C0_23",
540 "C0_24", "C0_25", "C0_26", "C0_27", "C0_28", "C0_29", "C0_30", "C0_31",
542 "C2D0", "C2D1", "C2D2", "C2D3", "C2D4", "C2D5", "C2D6", "C2D7",
543 "C2D8", "C2D9", "C2D10", "C2D11", "C2D12", "C2D13", "C2D14", "C2D15",
544 "C2D16", "C2D17", "C2D18", "C2D19", "C2D20", "C2D21", "C2D22", "C2D23",
545 "C2D24", "C2D25", "C2D26", "C2D27", "C2D28", "C2D29", "C2D30", "C2D31",
547 "C2C0", "C2C1", "C2C2", "C2C3", "C2C4", "C2C5", "C2C6", "C2C7",
548 "C2C8", "C2C9", "C2C10", "C2C11", "C2C12", "C2C13", "C2C14", "C2C15",
549 "C2C16", "C2C17", "C2C18", "C2C19", "C2C20", "C2C21", "C2C22", "C2C23",
550 "C2C24", "C2C25", "C2C26", "C2C27", "C2C28", "C2C29", "C2C30", "C2C31",
552 "PC", "code", "cycle", "interrupt",
560 static int miss_log_i;
561 #define miss_log_len (sizeof(miss_log)/sizeof(miss_log[0]))
562 #define miss_log_mask (miss_log_len-1)
564 static void miss_log_add(int reg, u32 val, u32 val_expect, u32 pc, u32 cycle)
566 miss_log[miss_log_i].reg = reg;
567 miss_log[miss_log_i].val = val;
568 miss_log[miss_log_i].val_expect = val_expect;
569 miss_log[miss_log_i].pc = pc;
570 miss_log[miss_log_i].cycle = cycle;
571 miss_log_i = (miss_log_i + 1) & miss_log_mask;
576 void do_insn_cmp(void)
578 extern int last_count;
579 static psxRegisters rregs;
580 static u32 mem_addr, mem_val;
581 static u32 irq_test_cycle_intr;
582 static u32 handler_cycle_intr;
583 u32 *allregs_p = (void *)&psxRegs;
584 u32 *allregs_e = (void *)&rregs;
585 static u32 ppc, failcount;
586 int i, ret, bad = 0, fatal = 0, which_event = -1;
591 f = fopen("tracelog", "rb");
594 if ((ret = fread(&code, 1, 1, f)) <= 0)
603 fread(&which_event, 1, 1, f);
604 fread(&ev_cycles, 1, 4, f);
607 fread(&irq_test_cycle_intr, 1, 4, f);
610 fread(&handler_cycle_intr, 1, 4, f);
613 fread(&mem_addr, 1, 4, f);
616 fread(&mem_val, 1, 4, f);
619 assert(code < offsetof(psxRegisters, intCycle) / 4);
620 fread(&allregs_e[code], 1, 4, f);
628 psxRegs.code = rregs.code; // don't care
629 psxRegs.cycle += last_count;
630 //psxRegs.cycle = rregs.cycle; // needs reload in _cmp
631 psxRegs.CP0.r[9] = rregs.CP0.r[9]; // Count
633 //if (psxRegs.cycle == 166172) breakme();
635 if (which_event >= 0 && event_cycles[which_event] != ev_cycles) {
636 printf("bad ev_cycles #%d: %u %u / %u\n", which_event,
637 event_cycles[which_event], ev_cycles, psxRegs.cycle);
641 if (irq_test_cycle > irq_test_cycle_intr) {
642 printf("bad irq_test_cycle: %u %u\n", irq_test_cycle, irq_test_cycle_intr);
646 if (handler_cycle != handler_cycle_intr) {
647 printf("bad handler_cycle: %u %u\n", handler_cycle, handler_cycle_intr);
651 if (mem_val != memcheck_read(mem_addr)) {
652 printf("bad mem @%08x: %08x %08x\n", mem_addr, memcheck_read(mem_addr), mem_val);
656 if (!fatal && !memcmp(&psxRegs, &rregs, offsetof(psxRegisters, intCycle))) {
661 for (i = 0; i < offsetof(psxRegisters, intCycle) / 4; i++) {
662 if (allregs_p[i] != allregs_e[i]) {
663 miss_log_add(i, allregs_p[i], allregs_e[i], psxRegs.pc, psxRegs.cycle);
670 if (!fatal && psxRegs.pc == rregs.pc && bad < 6 && failcount < 32) {
671 static int last_mcycle;
672 if (last_mcycle != psxRegs.cycle >> 20) {
673 printf("%u\n", psxRegs.cycle);
674 last_mcycle = psxRegs.cycle >> 20;
680 for (i = 0; i < miss_log_len; i++, miss_log_i = (miss_log_i + 1) & miss_log_mask)
681 printf("bad %5s: %08x %08x, pc=%08x, cycle %u\n",
682 regnames[miss_log[miss_log_i].reg], miss_log[miss_log_i].val,
683 miss_log[miss_log_i].val_expect, miss_log[miss_log_i].pc, miss_log[miss_log_i].cycle);
684 printf("-- %d\n", bad);
685 for (i = 0; i < 8; i++)
686 printf("r%d=%08x r%2d=%08x r%2d=%08x r%2d=%08x\n", i, allregs_p[i],
687 i+8, allregs_p[i+8], i+16, allregs_p[i+16], i+24, allregs_p[i+24]);
688 printf("PC: %08x/%08x, cycle %u, next %u\n", psxRegs.pc, ppc, psxRegs.cycle, next_interupt);
689 //dump_mem("/tmp/psxram.dump", psxM, 0x200000);
690 //dump_mem("/mnt/ntz/dev/pnd/tmp/psxregs.dump", psxH, 0x10000);
693 //psxRegs.cycle = rregs.cycle + 2; // sync timing