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