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];
166 gte_handlers[0x01] = gteRTPS_neon;
167 gte_handlers[0x30] = gteRTPT_neon;
168 gte_handlers[0x12] = gteMVMVA_neon;
169 gte_handlers[0x06] = gteNCLIP_neon;
177 static void ari64_reset()
179 printf("ari64_reset\n");
180 new_dyna_pcsx_mem_reset();
181 invalidate_all_pages();
183 pending_exception = 1;
186 // execute until predefined leave points
187 // (HLE softcall exit and BIOS fastboot end)
188 static void ari64_execute_until()
190 schedule_timeslice();
192 evprintf("ari64_execute %08x, %u->%u (%d)\n", psxRegs.pc,
193 psxRegs.cycle, next_interupt, next_interupt - psxRegs.cycle);
197 evprintf("ari64_execute end %08x, %u->%u (%d)\n", psxRegs.pc,
198 psxRegs.cycle, next_interupt, next_interupt - psxRegs.cycle);
201 static void ari64_execute()
204 ari64_execute_until();
205 evprintf("drc left @%08x\n", psxRegs.pc);
209 static void ari64_clear(u32 addr, u32 size)
211 u32 start, end, main_ram;
213 size *= 4; /* PCSX uses DMA units */
215 evprintf("ari64_clear %08x %04x\n", addr, size);
217 /* check for RAM mirrors */
218 main_ram = (addr & 0xffe00000) == 0x80000000;
221 end = (addr + size) >> 12;
223 for (; start <= end; start++)
224 if (!main_ram || !invalid_code[start])
225 invalidate_block(start);
228 static void ari64_shutdown()
230 new_dynarec_cleanup();
233 extern void intExecute();
234 extern void intExecuteT();
235 extern void intExecuteBlock();
236 extern void intExecuteBlockT();
238 #define intExecuteT intExecute
239 #define intExecuteBlockT intExecuteBlock
258 void do_insn_trace() {}
259 void do_insn_cmp() {}
262 #if defined(__x86_64__) || defined(__i386__)
263 unsigned int address, readmem_word, word;
264 unsigned short hword;
266 int pending_exception, stop;
267 unsigned int next_interupt;
269 void new_dynarec_init() {}
270 void new_dyna_start() {}
271 void new_dynarec_cleanup() {}
272 void new_dynarec_clear_full() {}
273 void invalidate_all_pages() {}
274 void invalidate_block(unsigned int block) {}
275 void new_dyna_pcsx_mem_init(void) {}
276 void new_dyna_pcsx_mem_reset(void) {}
283 extern u32 last_io_addr;
285 static void dump_mem(const char *fname, void *mem, size_t size)
287 FILE *f1 = fopen(fname, "wb");
289 f1 = fopen(strrchr(fname, '/') + 1, "wb");
290 fwrite(mem, 1, size, f1);
294 static u32 memcheck_read(u32 a)
296 if ((a >> 16) == 0x1f80)
298 return *(u32 *)(psxH + (a & 0xfffc));
300 if ((a >> 16) == 0x1f00)
302 return *(u32 *)(psxP + (a & 0xfffc));
304 // if ((a & ~0xe0600000) < 0x200000)
306 return *(u32 *)(psxM + (a & 0x1ffffc));
309 void do_insn_trace(void)
311 static psxRegisters oldregs;
312 static u32 old_io_addr = (u32)-1;
313 static u32 old_io_data = 0xbad0c0de;
314 u32 *allregs_p = (void *)&psxRegs;
315 u32 *allregs_o = (void *)&oldregs;
320 //last_io_addr = 0x5e2c8;
322 f = fopen("tracelog", "wb");
324 oldregs.code = psxRegs.code; // don't care
325 for (i = 0; i < offsetof(psxRegisters, intCycle) / 4; i++) {
326 if (allregs_p[i] != allregs_o[i]) {
328 fwrite(&allregs_p[i], 1, 4, f);
329 allregs_o[i] = allregs_p[i];
332 if (old_io_addr != last_io_addr) {
334 fwrite(&byte, 1, 1, f);
335 fwrite(&last_io_addr, 1, 4, f);
336 old_io_addr = last_io_addr;
338 io_data = memcheck_read(last_io_addr);
339 if (old_io_data != io_data) {
341 fwrite(&byte, 1, 1, f);
342 fwrite(&io_data, 1, 4, f);
343 old_io_data = io_data;
346 fwrite(&byte, 1, 1, f);
349 if (psxRegs.cycle == 190230) {
350 dump_mem("/mnt/ntz/dev/pnd/tmp/psxram_i.dump", psxM, 0x200000);
351 dump_mem("/mnt/ntz/dev/pnd/tmp/psxregs_i.dump", psxH, 0x10000);
358 static const char *regnames[offsetof(psxRegisters, intCycle) / 4] = {
359 "r0", "r1", "r2", "r3", "r4", "r5", "r6", "r7",
360 "r8", "r9", "r10", "r11", "r12", "r13", "r14", "r15",
361 "r16", "r17", "r18", "r19", "r20", "r21", "r22", "r23",
362 "r24", "r25", "r26", "r27", "r28", "r29", "r30", "r31",
364 "C0_0", "C0_1", "C0_2", "C0_3", "C0_4", "C0_5", "C0_6", "C0_7",
365 "C0_8", "C0_9", "C0_10", "C0_11", "C0_12", "C0_13", "C0_14", "C0_15",
366 "C0_16", "C0_17", "C0_18", "C0_19", "C0_20", "C0_21", "C0_22", "C0_23",
367 "C0_24", "C0_25", "C0_26", "C0_27", "C0_28", "C0_29", "C0_30", "C0_31",
369 "C2D0", "C2D1", "C2D2", "C2D3", "C2D4", "C2D5", "C2D6", "C2D7",
370 "C2D8", "C2D9", "C2D10", "C2D11", "C2D12", "C2D13", "C2D14", "C2D15",
371 "C2D16", "C2D17", "C2D18", "C2D19", "C2D20", "C2D21", "C2D22", "C2D23",
372 "C2D24", "C2D25", "C2D26", "C2D27", "C2D28", "C2D29", "C2D30", "C2D31",
374 "C2C0", "C2C1", "C2C2", "C2C3", "C2C4", "C2C5", "C2C6", "C2C7",
375 "C2C8", "C2C9", "C2C10", "C2C11", "C2C12", "C2C13", "C2C14", "C2C15",
376 "C2C16", "C2C17", "C2C18", "C2C19", "C2C20", "C2C21", "C2C22", "C2C23",
377 "C2C24", "C2C25", "C2C26", "C2C27", "C2C28", "C2C29", "C2C30", "C2C31",
379 "PC", "code", "cycle", "interrupt",
387 static int miss_log_i;
388 #define miss_log_len (sizeof(miss_log)/sizeof(miss_log[0]))
389 #define miss_log_mask (miss_log_len-1)
391 static void miss_log_add(int reg, u32 val, u32 val_expect, u32 pc, u32 cycle)
393 miss_log[miss_log_i].reg = reg;
394 miss_log[miss_log_i].val = val;
395 miss_log[miss_log_i].val_expect = val_expect;
396 miss_log[miss_log_i].pc = pc;
397 miss_log[miss_log_i].cycle = cycle;
398 miss_log_i = (miss_log_i + 1) & miss_log_mask;
403 void do_insn_cmp(void)
405 static psxRegisters rregs;
406 static u32 mem_addr, mem_val;
407 u32 *allregs_p = (void *)&psxRegs;
408 u32 *allregs_e = (void *)&rregs;
409 static u32 ppc, failcount;
414 f = fopen("tracelog", "rb");
417 if ((ret = fread(&code, 1, 1, f)) <= 0)
424 if ((ret = fread(&mem_addr, 1, 4, f)) <= 0)
429 if ((ret = fread(&mem_val, 1, 4, f)) <= 0)
433 if ((ret = fread(&allregs_e[code], 1, 4, f)) <= 0)
442 psxRegs.code = rregs.code; // don't care
443 psxRegs.cycle = rregs.cycle;
444 psxRegs.CP0.r[9] = rregs.CP0.r[9]; // Count
446 //if (psxRegs.cycle == 166172) breakme();
448 if (memcmp(&psxRegs, &rregs, offsetof(psxRegisters, intCycle)) == 0 &&
449 mem_val == memcheck_read(mem_addr)
455 for (i = 0; i < offsetof(psxRegisters, intCycle) / 4; i++) {
456 if (allregs_p[i] != allregs_e[i]) {
457 miss_log_add(i, allregs_p[i], allregs_e[i], psxRegs.pc, psxRegs.cycle);
462 if (mem_val != memcheck_read(mem_addr)) {
463 printf("bad mem @%08x: %08x %08x\n", mem_addr, memcheck_read(mem_addr), mem_val);
467 if (psxRegs.pc == rregs.pc && bad < 6 && failcount < 32) {
468 static int last_mcycle;
469 if (last_mcycle != psxRegs.cycle >> 20) {
470 printf("%u\n", psxRegs.cycle);
471 last_mcycle = psxRegs.cycle >> 20;
478 for (i = 0; i < miss_log_len; i++, miss_log_i = (miss_log_i + 1) & miss_log_mask)
479 printf("bad %5s: %08x %08x, pc=%08x, cycle %u\n",
480 regnames[miss_log[miss_log_i].reg], miss_log[miss_log_i].val,
481 miss_log[miss_log_i].val_expect, miss_log[miss_log_i].pc, miss_log[miss_log_i].cycle);
482 printf("-- %d\n", bad);
483 for (i = 0; i < 8; i++)
484 printf("r%d=%08x r%2d=%08x r%2d=%08x r%2d=%08x\n", i, allregs_p[i],
485 i+8, allregs_p[i+8], i+16, allregs_p[i+16], i+24, allregs_p[i+24]);
486 printf("PC: %08x/%08x, cycle %u\n", psxRegs.pc, ppc, psxRegs.cycle);
487 dump_mem("/mnt/ntz/dev/pnd/tmp/psxram.dump", psxM, 0x200000);
488 dump_mem("/mnt/ntz/dev/pnd/tmp/psxregs.dump", psxH, 0x10000);
491 psxRegs.cycle = rregs.cycle + 2; // sync timing