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