frontend: fix valgrind errors
[pcsx_rearmed.git] / libpcsxcore / new_dynarec / emu_if.c
1 /*
2  * (C) GraÅžvydas "notaz" Ignotas, 2010-2011
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
8 #include <stdio.h>
9
10 #include "emu_if.h"
11 #include "pcsxmem.h"
12 #include "../psxhle.h"
13 #include "../r3000a.h"
14 #include "../cdrom.h"
15 #include "../psxdma.h"
16 #include "../mdec.h"
17 #include "../gte_neon.h"
18
19 #define ARRAY_SIZE(x) (sizeof(x) / sizeof(x[0]))
20
21 //#define evprintf printf
22 #define evprintf(...)
23
24 char invalid_code[0x100000];
25 u32 event_cycles[PSXINT_COUNT];
26
27 static void schedule_timeslice(void)
28 {
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 }
53
54 typedef void (irq_func)();
55
56 static 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,
63         [PSXINT_MDECINDMA] = mdec0Interrupt,
64         [PSXINT_GPUOTCDMA] = gpuotcInterrupt,
65         [PSXINT_CDRDMA] = cdrDmaInterrupt,
66         [PSXINT_CDRLID] = cdrLidSeekInterrupt,
67         [PSXINT_CDRPLAY] = cdrPlayInterrupt,
68 };
69
70 /* local dupe of psxBranchTest, using event_cycles */
71 static 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
99 void gen_interupt()
100 {
101         evprintf("  +ge %08x, %u->%u\n", psxRegs.pc, psxRegs.cycle, next_interupt);
102 #ifdef DRC_DBG
103         psxRegs.cycle += 2;
104 #endif
105
106         irq_test();
107         //psxBranchTest();
108         //pending_exception = 1;
109
110         schedule_timeslice();
111
112         evprintf("  -ge %08x, %u->%u (%d)\n", psxRegs.pc, psxRegs.cycle,
113                 next_interupt, next_interupt - psxRegs.cycle);
114 }
115
116 // from interpreter
117 extern void MTC0(int reg, u32 val);
118
119 void pcsx_mtc0(u32 reg)
120 {
121         evprintf("MTC0 %d #%x @%08x %u\n", reg, readmem_word, psxRegs.pc, psxRegs.cycle);
122         MTC0(reg, readmem_word);
123         gen_interupt();
124 }
125
126 void 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);
130 }
131
132 void new_dyna_save(void)
133 {
134         // psxRegs.intCycle is always maintained, no need to convert
135 }
136
137 void new_dyna_restore(void)
138 {
139         int i;
140         for (i = 0; i < PSXINT_COUNT; i++)
141                 event_cycles[i] = psxRegs.intCycle[i].sCycle + psxRegs.intCycle[i].cycle;
142 }
143
144 void *gte_handlers[64];
145
146 /* from gte.txt.. not sure if this is any good. */
147 const 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 };
154
155 static int ari64_init()
156 {
157         extern void (*psxCP2[64])();
158         extern void psxNULL();
159         size_t i;
160
161         new_dynarec_init();
162         new_dyna_pcsx_mem_init();
163
164         for (i = 0; i < ARRAY_SIZE(gte_handlers); i++)
165                 if (psxCP2[i] != psxNULL)
166                         gte_handlers[i] = psxCP2[i];
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
173         psxH_ptr = psxH;
174
175         return 0;
176 }
177
178 static void ari64_reset()
179 {
180         printf("ari64_reset\n");
181         new_dyna_pcsx_mem_reset();
182         invalidate_all_pages();
183         new_dyna_restore();
184         pending_exception = 1;
185 }
186
187 // execute until predefined leave points
188 // (HLE softcall exit and BIOS fastboot end)
189 static void ari64_execute_until()
190 {
191         schedule_timeslice();
192
193         evprintf("ari64_execute %08x, %u->%u (%d)\n", psxRegs.pc,
194                 psxRegs.cycle, next_interupt, next_interupt - psxRegs.cycle);
195
196         new_dyna_start();
197
198         evprintf("ari64_execute end %08x, %u->%u (%d)\n", psxRegs.pc,
199                 psxRegs.cycle, next_interupt, next_interupt - psxRegs.cycle);
200 }
201
202 static void ari64_execute()
203 {
204         while (!stop) {
205                 ari64_execute_until();
206                 evprintf("drc left @%08x\n", psxRegs.pc);
207         }
208 }
209
210 static void ari64_clear(u32 addr, u32 size)
211 {
212         u32 start, end, main_ram;
213
214         size *= 4; /* PCSX uses DMA units */
215
216         evprintf("ari64_clear %08x %04x\n", addr, size);
217
218         /* check for RAM mirrors */
219         main_ram = (addr & 0xffe00000) == 0x80000000;
220
221         start = addr >> 12;
222         end = (addr + size) >> 12;
223
224         for (; start <= end; start++)
225                 if (!main_ram || !invalid_code[start])
226                         invalidate_block(start);
227 }
228
229 static void ari64_shutdown()
230 {
231         new_dynarec_cleanup();
232 }
233
234 extern void intExecute();
235 extern void intExecuteT();
236 extern void intExecuteBlock();
237 extern void intExecuteBlockT();
238 #ifndef DRC_DBG
239 #define intExecuteT intExecute
240 #define intExecuteBlockT intExecuteBlock
241 #endif
242
243 R3000Acpu psxRec = {
244         ari64_init,
245         ari64_reset,
246 #if defined(__arm__)
247         ari64_execute,
248         ari64_execute_until,
249 #else
250         intExecuteT,
251         intExecuteBlockT,
252 #endif
253         ari64_clear,
254         ari64_shutdown
255 };
256
257 // TODO: rm
258 #ifndef DRC_DBG
259 void do_insn_trace() {}
260 void do_insn_cmp() {}
261 #endif
262
263 #if defined(__x86_64__) || defined(__i386__)
264 unsigned int address, readmem_word, word;
265 unsigned short hword;
266 unsigned char byte;
267 int pending_exception, stop;
268 unsigned int next_interupt;
269 void *psxH_ptr;
270 void new_dynarec_init() {}
271 void new_dyna_start() {}
272 void new_dynarec_cleanup() {}
273 void new_dynarec_clear_full() {}
274 void invalidate_all_pages() {}
275 void invalidate_block(unsigned int block) {}
276 void new_dyna_pcsx_mem_init(void) {}
277 void new_dyna_pcsx_mem_reset(void) {}
278 #endif
279
280 #ifdef DRC_DBG
281
282 #include <stddef.h>
283 static FILE *f;
284 extern u32 last_io_addr;
285
286 static void dump_mem(const char *fname, void *mem, size_t size)
287 {
288         FILE *f1 = fopen(fname, "wb");
289         if (f1 == NULL)
290                 f1 = fopen(strrchr(fname, '/') + 1, "wb");
291         fwrite(mem, 1, size, f1);
292         fclose(f1);
293 }
294
295 static 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
310 void 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;
317         u32 io_data;
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         }
339         io_data = memcheck_read(last_io_addr);
340         if (old_io_data != io_data) {
341                 byte = 0xfe;
342                 fwrite(&byte, 1, 1, f);
343                 fwrite(&io_data, 1, 4, f);
344                 old_io_data = io_data;
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
359 static 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
383 static struct {
384         int reg;
385         u32 val, val_expect;
386         u32 pc, cycle;
387 } miss_log[64];
388 static 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
392 static 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
402 void breakme() {}
403
404 void 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
444         psxRegs.cycle = rregs.cycle;
445         psxRegs.CP0.r[9] = rregs.CP0.r[9]; // Count
446
447 //if (psxRegs.cycle == 166172) breakme();
448
449         if (memcmp(&psxRegs, &rregs, offsetof(psxRegisters, intCycle)) == 0 &&
450                         mem_val == memcheck_read(mem_addr)
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]) {
458                         miss_log_add(i, allregs_p[i], allregs_e[i], psxRegs.pc, psxRegs.cycle);
459                         bad++;
460                 }
461         }
462
463         if (mem_val != memcheck_read(mem_addr)) {
464                 printf("bad mem @%08x: %08x %08x\n", mem_addr, memcheck_read(mem_addr), mem_val);
465                 goto end;
466         }
467
468         if (psxRegs.pc == rregs.pc && bad < 6 && failcount < 32) {
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                 }
474                 failcount++;
475                 goto ok;
476         }
477
478 end:
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],
486                         i+8, allregs_p[i+8], i+16, allregs_p[i+16], i+24, allregs_p[i+24]);
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);
491 ok:
492         psxRegs.cycle = rregs.cycle + 2; // sync timing
493         ppc = psxRegs.pc;
494 }
495
496 #endif