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,
68 /* local dupe of psxBranchTest, using event_cycles */
69 static void irq_test(void)
71 u32 irqs = psxRegs.interrupt;
72 u32 cycle = psxRegs.cycle;
75 if ((psxRegs.cycle - psxNextsCounter) >= psxNextCounter)
78 // irq_funcs() may queue more irqs
79 psxRegs.interrupt = 0;
81 for (irq = 0, irq_bits = irqs; irq_bits != 0; irq++, irq_bits >>= 1) {
84 if ((s32)(cycle - event_cycles[irq]) >= 0) {
89 psxRegs.interrupt |= irqs;
91 if ((psxHu32(0x1070) & psxHu32(0x1074)) && (Status & 0x401) == 0x401) {
92 psxException(0x400, 0);
93 pending_exception = 1;
99 evprintf(" +ge %08x, %u->%u\n", psxRegs.pc, psxRegs.cycle, next_interupt);
106 //pending_exception = 1;
108 schedule_timeslice();
110 evprintf(" -ge %08x, %u->%u (%d)\n", psxRegs.pc, psxRegs.cycle,
111 next_interupt, next_interupt - psxRegs.cycle);
115 extern void MTC0(int reg, u32 val);
117 void pcsx_mtc0(u32 reg)
119 evprintf("MTC0 %d #%x @%08x %u\n", reg, readmem_word, psxRegs.pc, psxRegs.cycle);
120 MTC0(reg, readmem_word);
124 void pcsx_mtc0_ds(u32 reg)
126 evprintf("MTC0 %d #%x @%08x %u\n", reg, readmem_word, psxRegs.pc, psxRegs.cycle);
127 MTC0(reg, readmem_word);
130 void new_dyna_save(void)
132 // psxRegs.intCycle is always maintained, no need to convert
135 void new_dyna_restore(void)
138 for (i = 0; i < PSXINT_COUNT; i++)
139 event_cycles[i] = psxRegs.intCycle[i].sCycle + psxRegs.intCycle[i].cycle;
142 void *gte_handlers[64];
144 /* from gte.txt.. not sure if this is any good. */
145 const char gte_cycletab[64] = {
146 /* 1 2 3 4 5 6 7 8 9 a b c d e f */
147 0, 15, 0, 0, 0, 0, 8, 0, 0, 0, 0, 0, 6, 0, 0, 0,
148 8, 8, 8, 19, 13, 0, 44, 0, 0, 0, 0, 17, 11, 0, 14, 0,
149 30, 0, 0, 0, 0, 0, 0, 0, 5, 8, 17, 0, 0, 5, 6, 0,
150 23, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 5, 5, 39,
153 static int ari64_init()
155 extern void (*psxCP2[64])();
156 extern void psxNULL();
157 extern void *psxH_ptr;
161 new_dyna_pcsx_mem_init();
163 for (i = 0; i < ARRAY_SIZE(gte_handlers); i++)
164 if (psxCP2[i] != psxNULL)
165 gte_handlers[i] = psxCP2[i];
172 static void ari64_reset()
174 printf("ari64_reset\n");
175 new_dyna_pcsx_mem_reset();
176 invalidate_all_pages();
177 pending_exception = 1;
180 // execute until predefined leave points
181 // (HLE softcall exit and BIOS fastboot end)
182 static void ari64_execute_until()
184 schedule_timeslice();
186 evprintf("ari64_execute %08x, %u->%u (%d)\n", psxRegs.pc,
187 psxRegs.cycle, next_interupt, next_interupt - psxRegs.cycle);
191 evprintf("ari64_execute end %08x, %u->%u (%d)\n", psxRegs.pc,
192 psxRegs.cycle, next_interupt, next_interupt - psxRegs.cycle);
195 static void ari64_execute()
198 ari64_execute_until();
199 evprintf("drc left @%08x\n", psxRegs.pc);
203 static void ari64_clear(u32 addr, u32 size)
207 size *= 4; /* PCSX uses DMA units */
209 evprintf("ari64_clear %08x %04x\n", addr, size);
211 /* check for RAM mirrors */
212 if ((addr & ~0xe0600000) < 0x200000) {
218 end = (addr + size) >> 12;
220 for (; start <= end; start++)
221 if (!invalid_code[start])
222 invalidate_block(start);
225 static void ari64_shutdown()
227 new_dynarec_cleanup();
230 extern void intExecute();
231 extern void intExecuteT();
232 extern void intExecuteBlock();
233 extern void intExecuteBlockT();
235 #define intExecuteT intExecute
236 #define intExecuteBlockT intExecuteBlock
255 void do_insn_trace() {}
256 void do_insn_cmp() {}
259 #if defined(__x86_64__) || defined(__i386__)
260 unsigned int address, readmem_word, word;
261 unsigned short hword;
263 int pending_exception, stop;
264 unsigned int next_interupt;
266 void new_dynarec_init() {}
267 void new_dyna_start() {}
268 void new_dynarec_cleanup() {}
269 void invalidate_all_pages() {}
270 void invalidate_block(unsigned int block) {}
271 void new_dyna_pcsx_mem_init(void) {}
272 void new_dyna_pcsx_mem_reset(void) {}
279 extern u32 last_io_addr;
281 static void dump_mem(const char *fname, void *mem, size_t size)
283 FILE *f1 = fopen(fname, "wb");
285 f1 = fopen(strrchr(fname, '/') + 1, "wb");
286 fwrite(mem, 1, size, f1);
290 static u32 memcheck_read(u32 a)
292 if ((a >> 16) == 0x1f80)
294 return *(u32 *)(psxH + (a & 0xfffc));
296 if ((a >> 16) == 0x1f00)
298 return *(u32 *)(psxP + (a & 0xfffc));
300 // if ((a & ~0xe0600000) < 0x200000)
302 return *(u32 *)(psxM + (a & 0x1ffffc));
305 void do_insn_trace(void)
307 static psxRegisters oldregs;
308 static u32 old_io_addr = (u32)-1;
309 static u32 old_io_data = 0xbad0c0de;
310 u32 *allregs_p = (void *)&psxRegs;
311 u32 *allregs_o = (void *)&oldregs;
316 //last_io_addr = 0x5e2c8;
318 f = fopen("tracelog", "wb");
320 oldregs.code = psxRegs.code; // don't care
321 for (i = 0; i < offsetof(psxRegisters, intCycle) / 4; i++) {
322 if (allregs_p[i] != allregs_o[i]) {
324 fwrite(&allregs_p[i], 1, 4, f);
325 allregs_o[i] = allregs_p[i];
328 if (old_io_addr != last_io_addr) {
330 fwrite(&byte, 1, 1, f);
331 fwrite(&last_io_addr, 1, 4, f);
332 old_io_addr = last_io_addr;
334 io_data = memcheck_read(last_io_addr);
335 if (old_io_data != io_data) {
337 fwrite(&byte, 1, 1, f);
338 fwrite(&io_data, 1, 4, f);
339 old_io_data = io_data;
342 fwrite(&byte, 1, 1, f);
345 if (psxRegs.cycle == 190230) {
346 dump_mem("/mnt/ntz/dev/pnd/tmp/psxram_i.dump", psxM, 0x200000);
347 dump_mem("/mnt/ntz/dev/pnd/tmp/psxregs_i.dump", psxH, 0x10000);
354 static const char *regnames[offsetof(psxRegisters, intCycle) / 4] = {
355 "r0", "r1", "r2", "r3", "r4", "r5", "r6", "r7",
356 "r8", "r9", "r10", "r11", "r12", "r13", "r14", "r15",
357 "r16", "r17", "r18", "r19", "r20", "r21", "r22", "r23",
358 "r24", "r25", "r26", "r27", "r28", "r29", "r30", "r31",
360 "C0_0", "C0_1", "C0_2", "C0_3", "C0_4", "C0_5", "C0_6", "C0_7",
361 "C0_8", "C0_9", "C0_10", "C0_11", "C0_12", "C0_13", "C0_14", "C0_15",
362 "C0_16", "C0_17", "C0_18", "C0_19", "C0_20", "C0_21", "C0_22", "C0_23",
363 "C0_24", "C0_25", "C0_26", "C0_27", "C0_28", "C0_29", "C0_30", "C0_31",
365 "C2D0", "C2D1", "C2D2", "C2D3", "C2D4", "C2D5", "C2D6", "C2D7",
366 "C2D8", "C2D9", "C2D10", "C2D11", "C2D12", "C2D13", "C2D14", "C2D15",
367 "C2D16", "C2D17", "C2D18", "C2D19", "C2D20", "C2D21", "C2D22", "C2D23",
368 "C2D24", "C2D25", "C2D26", "C2D27", "C2D28", "C2D29", "C2D30", "C2D31",
370 "C2C0", "C2C1", "C2C2", "C2C3", "C2C4", "C2C5", "C2C6", "C2C7",
371 "C2C8", "C2C9", "C2C10", "C2C11", "C2C12", "C2C13", "C2C14", "C2C15",
372 "C2C16", "C2C17", "C2C18", "C2C19", "C2C20", "C2C21", "C2C22", "C2C23",
373 "C2C24", "C2C25", "C2C26", "C2C27", "C2C28", "C2C29", "C2C30", "C2C31",
375 "PC", "code", "cycle", "interrupt",
383 static int miss_log_i;
384 #define miss_log_len (sizeof(miss_log)/sizeof(miss_log[0]))
385 #define miss_log_mask (miss_log_len-1)
387 static void miss_log_add(int reg, u32 val, u32 val_expect, u32 pc, u32 cycle)
389 miss_log[miss_log_i].reg = reg;
390 miss_log[miss_log_i].val = val;
391 miss_log[miss_log_i].val_expect = val_expect;
392 miss_log[miss_log_i].pc = pc;
393 miss_log[miss_log_i].cycle = cycle;
394 miss_log_i = (miss_log_i + 1) & miss_log_mask;
399 void do_insn_cmp(void)
401 static psxRegisters rregs;
402 static u32 mem_addr, mem_val;
403 u32 *allregs_p = (void *)&psxRegs;
404 u32 *allregs_e = (void *)&rregs;
405 static u32 ppc, failcount;
410 f = fopen("tracelog", "rb");
413 if ((ret = fread(&code, 1, 1, f)) <= 0)
420 if ((ret = fread(&mem_addr, 1, 4, f)) <= 0)
425 if ((ret = fread(&mem_val, 1, 4, f)) <= 0)
429 if ((ret = fread(&allregs_e[code], 1, 4, f)) <= 0)
438 psxRegs.code = rregs.code; // don't care
439 psxRegs.cycle = rregs.cycle;
440 psxRegs.CP0.r[9] = rregs.CP0.r[9]; // Count
442 //if (psxRegs.cycle == 166172) breakme();
444 if (memcmp(&psxRegs, &rregs, offsetof(psxRegisters, intCycle)) == 0 &&
445 mem_val == memcheck_read(mem_addr)
451 for (i = 0; i < offsetof(psxRegisters, intCycle) / 4; i++) {
452 if (allregs_p[i] != allregs_e[i]) {
453 miss_log_add(i, allregs_p[i], allregs_e[i], psxRegs.pc, psxRegs.cycle);
458 if (mem_val != memcheck_read(mem_addr)) {
459 printf("bad mem @%08x: %08x %08x\n", mem_addr, memcheck_read(mem_addr), mem_val);
463 if (psxRegs.pc == rregs.pc && bad < 6 && failcount < 32) {
464 static int last_mcycle;
465 if (last_mcycle != psxRegs.cycle >> 20) {
466 printf("%u\n", psxRegs.cycle);
467 last_mcycle = psxRegs.cycle >> 20;
474 for (i = 0; i < miss_log_len; i++, miss_log_i = (miss_log_i + 1) & miss_log_mask)
475 printf("bad %5s: %08x %08x, pc=%08x, cycle %u\n",
476 regnames[miss_log[miss_log_i].reg], miss_log[miss_log_i].val,
477 miss_log[miss_log_i].val_expect, miss_log[miss_log_i].pc, miss_log[miss_log_i].cycle);
478 printf("-- %d\n", bad);
479 for (i = 0; i < 8; i++)
480 printf("r%d=%08x r%2d=%08x r%2d=%08x r%2d=%08x\n", i, allregs_p[i],
481 i+8, allregs_p[i+8], i+16, allregs_p[i+16], i+24, allregs_p[i+24]);
482 printf("PC: %08x/%08x, cycle %u\n", psxRegs.pc, ppc, psxRegs.cycle);
483 dump_mem("/mnt/ntz/dev/pnd/tmp/psxram.dump", psxM, 0x200000);
484 dump_mem("/mnt/ntz/dev/pnd/tmp/psxregs.dump", psxH, 0x10000);
487 psxRegs.cycle = rregs.cycle + 2; // sync timing