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 /* from gte.txt.. not sure if this is any good. */
158 const char gte_cycletab[64] = {
159 /* 1 2 3 4 5 6 7 8 9 a b c d e f */
160 0, 15, 0, 0, 0, 0, 8, 0, 0, 0, 0, 0, 6, 0, 0, 0,
161 8, 8, 8, 19, 13, 0, 44, 0, 0, 0, 0, 17, 11, 0, 14, 0,
162 30, 0, 0, 0, 0, 0, 0, 0, 5, 8, 17, 0, 0, 5, 6, 0,
163 23, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 5, 5, 39,
166 static int ari64_init()
168 extern void (*psxCP2[64])();
169 extern void psxNULL();
173 new_dyna_pcsx_mem_init();
175 for (i = 0; i < ARRAY_SIZE(gte_handlers); i++)
176 if (psxCP2[i] != psxNULL)
177 gte_handlers[i] = psxCP2[i];
179 #if !defined(DRC_DBG) && !defined(PCNT)
181 gte_handlers[0x06] = gteNCLIP_arm;
184 // compiler's _nf version is still a lot slower then neon
185 gte_handlers[0x01] = gte_handlers_nf[0x01] = gteRTPS_neon;
186 gte_handlers[0x30] = gte_handlers_nf[0x30] = gteRTPT_neon;
187 gte_handlers[0x12] = gte_handlers_nf[0x12] = gteMVMVA_neon;
195 static void ari64_reset()
197 printf("ari64_reset\n");
198 new_dyna_pcsx_mem_reset();
199 invalidate_all_pages();
201 pending_exception = 1;
204 // execute until predefined leave points
205 // (HLE softcall exit and BIOS fastboot end)
206 static void ari64_execute_until()
208 schedule_timeslice();
210 evprintf("ari64_execute %08x, %u->%u (%d)\n", psxRegs.pc,
211 psxRegs.cycle, next_interupt, next_interupt - psxRegs.cycle);
215 evprintf("ari64_execute end %08x, %u->%u (%d)\n", psxRegs.pc,
216 psxRegs.cycle, next_interupt, next_interupt - psxRegs.cycle);
219 static void ari64_execute()
222 ari64_execute_until();
223 evprintf("drc left @%08x\n", psxRegs.pc);
227 static void ari64_clear(u32 addr, u32 size)
229 u32 start, end, main_ram;
231 size *= 4; /* PCSX uses DMA units */
233 evprintf("ari64_clear %08x %04x\n", addr, size);
235 /* check for RAM mirrors */
236 main_ram = (addr & 0xffe00000) == 0x80000000;
239 end = (addr + size) >> 12;
241 for (; start <= end; start++)
242 if (!main_ram || !invalid_code[start])
243 invalidate_block(start);
246 static void ari64_shutdown()
248 new_dynarec_cleanup();
251 extern void intExecute();
252 extern void intExecuteT();
253 extern void intExecuteBlock();
254 extern void intExecuteBlockT();
256 #define intExecuteT intExecute
257 #define intExecuteBlockT intExecuteBlock
276 void do_insn_trace() {}
277 void do_insn_cmp() {}
280 #if defined(__x86_64__) || defined(__i386__)
281 unsigned int address, readmem_word, word;
282 unsigned short hword;
284 int pending_exception, stop;
285 unsigned int next_interupt;
287 void new_dynarec_init() {}
288 void new_dyna_start() {}
289 void new_dynarec_cleanup() {}
290 void new_dynarec_clear_full() {}
291 void invalidate_all_pages() {}
292 void invalidate_block(unsigned int block) {}
293 void new_dyna_pcsx_mem_init(void) {}
294 void new_dyna_pcsx_mem_reset(void) {}
301 extern u32 last_io_addr;
303 static void dump_mem(const char *fname, void *mem, size_t size)
305 FILE *f1 = fopen(fname, "wb");
307 f1 = fopen(strrchr(fname, '/') + 1, "wb");
308 fwrite(mem, 1, size, f1);
312 static u32 memcheck_read(u32 a)
314 if ((a >> 16) == 0x1f80)
316 return *(u32 *)(psxH + (a & 0xfffc));
318 if ((a >> 16) == 0x1f00)
320 return *(u32 *)(psxP + (a & 0xfffc));
322 // if ((a & ~0xe0600000) < 0x200000)
324 return *(u32 *)(psxM + (a & 0x1ffffc));
327 void do_insn_trace(void)
329 static psxRegisters oldregs;
330 static u32 old_io_addr = (u32)-1;
331 static u32 old_io_data = 0xbad0c0de;
332 u32 *allregs_p = (void *)&psxRegs;
333 u32 *allregs_o = (void *)&oldregs;
338 //last_io_addr = 0x5e2c8;
340 f = fopen("tracelog", "wb");
342 oldregs.code = psxRegs.code; // don't care
343 for (i = 0; i < offsetof(psxRegisters, intCycle) / 4; i++) {
344 if (allregs_p[i] != allregs_o[i]) {
346 fwrite(&allregs_p[i], 1, 4, f);
347 allregs_o[i] = allregs_p[i];
350 if (old_io_addr != last_io_addr) {
352 fwrite(&byte, 1, 1, f);
353 fwrite(&last_io_addr, 1, 4, f);
354 old_io_addr = last_io_addr;
356 io_data = memcheck_read(last_io_addr);
357 if (old_io_data != io_data) {
359 fwrite(&byte, 1, 1, f);
360 fwrite(&io_data, 1, 4, f);
361 old_io_data = io_data;
364 fwrite(&byte, 1, 1, f);
367 if (psxRegs.cycle == 190230) {
368 dump_mem("/mnt/ntz/dev/pnd/tmp/psxram_i.dump", psxM, 0x200000);
369 dump_mem("/mnt/ntz/dev/pnd/tmp/psxregs_i.dump", psxH, 0x10000);
376 static const char *regnames[offsetof(psxRegisters, intCycle) / 4] = {
377 "r0", "r1", "r2", "r3", "r4", "r5", "r6", "r7",
378 "r8", "r9", "r10", "r11", "r12", "r13", "r14", "r15",
379 "r16", "r17", "r18", "r19", "r20", "r21", "r22", "r23",
380 "r24", "r25", "r26", "r27", "r28", "r29", "r30", "r31",
382 "C0_0", "C0_1", "C0_2", "C0_3", "C0_4", "C0_5", "C0_6", "C0_7",
383 "C0_8", "C0_9", "C0_10", "C0_11", "C0_12", "C0_13", "C0_14", "C0_15",
384 "C0_16", "C0_17", "C0_18", "C0_19", "C0_20", "C0_21", "C0_22", "C0_23",
385 "C0_24", "C0_25", "C0_26", "C0_27", "C0_28", "C0_29", "C0_30", "C0_31",
387 "C2D0", "C2D1", "C2D2", "C2D3", "C2D4", "C2D5", "C2D6", "C2D7",
388 "C2D8", "C2D9", "C2D10", "C2D11", "C2D12", "C2D13", "C2D14", "C2D15",
389 "C2D16", "C2D17", "C2D18", "C2D19", "C2D20", "C2D21", "C2D22", "C2D23",
390 "C2D24", "C2D25", "C2D26", "C2D27", "C2D28", "C2D29", "C2D30", "C2D31",
392 "C2C0", "C2C1", "C2C2", "C2C3", "C2C4", "C2C5", "C2C6", "C2C7",
393 "C2C8", "C2C9", "C2C10", "C2C11", "C2C12", "C2C13", "C2C14", "C2C15",
394 "C2C16", "C2C17", "C2C18", "C2C19", "C2C20", "C2C21", "C2C22", "C2C23",
395 "C2C24", "C2C25", "C2C26", "C2C27", "C2C28", "C2C29", "C2C30", "C2C31",
397 "PC", "code", "cycle", "interrupt",
405 static int miss_log_i;
406 #define miss_log_len (sizeof(miss_log)/sizeof(miss_log[0]))
407 #define miss_log_mask (miss_log_len-1)
409 static void miss_log_add(int reg, u32 val, u32 val_expect, u32 pc, u32 cycle)
411 miss_log[miss_log_i].reg = reg;
412 miss_log[miss_log_i].val = val;
413 miss_log[miss_log_i].val_expect = val_expect;
414 miss_log[miss_log_i].pc = pc;
415 miss_log[miss_log_i].cycle = cycle;
416 miss_log_i = (miss_log_i + 1) & miss_log_mask;
421 void do_insn_cmp(void)
423 static psxRegisters rregs;
424 static u32 mem_addr, mem_val;
425 u32 *allregs_p = (void *)&psxRegs;
426 u32 *allregs_e = (void *)&rregs;
427 static u32 ppc, failcount;
432 f = fopen("tracelog", "rb");
435 if ((ret = fread(&code, 1, 1, f)) <= 0)
442 if ((ret = fread(&mem_addr, 1, 4, f)) <= 0)
447 if ((ret = fread(&mem_val, 1, 4, f)) <= 0)
451 if ((ret = fread(&allregs_e[code], 1, 4, f)) <= 0)
460 psxRegs.code = rregs.code; // don't care
461 psxRegs.cycle = rregs.cycle;
462 psxRegs.CP0.r[9] = rregs.CP0.r[9]; // Count
464 //if (psxRegs.cycle == 166172) breakme();
466 if (memcmp(&psxRegs, &rregs, offsetof(psxRegisters, intCycle)) == 0 &&
467 mem_val == memcheck_read(mem_addr)
473 for (i = 0; i < offsetof(psxRegisters, intCycle) / 4; i++) {
474 if (allregs_p[i] != allregs_e[i]) {
475 miss_log_add(i, allregs_p[i], allregs_e[i], psxRegs.pc, psxRegs.cycle);
480 if (mem_val != memcheck_read(mem_addr)) {
481 printf("bad mem @%08x: %08x %08x\n", mem_addr, memcheck_read(mem_addr), mem_val);
485 if (psxRegs.pc == rregs.pc && bad < 6 && failcount < 32) {
486 static int last_mcycle;
487 if (last_mcycle != psxRegs.cycle >> 20) {
488 printf("%u\n", psxRegs.cycle);
489 last_mcycle = psxRegs.cycle >> 20;
496 for (i = 0; i < miss_log_len; i++, miss_log_i = (miss_log_i + 1) & miss_log_mask)
497 printf("bad %5s: %08x %08x, pc=%08x, cycle %u\n",
498 regnames[miss_log[miss_log_i].reg], miss_log[miss_log_i].val,
499 miss_log[miss_log_i].val_expect, miss_log[miss_log_i].pc, miss_log[miss_log_i].cycle);
500 printf("-- %d\n", bad);
501 for (i = 0; i < 8; i++)
502 printf("r%d=%08x r%2d=%08x r%2d=%08x r%2d=%08x\n", i, allregs_p[i],
503 i+8, allregs_p[i+8], i+16, allregs_p[i+16], i+24, allregs_p[i+24]);
504 printf("PC: %08x/%08x, cycle %u\n", psxRegs.pc, ppc, psxRegs.cycle);
505 dump_mem("/mnt/ntz/dev/pnd/tmp/psxram.dump", psxM, 0x200000);
506 dump_mem("/mnt/ntz/dev/pnd/tmp/psxregs.dump", psxH, 0x10000);
509 psxRegs.cycle = rregs.cycle + 2; // sync timing