psxinterpreter: use cycle_multiplier also
[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)) && (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 (Cause & 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 #ifndef DRC_DISABLE
194
195 /* GTE stuff */
196 void *gte_handlers[64];
197
198 void *gte_handlers_nf[64] = {
199         NULL      , gteRTPS_nf , NULL       , NULL      , NULL     , NULL       , gteNCLIP_nf, NULL      , // 00
200         NULL      , NULL       , NULL       , NULL      , gteOP_nf , NULL       , NULL       , NULL      , // 08
201         gteDPCS_nf, gteINTPL_nf, gteMVMVA_nf, gteNCDS_nf, gteCDP_nf, NULL       , gteNCDT_nf , NULL      , // 10
202         NULL      , NULL       , NULL       , gteNCCS_nf, gteCC_nf , NULL       , gteNCS_nf  , NULL      , // 18
203         gteNCT_nf , NULL       , NULL       , NULL      , NULL     , NULL       , NULL       , NULL      , // 20
204         gteSQR_nf , gteDCPL_nf , gteDPCT_nf , NULL      , NULL     , gteAVSZ3_nf, gteAVSZ4_nf, NULL      , // 28 
205         gteRTPT_nf, NULL       , NULL       , NULL      , NULL     , NULL       , NULL       , NULL      , // 30
206         NULL      , NULL       , NULL       , NULL      , NULL     , gteGPF_nf  , gteGPL_nf  , gteNCCT_nf, // 38
207 };
208
209 const char *gte_regnames[64] = {
210         NULL  , "RTPS" , NULL   , NULL  , NULL , NULL   , "NCLIP", NULL  , // 00
211         NULL  , NULL   , NULL   , NULL  , "OP" , NULL   , NULL   , NULL  , // 08
212         "DPCS", "INTPL", "MVMVA", "NCDS", "CDP", NULL   , "NCDT" , NULL  , // 10
213         NULL  , NULL   , NULL   , "NCCS", "CC" , NULL   , "NCS"  , NULL  , // 18
214         "NCT" , NULL   , NULL   , NULL  , NULL , NULL   , NULL   , NULL  , // 20
215         "SQR" , "DCPL" , "DPCT" , NULL  , NULL , "AVSZ3", "AVSZ4", NULL  , // 28 
216         "RTPT", NULL   , NULL   , NULL  , NULL , NULL   , NULL   , NULL  , // 30
217         NULL  , NULL   , NULL   , NULL  , NULL , "GPF"  , "GPL"  , "NCCT", // 38
218 };
219
220 #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         /*
374         Should be fixed when ARM dynarec has proper icache emulation.
375         switch (note)
376         {
377                 case R3000ACPU_NOTIFY_CACHE_UNISOLATED:
378                         break;
379                 case R3000ACPU_NOTIFY_CACHE_ISOLATED:
380                 Sent from psxDma3().
381                 case R3000ACPU_NOTIFY_DMA3_EXE_LOAD:
382                 default:
383                         break;
384         }
385         */
386 }
387
388 static void ari64_apply_config()
389 {
390         intApplyConfig();
391
392         if (Config.DisableStalls)
393                 new_dynarec_hacks |= NDHACK_NO_STALLS;
394         else
395                 new_dynarec_hacks &= ~NDHACK_NO_STALLS;
396
397         if (Config.cycle_multiplier != cycle_multiplier_old
398             || new_dynarec_hacks != new_dynarec_hacks_old)
399         {
400                 new_dynarec_clear_full();
401         }
402 }
403
404 static void ari64_shutdown()
405 {
406         new_dynarec_cleanup();
407         new_dyna_pcsx_mem_shutdown();
408 }
409
410 R3000Acpu psxRec = {
411         ari64_init,
412         ari64_reset,
413         ari64_execute,
414         ari64_execute_until,
415         ari64_clear,
416         ari64_notify,
417         ari64_apply_config,
418         ari64_shutdown
419 };
420
421 #else // if DRC_DISABLE
422
423 unsigned int address;
424 int pending_exception, stop;
425 unsigned int next_interupt;
426 int new_dynarec_did_compile;
427 int cycle_multiplier_old;
428 int new_dynarec_hacks_pergame;
429 int new_dynarec_hacks_old;
430 int new_dynarec_hacks;
431 void *psxH_ptr;
432 void *zeromem_ptr;
433 u8 zero_mem[0x1000];
434 void *mem_rtab;
435 void *scratch_buf_ptr;
436 void new_dynarec_init() {}
437 void new_dyna_start(void *context) {}
438 void new_dynarec_cleanup() {}
439 void new_dynarec_clear_full() {}
440 void new_dynarec_invalidate_all_pages() {}
441 void new_dynarec_invalidate_range(unsigned int start, unsigned int end) {}
442 void new_dyna_pcsx_mem_init(void) {}
443 void new_dyna_pcsx_mem_reset(void) {}
444 void new_dyna_pcsx_mem_load_state(void) {}
445 void new_dyna_pcsx_mem_shutdown(void) {}
446 int  new_dynarec_save_blocks(void *save, int size) { return 0; }
447 void new_dynarec_load_blocks(const void *save, int size) {}
448 #endif
449
450 #ifdef DRC_DBG
451
452 #include <stddef.h>
453 static FILE *f;
454 u32 irq_test_cycle;
455 u32 handler_cycle;
456 u32 last_io_addr;
457
458 void dump_mem(const char *fname, void *mem, size_t size)
459 {
460         FILE *f1 = fopen(fname, "wb");
461         if (f1 == NULL)
462                 f1 = fopen(strrchr(fname, '/') + 1, "wb");
463         fwrite(mem, 1, size, f1);
464         fclose(f1);
465 }
466
467 static u32 memcheck_read(u32 a)
468 {
469         if ((a >> 16) == 0x1f80)
470                 // scratchpad/IO
471                 return *(u32 *)(psxH + (a & 0xfffc));
472
473         if ((a >> 16) == 0x1f00)
474                 // parallel
475                 return *(u32 *)(psxP + (a & 0xfffc));
476
477 //      if ((a & ~0xe0600000) < 0x200000)
478         // RAM
479         return *(u32 *)(psxM + (a & 0x1ffffc));
480 }
481
482 #if 0
483 void do_insn_trace(void)
484 {
485         static psxRegisters oldregs;
486         static u32 event_cycles_o[PSXINT_COUNT];
487         u32 *allregs_p = (void *)&psxRegs;
488         u32 *allregs_o = (void *)&oldregs;
489         u32 io_data;
490         int i;
491         u8 byte;
492
493         //last_io_addr = 0x5e2c8;
494         if (f == NULL)
495                 f = fopen("tracelog", "wb");
496
497         // log reg changes
498         oldregs.code = psxRegs.code; // don't care
499         for (i = 0; i < offsetof(psxRegisters, intCycle) / 4; i++) {
500                 if (allregs_p[i] != allregs_o[i]) {
501                         fwrite(&i, 1, 1, f);
502                         fwrite(&allregs_p[i], 1, 4, f);
503                         allregs_o[i] = allregs_p[i];
504                 }
505         }
506         // log event changes
507         for (i = 0; i < PSXINT_COUNT; i++) {
508                 if (event_cycles[i] != event_cycles_o[i]) {
509                         byte = 0xf8;
510                         fwrite(&byte, 1, 1, f);
511                         fwrite(&i, 1, 1, f);
512                         fwrite(&event_cycles[i], 1, 4, f);
513                         event_cycles_o[i] = event_cycles[i];
514                 }
515         }
516         #define SAVE_IF_CHANGED(code_, name_) { \
517                 static u32 old_##name_ = 0xbad0c0de; \
518                 if (old_##name_ != name_) { \
519                         byte = code_; \
520                         fwrite(&byte, 1, 1, f); \
521                         fwrite(&name_, 1, 4, f); \
522                         old_##name_ = name_; \
523                 } \
524         }
525         SAVE_IF_CHANGED(0xfb, irq_test_cycle);
526         SAVE_IF_CHANGED(0xfc, handler_cycle);
527         SAVE_IF_CHANGED(0xfd, last_io_addr);
528         io_data = memcheck_read(last_io_addr);
529         SAVE_IF_CHANGED(0xfe, io_data);
530         byte = 0xff;
531         fwrite(&byte, 1, 1, f);
532
533 #if 0
534         if (psxRegs.cycle == 190230) {
535                 dump_mem("/mnt/ntz/dev/pnd/tmp/psxram_i.dump", psxM, 0x200000);
536                 dump_mem("/mnt/ntz/dev/pnd/tmp/psxregs_i.dump", psxH, 0x10000);
537                 printf("dumped\n");
538                 exit(1);
539         }
540 #endif
541 }
542 #endif
543
544 static const char *regnames[offsetof(psxRegisters, intCycle) / 4] = {
545         "r0",  "r1",  "r2",  "r3",  "r4",  "r5",  "r6",  "r7",
546         "r8",  "r9",  "r10", "r11", "r12", "r13", "r14", "r15",
547         "r16", "r17", "r18", "r19", "r20", "r21", "r22", "r23",
548         "r24", "r25", "r26", "r27", "r28", "r29", "r30", "r31",
549         "lo",  "hi",
550         "C0_0",  "C0_1",  "C0_2",  "C0_3",  "C0_4",  "C0_5",  "C0_6",  "C0_7",
551         "C0_8",  "C0_9",  "C0_10", "C0_11", "C0_12", "C0_13", "C0_14", "C0_15",
552         "C0_16", "C0_17", "C0_18", "C0_19", "C0_20", "C0_21", "C0_22", "C0_23",
553         "C0_24", "C0_25", "C0_26", "C0_27", "C0_28", "C0_29", "C0_30", "C0_31",
554
555         "C2D0",  "C2D1",  "C2D2",  "C2D3",  "C2D4",  "C2D5",  "C2D6",  "C2D7",
556         "C2D8",  "C2D9",  "C2D10", "C2D11", "C2D12", "C2D13", "C2D14", "C2D15",
557         "C2D16", "C2D17", "C2D18", "C2D19", "C2D20", "C2D21", "C2D22", "C2D23",
558         "C2D24", "C2D25", "C2D26", "C2D27", "C2D28", "C2D29", "C2D30", "C2D31",
559
560         "C2C0",  "C2C1",  "C2C2",  "C2C3",  "C2C4",  "C2C5",  "C2C6",  "C2C7",
561         "C2C8",  "C2C9",  "C2C10", "C2C11", "C2C12", "C2C13", "C2C14", "C2C15",
562         "C2C16", "C2C17", "C2C18", "C2C19", "C2C20", "C2C21", "C2C22", "C2C23",
563         "C2C24", "C2C25", "C2C26", "C2C27", "C2C28", "C2C29", "C2C30", "C2C31",
564
565         "PC", "code", "cycle", "interrupt",
566 };
567
568 static struct {
569         int reg;
570         u32 val, val_expect;
571         u32 pc, cycle;
572 } miss_log[64];
573 static int miss_log_i;
574 #define miss_log_len (sizeof(miss_log)/sizeof(miss_log[0]))
575 #define miss_log_mask (miss_log_len-1)
576
577 static void miss_log_add(int reg, u32 val, u32 val_expect, u32 pc, u32 cycle)
578 {
579         miss_log[miss_log_i].reg = reg;
580         miss_log[miss_log_i].val = val;
581         miss_log[miss_log_i].val_expect = val_expect;
582         miss_log[miss_log_i].pc = pc;
583         miss_log[miss_log_i].cycle = cycle;
584         miss_log_i = (miss_log_i + 1) & miss_log_mask;
585 }
586
587 void breakme() {}
588
589 void do_insn_cmp(void)
590 {
591         extern int last_count;
592         static psxRegisters rregs;
593         static u32 mem_addr, mem_val;
594         static u32 irq_test_cycle_intr;
595         static u32 handler_cycle_intr;
596         u32 *allregs_p = (void *)&psxRegs;
597         u32 *allregs_e = (void *)&rregs;
598         static u32 ppc, failcount;
599         int i, ret, bad = 0, fatal = 0, which_event = -1;
600         u32 ev_cycles = 0;
601         u8 code;
602
603         if (f == NULL)
604                 f = fopen("tracelog", "rb");
605
606         while (1) {
607                 if ((ret = fread(&code, 1, 1, f)) <= 0)
608                         break;
609                 if (ret <= 0)
610                         break;
611                 if (code == 0xff)
612                         break;
613                 switch (code) {
614                 case 0xf8:
615                         which_event = 0;
616                         fread(&which_event, 1, 1, f);
617                         fread(&ev_cycles, 1, 4, f);
618                         continue;
619                 case 0xfb:
620                         fread(&irq_test_cycle_intr, 1, 4, f);
621                         continue;
622                 case 0xfc:
623                         fread(&handler_cycle_intr, 1, 4, f);
624                         continue;
625                 case 0xfd:
626                         fread(&mem_addr, 1, 4, f);
627                         continue;
628                 case 0xfe:
629                         fread(&mem_val, 1, 4, f);
630                         continue;
631                 }
632                 assert(code < offsetof(psxRegisters, intCycle) / 4);
633                 fread(&allregs_e[code], 1, 4, f);
634         }
635
636         if (ret <= 0) {
637                 printf("EOF?\n");
638                 exit(1);
639         }
640
641         psxRegs.code = rregs.code; // don't care
642         psxRegs.cycle += last_count;
643         //psxRegs.cycle = rregs.cycle; // needs reload in _cmp
644         psxRegs.CP0.r[9] = rregs.CP0.r[9]; // Count
645
646         //if (psxRegs.cycle == 166172) breakme();
647
648         if (which_event >= 0 && event_cycles[which_event] != ev_cycles) {
649                 printf("bad ev_cycles #%d: %u %u / %u\n", which_event,
650                         event_cycles[which_event], ev_cycles, psxRegs.cycle);
651                 fatal = 1;
652         }
653
654         if (irq_test_cycle > irq_test_cycle_intr) {
655                 printf("bad irq_test_cycle: %u %u\n", irq_test_cycle, irq_test_cycle_intr);
656                 fatal = 1;
657         }
658
659         if (handler_cycle != handler_cycle_intr) {
660                 printf("bad handler_cycle: %u %u\n", handler_cycle, handler_cycle_intr);
661                 fatal = 1;
662         }
663
664         if (mem_val != memcheck_read(mem_addr)) {
665                 printf("bad mem @%08x: %08x %08x\n", mem_addr, memcheck_read(mem_addr), mem_val);
666                 fatal = 1;
667         }
668
669         if (!fatal && !memcmp(&psxRegs, &rregs, offsetof(psxRegisters, intCycle))) {
670                 failcount = 0;
671                 goto ok;
672         }
673
674         for (i = 0; i < offsetof(psxRegisters, intCycle) / 4; i++) {
675                 if (allregs_p[i] != allregs_e[i]) {
676                         miss_log_add(i, allregs_p[i], allregs_e[i], psxRegs.pc, psxRegs.cycle);
677                         bad++;
678                         if (i > 32+2)
679                                 fatal = 1;
680                 }
681         }
682
683         if (!fatal && psxRegs.pc == rregs.pc && bad < 6 && failcount < 32) {
684                 static int last_mcycle;
685                 if (last_mcycle != psxRegs.cycle >> 20) {
686                         printf("%u\n", psxRegs.cycle);
687                         last_mcycle = psxRegs.cycle >> 20;
688                 }
689                 failcount++;
690                 goto ok;
691         }
692
693         for (i = 0; i < miss_log_len; i++, miss_log_i = (miss_log_i + 1) & miss_log_mask)
694                 printf("bad %5s: %08x %08x, pc=%08x, cycle %u\n",
695                         regnames[miss_log[miss_log_i].reg], miss_log[miss_log_i].val,
696                         miss_log[miss_log_i].val_expect, miss_log[miss_log_i].pc, miss_log[miss_log_i].cycle);
697         printf("-- %d\n", bad);
698         for (i = 0; i < 8; i++)
699                 printf("r%d=%08x r%2d=%08x r%2d=%08x r%2d=%08x\n", i, allregs_p[i],
700                         i+8, allregs_p[i+8], i+16, allregs_p[i+16], i+24, allregs_p[i+24]);
701         printf("PC: %08x/%08x, cycle %u, next %u\n", psxRegs.pc, ppc, psxRegs.cycle, next_interupt);
702         //dump_mem("/tmp/psxram.dump", psxM, 0x200000);
703         //dump_mem("/mnt/ntz/dev/pnd/tmp/psxregs.dump", psxH, 0x10000);
704         exit(1);
705 ok:
706         //psxRegs.cycle = rregs.cycle + 2; // sync timing
707         ppc = psxRegs.pc;
708 }
709
710 #endif