mirror of https://github.com/RPCS3/rpcs3.git
Implement CALL_FUNC
This commit is contained in:
parent
d296e6021d
commit
144f6809bf
|
@ -124,7 +124,8 @@ struct ppu_linkage_info
|
||||||
{
|
{
|
||||||
struct info
|
struct info
|
||||||
{
|
{
|
||||||
bool hle = false;
|
ppu_static_function* static_func = nullptr;
|
||||||
|
ppu_static_variable* static_var = nullptr;
|
||||||
u32 export_addr = 0;
|
u32 export_addr = 0;
|
||||||
std::set<u32> imports;
|
std::set<u32> imports;
|
||||||
std::set<u32> frefss;
|
std::set<u32> frefss;
|
||||||
|
@ -315,8 +316,9 @@ static void ppu_initialize_modules(const std::shared_ptr<ppu_linkage_info>& link
|
||||||
{
|
{
|
||||||
auto& flink = linkage.functions[function.first];
|
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;
|
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<ppu_linkage_info>& link
|
||||||
{
|
{
|
||||||
auto& vlink = linkage.variables[variable.first];
|
auto& vlink = linkage.variables[variable.first];
|
||||||
|
|
||||||
vlink.hle = true;
|
vlink.static_var = &variable.second;
|
||||||
vlink.export_addr = variable.second.var->addr();
|
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<ppu_linkage_info>& link, u32
|
||||||
// Function linkage info
|
// Function linkage info
|
||||||
auto& flink = mlink.functions[fnid];
|
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);
|
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<ppu_linkage_info>& link, u32
|
||||||
{
|
{
|
||||||
// Set exported function
|
// Set exported function
|
||||||
flink.export_addr = faddr;
|
flink.export_addr = faddr;
|
||||||
flink.hle = false;
|
|
||||||
|
|
||||||
// Fix imports
|
// Fix imports
|
||||||
for (const u32 addr : flink.imports)
|
for (const u32 addr : flink.imports)
|
||||||
|
@ -582,7 +589,12 @@ static auto ppu_load_exports(const std::shared_ptr<ppu_linkage_info>& link, u32
|
||||||
// Variable linkage info
|
// Variable linkage info
|
||||||
auto& vlink = mlink.variables[vnid];
|
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);
|
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<ppu_linkage_info>& link, u32
|
||||||
{
|
{
|
||||||
// Set exported variable
|
// Set exported variable
|
||||||
vlink.export_addr = vaddr;
|
vlink.export_addr = vaddr;
|
||||||
vlink.hle = false;
|
|
||||||
|
|
||||||
// Fix imports
|
// Fix imports
|
||||||
for (const auto vref : vlink.imports)
|
for (const auto vref : vlink.imports)
|
||||||
|
@ -954,6 +965,23 @@ void ppu_unload_prx(const lv2_prx& prx)
|
||||||
pinfo->imports.erase(imp.first);
|
pinfo->imports.erase(imp.first);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
//for (auto& exp : prx.exports)
|
||||||
|
//{
|
||||||
|
// auto pinfo = static_cast<ppu_linkage_info::module::info*>(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)
|
for (auto& seg : prx.segs)
|
||||||
{
|
{
|
||||||
vm::dealloc(seg.addr, vm::main);
|
vm::dealloc(seg.addr, vm::main);
|
||||||
|
|
|
@ -42,6 +42,7 @@ struct ppu_static_function
|
||||||
u32 flags;
|
u32 flags;
|
||||||
const char* type;
|
const char* type;
|
||||||
std::vector<const char*> args; // Arg names
|
std::vector<const char*> args; // Arg names
|
||||||
|
const u32* export_addr;
|
||||||
|
|
||||||
ppu_static_function& flag(ppu_static_module_flags value)
|
ppu_static_function& flag(ppu_static_module_flags value)
|
||||||
{
|
{
|
||||||
|
@ -61,6 +62,7 @@ struct ppu_static_variable
|
||||||
const char* type;
|
const char* type;
|
||||||
u32 flags;
|
u32 flags;
|
||||||
u32 addr;
|
u32 addr;
|
||||||
|
const u32* export_addr;
|
||||||
|
|
||||||
ppu_static_variable& flag(ppu_static_module_flags value)
|
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);
|
static ppu_static_variable& access_static_variable(const char* module, u32 vnid);
|
||||||
|
|
||||||
|
// Global variable for each registered function
|
||||||
|
template <typename T, T Func>
|
||||||
|
struct registered
|
||||||
|
{
|
||||||
|
static ppu_static_function* info;
|
||||||
|
};
|
||||||
|
|
||||||
public:
|
public:
|
||||||
static const ppu_static_module* get_module(const std::string& name);
|
static const ppu_static_module* get_module(const std::string& name);
|
||||||
|
|
||||||
template<typename T, T Func>
|
template <typename T, T Func>
|
||||||
static auto& register_static_function(const char* module, const char* name, ppu_function_t func, u32 fnid)
|
static auto& register_static_function(const char* module, const char* name, ppu_function_t func, u32 fnid)
|
||||||
{
|
{
|
||||||
auto& info = access_static_function(module, fnid);
|
auto& info = access_static_function(module, fnid);
|
||||||
|
@ -122,10 +131,18 @@ public:
|
||||||
info.flags = 0;
|
info.flags = 0;
|
||||||
info.type = typeid(T).name();
|
info.type = typeid(T).name();
|
||||||
|
|
||||||
|
registered<T, Func>::info = &info;
|
||||||
|
|
||||||
return info;
|
return info;
|
||||||
}
|
}
|
||||||
|
|
||||||
template<typename T, T* Var>
|
template <typename T, T Func>
|
||||||
|
static auto& find_static_function()
|
||||||
|
{
|
||||||
|
return *registered<T, Func>::info;
|
||||||
|
}
|
||||||
|
|
||||||
|
template <typename T, T* Var>
|
||||||
static auto& register_static_variable(const char* module, const char* name, u32 vnid)
|
static auto& register_static_variable(const char* module, const char* name, u32 vnid)
|
||||||
{
|
{
|
||||||
static_assert(std::is_same<u32, std::decay_t<typename T::addr_type>>::value, "Static variable registration: vm::gvar<T> expected");
|
static_assert(std::is_same<u32, std::decay_t<typename T::addr_type>>::value, "Static variable registration: vm::gvar<T> expected");
|
||||||
|
@ -249,14 +266,18 @@ public:
|
||||||
static const ppu_static_module sys_lv2dbg;
|
static const ppu_static_module sys_lv2dbg;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
template<typename T, T Func>
|
||||||
|
ppu_static_function* ppu_module_manager::registered<T, Func>::info = nullptr;
|
||||||
|
|
||||||
// Call specified function directly if LLE is not available, call LLE equivalent in callback style otherwise
|
// Call specified function directly if LLE is not available, call LLE equivalent in callback style otherwise
|
||||||
template<typename T, T Func, typename... Args, typename RT = std::result_of_t<T(Args...)>>
|
template<typename T, T Func, typename... Args, typename RT = std::result_of_t<T(Args...)>>
|
||||||
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>(args)...);
|
vm::ps3::ptr<RT(Args...)> func = vm::cast(*ppu_module_manager::find_static_function<T, Func>().export_addr);
|
||||||
|
return func(ppu, std::forward<Args>(args)...);
|
||||||
}
|
}
|
||||||
|
|
||||||
#define CALL_FUNC(ppu, func, ...) ppu_execute_function_or_callback<decltype(&func), &func>(#func, ppu, __VA_ARGS__)
|
#define CALL_FUNC(ppu, func, ...) ppu_execute_function_or_callback<decltype(&func), &func>(ppu, __VA_ARGS__)
|
||||||
|
|
||||||
#define REG_FNID(module, nid, func) ppu_module_manager::register_static_function<decltype(&func), &func>(#module, ppu_select_name(#func, nid), BIND_FUNC(func, ppu.cia = (u32)ppu.lr & ~3), ppu_generate_id(nid))
|
#define REG_FNID(module, nid, func) ppu_module_manager::register_static_function<decltype(&func), &func>(#module, ppu_select_name(#func, nid), BIND_FUNC(func, ppu.cia = (u32)ppu.lr & ~3), ppu_generate_id(nid))
|
||||||
|
|
||||||
|
|
|
@ -238,6 +238,20 @@ struct ppu_gpr_cast_impl<vm::_ref_base<T, AT>, void>
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
template <>
|
||||||
|
struct ppu_gpr_cast_impl<vm::null_t, void>
|
||||||
|
{
|
||||||
|
static inline u64 to(const vm::null_t& value)
|
||||||
|
{
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
static inline vm::null_t from(const u64 reg)
|
||||||
|
{
|
||||||
|
return vm::null;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
template<typename To = u64, typename From>
|
template<typename To = u64, typename From>
|
||||||
inline To ppu_gpr_cast(const From& value)
|
inline To ppu_gpr_cast(const From& value)
|
||||||
{
|
{
|
||||||
|
|
Loading…
Reference in New Issue