From 61ad2a6193b343bed12af5400746254583339304 Mon Sep 17 00:00:00 2001 From: notaz Date: Mon, 22 Nov 2021 21:29:08 +0200 Subject: [PATCH] make icache implementation play nice with the dynarec No need to to have a build-time option now. --- configure | 12 --- frontend/menu.c | 17 ++-- libpcsxcore/new_dynarec/emu_if.c | 7 +- libpcsxcore/new_dynarec/patches/trace_intr | 12 --- libpcsxcore/psxbios.c | 2 - libpcsxcore/psxinterpreter.c | 92 ++++++---------------- libpcsxcore/psxinterpreter.h | 3 + libpcsxcore/psxmem.c | 4 - libpcsxcore/r3000a.c | 16 +--- libpcsxcore/r3000a.h | 5 -- 10 files changed, 43 insertions(+), 127 deletions(-) diff --git a/configure b/configure index 16f510c7..7b300259 100755 --- a/configure +++ b/configure @@ -59,7 +59,6 @@ need_sdl="no" need_xlib="no" need_libpicofe="yes" need_warm="no" -enable_icache_emu="yes" CFLAGS_GLES="" LDLIBS_GLES="" # these are for known platforms @@ -95,14 +94,12 @@ set_platform() optimize_cortexa8="yes" have_arm_neon="yes" need_xlib="yes" - enable_icache_emu="no" ;; maemo) ram_fixed="yes" drc_cache_base="yes" optimize_cortexa8="yes" have_arm_neon="yes" - enable_icache_emu="no" ;; caanoo) sound_drivers="oss" @@ -110,7 +107,6 @@ set_platform() drc_cache_base="yes" optimize_arm926ej="yes" need_warm="yes" - enable_icache_emu="no" ;; libretro) sound_drivers="libretro" @@ -139,10 +135,6 @@ for opt do ;; --disable-dynarec) enable_dynarec="no" ;; - --disable-icache-emu) enable_icache_emu="no" - ;; - --enable-icache-emu) enable_icache_emu="yes" - ;; *) echo "ERROR: unknown option $opt"; show_help="yes" ;; esac @@ -504,10 +496,6 @@ if [ "x$sizeof_long" = "x4" ]; then CFLAGS="$CFLAGS -D_FILE_OFFSET_BITS=64" fi -if [ "$enable_icache_emu" = "yes" ]; then - CFLAGS="$CFLAGS -DICACHE_EMULATION" -fi - cat > $TMPC <Notify(R3000ACPU_NOTIFY_CACHE_ISOLATED, NULL); psxCpu->Notify(R3000ACPU_NOTIFY_CACHE_UNISOLATED, NULL); -#endif pc0 = ra; } diff --git a/libpcsxcore/psxinterpreter.c b/libpcsxcore/psxinterpreter.c index 2dd90b0f..d2225c41 100644 --- a/libpcsxcore/psxinterpreter.c +++ b/libpcsxcore/psxinterpreter.c @@ -49,14 +49,19 @@ void (*psxCP0[32])(); void (*psxCP2[64])(struct psxCP2Regs *regs); void (*psxCP2BSC[32])(); -#ifdef ICACHE_EMULATION +static u32 fetchNoCache(u32 pc) +{ + u32 *code = (u32 *)PSXM(pc); + return ((code == NULL) ? 0 : SWAP32(*code)); +} + /* Formula One 2001 : Use old CPU cache code when the RAM location is updated with new code (affects in-game racing) */ static u8* ICache_Addr; static u8* ICache_Code; -uint32_t *Read_ICache(uint32_t pc) +static u32 fetchICache(u32 pc) { uint32_t pc_bank, pc_offset, pc_cache; uint8_t *IAddr, *ICode; @@ -74,7 +79,7 @@ uint32_t *Read_ICache(uint32_t pc) if (SWAP32(*(uint32_t *)(IAddr + pc_cache)) == pc_offset) { // Cache hit - return last opcode used - return (uint32_t *)(ICode + pc_cache); + return *(uint32_t *)(ICode + pc_cache); } else { @@ -104,9 +109,10 @@ uint32_t *Read_ICache(uint32_t pc) TODO: Probably should add cached BIOS */ // default - return (uint32_t *)PSXM(pc); + return fetchNoCache(pc); } -#endif + +u32 (*fetch)(u32 pc) = fetchNoCache; static void delayRead(int reg, u32 bpc) { u32 rold, rnew; @@ -322,21 +328,7 @@ int psxTestLoadDelay(int reg, u32 tmp) { } void psxDelayTest(int reg, u32 bpc) { - u32 *code; - u32 tmp; - - #ifdef ICACHE_EMULATION - if (Config.icache_emulation) - { - code = Read_ICache(psxRegs.pc); - } - else - #endif - { - code = (u32 *)PSXM(psxRegs.pc); - } - - tmp = ((code == NULL) ? 0 : SWAP32(*code)); + u32 tmp = fetch(psxRegs.pc); branch = 1; switch (psxTestLoadDelay(reg, tmp)) { @@ -356,20 +348,9 @@ void psxDelayTest(int reg, u32 bpc) { } static u32 psxBranchNoDelay(void) { - u32 *code; u32 temp; - #ifdef ICACHE_EMULATION - if (Config.icache_emulation) - { - code = Read_ICache(psxRegs.pc); - } - else - #endif - { - code = (u32 *)PSXM(psxRegs.pc); - } - psxRegs.code = ((code == NULL) ? 0 : SWAP32(*code)); + psxRegs.code = fetch(psxRegs.pc); switch (_Op_) { case 0x00: // SPECIAL switch (_Funct_) { @@ -487,7 +468,6 @@ static int psxDelayBranchTest(u32 tar1) { } static void doBranch(u32 tar) { - u32 *code; u32 tmp; branch2 = branch = 1; @@ -497,17 +477,7 @@ static void doBranch(u32 tar) { if (psxDelayBranchTest(tar)) return; - #ifdef ICACHE_EMULATION - if (Config.icache_emulation) - { - code = Read_ICache(psxRegs.pc); - } - else - #endif - { - code = (u32 *)PSXM(psxRegs.pc); - } - psxRegs.code = ((code == NULL) ? 0 : SWAP32(*code)); + psxRegs.code = fetch(psxRegs.pc); debugI(); @@ -1057,7 +1027,6 @@ void (*psxCP2BSC[32])() = { /////////////////////////////////////////// static int intInit() { - #ifdef ICACHE_EMULATION /* We have to allocate the icache memory even if * the user has not enabled it as otherwise it can cause issues. */ @@ -1080,15 +1049,12 @@ static int intInit() { } memset(ICache_Addr, 0xff, 0x1000); memset(ICache_Code, 0xff, 0x1000); - #endif return 0; } static void intReset() { - #ifdef ICACHE_EMULATION memset(ICache_Addr, 0xff, 0x1000); memset(ICache_Code, 0xff, 0x1000); - #endif } void intExecute() { @@ -1106,17 +1072,15 @@ static void intClear(u32 Addr, u32 Size) { } void intNotify (int note, void *data) { - #ifdef ICACHE_EMULATION /* Gameblabla - Only clear the icache if it's isolated */ if (note == R3000ACPU_NOTIFY_CACHE_ISOLATED) { memset(ICache_Addr, 0xff, 0x1000); memset(ICache_Code, 0xff, 0x1000); } - #endif } -void applyConfig() { +void intApplyConfig() { assert(psxBSC[18] == psxCOP2 || psxBSC[18] == psxCOP2_stall); assert(psxBSC[50] == gteLWC2 || psxBSC[50] == gteLWC2_stall); assert(psxBSC[58] == gteSWC2 || psxBSC[58] == gteSWC2_stall); @@ -1148,10 +1112,16 @@ void applyConfig() { psxSPC[26] = psxDIV_stall; psxSPC[27] = psxDIVU_stall; } + + // dynarec may occasionally call the interpreter, in such a case the + // cache won't work (cache only works right if all fetches go through it) + if (!Config.icache_emulation || psxCpu != &psxInt) + fetch = fetchNoCache; + else + fetch = fetchICache; } static void intShutdown() { - #ifdef ICACHE_EMULATION if (ICache_Addr) { free(ICache_Addr); @@ -1163,23 +1133,11 @@ static void intShutdown() { free(ICache_Code); ICache_Code = NULL; } - #endif } // interpreter execution void execI() { - u32 *code; - #ifdef ICACHE_EMULATION - if (Config.icache_emulation) - { - code = Read_ICache(psxRegs.pc); - } - else - #endif - { - code = (u32 *)PSXM(psxRegs.pc); - } - psxRegs.code = ((code == NULL) ? 0 : SWAP32(*code)); + psxRegs.code = fetch(psxRegs.pc); debugI(); @@ -1197,9 +1155,7 @@ R3000Acpu psxInt = { intExecute, intExecuteBlock, intClear, -#ifdef ICACHE_EMULATION intNotify, -#endif - applyConfig, + intApplyConfig, intShutdown }; diff --git a/libpcsxcore/psxinterpreter.h b/libpcsxcore/psxinterpreter.h index 1c97689f..89dd7ea1 100644 --- a/libpcsxcore/psxinterpreter.h +++ b/libpcsxcore/psxinterpreter.h @@ -1,4 +1,7 @@ +extern u32 (*fetch)(u32 pc); + // called by "new_dynarec" void execI(); void psxNULL(); +void intApplyConfig(); diff --git a/libpcsxcore/psxmem.c b/libpcsxcore/psxmem.c index c09965dc..52d27593 100644 --- a/libpcsxcore/psxmem.c +++ b/libpcsxcore/psxmem.c @@ -389,10 +389,8 @@ void psxMemWrite32(u32 mem, u32 value) { memset(psxMemWLUT + 0x0000, 0, 0x80 * sizeof(void *)); memset(psxMemWLUT + 0x8000, 0, 0x80 * sizeof(void *)); memset(psxMemWLUT + 0xa000, 0, 0x80 * sizeof(void *)); -#ifdef ICACHE_EMULATION /* Required for icache interpreter otherwise Armored Core won't boot on icache interpreter */ psxCpu->Notify(R3000ACPU_NOTIFY_CACHE_ISOLATED, NULL); -#endif break; case 0x00: case 0x1e988: if (writeok == 1) break; @@ -400,10 +398,8 @@ void psxMemWrite32(u32 mem, u32 value) { for (i = 0; i < 0x80; i++) psxMemWLUT[i + 0x0000] = (void *)&psxM[(i & 0x1f) << 16]; memcpy(psxMemWLUT + 0x8000, psxMemWLUT, 0x80 * sizeof(void *)); memcpy(psxMemWLUT + 0xa000, psxMemWLUT, 0x80 * sizeof(void *)); -#ifdef ICACHE_EMULATION /* Dynarecs might take this opportunity to flush their code cache */ psxCpu->Notify(R3000ACPU_NOTIFY_CACHE_UNISOLATED, NULL); -#endif break; default: #ifdef PSXMEM_LOG diff --git a/libpcsxcore/r3000a.c b/libpcsxcore/r3000a.c index e21d4883..7e6f16b4 100644 --- a/libpcsxcore/r3000a.c +++ b/libpcsxcore/r3000a.c @@ -25,6 +25,7 @@ #include "cdrom.h" #include "mdec.h" #include "gte.h" +#include "psxinterpreter.h" R3000Acpu *psxCpu = NULL; #ifdef DRC_DISABLE @@ -39,6 +40,7 @@ int psxInit() { psxCpu = &psxInt; } else psxCpu = &psxRec; #else + Config.Cpu = CPU_INTERPRETER; psxCpu = &psxInt; #endif @@ -81,19 +83,7 @@ void psxShutdown() { } void psxException(u32 code, u32 bd) { - #ifdef ICACHE_EMULATION - /* Dynarecs may use this codepath and crash as a result. - * This should only be used for the interpreter. - Gameblabla - * */ - if (Config.icache_emulation && Config.Cpu == CPU_INTERPRETER) - { - psxRegs.code = SWAPu32(*Read_ICache(psxRegs.pc)); - } - else - #endif - { - psxRegs.code = PSXMu32(psxRegs.pc); - } + psxRegs.code = fetch(psxRegs.pc); if (!Config.HLE && ((((psxRegs.code) >> 24) & 0xfe) == 0x4a)) { // "hokuto no ken" / "Crash Bandicot 2" ... diff --git a/libpcsxcore/r3000a.h b/libpcsxcore/r3000a.h index 94d7d955..cb72bf36 100644 --- a/libpcsxcore/r3000a.h +++ b/libpcsxcore/r3000a.h @@ -29,14 +29,11 @@ extern "C" { #include "psxcounters.h" #include "psxbios.h" -#ifdef ICACHE_EMULATION enum { R3000ACPU_NOTIFY_CACHE_ISOLATED = 0, R3000ACPU_NOTIFY_CACHE_UNISOLATED = 1, R3000ACPU_NOTIFY_DMA3_EXE_LOAD = 2 }; -extern uint32_t *Read_ICache(uint32_t pc); -#endif typedef struct { int (*Init)(); @@ -44,9 +41,7 @@ typedef struct { void (*Execute)(); /* executes up to a break */ void (*ExecuteBlock)(); /* executes up to a jump */ void (*Clear)(u32 Addr, u32 Size); -#ifdef ICACHE_EMULATION void (*Notify)(int note, void *data); -#endif void (*ApplyConfig)(); void (*Shutdown)(); } R3000Acpu; -- 2.39.2