io asm: always write out to psxH, like C code does
[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 1
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 void do_insn_trace(void)
276 {
277         static psxRegisters oldregs;
278         static u32 old_io_addr = (u32)-1;
279         static u32 old_io_data = 0xbad0c0de;
280         u32 *allregs_p = (void *)&psxRegs;
281         u32 *allregs_o = (void *)&oldregs;
282         u32 *io_data;
283         int i;
284         u8 byte;
285
286 //last_io_addr = 0x5e2c8;
287         if (f == NULL)
288                 f = fopen("tracelog", "wb");
289
290         oldregs.code = psxRegs.code; // don't care
291         for (i = 0; i < offsetof(psxRegisters, intCycle) / 4; i++) {
292                 if (allregs_p[i] != allregs_o[i]) {
293                         fwrite(&i, 1, 1, f);
294                         fwrite(&allregs_p[i], 1, 4, f);
295                         allregs_o[i] = allregs_p[i];
296                 }
297         }
298         if (old_io_addr != last_io_addr) {
299                 byte = 0xfd;
300                 fwrite(&byte, 1, 1, f);
301                 fwrite(&last_io_addr, 1, 4, f);
302                 old_io_addr = last_io_addr;
303         }
304         io_data = (void *)(psxM + (last_io_addr&0x1ffffc));
305         if (old_io_data != *io_data) {
306                 byte = 0xfe;
307                 fwrite(&byte, 1, 1, f);
308                 fwrite(io_data, 1, 4, f);
309                 old_io_data = *io_data;
310         }
311         byte = 0xff;
312         fwrite(&byte, 1, 1, f);
313
314 #if 0
315         if (psxRegs.cycle == 190230) {
316                 dump_mem("/mnt/ntz/dev/pnd/tmp/psxram_i.dump", psxM, 0x200000);
317                 dump_mem("/mnt/ntz/dev/pnd/tmp/psxregs_i.dump", psxH, 0x10000);
318                 printf("dumped\n");
319                 exit(1);
320         }
321 #endif
322 }
323
324 static const char *regnames[offsetof(psxRegisters, intCycle) / 4] = {
325         "r0",  "r1",  "r2",  "r3",  "r4",  "r5",  "r6",  "r7",
326         "r8",  "r9",  "r10", "r11", "r12", "r13", "r14", "r15",
327         "r16", "r17", "r18", "r19", "r20", "r21", "r22", "r23",
328         "r24", "r25", "r26", "r27", "r28", "r29", "r30", "r31",
329         "lo",  "hi",
330         "C0_0",  "C0_1",  "C0_2",  "C0_3",  "C0_4",  "C0_5",  "C0_6",  "C0_7",
331         "C0_8",  "C0_9",  "C0_10", "C0_11", "C0_12", "C0_13", "C0_14", "C0_15",
332         "C0_16", "C0_17", "C0_18", "C0_19", "C0_20", "C0_21", "C0_22", "C0_23",
333         "C0_24", "C0_25", "C0_26", "C0_27", "C0_28", "C0_29", "C0_30", "C0_31",
334
335         "C2D0",  "C2D1",  "C2D2",  "C2D3",  "C2D4",  "C2D5",  "C2D6",  "C2D7",
336         "C2D8",  "C2D9",  "C2D10", "C2D11", "C2D12", "C2D13", "C2D14", "C2D15",
337         "C2D16", "C2D17", "C2D18", "C2D19", "C2D20", "C2D21", "C2D22", "C2D23",
338         "C2D24", "C2D25", "C2D26", "C2D27", "C2D28", "C2D29", "C2D30", "C2D31",
339
340         "C2C0",  "C2C1",  "C2C2",  "C2C3",  "C2C4",  "C2C5",  "C2C6",  "C2C7",
341         "C2C8",  "C2C9",  "C2C10", "C2C11", "C2C12", "C2C13", "C2C14", "C2C15",
342         "C2C16", "C2C17", "C2C18", "C2C19", "C2C20", "C2C21", "C2C22", "C2C23",
343         "C2C24", "C2C25", "C2C26", "C2C27", "C2C28", "C2C29", "C2C30", "C2C31",
344
345         "PC", "code", "cycle", "interrupt",
346 };
347
348 static struct {
349         int reg;
350         u32 val, val_expect;
351         u32 pc, cycle;
352 } miss_log[64];
353 static int miss_log_i;
354 #define miss_log_len (sizeof(miss_log)/sizeof(miss_log[0]))
355 #define miss_log_mask (miss_log_len-1)
356
357 static void miss_log_add(int reg, u32 val, u32 val_expect, u32 pc, u32 cycle)
358 {
359         miss_log[miss_log_i].reg = reg;
360         miss_log[miss_log_i].val = val;
361         miss_log[miss_log_i].val_expect = val_expect;
362         miss_log[miss_log_i].pc = pc;
363         miss_log[miss_log_i].cycle = cycle;
364         miss_log_i = (miss_log_i + 1) & miss_log_mask;
365 }
366
367 void breakme() {}
368
369 void do_insn_cmp(void)
370 {
371         static psxRegisters rregs;
372         static u32 mem_addr, mem_val;
373         u32 *allregs_p = (void *)&psxRegs;
374         u32 *allregs_e = (void *)&rregs;
375         static u32 ppc, failcount;
376         int i, ret, bad = 0;
377         u8 code;
378
379         if (f == NULL)
380                 f = fopen("tracelog", "rb");
381
382         while (1) {
383                 if ((ret = fread(&code, 1, 1, f)) <= 0)
384                         break;
385                 if (ret <= 0)
386                         break;
387                 if (code == 0xff)
388                         break;
389                 if (code == 0xfd) {
390                         if ((ret = fread(&mem_addr, 1, 4, f)) <= 0)
391                                 break;
392                         continue;
393                 }
394                 if (code == 0xfe) {
395                         if ((ret = fread(&mem_val, 1, 4, f)) <= 0)
396                                 break;
397                         continue;
398                 }
399                 if ((ret = fread(&allregs_e[code], 1, 4, f)) <= 0)
400                         break;
401         }
402
403         if (ret <= 0) {
404                 printf("EOF?\n");
405                 goto end;
406         }
407
408         psxRegs.code = rregs.code; // don't care
409 psxRegs.cycle = rregs.cycle;
410 psxRegs.CP0.r[9] = rregs.CP0.r[9]; // Count
411
412 //if (psxRegs.cycle == 166172) breakme();
413 //if (psxRegs.cycle > 11296376) printf("pc=%08x %u  %08x\n", psxRegs.pc, psxRegs.cycle, psxRegs.interrupt);
414
415         mem_addr &= 0x1ffffc;
416
417         if (memcmp(&psxRegs, &rregs, offsetof(psxRegisters, intCycle)) == 0 &&
418                         mem_val == *(u32 *)(psxM + mem_addr)
419            ) {
420                 failcount = 0;
421                 goto ok;
422         }
423
424         for (i = 0; i < offsetof(psxRegisters, intCycle) / 4; i++) {
425                 if (allregs_p[i] != allregs_e[i]) {
426                         miss_log_add(i, allregs_p[i], allregs_e[i], psxRegs.pc, psxRegs.cycle);
427                         bad++;
428                 }
429         }
430
431         if (mem_val != *(u32 *)(psxM + mem_addr)) {
432                 printf("bad mem @%08x: %08x %08x\n", mem_addr, *(u32 *)(psxM + mem_addr), mem_val);
433                 goto end;
434         }
435
436         if (psxRegs.pc == rregs.pc && bad < 6 && failcount < 32) {
437                 static int last_mcycle;
438                 if (last_mcycle != psxRegs.cycle >> 20) {
439                         printf("%u\n", psxRegs.cycle);
440                         last_mcycle = psxRegs.cycle >> 20;
441                 }
442                 failcount++;
443                 goto ok;
444         }
445
446 end:
447         for (i = 0; i < miss_log_len; i++, miss_log_i = (miss_log_i + 1) & miss_log_mask)
448                 printf("bad %5s: %08x %08x, pc=%08x, cycle %u\n",
449                         regnames[miss_log[miss_log_i].reg], miss_log[miss_log_i].val,
450                         miss_log[miss_log_i].val_expect, miss_log[miss_log_i].pc, miss_log[miss_log_i].cycle);
451         printf("-- %d\n", bad);
452         for (i = 0; i < 8; i++)
453                 printf("r%d=%08x r%2d=%08x r%2d=%08x r%2d=%08x\n", i, allregs_p[i],
454                         i+8, allregs_p[i+8], i+16, allregs_p[i+16], i+24, allregs_p[i+24]);
455         printf("PC: %08x/%08x, cycle %u\n", psxRegs.pc, ppc, psxRegs.cycle);
456         dump_mem("/mnt/ntz/dev/pnd/tmp/psxram.dump", psxM, 0x200000);
457         dump_mem("/mnt/ntz/dev/pnd/tmp/psxregs.dump", psxH, 0x10000);
458         exit(1);
459 ok:
460         psxRegs.cycle = rregs.cycle + 2; // sync timing
461         ppc = psxRegs.pc;
462 }
463
464 #endif