MMU: Create constants for our BAT flags.
This avoids a few hard-coded constants in several files.
This commit is contained in:
parent
54e32fd91e
commit
5152c997a4
|
@ -229,12 +229,12 @@ void UpdateLogicalMemory(const PowerPC::BatTable& dbat_table)
|
||||||
logical_mapped_entries.clear();
|
logical_mapped_entries.clear();
|
||||||
for (u32 i = 0; i < (1 << (32 - PowerPC::BAT_INDEX_SHIFT)); ++i)
|
for (u32 i = 0; i < (1 << (32 - PowerPC::BAT_INDEX_SHIFT)); ++i)
|
||||||
{
|
{
|
||||||
if (dbat_table[i] & 1)
|
if (dbat_table[i] & PowerPC::BAT_MAPPED_BIT)
|
||||||
{
|
{
|
||||||
u32 logical_address = i << PowerPC::BAT_INDEX_SHIFT;
|
u32 logical_address = i << PowerPC::BAT_INDEX_SHIFT;
|
||||||
// TODO: Merge adjacent mappings to make this faster.
|
// TODO: Merge adjacent mappings to make this faster.
|
||||||
u32 logical_size = 1 << PowerPC::BAT_INDEX_SHIFT;
|
u32 logical_size = PowerPC::BAT_PAGE_SIZE;
|
||||||
u32 translated_address = dbat_table[i] & ~3;
|
u32 translated_address = dbat_table[i] & PowerPC::BAT_RESULT_MASK;
|
||||||
for (const auto& physical_region : physical_regions)
|
for (const auto& physical_region : physical_regions)
|
||||||
{
|
{
|
||||||
u32 mapping_address = physical_region.physical_address;
|
u32 mapping_address = physical_region.physical_address;
|
||||||
|
|
|
@ -347,7 +347,8 @@ void Jit64::dcbz(UGeckoInstruction inst)
|
||||||
// Perform lookup to see if we can use fast path.
|
// Perform lookup to see if we can use fast path.
|
||||||
MOV(32, R(RSCRATCH2), R(RSCRATCH));
|
MOV(32, R(RSCRATCH2), R(RSCRATCH));
|
||||||
SHR(32, R(RSCRATCH2), Imm8(PowerPC::BAT_INDEX_SHIFT));
|
SHR(32, R(RSCRATCH2), Imm8(PowerPC::BAT_INDEX_SHIFT));
|
||||||
TEST(32, MScaled(RSCRATCH2, SCALE_4, PtrOffset(&PowerPC::dbat_table[0])), Imm32(2));
|
TEST(32, MScaled(RSCRATCH2, SCALE_4, PtrOffset(&PowerPC::dbat_table[0])),
|
||||||
|
Imm32(PowerPC::BAT_PHYSICAL_BIT));
|
||||||
FixupBranch slow = J_CC(CC_Z, true);
|
FixupBranch slow = J_CC(CC_Z, true);
|
||||||
|
|
||||||
// Fast path: compute full address, then zero out 32 bytes of memory.
|
// Fast path: compute full address, then zero out 32 bytes of memory.
|
||||||
|
|
|
@ -105,7 +105,8 @@ FixupBranch EmuCodeBlock::CheckIfSafeAddress(const OpArg& reg_value, X64Reg reg_
|
||||||
|
|
||||||
// Perform lookup to see if we can use fast path.
|
// Perform lookup to see if we can use fast path.
|
||||||
SHR(32, R(scratch), Imm8(PowerPC::BAT_INDEX_SHIFT));
|
SHR(32, R(scratch), Imm8(PowerPC::BAT_INDEX_SHIFT));
|
||||||
TEST(32, MScaled(scratch, SCALE_4, PtrOffset(&PowerPC::dbat_table[0])), Imm32(2));
|
TEST(32, MScaled(scratch, SCALE_4, PtrOffset(&PowerPC::dbat_table[0])),
|
||||||
|
Imm32(PowerPC::BAT_PHYSICAL_BIT));
|
||||||
|
|
||||||
if (scratch == reg_addr)
|
if (scratch == reg_addr)
|
||||||
POP(scratch);
|
POP(scratch);
|
||||||
|
|
|
@ -109,7 +109,7 @@ struct TranslateAddressResult
|
||||||
bool Success() const { return result <= PAGE_TABLE_TRANSLATED; }
|
bool Success() const { return result <= PAGE_TABLE_TRANSLATED; }
|
||||||
};
|
};
|
||||||
template <const XCheckTLBFlag flag>
|
template <const XCheckTLBFlag flag>
|
||||||
static TranslateAddressResult TranslateAddress(const u32 address);
|
static TranslateAddressResult TranslateAddress(u32 address);
|
||||||
|
|
||||||
// Nasty but necessary. Super Mario Galaxy pointer relies on this stuff.
|
// Nasty but necessary. Super Mario Galaxy pointer relies on this stuff.
|
||||||
static u32 EFB_Read(const u32 addr)
|
static u32 EFB_Read(const u32 addr)
|
||||||
|
@ -623,7 +623,7 @@ bool IsOptimizableRAMAddress(const u32 address)
|
||||||
// We store whether an access can be optimized to an unchecked access
|
// We store whether an access can be optimized to an unchecked access
|
||||||
// in dbat_table.
|
// in dbat_table.
|
||||||
u32 bat_result = dbat_table[address >> BAT_INDEX_SHIFT];
|
u32 bat_result = dbat_table[address >> BAT_INDEX_SHIFT];
|
||||||
return (bat_result & 2) != 0;
|
return (bat_result & BAT_PHYSICAL_BIT) != 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
template <XCheckTLBFlag flag>
|
template <XCheckTLBFlag flag>
|
||||||
|
@ -1177,27 +1177,29 @@ static void UpdateBATs(BatTable& bat_table, u32 base_spr)
|
||||||
{
|
{
|
||||||
// This bit is a little weird: if BRPN & j != 0, we end up with
|
// This bit is a little weird: if BRPN & j != 0, we end up with
|
||||||
// a strange mapping. Need to check on hardware.
|
// a strange mapping. Need to check on hardware.
|
||||||
u32 address = (batl.BRPN | j) << BAT_INDEX_SHIFT;
|
u32 physical_address = (batl.BRPN | j) << BAT_INDEX_SHIFT;
|
||||||
|
u32 virtual_address = (batu.BEPI | j) << BAT_INDEX_SHIFT;
|
||||||
|
|
||||||
// The bottom bit is whether the translation is valid; the second
|
// The bottom bit is whether the translation is valid; the second
|
||||||
// bit from the bottom is whether we can use the fastmem arena.
|
// bit from the bottom is whether we can use the fastmem arena.
|
||||||
u32 valid_bit = 0x1;
|
u32 valid_bit = BAT_MAPPED_BIT;
|
||||||
if (Memory::m_pFakeVMEM && ((address & 0xFE000000) == 0x7E000000))
|
if (Memory::m_pFakeVMEM && (physical_address & 0xFE000000) == 0x7E000000)
|
||||||
valid_bit = 0x3;
|
valid_bit |= BAT_PHYSICAL_BIT;
|
||||||
else if (address < Memory::REALRAM_SIZE)
|
else if (physical_address < Memory::REALRAM_SIZE)
|
||||||
valid_bit = 0x3;
|
valid_bit |= BAT_PHYSICAL_BIT;
|
||||||
else if (Memory::m_pEXRAM && (address >> 28) == 0x1 &&
|
else if (Memory::m_pEXRAM && physical_address >> 28 == 0x1 &&
|
||||||
(address & 0x0FFFFFFF) < Memory::EXRAM_SIZE)
|
(physical_address & 0x0FFFFFFF) < Memory::EXRAM_SIZE)
|
||||||
valid_bit = 0x3;
|
valid_bit |= BAT_PHYSICAL_BIT;
|
||||||
else if ((address >> 28) == 0xE && (address < (0xE0000000 + Memory::L1_CACHE_SIZE)))
|
else if (physical_address >> 28 == 0xE &&
|
||||||
valid_bit = 0x3;
|
physical_address < 0xE0000000 + Memory::L1_CACHE_SIZE)
|
||||||
|
valid_bit |= BAT_PHYSICAL_BIT;
|
||||||
|
|
||||||
// Fastmem doesn't support memchecks, so disable it for all overlapping virtual pages.
|
// Fastmem doesn't support memchecks, so disable it for all overlapping virtual pages.
|
||||||
if (PowerPC::memchecks.OverlapsMemcheck(((batu.BEPI | j) << BAT_INDEX_SHIFT),
|
if (PowerPC::memchecks.OverlapsMemcheck(virtual_address, BAT_PAGE_SIZE))
|
||||||
1 << BAT_INDEX_SHIFT))
|
valid_bit &= ~BAT_PHYSICAL_BIT;
|
||||||
valid_bit &= ~0x2;
|
|
||||||
|
|
||||||
// (BEPI | j) == (BEPI & ~BL) | (j & BL).
|
// (BEPI | j) == (BEPI & ~BL) | (j & BL).
|
||||||
bat_table[batu.BEPI | j] = address | valid_bit;
|
bat_table[virtual_address >> BAT_INDEX_SHIFT] = physical_address | valid_bit;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1210,8 +1212,13 @@ static void UpdateFakeMMUBat(BatTable& bat_table, u32 start_addr)
|
||||||
// Map from 0x4XXXXXXX or 0x7XXXXXXX to the range
|
// Map from 0x4XXXXXXX or 0x7XXXXXXX to the range
|
||||||
// [0x7E000000,0x80000000).
|
// [0x7E000000,0x80000000).
|
||||||
u32 e_address = i + (start_addr >> BAT_INDEX_SHIFT);
|
u32 e_address = i + (start_addr >> BAT_INDEX_SHIFT);
|
||||||
u32 p_address = 0x7E000003 | ((i << BAT_INDEX_SHIFT) & Memory::FAKEVMEM_MASK);
|
u32 p_address = 0x7E000000 | (i << BAT_INDEX_SHIFT & Memory::FAKEVMEM_MASK);
|
||||||
bat_table[e_address] = p_address;
|
u32 flags = BAT_MAPPED_BIT | BAT_PHYSICAL_BIT;
|
||||||
|
|
||||||
|
if (PowerPC::memchecks.OverlapsMemcheck(e_address << BAT_INDEX_SHIFT, BAT_PAGE_SIZE))
|
||||||
|
flags &= ~BAT_PHYSICAL_BIT;
|
||||||
|
|
||||||
|
bat_table[e_address] = p_address | flags;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1258,14 +1265,11 @@ void IBATUpdated()
|
||||||
// So we first check if there is a matching BAT entry, else we look for the TLB in
|
// So we first check if there is a matching BAT entry, else we look for the TLB in
|
||||||
// TranslatePageAddress().
|
// TranslatePageAddress().
|
||||||
template <const XCheckTLBFlag flag>
|
template <const XCheckTLBFlag flag>
|
||||||
static TranslateAddressResult TranslateAddress(const u32 address)
|
static TranslateAddressResult TranslateAddress(u32 address)
|
||||||
{
|
{
|
||||||
u32 bat_result = (IsOpcodeFlag(flag) ? ibat_table : dbat_table)[address >> BAT_INDEX_SHIFT];
|
if (TranslateBatAddess(IsOpcodeFlag(flag) ? ibat_table : dbat_table, &address))
|
||||||
if (bat_result & 1)
|
return TranslateAddressResult{TranslateAddressResult::BAT_TRANSLATED, address};
|
||||||
{
|
|
||||||
u32 result_addr = (bat_result & ~3) | (address & 0x0001FFFF);
|
|
||||||
return TranslateAddressResult{TranslateAddressResult::BAT_TRANSLATED, result_addr};
|
|
||||||
}
|
|
||||||
return TranslatePageAddress(address, flag);
|
return TranslatePageAddress(address, flag);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -288,16 +288,20 @@ struct TranslateResult
|
||||||
};
|
};
|
||||||
TranslateResult JitCache_TranslateAddress(u32 address);
|
TranslateResult JitCache_TranslateAddress(u32 address);
|
||||||
|
|
||||||
static const int BAT_INDEX_SHIFT = 17;
|
constexpr int BAT_INDEX_SHIFT = 17;
|
||||||
|
constexpr u32 BAT_PAGE_SIZE = 1 << BAT_INDEX_SHIFT;
|
||||||
|
constexpr u32 BAT_MAPPED_BIT = 0x1;
|
||||||
|
constexpr u32 BAT_PHYSICAL_BIT = 0x2;
|
||||||
|
constexpr u32 BAT_RESULT_MASK = ~0x3;
|
||||||
using BatTable = std::array<u32, 1 << (32 - BAT_INDEX_SHIFT)>; // 128 KB
|
using BatTable = std::array<u32, 1 << (32 - BAT_INDEX_SHIFT)>; // 128 KB
|
||||||
extern BatTable ibat_table;
|
extern BatTable ibat_table;
|
||||||
extern BatTable dbat_table;
|
extern BatTable dbat_table;
|
||||||
inline bool TranslateBatAddess(const BatTable& bat_table, u32* address)
|
inline bool TranslateBatAddess(const BatTable& bat_table, u32* address)
|
||||||
{
|
{
|
||||||
u32 bat_result = bat_table[*address >> BAT_INDEX_SHIFT];
|
u32 bat_result = bat_table[*address >> BAT_INDEX_SHIFT];
|
||||||
if ((bat_result & 1) == 0)
|
if ((bat_result & BAT_MAPPED_BIT) == 0)
|
||||||
return false;
|
return false;
|
||||||
*address = (bat_result & ~3) | (*address & 0x0001FFFF);
|
*address = (bat_result & BAT_RESULT_MASK) | (*address & (BAT_PAGE_SIZE - 1));
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
} // namespace
|
} // namespace
|
||||||
|
|
Loading…
Reference in New Issue