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