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