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