drc: get rid of SPAN
[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();
f95a77f7 299 size_t i;
b9b61529 300
f95a77f7 301 new_dynarec_init();
7e605697 302 new_dyna_pcsx_mem_init();
7139f3c8 303
ae602c19 304 for (i = 0; i < ARRAY_SIZE(gte_handlers); i++)
b9b61529 305 if (psxCP2[i] != psxNULL)
306 gte_handlers[i] = psxCP2[i];
59774ed0 307
665f33e1 308#if defined(__arm__) && !defined(DRC_DBG)
59774ed0 309 gte_handlers[0x06] = gteNCLIP_arm;
665f33e1 310#ifdef HAVE_ARMV5
0c2ca3ba 311 gte_handlers_nf[0x01] = gteRTPS_nf_arm;
312 gte_handlers_nf[0x30] = gteRTPT_nf_arm;
59774ed0 313#endif
a80ae4a0 314#ifdef __ARM_NEON__
054175e9 315 // compiler's _nf version is still a lot slower than neon
0c2ca3ba 316 // _nf_arm RTPS is roughly the same, RTPT slower
59774ed0 317 gte_handlers[0x01] = gte_handlers_nf[0x01] = gteRTPS_neon;
318 gte_handlers[0x30] = gte_handlers_nf[0x30] = gteRTPT_neon;
a80ae4a0 319#endif
d3f3bf09 320#endif
321#ifdef DRC_DBG
322 memcpy(gte_handlers_nf, gte_handlers, sizeof(gte_handlers_nf));
009faf24 323#endif
7e605697 324 psxH_ptr = psxH;
054175e9 325 zeromem_ptr = zero_mem;
c6d5790c 326 scratch_buf_ptr = scratch_buf;
7e605697 327
b9b61529 328 return 0;
f95a77f7 329}
330
331static void ari64_reset()
332{
f95a77f7 333 printf("ari64_reset\n");
7e605697 334 new_dyna_pcsx_mem_reset();
4b421010 335 invalidate_all_pages();
7f457614 336 new_dyna_restore();
4b421010 337 pending_exception = 1;
f95a77f7 338}
339
e4eb18c1 340// execute until predefined leave points
341// (HLE softcall exit and BIOS fastboot end)
342static void ari64_execute_until()
f95a77f7 343{
654e8cfb 344 schedule_timeslice();
345
346 evprintf("ari64_execute %08x, %u->%u (%d)\n", psxRegs.pc,
347 psxRegs.cycle, next_interupt, next_interupt - psxRegs.cycle);
7139f3c8 348
be516ebe 349 new_dyna_start(dynarec_local);
654e8cfb 350
351 evprintf("ari64_execute end %08x, %u->%u (%d)\n", psxRegs.pc,
352 psxRegs.cycle, next_interupt, next_interupt - psxRegs.cycle);
f95a77f7 353}
354
e4eb18c1 355static void ari64_execute()
356{
357 while (!stop) {
358 ari64_execute_until();
359 evprintf("drc left @%08x\n", psxRegs.pc);
360 }
361}
362
4b421010 363static void ari64_clear(u32 addr, u32 size)
f95a77f7 364{
0ce47d46 365 u32 start, end, main_ram;
4b421010 366
58ebb94c 367 size *= 4; /* PCSX uses DMA units (words) */
76739a08 368
4b421010 369 evprintf("ari64_clear %08x %04x\n", addr, size);
370
371 /* check for RAM mirrors */
0ce47d46 372 main_ram = (addr & 0xffe00000) == 0x80000000;
4b421010 373
374 start = addr >> 12;
375 end = (addr + size) >> 12;
376
377 for (; start <= end; start++)
0ce47d46 378 if (!main_ram || !invalid_code[start])
4b421010 379 invalidate_block(start);
f95a77f7 380}
381
943a507a 382static void ari64_notify(int note, void *data) {
383 /*
384 Should be fixed when ARM dynarec has proper icache emulation.
385 switch (note)
386 {
387 case R3000ACPU_NOTIFY_CACHE_UNISOLATED:
388 break;
389 case R3000ACPU_NOTIFY_CACHE_ISOLATED:
390 Sent from psxDma3().
391 case R3000ACPU_NOTIFY_DMA3_EXE_LOAD:
392 default:
393 break;
394 }
395 */
396}
943a507a 397
32631e6a 398static void ari64_apply_config()
399{
61ad2a61 400 intApplyConfig();
401
32631e6a 402 if (Config.DisableStalls)
403 new_dynarec_hacks |= NDHACK_NO_STALLS;
404 else
405 new_dynarec_hacks &= ~NDHACK_NO_STALLS;
406
407 if (cycle_multiplier != cycle_multiplier_old
408 || new_dynarec_hacks != new_dynarec_hacks_old)
409 {
410 new_dynarec_clear_full();
411 }
412}
413
f95a77f7 414static void ari64_shutdown()
415{
416 new_dynarec_cleanup();
92879b62 417 new_dyna_pcsx_mem_shutdown();
f95a77f7 418}
419
420R3000Acpu psxRec = {
421 ari64_init,
422 ari64_reset,
423 ari64_execute,
e4eb18c1 424 ari64_execute_until,
f95a77f7 425 ari64_clear,
943a507a 426 ari64_notify,
32631e6a 427 ari64_apply_config,
f95a77f7 428 ari64_shutdown
429};
7139f3c8 430
d6348639 431#else // if DRC_DISABLE
7139f3c8 432
054175e9 433unsigned int address;
ccf51908 434int pending_exception, stop;
7139f3c8 435unsigned int next_interupt;
2f546f9a 436int new_dynarec_did_compile;
2573466a 437int cycle_multiplier;
17ce04cc 438int cycle_multiplier_override;
32631e6a 439int cycle_multiplier_old;
d62c125a 440int new_dynarec_hacks_pergame;
32631e6a 441int new_dynarec_hacks_old;
0ff8c62c 442int new_dynarec_hacks;
7e605697 443void *psxH_ptr;
054175e9 444void *zeromem_ptr;
445u8 zero_mem[0x1000];
0069615f 446void *mem_rtab;
c6d5790c 447void *scratch_buf_ptr;
d6348639 448void new_dynarec_init() {}
be516ebe 449void new_dyna_start(void *context) {}
7139f3c8 450void new_dynarec_cleanup() {}
2c886904 451void new_dynarec_clear_full() {}
ccf51908 452void invalidate_all_pages() {}
453void invalidate_block(unsigned int block) {}
7e605697 454void new_dyna_pcsx_mem_init(void) {}
455void new_dyna_pcsx_mem_reset(void) {}
b1be1eee 456void new_dyna_pcsx_mem_load_state(void) {}
92879b62 457void new_dyna_pcsx_mem_shutdown(void) {}
03f55e6b 458int new_dynarec_save_blocks(void *save, int size) { return 0; }
459void new_dynarec_load_blocks(const void *save, int size) {}
7139f3c8 460#endif
461
462#ifdef DRC_DBG
463
464#include <stddef.h>
465static FILE *f;
2330734f 466u32 irq_test_cycle;
467u32 handler_cycle;
468u32 last_io_addr;
7139f3c8 469
079ab0c6 470void dump_mem(const char *fname, void *mem, size_t size)
7139f3c8 471{
472 FILE *f1 = fopen(fname, "wb");
3eb78778 473 if (f1 == NULL)
474 f1 = fopen(strrchr(fname, '/') + 1, "wb");
7139f3c8 475 fwrite(mem, 1, size, f1);
476 fclose(f1);
477}
478
2185e39b 479static u32 memcheck_read(u32 a)
480{
481 if ((a >> 16) == 0x1f80)
482 // scratchpad/IO
483 return *(u32 *)(psxH + (a & 0xfffc));
484
485 if ((a >> 16) == 0x1f00)
486 // parallel
487 return *(u32 *)(psxP + (a & 0xfffc));
488
489// if ((a & ~0xe0600000) < 0x200000)
490 // RAM
491 return *(u32 *)(psxM + (a & 0x1ffffc));
492}
493
dd114d7d 494#if 0
7139f3c8 495void do_insn_trace(void)
496{
497 static psxRegisters oldregs;
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]) {
2330734f 521 byte = 0xf8;
19776aef 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 }
2330734f 528 #define SAVE_IF_CHANGED(code_, name_) { \
529 static u32 old_##name_ = 0xbad0c0de; \
530 if (old_##name_ != name_) { \
531 byte = code_; \
532 fwrite(&byte, 1, 1, f); \
533 fwrite(&name_, 1, 4, f); \
534 old_##name_ = name_; \
535 } \
7139f3c8 536 }
2330734f 537 SAVE_IF_CHANGED(0xfb, irq_test_cycle);
538 SAVE_IF_CHANGED(0xfc, handler_cycle);
539 SAVE_IF_CHANGED(0xfd, last_io_addr);
2185e39b 540 io_data = memcheck_read(last_io_addr);
2330734f 541 SAVE_IF_CHANGED(0xfe, io_data);
7139f3c8 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}
dd114d7d 554#endif
7139f3c8 555
556static const char *regnames[offsetof(psxRegisters, intCycle) / 4] = {
557 "r0", "r1", "r2", "r3", "r4", "r5", "r6", "r7",
558 "r8", "r9", "r10", "r11", "r12", "r13", "r14", "r15",
559 "r16", "r17", "r18", "r19", "r20", "r21", "r22", "r23",
560 "r24", "r25", "r26", "r27", "r28", "r29", "r30", "r31",
561 "lo", "hi",
562 "C0_0", "C0_1", "C0_2", "C0_3", "C0_4", "C0_5", "C0_6", "C0_7",
563 "C0_8", "C0_9", "C0_10", "C0_11", "C0_12", "C0_13", "C0_14", "C0_15",
564 "C0_16", "C0_17", "C0_18", "C0_19", "C0_20", "C0_21", "C0_22", "C0_23",
565 "C0_24", "C0_25", "C0_26", "C0_27", "C0_28", "C0_29", "C0_30", "C0_31",
566
567 "C2D0", "C2D1", "C2D2", "C2D3", "C2D4", "C2D5", "C2D6", "C2D7",
568 "C2D8", "C2D9", "C2D10", "C2D11", "C2D12", "C2D13", "C2D14", "C2D15",
569 "C2D16", "C2D17", "C2D18", "C2D19", "C2D20", "C2D21", "C2D22", "C2D23",
570 "C2D24", "C2D25", "C2D26", "C2D27", "C2D28", "C2D29", "C2D30", "C2D31",
571
572 "C2C0", "C2C1", "C2C2", "C2C3", "C2C4", "C2C5", "C2C6", "C2C7",
573 "C2C8", "C2C9", "C2C10", "C2C11", "C2C12", "C2C13", "C2C14", "C2C15",
574 "C2C16", "C2C17", "C2C18", "C2C19", "C2C20", "C2C21", "C2C22", "C2C23",
575 "C2C24", "C2C25", "C2C26", "C2C27", "C2C28", "C2C29", "C2C30", "C2C31",
576
577 "PC", "code", "cycle", "interrupt",
578};
579
3eb78778 580static struct {
581 int reg;
582 u32 val, val_expect;
583 u32 pc, cycle;
584} miss_log[64];
585static int miss_log_i;
586#define miss_log_len (sizeof(miss_log)/sizeof(miss_log[0]))
587#define miss_log_mask (miss_log_len-1)
588
589static void miss_log_add(int reg, u32 val, u32 val_expect, u32 pc, u32 cycle)
590{
591 miss_log[miss_log_i].reg = reg;
592 miss_log[miss_log_i].val = val;
593 miss_log[miss_log_i].val_expect = val_expect;
594 miss_log[miss_log_i].pc = pc;
595 miss_log[miss_log_i].cycle = cycle;
596 miss_log_i = (miss_log_i + 1) & miss_log_mask;
597}
598
7139f3c8 599void breakme() {}
600
601void do_insn_cmp(void)
602{
2330734f 603 extern int last_count;
7139f3c8 604 static psxRegisters rregs;
605 static u32 mem_addr, mem_val;
2330734f 606 static u32 irq_test_cycle_intr;
607 static u32 handler_cycle_intr;
7139f3c8 608 u32 *allregs_p = (void *)&psxRegs;
609 u32 *allregs_e = (void *)&rregs;
610 static u32 ppc, failcount;
2330734f 611 int i, ret, bad = 0, fatal = 0, which_event = -1;
19776aef 612 u32 ev_cycles = 0;
7139f3c8 613 u8 code;
614
615 if (f == NULL)
616 f = fopen("tracelog", "rb");
617
618 while (1) {
619 if ((ret = fread(&code, 1, 1, f)) <= 0)
620 break;
621 if (ret <= 0)
622 break;
623 if (code == 0xff)
624 break;
19776aef 625 switch (code) {
2330734f 626 case 0xf8:
19776aef 627 which_event = 0;
628 fread(&which_event, 1, 1, f);
629 fread(&ev_cycles, 1, 4, f);
7139f3c8 630 continue;
2330734f 631 case 0xfb:
632 fread(&irq_test_cycle_intr, 1, 4, f);
633 continue;
634 case 0xfc:
635 fread(&handler_cycle_intr, 1, 4, f);
636 continue;
19776aef 637 case 0xfd:
638 fread(&mem_addr, 1, 4, f);
639 continue;
640 case 0xfe:
641 fread(&mem_val, 1, 4, f);
7139f3c8 642 continue;
643 }
2330734f 644 assert(code < offsetof(psxRegisters, intCycle) / 4);
19776aef 645 fread(&allregs_e[code], 1, 4, f);
7139f3c8 646 }
647
648 if (ret <= 0) {
649 printf("EOF?\n");
2330734f 650 exit(1);
7139f3c8 651 }
652
653 psxRegs.code = rregs.code; // don't care
2330734f 654 psxRegs.cycle += last_count;
079ab0c6 655 //psxRegs.cycle = rregs.cycle; // needs reload in _cmp
2185e39b 656 psxRegs.CP0.r[9] = rregs.CP0.r[9]; // Count
7139f3c8 657
19776aef 658 //if (psxRegs.cycle == 166172) breakme();
7139f3c8 659
2330734f 660 if (which_event >= 0 && event_cycles[which_event] != ev_cycles) {
661 printf("bad ev_cycles #%d: %08x %08x\n", which_event, event_cycles[which_event], ev_cycles);
662 fatal = 1;
663 }
664
665 if (irq_test_cycle > irq_test_cycle_intr) {
666 printf("bad irq_test_cycle: %u %u\n", irq_test_cycle, irq_test_cycle_intr);
667 fatal = 1;
668 }
669
670 if (handler_cycle != handler_cycle_intr) {
671 printf("bad handler_cycle: %u %u\n", handler_cycle, handler_cycle_intr);
672 fatal = 1;
673 }
674
675 if (mem_val != memcheck_read(mem_addr)) {
676 printf("bad mem @%08x: %08x %08x\n", mem_addr, memcheck_read(mem_addr), mem_val);
677 fatal = 1;
678 }
679
680 if (!fatal && !memcmp(&psxRegs, &rregs, offsetof(psxRegisters, intCycle))) {
7139f3c8 681 failcount = 0;
682 goto ok;
683 }
684
685 for (i = 0; i < offsetof(psxRegisters, intCycle) / 4; i++) {
686 if (allregs_p[i] != allregs_e[i]) {
3eb78778 687 miss_log_add(i, allregs_p[i], allregs_e[i], psxRegs.pc, psxRegs.cycle);
7139f3c8 688 bad++;
3968e69e 689 if (i > 32+2)
2330734f 690 fatal = 1;
7139f3c8 691 }
692 }
693
2330734f 694 if (!fatal && psxRegs.pc == rregs.pc && bad < 6 && failcount < 32) {
3eb78778 695 static int last_mcycle;
696 if (last_mcycle != psxRegs.cycle >> 20) {
697 printf("%u\n", psxRegs.cycle);
698 last_mcycle = psxRegs.cycle >> 20;
699 }
7139f3c8 700 failcount++;
701 goto ok;
702 }
703
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]);
079ab0c6 712 printf("PC: %08x/%08x, cycle %u, next %u\n", psxRegs.pc, ppc, psxRegs.cycle, next_interupt);
713 //dump_mem("/tmp/psxram.dump", psxM, 0x200000);
714 //dump_mem("/mnt/ntz/dev/pnd/tmp/psxregs.dump", psxH, 0x10000);
7139f3c8 715 exit(1);
716ok:
2330734f 717 //psxRegs.cycle = rregs.cycle + 2; // sync timing
7139f3c8 718 ppc = psxRegs.pc;
719}
720
721#endif