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;
193 gte_handlers_nf[0x01] = gteRTPS_nf_arm;
194 gte_handlers_nf[0x30] = gteRTPT_nf_arm;
197 // compiler's _nf version is still a lot slower then neon
198 // _nf_arm RTPS is roughly the same, RTPT slower
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;
209 static void ari64_reset()
211 printf("ari64_reset\n");
212 new_dyna_pcsx_mem_reset();
213 invalidate_all_pages();
215 pending_exception = 1;
218 // execute until predefined leave points
219 // (HLE softcall exit and BIOS fastboot end)
220 static void ari64_execute_until()
222 schedule_timeslice();
224 evprintf("ari64_execute %08x, %u->%u (%d)\n", psxRegs.pc,
225 psxRegs.cycle, next_interupt, next_interupt - psxRegs.cycle);
229 evprintf("ari64_execute end %08x, %u->%u (%d)\n", psxRegs.pc,
230 psxRegs.cycle, next_interupt, next_interupt - psxRegs.cycle);
233 static void ari64_execute()
236 ari64_execute_until();
237 evprintf("drc left @%08x\n", psxRegs.pc);
241 static void ari64_clear(u32 addr, u32 size)
243 u32 start, end, main_ram;
245 size *= 4; /* PCSX uses DMA units */
247 evprintf("ari64_clear %08x %04x\n", addr, size);
249 /* check for RAM mirrors */
250 main_ram = (addr & 0xffe00000) == 0x80000000;
253 end = (addr + size) >> 12;
255 for (; start <= end; start++)
256 if (!main_ram || !invalid_code[start])
257 invalidate_block(start);
260 static void ari64_shutdown()
262 new_dynarec_cleanup();
265 extern void intExecute();
266 extern void intExecuteT();
267 extern void intExecuteBlock();
268 extern void intExecuteBlockT();
270 #define intExecuteT intExecute
271 #define intExecuteBlockT intExecuteBlock
290 void do_insn_trace() {}
291 void do_insn_cmp() {}
294 #if defined(__x86_64__) || defined(__i386__)
295 unsigned int address, readmem_word, word;
296 unsigned short hword;
298 int pending_exception, stop;
299 unsigned int next_interupt;
301 void new_dynarec_init() {}
302 void new_dyna_start() {}
303 void new_dynarec_cleanup() {}
304 void new_dynarec_clear_full() {}
305 void invalidate_all_pages() {}
306 void invalidate_block(unsigned int block) {}
307 void new_dyna_pcsx_mem_init(void) {}
308 void new_dyna_pcsx_mem_reset(void) {}
315 extern u32 last_io_addr;
317 static void dump_mem(const char *fname, void *mem, size_t size)
319 FILE *f1 = fopen(fname, "wb");
321 f1 = fopen(strrchr(fname, '/') + 1, "wb");
322 fwrite(mem, 1, size, f1);
326 static u32 memcheck_read(u32 a)
328 if ((a >> 16) == 0x1f80)
330 return *(u32 *)(psxH + (a & 0xfffc));
332 if ((a >> 16) == 0x1f00)
334 return *(u32 *)(psxP + (a & 0xfffc));
336 // if ((a & ~0xe0600000) < 0x200000)
338 return *(u32 *)(psxM + (a & 0x1ffffc));
341 void do_insn_trace(void)
343 static psxRegisters oldregs;
344 static u32 old_io_addr = (u32)-1;
345 static u32 old_io_data = 0xbad0c0de;
346 u32 *allregs_p = (void *)&psxRegs;
347 u32 *allregs_o = (void *)&oldregs;
352 //last_io_addr = 0x5e2c8;
354 f = fopen("tracelog", "wb");
356 oldregs.code = psxRegs.code; // don't care
357 for (i = 0; i < offsetof(psxRegisters, intCycle) / 4; i++) {
358 if (allregs_p[i] != allregs_o[i]) {
360 fwrite(&allregs_p[i], 1, 4, f);
361 allregs_o[i] = allregs_p[i];
364 if (old_io_addr != last_io_addr) {
366 fwrite(&byte, 1, 1, f);
367 fwrite(&last_io_addr, 1, 4, f);
368 old_io_addr = last_io_addr;
370 io_data = memcheck_read(last_io_addr);
371 if (old_io_data != io_data) {
373 fwrite(&byte, 1, 1, f);
374 fwrite(&io_data, 1, 4, f);
375 old_io_data = io_data;
378 fwrite(&byte, 1, 1, f);
381 if (psxRegs.cycle == 190230) {
382 dump_mem("/mnt/ntz/dev/pnd/tmp/psxram_i.dump", psxM, 0x200000);
383 dump_mem("/mnt/ntz/dev/pnd/tmp/psxregs_i.dump", psxH, 0x10000);
390 static const char *regnames[offsetof(psxRegisters, intCycle) / 4] = {
391 "r0", "r1", "r2", "r3", "r4", "r5", "r6", "r7",
392 "r8", "r9", "r10", "r11", "r12", "r13", "r14", "r15",
393 "r16", "r17", "r18", "r19", "r20", "r21", "r22", "r23",
394 "r24", "r25", "r26", "r27", "r28", "r29", "r30", "r31",
396 "C0_0", "C0_1", "C0_2", "C0_3", "C0_4", "C0_5", "C0_6", "C0_7",
397 "C0_8", "C0_9", "C0_10", "C0_11", "C0_12", "C0_13", "C0_14", "C0_15",
398 "C0_16", "C0_17", "C0_18", "C0_19", "C0_20", "C0_21", "C0_22", "C0_23",
399 "C0_24", "C0_25", "C0_26", "C0_27", "C0_28", "C0_29", "C0_30", "C0_31",
401 "C2D0", "C2D1", "C2D2", "C2D3", "C2D4", "C2D5", "C2D6", "C2D7",
402 "C2D8", "C2D9", "C2D10", "C2D11", "C2D12", "C2D13", "C2D14", "C2D15",
403 "C2D16", "C2D17", "C2D18", "C2D19", "C2D20", "C2D21", "C2D22", "C2D23",
404 "C2D24", "C2D25", "C2D26", "C2D27", "C2D28", "C2D29", "C2D30", "C2D31",
406 "C2C0", "C2C1", "C2C2", "C2C3", "C2C4", "C2C5", "C2C6", "C2C7",
407 "C2C8", "C2C9", "C2C10", "C2C11", "C2C12", "C2C13", "C2C14", "C2C15",
408 "C2C16", "C2C17", "C2C18", "C2C19", "C2C20", "C2C21", "C2C22", "C2C23",
409 "C2C24", "C2C25", "C2C26", "C2C27", "C2C28", "C2C29", "C2C30", "C2C31",
411 "PC", "code", "cycle", "interrupt",
419 static int miss_log_i;
420 #define miss_log_len (sizeof(miss_log)/sizeof(miss_log[0]))
421 #define miss_log_mask (miss_log_len-1)
423 static void miss_log_add(int reg, u32 val, u32 val_expect, u32 pc, u32 cycle)
425 miss_log[miss_log_i].reg = reg;
426 miss_log[miss_log_i].val = val;
427 miss_log[miss_log_i].val_expect = val_expect;
428 miss_log[miss_log_i].pc = pc;
429 miss_log[miss_log_i].cycle = cycle;
430 miss_log_i = (miss_log_i + 1) & miss_log_mask;
435 void do_insn_cmp(void)
437 static psxRegisters rregs;
438 static u32 mem_addr, mem_val;
439 u32 *allregs_p = (void *)&psxRegs;
440 u32 *allregs_e = (void *)&rregs;
441 static u32 ppc, failcount;
446 f = fopen("tracelog", "rb");
449 if ((ret = fread(&code, 1, 1, f)) <= 0)
456 if ((ret = fread(&mem_addr, 1, 4, f)) <= 0)
461 if ((ret = fread(&mem_val, 1, 4, f)) <= 0)
465 if ((ret = fread(&allregs_e[code], 1, 4, f)) <= 0)
474 psxRegs.code = rregs.code; // don't care
475 psxRegs.cycle = rregs.cycle;
476 psxRegs.CP0.r[9] = rregs.CP0.r[9]; // Count
478 //if (psxRegs.cycle == 166172) breakme();
480 if (memcmp(&psxRegs, &rregs, offsetof(psxRegisters, intCycle)) == 0 &&
481 mem_val == memcheck_read(mem_addr)
487 for (i = 0; i < offsetof(psxRegisters, intCycle) / 4; i++) {
488 if (allregs_p[i] != allregs_e[i]) {
489 miss_log_add(i, allregs_p[i], allregs_e[i], psxRegs.pc, psxRegs.cycle);
494 if (mem_val != memcheck_read(mem_addr)) {
495 printf("bad mem @%08x: %08x %08x\n", mem_addr, memcheck_read(mem_addr), mem_val);
499 if (psxRegs.pc == rregs.pc && bad < 6 && failcount < 32) {
500 static int last_mcycle;
501 if (last_mcycle != psxRegs.cycle >> 20) {
502 printf("%u\n", psxRegs.cycle);
503 last_mcycle = psxRegs.cycle >> 20;
510 for (i = 0; i < miss_log_len; i++, miss_log_i = (miss_log_i + 1) & miss_log_mask)
511 printf("bad %5s: %08x %08x, pc=%08x, cycle %u\n",
512 regnames[miss_log[miss_log_i].reg], miss_log[miss_log_i].val,
513 miss_log[miss_log_i].val_expect, miss_log[miss_log_i].pc, miss_log[miss_log_i].cycle);
514 printf("-- %d\n", bad);
515 for (i = 0; i < 8; i++)
516 printf("r%d=%08x r%2d=%08x r%2d=%08x r%2d=%08x\n", i, allregs_p[i],
517 i+8, allregs_p[i+8], i+16, allregs_p[i+16], i+24, allregs_p[i+24]);
518 printf("PC: %08x/%08x, cycle %u\n", psxRegs.pc, ppc, psxRegs.cycle);
519 dump_mem("/mnt/ntz/dev/pnd/tmp/psxram.dump", psxM, 0x200000);
520 dump_mem("/mnt/ntz/dev/pnd/tmp/psxregs.dump", psxH, 0x10000);
523 psxRegs.cycle = rregs.cycle + 2; // sync timing