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 lightrec_restore_state(struct lightrec_state *state)
131 lightrec_reset_cycle_count(state, psxRegs.cycle);
132 lightrec_set_exit_flags(state, LIGHTREC_EXIT_CHECK_INTERRUPT);
135 static void cop0_mtc_ctc(struct lightrec_state *state,
136 u8 reg, u32 value, bool ctc)
144 /* Those registers are read-only */
146 case 12: /* Status */
147 if ((psxRegs.CP0.n.Status & ~value) & (1 << 16)) {
148 memcpy(psxM, cache_buf, sizeof(cache_buf));
149 lightrec_invalidate_all(state);
150 } else if ((~psxRegs.CP0.n.Status & value) & (1 << 16)) {
151 memcpy(cache_buf, psxM, sizeof(cache_buf));
154 psxRegs.CP0.n.Status = value;
157 psxRegs.CP0.n.Cause &= ~0x0300;
158 psxRegs.CP0.n.Cause |= value & 0x0300;
161 psxRegs.CP0.r[reg] = value;
165 lightrec_restore_state(state);
168 static void cop2_mtc_ctc(struct lightrec_state *state,
169 u8 reg, u32 value, bool ctc)
177 static void cop0_mtc(struct lightrec_state *state, u32 op, u8 reg, u32 value)
179 cop0_mtc_ctc(state, reg, value, false);
182 static void cop0_ctc(struct lightrec_state *state, u32 op, u8 reg, u32 value)
184 cop0_mtc_ctc(state, reg, value, true);
187 static void cop2_mtc(struct lightrec_state *state, u32 op, u8 reg, u32 value)
189 cop2_mtc_ctc(state, reg, value, false);
192 static void cop2_ctc(struct lightrec_state *state, u32 op, u8 reg, u32 value)
194 cop2_mtc_ctc(state, reg, value, true);
197 static void cop0_op(struct lightrec_state *state, u32 func)
199 fprintf(stderr, "Invalid access to COP0\n");
202 static void cop2_op(struct lightrec_state *state, u32 func)
206 if (unlikely(!cp2_ops[func & 0x3f]))
207 fprintf(stderr, "Invalid CP2 function %u\n", func);
209 cp2_ops[func & 0x3f](&psxRegs.CP2);
212 static void hw_write_byte(struct lightrec_state *state,
213 u32 op, void *host, u32 mem, u8 val)
215 psxRegs.cycle = lightrec_current_cycle_count(state);
217 psxHwWrite8(mem, val);
219 lightrec_restore_state(state);
222 static void hw_write_half(struct lightrec_state *state,
223 u32 op, void *host, u32 mem, u16 val)
225 psxRegs.cycle = lightrec_current_cycle_count(state);
227 psxHwWrite16(mem, val);
229 lightrec_restore_state(state);
232 static void hw_write_word(struct lightrec_state *state,
233 u32 op, void *host, u32 mem, u32 val)
235 psxRegs.cycle = lightrec_current_cycle_count(state);
237 psxHwWrite32(mem, val);
239 lightrec_restore_state(state);
242 static u8 hw_read_byte(struct lightrec_state *state, u32 op, void *host, u32 mem)
246 psxRegs.cycle = lightrec_current_cycle_count(state);
248 val = psxHwRead8(mem);
250 lightrec_restore_state(state);
255 static u16 hw_read_half(struct lightrec_state *state,
256 u32 op, void *host, u32 mem)
260 psxRegs.cycle = lightrec_current_cycle_count(state);
262 val = psxHwRead16(mem);
264 lightrec_restore_state(state);
269 static u32 hw_read_word(struct lightrec_state *state,
270 u32 op, void *host, u32 mem)
274 psxRegs.cycle = lightrec_current_cycle_count(state);
276 val = psxHwRead32(mem);
278 lightrec_restore_state(state);
283 static struct lightrec_mem_map_ops hw_regs_ops = {
292 static u32 cache_ctrl;
294 static void cache_ctrl_write_word(struct lightrec_state *state,
295 u32 op, void *host, u32 mem, u32 val)
300 static u32 cache_ctrl_read_word(struct lightrec_state *state,
301 u32 op, void *host, u32 mem)
306 static struct lightrec_mem_map_ops cache_ctrl_ops = {
307 .sw = cache_ctrl_write_word,
308 .lw = cache_ctrl_read_word,
311 static struct lightrec_mem_map lightrec_map[] = {
312 [PSX_MAP_KERNEL_USER_RAM] = {
313 /* Kernel and user memory */
322 [PSX_MAP_SCRATCH_PAD] = {
327 [PSX_MAP_PARALLEL_PORT] = {
332 [PSX_MAP_HW_REGISTERS] = {
333 /* Hardware registers */
338 [PSX_MAP_CACHE_CONTROL] = {
342 .ops = &cache_ctrl_ops,
345 /* Mirrors of the kernel/user memory */
346 [PSX_MAP_MIRROR1] = {
349 .mirror_of = &lightrec_map[PSX_MAP_KERNEL_USER_RAM],
351 [PSX_MAP_MIRROR2] = {
354 .mirror_of = &lightrec_map[PSX_MAP_KERNEL_USER_RAM],
356 [PSX_MAP_MIRROR3] = {
359 .mirror_of = &lightrec_map[PSX_MAP_KERNEL_USER_RAM],
363 static const struct lightrec_ops lightrec_ops = {
380 static int lightrec_plugin_init(void)
382 lightrec_map[PSX_MAP_KERNEL_USER_RAM].address = psxM;
383 lightrec_map[PSX_MAP_BIOS].address = psxR;
384 lightrec_map[PSX_MAP_SCRATCH_PAD].address = psxH;
385 lightrec_map[PSX_MAP_PARALLEL_PORT].address = psxP;
387 lightrec_debug = !!getenv("LIGHTREC_DEBUG");
388 lightrec_very_debug = !!getenv("LIGHTREC_VERY_DEBUG");
389 use_lightrec_interpreter = !!getenv("LIGHTREC_INTERPRETER");
390 if (getenv("LIGHTREC_BEGIN_CYCLES"))
391 lightrec_begin_cycles = (unsigned int) strtol(
392 getenv("LIGHTREC_BEGIN_CYCLES"), NULL, 0);
394 lightrec_state = lightrec_init(name,
395 lightrec_map, ARRAY_SIZE(lightrec_map),
398 // fprintf(stderr, "M=0x%lx, P=0x%lx, R=0x%lx, H=0x%lx\n",
402 // (uintptr_t) psxH);
405 signal(SIGPIPE, exit);
410 static u32 hash_calculate_le(const void *buffer, u32 count)
413 u32 *data = (u32 *) buffer;
414 u32 hash = 0xffffffff;
417 for(i = 0; i < count; ++i) {
418 hash += LE32TOH(data[i]);
419 hash += (hash << 10);
424 hash ^= (hash >> 11);
425 hash += (hash << 15);
429 static u32 hash_calculate(const void *buffer, u32 count)
432 u32 *data = (u32 *) buffer;
433 u32 hash = 0xffffffff;
436 for(i = 0; i < count; ++i) {
438 hash += (hash << 10);
443 hash ^= (hash >> 11);
444 hash += (hash << 15);
448 static const char * const mips_regs[] = {
452 "a0", "a1", "a2", "a3",
453 "t0", "t1", "t2", "t3", "t4", "t5", "t6", "t7",
454 "s0", "s1", "s2", "s3", "s4", "s5", "s6", "s7",
457 "gp", "sp", "fp", "ra",
461 static void print_for_big_ass_debugger(void)
465 printf("CYCLE 0x%08x PC 0x%08x", psxRegs.cycle, psxRegs.pc);
467 if (lightrec_very_debug)
468 printf(" RAM 0x%08x SCRATCH 0x%08x HW 0x%08x",
469 hash_calculate_le(psxM, 0x200000),
470 hash_calculate_le(psxH, 0x400),
471 hash_calculate_le(psxH + 0x1000, 0x2000));
473 printf(" CP0 0x%08x CP2D 0x%08x CP2C 0x%08x INT 0x%04x INTCYCLE 0x%08x GPU 0x%08x",
474 hash_calculate(&psxRegs.CP0.r,
475 sizeof(psxRegs.CP0.r)),
476 hash_calculate(&psxRegs.CP2D.r,
477 sizeof(psxRegs.CP2D.r)),
478 hash_calculate(&psxRegs.CP2C.r,
479 sizeof(psxRegs.CP2C.r)),
481 hash_calculate(psxRegs.intCycle,
482 sizeof(psxRegs.intCycle)),
483 LE32TOH(HW_GPU_STATUS));
485 if (lightrec_very_debug)
486 for (i = 0; i < 34; i++)
487 printf(" %s 0x%08x", mips_regs[i], psxRegs.GPR.r[i]);
489 printf(" GPR 0x%08x", hash_calculate(&psxRegs.GPR.r,
490 sizeof(psxRegs.GPR.r)));
495 extern void intExecuteBlock();
497 static u32 old_cycle_counter;
499 static void lightrec_plugin_execute_block(void)
501 u32 old_pc = psxRegs.pc;
504 if (use_pcsx_interpreter) {
507 lightrec_reset_cycle_count(lightrec_state, psxRegs.cycle);
508 lightrec_restore_registers(lightrec_state, psxRegs.GPR.r);
510 if (use_lightrec_interpreter)
511 psxRegs.pc = lightrec_run_interpreter(lightrec_state,
514 psxRegs.pc = lightrec_execute_one(lightrec_state,
517 psxRegs.cycle = lightrec_current_cycle_count(lightrec_state);
519 lightrec_dump_registers(lightrec_state, psxRegs.GPR.r);
520 flags = lightrec_exit_flags(lightrec_state);
522 if (flags & LIGHTREC_EXIT_SEGFAULT) {
523 fprintf(stderr, "Exiting at cycle 0x%08x\n",
528 if (flags & LIGHTREC_EXIT_SYSCALL)
529 psxException(0x20, 0);
534 if (lightrec_debug && psxRegs.cycle >= lightrec_begin_cycles
535 && psxRegs.pc != old_pc)
536 print_for_big_ass_debugger();
538 if ((psxRegs.CP0.n.Cause & psxRegs.CP0.n.Status & 0x300) &&
539 (psxRegs.CP0.n.Status & 0x1)) {
540 /* Handle software interrupts */
541 psxRegs.CP0.n.Cause &= ~0x7c;
542 psxException(psxRegs.CP0.n.Cause, 0);
545 if ((psxRegs.cycle & ~0xfffffff) != old_cycle_counter) {
546 SysDLog("RAM usage: Lightrec %u KiB, IR %u KiB, CODE %u KiB, "
547 "MIPS %u KiB, TOTAL %u KiB, avg. IPI %f\n",
548 lightrec_get_mem_usage(MEM_FOR_LIGHTREC) / 1024,
549 lightrec_get_mem_usage(MEM_FOR_IR) / 1024,
550 lightrec_get_mem_usage(MEM_FOR_CODE) / 1024,
551 lightrec_get_mem_usage(MEM_FOR_MIPS_CODE) / 1024,
552 lightrec_get_total_mem_usage() / 1024,
553 lightrec_get_average_ipi());
554 old_cycle_counter = psxRegs.cycle & ~0xfffffff;
558 static void lightrec_plugin_execute(void)
563 lightrec_plugin_execute_block();
566 static void lightrec_plugin_clear(u32 addr, u32 size)
568 if (addr == 0 && size == UINT32_MAX)
569 lightrec_invalidate_all(lightrec_state);
571 /* size * 4: PCSX uses DMA units */
572 lightrec_invalidate(lightrec_state, addr, size * 4);
575 static void lightrec_plugin_notify(int note, void *data)
578 To change once proper icache emulation is emulated
581 case R3000ACPU_NOTIFY_CACHE_UNISOLATED:
582 lightrec_plugin_clear(0, 0x200000/4);
584 case R3000ACPU_NOTIFY_CACHE_ISOLATED:
585 // Sent from psxDma3().
586 case R3000ACPU_NOTIFY_DMA3_EXE_LOAD:
592 static void lightrec_plugin_apply_config()
596 static void lightrec_plugin_shutdown(void)
598 lightrec_destroy(lightrec_state);
601 static void lightrec_plugin_reset(void)
603 lightrec_plugin_shutdown();
604 lightrec_plugin_init();
609 lightrec_plugin_init,
610 lightrec_plugin_reset,
611 lightrec_plugin_execute,
612 lightrec_plugin_execute_block,
613 lightrec_plugin_clear,
614 lightrec_plugin_notify,
615 lightrec_plugin_apply_config,
616 lightrec_plugin_shutdown,