improve event handling (still has problems though)
[pcsx_rearmed.git] / libpcsxcore / new_dynarec / emu_if.c
CommitLineData
7139f3c8 1// pending_exception?
822b27d1 2// swi 0 in do_unalignedwritestub?
f95a77f7 3#include <stdio.h>
4
5#include "emu_if.h"
7139f3c8 6#include "../psxmem.h"
7#include "../psxhle.h"
8
ae602c19 9#define ARRAY_SIZE(x) (sizeof(x) / sizeof(x[0]))
10
7139f3c8 11//#define memprintf printf
12#define memprintf(...)
13//#define evprintf printf
14#define evprintf(...)
15
f95a77f7 16char invalid_code[0x100000];
ae602c19 17u32 event_cycles[6];
f95a77f7 18
7139f3c8 19void MTC0_()
f95a77f7 20{
7139f3c8 21 extern void psxMTC0();
22
b9b61529 23 memprintf("ari64 MTC0 %08x\n", psxRegs.code);
7139f3c8 24 psxMTC0();
25 pending_exception = 1; /* FIXME? */
f95a77f7 26}
27
28void gen_interupt()
29{
ae602c19 30 u32 c, min;
31 int i;
32
7139f3c8 33 evprintf("ari64_gen_interupt\n");
822b27d1 34 evprintf(" +ge %08x, %d->%d\n", psxRegs.pc, psxRegs.cycle, next_interupt);
7139f3c8 35#ifdef DRC_DBG
36 psxRegs.cycle += 2;
7139f3c8 37#endif
38
39 psxBranchTest();
40
ae602c19 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;
822b27d1 51 evprintf(" -ge %08x, %d->%d\n", psxRegs.pc, psxRegs.cycle, next_interupt);
7139f3c8 52
53 pending_exception = 1; /* FIXME */
f95a77f7 54}
55
56void check_interupt()
57{
7139f3c8 58 printf("ari64_check_interupt\n");
f95a77f7 59}
60
61void read_nomem_new()
62{
7139f3c8 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);
f95a77f7 88}
89
7139f3c8 90static void write_mem16()
f95a77f7 91{
7139f3c8 92 memprintf("ari64_write_mem16 %08x, %04x, PC~=%08x\n", address, hword, psxRegs.pc);
93 psxMemWrite16(address, hword);
f95a77f7 94}
95
7139f3c8 96static void write_mem32()
f95a77f7 97{
7139f3c8 98 memprintf("ari64_write_mem32 %08x, %08x, PC~=%08x\n", address, word, psxRegs.pc);
99 psxMemWrite32(address, word);
f95a77f7 100}
101
102void (*readmem[0x10000])();
103void (*readmemb[0x10000])();
104void (*readmemh[0x10000])();
105void (*writemem[0x10000])();
106void (*writememb[0x10000])();
107void (*writememh[0x10000])();
108
b9b61529 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};
f95a77f7 119
120static int ari64_init()
121{
b9b61529 122 extern void (*psxCP2[64])();
123 extern void psxNULL();
f95a77f7 124 size_t i;
b9b61529 125
f95a77f7 126 new_dynarec_init();
127
ae602c19 128 for (i = 0; i < ARRAY_SIZE(readmem); i++) {
7139f3c8 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;
f95a77f7 135 }
7139f3c8 136
ae602c19 137 for (i = 0; i < ARRAY_SIZE(gte_handlers); i++)
b9b61529 138 if (psxCP2[i] != psxNULL)
139 gte_handlers[i] = psxCP2[i];
140
b9b61529 141 return 0;
f95a77f7 142}
143
144static void ari64_reset()
145{
146 /* hmh */
147 printf("ari64_reset\n");
148}
149
150static void ari64_execute()
151{
822b27d1 152 next_interupt = psxNextsCounter + psxNextCounter;
7139f3c8 153
b9b61529 154 evprintf("psxNextsCounter %d, psxNextCounter %d\n", psxNextsCounter, psxNextCounter);
822b27d1 155 evprintf("ari64_execute %08x, %d->%d\n", psxRegs.pc, psxRegs.cycle, next_interupt);
b9b61529 156 new_dyna_start();
822b27d1 157 evprintf("ari64_execute end %08x, %d->%d\n", psxRegs.pc, psxRegs.cycle, next_interupt);
f95a77f7 158}
159
160static void ari64_clear(u32 Addr, u32 Size)
161{
162}
163
164static void ari64_shutdown()
165{
166 new_dynarec_cleanup();
167}
168
7139f3c8 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
f95a77f7 178R3000Acpu psxRec = {
179 ari64_init,
180 ari64_reset,
7139f3c8 181#if 1
f95a77f7 182 ari64_execute,
7139f3c8 183 ari64_execute,
184#else
185 intExecuteT,
186 intExecuteBlockT,
187#endif
f95a77f7 188 ari64_clear,
189 ari64_shutdown
190};
7139f3c8 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;
7139f3c8 204void new_dynarec_init() {}
3eb78778 205void new_dyna_start() {}
7139f3c8 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");
3eb78778 218 if (f1 == NULL)
219 f1 = fopen(strrchr(fname, '/') + 1, "wb");
7139f3c8 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
3eb78778 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
7139f3c8 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]) {
3eb78778 375 miss_log_add(i, allregs_p[i], allregs_e[i], psxRegs.pc, psxRegs.cycle);
7139f3c8 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) {
3eb78778 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 }
7139f3c8 391 failcount++;
392 goto ok;
393 }
394
395end:
3eb78778 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]);
7139f3c8 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