From 6d75addfea5544b926d3924b1bd1e1d8ce9ffdb4 Mon Sep 17 00:00:00 2001 From: notaz Date: Mon, 10 Jul 2023 01:50:00 +0300 Subject: [PATCH] drc: handle regs-not-in-psxRegs case better for lightrec --- Makefile | 2 +- libpcsxcore/misc.c | 34 +++++---- libpcsxcore/new_dynarec/emu_if.c | 86 +---------------------- libpcsxcore/new_dynarec/emu_if.h | 6 -- libpcsxcore/new_dynarec/events.c | 91 +++++++++++++++++++++++++ libpcsxcore/new_dynarec/events.h | 3 + libpcsxcore/new_dynarec/linkage_arm.S | 4 +- libpcsxcore/new_dynarec/linkage_arm64.S | 4 +- libpcsxcore/new_dynarec/new_dynarec.c | 7 +- libpcsxcore/plugins.h | 5 ++ libpcsxcore/psxinterpreter.c | 6 +- libpcsxcore/r3000a.c | 21 +++--- libpcsxcore/r3000a.h | 10 +-- 13 files changed, 153 insertions(+), 126 deletions(-) create mode 100644 libpcsxcore/new_dynarec/events.c create mode 100644 libpcsxcore/new_dynarec/events.h diff --git a/Makefile b/Makefile index 585480d1..ded26893 100644 --- 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 diff --git a/libpcsxcore/misc.c b/libpcsxcore/misc.c index d52a931c..57d3959f 100644 --- a/libpcsxcore/misc.c +++ b/libpcsxcore/misc.c @@ -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); diff --git a/libpcsxcore/new_dynarec/emu_if.c b/libpcsxcore/new_dynarec/emu_if.c index c1dab56d..50819e4b 100644 --- a/libpcsxcore/new_dynarec/emu_if.c +++ b/libpcsxcore/new_dynarec/emu_if.c @@ -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 @@ -25,91 +23,11 @@ //#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; } diff --git a/libpcsxcore/new_dynarec/emu_if.h b/libpcsxcore/new_dynarec/emu_if.h index b49b84ba..3f4aba6f 100644 --- a/libpcsxcore/new_dynarec/emu_if.h +++ b/libpcsxcore/new_dynarec/emu_if.h @@ -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 index 00000000..5d981f8d --- /dev/null +++ b/libpcsxcore/new_dynarec/events.c @@ -0,0 +1,91 @@ +#include +#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 index 00000000..919855cc --- /dev/null +++ b/libpcsxcore/new_dynarec/events.h @@ -0,0 +1,3 @@ +union psxCP0Regs_; +void schedule_timeslice(void); +void gen_interupt(union psxCP0Regs_ *cp0); diff --git a/libpcsxcore/new_dynarec/linkage_arm.S b/libpcsxcore/new_dynarec/linkage_arm.S index 7e0db2d7..f97b2d05 100644 --- a/libpcsxcore/new_dynarec/linkage_arm.S +++ b/libpcsxcore/new_dynarec/linkage_arm.S @@ -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, diff --git a/libpcsxcore/new_dynarec/linkage_arm64.S b/libpcsxcore/new_dynarec/linkage_arm64.S index d073ded4..72d13f3d 100644 --- a/libpcsxcore/new_dynarec/linkage_arm64.S +++ b/libpcsxcore/new_dynarec/linkage_arm64.S @@ -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, diff --git a/libpcsxcore/new_dynarec/new_dynarec.c b/libpcsxcore/new_dynarec/new_dynarec.c index 2673a6ea..17f7af95 100644 --- a/libpcsxcore/new_dynarec/new_dynarec.c +++ b/libpcsxcore/new_dynarec/new_dynarec.c @@ -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 { diff --git a/libpcsxcore/plugins.h b/libpcsxcore/plugins.h index ced14cff..ac89d1ff 100644 --- a/libpcsxcore/plugins.h +++ b/libpcsxcore/plugins.h @@ -176,6 +176,11 @@ typedef void (CALLBACK* SPUregisterScheduleCb)(void (CALLBACK *callback)(unsigne typedef long (CALLBACK* SPUconfigure)(void); typedef long (CALLBACK* SPUtest)(void); typedef void (CALLBACK* SPUabout)(void); +typedef struct { + unsigned char PluginName[8]; + uint32_t PluginVersion; + uint32_t Size; +} SPUFreezeHdr_t; typedef struct { unsigned char PluginName[8]; uint32_t PluginVersion; diff --git a/libpcsxcore/psxinterpreter.c b/libpcsxcore/psxinterpreter.c index 036b062f..f59934ae 100644 --- a/libpcsxcore/psxinterpreter.c +++ b/libpcsxcore/psxinterpreter.c @@ -750,19 +750,19 @@ OP(psxMTLO) { _rLo_ = _rRs_; } // Lo = Rs *********************************************************/ OP(psxBREAK) { regs_->pc -= 4; - psxException(0x24, branch); + psxException(0x24, branch, ®s_->CP0); } OP(psxSYSCALL) { regs_->pc -= 4; - psxException(0x20, branch); + psxException(0x20, branch, ®s_->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, ®s_->CP0); } } diff --git a/libpcsxcore/r3000a.c b/libpcsxcore/r3000a.c index ddf83886..8b7cfbf7 100644 --- a/libpcsxcore/r3000a.c +++ b/libpcsxcore/r3000a.c @@ -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); } } } diff --git a/libpcsxcore/r3000a.h b/libpcsxcore/r3000a.h index be0e3368..229b14a1 100644 --- a/libpcsxcore/r3000a.h +++ b/libpcsxcore/r3000a.h @@ -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(); -- 2.39.2