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