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