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