fix clang warnings
[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 size_t i;
264
265 new_dynarec_init();
266 new_dyna_pcsx_mem_init();
267
268 for (i = 0; i < ARRAY_SIZE(gte_handlers); i++)
269 if (psxCP2[i] != psxNULL)
270 gte_handlers[i] = psxCP2[i];
271
272#if defined(__arm__) && !defined(DRC_DBG)
273 gte_handlers[0x06] = gteNCLIP_arm;
274#ifdef HAVE_ARMV5
275 gte_handlers_nf[0x01] = gteRTPS_nf_arm;
276 gte_handlers_nf[0x30] = gteRTPT_nf_arm;
277#endif
278#ifdef __ARM_NEON__
279 // compiler's _nf version is still a lot slower than neon
280 // _nf_arm RTPS is roughly the same, RTPT slower
281 gte_handlers[0x01] = gte_handlers_nf[0x01] = gteRTPS_neon;
282 gte_handlers[0x30] = gte_handlers_nf[0x30] = gteRTPT_neon;
283#endif
284#endif
285#ifdef DRC_DBG
286 memcpy(gte_handlers_nf, gte_handlers, sizeof(gte_handlers_nf));
287#endif
288 psxH_ptr = psxH;
289 zeromem_ptr = zero_mem;
290 scratch_buf_ptr = scratch_buf;
291
292 return 0;
293}
294
295static void ari64_reset()
296{
297 printf("ari64_reset\n");
298 new_dyna_pcsx_mem_reset();
299 invalidate_all_pages();
300 new_dyna_restore();
301 pending_exception = 1;
302}
303
304// execute until predefined leave points
305// (HLE softcall exit and BIOS fastboot end)
306static void ari64_execute_until()
307{
308 schedule_timeslice();
309
310 evprintf("ari64_execute %08x, %u->%u (%d)\n", psxRegs.pc,
311 psxRegs.cycle, next_interupt, next_interupt - psxRegs.cycle);
312
313 new_dyna_start();
314
315 evprintf("ari64_execute end %08x, %u->%u (%d)\n", psxRegs.pc,
316 psxRegs.cycle, next_interupt, next_interupt - psxRegs.cycle);
317}
318
319static void ari64_execute()
320{
321 while (!stop) {
322 ari64_execute_until();
323 evprintf("drc left @%08x\n", psxRegs.pc);
324 }
325}
326
327static void ari64_clear(u32 addr, u32 size)
328{
329 u32 start, end, main_ram;
330
331 size *= 4; /* PCSX uses DMA units */
332
333 evprintf("ari64_clear %08x %04x\n", addr, size);
334
335 /* check for RAM mirrors */
336 main_ram = (addr & 0xffe00000) == 0x80000000;
337
338 start = addr >> 12;
339 end = (addr + size) >> 12;
340
341 for (; start <= end; start++)
342 if (!main_ram || !invalid_code[start])
343 invalidate_block(start);
344}
345
346static void ari64_shutdown()
347{
348 new_dynarec_cleanup();
349 new_dyna_pcsx_mem_shutdown();
350}
351
352extern void intExecute();
353extern void intExecuteT();
354extern void intExecuteBlock();
355extern void intExecuteBlockT();
356#ifndef DRC_DBG
357#define intExecuteT intExecute
358#define intExecuteBlockT intExecuteBlock
359#endif
360
361R3000Acpu psxRec = {
362 ari64_init,
363 ari64_reset,
364#ifndef DRC_DISABLE
365 ari64_execute,
366 ari64_execute_until,
367#else
368 intExecuteT,
369 intExecuteBlockT,
370#endif
371 ari64_clear,
372 ari64_shutdown
373};
374
375// TODO: rm
376#ifndef DRC_DBG
377void do_insn_trace() {}
378void do_insn_cmp() {}
379#endif
380
381#ifdef DRC_DISABLE
382unsigned int address;
383int pending_exception, stop;
384unsigned int next_interupt;
385int new_dynarec_did_compile;
386int cycle_multiplier;
387int new_dynarec_hacks;
388void *psxH_ptr;
389void *zeromem_ptr;
390u8 zero_mem[0x1000];
391void *scratch_buf_ptr;
392void new_dynarec_init() { (void)ari64_execute; }
393void new_dyna_start() {}
394void new_dynarec_cleanup() {}
395void new_dynarec_clear_full() {}
396void invalidate_all_pages() {}
397void invalidate_block(unsigned int block) {}
398void new_dyna_pcsx_mem_init(void) {}
399void new_dyna_pcsx_mem_reset(void) {}
400void new_dyna_pcsx_mem_load_state(void) {}
401void new_dyna_pcsx_mem_shutdown(void) {}
402#endif
403
404#ifdef DRC_DBG
405
406#include <stddef.h>
407static FILE *f;
408extern u32 last_io_addr;
409
410static void dump_mem(const char *fname, void *mem, size_t size)
411{
412 FILE *f1 = fopen(fname, "wb");
413 if (f1 == NULL)
414 f1 = fopen(strrchr(fname, '/') + 1, "wb");
415 fwrite(mem, 1, size, f1);
416 fclose(f1);
417}
418
419static u32 memcheck_read(u32 a)
420{
421 if ((a >> 16) == 0x1f80)
422 // scratchpad/IO
423 return *(u32 *)(psxH + (a & 0xfffc));
424
425 if ((a >> 16) == 0x1f00)
426 // parallel
427 return *(u32 *)(psxP + (a & 0xfffc));
428
429// if ((a & ~0xe0600000) < 0x200000)
430 // RAM
431 return *(u32 *)(psxM + (a & 0x1ffffc));
432}
433
434void do_insn_trace(void)
435{
436 static psxRegisters oldregs;
437 static u32 old_io_addr = (u32)-1;
438 static u32 old_io_data = 0xbad0c0de;
439 static u32 event_cycles_o[PSXINT_COUNT];
440 u32 *allregs_p = (void *)&psxRegs;
441 u32 *allregs_o = (void *)&oldregs;
442 u32 io_data;
443 int i;
444 u8 byte;
445
446 //last_io_addr = 0x5e2c8;
447 if (f == NULL)
448 f = fopen("tracelog", "wb");
449
450 // log reg changes
451 oldregs.code = psxRegs.code; // don't care
452 for (i = 0; i < offsetof(psxRegisters, intCycle) / 4; i++) {
453 if (allregs_p[i] != allregs_o[i]) {
454 fwrite(&i, 1, 1, f);
455 fwrite(&allregs_p[i], 1, 4, f);
456 allregs_o[i] = allregs_p[i];
457 }
458 }
459 // log event changes
460 for (i = 0; i < PSXINT_COUNT; i++) {
461 if (event_cycles[i] != event_cycles_o[i]) {
462 byte = 0xfc;
463 fwrite(&byte, 1, 1, f);
464 fwrite(&i, 1, 1, f);
465 fwrite(&event_cycles[i], 1, 4, f);
466 event_cycles_o[i] = event_cycles[i];
467 }
468 }
469 // log last io
470 if (old_io_addr != last_io_addr) {
471 byte = 0xfd;
472 fwrite(&byte, 1, 1, f);
473 fwrite(&last_io_addr, 1, 4, f);
474 old_io_addr = last_io_addr;
475 }
476 io_data = memcheck_read(last_io_addr);
477 if (old_io_data != io_data) {
478 byte = 0xfe;
479 fwrite(&byte, 1, 1, f);
480 fwrite(&io_data, 1, 4, f);
481 old_io_data = io_data;
482 }
483 byte = 0xff;
484 fwrite(&byte, 1, 1, f);
485
486#if 0
487 if (psxRegs.cycle == 190230) {
488 dump_mem("/mnt/ntz/dev/pnd/tmp/psxram_i.dump", psxM, 0x200000);
489 dump_mem("/mnt/ntz/dev/pnd/tmp/psxregs_i.dump", psxH, 0x10000);
490 printf("dumped\n");
491 exit(1);
492 }
493#endif
494}
495
496static const char *regnames[offsetof(psxRegisters, intCycle) / 4] = {
497 "r0", "r1", "r2", "r3", "r4", "r5", "r6", "r7",
498 "r8", "r9", "r10", "r11", "r12", "r13", "r14", "r15",
499 "r16", "r17", "r18", "r19", "r20", "r21", "r22", "r23",
500 "r24", "r25", "r26", "r27", "r28", "r29", "r30", "r31",
501 "lo", "hi",
502 "C0_0", "C0_1", "C0_2", "C0_3", "C0_4", "C0_5", "C0_6", "C0_7",
503 "C0_8", "C0_9", "C0_10", "C0_11", "C0_12", "C0_13", "C0_14", "C0_15",
504 "C0_16", "C0_17", "C0_18", "C0_19", "C0_20", "C0_21", "C0_22", "C0_23",
505 "C0_24", "C0_25", "C0_26", "C0_27", "C0_28", "C0_29", "C0_30", "C0_31",
506
507 "C2D0", "C2D1", "C2D2", "C2D3", "C2D4", "C2D5", "C2D6", "C2D7",
508 "C2D8", "C2D9", "C2D10", "C2D11", "C2D12", "C2D13", "C2D14", "C2D15",
509 "C2D16", "C2D17", "C2D18", "C2D19", "C2D20", "C2D21", "C2D22", "C2D23",
510 "C2D24", "C2D25", "C2D26", "C2D27", "C2D28", "C2D29", "C2D30", "C2D31",
511
512 "C2C0", "C2C1", "C2C2", "C2C3", "C2C4", "C2C5", "C2C6", "C2C7",
513 "C2C8", "C2C9", "C2C10", "C2C11", "C2C12", "C2C13", "C2C14", "C2C15",
514 "C2C16", "C2C17", "C2C18", "C2C19", "C2C20", "C2C21", "C2C22", "C2C23",
515 "C2C24", "C2C25", "C2C26", "C2C27", "C2C28", "C2C29", "C2C30", "C2C31",
516
517 "PC", "code", "cycle", "interrupt",
518};
519
520static struct {
521 int reg;
522 u32 val, val_expect;
523 u32 pc, cycle;
524} miss_log[64];
525static int miss_log_i;
526#define miss_log_len (sizeof(miss_log)/sizeof(miss_log[0]))
527#define miss_log_mask (miss_log_len-1)
528
529static void miss_log_add(int reg, u32 val, u32 val_expect, u32 pc, u32 cycle)
530{
531 miss_log[miss_log_i].reg = reg;
532 miss_log[miss_log_i].val = val;
533 miss_log[miss_log_i].val_expect = val_expect;
534 miss_log[miss_log_i].pc = pc;
535 miss_log[miss_log_i].cycle = cycle;
536 miss_log_i = (miss_log_i + 1) & miss_log_mask;
537}
538
539void breakme() {}
540
541void do_insn_cmp(void)
542{
543 static psxRegisters rregs;
544 static u32 mem_addr, mem_val;
545 u32 *allregs_p = (void *)&psxRegs;
546 u32 *allregs_e = (void *)&rregs;
547 static u32 ppc, failcount;
548 int i, ret, bad = 0, which_event = -1;
549 u32 ev_cycles = 0;
550 u8 code;
551
552 if (f == NULL)
553 f = fopen("tracelog", "rb");
554
555 while (1) {
556 if ((ret = fread(&code, 1, 1, f)) <= 0)
557 break;
558 if (ret <= 0)
559 break;
560 if (code == 0xff)
561 break;
562 switch (code) {
563 case 0xfc:
564 which_event = 0;
565 fread(&which_event, 1, 1, f);
566 fread(&ev_cycles, 1, 4, f);
567 continue;
568 case 0xfd:
569 fread(&mem_addr, 1, 4, f);
570 continue;
571 case 0xfe:
572 fread(&mem_val, 1, 4, f);
573 continue;
574 }
575 fread(&allregs_e[code], 1, 4, f);
576 }
577
578 if (ret <= 0) {
579 printf("EOF?\n");
580 goto end;
581 }
582
583 psxRegs.code = rregs.code; // don't care
584 psxRegs.cycle = rregs.cycle;
585 psxRegs.CP0.r[9] = rregs.CP0.r[9]; // Count
586
587 //if (psxRegs.cycle == 166172) breakme();
588
589 if (memcmp(&psxRegs, &rregs, offsetof(psxRegisters, intCycle)) == 0 &&
590 mem_val == memcheck_read(mem_addr)
591 ) {
592 failcount = 0;
593 goto ok;
594 }
595
596 for (i = 0; i < offsetof(psxRegisters, intCycle) / 4; i++) {
597 if (allregs_p[i] != allregs_e[i]) {
598 miss_log_add(i, allregs_p[i], allregs_e[i], psxRegs.pc, psxRegs.cycle);
599 bad++;
600 }
601 }
602
603 if (mem_val != memcheck_read(mem_addr)) {
604 printf("bad mem @%08x: %08x %08x\n", mem_addr, memcheck_read(mem_addr), mem_val);
605 goto end;
606 }
607
608 if (which_event >= 0 && event_cycles[which_event] != ev_cycles) {
609 printf("bad ev_cycles #%d: %08x %08x\n", which_event, event_cycles[which_event], ev_cycles);
610 goto end;
611 }
612
613 if (psxRegs.pc == rregs.pc && bad < 6 && failcount < 32) {
614 static int last_mcycle;
615 if (last_mcycle != psxRegs.cycle >> 20) {
616 printf("%u\n", psxRegs.cycle);
617 last_mcycle = psxRegs.cycle >> 20;
618 }
619 failcount++;
620 goto ok;
621 }
622
623end:
624 for (i = 0; i < miss_log_len; i++, miss_log_i = (miss_log_i + 1) & miss_log_mask)
625 printf("bad %5s: %08x %08x, pc=%08x, cycle %u\n",
626 regnames[miss_log[miss_log_i].reg], miss_log[miss_log_i].val,
627 miss_log[miss_log_i].val_expect, miss_log[miss_log_i].pc, miss_log[miss_log_i].cycle);
628 printf("-- %d\n", bad);
629 for (i = 0; i < 8; i++)
630 printf("r%d=%08x r%2d=%08x r%2d=%08x r%2d=%08x\n", i, allregs_p[i],
631 i+8, allregs_p[i+8], i+16, allregs_p[i+16], i+24, allregs_p[i+24]);
632 printf("PC: %08x/%08x, cycle %u\n", psxRegs.pc, ppc, psxRegs.cycle);
633 dump_mem("/mnt/ntz/dev/pnd/tmp/psxram.dump", psxM, 0x200000);
634 dump_mem("/mnt/ntz/dev/pnd/tmp/psxregs.dump", psxH, 0x10000);
635 exit(1);
636ok:
637 psxRegs.cycle = rregs.cycle + 2; // sync timing
638 ppc = psxRegs.pc;
639}
640
641#endif