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)
43 static struct lightrec_state *lightrec_state;
45 static char *name = "retroarch.exe";
47 static bool use_lightrec_interpreter;
48 static bool use_pcsx_interpreter;
49 static bool lightrec_debug;
50 static bool lightrec_very_debug;
51 static u32 lightrec_begin_cycles;
78 static void (*cp2_ops[])(struct psxCP2Regs *) = {
79 [OP_CP2_RTPS] = gteRTPS,
80 [OP_CP2_RTPS] = gteRTPS,
81 [OP_CP2_NCLIP] = gteNCLIP,
83 [OP_CP2_DPCS] = gteDPCS,
84 [OP_CP2_INTPL] = gteINTPL,
85 [OP_CP2_MVMVA] = gteMVMVA,
86 [OP_CP2_NCDS] = gteNCDS,
87 [OP_CP2_CDP] = gteCDP,
88 [OP_CP2_NCDT] = gteNCDT,
89 [OP_CP2_NCCS] = gteNCCS,
91 [OP_CP2_NCS] = gteNCS,
92 [OP_CP2_NCT] = gteNCT,
93 [OP_CP2_SQR] = gteSQR,
94 [OP_CP2_DCPL] = gteDCPL,
95 [OP_CP2_DPCT] = gteDPCT,
96 [OP_CP2_AVSZ3] = gteAVSZ3,
97 [OP_CP2_AVSZ4] = gteAVSZ4,
98 [OP_CP2_RTPT] = gteRTPT,
99 [OP_CP2_GPF] = gteGPF,
100 [OP_CP2_GPL] = gteGPL,
101 [OP_CP2_NCCT] = gteNCCT,
104 static char cache_buf[64 * 1024];
106 static u32 cop0_mfc(struct lightrec_state *state, u32 op, u8 reg)
108 return psxRegs.CP0.r[reg];
111 static u32 cop2_mfc_cfc(struct lightrec_state *state, u8 reg, bool cfc)
114 return psxRegs.CP2C.r[reg];
119 static u32 cop2_mfc(struct lightrec_state *state, u32 op, u8 reg)
121 return cop2_mfc_cfc(state, reg, false);
124 static u32 cop2_cfc(struct lightrec_state *state, u32 op, u8 reg)
126 return cop2_mfc_cfc(state, reg, true);
129 static void cop0_mtc_ctc(struct lightrec_state *state,
130 u8 reg, u32 value, bool ctc)
138 /* Those registers are read-only */
140 case 12: /* Status */
141 if ((psxRegs.CP0.n.Status & ~value) & (1 << 16)) {
142 memcpy(psxM, cache_buf, sizeof(cache_buf));
143 lightrec_invalidate_all(state);
144 } else if ((~psxRegs.CP0.n.Status & value) & (1 << 16)) {
145 memcpy(cache_buf, psxM, sizeof(cache_buf));
148 psxRegs.CP0.n.Status = value;
149 lightrec_set_exit_flags(state, LIGHTREC_EXIT_CHECK_INTERRUPT);
152 psxRegs.CP0.n.Cause &= ~0x0300;
153 psxRegs.CP0.n.Cause |= value & 0x0300;
154 lightrec_set_exit_flags(state, LIGHTREC_EXIT_CHECK_INTERRUPT);
157 psxRegs.CP0.r[reg] = value;
162 static void cop2_mtc_ctc(struct lightrec_state *state,
163 u8 reg, u32 value, bool ctc)
171 static void cop0_mtc(struct lightrec_state *state, u32 op, u8 reg, u32 value)
173 cop0_mtc_ctc(state, reg, value, false);
176 static void cop0_ctc(struct lightrec_state *state, u32 op, u8 reg, u32 value)
178 cop0_mtc_ctc(state, reg, value, true);
181 static void cop2_mtc(struct lightrec_state *state, u32 op, u8 reg, u32 value)
183 cop2_mtc_ctc(state, reg, value, false);
186 static void cop2_ctc(struct lightrec_state *state, u32 op, u8 reg, u32 value)
188 cop2_mtc_ctc(state, reg, value, true);
191 static void cop0_op(struct lightrec_state *state, u32 func)
193 fprintf(stderr, "Invalid access to COP0\n");
196 static void cop2_op(struct lightrec_state *state, u32 func)
200 if (unlikely(!cp2_ops[func & 0x3f]))
201 fprintf(stderr, "Invalid CP2 function %u\n", func);
203 cp2_ops[func & 0x3f](&psxRegs.CP2);
206 static void hw_write_byte(struct lightrec_state *state,
207 u32 op, void *host, u32 mem, u8 val)
209 psxRegs.cycle = lightrec_current_cycle_count(state);
211 psxHwWrite8(mem, val);
212 lightrec_set_exit_flags(state, LIGHTREC_EXIT_CHECK_INTERRUPT);
214 lightrec_reset_cycle_count(state, psxRegs.cycle);
217 static void hw_write_half(struct lightrec_state *state,
218 u32 op, void *host, u32 mem, u16 val)
220 psxRegs.cycle = lightrec_current_cycle_count(state);
222 psxHwWrite16(mem, val);
223 lightrec_set_exit_flags(state, LIGHTREC_EXIT_CHECK_INTERRUPT);
225 lightrec_reset_cycle_count(state, psxRegs.cycle);
228 static void hw_write_word(struct lightrec_state *state,
229 u32 op, void *host, u32 mem, u32 val)
231 psxRegs.cycle = lightrec_current_cycle_count(state);
233 psxHwWrite32(mem, val);
234 lightrec_set_exit_flags(state, LIGHTREC_EXIT_CHECK_INTERRUPT);
236 lightrec_reset_cycle_count(state, psxRegs.cycle);
239 static u8 hw_read_byte(struct lightrec_state *state, u32 op, void *host, u32 mem)
243 psxRegs.cycle = lightrec_current_cycle_count(state);
245 lightrec_set_exit_flags(state, LIGHTREC_EXIT_CHECK_INTERRUPT);
246 val = psxHwRead8(mem);
247 lightrec_reset_cycle_count(state, psxRegs.cycle);
252 static u16 hw_read_half(struct lightrec_state *state,
253 u32 op, void *host, u32 mem)
257 psxRegs.cycle = lightrec_current_cycle_count(state);
259 lightrec_set_exit_flags(state, LIGHTREC_EXIT_CHECK_INTERRUPT);
260 val = psxHwRead16(mem);
261 lightrec_reset_cycle_count(state, psxRegs.cycle);
266 static u32 hw_read_word(struct lightrec_state *state,
267 u32 op, void *host, u32 mem)
271 psxRegs.cycle = lightrec_current_cycle_count(state);
273 lightrec_set_exit_flags(state, LIGHTREC_EXIT_CHECK_INTERRUPT);
274 val = psxHwRead32(mem);
275 lightrec_reset_cycle_count(state, psxRegs.cycle);
280 static struct lightrec_mem_map_ops hw_regs_ops = {
289 static u32 cache_ctrl;
291 static void cache_ctrl_write_word(struct lightrec_state *state,
292 u32 op, void *host, u32 mem, u32 val)
297 static u32 cache_ctrl_read_word(struct lightrec_state *state,
298 u32 op, void *host, u32 mem)
303 static struct lightrec_mem_map_ops cache_ctrl_ops = {
304 .sw = cache_ctrl_write_word,
305 .lw = cache_ctrl_read_word,
308 static struct lightrec_mem_map lightrec_map[] = {
309 [PSX_MAP_KERNEL_USER_RAM] = {
310 /* Kernel and user memory */
319 [PSX_MAP_SCRATCH_PAD] = {
324 [PSX_MAP_PARALLEL_PORT] = {
329 [PSX_MAP_HW_REGISTERS] = {
330 /* Hardware registers */
335 [PSX_MAP_CACHE_CONTROL] = {
339 .ops = &cache_ctrl_ops,
342 /* Mirrors of the kernel/user memory */
343 [PSX_MAP_MIRROR1] = {
346 .mirror_of = &lightrec_map[PSX_MAP_KERNEL_USER_RAM],
348 [PSX_MAP_MIRROR2] = {
351 .mirror_of = &lightrec_map[PSX_MAP_KERNEL_USER_RAM],
353 [PSX_MAP_MIRROR3] = {
356 .mirror_of = &lightrec_map[PSX_MAP_KERNEL_USER_RAM],
360 static const struct lightrec_ops lightrec_ops = {
377 static int lightrec_plugin_init(void)
379 lightrec_map[PSX_MAP_KERNEL_USER_RAM].address = psxM;
380 lightrec_map[PSX_MAP_BIOS].address = psxR;
381 lightrec_map[PSX_MAP_SCRATCH_PAD].address = psxH;
382 lightrec_map[PSX_MAP_PARALLEL_PORT].address = psxP;
384 lightrec_debug = !!getenv("LIGHTREC_DEBUG");
385 lightrec_very_debug = !!getenv("LIGHTREC_VERY_DEBUG");
386 use_lightrec_interpreter = !!getenv("LIGHTREC_INTERPRETER");
387 if (getenv("LIGHTREC_BEGIN_CYCLES"))
388 lightrec_begin_cycles = (unsigned int) strtol(
389 getenv("LIGHTREC_BEGIN_CYCLES"), NULL, 0);
391 lightrec_state = lightrec_init(name,
392 lightrec_map, ARRAY_SIZE(lightrec_map),
395 // fprintf(stderr, "M=0x%lx, P=0x%lx, R=0x%lx, H=0x%lx\n",
399 // (uintptr_t) psxH);
402 signal(SIGPIPE, exit);
407 static u32 hash_calculate_le(const void *buffer, u32 count)
410 u32 *data = (u32 *) buffer;
411 u32 hash = 0xffffffff;
414 for(i = 0; i < count; ++i) {
415 hash += LE32TOH(data[i]);
416 hash += (hash << 10);
421 hash ^= (hash >> 11);
422 hash += (hash << 15);
426 static u32 hash_calculate(const void *buffer, u32 count)
429 u32 *data = (u32 *) buffer;
430 u32 hash = 0xffffffff;
433 for(i = 0; i < count; ++i) {
435 hash += (hash << 10);
440 hash ^= (hash >> 11);
441 hash += (hash << 15);
445 static const char * const mips_regs[] = {
449 "a0", "a1", "a2", "a3",
450 "t0", "t1", "t2", "t3", "t4", "t5", "t6", "t7",
451 "s0", "s1", "s2", "s3", "s4", "s5", "s6", "s7",
454 "gp", "sp", "fp", "ra",
458 static void print_for_big_ass_debugger(void)
462 printf("CYCLE 0x%08x PC 0x%08x", psxRegs.cycle, psxRegs.pc);
464 if (lightrec_very_debug)
465 printf(" RAM 0x%08x SCRATCH 0x%08x HW 0x%08x",
466 hash_calculate_le(psxM, 0x200000),
467 hash_calculate_le(psxH, 0x400),
468 hash_calculate_le(psxH + 0x1000, 0x2000));
470 printf(" CP0 0x%08x CP2D 0x%08x CP2C 0x%08x INT 0x%04x INTCYCLE 0x%08x GPU 0x%08x",
471 hash_calculate(&psxRegs.CP0.r,
472 sizeof(psxRegs.CP0.r)),
473 hash_calculate(&psxRegs.CP2D.r,
474 sizeof(psxRegs.CP2D.r)),
475 hash_calculate(&psxRegs.CP2C.r,
476 sizeof(psxRegs.CP2C.r)),
478 hash_calculate(psxRegs.intCycle,
479 sizeof(psxRegs.intCycle)),
480 LE32TOH(HW_GPU_STATUS));
482 if (lightrec_very_debug)
483 for (i = 0; i < 34; i++)
484 printf(" %s 0x%08x", mips_regs[i], psxRegs.GPR.r[i]);
486 printf(" GPR 0x%08x", hash_calculate(&psxRegs.GPR.r,
487 sizeof(psxRegs.GPR.r)));
492 extern void intExecuteBlock();
494 static u32 old_cycle_counter;
496 static void lightrec_plugin_execute_block(void)
498 u32 old_pc = psxRegs.pc;
501 if (use_pcsx_interpreter) {
504 lightrec_reset_cycle_count(lightrec_state, psxRegs.cycle);
505 lightrec_restore_registers(lightrec_state, psxRegs.GPR.r);
507 if (use_lightrec_interpreter)
508 psxRegs.pc = lightrec_run_interpreter(lightrec_state,
511 psxRegs.pc = lightrec_execute_one(lightrec_state,
514 psxRegs.cycle = lightrec_current_cycle_count(lightrec_state);
516 lightrec_dump_registers(lightrec_state, psxRegs.GPR.r);
517 flags = lightrec_exit_flags(lightrec_state);
519 if (flags & LIGHTREC_EXIT_SEGFAULT) {
520 fprintf(stderr, "Exiting at cycle 0x%08x\n",
525 if (flags & LIGHTREC_EXIT_SYSCALL)
526 psxException(0x20, 0);
531 if (lightrec_debug && psxRegs.cycle >= lightrec_begin_cycles
532 && psxRegs.pc != old_pc)
533 print_for_big_ass_debugger();
535 if ((psxRegs.CP0.n.Cause & psxRegs.CP0.n.Status & 0x300) &&
536 (psxRegs.CP0.n.Status & 0x1)) {
537 /* Handle software interrupts */
538 psxRegs.CP0.n.Cause &= ~0x7c;
539 psxException(psxRegs.CP0.n.Cause, 0);
542 if ((psxRegs.cycle & ~0xfffffff) != old_cycle_counter) {
543 SysDLog("RAM usage: Lightrec %u KiB, IR %u KiB, CODE %u KiB, "
544 "MIPS %u KiB, TOTAL %u KiB, avg. IPI %f\n",
545 lightrec_get_mem_usage(MEM_FOR_LIGHTREC) / 1024,
546 lightrec_get_mem_usage(MEM_FOR_IR) / 1024,
547 lightrec_get_mem_usage(MEM_FOR_CODE) / 1024,
548 lightrec_get_mem_usage(MEM_FOR_MIPS_CODE) / 1024,
549 lightrec_get_total_mem_usage() / 1024,
550 lightrec_get_average_ipi());
551 old_cycle_counter = psxRegs.cycle & ~0xfffffff;
555 static void lightrec_plugin_execute(void)
560 lightrec_plugin_execute_block();
563 static void lightrec_plugin_clear(u32 addr, u32 size)
565 if (addr == 0 && size == UINT32_MAX)
566 lightrec_invalidate_all(lightrec_state);
568 /* size * 4: PCSX uses DMA units */
569 lightrec_invalidate(lightrec_state, addr, size * 4);
572 static void lightrec_plugin_notify(int note, void *data)
575 To change once proper icache emulation is emulated
578 case R3000ACPU_NOTIFY_CACHE_UNISOLATED:
579 lightrec_plugin_clear(0, 0x200000/4);
581 case R3000ACPU_NOTIFY_CACHE_ISOLATED:
582 // Sent from psxDma3().
583 case R3000ACPU_NOTIFY_DMA3_EXE_LOAD:
589 static void lightrec_plugin_apply_config()
593 static void lightrec_plugin_shutdown(void)
595 lightrec_destroy(lightrec_state);
598 static void lightrec_plugin_reset(void)
600 lightrec_plugin_shutdown();
601 lightrec_plugin_init();
606 lightrec_plugin_init,
607 lightrec_plugin_reset,
608 lightrec_plugin_execute,
609 lightrec_plugin_execute_block,
610 lightrec_plugin_clear,
611 lightrec_plugin_notify,
612 lightrec_plugin_apply_config,
613 lightrec_plugin_shutdown,