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