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