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