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;
304 int cycle_multiplier;
306 void new_dynarec_init() {}
307 void new_dyna_start() {}
308 void new_dynarec_cleanup() {}
309 void new_dynarec_clear_full() {}
310 void invalidate_all_pages() {}
311 void invalidate_block(unsigned int block) {}
312 void new_dyna_pcsx_mem_init(void) {}
313 void new_dyna_pcsx_mem_reset(void) {}
320 extern u32 last_io_addr;
322 static void dump_mem(const char *fname, void *mem, size_t size)
324 FILE *f1 = fopen(fname, "wb");
326 f1 = fopen(strrchr(fname, '/') + 1, "wb");
327 fwrite(mem, 1, size, f1);
331 static u32 memcheck_read(u32 a)
333 if ((a >> 16) == 0x1f80)
335 return *(u32 *)(psxH + (a & 0xfffc));
337 if ((a >> 16) == 0x1f00)
339 return *(u32 *)(psxP + (a & 0xfffc));
341 // if ((a & ~0xe0600000) < 0x200000)
343 return *(u32 *)(psxM + (a & 0x1ffffc));
346 void do_insn_trace(void)
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;
357 //last_io_addr = 0x5e2c8;
359 f = fopen("tracelog", "wb");
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]) {
365 fwrite(&allregs_p[i], 1, 4, f);
366 allregs_o[i] = allregs_p[i];
369 if (old_io_addr != last_io_addr) {
371 fwrite(&byte, 1, 1, f);
372 fwrite(&last_io_addr, 1, 4, f);
373 old_io_addr = last_io_addr;
375 io_data = memcheck_read(last_io_addr);
376 if (old_io_data != io_data) {
378 fwrite(&byte, 1, 1, f);
379 fwrite(&io_data, 1, 4, f);
380 old_io_data = io_data;
383 fwrite(&byte, 1, 1, f);
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);
395 static 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",
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",
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",
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",
416 "PC", "code", "cycle", "interrupt",
424 static 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)
428 static void miss_log_add(int reg, u32 val, u32 val_expect, u32 pc, u32 cycle)
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;
440 void do_insn_cmp(void)
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;
451 f = fopen("tracelog", "rb");
454 if ((ret = fread(&code, 1, 1, f)) <= 0)
461 if ((ret = fread(&mem_addr, 1, 4, f)) <= 0)
466 if ((ret = fread(&mem_val, 1, 4, f)) <= 0)
470 if ((ret = fread(&allregs_e[code], 1, 4, f)) <= 0)
479 psxRegs.code = rregs.code; // don't care
480 psxRegs.cycle = rregs.cycle;
481 psxRegs.CP0.r[9] = rregs.CP0.r[9]; // Count
483 //if (psxRegs.cycle == 166172) breakme();
485 if (memcmp(&psxRegs, &rregs, offsetof(psxRegisters, intCycle)) == 0 &&
486 mem_val == memcheck_read(mem_addr)
492 for (i = 0; i < offsetof(psxRegisters, intCycle) / 4; i++) {
493 if (allregs_p[i] != allregs_e[i]) {
494 miss_log_add(i, allregs_p[i], allregs_e[i], psxRegs.pc, psxRegs.cycle);
499 if (mem_val != memcheck_read(mem_addr)) {
500 printf("bad mem @%08x: %08x %08x\n", mem_addr, memcheck_read(mem_addr), mem_val);
504 if (psxRegs.pc == rregs.pc && bad < 6 && failcount < 32) {
505 static int last_mcycle;
506 if (last_mcycle != psxRegs.cycle >> 20) {
507 printf("%u\n", psxRegs.cycle);
508 last_mcycle = psxRegs.cycle >> 20;
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],
522 i+8, allregs_p[i+8], i+16, allregs_p[i+16], i+24, allregs_p[i+24]);
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);
528 psxRegs.cycle = rregs.cycle + 2; // sync timing