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