CALL_FUNC macro fixed

Now it can call any HLE function, possibly using LLE if available.
This commit is contained in:
Nekotekina 2015-09-08 14:29:27 +03:00
parent da4bf43fb2
commit 093ecc0a02
7 changed files with 787 additions and 788 deletions

View File

@ -125,33 +125,36 @@ void hook_ppu_funcs(vm::ptr<u32> base, u32 size);
bool patch_ppu_import(u32 addr, u32 index); bool patch_ppu_import(u32 addr, u32 index);
// call specified function directly if LLE is not available, call LLE equivalent in callback style otherwise // Variable associated with registered HLE function
template<typename T, typename... Args> inline auto hle_call_func(PPUThread& CPU, T func, u32 index, Args&&... args) -> decltype(func(std::forward<Args>(args)...)) template<typename T, T Func> struct ppu_func_by_func { static u32 index; };
template<typename T, T Func> u32 ppu_func_by_func<T, Func>::index = 0xffffffffu;
template<typename T, T Func, typename... Args, typename RT = std::result_of_t<T(Args...)>> inline RT call_ppu_func(PPUThread& ppu, Args&&... args)
{ {
const auto mfunc = get_ppu_func_by_index(index); const auto mfunc = get_ppu_func_by_index(ppu_func_by_func<T, Func>::index);
if (mfunc && mfunc->lle_func && (mfunc->flags & MFF_FORCED_HLE) == 0 && (mfunc->flags & MFF_NO_RETURN) == 0) if (mfunc && mfunc->lle_func && (mfunc->flags & MFF_FORCED_HLE) == 0 && (mfunc->flags & MFF_NO_RETURN) == 0)
{ {
const u32 pc = vm::read32(mfunc->lle_func.addr()); const u32 pc = vm::read32(mfunc->lle_func.addr());
const u32 rtoc = vm::read32(mfunc->lle_func.addr() + 4); const u32 rtoc = vm::read32(mfunc->lle_func.addr() + 4);
return cb_call<decltype(func(std::forward<Args>(args)...)), Args...>(CPU, pc, rtoc, std::forward<Args>(args)...); return cb_call<RT, Args...>(ppu, pc, rtoc, std::forward<Args>(args)...);
} }
else else
{ {
return func(std::forward<Args>(args)...); return Func(std::forward<Args>(args)...);
} }
} }
#define CALL_FUNC(cpu, func, ...) hle_call_func(cpu, func, g_ppu_func_index__##func, __VA_ARGS__) // call specified function directly if LLE is not available, call LLE equivalent in callback style otherwise
#define CALL_FUNC(ppu, func, ...) call_ppu_func<decltype(&func), &func>(ppu, __VA_ARGS__)
#define REG_FUNC(module, name) add_ppu_func(ModuleFunc(get_function_id(#name), 0, &module, #name, bind_func(name))) #define REG_FNID(module, nid, func, ...) (ppu_func_by_func<decltype(&func), &func>::index = add_ppu_func(ModuleFunc(nid, { __VA_ARGS__ }, &module, #func, BIND_FUNC(func))))
#define REG_FUNC_FH(module, name) add_ppu_func(ModuleFunc(get_function_id(#name), MFF_FORCED_HLE, &module, #name, bind_func(name)))
#define REG_FUNC_NR(module, name) add_ppu_func(ModuleFunc(get_function_id(#name), MFF_NO_RETURN, &module, #name, bind_func(name)))
#define REG_UNNAMED(module, nid) add_ppu_func(ModuleFunc(0x##nid, 0, &module, "_nid_"#nid, bind_func(_nid_##nid))) #define REG_FUNC(module, func, ...) REG_FNID(module, get_function_id(#func), func, __VA_ARGS__)
#define REG_SUB(module, ns, name, ...) add_ppu_func_sub({ __VA_ARGS__ }, #name, &module, bind_func(ns::name)) #define REG_SUB(module, ns, name, ...) add_ppu_func_sub({ __VA_ARGS__ }, #name, &module, BIND_FUNC(ns::name))
#define SP_OP(type, op, sup) []() { s32 XXX = 0; SearchPatternEntry res = { (type), (op), 0, (sup) }; XXX = -1; res.mask = (op) ^ ~res.data; return res; }() #define SP_OP(type, op, sup) []() { s32 XXX = 0; SearchPatternEntry res = { (type), (op), 0, (sup) }; XXX = -1; res.mask = (op) ^ ~res.data; return res; }()
#define SP_I(op) SP_OP(SPET_MASKED_OPCODE, op, 0) #define SP_I(op) SP_OP(SPET_MASKED_OPCODE, op, 0)

View File

@ -293,57 +293,57 @@ s32 cellFiberPpuUtilWorkerControlInitializeWithAttribute()
Module cellFiber("cellFiber", []() Module cellFiber("cellFiber", []()
{ {
REG_FUNC_NR(cellFiber, _cellFiberPpuInitialize); REG_FUNC(cellFiber, _cellFiberPpuInitialize, MFF_NO_RETURN);
REG_FUNC_NR(cellFiber, _cellFiberPpuSchedulerAttributeInitialize); REG_FUNC(cellFiber, _cellFiberPpuSchedulerAttributeInitialize, MFF_NO_RETURN);
REG_FUNC_NR(cellFiber, cellFiberPpuInitializeScheduler); REG_FUNC(cellFiber, cellFiberPpuInitializeScheduler, MFF_NO_RETURN);
REG_FUNC_NR(cellFiber, cellFiberPpuFinalizeScheduler); REG_FUNC(cellFiber, cellFiberPpuFinalizeScheduler, MFF_NO_RETURN);
REG_FUNC_NR(cellFiber, cellFiberPpuRunFibers); REG_FUNC(cellFiber, cellFiberPpuRunFibers, MFF_NO_RETURN);
REG_FUNC_NR(cellFiber, cellFiberPpuCheckFlags); REG_FUNC(cellFiber, cellFiberPpuCheckFlags, MFF_NO_RETURN);
REG_FUNC_NR(cellFiber, cellFiberPpuHasRunnableFiber); REG_FUNC(cellFiber, cellFiberPpuHasRunnableFiber, MFF_NO_RETURN);
REG_FUNC_NR(cellFiber, _cellFiberPpuAttributeInitialize); REG_FUNC(cellFiber, _cellFiberPpuAttributeInitialize, MFF_NO_RETURN);
REG_FUNC_NR(cellFiber, cellFiberPpuCreateFiber); REG_FUNC(cellFiber, cellFiberPpuCreateFiber, MFF_NO_RETURN);
REG_FUNC_NR(cellFiber, cellFiberPpuExit); REG_FUNC(cellFiber, cellFiberPpuExit, MFF_NO_RETURN);
REG_FUNC_NR(cellFiber, cellFiberPpuYield); REG_FUNC(cellFiber, cellFiberPpuYield, MFF_NO_RETURN);
REG_FUNC_NR(cellFiber, cellFiberPpuJoinFiber); REG_FUNC(cellFiber, cellFiberPpuJoinFiber, MFF_NO_RETURN);
REG_FUNC(cellFiber, cellFiberPpuSelf); REG_FUNC(cellFiber, cellFiberPpuSelf);
REG_FUNC_NR(cellFiber, cellFiberPpuSendSignal); REG_FUNC(cellFiber, cellFiberPpuSendSignal, MFF_NO_RETURN);
REG_FUNC_NR(cellFiber, cellFiberPpuWaitSignal); REG_FUNC(cellFiber, cellFiberPpuWaitSignal, MFF_NO_RETURN);
REG_FUNC_NR(cellFiber, cellFiberPpuWaitFlag); REG_FUNC(cellFiber, cellFiberPpuWaitFlag, MFF_NO_RETURN);
REG_FUNC_NR(cellFiber, cellFiberPpuGetScheduler); REG_FUNC(cellFiber, cellFiberPpuGetScheduler, MFF_NO_RETURN);
REG_FUNC_NR(cellFiber, cellFiberPpuSetPriority); REG_FUNC(cellFiber, cellFiberPpuSetPriority, MFF_NO_RETURN);
REG_FUNC_NR(cellFiber, cellFiberPpuCheckStackLimit); REG_FUNC(cellFiber, cellFiberPpuCheckStackLimit, MFF_NO_RETURN);
REG_FUNC_NR(cellFiber, _cellFiberPpuContextAttributeInitialize); REG_FUNC(cellFiber, _cellFiberPpuContextAttributeInitialize, MFF_NO_RETURN);
REG_FUNC_NR(cellFiber, cellFiberPpuContextInitialize); REG_FUNC(cellFiber, cellFiberPpuContextInitialize, MFF_NO_RETURN);
REG_FUNC_NR(cellFiber, cellFiberPpuContextFinalize); REG_FUNC(cellFiber, cellFiberPpuContextFinalize, MFF_NO_RETURN);
REG_FUNC_NR(cellFiber, cellFiberPpuContextRun); REG_FUNC(cellFiber, cellFiberPpuContextRun, MFF_NO_RETURN);
REG_FUNC_NR(cellFiber, cellFiberPpuContextSwitch); REG_FUNC(cellFiber, cellFiberPpuContextSwitch, MFF_NO_RETURN);
REG_FUNC_NR(cellFiber, cellFiberPpuContextSelf); REG_FUNC(cellFiber, cellFiberPpuContextSelf, MFF_NO_RETURN);
REG_FUNC_NR(cellFiber, cellFiberPpuContextReturnToThread); REG_FUNC(cellFiber, cellFiberPpuContextReturnToThread, MFF_NO_RETURN);
REG_FUNC_NR(cellFiber, cellFiberPpuContextCheckStackLimit); REG_FUNC(cellFiber, cellFiberPpuContextCheckStackLimit, MFF_NO_RETURN);
REG_FUNC_NR(cellFiber, cellFiberPpuContextRunScheduler); REG_FUNC(cellFiber, cellFiberPpuContextRunScheduler, MFF_NO_RETURN);
REG_FUNC_NR(cellFiber, cellFiberPpuContextEnterScheduler); REG_FUNC(cellFiber, cellFiberPpuContextEnterScheduler, MFF_NO_RETURN);
REG_FUNC_NR(cellFiber, cellFiberPpuSchedulerTraceInitialize); REG_FUNC(cellFiber, cellFiberPpuSchedulerTraceInitialize, MFF_NO_RETURN);
REG_FUNC_NR(cellFiber, cellFiberPpuSchedulerTraceFinalize); REG_FUNC(cellFiber, cellFiberPpuSchedulerTraceFinalize, MFF_NO_RETURN);
REG_FUNC_NR(cellFiber, cellFiberPpuSchedulerTraceStart); REG_FUNC(cellFiber, cellFiberPpuSchedulerTraceStart, MFF_NO_RETURN);
REG_FUNC_NR(cellFiber, cellFiberPpuSchedulerTraceStop); REG_FUNC(cellFiber, cellFiberPpuSchedulerTraceStop, MFF_NO_RETURN);
REG_FUNC_NR(cellFiber, _cellFiberPpuUtilWorkerControlAttributeInitialize); REG_FUNC(cellFiber, _cellFiberPpuUtilWorkerControlAttributeInitialize, MFF_NO_RETURN);
REG_FUNC_NR(cellFiber, cellFiberPpuUtilWorkerControlRunFibers); REG_FUNC(cellFiber, cellFiberPpuUtilWorkerControlRunFibers, MFF_NO_RETURN);
REG_FUNC_NR(cellFiber, cellFiberPpuUtilWorkerControlInitialize); REG_FUNC(cellFiber, cellFiberPpuUtilWorkerControlInitialize, MFF_NO_RETURN);
REG_FUNC_NR(cellFiber, cellFiberPpuUtilWorkerControlSetPollingMode); REG_FUNC(cellFiber, cellFiberPpuUtilWorkerControlSetPollingMode, MFF_NO_RETURN);
REG_FUNC_NR(cellFiber, cellFiberPpuUtilWorkerControlJoinFiber); REG_FUNC(cellFiber, cellFiberPpuUtilWorkerControlJoinFiber, MFF_NO_RETURN);
REG_FUNC_NR(cellFiber, cellFiberPpuUtilWorkerControlDisconnectEventQueue); REG_FUNC(cellFiber, cellFiberPpuUtilWorkerControlDisconnectEventQueue, MFF_NO_RETURN);
REG_FUNC_NR(cellFiber, cellFiberPpuUtilWorkerControlSendSignal); REG_FUNC(cellFiber, cellFiberPpuUtilWorkerControlSendSignal, MFF_NO_RETURN);
REG_FUNC_NR(cellFiber, cellFiberPpuUtilWorkerControlConnectEventQueueToSpurs); REG_FUNC(cellFiber, cellFiberPpuUtilWorkerControlConnectEventQueueToSpurs, MFF_NO_RETURN);
REG_FUNC_NR(cellFiber, cellFiberPpuUtilWorkerControlFinalize); REG_FUNC(cellFiber, cellFiberPpuUtilWorkerControlFinalize, MFF_NO_RETURN);
REG_FUNC_NR(cellFiber, cellFiberPpuUtilWorkerControlWakeup); REG_FUNC(cellFiber, cellFiberPpuUtilWorkerControlWakeup, MFF_NO_RETURN);
REG_FUNC_NR(cellFiber, cellFiberPpuUtilWorkerControlCreateFiber); REG_FUNC(cellFiber, cellFiberPpuUtilWorkerControlCreateFiber, MFF_NO_RETURN);
REG_FUNC_NR(cellFiber, cellFiberPpuUtilWorkerControlShutdown); REG_FUNC(cellFiber, cellFiberPpuUtilWorkerControlShutdown, MFF_NO_RETURN);
REG_FUNC_NR(cellFiber, cellFiberPpuUtilWorkerControlCheckFlags); REG_FUNC(cellFiber, cellFiberPpuUtilWorkerControlCheckFlags, MFF_NO_RETURN);
REG_FUNC_NR(cellFiber, cellFiberPpuUtilWorkerControlInitializeWithAttribute); REG_FUNC(cellFiber, cellFiberPpuUtilWorkerControlInitializeWithAttribute, MFF_NO_RETURN);
}); });

View File

@ -422,8 +422,6 @@ void spursHandlerWaitReady(PPUThread& ppu, vm::ptr<CellSpurs> spurs)
if (spurs->handlerExiting.load()) if (spurs->handlerExiting.load())
{ {
extern u32 g_ppu_func_index__sys_lwmutex_unlock; // test
if (s32 rc = CALL_FUNC(ppu, sys_lwmutex_unlock, ppu, spurs.ptr(&CellSpurs::mutex))) if (s32 rc = CALL_FUNC(ppu, sys_lwmutex_unlock, ppu, spurs.ptr(&CellSpurs::mutex)))
{ {
throw EXCEPTION("sys_lwmutex_unlock() failed (0x%x)", rc); throw EXCEPTION("sys_lwmutex_unlock() failed (0x%x)", rc);

View File

@ -276,13 +276,11 @@ s32 sys_lwmutex_unlock(PPUThread& ppu, vm::ptr<sys_lwmutex_t> lwmutex)
return CELL_OK; return CELL_OK;
} }
u32 g_ppu_func_index__sys_lwmutex_unlock; // test
void sysPrxForUser_sys_lwmutex_init() void sysPrxForUser_sys_lwmutex_init()
{ {
REG_FUNC(sysPrxForUser, sys_lwmutex_create); REG_FUNC(sysPrxForUser, sys_lwmutex_create);
REG_FUNC(sysPrxForUser, sys_lwmutex_destroy); REG_FUNC(sysPrxForUser, sys_lwmutex_destroy);
REG_FUNC(sysPrxForUser, sys_lwmutex_lock); REG_FUNC(sysPrxForUser, sys_lwmutex_lock);
REG_FUNC(sysPrxForUser, sys_lwmutex_trylock); REG_FUNC(sysPrxForUser, sys_lwmutex_trylock);
g_ppu_func_index__sys_lwmutex_unlock = REG_FUNC(sysPrxForUser, sys_lwmutex_unlock); // test REG_FUNC(sysPrxForUser, sys_lwmutex_unlock);
} }

View File

@ -614,7 +614,7 @@ namespace sys_net
} }
// define additional macro for specific namespace // define additional macro for specific namespace
#define REG_FUNC_(name) add_ppu_func(ModuleFunc(get_function_id(#name), 0, &libnet, #name, bind_func(sys_net::name))) #define REG_FUNC_(name) add_ppu_func(ModuleFunc(get_function_id(#name), 0, &libnet, #name, BIND_FUNC(sys_net::name)))
Module libnet("sys_net", []() Module libnet("sys_net", []()
{ {

View File

@ -228,11 +228,11 @@ namespace ppu_func_detail
bind_result<RT, result_type<RT>::value>::put_result(ppu, call<T...>(ppu, func, arg_info_pack_t<>{})); bind_result<RT, result_type<RT>::value>::put_result(ppu, call<T...>(ppu, func, arg_info_pack_t<>{}));
} }
}; };
template<typename RT, typename... T> force_inline void do_call(PPUThread& ppu, RT(*func)(T...))
{
func_binder<RT, T...>::do_call(ppu, func);
}
} }
template<typename RT, typename... T> force_inline void call_ppu_func(PPUThread& ppu, RT(*func)(T...)) #define BIND_FUNC(func) [](PPUThread& ppu){ ppu_func_detail::do_call(ppu, func); }
{
ppu_func_detail::func_binder<RT, T...>::do_call(ppu, func);
}
#define bind_func(func) [](PPUThread& ppu){ call_ppu_func(ppu, func); }

File diff suppressed because it is too large Load Diff