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_neon.h"
19 #define ARRAY_SIZE(x) (sizeof(x) / sizeof(x[0]))
21 //#define evprintf printf
24 char invalid_code[0x100000];
25 u32 event_cycles[PSXINT_COUNT];
27 static void schedule_timeslice(void)
29 u32 i, c = psxRegs.cycle;
32 min = psxNextsCounter + psxNextCounter - c;
33 for (i = 0; i < ARRAY_SIZE(event_cycles); i++) {
34 dif = event_cycles[i] - c;
35 //evprintf(" ev %d\n", dif);
36 if (0 < dif && dif < min)
39 next_interupt = c + min;
42 static u32 cnt, last_cycle;
46 sum += psxRegs.cycle - last_cycle;
47 if ((cnt & 0xff) == 0)
48 printf("%u\n", (u32)(sum / cnt));
50 last_cycle = psxRegs.cycle;
54 typedef void (irq_func)();
56 static irq_func * const irq_funcs[] = {
57 [PSXINT_SIO] = sioInterrupt,
58 [PSXINT_CDR] = cdrInterrupt,
59 [PSXINT_CDREAD] = cdrReadInterrupt,
60 [PSXINT_GPUDMA] = gpuInterrupt,
61 [PSXINT_MDECOUTDMA] = mdec1Interrupt,
62 [PSXINT_SPUDMA] = spuInterrupt,
63 [PSXINT_MDECINDMA] = mdec0Interrupt,
64 [PSXINT_GPUOTCDMA] = gpuotcInterrupt,
65 [PSXINT_CDRDMA] = cdrDmaInterrupt,
66 [PSXINT_CDRLID] = cdrLidSeekInterrupt,
67 [PSXINT_CDRPLAY] = cdrPlayInterrupt,
70 /* local dupe of psxBranchTest, using event_cycles */
71 static void irq_test(void)
73 u32 irqs = psxRegs.interrupt;
74 u32 cycle = psxRegs.cycle;
77 if ((psxRegs.cycle - psxNextsCounter) >= psxNextCounter)
80 // irq_funcs() may queue more irqs
81 psxRegs.interrupt = 0;
83 for (irq = 0, irq_bits = irqs; irq_bits != 0; irq++, irq_bits >>= 1) {
86 if ((s32)(cycle - event_cycles[irq]) >= 0) {
91 psxRegs.interrupt |= irqs;
93 if ((psxHu32(0x1070) & psxHu32(0x1074)) && (Status & 0x401) == 0x401) {
94 psxException(0x400, 0);
95 pending_exception = 1;
101 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 /* from gte.txt.. not sure if this is any good. */
147 const char gte_cycletab[64] = {
148 /* 1 2 3 4 5 6 7 8 9 a b c d e f */
149 0, 15, 0, 0, 0, 0, 8, 0, 0, 0, 0, 0, 6, 0, 0, 0,
150 8, 8, 8, 19, 13, 0, 44, 0, 0, 0, 0, 17, 11, 0, 14, 0,
151 30, 0, 0, 0, 0, 0, 0, 0, 5, 8, 17, 0, 0, 5, 6, 0,
152 23, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 5, 5, 39,
155 static int ari64_init()
157 extern void (*psxCP2[64])();
158 extern void psxNULL();
162 new_dyna_pcsx_mem_init();
164 for (i = 0; i < ARRAY_SIZE(gte_handlers); i++)
165 if (psxCP2[i] != psxNULL)
166 gte_handlers[i] = psxCP2[i];
168 gte_handlers[0x01] = gteRTPS_neon;
169 gte_handlers[0x30] = gteRTPT_neon;
170 gte_handlers[0x12] = gteMVMVA_neon;
171 gte_handlers[0x06] = gteNCLIP_neon;
178 static void ari64_reset()
180 printf("ari64_reset\n");
181 new_dyna_pcsx_mem_reset();
182 invalidate_all_pages();
184 pending_exception = 1;
187 // execute until predefined leave points
188 // (HLE softcall exit and BIOS fastboot end)
189 static void ari64_execute_until()
191 schedule_timeslice();
193 evprintf("ari64_execute %08x, %u->%u (%d)\n", psxRegs.pc,
194 psxRegs.cycle, next_interupt, next_interupt - psxRegs.cycle);
198 evprintf("ari64_execute end %08x, %u->%u (%d)\n", psxRegs.pc,
199 psxRegs.cycle, next_interupt, next_interupt - psxRegs.cycle);
202 static void ari64_execute()
205 ari64_execute_until();
206 evprintf("drc left @%08x\n", psxRegs.pc);
210 static void ari64_clear(u32 addr, u32 size)
212 u32 start, end, main_ram;
214 size *= 4; /* PCSX uses DMA units */
216 evprintf("ari64_clear %08x %04x\n", addr, size);
218 /* check for RAM mirrors */
219 main_ram = (addr & 0xffe00000) == 0x80000000;
222 end = (addr + size) >> 12;
224 for (; start <= end; start++)
225 if (!main_ram || !invalid_code[start])
226 invalidate_block(start);
229 static void ari64_shutdown()
231 new_dynarec_cleanup();
234 extern void intExecute();
235 extern void intExecuteT();
236 extern void intExecuteBlock();
237 extern void intExecuteBlockT();
239 #define intExecuteT intExecute
240 #define intExecuteBlockT intExecuteBlock
259 void do_insn_trace() {}
260 void do_insn_cmp() {}
263 #if defined(__x86_64__) || defined(__i386__)
264 unsigned int address, readmem_word, word;
265 unsigned short hword;
267 int pending_exception, stop;
268 unsigned int next_interupt;
270 void new_dynarec_init() {}
271 void new_dyna_start() {}
272 void new_dynarec_cleanup() {}
273 void new_dynarec_clear_full() {}
274 void invalidate_all_pages() {}
275 void invalidate_block(unsigned int block) {}
276 void new_dyna_pcsx_mem_init(void) {}
277 void new_dyna_pcsx_mem_reset(void) {}
284 extern u32 last_io_addr;
286 static void dump_mem(const char *fname, void *mem, size_t size)
288 FILE *f1 = fopen(fname, "wb");
290 f1 = fopen(strrchr(fname, '/') + 1, "wb");
291 fwrite(mem, 1, size, f1);
295 static u32 memcheck_read(u32 a)
297 if ((a >> 16) == 0x1f80)
299 return *(u32 *)(psxH + (a & 0xfffc));
301 if ((a >> 16) == 0x1f00)
303 return *(u32 *)(psxP + (a & 0xfffc));
305 // if ((a & ~0xe0600000) < 0x200000)
307 return *(u32 *)(psxM + (a & 0x1ffffc));
310 void do_insn_trace(void)
312 static psxRegisters oldregs;
313 static u32 old_io_addr = (u32)-1;
314 static u32 old_io_data = 0xbad0c0de;
315 u32 *allregs_p = (void *)&psxRegs;
316 u32 *allregs_o = (void *)&oldregs;
321 //last_io_addr = 0x5e2c8;
323 f = fopen("tracelog", "wb");
325 oldregs.code = psxRegs.code; // don't care
326 for (i = 0; i < offsetof(psxRegisters, intCycle) / 4; i++) {
327 if (allregs_p[i] != allregs_o[i]) {
329 fwrite(&allregs_p[i], 1, 4, f);
330 allregs_o[i] = allregs_p[i];
333 if (old_io_addr != last_io_addr) {
335 fwrite(&byte, 1, 1, f);
336 fwrite(&last_io_addr, 1, 4, f);
337 old_io_addr = last_io_addr;
339 io_data = memcheck_read(last_io_addr);
340 if (old_io_data != io_data) {
342 fwrite(&byte, 1, 1, f);
343 fwrite(&io_data, 1, 4, f);
344 old_io_data = io_data;
347 fwrite(&byte, 1, 1, f);
350 if (psxRegs.cycle == 190230) {
351 dump_mem("/mnt/ntz/dev/pnd/tmp/psxram_i.dump", psxM, 0x200000);
352 dump_mem("/mnt/ntz/dev/pnd/tmp/psxregs_i.dump", psxH, 0x10000);
359 static const char *regnames[offsetof(psxRegisters, intCycle) / 4] = {
360 "r0", "r1", "r2", "r3", "r4", "r5", "r6", "r7",
361 "r8", "r9", "r10", "r11", "r12", "r13", "r14", "r15",
362 "r16", "r17", "r18", "r19", "r20", "r21", "r22", "r23",
363 "r24", "r25", "r26", "r27", "r28", "r29", "r30", "r31",
365 "C0_0", "C0_1", "C0_2", "C0_3", "C0_4", "C0_5", "C0_6", "C0_7",
366 "C0_8", "C0_9", "C0_10", "C0_11", "C0_12", "C0_13", "C0_14", "C0_15",
367 "C0_16", "C0_17", "C0_18", "C0_19", "C0_20", "C0_21", "C0_22", "C0_23",
368 "C0_24", "C0_25", "C0_26", "C0_27", "C0_28", "C0_29", "C0_30", "C0_31",
370 "C2D0", "C2D1", "C2D2", "C2D3", "C2D4", "C2D5", "C2D6", "C2D7",
371 "C2D8", "C2D9", "C2D10", "C2D11", "C2D12", "C2D13", "C2D14", "C2D15",
372 "C2D16", "C2D17", "C2D18", "C2D19", "C2D20", "C2D21", "C2D22", "C2D23",
373 "C2D24", "C2D25", "C2D26", "C2D27", "C2D28", "C2D29", "C2D30", "C2D31",
375 "C2C0", "C2C1", "C2C2", "C2C3", "C2C4", "C2C5", "C2C6", "C2C7",
376 "C2C8", "C2C9", "C2C10", "C2C11", "C2C12", "C2C13", "C2C14", "C2C15",
377 "C2C16", "C2C17", "C2C18", "C2C19", "C2C20", "C2C21", "C2C22", "C2C23",
378 "C2C24", "C2C25", "C2C26", "C2C27", "C2C28", "C2C29", "C2C30", "C2C31",
380 "PC", "code", "cycle", "interrupt",
388 static int miss_log_i;
389 #define miss_log_len (sizeof(miss_log)/sizeof(miss_log[0]))
390 #define miss_log_mask (miss_log_len-1)
392 static void miss_log_add(int reg, u32 val, u32 val_expect, u32 pc, u32 cycle)
394 miss_log[miss_log_i].reg = reg;
395 miss_log[miss_log_i].val = val;
396 miss_log[miss_log_i].val_expect = val_expect;
397 miss_log[miss_log_i].pc = pc;
398 miss_log[miss_log_i].cycle = cycle;
399 miss_log_i = (miss_log_i + 1) & miss_log_mask;
404 void do_insn_cmp(void)
406 static psxRegisters rregs;
407 static u32 mem_addr, mem_val;
408 u32 *allregs_p = (void *)&psxRegs;
409 u32 *allregs_e = (void *)&rregs;
410 static u32 ppc, failcount;
415 f = fopen("tracelog", "rb");
418 if ((ret = fread(&code, 1, 1, f)) <= 0)
425 if ((ret = fread(&mem_addr, 1, 4, f)) <= 0)
430 if ((ret = fread(&mem_val, 1, 4, f)) <= 0)
434 if ((ret = fread(&allregs_e[code], 1, 4, f)) <= 0)
443 psxRegs.code = rregs.code; // don't care
444 psxRegs.cycle = rregs.cycle;
445 psxRegs.CP0.r[9] = rregs.CP0.r[9]; // Count
447 //if (psxRegs.cycle == 166172) breakme();
449 if (memcmp(&psxRegs, &rregs, offsetof(psxRegisters, intCycle)) == 0 &&
450 mem_val == memcheck_read(mem_addr)
456 for (i = 0; i < offsetof(psxRegisters, intCycle) / 4; i++) {
457 if (allregs_p[i] != allregs_e[i]) {
458 miss_log_add(i, allregs_p[i], allregs_e[i], psxRegs.pc, psxRegs.cycle);
463 if (mem_val != memcheck_read(mem_addr)) {
464 printf("bad mem @%08x: %08x %08x\n", mem_addr, memcheck_read(mem_addr), mem_val);
468 if (psxRegs.pc == rregs.pc && bad < 6 && failcount < 32) {
469 static int last_mcycle;
470 if (last_mcycle != psxRegs.cycle >> 20) {
471 printf("%u\n", psxRegs.cycle);
472 last_mcycle = psxRegs.cycle >> 20;
479 for (i = 0; i < miss_log_len; i++, miss_log_i = (miss_log_i + 1) & miss_log_mask)
480 printf("bad %5s: %08x %08x, pc=%08x, cycle %u\n",
481 regnames[miss_log[miss_log_i].reg], miss_log[miss_log_i].val,
482 miss_log[miss_log_i].val_expect, miss_log[miss_log_i].pc, miss_log[miss_log_i].cycle);
483 printf("-- %d\n", bad);
484 for (i = 0; i < 8; i++)
485 printf("r%d=%08x r%2d=%08x r%2d=%08x r%2d=%08x\n", i, allregs_p[i],
486 i+8, allregs_p[i+8], i+16, allregs_p[i+16], i+24, allregs_p[i+24]);
487 printf("PC: %08x/%08x, cycle %u\n", psxRegs.pc, ppc, psxRegs.cycle);
488 dump_mem("/mnt/ntz/dev/pnd/tmp/psxram.dump", psxM, 0x200000);
489 dump_mem("/mnt/ntz/dev/pnd/tmp/psxregs.dump", psxH, 0x10000);
492 psxRegs.cycle = rregs.cycle + 2; // sync timing