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