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