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