diff --git a/Source/Core/Common/MemArena.cpp b/Source/Core/Common/MemArena.cpp index 16eecf33d6..60ad058778 100644 --- a/Source/Core/Common/MemArena.cpp +++ b/Source/Core/Common/MemArena.cpp @@ -49,7 +49,7 @@ static int AshmemCreateFileMapping(const char *name, size_t size) } #endif -void MemArena::GrabLowMemSpace(size_t size) +void MemArena::GrabSHMSegment(size_t size) { #ifdef _WIN32 hMemoryMapping = CreateFileMapping(INVALID_HANDLE_VALUE, nullptr, PAGE_READWRITE, 0, (DWORD)(size), nullptr); @@ -82,7 +82,7 @@ void MemArena::GrabLowMemSpace(size_t size) } -void MemArena::ReleaseSpace() +void MemArena::ReleaseSHMSegment() { #ifdef _WIN32 CloseHandle(hMemoryMapping); @@ -170,56 +170,60 @@ u8* MemArena::Find4GBBase() if (!(a_flags & MV_FAKE_VMEM) && (b_flags & MV_FAKE_VMEM)) \ continue; \ - -static bool Memory_TryBase(u8 *base, const MemoryView *views, int num_views, u32 flags, MemArena *arena) +static bool Memory_TryBase(u8 *base, MemoryView *views, int num_views, u32 flags, MemArena *arena) { // OK, we know where to find free space. Now grab it! // We just mimic the popular BAT setup. - u32 position = 0; - u32 last_position = 0; + u32 shm_position = 0; // Zero all the pointers to be sure. for (int i = 0; i < num_views; i++) { - if (views[i].out_ptr_low) - *views[i].out_ptr_low = nullptr; - if (views[i].out_ptr) - *views[i].out_ptr = nullptr; + views[i].mapped_ptr = nullptr; + + if (!(views[i].flags & MV_MIRROR_PREVIOUS) && i > 0) + shm_position += views[i - 1].size; + + views[i].shm_position = shm_position; } int i; for (i = 0; i < num_views; i++) { - SKIP(flags, views[i].flags); - if (views[i].flags & MV_MIRROR_PREVIOUS) - { - position = last_position; - } - else - { - *(views[i].out_ptr_low) = (u8*)arena->CreateView(position, views[i].size); - if (!*views[i].out_ptr_low) - goto bail; - } + MemoryView* view = &views[i]; + void* view_base; + bool use_sw_mirror; + + SKIP(flags, view->flags); + #if _ARCH_64 - *views[i].out_ptr = (u8*)arena->CreateView( - position, views[i].size, base + views[i].virtual_address); + // On 64-bit, we map the same file position multiple times, so we + // don't need the software fallback for the mirrors. + view_base = base + view->virtual_address; + use_sw_mirror = false; #else - if (views[i].flags & MV_MIRROR_PREVIOUS) + // On 32-bit, we don't have the actual address space to store all + // the mirrors, so we just map the fallbacks somewhere in our address + // space and use the software fallbacks for mirroring. + view_base = base + (view->virtual_address & 0x3FFFFFFF); + use_sw_mirror = true; +#endif + + if (use_sw_mirror && (view->flags & MV_MIRROR_PREVIOUS)) { - // No need to create multiple identical views. - *views[i].out_ptr = *views[i - 1].out_ptr; + view->view_ptr = views[i - 1].view_ptr; } else { - *views[i].out_ptr = (u8*)arena->CreateView( - position, views[i].size, base + (views[i].virtual_address & 0x3FFFFFFF)); - if (!*views[i].out_ptr) - goto bail; + view->mapped_ptr = arena->CreateView(view->shm_position, view->size, view_base); + view->view_ptr = view->mapped_ptr; } -#endif - last_position = position; - position += views[i].size; + + if (!view->view_ptr) + goto bail; + + if (view->out_ptr) + *(view->out_ptr) = (u8*) view->view_ptr; } return true; @@ -230,7 +234,7 @@ bail: return false; } -u8 *MemoryMap_Setup(const MemoryView *views, int num_views, u32 flags, MemArena *arena) +u8 *MemoryMap_Setup(MemoryView *views, int num_views, u32 flags, MemArena *arena) { u32 total_mem = 0; @@ -240,11 +244,10 @@ u8 *MemoryMap_Setup(const MemoryView *views, int num_views, u32 flags, MemArena if ((views[i].flags & MV_MIRROR_PREVIOUS) == 0) total_mem += views[i].size; } - // Grab some pagefile backed memory out of the void ... - arena->GrabLowMemSpace(total_mem); + + arena->GrabSHMSegment(total_mem); // Now, create views in high memory where there's plenty of space. -#if _ARCH_64 u8 *base = MemArena::Find4GBBase(); // This really shouldn't fail - in 64-bit, there will always be enough // address space. @@ -254,35 +257,21 @@ u8 *MemoryMap_Setup(const MemoryView *views, int num_views, u32 flags, MemArena exit(0); return nullptr; } -#else - // Linux32 is fine with the x64 method, although limited to 32-bit with no automirrors. - u8 *base = MemArena::Find4GBBase(); - if (!Memory_TryBase(base, views, num_views, flags, arena)) - { - PanicAlert("MemoryMap_Setup: Failed finding a memory base."); - exit(0); - return 0; - } -#endif return base; } -void MemoryMap_Shutdown(const MemoryView *views, int num_views, u32 flags, MemArena *arena) +void MemoryMap_Shutdown(MemoryView *views, int num_views, u32 flags, MemArena *arena) { std::set freeset; for (int i = 0; i < num_views; i++) { - const MemoryView* view = &views[i]; - u8** outptrs[2] = {view->out_ptr_low, view->out_ptr}; - for (auto outptr : outptrs) + MemoryView* view = &views[i]; + if (view->mapped_ptr && *(u8*)view->mapped_ptr && !freeset.count(view->mapped_ptr)) { - if (outptr && *outptr && !freeset.count(*outptr)) - { - arena->ReleaseView(*outptr, view->size); - freeset.insert(*outptr); - *outptr = nullptr; - } + arena->ReleaseView(view->mapped_ptr, view->size); + freeset.insert(view->mapped_ptr); + view->mapped_ptr = nullptr; } } } diff --git a/Source/Core/Common/MemArena.h b/Source/Core/Common/MemArena.h index ccfc962f22..67482432fd 100644 --- a/Source/Core/Common/MemArena.h +++ b/Source/Core/Common/MemArena.h @@ -19,8 +19,8 @@ class MemArena { public: - void GrabLowMemSpace(size_t size); - void ReleaseSpace(); + void GrabSHMSegment(size_t size); + void ReleaseSHMSegment(); void *CreateView(s64 offset, size_t size, void *base = nullptr); void ReleaseView(void *view, size_t size); @@ -43,14 +43,16 @@ enum { struct MemoryView { - u8 **out_ptr_low; - u8 **out_ptr; + u8** out_ptr; u32 virtual_address; u32 size; u32 flags; + void* mapped_ptr; + void* view_ptr; + u32 shm_position; }; // Uses a memory arena to set up an emulator-friendly memory map according to // a passed-in list of MemoryView structures. -u8 *MemoryMap_Setup(const MemoryView *views, int num_views, u32 flags, MemArena *arena); -void MemoryMap_Shutdown(const MemoryView *views, int num_views, u32 flags, MemArena *arena); +u8 *MemoryMap_Setup(MemoryView *views, int num_views, u32 flags, MemArena *arena); +void MemoryMap_Shutdown(MemoryView *views, int num_views, u32 flags, MemArena *arena); diff --git a/Source/Core/Core/HW/Memmap.cpp b/Source/Core/Core/HW/Memmap.cpp index 049b53a0de..d89647592e 100644 --- a/Source/Core/Core/HW/Memmap.cpp +++ b/Source/Core/Core/HW/Memmap.cpp @@ -63,24 +63,11 @@ static MemArena g_arena; static bool m_IsInitialized = false; // Save the Init(), Shutdown() state // END STATE_TO_SAVE -// 64-bit: Pointers to low-mem (sub-0x10000000) mirror -// 32-bit: Same as the corresponding physical/virtual pointers. u8* m_pRAM; u8* m_pL1Cache; u8* m_pEXRAM; u8* m_pFakeVMEM; -// 64-bit: Pointers to high-mem mirrors -// 32-bit: Same as above -static u8* m_pPhysicalRAM; -static u8* m_pVirtualCachedRAM; -static u8* m_pVirtualUncachedRAM; -static u8* m_pPhysicalEXRAM; // wii only -static u8* m_pVirtualCachedEXRAM; // wii only -static u8* m_pVirtualUncachedEXRAM; // wii only -static u8* m_pVirtualL1Cache; -u8* m_pVirtualFakeVMEM; - // MMIO mapping object. MMIO::Mapping* mmio_mapping; @@ -116,22 +103,16 @@ bool IsInitialized() // We don't declare the IO region in here since its handled by other means. -static const MemoryView views[] = +static MemoryView views[] = { - {&m_pRAM, &m_pPhysicalRAM, 0x00000000, RAM_SIZE, 0}, - {nullptr, &m_pVirtualCachedRAM, 0x80000000, RAM_SIZE, MV_MIRROR_PREVIOUS}, - {nullptr, &m_pVirtualUncachedRAM, 0xC0000000, RAM_SIZE, MV_MIRROR_PREVIOUS}, - -// Don't map any memory for the EFB. We want all access to this area to go -// through the hardware access handlers. - - {&m_pL1Cache, &m_pVirtualL1Cache, 0xE0000000, L1_CACHE_SIZE, 0}, - - {&m_pFakeVMEM, &m_pVirtualFakeVMEM, 0x7E000000, FAKEVMEM_SIZE, MV_FAKE_VMEM}, - - {&m_pEXRAM, &m_pPhysicalEXRAM, 0x10000000, EXRAM_SIZE, MV_WII_ONLY}, - {nullptr, &m_pVirtualCachedEXRAM, 0x90000000, EXRAM_SIZE, MV_WII_ONLY | MV_MIRROR_PREVIOUS}, - {nullptr, &m_pVirtualUncachedEXRAM, 0xD0000000, EXRAM_SIZE, MV_WII_ONLY | MV_MIRROR_PREVIOUS}, + {&m_pRAM, 0x00000000, RAM_SIZE, 0}, + {nullptr, 0x80000000, RAM_SIZE, MV_MIRROR_PREVIOUS}, + {nullptr, 0xC0000000, RAM_SIZE, MV_MIRROR_PREVIOUS}, + {&m_pL1Cache, 0xE0000000, L1_CACHE_SIZE, 0}, + {&m_pFakeVMEM, 0x7E000000, FAKEVMEM_SIZE, MV_FAKE_VMEM}, + {&m_pEXRAM, 0x10000000, EXRAM_SIZE, MV_WII_ONLY}, + {nullptr, 0x90000000, EXRAM_SIZE, MV_WII_ONLY | MV_MIRROR_PREVIOUS}, + {nullptr, 0xD0000000, EXRAM_SIZE, MV_WII_ONLY | MV_MIRROR_PREVIOUS}, }; static const int num_views = sizeof(views) / sizeof(MemoryView); @@ -157,19 +138,18 @@ void Init() else InitMMIO(mmio_mapping); - INFO_LOG(MEMMAP, "Memory system initialized. RAM at %p (mirrors at 0 @ %p, 0x80000000 @ %p , 0xC0000000 @ %p)", - m_pRAM, m_pPhysicalRAM, m_pVirtualCachedRAM, m_pVirtualUncachedRAM); + INFO_LOG(MEMMAP, "Memory system initialized. RAM at %p", m_pRAM); m_IsInitialized = true; } void DoState(PointerWrap &p) { bool wii = SConfig::GetInstance().m_LocalCoreStartupParameter.bWii; - p.DoArray(m_pPhysicalRAM, RAM_SIZE); - p.DoArray(m_pVirtualL1Cache, L1_CACHE_SIZE); + p.DoArray(m_pRAM, RAM_SIZE); + p.DoArray(m_pL1Cache, L1_CACHE_SIZE); p.DoMarker("Memory RAM"); if (bFakeVMEM) - p.DoArray(m_pVirtualFakeVMEM, FAKEVMEM_SIZE); + p.DoArray(m_pFakeVMEM, FAKEVMEM_SIZE); p.DoMarker("Memory FakeVMEM"); if (wii) p.DoArray(m_pEXRAM, EXRAM_SIZE); @@ -183,7 +163,7 @@ void Shutdown() if (SConfig::GetInstance().m_LocalCoreStartupParameter.bWii) flags |= MV_WII_ONLY; if (bFakeVMEM) flags |= MV_FAKE_VMEM; MemoryMap_Shutdown(views, num_views, flags, &g_arena); - g_arena.ReleaseSpace(); + g_arena.ReleaseSHMSegment(); base = nullptr; delete mmio_mapping; INFO_LOG(MEMMAP, "Memory system shut down."); @@ -331,7 +311,7 @@ u8* GetPointer(const u32 _Address) case 0x0: case 0x8: if ((_Address & 0xfffffff) < REALRAM_SIZE) - return m_pPhysicalRAM + (_Address & RAM_MASK); + return m_pRAM + (_Address & RAM_MASK); case 0xc: switch (_Address >> 24) { @@ -344,7 +324,7 @@ u8* GetPointer(const u32 _Address) default: if ((_Address & 0xfffffff) < REALRAM_SIZE) - return m_pPhysicalRAM + (_Address & RAM_MASK); + return m_pRAM + (_Address & RAM_MASK); } case 0x1: @@ -353,7 +333,7 @@ u8* GetPointer(const u32 _Address) if (SConfig::GetInstance().m_LocalCoreStartupParameter.bWii) { if ((_Address & 0xfffffff) < EXRAM_SIZE) - return m_pPhysicalEXRAM + (_Address & EXRAM_MASK); + return m_pEXRAM + (_Address & EXRAM_MASK); } else break; @@ -366,7 +346,7 @@ u8* GetPointer(const u32 _Address) default: if (bFakeVMEM) - return m_pVirtualFakeVMEM + (_Address & FAKEVMEM_MASK); + return m_pFakeVMEM + (_Address & FAKEVMEM_MASK); } ERROR_LOG(MEMMAP, "Unknown Pointer %#8x PC %#8x LR %#8x", _Address, PC, LR); diff --git a/Source/Core/Core/HW/Memmap.h b/Source/Core/Core/HW/Memmap.h index e10eec6cbf..8c6a00c128 100644 --- a/Source/Core/Core/HW/Memmap.h +++ b/Source/Core/Core/HW/Memmap.h @@ -33,7 +33,6 @@ extern u8* base; extern u8* m_pRAM; extern u8* m_pEXRAM; extern u8* m_pL1Cache; -extern u8* m_pVirtualFakeVMEM; extern u8* m_pFakeVMEM; extern bool bFakeVMEM; @@ -48,11 +47,9 @@ enum RAM_MASK = RAM_SIZE - 1, FAKEVMEM_SIZE = 0x02000000, FAKEVMEM_MASK = FAKEVMEM_SIZE - 1, - L1_CACHE_SIZE = 0x40000, + L1_CACHE_SIZE = 0x00040000, L1_CACHE_MASK = L1_CACHE_SIZE - 1, - EFB_SIZE = 0x200000, - EFB_MASK = EFB_SIZE - 1, - IO_SIZE = 0x10000, + IO_SIZE = 0x00010000, EXRAM_SIZE = 0x04000000, EXRAM_MASK = EXRAM_SIZE - 1, diff --git a/Source/Core/Core/HW/MemmapFunctions.cpp b/Source/Core/Core/HW/MemmapFunctions.cpp index 194555004c..26ea59e4eb 100644 --- a/Source/Core/Core/HW/MemmapFunctions.cpp +++ b/Source/Core/Core/HW/MemmapFunctions.cpp @@ -90,7 +90,7 @@ static u32 EFB_Read(const u32 addr) static void GenerateDSIException(u32 _EffectiveAddress, bool _bWrite); template -inline void ReadFromHardware(T &_var, const u32 em_address, const u32 effective_address, Memory::XCheckTLBFlag flag) +inline void ReadFromHardware(T &_var, const u32 em_address, Memory::XCheckTLBFlag flag) { // TODO: Figure out the fastest order of tests for both read and write (they are probably different). if ((em_address & 0xC8000000) == 0xC8000000) @@ -197,7 +197,7 @@ inline void ReadFromHardware(T &_var, const u32 em_address, const u32 effective_ template -inline void WriteToHardware(u32 em_address, const T data, u32 effective_address, Memory::XCheckTLBFlag flag) +inline void WriteToHardware(u32 em_address, const T data, Memory::XCheckTLBFlag flag) { // First, let's check for FIFO writes, since they are probably the most common // reason we end up in this function: @@ -368,7 +368,7 @@ u32 Read_Opcode(u32 _Address) u8 Read_U8(const u32 _Address) { u8 _var = 0; - ReadFromHardware(_var, _Address, _Address, FLAG_READ); + ReadFromHardware(_var, _Address, FLAG_READ); #ifdef ENABLE_MEM_CHECK TMemCheck *mc = PowerPC::memchecks.GetMemCheck(_Address); if (mc) @@ -383,7 +383,7 @@ u8 Read_U8(const u32 _Address) u16 Read_U16(const u32 _Address) { u16 _var = 0; - ReadFromHardware(_var, _Address, _Address, FLAG_READ); + ReadFromHardware(_var, _Address, FLAG_READ); #ifdef ENABLE_MEM_CHECK TMemCheck *mc = PowerPC::memchecks.GetMemCheck(_Address); if (mc) @@ -398,7 +398,7 @@ u16 Read_U16(const u32 _Address) u32 Read_U32(const u32 _Address) { u32 _var = 0; - ReadFromHardware(_var, _Address, _Address, FLAG_READ); + ReadFromHardware(_var, _Address, FLAG_READ); #ifdef ENABLE_MEM_CHECK TMemCheck *mc = PowerPC::memchecks.GetMemCheck(_Address); if (mc) @@ -413,7 +413,7 @@ u32 Read_U32(const u32 _Address) u64 Read_U64(const u32 _Address) { u64 _var = 0; - ReadFromHardware(_var, _Address, _Address, FLAG_READ); + ReadFromHardware(_var, _Address, FLAG_READ); #ifdef ENABLE_MEM_CHECK TMemCheck *mc = PowerPC::memchecks.GetMemCheck(_Address); if (mc) @@ -469,7 +469,7 @@ void Write_U8(const u8 _Data, const u32 _Address) mc->Action(&PowerPC::debug_interface, _Data,_Address,true,1,PC); } #endif - WriteToHardware(_Address, _Data, _Address, FLAG_WRITE); + WriteToHardware(_Address, _Data, FLAG_WRITE); } @@ -484,7 +484,7 @@ void Write_U16(const u16 _Data, const u32 _Address) } #endif - WriteToHardware(_Address, _Data, _Address, FLAG_WRITE); + WriteToHardware(_Address, _Data, FLAG_WRITE); } void Write_U16_Swap(const u16 _Data, const u32 _Address) { @@ -502,7 +502,7 @@ void Write_U32(const u32 _Data, const u32 _Address) mc->Action(&PowerPC::debug_interface, _Data,_Address,true,4,PC); } #endif - WriteToHardware(_Address, _Data, _Address, FLAG_WRITE); + WriteToHardware(_Address, _Data, FLAG_WRITE); } void Write_U32_Swap(const u32 _Data, const u32 _Address) { @@ -520,7 +520,7 @@ void Write_U64(const u64 _Data, const u32 _Address) } #endif - WriteToHardware(_Address, _Data, _Address + 4, FLAG_WRITE); + WriteToHardware(_Address, _Data, FLAG_WRITE); } void Write_U64_Swap(const u64 _Data, const u32 _Address) { @@ -540,7 +540,7 @@ void Write_F64(const double _Data, const u32 _Address) u8 ReadUnchecked_U8(const u32 _Address) { u8 _var = 0; - ReadFromHardware(_var, _Address, _Address, FLAG_NO_EXCEPTION); + ReadFromHardware(_var, _Address, FLAG_NO_EXCEPTION); return _var; } @@ -548,19 +548,19 @@ u8 ReadUnchecked_U8(const u32 _Address) u32 ReadUnchecked_U32(const u32 _Address) { u32 _var = 0; - ReadFromHardware(_var, _Address, _Address, FLAG_NO_EXCEPTION); + ReadFromHardware(_var, _Address, FLAG_NO_EXCEPTION); return _var; } void WriteUnchecked_U8(const u8 _iValue, const u32 _Address) { - WriteToHardware(_Address, _iValue, _Address, FLAG_NO_EXCEPTION); + WriteToHardware(_Address, _iValue, FLAG_NO_EXCEPTION); } void WriteUnchecked_U32(const u32 _iValue, const u32 _Address) { - WriteToHardware(_Address, _iValue, _Address, FLAG_NO_EXCEPTION); + WriteToHardware(_Address, _iValue, FLAG_NO_EXCEPTION); } // ********************************************************************************* diff --git a/Source/Core/DolphinWX/Debugger/MemoryWindow.cpp b/Source/Core/DolphinWX/Debugger/MemoryWindow.cpp index 60978b6693..c620d327c6 100644 --- a/Source/Core/DolphinWX/Debugger/MemoryWindow.cpp +++ b/Source/Core/DolphinWX/Debugger/MemoryWindow.cpp @@ -278,7 +278,7 @@ void CMemoryWindow::OnDumpMem2( wxCommandEvent& event ) // Write fake vmem to file void CMemoryWindow::OnDumpFakeVMEM( wxCommandEvent& event ) { - DumpArray(File::GetUserPath(F_FAKEVMEMDUMP_IDX), Memory::m_pVirtualFakeVMEM, Memory::FAKEVMEM_SIZE); + DumpArray(File::GetUserPath(F_FAKEVMEMDUMP_IDX), Memory::m_pFakeVMEM, Memory::FAKEVMEM_SIZE); } void CMemoryWindow::U8(wxCommandEvent& event)