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