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 void new_dyna_before_save(void)
125 psxRegs.interrupt &= ~(1 << PSXINT_RCNT); // old savestate compat
127 // psxRegs.intCycle is always maintained, no need to convert
130 void new_dyna_after_save(void)
132 psxRegs.interrupt |= 1 << PSXINT_RCNT;
135 static void new_dyna_restore(void)
138 for (i = 0; i < PSXINT_COUNT; i++)
139 event_cycles[i] = psxRegs.intCycle[i].sCycle + psxRegs.intCycle[i].cycle;
141 event_cycles[PSXINT_RCNT] = psxNextsCounter + psxNextCounter;
142 psxRegs.interrupt |= 1 << PSXINT_RCNT;
143 psxRegs.interrupt &= (1 << PSXINT_COUNT) - 1;
145 new_dyna_pcsx_mem_load_state();
148 void new_dyna_freeze(void *f, int mode)
150 const char header_save[8] = "ariblks";
151 uint32_t addrs[1024 * 4];
156 if (mode != 0) { // save
157 size = new_dynarec_save_blocks(addrs, sizeof(addrs));
161 SaveFuncs.write(f, header_save, sizeof(header_save));
162 SaveFuncs.write(f, &size, sizeof(size));
163 SaveFuncs.write(f, addrs, size);
168 bytes = SaveFuncs.read(f, header, sizeof(header));
169 if (bytes != sizeof(header) || strcmp(header, header_save)) {
171 SaveFuncs.seek(f, -bytes, SEEK_CUR);
174 SaveFuncs.read(f, &size, sizeof(size));
177 if (size > sizeof(addrs)) {
178 bytes = size - sizeof(addrs);
179 SaveFuncs.seek(f, bytes, SEEK_CUR);
180 size = sizeof(addrs);
182 bytes = SaveFuncs.read(f, addrs, size);
186 if (psxCpu != &psxInt)
187 new_dynarec_load_blocks(addrs, size);
190 //printf("drc: %d block info entries %s\n", size/8, mode ? "saved" : "loaded");
193 #if !defined(DRC_DISABLE) && !defined(LIGHTREC)
196 void *gte_handlers[64];
198 void *gte_handlers_nf[64] = {
199 NULL , gteRTPS_nf , NULL , NULL , NULL , NULL , gteNCLIP_nf, NULL , // 00
200 NULL , NULL , NULL , NULL , gteOP_nf , NULL , NULL , NULL , // 08
201 gteDPCS_nf, gteINTPL_nf, gteMVMVA_nf, gteNCDS_nf, gteCDP_nf, NULL , gteNCDT_nf , NULL , // 10
202 NULL , NULL , NULL , gteNCCS_nf, gteCC_nf , NULL , gteNCS_nf , NULL , // 18
203 gteNCT_nf , NULL , NULL , NULL , NULL , NULL , NULL , NULL , // 20
204 gteSQR_nf , gteDCPL_nf , gteDPCT_nf , NULL , NULL , gteAVSZ3_nf, gteAVSZ4_nf, NULL , // 28
205 gteRTPT_nf, NULL , NULL , NULL , NULL , NULL , NULL , NULL , // 30
206 NULL , NULL , NULL , NULL , NULL , gteGPF_nf , gteGPL_nf , gteNCCT_nf, // 38
209 const char *gte_regnames[64] = {
210 NULL , "RTPS" , NULL , NULL , NULL , NULL , "NCLIP", NULL , // 00
211 NULL , NULL , NULL , NULL , "OP" , NULL , NULL , NULL , // 08
212 "DPCS", "INTPL", "MVMVA", "NCDS", "CDP", NULL , "NCDT" , NULL , // 10
213 NULL , NULL , NULL , "NCCS", "CC" , NULL , "NCS" , NULL , // 18
214 "NCT" , NULL , NULL , NULL , NULL , NULL , NULL , NULL , // 20
215 "SQR" , "DCPL" , "DPCT" , NULL , NULL , "AVSZ3", "AVSZ4", NULL , // 28
216 "RTPT", NULL , NULL , NULL , NULL , NULL , NULL , NULL , // 30
217 NULL , NULL , NULL , NULL , NULL , "GPF" , "GPL" , "NCCT", // 38
224 #define GCBITS3(b0,b1,b2) \
225 (GCBIT(b0) | GCBIT(b1) | GCBIT(b2))
226 #define GDBITS2(b0,b1) \
227 (GDBIT(b0) | GDBIT(b1))
228 #define GDBITS3(b0,b1,b2) \
229 (GDBITS2(b0,b1) | GDBIT(b2))
230 #define GDBITS4(b0,b1,b2,b3) \
231 (GDBITS3(b0,b1,b2) | GDBIT(b3))
232 #define GDBITS5(b0,b1,b2,b3,b4) \
233 (GDBITS4(b0,b1,b2,b3) | GDBIT(b4))
234 #define GDBITS6(b0,b1,b2,b3,b4,b5) \
235 (GDBITS5(b0,b1,b2,b3,b4) | GDBIT(b5))
236 #define GDBITS7(b0,b1,b2,b3,b4,b5,b6) \
237 (GDBITS6(b0,b1,b2,b3,b4,b5) | GDBIT(b6))
238 #define GDBITS8(b0,b1,b2,b3,b4,b5,b6,b7) \
239 (GDBITS7(b0,b1,b2,b3,b4,b5,b6) | GDBIT(b7))
240 #define GDBITS9(b0,b1,b2,b3,b4,b5,b6,b7,b8) \
241 (GDBITS8(b0,b1,b2,b3,b4,b5,b6,b7) | GDBIT(b8))
242 #define GDBITS10(b0,b1,b2,b3,b4,b5,b6,b7,b8,b9) \
243 (GDBITS9(b0,b1,b2,b3,b4,b5,b6,b7,b8) | GDBIT(b9))
245 const uint64_t gte_reg_reads[64] = {
246 [GTE_RTPS] = 0x1f0000ff00000000ll | GDBITS7(0,1,13,14,17,18,19),
247 [GTE_NCLIP] = GDBITS3(12,13,14),
248 [GTE_OP] = GCBITS3(0,2,4) | GDBITS3(9,10,11),
249 [GTE_DPCS] = GCBITS3(21,22,23) | GDBITS4(6,8,21,22),
250 [GTE_INTPL] = GCBITS3(21,22,23) | GDBITS7(6,8,9,10,11,21,22),
251 [GTE_MVMVA] = 0x00ffffff00000000ll | GDBITS9(0,1,2,3,4,5,9,10,11), // XXX: maybe decode further?
252 [GTE_NCDS] = 0x00ffff0000000000ll | GDBITS6(0,1,6,8,21,22),
253 [GTE_CDP] = 0x00ffe00000000000ll | GDBITS7(6,8,9,10,11,21,22),
254 [GTE_NCDT] = 0x00ffff0000000000ll | GDBITS8(0,1,2,3,4,5,6,8),
255 [GTE_NCCS] = 0x001fff0000000000ll | GDBITS5(0,1,6,21,22),
256 [GTE_CC] = 0x001fe00000000000ll | GDBITS6(6,9,10,11,21,22),
257 [GTE_NCS] = 0x001fff0000000000ll | GDBITS5(0,1,6,21,22),
258 [GTE_NCT] = 0x001fff0000000000ll | GDBITS7(0,1,2,3,4,5,6),
259 [GTE_SQR] = GDBITS3(9,10,11),
260 [GTE_DCPL] = GCBITS3(21,22,23) | GDBITS7(6,8,9,10,11,21,22),
261 [GTE_DPCT] = GCBITS3(21,22,23) | GDBITS4(8,20,21,22),
262 [GTE_AVSZ3] = GCBIT(29) | GDBITS3(17,18,19),
263 [GTE_AVSZ4] = GCBIT(30) | GDBITS4(16,17,18,19),
264 [GTE_RTPT] = 0x1f0000ff00000000ll | GDBITS7(0,1,2,3,4,5,19),
265 [GTE_GPF] = GDBITS7(6,8,9,10,11,21,22),
266 [GTE_GPL] = GDBITS10(6,8,9,10,11,21,22,25,26,27),
267 [GTE_NCCT] = 0x001fff0000000000ll | GDBITS7(0,1,2,3,4,5,6),
270 // note: this excludes gteFLAG that is always written to
271 const uint64_t gte_reg_writes[64] = {
272 [GTE_RTPS] = 0x0f0f7f00ll,
273 [GTE_NCLIP] = GDBIT(24),
274 [GTE_OP] = GDBITS6(9,10,11,25,26,27),
275 [GTE_DPCS] = GDBITS9(9,10,11,20,21,22,25,26,27),
276 [GTE_INTPL] = GDBITS9(9,10,11,20,21,22,25,26,27),
277 [GTE_MVMVA] = GDBITS6(9,10,11,25,26,27),
278 [GTE_NCDS] = GDBITS9(9,10,11,20,21,22,25,26,27),
279 [GTE_CDP] = GDBITS9(9,10,11,20,21,22,25,26,27),
280 [GTE_NCDT] = GDBITS9(9,10,11,20,21,22,25,26,27),
281 [GTE_NCCS] = GDBITS9(9,10,11,20,21,22,25,26,27),
282 [GTE_CC] = GDBITS9(9,10,11,20,21,22,25,26,27),
283 [GTE_NCS] = GDBITS9(9,10,11,20,21,22,25,26,27),
284 [GTE_NCT] = GDBITS9(9,10,11,20,21,22,25,26,27),
285 [GTE_SQR] = GDBITS6(9,10,11,25,26,27),
286 [GTE_DCPL] = GDBITS9(9,10,11,20,21,22,25,26,27),
287 [GTE_DPCT] = GDBITS9(9,10,11,20,21,22,25,26,27),
288 [GTE_AVSZ3] = GDBITS2(7,24),
289 [GTE_AVSZ4] = GDBITS2(7,24),
290 [GTE_RTPT] = 0x0f0f7f00ll,
291 [GTE_GPF] = GDBITS9(9,10,11,20,21,22,25,26,27),
292 [GTE_GPL] = GDBITS9(9,10,11,20,21,22,25,26,27),
293 [GTE_NCCT] = GDBITS9(9,10,11,20,21,22,25,26,27),
296 static int ari64_init()
298 static u32 scratch_buf[8*8*2] __attribute__((aligned(64)));
302 new_dyna_pcsx_mem_init();
304 for (i = 0; i < ARRAY_SIZE(gte_handlers); i++)
305 if (psxCP2[i] != gteNULL)
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 new_dynarec_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 size *= 4; /* PCSX uses DMA units (words) */
367 evprintf("ari64_clear %08x %04x\n", addr, size);
369 new_dynarec_invalidate_range(addr, addr + size);
372 static void ari64_notify(int note, void *data) {
375 case R3000ACPU_NOTIFY_CACHE_UNISOLATED:
376 case R3000ACPU_NOTIFY_CACHE_ISOLATED:
377 new_dyna_pcsx_mem_isolate(note == R3000ACPU_NOTIFY_CACHE_ISOLATED);
384 static void ari64_apply_config()
388 if (Config.DisableStalls)
389 new_dynarec_hacks |= NDHACK_NO_STALLS;
391 new_dynarec_hacks &= ~NDHACK_NO_STALLS;
393 if (Config.cycle_multiplier != cycle_multiplier_old
394 || new_dynarec_hacks != new_dynarec_hacks_old)
396 new_dynarec_clear_full();
400 static void ari64_shutdown()
402 new_dynarec_cleanup();
403 new_dyna_pcsx_mem_shutdown();
417 #else // if DRC_DISABLE
419 unsigned int address;
420 int pending_exception, stop;
421 unsigned int next_interupt;
422 int new_dynarec_did_compile;
423 int cycle_multiplier_old;
424 int new_dynarec_hacks_pergame;
425 int new_dynarec_hacks_old;
426 int new_dynarec_hacks;
429 u32 zero_mem[0x1000/4];
431 void *scratch_buf_ptr;
432 void new_dynarec_init() {}
433 void new_dyna_start(void *context) {}
434 void new_dynarec_cleanup() {}
435 void new_dynarec_clear_full() {}
436 void new_dynarec_invalidate_all_pages() {}
437 void new_dynarec_invalidate_range(unsigned int start, unsigned int end) {}
438 void new_dyna_pcsx_mem_init(void) {}
439 void new_dyna_pcsx_mem_reset(void) {}
440 void new_dyna_pcsx_mem_load_state(void) {}
441 void new_dyna_pcsx_mem_isolate(int enable) {}
442 void new_dyna_pcsx_mem_shutdown(void) {}
443 int new_dynarec_save_blocks(void *save, int size) { return 0; }
444 void new_dynarec_load_blocks(const void *save, int size) {}
455 void dump_mem(const char *fname, void *mem, size_t size)
457 FILE *f1 = fopen(fname, "wb");
459 f1 = fopen(strrchr(fname, '/') + 1, "wb");
460 fwrite(mem, 1, size, f1);
464 static u32 memcheck_read(u32 a)
466 if ((a >> 16) == 0x1f80)
468 return *(u32 *)(psxH + (a & 0xfffc));
470 if ((a >> 16) == 0x1f00)
472 return *(u32 *)(psxP + (a & 0xfffc));
474 // if ((a & ~0xe0600000) < 0x200000)
476 return *(u32 *)(psxM + (a & 0x1ffffc));
480 void do_insn_trace(void)
482 static psxRegisters oldregs;
483 static u32 event_cycles_o[PSXINT_COUNT];
484 u32 *allregs_p = (void *)&psxRegs;
485 u32 *allregs_o = (void *)&oldregs;
490 //last_io_addr = 0x5e2c8;
492 f = fopen("tracelog", "wb");
495 oldregs.code = psxRegs.code; // don't care
496 for (i = 0; i < offsetof(psxRegisters, intCycle) / 4; i++) {
497 if (allregs_p[i] != allregs_o[i]) {
499 fwrite(&allregs_p[i], 1, 4, f);
500 allregs_o[i] = allregs_p[i];
504 for (i = 0; i < PSXINT_COUNT; i++) {
505 if (event_cycles[i] != event_cycles_o[i]) {
507 fwrite(&byte, 1, 1, f);
509 fwrite(&event_cycles[i], 1, 4, f);
510 event_cycles_o[i] = event_cycles[i];
513 #define SAVE_IF_CHANGED(code_, name_) { \
514 static u32 old_##name_ = 0xbad0c0de; \
515 if (old_##name_ != name_) { \
517 fwrite(&byte, 1, 1, f); \
518 fwrite(&name_, 1, 4, f); \
519 old_##name_ = name_; \
522 SAVE_IF_CHANGED(0xfb, irq_test_cycle);
523 SAVE_IF_CHANGED(0xfc, handler_cycle);
524 SAVE_IF_CHANGED(0xfd, last_io_addr);
525 io_data = memcheck_read(last_io_addr);
526 SAVE_IF_CHANGED(0xfe, io_data);
528 fwrite(&byte, 1, 1, f);
531 if (psxRegs.cycle == 190230) {
532 dump_mem("/mnt/ntz/dev/pnd/tmp/psxram_i.dump", psxM, 0x200000);
533 dump_mem("/mnt/ntz/dev/pnd/tmp/psxregs_i.dump", psxH, 0x10000);
541 static const char *regnames[offsetof(psxRegisters, intCycle) / 4] = {
542 "r0", "r1", "r2", "r3", "r4", "r5", "r6", "r7",
543 "r8", "r9", "r10", "r11", "r12", "r13", "r14", "r15",
544 "r16", "r17", "r18", "r19", "r20", "r21", "r22", "r23",
545 "r24", "r25", "r26", "r27", "r28", "r29", "r30", "r31",
547 "C0_0", "C0_1", "C0_2", "C0_3", "C0_4", "C0_5", "C0_6", "C0_7",
548 "C0_8", "C0_9", "C0_10", "C0_11", "C0_12", "C0_13", "C0_14", "C0_15",
549 "C0_16", "C0_17", "C0_18", "C0_19", "C0_20", "C0_21", "C0_22", "C0_23",
550 "C0_24", "C0_25", "C0_26", "C0_27", "C0_28", "C0_29", "C0_30", "C0_31",
552 "C2D0", "C2D1", "C2D2", "C2D3", "C2D4", "C2D5", "C2D6", "C2D7",
553 "C2D8", "C2D9", "C2D10", "C2D11", "C2D12", "C2D13", "C2D14", "C2D15",
554 "C2D16", "C2D17", "C2D18", "C2D19", "C2D20", "C2D21", "C2D22", "C2D23",
555 "C2D24", "C2D25", "C2D26", "C2D27", "C2D28", "C2D29", "C2D30", "C2D31",
557 "C2C0", "C2C1", "C2C2", "C2C3", "C2C4", "C2C5", "C2C6", "C2C7",
558 "C2C8", "C2C9", "C2C10", "C2C11", "C2C12", "C2C13", "C2C14", "C2C15",
559 "C2C16", "C2C17", "C2C18", "C2C19", "C2C20", "C2C21", "C2C22", "C2C23",
560 "C2C24", "C2C25", "C2C26", "C2C27", "C2C28", "C2C29", "C2C30", "C2C31",
562 "PC", "code", "cycle", "interrupt",
570 static int miss_log_i;
571 #define miss_log_len (sizeof(miss_log)/sizeof(miss_log[0]))
572 #define miss_log_mask (miss_log_len-1)
574 static void miss_log_add(int reg, u32 val, u32 val_expect, u32 pc, u32 cycle)
576 miss_log[miss_log_i].reg = reg;
577 miss_log[miss_log_i].val = val;
578 miss_log[miss_log_i].val_expect = val_expect;
579 miss_log[miss_log_i].pc = pc;
580 miss_log[miss_log_i].cycle = cycle;
581 miss_log_i = (miss_log_i + 1) & miss_log_mask;
586 void do_insn_cmp(void)
588 extern int last_count;
589 static psxRegisters rregs;
590 static u32 mem_addr, mem_val;
591 static u32 irq_test_cycle_intr;
592 static u32 handler_cycle_intr;
593 u32 *allregs_p = (void *)&psxRegs;
594 u32 *allregs_e = (void *)&rregs;
595 static u32 ppc, failcount;
596 int i, ret, bad = 0, fatal = 0, which_event = -1;
601 f = fopen("tracelog", "rb");
604 if ((ret = fread(&code, 1, 1, f)) <= 0)
613 fread(&which_event, 1, 1, f);
614 fread(&ev_cycles, 1, 4, f);
617 fread(&irq_test_cycle_intr, 1, 4, f);
620 fread(&handler_cycle_intr, 1, 4, f);
623 fread(&mem_addr, 1, 4, f);
626 fread(&mem_val, 1, 4, f);
629 assert(code < offsetof(psxRegisters, intCycle) / 4);
630 fread(&allregs_e[code], 1, 4, f);
638 psxRegs.code = rregs.code; // don't care
639 psxRegs.cycle += last_count;
640 //psxRegs.cycle = rregs.cycle; // needs reload in _cmp
641 psxRegs.CP0.r[9] = rregs.CP0.r[9]; // Count
643 //if (psxRegs.cycle == 166172) breakme();
645 if (which_event >= 0 && event_cycles[which_event] != ev_cycles) {
646 printf("bad ev_cycles #%d: %u %u / %u\n", which_event,
647 event_cycles[which_event], ev_cycles, psxRegs.cycle);
651 if (irq_test_cycle > irq_test_cycle_intr) {
652 printf("bad irq_test_cycle: %u %u\n", irq_test_cycle, irq_test_cycle_intr);
656 if (handler_cycle != handler_cycle_intr) {
657 printf("bad handler_cycle: %u %u\n", handler_cycle, handler_cycle_intr);
661 if (mem_val != memcheck_read(mem_addr)) {
662 printf("bad mem @%08x: %08x %08x\n", mem_addr, memcheck_read(mem_addr), mem_val);
666 if (!fatal && !memcmp(&psxRegs, &rregs, offsetof(psxRegisters, intCycle))) {
671 for (i = 0; i < offsetof(psxRegisters, intCycle) / 4; i++) {
672 if (allregs_p[i] != allregs_e[i]) {
673 miss_log_add(i, allregs_p[i], allregs_e[i], psxRegs.pc, psxRegs.cycle);
680 if (!fatal && psxRegs.pc == rregs.pc && bad < 6 && failcount < 32) {
681 static int last_mcycle;
682 if (last_mcycle != psxRegs.cycle >> 20) {
683 printf("%u\n", psxRegs.cycle);
684 last_mcycle = psxRegs.cycle >> 20;
690 for (i = 0; i < miss_log_len; i++, miss_log_i = (miss_log_i + 1) & miss_log_mask)
691 printf("bad %5s: %08x %08x, pc=%08x, cycle %u\n",
692 regnames[miss_log[miss_log_i].reg], miss_log[miss_log_i].val,
693 miss_log[miss_log_i].val_expect, miss_log[miss_log_i].pc, miss_log[miss_log_i].cycle);
694 printf("-- %d\n", bad);
695 for (i = 0; i < 8; i++)
696 printf("r%d=%08x r%2d=%08x r%2d=%08x r%2d=%08x\n", i, allregs_p[i],
697 i+8, allregs_p[i+8], i+16, allregs_p[i+16], i+24, allregs_p[i+24]);
698 printf("PC: %08x/%08x, cycle %u, next %u\n", psxRegs.pc, ppc, psxRegs.cycle, next_interupt);
699 //dump_mem("/tmp/psxram.dump", psxM, 0x200000);
700 //dump_mem("/mnt/ntz/dev/pnd/tmp/psxregs.dump", psxH, 0x10000);
703 //psxRegs.cycle = rregs.cycle + 2; // sync timing