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