From e459d019272975b0f18b44db9a9803c053897289 Mon Sep 17 00:00:00 2001 From: Vincent Lejeune Date: Sun, 26 Jul 2015 01:39:55 +0200 Subject: [PATCH] PPU/LLVM: Add debug tool for LLVM recompiler --- rpcs3/Emu/Cell/PPULLVMRecompiler.cpp | 77 ++++++++++++++++------------ rpcs3/Emu/Cell/PPULLVMRecompiler.h | 6 ++- rpcs3/Gui/MainFrame.cpp | 28 ++++++++++ rpcs3/Ini.h | 16 ++++++ 4 files changed, 92 insertions(+), 35 deletions(-) diff --git a/rpcs3/Emu/Cell/PPULLVMRecompiler.cpp b/rpcs3/Emu/Cell/PPULLVMRecompiler.cpp index 0676c8f828..a199490448 100644 --- a/rpcs3/Emu/Cell/PPULLVMRecompiler.cpp +++ b/rpcs3/Emu/Cell/PPULLVMRecompiler.cpp @@ -279,6 +279,7 @@ std::shared_ptr RecompilationEngine::s_the_instance = nullp RecompilationEngine::RecompilationEngine() : m_log(nullptr) + , m_currentId(0) , m_last_cache_clear_time(std::chrono::high_resolution_clock::now()) , m_compiler(*this, CPUHybridDecoderRecompiler::ExecuteFunction, CPUHybridDecoderRecompiler::ExecuteTillReturn, CPUHybridDecoderRecompiler::PollStatus) { m_compiler.RunAllTests(); @@ -312,6 +313,9 @@ const Executable *RecompilationEngine::GetCompiledExecutableIfAvailable(u32 addr return nullptr; if (std::get<1>(It->second) == nullptr) return nullptr; + u32 id = std::get<3>(It->second); + if (Ini.LLVMExclusionRange.GetValue() && (id >= Ini.LLVMMinId.GetValue() && id <= Ini.LLVMMaxId.GetValue())) + return nullptr; return &(std::get<0>(It->second)); } @@ -495,7 +499,7 @@ void RecompilationEngine::ProcessExecutionTrace(const ExecutionTrace & execution for (auto i = processed_execution_trace_i->second.begin(); i != processed_execution_trace_i->second.end(); i++) { if (!(*i)->is_compiled) { (*i)->num_hits++; - if ((*i)->num_hits >= 1000) { // TODO: Make this configurable + if ((*i)->num_hits >= Ini.LLVMThreshold.GetValue()) { CompileBlock(*(*i)); } } @@ -569,6 +573,9 @@ void RecompilationEngine::CompileBlock(BlockEntry & block_entry) { std::get<1>(m_address_to_function[block_entry.cfg.start_address]) = std::unique_ptr(compileResult.second); std::get<0>(m_address_to_function[block_entry.cfg.start_address]) = compileResult.first; + std::get<3>(m_address_to_function[block_entry.cfg.start_address]) = m_currentId; + Log() << "ID IS " << m_currentId << "\n"; + m_currentId++; block_entry.last_compiled_cfg_size = block_entry.cfg.GetSize(); block_entry.is_compiled = true; } @@ -722,39 +729,43 @@ u32 ppu_recompiler_llvm::CPUHybridDecoderRecompiler::ExecuteTillReturn(PPUThread mut->second.fetch_add(1); } const Executable *executable = execution_engine->m_recompilation_engine->GetCompiledExecutableIfAvailable(ppu_state->PC); - auto entry = ppu_state->PC; - u32 exit = (u32)(*executable)(ppu_state, 0); - execution_engine->m_tracer.Trace(Tracer::TraceType::ExitFromCompiledBlock, entry, exit); - mut->second.fetch_sub(1); - if (exit == 0) - return 0; - } else { - execution_engine->m_tracer.Trace(Tracer::TraceType::Instruction, ppu_state->PC, 0); - u32 instruction = vm::ps3::read32(ppu_state->PC); - u32 oldPC = ppu_state->PC; - execution_engine->m_decoder.Decode(instruction); - auto branch_type = ppu_state->PC != oldPC ? GetBranchTypeFromInstruction(instruction) : BranchType::NonBranch; - ppu_state->PC += 4; + if (executable) + { + auto entry = ppu_state->PC; + u32 exit = (u32)(*executable)(ppu_state, 0); + mut->second.fetch_sub(1); + execution_engine->m_tracer.Trace(Tracer::TraceType::ExitFromCompiledBlock, entry, exit); + if (exit == 0) + return 0; + continue; + } + mut->second.fetch_add(1); + } + execution_engine->m_tracer.Trace(Tracer::TraceType::Instruction, ppu_state->PC, 0); + u32 instruction = vm::ps3::read32(ppu_state->PC); + u32 oldPC = ppu_state->PC; + execution_engine->m_decoder.Decode(instruction); + auto branch_type = ppu_state->PC != oldPC ? GetBranchTypeFromInstruction(instruction) : BranchType::NonBranch; + ppu_state->PC += 4; - switch (branch_type) { - case BranchType::Return: - execution_engine->m_tracer.Trace(Tracer::TraceType::Return, 0, 0); - if (Emu.GetCPUThreadStop() == ppu_state->PC) ppu_state->fast_stop(); - return 0; - case BranchType::FunctionCall: { - execution_engine->m_tracer.Trace(Tracer::TraceType::CallFunction, ppu_state->PC, 0); - const Executable *executable = execution_engine->m_recompilation_engine->GetExecutable(ppu_state->PC, true); - (*executable)(ppu_state, 0); - break; - } - case BranchType::LocalBranch: - break; - case BranchType::NonBranch: - break; - default: - assert(0); - break; - } + switch (branch_type) { + case BranchType::Return: + execution_engine->m_tracer.Trace(Tracer::TraceType::Return, 0, 0); + if (Emu.GetCPUThreadStop() == ppu_state->PC) ppu_state->fast_stop(); + return 0; + case BranchType::FunctionCall: { + execution_engine->m_tracer.Trace(Tracer::TraceType::CallFunction, ppu_state->PC, 0); + const Executable *executable = execution_engine->m_recompilation_engine->GetExecutable(ppu_state->PC, true); + (*executable)(ppu_state, 0); + break; + } + case BranchType::LocalBranch: + break; + case BranchType::NonBranch: + break; + default: + assert(0); + break; } } diff --git a/rpcs3/Emu/Cell/PPULLVMRecompiler.h b/rpcs3/Emu/Cell/PPULLVMRecompiler.h index 4a24a7e97c..71fd79f001 100644 --- a/rpcs3/Emu/Cell/PPULLVMRecompiler.h +++ b/rpcs3/Emu/Cell/PPULLVMRecompiler.h @@ -1103,8 +1103,10 @@ namespace ppu_recompiler_llvm { /// Lock for modifying address mutex table std::mutex m_address_locks_lock; - /// (function, module containing function, times hit, mutex for access). - typedef std::tuple, u32> ExecutableStorage; + int m_currentId; + + /// (function, module containing function, times hit, id). + typedef std::tuple, u32, u32> ExecutableStorage; /// Address to ordinal cahce. Key is address. std::unordered_map m_address_to_function; std::unordered_map > > m_address_locks; diff --git a/rpcs3/Gui/MainFrame.cpp b/rpcs3/Gui/MainFrame.cpp index 5a06624cf3..3016be4d22 100644 --- a/rpcs3/Gui/MainFrame.cpp +++ b/rpcs3/Gui/MainFrame.cpp @@ -396,6 +396,9 @@ void MainFrame::Config(wxCommandEvent& WXUNUSED(event)) // Core settings wxStaticBoxSizer* s_round_cpu_decoder = new wxStaticBoxSizer(wxVERTICAL, p_core, _("CPU")); wxStaticBoxSizer* s_round_spu_decoder = new wxStaticBoxSizer(wxVERTICAL, p_core, _("SPU")); + wxStaticBoxSizer* s_round_llvm = new wxStaticBoxSizer(wxVERTICAL, p_core, _("LLVM config")); + wxStaticBoxSizer* s_round_llvm_range = new wxStaticBoxSizer(wxHORIZONTAL, p_core, _("Excluded block range")); + wxStaticBoxSizer* s_round_llvm_threshold = new wxStaticBoxSizer(wxHORIZONTAL, p_core, _("Compilation threshold")); // Graphics wxStaticBoxSizer* s_round_gs_render = new wxStaticBoxSizer(wxVERTICAL, p_graphics, _("Render")); @@ -440,6 +443,7 @@ void MainFrame::Config(wxCommandEvent& WXUNUSED(event)) wxComboBox* cbox_net_interface = new wxComboBox(p_networking, wxID_ANY); wxComboBox* cbox_sys_lang = new wxComboBox(p_system, wxID_ANY); + wxCheckBox* chbox_core_llvm_exclud = new wxCheckBox(p_core, wxID_ANY, "Enable exclusion of compiled blocks"); wxCheckBox* chbox_core_hook_stfunc = new wxCheckBox(p_core, wxID_ANY, "Hook static functions"); wxCheckBox* chbox_core_load_liblv2 = new wxCheckBox(p_core, wxID_ANY, "Load liblv2.sprx"); wxCheckBox* chbox_gs_log_prog = new wxCheckBox(p_graphics, wxID_ANY, "Log vertex/fragment programs"); @@ -456,6 +460,10 @@ void MainFrame::Config(wxCommandEvent& WXUNUSED(event)) wxCheckBox* chbox_hle_exitonstop = new wxCheckBox(p_misc, wxID_ANY, "Exit RPCS3 when process finishes"); wxCheckBox* chbox_hle_always_start = new wxCheckBox(p_misc, wxID_ANY, "Always start after boot"); + wxTextCtrl* txt_dbg_range_min = new wxTextCtrl(p_core, wxID_ANY); + wxTextCtrl* txt_dbg_range_max = new wxTextCtrl(p_core, wxID_ANY); + wxTextCtrl* txt_llvm_threshold = new wxTextCtrl(p_core, wxID_ANY); + //Auto Pause wxCheckBox* chbox_dbg_ap_systemcall = new wxCheckBox(p_misc, wxID_ANY, "Auto Pause at System Call"); wxCheckBox* chbox_dbg_ap_functioncall = new wxCheckBox(p_misc, wxID_ANY, "Auto Pause at Function Call"); @@ -601,6 +609,7 @@ void MainFrame::Config(wxCommandEvent& WXUNUSED(event)) cbox_sys_lang->Append("English (UK)"); // Get values from .ini + chbox_core_llvm_exclud ->SetValue(Ini.LLVMExclusionRange.GetValue()); chbox_gs_log_prog ->SetValue(Ini.GSLogPrograms.GetValue()); chbox_gs_dump_depth ->SetValue(Ini.GSDumpDepthBuffer.GetValue()); chbox_gs_dump_color ->SetValue(Ini.GSDumpColorBuffers.GetValue()); @@ -626,6 +635,9 @@ void MainFrame::Config(wxCommandEvent& WXUNUSED(event)) txt_emulationdir_path ->SetValue(Ini.SysEmulationDirPath.GetValue()); cbox_cpu_decoder ->SetSelection(Ini.CPUDecoderMode.GetValue() ? Ini.CPUDecoderMode.GetValue() : 0); + txt_dbg_range_min ->SetValue(std::to_string(Ini.LLVMMinId.GetValue())); + txt_dbg_range_max ->SetValue(std::to_string(Ini.LLVMMaxId.GetValue())); + txt_llvm_threshold ->SetValue(std::to_string(Ini.LLVMThreshold.GetValue())); cbox_spu_decoder ->SetSelection(Ini.SPUDecoderMode.GetValue() ? Ini.SPUDecoderMode.GetValue() : 0); cbox_gs_render ->SetSelection(Ini.GSRenderMode.GetValue()); cbox_gs_resolution ->SetSelection(ResolutionIdToNum(Ini.GSResolution.GetValue()) - 1); @@ -645,6 +657,12 @@ void MainFrame::Config(wxCommandEvent& WXUNUSED(event)) // Core s_round_cpu_decoder->Add(cbox_cpu_decoder, wxSizerFlags().Border(wxALL, 5).Expand()); s_round_spu_decoder->Add(cbox_spu_decoder, wxSizerFlags().Border(wxALL, 5).Expand()); + s_round_llvm->Add(chbox_core_llvm_exclud, wxSizerFlags().Border(wxALL, 5).Expand()); + s_round_llvm_range->Add(txt_dbg_range_min, wxSizerFlags().Border(wxALL, 5).Expand()); + s_round_llvm_range->Add(txt_dbg_range_max, wxSizerFlags().Border(wxALL, 5).Expand()); + s_round_llvm->Add(s_round_llvm_range, wxSizerFlags().Border(wxALL, 5).Expand()); + s_round_llvm_threshold->Add(txt_llvm_threshold, wxSizerFlags().Border(wxALL, 5).Expand()); + s_round_llvm->Add(s_round_llvm_threshold, wxSizerFlags().Border(wxALL, 5).Expand()); // Rendering s_round_gs_render->Add(cbox_gs_render, wxSizerFlags().Border(wxALL, 5).Expand()); @@ -672,6 +690,7 @@ void MainFrame::Config(wxCommandEvent& WXUNUSED(event)) // Core s_subpanel_core->Add(s_round_cpu_decoder, wxSizerFlags().Border(wxALL, 5).Expand()); s_subpanel_core->Add(s_round_spu_decoder, wxSizerFlags().Border(wxALL, 5).Expand()); + s_subpanel_core->Add(s_round_llvm, wxSizerFlags().Border(wxALL, 5).Expand()); s_subpanel_core->Add(chbox_core_hook_stfunc, wxSizerFlags().Border(wxALL, 5).Expand()); s_subpanel_core->Add(chbox_core_load_liblv2, wxSizerFlags().Border(wxALL, 5).Expand()); @@ -742,6 +761,15 @@ void MainFrame::Config(wxCommandEvent& WXUNUSED(event)) if(diag.ShowModal() == wxID_OK) { Ini.CPUDecoderMode.SetValue(cbox_cpu_decoder->GetSelection()); + long minllvmid, maxllvmid; + txt_dbg_range_min->GetValue().ToLong(&minllvmid); + txt_dbg_range_max->GetValue().ToLong(&maxllvmid); + Ini.LLVMExclusionRange.SetValue(chbox_core_llvm_exclud->GetValue()); + Ini.LLVMMinId.SetValue(minllvmid); + Ini.LLVMMaxId.SetValue(maxllvmid); + long llvmthreshold; + txt_llvm_threshold->GetValue().ToLong(&llvmthreshold); + Ini.LLVMThreshold.SetValue(llvmthreshold); Ini.SPUDecoderMode.SetValue(cbox_spu_decoder->GetSelection()); Ini.HookStFunc.SetValue(chbox_core_hook_stfunc->GetValue()); Ini.LoadLibLv2.SetValue(chbox_core_load_liblv2->GetValue()); diff --git a/rpcs3/Ini.h b/rpcs3/Ini.h index 5e43bc0353..c2ffb59e89 100644 --- a/rpcs3/Ini.h +++ b/rpcs3/Ini.h @@ -92,6 +92,10 @@ private: public: // Core IniEntry CPUDecoderMode; + IniEntry LLVMExclusionRange; + IniEntry LLVMMinId; + IniEntry LLVMMaxId; + IniEntry LLVMThreshold; IniEntry SPUDecoderMode; IniEntry HookStFunc; IniEntry LoadLibLv2; @@ -176,6 +180,10 @@ public: // Core CPUDecoderMode.Init("CORE_DecoderMode", path); + LLVMExclusionRange.Init("LLVM_Exclusion_Range", path); + LLVMMinId.Init("LLVM_Min_ID", path); + LLVMMaxId.Init("LLVM_Max_ID", path); + LLVMThreshold.Init("LLVM_Threshold", path); SPUDecoderMode.Init("CORE_SPUDecoderMode", path); HookStFunc.Init("CORE_HookStFunc", path); LoadLibLv2.Init("CORE_LoadLibLv2", path); @@ -256,6 +264,10 @@ public: { // Core CPUDecoderMode.Load(0); + LLVMExclusionRange.Load(false); + LLVMMinId.Load(200); + LLVMMaxId.Load(250); + LLVMThreshold.Load(1000); SPUDecoderMode.Load(0); HookStFunc.Load(false); LoadLibLv2.Load(false); @@ -336,6 +348,10 @@ public: { // Core CPUDecoderMode.Save(); + LLVMExclusionRange.Save(); + LLVMMinId.Save(); + LLVMMaxId.Save(); + LLVMThreshold.Save(); SPUDecoderMode.Save(); HookStFunc.Save(); LoadLibLv2.Save();