Merge pull request #5012 from degasus/BAT

MMU: Create constants for our BAT flags.
This commit is contained in:
Markus Wick 2017-03-16 16:02:16 +01:00 committed by GitHub
commit 907e73a1fc
5 changed files with 44 additions and 34 deletions

View File

@ -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;

View File

@ -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.

View File

@ -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);

View File

@ -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);
} }

View File

@ -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