mave plugin and core shared includes to single location
[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
82ed88eb 271#if !defined(DRC_DBG)
59774ed0 272#ifdef __arm__
273 gte_handlers[0x06] = gteNCLIP_arm;
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();
347}
348
7139f3c8 349extern void intExecute();
350extern void intExecuteT();
351extern void intExecuteBlock();
352extern void intExecuteBlockT();
353#ifndef DRC_DBG
354#define intExecuteT intExecute
355#define intExecuteBlockT intExecuteBlock
356#endif
357
f95a77f7 358R3000Acpu psxRec = {
359 ari64_init,
360 ari64_reset,
448bbcae 361#ifndef DRC_DISABLE
f95a77f7 362 ari64_execute,
e4eb18c1 363 ari64_execute_until,
7139f3c8 364#else
365 intExecuteT,
366 intExecuteBlockT,
367#endif
f95a77f7 368 ari64_clear,
369 ari64_shutdown
370};
7139f3c8 371
372// TODO: rm
373#ifndef DRC_DBG
374void do_insn_trace() {}
375void do_insn_cmp() {}
376#endif
377
448bbcae 378#ifdef DRC_DISABLE
054175e9 379unsigned int address;
ccf51908 380int pending_exception, stop;
7139f3c8 381unsigned int next_interupt;
2f546f9a 382int new_dynarec_did_compile;
2573466a 383int cycle_multiplier;
0ff8c62c 384int new_dynarec_hacks;
7e605697 385void *psxH_ptr;
054175e9 386void *zeromem_ptr;
387u8 zero_mem[0x1000];
448bbcae 388void new_dynarec_init() { (void)ari64_execute; }
3eb78778 389void new_dyna_start() {}
7139f3c8 390void new_dynarec_cleanup() {}
2c886904 391void new_dynarec_clear_full() {}
ccf51908 392void invalidate_all_pages() {}
393void invalidate_block(unsigned int block) {}
7e605697 394void new_dyna_pcsx_mem_init(void) {}
395void new_dyna_pcsx_mem_reset(void) {}
b1be1eee 396void new_dyna_pcsx_mem_load_state(void) {}
7139f3c8 397#endif
398
399#ifdef DRC_DBG
400
401#include <stddef.h>
402static FILE *f;
403extern u32 last_io_addr;
404
405static void dump_mem(const char *fname, void *mem, size_t size)
406{
407 FILE *f1 = fopen(fname, "wb");
3eb78778 408 if (f1 == NULL)
409 f1 = fopen(strrchr(fname, '/') + 1, "wb");
7139f3c8 410 fwrite(mem, 1, size, f1);
411 fclose(f1);
412}
413
2185e39b 414static u32 memcheck_read(u32 a)
415{
416 if ((a >> 16) == 0x1f80)
417 // scratchpad/IO
418 return *(u32 *)(psxH + (a & 0xfffc));
419
420 if ((a >> 16) == 0x1f00)
421 // parallel
422 return *(u32 *)(psxP + (a & 0xfffc));
423
424// if ((a & ~0xe0600000) < 0x200000)
425 // RAM
426 return *(u32 *)(psxM + (a & 0x1ffffc));
427}
428
7139f3c8 429void do_insn_trace(void)
430{
431 static psxRegisters oldregs;
432 static u32 old_io_addr = (u32)-1;
433 static u32 old_io_data = 0xbad0c0de;
19776aef 434 static u32 event_cycles_o[PSXINT_COUNT];
7139f3c8 435 u32 *allregs_p = (void *)&psxRegs;
436 u32 *allregs_o = (void *)&oldregs;
2185e39b 437 u32 io_data;
7139f3c8 438 int i;
439 u8 byte;
440
19776aef 441 //last_io_addr = 0x5e2c8;
7139f3c8 442 if (f == NULL)
443 f = fopen("tracelog", "wb");
444
19776aef 445 // log reg changes
7139f3c8 446 oldregs.code = psxRegs.code; // don't care
447 for (i = 0; i < offsetof(psxRegisters, intCycle) / 4; i++) {
448 if (allregs_p[i] != allregs_o[i]) {
449 fwrite(&i, 1, 1, f);
450 fwrite(&allregs_p[i], 1, 4, f);
451 allregs_o[i] = allregs_p[i];
452 }
453 }
19776aef 454 // log event changes
455 for (i = 0; i < PSXINT_COUNT; i++) {
456 if (event_cycles[i] != event_cycles_o[i]) {
457 byte = 0xfc;
458 fwrite(&byte, 1, 1, f);
459 fwrite(&i, 1, 1, f);
460 fwrite(&event_cycles[i], 1, 4, f);
461 event_cycles_o[i] = event_cycles[i];
462 }
463 }
464 // log last io
7139f3c8 465 if (old_io_addr != last_io_addr) {
466 byte = 0xfd;
467 fwrite(&byte, 1, 1, f);
468 fwrite(&last_io_addr, 1, 4, f);
469 old_io_addr = last_io_addr;
470 }
2185e39b 471 io_data = memcheck_read(last_io_addr);
472 if (old_io_data != io_data) {
7139f3c8 473 byte = 0xfe;
474 fwrite(&byte, 1, 1, f);
2185e39b 475 fwrite(&io_data, 1, 4, f);
476 old_io_data = io_data;
7139f3c8 477 }
478 byte = 0xff;
479 fwrite(&byte, 1, 1, f);
480
481#if 0
482 if (psxRegs.cycle == 190230) {
483 dump_mem("/mnt/ntz/dev/pnd/tmp/psxram_i.dump", psxM, 0x200000);
484 dump_mem("/mnt/ntz/dev/pnd/tmp/psxregs_i.dump", psxH, 0x10000);
485 printf("dumped\n");
486 exit(1);
487 }
488#endif
489}
490
491static const char *regnames[offsetof(psxRegisters, intCycle) / 4] = {
492 "r0", "r1", "r2", "r3", "r4", "r5", "r6", "r7",
493 "r8", "r9", "r10", "r11", "r12", "r13", "r14", "r15",
494 "r16", "r17", "r18", "r19", "r20", "r21", "r22", "r23",
495 "r24", "r25", "r26", "r27", "r28", "r29", "r30", "r31",
496 "lo", "hi",
497 "C0_0", "C0_1", "C0_2", "C0_3", "C0_4", "C0_5", "C0_6", "C0_7",
498 "C0_8", "C0_9", "C0_10", "C0_11", "C0_12", "C0_13", "C0_14", "C0_15",
499 "C0_16", "C0_17", "C0_18", "C0_19", "C0_20", "C0_21", "C0_22", "C0_23",
500 "C0_24", "C0_25", "C0_26", "C0_27", "C0_28", "C0_29", "C0_30", "C0_31",
501
502 "C2D0", "C2D1", "C2D2", "C2D3", "C2D4", "C2D5", "C2D6", "C2D7",
503 "C2D8", "C2D9", "C2D10", "C2D11", "C2D12", "C2D13", "C2D14", "C2D15",
504 "C2D16", "C2D17", "C2D18", "C2D19", "C2D20", "C2D21", "C2D22", "C2D23",
505 "C2D24", "C2D25", "C2D26", "C2D27", "C2D28", "C2D29", "C2D30", "C2D31",
506
507 "C2C0", "C2C1", "C2C2", "C2C3", "C2C4", "C2C5", "C2C6", "C2C7",
508 "C2C8", "C2C9", "C2C10", "C2C11", "C2C12", "C2C13", "C2C14", "C2C15",
509 "C2C16", "C2C17", "C2C18", "C2C19", "C2C20", "C2C21", "C2C22", "C2C23",
510 "C2C24", "C2C25", "C2C26", "C2C27", "C2C28", "C2C29", "C2C30", "C2C31",
511
512 "PC", "code", "cycle", "interrupt",
513};
514
3eb78778 515static struct {
516 int reg;
517 u32 val, val_expect;
518 u32 pc, cycle;
519} miss_log[64];
520static int miss_log_i;
521#define miss_log_len (sizeof(miss_log)/sizeof(miss_log[0]))
522#define miss_log_mask (miss_log_len-1)
523
524static void miss_log_add(int reg, u32 val, u32 val_expect, u32 pc, u32 cycle)
525{
526 miss_log[miss_log_i].reg = reg;
527 miss_log[miss_log_i].val = val;
528 miss_log[miss_log_i].val_expect = val_expect;
529 miss_log[miss_log_i].pc = pc;
530 miss_log[miss_log_i].cycle = cycle;
531 miss_log_i = (miss_log_i + 1) & miss_log_mask;
532}
533
7139f3c8 534void breakme() {}
535
536void do_insn_cmp(void)
537{
538 static psxRegisters rregs;
539 static u32 mem_addr, mem_val;
540 u32 *allregs_p = (void *)&psxRegs;
541 u32 *allregs_e = (void *)&rregs;
542 static u32 ppc, failcount;
19776aef 543 int i, ret, bad = 0, which_event = -1;
544 u32 ev_cycles = 0;
7139f3c8 545 u8 code;
546
547 if (f == NULL)
548 f = fopen("tracelog", "rb");
549
550 while (1) {
551 if ((ret = fread(&code, 1, 1, f)) <= 0)
552 break;
553 if (ret <= 0)
554 break;
555 if (code == 0xff)
556 break;
19776aef 557 switch (code) {
558 case 0xfc:
559 which_event = 0;
560 fread(&which_event, 1, 1, f);
561 fread(&ev_cycles, 1, 4, f);
7139f3c8 562 continue;
19776aef 563 case 0xfd:
564 fread(&mem_addr, 1, 4, f);
565 continue;
566 case 0xfe:
567 fread(&mem_val, 1, 4, f);
7139f3c8 568 continue;
569 }
19776aef 570 fread(&allregs_e[code], 1, 4, f);
7139f3c8 571 }
572
573 if (ret <= 0) {
574 printf("EOF?\n");
575 goto end;
576 }
577
578 psxRegs.code = rregs.code; // don't care
2185e39b 579 psxRegs.cycle = rregs.cycle;
580 psxRegs.CP0.r[9] = rregs.CP0.r[9]; // Count
7139f3c8 581
19776aef 582 //if (psxRegs.cycle == 166172) breakme();
7139f3c8 583
584 if (memcmp(&psxRegs, &rregs, offsetof(psxRegisters, intCycle)) == 0 &&
2185e39b 585 mem_val == memcheck_read(mem_addr)
7139f3c8 586 ) {
587 failcount = 0;
588 goto ok;
589 }
590
591 for (i = 0; i < offsetof(psxRegisters, intCycle) / 4; i++) {
592 if (allregs_p[i] != allregs_e[i]) {
3eb78778 593 miss_log_add(i, allregs_p[i], allregs_e[i], psxRegs.pc, psxRegs.cycle);
7139f3c8 594 bad++;
595 }
596 }
597
2185e39b 598 if (mem_val != memcheck_read(mem_addr)) {
599 printf("bad mem @%08x: %08x %08x\n", mem_addr, memcheck_read(mem_addr), mem_val);
7139f3c8 600 goto end;
19776aef 601 }
602
603 if (which_event >= 0 && event_cycles[which_event] != ev_cycles) {
604 printf("bad ev_cycles #%d: %08x %08x\n", which_event, event_cycles[which_event], ev_cycles);
605 goto end;
7139f3c8 606 }
607
608 if (psxRegs.pc == rregs.pc && bad < 6 && failcount < 32) {
3eb78778 609 static int last_mcycle;
610 if (last_mcycle != psxRegs.cycle >> 20) {
611 printf("%u\n", psxRegs.cycle);
612 last_mcycle = psxRegs.cycle >> 20;
613 }
7139f3c8 614 failcount++;
615 goto ok;
616 }
617
618end:
3eb78778 619 for (i = 0; i < miss_log_len; i++, miss_log_i = (miss_log_i + 1) & miss_log_mask)
620 printf("bad %5s: %08x %08x, pc=%08x, cycle %u\n",
621 regnames[miss_log[miss_log_i].reg], miss_log[miss_log_i].val,
622 miss_log[miss_log_i].val_expect, miss_log[miss_log_i].pc, miss_log[miss_log_i].cycle);
623 printf("-- %d\n", bad);
624 for (i = 0; i < 8; i++)
625 printf("r%d=%08x r%2d=%08x r%2d=%08x r%2d=%08x\n", i, allregs_p[i],
87c06e51 626 i+8, allregs_p[i+8], i+16, allregs_p[i+16], i+24, allregs_p[i+24]);
7139f3c8 627 printf("PC: %08x/%08x, cycle %u\n", psxRegs.pc, ppc, psxRegs.cycle);
628 dump_mem("/mnt/ntz/dev/pnd/tmp/psxram.dump", psxM, 0x200000);
629 dump_mem("/mnt/ntz/dev/pnd/tmp/psxregs.dump", psxH, 0x10000);
630 exit(1);
631ok:
632 psxRegs.cycle = rregs.cycle + 2; // sync timing
633 ppc = psxRegs.pc;
634}
635
636#endif