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 evprintf("ari64_clear %08x %04x\n", addr, size);
197 /* check for RAM mirrors */
198 if ((addr & ~0xe0600000) < 0x200000) {
204 end = (addr + size) >> 12;
206 for (; start <= end; start++)
207 if (!invalid_code[start])
208 invalidate_block(start);
211 static void ari64_shutdown()
213 new_dynarec_cleanup();
216 extern void intExecute();
217 extern void intExecuteT();
218 extern void intExecuteBlock();
219 extern void intExecuteBlockT();
221 #define intExecuteT intExecute
222 #define intExecuteBlockT intExecuteBlock
241 void do_insn_trace() {}
242 void do_insn_cmp() {}
245 #if defined(__x86_64__) || defined(__i386__)
246 unsigned int address, readmem_word, word;
247 unsigned short hword;
249 int pending_exception, stop;
250 unsigned int next_interupt;
252 void new_dynarec_init() {}
253 void new_dyna_start() {}
254 void new_dynarec_cleanup() {}
255 void invalidate_all_pages() {}
256 void invalidate_block(unsigned int block) {}
257 void new_dyna_pcsx_mem_init(void) {}
258 void new_dyna_pcsx_mem_reset(void) {}
265 extern u32 last_io_addr;
267 static void dump_mem(const char *fname, void *mem, size_t size)
269 FILE *f1 = fopen(fname, "wb");
271 f1 = fopen(strrchr(fname, '/') + 1, "wb");
272 fwrite(mem, 1, size, f1);
276 static u32 memcheck_read(u32 a)
278 if ((a >> 16) == 0x1f80)
280 return *(u32 *)(psxH + (a & 0xfffc));
282 if ((a >> 16) == 0x1f00)
284 return *(u32 *)(psxP + (a & 0xfffc));
286 // if ((a & ~0xe0600000) < 0x200000)
288 return *(u32 *)(psxM + (a & 0x1ffffc));
291 void do_insn_trace(void)
293 static psxRegisters oldregs;
294 static u32 old_io_addr = (u32)-1;
295 static u32 old_io_data = 0xbad0c0de;
296 u32 *allregs_p = (void *)&psxRegs;
297 u32 *allregs_o = (void *)&oldregs;
302 //last_io_addr = 0x5e2c8;
304 f = fopen("tracelog", "wb");
306 oldregs.code = psxRegs.code; // don't care
307 for (i = 0; i < offsetof(psxRegisters, intCycle) / 4; i++) {
308 if (allregs_p[i] != allregs_o[i]) {
310 fwrite(&allregs_p[i], 1, 4, f);
311 allregs_o[i] = allregs_p[i];
314 if (old_io_addr != last_io_addr) {
316 fwrite(&byte, 1, 1, f);
317 fwrite(&last_io_addr, 1, 4, f);
318 old_io_addr = last_io_addr;
320 io_data = memcheck_read(last_io_addr);
321 if (old_io_data != io_data) {
323 fwrite(&byte, 1, 1, f);
324 fwrite(&io_data, 1, 4, f);
325 old_io_data = io_data;
328 fwrite(&byte, 1, 1, f);
331 if (psxRegs.cycle == 190230) {
332 dump_mem("/mnt/ntz/dev/pnd/tmp/psxram_i.dump", psxM, 0x200000);
333 dump_mem("/mnt/ntz/dev/pnd/tmp/psxregs_i.dump", psxH, 0x10000);
340 static const char *regnames[offsetof(psxRegisters, intCycle) / 4] = {
341 "r0", "r1", "r2", "r3", "r4", "r5", "r6", "r7",
342 "r8", "r9", "r10", "r11", "r12", "r13", "r14", "r15",
343 "r16", "r17", "r18", "r19", "r20", "r21", "r22", "r23",
344 "r24", "r25", "r26", "r27", "r28", "r29", "r30", "r31",
346 "C0_0", "C0_1", "C0_2", "C0_3", "C0_4", "C0_5", "C0_6", "C0_7",
347 "C0_8", "C0_9", "C0_10", "C0_11", "C0_12", "C0_13", "C0_14", "C0_15",
348 "C0_16", "C0_17", "C0_18", "C0_19", "C0_20", "C0_21", "C0_22", "C0_23",
349 "C0_24", "C0_25", "C0_26", "C0_27", "C0_28", "C0_29", "C0_30", "C0_31",
351 "C2D0", "C2D1", "C2D2", "C2D3", "C2D4", "C2D5", "C2D6", "C2D7",
352 "C2D8", "C2D9", "C2D10", "C2D11", "C2D12", "C2D13", "C2D14", "C2D15",
353 "C2D16", "C2D17", "C2D18", "C2D19", "C2D20", "C2D21", "C2D22", "C2D23",
354 "C2D24", "C2D25", "C2D26", "C2D27", "C2D28", "C2D29", "C2D30", "C2D31",
356 "C2C0", "C2C1", "C2C2", "C2C3", "C2C4", "C2C5", "C2C6", "C2C7",
357 "C2C8", "C2C9", "C2C10", "C2C11", "C2C12", "C2C13", "C2C14", "C2C15",
358 "C2C16", "C2C17", "C2C18", "C2C19", "C2C20", "C2C21", "C2C22", "C2C23",
359 "C2C24", "C2C25", "C2C26", "C2C27", "C2C28", "C2C29", "C2C30", "C2C31",
361 "PC", "code", "cycle", "interrupt",
369 static int miss_log_i;
370 #define miss_log_len (sizeof(miss_log)/sizeof(miss_log[0]))
371 #define miss_log_mask (miss_log_len-1)
373 static void miss_log_add(int reg, u32 val, u32 val_expect, u32 pc, u32 cycle)
375 miss_log[miss_log_i].reg = reg;
376 miss_log[miss_log_i].val = val;
377 miss_log[miss_log_i].val_expect = val_expect;
378 miss_log[miss_log_i].pc = pc;
379 miss_log[miss_log_i].cycle = cycle;
380 miss_log_i = (miss_log_i + 1) & miss_log_mask;
385 void do_insn_cmp(void)
387 static psxRegisters rregs;
388 static u32 mem_addr, mem_val;
389 u32 *allregs_p = (void *)&psxRegs;
390 u32 *allregs_e = (void *)&rregs;
391 static u32 ppc, failcount;
396 f = fopen("tracelog", "rb");
399 if ((ret = fread(&code, 1, 1, f)) <= 0)
406 if ((ret = fread(&mem_addr, 1, 4, f)) <= 0)
411 if ((ret = fread(&mem_val, 1, 4, f)) <= 0)
415 if ((ret = fread(&allregs_e[code], 1, 4, f)) <= 0)
424 psxRegs.code = rregs.code; // don't care
425 psxRegs.cycle = rregs.cycle;
426 psxRegs.CP0.r[9] = rregs.CP0.r[9]; // Count
428 //if (psxRegs.cycle == 166172) breakme();
430 if (memcmp(&psxRegs, &rregs, offsetof(psxRegisters, intCycle)) == 0 &&
431 mem_val == memcheck_read(mem_addr)
437 for (i = 0; i < offsetof(psxRegisters, intCycle) / 4; i++) {
438 if (allregs_p[i] != allregs_e[i]) {
439 miss_log_add(i, allregs_p[i], allregs_e[i], psxRegs.pc, psxRegs.cycle);
444 if (mem_val != memcheck_read(mem_addr)) {
445 printf("bad mem @%08x: %08x %08x\n", mem_addr, memcheck_read(mem_addr), mem_val);
449 if (psxRegs.pc == rregs.pc && bad < 6 && failcount < 32) {
450 static int last_mcycle;
451 if (last_mcycle != psxRegs.cycle >> 20) {
452 printf("%u\n", psxRegs.cycle);
453 last_mcycle = psxRegs.cycle >> 20;
460 for (i = 0; i < miss_log_len; i++, miss_log_i = (miss_log_i + 1) & miss_log_mask)
461 printf("bad %5s: %08x %08x, pc=%08x, cycle %u\n",
462 regnames[miss_log[miss_log_i].reg], miss_log[miss_log_i].val,
463 miss_log[miss_log_i].val_expect, miss_log[miss_log_i].pc, miss_log[miss_log_i].cycle);
464 printf("-- %d\n", bad);
465 for (i = 0; i < 8; i++)
466 printf("r%d=%08x r%2d=%08x r%2d=%08x r%2d=%08x\n", i, allregs_p[i],
467 i+8, allregs_p[i+8], i+16, allregs_p[i+16], i+24, allregs_p[i+24]);
468 printf("PC: %08x/%08x, cycle %u\n", psxRegs.pc, ppc, psxRegs.cycle);
469 dump_mem("/mnt/ntz/dev/pnd/tmp/psxram.dump", psxM, 0x200000);
470 dump_mem("/mnt/ntz/dev/pnd/tmp/psxregs.dump", psxH, 0x10000);
473 psxRegs.cycle = rregs.cycle + 2; // sync timing