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