add PoC ARM9 instruction cache logic. not actually in use, but it's there as a reference (and if we ever need it).
This commit is contained in:
parent
1e35d18ce6
commit
90f2c0834e
36
src/ARM.cpp
36
src/ARM.cpp
|
@ -176,14 +176,14 @@ void ARMv5::JumpTo(u32 addr, bool restorecpsr)
|
|||
//if (addr == 0x0201764C) printf("capture test %d: R1=%08X\n", R[6], R[1]);
|
||||
//if (addr == 0x020175D8) printf("capture test %d: res=%08X\n", R[6], R[0]);
|
||||
// R0=DMA# R1=src R2=size
|
||||
//if (addr==0x02019A88) printf("[%08X] [%03d] GX FIFO CMD %08X\n", R[15], NDS::ARM9Read16(0x04000006), R[0]);
|
||||
//if (addr==0x02022A5C) printf("[%08X] [%03d|%04X] RENDE SHITO %08X\n", R[15], NDS::ARM9Read16(0x04000006), NDS::ARM9Read16(0x04000304), R[0]);
|
||||
|
||||
u32 oldregion = R[15] >> 24;
|
||||
u32 newregion = addr >> 24;
|
||||
|
||||
RegionCodeCycles = MemTimings[addr >> 12][0];
|
||||
|
||||
s32 cycles;
|
||||
|
||||
if (addr & 0x1)
|
||||
{
|
||||
addr &= ~0x1;
|
||||
|
@ -195,15 +195,16 @@ void ARMv5::JumpTo(u32 addr, bool restorecpsr)
|
|||
// doesn't matter if we put garbage in the MSbs there
|
||||
if (addr & 0x2)
|
||||
{
|
||||
NextInstr[0] = CodeRead32(addr-2) >> 16;
|
||||
NextInstr[1] = CodeRead32(addr+2);
|
||||
cycles = CodeCycles * 2;
|
||||
NextInstr[0] = CodeRead32(addr-2, true) >> 16;
|
||||
Cycles += CodeCycles;
|
||||
NextInstr[1] = CodeRead32(addr+2, false);
|
||||
Cycles += CodeCycles;
|
||||
}
|
||||
else
|
||||
{
|
||||
NextInstr[0] = CodeRead32(addr);
|
||||
NextInstr[0] = CodeRead32(addr, true);
|
||||
NextInstr[1] = NextInstr[0] >> 16;
|
||||
cycles = CodeCycles;
|
||||
Cycles += CodeCycles;
|
||||
}
|
||||
|
||||
CPSR |= 0x20;
|
||||
|
@ -215,9 +216,10 @@ void ARMv5::JumpTo(u32 addr, bool restorecpsr)
|
|||
|
||||
if (newregion != oldregion) SetupCodeMem(addr);
|
||||
|
||||
NextInstr[0] = CodeRead32(addr);
|
||||
NextInstr[1] = CodeRead32(addr+4);
|
||||
cycles = CodeCycles * 2;
|
||||
NextInstr[0] = CodeRead32(addr, true);
|
||||
Cycles += CodeCycles;
|
||||
NextInstr[1] = CodeRead32(addr+4, false);
|
||||
Cycles += CodeCycles;
|
||||
|
||||
CPSR &= ~0x20;
|
||||
}
|
||||
|
@ -231,8 +233,6 @@ void ARMv5::JumpTo(u32 addr, bool restorecpsr)
|
|||
PrefetchAbort();
|
||||
return;
|
||||
}*/
|
||||
|
||||
Cycles += cycles;
|
||||
}
|
||||
|
||||
void ARMv4::JumpTo(u32 addr, bool restorecpsr)
|
||||
|
@ -487,7 +487,7 @@ s32 ARMv5::Execute()
|
|||
CurInstr = NextInstr[0];
|
||||
NextInstr[0] = NextInstr[1];
|
||||
if (R[15] & 0x2) { NextInstr[1] >>= 16; CodeCycles = 0; }
|
||||
else NextInstr[1] = CodeRead32(R[15]);
|
||||
else NextInstr[1] = CodeRead32(R[15], false);
|
||||
|
||||
// actually execute
|
||||
u32 icode = (CurInstr >> 6) & 0x3FF;
|
||||
|
@ -499,7 +499,7 @@ s32 ARMv5::Execute()
|
|||
R[15] += 4;
|
||||
CurInstr = NextInstr[0];
|
||||
NextInstr[0] = NextInstr[1];
|
||||
NextInstr[1] = CodeRead32(R[15]);
|
||||
NextInstr[1] = CodeRead32(R[15], false);
|
||||
|
||||
// actually execute
|
||||
if (CheckCondition(CurInstr >> 28))
|
||||
|
@ -515,7 +515,7 @@ s32 ARMv5::Execute()
|
|||
AddCycles_C();
|
||||
}
|
||||
|
||||
//s32 diff = Cycles - lastcycles;arm9timer+=(diff>>1);
|
||||
//s32 diff = Cycles - lastcycles;
|
||||
//NDS::RunTightTimers(0, diff >> ClockShift);
|
||||
//lastcycles = Cycles - (diff & ClockDiffMask);
|
||||
|
||||
|
@ -543,7 +543,7 @@ s32 ARMv5::Execute()
|
|||
|
||||
/*if (Cycles > lastcycles)
|
||||
{
|
||||
//s32 diff = Cycles - lastcycles;arm9timer+=(diff>>1);
|
||||
s32 diff = Cycles - lastcycles;
|
||||
//NDS::RunTightTimers(0, diff >> ClockShift);
|
||||
}*/
|
||||
#ifdef DEBUG_CHECK_DESYNC
|
||||
|
@ -613,7 +613,7 @@ s32 ARMv4::Execute()
|
|||
AddCycles_C();
|
||||
}
|
||||
|
||||
//s32 diff = Cycles - lastcycles;arm7timer+=diff;
|
||||
//s32 diff = Cycles - lastcycles;
|
||||
//NDS::RunTightTimers(1, diff);
|
||||
//lastcycles = Cycles;
|
||||
|
||||
|
@ -641,7 +641,7 @@ s32 ARMv4::Execute()
|
|||
|
||||
/*if (Cycles > lastcycles)
|
||||
{
|
||||
//s32 diff = Cycles - lastcycles;arm7timer+=(diff);
|
||||
//s32 diff = Cycles - lastcycles;
|
||||
//NDS::RunTightTimers(1, diff);
|
||||
}*/
|
||||
|
||||
|
|
15
src/ARM.h
15
src/ARM.h
|
@ -173,7 +173,7 @@ public:
|
|||
s32 Execute();
|
||||
|
||||
// all code accesses are forced nonseq 32bit
|
||||
u32 CodeRead32(u32 addr);
|
||||
u32 CodeRead32(u32 addr, bool branch);
|
||||
|
||||
void DataRead8(u32 addr, u32* val);
|
||||
void DataRead16(u32 addr, u32* val);
|
||||
|
@ -233,11 +233,19 @@ public:
|
|||
|
||||
void UpdatePURegions();
|
||||
|
||||
u32 RandomLineIndex();
|
||||
|
||||
void ICacheLookup(u32 addr);
|
||||
void ICacheInvalidateByAddr(u32 addr);
|
||||
void ICacheInvalidateAll();
|
||||
|
||||
void CP15Write(u32 id, u32 val);
|
||||
u32 CP15Read(u32 id);
|
||||
|
||||
u32 CP15Control;
|
||||
|
||||
u32 RNGSeed;
|
||||
|
||||
u32 DTCMSetting, ITCMSetting;
|
||||
|
||||
u8 ITCM[0x8000];
|
||||
|
@ -245,6 +253,10 @@ public:
|
|||
u8 DTCM[0x4000];
|
||||
u32 DTCMBase, DTCMSize;
|
||||
|
||||
u8 ICache[0x2000];
|
||||
u32 ICacheTags[64*4];
|
||||
u8 ICacheCount[64];
|
||||
|
||||
u32 PU_CodeCacheable;
|
||||
u32 PU_DataCacheable;
|
||||
u32 PU_DataCacheWrite;
|
||||
|
@ -265,6 +277,7 @@ public:
|
|||
u8 MemTimings[0x100000][4];
|
||||
|
||||
s32 RegionCodeCycles;
|
||||
u8* CurICacheLine;
|
||||
};
|
||||
|
||||
class ARMv4 : public ARM
|
||||
|
|
145
src/CP15.cpp
145
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];
|
||||
|
|
Loading…
Reference in New Issue