Merge pull request #11183 from TheLordScruffy/write-back-cache

Implement PowerPC data cache
This commit is contained in:
Admiral H. Curtiss
2023-01-09 17:09:32 +01:00
committed by GitHub
23 changed files with 611 additions and 183 deletions

View File

@ -189,6 +189,8 @@ static T ReadFromHardware(Memory::MemoryManager& memory, u32 em_address)
return static_cast<T>(var);
}
bool wi = false;
if (!never_translate && MSR.DR)
{
auto translated_addr = TranslateAddress<flag>(em_address);
@ -199,6 +201,7 @@ static T ReadFromHardware(Memory::MemoryManager& memory, u32 em_address)
return 0;
}
em_address = translated_addr.address;
wi = translated_addr.wi;
}
if (flag == XCheckTLBFlag::Read && (em_address & 0xF8000000) == 0x08000000)
@ -223,7 +226,18 @@ static T ReadFromHardware(Memory::MemoryManager& memory, u32 em_address)
// Handle RAM; the masking intentionally discards bits (essentially creating
// mirrors of memory).
T value;
std::memcpy(&value, &memory.GetRAM()[em_address & memory.GetRamMask()], sizeof(T));
em_address &= memory.GetRamMask();
if (!ppcState.m_enable_dcache || wi)
{
std::memcpy(&value, &memory.GetRAM()[em_address], sizeof(T));
}
else
{
ppcState.dCache.Read(em_address, &value, sizeof(T),
HID0.DLOCK || flag != XCheckTLBFlag::Read);
}
return bswap(value);
}
@ -231,7 +245,18 @@ static T ReadFromHardware(Memory::MemoryManager& memory, u32 em_address)
(em_address & 0x0FFFFFFF) < memory.GetExRamSizeReal())
{
T value;
std::memcpy(&value, &memory.GetEXRAM()[em_address & 0x0FFFFFFF], sizeof(T));
em_address &= 0x0FFFFFFF;
if (!ppcState.m_enable_dcache || wi)
{
std::memcpy(&value, &memory.GetEXRAM()[em_address], sizeof(T));
}
else
{
ppcState.dCache.Read(em_address + 0x10000000, &value, sizeof(T),
HID0.DLOCK || flag != XCheckTLBFlag::Read);
}
return bswap(value);
}
@ -396,14 +421,28 @@ static void WriteToHardware(Core::System& system, Memory::MemoryManager& memory,
{
// Handle RAM; the masking intentionally discards bits (essentially creating
// mirrors of memory).
std::memcpy(&memory.GetRAM()[em_address & memory.GetRamMask()], &swapped_data, size);
em_address &= memory.GetRamMask();
if (ppcState.m_enable_dcache && !wi)
ppcState.dCache.Write(em_address, &swapped_data, size, HID0.DLOCK);
if (!ppcState.m_enable_dcache || wi || flag != XCheckTLBFlag::Write)
std::memcpy(&memory.GetRAM()[em_address], &swapped_data, size);
return;
}
if (memory.GetEXRAM() && (em_address >> 28) == 0x1 &&
(em_address & 0x0FFFFFFF) < memory.GetExRamSizeReal())
{
std::memcpy(&memory.GetEXRAM()[em_address & 0x0FFFFFFF], &swapped_data, size);
em_address &= 0x0FFFFFFF;
if (ppcState.m_enable_dcache && !wi)
ppcState.dCache.Write(em_address + 0x10000000, &swapped_data, size, HID0.DLOCK);
if (!ppcState.m_enable_dcache || wi || flag != XCheckTLBFlag::Write)
std::memcpy(&memory.GetEXRAM()[em_address], &swapped_data, size);
return;
}
@ -1105,7 +1144,7 @@ void DMA_MemoryToLC(const u32 cache_address, const u32 mem_address, const u32 nu
memcpy(dst, src, 32 * num_blocks);
}
void ClearCacheLine(u32 address)
void ClearDCacheLine(u32 address)
{
DEBUG_ASSERT((address & 0x1F) == 0);
if (MSR.DR)
@ -1136,6 +1175,100 @@ void ClearCacheLine(u32 address)
WriteToHardware<XCheckTLBFlag::Write, true>(system, memory, address + i, 0, 4);
}
void StoreDCacheLine(u32 address)
{
address &= ~0x1F;
if (MSR.DR)
{
auto translated_address = TranslateAddress<XCheckTLBFlag::Write>(address);
if (translated_address.result == TranslateAddressResultEnum::DIRECT_STORE_SEGMENT)
{
return;
}
if (translated_address.result == TranslateAddressResultEnum::PAGE_FAULT)
{
// If translation fails, generate a DSI.
GenerateDSIException(address, true);
return;
}
address = translated_address.address;
}
if (ppcState.m_enable_dcache)
ppcState.dCache.Store(address);
}
void InvalidateDCacheLine(u32 address)
{
address &= ~0x1F;
if (MSR.DR)
{
auto translated_address = TranslateAddress<XCheckTLBFlag::Write>(address);
if (translated_address.result == TranslateAddressResultEnum::DIRECT_STORE_SEGMENT)
{
return;
}
if (translated_address.result == TranslateAddressResultEnum::PAGE_FAULT)
{
return;
}
address = translated_address.address;
}
if (ppcState.m_enable_dcache)
ppcState.dCache.Invalidate(address);
}
void FlushDCacheLine(u32 address)
{
address &= ~0x1F;
if (MSR.DR)
{
auto translated_address = TranslateAddress<XCheckTLBFlag::Write>(address);
if (translated_address.result == TranslateAddressResultEnum::DIRECT_STORE_SEGMENT)
{
return;
}
if (translated_address.result == TranslateAddressResultEnum::PAGE_FAULT)
{
// If translation fails, generate a DSI.
GenerateDSIException(address, true);
return;
}
address = translated_address.address;
}
if (ppcState.m_enable_dcache)
ppcState.dCache.Flush(address);
}
void TouchDCacheLine(u32 address, bool store)
{
address &= ~0x1F;
if (MSR.DR)
{
auto translated_address = TranslateAddress<XCheckTLBFlag::Write>(address);
if (translated_address.result == TranslateAddressResultEnum::DIRECT_STORE_SEGMENT)
{
return;
}
if (translated_address.result == TranslateAddressResultEnum::PAGE_FAULT)
{
// If translation fails, generate a DSI.
GenerateDSIException(address, true);
return;
}
address = translated_address.address;
}
if (ppcState.m_enable_dcache)
ppcState.dCache.Touch(address, store);
}
u32 IsOptimizableMMIOAccess(u32 address, u32 access_size)
{
if (PowerPC::memchecks.HasAny())