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