drc: adjust ld_use_hazard
[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 evprintf("ari64_execute %08x, %u->%u (%d)\n", psxRegs.pc,
252 psxRegs.cycle, next_interupt, next_interupt - psxRegs.cycle);
7139f3c8 253
be516ebe 254 new_dyna_start(dynarec_local);
654e8cfb 255
256 evprintf("ari64_execute end %08x, %u->%u (%d)\n", psxRegs.pc,
257 psxRegs.cycle, next_interupt, next_interupt - psxRegs.cycle);
f95a77f7 258}
259
e4eb18c1 260static void ari64_execute()
261{
262 while (!stop) {
dc4fa8bc 263 schedule_timeslice();
e4eb18c1 264 ari64_execute_until();
265 evprintf("drc left @%08x\n", psxRegs.pc);
266 }
267}
268
da65071f 269static void ari64_execute_block(enum blockExecCaller caller)
270{
271 if (caller == EXEC_CALLER_BOOT)
272 stop++;
273
dc4fa8bc 274 next_interupt = psxRegs.cycle + 1;
da65071f 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:
1da9b9ae 300 if (data == NULL)
301 ari64_reset();
90f98e7c 302 psxInt.Notify(note, data);
679d5ee3 303 break;
943a507a 304 }
943a507a 305}
943a507a 306
32631e6a 307static void ari64_apply_config()
308{
61ad2a61 309 intApplyConfig();
310
32631e6a 311 if (Config.DisableStalls)
312 new_dynarec_hacks |= NDHACK_NO_STALLS;
313 else
314 new_dynarec_hacks &= ~NDHACK_NO_STALLS;
315
d5aeda23 316 if (Config.cycle_multiplier != cycle_multiplier_old
32631e6a 317 || new_dynarec_hacks != new_dynarec_hacks_old)
318 {
319 new_dynarec_clear_full();
320 }
321}
322
f95a77f7 323static void ari64_shutdown()
324{
325 new_dynarec_cleanup();
92879b62 326 new_dyna_pcsx_mem_shutdown();
f95a77f7 327}
328
329R3000Acpu psxRec = {
330 ari64_init,
331 ari64_reset,
332 ari64_execute,
da65071f 333 ari64_execute_block,
f95a77f7 334 ari64_clear,
943a507a 335 ari64_notify,
32631e6a 336 ari64_apply_config,
f95a77f7 337 ari64_shutdown
338};
7139f3c8 339
d6348639 340#else // if DRC_DISABLE
7139f3c8 341
054175e9 342unsigned int address;
ccf51908 343int pending_exception, stop;
45a1e89f 344u32 next_interupt;
2f546f9a 345int new_dynarec_did_compile;
32631e6a 346int cycle_multiplier_old;
d62c125a 347int new_dynarec_hacks_pergame;
32631e6a 348int new_dynarec_hacks_old;
0ff8c62c 349int new_dynarec_hacks;
7e605697 350void *psxH_ptr;
054175e9 351void *zeromem_ptr;
679d5ee3 352u32 zero_mem[0x1000/4];
0069615f 353void *mem_rtab;
c6d5790c 354void *scratch_buf_ptr;
d6348639 355void new_dynarec_init() {}
be516ebe 356void new_dyna_start(void *context) {}
7139f3c8 357void new_dynarec_cleanup() {}
2c886904 358void new_dynarec_clear_full() {}
104df9d3 359void new_dynarec_invalidate_all_pages() {}
c8e482ed 360void new_dynarec_invalidate_range(unsigned int start, unsigned int end) {}
7e605697 361void new_dyna_pcsx_mem_init(void) {}
362void new_dyna_pcsx_mem_reset(void) {}
b1be1eee 363void new_dyna_pcsx_mem_load_state(void) {}
679d5ee3 364void new_dyna_pcsx_mem_isolate(int enable) {}
92879b62 365void new_dyna_pcsx_mem_shutdown(void) {}
03f55e6b 366int new_dynarec_save_blocks(void *save, int size) { return 0; }
367void new_dynarec_load_blocks(const void *save, int size) {}
7139f3c8 368#endif
369
370#ifdef DRC_DBG
371
372#include <stddef.h>
373static FILE *f;
2330734f 374u32 irq_test_cycle;
375u32 handler_cycle;
376u32 last_io_addr;
7139f3c8 377
079ab0c6 378void dump_mem(const char *fname, void *mem, size_t size)
7139f3c8 379{
380 FILE *f1 = fopen(fname, "wb");
3eb78778 381 if (f1 == NULL)
382 f1 = fopen(strrchr(fname, '/') + 1, "wb");
7139f3c8 383 fwrite(mem, 1, size, f1);
384 fclose(f1);
385}
386
2185e39b 387static u32 memcheck_read(u32 a)
388{
389 if ((a >> 16) == 0x1f80)
390 // scratchpad/IO
391 return *(u32 *)(psxH + (a & 0xfffc));
392
393 if ((a >> 16) == 0x1f00)
394 // parallel
395 return *(u32 *)(psxP + (a & 0xfffc));
396
397// if ((a & ~0xe0600000) < 0x200000)
398 // RAM
399 return *(u32 *)(psxM + (a & 0x1ffffc));
400}
401
dd114d7d 402#if 0
7139f3c8 403void do_insn_trace(void)
404{
405 static psxRegisters oldregs;
19776aef 406 static u32 event_cycles_o[PSXINT_COUNT];
7139f3c8 407 u32 *allregs_p = (void *)&psxRegs;
408 u32 *allregs_o = (void *)&oldregs;
2185e39b 409 u32 io_data;
7139f3c8 410 int i;
411 u8 byte;
412
19776aef 413 //last_io_addr = 0x5e2c8;
7139f3c8 414 if (f == NULL)
415 f = fopen("tracelog", "wb");
416
19776aef 417 // log reg changes
7139f3c8 418 oldregs.code = psxRegs.code; // don't care
419 for (i = 0; i < offsetof(psxRegisters, intCycle) / 4; i++) {
420 if (allregs_p[i] != allregs_o[i]) {
421 fwrite(&i, 1, 1, f);
422 fwrite(&allregs_p[i], 1, 4, f);
423 allregs_o[i] = allregs_p[i];
424 }
425 }
19776aef 426 // log event changes
427 for (i = 0; i < PSXINT_COUNT; i++) {
428 if (event_cycles[i] != event_cycles_o[i]) {
2330734f 429 byte = 0xf8;
19776aef 430 fwrite(&byte, 1, 1, f);
431 fwrite(&i, 1, 1, f);
432 fwrite(&event_cycles[i], 1, 4, f);
433 event_cycles_o[i] = event_cycles[i];
434 }
435 }
2330734f 436 #define SAVE_IF_CHANGED(code_, name_) { \
437 static u32 old_##name_ = 0xbad0c0de; \
438 if (old_##name_ != name_) { \
439 byte = code_; \
440 fwrite(&byte, 1, 1, f); \
441 fwrite(&name_, 1, 4, f); \
442 old_##name_ = name_; \
443 } \
7139f3c8 444 }
2330734f 445 SAVE_IF_CHANGED(0xfb, irq_test_cycle);
446 SAVE_IF_CHANGED(0xfc, handler_cycle);
447 SAVE_IF_CHANGED(0xfd, last_io_addr);
2185e39b 448 io_data = memcheck_read(last_io_addr);
2330734f 449 SAVE_IF_CHANGED(0xfe, io_data);
7139f3c8 450 byte = 0xff;
451 fwrite(&byte, 1, 1, f);
452
453#if 0
454 if (psxRegs.cycle == 190230) {
455 dump_mem("/mnt/ntz/dev/pnd/tmp/psxram_i.dump", psxM, 0x200000);
456 dump_mem("/mnt/ntz/dev/pnd/tmp/psxregs_i.dump", psxH, 0x10000);
457 printf("dumped\n");
458 exit(1);
459 }
460#endif
461}
dd114d7d 462#endif
7139f3c8 463
464static const char *regnames[offsetof(psxRegisters, intCycle) / 4] = {
465 "r0", "r1", "r2", "r3", "r4", "r5", "r6", "r7",
466 "r8", "r9", "r10", "r11", "r12", "r13", "r14", "r15",
467 "r16", "r17", "r18", "r19", "r20", "r21", "r22", "r23",
468 "r24", "r25", "r26", "r27", "r28", "r29", "r30", "r31",
469 "lo", "hi",
470 "C0_0", "C0_1", "C0_2", "C0_3", "C0_4", "C0_5", "C0_6", "C0_7",
471 "C0_8", "C0_9", "C0_10", "C0_11", "C0_12", "C0_13", "C0_14", "C0_15",
472 "C0_16", "C0_17", "C0_18", "C0_19", "C0_20", "C0_21", "C0_22", "C0_23",
473 "C0_24", "C0_25", "C0_26", "C0_27", "C0_28", "C0_29", "C0_30", "C0_31",
474
475 "C2D0", "C2D1", "C2D2", "C2D3", "C2D4", "C2D5", "C2D6", "C2D7",
476 "C2D8", "C2D9", "C2D10", "C2D11", "C2D12", "C2D13", "C2D14", "C2D15",
477 "C2D16", "C2D17", "C2D18", "C2D19", "C2D20", "C2D21", "C2D22", "C2D23",
478 "C2D24", "C2D25", "C2D26", "C2D27", "C2D28", "C2D29", "C2D30", "C2D31",
479
480 "C2C0", "C2C1", "C2C2", "C2C3", "C2C4", "C2C5", "C2C6", "C2C7",
481 "C2C8", "C2C9", "C2C10", "C2C11", "C2C12", "C2C13", "C2C14", "C2C15",
482 "C2C16", "C2C17", "C2C18", "C2C19", "C2C20", "C2C21", "C2C22", "C2C23",
483 "C2C24", "C2C25", "C2C26", "C2C27", "C2C28", "C2C29", "C2C30", "C2C31",
484
485 "PC", "code", "cycle", "interrupt",
486};
487
3eb78778 488static struct {
489 int reg;
490 u32 val, val_expect;
491 u32 pc, cycle;
492} miss_log[64];
493static int miss_log_i;
494#define miss_log_len (sizeof(miss_log)/sizeof(miss_log[0]))
495#define miss_log_mask (miss_log_len-1)
496
497static void miss_log_add(int reg, u32 val, u32 val_expect, u32 pc, u32 cycle)
498{
499 miss_log[miss_log_i].reg = reg;
500 miss_log[miss_log_i].val = val;
501 miss_log[miss_log_i].val_expect = val_expect;
502 miss_log[miss_log_i].pc = pc;
503 miss_log[miss_log_i].cycle = cycle;
504 miss_log_i = (miss_log_i + 1) & miss_log_mask;
505}
506
7139f3c8 507void breakme() {}
508
509void do_insn_cmp(void)
510{
2330734f 511 extern int last_count;
7139f3c8 512 static psxRegisters rregs;
513 static u32 mem_addr, mem_val;
2330734f 514 static u32 irq_test_cycle_intr;
515 static u32 handler_cycle_intr;
7139f3c8 516 u32 *allregs_p = (void *)&psxRegs;
517 u32 *allregs_e = (void *)&rregs;
ecca05e3 518 u32 badregs_mask = 0;
7139f3c8 519 static u32 ppc, failcount;
ecca05e3 520 static u32 badregs_mask_prev;
2330734f 521 int i, ret, bad = 0, fatal = 0, which_event = -1;
19776aef 522 u32 ev_cycles = 0;
7139f3c8 523 u8 code;
524
525 if (f == NULL)
526 f = fopen("tracelog", "rb");
527
528 while (1) {
529 if ((ret = fread(&code, 1, 1, f)) <= 0)
530 break;
531 if (ret <= 0)
532 break;
533 if (code == 0xff)
534 break;
19776aef 535 switch (code) {
2330734f 536 case 0xf8:
19776aef 537 which_event = 0;
538 fread(&which_event, 1, 1, f);
539 fread(&ev_cycles, 1, 4, f);
7139f3c8 540 continue;
2330734f 541 case 0xfb:
542 fread(&irq_test_cycle_intr, 1, 4, f);
543 continue;
544 case 0xfc:
545 fread(&handler_cycle_intr, 1, 4, f);
546 continue;
19776aef 547 case 0xfd:
548 fread(&mem_addr, 1, 4, f);
549 continue;
550 case 0xfe:
551 fread(&mem_val, 1, 4, f);
7139f3c8 552 continue;
553 }
2330734f 554 assert(code < offsetof(psxRegisters, intCycle) / 4);
19776aef 555 fread(&allregs_e[code], 1, 4, f);
7139f3c8 556 }
557
558 if (ret <= 0) {
559 printf("EOF?\n");
2330734f 560 exit(1);
7139f3c8 561 }
562
563 psxRegs.code = rregs.code; // don't care
2330734f 564 psxRegs.cycle += last_count;
079ab0c6 565 //psxRegs.cycle = rregs.cycle; // needs reload in _cmp
2185e39b 566 psxRegs.CP0.r[9] = rregs.CP0.r[9]; // Count
7139f3c8 567
19776aef 568 //if (psxRegs.cycle == 166172) breakme();
7139f3c8 569
2330734f 570 if (which_event >= 0 && event_cycles[which_event] != ev_cycles) {
55a695d9 571 printf("bad ev_cycles #%d: %u %u / %u\n", which_event,
572 event_cycles[which_event], ev_cycles, psxRegs.cycle);
2330734f 573 fatal = 1;
574 }
575
576 if (irq_test_cycle > irq_test_cycle_intr) {
577 printf("bad irq_test_cycle: %u %u\n", irq_test_cycle, irq_test_cycle_intr);
578 fatal = 1;
579 }
580
581 if (handler_cycle != handler_cycle_intr) {
582 printf("bad handler_cycle: %u %u\n", handler_cycle, handler_cycle_intr);
583 fatal = 1;
584 }
585
586 if (mem_val != memcheck_read(mem_addr)) {
587 printf("bad mem @%08x: %08x %08x\n", mem_addr, memcheck_read(mem_addr), mem_val);
588 fatal = 1;
589 }
590
591 if (!fatal && !memcmp(&psxRegs, &rregs, offsetof(psxRegisters, intCycle))) {
7139f3c8 592 failcount = 0;
593 goto ok;
594 }
595
596 for (i = 0; i < offsetof(psxRegisters, intCycle) / 4; i++) {
597 if (allregs_p[i] != allregs_e[i]) {
3eb78778 598 miss_log_add(i, allregs_p[i], allregs_e[i], psxRegs.pc, psxRegs.cycle);
7139f3c8 599 bad++;
ecca05e3 600 if (i >= 32)
2330734f 601 fatal = 1;
ecca05e3 602 else
603 badregs_mask |= 1u << i;
7139f3c8 604 }
605 }
606
ecca05e3 607 if (badregs_mask_prev & badregs_mask)
608 failcount++;
609 else
610 failcount = 0;
611
612 if (!fatal && psxRegs.pc == rregs.pc && bad < 6 && failcount < 24) {
3eb78778 613 static int last_mcycle;
614 if (last_mcycle != psxRegs.cycle >> 20) {
615 printf("%u\n", psxRegs.cycle);
616 last_mcycle = psxRegs.cycle >> 20;
617 }
7139f3c8 618 goto ok;
619 }
620
3eb78778 621 for (i = 0; i < miss_log_len; i++, miss_log_i = (miss_log_i + 1) & miss_log_mask)
622 printf("bad %5s: %08x %08x, pc=%08x, cycle %u\n",
623 regnames[miss_log[miss_log_i].reg], miss_log[miss_log_i].val,
624 miss_log[miss_log_i].val_expect, miss_log[miss_log_i].pc, miss_log[miss_log_i].cycle);
625 printf("-- %d\n", bad);
626 for (i = 0; i < 8; i++)
627 printf("r%d=%08x r%2d=%08x r%2d=%08x r%2d=%08x\n", i, allregs_p[i],
87c06e51 628 i+8, allregs_p[i+8], i+16, allregs_p[i+16], i+24, allregs_p[i+24]);
079ab0c6 629 printf("PC: %08x/%08x, cycle %u, next %u\n", psxRegs.pc, ppc, psxRegs.cycle, next_interupt);
630 //dump_mem("/tmp/psxram.dump", psxM, 0x200000);
631 //dump_mem("/mnt/ntz/dev/pnd/tmp/psxregs.dump", psxH, 0x10000);
7139f3c8 632 exit(1);
633ok:
2330734f 634 //psxRegs.cycle = rregs.cycle + 2; // sync timing
7139f3c8 635 ppc = psxRegs.pc;
ecca05e3 636 badregs_mask_prev = badregs_mask;
7139f3c8 637}
638
639#endif