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"
6c62131f 12#include "events.h"
630b122b 13#include "../psxhle.h"
14#include "../psxinterpreter.h"
584fc319 15#include "../psxcounters.h"
630b122b 16#include "../r3000a.h"
630b122b 17#include "../gte_arm.h"
18#include "../gte_neon.h"
59774ed0 19#define FLAGLESS
630b122b 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);
cab87bf3 30 MTC0(&psxRegs, reg, val);
6c62131f 31 gen_interupt(&psxRegs.CP0);
5753f874 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);
cab87bf3 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
630b122b 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
630b122b 102#if !defined(DRC_DISABLE) && !defined(LIGHTREC)
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{
630b122b 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++)
cab87bf3 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();
048fcced 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
630b122b 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) {
9415f066 264 schedule_timeslice();
e4eb18c1 265 ari64_execute_until();
266 evprintf("drc left @%08x\n", psxRegs.pc);
267 }
268}
269
f3bc907d 270static void ari64_execute_block(enum blockExecCaller caller)
271{
272 if (caller == EXEC_CALLER_BOOT)
273 stop++;
274
9415f066 275 next_interupt = psxRegs.cycle + 1;
f3bc907d 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
048fcced 288 new_dynarec_invalidate_range(addr, addr + size);
f95a77f7 289}
290
20196899 291static void ari64_notify(enum R3000Anote note, void *data) {
7a811716 292 switch (note)
293 {
c6b7420b 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;
20196899 298 case R3000ACPU_NOTIFY_BEFORE_SAVE:
299 break;
300 case R3000ACPU_NOTIFY_AFTER_LOAD:
ec4baa7d 301 if (data == NULL)
302 ari64_reset();
b4661440 303 psxInt.Notify(note, data);
c6b7420b 304 break;
630b122b 305 }
630b122b 306}
307
308static void ari64_apply_config()
309{
310 intApplyConfig();
311
312 if (Config.DisableStalls)
313 new_dynarec_hacks |= NDHACK_NO_STALLS;
314 else
315 new_dynarec_hacks &= ~NDHACK_NO_STALLS;
316
1562ed57 317 if (Config.cycle_multiplier != cycle_multiplier_old
630b122b 318 || new_dynarec_hacks != new_dynarec_hacks_old)
319 {
320 new_dynarec_clear_full();
321 }
7a811716 322}
7a811716 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,
f3bc907d 334 ari64_execute_block,
f95a77f7 335 ari64_clear,
7a811716 336 ari64_notify,
630b122b 337 ari64_apply_config,
f95a77f7 338 ari64_shutdown
339};
7139f3c8 340
630b122b 341#else // if DRC_DISABLE
7139f3c8 342
054175e9 343unsigned int address;
ccf51908 344int pending_exception, stop;
67cbfa7b 345u32 next_interupt;
2f546f9a 346int new_dynarec_did_compile;
630b122b 347int cycle_multiplier_old;
348int new_dynarec_hacks_pergame;
349int new_dynarec_hacks_old;
0ff8c62c 350int new_dynarec_hacks;
7e605697 351void *psxH_ptr;
054175e9 352void *zeromem_ptr;
c6b7420b 353u32 zero_mem[0x1000/4];
0069615f 354void *mem_rtab;
c6d5790c 355void *scratch_buf_ptr;
630b122b 356void new_dynarec_init() {}
357void new_dyna_start(void *context) {}
7139f3c8 358void new_dynarec_cleanup() {}
2c886904 359void new_dynarec_clear_full() {}
048fcced 360void new_dynarec_invalidate_all_pages() {}
bd298778 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) {}
c6b7420b 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;
630b122b 375u32 irq_test_cycle;
376u32 handler_cycle;
377u32 last_io_addr;
7139f3c8 378
c1c88a12 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
630b122b 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]) {
630b122b 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 }
630b122b 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 }
630b122b 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);
630b122b 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}
630b122b 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{
630b122b 512 extern int last_count;
7139f3c8 513 static psxRegisters rregs;
514 static u32 mem_addr, mem_val;
630b122b 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;
3a64d2f7 519 u32 badregs_mask = 0;
7139f3c8 520 static u32 ppc, failcount;
3a64d2f7 521 static u32 badregs_mask_prev;
630b122b 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) {
630b122b 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;
630b122b 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 }
630b122b 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");
630b122b 561 exit(1);
7139f3c8 562 }
563
564 psxRegs.code = rregs.code; // don't care
630b122b 565 psxRegs.cycle += last_count;
c1c88a12 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
630b122b 571 if (which_event >= 0 && event_cycles[which_event] != ev_cycles) {
a6905f16 572 printf("bad ev_cycles #%d: %u %u / %u\n", which_event,
573 event_cycles[which_event], ev_cycles, psxRegs.cycle);
630b122b 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++;
3a64d2f7 601 if (i >= 32)
630b122b 602 fatal = 1;
3a64d2f7 603 else
604 badregs_mask |= 1u << i;
7139f3c8 605 }
606 }
607
3a64d2f7 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]);
c1c88a12 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:
630b122b 635 //psxRegs.cycle = rregs.cycle + 2; // sync timing
7139f3c8 636 ppc = psxRegs.pc;
3a64d2f7 637 badregs_mask_prev = badregs_mask;
7139f3c8 638}
639
640#endif