Merge pull request #292 from pcercuei/dfsound-big-endian
[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 switch (note)
374 {
375 case R3000ACPU_NOTIFY_CACHE_UNISOLATED:
376 case R3000ACPU_NOTIFY_CACHE_ISOLATED:
377 new_dyna_pcsx_mem_isolate(note == R3000ACPU_NOTIFY_CACHE_ISOLATED);
378 break;
379 default:
380 break;
381 }
382}
383
384static void ari64_apply_config()
385{
386 intApplyConfig();
387
388 if (Config.DisableStalls)
389 new_dynarec_hacks |= NDHACK_NO_STALLS;
390 else
391 new_dynarec_hacks &= ~NDHACK_NO_STALLS;
392
393 if (Config.cycle_multiplier != cycle_multiplier_old
394 || new_dynarec_hacks != new_dynarec_hacks_old)
395 {
396 new_dynarec_clear_full();
397 }
398}
399
400static void ari64_shutdown()
401{
402 new_dynarec_cleanup();
403 new_dyna_pcsx_mem_shutdown();
404}
405
406R3000Acpu psxRec = {
407 ari64_init,
408 ari64_reset,
409 ari64_execute,
410 ari64_execute_until,
411 ari64_clear,
412 ari64_notify,
413 ari64_apply_config,
414 ari64_shutdown
415};
416
417#else // if DRC_DISABLE
418
419unsigned int address;
420int pending_exception, stop;
421unsigned int next_interupt;
422int new_dynarec_did_compile;
423int cycle_multiplier_old;
424int new_dynarec_hacks_pergame;
425int new_dynarec_hacks_old;
426int new_dynarec_hacks;
427void *psxH_ptr;
428void *zeromem_ptr;
429u32 zero_mem[0x1000/4];
430void *mem_rtab;
431void *scratch_buf_ptr;
432void new_dynarec_init() {}
433void new_dyna_start(void *context) {}
434void new_dynarec_cleanup() {}
435void new_dynarec_clear_full() {}
436void new_dynarec_invalidate_all_pages() {}
437void new_dynarec_invalidate_range(unsigned int start, unsigned int end) {}
438void new_dyna_pcsx_mem_init(void) {}
439void new_dyna_pcsx_mem_reset(void) {}
440void new_dyna_pcsx_mem_load_state(void) {}
441void new_dyna_pcsx_mem_isolate(int enable) {}
442void new_dyna_pcsx_mem_shutdown(void) {}
443int new_dynarec_save_blocks(void *save, int size) { return 0; }
444void new_dynarec_load_blocks(const void *save, int size) {}
445#endif
446
447#ifdef DRC_DBG
448
449#include <stddef.h>
450static FILE *f;
451u32 irq_test_cycle;
452u32 handler_cycle;
453u32 last_io_addr;
454
455void dump_mem(const char *fname, void *mem, size_t size)
456{
457 FILE *f1 = fopen(fname, "wb");
458 if (f1 == NULL)
459 f1 = fopen(strrchr(fname, '/') + 1, "wb");
460 fwrite(mem, 1, size, f1);
461 fclose(f1);
462}
463
464static u32 memcheck_read(u32 a)
465{
466 if ((a >> 16) == 0x1f80)
467 // scratchpad/IO
468 return *(u32 *)(psxH + (a & 0xfffc));
469
470 if ((a >> 16) == 0x1f00)
471 // parallel
472 return *(u32 *)(psxP + (a & 0xfffc));
473
474// if ((a & ~0xe0600000) < 0x200000)
475 // RAM
476 return *(u32 *)(psxM + (a & 0x1ffffc));
477}
478
479#if 0
480void do_insn_trace(void)
481{
482 static psxRegisters oldregs;
483 static u32 event_cycles_o[PSXINT_COUNT];
484 u32 *allregs_p = (void *)&psxRegs;
485 u32 *allregs_o = (void *)&oldregs;
486 u32 io_data;
487 int i;
488 u8 byte;
489
490 //last_io_addr = 0x5e2c8;
491 if (f == NULL)
492 f = fopen("tracelog", "wb");
493
494 // log reg changes
495 oldregs.code = psxRegs.code; // don't care
496 for (i = 0; i < offsetof(psxRegisters, intCycle) / 4; i++) {
497 if (allregs_p[i] != allregs_o[i]) {
498 fwrite(&i, 1, 1, f);
499 fwrite(&allregs_p[i], 1, 4, f);
500 allregs_o[i] = allregs_p[i];
501 }
502 }
503 // log event changes
504 for (i = 0; i < PSXINT_COUNT; i++) {
505 if (event_cycles[i] != event_cycles_o[i]) {
506 byte = 0xf8;
507 fwrite(&byte, 1, 1, f);
508 fwrite(&i, 1, 1, f);
509 fwrite(&event_cycles[i], 1, 4, f);
510 event_cycles_o[i] = event_cycles[i];
511 }
512 }
513 #define SAVE_IF_CHANGED(code_, name_) { \
514 static u32 old_##name_ = 0xbad0c0de; \
515 if (old_##name_ != name_) { \
516 byte = code_; \
517 fwrite(&byte, 1, 1, f); \
518 fwrite(&name_, 1, 4, f); \
519 old_##name_ = name_; \
520 } \
521 }
522 SAVE_IF_CHANGED(0xfb, irq_test_cycle);
523 SAVE_IF_CHANGED(0xfc, handler_cycle);
524 SAVE_IF_CHANGED(0xfd, last_io_addr);
525 io_data = memcheck_read(last_io_addr);
526 SAVE_IF_CHANGED(0xfe, io_data);
527 byte = 0xff;
528 fwrite(&byte, 1, 1, f);
529
530#if 0
531 if (psxRegs.cycle == 190230) {
532 dump_mem("/mnt/ntz/dev/pnd/tmp/psxram_i.dump", psxM, 0x200000);
533 dump_mem("/mnt/ntz/dev/pnd/tmp/psxregs_i.dump", psxH, 0x10000);
534 printf("dumped\n");
535 exit(1);
536 }
537#endif
538}
539#endif
540
541static const char *regnames[offsetof(psxRegisters, intCycle) / 4] = {
542 "r0", "r1", "r2", "r3", "r4", "r5", "r6", "r7",
543 "r8", "r9", "r10", "r11", "r12", "r13", "r14", "r15",
544 "r16", "r17", "r18", "r19", "r20", "r21", "r22", "r23",
545 "r24", "r25", "r26", "r27", "r28", "r29", "r30", "r31",
546 "lo", "hi",
547 "C0_0", "C0_1", "C0_2", "C0_3", "C0_4", "C0_5", "C0_6", "C0_7",
548 "C0_8", "C0_9", "C0_10", "C0_11", "C0_12", "C0_13", "C0_14", "C0_15",
549 "C0_16", "C0_17", "C0_18", "C0_19", "C0_20", "C0_21", "C0_22", "C0_23",
550 "C0_24", "C0_25", "C0_26", "C0_27", "C0_28", "C0_29", "C0_30", "C0_31",
551
552 "C2D0", "C2D1", "C2D2", "C2D3", "C2D4", "C2D5", "C2D6", "C2D7",
553 "C2D8", "C2D9", "C2D10", "C2D11", "C2D12", "C2D13", "C2D14", "C2D15",
554 "C2D16", "C2D17", "C2D18", "C2D19", "C2D20", "C2D21", "C2D22", "C2D23",
555 "C2D24", "C2D25", "C2D26", "C2D27", "C2D28", "C2D29", "C2D30", "C2D31",
556
557 "C2C0", "C2C1", "C2C2", "C2C3", "C2C4", "C2C5", "C2C6", "C2C7",
558 "C2C8", "C2C9", "C2C10", "C2C11", "C2C12", "C2C13", "C2C14", "C2C15",
559 "C2C16", "C2C17", "C2C18", "C2C19", "C2C20", "C2C21", "C2C22", "C2C23",
560 "C2C24", "C2C25", "C2C26", "C2C27", "C2C28", "C2C29", "C2C30", "C2C31",
561
562 "PC", "code", "cycle", "interrupt",
563};
564
565static struct {
566 int reg;
567 u32 val, val_expect;
568 u32 pc, cycle;
569} miss_log[64];
570static int miss_log_i;
571#define miss_log_len (sizeof(miss_log)/sizeof(miss_log[0]))
572#define miss_log_mask (miss_log_len-1)
573
574static void miss_log_add(int reg, u32 val, u32 val_expect, u32 pc, u32 cycle)
575{
576 miss_log[miss_log_i].reg = reg;
577 miss_log[miss_log_i].val = val;
578 miss_log[miss_log_i].val_expect = val_expect;
579 miss_log[miss_log_i].pc = pc;
580 miss_log[miss_log_i].cycle = cycle;
581 miss_log_i = (miss_log_i + 1) & miss_log_mask;
582}
583
584void breakme() {}
585
586void do_insn_cmp(void)
587{
588 extern int last_count;
589 static psxRegisters rregs;
590 static u32 mem_addr, mem_val;
591 static u32 irq_test_cycle_intr;
592 static u32 handler_cycle_intr;
593 u32 *allregs_p = (void *)&psxRegs;
594 u32 *allregs_e = (void *)&rregs;
595 static u32 ppc, failcount;
596 int i, ret, bad = 0, fatal = 0, which_event = -1;
597 u32 ev_cycles = 0;
598 u8 code;
599
600 if (f == NULL)
601 f = fopen("tracelog", "rb");
602
603 while (1) {
604 if ((ret = fread(&code, 1, 1, f)) <= 0)
605 break;
606 if (ret <= 0)
607 break;
608 if (code == 0xff)
609 break;
610 switch (code) {
611 case 0xf8:
612 which_event = 0;
613 fread(&which_event, 1, 1, f);
614 fread(&ev_cycles, 1, 4, f);
615 continue;
616 case 0xfb:
617 fread(&irq_test_cycle_intr, 1, 4, f);
618 continue;
619 case 0xfc:
620 fread(&handler_cycle_intr, 1, 4, f);
621 continue;
622 case 0xfd:
623 fread(&mem_addr, 1, 4, f);
624 continue;
625 case 0xfe:
626 fread(&mem_val, 1, 4, f);
627 continue;
628 }
629 assert(code < offsetof(psxRegisters, intCycle) / 4);
630 fread(&allregs_e[code], 1, 4, f);
631 }
632
633 if (ret <= 0) {
634 printf("EOF?\n");
635 exit(1);
636 }
637
638 psxRegs.code = rregs.code; // don't care
639 psxRegs.cycle += last_count;
640 //psxRegs.cycle = rregs.cycle; // needs reload in _cmp
641 psxRegs.CP0.r[9] = rregs.CP0.r[9]; // Count
642
643 //if (psxRegs.cycle == 166172) breakme();
644
645 if (which_event >= 0 && event_cycles[which_event] != ev_cycles) {
646 printf("bad ev_cycles #%d: %u %u / %u\n", which_event,
647 event_cycles[which_event], ev_cycles, psxRegs.cycle);
648 fatal = 1;
649 }
650
651 if (irq_test_cycle > irq_test_cycle_intr) {
652 printf("bad irq_test_cycle: %u %u\n", irq_test_cycle, irq_test_cycle_intr);
653 fatal = 1;
654 }
655
656 if (handler_cycle != handler_cycle_intr) {
657 printf("bad handler_cycle: %u %u\n", handler_cycle, handler_cycle_intr);
658 fatal = 1;
659 }
660
661 if (mem_val != memcheck_read(mem_addr)) {
662 printf("bad mem @%08x: %08x %08x\n", mem_addr, memcheck_read(mem_addr), mem_val);
663 fatal = 1;
664 }
665
666 if (!fatal && !memcmp(&psxRegs, &rregs, offsetof(psxRegisters, intCycle))) {
667 failcount = 0;
668 goto ok;
669 }
670
671 for (i = 0; i < offsetof(psxRegisters, intCycle) / 4; i++) {
672 if (allregs_p[i] != allregs_e[i]) {
673 miss_log_add(i, allregs_p[i], allregs_e[i], psxRegs.pc, psxRegs.cycle);
674 bad++;
675 if (i > 32+2)
676 fatal = 1;
677 }
678 }
679
680 if (!fatal && psxRegs.pc == rregs.pc && bad < 6 && failcount < 32) {
681 static int last_mcycle;
682 if (last_mcycle != psxRegs.cycle >> 20) {
683 printf("%u\n", psxRegs.cycle);
684 last_mcycle = psxRegs.cycle >> 20;
685 }
686 failcount++;
687 goto ok;
688 }
689
690 for (i = 0; i < miss_log_len; i++, miss_log_i = (miss_log_i + 1) & miss_log_mask)
691 printf("bad %5s: %08x %08x, pc=%08x, cycle %u\n",
692 regnames[miss_log[miss_log_i].reg], miss_log[miss_log_i].val,
693 miss_log[miss_log_i].val_expect, miss_log[miss_log_i].pc, miss_log[miss_log_i].cycle);
694 printf("-- %d\n", bad);
695 for (i = 0; i < 8; i++)
696 printf("r%d=%08x r%2d=%08x r%2d=%08x r%2d=%08x\n", i, allregs_p[i],
697 i+8, allregs_p[i+8], i+16, allregs_p[i+16], i+24, allregs_p[i+24]);
698 printf("PC: %08x/%08x, cycle %u, next %u\n", psxRegs.pc, ppc, psxRegs.cycle, next_interupt);
699 //dump_mem("/tmp/psxram.dump", psxM, 0x200000);
700 //dump_mem("/mnt/ntz/dev/pnd/tmp/psxregs.dump", psxH, 0x10000);
701 exit(1);
702ok:
703 //psxRegs.cycle = rregs.cycle + 2; // sync timing
704 ppc = psxRegs.pc;
705}
706
707#endif