drc: don't cache psxRegs.interrupt
[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 "../psxinterpreter.h"
14 #include "../r3000a.h"
15 #include "../cdrom.h"
16 #include "../psxdma.h"
17 #include "../mdec.h"
18 #include "../gte_arm.h"
19 #include "../gte_neon.h"
20 #define FLAGLESS
21 #include "../gte.h"
22
23 #define ARRAY_SIZE(x) (sizeof(x) / sizeof(x[0]))
24
25 //#define evprintf printf
26 #define evprintf(...)
27
28 char invalid_code[0x100000];
29 u32 event_cycles[PSXINT_COUNT];
30
31 static void schedule_timeslice(void)
32 {
33         u32 i, c = psxRegs.cycle;
34         u32 irqs = psxRegs.interrupt;
35         s32 min, dif;
36
37         min = PSXCLK;
38         for (i = 0; irqs != 0; i++, irqs >>= 1) {
39                 if (!(irqs & 1))
40                         continue;
41                 dif = event_cycles[i] - c;
42                 //evprintf("  ev %d\n", dif);
43                 if (0 < dif && dif < min)
44                         min = dif;
45         }
46         next_interupt = c + min;
47 }
48
49 typedef void (irq_func)();
50
51 static irq_func * const irq_funcs[] = {
52         [PSXINT_SIO]    = sioInterrupt,
53         [PSXINT_CDR]    = cdrInterrupt,
54         [PSXINT_CDREAD] = cdrReadInterrupt,
55         [PSXINT_GPUDMA] = gpuInterrupt,
56         [PSXINT_MDECOUTDMA] = mdec1Interrupt,
57         [PSXINT_SPUDMA] = spuInterrupt,
58         [PSXINT_MDECINDMA] = mdec0Interrupt,
59         [PSXINT_GPUOTCDMA] = gpuotcInterrupt,
60         [PSXINT_CDRDMA] = cdrDmaInterrupt,
61         [PSXINT_CDRLID] = cdrLidSeekInterrupt,
62         [PSXINT_CDRPLAY] = cdrPlayInterrupt,
63         [PSXINT_SPU_UPDATE] = spuUpdate,
64         [PSXINT_RCNT] = psxRcntUpdate,
65 };
66
67 /* local dupe of psxBranchTest, using event_cycles */
68 static void irq_test(void)
69 {
70         u32 cycle = psxRegs.cycle;
71         u32 irq, irq_bits;
72
73         for (irq = 0, irq_bits = psxRegs.interrupt; irq_bits != 0; irq++, irq_bits >>= 1) {
74                 if (!(irq_bits & 1))
75                         continue;
76                 if ((s32)(cycle - event_cycles[irq]) >= 0) {
77                         // note: irq_funcs() also modify psxRegs.interrupt
78                         psxRegs.interrupt &= ~(1u << irq);
79                         irq_funcs[irq]();
80                 }
81         }
82
83         if ((psxHu32(0x1070) & psxHu32(0x1074)) && (Status & 0x401) == 0x401) {
84                 psxException(0x400, 0);
85                 pending_exception = 1;
86         }
87 }
88
89 void gen_interupt()
90 {
91         evprintf("  +ge %08x, %u->%u\n", psxRegs.pc, psxRegs.cycle, next_interupt);
92
93         irq_test();
94         //psxBranchTest();
95         //pending_exception = 1;
96
97         schedule_timeslice();
98
99         evprintf("  -ge %08x, %u->%u (%d)\n", psxRegs.pc, psxRegs.cycle,
100                 next_interupt, next_interupt - psxRegs.cycle);
101 }
102
103 // from interpreter
104 extern void MTC0(int reg, u32 val);
105
106 void pcsx_mtc0(u32 reg, u32 val)
107 {
108         evprintf("MTC0 %d #%x @%08x %u\n", reg, val, psxRegs.pc, psxRegs.cycle);
109         MTC0(reg, val);
110         gen_interupt();
111         if (Cause & Status & 0x0300) // possible sw irq
112                 pending_exception = 1;
113 }
114
115 void pcsx_mtc0_ds(u32 reg, u32 val)
116 {
117         evprintf("MTC0 %d #%x @%08x %u\n", reg, val, psxRegs.pc, psxRegs.cycle);
118         MTC0(reg, val);
119 }
120
121 void new_dyna_before_save(void)
122 {
123         psxRegs.interrupt &= ~(1 << PSXINT_RCNT); // old savestate compat
124
125         // psxRegs.intCycle is always maintained, no need to convert
126 }
127
128 void new_dyna_after_save(void)
129 {
130         psxRegs.interrupt |= 1 << PSXINT_RCNT;
131 }
132
133 static void new_dyna_restore(void)
134 {
135         int i;
136         for (i = 0; i < PSXINT_COUNT; i++)
137                 event_cycles[i] = psxRegs.intCycle[i].sCycle + psxRegs.intCycle[i].cycle;
138
139         event_cycles[PSXINT_RCNT] = psxNextsCounter + psxNextCounter;
140         psxRegs.interrupt |=  1 << PSXINT_RCNT;
141         psxRegs.interrupt &= (1 << PSXINT_COUNT) - 1;
142
143         new_dyna_pcsx_mem_load_state();
144 }
145
146 void new_dyna_freeze(void *f, int mode)
147 {
148         const char header_save[8] = "ariblks";
149         uint32_t addrs[1024 * 4];
150         int32_t size = 0;
151         int bytes;
152         char header[8];
153
154         if (mode != 0) { // save
155                 size = new_dynarec_save_blocks(addrs, sizeof(addrs));
156                 if (size == 0)
157                         return;
158
159                 SaveFuncs.write(f, header_save, sizeof(header_save));
160                 SaveFuncs.write(f, &size, sizeof(size));
161                 SaveFuncs.write(f, addrs, size);
162         }
163         else {
164                 new_dyna_restore();
165
166                 bytes = SaveFuncs.read(f, header, sizeof(header));
167                 if (bytes != sizeof(header) || strcmp(header, header_save)) {
168                         if (bytes > 0)
169                                 SaveFuncs.seek(f, -bytes, SEEK_CUR);
170                         return;
171                 }
172                 SaveFuncs.read(f, &size, sizeof(size));
173                 if (size <= 0)
174                         return;
175                 if (size > sizeof(addrs)) {
176                         bytes = size - sizeof(addrs);
177                         SaveFuncs.seek(f, bytes, SEEK_CUR);
178                         size = sizeof(addrs);
179                 }
180                 bytes = SaveFuncs.read(f, addrs, size);
181                 if (bytes != size)
182                         return;
183
184                 if (psxCpu != &psxInt)
185                         new_dynarec_load_blocks(addrs, size);
186         }
187
188         //printf("drc: %d block info entries %s\n", size/8, mode ? "saved" : "loaded");
189 }
190
191 #ifndef DRC_DISABLE
192
193 /* GTE stuff */
194 void *gte_handlers[64];
195
196 void *gte_handlers_nf[64] = {
197         NULL      , gteRTPS_nf , NULL       , NULL      , NULL     , NULL       , gteNCLIP_nf, NULL      , // 00
198         NULL      , NULL       , NULL       , NULL      , gteOP_nf , NULL       , NULL       , NULL      , // 08
199         gteDPCS_nf, gteINTPL_nf, gteMVMVA_nf, gteNCDS_nf, gteCDP_nf, NULL       , gteNCDT_nf , NULL      , // 10
200         NULL      , NULL       , NULL       , gteNCCS_nf, gteCC_nf , NULL       , gteNCS_nf  , NULL      , // 18
201         gteNCT_nf , NULL       , NULL       , NULL      , NULL     , NULL       , NULL       , NULL      , // 20
202         gteSQR_nf , gteDCPL_nf , gteDPCT_nf , NULL      , NULL     , gteAVSZ3_nf, gteAVSZ4_nf, NULL      , // 28 
203         gteRTPT_nf, NULL       , NULL       , NULL      , NULL     , NULL       , NULL       , NULL      , // 30
204         NULL      , NULL       , NULL       , NULL      , NULL     , gteGPF_nf  , gteGPL_nf  , gteNCCT_nf, // 38
205 };
206
207 const char *gte_regnames[64] = {
208         NULL  , "RTPS" , NULL   , NULL  , NULL , NULL   , "NCLIP", NULL  , // 00
209         NULL  , NULL   , NULL   , NULL  , "OP" , NULL   , NULL   , NULL  , // 08
210         "DPCS", "INTPL", "MVMVA", "NCDS", "CDP", NULL   , "NCDT" , NULL  , // 10
211         NULL  , NULL   , NULL   , "NCCS", "CC" , NULL   , "NCS"  , NULL  , // 18
212         "NCT" , NULL   , NULL   , NULL  , NULL , NULL   , NULL   , NULL  , // 20
213         "SQR" , "DCPL" , "DPCT" , NULL  , NULL , "AVSZ3", "AVSZ4", NULL  , // 28 
214         "RTPT", NULL   , NULL   , NULL  , NULL , NULL   , NULL   , NULL  , // 30
215         NULL  , NULL   , NULL   , NULL  , NULL , "GPF"  , "GPL"  , "NCCT", // 38
216 };
217
218 #define GCBIT(x) \
219         (1ll << (32+x))
220 #define GDBIT(x) \
221         (1ll << (x))
222 #define GCBITS3(b0,b1,b2) \
223         (GCBIT(b0) | GCBIT(b1) | GCBIT(b2))
224 #define GDBITS2(b0,b1) \
225         (GDBIT(b0) | GDBIT(b1))
226 #define GDBITS3(b0,b1,b2) \
227         (GDBITS2(b0,b1) | GDBIT(b2))
228 #define GDBITS4(b0,b1,b2,b3) \
229         (GDBITS3(b0,b1,b2) | GDBIT(b3))
230 #define GDBITS5(b0,b1,b2,b3,b4) \
231         (GDBITS4(b0,b1,b2,b3) | GDBIT(b4))
232 #define GDBITS6(b0,b1,b2,b3,b4,b5) \
233         (GDBITS5(b0,b1,b2,b3,b4) | GDBIT(b5))
234 #define GDBITS7(b0,b1,b2,b3,b4,b5,b6) \
235         (GDBITS6(b0,b1,b2,b3,b4,b5) | GDBIT(b6))
236 #define GDBITS8(b0,b1,b2,b3,b4,b5,b6,b7) \
237         (GDBITS7(b0,b1,b2,b3,b4,b5,b6) | GDBIT(b7))
238 #define GDBITS9(b0,b1,b2,b3,b4,b5,b6,b7,b8) \
239         (GDBITS8(b0,b1,b2,b3,b4,b5,b6,b7) | GDBIT(b8))
240 #define GDBITS10(b0,b1,b2,b3,b4,b5,b6,b7,b8,b9) \
241         (GDBITS9(b0,b1,b2,b3,b4,b5,b6,b7,b8) | GDBIT(b9))
242
243 const uint64_t gte_reg_reads[64] = {
244         [GTE_RTPS]  = 0x1f0000ff00000000ll | GDBITS7(0,1,13,14,17,18,19),
245         [GTE_NCLIP] =                        GDBITS3(12,13,14),
246         [GTE_OP]    = GCBITS3(0,2,4)       | GDBITS3(9,10,11),
247         [GTE_DPCS]  = GCBITS3(21,22,23)    | GDBITS4(6,8,21,22),
248         [GTE_INTPL] = GCBITS3(21,22,23)    | GDBITS7(6,8,9,10,11,21,22),
249         [GTE_MVMVA] = 0x00ffffff00000000ll | GDBITS9(0,1,2,3,4,5,9,10,11), // XXX: maybe decode further?
250         [GTE_NCDS]  = 0x00ffff0000000000ll | GDBITS6(0,1,6,8,21,22),
251         [GTE_CDP]   = 0x00ffe00000000000ll | GDBITS7(6,8,9,10,11,21,22),
252         [GTE_NCDT]  = 0x00ffff0000000000ll | GDBITS8(0,1,2,3,4,5,6,8),
253         [GTE_NCCS]  = 0x001fff0000000000ll | GDBITS5(0,1,6,21,22),
254         [GTE_CC]    = 0x001fe00000000000ll | GDBITS6(6,9,10,11,21,22),
255         [GTE_NCS]   = 0x001fff0000000000ll | GDBITS5(0,1,6,21,22),
256         [GTE_NCT]   = 0x001fff0000000000ll | GDBITS7(0,1,2,3,4,5,6),
257         [GTE_SQR]   =                        GDBITS3(9,10,11),
258         [GTE_DCPL]  = GCBITS3(21,22,23)    | GDBITS7(6,8,9,10,11,21,22),
259         [GTE_DPCT]  = GCBITS3(21,22,23)    | GDBITS4(8,20,21,22),
260         [GTE_AVSZ3] = GCBIT(29)            | GDBITS3(17,18,19),
261         [GTE_AVSZ4] = GCBIT(30)            | GDBITS4(16,17,18,19),
262         [GTE_RTPT]  = 0x1f0000ff00000000ll | GDBITS7(0,1,2,3,4,5,19),
263         [GTE_GPF]   =                        GDBITS7(6,8,9,10,11,21,22),
264         [GTE_GPL]   =                        GDBITS10(6,8,9,10,11,21,22,25,26,27),
265         [GTE_NCCT]  = 0x001fff0000000000ll | GDBITS7(0,1,2,3,4,5,6),
266 };
267
268 // note: this excludes gteFLAG that is always written to
269 const uint64_t gte_reg_writes[64] = {
270         [GTE_RTPS]  = 0x0f0f7f00ll,
271         [GTE_NCLIP] = GDBIT(24),
272         [GTE_OP]    = GDBITS6(9,10,11,25,26,27),
273         [GTE_DPCS]  = GDBITS9(9,10,11,20,21,22,25,26,27),
274         [GTE_INTPL] = GDBITS9(9,10,11,20,21,22,25,26,27),
275         [GTE_MVMVA] = GDBITS6(9,10,11,25,26,27),
276         [GTE_NCDS]  = GDBITS9(9,10,11,20,21,22,25,26,27),
277         [GTE_CDP]   = GDBITS9(9,10,11,20,21,22,25,26,27),
278         [GTE_NCDT]  = GDBITS9(9,10,11,20,21,22,25,26,27),
279         [GTE_NCCS]  = GDBITS9(9,10,11,20,21,22,25,26,27),
280         [GTE_CC]    = GDBITS9(9,10,11,20,21,22,25,26,27),
281         [GTE_NCS]   = GDBITS9(9,10,11,20,21,22,25,26,27),
282         [GTE_NCT]   = GDBITS9(9,10,11,20,21,22,25,26,27),
283         [GTE_SQR]   = GDBITS6(9,10,11,25,26,27),
284         [GTE_DCPL]  = GDBITS9(9,10,11,20,21,22,25,26,27),
285         [GTE_DPCT]  = GDBITS9(9,10,11,20,21,22,25,26,27),
286         [GTE_AVSZ3] = GDBITS2(7,24),
287         [GTE_AVSZ4] = GDBITS2(7,24),
288         [GTE_RTPT]  = 0x0f0f7f00ll,
289         [GTE_GPF]   = GDBITS9(9,10,11,20,21,22,25,26,27),
290         [GTE_GPL]   = GDBITS9(9,10,11,20,21,22,25,26,27),
291         [GTE_NCCT]  = GDBITS9(9,10,11,20,21,22,25,26,27),
292 };
293
294 static int ari64_init()
295 {
296         static u32 scratch_buf[8*8*2] __attribute__((aligned(64)));
297         extern void (*psxCP2[64])();
298         extern void psxNULL();
299         extern unsigned char *out;
300         size_t i;
301
302         new_dynarec_init();
303         new_dyna_pcsx_mem_init();
304
305         for (i = 0; i < ARRAY_SIZE(gte_handlers); i++)
306                 if (psxCP2[i] != psxNULL)
307                         gte_handlers[i] = psxCP2[i];
308
309 #if defined(__arm__) && !defined(DRC_DBG)
310         gte_handlers[0x06] = gteNCLIP_arm;
311 #ifdef HAVE_ARMV5
312         gte_handlers_nf[0x01] = gteRTPS_nf_arm;
313         gte_handlers_nf[0x30] = gteRTPT_nf_arm;
314 #endif
315 #ifdef __ARM_NEON__
316         // compiler's _nf version is still a lot slower than neon
317         // _nf_arm RTPS is roughly the same, RTPT slower
318         gte_handlers[0x01] = gte_handlers_nf[0x01] = gteRTPS_neon;
319         gte_handlers[0x30] = gte_handlers_nf[0x30] = gteRTPT_neon;
320 #endif
321 #endif
322 #ifdef DRC_DBG
323         memcpy(gte_handlers_nf, gte_handlers, sizeof(gte_handlers_nf));
324 #endif
325         psxH_ptr = psxH;
326         zeromem_ptr = zero_mem;
327         scratch_buf_ptr = scratch_buf;
328
329         SysPrintf("Mapped (RAM/scrp/ROM/LUTs/TC):\n");
330         SysPrintf("%p/%p/%p/%p/%p\n",
331                 psxM, psxH, psxR, mem_rtab, out);
332
333         return 0;
334 }
335
336 static void ari64_reset()
337 {
338         printf("ari64_reset\n");
339         new_dyna_pcsx_mem_reset();
340         invalidate_all_pages();
341         new_dyna_restore();
342         pending_exception = 1;
343 }
344
345 // execute until predefined leave points
346 // (HLE softcall exit and BIOS fastboot end)
347 static void ari64_execute_until()
348 {
349         schedule_timeslice();
350
351         evprintf("ari64_execute %08x, %u->%u (%d)\n", psxRegs.pc,
352                 psxRegs.cycle, next_interupt, next_interupt - psxRegs.cycle);
353
354         new_dyna_start(dynarec_local);
355
356         evprintf("ari64_execute end %08x, %u->%u (%d)\n", psxRegs.pc,
357                 psxRegs.cycle, next_interupt, next_interupt - psxRegs.cycle);
358 }
359
360 static void ari64_execute()
361 {
362         while (!stop) {
363                 ari64_execute_until();
364                 evprintf("drc left @%08x\n", psxRegs.pc);
365         }
366 }
367
368 static void ari64_clear(u32 addr, u32 size)
369 {
370         u32 start, end, main_ram;
371
372         size *= 4; /* PCSX uses DMA units (words) */
373
374         evprintf("ari64_clear %08x %04x\n", addr, size);
375
376         /* check for RAM mirrors */
377         main_ram = (addr & 0xffe00000) == 0x80000000;
378
379         start = addr >> 12;
380         end = (addr + size) >> 12;
381
382         for (; start <= end; start++)
383                 if (!main_ram || !invalid_code[start])
384                         invalidate_block(start);
385 }
386
387 static void ari64_notify(int note, void *data) {
388         /*
389         Should be fixed when ARM dynarec has proper icache emulation.
390         switch (note)
391         {
392                 case R3000ACPU_NOTIFY_CACHE_UNISOLATED:
393                         break;
394                 case R3000ACPU_NOTIFY_CACHE_ISOLATED:
395                 Sent from psxDma3().
396                 case R3000ACPU_NOTIFY_DMA3_EXE_LOAD:
397                 default:
398                         break;
399         }
400         */
401 }
402
403 static void ari64_apply_config()
404 {
405         intApplyConfig();
406
407         if (Config.DisableStalls)
408                 new_dynarec_hacks |= NDHACK_NO_STALLS;
409         else
410                 new_dynarec_hacks &= ~NDHACK_NO_STALLS;
411
412         if (cycle_multiplier != cycle_multiplier_old
413             || new_dynarec_hacks != new_dynarec_hacks_old)
414         {
415                 new_dynarec_clear_full();
416         }
417 }
418
419 static void ari64_shutdown()
420 {
421         new_dynarec_cleanup();
422         new_dyna_pcsx_mem_shutdown();
423 }
424
425 R3000Acpu psxRec = {
426         ari64_init,
427         ari64_reset,
428         ari64_execute,
429         ari64_execute_until,
430         ari64_clear,
431         ari64_notify,
432         ari64_apply_config,
433         ari64_shutdown
434 };
435
436 #else // if DRC_DISABLE
437
438 unsigned int address;
439 int pending_exception, stop;
440 unsigned int next_interupt;
441 int new_dynarec_did_compile;
442 int cycle_multiplier;
443 int cycle_multiplier_override;
444 int cycle_multiplier_old;
445 int new_dynarec_hacks_pergame;
446 int new_dynarec_hacks_old;
447 int new_dynarec_hacks;
448 void *psxH_ptr;
449 void *zeromem_ptr;
450 u8 zero_mem[0x1000];
451 unsigned char *out;
452 void *mem_rtab;
453 void *scratch_buf_ptr;
454 void new_dynarec_init() {}
455 void new_dyna_start(void *context) {}
456 void new_dynarec_cleanup() {}
457 void new_dynarec_clear_full() {}
458 void invalidate_all_pages() {}
459 void invalidate_block(unsigned int block) {}
460 void new_dyna_pcsx_mem_init(void) {}
461 void new_dyna_pcsx_mem_reset(void) {}
462 void new_dyna_pcsx_mem_load_state(void) {}
463 void new_dyna_pcsx_mem_shutdown(void) {}
464 int  new_dynarec_save_blocks(void *save, int size) { return 0; }
465 void new_dynarec_load_blocks(const void *save, int size) {}
466 #endif
467
468 #ifdef DRC_DBG
469
470 #include <stddef.h>
471 static FILE *f;
472 u32 irq_test_cycle;
473 u32 handler_cycle;
474 u32 last_io_addr;
475
476 void dump_mem(const char *fname, void *mem, size_t size)
477 {
478         FILE *f1 = fopen(fname, "wb");
479         if (f1 == NULL)
480                 f1 = fopen(strrchr(fname, '/') + 1, "wb");
481         fwrite(mem, 1, size, f1);
482         fclose(f1);
483 }
484
485 static u32 memcheck_read(u32 a)
486 {
487         if ((a >> 16) == 0x1f80)
488                 // scratchpad/IO
489                 return *(u32 *)(psxH + (a & 0xfffc));
490
491         if ((a >> 16) == 0x1f00)
492                 // parallel
493                 return *(u32 *)(psxP + (a & 0xfffc));
494
495 //      if ((a & ~0xe0600000) < 0x200000)
496         // RAM
497         return *(u32 *)(psxM + (a & 0x1ffffc));
498 }
499
500 #if 0
501 void do_insn_trace(void)
502 {
503         static psxRegisters oldregs;
504         static u32 event_cycles_o[PSXINT_COUNT];
505         u32 *allregs_p = (void *)&psxRegs;
506         u32 *allregs_o = (void *)&oldregs;
507         u32 io_data;
508         int i;
509         u8 byte;
510
511         //last_io_addr = 0x5e2c8;
512         if (f == NULL)
513                 f = fopen("tracelog", "wb");
514
515         // log reg changes
516         oldregs.code = psxRegs.code; // don't care
517         for (i = 0; i < offsetof(psxRegisters, intCycle) / 4; i++) {
518                 if (allregs_p[i] != allregs_o[i]) {
519                         fwrite(&i, 1, 1, f);
520                         fwrite(&allregs_p[i], 1, 4, f);
521                         allregs_o[i] = allregs_p[i];
522                 }
523         }
524         // log event changes
525         for (i = 0; i < PSXINT_COUNT; i++) {
526                 if (event_cycles[i] != event_cycles_o[i]) {
527                         byte = 0xf8;
528                         fwrite(&byte, 1, 1, f);
529                         fwrite(&i, 1, 1, f);
530                         fwrite(&event_cycles[i], 1, 4, f);
531                         event_cycles_o[i] = event_cycles[i];
532                 }
533         }
534         #define SAVE_IF_CHANGED(code_, name_) { \
535                 static u32 old_##name_ = 0xbad0c0de; \
536                 if (old_##name_ != name_) { \
537                         byte = code_; \
538                         fwrite(&byte, 1, 1, f); \
539                         fwrite(&name_, 1, 4, f); \
540                         old_##name_ = name_; \
541                 } \
542         }
543         SAVE_IF_CHANGED(0xfb, irq_test_cycle);
544         SAVE_IF_CHANGED(0xfc, handler_cycle);
545         SAVE_IF_CHANGED(0xfd, last_io_addr);
546         io_data = memcheck_read(last_io_addr);
547         SAVE_IF_CHANGED(0xfe, io_data);
548         byte = 0xff;
549         fwrite(&byte, 1, 1, f);
550
551 #if 0
552         if (psxRegs.cycle == 190230) {
553                 dump_mem("/mnt/ntz/dev/pnd/tmp/psxram_i.dump", psxM, 0x200000);
554                 dump_mem("/mnt/ntz/dev/pnd/tmp/psxregs_i.dump", psxH, 0x10000);
555                 printf("dumped\n");
556                 exit(1);
557         }
558 #endif
559 }
560 #endif
561
562 static const char *regnames[offsetof(psxRegisters, intCycle) / 4] = {
563         "r0",  "r1",  "r2",  "r3",  "r4",  "r5",  "r6",  "r7",
564         "r8",  "r9",  "r10", "r11", "r12", "r13", "r14", "r15",
565         "r16", "r17", "r18", "r19", "r20", "r21", "r22", "r23",
566         "r24", "r25", "r26", "r27", "r28", "r29", "r30", "r31",
567         "lo",  "hi",
568         "C0_0",  "C0_1",  "C0_2",  "C0_3",  "C0_4",  "C0_5",  "C0_6",  "C0_7",
569         "C0_8",  "C0_9",  "C0_10", "C0_11", "C0_12", "C0_13", "C0_14", "C0_15",
570         "C0_16", "C0_17", "C0_18", "C0_19", "C0_20", "C0_21", "C0_22", "C0_23",
571         "C0_24", "C0_25", "C0_26", "C0_27", "C0_28", "C0_29", "C0_30", "C0_31",
572
573         "C2D0",  "C2D1",  "C2D2",  "C2D3",  "C2D4",  "C2D5",  "C2D6",  "C2D7",
574         "C2D8",  "C2D9",  "C2D10", "C2D11", "C2D12", "C2D13", "C2D14", "C2D15",
575         "C2D16", "C2D17", "C2D18", "C2D19", "C2D20", "C2D21", "C2D22", "C2D23",
576         "C2D24", "C2D25", "C2D26", "C2D27", "C2D28", "C2D29", "C2D30", "C2D31",
577
578         "C2C0",  "C2C1",  "C2C2",  "C2C3",  "C2C4",  "C2C5",  "C2C6",  "C2C7",
579         "C2C8",  "C2C9",  "C2C10", "C2C11", "C2C12", "C2C13", "C2C14", "C2C15",
580         "C2C16", "C2C17", "C2C18", "C2C19", "C2C20", "C2C21", "C2C22", "C2C23",
581         "C2C24", "C2C25", "C2C26", "C2C27", "C2C28", "C2C29", "C2C30", "C2C31",
582
583         "PC", "code", "cycle", "interrupt",
584 };
585
586 static struct {
587         int reg;
588         u32 val, val_expect;
589         u32 pc, cycle;
590 } miss_log[64];
591 static int miss_log_i;
592 #define miss_log_len (sizeof(miss_log)/sizeof(miss_log[0]))
593 #define miss_log_mask (miss_log_len-1)
594
595 static void miss_log_add(int reg, u32 val, u32 val_expect, u32 pc, u32 cycle)
596 {
597         miss_log[miss_log_i].reg = reg;
598         miss_log[miss_log_i].val = val;
599         miss_log[miss_log_i].val_expect = val_expect;
600         miss_log[miss_log_i].pc = pc;
601         miss_log[miss_log_i].cycle = cycle;
602         miss_log_i = (miss_log_i + 1) & miss_log_mask;
603 }
604
605 void breakme() {}
606
607 void do_insn_cmp(void)
608 {
609         extern int last_count;
610         static psxRegisters rregs;
611         static u32 mem_addr, mem_val;
612         static u32 irq_test_cycle_intr;
613         static u32 handler_cycle_intr;
614         u32 *allregs_p = (void *)&psxRegs;
615         u32 *allregs_e = (void *)&rregs;
616         static u32 ppc, failcount;
617         int i, ret, bad = 0, fatal = 0, which_event = -1;
618         u32 ev_cycles = 0;
619         u8 code;
620
621         if (f == NULL)
622                 f = fopen("tracelog", "rb");
623
624         while (1) {
625                 if ((ret = fread(&code, 1, 1, f)) <= 0)
626                         break;
627                 if (ret <= 0)
628                         break;
629                 if (code == 0xff)
630                         break;
631                 switch (code) {
632                 case 0xf8:
633                         which_event = 0;
634                         fread(&which_event, 1, 1, f);
635                         fread(&ev_cycles, 1, 4, f);
636                         continue;
637                 case 0xfb:
638                         fread(&irq_test_cycle_intr, 1, 4, f);
639                         continue;
640                 case 0xfc:
641                         fread(&handler_cycle_intr, 1, 4, f);
642                         continue;
643                 case 0xfd:
644                         fread(&mem_addr, 1, 4, f);
645                         continue;
646                 case 0xfe:
647                         fread(&mem_val, 1, 4, f);
648                         continue;
649                 }
650                 assert(code < offsetof(psxRegisters, intCycle) / 4);
651                 fread(&allregs_e[code], 1, 4, f);
652         }
653
654         if (ret <= 0) {
655                 printf("EOF?\n");
656                 exit(1);
657         }
658
659         psxRegs.code = rregs.code; // don't care
660         psxRegs.cycle += last_count;
661         //psxRegs.cycle = rregs.cycle; // needs reload in _cmp
662         psxRegs.CP0.r[9] = rregs.CP0.r[9]; // Count
663
664         //if (psxRegs.cycle == 166172) breakme();
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                 fatal = 1;
669         }
670
671         if (irq_test_cycle > irq_test_cycle_intr) {
672                 printf("bad irq_test_cycle: %u %u\n", irq_test_cycle, irq_test_cycle_intr);
673                 fatal = 1;
674         }
675
676         if (handler_cycle != handler_cycle_intr) {
677                 printf("bad handler_cycle: %u %u\n", handler_cycle, handler_cycle_intr);
678                 fatal = 1;
679         }
680
681         if (mem_val != memcheck_read(mem_addr)) {
682                 printf("bad mem @%08x: %08x %08x\n", mem_addr, memcheck_read(mem_addr), mem_val);
683                 fatal = 1;
684         }
685
686         if (!fatal && !memcmp(&psxRegs, &rregs, offsetof(psxRegisters, intCycle))) {
687                 failcount = 0;
688                 goto ok;
689         }
690
691         for (i = 0; i < offsetof(psxRegisters, intCycle) / 4; i++) {
692                 if (allregs_p[i] != allregs_e[i]) {
693                         miss_log_add(i, allregs_p[i], allregs_e[i], psxRegs.pc, psxRegs.cycle);
694                         bad++;
695                         if (i > 32+2)
696                                 fatal = 1;
697                 }
698         }
699
700         if (!fatal && psxRegs.pc == rregs.pc && bad < 6 && failcount < 32) {
701                 static int last_mcycle;
702                 if (last_mcycle != psxRegs.cycle >> 20) {
703                         printf("%u\n", psxRegs.cycle);
704                         last_mcycle = psxRegs.cycle >> 20;
705                 }
706                 failcount++;
707                 goto ok;
708         }
709
710         for (i = 0; i < miss_log_len; i++, miss_log_i = (miss_log_i + 1) & miss_log_mask)
711                 printf("bad %5s: %08x %08x, pc=%08x, cycle %u\n",
712                         regnames[miss_log[miss_log_i].reg], miss_log[miss_log_i].val,
713                         miss_log[miss_log_i].val_expect, miss_log[miss_log_i].pc, miss_log[miss_log_i].cycle);
714         printf("-- %d\n", bad);
715         for (i = 0; i < 8; i++)
716                 printf("r%d=%08x r%2d=%08x r%2d=%08x r%2d=%08x\n", i, allregs_p[i],
717                         i+8, allregs_p[i+8], i+16, allregs_p[i+16], i+24, allregs_p[i+24]);
718         printf("PC: %08x/%08x, cycle %u, next %u\n", psxRegs.pc, ppc, psxRegs.cycle, next_interupt);
719         //dump_mem("/tmp/psxram.dump", psxM, 0x200000);
720         //dump_mem("/mnt/ntz/dev/pnd/tmp/psxregs.dump", psxH, 0x10000);
721         exit(1);
722 ok:
723         //psxRegs.cycle = rregs.cycle + 2; // sync timing
724         ppc = psxRegs.pc;
725 }
726
727 #endif