11 #include "../psxdma.h"
13 #include "../psxmem.h"
14 #include "../r3000a.h"
16 #include "../frontend/main.h"
18 #define ARRAY_SIZE(x) (sizeof(x) ? sizeof(x) / sizeof((x)[0]) : 0)
20 #if __BYTE_ORDER__ == __ORDER_BIG_ENDIAN__
21 # define LE32TOH(x) __builtin_bswap32(x)
22 # define HTOLE32(x) __builtin_bswap32(x)
23 # define LE16TOH(x) __builtin_bswap16(x)
24 # define HTOLE16(x) __builtin_bswap16(x)
26 # define LE32TOH(x) (x)
27 # define HTOLE32(x) (x)
28 # define LE16TOH(x) (x)
29 # define HTOLE16(x) (x)
33 # define likely(x) __builtin_expect(!!(x),1)
34 # define unlikely(x) __builtin_expect(!!(x),0)
36 # define likely(x) (x)
37 # define unlikely(x) (x)
40 static struct lightrec_state *lightrec_state;
42 static char *name = "retroarch.exe";
44 static bool use_lightrec_interpreter;
45 static bool use_pcsx_interpreter;
46 static bool lightrec_debug;
47 static bool lightrec_very_debug;
48 static u32 lightrec_begin_cycles;
52 int new_dynarec_hacks;
55 u32 event_cycles[PSXINT_COUNT];
58 void new_dyna_before_save() {}
59 void new_dyna_after_save() {}
60 void new_dyna_freeze(void *f, int i) {}
87 static void (*cp2_ops[])(struct psxCP2Regs *) = {
88 [OP_CP2_RTPS] = gteRTPS,
89 [OP_CP2_RTPS] = gteRTPS,
90 [OP_CP2_NCLIP] = gteNCLIP,
92 [OP_CP2_DPCS] = gteDPCS,
93 [OP_CP2_INTPL] = gteINTPL,
94 [OP_CP2_MVMVA] = gteMVMVA,
95 [OP_CP2_NCDS] = gteNCDS,
96 [OP_CP2_CDP] = gteCDP,
97 [OP_CP2_NCDT] = gteNCDT,
98 [OP_CP2_NCCS] = gteNCCS,
100 [OP_CP2_NCS] = gteNCS,
101 [OP_CP2_NCT] = gteNCT,
102 [OP_CP2_SQR] = gteSQR,
103 [OP_CP2_DCPL] = gteDCPL,
104 [OP_CP2_DPCT] = gteDPCT,
105 [OP_CP2_AVSZ3] = gteAVSZ3,
106 [OP_CP2_AVSZ4] = gteAVSZ4,
107 [OP_CP2_RTPT] = gteRTPT,
108 [OP_CP2_GPF] = gteGPF,
109 [OP_CP2_GPL] = gteGPL,
110 [OP_CP2_NCCT] = gteNCCT,
113 static char cache_buf[64 * 1024];
115 static u32 cop0_mfc(struct lightrec_state *state, u32 op, u8 reg)
117 return psxRegs.CP0.r[reg];
120 static u32 cop2_mfc_cfc(struct lightrec_state *state, u8 reg, bool cfc)
123 return psxRegs.CP2C.r[reg];
128 static u32 cop2_mfc(struct lightrec_state *state, u32 op, u8 reg)
130 return cop2_mfc_cfc(state, reg, false);
133 static u32 cop2_cfc(struct lightrec_state *state, u32 op, u8 reg)
135 return cop2_mfc_cfc(state, reg, true);
138 static void cop0_mtc_ctc(struct lightrec_state *state,
139 u8 reg, u32 value, bool ctc)
147 /* Those registers are read-only */
149 case 12: /* Status */
150 if ((psxRegs.CP0.n.Status & ~value) & (1 << 16)) {
151 memcpy(psxM, cache_buf, sizeof(cache_buf));
152 lightrec_invalidate_all(state);
153 } else if ((~psxRegs.CP0.n.Status & value) & (1 << 16)) {
154 memcpy(cache_buf, psxM, sizeof(cache_buf));
157 psxRegs.CP0.n.Status = value;
158 lightrec_set_exit_flags(state, LIGHTREC_EXIT_CHECK_INTERRUPT);
161 psxRegs.CP0.n.Cause &= ~0x0300;
162 psxRegs.CP0.n.Cause |= value & 0x0300;
163 lightrec_set_exit_flags(state, LIGHTREC_EXIT_CHECK_INTERRUPT);
166 psxRegs.CP0.r[reg] = value;
171 static void cop2_mtc_ctc(struct lightrec_state *state,
172 u8 reg, u32 value, bool ctc)
180 static void cop0_mtc(struct lightrec_state *state, u32 op, u8 reg, u32 value)
182 cop0_mtc_ctc(state, reg, value, false);
185 static void cop0_ctc(struct lightrec_state *state, u32 op, u8 reg, u32 value)
187 cop0_mtc_ctc(state, reg, value, true);
190 static void cop2_mtc(struct lightrec_state *state, u32 op, u8 reg, u32 value)
192 cop2_mtc_ctc(state, reg, value, false);
195 static void cop2_ctc(struct lightrec_state *state, u32 op, u8 reg, u32 value)
197 cop2_mtc_ctc(state, reg, value, true);
200 static void cop0_op(struct lightrec_state *state, u32 func)
202 fprintf(stderr, "Invalid access to COP0\n");
205 static void cop2_op(struct lightrec_state *state, u32 func)
209 if (unlikely(!cp2_ops[func & 0x3f]))
210 fprintf(stderr, "Invalid CP2 function %u\n", func);
212 cp2_ops[func & 0x3f](&psxRegs.CP2);
215 static void hw_write_byte(struct lightrec_state *state,
216 u32 op, void *host, u32 mem, u8 val)
218 psxRegs.cycle = lightrec_current_cycle_count(state);
220 psxHwWrite8(mem, val);
221 lightrec_set_exit_flags(state, LIGHTREC_EXIT_CHECK_INTERRUPT);
223 lightrec_reset_cycle_count(state, psxRegs.cycle);
226 static void hw_write_half(struct lightrec_state *state,
227 u32 op, void *host, u32 mem, u16 val)
229 psxRegs.cycle = lightrec_current_cycle_count(state);
231 psxHwWrite16(mem, val);
232 lightrec_set_exit_flags(state, LIGHTREC_EXIT_CHECK_INTERRUPT);
234 lightrec_reset_cycle_count(state, psxRegs.cycle);
237 static void hw_write_word(struct lightrec_state *state,
238 u32 op, void *host, u32 mem, u32 val)
240 psxRegs.cycle = lightrec_current_cycle_count(state);
242 psxHwWrite32(mem, val);
243 lightrec_set_exit_flags(state, LIGHTREC_EXIT_CHECK_INTERRUPT);
245 lightrec_reset_cycle_count(state, psxRegs.cycle);
248 static u8 hw_read_byte(struct lightrec_state *state, u32 op, void *host, u32 mem)
252 psxRegs.cycle = lightrec_current_cycle_count(state);
254 lightrec_set_exit_flags(state, LIGHTREC_EXIT_CHECK_INTERRUPT);
255 val = psxHwRead8(mem);
256 lightrec_reset_cycle_count(state, psxRegs.cycle);
261 static u16 hw_read_half(struct lightrec_state *state,
262 u32 op, void *host, u32 mem)
266 psxRegs.cycle = lightrec_current_cycle_count(state);
268 lightrec_set_exit_flags(state, LIGHTREC_EXIT_CHECK_INTERRUPT);
269 val = psxHwRead16(mem);
270 lightrec_reset_cycle_count(state, psxRegs.cycle);
275 static u32 hw_read_word(struct lightrec_state *state,
276 u32 op, void *host, u32 mem)
280 psxRegs.cycle = lightrec_current_cycle_count(state);
282 lightrec_set_exit_flags(state, LIGHTREC_EXIT_CHECK_INTERRUPT);
283 val = psxHwRead32(mem);
284 lightrec_reset_cycle_count(state, psxRegs.cycle);
289 static struct lightrec_mem_map_ops hw_regs_ops = {
298 static u32 cache_ctrl;
300 static void cache_ctrl_write_word(struct lightrec_state *state,
301 u32 op, void *host, u32 mem, u32 val)
306 static u32 cache_ctrl_read_word(struct lightrec_state *state,
307 u32 op, void *host, u32 mem)
312 static struct lightrec_mem_map_ops cache_ctrl_ops = {
313 .sw = cache_ctrl_write_word,
314 .lw = cache_ctrl_read_word,
317 static struct lightrec_mem_map lightrec_map[] = {
318 [PSX_MAP_KERNEL_USER_RAM] = {
319 /* Kernel and user memory */
328 [PSX_MAP_SCRATCH_PAD] = {
333 [PSX_MAP_PARALLEL_PORT] = {
338 [PSX_MAP_HW_REGISTERS] = {
339 /* Hardware registers */
344 [PSX_MAP_CACHE_CONTROL] = {
348 .ops = &cache_ctrl_ops,
351 /* Mirrors of the kernel/user memory */
352 [PSX_MAP_MIRROR1] = {
355 .mirror_of = &lightrec_map[PSX_MAP_KERNEL_USER_RAM],
357 [PSX_MAP_MIRROR2] = {
360 .mirror_of = &lightrec_map[PSX_MAP_KERNEL_USER_RAM],
362 [PSX_MAP_MIRROR3] = {
365 .mirror_of = &lightrec_map[PSX_MAP_KERNEL_USER_RAM],
369 static const struct lightrec_ops lightrec_ops = {
386 static int lightrec_plugin_init(void)
388 lightrec_map[PSX_MAP_KERNEL_USER_RAM].address = psxM;
389 lightrec_map[PSX_MAP_BIOS].address = psxR;
390 lightrec_map[PSX_MAP_SCRATCH_PAD].address = psxH;
391 lightrec_map[PSX_MAP_PARALLEL_PORT].address = psxP;
393 lightrec_debug = !!getenv("LIGHTREC_DEBUG");
394 lightrec_very_debug = !!getenv("LIGHTREC_VERY_DEBUG");
395 use_lightrec_interpreter = !!getenv("LIGHTREC_INTERPRETER");
396 if (getenv("LIGHTREC_BEGIN_CYCLES"))
397 lightrec_begin_cycles = (unsigned int) strtol(
398 getenv("LIGHTREC_BEGIN_CYCLES"), NULL, 0);
400 lightrec_state = lightrec_init(name,
401 lightrec_map, ARRAY_SIZE(lightrec_map),
404 // fprintf(stderr, "M=0x%lx, P=0x%lx, R=0x%lx, H=0x%lx\n",
408 // (uintptr_t) psxH);
411 signal(SIGPIPE, exit);
416 static u32 hash_calculate_le(const void *buffer, u32 count)
419 u32 *data = (u32 *) buffer;
420 u32 hash = 0xffffffff;
423 for(i = 0; i < count; ++i) {
424 hash += LE32TOH(data[i]);
425 hash += (hash << 10);
430 hash ^= (hash >> 11);
431 hash += (hash << 15);
435 static u32 hash_calculate(const void *buffer, u32 count)
438 u32 *data = (u32 *) buffer;
439 u32 hash = 0xffffffff;
442 for(i = 0; i < count; ++i) {
444 hash += (hash << 10);
449 hash ^= (hash >> 11);
450 hash += (hash << 15);
454 static const char * const mips_regs[] = {
458 "a0", "a1", "a2", "a3",
459 "t0", "t1", "t2", "t3", "t4", "t5", "t6", "t7",
460 "s0", "s1", "s2", "s3", "s4", "s5", "s6", "s7",
463 "gp", "sp", "fp", "ra",
467 static void print_for_big_ass_debugger(void)
471 printf("CYCLE 0x%08x PC 0x%08x", psxRegs.cycle, psxRegs.pc);
473 if (lightrec_very_debug)
474 printf(" RAM 0x%08x SCRATCH 0x%08x HW 0x%08x",
475 hash_calculate_le(psxM, 0x200000),
476 hash_calculate_le(psxH, 0x400),
477 hash_calculate_le(psxH + 0x1000, 0x2000));
479 printf(" CP0 0x%08x CP2D 0x%08x CP2C 0x%08x INT 0x%04x INTCYCLE 0x%08x GPU 0x%08x",
480 hash_calculate(&psxRegs.CP0.r,
481 sizeof(psxRegs.CP0.r)),
482 hash_calculate(&psxRegs.CP2D.r,
483 sizeof(psxRegs.CP2D.r)),
484 hash_calculate(&psxRegs.CP2C.r,
485 sizeof(psxRegs.CP2C.r)),
487 hash_calculate(psxRegs.intCycle,
488 sizeof(psxRegs.intCycle)),
489 LE32TOH(HW_GPU_STATUS));
491 if (lightrec_very_debug)
492 for (i = 0; i < 34; i++)
493 printf(" %s 0x%08x", mips_regs[i], psxRegs.GPR.r[i]);
495 printf(" GPR 0x%08x", hash_calculate(&psxRegs.GPR.r,
496 sizeof(psxRegs.GPR.r)));
501 extern void intExecuteBlock();
503 static u32 old_cycle_counter;
505 static void lightrec_plugin_execute_block(void)
507 u32 old_pc = psxRegs.pc;
510 if (use_pcsx_interpreter) {
513 lightrec_reset_cycle_count(lightrec_state, psxRegs.cycle);
514 lightrec_restore_registers(lightrec_state, psxRegs.GPR.r);
516 if (use_lightrec_interpreter)
517 psxRegs.pc = lightrec_run_interpreter(lightrec_state,
520 psxRegs.pc = lightrec_execute_one(lightrec_state,
523 psxRegs.cycle = lightrec_current_cycle_count(lightrec_state);
525 lightrec_dump_registers(lightrec_state, psxRegs.GPR.r);
526 flags = lightrec_exit_flags(lightrec_state);
528 if (flags & LIGHTREC_EXIT_SEGFAULT) {
529 fprintf(stderr, "Exiting at cycle 0x%08x\n",
534 if (flags & LIGHTREC_EXIT_SYSCALL)
535 psxException(0x20, 0);
540 if (lightrec_debug && psxRegs.cycle >= lightrec_begin_cycles
541 && psxRegs.pc != old_pc)
542 print_for_big_ass_debugger();
544 if ((psxRegs.CP0.n.Cause & psxRegs.CP0.n.Status & 0x300) &&
545 (psxRegs.CP0.n.Status & 0x1)) {
546 /* Handle software interrupts */
547 psxRegs.CP0.n.Cause &= ~0x7c;
548 psxException(psxRegs.CP0.n.Cause, 0);
551 if ((psxRegs.cycle & ~0xfffffff) != old_cycle_counter) {
552 SysDLog("RAM usage: Lightrec %u KiB, IR %u KiB, CODE %u KiB, "
553 "MIPS %u KiB, TOTAL %u KiB, avg. IPI %f\n",
554 lightrec_get_mem_usage(MEM_FOR_LIGHTREC) / 1024,
555 lightrec_get_mem_usage(MEM_FOR_IR) / 1024,
556 lightrec_get_mem_usage(MEM_FOR_CODE) / 1024,
557 lightrec_get_mem_usage(MEM_FOR_MIPS_CODE) / 1024,
558 lightrec_get_total_mem_usage() / 1024,
559 lightrec_get_average_ipi());
560 old_cycle_counter = psxRegs.cycle & ~0xfffffff;
564 static void lightrec_plugin_execute(void)
569 lightrec_plugin_execute_block();
572 static void lightrec_plugin_clear(u32 addr, u32 size)
574 if (addr == 0 && size == UINT32_MAX)
575 lightrec_invalidate_all(lightrec_state);
577 /* size * 4: PCSX uses DMA units */
578 lightrec_invalidate(lightrec_state, addr, size * 4);
581 static void lightrec_plugin_shutdown(void)
583 lightrec_destroy(lightrec_state);
586 static void lightrec_plugin_reset(void)
588 lightrec_plugin_shutdown();
589 lightrec_plugin_init();
594 lightrec_plugin_init,
595 lightrec_plugin_reset,
596 lightrec_plugin_execute,
597 lightrec_plugin_execute_block,
598 lightrec_plugin_clear,
599 lightrec_plugin_shutdown,