make icache implementation play nice with the dynarec
authornotaz <notasas@gmail.com>
Mon, 22 Nov 2021 19:29:08 +0000 (21:29 +0200)
committernotaz <notasas@gmail.com>
Mon, 22 Nov 2021 23:51:24 +0000 (01:51 +0200)
No need to to have a build-time option now.

configure
frontend/menu.c
libpcsxcore/new_dynarec/emu_if.c
libpcsxcore/new_dynarec/patches/trace_intr
libpcsxcore/psxbios.c
libpcsxcore/psxinterpreter.c
libpcsxcore/psxinterpreter.h
libpcsxcore/psxmem.c
libpcsxcore/r3000a.c
libpcsxcore/r3000a.h

index 16f510c..7b30025 100755 (executable)
--- 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 <<EOF
 void test(void *f, void *d) { fread(d, 1, 1, f); }
 EOF
index 76d0e86..289c30c 100644 (file)
@@ -1552,19 +1552,23 @@ static int menu_loop_plugin_options(int id, int keys)
 
 // ------------ adv options menu ------------
 
+#ifndef DRC_DISABLE
 static const char h_cfg_psxclk[]  = "Over/under-clock the PSX, default is " DEFAULT_PSX_CLOCK_S "\n"
                                    "(lower value - less work for the emu, may be faster)";
 static const char h_cfg_nosmc[]   = "Will cause crashes when loading, break memcards";
 static const char h_cfg_gteunn[]  = "May cause graphical glitches";
 static const char h_cfg_gteflgs[] = "Will cause graphical glitches";
+#endif
 static const char h_cfg_stalls[]  = "Will cause some games to run too fast";
 
 static menu_entry e_menu_speed_hacks[] =
 {
+#ifndef DRC_DISABLE
        mee_range_h   ("PSX CPU clock, %%",        0, psx_clock, 1, 500, h_cfg_psxclk),
        mee_onoff_h   ("Disable SMC checks",       0, new_dynarec_hacks, NDHACK_NO_SMC_CHECK, h_cfg_nosmc),
        mee_onoff_h   ("Assume GTE regs unneeded", 0, new_dynarec_hacks, NDHACK_GTE_UNNEEDED, h_cfg_gteunn),
        mee_onoff_h   ("Disable GTE flags",        0, new_dynarec_hacks, NDHACK_GTE_NO_FLAGS, h_cfg_gteflgs),
+#endif
        mee_onoff_h   ("Disable CPU/GTE stalls",   0, Config.DisableStalls, 1, h_cfg_stalls),
        mee_end,
 };
@@ -1589,14 +1593,13 @@ static const char h_cfg_spuirq[] = "Compatibility tweak; should be left off";
 //                                "(timing hack, breaks other games)";
 static const char h_cfg_rcnt2[]  = "InuYasha Sengoku Battle Fix\n"
                                   "(timing hack, breaks other games)";
+#ifndef DRC_DISABLE
 static const char h_cfg_nodrc[]  = "Disable dynamic recompiler and use interpreter\n"
                                   "Might be useful to overcome some dynarec bugs";
-static const char h_cfg_shacks[] = "Breaks games but may give better performance\n"
-                                  "must reload game for any change to take effect";
-#ifdef ICACHE_EMULATION
-static const char h_cfg_icache[] = "Allows you to play the F1 games.\n"
-                                  "Note: This breaks the PAL version of Spyro 2.";
 #endif
+static const char h_cfg_shacks[] = "Breaks games but may give better performance";
+static const char h_cfg_icache[] = "Support F1 games (only when dynarec is off).\n"
+                                  "Note: This breaks the PAL version of Spyro 2.";
                                   
 static menu_entry e_menu_adv_options[] =
 {
@@ -1607,12 +1610,12 @@ static menu_entry e_menu_adv_options[] =
        mee_onoff_h   ("Disable CD Audio",       0, Config.Cdda, 1, h_cfg_cdda),
        //mee_onoff_h   ("SIO IRQ Always Enabled", 0, Config.Sio, 1, h_cfg_sio),
        mee_onoff_h   ("SPU IRQ Always Enabled", 0, Config.SpuIrq, 1, h_cfg_spuirq),
-#ifdef ICACHE_EMULATION
        mee_onoff_h   ("ICache emulation",       0, Config.icache_emulation, 1, h_cfg_icache),
-#endif
        //mee_onoff_h   ("Rootcounter hack",       0, Config.RCntFix, 1, h_cfg_rcnt1),
        mee_onoff_h   ("Rootcounter hack 2",     0, Config.VSyncWA, 1, h_cfg_rcnt2),
+#ifndef DRC_DISABLE
        mee_onoff_h   ("Disable dynarec (slow!)",0, Config.Cpu, 1, h_cfg_nodrc),
+#endif
        mee_handler_h ("[Speed hacks]",             menu_loop_speed_hacks, h_cfg_shacks),
        mee_end,
 };
index f170be7..8c96504 100644 (file)
@@ -10,6 +10,7 @@
 #include "emu_if.h"
 #include "pcsxmem.h"
 #include "../psxhle.h"
+#include "../psxinterpreter.h"
 #include "../r3000a.h"
 #include "../cdrom.h"
 #include "../psxdma.h"
@@ -387,7 +388,6 @@ static void ari64_clear(u32 addr, u32 size)
                        invalidate_block(start);
 }
 
-#ifdef ICACHE_EMULATION
 static void ari64_notify(int note, void *data) {
        /*
        Should be fixed when ARM dynarec has proper icache emulation.
@@ -403,10 +403,11 @@ static void ari64_notify(int note, void *data) {
        }
        */
 }
-#endif
 
 static void ari64_apply_config()
 {
+       intApplyConfig();
+
        if (Config.DisableStalls)
                new_dynarec_hacks |= NDHACK_NO_STALLS;
        else
@@ -431,9 +432,7 @@ R3000Acpu psxRec = {
        ari64_execute,
        ari64_execute_until,
        ari64_clear,
-#ifdef ICACHE_EMULATION
        ari64_notify,
-#endif
        ari64_apply_config,
        ari64_shutdown
 };
index e4f790b..9538bd0 100644 (file)
@@ -1,15 +1,3 @@
-diff --git a/Makefile b/Makefile
-index 0db94f7..e4fe560 100644
---- a/Makefile
-+++ b/Makefile
-@@ -26,6 +26,7 @@ endif
- else # NO_CONFIG_MAK
- config.mak:
- endif
-+CFLAGS += -UICACHE_EMULATION
- -include Makefile.local
 diff --git a/libpcsxcore/new_dynarec/emu_if.c b/libpcsxcore/new_dynarec/emu_if.c
 index 2df259b..2a15e6e 100644
 --- a/libpcsxcore/new_dynarec/emu_if.c
index a0588be..16b48d9 100644 (file)
@@ -1405,10 +1405,8 @@ void psxBios_FlushCache() { // 44
 #ifdef PSXBIOS_LOG
        PSXBIOS_LOG("psxBios_%s\n", biosA0n[0x44]);
 #endif
-#ifdef ICACHE_EMULATION
        psxCpu->Notify(R3000ACPU_NOTIFY_CACHE_ISOLATED, NULL);
        psxCpu->Notify(R3000ACPU_NOTIFY_CACHE_UNISOLATED, NULL);
-#endif
        pc0 = ra;
 }
 
index 2dd90b0..d2225c4 100644 (file)
@@ -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
 };
index 1c97689..89dd7ea 100644 (file)
@@ -1,4 +1,7 @@
 
+extern u32 (*fetch)(u32 pc);
+
 // called by "new_dynarec"
 void execI();
 void psxNULL();
+void intApplyConfig();
index c09965d..52d2759 100644 (file)
@@ -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
index e21d488..7e6f16b 100644 (file)
@@ -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" ...
index 94d7d95..cb72bf3 100644 (file)
@@ -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;