2 * (C) GraÅžvydas "notaz" Ignotas, 2010-2011
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.
12 #include "../psxhle.h"
13 #include "../r3000a.h"
15 #include "../psxdma.h"
17 #include "../gte_arm.h"
18 #include "../gte_neon.h"
22 #define ARRAY_SIZE(x) (sizeof(x) / sizeof(x[0]))
24 //#define evprintf printf
27 char invalid_code[0x100000];
28 u32 event_cycles[PSXINT_COUNT];
30 static void schedule_timeslice(void)
32 u32 i, c = psxRegs.cycle;
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)
42 next_interupt = c + min;
45 static u32 cnt, last_cycle;
49 sum += psxRegs.cycle - last_cycle;
50 if ((cnt & 0xff) == 0)
51 printf("%u\n", (u32)(sum / cnt));
53 last_cycle = psxRegs.cycle;
57 typedef void (irq_func)();
59 static 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,
66 [PSXINT_MDECINDMA] = mdec0Interrupt,
67 [PSXINT_GPUOTCDMA] = gpuotcInterrupt,
68 [PSXINT_CDRDMA] = cdrDmaInterrupt,
69 [PSXINT_CDRLID] = cdrLidSeekInterrupt,
70 [PSXINT_CDRPLAY] = cdrPlayInterrupt,
73 /* local dupe of psxBranchTest, using event_cycles */
74 static void irq_test(void)
76 u32 irqs = psxRegs.interrupt;
77 u32 cycle = psxRegs.cycle;
80 if ((psxRegs.cycle - psxNextsCounter) >= psxNextCounter)
83 // irq_funcs() may queue more irqs
84 psxRegs.interrupt = 0;
86 for (irq = 0, irq_bits = irqs; irq_bits != 0; irq++, irq_bits >>= 1) {
89 if ((s32)(cycle - event_cycles[irq]) >= 0) {
94 psxRegs.interrupt |= irqs;
96 if ((psxHu32(0x1070) & psxHu32(0x1074)) && (Status & 0x401) == 0x401) {
97 psxException(0x400, 0);
98 pending_exception = 1;
104 evprintf(" +ge %08x, %u->%u\n", psxRegs.pc, psxRegs.cycle, next_interupt);
108 //pending_exception = 1;
110 schedule_timeslice();
112 evprintf(" -ge %08x, %u->%u (%d)\n", psxRegs.pc, psxRegs.cycle,
113 next_interupt, next_interupt - psxRegs.cycle);
117 extern void MTC0(int reg, u32 val);
119 void pcsx_mtc0(u32 reg)
121 evprintf("MTC0 %d #%x @%08x %u\n", reg, readmem_word, psxRegs.pc, psxRegs.cycle);
122 MTC0(reg, readmem_word);
126 void pcsx_mtc0_ds(u32 reg)
128 evprintf("MTC0 %d #%x @%08x %u\n", reg, readmem_word, psxRegs.pc, psxRegs.cycle);
129 MTC0(reg, readmem_word);
132 void new_dyna_save(void)
134 // psxRegs.intCycle is always maintained, no need to convert
137 void new_dyna_restore(void)
140 for (i = 0; i < PSXINT_COUNT; i++)
141 event_cycles[i] = psxRegs.intCycle[i].sCycle + psxRegs.intCycle[i].cycle;
144 void *gte_handlers[64];
146 void *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
157 const 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
168 /* from gte.txt.. not sure if this is any good. */
169 const 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,
177 static int ari64_init()
179 extern void (*psxCP2[64])();
180 extern void psxNULL();
184 new_dyna_pcsx_mem_init();
186 for (i = 0; i < ARRAY_SIZE(gte_handlers); i++)
187 if (psxCP2[i] != psxNULL)
188 gte_handlers[i] = psxCP2[i];
190 #if !defined(DRC_DBG) && !defined(PCNT)
192 gte_handlers[0x06] = gteNCLIP_arm;
195 // compiler's _nf version is still a lot slower then neon
196 gte_handlers[0x01] = gte_handlers_nf[0x01] = gteRTPS_neon;
197 gte_handlers[0x30] = gte_handlers_nf[0x30] = gteRTPT_neon;
198 gte_handlers[0x12] = gte_handlers_nf[0x12] = gteMVMVA_neon;
206 static void ari64_reset()
208 printf("ari64_reset\n");
209 new_dyna_pcsx_mem_reset();
210 invalidate_all_pages();
212 pending_exception = 1;
215 // execute until predefined leave points
216 // (HLE softcall exit and BIOS fastboot end)
217 static void ari64_execute_until()
219 schedule_timeslice();
221 evprintf("ari64_execute %08x, %u->%u (%d)\n", psxRegs.pc,
222 psxRegs.cycle, next_interupt, next_interupt - psxRegs.cycle);
226 evprintf("ari64_execute end %08x, %u->%u (%d)\n", psxRegs.pc,
227 psxRegs.cycle, next_interupt, next_interupt - psxRegs.cycle);
230 static void ari64_execute()
233 ari64_execute_until();
234 evprintf("drc left @%08x\n", psxRegs.pc);
238 static void ari64_clear(u32 addr, u32 size)
240 u32 start, end, main_ram;
242 size *= 4; /* PCSX uses DMA units */
244 evprintf("ari64_clear %08x %04x\n", addr, size);
246 /* check for RAM mirrors */
247 main_ram = (addr & 0xffe00000) == 0x80000000;
250 end = (addr + size) >> 12;
252 for (; start <= end; start++)
253 if (!main_ram || !invalid_code[start])
254 invalidate_block(start);
257 static void ari64_shutdown()
259 new_dynarec_cleanup();
262 extern void intExecute();
263 extern void intExecuteT();
264 extern void intExecuteBlock();
265 extern void intExecuteBlockT();
267 #define intExecuteT intExecute
268 #define intExecuteBlockT intExecuteBlock
287 void do_insn_trace() {}
288 void do_insn_cmp() {}
291 #if defined(__x86_64__) || defined(__i386__)
292 unsigned int address, readmem_word, word;
293 unsigned short hword;
295 int pending_exception, stop;
296 unsigned int next_interupt;
298 void new_dynarec_init() {}
299 void new_dyna_start() {}
300 void new_dynarec_cleanup() {}
301 void new_dynarec_clear_full() {}
302 void invalidate_all_pages() {}
303 void invalidate_block(unsigned int block) {}
304 void new_dyna_pcsx_mem_init(void) {}
305 void new_dyna_pcsx_mem_reset(void) {}
312 extern u32 last_io_addr;
314 static void dump_mem(const char *fname, void *mem, size_t size)
316 FILE *f1 = fopen(fname, "wb");
318 f1 = fopen(strrchr(fname, '/') + 1, "wb");
319 fwrite(mem, 1, size, f1);
323 static u32 memcheck_read(u32 a)
325 if ((a >> 16) == 0x1f80)
327 return *(u32 *)(psxH + (a & 0xfffc));
329 if ((a >> 16) == 0x1f00)
331 return *(u32 *)(psxP + (a & 0xfffc));
333 // if ((a & ~0xe0600000) < 0x200000)
335 return *(u32 *)(psxM + (a & 0x1ffffc));
338 void do_insn_trace(void)
340 static psxRegisters oldregs;
341 static u32 old_io_addr = (u32)-1;
342 static u32 old_io_data = 0xbad0c0de;
343 u32 *allregs_p = (void *)&psxRegs;
344 u32 *allregs_o = (void *)&oldregs;
349 //last_io_addr = 0x5e2c8;
351 f = fopen("tracelog", "wb");
353 oldregs.code = psxRegs.code; // don't care
354 for (i = 0; i < offsetof(psxRegisters, intCycle) / 4; i++) {
355 if (allregs_p[i] != allregs_o[i]) {
357 fwrite(&allregs_p[i], 1, 4, f);
358 allregs_o[i] = allregs_p[i];
361 if (old_io_addr != last_io_addr) {
363 fwrite(&byte, 1, 1, f);
364 fwrite(&last_io_addr, 1, 4, f);
365 old_io_addr = last_io_addr;
367 io_data = memcheck_read(last_io_addr);
368 if (old_io_data != io_data) {
370 fwrite(&byte, 1, 1, f);
371 fwrite(&io_data, 1, 4, f);
372 old_io_data = io_data;
375 fwrite(&byte, 1, 1, f);
378 if (psxRegs.cycle == 190230) {
379 dump_mem("/mnt/ntz/dev/pnd/tmp/psxram_i.dump", psxM, 0x200000);
380 dump_mem("/mnt/ntz/dev/pnd/tmp/psxregs_i.dump", psxH, 0x10000);
387 static const char *regnames[offsetof(psxRegisters, intCycle) / 4] = {
388 "r0", "r1", "r2", "r3", "r4", "r5", "r6", "r7",
389 "r8", "r9", "r10", "r11", "r12", "r13", "r14", "r15",
390 "r16", "r17", "r18", "r19", "r20", "r21", "r22", "r23",
391 "r24", "r25", "r26", "r27", "r28", "r29", "r30", "r31",
393 "C0_0", "C0_1", "C0_2", "C0_3", "C0_4", "C0_5", "C0_6", "C0_7",
394 "C0_8", "C0_9", "C0_10", "C0_11", "C0_12", "C0_13", "C0_14", "C0_15",
395 "C0_16", "C0_17", "C0_18", "C0_19", "C0_20", "C0_21", "C0_22", "C0_23",
396 "C0_24", "C0_25", "C0_26", "C0_27", "C0_28", "C0_29", "C0_30", "C0_31",
398 "C2D0", "C2D1", "C2D2", "C2D3", "C2D4", "C2D5", "C2D6", "C2D7",
399 "C2D8", "C2D9", "C2D10", "C2D11", "C2D12", "C2D13", "C2D14", "C2D15",
400 "C2D16", "C2D17", "C2D18", "C2D19", "C2D20", "C2D21", "C2D22", "C2D23",
401 "C2D24", "C2D25", "C2D26", "C2D27", "C2D28", "C2D29", "C2D30", "C2D31",
403 "C2C0", "C2C1", "C2C2", "C2C3", "C2C4", "C2C5", "C2C6", "C2C7",
404 "C2C8", "C2C9", "C2C10", "C2C11", "C2C12", "C2C13", "C2C14", "C2C15",
405 "C2C16", "C2C17", "C2C18", "C2C19", "C2C20", "C2C21", "C2C22", "C2C23",
406 "C2C24", "C2C25", "C2C26", "C2C27", "C2C28", "C2C29", "C2C30", "C2C31",
408 "PC", "code", "cycle", "interrupt",
416 static int miss_log_i;
417 #define miss_log_len (sizeof(miss_log)/sizeof(miss_log[0]))
418 #define miss_log_mask (miss_log_len-1)
420 static void miss_log_add(int reg, u32 val, u32 val_expect, u32 pc, u32 cycle)
422 miss_log[miss_log_i].reg = reg;
423 miss_log[miss_log_i].val = val;
424 miss_log[miss_log_i].val_expect = val_expect;
425 miss_log[miss_log_i].pc = pc;
426 miss_log[miss_log_i].cycle = cycle;
427 miss_log_i = (miss_log_i + 1) & miss_log_mask;
432 void do_insn_cmp(void)
434 static psxRegisters rregs;
435 static u32 mem_addr, mem_val;
436 u32 *allregs_p = (void *)&psxRegs;
437 u32 *allregs_e = (void *)&rregs;
438 static u32 ppc, failcount;
443 f = fopen("tracelog", "rb");
446 if ((ret = fread(&code, 1, 1, f)) <= 0)
453 if ((ret = fread(&mem_addr, 1, 4, f)) <= 0)
458 if ((ret = fread(&mem_val, 1, 4, f)) <= 0)
462 if ((ret = fread(&allregs_e[code], 1, 4, f)) <= 0)
471 psxRegs.code = rregs.code; // don't care
472 psxRegs.cycle = rregs.cycle;
473 psxRegs.CP0.r[9] = rregs.CP0.r[9]; // Count
475 //if (psxRegs.cycle == 166172) breakme();
477 if (memcmp(&psxRegs, &rregs, offsetof(psxRegisters, intCycle)) == 0 &&
478 mem_val == memcheck_read(mem_addr)
484 for (i = 0; i < offsetof(psxRegisters, intCycle) / 4; i++) {
485 if (allregs_p[i] != allregs_e[i]) {
486 miss_log_add(i, allregs_p[i], allregs_e[i], psxRegs.pc, psxRegs.cycle);
491 if (mem_val != memcheck_read(mem_addr)) {
492 printf("bad mem @%08x: %08x %08x\n", mem_addr, memcheck_read(mem_addr), mem_val);
496 if (psxRegs.pc == rregs.pc && bad < 6 && failcount < 32) {
497 static int last_mcycle;
498 if (last_mcycle != psxRegs.cycle >> 20) {
499 printf("%u\n", psxRegs.cycle);
500 last_mcycle = psxRegs.cycle >> 20;
507 for (i = 0; i < miss_log_len; i++, miss_log_i = (miss_log_i + 1) & miss_log_mask)
508 printf("bad %5s: %08x %08x, pc=%08x, cycle %u\n",
509 regnames[miss_log[miss_log_i].reg], miss_log[miss_log_i].val,
510 miss_log[miss_log_i].val_expect, miss_log[miss_log_i].pc, miss_log[miss_log_i].cycle);
511 printf("-- %d\n", bad);
512 for (i = 0; i < 8; i++)
513 printf("r%d=%08x r%2d=%08x r%2d=%08x r%2d=%08x\n", i, allregs_p[i],
514 i+8, allregs_p[i+8], i+16, allregs_p[i+16], i+24, allregs_p[i+24]);
515 printf("PC: %08x/%08x, cycle %u\n", psxRegs.pc, ppc, psxRegs.cycle);
516 dump_mem("/mnt/ntz/dev/pnd/tmp/psxram.dump", psxM, 0x200000);
517 dump_mem("/mnt/ntz/dev/pnd/tmp/psxregs.dump", psxH, 0x10000);
520 psxRegs.cycle = rregs.cycle + 2; // sync timing