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