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