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 "../../../r3000a.h"
14 #include "../../../cdrom.h"
15 #include "../../../psxdma.h"
16 #include "../../../mdec.h"
17 #include "../../../gte_arm.h"
18 #include "../../../gte_neon.h"
20 #include "../../../gte.h"
23 #include "../../../gte.h"
26 #define ARRAY_SIZE(x) (sizeof(x) / sizeof(x[0]))
28 //#define evprintf printf
31 char invalid_code[0x100000];
32 static u32 scratch_buf[8*8*2] __attribute__((aligned(64)));
33 u32 event_cycles[PSXINT_COUNT];
35 static void schedule_timeslice(void)
37 u32 i, c = psxRegs.cycle;
38 u32 irqs = psxRegs.interrupt;
42 for (i = 0; irqs != 0; i++, irqs >>= 1) {
45 dif = event_cycles[i] - c;
46 //evprintf(" ev %d\n", dif);
47 if (0 < dif && dif < min)
50 next_interupt = c + min;
53 typedef void (irq_func)();
55 static irq_func * const irq_funcs[] = {
56 [PSXINT_SIO] = sioInterrupt,
57 [PSXINT_CDR] = cdrInterrupt,
58 [PSXINT_CDREAD] = cdrReadInterrupt,
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] = cdrPlayInterrupt,
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 irqs = psxRegs.interrupt;
75 u32 cycle = psxRegs.cycle;
78 // irq_funcs() may queue more irqs
79 psxRegs.interrupt = 0;
81 for (irq = 0, irq_bits = irqs; irq_bits != 0; irq++, irq_bits >>= 1) {
84 if ((s32)(cycle - event_cycles[irq]) >= 0) {
89 psxRegs.interrupt |= irqs;
91 if ((psxHu32(0x1070) & psxHu32(0x1074)) && (Status & 0x401) == 0x401) {
92 psxException(0x400, 0);
93 pending_exception = 1;
99 evprintf(" +ge %08x, %u->%u\n", psxRegs.pc, psxRegs.cycle, next_interupt);
103 //pending_exception = 1;
105 schedule_timeslice();
107 evprintf(" -ge %08x, %u->%u (%d)\n", psxRegs.pc, psxRegs.cycle,
108 next_interupt, next_interupt - psxRegs.cycle);
112 extern void MTC0(int reg, u32 val);
114 void pcsx_mtc0(u32 reg, u32 val)
116 evprintf("MTC0 %d #%x @%08x %u\n", reg, val, psxRegs.pc, psxRegs.cycle);
119 if (Cause & Status & 0x0300) // possible sw irq
120 pending_exception = 1;
123 void pcsx_mtc0_ds(u32 reg, u32 val)
125 evprintf("MTC0 %d #%x @%08x %u\n", reg, val, psxRegs.pc, psxRegs.cycle);
129 void new_dyna_before_save(void)
131 psxRegs.interrupt &= ~(1 << PSXINT_RCNT); // old savestate compat
133 // psxRegs.intCycle is always maintained, no need to convert
136 void new_dyna_after_save(void)
138 psxRegs.interrupt |= 1 << PSXINT_RCNT;
141 static void new_dyna_restore(void)
144 for (i = 0; i < PSXINT_COUNT; i++)
145 event_cycles[i] = psxRegs.intCycle[i].sCycle + psxRegs.intCycle[i].cycle;
147 event_cycles[PSXINT_RCNT] = psxNextsCounter + psxNextCounter;
148 psxRegs.interrupt |= 1 << PSXINT_RCNT;
149 psxRegs.interrupt &= (1 << PSXINT_COUNT) - 1;
151 new_dyna_pcsx_mem_load_state();
154 void new_dyna_freeze(void *f, int mode)
156 const char header_save[8] = "ariblks";
157 uint32_t addrs[1024 * 4];
162 if (mode != 0) { // save
163 size = new_dynarec_save_blocks(addrs, sizeof(addrs));
167 SaveFuncs.write(f, header_save, sizeof(header_save));
168 SaveFuncs.write(f, &size, sizeof(size));
169 SaveFuncs.write(f, addrs, size);
174 bytes = SaveFuncs.read(f, header, sizeof(header));
175 if (bytes != sizeof(header) || strcmp(header, header_save)) {
177 SaveFuncs.seek(f, -bytes, SEEK_CUR);
180 SaveFuncs.read(f, &size, sizeof(size));
183 if (size > sizeof(addrs)) {
184 bytes = size - sizeof(addrs);
185 SaveFuncs.seek(f, bytes, SEEK_CUR);
186 size = sizeof(addrs);
188 bytes = SaveFuncs.read(f, addrs, size);
192 new_dynarec_load_blocks(addrs, size);
195 //printf("drc: %d block info entries %s\n", size/8, mode ? "saved" : "loaded");
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
223 /* from gte.txt.. not sure if this is any good. */
224 const char gte_cycletab[64] = {
225 /* 1 2 3 4 5 6 7 8 9 a b c d e f */
226 0, 15, 0, 0, 0, 0, 8, 0, 0, 0, 0, 0, 6, 0, 0, 0,
227 8, 8, 8, 19, 13, 0, 44, 0, 0, 0, 0, 17, 11, 0, 14, 0,
228 30, 0, 0, 0, 0, 0, 0, 0, 5, 8, 17, 0, 0, 5, 6, 0,
229 23, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 5, 5, 39,
236 #define GCBITS3(b0,b1,b2) \
237 (GCBIT(b0) | GCBIT(b1) | GCBIT(b2))
238 #define GDBITS2(b0,b1) \
239 (GDBIT(b0) | GDBIT(b1))
240 #define GDBITS3(b0,b1,b2) \
241 (GDBITS2(b0,b1) | GDBIT(b2))
242 #define GDBITS4(b0,b1,b2,b3) \
243 (GDBITS3(b0,b1,b2) | GDBIT(b3))
244 #define GDBITS5(b0,b1,b2,b3,b4) \
245 (GDBITS4(b0,b1,b2,b3) | GDBIT(b4))
246 #define GDBITS6(b0,b1,b2,b3,b4,b5) \
247 (GDBITS5(b0,b1,b2,b3,b4) | GDBIT(b5))
248 #define GDBITS7(b0,b1,b2,b3,b4,b5,b6) \
249 (GDBITS6(b0,b1,b2,b3,b4,b5) | GDBIT(b6))
250 #define GDBITS8(b0,b1,b2,b3,b4,b5,b6,b7) \
251 (GDBITS7(b0,b1,b2,b3,b4,b5,b6) | GDBIT(b7))
252 #define GDBITS9(b0,b1,b2,b3,b4,b5,b6,b7,b8) \
253 (GDBITS8(b0,b1,b2,b3,b4,b5,b6,b7) | GDBIT(b8))
254 #define GDBITS10(b0,b1,b2,b3,b4,b5,b6,b7,b8,b9) \
255 (GDBITS9(b0,b1,b2,b3,b4,b5,b6,b7,b8) | GDBIT(b9))
257 const uint64_t gte_reg_reads[64] = {
258 [GTE_RTPS] = 0x1f0000ff00000000ll | GDBITS7(0,1,13,14,17,18,19),
259 [GTE_NCLIP] = GDBITS3(12,13,14),
260 [GTE_OP] = GCBITS3(0,2,4) | GDBITS3(9,10,11),
261 [GTE_DPCS] = GCBITS3(21,22,23) | GDBITS4(6,8,21,22),
262 [GTE_INTPL] = GCBITS3(21,22,23) | GDBITS7(6,8,9,10,11,21,22),
263 [GTE_MVMVA] = 0x00ffffff00000000ll | GDBITS9(0,1,2,3,4,5,9,10,11), // XXX: maybe decode further?
264 [GTE_NCDS] = 0x00ffff0000000000ll | GDBITS6(0,1,6,8,21,22),
265 [GTE_CDP] = 0x00ffe00000000000ll | GDBITS7(6,8,9,10,11,21,22),
266 [GTE_NCDT] = 0x00ffff0000000000ll | GDBITS8(0,1,2,3,4,5,6,8),
267 [GTE_NCCS] = 0x001fff0000000000ll | GDBITS5(0,1,6,21,22),
268 [GTE_CC] = 0x001fe00000000000ll | GDBITS6(6,9,10,11,21,22),
269 [GTE_NCS] = 0x001fff0000000000ll | GDBITS5(0,1,6,21,22),
270 [GTE_NCT] = 0x001fff0000000000ll | GDBITS7(0,1,2,3,4,5,6),
271 [GTE_SQR] = GDBITS3(9,10,11),
272 [GTE_DCPL] = GCBITS3(21,22,23) | GDBITS7(6,8,9,10,11,21,22),
273 [GTE_DPCT] = GCBITS3(21,22,23) | GDBITS4(8,20,21,22),
274 [GTE_AVSZ3] = GCBIT(29) | GDBITS3(17,18,19),
275 [GTE_AVSZ4] = GCBIT(30) | GDBITS4(16,17,18,19),
276 [GTE_RTPT] = 0x1f0000ff00000000ll | GDBITS7(0,1,2,3,4,5,19),
277 [GTE_GPF] = GDBITS7(6,8,9,10,11,21,22),
278 [GTE_GPL] = GDBITS10(6,8,9,10,11,21,22,25,26,27),
279 [GTE_NCCT] = 0x001fff0000000000ll | GDBITS7(0,1,2,3,4,5,6),
282 // note: this excludes gteFLAG that is always written to
283 const uint64_t gte_reg_writes[64] = {
284 [GTE_RTPS] = 0x0f0f7f00ll,
285 [GTE_NCLIP] = GDBIT(24),
286 [GTE_OP] = GDBITS6(9,10,11,25,26,27),
287 [GTE_DPCS] = GDBITS9(9,10,11,20,21,22,25,26,27),
288 [GTE_INTPL] = GDBITS9(9,10,11,20,21,22,25,26,27),
289 [GTE_MVMVA] = GDBITS6(9,10,11,25,26,27),
290 [GTE_NCDS] = GDBITS9(9,10,11,20,21,22,25,26,27),
291 [GTE_CDP] = GDBITS9(9,10,11,20,21,22,25,26,27),
292 [GTE_NCDT] = GDBITS9(9,10,11,20,21,22,25,26,27),
293 [GTE_NCCS] = GDBITS9(9,10,11,20,21,22,25,26,27),
294 [GTE_CC] = GDBITS9(9,10,11,20,21,22,25,26,27),
295 [GTE_NCS] = GDBITS9(9,10,11,20,21,22,25,26,27),
296 [GTE_NCT] = GDBITS9(9,10,11,20,21,22,25,26,27),
297 [GTE_SQR] = GDBITS6(9,10,11,25,26,27),
298 [GTE_DCPL] = GDBITS9(9,10,11,20,21,22,25,26,27),
299 [GTE_DPCT] = GDBITS9(9,10,11,20,21,22,25,26,27),
300 [GTE_AVSZ3] = GDBITS2(7,24),
301 [GTE_AVSZ4] = GDBITS2(7,24),
302 [GTE_RTPT] = 0x0f0f7f00ll,
303 [GTE_GPF] = GDBITS9(9,10,11,20,21,22,25,26,27),
304 [GTE_GPL] = GDBITS9(9,10,11,20,21,22,25,26,27),
305 [GTE_NCCT] = GDBITS9(9,10,11,20,21,22,25,26,27),
308 static int ari64_init()
310 extern void (*psxCP2[64])();
311 extern void psxNULL();
312 extern unsigned char *out;
316 new_dyna_pcsx_mem_init();
318 for (i = 0; i < ARRAY_SIZE(gte_handlers); i++)
319 if (psxCP2[i] != psxNULL)
320 gte_handlers[i] = psxCP2[i];
322 #if defined(__arm__) && !defined(DRC_DBG)
323 gte_handlers[0x06] = gteNCLIP_arm;
325 gte_handlers_nf[0x01] = gteRTPS_nf_arm;
326 gte_handlers_nf[0x30] = gteRTPT_nf_arm;
329 // compiler's _nf version is still a lot slower than neon
330 // _nf_arm RTPS is roughly the same, RTPT slower
331 gte_handlers[0x01] = gte_handlers_nf[0x01] = gteRTPS_neon;
332 gte_handlers[0x30] = gte_handlers_nf[0x30] = gteRTPT_neon;
336 memcpy(gte_handlers_nf, gte_handlers, sizeof(gte_handlers_nf));
340 zeromem_ptr = zero_mem;
341 scratch_buf_ptr = scratch_buf;
343 SysPrintf("Mapped (RAM/scrp/ROM/LUTs/TC):\n");
344 SysPrintf("%08x/%08x/%08x/%08x/%08x\n",
345 psxM, psxH, psxR, mem_rtab, out);
350 static void ari64_reset()
352 printf("ari64_reset\n");
353 new_dyna_pcsx_mem_reset();
354 invalidate_all_pages();
356 pending_exception = 1;
359 // execute until predefined leave points
360 // (HLE softcall exit and BIOS fastboot end)
361 static void ari64_execute_until()
363 schedule_timeslice();
365 evprintf("ari64_execute %08x, %u->%u (%d)\n", psxRegs.pc,
366 psxRegs.cycle, next_interupt, next_interupt - psxRegs.cycle);
370 evprintf("ari64_execute end %08x, %u->%u (%d)\n", psxRegs.pc,
371 psxRegs.cycle, next_interupt, next_interupt - psxRegs.cycle);
374 static void ari64_execute()
377 ari64_execute_until();
378 evprintf("drc left @%08x\n", psxRegs.pc);
382 static void ari64_clear(u32 addr, u32 size)
384 u32 start, end, main_ram;
386 size *= 4; /* PCSX uses DMA units (words) */
388 evprintf("ari64_clear %08x %04x\n", addr, size);
390 /* check for RAM mirrors */
391 main_ram = (addr & 0xffe00000) == 0x80000000;
394 end = (addr + size) >> 12;
396 for (; start <= end; start++)
397 if (!main_ram || !invalid_code[start])
398 invalidate_block(start);
401 #ifdef ICACHE_EMULATION
402 static void ari64_notify(int note, void *data) {
404 To change once we have proper icache emulation
407 case R3000ACPU_NOTIFY_CACHE_UNISOLATED:
408 ari64_clear(0, 0x200000/4);
410 case R3000ACPU_NOTIFY_CACHE_ISOLATED:
411 // Sent from psxDma3().
412 case R3000ACPU_NOTIFY_DMA3_EXE_LOAD:
419 static void ari64_shutdown()
421 new_dynarec_cleanup();
422 new_dyna_pcsx_mem_shutdown();
425 extern void intExecute();
426 extern void intExecuteT();
427 extern void intExecuteBlock();
428 extern void intExecuteBlockT();
430 #define intExecuteT intExecute
431 #define intExecuteBlockT intExecuteBlock
445 #ifdef ICACHE_EMULATION
453 void do_insn_trace() {}
454 void do_insn_cmp() {}
458 unsigned int address;
459 int pending_exception, stop;
461 int new_dynarec_did_compile;
462 int cycle_multiplier;
463 int new_dynarec_hacks;
469 void *scratch_buf_ptr;
470 void new_dynarec_init() { (void)ari64_execute; }
471 void new_dyna_start() {}
472 void new_dynarec_cleanup() {}
473 void new_dynarec_clear_full() {}
474 void invalidate_all_pages() {}
475 void invalidate_block(unsigned int block) {}
476 void new_dyna_pcsx_mem_init(void) {}
477 void new_dyna_pcsx_mem_reset(void) {}
478 void new_dyna_pcsx_mem_load_state(void) {}
479 void new_dyna_pcsx_mem_shutdown(void) {}
480 int new_dynarec_save_blocks(void *save, int size) { return 0; }
481 void new_dynarec_load_blocks(const void *save, int size) {}
488 extern u32 last_io_addr;
490 static void dump_mem(const char *fname, void *mem, size_t size)
492 FILE *f1 = fopen(fname, "wb");
494 f1 = fopen(strrchr(fname, '/') + 1, "wb");
495 fwrite(mem, 1, size, f1);
499 static u32 memcheck_read(u32 a)
501 if ((a >> 16) == 0x1f80)
503 return *(u32 *)(psxH + (a & 0xfffc));
505 if ((a >> 16) == 0x1f00)
507 return *(u32 *)(psxP + (a & 0xfffc));
509 // if ((a & ~0xe0600000) < 0x200000)
511 return *(u32 *)(psxM + (a & 0x1ffffc));
514 void do_insn_trace(void)
516 static psxRegisters oldregs;
517 static u32 old_io_addr = (u32)-1;
518 static u32 old_io_data = 0xbad0c0de;
519 static u32 event_cycles_o[PSXINT_COUNT];
520 u32 *allregs_p = (void *)&psxRegs;
521 u32 *allregs_o = (void *)&oldregs;
526 //last_io_addr = 0x5e2c8;
528 f = fopen("tracelog", "wb");
531 oldregs.code = psxRegs.code; // don't care
532 for (i = 0; i < offsetof(psxRegisters, intCycle) / 4; i++) {
533 if (allregs_p[i] != allregs_o[i]) {
535 fwrite(&allregs_p[i], 1, 4, f);
536 allregs_o[i] = allregs_p[i];
540 for (i = 0; i < PSXINT_COUNT; i++) {
541 if (event_cycles[i] != event_cycles_o[i]) {
543 fwrite(&byte, 1, 1, f);
545 fwrite(&event_cycles[i], 1, 4, f);
546 event_cycles_o[i] = event_cycles[i];
550 if (old_io_addr != last_io_addr) {
552 fwrite(&byte, 1, 1, f);
553 fwrite(&last_io_addr, 1, 4, f);
554 old_io_addr = last_io_addr;
556 io_data = memcheck_read(last_io_addr);
557 if (old_io_data != io_data) {
559 fwrite(&byte, 1, 1, f);
560 fwrite(&io_data, 1, 4, f);
561 old_io_data = io_data;
564 fwrite(&byte, 1, 1, f);
567 if (psxRegs.cycle == 190230) {
568 dump_mem("/mnt/ntz/dev/pnd/tmp/psxram_i.dump", psxM, 0x200000);
569 dump_mem("/mnt/ntz/dev/pnd/tmp/psxregs_i.dump", psxH, 0x10000);
576 static const char *regnames[offsetof(psxRegisters, intCycle) / 4] = {
577 "r0", "r1", "r2", "r3", "r4", "r5", "r6", "r7",
578 "r8", "r9", "r10", "r11", "r12", "r13", "r14", "r15",
579 "r16", "r17", "r18", "r19", "r20", "r21", "r22", "r23",
580 "r24", "r25", "r26", "r27", "r28", "r29", "r30", "r31",
582 "C0_0", "C0_1", "C0_2", "C0_3", "C0_4", "C0_5", "C0_6", "C0_7",
583 "C0_8", "C0_9", "C0_10", "C0_11", "C0_12", "C0_13", "C0_14", "C0_15",
584 "C0_16", "C0_17", "C0_18", "C0_19", "C0_20", "C0_21", "C0_22", "C0_23",
585 "C0_24", "C0_25", "C0_26", "C0_27", "C0_28", "C0_29", "C0_30", "C0_31",
587 "C2D0", "C2D1", "C2D2", "C2D3", "C2D4", "C2D5", "C2D6", "C2D7",
588 "C2D8", "C2D9", "C2D10", "C2D11", "C2D12", "C2D13", "C2D14", "C2D15",
589 "C2D16", "C2D17", "C2D18", "C2D19", "C2D20", "C2D21", "C2D22", "C2D23",
590 "C2D24", "C2D25", "C2D26", "C2D27", "C2D28", "C2D29", "C2D30", "C2D31",
592 "C2C0", "C2C1", "C2C2", "C2C3", "C2C4", "C2C5", "C2C6", "C2C7",
593 "C2C8", "C2C9", "C2C10", "C2C11", "C2C12", "C2C13", "C2C14", "C2C15",
594 "C2C16", "C2C17", "C2C18", "C2C19", "C2C20", "C2C21", "C2C22", "C2C23",
595 "C2C24", "C2C25", "C2C26", "C2C27", "C2C28", "C2C29", "C2C30", "C2C31",
597 "PC", "code", "cycle", "interrupt",
605 static int miss_log_i;
606 #define miss_log_len (sizeof(miss_log)/sizeof(miss_log[0]))
607 #define miss_log_mask (miss_log_len-1)
609 static void miss_log_add(int reg, u32 val, u32 val_expect, u32 pc, u32 cycle)
611 miss_log[miss_log_i].reg = reg;
612 miss_log[miss_log_i].val = val;
613 miss_log[miss_log_i].val_expect = val_expect;
614 miss_log[miss_log_i].pc = pc;
615 miss_log[miss_log_i].cycle = cycle;
616 miss_log_i = (miss_log_i + 1) & miss_log_mask;
621 void do_insn_cmp(void)
623 static psxRegisters rregs;
624 static u32 mem_addr, mem_val;
625 u32 *allregs_p = (void *)&psxRegs;
626 u32 *allregs_e = (void *)&rregs;
627 static u32 ppc, failcount;
628 int i, ret, bad = 0, which_event = -1;
633 f = fopen("tracelog", "rb");
636 if ((ret = fread(&code, 1, 1, f)) <= 0)
645 fread(&which_event, 1, 1, f);
646 fread(&ev_cycles, 1, 4, f);
649 fread(&mem_addr, 1, 4, f);
652 fread(&mem_val, 1, 4, f);
655 fread(&allregs_e[code], 1, 4, f);
663 psxRegs.code = rregs.code; // don't care
664 psxRegs.cycle = rregs.cycle;
665 psxRegs.CP0.r[9] = rregs.CP0.r[9]; // Count
667 //if (psxRegs.cycle == 166172) breakme();
669 if (memcmp(&psxRegs, &rregs, offsetof(psxRegisters, intCycle)) == 0 &&
670 mem_val == memcheck_read(mem_addr)
676 for (i = 0; i < offsetof(psxRegisters, intCycle) / 4; i++) {
677 if (allregs_p[i] != allregs_e[i]) {
678 miss_log_add(i, allregs_p[i], allregs_e[i], psxRegs.pc, psxRegs.cycle);
683 if (mem_val != memcheck_read(mem_addr)) {
684 printf("bad mem @%08x: %08x %08x\n", mem_addr, memcheck_read(mem_addr), mem_val);
688 if (which_event >= 0 && event_cycles[which_event] != ev_cycles) {
689 printf("bad ev_cycles #%d: %08x %08x\n", which_event, event_cycles[which_event], ev_cycles);
693 if (psxRegs.pc == rregs.pc && bad < 6 && failcount < 32) {
694 static int last_mcycle;
695 if (last_mcycle != psxRegs.cycle >> 20) {
696 printf("%u\n", psxRegs.cycle);
697 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\n", psxRegs.pc, ppc, psxRegs.cycle);
713 dump_mem("/mnt/ntz/dev/pnd/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