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