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