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