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