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,
64 /* local dupe of psxBranchTest, using event_cycles */
65 static void irq_test(void)
67 u32 irqs = psxRegs.interrupt;
68 u32 cycle = psxRegs.cycle;
71 if ((psxRegs.cycle - psxNextsCounter) >= psxNextCounter)
74 // irq_funcs() may queue more irqs
75 psxRegs.interrupt = 0;
77 for (irq = 0, irq_bits = irqs; irq_bits != 0; irq++, irq_bits >>= 1) {
80 if ((s32)(cycle - event_cycles[irq]) >= 0) {
85 psxRegs.interrupt |= irqs;
87 if ((psxHu32(0x1070) & psxHu32(0x1074)) && (Status & 0x401) == 0x401) {
88 psxException(0x400, 0);
89 pending_exception = 1;
95 evprintf(" +ge %08x, %u->%u\n", psxRegs.pc, psxRegs.cycle, next_interupt);
102 //pending_exception = 1;
104 schedule_timeslice();
106 evprintf(" -ge %08x, %u->%u (%d)\n", psxRegs.pc, psxRegs.cycle,
107 next_interupt, next_interupt - psxRegs.cycle);
112 extern void psxMTC0();
114 evprintf("ari64 MTC0 %08x %08x %u\n", psxRegs.code, psxRegs.pc, psxRegs.cycle);
116 gen_interupt(); /* FIXME: checking pending irqs should be enough */
119 void check_interupt()
121 /* FIXME (also asm) */
122 printf("ari64_check_interupt\n");
125 void new_dyna_save(void)
127 // psxRegs.intCycle is always maintained, no need to convert
130 void new_dyna_restore(void)
133 for (i = 0; i < PSXINT_NEWDRC_CHECK; i++)
134 event_cycles[i] = psxRegs.intCycle[i].sCycle + psxRegs.intCycle[i].cycle;
137 void *gte_handlers[64];
139 /* from gte.txt.. not sure if this is any good. */
140 const char gte_cycletab[64] = {
141 /* 1 2 3 4 5 6 7 8 9 a b c d e f */
142 0, 15, 0, 0, 0, 0, 8, 0, 0, 0, 0, 0, 6, 0, 0, 0,
143 8, 8, 8, 19, 13, 0, 44, 0, 0, 0, 0, 17, 11, 0, 14, 0,
144 30, 0, 0, 0, 0, 0, 0, 0, 5, 8, 17, 0, 0, 5, 6, 0,
145 23, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 5, 5, 39,
148 static int ari64_init()
150 extern void (*psxCP2[64])();
151 extern void psxNULL();
152 extern void *psxH_ptr;
156 new_dyna_pcsx_mem_init();
158 for (i = 0; i < ARRAY_SIZE(gte_handlers); i++)
159 if (psxCP2[i] != psxNULL)
160 gte_handlers[i] = psxCP2[i];
167 static void ari64_reset()
169 printf("ari64_reset\n");
170 new_dyna_pcsx_mem_reset();
171 invalidate_all_pages();
172 pending_exception = 1;
175 static void ari64_execute()
177 schedule_timeslice();
179 evprintf("ari64_execute %08x, %u->%u (%d)\n", psxRegs.pc,
180 psxRegs.cycle, next_interupt, next_interupt - psxRegs.cycle);
184 evprintf("ari64_execute end %08x, %u->%u (%d)\n", psxRegs.pc,
185 psxRegs.cycle, next_interupt, next_interupt - psxRegs.cycle);
188 static void ari64_clear(u32 addr, u32 size)
192 evprintf("ari64_clear %08x %04x\n", addr, size);
194 /* check for RAM mirrors */
195 if ((addr & ~0xe0600000) < 0x200000) {
201 end = (addr + size) >> 12;
203 for (; start <= end; start++)
204 if (!invalid_code[start])
205 invalidate_block(start);
208 static void ari64_shutdown()
210 new_dynarec_cleanup();
213 extern void intExecute();
214 extern void intExecuteT();
215 extern void intExecuteBlock();
216 extern void intExecuteBlockT();
218 #define intExecuteT intExecute
219 #define intExecuteBlockT intExecuteBlock
238 void do_insn_trace() {}
239 void do_insn_cmp() {}
242 #if defined(__x86_64__) || defined(__i386__)
243 unsigned int address, readmem_word, word;
244 unsigned short hword;
246 int pending_exception, stop;
247 unsigned int next_interupt;
249 void new_dynarec_init() {}
250 void new_dyna_start() {}
251 void new_dynarec_cleanup() {}
252 void invalidate_all_pages() {}
253 void invalidate_block(unsigned int block) {}
254 void new_dyna_pcsx_mem_init(void) {}
255 void new_dyna_pcsx_mem_reset(void) {}
262 extern u32 last_io_addr;
264 static void dump_mem(const char *fname, void *mem, size_t size)
266 FILE *f1 = fopen(fname, "wb");
268 f1 = fopen(strrchr(fname, '/') + 1, "wb");
269 fwrite(mem, 1, size, f1);
273 void do_insn_trace(void)
275 static psxRegisters oldregs;
276 static u32 old_io_addr = (u32)-1;
277 static u32 old_io_data = 0xbad0c0de;
278 u32 *allregs_p = (void *)&psxRegs;
279 u32 *allregs_o = (void *)&oldregs;
284 //last_io_addr = 0x5e2c8;
286 f = fopen("tracelog", "wb");
288 oldregs.code = psxRegs.code; // don't care
289 for (i = 0; i < offsetof(psxRegisters, intCycle) / 4; i++) {
290 if (allregs_p[i] != allregs_o[i]) {
292 fwrite(&allregs_p[i], 1, 4, f);
293 allregs_o[i] = allregs_p[i];
296 if (old_io_addr != last_io_addr) {
298 fwrite(&byte, 1, 1, f);
299 fwrite(&last_io_addr, 1, 4, f);
300 old_io_addr = last_io_addr;
302 io_data = (void *)(psxM + (last_io_addr&0x1ffffc));
303 if (old_io_data != *io_data) {
305 fwrite(&byte, 1, 1, f);
306 fwrite(io_data, 1, 4, f);
307 old_io_data = *io_data;
310 fwrite(&byte, 1, 1, f);
313 if (psxRegs.cycle == 190230) {
314 dump_mem("/mnt/ntz/dev/pnd/tmp/psxram_i.dump", psxM, 0x200000);
315 dump_mem("/mnt/ntz/dev/pnd/tmp/psxregs_i.dump", psxH, 0x10000);
322 static const char *regnames[offsetof(psxRegisters, intCycle) / 4] = {
323 "r0", "r1", "r2", "r3", "r4", "r5", "r6", "r7",
324 "r8", "r9", "r10", "r11", "r12", "r13", "r14", "r15",
325 "r16", "r17", "r18", "r19", "r20", "r21", "r22", "r23",
326 "r24", "r25", "r26", "r27", "r28", "r29", "r30", "r31",
328 "C0_0", "C0_1", "C0_2", "C0_3", "C0_4", "C0_5", "C0_6", "C0_7",
329 "C0_8", "C0_9", "C0_10", "C0_11", "C0_12", "C0_13", "C0_14", "C0_15",
330 "C0_16", "C0_17", "C0_18", "C0_19", "C0_20", "C0_21", "C0_22", "C0_23",
331 "C0_24", "C0_25", "C0_26", "C0_27", "C0_28", "C0_29", "C0_30", "C0_31",
333 "C2D0", "C2D1", "C2D2", "C2D3", "C2D4", "C2D5", "C2D6", "C2D7",
334 "C2D8", "C2D9", "C2D10", "C2D11", "C2D12", "C2D13", "C2D14", "C2D15",
335 "C2D16", "C2D17", "C2D18", "C2D19", "C2D20", "C2D21", "C2D22", "C2D23",
336 "C2D24", "C2D25", "C2D26", "C2D27", "C2D28", "C2D29", "C2D30", "C2D31",
338 "C2C0", "C2C1", "C2C2", "C2C3", "C2C4", "C2C5", "C2C6", "C2C7",
339 "C2C8", "C2C9", "C2C10", "C2C11", "C2C12", "C2C13", "C2C14", "C2C15",
340 "C2C16", "C2C17", "C2C18", "C2C19", "C2C20", "C2C21", "C2C22", "C2C23",
341 "C2C24", "C2C25", "C2C26", "C2C27", "C2C28", "C2C29", "C2C30", "C2C31",
343 "PC", "code", "cycle", "interrupt",
351 static int miss_log_i;
352 #define miss_log_len (sizeof(miss_log)/sizeof(miss_log[0]))
353 #define miss_log_mask (miss_log_len-1)
355 static void miss_log_add(int reg, u32 val, u32 val_expect, u32 pc, u32 cycle)
357 miss_log[miss_log_i].reg = reg;
358 miss_log[miss_log_i].val = val;
359 miss_log[miss_log_i].val_expect = val_expect;
360 miss_log[miss_log_i].pc = pc;
361 miss_log[miss_log_i].cycle = cycle;
362 miss_log_i = (miss_log_i + 1) & miss_log_mask;
367 void do_insn_cmp(void)
369 static psxRegisters rregs;
370 static u32 mem_addr, mem_val;
371 u32 *allregs_p = (void *)&psxRegs;
372 u32 *allregs_e = (void *)&rregs;
373 static u32 ppc, failcount;
378 f = fopen("tracelog", "rb");
381 if ((ret = fread(&code, 1, 1, f)) <= 0)
388 if ((ret = fread(&mem_addr, 1, 4, f)) <= 0)
393 if ((ret = fread(&mem_val, 1, 4, f)) <= 0)
397 if ((ret = fread(&allregs_e[code], 1, 4, f)) <= 0)
406 psxRegs.code = rregs.code; // don't care
407 psxRegs.cycle = rregs.cycle;
408 psxRegs.CP0.r[9] = rregs.CP0.r[9]; // Count
410 //if (psxRegs.cycle == 166172) breakme();
411 //if (psxRegs.cycle > 11296376) printf("pc=%08x %u %08x\n", psxRegs.pc, psxRegs.cycle, psxRegs.interrupt);
413 mem_addr &= 0x1ffffc;
415 if (memcmp(&psxRegs, &rregs, offsetof(psxRegisters, intCycle)) == 0 &&
416 mem_val == *(u32 *)(psxM + mem_addr)
422 for (i = 0; i < offsetof(psxRegisters, intCycle) / 4; i++) {
423 if (allregs_p[i] != allregs_e[i]) {
424 miss_log_add(i, allregs_p[i], allregs_e[i], psxRegs.pc, psxRegs.cycle);
429 if (mem_val != *(u32 *)(psxM + mem_addr)) {
430 printf("bad mem @%08x: %08x %08x\n", mem_addr, *(u32 *)(psxM + mem_addr), mem_val);
434 if (psxRegs.pc == rregs.pc && bad < 6 && failcount < 32) {
435 static int last_mcycle;
436 if (last_mcycle != psxRegs.cycle >> 20) {
437 printf("%u\n", psxRegs.cycle);
438 last_mcycle = psxRegs.cycle >> 20;
445 for (i = 0; i < miss_log_len; i++, miss_log_i = (miss_log_i + 1) & miss_log_mask)
446 printf("bad %5s: %08x %08x, pc=%08x, cycle %u\n",
447 regnames[miss_log[miss_log_i].reg], miss_log[miss_log_i].val,
448 miss_log[miss_log_i].val_expect, miss_log[miss_log_i].pc, miss_log[miss_log_i].cycle);
449 printf("-- %d\n", bad);
450 for (i = 0; i < 8; i++)
451 printf("r%d=%08x r%2d=%08x r%2d=%08x r%2d=%08x\n", i, allregs_p[i],
452 i+8, allregs_p[i+8], i+16, allregs_p[i+16], i+24, allregs_p[i+24]);
453 printf("PC: %08x/%08x, cycle %u\n", psxRegs.pc, ppc, psxRegs.cycle);
454 dump_mem("/mnt/ntz/dev/pnd/tmp/psxram.dump", psxM, 0x200000);
455 dump_mem("/mnt/ntz/dev/pnd/tmp/psxregs.dump", psxH, 0x10000);
458 psxRegs.cycle = rregs.cycle + 2; // sync timing