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