drc: use direct hle 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 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         return 0;
127 }
128
129 static void ari64_reset()
130 {
131         /* hmh */
132         printf("ari64_reset\n");
133 }
134
135 static void ari64_execute()
136 {
137         next_interupt = psxNextsCounter + psxNextCounter;
138
139         evprintf("psxNextsCounter %d, psxNextCounter %d\n", psxNextsCounter, psxNextCounter);
140         evprintf("ari64_execute %08x, %d->%d\n", psxRegs.pc, psxRegs.cycle, next_interupt);
141         new_dyna_start();
142         evprintf("ari64_execute end %08x, %d->%d\n", psxRegs.pc, psxRegs.cycle, next_interupt);
143 }
144
145 static void ari64_clear(u32 Addr, u32 Size)
146 {
147 }
148
149 static void ari64_shutdown()
150 {
151         new_dynarec_cleanup();
152 }
153
154 extern void intExecute();
155 extern void intExecuteT();
156 extern void intExecuteBlock();
157 extern void intExecuteBlockT();
158 #ifndef DRC_DBG
159 #define intExecuteT intExecute
160 #define intExecuteBlockT intExecuteBlock
161 #endif
162
163 R3000Acpu psxRec = {
164         ari64_init,
165         ari64_reset,
166 #if 1
167         ari64_execute,
168         ari64_execute,
169 #else
170         intExecuteT,
171         intExecuteBlockT,
172 #endif
173         ari64_clear,
174         ari64_shutdown
175 };
176
177 // TODO: rm
178 #ifndef DRC_DBG
179 void do_insn_trace() {}
180 void do_insn_cmp() {}
181 #endif
182
183 #if defined(__x86_64__) || defined(__i386__)
184 unsigned int address, readmem_word, word;
185 unsigned short hword;
186 unsigned char byte;
187 int pending_exception;
188 unsigned int next_interupt;
189 void new_dynarec_init() {}
190 int  new_dyna_start() {}
191 void new_dynarec_cleanup() {}
192 #endif
193
194 #ifdef DRC_DBG
195
196 #include <stddef.h>
197 static FILE *f;
198 extern u32 last_io_addr;
199
200 static void dump_mem(const char *fname, void *mem, size_t size)
201 {
202         FILE *f1 = fopen(fname, "wb");
203         fwrite(mem, 1, size, f1);
204         fclose(f1);
205 }
206
207 void do_insn_trace(void)
208 {
209         static psxRegisters oldregs;
210         static u32 old_io_addr = (u32)-1;
211         static u32 old_io_data = 0xbad0c0de;
212         u32 *allregs_p = (void *)&psxRegs;
213         u32 *allregs_o = (void *)&oldregs;
214         u32 *io_data;
215         int i;
216         u8 byte;
217
218 //last_io_addr = 0x5e2c8;
219         if (f == NULL)
220                 f = fopen("tracelog", "wb");
221
222         oldregs.code = psxRegs.code; // don't care
223         for (i = 0; i < offsetof(psxRegisters, intCycle) / 4; i++) {
224                 if (allregs_p[i] != allregs_o[i]) {
225                         fwrite(&i, 1, 1, f);
226                         fwrite(&allregs_p[i], 1, 4, f);
227                         allregs_o[i] = allregs_p[i];
228                 }
229         }
230         if (old_io_addr != last_io_addr) {
231                 byte = 0xfd;
232                 fwrite(&byte, 1, 1, f);
233                 fwrite(&last_io_addr, 1, 4, f);
234                 old_io_addr = last_io_addr;
235         }
236         io_data = (void *)(psxM + (last_io_addr&0x1ffffc));
237         if (old_io_data != *io_data) {
238                 byte = 0xfe;
239                 fwrite(&byte, 1, 1, f);
240                 fwrite(io_data, 1, 4, f);
241                 old_io_data = *io_data;
242         }
243         byte = 0xff;
244         fwrite(&byte, 1, 1, f);
245
246 #if 0
247         if (psxRegs.cycle == 190230) {
248                 dump_mem("/mnt/ntz/dev/pnd/tmp/psxram_i.dump", psxM, 0x200000);
249                 dump_mem("/mnt/ntz/dev/pnd/tmp/psxregs_i.dump", psxH, 0x10000);
250                 printf("dumped\n");
251                 exit(1);
252         }
253 #endif
254 }
255
256 static const char *regnames[offsetof(psxRegisters, intCycle) / 4] = {
257         "r0",  "r1",  "r2",  "r3",  "r4",  "r5",  "r6",  "r7",
258         "r8",  "r9",  "r10", "r11", "r12", "r13", "r14", "r15",
259         "r16", "r17", "r18", "r19", "r20", "r21", "r22", "r23",
260         "r24", "r25", "r26", "r27", "r28", "r29", "r30", "r31",
261         "lo",  "hi",
262         "C0_0",  "C0_1",  "C0_2",  "C0_3",  "C0_4",  "C0_5",  "C0_6",  "C0_7",
263         "C0_8",  "C0_9",  "C0_10", "C0_11", "C0_12", "C0_13", "C0_14", "C0_15",
264         "C0_16", "C0_17", "C0_18", "C0_19", "C0_20", "C0_21", "C0_22", "C0_23",
265         "C0_24", "C0_25", "C0_26", "C0_27", "C0_28", "C0_29", "C0_30", "C0_31",
266
267         "C2D0",  "C2D1",  "C2D2",  "C2D3",  "C2D4",  "C2D5",  "C2D6",  "C2D7",
268         "C2D8",  "C2D9",  "C2D10", "C2D11", "C2D12", "C2D13", "C2D14", "C2D15",
269         "C2D16", "C2D17", "C2D18", "C2D19", "C2D20", "C2D21", "C2D22", "C2D23",
270         "C2D24", "C2D25", "C2D26", "C2D27", "C2D28", "C2D29", "C2D30", "C2D31",
271
272         "C2C0",  "C2C1",  "C2C2",  "C2C3",  "C2C4",  "C2C5",  "C2C6",  "C2C7",
273         "C2C8",  "C2C9",  "C2C10", "C2C11", "C2C12", "C2C13", "C2C14", "C2C15",
274         "C2C16", "C2C17", "C2C18", "C2C19", "C2C20", "C2C21", "C2C22", "C2C23",
275         "C2C24", "C2C25", "C2C26", "C2C27", "C2C28", "C2C29", "C2C30", "C2C31",
276
277         "PC", "code", "cycle", "interrupt",
278 };
279
280 void breakme() {}
281
282 void do_insn_cmp(void)
283 {
284         static psxRegisters rregs;
285         static u32 mem_addr, mem_val;
286         u32 *allregs_p = (void *)&psxRegs;
287         u32 *allregs_e = (void *)&rregs;
288         static u32 ppc, failcount;
289         int i, ret, bad = 0;
290         u8 code;
291
292         if (f == NULL)
293                 f = fopen("tracelog", "rb");
294
295         while (1) {
296                 if ((ret = fread(&code, 1, 1, f)) <= 0)
297                         break;
298                 if (ret <= 0)
299                         break;
300                 if (code == 0xff)
301                         break;
302                 if (code == 0xfd) {
303                         if ((ret = fread(&mem_addr, 1, 4, f)) <= 0)
304                                 break;
305                         continue;
306                 }
307                 if (code == 0xfe) {
308                         if ((ret = fread(&mem_val, 1, 4, f)) <= 0)
309                                 break;
310                         continue;
311                 }
312                 if ((ret = fread(&allregs_e[code], 1, 4, f)) <= 0)
313                         break;
314         }
315
316         if (ret <= 0) {
317                 printf("EOF?\n");
318                 goto end;
319         }
320
321         psxRegs.code = rregs.code; // don't care
322 psxRegs.cycle = rregs.cycle;
323 psxRegs.CP0.r[9] = rregs.CP0.r[9]; // Count
324
325 //if (psxRegs.cycle == 166172) breakme();
326 //if (psxRegs.cycle > 11296376) printf("pc=%08x %u  %08x\n", psxRegs.pc, psxRegs.cycle, psxRegs.interrupt);
327
328         mem_addr &= 0x1ffffc;
329
330         if (memcmp(&psxRegs, &rregs, offsetof(psxRegisters, intCycle)) == 0 &&
331                         mem_val == *(u32 *)(psxM + mem_addr)
332            ) {
333                 failcount = 0;
334                 goto ok;
335         }
336
337         for (i = 0; i < offsetof(psxRegisters, intCycle) / 4; i++) {
338                 if (allregs_p[i] != allregs_e[i]) {
339                         printf("bad %5s: %08x %08x, pc=%08x, cycle %u\n",
340                                 regnames[i], allregs_p[i], allregs_e[i], psxRegs.pc, psxRegs.cycle);
341                         bad++;
342                 }
343         }
344
345         if (mem_val != *(u32 *)(psxM + mem_addr)) {
346                 printf("bad mem @%08x: %08x %08x\n", mem_addr, *(u32 *)(psxM + mem_addr), mem_val);
347                 goto end;
348         }
349
350         if (psxRegs.pc == rregs.pc && bad < 6 && failcount < 32) {
351                 printf("-- %d\n", bad);
352                 failcount++;
353                 goto ok;
354         }
355
356 end:
357         printf("PC: %08x/%08x, cycle %u\n", psxRegs.pc, ppc, psxRegs.cycle);
358         dump_mem("/mnt/ntz/dev/pnd/tmp/psxram.dump", psxM, 0x200000);
359         dump_mem("/mnt/ntz/dev/pnd/tmp/psxregs.dump", psxH, 0x10000);
360         exit(1);
361 ok:
362         psxRegs.cycle = rregs.cycle + 2; // sync timing
363         ppc = psxRegs.pc;
364 }
365
366 #endif