From e117da235e939a47e4dd08fbded68abc3165271d Mon Sep 17 00:00:00 2001 From: Arisotura Date: Mon, 21 Oct 2019 23:14:34 +0200 Subject: smarter CP15 PU region updates. disable some useless logging. fixes #528 --- src/ARM.h | 3 +- src/CP15.cpp | 307 +++++++++++++++++++++++++++++++++-------------------------- 2 files changed, 175 insertions(+), 135 deletions(-) (limited to 'src') diff --git a/src/ARM.h b/src/ARM.h index d13d535..dcff477 100644 --- a/src/ARM.h +++ b/src/ARM.h @@ -211,7 +211,8 @@ public: void UpdateDTCMSetting(); void UpdateITCMSetting(); - void UpdatePURegions(); + void UpdatePURegion(u32 n); + void UpdatePURegions(bool update_all); u32 RandomLineIndex(); diff --git a/src/CP15.cpp b/src/CP15.cpp index a4db5f3..cf0ece9 100644 --- a/src/CP15.cpp +++ b/src/CP15.cpp @@ -59,7 +59,7 @@ void ARMv5::CP15Reset() PU_DataRW = 0; memset(PU_Region, 0, 8*sizeof(u32)); - UpdatePURegions(); + UpdatePURegions(true); CurICacheLine = NULL; } @@ -89,7 +89,7 @@ void ARMv5::CP15DoSavestate(Savestate* file) { UpdateDTCMSetting(); UpdateITCMSetting(); - UpdatePURegions(); + UpdatePURegions(true); } } @@ -125,27 +125,12 @@ void ARMv5::UpdateITCMSetting() } -void ARMv5::UpdatePURegions() +// covers updates to a specific PU region's cache/etc settings +// (not to the region range/enabled status) +void ARMv5::UpdatePURegion(u32 n) { - if (!(CP15Control & (1<<0))) - { - // PU disabled - - u8 mask = 0x07; - if (CP15Control & (1<<2)) mask |= 0x30; - if (CP15Control & (1<<12)) mask |= 0x40; - - memset(PU_UserMap, mask, 0x100000); - memset(PU_PrivMap, mask, 0x100000); - - return; - } - - memset(PU_UserMap, 0, 0x100000); - memset(PU_PrivMap, 0, 0x100000); - - u32 coderw = PU_CodeRW; - u32 datarw = PU_DataRW; + u32 coderw = (PU_CodeRW >> (4*n)) & 0xF; + u32 datarw = (PU_DataRW >> (4*n)) & 0xF; u32 codecache, datacache, datawrite; @@ -156,14 +141,14 @@ void ARMv5::UpdatePURegions() // 1/1: goes to cache if (CP15Control & (1<<12)) - codecache = PU_CodeCacheable; + codecache = (PU_CodeCacheable >> n) & 0x1; else codecache = 0; if (CP15Control & (1<<2)) { - datacache = PU_DataCacheable; - datawrite = PU_DataCacheWrite; + datacache = (PU_DataCacheable >> n) & 0x1; + datawrite = (PU_DataCacheWrite >> n) & 0x1; } else { @@ -171,88 +156,102 @@ void ARMv5::UpdatePURegions() datawrite = 0; } - for (int n = 0; n < 8; n++) + u32 rgn = PU_Region[n]; + if (!(rgn & (1<<0))) { - u32 rgn = PU_Region[n]; - if (!(rgn & (1<<0))) - { - coderw >>= 4; - datarw >>= 4; - codecache >>= 1; - datacache >>= 1; - datawrite >>= 1; - continue; - } + return; + } - u32 start = rgn >> 12; - u32 sz = 2 << ((rgn >> 1) & 0x1F); - u32 end = start + (sz >> 12); - // TODO: check alignment of start + u32 start = rgn >> 12; + u32 sz = 2 << ((rgn >> 1) & 0x1F); + u32 end = start + (sz >> 12); + // TODO: check alignment of start - u8 usermask = 0; - u8 privmask = 0; + u8 usermask = 0; + u8 privmask = 0; - switch (datarw & 0xF) - { - case 0: break; - case 1: privmask |= 0x03; break; - case 2: privmask |= 0x03; usermask |= 0x01; break; - case 3: privmask |= 0x03; usermask |= 0x03; break; - case 5: privmask |= 0x01; break; - case 6: privmask |= 0x01; usermask |= 0x01; break; - default: printf("!! BAD DATARW VALUE %d\n", datarw&0xF); - } + switch (datarw) + { + case 0: break; + case 1: privmask |= 0x03; break; + case 2: privmask |= 0x03; usermask |= 0x01; break; + case 3: privmask |= 0x03; usermask |= 0x03; break; + case 5: privmask |= 0x01; break; + case 6: privmask |= 0x01; usermask |= 0x01; break; + default: printf("!! BAD DATARW VALUE %d\n", datarw&0xF); + } - switch (coderw & 0xF) + switch (coderw) + { + case 0: break; + case 1: privmask |= 0x04; break; + case 2: privmask |= 0x04; usermask |= 0x04; break; + case 3: privmask |= 0x04; usermask |= 0x04; break; + case 5: privmask |= 0x04; break; + case 6: privmask |= 0x04; usermask |= 0x04; break; + default: printf("!! BAD CODERW VALUE %d\n", datarw&0xF); + } + + if (datacache & 0x1) + { + privmask |= 0x10; + usermask |= 0x10; + + if (datawrite & 0x1) { - case 0: break; - case 1: privmask |= 0x04; break; - case 2: privmask |= 0x04; usermask |= 0x04; break; - case 3: privmask |= 0x04; usermask |= 0x04; break; - case 5: privmask |= 0x04; break; - case 6: privmask |= 0x04; usermask |= 0x04; break; - default: printf("!! BAD CODERW VALUE %d\n", datarw&0xF); + privmask |= 0x20; + usermask |= 0x20; } + } - if (datacache & 0x1) - { - privmask |= 0x10; - usermask |= 0x10; + if (codecache & 0x1) + { + privmask |= 0x40; + usermask |= 0x40; + } - if (datawrite & 0x1) - { - privmask |= 0x20; - usermask |= 0x20; - } - } + //printf("PU region %d: %08X-%08X, user=%02X priv=%02X\n", n, start<<12, end<<12, usermask, privmask); - if (codecache & 0x1) - { - privmask |= 0x40; - usermask |= 0x40; - } + for (u32 i = start; i < end; i++) + { + PU_UserMap[i] = usermask; + PU_PrivMap[i] = privmask; + } - printf("PU region %d: %08X-%08X, user=%02X priv=%02X\n", n, start<<12, end<<12, usermask, privmask); + UpdateRegionTimings(start<<12, end<<12); +} - for (u32 i = start; i < end; i++) - { - PU_UserMap[i] = usermask; - PU_PrivMap[i] = privmask; - } +void ARMv5::UpdatePURegions(bool update_all) +{ + if (!(CP15Control & (1<<0))) + { + // PU disabled - coderw >>= 4; - datarw >>= 4; - codecache >>= 1; - datacache >>= 1; - datawrite >>= 1; + u8 mask = 0x07; + if (CP15Control & (1<<2)) mask |= 0x30; + if (CP15Control & (1<<12)) mask |= 0x40; + + memset(PU_UserMap, mask, 0x100000); + memset(PU_PrivMap, mask, 0x100000); + + UpdateRegionTimings(0x00000000, 0xFFFFFFFF); + return; + } + + if (update_all) + { + memset(PU_UserMap, 0, 0x100000); + memset(PU_PrivMap, 0, 0x100000); + } - // TODO: this will not be enough if they change their PU regions after the intial setup - //UpdateRegionTimings(start<<12, end<<12); + for (int n = 0; n < 8; n++) + { + UpdatePURegion(n); } // TODO: this is way unoptimized // should be okay unless the game keeps changing shit, tho - UpdateRegionTimings(0x00000000, 0xFFFFFFFF); + if (update_all) UpdateRegionTimings(0x00000000, 0xFFFFFFFF); } void ARMv5::UpdateRegionTimings(u32 addrstart, u32 addrend) @@ -302,7 +301,6 @@ u32 ARMv5::RandomLineIndex() return (RNGSeed >> 17) & 0x3; } -int zog=1; void ARMv5::ICacheLookup(u32 addr) { u32 tag = addr & 0xFFFFF800; @@ -311,25 +309,25 @@ void ARMv5::ICacheLookup(u32 addr) id <<= 2; if (ICacheTags[id+0] == tag) { - CodeCycles = 1;zog=1; + CodeCycles = 1; CurICacheLine = &ICache[(id+0) << 5]; return; } if (ICacheTags[id+1] == tag) { - CodeCycles = 1;zog=2; + CodeCycles = 1; CurICacheLine = &ICache[(id+1) << 5]; return; } if (ICacheTags[id+2] == tag) { - CodeCycles = 1;zog=3; + CodeCycles = 1; CurICacheLine = &ICache[(id+2) << 5]; return; } if (ICacheTags[id+3] == tag) { - CodeCycles = 1;zog=4; + CodeCycles = 1; CurICacheLine = &ICache[(id+3) << 5]; return; } @@ -417,10 +415,13 @@ void ARMv5::CP15Write(u32 id, u32 val) val &= 0x000FF085; CP15Control &= ~0x000FF085; CP15Control |= val; - printf("CP15Control = %08X (%08X->%08X)\n", CP15Control, old, val); + //printf("CP15Control = %08X (%08X->%08X)\n", CP15Control, old, val); UpdateDTCMSetting(); UpdateITCMSetting(); - if ((old & 0x1005) != (val & 0x1005)) UpdatePURegions(); + if ((old & 0x1005) != (val & 0x1005)) + { + UpdatePURegions((old & 0x1) != (val & 0x1)); + } if (val & (1<<7)) printf("!!!! ARM9 BIG ENDIAN MODE. VERY BAD. SHIT GONNA ASPLODE NOW\n"); if (val & (1<<13)) ExceptionBase = 0xFFFF0000; else ExceptionBase = 0x00000000; @@ -429,63 +430,100 @@ void ARMv5::CP15Write(u32 id, u32 val) case 0x200: // data cacheable - PU_DataCacheable = val; - printf("PU: DataCacheable=%08X\n", val); - UpdatePURegions(); + { + u32 diff = PU_DataCacheable ^ val; + PU_DataCacheable = val; + for (u32 i = 0; i < 8; i++) + { + if (diff & (1<>1))); - UpdatePURegions(); + // TODO: smarter region update for this? + UpdatePURegions(true); return; -- cgit v1.2.3