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