drc: remove some old inline memhandlers
[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 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 void *psxH_ptr;
305 void new_dynarec_init() {}
306 void new_dyna_start() {}
307 void new_dynarec_cleanup() {}
308 void new_dynarec_clear_full() {}
309 void invalidate_all_pages() {}
310 void invalidate_block(unsigned int block) {}
311 void new_dyna_pcsx_mem_init(void) {}
312 void new_dyna_pcsx_mem_reset(void) {}
313 #endif
314
315 #ifdef DRC_DBG
316
317 #include <stddef.h>
318 static FILE *f;
319 extern u32 last_io_addr;
320
321 static void dump_mem(const char *fname, void *mem, size_t size)
322 {
323         FILE *f1 = fopen(fname, "wb");
324         if (f1 == NULL)
325                 f1 = fopen(strrchr(fname, '/') + 1, "wb");
326         fwrite(mem, 1, size, f1);
327         fclose(f1);
328 }
329
330 static u32 memcheck_read(u32 a)
331 {
332         if ((a >> 16) == 0x1f80)
333                 // scratchpad/IO
334                 return *(u32 *)(psxH + (a & 0xfffc));
335
336         if ((a >> 16) == 0x1f00)
337                 // parallel
338                 return *(u32 *)(psxP + (a & 0xfffc));
339
340 //      if ((a & ~0xe0600000) < 0x200000)
341         // RAM
342         return *(u32 *)(psxM + (a & 0x1ffffc));
343 }
344
345 void do_insn_trace(void)
346 {
347         static psxRegisters oldregs;
348         static u32 old_io_addr = (u32)-1;
349         static u32 old_io_data = 0xbad0c0de;
350         u32 *allregs_p = (void *)&psxRegs;
351         u32 *allregs_o = (void *)&oldregs;
352         u32 io_data;
353         int i;
354         u8 byte;
355
356 //last_io_addr = 0x5e2c8;
357         if (f == NULL)
358                 f = fopen("tracelog", "wb");
359
360         oldregs.code = psxRegs.code; // don't care
361         for (i = 0; i < offsetof(psxRegisters, intCycle) / 4; i++) {
362                 if (allregs_p[i] != allregs_o[i]) {
363                         fwrite(&i, 1, 1, f);
364                         fwrite(&allregs_p[i], 1, 4, f);
365                         allregs_o[i] = allregs_p[i];
366                 }
367         }
368         if (old_io_addr != last_io_addr) {
369                 byte = 0xfd;
370                 fwrite(&byte, 1, 1, f);
371                 fwrite(&last_io_addr, 1, 4, f);
372                 old_io_addr = last_io_addr;
373         }
374         io_data = memcheck_read(last_io_addr);
375         if (old_io_data != io_data) {
376                 byte = 0xfe;
377                 fwrite(&byte, 1, 1, f);
378                 fwrite(&io_data, 1, 4, f);
379                 old_io_data = io_data;
380         }
381         byte = 0xff;
382         fwrite(&byte, 1, 1, f);
383
384 #if 0
385         if (psxRegs.cycle == 190230) {
386                 dump_mem("/mnt/ntz/dev/pnd/tmp/psxram_i.dump", psxM, 0x200000);
387                 dump_mem("/mnt/ntz/dev/pnd/tmp/psxregs_i.dump", psxH, 0x10000);
388                 printf("dumped\n");
389                 exit(1);
390         }
391 #endif
392 }
393
394 static const char *regnames[offsetof(psxRegisters, intCycle) / 4] = {
395         "r0",  "r1",  "r2",  "r3",  "r4",  "r5",  "r6",  "r7",
396         "r8",  "r9",  "r10", "r11", "r12", "r13", "r14", "r15",
397         "r16", "r17", "r18", "r19", "r20", "r21", "r22", "r23",
398         "r24", "r25", "r26", "r27", "r28", "r29", "r30", "r31",
399         "lo",  "hi",
400         "C0_0",  "C0_1",  "C0_2",  "C0_3",  "C0_4",  "C0_5",  "C0_6",  "C0_7",
401         "C0_8",  "C0_9",  "C0_10", "C0_11", "C0_12", "C0_13", "C0_14", "C0_15",
402         "C0_16", "C0_17", "C0_18", "C0_19", "C0_20", "C0_21", "C0_22", "C0_23",
403         "C0_24", "C0_25", "C0_26", "C0_27", "C0_28", "C0_29", "C0_30", "C0_31",
404
405         "C2D0",  "C2D1",  "C2D2",  "C2D3",  "C2D4",  "C2D5",  "C2D6",  "C2D7",
406         "C2D8",  "C2D9",  "C2D10", "C2D11", "C2D12", "C2D13", "C2D14", "C2D15",
407         "C2D16", "C2D17", "C2D18", "C2D19", "C2D20", "C2D21", "C2D22", "C2D23",
408         "C2D24", "C2D25", "C2D26", "C2D27", "C2D28", "C2D29", "C2D30", "C2D31",
409
410         "C2C0",  "C2C1",  "C2C2",  "C2C3",  "C2C4",  "C2C5",  "C2C6",  "C2C7",
411         "C2C8",  "C2C9",  "C2C10", "C2C11", "C2C12", "C2C13", "C2C14", "C2C15",
412         "C2C16", "C2C17", "C2C18", "C2C19", "C2C20", "C2C21", "C2C22", "C2C23",
413         "C2C24", "C2C25", "C2C26", "C2C27", "C2C28", "C2C29", "C2C30", "C2C31",
414
415         "PC", "code", "cycle", "interrupt",
416 };
417
418 static struct {
419         int reg;
420         u32 val, val_expect;
421         u32 pc, cycle;
422 } miss_log[64];
423 static int miss_log_i;
424 #define miss_log_len (sizeof(miss_log)/sizeof(miss_log[0]))
425 #define miss_log_mask (miss_log_len-1)
426
427 static void miss_log_add(int reg, u32 val, u32 val_expect, u32 pc, u32 cycle)
428 {
429         miss_log[miss_log_i].reg = reg;
430         miss_log[miss_log_i].val = val;
431         miss_log[miss_log_i].val_expect = val_expect;
432         miss_log[miss_log_i].pc = pc;
433         miss_log[miss_log_i].cycle = cycle;
434         miss_log_i = (miss_log_i + 1) & miss_log_mask;
435 }
436
437 void breakme() {}
438
439 void do_insn_cmp(void)
440 {
441         static psxRegisters rregs;
442         static u32 mem_addr, mem_val;
443         u32 *allregs_p = (void *)&psxRegs;
444         u32 *allregs_e = (void *)&rregs;
445         static u32 ppc, failcount;
446         int i, ret, bad = 0;
447         u8 code;
448
449         if (f == NULL)
450                 f = fopen("tracelog", "rb");
451
452         while (1) {
453                 if ((ret = fread(&code, 1, 1, f)) <= 0)
454                         break;
455                 if (ret <= 0)
456                         break;
457                 if (code == 0xff)
458                         break;
459                 if (code == 0xfd) {
460                         if ((ret = fread(&mem_addr, 1, 4, f)) <= 0)
461                                 break;
462                         continue;
463                 }
464                 if (code == 0xfe) {
465                         if ((ret = fread(&mem_val, 1, 4, f)) <= 0)
466                                 break;
467                         continue;
468                 }
469                 if ((ret = fread(&allregs_e[code], 1, 4, f)) <= 0)
470                         break;
471         }
472
473         if (ret <= 0) {
474                 printf("EOF?\n");
475                 goto end;
476         }
477
478         psxRegs.code = rregs.code; // don't care
479         psxRegs.cycle = rregs.cycle;
480         psxRegs.CP0.r[9] = rregs.CP0.r[9]; // Count
481
482 //if (psxRegs.cycle == 166172) breakme();
483
484         if (memcmp(&psxRegs, &rregs, offsetof(psxRegisters, intCycle)) == 0 &&
485                         mem_val == memcheck_read(mem_addr)
486            ) {
487                 failcount = 0;
488                 goto ok;
489         }
490
491         for (i = 0; i < offsetof(psxRegisters, intCycle) / 4; i++) {
492                 if (allregs_p[i] != allregs_e[i]) {
493                         miss_log_add(i, allregs_p[i], allregs_e[i], psxRegs.pc, psxRegs.cycle);
494                         bad++;
495                 }
496         }
497
498         if (mem_val != memcheck_read(mem_addr)) {
499                 printf("bad mem @%08x: %08x %08x\n", mem_addr, memcheck_read(mem_addr), mem_val);
500                 goto end;
501         }
502
503         if (psxRegs.pc == rregs.pc && bad < 6 && failcount < 32) {
504                 static int last_mcycle;
505                 if (last_mcycle != psxRegs.cycle >> 20) {
506                         printf("%u\n", psxRegs.cycle);
507                         last_mcycle = psxRegs.cycle >> 20;
508                 }
509                 failcount++;
510                 goto ok;
511         }
512
513 end:
514         for (i = 0; i < miss_log_len; i++, miss_log_i = (miss_log_i + 1) & miss_log_mask)
515                 printf("bad %5s: %08x %08x, pc=%08x, cycle %u\n",
516                         regnames[miss_log[miss_log_i].reg], miss_log[miss_log_i].val,
517                         miss_log[miss_log_i].val_expect, miss_log[miss_log_i].pc, miss_log[miss_log_i].cycle);
518         printf("-- %d\n", bad);
519         for (i = 0; i < 8; i++)
520                 printf("r%d=%08x r%2d=%08x r%2d=%08x r%2d=%08x\n", i, allregs_p[i],
521                         i+8, allregs_p[i+8], i+16, allregs_p[i+16], i+24, allregs_p[i+24]);
522         printf("PC: %08x/%08x, cycle %u\n", psxRegs.pc, ppc, psxRegs.cycle);
523         dump_mem("/mnt/ntz/dev/pnd/tmp/psxram.dump", psxM, 0x200000);
524         dump_mem("/mnt/ntz/dev/pnd/tmp/psxregs.dump", psxH, 0x10000);
525         exit(1);
526 ok:
527         psxRegs.cycle = rregs.cycle + 2; // sync timing
528         ppc = psxRegs.pc;
529 }
530
531 #endif