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