02e108f8b930734096b2c8cce176de7a91e9b6c5
[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 "../r3000a.h"
14 #include "../cdrom.h"
15 #include "../psxdma.h"
16 #include "../mdec.h"
17 #include "../gte_arm.h"
18 #include "../gte_neon.h"
19 #define FLAGLESS
20 #include "../gte.h"
21
22 #define ARRAY_SIZE(x) (sizeof(x) / sizeof(x[0]))
23
24 //#define evprintf printf
25 #define evprintf(...)
26
27 char invalid_code[0x100000];
28 u32 event_cycles[PSXINT_COUNT];
29
30 static void schedule_timeslice(void)
31 {
32         u32 i, c = psxRegs.cycle;
33         u32 irqs = psxRegs.interrupt;
34         s32 min, dif;
35
36         min = PSXCLK;
37         for (i = 0; irqs != 0; i++, irqs >>= 1) {
38                 if (!(irqs & 1))
39                         continue;
40                 dif = event_cycles[i] - c;
41                 //evprintf("  ev %d\n", dif);
42                 if (0 < dif && dif < min)
43                         min = dif;
44         }
45         next_interupt = c + min;
46 }
47
48 typedef void (irq_func)();
49
50 static irq_func * const irq_funcs[] = {
51         [PSXINT_SIO]    = sioInterrupt,
52         [PSXINT_CDR]    = cdrInterrupt,
53         [PSXINT_CDREAD] = cdrReadInterrupt,
54         [PSXINT_GPUDMA] = gpuInterrupt,
55         [PSXINT_MDECOUTDMA] = mdec1Interrupt,
56         [PSXINT_SPUDMA] = spuInterrupt,
57         [PSXINT_MDECINDMA] = mdec0Interrupt,
58         [PSXINT_GPUOTCDMA] = gpuotcInterrupt,
59         [PSXINT_CDRDMA] = cdrDmaInterrupt,
60         [PSXINT_CDRLID] = cdrLidSeekInterrupt,
61         [PSXINT_CDRPLAY] = cdrPlayInterrupt,
62         [PSXINT_RCNT] = psxRcntUpdate,
63 };
64
65 /* local dupe of psxBranchTest, using event_cycles */
66 static void irq_test(void)
67 {
68         u32 irqs = psxRegs.interrupt;
69         u32 cycle = psxRegs.cycle;
70         u32 irq, irq_bits;
71
72         // irq_funcs() may queue more irqs
73         psxRegs.interrupt = 0;
74
75         for (irq = 0, irq_bits = irqs; irq_bits != 0; irq++, irq_bits >>= 1) {
76                 if (!(irq_bits & 1))
77                         continue;
78                 if ((s32)(cycle - event_cycles[irq]) >= 0) {
79                         irqs &= ~(1 << irq);
80                         irq_funcs[irq]();
81                 }
82         }
83         psxRegs.interrupt |= irqs;
84
85         if ((psxHu32(0x1070) & psxHu32(0x1074)) && (Status & 0x401) == 0x401) {
86                 psxException(0x400, 0);
87                 pending_exception = 1;
88         }
89 }
90
91 void gen_interupt()
92 {
93         evprintf("  +ge %08x, %u->%u\n", psxRegs.pc, psxRegs.cycle, next_interupt);
94
95         irq_test();
96         //psxBranchTest();
97         //pending_exception = 1;
98
99         schedule_timeslice();
100
101         evprintf("  -ge %08x, %u->%u (%d)\n", psxRegs.pc, psxRegs.cycle,
102                 next_interupt, next_interupt - psxRegs.cycle);
103 }
104
105 // from interpreter
106 extern void MTC0(int reg, u32 val);
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(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(reg, val);
121 }
122
123 void new_dyna_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 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 /* GTE stuff */
149 void *gte_handlers[64];
150
151 void *gte_handlers_nf[64] = {
152         NULL      , gteRTPS_nf , NULL       , NULL      , NULL     , NULL       , gteNCLIP_nf, NULL      , // 00
153         NULL      , NULL       , NULL       , NULL      , gteOP_nf , NULL       , NULL       , NULL      , // 08
154         gteDPCS_nf, gteINTPL_nf, gteMVMVA_nf, gteNCDS_nf, gteCDP_nf, NULL       , gteNCDT_nf , NULL      , // 10
155         NULL      , NULL       , NULL       , gteNCCS_nf, gteCC_nf , NULL       , gteNCS_nf  , NULL      , // 18
156         gteNCT_nf , NULL       , NULL       , NULL      , NULL     , NULL       , NULL       , NULL      , // 20
157         gteSQR_nf , gteDCPL_nf , gteDPCT_nf , NULL      , NULL     , gteAVSZ3_nf, gteAVSZ4_nf, NULL      , // 28 
158         gteRTPT_nf, NULL       , NULL       , NULL      , NULL     , NULL       , NULL       , NULL      , // 30
159         NULL      , NULL       , NULL       , NULL      , NULL     , gteGPF_nf  , gteGPL_nf  , gteNCCT_nf, // 38
160 };
161
162 const char *gte_regnames[64] = {
163         NULL  , "RTPS" , NULL   , NULL  , NULL , NULL   , "NCLIP", NULL  , // 00
164         NULL  , NULL   , NULL   , NULL  , "OP" , NULL   , NULL   , NULL  , // 08
165         "DPCS", "INTPL", "MVMVA", "NCDS", "CDP", NULL   , "NCDT" , NULL  , // 10
166         NULL  , NULL   , NULL   , "NCCS", "CC" , NULL   , "NCS"  , NULL  , // 18
167         "NCT" , NULL   , NULL   , NULL  , NULL , NULL   , NULL   , NULL  , // 20
168         "SQR" , "DCPL" , "DPCT" , NULL  , NULL , "AVSZ3", "AVSZ4", NULL  , // 28 
169         "RTPT", NULL   , NULL   , NULL  , NULL , NULL   , NULL   , NULL  , // 30
170         NULL  , NULL   , NULL   , NULL  , NULL , "GPF"  , "GPL"  , "NCCT", // 38
171 };
172
173 /* from gte.txt.. not sure if this is any good. */
174 const char gte_cycletab[64] = {
175         /*   1   2   3   4   5   6   7   8   9   a   b   c   d   e   f */
176          0, 15,  0,  0,  0,  0,  8,  0,  0,  0,  0,  0,  6,  0,  0,  0,
177          8,  8,  8, 19, 13,  0, 44,  0,  0,  0,  0, 17, 11,  0, 14,  0,
178         30,  0,  0,  0,  0,  0,  0,  0,  5,  8, 17,  0,  0,  5,  6,  0,
179         23,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  5,  5, 39,
180 };
181
182 #define GCBIT(x) \
183         (1ll << (32+x))
184 #define GDBIT(x) \
185         (1ll << (x))
186 #define GCBITS3(b0,b1,b2) \
187         (GCBIT(b0) | GCBIT(b1) | GCBIT(b2))
188 #define GDBITS2(b0,b1) \
189         (GDBIT(b0) | GDBIT(b1))
190 #define GDBITS3(b0,b1,b2) \
191         (GDBITS2(b0,b1) | GDBIT(b2))
192 #define GDBITS4(b0,b1,b2,b3) \
193         (GDBITS3(b0,b1,b2) | GDBIT(b3))
194 #define GDBITS5(b0,b1,b2,b3,b4) \
195         (GDBITS4(b0,b1,b2,b3) | GDBIT(b4))
196 #define GDBITS6(b0,b1,b2,b3,b4,b5) \
197         (GDBITS5(b0,b1,b2,b3,b4) | GDBIT(b5))
198 #define GDBITS7(b0,b1,b2,b3,b4,b5,b6) \
199         (GDBITS6(b0,b1,b2,b3,b4,b5) | GDBIT(b6))
200 #define GDBITS8(b0,b1,b2,b3,b4,b5,b6,b7) \
201         (GDBITS7(b0,b1,b2,b3,b4,b5,b6) | GDBIT(b7))
202 #define GDBITS9(b0,b1,b2,b3,b4,b5,b6,b7,b8) \
203         (GDBITS8(b0,b1,b2,b3,b4,b5,b6,b7) | GDBIT(b8))
204 #define GDBITS10(b0,b1,b2,b3,b4,b5,b6,b7,b8,b9) \
205         (GDBITS9(b0,b1,b2,b3,b4,b5,b6,b7,b8) | GDBIT(b9))
206
207 const uint64_t gte_reg_reads[64] = {
208         [GTE_RTPS]  = 0x1f0000ff00000000ll | GDBITS7(0,1,13,14,17,18,19),
209         [GTE_NCLIP] =                        GDBITS3(12,13,14),
210         [GTE_OP]    = GCBITS3(0,2,4)       | GDBITS3(9,10,11),
211         [GTE_DPCS]  = GCBITS3(21,22,23)    | GDBITS4(6,8,21,22),
212         [GTE_INTPL] = GCBITS3(21,22,23)    | GDBITS7(6,8,9,10,11,21,22),
213         [GTE_MVMVA] = 0x00ffffff00000000ll | GDBITS9(0,1,2,3,4,5,9,10,11), // XXX: maybe decode further?
214         [GTE_NCDS]  = 0x00ffff0000000000ll | GDBITS6(0,1,6,8,21,22),
215         [GTE_CDP]   = 0x00ffe00000000000ll | GDBITS7(6,8,9,10,11,21,22),
216         [GTE_NCDT]  = 0x00ffff0000000000ll | GDBITS8(0,1,2,3,4,5,6,8),
217         [GTE_NCCS]  = 0x001fff0000000000ll | GDBITS5(0,1,6,21,22),
218         [GTE_CC]    = 0x001fe00000000000ll | GDBITS6(6,9,10,11,21,22),
219         [GTE_NCS]   = 0x001fff0000000000ll | GDBITS5(0,1,6,21,22),
220         [GTE_NCT]   = 0x001fff0000000000ll | GDBITS7(0,1,2,3,4,5,6),
221         [GTE_SQR]   =                        GDBITS3(9,10,11),
222         [GTE_DCPL]  = GCBITS3(21,22,23)    | GDBITS7(6,8,9,10,11,21,22),
223         [GTE_DPCT]  = GCBITS3(21,22,23)    | GDBITS4(8,20,21,22),
224         [GTE_AVSZ3] = GCBIT(29)            | GDBITS3(17,18,19),
225         [GTE_AVSZ4] = GCBIT(30)            | GDBITS4(16,17,18,19),
226         [GTE_RTPT]  = 0x1f0000ff00000000ll | GDBITS7(0,1,2,3,4,5,19),
227         [GTE_GPF]   =                        GDBITS7(6,8,9,10,11,21,22),
228         [GTE_GPL]   =                        GDBITS10(6,8,9,10,11,21,22,25,26,27),
229         [GTE_NCCT]  = 0x001fff0000000000ll | GDBITS7(0,1,2,3,4,5,6),
230 };
231
232 // note: this excludes gteFLAG that is always written to
233 const uint64_t gte_reg_writes[64] = {
234         [GTE_RTPS]  = 0x0f0f7f00ll,
235         [GTE_NCLIP] = GDBIT(24),
236         [GTE_OP]    = GDBITS6(9,10,11,25,26,27),
237         [GTE_DPCS]  = GDBITS9(9,10,11,20,21,22,25,26,27),
238         [GTE_INTPL] = GDBITS9(9,10,11,20,21,22,25,26,27),
239         [GTE_MVMVA] = GDBITS6(9,10,11,25,26,27),
240         [GTE_NCDS]  = GDBITS9(9,10,11,20,21,22,25,26,27),
241         [GTE_CDP]   = GDBITS9(9,10,11,20,21,22,25,26,27),
242         [GTE_NCDT]  = GDBITS9(9,10,11,20,21,22,25,26,27),
243         [GTE_NCCS]  = GDBITS9(9,10,11,20,21,22,25,26,27),
244         [GTE_CC]    = GDBITS9(9,10,11,20,21,22,25,26,27),
245         [GTE_NCS]   = GDBITS9(9,10,11,20,21,22,25,26,27),
246         [GTE_NCT]   = GDBITS9(9,10,11,20,21,22,25,26,27),
247         [GTE_SQR]   = GDBITS6(9,10,11,25,26,27),
248         [GTE_DCPL]  = GDBITS9(9,10,11,20,21,22,25,26,27),
249         [GTE_DPCT]  = GDBITS9(9,10,11,20,21,22,25,26,27),
250         [GTE_AVSZ3] = GDBITS2(7,24),
251         [GTE_AVSZ4] = GDBITS2(7,24),
252         [GTE_RTPT]  = 0x0f0f7f00ll,
253         [GTE_GPF]   = GDBITS9(9,10,11,20,21,22,25,26,27),
254         [GTE_GPL]   = GDBITS9(9,10,11,20,21,22,25,26,27),
255         [GTE_NCCT]  = GDBITS9(9,10,11,20,21,22,25,26,27),
256 };
257
258 static int ari64_init()
259 {
260         extern void (*psxCP2[64])();
261         extern void psxNULL();
262         size_t i;
263
264         new_dynarec_init();
265         new_dyna_pcsx_mem_init();
266
267         for (i = 0; i < ARRAY_SIZE(gte_handlers); i++)
268                 if (psxCP2[i] != psxNULL)
269                         gte_handlers[i] = psxCP2[i];
270
271 #if defined(__arm__) && !defined(DRC_DBG)
272         gte_handlers[0x06] = gteNCLIP_arm;
273 #ifdef HAVE_ARMV5
274         gte_handlers_nf[0x01] = gteRTPS_nf_arm;
275         gte_handlers_nf[0x30] = gteRTPT_nf_arm;
276 #endif
277 #ifdef __ARM_NEON__
278         // compiler's _nf version is still a lot slower than neon
279         // _nf_arm RTPS is roughly the same, RTPT slower
280         gte_handlers[0x01] = gte_handlers_nf[0x01] = gteRTPS_neon;
281         gte_handlers[0x30] = gte_handlers_nf[0x30] = gteRTPT_neon;
282 #endif
283 #endif
284 #ifdef DRC_DBG
285         memcpy(gte_handlers_nf, gte_handlers, sizeof(gte_handlers_nf));
286 #endif
287         psxH_ptr = psxH;
288         zeromem_ptr = zero_mem;
289
290         return 0;
291 }
292
293 static void ari64_reset()
294 {
295         printf("ari64_reset\n");
296         new_dyna_pcsx_mem_reset();
297         invalidate_all_pages();
298         new_dyna_restore();
299         pending_exception = 1;
300 }
301
302 // execute until predefined leave points
303 // (HLE softcall exit and BIOS fastboot end)
304 static void ari64_execute_until()
305 {
306         schedule_timeslice();
307
308         evprintf("ari64_execute %08x, %u->%u (%d)\n", psxRegs.pc,
309                 psxRegs.cycle, next_interupt, next_interupt - psxRegs.cycle);
310
311         new_dyna_start();
312
313         evprintf("ari64_execute end %08x, %u->%u (%d)\n", psxRegs.pc,
314                 psxRegs.cycle, next_interupt, next_interupt - psxRegs.cycle);
315 }
316
317 static void ari64_execute()
318 {
319         while (!stop) {
320                 ari64_execute_until();
321                 evprintf("drc left @%08x\n", psxRegs.pc);
322         }
323 }
324
325 static void ari64_clear(u32 addr, u32 size)
326 {
327         u32 start, end, main_ram;
328
329         size *= 4; /* PCSX uses DMA units */
330
331         evprintf("ari64_clear %08x %04x\n", addr, size);
332
333         /* check for RAM mirrors */
334         main_ram = (addr & 0xffe00000) == 0x80000000;
335
336         start = addr >> 12;
337         end = (addr + size) >> 12;
338
339         for (; start <= end; start++)
340                 if (!main_ram || !invalid_code[start])
341                         invalidate_block(start);
342 }
343
344 static void ari64_shutdown()
345 {
346         new_dynarec_cleanup();
347         new_dyna_pcsx_mem_shutdown();
348 }
349
350 extern void intExecute();
351 extern void intExecuteT();
352 extern void intExecuteBlock();
353 extern void intExecuteBlockT();
354 #ifndef DRC_DBG
355 #define intExecuteT intExecute
356 #define intExecuteBlockT intExecuteBlock
357 #endif
358
359 R3000Acpu psxRec = {
360         ari64_init,
361         ari64_reset,
362 #ifndef DRC_DISABLE
363         ari64_execute,
364         ari64_execute_until,
365 #else
366         intExecuteT,
367         intExecuteBlockT,
368 #endif
369         ari64_clear,
370         ari64_shutdown
371 };
372
373 // TODO: rm
374 #ifndef DRC_DBG
375 void do_insn_trace() {}
376 void do_insn_cmp() {}
377 #endif
378
379 #ifdef DRC_DISABLE
380 unsigned int address;
381 int pending_exception, stop;
382 unsigned int next_interupt;
383 int new_dynarec_did_compile;
384 int cycle_multiplier;
385 int new_dynarec_hacks;
386 void *psxH_ptr;
387 void *zeromem_ptr;
388 u8 zero_mem[0x1000];
389 void new_dynarec_init() { (void)ari64_execute; }
390 void new_dyna_start() {}
391 void new_dynarec_cleanup() {}
392 void new_dynarec_clear_full() {}
393 void invalidate_all_pages() {}
394 void invalidate_block(unsigned int block) {}
395 void new_dyna_pcsx_mem_init(void) {}
396 void new_dyna_pcsx_mem_reset(void) {}
397 void new_dyna_pcsx_mem_load_state(void) {}
398 void new_dyna_pcsx_mem_shutdown(void) {}
399 #endif
400
401 #ifdef DRC_DBG
402
403 #include <stddef.h>
404 static FILE *f;
405 extern u32 last_io_addr;
406
407 static void dump_mem(const char *fname, void *mem, size_t size)
408 {
409         FILE *f1 = fopen(fname, "wb");
410         if (f1 == NULL)
411                 f1 = fopen(strrchr(fname, '/') + 1, "wb");
412         fwrite(mem, 1, size, f1);
413         fclose(f1);
414 }
415
416 static u32 memcheck_read(u32 a)
417 {
418         if ((a >> 16) == 0x1f80)
419                 // scratchpad/IO
420                 return *(u32 *)(psxH + (a & 0xfffc));
421
422         if ((a >> 16) == 0x1f00)
423                 // parallel
424                 return *(u32 *)(psxP + (a & 0xfffc));
425
426 //      if ((a & ~0xe0600000) < 0x200000)
427         // RAM
428         return *(u32 *)(psxM + (a & 0x1ffffc));
429 }
430
431 void do_insn_trace(void)
432 {
433         static psxRegisters oldregs;
434         static u32 old_io_addr = (u32)-1;
435         static u32 old_io_data = 0xbad0c0de;
436         static u32 event_cycles_o[PSXINT_COUNT];
437         u32 *allregs_p = (void *)&psxRegs;
438         u32 *allregs_o = (void *)&oldregs;
439         u32 io_data;
440         int i;
441         u8 byte;
442
443         //last_io_addr = 0x5e2c8;
444         if (f == NULL)
445                 f = fopen("tracelog", "wb");
446
447         // log reg changes
448         oldregs.code = psxRegs.code; // don't care
449         for (i = 0; i < offsetof(psxRegisters, intCycle) / 4; i++) {
450                 if (allregs_p[i] != allregs_o[i]) {
451                         fwrite(&i, 1, 1, f);
452                         fwrite(&allregs_p[i], 1, 4, f);
453                         allregs_o[i] = allregs_p[i];
454                 }
455         }
456         // log event changes
457         for (i = 0; i < PSXINT_COUNT; i++) {
458                 if (event_cycles[i] != event_cycles_o[i]) {
459                         byte = 0xfc;
460                         fwrite(&byte, 1, 1, f);
461                         fwrite(&i, 1, 1, f);
462                         fwrite(&event_cycles[i], 1, 4, f);
463                         event_cycles_o[i] = event_cycles[i];
464                 }
465         }
466         // log last io
467         if (old_io_addr != last_io_addr) {
468                 byte = 0xfd;
469                 fwrite(&byte, 1, 1, f);
470                 fwrite(&last_io_addr, 1, 4, f);
471                 old_io_addr = last_io_addr;
472         }
473         io_data = memcheck_read(last_io_addr);
474         if (old_io_data != io_data) {
475                 byte = 0xfe;
476                 fwrite(&byte, 1, 1, f);
477                 fwrite(&io_data, 1, 4, f);
478                 old_io_data = io_data;
479         }
480         byte = 0xff;
481         fwrite(&byte, 1, 1, f);
482
483 #if 0
484         if (psxRegs.cycle == 190230) {
485                 dump_mem("/mnt/ntz/dev/pnd/tmp/psxram_i.dump", psxM, 0x200000);
486                 dump_mem("/mnt/ntz/dev/pnd/tmp/psxregs_i.dump", psxH, 0x10000);
487                 printf("dumped\n");
488                 exit(1);
489         }
490 #endif
491 }
492
493 static const char *regnames[offsetof(psxRegisters, intCycle) / 4] = {
494         "r0",  "r1",  "r2",  "r3",  "r4",  "r5",  "r6",  "r7",
495         "r8",  "r9",  "r10", "r11", "r12", "r13", "r14", "r15",
496         "r16", "r17", "r18", "r19", "r20", "r21", "r22", "r23",
497         "r24", "r25", "r26", "r27", "r28", "r29", "r30", "r31",
498         "lo",  "hi",
499         "C0_0",  "C0_1",  "C0_2",  "C0_3",  "C0_4",  "C0_5",  "C0_6",  "C0_7",
500         "C0_8",  "C0_9",  "C0_10", "C0_11", "C0_12", "C0_13", "C0_14", "C0_15",
501         "C0_16", "C0_17", "C0_18", "C0_19", "C0_20", "C0_21", "C0_22", "C0_23",
502         "C0_24", "C0_25", "C0_26", "C0_27", "C0_28", "C0_29", "C0_30", "C0_31",
503
504         "C2D0",  "C2D1",  "C2D2",  "C2D3",  "C2D4",  "C2D5",  "C2D6",  "C2D7",
505         "C2D8",  "C2D9",  "C2D10", "C2D11", "C2D12", "C2D13", "C2D14", "C2D15",
506         "C2D16", "C2D17", "C2D18", "C2D19", "C2D20", "C2D21", "C2D22", "C2D23",
507         "C2D24", "C2D25", "C2D26", "C2D27", "C2D28", "C2D29", "C2D30", "C2D31",
508
509         "C2C0",  "C2C1",  "C2C2",  "C2C3",  "C2C4",  "C2C5",  "C2C6",  "C2C7",
510         "C2C8",  "C2C9",  "C2C10", "C2C11", "C2C12", "C2C13", "C2C14", "C2C15",
511         "C2C16", "C2C17", "C2C18", "C2C19", "C2C20", "C2C21", "C2C22", "C2C23",
512         "C2C24", "C2C25", "C2C26", "C2C27", "C2C28", "C2C29", "C2C30", "C2C31",
513
514         "PC", "code", "cycle", "interrupt",
515 };
516
517 static struct {
518         int reg;
519         u32 val, val_expect;
520         u32 pc, cycle;
521 } miss_log[64];
522 static int miss_log_i;
523 #define miss_log_len (sizeof(miss_log)/sizeof(miss_log[0]))
524 #define miss_log_mask (miss_log_len-1)
525
526 static void miss_log_add(int reg, u32 val, u32 val_expect, u32 pc, u32 cycle)
527 {
528         miss_log[miss_log_i].reg = reg;
529         miss_log[miss_log_i].val = val;
530         miss_log[miss_log_i].val_expect = val_expect;
531         miss_log[miss_log_i].pc = pc;
532         miss_log[miss_log_i].cycle = cycle;
533         miss_log_i = (miss_log_i + 1) & miss_log_mask;
534 }
535
536 void breakme() {}
537
538 void do_insn_cmp(void)
539 {
540         static psxRegisters rregs;
541         static u32 mem_addr, mem_val;
542         u32 *allregs_p = (void *)&psxRegs;
543         u32 *allregs_e = (void *)&rregs;
544         static u32 ppc, failcount;
545         int i, ret, bad = 0, which_event = -1;
546         u32 ev_cycles = 0;
547         u8 code;
548
549         if (f == NULL)
550                 f = fopen("tracelog", "rb");
551
552         while (1) {
553                 if ((ret = fread(&code, 1, 1, f)) <= 0)
554                         break;
555                 if (ret <= 0)
556                         break;
557                 if (code == 0xff)
558                         break;
559                 switch (code) {
560                 case 0xfc:
561                         which_event = 0;
562                         fread(&which_event, 1, 1, f);
563                         fread(&ev_cycles, 1, 4, f);
564                         continue;
565                 case 0xfd:
566                         fread(&mem_addr, 1, 4, f);
567                         continue;
568                 case 0xfe:
569                         fread(&mem_val, 1, 4, f);
570                         continue;
571                 }
572                 fread(&allregs_e[code], 1, 4, f);
573         }
574
575         if (ret <= 0) {
576                 printf("EOF?\n");
577                 goto end;
578         }
579
580         psxRegs.code = rregs.code; // don't care
581         psxRegs.cycle = rregs.cycle;
582         psxRegs.CP0.r[9] = rregs.CP0.r[9]; // Count
583
584         //if (psxRegs.cycle == 166172) breakme();
585
586         if (memcmp(&psxRegs, &rregs, offsetof(psxRegisters, intCycle)) == 0 &&
587                         mem_val == memcheck_read(mem_addr)
588            ) {
589                 failcount = 0;
590                 goto ok;
591         }
592
593         for (i = 0; i < offsetof(psxRegisters, intCycle) / 4; i++) {
594                 if (allregs_p[i] != allregs_e[i]) {
595                         miss_log_add(i, allregs_p[i], allregs_e[i], psxRegs.pc, psxRegs.cycle);
596                         bad++;
597                 }
598         }
599
600         if (mem_val != memcheck_read(mem_addr)) {
601                 printf("bad mem @%08x: %08x %08x\n", mem_addr, memcheck_read(mem_addr), mem_val);
602                 goto end;
603         }
604
605         if (which_event >= 0 && event_cycles[which_event] != ev_cycles) {
606                 printf("bad ev_cycles #%d: %08x %08x\n", which_event, event_cycles[which_event], ev_cycles);
607                 goto end;
608         }
609
610         if (psxRegs.pc == rregs.pc && bad < 6 && failcount < 32) {
611                 static int last_mcycle;
612                 if (last_mcycle != psxRegs.cycle >> 20) {
613                         printf("%u\n", psxRegs.cycle);
614                         last_mcycle = psxRegs.cycle >> 20;
615                 }
616                 failcount++;
617                 goto ok;
618         }
619
620 end:
621         for (i = 0; i < miss_log_len; i++, miss_log_i = (miss_log_i + 1) & miss_log_mask)
622                 printf("bad %5s: %08x %08x, pc=%08x, cycle %u\n",
623                         regnames[miss_log[miss_log_i].reg], miss_log[miss_log_i].val,
624                         miss_log[miss_log_i].val_expect, miss_log[miss_log_i].pc, miss_log[miss_log_i].cycle);
625         printf("-- %d\n", bad);
626         for (i = 0; i < 8; i++)
627                 printf("r%d=%08x r%2d=%08x r%2d=%08x r%2d=%08x\n", i, allregs_p[i],
628                         i+8, allregs_p[i+8], i+16, allregs_p[i+16], i+24, allregs_p[i+24]);
629         printf("PC: %08x/%08x, cycle %u\n", psxRegs.pc, ppc, psxRegs.cycle);
630         dump_mem("/mnt/ntz/dev/pnd/tmp/psxram.dump", psxM, 0x200000);
631         dump_mem("/mnt/ntz/dev/pnd/tmp/psxregs.dump", psxH, 0x10000);
632         exit(1);
633 ok:
634         psxRegs.cycle = rregs.cycle + 2; // sync timing
635         ppc = psxRegs.pc;
636 }
637
638 #endif