drc: invalidate RAM mirrors correctly
[pcsx_rearmed.git] / libpcsxcore / new_dynarec / emu_if.c
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 #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
18 #define ARRAY_SIZE(x) (sizeof(x) / sizeof(x[0]))
19
20 //#define evprintf printf
21 #define evprintf(...)
22
23 char invalid_code[0x100000];
24 u32 event_cycles[PSXINT_COUNT];
25
26 static void schedule_timeslice(void)
27 {
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 }
52
53 typedef void (irq_func)();
54
55 static 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,
62         [PSXINT_MDECINDMA] = mdec0Interrupt,
63         [PSXINT_GPUOTCDMA] = gpuotcInterrupt,
64         [PSXINT_CDRDMA] = cdrDmaInterrupt,
65         [PSXINT_CDRLID] = cdrLidSeekInterrupt,
66 };
67
68 /* local dupe of psxBranchTest, using event_cycles */
69 static 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
97 void gen_interupt()
98 {
99         evprintf("  +ge %08x, %u->%u\n", psxRegs.pc, psxRegs.cycle, next_interupt);
100 #ifdef DRC_DBG
101         psxRegs.cycle += 2;
102 #endif
103
104         irq_test();
105         //psxBranchTest();
106         //pending_exception = 1;
107
108         schedule_timeslice();
109
110         evprintf("  -ge %08x, %u->%u (%d)\n", psxRegs.pc, psxRegs.cycle,
111                 next_interupt, next_interupt - psxRegs.cycle);
112 }
113
114 // from interpreter
115 extern void MTC0(int reg, u32 val);
116
117 void pcsx_mtc0(u32 reg)
118 {
119         evprintf("MTC0 %d #%x @%08x %u\n", reg, readmem_word, psxRegs.pc, psxRegs.cycle);
120         MTC0(reg, readmem_word);
121         gen_interupt();
122 }
123
124 void 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);
128 }
129
130 void new_dyna_save(void)
131 {
132         // psxRegs.intCycle is always maintained, no need to convert
133 }
134
135 void new_dyna_restore(void)
136 {
137         int i;
138         for (i = 0; i < PSXINT_COUNT; i++)
139                 event_cycles[i] = psxRegs.intCycle[i].sCycle + psxRegs.intCycle[i].cycle;
140 }
141
142 void *gte_handlers[64];
143
144 /* from gte.txt.. not sure if this is any good. */
145 const 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 };
152
153 static int ari64_init()
154 {
155         extern void (*psxCP2[64])();
156         extern void psxNULL();
157         extern void *psxH_ptr;
158         size_t i;
159
160         new_dynarec_init();
161         new_dyna_pcsx_mem_init();
162
163         for (i = 0; i < ARRAY_SIZE(gte_handlers); i++)
164                 if (psxCP2[i] != psxNULL)
165                         gte_handlers[i] = psxCP2[i];
166
167         psxH_ptr = psxH;
168
169         return 0;
170 }
171
172 static void ari64_reset()
173 {
174         printf("ari64_reset\n");
175         new_dyna_pcsx_mem_reset();
176         invalidate_all_pages();
177         pending_exception = 1;
178 }
179
180 // execute until predefined leave points
181 // (HLE softcall exit and BIOS fastboot end)
182 static void ari64_execute_until()
183 {
184         schedule_timeslice();
185
186         evprintf("ari64_execute %08x, %u->%u (%d)\n", psxRegs.pc,
187                 psxRegs.cycle, next_interupt, next_interupt - psxRegs.cycle);
188
189         new_dyna_start();
190
191         evprintf("ari64_execute end %08x, %u->%u (%d)\n", psxRegs.pc,
192                 psxRegs.cycle, next_interupt, next_interupt - psxRegs.cycle);
193 }
194
195 static void ari64_execute()
196 {
197         while (!stop) {
198                 ari64_execute_until();
199                 evprintf("drc left @%08x\n", psxRegs.pc);
200         }
201 }
202
203 static void ari64_clear(u32 addr, u32 size)
204 {
205         u32 start, end, main_ram;
206
207         size *= 4; /* PCSX uses DMA units */
208
209         evprintf("ari64_clear %08x %04x\n", addr, size);
210
211         /* check for RAM mirrors */
212         main_ram = (addr & 0xffe00000) == 0x80000000;
213
214         start = addr >> 12;
215         end = (addr + size) >> 12;
216
217         for (; start <= end; start++)
218                 if (!main_ram || !invalid_code[start])
219                         invalidate_block(start);
220 }
221
222 static void ari64_shutdown()
223 {
224         new_dynarec_cleanup();
225 }
226
227 extern void intExecute();
228 extern void intExecuteT();
229 extern void intExecuteBlock();
230 extern void intExecuteBlockT();
231 #ifndef DRC_DBG
232 #define intExecuteT intExecute
233 #define intExecuteBlockT intExecuteBlock
234 #endif
235
236 R3000Acpu psxRec = {
237         ari64_init,
238         ari64_reset,
239 #if defined(__arm__)
240         ari64_execute,
241         ari64_execute_until,
242 #else
243         intExecuteT,
244         intExecuteBlockT,
245 #endif
246         ari64_clear,
247         ari64_shutdown
248 };
249
250 // TODO: rm
251 #ifndef DRC_DBG
252 void do_insn_trace() {}
253 void do_insn_cmp() {}
254 #endif
255
256 #if defined(__x86_64__) || defined(__i386__)
257 unsigned int address, readmem_word, word;
258 unsigned short hword;
259 unsigned char byte;
260 int pending_exception, stop;
261 unsigned int next_interupt;
262 void *psxH_ptr;
263 void new_dynarec_init() {}
264 void new_dyna_start() {}
265 void new_dynarec_cleanup() {}
266 void invalidate_all_pages() {}
267 void invalidate_block(unsigned int block) {}
268 void new_dyna_pcsx_mem_init(void) {}
269 void new_dyna_pcsx_mem_reset(void) {}
270 #endif
271
272 #ifdef DRC_DBG
273
274 #include <stddef.h>
275 static FILE *f;
276 extern u32 last_io_addr;
277
278 static void dump_mem(const char *fname, void *mem, size_t size)
279 {
280         FILE *f1 = fopen(fname, "wb");
281         if (f1 == NULL)
282                 f1 = fopen(strrchr(fname, '/') + 1, "wb");
283         fwrite(mem, 1, size, f1);
284         fclose(f1);
285 }
286
287 static 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
302 void 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;
309         u32 io_data;
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         }
331         io_data = memcheck_read(last_io_addr);
332         if (old_io_data != io_data) {
333                 byte = 0xfe;
334                 fwrite(&byte, 1, 1, f);
335                 fwrite(&io_data, 1, 4, f);
336                 old_io_data = io_data;
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
351 static 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
375 static struct {
376         int reg;
377         u32 val, val_expect;
378         u32 pc, cycle;
379 } miss_log[64];
380 static 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
384 static 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
394 void breakme() {}
395
396 void 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
436         psxRegs.cycle = rregs.cycle;
437         psxRegs.CP0.r[9] = rregs.CP0.r[9]; // Count
438
439 //if (psxRegs.cycle == 166172) breakme();
440
441         if (memcmp(&psxRegs, &rregs, offsetof(psxRegisters, intCycle)) == 0 &&
442                         mem_val == memcheck_read(mem_addr)
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]) {
450                         miss_log_add(i, allregs_p[i], allregs_e[i], psxRegs.pc, psxRegs.cycle);
451                         bad++;
452                 }
453         }
454
455         if (mem_val != memcheck_read(mem_addr)) {
456                 printf("bad mem @%08x: %08x %08x\n", mem_addr, memcheck_read(mem_addr), mem_val);
457                 goto end;
458         }
459
460         if (psxRegs.pc == rregs.pc && bad < 6 && failcount < 32) {
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                 }
466                 failcount++;
467                 goto ok;
468         }
469
470 end:
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],
478                         i+8, allregs_p[i+8], i+16, allregs_p[i+16], i+24, allregs_p[i+24]);
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);
483 ok:
484         psxRegs.cycle = rregs.cycle + 2; // sync timing
485         ppc = psxRegs.pc;
486 }
487
488 #endif