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