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, u32 val)
121 evprintf("MTC0 %d #%x @%08x %u\n", reg, val, psxRegs.pc, psxRegs.cycle);
126 void pcsx_mtc0_ds(u32 reg, u32 val)
128 evprintf("MTC0 %d #%x @%08x %u\n", reg, val, psxRegs.pc, psxRegs.cycle);
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;
143 new_dyna_pcsx_mem_load_state();
146 void *gte_handlers[64];
148 void *gte_handlers_nf[64] = {
149 NULL , gteRTPS_nf , NULL , NULL , NULL , NULL , gteNCLIP_nf, NULL , // 00
150 NULL , NULL , NULL , NULL , gteOP_nf , NULL , NULL , NULL , // 08
151 gteDPCS_nf, gteINTPL_nf, gteMVMVA_nf, gteNCDS_nf, gteCDP_nf, NULL , gteNCDT_nf , NULL , // 10
152 NULL , NULL , NULL , gteNCCS_nf, gteCC_nf , NULL , gteNCS_nf , NULL , // 18
153 gteNCT_nf , NULL , NULL , NULL , NULL , NULL , NULL , NULL , // 20
154 gteSQR_nf , gteDCPL_nf , gteDPCT_nf , NULL , NULL , gteAVSZ3_nf, gteAVSZ4_nf, NULL , // 28
155 gteRTPT_nf, NULL , NULL , NULL , NULL , NULL , NULL , NULL , // 30
156 NULL , NULL , NULL , NULL , NULL , gteGPF_nf , gteGPL_nf , gteNCCT_nf, // 38
159 const char *gte_regnames[64] = {
160 NULL , "RTPS" , NULL , NULL , NULL , NULL , "NCLIP", NULL , // 00
161 NULL , NULL , NULL , NULL , "OP" , NULL , NULL , NULL , // 08
162 "DPCS", "INTPL", "MVMVA", "NCDS", "CDP", NULL , "NCDT" , NULL , // 10
163 NULL , NULL , NULL , "NCCS", "CC" , NULL , "NCS" , NULL , // 18
164 "NCT" , NULL , NULL , NULL , NULL , NULL , NULL , NULL , // 20
165 "SQR" , "DCPL" , "DPCT" , NULL , NULL , "AVSZ3", "AVSZ4", NULL , // 28
166 "RTPT", NULL , NULL , NULL , NULL , NULL , NULL , NULL , // 30
167 NULL , NULL , NULL , NULL , NULL , "GPF" , "GPL" , "NCCT", // 38
170 /* from gte.txt.. not sure if this is any good. */
171 const char gte_cycletab[64] = {
172 /* 1 2 3 4 5 6 7 8 9 a b c d e f */
173 0, 15, 0, 0, 0, 0, 8, 0, 0, 0, 0, 0, 6, 0, 0, 0,
174 8, 8, 8, 19, 13, 0, 44, 0, 0, 0, 0, 17, 11, 0, 14, 0,
175 30, 0, 0, 0, 0, 0, 0, 0, 5, 8, 17, 0, 0, 5, 6, 0,
176 23, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 5, 5, 39,
179 static int ari64_init()
181 extern void (*psxCP2[64])();
182 extern void psxNULL();
186 new_dyna_pcsx_mem_init();
188 for (i = 0; i < ARRAY_SIZE(gte_handlers); i++)
189 if (psxCP2[i] != psxNULL)
190 gte_handlers[i] = psxCP2[i];
192 #if !defined(DRC_DBG) && !defined(PCNT)
194 gte_handlers[0x06] = gteNCLIP_arm;
195 gte_handlers_nf[0x01] = gteRTPS_nf_arm;
196 gte_handlers_nf[0x30] = gteRTPT_nf_arm;
199 // compiler's _nf version is still a lot slower then neon
200 // _nf_arm RTPS is roughly the same, RTPT slower
201 gte_handlers[0x01] = gte_handlers_nf[0x01] = gteRTPS_neon;
202 gte_handlers[0x30] = gte_handlers_nf[0x30] = gteRTPT_neon;
203 gte_handlers[0x12] = gte_handlers_nf[0x12] = gteMVMVA_neon;
207 memcpy(gte_handlers_nf, gte_handlers, sizeof(gte_handlers_nf));
214 static void ari64_reset()
216 printf("ari64_reset\n");
217 new_dyna_pcsx_mem_reset();
218 invalidate_all_pages();
220 pending_exception = 1;
223 // execute until predefined leave points
224 // (HLE softcall exit and BIOS fastboot end)
225 static void ari64_execute_until()
227 schedule_timeslice();
229 evprintf("ari64_execute %08x, %u->%u (%d)\n", psxRegs.pc,
230 psxRegs.cycle, next_interupt, next_interupt - psxRegs.cycle);
234 evprintf("ari64_execute end %08x, %u->%u (%d)\n", psxRegs.pc,
235 psxRegs.cycle, next_interupt, next_interupt - psxRegs.cycle);
238 static void ari64_execute()
241 ari64_execute_until();
242 evprintf("drc left @%08x\n", psxRegs.pc);
246 static void ari64_clear(u32 addr, u32 size)
248 u32 start, end, main_ram;
250 size *= 4; /* PCSX uses DMA units */
252 evprintf("ari64_clear %08x %04x\n", addr, size);
254 /* check for RAM mirrors */
255 main_ram = (addr & 0xffe00000) == 0x80000000;
258 end = (addr + size) >> 12;
260 for (; start <= end; start++)
261 if (!main_ram || !invalid_code[start])
262 invalidate_block(start);
265 static void ari64_shutdown()
267 new_dynarec_cleanup();
270 extern void intExecute();
271 extern void intExecuteT();
272 extern void intExecuteBlock();
273 extern void intExecuteBlockT();
275 #define intExecuteT intExecute
276 #define intExecuteBlockT intExecuteBlock
295 void do_insn_trace() {}
296 void do_insn_cmp() {}
299 #if defined(__x86_64__) || defined(__i386__)
300 unsigned int address, readmem_word, word;
301 unsigned short hword;
303 int pending_exception, stop;
304 unsigned int next_interupt;
305 int new_dynarec_did_compile;
306 int cycle_multiplier;
308 void new_dynarec_init() {}
309 void new_dyna_start() {}
310 void new_dynarec_cleanup() {}
311 void new_dynarec_clear_full() {}
312 void invalidate_all_pages() {}
313 void invalidate_block(unsigned int block) {}
314 void new_dyna_pcsx_mem_init(void) {}
315 void new_dyna_pcsx_mem_reset(void) {}
316 void new_dyna_pcsx_mem_load_state(void) {}
323 extern u32 last_io_addr;
325 static void dump_mem(const char *fname, void *mem, size_t size)
327 FILE *f1 = fopen(fname, "wb");
329 f1 = fopen(strrchr(fname, '/') + 1, "wb");
330 fwrite(mem, 1, size, f1);
334 static u32 memcheck_read(u32 a)
336 if ((a >> 16) == 0x1f80)
338 return *(u32 *)(psxH + (a & 0xfffc));
340 if ((a >> 16) == 0x1f00)
342 return *(u32 *)(psxP + (a & 0xfffc));
344 // if ((a & ~0xe0600000) < 0x200000)
346 return *(u32 *)(psxM + (a & 0x1ffffc));
349 void do_insn_trace(void)
351 static psxRegisters oldregs;
352 static u32 old_io_addr = (u32)-1;
353 static u32 old_io_data = 0xbad0c0de;
354 u32 *allregs_p = (void *)&psxRegs;
355 u32 *allregs_o = (void *)&oldregs;
360 //last_io_addr = 0x5e2c8;
362 f = fopen("tracelog", "wb");
364 oldregs.code = psxRegs.code; // don't care
365 for (i = 0; i < offsetof(psxRegisters, intCycle) / 4; i++) {
366 if (allregs_p[i] != allregs_o[i]) {
368 fwrite(&allregs_p[i], 1, 4, f);
369 allregs_o[i] = allregs_p[i];
372 if (old_io_addr != last_io_addr) {
374 fwrite(&byte, 1, 1, f);
375 fwrite(&last_io_addr, 1, 4, f);
376 old_io_addr = last_io_addr;
378 io_data = memcheck_read(last_io_addr);
379 if (old_io_data != io_data) {
381 fwrite(&byte, 1, 1, f);
382 fwrite(&io_data, 1, 4, f);
383 old_io_data = io_data;
386 fwrite(&byte, 1, 1, f);
389 if (psxRegs.cycle == 190230) {
390 dump_mem("/mnt/ntz/dev/pnd/tmp/psxram_i.dump", psxM, 0x200000);
391 dump_mem("/mnt/ntz/dev/pnd/tmp/psxregs_i.dump", psxH, 0x10000);
398 static const char *regnames[offsetof(psxRegisters, intCycle) / 4] = {
399 "r0", "r1", "r2", "r3", "r4", "r5", "r6", "r7",
400 "r8", "r9", "r10", "r11", "r12", "r13", "r14", "r15",
401 "r16", "r17", "r18", "r19", "r20", "r21", "r22", "r23",
402 "r24", "r25", "r26", "r27", "r28", "r29", "r30", "r31",
404 "C0_0", "C0_1", "C0_2", "C0_3", "C0_4", "C0_5", "C0_6", "C0_7",
405 "C0_8", "C0_9", "C0_10", "C0_11", "C0_12", "C0_13", "C0_14", "C0_15",
406 "C0_16", "C0_17", "C0_18", "C0_19", "C0_20", "C0_21", "C0_22", "C0_23",
407 "C0_24", "C0_25", "C0_26", "C0_27", "C0_28", "C0_29", "C0_30", "C0_31",
409 "C2D0", "C2D1", "C2D2", "C2D3", "C2D4", "C2D5", "C2D6", "C2D7",
410 "C2D8", "C2D9", "C2D10", "C2D11", "C2D12", "C2D13", "C2D14", "C2D15",
411 "C2D16", "C2D17", "C2D18", "C2D19", "C2D20", "C2D21", "C2D22", "C2D23",
412 "C2D24", "C2D25", "C2D26", "C2D27", "C2D28", "C2D29", "C2D30", "C2D31",
414 "C2C0", "C2C1", "C2C2", "C2C3", "C2C4", "C2C5", "C2C6", "C2C7",
415 "C2C8", "C2C9", "C2C10", "C2C11", "C2C12", "C2C13", "C2C14", "C2C15",
416 "C2C16", "C2C17", "C2C18", "C2C19", "C2C20", "C2C21", "C2C22", "C2C23",
417 "C2C24", "C2C25", "C2C26", "C2C27", "C2C28", "C2C29", "C2C30", "C2C31",
419 "PC", "code", "cycle", "interrupt",
427 static int miss_log_i;
428 #define miss_log_len (sizeof(miss_log)/sizeof(miss_log[0]))
429 #define miss_log_mask (miss_log_len-1)
431 static void miss_log_add(int reg, u32 val, u32 val_expect, u32 pc, u32 cycle)
433 miss_log[miss_log_i].reg = reg;
434 miss_log[miss_log_i].val = val;
435 miss_log[miss_log_i].val_expect = val_expect;
436 miss_log[miss_log_i].pc = pc;
437 miss_log[miss_log_i].cycle = cycle;
438 miss_log_i = (miss_log_i + 1) & miss_log_mask;
443 void do_insn_cmp(void)
445 static psxRegisters rregs;
446 static u32 mem_addr, mem_val;
447 u32 *allregs_p = (void *)&psxRegs;
448 u32 *allregs_e = (void *)&rregs;
449 static u32 ppc, failcount;
454 f = fopen("tracelog", "rb");
457 if ((ret = fread(&code, 1, 1, f)) <= 0)
464 if ((ret = fread(&mem_addr, 1, 4, f)) <= 0)
469 if ((ret = fread(&mem_val, 1, 4, f)) <= 0)
473 if ((ret = fread(&allregs_e[code], 1, 4, f)) <= 0)
482 psxRegs.code = rregs.code; // don't care
483 psxRegs.cycle = rregs.cycle;
484 psxRegs.CP0.r[9] = rregs.CP0.r[9]; // Count
486 //if (psxRegs.cycle == 166172) breakme();
488 if (memcmp(&psxRegs, &rregs, offsetof(psxRegisters, intCycle)) == 0 &&
489 mem_val == memcheck_read(mem_addr)
495 for (i = 0; i < offsetof(psxRegisters, intCycle) / 4; i++) {
496 if (allregs_p[i] != allregs_e[i]) {
497 miss_log_add(i, allregs_p[i], allregs_e[i], psxRegs.pc, psxRegs.cycle);
502 if (mem_val != memcheck_read(mem_addr)) {
503 printf("bad mem @%08x: %08x %08x\n", mem_addr, memcheck_read(mem_addr), mem_val);
507 if (psxRegs.pc == rregs.pc && bad < 6 && failcount < 32) {
508 static int last_mcycle;
509 if (last_mcycle != psxRegs.cycle >> 20) {
510 printf("%u\n", psxRegs.cycle);
511 last_mcycle = psxRegs.cycle >> 20;
518 for (i = 0; i < miss_log_len; i++, miss_log_i = (miss_log_i + 1) & miss_log_mask)
519 printf("bad %5s: %08x %08x, pc=%08x, cycle %u\n",
520 regnames[miss_log[miss_log_i].reg], miss_log[miss_log_i].val,
521 miss_log[miss_log_i].val_expect, miss_log[miss_log_i].pc, miss_log[miss_log_i].cycle);
522 printf("-- %d\n", bad);
523 for (i = 0; i < 8; i++)
524 printf("r%d=%08x r%2d=%08x r%2d=%08x r%2d=%08x\n", i, allregs_p[i],
525 i+8, allregs_p[i+8], i+16, allregs_p[i+16], i+24, allregs_p[i+24]);
526 printf("PC: %08x/%08x, cycle %u\n", psxRegs.pc, ppc, psxRegs.cycle);
527 dump_mem("/mnt/ntz/dev/pnd/tmp/psxram.dump", psxM, 0x200000);
528 dump_mem("/mnt/ntz/dev/pnd/tmp/psxregs.dump", psxH, 0x10000);
531 psxRegs.cycle = rregs.cycle + 2; // sync timing