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