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);
114 extern void psxMTC0();
116 evprintf("ari64 MTC0 %08x %08x %u\n", psxRegs.code, psxRegs.pc, psxRegs.cycle);
118 gen_interupt(); /* FIXME: checking pending irqs should be enough */
121 void check_interupt()
123 /* FIXME (also asm) */
124 printf("ari64_check_interupt\n");
127 void new_dyna_save(void)
129 // psxRegs.intCycle is always maintained, no need to convert
132 void new_dyna_restore(void)
135 for (i = 0; i < PSXINT_NEWDRC_CHECK; i++)
136 event_cycles[i] = psxRegs.intCycle[i].sCycle + psxRegs.intCycle[i].cycle;
139 void *gte_handlers[64];
141 /* from gte.txt.. not sure if this is any good. */
142 const char gte_cycletab[64] = {
143 /* 1 2 3 4 5 6 7 8 9 a b c d e f */
144 0, 15, 0, 0, 0, 0, 8, 0, 0, 0, 0, 0, 6, 0, 0, 0,
145 8, 8, 8, 19, 13, 0, 44, 0, 0, 0, 0, 17, 11, 0, 14, 0,
146 30, 0, 0, 0, 0, 0, 0, 0, 5, 8, 17, 0, 0, 5, 6, 0,
147 23, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 5, 5, 39,
150 static int ari64_init()
152 extern void (*psxCP2[64])();
153 extern void psxNULL();
154 extern void *psxH_ptr;
158 new_dyna_pcsx_mem_init();
160 for (i = 0; i < ARRAY_SIZE(gte_handlers); i++)
161 if (psxCP2[i] != psxNULL)
162 gte_handlers[i] = psxCP2[i];
169 static void ari64_reset()
171 printf("ari64_reset\n");
172 new_dyna_pcsx_mem_reset();
173 invalidate_all_pages();
174 pending_exception = 1;
177 static void ari64_execute()
179 schedule_timeslice();
181 evprintf("ari64_execute %08x, %u->%u (%d)\n", psxRegs.pc,
182 psxRegs.cycle, next_interupt, next_interupt - psxRegs.cycle);
186 evprintf("ari64_execute end %08x, %u->%u (%d)\n", psxRegs.pc,
187 psxRegs.cycle, next_interupt, next_interupt - psxRegs.cycle);
190 static void ari64_clear(u32 addr, u32 size)
194 evprintf("ari64_clear %08x %04x\n", addr, size);
196 /* check for RAM mirrors */
197 if ((addr & ~0xe0600000) < 0x200000) {
203 end = (addr + size) >> 12;
205 for (; start <= end; start++)
206 if (!invalid_code[start])
207 invalidate_block(start);
210 static void ari64_shutdown()
212 new_dynarec_cleanup();
215 extern void intExecute();
216 extern void intExecuteT();
217 extern void intExecuteBlock();
218 extern void intExecuteBlockT();
220 #define intExecuteT intExecute
221 #define intExecuteBlockT intExecuteBlock
240 void do_insn_trace() {}
241 void do_insn_cmp() {}
244 #if defined(__x86_64__) || defined(__i386__)
245 unsigned int address, readmem_word, word;
246 unsigned short hword;
248 int pending_exception, stop;
249 unsigned int next_interupt;
251 void new_dynarec_init() {}
252 void new_dyna_start() {}
253 void new_dynarec_cleanup() {}
254 void invalidate_all_pages() {}
255 void invalidate_block(unsigned int block) {}
256 void new_dyna_pcsx_mem_init(void) {}
257 void new_dyna_pcsx_mem_reset(void) {}
264 extern u32 last_io_addr;
266 static void dump_mem(const char *fname, void *mem, size_t size)
268 FILE *f1 = fopen(fname, "wb");
270 f1 = fopen(strrchr(fname, '/') + 1, "wb");
271 fwrite(mem, 1, size, f1);
275 static u32 memcheck_read(u32 a)
277 if ((a >> 16) == 0x1f80)
279 return *(u32 *)(psxH + (a & 0xfffc));
281 if ((a >> 16) == 0x1f00)
283 return *(u32 *)(psxP + (a & 0xfffc));
285 // if ((a & ~0xe0600000) < 0x200000)
287 return *(u32 *)(psxM + (a & 0x1ffffc));
290 void do_insn_trace(void)
292 static psxRegisters oldregs;
293 static u32 old_io_addr = (u32)-1;
294 static u32 old_io_data = 0xbad0c0de;
295 u32 *allregs_p = (void *)&psxRegs;
296 u32 *allregs_o = (void *)&oldregs;
301 //last_io_addr = 0x5e2c8;
303 f = fopen("tracelog", "wb");
305 oldregs.code = psxRegs.code; // don't care
306 for (i = 0; i < offsetof(psxRegisters, intCycle) / 4; i++) {
307 if (allregs_p[i] != allregs_o[i]) {
309 fwrite(&allregs_p[i], 1, 4, f);
310 allregs_o[i] = allregs_p[i];
313 if (old_io_addr != last_io_addr) {
315 fwrite(&byte, 1, 1, f);
316 fwrite(&last_io_addr, 1, 4, f);
317 old_io_addr = last_io_addr;
319 io_data = memcheck_read(last_io_addr);
320 if (old_io_data != io_data) {
322 fwrite(&byte, 1, 1, f);
323 fwrite(&io_data, 1, 4, f);
324 old_io_data = io_data;
327 fwrite(&byte, 1, 1, f);
330 if (psxRegs.cycle == 190230) {
331 dump_mem("/mnt/ntz/dev/pnd/tmp/psxram_i.dump", psxM, 0x200000);
332 dump_mem("/mnt/ntz/dev/pnd/tmp/psxregs_i.dump", psxH, 0x10000);
339 static const char *regnames[offsetof(psxRegisters, intCycle) / 4] = {
340 "r0", "r1", "r2", "r3", "r4", "r5", "r6", "r7",
341 "r8", "r9", "r10", "r11", "r12", "r13", "r14", "r15",
342 "r16", "r17", "r18", "r19", "r20", "r21", "r22", "r23",
343 "r24", "r25", "r26", "r27", "r28", "r29", "r30", "r31",
345 "C0_0", "C0_1", "C0_2", "C0_3", "C0_4", "C0_5", "C0_6", "C0_7",
346 "C0_8", "C0_9", "C0_10", "C0_11", "C0_12", "C0_13", "C0_14", "C0_15",
347 "C0_16", "C0_17", "C0_18", "C0_19", "C0_20", "C0_21", "C0_22", "C0_23",
348 "C0_24", "C0_25", "C0_26", "C0_27", "C0_28", "C0_29", "C0_30", "C0_31",
350 "C2D0", "C2D1", "C2D2", "C2D3", "C2D4", "C2D5", "C2D6", "C2D7",
351 "C2D8", "C2D9", "C2D10", "C2D11", "C2D12", "C2D13", "C2D14", "C2D15",
352 "C2D16", "C2D17", "C2D18", "C2D19", "C2D20", "C2D21", "C2D22", "C2D23",
353 "C2D24", "C2D25", "C2D26", "C2D27", "C2D28", "C2D29", "C2D30", "C2D31",
355 "C2C0", "C2C1", "C2C2", "C2C3", "C2C4", "C2C5", "C2C6", "C2C7",
356 "C2C8", "C2C9", "C2C10", "C2C11", "C2C12", "C2C13", "C2C14", "C2C15",
357 "C2C16", "C2C17", "C2C18", "C2C19", "C2C20", "C2C21", "C2C22", "C2C23",
358 "C2C24", "C2C25", "C2C26", "C2C27", "C2C28", "C2C29", "C2C30", "C2C31",
360 "PC", "code", "cycle", "interrupt",
368 static int miss_log_i;
369 #define miss_log_len (sizeof(miss_log)/sizeof(miss_log[0]))
370 #define miss_log_mask (miss_log_len-1)
372 static void miss_log_add(int reg, u32 val, u32 val_expect, u32 pc, u32 cycle)
374 miss_log[miss_log_i].reg = reg;
375 miss_log[miss_log_i].val = val;
376 miss_log[miss_log_i].val_expect = val_expect;
377 miss_log[miss_log_i].pc = pc;
378 miss_log[miss_log_i].cycle = cycle;
379 miss_log_i = (miss_log_i + 1) & miss_log_mask;
384 void do_insn_cmp(void)
386 static psxRegisters rregs;
387 static u32 mem_addr, mem_val;
388 u32 *allregs_p = (void *)&psxRegs;
389 u32 *allregs_e = (void *)&rregs;
390 static u32 ppc, failcount;
395 f = fopen("tracelog", "rb");
398 if ((ret = fread(&code, 1, 1, f)) <= 0)
405 if ((ret = fread(&mem_addr, 1, 4, f)) <= 0)
410 if ((ret = fread(&mem_val, 1, 4, f)) <= 0)
414 if ((ret = fread(&allregs_e[code], 1, 4, f)) <= 0)
423 psxRegs.code = rregs.code; // don't care
424 psxRegs.cycle = rregs.cycle;
425 psxRegs.CP0.r[9] = rregs.CP0.r[9]; // Count
427 //if (psxRegs.cycle == 166172) breakme();
429 if (memcmp(&psxRegs, &rregs, offsetof(psxRegisters, intCycle)) == 0 &&
430 mem_val == memcheck_read(mem_addr)
436 for (i = 0; i < offsetof(psxRegisters, intCycle) / 4; i++) {
437 if (allregs_p[i] != allregs_e[i]) {
438 miss_log_add(i, allregs_p[i], allregs_e[i], psxRegs.pc, psxRegs.cycle);
443 if (mem_val != memcheck_read(mem_addr)) {
444 printf("bad mem @%08x: %08x %08x\n", mem_addr, memcheck_read(mem_addr), mem_val);
448 if (psxRegs.pc == rregs.pc && bad < 6 && failcount < 32) {
449 static int last_mcycle;
450 if (last_mcycle != psxRegs.cycle >> 20) {
451 printf("%u\n", psxRegs.cycle);
452 last_mcycle = psxRegs.cycle >> 20;
459 for (i = 0; i < miss_log_len; i++, miss_log_i = (miss_log_i + 1) & miss_log_mask)
460 printf("bad %5s: %08x %08x, pc=%08x, cycle %u\n",
461 regnames[miss_log[miss_log_i].reg], miss_log[miss_log_i].val,
462 miss_log[miss_log_i].val_expect, miss_log[miss_log_i].pc, miss_log[miss_log_i].cycle);
463 printf("-- %d\n", bad);
464 for (i = 0; i < 8; i++)
465 printf("r%d=%08x r%2d=%08x r%2d=%08x r%2d=%08x\n", i, allregs_p[i],
466 i+8, allregs_p[i+8], i+16, allregs_p[i+16], i+24, allregs_p[i+24]);
467 printf("PC: %08x/%08x, cycle %u\n", psxRegs.pc, ppc, psxRegs.cycle);
468 dump_mem("/mnt/ntz/dev/pnd/tmp/psxram.dump", psxM, 0x200000);
469 dump_mem("/mnt/ntz/dev/pnd/tmp/psxregs.dump", psxH, 0x10000);
472 psxRegs.cycle = rregs.cycle + 2; // sync timing