mirror of
https://github.com/dolphin-emu/dolphin.git
synced 2025-02-19 02:36:27 +01:00
PowerPC: Handle translation if range given to InvalidateICache spans multiple BAT or Page Table pages.
This commit is contained in:
parent
57037a69f9
commit
df1e59409b
@ -183,13 +183,46 @@ const u8* JitBaseBlockCache::Dispatch()
|
|||||||
return block->normalEntry;
|
return block->normalEntry;
|
||||||
}
|
}
|
||||||
|
|
||||||
void JitBaseBlockCache::InvalidateICache(u32 address, u32 length, bool forced)
|
void JitBaseBlockCache::InvalidateICacheLine(u32 address)
|
||||||
{
|
{
|
||||||
const auto translated = PowerPC::JitCache_TranslateAddress(address);
|
const u32 cache_line_address = address & ~0x1f;
|
||||||
if (!translated.valid)
|
const auto translated = PowerPC::JitCache_TranslateAddress(cache_line_address);
|
||||||
return;
|
if (translated.valid)
|
||||||
const u32 physical_address = translated.address;
|
InvalidateICacheInternal(translated.address, cache_line_address, 32, false);
|
||||||
|
}
|
||||||
|
|
||||||
|
void JitBaseBlockCache::InvalidateICache(u32 initial_address, u32 initial_length, bool forced)
|
||||||
|
{
|
||||||
|
u32 address = initial_address;
|
||||||
|
u32 length = initial_length;
|
||||||
|
while (length > 0)
|
||||||
|
{
|
||||||
|
const auto translated = PowerPC::JitCache_TranslateAddress(address);
|
||||||
|
|
||||||
|
const bool address_from_bat = translated.valid && translated.translated && translated.from_bat;
|
||||||
|
const int shift = address_from_bat ? PowerPC::BAT_INDEX_SHIFT : PowerPC::HW_PAGE_INDEX_SHIFT;
|
||||||
|
const u32 mask = ~((1u << shift) - 1u);
|
||||||
|
const u32 first_address = address;
|
||||||
|
const u32 last_address = address + (length - 1u);
|
||||||
|
if ((first_address & mask) == (last_address & mask))
|
||||||
|
{
|
||||||
|
if (translated.valid)
|
||||||
|
InvalidateICacheInternal(translated.address, address, length, forced);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
const u32 end_of_page = (first_address + (1u << shift)) & mask;
|
||||||
|
const u32 length_this_page = end_of_page - first_address;
|
||||||
|
if (translated.valid)
|
||||||
|
InvalidateICacheInternal(translated.address, address, length_this_page, forced);
|
||||||
|
address = address + length_this_page;
|
||||||
|
length = length - length_this_page;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void JitBaseBlockCache::InvalidateICacheInternal(u32 physical_address, u32 address, u32 length,
|
||||||
|
bool forced)
|
||||||
|
{
|
||||||
// Optimization for the case of invalidating a single cache line, which is used by the dcb*
|
// Optimization for the case of invalidating a single cache line, which is used by the dcb*
|
||||||
// instructions. If the valid_block bit for that cacheline is not set, we can safely skip
|
// instructions. If the valid_block bit for that cacheline is not set, we can safely skip
|
||||||
// the remaining invalidation logic.
|
// the remaining invalidation logic.
|
||||||
|
@ -161,6 +161,7 @@ public:
|
|||||||
const u8* Dispatch();
|
const u8* Dispatch();
|
||||||
|
|
||||||
void InvalidateICache(u32 address, u32 length, bool forced);
|
void InvalidateICache(u32 address, u32 length, bool forced);
|
||||||
|
void InvalidateICacheLine(u32 address);
|
||||||
void ErasePhysicalRange(u32 address, u32 length);
|
void ErasePhysicalRange(u32 address, u32 length);
|
||||||
|
|
||||||
u32* GetBlockBitSet() const;
|
u32* GetBlockBitSet() const;
|
||||||
@ -177,6 +178,7 @@ private:
|
|||||||
void LinkBlockExits(JitBlock& block);
|
void LinkBlockExits(JitBlock& block);
|
||||||
void LinkBlock(JitBlock& block);
|
void LinkBlock(JitBlock& block);
|
||||||
void UnlinkBlock(const JitBlock& block);
|
void UnlinkBlock(const JitBlock& block);
|
||||||
|
void InvalidateICacheInternal(u32 physical_address, u32 address, u32 length, bool forced);
|
||||||
|
|
||||||
JitBlock* MoveBlockIntoFastCache(u32 em_address, u32 msr);
|
JitBlock* MoveBlockIntoFastCache(u32 em_address, u32 msr);
|
||||||
|
|
||||||
|
@ -226,7 +226,8 @@ void InvalidateICache(u32 address, u32 size, bool forced)
|
|||||||
|
|
||||||
void InvalidateICacheLine(u32 address)
|
void InvalidateICacheLine(u32 address)
|
||||||
{
|
{
|
||||||
InvalidateICache(address & ~0x1f, 32, false);
|
if (g_jit)
|
||||||
|
g_jit->GetBlockCache()->InvalidateICacheLine(address);
|
||||||
}
|
}
|
||||||
|
|
||||||
void CompileExceptionCheck(ExceptionType type)
|
void CompileExceptionCheck(ExceptionType type)
|
||||||
|
@ -30,10 +30,6 @@
|
|||||||
|
|
||||||
namespace PowerPC
|
namespace PowerPC
|
||||||
{
|
{
|
||||||
constexpr size_t HW_PAGE_SIZE = 4096;
|
|
||||||
constexpr u32 HW_PAGE_INDEX_SHIFT = 12;
|
|
||||||
constexpr u32 HW_PAGE_INDEX_MASK = 0x3f;
|
|
||||||
|
|
||||||
// EFB RE
|
// EFB RE
|
||||||
/*
|
/*
|
||||||
GXPeekZ
|
GXPeekZ
|
||||||
|
@ -222,5 +222,9 @@ inline bool TranslateBatAddess(const BatTable& bat_table, u32* address, bool* wi
|
|||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
constexpr size_t HW_PAGE_SIZE = 4096;
|
||||||
|
constexpr u32 HW_PAGE_INDEX_SHIFT = 12;
|
||||||
|
constexpr u32 HW_PAGE_INDEX_MASK = 0x3f;
|
||||||
|
|
||||||
std::optional<u32> GetTranslatedAddress(u32 address);
|
std::optional<u32> GetTranslatedAddress(u32 address);
|
||||||
} // namespace PowerPC
|
} // namespace PowerPC
|
||||||
|
Loading…
x
Reference in New Issue
Block a user