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