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, u32 val)
121 evprintf("MTC0 %d #%x @%08x %u\n", reg, val, psxRegs.pc, psxRegs.cycle);
126 void pcsx_mtc0_ds(u32 reg, u32 val)
128 evprintf("MTC0 %d #%x @%08x %u\n", reg, val, psxRegs.pc, psxRegs.cycle);
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;
205 memcpy(gte_handlers_nf, gte_handlers, sizeof(gte_handlers_nf));
212 static void ari64_reset()
214 printf("ari64_reset\n");
215 new_dyna_pcsx_mem_reset();
216 invalidate_all_pages();
218 pending_exception = 1;
221 // execute until predefined leave points
222 // (HLE softcall exit and BIOS fastboot end)
223 static void ari64_execute_until()
225 schedule_timeslice();
227 evprintf("ari64_execute %08x, %u->%u (%d)\n", psxRegs.pc,
228 psxRegs.cycle, next_interupt, next_interupt - psxRegs.cycle);
232 evprintf("ari64_execute end %08x, %u->%u (%d)\n", psxRegs.pc,
233 psxRegs.cycle, next_interupt, next_interupt - psxRegs.cycle);
236 static void ari64_execute()
239 ari64_execute_until();
240 evprintf("drc left @%08x\n", psxRegs.pc);
244 static void ari64_clear(u32 addr, u32 size)
246 u32 start, end, main_ram;
248 size *= 4; /* PCSX uses DMA units */
250 evprintf("ari64_clear %08x %04x\n", addr, size);
252 /* check for RAM mirrors */
253 main_ram = (addr & 0xffe00000) == 0x80000000;
256 end = (addr + size) >> 12;
258 for (; start <= end; start++)
259 if (!main_ram || !invalid_code[start])
260 invalidate_block(start);
263 static void ari64_shutdown()
265 new_dynarec_cleanup();
268 extern void intExecute();
269 extern void intExecuteT();
270 extern void intExecuteBlock();
271 extern void intExecuteBlockT();
273 #define intExecuteT intExecute
274 #define intExecuteBlockT intExecuteBlock
293 void do_insn_trace() {}
294 void do_insn_cmp() {}
297 #if defined(__x86_64__) || defined(__i386__)
298 unsigned int address, readmem_word, word;
299 unsigned short hword;
301 int pending_exception, stop;
302 unsigned int next_interupt;
303 int new_dynarec_did_compile;
305 void new_dynarec_init() {}
306 void new_dyna_start() {}
307 void new_dynarec_cleanup() {}
308 void new_dynarec_clear_full() {}
309 void invalidate_all_pages() {}
310 void invalidate_block(unsigned int block) {}
311 void new_dyna_pcsx_mem_init(void) {}
312 void new_dyna_pcsx_mem_reset(void) {}
319 extern u32 last_io_addr;
321 static void dump_mem(const char *fname, void *mem, size_t size)
323 FILE *f1 = fopen(fname, "wb");
325 f1 = fopen(strrchr(fname, '/') + 1, "wb");
326 fwrite(mem, 1, size, f1);
330 static u32 memcheck_read(u32 a)
332 if ((a >> 16) == 0x1f80)
334 return *(u32 *)(psxH + (a & 0xfffc));
336 if ((a >> 16) == 0x1f00)
338 return *(u32 *)(psxP + (a & 0xfffc));
340 // if ((a & ~0xe0600000) < 0x200000)
342 return *(u32 *)(psxM + (a & 0x1ffffc));
345 void do_insn_trace(void)
347 static psxRegisters oldregs;
348 static u32 old_io_addr = (u32)-1;
349 static u32 old_io_data = 0xbad0c0de;
350 u32 *allregs_p = (void *)&psxRegs;
351 u32 *allregs_o = (void *)&oldregs;
356 //last_io_addr = 0x5e2c8;
358 f = fopen("tracelog", "wb");
360 oldregs.code = psxRegs.code; // don't care
361 for (i = 0; i < offsetof(psxRegisters, intCycle) / 4; i++) {
362 if (allregs_p[i] != allregs_o[i]) {
364 fwrite(&allregs_p[i], 1, 4, f);
365 allregs_o[i] = allregs_p[i];
368 if (old_io_addr != last_io_addr) {
370 fwrite(&byte, 1, 1, f);
371 fwrite(&last_io_addr, 1, 4, f);
372 old_io_addr = last_io_addr;
374 io_data = memcheck_read(last_io_addr);
375 if (old_io_data != io_data) {
377 fwrite(&byte, 1, 1, f);
378 fwrite(&io_data, 1, 4, f);
379 old_io_data = io_data;
382 fwrite(&byte, 1, 1, f);
385 if (psxRegs.cycle == 190230) {
386 dump_mem("/mnt/ntz/dev/pnd/tmp/psxram_i.dump", psxM, 0x200000);
387 dump_mem("/mnt/ntz/dev/pnd/tmp/psxregs_i.dump", psxH, 0x10000);
394 static const char *regnames[offsetof(psxRegisters, intCycle) / 4] = {
395 "r0", "r1", "r2", "r3", "r4", "r5", "r6", "r7",
396 "r8", "r9", "r10", "r11", "r12", "r13", "r14", "r15",
397 "r16", "r17", "r18", "r19", "r20", "r21", "r22", "r23",
398 "r24", "r25", "r26", "r27", "r28", "r29", "r30", "r31",
400 "C0_0", "C0_1", "C0_2", "C0_3", "C0_4", "C0_5", "C0_6", "C0_7",
401 "C0_8", "C0_9", "C0_10", "C0_11", "C0_12", "C0_13", "C0_14", "C0_15",
402 "C0_16", "C0_17", "C0_18", "C0_19", "C0_20", "C0_21", "C0_22", "C0_23",
403 "C0_24", "C0_25", "C0_26", "C0_27", "C0_28", "C0_29", "C0_30", "C0_31",
405 "C2D0", "C2D1", "C2D2", "C2D3", "C2D4", "C2D5", "C2D6", "C2D7",
406 "C2D8", "C2D9", "C2D10", "C2D11", "C2D12", "C2D13", "C2D14", "C2D15",
407 "C2D16", "C2D17", "C2D18", "C2D19", "C2D20", "C2D21", "C2D22", "C2D23",
408 "C2D24", "C2D25", "C2D26", "C2D27", "C2D28", "C2D29", "C2D30", "C2D31",
410 "C2C0", "C2C1", "C2C2", "C2C3", "C2C4", "C2C5", "C2C6", "C2C7",
411 "C2C8", "C2C9", "C2C10", "C2C11", "C2C12", "C2C13", "C2C14", "C2C15",
412 "C2C16", "C2C17", "C2C18", "C2C19", "C2C20", "C2C21", "C2C22", "C2C23",
413 "C2C24", "C2C25", "C2C26", "C2C27", "C2C28", "C2C29", "C2C30", "C2C31",
415 "PC", "code", "cycle", "interrupt",
423 static int miss_log_i;
424 #define miss_log_len (sizeof(miss_log)/sizeof(miss_log[0]))
425 #define miss_log_mask (miss_log_len-1)
427 static void miss_log_add(int reg, u32 val, u32 val_expect, u32 pc, u32 cycle)
429 miss_log[miss_log_i].reg = reg;
430 miss_log[miss_log_i].val = val;
431 miss_log[miss_log_i].val_expect = val_expect;
432 miss_log[miss_log_i].pc = pc;
433 miss_log[miss_log_i].cycle = cycle;
434 miss_log_i = (miss_log_i + 1) & miss_log_mask;
439 void do_insn_cmp(void)
441 static psxRegisters rregs;
442 static u32 mem_addr, mem_val;
443 u32 *allregs_p = (void *)&psxRegs;
444 u32 *allregs_e = (void *)&rregs;
445 static u32 ppc, failcount;
450 f = fopen("tracelog", "rb");
453 if ((ret = fread(&code, 1, 1, f)) <= 0)
460 if ((ret = fread(&mem_addr, 1, 4, f)) <= 0)
465 if ((ret = fread(&mem_val, 1, 4, f)) <= 0)
469 if ((ret = fread(&allregs_e[code], 1, 4, f)) <= 0)
478 psxRegs.code = rregs.code; // don't care
479 psxRegs.cycle = rregs.cycle;
480 psxRegs.CP0.r[9] = rregs.CP0.r[9]; // Count
482 //if (psxRegs.cycle == 166172) breakme();
484 if (memcmp(&psxRegs, &rregs, offsetof(psxRegisters, intCycle)) == 0 &&
485 mem_val == memcheck_read(mem_addr)
491 for (i = 0; i < offsetof(psxRegisters, intCycle) / 4; i++) {
492 if (allregs_p[i] != allregs_e[i]) {
493 miss_log_add(i, allregs_p[i], allregs_e[i], psxRegs.pc, psxRegs.cycle);
498 if (mem_val != memcheck_read(mem_addr)) {
499 printf("bad mem @%08x: %08x %08x\n", mem_addr, memcheck_read(mem_addr), mem_val);
503 if (psxRegs.pc == rregs.pc && bad < 6 && failcount < 32) {
504 static int last_mcycle;
505 if (last_mcycle != psxRegs.cycle >> 20) {
506 printf("%u\n", psxRegs.cycle);
507 last_mcycle = psxRegs.cycle >> 20;
514 for (i = 0; i < miss_log_len; i++, miss_log_i = (miss_log_i + 1) & miss_log_mask)
515 printf("bad %5s: %08x %08x, pc=%08x, cycle %u\n",
516 regnames[miss_log[miss_log_i].reg], miss_log[miss_log_i].val,
517 miss_log[miss_log_i].val_expect, miss_log[miss_log_i].pc, miss_log[miss_log_i].cycle);
518 printf("-- %d\n", bad);
519 for (i = 0; i < 8; i++)
520 printf("r%d=%08x r%2d=%08x r%2d=%08x r%2d=%08x\n", i, allregs_p[i],
521 i+8, allregs_p[i+8], i+16, allregs_p[i+16], i+24, allregs_p[i+24]);
522 printf("PC: %08x/%08x, cycle %u\n", psxRegs.pc, ppc, psxRegs.cycle);
523 dump_mem("/mnt/ntz/dev/pnd/tmp/psxram.dump", psxM, 0x200000);
524 dump_mem("/mnt/ntz/dev/pnd/tmp/psxregs.dump", psxH, 0x10000);
527 psxRegs.cycle = rregs.cycle + 2; // sync timing