From 144f6809bf2f18464b9867caae1d6e649a8977c5 Mon Sep 17 00:00:00 2001 From: Nekotekina Date: Sun, 1 Oct 2017 04:40:11 +0300 Subject: [PATCH] Implement CALL_FUNC --- rpcs3/Emu/Cell/PPUModule.cpp | 44 +++++++++++++++++++++++++++++------- rpcs3/Emu/Cell/PPUModule.h | 31 +++++++++++++++++++++---- rpcs3/Emu/Cell/PPUThread.h | 14 ++++++++++++ 3 files changed, 76 insertions(+), 13 deletions(-) diff --git a/rpcs3/Emu/Cell/PPUModule.cpp b/rpcs3/Emu/Cell/PPUModule.cpp index ce6c6f63d7..dfd3fa0924 100644 --- a/rpcs3/Emu/Cell/PPUModule.cpp +++ b/rpcs3/Emu/Cell/PPUModule.cpp @@ -124,7 +124,8 @@ struct ppu_linkage_info { struct info { - bool hle = false; + ppu_static_function* static_func = nullptr; + ppu_static_variable* static_var = nullptr; u32 export_addr = 0; std::set imports; std::set frefss; @@ -315,8 +316,9 @@ static void ppu_initialize_modules(const std::shared_ptr& link { auto& flink = linkage.functions[function.first]; - flink.hle = true; + flink.static_func = &function.second; flink.export_addr = ppu_function_manager::addr + 8 * function.second.index; + function.second.export_addr = &flink.export_addr; } } @@ -364,8 +366,9 @@ static void ppu_initialize_modules(const std::shared_ptr& link { auto& vlink = linkage.variables[variable.first]; - vlink.hle = true; - vlink.export_addr = variable.second.var->addr(); + vlink.static_var = &variable.second; + vlink.export_addr = variable.second.addr; + variable.second.export_addr = &vlink.export_addr; } } } @@ -518,7 +521,12 @@ static auto ppu_load_exports(const std::shared_ptr& link, u32 // Function linkage info auto& flink = mlink.functions[fnid]; - if (flink.export_addr && !flink.hle) + if (flink.static_func && flink.export_addr == ppu_function_manager::addr + 8 * flink.static_func->index) + { + flink.export_addr = 0; + } + + if (flink.export_addr) { LOG_ERROR(LOADER, "Already linked function '%s' in module '%s'", ppu_get_function_name(module_name, fnid), module_name); } @@ -552,7 +560,6 @@ static auto ppu_load_exports(const std::shared_ptr& link, u32 { // Set exported function flink.export_addr = faddr; - flink.hle = false; // Fix imports for (const u32 addr : flink.imports) @@ -582,7 +589,12 @@ static auto ppu_load_exports(const std::shared_ptr& link, u32 // Variable linkage info auto& vlink = mlink.variables[vnid]; - if (vlink.export_addr && !vlink.hle) + if (vlink.static_var && vlink.export_addr == vlink.static_var->addr) + { + vlink.export_addr = 0; + } + + if (vlink.export_addr) { LOG_ERROR(LOADER, "Already linked variable '%s' in module '%s'", ppu_get_variable_name(module_name, vnid), module_name); } @@ -590,7 +602,6 @@ static auto ppu_load_exports(const std::shared_ptr& link, u32 { // Set exported variable vlink.export_addr = vaddr; - vlink.hle = false; // Fix imports for (const auto vref : vlink.imports) @@ -954,6 +965,23 @@ void ppu_unload_prx(const lv2_prx& prx) pinfo->imports.erase(imp.first); } + //for (auto& exp : prx.exports) + //{ + // auto pinfo = static_cast(exp.second); + // if (pinfo->static_func) + // { + // pinfo->export_addr = ppu_function_manager::addr + 8 * pinfo->static_func->index; + // } + // else if (pinfo->static_var) + // { + // pinfo->export_addr = pinfo->static_var->addr; + // } + // else + // { + // pinfo->export_addr = 0; + // } + //} + for (auto& seg : prx.segs) { vm::dealloc(seg.addr, vm::main); diff --git a/rpcs3/Emu/Cell/PPUModule.h b/rpcs3/Emu/Cell/PPUModule.h index 10082a6f26..ca11e49150 100644 --- a/rpcs3/Emu/Cell/PPUModule.h +++ b/rpcs3/Emu/Cell/PPUModule.h @@ -42,6 +42,7 @@ struct ppu_static_function u32 flags; const char* type; std::vector args; // Arg names + const u32* export_addr; ppu_static_function& flag(ppu_static_module_flags value) { @@ -61,6 +62,7 @@ struct ppu_static_variable const char* type; u32 flags; u32 addr; + const u32* export_addr; ppu_static_variable& flag(ppu_static_module_flags value) { @@ -109,10 +111,17 @@ class ppu_module_manager final static ppu_static_variable& access_static_variable(const char* module, u32 vnid); + // Global variable for each registered function + template + struct registered + { + static ppu_static_function* info; + }; + public: static const ppu_static_module* get_module(const std::string& name); - template + template static auto& register_static_function(const char* module, const char* name, ppu_function_t func, u32 fnid) { auto& info = access_static_function(module, fnid); @@ -122,10 +131,18 @@ public: info.flags = 0; info.type = typeid(T).name(); + registered::info = &info; + return info; } - template + template + static auto& find_static_function() + { + return *registered::info; + } + + template static auto& register_static_variable(const char* module, const char* name, u32 vnid) { static_assert(std::is_same>::value, "Static variable registration: vm::gvar expected"); @@ -249,14 +266,18 @@ public: static const ppu_static_module sys_lv2dbg; }; +template +ppu_static_function* ppu_module_manager::registered::info = nullptr; + // Call specified function directly if LLE is not available, call LLE equivalent in callback style otherwise template> -inline RT ppu_execute_function_or_callback(const char* name, ppu_thread& ppu, Args&&... args) +inline RT ppu_execute_function_or_callback(ppu_thread& ppu, Args&&... args) { - return Func(std::forward(args)...); + vm::ps3::ptr func = vm::cast(*ppu_module_manager::find_static_function().export_addr); + return func(ppu, std::forward(args)...); } -#define CALL_FUNC(ppu, func, ...) ppu_execute_function_or_callback(#func, ppu, __VA_ARGS__) +#define CALL_FUNC(ppu, func, ...) ppu_execute_function_or_callback(ppu, __VA_ARGS__) #define REG_FNID(module, nid, func) ppu_module_manager::register_static_function(#module, ppu_select_name(#func, nid), BIND_FUNC(func, ppu.cia = (u32)ppu.lr & ~3), ppu_generate_id(nid)) diff --git a/rpcs3/Emu/Cell/PPUThread.h b/rpcs3/Emu/Cell/PPUThread.h index b00c95070e..3d5be3f8ab 100644 --- a/rpcs3/Emu/Cell/PPUThread.h +++ b/rpcs3/Emu/Cell/PPUThread.h @@ -238,6 +238,20 @@ struct ppu_gpr_cast_impl, void> } }; +template <> +struct ppu_gpr_cast_impl +{ + static inline u64 to(const vm::null_t& value) + { + return 0; + } + + static inline vm::null_t from(const u64 reg) + { + return vm::null; + } +}; + template inline To ppu_gpr_cast(const From& value) {