38 lines
2.4 KiB
Text
38 lines
2.4 KiB
Text
//=============================================================================
|
|
// Indirect Call Dispatch
|
|
//
|
|
// REX_LOOKUP_FUNC indexes into the per-module dispatch table at
|
|
// IMAGE_BASE + IMAGE_SIZE. REX_CALL_INDIRECT_FUNC bounds-checks the target
|
|
// against the caller's [REX_CODE_BASE, REX_CODE_BASE + REX_CODE_SIZE +
|
|
// REX_THUNK_RESERVE_SIZE) range; out-of-bounds targets and in-bounds
|
|
// unregistered slots fall back to rex::runtime::ResolveIndirectFunction,
|
|
// which queries the global FunctionDispatcher across every loaded module.
|
|
//=============================================================================
|
|
|
|
#ifdef REXGLUE_ENABLE_PROFILING
|
|
#include <rex/perf/counter.h>
|
|
#define REX_PROFILE_INDIRECT_DISPATCH() PROFILE_FUNCTION_DISPATCHED()
|
|
#else
|
|
#define REX_PROFILE_INDIRECT_DISPATCH()
|
|
#endif
|
|
|
|
#define REX_LOOKUP_FUNC(x, y) \
|
|
(*(PPCFunc**)(x + REX_IMAGE_BASE + REX_IMAGE_SIZE + (u64(u32(y) - REX_CODE_BASE) * 2)))
|
|
|
|
#define REX_CALL_INDIRECT_FUNC(x) \
|
|
do { \
|
|
REX_PROFILE_INDIRECT_DISPATCH(); \
|
|
uint32_t rex_indirect_target_ = (uint32_t)(x); \
|
|
PPCFunc* rex_indirect_func_; \
|
|
if ((uint32_t)(rex_indirect_target_ - REX_CODE_BASE) < \
|
|
REX_CODE_SIZE + REX_THUNK_RESERVE_SIZE) [[likely]] { \
|
|
rex_indirect_func_ = REX_LOOKUP_FUNC(base, rex_indirect_target_); \
|
|
} else { \
|
|
rex_indirect_func_ = nullptr; \
|
|
} \
|
|
if (!rex_indirect_func_) [[unlikely]] { \
|
|
ctx.last_indirect_target = rex_indirect_target_; \
|
|
rex_indirect_func_ = rex::runtime::ResolveIndirectFunction(rex_indirect_target_); \
|
|
} \
|
|
rex_indirect_func_(ctx, base); \
|
|
} while (0)
|