diff --git a/rpcs3/Emu/Cell/PPUModule.cpp b/rpcs3/Emu/Cell/PPUModule.cpp index a817c7d46e..b7267e3f81 100644 --- a/rpcs3/Emu/Cell/PPUModule.cpp +++ b/rpcs3/Emu/Cell/PPUModule.cpp @@ -2121,7 +2121,7 @@ bool ppu_load_exec(const ppu_exec_object& elf, utils::serial* ar) } // Program entry - u32 entry = 0; + u32 entry = static_cast(elf.header.e_entry); // Run entry from elf (HLE) // Set path (TODO) _main.name.clear(); @@ -2264,6 +2264,7 @@ bool ppu_load_exec(const ppu_exec_object& elf, utils::serial* ar) ppu_thread_params p{}; p.stack_addr = vm::cast(vm::alloc(primary_stacksize, vm::stack, 4096)); p.stack_size = primary_stacksize; + p.entry = vm::_ref(entry); auto ppu = idm::make_ptr>(p, "main_thread", primary_prio, 1); @@ -2278,7 +2279,7 @@ bool ppu_load_exec(const ppu_exec_object& elf, utils::serial* ar) ppu->cmd_push({ppu_cmd::initialize, 0}); - if (!entry && !Emu.IsVsh()) + if (entry == static_cast(elf.header.e_entry) && !Emu.IsVsh()) { // Set TLS args, call sys_initialize_tls ppu->cmd_list @@ -2288,11 +2289,6 @@ bool ppu_load_exec(const ppu_exec_object& elf, utils::serial* ar) }); } - if (!entry) - { - entry = static_cast(elf.header.e_entry); // Run entry from elf - } - // Run start functions for (const auto& prx : loaded_modules) { @@ -2315,7 +2311,7 @@ bool ppu_load_exec(const ppu_exec_object& elf, utils::serial* ar) { ppu_cmd::set_args, 8 }, u64{Emu.argv.size()}, u64{argv.addr()}, u64{envp.addr()}, u64{0}, u64{ppu->id}, u64{tls_vaddr}, u64{tls_fsize}, u64{tls_vsize}, { ppu_cmd::set_gpr, 11 }, u64{elf.header.e_entry}, { ppu_cmd::set_gpr, 12 }, u64{malloc_pagesize}, - { ppu_cmd::lle_call, entry }, + { ppu_cmd::entry_call, 0 }, }); // Set actual memory protection (experimental) diff --git a/rpcs3/Emu/Cell/PPUThread.cpp b/rpcs3/Emu/Cell/PPUThread.cpp index 70a596f658..a5c528b0c5 100644 --- a/rpcs3/Emu/Cell/PPUThread.cpp +++ b/rpcs3/Emu/Cell/PPUThread.cpp @@ -1480,6 +1480,14 @@ void ppu_thread::cpu_task() cmd_pop(), fast_call(opd[0], opd[1]); break; } + case ppu_cmd::entry_call: + { +#ifdef __APPLE__ + pthread_jit_write_protect_np(true); +#endif + cmd_pop(), fast_call(entry_func.addr, entry_func.rtoc, true); + break; + } case ppu_cmd::hle_call: { cmd_pop(), ::at32(ppu_function_manager::get(), arg)(*this, {arg}, vm::_ptr(cia - 4), &ppu_ret); @@ -1503,7 +1511,7 @@ void ppu_thread::cpu_task() case ppu_cmd::cia_call: { loaded_from_savestate = true; - cmd_pop(), fast_call(std::exchange(cia, 0), gpr[2]); + cmd_pop(), fast_call(std::exchange(cia, 0), gpr[2], true); break; } case ppu_cmd::initialize: @@ -2000,7 +2008,7 @@ be_t* ppu_thread::get_stack_arg(s32 i, u64 align) return vm::_ptr(vm::cast((gpr[1] + 0x30 + 0x8 * (i - 1)) & (0 - align))); } -void ppu_thread::fast_call(u32 addr, u64 rtoc) +void ppu_thread::fast_call(u32 addr, u64 rtoc, bool is_thread_entry) { const auto old_cia = cia; const auto old_rtoc = gpr[2]; @@ -2066,7 +2074,7 @@ void ppu_thread::fast_call(u32 addr, u64 rtoc) gpr[2] = old_rtoc; lr = old_lr; } - else if (state & cpu_flag::ret && cia == g_fxo->get().func_addr(1, true) + 4) + else if (state & cpu_flag::ret && cia == g_fxo->get().func_addr(1, true) + 4 && is_thread_entry) { std::string ret; dump_all(ret); @@ -2076,7 +2084,9 @@ void ppu_thread::fast_call(u32 addr, u64 rtoc) lv2_obj::sleep(*this); - state += cpu_flag::again; // For savestates + // For savestates + state += cpu_flag::again; + std::memcpy(syscall_args, &gpr[3], sizeof(syscall_args)); } current_function = old_func; diff --git a/rpcs3/Emu/Cell/PPUThread.h b/rpcs3/Emu/Cell/PPUThread.h index 41135cea5c..8e94252306 100644 --- a/rpcs3/Emu/Cell/PPUThread.h +++ b/rpcs3/Emu/Cell/PPUThread.h @@ -22,6 +22,7 @@ enum class ppu_cmd : u32 ptr_call, // Execute function by pointer opd_call, // Execute function by provided rtoc and address (unlike lle_call, does not read memory) cia_call, // Execute from current CIA, mo GPR modification applied + entry_call, // Load addr and rtoc from entry_func initialize, // ppu_initialize() sleep, reset_stack, // resets stack address @@ -339,7 +340,7 @@ public: be_t* get_stack_arg(s32 i, u64 align = alignof(u64)); void exec_task(); - void fast_call(u32 addr, u64 rtoc); + void fast_call(u32 addr, u64 rtoc, bool is_thread_entry = false); static std::pair stack_push(u32 size, u32 align_v); static void stack_pop_verbose(u32 addr, u32 size) noexcept; diff --git a/rpcs3/Emu/Cell/lv2/sys_interrupt.cpp b/rpcs3/Emu/Cell/lv2/sys_interrupt.cpp index 9853c8eeee..f18fb96502 100644 --- a/rpcs3/Emu/Cell/lv2/sys_interrupt.cpp +++ b/rpcs3/Emu/Cell/lv2/sys_interrupt.cpp @@ -75,7 +75,7 @@ void lv2_int_serv::exec() const ({ { ppu_cmd::reset_stack, 0 }, { ppu_cmd::set_args, 2 }, arg1, arg2, - { ppu_cmd::opd_call, 0 }, thread->entry_func, + { ppu_cmd::entry_call, 0 }, { ppu_cmd::sleep, 0 }, { ppu_cmd::ptr_call, 0 }, std::bit_cast(&ppu_interrupt_thread_entry) diff --git a/rpcs3/Emu/Cell/lv2/sys_ppu_thread.cpp b/rpcs3/Emu/Cell/lv2/sys_ppu_thread.cpp index 822648ee53..b09dc25e02 100644 --- a/rpcs3/Emu/Cell/lv2/sys_ppu_thread.cpp +++ b/rpcs3/Emu/Cell/lv2/sys_ppu_thread.cpp @@ -563,7 +563,7 @@ error_code sys_ppu_thread_start(ppu_thread& ppu, u32 thread_id) thread.cmd_list ({ - {ppu_cmd::opd_call, 0}, thread.entry_func + {ppu_cmd::entry_call, 0}, }); return {};