release r10
[pcsx_rearmed.git] / libpcsxcore / new_dynarec / emu_if.c
CommitLineData
7e605697 1/*
009faf24 2 * (C) GraÅžvydas "notaz" Ignotas, 2010-2011
7e605697 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
f95a77f7 8#include <stdio.h>
9
10#include "emu_if.h"
7e605697 11#include "pcsxmem.h"
7139f3c8 12#include "../psxhle.h"
d28b54b1 13#include "../r3000a.h"
52082bc1 14#include "../cdrom.h"
15#include "../psxdma.h"
16#include "../mdec.h"
009faf24 17#include "../gte_neon.h"
7139f3c8 18
ae602c19 19#define ARRAY_SIZE(x) (sizeof(x) / sizeof(x[0]))
20
7139f3c8 21//#define evprintf printf
22#define evprintf(...)
23
f95a77f7 24char invalid_code[0x100000];
d28b54b1 25u32 event_cycles[PSXINT_COUNT];
f95a77f7 26
654e8cfb 27static void schedule_timeslice(void)
f95a77f7 28{
654e8cfb 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}
ae602c19 53
52082bc1 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,
528ad661 63 [PSXINT_MDECINDMA] = mdec0Interrupt,
57a757ce 64 [PSXINT_GPUOTCDMA] = gpuotcInterrupt,
9f8b032d 65 [PSXINT_CDRDMA] = cdrDmaInterrupt,
66 [PSXINT_CDRLID] = cdrLidSeekInterrupt,
7f457614 67 [PSXINT_CDRPLAY] = cdrPlayInterrupt,
52082bc1 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
654e8cfb 99void gen_interupt()
100{
654e8cfb 101 evprintf(" +ge %08x, %u->%u\n", psxRegs.pc, psxRegs.cycle, next_interupt);
7139f3c8 102
52082bc1 103 irq_test();
104 //psxBranchTest();
105 //pending_exception = 1;
7139f3c8 106
654e8cfb 107 schedule_timeslice();
ae602c19 108
654e8cfb 109 evprintf(" -ge %08x, %u->%u (%d)\n", psxRegs.pc, psxRegs.cycle,
110 next_interupt, next_interupt - psxRegs.cycle);
f95a77f7 111}
112
fca1aef2 113// from interpreter
114extern void MTC0(int reg, u32 val);
115
116void pcsx_mtc0(u32 reg)
28bc5688 117{
fca1aef2 118 evprintf("MTC0 %d #%x @%08x %u\n", reg, readmem_word, psxRegs.pc, psxRegs.cycle);
119 MTC0(reg, readmem_word);
120 gen_interupt();
121}
28bc5688 122
fca1aef2 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);
28bc5688 127}
128
52082bc1 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;
9f8b032d 137 for (i = 0; i < PSXINT_COUNT; i++)
52082bc1 138 event_cycles[i] = psxRegs.intCycle[i].sCycle + psxRegs.intCycle[i].cycle;
139}
140
b9b61529 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};
f95a77f7 151
152static int ari64_init()
153{
b9b61529 154 extern void (*psxCP2[64])();
155 extern void psxNULL();
f95a77f7 156 size_t i;
b9b61529 157
f95a77f7 158 new_dynarec_init();
7e605697 159 new_dyna_pcsx_mem_init();
7139f3c8 160
ae602c19 161 for (i = 0; i < ARRAY_SIZE(gte_handlers); i++)
b9b61529 162 if (psxCP2[i] != psxNULL)
163 gte_handlers[i] = psxCP2[i];
149a4d34 164#if defined(__arm__) && !defined(DRC_DBG)
009faf24 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
7e605697 170 psxH_ptr = psxH;
171
b9b61529 172 return 0;
f95a77f7 173}
174
175static void ari64_reset()
176{
f95a77f7 177 printf("ari64_reset\n");
7e605697 178 new_dyna_pcsx_mem_reset();
4b421010 179 invalidate_all_pages();
7f457614 180 new_dyna_restore();
4b421010 181 pending_exception = 1;
f95a77f7 182}
183
e4eb18c1 184// execute until predefined leave points
185// (HLE softcall exit and BIOS fastboot end)
186static void ari64_execute_until()
f95a77f7 187{
654e8cfb 188 schedule_timeslice();
189
190 evprintf("ari64_execute %08x, %u->%u (%d)\n", psxRegs.pc,
191 psxRegs.cycle, next_interupt, next_interupt - psxRegs.cycle);
7139f3c8 192
b9b61529 193 new_dyna_start();
654e8cfb 194
195 evprintf("ari64_execute end %08x, %u->%u (%d)\n", psxRegs.pc,
196 psxRegs.cycle, next_interupt, next_interupt - psxRegs.cycle);
f95a77f7 197}
198
e4eb18c1 199static void ari64_execute()
200{
201 while (!stop) {
202 ari64_execute_until();
203 evprintf("drc left @%08x\n", psxRegs.pc);
204 }
205}
206
4b421010 207static void ari64_clear(u32 addr, u32 size)
f95a77f7 208{
0ce47d46 209 u32 start, end, main_ram;
4b421010 210
76739a08 211 size *= 4; /* PCSX uses DMA units */
212
4b421010 213 evprintf("ari64_clear %08x %04x\n", addr, size);
214
215 /* check for RAM mirrors */
0ce47d46 216 main_ram = (addr & 0xffe00000) == 0x80000000;
4b421010 217
218 start = addr >> 12;
219 end = (addr + size) >> 12;
220
221 for (; start <= end; start++)
0ce47d46 222 if (!main_ram || !invalid_code[start])
4b421010 223 invalidate_block(start);
f95a77f7 224}
225
226static void ari64_shutdown()
227{
228 new_dynarec_cleanup();
229}
230
7139f3c8 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
f95a77f7 240R3000Acpu psxRec = {
241 ari64_init,
242 ari64_reset,
2185e39b 243#if defined(__arm__)
f95a77f7 244 ari64_execute,
e4eb18c1 245 ari64_execute_until,
7139f3c8 246#else
247 intExecuteT,
248 intExecuteBlockT,
249#endif
f95a77f7 250 ari64_clear,
251 ari64_shutdown
252};
7139f3c8 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;
ccf51908 264int pending_exception, stop;
7139f3c8 265unsigned int next_interupt;
7e605697 266void *psxH_ptr;
7139f3c8 267void new_dynarec_init() {}
3eb78778 268void new_dyna_start() {}
7139f3c8 269void new_dynarec_cleanup() {}
2c886904 270void new_dynarec_clear_full() {}
ccf51908 271void invalidate_all_pages() {}
272void invalidate_block(unsigned int block) {}
7e605697 273void new_dyna_pcsx_mem_init(void) {}
274void new_dyna_pcsx_mem_reset(void) {}
7139f3c8 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");
3eb78778 286 if (f1 == NULL)
287 f1 = fopen(strrchr(fname, '/') + 1, "wb");
7139f3c8 288 fwrite(mem, 1, size, f1);
289 fclose(f1);
290}
291
2185e39b 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
7139f3c8 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;
2185e39b 314 u32 io_data;
7139f3c8 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 }
2185e39b 336 io_data = memcheck_read(last_io_addr);
337 if (old_io_data != io_data) {
7139f3c8 338 byte = 0xfe;
339 fwrite(&byte, 1, 1, f);
2185e39b 340 fwrite(&io_data, 1, 4, f);
341 old_io_data = io_data;
7139f3c8 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
3eb78778 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
7139f3c8 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
2185e39b 441 psxRegs.cycle = rregs.cycle;
442 psxRegs.CP0.r[9] = rregs.CP0.r[9]; // Count
7139f3c8 443
444//if (psxRegs.cycle == 166172) breakme();
7139f3c8 445
446 if (memcmp(&psxRegs, &rregs, offsetof(psxRegisters, intCycle)) == 0 &&
2185e39b 447 mem_val == memcheck_read(mem_addr)
7139f3c8 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]) {
3eb78778 455 miss_log_add(i, allregs_p[i], allregs_e[i], psxRegs.pc, psxRegs.cycle);
7139f3c8 456 bad++;
457 }
458 }
459
2185e39b 460 if (mem_val != memcheck_read(mem_addr)) {
461 printf("bad mem @%08x: %08x %08x\n", mem_addr, memcheck_read(mem_addr), mem_val);
7139f3c8 462 goto end;
463 }
464
465 if (psxRegs.pc == rregs.pc && bad < 6 && failcount < 32) {
3eb78778 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 }
7139f3c8 471 failcount++;
472 goto ok;
473 }
474
475end:
3eb78778 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],
87c06e51 483 i+8, allregs_p[i+8], i+16, allregs_p[i+16], i+24, allregs_p[i+24]);
7139f3c8 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