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