diff --git a/Source/Core/Core/HW/Memmap.cpp b/Source/Core/Core/HW/Memmap.cpp index 8fa5e4f337..175b030e13 100644 --- a/Source/Core/Core/HW/Memmap.cpp +++ b/Source/Core/Core/HW/Memmap.cpp @@ -229,12 +229,12 @@ void UpdateLogicalMemory(const PowerPC::BatTable& dbat_table) logical_mapped_entries.clear(); 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; // TODO: Merge adjacent mappings to make this faster. - u32 logical_size = 1 << PowerPC::BAT_INDEX_SHIFT; - u32 translated_address = dbat_table[i] & ~3; + u32 logical_size = PowerPC::BAT_PAGE_SIZE; + u32 translated_address = dbat_table[i] & PowerPC::BAT_RESULT_MASK; for (const auto& physical_region : physical_regions) { u32 mapping_address = physical_region.physical_address; diff --git a/Source/Core/Core/PowerPC/Jit64/Jit_LoadStore.cpp b/Source/Core/Core/PowerPC/Jit64/Jit_LoadStore.cpp index 23eaee35b6..9fa97ff09e 100644 --- a/Source/Core/Core/PowerPC/Jit64/Jit_LoadStore.cpp +++ b/Source/Core/Core/PowerPC/Jit64/Jit_LoadStore.cpp @@ -347,7 +347,8 @@ void Jit64::dcbz(UGeckoInstruction inst) // Perform lookup to see if we can use fast path. MOV(32, R(RSCRATCH2), R(RSCRATCH)); 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); // Fast path: compute full address, then zero out 32 bytes of memory. diff --git a/Source/Core/Core/PowerPC/Jit64Common/EmuCodeBlock.cpp b/Source/Core/Core/PowerPC/Jit64Common/EmuCodeBlock.cpp index 62f78c7790..353aaed52d 100644 --- a/Source/Core/Core/PowerPC/Jit64Common/EmuCodeBlock.cpp +++ b/Source/Core/Core/PowerPC/Jit64Common/EmuCodeBlock.cpp @@ -105,7 +105,8 @@ FixupBranch EmuCodeBlock::CheckIfSafeAddress(const OpArg& reg_value, X64Reg reg_ // Perform lookup to see if we can use fast path. 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) POP(scratch); diff --git a/Source/Core/Core/PowerPC/MMU.cpp b/Source/Core/Core/PowerPC/MMU.cpp index 583d170f43..3ac3f2b9e1 100644 --- a/Source/Core/Core/PowerPC/MMU.cpp +++ b/Source/Core/Core/PowerPC/MMU.cpp @@ -109,7 +109,7 @@ struct TranslateAddressResult bool Success() const { return result <= PAGE_TABLE_TRANSLATED; } }; template -static TranslateAddressResult TranslateAddress(const u32 address); +static TranslateAddressResult TranslateAddress(u32 address); // Nasty but necessary. Super Mario Galaxy pointer relies on this stuff. 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 // in dbat_table. u32 bat_result = dbat_table[address >> BAT_INDEX_SHIFT]; - return (bat_result & 2) != 0; + return (bat_result & BAT_PHYSICAL_BIT) != 0; } template @@ -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 // 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 // bit from the bottom is whether we can use the fastmem arena. - u32 valid_bit = 0x1; - if (Memory::m_pFakeVMEM && ((address & 0xFE000000) == 0x7E000000)) - valid_bit = 0x3; - else if (address < Memory::REALRAM_SIZE) - valid_bit = 0x3; - else if (Memory::m_pEXRAM && (address >> 28) == 0x1 && - (address & 0x0FFFFFFF) < Memory::EXRAM_SIZE) - valid_bit = 0x3; - else if ((address >> 28) == 0xE && (address < (0xE0000000 + Memory::L1_CACHE_SIZE))) - valid_bit = 0x3; + u32 valid_bit = BAT_MAPPED_BIT; + if (Memory::m_pFakeVMEM && (physical_address & 0xFE000000) == 0x7E000000) + valid_bit |= BAT_PHYSICAL_BIT; + else if (physical_address < Memory::REALRAM_SIZE) + valid_bit |= BAT_PHYSICAL_BIT; + else if (Memory::m_pEXRAM && physical_address >> 28 == 0x1 && + (physical_address & 0x0FFFFFFF) < Memory::EXRAM_SIZE) + valid_bit |= BAT_PHYSICAL_BIT; + else if (physical_address >> 28 == 0xE && + 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. - if (PowerPC::memchecks.OverlapsMemcheck(((batu.BEPI | j) << BAT_INDEX_SHIFT), - 1 << BAT_INDEX_SHIFT)) - valid_bit &= ~0x2; + if (PowerPC::memchecks.OverlapsMemcheck(virtual_address, BAT_PAGE_SIZE)) + valid_bit &= ~BAT_PHYSICAL_BIT; // (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 // [0x7E000000,0x80000000). u32 e_address = i + (start_addr >> BAT_INDEX_SHIFT); - u32 p_address = 0x7E000003 | ((i << BAT_INDEX_SHIFT) & Memory::FAKEVMEM_MASK); - bat_table[e_address] = p_address; + u32 p_address = 0x7E000000 | (i << BAT_INDEX_SHIFT & Memory::FAKEVMEM_MASK); + 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 // TranslatePageAddress(). template -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 (bat_result & 1) - { - u32 result_addr = (bat_result & ~3) | (address & 0x0001FFFF); - return TranslateAddressResult{TranslateAddressResult::BAT_TRANSLATED, result_addr}; - } + if (TranslateBatAddess(IsOpcodeFlag(flag) ? ibat_table : dbat_table, &address)) + return TranslateAddressResult{TranslateAddressResult::BAT_TRANSLATED, address}; + return TranslatePageAddress(address, flag); } diff --git a/Source/Core/Core/PowerPC/PowerPC.h b/Source/Core/Core/PowerPC/PowerPC.h index 052331e962..808083a653 100644 --- a/Source/Core/Core/PowerPC/PowerPC.h +++ b/Source/Core/Core/PowerPC/PowerPC.h @@ -288,16 +288,20 @@ struct TranslateResult }; 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; // 128 KB extern BatTable ibat_table; extern BatTable dbat_table; inline bool TranslateBatAddess(const BatTable& bat_table, u32* address) { u32 bat_result = bat_table[*address >> BAT_INDEX_SHIFT]; - if ((bat_result & 1) == 0) + if ((bat_result & BAT_MAPPED_BIT) == 0) return false; - *address = (bat_result & ~3) | (*address & 0x0001FFFF); + *address = (bat_result & BAT_RESULT_MASK) | (*address & (BAT_PAGE_SIZE - 1)); return true; } } // namespace