diff --git a/Utilities/Thread.cpp b/Utilities/Thread.cpp index 87bb3a0f95..8690f67606 100644 --- a/Utilities/Thread.cpp +++ b/Utilities/Thread.cpp @@ -189,6 +189,13 @@ bool IsDebuggerPresent() } #endif +bool is_debugger_present() +{ + if (g_cfg.core.external_debugger) + return true; + return IsDebuggerPresent(); +} + #if defined(ARCH_X64) enum x64_reg_t : u32 { @@ -1630,7 +1637,7 @@ static void append_thread_name(std::string& msg) static LONG exception_handler(PEXCEPTION_POINTERS pExp) noexcept { - if (pExp->ExceptionRecord->ExceptionCode == EXCEPTION_BREAKPOINT && IsDebuggerPresent()) + if (pExp->ExceptionRecord->ExceptionCode == EXCEPTION_BREAKPOINT) { return EXCEPTION_CONTINUE_SEARCH; } diff --git a/rpcs3/Emu/Cell/PPUInterpreter.cpp b/rpcs3/Emu/Cell/PPUInterpreter.cpp index 52e90f803e..2f78420666 100644 --- a/rpcs3/Emu/Cell/PPUInterpreter.cpp +++ b/rpcs3/Emu/Cell/PPUInterpreter.cpp @@ -25,6 +25,8 @@ #pragma GCC diagnostic ignored "-Wold-style-cast" #endif +extern bool is_debugger_present(); + extern const ppu_decoder g_ppu_itype; extern const ppu_decoder g_ppu_iname; @@ -109,10 +111,17 @@ struct ppu_exec_select #define RETURN_(...) \ if constexpr (Build == 0) { \ static_cast(exec); \ - return +[](ppu_thread& ppu, ppu_opcode_t op, be_t* this_op, ppu_intrp_func* next_fn) { \ - const auto fn = atomic_storage::observe(next_fn->fn); \ + if (is_debugger_present()) return +[](ppu_thread& ppu, ppu_opcode_t op, be_t* this_op, ppu_intrp_func* next_fn) { \ exec(__VA_ARGS__); \ const auto next_op = this_op + 1; \ + const auto fn = atomic_storage::load(next_fn->fn); \ + ppu.cia = vm::get_addr(next_op); \ + return fn(ppu, {*next_op}, next_op, next_fn + 1); \ + }; \ + return +[](ppu_thread& ppu, ppu_opcode_t op, be_t* this_op, ppu_intrp_func* next_fn) { \ + exec(__VA_ARGS__); \ + const auto next_op = this_op + 1; \ + const auto fn = atomic_storage::observe(next_fn->fn); \ return fn(ppu, {*next_op}, next_op, next_fn + 1); \ }; \ } @@ -145,8 +154,6 @@ namespace asmjit ppu_builder(CodeHolder* ch) : base(ch) { - // Initialize pointer to next function - base::mov(x86::r11, x86::qword_ptr(arg_next_fn)); } // Indexed offset to ppu.member @@ -222,11 +229,15 @@ namespace asmjit void ppu_ret(bool last = true) { + // Initialize pointer to next function + base::mov(x86::rax, x86::qword_ptr(arg_next_fn)); base::add(arg_this_op, 4); + if (is_debugger_present()) + base::mov(ppu_mem<&ppu_thread::cia>(), arg_this_op.r32()); base::mov(arg_op, x86::dword_ptr(arg_this_op)); base::bswap(arg_op); base::add(arg_next_fn, 8); - base::jmp(x86::r11); + base::jmp(x86::rax); // Embed constants (TODO: after last return) if (last) diff --git a/rpcs3/Emu/system_config.h b/rpcs3/Emu/system_config.h index 9c24b95eae..17be037760 100644 --- a/rpcs3/Emu/system_config.h +++ b/rpcs3/Emu/system_config.h @@ -82,6 +82,7 @@ struct cfg_root : cfg::node cfg::uint64 perf_report_threshold{this, "Performance Report Threshold", 500, true}; // In µs, 0.5ms = default, 0 = everything cfg::_bool perf_report{this, "Enable Performance Report", false, true}; // Show certain perf-related logs + cfg::_bool external_debugger{this, "Assume External Debugger"}; } core{ this }; struct node_vfs : cfg::node