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