Implemented DCache and several CP15 registers
This commit is contained in:
parent
b6b0197dd3
commit
0a07661b57
30
src/ARM.h
30
src/ARM.h
|
@ -311,11 +311,25 @@ public:
|
|||
u32 RandomLineIndex();
|
||||
|
||||
void ICacheLookup(u32 addr);
|
||||
bool IsAddressICachable(u32 addr);
|
||||
|
||||
void ICacheInvalidateAll();
|
||||
void ICacheInvalidateByAddr(u32 addr);
|
||||
void ICacheInvalidateBySetAndWay(u8 cacheSet, u8 cacheLine);
|
||||
|
||||
void ICacheInvalidateAll();
|
||||
bool IsAddressICachable(u32 addr);
|
||||
|
||||
void DCacheLookup(u32 addr);
|
||||
bool IsAddressDCachable(u32 addr);
|
||||
|
||||
void DCacheInvalidateAll();
|
||||
void DCacheInvalidateByAddr(u32 addr);
|
||||
void DCacheInvalidateBySetAndWay(u8 cacheSet, u8 cacheLine);
|
||||
|
||||
void DCacheClearAll();
|
||||
void DCacheClearByAddr(u32 addr);
|
||||
void DCacheClearByASetAndWay(u8 cacheSet, u8 cacheLine);
|
||||
|
||||
|
||||
|
||||
void CP15Write(u32 id, u32 val);
|
||||
u32 CP15Read(u32 id) const;
|
||||
|
@ -326,6 +340,7 @@ public:
|
|||
|
||||
u32 DTCMSetting, ITCMSetting;
|
||||
u32 DCacheLockDown, ICacheLockDown;
|
||||
u32 CacheDebugRegisterIndex;
|
||||
|
||||
// for aarch64 JIT they need to go up here
|
||||
// to be addressable by a 12-bit immediate
|
||||
|
@ -336,9 +351,13 @@ public:
|
|||
u8 ITCM[ITCMPhysicalSize];
|
||||
u8* DTCM;
|
||||
|
||||
u8 ICache[0x2000];
|
||||
u32 ICacheTags[64*4];
|
||||
u8 ICacheCount[64];
|
||||
u8 ICache[ICACHE_SIZE];
|
||||
u32 ICacheTags[ICACHE_LINESPERSET*ICACHE_SETS];
|
||||
u8 ICacheCount;
|
||||
|
||||
u8 DCache[DCACHE_SIZE];
|
||||
u32 DCacheTags[DCACHE_LINESPERSET*DCACHE_SETS];
|
||||
u8 DCacheCount;
|
||||
|
||||
u32 PU_CodeCacheable;
|
||||
u32 PU_DataCacheable;
|
||||
|
@ -361,6 +380,7 @@ public:
|
|||
u8 MemTimings[0x100000][4];
|
||||
|
||||
u8* CurICacheLine;
|
||||
u8* CurDCacheLine;
|
||||
|
||||
bool (*GetMemRegion)(u32 addr, bool write, MemRegion* region);
|
||||
|
||||
|
|
355
src/CP15.cpp
355
src/CP15.cpp
|
@ -57,10 +57,15 @@ void ARMv5::CP15Reset()
|
|||
|
||||
ICacheLockDown = 0;
|
||||
DCacheLockDown = 0;
|
||||
CacheDebugRegisterIndex = 0;
|
||||
|
||||
memset(ICache, 0, ICACHE_SIZE);
|
||||
ICacheInvalidateAll();
|
||||
memset(ICacheCount, 0, ICACHE_LINESPERSET);
|
||||
ICacheCount = 0;
|
||||
|
||||
memset(DCache, 0, DCACHE_SIZE);
|
||||
DCacheInvalidateAll();
|
||||
DCacheCount = 0;
|
||||
|
||||
PU_CodeCacheable = 0;
|
||||
PU_DataCacheable = 0;
|
||||
|
@ -87,8 +92,17 @@ void ARMv5::CP15DoSavestate(Savestate* file)
|
|||
file->VarArray(ITCM, ITCMPhysicalSize);
|
||||
file->VarArray(DTCM, DTCMPhysicalSize);
|
||||
|
||||
file->VarArray(ICache, sizeof(ICache));
|
||||
file->VarArray(ICacheTags, sizeof(ICacheTags));
|
||||
file->Var8(&ICacheCount);
|
||||
|
||||
file->VarArray(DCache, sizeof(DCache));
|
||||
file->VarArray(DCacheTags, sizeof(DCacheTags));
|
||||
file->Var8(&DCacheCount);
|
||||
|
||||
file->Var32(&DCacheLockDown);
|
||||
file->Var32(&ICacheLockDown);
|
||||
file->Var32(&CacheDebugRegisterIndex);
|
||||
|
||||
file->Var32(&PU_CodeCacheable);
|
||||
file->Var32(&PU_DataCacheable);
|
||||
|
@ -340,13 +354,13 @@ u32 ARMv5::RandomLineIndex()
|
|||
|
||||
void ARMv5::ICacheLookup(u32 addr)
|
||||
{
|
||||
u32 tag = addr & ~(ICACHE_LINESPERSET * ICACHE_LINELENGTH - 1);
|
||||
u32 tag = (addr & ~(ICACHE_LINELENGTH - 1)) | CACHE_FLAG_VALID;
|
||||
u32 id = (addr >> ICACHE_LINELENGTH_LOG2) & (ICACHE_LINESPERSET-1);
|
||||
|
||||
id <<= ICACHE_SETS_LOG2;
|
||||
for (int set=0;set<ICACHE_SETS;set++)
|
||||
{
|
||||
if (ICacheTags[id+set] == tag)
|
||||
if ((ICacheTags[id+set] & ~0x0F) == (tag &~0x0F))
|
||||
{
|
||||
CodeCycles = 1;
|
||||
CurICacheLine = &ICache[(id+set) << ICACHE_LINELENGTH_LOG2];
|
||||
|
@ -358,8 +372,8 @@ void ARMv5::ICacheLookup(u32 addr)
|
|||
u32 line;
|
||||
if (CP15Control & CP15_CACHE_CR_ROUNDROBIN)
|
||||
{
|
||||
line = ICacheCount[id>>ICACHE_SETS_LOG2];
|
||||
ICacheCount[id>>ICACHE_SETS_LOG2] = (line+1) & (ICACHE_SETS-1);
|
||||
line = ICacheCount;
|
||||
ICacheCount = (line+1) & (ICACHE_SETS-1);
|
||||
}
|
||||
else
|
||||
{
|
||||
|
@ -381,7 +395,7 @@ void ARMv5::ICacheLookup(u32 addr)
|
|||
*(u32*)&ptr[i] = NDS.ARM9Read32(addr+i);
|
||||
}
|
||||
|
||||
ICacheTags[line] = tag;
|
||||
ICacheTags[line] = addr | (line & (ICACHE_SETS-1)) | CACHE_FLAG_VALID;
|
||||
|
||||
// ouch :/
|
||||
//printf("cache miss %08X: %d/%d\n", addr, NDS::ARM9MemTimings[addr >> 14][2], NDS::ARM9MemTimings[addr >> 14][3]);
|
||||
|
@ -391,18 +405,15 @@ void ARMv5::ICacheLookup(u32 addr)
|
|||
|
||||
void ARMv5::ICacheInvalidateByAddr(u32 addr)
|
||||
{
|
||||
u32 tag = addr & ~(ICACHE_LINESPERSET * ICACHE_LINELENGTH - 1);
|
||||
u32 tag = (addr & ~(ICACHE_LINELENGTH - 1)) | CACHE_FLAG_VALID;
|
||||
u32 id = (addr >> ICACHE_LINELENGTH_LOG2) & (ICACHE_LINESPERSET-1);
|
||||
|
||||
id <<= ICACHE_SETS_LOG2;
|
||||
for (int set=0;set<ICACHE_SETS;set++)
|
||||
{
|
||||
if (ICacheTags[id+set] == tag)
|
||||
if ((ICacheTags[id+set] & ~0x0F) == tag)
|
||||
{
|
||||
// TODO: is this a valid magic number?
|
||||
// it should indicate that no address is loaded here, instead
|
||||
// a tag of 1 indicates that addr 0x00000800.. 0x0000FBF (depending on id) ist stored at this set.
|
||||
ICacheTags[id+set] = 1;
|
||||
ICacheTags[id+set] &= ~CACHE_FLAG_VALID; ;
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
@ -416,20 +427,14 @@ void ARMv5::ICacheInvalidateBySetAndWay(u8 cacheSet, u8 cacheLine)
|
|||
return;
|
||||
|
||||
u32 idx = (cacheLine << ICACHE_SETS_LOG2) + cacheSet;
|
||||
// TODO: is this a valid magic number?
|
||||
// it should indicate that no address is loaded here, instead
|
||||
// a tag of 1 indicates that addr 0x00000800.. 0x0000FBF (depending on id) ist stored at this set.
|
||||
ICacheTags[idx] = 1;
|
||||
ICacheTags[idx] &= ~CACHE_FLAG_VALID; ;
|
||||
}
|
||||
|
||||
|
||||
void ARMv5::ICacheInvalidateAll()
|
||||
{
|
||||
// TODO: is this a valid magic number?
|
||||
// it should indicate that no address is loaded here, instead
|
||||
// a tag of 1 indicates that addr 0x00000800.. 0x0000FBF (depending on id) ist stored at this set.
|
||||
for (int i = 0; i < ICACHE_SIZE / ICACHE_LINELENGTH; i++)
|
||||
ICacheTags[i] = 1;
|
||||
ICacheTags[i] &= ~CACHE_FLAG_VALID; ;
|
||||
}
|
||||
|
||||
bool ARMv5::IsAddressICachable(u32 addr)
|
||||
|
@ -437,6 +442,126 @@ bool ARMv5::IsAddressICachable(u32 addr)
|
|||
return PU_Map[addr >> 12] & 0x40 ;
|
||||
}
|
||||
|
||||
void ARMv5::DCacheLookup(u32 addr)
|
||||
{
|
||||
//Log(LogLevel::Debug,"DCache load @ %08x\n", addr);
|
||||
addr &= ~3;
|
||||
u32 tag = (addr & ~(DCACHE_LINELENGTH - 1)) | CACHE_FLAG_VALID;
|
||||
u32 id = (addr >> DCACHE_LINELENGTH_LOG2) & (DCACHE_LINESPERSET-1);
|
||||
|
||||
id <<= DCACHE_SETS_LOG2;
|
||||
for (int set=0;set<DCACHE_SETS;set++)
|
||||
{
|
||||
if ((DCacheTags[id+set] & ~0x0F) == tag)
|
||||
{
|
||||
DataCycles = 1;
|
||||
CurDCacheLine = &DCache[(id+set) << DCACHE_LINELENGTH_LOG2];
|
||||
//Log(LogLevel::Debug,"DCache hit @ %08x -> %08lx\n", addr, ((u32 *)CurDCacheLine)[(addr & (DCACHE_LINELENGTH-1)) >> 2]);
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
// cache miss
|
||||
u32 line;
|
||||
if (CP15Control & CP15_CACHE_CR_ROUNDROBIN)
|
||||
{
|
||||
line = DCacheCount;
|
||||
DCacheCount = (line+1) & (DCACHE_SETS-1);
|
||||
}
|
||||
else
|
||||
{
|
||||
line = RandomLineIndex();
|
||||
}
|
||||
|
||||
line += id;
|
||||
|
||||
addr &= ~(DCACHE_LINELENGTH-1);
|
||||
u8* ptr = &DCache[line << DCACHE_LINELENGTH_LOG2];
|
||||
|
||||
//Log(LogLevel::Debug,"DCache miss, load @ %08x\n", addr);
|
||||
for (int i = 0; i < DCACHE_LINELENGTH; i+=sizeof(u32))
|
||||
{
|
||||
//DataRead32S(addr+i, (u32*)&ptr[i]);
|
||||
if (addr+i < ITCMSize)
|
||||
{
|
||||
*((u32*)&ptr[i]) = *(u32*)&ITCM[addr & (ITCMPhysicalSize - 1)];
|
||||
} else
|
||||
if (((addr+i) & DTCMMask) == DTCMBase)
|
||||
{
|
||||
*((u32*)&ptr[i]) = *(u32*)&DTCM[addr & (DTCMPhysicalSize - 1)];
|
||||
} else
|
||||
{
|
||||
*((u32*)&ptr[i]) = BusRead32(addr+i);
|
||||
|
||||
}
|
||||
//Log(LogLevel::Debug,"DCache store @ %08x: %08x\n", addr+i, *(u32*)&ptr[i]);
|
||||
}
|
||||
|
||||
DCacheTags[line] = addr | (line & (DCACHE_SETS-1)) | CACHE_FLAG_VALID;
|
||||
|
||||
// ouch :/
|
||||
//printf("cache miss %08X: %d/%d\n", addr, NDS::ARM9MemTimings[addr >> 14][2], NDS::ARM9MemTimings[addr >> 14][3]);
|
||||
DataCycles = (NDS.ARM9MemTimings[addr >> 14][2] + (NDS.ARM9MemTimings[addr >> 14][3] * 7)) << NDS.ARM9ClockShift;
|
||||
CurDCacheLine = ptr;
|
||||
}
|
||||
|
||||
void ARMv5::DCacheInvalidateByAddr(u32 addr)
|
||||
{
|
||||
u32 tag = (addr & ~(DCACHE_LINELENGTH - 1)) | CACHE_FLAG_VALID;
|
||||
u32 id = (addr >> DCACHE_LINELENGTH_LOG2) & (DCACHE_LINESPERSET-1);
|
||||
|
||||
id <<= DCACHE_SETS_LOG2;
|
||||
for (int set=0;set<DCACHE_SETS;set++)
|
||||
{
|
||||
if ((DCacheTags[id+set] & ~0x0Ful) == tag)
|
||||
{
|
||||
//Log(LogLevel::Debug,"DCache invalidated %08lx\n", addr & ~(ICACHE_LINELENGTH-1));
|
||||
DCacheTags[id+set] &= ~CACHE_FLAG_VALID; ;
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void ARMv5::DCacheInvalidateBySetAndWay(u8 cacheSet, u8 cacheLine)
|
||||
{
|
||||
if (cacheSet >= DCACHE_SETS)
|
||||
return;
|
||||
if (cacheLine >= DCACHE_LINESPERSET)
|
||||
return;
|
||||
|
||||
u32 idx = (cacheLine << DCACHE_SETS_LOG2) + cacheSet;
|
||||
DCacheTags[idx] &= ~CACHE_FLAG_VALID; ;
|
||||
}
|
||||
|
||||
|
||||
void ARMv5::DCacheInvalidateAll()
|
||||
{
|
||||
for (int i = 0; i < DCACHE_SIZE / DCACHE_LINELENGTH; i++)
|
||||
DCacheTags[i] &= ~CACHE_FLAG_VALID; ;
|
||||
}
|
||||
|
||||
void ARMv5::DCacheClearAll()
|
||||
{
|
||||
// TODO: right now any write to cached data goes straight to the
|
||||
// underlying memory and invalidates the cache line.
|
||||
}
|
||||
|
||||
void ARMv5::DCacheClearByAddr(u32 addr)
|
||||
{
|
||||
// TODO: right now any write to cached data goes straight to the
|
||||
// underlying memory and invalidates the cache line.
|
||||
}
|
||||
|
||||
void ARMv5::DCacheClearByASetAndWay(u8 cacheSet, u8 cacheLine)
|
||||
{
|
||||
// TODO: right now any write to cached data goes straight to the
|
||||
// underlying memory and invalidates the cache line.
|
||||
}
|
||||
|
||||
bool ARMv5::IsAddressDCachable(u32 addr)
|
||||
{
|
||||
return PU_Map[addr >> 12] & 0x10 ;
|
||||
}
|
||||
|
||||
void ARMv5::CP15Write(u32 id, u32 val)
|
||||
{
|
||||
|
@ -623,23 +748,75 @@ void ARMv5::CP15Write(u32 id, u32 val)
|
|||
return;
|
||||
|
||||
|
||||
case 0x761:
|
||||
case 0x760:
|
||||
DCacheInvalidateAll();
|
||||
//printf("inval data cache %08X\n", val);
|
||||
return;
|
||||
case 0x762:
|
||||
case 0x761:
|
||||
DCacheInvalidateByAddr(val);
|
||||
//printf("inval data cache SI\n");
|
||||
return;
|
||||
case 0x762:
|
||||
{
|
||||
// Cache invalidat by line number and set number
|
||||
u8 cacheSet = val >> (32 - DCACHE_SETS_LOG2) & (DCACHE_SETS -1);
|
||||
u8 cacheLine = (val >> DCACHE_LINELENGTH_LOG2) & (DCACHE_LINESPERSET -1);
|
||||
DCacheInvalidateBySetAndWay(cacheSet, cacheLine);
|
||||
}
|
||||
return;
|
||||
|
||||
case 0x770:
|
||||
// invalidate both caches
|
||||
ICacheInvalidateAll();
|
||||
DCacheInvalidateAll();
|
||||
break;
|
||||
|
||||
case 0x7A0:
|
||||
//Log(LogLevel::Debug,"clean data cache\n");
|
||||
DCacheClearAll();
|
||||
return;
|
||||
case 0x7A1:
|
||||
//printf("flush data cache %08X\n", val);
|
||||
//Log(LogLevel::Debug,"clean data cache MVA\n");
|
||||
DCacheClearByAddr(val);
|
||||
return;
|
||||
case 0x7A2:
|
||||
//printf("flush data cache SI\n");
|
||||
//Log(LogLevel::Debug,"clean data cache SET/WAY\n");
|
||||
{
|
||||
// Cache invalidat by line number and set number
|
||||
u8 cacheSet = val >> (32 - DCACHE_SETS_LOG2) & (DCACHE_SETS -1);
|
||||
u8 cacheLine = (val >> DCACHE_LINELENGTH_LOG2) & (DCACHE_LINESPERSET -1);
|
||||
DCacheClearByASetAndWay(cacheSet, cacheLine);
|
||||
}
|
||||
return;
|
||||
case 0x7A3:
|
||||
// Test and clean (optional)
|
||||
// Is not present on the NDS/DSi
|
||||
return;
|
||||
return;
|
||||
|
||||
case 0x7D1:
|
||||
Log(LogLevel::Debug,"Prefetch instruction cache MVA\n");
|
||||
break;
|
||||
|
||||
case 0x7E0:
|
||||
//Log(LogLevel::Debug,"clean & invalidate data cache\n");
|
||||
DCacheClearAll();
|
||||
DCacheInvalidateAll();
|
||||
return;
|
||||
case 0x7E1:
|
||||
//Log(LogLevel::Debug,"clean & invalidate data cache MVA\n");
|
||||
DCacheClearByAddr(val);
|
||||
DCacheInvalidateByAddr(val);
|
||||
return;
|
||||
case 0x7E2:
|
||||
//Log(LogLevel::Debug,"clean & invalidate data cache SET/WAY\n");
|
||||
{
|
||||
// Cache invalidat by line number and set number
|
||||
u8 cacheSet = val >> (32 - DCACHE_SETS_LOG2) & (DCACHE_SETS -1);
|
||||
u8 cacheLine = (val >> DCACHE_LINELENGTH_LOG2) & (DCACHE_LINESPERSET -1);
|
||||
DCacheClearByASetAndWay(cacheSet, cacheLine);
|
||||
DCacheInvalidateBySetAndWay(cacheSet, cacheLine);
|
||||
}
|
||||
return;
|
||||
|
||||
case 0x900:
|
||||
// Cache Lockdown - Format B
|
||||
|
@ -648,6 +825,7 @@ void ARMv5::CP15Write(u32 id, u32 val)
|
|||
// The Cache is 4 way associative
|
||||
// But all bits are r/w
|
||||
DCacheLockDown = val ;
|
||||
Log(LogLevel::Debug,"ICacheLockDown\n");
|
||||
return;
|
||||
case 0x901:
|
||||
// Cache Lockdown - Format B
|
||||
|
@ -656,6 +834,7 @@ void ARMv5::CP15Write(u32 id, u32 val)
|
|||
// The Cache is 4 way associative
|
||||
// But all bits are r/w
|
||||
ICacheLockDown = val;
|
||||
Log(LogLevel::Debug,"ICacheLockDown\n");
|
||||
return;
|
||||
|
||||
case 0x910:
|
||||
|
@ -669,16 +848,27 @@ void ARMv5::CP15Write(u32 id, u32 val)
|
|||
return;
|
||||
|
||||
case 0xF00:
|
||||
//printf("cache debug index register %08X\n", val);
|
||||
CacheDebugRegisterIndex = val;
|
||||
return;
|
||||
|
||||
case 0xF10:
|
||||
//printf("cache debug instruction tag %08X\n", val);
|
||||
return;
|
||||
// instruction cache Tag register
|
||||
{
|
||||
uint8_t segment = (CacheDebugRegisterIndex >> (32-ICACHE_SETS_LOG2)) & (ICACHE_SETS-1);
|
||||
uint8_t wordAddress = (CacheDebugRegisterIndex & (ICACHE_LINELENGTH-1)) >> 2;
|
||||
uint8_t index = (CacheDebugRegisterIndex >> ICACHE_LINELENGTH_LOG2) & (ICACHE_LINESPERSET-1);
|
||||
ICacheTags[(index << ICACHE_SETS_LOG2) + segment] = val;
|
||||
}
|
||||
|
||||
case 0xF20:
|
||||
//printf("cache debug data tag %08X\n", val);
|
||||
return;
|
||||
// data cache Tag register
|
||||
{
|
||||
uint8_t segment = (CacheDebugRegisterIndex >> (32-DCACHE_SETS_LOG2)) & (DCACHE_SETS-1);
|
||||
uint8_t wordAddress = (CacheDebugRegisterIndex & (DCACHE_LINELENGTH-1)) >> 2;
|
||||
uint8_t index = (CacheDebugRegisterIndex >> DCACHE_LINELENGTH_LOG2) & (DCACHE_LINESPERSET-1);
|
||||
DCacheTags[(index << DCACHE_SETS_LOG2) + segment] = val;
|
||||
}
|
||||
|
||||
|
||||
case 0xF30:
|
||||
//printf("cache debug instruction cache %08X\n", val);
|
||||
|
@ -794,6 +984,27 @@ u32 ARMv5::CP15Read(u32 id) const
|
|||
return DTCMSetting;
|
||||
case 0x911:
|
||||
return ITCMSetting;
|
||||
|
||||
case 0xF00:
|
||||
return CacheDebugRegisterIndex;
|
||||
case 0xF10:
|
||||
// instruction cache Tag register
|
||||
{
|
||||
uint8_t segment = (CacheDebugRegisterIndex >> (32-ICACHE_SETS_LOG2)) & (ICACHE_SETS-1);
|
||||
uint8_t wordAddress = (CacheDebugRegisterIndex & (ICACHE_LINELENGTH-1)) >> 2;
|
||||
uint8_t index = (CacheDebugRegisterIndex >> ICACHE_LINELENGTH_LOG2) & (ICACHE_LINESPERSET-1);
|
||||
Log(LogLevel::Debug, "Read ICache Tag %08lx -> %08lx\n", CacheDebugRegisterIndex, ICacheTags[(index << ICACHE_SETS_LOG2) + segment]);
|
||||
return ICacheTags[(index << ICACHE_SETS_LOG2) + segment];
|
||||
}
|
||||
case 0xF20:
|
||||
// data cache Tag register
|
||||
{
|
||||
uint8_t segment = (CacheDebugRegisterIndex >> (32-DCACHE_SETS_LOG2)) & (DCACHE_SETS-1);
|
||||
uint8_t wordAddress = (CacheDebugRegisterIndex & (DCACHE_LINELENGTH-1)) >> 2;
|
||||
uint8_t index = (CacheDebugRegisterIndex >> DCACHE_LINELENGTH_LOG2) & (DCACHE_LINESPERSET-1);
|
||||
Log(LogLevel::Debug, "Read DCache Tag %08lx (%u, %02x, %u) -> %08lx\n", CacheDebugRegisterIndex, segment, index, wordAddress, DCacheTags[(index << DCACHE_SETS_LOG2) + segment]);
|
||||
return DCacheTags[(index << DCACHE_SETS_LOG2) + segment];
|
||||
}
|
||||
}
|
||||
|
||||
if ((id & 0xF00) == 0xF00) // test/debug shit?
|
||||
|
@ -860,6 +1071,19 @@ void ARMv5::DataRead8(u32 addr, u32* val)
|
|||
return;
|
||||
}
|
||||
|
||||
#if 1
|
||||
if (CP15Control & CP15_CACHE_CR_DCACHEENABLE)
|
||||
{
|
||||
if (PU_Map[addr >> 12] & 0x10)
|
||||
{
|
||||
DCacheLookup(addr & ~3);
|
||||
DataCycles = 1;
|
||||
*val = CurDCacheLine[addr & (DCACHE_LINELENGTH - 1)];
|
||||
return;
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
DataRegion = addr;
|
||||
|
||||
if (addr < ITCMSize)
|
||||
|
@ -887,6 +1111,19 @@ void ARMv5::DataRead16(u32 addr, u32* val)
|
|||
return;
|
||||
}
|
||||
|
||||
#if 1
|
||||
if (CP15Control & CP15_CACHE_CR_DCACHEENABLE)
|
||||
{
|
||||
if (PU_Map[addr >> 12] & 0x10)
|
||||
{
|
||||
DCacheLookup(addr & ~3);
|
||||
DataCycles = 1;
|
||||
*val = *(u16 *)&CurDCacheLine[addr & (DCACHE_LINELENGTH - 2)];
|
||||
return;
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
DataRegion = addr;
|
||||
|
||||
addr &= ~1;
|
||||
|
@ -916,6 +1153,19 @@ void ARMv5::DataRead32(u32 addr, u32* val)
|
|||
return;
|
||||
}
|
||||
|
||||
#if 1
|
||||
if (CP15Control & CP15_CACHE_CR_DCACHEENABLE)
|
||||
{
|
||||
if (PU_Map[addr >> 12] & 0x10)
|
||||
{
|
||||
DCacheLookup(addr & ~3);
|
||||
DataCycles = 1;
|
||||
*val = *(u32 *)&CurDCacheLine[addr & (DCACHE_LINELENGTH - 4)];
|
||||
return;
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
DataRegion = addr;
|
||||
|
||||
addr &= ~3;
|
||||
|
@ -941,6 +1191,19 @@ void ARMv5::DataRead32S(u32 addr, u32* val)
|
|||
{
|
||||
addr &= ~3;
|
||||
|
||||
#if 1
|
||||
if (CP15Control & CP15_CACHE_CR_DCACHEENABLE)
|
||||
{
|
||||
if (PU_Map[addr >> 12] & 0x10)
|
||||
{
|
||||
DCacheLookup(addr & ~3);
|
||||
DataCycles = 1;
|
||||
*val = *(u32 *)&CurDCacheLine[addr & (DCACHE_LINELENGTH - 4)];
|
||||
return;
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
if (addr < ITCMSize)
|
||||
{
|
||||
DataCycles += 1;
|
||||
|
@ -966,6 +1229,14 @@ void ARMv5::DataWrite8(u32 addr, u8 val)
|
|||
return;
|
||||
}
|
||||
|
||||
if (CP15Control & CP15_CACHE_CR_DCACHEENABLE)
|
||||
{
|
||||
if (PU_Map[addr >> 12] & 0x10)
|
||||
{
|
||||
DCacheInvalidateByAddr(addr);
|
||||
}
|
||||
}
|
||||
|
||||
DataRegion = addr;
|
||||
|
||||
if (addr < ITCMSize)
|
||||
|
@ -994,6 +1265,14 @@ void ARMv5::DataWrite16(u32 addr, u16 val)
|
|||
return;
|
||||
}
|
||||
|
||||
if (CP15Control & CP15_CACHE_CR_DCACHEENABLE)
|
||||
{
|
||||
if (PU_Map[addr >> 12] & 0x10)
|
||||
{
|
||||
DCacheInvalidateByAddr(addr);
|
||||
}
|
||||
}
|
||||
|
||||
DataRegion = addr;
|
||||
|
||||
addr &= ~1;
|
||||
|
@ -1024,6 +1303,14 @@ void ARMv5::DataWrite32(u32 addr, u32 val)
|
|||
return;
|
||||
}
|
||||
|
||||
if (CP15Control & CP15_CACHE_CR_DCACHEENABLE)
|
||||
{
|
||||
if (PU_Map[addr >> 12] & 0x10)
|
||||
{
|
||||
DCacheInvalidateByAddr(addr);
|
||||
}
|
||||
}
|
||||
|
||||
DataRegion = addr;
|
||||
|
||||
addr &= ~3;
|
||||
|
@ -1050,6 +1337,14 @@ void ARMv5::DataWrite32S(u32 addr, u32 val)
|
|||
{
|
||||
addr &= ~3;
|
||||
|
||||
if (CP15Control & CP15_CACHE_CR_DCACHEENABLE)
|
||||
{
|
||||
if (PU_Map[addr >> 12] & 0x10)
|
||||
{
|
||||
DCacheInvalidateByAddr(addr);
|
||||
}
|
||||
}
|
||||
|
||||
if (addr < ITCMSize)
|
||||
{
|
||||
DataCycles += 1;
|
||||
|
|
|
@ -44,6 +44,19 @@ 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 CP15_CR_MPUENABLE = (1 << 0);
|
||||
constexpr u32 CP15_CR_BIGENDIAN = (1 << 7);
|
||||
constexpr u32 CP15_CR_HIGHEXCEPTIONBASE = (1 << 13);
|
||||
|
|
Loading…
Reference in New Issue