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