drc: finish GTE reg liveness analysis
[pcsx_rearmed.git] / libpcsxcore / new_dynarec / emu_if.c
CommitLineData
7e605697 1/*
009faf24 2 * (C) GraÅžvydas "notaz" Ignotas, 2010-2011
7e605697 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
f95a77f7 8#include <stdio.h>
9
10#include "emu_if.h"
7e605697 11#include "pcsxmem.h"
7139f3c8 12#include "../psxhle.h"
d28b54b1 13#include "../r3000a.h"
52082bc1 14#include "../cdrom.h"
15#include "../psxdma.h"
16#include "../mdec.h"
59774ed0 17#include "../gte_arm.h"
009faf24 18#include "../gte_neon.h"
59774ed0 19#define FLAGLESS
20#include "../gte.h"
7139f3c8 21
ae602c19 22#define ARRAY_SIZE(x) (sizeof(x) / sizeof(x[0]))
23
7139f3c8 24//#define evprintf printf
25#define evprintf(...)
26
f95a77f7 27char invalid_code[0x100000];
d28b54b1 28u32 event_cycles[PSXINT_COUNT];
f95a77f7 29
654e8cfb 30static void schedule_timeslice(void)
f95a77f7 31{
654e8cfb 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}
ae602c19 56
52082bc1 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,
528ad661 66 [PSXINT_MDECINDMA] = mdec0Interrupt,
57a757ce 67 [PSXINT_GPUOTCDMA] = gpuotcInterrupt,
9f8b032d 68 [PSXINT_CDRDMA] = cdrDmaInterrupt,
69 [PSXINT_CDRLID] = cdrLidSeekInterrupt,
7f457614 70 [PSXINT_CDRPLAY] = cdrPlayInterrupt,
52082bc1 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
654e8cfb 102void gen_interupt()
103{
654e8cfb 104 evprintf(" +ge %08x, %u->%u\n", psxRegs.pc, psxRegs.cycle, next_interupt);
7139f3c8 105
52082bc1 106 irq_test();
107 //psxBranchTest();
108 //pending_exception = 1;
7139f3c8 109
654e8cfb 110 schedule_timeslice();
ae602c19 111
654e8cfb 112 evprintf(" -ge %08x, %u->%u (%d)\n", psxRegs.pc, psxRegs.cycle,
113 next_interupt, next_interupt - psxRegs.cycle);
f95a77f7 114}
115
fca1aef2 116// from interpreter
117extern void MTC0(int reg, u32 val);
118
63cb0298 119void pcsx_mtc0(u32 reg, u32 val)
28bc5688 120{
63cb0298 121 evprintf("MTC0 %d #%x @%08x %u\n", reg, val, psxRegs.pc, psxRegs.cycle);
122 MTC0(reg, val);
fca1aef2 123 gen_interupt();
124}
28bc5688 125
63cb0298 126void pcsx_mtc0_ds(u32 reg, u32 val)
fca1aef2 127{
63cb0298 128 evprintf("MTC0 %d #%x @%08x %u\n", reg, val, psxRegs.pc, psxRegs.cycle);
129 MTC0(reg, val);
28bc5688 130}
131
52082bc1 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;
9f8b032d 140 for (i = 0; i < PSXINT_COUNT; i++)
52082bc1 141 event_cycles[i] = psxRegs.intCycle[i].sCycle + psxRegs.intCycle[i].cycle;
b1be1eee 142
143 new_dyna_pcsx_mem_load_state();
52082bc1 144}
145
2167bef6 146/* GTE stuff */
b9b61529 147void *gte_handlers[64];
148
59774ed0 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
bedfea38 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
b9b61529 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};
f95a77f7 179
2167bef6 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
f95a77f7 281static int ari64_init()
282{
b9b61529 283 extern void (*psxCP2[64])();
284 extern void psxNULL();
f95a77f7 285 size_t i;
b9b61529 286
f95a77f7 287 new_dynarec_init();
7e605697 288 new_dyna_pcsx_mem_init();
7139f3c8 289
ae602c19 290 for (i = 0; i < ARRAY_SIZE(gte_handlers); i++)
b9b61529 291 if (psxCP2[i] != psxNULL)
292 gte_handlers[i] = psxCP2[i];
59774ed0 293
294#if !defined(DRC_DBG) && !defined(PCNT)
295#ifdef __arm__
296 gte_handlers[0x06] = gteNCLIP_arm;
0c2ca3ba 297 gte_handlers_nf[0x01] = gteRTPS_nf_arm;
298 gte_handlers_nf[0x30] = gteRTPT_nf_arm;
59774ed0 299#endif
a80ae4a0 300#ifdef __ARM_NEON__
59774ed0 301 // compiler's _nf version is still a lot slower then neon
0c2ca3ba 302 // _nf_arm RTPS is roughly the same, RTPT slower
59774ed0 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;
a80ae4a0 306#endif
d3f3bf09 307#endif
308#ifdef DRC_DBG
309 memcpy(gte_handlers_nf, gte_handlers, sizeof(gte_handlers_nf));
009faf24 310#endif
7e605697 311 psxH_ptr = psxH;
312
b9b61529 313 return 0;
f95a77f7 314}
315
316static void ari64_reset()
317{
f95a77f7 318 printf("ari64_reset\n");
7e605697 319 new_dyna_pcsx_mem_reset();
4b421010 320 invalidate_all_pages();
7f457614 321 new_dyna_restore();
4b421010 322 pending_exception = 1;
f95a77f7 323}
324
e4eb18c1 325// execute until predefined leave points
326// (HLE softcall exit and BIOS fastboot end)
327static void ari64_execute_until()
f95a77f7 328{
654e8cfb 329 schedule_timeslice();
330
331 evprintf("ari64_execute %08x, %u->%u (%d)\n", psxRegs.pc,
332 psxRegs.cycle, next_interupt, next_interupt - psxRegs.cycle);
7139f3c8 333
b9b61529 334 new_dyna_start();
654e8cfb 335
336 evprintf("ari64_execute end %08x, %u->%u (%d)\n", psxRegs.pc,
337 psxRegs.cycle, next_interupt, next_interupt - psxRegs.cycle);
f95a77f7 338}
339
e4eb18c1 340static void ari64_execute()
341{
342 while (!stop) {
343 ari64_execute_until();
344 evprintf("drc left @%08x\n", psxRegs.pc);
345 }
346}
347
4b421010 348static void ari64_clear(u32 addr, u32 size)
f95a77f7 349{
0ce47d46 350 u32 start, end, main_ram;
4b421010 351
76739a08 352 size *= 4; /* PCSX uses DMA units */
353
4b421010 354 evprintf("ari64_clear %08x %04x\n", addr, size);
355
356 /* check for RAM mirrors */
0ce47d46 357 main_ram = (addr & 0xffe00000) == 0x80000000;
4b421010 358
359 start = addr >> 12;
360 end = (addr + size) >> 12;
361
362 for (; start <= end; start++)
0ce47d46 363 if (!main_ram || !invalid_code[start])
4b421010 364 invalidate_block(start);
f95a77f7 365}
366
367static void ari64_shutdown()
368{
369 new_dynarec_cleanup();
370}
371
7139f3c8 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
f95a77f7 381R3000Acpu psxRec = {
382 ari64_init,
383 ari64_reset,
2185e39b 384#if defined(__arm__)
f95a77f7 385 ari64_execute,
e4eb18c1 386 ari64_execute_until,
7139f3c8 387#else
388 intExecuteT,
389 intExecuteBlockT,
390#endif
f95a77f7 391 ari64_clear,
392 ari64_shutdown
393};
7139f3c8 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;
ccf51908 405int pending_exception, stop;
7139f3c8 406unsigned int next_interupt;
2f546f9a 407int new_dynarec_did_compile;
2573466a 408int cycle_multiplier;
7e605697 409void *psxH_ptr;
7139f3c8 410void new_dynarec_init() {}
3eb78778 411void new_dyna_start() {}
7139f3c8 412void new_dynarec_cleanup() {}
2c886904 413void new_dynarec_clear_full() {}
ccf51908 414void invalidate_all_pages() {}
415void invalidate_block(unsigned int block) {}
7e605697 416void new_dyna_pcsx_mem_init(void) {}
417void new_dyna_pcsx_mem_reset(void) {}
b1be1eee 418void new_dyna_pcsx_mem_load_state(void) {}
7139f3c8 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");
3eb78778 430 if (f1 == NULL)
431 f1 = fopen(strrchr(fname, '/') + 1, "wb");
7139f3c8 432 fwrite(mem, 1, size, f1);
433 fclose(f1);
434}
435
2185e39b 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
7139f3c8 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;
2185e39b 458 u32 io_data;
7139f3c8 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 }
2185e39b 480 io_data = memcheck_read(last_io_addr);
481 if (old_io_data != io_data) {
7139f3c8 482 byte = 0xfe;
483 fwrite(&byte, 1, 1, f);
2185e39b 484 fwrite(&io_data, 1, 4, f);
485 old_io_data = io_data;
7139f3c8 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
3eb78778 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
7139f3c8 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
2185e39b 585 psxRegs.cycle = rregs.cycle;
586 psxRegs.CP0.r[9] = rregs.CP0.r[9]; // Count
7139f3c8 587
588//if (psxRegs.cycle == 166172) breakme();
7139f3c8 589
590 if (memcmp(&psxRegs, &rregs, offsetof(psxRegisters, intCycle)) == 0 &&
2185e39b 591 mem_val == memcheck_read(mem_addr)
7139f3c8 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]) {
3eb78778 599 miss_log_add(i, allregs_p[i], allregs_e[i], psxRegs.pc, psxRegs.cycle);
7139f3c8 600 bad++;
601 }
602 }
603
2185e39b 604 if (mem_val != memcheck_read(mem_addr)) {
605 printf("bad mem @%08x: %08x %08x\n", mem_addr, memcheck_read(mem_addr), mem_val);
7139f3c8 606 goto end;
607 }
608
609 if (psxRegs.pc == rregs.pc && bad < 6 && failcount < 32) {
3eb78778 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 }
7139f3c8 615 failcount++;
616 goto ok;
617 }
618
619end:
3eb78778 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],
87c06e51 627 i+8, allregs_p[i+8], i+16, allregs_p[i+16], i+24, allregs_p[i+24]);
7139f3c8 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