omap: only setup mem before using fb
[pcsx_rearmed.git] / libpcsxcore / new_dynarec / emu_if.c
CommitLineData
7e605697 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
7139f3c8 8// pending_exception?
822b27d1 9// swi 0 in do_unalignedwritestub?
f95a77f7 10#include <stdio.h>
11
12#include "emu_if.h"
7e605697 13#include "pcsxmem.h"
7139f3c8 14#include "../psxhle.h"
15
ae602c19 16#define ARRAY_SIZE(x) (sizeof(x) / sizeof(x[0]))
17
7139f3c8 18//#define evprintf printf
19#define evprintf(...)
20
f95a77f7 21char invalid_code[0x100000];
28bc5688 22u32 event_cycles[7];
f95a77f7 23
654e8cfb 24static void schedule_timeslice(void)
f95a77f7 25{
654e8cfb 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}
ae602c19 50
654e8cfb 51void gen_interupt()
52{
654e8cfb 53 evprintf(" +ge %08x, %u->%u\n", psxRegs.pc, psxRegs.cycle, next_interupt);
7139f3c8 54#ifdef DRC_DBG
55 psxRegs.cycle += 2;
7139f3c8 56#endif
57
58 psxBranchTest();
59
654e8cfb 60 schedule_timeslice();
ae602c19 61
654e8cfb 62 evprintf(" -ge %08x, %u->%u (%d)\n", psxRegs.pc, psxRegs.cycle,
63 next_interupt, next_interupt - psxRegs.cycle);
7139f3c8 64
65 pending_exception = 1; /* FIXME */
f95a77f7 66}
67
28bc5688 68void 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
f95a77f7 77void check_interupt()
78{
7139f3c8 79 printf("ari64_check_interupt\n");
f95a77f7 80}
81
b9b61529 82void *gte_handlers[64];
83
84/* from gte.txt.. not sure if this is any good. */
85const 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};
f95a77f7 92
93static int ari64_init()
94{
b9b61529 95 extern void (*psxCP2[64])();
96 extern void psxNULL();
7e605697 97 extern void *psxH_ptr;
f95a77f7 98 size_t i;
b9b61529 99
f95a77f7 100 new_dynarec_init();
7e605697 101 new_dyna_pcsx_mem_init();
7139f3c8 102
ae602c19 103 for (i = 0; i < ARRAY_SIZE(gte_handlers); i++)
b9b61529 104 if (psxCP2[i] != psxNULL)
105 gte_handlers[i] = psxCP2[i];
106
7e605697 107 psxH_ptr = psxH;
108
b9b61529 109 return 0;
f95a77f7 110}
111
112static void ari64_reset()
113{
f95a77f7 114 printf("ari64_reset\n");
7e605697 115 new_dyna_pcsx_mem_reset();
4b421010 116 invalidate_all_pages();
117 pending_exception = 1;
f95a77f7 118}
119
120static void ari64_execute()
121{
654e8cfb 122 schedule_timeslice();
123
124 evprintf("ari64_execute %08x, %u->%u (%d)\n", psxRegs.pc,
125 psxRegs.cycle, next_interupt, next_interupt - psxRegs.cycle);
7139f3c8 126
b9b61529 127 new_dyna_start();
654e8cfb 128
129 evprintf("ari64_execute end %08x, %u->%u (%d)\n", psxRegs.pc,
130 psxRegs.cycle, next_interupt, next_interupt - psxRegs.cycle);
f95a77f7 131}
132
4b421010 133static void ari64_clear(u32 addr, u32 size)
f95a77f7 134{
4b421010 135 u32 start, end;
136
137 evprintf("ari64_clear %08x %04x\n", addr, size);
138
139 /* check for RAM mirrors */
4cb76aa4 140 if ((addr & ~0xe0600000) < 0x200000) {
141 addr &= ~0xe0600000;
f76eeef9 142 addr |= 0x80000000;
4b421010 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);
f95a77f7 151}
152
153static void ari64_shutdown()
154{
155 new_dynarec_cleanup();
156}
157
7139f3c8 158extern void intExecute();
159extern void intExecuteT();
160extern void intExecuteBlock();
161extern void intExecuteBlockT();
162#ifndef DRC_DBG
163#define intExecuteT intExecute
164#define intExecuteBlockT intExecuteBlock
165#endif
166
f95a77f7 167R3000Acpu psxRec = {
168 ari64_init,
169 ari64_reset,
7139f3c8 170#if 1
f95a77f7 171 ari64_execute,
7139f3c8 172 ari64_execute,
173#else
174 intExecuteT,
175 intExecuteBlockT,
176#endif
f95a77f7 177 ari64_clear,
178 ari64_shutdown
179};
7139f3c8 180
181// TODO: rm
182#ifndef DRC_DBG
183void do_insn_trace() {}
184void do_insn_cmp() {}
185#endif
186
187#if defined(__x86_64__) || defined(__i386__)
188unsigned int address, readmem_word, word;
189unsigned short hword;
190unsigned char byte;
ccf51908 191int pending_exception, stop;
7139f3c8 192unsigned int next_interupt;
7e605697 193void *psxH_ptr;
7139f3c8 194void new_dynarec_init() {}
3eb78778 195void new_dyna_start() {}
7139f3c8 196void new_dynarec_cleanup() {}
ccf51908 197void invalidate_all_pages() {}
198void invalidate_block(unsigned int block) {}
7e605697 199void new_dyna_pcsx_mem_init(void) {}
200void new_dyna_pcsx_mem_reset(void) {}
7139f3c8 201#endif
202
203#ifdef DRC_DBG
204
205#include <stddef.h>
206static FILE *f;
207extern u32 last_io_addr;
208
209static void dump_mem(const char *fname, void *mem, size_t size)
210{
211 FILE *f1 = fopen(fname, "wb");
3eb78778 212 if (f1 == NULL)
213 f1 = fopen(strrchr(fname, '/') + 1, "wb");
7139f3c8 214 fwrite(mem, 1, size, f1);
215 fclose(f1);
216}
217
218void 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
267static 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
3eb78778 291static struct {
292 int reg;
293 u32 val, val_expect;
294 u32 pc, cycle;
295} miss_log[64];
296static 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
300static 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
7139f3c8 310void breakme() {}
311
312void 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
352psxRegs.cycle = rregs.cycle;
353psxRegs.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]) {
3eb78778 369 miss_log_add(i, allregs_p[i], allregs_e[i], psxRegs.pc, psxRegs.cycle);
7139f3c8 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) {
3eb78778 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 }
7139f3c8 385 failcount++;
386 goto ok;
387 }
388
389end:
3eb78778 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],
87c06e51 397 i+8, allregs_p[i+8], i+16, allregs_p[i+16], i+24, allregs_p[i+24]);
7139f3c8 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);
402ok:
403 psxRegs.cycle = rregs.cycle + 2; // sync timing
404 ppc = psxRegs.pc;
405}
406
407#endif