frontend: fix valgrind errors
[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"
d28b54b1 13#include "../r3000a.h"
52082bc1 14#include "../cdrom.h"
15#include "../psxdma.h"
16#include "../mdec.h"
009faf24 17#include "../gte_neon.h"
7139f3c8 18
ae602c19 19#define ARRAY_SIZE(x) (sizeof(x) / sizeof(x[0]))
20
7139f3c8 21//#define evprintf printf
22#define evprintf(...)
23
f95a77f7 24char invalid_code[0x100000];
d28b54b1 25u32 event_cycles[PSXINT_COUNT];
f95a77f7 26
654e8cfb 27static void schedule_timeslice(void)
f95a77f7 28{
654e8cfb 29 u32 i, c = psxRegs.cycle;
30 s32 min, dif;
31
32 min = psxNextsCounter + psxNextCounter - c;
33 for (i = 0; i < ARRAY_SIZE(event_cycles); i++) {
34 dif = event_cycles[i] - c;
35 //evprintf(" ev %d\n", dif);
36 if (0 < dif && dif < min)
37 min = dif;
38 }
39 next_interupt = c + min;
40
41#if 0
42 static u32 cnt, last_cycle;
43 static u64 sum;
44 if (last_cycle) {
45 cnt++;
46 sum += psxRegs.cycle - last_cycle;
47 if ((cnt & 0xff) == 0)
48 printf("%u\n", (u32)(sum / cnt));
49 }
50 last_cycle = psxRegs.cycle;
51#endif
52}
ae602c19 53
52082bc1 54typedef void (irq_func)();
55
56static irq_func * const irq_funcs[] = {
57 [PSXINT_SIO] = sioInterrupt,
58 [PSXINT_CDR] = cdrInterrupt,
59 [PSXINT_CDREAD] = cdrReadInterrupt,
60 [PSXINT_GPUDMA] = gpuInterrupt,
61 [PSXINT_MDECOUTDMA] = mdec1Interrupt,
62 [PSXINT_SPUDMA] = spuInterrupt,
528ad661 63 [PSXINT_MDECINDMA] = mdec0Interrupt,
57a757ce 64 [PSXINT_GPUOTCDMA] = gpuotcInterrupt,
9f8b032d 65 [PSXINT_CDRDMA] = cdrDmaInterrupt,
66 [PSXINT_CDRLID] = cdrLidSeekInterrupt,
7f457614 67 [PSXINT_CDRPLAY] = cdrPlayInterrupt,
52082bc1 68};
69
70/* local dupe of psxBranchTest, using event_cycles */
71static void irq_test(void)
72{
73 u32 irqs = psxRegs.interrupt;
74 u32 cycle = psxRegs.cycle;
75 u32 irq, irq_bits;
76
77 if ((psxRegs.cycle - psxNextsCounter) >= psxNextCounter)
78 psxRcntUpdate();
79
80 // irq_funcs() may queue more irqs
81 psxRegs.interrupt = 0;
82
83 for (irq = 0, irq_bits = irqs; irq_bits != 0; irq++, irq_bits >>= 1) {
84 if (!(irq_bits & 1))
85 continue;
86 if ((s32)(cycle - event_cycles[irq]) >= 0) {
87 irqs &= ~(1 << irq);
88 irq_funcs[irq]();
89 }
90 }
91 psxRegs.interrupt |= irqs;
92
93 if ((psxHu32(0x1070) & psxHu32(0x1074)) && (Status & 0x401) == 0x401) {
94 psxException(0x400, 0);
95 pending_exception = 1;
96 }
97}
98
654e8cfb 99void gen_interupt()
100{
654e8cfb 101 evprintf(" +ge %08x, %u->%u\n", psxRegs.pc, psxRegs.cycle, next_interupt);
7139f3c8 102#ifdef DRC_DBG
103 psxRegs.cycle += 2;
7139f3c8 104#endif
105
52082bc1 106 irq_test();
107 //psxBranchTest();
108 //pending_exception = 1;
7139f3c8 109
654e8cfb 110 schedule_timeslice();
ae602c19 111
654e8cfb 112 evprintf(" -ge %08x, %u->%u (%d)\n", psxRegs.pc, psxRegs.cycle,
113 next_interupt, next_interupt - psxRegs.cycle);
f95a77f7 114}
115
fca1aef2 116// from interpreter
117extern void MTC0(int reg, u32 val);
118
119void pcsx_mtc0(u32 reg)
28bc5688 120{
fca1aef2 121 evprintf("MTC0 %d #%x @%08x %u\n", reg, readmem_word, psxRegs.pc, psxRegs.cycle);
122 MTC0(reg, readmem_word);
123 gen_interupt();
124}
28bc5688 125
fca1aef2 126void pcsx_mtc0_ds(u32 reg)
127{
128 evprintf("MTC0 %d #%x @%08x %u\n", reg, readmem_word, psxRegs.pc, psxRegs.cycle);
129 MTC0(reg, readmem_word);
28bc5688 130}
131
52082bc1 132void new_dyna_save(void)
133{
134 // psxRegs.intCycle is always maintained, no need to convert
135}
136
137void new_dyna_restore(void)
138{
139 int i;
9f8b032d 140 for (i = 0; i < PSXINT_COUNT; i++)
52082bc1 141 event_cycles[i] = psxRegs.intCycle[i].sCycle + psxRegs.intCycle[i].cycle;
142}
143
b9b61529 144void *gte_handlers[64];
145
146/* from gte.txt.. not sure if this is any good. */
147const char gte_cycletab[64] = {
148 /* 1 2 3 4 5 6 7 8 9 a b c d e f */
149 0, 15, 0, 0, 0, 0, 8, 0, 0, 0, 0, 0, 6, 0, 0, 0,
150 8, 8, 8, 19, 13, 0, 44, 0, 0, 0, 0, 17, 11, 0, 14, 0,
151 30, 0, 0, 0, 0, 0, 0, 0, 5, 8, 17, 0, 0, 5, 6, 0,
152 23, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 5, 5, 39,
153};
f95a77f7 154
155static int ari64_init()
156{
b9b61529 157 extern void (*psxCP2[64])();
158 extern void psxNULL();
f95a77f7 159 size_t i;
b9b61529 160
f95a77f7 161 new_dynarec_init();
7e605697 162 new_dyna_pcsx_mem_init();
7139f3c8 163
ae602c19 164 for (i = 0; i < ARRAY_SIZE(gte_handlers); i++)
b9b61529 165 if (psxCP2[i] != psxNULL)
166 gte_handlers[i] = psxCP2[i];
009faf24 167#ifdef __arm__
168 gte_handlers[0x01] = gteRTPS_neon;
169 gte_handlers[0x30] = gteRTPT_neon;
170 gte_handlers[0x12] = gteMVMVA_neon;
171 gte_handlers[0x06] = gteNCLIP_neon;
172#endif
7e605697 173 psxH_ptr = psxH;
174
b9b61529 175 return 0;
f95a77f7 176}
177
178static void ari64_reset()
179{
f95a77f7 180 printf("ari64_reset\n");
7e605697 181 new_dyna_pcsx_mem_reset();
4b421010 182 invalidate_all_pages();
7f457614 183 new_dyna_restore();
4b421010 184 pending_exception = 1;
f95a77f7 185}
186
e4eb18c1 187// execute until predefined leave points
188// (HLE softcall exit and BIOS fastboot end)
189static void ari64_execute_until()
f95a77f7 190{
654e8cfb 191 schedule_timeslice();
192
193 evprintf("ari64_execute %08x, %u->%u (%d)\n", psxRegs.pc,
194 psxRegs.cycle, next_interupt, next_interupt - psxRegs.cycle);
7139f3c8 195
b9b61529 196 new_dyna_start();
654e8cfb 197
198 evprintf("ari64_execute end %08x, %u->%u (%d)\n", psxRegs.pc,
199 psxRegs.cycle, next_interupt, next_interupt - psxRegs.cycle);
f95a77f7 200}
201
e4eb18c1 202static void ari64_execute()
203{
204 while (!stop) {
205 ari64_execute_until();
206 evprintf("drc left @%08x\n", psxRegs.pc);
207 }
208}
209
4b421010 210static void ari64_clear(u32 addr, u32 size)
f95a77f7 211{
0ce47d46 212 u32 start, end, main_ram;
4b421010 213
76739a08 214 size *= 4; /* PCSX uses DMA units */
215
4b421010 216 evprintf("ari64_clear %08x %04x\n", addr, size);
217
218 /* check for RAM mirrors */
0ce47d46 219 main_ram = (addr & 0xffe00000) == 0x80000000;
4b421010 220
221 start = addr >> 12;
222 end = (addr + size) >> 12;
223
224 for (; start <= end; start++)
0ce47d46 225 if (!main_ram || !invalid_code[start])
4b421010 226 invalidate_block(start);
f95a77f7 227}
228
229static void ari64_shutdown()
230{
231 new_dynarec_cleanup();
232}
233
7139f3c8 234extern void intExecute();
235extern void intExecuteT();
236extern void intExecuteBlock();
237extern void intExecuteBlockT();
238#ifndef DRC_DBG
239#define intExecuteT intExecute
240#define intExecuteBlockT intExecuteBlock
241#endif
242
f95a77f7 243R3000Acpu psxRec = {
244 ari64_init,
245 ari64_reset,
2185e39b 246#if defined(__arm__)
f95a77f7 247 ari64_execute,
e4eb18c1 248 ari64_execute_until,
7139f3c8 249#else
250 intExecuteT,
251 intExecuteBlockT,
252#endif
f95a77f7 253 ari64_clear,
254 ari64_shutdown
255};
7139f3c8 256
257// TODO: rm
258#ifndef DRC_DBG
259void do_insn_trace() {}
260void do_insn_cmp() {}
261#endif
262
263#if defined(__x86_64__) || defined(__i386__)
264unsigned int address, readmem_word, word;
265unsigned short hword;
266unsigned char byte;
ccf51908 267int pending_exception, stop;
7139f3c8 268unsigned int next_interupt;
7e605697 269void *psxH_ptr;
7139f3c8 270void new_dynarec_init() {}
3eb78778 271void new_dyna_start() {}
7139f3c8 272void new_dynarec_cleanup() {}
2c886904 273void new_dynarec_clear_full() {}
ccf51908 274void invalidate_all_pages() {}
275void invalidate_block(unsigned int block) {}
7e605697 276void new_dyna_pcsx_mem_init(void) {}
277void new_dyna_pcsx_mem_reset(void) {}
7139f3c8 278#endif
279
280#ifdef DRC_DBG
281
282#include <stddef.h>
283static FILE *f;
284extern u32 last_io_addr;
285
286static void dump_mem(const char *fname, void *mem, size_t size)
287{
288 FILE *f1 = fopen(fname, "wb");
3eb78778 289 if (f1 == NULL)
290 f1 = fopen(strrchr(fname, '/') + 1, "wb");
7139f3c8 291 fwrite(mem, 1, size, f1);
292 fclose(f1);
293}
294
2185e39b 295static u32 memcheck_read(u32 a)
296{
297 if ((a >> 16) == 0x1f80)
298 // scratchpad/IO
299 return *(u32 *)(psxH + (a & 0xfffc));
300
301 if ((a >> 16) == 0x1f00)
302 // parallel
303 return *(u32 *)(psxP + (a & 0xfffc));
304
305// if ((a & ~0xe0600000) < 0x200000)
306 // RAM
307 return *(u32 *)(psxM + (a & 0x1ffffc));
308}
309
7139f3c8 310void do_insn_trace(void)
311{
312 static psxRegisters oldregs;
313 static u32 old_io_addr = (u32)-1;
314 static u32 old_io_data = 0xbad0c0de;
315 u32 *allregs_p = (void *)&psxRegs;
316 u32 *allregs_o = (void *)&oldregs;
2185e39b 317 u32 io_data;
7139f3c8 318 int i;
319 u8 byte;
320
321//last_io_addr = 0x5e2c8;
322 if (f == NULL)
323 f = fopen("tracelog", "wb");
324
325 oldregs.code = psxRegs.code; // don't care
326 for (i = 0; i < offsetof(psxRegisters, intCycle) / 4; i++) {
327 if (allregs_p[i] != allregs_o[i]) {
328 fwrite(&i, 1, 1, f);
329 fwrite(&allregs_p[i], 1, 4, f);
330 allregs_o[i] = allregs_p[i];
331 }
332 }
333 if (old_io_addr != last_io_addr) {
334 byte = 0xfd;
335 fwrite(&byte, 1, 1, f);
336 fwrite(&last_io_addr, 1, 4, f);
337 old_io_addr = last_io_addr;
338 }
2185e39b 339 io_data = memcheck_read(last_io_addr);
340 if (old_io_data != io_data) {
7139f3c8 341 byte = 0xfe;
342 fwrite(&byte, 1, 1, f);
2185e39b 343 fwrite(&io_data, 1, 4, f);
344 old_io_data = io_data;
7139f3c8 345 }
346 byte = 0xff;
347 fwrite(&byte, 1, 1, f);
348
349#if 0
350 if (psxRegs.cycle == 190230) {
351 dump_mem("/mnt/ntz/dev/pnd/tmp/psxram_i.dump", psxM, 0x200000);
352 dump_mem("/mnt/ntz/dev/pnd/tmp/psxregs_i.dump", psxH, 0x10000);
353 printf("dumped\n");
354 exit(1);
355 }
356#endif
357}
358
359static const char *regnames[offsetof(psxRegisters, intCycle) / 4] = {
360 "r0", "r1", "r2", "r3", "r4", "r5", "r6", "r7",
361 "r8", "r9", "r10", "r11", "r12", "r13", "r14", "r15",
362 "r16", "r17", "r18", "r19", "r20", "r21", "r22", "r23",
363 "r24", "r25", "r26", "r27", "r28", "r29", "r30", "r31",
364 "lo", "hi",
365 "C0_0", "C0_1", "C0_2", "C0_3", "C0_4", "C0_5", "C0_6", "C0_7",
366 "C0_8", "C0_9", "C0_10", "C0_11", "C0_12", "C0_13", "C0_14", "C0_15",
367 "C0_16", "C0_17", "C0_18", "C0_19", "C0_20", "C0_21", "C0_22", "C0_23",
368 "C0_24", "C0_25", "C0_26", "C0_27", "C0_28", "C0_29", "C0_30", "C0_31",
369
370 "C2D0", "C2D1", "C2D2", "C2D3", "C2D4", "C2D5", "C2D6", "C2D7",
371 "C2D8", "C2D9", "C2D10", "C2D11", "C2D12", "C2D13", "C2D14", "C2D15",
372 "C2D16", "C2D17", "C2D18", "C2D19", "C2D20", "C2D21", "C2D22", "C2D23",
373 "C2D24", "C2D25", "C2D26", "C2D27", "C2D28", "C2D29", "C2D30", "C2D31",
374
375 "C2C0", "C2C1", "C2C2", "C2C3", "C2C4", "C2C5", "C2C6", "C2C7",
376 "C2C8", "C2C9", "C2C10", "C2C11", "C2C12", "C2C13", "C2C14", "C2C15",
377 "C2C16", "C2C17", "C2C18", "C2C19", "C2C20", "C2C21", "C2C22", "C2C23",
378 "C2C24", "C2C25", "C2C26", "C2C27", "C2C28", "C2C29", "C2C30", "C2C31",
379
380 "PC", "code", "cycle", "interrupt",
381};
382
3eb78778 383static struct {
384 int reg;
385 u32 val, val_expect;
386 u32 pc, cycle;
387} miss_log[64];
388static int miss_log_i;
389#define miss_log_len (sizeof(miss_log)/sizeof(miss_log[0]))
390#define miss_log_mask (miss_log_len-1)
391
392static void miss_log_add(int reg, u32 val, u32 val_expect, u32 pc, u32 cycle)
393{
394 miss_log[miss_log_i].reg = reg;
395 miss_log[miss_log_i].val = val;
396 miss_log[miss_log_i].val_expect = val_expect;
397 miss_log[miss_log_i].pc = pc;
398 miss_log[miss_log_i].cycle = cycle;
399 miss_log_i = (miss_log_i + 1) & miss_log_mask;
400}
401
7139f3c8 402void breakme() {}
403
404void do_insn_cmp(void)
405{
406 static psxRegisters rregs;
407 static u32 mem_addr, mem_val;
408 u32 *allregs_p = (void *)&psxRegs;
409 u32 *allregs_e = (void *)&rregs;
410 static u32 ppc, failcount;
411 int i, ret, bad = 0;
412 u8 code;
413
414 if (f == NULL)
415 f = fopen("tracelog", "rb");
416
417 while (1) {
418 if ((ret = fread(&code, 1, 1, f)) <= 0)
419 break;
420 if (ret <= 0)
421 break;
422 if (code == 0xff)
423 break;
424 if (code == 0xfd) {
425 if ((ret = fread(&mem_addr, 1, 4, f)) <= 0)
426 break;
427 continue;
428 }
429 if (code == 0xfe) {
430 if ((ret = fread(&mem_val, 1, 4, f)) <= 0)
431 break;
432 continue;
433 }
434 if ((ret = fread(&allregs_e[code], 1, 4, f)) <= 0)
435 break;
436 }
437
438 if (ret <= 0) {
439 printf("EOF?\n");
440 goto end;
441 }
442
443 psxRegs.code = rregs.code; // don't care
2185e39b 444 psxRegs.cycle = rregs.cycle;
445 psxRegs.CP0.r[9] = rregs.CP0.r[9]; // Count
7139f3c8 446
447//if (psxRegs.cycle == 166172) breakme();
7139f3c8 448
449 if (memcmp(&psxRegs, &rregs, offsetof(psxRegisters, intCycle)) == 0 &&
2185e39b 450 mem_val == memcheck_read(mem_addr)
7139f3c8 451 ) {
452 failcount = 0;
453 goto ok;
454 }
455
456 for (i = 0; i < offsetof(psxRegisters, intCycle) / 4; i++) {
457 if (allregs_p[i] != allregs_e[i]) {
3eb78778 458 miss_log_add(i, allregs_p[i], allregs_e[i], psxRegs.pc, psxRegs.cycle);
7139f3c8 459 bad++;
460 }
461 }
462
2185e39b 463 if (mem_val != memcheck_read(mem_addr)) {
464 printf("bad mem @%08x: %08x %08x\n", mem_addr, memcheck_read(mem_addr), mem_val);
7139f3c8 465 goto end;
466 }
467
468 if (psxRegs.pc == rregs.pc && bad < 6 && failcount < 32) {
3eb78778 469 static int last_mcycle;
470 if (last_mcycle != psxRegs.cycle >> 20) {
471 printf("%u\n", psxRegs.cycle);
472 last_mcycle = psxRegs.cycle >> 20;
473 }
7139f3c8 474 failcount++;
475 goto ok;
476 }
477
478end:
3eb78778 479 for (i = 0; i < miss_log_len; i++, miss_log_i = (miss_log_i + 1) & miss_log_mask)
480 printf("bad %5s: %08x %08x, pc=%08x, cycle %u\n",
481 regnames[miss_log[miss_log_i].reg], miss_log[miss_log_i].val,
482 miss_log[miss_log_i].val_expect, miss_log[miss_log_i].pc, miss_log[miss_log_i].cycle);
483 printf("-- %d\n", bad);
484 for (i = 0; i < 8; i++)
485 printf("r%d=%08x r%2d=%08x r%2d=%08x r%2d=%08x\n", i, allregs_p[i],
87c06e51 486 i+8, allregs_p[i+8], i+16, allregs_p[i+16], i+24, allregs_p[i+24]);
7139f3c8 487 printf("PC: %08x/%08x, cycle %u\n", psxRegs.pc, ppc, psxRegs.cycle);
488 dump_mem("/mnt/ntz/dev/pnd/tmp/psxram.dump", psxM, 0x200000);
489 dump_mem("/mnt/ntz/dev/pnd/tmp/psxregs.dump", psxH, 0x10000);
490 exit(1);
491ok:
492 psxRegs.cycle = rregs.cycle + 2; // sync timing
493 ppc = psxRegs.pc;
494}
495
496#endif