cdrom: merge most of cdrom.c from latest pcsxr (r62214)
[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;
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         if ((addr & ~0xe0600000) < 0x200000) {
213                 addr &= ~0xe0600000;
214                 addr |=  0x80000000;
215         }
216
217         start = addr >> 12;
218         end = (addr + size) >> 12;
219
220         for (; start <= end; start++)
221                 if (!invalid_code[start])
222                         invalidate_block(start);
223 }
224
225 static void ari64_shutdown()
226 {
227         new_dynarec_cleanup();
228 }
229
230 extern void intExecute();
231 extern void intExecuteT();
232 extern void intExecuteBlock();
233 extern void intExecuteBlockT();
234 #ifndef DRC_DBG
235 #define intExecuteT intExecute
236 #define intExecuteBlockT intExecuteBlock
237 #endif
238
239 R3000Acpu psxRec = {
240         ari64_init,
241         ari64_reset,
242 #if defined(__arm__)
243         ari64_execute,
244         ari64_execute_until,
245 #else
246         intExecuteT,
247         intExecuteBlockT,
248 #endif
249         ari64_clear,
250         ari64_shutdown
251 };
252
253 // TODO: rm
254 #ifndef DRC_DBG
255 void do_insn_trace() {}
256 void do_insn_cmp() {}
257 #endif
258
259 #if defined(__x86_64__) || defined(__i386__)
260 unsigned int address, readmem_word, word;
261 unsigned short hword;
262 unsigned char byte;
263 int pending_exception, stop;
264 unsigned int next_interupt;
265 void *psxH_ptr;
266 void new_dynarec_init() {}
267 void new_dyna_start() {}
268 void new_dynarec_cleanup() {}
269 void invalidate_all_pages() {}
270 void invalidate_block(unsigned int block) {}
271 void new_dyna_pcsx_mem_init(void) {}
272 void new_dyna_pcsx_mem_reset(void) {}
273 #endif
274
275 #ifdef DRC_DBG
276
277 #include <stddef.h>
278 static FILE *f;
279 extern u32 last_io_addr;
280
281 static void dump_mem(const char *fname, void *mem, size_t size)
282 {
283         FILE *f1 = fopen(fname, "wb");
284         if (f1 == NULL)
285                 f1 = fopen(strrchr(fname, '/') + 1, "wb");
286         fwrite(mem, 1, size, f1);
287         fclose(f1);
288 }
289
290 static u32 memcheck_read(u32 a)
291 {
292         if ((a >> 16) == 0x1f80)
293                 // scratchpad/IO
294                 return *(u32 *)(psxH + (a & 0xfffc));
295
296         if ((a >> 16) == 0x1f00)
297                 // parallel
298                 return *(u32 *)(psxP + (a & 0xfffc));
299
300 //      if ((a & ~0xe0600000) < 0x200000)
301         // RAM
302         return *(u32 *)(psxM + (a & 0x1ffffc));
303 }
304
305 void do_insn_trace(void)
306 {
307         static psxRegisters oldregs;
308         static u32 old_io_addr = (u32)-1;
309         static u32 old_io_data = 0xbad0c0de;
310         u32 *allregs_p = (void *)&psxRegs;
311         u32 *allregs_o = (void *)&oldregs;
312         u32 io_data;
313         int i;
314         u8 byte;
315
316 //last_io_addr = 0x5e2c8;
317         if (f == NULL)
318                 f = fopen("tracelog", "wb");
319
320         oldregs.code = psxRegs.code; // don't care
321         for (i = 0; i < offsetof(psxRegisters, intCycle) / 4; i++) {
322                 if (allregs_p[i] != allregs_o[i]) {
323                         fwrite(&i, 1, 1, f);
324                         fwrite(&allregs_p[i], 1, 4, f);
325                         allregs_o[i] = allregs_p[i];
326                 }
327         }
328         if (old_io_addr != last_io_addr) {
329                 byte = 0xfd;
330                 fwrite(&byte, 1, 1, f);
331                 fwrite(&last_io_addr, 1, 4, f);
332                 old_io_addr = last_io_addr;
333         }
334         io_data = memcheck_read(last_io_addr);
335         if (old_io_data != io_data) {
336                 byte = 0xfe;
337                 fwrite(&byte, 1, 1, f);
338                 fwrite(&io_data, 1, 4, f);
339                 old_io_data = io_data;
340         }
341         byte = 0xff;
342         fwrite(&byte, 1, 1, f);
343
344 #if 0
345         if (psxRegs.cycle == 190230) {
346                 dump_mem("/mnt/ntz/dev/pnd/tmp/psxram_i.dump", psxM, 0x200000);
347                 dump_mem("/mnt/ntz/dev/pnd/tmp/psxregs_i.dump", psxH, 0x10000);
348                 printf("dumped\n");
349                 exit(1);
350         }
351 #endif
352 }
353
354 static const char *regnames[offsetof(psxRegisters, intCycle) / 4] = {
355         "r0",  "r1",  "r2",  "r3",  "r4",  "r5",  "r6",  "r7",
356         "r8",  "r9",  "r10", "r11", "r12", "r13", "r14", "r15",
357         "r16", "r17", "r18", "r19", "r20", "r21", "r22", "r23",
358         "r24", "r25", "r26", "r27", "r28", "r29", "r30", "r31",
359         "lo",  "hi",
360         "C0_0",  "C0_1",  "C0_2",  "C0_3",  "C0_4",  "C0_5",  "C0_6",  "C0_7",
361         "C0_8",  "C0_9",  "C0_10", "C0_11", "C0_12", "C0_13", "C0_14", "C0_15",
362         "C0_16", "C0_17", "C0_18", "C0_19", "C0_20", "C0_21", "C0_22", "C0_23",
363         "C0_24", "C0_25", "C0_26", "C0_27", "C0_28", "C0_29", "C0_30", "C0_31",
364
365         "C2D0",  "C2D1",  "C2D2",  "C2D3",  "C2D4",  "C2D5",  "C2D6",  "C2D7",
366         "C2D8",  "C2D9",  "C2D10", "C2D11", "C2D12", "C2D13", "C2D14", "C2D15",
367         "C2D16", "C2D17", "C2D18", "C2D19", "C2D20", "C2D21", "C2D22", "C2D23",
368         "C2D24", "C2D25", "C2D26", "C2D27", "C2D28", "C2D29", "C2D30", "C2D31",
369
370         "C2C0",  "C2C1",  "C2C2",  "C2C3",  "C2C4",  "C2C5",  "C2C6",  "C2C7",
371         "C2C8",  "C2C9",  "C2C10", "C2C11", "C2C12", "C2C13", "C2C14", "C2C15",
372         "C2C16", "C2C17", "C2C18", "C2C19", "C2C20", "C2C21", "C2C22", "C2C23",
373         "C2C24", "C2C25", "C2C26", "C2C27", "C2C28", "C2C29", "C2C30", "C2C31",
374
375         "PC", "code", "cycle", "interrupt",
376 };
377
378 static struct {
379         int reg;
380         u32 val, val_expect;
381         u32 pc, cycle;
382 } miss_log[64];
383 static int miss_log_i;
384 #define miss_log_len (sizeof(miss_log)/sizeof(miss_log[0]))
385 #define miss_log_mask (miss_log_len-1)
386
387 static void miss_log_add(int reg, u32 val, u32 val_expect, u32 pc, u32 cycle)
388 {
389         miss_log[miss_log_i].reg = reg;
390         miss_log[miss_log_i].val = val;
391         miss_log[miss_log_i].val_expect = val_expect;
392         miss_log[miss_log_i].pc = pc;
393         miss_log[miss_log_i].cycle = cycle;
394         miss_log_i = (miss_log_i + 1) & miss_log_mask;
395 }
396
397 void breakme() {}
398
399 void do_insn_cmp(void)
400 {
401         static psxRegisters rregs;
402         static u32 mem_addr, mem_val;
403         u32 *allregs_p = (void *)&psxRegs;
404         u32 *allregs_e = (void *)&rregs;
405         static u32 ppc, failcount;
406         int i, ret, bad = 0;
407         u8 code;
408
409         if (f == NULL)
410                 f = fopen("tracelog", "rb");
411
412         while (1) {
413                 if ((ret = fread(&code, 1, 1, f)) <= 0)
414                         break;
415                 if (ret <= 0)
416                         break;
417                 if (code == 0xff)
418                         break;
419                 if (code == 0xfd) {
420                         if ((ret = fread(&mem_addr, 1, 4, f)) <= 0)
421                                 break;
422                         continue;
423                 }
424                 if (code == 0xfe) {
425                         if ((ret = fread(&mem_val, 1, 4, f)) <= 0)
426                                 break;
427                         continue;
428                 }
429                 if ((ret = fread(&allregs_e[code], 1, 4, f)) <= 0)
430                         break;
431         }
432
433         if (ret <= 0) {
434                 printf("EOF?\n");
435                 goto end;
436         }
437
438         psxRegs.code = rregs.code; // don't care
439         psxRegs.cycle = rregs.cycle;
440         psxRegs.CP0.r[9] = rregs.CP0.r[9]; // Count
441
442 //if (psxRegs.cycle == 166172) breakme();
443
444         if (memcmp(&psxRegs, &rregs, offsetof(psxRegisters, intCycle)) == 0 &&
445                         mem_val == memcheck_read(mem_addr)
446            ) {
447                 failcount = 0;
448                 goto ok;
449         }
450
451         for (i = 0; i < offsetof(psxRegisters, intCycle) / 4; i++) {
452                 if (allregs_p[i] != allregs_e[i]) {
453                         miss_log_add(i, allregs_p[i], allregs_e[i], psxRegs.pc, psxRegs.cycle);
454                         bad++;
455                 }
456         }
457
458         if (mem_val != memcheck_read(mem_addr)) {
459                 printf("bad mem @%08x: %08x %08x\n", mem_addr, memcheck_read(mem_addr), mem_val);
460                 goto end;
461         }
462
463         if (psxRegs.pc == rregs.pc && bad < 6 && failcount < 32) {
464                 static int last_mcycle;
465                 if (last_mcycle != psxRegs.cycle >> 20) {
466                         printf("%u\n", psxRegs.cycle);
467                         last_mcycle = psxRegs.cycle >> 20;
468                 }
469                 failcount++;
470                 goto ok;
471         }
472
473 end:
474         for (i = 0; i < miss_log_len; i++, miss_log_i = (miss_log_i + 1) & miss_log_mask)
475                 printf("bad %5s: %08x %08x, pc=%08x, cycle %u\n",
476                         regnames[miss_log[miss_log_i].reg], miss_log[miss_log_i].val,
477                         miss_log[miss_log_i].val_expect, miss_log[miss_log_i].pc, miss_log[miss_log_i].cycle);
478         printf("-- %d\n", bad);
479         for (i = 0; i < 8; i++)
480                 printf("r%d=%08x r%2d=%08x r%2d=%08x r%2d=%08x\n", i, allregs_p[i],
481                         i+8, allregs_p[i+8], i+16, allregs_p[i+16], i+24, allregs_p[i+24]);
482         printf("PC: %08x/%08x, cycle %u\n", psxRegs.pc, ppc, psxRegs.cycle);
483         dump_mem("/mnt/ntz/dev/pnd/tmp/psxram.dump", psxM, 0x200000);
484         dump_mem("/mnt/ntz/dev/pnd/tmp/psxregs.dump", psxH, 0x10000);
485         exit(1);
486 ok:
487         psxRegs.cycle = rregs.cycle + 2; // sync timing
488         ppc = psxRegs.pc;
489 }
490
491 #endif