aboutsummaryrefslogtreecommitdiff
path: root/src/CP15.cpp
diff options
context:
space:
mode:
authorStapleButter <thetotalworm@gmail.com>2019-01-04 21:47:06 +0100
committerStapleButter <thetotalworm@gmail.com>2019-01-04 21:47:06 +0100
commit90f2c0834eac848e7840513d2abea433b7310ac8 (patch)
tree71d53e3f8bbe5a0e01d0b5b9b84be9af6ca0027a /src/CP15.cpp
parent1e35d18ce625161c10d9897b9fbedb7c865d5f3d (diff)
add PoC ARM9 instruction cache logic. not actually in use, but it's there as a reference (and if we ever need it).
Diffstat (limited to 'src/CP15.cpp')
-rw-r--r--src/CP15.cpp145
1 files changed, 140 insertions, 5 deletions
diff --git a/src/CP15.cpp b/src/CP15.cpp
index 8661364..7da41e8 100644
--- a/src/CP15.cpp
+++ b/src/CP15.cpp
@@ -35,6 +35,8 @@ void ARMv5::CP15Reset()
{
CP15Control = 0x2078; // dunno
+ RNGSeed = 44203;
+
DTCMSetting = 0;
ITCMSetting = 0;
@@ -45,6 +47,10 @@ void ARMv5::CP15Reset()
DTCMBase = 0xFFFFFFFF;
DTCMSize = 0;
+ memset(ICache, 0, 0x2000);
+ ICacheInvalidateAll();
+ memset(ICacheCount, 0, 64);
+
PU_CodeCacheable = 0;
PU_DataCacheable = 0;
PU_DataCacheWrite = 0;
@@ -54,6 +60,8 @@ void ARMv5::CP15Reset()
memset(PU_Region, 0, 8*sizeof(u32));
UpdatePURegions();
+
+ CurICacheLine = NULL;
}
void ARMv5::CP15DoSavestate(Savestate* file)
@@ -276,6 +284,119 @@ void ARMv5::UpdateRegionTimings(u32 addrstart, u32 addrend)
}
+u32 ARMv5::RandomLineIndex()
+{
+ // lame RNG, but good enough for this purpose
+ u32 s = RNGSeed;
+ RNGSeed ^= (s*17);
+ RNGSeed ^= (s*7);
+
+ return (RNGSeed >> 17) & 0x3;
+}
+
+int zog=1;
+void ARMv5::ICacheLookup(u32 addr)
+{
+ u32 tag = addr & 0xFFFFF800;
+ u32 id = (addr >> 5) & 0x3F;
+
+ id <<= 2;
+ if (ICacheTags[id+0] == tag)
+ {
+ CodeCycles = 1;zog=1;
+ CurICacheLine = &ICache[(id+0) << 5];
+ return;
+ }
+ if (ICacheTags[id+1] == tag)
+ {
+ CodeCycles = 1;zog=2;
+ CurICacheLine = &ICache[(id+1) << 5];
+ return;
+ }
+ if (ICacheTags[id+2] == tag)
+ {
+ CodeCycles = 1;zog=3;
+ CurICacheLine = &ICache[(id+2) << 5];
+ return;
+ }
+ if (ICacheTags[id+3] == tag)
+ {
+ CodeCycles = 1;zog=4;
+ CurICacheLine = &ICache[(id+3) << 5];
+ return;
+ }
+
+ // cache miss
+
+ u32 line;
+ if (CP15Control & (1<<14))
+ {
+ line = ICacheCount[id>>2];
+ ICacheCount[id>>2] = (line+1) & 0x3;
+ }
+ else
+ {
+ line = RandomLineIndex();
+ }
+
+ line += id;
+
+ addr &= ~0x1F;
+ u8* ptr = &ICache[line << 5];
+
+ if (CodeMem.Mem)
+ {
+ memcpy(ptr, &CodeMem.Mem[addr & CodeMem.Mask], 32);
+ }
+ else
+ {
+ for (int i = 0; i < 32; i+=4)
+ *(u32*)&ptr[i] = NDS::ARM9Read32(addr+i);
+ }
+
+ ICacheTags[line] = tag;
+
+ // ouch :/
+ //printf("cache miss %08X: %d/%d\n", addr, NDS::ARM9MemTimings[addr >> 14][2], NDS::ARM9MemTimings[addr >> 14][3]);
+ CodeCycles = (NDS::ARM9MemTimings[addr >> 14][2] + (NDS::ARM9MemTimings[addr >> 14][3] * 7)) << ClockShift;
+ CurICacheLine = ptr;
+}
+
+void ARMv5::ICacheInvalidateByAddr(u32 addr)
+{
+ u32 tag = addr & 0xFFFFF800;
+ u32 id = (addr >> 5) & 0x3F;
+
+ id <<= 2;
+ if (ICacheTags[id+0] == tag)
+ {
+ ICacheTags[id+0] = 1;
+ return;
+ }
+ if (ICacheTags[id+1] == tag)
+ {
+ ICacheTags[id+1] = 1;
+ return;
+ }
+ if (ICacheTags[id+2] == tag)
+ {
+ ICacheTags[id+2] = 1;
+ return;
+ }
+ if (ICacheTags[id+3] == tag)
+ {
+ ICacheTags[id+3] = 1;
+ return;
+ }
+}
+
+void ARMv5::ICacheInvalidateAll()
+{
+ for (int i = 0; i < 64*4; i++)
+ ICacheTags[i] = 1;
+}
+
+
void ARMv5::CP15Write(u32 id, u32 val)
{
//printf("CP15 write op %03X %08X %08X\n", id, val, NDS::ARM9->R[15]);
@@ -391,6 +512,17 @@ void ARMv5::CP15Write(u32 id, u32 val)
return;
+ case 0x750:
+ ICacheInvalidateAll();
+ return;
+ case 0x751:
+ ICacheInvalidateByAddr(val);
+ return;
+ case 0x752:
+ printf("CP15: ICACHE INVALIDATE WEIRD. %08X\n", val);
+ return;
+
+
case 0x761:
//printf("inval data cache %08X\n", val);
return;
@@ -519,7 +651,7 @@ u32 ARMv5::CP15Read(u32 id)
// TCM are handled here.
// TODO: later on, handle PU, and maybe caches
-u32 ARMv5::CodeRead32(u32 addr)
+u32 ARMv5::CodeRead32(u32 addr, bool branch)
{
if (addr < ITCMSize)
{
@@ -528,11 +660,14 @@ u32 ARMv5::CodeRead32(u32 addr)
}
CodeCycles = RegionCodeCycles;
- if (CodeCycles == 0xFF)
+ if (CodeCycles == 0xFF) // cached memory. hax
{
- // sort of code cache hit/miss average
- if (!(addr & 0x1F)) CodeCycles = kCodeCacheTiming;
- else CodeCycles = 1;
+ if (branch || !(addr & 0x1F))
+ CodeCycles = kCodeCacheTiming;//ICacheLookup(addr);
+ else
+ CodeCycles = 1;
+
+ //return *(u32*)&CurICacheLine[addr & 0x1C];
}
if (CodeMem.Mem) return *(u32*)&CodeMem.Mem[addr & CodeMem.Mask];