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