fix x86 build
[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 u32 event_cycles[PSXINT_COUNT];
29
30 static void schedule_timeslice(void)
31 {
32         u32 i, c = psxRegs.cycle;
33         u32 irqs = psxRegs.interrupt;
34         s32 min, dif;
35
36         min = PSXCLK;
37         for (i = 0; irqs != 0; i++, irqs >>= 1) {
38                 if (!(irqs & 1))
39                         continue;
40                 dif = event_cycles[i] - c;
41                 //evprintf("  ev %d\n", dif);
42                 if (0 < dif && dif < min)
43                         min = dif;
44         }
45         next_interupt = c + min;
46 }
47
48 typedef void (irq_func)();
49
50 static irq_func * const irq_funcs[] = {
51         [PSXINT_SIO]    = sioInterrupt,
52         [PSXINT_CDR]    = cdrInterrupt,
53         [PSXINT_CDREAD] = cdrReadInterrupt,
54         [PSXINT_GPUDMA] = gpuInterrupt,
55         [PSXINT_MDECOUTDMA] = mdec1Interrupt,
56         [PSXINT_SPUDMA] = spuInterrupt,
57         [PSXINT_MDECINDMA] = mdec0Interrupt,
58         [PSXINT_GPUOTCDMA] = gpuotcInterrupt,
59         [PSXINT_CDRDMA] = cdrDmaInterrupt,
60         [PSXINT_CDRLID] = cdrLidSeekInterrupt,
61         [PSXINT_CDRPLAY] = cdrPlayInterrupt,
62         [PSXINT_SPU_UPDATE] = spuUpdate,
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_before_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 static 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 void new_dyna_freeze(void *f, int mode)
150 {
151         const char header_save[8] = "ariblks";
152         uint32_t addrs[1024 * 4];
153         int32_t size = 0;
154         int bytes;
155         char header[8];
156
157         if (mode != 0) { // save
158                 size = new_dynarec_save_blocks(addrs, sizeof(addrs));
159                 if (size == 0)
160                         return;
161
162                 SaveFuncs.write(f, header_save, sizeof(header_save));
163                 SaveFuncs.write(f, &size, sizeof(size));
164                 SaveFuncs.write(f, addrs, size);
165         }
166         else {
167                 new_dyna_restore();
168
169                 bytes = SaveFuncs.read(f, header, sizeof(header));
170                 if (bytes != sizeof(header) || strcmp(header, header_save)) {
171                         if (bytes > 0)
172                                 SaveFuncs.seek(f, -bytes, SEEK_CUR);
173                         return;
174                 }
175                 SaveFuncs.read(f, &size, sizeof(size));
176                 if (size <= 0)
177                         return;
178                 if (size > sizeof(addrs)) {
179                         bytes = size - sizeof(addrs);
180                         SaveFuncs.seek(f, bytes, SEEK_CUR);
181                         size = sizeof(addrs);
182                 }
183                 bytes = SaveFuncs.read(f, addrs, size);
184                 if (bytes != size)
185                         return;
186
187                 new_dynarec_load_blocks(addrs, size);
188         }
189
190         //printf("drc: %d block info entries %s\n", size/8, mode ? "saved" : "loaded");
191 }
192
193 #ifndef DRC_DISABLE
194
195 /* GTE stuff */
196 void *gte_handlers[64];
197
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
207 };
208
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
218 };
219
220 /* from gte.txt.. not sure if this is any good. */
221 const char gte_cycletab[64] = {
222         /*   1   2   3   4   5   6   7   8   9   a   b   c   d   e   f */
223          0, 15,  0,  0,  0,  0,  8,  0,  0,  0,  0,  0,  6,  0,  0,  0,
224          8,  8,  8, 19, 13,  0, 44,  0,  0,  0,  0, 17, 11,  0, 14,  0,
225         30,  0,  0,  0,  0,  0,  0,  0,  5,  8, 17,  0,  0,  5,  6,  0,
226         23,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  5,  5, 39,
227 };
228
229 #define GCBIT(x) \
230         (1ll << (32+x))
231 #define GDBIT(x) \
232         (1ll << (x))
233 #define GCBITS3(b0,b1,b2) \
234         (GCBIT(b0) | GCBIT(b1) | GCBIT(b2))
235 #define GDBITS2(b0,b1) \
236         (GDBIT(b0) | GDBIT(b1))
237 #define GDBITS3(b0,b1,b2) \
238         (GDBITS2(b0,b1) | GDBIT(b2))
239 #define GDBITS4(b0,b1,b2,b3) \
240         (GDBITS3(b0,b1,b2) | GDBIT(b3))
241 #define GDBITS5(b0,b1,b2,b3,b4) \
242         (GDBITS4(b0,b1,b2,b3) | GDBIT(b4))
243 #define GDBITS6(b0,b1,b2,b3,b4,b5) \
244         (GDBITS5(b0,b1,b2,b3,b4) | GDBIT(b5))
245 #define GDBITS7(b0,b1,b2,b3,b4,b5,b6) \
246         (GDBITS6(b0,b1,b2,b3,b4,b5) | GDBIT(b6))
247 #define GDBITS8(b0,b1,b2,b3,b4,b5,b6,b7) \
248         (GDBITS7(b0,b1,b2,b3,b4,b5,b6) | GDBIT(b7))
249 #define GDBITS9(b0,b1,b2,b3,b4,b5,b6,b7,b8) \
250         (GDBITS8(b0,b1,b2,b3,b4,b5,b6,b7) | GDBIT(b8))
251 #define GDBITS10(b0,b1,b2,b3,b4,b5,b6,b7,b8,b9) \
252         (GDBITS9(b0,b1,b2,b3,b4,b5,b6,b7,b8) | GDBIT(b9))
253
254 const uint64_t gte_reg_reads[64] = {
255         [GTE_RTPS]  = 0x1f0000ff00000000ll | GDBITS7(0,1,13,14,17,18,19),
256         [GTE_NCLIP] =                        GDBITS3(12,13,14),
257         [GTE_OP]    = GCBITS3(0,2,4)       | GDBITS3(9,10,11),
258         [GTE_DPCS]  = GCBITS3(21,22,23)    | GDBITS4(6,8,21,22),
259         [GTE_INTPL] = GCBITS3(21,22,23)    | GDBITS7(6,8,9,10,11,21,22),
260         [GTE_MVMVA] = 0x00ffffff00000000ll | GDBITS9(0,1,2,3,4,5,9,10,11), // XXX: maybe decode further?
261         [GTE_NCDS]  = 0x00ffff0000000000ll | GDBITS6(0,1,6,8,21,22),
262         [GTE_CDP]   = 0x00ffe00000000000ll | GDBITS7(6,8,9,10,11,21,22),
263         [GTE_NCDT]  = 0x00ffff0000000000ll | GDBITS8(0,1,2,3,4,5,6,8),
264         [GTE_NCCS]  = 0x001fff0000000000ll | GDBITS5(0,1,6,21,22),
265         [GTE_CC]    = 0x001fe00000000000ll | GDBITS6(6,9,10,11,21,22),
266         [GTE_NCS]   = 0x001fff0000000000ll | GDBITS5(0,1,6,21,22),
267         [GTE_NCT]   = 0x001fff0000000000ll | GDBITS7(0,1,2,3,4,5,6),
268         [GTE_SQR]   =                        GDBITS3(9,10,11),
269         [GTE_DCPL]  = GCBITS3(21,22,23)    | GDBITS7(6,8,9,10,11,21,22),
270         [GTE_DPCT]  = GCBITS3(21,22,23)    | GDBITS4(8,20,21,22),
271         [GTE_AVSZ3] = GCBIT(29)            | GDBITS3(17,18,19),
272         [GTE_AVSZ4] = GCBIT(30)            | GDBITS4(16,17,18,19),
273         [GTE_RTPT]  = 0x1f0000ff00000000ll | GDBITS7(0,1,2,3,4,5,19),
274         [GTE_GPF]   =                        GDBITS7(6,8,9,10,11,21,22),
275         [GTE_GPL]   =                        GDBITS10(6,8,9,10,11,21,22,25,26,27),
276         [GTE_NCCT]  = 0x001fff0000000000ll | GDBITS7(0,1,2,3,4,5,6),
277 };
278
279 // note: this excludes gteFLAG that is always written to
280 const uint64_t gte_reg_writes[64] = {
281         [GTE_RTPS]  = 0x0f0f7f00ll,
282         [GTE_NCLIP] = GDBIT(24),
283         [GTE_OP]    = GDBITS6(9,10,11,25,26,27),
284         [GTE_DPCS]  = GDBITS9(9,10,11,20,21,22,25,26,27),
285         [GTE_INTPL] = GDBITS9(9,10,11,20,21,22,25,26,27),
286         [GTE_MVMVA] = GDBITS6(9,10,11,25,26,27),
287         [GTE_NCDS]  = GDBITS9(9,10,11,20,21,22,25,26,27),
288         [GTE_CDP]   = GDBITS9(9,10,11,20,21,22,25,26,27),
289         [GTE_NCDT]  = GDBITS9(9,10,11,20,21,22,25,26,27),
290         [GTE_NCCS]  = GDBITS9(9,10,11,20,21,22,25,26,27),
291         [GTE_CC]    = GDBITS9(9,10,11,20,21,22,25,26,27),
292         [GTE_NCS]   = GDBITS9(9,10,11,20,21,22,25,26,27),
293         [GTE_NCT]   = GDBITS9(9,10,11,20,21,22,25,26,27),
294         [GTE_SQR]   = GDBITS6(9,10,11,25,26,27),
295         [GTE_DCPL]  = GDBITS9(9,10,11,20,21,22,25,26,27),
296         [GTE_DPCT]  = GDBITS9(9,10,11,20,21,22,25,26,27),
297         [GTE_AVSZ3] = GDBITS2(7,24),
298         [GTE_AVSZ4] = GDBITS2(7,24),
299         [GTE_RTPT]  = 0x0f0f7f00ll,
300         [GTE_GPF]   = GDBITS9(9,10,11,20,21,22,25,26,27),
301         [GTE_GPL]   = GDBITS9(9,10,11,20,21,22,25,26,27),
302         [GTE_NCCT]  = GDBITS9(9,10,11,20,21,22,25,26,27),
303 };
304
305 static int ari64_init()
306 {
307         static u32 scratch_buf[8*8*2] __attribute__((aligned(64)));
308         extern void (*psxCP2[64])();
309         extern void psxNULL();
310         extern unsigned char *out;
311         size_t i;
312
313         new_dynarec_init();
314         new_dyna_pcsx_mem_init();
315
316         for (i = 0; i < ARRAY_SIZE(gte_handlers); i++)
317                 if (psxCP2[i] != psxNULL)
318                         gte_handlers[i] = psxCP2[i];
319
320 #if defined(__arm__) && !defined(DRC_DBG)
321         gte_handlers[0x06] = gteNCLIP_arm;
322 #ifdef HAVE_ARMV5
323         gte_handlers_nf[0x01] = gteRTPS_nf_arm;
324         gte_handlers_nf[0x30] = gteRTPT_nf_arm;
325 #endif
326 #ifdef __ARM_NEON__
327         // compiler's _nf version is still a lot slower than neon
328         // _nf_arm RTPS is roughly the same, RTPT slower
329         gte_handlers[0x01] = gte_handlers_nf[0x01] = gteRTPS_neon;
330         gte_handlers[0x30] = gte_handlers_nf[0x30] = gteRTPT_neon;
331 #endif
332 #endif
333 #ifdef DRC_DBG
334         memcpy(gte_handlers_nf, gte_handlers, sizeof(gte_handlers_nf));
335 #endif
336         psxH_ptr = psxH;
337         zeromem_ptr = zero_mem;
338         scratch_buf_ptr = scratch_buf;
339
340         SysPrintf("Mapped (RAM/scrp/ROM/LUTs/TC):\n");
341         SysPrintf("%p/%p/%p/%p/%p\n",
342                 psxM, psxH, psxR, mem_rtab, out);
343
344         return 0;
345 }
346
347 static void ari64_reset()
348 {
349         printf("ari64_reset\n");
350         new_dyna_pcsx_mem_reset();
351         invalidate_all_pages();
352         new_dyna_restore();
353         pending_exception = 1;
354 }
355
356 // execute until predefined leave points
357 // (HLE softcall exit and BIOS fastboot end)
358 static void ari64_execute_until()
359 {
360         schedule_timeslice();
361
362         evprintf("ari64_execute %08x, %u->%u (%d)\n", psxRegs.pc,
363                 psxRegs.cycle, next_interupt, next_interupt - psxRegs.cycle);
364
365         new_dyna_start(dynarec_local);
366
367         evprintf("ari64_execute end %08x, %u->%u (%d)\n", psxRegs.pc,
368                 psxRegs.cycle, next_interupt, next_interupt - psxRegs.cycle);
369 }
370
371 static void ari64_execute()
372 {
373         while (!stop) {
374                 ari64_execute_until();
375                 evprintf("drc left @%08x\n", psxRegs.pc);
376         }
377 }
378
379 static void ari64_clear(u32 addr, u32 size)
380 {
381         u32 start, end, main_ram;
382
383         size *= 4; /* PCSX uses DMA units (words) */
384
385         evprintf("ari64_clear %08x %04x\n", addr, size);
386
387         /* check for RAM mirrors */
388         main_ram = (addr & 0xffe00000) == 0x80000000;
389
390         start = addr >> 12;
391         end = (addr + size) >> 12;
392
393         for (; start <= end; start++)
394                 if (!main_ram || !invalid_code[start])
395                         invalidate_block(start);
396 }
397
398 #ifdef ICACHE_EMULATION
399 static void ari64_notify(int note, void *data) {
400         /*
401         Should be fixed when ARM dynarec has proper icache emulation.
402         switch (note)
403         {
404                 case R3000ACPU_NOTIFY_CACHE_UNISOLATED:
405                         break;
406                 case R3000ACPU_NOTIFY_CACHE_ISOLATED:
407                 Sent from psxDma3().
408                 case R3000ACPU_NOTIFY_DMA3_EXE_LOAD:
409                 default:
410                         break;
411         }
412         */
413 }
414 #endif
415
416 static void ari64_shutdown()
417 {
418         new_dynarec_cleanup();
419         new_dyna_pcsx_mem_shutdown();
420 }
421
422 R3000Acpu psxRec = {
423         ari64_init,
424         ari64_reset,
425         ari64_execute,
426         ari64_execute_until,
427         ari64_clear,
428 #ifdef ICACHE_EMULATION
429         ari64_notify,
430 #endif
431         ari64_shutdown
432 };
433
434 #else // if DRC_DISABLE
435
436 unsigned int address;
437 int pending_exception, stop;
438 unsigned int next_interupt;
439 int new_dynarec_did_compile;
440 int cycle_multiplier;
441 int cycle_multiplier_override;
442 int new_dynarec_hacks;
443 void *psxH_ptr;
444 void *zeromem_ptr;
445 u8 zero_mem[0x1000];
446 unsigned char *out;
447 void *mem_rtab;
448 void *scratch_buf_ptr;
449 void new_dynarec_init() {}
450 void new_dyna_start(void *context) {}
451 void new_dynarec_cleanup() {}
452 void new_dynarec_clear_full() {}
453 void invalidate_all_pages() {}
454 void invalidate_block(unsigned int block) {}
455 void new_dyna_pcsx_mem_init(void) {}
456 void new_dyna_pcsx_mem_reset(void) {}
457 void new_dyna_pcsx_mem_load_state(void) {}
458 void new_dyna_pcsx_mem_shutdown(void) {}
459 int  new_dynarec_save_blocks(void *save, int size) { return 0; }
460 void new_dynarec_load_blocks(const void *save, int size) {}
461 #endif
462
463 #ifdef DRC_DBG
464
465 #include <stddef.h>
466 static FILE *f;
467 extern u32 last_io_addr;
468
469 static void dump_mem(const char *fname, void *mem, size_t size)
470 {
471         FILE *f1 = fopen(fname, "wb");
472         if (f1 == NULL)
473                 f1 = fopen(strrchr(fname, '/') + 1, "wb");
474         fwrite(mem, 1, size, f1);
475         fclose(f1);
476 }
477
478 static u32 memcheck_read(u32 a)
479 {
480         if ((a >> 16) == 0x1f80)
481                 // scratchpad/IO
482                 return *(u32 *)(psxH + (a & 0xfffc));
483
484         if ((a >> 16) == 0x1f00)
485                 // parallel
486                 return *(u32 *)(psxP + (a & 0xfffc));
487
488 //      if ((a & ~0xe0600000) < 0x200000)
489         // RAM
490         return *(u32 *)(psxM + (a & 0x1ffffc));
491 }
492
493 #if 0
494 void do_insn_trace(void)
495 {
496         static psxRegisters oldregs;
497         static u32 old_io_addr = (u32)-1;
498         static u32 old_io_data = 0xbad0c0de;
499         static u32 event_cycles_o[PSXINT_COUNT];
500         u32 *allregs_p = (void *)&psxRegs;
501         u32 *allregs_o = (void *)&oldregs;
502         u32 io_data;
503         int i;
504         u8 byte;
505
506         //last_io_addr = 0x5e2c8;
507         if (f == NULL)
508                 f = fopen("tracelog", "wb");
509
510         // log reg changes
511         oldregs.code = psxRegs.code; // don't care
512         for (i = 0; i < offsetof(psxRegisters, intCycle) / 4; i++) {
513                 if (allregs_p[i] != allregs_o[i]) {
514                         fwrite(&i, 1, 1, f);
515                         fwrite(&allregs_p[i], 1, 4, f);
516                         allregs_o[i] = allregs_p[i];
517                 }
518         }
519         // log event changes
520         for (i = 0; i < PSXINT_COUNT; i++) {
521                 if (event_cycles[i] != event_cycles_o[i]) {
522                         byte = 0xfc;
523                         fwrite(&byte, 1, 1, f);
524                         fwrite(&i, 1, 1, f);
525                         fwrite(&event_cycles[i], 1, 4, f);
526                         event_cycles_o[i] = event_cycles[i];
527                 }
528         }
529         // log last io
530         if (old_io_addr != last_io_addr) {
531                 byte = 0xfd;
532                 fwrite(&byte, 1, 1, f);
533                 fwrite(&last_io_addr, 1, 4, f);
534                 old_io_addr = last_io_addr;
535         }
536         io_data = memcheck_read(last_io_addr);
537         if (old_io_data != io_data) {
538                 byte = 0xfe;
539                 fwrite(&byte, 1, 1, f);
540                 fwrite(&io_data, 1, 4, f);
541                 old_io_data = io_data;
542         }
543         byte = 0xff;
544         fwrite(&byte, 1, 1, f);
545
546 #if 0
547         if (psxRegs.cycle == 190230) {
548                 dump_mem("/mnt/ntz/dev/pnd/tmp/psxram_i.dump", psxM, 0x200000);
549                 dump_mem("/mnt/ntz/dev/pnd/tmp/psxregs_i.dump", psxH, 0x10000);
550                 printf("dumped\n");
551                 exit(1);
552         }
553 #endif
554 }
555 #endif
556
557 static const char *regnames[offsetof(psxRegisters, intCycle) / 4] = {
558         "r0",  "r1",  "r2",  "r3",  "r4",  "r5",  "r6",  "r7",
559         "r8",  "r9",  "r10", "r11", "r12", "r13", "r14", "r15",
560         "r16", "r17", "r18", "r19", "r20", "r21", "r22", "r23",
561         "r24", "r25", "r26", "r27", "r28", "r29", "r30", "r31",
562         "lo",  "hi",
563         "C0_0",  "C0_1",  "C0_2",  "C0_3",  "C0_4",  "C0_5",  "C0_6",  "C0_7",
564         "C0_8",  "C0_9",  "C0_10", "C0_11", "C0_12", "C0_13", "C0_14", "C0_15",
565         "C0_16", "C0_17", "C0_18", "C0_19", "C0_20", "C0_21", "C0_22", "C0_23",
566         "C0_24", "C0_25", "C0_26", "C0_27", "C0_28", "C0_29", "C0_30", "C0_31",
567
568         "C2D0",  "C2D1",  "C2D2",  "C2D3",  "C2D4",  "C2D5",  "C2D6",  "C2D7",
569         "C2D8",  "C2D9",  "C2D10", "C2D11", "C2D12", "C2D13", "C2D14", "C2D15",
570         "C2D16", "C2D17", "C2D18", "C2D19", "C2D20", "C2D21", "C2D22", "C2D23",
571         "C2D24", "C2D25", "C2D26", "C2D27", "C2D28", "C2D29", "C2D30", "C2D31",
572
573         "C2C0",  "C2C1",  "C2C2",  "C2C3",  "C2C4",  "C2C5",  "C2C6",  "C2C7",
574         "C2C8",  "C2C9",  "C2C10", "C2C11", "C2C12", "C2C13", "C2C14", "C2C15",
575         "C2C16", "C2C17", "C2C18", "C2C19", "C2C20", "C2C21", "C2C22", "C2C23",
576         "C2C24", "C2C25", "C2C26", "C2C27", "C2C28", "C2C29", "C2C30", "C2C31",
577
578         "PC", "code", "cycle", "interrupt",
579 };
580
581 static struct {
582         int reg;
583         u32 val, val_expect;
584         u32 pc, cycle;
585 } miss_log[64];
586 static int miss_log_i;
587 #define miss_log_len (sizeof(miss_log)/sizeof(miss_log[0]))
588 #define miss_log_mask (miss_log_len-1)
589
590 static void miss_log_add(int reg, u32 val, u32 val_expect, u32 pc, u32 cycle)
591 {
592         miss_log[miss_log_i].reg = reg;
593         miss_log[miss_log_i].val = val;
594         miss_log[miss_log_i].val_expect = val_expect;
595         miss_log[miss_log_i].pc = pc;
596         miss_log[miss_log_i].cycle = cycle;
597         miss_log_i = (miss_log_i + 1) & miss_log_mask;
598 }
599
600 void breakme() {}
601
602 void do_insn_cmp(void)
603 {
604         static psxRegisters rregs;
605         static u32 mem_addr, mem_val;
606         u32 *allregs_p = (void *)&psxRegs;
607         u32 *allregs_e = (void *)&rregs;
608         static u32 ppc, failcount;
609         int i, ret, bad = 0, which_event = -1;
610         u32 ev_cycles = 0;
611         u8 code;
612
613         if (f == NULL)
614                 f = fopen("tracelog", "rb");
615
616         while (1) {
617                 if ((ret = fread(&code, 1, 1, f)) <= 0)
618                         break;
619                 if (ret <= 0)
620                         break;
621                 if (code == 0xff)
622                         break;
623                 switch (code) {
624                 case 0xfc:
625                         which_event = 0;
626                         fread(&which_event, 1, 1, f);
627                         fread(&ev_cycles, 1, 4, f);
628                         continue;
629                 case 0xfd:
630                         fread(&mem_addr, 1, 4, f);
631                         continue;
632                 case 0xfe:
633                         fread(&mem_val, 1, 4, f);
634                         continue;
635                 }
636                 fread(&allregs_e[code], 1, 4, f);
637         }
638
639         if (ret <= 0) {
640                 printf("EOF?\n");
641                 goto end;
642         }
643
644         psxRegs.code = rregs.code; // don't care
645         psxRegs.cycle = rregs.cycle;
646         psxRegs.CP0.r[9] = rregs.CP0.r[9]; // Count
647
648         //if (psxRegs.cycle == 166172) breakme();
649
650         if (memcmp(&psxRegs, &rregs, offsetof(psxRegisters, intCycle)) == 0 &&
651                         mem_val == memcheck_read(mem_addr)
652            ) {
653                 failcount = 0;
654                 goto ok;
655         }
656
657         for (i = 0; i < offsetof(psxRegisters, intCycle) / 4; i++) {
658                 if (allregs_p[i] != allregs_e[i]) {
659                         miss_log_add(i, allregs_p[i], allregs_e[i], psxRegs.pc, psxRegs.cycle);
660                         bad++;
661                         if (i > 32+2)
662                                 goto end;
663                 }
664         }
665
666         if (mem_val != memcheck_read(mem_addr)) {
667                 printf("bad mem @%08x: %08x %08x\n", mem_addr, memcheck_read(mem_addr), mem_val);
668                 goto end;
669         }
670
671         if (which_event >= 0 && event_cycles[which_event] != ev_cycles) {
672                 printf("bad ev_cycles #%d: %08x %08x\n", which_event, event_cycles[which_event], ev_cycles);
673                 goto end;
674         }
675
676         if (psxRegs.pc == rregs.pc && bad < 6 && failcount < 32) {
677                 static int last_mcycle;
678                 if (last_mcycle != psxRegs.cycle >> 20) {
679                         printf("%u\n", psxRegs.cycle);
680                         last_mcycle = psxRegs.cycle >> 20;
681                 }
682                 failcount++;
683                 goto ok;
684         }
685
686 end:
687         for (i = 0; i < miss_log_len; i++, miss_log_i = (miss_log_i + 1) & miss_log_mask)
688                 printf("bad %5s: %08x %08x, pc=%08x, cycle %u\n",
689                         regnames[miss_log[miss_log_i].reg], miss_log[miss_log_i].val,
690                         miss_log[miss_log_i].val_expect, miss_log[miss_log_i].pc, miss_log[miss_log_i].cycle);
691         printf("-- %d\n", bad);
692         for (i = 0; i < 8; i++)
693                 printf("r%d=%08x r%2d=%08x r%2d=%08x r%2d=%08x\n", i, allregs_p[i],
694                         i+8, allregs_p[i+8], i+16, allregs_p[i+16], i+24, allregs_p[i+24]);
695         printf("PC: %08x/%08x, cycle %u\n", psxRegs.pc, ppc, psxRegs.cycle);
696         dump_mem("/mnt/ntz/dev/pnd/tmp/psxram.dump", psxM, 0x200000);
697         dump_mem("/mnt/ntz/dev/pnd/tmp/psxregs.dump", psxH, 0x10000);
698         exit(1);
699 ok:
700         psxRegs.cycle = rregs.cycle + 2; // sync timing
701         ppc = psxRegs.pc;
702 }
703
704 #endif