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