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