diff options
Diffstat (limited to 'src')
-rw-r--r-- | src/ARM.h | 3 | ||||
-rw-r--r-- | src/CP15.cpp | 307 |
2 files changed, 175 insertions, 135 deletions
@@ -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<<i)) UpdatePURegion(i); + } + } return; case 0x201: // code cacheable - PU_CodeCacheable = val; - printf("PU: CodeCacheable=%08X\n", val); - UpdatePURegions(); + { + u32 diff = PU_CodeCacheable ^ val; + PU_CodeCacheable = val; + for (u32 i = 0; i < 8; i++) + { + if (diff & (1<<i)) UpdatePURegion(i); + } + } return; case 0x300: // data cache write-buffer - PU_DataCacheWrite = val; - printf("PU: DataCacheWrite=%08X\n", val); - UpdatePURegions(); + { + u32 diff = PU_DataCacheWrite ^ val; + PU_DataCacheWrite = val; + for (u32 i = 0; i < 8; i++) + { + if (diff & (1<<i)) UpdatePURegion(i); + } + } return; case 0x500: // legacy data permissions - PU_DataRW = 0; - PU_DataRW |= (val & 0x0003); - PU_DataRW |= ((val & 0x000C) << 2); - PU_DataRW |= ((val & 0x0030) << 4); - PU_DataRW |= ((val & 0x00C0) << 6); - PU_DataRW |= ((val & 0x0300) << 8); - PU_DataRW |= ((val & 0x0C00) << 10); - PU_DataRW |= ((val & 0x3000) << 12); - PU_DataRW |= ((val & 0xC000) << 14); - printf("PU: DataRW=%08X (legacy %08X)\n", PU_DataRW, val); - UpdatePURegions(); + { + u32 old = PU_DataRW; + PU_DataRW = 0; + PU_DataRW |= (val & 0x0003); + PU_DataRW |= ((val & 0x000C) << 2); + PU_DataRW |= ((val & 0x0030) << 4); + PU_DataRW |= ((val & 0x00C0) << 6); + PU_DataRW |= ((val & 0x0300) << 8); + PU_DataRW |= ((val & 0x0C00) << 10); + PU_DataRW |= ((val & 0x3000) << 12); + PU_DataRW |= ((val & 0xC000) << 14); + u32 diff = old ^ PU_DataRW; + for (u32 i = 0; i < 8; i++) + { + if (diff & (0xF<<(i*4))) UpdatePURegion(i); + } + } return; case 0x501: // legacy code permissions - PU_CodeRW = 0; - PU_CodeRW |= (val & 0x0003); - PU_CodeRW |= ((val & 0x000C) << 2); - PU_CodeRW |= ((val & 0x0030) << 4); - PU_CodeRW |= ((val & 0x00C0) << 6); - PU_CodeRW |= ((val & 0x0300) << 8); - PU_CodeRW |= ((val & 0x0C00) << 10); - PU_CodeRW |= ((val & 0x3000) << 12); - PU_CodeRW |= ((val & 0xC000) << 14); - printf("PU: CodeRW=%08X (legacy %08X)\n", PU_CodeRW, val); - UpdatePURegions(); + { + u32 old = PU_CodeRW; + PU_CodeRW = 0; + PU_CodeRW |= (val & 0x0003); + PU_CodeRW |= ((val & 0x000C) << 2); + PU_CodeRW |= ((val & 0x0030) << 4); + PU_CodeRW |= ((val & 0x00C0) << 6); + PU_CodeRW |= ((val & 0x0300) << 8); + PU_CodeRW |= ((val & 0x0C00) << 10); + PU_CodeRW |= ((val & 0x3000) << 12); + PU_CodeRW |= ((val & 0xC000) << 14); + u32 diff = old ^ PU_CodeRW; + for (u32 i = 0; i < 8; i++) + { + if (diff & (0xF<<(i*4))) UpdatePURegion(i); + } + } return; case 0x502: // data permissions - PU_DataRW = val; - printf("PU: DataRW=%08X\n", PU_DataRW); - UpdatePURegions(); + { + u32 diff = PU_DataRW ^ val; + PU_DataRW = val; + for (u32 i = 0; i < 8; i++) + { + if (diff & (0xF<<(i*4))) UpdatePURegion(i); + } + } return; case 0x503: // code permissions - PU_CodeRW = val; - printf("PU: CodeRW=%08X\n", PU_CodeRW); - UpdatePURegions(); + { + u32 diff = PU_CodeRW ^ val; + PU_CodeRW = val; + for (u32 i = 0; i < 8; i++) + { + if (diff & (0xF<<(i*4))) UpdatePURegion(i); + } + } return; @@ -510,7 +548,8 @@ void ARMv5::CP15Write(u32 id, u32 val) printf("%s, ", val&1 ? "enabled":"disabled"); printf("%08X-", val&0xFFFFF000); printf("%08X\n", (val&0xFFFFF000)+(2<<((val&0x3E)>>1))); - UpdatePURegions(); + // TODO: smarter region update for this? + UpdatePURegions(true); return; |