From ebc47a4b367022997d0053263ff70b7837f197ff Mon Sep 17 00:00:00 2001 From: degasus Date: Sun, 4 Sep 2016 10:50:48 +0200 Subject: [PATCH 1/5] Memmap: Drop redundant global bFakeVMEM flag. --- Source/Core/Core/HW/Memmap.cpp | 10 ++++------ Source/Core/Core/HW/Memmap.h | 1 - Source/Core/Core/PowerPC/MMU.cpp | 14 +++++++------- 3 files changed, 11 insertions(+), 14 deletions(-) diff --git a/Source/Core/Core/HW/Memmap.cpp b/Source/Core/Core/HW/Memmap.cpp index 05d731efcc..c82380b903 100644 --- a/Source/Core/Core/HW/Memmap.cpp +++ b/Source/Core/Core/HW/Memmap.cpp @@ -34,9 +34,6 @@ namespace Memory { -// (See comment below describing memory map.) -bool bFakeVMEM = false; - // ================================= // Init() declarations // ---------------- @@ -169,6 +166,7 @@ void Init() { bool wii = SConfig::GetInstance().bWii; bool bMMU = SConfig::GetInstance().bMMU; + bool bFakeVMEM = false; #ifndef _ARCH_32 // If MMU is turned off in GameCube mode, turn on fake VMEM hack. // The fake VMEM hack's address space is above the memory space that we @@ -269,7 +267,7 @@ void DoState(PointerWrap& p) p.DoArray(m_pRAM, RAM_SIZE); p.DoArray(m_pL1Cache, L1_CACHE_SIZE); p.DoMarker("Memory RAM"); - if (bFakeVMEM) + if (m_pFakeVMEM) p.DoArray(m_pFakeVMEM, FAKEVMEM_SIZE); p.DoMarker("Memory FakeVMEM"); if (wii) @@ -283,7 +281,7 @@ void Shutdown() u32 flags = 0; if (SConfig::GetInstance().bWii) flags |= PhysicalMemoryRegion::WII_ONLY; - if (bFakeVMEM) + if (m_pFakeVMEM) flags |= PhysicalMemoryRegion::FAKE_VMEM; for (PhysicalMemoryRegion& region : physical_regions) { @@ -397,7 +395,7 @@ u8* GetPointer(u32 address) if (address < REALRAM_SIZE) return m_pRAM + address; - if (SConfig::GetInstance().bWii) + if (m_pEXRAM) { if ((address >> 28) == 0x1 && (address & 0x0fffffff) < EXRAM_SIZE) return m_pEXRAM + (address & EXRAM_MASK); diff --git a/Source/Core/Core/HW/Memmap.h b/Source/Core/Core/HW/Memmap.h index 02c0650818..1e628fe215 100644 --- a/Source/Core/Core/HW/Memmap.h +++ b/Source/Core/Core/HW/Memmap.h @@ -35,7 +35,6 @@ extern u8* m_pRAM; extern u8* m_pEXRAM; extern u8* m_pL1Cache; extern u8* m_pFakeVMEM; -extern bool bFakeVMEM; enum { diff --git a/Source/Core/Core/PowerPC/MMU.cpp b/Source/Core/Core/PowerPC/MMU.cpp index a637399ce0..d114a75c34 100644 --- a/Source/Core/Core/PowerPC/MMU.cpp +++ b/Source/Core/Core/PowerPC/MMU.cpp @@ -211,7 +211,7 @@ __forceinline static T ReadFromHardware(u32 em_address) // In Fake-VMEM mode, we need to map the memory somewhere into // physical memory for BAT translation to work; we currently use // [0x7E000000, 0x80000000). - if (Memory::bFakeVMEM && ((em_address & 0xFE000000) == 0x7E000000)) + if (Memory::m_pFakeVMEM && ((em_address & 0xFE000000) == 0x7E000000)) { return bswap(*(T*)&Memory::m_pFakeVMEM[em_address & Memory::RAM_MASK]); } @@ -295,7 +295,7 @@ __forceinline static void WriteToHardware(u32 em_address, const T data) // In Fake-VMEM mode, we need to map the memory somewhere into // physical memory for BAT translation to work; we currently use // [0x7E000000, 0x80000000). - if (Memory::bFakeVMEM && ((em_address & 0xFE000000) == 0x7E000000)) + if (Memory::m_pFakeVMEM && ((em_address & 0xFE000000) == 0x7E000000)) { *(T*)&Memory::m_pFakeVMEM[em_address & Memory::RAM_MASK] = bswap(data); return; @@ -395,7 +395,7 @@ TryReadInstResult TryReadInstruction(u32 address) u32 hex; // TODO: Refactor this. This icache implementation is totally wrong if used with the fake vmem. - if (Memory::bFakeVMEM && ((address & 0xFE000000) == 0x7E000000)) + if (Memory::m_pFakeVMEM && ((address & 0xFE000000) == 0x7E000000)) { hex = bswap(*(const u32*)&Memory::m_pFakeVMEM[address & Memory::FAKEVMEM_MASK]); } @@ -639,7 +639,7 @@ bool HostIsRAMAddress(u32 address) return true; else if (Memory::m_pEXRAM && segment == 0x1 && (address & 0x0FFFFFFF) < Memory::EXRAM_SIZE) return true; - else if (Memory::bFakeVMEM && ((address & 0xFE000000) == 0x7E000000)) + else if (Memory::m_pFakeVMEM && ((address & 0xFE000000) == 0x7E000000)) return true; else if (segment == 0xE && (address < (0xE0000000 + Memory::L1_CACHE_SIZE))) return true; @@ -1166,7 +1166,7 @@ static void UpdateBATs(BatTable& bat_table, u32 base_spr) // 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::bFakeVMEM && ((address & 0xFE000000) == 0x7E000000)) + if (Memory::m_pFakeVMEM && ((address & 0xFE000000) == 0x7E000000)) valid_bit = 0x3; else if (address < Memory::REALRAM_SIZE) valid_bit = 0x3; @@ -1202,7 +1202,7 @@ void DBATUpdated() bool extended_bats = SConfig::GetInstance().bWii && HID4.SBE; if (extended_bats) UpdateBATs(dbat_table, SPR_DBAT4U); - if (Memory::bFakeVMEM) + if (Memory::m_pFakeVMEM) { // In Fake-MMU mode, insert some extra entries into the BAT tables. UpdateFakeMMUBat(dbat_table, 0x40000000); @@ -1221,7 +1221,7 @@ void IBATUpdated() bool extended_bats = SConfig::GetInstance().bWii && HID4.SBE; if (extended_bats) UpdateBATs(ibat_table, SPR_IBAT4U); - if (Memory::bFakeVMEM) + if (Memory::m_pFakeVMEM) { // In Fake-MMU mode, insert some extra entries into the BAT tables. UpdateFakeMMUBat(ibat_table, 0x40000000); From 4b3e388bd7cdbfb7c04712e3998f965b9134737e Mon Sep 17 00:00:00 2001 From: degasus Date: Tue, 6 Sep 2016 23:28:33 +0200 Subject: [PATCH 2/5] Jit64: Fix merge failure of dynamic_bat. --- Source/Core/Core/PowerPC/Jit64/Jit_LoadStore.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Source/Core/Core/PowerPC/Jit64/Jit_LoadStore.cpp b/Source/Core/Core/PowerPC/Jit64/Jit_LoadStore.cpp index 8a076b2e40..458b143112 100644 --- a/Source/Core/Core/PowerPC/Jit64/Jit_LoadStore.cpp +++ b/Source/Core/Core/PowerPC/Jit64/Jit_LoadStore.cpp @@ -373,7 +373,7 @@ void Jit64::dcbz(UGeckoInstruction inst) MOV(32, M(&PC), Imm32(jit->js.compilerPC)); BitSet32 registersInUse = CallerSavedRegistersInUse(); ABI_PushRegistersAndAdjustStack(registersInUse, 0); - ABI_CallFunctionR(&PowerPC::ClearCacheLine, RSCRATCH); + ABI_CallFunctionR(PowerPC::ClearCacheLine, RSCRATCH); ABI_PopRegistersAndAdjustStack(registersInUse, 0); if (UReg_MSR(MSR).DR) From d1488d0dc47a539e949065b4d2ecca5289a36eae Mon Sep 17 00:00:00 2001 From: degasus Date: Wed, 7 Sep 2016 00:13:25 +0200 Subject: [PATCH 3/5] MMU: Drop force inline usage. This is not needed, the compiler will do it on it's own if required. --- Source/Core/Core/PowerPC/MMU.cpp | 16 +++++++--------- 1 file changed, 7 insertions(+), 9 deletions(-) diff --git a/Source/Core/Core/PowerPC/MMU.cpp b/Source/Core/Core/PowerPC/MMU.cpp index d114a75c34..447472c8d3 100644 --- a/Source/Core/Core/PowerPC/MMU.cpp +++ b/Source/Core/Core/PowerPC/MMU.cpp @@ -163,7 +163,7 @@ BatTable dbat_table; static void GenerateDSIException(u32 _EffectiveAddress, bool _bWrite); template -__forceinline static T ReadFromHardware(u32 em_address) +static T ReadFromHardware(u32 em_address) { if (!never_translate && UReg_MSR(MSR).DR) { @@ -243,7 +243,7 @@ __forceinline static T ReadFromHardware(u32 em_address) } template -__forceinline static void WriteToHardware(u32 em_address, const T data) +static void WriteToHardware(u32 em_address, const T data) { if (!never_translate && UReg_MSR(MSR).DR) { @@ -412,7 +412,7 @@ u32 HostRead_Instruction(const u32 address) return inst.hex; } -static __forceinline void Memcheck(u32 address, u32 var, bool write, int size) +static void Memcheck(u32 address, u32 var, bool write, int size) { if (PowerPC::memchecks.HasAny()) { @@ -953,8 +953,7 @@ enum TLBLookupResult TLB_UPDATE_C }; -static __forceinline TLBLookupResult LookupTLBPageAddress(const XCheckTLBFlag flag, const u32 vpa, - u32* paddr) +static TLBLookupResult LookupTLBPageAddress(const XCheckTLBFlag flag, const u32 vpa, u32* paddr) { u32 tag = vpa >> HW_PAGE_INDEX_SHIFT; PowerPC::tlb_entry* tlbe = &PowerPC::ppcState.tlb[IsOpcodeFlag(flag)][tag & HW_PAGE_INDEX_MASK]; @@ -1005,7 +1004,7 @@ static __forceinline TLBLookupResult LookupTLBPageAddress(const XCheckTLBFlag fl return TLB_NOTFOUND; } -static __forceinline void UpdateTLBEntry(const XCheckTLBFlag flag, UPTE2 PTE2, const u32 address) +static void UpdateTLBEntry(const XCheckTLBFlag flag, UPTE2 PTE2, const u32 address) { if (IsNoExceptionFlag(flag)) return; @@ -1032,8 +1031,7 @@ void InvalidateTLBEntry(u32 address) } // Page Address Translation -static __forceinline TranslateAddressResult TranslatePageAddress(const u32 address, - const XCheckTLBFlag flag) +static TranslateAddressResult TranslatePageAddress(const u32 address, const XCheckTLBFlag flag) { // TLB cache // This catches 99%+ of lookups in practice, so the actual page table entry code below doesn't @@ -1235,7 +1233,7 @@ void IBATUpdated() // So we first check if there is a matching BAT entry, else we look for the TLB in // TranslatePageAddress(). template -TranslateAddressResult TranslateAddress(const u32 address) +static TranslateAddressResult TranslateAddress(const u32 address) { u32 bat_result = (flag == FLAG_OPCODE ? ibat_table : dbat_table)[address >> BAT_INDEX_SHIFT]; if (bat_result & 1) From 0de1c6c99c5b81e25a816ec3e706c66faa571dd0 Mon Sep 17 00:00:00 2001 From: degasus Date: Fri, 9 Sep 2016 01:16:26 +0200 Subject: [PATCH 4/5] MMU: Sort physical access by common access pattern. --- Source/Core/Core/PowerPC/MMU.cpp | 60 ++++++++++++++++---------------- 1 file changed, 30 insertions(+), 30 deletions(-) diff --git a/Source/Core/Core/PowerPC/MMU.cpp b/Source/Core/Core/PowerPC/MMU.cpp index 447472c8d3..2237421f5c 100644 --- a/Source/Core/Core/PowerPC/MMU.cpp +++ b/Source/Core/Core/PowerPC/MMU.cpp @@ -203,6 +203,20 @@ static T ReadFromHardware(u32 em_address) // TODO: Make sure these are safe for unaligned addresses. + if ((em_address & 0xF8000000) == 0x00000000) + { + // Handle RAM; the masking intentionally discards bits (essentially creating + // mirrors of memory). + // TODO: Only the first REALRAM_SIZE is supposed to be backed by actual memory. + return bswap((*(const T*)&Memory::m_pRAM[em_address & Memory::RAM_MASK])); + } + + if (Memory::m_pEXRAM && (em_address >> 28) == 0x1 && + (em_address & 0x0FFFFFFF) < Memory::EXRAM_SIZE) + { + return bswap((*(const T*)&Memory::m_pEXRAM[em_address & 0x0FFFFFFF])); + } + // Locked L1 technically doesn't have a fixed address, but games all use 0xE0000000. if ((em_address >> 28) == 0xE && (em_address < (0xE0000000 + Memory::L1_CACHE_SIZE))) { @@ -224,20 +238,6 @@ static T ReadFromHardware(u32 em_address) return (T)Memory::mmio_mapping->Read::type>(em_address); } - if ((em_address & 0xF8000000) == 0x00000000) - { - // Handle RAM; the masking intentionally discards bits (essentially creating - // mirrors of memory). - // TODO: Only the first REALRAM_SIZE is supposed to be backed by actual memory. - return bswap((*(const T*)&Memory::m_pRAM[em_address & Memory::RAM_MASK])); - } - - if (Memory::m_pEXRAM && (em_address >> 28) == 0x1 && - (em_address & 0x0FFFFFFF) < Memory::EXRAM_SIZE) - { - return bswap((*(const T*)&Memory::m_pEXRAM[em_address & 0x0FFFFFFF])); - } - PanicAlert("Unable to resolve read address %x PC %x", em_address, PC); return 0; } @@ -285,6 +285,22 @@ static void WriteToHardware(u32 em_address, const T data) // TODO: Make sure these are safe for unaligned addresses. + if ((em_address & 0xF8000000) == 0x00000000) + { + // Handle RAM; the masking intentionally discards bits (essentially creating + // mirrors of memory). + // TODO: Only the first REALRAM_SIZE is supposed to be backed by actual memory. + *(T*)&Memory::m_pRAM[em_address & Memory::RAM_MASK] = bswap(data); + return; + } + + if (Memory::m_pEXRAM && (em_address >> 28) == 0x1 && + (em_address & 0x0FFFFFFF) < Memory::EXRAM_SIZE) + { + *(T*)&Memory::m_pEXRAM[em_address & 0x0FFFFFFF] = bswap(data); + return; + } + // Locked L1 technically doesn't have a fixed address, but games all use 0xE0000000. if ((em_address >> 28 == 0xE) && (em_address < (0xE0000000 + Memory::L1_CACHE_SIZE))) { @@ -337,22 +353,6 @@ static void WriteToHardware(u32 em_address, const T data) } } - if ((em_address & 0xF8000000) == 0x00000000) - { - // Handle RAM; the masking intentionally discards bits (essentially creating - // mirrors of memory). - // TODO: Only the first REALRAM_SIZE is supposed to be backed by actual memory. - *(T*)&Memory::m_pRAM[em_address & Memory::RAM_MASK] = bswap(data); - return; - } - - if (Memory::m_pEXRAM && (em_address >> 28) == 0x1 && - (em_address & 0x0FFFFFFF) < Memory::EXRAM_SIZE) - { - *(T*)&Memory::m_pEXRAM[em_address & 0x0FFFFFFF] = bswap(data); - return; - } - PanicAlert("Unable to resolve write address %x PC %x", em_address, PC); return; } From f7e07f8f3b4eeb46bb424d8761a372bdfde28795 Mon Sep 17 00:00:00 2001 From: degasus Date: Sat, 1 Oct 2016 17:38:09 +0200 Subject: [PATCH 5/5] MMU: Don't generate virtual memory area on 32bit builds. There is no JIT, so no need for fastmem. This memory won't be used at all. --- Source/Core/Core/PowerPC/MMU.cpp | 3 +++ 1 file changed, 3 insertions(+) diff --git a/Source/Core/Core/PowerPC/MMU.cpp b/Source/Core/Core/PowerPC/MMU.cpp index 2237421f5c..8c293c31c9 100644 --- a/Source/Core/Core/PowerPC/MMU.cpp +++ b/Source/Core/Core/PowerPC/MMU.cpp @@ -1206,7 +1206,10 @@ void DBATUpdated() UpdateFakeMMUBat(dbat_table, 0x40000000); UpdateFakeMMUBat(dbat_table, 0x70000000); } + +#ifndef _ARCH_32 Memory::UpdateLogicalMemory(dbat_table); +#endif // IsOptimizable*Address and dcbz depends on the BAT mapping, so we need a flush here. JitInterface::ClearSafe();