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