17 #include "../psxdma.h"
19 #include "../psxmem.h"
20 #include "../r3000a.h"
21 #include "../psxinterpreter.h"
22 #include "../psxhle.h"
23 #include "../psxevents.h"
25 #include "../frontend/main.h"
30 #if (defined(__arm__) || defined(__aarch64__)) && !defined(ALLOW_LIGHTREC_ON_ARM)
31 #error "Lightrec should not be used on ARM (please specify DYNAREC=ari64 to make)"
34 #define ARRAY_SIZE(x) (sizeof(x) ? sizeof(x) / sizeof((x)[0]) : 0)
36 #if __BYTE_ORDER__ == __ORDER_BIG_ENDIAN__
37 # define LE32TOH(x) __builtin_bswap32(x)
38 # define HTOLE32(x) __builtin_bswap32(x)
39 # define LE16TOH(x) __builtin_bswap16(x)
40 # define HTOLE16(x) __builtin_bswap16(x)
42 # define LE32TOH(x) (x)
43 # define HTOLE32(x) (x)
44 # define LE16TOH(x) (x)
45 # define HTOLE16(x) (x)
49 # define likely(x) __builtin_expect(!!(x),1)
50 # define unlikely(x) __builtin_expect(!!(x),0)
52 # define likely(x) (x)
53 # define unlikely(x) (x)
56 #ifndef LIGHTREC_PROG_NAME
58 # define LIGHTREC_PROG_NAME "/proc/self/exe"
60 # define LIGHTREC_PROG_NAME "retroarch.exe"
64 #ifndef GPUSTATUS_POLLING_THRESHOLD
65 # define GPUSTATUS_POLLING_THRESHOLD 0
73 static struct lightrec_state *lightrec_state;
75 static bool use_lightrec_interpreter;
76 static bool block_stepping;
77 //static bool use_pcsx_interpreter;
78 #define use_pcsx_interpreter 0
79 static bool ram_disabled;
80 static bool lightrec_debug, lightrec_very_debug;
81 static u32 lightrec_begin_cycles;
83 extern u32 lightrec_hacks;
85 static void lightrec_plugin_apply_config();
86 extern void lightrec_code_inv(void *ptr, uint32_t len);
113 static void (*cp2_ops[])(struct psxCP2Regs *) = {
114 [OP_CP2_RTPS] = gteRTPS,
115 [OP_CP2_NCLIP] = gteNCLIP,
117 [OP_CP2_DPCS] = gteDPCS,
118 [OP_CP2_INTPL] = gteINTPL,
119 [OP_CP2_MVMVA] = gteMVMVA,
120 [OP_CP2_NCDS] = gteNCDS,
121 [OP_CP2_CDP] = gteCDP,
122 [OP_CP2_NCDT] = gteNCDT,
123 [OP_CP2_NCCS] = gteNCCS,
125 [OP_CP2_NCS] = gteNCS,
126 [OP_CP2_NCT] = gteNCT,
127 [OP_CP2_SQR] = gteSQR,
128 [OP_CP2_DCPL] = gteDCPL,
129 [OP_CP2_DPCT] = gteDPCT,
130 [OP_CP2_AVSZ3] = gteAVSZ3,
131 [OP_CP2_AVSZ4] = gteAVSZ4,
132 [OP_CP2_RTPT] = gteRTPT,
133 [OP_CP2_GPF] = gteGPF,
134 [OP_CP2_GPL] = gteGPL,
135 [OP_CP2_NCCT] = gteNCCT,
138 static char cache_buf[64 * 1024];
140 static void cop2_op(struct lightrec_state *state, u32 func)
142 struct lightrec_registers *regs = lightrec_get_registers(state);
146 if (unlikely(!cp2_ops[func & 0x3f])) {
147 fprintf(stderr, "Invalid CP2 function %u\n", func);
149 /* This works because regs->cp2c comes right after regs->cp2d,
150 * so it can be cast to a pcsxCP2Regs pointer. */
151 cp2_ops[func & 0x3f]((psxCP2Regs *) regs->cp2d);
155 static bool has_interrupt(void)
157 struct lightrec_registers *regs = lightrec_get_registers(lightrec_state);
159 return ((psxHu32(0x1070) & psxHu32(0x1074)) &&
160 (regs->cp0[12] & 0x401) == 0x401) ||
161 (regs->cp0[12] & regs->cp0[13] & 0x0300);
164 static void lightrec_tansition_to_pcsx(struct lightrec_state *state)
166 psxRegs.cycle += lightrec_current_cycle_count(state) / 1024;
167 lightrec_reset_cycle_count(state, 0);
170 static void lightrec_tansition_from_pcsx(struct lightrec_state *state)
172 s32 cycles_left = psxRegs.next_interupt - psxRegs.cycle;
174 if (block_stepping || cycles_left <= 0 || has_interrupt())
175 lightrec_set_exit_flags(state, LIGHTREC_EXIT_CHECK_INTERRUPT);
177 lightrec_set_target_cycle_count(state, cycles_left * 1024);
181 static void hw_write_byte(struct lightrec_state *state,
182 u32 op, void *host, u32 mem, u32 val)
184 lightrec_tansition_to_pcsx(state);
186 psxHwWrite8(mem, val);
188 lightrec_tansition_from_pcsx(state);
191 static void hw_write_half(struct lightrec_state *state,
192 u32 op, void *host, u32 mem, u32 val)
194 lightrec_tansition_to_pcsx(state);
196 psxHwWrite16(mem, val);
198 lightrec_tansition_from_pcsx(state);
201 static void hw_write_word(struct lightrec_state *state,
202 u32 op, void *host, u32 mem, u32 val)
204 lightrec_tansition_to_pcsx(state);
206 psxHwWrite32(mem, val);
208 lightrec_tansition_from_pcsx(state);
211 static u8 hw_read_byte(struct lightrec_state *state, u32 op, void *host, u32 mem)
215 lightrec_tansition_to_pcsx(state);
217 val = psxHwRead8(mem);
219 lightrec_tansition_from_pcsx(state);
224 static u16 hw_read_half(struct lightrec_state *state,
225 u32 op, void *host, u32 mem)
229 lightrec_tansition_to_pcsx(state);
231 val = psxHwRead16(mem);
233 lightrec_tansition_from_pcsx(state);
238 static u32 hw_read_word(struct lightrec_state *state,
239 u32 op, void *host, u32 mem)
241 static u32 old_cycle, oldold_cycle, old_gpusr;
244 lightrec_tansition_to_pcsx(state);
246 val = psxHwRead32(mem);
248 if (GPUSTATUS_POLLING_THRESHOLD > 0 && mem == 0x1f801814) {
249 diff = psxRegs.cycle - old_cycle;
252 && diff < GPUSTATUS_POLLING_THRESHOLD
253 && diff == old_cycle - oldold_cycle) {
254 while (psxRegs.next_interupt > psxRegs.cycle && val == old_gpusr) {
255 psxRegs.cycle += diff;
256 val = psxHwRead32(mem);
260 oldold_cycle = old_cycle;
261 old_cycle = psxRegs.cycle;
265 lightrec_tansition_from_pcsx(state);
270 static struct lightrec_mem_map_ops hw_regs_ops = {
279 static u32 cache_ctrl;
281 static void cache_ctrl_write_word(struct lightrec_state *state,
282 u32 op, void *host, u32 mem, u32 val)
287 static u32 cache_ctrl_read_word(struct lightrec_state *state,
288 u32 op, void *host, u32 mem)
293 static struct lightrec_mem_map_ops cache_ctrl_ops = {
294 .sw = cache_ctrl_write_word,
295 .lw = cache_ctrl_read_word,
298 static struct lightrec_mem_map lightrec_map[] = {
299 [PSX_MAP_KERNEL_USER_RAM] = {
300 /* Kernel and user memory */
309 [PSX_MAP_SCRATCH_PAD] = {
314 [PSX_MAP_PARALLEL_PORT] = {
319 [PSX_MAP_HW_REGISTERS] = {
320 /* Hardware registers */
325 [PSX_MAP_CACHE_CONTROL] = {
329 .ops = &cache_ctrl_ops,
332 /* Mirrors of the kernel/user memory */
333 [PSX_MAP_MIRROR1] = {
336 .mirror_of = &lightrec_map[PSX_MAP_KERNEL_USER_RAM],
338 [PSX_MAP_MIRROR2] = {
341 .mirror_of = &lightrec_map[PSX_MAP_KERNEL_USER_RAM],
343 [PSX_MAP_MIRROR3] = {
346 .mirror_of = &lightrec_map[PSX_MAP_KERNEL_USER_RAM],
349 /* Mirror of the parallel port. Only used by the PS2/PS3 BIOS */
350 [PSX_MAP_PPORT_MIRROR] = {
353 .mirror_of = &lightrec_map[PSX_MAP_PARALLEL_PORT],
357 [PSX_MAP_CODE_BUFFER] = {
358 .length = CODE_BUFFER_SIZE,
362 static void lightrec_enable_ram(struct lightrec_state *state, bool enable)
365 memcpy(psxM, cache_buf, sizeof(cache_buf));
367 memcpy(cache_buf, psxM, sizeof(cache_buf));
369 ram_disabled = !enable;
372 static bool lightrec_can_hw_direct(u32 kaddr, bool is_write, u8 size)
374 if (is_write && size != 32) {
375 // force32 so must go through handlers
376 if (0x1f801000 <= kaddr && kaddr < 0x1f801024)
378 if ((kaddr & 0x1fffff80) == 0x1f801080) // dma
420 return kaddr < 0x1f801c00 || kaddr >= 0x1f801e00;
451 return !is_write || kaddr < 0x1f801c00 || kaddr >= 0x1f801e00;
456 static const struct lightrec_ops lightrec_ops = {
458 .enable_ram = lightrec_enable_ram,
459 .hw_direct = lightrec_can_hw_direct,
460 .code_inv = LIGHTREC_CODE_INV ? lightrec_code_inv : NULL,
463 static int lightrec_plugin_init(void)
465 lightrec_map[PSX_MAP_KERNEL_USER_RAM].address = psxM;
466 lightrec_map[PSX_MAP_BIOS].address = psxR;
467 lightrec_map[PSX_MAP_SCRATCH_PAD].address = psxH;
468 lightrec_map[PSX_MAP_HW_REGISTERS].address = psxH + 0x1000;
469 lightrec_map[PSX_MAP_PARALLEL_PORT].address = psxP;
471 if (!LIGHTREC_CUSTOM_MAP) {
473 code_buffer = mmap(0, CODE_BUFFER_SIZE,
474 PROT_EXEC | PROT_READ | PROT_WRITE,
475 MAP_PRIVATE | MAP_ANONYMOUS, -1, 0);
476 if (code_buffer == MAP_FAILED)
479 code_buffer = malloc(CODE_BUFFER_SIZE);
485 if (LIGHTREC_CUSTOM_MAP) {
486 lightrec_map[PSX_MAP_MIRROR1].address = psxM + 0x200000;
487 lightrec_map[PSX_MAP_MIRROR2].address = psxM + 0x400000;
488 lightrec_map[PSX_MAP_MIRROR3].address = psxM + 0x600000;
491 lightrec_map[PSX_MAP_CODE_BUFFER].address = code_buffer;
493 use_lightrec_interpreter = !!getenv("LIGHTREC_INTERPRETER");
495 #ifdef LIGHTREC_DEBUG
496 char *cycles = getenv("LIGHTREC_BEGIN_CYCLES");
498 lightrec_very_debug = !!getenv("LIGHTREC_VERY_DEBUG");
499 lightrec_debug = lightrec_very_debug || !!getenv("LIGHTREC_DEBUG");
502 lightrec_begin_cycles = (unsigned int) strtol(cycles, NULL, 0);
505 lightrec_state = lightrec_init(LIGHTREC_PROG_NAME,
506 lightrec_map, ARRAY_SIZE(lightrec_map),
509 // fprintf(stderr, "M=0x%lx, P=0x%lx, R=0x%lx, H=0x%lx\n",
513 // (uintptr_t) psxH);
516 signal(SIGPIPE, exit);
518 lightrec_plugin_apply_config();
522 static u32 do_calculate_hash(const void *buffer, u32 count, u32 needle, bool le)
525 const u32 *data = (const u32 *) buffer;
529 for(i = 0; i < count; ++i) {
530 hash += le ? LE32TOH(data[i]) : data[i];
531 hash += (hash << 10);
536 hash ^= (hash >> 11);
537 hash += (hash << 15);
542 static u32 hash_calculate_le(const void *buffer, u32 count)
544 return do_calculate_hash(buffer, count, 0xffffffff, true);
547 u32 hash_calculate(const void *buffer, u32 count)
549 return do_calculate_hash(buffer, count, 0xffffffff, false);
552 static u32 hash_calculate_ram(const void *buffer, u32 ram_size)
557 hash = hash_calculate_le(cache_buf, sizeof(cache_buf));
559 hash = hash_calculate_le(buffer, sizeof(cache_buf));
561 return do_calculate_hash(buffer + sizeof(cache_buf),
562 ram_size - sizeof(cache_buf),
566 static const char * const mips_regs[] = {
570 "a0", "a1", "a2", "a3",
571 "t0", "t1", "t2", "t3", "t4", "t5", "t6", "t7",
572 "s0", "s1", "s2", "s3", "s4", "s5", "s6", "s7",
575 "gp", "sp", "fp", "ra",
579 static void print_for_big_ass_debugger(void)
581 struct lightrec_registers *regs;
584 regs = lightrec_get_registers(lightrec_state);
586 printf("CYCLE 0x%08x PC 0x%08x", psxRegs.cycle, psxRegs.pc);
588 if (lightrec_very_debug)
589 printf(" RAM 0x%08x SCRATCH 0x%08x HW 0x%08x",
590 hash_calculate_ram(psxM, 0x200000),
591 hash_calculate_le(psxH, 0x400),
592 hash_calculate_le(psxH + 0x1000, 0x2000));
594 printf(" CP0 0x%08x CP2D 0x%08x CP2C 0x%08x INT 0x%04x INTCYCLE 0x%08x GPU 0x%08x",
595 hash_calculate(regs->cp0, sizeof(regs->cp0)),
596 hash_calculate(regs->cp2d, sizeof(regs->cp2d)),
597 hash_calculate(regs->cp2c, sizeof(regs->cp2c)),
599 hash_calculate(psxRegs.intCycle, sizeof(psxRegs.intCycle)),
600 LE32TOH(HW_GPU_STATUS));
602 if (lightrec_very_debug) {
603 for (i = 0; i < 32; i++)
604 printf(" CP2D%u 0x%08x", i, regs->cp2d[i]);
605 for (i = 0; i < 32; i++)
606 printf(" CP2C%u 0x%08x", i, regs->cp2c[i]);
609 if (lightrec_very_debug)
610 for (i = 0; i < 34; i++)
611 printf(" %s 0x%08x", mips_regs[i], regs->gpr[i]);
613 printf(" GPR 0x%08x",
614 hash_calculate(regs->gpr, sizeof(regs->gpr)));
620 static void lightrec_plugin_sync_regs_to_pcsx(bool need_cp2);
621 static void lightrec_plugin_sync_regs_from_pcsx(bool need_cp2);
623 static void lightrec_plugin_execute_internal(bool block_only)
625 struct lightrec_registers *regs;
626 u32 flags, cycles_pcsx;
627 u32 old_pc = psxRegs.pc;
629 regs = lightrec_get_registers(lightrec_state);
630 gen_interupt((psxCP0Regs *)regs->cp0);
631 if (!block_only && psxRegs.stop)
634 cycles_pcsx = psxRegs.next_interupt - psxRegs.cycle;
635 assert((s32)cycles_pcsx > 0);
637 // step during early boot so that 0x80030000 fastboot hack works
638 block_stepping = block_only;
642 if (use_pcsx_interpreter) {
643 psxInt.ExecuteBlock(&psxRegs, 0);
645 u32 cycles_lightrec = cycles_pcsx * 1024;
646 if (unlikely(use_lightrec_interpreter)) {
647 psxRegs.pc = lightrec_run_interpreter(lightrec_state,
651 psxRegs.pc = lightrec_execute(lightrec_state,
652 psxRegs.pc, cycles_lightrec);
655 lightrec_tansition_to_pcsx(lightrec_state);
657 flags = lightrec_exit_flags(lightrec_state);
659 if (flags & LIGHTREC_EXIT_SEGFAULT) {
660 fprintf(stderr, "Exiting at cycle 0x%08x\n",
663 print_for_big_ass_debugger();
667 if (flags & LIGHTREC_EXIT_SYSCALL)
668 psxException(R3000E_Syscall << 2, 0, (psxCP0Regs *)regs->cp0);
669 if (flags & LIGHTREC_EXIT_BREAK)
670 psxException(R3000E_Bp << 2, 0, (psxCP0Regs *)regs->cp0);
671 else if (flags & LIGHTREC_EXIT_UNKNOWN_OP) {
672 u32 op = intFakeFetch(psxRegs.pc);
673 u32 hlec = op & 0x03ffffff;
674 if ((op >> 26) == 0x3b && hlec < ARRAY_SIZE(psxHLEt) && Config.HLE) {
675 lightrec_plugin_sync_regs_to_pcsx(0);
677 lightrec_plugin_sync_regs_from_pcsx(0);
680 psxException(R3000E_RI << 2, 0, (psxCP0Regs *)regs->cp0);
684 if (lightrec_debug && psxRegs.cycle >= lightrec_begin_cycles && psxRegs.pc != old_pc) {
685 print_for_big_ass_debugger();
688 if ((regs->cp0[13] & regs->cp0[12] & 0x300) && (regs->cp0[12] & 0x1)) {
689 /* Handle software interrupts */
690 regs->cp0[13] &= ~0x7c;
691 psxException(regs->cp0[13], 0, (psxCP0Regs *)regs->cp0);
695 static void lightrec_plugin_execute(psxRegisters *regs)
698 lightrec_plugin_execute_internal(lightrec_very_debug);
701 static void lightrec_plugin_execute_block(psxRegisters *regs,
702 enum blockExecCaller caller)
704 lightrec_plugin_execute_internal(true);
707 static void lightrec_plugin_clear(u32 addr, u32 size)
709 if ((addr == 0 && size == UINT32_MAX)
710 || (lightrec_hacks & LIGHTREC_OPT_INV_DMA_ONLY))
711 lightrec_invalidate_all(lightrec_state);
713 /* size * 4: PCSX uses DMA units */
714 lightrec_invalidate(lightrec_state, addr, size * 4);
717 static void lightrec_plugin_notify(enum R3000Anote note, void *data)
721 case R3000ACPU_NOTIFY_CACHE_ISOLATED:
722 case R3000ACPU_NOTIFY_CACHE_UNISOLATED:
723 /* not used, lightrec calls lightrec_enable_ram() instead */
725 case R3000ACPU_NOTIFY_BEFORE_SAVE:
726 /* non-null 'data' means this is HLE related sync */
727 lightrec_plugin_sync_regs_to_pcsx(data == NULL);
729 case R3000ACPU_NOTIFY_AFTER_LOAD:
730 lightrec_plugin_sync_regs_from_pcsx(data == NULL);
732 lightrec_invalidate_all(lightrec_state);
737 static void lightrec_plugin_apply_config()
739 static u32 cycles_per_op_old;
740 u32 cycle_mult = Config.cycle_multiplier_override && Config.cycle_multiplier == CYCLE_MULT_DEFAULT
741 ? Config.cycle_multiplier_override : Config.cycle_multiplier;
742 u32 cycles_per_op = cycle_mult * 1024 / 100;
743 assert(cycles_per_op);
745 if (cycles_per_op_old && cycles_per_op_old != cycles_per_op) {
746 SysPrintf("lightrec: reinit block cache for cycles_per_op %.2f\n",
747 cycles_per_op / 1024.f);
749 cycles_per_op_old = cycles_per_op;
750 lightrec_set_cycles_per_opcode(lightrec_state, cycles_per_op);
752 lightrec_set_unsafe_opt_flags(lightrec_state, lightrec_hacks);
756 static void lightrec_plugin_shutdown(void)
758 lightrec_destroy(lightrec_state);
760 if (!LIGHTREC_CUSTOM_MAP) {
762 munmap(code_buffer, CODE_BUFFER_SIZE);
769 static void lightrec_plugin_reset(void)
771 struct lightrec_registers *regs;
773 regs = lightrec_get_registers(lightrec_state);
775 /* Invalidate all blocks */
776 lightrec_invalidate_all(lightrec_state);
778 /* Reset registers */
779 memset(regs, 0, sizeof(*regs));
781 regs->cp0[12] = 0x10900000; // COP0 enabled | BEV = 1 | TS = 1
782 regs->cp0[15] = 0x00000002; // PRevID = Revision ID, same as R3000A
785 static void lightrec_plugin_sync_regs_from_pcsx(bool need_cp2)
787 struct lightrec_registers *regs;
789 regs = lightrec_get_registers(lightrec_state);
790 memcpy(regs->gpr, &psxRegs.GPR, sizeof(regs->gpr));
791 memcpy(regs->cp0, &psxRegs.CP0, sizeof(regs->cp0));
793 memcpy(regs->cp2d, &psxRegs.CP2, sizeof(regs->cp2d) + sizeof(regs->cp2c));
796 static void lightrec_plugin_sync_regs_to_pcsx(bool need_cp2)
798 struct lightrec_registers *regs;
800 regs = lightrec_get_registers(lightrec_state);
801 memcpy(&psxRegs.GPR, regs->gpr, sizeof(regs->gpr));
802 memcpy(&psxRegs.CP0, regs->cp0, sizeof(regs->cp0));
804 memcpy(&psxRegs.CP2, regs->cp2d, sizeof(regs->cp2d) + sizeof(regs->cp2c));
809 lightrec_plugin_init,
810 lightrec_plugin_reset,
811 lightrec_plugin_execute,
812 lightrec_plugin_execute_block,
813 lightrec_plugin_clear,
814 lightrec_plugin_notify,
815 lightrec_plugin_apply_config,
816 lightrec_plugin_shutdown,