improved memhandlers
[pcsx_rearmed.git] / libpcsxcore / new_dynarec / emu_if.c
... / ...
CommitLineData
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
21char invalid_code[0x100000];
22u32 event_cycles[7];
23
24static 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
51void 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
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
77void check_interupt()
78{
79 printf("ari64_check_interupt\n");
80}
81
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};
92
93static 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
112static 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
120static 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
133static 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
153static void ari64_shutdown()
154{
155 new_dynarec_cleanup();
156}
157
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
167R3000Acpu 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
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;
191int pending_exception, stop;
192unsigned int next_interupt;
193void *psxH_ptr;
194void new_dynarec_init() {}
195void new_dyna_start() {}
196void new_dynarec_cleanup() {}
197void invalidate_all_pages() {}
198void invalidate_block(unsigned int block) {}
199void new_dyna_pcsx_mem_init(void) {}
200void new_dyna_pcsx_mem_reset(void) {}
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");
212 if (f1 == NULL)
213 f1 = fopen(strrchr(fname, '/') + 1, "wb");
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
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
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]) {
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
389end:
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);
402ok:
403 psxRegs.cycle = rregs.cycle + 2; // sync timing
404 ppc = psxRegs.pc;
405}
406
407#endif