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