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