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