aboutsummaryrefslogtreecommitdiff
path: root/include/ejit/ejit.h
diff options
context:
space:
mode:
Diffstat (limited to 'include/ejit/ejit.h')
-rw-r--r--include/ejit/ejit.h196
1 files changed, 132 insertions, 64 deletions
diff --git a/include/ejit/ejit.h b/include/ejit/ejit.h
index 4ab2bbc..ab06d8f 100644
--- a/include/ejit/ejit.h
+++ b/include/ejit/ejit.h
@@ -72,29 +72,20 @@ static inline enum ejit_type ejit_signed_type(size_t w)
struct ejit_arg {
union {
- int8_t i8;
- uint8_t u8;
+ int8_t i8;
int16_t i16;
- uint16_t u16;
int32_t i32;
- uint32_t u32;
int64_t i64;
- uint64_t u64;
- signed char c;
- unsigned char uc;
- signed short s;
- unsigned short us;
- signed int i;
- unsigned int ui;
- signed long l;
- unsigned long ul;
- signed long long ll;
- unsigned long long ull;
+ uint8_t u8;
+ uint16_t u16;
+ uint32_t u32;
+ uint64_t u64;
float f;
double d;
void *p;
+ long l;
};
enum ejit_type type;
};
@@ -113,6 +104,7 @@ static inline bool ejit_int_type(enum ejit_type t)
case EJIT_POINTER:
return true;
default:
+ break;
}
return false;
@@ -125,6 +117,7 @@ static inline bool ejit_float_type(enum ejit_type t)
case EJIT_DOUBLE:
return true;
default:
+ break;
}
return false;
@@ -136,15 +129,15 @@ static inline struct ejit_arg ejit_build_arg(enum ejit_type type, uint64_t x)
a.type = type;
switch (type) {
- case EJIT_INT8: a.u64 = (int8_t)x; break;
- case EJIT_INT16: a.u64 = (int16_t)x; break;
- case EJIT_INT32: a.u64 = (int32_t)x; break;
- case EJIT_INT64: a.u64 = (int64_t)x; break;
- case EJIT_UINT8: a.u64 = (uint8_t)x; break;
- case EJIT_UINT16: a.u64 = (uint16_t)x; break;
- case EJIT_UINT32: a.u64 = (uint32_t)x; break;
- case EJIT_UINT64: a.u64 = (uint64_t)x; break;
- case EJIT_POINTER: a.p = (void *)(uintptr_t)x; break;
+ case EJIT_INT8: a.i8 = (int8_t)x; break;
+ case EJIT_INT16: a.i16 = (int16_t)x; break;
+ case EJIT_INT32: a.i32 = (int32_t)x; break;
+ case EJIT_INT64: a.i64 = (int64_t)x; break;
+ case EJIT_UINT8: a.u8 = (uint8_t)x; break;
+ case EJIT_UINT16: a.u16 = (uint16_t)x; break;
+ case EJIT_UINT32: a.u32 = (uint32_t)x; break;
+ case EJIT_UINT64: a.u64 = (uint64_t)x; break;
+ case EJIT_POINTER: a.p = (void *)(uintptr_t)x; break;
default: abort();
}
@@ -157,7 +150,7 @@ static inline struct ejit_arg ejit_build_arg_f(enum ejit_type type, double x)
a.type = type;
switch (type) {
- case EJIT_FLOAT: a.f = x; break;
+ case EJIT_FLOAT: a.f = (float)x; break;
case EJIT_DOUBLE: a.d = x; break;
default: abort();
}
@@ -223,21 +216,6 @@ double ejit_run_func_d(struct ejit_func *f, size_t argc,
struct ejit_arg ejit_run_func(struct ejit_func *f, size_t argc, struct ejit_arg args[argc]);
-
-/* currently unused, the idea is that an escape could get the interpreter state
- * and pass it on to speed up entering/exiting the VM, could be useful for more
- * dynamic languages */
-struct interp_state;
-
-long ejit_run_func_ctx_i(struct ejit_func *f, size_t argc, struct ejit_arg args[argc], struct interp_state *ctx);
-
-int64_t ejit_run_func_ctx_l(struct ejit_func *f, size_t argc, struct ejit_arg args[argc], struct interp_state *ctx);
-
-float ejit_run_func_ctx_f(struct ejit_func *f, size_t argc, struct ejit_arg args[argc], struct interp_state *ctx);
-
-double ejit_run_func_ctx_d(struct ejit_func *f, size_t argc, struct ejit_arg args[argc], struct interp_state *ctx);
-
-
void ejit_destroy_func(struct ejit_func *s);
#define EJIT_GPR(x) ((struct ejit_gpr){.r = (x)})
@@ -260,23 +238,23 @@ void ejit_destroy_func(struct ejit_func *s);
.type = (t)})
#define EJIT_OPERAND_FLT(x, t) \
((struct ejit_operand){ .kind = EJIT_OPERAND_FLT, \
- .r = (double)(x), \
+ .d = (double)(x), \
.type = (t)})
/* maybe slight hack, but increase width to interpeter register width */
static inline struct ejit_arg ejit_i8(int8_t a)
{
- return (struct ejit_arg){.i64 = a, .type = EJIT_INT8};
+ return (struct ejit_arg){.i8 = a, .type = EJIT_INT8};
}
static inline struct ejit_arg ejit_i16(int16_t a)
{
- return (struct ejit_arg){.i64 = a, .type = EJIT_INT16};
+ return (struct ejit_arg){.i16 = a, .type = EJIT_INT16};
}
static inline struct ejit_arg ejit_i32(int32_t a)
{
- return (struct ejit_arg){.i64 = a, .type = EJIT_INT32};
+ return (struct ejit_arg){.i32 = a, .type = EJIT_INT32};
}
static inline struct ejit_arg ejit_i64(int64_t a)
@@ -286,22 +264,22 @@ static inline struct ejit_arg ejit_i64(int64_t a)
static inline struct ejit_arg ejit_u8(uint8_t a)
{
- return (struct ejit_arg){.i64 = a, .type = EJIT_UINT8};
+ return (struct ejit_arg){.u8 = a, .type = EJIT_UINT8};
}
static inline struct ejit_arg ejit_u16(uint16_t a)
{
- return (struct ejit_arg){.i64 = a, .type = EJIT_UINT16};
+ return (struct ejit_arg){.u16 = a, .type = EJIT_UINT16};
}
static inline struct ejit_arg ejit_u32(uint32_t a)
{
- return (struct ejit_arg){.i64 = a, .type = EJIT_UINT32};
+ return (struct ejit_arg){.u32 = a, .type = EJIT_UINT32};
}
static inline struct ejit_arg ejit_u64(uint64_t a)
{
- return (struct ejit_arg){.i64 = a, .type = EJIT_UINT64};
+ return (struct ejit_arg){.u64 = a, .type = EJIT_UINT64};
}
static inline struct ejit_arg ejit_pointer(void *p)
@@ -387,6 +365,77 @@ static inline struct ejit_arg ejit_pointer_arg(void *p, size_t w)
#define EJIT_AUTO(x) \
EJIT_ARG(x, typeof(x))
+static inline int64_t ejit_signed_param(size_t argc, const struct ejit_arg args[argc],
+ size_t idx, enum ejit_type type)
+{
+ assert(idx < argc);
+ assert(args[idx].type == type);
+ switch (type) {
+ case EJIT_INT64: return args[idx].i64;
+ case EJIT_INT32: return args[idx].i32;
+ case EJIT_INT16: return args[idx].i16;
+ case EJIT_INT8: return args[idx].i8;
+ default: abort();
+ }
+
+ return 0;
+}
+
+static inline uint64_t ejit_unsigned_param(size_t argc, const struct ejit_arg args[argc],
+ size_t idx, enum ejit_type type)
+{
+ assert(idx < argc);
+ assert(args[idx].type == type);
+ switch (type) {
+ case EJIT_UINT64: return args[idx].u64;
+ case EJIT_UINT32: return args[idx].u32;
+ case EJIT_UINT16: return args[idx].u16;
+ case EJIT_UINT8: return args[idx].u8;
+ default: abort();
+ }
+}
+
+static inline float ejit_float_param(size_t argc, const struct ejit_arg args[argc],
+ size_t idx, enum ejit_type type)
+{
+ assert(idx < argc);
+ assert(args[idx].type == type && type == EJIT_FLOAT);
+ return args[idx].f;
+}
+
+static inline double ejit_double_param(size_t argc, const struct ejit_arg args[argc],
+ size_t idx, enum ejit_type type)
+{
+ assert(idx < argc);
+ assert(args[idx].type == type && type == EJIT_DOUBLE);
+ return args[idx].d;
+}
+
+static inline void *ejit_pointer_param(size_t argc, const struct ejit_arg args[argc],
+ size_t idx, enum ejit_type type)
+{
+ assert(idx < argc);
+ assert(args[idx].type == type && type == EJIT_POINTER);
+ return args[idx].p;
+}
+
+#define EJIT_PARAM(argc, args, idx, t) \
+ _Generic((t)(0), \
+ signed char : ejit_signed_param, \
+ signed short : ejit_signed_param, \
+ signed int : ejit_signed_param, \
+ signed long : ejit_signed_param, \
+ signed long long : ejit_signed_param, \
+ unsigned char : ejit_unsigned_param, \
+ unsigned short : ejit_unsigned_param, \
+ unsigned int : ejit_unsigned_param, \
+ unsigned long : ejit_unsigned_param, \
+ unsigned long long: ejit_unsigned_param, \
+ float : ejit_float_param, \
+ double : ejit_double_param, \
+ default : ejit_pointer_param \
+ )(argc, args, idx, EJIT_TYPE(t))
+
static inline bool ejit_use64(struct ejit_arg a)
{
if (a.type == EJIT_INT64 || a.type == EJIT_UINT64)
@@ -405,29 +454,39 @@ typedef double (*ejit_escape_d_t)(size_t argc, const struct ejit_arg args[argc])
struct ejit_label ejit_label(struct ejit_func *s);
-void ejit_calli_i(struct ejit_func *s, struct ejit_func *f, size_t argc,
- const struct ejit_operand args[argc]);
+void ejit_tailr(struct ejit_func *s, struct ejit_gpr target,
+ size_t argc, const struct ejit_operand args[argc]);
+
+void ejit_taili(struct ejit_func *s, struct ejit_func *f,
+ size_t argc, const struct ejit_operand args[argc]);
-void ejit_calli_l(struct ejit_func *s, struct ejit_func *f, size_t argc,
- const struct ejit_operand args[argc]);
+/* return type can be deduced */
+void ejit_calli(struct ejit_func *s, struct ejit_func *f,
+ size_t argc, const struct ejit_operand args[argc]);
-void ejit_calli_f(struct ejit_func *s, struct ejit_func *f, size_t argc,
- const struct ejit_operand args[argc]);
+void ejit_callr_i(struct ejit_func *s, struct ejit_gpr target,
+ size_t argc, const struct ejit_operand args[argc]);
-void ejit_calli_d(struct ejit_func *s, struct ejit_func *f, size_t argc,
- const struct ejit_operand args[argc]);
+void ejit_callr_l(struct ejit_func *s, struct ejit_gpr target,
+ size_t argc, const struct ejit_operand args[argc]);
-void ejit_escapei_i(struct ejit_func *s, ejit_escape_i_t f, size_t argc,
- const struct ejit_operand args[argc]);
+void ejit_callr_f(struct ejit_func *s, struct ejit_gpr target,
+ size_t argc, const struct ejit_operand args[argc]);
-void ejit_escapei_l(struct ejit_func *s, ejit_escape_l_t f, size_t argc,
- const struct ejit_operand args[argc]);
+void ejit_callr_d(struct ejit_func *s, struct ejit_gpr target,
+ size_t argc, const struct ejit_operand args[argc]);
-void ejit_escapei_f(struct ejit_func *s, ejit_escape_f_t f, size_t argc,
- const struct ejit_operand args[argc]);
+void ejit_escapei_i(struct ejit_func *s, ejit_escape_i_t f,
+ size_t argc, const struct ejit_operand args[argc]);
-void ejit_escapei_d(struct ejit_func *s, ejit_escape_d_t f, size_t argc,
- const struct ejit_operand args[argc]);
+void ejit_escapei_l(struct ejit_func *s, ejit_escape_l_t f,
+ size_t argc, const struct ejit_operand args[argc]);
+
+void ejit_escapei_f(struct ejit_func *s, ejit_escape_f_t f,
+ size_t argc, const struct ejit_operand args[argc]);
+
+void ejit_escapei_d(struct ejit_func *s, ejit_escape_d_t f,
+ size_t argc, const struct ejit_operand args[argc]);
void ejit_ret(struct ejit_func *s);
void ejit_retr(struct ejit_func *s, struct ejit_gpr r0);
@@ -820,6 +879,15 @@ void ejit_truncr_d_32(struct ejit_func *s, struct ejit_gpr r0,
void ejit_truncr_d_64(struct ejit_func *s, struct ejit_gpr r0,
struct ejit_fpr r1);
+void ejit_sqrtr_f(struct ejit_func *s, struct ejit_fpr r0, struct ejit_fpr r1);
+void ejit_sqrtr_d(struct ejit_func *s, struct ejit_fpr r0, struct ejit_fpr r1);
+
+void ejit_minr_f(struct ejit_func *s, struct ejit_fpr r0, struct ejit_fpr r1, struct ejit_fpr r2);
+void ejit_minr_d(struct ejit_func *s, struct ejit_fpr r0, struct ejit_fpr r1, struct ejit_fpr r2);
+
+void ejit_maxr_f(struct ejit_func *s, struct ejit_fpr r0, struct ejit_fpr r1, struct ejit_fpr r2);
+void ejit_maxr_d(struct ejit_func *s, struct ejit_fpr r0, struct ejit_fpr r1, struct ejit_fpr r2);
+
struct ejit_reloc ejit_bltr(struct ejit_func *s, struct ejit_gpr r0,
struct ejit_gpr r1);
struct ejit_reloc ejit_bner(struct ejit_func *s, struct ejit_gpr r0,