minor debug code updates
[pcsx_rearmed.git] / libpcsxcore / new_dynarec / emu_if.c
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
24 char invalid_code[0x100000];
25 u32 event_cycles[PSXINT_COUNT];
26
27 static 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
54 typedef void (irq_func)();
55
56 static 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 */
71 static 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
99 void 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
114 extern void MTC0(int reg, u32 val);
115
116 void 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
123 void 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
129 void new_dyna_save(void)
130 {
131         // psxRegs.intCycle is always maintained, no need to convert
132 }
133
134 void 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
141 void *gte_handlers[64];
142
143 /* from gte.txt.. not sure if this is any good. */
144 const 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
152 static 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
175 static 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)
186 static 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
199 static void ari64_execute()
200 {
201         while (!stop) {
202                 ari64_execute_until();
203                 evprintf("drc left @%08x\n", psxRegs.pc);
204         }
205 }
206
207 static 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
226 static void ari64_shutdown()
227 {
228         new_dynarec_cleanup();
229 }
230
231 extern void intExecute();
232 extern void intExecuteT();
233 extern void intExecuteBlock();
234 extern void intExecuteBlockT();
235 #ifndef DRC_DBG
236 #define intExecuteT intExecute
237 #define intExecuteBlockT intExecuteBlock
238 #endif
239
240 R3000Acpu 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
256 void do_insn_trace() {}
257 void do_insn_cmp() {}
258 #endif
259
260 #if defined(__x86_64__) || defined(__i386__)
261 unsigned int address, readmem_word, word;
262 unsigned short hword;
263 unsigned char byte;
264 int pending_exception, stop;
265 unsigned int next_interupt;
266 void *psxH_ptr;
267 void new_dynarec_init() {}
268 void new_dyna_start() {}
269 void new_dynarec_cleanup() {}
270 void new_dynarec_clear_full() {}
271 void invalidate_all_pages() {}
272 void invalidate_block(unsigned int block) {}
273 void new_dyna_pcsx_mem_init(void) {}
274 void new_dyna_pcsx_mem_reset(void) {}
275 #endif
276
277 #ifdef DRC_DBG
278
279 #include <stddef.h>
280 static FILE *f;
281 extern u32 last_io_addr;
282
283 static 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
292 static 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
307 void 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
356 static 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
380 static struct {
381         int reg;
382         u32 val, val_expect;
383         u32 pc, cycle;
384 } miss_log[64];
385 static 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
389 static 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
399 void breakme() {}
400
401 void 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
475 end:
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);
488 ok:
489         psxRegs.cycle = rregs.cycle + 2; // sync timing
490         ppc = psxRegs.pc;
491 }
492
493 #endif