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