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