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