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