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