9e3c0c7482db5c0c0061154b971699046b04d5ac
[pcsx_rearmed.git] / libpcsxcore / lightrec / plugin.c
1 #include <lightrec.h>
2 #include <stdbool.h>
3 #include <stdio.h>
4 #include <unistd.h>
5 #include <signal.h>
6
7 #include "../cdrom.h"
8 #include "../gpu.h"
9 #include "../gte.h"
10 #include "../mdec.h"
11 #include "../psxdma.h"
12 #include "../psxhw.h"
13 #include "../psxmem.h"
14 #include "../r3000a.h"
15
16 #include "../frontend/main.h"
17
18 #define ARRAY_SIZE(x) (sizeof(x) ? sizeof(x) / sizeof((x)[0]) : 0)
19
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)
25 #else
26 #       define LE32TOH(x)       (x)
27 #       define HTOLE32(x)       (x)
28 #       define LE16TOH(x)       (x)
29 #       define HTOLE16(x)       (x)
30 #endif
31
32 #ifdef __GNUC__
33 #       define likely(x)       __builtin_expect(!!(x),1)
34 #       define unlikely(x)     __builtin_expect(!!(x),0)
35 #else
36 #       define likely(x)       (x)
37 #       define unlikely(x)     (x)
38 #endif
39
40 static struct lightrec_state *lightrec_state;
41
42 static char *name = "retroarch.exe";
43
44 static bool use_lightrec_interpreter;
45 static bool use_pcsx_interpreter;
46 static bool lightrec_debug;
47 static bool lightrec_very_debug;
48 static u32 lightrec_begin_cycles;
49
50 int stop;
51 u32 cycle_multiplier;
52 int new_dynarec_hacks;
53
54 /* Unused for now */
55 u32 event_cycles[PSXINT_COUNT];
56 u32 next_interupt;
57
58 void new_dyna_before_save() {}
59 void new_dyna_after_save() {}
60 void new_dyna_freeze(void *f, int i) {}
61
62 enum my_cp2_opcodes {
63         OP_CP2_RTPS             = 0x01,
64         OP_CP2_NCLIP            = 0x06,
65         OP_CP2_OP               = 0x0c,
66         OP_CP2_DPCS             = 0x10,
67         OP_CP2_INTPL            = 0x11,
68         OP_CP2_MVMVA            = 0x12,
69         OP_CP2_NCDS             = 0x13,
70         OP_CP2_CDP              = 0x14,
71         OP_CP2_NCDT             = 0x16,
72         OP_CP2_NCCS             = 0x1b,
73         OP_CP2_CC               = 0x1c,
74         OP_CP2_NCS              = 0x1e,
75         OP_CP2_NCT              = 0x20,
76         OP_CP2_SQR              = 0x28,
77         OP_CP2_DCPL             = 0x29,
78         OP_CP2_DPCT             = 0x2a,
79         OP_CP2_AVSZ3            = 0x2d,
80         OP_CP2_AVSZ4            = 0x2e,
81         OP_CP2_RTPT             = 0x30,
82         OP_CP2_GPF              = 0x3d,
83         OP_CP2_GPL              = 0x3e,
84         OP_CP2_NCCT             = 0x3f,
85 };
86
87 static void (*cp2_ops[])(struct psxCP2Regs *) = {
88         [OP_CP2_RTPS] = gteRTPS,
89         [OP_CP2_RTPS] = gteRTPS,
90         [OP_CP2_NCLIP] = gteNCLIP,
91         [OP_CP2_OP] = gteOP,
92         [OP_CP2_DPCS] = gteDPCS,
93         [OP_CP2_INTPL] = gteINTPL,
94         [OP_CP2_MVMVA] = gteMVMVA,
95         [OP_CP2_NCDS] = gteNCDS,
96         [OP_CP2_CDP] = gteCDP,
97         [OP_CP2_NCDT] = gteNCDT,
98         [OP_CP2_NCCS] = gteNCCS,
99         [OP_CP2_CC] = gteCC,
100         [OP_CP2_NCS] = gteNCS,
101         [OP_CP2_NCT] = gteNCT,
102         [OP_CP2_SQR] = gteSQR,
103         [OP_CP2_DCPL] = gteDCPL,
104         [OP_CP2_DPCT] = gteDPCT,
105         [OP_CP2_AVSZ3] = gteAVSZ3,
106         [OP_CP2_AVSZ4] = gteAVSZ4,
107         [OP_CP2_RTPT] = gteRTPT,
108         [OP_CP2_GPF] = gteGPF,
109         [OP_CP2_GPL] = gteGPL,
110         [OP_CP2_NCCT] = gteNCCT,
111 };
112
113 static char cache_buf[64 * 1024];
114
115 static u32 cop0_mfc(struct lightrec_state *state, u32 op, u8 reg)
116 {
117         return psxRegs.CP0.r[reg];
118 }
119
120 static u32 cop2_mfc_cfc(struct lightrec_state *state, u8 reg, bool cfc)
121 {
122         if (cfc)
123                 return psxRegs.CP2C.r[reg];
124         else
125                 return MFC2(reg);
126 }
127
128 static u32 cop2_mfc(struct lightrec_state *state, u32 op, u8 reg)
129 {
130         return cop2_mfc_cfc(state, reg, false);
131 }
132
133 static u32 cop2_cfc(struct lightrec_state *state, u32 op, u8 reg)
134 {
135         return cop2_mfc_cfc(state, reg, true);
136 }
137
138 static void cop0_mtc_ctc(struct lightrec_state *state,
139                          u8 reg, u32 value, bool ctc)
140 {
141         switch (reg) {
142         case 1:
143         case 4:
144         case 8:
145         case 14:
146         case 15:
147                 /* Those registers are read-only */
148                 break;
149         case 12: /* Status */
150                 if ((psxRegs.CP0.n.Status & ~value) & (1 << 16)) {
151                         memcpy(psxM, cache_buf, sizeof(cache_buf));
152                         lightrec_invalidate_all(state);
153                 } else if ((~psxRegs.CP0.n.Status & value) & (1 << 16)) {
154                         memcpy(cache_buf, psxM, sizeof(cache_buf));
155                 }
156
157                 psxRegs.CP0.n.Status = value;
158                 lightrec_set_exit_flags(state, LIGHTREC_EXIT_CHECK_INTERRUPT);
159                 break;
160         case 13: /* Cause */
161                 psxRegs.CP0.n.Cause &= ~0x0300;
162                 psxRegs.CP0.n.Cause |= value & 0x0300;
163                 lightrec_set_exit_flags(state, LIGHTREC_EXIT_CHECK_INTERRUPT);
164                 break;
165         default:
166                 psxRegs.CP0.r[reg] = value;
167                 break;
168         }
169 }
170
171 static void cop2_mtc_ctc(struct lightrec_state *state,
172                          u8 reg, u32 value, bool ctc)
173 {
174         if (ctc)
175                 CTC2(value, reg);
176         else
177                 MTC2(value, reg);
178 }
179
180 static void cop0_mtc(struct lightrec_state *state, u32 op, u8 reg, u32 value)
181 {
182         cop0_mtc_ctc(state, reg, value, false);
183 }
184
185 static void cop0_ctc(struct lightrec_state *state, u32 op, u8 reg, u32 value)
186 {
187         cop0_mtc_ctc(state, reg, value, true);
188 }
189
190 static void cop2_mtc(struct lightrec_state *state, u32 op, u8 reg, u32 value)
191 {
192         cop2_mtc_ctc(state, reg, value, false);
193 }
194
195 static void cop2_ctc(struct lightrec_state *state, u32 op, u8 reg, u32 value)
196 {
197         cop2_mtc_ctc(state, reg, value, true);
198 }
199
200 static void cop0_op(struct lightrec_state *state, u32 func)
201 {
202         fprintf(stderr, "Invalid access to COP0\n");
203 }
204
205 static void cop2_op(struct lightrec_state *state, u32 func)
206 {
207         psxRegs.code = func;
208
209         if (unlikely(!cp2_ops[func & 0x3f]))
210                 fprintf(stderr, "Invalid CP2 function %u\n", func);
211         else
212                 cp2_ops[func & 0x3f](&psxRegs.CP2);
213 }
214
215 static void hw_write_byte(struct lightrec_state *state,
216                           u32 op, void *host, u32 mem, u8 val)
217 {
218         psxRegs.cycle = lightrec_current_cycle_count(state);
219
220         psxHwWrite8(mem, val);
221         lightrec_set_exit_flags(state, LIGHTREC_EXIT_CHECK_INTERRUPT);
222
223         lightrec_reset_cycle_count(state, psxRegs.cycle);
224 }
225
226 static void hw_write_half(struct lightrec_state *state,
227                           u32 op, void *host, u32 mem, u16 val)
228 {
229         psxRegs.cycle = lightrec_current_cycle_count(state);
230
231         psxHwWrite16(mem, val);
232         lightrec_set_exit_flags(state, LIGHTREC_EXIT_CHECK_INTERRUPT);
233
234         lightrec_reset_cycle_count(state, psxRegs.cycle);
235 }
236
237 static void hw_write_word(struct lightrec_state *state,
238                           u32 op, void *host, u32 mem, u32 val)
239 {
240         psxRegs.cycle = lightrec_current_cycle_count(state);
241
242         psxHwWrite32(mem, val);
243         lightrec_set_exit_flags(state, LIGHTREC_EXIT_CHECK_INTERRUPT);
244
245         lightrec_reset_cycle_count(state, psxRegs.cycle);
246 }
247
248 static u8 hw_read_byte(struct lightrec_state *state, u32 op, void *host, u32 mem)
249 {
250         u8 val;
251
252         psxRegs.cycle = lightrec_current_cycle_count(state);
253
254         lightrec_set_exit_flags(state, LIGHTREC_EXIT_CHECK_INTERRUPT);
255         val = psxHwRead8(mem);
256         lightrec_reset_cycle_count(state, psxRegs.cycle);
257
258         return val;
259 }
260
261 static u16 hw_read_half(struct lightrec_state *state,
262                         u32 op, void *host, u32 mem)
263 {
264         u16 val;
265
266         psxRegs.cycle = lightrec_current_cycle_count(state);
267
268         lightrec_set_exit_flags(state, LIGHTREC_EXIT_CHECK_INTERRUPT);
269         val = psxHwRead16(mem);
270         lightrec_reset_cycle_count(state, psxRegs.cycle);
271
272         return val;
273 }
274
275 static u32 hw_read_word(struct lightrec_state *state,
276                         u32 op, void *host, u32 mem)
277 {
278         u32 val;
279
280         psxRegs.cycle = lightrec_current_cycle_count(state);
281
282         lightrec_set_exit_flags(state, LIGHTREC_EXIT_CHECK_INTERRUPT);
283         val = psxHwRead32(mem);
284         lightrec_reset_cycle_count(state, psxRegs.cycle);
285
286         return val;
287 }
288
289 static struct lightrec_mem_map_ops hw_regs_ops = {
290         .sb = hw_write_byte,
291         .sh = hw_write_half,
292         .sw = hw_write_word,
293         .lb = hw_read_byte,
294         .lh = hw_read_half,
295         .lw = hw_read_word,
296 };
297
298 static u32 cache_ctrl;
299
300 static void cache_ctrl_write_word(struct lightrec_state *state,
301                                   u32 op, void *host, u32 mem, u32 val)
302 {
303         cache_ctrl = val;
304 }
305
306 static u32 cache_ctrl_read_word(struct lightrec_state *state,
307                                 u32 op, void *host, u32 mem)
308 {
309         return cache_ctrl;
310 }
311
312 static struct lightrec_mem_map_ops cache_ctrl_ops = {
313         .sw = cache_ctrl_write_word,
314         .lw = cache_ctrl_read_word,
315 };
316
317 static struct lightrec_mem_map lightrec_map[] = {
318         [PSX_MAP_KERNEL_USER_RAM] = {
319                 /* Kernel and user memory */
320                 .pc = 0x00000000,
321                 .length = 0x200000,
322         },
323         [PSX_MAP_BIOS] = {
324                 /* BIOS */
325                 .pc = 0x1fc00000,
326                 .length = 0x80000,
327         },
328         [PSX_MAP_SCRATCH_PAD] = {
329                 /* Scratch pad */
330                 .pc = 0x1f800000,
331                 .length = 0x400,
332         },
333         [PSX_MAP_PARALLEL_PORT] = {
334                 /* Parallel port */
335                 .pc = 0x1f000000,
336                 .length = 0x10000,
337         },
338         [PSX_MAP_HW_REGISTERS] = {
339                 /* Hardware registers */
340                 .pc = 0x1f801000,
341                 .length = 0x2000,
342                 .ops = &hw_regs_ops,
343         },
344         [PSX_MAP_CACHE_CONTROL] = {
345                 /* Cache control */
346                 .pc = 0x5ffe0130,
347                 .length = 4,
348                 .ops = &cache_ctrl_ops,
349         },
350
351         /* Mirrors of the kernel/user memory */
352         [PSX_MAP_MIRROR1] = {
353                 .pc = 0x00200000,
354                 .length = 0x200000,
355                 .mirror_of = &lightrec_map[PSX_MAP_KERNEL_USER_RAM],
356         },
357         [PSX_MAP_MIRROR2] = {
358                 .pc = 0x00400000,
359                 .length = 0x200000,
360                 .mirror_of = &lightrec_map[PSX_MAP_KERNEL_USER_RAM],
361         },
362         [PSX_MAP_MIRROR3] = {
363                 .pc = 0x00600000,
364                 .length = 0x200000,
365                 .mirror_of = &lightrec_map[PSX_MAP_KERNEL_USER_RAM],
366         },
367 };
368
369 static const struct lightrec_ops lightrec_ops = {
370         .cop0_ops = {
371                 .mfc = cop0_mfc,
372                 .cfc = cop0_mfc,
373                 .mtc = cop0_mtc,
374                 .ctc = cop0_ctc,
375                 .op = cop0_op,
376         },
377         .cop2_ops = {
378                 .mfc = cop2_mfc,
379                 .cfc = cop2_cfc,
380                 .mtc = cop2_mtc,
381                 .ctc = cop2_ctc,
382                 .op = cop2_op,
383         },
384 };
385
386 static int lightrec_plugin_init(void)
387 {
388         lightrec_map[PSX_MAP_KERNEL_USER_RAM].address = psxM;
389         lightrec_map[PSX_MAP_BIOS].address = psxR;
390         lightrec_map[PSX_MAP_SCRATCH_PAD].address = psxH;
391         lightrec_map[PSX_MAP_PARALLEL_PORT].address = psxP;
392
393         lightrec_debug = !!getenv("LIGHTREC_DEBUG");
394         lightrec_very_debug = !!getenv("LIGHTREC_VERY_DEBUG");
395         use_lightrec_interpreter = !!getenv("LIGHTREC_INTERPRETER");
396         if (getenv("LIGHTREC_BEGIN_CYCLES"))
397           lightrec_begin_cycles = (unsigned int) strtol(
398                                   getenv("LIGHTREC_BEGIN_CYCLES"), NULL, 0);
399
400         lightrec_state = lightrec_init(name,
401                         lightrec_map, ARRAY_SIZE(lightrec_map),
402                         &lightrec_ops);
403
404         fprintf(stderr, "M=0x%lx, P=0x%lx, R=0x%lx, H=0x%lx\n",
405                         (uintptr_t) psxM,
406                         (uintptr_t) psxP,
407                         (uintptr_t) psxR,
408                         (uintptr_t) psxH);
409
410 #ifndef _WIN32
411         signal(SIGPIPE, exit);
412 #endif
413         return 0;
414 }
415
416 static u32 hash_calculate_le(const void *buffer, u32 count)
417 {
418         unsigned int i;
419         u32 *data = (u32 *) buffer;
420         u32 hash = 0xffffffff;
421
422         count /= 4;
423         for(i = 0; i < count; ++i) {
424                 hash += LE32TOH(data[i]);
425                 hash += (hash << 10);
426                 hash ^= (hash >> 6);
427         }
428
429         hash += (hash << 3);
430         hash ^= (hash >> 11);
431         hash += (hash << 15);
432         return hash;
433 }
434
435 static u32 hash_calculate(const void *buffer, u32 count)
436 {
437         unsigned int i;
438         u32 *data = (u32 *) buffer;
439         u32 hash = 0xffffffff;
440
441         count /= 4;
442         for(i = 0; i < count; ++i) {
443                 hash += data[i];
444                 hash += (hash << 10);
445                 hash ^= (hash >> 6);
446         }
447
448         hash += (hash << 3);
449         hash ^= (hash >> 11);
450         hash += (hash << 15);
451         return hash;
452 }
453
454 static const char * const mips_regs[] = {
455         "zero",
456         "at",
457         "v0", "v1",
458         "a0", "a1", "a2", "a3",
459         "t0", "t1", "t2", "t3", "t4", "t5", "t6", "t7",
460         "s0", "s1", "s2", "s3", "s4", "s5", "s6", "s7",
461         "t8", "t9",
462         "k0", "k1",
463         "gp", "sp", "fp", "ra",
464         "lo", "hi",
465 };
466
467 static void print_for_big_ass_debugger(void)
468 {
469         unsigned int i;
470
471         printf("CYCLE 0x%08x PC 0x%08x", psxRegs.cycle, psxRegs.pc);
472
473         if (lightrec_very_debug)
474                 printf(" RAM 0x%08x SCRATCH 0x%08x HW 0x%08x",
475                                 hash_calculate_le(psxM, 0x200000),
476                                 hash_calculate_le(psxH, 0x400),
477                                 hash_calculate_le(psxH + 0x1000, 0x2000));
478
479         printf(" CP0 0x%08x CP2D 0x%08x CP2C 0x%08x INT 0x%04x INTCYCLE 0x%08x GPU 0x%08x",
480                         hash_calculate(&psxRegs.CP0.r,
481                                 sizeof(psxRegs.CP0.r)),
482                         hash_calculate(&psxRegs.CP2D.r,
483                                 sizeof(psxRegs.CP2D.r)),
484                         hash_calculate(&psxRegs.CP2C.r,
485                                 sizeof(psxRegs.CP2C.r)),
486                         psxRegs.interrupt,
487                         hash_calculate(psxRegs.intCycle,
488                                 sizeof(psxRegs.intCycle)),
489                         LE32TOH(HW_GPU_STATUS));
490
491         if (lightrec_very_debug)
492                 for (i = 0; i < 34; i++)
493                         printf(" %s 0x%08x", mips_regs[i], psxRegs.GPR.r[i]);
494         else
495                 printf(" GPR 0x%08x", hash_calculate(&psxRegs.GPR.r,
496                                         sizeof(psxRegs.GPR.r)));
497         printf("\n");
498 }
499
500
501 extern void intExecuteBlock();
502
503 static u32 old_cycle_counter;
504
505 static void lightrec_plugin_execute_block(void)
506 {
507         u32 old_pc = psxRegs.pc;
508         u32 flags;
509
510         if (use_pcsx_interpreter) {
511                 intExecuteBlock();
512         } else {
513                 lightrec_reset_cycle_count(lightrec_state, psxRegs.cycle);
514                 lightrec_restore_registers(lightrec_state, psxRegs.GPR.r);
515
516                 if (use_lightrec_interpreter)
517                         psxRegs.pc = lightrec_run_interpreter(lightrec_state,
518                                                               psxRegs.pc);
519                 else
520                         psxRegs.pc = lightrec_execute_one(lightrec_state,
521                                                           psxRegs.pc);
522
523                 psxRegs.cycle = lightrec_current_cycle_count(lightrec_state);
524
525                 lightrec_dump_registers(lightrec_state, psxRegs.GPR.r);
526                 flags = lightrec_exit_flags(lightrec_state);
527
528                 if (flags & LIGHTREC_EXIT_SEGFAULT) {
529                         fprintf(stderr, "Exiting at cycle 0x%08x\n",
530                                 psxRegs.cycle);
531                         exit(1);
532                 }
533
534                 if (flags & LIGHTREC_EXIT_SYSCALL)
535                         psxException(0x20, 0);
536         }
537
538         psxBranchTest();
539
540         if (lightrec_debug && psxRegs.cycle >= lightrec_begin_cycles
541                         && psxRegs.pc != old_pc)
542                 print_for_big_ass_debugger();
543
544         if ((psxRegs.CP0.n.Cause & psxRegs.CP0.n.Status & 0x300) &&
545                         (psxRegs.CP0.n.Status & 0x1)) {
546                 /* Handle software interrupts */
547                 psxRegs.CP0.n.Cause &= ~0x7c;
548                 psxException(psxRegs.CP0.n.Cause, 0);
549         }
550
551         if ((psxRegs.cycle & ~0xfffffff) != old_cycle_counter) {
552                 SysDLog("RAM usage: Lightrec %u KiB, IR %u KiB, CODE %u KiB, "
553                        "MIPS %u KiB, TOTAL %u KiB, avg. IPI %f\n",
554                        lightrec_get_mem_usage(MEM_FOR_LIGHTREC) / 1024,
555                        lightrec_get_mem_usage(MEM_FOR_IR) / 1024,
556                        lightrec_get_mem_usage(MEM_FOR_CODE) / 1024,
557                        lightrec_get_mem_usage(MEM_FOR_MIPS_CODE) / 1024,
558                        lightrec_get_total_mem_usage() / 1024,
559                        lightrec_get_average_ipi());
560                 old_cycle_counter = psxRegs.cycle & ~0xfffffff;
561         }
562 }
563
564 static void lightrec_plugin_execute(void)
565 {
566         extern int stop;
567
568         while (!stop)
569                 lightrec_plugin_execute_block();
570 }
571
572 static void lightrec_plugin_clear(u32 addr, u32 size)
573 {
574         if (addr == 0 && size == UINT32_MAX)
575                 lightrec_invalidate_all(lightrec_state);
576         else
577                 /* size * 4: PCSX uses DMA units */
578                 lightrec_invalidate(lightrec_state, addr, size * 4);
579 }
580
581 static void lightrec_plugin_shutdown(void)
582 {
583         lightrec_destroy(lightrec_state);
584 }
585
586 static void lightrec_plugin_reset(void)
587 {
588         lightrec_plugin_shutdown();
589         lightrec_plugin_init();
590 }
591
592 R3000Acpu psxRec =
593 {
594         lightrec_plugin_init,
595         lightrec_plugin_reset,
596         lightrec_plugin_execute,
597         lightrec_plugin_execute_block,
598         lightrec_plugin_clear,
599         lightrec_plugin_shutdown,
600 };