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