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