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 void cop2_op(struct lightrec_state *state, u32 func)
109 struct lightrec_registers *regs = lightrec_get_registers(state);
113 if (unlikely(!cp2_ops[func & 0x3f])) {
114 fprintf(stderr, "Invalid CP2 function %u\n", func);
116 /* This works because regs->cp2c comes right after regs->cp2d,
117 * so it can be cast to a pcsxCP2Regs pointer. */
118 cp2_ops[func & 0x3f]((psxCP2Regs *) regs->cp2d);
122 static bool has_interrupt(void)
124 return ((psxHu32(0x1070) & psxHu32(0x1074)) &&
125 (psxRegs.CP0.n.Status & 0x401) == 0x401) ||
126 (psxRegs.CP0.n.Status & psxRegs.CP0.n.Cause & 0x0300);
129 static void lightrec_restore_state(struct lightrec_state *state)
131 lightrec_reset_cycle_count(state, psxRegs.cycle);
133 if (booting || has_interrupt())
134 lightrec_set_exit_flags(state, LIGHTREC_EXIT_CHECK_INTERRUPT);
136 lightrec_set_target_cycle_count(state, next_interupt);
139 static void hw_write_byte(struct lightrec_state *state,
140 u32 op, void *host, u32 mem, u8 val)
142 psxRegs.cycle = lightrec_current_cycle_count(state);
144 psxHwWrite8(mem, val);
146 lightrec_restore_state(state);
149 static void hw_write_half(struct lightrec_state *state,
150 u32 op, void *host, u32 mem, u16 val)
152 psxRegs.cycle = lightrec_current_cycle_count(state);
154 psxHwWrite16(mem, val);
156 lightrec_restore_state(state);
159 static void hw_write_word(struct lightrec_state *state,
160 u32 op, void *host, u32 mem, u32 val)
162 psxRegs.cycle = lightrec_current_cycle_count(state);
164 psxHwWrite32(mem, val);
166 lightrec_restore_state(state);
169 static u8 hw_read_byte(struct lightrec_state *state, u32 op, void *host, u32 mem)
173 psxRegs.cycle = lightrec_current_cycle_count(state);
175 val = psxHwRead8(mem);
177 lightrec_restore_state(state);
182 static u16 hw_read_half(struct lightrec_state *state,
183 u32 op, void *host, u32 mem)
187 psxRegs.cycle = lightrec_current_cycle_count(state);
189 val = psxHwRead16(mem);
191 lightrec_restore_state(state);
196 static u32 hw_read_word(struct lightrec_state *state,
197 u32 op, void *host, u32 mem)
201 psxRegs.cycle = lightrec_current_cycle_count(state);
203 val = psxHwRead32(mem);
205 lightrec_restore_state(state);
210 static struct lightrec_mem_map_ops hw_regs_ops = {
219 static u32 cache_ctrl;
221 static void cache_ctrl_write_word(struct lightrec_state *state,
222 u32 op, void *host, u32 mem, u32 val)
227 static u32 cache_ctrl_read_word(struct lightrec_state *state,
228 u32 op, void *host, u32 mem)
233 static struct lightrec_mem_map_ops cache_ctrl_ops = {
234 .sw = cache_ctrl_write_word,
235 .lw = cache_ctrl_read_word,
238 static struct lightrec_mem_map lightrec_map[] = {
239 [PSX_MAP_KERNEL_USER_RAM] = {
240 /* Kernel and user memory */
249 [PSX_MAP_SCRATCH_PAD] = {
254 [PSX_MAP_PARALLEL_PORT] = {
259 [PSX_MAP_HW_REGISTERS] = {
260 /* Hardware registers */
265 [PSX_MAP_CACHE_CONTROL] = {
269 .ops = &cache_ctrl_ops,
272 /* Mirrors of the kernel/user memory */
273 [PSX_MAP_MIRROR1] = {
276 .mirror_of = &lightrec_map[PSX_MAP_KERNEL_USER_RAM],
278 [PSX_MAP_MIRROR2] = {
281 .mirror_of = &lightrec_map[PSX_MAP_KERNEL_USER_RAM],
283 [PSX_MAP_MIRROR3] = {
286 .mirror_of = &lightrec_map[PSX_MAP_KERNEL_USER_RAM],
290 static void lightrec_enable_ram(struct lightrec_state *state, bool enable)
293 memcpy(psxM, cache_buf, sizeof(cache_buf));
295 memcpy(cache_buf, psxM, sizeof(cache_buf));
298 static const struct lightrec_ops lightrec_ops = {
300 .enable_ram = lightrec_enable_ram,
303 static int lightrec_plugin_init(void)
305 lightrec_map[PSX_MAP_KERNEL_USER_RAM].address = psxM;
306 lightrec_map[PSX_MAP_BIOS].address = psxR;
307 lightrec_map[PSX_MAP_SCRATCH_PAD].address = psxH;
308 lightrec_map[PSX_MAP_PARALLEL_PORT].address = psxP;
310 lightrec_debug = !!getenv("LIGHTREC_DEBUG");
311 lightrec_very_debug = !!getenv("LIGHTREC_VERY_DEBUG");
312 use_lightrec_interpreter = !!getenv("LIGHTREC_INTERPRETER");
313 if (getenv("LIGHTREC_BEGIN_CYCLES"))
314 lightrec_begin_cycles = (unsigned int) strtol(
315 getenv("LIGHTREC_BEGIN_CYCLES"), NULL, 0);
317 lightrec_state = lightrec_init(name,
318 lightrec_map, ARRAY_SIZE(lightrec_map),
321 // fprintf(stderr, "M=0x%lx, P=0x%lx, R=0x%lx, H=0x%lx\n",
325 // (uintptr_t) psxH);
328 signal(SIGPIPE, exit);
333 static u32 hash_calculate_le(const void *buffer, u32 count)
336 u32 *data = (u32 *) buffer;
337 u32 hash = 0xffffffff;
340 for(i = 0; i < count; ++i) {
341 hash += LE32TOH(data[i]);
342 hash += (hash << 10);
347 hash ^= (hash >> 11);
348 hash += (hash << 15);
352 static u32 hash_calculate(const void *buffer, u32 count)
355 u32 *data = (u32 *) buffer;
356 u32 hash = 0xffffffff;
359 for(i = 0; i < count; ++i) {
361 hash += (hash << 10);
366 hash ^= (hash >> 11);
367 hash += (hash << 15);
371 static const char * const mips_regs[] = {
375 "a0", "a1", "a2", "a3",
376 "t0", "t1", "t2", "t3", "t4", "t5", "t6", "t7",
377 "s0", "s1", "s2", "s3", "s4", "s5", "s6", "s7",
380 "gp", "sp", "fp", "ra",
384 static void print_for_big_ass_debugger(void)
388 printf("CYCLE 0x%08x PC 0x%08x", psxRegs.cycle, psxRegs.pc);
390 if (lightrec_very_debug)
391 printf(" RAM 0x%08x SCRATCH 0x%08x HW 0x%08x",
392 hash_calculate_le(psxM, 0x200000),
393 hash_calculate_le(psxH, 0x400),
394 hash_calculate_le(psxH + 0x1000, 0x2000));
396 printf(" CP0 0x%08x CP2D 0x%08x CP2C 0x%08x INT 0x%04x INTCYCLE 0x%08x GPU 0x%08x",
397 hash_calculate(&psxRegs.CP0.r,
398 sizeof(psxRegs.CP0.r)),
399 hash_calculate(&psxRegs.CP2D.r,
400 sizeof(psxRegs.CP2D.r)),
401 hash_calculate(&psxRegs.CP2C.r,
402 sizeof(psxRegs.CP2C.r)),
404 hash_calculate(psxRegs.intCycle,
405 sizeof(psxRegs.intCycle)),
406 LE32TOH(HW_GPU_STATUS));
408 if (lightrec_very_debug)
409 for (i = 0; i < 34; i++)
410 printf(" %s 0x%08x", mips_regs[i], psxRegs.GPR.r[i]);
412 printf(" GPR 0x%08x", hash_calculate(&psxRegs.GPR.r,
413 sizeof(psxRegs.GPR.r)));
417 static void lightrec_dump_regs(struct lightrec_state *state)
419 struct lightrec_registers *regs = lightrec_get_registers(state);
421 if (unlikely(booting))
422 memcpy(&psxRegs.GPR, regs->gpr, sizeof(regs->gpr));
423 psxRegs.CP0.n.Status = regs->cp0[12];
424 psxRegs.CP0.n.Cause = regs->cp0[13];
427 static void lightrec_restore_regs(struct lightrec_state *state)
429 struct lightrec_registers *regs = lightrec_get_registers(state);
431 if (unlikely(booting))
432 memcpy(regs->gpr, &psxRegs.GPR, sizeof(regs->gpr));
433 regs->cp0[12] = psxRegs.CP0.n.Status;
434 regs->cp0[13] = psxRegs.CP0.n.Cause;
435 regs->cp0[14] = psxRegs.CP0.n.EPC;
438 extern void intExecuteBlock();
439 extern void gen_interupt();
441 static void lightrec_plugin_execute_block(void)
443 u32 old_pc = psxRegs.pc;
448 if (use_pcsx_interpreter) {
451 lightrec_reset_cycle_count(lightrec_state, psxRegs.cycle);
452 lightrec_restore_regs(lightrec_state);
454 if (unlikely(use_lightrec_interpreter))
455 psxRegs.pc = lightrec_run_interpreter(lightrec_state,
457 // step during early boot so that 0x80030000 fastboot hack works
458 else if (unlikely(booting || lightrec_debug))
459 psxRegs.pc = lightrec_execute_one(lightrec_state,
462 psxRegs.pc = lightrec_execute(lightrec_state,
463 psxRegs.pc, next_interupt);
465 psxRegs.cycle = lightrec_current_cycle_count(lightrec_state);
467 lightrec_dump_regs(lightrec_state);
468 flags = lightrec_exit_flags(lightrec_state);
470 if (flags & LIGHTREC_EXIT_SEGFAULT) {
471 fprintf(stderr, "Exiting at cycle 0x%08x\n",
476 if (flags & LIGHTREC_EXIT_SYSCALL)
477 psxException(0x20, 0);
479 if (booting && (psxRegs.pc & 0xff800000) == 0x80000000)
483 if (lightrec_debug && psxRegs.cycle >= lightrec_begin_cycles
484 && psxRegs.pc != old_pc)
485 print_for_big_ass_debugger();
487 if ((psxRegs.CP0.n.Cause & psxRegs.CP0.n.Status & 0x300) &&
488 (psxRegs.CP0.n.Status & 0x1)) {
489 /* Handle software interrupts */
490 psxRegs.CP0.n.Cause &= ~0x7c;
491 psxException(psxRegs.CP0.n.Cause, 0);
495 static void lightrec_plugin_execute(void)
500 lightrec_plugin_execute_block();
503 static void lightrec_plugin_clear(u32 addr, u32 size)
505 if (addr == 0 && size == UINT32_MAX)
506 lightrec_invalidate_all(lightrec_state);
508 /* size * 4: PCSX uses DMA units */
509 lightrec_invalidate(lightrec_state, addr, size * 4);
512 static void lightrec_plugin_notify(int note, void *data)
515 To change once proper icache emulation is emulated
518 case R3000ACPU_NOTIFY_CACHE_UNISOLATED:
519 lightrec_plugin_clear(0, 0x200000/4);
521 case R3000ACPU_NOTIFY_CACHE_ISOLATED:
522 // Sent from psxDma3().
523 case R3000ACPU_NOTIFY_DMA3_EXE_LOAD:
529 static void lightrec_plugin_apply_config()
533 static void lightrec_plugin_shutdown(void)
535 lightrec_destroy(lightrec_state);
538 static void lightrec_plugin_reset(void)
540 struct lightrec_registers *regs;
542 lightrec_plugin_shutdown();
543 lightrec_plugin_init();
545 regs = lightrec_get_registers(lightrec_state);
547 regs->cp0[12] = 0x10900000; // COP0 enabled | BEV = 1 | TS = 1
548 regs->cp0[15] = 0x00000002; // PRevID = Revision ID, same as R3000A
555 lightrec_plugin_init,
556 lightrec_plugin_reset,
557 lightrec_plugin_execute,
558 lightrec_plugin_execute_block,
559 lightrec_plugin_clear,
560 lightrec_plugin_notify,
561 lightrec_plugin_apply_config,
562 lightrec_plugin_shutdown,