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