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