mirror of
https://github.com/RPCS3/rpcs3.git
synced 2025-04-21 12:05:23 +00:00
Flags for HLE functions
This commit is contained in:
parent
5416782392
commit
07cb56e1ea
10 changed files with 134 additions and 104 deletions
|
@ -9,22 +9,7 @@ u32 add_psv_func(psv_func data)
|
|||
{
|
||||
for (auto& f : g_psv_func_list)
|
||||
{
|
||||
if (f.nid == data.nid)
|
||||
{
|
||||
const u32 index = (u32)(&f - g_psv_func_list.data());
|
||||
|
||||
if (index < SFI_MAX)
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
if (data.func)
|
||||
{
|
||||
f.func = data.func;
|
||||
}
|
||||
|
||||
return index;
|
||||
}
|
||||
assert(f.nid != data.nid || (&f - g_psv_func_list.data()) < SFI_MAX);
|
||||
}
|
||||
|
||||
g_psv_func_list.push_back(data);
|
||||
|
|
|
@ -38,7 +38,7 @@ typedef void(*psv_func_caller)(ARMv7Context&);
|
|||
// Utilities for binding ARMv7Context to C++ function arguments received by HLE functions or sent to callbacks
|
||||
namespace psv_func_detail
|
||||
{
|
||||
enum bind_arg_type
|
||||
enum arg_class
|
||||
{
|
||||
ARG_GENERAL,
|
||||
ARG_FLOAT,
|
||||
|
@ -48,7 +48,7 @@ namespace psv_func_detail
|
|||
|
||||
static const auto FIXED_STACK_FRAME_SIZE = 0x100; // described in CB_FUNC.h
|
||||
|
||||
template<typename T, bind_arg_type type, int g_count, int f_count, int v_count>
|
||||
template<typename T, arg_class type, int g_count, int f_count, int v_count>
|
||||
struct bind_arg;
|
||||
|
||||
template<typename T, int g_count, int f_count, int v_count>
|
||||
|
@ -191,7 +191,7 @@ namespace psv_func_detail
|
|||
}
|
||||
};
|
||||
|
||||
template<typename T, bind_arg_type type>
|
||||
template<typename T, arg_class type>
|
||||
struct bind_result
|
||||
{
|
||||
static_assert(type != ARG_FLOAT, "TODO: Unsupported funcion result type (float)");
|
||||
|
@ -265,7 +265,7 @@ namespace psv_func_detail
|
|||
static_assert(!std::is_reference<RT>::value, "Invalid function result type (reference)");
|
||||
static const bool is_float = std::is_floating_point<RT>::value;
|
||||
static const bool is_vector = std::is_same<RT, u128>::value;
|
||||
static const bind_arg_type value = is_float ? ARG_FLOAT : (is_vector ? ARG_VECTOR : ARG_GENERAL);
|
||||
static const arg_class value = is_float ? ARG_FLOAT : (is_vector ? ARG_VECTOR : ARG_GENERAL);
|
||||
};
|
||||
|
||||
template<typename T, int g_count, int f_count, int v_count>
|
||||
|
@ -281,7 +281,7 @@ namespace psv_func_detail
|
|||
static const int g_next = g_pos + g_align - 1;
|
||||
static const int f_value = !is_float ? f_count : f_count + 1;
|
||||
static const int v_value = !is_vector ? v_count : v_count + 1;
|
||||
static const bind_arg_type value = is_float
|
||||
static const arg_class value = is_float
|
||||
? ((f_value > 9000) ? ARG_STACK : ARG_FLOAT)
|
||||
: (is_vector ? ((v_value > 9000) ? ARG_STACK : ARG_VECTOR) : ((g_pos > 4) ? ARG_STACK : ARG_GENERAL));
|
||||
};
|
||||
|
@ -322,7 +322,7 @@ namespace psv_func_detail
|
|||
__forceinline std::tuple<T, A...> get_func_args(ARMv7Context& context)
|
||||
{
|
||||
typedef arg_type<T, g_count, f_count, v_count> type;
|
||||
const bind_arg_type t = type::value;
|
||||
const arg_class t = type::value;
|
||||
const int g0 = type::g_pos;
|
||||
const int g1 = type::g_next;
|
||||
const int f = type::f_value;
|
||||
|
@ -342,7 +342,7 @@ namespace psv_func_detail
|
|||
__forceinline static bool put_func_args(ARMv7Context& context, T1 arg, T... args)
|
||||
{
|
||||
typedef arg_type<T1, g_count, f_count, v_count> type;
|
||||
const bind_arg_type t = type::value;
|
||||
const arg_class t = type::value;
|
||||
const int g0 = type::g_pos;
|
||||
const int g1 = type::g_next;
|
||||
const int f = type::f_value;
|
||||
|
@ -435,9 +435,23 @@ namespace psv_func_detail
|
|||
struct psv_func
|
||||
{
|
||||
u32 nid; // Unique function ID (should be generated individually for each elf loaded)
|
||||
u32 flags;
|
||||
const char* name; // Function name for information
|
||||
psv_func_caller func; // Function caller
|
||||
psv_log_base* module; // Module for information
|
||||
|
||||
psv_func()
|
||||
{
|
||||
}
|
||||
|
||||
psv_func(u32 nid, u32 flags, psv_log_base* module, const char* name, psv_func_caller func)
|
||||
: nid(nid)
|
||||
, flags(flags)
|
||||
, name(name)
|
||||
, func(func)
|
||||
, module(module)
|
||||
{
|
||||
}
|
||||
};
|
||||
|
||||
enum psv_special_function_index : u16
|
||||
|
@ -450,23 +464,12 @@ enum psv_special_function_index : u16
|
|||
// Do not call directly
|
||||
u32 add_psv_func(psv_func data);
|
||||
// Do not call directly
|
||||
__forceinline static u32 add_psv_func(u32 nid, psv_log_base* module, const char* name, psv_func_caller func)
|
||||
{
|
||||
psv_func f;
|
||||
f.nid = nid;
|
||||
f.name = name;
|
||||
f.func = func;
|
||||
f.module = module;
|
||||
|
||||
return add_psv_func(f);
|
||||
}
|
||||
// Do not call directly
|
||||
template<typename RT, typename... T> __forceinline void call_psv_func(ARMv7Context& context, RT(*func)(T...))
|
||||
{
|
||||
psv_func_detail::func_binder<RT, T...>::do_call(context, func);
|
||||
}
|
||||
|
||||
#define reg_psv_func(nid, module, name, func) add_psv_func(nid, module, name, [](ARMv7Context& context){ call_psv_func(context, func); })
|
||||
#define reg_psv_func(nid, module, name, func) add_psv_func(psv_func(nid, 0, module, name, [](ARMv7Context& context){ call_psv_func(context, func); }))
|
||||
|
||||
// Find registered HLE function by NID
|
||||
psv_func* get_psv_func_by_nid(u32 nid, u32* out_index = nullptr);
|
||||
|
|
|
@ -163,7 +163,6 @@ static const g_module_list[] =
|
|||
{ 0xf053, "cellAdecAt3multi", nullptr },
|
||||
{ 0xf054, "cellLibatrac3multi", nullptr },
|
||||
|
||||
{ -1, "cellSync", &cellSync },
|
||||
{ -1, "cellSysmodule", &cellSysmodule },
|
||||
{ -1, "libmixer", &libmixer },
|
||||
{ -1, "sysPrxForUser", &sysPrxForUser },
|
||||
|
|
|
@ -17,22 +17,7 @@ u32 add_ppu_func(ModuleFunc func)
|
|||
{
|
||||
for (auto& f : g_ppu_func_list)
|
||||
{
|
||||
if (f.id == func.id)
|
||||
{
|
||||
// partial update
|
||||
|
||||
if (func.func)
|
||||
{
|
||||
f.func = func.func;
|
||||
}
|
||||
|
||||
if (func.lle_func)
|
||||
{
|
||||
f.lle_func = func.lle_func;
|
||||
}
|
||||
|
||||
return (u32)(&f - g_ppu_func_list.data());
|
||||
}
|
||||
assert(f.id != func.id);
|
||||
}
|
||||
|
||||
g_ppu_func_list.push_back(func);
|
||||
|
@ -48,7 +33,7 @@ u32 add_ppu_func_sub(StaticFunc func)
|
|||
u32 add_ppu_func_sub(const char group[8], const u64 ops[], const char* name, Module* module, ppu_func_caller func)
|
||||
{
|
||||
StaticFunc sf;
|
||||
sf.index = add_ppu_func(ModuleFunc(get_function_id(name), module, func));
|
||||
sf.index = add_ppu_func(ModuleFunc(get_function_id(name), MFF_DONT_SAVE_RTOC, module, func));
|
||||
sf.name = name;
|
||||
sf.group = *(u64*)group;
|
||||
sf.found = 0;
|
||||
|
@ -98,14 +83,18 @@ void execute_ppu_func_by_index(PPUThread& CPU, u32 index)
|
|||
{
|
||||
if (auto func = get_ppu_func_by_index(index))
|
||||
{
|
||||
// save RTOC
|
||||
vm::write64(vm::cast(CPU.GPR[1] + 0x28), CPU.GPR[2]);
|
||||
if ((!func->lle_func || CPU.PC != vm::read32(func->lle_func.addr())) && !(func->flags & MFF_DONT_SAVE_RTOC))
|
||||
{
|
||||
// save RTOC if necessary
|
||||
vm::write64(vm::cast(CPU.GPR[1] + 0x28), CPU.GPR[2]);
|
||||
}
|
||||
|
||||
auto old_last_syscall = CPU.m_last_syscall;
|
||||
CPU.m_last_syscall = func->id;
|
||||
|
||||
if (func->lle_func)
|
||||
if (func->lle_func && !(func->flags & MFF_FORCED_HLE))
|
||||
{
|
||||
// call LLE function if possible
|
||||
func->lle_func(CPU);
|
||||
}
|
||||
else if (func->func)
|
||||
|
|
|
@ -6,15 +6,27 @@
|
|||
|
||||
class Module;
|
||||
|
||||
enum : u32
|
||||
{
|
||||
MFF_DONT_SAVE_RTOC = (1 << 0), // don't save RTOC before calling
|
||||
MFF_FORCED_HLE = (1 << 1), // always call HLE function
|
||||
};
|
||||
|
||||
struct ModuleFunc
|
||||
{
|
||||
u32 id;
|
||||
u32 flags;
|
||||
Module* module;
|
||||
ppu_func_caller func;
|
||||
vm::ptr<void()> lle_func;
|
||||
|
||||
ModuleFunc(u32 id, Module* module, ppu_func_caller func, vm::ptr<void()> lle_func = vm::ptr<void()>::make(0))
|
||||
ModuleFunc()
|
||||
{
|
||||
}
|
||||
|
||||
ModuleFunc(u32 id, u32 flags, Module* module, ppu_func_caller func, vm::ptr<void()> lle_func = vm::ptr<void()>::make(0))
|
||||
: id(id)
|
||||
, flags(flags)
|
||||
, module(module)
|
||||
, func(func)
|
||||
, lle_func(lle_func)
|
||||
|
@ -121,9 +133,10 @@ u32 add_ppu_func_sub(const char group[8], const u64 ops[], const char* name, Mod
|
|||
|
||||
void hook_ppu_funcs(u32* base, u32 size);
|
||||
|
||||
#define REG_FUNC(module, name) add_ppu_func(ModuleFunc(get_function_id(#name), &module, bind_func(name)))
|
||||
#define REG_FUNC(module, name) add_ppu_func(ModuleFunc(get_function_id(#name), 0, &module, bind_func(name)))
|
||||
#define REG_FUNC_FH(module, name) add_ppu_func(ModuleFunc(get_function_id(#name), MFF_FORCED_HLE, &module, bind_func(name)))
|
||||
|
||||
#define REG_UNNAMED(module, nid) add_ppu_func(ModuleFunc(0x##nid, &module, bind_func(_nid_##nid)))
|
||||
#define REG_UNNAMED(module, nid) add_ppu_func(ModuleFunc(0x##nid, 0, &module, bind_func(_nid_##nid)))
|
||||
|
||||
#define REG_SUB(module, group, name, ...) \
|
||||
static const u64 name ## _table[] = {__VA_ARGS__ , 0}; \
|
||||
|
|
|
@ -1081,7 +1081,7 @@ s32 syncLFQueueGetPushPointer(vm::ptr<CellSyncLFQueue> queue, s32& pointer, u32
|
|||
|
||||
s32 _cellSyncLFQueueGetPushPointer(vm::ptr<CellSyncLFQueue> queue, vm::ptr<u32> pointer, u32 isBlocking, u32 useEventQueue)
|
||||
{
|
||||
cellSync.Todo("_cellSyncLFQueueGetPushPointer(queue_addr=0x%x, pointer_addr=0x%x, isBlocking=%d, useEventQueue=%d)",
|
||||
cellSync.Warning("_cellSyncLFQueueGetPushPointer(queue_addr=0x%x, pointer_addr=0x%x, isBlocking=%d, useEventQueue=%d)",
|
||||
queue.addr(), pointer.addr(), isBlocking, useEventQueue);
|
||||
|
||||
s32 pointer_value;
|
||||
|
@ -1243,7 +1243,7 @@ s32 syncLFQueueCompletePushPointer(vm::ptr<CellSyncLFQueue> queue, s32 pointer,
|
|||
|
||||
s32 _cellSyncLFQueueCompletePushPointer(vm::ptr<CellSyncLFQueue> queue, s32 pointer, vm::ptr<s32(u32 addr, u32 arg)> fpSendSignal)
|
||||
{
|
||||
cellSync.Todo("_cellSyncLFQueueCompletePushPointer(queue_addr=0x%x, pointer=%d, fpSendSignal_addr=0x%x)",
|
||||
cellSync.Warning("_cellSyncLFQueueCompletePushPointer(queue_addr=0x%x, pointer=%d, fpSendSignal_addr=0x%x)",
|
||||
queue.addr(), pointer, fpSendSignal.addr());
|
||||
|
||||
return syncLFQueueCompletePushPointer(queue, pointer, fpSendSignal);
|
||||
|
@ -1432,7 +1432,7 @@ s32 syncLFQueueGetPopPointer(vm::ptr<CellSyncLFQueue> queue, s32& pointer, u32 i
|
|||
|
||||
s32 _cellSyncLFQueueGetPopPointer(vm::ptr<CellSyncLFQueue> queue, vm::ptr<u32> pointer, u32 isBlocking, u32 arg4, u32 useEventQueue)
|
||||
{
|
||||
cellSync.Todo("_cellSyncLFQueueGetPopPointer(queue_addr=0x%x, pointer_addr=0x%x, isBlocking=%d, arg4=%d, useEventQueue=%d)",
|
||||
cellSync.Warning("_cellSyncLFQueueGetPopPointer(queue_addr=0x%x, pointer_addr=0x%x, isBlocking=%d, arg4=%d, useEventQueue=%d)",
|
||||
queue.addr(), pointer.addr(), isBlocking, arg4, useEventQueue);
|
||||
|
||||
s32 pointer_value;
|
||||
|
@ -1594,7 +1594,7 @@ s32 syncLFQueueCompletePopPointer(vm::ptr<CellSyncLFQueue> queue, s32 pointer, c
|
|||
s32 _cellSyncLFQueueCompletePopPointer(vm::ptr<CellSyncLFQueue> queue, s32 pointer, vm::ptr<s32(u32 addr, u32 arg)> fpSendSignal, u32 noQueueFull)
|
||||
{
|
||||
// arguments copied from _cellSyncLFQueueCompletePushPointer + unknown argument (noQueueFull taken from LFQueue2CompletePopPointer)
|
||||
cellSync.Todo("_cellSyncLFQueueCompletePopPointer(queue_addr=0x%x, pointer=%d, fpSendSignal_addr=0x%x, noQueueFull=%d)",
|
||||
cellSync.Warning("_cellSyncLFQueueCompletePopPointer(queue_addr=0x%x, pointer=%d, fpSendSignal_addr=0x%x, noQueueFull=%d)",
|
||||
queue.addr(), pointer, fpSendSignal.addr(), noQueueFull);
|
||||
|
||||
return syncLFQueueCompletePopPointer(queue, pointer, fpSendSignal, noQueueFull);
|
||||
|
|
|
@ -504,7 +504,7 @@ s32 sys_net_free_thread_context()
|
|||
}
|
||||
|
||||
// define additional macro for specific namespace
|
||||
#define REG_FUNC_(name) add_ppu_func(ModuleFunc(get_function_id(#name), &sys_net, bind_func(sys_net_func::name)))
|
||||
#define REG_FUNC_(name) add_ppu_func(ModuleFunc(get_function_id(#name), 0, &sys_net, bind_func(sys_net_func::name)))
|
||||
|
||||
Module sys_net("sys_net", []()
|
||||
{
|
||||
|
|
|
@ -5,7 +5,7 @@ typedef void(*ppu_func_caller)(PPUThread&);
|
|||
|
||||
namespace ppu_func_detail
|
||||
{
|
||||
enum bind_arg_type
|
||||
enum arg_class : u8
|
||||
{
|
||||
ARG_GENERAL,
|
||||
ARG_FLOAT,
|
||||
|
@ -13,50 +13,50 @@ namespace ppu_func_detail
|
|||
ARG_STACK,
|
||||
};
|
||||
|
||||
template<typename T, bind_arg_type type, int g_count, int f_count, int v_count>
|
||||
template<typename T, arg_class type, u8 g_count, u8 f_count, u8 v_count>
|
||||
struct bind_arg;
|
||||
|
||||
template<typename T, int g_count, int f_count, int v_count>
|
||||
template<typename T, u8 g_count, u8 f_count, u8 v_count>
|
||||
struct bind_arg<T, ARG_GENERAL, g_count, f_count, v_count>
|
||||
{
|
||||
static_assert(sizeof(T) <= 8, "Invalid function argument type for ARG_GENERAL");
|
||||
|
||||
static __forceinline T func(PPUThread& CPU)
|
||||
static __forceinline T get_arg(PPUThread& CPU)
|
||||
{
|
||||
return cast_from_ppu_gpr<T>(CPU.GPR[g_count + 2]);
|
||||
}
|
||||
};
|
||||
|
||||
template<typename T, int g_count, int f_count, int v_count>
|
||||
template<typename T, u8 g_count, u8 f_count, u8 v_count>
|
||||
struct bind_arg<T, ARG_FLOAT, g_count, f_count, v_count>
|
||||
{
|
||||
static_assert(sizeof(T) <= 8, "Invalid function argument type for ARG_FLOAT");
|
||||
|
||||
static __forceinline T func(PPUThread& CPU)
|
||||
static __forceinline T get_arg(PPUThread& CPU)
|
||||
{
|
||||
return static_cast<T>(CPU.FPR[f_count]);
|
||||
}
|
||||
};
|
||||
|
||||
template<typename T, int g_count, int f_count, int v_count>
|
||||
template<typename T, u8 g_count, u8 f_count, u8 v_count>
|
||||
struct bind_arg<T, ARG_VECTOR, g_count, f_count, v_count>
|
||||
{
|
||||
static_assert(std::is_same<T, u128>::value, "Invalid function argument type for ARG_VECTOR");
|
||||
|
||||
static __forceinline T func(PPUThread& CPU)
|
||||
static __forceinline T get_arg(PPUThread& CPU)
|
||||
{
|
||||
return CPU.VPR[v_count + 1];
|
||||
}
|
||||
};
|
||||
|
||||
template<typename T, int g_count, int f_count, int v_count>
|
||||
template<typename T, u8 g_count, u8 f_count, u8 v_count>
|
||||
struct bind_arg<T, ARG_STACK, g_count, f_count, v_count>
|
||||
{
|
||||
static_assert(f_count <= 13, "TODO: Unsupported stack argument type (float)");
|
||||
static_assert(v_count <= 12, "TODO: Unsupported stack argument type (vector)");
|
||||
static_assert(sizeof(T) <= 8, "Invalid function argument type for ARG_STACK");
|
||||
|
||||
static __forceinline T func(PPUThread& CPU)
|
||||
static __forceinline T get_arg(PPUThread& CPU)
|
||||
{
|
||||
// TODO: check stack argument displacement
|
||||
const u64 res = CPU.GetStackArg(8 + std::max(g_count - 8, 0) + std::max(f_count - 13, 0) + std::max(v_count - 12, 0));
|
||||
|
@ -64,13 +64,13 @@ namespace ppu_func_detail
|
|||
}
|
||||
};
|
||||
|
||||
template<typename T, bind_arg_type type>
|
||||
template<typename T, arg_class type>
|
||||
struct bind_result
|
||||
{
|
||||
static_assert(type == ARG_GENERAL, "Wrong use of bind_result template");
|
||||
static_assert(sizeof(T) <= 8, "Invalid function result type for ARG_GENERAL");
|
||||
|
||||
static __forceinline void func(PPUThread& CPU, const T& result)
|
||||
static __forceinline void put_result(PPUThread& CPU, const T& result)
|
||||
{
|
||||
CPU.GPR[3] = cast_to_ppu_gpr<T>(result);
|
||||
}
|
||||
|
@ -81,7 +81,7 @@ namespace ppu_func_detail
|
|||
{
|
||||
static_assert(sizeof(T) <= 8, "Invalid function result type for ARG_FLOAT");
|
||||
|
||||
static __forceinline void func(PPUThread& CPU, const T& result)
|
||||
static __forceinline void put_result(PPUThread& CPU, const T& result)
|
||||
{
|
||||
CPU.FPR[1] = static_cast<T>(result);
|
||||
}
|
||||
|
@ -92,12 +92,29 @@ namespace ppu_func_detail
|
|||
{
|
||||
static_assert(std::is_same<T, u128>::value, "Invalid function result type for ARG_VECTOR");
|
||||
|
||||
static __forceinline void func(PPUThread& CPU, const T& result)
|
||||
static __forceinline void put_result(PPUThread& CPU, const T& result)
|
||||
{
|
||||
CPU.VPR[2] = result;
|
||||
}
|
||||
};
|
||||
|
||||
struct arg_type_pack
|
||||
{
|
||||
arg_class type;
|
||||
u8 g_count;
|
||||
u8 f_count;
|
||||
u8 v_count;
|
||||
};
|
||||
|
||||
template<typename T, u32 type_pack>
|
||||
struct bind_arg_packed
|
||||
{
|
||||
static __forceinline T get_arg(PPUThread& CPU)
|
||||
{
|
||||
return bind_arg<T, type_pack, type_pack >> 8, type_pack >> 16, type_pack >> 24>::get_arg(CPU);
|
||||
}
|
||||
};
|
||||
|
||||
template <typename RT, typename F, typename Tuple, bool Done, int Total, int... N>
|
||||
struct call_impl
|
||||
{
|
||||
|
@ -123,14 +140,14 @@ namespace ppu_func_detail
|
|||
return ppu_func_detail::call_impl<RT, F, Tuple, 0 == std::tuple_size<ttype>::value, std::tuple_size<ttype>::value>::call(f, std::forward<Tuple>(t));
|
||||
}
|
||||
|
||||
template<int g_count, int f_count, int v_count>
|
||||
template<u32 g_count, u32 f_count, u32 v_count>
|
||||
__forceinline std::tuple<> iterate(PPUThread& CPU)
|
||||
{
|
||||
// terminator
|
||||
return std::tuple<>();
|
||||
}
|
||||
|
||||
template<int g_count, int f_count, int v_count, typename T, typename... A>
|
||||
template<u32 g_count, u32 f_count, u32 v_count, typename T, typename... A>
|
||||
__forceinline std::tuple<T, A...> iterate(PPUThread& CPU)
|
||||
{
|
||||
static_assert(!std::is_pointer<T>::value, "Invalid function argument type (pointer)");
|
||||
|
@ -138,14 +155,14 @@ namespace ppu_func_detail
|
|||
// TODO: check calculations
|
||||
const bool is_float = std::is_floating_point<T>::value;
|
||||
const bool is_vector = std::is_same<T, u128>::value;
|
||||
const bind_arg_type t = is_float
|
||||
const arg_class t = is_float
|
||||
? ((f_count >= 13) ? ARG_STACK : ARG_FLOAT)
|
||||
: (is_vector ? ((v_count >= 12) ? ARG_STACK : ARG_VECTOR) : ((g_count >= 8) ? ARG_STACK : ARG_GENERAL));
|
||||
const int g = g_count + (is_float || is_vector ? 0 : 1);
|
||||
const int f = f_count + (is_float ? 1 : 0);
|
||||
const int v = v_count + (is_vector ? 1 : 0);
|
||||
const u32 g = g_count + (is_float || is_vector ? 0 : 1);
|
||||
const u32 f = f_count + (is_float ? 1 : 0);
|
||||
const u32 v = v_count + (is_vector ? 1 : 0);
|
||||
|
||||
return std::tuple_cat(std::tuple<T>(bind_arg<T, t, g, f, v>::func(CPU)), iterate<g, f, v, A...>(CPU));
|
||||
return std::tuple_cat(std::tuple<T>(bind_arg<T, t, g, f, v>::get_arg(CPU)), iterate<g, f, v, A...>(CPU));
|
||||
}
|
||||
|
||||
template<typename RT>
|
||||
|
@ -155,7 +172,7 @@ namespace ppu_func_detail
|
|||
static_assert(!std::is_reference<RT>::value, "Invalid function result type (reference)");
|
||||
static const bool is_float = std::is_floating_point<RT>::value;
|
||||
static const bool is_vector = std::is_same<RT, u128>::value;
|
||||
static const bind_arg_type value = is_float ? ARG_FLOAT : (is_vector ? ARG_VECTOR : ARG_GENERAL);
|
||||
static const arg_class value = is_float ? ARG_FLOAT : (is_vector ? ARG_VECTOR : ARG_GENERAL);
|
||||
};
|
||||
|
||||
template<typename RT, typename... T>
|
||||
|
@ -166,9 +183,9 @@ namespace ppu_func_detail
|
|||
{
|
||||
typedef void(*func_t)(PPUThread&, T...);
|
||||
|
||||
static void do_call(PPUThread& CPU, func_t _func)
|
||||
static void do_call(PPUThread& CPU, func_t func)
|
||||
{
|
||||
call<void>(_func, std::tuple_cat(std::tuple<PPUThread&>(CPU), iterate<0, 0, 0, T...>(CPU)));
|
||||
call<void>(func, std::tuple_cat(std::tuple<PPUThread&>(CPU), iterate<0, 0, 0, T...>(CPU)));
|
||||
}
|
||||
};
|
||||
|
||||
|
@ -177,9 +194,9 @@ namespace ppu_func_detail
|
|||
{
|
||||
typedef void(*func_t)(T...);
|
||||
|
||||
static void do_call(PPUThread& CPU, func_t _func)
|
||||
static void do_call(PPUThread& CPU, func_t func)
|
||||
{
|
||||
call<void>(_func, iterate<0, 0, 0, T...>(CPU));
|
||||
call<void>(func, iterate<0, 0, 0, T...>(CPU));
|
||||
}
|
||||
};
|
||||
|
||||
|
@ -188,9 +205,9 @@ namespace ppu_func_detail
|
|||
{
|
||||
typedef RT(*func_t)(PPUThread&, T...);
|
||||
|
||||
static void do_call(PPUThread& CPU, func_t _func)
|
||||
static void do_call(PPUThread& CPU, func_t func)
|
||||
{
|
||||
bind_result<RT, result_type<RT>::value>::func(CPU, call<RT>(_func, std::tuple_cat(std::tuple<PPUThread&>(CPU), iterate<0, 0, 0, T...>(CPU))));
|
||||
bind_result<RT, result_type<RT>::value>::put_result(CPU, call<RT>(func, std::tuple_cat(std::tuple<PPUThread&>(CPU), iterate<0, 0, 0, T...>(CPU))));
|
||||
}
|
||||
};
|
||||
|
||||
|
@ -199,9 +216,9 @@ namespace ppu_func_detail
|
|||
{
|
||||
typedef RT(*func_t)(T...);
|
||||
|
||||
static void do_call(PPUThread& CPU, func_t _func)
|
||||
static void do_call(PPUThread& CPU, func_t func)
|
||||
{
|
||||
bind_result<RT, result_type<RT>::value>::func(CPU, call<RT>(_func, iterate<0, 0, 0, T...>(CPU)));
|
||||
bind_result<RT, result_type<RT>::value>::put_result(CPU, call<RT>(func, iterate<0, 0, 0, T...>(CPU)));
|
||||
}
|
||||
};
|
||||
}
|
||||
|
|
|
@ -245,13 +245,8 @@ namespace loader
|
|||
{
|
||||
LOG_ERROR(LOADER, "Unknown function 0x%08x (addr=0x%x)", nid, addr);
|
||||
|
||||
psv_func unimplemented;
|
||||
unimplemented.nid = nid;
|
||||
unimplemented.module = nullptr;
|
||||
unimplemented.name = "UNKNOWN"; // TODO: set correct name if possible
|
||||
unimplemented.func = nullptr;
|
||||
|
||||
index = add_psv_func(unimplemented);
|
||||
// TODO: set correct name if possible
|
||||
index = add_psv_func(psv_func(nid, 0, nullptr, "UNKNOWN", nullptr));
|
||||
}
|
||||
|
||||
vm::psv::write32(addr + 0, 0xe0700090 | (index & 0xfff0) << 4 | (index & 0xf)); // HACK instruction (ARM)
|
||||
|
|
|
@ -398,7 +398,36 @@ namespace loader
|
|||
|
||||
for (auto& f : m.second.exports)
|
||||
{
|
||||
add_ppu_func(ModuleFunc(f.first, module, nullptr, vm::ptr<void()>::make(f.second)));
|
||||
const u32 nid = f.first;
|
||||
const u32 addr = f.second;
|
||||
|
||||
u32 index;
|
||||
|
||||
auto func = get_ppu_func_by_nid(nid, &index);
|
||||
|
||||
if (!func)
|
||||
{
|
||||
index = add_ppu_func(ModuleFunc(nid, 0, module, nullptr, vm::ptr<void()>::make(addr)));
|
||||
}
|
||||
else
|
||||
{
|
||||
func->lle_func.set(addr);
|
||||
|
||||
if (func->flags & MFF_FORCED_HLE)
|
||||
{
|
||||
u32 i_addr = 0;
|
||||
|
||||
if (!vm::check_addr(addr, 8) || !vm::check_addr(i_addr = vm::read32(addr), 8))
|
||||
{
|
||||
LOG_ERROR(LOADER, "Failed to inject code for function '%s' (opd=0x%x, 0x%x)", SysCalls::GetHLEFuncName(nid), addr, i_addr);
|
||||
}
|
||||
else
|
||||
{
|
||||
vm::write32(i_addr + 0, HACK(index));
|
||||
vm::write32(i_addr + 4, BLR());
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
for (auto& f : m.second.imports)
|
||||
|
@ -414,7 +443,7 @@ namespace loader
|
|||
{
|
||||
LOG_ERROR(LOADER, "Unimplemented function '%s' (0x%x)", SysCalls::GetHLEFuncName(nid), addr);
|
||||
|
||||
index = add_ppu_func(ModuleFunc(nid, module, nullptr));
|
||||
index = add_ppu_func(ModuleFunc(nid, 0, module, nullptr));
|
||||
}
|
||||
else
|
||||
{
|
||||
|
@ -635,7 +664,7 @@ namespace loader
|
|||
{
|
||||
LOG_ERROR(LOADER, "Unimplemented function '%s' in '%s' module (0x%x)", SysCalls::GetHLEFuncName(nid), module_name, addr);
|
||||
|
||||
index = add_ppu_func(ModuleFunc(nid, module, nullptr));
|
||||
index = add_ppu_func(ModuleFunc(nid, 0, module, nullptr));
|
||||
}
|
||||
else
|
||||
{
|
||||
|
|
Loading…
Add table
Reference in a new issue