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 typedef void (irq_func)();
51 static irq_func * const irq_funcs[] = {
52 [PSXINT_SIO] = sioInterrupt,
53 [PSXINT_CDR] = cdrInterrupt,
54 [PSXINT_CDREAD] = cdrReadInterrupt,
55 [PSXINT_GPUDMA] = gpuInterrupt,
56 [PSXINT_MDECOUTDMA] = mdec1Interrupt,
57 [PSXINT_SPUDMA] = spuInterrupt,
58 [PSXINT_MDECINDMA] = mdec0Interrupt,
59 [PSXINT_GPUOTCDMA] = gpuotcInterrupt,
60 [PSXINT_CDRDMA] = cdrDmaInterrupt,
61 [PSXINT_CDRLID] = cdrLidSeekInterrupt,
62 [PSXINT_CDRPLAY] = cdrPlayInterrupt,
63 [PSXINT_SPU_UPDATE] = spuUpdate,
64 [PSXINT_RCNT] = psxRcntUpdate,
67 /* local dupe of psxBranchTest, using event_cycles */
68 static void irq_test(void)
70 u32 cycle = psxRegs.cycle;
73 for (irq = 0, irq_bits = psxRegs.interrupt; irq_bits != 0; irq++, irq_bits >>= 1) {
76 if ((s32)(cycle - event_cycles[irq]) >= 0) {
77 // note: irq_funcs() also modify psxRegs.interrupt
78 psxRegs.interrupt &= ~(1u << irq);
83 if ((psxHu32(0x1070) & psxHu32(0x1074)) && (Status & 0x401) == 0x401) {
84 psxException(0x400, 0);
85 pending_exception = 1;
91 evprintf(" +ge %08x, %u->%u\n", psxRegs.pc, psxRegs.cycle, next_interupt);
95 //pending_exception = 1;
99 evprintf(" -ge %08x, %u->%u (%d)\n", psxRegs.pc, psxRegs.cycle,
100 next_interupt, next_interupt - psxRegs.cycle);
104 extern void MTC0(int reg, u32 val);
106 void pcsx_mtc0(u32 reg, u32 val)
108 evprintf("MTC0 %d #%x @%08x %u\n", reg, val, psxRegs.pc, psxRegs.cycle);
111 if (Cause & Status & 0x0300) // possible sw irq
112 pending_exception = 1;
115 void pcsx_mtc0_ds(u32 reg, u32 val)
117 evprintf("MTC0 %d #%x @%08x %u\n", reg, val, psxRegs.pc, psxRegs.cycle);
121 void new_dyna_before_save(void)
123 psxRegs.interrupt &= ~(1 << PSXINT_RCNT); // old savestate compat
125 // psxRegs.intCycle is always maintained, no need to convert
128 void new_dyna_after_save(void)
130 psxRegs.interrupt |= 1 << PSXINT_RCNT;
133 static void new_dyna_restore(void)
136 for (i = 0; i < PSXINT_COUNT; i++)
137 event_cycles[i] = psxRegs.intCycle[i].sCycle + psxRegs.intCycle[i].cycle;
139 event_cycles[PSXINT_RCNT] = psxNextsCounter + psxNextCounter;
140 psxRegs.interrupt |= 1 << PSXINT_RCNT;
141 psxRegs.interrupt &= (1 << PSXINT_COUNT) - 1;
143 new_dyna_pcsx_mem_load_state();
146 void new_dyna_freeze(void *f, int mode)
148 const char header_save[8] = "ariblks";
149 uint32_t addrs[1024 * 4];
154 if (mode != 0) { // save
155 size = new_dynarec_save_blocks(addrs, sizeof(addrs));
159 SaveFuncs.write(f, header_save, sizeof(header_save));
160 SaveFuncs.write(f, &size, sizeof(size));
161 SaveFuncs.write(f, addrs, size);
166 bytes = SaveFuncs.read(f, header, sizeof(header));
167 if (bytes != sizeof(header) || strcmp(header, header_save)) {
169 SaveFuncs.seek(f, -bytes, SEEK_CUR);
172 SaveFuncs.read(f, &size, sizeof(size));
175 if (size > sizeof(addrs)) {
176 bytes = size - sizeof(addrs);
177 SaveFuncs.seek(f, bytes, SEEK_CUR);
178 size = sizeof(addrs);
180 bytes = SaveFuncs.read(f, addrs, size);
184 if (psxCpu != &psxInt)
185 new_dynarec_load_blocks(addrs, size);
188 //printf("drc: %d block info entries %s\n", size/8, mode ? "saved" : "loaded");
194 void *gte_handlers[64];
196 void *gte_handlers_nf[64] = {
197 NULL , gteRTPS_nf , NULL , NULL , NULL , NULL , gteNCLIP_nf, NULL , // 00
198 NULL , NULL , NULL , NULL , gteOP_nf , NULL , NULL , NULL , // 08
199 gteDPCS_nf, gteINTPL_nf, gteMVMVA_nf, gteNCDS_nf, gteCDP_nf, NULL , gteNCDT_nf , NULL , // 10
200 NULL , NULL , NULL , gteNCCS_nf, gteCC_nf , NULL , gteNCS_nf , NULL , // 18
201 gteNCT_nf , NULL , NULL , NULL , NULL , NULL , NULL , NULL , // 20
202 gteSQR_nf , gteDCPL_nf , gteDPCT_nf , NULL , NULL , gteAVSZ3_nf, gteAVSZ4_nf, NULL , // 28
203 gteRTPT_nf, NULL , NULL , NULL , NULL , NULL , NULL , NULL , // 30
204 NULL , NULL , NULL , NULL , NULL , gteGPF_nf , gteGPL_nf , gteNCCT_nf, // 38
207 const char *gte_regnames[64] = {
208 NULL , "RTPS" , NULL , NULL , NULL , NULL , "NCLIP", NULL , // 00
209 NULL , NULL , NULL , NULL , "OP" , NULL , NULL , NULL , // 08
210 "DPCS", "INTPL", "MVMVA", "NCDS", "CDP", NULL , "NCDT" , NULL , // 10
211 NULL , NULL , NULL , "NCCS", "CC" , NULL , "NCS" , NULL , // 18
212 "NCT" , NULL , NULL , NULL , NULL , NULL , NULL , NULL , // 20
213 "SQR" , "DCPL" , "DPCT" , NULL , NULL , "AVSZ3", "AVSZ4", NULL , // 28
214 "RTPT", NULL , NULL , NULL , NULL , NULL , NULL , NULL , // 30
215 NULL , NULL , NULL , NULL , NULL , "GPF" , "GPL" , "NCCT", // 38
222 #define GCBITS3(b0,b1,b2) \
223 (GCBIT(b0) | GCBIT(b1) | GCBIT(b2))
224 #define GDBITS2(b0,b1) \
225 (GDBIT(b0) | GDBIT(b1))
226 #define GDBITS3(b0,b1,b2) \
227 (GDBITS2(b0,b1) | GDBIT(b2))
228 #define GDBITS4(b0,b1,b2,b3) \
229 (GDBITS3(b0,b1,b2) | GDBIT(b3))
230 #define GDBITS5(b0,b1,b2,b3,b4) \
231 (GDBITS4(b0,b1,b2,b3) | GDBIT(b4))
232 #define GDBITS6(b0,b1,b2,b3,b4,b5) \
233 (GDBITS5(b0,b1,b2,b3,b4) | GDBIT(b5))
234 #define GDBITS7(b0,b1,b2,b3,b4,b5,b6) \
235 (GDBITS6(b0,b1,b2,b3,b4,b5) | GDBIT(b6))
236 #define GDBITS8(b0,b1,b2,b3,b4,b5,b6,b7) \
237 (GDBITS7(b0,b1,b2,b3,b4,b5,b6) | GDBIT(b7))
238 #define GDBITS9(b0,b1,b2,b3,b4,b5,b6,b7,b8) \
239 (GDBITS8(b0,b1,b2,b3,b4,b5,b6,b7) | GDBIT(b8))
240 #define GDBITS10(b0,b1,b2,b3,b4,b5,b6,b7,b8,b9) \
241 (GDBITS9(b0,b1,b2,b3,b4,b5,b6,b7,b8) | GDBIT(b9))
243 const uint64_t gte_reg_reads[64] = {
244 [GTE_RTPS] = 0x1f0000ff00000000ll | GDBITS7(0,1,13,14,17,18,19),
245 [GTE_NCLIP] = GDBITS3(12,13,14),
246 [GTE_OP] = GCBITS3(0,2,4) | GDBITS3(9,10,11),
247 [GTE_DPCS] = GCBITS3(21,22,23) | GDBITS4(6,8,21,22),
248 [GTE_INTPL] = GCBITS3(21,22,23) | GDBITS7(6,8,9,10,11,21,22),
249 [GTE_MVMVA] = 0x00ffffff00000000ll | GDBITS9(0,1,2,3,4,5,9,10,11), // XXX: maybe decode further?
250 [GTE_NCDS] = 0x00ffff0000000000ll | GDBITS6(0,1,6,8,21,22),
251 [GTE_CDP] = 0x00ffe00000000000ll | GDBITS7(6,8,9,10,11,21,22),
252 [GTE_NCDT] = 0x00ffff0000000000ll | GDBITS8(0,1,2,3,4,5,6,8),
253 [GTE_NCCS] = 0x001fff0000000000ll | GDBITS5(0,1,6,21,22),
254 [GTE_CC] = 0x001fe00000000000ll | GDBITS6(6,9,10,11,21,22),
255 [GTE_NCS] = 0x001fff0000000000ll | GDBITS5(0,1,6,21,22),
256 [GTE_NCT] = 0x001fff0000000000ll | GDBITS7(0,1,2,3,4,5,6),
257 [GTE_SQR] = GDBITS3(9,10,11),
258 [GTE_DCPL] = GCBITS3(21,22,23) | GDBITS7(6,8,9,10,11,21,22),
259 [GTE_DPCT] = GCBITS3(21,22,23) | GDBITS4(8,20,21,22),
260 [GTE_AVSZ3] = GCBIT(29) | GDBITS3(17,18,19),
261 [GTE_AVSZ4] = GCBIT(30) | GDBITS4(16,17,18,19),
262 [GTE_RTPT] = 0x1f0000ff00000000ll | GDBITS7(0,1,2,3,4,5,19),
263 [GTE_GPF] = GDBITS7(6,8,9,10,11,21,22),
264 [GTE_GPL] = GDBITS10(6,8,9,10,11,21,22,25,26,27),
265 [GTE_NCCT] = 0x001fff0000000000ll | GDBITS7(0,1,2,3,4,5,6),
268 // note: this excludes gteFLAG that is always written to
269 const uint64_t gte_reg_writes[64] = {
270 [GTE_RTPS] = 0x0f0f7f00ll,
271 [GTE_NCLIP] = GDBIT(24),
272 [GTE_OP] = GDBITS6(9,10,11,25,26,27),
273 [GTE_DPCS] = GDBITS9(9,10,11,20,21,22,25,26,27),
274 [GTE_INTPL] = GDBITS9(9,10,11,20,21,22,25,26,27),
275 [GTE_MVMVA] = GDBITS6(9,10,11,25,26,27),
276 [GTE_NCDS] = GDBITS9(9,10,11,20,21,22,25,26,27),
277 [GTE_CDP] = GDBITS9(9,10,11,20,21,22,25,26,27),
278 [GTE_NCDT] = GDBITS9(9,10,11,20,21,22,25,26,27),
279 [GTE_NCCS] = GDBITS9(9,10,11,20,21,22,25,26,27),
280 [GTE_CC] = GDBITS9(9,10,11,20,21,22,25,26,27),
281 [GTE_NCS] = GDBITS9(9,10,11,20,21,22,25,26,27),
282 [GTE_NCT] = GDBITS9(9,10,11,20,21,22,25,26,27),
283 [GTE_SQR] = GDBITS6(9,10,11,25,26,27),
284 [GTE_DCPL] = GDBITS9(9,10,11,20,21,22,25,26,27),
285 [GTE_DPCT] = GDBITS9(9,10,11,20,21,22,25,26,27),
286 [GTE_AVSZ3] = GDBITS2(7,24),
287 [GTE_AVSZ4] = GDBITS2(7,24),
288 [GTE_RTPT] = 0x0f0f7f00ll,
289 [GTE_GPF] = GDBITS9(9,10,11,20,21,22,25,26,27),
290 [GTE_GPL] = GDBITS9(9,10,11,20,21,22,25,26,27),
291 [GTE_NCCT] = GDBITS9(9,10,11,20,21,22,25,26,27),
294 static int ari64_init()
296 static u32 scratch_buf[8*8*2] __attribute__((aligned(64)));
297 extern void (*psxCP2[64])();
298 extern void psxNULL();
302 new_dyna_pcsx_mem_init();
304 for (i = 0; i < ARRAY_SIZE(gte_handlers); i++)
305 if (psxCP2[i] != psxNULL)
306 gte_handlers[i] = psxCP2[i];
308 #if defined(__arm__) && !defined(DRC_DBG)
309 gte_handlers[0x06] = gteNCLIP_arm;
311 gte_handlers_nf[0x01] = gteRTPS_nf_arm;
312 gte_handlers_nf[0x30] = gteRTPT_nf_arm;
315 // compiler's _nf version is still a lot slower than neon
316 // _nf_arm RTPS is roughly the same, RTPT slower
317 gte_handlers[0x01] = gte_handlers_nf[0x01] = gteRTPS_neon;
318 gte_handlers[0x30] = gte_handlers_nf[0x30] = gteRTPT_neon;
322 memcpy(gte_handlers_nf, gte_handlers, sizeof(gte_handlers_nf));
325 zeromem_ptr = zero_mem;
326 scratch_buf_ptr = scratch_buf;
331 static void ari64_reset()
333 printf("ari64_reset\n");
334 new_dyna_pcsx_mem_reset();
335 invalidate_all_pages();
337 pending_exception = 1;
340 // execute until predefined leave points
341 // (HLE softcall exit and BIOS fastboot end)
342 static void ari64_execute_until()
344 schedule_timeslice();
346 evprintf("ari64_execute %08x, %u->%u (%d)\n", psxRegs.pc,
347 psxRegs.cycle, next_interupt, next_interupt - psxRegs.cycle);
349 new_dyna_start(dynarec_local);
351 evprintf("ari64_execute end %08x, %u->%u (%d)\n", psxRegs.pc,
352 psxRegs.cycle, next_interupt, next_interupt - psxRegs.cycle);
355 static void ari64_execute()
358 ari64_execute_until();
359 evprintf("drc left @%08x\n", psxRegs.pc);
363 static void ari64_clear(u32 addr, u32 size)
365 u32 start, end, main_ram;
367 size *= 4; /* PCSX uses DMA units (words) */
369 evprintf("ari64_clear %08x %04x\n", addr, size);
371 /* check for RAM mirrors */
372 main_ram = (addr & 0xffe00000) == 0x80000000;
375 end = (addr + size) >> 12;
377 for (; start <= end; start++)
378 if (!main_ram || !invalid_code[start])
379 invalidate_block(start);
382 static void ari64_notify(int note, void *data) {
384 Should be fixed when ARM dynarec has proper icache emulation.
387 case R3000ACPU_NOTIFY_CACHE_UNISOLATED:
389 case R3000ACPU_NOTIFY_CACHE_ISOLATED:
391 case R3000ACPU_NOTIFY_DMA3_EXE_LOAD:
398 static void ari64_apply_config()
402 if (Config.DisableStalls)
403 new_dynarec_hacks |= NDHACK_NO_STALLS;
405 new_dynarec_hacks &= ~NDHACK_NO_STALLS;
407 if (cycle_multiplier != cycle_multiplier_old
408 || new_dynarec_hacks != new_dynarec_hacks_old)
410 new_dynarec_clear_full();
414 static void ari64_shutdown()
416 new_dynarec_cleanup();
417 new_dyna_pcsx_mem_shutdown();
431 #else // if DRC_DISABLE
433 unsigned int address;
434 int pending_exception, stop;
435 unsigned int next_interupt;
436 int new_dynarec_did_compile;
437 int cycle_multiplier;
438 int cycle_multiplier_override;
439 int cycle_multiplier_old;
440 int new_dynarec_hacks_pergame;
441 int new_dynarec_hacks_old;
442 int new_dynarec_hacks;
447 void *scratch_buf_ptr;
448 void new_dynarec_init() {}
449 void new_dyna_start(void *context) {}
450 void new_dynarec_cleanup() {}
451 void new_dynarec_clear_full() {}
452 void invalidate_all_pages() {}
453 void invalidate_block(unsigned int block) {}
454 void new_dyna_pcsx_mem_init(void) {}
455 void new_dyna_pcsx_mem_reset(void) {}
456 void new_dyna_pcsx_mem_load_state(void) {}
457 void new_dyna_pcsx_mem_shutdown(void) {}
458 int new_dynarec_save_blocks(void *save, int size) { return 0; }
459 void new_dynarec_load_blocks(const void *save, int size) {}
470 void dump_mem(const char *fname, void *mem, size_t size)
472 FILE *f1 = fopen(fname, "wb");
474 f1 = fopen(strrchr(fname, '/') + 1, "wb");
475 fwrite(mem, 1, size, f1);
479 static u32 memcheck_read(u32 a)
481 if ((a >> 16) == 0x1f80)
483 return *(u32 *)(psxH + (a & 0xfffc));
485 if ((a >> 16) == 0x1f00)
487 return *(u32 *)(psxP + (a & 0xfffc));
489 // if ((a & ~0xe0600000) < 0x200000)
491 return *(u32 *)(psxM + (a & 0x1ffffc));
495 void do_insn_trace(void)
497 static psxRegisters oldregs;
498 static u32 event_cycles_o[PSXINT_COUNT];
499 u32 *allregs_p = (void *)&psxRegs;
500 u32 *allregs_o = (void *)&oldregs;
505 //last_io_addr = 0x5e2c8;
507 f = fopen("tracelog", "wb");
510 oldregs.code = psxRegs.code; // don't care
511 for (i = 0; i < offsetof(psxRegisters, intCycle) / 4; i++) {
512 if (allregs_p[i] != allregs_o[i]) {
514 fwrite(&allregs_p[i], 1, 4, f);
515 allregs_o[i] = allregs_p[i];
519 for (i = 0; i < PSXINT_COUNT; i++) {
520 if (event_cycles[i] != event_cycles_o[i]) {
522 fwrite(&byte, 1, 1, f);
524 fwrite(&event_cycles[i], 1, 4, f);
525 event_cycles_o[i] = event_cycles[i];
528 #define SAVE_IF_CHANGED(code_, name_) { \
529 static u32 old_##name_ = 0xbad0c0de; \
530 if (old_##name_ != name_) { \
532 fwrite(&byte, 1, 1, f); \
533 fwrite(&name_, 1, 4, f); \
534 old_##name_ = name_; \
537 SAVE_IF_CHANGED(0xfb, irq_test_cycle);
538 SAVE_IF_CHANGED(0xfc, handler_cycle);
539 SAVE_IF_CHANGED(0xfd, last_io_addr);
540 io_data = memcheck_read(last_io_addr);
541 SAVE_IF_CHANGED(0xfe, io_data);
543 fwrite(&byte, 1, 1, f);
546 if (psxRegs.cycle == 190230) {
547 dump_mem("/mnt/ntz/dev/pnd/tmp/psxram_i.dump", psxM, 0x200000);
548 dump_mem("/mnt/ntz/dev/pnd/tmp/psxregs_i.dump", psxH, 0x10000);
556 static const char *regnames[offsetof(psxRegisters, intCycle) / 4] = {
557 "r0", "r1", "r2", "r3", "r4", "r5", "r6", "r7",
558 "r8", "r9", "r10", "r11", "r12", "r13", "r14", "r15",
559 "r16", "r17", "r18", "r19", "r20", "r21", "r22", "r23",
560 "r24", "r25", "r26", "r27", "r28", "r29", "r30", "r31",
562 "C0_0", "C0_1", "C0_2", "C0_3", "C0_4", "C0_5", "C0_6", "C0_7",
563 "C0_8", "C0_9", "C0_10", "C0_11", "C0_12", "C0_13", "C0_14", "C0_15",
564 "C0_16", "C0_17", "C0_18", "C0_19", "C0_20", "C0_21", "C0_22", "C0_23",
565 "C0_24", "C0_25", "C0_26", "C0_27", "C0_28", "C0_29", "C0_30", "C0_31",
567 "C2D0", "C2D1", "C2D2", "C2D3", "C2D4", "C2D5", "C2D6", "C2D7",
568 "C2D8", "C2D9", "C2D10", "C2D11", "C2D12", "C2D13", "C2D14", "C2D15",
569 "C2D16", "C2D17", "C2D18", "C2D19", "C2D20", "C2D21", "C2D22", "C2D23",
570 "C2D24", "C2D25", "C2D26", "C2D27", "C2D28", "C2D29", "C2D30", "C2D31",
572 "C2C0", "C2C1", "C2C2", "C2C3", "C2C4", "C2C5", "C2C6", "C2C7",
573 "C2C8", "C2C9", "C2C10", "C2C11", "C2C12", "C2C13", "C2C14", "C2C15",
574 "C2C16", "C2C17", "C2C18", "C2C19", "C2C20", "C2C21", "C2C22", "C2C23",
575 "C2C24", "C2C25", "C2C26", "C2C27", "C2C28", "C2C29", "C2C30", "C2C31",
577 "PC", "code", "cycle", "interrupt",
585 static int miss_log_i;
586 #define miss_log_len (sizeof(miss_log)/sizeof(miss_log[0]))
587 #define miss_log_mask (miss_log_len-1)
589 static void miss_log_add(int reg, u32 val, u32 val_expect, u32 pc, u32 cycle)
591 miss_log[miss_log_i].reg = reg;
592 miss_log[miss_log_i].val = val;
593 miss_log[miss_log_i].val_expect = val_expect;
594 miss_log[miss_log_i].pc = pc;
595 miss_log[miss_log_i].cycle = cycle;
596 miss_log_i = (miss_log_i + 1) & miss_log_mask;
601 void do_insn_cmp(void)
603 extern int last_count;
604 static psxRegisters rregs;
605 static u32 mem_addr, mem_val;
606 static u32 irq_test_cycle_intr;
607 static u32 handler_cycle_intr;
608 u32 *allregs_p = (void *)&psxRegs;
609 u32 *allregs_e = (void *)&rregs;
610 static u32 ppc, failcount;
611 int i, ret, bad = 0, fatal = 0, which_event = -1;
616 f = fopen("tracelog", "rb");
619 if ((ret = fread(&code, 1, 1, f)) <= 0)
628 fread(&which_event, 1, 1, f);
629 fread(&ev_cycles, 1, 4, f);
632 fread(&irq_test_cycle_intr, 1, 4, f);
635 fread(&handler_cycle_intr, 1, 4, f);
638 fread(&mem_addr, 1, 4, f);
641 fread(&mem_val, 1, 4, f);
644 assert(code < offsetof(psxRegisters, intCycle) / 4);
645 fread(&allregs_e[code], 1, 4, f);
653 psxRegs.code = rregs.code; // don't care
654 psxRegs.cycle += last_count;
655 //psxRegs.cycle = rregs.cycle; // needs reload in _cmp
656 psxRegs.CP0.r[9] = rregs.CP0.r[9]; // Count
658 //if (psxRegs.cycle == 166172) breakme();
660 if (which_event >= 0 && event_cycles[which_event] != ev_cycles) {
661 printf("bad ev_cycles #%d: %08x %08x\n", which_event, event_cycles[which_event], ev_cycles);
665 if (irq_test_cycle > irq_test_cycle_intr) {
666 printf("bad irq_test_cycle: %u %u\n", irq_test_cycle, irq_test_cycle_intr);
670 if (handler_cycle != handler_cycle_intr) {
671 printf("bad handler_cycle: %u %u\n", handler_cycle, handler_cycle_intr);
675 if (mem_val != memcheck_read(mem_addr)) {
676 printf("bad mem @%08x: %08x %08x\n", mem_addr, memcheck_read(mem_addr), mem_val);
680 if (!fatal && !memcmp(&psxRegs, &rregs, offsetof(psxRegisters, intCycle))) {
685 for (i = 0; i < offsetof(psxRegisters, intCycle) / 4; i++) {
686 if (allregs_p[i] != allregs_e[i]) {
687 miss_log_add(i, allregs_p[i], allregs_e[i], psxRegs.pc, psxRegs.cycle);
694 if (!fatal && psxRegs.pc == rregs.pc && bad < 6 && failcount < 32) {
695 static int last_mcycle;
696 if (last_mcycle != psxRegs.cycle >> 20) {
697 printf("%u\n", psxRegs.cycle);
698 last_mcycle = psxRegs.cycle >> 20;
704 for (i = 0; i < miss_log_len; i++, miss_log_i = (miss_log_i + 1) & miss_log_mask)
705 printf("bad %5s: %08x %08x, pc=%08x, cycle %u\n",
706 regnames[miss_log[miss_log_i].reg], miss_log[miss_log_i].val,
707 miss_log[miss_log_i].val_expect, miss_log[miss_log_i].pc, miss_log[miss_log_i].cycle);
708 printf("-- %d\n", bad);
709 for (i = 0; i < 8; i++)
710 printf("r%d=%08x r%2d=%08x r%2d=%08x r%2d=%08x\n", i, allregs_p[i],
711 i+8, allregs_p[i+8], i+16, allregs_p[i+16], i+24, allregs_p[i+24]);
712 printf("PC: %08x/%08x, cycle %u, next %u\n", psxRegs.pc, ppc, psxRegs.cycle, next_interupt);
713 //dump_mem("/tmp/psxram.dump", psxM, 0x200000);
714 //dump_mem("/mnt/ntz/dev/pnd/tmp/psxregs.dump", psxH, 0x10000);
717 //psxRegs.cycle = rregs.cycle + 2; // sync timing