fix x86 build
[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 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#ifndef DRC_DISABLE
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/* from gte.txt.. not sure if this is any good. */
221const char gte_cycletab[64] = {
222 /* 1 2 3 4 5 6 7 8 9 a b c d e f */
223 0, 15, 0, 0, 0, 0, 8, 0, 0, 0, 0, 0, 6, 0, 0, 0,
224 8, 8, 8, 19, 13, 0, 44, 0, 0, 0, 0, 17, 11, 0, 14, 0,
225 30, 0, 0, 0, 0, 0, 0, 0, 5, 8, 17, 0, 0, 5, 6, 0,
226 23, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 5, 5, 39,
227};
228
229#define GCBIT(x) \
230 (1ll << (32+x))
231#define GDBIT(x) \
232 (1ll << (x))
233#define GCBITS3(b0,b1,b2) \
234 (GCBIT(b0) | GCBIT(b1) | GCBIT(b2))
235#define GDBITS2(b0,b1) \
236 (GDBIT(b0) | GDBIT(b1))
237#define GDBITS3(b0,b1,b2) \
238 (GDBITS2(b0,b1) | GDBIT(b2))
239#define GDBITS4(b0,b1,b2,b3) \
240 (GDBITS3(b0,b1,b2) | GDBIT(b3))
241#define GDBITS5(b0,b1,b2,b3,b4) \
242 (GDBITS4(b0,b1,b2,b3) | GDBIT(b4))
243#define GDBITS6(b0,b1,b2,b3,b4,b5) \
244 (GDBITS5(b0,b1,b2,b3,b4) | GDBIT(b5))
245#define GDBITS7(b0,b1,b2,b3,b4,b5,b6) \
246 (GDBITS6(b0,b1,b2,b3,b4,b5) | GDBIT(b6))
247#define GDBITS8(b0,b1,b2,b3,b4,b5,b6,b7) \
248 (GDBITS7(b0,b1,b2,b3,b4,b5,b6) | GDBIT(b7))
249#define GDBITS9(b0,b1,b2,b3,b4,b5,b6,b7,b8) \
250 (GDBITS8(b0,b1,b2,b3,b4,b5,b6,b7) | GDBIT(b8))
251#define GDBITS10(b0,b1,b2,b3,b4,b5,b6,b7,b8,b9) \
252 (GDBITS9(b0,b1,b2,b3,b4,b5,b6,b7,b8) | GDBIT(b9))
253
254const uint64_t gte_reg_reads[64] = {
255 [GTE_RTPS] = 0x1f0000ff00000000ll | GDBITS7(0,1,13,14,17,18,19),
256 [GTE_NCLIP] = GDBITS3(12,13,14),
257 [GTE_OP] = GCBITS3(0,2,4) | GDBITS3(9,10,11),
258 [GTE_DPCS] = GCBITS3(21,22,23) | GDBITS4(6,8,21,22),
259 [GTE_INTPL] = GCBITS3(21,22,23) | GDBITS7(6,8,9,10,11,21,22),
260 [GTE_MVMVA] = 0x00ffffff00000000ll | GDBITS9(0,1,2,3,4,5,9,10,11), // XXX: maybe decode further?
261 [GTE_NCDS] = 0x00ffff0000000000ll | GDBITS6(0,1,6,8,21,22),
262 [GTE_CDP] = 0x00ffe00000000000ll | GDBITS7(6,8,9,10,11,21,22),
263 [GTE_NCDT] = 0x00ffff0000000000ll | GDBITS8(0,1,2,3,4,5,6,8),
264 [GTE_NCCS] = 0x001fff0000000000ll | GDBITS5(0,1,6,21,22),
265 [GTE_CC] = 0x001fe00000000000ll | GDBITS6(6,9,10,11,21,22),
266 [GTE_NCS] = 0x001fff0000000000ll | GDBITS5(0,1,6,21,22),
267 [GTE_NCT] = 0x001fff0000000000ll | GDBITS7(0,1,2,3,4,5,6),
268 [GTE_SQR] = GDBITS3(9,10,11),
269 [GTE_DCPL] = GCBITS3(21,22,23) | GDBITS7(6,8,9,10,11,21,22),
270 [GTE_DPCT] = GCBITS3(21,22,23) | GDBITS4(8,20,21,22),
271 [GTE_AVSZ3] = GCBIT(29) | GDBITS3(17,18,19),
272 [GTE_AVSZ4] = GCBIT(30) | GDBITS4(16,17,18,19),
273 [GTE_RTPT] = 0x1f0000ff00000000ll | GDBITS7(0,1,2,3,4,5,19),
274 [GTE_GPF] = GDBITS7(6,8,9,10,11,21,22),
275 [GTE_GPL] = GDBITS10(6,8,9,10,11,21,22,25,26,27),
276 [GTE_NCCT] = 0x001fff0000000000ll | GDBITS7(0,1,2,3,4,5,6),
277};
278
279// note: this excludes gteFLAG that is always written to
280const uint64_t gte_reg_writes[64] = {
281 [GTE_RTPS] = 0x0f0f7f00ll,
282 [GTE_NCLIP] = GDBIT(24),
283 [GTE_OP] = GDBITS6(9,10,11,25,26,27),
284 [GTE_DPCS] = GDBITS9(9,10,11,20,21,22,25,26,27),
285 [GTE_INTPL] = GDBITS9(9,10,11,20,21,22,25,26,27),
286 [GTE_MVMVA] = GDBITS6(9,10,11,25,26,27),
287 [GTE_NCDS] = GDBITS9(9,10,11,20,21,22,25,26,27),
288 [GTE_CDP] = GDBITS9(9,10,11,20,21,22,25,26,27),
289 [GTE_NCDT] = GDBITS9(9,10,11,20,21,22,25,26,27),
290 [GTE_NCCS] = GDBITS9(9,10,11,20,21,22,25,26,27),
291 [GTE_CC] = GDBITS9(9,10,11,20,21,22,25,26,27),
292 [GTE_NCS] = GDBITS9(9,10,11,20,21,22,25,26,27),
293 [GTE_NCT] = GDBITS9(9,10,11,20,21,22,25,26,27),
294 [GTE_SQR] = GDBITS6(9,10,11,25,26,27),
295 [GTE_DCPL] = GDBITS9(9,10,11,20,21,22,25,26,27),
296 [GTE_DPCT] = GDBITS9(9,10,11,20,21,22,25,26,27),
297 [GTE_AVSZ3] = GDBITS2(7,24),
298 [GTE_AVSZ4] = GDBITS2(7,24),
299 [GTE_RTPT] = 0x0f0f7f00ll,
300 [GTE_GPF] = GDBITS9(9,10,11,20,21,22,25,26,27),
301 [GTE_GPL] = GDBITS9(9,10,11,20,21,22,25,26,27),
302 [GTE_NCCT] = GDBITS9(9,10,11,20,21,22,25,26,27),
303};
304
305static int ari64_init()
306{
307 static u32 scratch_buf[8*8*2] __attribute__((aligned(64)));
308 extern void (*psxCP2[64])();
309 extern void psxNULL();
310 extern unsigned char *out;
311 size_t i;
312
313 new_dynarec_init();
314 new_dyna_pcsx_mem_init();
315
316 for (i = 0; i < ARRAY_SIZE(gte_handlers); i++)
317 if (psxCP2[i] != psxNULL)
318 gte_handlers[i] = psxCP2[i];
319
320#if defined(__arm__) && !defined(DRC_DBG)
321 gte_handlers[0x06] = gteNCLIP_arm;
322#ifdef HAVE_ARMV5
323 gte_handlers_nf[0x01] = gteRTPS_nf_arm;
324 gte_handlers_nf[0x30] = gteRTPT_nf_arm;
325#endif
326#ifdef __ARM_NEON__
327 // compiler's _nf version is still a lot slower than neon
328 // _nf_arm RTPS is roughly the same, RTPT slower
329 gte_handlers[0x01] = gte_handlers_nf[0x01] = gteRTPS_neon;
330 gte_handlers[0x30] = gte_handlers_nf[0x30] = gteRTPT_neon;
331#endif
332#endif
333#ifdef DRC_DBG
334 memcpy(gte_handlers_nf, gte_handlers, sizeof(gte_handlers_nf));
335#endif
336 psxH_ptr = psxH;
337 zeromem_ptr = zero_mem;
338 scratch_buf_ptr = scratch_buf;
339
340 SysPrintf("Mapped (RAM/scrp/ROM/LUTs/TC):\n");
341 SysPrintf("%p/%p/%p/%p/%p\n",
342 psxM, psxH, psxR, mem_rtab, out);
343
344 return 0;
345}
346
347static void ari64_reset()
348{
349 printf("ari64_reset\n");
350 new_dyna_pcsx_mem_reset();
351 invalidate_all_pages();
352 new_dyna_restore();
353 pending_exception = 1;
354}
355
356// execute until predefined leave points
357// (HLE softcall exit and BIOS fastboot end)
358static void ari64_execute_until()
359{
360 schedule_timeslice();
361
362 evprintf("ari64_execute %08x, %u->%u (%d)\n", psxRegs.pc,
363 psxRegs.cycle, next_interupt, next_interupt - psxRegs.cycle);
364
365 new_dyna_start(dynarec_local);
366
367 evprintf("ari64_execute end %08x, %u->%u (%d)\n", psxRegs.pc,
368 psxRegs.cycle, next_interupt, next_interupt - psxRegs.cycle);
369}
370
371static void ari64_execute()
372{
373 while (!stop) {
374 ari64_execute_until();
375 evprintf("drc left @%08x\n", psxRegs.pc);
376 }
377}
378
379static void ari64_clear(u32 addr, u32 size)
380{
381 u32 start, end, main_ram;
382
383 size *= 4; /* PCSX uses DMA units (words) */
384
385 evprintf("ari64_clear %08x %04x\n", addr, size);
386
387 /* check for RAM mirrors */
388 main_ram = (addr & 0xffe00000) == 0x80000000;
389
390 start = addr >> 12;
391 end = (addr + size) >> 12;
392
393 for (; start <= end; start++)
394 if (!main_ram || !invalid_code[start])
395 invalidate_block(start);
396}
397
398#ifdef ICACHE_EMULATION
399static void ari64_notify(int note, void *data) {
400 /*
401 Should be fixed when ARM dynarec has proper icache emulation.
402 switch (note)
403 {
404 case R3000ACPU_NOTIFY_CACHE_UNISOLATED:
405 break;
406 case R3000ACPU_NOTIFY_CACHE_ISOLATED:
407 Sent from psxDma3().
408 case R3000ACPU_NOTIFY_DMA3_EXE_LOAD:
409 default:
410 break;
411 }
412 */
413}
414#endif
415
416static void ari64_shutdown()
417{
418 new_dynarec_cleanup();
419 new_dyna_pcsx_mem_shutdown();
420}
421
422R3000Acpu psxRec = {
423 ari64_init,
424 ari64_reset,
425 ari64_execute,
426 ari64_execute_until,
427 ari64_clear,
428#ifdef ICACHE_EMULATION
429 ari64_notify,
430#endif
431 ari64_shutdown
432};
433
434#else // if DRC_DISABLE
435
436unsigned int address;
437int pending_exception, stop;
438unsigned int next_interupt;
439int new_dynarec_did_compile;
440int cycle_multiplier;
441int cycle_multiplier_override;
442int new_dynarec_hacks;
443void *psxH_ptr;
444void *zeromem_ptr;
445u8 zero_mem[0x1000];
446unsigned char *out;
447void *mem_rtab;
448void *scratch_buf_ptr;
449void new_dynarec_init() {}
450void new_dyna_start(void *context) {}
451void new_dynarec_cleanup() {}
452void new_dynarec_clear_full() {}
453void invalidate_all_pages() {}
454void invalidate_block(unsigned int block) {}
455void new_dyna_pcsx_mem_init(void) {}
456void new_dyna_pcsx_mem_reset(void) {}
457void new_dyna_pcsx_mem_load_state(void) {}
458void new_dyna_pcsx_mem_shutdown(void) {}
459int new_dynarec_save_blocks(void *save, int size) { return 0; }
460void new_dynarec_load_blocks(const void *save, int size) {}
461#endif
462
463#ifdef DRC_DBG
464
465#include <stddef.h>
466static FILE *f;
467extern u32 last_io_addr;
468
469static void dump_mem(const char *fname, void *mem, size_t size)
470{
471 FILE *f1 = fopen(fname, "wb");
472 if (f1 == NULL)
473 f1 = fopen(strrchr(fname, '/') + 1, "wb");
474 fwrite(mem, 1, size, f1);
475 fclose(f1);
476}
477
478static u32 memcheck_read(u32 a)
479{
480 if ((a >> 16) == 0x1f80)
481 // scratchpad/IO
482 return *(u32 *)(psxH + (a & 0xfffc));
483
484 if ((a >> 16) == 0x1f00)
485 // parallel
486 return *(u32 *)(psxP + (a & 0xfffc));
487
488// if ((a & ~0xe0600000) < 0x200000)
489 // RAM
490 return *(u32 *)(psxM + (a & 0x1ffffc));
491}
492
493#if 0
494void do_insn_trace(void)
495{
496 static psxRegisters oldregs;
497 static u32 old_io_addr = (u32)-1;
498 static u32 old_io_data = 0xbad0c0de;
499 static u32 event_cycles_o[PSXINT_COUNT];
500 u32 *allregs_p = (void *)&psxRegs;
501 u32 *allregs_o = (void *)&oldregs;
502 u32 io_data;
503 int i;
504 u8 byte;
505
506 //last_io_addr = 0x5e2c8;
507 if (f == NULL)
508 f = fopen("tracelog", "wb");
509
510 // log reg changes
511 oldregs.code = psxRegs.code; // don't care
512 for (i = 0; i < offsetof(psxRegisters, intCycle) / 4; i++) {
513 if (allregs_p[i] != allregs_o[i]) {
514 fwrite(&i, 1, 1, f);
515 fwrite(&allregs_p[i], 1, 4, f);
516 allregs_o[i] = allregs_p[i];
517 }
518 }
519 // log event changes
520 for (i = 0; i < PSXINT_COUNT; i++) {
521 if (event_cycles[i] != event_cycles_o[i]) {
522 byte = 0xfc;
523 fwrite(&byte, 1, 1, f);
524 fwrite(&i, 1, 1, f);
525 fwrite(&event_cycles[i], 1, 4, f);
526 event_cycles_o[i] = event_cycles[i];
527 }
528 }
529 // log last io
530 if (old_io_addr != last_io_addr) {
531 byte = 0xfd;
532 fwrite(&byte, 1, 1, f);
533 fwrite(&last_io_addr, 1, 4, f);
534 old_io_addr = last_io_addr;
535 }
536 io_data = memcheck_read(last_io_addr);
537 if (old_io_data != io_data) {
538 byte = 0xfe;
539 fwrite(&byte, 1, 1, f);
540 fwrite(&io_data, 1, 4, f);
541 old_io_data = io_data;
542 }
543 byte = 0xff;
544 fwrite(&byte, 1, 1, f);
545
546#if 0
547 if (psxRegs.cycle == 190230) {
548 dump_mem("/mnt/ntz/dev/pnd/tmp/psxram_i.dump", psxM, 0x200000);
549 dump_mem("/mnt/ntz/dev/pnd/tmp/psxregs_i.dump", psxH, 0x10000);
550 printf("dumped\n");
551 exit(1);
552 }
553#endif
554}
555#endif
556
557static const char *regnames[offsetof(psxRegisters, intCycle) / 4] = {
558 "r0", "r1", "r2", "r3", "r4", "r5", "r6", "r7",
559 "r8", "r9", "r10", "r11", "r12", "r13", "r14", "r15",
560 "r16", "r17", "r18", "r19", "r20", "r21", "r22", "r23",
561 "r24", "r25", "r26", "r27", "r28", "r29", "r30", "r31",
562 "lo", "hi",
563 "C0_0", "C0_1", "C0_2", "C0_3", "C0_4", "C0_5", "C0_6", "C0_7",
564 "C0_8", "C0_9", "C0_10", "C0_11", "C0_12", "C0_13", "C0_14", "C0_15",
565 "C0_16", "C0_17", "C0_18", "C0_19", "C0_20", "C0_21", "C0_22", "C0_23",
566 "C0_24", "C0_25", "C0_26", "C0_27", "C0_28", "C0_29", "C0_30", "C0_31",
567
568 "C2D0", "C2D1", "C2D2", "C2D3", "C2D4", "C2D5", "C2D6", "C2D7",
569 "C2D8", "C2D9", "C2D10", "C2D11", "C2D12", "C2D13", "C2D14", "C2D15",
570 "C2D16", "C2D17", "C2D18", "C2D19", "C2D20", "C2D21", "C2D22", "C2D23",
571 "C2D24", "C2D25", "C2D26", "C2D27", "C2D28", "C2D29", "C2D30", "C2D31",
572
573 "C2C0", "C2C1", "C2C2", "C2C3", "C2C4", "C2C5", "C2C6", "C2C7",
574 "C2C8", "C2C9", "C2C10", "C2C11", "C2C12", "C2C13", "C2C14", "C2C15",
575 "C2C16", "C2C17", "C2C18", "C2C19", "C2C20", "C2C21", "C2C22", "C2C23",
576 "C2C24", "C2C25", "C2C26", "C2C27", "C2C28", "C2C29", "C2C30", "C2C31",
577
578 "PC", "code", "cycle", "interrupt",
579};
580
581static struct {
582 int reg;
583 u32 val, val_expect;
584 u32 pc, cycle;
585} miss_log[64];
586static int miss_log_i;
587#define miss_log_len (sizeof(miss_log)/sizeof(miss_log[0]))
588#define miss_log_mask (miss_log_len-1)
589
590static void miss_log_add(int reg, u32 val, u32 val_expect, u32 pc, u32 cycle)
591{
592 miss_log[miss_log_i].reg = reg;
593 miss_log[miss_log_i].val = val;
594 miss_log[miss_log_i].val_expect = val_expect;
595 miss_log[miss_log_i].pc = pc;
596 miss_log[miss_log_i].cycle = cycle;
597 miss_log_i = (miss_log_i + 1) & miss_log_mask;
598}
599
600void breakme() {}
601
602void do_insn_cmp(void)
603{
604 static psxRegisters rregs;
605 static u32 mem_addr, mem_val;
606 u32 *allregs_p = (void *)&psxRegs;
607 u32 *allregs_e = (void *)&rregs;
608 static u32 ppc, failcount;
609 int i, ret, bad = 0, which_event = -1;
610 u32 ev_cycles = 0;
611 u8 code;
612
613 if (f == NULL)
614 f = fopen("tracelog", "rb");
615
616 while (1) {
617 if ((ret = fread(&code, 1, 1, f)) <= 0)
618 break;
619 if (ret <= 0)
620 break;
621 if (code == 0xff)
622 break;
623 switch (code) {
624 case 0xfc:
625 which_event = 0;
626 fread(&which_event, 1, 1, f);
627 fread(&ev_cycles, 1, 4, f);
628 continue;
629 case 0xfd:
630 fread(&mem_addr, 1, 4, f);
631 continue;
632 case 0xfe:
633 fread(&mem_val, 1, 4, f);
634 continue;
635 }
636 fread(&allregs_e[code], 1, 4, f);
637 }
638
639 if (ret <= 0) {
640 printf("EOF?\n");
641 goto end;
642 }
643
644 psxRegs.code = rregs.code; // don't care
645 psxRegs.cycle = rregs.cycle;
646 psxRegs.CP0.r[9] = rregs.CP0.r[9]; // Count
647
648 //if (psxRegs.cycle == 166172) breakme();
649
650 if (memcmp(&psxRegs, &rregs, offsetof(psxRegisters, intCycle)) == 0 &&
651 mem_val == memcheck_read(mem_addr)
652 ) {
653 failcount = 0;
654 goto ok;
655 }
656
657 for (i = 0; i < offsetof(psxRegisters, intCycle) / 4; i++) {
658 if (allregs_p[i] != allregs_e[i]) {
659 miss_log_add(i, allregs_p[i], allregs_e[i], psxRegs.pc, psxRegs.cycle);
660 bad++;
661 if (i > 32+2)
662 goto end;
663 }
664 }
665
666 if (mem_val != memcheck_read(mem_addr)) {
667 printf("bad mem @%08x: %08x %08x\n", mem_addr, memcheck_read(mem_addr), mem_val);
668 goto end;
669 }
670
671 if (which_event >= 0 && event_cycles[which_event] != ev_cycles) {
672 printf("bad ev_cycles #%d: %08x %08x\n", which_event, event_cycles[which_event], ev_cycles);
673 goto end;
674 }
675
676 if (psxRegs.pc == rregs.pc && bad < 6 && failcount < 32) {
677 static int last_mcycle;
678 if (last_mcycle != psxRegs.cycle >> 20) {
679 printf("%u\n", psxRegs.cycle);
680 last_mcycle = psxRegs.cycle >> 20;
681 }
682 failcount++;
683 goto ok;
684 }
685
686end:
687 for (i = 0; i < miss_log_len; i++, miss_log_i = (miss_log_i + 1) & miss_log_mask)
688 printf("bad %5s: %08x %08x, pc=%08x, cycle %u\n",
689 regnames[miss_log[miss_log_i].reg], miss_log[miss_log_i].val,
690 miss_log[miss_log_i].val_expect, miss_log[miss_log_i].pc, miss_log[miss_log_i].cycle);
691 printf("-- %d\n", bad);
692 for (i = 0; i < 8; i++)
693 printf("r%d=%08x r%2d=%08x r%2d=%08x r%2d=%08x\n", i, allregs_p[i],
694 i+8, allregs_p[i+8], i+16, allregs_p[i+16], i+24, allregs_p[i+24]);
695 printf("PC: %08x/%08x, cycle %u\n", psxRegs.pc, ppc, psxRegs.cycle);
696 dump_mem("/mnt/ntz/dev/pnd/tmp/psxram.dump", psxM, 0x200000);
697 dump_mem("/mnt/ntz/dev/pnd/tmp/psxregs.dump", psxH, 0x10000);
698 exit(1);
699ok:
700 psxRegs.cycle = rregs.cycle + 2; // sync timing
701 ppc = psxRegs.pc;
702}
703
704#endif