mirror of
https://github.com/RPCS3/rpcs3.git
synced 2024-11-16 23:17:29 +00:00
Implement CALL_FUNC
This commit is contained in:
parent
d296e6021d
commit
144f6809bf
@ -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<u32> imports;
|
||||
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];
|
||||
|
||||
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<ppu_linkage_info>& 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<ppu_linkage_info>& 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<ppu_linkage_info>& 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<ppu_linkage_info>& 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<ppu_linkage_info>& 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<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)
|
||||
{
|
||||
vm::dealloc(seg.addr, vm::main);
|
||||
|
@ -42,6 +42,7 @@ struct ppu_static_function
|
||||
u32 flags;
|
||||
const char* type;
|
||||
std::vector<const char*> 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 <typename T, T Func>
|
||||
struct registered
|
||||
{
|
||||
static ppu_static_function* info;
|
||||
};
|
||||
|
||||
public:
|
||||
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)
|
||||
{
|
||||
auto& info = access_static_function(module, fnid);
|
||||
@ -122,10 +131,18 @@ public:
|
||||
info.flags = 0;
|
||||
info.type = typeid(T).name();
|
||||
|
||||
registered<T, Func>::info = &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_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;
|
||||
};
|
||||
|
||||
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
|
||||
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))
|
||||
|
||||
|
@ -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>
|
||||
inline To ppu_gpr_cast(const From& value)
|
||||
{
|
||||
|
Loading…
Reference in New Issue
Block a user