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