gte: parametrize remaining ops
[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 180#define GCBIT(x) \
181 (1ll << (32+x))
182#define GDBIT(x) \
183 (1ll << (x))
184#define GCBITS3(b0,b1,b2) \
185 (GCBIT(b0) | GCBIT(b1) | GCBIT(b2))
186#define GDBITS2(b0,b1) \
187 (GDBIT(b0) | GDBIT(b1))
188#define GDBITS3(b0,b1,b2) \
189 (GDBITS2(b0,b1) | GDBIT(b2))
190#define GDBITS4(b0,b1,b2,b3) \
191 (GDBITS3(b0,b1,b2) | GDBIT(b3))
192#define GDBITS5(b0,b1,b2,b3,b4) \
193 (GDBITS4(b0,b1,b2,b3) | GDBIT(b4))
194#define GDBITS6(b0,b1,b2,b3,b4,b5) \
195 (GDBITS5(b0,b1,b2,b3,b4) | GDBIT(b5))
196#define GDBITS7(b0,b1,b2,b3,b4,b5,b6) \
197 (GDBITS6(b0,b1,b2,b3,b4,b5) | GDBIT(b6))
198#define GDBITS8(b0,b1,b2,b3,b4,b5,b6,b7) \
199 (GDBITS7(b0,b1,b2,b3,b4,b5,b6) | GDBIT(b7))
200#define GDBITS9(b0,b1,b2,b3,b4,b5,b6,b7,b8) \
201 (GDBITS8(b0,b1,b2,b3,b4,b5,b6,b7) | GDBIT(b8))
202#define GDBITS10(b0,b1,b2,b3,b4,b5,b6,b7,b8,b9) \
203 (GDBITS9(b0,b1,b2,b3,b4,b5,b6,b7,b8) | GDBIT(b9))
204
205const uint64_t gte_reg_reads[64] = {
206 [GTE_RTPS] = 0x1f0000ff00000000ll | GDBITS7(0,1,13,14,17,18,19),
207 [GTE_NCLIP] = GDBITS3(12,13,14),
208 [GTE_OP] = GCBITS3(0,2,4) | GDBITS3(9,10,11),
209 [GTE_DPCS] = GCBITS3(21,22,23) | GDBITS4(6,8,21,22),
210 [GTE_INTPL] = GCBITS3(21,22,23) | GDBITS7(6,8,9,10,11,21,22),
211 [GTE_MVMVA] = 0x00ffffff00000000ll | GDBITS6(0,1,2,3,4,5), // XXX: maybe decode further?
212 [GTE_NCDS] = 0x00ffff0000000000ll | GDBITS5(0,1,6,21,22),
213 [GTE_CDP] = 0x00fff00000000000ll | GDBITS7(6,8,9,10,11,21,22),
214 [GTE_NCDT] = 0x00ffff0000000000ll | GDBITS8(0,1,2,3,4,5,6,8),
215 [GTE_NCCS] = 0x00ffff0000000000ll | GDBITS6(0,1,6,8,21,22),
216 [GTE_CC] = 0x001fe00000000000ll | GDBITS6(6,9,10,11,21,22),
217 [GTE_NCS] = 0x001fff0000000000ll | GDBITS4(0,1,21,22),
218 [GTE_NCT] = 0x001fff0000000000ll | GDBITS7(0,1,2,3,4,5,6),
219 [GTE_SQR] = GDBITS3(9,10,11),
220 [GTE_DCPL] = GCBITS3(21,22,23) | GDBITS7(6,8,9,10,11,21,22),
221 [GTE_DPCT] = GCBITS3(21,22,23) | GDBITS4(8,20,21,22),
222 [GTE_AVSZ3] = GCBIT(29) | GDBITS3(17,18,19),
223 [GTE_AVSZ4] = GCBIT(30) | GDBITS4(16,17,18,19),
224 [GTE_RTPT] = 0x1f0000ff00000000ll | GDBITS7(0,1,2,3,4,5,19),
225 [GTE_GPF] = GDBITS7(6,8,9,10,11,21,22),
226 [GTE_GPL] = GDBITS10(6,8,9,10,11,21,22,25,26,27),
227 [GTE_NCCT] = 0x001fff0000000000ll | GDBITS7(0,1,2,3,4,5,6),
228};
229
230// note: this excludes gteFLAG that is always written to
231const uint64_t gte_reg_writes[64] = {
232 [GTE_RTPS] = 0x0f0f7f00ll,
233 [GTE_NCLIP] = GDBIT(24),
234 [GTE_OP] = GDBITS6(9,10,11,25,26,27),
235 [GTE_DPCS] = GDBITS9(9,10,11,20,21,22,25,26,27),
236 [GTE_INTPL] = GDBITS9(9,10,11,20,21,22,25,26,27),
237 [GTE_MVMVA] = GDBITS6(9,10,11,25,26,27),
238 [GTE_NCDS] = GDBITS9(9,10,11,20,21,22,25,26,27),
239 [GTE_CDP] = GDBITS9(9,10,11,20,21,22,25,26,27),
240 [GTE_NCDT] = GDBITS9(9,10,11,20,21,22,25,26,27),
241 [GTE_NCCS] = GDBITS9(9,10,11,20,21,22,25,26,27),
242 [GTE_CC] = GDBITS9(9,10,11,20,21,22,25,26,27),
243 [GTE_NCS] = GDBITS9(9,10,11,20,21,22,25,26,27),
244 [GTE_NCT] = GDBITS9(9,10,11,20,21,22,25,26,27),
245 [GTE_SQR] = GDBITS6(9,10,11,25,26,27),
246 [GTE_DCPL] = GDBITS9(9,10,11,20,21,22,25,26,27),
247 [GTE_DPCT] = GDBITS9(9,10,11,20,21,22,25,26,27),
248 [GTE_AVSZ3] = GDBITS2(7,24),
249 [GTE_AVSZ4] = GDBITS2(7,24),
250 [GTE_RTPT] = 0x0f0f7f00ll,
251 [GTE_GPF] = GDBITS9(9,10,11,20,21,22,25,26,27),
252 [GTE_GPL] = GDBITS9(9,10,11,20,21,22,25,26,27),
253 [GTE_NCCT] = GDBITS9(9,10,11,20,21,22,25,26,27),
254};
255
f95a77f7 256static int ari64_init()
257{
b9b61529 258 extern void (*psxCP2[64])();
259 extern void psxNULL();
f95a77f7 260 size_t i;
b9b61529 261
f95a77f7 262 new_dynarec_init();
7e605697 263 new_dyna_pcsx_mem_init();
7139f3c8 264
ae602c19 265 for (i = 0; i < ARRAY_SIZE(gte_handlers); i++)
b9b61529 266 if (psxCP2[i] != psxNULL)
267 gte_handlers[i] = psxCP2[i];
59774ed0 268
82ed88eb 269#if !defined(DRC_DBG)
59774ed0 270#ifdef __arm__
271 gte_handlers[0x06] = gteNCLIP_arm;
0c2ca3ba 272 gte_handlers_nf[0x01] = gteRTPS_nf_arm;
273 gte_handlers_nf[0x30] = gteRTPT_nf_arm;
59774ed0 274#endif
a80ae4a0 275#ifdef __ARM_NEON__
054175e9 276 // compiler's _nf version is still a lot slower than neon
0c2ca3ba 277 // _nf_arm RTPS is roughly the same, RTPT slower
59774ed0 278 gte_handlers[0x01] = gte_handlers_nf[0x01] = gteRTPS_neon;
279 gte_handlers[0x30] = gte_handlers_nf[0x30] = gteRTPT_neon;
a80ae4a0 280#endif
d3f3bf09 281#endif
282#ifdef DRC_DBG
283 memcpy(gte_handlers_nf, gte_handlers, sizeof(gte_handlers_nf));
009faf24 284#endif
7e605697 285 psxH_ptr = psxH;
054175e9 286 zeromem_ptr = zero_mem;
7e605697 287
b9b61529 288 return 0;
f95a77f7 289}
290
291static void ari64_reset()
292{
f95a77f7 293 printf("ari64_reset\n");
7e605697 294 new_dyna_pcsx_mem_reset();
4b421010 295 invalidate_all_pages();
7f457614 296 new_dyna_restore();
4b421010 297 pending_exception = 1;
f95a77f7 298}
299
e4eb18c1 300// execute until predefined leave points
301// (HLE softcall exit and BIOS fastboot end)
302static void ari64_execute_until()
f95a77f7 303{
654e8cfb 304 schedule_timeslice();
305
306 evprintf("ari64_execute %08x, %u->%u (%d)\n", psxRegs.pc,
307 psxRegs.cycle, next_interupt, next_interupt - psxRegs.cycle);
7139f3c8 308
b9b61529 309 new_dyna_start();
654e8cfb 310
311 evprintf("ari64_execute end %08x, %u->%u (%d)\n", psxRegs.pc,
312 psxRegs.cycle, next_interupt, next_interupt - psxRegs.cycle);
f95a77f7 313}
314
e4eb18c1 315static void ari64_execute()
316{
317 while (!stop) {
318 ari64_execute_until();
319 evprintf("drc left @%08x\n", psxRegs.pc);
320 }
321}
322
4b421010 323static void ari64_clear(u32 addr, u32 size)
f95a77f7 324{
0ce47d46 325 u32 start, end, main_ram;
4b421010 326
76739a08 327 size *= 4; /* PCSX uses DMA units */
328
4b421010 329 evprintf("ari64_clear %08x %04x\n", addr, size);
330
331 /* check for RAM mirrors */
0ce47d46 332 main_ram = (addr & 0xffe00000) == 0x80000000;
4b421010 333
334 start = addr >> 12;
335 end = (addr + size) >> 12;
336
337 for (; start <= end; start++)
0ce47d46 338 if (!main_ram || !invalid_code[start])
4b421010 339 invalidate_block(start);
f95a77f7 340}
341
342static void ari64_shutdown()
343{
344 new_dynarec_cleanup();
345}
346
7139f3c8 347extern void intExecute();
348extern void intExecuteT();
349extern void intExecuteBlock();
350extern void intExecuteBlockT();
351#ifndef DRC_DBG
352#define intExecuteT intExecute
353#define intExecuteBlockT intExecuteBlock
354#endif
355
f95a77f7 356R3000Acpu psxRec = {
357 ari64_init,
358 ari64_reset,
2185e39b 359#if defined(__arm__)
f95a77f7 360 ari64_execute,
e4eb18c1 361 ari64_execute_until,
7139f3c8 362#else
363 intExecuteT,
364 intExecuteBlockT,
365#endif
f95a77f7 366 ari64_clear,
367 ari64_shutdown
368};
7139f3c8 369
370// TODO: rm
371#ifndef DRC_DBG
372void do_insn_trace() {}
373void do_insn_cmp() {}
374#endif
375
376#if defined(__x86_64__) || defined(__i386__)
054175e9 377unsigned int address;
ccf51908 378int pending_exception, stop;
7139f3c8 379unsigned int next_interupt;
2f546f9a 380int new_dynarec_did_compile;
2573466a 381int cycle_multiplier;
7e605697 382void *psxH_ptr;
054175e9 383void *zeromem_ptr;
384u8 zero_mem[0x1000];
7139f3c8 385void new_dynarec_init() {}
3eb78778 386void new_dyna_start() {}
7139f3c8 387void new_dynarec_cleanup() {}
2c886904 388void new_dynarec_clear_full() {}
ccf51908 389void invalidate_all_pages() {}
390void invalidate_block(unsigned int block) {}
7e605697 391void new_dyna_pcsx_mem_init(void) {}
392void new_dyna_pcsx_mem_reset(void) {}
b1be1eee 393void new_dyna_pcsx_mem_load_state(void) {}
7139f3c8 394#endif
395
396#ifdef DRC_DBG
397
398#include <stddef.h>
399static FILE *f;
400extern u32 last_io_addr;
401
402static void dump_mem(const char *fname, void *mem, size_t size)
403{
404 FILE *f1 = fopen(fname, "wb");
3eb78778 405 if (f1 == NULL)
406 f1 = fopen(strrchr(fname, '/') + 1, "wb");
7139f3c8 407 fwrite(mem, 1, size, f1);
408 fclose(f1);
409}
410
2185e39b 411static u32 memcheck_read(u32 a)
412{
413 if ((a >> 16) == 0x1f80)
414 // scratchpad/IO
415 return *(u32 *)(psxH + (a & 0xfffc));
416
417 if ((a >> 16) == 0x1f00)
418 // parallel
419 return *(u32 *)(psxP + (a & 0xfffc));
420
421// if ((a & ~0xe0600000) < 0x200000)
422 // RAM
423 return *(u32 *)(psxM + (a & 0x1ffffc));
424}
425
7139f3c8 426void do_insn_trace(void)
427{
428 static psxRegisters oldregs;
429 static u32 old_io_addr = (u32)-1;
430 static u32 old_io_data = 0xbad0c0de;
431 u32 *allregs_p = (void *)&psxRegs;
432 u32 *allregs_o = (void *)&oldregs;
2185e39b 433 u32 io_data;
7139f3c8 434 int i;
435 u8 byte;
436
437//last_io_addr = 0x5e2c8;
438 if (f == NULL)
439 f = fopen("tracelog", "wb");
440
441 oldregs.code = psxRegs.code; // don't care
442 for (i = 0; i < offsetof(psxRegisters, intCycle) / 4; i++) {
443 if (allregs_p[i] != allregs_o[i]) {
444 fwrite(&i, 1, 1, f);
445 fwrite(&allregs_p[i], 1, 4, f);
446 allregs_o[i] = allregs_p[i];
447 }
448 }
449 if (old_io_addr != last_io_addr) {
450 byte = 0xfd;
451 fwrite(&byte, 1, 1, f);
452 fwrite(&last_io_addr, 1, 4, f);
453 old_io_addr = last_io_addr;
454 }
2185e39b 455 io_data = memcheck_read(last_io_addr);
456 if (old_io_data != io_data) {
7139f3c8 457 byte = 0xfe;
458 fwrite(&byte, 1, 1, f);
2185e39b 459 fwrite(&io_data, 1, 4, f);
460 old_io_data = io_data;
7139f3c8 461 }
462 byte = 0xff;
463 fwrite(&byte, 1, 1, f);
464
465#if 0
466 if (psxRegs.cycle == 190230) {
467 dump_mem("/mnt/ntz/dev/pnd/tmp/psxram_i.dump", psxM, 0x200000);
468 dump_mem("/mnt/ntz/dev/pnd/tmp/psxregs_i.dump", psxH, 0x10000);
469 printf("dumped\n");
470 exit(1);
471 }
472#endif
473}
474
475static const char *regnames[offsetof(psxRegisters, intCycle) / 4] = {
476 "r0", "r1", "r2", "r3", "r4", "r5", "r6", "r7",
477 "r8", "r9", "r10", "r11", "r12", "r13", "r14", "r15",
478 "r16", "r17", "r18", "r19", "r20", "r21", "r22", "r23",
479 "r24", "r25", "r26", "r27", "r28", "r29", "r30", "r31",
480 "lo", "hi",
481 "C0_0", "C0_1", "C0_2", "C0_3", "C0_4", "C0_5", "C0_6", "C0_7",
482 "C0_8", "C0_9", "C0_10", "C0_11", "C0_12", "C0_13", "C0_14", "C0_15",
483 "C0_16", "C0_17", "C0_18", "C0_19", "C0_20", "C0_21", "C0_22", "C0_23",
484 "C0_24", "C0_25", "C0_26", "C0_27", "C0_28", "C0_29", "C0_30", "C0_31",
485
486 "C2D0", "C2D1", "C2D2", "C2D3", "C2D4", "C2D5", "C2D6", "C2D7",
487 "C2D8", "C2D9", "C2D10", "C2D11", "C2D12", "C2D13", "C2D14", "C2D15",
488 "C2D16", "C2D17", "C2D18", "C2D19", "C2D20", "C2D21", "C2D22", "C2D23",
489 "C2D24", "C2D25", "C2D26", "C2D27", "C2D28", "C2D29", "C2D30", "C2D31",
490
491 "C2C0", "C2C1", "C2C2", "C2C3", "C2C4", "C2C5", "C2C6", "C2C7",
492 "C2C8", "C2C9", "C2C10", "C2C11", "C2C12", "C2C13", "C2C14", "C2C15",
493 "C2C16", "C2C17", "C2C18", "C2C19", "C2C20", "C2C21", "C2C22", "C2C23",
494 "C2C24", "C2C25", "C2C26", "C2C27", "C2C28", "C2C29", "C2C30", "C2C31",
495
496 "PC", "code", "cycle", "interrupt",
497};
498
3eb78778 499static struct {
500 int reg;
501 u32 val, val_expect;
502 u32 pc, cycle;
503} miss_log[64];
504static int miss_log_i;
505#define miss_log_len (sizeof(miss_log)/sizeof(miss_log[0]))
506#define miss_log_mask (miss_log_len-1)
507
508static void miss_log_add(int reg, u32 val, u32 val_expect, u32 pc, u32 cycle)
509{
510 miss_log[miss_log_i].reg = reg;
511 miss_log[miss_log_i].val = val;
512 miss_log[miss_log_i].val_expect = val_expect;
513 miss_log[miss_log_i].pc = pc;
514 miss_log[miss_log_i].cycle = cycle;
515 miss_log_i = (miss_log_i + 1) & miss_log_mask;
516}
517
7139f3c8 518void breakme() {}
519
520void do_insn_cmp(void)
521{
522 static psxRegisters rregs;
523 static u32 mem_addr, mem_val;
524 u32 *allregs_p = (void *)&psxRegs;
525 u32 *allregs_e = (void *)&rregs;
526 static u32 ppc, failcount;
527 int i, ret, bad = 0;
528 u8 code;
529
530 if (f == NULL)
531 f = fopen("tracelog", "rb");
532
533 while (1) {
534 if ((ret = fread(&code, 1, 1, f)) <= 0)
535 break;
536 if (ret <= 0)
537 break;
538 if (code == 0xff)
539 break;
540 if (code == 0xfd) {
541 if ((ret = fread(&mem_addr, 1, 4, f)) <= 0)
542 break;
543 continue;
544 }
545 if (code == 0xfe) {
546 if ((ret = fread(&mem_val, 1, 4, f)) <= 0)
547 break;
548 continue;
549 }
550 if ((ret = fread(&allregs_e[code], 1, 4, f)) <= 0)
551 break;
552 }
553
554 if (ret <= 0) {
555 printf("EOF?\n");
556 goto end;
557 }
558
559 psxRegs.code = rregs.code; // don't care
2185e39b 560 psxRegs.cycle = rregs.cycle;
561 psxRegs.CP0.r[9] = rregs.CP0.r[9]; // Count
7139f3c8 562
563//if (psxRegs.cycle == 166172) breakme();
7139f3c8 564
565 if (memcmp(&psxRegs, &rregs, offsetof(psxRegisters, intCycle)) == 0 &&
2185e39b 566 mem_val == memcheck_read(mem_addr)
7139f3c8 567 ) {
568 failcount = 0;
569 goto ok;
570 }
571
572 for (i = 0; i < offsetof(psxRegisters, intCycle) / 4; i++) {
573 if (allregs_p[i] != allregs_e[i]) {
3eb78778 574 miss_log_add(i, allregs_p[i], allregs_e[i], psxRegs.pc, psxRegs.cycle);
7139f3c8 575 bad++;
576 }
577 }
578
2185e39b 579 if (mem_val != memcheck_read(mem_addr)) {
580 printf("bad mem @%08x: %08x %08x\n", mem_addr, memcheck_read(mem_addr), mem_val);
7139f3c8 581 goto end;
582 }
583
584 if (psxRegs.pc == rregs.pc && bad < 6 && failcount < 32) {
3eb78778 585 static int last_mcycle;
586 if (last_mcycle != psxRegs.cycle >> 20) {
587 printf("%u\n", psxRegs.cycle);
588 last_mcycle = psxRegs.cycle >> 20;
589 }
7139f3c8 590 failcount++;
591 goto ok;
592 }
593
594end:
3eb78778 595 for (i = 0; i < miss_log_len; i++, miss_log_i = (miss_log_i + 1) & miss_log_mask)
596 printf("bad %5s: %08x %08x, pc=%08x, cycle %u\n",
597 regnames[miss_log[miss_log_i].reg], miss_log[miss_log_i].val,
598 miss_log[miss_log_i].val_expect, miss_log[miss_log_i].pc, miss_log[miss_log_i].cycle);
599 printf("-- %d\n", bad);
600 for (i = 0; i < 8; i++)
601 printf("r%d=%08x r%2d=%08x r%2d=%08x r%2d=%08x\n", i, allregs_p[i],
87c06e51 602 i+8, allregs_p[i+8], i+16, allregs_p[i+16], i+24, allregs_p[i+24]);
7139f3c8 603 printf("PC: %08x/%08x, cycle %u\n", psxRegs.pc, ppc, psxRegs.cycle);
604 dump_mem("/mnt/ntz/dev/pnd/tmp/psxram.dump", psxM, 0x200000);
605 dump_mem("/mnt/ntz/dev/pnd/tmp/psxregs.dump", psxH, 0x10000);
606 exit(1);
607ok:
608 psxRegs.cycle = rregs.cycle + 2; // sync timing
609 ppc = psxRegs.pc;
610}
611
612#endif