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