Revert "Use a more lightweight reset method for lightrec"
[pcsx_rearmed.git] / libpcsxcore / lightrec / plugin.c
CommitLineData
6f1edc3c
PC
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
40static struct lightrec_state *lightrec_state;
41
42static char *name = "retroarch.exe";
43
44static bool use_lightrec_interpreter;
45static bool lightrec_debug;
46static bool lightrec_very_debug;
47static u32 lightrec_begin_cycles;
48
49int stop;
50u32 cycle_multiplier;
51int new_dynarec_hacks;
52
53/* Unused for now */
54u32 event_cycles[PSXINT_COUNT];
55u32 next_interupt;
56
57void new_dyna_before_save() {}
58void new_dyna_after_save() {}
59void new_dyna_freeze(void *f, int i) {}
60
61enum 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
86static 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
112static char cache_buf[64 * 1024];
113
114static u32 cop0_mfc(struct lightrec_state *state, u8 reg)
115{
116 return psxRegs.CP0.r[reg];
117}
118
119static 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
127static u32 cop2_mfc(struct lightrec_state *state, u8 reg)
128{
129 return cop2_mfc_cfc(state, reg, false);
130}
131
132static u32 cop2_cfc(struct lightrec_state *state, u8 reg)
133{
134 return cop2_mfc_cfc(state, reg, true);
135}
136
137static 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
170static 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
179static void cop0_mtc(struct lightrec_state *state, u8 reg, u32 value)
180{
181 cop0_mtc_ctc(state, reg, value, false);
182}
183
184static void cop0_ctc(struct lightrec_state *state, u8 reg, u32 value)
185{
186 cop0_mtc_ctc(state, reg, value, true);
187}
188
189static void cop2_mtc(struct lightrec_state *state, u8 reg, u32 value)
190{
191 cop2_mtc_ctc(state, reg, value, false);
192}
193
194static void cop2_ctc(struct lightrec_state *state, u8 reg, u32 value)
195{
196 cop2_mtc_ctc(state, reg, value, true);
197}
198
199static void cop0_op(struct lightrec_state *state, u32 func)
200{
201 fprintf(stderr, "Invalid access to COP0\n");
202}
203
204static 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
214static 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
224static 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
234static 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
244static 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
257static 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
270static 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
283static 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
292static u32 cache_ctrl;
293
294static void cache_ctrl_write_word(struct lightrec_state *state, u32 mem, u32 val)
295{
296 cache_ctrl = val;
297}
298
299static u32 cache_ctrl_read_word(struct lightrec_state *state, u32 mem)
300{
301 return cache_ctrl;
302}
303
304static struct lightrec_mem_map_ops cache_ctrl_ops = {
305 .sw = cache_ctrl_write_word,
306 .lw = cache_ctrl_read_word,
307};
308
309static 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
361static 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
378static 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
408static 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
427static 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
446static 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
459static 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
492static u32 old_cycle_counter;
493
494static 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
546static void lightrec_plugin_execute(void)
547{
548 extern int stop;
549
550 while (!stop)
551 lightrec_plugin_execute_block();
552}
553
554static void lightrec_plugin_clear(u32 addr, u32 size)
555{
556 /* size * 4: PCSX uses DMA units */
557 lightrec_invalidate(lightrec_state, addr, size * 4);
558}
559
560static void lightrec_plugin_shutdown(void)
561{
562 lightrec_destroy(lightrec_state);
563}
564
565static void lightrec_plugin_reset(void)
566{
37e4b2cc 567 lightrec_plugin_shutdown();
568 lightrec_plugin_init();
6f1edc3c
PC
569}
570
571R3000Acpu psxRec =
572{
573 lightrec_plugin_init,
574 lightrec_plugin_reset,
575 lightrec_plugin_execute,
576 lightrec_plugin_execute_block,
577 lightrec_plugin_clear,
578 lightrec_plugin_shutdown,
579};