2 * (C) GraÅžvydas "notaz" Ignotas, 2010
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"
18 #define ARRAY_SIZE(x) (sizeof(x) / sizeof(x[0]))
20 //#define evprintf printf
23 char invalid_code[0x100000];
24 u32 event_cycles[PSXINT_COUNT];
26 static void schedule_timeslice(void)
28 u32 i, c = psxRegs.cycle;
31 min = psxNextsCounter + psxNextCounter - c;
32 for (i = 0; i < ARRAY_SIZE(event_cycles); i++) {
33 dif = event_cycles[i] - c;
34 //evprintf(" ev %d\n", dif);
35 if (0 < dif && dif < min)
38 next_interupt = c + min;
41 static u32 cnt, last_cycle;
45 sum += psxRegs.cycle - last_cycle;
46 if ((cnt & 0xff) == 0)
47 printf("%u\n", (u32)(sum / cnt));
49 last_cycle = psxRegs.cycle;
53 typedef void (irq_func)();
55 static irq_func * const irq_funcs[] = {
56 [PSXINT_SIO] = sioInterrupt,
57 [PSXINT_CDR] = cdrInterrupt,
58 [PSXINT_CDREAD] = cdrReadInterrupt,
59 [PSXINT_GPUDMA] = gpuInterrupt,
60 [PSXINT_MDECOUTDMA] = mdec1Interrupt,
61 [PSXINT_SPUDMA] = spuInterrupt,
62 [PSXINT_MDECINDMA] = mdec0Interrupt,
63 [PSXINT_GPUOTCDMA] = gpuotcInterrupt,
64 [PSXINT_CDRDMA] = cdrDmaInterrupt,
65 [PSXINT_CDRLID] = cdrLidSeekInterrupt,
68 /* local dupe of psxBranchTest, using event_cycles */
69 static void irq_test(void)
71 u32 irqs = psxRegs.interrupt;
72 u32 cycle = psxRegs.cycle;
75 if ((psxRegs.cycle - psxNextsCounter) >= psxNextCounter)
78 // irq_funcs() may queue more irqs
79 psxRegs.interrupt = 0;
81 for (irq = 0, irq_bits = irqs; irq_bits != 0; irq++, irq_bits >>= 1) {
84 if ((s32)(cycle - event_cycles[irq]) >= 0) {
89 psxRegs.interrupt |= irqs;
91 if ((psxHu32(0x1070) & psxHu32(0x1074)) && (Status & 0x401) == 0x401) {
92 psxException(0x400, 0);
93 pending_exception = 1;
99 evprintf(" +ge %08x, %u->%u\n", psxRegs.pc, psxRegs.cycle, next_interupt);
106 //pending_exception = 1;
108 schedule_timeslice();
110 evprintf(" -ge %08x, %u->%u (%d)\n", psxRegs.pc, psxRegs.cycle,
111 next_interupt, next_interupt - psxRegs.cycle);
115 extern void MTC0(int reg, u32 val);
117 void pcsx_mtc0(u32 reg)
119 evprintf("MTC0 %d #%x @%08x %u\n", reg, readmem_word, psxRegs.pc, psxRegs.cycle);
120 MTC0(reg, readmem_word);
124 void pcsx_mtc0_ds(u32 reg)
126 evprintf("MTC0 %d #%x @%08x %u\n", reg, readmem_word, psxRegs.pc, psxRegs.cycle);
127 MTC0(reg, readmem_word);
130 void new_dyna_save(void)
132 // psxRegs.intCycle is always maintained, no need to convert
135 void new_dyna_restore(void)
138 for (i = 0; i < PSXINT_COUNT; i++)
139 event_cycles[i] = psxRegs.intCycle[i].sCycle + psxRegs.intCycle[i].cycle;
142 void *gte_handlers[64];
144 /* from gte.txt.. not sure if this is any good. */
145 const char gte_cycletab[64] = {
146 /* 1 2 3 4 5 6 7 8 9 a b c d e f */
147 0, 15, 0, 0, 0, 0, 8, 0, 0, 0, 0, 0, 6, 0, 0, 0,
148 8, 8, 8, 19, 13, 0, 44, 0, 0, 0, 0, 17, 11, 0, 14, 0,
149 30, 0, 0, 0, 0, 0, 0, 0, 5, 8, 17, 0, 0, 5, 6, 0,
150 23, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 5, 5, 39,
153 static int ari64_init()
155 extern void (*psxCP2[64])();
156 extern void psxNULL();
157 extern void *psxH_ptr;
161 new_dyna_pcsx_mem_init();
163 for (i = 0; i < ARRAY_SIZE(gte_handlers); i++)
164 if (psxCP2[i] != psxNULL)
165 gte_handlers[i] = psxCP2[i];
172 static void ari64_reset()
174 printf("ari64_reset\n");
175 new_dyna_pcsx_mem_reset();
176 invalidate_all_pages();
177 pending_exception = 1;
180 // execute until predefined leave points
181 // (HLE softcall exit and BIOS fastboot end)
182 static void ari64_execute_until()
184 schedule_timeslice();
186 evprintf("ari64_execute %08x, %u->%u (%d)\n", psxRegs.pc,
187 psxRegs.cycle, next_interupt, next_interupt - psxRegs.cycle);
191 evprintf("ari64_execute end %08x, %u->%u (%d)\n", psxRegs.pc,
192 psxRegs.cycle, next_interupt, next_interupt - psxRegs.cycle);
195 static void ari64_execute()
198 ari64_execute_until();
199 evprintf("drc left @%08x\n", psxRegs.pc);
203 static void ari64_clear(u32 addr, u32 size)
205 u32 start, end, main_ram;
207 size *= 4; /* PCSX uses DMA units */
209 evprintf("ari64_clear %08x %04x\n", addr, size);
211 /* check for RAM mirrors */
212 main_ram = (addr & 0xffe00000) == 0x80000000;
215 end = (addr + size) >> 12;
217 for (; start <= end; start++)
218 if (!main_ram || !invalid_code[start])
219 invalidate_block(start);
222 static void ari64_shutdown()
224 new_dynarec_cleanup();
227 extern void intExecute();
228 extern void intExecuteT();
229 extern void intExecuteBlock();
230 extern void intExecuteBlockT();
232 #define intExecuteT intExecute
233 #define intExecuteBlockT intExecuteBlock
252 void do_insn_trace() {}
253 void do_insn_cmp() {}
256 #if defined(__x86_64__) || defined(__i386__)
257 unsigned int address, readmem_word, word;
258 unsigned short hword;
260 int pending_exception, stop;
261 unsigned int next_interupt;
263 void new_dynarec_init() {}
264 void new_dyna_start() {}
265 void new_dynarec_cleanup() {}
266 void invalidate_all_pages() {}
267 void invalidate_block(unsigned int block) {}
268 void new_dyna_pcsx_mem_init(void) {}
269 void new_dyna_pcsx_mem_reset(void) {}
276 extern u32 last_io_addr;
278 static void dump_mem(const char *fname, void *mem, size_t size)
280 FILE *f1 = fopen(fname, "wb");
282 f1 = fopen(strrchr(fname, '/') + 1, "wb");
283 fwrite(mem, 1, size, f1);
287 static u32 memcheck_read(u32 a)
289 if ((a >> 16) == 0x1f80)
291 return *(u32 *)(psxH + (a & 0xfffc));
293 if ((a >> 16) == 0x1f00)
295 return *(u32 *)(psxP + (a & 0xfffc));
297 // if ((a & ~0xe0600000) < 0x200000)
299 return *(u32 *)(psxM + (a & 0x1ffffc));
302 void do_insn_trace(void)
304 static psxRegisters oldregs;
305 static u32 old_io_addr = (u32)-1;
306 static u32 old_io_data = 0xbad0c0de;
307 u32 *allregs_p = (void *)&psxRegs;
308 u32 *allregs_o = (void *)&oldregs;
313 //last_io_addr = 0x5e2c8;
315 f = fopen("tracelog", "wb");
317 oldregs.code = psxRegs.code; // don't care
318 for (i = 0; i < offsetof(psxRegisters, intCycle) / 4; i++) {
319 if (allregs_p[i] != allregs_o[i]) {
321 fwrite(&allregs_p[i], 1, 4, f);
322 allregs_o[i] = allregs_p[i];
325 if (old_io_addr != last_io_addr) {
327 fwrite(&byte, 1, 1, f);
328 fwrite(&last_io_addr, 1, 4, f);
329 old_io_addr = last_io_addr;
331 io_data = memcheck_read(last_io_addr);
332 if (old_io_data != io_data) {
334 fwrite(&byte, 1, 1, f);
335 fwrite(&io_data, 1, 4, f);
336 old_io_data = io_data;
339 fwrite(&byte, 1, 1, f);
342 if (psxRegs.cycle == 190230) {
343 dump_mem("/mnt/ntz/dev/pnd/tmp/psxram_i.dump", psxM, 0x200000);
344 dump_mem("/mnt/ntz/dev/pnd/tmp/psxregs_i.dump", psxH, 0x10000);
351 static const char *regnames[offsetof(psxRegisters, intCycle) / 4] = {
352 "r0", "r1", "r2", "r3", "r4", "r5", "r6", "r7",
353 "r8", "r9", "r10", "r11", "r12", "r13", "r14", "r15",
354 "r16", "r17", "r18", "r19", "r20", "r21", "r22", "r23",
355 "r24", "r25", "r26", "r27", "r28", "r29", "r30", "r31",
357 "C0_0", "C0_1", "C0_2", "C0_3", "C0_4", "C0_5", "C0_6", "C0_7",
358 "C0_8", "C0_9", "C0_10", "C0_11", "C0_12", "C0_13", "C0_14", "C0_15",
359 "C0_16", "C0_17", "C0_18", "C0_19", "C0_20", "C0_21", "C0_22", "C0_23",
360 "C0_24", "C0_25", "C0_26", "C0_27", "C0_28", "C0_29", "C0_30", "C0_31",
362 "C2D0", "C2D1", "C2D2", "C2D3", "C2D4", "C2D5", "C2D6", "C2D7",
363 "C2D8", "C2D9", "C2D10", "C2D11", "C2D12", "C2D13", "C2D14", "C2D15",
364 "C2D16", "C2D17", "C2D18", "C2D19", "C2D20", "C2D21", "C2D22", "C2D23",
365 "C2D24", "C2D25", "C2D26", "C2D27", "C2D28", "C2D29", "C2D30", "C2D31",
367 "C2C0", "C2C1", "C2C2", "C2C3", "C2C4", "C2C5", "C2C6", "C2C7",
368 "C2C8", "C2C9", "C2C10", "C2C11", "C2C12", "C2C13", "C2C14", "C2C15",
369 "C2C16", "C2C17", "C2C18", "C2C19", "C2C20", "C2C21", "C2C22", "C2C23",
370 "C2C24", "C2C25", "C2C26", "C2C27", "C2C28", "C2C29", "C2C30", "C2C31",
372 "PC", "code", "cycle", "interrupt",
380 static int miss_log_i;
381 #define miss_log_len (sizeof(miss_log)/sizeof(miss_log[0]))
382 #define miss_log_mask (miss_log_len-1)
384 static void miss_log_add(int reg, u32 val, u32 val_expect, u32 pc, u32 cycle)
386 miss_log[miss_log_i].reg = reg;
387 miss_log[miss_log_i].val = val;
388 miss_log[miss_log_i].val_expect = val_expect;
389 miss_log[miss_log_i].pc = pc;
390 miss_log[miss_log_i].cycle = cycle;
391 miss_log_i = (miss_log_i + 1) & miss_log_mask;
396 void do_insn_cmp(void)
398 static psxRegisters rregs;
399 static u32 mem_addr, mem_val;
400 u32 *allregs_p = (void *)&psxRegs;
401 u32 *allregs_e = (void *)&rregs;
402 static u32 ppc, failcount;
407 f = fopen("tracelog", "rb");
410 if ((ret = fread(&code, 1, 1, f)) <= 0)
417 if ((ret = fread(&mem_addr, 1, 4, f)) <= 0)
422 if ((ret = fread(&mem_val, 1, 4, f)) <= 0)
426 if ((ret = fread(&allregs_e[code], 1, 4, f)) <= 0)
435 psxRegs.code = rregs.code; // don't care
436 psxRegs.cycle = rregs.cycle;
437 psxRegs.CP0.r[9] = rregs.CP0.r[9]; // Count
439 //if (psxRegs.cycle == 166172) breakme();
441 if (memcmp(&psxRegs, &rregs, offsetof(psxRegisters, intCycle)) == 0 &&
442 mem_val == memcheck_read(mem_addr)
448 for (i = 0; i < offsetof(psxRegisters, intCycle) / 4; i++) {
449 if (allregs_p[i] != allregs_e[i]) {
450 miss_log_add(i, allregs_p[i], allregs_e[i], psxRegs.pc, psxRegs.cycle);
455 if (mem_val != memcheck_read(mem_addr)) {
456 printf("bad mem @%08x: %08x %08x\n", mem_addr, memcheck_read(mem_addr), mem_val);
460 if (psxRegs.pc == rregs.pc && bad < 6 && failcount < 32) {
461 static int last_mcycle;
462 if (last_mcycle != psxRegs.cycle >> 20) {
463 printf("%u\n", psxRegs.cycle);
464 last_mcycle = psxRegs.cycle >> 20;
471 for (i = 0; i < miss_log_len; i++, miss_log_i = (miss_log_i + 1) & miss_log_mask)
472 printf("bad %5s: %08x %08x, pc=%08x, cycle %u\n",
473 regnames[miss_log[miss_log_i].reg], miss_log[miss_log_i].val,
474 miss_log[miss_log_i].val_expect, miss_log[miss_log_i].pc, miss_log[miss_log_i].cycle);
475 printf("-- %d\n", bad);
476 for (i = 0; i < 8; i++)
477 printf("r%d=%08x r%2d=%08x r%2d=%08x r%2d=%08x\n", i, allregs_p[i],
478 i+8, allregs_p[i+8], i+16, allregs_p[i+16], i+24, allregs_p[i+24]);
479 printf("PC: %08x/%08x, cycle %u\n", psxRegs.pc, ppc, psxRegs.cycle);
480 dump_mem("/mnt/ntz/dev/pnd/tmp/psxram.dump", psxM, 0x200000);
481 dump_mem("/mnt/ntz/dev/pnd/tmp/psxregs.dump", psxH, 0x10000);
484 psxRegs.cycle = rregs.cycle + 2; // sync timing