drc: handle regs-not-in-psxRegs case better
authornotaz <notasas@gmail.com>
Sun, 9 Jul 2023 22:50:00 +0000 (01:50 +0300)
committernotaz <notasas@gmail.com>
Sun, 9 Jul 2023 23:12:00 +0000 (02:12 +0300)
for lightrec

13 files changed:
Makefile
libpcsxcore/misc.c
libpcsxcore/new_dynarec/emu_if.c
libpcsxcore/new_dynarec/emu_if.h
libpcsxcore/new_dynarec/events.c [new file with mode: 0644]
libpcsxcore/new_dynarec/events.h [new file with mode: 0644]
libpcsxcore/new_dynarec/linkage_arm.S
libpcsxcore/new_dynarec/linkage_arm64.S
libpcsxcore/new_dynarec/new_dynarec.c
libpcsxcore/plugins.h
libpcsxcore/psxinterpreter.c
libpcsxcore/r3000a.c
libpcsxcore/r3000a.h

index 585480d..ded2689 100644 (file)
--- a/Makefile
+++ b/Makefile
@@ -71,7 +71,7 @@ OBJS += libpcsxcore/new_dynarec/pcsxmem.o
 else
 CFLAGS += -DDRC_DISABLE
 endif
-OBJS += libpcsxcore/new_dynarec/emu_if.o
+OBJS += libpcsxcore/new_dynarec/emu_if.o libpcsxcore/new_dynarec/events.o
 libpcsxcore/new_dynarec/new_dynarec.o: libpcsxcore/new_dynarec/pcsxmem_inline.c
 ifdef DRC_DBG
 libpcsxcore/new_dynarec/emu_if.o: CFLAGS += -D_FILE_OFFSET_BITS=64
index d52a931..57d3959 100644 (file)
@@ -165,6 +165,18 @@ static void fake_bios_gpu_setup(void)
                GPU_writeData(gpu_data_def[i]);
 }
 
+static void SetBootRegs(u32 pc, u32 gp, u32 sp)
+{
+       //printf("%s %08x %08x %08x\n", __func__, pc, gp, sp);
+       psxCpu->Notify(R3000ACPU_NOTIFY_BEFORE_SAVE, NULL);
+
+       psxRegs.pc = pc;
+       psxRegs.GPR.n.gp = gp;
+       psxRegs.GPR.n.sp = sp ? sp : 0x801fff00;
+
+       psxCpu->Notify(R3000ACPU_NOTIFY_AFTER_LOAD, NULL);
+}
+
 int LoadCdrom() {
        EXE_HEADER tmpHead;
        struct iso_directory_record *dir;
@@ -178,6 +190,7 @@ int LoadCdrom() {
 
        if (!Config.HLE && !Config.SlowBoot) {
                // skip BIOS logos
+               psxCpu->Notify(R3000ACPU_NOTIFY_BEFORE_SAVE, NULL);
                psxRegs.pc = psxRegs.GPR.n.ra;
                return 0;
        }
@@ -230,10 +243,7 @@ int LoadCdrom() {
 
        memcpy(&tmpHead, buf + 12, sizeof(EXE_HEADER));
 
-       psxRegs.pc = SWAP32(tmpHead.pc0);
-       psxRegs.GPR.n.gp = SWAP32(tmpHead.gp0);
-       psxRegs.GPR.n.sp = SWAP32(tmpHead.s_addr);
-       if (psxRegs.GPR.n.sp == 0) psxRegs.GPR.n.sp = 0x801fff00;
+       SetBootRegs(SWAP32(tmpHead.pc0), SWAP32(tmpHead.gp0), SWAP32(tmpHead.s_addr));
 
        tmpHead.t_size = SWAP32(tmpHead.t_size);
        tmpHead.t_addr = SWAP32(tmpHead.t_addr);
@@ -488,11 +498,8 @@ int Load(const char *ExePath) {
                                        fread_to_ram(mem, section_size, 1, tmpFile);
                                        psxCpu->Clear(section_address, section_size / 4);
                                }
-                               psxRegs.pc = SWAP32(tmpHead.pc0);
-                               psxRegs.GPR.n.gp = SWAP32(tmpHead.gp0);
-                               psxRegs.GPR.n.sp = SWAP32(tmpHead.s_addr);
-                               if (psxRegs.GPR.n.sp == 0)
-                                       psxRegs.GPR.n.sp = 0x801fff00;
+                               SetBootRegs(SWAP32(tmpHead.pc0), SWAP32(tmpHead.gp0),
+                                       SWAP32(tmpHead.s_addr));
                                retval = 0;
                                break;
                        case CPE_EXE:
@@ -601,6 +608,7 @@ static const u32 SaveVersion = 0x8b410006;
 int SaveState(const char *file) {
        void *f;
        GPUFreeze_t *gpufP;
+       SPUFreezeHdr_t *spufH;
        SPUFreeze_t *spufP;
        int Size;
        unsigned char *pMem;
@@ -637,10 +645,10 @@ int SaveState(const char *file) {
        free(gpufP);
 
        // spu
-       spufP = (SPUFreeze_t *) malloc(16);
-       SPU_freeze(2, spufP, psxRegs.cycle);
-       Size = spufP->Size; SaveFuncs.write(f, &Size, 4);
-       free(spufP);
+       spufH = malloc(sizeof(*spufH));
+       SPU_freeze(2, (SPUFreeze_t *)spufH, psxRegs.cycle);
+       Size = spufH->Size; SaveFuncs.write(f, &Size, 4);
+       free(spufH);
        spufP = (SPUFreeze_t *) malloc(Size);
        SPU_freeze(1, spufP, psxRegs.cycle);
        SaveFuncs.write(f, spufP, Size);
index c1dab56..50819e4 100644 (file)
@@ -9,12 +9,10 @@
 
 #include "emu_if.h"
 #include "pcsxmem.h"
+#include "events.h"
 #include "../psxhle.h"
 #include "../psxinterpreter.h"
 #include "../r3000a.h"
-#include "../cdrom.h"
-#include "../psxdma.h"
-#include "../mdec.h"
 #include "../gte_arm.h"
 #include "../gte_neon.h"
 #define FLAGLESS
 //#define evprintf printf
 #define evprintf(...)
 
-char invalid_code[0x100000];
-u32 event_cycles[PSXINT_COUNT];
-
-static void schedule_timeslice(void)
-{
-       u32 i, c = psxRegs.cycle;
-       u32 irqs = psxRegs.interrupt;
-       s32 min, dif;
-
-       min = PSXCLK;
-       for (i = 0; irqs != 0; i++, irqs >>= 1) {
-               if (!(irqs & 1))
-                       continue;
-               dif = event_cycles[i] - c;
-               //evprintf("  ev %d\n", dif);
-               if (0 < dif && dif < min)
-                       min = dif;
-       }
-       next_interupt = c + min;
-}
-
-static void unusedInterrupt()
-{
-}
-
-typedef void (irq_func)();
-
-static irq_func * const irq_funcs[] = {
-       [PSXINT_SIO]    = sioInterrupt,
-       [PSXINT_CDR]    = cdrInterrupt,
-       [PSXINT_CDREAD] = cdrPlayReadInterrupt,
-       [PSXINT_GPUDMA] = gpuInterrupt,
-       [PSXINT_MDECOUTDMA] = mdec1Interrupt,
-       [PSXINT_SPUDMA] = spuInterrupt,
-       [PSXINT_MDECINDMA] = mdec0Interrupt,
-       [PSXINT_GPUOTCDMA] = gpuotcInterrupt,
-       [PSXINT_CDRDMA] = cdrDmaInterrupt,
-       [PSXINT_CDRLID] = cdrLidSeekInterrupt,
-       [PSXINT_CDRPLAY_OLD] = unusedInterrupt,
-       [PSXINT_SPU_UPDATE] = spuUpdate,
-       [PSXINT_RCNT] = psxRcntUpdate,
-};
-
-/* local dupe of psxBranchTest, using event_cycles */
-static void irq_test(void)
-{
-       u32 cycle = psxRegs.cycle;
-       u32 irq, irq_bits;
-
-       for (irq = 0, irq_bits = psxRegs.interrupt; irq_bits != 0; irq++, irq_bits >>= 1) {
-               if (!(irq_bits & 1))
-                       continue;
-               if ((s32)(cycle - event_cycles[irq]) >= 0) {
-                       // note: irq_funcs() also modify psxRegs.interrupt
-                       psxRegs.interrupt &= ~(1u << irq);
-                       irq_funcs[irq]();
-               }
-       }
-
-       if ((psxHu32(0x1070) & psxHu32(0x1074)) && (psxRegs.CP0.n.Status & 0x401) == 0x401) {
-               psxException(0x400, 0);
-               pending_exception = 1;
-       }
-}
-
-void gen_interupt()
-{
-       evprintf("  +ge %08x, %u->%u (%d)\n", psxRegs.pc, psxRegs.cycle,
-               next_interupt, next_interupt - psxRegs.cycle);
-
-       irq_test();
-       //psxBranchTest();
-       //pending_exception = 1;
-
-       schedule_timeslice();
-
-       evprintf("  -ge %08x, %u->%u (%d)\n", psxRegs.pc, psxRegs.cycle,
-               next_interupt, next_interupt - psxRegs.cycle);
-}
-
 void pcsx_mtc0(u32 reg, u32 val)
 {
        evprintf("MTC0 %d #%x @%08x %u\n", reg, val, psxRegs.pc, psxRegs.cycle);
        MTC0(&psxRegs, reg, val);
-       gen_interupt();
+       gen_interupt(&psxRegs.CP0);
        if (psxRegs.CP0.n.Cause & psxRegs.CP0.n.Status & 0x0300) // possible sw irq
                pending_exception = 1;
 }
index b49b84b..3f4aba6 100644 (file)
@@ -1,12 +1,6 @@
 #include "new_dynarec.h"
 #include "../r3000a.h"
 
-extern char invalid_code[0x100000];
-
-/* weird stuff */
-#define EAX 0
-#define ECX 1
-
 extern int dynarec_local[];
 
 /* same as psxRegs.GPR.n.* */
diff --git a/libpcsxcore/new_dynarec/events.c b/libpcsxcore/new_dynarec/events.c
new file mode 100644 (file)
index 0000000..5d981f8
--- /dev/null
@@ -0,0 +1,91 @@
+#include <stdio.h>
+#include "../r3000a.h"
+#include "../cdrom.h"
+#include "../psxdma.h"
+#include "../mdec.h"
+#include "events.h"
+
+extern int pending_exception;
+
+//#define evprintf printf
+#define evprintf(...)
+
+u32 event_cycles[PSXINT_COUNT];
+
+void schedule_timeslice(void)
+{
+       u32 i, c = psxRegs.cycle;
+       u32 irqs = psxRegs.interrupt;
+       s32 min, dif;
+
+       min = PSXCLK;
+       for (i = 0; irqs != 0; i++, irqs >>= 1) {
+               if (!(irqs & 1))
+                       continue;
+               dif = event_cycles[i] - c;
+               //evprintf("  ev %d\n", dif);
+               if (0 < dif && dif < min)
+                       min = dif;
+       }
+       next_interupt = c + min;
+}
+
+static void unusedInterrupt()
+{
+}
+
+typedef void (irq_func)();
+
+static irq_func * const irq_funcs[] = {
+       [PSXINT_SIO]    = sioInterrupt,
+       [PSXINT_CDR]    = cdrInterrupt,
+       [PSXINT_CDREAD] = cdrPlayReadInterrupt,
+       [PSXINT_GPUDMA] = gpuInterrupt,
+       [PSXINT_MDECOUTDMA] = mdec1Interrupt,
+       [PSXINT_SPUDMA] = spuInterrupt,
+       [PSXINT_MDECINDMA] = mdec0Interrupt,
+       [PSXINT_GPUOTCDMA] = gpuotcInterrupt,
+       [PSXINT_CDRDMA] = cdrDmaInterrupt,
+       [PSXINT_CDRLID] = cdrLidSeekInterrupt,
+       [PSXINT_CDRPLAY_OLD] = unusedInterrupt,
+       [PSXINT_SPU_UPDATE] = spuUpdate,
+       [PSXINT_RCNT] = psxRcntUpdate,
+};
+
+/* local dupe of psxBranchTest, using event_cycles */
+static void irq_test(psxCP0Regs *cp0)
+{
+       u32 cycle = psxRegs.cycle;
+       u32 irq, irq_bits;
+
+       for (irq = 0, irq_bits = psxRegs.interrupt; irq_bits != 0; irq++, irq_bits >>= 1) {
+               if (!(irq_bits & 1))
+                       continue;
+               if ((s32)(cycle - event_cycles[irq]) >= 0) {
+                       // note: irq_funcs() also modify psxRegs.interrupt
+                       psxRegs.interrupt &= ~(1u << irq);
+                       irq_funcs[irq]();
+               }
+       }
+
+       if ((psxHu32(0x1070) & psxHu32(0x1074)) && (cp0->n.Status & 0x401) == 0x401) {
+               psxException(0x400, 0, cp0);
+               pending_exception = 1;
+       }
+}
+
+void gen_interupt(psxCP0Regs *cp0)
+{
+       evprintf("  +ge %08x, %u->%u (%d)\n", psxRegs.pc, psxRegs.cycle,
+               next_interupt, next_interupt - psxRegs.cycle);
+
+       irq_test(cp0);
+       //pending_exception = 1;
+
+       schedule_timeslice();
+
+       evprintf("  -ge %08x, %u->%u (%d)\n", psxRegs.pc, psxRegs.cycle,
+               next_interupt, next_interupt - psxRegs.cycle);
+}
+
+
diff --git a/libpcsxcore/new_dynarec/events.h b/libpcsxcore/new_dynarec/events.h
new file mode 100644 (file)
index 0000000..919855c
--- /dev/null
@@ -0,0 +1,3 @@
+union psxCP0Regs_;
+void schedule_timeslice(void);
+void gen_interupt(union psxCP0Regs_ *cp0);
index 7e0db2d..f97b2d0 100644 (file)
@@ -242,6 +242,7 @@ FUNCTION(cc_interrupt):
 @@     str     r10, [fp, #LO_reg_cop0+36]      /* Count - not on PSX */
        mov     r10, lr
 
+       add     r0, fp, #(LO_psxRegs + 34*4)    /* CP0 */
        bl      gen_interupt
        mov     lr, r10
        ldr     r10, [fp, #LO_cycle]
@@ -301,7 +302,8 @@ call_psxException:
        ldr     r3, [fp, #LO_last_count]
        str     r2, [fp, #LO_pcaddr]
        add     r10, r3, r10
-       str     r10, [fp, #LO_cycle]            /* PCSX cycles */
+       str     r10, [fp, #LO_cycle]            /* PCSX cycles */
+       add     r2, fp, #(LO_psxRegs + 34*4)    /* CP0 */
        bl      psxException
 
        /* note: psxException might do recursive recompiler call from it's HLE code,
index d073ded..72d13f3 100644 (file)
@@ -100,6 +100,7 @@ FUNCTION(cc_interrupt):
 #      str     rCC, [rFP, #LO_reg_cop0+36]     /* Count */
        mov     x21, lr
 1:
+       add     x0, rFP, #(LO_psxRegs + 34*4)   /* CP0 */
        bl      gen_interupt
        mov     lr, x21
        ldr     rCC, [rFP, #LO_cycle]
@@ -159,7 +160,8 @@ call_psxException:
        ldr     w3, [rFP, #LO_last_count]
        str     w2, [rFP, #LO_pcaddr]
        add     rCC, w3, rCC
-       str     rCC, [rFP, #LO_cycle]           /* PCSX cycles */
+       str     rCC, [rFP, #LO_cycle]           /* PCSX cycles */
+       add     x2, rFP, #(LO_psxRegs + 34*4)   /* CP0 */
        bl      psxException
 
        /* note: psxException might do recursive recompiler call from it's HLE code,
index 2673a6e..17f7af9 100644 (file)
@@ -242,6 +242,7 @@ static struct decoded_insn
 } dops[MAXBLOCK];
 
   static u_char *out;
+  static char invalid_code[0x100000];
   static struct ht_entry hash_table[65536];
   static struct block_info *blocks[PAGE_COUNT];
   static struct jump_info *jumps[PAGE_COUNT];
@@ -3605,7 +3606,7 @@ static void do_cop1stub(int n)
   //else {printf("fp exception in delay slot\n");}
   wb_dirtys(i_regs->regmap_entry,i_regs->wasdirty);
   if(regs[i].regmap_entry[HOST_CCREG]!=CCREG) emit_loadreg(CCREG,HOST_CCREG);
-  emit_movimm(start+(i-ds)*4,EAX); // Get PC
+  emit_movimm(start+(i-ds)*4,0); // Get PC
   emit_addimm(HOST_CCREG,ccadj[i],HOST_CCREG); // CHECK: is this right?  There should probably be an extra cycle...
   emit_far_jump(ds?fp_exception_ds:fp_exception);
 }
@@ -5071,8 +5072,8 @@ static void do_ccstub(int n)
   if(stubs[n].c!=-1)
   {
     // Save PC as return address
-    emit_movimm(stubs[n].c,EAX);
-    emit_writeword(EAX,&pcaddr);
+    emit_movimm(stubs[n].c,0);
+    emit_writeword(0,&pcaddr);
   }
   else
   {
index ced14cf..ac89d1f 100644 (file)
@@ -176,6 +176,11 @@ typedef void (CALLBACK* SPUregisterScheduleCb)(void (CALLBACK *callback)(unsigne
 typedef long (CALLBACK* SPUconfigure)(void);\r
 typedef long (CALLBACK* SPUtest)(void);\r
 typedef void (CALLBACK* SPUabout)(void);\r
+typedef struct {\r
+       unsigned char PluginName[8];\r
+       uint32_t PluginVersion;\r
+       uint32_t Size;\r
+} SPUFreezeHdr_t;\r
 typedef struct {\r
        unsigned char PluginName[8];\r
        uint32_t PluginVersion;\r
index 036b062..f59934a 100644 (file)
@@ -750,19 +750,19 @@ OP(psxMTLO) { _rLo_ = _rRs_; } // Lo = Rs
 *********************************************************/
 OP(psxBREAK) {
        regs_->pc -= 4;
-       psxException(0x24, branch);
+       psxException(0x24, branch, &regs_->CP0);
 }
 
 OP(psxSYSCALL) {
        regs_->pc -= 4;
-       psxException(0x20, branch);
+       psxException(0x20, branch, &regs_->CP0);
 }
 
 static inline void psxTestSWInts(psxRegisters *regs_) {
        if (regs_->CP0.n.Cause & regs_->CP0.n.Status & 0x0300 &&
           regs_->CP0.n.Status & 0x1) {
                regs_->CP0.n.Cause &= ~0x7c;
-               psxException(regs_->CP0.n.Cause, branch);
+               psxException(regs_->CP0.n.Cause, branch, &regs_->CP0);
        }
 }
 
index ddf8388..8b7cfbf 100644 (file)
@@ -84,7 +84,8 @@ void psxShutdown() {
        psxMemShutdown();
 }
 
-void psxException(u32 code, u32 bd) {
+// cp0 is passed separately for lightrec to be less messy
+void psxException(u32 code, u32 bd, psxCP0Regs *cp0) {
        psxRegs.code = PSXMu32(psxRegs.pc);
        
        if (!Config.HLE && ((((psxRegs.code) >> 24) & 0xfe) == 0x4a)) {
@@ -92,30 +93,30 @@ void psxException(u32 code, u32 bd) {
                // BIOS does not allow to return to GTE instructions
                // (just skips it, supposedly because it's scheduled already)
                // so we execute it here
-               psxCP2[psxRegs.code & 0x3f](&psxRegs.CP2);
+               psxCP2Regs *cp2 = (void *)(cp0 + 1);
+               psxCP2[psxRegs.code & 0x3f](cp2);
        }
 
        // Set the Cause
-       psxRegs.CP0.n.Cause = (psxRegs.CP0.n.Cause & 0x300) | code;
+       cp0->n.Cause = (cp0->n.Cause & 0x300) | code;
 
        // Set the EPC & PC
        if (bd) {
 #ifdef PSXCPU_LOG
                PSXCPU_LOG("bd set!!!\n");
 #endif
-               psxRegs.CP0.n.Cause |= 0x80000000;
-               psxRegs.CP0.n.EPC = (psxRegs.pc - 4);
+               cp0->n.Cause |= 0x80000000;
+               cp0->n.EPC = (psxRegs.pc - 4);
        } else
-               psxRegs.CP0.n.EPC = (psxRegs.pc);
+               cp0->n.EPC = (psxRegs.pc);
 
-       if (psxRegs.CP0.n.Status & 0x400000)
+       if (cp0->n.Status & 0x400000)
                psxRegs.pc = 0xbfc00180;
        else
                psxRegs.pc = 0x80000080;
 
        // Set the Status
-       psxRegs.CP0.n.Status = (psxRegs.CP0.n.Status &~0x3f) |
-                                                 ((psxRegs.CP0.n.Status & 0xf) << 2);
+       cp0->n.Status = (cp0->n.Status & ~0x3f) | ((cp0->n.Status & 0x0f) << 2);
 
        if (Config.HLE) psxBiosException();
 }
@@ -199,7 +200,7 @@ void psxBranchTest() {
                        PSXCPU_LOG("Interrupt: %x %x\n", psxHu32(0x1070), psxHu32(0x1074));
 #endif
 //                     SysPrintf("Interrupt (%x): %x %x\n", psxRegs.cycle, psxHu32(0x1070), psxHu32(0x1074));
-                       psxException(0x400, 0);
+                       psxException(0x400, 0, &psxRegs.CP0);
                }
        }
 }
index be0e336..229b14a 100644 (file)
@@ -76,7 +76,7 @@ typedef union {
        PAIR p[34];
 } psxGPRRegs;
 
-typedef union {
+typedef union psxCP0Regs_ {
        struct {
                u32     Index,     Random,    EntryLo0,  EntryLo1,
                                                Context,   PageMask,  Wired,     Reserved0,
@@ -176,6 +176,8 @@ typedef struct psxCP2Regs {
 } psxCP2Regs;
 
 typedef struct {
+       // note: some cores like lightrec don't keep their data here,
+       // so use R3000ACPU_NOTIFY_BEFORE_SAVE to sync
        psxGPRRegs GPR;         /* General Purpose Registers */
        psxCP0Regs CP0;         /* Coprocessor0 Registers */
        union {
@@ -185,8 +187,8 @@ typedef struct {
                };
                psxCP2Regs CP2;
        };
-    u32 pc;                            /* Program counter */
-    u32 code;                  /* The instruction */
+       u32 pc;                         /* Program counter */
+       u32 code;                       /* The instruction */
        u32 cycle;
        u32 interrupt;
        struct { u32 sCycle, cycle; } intCycle[32];
@@ -224,7 +226,7 @@ void new_dyna_freeze(void *f, int mode);
 int  psxInit();
 void psxReset();
 void psxShutdown();
-void psxException(u32 code, u32 bd);
+void psxException(u32 code, u32 bd, psxCP0Regs *cp0);
 void psxBranchTest();
 void psxExecuteBios();
 void psxJumpTest();