From df2fc13b7af77f6574a2199b0b95eb92bfc09065 Mon Sep 17 00:00:00 2001 From: Nekotekina Date: Fri, 6 Oct 2017 00:24:50 +0300 Subject: [PATCH] Add PPU instruction stat dumper Needs PPU Debug option to activate and PPU Interpreter Dumps after Resume (after Pause) Fix utils::memory_decommit, clean vm.cpp --- Utilities/VirtualMemory.cpp | 2 +- rpcs3/Emu/Cell/PPUInterpreter.cpp | 5 +++ rpcs3/Emu/Memory/vm.cpp | 64 +++++++++++-------------------- rpcs3/Emu/Memory/vm.h | 1 + rpcs3/Emu/System.cpp | 32 ++++++++++++++++ 5 files changed, 61 insertions(+), 43 deletions(-) diff --git a/Utilities/VirtualMemory.cpp b/Utilities/VirtualMemory.cpp index 5aad6ef062..ec34b91916 100644 --- a/Utilities/VirtualMemory.cpp +++ b/Utilities/VirtualMemory.cpp @@ -70,7 +70,7 @@ namespace utils void memory_decommit(void* pointer, std::size_t size) { #ifdef _WIN32 - verify(HERE), ::VirtualFree(pointer, 0, MEM_DECOMMIT); + verify(HERE), ::VirtualFree(pointer, size, MEM_DECOMMIT); #else verify(HERE), ::mmap(pointer, size, PROT_NONE, MAP_FIXED | MAP_ANON | MAP_PRIVATE, -1, 0); #endif diff --git a/rpcs3/Emu/Cell/PPUInterpreter.cpp b/rpcs3/Emu/Cell/PPUInterpreter.cpp index bf5dcf8788..ca2f4f794f 100644 --- a/rpcs3/Emu/Cell/PPUInterpreter.cpp +++ b/rpcs3/Emu/Cell/PPUInterpreter.cpp @@ -14,6 +14,11 @@ inline void ppu_cr_set(ppu_thread& ppu, u32 field, bool le, bool gt, bool eq, bo ppu.cr[field * 4 + 1] = gt; ppu.cr[field * 4 + 2] = eq; ppu.cr[field * 4 + 3] = so; + + if (UNLIKELY(g_cfg.core.ppu_debug)) + { + *(u32*)(vm::g_stat_addr + ppu.cia) |= *(u32*)(u8*)(ppu.cr + field * 4); + } } // Write comparison results to CR field diff --git a/rpcs3/Emu/Memory/vm.cpp b/rpcs3/Emu/Memory/vm.cpp index 75040eb842..b83f6d4cae 100644 --- a/rpcs3/Emu/Memory/vm.cpp +++ b/rpcs3/Emu/Memory/vm.cpp @@ -8,21 +8,6 @@ #include "Emu/Cell/lv2/sys_memory.h" #include "Emu/RSX/GSRender.h" -#ifdef _WIN32 -#include -#else -#include -#include -#include -#include -#include - -/* OS X uses MAP_ANON instead of MAP_ANONYMOUS */ -#ifndef MAP_ANONYMOUS -#define MAP_ANONYMOUS MAP_ANON -#endif -#endif - #include #include @@ -48,6 +33,9 @@ namespace vm // Auxiliary virtual memory for executable areas u8* const g_exec_addr = memory_reserve_4GiB((std::uintptr_t)g_base_addr); + // Stats for debugging + u8* const g_stat_addr = memory_reserve_4GiB((std::uintptr_t)g_exec_addr); + // Memory locations std::vector> g_locations; @@ -349,16 +337,17 @@ namespace vm } } - void* real_addr = g_base_addr + addr; - void* exec_addr = g_exec_addr + addr; + utils::memory_commit(g_base_addr + addr, size); -#ifdef _WIN32 - auto protection = flags & page_writable ? PAGE_READWRITE : (flags & page_readable ? PAGE_READONLY : PAGE_NOACCESS); - verify(__func__), ::VirtualAlloc(real_addr, size, MEM_COMMIT, protection); -#else - auto protection = flags & page_writable ? PROT_WRITE | PROT_READ : (flags & page_readable ? PROT_READ : PROT_NONE); - verify(__func__), !::mprotect(real_addr, size, protection), !::madvise(real_addr, size, MADV_WILLNEED); -#endif + if (flags & page_executable) + { + utils::memory_commit(g_exec_addr + addr, size); + } + + if (g_cfg.core.ppu_debug && g_system == system_type::ps3) + { + utils::memory_commit(g_stat_addr + addr, size); + } for (u32 i = addr / 4096; i < addr / 4096 + size / 4096; i++) { @@ -415,15 +404,8 @@ namespace vm { if (u32 page_size = (i - start) * 4096) { -#ifdef _WIN32 - DWORD old; - - auto protection = start_value & page_writable ? PAGE_READWRITE : (start_value & page_readable ? PAGE_READONLY : PAGE_NOACCESS); - verify(__func__), ::VirtualProtect(vm::base(start * 4096), page_size, protection, &old); -#else - auto protection = start_value & page_writable ? PROT_WRITE | PROT_READ : (start_value & page_readable ? PROT_READ : PROT_NONE); - verify(__func__), !::mprotect(vm::base(start * 4096), page_size, protection); -#endif + const auto protection = start_value & page_writable ? utils::protection::rw : (start_value & page_readable ? utils::protection::ro : utils::protection::no); + utils::memory_protect(g_base_addr + start * 4096, page_size, protection); } start_value = new_val; @@ -457,16 +439,13 @@ namespace vm } } - void* real_addr = g_base_addr + addr; - void* exec_addr = g_exec_addr + addr; + utils::memory_decommit(g_base_addr + addr, size); + utils::memory_decommit(g_exec_addr + addr, size); -#ifdef _WIN32 - verify(__func__), ::VirtualFree(real_addr, size, MEM_DECOMMIT); - verify(__func__), ::VirtualFree(exec_addr, size, MEM_DECOMMIT); -#else - verify(__func__), ::mmap(real_addr, size, PROT_NONE, MAP_FIXED | MAP_ANON | MAP_PRIVATE, -1, 0); - verify(__func__), ::mmap(exec_addr, size, PROT_NONE, MAP_FIXED | MAP_ANON | MAP_PRIVATE, -1, 0); -#endif + if (g_cfg.core.ppu_debug && g_system == system_type::ps3) + { + utils::memory_decommit(g_stat_addr + addr, size); + } } bool check_addr(u32 addr, u32 size, u8 flags) @@ -856,6 +835,7 @@ namespace vm utils::memory_decommit(g_base_addr, 0x100000000); utils::memory_decommit(g_exec_addr, 0x100000000); + utils::memory_decommit(g_stat_addr, 0x100000000); } } diff --git a/rpcs3/Emu/Memory/vm.h b/rpcs3/Emu/Memory/vm.h index 0c50f1d9e0..974180df73 100644 --- a/rpcs3/Emu/Memory/vm.h +++ b/rpcs3/Emu/Memory/vm.h @@ -11,6 +11,7 @@ namespace vm { extern u8* const g_base_addr; extern u8* const g_exec_addr; + extern u8* const g_stat_addr; enum memory_location_t : uint { diff --git a/rpcs3/Emu/System.cpp b/rpcs3/Emu/System.cpp index 98b3693edc..c1f19c38b4 100644 --- a/rpcs3/Emu/System.cpp +++ b/rpcs3/Emu/System.cpp @@ -7,6 +7,7 @@ #include "Emu/Cell/PPUThread.h" #include "Emu/Cell/PPUCallback.h" #include "Emu/Cell/PPUOpcodes.h" +#include "Emu/Cell/PPUDisAsm.h" #include "Emu/Cell/SPUThread.h" #include "Emu/Cell/RawSPUThread.h" #include "Emu/Cell/lv2/sys_sync.h" @@ -695,6 +696,37 @@ void Emulator::Resume() m_pause_amend_time += get_system_time() - time; } + // Print and reset debug data collected + if (m_state == system_state::paused && g_cfg.core.ppu_debug && g_system == system_type::ps3) + { + PPUDisAsm dis_asm(CPUDisAsm_InterpreterMode); + dis_asm.offset = vm::g_base_addr; + + std::string dump; + + for (u32 i = 0x10000; i < 0x40000000;) + { + if (vm::check_addr(i)) + { + if (auto& data = *(be_t*)(vm::g_stat_addr + i)) + { + dis_asm.dump_pc = i; + dis_asm.disasm(i); + fmt::append(dump, "\n\t'%08X' %s", data, dis_asm.last_opcode); + data = 0; + } + + i += sizeof(u32); + } + else + { + i += 4096; + } + } + + LOG_NOTICE(PPU, "[RESUME] Dumping instruction stats:%s", dump); + } + // Try to resume if (!m_state.compare_and_swap_test(system_state::paused, system_state::running)) {