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