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)
40 static struct lightrec_state *lightrec_state;
42 static char *name = "retroarch.exe";
44 static bool use_lightrec_interpreter;
45 static bool lightrec_debug;
46 static bool lightrec_very_debug;
47 static u32 lightrec_begin_cycles;
51 int new_dynarec_hacks;
54 u32 event_cycles[PSXINT_COUNT];
57 void new_dyna_before_save() {}
58 void new_dyna_after_save() {}
59 void new_dyna_freeze(void *f, int i) {}
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 u32 cop0_mfc(struct lightrec_state *state, u8 reg)
116 return psxRegs.CP0.r[reg];
119 static u32 cop2_mfc_cfc(struct lightrec_state *state, u8 reg, bool cfc)
122 return psxRegs.CP2C.r[reg];
127 static u32 cop2_mfc(struct lightrec_state *state, u8 reg)
129 return cop2_mfc_cfc(state, reg, false);
132 static u32 cop2_cfc(struct lightrec_state *state, u8 reg)
134 return cop2_mfc_cfc(state, reg, true);
137 static void cop0_mtc_ctc(struct lightrec_state *state,
138 u8 reg, u32 value, bool ctc)
146 /* Those registers are read-only */
148 case 12: /* Status */
149 if ((psxRegs.CP0.n.Status & ~value) & (1 << 16)) {
150 memcpy(psxM, cache_buf, sizeof(cache_buf));
151 lightrec_invalidate_all(state);
152 } else if ((~psxRegs.CP0.n.Status & value) & (1 << 16)) {
153 memcpy(cache_buf, psxM, sizeof(cache_buf));
156 psxRegs.CP0.n.Status = value;
157 lightrec_set_exit_flags(state, LIGHTREC_EXIT_CHECK_INTERRUPT);
160 psxRegs.CP0.n.Cause &= ~0x0300;
161 psxRegs.CP0.n.Cause |= value & 0x0300;
162 lightrec_set_exit_flags(state, LIGHTREC_EXIT_CHECK_INTERRUPT);
165 psxRegs.CP0.r[reg] = value;
170 static void cop2_mtc_ctc(struct lightrec_state *state,
171 u8 reg, u32 value, bool ctc)
179 static void cop0_mtc(struct lightrec_state *state, u8 reg, u32 value)
181 cop0_mtc_ctc(state, reg, value, false);
184 static void cop0_ctc(struct lightrec_state *state, u8 reg, u32 value)
186 cop0_mtc_ctc(state, reg, value, true);
189 static void cop2_mtc(struct lightrec_state *state, u8 reg, u32 value)
191 cop2_mtc_ctc(state, reg, value, false);
194 static void cop2_ctc(struct lightrec_state *state, u8 reg, u32 value)
196 cop2_mtc_ctc(state, reg, value, true);
199 static void cop0_op(struct lightrec_state *state, u32 func)
201 fprintf(stderr, "Invalid access to COP0\n");
204 static void cop2_op(struct lightrec_state *state, u32 func)
208 if (unlikely(!cp2_ops[func & 0x3f]))
209 fprintf(stderr, "Invalid CP2 function %u\n", func);
211 cp2_ops[func & 0x3f](&psxRegs.CP2);
214 static void hw_write_byte(struct lightrec_state *state, u32 mem, u8 val)
216 psxRegs.cycle = lightrec_current_cycle_count(state);
218 psxHwWrite8(mem, val);
219 lightrec_set_exit_flags(state, LIGHTREC_EXIT_CHECK_INTERRUPT);
221 lightrec_reset_cycle_count(state, psxRegs.cycle);
224 static void hw_write_half(struct lightrec_state *state, u32 mem, u16 val)
226 psxRegs.cycle = lightrec_current_cycle_count(state);
228 psxHwWrite16(mem, val);
229 lightrec_set_exit_flags(state, LIGHTREC_EXIT_CHECK_INTERRUPT);
231 lightrec_reset_cycle_count(state, psxRegs.cycle);
234 static void hw_write_word(struct lightrec_state *state, u32 mem, u32 val)
236 psxRegs.cycle = lightrec_current_cycle_count(state);
238 psxHwWrite32(mem, val);
239 lightrec_set_exit_flags(state, LIGHTREC_EXIT_CHECK_INTERRUPT);
241 lightrec_reset_cycle_count(state, psxRegs.cycle);
244 static u8 hw_read_byte(struct lightrec_state *state, u32 mem)
248 psxRegs.cycle = lightrec_current_cycle_count(state);
250 lightrec_set_exit_flags(state, LIGHTREC_EXIT_CHECK_INTERRUPT);
251 val = psxHwRead8(mem);
252 lightrec_reset_cycle_count(state, psxRegs.cycle);
257 static u16 hw_read_half(struct lightrec_state *state, u32 mem)
261 psxRegs.cycle = lightrec_current_cycle_count(state);
263 lightrec_set_exit_flags(state, LIGHTREC_EXIT_CHECK_INTERRUPT);
264 val = psxHwRead16(mem);
265 lightrec_reset_cycle_count(state, psxRegs.cycle);
270 static u32 hw_read_word(struct lightrec_state *state, u32 mem)
274 psxRegs.cycle = lightrec_current_cycle_count(state);
276 lightrec_set_exit_flags(state, LIGHTREC_EXIT_CHECK_INTERRUPT);
277 val = psxHwRead32(mem);
278 lightrec_reset_cycle_count(state, psxRegs.cycle);
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, u32 mem, u32 val)
299 static u32 cache_ctrl_read_word(struct lightrec_state *state, u32 mem)
304 static struct lightrec_mem_map_ops cache_ctrl_ops = {
305 .sw = cache_ctrl_write_word,
306 .lw = cache_ctrl_read_word,
309 static struct lightrec_mem_map lightrec_map[] = {
310 [PSX_MAP_KERNEL_USER_RAM] = {
311 /* Kernel and user memory */
320 [PSX_MAP_SCRATCH_PAD] = {
325 [PSX_MAP_PARALLEL_PORT] = {
330 [PSX_MAP_HW_REGISTERS] = {
331 /* Hardware registers */
336 [PSX_MAP_CACHE_CONTROL] = {
340 .ops = &cache_ctrl_ops,
343 /* Mirrors of the kernel/user memory */
344 [PSX_MAP_MIRROR1] = {
347 .mirror_of = &lightrec_map[PSX_MAP_KERNEL_USER_RAM],
349 [PSX_MAP_MIRROR2] = {
352 .mirror_of = &lightrec_map[PSX_MAP_KERNEL_USER_RAM],
354 [PSX_MAP_MIRROR3] = {
357 .mirror_of = &lightrec_map[PSX_MAP_KERNEL_USER_RAM],
361 static const struct lightrec_ops lightrec_ops = {
378 static int lightrec_plugin_init(void)
380 lightrec_map[PSX_MAP_KERNEL_USER_RAM].address = psxM;
381 lightrec_map[PSX_MAP_BIOS].address = psxR;
382 lightrec_map[PSX_MAP_SCRATCH_PAD].address = psxH;
383 lightrec_map[PSX_MAP_PARALLEL_PORT].address = psxP;
385 lightrec_debug = !!getenv("LIGHTREC_DEBUG");
386 lightrec_very_debug = !!getenv("LIGHTREC_VERY_DEBUG");
387 use_lightrec_interpreter = !!getenv("LIGHTREC_INTERPRETER");
388 if (getenv("LIGHTREC_BEGIN_CYCLES"))
389 lightrec_begin_cycles = (unsigned int) strtol(
390 getenv("LIGHTREC_BEGIN_CYCLES"), NULL, 0);
392 lightrec_state = lightrec_init(name,
393 lightrec_map, ARRAY_SIZE(lightrec_map),
396 fprintf(stderr, "M=0x%lx, P=0x%lx, R=0x%lx, H=0x%lx\n",
403 signal(SIGPIPE, exit);
408 static u32 hash_calculate_le(const void *buffer, u32 count)
411 u32 *data = (u32 *) buffer;
412 u32 hash = 0xffffffff;
415 for(i = 0; i < count; ++i) {
416 hash += LE32TOH(data[i]);
417 hash += (hash << 10);
422 hash ^= (hash >> 11);
423 hash += (hash << 15);
427 static u32 hash_calculate(const void *buffer, u32 count)
430 u32 *data = (u32 *) buffer;
431 u32 hash = 0xffffffff;
434 for(i = 0; i < count; ++i) {
436 hash += (hash << 10);
441 hash ^= (hash >> 11);
442 hash += (hash << 15);
446 static const char * const mips_regs[] = {
450 "a0", "a1", "a2", "a3",
451 "t0", "t1", "t2", "t3", "t4", "t5", "t6", "t7",
452 "s0", "s1", "s2", "s3", "s4", "s5", "s6", "s7",
455 "gp", "sp", "fp", "ra",
459 static void print_for_big_ass_debugger(void)
463 printf("CYCLE 0x%08x PC 0x%08x", psxRegs.cycle, psxRegs.pc);
465 if (lightrec_very_debug)
466 printf(" RAM 0x%08x SCRATCH 0x%08x HW 0x%08x",
467 hash_calculate_le(psxM, 0x200000),
468 hash_calculate_le(psxH, 0x400),
469 hash_calculate_le(psxH + 0x1000, 0x2000));
471 printf(" CP0 0x%08x CP2D 0x%08x CP2C 0x%08x INT 0x%04x INTCYCLE 0x%08x GPU 0x%08x",
472 hash_calculate(&psxRegs.CP0.r,
473 sizeof(psxRegs.CP0.r)),
474 hash_calculate(&psxRegs.CP2D.r,
475 sizeof(psxRegs.CP2D.r)),
476 hash_calculate(&psxRegs.CP2C.r,
477 sizeof(psxRegs.CP2C.r)),
479 hash_calculate(psxRegs.intCycle,
480 sizeof(psxRegs.intCycle)),
481 LE32TOH(HW_GPU_STATUS));
483 if (lightrec_very_debug)
484 for (i = 0; i < 34; i++)
485 printf(" %s 0x%08x", mips_regs[i], psxRegs.GPR.r[i]);
487 printf(" GPR 0x%08x", hash_calculate(&psxRegs.GPR.r,
488 sizeof(psxRegs.GPR.r)));
492 static u32 old_cycle_counter;
494 static void lightrec_plugin_execute_block(void)
496 u32 old_pc = psxRegs.pc;
499 lightrec_reset_cycle_count(lightrec_state, psxRegs.cycle);
500 lightrec_restore_registers(lightrec_state, psxRegs.GPR.r);
502 if (use_lightrec_interpreter)
503 psxRegs.pc = lightrec_run_interpreter(lightrec_state, psxRegs.pc);
505 psxRegs.pc = lightrec_execute_one(lightrec_state, psxRegs.pc);
507 psxRegs.cycle = lightrec_current_cycle_count(lightrec_state);
509 lightrec_dump_registers(lightrec_state, psxRegs.GPR.r);
510 flags = lightrec_exit_flags(lightrec_state);
512 if (flags & LIGHTREC_EXIT_SEGFAULT) {
513 fprintf(stderr, "Exiting at cycle 0x%08x\n",
518 if (flags & LIGHTREC_EXIT_SYSCALL)
519 psxException(0x20, 0);
523 if (lightrec_debug && psxRegs.cycle >= lightrec_begin_cycles
524 && psxRegs.pc != old_pc)
525 print_for_big_ass_debugger();
527 if ((psxRegs.CP0.n.Cause & psxRegs.CP0.n.Status & 0x300) &&
528 (psxRegs.CP0.n.Status & 0x1)) {
529 /* Handle software interrupts */
530 psxRegs.CP0.n.Cause &= ~0x7c;
531 psxException(psxRegs.CP0.n.Cause, 0);
534 if ((psxRegs.cycle & ~0xfffffff) != old_cycle_counter) {
535 printf("RAM usage: IR %u KiB, CODE %u KiB, "
536 "MIPS %u KiB, TOTAL %u KiB, avg. IPI %f\n",
537 lightrec_get_mem_usage(MEM_FOR_IR) / 1024,
538 lightrec_get_mem_usage(MEM_FOR_CODE) / 1024,
539 lightrec_get_mem_usage(MEM_FOR_MIPS_CODE) / 1024,
540 lightrec_get_total_mem_usage() / 1024,
541 lightrec_get_average_ipi());
542 old_cycle_counter = psxRegs.cycle & ~0xfffffff;
546 static void lightrec_plugin_execute(void)
551 lightrec_plugin_execute_block();
554 static void lightrec_plugin_clear(u32 addr, u32 size)
556 /* size * 4: PCSX uses DMA units */
557 lightrec_invalidate(lightrec_state, addr, size * 4);
560 static void lightrec_plugin_shutdown(void)
562 lightrec_destroy(lightrec_state);
565 static void lightrec_plugin_reset(void)
567 lightrec_plugin_shutdown();
568 lightrec_plugin_init();
573 lightrec_plugin_init,
574 lightrec_plugin_reset,
575 lightrec_plugin_execute,
576 lightrec_plugin_execute_block,
577 lightrec_plugin_clear,
578 lightrec_plugin_shutdown,