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