drc: starting arm64 support
[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("%08x/%08x/%08x/%08x/%08x\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 new_dynarec_hacks;
442 void *psxH_ptr;
443 void *zeromem_ptr;
444 u8 zero_mem[0x1000];
445 unsigned char *out;
446 void *mem_rtab;
447 void *scratch_buf_ptr;
448 void new_dynarec_init() {}
449 void new_dyna_start(void *context) {}
450 void new_dynarec_cleanup() {}
451 void new_dynarec_clear_full() {}
452 void invalidate_all_pages() {}
453 void invalidate_block(unsigned int block) {}
454 void new_dyna_pcsx_mem_init(void) {}
455 void new_dyna_pcsx_mem_reset(void) {}
456 void new_dyna_pcsx_mem_load_state(void) {}
457 void new_dyna_pcsx_mem_shutdown(void) {}
458 int  new_dynarec_save_blocks(void *save, int size) { return 0; }
459 void new_dynarec_load_blocks(const void *save, int size) {}
460 #endif
461
462 #ifdef DRC_DBG
463
464 #include <stddef.h>
465 static FILE *f;
466 extern u32 last_io_addr;
467
468 static void dump_mem(const char *fname, void *mem, size_t size)
469 {
470         FILE *f1 = fopen(fname, "wb");
471         if (f1 == NULL)
472                 f1 = fopen(strrchr(fname, '/') + 1, "wb");
473         fwrite(mem, 1, size, f1);
474         fclose(f1);
475 }
476
477 static u32 memcheck_read(u32 a)
478 {
479         if ((a >> 16) == 0x1f80)
480                 // scratchpad/IO
481                 return *(u32 *)(psxH + (a & 0xfffc));
482
483         if ((a >> 16) == 0x1f00)
484                 // parallel
485                 return *(u32 *)(psxP + (a & 0xfffc));
486
487 //      if ((a & ~0xe0600000) < 0x200000)
488         // RAM
489         return *(u32 *)(psxM + (a & 0x1ffffc));
490 }
491
492 #if 0
493 void do_insn_trace(void)
494 {
495         static psxRegisters oldregs;
496         static u32 old_io_addr = (u32)-1;
497         static u32 old_io_data = 0xbad0c0de;
498         static u32 event_cycles_o[PSXINT_COUNT];
499         u32 *allregs_p = (void *)&psxRegs;
500         u32 *allregs_o = (void *)&oldregs;
501         u32 io_data;
502         int i;
503         u8 byte;
504
505         //last_io_addr = 0x5e2c8;
506         if (f == NULL)
507                 f = fopen("tracelog", "wb");
508
509         // log reg changes
510         oldregs.code = psxRegs.code; // don't care
511         for (i = 0; i < offsetof(psxRegisters, intCycle) / 4; i++) {
512                 if (allregs_p[i] != allregs_o[i]) {
513                         fwrite(&i, 1, 1, f);
514                         fwrite(&allregs_p[i], 1, 4, f);
515                         allregs_o[i] = allregs_p[i];
516                 }
517         }
518         // log event changes
519         for (i = 0; i < PSXINT_COUNT; i++) {
520                 if (event_cycles[i] != event_cycles_o[i]) {
521                         byte = 0xfc;
522                         fwrite(&byte, 1, 1, f);
523                         fwrite(&i, 1, 1, f);
524                         fwrite(&event_cycles[i], 1, 4, f);
525                         event_cycles_o[i] = event_cycles[i];
526                 }
527         }
528         // log last io
529         if (old_io_addr != last_io_addr) {
530                 byte = 0xfd;
531                 fwrite(&byte, 1, 1, f);
532                 fwrite(&last_io_addr, 1, 4, f);
533                 old_io_addr = last_io_addr;
534         }
535         io_data = memcheck_read(last_io_addr);
536         if (old_io_data != io_data) {
537                 byte = 0xfe;
538                 fwrite(&byte, 1, 1, f);
539                 fwrite(&io_data, 1, 4, f);
540                 old_io_data = io_data;
541         }
542         byte = 0xff;
543         fwrite(&byte, 1, 1, f);
544
545 #if 0
546         if (psxRegs.cycle == 190230) {
547                 dump_mem("/mnt/ntz/dev/pnd/tmp/psxram_i.dump", psxM, 0x200000);
548                 dump_mem("/mnt/ntz/dev/pnd/tmp/psxregs_i.dump", psxH, 0x10000);
549                 printf("dumped\n");
550                 exit(1);
551         }
552 #endif
553 }
554 #endif
555
556 static const char *regnames[offsetof(psxRegisters, intCycle) / 4] = {
557         "r0",  "r1",  "r2",  "r3",  "r4",  "r5",  "r6",  "r7",
558         "r8",  "r9",  "r10", "r11", "r12", "r13", "r14", "r15",
559         "r16", "r17", "r18", "r19", "r20", "r21", "r22", "r23",
560         "r24", "r25", "r26", "r27", "r28", "r29", "r30", "r31",
561         "lo",  "hi",
562         "C0_0",  "C0_1",  "C0_2",  "C0_3",  "C0_4",  "C0_5",  "C0_6",  "C0_7",
563         "C0_8",  "C0_9",  "C0_10", "C0_11", "C0_12", "C0_13", "C0_14", "C0_15",
564         "C0_16", "C0_17", "C0_18", "C0_19", "C0_20", "C0_21", "C0_22", "C0_23",
565         "C0_24", "C0_25", "C0_26", "C0_27", "C0_28", "C0_29", "C0_30", "C0_31",
566
567         "C2D0",  "C2D1",  "C2D2",  "C2D3",  "C2D4",  "C2D5",  "C2D6",  "C2D7",
568         "C2D8",  "C2D9",  "C2D10", "C2D11", "C2D12", "C2D13", "C2D14", "C2D15",
569         "C2D16", "C2D17", "C2D18", "C2D19", "C2D20", "C2D21", "C2D22", "C2D23",
570         "C2D24", "C2D25", "C2D26", "C2D27", "C2D28", "C2D29", "C2D30", "C2D31",
571
572         "C2C0",  "C2C1",  "C2C2",  "C2C3",  "C2C4",  "C2C5",  "C2C6",  "C2C7",
573         "C2C8",  "C2C9",  "C2C10", "C2C11", "C2C12", "C2C13", "C2C14", "C2C15",
574         "C2C16", "C2C17", "C2C18", "C2C19", "C2C20", "C2C21", "C2C22", "C2C23",
575         "C2C24", "C2C25", "C2C26", "C2C27", "C2C28", "C2C29", "C2C30", "C2C31",
576
577         "PC", "code", "cycle", "interrupt",
578 };
579
580 static struct {
581         int reg;
582         u32 val, val_expect;
583         u32 pc, cycle;
584 } miss_log[64];
585 static int miss_log_i;
586 #define miss_log_len (sizeof(miss_log)/sizeof(miss_log[0]))
587 #define miss_log_mask (miss_log_len-1)
588
589 static void miss_log_add(int reg, u32 val, u32 val_expect, u32 pc, u32 cycle)
590 {
591         miss_log[miss_log_i].reg = reg;
592         miss_log[miss_log_i].val = val;
593         miss_log[miss_log_i].val_expect = val_expect;
594         miss_log[miss_log_i].pc = pc;
595         miss_log[miss_log_i].cycle = cycle;
596         miss_log_i = (miss_log_i + 1) & miss_log_mask;
597 }
598
599 void breakme() {}
600
601 void do_insn_cmp(void)
602 {
603         static psxRegisters rregs;
604         static u32 mem_addr, mem_val;
605         u32 *allregs_p = (void *)&psxRegs;
606         u32 *allregs_e = (void *)&rregs;
607         static u32 ppc, failcount;
608         int i, ret, bad = 0, which_event = -1;
609         u32 ev_cycles = 0;
610         u8 code;
611
612         if (f == NULL)
613                 f = fopen("tracelog", "rb");
614
615         while (1) {
616                 if ((ret = fread(&code, 1, 1, f)) <= 0)
617                         break;
618                 if (ret <= 0)
619                         break;
620                 if (code == 0xff)
621                         break;
622                 switch (code) {
623                 case 0xfc:
624                         which_event = 0;
625                         fread(&which_event, 1, 1, f);
626                         fread(&ev_cycles, 1, 4, f);
627                         continue;
628                 case 0xfd:
629                         fread(&mem_addr, 1, 4, f);
630                         continue;
631                 case 0xfe:
632                         fread(&mem_val, 1, 4, f);
633                         continue;
634                 }
635                 fread(&allregs_e[code], 1, 4, f);
636         }
637
638         if (ret <= 0) {
639                 printf("EOF?\n");
640                 goto end;
641         }
642
643         psxRegs.code = rregs.code; // don't care
644         psxRegs.cycle = rregs.cycle;
645         psxRegs.CP0.r[9] = rregs.CP0.r[9]; // Count
646
647         //if (psxRegs.cycle == 166172) breakme();
648
649         if (memcmp(&psxRegs, &rregs, offsetof(psxRegisters, intCycle)) == 0 &&
650                         mem_val == memcheck_read(mem_addr)
651            ) {
652                 failcount = 0;
653                 goto ok;
654         }
655
656         for (i = 0; i < offsetof(psxRegisters, intCycle) / 4; i++) {
657                 if (allregs_p[i] != allregs_e[i]) {
658                         miss_log_add(i, allregs_p[i], allregs_e[i], psxRegs.pc, psxRegs.cycle);
659                         bad++;
660                 }
661         }
662
663         if (mem_val != memcheck_read(mem_addr)) {
664                 printf("bad mem @%08x: %08x %08x\n", mem_addr, memcheck_read(mem_addr), mem_val);
665                 goto end;
666         }
667
668         if (which_event >= 0 && event_cycles[which_event] != ev_cycles) {
669                 printf("bad ev_cycles #%d: %08x %08x\n", which_event, event_cycles[which_event], ev_cycles);
670                 goto end;
671         }
672
673         if (psxRegs.pc == rregs.pc && bad < 6 && failcount < 32) {
674                 static int last_mcycle;
675                 if (last_mcycle != psxRegs.cycle >> 20) {
676                         printf("%u\n", psxRegs.cycle);
677                         last_mcycle = psxRegs.cycle >> 20;
678                 }
679                 failcount++;
680                 goto ok;
681         }
682
683 end:
684         for (i = 0; i < miss_log_len; i++, miss_log_i = (miss_log_i + 1) & miss_log_mask)
685                 printf("bad %5s: %08x %08x, pc=%08x, cycle %u\n",
686                         regnames[miss_log[miss_log_i].reg], miss_log[miss_log_i].val,
687                         miss_log[miss_log_i].val_expect, miss_log[miss_log_i].pc, miss_log[miss_log_i].cycle);
688         printf("-- %d\n", bad);
689         for (i = 0; i < 8; i++)
690                 printf("r%d=%08x r%2d=%08x r%2d=%08x r%2d=%08x\n", i, allregs_p[i],
691                         i+8, allregs_p[i+8], i+16, allregs_p[i+16], i+24, allregs_p[i+24]);
692         printf("PC: %08x/%08x, cycle %u\n", psxRegs.pc, ppc, psxRegs.cycle);
693         dump_mem("/mnt/ntz/dev/pnd/tmp/psxram.dump", psxM, 0x200000);
694         dump_mem("/mnt/ntz/dev/pnd/tmp/psxregs.dump", psxH, 0x10000);
695         exit(1);
696 ok:
697         psxRegs.cycle = rregs.cycle + 2; // sync timing
698         ppc = psxRegs.pc;
699 }
700
701 #endif