gpu_neon: more complicated overflow check
[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 ari64_reset();
301 psxInt.Notify(note, data);
302 break;
303 }
304}
305
306static void ari64_apply_config()
307{
308 intApplyConfig();
309
310 if (Config.DisableStalls)
311 new_dynarec_hacks |= NDHACK_NO_STALLS;
312 else
313 new_dynarec_hacks &= ~NDHACK_NO_STALLS;
314
315 if (Config.cycle_multiplier != cycle_multiplier_old
316 || new_dynarec_hacks != new_dynarec_hacks_old)
317 {
318 new_dynarec_clear_full();
319 }
320}
321
322static void ari64_shutdown()
323{
324 new_dynarec_cleanup();
325 new_dyna_pcsx_mem_shutdown();
326}
327
328R3000Acpu psxRec = {
329 ari64_init,
330 ari64_reset,
331 ari64_execute,
332 ari64_execute_block,
333 ari64_clear,
334 ari64_notify,
335 ari64_apply_config,
336 ari64_shutdown
337};
338
339#else // if DRC_DISABLE
340
341unsigned int address;
342int pending_exception, stop;
343u32 next_interupt;
344int new_dynarec_did_compile;
345int cycle_multiplier_old;
346int new_dynarec_hacks_pergame;
347int new_dynarec_hacks_old;
348int new_dynarec_hacks;
349void *psxH_ptr;
350void *zeromem_ptr;
351u32 zero_mem[0x1000/4];
352void *mem_rtab;
353void *scratch_buf_ptr;
354void new_dynarec_init() {}
355void new_dyna_start(void *context) {}
356void new_dynarec_cleanup() {}
357void new_dynarec_clear_full() {}
358void new_dynarec_invalidate_all_pages() {}
359void new_dynarec_invalidate_range(unsigned int start, unsigned int end) {}
360void new_dyna_pcsx_mem_init(void) {}
361void new_dyna_pcsx_mem_reset(void) {}
362void new_dyna_pcsx_mem_load_state(void) {}
363void new_dyna_pcsx_mem_isolate(int enable) {}
364void new_dyna_pcsx_mem_shutdown(void) {}
365int new_dynarec_save_blocks(void *save, int size) { return 0; }
366void new_dynarec_load_blocks(const void *save, int size) {}
367#endif
368
369#ifdef DRC_DBG
370
371#include <stddef.h>
372static FILE *f;
373u32 irq_test_cycle;
374u32 handler_cycle;
375u32 last_io_addr;
376
377void dump_mem(const char *fname, void *mem, size_t size)
378{
379 FILE *f1 = fopen(fname, "wb");
380 if (f1 == NULL)
381 f1 = fopen(strrchr(fname, '/') + 1, "wb");
382 fwrite(mem, 1, size, f1);
383 fclose(f1);
384}
385
386static u32 memcheck_read(u32 a)
387{
388 if ((a >> 16) == 0x1f80)
389 // scratchpad/IO
390 return *(u32 *)(psxH + (a & 0xfffc));
391
392 if ((a >> 16) == 0x1f00)
393 // parallel
394 return *(u32 *)(psxP + (a & 0xfffc));
395
396// if ((a & ~0xe0600000) < 0x200000)
397 // RAM
398 return *(u32 *)(psxM + (a & 0x1ffffc));
399}
400
401#if 0
402void do_insn_trace(void)
403{
404 static psxRegisters oldregs;
405 static u32 event_cycles_o[PSXINT_COUNT];
406 u32 *allregs_p = (void *)&psxRegs;
407 u32 *allregs_o = (void *)&oldregs;
408 u32 io_data;
409 int i;
410 u8 byte;
411
412 //last_io_addr = 0x5e2c8;
413 if (f == NULL)
414 f = fopen("tracelog", "wb");
415
416 // log reg changes
417 oldregs.code = psxRegs.code; // don't care
418 for (i = 0; i < offsetof(psxRegisters, intCycle) / 4; i++) {
419 if (allregs_p[i] != allregs_o[i]) {
420 fwrite(&i, 1, 1, f);
421 fwrite(&allregs_p[i], 1, 4, f);
422 allregs_o[i] = allregs_p[i];
423 }
424 }
425 // log event changes
426 for (i = 0; i < PSXINT_COUNT; i++) {
427 if (event_cycles[i] != event_cycles_o[i]) {
428 byte = 0xf8;
429 fwrite(&byte, 1, 1, f);
430 fwrite(&i, 1, 1, f);
431 fwrite(&event_cycles[i], 1, 4, f);
432 event_cycles_o[i] = event_cycles[i];
433 }
434 }
435 #define SAVE_IF_CHANGED(code_, name_) { \
436 static u32 old_##name_ = 0xbad0c0de; \
437 if (old_##name_ != name_) { \
438 byte = code_; \
439 fwrite(&byte, 1, 1, f); \
440 fwrite(&name_, 1, 4, f); \
441 old_##name_ = name_; \
442 } \
443 }
444 SAVE_IF_CHANGED(0xfb, irq_test_cycle);
445 SAVE_IF_CHANGED(0xfc, handler_cycle);
446 SAVE_IF_CHANGED(0xfd, last_io_addr);
447 io_data = memcheck_read(last_io_addr);
448 SAVE_IF_CHANGED(0xfe, io_data);
449 byte = 0xff;
450 fwrite(&byte, 1, 1, f);
451
452#if 0
453 if (psxRegs.cycle == 190230) {
454 dump_mem("/mnt/ntz/dev/pnd/tmp/psxram_i.dump", psxM, 0x200000);
455 dump_mem("/mnt/ntz/dev/pnd/tmp/psxregs_i.dump", psxH, 0x10000);
456 printf("dumped\n");
457 exit(1);
458 }
459#endif
460}
461#endif
462
463static const char *regnames[offsetof(psxRegisters, intCycle) / 4] = {
464 "r0", "r1", "r2", "r3", "r4", "r5", "r6", "r7",
465 "r8", "r9", "r10", "r11", "r12", "r13", "r14", "r15",
466 "r16", "r17", "r18", "r19", "r20", "r21", "r22", "r23",
467 "r24", "r25", "r26", "r27", "r28", "r29", "r30", "r31",
468 "lo", "hi",
469 "C0_0", "C0_1", "C0_2", "C0_3", "C0_4", "C0_5", "C0_6", "C0_7",
470 "C0_8", "C0_9", "C0_10", "C0_11", "C0_12", "C0_13", "C0_14", "C0_15",
471 "C0_16", "C0_17", "C0_18", "C0_19", "C0_20", "C0_21", "C0_22", "C0_23",
472 "C0_24", "C0_25", "C0_26", "C0_27", "C0_28", "C0_29", "C0_30", "C0_31",
473
474 "C2D0", "C2D1", "C2D2", "C2D3", "C2D4", "C2D5", "C2D6", "C2D7",
475 "C2D8", "C2D9", "C2D10", "C2D11", "C2D12", "C2D13", "C2D14", "C2D15",
476 "C2D16", "C2D17", "C2D18", "C2D19", "C2D20", "C2D21", "C2D22", "C2D23",
477 "C2D24", "C2D25", "C2D26", "C2D27", "C2D28", "C2D29", "C2D30", "C2D31",
478
479 "C2C0", "C2C1", "C2C2", "C2C3", "C2C4", "C2C5", "C2C6", "C2C7",
480 "C2C8", "C2C9", "C2C10", "C2C11", "C2C12", "C2C13", "C2C14", "C2C15",
481 "C2C16", "C2C17", "C2C18", "C2C19", "C2C20", "C2C21", "C2C22", "C2C23",
482 "C2C24", "C2C25", "C2C26", "C2C27", "C2C28", "C2C29", "C2C30", "C2C31",
483
484 "PC", "code", "cycle", "interrupt",
485};
486
487static struct {
488 int reg;
489 u32 val, val_expect;
490 u32 pc, cycle;
491} miss_log[64];
492static int miss_log_i;
493#define miss_log_len (sizeof(miss_log)/sizeof(miss_log[0]))
494#define miss_log_mask (miss_log_len-1)
495
496static void miss_log_add(int reg, u32 val, u32 val_expect, u32 pc, u32 cycle)
497{
498 miss_log[miss_log_i].reg = reg;
499 miss_log[miss_log_i].val = val;
500 miss_log[miss_log_i].val_expect = val_expect;
501 miss_log[miss_log_i].pc = pc;
502 miss_log[miss_log_i].cycle = cycle;
503 miss_log_i = (miss_log_i + 1) & miss_log_mask;
504}
505
506void breakme() {}
507
508void do_insn_cmp(void)
509{
510 extern int last_count;
511 static psxRegisters rregs;
512 static u32 mem_addr, mem_val;
513 static u32 irq_test_cycle_intr;
514 static u32 handler_cycle_intr;
515 u32 *allregs_p = (void *)&psxRegs;
516 u32 *allregs_e = (void *)&rregs;
517 u32 badregs_mask = 0;
518 static u32 ppc, failcount;
519 static u32 badregs_mask_prev;
520 int i, ret, bad = 0, fatal = 0, which_event = -1;
521 u32 ev_cycles = 0;
522 u8 code;
523
524 if (f == NULL)
525 f = fopen("tracelog", "rb");
526
527 while (1) {
528 if ((ret = fread(&code, 1, 1, f)) <= 0)
529 break;
530 if (ret <= 0)
531 break;
532 if (code == 0xff)
533 break;
534 switch (code) {
535 case 0xf8:
536 which_event = 0;
537 fread(&which_event, 1, 1, f);
538 fread(&ev_cycles, 1, 4, f);
539 continue;
540 case 0xfb:
541 fread(&irq_test_cycle_intr, 1, 4, f);
542 continue;
543 case 0xfc:
544 fread(&handler_cycle_intr, 1, 4, f);
545 continue;
546 case 0xfd:
547 fread(&mem_addr, 1, 4, f);
548 continue;
549 case 0xfe:
550 fread(&mem_val, 1, 4, f);
551 continue;
552 }
553 assert(code < offsetof(psxRegisters, intCycle) / 4);
554 fread(&allregs_e[code], 1, 4, f);
555 }
556
557 if (ret <= 0) {
558 printf("EOF?\n");
559 exit(1);
560 }
561
562 psxRegs.code = rregs.code; // don't care
563 psxRegs.cycle += last_count;
564 //psxRegs.cycle = rregs.cycle; // needs reload in _cmp
565 psxRegs.CP0.r[9] = rregs.CP0.r[9]; // Count
566
567 //if (psxRegs.cycle == 166172) breakme();
568
569 if (which_event >= 0 && event_cycles[which_event] != ev_cycles) {
570 printf("bad ev_cycles #%d: %u %u / %u\n", which_event,
571 event_cycles[which_event], ev_cycles, psxRegs.cycle);
572 fatal = 1;
573 }
574
575 if (irq_test_cycle > irq_test_cycle_intr) {
576 printf("bad irq_test_cycle: %u %u\n", irq_test_cycle, irq_test_cycle_intr);
577 fatal = 1;
578 }
579
580 if (handler_cycle != handler_cycle_intr) {
581 printf("bad handler_cycle: %u %u\n", handler_cycle, handler_cycle_intr);
582 fatal = 1;
583 }
584
585 if (mem_val != memcheck_read(mem_addr)) {
586 printf("bad mem @%08x: %08x %08x\n", mem_addr, memcheck_read(mem_addr), mem_val);
587 fatal = 1;
588 }
589
590 if (!fatal && !memcmp(&psxRegs, &rregs, offsetof(psxRegisters, intCycle))) {
591 failcount = 0;
592 goto ok;
593 }
594
595 for (i = 0; i < offsetof(psxRegisters, intCycle) / 4; i++) {
596 if (allregs_p[i] != allregs_e[i]) {
597 miss_log_add(i, allregs_p[i], allregs_e[i], psxRegs.pc, psxRegs.cycle);
598 bad++;
599 if (i >= 32)
600 fatal = 1;
601 else
602 badregs_mask |= 1u << i;
603 }
604 }
605
606 if (badregs_mask_prev & badregs_mask)
607 failcount++;
608 else
609 failcount = 0;
610
611 if (!fatal && psxRegs.pc == rregs.pc && bad < 6 && failcount < 24) {
612 static int last_mcycle;
613 if (last_mcycle != psxRegs.cycle >> 20) {
614 printf("%u\n", psxRegs.cycle);
615 last_mcycle = psxRegs.cycle >> 20;
616 }
617 goto ok;
618 }
619
620 for (i = 0; i < miss_log_len; i++, miss_log_i = (miss_log_i + 1) & miss_log_mask)
621 printf("bad %5s: %08x %08x, pc=%08x, cycle %u\n",
622 regnames[miss_log[miss_log_i].reg], miss_log[miss_log_i].val,
623 miss_log[miss_log_i].val_expect, miss_log[miss_log_i].pc, miss_log[miss_log_i].cycle);
624 printf("-- %d\n", bad);
625 for (i = 0; i < 8; i++)
626 printf("r%d=%08x r%2d=%08x r%2d=%08x r%2d=%08x\n", i, allregs_p[i],
627 i+8, allregs_p[i+8], i+16, allregs_p[i+16], i+24, allregs_p[i+24]);
628 printf("PC: %08x/%08x, cycle %u, next %u\n", psxRegs.pc, ppc, psxRegs.cycle, next_interupt);
629 //dump_mem("/tmp/psxram.dump", psxM, 0x200000);
630 //dump_mem("/mnt/ntz/dev/pnd/tmp/psxregs.dump", psxH, 0x10000);
631 exit(1);
632ok:
633 //psxRegs.cycle = rregs.cycle + 2; // sync timing
634 ppc = psxRegs.pc;
635 badregs_mask_prev = badregs_mask;
636}
637
638#endif