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