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