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 (%d)\n", psxRegs.pc, psxRegs.cycle,
92 next_interupt, next_interupt - psxRegs.cycle);
96 //pending_exception = 1;
100 evprintf(" -ge %08x, %u->%u (%d)\n", psxRegs.pc, psxRegs.cycle,
101 next_interupt, next_interupt - psxRegs.cycle);
105 extern void MTC0(int reg, u32 val);
107 void pcsx_mtc0(u32 reg, u32 val)
109 evprintf("MTC0 %d #%x @%08x %u\n", reg, val, psxRegs.pc, psxRegs.cycle);
112 if (Cause & Status & 0x0300) // possible sw irq
113 pending_exception = 1;
116 void pcsx_mtc0_ds(u32 reg, u32 val)
118 evprintf("MTC0 %d #%x @%08x %u\n", reg, val, psxRegs.pc, psxRegs.cycle);
122 void new_dyna_before_save(void)
124 psxRegs.interrupt &= ~(1 << PSXINT_RCNT); // old savestate compat
126 // psxRegs.intCycle is always maintained, no need to convert
129 void new_dyna_after_save(void)
131 psxRegs.interrupt |= 1 << PSXINT_RCNT;
134 static void new_dyna_restore(void)
137 for (i = 0; i < PSXINT_COUNT; i++)
138 event_cycles[i] = psxRegs.intCycle[i].sCycle + psxRegs.intCycle[i].cycle;
140 event_cycles[PSXINT_RCNT] = psxNextsCounter + psxNextCounter;
141 psxRegs.interrupt |= 1 << PSXINT_RCNT;
142 psxRegs.interrupt &= (1 << PSXINT_COUNT) - 1;
144 new_dyna_pcsx_mem_load_state();
147 void new_dyna_freeze(void *f, int mode)
149 const char header_save[8] = "ariblks";
150 uint32_t addrs[1024 * 4];
155 if (mode != 0) { // save
156 size = new_dynarec_save_blocks(addrs, sizeof(addrs));
160 SaveFuncs.write(f, header_save, sizeof(header_save));
161 SaveFuncs.write(f, &size, sizeof(size));
162 SaveFuncs.write(f, addrs, size);
167 bytes = SaveFuncs.read(f, header, sizeof(header));
168 if (bytes != sizeof(header) || strcmp(header, header_save)) {
170 SaveFuncs.seek(f, -bytes, SEEK_CUR);
173 SaveFuncs.read(f, &size, sizeof(size));
176 if (size > sizeof(addrs)) {
177 bytes = size - sizeof(addrs);
178 SaveFuncs.seek(f, bytes, SEEK_CUR);
179 size = sizeof(addrs);
181 bytes = SaveFuncs.read(f, addrs, size);
185 if (psxCpu != &psxInt)
186 new_dynarec_load_blocks(addrs, size);
189 //printf("drc: %d block info entries %s\n", size/8, mode ? "saved" : "loaded");
195 void *gte_handlers[64];
197 void *gte_handlers_nf[64] = {
198 NULL , gteRTPS_nf , NULL , NULL , NULL , NULL , gteNCLIP_nf, NULL , // 00
199 NULL , NULL , NULL , NULL , gteOP_nf , NULL , NULL , NULL , // 08
200 gteDPCS_nf, gteINTPL_nf, gteMVMVA_nf, gteNCDS_nf, gteCDP_nf, NULL , gteNCDT_nf , NULL , // 10
201 NULL , NULL , NULL , gteNCCS_nf, gteCC_nf , NULL , gteNCS_nf , NULL , // 18
202 gteNCT_nf , NULL , NULL , NULL , NULL , NULL , NULL , NULL , // 20
203 gteSQR_nf , gteDCPL_nf , gteDPCT_nf , NULL , NULL , gteAVSZ3_nf, gteAVSZ4_nf, NULL , // 28
204 gteRTPT_nf, NULL , NULL , NULL , NULL , NULL , NULL , NULL , // 30
205 NULL , NULL , NULL , NULL , NULL , gteGPF_nf , gteGPL_nf , gteNCCT_nf, // 38
208 const char *gte_regnames[64] = {
209 NULL , "RTPS" , NULL , NULL , NULL , NULL , "NCLIP", NULL , // 00
210 NULL , NULL , NULL , NULL , "OP" , NULL , NULL , NULL , // 08
211 "DPCS", "INTPL", "MVMVA", "NCDS", "CDP", NULL , "NCDT" , NULL , // 10
212 NULL , NULL , NULL , "NCCS", "CC" , NULL , "NCS" , NULL , // 18
213 "NCT" , NULL , NULL , NULL , NULL , NULL , NULL , NULL , // 20
214 "SQR" , "DCPL" , "DPCT" , NULL , NULL , "AVSZ3", "AVSZ4", NULL , // 28
215 "RTPT", NULL , NULL , NULL , NULL , NULL , NULL , NULL , // 30
216 NULL , NULL , NULL , NULL , NULL , "GPF" , "GPL" , "NCCT", // 38
223 #define GCBITS3(b0,b1,b2) \
224 (GCBIT(b0) | GCBIT(b1) | GCBIT(b2))
225 #define GDBITS2(b0,b1) \
226 (GDBIT(b0) | GDBIT(b1))
227 #define GDBITS3(b0,b1,b2) \
228 (GDBITS2(b0,b1) | GDBIT(b2))
229 #define GDBITS4(b0,b1,b2,b3) \
230 (GDBITS3(b0,b1,b2) | GDBIT(b3))
231 #define GDBITS5(b0,b1,b2,b3,b4) \
232 (GDBITS4(b0,b1,b2,b3) | GDBIT(b4))
233 #define GDBITS6(b0,b1,b2,b3,b4,b5) \
234 (GDBITS5(b0,b1,b2,b3,b4) | GDBIT(b5))
235 #define GDBITS7(b0,b1,b2,b3,b4,b5,b6) \
236 (GDBITS6(b0,b1,b2,b3,b4,b5) | GDBIT(b6))
237 #define GDBITS8(b0,b1,b2,b3,b4,b5,b6,b7) \
238 (GDBITS7(b0,b1,b2,b3,b4,b5,b6) | GDBIT(b7))
239 #define GDBITS9(b0,b1,b2,b3,b4,b5,b6,b7,b8) \
240 (GDBITS8(b0,b1,b2,b3,b4,b5,b6,b7) | GDBIT(b8))
241 #define GDBITS10(b0,b1,b2,b3,b4,b5,b6,b7,b8,b9) \
242 (GDBITS9(b0,b1,b2,b3,b4,b5,b6,b7,b8) | GDBIT(b9))
244 const uint64_t gte_reg_reads[64] = {
245 [GTE_RTPS] = 0x1f0000ff00000000ll | GDBITS7(0,1,13,14,17,18,19),
246 [GTE_NCLIP] = GDBITS3(12,13,14),
247 [GTE_OP] = GCBITS3(0,2,4) | GDBITS3(9,10,11),
248 [GTE_DPCS] = GCBITS3(21,22,23) | GDBITS4(6,8,21,22),
249 [GTE_INTPL] = GCBITS3(21,22,23) | GDBITS7(6,8,9,10,11,21,22),
250 [GTE_MVMVA] = 0x00ffffff00000000ll | GDBITS9(0,1,2,3,4,5,9,10,11), // XXX: maybe decode further?
251 [GTE_NCDS] = 0x00ffff0000000000ll | GDBITS6(0,1,6,8,21,22),
252 [GTE_CDP] = 0x00ffe00000000000ll | GDBITS7(6,8,9,10,11,21,22),
253 [GTE_NCDT] = 0x00ffff0000000000ll | GDBITS8(0,1,2,3,4,5,6,8),
254 [GTE_NCCS] = 0x001fff0000000000ll | GDBITS5(0,1,6,21,22),
255 [GTE_CC] = 0x001fe00000000000ll | GDBITS6(6,9,10,11,21,22),
256 [GTE_NCS] = 0x001fff0000000000ll | GDBITS5(0,1,6,21,22),
257 [GTE_NCT] = 0x001fff0000000000ll | GDBITS7(0,1,2,3,4,5,6),
258 [GTE_SQR] = GDBITS3(9,10,11),
259 [GTE_DCPL] = GCBITS3(21,22,23) | GDBITS7(6,8,9,10,11,21,22),
260 [GTE_DPCT] = GCBITS3(21,22,23) | GDBITS4(8,20,21,22),
261 [GTE_AVSZ3] = GCBIT(29) | GDBITS3(17,18,19),
262 [GTE_AVSZ4] = GCBIT(30) | GDBITS4(16,17,18,19),
263 [GTE_RTPT] = 0x1f0000ff00000000ll | GDBITS7(0,1,2,3,4,5,19),
264 [GTE_GPF] = GDBITS7(6,8,9,10,11,21,22),
265 [GTE_GPL] = GDBITS10(6,8,9,10,11,21,22,25,26,27),
266 [GTE_NCCT] = 0x001fff0000000000ll | GDBITS7(0,1,2,3,4,5,6),
269 // note: this excludes gteFLAG that is always written to
270 const uint64_t gte_reg_writes[64] = {
271 [GTE_RTPS] = 0x0f0f7f00ll,
272 [GTE_NCLIP] = GDBIT(24),
273 [GTE_OP] = GDBITS6(9,10,11,25,26,27),
274 [GTE_DPCS] = GDBITS9(9,10,11,20,21,22,25,26,27),
275 [GTE_INTPL] = GDBITS9(9,10,11,20,21,22,25,26,27),
276 [GTE_MVMVA] = GDBITS6(9,10,11,25,26,27),
277 [GTE_NCDS] = GDBITS9(9,10,11,20,21,22,25,26,27),
278 [GTE_CDP] = GDBITS9(9,10,11,20,21,22,25,26,27),
279 [GTE_NCDT] = GDBITS9(9,10,11,20,21,22,25,26,27),
280 [GTE_NCCS] = GDBITS9(9,10,11,20,21,22,25,26,27),
281 [GTE_CC] = GDBITS9(9,10,11,20,21,22,25,26,27),
282 [GTE_NCS] = GDBITS9(9,10,11,20,21,22,25,26,27),
283 [GTE_NCT] = GDBITS9(9,10,11,20,21,22,25,26,27),
284 [GTE_SQR] = GDBITS6(9,10,11,25,26,27),
285 [GTE_DCPL] = GDBITS9(9,10,11,20,21,22,25,26,27),
286 [GTE_DPCT] = GDBITS9(9,10,11,20,21,22,25,26,27),
287 [GTE_AVSZ3] = GDBITS2(7,24),
288 [GTE_AVSZ4] = GDBITS2(7,24),
289 [GTE_RTPT] = 0x0f0f7f00ll,
290 [GTE_GPF] = GDBITS9(9,10,11,20,21,22,25,26,27),
291 [GTE_GPL] = GDBITS9(9,10,11,20,21,22,25,26,27),
292 [GTE_NCCT] = GDBITS9(9,10,11,20,21,22,25,26,27),
295 static int ari64_init()
297 static u32 scratch_buf[8*8*2] __attribute__((aligned(64)));
298 extern void (*psxCP2[64])();
299 extern void psxNULL();
303 new_dyna_pcsx_mem_init();
305 for (i = 0; i < ARRAY_SIZE(gte_handlers); i++)
306 if (psxCP2[i] != psxNULL)
307 gte_handlers[i] = psxCP2[i];
309 #if defined(__arm__) && !defined(DRC_DBG)
310 gte_handlers[0x06] = gteNCLIP_arm;
312 gte_handlers_nf[0x01] = gteRTPS_nf_arm;
313 gte_handlers_nf[0x30] = gteRTPT_nf_arm;
316 // compiler's _nf version is still a lot slower than neon
317 // _nf_arm RTPS is roughly the same, RTPT slower
318 gte_handlers[0x01] = gte_handlers_nf[0x01] = gteRTPS_neon;
319 gte_handlers[0x30] = gte_handlers_nf[0x30] = gteRTPT_neon;
323 memcpy(gte_handlers_nf, gte_handlers, sizeof(gte_handlers_nf));
326 zeromem_ptr = zero_mem;
327 scratch_buf_ptr = scratch_buf;
332 static void ari64_reset()
334 printf("ari64_reset\n");
335 new_dyna_pcsx_mem_reset();
336 new_dynarec_invalidate_all_pages();
338 pending_exception = 1;
341 // execute until predefined leave points
342 // (HLE softcall exit and BIOS fastboot end)
343 static void ari64_execute_until()
345 schedule_timeslice();
347 evprintf("ari64_execute %08x, %u->%u (%d)\n", psxRegs.pc,
348 psxRegs.cycle, next_interupt, next_interupt - psxRegs.cycle);
350 new_dyna_start(dynarec_local);
352 evprintf("ari64_execute end %08x, %u->%u (%d)\n", psxRegs.pc,
353 psxRegs.cycle, next_interupt, next_interupt - psxRegs.cycle);
356 static void ari64_execute()
359 ari64_execute_until();
360 evprintf("drc left @%08x\n", psxRegs.pc);
364 static void ari64_clear(u32 addr, u32 size)
366 size *= 4; /* PCSX uses DMA units (words) */
368 evprintf("ari64_clear %08x %04x\n", addr, size);
370 new_dynarec_invalidate_range(addr, addr + size);
373 static void ari64_notify(int note, void *data) {
375 Should be fixed when ARM dynarec has proper icache emulation.
378 case R3000ACPU_NOTIFY_CACHE_UNISOLATED:
380 case R3000ACPU_NOTIFY_CACHE_ISOLATED:
382 case R3000ACPU_NOTIFY_DMA3_EXE_LOAD:
389 static void ari64_apply_config()
393 if (Config.DisableStalls)
394 new_dynarec_hacks |= NDHACK_NO_STALLS;
396 new_dynarec_hacks &= ~NDHACK_NO_STALLS;
398 if (cycle_multiplier != cycle_multiplier_old
399 || new_dynarec_hacks != new_dynarec_hacks_old)
401 new_dynarec_clear_full();
405 static void ari64_shutdown()
407 new_dynarec_cleanup();
408 new_dyna_pcsx_mem_shutdown();
422 #else // if DRC_DISABLE
424 unsigned int address;
425 int pending_exception, stop;
426 unsigned int next_interupt;
427 int new_dynarec_did_compile;
428 int cycle_multiplier;
429 int cycle_multiplier_override;
430 int cycle_multiplier_old;
431 int new_dynarec_hacks_pergame;
432 int new_dynarec_hacks_old;
433 int new_dynarec_hacks;
438 void *scratch_buf_ptr;
439 void new_dynarec_init() {}
440 void new_dyna_start(void *context) {}
441 void new_dynarec_cleanup() {}
442 void new_dynarec_clear_full() {}
443 void new_dynarec_invalidate_all_pages() {}
444 void new_dynarec_invalidate_range(unsigned int start, unsigned int end) {}
445 void new_dyna_pcsx_mem_init(void) {}
446 void new_dyna_pcsx_mem_reset(void) {}
447 void new_dyna_pcsx_mem_load_state(void) {}
448 void new_dyna_pcsx_mem_shutdown(void) {}
449 int new_dynarec_save_blocks(void *save, int size) { return 0; }
450 void new_dynarec_load_blocks(const void *save, int size) {}
461 void dump_mem(const char *fname, void *mem, size_t size)
463 FILE *f1 = fopen(fname, "wb");
465 f1 = fopen(strrchr(fname, '/') + 1, "wb");
466 fwrite(mem, 1, size, f1);
470 static u32 memcheck_read(u32 a)
472 if ((a >> 16) == 0x1f80)
474 return *(u32 *)(psxH + (a & 0xfffc));
476 if ((a >> 16) == 0x1f00)
478 return *(u32 *)(psxP + (a & 0xfffc));
480 // if ((a & ~0xe0600000) < 0x200000)
482 return *(u32 *)(psxM + (a & 0x1ffffc));
486 void do_insn_trace(void)
488 static psxRegisters oldregs;
489 static u32 event_cycles_o[PSXINT_COUNT];
490 u32 *allregs_p = (void *)&psxRegs;
491 u32 *allregs_o = (void *)&oldregs;
496 //last_io_addr = 0x5e2c8;
498 f = fopen("tracelog", "wb");
501 oldregs.code = psxRegs.code; // don't care
502 for (i = 0; i < offsetof(psxRegisters, intCycle) / 4; i++) {
503 if (allregs_p[i] != allregs_o[i]) {
505 fwrite(&allregs_p[i], 1, 4, f);
506 allregs_o[i] = allregs_p[i];
510 for (i = 0; i < PSXINT_COUNT; i++) {
511 if (event_cycles[i] != event_cycles_o[i]) {
513 fwrite(&byte, 1, 1, f);
515 fwrite(&event_cycles[i], 1, 4, f);
516 event_cycles_o[i] = event_cycles[i];
519 #define SAVE_IF_CHANGED(code_, name_) { \
520 static u32 old_##name_ = 0xbad0c0de; \
521 if (old_##name_ != name_) { \
523 fwrite(&byte, 1, 1, f); \
524 fwrite(&name_, 1, 4, f); \
525 old_##name_ = name_; \
528 SAVE_IF_CHANGED(0xfb, irq_test_cycle);
529 SAVE_IF_CHANGED(0xfc, handler_cycle);
530 SAVE_IF_CHANGED(0xfd, last_io_addr);
531 io_data = memcheck_read(last_io_addr);
532 SAVE_IF_CHANGED(0xfe, io_data);
534 fwrite(&byte, 1, 1, f);
537 if (psxRegs.cycle == 190230) {
538 dump_mem("/mnt/ntz/dev/pnd/tmp/psxram_i.dump", psxM, 0x200000);
539 dump_mem("/mnt/ntz/dev/pnd/tmp/psxregs_i.dump", psxH, 0x10000);
547 static const char *regnames[offsetof(psxRegisters, intCycle) / 4] = {
548 "r0", "r1", "r2", "r3", "r4", "r5", "r6", "r7",
549 "r8", "r9", "r10", "r11", "r12", "r13", "r14", "r15",
550 "r16", "r17", "r18", "r19", "r20", "r21", "r22", "r23",
551 "r24", "r25", "r26", "r27", "r28", "r29", "r30", "r31",
553 "C0_0", "C0_1", "C0_2", "C0_3", "C0_4", "C0_5", "C0_6", "C0_7",
554 "C0_8", "C0_9", "C0_10", "C0_11", "C0_12", "C0_13", "C0_14", "C0_15",
555 "C0_16", "C0_17", "C0_18", "C0_19", "C0_20", "C0_21", "C0_22", "C0_23",
556 "C0_24", "C0_25", "C0_26", "C0_27", "C0_28", "C0_29", "C0_30", "C0_31",
558 "C2D0", "C2D1", "C2D2", "C2D3", "C2D4", "C2D5", "C2D6", "C2D7",
559 "C2D8", "C2D9", "C2D10", "C2D11", "C2D12", "C2D13", "C2D14", "C2D15",
560 "C2D16", "C2D17", "C2D18", "C2D19", "C2D20", "C2D21", "C2D22", "C2D23",
561 "C2D24", "C2D25", "C2D26", "C2D27", "C2D28", "C2D29", "C2D30", "C2D31",
563 "C2C0", "C2C1", "C2C2", "C2C3", "C2C4", "C2C5", "C2C6", "C2C7",
564 "C2C8", "C2C9", "C2C10", "C2C11", "C2C12", "C2C13", "C2C14", "C2C15",
565 "C2C16", "C2C17", "C2C18", "C2C19", "C2C20", "C2C21", "C2C22", "C2C23",
566 "C2C24", "C2C25", "C2C26", "C2C27", "C2C28", "C2C29", "C2C30", "C2C31",
568 "PC", "code", "cycle", "interrupt",
576 static int miss_log_i;
577 #define miss_log_len (sizeof(miss_log)/sizeof(miss_log[0]))
578 #define miss_log_mask (miss_log_len-1)
580 static void miss_log_add(int reg, u32 val, u32 val_expect, u32 pc, u32 cycle)
582 miss_log[miss_log_i].reg = reg;
583 miss_log[miss_log_i].val = val;
584 miss_log[miss_log_i].val_expect = val_expect;
585 miss_log[miss_log_i].pc = pc;
586 miss_log[miss_log_i].cycle = cycle;
587 miss_log_i = (miss_log_i + 1) & miss_log_mask;
592 void do_insn_cmp(void)
594 extern int last_count;
595 static psxRegisters rregs;
596 static u32 mem_addr, mem_val;
597 static u32 irq_test_cycle_intr;
598 static u32 handler_cycle_intr;
599 u32 *allregs_p = (void *)&psxRegs;
600 u32 *allregs_e = (void *)&rregs;
601 static u32 ppc, failcount;
602 int i, ret, bad = 0, fatal = 0, which_event = -1;
607 f = fopen("tracelog", "rb");
610 if ((ret = fread(&code, 1, 1, f)) <= 0)
619 fread(&which_event, 1, 1, f);
620 fread(&ev_cycles, 1, 4, f);
623 fread(&irq_test_cycle_intr, 1, 4, f);
626 fread(&handler_cycle_intr, 1, 4, f);
629 fread(&mem_addr, 1, 4, f);
632 fread(&mem_val, 1, 4, f);
635 assert(code < offsetof(psxRegisters, intCycle) / 4);
636 fread(&allregs_e[code], 1, 4, f);
644 psxRegs.code = rregs.code; // don't care
645 psxRegs.cycle += last_count;
646 //psxRegs.cycle = rregs.cycle; // needs reload in _cmp
647 psxRegs.CP0.r[9] = rregs.CP0.r[9]; // Count
649 //if (psxRegs.cycle == 166172) breakme();
651 if (which_event >= 0 && event_cycles[which_event] != ev_cycles) {
652 printf("bad ev_cycles #%d: %u %u / %u\n", which_event,
653 event_cycles[which_event], ev_cycles, psxRegs.cycle);
657 if (irq_test_cycle > irq_test_cycle_intr) {
658 printf("bad irq_test_cycle: %u %u\n", irq_test_cycle, irq_test_cycle_intr);
662 if (handler_cycle != handler_cycle_intr) {
663 printf("bad handler_cycle: %u %u\n", handler_cycle, handler_cycle_intr);
667 if (mem_val != memcheck_read(mem_addr)) {
668 printf("bad mem @%08x: %08x %08x\n", mem_addr, memcheck_read(mem_addr), mem_val);
672 if (!fatal && !memcmp(&psxRegs, &rregs, offsetof(psxRegisters, intCycle))) {
677 for (i = 0; i < offsetof(psxRegisters, intCycle) / 4; i++) {
678 if (allregs_p[i] != allregs_e[i]) {
679 miss_log_add(i, allregs_p[i], allregs_e[i], psxRegs.pc, psxRegs.cycle);
686 if (!fatal && psxRegs.pc == rregs.pc && bad < 6 && failcount < 32) {
687 static int last_mcycle;
688 if (last_mcycle != psxRegs.cycle >> 20) {
689 printf("%u\n", psxRegs.cycle);
690 last_mcycle = psxRegs.cycle >> 20;
696 for (i = 0; i < miss_log_len; i++, miss_log_i = (miss_log_i + 1) & miss_log_mask)
697 printf("bad %5s: %08x %08x, pc=%08x, cycle %u\n",
698 regnames[miss_log[miss_log_i].reg], miss_log[miss_log_i].val,
699 miss_log[miss_log_i].val_expect, miss_log[miss_log_i].pc, miss_log[miss_log_i].cycle);
700 printf("-- %d\n", bad);
701 for (i = 0; i < 8; i++)
702 printf("r%d=%08x r%2d=%08x r%2d=%08x r%2d=%08x\n", i, allregs_p[i],
703 i+8, allregs_p[i+8], i+16, allregs_p[i+16], i+24, allregs_p[i+24]);
704 printf("PC: %08x/%08x, cycle %u, next %u\n", psxRegs.pc, ppc, psxRegs.cycle, next_interupt);
705 //dump_mem("/tmp/psxram.dump", psxM, 0x200000);
706 //dump_mem("/mnt/ntz/dev/pnd/tmp/psxregs.dump", psxH, 0x10000);
709 //psxRegs.cycle = rregs.cycle + 2; // sync timing