Implement CALL_FUNC

This commit is contained in:
Nekotekina 2017-10-01 04:40:11 +03:00
parent d296e6021d
commit 144f6809bf
3 changed files with 76 additions and 13 deletions

View File

@ -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);

View File

@ -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))

View File

@ -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)
{