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