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 // execute until predefined leave points
179 // (HLE softcall exit and BIOS fastboot end)
180 static void ari64_execute_until()
182 schedule_timeslice();
184 evprintf("ari64_execute %08x, %u->%u (%d)\n", psxRegs.pc,
185 psxRegs.cycle, next_interupt, next_interupt - psxRegs.cycle);
189 evprintf("ari64_execute end %08x, %u->%u (%d)\n", psxRegs.pc,
190 psxRegs.cycle, next_interupt, next_interupt - psxRegs.cycle);
193 static void ari64_execute()
196 ari64_execute_until();
197 evprintf("drc left @%08x\n", psxRegs.pc);
201 static void ari64_clear(u32 addr, u32 size)
205 size *= 4; /* PCSX uses DMA units */
207 evprintf("ari64_clear %08x %04x\n", addr, size);
209 /* check for RAM mirrors */
210 if ((addr & ~0xe0600000) < 0x200000) {
216 end = (addr + size) >> 12;
218 for (; start <= end; start++)
219 if (!invalid_code[start])
220 invalidate_block(start);
223 static void ari64_shutdown()
225 new_dynarec_cleanup();
228 extern void intExecute();
229 extern void intExecuteT();
230 extern void intExecuteBlock();
231 extern void intExecuteBlockT();
233 #define intExecuteT intExecute
234 #define intExecuteBlockT intExecuteBlock
253 void do_insn_trace() {}
254 void do_insn_cmp() {}
257 #if defined(__x86_64__) || defined(__i386__)
258 unsigned int address, readmem_word, word;
259 unsigned short hword;
261 int pending_exception, stop;
262 unsigned int next_interupt;
264 void new_dynarec_init() {}
265 void new_dyna_start() {}
266 void new_dynarec_cleanup() {}
267 void invalidate_all_pages() {}
268 void invalidate_block(unsigned int block) {}
269 void new_dyna_pcsx_mem_init(void) {}
270 void new_dyna_pcsx_mem_reset(void) {}
277 extern u32 last_io_addr;
279 static void dump_mem(const char *fname, void *mem, size_t size)
281 FILE *f1 = fopen(fname, "wb");
283 f1 = fopen(strrchr(fname, '/') + 1, "wb");
284 fwrite(mem, 1, size, f1);
288 static u32 memcheck_read(u32 a)
290 if ((a >> 16) == 0x1f80)
292 return *(u32 *)(psxH + (a & 0xfffc));
294 if ((a >> 16) == 0x1f00)
296 return *(u32 *)(psxP + (a & 0xfffc));
298 // if ((a & ~0xe0600000) < 0x200000)
300 return *(u32 *)(psxM + (a & 0x1ffffc));
303 void do_insn_trace(void)
305 static psxRegisters oldregs;
306 static u32 old_io_addr = (u32)-1;
307 static u32 old_io_data = 0xbad0c0de;
308 u32 *allregs_p = (void *)&psxRegs;
309 u32 *allregs_o = (void *)&oldregs;
314 //last_io_addr = 0x5e2c8;
316 f = fopen("tracelog", "wb");
318 oldregs.code = psxRegs.code; // don't care
319 for (i = 0; i < offsetof(psxRegisters, intCycle) / 4; i++) {
320 if (allregs_p[i] != allregs_o[i]) {
322 fwrite(&allregs_p[i], 1, 4, f);
323 allregs_o[i] = allregs_p[i];
326 if (old_io_addr != last_io_addr) {
328 fwrite(&byte, 1, 1, f);
329 fwrite(&last_io_addr, 1, 4, f);
330 old_io_addr = last_io_addr;
332 io_data = memcheck_read(last_io_addr);
333 if (old_io_data != io_data) {
335 fwrite(&byte, 1, 1, f);
336 fwrite(&io_data, 1, 4, f);
337 old_io_data = io_data;
340 fwrite(&byte, 1, 1, f);
343 if (psxRegs.cycle == 190230) {
344 dump_mem("/mnt/ntz/dev/pnd/tmp/psxram_i.dump", psxM, 0x200000);
345 dump_mem("/mnt/ntz/dev/pnd/tmp/psxregs_i.dump", psxH, 0x10000);
352 static const char *regnames[offsetof(psxRegisters, intCycle) / 4] = {
353 "r0", "r1", "r2", "r3", "r4", "r5", "r6", "r7",
354 "r8", "r9", "r10", "r11", "r12", "r13", "r14", "r15",
355 "r16", "r17", "r18", "r19", "r20", "r21", "r22", "r23",
356 "r24", "r25", "r26", "r27", "r28", "r29", "r30", "r31",
358 "C0_0", "C0_1", "C0_2", "C0_3", "C0_4", "C0_5", "C0_6", "C0_7",
359 "C0_8", "C0_9", "C0_10", "C0_11", "C0_12", "C0_13", "C0_14", "C0_15",
360 "C0_16", "C0_17", "C0_18", "C0_19", "C0_20", "C0_21", "C0_22", "C0_23",
361 "C0_24", "C0_25", "C0_26", "C0_27", "C0_28", "C0_29", "C0_30", "C0_31",
363 "C2D0", "C2D1", "C2D2", "C2D3", "C2D4", "C2D5", "C2D6", "C2D7",
364 "C2D8", "C2D9", "C2D10", "C2D11", "C2D12", "C2D13", "C2D14", "C2D15",
365 "C2D16", "C2D17", "C2D18", "C2D19", "C2D20", "C2D21", "C2D22", "C2D23",
366 "C2D24", "C2D25", "C2D26", "C2D27", "C2D28", "C2D29", "C2D30", "C2D31",
368 "C2C0", "C2C1", "C2C2", "C2C3", "C2C4", "C2C5", "C2C6", "C2C7",
369 "C2C8", "C2C9", "C2C10", "C2C11", "C2C12", "C2C13", "C2C14", "C2C15",
370 "C2C16", "C2C17", "C2C18", "C2C19", "C2C20", "C2C21", "C2C22", "C2C23",
371 "C2C24", "C2C25", "C2C26", "C2C27", "C2C28", "C2C29", "C2C30", "C2C31",
373 "PC", "code", "cycle", "interrupt",
381 static int miss_log_i;
382 #define miss_log_len (sizeof(miss_log)/sizeof(miss_log[0]))
383 #define miss_log_mask (miss_log_len-1)
385 static void miss_log_add(int reg, u32 val, u32 val_expect, u32 pc, u32 cycle)
387 miss_log[miss_log_i].reg = reg;
388 miss_log[miss_log_i].val = val;
389 miss_log[miss_log_i].val_expect = val_expect;
390 miss_log[miss_log_i].pc = pc;
391 miss_log[miss_log_i].cycle = cycle;
392 miss_log_i = (miss_log_i + 1) & miss_log_mask;
397 void do_insn_cmp(void)
399 static psxRegisters rregs;
400 static u32 mem_addr, mem_val;
401 u32 *allregs_p = (void *)&psxRegs;
402 u32 *allregs_e = (void *)&rregs;
403 static u32 ppc, failcount;
408 f = fopen("tracelog", "rb");
411 if ((ret = fread(&code, 1, 1, f)) <= 0)
418 if ((ret = fread(&mem_addr, 1, 4, f)) <= 0)
423 if ((ret = fread(&mem_val, 1, 4, f)) <= 0)
427 if ((ret = fread(&allregs_e[code], 1, 4, f)) <= 0)
436 psxRegs.code = rregs.code; // don't care
437 psxRegs.cycle = rregs.cycle;
438 psxRegs.CP0.r[9] = rregs.CP0.r[9]; // Count
440 //if (psxRegs.cycle == 166172) breakme();
442 if (memcmp(&psxRegs, &rregs, offsetof(psxRegisters, intCycle)) == 0 &&
443 mem_val == memcheck_read(mem_addr)
449 for (i = 0; i < offsetof(psxRegisters, intCycle) / 4; i++) {
450 if (allregs_p[i] != allregs_e[i]) {
451 miss_log_add(i, allregs_p[i], allregs_e[i], psxRegs.pc, psxRegs.cycle);
456 if (mem_val != memcheck_read(mem_addr)) {
457 printf("bad mem @%08x: %08x %08x\n", mem_addr, memcheck_read(mem_addr), mem_val);
461 if (psxRegs.pc == rregs.pc && bad < 6 && failcount < 32) {
462 static int last_mcycle;
463 if (last_mcycle != psxRegs.cycle >> 20) {
464 printf("%u\n", psxRegs.cycle);
465 last_mcycle = psxRegs.cycle >> 20;
472 for (i = 0; i < miss_log_len; i++, miss_log_i = (miss_log_i + 1) & miss_log_mask)
473 printf("bad %5s: %08x %08x, pc=%08x, cycle %u\n",
474 regnames[miss_log[miss_log_i].reg], miss_log[miss_log_i].val,
475 miss_log[miss_log_i].val_expect, miss_log[miss_log_i].pc, miss_log[miss_log_i].cycle);
476 printf("-- %d\n", bad);
477 for (i = 0; i < 8; i++)
478 printf("r%d=%08x r%2d=%08x r%2d=%08x r%2d=%08x\n", i, allregs_p[i],
479 i+8, allregs_p[i+8], i+16, allregs_p[i+16], i+24, allregs_p[i+24]);
480 printf("PC: %08x/%08x, cycle %u\n", psxRegs.pc, ppc, psxRegs.cycle);
481 dump_mem("/mnt/ntz/dev/pnd/tmp/psxram.dump", psxM, 0x200000);
482 dump_mem("/mnt/ntz/dev/pnd/tmp/psxregs.dump", psxH, 0x10000);
485 psxRegs.cycle = rregs.cycle + 2; // sync timing