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