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