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