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