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,
66 /* local dupe of psxBranchTest, using event_cycles */
67 static void irq_test(void)
69 u32 irqs = psxRegs.interrupt;
70 u32 cycle = psxRegs.cycle;
73 if ((psxRegs.cycle - psxNextsCounter) >= psxNextCounter)
76 // irq_funcs() may queue more irqs
77 psxRegs.interrupt = 0;
79 for (irq = 0, irq_bits = irqs; irq_bits != 0; irq++, irq_bits >>= 1) {
82 if ((s32)(cycle - event_cycles[irq]) >= 0) {
87 psxRegs.interrupt |= irqs;
89 if ((psxHu32(0x1070) & psxHu32(0x1074)) && (Status & 0x401) == 0x401) {
90 psxException(0x400, 0);
91 pending_exception = 1;
97 evprintf(" +ge %08x, %u->%u\n", psxRegs.pc, psxRegs.cycle, next_interupt);
104 //pending_exception = 1;
106 schedule_timeslice();
108 evprintf(" -ge %08x, %u->%u (%d)\n", psxRegs.pc, psxRegs.cycle,
109 next_interupt, next_interupt - psxRegs.cycle);
113 extern void MTC0(int reg, u32 val);
115 void pcsx_mtc0(u32 reg)
117 evprintf("MTC0 %d #%x @%08x %u\n", reg, readmem_word, psxRegs.pc, psxRegs.cycle);
118 MTC0(reg, readmem_word);
122 void pcsx_mtc0_ds(u32 reg)
124 evprintf("MTC0 %d #%x @%08x %u\n", reg, readmem_word, psxRegs.pc, psxRegs.cycle);
125 MTC0(reg, readmem_word);
128 void new_dyna_save(void)
130 // psxRegs.intCycle is always maintained, no need to convert
133 void new_dyna_restore(void)
136 for (i = 0; i < PSXINT_NEWDRC_CHECK; i++)
137 event_cycles[i] = psxRegs.intCycle[i].sCycle + psxRegs.intCycle[i].cycle;
140 void *gte_handlers[64];
142 /* from gte.txt.. not sure if this is any good. */
143 const char gte_cycletab[64] = {
144 /* 1 2 3 4 5 6 7 8 9 a b c d e f */
145 0, 15, 0, 0, 0, 0, 8, 0, 0, 0, 0, 0, 6, 0, 0, 0,
146 8, 8, 8, 19, 13, 0, 44, 0, 0, 0, 0, 17, 11, 0, 14, 0,
147 30, 0, 0, 0, 0, 0, 0, 0, 5, 8, 17, 0, 0, 5, 6, 0,
148 23, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 5, 5, 39,
151 static int ari64_init()
153 extern void (*psxCP2[64])();
154 extern void psxNULL();
155 extern void *psxH_ptr;
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];
170 static void ari64_reset()
172 printf("ari64_reset\n");
173 new_dyna_pcsx_mem_reset();
174 invalidate_all_pages();
175 pending_exception = 1;
178 static void ari64_execute()
180 schedule_timeslice();
182 evprintf("ari64_execute %08x, %u->%u (%d)\n", psxRegs.pc,
183 psxRegs.cycle, next_interupt, next_interupt - psxRegs.cycle);
187 evprintf("ari64_execute end %08x, %u->%u (%d)\n", psxRegs.pc,
188 psxRegs.cycle, next_interupt, next_interupt - psxRegs.cycle);
191 static void ari64_clear(u32 addr, u32 size)
195 size *= 4; /* PCSX uses DMA units */
197 evprintf("ari64_clear %08x %04x\n", addr, size);
199 /* check for RAM mirrors */
200 if ((addr & ~0xe0600000) < 0x200000) {
206 end = (addr + size) >> 12;
208 for (; start <= end; start++)
209 if (!invalid_code[start])
210 invalidate_block(start);
213 static void ari64_shutdown()
215 new_dynarec_cleanup();
218 extern void intExecute();
219 extern void intExecuteT();
220 extern void intExecuteBlock();
221 extern void intExecuteBlockT();
223 #define intExecuteT intExecute
224 #define intExecuteBlockT intExecuteBlock
243 void do_insn_trace() {}
244 void do_insn_cmp() {}
247 #if defined(__x86_64__) || defined(__i386__)
248 unsigned int address, readmem_word, word;
249 unsigned short hword;
251 int pending_exception, stop;
252 unsigned int next_interupt;
254 void new_dynarec_init() {}
255 void new_dyna_start() {}
256 void new_dynarec_cleanup() {}
257 void invalidate_all_pages() {}
258 void invalidate_block(unsigned int block) {}
259 void new_dyna_pcsx_mem_init(void) {}
260 void new_dyna_pcsx_mem_reset(void) {}
267 extern u32 last_io_addr;
269 static void dump_mem(const char *fname, void *mem, size_t size)
271 FILE *f1 = fopen(fname, "wb");
273 f1 = fopen(strrchr(fname, '/') + 1, "wb");
274 fwrite(mem, 1, size, f1);
278 static u32 memcheck_read(u32 a)
280 if ((a >> 16) == 0x1f80)
282 return *(u32 *)(psxH + (a & 0xfffc));
284 if ((a >> 16) == 0x1f00)
286 return *(u32 *)(psxP + (a & 0xfffc));
288 // if ((a & ~0xe0600000) < 0x200000)
290 return *(u32 *)(psxM + (a & 0x1ffffc));
293 void do_insn_trace(void)
295 static psxRegisters oldregs;
296 static u32 old_io_addr = (u32)-1;
297 static u32 old_io_data = 0xbad0c0de;
298 u32 *allregs_p = (void *)&psxRegs;
299 u32 *allregs_o = (void *)&oldregs;
304 //last_io_addr = 0x5e2c8;
306 f = fopen("tracelog", "wb");
308 oldregs.code = psxRegs.code; // don't care
309 for (i = 0; i < offsetof(psxRegisters, intCycle) / 4; i++) {
310 if (allregs_p[i] != allregs_o[i]) {
312 fwrite(&allregs_p[i], 1, 4, f);
313 allregs_o[i] = allregs_p[i];
316 if (old_io_addr != last_io_addr) {
318 fwrite(&byte, 1, 1, f);
319 fwrite(&last_io_addr, 1, 4, f);
320 old_io_addr = last_io_addr;
322 io_data = memcheck_read(last_io_addr);
323 if (old_io_data != io_data) {
325 fwrite(&byte, 1, 1, f);
326 fwrite(&io_data, 1, 4, f);
327 old_io_data = io_data;
330 fwrite(&byte, 1, 1, f);
333 if (psxRegs.cycle == 190230) {
334 dump_mem("/mnt/ntz/dev/pnd/tmp/psxram_i.dump", psxM, 0x200000);
335 dump_mem("/mnt/ntz/dev/pnd/tmp/psxregs_i.dump", psxH, 0x10000);
342 static const char *regnames[offsetof(psxRegisters, intCycle) / 4] = {
343 "r0", "r1", "r2", "r3", "r4", "r5", "r6", "r7",
344 "r8", "r9", "r10", "r11", "r12", "r13", "r14", "r15",
345 "r16", "r17", "r18", "r19", "r20", "r21", "r22", "r23",
346 "r24", "r25", "r26", "r27", "r28", "r29", "r30", "r31",
348 "C0_0", "C0_1", "C0_2", "C0_3", "C0_4", "C0_5", "C0_6", "C0_7",
349 "C0_8", "C0_9", "C0_10", "C0_11", "C0_12", "C0_13", "C0_14", "C0_15",
350 "C0_16", "C0_17", "C0_18", "C0_19", "C0_20", "C0_21", "C0_22", "C0_23",
351 "C0_24", "C0_25", "C0_26", "C0_27", "C0_28", "C0_29", "C0_30", "C0_31",
353 "C2D0", "C2D1", "C2D2", "C2D3", "C2D4", "C2D5", "C2D6", "C2D7",
354 "C2D8", "C2D9", "C2D10", "C2D11", "C2D12", "C2D13", "C2D14", "C2D15",
355 "C2D16", "C2D17", "C2D18", "C2D19", "C2D20", "C2D21", "C2D22", "C2D23",
356 "C2D24", "C2D25", "C2D26", "C2D27", "C2D28", "C2D29", "C2D30", "C2D31",
358 "C2C0", "C2C1", "C2C2", "C2C3", "C2C4", "C2C5", "C2C6", "C2C7",
359 "C2C8", "C2C9", "C2C10", "C2C11", "C2C12", "C2C13", "C2C14", "C2C15",
360 "C2C16", "C2C17", "C2C18", "C2C19", "C2C20", "C2C21", "C2C22", "C2C23",
361 "C2C24", "C2C25", "C2C26", "C2C27", "C2C28", "C2C29", "C2C30", "C2C31",
363 "PC", "code", "cycle", "interrupt",
371 static int miss_log_i;
372 #define miss_log_len (sizeof(miss_log)/sizeof(miss_log[0]))
373 #define miss_log_mask (miss_log_len-1)
375 static void miss_log_add(int reg, u32 val, u32 val_expect, u32 pc, u32 cycle)
377 miss_log[miss_log_i].reg = reg;
378 miss_log[miss_log_i].val = val;
379 miss_log[miss_log_i].val_expect = val_expect;
380 miss_log[miss_log_i].pc = pc;
381 miss_log[miss_log_i].cycle = cycle;
382 miss_log_i = (miss_log_i + 1) & miss_log_mask;
387 void do_insn_cmp(void)
389 static psxRegisters rregs;
390 static u32 mem_addr, mem_val;
391 u32 *allregs_p = (void *)&psxRegs;
392 u32 *allregs_e = (void *)&rregs;
393 static u32 ppc, failcount;
398 f = fopen("tracelog", "rb");
401 if ((ret = fread(&code, 1, 1, f)) <= 0)
408 if ((ret = fread(&mem_addr, 1, 4, f)) <= 0)
413 if ((ret = fread(&mem_val, 1, 4, f)) <= 0)
417 if ((ret = fread(&allregs_e[code], 1, 4, f)) <= 0)
426 psxRegs.code = rregs.code; // don't care
427 psxRegs.cycle = rregs.cycle;
428 psxRegs.CP0.r[9] = rregs.CP0.r[9]; // Count
430 //if (psxRegs.cycle == 166172) breakme();
432 if (memcmp(&psxRegs, &rregs, offsetof(psxRegisters, intCycle)) == 0 &&
433 mem_val == memcheck_read(mem_addr)
439 for (i = 0; i < offsetof(psxRegisters, intCycle) / 4; i++) {
440 if (allregs_p[i] != allregs_e[i]) {
441 miss_log_add(i, allregs_p[i], allregs_e[i], psxRegs.pc, psxRegs.cycle);
446 if (mem_val != memcheck_read(mem_addr)) {
447 printf("bad mem @%08x: %08x %08x\n", mem_addr, memcheck_read(mem_addr), mem_val);
451 if (psxRegs.pc == rregs.pc && bad < 6 && failcount < 32) {
452 static int last_mcycle;
453 if (last_mcycle != psxRegs.cycle >> 20) {
454 printf("%u\n", psxRegs.cycle);
455 last_mcycle = psxRegs.cycle >> 20;
462 for (i = 0; i < miss_log_len; i++, miss_log_i = (miss_log_i + 1) & miss_log_mask)
463 printf("bad %5s: %08x %08x, pc=%08x, cycle %u\n",
464 regnames[miss_log[miss_log_i].reg], miss_log[miss_log_i].val,
465 miss_log[miss_log_i].val_expect, miss_log[miss_log_i].pc, miss_log[miss_log_i].cycle);
466 printf("-- %d\n", bad);
467 for (i = 0; i < 8; i++)
468 printf("r%d=%08x r%2d=%08x r%2d=%08x r%2d=%08x\n", i, allregs_p[i],
469 i+8, allregs_p[i+8], i+16, allregs_p[i+16], i+24, allregs_p[i+24]);
470 printf("PC: %08x/%08x, cycle %u\n", psxRegs.pc, ppc, psxRegs.cycle);
471 dump_mem("/mnt/ntz/dev/pnd/tmp/psxram.dump", psxM, 0x200000);
472 dump_mem("/mnt/ntz/dev/pnd/tmp/psxregs.dump", psxH, 0x10000);
475 psxRegs.cycle = rregs.cycle + 2; // sync timing