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