2 * (C) GraÅžvydas "notaz" Ignotas, 2010-2011
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"
17 #include "../gte_arm.h"
18 #include "../gte_neon.h"
22 #define ARRAY_SIZE(x) (sizeof(x) / sizeof(x[0]))
24 //#define evprintf printf
27 char invalid_code[0x100000];
28 u32 event_cycles[PSXINT_COUNT];
30 static void schedule_timeslice(void)
32 u32 i, c = psxRegs.cycle;
35 min = psxNextsCounter + psxNextCounter - c;
36 for (i = 0; i < ARRAY_SIZE(event_cycles); i++) {
37 dif = event_cycles[i] - c;
38 //evprintf(" ev %d\n", dif);
39 if (0 < dif && dif < min)
42 next_interupt = c + min;
45 static u32 cnt, last_cycle;
49 sum += psxRegs.cycle - last_cycle;
50 if ((cnt & 0xff) == 0)
51 printf("%u\n", (u32)(sum / cnt));
53 last_cycle = psxRegs.cycle;
57 typedef void (irq_func)();
59 static irq_func * const irq_funcs[] = {
60 [PSXINT_SIO] = sioInterrupt,
61 [PSXINT_CDR] = cdrInterrupt,
62 [PSXINT_CDREAD] = cdrReadInterrupt,
63 [PSXINT_GPUDMA] = gpuInterrupt,
64 [PSXINT_MDECOUTDMA] = mdec1Interrupt,
65 [PSXINT_SPUDMA] = spuInterrupt,
66 [PSXINT_MDECINDMA] = mdec0Interrupt,
67 [PSXINT_GPUOTCDMA] = gpuotcInterrupt,
68 [PSXINT_CDRDMA] = cdrDmaInterrupt,
69 [PSXINT_CDRLID] = cdrLidSeekInterrupt,
70 [PSXINT_CDRPLAY] = cdrPlayInterrupt,
73 /* local dupe of psxBranchTest, using event_cycles */
74 static void irq_test(void)
76 u32 irqs = psxRegs.interrupt;
77 u32 cycle = psxRegs.cycle;
80 if ((psxRegs.cycle - psxNextsCounter) >= psxNextCounter)
83 // irq_funcs() may queue more irqs
84 psxRegs.interrupt = 0;
86 for (irq = 0, irq_bits = irqs; irq_bits != 0; irq++, irq_bits >>= 1) {
89 if ((s32)(cycle - event_cycles[irq]) >= 0) {
94 psxRegs.interrupt |= irqs;
96 if ((psxHu32(0x1070) & psxHu32(0x1074)) && (Status & 0x401) == 0x401) {
97 psxException(0x400, 0);
98 pending_exception = 1;
104 evprintf(" +ge %08x, %u->%u\n", psxRegs.pc, psxRegs.cycle, next_interupt);
108 //pending_exception = 1;
110 schedule_timeslice();
112 evprintf(" -ge %08x, %u->%u (%d)\n", psxRegs.pc, psxRegs.cycle,
113 next_interupt, next_interupt - psxRegs.cycle);
117 extern void MTC0(int reg, u32 val);
119 void pcsx_mtc0(u32 reg)
121 evprintf("MTC0 %d #%x @%08x %u\n", reg, readmem_word, psxRegs.pc, psxRegs.cycle);
122 MTC0(reg, readmem_word);
126 void pcsx_mtc0_ds(u32 reg)
128 evprintf("MTC0 %d #%x @%08x %u\n", reg, readmem_word, psxRegs.pc, psxRegs.cycle);
129 MTC0(reg, readmem_word);
132 void new_dyna_save(void)
134 // psxRegs.intCycle is always maintained, no need to convert
137 void new_dyna_restore(void)
140 for (i = 0; i < PSXINT_COUNT; i++)
141 event_cycles[i] = psxRegs.intCycle[i].sCycle + psxRegs.intCycle[i].cycle;
144 void *gte_handlers[64];
146 void *gte_handlers_nf[64] = {
147 NULL , gteRTPS_nf , NULL , NULL , NULL , NULL , gteNCLIP_nf, NULL , // 00
148 NULL , NULL , NULL , NULL , gteOP_nf , NULL , NULL , NULL , // 08
149 gteDPCS_nf, gteINTPL_nf, gteMVMVA_nf, gteNCDS_nf, gteCDP_nf, NULL , gteNCDT_nf , NULL , // 10
150 NULL , NULL , NULL , gteNCCS_nf, gteCC_nf , NULL , gteNCS_nf , NULL , // 18
151 gteNCT_nf , NULL , NULL , NULL , NULL , NULL , NULL , NULL , // 20
152 gteSQR_nf , gteDCPL_nf , gteDPCT_nf , NULL , NULL , gteAVSZ3_nf, gteAVSZ4_nf, NULL , // 28
153 gteRTPT_nf, NULL , NULL , NULL , NULL , NULL , NULL , NULL , // 30
154 NULL , NULL , NULL , NULL , NULL , gteGPF_nf , gteGPL_nf , gteNCCT_nf, // 38
157 const char *gte_regnames[64] = {
158 NULL , "RTPS" , NULL , NULL , NULL , NULL , "NCLIP", NULL , // 00
159 NULL , NULL , NULL , NULL , "OP" , NULL , NULL , NULL , // 08
160 "DPCS", "INTPL", "MVMVA", "NCDS", "CDP", NULL , "NCDT" , NULL , // 10
161 NULL , NULL , NULL , "NCCS", "CC" , NULL , "NCS" , NULL , // 18
162 "NCT" , NULL , NULL , NULL , NULL , NULL , NULL , NULL , // 20
163 "SQR" , "DCPL" , "DPCT" , NULL , NULL , "AVSZ3", "AVSZ4", NULL , // 28
164 "RTPT", NULL , NULL , NULL , NULL , NULL , NULL , NULL , // 30
165 NULL , NULL , NULL , NULL , NULL , "GPF" , "GPL" , "NCCT", // 38
168 /* from gte.txt.. not sure if this is any good. */
169 const char gte_cycletab[64] = {
170 /* 1 2 3 4 5 6 7 8 9 a b c d e f */
171 0, 15, 0, 0, 0, 0, 8, 0, 0, 0, 0, 0, 6, 0, 0, 0,
172 8, 8, 8, 19, 13, 0, 44, 0, 0, 0, 0, 17, 11, 0, 14, 0,
173 30, 0, 0, 0, 0, 0, 0, 0, 5, 8, 17, 0, 0, 5, 6, 0,
174 23, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 5, 5, 39,
177 static int ari64_init()
179 extern void (*psxCP2[64])();
180 extern void psxNULL();
184 new_dyna_pcsx_mem_init();
186 for (i = 0; i < ARRAY_SIZE(gte_handlers); i++)
187 if (psxCP2[i] != psxNULL)
188 gte_handlers[i] = psxCP2[i];
190 #if !defined(DRC_DBG) && !defined(PCNT)
192 gte_handlers[0x06] = gteNCLIP_arm;
193 gte_handlers_nf[0x01] = gteRTPS_nf_arm;
194 gte_handlers_nf[0x30] = gteRTPT_nf_arm;
197 // compiler's _nf version is still a lot slower then neon
198 // _nf_arm RTPS is roughly the same, RTPT slower
199 gte_handlers[0x01] = gte_handlers_nf[0x01] = gteRTPS_neon;
200 gte_handlers[0x30] = gte_handlers_nf[0x30] = gteRTPT_neon;
201 gte_handlers[0x12] = gte_handlers_nf[0x12] = gteMVMVA_neon;
205 memcpy(gte_handlers_nf, gte_handlers, sizeof(gte_handlers_nf));
212 static void ari64_reset()
214 printf("ari64_reset\n");
215 new_dyna_pcsx_mem_reset();
216 invalidate_all_pages();
218 pending_exception = 1;
221 // execute until predefined leave points
222 // (HLE softcall exit and BIOS fastboot end)
223 static void ari64_execute_until()
225 schedule_timeslice();
227 evprintf("ari64_execute %08x, %u->%u (%d)\n", psxRegs.pc,
228 psxRegs.cycle, next_interupt, next_interupt - psxRegs.cycle);
232 evprintf("ari64_execute end %08x, %u->%u (%d)\n", psxRegs.pc,
233 psxRegs.cycle, next_interupt, next_interupt - psxRegs.cycle);
236 static void ari64_execute()
239 ari64_execute_until();
240 evprintf("drc left @%08x\n", psxRegs.pc);
244 static void ari64_clear(u32 addr, u32 size)
246 u32 start, end, main_ram;
248 size *= 4; /* PCSX uses DMA units */
250 evprintf("ari64_clear %08x %04x\n", addr, size);
252 /* check for RAM mirrors */
253 main_ram = (addr & 0xffe00000) == 0x80000000;
256 end = (addr + size) >> 12;
258 for (; start <= end; start++)
259 if (!main_ram || !invalid_code[start])
260 invalidate_block(start);
263 static void ari64_shutdown()
265 new_dynarec_cleanup();
268 extern void intExecute();
269 extern void intExecuteT();
270 extern void intExecuteBlock();
271 extern void intExecuteBlockT();
273 #define intExecuteT intExecute
274 #define intExecuteBlockT intExecuteBlock
293 void do_insn_trace() {}
294 void do_insn_cmp() {}
297 #if defined(__x86_64__) || defined(__i386__)
298 unsigned int address, readmem_word, word;
299 unsigned short hword;
301 int pending_exception, stop;
302 unsigned int next_interupt;
304 void new_dynarec_init() {}
305 void new_dyna_start() {}
306 void new_dynarec_cleanup() {}
307 void new_dynarec_clear_full() {}
308 void invalidate_all_pages() {}
309 void invalidate_block(unsigned int block) {}
310 void new_dyna_pcsx_mem_init(void) {}
311 void new_dyna_pcsx_mem_reset(void) {}
318 extern u32 last_io_addr;
320 static void dump_mem(const char *fname, void *mem, size_t size)
322 FILE *f1 = fopen(fname, "wb");
324 f1 = fopen(strrchr(fname, '/') + 1, "wb");
325 fwrite(mem, 1, size, f1);
329 static u32 memcheck_read(u32 a)
331 if ((a >> 16) == 0x1f80)
333 return *(u32 *)(psxH + (a & 0xfffc));
335 if ((a >> 16) == 0x1f00)
337 return *(u32 *)(psxP + (a & 0xfffc));
339 // if ((a & ~0xe0600000) < 0x200000)
341 return *(u32 *)(psxM + (a & 0x1ffffc));
344 void do_insn_trace(void)
346 static psxRegisters oldregs;
347 static u32 old_io_addr = (u32)-1;
348 static u32 old_io_data = 0xbad0c0de;
349 u32 *allregs_p = (void *)&psxRegs;
350 u32 *allregs_o = (void *)&oldregs;
355 //last_io_addr = 0x5e2c8;
357 f = fopen("tracelog", "wb");
359 oldregs.code = psxRegs.code; // don't care
360 for (i = 0; i < offsetof(psxRegisters, intCycle) / 4; i++) {
361 if (allregs_p[i] != allregs_o[i]) {
363 fwrite(&allregs_p[i], 1, 4, f);
364 allregs_o[i] = allregs_p[i];
367 if (old_io_addr != last_io_addr) {
369 fwrite(&byte, 1, 1, f);
370 fwrite(&last_io_addr, 1, 4, f);
371 old_io_addr = last_io_addr;
373 io_data = memcheck_read(last_io_addr);
374 if (old_io_data != io_data) {
376 fwrite(&byte, 1, 1, f);
377 fwrite(&io_data, 1, 4, f);
378 old_io_data = io_data;
381 fwrite(&byte, 1, 1, f);
384 if (psxRegs.cycle == 190230) {
385 dump_mem("/mnt/ntz/dev/pnd/tmp/psxram_i.dump", psxM, 0x200000);
386 dump_mem("/mnt/ntz/dev/pnd/tmp/psxregs_i.dump", psxH, 0x10000);
393 static const char *regnames[offsetof(psxRegisters, intCycle) / 4] = {
394 "r0", "r1", "r2", "r3", "r4", "r5", "r6", "r7",
395 "r8", "r9", "r10", "r11", "r12", "r13", "r14", "r15",
396 "r16", "r17", "r18", "r19", "r20", "r21", "r22", "r23",
397 "r24", "r25", "r26", "r27", "r28", "r29", "r30", "r31",
399 "C0_0", "C0_1", "C0_2", "C0_3", "C0_4", "C0_5", "C0_6", "C0_7",
400 "C0_8", "C0_9", "C0_10", "C0_11", "C0_12", "C0_13", "C0_14", "C0_15",
401 "C0_16", "C0_17", "C0_18", "C0_19", "C0_20", "C0_21", "C0_22", "C0_23",
402 "C0_24", "C0_25", "C0_26", "C0_27", "C0_28", "C0_29", "C0_30", "C0_31",
404 "C2D0", "C2D1", "C2D2", "C2D3", "C2D4", "C2D5", "C2D6", "C2D7",
405 "C2D8", "C2D9", "C2D10", "C2D11", "C2D12", "C2D13", "C2D14", "C2D15",
406 "C2D16", "C2D17", "C2D18", "C2D19", "C2D20", "C2D21", "C2D22", "C2D23",
407 "C2D24", "C2D25", "C2D26", "C2D27", "C2D28", "C2D29", "C2D30", "C2D31",
409 "C2C0", "C2C1", "C2C2", "C2C3", "C2C4", "C2C5", "C2C6", "C2C7",
410 "C2C8", "C2C9", "C2C10", "C2C11", "C2C12", "C2C13", "C2C14", "C2C15",
411 "C2C16", "C2C17", "C2C18", "C2C19", "C2C20", "C2C21", "C2C22", "C2C23",
412 "C2C24", "C2C25", "C2C26", "C2C27", "C2C28", "C2C29", "C2C30", "C2C31",
414 "PC", "code", "cycle", "interrupt",
422 static int miss_log_i;
423 #define miss_log_len (sizeof(miss_log)/sizeof(miss_log[0]))
424 #define miss_log_mask (miss_log_len-1)
426 static void miss_log_add(int reg, u32 val, u32 val_expect, u32 pc, u32 cycle)
428 miss_log[miss_log_i].reg = reg;
429 miss_log[miss_log_i].val = val;
430 miss_log[miss_log_i].val_expect = val_expect;
431 miss_log[miss_log_i].pc = pc;
432 miss_log[miss_log_i].cycle = cycle;
433 miss_log_i = (miss_log_i + 1) & miss_log_mask;
438 void do_insn_cmp(void)
440 static psxRegisters rregs;
441 static u32 mem_addr, mem_val;
442 u32 *allregs_p = (void *)&psxRegs;
443 u32 *allregs_e = (void *)&rregs;
444 static u32 ppc, failcount;
449 f = fopen("tracelog", "rb");
452 if ((ret = fread(&code, 1, 1, f)) <= 0)
459 if ((ret = fread(&mem_addr, 1, 4, f)) <= 0)
464 if ((ret = fread(&mem_val, 1, 4, f)) <= 0)
468 if ((ret = fread(&allregs_e[code], 1, 4, f)) <= 0)
477 psxRegs.code = rregs.code; // don't care
478 psxRegs.cycle = rregs.cycle;
479 psxRegs.CP0.r[9] = rregs.CP0.r[9]; // Count
481 //if (psxRegs.cycle == 166172) breakme();
483 if (memcmp(&psxRegs, &rregs, offsetof(psxRegisters, intCycle)) == 0 &&
484 mem_val == memcheck_read(mem_addr)
490 for (i = 0; i < offsetof(psxRegisters, intCycle) / 4; i++) {
491 if (allregs_p[i] != allregs_e[i]) {
492 miss_log_add(i, allregs_p[i], allregs_e[i], psxRegs.pc, psxRegs.cycle);
497 if (mem_val != memcheck_read(mem_addr)) {
498 printf("bad mem @%08x: %08x %08x\n", mem_addr, memcheck_read(mem_addr), mem_val);
502 if (psxRegs.pc == rregs.pc && bad < 6 && failcount < 32) {
503 static int last_mcycle;
504 if (last_mcycle != psxRegs.cycle >> 20) {
505 printf("%u\n", psxRegs.cycle);
506 last_mcycle = psxRegs.cycle >> 20;
513 for (i = 0; i < miss_log_len; i++, miss_log_i = (miss_log_i + 1) & miss_log_mask)
514 printf("bad %5s: %08x %08x, pc=%08x, cycle %u\n",
515 regnames[miss_log[miss_log_i].reg], miss_log[miss_log_i].val,
516 miss_log[miss_log_i].val_expect, miss_log[miss_log_i].pc, miss_log[miss_log_i].cycle);
517 printf("-- %d\n", bad);
518 for (i = 0; i < 8; i++)
519 printf("r%d=%08x r%2d=%08x r%2d=%08x r%2d=%08x\n", i, allregs_p[i],
520 i+8, allregs_p[i+8], i+16, allregs_p[i+16], i+24, allregs_p[i+24]);
521 printf("PC: %08x/%08x, cycle %u\n", psxRegs.pc, ppc, psxRegs.cycle);
522 dump_mem("/mnt/ntz/dev/pnd/tmp/psxram.dump", psxM, 0x200000);
523 dump_mem("/mnt/ntz/dev/pnd/tmp/psxregs.dump", psxH, 0x10000);
526 psxRegs.cycle = rregs.cycle + 2; // sync timing