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