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