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