new ability to adjust psx cpu clock
[pcsx_rearmed.git] / libpcsxcore / new_dynarec / emu_if.c
CommitLineData
7e605697 1/*
009faf24 2 * (C) GraÅžvydas "notaz" Ignotas, 2010-2011
7e605697 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"
59774ed0 17#include "../gte_arm.h"
009faf24 18#include "../gte_neon.h"
59774ed0 19#define FLAGLESS
20#include "../gte.h"
7139f3c8 21
ae602c19 22#define ARRAY_SIZE(x) (sizeof(x) / sizeof(x[0]))
23
7139f3c8 24//#define evprintf printf
25#define evprintf(...)
26
f95a77f7 27char invalid_code[0x100000];
d28b54b1 28u32 event_cycles[PSXINT_COUNT];
f95a77f7 29
654e8cfb 30static void schedule_timeslice(void)
f95a77f7 31{
654e8cfb 32 u32 i, c = psxRegs.cycle;
33 s32 min, dif;
34
35 min = psxNextsCounter + psxNextCounter - c;
36 for (i = 0; i < ARRAY_SIZE(event_cycles); i++) {
37 dif = event_cycles[i] - c;
38 //evprintf(" ev %d\n", dif);
39 if (0 < dif && dif < min)
40 min = dif;
41 }
42 next_interupt = c + min;
43
44#if 0
45 static u32 cnt, last_cycle;
46 static u64 sum;
47 if (last_cycle) {
48 cnt++;
49 sum += psxRegs.cycle - last_cycle;
50 if ((cnt & 0xff) == 0)
51 printf("%u\n", (u32)(sum / cnt));
52 }
53 last_cycle = psxRegs.cycle;
54#endif
55}
ae602c19 56
52082bc1 57typedef void (irq_func)();
58
59static irq_func * const irq_funcs[] = {
60 [PSXINT_SIO] = sioInterrupt,
61 [PSXINT_CDR] = cdrInterrupt,
62 [PSXINT_CDREAD] = cdrReadInterrupt,
63 [PSXINT_GPUDMA] = gpuInterrupt,
64 [PSXINT_MDECOUTDMA] = mdec1Interrupt,
65 [PSXINT_SPUDMA] = spuInterrupt,
528ad661 66 [PSXINT_MDECINDMA] = mdec0Interrupt,
57a757ce 67 [PSXINT_GPUOTCDMA] = gpuotcInterrupt,
9f8b032d 68 [PSXINT_CDRDMA] = cdrDmaInterrupt,
69 [PSXINT_CDRLID] = cdrLidSeekInterrupt,
7f457614 70 [PSXINT_CDRPLAY] = cdrPlayInterrupt,
52082bc1 71};
72
73/* local dupe of psxBranchTest, using event_cycles */
74static void irq_test(void)
75{
76 u32 irqs = psxRegs.interrupt;
77 u32 cycle = psxRegs.cycle;
78 u32 irq, irq_bits;
79
80 if ((psxRegs.cycle - psxNextsCounter) >= psxNextCounter)
81 psxRcntUpdate();
82
83 // irq_funcs() may queue more irqs
84 psxRegs.interrupt = 0;
85
86 for (irq = 0, irq_bits = irqs; irq_bits != 0; irq++, irq_bits >>= 1) {
87 if (!(irq_bits & 1))
88 continue;
89 if ((s32)(cycle - event_cycles[irq]) >= 0) {
90 irqs &= ~(1 << irq);
91 irq_funcs[irq]();
92 }
93 }
94 psxRegs.interrupt |= irqs;
95
96 if ((psxHu32(0x1070) & psxHu32(0x1074)) && (Status & 0x401) == 0x401) {
97 psxException(0x400, 0);
98 pending_exception = 1;
99 }
100}
101
654e8cfb 102void gen_interupt()
103{
654e8cfb 104 evprintf(" +ge %08x, %u->%u\n", psxRegs.pc, psxRegs.cycle, next_interupt);
7139f3c8 105
52082bc1 106 irq_test();
107 //psxBranchTest();
108 //pending_exception = 1;
7139f3c8 109
654e8cfb 110 schedule_timeslice();
ae602c19 111
654e8cfb 112 evprintf(" -ge %08x, %u->%u (%d)\n", psxRegs.pc, psxRegs.cycle,
113 next_interupt, next_interupt - psxRegs.cycle);
f95a77f7 114}
115
fca1aef2 116// from interpreter
117extern void MTC0(int reg, u32 val);
118
63cb0298 119void pcsx_mtc0(u32 reg, u32 val)
28bc5688 120{
63cb0298 121 evprintf("MTC0 %d #%x @%08x %u\n", reg, val, psxRegs.pc, psxRegs.cycle);
122 MTC0(reg, val);
fca1aef2 123 gen_interupt();
124}
28bc5688 125
63cb0298 126void pcsx_mtc0_ds(u32 reg, u32 val)
fca1aef2 127{
63cb0298 128 evprintf("MTC0 %d #%x @%08x %u\n", reg, val, psxRegs.pc, psxRegs.cycle);
129 MTC0(reg, val);
28bc5688 130}
131
52082bc1 132void new_dyna_save(void)
133{
134 // psxRegs.intCycle is always maintained, no need to convert
135}
136
137void new_dyna_restore(void)
138{
139 int i;
9f8b032d 140 for (i = 0; i < PSXINT_COUNT; i++)
52082bc1 141 event_cycles[i] = psxRegs.intCycle[i].sCycle + psxRegs.intCycle[i].cycle;
142}
143
b9b61529 144void *gte_handlers[64];
145
59774ed0 146void *gte_handlers_nf[64] = {
147 NULL , gteRTPS_nf , NULL , NULL , NULL , NULL , gteNCLIP_nf, NULL , // 00
148 NULL , NULL , NULL , NULL , gteOP_nf , NULL , NULL , NULL , // 08
149 gteDPCS_nf, gteINTPL_nf, gteMVMVA_nf, gteNCDS_nf, gteCDP_nf, NULL , gteNCDT_nf , NULL , // 10
150 NULL , NULL , NULL , gteNCCS_nf, gteCC_nf , NULL , gteNCS_nf , NULL , // 18
151 gteNCT_nf , NULL , NULL , NULL , NULL , NULL , NULL , NULL , // 20
152 gteSQR_nf , gteDCPL_nf , gteDPCT_nf , NULL , NULL , gteAVSZ3_nf, gteAVSZ4_nf, NULL , // 28
153 gteRTPT_nf, NULL , NULL , NULL , NULL , NULL , NULL , NULL , // 30
154 NULL , NULL , NULL , NULL , NULL , gteGPF_nf , gteGPL_nf , gteNCCT_nf, // 38
155};
156
bedfea38 157const char *gte_regnames[64] = {
158 NULL , "RTPS" , NULL , NULL , NULL , NULL , "NCLIP", NULL , // 00
159 NULL , NULL , NULL , NULL , "OP" , NULL , NULL , NULL , // 08
160 "DPCS", "INTPL", "MVMVA", "NCDS", "CDP", NULL , "NCDT" , NULL , // 10
161 NULL , NULL , NULL , "NCCS", "CC" , NULL , "NCS" , NULL , // 18
162 "NCT" , NULL , NULL , NULL , NULL , NULL , NULL , NULL , // 20
163 "SQR" , "DCPL" , "DPCT" , NULL , NULL , "AVSZ3", "AVSZ4", NULL , // 28
164 "RTPT", NULL , NULL , NULL , NULL , NULL , NULL , NULL , // 30
165 NULL , NULL , NULL , NULL , NULL , "GPF" , "GPL" , "NCCT", // 38
166};
167
b9b61529 168/* from gte.txt.. not sure if this is any good. */
169const char gte_cycletab[64] = {
170 /* 1 2 3 4 5 6 7 8 9 a b c d e f */
171 0, 15, 0, 0, 0, 0, 8, 0, 0, 0, 0, 0, 6, 0, 0, 0,
172 8, 8, 8, 19, 13, 0, 44, 0, 0, 0, 0, 17, 11, 0, 14, 0,
173 30, 0, 0, 0, 0, 0, 0, 0, 5, 8, 17, 0, 0, 5, 6, 0,
174 23, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 5, 5, 39,
175};
f95a77f7 176
177static int ari64_init()
178{
b9b61529 179 extern void (*psxCP2[64])();
180 extern void psxNULL();
f95a77f7 181 size_t i;
b9b61529 182
f95a77f7 183 new_dynarec_init();
7e605697 184 new_dyna_pcsx_mem_init();
7139f3c8 185
ae602c19 186 for (i = 0; i < ARRAY_SIZE(gte_handlers); i++)
b9b61529 187 if (psxCP2[i] != psxNULL)
188 gte_handlers[i] = psxCP2[i];
59774ed0 189
190#if !defined(DRC_DBG) && !defined(PCNT)
191#ifdef __arm__
192 gte_handlers[0x06] = gteNCLIP_arm;
0c2ca3ba 193 gte_handlers_nf[0x01] = gteRTPS_nf_arm;
194 gte_handlers_nf[0x30] = gteRTPT_nf_arm;
59774ed0 195#endif
a80ae4a0 196#ifdef __ARM_NEON__
59774ed0 197 // compiler's _nf version is still a lot slower then neon
0c2ca3ba 198 // _nf_arm RTPS is roughly the same, RTPT slower
59774ed0 199 gte_handlers[0x01] = gte_handlers_nf[0x01] = gteRTPS_neon;
200 gte_handlers[0x30] = gte_handlers_nf[0x30] = gteRTPT_neon;
201 gte_handlers[0x12] = gte_handlers_nf[0x12] = gteMVMVA_neon;
a80ae4a0 202#endif
d3f3bf09 203#endif
204#ifdef DRC_DBG
205 memcpy(gte_handlers_nf, gte_handlers, sizeof(gte_handlers_nf));
009faf24 206#endif
7e605697 207 psxH_ptr = psxH;
208
b9b61529 209 return 0;
f95a77f7 210}
211
212static void ari64_reset()
213{
f95a77f7 214 printf("ari64_reset\n");
7e605697 215 new_dyna_pcsx_mem_reset();
4b421010 216 invalidate_all_pages();
7f457614 217 new_dyna_restore();
4b421010 218 pending_exception = 1;
f95a77f7 219}
220
e4eb18c1 221// execute until predefined leave points
222// (HLE softcall exit and BIOS fastboot end)
223static void ari64_execute_until()
f95a77f7 224{
654e8cfb 225 schedule_timeslice();
226
227 evprintf("ari64_execute %08x, %u->%u (%d)\n", psxRegs.pc,
228 psxRegs.cycle, next_interupt, next_interupt - psxRegs.cycle);
7139f3c8 229
b9b61529 230 new_dyna_start();
654e8cfb 231
232 evprintf("ari64_execute end %08x, %u->%u (%d)\n", psxRegs.pc,
233 psxRegs.cycle, next_interupt, next_interupt - psxRegs.cycle);
f95a77f7 234}
235
e4eb18c1 236static void ari64_execute()
237{
238 while (!stop) {
239 ari64_execute_until();
240 evprintf("drc left @%08x\n", psxRegs.pc);
241 }
242}
243
4b421010 244static void ari64_clear(u32 addr, u32 size)
f95a77f7 245{
0ce47d46 246 u32 start, end, main_ram;
4b421010 247
76739a08 248 size *= 4; /* PCSX uses DMA units */
249
4b421010 250 evprintf("ari64_clear %08x %04x\n", addr, size);
251
252 /* check for RAM mirrors */
0ce47d46 253 main_ram = (addr & 0xffe00000) == 0x80000000;
4b421010 254
255 start = addr >> 12;
256 end = (addr + size) >> 12;
257
258 for (; start <= end; start++)
0ce47d46 259 if (!main_ram || !invalid_code[start])
4b421010 260 invalidate_block(start);
f95a77f7 261}
262
263static void ari64_shutdown()
264{
265 new_dynarec_cleanup();
266}
267
7139f3c8 268extern void intExecute();
269extern void intExecuteT();
270extern void intExecuteBlock();
271extern void intExecuteBlockT();
272#ifndef DRC_DBG
273#define intExecuteT intExecute
274#define intExecuteBlockT intExecuteBlock
275#endif
276
f95a77f7 277R3000Acpu psxRec = {
278 ari64_init,
279 ari64_reset,
2185e39b 280#if defined(__arm__)
f95a77f7 281 ari64_execute,
e4eb18c1 282 ari64_execute_until,
7139f3c8 283#else
284 intExecuteT,
285 intExecuteBlockT,
286#endif
f95a77f7 287 ari64_clear,
288 ari64_shutdown
289};
7139f3c8 290
291// TODO: rm
292#ifndef DRC_DBG
293void do_insn_trace() {}
294void do_insn_cmp() {}
295#endif
296
297#if defined(__x86_64__) || defined(__i386__)
298unsigned int address, readmem_word, word;
299unsigned short hword;
300unsigned char byte;
ccf51908 301int pending_exception, stop;
7139f3c8 302unsigned int next_interupt;
2f546f9a 303int new_dynarec_did_compile;
2573466a 304int cycle_multiplier;
7e605697 305void *psxH_ptr;
7139f3c8 306void new_dynarec_init() {}
3eb78778 307void new_dyna_start() {}
7139f3c8 308void new_dynarec_cleanup() {}
2c886904 309void new_dynarec_clear_full() {}
ccf51908 310void invalidate_all_pages() {}
311void invalidate_block(unsigned int block) {}
7e605697 312void new_dyna_pcsx_mem_init(void) {}
313void new_dyna_pcsx_mem_reset(void) {}
7139f3c8 314#endif
315
316#ifdef DRC_DBG
317
318#include <stddef.h>
319static FILE *f;
320extern u32 last_io_addr;
321
322static void dump_mem(const char *fname, void *mem, size_t size)
323{
324 FILE *f1 = fopen(fname, "wb");
3eb78778 325 if (f1 == NULL)
326 f1 = fopen(strrchr(fname, '/') + 1, "wb");
7139f3c8 327 fwrite(mem, 1, size, f1);
328 fclose(f1);
329}
330
2185e39b 331static u32 memcheck_read(u32 a)
332{
333 if ((a >> 16) == 0x1f80)
334 // scratchpad/IO
335 return *(u32 *)(psxH + (a & 0xfffc));
336
337 if ((a >> 16) == 0x1f00)
338 // parallel
339 return *(u32 *)(psxP + (a & 0xfffc));
340
341// if ((a & ~0xe0600000) < 0x200000)
342 // RAM
343 return *(u32 *)(psxM + (a & 0x1ffffc));
344}
345
7139f3c8 346void do_insn_trace(void)
347{
348 static psxRegisters oldregs;
349 static u32 old_io_addr = (u32)-1;
350 static u32 old_io_data = 0xbad0c0de;
351 u32 *allregs_p = (void *)&psxRegs;
352 u32 *allregs_o = (void *)&oldregs;
2185e39b 353 u32 io_data;
7139f3c8 354 int i;
355 u8 byte;
356
357//last_io_addr = 0x5e2c8;
358 if (f == NULL)
359 f = fopen("tracelog", "wb");
360
361 oldregs.code = psxRegs.code; // don't care
362 for (i = 0; i < offsetof(psxRegisters, intCycle) / 4; i++) {
363 if (allregs_p[i] != allregs_o[i]) {
364 fwrite(&i, 1, 1, f);
365 fwrite(&allregs_p[i], 1, 4, f);
366 allregs_o[i] = allregs_p[i];
367 }
368 }
369 if (old_io_addr != last_io_addr) {
370 byte = 0xfd;
371 fwrite(&byte, 1, 1, f);
372 fwrite(&last_io_addr, 1, 4, f);
373 old_io_addr = last_io_addr;
374 }
2185e39b 375 io_data = memcheck_read(last_io_addr);
376 if (old_io_data != io_data) {
7139f3c8 377 byte = 0xfe;
378 fwrite(&byte, 1, 1, f);
2185e39b 379 fwrite(&io_data, 1, 4, f);
380 old_io_data = io_data;
7139f3c8 381 }
382 byte = 0xff;
383 fwrite(&byte, 1, 1, f);
384
385#if 0
386 if (psxRegs.cycle == 190230) {
387 dump_mem("/mnt/ntz/dev/pnd/tmp/psxram_i.dump", psxM, 0x200000);
388 dump_mem("/mnt/ntz/dev/pnd/tmp/psxregs_i.dump", psxH, 0x10000);
389 printf("dumped\n");
390 exit(1);
391 }
392#endif
393}
394
395static const char *regnames[offsetof(psxRegisters, intCycle) / 4] = {
396 "r0", "r1", "r2", "r3", "r4", "r5", "r6", "r7",
397 "r8", "r9", "r10", "r11", "r12", "r13", "r14", "r15",
398 "r16", "r17", "r18", "r19", "r20", "r21", "r22", "r23",
399 "r24", "r25", "r26", "r27", "r28", "r29", "r30", "r31",
400 "lo", "hi",
401 "C0_0", "C0_1", "C0_2", "C0_3", "C0_4", "C0_5", "C0_6", "C0_7",
402 "C0_8", "C0_9", "C0_10", "C0_11", "C0_12", "C0_13", "C0_14", "C0_15",
403 "C0_16", "C0_17", "C0_18", "C0_19", "C0_20", "C0_21", "C0_22", "C0_23",
404 "C0_24", "C0_25", "C0_26", "C0_27", "C0_28", "C0_29", "C0_30", "C0_31",
405
406 "C2D0", "C2D1", "C2D2", "C2D3", "C2D4", "C2D5", "C2D6", "C2D7",
407 "C2D8", "C2D9", "C2D10", "C2D11", "C2D12", "C2D13", "C2D14", "C2D15",
408 "C2D16", "C2D17", "C2D18", "C2D19", "C2D20", "C2D21", "C2D22", "C2D23",
409 "C2D24", "C2D25", "C2D26", "C2D27", "C2D28", "C2D29", "C2D30", "C2D31",
410
411 "C2C0", "C2C1", "C2C2", "C2C3", "C2C4", "C2C5", "C2C6", "C2C7",
412 "C2C8", "C2C9", "C2C10", "C2C11", "C2C12", "C2C13", "C2C14", "C2C15",
413 "C2C16", "C2C17", "C2C18", "C2C19", "C2C20", "C2C21", "C2C22", "C2C23",
414 "C2C24", "C2C25", "C2C26", "C2C27", "C2C28", "C2C29", "C2C30", "C2C31",
415
416 "PC", "code", "cycle", "interrupt",
417};
418
3eb78778 419static struct {
420 int reg;
421 u32 val, val_expect;
422 u32 pc, cycle;
423} miss_log[64];
424static int miss_log_i;
425#define miss_log_len (sizeof(miss_log)/sizeof(miss_log[0]))
426#define miss_log_mask (miss_log_len-1)
427
428static void miss_log_add(int reg, u32 val, u32 val_expect, u32 pc, u32 cycle)
429{
430 miss_log[miss_log_i].reg = reg;
431 miss_log[miss_log_i].val = val;
432 miss_log[miss_log_i].val_expect = val_expect;
433 miss_log[miss_log_i].pc = pc;
434 miss_log[miss_log_i].cycle = cycle;
435 miss_log_i = (miss_log_i + 1) & miss_log_mask;
436}
437
7139f3c8 438void breakme() {}
439
440void do_insn_cmp(void)
441{
442 static psxRegisters rregs;
443 static u32 mem_addr, mem_val;
444 u32 *allregs_p = (void *)&psxRegs;
445 u32 *allregs_e = (void *)&rregs;
446 static u32 ppc, failcount;
447 int i, ret, bad = 0;
448 u8 code;
449
450 if (f == NULL)
451 f = fopen("tracelog", "rb");
452
453 while (1) {
454 if ((ret = fread(&code, 1, 1, f)) <= 0)
455 break;
456 if (ret <= 0)
457 break;
458 if (code == 0xff)
459 break;
460 if (code == 0xfd) {
461 if ((ret = fread(&mem_addr, 1, 4, f)) <= 0)
462 break;
463 continue;
464 }
465 if (code == 0xfe) {
466 if ((ret = fread(&mem_val, 1, 4, f)) <= 0)
467 break;
468 continue;
469 }
470 if ((ret = fread(&allregs_e[code], 1, 4, f)) <= 0)
471 break;
472 }
473
474 if (ret <= 0) {
475 printf("EOF?\n");
476 goto end;
477 }
478
479 psxRegs.code = rregs.code; // don't care
2185e39b 480 psxRegs.cycle = rregs.cycle;
481 psxRegs.CP0.r[9] = rregs.CP0.r[9]; // Count
7139f3c8 482
483//if (psxRegs.cycle == 166172) breakme();
7139f3c8 484
485 if (memcmp(&psxRegs, &rregs, offsetof(psxRegisters, intCycle)) == 0 &&
2185e39b 486 mem_val == memcheck_read(mem_addr)
7139f3c8 487 ) {
488 failcount = 0;
489 goto ok;
490 }
491
492 for (i = 0; i < offsetof(psxRegisters, intCycle) / 4; i++) {
493 if (allregs_p[i] != allregs_e[i]) {
3eb78778 494 miss_log_add(i, allregs_p[i], allregs_e[i], psxRegs.pc, psxRegs.cycle);
7139f3c8 495 bad++;
496 }
497 }
498
2185e39b 499 if (mem_val != memcheck_read(mem_addr)) {
500 printf("bad mem @%08x: %08x %08x\n", mem_addr, memcheck_read(mem_addr), mem_val);
7139f3c8 501 goto end;
502 }
503
504 if (psxRegs.pc == rregs.pc && bad < 6 && failcount < 32) {
3eb78778 505 static int last_mcycle;
506 if (last_mcycle != psxRegs.cycle >> 20) {
507 printf("%u\n", psxRegs.cycle);
508 last_mcycle = psxRegs.cycle >> 20;
509 }
7139f3c8 510 failcount++;
511 goto ok;
512 }
513
514end:
3eb78778 515 for (i = 0; i < miss_log_len; i++, miss_log_i = (miss_log_i + 1) & miss_log_mask)
516 printf("bad %5s: %08x %08x, pc=%08x, cycle %u\n",
517 regnames[miss_log[miss_log_i].reg], miss_log[miss_log_i].val,
518 miss_log[miss_log_i].val_expect, miss_log[miss_log_i].pc, miss_log[miss_log_i].cycle);
519 printf("-- %d\n", bad);
520 for (i = 0; i < 8; i++)
521 printf("r%d=%08x r%2d=%08x r%2d=%08x r%2d=%08x\n", i, allregs_p[i],
87c06e51 522 i+8, allregs_p[i+8], i+16, allregs_p[i+16], i+24, allregs_p[i+24]);
7139f3c8 523 printf("PC: %08x/%08x, cycle %u\n", psxRegs.pc, ppc, psxRegs.cycle);
524 dump_mem("/mnt/ntz/dev/pnd/tmp/psxram.dump", psxM, 0x200000);
525 dump_mem("/mnt/ntz/dev/pnd/tmp/psxregs.dump", psxH, 0x10000);
526 exit(1);
527ok:
528 psxRegs.cycle = rregs.cycle + 2; // sync timing
529 ppc = psxRegs.pc;
530}
531
532#endif