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