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