vxKernel/include/vhex/defs/call.h

99 lines
2.6 KiB
C

#ifndef __VHEX_DEFS_CALL__
# define __VHEX_DEFS_CALL__
#include <vhex/defs/types.h>
/* vhex_call_arg_t: All types of arguments allowed in an indirect call
Because a function call cannot be easily pieced together, there are
restrictions on what arguments can be passed. The following union lists all
of the available types. Other types can be used if casted, mainly pointers;
see the description of VHEX_CALL() for details. */
typedef union {
/* 32-bit integers */
int i;
unsigned int u;
int32_t i32;
uint32_t u32;
uintptr_t up32;
intptr_t ip32;
/* 32-bit floating-point */
float f;
/* Pointers to most common types, in all possible const/volatile
qualifications */
#define POINTER(type, name) \
type *name; \
type const *name ## _c; \
type volatile *name ## _v; \
type volatile const *name ## _cv;
POINTER(void, pv)
POINTER(char, pc)
POINTER(unsigned char, puc)
POINTER(short, ps)
POINTER(unsigned short, pus)
POINTER(int, pi)
POINTER(unsigned int, pui)
POINTER(int8_t, pi8)
POINTER(uint8_t, pu8)
POINTER(int16_t, pi16)
POINTER(uint16_t, pu16)
POINTER(int32_t, pi32)
POINTER(uint32_t, pu32)
POINTER(int64_t, pi64)
POINTER(uint64_t, pu64)
POINTER(long long int, pll)
POINTER(unsigned long long int, pull)
POINTER(float, pf)
POINTER(double, pd)
#undef POINTER
} vhex_call_arg_t;
/* vhex_call_t: Indirect call with up to 4 register arguments */
struct vhex_call {
void *function;
vhex_call_arg_t args[4];
};
typedef struct vhex_call vhex_call_t;
/* VHEX_CALL(): Build an callback from function and arguments */
#define VHEX_CALL(fct, ...) \
(vhex_call_t){ \
.function = (void*)fct, \
.args = { __VA_OPT__(VHEX_CALL_ARGS1(__VA_ARGS__)) } \
}
#define VHEX_CALL_ARGS1(a1, ...) \
(vhex_call_arg_t)(a1), __VA_OPT__(VHEX_CALL_ARGS2(__VA_ARGS__))
#define VHEX_CALL_ARGS2(a2, ...) \
(vhex_call_arg_t)(a2), __VA_OPT__(VHEX_CALL_ARGS3(__VA_ARGS__))
#define VHEX_CALL_ARGS3(a3, ...) \
(vhex_call_arg_t)(a3), __VA_OPT__(VHEX_CALL_ARGS4(__VA_ARGS__))
#define VHEX_CALL_ARGS4(a4, ...) \
({ \
__VA_OPT__( \
_Static_assert( \
0, \ \
"VHEX_CALL: too many arguments (maximum 4)" \
); \
) \
(vhex_call_arg_t)(a4); \
})
/* VHEX_CALL_NULL: Empty function call */
#define VHEX_CALL_NULL ((vhex_call_t){ .function = NULL, .args = {} })
/* vhex_call(): Perform an indirect call */
static VINLINE int vhex_call(vhex_call_t callback)
{
return ((int(*)(uintptr_t, uintptr_t, uintptr_t, uintptr_t))callback.function)(
callback.args[0].up32,
callback.args[1].up32,
callback.args[2].up32,
callback.args[3].up32
);
}
#endif /* __VHEX_DEFS_CALL__ */