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);
105 //pending_exception = 1;
107 schedule_timeslice();
109 evprintf(" -ge %08x, %u->%u (%d)\n", psxRegs.pc, psxRegs.cycle,
110 next_interupt, next_interupt - psxRegs.cycle);
114 extern void MTC0(int reg, u32 val);
116 void pcsx_mtc0(u32 reg)
118 evprintf("MTC0 %d #%x @%08x %u\n", reg, readmem_word, psxRegs.pc, psxRegs.cycle);
119 MTC0(reg, readmem_word);
123 void pcsx_mtc0_ds(u32 reg)
125 evprintf("MTC0 %d #%x @%08x %u\n", reg, readmem_word, psxRegs.pc, psxRegs.cycle);
126 MTC0(reg, readmem_word);
129 void new_dyna_save(void)
131 // psxRegs.intCycle is always maintained, no need to convert
134 void new_dyna_restore(void)
137 for (i = 0; i < PSXINT_COUNT; i++)
138 event_cycles[i] = psxRegs.intCycle[i].sCycle + psxRegs.intCycle[i].cycle;
141 void *gte_handlers[64];
143 /* from gte.txt.. not sure if this is any good. */
144 const char gte_cycletab[64] = {
145 /* 1 2 3 4 5 6 7 8 9 a b c d e f */
146 0, 15, 0, 0, 0, 0, 8, 0, 0, 0, 0, 0, 6, 0, 0, 0,
147 8, 8, 8, 19, 13, 0, 44, 0, 0, 0, 0, 17, 11, 0, 14, 0,
148 30, 0, 0, 0, 0, 0, 0, 0, 5, 8, 17, 0, 0, 5, 6, 0,
149 23, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 5, 5, 39,
152 static int ari64_init()
154 extern void (*psxCP2[64])();
155 extern void psxNULL();
159 new_dyna_pcsx_mem_init();
161 for (i = 0; i < ARRAY_SIZE(gte_handlers); i++)
162 if (psxCP2[i] != psxNULL)
163 gte_handlers[i] = psxCP2[i];
164 #if defined(__arm__) && !defined(DRC_DBG)
165 gte_handlers[0x01] = gteRTPS_neon;
166 gte_handlers[0x30] = gteRTPT_neon;
167 gte_handlers[0x12] = gteMVMVA_neon;
168 gte_handlers[0x06] = gteNCLIP_neon;
175 static void ari64_reset()
177 printf("ari64_reset\n");
178 new_dyna_pcsx_mem_reset();
179 invalidate_all_pages();
181 pending_exception = 1;
184 // execute until predefined leave points
185 // (HLE softcall exit and BIOS fastboot end)
186 static void ari64_execute_until()
188 schedule_timeslice();
190 evprintf("ari64_execute %08x, %u->%u (%d)\n", psxRegs.pc,
191 psxRegs.cycle, next_interupt, next_interupt - psxRegs.cycle);
195 evprintf("ari64_execute end %08x, %u->%u (%d)\n", psxRegs.pc,
196 psxRegs.cycle, next_interupt, next_interupt - psxRegs.cycle);
199 static void ari64_execute()
202 ari64_execute_until();
203 evprintf("drc left @%08x\n", psxRegs.pc);
207 static void ari64_clear(u32 addr, u32 size)
209 u32 start, end, main_ram;
211 size *= 4; /* PCSX uses DMA units */
213 evprintf("ari64_clear %08x %04x\n", addr, size);
215 /* check for RAM mirrors */
216 main_ram = (addr & 0xffe00000) == 0x80000000;
219 end = (addr + size) >> 12;
221 for (; start <= end; start++)
222 if (!main_ram || !invalid_code[start])
223 invalidate_block(start);
226 static void ari64_shutdown()
228 new_dynarec_cleanup();
231 extern void intExecute();
232 extern void intExecuteT();
233 extern void intExecuteBlock();
234 extern void intExecuteBlockT();
236 #define intExecuteT intExecute
237 #define intExecuteBlockT intExecuteBlock
256 void do_insn_trace() {}
257 void do_insn_cmp() {}
260 #if defined(__x86_64__) || defined(__i386__)
261 unsigned int address, readmem_word, word;
262 unsigned short hword;
264 int pending_exception, stop;
265 unsigned int next_interupt;
267 void new_dynarec_init() {}
268 void new_dyna_start() {}
269 void new_dynarec_cleanup() {}
270 void new_dynarec_clear_full() {}
271 void invalidate_all_pages() {}
272 void invalidate_block(unsigned int block) {}
273 void new_dyna_pcsx_mem_init(void) {}
274 void new_dyna_pcsx_mem_reset(void) {}
281 extern u32 last_io_addr;
283 static void dump_mem(const char *fname, void *mem, size_t size)
285 FILE *f1 = fopen(fname, "wb");
287 f1 = fopen(strrchr(fname, '/') + 1, "wb");
288 fwrite(mem, 1, size, f1);
292 static u32 memcheck_read(u32 a)
294 if ((a >> 16) == 0x1f80)
296 return *(u32 *)(psxH + (a & 0xfffc));
298 if ((a >> 16) == 0x1f00)
300 return *(u32 *)(psxP + (a & 0xfffc));
302 // if ((a & ~0xe0600000) < 0x200000)
304 return *(u32 *)(psxM + (a & 0x1ffffc));
307 void do_insn_trace(void)
309 static psxRegisters oldregs;
310 static u32 old_io_addr = (u32)-1;
311 static u32 old_io_data = 0xbad0c0de;
312 u32 *allregs_p = (void *)&psxRegs;
313 u32 *allregs_o = (void *)&oldregs;
318 //last_io_addr = 0x5e2c8;
320 f = fopen("tracelog", "wb");
322 oldregs.code = psxRegs.code; // don't care
323 for (i = 0; i < offsetof(psxRegisters, intCycle) / 4; i++) {
324 if (allregs_p[i] != allregs_o[i]) {
326 fwrite(&allregs_p[i], 1, 4, f);
327 allregs_o[i] = allregs_p[i];
330 if (old_io_addr != last_io_addr) {
332 fwrite(&byte, 1, 1, f);
333 fwrite(&last_io_addr, 1, 4, f);
334 old_io_addr = last_io_addr;
336 io_data = memcheck_read(last_io_addr);
337 if (old_io_data != io_data) {
339 fwrite(&byte, 1, 1, f);
340 fwrite(&io_data, 1, 4, f);
341 old_io_data = io_data;
344 fwrite(&byte, 1, 1, f);
347 if (psxRegs.cycle == 190230) {
348 dump_mem("/mnt/ntz/dev/pnd/tmp/psxram_i.dump", psxM, 0x200000);
349 dump_mem("/mnt/ntz/dev/pnd/tmp/psxregs_i.dump", psxH, 0x10000);
356 static const char *regnames[offsetof(psxRegisters, intCycle) / 4] = {
357 "r0", "r1", "r2", "r3", "r4", "r5", "r6", "r7",
358 "r8", "r9", "r10", "r11", "r12", "r13", "r14", "r15",
359 "r16", "r17", "r18", "r19", "r20", "r21", "r22", "r23",
360 "r24", "r25", "r26", "r27", "r28", "r29", "r30", "r31",
362 "C0_0", "C0_1", "C0_2", "C0_3", "C0_4", "C0_5", "C0_6", "C0_7",
363 "C0_8", "C0_9", "C0_10", "C0_11", "C0_12", "C0_13", "C0_14", "C0_15",
364 "C0_16", "C0_17", "C0_18", "C0_19", "C0_20", "C0_21", "C0_22", "C0_23",
365 "C0_24", "C0_25", "C0_26", "C0_27", "C0_28", "C0_29", "C0_30", "C0_31",
367 "C2D0", "C2D1", "C2D2", "C2D3", "C2D4", "C2D5", "C2D6", "C2D7",
368 "C2D8", "C2D9", "C2D10", "C2D11", "C2D12", "C2D13", "C2D14", "C2D15",
369 "C2D16", "C2D17", "C2D18", "C2D19", "C2D20", "C2D21", "C2D22", "C2D23",
370 "C2D24", "C2D25", "C2D26", "C2D27", "C2D28", "C2D29", "C2D30", "C2D31",
372 "C2C0", "C2C1", "C2C2", "C2C3", "C2C4", "C2C5", "C2C6", "C2C7",
373 "C2C8", "C2C9", "C2C10", "C2C11", "C2C12", "C2C13", "C2C14", "C2C15",
374 "C2C16", "C2C17", "C2C18", "C2C19", "C2C20", "C2C21", "C2C22", "C2C23",
375 "C2C24", "C2C25", "C2C26", "C2C27", "C2C28", "C2C29", "C2C30", "C2C31",
377 "PC", "code", "cycle", "interrupt",
385 static int miss_log_i;
386 #define miss_log_len (sizeof(miss_log)/sizeof(miss_log[0]))
387 #define miss_log_mask (miss_log_len-1)
389 static void miss_log_add(int reg, u32 val, u32 val_expect, u32 pc, u32 cycle)
391 miss_log[miss_log_i].reg = reg;
392 miss_log[miss_log_i].val = val;
393 miss_log[miss_log_i].val_expect = val_expect;
394 miss_log[miss_log_i].pc = pc;
395 miss_log[miss_log_i].cycle = cycle;
396 miss_log_i = (miss_log_i + 1) & miss_log_mask;
401 void do_insn_cmp(void)
403 static psxRegisters rregs;
404 static u32 mem_addr, mem_val;
405 u32 *allregs_p = (void *)&psxRegs;
406 u32 *allregs_e = (void *)&rregs;
407 static u32 ppc, failcount;
412 f = fopen("tracelog", "rb");
415 if ((ret = fread(&code, 1, 1, f)) <= 0)
422 if ((ret = fread(&mem_addr, 1, 4, f)) <= 0)
427 if ((ret = fread(&mem_val, 1, 4, f)) <= 0)
431 if ((ret = fread(&allregs_e[code], 1, 4, f)) <= 0)
440 psxRegs.code = rregs.code; // don't care
441 psxRegs.cycle = rregs.cycle;
442 psxRegs.CP0.r[9] = rregs.CP0.r[9]; // Count
444 //if (psxRegs.cycle == 166172) breakme();
446 if (memcmp(&psxRegs, &rregs, offsetof(psxRegisters, intCycle)) == 0 &&
447 mem_val == memcheck_read(mem_addr)
453 for (i = 0; i < offsetof(psxRegisters, intCycle) / 4; i++) {
454 if (allregs_p[i] != allregs_e[i]) {
455 miss_log_add(i, allregs_p[i], allregs_e[i], psxRegs.pc, psxRegs.cycle);
460 if (mem_val != memcheck_read(mem_addr)) {
461 printf("bad mem @%08x: %08x %08x\n", mem_addr, memcheck_read(mem_addr), mem_val);
465 if (psxRegs.pc == rregs.pc && bad < 6 && failcount < 32) {
466 static int last_mcycle;
467 if (last_mcycle != psxRegs.cycle >> 20) {
468 printf("%u\n", psxRegs.cycle);
469 last_mcycle = psxRegs.cycle >> 20;
476 for (i = 0; i < miss_log_len; i++, miss_log_i = (miss_log_i + 1) & miss_log_mask)
477 printf("bad %5s: %08x %08x, pc=%08x, cycle %u\n",
478 regnames[miss_log[miss_log_i].reg], miss_log[miss_log_i].val,
479 miss_log[miss_log_i].val_expect, miss_log[miss_log_i].pc, miss_log[miss_log_i].cycle);
480 printf("-- %d\n", bad);
481 for (i = 0; i < 8; i++)
482 printf("r%d=%08x r%2d=%08x r%2d=%08x r%2d=%08x\n", i, allregs_p[i],
483 i+8, allregs_p[i+8], i+16, allregs_p[i+16], i+24, allregs_p[i+24]);
484 printf("PC: %08x/%08x, cycle %u\n", psxRegs.pc, ppc, psxRegs.cycle);
485 dump_mem("/mnt/ntz/dev/pnd/tmp/psxram.dump", psxM, 0x200000);
486 dump_mem("/mnt/ntz/dev/pnd/tmp/psxregs.dump", psxH, 0x10000);
489 psxRegs.cycle = rregs.cycle + 2; // sync timing