Merge pull request #578 from gameblabla/counters_lib
[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
7a811716 401#ifdef ICACHE_EMULATION
402static void ari64_notify(int note, void *data) {
403 /*
404 To change once we have proper icache emulation
405 switch (note)
406 {
407 case R3000ACPU_NOTIFY_CACHE_UNISOLATED:
408 ari64_clear(0, 0x200000/4);
409 break;
410 case R3000ACPU_NOTIFY_CACHE_ISOLATED:
411 // Sent from psxDma3().
412 case R3000ACPU_NOTIFY_DMA3_EXE_LOAD:
413 default:
414 break;
415 }*/
416}
417#endif
418
f95a77f7 419static void ari64_shutdown()
420{
421 new_dynarec_cleanup();
92879b62 422 new_dyna_pcsx_mem_shutdown();
f95a77f7 423}
424
7139f3c8 425extern void intExecute();
426extern void intExecuteT();
427extern void intExecuteBlock();
428extern void intExecuteBlockT();
429#ifndef DRC_DBG
430#define intExecuteT intExecute
431#define intExecuteBlockT intExecuteBlock
432#endif
433
f95a77f7 434R3000Acpu psxRec = {
435 ari64_init,
436 ari64_reset,
448bbcae 437#ifndef DRC_DISABLE
f95a77f7 438 ari64_execute,
e4eb18c1 439 ari64_execute_until,
7139f3c8 440#else
441 intExecuteT,
442 intExecuteBlockT,
443#endif
f95a77f7 444 ari64_clear,
7a811716 445#ifdef ICACHE_EMULATION
446 ari64_notify,
447#endif
f95a77f7 448 ari64_shutdown
449};
7139f3c8 450
451// TODO: rm
452#ifndef DRC_DBG
453void do_insn_trace() {}
454void do_insn_cmp() {}
455#endif
456
448bbcae 457#ifdef DRC_DISABLE
054175e9 458unsigned int address;
ccf51908 459int pending_exception, stop;
c4052f4d 460u32 next_interupt;
2f546f9a 461int new_dynarec_did_compile;
2573466a 462int cycle_multiplier;
0ff8c62c 463int new_dynarec_hacks;
7e605697 464void *psxH_ptr;
054175e9 465void *zeromem_ptr;
466u8 zero_mem[0x1000];
003cfc63 467unsigned char *out;
0069615f 468void *mem_rtab;
c6d5790c 469void *scratch_buf_ptr;
448bbcae 470void new_dynarec_init() { (void)ari64_execute; }
3eb78778 471void new_dyna_start() {}
7139f3c8 472void new_dynarec_cleanup() {}
2c886904 473void new_dynarec_clear_full() {}
ccf51908 474void invalidate_all_pages() {}
475void invalidate_block(unsigned int block) {}
7e605697 476void new_dyna_pcsx_mem_init(void) {}
477void new_dyna_pcsx_mem_reset(void) {}
b1be1eee 478void new_dyna_pcsx_mem_load_state(void) {}
92879b62 479void new_dyna_pcsx_mem_shutdown(void) {}
03f55e6b 480int new_dynarec_save_blocks(void *save, int size) { return 0; }
481void new_dynarec_load_blocks(const void *save, int size) {}
7139f3c8 482#endif
483
484#ifdef DRC_DBG
485
486#include <stddef.h>
487static FILE *f;
488extern u32 last_io_addr;
489
490static void dump_mem(const char *fname, void *mem, size_t size)
491{
492 FILE *f1 = fopen(fname, "wb");
3eb78778 493 if (f1 == NULL)
494 f1 = fopen(strrchr(fname, '/') + 1, "wb");
7139f3c8 495 fwrite(mem, 1, size, f1);
496 fclose(f1);
497}
498
2185e39b 499static u32 memcheck_read(u32 a)
500{
501 if ((a >> 16) == 0x1f80)
502 // scratchpad/IO
503 return *(u32 *)(psxH + (a & 0xfffc));
504
505 if ((a >> 16) == 0x1f00)
506 // parallel
507 return *(u32 *)(psxP + (a & 0xfffc));
508
509// if ((a & ~0xe0600000) < 0x200000)
510 // RAM
511 return *(u32 *)(psxM + (a & 0x1ffffc));
512}
513
7139f3c8 514void do_insn_trace(void)
515{
516 static psxRegisters oldregs;
517 static u32 old_io_addr = (u32)-1;
518 static u32 old_io_data = 0xbad0c0de;
19776aef 519 static u32 event_cycles_o[PSXINT_COUNT];
7139f3c8 520 u32 *allregs_p = (void *)&psxRegs;
521 u32 *allregs_o = (void *)&oldregs;
2185e39b 522 u32 io_data;
7139f3c8 523 int i;
524 u8 byte;
525
19776aef 526 //last_io_addr = 0x5e2c8;
7139f3c8 527 if (f == NULL)
528 f = fopen("tracelog", "wb");
529
19776aef 530 // log reg changes
7139f3c8 531 oldregs.code = psxRegs.code; // don't care
532 for (i = 0; i < offsetof(psxRegisters, intCycle) / 4; i++) {
533 if (allregs_p[i] != allregs_o[i]) {
534 fwrite(&i, 1, 1, f);
535 fwrite(&allregs_p[i], 1, 4, f);
536 allregs_o[i] = allregs_p[i];
537 }
538 }
19776aef 539 // log event changes
540 for (i = 0; i < PSXINT_COUNT; i++) {
541 if (event_cycles[i] != event_cycles_o[i]) {
542 byte = 0xfc;
543 fwrite(&byte, 1, 1, f);
544 fwrite(&i, 1, 1, f);
545 fwrite(&event_cycles[i], 1, 4, f);
546 event_cycles_o[i] = event_cycles[i];
547 }
548 }
549 // log last io
7139f3c8 550 if (old_io_addr != last_io_addr) {
551 byte = 0xfd;
552 fwrite(&byte, 1, 1, f);
553 fwrite(&last_io_addr, 1, 4, f);
554 old_io_addr = last_io_addr;
555 }
2185e39b 556 io_data = memcheck_read(last_io_addr);
557 if (old_io_data != io_data) {
7139f3c8 558 byte = 0xfe;
559 fwrite(&byte, 1, 1, f);
2185e39b 560 fwrite(&io_data, 1, 4, f);
561 old_io_data = io_data;
7139f3c8 562 }
563 byte = 0xff;
564 fwrite(&byte, 1, 1, f);
565
566#if 0
567 if (psxRegs.cycle == 190230) {
568 dump_mem("/mnt/ntz/dev/pnd/tmp/psxram_i.dump", psxM, 0x200000);
569 dump_mem("/mnt/ntz/dev/pnd/tmp/psxregs_i.dump", psxH, 0x10000);
570 printf("dumped\n");
571 exit(1);
572 }
573#endif
574}
575
576static const char *regnames[offsetof(psxRegisters, intCycle) / 4] = {
577 "r0", "r1", "r2", "r3", "r4", "r5", "r6", "r7",
578 "r8", "r9", "r10", "r11", "r12", "r13", "r14", "r15",
579 "r16", "r17", "r18", "r19", "r20", "r21", "r22", "r23",
580 "r24", "r25", "r26", "r27", "r28", "r29", "r30", "r31",
581 "lo", "hi",
582 "C0_0", "C0_1", "C0_2", "C0_3", "C0_4", "C0_5", "C0_6", "C0_7",
583 "C0_8", "C0_9", "C0_10", "C0_11", "C0_12", "C0_13", "C0_14", "C0_15",
584 "C0_16", "C0_17", "C0_18", "C0_19", "C0_20", "C0_21", "C0_22", "C0_23",
585 "C0_24", "C0_25", "C0_26", "C0_27", "C0_28", "C0_29", "C0_30", "C0_31",
586
587 "C2D0", "C2D1", "C2D2", "C2D3", "C2D4", "C2D5", "C2D6", "C2D7",
588 "C2D8", "C2D9", "C2D10", "C2D11", "C2D12", "C2D13", "C2D14", "C2D15",
589 "C2D16", "C2D17", "C2D18", "C2D19", "C2D20", "C2D21", "C2D22", "C2D23",
590 "C2D24", "C2D25", "C2D26", "C2D27", "C2D28", "C2D29", "C2D30", "C2D31",
591
592 "C2C0", "C2C1", "C2C2", "C2C3", "C2C4", "C2C5", "C2C6", "C2C7",
593 "C2C8", "C2C9", "C2C10", "C2C11", "C2C12", "C2C13", "C2C14", "C2C15",
594 "C2C16", "C2C17", "C2C18", "C2C19", "C2C20", "C2C21", "C2C22", "C2C23",
595 "C2C24", "C2C25", "C2C26", "C2C27", "C2C28", "C2C29", "C2C30", "C2C31",
596
597 "PC", "code", "cycle", "interrupt",
598};
599
3eb78778 600static struct {
601 int reg;
602 u32 val, val_expect;
603 u32 pc, cycle;
604} miss_log[64];
605static int miss_log_i;
606#define miss_log_len (sizeof(miss_log)/sizeof(miss_log[0]))
607#define miss_log_mask (miss_log_len-1)
608
609static void miss_log_add(int reg, u32 val, u32 val_expect, u32 pc, u32 cycle)
610{
611 miss_log[miss_log_i].reg = reg;
612 miss_log[miss_log_i].val = val;
613 miss_log[miss_log_i].val_expect = val_expect;
614 miss_log[miss_log_i].pc = pc;
615 miss_log[miss_log_i].cycle = cycle;
616 miss_log_i = (miss_log_i + 1) & miss_log_mask;
617}
618
7139f3c8 619void breakme() {}
620
621void do_insn_cmp(void)
622{
623 static psxRegisters rregs;
624 static u32 mem_addr, mem_val;
625 u32 *allregs_p = (void *)&psxRegs;
626 u32 *allregs_e = (void *)&rregs;
627 static u32 ppc, failcount;
19776aef 628 int i, ret, bad = 0, which_event = -1;
629 u32 ev_cycles = 0;
7139f3c8 630 u8 code;
631
632 if (f == NULL)
633 f = fopen("tracelog", "rb");
634
635 while (1) {
636 if ((ret = fread(&code, 1, 1, f)) <= 0)
637 break;
638 if (ret <= 0)
639 break;
640 if (code == 0xff)
641 break;
19776aef 642 switch (code) {
643 case 0xfc:
644 which_event = 0;
645 fread(&which_event, 1, 1, f);
646 fread(&ev_cycles, 1, 4, f);
7139f3c8 647 continue;
19776aef 648 case 0xfd:
649 fread(&mem_addr, 1, 4, f);
650 continue;
651 case 0xfe:
652 fread(&mem_val, 1, 4, f);
7139f3c8 653 continue;
654 }
19776aef 655 fread(&allregs_e[code], 1, 4, f);
7139f3c8 656 }
657
658 if (ret <= 0) {
659 printf("EOF?\n");
660 goto end;
661 }
662
663 psxRegs.code = rregs.code; // don't care
2185e39b 664 psxRegs.cycle = rregs.cycle;
665 psxRegs.CP0.r[9] = rregs.CP0.r[9]; // Count
7139f3c8 666
19776aef 667 //if (psxRegs.cycle == 166172) breakme();
7139f3c8 668
669 if (memcmp(&psxRegs, &rregs, offsetof(psxRegisters, intCycle)) == 0 &&
2185e39b 670 mem_val == memcheck_read(mem_addr)
7139f3c8 671 ) {
672 failcount = 0;
673 goto ok;
674 }
675
676 for (i = 0; i < offsetof(psxRegisters, intCycle) / 4; i++) {
677 if (allregs_p[i] != allregs_e[i]) {
3eb78778 678 miss_log_add(i, allregs_p[i], allregs_e[i], psxRegs.pc, psxRegs.cycle);
7139f3c8 679 bad++;
680 }
681 }
682
2185e39b 683 if (mem_val != memcheck_read(mem_addr)) {
684 printf("bad mem @%08x: %08x %08x\n", mem_addr, memcheck_read(mem_addr), mem_val);
7139f3c8 685 goto end;
19776aef 686 }
687
688 if (which_event >= 0 && event_cycles[which_event] != ev_cycles) {
689 printf("bad ev_cycles #%d: %08x %08x\n", which_event, event_cycles[which_event], ev_cycles);
690 goto end;
7139f3c8 691 }
692
693 if (psxRegs.pc == rregs.pc && bad < 6 && failcount < 32) {
3eb78778 694 static int last_mcycle;
695 if (last_mcycle != psxRegs.cycle >> 20) {
696 printf("%u\n", psxRegs.cycle);
697 last_mcycle = psxRegs.cycle >> 20;
698 }
7139f3c8 699 failcount++;
700 goto ok;
701 }
702
703end:
3eb78778 704 for (i = 0; i < miss_log_len; i++, miss_log_i = (miss_log_i + 1) & miss_log_mask)
705 printf("bad %5s: %08x %08x, pc=%08x, cycle %u\n",
706 regnames[miss_log[miss_log_i].reg], miss_log[miss_log_i].val,
707 miss_log[miss_log_i].val_expect, miss_log[miss_log_i].pc, miss_log[miss_log_i].cycle);
708 printf("-- %d\n", bad);
709 for (i = 0; i < 8; i++)
710 printf("r%d=%08x r%2d=%08x r%2d=%08x r%2d=%08x\n", i, allregs_p[i],
87c06e51 711 i+8, allregs_p[i+8], i+16, allregs_p[i+16], i+24, allregs_p[i+24]);
7139f3c8 712 printf("PC: %08x/%08x, cycle %u\n", psxRegs.pc, ppc, psxRegs.cycle);
713 dump_mem("/mnt/ntz/dev/pnd/tmp/psxram.dump", psxM, 0x200000);
714 dump_mem("/mnt/ntz/dev/pnd/tmp/psxregs.dump", psxH, 0x10000);
715 exit(1);
716ok:
717 psxRegs.cycle = rregs.cycle + 2; // sync timing
718 ppc = psxRegs.pc;
719}
720
721#endif