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();
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();
178 pending_exception = 1;
181 // execute until predefined leave points
182 // (HLE softcall exit and BIOS fastboot end)
183 static void ari64_execute_until()
185 schedule_timeslice();
187 evprintf("ari64_execute %08x, %u->%u (%d)\n", psxRegs.pc,
188 psxRegs.cycle, next_interupt, next_interupt - psxRegs.cycle);
192 evprintf("ari64_execute end %08x, %u->%u (%d)\n", psxRegs.pc,
193 psxRegs.cycle, next_interupt, next_interupt - psxRegs.cycle);
196 static void ari64_execute()
199 ari64_execute_until();
200 evprintf("drc left @%08x\n", psxRegs.pc);
204 static void ari64_clear(u32 addr, u32 size)
206 u32 start, end, main_ram;
208 size *= 4; /* PCSX uses DMA units */
210 evprintf("ari64_clear %08x %04x\n", addr, size);
212 /* check for RAM mirrors */
213 main_ram = (addr & 0xffe00000) == 0x80000000;
216 end = (addr + size) >> 12;
218 for (; start <= end; start++)
219 if (!main_ram || !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