Add compile-time option to drop psxMemRLUT, psxMemWLUT
authorPaul Cercueil <paul@crapouillou.net>
Fri, 6 Oct 2023 20:53:47 +0000 (22:53 +0200)
committernotaz <notasas@gmail.com>
Mon, 9 Oct 2023 18:05:11 +0000 (21:05 +0300)
Add compile-time option which, if enabled, will replace accesses to
psxMemRLUT and psxMemWLUT with a small inline function psxm().

The reasons behind this change are:

- These were some BIG LUTs. On 32-bit, they would account for 512 KiB of
  RAM. On 64-bit, they would account for 1 MiB of RAM. This sounds tiny
  by today's standards, but it still is huge for some of the platforms
  that PCSX supports.

- Computing the pointer isn't that resource-intensive. Still slower than
  reading from a LUT (as long as the LUT entry is in the cache, which it
  should be, as the few valid entries are grouped together), but I doubt
  that it slows down the interpreter by a lot.

- Even if it does slow down the interpreter a bit, it shouldn't be a
  huge deal, given that the interpreter isn't really used nowadays as
  the JITs support all the major CPU architectures, and the interpreter
  is used mostly for debugging purposes. Besides, the two JITs do not
  use these LUTs.

Signed-off-by: Paul Cercueil <paul@crapouillou.net>
Makefile
libpcsxcore/psxinterpreter.c
libpcsxcore/psxmem.c
libpcsxcore/psxmem.h

index 9779ddc..6ef105a 100644 (file)
--- a/Makefile
+++ b/Makefile
@@ -14,7 +14,8 @@ endif
 endif
 CFLAGS += -DP_HAVE_MMAP=$(if $(NO_MMAP),0,1) \
          -DP_HAVE_PTHREAD=$(if $(NO_PTHREAD),0,1) \
-         -DP_HAVE_POSIX_MEMALIGN=$(if $(NO_POSIX_MEMALIGN),0,1)
+         -DP_HAVE_POSIX_MEMALIGN=$(if $(NO_POSIX_MEMALIGN),0,1) \
+         -DDISABLE_MEM_LUTS=0
 CXXFLAGS += $(CFLAGS)
 #DRC_DBG = 1
 #PCNT = 1
index 2ffab69..f6ff2e8 100644 (file)
@@ -176,25 +176,21 @@ static int execBreakCheck(psxRegisters *regs, u32 pc)
 // get an opcode without triggering exceptions or affecting cache
 u32 intFakeFetch(u32 pc)
 {
-       u8 *base = psxMemRLUT[pc >> 16];
-       u32 *code;
-       if (unlikely(base == INVALID_PTR))
+       u32 *code = (u32 *)psxm(pc & ~0x3, 0);
+       if (unlikely(code == INVALID_PTR))
                return 0; // nop
-       code = (u32 *)(base + (pc & 0xfffc));
        return SWAP32(*code);
 
 }
 
 static u32 INT_ATTR fetchNoCache(psxRegisters *regs, u8 **memRLUT, u32 pc)
 {
-       u8 *base = memRLUT[pc >> 16];
-       u32 *code;
-       if (unlikely(base == INVALID_PTR)) {
+       u32 *code = (u32 *)psxm_lut(pc & ~0x3, 0, memRLUT);
+       if (unlikely(code == INVALID_PTR)) {
                SysPrintf("game crash @%08x, ra=%08x\n", pc, regs->GPR.n.ra);
                intException(regs, pc, R3000E_IBE << 2);
                return 0; // execute as nop
        }
-       code = (u32 *)(base + (pc & 0xfffc));
        return SWAP32(*code);
 }
 
@@ -217,14 +213,12 @@ static u32 INT_ATTR fetchICache(psxRegisters *regs, u8 **memRLUT, u32 pc)
 
                if (((entry->tag ^ pc) & 0xfffffff0) != 0 || pc < entry->tag)
                {
-                       const u8 *base = memRLUT[pc >> 16];
-                       const u32 *code;
-                       if (unlikely(base == INVALID_PTR)) {
+                       const u32 *code = (u32 *)psxm_lut(pc & ~0xf, 0, memRLUT);
+                       if (unlikely(code == INVALID_PTR)) {
                                SysPrintf("game crash @%08x, ra=%08x\n", pc, regs->GPR.n.ra);
                                intException(regs, pc, R3000E_IBE << 2);
                                return 0; // execute as nop
                        }
-                       code = (u32 *)(base + (pc & 0xfff0));
 
                        entry->tag = pc;
                        // treat as 4 words, although other configurations are said to be possible
index 389bdba..2196fa7 100644 (file)
@@ -206,6 +206,9 @@ int psxMemInit(void)
                return -1;
        }
 
+       if (DISABLE_MEM_LUTS)
+               return 0;
+
        psxMemRLUT = (u8 **)malloc(0x10000 * sizeof(void *));
        psxMemWLUT = (u8 **)malloc(0x10000 * sizeof(void *));
 
@@ -285,19 +288,25 @@ void psxMemShutdown() {
        free(psxMemWLUT); psxMemWLUT = NULL;
 }
 
+int cache_isolated;
+
 void psxMemOnIsolate(int enable)
 {
-       if (enable) {
-               memset(psxMemWLUT + 0x0000, (int)(uintptr_t)INVALID_PTR, 0x80 * sizeof(void *));
-               memset(psxMemWLUT + 0x8000, (int)(uintptr_t)INVALID_PTR, 0x80 * sizeof(void *));
-               //memset(psxMemWLUT + 0xa000, (int)(uintptr_t)INVALID_PTR, 0x80 * sizeof(void *));
-       } else {
-               int i;
-               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 *));
+       if (!DISABLE_MEM_LUTS) {
+               if (enable) {
+                       memset(psxMemWLUT + 0x0000, (int)(uintptr_t)INVALID_PTR, 0x80 * sizeof(void *));
+                       memset(psxMemWLUT + 0x8000, (int)(uintptr_t)INVALID_PTR, 0x80 * sizeof(void *));
+                       //memset(psxMemWLUT + 0xa000, (int)(uintptr_t)INVALID_PTR, 0x80 * sizeof(void *));
+               } else {
+                       int i;
+                       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 *));
+               }
        }
+
+       cache_isolated = enable;
        psxCpu->Notify(enable ? R3000ACPU_NOTIFY_CACHE_ISOLATED
                        : R3000ACPU_NOTIFY_CACHE_UNISOLATED, NULL);
 }
@@ -313,11 +322,11 @@ u8 psxMemRead8(u32 mem) {
                else
                        return psxHwRead8(mem);
        } else {
-               p = (char *)(psxMemRLUT[t]);
+               p = psxm(mem, 0);
                if (p != INVALID_PTR) {
                        if (Config.Debug)
                                DebugCheckBP((mem & 0xffffff) | 0x80000000, R1);
-                       return *(u8 *)(p + (mem & 0xffff));
+                       return *(u8 *)p;
                } else {
 #ifdef PSXMEM_LOG
                        PSXMEM_LOG("err lb %8.8lx\n", mem);
@@ -338,11 +347,11 @@ u16 psxMemRead16(u32 mem) {
                else
                        return psxHwRead16(mem);
        } else {
-               p = (char *)(psxMemRLUT[t]);
+               p = psxm(mem, 0);
                if (p != INVALID_PTR) {
                        if (Config.Debug)
                                DebugCheckBP((mem & 0xffffff) | 0x80000000, R2);
-                       return SWAPu16(*(u16 *)(p + (mem & 0xffff)));
+                       return SWAPu16(*(u16 *)p);
                } else {
 #ifdef PSXMEM_LOG
                        PSXMEM_LOG("err lh %8.8lx\n", mem);
@@ -363,11 +372,11 @@ u32 psxMemRead32(u32 mem) {
                else
                        return psxHwRead32(mem);
        } else {
-               p = (char *)(psxMemRLUT[t]);
+               p = psxm(mem, 0);
                if (p != INVALID_PTR) {
                        if (Config.Debug)
                                DebugCheckBP((mem & 0xffffff) | 0x80000000, R4);
-                       return SWAPu32(*(u32 *)(p + (mem & 0xffff)));
+                       return SWAPu32(*(u32 *)p);
                } else {
                        if (mem == 0xfffe0130)
                                return psxRegs.biuReg;
@@ -390,11 +399,11 @@ void psxMemWrite8(u32 mem, u8 value) {
                else
                        psxHwWrite8(mem, value);
        } else {
-               p = (char *)(psxMemWLUT[t]);
+               p = psxm(mem, 1);
                if (p != INVALID_PTR) {
                        if (Config.Debug)
                                DebugCheckBP((mem & 0xffffff) | 0x80000000, W1);
-                       *(u8 *)(p + (mem & 0xffff)) = value;
+                       *(u8 *)p = value;
 #ifndef DRC_DISABLE
                        psxCpu->Clear((mem & (~3)), 1);
 #endif
@@ -417,11 +426,11 @@ void psxMemWrite16(u32 mem, u16 value) {
                else
                        psxHwWrite16(mem, value);
        } else {
-               p = (char *)(psxMemWLUT[t]);
+               p = psxm(mem, 1);
                if (p != INVALID_PTR) {
                        if (Config.Debug)
                                DebugCheckBP((mem & 0xffffff) | 0x80000000, W2);
-                       *(u16 *)(p + (mem & 0xffff)) = SWAPu16(value);
+                       *(u16 *)p = SWAPu16(value);
 #ifndef DRC_DISABLE
                        psxCpu->Clear((mem & (~3)), 1);
 #endif
@@ -445,11 +454,11 @@ void psxMemWrite32(u32 mem, u32 value) {
                else
                        psxHwWrite32(mem, value);
        } else {
-               p = (char *)(psxMemWLUT[t]);
+               p = psxm(mem, 1);
                if (p != INVALID_PTR) {
                        if (Config.Debug)
                                DebugCheckBP((mem & 0xffffff) | 0x80000000, W4);
-                       *(u32 *)(p + (mem & 0xffff)) = SWAPu32(value);
+                       *(u32 *)p = SWAPu32(value);
 #ifndef DRC_DISABLE
                        psxCpu->Clear(mem, 1);
 #endif
@@ -476,9 +485,9 @@ void *psxMemPointer(u32 mem) {
                else
                        return NULL;
        } else {
-               p = (char *)(psxMemWLUT[t]);
+               p = psxm(mem, 1);
                if (p != INVALID_PTR) {
-                       return (void *)(p + (mem & 0xffff));
+                       return (void *)p;
                }
                return NULL;
        }
index 129973c..a52472c 100644 (file)
@@ -114,8 +114,48 @@ extern s8 *psxH;
 
 extern u8 **psxMemWLUT;
 extern u8 **psxMemRLUT;
+extern int cache_isolated;
 
-#define PSXM(mem)              (psxMemRLUT[(mem) >> 16] == INVALID_PTR ? INVALID_PTR : (u8*)(psxMemRLUT[(mem) >> 16] + ((mem) & 0xffff)))
+static inline void * psxm_lut(u32 mem, int write, u8 **lut)
+{
+       if (!DISABLE_MEM_LUTS) {
+               void *ptr = lut[mem >> 16];
+
+               return ptr == INVALID_PTR ? INVALID_PTR : ptr + (u16)mem;
+       }
+
+       if (mem >= 0xa0000000)
+               mem -= 0xa0000000;
+       else
+               mem &= ~0x80000000;
+
+       if (mem < 0x800000) {
+               if (cache_isolated)
+                       return INVALID_PTR;
+
+               return &psxM[mem & 0x1fffff];
+       }
+
+       if (mem > 0x1f800000 && mem <= 0x1f810000)
+               return &psxH[mem - 0x1f800000];
+
+       if (!write) {
+               if (mem > 0x1fc00000 && mem <= 0x1fc80000)
+                       return &psxR[mem - 0x1fc00000];
+
+               if (mem > 0x1f000000 && mem <= 0x1f010000)
+                       return &psxP[mem - 0x1f000000];
+       }
+
+       return INVALID_PTR;
+}
+
+static inline void * psxm(u32 mem, int write)
+{
+       return psxm_lut(mem, write, write ? psxMemWLUT : psxMemRLUT);
+}
+
+#define PSXM(mem) psxm(mem, 0)
 #define PSXMs8(mem)            (*(s8 *)PSXM(mem))
 #define PSXMs16(mem)   (SWAP16(*(s16 *)PSXM(mem)))
 #define PSXMs32(mem)   (SWAP32(*(s32 *)PSXM(mem)))