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,
65 /* local dupe of psxBranchTest, using event_cycles */
66 static void irq_test(void)
68 u32 irqs = psxRegs.interrupt;
69 u32 cycle = psxRegs.cycle;
72 if ((psxRegs.cycle - psxNextsCounter) >= psxNextCounter)
75 // irq_funcs() may queue more irqs
76 psxRegs.interrupt = 0;
78 for (irq = 0, irq_bits = irqs; irq_bits != 0; irq++, irq_bits >>= 1) {
81 if ((s32)(cycle - event_cycles[irq]) >= 0) {
86 psxRegs.interrupt |= irqs;
88 if ((psxHu32(0x1070) & psxHu32(0x1074)) && (Status & 0x401) == 0x401) {
89 psxException(0x400, 0);
90 pending_exception = 1;
96 evprintf(" +ge %08x, %u->%u\n", psxRegs.pc, psxRegs.cycle, next_interupt);
103 //pending_exception = 1;
105 schedule_timeslice();
107 evprintf(" -ge %08x, %u->%u (%d)\n", psxRegs.pc, psxRegs.cycle,
108 next_interupt, next_interupt - psxRegs.cycle);
113 extern void psxMTC0();
115 evprintf("ari64 MTC0 %08x %08x %u\n", psxRegs.code, psxRegs.pc, psxRegs.cycle);
117 gen_interupt(); /* FIXME: checking pending irqs should be enough */
120 void check_interupt()
122 /* FIXME (also asm) */
123 printf("ari64_check_interupt\n");
126 void new_dyna_save(void)
128 // psxRegs.intCycle is always maintained, no need to convert
131 void new_dyna_restore(void)
134 for (i = 0; i < PSXINT_NEWDRC_CHECK; i++)
135 event_cycles[i] = psxRegs.intCycle[i].sCycle + psxRegs.intCycle[i].cycle;
138 void *gte_handlers[64];
140 /* from gte.txt.. not sure if this is any good. */
141 const char gte_cycletab[64] = {
142 /* 1 2 3 4 5 6 7 8 9 a b c d e f */
143 0, 15, 0, 0, 0, 0, 8, 0, 0, 0, 0, 0, 6, 0, 0, 0,
144 8, 8, 8, 19, 13, 0, 44, 0, 0, 0, 0, 17, 11, 0, 14, 0,
145 30, 0, 0, 0, 0, 0, 0, 0, 5, 8, 17, 0, 0, 5, 6, 0,
146 23, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 5, 5, 39,
149 static int ari64_init()
151 extern void (*psxCP2[64])();
152 extern void psxNULL();
153 extern void *psxH_ptr;
157 new_dyna_pcsx_mem_init();
159 for (i = 0; i < ARRAY_SIZE(gte_handlers); i++)
160 if (psxCP2[i] != psxNULL)
161 gte_handlers[i] = psxCP2[i];
168 static void ari64_reset()
170 printf("ari64_reset\n");
171 new_dyna_pcsx_mem_reset();
172 invalidate_all_pages();
173 pending_exception = 1;
176 static void ari64_execute()
178 schedule_timeslice();
180 evprintf("ari64_execute %08x, %u->%u (%d)\n", psxRegs.pc,
181 psxRegs.cycle, next_interupt, next_interupt - psxRegs.cycle);
185 evprintf("ari64_execute end %08x, %u->%u (%d)\n", psxRegs.pc,
186 psxRegs.cycle, next_interupt, next_interupt - psxRegs.cycle);
189 static void ari64_clear(u32 addr, u32 size)
193 evprintf("ari64_clear %08x %04x\n", addr, size);
195 /* check for RAM mirrors */
196 if ((addr & ~0xe0600000) < 0x200000) {
202 end = (addr + size) >> 12;
204 for (; start <= end; start++)
205 if (!invalid_code[start])
206 invalidate_block(start);
209 static void ari64_shutdown()
211 new_dynarec_cleanup();
214 extern void intExecute();
215 extern void intExecuteT();
216 extern void intExecuteBlock();
217 extern void intExecuteBlockT();
219 #define intExecuteT intExecute
220 #define intExecuteBlockT intExecuteBlock
239 void do_insn_trace() {}
240 void do_insn_cmp() {}
243 #if defined(__x86_64__) || defined(__i386__)
244 unsigned int address, readmem_word, word;
245 unsigned short hword;
247 int pending_exception, stop;
248 unsigned int next_interupt;
250 void new_dynarec_init() {}
251 void new_dyna_start() {}
252 void new_dynarec_cleanup() {}
253 void invalidate_all_pages() {}
254 void invalidate_block(unsigned int block) {}
255 void new_dyna_pcsx_mem_init(void) {}
256 void new_dyna_pcsx_mem_reset(void) {}
263 extern u32 last_io_addr;
265 static void dump_mem(const char *fname, void *mem, size_t size)
267 FILE *f1 = fopen(fname, "wb");
269 f1 = fopen(strrchr(fname, '/') + 1, "wb");
270 fwrite(mem, 1, size, f1);
274 void do_insn_trace(void)
276 static psxRegisters oldregs;
277 static u32 old_io_addr = (u32)-1;
278 static u32 old_io_data = 0xbad0c0de;
279 u32 *allregs_p = (void *)&psxRegs;
280 u32 *allregs_o = (void *)&oldregs;
285 //last_io_addr = 0x5e2c8;
287 f = fopen("tracelog", "wb");
289 oldregs.code = psxRegs.code; // don't care
290 for (i = 0; i < offsetof(psxRegisters, intCycle) / 4; i++) {
291 if (allregs_p[i] != allregs_o[i]) {
293 fwrite(&allregs_p[i], 1, 4, f);
294 allregs_o[i] = allregs_p[i];
297 if (old_io_addr != last_io_addr) {
299 fwrite(&byte, 1, 1, f);
300 fwrite(&last_io_addr, 1, 4, f);
301 old_io_addr = last_io_addr;
303 io_data = (void *)(psxM + (last_io_addr&0x1ffffc));
304 if (old_io_data != *io_data) {
306 fwrite(&byte, 1, 1, f);
307 fwrite(io_data, 1, 4, f);
308 old_io_data = *io_data;
311 fwrite(&byte, 1, 1, f);
314 if (psxRegs.cycle == 190230) {
315 dump_mem("/mnt/ntz/dev/pnd/tmp/psxram_i.dump", psxM, 0x200000);
316 dump_mem("/mnt/ntz/dev/pnd/tmp/psxregs_i.dump", psxH, 0x10000);
323 static const char *regnames[offsetof(psxRegisters, intCycle) / 4] = {
324 "r0", "r1", "r2", "r3", "r4", "r5", "r6", "r7",
325 "r8", "r9", "r10", "r11", "r12", "r13", "r14", "r15",
326 "r16", "r17", "r18", "r19", "r20", "r21", "r22", "r23",
327 "r24", "r25", "r26", "r27", "r28", "r29", "r30", "r31",
329 "C0_0", "C0_1", "C0_2", "C0_3", "C0_4", "C0_5", "C0_6", "C0_7",
330 "C0_8", "C0_9", "C0_10", "C0_11", "C0_12", "C0_13", "C0_14", "C0_15",
331 "C0_16", "C0_17", "C0_18", "C0_19", "C0_20", "C0_21", "C0_22", "C0_23",
332 "C0_24", "C0_25", "C0_26", "C0_27", "C0_28", "C0_29", "C0_30", "C0_31",
334 "C2D0", "C2D1", "C2D2", "C2D3", "C2D4", "C2D5", "C2D6", "C2D7",
335 "C2D8", "C2D9", "C2D10", "C2D11", "C2D12", "C2D13", "C2D14", "C2D15",
336 "C2D16", "C2D17", "C2D18", "C2D19", "C2D20", "C2D21", "C2D22", "C2D23",
337 "C2D24", "C2D25", "C2D26", "C2D27", "C2D28", "C2D29", "C2D30", "C2D31",
339 "C2C0", "C2C1", "C2C2", "C2C3", "C2C4", "C2C5", "C2C6", "C2C7",
340 "C2C8", "C2C9", "C2C10", "C2C11", "C2C12", "C2C13", "C2C14", "C2C15",
341 "C2C16", "C2C17", "C2C18", "C2C19", "C2C20", "C2C21", "C2C22", "C2C23",
342 "C2C24", "C2C25", "C2C26", "C2C27", "C2C28", "C2C29", "C2C30", "C2C31",
344 "PC", "code", "cycle", "interrupt",
352 static int miss_log_i;
353 #define miss_log_len (sizeof(miss_log)/sizeof(miss_log[0]))
354 #define miss_log_mask (miss_log_len-1)
356 static void miss_log_add(int reg, u32 val, u32 val_expect, u32 pc, u32 cycle)
358 miss_log[miss_log_i].reg = reg;
359 miss_log[miss_log_i].val = val;
360 miss_log[miss_log_i].val_expect = val_expect;
361 miss_log[miss_log_i].pc = pc;
362 miss_log[miss_log_i].cycle = cycle;
363 miss_log_i = (miss_log_i + 1) & miss_log_mask;
368 void do_insn_cmp(void)
370 static psxRegisters rregs;
371 static u32 mem_addr, mem_val;
372 u32 *allregs_p = (void *)&psxRegs;
373 u32 *allregs_e = (void *)&rregs;
374 static u32 ppc, failcount;
379 f = fopen("tracelog", "rb");
382 if ((ret = fread(&code, 1, 1, f)) <= 0)
389 if ((ret = fread(&mem_addr, 1, 4, f)) <= 0)
394 if ((ret = fread(&mem_val, 1, 4, f)) <= 0)
398 if ((ret = fread(&allregs_e[code], 1, 4, f)) <= 0)
407 psxRegs.code = rregs.code; // don't care
408 psxRegs.cycle = rregs.cycle;
409 psxRegs.CP0.r[9] = rregs.CP0.r[9]; // Count
411 //if (psxRegs.cycle == 166172) breakme();
412 //if (psxRegs.cycle > 11296376) printf("pc=%08x %u %08x\n", psxRegs.pc, psxRegs.cycle, psxRegs.interrupt);
414 mem_addr &= 0x1ffffc;
416 if (memcmp(&psxRegs, &rregs, offsetof(psxRegisters, intCycle)) == 0 &&
417 mem_val == *(u32 *)(psxM + mem_addr)
423 for (i = 0; i < offsetof(psxRegisters, intCycle) / 4; i++) {
424 if (allregs_p[i] != allregs_e[i]) {
425 miss_log_add(i, allregs_p[i], allregs_e[i], psxRegs.pc, psxRegs.cycle);
430 if (mem_val != *(u32 *)(psxM + mem_addr)) {
431 printf("bad mem @%08x: %08x %08x\n", mem_addr, *(u32 *)(psxM + mem_addr), mem_val);
435 if (psxRegs.pc == rregs.pc && bad < 6 && failcount < 32) {
436 static int last_mcycle;
437 if (last_mcycle != psxRegs.cycle >> 20) {
438 printf("%u\n", psxRegs.cycle);
439 last_mcycle = psxRegs.cycle >> 20;
446 for (i = 0; i < miss_log_len; i++, miss_log_i = (miss_log_i + 1) & miss_log_mask)
447 printf("bad %5s: %08x %08x, pc=%08x, cycle %u\n",
448 regnames[miss_log[miss_log_i].reg], miss_log[miss_log_i].val,
449 miss_log[miss_log_i].val_expect, miss_log[miss_log_i].pc, miss_log[miss_log_i].cycle);
450 printf("-- %d\n", bad);
451 for (i = 0; i < 8; i++)
452 printf("r%d=%08x r%2d=%08x r%2d=%08x r%2d=%08x\n", i, allregs_p[i],
453 i+8, allregs_p[i+8], i+16, allregs_p[i+16], i+24, allregs_p[i+24]);
454 printf("PC: %08x/%08x, cycle %u\n", psxRegs.pc, ppc, psxRegs.cycle);
455 dump_mem("/mnt/ntz/dev/pnd/tmp/psxram.dump", psxM, 0x200000);
456 dump_mem("/mnt/ntz/dev/pnd/tmp/psxregs.dump", psxH, 0x10000);
459 psxRegs.cycle = rregs.cycle + 2; // sync timing