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