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 new_dyna_save(void)
123 // psxRegs.intCycle is always maintained, no need to convert
126 void new_dyna_restore(void)
129 for (i = 0; i < PSXINT_NEWDRC_CHECK; i++)
130 event_cycles[i] = psxRegs.intCycle[i].sCycle + psxRegs.intCycle[i].cycle;
133 void *gte_handlers[64];
135 /* from gte.txt.. not sure if this is any good. */
136 const char gte_cycletab[64] = {
137 /* 1 2 3 4 5 6 7 8 9 a b c d e f */
138 0, 15, 0, 0, 0, 0, 8, 0, 0, 0, 0, 0, 6, 0, 0, 0,
139 8, 8, 8, 19, 13, 0, 44, 0, 0, 0, 0, 17, 11, 0, 14, 0,
140 30, 0, 0, 0, 0, 0, 0, 0, 5, 8, 17, 0, 0, 5, 6, 0,
141 23, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 5, 5, 39,
144 static int ari64_init()
146 extern void (*psxCP2[64])();
147 extern void psxNULL();
148 extern void *psxH_ptr;
152 new_dyna_pcsx_mem_init();
154 for (i = 0; i < ARRAY_SIZE(gte_handlers); i++)
155 if (psxCP2[i] != psxNULL)
156 gte_handlers[i] = psxCP2[i];
163 static void ari64_reset()
165 printf("ari64_reset\n");
166 new_dyna_pcsx_mem_reset();
167 invalidate_all_pages();
168 pending_exception = 1;
171 static void ari64_execute()
173 schedule_timeslice();
175 evprintf("ari64_execute %08x, %u->%u (%d)\n", psxRegs.pc,
176 psxRegs.cycle, next_interupt, next_interupt - psxRegs.cycle);
180 evprintf("ari64_execute end %08x, %u->%u (%d)\n", psxRegs.pc,
181 psxRegs.cycle, next_interupt, next_interupt - psxRegs.cycle);
184 static void ari64_clear(u32 addr, u32 size)
188 evprintf("ari64_clear %08x %04x\n", addr, size);
190 /* check for RAM mirrors */
191 if ((addr & ~0xe0600000) < 0x200000) {
197 end = (addr + size) >> 12;
199 for (; start <= end; start++)
200 if (!invalid_code[start])
201 invalidate_block(start);
204 static void ari64_shutdown()
206 new_dynarec_cleanup();
209 extern void intExecute();
210 extern void intExecuteT();
211 extern void intExecuteBlock();
212 extern void intExecuteBlockT();
214 #define intExecuteT intExecute
215 #define intExecuteBlockT intExecuteBlock
234 void do_insn_trace() {}
235 void do_insn_cmp() {}
238 #if defined(__x86_64__) || defined(__i386__)
239 unsigned int address, readmem_word, word;
240 unsigned short hword;
242 int pending_exception, stop;
243 unsigned int next_interupt;
245 void new_dynarec_init() {}
246 void new_dyna_start() {}
247 void new_dynarec_cleanup() {}
248 void invalidate_all_pages() {}
249 void invalidate_block(unsigned int block) {}
250 void new_dyna_pcsx_mem_init(void) {}
251 void new_dyna_pcsx_mem_reset(void) {}
258 extern u32 last_io_addr;
260 static void dump_mem(const char *fname, void *mem, size_t size)
262 FILE *f1 = fopen(fname, "wb");
264 f1 = fopen(strrchr(fname, '/') + 1, "wb");
265 fwrite(mem, 1, size, f1);
269 static u32 memcheck_read(u32 a)
271 if ((a >> 16) == 0x1f80)
273 return *(u32 *)(psxH + (a & 0xfffc));
275 if ((a >> 16) == 0x1f00)
277 return *(u32 *)(psxP + (a & 0xfffc));
279 // if ((a & ~0xe0600000) < 0x200000)
281 return *(u32 *)(psxM + (a & 0x1ffffc));
284 void do_insn_trace(void)
286 static psxRegisters oldregs;
287 static u32 old_io_addr = (u32)-1;
288 static u32 old_io_data = 0xbad0c0de;
289 u32 *allregs_p = (void *)&psxRegs;
290 u32 *allregs_o = (void *)&oldregs;
295 //last_io_addr = 0x5e2c8;
297 f = fopen("tracelog", "wb");
299 oldregs.code = psxRegs.code; // don't care
300 for (i = 0; i < offsetof(psxRegisters, intCycle) / 4; i++) {
301 if (allregs_p[i] != allregs_o[i]) {
303 fwrite(&allregs_p[i], 1, 4, f);
304 allregs_o[i] = allregs_p[i];
307 if (old_io_addr != last_io_addr) {
309 fwrite(&byte, 1, 1, f);
310 fwrite(&last_io_addr, 1, 4, f);
311 old_io_addr = last_io_addr;
313 io_data = memcheck_read(last_io_addr);
314 if (old_io_data != io_data) {
316 fwrite(&byte, 1, 1, f);
317 fwrite(&io_data, 1, 4, f);
318 old_io_data = io_data;
321 fwrite(&byte, 1, 1, f);
324 if (psxRegs.cycle == 190230) {
325 dump_mem("/mnt/ntz/dev/pnd/tmp/psxram_i.dump", psxM, 0x200000);
326 dump_mem("/mnt/ntz/dev/pnd/tmp/psxregs_i.dump", psxH, 0x10000);
333 static const char *regnames[offsetof(psxRegisters, intCycle) / 4] = {
334 "r0", "r1", "r2", "r3", "r4", "r5", "r6", "r7",
335 "r8", "r9", "r10", "r11", "r12", "r13", "r14", "r15",
336 "r16", "r17", "r18", "r19", "r20", "r21", "r22", "r23",
337 "r24", "r25", "r26", "r27", "r28", "r29", "r30", "r31",
339 "C0_0", "C0_1", "C0_2", "C0_3", "C0_4", "C0_5", "C0_6", "C0_7",
340 "C0_8", "C0_9", "C0_10", "C0_11", "C0_12", "C0_13", "C0_14", "C0_15",
341 "C0_16", "C0_17", "C0_18", "C0_19", "C0_20", "C0_21", "C0_22", "C0_23",
342 "C0_24", "C0_25", "C0_26", "C0_27", "C0_28", "C0_29", "C0_30", "C0_31",
344 "C2D0", "C2D1", "C2D2", "C2D3", "C2D4", "C2D5", "C2D6", "C2D7",
345 "C2D8", "C2D9", "C2D10", "C2D11", "C2D12", "C2D13", "C2D14", "C2D15",
346 "C2D16", "C2D17", "C2D18", "C2D19", "C2D20", "C2D21", "C2D22", "C2D23",
347 "C2D24", "C2D25", "C2D26", "C2D27", "C2D28", "C2D29", "C2D30", "C2D31",
349 "C2C0", "C2C1", "C2C2", "C2C3", "C2C4", "C2C5", "C2C6", "C2C7",
350 "C2C8", "C2C9", "C2C10", "C2C11", "C2C12", "C2C13", "C2C14", "C2C15",
351 "C2C16", "C2C17", "C2C18", "C2C19", "C2C20", "C2C21", "C2C22", "C2C23",
352 "C2C24", "C2C25", "C2C26", "C2C27", "C2C28", "C2C29", "C2C30", "C2C31",
354 "PC", "code", "cycle", "interrupt",
362 static int miss_log_i;
363 #define miss_log_len (sizeof(miss_log)/sizeof(miss_log[0]))
364 #define miss_log_mask (miss_log_len-1)
366 static void miss_log_add(int reg, u32 val, u32 val_expect, u32 pc, u32 cycle)
368 miss_log[miss_log_i].reg = reg;
369 miss_log[miss_log_i].val = val;
370 miss_log[miss_log_i].val_expect = val_expect;
371 miss_log[miss_log_i].pc = pc;
372 miss_log[miss_log_i].cycle = cycle;
373 miss_log_i = (miss_log_i + 1) & miss_log_mask;
378 void do_insn_cmp(void)
380 static psxRegisters rregs;
381 static u32 mem_addr, mem_val;
382 u32 *allregs_p = (void *)&psxRegs;
383 u32 *allregs_e = (void *)&rregs;
384 static u32 ppc, failcount;
389 f = fopen("tracelog", "rb");
392 if ((ret = fread(&code, 1, 1, f)) <= 0)
399 if ((ret = fread(&mem_addr, 1, 4, f)) <= 0)
404 if ((ret = fread(&mem_val, 1, 4, f)) <= 0)
408 if ((ret = fread(&allregs_e[code], 1, 4, f)) <= 0)
417 psxRegs.code = rregs.code; // don't care
418 psxRegs.cycle = rregs.cycle;
419 psxRegs.CP0.r[9] = rregs.CP0.r[9]; // Count
421 //if (psxRegs.cycle == 166172) breakme();
423 if (memcmp(&psxRegs, &rregs, offsetof(psxRegisters, intCycle)) == 0 &&
424 mem_val == memcheck_read(mem_addr)
430 for (i = 0; i < offsetof(psxRegisters, intCycle) / 4; i++) {
431 if (allregs_p[i] != allregs_e[i]) {
432 miss_log_add(i, allregs_p[i], allregs_e[i], psxRegs.pc, psxRegs.cycle);
437 if (mem_val != memcheck_read(mem_addr)) {
438 printf("bad mem @%08x: %08x %08x\n", mem_addr, memcheck_read(mem_addr), mem_val);
442 if (psxRegs.pc == rregs.pc && bad < 6 && failcount < 32) {
443 static int last_mcycle;
444 if (last_mcycle != psxRegs.cycle >> 20) {
445 printf("%u\n", psxRegs.cycle);
446 last_mcycle = psxRegs.cycle >> 20;
453 for (i = 0; i < miss_log_len; i++, miss_log_i = (miss_log_i + 1) & miss_log_mask)
454 printf("bad %5s: %08x %08x, pc=%08x, cycle %u\n",
455 regnames[miss_log[miss_log_i].reg], miss_log[miss_log_i].val,
456 miss_log[miss_log_i].val_expect, miss_log[miss_log_i].pc, miss_log[miss_log_i].cycle);
457 printf("-- %d\n", bad);
458 for (i = 0; i < 8; i++)
459 printf("r%d=%08x r%2d=%08x r%2d=%08x r%2d=%08x\n", i, allregs_p[i],
460 i+8, allregs_p[i+8], i+16, allregs_p[i+16], i+24, allregs_p[i+24]);
461 printf("PC: %08x/%08x, cycle %u\n", psxRegs.pc, ppc, psxRegs.cycle);
462 dump_mem("/mnt/ntz/dev/pnd/tmp/psxram.dump", psxM, 0x200000);
463 dump_mem("/mnt/ntz/dev/pnd/tmp/psxregs.dump", psxH, 0x10000);
466 psxRegs.cycle = rregs.cycle + 2; // sync timing