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