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