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