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