drc: rework cycle counting
[pcsx_rearmed.git] / libpcsxcore / new_dynarec / emu_if.c
1 /*
2  * (C) GraÅžvydas "notaz" Ignotas, 2010-2011
3  *
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.
6  */
7
8 #include <stdio.h>
9
10 #include "emu_if.h"
11 #include "pcsxmem.h"
12 #include "../psxhle.h"
13 #include "../psxinterpreter.h"
14 #include "../r3000a.h"
15 #include "../cdrom.h"
16 #include "../psxdma.h"
17 #include "../mdec.h"
18 #include "../gte_arm.h"
19 #include "../gte_neon.h"
20 #define FLAGLESS
21 #include "../gte.h"
22
23 #define ARRAY_SIZE(x) (sizeof(x) / sizeof(x[0]))
24
25 //#define evprintf printf
26 #define evprintf(...)
27
28 char invalid_code[0x100000];
29 u32 event_cycles[PSXINT_COUNT];
30
31 static void schedule_timeslice(void)
32 {
33         u32 i, c = psxRegs.cycle;
34         u32 irqs = psxRegs.interrupt;
35         s32 min, dif;
36
37         min = PSXCLK;
38         for (i = 0; irqs != 0; i++, irqs >>= 1) {
39                 if (!(irqs & 1))
40                         continue;
41                 dif = event_cycles[i] - c;
42                 //evprintf("  ev %d\n", dif);
43                 if (0 < dif && dif < min)
44                         min = dif;
45         }
46         next_interupt = c + min;
47 }
48
49 typedef void (irq_func)();
50
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,
65 };
66
67 /* local dupe of psxBranchTest, using event_cycles */
68 static void irq_test(void)
69 {
70         u32 irqs = psxRegs.interrupt;
71         u32 cycle = psxRegs.cycle;
72         u32 irq, irq_bits;
73
74         // irq_funcs() may queue more irqs
75         psxRegs.interrupt = 0;
76
77         for (irq = 0, irq_bits = irqs; irq_bits != 0; irq++, irq_bits >>= 1) {
78                 if (!(irq_bits & 1))
79                         continue;
80                 if ((s32)(cycle - event_cycles[irq]) >= 0) {
81                         irqs &= ~(1 << irq);
82                         irq_funcs[irq]();
83                 }
84         }
85         psxRegs.interrupt |= irqs;
86
87         if ((psxHu32(0x1070) & psxHu32(0x1074)) && (Status & 0x401) == 0x401) {
88                 psxException(0x400, 0);
89                 pending_exception = 1;
90         }
91 }
92
93 void gen_interupt()
94 {
95         evprintf("  +ge %08x, %u->%u\n", psxRegs.pc, psxRegs.cycle, next_interupt);
96
97         irq_test();
98         //psxBranchTest();
99         //pending_exception = 1;
100
101         schedule_timeslice();
102
103         evprintf("  -ge %08x, %u->%u (%d)\n", psxRegs.pc, psxRegs.cycle,
104                 next_interupt, next_interupt - psxRegs.cycle);
105 }
106
107 // from interpreter
108 extern void MTC0(int reg, u32 val);
109
110 void pcsx_mtc0(u32 reg, u32 val)
111 {
112         evprintf("MTC0 %d #%x @%08x %u\n", reg, val, psxRegs.pc, psxRegs.cycle);
113         MTC0(reg, val);
114         gen_interupt();
115         if (Cause & Status & 0x0300) // possible sw irq
116                 pending_exception = 1;
117 }
118
119 void pcsx_mtc0_ds(u32 reg, u32 val)
120 {
121         evprintf("MTC0 %d #%x @%08x %u\n", reg, val, psxRegs.pc, psxRegs.cycle);
122         MTC0(reg, val);
123 }
124
125 void new_dyna_before_save(void)
126 {
127         psxRegs.interrupt &= ~(1 << PSXINT_RCNT); // old savestate compat
128
129         // psxRegs.intCycle is always maintained, no need to convert
130 }
131
132 void new_dyna_after_save(void)
133 {
134         psxRegs.interrupt |= 1 << PSXINT_RCNT;
135 }
136
137 static void new_dyna_restore(void)
138 {
139         int i;
140         for (i = 0; i < PSXINT_COUNT; i++)
141                 event_cycles[i] = psxRegs.intCycle[i].sCycle + psxRegs.intCycle[i].cycle;
142
143         event_cycles[PSXINT_RCNT] = psxNextsCounter + psxNextCounter;
144         psxRegs.interrupt |=  1 << PSXINT_RCNT;
145         psxRegs.interrupt &= (1 << PSXINT_COUNT) - 1;
146
147         new_dyna_pcsx_mem_load_state();
148 }
149
150 void new_dyna_freeze(void *f, int mode)
151 {
152         const char header_save[8] = "ariblks";
153         uint32_t addrs[1024 * 4];
154         int32_t size = 0;
155         int bytes;
156         char header[8];
157
158         if (mode != 0) { // save
159                 size = new_dynarec_save_blocks(addrs, sizeof(addrs));
160                 if (size == 0)
161                         return;
162
163                 SaveFuncs.write(f, header_save, sizeof(header_save));
164                 SaveFuncs.write(f, &size, sizeof(size));
165                 SaveFuncs.write(f, addrs, size);
166         }
167         else {
168                 new_dyna_restore();
169
170                 bytes = SaveFuncs.read(f, header, sizeof(header));
171                 if (bytes != sizeof(header) || strcmp(header, header_save)) {
172                         if (bytes > 0)
173                                 SaveFuncs.seek(f, -bytes, SEEK_CUR);
174                         return;
175                 }
176                 SaveFuncs.read(f, &size, sizeof(size));
177                 if (size <= 0)
178                         return;
179                 if (size > sizeof(addrs)) {
180                         bytes = size - sizeof(addrs);
181                         SaveFuncs.seek(f, bytes, SEEK_CUR);
182                         size = sizeof(addrs);
183                 }
184                 bytes = SaveFuncs.read(f, addrs, size);
185                 if (bytes != size)
186                         return;
187
188                 if (psxCpu != &psxInt)
189                         new_dynarec_load_blocks(addrs, size);
190         }
191
192         //printf("drc: %d block info entries %s\n", size/8, mode ? "saved" : "loaded");
193 }
194
195 #ifndef DRC_DISABLE
196
197 /* GTE stuff */
198 void *gte_handlers[64];
199
200 void *gte_handlers_nf[64] = {
201         NULL      , gteRTPS_nf , NULL       , NULL      , NULL     , NULL       , gteNCLIP_nf, NULL      , // 00
202         NULL      , NULL       , NULL       , NULL      , gteOP_nf , NULL       , NULL       , NULL      , // 08
203         gteDPCS_nf, gteINTPL_nf, gteMVMVA_nf, gteNCDS_nf, gteCDP_nf, NULL       , gteNCDT_nf , NULL      , // 10
204         NULL      , NULL       , NULL       , gteNCCS_nf, gteCC_nf , NULL       , gteNCS_nf  , NULL      , // 18
205         gteNCT_nf , NULL       , NULL       , NULL      , NULL     , NULL       , NULL       , NULL      , // 20
206         gteSQR_nf , gteDCPL_nf , gteDPCT_nf , NULL      , NULL     , gteAVSZ3_nf, gteAVSZ4_nf, NULL      , // 28 
207         gteRTPT_nf, NULL       , NULL       , NULL      , NULL     , NULL       , NULL       , NULL      , // 30
208         NULL      , NULL       , NULL       , NULL      , NULL     , gteGPF_nf  , gteGPL_nf  , gteNCCT_nf, // 38
209 };
210
211 const char *gte_regnames[64] = {
212         NULL  , "RTPS" , NULL   , NULL  , NULL , NULL   , "NCLIP", NULL  , // 00
213         NULL  , NULL   , NULL   , NULL  , "OP" , NULL   , NULL   , NULL  , // 08
214         "DPCS", "INTPL", "MVMVA", "NCDS", "CDP", NULL   , "NCDT" , NULL  , // 10
215         NULL  , NULL   , NULL   , "NCCS", "CC" , NULL   , "NCS"  , NULL  , // 18
216         "NCT" , NULL   , NULL   , NULL  , NULL , NULL   , NULL   , NULL  , // 20
217         "SQR" , "DCPL" , "DPCT" , NULL  , NULL , "AVSZ3", "AVSZ4", NULL  , // 28 
218         "RTPT", NULL   , NULL   , NULL  , NULL , NULL   , NULL   , NULL  , // 30
219         NULL  , NULL   , NULL   , NULL  , NULL , "GPF"  , "GPL"  , "NCCT", // 38
220 };
221
222 #define GCBIT(x) \
223         (1ll << (32+x))
224 #define GDBIT(x) \
225         (1ll << (x))
226 #define GCBITS3(b0,b1,b2) \
227         (GCBIT(b0) | GCBIT(b1) | GCBIT(b2))
228 #define GDBITS2(b0,b1) \
229         (GDBIT(b0) | GDBIT(b1))
230 #define GDBITS3(b0,b1,b2) \
231         (GDBITS2(b0,b1) | GDBIT(b2))
232 #define GDBITS4(b0,b1,b2,b3) \
233         (GDBITS3(b0,b1,b2) | GDBIT(b3))
234 #define GDBITS5(b0,b1,b2,b3,b4) \
235         (GDBITS4(b0,b1,b2,b3) | GDBIT(b4))
236 #define GDBITS6(b0,b1,b2,b3,b4,b5) \
237         (GDBITS5(b0,b1,b2,b3,b4) | GDBIT(b5))
238 #define GDBITS7(b0,b1,b2,b3,b4,b5,b6) \
239         (GDBITS6(b0,b1,b2,b3,b4,b5) | GDBIT(b6))
240 #define GDBITS8(b0,b1,b2,b3,b4,b5,b6,b7) \
241         (GDBITS7(b0,b1,b2,b3,b4,b5,b6) | GDBIT(b7))
242 #define GDBITS9(b0,b1,b2,b3,b4,b5,b6,b7,b8) \
243         (GDBITS8(b0,b1,b2,b3,b4,b5,b6,b7) | GDBIT(b8))
244 #define GDBITS10(b0,b1,b2,b3,b4,b5,b6,b7,b8,b9) \
245         (GDBITS9(b0,b1,b2,b3,b4,b5,b6,b7,b8) | GDBIT(b9))
246
247 const uint64_t gte_reg_reads[64] = {
248         [GTE_RTPS]  = 0x1f0000ff00000000ll | GDBITS7(0,1,13,14,17,18,19),
249         [GTE_NCLIP] =                        GDBITS3(12,13,14),
250         [GTE_OP]    = GCBITS3(0,2,4)       | GDBITS3(9,10,11),
251         [GTE_DPCS]  = GCBITS3(21,22,23)    | GDBITS4(6,8,21,22),
252         [GTE_INTPL] = GCBITS3(21,22,23)    | GDBITS7(6,8,9,10,11,21,22),
253         [GTE_MVMVA] = 0x00ffffff00000000ll | GDBITS9(0,1,2,3,4,5,9,10,11), // XXX: maybe decode further?
254         [GTE_NCDS]  = 0x00ffff0000000000ll | GDBITS6(0,1,6,8,21,22),
255         [GTE_CDP]   = 0x00ffe00000000000ll | GDBITS7(6,8,9,10,11,21,22),
256         [GTE_NCDT]  = 0x00ffff0000000000ll | GDBITS8(0,1,2,3,4,5,6,8),
257         [GTE_NCCS]  = 0x001fff0000000000ll | GDBITS5(0,1,6,21,22),
258         [GTE_CC]    = 0x001fe00000000000ll | GDBITS6(6,9,10,11,21,22),
259         [GTE_NCS]   = 0x001fff0000000000ll | GDBITS5(0,1,6,21,22),
260         [GTE_NCT]   = 0x001fff0000000000ll | GDBITS7(0,1,2,3,4,5,6),
261         [GTE_SQR]   =                        GDBITS3(9,10,11),
262         [GTE_DCPL]  = GCBITS3(21,22,23)    | GDBITS7(6,8,9,10,11,21,22),
263         [GTE_DPCT]  = GCBITS3(21,22,23)    | GDBITS4(8,20,21,22),
264         [GTE_AVSZ3] = GCBIT(29)            | GDBITS3(17,18,19),
265         [GTE_AVSZ4] = GCBIT(30)            | GDBITS4(16,17,18,19),
266         [GTE_RTPT]  = 0x1f0000ff00000000ll | GDBITS7(0,1,2,3,4,5,19),
267         [GTE_GPF]   =                        GDBITS7(6,8,9,10,11,21,22),
268         [GTE_GPL]   =                        GDBITS10(6,8,9,10,11,21,22,25,26,27),
269         [GTE_NCCT]  = 0x001fff0000000000ll | GDBITS7(0,1,2,3,4,5,6),
270 };
271
272 // note: this excludes gteFLAG that is always written to
273 const uint64_t gte_reg_writes[64] = {
274         [GTE_RTPS]  = 0x0f0f7f00ll,
275         [GTE_NCLIP] = GDBIT(24),
276         [GTE_OP]    = GDBITS6(9,10,11,25,26,27),
277         [GTE_DPCS]  = GDBITS9(9,10,11,20,21,22,25,26,27),
278         [GTE_INTPL] = GDBITS9(9,10,11,20,21,22,25,26,27),
279         [GTE_MVMVA] = GDBITS6(9,10,11,25,26,27),
280         [GTE_NCDS]  = GDBITS9(9,10,11,20,21,22,25,26,27),
281         [GTE_CDP]   = GDBITS9(9,10,11,20,21,22,25,26,27),
282         [GTE_NCDT]  = GDBITS9(9,10,11,20,21,22,25,26,27),
283         [GTE_NCCS]  = GDBITS9(9,10,11,20,21,22,25,26,27),
284         [GTE_CC]    = GDBITS9(9,10,11,20,21,22,25,26,27),
285         [GTE_NCS]   = GDBITS9(9,10,11,20,21,22,25,26,27),
286         [GTE_NCT]   = GDBITS9(9,10,11,20,21,22,25,26,27),
287         [GTE_SQR]   = GDBITS6(9,10,11,25,26,27),
288         [GTE_DCPL]  = GDBITS9(9,10,11,20,21,22,25,26,27),
289         [GTE_DPCT]  = GDBITS9(9,10,11,20,21,22,25,26,27),
290         [GTE_AVSZ3] = GDBITS2(7,24),
291         [GTE_AVSZ4] = GDBITS2(7,24),
292         [GTE_RTPT]  = 0x0f0f7f00ll,
293         [GTE_GPF]   = GDBITS9(9,10,11,20,21,22,25,26,27),
294         [GTE_GPL]   = GDBITS9(9,10,11,20,21,22,25,26,27),
295         [GTE_NCCT]  = GDBITS9(9,10,11,20,21,22,25,26,27),
296 };
297
298 static int ari64_init()
299 {
300         static u32 scratch_buf[8*8*2] __attribute__((aligned(64)));
301         extern void (*psxCP2[64])();
302         extern void psxNULL();
303         extern unsigned char *out;
304         size_t i;
305
306         new_dynarec_init();
307         new_dyna_pcsx_mem_init();
308
309         for (i = 0; i < ARRAY_SIZE(gte_handlers); i++)
310                 if (psxCP2[i] != psxNULL)
311                         gte_handlers[i] = psxCP2[i];
312
313 #if defined(__arm__) && !defined(DRC_DBG)
314         gte_handlers[0x06] = gteNCLIP_arm;
315 #ifdef HAVE_ARMV5
316         gte_handlers_nf[0x01] = gteRTPS_nf_arm;
317         gte_handlers_nf[0x30] = gteRTPT_nf_arm;
318 #endif
319 #ifdef __ARM_NEON__
320         // compiler's _nf version is still a lot slower than neon
321         // _nf_arm RTPS is roughly the same, RTPT slower
322         gte_handlers[0x01] = gte_handlers_nf[0x01] = gteRTPS_neon;
323         gte_handlers[0x30] = gte_handlers_nf[0x30] = gteRTPT_neon;
324 #endif
325 #endif
326 #ifdef DRC_DBG
327         memcpy(gte_handlers_nf, gte_handlers, sizeof(gte_handlers_nf));
328 #endif
329         psxH_ptr = psxH;
330         zeromem_ptr = zero_mem;
331         scratch_buf_ptr = scratch_buf;
332
333         SysPrintf("Mapped (RAM/scrp/ROM/LUTs/TC):\n");
334         SysPrintf("%p/%p/%p/%p/%p\n",
335                 psxM, psxH, psxR, mem_rtab, out);
336
337         return 0;
338 }
339
340 static void ari64_reset()
341 {
342         printf("ari64_reset\n");
343         new_dyna_pcsx_mem_reset();
344         invalidate_all_pages();
345         new_dyna_restore();
346         pending_exception = 1;
347 }
348
349 // execute until predefined leave points
350 // (HLE softcall exit and BIOS fastboot end)
351 static void ari64_execute_until()
352 {
353         schedule_timeslice();
354
355         evprintf("ari64_execute %08x, %u->%u (%d)\n", psxRegs.pc,
356                 psxRegs.cycle, next_interupt, next_interupt - psxRegs.cycle);
357
358         new_dyna_start(dynarec_local);
359
360         evprintf("ari64_execute end %08x, %u->%u (%d)\n", psxRegs.pc,
361                 psxRegs.cycle, next_interupt, next_interupt - psxRegs.cycle);
362 }
363
364 static void ari64_execute()
365 {
366         while (!stop) {
367                 ari64_execute_until();
368                 evprintf("drc left @%08x\n", psxRegs.pc);
369         }
370 }
371
372 static void ari64_clear(u32 addr, u32 size)
373 {
374         u32 start, end, main_ram;
375
376         size *= 4; /* PCSX uses DMA units (words) */
377
378         evprintf("ari64_clear %08x %04x\n", addr, size);
379
380         /* check for RAM mirrors */
381         main_ram = (addr & 0xffe00000) == 0x80000000;
382
383         start = addr >> 12;
384         end = (addr + size) >> 12;
385
386         for (; start <= end; start++)
387                 if (!main_ram || !invalid_code[start])
388                         invalidate_block(start);
389 }
390
391 static void ari64_notify(int note, void *data) {
392         /*
393         Should be fixed when ARM dynarec has proper icache emulation.
394         switch (note)
395         {
396                 case R3000ACPU_NOTIFY_CACHE_UNISOLATED:
397                         break;
398                 case R3000ACPU_NOTIFY_CACHE_ISOLATED:
399                 Sent from psxDma3().
400                 case R3000ACPU_NOTIFY_DMA3_EXE_LOAD:
401                 default:
402                         break;
403         }
404         */
405 }
406
407 static void ari64_apply_config()
408 {
409         intApplyConfig();
410
411         if (Config.DisableStalls)
412                 new_dynarec_hacks |= NDHACK_NO_STALLS;
413         else
414                 new_dynarec_hacks &= ~NDHACK_NO_STALLS;
415
416         if (cycle_multiplier != cycle_multiplier_old
417             || new_dynarec_hacks != new_dynarec_hacks_old)
418         {
419                 new_dynarec_clear_full();
420         }
421 }
422
423 static void ari64_shutdown()
424 {
425         new_dynarec_cleanup();
426         new_dyna_pcsx_mem_shutdown();
427 }
428
429 R3000Acpu psxRec = {
430         ari64_init,
431         ari64_reset,
432         ari64_execute,
433         ari64_execute_until,
434         ari64_clear,
435         ari64_notify,
436         ari64_apply_config,
437         ari64_shutdown
438 };
439
440 #else // if DRC_DISABLE
441
442 unsigned int address;
443 int pending_exception, stop;
444 unsigned int next_interupt;
445 int new_dynarec_did_compile;
446 int cycle_multiplier;
447 int cycle_multiplier_override;
448 int cycle_multiplier_old;
449 int new_dynarec_hacks_pergame;
450 int new_dynarec_hacks_old;
451 int new_dynarec_hacks;
452 void *psxH_ptr;
453 void *zeromem_ptr;
454 u8 zero_mem[0x1000];
455 unsigned char *out;
456 void *mem_rtab;
457 void *scratch_buf_ptr;
458 void new_dynarec_init() {}
459 void new_dyna_start(void *context) {}
460 void new_dynarec_cleanup() {}
461 void new_dynarec_clear_full() {}
462 void invalidate_all_pages() {}
463 void invalidate_block(unsigned int block) {}
464 void new_dyna_pcsx_mem_init(void) {}
465 void new_dyna_pcsx_mem_reset(void) {}
466 void new_dyna_pcsx_mem_load_state(void) {}
467 void new_dyna_pcsx_mem_shutdown(void) {}
468 int  new_dynarec_save_blocks(void *save, int size) { return 0; }
469 void new_dynarec_load_blocks(const void *save, int size) {}
470 #endif
471
472 #ifdef DRC_DBG
473
474 #include <stddef.h>
475 static FILE *f;
476 u32 irq_test_cycle;
477 u32 handler_cycle;
478 u32 last_io_addr;
479
480 static void dump_mem(const char *fname, void *mem, size_t size)
481 {
482         FILE *f1 = fopen(fname, "wb");
483         if (f1 == NULL)
484                 f1 = fopen(strrchr(fname, '/') + 1, "wb");
485         fwrite(mem, 1, size, f1);
486         fclose(f1);
487 }
488
489 static u32 memcheck_read(u32 a)
490 {
491         if ((a >> 16) == 0x1f80)
492                 // scratchpad/IO
493                 return *(u32 *)(psxH + (a & 0xfffc));
494
495         if ((a >> 16) == 0x1f00)
496                 // parallel
497                 return *(u32 *)(psxP + (a & 0xfffc));
498
499 //      if ((a & ~0xe0600000) < 0x200000)
500         // RAM
501         return *(u32 *)(psxM + (a & 0x1ffffc));
502 }
503
504 #if 0
505 void do_insn_trace(void)
506 {
507         static psxRegisters oldregs;
508         static u32 event_cycles_o[PSXINT_COUNT];
509         u32 *allregs_p = (void *)&psxRegs;
510         u32 *allregs_o = (void *)&oldregs;
511         u32 io_data;
512         int i;
513         u8 byte;
514
515         //last_io_addr = 0x5e2c8;
516         if (f == NULL)
517                 f = fopen("tracelog", "wb");
518
519         // log reg changes
520         oldregs.code = psxRegs.code; // don't care
521         for (i = 0; i < offsetof(psxRegisters, intCycle) / 4; i++) {
522                 if (allregs_p[i] != allregs_o[i]) {
523                         fwrite(&i, 1, 1, f);
524                         fwrite(&allregs_p[i], 1, 4, f);
525                         allregs_o[i] = allregs_p[i];
526                 }
527         }
528         // log event changes
529         for (i = 0; i < PSXINT_COUNT; i++) {
530                 if (event_cycles[i] != event_cycles_o[i]) {
531                         byte = 0xf8;
532                         fwrite(&byte, 1, 1, f);
533                         fwrite(&i, 1, 1, f);
534                         fwrite(&event_cycles[i], 1, 4, f);
535                         event_cycles_o[i] = event_cycles[i];
536                 }
537         }
538         #define SAVE_IF_CHANGED(code_, name_) { \
539                 static u32 old_##name_ = 0xbad0c0de; \
540                 if (old_##name_ != name_) { \
541                         byte = code_; \
542                         fwrite(&byte, 1, 1, f); \
543                         fwrite(&name_, 1, 4, f); \
544                         old_##name_ = name_; \
545                 } \
546         }
547         SAVE_IF_CHANGED(0xfb, irq_test_cycle);
548         SAVE_IF_CHANGED(0xfc, handler_cycle);
549         SAVE_IF_CHANGED(0xfd, last_io_addr);
550         io_data = memcheck_read(last_io_addr);
551         SAVE_IF_CHANGED(0xfe, io_data);
552         byte = 0xff;
553         fwrite(&byte, 1, 1, f);
554
555 #if 0
556         if (psxRegs.cycle == 190230) {
557                 dump_mem("/mnt/ntz/dev/pnd/tmp/psxram_i.dump", psxM, 0x200000);
558                 dump_mem("/mnt/ntz/dev/pnd/tmp/psxregs_i.dump", psxH, 0x10000);
559                 printf("dumped\n");
560                 exit(1);
561         }
562 #endif
563 }
564 #endif
565
566 static const char *regnames[offsetof(psxRegisters, intCycle) / 4] = {
567         "r0",  "r1",  "r2",  "r3",  "r4",  "r5",  "r6",  "r7",
568         "r8",  "r9",  "r10", "r11", "r12", "r13", "r14", "r15",
569         "r16", "r17", "r18", "r19", "r20", "r21", "r22", "r23",
570         "r24", "r25", "r26", "r27", "r28", "r29", "r30", "r31",
571         "lo",  "hi",
572         "C0_0",  "C0_1",  "C0_2",  "C0_3",  "C0_4",  "C0_5",  "C0_6",  "C0_7",
573         "C0_8",  "C0_9",  "C0_10", "C0_11", "C0_12", "C0_13", "C0_14", "C0_15",
574         "C0_16", "C0_17", "C0_18", "C0_19", "C0_20", "C0_21", "C0_22", "C0_23",
575         "C0_24", "C0_25", "C0_26", "C0_27", "C0_28", "C0_29", "C0_30", "C0_31",
576
577         "C2D0",  "C2D1",  "C2D2",  "C2D3",  "C2D4",  "C2D5",  "C2D6",  "C2D7",
578         "C2D8",  "C2D9",  "C2D10", "C2D11", "C2D12", "C2D13", "C2D14", "C2D15",
579         "C2D16", "C2D17", "C2D18", "C2D19", "C2D20", "C2D21", "C2D22", "C2D23",
580         "C2D24", "C2D25", "C2D26", "C2D27", "C2D28", "C2D29", "C2D30", "C2D31",
581
582         "C2C0",  "C2C1",  "C2C2",  "C2C3",  "C2C4",  "C2C5",  "C2C6",  "C2C7",
583         "C2C8",  "C2C9",  "C2C10", "C2C11", "C2C12", "C2C13", "C2C14", "C2C15",
584         "C2C16", "C2C17", "C2C18", "C2C19", "C2C20", "C2C21", "C2C22", "C2C23",
585         "C2C24", "C2C25", "C2C26", "C2C27", "C2C28", "C2C29", "C2C30", "C2C31",
586
587         "PC", "code", "cycle", "interrupt",
588 };
589
590 static struct {
591         int reg;
592         u32 val, val_expect;
593         u32 pc, cycle;
594 } miss_log[64];
595 static int miss_log_i;
596 #define miss_log_len (sizeof(miss_log)/sizeof(miss_log[0]))
597 #define miss_log_mask (miss_log_len-1)
598
599 static void miss_log_add(int reg, u32 val, u32 val_expect, u32 pc, u32 cycle)
600 {
601         miss_log[miss_log_i].reg = reg;
602         miss_log[miss_log_i].val = val;
603         miss_log[miss_log_i].val_expect = val_expect;
604         miss_log[miss_log_i].pc = pc;
605         miss_log[miss_log_i].cycle = cycle;
606         miss_log_i = (miss_log_i + 1) & miss_log_mask;
607 }
608
609 void breakme() {}
610
611 void do_insn_cmp(void)
612 {
613         extern int last_count;
614         static psxRegisters rregs;
615         static u32 mem_addr, mem_val;
616         static u32 irq_test_cycle_intr;
617         static u32 handler_cycle_intr;
618         u32 *allregs_p = (void *)&psxRegs;
619         u32 *allregs_e = (void *)&rregs;
620         static u32 ppc, failcount;
621         int i, ret, bad = 0, fatal = 0, which_event = -1;
622         u32 ev_cycles = 0;
623         u8 code;
624
625         if (f == NULL)
626                 f = fopen("tracelog", "rb");
627
628         while (1) {
629                 if ((ret = fread(&code, 1, 1, f)) <= 0)
630                         break;
631                 if (ret <= 0)
632                         break;
633                 if (code == 0xff)
634                         break;
635                 switch (code) {
636                 case 0xf8:
637                         which_event = 0;
638                         fread(&which_event, 1, 1, f);
639                         fread(&ev_cycles, 1, 4, f);
640                         continue;
641                 case 0xfb:
642                         fread(&irq_test_cycle_intr, 1, 4, f);
643                         continue;
644                 case 0xfc:
645                         fread(&handler_cycle_intr, 1, 4, f);
646                         continue;
647                 case 0xfd:
648                         fread(&mem_addr, 1, 4, f);
649                         continue;
650                 case 0xfe:
651                         fread(&mem_val, 1, 4, f);
652                         continue;
653                 }
654                 assert(code < offsetof(psxRegisters, intCycle) / 4);
655                 fread(&allregs_e[code], 1, 4, f);
656         }
657
658         if (ret <= 0) {
659                 printf("EOF?\n");
660                 exit(1);
661         }
662
663         psxRegs.code = rregs.code; // don't care
664         psxRegs.cycle += last_count;
665         //psxRegs.cycle = rregs.cycle;
666         psxRegs.CP0.r[9] = rregs.CP0.r[9]; // Count
667
668         //if (psxRegs.cycle == 166172) breakme();
669
670         if (which_event >= 0 && event_cycles[which_event] != ev_cycles) {
671                 printf("bad ev_cycles #%d: %08x %08x\n", which_event, event_cycles[which_event], ev_cycles);
672                 fatal = 1;
673         }
674
675         if (irq_test_cycle > irq_test_cycle_intr) {
676                 printf("bad irq_test_cycle: %u %u\n", irq_test_cycle, irq_test_cycle_intr);
677                 fatal = 1;
678         }
679
680         if (handler_cycle != handler_cycle_intr) {
681                 printf("bad handler_cycle: %u %u\n", handler_cycle, handler_cycle_intr);
682                 fatal = 1;
683         }
684
685         if (mem_val != memcheck_read(mem_addr)) {
686                 printf("bad mem @%08x: %08x %08x\n", mem_addr, memcheck_read(mem_addr), mem_val);
687                 fatal = 1;
688         }
689
690         if (!fatal && !memcmp(&psxRegs, &rregs, offsetof(psxRegisters, intCycle))) {
691                 failcount = 0;
692                 goto ok;
693         }
694
695         for (i = 0; i < offsetof(psxRegisters, intCycle) / 4; i++) {
696                 if (allregs_p[i] != allregs_e[i]) {
697                         miss_log_add(i, allregs_p[i], allregs_e[i], psxRegs.pc, psxRegs.cycle);
698                         bad++;
699                         if (i > 32+2)
700                                 fatal = 1;
701                 }
702         }
703
704         if (!fatal && psxRegs.pc == rregs.pc && bad < 6 && failcount < 32) {
705                 static int last_mcycle;
706                 if (last_mcycle != psxRegs.cycle >> 20) {
707                         printf("%u\n", psxRegs.cycle);
708                         last_mcycle = psxRegs.cycle >> 20;
709                 }
710                 failcount++;
711                 goto ok;
712         }
713
714         for (i = 0; i < miss_log_len; i++, miss_log_i = (miss_log_i + 1) & miss_log_mask)
715                 printf("bad %5s: %08x %08x, pc=%08x, cycle %u\n",
716                         regnames[miss_log[miss_log_i].reg], miss_log[miss_log_i].val,
717                         miss_log[miss_log_i].val_expect, miss_log[miss_log_i].pc, miss_log[miss_log_i].cycle);
718         printf("-- %d\n", bad);
719         for (i = 0; i < 8; i++)
720                 printf("r%d=%08x r%2d=%08x r%2d=%08x r%2d=%08x\n", i, allregs_p[i],
721                         i+8, allregs_p[i+8], i+16, allregs_p[i+16], i+24, allregs_p[i+24]);
722         printf("PC: %08x/%08x, cycle %u\n", psxRegs.pc, ppc, psxRegs.cycle);
723         dump_mem("/mnt/ntz/dev/pnd/tmp/psxram.dump", psxM, 0x200000);
724         dump_mem("/mnt/ntz/dev/pnd/tmp/psxregs.dump", psxH, 0x10000);
725         exit(1);
726 ok:
727         //psxRegs.cycle = rregs.cycle + 2; // sync timing
728         ppc = psxRegs.pc;
729 }
730
731 #endif