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,
64 [PSXINT_CDRDMA] = cdrDmaInterrupt,
65 [PSXINT_CDRLID] = cdrLidSeekInterrupt,
66 [PSXINT_CDRPLAY] = cdrPlayInterrupt,
69 /* local dupe of psxBranchTest, using event_cycles */
70 static void irq_test(void)
72 u32 irqs = psxRegs.interrupt;
73 u32 cycle = psxRegs.cycle;
76 if ((psxRegs.cycle - psxNextsCounter) >= psxNextCounter)
79 // irq_funcs() may queue more irqs
80 psxRegs.interrupt = 0;
82 for (irq = 0, irq_bits = irqs; irq_bits != 0; irq++, irq_bits >>= 1) {
85 if ((s32)(cycle - event_cycles[irq]) >= 0) {
90 psxRegs.interrupt |= irqs;
92 if ((psxHu32(0x1070) & psxHu32(0x1074)) && (Status & 0x401) == 0x401) {
93 psxException(0x400, 0);
94 pending_exception = 1;
100 evprintf(" +ge %08x, %u->%u\n", psxRegs.pc, psxRegs.cycle, next_interupt);
107 //pending_exception = 1;
109 schedule_timeslice();
111 evprintf(" -ge %08x, %u->%u (%d)\n", psxRegs.pc, psxRegs.cycle,
112 next_interupt, next_interupt - psxRegs.cycle);
116 extern void MTC0(int reg, u32 val);
118 void pcsx_mtc0(u32 reg)
120 evprintf("MTC0 %d #%x @%08x %u\n", reg, readmem_word, psxRegs.pc, psxRegs.cycle);
121 MTC0(reg, readmem_word);
125 void pcsx_mtc0_ds(u32 reg)
127 evprintf("MTC0 %d #%x @%08x %u\n", reg, readmem_word, psxRegs.pc, psxRegs.cycle);
128 MTC0(reg, readmem_word);
131 void new_dyna_save(void)
133 // psxRegs.intCycle is always maintained, no need to convert
136 void new_dyna_restore(void)
139 for (i = 0; i < PSXINT_COUNT; i++)
140 event_cycles[i] = psxRegs.intCycle[i].sCycle + psxRegs.intCycle[i].cycle;
143 void *gte_handlers[64];
145 /* from gte.txt.. not sure if this is any good. */
146 const char gte_cycletab[64] = {
147 /* 1 2 3 4 5 6 7 8 9 a b c d e f */
148 0, 15, 0, 0, 0, 0, 8, 0, 0, 0, 0, 0, 6, 0, 0, 0,
149 8, 8, 8, 19, 13, 0, 44, 0, 0, 0, 0, 17, 11, 0, 14, 0,
150 30, 0, 0, 0, 0, 0, 0, 0, 5, 8, 17, 0, 0, 5, 6, 0,
151 23, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 5, 5, 39,
154 static int ari64_init()
156 extern void (*psxCP2[64])();
157 extern void psxNULL();
158 extern void *psxH_ptr;
162 new_dyna_pcsx_mem_init();
164 for (i = 0; i < ARRAY_SIZE(gte_handlers); i++)
165 if (psxCP2[i] != psxNULL)
166 gte_handlers[i] = psxCP2[i];
173 static void ari64_reset()
175 printf("ari64_reset\n");
176 new_dyna_pcsx_mem_reset();
177 invalidate_all_pages();
179 pending_exception = 1;
182 // execute until predefined leave points
183 // (HLE softcall exit and BIOS fastboot end)
184 static void ari64_execute_until()
186 schedule_timeslice();
188 evprintf("ari64_execute %08x, %u->%u (%d)\n", psxRegs.pc,
189 psxRegs.cycle, next_interupt, next_interupt - psxRegs.cycle);
193 evprintf("ari64_execute end %08x, %u->%u (%d)\n", psxRegs.pc,
194 psxRegs.cycle, next_interupt, next_interupt - psxRegs.cycle);
197 static void ari64_execute()
200 ari64_execute_until();
201 evprintf("drc left @%08x\n", psxRegs.pc);
205 static void ari64_clear(u32 addr, u32 size)
207 u32 start, end, main_ram;
209 size *= 4; /* PCSX uses DMA units */
211 evprintf("ari64_clear %08x %04x\n", addr, size);
213 /* check for RAM mirrors */
214 main_ram = (addr & 0xffe00000) == 0x80000000;
217 end = (addr + size) >> 12;
219 for (; start <= end; start++)
220 if (!main_ram || !invalid_code[start])
221 invalidate_block(start);
224 static void ari64_shutdown()
226 new_dynarec_cleanup();
229 extern void intExecute();
230 extern void intExecuteT();
231 extern void intExecuteBlock();
232 extern void intExecuteBlockT();
234 #define intExecuteT intExecute
235 #define intExecuteBlockT intExecuteBlock
254 void do_insn_trace() {}
255 void do_insn_cmp() {}
258 #if defined(__x86_64__) || defined(__i386__)
259 unsigned int address, readmem_word, word;
260 unsigned short hword;
262 int pending_exception, stop;
263 unsigned int next_interupt;
265 void new_dynarec_init() {}
266 void new_dyna_start() {}
267 void new_dynarec_cleanup() {}
268 void invalidate_all_pages() {}
269 void invalidate_block(unsigned int block) {}
270 void new_dyna_pcsx_mem_init(void) {}
271 void new_dyna_pcsx_mem_reset(void) {}
278 extern u32 last_io_addr;
280 static void dump_mem(const char *fname, void *mem, size_t size)
282 FILE *f1 = fopen(fname, "wb");
284 f1 = fopen(strrchr(fname, '/') + 1, "wb");
285 fwrite(mem, 1, size, f1);
289 static u32 memcheck_read(u32 a)
291 if ((a >> 16) == 0x1f80)
293 return *(u32 *)(psxH + (a & 0xfffc));
295 if ((a >> 16) == 0x1f00)
297 return *(u32 *)(psxP + (a & 0xfffc));
299 // if ((a & ~0xe0600000) < 0x200000)
301 return *(u32 *)(psxM + (a & 0x1ffffc));
304 void do_insn_trace(void)
306 static psxRegisters oldregs;
307 static u32 old_io_addr = (u32)-1;
308 static u32 old_io_data = 0xbad0c0de;
309 u32 *allregs_p = (void *)&psxRegs;
310 u32 *allregs_o = (void *)&oldregs;
315 //last_io_addr = 0x5e2c8;
317 f = fopen("tracelog", "wb");
319 oldregs.code = psxRegs.code; // don't care
320 for (i = 0; i < offsetof(psxRegisters, intCycle) / 4; i++) {
321 if (allregs_p[i] != allregs_o[i]) {
323 fwrite(&allregs_p[i], 1, 4, f);
324 allregs_o[i] = allregs_p[i];
327 if (old_io_addr != last_io_addr) {
329 fwrite(&byte, 1, 1, f);
330 fwrite(&last_io_addr, 1, 4, f);
331 old_io_addr = last_io_addr;
333 io_data = memcheck_read(last_io_addr);
334 if (old_io_data != io_data) {
336 fwrite(&byte, 1, 1, f);
337 fwrite(&io_data, 1, 4, f);
338 old_io_data = io_data;
341 fwrite(&byte, 1, 1, f);
344 if (psxRegs.cycle == 190230) {
345 dump_mem("/mnt/ntz/dev/pnd/tmp/psxram_i.dump", psxM, 0x200000);
346 dump_mem("/mnt/ntz/dev/pnd/tmp/psxregs_i.dump", psxH, 0x10000);
353 static const char *regnames[offsetof(psxRegisters, intCycle) / 4] = {
354 "r0", "r1", "r2", "r3", "r4", "r5", "r6", "r7",
355 "r8", "r9", "r10", "r11", "r12", "r13", "r14", "r15",
356 "r16", "r17", "r18", "r19", "r20", "r21", "r22", "r23",
357 "r24", "r25", "r26", "r27", "r28", "r29", "r30", "r31",
359 "C0_0", "C0_1", "C0_2", "C0_3", "C0_4", "C0_5", "C0_6", "C0_7",
360 "C0_8", "C0_9", "C0_10", "C0_11", "C0_12", "C0_13", "C0_14", "C0_15",
361 "C0_16", "C0_17", "C0_18", "C0_19", "C0_20", "C0_21", "C0_22", "C0_23",
362 "C0_24", "C0_25", "C0_26", "C0_27", "C0_28", "C0_29", "C0_30", "C0_31",
364 "C2D0", "C2D1", "C2D2", "C2D3", "C2D4", "C2D5", "C2D6", "C2D7",
365 "C2D8", "C2D9", "C2D10", "C2D11", "C2D12", "C2D13", "C2D14", "C2D15",
366 "C2D16", "C2D17", "C2D18", "C2D19", "C2D20", "C2D21", "C2D22", "C2D23",
367 "C2D24", "C2D25", "C2D26", "C2D27", "C2D28", "C2D29", "C2D30", "C2D31",
369 "C2C0", "C2C1", "C2C2", "C2C3", "C2C4", "C2C5", "C2C6", "C2C7",
370 "C2C8", "C2C9", "C2C10", "C2C11", "C2C12", "C2C13", "C2C14", "C2C15",
371 "C2C16", "C2C17", "C2C18", "C2C19", "C2C20", "C2C21", "C2C22", "C2C23",
372 "C2C24", "C2C25", "C2C26", "C2C27", "C2C28", "C2C29", "C2C30", "C2C31",
374 "PC", "code", "cycle", "interrupt",
382 static int miss_log_i;
383 #define miss_log_len (sizeof(miss_log)/sizeof(miss_log[0]))
384 #define miss_log_mask (miss_log_len-1)
386 static void miss_log_add(int reg, u32 val, u32 val_expect, u32 pc, u32 cycle)
388 miss_log[miss_log_i].reg = reg;
389 miss_log[miss_log_i].val = val;
390 miss_log[miss_log_i].val_expect = val_expect;
391 miss_log[miss_log_i].pc = pc;
392 miss_log[miss_log_i].cycle = cycle;
393 miss_log_i = (miss_log_i + 1) & miss_log_mask;
398 void do_insn_cmp(void)
400 static psxRegisters rregs;
401 static u32 mem_addr, mem_val;
402 u32 *allregs_p = (void *)&psxRegs;
403 u32 *allregs_e = (void *)&rregs;
404 static u32 ppc, failcount;
409 f = fopen("tracelog", "rb");
412 if ((ret = fread(&code, 1, 1, f)) <= 0)
419 if ((ret = fread(&mem_addr, 1, 4, f)) <= 0)
424 if ((ret = fread(&mem_val, 1, 4, f)) <= 0)
428 if ((ret = fread(&allregs_e[code], 1, 4, f)) <= 0)
437 psxRegs.code = rregs.code; // don't care
438 psxRegs.cycle = rregs.cycle;
439 psxRegs.CP0.r[9] = rregs.CP0.r[9]; // Count
441 //if (psxRegs.cycle == 166172) breakme();
443 if (memcmp(&psxRegs, &rregs, offsetof(psxRegisters, intCycle)) == 0 &&
444 mem_val == memcheck_read(mem_addr)
450 for (i = 0; i < offsetof(psxRegisters, intCycle) / 4; i++) {
451 if (allregs_p[i] != allregs_e[i]) {
452 miss_log_add(i, allregs_p[i], allregs_e[i], psxRegs.pc, psxRegs.cycle);
457 if (mem_val != memcheck_read(mem_addr)) {
458 printf("bad mem @%08x: %08x %08x\n", mem_addr, memcheck_read(mem_addr), mem_val);
462 if (psxRegs.pc == rregs.pc && bad < 6 && failcount < 32) {
463 static int last_mcycle;
464 if (last_mcycle != psxRegs.cycle >> 20) {
465 printf("%u\n", psxRegs.cycle);
466 last_mcycle = psxRegs.cycle >> 20;
473 for (i = 0; i < miss_log_len; i++, miss_log_i = (miss_log_i + 1) & miss_log_mask)
474 printf("bad %5s: %08x %08x, pc=%08x, cycle %u\n",
475 regnames[miss_log[miss_log_i].reg], miss_log[miss_log_i].val,
476 miss_log[miss_log_i].val_expect, miss_log[miss_log_i].pc, miss_log[miss_log_i].cycle);
477 printf("-- %d\n", bad);
478 for (i = 0; i < 8; i++)
479 printf("r%d=%08x r%2d=%08x r%2d=%08x r%2d=%08x\n", i, allregs_p[i],
480 i+8, allregs_p[i+8], i+16, allregs_p[i+16], i+24, allregs_p[i+24]);
481 printf("PC: %08x/%08x, cycle %u\n", psxRegs.pc, ppc, psxRegs.cycle);
482 dump_mem("/mnt/ntz/dev/pnd/tmp/psxram.dump", psxM, 0x200000);
483 dump_mem("/mnt/ntz/dev/pnd/tmp/psxregs.dump", psxH, 0x10000);
486 psxRegs.cycle = rregs.cycle + 2; // sync timing