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