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