diff --git a/src/ARM.cpp b/src/ARM.cpp index c2f6a6c2..b8961a8f 100644 --- a/src/ARM.cpp +++ b/src/ARM.cpp @@ -1152,69 +1152,57 @@ u32 ARMv5::ReadMem(u32 addr, int size) } #endif -void ARMv4::DataRead8(u32 addr, u32* val) +void ARMv4::DataRead8(const u32 addr, u32* val) { *val = BusRead8(addr); DataRegion = addr; DataCycles = NDS.ARM7MemTimings[addr >> 15][0]; } -void ARMv4::DataRead16(u32 addr, u32* val) +void ARMv4::DataRead16(const u32 addr, u32* val) { - addr &= ~1; - - *val = BusRead16(addr); + *val = BusRead16(addr & ~1); DataRegion = addr; DataCycles = NDS.ARM7MemTimings[addr >> 15][0]; } -void ARMv4::DataRead32(u32 addr, u32* val) +void ARMv4::DataRead32(const u32 addr, u32* val) { - addr &= ~3; - - *val = BusRead32(addr); + *val = BusRead32(addr & ~3); DataRegion = addr; DataCycles = NDS.ARM7MemTimings[addr >> 15][2]; } -void ARMv4::DataRead32S(u32 addr, u32* val) +void ARMv4::DataRead32S(const u32 addr, u32* val) { - addr &= ~3; - - *val = BusRead32(addr); + *val = BusRead32(addr & ~3); DataCycles += NDS.ARM7MemTimings[addr >> 15][3]; } -void ARMv4::DataWrite8(u32 addr, u8 val) +void ARMv4::DataWrite8(const u32 addr, const u8 val) { BusWrite8(addr, val); DataRegion = addr; DataCycles = NDS.ARM7MemTimings[addr >> 15][0]; } -void ARMv4::DataWrite16(u32 addr, u16 val) +void ARMv4::DataWrite16(const u32 addr, const u16 val) { - addr &= ~1; - - BusWrite16(addr, val); + BusWrite16(addr & ~1, val); DataRegion = addr; DataCycles = NDS.ARM7MemTimings[addr >> 15][0]; } -void ARMv4::DataWrite32(u32 addr, u32 val) +void ARMv4::DataWrite32(const u32 addr, const u32 val) { - addr &= ~3; - - BusWrite32(addr, val); + BusWrite32(addr & ~3, val); DataRegion = addr; DataCycles = NDS.ARM7MemTimings[addr >> 15][2]; } -void ARMv4::DataWrite32S(u32 addr, u32 val) +void ARMv4::DataWrite32S(const u32 addr, const u32 val) { - addr &= ~3; - - BusWrite32(addr, val); + BusWrite32(addr & ~3, val); DataCycles += NDS.ARM7MemTimings[addr >> 15][3]; } diff --git a/src/ARM.h b/src/ARM.h index eedd997b..df06e84e 100644 --- a/src/ARM.h +++ b/src/ARM.h @@ -25,6 +25,7 @@ #include "types.h" #include "MemRegion.h" #include "MemConstants.h" +#include "CP15_Constants.h" #ifdef GDBSTUB_ENABLED #include "debug/GdbStub.h" @@ -128,14 +129,14 @@ public: void SetupCodeMem(u32 addr); - virtual void DataRead8(u32 addr, u32* val) = 0; - virtual void DataRead16(u32 addr, u32* val) = 0; - virtual void DataRead32(u32 addr, u32* val) = 0; - virtual void DataRead32S(u32 addr, u32* val) = 0; - virtual void DataWrite8(u32 addr, u8 val) = 0; - virtual void DataWrite16(u32 addr, u16 val) = 0; - virtual void DataWrite32(u32 addr, u32 val) = 0; - virtual void DataWrite32S(u32 addr, u32 val) = 0; + virtual void DataRead8(const u32 addr, u32* val) = 0; + virtual void DataRead16(const u32 addr, u32* val) = 0; + virtual void DataRead32(const u32 addr, u32* val) = 0; + virtual void DataRead32S(const u32 addr, u32* val) = 0; + virtual void DataWrite8(const u32 addr, const u8 val) = 0; + virtual void DataWrite16(const u32 addr, const u16 val) = 0; + virtual void DataWrite32(const u32 addr, const u32 val) = 0; + virtual void DataWrite32S(const u32 addr, const u32 val) = 0; virtual void AddCycles_C() = 0; virtual void AddCycles_CI(s32 numI) = 0; @@ -247,16 +248,16 @@ public: #endif // all code accesses are forced nonseq 32bit - u32 CodeRead32(u32 addr, bool branch); + u32 CodeRead32(const u32 addr, const bool branch); - void DataRead8(u32 addr, u32* val) override; - void DataRead16(u32 addr, u32* val) override; - void DataRead32(u32 addr, u32* val) override; - void DataRead32S(u32 addr, u32* val) override; - void DataWrite8(u32 addr, u8 val) override; - void DataWrite16(u32 addr, u16 val) override; - void DataWrite32(u32 addr, u32 val) override; - void DataWrite32S(u32 addr, u32 val) override; + void DataRead8(const u32 addr, u32* val) override; + void DataRead16(const u32 addr, u32* val) override; + void DataRead32(const u32 addr, u32* val) override; + void DataRead32S(const u32 addr, u32* val) override; + void DataWrite8(const u32 addr, const u8 val) override; + void DataWrite16(const u32 addr, const u16 val) override; + void DataWrite32(const u32 addr, const u32 val) override; + void DataWrite32S(const u32 addr, const u32 val) override; void AddCycles_C() override { @@ -317,7 +318,6 @@ public: void ICacheInvalidateByAddr(const u32 addr); void ICacheInvalidateBySetAndWay(const u8 cacheSet, const u8 cacheLine); - u32 DCacheLookup(const u32 addr); void DCacheWrite32(const u32 addr, const u32 val); void DCacheWrite16(const u32 addr, const u16 val); @@ -361,7 +361,6 @@ public: u8 DCache[DCACHE_SIZE]; u32 DCacheTags[DCACHE_LINESPERSET*DCACHE_SETS]; u8 DCacheCount; - u32 DCacheLFSRStates; u32 PU_CodeCacheable; u32 PU_DataCacheable; @@ -383,9 +382,6 @@ public: // code/16N/32N/32S u8 MemTimings[0x100000][4]; - u8* CurICacheLine; - u8* CurDCacheLine; - bool (*GetMemRegion)(u32 addr, bool write, MemRegion* region); #ifdef GDBSTUB_ENABLED @@ -416,24 +412,24 @@ public: void ExecuteJIT() override; #endif - u16 CodeRead16(u32 addr) + u16 CodeRead16(const u32 addr) { return BusRead16(addr); } - u32 CodeRead32(u32 addr) + u32 CodeRead32(const u32 addr) { return BusRead32(addr); } - void DataRead8(u32 addr, u32* val) override; - void DataRead16(u32 addr, u32* val) override; - void DataRead32(u32 addr, u32* val) override; - void DataRead32S(u32 addr, u32* val) override; - void DataWrite8(u32 addr, u8 val) override; - void DataWrite16(u32 addr, u16 val) override; - void DataWrite32(u32 addr, u32 val) override; - void DataWrite32S(u32 addr, u32 val) override; + void DataRead8(const u32 addr, u32* val) override; + void DataRead16(const u32 addr, u32* val) override; + void DataRead32(const u32 addr, u32* val) override; + void DataRead32S(const u32 addr, u32* val) override; + void DataWrite8(const u32 addr, const u8 val) override; + void DataWrite16(const u32 addr, const u16 val) override; + void DataWrite32(const u32 addr, const u32 val) override; + void DataWrite32S(const u32 addr, const u32 val) override; void AddCycles_C() override; void AddCycles_CI(s32 num) override; void AddCycles_CDI() override; diff --git a/src/CP15.cpp b/src/CP15.cpp index 2dcce5c1..714e591d 100644 --- a/src/CP15.cpp +++ b/src/CP15.cpp @@ -24,6 +24,7 @@ #include "Platform.h" #include "ARMJIT_Memory.h" #include "ARMJIT.h" +#include "CP15_Constants.h" namespace melonDS { @@ -67,10 +68,6 @@ void ARMv5::CP15Reset() DCacheInvalidateAll(); DCacheCount = 0; - // make sure that both half words are not the same otherwise the random of the DCache set selection only produces - // '00' and '11' - DCacheLFSRStates = 0xDEADBEEF; - PU_CodeCacheable = 0; PU_DataCacheable = 0; PU_DataCacheWrite = 0; @@ -78,10 +75,9 @@ void ARMv5::CP15Reset() PU_CodeRW = 0; PU_DataRW = 0; - memset(PU_Region, 0, 8*sizeof(u32)); + memset(PU_Region, 0, CP15_REGION_COUNT*sizeof(u32)); UpdatePURegions(true); - CurICacheLine = NULL; } void ARMv5::CP15DoSavestate(Savestate* file) @@ -103,7 +99,6 @@ void ARMv5::CP15DoSavestate(Savestate* file) file->VarArray(DCache, sizeof(DCache)); file->VarArray(DCacheTags, sizeof(DCacheTags)); file->Var8(&DCacheCount); - file->Var32(&DCacheLFSRStates); file->Var32(&DCacheLockDown); file->Var32(&ICacheLockDown); @@ -116,7 +111,7 @@ void ARMv5::CP15DoSavestate(Savestate* file) file->Var32(&PU_CodeRW); file->Var32(&PU_DataRW); - file->VarArray(PU_Region, 8*sizeof(u32)); + file->VarArray(PU_Region, CP15_REGION_COUNT*sizeof(u32)); if (!file->Saving) { @@ -178,8 +173,11 @@ void ARMv5::UpdatePURegion(u32 n) if (!(CP15Control & CP15_CR_MPUENABLE)) return; - u32 coderw = (PU_CodeRW >> (4*n)) & 0xF; - u32 datarw = (PU_DataRW >> (4*n)) & 0xF; + if (n >= CP15_REGION_COUNT) + return; + + u32 coderw = (PU_CodeRW >> (CP15_REGIONACCESS_BITS_PER_REGION * n)) & CP15_REGIONACCESS_REGIONMASK; + u32 datarw = (PU_DataRW >> (CP15_REGIONACCESS_BITS_PER_REGION * n)) & CP15_REGIONACCESS_REGIONMASK; u32 codecache, datacache, datawrite; @@ -211,60 +209,60 @@ void ARMv5::UpdatePURegion(u32 n) return; } - u32 start = rgn >> 12; - u32 sz = 2 << ((rgn >> 1) & 0x1F); - u32 end = start + (sz >> 12); + u32 start = (rgn & CP15_REGION_BASE_MASK) >> CP15_MAP_ENTRYSIZE_LOG2; + u32 sz = 2 << ((rgn & CP15_REGION_SIZE_MASK) >> 1); + u32 end = start + (sz >> CP15_MAP_ENTRYSIZE_LOG2); // TODO: check alignment of start - u8 usermask = 0; - u8 privmask = 0; + u8 usermask = CP15_MAP_NOACCESS; + u8 privmask = CP15_MAP_NOACCESS; 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; + case 1: privmask |= CP15_MAP_READABLE | CP15_MAP_WRITEABLE; break; + case 2: privmask |= CP15_MAP_READABLE | CP15_MAP_WRITEABLE; usermask |= CP15_MAP_READABLE; break; + case 3: privmask |= CP15_MAP_READABLE | CP15_MAP_WRITEABLE; usermask |= CP15_MAP_READABLE | CP15_MAP_WRITEABLE; break; + case 5: privmask |= CP15_MAP_READABLE; break; + case 6: privmask |= CP15_MAP_READABLE; usermask |= CP15_MAP_READABLE; break; default: Log(LogLevel::Warn, "!! BAD DATARW VALUE %d\n", datarw&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; + case 1: privmask |= CP15_MAP_EXECUTABLE; break; + case 2: privmask |= CP15_MAP_EXECUTABLE; usermask |= CP15_MAP_EXECUTABLE; break; + case 3: privmask |= CP15_MAP_EXECUTABLE; usermask |= CP15_MAP_EXECUTABLE; break; + case 5: privmask |= CP15_MAP_EXECUTABLE; break; + case 6: privmask |= CP15_MAP_EXECUTABLE; usermask |= CP15_MAP_EXECUTABLE; break; default: Log(LogLevel::Warn, "!! BAD CODERW VALUE %d\n", datarw&0xF); } if (datacache & 0x1) { - privmask |= 0x10; - usermask |= 0x10; + privmask |= CP15_MAP_DCACHEABLE; + usermask |= CP15_MAP_DCACHEABLE; if (datawrite & 0x1) { - privmask |= 0x20; - usermask |= 0x20; + privmask |= CP15_MAP_DCACHEWRITEBACK; + usermask |= CP15_MAP_DCACHEWRITEBACK; } } if (codecache & 0x1) { - privmask |= 0x40; - usermask |= 0x40; + privmask |= CP15_MAP_ICACHEABLE; + usermask |= CP15_MAP_ICACHEABLE; } Log( LogLevel::Debug, "PU region %d: %08X-%08X, user=%02X priv=%02X, %08X/%08X\n", n, - start << 12, - end << 12, + start << CP15_MAP_ENTRYSIZE_LOG2, + end << CP15_MAP_ENTRYSIZE_LOG2, usermask, privmask, PU_DataRW, @@ -286,9 +284,9 @@ void ARMv5::UpdatePURegions(bool update_all) { // PU disabled - u8 mask = 0x07; - if (CP15Control & CP15_CACHE_CR_DCACHEENABLE) mask |= 0x30; - if (CP15Control & CP15_CACHE_CR_ICACHEENABLE) mask |= 0x40; + u8 mask = CP15_MAP_READABLE | CP15_MAP_WRITEABLE | CP15_MAP_EXECUTABLE; + if (CP15Control & CP15_CACHE_CR_DCACHEENABLE) mask |= CP15_MAP_DCACHEABLE | CP15_MAP_DCACHEWRITEBACK ; + if (CP15Control & CP15_CACHE_CR_ICACHEENABLE) mask |= CP15_MAP_ICACHEABLE; memset(PU_UserMap, mask, 0x100000); memset(PU_PrivMap, mask, 0x100000); @@ -299,11 +297,11 @@ void ARMv5::UpdatePURegions(bool update_all) if (update_all) { - memset(PU_UserMap, 0, 0x100000); - memset(PU_PrivMap, 0, 0x100000); + memset(PU_UserMap, CP15_MAP_NOACCESS, 0x100000); + memset(PU_PrivMap, CP15_MAP_NOACCESS, 0x100000); } - for (int n = 0; n < 8; n++) + for (int n = 0; n < CP15_REGION_COUNT; n++) { UpdatePURegion(n); } @@ -322,7 +320,7 @@ void ARMv5::UpdateRegionTimings(u32 addrstart, u32 addrend) u8 pu = PU_Map[i]; u8* bustimings = NDS.ARM9MemTimings[i >> 2]; - if (pu & 0x40) + if (pu & CP15_MAP_ICACHEABLE) { MemTimings[i][0] = 0xFF;//kCodeCacheTiming; } @@ -331,7 +329,7 @@ void ARMv5::UpdateRegionTimings(u32 addrstart, u32 addrend) MemTimings[i][0] = bustimings[2] << NDS.ARM9ClockShift; } - if (pu & 0x10) + if (pu & CP15_MAP_DCACHEABLE) { MemTimings[i][1] = kDataCacheTiming; MemTimings[i][2] = kDataCacheTiming; @@ -364,7 +362,7 @@ u32 ARMv5::ICacheLookup(const u32 addr) for (int set=0;set> 12] & 0x40 ; + return PU_Map[addr >> CP15_MAP_ENTRYSIZE_LOG2] & CP15_MAP_ICACHEABLE ; } u32 ARMv5::DCacheLookup(const u32 addr) @@ -487,7 +485,7 @@ u32 ARMv5::DCacheLookup(const u32 addr) for (int set=0;set> 2] = val; DataCycles = 1; - - //Log(LogLevel::Debug,"DCache write32 hit @ %08x -> %08lx\n", addr, ((u32 *)CurDCacheLine)[(addr & (DCACHE_LINELENGTH-1)) >> 2]); return; } } @@ -597,13 +593,11 @@ void ARMv5::DCacheWrite16(const u32 addr, const u16 val) for (int set=0;set> 1] = val; DataCycles = 1; - - //Log(LogLevel::Debug,"DCache write16 hit @ %08x -> %04x\n", addr, ((u16 *)CurDCacheLine)[(addr & (DCACHE_LINELENGTH-1)) >> 2]); return; } } @@ -616,13 +610,11 @@ void ARMv5::DCacheWrite8(const u32 addr, const u8 val) for (int set=0;set %02x\n", addr, ((u8 *)CurDCacheLine)[(addr & (DCACHE_LINELENGTH-1)) >> 2]); return; } } @@ -635,7 +627,7 @@ void ARMv5::DCacheInvalidateByAddr(const u32 addr) for (int set=0;set> 12] & 0x10 ; + return PU_Map[addr >> CP15_MAP_ENTRYSIZE_LOG2] & CP15_MAP_DCACHEABLE ; } void ARMv5::CP15Write(u32 id, u32 val) @@ -700,13 +692,14 @@ void ARMv5::CP15Write(u32 id, u32 val) //Log(LogLevel::Debug, "CP15Control = %08X (%08X->%08X)\n", CP15Control, old, val); UpdateDTCMSetting(); UpdateITCMSetting(); - if ((old & 0x1005) != (val & 0x1005)) + u32 changedBits = old^val; + if (changedBits & (CP15_CR_MPUENABLE | CP15_CACHE_CR_ICACHEENABLE| CP15_CACHE_CR_DCACHEENABLE)) { - UpdatePURegions((old & 0x1) != (val & 0x1)); + UpdatePURegions(changedBits & CP15_CR_MPUENABLE); } if (val & CP15_CR_BIGENDIAN) Log(LogLevel::Warn, "!!!! ARM9 BIG ENDIAN MODE. VERY BAD. SHIT GONNA ASPLODE NOW\n"); - if (val & CP15_CR_HIGHEXCEPTIONBASE) ExceptionBase = 0xFFFF0000; - else ExceptionBase = 0x00000000; + if (val & CP15_CR_HIGHEXCEPTIONBASE) ExceptionBase = CP15_EXCEPTIONBASE_HIGH; + else ExceptionBase = CP15_EXCEPTIONBASE_LOW; } return; @@ -715,7 +708,7 @@ void ARMv5::CP15Write(u32 id, u32 val) { u32 diff = PU_DataCacheable ^ val; PU_DataCacheable = val; - for (u32 i = 0; i < 8; i++) + for (u32 i = 0; i < CP15_REGION_COUNT; i++) { if (diff & (1<> 4) & 0xF] = val; + PU_Region[(id >> CP15_REGIONACCESS_BITS_PER_REGION) & CP15_REGIONACCESS_REGIONMASK] = val; - std::snprintf(log_output, - sizeof(log_output), + Log(LogLevel::Debug, "PU: region %d = %08X : %s, %08X-%08X\n", - (id >> 4) & 0xF, + (id >> CP15_REGIONACCESS_BITS_PER_REGION) & CP15_REGIONACCESS_REGIONMASK, val, val & 1 ? "enabled" : "disabled", - val & 0xFFFFF000, - (val & 0xFFFFF000) + (2 << ((val & 0x3E) >> 1)) + val & CP15_REGION_BASE_MASK, + (val & CP15_REGION_BASE_MASK) + (2 << ((val & CP15_REGION_SIZE_MASK) >> 1)) ); - Log(LogLevel::Debug, "%s", log_output); - // Some implementations of Log imply a newline, so we build up the line before printing it - // TODO: smarter region update for this? UpdatePURegions(true); return; @@ -854,7 +842,6 @@ void ARMv5::CP15Write(u32 id, u32 val) case 0x750: // Can be executed in user and priv mode ICacheInvalidateAll(); - //Halt(255); return; case 0x751: // requires priv mode or causes UNKNOWN INSTRUCTION exception @@ -1179,11 +1166,7 @@ void ARMv5::CP15Write(u32 id, u32 val) } - if ((id & 0xF00) == 0xF00) // test/debug shit? - return; - - if ((id & 0xF00) != 0x700) - Log(LogLevel::Debug, "unknown CP15 write op %03X %08X\n", id, val); + Log(LogLevel::Debug, "unknown CP15 write op %03X %08X\n", id, val); } u32 ARMv5::CP15Read(u32 id) const @@ -1198,7 +1181,7 @@ u32 ARMv5::CP15Read(u32 id) const case 0x005: case 0x006: case 0x007: - return 0x41059461; + return CP15_MAINID_IMPLEMENTOR_ARM | CP15_MAINID_VARIANT_0 | CP15_MAINID_ARCH_v5TE | CP15_MAINID_IMPLEMENTATION_946 | CP15_MAINID_REVISION_1; case 0x001: // cache type return CACHE_TR_LOCKDOWN_TYPE_B | CACHE_TR_NONUNIFIED @@ -1269,7 +1252,7 @@ u32 ARMv5::CP15Read(u32 id) const case 0x661: case 0x670: case 0x671: - return PU_Region[(id >> 4) & 0xF]; + return PU_Region[(id >> CP15_REGIONACCESS_BITS_PER_REGION) & 0xF]; case 0x7A6: // read Cache Dirty Bit (optional) @@ -1346,9 +1329,6 @@ u32 ARMv5::CP15Read(u32 id) const } } - if ((id & 0xF00) == 0xF00) // test/debug shit? - return 0; - Log(LogLevel::Debug, "unknown CP15 read op %03X\n", id); return 0; } @@ -1357,24 +1337,9 @@ u32 ARMv5::CP15Read(u32 id) const // TCM are handled here. // TODO: later on, handle PU -u32 ARMv5::CodeRead32(u32 addr, bool branch) +u32 ARMv5::CodeRead32(const u32 addr, bool const branch) { - /*if (branch || (!(addr & 0xFFF))) - { - if (!(PU_Map[addr>>12] & 0x04)) - { - PrefetchAbort(); - return 0; - } - }*/ - if (addr < ITCMSize) - { - CodeCycles = 1; - return *(u32*)&ITCM[addr & (ITCMPhysicalSize - 1)]; - } - - CodeCycles = RegionCodeCycles; #ifdef JIT_ENABLED if (!NDS.IsJITEnabled()) #endif @@ -1386,27 +1351,33 @@ u32 ARMv5::CodeRead32(u32 addr, bool branch) return ICacheLookup(addr); } } - } else - { - if (CodeCycles == 0xFF) // cached memory. hax - { - if (branch || !(addr & 0x1F)) - CodeCycles = kCodeCacheTiming;//ICacheLookup(addr); - else - CodeCycles = 1; + } - //return *(u32*)&CurICacheLine[addr & 0x1C]; - } + if (addr < ITCMSize) + { + CodeCycles = 1; + return *(u32*)&ITCM[addr & (ITCMPhysicalSize - 1)]; } + + CodeCycles = RegionCodeCycles; + + if (CodeCycles == 0xFF) // cached memory. hax + { + if (branch || !(addr & (ICACHE_LINELENGTH-1))) + CodeCycles = kCodeCacheTiming;//ICacheLookup(addr); + else + CodeCycles = 1; + } + if (CodeMem.Mem) return *(u32*)&CodeMem.Mem[addr & CodeMem.Mask]; return BusRead32(addr); } -void ARMv5::DataRead8(u32 addr, u32* val) +void ARMv5::DataRead8(const u32 addr, u32* val) { - if (!(PU_Map[addr>>12] & 0x01)) + if (!(PU_Map[addr>>CP15_MAP_ENTRYSIZE_LOG2] & CP15_MAP_READABLE)) { Log(LogLevel::Debug, "data8 abort @ %08lx\n", addr); DataAbort(); @@ -1421,9 +1392,9 @@ void ARMv5::DataRead8(u32 addr, u32* val) { if (CP15Control & CP15_CACHE_CR_DCACHEENABLE) { - if (PU_Map[addr >> 12] & 0x10) + if (IsAddressDCachable(addr)) { - *val = (DCacheLookup(addr) >> (8* (addr & 3))) & 0xff; + *val = (DCacheLookup(addr) >> (8 * (addr & 3))) & 0xff; return; } } @@ -1443,12 +1414,12 @@ void ARMv5::DataRead8(u32 addr, u32* val) } *val = BusRead8(addr); - DataCycles = MemTimings[addr >> 12][1]; + DataCycles = MemTimings[addr >> BUSCYCLES_MAP_GRANULARITY_LOG2][BUSCYCLES_S16]; } -void ARMv5::DataRead16(u32 addr, u32* val) +void ARMv5::DataRead16(const u32 addr, u32* val) { - if (!(PU_Map[addr>>12] & 0x01)) + if (!(PU_Map[addr>>CP15_MAP_ENTRYSIZE_LOG2] & CP15_MAP_READABLE)) { Log(LogLevel::Debug, "data16 abort @ %08lx\n", addr); DataAbort(); @@ -1463,7 +1434,7 @@ void ARMv5::DataRead16(u32 addr, u32* val) { if (CP15Control & CP15_CACHE_CR_DCACHEENABLE) { - if (PU_Map[addr >> 12] & 0x10) + if (IsAddressDCachable(addr)) { *val = (DCacheLookup(addr) >> (8* (addr & 2))) & 0xffff; return; @@ -1471,28 +1442,26 @@ void ARMv5::DataRead16(u32 addr, u32* val) } } - addr &= ~1; - if (addr < ITCMSize) { DataCycles = 1; - *val = *(u16*)&ITCM[addr & (ITCMPhysicalSize - 1)]; + *val = *(u16*)&ITCM[addr & (ITCMPhysicalSize - 2)]; return; } if ((addr & DTCMMask) == DTCMBase) { DataCycles = 1; - *val = *(u16*)&DTCM[addr & (DTCMPhysicalSize - 1)]; + *val = *(u16*)&DTCM[addr & (DTCMPhysicalSize - 2)]; return; } - *val = BusRead16(addr); - DataCycles = MemTimings[addr >> 12][1]; + *val = BusRead16(addr & ~1); + DataCycles = MemTimings[addr >> BUSCYCLES_MAP_GRANULARITY_LOG2][BUSCYCLES_S16]; } -void ARMv5::DataRead32(u32 addr, u32* val) +void ARMv5::DataRead32(const u32 addr, u32* val) { - if (!(PU_Map[addr>>12] & 0x01)) + if (!(PU_Map[addr>>CP15_MAP_ENTRYSIZE_LOG2] & CP15_MAP_READABLE)) { Log(LogLevel::Debug, "data32 abort @ %08lx\n", addr); DataAbort(); @@ -1507,7 +1476,7 @@ void ARMv5::DataRead32(u32 addr, u32* val) { if (CP15Control & CP15_CACHE_CR_DCACHEENABLE) { - if (PU_Map[addr >> 12] & 0x10) + if (IsAddressDCachable(addr)) { *val = DCacheLookup(addr); return; @@ -1515,36 +1484,32 @@ void ARMv5::DataRead32(u32 addr, u32* val) } } - addr &= ~3; - if (addr < ITCMSize) { DataCycles = 1; - *val = *(u32*)&ITCM[addr & (ITCMPhysicalSize - 1)]; + *val = *(u32*)&ITCM[addr & (ITCMPhysicalSize - 3)]; return; } if ((addr & DTCMMask) == DTCMBase) { DataCycles = 1; - *val = *(u32*)&DTCM[addr & (DTCMPhysicalSize - 1)]; + *val = *(u32*)&DTCM[addr & (DTCMPhysicalSize - 3)]; return; } - *val = BusRead32(addr); - DataCycles = MemTimings[addr >> 12][2]; + *val = BusRead32(addr & ~0x03); + DataCycles = MemTimings[addr >> BUSCYCLES_MAP_GRANULARITY_LOG2][BUSCYCLES_N32]; } -void ARMv5::DataRead32S(u32 addr, u32* val) +void ARMv5::DataRead32S(const u32 addr, u32* val) { - addr &= ~3; - #ifdef JIT_ENABLED if (!NDS.IsJITEnabled()) #endif { if (CP15Control & CP15_CACHE_CR_DCACHEENABLE) { - if (PU_Map[addr >> 12] & 0x10) + if (IsAddressDCachable(addr)) { *val = DCacheLookup(addr); return; @@ -1555,23 +1520,23 @@ void ARMv5::DataRead32S(u32 addr, u32* val) if (addr < ITCMSize) { DataCycles += 1; - *val = *(u32*)&ITCM[addr & (ITCMPhysicalSize - 1)]; + *val = *(u32*)&ITCM[addr & (ITCMPhysicalSize - 3)]; return; } if ((addr & DTCMMask) == DTCMBase) { DataCycles += 1; - *val = *(u32*)&DTCM[addr & (DTCMPhysicalSize - 1)]; + *val = *(u32*)&DTCM[addr & (DTCMPhysicalSize - 3)]; return; } - *val = BusRead32(addr); - DataCycles += MemTimings[addr >> 12][3]; + *val = BusRead32(addr & ~0x03); + DataCycles += MemTimings[addr >> BUSCYCLES_MAP_GRANULARITY_LOG2][BUSCYCLES_S32]; } -void ARMv5::DataWrite8(u32 addr, u8 val) +void ARMv5::DataWrite8(const u32 addr, const u8 val) { - if (!(PU_Map[addr>>12] & 0x02)) + if (!(PU_Map[addr>>CP15_MAP_ENTRYSIZE_LOG2] & CP15_MAP_WRITEABLE)) { DataAbort(); return; @@ -1583,10 +1548,9 @@ void ARMv5::DataWrite8(u32 addr, u8 val) { if (CP15Control & CP15_CACHE_CR_DCACHEENABLE) { - if (PU_Map[addr >> 12] & 0x10) + if (IsAddressDCachable(addr)) { DCacheWrite8(addr, val); - //DCacheInvalidateByAddr(addr); } } } @@ -1608,12 +1572,12 @@ void ARMv5::DataWrite8(u32 addr, u8 val) } BusWrite8(addr, val); - DataCycles = MemTimings[addr >> 12][1]; + DataCycles = MemTimings[addr >> BUSCYCLES_MAP_GRANULARITY_LOG2][BUSCYCLES_S16]; } -void ARMv5::DataWrite16(u32 addr, u16 val) +void ARMv5::DataWrite16(const u32 addr, const u16 val) { - if (!(PU_Map[addr>>12] & 0x02)) + if (!(PU_Map[addr>>CP15_MAP_ENTRYSIZE_LOG2] & CP15_MAP_WRITEABLE)) { DataAbort(); return; @@ -1625,39 +1589,36 @@ void ARMv5::DataWrite16(u32 addr, u16 val) { if (CP15Control & CP15_CACHE_CR_DCACHEENABLE) { - if (PU_Map[addr >> 12] & 0x10) + if (IsAddressDCachable(addr)) { DCacheWrite16(addr, val); - // DCacheInvalidateByAddr(addr); } } } DataRegion = addr; - addr &= ~1; - if (addr < ITCMSize) { DataCycles = 1; - *(u16*)&ITCM[addr & (ITCMPhysicalSize - 1)] = val; + *(u16*)&ITCM[addr & (ITCMPhysicalSize - 2)] = val; NDS.JIT.CheckAndInvalidate<0, ARMJIT_Memory::memregion_ITCM>(addr); return; } if ((addr & DTCMMask) == DTCMBase) { DataCycles = 1; - *(u16*)&DTCM[addr & (DTCMPhysicalSize - 1)] = val; + *(u16*)&DTCM[addr & (DTCMPhysicalSize - 2)] = val; return; } - BusWrite16(addr, val); - DataCycles = MemTimings[addr >> 12][1]; + BusWrite16(addr & ~1, val); + DataCycles = MemTimings[addr >> BUSCYCLES_MAP_GRANULARITY_LOG2][BUSCYCLES_S16]; } -void ARMv5::DataWrite32(u32 addr, u32 val) +void ARMv5::DataWrite32(const u32 addr, const u32 val) { - if (!(PU_Map[addr>>12] & 0x02)) + if (!(PU_Map[addr>>CP15_MAP_ENTRYSIZE_LOG2] & CP15_MAP_WRITEABLE)) { DataAbort(); return; @@ -1669,50 +1630,44 @@ void ARMv5::DataWrite32(u32 addr, u32 val) { if (CP15Control & CP15_CACHE_CR_DCACHEENABLE) { - if (PU_Map[addr >> 12] & 0x10) + if (IsAddressDCachable(addr)) { DCacheWrite32(addr, val); - // DCacheInvalidateByAddr(addr); } } } DataRegion = addr; - addr &= ~3; - if (addr < ITCMSize) { DataCycles = 1; - *(u32*)&ITCM[addr & (ITCMPhysicalSize - 1)] = val; + *(u32*)&ITCM[addr & (ITCMPhysicalSize - 3)] = val; NDS.JIT.CheckAndInvalidate<0, ARMJIT_Memory::memregion_ITCM>(addr); return; } if ((addr & DTCMMask) == DTCMBase) { DataCycles = 1; - *(u32*)&DTCM[addr & (DTCMPhysicalSize - 1)] = val; + *(u32*)&DTCM[addr & (DTCMPhysicalSize - 3)] = val; return; } - BusWrite32(addr, val); - DataCycles = MemTimings[addr >> 12][2]; + BusWrite32(addr & ~3, val); + DataCycles = MemTimings[addr >> BUSCYCLES_MAP_GRANULARITY_LOG2][BUSCYCLES_N32]; } -void ARMv5::DataWrite32S(u32 addr, u32 val) +void ARMv5::DataWrite32S(const u32 addr, const u32 val) { - addr &= ~3; - #ifdef JIT_ENABLED if (!NDS.IsJITEnabled()) #endif { if (CP15Control & CP15_CACHE_CR_DCACHEENABLE) { - if (PU_Map[addr >> 12] & 0x10) + if (IsAddressDCachable(addr)) { DCacheWrite32(addr, val); - // DCacheInvalidateByAddr(addr); } } } @@ -1720,7 +1675,7 @@ void ARMv5::DataWrite32S(u32 addr, u32 val) if (addr < ITCMSize) { DataCycles += 1; - *(u32*)&ITCM[addr & (ITCMPhysicalSize - 1)] = val; + *(u32*)&ITCM[addr & (ITCMPhysicalSize - 3)] = val; #ifdef JIT_ENABLED NDS.JIT.CheckAndInvalidate<0, ARMJIT_Memory::memregion_ITCM>(addr); #endif @@ -1729,23 +1684,16 @@ void ARMv5::DataWrite32S(u32 addr, u32 val) if ((addr & DTCMMask) == DTCMBase) { DataCycles += 1; - *(u32*)&DTCM[addr & (DTCMPhysicalSize - 1)] = val; + *(u32*)&DTCM[addr & (DTCMPhysicalSize - 3)] = val; return; } - BusWrite32(addr, val); - DataCycles += MemTimings[addr >> 12][3]; + BusWrite32(addr & ~3, val); + DataCycles += MemTimings[addr >> BUSCYCLES_MAP_GRANULARITY_LOG2][BUSCYCLES_S32]; } void ARMv5::GetCodeMemRegion(u32 addr, MemRegion* region) { - /*if (addr < ITCMSize) - { - region->Mem = ITCM; - region->Mask = 0x7FFF; - return; - }*/ - NDS.ARM9GetMemRegion(addr, false, &CodeMem); } diff --git a/src/CP15_Constants.h b/src/CP15_Constants.h new file mode 100644 index 00000000..80fadf31 --- /dev/null +++ b/src/CP15_Constants.h @@ -0,0 +1,131 @@ +/* + Copyright 2016-2023 melonDS team + + This file is part of melonDS. + + melonDS is free software: you can redistribute it and/or modify it under + the terms of the GNU General Public License as published by the Free + Software Foundation, either version 3 of the License, or (at your option) + any later version. + + melonDS is distributed in the hope that it will be useful, but WITHOUT ANY + WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS + FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. + + You should have received a copy of the GNU General Public License along + with melonDS. If not, see http://www.gnu.org/licenses/. +*/ + +#ifndef MELONDS_CP15CONSTANTS_H +#define MELONDS_CP15CONSTANTS_H + +#include "types.h" + +namespace melonDS +{ + +/* ICACHE Layout constants */ +constexpr u32 ICACHE_SIZE_LOG2 = 13; +constexpr u32 ICACHE_SIZE = 1 << ICACHE_SIZE_LOG2; +constexpr u32 ICACHE_SETS_LOG2 = 2; +constexpr u32 ICACHE_SETS = 1 << ICACHE_SETS_LOG2; +constexpr u32 ICACHE_LINELENGTH_ENCODED = 2; +constexpr u32 ICACHE_LINELENGTH_LOG2 = ICACHE_LINELENGTH_ENCODED + 3; +constexpr u32 ICACHE_LINELENGTH = 8 * (1 << ICACHE_LINELENGTH_ENCODED); +constexpr u32 ICACHE_LINESPERSET = ICACHE_SIZE / (ICACHE_SETS * ICACHE_LINELENGTH); + +/* DCACHE Layout constants */ +constexpr u32 DCACHE_SIZE_LOG2 = 12; +constexpr u32 DCACHE_SIZE = 1 << DCACHE_SIZE_LOG2; +constexpr u32 DCACHE_SETS_LOG2 = 2; +constexpr u32 DCACHE_SETS = 1 << DCACHE_SETS_LOG2; +constexpr u32 DCACHE_LINELENGTH_ENCODED = 2; +constexpr u32 DCACHE_LINELENGTH_LOG2 = DCACHE_LINELENGTH_ENCODED + 3; +constexpr u32 DCACHE_LINELENGTH = 8 * (1 << DCACHE_LINELENGTH_ENCODED); +constexpr u32 DCACHE_LINESPERSET = DCACHE_SIZE / (DCACHE_SETS * DCACHE_LINELENGTH); + +/* CP15 Cache Data TAGs */ +constexpr u32 CACHE_FLAG_VALID = (1 << 4); +constexpr u32 CACHE_FLAG_DIRTY_LOWERHALF = (1 << 2); +constexpr u32 CACHE_FLAG_DIRTY_UPPERHALF = (1 << 3); +constexpr u32 CACHE_FLAG_DIRTY_MASK = (3 << 2); +constexpr u32 CACHE_FLAG_SET_MASK = (3 << 0); + +/* CP15 Cache Type Register */ +constexpr u32 CACHE_TR_LOCKDOWN_TYPE_B = (7 << 25); +constexpr u32 CACHE_TR_NONUNIFIED = (1 << 24); + +/* CP15 I/DCache LockDown registers */ +constexpr u32 CACHE_LOCKUP_L = (1 << 31); + +/* CP15 Main ID register */ +constexpr u32 CP15_MAINID_IMPLEMENTOR_ARM = (0x41 << 24); +constexpr u32 CP15_MAINID_IMPLEMENTOR_DEC = (0x44 << 24); +constexpr u32 CP15_MAINID_IMPLEMENTOR_MOTOROLA = (0x4D << 24); +constexpr u32 CP15_MAINID_IMPLEMENTOR_MARVELL = (0x56 << 24); +constexpr u32 CP15_MAINID_IMPLEMENTOR_INTEL = (0x69 << 24); +constexpr u32 CP15_MAINID_VARIANT_0 = (0 << 20); +constexpr u32 CP15_MAINID_ARCH_v4 = (1 << 16); +constexpr u32 CP15_MAINID_ARCH_v4T = (2 << 16); +constexpr u32 CP15_MAINID_ARCH_v5 = (3 << 16); +constexpr u32 CP15_MAINID_ARCH_v5T = (4 << 16); +constexpr u32 CP15_MAINID_ARCH_v5TE = (5 << 16); +constexpr u32 CP15_MAINID_ARCH_v5TEJ = (6 << 16); +constexpr u32 CP15_MAINID_ARCH_v6 = (7 << 16); +constexpr u32 CP15_MAINID_IMPLEMENTATION_946 = (0x946 << 4); +constexpr u32 CP15_MAINID_REVISION_0 = (0 << 0); +constexpr u32 CP15_MAINID_REVISION_1 = (1 << 0); + +/* CP15 Control Register */ +constexpr u32 CP15_CR_MPUENABLE = (1 << 0); +constexpr u32 CP15_CR_BIGENDIAN = (1 << 7); +constexpr u32 CP15_CR_HIGHEXCEPTIONBASE = (1 << 13); + +/* CP15 Internal Exception base value */ +constexpr u32 CP15_EXCEPTIONBASE_HIGH = 0xFFFF0000; +constexpr u32 CP15_EXCEPTIONBASE_LOW = 0x00000000; + +/* CP15 Cache and Write Buffer Conrol Register */ +constexpr u32 CP15_CACHE_CR_ROUNDROBIN = (1 << 14); +constexpr u32 CP15_CACHE_CR_ICACHEENABLE = (1 << 12); +constexpr u32 CP15_CACHE_CR_DCACHEENABLE = (1 << 2); +constexpr u32 CP15_CACHE_CR_WRITEBUFFERENABLE = (1 << 3); + +/* CP15 TCM Control Register */ +constexpr u32 CP15_TCM_CR_DTCM_ENABLE = (1 << 16); +constexpr u32 CP15_TCM_CR_ITCM_ENABLE = (1 << 18); + +/* CP15 Region Base and Size Register */ +constexpr u32 CP15_REGION_COUNT = 8; +constexpr u32 CP15_REGION_ENABLE = (1 << 0); +constexpr u32 CP15_REGION_SIZE_MASK = (0x1F << 1); +constexpr u32 CP15_REGION_BASE_GRANULARITY_LOG2 = 12; +constexpr u32 CP15_REGION_BASE_GRANULARITY = (1 << CP15_REGION_BASE_GRANULARITY_LOG2); +constexpr u32 CP15_REGION_BASE_MASK = ~(CP15_REGION_BASE_GRANULARITY_LOG2-1); + +/* CP15 Region access mask registers */ +constexpr u32 CP15_REGIONACCESS_BITS_PER_REGION = 4; +constexpr u32 CP15_REGIONACCESS_REGIONMASK = (1 << CP15_REGIONACCESS_BITS_PER_REGION) - 1; + +/* Flags in the melonDS internal PU_PrivMap and PU_UserMap */ +constexpr u32 CP15_MAP_NOACCESS = 0x00; +constexpr u32 CP15_MAP_READABLE = 0x01; +constexpr u32 CP15_MAP_WRITEABLE = 0x02; +constexpr u32 CP15_MAP_EXECUTABLE = 0x04; +constexpr u32 CP15_MAP_DCACHEABLE = 0x10; +constexpr u32 CP15_MAP_DCACHEWRITEBACK = 0x20; +constexpr u32 CP15_MAP_ICACHEABLE = 0x40; + +constexpr u32 CP15_MAP_ENTRYSIZE_LOG2 = CP15_REGION_BASE_GRANULARITY_LOG2; +constexpr u32 CP15_MAP_ENTRYSIZE = (1 << CP15_MAP_ENTRYSIZE_LOG2); + +/* Internal Timing Constants */ +constexpr u32 BUSCYCLES_N16 = 0; +constexpr u32 BUSCYCLES_S16 = 1; +constexpr u32 BUSCYCLES_N32 = 2; +constexpr u32 BUSCYCLES_S32 = 3; + +constexpr u32 BUSCYCLES_MAP_GRANULARITY_LOG2 = CP15_REGION_BASE_GRANULARITY_LOG2; +} + +#endif // MELONDS_CP15CONSTANTS_H \ No newline at end of file diff --git a/src/MemConstants.h b/src/MemConstants.h index 332b9b18..e9aa6b2b 100644 --- a/src/MemConstants.h +++ b/src/MemConstants.h @@ -34,44 +34,6 @@ constexpr u32 ITCMPhysicalSize = 0x8000; constexpr u32 DTCMPhysicalSize = 0x4000; constexpr u32 ARM7BIOSCRC32 = 0x1280f0d5; constexpr u32 ARM9BIOSCRC32 = 0x2ab23573; - -constexpr u32 ICACHE_SIZE_LOG2 = 13; -constexpr u32 ICACHE_SIZE = 1 << ICACHE_SIZE_LOG2; -constexpr u32 ICACHE_SETS_LOG2 = 2; -constexpr u32 ICACHE_SETS = 1 << ICACHE_SETS_LOG2; -constexpr u32 ICACHE_LINELENGTH_ENCODED = 2; -constexpr u32 ICACHE_LINELENGTH_LOG2 = ICACHE_LINELENGTH_ENCODED + 3; -constexpr u32 ICACHE_LINELENGTH = 8 * (1 << ICACHE_LINELENGTH_ENCODED); -constexpr u32 ICACHE_LINESPERSET = ICACHE_SIZE / (ICACHE_SETS * ICACHE_LINELENGTH); - -constexpr u32 DCACHE_SIZE_LOG2 = 12; -constexpr u32 DCACHE_SIZE = 1 << DCACHE_SIZE_LOG2; -constexpr u32 DCACHE_SETS_LOG2 = 2; -constexpr u32 DCACHE_SETS = 1 << DCACHE_SETS_LOG2; -constexpr u32 DCACHE_LINELENGTH_ENCODED = 2; -constexpr u32 DCACHE_LINELENGTH_LOG2 = DCACHE_LINELENGTH_ENCODED + 3; -constexpr u32 DCACHE_LINELENGTH = 8 * (1 << DCACHE_LINELENGTH_ENCODED); -constexpr u32 DCACHE_LINESPERSET = DCACHE_SIZE / (DCACHE_SETS * DCACHE_LINELENGTH); - -constexpr u32 CACHE_FLAG_VALID = (1 << 4); -constexpr u32 CACHE_FLAG_DIRTY_LOWERHALF = (1 << 2); -constexpr u32 CACHE_FLAG_DIRTY_UPPERHALF = (1 << 3); - -constexpr u32 CACHE_TR_LOCKDOWN_TYPE_B = (7 << 25); -constexpr u32 CACHE_TR_NONUNIFIED = (1 << 24); - -constexpr u32 CACHE_LOCKUP_L = (1 << 31); - -constexpr u32 CP15_CR_MPUENABLE = (1 << 0); -constexpr u32 CP15_CR_BIGENDIAN = (1 << 7); -constexpr u32 CP15_CR_HIGHEXCEPTIONBASE = (1 << 13); -constexpr u32 CP15_CACHE_CR_ROUNDROBIN = (1 << 14); -constexpr u32 CP15_CACHE_CR_ICACHEENABLE = (1 << 12); -constexpr u32 CP15_CACHE_CR_DCACHEENABLE = (1 << 2); -constexpr u32 CP15_CACHE_CR_WRITEBUFFERENABLE = (1 << 3); -constexpr u32 CP15_TCM_CR_DTCM_ENABLE = (1 << 16); -constexpr u32 CP15_TCM_CR_ITCM_ENABLE = (1 << 18); - } #endif // MELONDS_MEMCONSTANTS_H \ No newline at end of file