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