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