core: update to newer interrupt code, seems to affect timings too
[pcsx_rearmed.git] / libpcsxcore / new_dynarec / emu_if.c
CommitLineData
7e605697 1/*
2 * (C) GraÅžvydas "notaz" Ignotas, 2010
3 *
4 * This work is licensed under the terms of GNU GPL version 2 or later.
5 * See the COPYING file in the top-level directory.
6 */
7
7139f3c8 8// pending_exception?
822b27d1 9// swi 0 in do_unalignedwritestub?
f95a77f7 10#include <stdio.h>
11
12#include "emu_if.h"
7e605697 13#include "pcsxmem.h"
7139f3c8 14#include "../psxhle.h"
d28b54b1 15#include "../r3000a.h"
7139f3c8 16
ae602c19 17#define ARRAY_SIZE(x) (sizeof(x) / sizeof(x[0]))
18
7139f3c8 19//#define evprintf printf
20#define evprintf(...)
21
f95a77f7 22char invalid_code[0x100000];
d28b54b1 23u32 event_cycles[PSXINT_COUNT];
f95a77f7 24
654e8cfb 25static void schedule_timeslice(void)
f95a77f7 26{
654e8cfb 27 u32 i, c = psxRegs.cycle;
28 s32 min, dif;
29
30 min = psxNextsCounter + psxNextCounter - c;
31 for (i = 0; i < ARRAY_SIZE(event_cycles); i++) {
32 dif = event_cycles[i] - c;
33 //evprintf(" ev %d\n", dif);
34 if (0 < dif && dif < min)
35 min = dif;
36 }
37 next_interupt = c + min;
38
39#if 0
40 static u32 cnt, last_cycle;
41 static u64 sum;
42 if (last_cycle) {
43 cnt++;
44 sum += psxRegs.cycle - last_cycle;
45 if ((cnt & 0xff) == 0)
46 printf("%u\n", (u32)(sum / cnt));
47 }
48 last_cycle = psxRegs.cycle;
49#endif
50}
ae602c19 51
654e8cfb 52void gen_interupt()
53{
654e8cfb 54 evprintf(" +ge %08x, %u->%u\n", psxRegs.pc, psxRegs.cycle, next_interupt);
7139f3c8 55#ifdef DRC_DBG
56 psxRegs.cycle += 2;
7139f3c8 57#endif
58
59 psxBranchTest();
60
654e8cfb 61 schedule_timeslice();
ae602c19 62
654e8cfb 63 evprintf(" -ge %08x, %u->%u (%d)\n", psxRegs.pc, psxRegs.cycle,
64 next_interupt, next_interupt - psxRegs.cycle);
7139f3c8 65
66 pending_exception = 1; /* FIXME */
f95a77f7 67}
68
28bc5688 69void MTC0_()
70{
71 extern void psxMTC0();
72
73 evprintf("ari64 MTC0 %08x %08x %u\n", psxRegs.code, psxRegs.pc, psxRegs.cycle);
74 psxMTC0();
75 gen_interupt(); /* FIXME: checking pending irqs should be enough */
76}
77
f95a77f7 78void check_interupt()
79{
7139f3c8 80 printf("ari64_check_interupt\n");
f95a77f7 81}
82
b9b61529 83void *gte_handlers[64];
84
85/* from gte.txt.. not sure if this is any good. */
86const char gte_cycletab[64] = {
87 /* 1 2 3 4 5 6 7 8 9 a b c d e f */
88 0, 15, 0, 0, 0, 0, 8, 0, 0, 0, 0, 0, 6, 0, 0, 0,
89 8, 8, 8, 19, 13, 0, 44, 0, 0, 0, 0, 17, 11, 0, 14, 0,
90 30, 0, 0, 0, 0, 0, 0, 0, 5, 8, 17, 0, 0, 5, 6, 0,
91 23, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 5, 5, 39,
92};
f95a77f7 93
94static int ari64_init()
95{
b9b61529 96 extern void (*psxCP2[64])();
97 extern void psxNULL();
7e605697 98 extern void *psxH_ptr;
f95a77f7 99 size_t i;
b9b61529 100
f95a77f7 101 new_dynarec_init();
7e605697 102 new_dyna_pcsx_mem_init();
7139f3c8 103
ae602c19 104 for (i = 0; i < ARRAY_SIZE(gte_handlers); i++)
b9b61529 105 if (psxCP2[i] != psxNULL)
106 gte_handlers[i] = psxCP2[i];
107
7e605697 108 psxH_ptr = psxH;
109
b9b61529 110 return 0;
f95a77f7 111}
112
113static void ari64_reset()
114{
f95a77f7 115 printf("ari64_reset\n");
7e605697 116 new_dyna_pcsx_mem_reset();
4b421010 117 invalidate_all_pages();
118 pending_exception = 1;
f95a77f7 119}
120
121static void ari64_execute()
122{
654e8cfb 123 schedule_timeslice();
124
125 evprintf("ari64_execute %08x, %u->%u (%d)\n", psxRegs.pc,
126 psxRegs.cycle, next_interupt, next_interupt - psxRegs.cycle);
7139f3c8 127
b9b61529 128 new_dyna_start();
654e8cfb 129
130 evprintf("ari64_execute end %08x, %u->%u (%d)\n", psxRegs.pc,
131 psxRegs.cycle, next_interupt, next_interupt - psxRegs.cycle);
f95a77f7 132}
133
4b421010 134static void ari64_clear(u32 addr, u32 size)
f95a77f7 135{
4b421010 136 u32 start, end;
137
138 evprintf("ari64_clear %08x %04x\n", addr, size);
139
140 /* check for RAM mirrors */
4cb76aa4 141 if ((addr & ~0xe0600000) < 0x200000) {
142 addr &= ~0xe0600000;
f76eeef9 143 addr |= 0x80000000;
4b421010 144 }
145
146 start = addr >> 12;
147 end = (addr + size) >> 12;
148
149 for (; start <= end; start++)
150 if (!invalid_code[start])
151 invalidate_block(start);
f95a77f7 152}
153
154static void ari64_shutdown()
155{
156 new_dynarec_cleanup();
157}
158
7139f3c8 159extern void intExecute();
160extern void intExecuteT();
161extern void intExecuteBlock();
162extern void intExecuteBlockT();
163#ifndef DRC_DBG
164#define intExecuteT intExecute
165#define intExecuteBlockT intExecuteBlock
166#endif
167
f95a77f7 168R3000Acpu psxRec = {
169 ari64_init,
170 ari64_reset,
7139f3c8 171#if 1
f95a77f7 172 ari64_execute,
7139f3c8 173 ari64_execute,
174#else
175 intExecuteT,
176 intExecuteBlockT,
177#endif
f95a77f7 178 ari64_clear,
179 ari64_shutdown
180};
7139f3c8 181
182// TODO: rm
183#ifndef DRC_DBG
184void do_insn_trace() {}
185void do_insn_cmp() {}
186#endif
187
188#if defined(__x86_64__) || defined(__i386__)
189unsigned int address, readmem_word, word;
190unsigned short hword;
191unsigned char byte;
ccf51908 192int pending_exception, stop;
7139f3c8 193unsigned int next_interupt;
7e605697 194void *psxH_ptr;
7139f3c8 195void new_dynarec_init() {}
3eb78778 196void new_dyna_start() {}
7139f3c8 197void new_dynarec_cleanup() {}
ccf51908 198void invalidate_all_pages() {}
199void invalidate_block(unsigned int block) {}
7e605697 200void new_dyna_pcsx_mem_init(void) {}
201void new_dyna_pcsx_mem_reset(void) {}
7139f3c8 202#endif
203
204#ifdef DRC_DBG
205
206#include <stddef.h>
207static FILE *f;
208extern u32 last_io_addr;
209
210static void dump_mem(const char *fname, void *mem, size_t size)
211{
212 FILE *f1 = fopen(fname, "wb");
3eb78778 213 if (f1 == NULL)
214 f1 = fopen(strrchr(fname, '/') + 1, "wb");
7139f3c8 215 fwrite(mem, 1, size, f1);
216 fclose(f1);
217}
218
219void do_insn_trace(void)
220{
221 static psxRegisters oldregs;
222 static u32 old_io_addr = (u32)-1;
223 static u32 old_io_data = 0xbad0c0de;
224 u32 *allregs_p = (void *)&psxRegs;
225 u32 *allregs_o = (void *)&oldregs;
226 u32 *io_data;
227 int i;
228 u8 byte;
229
230//last_io_addr = 0x5e2c8;
231 if (f == NULL)
232 f = fopen("tracelog", "wb");
233
234 oldregs.code = psxRegs.code; // don't care
235 for (i = 0; i < offsetof(psxRegisters, intCycle) / 4; i++) {
236 if (allregs_p[i] != allregs_o[i]) {
237 fwrite(&i, 1, 1, f);
238 fwrite(&allregs_p[i], 1, 4, f);
239 allregs_o[i] = allregs_p[i];
240 }
241 }
242 if (old_io_addr != last_io_addr) {
243 byte = 0xfd;
244 fwrite(&byte, 1, 1, f);
245 fwrite(&last_io_addr, 1, 4, f);
246 old_io_addr = last_io_addr;
247 }
248 io_data = (void *)(psxM + (last_io_addr&0x1ffffc));
249 if (old_io_data != *io_data) {
250 byte = 0xfe;
251 fwrite(&byte, 1, 1, f);
252 fwrite(io_data, 1, 4, f);
253 old_io_data = *io_data;
254 }
255 byte = 0xff;
256 fwrite(&byte, 1, 1, f);
257
258#if 0
259 if (psxRegs.cycle == 190230) {
260 dump_mem("/mnt/ntz/dev/pnd/tmp/psxram_i.dump", psxM, 0x200000);
261 dump_mem("/mnt/ntz/dev/pnd/tmp/psxregs_i.dump", psxH, 0x10000);
262 printf("dumped\n");
263 exit(1);
264 }
265#endif
266}
267
268static const char *regnames[offsetof(psxRegisters, intCycle) / 4] = {
269 "r0", "r1", "r2", "r3", "r4", "r5", "r6", "r7",
270 "r8", "r9", "r10", "r11", "r12", "r13", "r14", "r15",
271 "r16", "r17", "r18", "r19", "r20", "r21", "r22", "r23",
272 "r24", "r25", "r26", "r27", "r28", "r29", "r30", "r31",
273 "lo", "hi",
274 "C0_0", "C0_1", "C0_2", "C0_3", "C0_4", "C0_5", "C0_6", "C0_7",
275 "C0_8", "C0_9", "C0_10", "C0_11", "C0_12", "C0_13", "C0_14", "C0_15",
276 "C0_16", "C0_17", "C0_18", "C0_19", "C0_20", "C0_21", "C0_22", "C0_23",
277 "C0_24", "C0_25", "C0_26", "C0_27", "C0_28", "C0_29", "C0_30", "C0_31",
278
279 "C2D0", "C2D1", "C2D2", "C2D3", "C2D4", "C2D5", "C2D6", "C2D7",
280 "C2D8", "C2D9", "C2D10", "C2D11", "C2D12", "C2D13", "C2D14", "C2D15",
281 "C2D16", "C2D17", "C2D18", "C2D19", "C2D20", "C2D21", "C2D22", "C2D23",
282 "C2D24", "C2D25", "C2D26", "C2D27", "C2D28", "C2D29", "C2D30", "C2D31",
283
284 "C2C0", "C2C1", "C2C2", "C2C3", "C2C4", "C2C5", "C2C6", "C2C7",
285 "C2C8", "C2C9", "C2C10", "C2C11", "C2C12", "C2C13", "C2C14", "C2C15",
286 "C2C16", "C2C17", "C2C18", "C2C19", "C2C20", "C2C21", "C2C22", "C2C23",
287 "C2C24", "C2C25", "C2C26", "C2C27", "C2C28", "C2C29", "C2C30", "C2C31",
288
289 "PC", "code", "cycle", "interrupt",
290};
291
3eb78778 292static struct {
293 int reg;
294 u32 val, val_expect;
295 u32 pc, cycle;
296} miss_log[64];
297static int miss_log_i;
298#define miss_log_len (sizeof(miss_log)/sizeof(miss_log[0]))
299#define miss_log_mask (miss_log_len-1)
300
301static void miss_log_add(int reg, u32 val, u32 val_expect, u32 pc, u32 cycle)
302{
303 miss_log[miss_log_i].reg = reg;
304 miss_log[miss_log_i].val = val;
305 miss_log[miss_log_i].val_expect = val_expect;
306 miss_log[miss_log_i].pc = pc;
307 miss_log[miss_log_i].cycle = cycle;
308 miss_log_i = (miss_log_i + 1) & miss_log_mask;
309}
310
7139f3c8 311void breakme() {}
312
313void do_insn_cmp(void)
314{
315 static psxRegisters rregs;
316 static u32 mem_addr, mem_val;
317 u32 *allregs_p = (void *)&psxRegs;
318 u32 *allregs_e = (void *)&rregs;
319 static u32 ppc, failcount;
320 int i, ret, bad = 0;
321 u8 code;
322
323 if (f == NULL)
324 f = fopen("tracelog", "rb");
325
326 while (1) {
327 if ((ret = fread(&code, 1, 1, f)) <= 0)
328 break;
329 if (ret <= 0)
330 break;
331 if (code == 0xff)
332 break;
333 if (code == 0xfd) {
334 if ((ret = fread(&mem_addr, 1, 4, f)) <= 0)
335 break;
336 continue;
337 }
338 if (code == 0xfe) {
339 if ((ret = fread(&mem_val, 1, 4, f)) <= 0)
340 break;
341 continue;
342 }
343 if ((ret = fread(&allregs_e[code], 1, 4, f)) <= 0)
344 break;
345 }
346
347 if (ret <= 0) {
348 printf("EOF?\n");
349 goto end;
350 }
351
352 psxRegs.code = rregs.code; // don't care
353psxRegs.cycle = rregs.cycle;
354psxRegs.CP0.r[9] = rregs.CP0.r[9]; // Count
355
356//if (psxRegs.cycle == 166172) breakme();
357//if (psxRegs.cycle > 11296376) printf("pc=%08x %u %08x\n", psxRegs.pc, psxRegs.cycle, psxRegs.interrupt);
358
359 mem_addr &= 0x1ffffc;
360
361 if (memcmp(&psxRegs, &rregs, offsetof(psxRegisters, intCycle)) == 0 &&
362 mem_val == *(u32 *)(psxM + mem_addr)
363 ) {
364 failcount = 0;
365 goto ok;
366 }
367
368 for (i = 0; i < offsetof(psxRegisters, intCycle) / 4; i++) {
369 if (allregs_p[i] != allregs_e[i]) {
3eb78778 370 miss_log_add(i, allregs_p[i], allregs_e[i], psxRegs.pc, psxRegs.cycle);
7139f3c8 371 bad++;
372 }
373 }
374
375 if (mem_val != *(u32 *)(psxM + mem_addr)) {
376 printf("bad mem @%08x: %08x %08x\n", mem_addr, *(u32 *)(psxM + mem_addr), mem_val);
377 goto end;
378 }
379
380 if (psxRegs.pc == rregs.pc && bad < 6 && failcount < 32) {
3eb78778 381 static int last_mcycle;
382 if (last_mcycle != psxRegs.cycle >> 20) {
383 printf("%u\n", psxRegs.cycle);
384 last_mcycle = psxRegs.cycle >> 20;
385 }
7139f3c8 386 failcount++;
387 goto ok;
388 }
389
390end:
3eb78778 391 for (i = 0; i < miss_log_len; i++, miss_log_i = (miss_log_i + 1) & miss_log_mask)
392 printf("bad %5s: %08x %08x, pc=%08x, cycle %u\n",
393 regnames[miss_log[miss_log_i].reg], miss_log[miss_log_i].val,
394 miss_log[miss_log_i].val_expect, miss_log[miss_log_i].pc, miss_log[miss_log_i].cycle);
395 printf("-- %d\n", bad);
396 for (i = 0; i < 8; i++)
397 printf("r%d=%08x r%2d=%08x r%2d=%08x r%2d=%08x\n", i, allregs_p[i],
87c06e51 398 i+8, allregs_p[i+8], i+16, allregs_p[i+16], i+24, allregs_p[i+24]);
7139f3c8 399 printf("PC: %08x/%08x, cycle %u\n", psxRegs.pc, ppc, psxRegs.cycle);
400 dump_mem("/mnt/ntz/dev/pnd/tmp/psxram.dump", psxM, 0x200000);
401 dump_mem("/mnt/ntz/dev/pnd/tmp/psxregs.dump", psxH, 0x10000);
402 exit(1);
403ok:
404 psxRegs.cycle = rregs.cycle + 2; // sync timing
405 ppc = psxRegs.pc;
406}
407
408#endif