adjust bios handling again
[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.Status & 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         static u32 ppc, failcount;
515         int i, ret, bad = 0, fatal = 0, which_event = -1;
516         u32 ev_cycles = 0;
517         u8 code;
518
519         if (f == NULL)
520                 f = fopen("tracelog", "rb");
521
522         while (1) {
523                 if ((ret = fread(&code, 1, 1, f)) <= 0)
524                         break;
525                 if (ret <= 0)
526                         break;
527                 if (code == 0xff)
528                         break;
529                 switch (code) {
530                 case 0xf8:
531                         which_event = 0;
532                         fread(&which_event, 1, 1, f);
533                         fread(&ev_cycles, 1, 4, f);
534                         continue;
535                 case 0xfb:
536                         fread(&irq_test_cycle_intr, 1, 4, f);
537                         continue;
538                 case 0xfc:
539                         fread(&handler_cycle_intr, 1, 4, f);
540                         continue;
541                 case 0xfd:
542                         fread(&mem_addr, 1, 4, f);
543                         continue;
544                 case 0xfe:
545                         fread(&mem_val, 1, 4, f);
546                         continue;
547                 }
548                 assert(code < offsetof(psxRegisters, intCycle) / 4);
549                 fread(&allregs_e[code], 1, 4, f);
550         }
551
552         if (ret <= 0) {
553                 printf("EOF?\n");
554                 exit(1);
555         }
556
557         psxRegs.code = rregs.code; // don't care
558         psxRegs.cycle += last_count;
559         //psxRegs.cycle = rregs.cycle; // needs reload in _cmp
560         psxRegs.CP0.r[9] = rregs.CP0.r[9]; // Count
561
562         //if (psxRegs.cycle == 166172) breakme();
563
564         if (which_event >= 0 && event_cycles[which_event] != ev_cycles) {
565                 printf("bad ev_cycles #%d: %u %u / %u\n", which_event,
566                         event_cycles[which_event], ev_cycles, psxRegs.cycle);
567                 fatal = 1;
568         }
569
570         if (irq_test_cycle > irq_test_cycle_intr) {
571                 printf("bad irq_test_cycle: %u %u\n", irq_test_cycle, irq_test_cycle_intr);
572                 fatal = 1;
573         }
574
575         if (handler_cycle != handler_cycle_intr) {
576                 printf("bad handler_cycle: %u %u\n", handler_cycle, handler_cycle_intr);
577                 fatal = 1;
578         }
579
580         if (mem_val != memcheck_read(mem_addr)) {
581                 printf("bad mem @%08x: %08x %08x\n", mem_addr, memcheck_read(mem_addr), mem_val);
582                 fatal = 1;
583         }
584
585         if (!fatal && !memcmp(&psxRegs, &rregs, offsetof(psxRegisters, intCycle))) {
586                 failcount = 0;
587                 goto ok;
588         }
589
590         for (i = 0; i < offsetof(psxRegisters, intCycle) / 4; i++) {
591                 if (allregs_p[i] != allregs_e[i]) {
592                         miss_log_add(i, allregs_p[i], allregs_e[i], psxRegs.pc, psxRegs.cycle);
593                         bad++;
594                         if (i > 32+2)
595                                 fatal = 1;
596                 }
597         }
598
599         if (!fatal && psxRegs.pc == rregs.pc && bad < 6 && failcount < 32) {
600                 static int last_mcycle;
601                 if (last_mcycle != psxRegs.cycle >> 20) {
602                         printf("%u\n", psxRegs.cycle);
603                         last_mcycle = psxRegs.cycle >> 20;
604                 }
605                 failcount++;
606                 goto ok;
607         }
608
609         for (i = 0; i < miss_log_len; i++, miss_log_i = (miss_log_i + 1) & miss_log_mask)
610                 printf("bad %5s: %08x %08x, pc=%08x, cycle %u\n",
611                         regnames[miss_log[miss_log_i].reg], miss_log[miss_log_i].val,
612                         miss_log[miss_log_i].val_expect, miss_log[miss_log_i].pc, miss_log[miss_log_i].cycle);
613         printf("-- %d\n", bad);
614         for (i = 0; i < 8; i++)
615                 printf("r%d=%08x r%2d=%08x r%2d=%08x r%2d=%08x\n", i, allregs_p[i],
616                         i+8, allregs_p[i+8], i+16, allregs_p[i+16], i+24, allregs_p[i+24]);
617         printf("PC: %08x/%08x, cycle %u, next %u\n", psxRegs.pc, ppc, psxRegs.cycle, next_interupt);
618         //dump_mem("/tmp/psxram.dump", psxM, 0x200000);
619         //dump_mem("/mnt/ntz/dev/pnd/tmp/psxregs.dump", psxH, 0x10000);
620         exit(1);
621 ok:
622         //psxRegs.cycle = rregs.cycle + 2; // sync timing
623         ppc = psxRegs.pc;
624 }
625
626 #endif