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