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;
52 static u32 lightrec_begin_cycles;
79 static void (*cp2_ops[])(struct psxCP2Regs *) = {
80 [OP_CP2_RTPS] = gteRTPS,
81 [OP_CP2_RTPS] = gteRTPS,
82 [OP_CP2_NCLIP] = gteNCLIP,
84 [OP_CP2_DPCS] = gteDPCS,
85 [OP_CP2_INTPL] = gteINTPL,
86 [OP_CP2_MVMVA] = gteMVMVA,
87 [OP_CP2_NCDS] = gteNCDS,
88 [OP_CP2_CDP] = gteCDP,
89 [OP_CP2_NCDT] = gteNCDT,
90 [OP_CP2_NCCS] = gteNCCS,
92 [OP_CP2_NCS] = gteNCS,
93 [OP_CP2_NCT] = gteNCT,
94 [OP_CP2_SQR] = gteSQR,
95 [OP_CP2_DCPL] = gteDCPL,
96 [OP_CP2_DPCT] = gteDPCT,
97 [OP_CP2_AVSZ3] = gteAVSZ3,
98 [OP_CP2_AVSZ4] = gteAVSZ4,
99 [OP_CP2_RTPT] = gteRTPT,
100 [OP_CP2_GPF] = gteGPF,
101 [OP_CP2_GPL] = gteGPL,
102 [OP_CP2_NCCT] = gteNCCT,
105 static char cache_buf[64 * 1024];
107 static u32 cop0_mfc(struct lightrec_state *state, u32 op, u8 reg)
109 return psxRegs.CP0.r[reg];
112 static u32 cop2_mfc_cfc(struct lightrec_state *state, u8 reg, bool cfc)
115 return psxRegs.CP2C.r[reg];
120 static u32 cop2_mfc(struct lightrec_state *state, u32 op, u8 reg)
122 return cop2_mfc_cfc(state, reg, false);
125 static u32 cop2_cfc(struct lightrec_state *state, u32 op, u8 reg)
127 return cop2_mfc_cfc(state, reg, true);
130 static bool has_interrupt(void)
132 return ((psxHu32(0x1070) & psxHu32(0x1074)) &&
133 (psxRegs.CP0.n.Status & 0x401) == 0x401) ||
134 (psxRegs.CP0.n.Status & psxRegs.CP0.n.Cause & 0x0300);
137 static void lightrec_restore_state(struct lightrec_state *state)
139 lightrec_reset_cycle_count(state, psxRegs.cycle);
141 if (booting || has_interrupt())
142 lightrec_set_exit_flags(state, LIGHTREC_EXIT_CHECK_INTERRUPT);
144 lightrec_set_target_cycle_count(state, next_interupt);
147 static void cop0_mtc_ctc(struct lightrec_state *state,
148 u8 reg, u32 value, bool ctc)
150 psxRegs.cycle = lightrec_current_cycle_count(state);
158 /* Those registers are read-only */
160 case 12: /* Status */
161 if ((psxRegs.CP0.n.Status & ~value) & (1 << 16)) {
162 memcpy(psxM, cache_buf, sizeof(cache_buf));
163 lightrec_invalidate_all(state);
164 } else if ((~psxRegs.CP0.n.Status & value) & (1 << 16)) {
165 memcpy(cache_buf, psxM, sizeof(cache_buf));
168 psxRegs.CP0.n.Status = value;
171 psxRegs.CP0.n.Cause &= ~0x0300;
172 psxRegs.CP0.n.Cause |= value & 0x0300;
175 psxRegs.CP0.r[reg] = value;
179 lightrec_restore_state(state);
182 static void cop2_mtc_ctc(struct lightrec_state *state,
183 u8 reg, u32 value, bool ctc)
191 static void cop0_mtc(struct lightrec_state *state, u32 op, u8 reg, u32 value)
193 cop0_mtc_ctc(state, reg, value, false);
196 static void cop0_ctc(struct lightrec_state *state, u32 op, u8 reg, u32 value)
198 cop0_mtc_ctc(state, reg, value, true);
201 static void cop2_mtc(struct lightrec_state *state, u32 op, u8 reg, u32 value)
203 cop2_mtc_ctc(state, reg, value, false);
206 static void cop2_ctc(struct lightrec_state *state, u32 op, u8 reg, u32 value)
208 cop2_mtc_ctc(state, reg, value, true);
211 static void cop0_op(struct lightrec_state *state, u32 func)
213 fprintf(stderr, "Invalid access to COP0\n");
216 static void cop2_op(struct lightrec_state *state, u32 func)
220 if (unlikely(!cp2_ops[func & 0x3f]))
221 fprintf(stderr, "Invalid CP2 function %u\n", func);
223 cp2_ops[func & 0x3f](&psxRegs.CP2);
226 static void hw_write_byte(struct lightrec_state *state,
227 u32 op, void *host, u32 mem, u8 val)
229 psxRegs.cycle = lightrec_current_cycle_count(state);
231 psxHwWrite8(mem, val);
233 lightrec_restore_state(state);
236 static void hw_write_half(struct lightrec_state *state,
237 u32 op, void *host, u32 mem, u16 val)
239 psxRegs.cycle = lightrec_current_cycle_count(state);
241 psxHwWrite16(mem, val);
243 lightrec_restore_state(state);
246 static void hw_write_word(struct lightrec_state *state,
247 u32 op, void *host, u32 mem, u32 val)
249 psxRegs.cycle = lightrec_current_cycle_count(state);
251 psxHwWrite32(mem, val);
253 lightrec_restore_state(state);
256 static u8 hw_read_byte(struct lightrec_state *state, u32 op, void *host, u32 mem)
260 psxRegs.cycle = lightrec_current_cycle_count(state);
262 val = psxHwRead8(mem);
264 lightrec_restore_state(state);
269 static u16 hw_read_half(struct lightrec_state *state,
270 u32 op, void *host, u32 mem)
274 psxRegs.cycle = lightrec_current_cycle_count(state);
276 val = psxHwRead16(mem);
278 lightrec_restore_state(state);
283 static u32 hw_read_word(struct lightrec_state *state,
284 u32 op, void *host, u32 mem)
288 psxRegs.cycle = lightrec_current_cycle_count(state);
290 val = psxHwRead32(mem);
292 lightrec_restore_state(state);
297 static struct lightrec_mem_map_ops hw_regs_ops = {
306 static u32 cache_ctrl;
308 static void cache_ctrl_write_word(struct lightrec_state *state,
309 u32 op, void *host, u32 mem, u32 val)
314 static u32 cache_ctrl_read_word(struct lightrec_state *state,
315 u32 op, void *host, u32 mem)
320 static struct lightrec_mem_map_ops cache_ctrl_ops = {
321 .sw = cache_ctrl_write_word,
322 .lw = cache_ctrl_read_word,
325 static struct lightrec_mem_map lightrec_map[] = {
326 [PSX_MAP_KERNEL_USER_RAM] = {
327 /* Kernel and user memory */
336 [PSX_MAP_SCRATCH_PAD] = {
341 [PSX_MAP_PARALLEL_PORT] = {
346 [PSX_MAP_HW_REGISTERS] = {
347 /* Hardware registers */
352 [PSX_MAP_CACHE_CONTROL] = {
356 .ops = &cache_ctrl_ops,
359 /* Mirrors of the kernel/user memory */
360 [PSX_MAP_MIRROR1] = {
363 .mirror_of = &lightrec_map[PSX_MAP_KERNEL_USER_RAM],
365 [PSX_MAP_MIRROR2] = {
368 .mirror_of = &lightrec_map[PSX_MAP_KERNEL_USER_RAM],
370 [PSX_MAP_MIRROR3] = {
373 .mirror_of = &lightrec_map[PSX_MAP_KERNEL_USER_RAM],
377 static const struct lightrec_ops lightrec_ops = {
394 static int lightrec_plugin_init(void)
396 lightrec_map[PSX_MAP_KERNEL_USER_RAM].address = psxM;
397 lightrec_map[PSX_MAP_BIOS].address = psxR;
398 lightrec_map[PSX_MAP_SCRATCH_PAD].address = psxH;
399 lightrec_map[PSX_MAP_PARALLEL_PORT].address = psxP;
401 lightrec_debug = !!getenv("LIGHTREC_DEBUG");
402 lightrec_very_debug = !!getenv("LIGHTREC_VERY_DEBUG");
403 use_lightrec_interpreter = !!getenv("LIGHTREC_INTERPRETER");
404 if (getenv("LIGHTREC_BEGIN_CYCLES"))
405 lightrec_begin_cycles = (unsigned int) strtol(
406 getenv("LIGHTREC_BEGIN_CYCLES"), NULL, 0);
408 lightrec_state = lightrec_init(name,
409 lightrec_map, ARRAY_SIZE(lightrec_map),
412 // fprintf(stderr, "M=0x%lx, P=0x%lx, R=0x%lx, H=0x%lx\n",
416 // (uintptr_t) psxH);
419 signal(SIGPIPE, exit);
424 static u32 hash_calculate_le(const void *buffer, u32 count)
427 u32 *data = (u32 *) buffer;
428 u32 hash = 0xffffffff;
431 for(i = 0; i < count; ++i) {
432 hash += LE32TOH(data[i]);
433 hash += (hash << 10);
438 hash ^= (hash >> 11);
439 hash += (hash << 15);
443 static u32 hash_calculate(const void *buffer, u32 count)
446 u32 *data = (u32 *) buffer;
447 u32 hash = 0xffffffff;
450 for(i = 0; i < count; ++i) {
452 hash += (hash << 10);
457 hash ^= (hash >> 11);
458 hash += (hash << 15);
462 static const char * const mips_regs[] = {
466 "a0", "a1", "a2", "a3",
467 "t0", "t1", "t2", "t3", "t4", "t5", "t6", "t7",
468 "s0", "s1", "s2", "s3", "s4", "s5", "s6", "s7",
471 "gp", "sp", "fp", "ra",
475 static void print_for_big_ass_debugger(void)
479 printf("CYCLE 0x%08x PC 0x%08x", psxRegs.cycle, psxRegs.pc);
481 if (lightrec_very_debug)
482 printf(" RAM 0x%08x SCRATCH 0x%08x HW 0x%08x",
483 hash_calculate_le(psxM, 0x200000),
484 hash_calculate_le(psxH, 0x400),
485 hash_calculate_le(psxH + 0x1000, 0x2000));
487 printf(" CP0 0x%08x CP2D 0x%08x CP2C 0x%08x INT 0x%04x INTCYCLE 0x%08x GPU 0x%08x",
488 hash_calculate(&psxRegs.CP0.r,
489 sizeof(psxRegs.CP0.r)),
490 hash_calculate(&psxRegs.CP2D.r,
491 sizeof(psxRegs.CP2D.r)),
492 hash_calculate(&psxRegs.CP2C.r,
493 sizeof(psxRegs.CP2C.r)),
495 hash_calculate(psxRegs.intCycle,
496 sizeof(psxRegs.intCycle)),
497 LE32TOH(HW_GPU_STATUS));
499 if (lightrec_very_debug)
500 for (i = 0; i < 34; i++)
501 printf(" %s 0x%08x", mips_regs[i], psxRegs.GPR.r[i]);
503 printf(" GPR 0x%08x", hash_calculate(&psxRegs.GPR.r,
504 sizeof(psxRegs.GPR.r)));
509 extern void intExecuteBlock();
510 extern void gen_interupt();
512 static u32 old_cycle_counter;
514 static void lightrec_plugin_execute_block(void)
516 u32 old_pc = psxRegs.pc;
521 if (use_pcsx_interpreter) {
524 lightrec_reset_cycle_count(lightrec_state, psxRegs.cycle);
525 lightrec_restore_registers(lightrec_state, psxRegs.GPR.r);
527 if (unlikely(use_lightrec_interpreter))
528 psxRegs.pc = lightrec_run_interpreter(lightrec_state,
530 // step during early boot so that 0x80030000 fastboot hack works
531 else if (unlikely(booting))
532 psxRegs.pc = lightrec_execute_one(lightrec_state,
535 psxRegs.pc = lightrec_execute(lightrec_state,
536 psxRegs.pc, next_interupt);
538 psxRegs.cycle = lightrec_current_cycle_count(lightrec_state);
540 lightrec_dump_registers(lightrec_state, psxRegs.GPR.r);
541 flags = lightrec_exit_flags(lightrec_state);
543 if (flags & LIGHTREC_EXIT_SEGFAULT) {
544 fprintf(stderr, "Exiting at cycle 0x%08x\n",
549 if (flags & LIGHTREC_EXIT_SYSCALL)
550 psxException(0x20, 0);
552 if (booting && (psxRegs.pc & 0xff800000) == 0x80000000)
556 if (lightrec_debug && psxRegs.cycle >= lightrec_begin_cycles
557 && psxRegs.pc != old_pc)
558 print_for_big_ass_debugger();
560 if ((psxRegs.CP0.n.Cause & psxRegs.CP0.n.Status & 0x300) &&
561 (psxRegs.CP0.n.Status & 0x1)) {
562 /* Handle software interrupts */
563 psxRegs.CP0.n.Cause &= ~0x7c;
564 psxException(psxRegs.CP0.n.Cause, 0);
567 if ((psxRegs.cycle & ~0xfffffff) != old_cycle_counter) {
568 SysDLog("RAM usage: Lightrec %u KiB, IR %u KiB, CODE %u KiB, "
569 "MIPS %u KiB, TOTAL %u KiB, avg. IPI %f\n",
570 lightrec_get_mem_usage(MEM_FOR_LIGHTREC) / 1024,
571 lightrec_get_mem_usage(MEM_FOR_IR) / 1024,
572 lightrec_get_mem_usage(MEM_FOR_CODE) / 1024,
573 lightrec_get_mem_usage(MEM_FOR_MIPS_CODE) / 1024,
574 lightrec_get_total_mem_usage() / 1024,
575 lightrec_get_average_ipi());
576 old_cycle_counter = psxRegs.cycle & ~0xfffffff;
580 static void lightrec_plugin_execute(void)
585 lightrec_plugin_execute_block();
588 static void lightrec_plugin_clear(u32 addr, u32 size)
590 if (addr == 0 && size == UINT32_MAX)
591 lightrec_invalidate_all(lightrec_state);
593 /* size * 4: PCSX uses DMA units */
594 lightrec_invalidate(lightrec_state, addr, size * 4);
597 static void lightrec_plugin_notify(int note, void *data)
600 To change once proper icache emulation is emulated
603 case R3000ACPU_NOTIFY_CACHE_UNISOLATED:
604 lightrec_plugin_clear(0, 0x200000/4);
606 case R3000ACPU_NOTIFY_CACHE_ISOLATED:
607 // Sent from psxDma3().
608 case R3000ACPU_NOTIFY_DMA3_EXE_LOAD:
614 static void lightrec_plugin_apply_config()
618 static void lightrec_plugin_shutdown(void)
620 lightrec_destroy(lightrec_state);
623 static void lightrec_plugin_reset(void)
625 lightrec_plugin_shutdown();
626 lightrec_plugin_init();
632 lightrec_plugin_init,
633 lightrec_plugin_reset,
634 lightrec_plugin_execute,
635 lightrec_plugin_execute_block,
636 lightrec_plugin_clear,
637 lightrec_plugin_notify,
638 lightrec_plugin_apply_config,
639 lightrec_plugin_shutdown,