core: update to newer interrupt code, seems to affect timings too
[pcsx_rearmed.git] / libpcsxcore / new_dynarec / emu_if.c
... / ...
CommitLineData
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
8// pending_exception?
9// swi 0 in do_unalignedwritestub?
10#include <stdio.h>
11
12#include "emu_if.h"
13#include "pcsxmem.h"
14#include "../psxhle.h"
15#include "../r3000a.h"
16
17#define ARRAY_SIZE(x) (sizeof(x) / sizeof(x[0]))
18
19//#define evprintf printf
20#define evprintf(...)
21
22char invalid_code[0x100000];
23u32 event_cycles[PSXINT_COUNT];
24
25static void schedule_timeslice(void)
26{
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}
51
52void gen_interupt()
53{
54 evprintf(" +ge %08x, %u->%u\n", psxRegs.pc, psxRegs.cycle, next_interupt);
55#ifdef DRC_DBG
56 psxRegs.cycle += 2;
57#endif
58
59 psxBranchTest();
60
61 schedule_timeslice();
62
63 evprintf(" -ge %08x, %u->%u (%d)\n", psxRegs.pc, psxRegs.cycle,
64 next_interupt, next_interupt - psxRegs.cycle);
65
66 pending_exception = 1; /* FIXME */
67}
68
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
78void check_interupt()
79{
80 printf("ari64_check_interupt\n");
81}
82
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};
93
94static int ari64_init()
95{
96 extern void (*psxCP2[64])();
97 extern void psxNULL();
98 extern void *psxH_ptr;
99 size_t i;
100
101 new_dynarec_init();
102 new_dyna_pcsx_mem_init();
103
104 for (i = 0; i < ARRAY_SIZE(gte_handlers); i++)
105 if (psxCP2[i] != psxNULL)
106 gte_handlers[i] = psxCP2[i];
107
108 psxH_ptr = psxH;
109
110 return 0;
111}
112
113static void ari64_reset()
114{
115 printf("ari64_reset\n");
116 new_dyna_pcsx_mem_reset();
117 invalidate_all_pages();
118 pending_exception = 1;
119}
120
121static void ari64_execute()
122{
123 schedule_timeslice();
124
125 evprintf("ari64_execute %08x, %u->%u (%d)\n", psxRegs.pc,
126 psxRegs.cycle, next_interupt, next_interupt - psxRegs.cycle);
127
128 new_dyna_start();
129
130 evprintf("ari64_execute end %08x, %u->%u (%d)\n", psxRegs.pc,
131 psxRegs.cycle, next_interupt, next_interupt - psxRegs.cycle);
132}
133
134static void ari64_clear(u32 addr, u32 size)
135{
136 u32 start, end;
137
138 evprintf("ari64_clear %08x %04x\n", addr, size);
139
140 /* check for RAM mirrors */
141 if ((addr & ~0xe0600000) < 0x200000) {
142 addr &= ~0xe0600000;
143 addr |= 0x80000000;
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);
152}
153
154static void ari64_shutdown()
155{
156 new_dynarec_cleanup();
157}
158
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
168R3000Acpu psxRec = {
169 ari64_init,
170 ari64_reset,
171#if 1
172 ari64_execute,
173 ari64_execute,
174#else
175 intExecuteT,
176 intExecuteBlockT,
177#endif
178 ari64_clear,
179 ari64_shutdown
180};
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;
192int pending_exception, stop;
193unsigned int next_interupt;
194void *psxH_ptr;
195void new_dynarec_init() {}
196void new_dyna_start() {}
197void new_dynarec_cleanup() {}
198void invalidate_all_pages() {}
199void invalidate_block(unsigned int block) {}
200void new_dyna_pcsx_mem_init(void) {}
201void new_dyna_pcsx_mem_reset(void) {}
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");
213 if (f1 == NULL)
214 f1 = fopen(strrchr(fname, '/') + 1, "wb");
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
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
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]) {
370 miss_log_add(i, allregs_p[i], allregs_e[i], psxRegs.pc, psxRegs.cycle);
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) {
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 }
386 failcount++;
387 goto ok;
388 }
389
390end:
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],
398 i+8, allregs_p[i+8], i+16, allregs_p[i+16], i+24, allregs_p[i+24]);
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