improve event handling (still has problems though)
[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
28void 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
56void check_interupt()
57{
58 printf("ari64_check_interupt\n");
59}
60
61void read_nomem_new()
62{
63 printf("ari64_read_nomem_new\n");
64}
65
66static void read_mem8()
67{
68 memprintf("ari64_read_mem8 %08x, PC~=%08x\n", address, psxRegs.pc);
69 readmem_word = psxMemRead8(address) & 0xff;
70}
71
72static void read_mem16()
73{
74 memprintf("ari64_read_mem16 %08x, PC~=%08x\n", address, psxRegs.pc);
75 readmem_word = psxMemRead16(address) & 0xffff;
76}
77
78static void read_mem32()
79{
80 memprintf("ari64_read_mem32 %08x, PC~=%08x\n", address, psxRegs.pc);
81 readmem_word = psxMemRead32(address);
82}
83
84static void write_mem8()
85{
86 memprintf("ari64_write_mem8 %08x, %02x, PC~=%08x\n", address, byte, psxRegs.pc);
87 psxMemWrite8(address, byte);
88}
89
90static void write_mem16()
91{
92 memprintf("ari64_write_mem16 %08x, %04x, PC~=%08x\n", address, hword, psxRegs.pc);
93 psxMemWrite16(address, hword);
94}
95
96static void write_mem32()
97{
98 memprintf("ari64_write_mem32 %08x, %08x, PC~=%08x\n", address, word, psxRegs.pc);
99 psxMemWrite32(address, word);
100}
101
102void (*readmem[0x10000])();
103void (*readmemb[0x10000])();
104void (*readmemh[0x10000])();
105void (*writemem[0x10000])();
106void (*writememb[0x10000])();
107void (*writememh[0x10000])();
108
109void *gte_handlers[64];
110
111/* from gte.txt.. not sure if this is any good. */
112const 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
120static 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
144static void ari64_reset()
145{
146 /* hmh */
147 printf("ari64_reset\n");
148}
149
150static 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
160static void ari64_clear(u32 Addr, u32 Size)
161{
162}
163
164static void ari64_shutdown()
165{
166 new_dynarec_cleanup();
167}
168
169extern void intExecute();
170extern void intExecuteT();
171extern void intExecuteBlock();
172extern void intExecuteBlockT();
173#ifndef DRC_DBG
174#define intExecuteT intExecute
175#define intExecuteBlockT intExecuteBlock
176#endif
177
178R3000Acpu 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
194void do_insn_trace() {}
195void do_insn_cmp() {}
196#endif
197
198#if defined(__x86_64__) || defined(__i386__)
199unsigned int address, readmem_word, word;
200unsigned short hword;
201unsigned char byte;
202int pending_exception;
203unsigned int next_interupt;
204void new_dynarec_init() {}
205void new_dyna_start() {}
206void new_dynarec_cleanup() {}
207#endif
208
209#ifdef DRC_DBG
210
211#include <stddef.h>
212static FILE *f;
213extern u32 last_io_addr;
214
215static 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
224void 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
273static 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
297static struct {
298 int reg;
299 u32 val, val_expect;
300 u32 pc, cycle;
301} miss_log[64];
302static 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
306static 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
316void breakme() {}
317
318void 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
358psxRegs.cycle = rregs.cycle;
359psxRegs.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
395end:
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);
408ok:
409 psxRegs.cycle = rregs.cycle + 2; // sync timing
410 ppc = psxRegs.pc;
411}
412
413#endif