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