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