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