11 #include "../psxdma.h"
13 #include "../psxmem.h"
14 #include "../r3000a.h"
16 #include "../frontend/main.h"
21 #if (defined(__arm__) || defined(__aarch64__)) && !defined(ALLOW_LIGHTREC_ON_ARM)
22 #error "Lightrec should not be used on ARM (please specify DYNAREC=ari64 to make)"
25 #define ARRAY_SIZE(x) (sizeof(x) ? sizeof(x) / sizeof((x)[0]) : 0)
27 #if __BYTE_ORDER__ == __ORDER_BIG_ENDIAN__
28 # define LE32TOH(x) __builtin_bswap32(x)
29 # define HTOLE32(x) __builtin_bswap32(x)
30 # define LE16TOH(x) __builtin_bswap16(x)
31 # define HTOLE16(x) __builtin_bswap16(x)
33 # define LE32TOH(x) (x)
34 # define HTOLE32(x) (x)
35 # define LE16TOH(x) (x)
36 # define HTOLE16(x) (x)
40 # define likely(x) __builtin_expect(!!(x),1)
41 # define unlikely(x) __builtin_expect(!!(x),0)
43 # define likely(x) (x)
44 # define unlikely(x) (x)
50 static struct lightrec_state *lightrec_state;
52 static char *name = "retroarch.exe";
54 static bool use_lightrec_interpreter;
55 static bool use_pcsx_interpreter;
56 static bool lightrec_debug;
57 static bool lightrec_very_debug;
59 static u32 lightrec_begin_cycles;
86 static void (*cp2_ops[])(struct psxCP2Regs *) = {
87 [OP_CP2_RTPS] = gteRTPS,
88 [OP_CP2_RTPS] = gteRTPS,
89 [OP_CP2_NCLIP] = gteNCLIP,
91 [OP_CP2_DPCS] = gteDPCS,
92 [OP_CP2_INTPL] = gteINTPL,
93 [OP_CP2_MVMVA] = gteMVMVA,
94 [OP_CP2_NCDS] = gteNCDS,
95 [OP_CP2_CDP] = gteCDP,
96 [OP_CP2_NCDT] = gteNCDT,
97 [OP_CP2_NCCS] = gteNCCS,
99 [OP_CP2_NCS] = gteNCS,
100 [OP_CP2_NCT] = gteNCT,
101 [OP_CP2_SQR] = gteSQR,
102 [OP_CP2_DCPL] = gteDCPL,
103 [OP_CP2_DPCT] = gteDPCT,
104 [OP_CP2_AVSZ3] = gteAVSZ3,
105 [OP_CP2_AVSZ4] = gteAVSZ4,
106 [OP_CP2_RTPT] = gteRTPT,
107 [OP_CP2_GPF] = gteGPF,
108 [OP_CP2_GPL] = gteGPL,
109 [OP_CP2_NCCT] = gteNCCT,
112 static char cache_buf[64 * 1024];
114 static void cop2_op(struct lightrec_state *state, u32 func)
116 struct lightrec_registers *regs = lightrec_get_registers(state);
120 if (unlikely(!cp2_ops[func & 0x3f])) {
121 fprintf(stderr, "Invalid CP2 function %u\n", func);
123 /* This works because regs->cp2c comes right after regs->cp2d,
124 * so it can be cast to a pcsxCP2Regs pointer. */
125 cp2_ops[func & 0x3f]((psxCP2Regs *) regs->cp2d);
129 static bool has_interrupt(void)
131 return ((psxHu32(0x1070) & psxHu32(0x1074)) &&
132 (psxRegs.CP0.n.Status & 0x401) == 0x401) ||
133 (psxRegs.CP0.n.Status & psxRegs.CP0.n.Cause & 0x0300);
136 static void lightrec_restore_state(struct lightrec_state *state)
138 lightrec_reset_cycle_count(state, psxRegs.cycle);
140 if (booting || has_interrupt())
141 lightrec_set_exit_flags(state, LIGHTREC_EXIT_CHECK_INTERRUPT);
143 lightrec_set_target_cycle_count(state, next_interupt);
146 static void hw_write_byte(struct lightrec_state *state,
147 u32 op, void *host, u32 mem, u8 val)
149 psxRegs.cycle = lightrec_current_cycle_count(state);
151 psxHwWrite8(mem, val);
153 lightrec_restore_state(state);
156 static void hw_write_half(struct lightrec_state *state,
157 u32 op, void *host, u32 mem, u16 val)
159 psxRegs.cycle = lightrec_current_cycle_count(state);
161 psxHwWrite16(mem, val);
163 lightrec_restore_state(state);
166 static void hw_write_word(struct lightrec_state *state,
167 u32 op, void *host, u32 mem, u32 val)
169 psxRegs.cycle = lightrec_current_cycle_count(state);
171 psxHwWrite32(mem, val);
173 lightrec_restore_state(state);
176 static u8 hw_read_byte(struct lightrec_state *state, u32 op, void *host, u32 mem)
180 psxRegs.cycle = lightrec_current_cycle_count(state);
182 val = psxHwRead8(mem);
184 lightrec_restore_state(state);
189 static u16 hw_read_half(struct lightrec_state *state,
190 u32 op, void *host, u32 mem)
194 psxRegs.cycle = lightrec_current_cycle_count(state);
196 val = psxHwRead16(mem);
198 lightrec_restore_state(state);
203 static u32 hw_read_word(struct lightrec_state *state,
204 u32 op, void *host, u32 mem)
208 psxRegs.cycle = lightrec_current_cycle_count(state);
210 val = psxHwRead32(mem);
212 lightrec_restore_state(state);
217 static struct lightrec_mem_map_ops hw_regs_ops = {
226 static u32 cache_ctrl;
228 static void cache_ctrl_write_word(struct lightrec_state *state,
229 u32 op, void *host, u32 mem, u32 val)
234 static u32 cache_ctrl_read_word(struct lightrec_state *state,
235 u32 op, void *host, u32 mem)
240 static struct lightrec_mem_map_ops cache_ctrl_ops = {
241 .sw = cache_ctrl_write_word,
242 .lw = cache_ctrl_read_word,
245 static struct lightrec_mem_map lightrec_map[] = {
246 [PSX_MAP_KERNEL_USER_RAM] = {
247 /* Kernel and user memory */
256 [PSX_MAP_SCRATCH_PAD] = {
261 [PSX_MAP_PARALLEL_PORT] = {
266 [PSX_MAP_HW_REGISTERS] = {
267 /* Hardware registers */
272 [PSX_MAP_CACHE_CONTROL] = {
276 .ops = &cache_ctrl_ops,
279 /* Mirrors of the kernel/user memory */
280 [PSX_MAP_MIRROR1] = {
283 .mirror_of = &lightrec_map[PSX_MAP_KERNEL_USER_RAM],
285 [PSX_MAP_MIRROR2] = {
288 .mirror_of = &lightrec_map[PSX_MAP_KERNEL_USER_RAM],
290 [PSX_MAP_MIRROR3] = {
293 .mirror_of = &lightrec_map[PSX_MAP_KERNEL_USER_RAM],
295 [PSX_MAP_CODE_BUFFER] = {
296 .length = CODE_BUFFER_SIZE,
300 static void lightrec_enable_ram(struct lightrec_state *state, bool enable)
303 memcpy(psxM, cache_buf, sizeof(cache_buf));
305 memcpy(cache_buf, psxM, sizeof(cache_buf));
308 static const struct lightrec_ops lightrec_ops = {
310 .enable_ram = lightrec_enable_ram,
313 static int lightrec_plugin_init(void)
315 lightrec_map[PSX_MAP_KERNEL_USER_RAM].address = psxM;
316 lightrec_map[PSX_MAP_BIOS].address = psxR;
317 lightrec_map[PSX_MAP_SCRATCH_PAD].address = psxH;
318 lightrec_map[PSX_MAP_PARALLEL_PORT].address = psxP;
320 if (LIGHTREC_CUSTOM_MAP) {
321 lightrec_map[PSX_MAP_MIRROR1].address = psxM + 0x200000;
322 lightrec_map[PSX_MAP_MIRROR2].address = psxM + 0x400000;
323 lightrec_map[PSX_MAP_MIRROR3].address = psxM + 0x600000;
324 lightrec_map[PSX_MAP_CODE_BUFFER].address = code_buffer;
327 lightrec_debug = !!getenv("LIGHTREC_DEBUG");
328 lightrec_very_debug = !!getenv("LIGHTREC_VERY_DEBUG");
329 use_lightrec_interpreter = !!getenv("LIGHTREC_INTERPRETER");
330 if (getenv("LIGHTREC_BEGIN_CYCLES"))
331 lightrec_begin_cycles = (unsigned int) strtol(
332 getenv("LIGHTREC_BEGIN_CYCLES"), NULL, 0);
334 lightrec_state = lightrec_init(name,
335 lightrec_map, ARRAY_SIZE(lightrec_map),
338 // fprintf(stderr, "M=0x%lx, P=0x%lx, R=0x%lx, H=0x%lx\n",
342 // (uintptr_t) psxH);
345 signal(SIGPIPE, exit);
350 static u32 hash_calculate_le(const void *buffer, u32 count)
353 u32 *data = (u32 *) buffer;
354 u32 hash = 0xffffffff;
357 for(i = 0; i < count; ++i) {
358 hash += LE32TOH(data[i]);
359 hash += (hash << 10);
364 hash ^= (hash >> 11);
365 hash += (hash << 15);
369 static u32 hash_calculate(const void *buffer, u32 count)
372 u32 *data = (u32 *) buffer;
373 u32 hash = 0xffffffff;
376 for(i = 0; i < count; ++i) {
378 hash += (hash << 10);
383 hash ^= (hash >> 11);
384 hash += (hash << 15);
388 static const char * const mips_regs[] = {
392 "a0", "a1", "a2", "a3",
393 "t0", "t1", "t2", "t3", "t4", "t5", "t6", "t7",
394 "s0", "s1", "s2", "s3", "s4", "s5", "s6", "s7",
397 "gp", "sp", "fp", "ra",
401 static void print_for_big_ass_debugger(void)
405 printf("CYCLE 0x%08x PC 0x%08x", psxRegs.cycle, psxRegs.pc);
407 if (lightrec_very_debug)
408 printf(" RAM 0x%08x SCRATCH 0x%08x HW 0x%08x",
409 hash_calculate_le(psxM, 0x200000),
410 hash_calculate_le(psxH, 0x400),
411 hash_calculate_le(psxH + 0x1000, 0x2000));
413 printf(" CP0 0x%08x CP2D 0x%08x CP2C 0x%08x INT 0x%04x INTCYCLE 0x%08x GPU 0x%08x",
414 hash_calculate(&psxRegs.CP0.r,
415 sizeof(psxRegs.CP0.r)),
416 hash_calculate(&psxRegs.CP2D.r,
417 sizeof(psxRegs.CP2D.r)),
418 hash_calculate(&psxRegs.CP2C.r,
419 sizeof(psxRegs.CP2C.r)),
421 hash_calculate(psxRegs.intCycle,
422 sizeof(psxRegs.intCycle)),
423 LE32TOH(HW_GPU_STATUS));
425 if (lightrec_very_debug)
426 for (i = 0; i < 34; i++)
427 printf(" %s 0x%08x", mips_regs[i], psxRegs.GPR.r[i]);
429 printf(" GPR 0x%08x", hash_calculate(&psxRegs.GPR.r,
430 sizeof(psxRegs.GPR.r)));
434 static void lightrec_dump_regs(struct lightrec_state *state)
436 struct lightrec_registers *regs = lightrec_get_registers(state);
438 if (unlikely(booting))
439 memcpy(&psxRegs.GPR, regs->gpr, sizeof(regs->gpr));
440 psxRegs.CP0.n.Status = regs->cp0[12];
441 psxRegs.CP0.n.Cause = regs->cp0[13];
444 static void lightrec_restore_regs(struct lightrec_state *state)
446 struct lightrec_registers *regs = lightrec_get_registers(state);
448 if (unlikely(booting))
449 memcpy(regs->gpr, &psxRegs.GPR, sizeof(regs->gpr));
450 regs->cp0[12] = psxRegs.CP0.n.Status;
451 regs->cp0[13] = psxRegs.CP0.n.Cause;
452 regs->cp0[14] = psxRegs.CP0.n.EPC;
455 extern void intExecuteBlock();
456 extern void gen_interupt();
458 static void lightrec_plugin_execute_block(void)
460 u32 old_pc = psxRegs.pc;
465 if (use_pcsx_interpreter) {
468 lightrec_reset_cycle_count(lightrec_state, psxRegs.cycle);
469 lightrec_restore_regs(lightrec_state);
471 if (unlikely(use_lightrec_interpreter))
472 psxRegs.pc = lightrec_run_interpreter(lightrec_state,
474 // step during early boot so that 0x80030000 fastboot hack works
475 else if (unlikely(booting || lightrec_debug))
476 psxRegs.pc = lightrec_execute_one(lightrec_state,
479 psxRegs.pc = lightrec_execute(lightrec_state,
480 psxRegs.pc, next_interupt);
482 psxRegs.cycle = lightrec_current_cycle_count(lightrec_state);
484 lightrec_dump_regs(lightrec_state);
485 flags = lightrec_exit_flags(lightrec_state);
487 if (flags & LIGHTREC_EXIT_SEGFAULT) {
488 fprintf(stderr, "Exiting at cycle 0x%08x\n",
493 if (flags & LIGHTREC_EXIT_SYSCALL)
494 psxException(0x20, 0);
496 if (booting && (psxRegs.pc & 0xff800000) == 0x80000000)
500 if (lightrec_debug && psxRegs.cycle >= lightrec_begin_cycles
501 && psxRegs.pc != old_pc)
502 print_for_big_ass_debugger();
504 if ((psxRegs.CP0.n.Cause & psxRegs.CP0.n.Status & 0x300) &&
505 (psxRegs.CP0.n.Status & 0x1)) {
506 /* Handle software interrupts */
507 psxRegs.CP0.n.Cause &= ~0x7c;
508 psxException(psxRegs.CP0.n.Cause, 0);
512 static void lightrec_plugin_execute(void)
517 lightrec_plugin_execute_block();
520 static void lightrec_plugin_clear(u32 addr, u32 size)
522 if (addr == 0 && size == UINT32_MAX)
523 lightrec_invalidate_all(lightrec_state);
525 /* size * 4: PCSX uses DMA units */
526 lightrec_invalidate(lightrec_state, addr, size * 4);
529 static void lightrec_plugin_notify(int note, void *data)
532 To change once proper icache emulation is emulated
535 case R3000ACPU_NOTIFY_CACHE_UNISOLATED:
536 lightrec_plugin_clear(0, 0x200000/4);
538 case R3000ACPU_NOTIFY_CACHE_ISOLATED:
539 // Sent from psxDma3().
540 case R3000ACPU_NOTIFY_DMA3_EXE_LOAD:
546 static void lightrec_plugin_apply_config()
550 static void lightrec_plugin_shutdown(void)
552 lightrec_destroy(lightrec_state);
555 static void lightrec_plugin_reset(void)
557 struct lightrec_registers *regs;
559 lightrec_plugin_shutdown();
560 lightrec_plugin_init();
562 regs = lightrec_get_registers(lightrec_state);
564 regs->cp0[12] = 0x10900000; // COP0 enabled | BEV = 1 | TS = 1
565 regs->cp0[15] = 0x00000002; // PRevID = Revision ID, same as R3000A
570 void lightrec_plugin_prepare_load_state(void)
572 struct lightrec_registers *regs;
574 regs = lightrec_get_registers(lightrec_state);
575 memcpy(regs->cp2d, &psxRegs.CP2, sizeof(regs->cp2d) + sizeof(regs->cp2c));
576 memcpy(regs->cp0, &psxRegs.CP0, sizeof(regs->cp0));
577 memcpy(regs->gpr, &psxRegs.GPR, sizeof(regs->gpr));
579 lightrec_invalidate_all(lightrec_state);
582 void lightrec_plugin_prepare_save_state(void)
584 struct lightrec_registers *regs;
586 regs = lightrec_get_registers(lightrec_state);
587 memcpy(&psxRegs.CP2, regs->cp2d, sizeof(regs->cp2d) + sizeof(regs->cp2c));
588 memcpy(&psxRegs.CP0, regs->cp0, sizeof(regs->cp0));
589 memcpy(&psxRegs.GPR, regs->gpr, sizeof(regs->gpr));
594 lightrec_plugin_init,
595 lightrec_plugin_reset,
596 lightrec_plugin_execute,
597 lightrec_plugin_execute_block,
598 lightrec_plugin_clear,
599 lightrec_plugin_notify,
600 lightrec_plugin_apply_config,
601 lightrec_plugin_shutdown,