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