From 912c07167705613c6db70e542723c7ec2c06c7ea Mon Sep 17 00:00:00 2001 From: Kimplul Date: Sat, 15 Mar 2025 13:16:54 +0200 Subject: experiment with allocating regs on stack in interp + Avoids having to lug around an execution context, arguably simplified things but now there's no real way to detect when we run out memory for regs. --- src/ejit.c | 79 +++++++++++++++----------------------------------------------- 1 file changed, 19 insertions(+), 60 deletions(-) (limited to 'src/ejit.c') diff --git a/src/ejit.c b/src/ejit.c index 265acea..0a0e7a1 100644 --- a/src/ejit.c +++ b/src/ejit.c @@ -339,6 +339,7 @@ struct ejit_func *ejit_create_func(enum ejit_type rtype, size_t argc, f->size = 0; f->prio = 1; f->use_64 = false; + f->max_args = 0; for (size_t i = 0; i < argc; ++i) { types_append(&f->sign, args[i].type); @@ -403,7 +404,7 @@ void ejit_select_compile_func(struct ejit_func *f, size_t gpr, size_t fpr, void **labels; /* just get labels, don't actually run anything yet */ - ejit_run(f, 0, NULL, NULL, false, &labels); + ejit_run(f, 0, NULL, false, &labels); foreach_vec(ii, f->insns) { struct ejit_insn i = *insns_at(&f->insns, ii); @@ -448,6 +449,7 @@ void ejit_patch(struct ejit_func *f, struct ejit_reloc r, struct ejit_label l) void ejit_calli_i(struct ejit_func *s, struct ejit_func *f, size_t argc, const struct ejit_operand args[argc]) { + f->max_args = argc > f->max_args ? argc : f->max_args; check_operands(f, argc, args); for (size_t i = 0; i < argc; ++i) { @@ -467,6 +469,7 @@ void ejit_calli_l(struct ejit_func *s, struct ejit_func *f, size_t argc, const struct ejit_operand args[argc]) { s->use_64 = true; + f->max_args = argc > f->max_args ? argc : f->max_args; check_operands(f, argc, args); for (size_t i = 0; i < argc; ++i) { @@ -485,6 +488,7 @@ void ejit_calli_l(struct ejit_func *s, struct ejit_func *f, size_t argc, void ejit_calli_f(struct ejit_func *s, struct ejit_func *f, size_t argc, const struct ejit_operand args[argc]) { + s->max_args = argc > s->max_args ? argc : s->max_args; check_operands(f, argc, args); for (size_t i = 0; i < argc; ++i) { @@ -503,6 +507,7 @@ void ejit_calli_f(struct ejit_func *s, struct ejit_func *f, size_t argc, void ejit_calli_d(struct ejit_func *s, struct ejit_func *f, size_t argc, const struct ejit_operand args[argc]) { + s->max_args = argc > s->max_args ? argc : s->max_args; check_operands(f, argc, args); for (size_t i = 0; i < argc; ++i) { @@ -521,6 +526,7 @@ void ejit_calli_d(struct ejit_func *s, struct ejit_func *f, size_t argc, void ejit_escapei_i(struct ejit_func *s, ejit_escape_i_t f, size_t argc, const struct ejit_operand args[argc]) { + s->max_args = argc > s->max_args ? argc : s->max_args; for (size_t i = 0; i < argc; ++i) { switch (args[i].kind) { case EJIT_OPERAND_GPR: emit_insn_ar(s, ARG, i, args[i].type, EJIT_GPR(args[i].r)); break; @@ -538,6 +544,7 @@ void ejit_escapei_l(struct ejit_func *s, ejit_escape_l_t f, size_t argc, const struct ejit_operand args[argc]) { s->use_64 = true; + s->max_args = argc > s->max_args ? argc : s->max_args; for (size_t i = 0; i < argc; ++i) { switch (args[i].kind) { case EJIT_OPERAND_GPR: emit_insn_ar(s, ARG, i, args[i].type, EJIT_GPR(args[i].r)); break; @@ -554,6 +561,7 @@ void ejit_escapei_l(struct ejit_func *s, ejit_escape_l_t f, size_t argc, void ejit_escapei_f(struct ejit_func *s, ejit_escape_f_t f, size_t argc, const struct ejit_operand args[argc]) { + s->max_args = argc > s->max_args ? argc : s->max_args; for (size_t i = 0; i < argc; ++i) { switch (args[i].kind) { case EJIT_OPERAND_GPR: emit_insn_ar(s, ARG, i, args[i].type, EJIT_GPR(args[i].r)); break; @@ -570,6 +578,7 @@ void ejit_escapei_f(struct ejit_func *s, ejit_escape_f_t f, size_t argc, void ejit_escapei_d(struct ejit_func *s, ejit_escape_d_t f, size_t argc, const struct ejit_operand args[argc]) { + s->max_args = argc > s->max_args ? argc : s->max_args; for (size_t i = 0; i < argc; ++i) { switch (args[i].kind) { case EJIT_OPERAND_GPR: emit_insn_ar(s, ARG, i, args[i].type, EJIT_GPR(args[i].r)); break; @@ -1647,23 +1656,8 @@ struct ejit_reloc ejit_bmsr(struct ejit_func *s, struct ejit_gpr r0, return (struct ejit_reloc){.insn = addr}; } -static struct interp_state create_interp_state() -{ - struct interp_state state; - state.gprs = gprs_create(); - state.fprs = fprs_create(); - state.args = args_create(); - return state; -} - -static void destroy_interp_state(struct interp_state state) -{ - gprs_destroy(&state.gprs); - fprs_destroy(&state.fprs); - args_destroy(&state.args); -} - -long ejit_run_func_ctx_i(struct ejit_func *f, size_t argc, struct ejit_arg args[argc], struct interp_state *ctx) +long ejit_run_func_i(struct ejit_func *f, size_t argc, + struct ejit_arg args[argc]) { check_args(f, argc, args); assert((f->rtype == EJIT_VOID || ejit_int_type(f->rtype)) @@ -1672,64 +1666,29 @@ long ejit_run_func_ctx_i(struct ejit_func *f, size_t argc, struct ejit_arg args[ #endif ); - return ejit_run(f, argc, args, ctx, true, NULL).i; + return ejit_run(f, argc, args, true, NULL).i; } -long ejit_run_func_i(struct ejit_func *f, size_t argc, +int64_t ejit_run_func_l(struct ejit_func *f, size_t argc, struct ejit_arg args[argc]) -{ - struct interp_state state = create_interp_state(); - long r = ejit_run_func_ctx_i(f, argc, args, &state); - destroy_interp_state(state); - return r; -} - -int64_t ejit_run_func_ctx_l(struct ejit_func *f, size_t argc, struct ejit_arg args[argc], struct interp_state *ctx) { check_args(f, argc, args); assert(f->rtype == EJIT_INT64 || f->rtype == EJIT_UINT64); - return ejit_run(f, argc, args, ctx, true, NULL).i; -} - -int64_t ejit_run_func_l(struct ejit_func *f, size_t argc, - struct ejit_arg args[argc]) -{ - struct interp_state state = create_interp_state(); - int64_t r = ejit_run_func_ctx_l(f, argc, args, &state); - destroy_interp_state(state); - return r; + return ejit_run(f, argc, args, true, NULL).i; } -float ejit_run_func_ctx_f(struct ejit_func *f, size_t argc, struct ejit_arg args[argc], struct interp_state *ctx) +float ejit_run_func_f(struct ejit_func *f, size_t argc, struct ejit_arg args[argc]) { check_args(f, argc, args); assert(f->rtype == EJIT_FLOAT); - return ejit_run(f, argc, args, ctx, true, NULL).f; + return ejit_run(f, argc, args, true, NULL).f; } -float ejit_run_func_f(struct ejit_func *f, size_t argc, - struct ejit_arg args[argc]) -{ - struct interp_state state = create_interp_state(); - float r = ejit_run_func_ctx_f(f, argc, args, &state); - destroy_interp_state(state); - return r; -} - -double ejit_run_func_ctx_d(struct ejit_func *f, size_t argc, struct ejit_arg args[argc], struct interp_state *ctx) +double ejit_run_func_d(struct ejit_func *f, size_t argc, struct ejit_arg args[argc]) { check_args(f, argc, args); assert(f->rtype == EJIT_DOUBLE); - return ejit_run(f, argc, args, ctx, true, NULL).f; -} - -double ejit_run_func_d(struct ejit_func *f, size_t argc, - struct ejit_arg args[argc]) -{ - struct interp_state state = create_interp_state(); - double r = ejit_run_func_ctx_d(f, argc, args, &state); - destroy_interp_state(state); - return r; + return ejit_run(f, argc, args, true, NULL).f; } struct ejit_arg ejit_run_func(struct ejit_func *f, size_t argc, struct ejit_arg args[argc]) -- cgit v1.2.3 From 67a13eb82534996fbd6ba2fc0c36d3e1284bcd8e Mon Sep 17 00:00:00 2001 From: Kimplul Date: Wed, 26 Mar 2025 13:17:58 +0200 Subject: handle immediates a bit better + Passing floats as immediate values is not supported in lightening, but I might have a go at adding it since it seems like a useful feature at some point --- include/ejit/ejit.h | 4 +-- src/compile/compile.c | 25 +++++++++++++++ src/ejit.c | 3 ++ src/interp.c | 2 +- tests/escapei_immediate_10.c | 73 ++++++++++++++++++++++++++++++++++++++++++++ 5 files changed, 104 insertions(+), 3 deletions(-) create mode 100644 tests/escapei_immediate_10.c (limited to 'src/ejit.c') diff --git a/include/ejit/ejit.h b/include/ejit/ejit.h index 48c4dda..d4bb725 100644 --- a/include/ejit/ejit.h +++ b/include/ejit/ejit.h @@ -157,7 +157,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(); } @@ -245,7 +245,7 @@ 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 */ diff --git a/src/compile/compile.c b/src/compile/compile.c index c979305..50f12dc 100644 --- a/src/compile/compile.c +++ b/src/compile/compile.c @@ -2140,6 +2140,31 @@ static size_t compile_fn_body(struct ejit_func *f, jit_state_t *j, void *arena, case JMP: compile_jmp(f, j, i, &relocs); break; + case ARG_I: { + jit_operand_t type = jit_operand_imm(JIT_OPERAND_ABI_WORD, i.r1); + jit_operand_t arg = jit_operand_imm(jit_abi_from(i.r1), i.o); + operands_append(&src, type); + operands_append(&src, arg); + operands_append(&direct, arg); + + jit_operand_t to[2] = { + jit_operand_mem(JIT_OPERAND_ABI_WORD, JIT_SP, + type_offset(i)), + jit_operand_mem(jit_abi_from(i.r1), JIT_SP, + arg_offset(i)) + }; + + operands_append(&dst, to[0]); + operands_append(&dst, to[1]); + break; + } + + case ARG_FI: { + assert(false && "immediate floats (currently?) not supported"); + abort(); + break; + } + case ARG: { size_t r2 = gpr_stats_at(&f->gpr, i.r2)->rno; jit_operand_t type = jit_operand_imm(JIT_OPERAND_ABI_WORD, i.r1); diff --git a/src/ejit.c b/src/ejit.c index 0a0e7a1..94c69e6 100644 --- a/src/ejit.c +++ b/src/ejit.c @@ -1,4 +1,5 @@ #include +#include #include #include @@ -161,6 +162,8 @@ static void emit_insn_af(struct ejit_func *f, enum ejit_opcode op, size_t idx, e static void emit_insn_ad(struct ejit_func *f, enum ejit_opcode op, size_t idx, enum ejit_type type, double d) { + fprintf(stderr, "warning: immediate floats are currently not supported.\n" + "Consider moving values into FPRs.\n"); struct ejit_insn i = {.op = op, .r0 = idx, .r1 = type, .d = d}; insns_append(&f->insns, i); } diff --git a/src/interp.c b/src/interp.c index 80a9edc..aa40c53 100644 --- a/src/interp.c +++ b/src/interp.c @@ -1009,7 +1009,7 @@ union interp_ret ejit_run(struct ejit_func *f, size_t paramc, struct ejit_arg pa if (i.r1 == EJIT_DOUBLE) a = ejit_build_arg_f(i.r1, i.d); else - a = ejit_build_arg_f(i.r1, i.f); + a = ejit_build_arg_f(i.r1, i.d); args[argc++] = a; DISPATCH(); diff --git a/tests/escapei_immediate_10.c b/tests/escapei_immediate_10.c new file mode 100644 index 0000000..381c79f --- /dev/null +++ b/tests/escapei_immediate_10.c @@ -0,0 +1,73 @@ +#include +#include +#include "do_jit.h" + +static int32_t func(int32_t a, int32_t b, int32_t c, int32_t d, int32_t e, + int32_t f, int32_t g, int32_t h, int32_t i, int32_t j) +{ + assert(a == 0); + assert(b == 1); + assert(c == 2); + assert(d == 3); + assert(e == 4); + assert(f == 5); + assert(g == 6); + assert(h == 7); + assert(i == 8); + assert(j == 9); + return 42; +} + +static long escape_func(size_t argc, const struct ejit_arg args[argc]) +{ + assert(argc == 10); + assert(args[0].type == EJIT_INT32); + assert(args[1].type == EJIT_INT32); + assert(args[3].type == EJIT_INT32); + assert(args[4].type == EJIT_INT32); + assert(args[5].type == EJIT_INT32); + assert(args[6].type == EJIT_INT32); + assert(args[7].type == EJIT_INT32); + assert(args[8].type == EJIT_INT32); + assert(args[9].type == EJIT_INT32); + + int32_t a = args[0].i32; + int32_t b = args[1].i32; + int32_t c = args[2].i32; + int32_t d = args[3].i32; + int32_t e = args[4].i32; + int32_t f = args[5].i32; + int32_t g = args[6].i32; + int32_t h = args[7].i32; + int32_t i = args[8].i32; + int32_t j = args[9].i32; + return func(a, b, c, d, e, f, g, h, i, j); +} + +int main(int argc, char *argv[]) +{ + (void)argv; + bool do_jit = argc > 1; + struct ejit_func *f = ejit_create_func(EJIT_INT32, 0, NULL); + struct ejit_operand args[10] = { + EJIT_OPERAND_IMM(0, EJIT_INT32), + EJIT_OPERAND_IMM(1, EJIT_INT32), + EJIT_OPERAND_IMM(2, EJIT_INT32), + EJIT_OPERAND_IMM(3, EJIT_INT32), + EJIT_OPERAND_IMM(4, EJIT_INT32), + EJIT_OPERAND_IMM(5, EJIT_INT32), + EJIT_OPERAND_IMM(6, EJIT_INT32), + EJIT_OPERAND_IMM(7, EJIT_INT32), + EJIT_OPERAND_IMM(8, EJIT_INT32), + EJIT_OPERAND_IMM(9, EJIT_INT32), + }; + ejit_escapei_i(f, escape_func, 10, args); + ejit_retval(f, EJIT_GPR(0)); + ejit_retr(f, EJIT_GPR(0)); + + ejit_select_compile_func(f, 11, 0, false, do_jit, true); + + assert(ejit_run_func_i(f, 0, NULL) == 42); + + ejit_destroy_func(f); +} -- cgit v1.2.3 From 704baab677029882a5924a59e3fb92f2295132a4 Mon Sep 17 00:00:00 2001 From: Kimplul Date: Tue, 1 Apr 2025 19:40:53 +0300 Subject: somewhat improved register allocator --- src/common.h | 4 +- src/compile/compile.c | 188 ++++++++++++++++++++++++++++++++++++++++++++------ src/ejit.c | 10 ++- 3 files changed, 176 insertions(+), 26 deletions(-) (limited to 'src/ejit.c') diff --git a/src/common.h b/src/common.h index 493a89d..3e56a76 100644 --- a/src/common.h +++ b/src/common.h @@ -258,7 +258,7 @@ struct ejit_insn { struct fpr_stat { struct ejit_fpr f; - size_t prio, fno; + size_t prio, fno, start, end; }; #define VEC_NAME fpr_stats @@ -267,7 +267,7 @@ struct fpr_stat { struct gpr_stat { struct ejit_gpr r; - size_t prio, rno; + size_t prio, rno, start, end; }; #define VEC_NAME gpr_stats diff --git a/src/compile/compile.c b/src/compile/compile.c index 50f12dc..aba44a0 100644 --- a/src/compile/compile.c +++ b/src/compile/compile.c @@ -2203,7 +2203,7 @@ static size_t compile_fn_body(struct ejit_func *f, jit_state_t *j, void *arena, jit_operand_t type = jit_operand_imm(JIT_OPERAND_ABI_WORD, i.r1); jit_operand_t arg; - if (i.r2 < physfpr_count()) { + if (f2 < physfpr_count()) { /* regular register */ arg = jit_operand_fpr(jit_abi_from(i.r1), physfpr_at(f2)); @@ -2421,43 +2421,187 @@ calli: return size; } -/* highest prio first */ -static int gpr_sort_prio(struct gpr_stat *a, struct gpr_stat *b) +struct alive_slot { + long r; + size_t cost; + size_t idx; + size_t remap; +}; + +#define VEC_NAME alive +#define VEC_TYPE struct alive_slot +#include "../vec.h" + +static int spill_cost_sort(struct alive_slot *a, struct alive_slot *b) { - return (int)b->prio - (int)a->prio; + if (a->cost > b->cost) + return -1; + + return a->cost < b->cost; +} + +/* slightly more parameters than I would like but I guess it's fine */ +static void calculate_alive(struct alive *alive, size_t idx, + size_t prio, size_t start, size_t end, size_t *rno, + void *regs, int (*dead)(void *regs, size_t idx, size_t start)) +{ + /* single-shot */ + if (end <= start + 1) { + *rno = 0; + struct alive_slot *a = alive_at(alive, 0); + a->cost += prio; + return; + } + + long max_cost_idx = -1; + size_t max_cost = 0; + long counter = 0; + foreach_vec(ai, *alive) { + struct alive_slot *a = alive_at(alive, ai); + + /* skip reserved slot */ + if (idx == 0) { + counter++; + continue; + } + + if (a->r < 0 && a->cost > max_cost) { + max_cost = a->cost; + max_cost_idx = counter; + } + + counter++; + + /* skip gravestones */ + if (a->r < 0) + continue; + + if (dead(regs, a->r, start)) + a->r = -1; /* gravestone */ + } + + /* there's a suitable slot for us */ + if (max_cost_idx >= 0) { + *rno = max_cost_idx; + + struct alive_slot *a = alive_at(alive, max_cost_idx); + a->cost += prio; + a->r = idx; + return; + } + + *rno = alive_len(alive); + struct alive_slot a = { + .cost = prio, + .r = idx, + .idx = *rno + }; + alive_append(alive, a); } -static int fpr_sort_prio(struct fpr_stat *a, struct fpr_stat *b) +static int gpr_dead(void *regs, size_t idx, size_t start) { - return (int)b->prio - (int)a->prio; + struct gpr_stats *gprs = regs; + return gpr_stats_at(gprs, idx)->end < start; } -/* sort registers by highest priority first, then renumber registers in the - * given order. Higher priority is given a physical register first. - * - * Note that the `->r` field becomes 'meaningless' after sorting, and you should - * only use the `->rno` field after this point. Essentially, if you have a - * register EJIT_GPR(2), you should use `gpr_stats_at(2)->rno` for the 'actual' - * register number in `getloc` and the like. - * - * Can be a bit confusing, but this way we don't have to allocate any new - * arrays, which is cool. */ +static void linear_gpr_alloc(struct ejit_func *f) +{ + foreach_vec(gi, f->gpr) { + gpr_stats_at(&f->gpr, gi)->rno = gi; + } +} + +/* there's a fair bit of repetition between this and the gpr case, hmm */ static void assign_gprs(struct ejit_func *f) { - gpr_stats_sort(&f->gpr, (vec_comp_t)gpr_sort_prio); + /* everything fits into registers, no need to start optimizing */ + if (gpr_stats_len(&f->gpr) <= physgpr_count()) + return linear_gpr_alloc(f); + + struct alive alive = alive_create(gpr_stats_len(&f->gpr)); + + /* special oneshot register class */ + struct alive_slot a = {.r = 0, .cost = 0, .idx = 0}; + alive_append(&alive, a); + + foreach_vec(gi, f->gpr) { + struct gpr_stat *gpr = gpr_stats_at(&f->gpr, gi); + calculate_alive(&alive, gi, + gpr->prio, gpr->start, gpr->end, &gpr->rno, + &f->gpr, gpr_dead); + } + + /* sort so that the highest spill cost register classes are at the front and + * as such more likely to be placed in registers */ + alive_sort(&alive, (vec_comp_t)spill_cost_sort); + + /* update remapping info */ + for(size_t i = 0; i < alive_len(&alive); ++i) { + struct alive_slot *a = alive_at(&alive, i); + alive_at(&alive, a->idx)->remap = i; + } + + /* remap locations */ for (size_t i = 0; i < gpr_stats_len(&f->gpr); ++i) { - size_t rno = gpr_stats_at(&f->gpr, i)->r.r; - gpr_stats_at(&f->gpr, rno)->rno = i; + struct gpr_stat *gpr = gpr_stats_at(&f->gpr, i); + struct alive_slot *a = alive_at(&alive, gpr->rno); + gpr->rno = a->remap; + } + + alive_destroy(&alive); +} + +static int fpr_dead(void *regs, size_t idx, size_t start) +{ + struct fpr_stats *fprs = regs; + return fpr_stats_at(fprs, idx)->end < start; +} + +static void linear_fpr_alloc(struct ejit_func *f) +{ + foreach_vec(fi, f->fpr) { + fpr_stats_at(&f->fpr, fi)->fno = fi; } } static void assign_fprs(struct ejit_func *f) { - fpr_stats_sort(&f->fpr, (vec_comp_t)fpr_sort_prio); + /* everything fits into registers, no need to start optimizing */ + if (fpr_stats_len(&f->fpr) <= physfpr_count()) + return linear_fpr_alloc(f); + + struct alive alive = alive_create(fpr_stats_len(&f->fpr)); + + /* special oneshot register class */ + struct alive_slot a = {.r = 0, .cost = 0, .idx = 0}; + alive_append(&alive, a); + + foreach_vec(fi, f->fpr) { + struct fpr_stat *fpr = fpr_stats_at(&f->fpr, fi); + calculate_alive(&alive, fi, + fpr->prio, fpr->start, fpr->end, &fpr->fno, + &f->fpr, fpr_dead); + } + + /* sort so that the highest spill cost register classes are at the front and + * as such more likely to be placed in registers */ + alive_sort(&alive, (vec_comp_t)spill_cost_sort); + + /* update remapping info */ + for(size_t i = 0; i < alive_len(&alive); ++i) { + struct alive_slot *a = alive_at(&alive, i); + alive_at(&alive, a->idx)->remap = i; + } + + /* remap locations */ for (size_t i = 0; i < fpr_stats_len(&f->fpr); ++i) { - size_t rno = fpr_stats_at(&f->fpr, i)->f.f; - fpr_stats_at(&f->fpr, rno)->fno = i; + struct fpr_stat *fpr = fpr_stats_at(&f->fpr, i); + struct alive_slot *a = alive_at(&alive, fpr->fno); + fpr->fno = a->remap; } + + alive_destroy(&alive); } static size_t align_up(size_t a, size_t n) diff --git a/src/ejit.c b/src/ejit.c index 94c69e6..8247bfe 100644 --- a/src/ejit.c +++ b/src/ejit.c @@ -48,9 +48,12 @@ static void update_gpr(struct ejit_func *f, struct ejit_gpr r0) struct gpr_stat *gpr = gpr_stats_at(&f->gpr, r0.r); /* presumably first time we see this gpr */ /** @todo are branches faster than a memory write? */ - if (gpr->prio == 0) + if (gpr->prio == 0) { + gpr->start = insns_len(&f->insns); gpr->r = r0; + } + gpr->end = insns_len(&f->insns); gpr->prio += f->prio; } @@ -60,9 +63,12 @@ static void update_fpr(struct ejit_func *f, struct ejit_fpr f0) fpr_stats_append(&f->fpr, zero_fpr_stat()); struct fpr_stat *fpr = fpr_stats_at(&f->fpr, f0.f); - if (fpr->prio == 0) + if (fpr->prio == 0) { + fpr->start = insns_len(&f->insns); fpr->f = f0; + } + fpr->end = insns_len(&f->insns); fpr->prio += f->prio; } -- cgit v1.2.3 From 449c23ebc32eb45f8a6360c472bfbf5db6cd132f Mon Sep 17 00:00:00 2001 From: Kimplul Date: Tue, 1 Apr 2025 20:39:42 +0300 Subject: aarch64 linux seems to work --- deps/lightening | 2 +- scripts/select-compile | 1 + src/common.h | 416 +++++++++++++++++++++++------------------------ src/compile/compile.c | 412 +++++++++++++++++++++++----------------------- src/ejit.c | 430 ++++++++++++++++++++++++------------------------- src/interp.c | 416 +++++++++++++++++++++++------------------------ 6 files changed, 839 insertions(+), 838 deletions(-) (limited to 'src/ejit.c') diff --git a/deps/lightening b/deps/lightening index 1cc7a2d..6421af4 160000 --- a/deps/lightening +++ b/deps/lightening @@ -1 +1 @@ -Subproject commit 1cc7a2d159d8cbfc46708d24bfe49f6c23c6e44a +Subproject commit 6421af4db1570a6a5fc3a15f3bcb2601d854ed0e diff --git a/scripts/select-compile b/scripts/select-compile index fca7350..9eff9fd 100755 --- a/scripts/select-compile +++ b/scripts/select-compile @@ -9,6 +9,7 @@ JIT="src/compile/compile.c" NOJIT="src/compile/nocompile.c" case "$ARCH" in + aarch64) echo "$JIT" ;; amd64) echo "$JIT" ;; x86*) echo "$JIT" ;; *) echo "$NOJIT" ;; diff --git a/src/common.h b/src/common.h index 3e56a76..6a3c754 100644 --- a/src/common.h +++ b/src/common.h @@ -21,214 +21,214 @@ #include "vec.h" enum ejit_opcode { - MOVI, - MOVI_F, - MOVI_D, - MOVR, - MOVR_F, - MOVR_D, - - LDI8, - LDI16, - LDI32, - LDI64, - LDIU8, - LDIU16, - LDIU32, - LDIU64, - LDIF, - LDID, - - LDXI8, - LDXI16, - LDXI32, - LDXI64, - LDXIU8, - LDXIU16, - LDXIU32, - LDXIU64, - LDXIF, - LDXID, - - LDXR8, - LDXR16, - LDXR32, - LDXR64, - LDXRU8, - LDXRU16, - LDXRU32, - LDXRU64, - LDXRF, - LDXRD, - - STI8, - STI16, - STI32, - STI64, - STIF, - STID, - - STXI8, - STXI16, - STXI32, - STXI64, - STXIF, - STXID, - - STXR8, - STXR16, - STXR32, - STXR64, - STXRF, - STXRD, - - EXTR8, - EXTR16, - EXTR32, - EXTRU8, - EXTRU16, - EXTRU32, - EXTRF, - EXTRD, - - ADDR, - ADDR_F, - ADDR_D, - ADDI, - - ABSR_F, - ABSR_D, - - SUBR, - SUBR_F, - SUBR_D, - SUBI, - - MULR, - MULR_F, - MULR_D, - - DIVR, - DIVR_U, - DIVR_F, - DIVR_D, - - REMR, - REMR_U, - - COMR, - NEGR, - NEGR_F, - NEGR_D, - - LSHI, - LSHR, - RSHI, - RSHI_U, - RSHR, - RSHR_U, - - ANDR, - ANDI, - - ORR, - ORI, - - XORR, - XORI, - - TRUNCR_D_32, - TRUNCR_D_64, - TRUNCR_F_32, - TRUNCR_F_64, - - EQR, - NER, - GTR, - GTR_U, - GER, - GER_U, - - EQR_F, - NER_F, - GTR_F, - GER_F, - EQR_D, - NER_D, - GTR_D, - GER_D, - - BNER, - BNEI, - BNER_F, - BNER_D, - - BEQR, - BEQI, - BEQR_F, - BEQR_D, - - BGER, - BGER_U, - BGEI, - BGEI_U, - BGER_F, - BGER_D, - - BLEI, - BLEI_U, - - BGTR, - BGTR_U, - BGTI, - BGTI_U, - BGTR_F, - BGTR_D, - - BLTI, - BLTI_U, - - JMP, - JMPR, - - BMCI, - BMCR, - BMSI, - BMSR, - - PARAM, - PARAM_F, - - ARG, - ARG_I, - ARG_F, - ARG_FI, - - ESCAPEI_I, - ESCAPEI_L, - ESCAPEI_F, - ESCAPEI_D, - - CALLI_I, - CALLI_L, - CALLI_F, - CALLI_D, - - RETR, - RETI, - RETR_F, - RETR_D, - RETI_F, - RETI_D, - - RETVAL, - RETVAL_F, - RETVAL_D, - - START, - END, - - OPCODE_COUNT, + EJIT_OP_MOVI, + EJIT_OP_MOVI_F, + EJIT_OP_MOVI_D, + EJIT_OP_MOVR, + EJIT_OP_MOVR_F, + EJIT_OP_MOVR_D, + + EJIT_OP_LDI8, + EJIT_OP_LDI16, + EJIT_OP_LDI32, + EJIT_OP_LDI64, + EJIT_OP_LDIU8, + EJIT_OP_LDIU16, + EJIT_OP_LDIU32, + EJIT_OP_LDIU64, + EJIT_OP_LDIF, + EJIT_OP_LDID, + + EJIT_OP_LDXI8, + EJIT_OP_LDXI16, + EJIT_OP_LDXI32, + EJIT_OP_LDXI64, + EJIT_OP_LDXIU8, + EJIT_OP_LDXIU16, + EJIT_OP_LDXIU32, + EJIT_OP_LDXIU64, + EJIT_OP_LDXIF, + EJIT_OP_LDXID, + + EJIT_OP_LDXR8, + EJIT_OP_LDXR16, + EJIT_OP_LDXR32, + EJIT_OP_LDXR64, + EJIT_OP_LDXRU8, + EJIT_OP_LDXRU16, + EJIT_OP_LDXRU32, + EJIT_OP_LDXRU64, + EJIT_OP_LDXRF, + EJIT_OP_LDXRD, + + EJIT_OP_STI8, + EJIT_OP_STI16, + EJIT_OP_STI32, + EJIT_OP_STI64, + EJIT_OP_STIF, + EJIT_OP_STID, + + EJIT_OP_STXI8, + EJIT_OP_STXI16, + EJIT_OP_STXI32, + EJIT_OP_STXI64, + EJIT_OP_STXIF, + EJIT_OP_STXID, + + EJIT_OP_STXR8, + EJIT_OP_STXR16, + EJIT_OP_STXR32, + EJIT_OP_STXR64, + EJIT_OP_STXRF, + EJIT_OP_STXRD, + + EJIT_OP_EXTR8, + EJIT_OP_EXTR16, + EJIT_OP_EXTR32, + EJIT_OP_EXTRU8, + EJIT_OP_EXTRU16, + EJIT_OP_EXTRU32, + EJIT_OP_EXTRF, + EJIT_OP_EXTRD, + + EJIT_OP_ADDR, + EJIT_OP_ADDR_F, + EJIT_OP_ADDR_D, + EJIT_OP_ADDI, + + EJIT_OP_ABSR_F, + EJIT_OP_ABSR_D, + + EJIT_OP_SUBR, + EJIT_OP_SUBR_F, + EJIT_OP_SUBR_D, + EJIT_OP_SUBI, + + EJIT_OP_MULR, + EJIT_OP_MULR_F, + EJIT_OP_MULR_D, + + EJIT_OP_DIVR, + EJIT_OP_DIVR_U, + EJIT_OP_DIVR_F, + EJIT_OP_DIVR_D, + + EJIT_OP_REMR, + EJIT_OP_REMR_U, + + EJIT_OP_COMR, + EJIT_OP_NEGR, + EJIT_OP_NEGR_F, + EJIT_OP_NEGR_D, + + EJIT_OP_LSHI, + EJIT_OP_LSHR, + EJIT_OP_RSHI, + EJIT_OP_RSHI_U, + EJIT_OP_RSHR, + EJIT_OP_RSHR_U, + + EJIT_OP_ANDR, + EJIT_OP_ANDI, + + EJIT_OP_ORR, + EJIT_OP_ORI, + + EJIT_OP_XORR, + EJIT_OP_XORI, + + EJIT_OP_TRUNCR_D_32, + EJIT_OP_TRUNCR_D_64, + EJIT_OP_TRUNCR_F_32, + EJIT_OP_TRUNCR_F_64, + + EJIT_OP_EQR, + EJIT_OP_NER, + EJIT_OP_GTR, + EJIT_OP_GTR_U, + EJIT_OP_GER, + EJIT_OP_GER_U, + + EJIT_OP_EQR_F, + EJIT_OP_NER_F, + EJIT_OP_GTR_F, + EJIT_OP_GER_F, + EJIT_OP_EQR_D, + EJIT_OP_NER_D, + EJIT_OP_GTR_D, + EJIT_OP_GER_D, + + EJIT_OP_BNER, + EJIT_OP_BNEI, + EJIT_OP_BNER_F, + EJIT_OP_BNER_D, + + EJIT_OP_BEQR, + EJIT_OP_BEQI, + EJIT_OP_BEQR_F, + EJIT_OP_BEQR_D, + + EJIT_OP_BGER, + EJIT_OP_BGER_U, + EJIT_OP_BGEI, + EJIT_OP_BGEI_U, + EJIT_OP_BGER_F, + EJIT_OP_BGER_D, + + EJIT_OP_BLEI, + EJIT_OP_BLEI_U, + + EJIT_OP_BGTR, + EJIT_OP_BGTR_U, + EJIT_OP_BGTI, + EJIT_OP_BGTI_U, + EJIT_OP_BGTR_F, + EJIT_OP_BGTR_D, + + EJIT_OP_BLTI, + EJIT_OP_BLTI_U, + + EJIT_OP_JMP, + EJIT_OP_JMPR, + + EJIT_OP_BMCI, + EJIT_OP_BMCR, + EJIT_OP_BMSI, + EJIT_OP_BMSR, + + EJIT_OP_PARAM, + EJIT_OP_PARAM_F, + + EJIT_OP_ARG, + EJIT_OP_ARG_I, + EJIT_OP_ARG_F, + EJIT_OP_ARG_FI, + + EJIT_OP_ESCAPEI_I, + EJIT_OP_ESCAPEI_L, + EJIT_OP_ESCAPEI_F, + EJIT_OP_ESCAPEI_D, + + EJIT_OP_CALLI_I, + EJIT_OP_CALLI_L, + EJIT_OP_CALLI_F, + EJIT_OP_CALLI_D, + + EJIT_OP_RETR, + EJIT_OP_RETI, + EJIT_OP_RETR_F, + EJIT_OP_RETR_D, + EJIT_OP_RETI_F, + EJIT_OP_RETI_D, + + EJIT_OP_RETVAL, + EJIT_OP_RETVAL_F, + EJIT_OP_RETVAL_D, + + EJIT_OP_START, + EJIT_OP_END, + + EJIT_OPCODE_COUNT, }; struct ejit_insn { diff --git a/src/compile/compile.c b/src/compile/compile.c index aba44a0..b90ee54 100644 --- a/src/compile/compile.c +++ b/src/compile/compile.c @@ -566,7 +566,7 @@ static void compile_absr_d(struct ejit_func *f, jit_state_t *j, { jit_fpr_t r0 = getfpr(f, i.r0, 0); jit_fpr_t r1 = getloc_d(f, j, i.r1, 1); - jit_absr_f(j, r0, r1); + jit_absr_d(j, r0, r1); putloc_d(f, j, i.r0, r0); } @@ -1890,19 +1890,19 @@ static void compile_trampoline(struct ejit_func *f, jit_state_t *j) foreach_vec(ii, f->insns) { struct ejit_insn i = *insns_at(&f->insns, ii); switch (i.op) { - case PARAM: { + case EJIT_OP_PARAM: { jit_operand_t p = jit_operand_mem(jit_abi_from(i.r1), JIT_R1, arg_offset(i)); operands_append(&args, p); break; } - case PARAM_F: { + case EJIT_OP_PARAM_F: { jit_operand_t p = jit_operand_mem(jit_abi_from(i.r1), JIT_R1, arg_offset(i)); operands_append(&args, p); break; } - case START: { + case EJIT_OP_START: { /* callr should be smart enough to avoid JIT_R0 if some * other register wants to write to it */ jit_reloc_t r = jit_mov_addr(j, JIT_R0); @@ -1961,186 +1961,186 @@ static size_t compile_fn_body(struct ejit_func *f, jit_state_t *j, void *arena, struct ejit_insn i = *insns_at(&f->insns, ii); switch (i.op) { - case MOVR: compile_movr(f, j, i); break; - case MOVR_F: compile_movr_f(f, j, i); break; - case MOVR_D: compile_movr_d(f, j, i); break; - - case MOVI: compile_movi(f, j, i); break; - case MOVI_F: compile_movi_f(f, j, i); break; - case MOVI_D: compile_movi_d(f, j, i); break; - - case ADDR: compile_addr(f, j, i); break; - case ADDI: compile_addi(f, j, i); break; - case ADDR_F: compile_addr_f(f, j, i); break; - case ADDR_D: compile_addr_d(f, j, i); break; - - case SUBR: compile_subr(f, j, i); break; - case SUBI: compile_subi(f, j, i); break; - case SUBR_F: compile_subr_f(f, j, i); break; - case SUBR_D: compile_subr_d(f, j, i); break; - - case MULR: compile_mulr(f, j, i); break; - case MULR_F: compile_mulr_f(f, j, i); break; - case MULR_D: compile_mulr_d(f, j, i); break; - - case ANDI: compile_andi(f, j, i); break; - case ANDR: compile_andr(f, j, i); break; - - case ORI: compile_ori(f, j, i); break; - case ORR: compile_orr(f, j, i); break; - - case XORI: compile_xori(f, j, i); break; - case XORR: compile_xorr(f, j, i); break; - - case DIVR: compile_divr(f, j, i); break; - case DIVR_U: compile_divr_u(f, j, i); break; - case DIVR_F: compile_divr_f(f, j, i); break; - case DIVR_D: compile_divr_d(f, j, i); break; - - case REMR: compile_remr(f, j, i); break; - case REMR_U: compile_remr_u(f, j, i); break; - - case ABSR_F: compile_absr_f(f, j, i); break; - case ABSR_D: compile_absr_d(f, j, i); break; - - case LSHI: compile_lshi(f, j, i); break; - case LSHR: compile_lshr(f, j, i); break; - case RSHI: compile_rshi(f, j, i); break; - case RSHI_U: compile_rshi_u(f, j, i); break; - case RSHR: compile_rshr(f, j, i); break; - case RSHR_U: compile_rshr_u(f, j, i); break; - - case STI8: compile_sti8(f, j, i); break; - case STI16: compile_sti16(f, j, i); break; - case STI32: compile_sti32(f, j, i); break; - case STI64: compile_sti64(f, j, i); break; - case STIF: compile_stif(f, j, i); break; - case STID: compile_stid(f, j, i); break; - - case STXI8: compile_stxi8(f, j, i); break; - case STXI16: compile_stxi16(f, j, i); break; - case STXI32: compile_stxi32(f, j, i); break; - case STXI64: compile_stxi64(f, j, i); break; - case STXIF: compile_stxif(f, j, i); break; - case STXID: compile_stxid(f, j, i); break; - - case STXR8: compile_stxr8(f, j, i); break; - case STXR16: compile_stxr16(f, j, i); break; - case STXR32: compile_stxr32(f, j, i); break; - case STXR64: compile_stxr64(f, j, i); break; - case STXRF: compile_stxrf(f, j, i); break; - case STXRD: compile_stxrd(f, j, i); break; - - case LDI8: compile_ldi8(f, j, i); break; - case LDI16: compile_ldi16(f, j, i); break; - case LDI32: compile_ldi32(f, j, i); break; - case LDI64: compile_ldi64(f, j, i); break; - case LDIU8: compile_ldiu8(f, j, i); break; - case LDIU16: compile_ldiu16(f, j, i); break; - case LDIU32: compile_ldiu32(f, j, i); break; - case LDIU64: compile_ldiu64(f, j, i); break; - case LDIF: compile_ldif(f, j, i); break; - case LDID: compile_ldid(f, j, i); break; - - case LDXI8: compile_ldxi8(f, j, i); break; - case LDXI16: compile_ldxi16(f, j, i); break; - case LDXI32: compile_ldxi32(f, j, i); break; - case LDXI64: compile_ldxi64(f, j, i); break; - case LDXIU8: compile_ldxiu8(f, j, i); break; - case LDXIU16: compile_ldxiu16(f, j, i); break; - case LDXIU32: compile_ldxiu32(f, j, i); break; - case LDXIU64: compile_ldxiu64(f, j, i); break; - case LDXIF: compile_ldxif(f, j, i); break; - case LDXID: compile_ldxid(f, j, i); break; - - case LDXR8: compile_ldxr8(f, j, i); break; - case LDXR16: compile_ldxr16(f, j, i); break; - case LDXR32: compile_ldxr32(f, j, i); break; - case LDXR64: compile_ldxr64(f, j, i); break; - case LDXRU8: compile_ldxru8(f, j, i); break; - case LDXRU16: compile_ldxru16(f, j, i); break; - case LDXRU32: compile_ldxru32(f, j, i); break; - case LDXRU64: compile_ldxru64(f, j, i); break; - case LDXRF: compile_ldxrf(f, j, i); break; - case LDXRD: compile_ldxrd(f, j, i); break; - - case COMR: compile_comr(f, j, i); break; - - case NEGR: compile_negr(f, j, i); break; - case NEGR_F: compile_negr_f(f, j, i); break; - case NEGR_D: compile_negr_d(f, j, i); break; - - case EXTR8: compile_extr8(f, j, i); break; - case EXTR16: compile_extr16(f, j, i); break; - case EXTR32: compile_extr32(f, j, i); break; - case EXTRU8: compile_extru8(f, j, i); break; - case EXTRU16: compile_extru16(f, j, i); break; - case EXTRU32: compile_extru32(f, j, i); break; - case EXTRF: compile_extrf(f, j, i); break; - case EXTRD: compile_extrd(f, j, i); break; - - case TRUNCR_D_32: compile_truncr_d_32(f, j, i); break; - case TRUNCR_D_64: compile_truncr_d_64(f, j, i); break; - case TRUNCR_F_32: compile_truncr_f_32(f, j, i); break; - case TRUNCR_F_64: compile_truncr_f_64(f, j, i); break; - - case EQR: compile_eqr(f, j, i); break; - case EQR_F: compile_eqr_f(f, j, i); break; - case EQR_D: compile_eqr_d(f, j, i); break; - - case NER: compile_ner(f, j, i); break; - case NER_F: compile_ner_f(f, j, i); break; - case NER_D: compile_ner_d(f, j, i); break; - - case GER: compile_ger(f, j, i); break; - case GER_U: compile_ger_u(f, j, i); break; - case GER_F: compile_ger_f(f, j, i); break; - case GER_D: compile_ger_d(f, j, i); break; - - case GTR: compile_gtr(f, j, i); break; - case GTR_U: compile_gtr_u(f, j, i); break; - case GTR_F: compile_gtr_f(f, j, i); break; - case GTR_D: compile_gtr_d(f, j, i); break; - - case BMCI: compile_bmci(f, j, i, &relocs); break; - case BMCR: compile_bmcr(f, j, i, &relocs); break; - - case BMSI: compile_bmsi(f, j, i, &relocs); break; - case BMSR: compile_bmsr(f, j, i, &relocs); break; - - case BEQR: compile_beqr(f, j, i, &relocs); break; - case BEQI: compile_beqi(f, j, i, &relocs); break; - case BEQR_F: compile_beqr_f(f, j, i, &relocs); break; - case BEQR_D: compile_beqr_d(f, j, i, &relocs); break; - - case BNER: compile_bner(f, j, i, &relocs); break; - case BNEI: compile_bnei(f, j, i, &relocs); break; - case BNER_F: compile_bner_f(f, j, i, &relocs); break; - case BNER_D: compile_bner_d(f, j, i, &relocs); break; - - case BGER: compile_bger(f, j, i, &relocs); break; - case BGER_U: compile_bger_u(f, j, i, &relocs); break; - case BGEI: compile_bgei(f, j, i, &relocs); break; - case BGEI_U: compile_bgei_u(f, j, i, &relocs); break; - case BGER_F: compile_bger_f(f, j, i, &relocs); break; - case BGER_D: compile_bger_d(f, j, i, &relocs); break; - - case BGTR: compile_bgtr(f, j, i, &relocs); break; - case BGTR_U: compile_bgtr_u(f, j, i, &relocs); break; - case BGTI: compile_bgti(f, j, i, &relocs); break; - case BGTI_U: compile_bgti_u(f, j, i, &relocs); break; - case BGTR_F: compile_bgtr_f(f, j, i, &relocs); break; - case BGTR_D: compile_bgtr_d(f, j, i, &relocs); break; - - case BLEI: compile_blei(f, j, i, &relocs); break; - case BLEI_U: compile_blei_u(f, j, i, &relocs); break; - - case BLTI: compile_blti(f, j, i, &relocs); break; - case BLTI_U: compile_blti_u(f, j, i, &relocs); break; - - case JMP: compile_jmp(f, j, i, &relocs); break; - - case ARG_I: { + case EJIT_OP_MOVR: compile_movr(f, j, i); break; + case EJIT_OP_MOVR_F: compile_movr_f(f, j, i); break; + case EJIT_OP_MOVR_D: compile_movr_d(f, j, i); break; + + case EJIT_OP_MOVI: compile_movi(f, j, i); break; + case EJIT_OP_MOVI_F: compile_movi_f(f, j, i); break; + case EJIT_OP_MOVI_D: compile_movi_d(f, j, i); break; + + case EJIT_OP_ADDR: compile_addr(f, j, i); break; + case EJIT_OP_ADDI: compile_addi(f, j, i); break; + case EJIT_OP_ADDR_F: compile_addr_f(f, j, i); break; + case EJIT_OP_ADDR_D: compile_addr_d(f, j, i); break; + + case EJIT_OP_SUBR: compile_subr(f, j, i); break; + case EJIT_OP_SUBI: compile_subi(f, j, i); break; + case EJIT_OP_SUBR_F: compile_subr_f(f, j, i); break; + case EJIT_OP_SUBR_D: compile_subr_d(f, j, i); break; + + case EJIT_OP_MULR: compile_mulr(f, j, i); break; + case EJIT_OP_MULR_F: compile_mulr_f(f, j, i); break; + case EJIT_OP_MULR_D: compile_mulr_d(f, j, i); break; + + case EJIT_OP_ANDI: compile_andi(f, j, i); break; + case EJIT_OP_ANDR: compile_andr(f, j, i); break; + + case EJIT_OP_ORI: compile_ori(f, j, i); break; + case EJIT_OP_ORR: compile_orr(f, j, i); break; + + case EJIT_OP_XORI: compile_xori(f, j, i); break; + case EJIT_OP_XORR: compile_xorr(f, j, i); break; + + case EJIT_OP_DIVR: compile_divr(f, j, i); break; + case EJIT_OP_DIVR_U: compile_divr_u(f, j, i); break; + case EJIT_OP_DIVR_F: compile_divr_f(f, j, i); break; + case EJIT_OP_DIVR_D: compile_divr_d(f, j, i); break; + + case EJIT_OP_REMR: compile_remr(f, j, i); break; + case EJIT_OP_REMR_U: compile_remr_u(f, j, i); break; + + case EJIT_OP_ABSR_F: compile_absr_f(f, j, i); break; + case EJIT_OP_ABSR_D: compile_absr_d(f, j, i); break; + + case EJIT_OP_LSHI: compile_lshi(f, j, i); break; + case EJIT_OP_LSHR: compile_lshr(f, j, i); break; + case EJIT_OP_RSHI: compile_rshi(f, j, i); break; + case EJIT_OP_RSHI_U: compile_rshi_u(f, j, i); break; + case EJIT_OP_RSHR: compile_rshr(f, j, i); break; + case EJIT_OP_RSHR_U: compile_rshr_u(f, j, i); break; + + case EJIT_OP_STI8: compile_sti8(f, j, i); break; + case EJIT_OP_STI16: compile_sti16(f, j, i); break; + case EJIT_OP_STI32: compile_sti32(f, j, i); break; + case EJIT_OP_STI64: compile_sti64(f, j, i); break; + case EJIT_OP_STIF: compile_stif(f, j, i); break; + case EJIT_OP_STID: compile_stid(f, j, i); break; + + case EJIT_OP_STXI8: compile_stxi8(f, j, i); break; + case EJIT_OP_STXI16: compile_stxi16(f, j, i); break; + case EJIT_OP_STXI32: compile_stxi32(f, j, i); break; + case EJIT_OP_STXI64: compile_stxi64(f, j, i); break; + case EJIT_OP_STXIF: compile_stxif(f, j, i); break; + case EJIT_OP_STXID: compile_stxid(f, j, i); break; + + case EJIT_OP_STXR8: compile_stxr8(f, j, i); break; + case EJIT_OP_STXR16: compile_stxr16(f, j, i); break; + case EJIT_OP_STXR32: compile_stxr32(f, j, i); break; + case EJIT_OP_STXR64: compile_stxr64(f, j, i); break; + case EJIT_OP_STXRF: compile_stxrf(f, j, i); break; + case EJIT_OP_STXRD: compile_stxrd(f, j, i); break; + + case EJIT_OP_LDI8: compile_ldi8(f, j, i); break; + case EJIT_OP_LDI16: compile_ldi16(f, j, i); break; + case EJIT_OP_LDI32: compile_ldi32(f, j, i); break; + case EJIT_OP_LDI64: compile_ldi64(f, j, i); break; + case EJIT_OP_LDIU8: compile_ldiu8(f, j, i); break; + case EJIT_OP_LDIU16: compile_ldiu16(f, j, i); break; + case EJIT_OP_LDIU32: compile_ldiu32(f, j, i); break; + case EJIT_OP_LDIU64: compile_ldiu64(f, j, i); break; + case EJIT_OP_LDIF: compile_ldif(f, j, i); break; + case EJIT_OP_LDID: compile_ldid(f, j, i); break; + + case EJIT_OP_LDXI8: compile_ldxi8(f, j, i); break; + case EJIT_OP_LDXI16: compile_ldxi16(f, j, i); break; + case EJIT_OP_LDXI32: compile_ldxi32(f, j, i); break; + case EJIT_OP_LDXI64: compile_ldxi64(f, j, i); break; + case EJIT_OP_LDXIU8: compile_ldxiu8(f, j, i); break; + case EJIT_OP_LDXIU16: compile_ldxiu16(f, j, i); break; + case EJIT_OP_LDXIU32: compile_ldxiu32(f, j, i); break; + case EJIT_OP_LDXIU64: compile_ldxiu64(f, j, i); break; + case EJIT_OP_LDXIF: compile_ldxif(f, j, i); break; + case EJIT_OP_LDXID: compile_ldxid(f, j, i); break; + + case EJIT_OP_LDXR8: compile_ldxr8(f, j, i); break; + case EJIT_OP_LDXR16: compile_ldxr16(f, j, i); break; + case EJIT_OP_LDXR32: compile_ldxr32(f, j, i); break; + case EJIT_OP_LDXR64: compile_ldxr64(f, j, i); break; + case EJIT_OP_LDXRU8: compile_ldxru8(f, j, i); break; + case EJIT_OP_LDXRU16: compile_ldxru16(f, j, i); break; + case EJIT_OP_LDXRU32: compile_ldxru32(f, j, i); break; + case EJIT_OP_LDXRU64: compile_ldxru64(f, j, i); break; + case EJIT_OP_LDXRF: compile_ldxrf(f, j, i); break; + case EJIT_OP_LDXRD: compile_ldxrd(f, j, i); break; + + case EJIT_OP_COMR: compile_comr(f, j, i); break; + + case EJIT_OP_NEGR: compile_negr(f, j, i); break; + case EJIT_OP_NEGR_F: compile_negr_f(f, j, i); break; + case EJIT_OP_NEGR_D: compile_negr_d(f, j, i); break; + + case EJIT_OP_EXTR8: compile_extr8(f, j, i); break; + case EJIT_OP_EXTR16: compile_extr16(f, j, i); break; + case EJIT_OP_EXTR32: compile_extr32(f, j, i); break; + case EJIT_OP_EXTRU8: compile_extru8(f, j, i); break; + case EJIT_OP_EXTRU16: compile_extru16(f, j, i); break; + case EJIT_OP_EXTRU32: compile_extru32(f, j, i); break; + case EJIT_OP_EXTRF: compile_extrf(f, j, i); break; + case EJIT_OP_EXTRD: compile_extrd(f, j, i); break; + + case EJIT_OP_TRUNCR_D_32: compile_truncr_d_32(f, j, i); break; + case EJIT_OP_TRUNCR_D_64: compile_truncr_d_64(f, j, i); break; + case EJIT_OP_TRUNCR_F_32: compile_truncr_f_32(f, j, i); break; + case EJIT_OP_TRUNCR_F_64: compile_truncr_f_64(f, j, i); break; + + case EJIT_OP_EQR: compile_eqr(f, j, i); break; + case EJIT_OP_EQR_F: compile_eqr_f(f, j, i); break; + case EJIT_OP_EQR_D: compile_eqr_d(f, j, i); break; + + case EJIT_OP_NER: compile_ner(f, j, i); break; + case EJIT_OP_NER_F: compile_ner_f(f, j, i); break; + case EJIT_OP_NER_D: compile_ner_d(f, j, i); break; + + case EJIT_OP_GER: compile_ger(f, j, i); break; + case EJIT_OP_GER_U: compile_ger_u(f, j, i); break; + case EJIT_OP_GER_F: compile_ger_f(f, j, i); break; + case EJIT_OP_GER_D: compile_ger_d(f, j, i); break; + + case EJIT_OP_GTR: compile_gtr(f, j, i); break; + case EJIT_OP_GTR_U: compile_gtr_u(f, j, i); break; + case EJIT_OP_GTR_F: compile_gtr_f(f, j, i); break; + case EJIT_OP_GTR_D: compile_gtr_d(f, j, i); break; + + case EJIT_OP_BMCI: compile_bmci(f, j, i, &relocs); break; + case EJIT_OP_BMCR: compile_bmcr(f, j, i, &relocs); break; + + case EJIT_OP_BMSI: compile_bmsi(f, j, i, &relocs); break; + case EJIT_OP_BMSR: compile_bmsr(f, j, i, &relocs); break; + + case EJIT_OP_BEQR: compile_beqr(f, j, i, &relocs); break; + case EJIT_OP_BEQI: compile_beqi(f, j, i, &relocs); break; + case EJIT_OP_BEQR_F: compile_beqr_f(f, j, i, &relocs); break; + case EJIT_OP_BEQR_D: compile_beqr_d(f, j, i, &relocs); break; + + case EJIT_OP_BNER: compile_bner(f, j, i, &relocs); break; + case EJIT_OP_BNEI: compile_bnei(f, j, i, &relocs); break; + case EJIT_OP_BNER_F: compile_bner_f(f, j, i, &relocs); break; + case EJIT_OP_BNER_D: compile_bner_d(f, j, i, &relocs); break; + + case EJIT_OP_BGER: compile_bger(f, j, i, &relocs); break; + case EJIT_OP_BGER_U: compile_bger_u(f, j, i, &relocs); break; + case EJIT_OP_BGEI: compile_bgei(f, j, i, &relocs); break; + case EJIT_OP_BGEI_U: compile_bgei_u(f, j, i, &relocs); break; + case EJIT_OP_BGER_F: compile_bger_f(f, j, i, &relocs); break; + case EJIT_OP_BGER_D: compile_bger_d(f, j, i, &relocs); break; + + case EJIT_OP_BGTR: compile_bgtr(f, j, i, &relocs); break; + case EJIT_OP_BGTR_U: compile_bgtr_u(f, j, i, &relocs); break; + case EJIT_OP_BGTI: compile_bgti(f, j, i, &relocs); break; + case EJIT_OP_BGTI_U: compile_bgti_u(f, j, i, &relocs); break; + case EJIT_OP_BGTR_F: compile_bgtr_f(f, j, i, &relocs); break; + case EJIT_OP_BGTR_D: compile_bgtr_d(f, j, i, &relocs); break; + + case EJIT_OP_BLEI: compile_blei(f, j, i, &relocs); break; + case EJIT_OP_BLEI_U: compile_blei_u(f, j, i, &relocs); break; + + case EJIT_OP_BLTI: compile_blti(f, j, i, &relocs); break; + case EJIT_OP_BLTI_U: compile_blti_u(f, j, i, &relocs); break; + + case EJIT_OP_JMP: compile_jmp(f, j, i, &relocs); break; + + case EJIT_OP_ARG_I: { jit_operand_t type = jit_operand_imm(JIT_OPERAND_ABI_WORD, i.r1); jit_operand_t arg = jit_operand_imm(jit_abi_from(i.r1), i.o); operands_append(&src, type); @@ -2159,13 +2159,13 @@ static size_t compile_fn_body(struct ejit_func *f, jit_state_t *j, void *arena, break; } - case ARG_FI: { + case EJIT_OP_ARG_FI: { assert(false && "immediate floats (currently?) not supported"); abort(); break; } - case ARG: { + case EJIT_OP_ARG: { size_t r2 = gpr_stats_at(&f->gpr, i.r2)->rno; jit_operand_t type = jit_operand_imm(JIT_OPERAND_ABI_WORD, i.r1); @@ -2198,7 +2198,7 @@ static size_t compile_fn_body(struct ejit_func *f, jit_state_t *j, void *arena, break; } - case ARG_F: { + case EJIT_OP_ARG_F: { size_t f2 = fpr_stats_at(&f->fpr, i.r2)->fno; jit_operand_t type = jit_operand_imm(JIT_OPERAND_ABI_WORD, i.r1); @@ -2232,7 +2232,7 @@ static size_t compile_fn_body(struct ejit_func *f, jit_state_t *j, void *arena, break; } - case ESCAPEI_L: + case EJIT_OP_ESCAPEI_L: #if __WORDSIZE == 64 /* fallthrough */ #else @@ -2240,9 +2240,9 @@ static size_t compile_fn_body(struct ejit_func *f, jit_state_t *j, void *arena, break; #endif - case ESCAPEI_D: - case ESCAPEI_F: - case ESCAPEI_I: { + case EJIT_OP_ESCAPEI_D: + case EJIT_OP_ESCAPEI_F: + case EJIT_OP_ESCAPEI_I: { save_caller_save_regs(f, j); jit_operand_t args[2] = { @@ -2261,7 +2261,7 @@ static size_t compile_fn_body(struct ejit_func *f, jit_state_t *j, void *arena, break; } - case CALLI_L: + case EJIT_OP_CALLI_L: #if __WORDSIZE == 64 call = checked_run_l; goto calli; #else @@ -2269,9 +2269,9 @@ static size_t compile_fn_body(struct ejit_func *f, jit_state_t *j, void *arena, break; #endif - case CALLI_F: { call = checked_run_f; goto calli; } - case CALLI_D: { call = checked_run_d; goto calli; } - case CALLI_I: { call = checked_run_i; goto calli; + case EJIT_OP_CALLI_F: { call = checked_run_f; goto calli; } + case EJIT_OP_CALLI_D: { call = checked_run_d; goto calli; } + case EJIT_OP_CALLI_I: { call = checked_run_i; goto calli; calli: save_caller_save_regs(f, j); @@ -2303,11 +2303,11 @@ calli: break; } - case RETVAL: compile_retval(f, j, i); break; - case RETVAL_F: compile_retval_f(f, j, i); break; - case RETVAL_D: compile_retval_d(f, j, i); break; + case EJIT_OP_RETVAL: compile_retval(f, j, i); break; + case EJIT_OP_RETVAL_F: compile_retval_f(f, j, i); break; + case EJIT_OP_RETVAL_D: compile_retval_d(f, j, i); break; - case RETR: { + case EJIT_OP_RETR: { jit_gpr_t r = getloc(f, j, i.r1, 0); /* R0 won't get overwritten by jit_leave_jit_abi */ jit_movr(j, JIT_R0, r); @@ -2317,7 +2317,7 @@ calli: break; } - case RETR_F: { + case EJIT_OP_RETR_F: { jit_fpr_t r = getloc_f(f, j, i.r1, 0); jit_movr_f(j, JIT_F0, r); jit_shrink_stack(j, stack); @@ -2326,7 +2326,7 @@ calli: break; } - case RETR_D: { + case EJIT_OP_RETR_D: { jit_fpr_t r = getloc_d(f, j, i.r1, 0); jit_movr_d(j, JIT_F0, r); jit_shrink_stack(j, stack); @@ -2335,14 +2335,14 @@ calli: break; } - case RETI: { + case EJIT_OP_RETI: { jit_shrink_stack(j, stack); jit_leave_jit_abi(j, gprs, fprs, frame); jit_reti(j, i.o); break; } - case END: { + case EJIT_OP_END: { /* 'void' return */ jit_shrink_stack(j, stack); jit_leave_jit_abi(j, gprs, fprs, frame); @@ -2350,7 +2350,7 @@ calli: break; } - case PARAM_F: { + case EJIT_OP_PARAM_F: { size_t f2 = fpr_stats_at(&f->fpr, i.r2)->fno; jit_operand_t to; @@ -2369,7 +2369,7 @@ calli: break; } - case PARAM: { + case EJIT_OP_PARAM: { size_t r2 = gpr_stats_at(&f->gpr, i.r2)->rno; jit_operand_t to; @@ -2388,7 +2388,7 @@ calli: break; } - case START: { + case EJIT_OP_START: { /* parameters should be done by now */ jit_load_args(j, operands_len(&dst), dst.buf); /* reuse for arguments */ diff --git a/src/ejit.c b/src/ejit.c index 8247bfe..e7e2ff2 100644 --- a/src/ejit.c +++ b/src/ejit.c @@ -356,20 +356,20 @@ struct ejit_func *ejit_create_func(enum ejit_type rtype, size_t argc, switch (args[i].kind) { case EJIT_OPERAND_GPR: { assert(ejit_int_type(args[i].type)); - emit_insn_ar(f, PARAM, i, args[i].type, EJIT_GPR(args[i].r)); + emit_insn_ar(f, EJIT_OP_PARAM, i, args[i].type, EJIT_GPR(args[i].r)); break; } case EJIT_OPERAND_FPR: { assert(ejit_float_type(args[i].type)); - emit_insn_af(f, PARAM_F, i, args[i].type, EJIT_FPR(args[i].r)); + emit_insn_af(f, EJIT_OP_PARAM_F, i, args[i].type, EJIT_FPR(args[i].r)); break; } default: abort(); } } - emit_insn_o(f, START); + emit_insn_o(f, EJIT_OP_START); return f; } @@ -398,7 +398,7 @@ void ejit_select_compile_func(struct ejit_func *f, size_t gpr, size_t fpr, bool use_64, bool try_jit, bool im_scawed) { /* emit a final end instruction in case user didn't do a return */ - emit_insn_o(f, END); + emit_insn_o(f, EJIT_OP_END); /* user can get some sanity checking done by passing these explicitly */ assert(gpr >= gpr_stats_len(&f->gpr)); @@ -463,15 +463,15 @@ void ejit_calli_i(struct ejit_func *s, struct ejit_func *f, size_t argc, for (size_t i = 0; i < argc; ++i) { switch (args[i].kind) { - case EJIT_OPERAND_GPR: emit_insn_ar(s, ARG, i, args[i].type, EJIT_GPR(args[i].r)); break; - case EJIT_OPERAND_FPR: emit_insn_af(s, ARG_F, i, args[i].type, EJIT_FPR(args[i].r)); break; - case EJIT_OPERAND_IMM: emit_insn_ai(s, ARG_I, i, args[i].type, args[i].r); break; - case EJIT_OPERAND_FLT: emit_insn_ad(s, ARG_FI, i, args[i].type, args[i].d); break; + case EJIT_OPERAND_GPR: emit_insn_ar(s, EJIT_OP_ARG, i, args[i].type, EJIT_GPR(args[i].r)); break; + case EJIT_OPERAND_FPR: emit_insn_af(s, EJIT_OP_ARG_F, i, args[i].type, EJIT_FPR(args[i].r)); break; + case EJIT_OPERAND_IMM: emit_insn_ai(s, EJIT_OP_ARG_I, i, args[i].type, args[i].r); break; + case EJIT_OPERAND_FLT: emit_insn_ad(s, EJIT_OP_ARG_FI, i, args[i].type, args[i].d); break; default: abort(); } } - emit_insn_op(s, CALLI_I, f); + emit_insn_op(s, EJIT_OP_CALLI_I, f); } void ejit_calli_l(struct ejit_func *s, struct ejit_func *f, size_t argc, @@ -483,15 +483,15 @@ void ejit_calli_l(struct ejit_func *s, struct ejit_func *f, size_t argc, for (size_t i = 0; i < argc; ++i) { switch (args[i].kind) { - case EJIT_OPERAND_GPR: emit_insn_ar(s, ARG, i, args[i].type, EJIT_GPR(args[i].r)); break; - case EJIT_OPERAND_FPR: emit_insn_af(s, ARG_F, i, args[i].type, EJIT_FPR(args[i].r)); break; - case EJIT_OPERAND_IMM: emit_insn_ai(s, ARG_I, i, args[i].type, args[i].r); break; - case EJIT_OPERAND_FLT: emit_insn_ad(s, ARG_FI, i, args[i].type, args[i].d); break; + case EJIT_OPERAND_GPR: emit_insn_ar(s, EJIT_OP_ARG, i, args[i].type, EJIT_GPR(args[i].r)); break; + case EJIT_OPERAND_FPR: emit_insn_af(s, EJIT_OP_ARG_F, i, args[i].type, EJIT_FPR(args[i].r)); break; + case EJIT_OPERAND_IMM: emit_insn_ai(s, EJIT_OP_ARG_I, i, args[i].type, args[i].r); break; + case EJIT_OPERAND_FLT: emit_insn_ad(s, EJIT_OP_ARG_FI, i, args[i].type, args[i].d); break; default: abort(); } } - emit_insn_op(s, CALLI_L, f); + emit_insn_op(s, EJIT_OP_CALLI_L, f); } void ejit_calli_f(struct ejit_func *s, struct ejit_func *f, size_t argc, @@ -502,15 +502,15 @@ void ejit_calli_f(struct ejit_func *s, struct ejit_func *f, size_t argc, for (size_t i = 0; i < argc; ++i) { switch (args[i].kind) { - case EJIT_OPERAND_GPR: emit_insn_ar(s, ARG, i, args[i].type, EJIT_GPR(args[i].r)); break; - case EJIT_OPERAND_FPR: emit_insn_af(s, ARG_F, i, args[i].type, EJIT_FPR(args[i].r)); break; - case EJIT_OPERAND_IMM: emit_insn_ai(s, ARG_I, i, args[i].type, args[i].r); break; - case EJIT_OPERAND_FLT: emit_insn_ad(s, ARG_FI, i, args[i].type, args[i].d); break; + case EJIT_OPERAND_GPR: emit_insn_ar(s, EJIT_OP_ARG, i, args[i].type, EJIT_GPR(args[i].r)); break; + case EJIT_OPERAND_FPR: emit_insn_af(s, EJIT_OP_ARG_F, i, args[i].type, EJIT_FPR(args[i].r)); break; + case EJIT_OPERAND_IMM: emit_insn_ai(s, EJIT_OP_ARG_I, i, args[i].type, args[i].r); break; + case EJIT_OPERAND_FLT: emit_insn_ad(s, EJIT_OP_ARG_FI, i, args[i].type, args[i].d); break; default: abort(); } } - emit_insn_op(s, CALLI_F, f); + emit_insn_op(s, EJIT_OP_CALLI_F, f); } void ejit_calli_d(struct ejit_func *s, struct ejit_func *f, size_t argc, @@ -521,15 +521,15 @@ void ejit_calli_d(struct ejit_func *s, struct ejit_func *f, size_t argc, for (size_t i = 0; i < argc; ++i) { switch (args[i].kind) { - case EJIT_OPERAND_GPR: emit_insn_ar(s, ARG, i, args[i].type, EJIT_GPR(args[i].r)); break; - case EJIT_OPERAND_FPR: emit_insn_af(s, ARG_F, i, args[i].type, EJIT_FPR(args[i].r)); break; - case EJIT_OPERAND_IMM: emit_insn_ai(s, ARG_I, i, args[i].type, args[i].r); break; - case EJIT_OPERAND_FLT: emit_insn_ad(s, ARG_FI, i, args[i].type, args[i].d); break; + case EJIT_OPERAND_GPR: emit_insn_ar(s, EJIT_OP_ARG, i, args[i].type, EJIT_GPR(args[i].r)); break; + case EJIT_OPERAND_FPR: emit_insn_af(s, EJIT_OP_ARG_F, i, args[i].type, EJIT_FPR(args[i].r)); break; + case EJIT_OPERAND_IMM: emit_insn_ai(s, EJIT_OP_ARG_I, i, args[i].type, args[i].r); break; + case EJIT_OPERAND_FLT: emit_insn_ad(s, EJIT_OP_ARG_FI, i, args[i].type, args[i].d); break; default: abort(); } } - emit_insn_op(s, CALLI_D, f); + emit_insn_op(s, EJIT_OP_CALLI_D, f); } void ejit_escapei_i(struct ejit_func *s, ejit_escape_i_t f, size_t argc, @@ -538,15 +538,15 @@ void ejit_escapei_i(struct ejit_func *s, ejit_escape_i_t f, size_t argc, s->max_args = argc > s->max_args ? argc : s->max_args; for (size_t i = 0; i < argc; ++i) { switch (args[i].kind) { - case EJIT_OPERAND_GPR: emit_insn_ar(s, ARG, i, args[i].type, EJIT_GPR(args[i].r)); break; - case EJIT_OPERAND_FPR: emit_insn_af(s, ARG_F, i, args[i].type, EJIT_FPR(args[i].r)); break; - case EJIT_OPERAND_IMM: emit_insn_ai(s, ARG_I, i, args[i].type, args[i].r); break; - case EJIT_OPERAND_FLT: emit_insn_ad(s, ARG_FI, i, args[i].type, args[i].d); break; + case EJIT_OPERAND_GPR: emit_insn_ar(s, EJIT_OP_ARG, i, args[i].type, EJIT_GPR(args[i].r)); break; + case EJIT_OPERAND_FPR: emit_insn_af(s, EJIT_OP_ARG_F, i, args[i].type, EJIT_FPR(args[i].r)); break; + case EJIT_OPERAND_IMM: emit_insn_ai(s, EJIT_OP_ARG_I, i, args[i].type, args[i].r); break; + case EJIT_OPERAND_FLT: emit_insn_ad(s, EJIT_OP_ARG_FI, i, args[i].type, args[i].d); break; default: abort(); } } - emit_insn_op(s, ESCAPEI_I, f); + emit_insn_op(s, EJIT_OP_ESCAPEI_I, f); } void ejit_escapei_l(struct ejit_func *s, ejit_escape_l_t f, size_t argc, @@ -556,15 +556,15 @@ void ejit_escapei_l(struct ejit_func *s, ejit_escape_l_t f, size_t argc, s->max_args = argc > s->max_args ? argc : s->max_args; for (size_t i = 0; i < argc; ++i) { switch (args[i].kind) { - case EJIT_OPERAND_GPR: emit_insn_ar(s, ARG, i, args[i].type, EJIT_GPR(args[i].r)); break; - case EJIT_OPERAND_FPR: emit_insn_af(s, ARG_F, i, args[i].type, EJIT_FPR(args[i].r)); break; - case EJIT_OPERAND_IMM: emit_insn_ai(s, ARG_I, i, args[i].type, args[i].r); break; - case EJIT_OPERAND_FLT: emit_insn_ad(s, ARG_FI, i, args[i].type, args[i].d); break; + case EJIT_OPERAND_GPR: emit_insn_ar(s, EJIT_OP_ARG, i, args[i].type, EJIT_GPR(args[i].r)); break; + case EJIT_OPERAND_FPR: emit_insn_af(s, EJIT_OP_ARG_F, i, args[i].type, EJIT_FPR(args[i].r)); break; + case EJIT_OPERAND_IMM: emit_insn_ai(s, EJIT_OP_ARG_I, i, args[i].type, args[i].r); break; + case EJIT_OPERAND_FLT: emit_insn_ad(s, EJIT_OP_ARG_FI, i, args[i].type, args[i].d); break; default: abort(); } } - emit_insn_op(s, ESCAPEI_L, f); + emit_insn_op(s, EJIT_OP_ESCAPEI_L, f); } void ejit_escapei_f(struct ejit_func *s, ejit_escape_f_t f, size_t argc, @@ -573,15 +573,15 @@ void ejit_escapei_f(struct ejit_func *s, ejit_escape_f_t f, size_t argc, s->max_args = argc > s->max_args ? argc : s->max_args; for (size_t i = 0; i < argc; ++i) { switch (args[i].kind) { - case EJIT_OPERAND_GPR: emit_insn_ar(s, ARG, i, args[i].type, EJIT_GPR(args[i].r)); break; - case EJIT_OPERAND_FPR: emit_insn_af(s, ARG_F, i, args[i].type, EJIT_FPR(args[i].r)); break; - case EJIT_OPERAND_IMM: emit_insn_ai(s, ARG_I, i, args[i].type, args[i].r); break; - case EJIT_OPERAND_FLT: emit_insn_ad(s, ARG_FI, i, args[i].type, args[i].d); break; + case EJIT_OPERAND_GPR: emit_insn_ar(s, EJIT_OP_ARG, i, args[i].type, EJIT_GPR(args[i].r)); break; + case EJIT_OPERAND_FPR: emit_insn_af(s, EJIT_OP_ARG_F, i, args[i].type, EJIT_FPR(args[i].r)); break; + case EJIT_OPERAND_IMM: emit_insn_ai(s, EJIT_OP_ARG_I, i, args[i].type, args[i].r); break; + case EJIT_OPERAND_FLT: emit_insn_ad(s, EJIT_OP_ARG_FI, i, args[i].type, args[i].d); break; default: abort(); } } - emit_insn_op(s, ESCAPEI_F, f); + emit_insn_op(s, EJIT_OP_ESCAPEI_F, f); } void ejit_escapei_d(struct ejit_func *s, ejit_escape_d_t f, size_t argc, @@ -590,603 +590,603 @@ void ejit_escapei_d(struct ejit_func *s, ejit_escape_d_t f, size_t argc, s->max_args = argc > s->max_args ? argc : s->max_args; for (size_t i = 0; i < argc; ++i) { switch (args[i].kind) { - case EJIT_OPERAND_GPR: emit_insn_ar(s, ARG, i, args[i].type, EJIT_GPR(args[i].r)); break; - case EJIT_OPERAND_FPR: emit_insn_af(s, ARG_F, i, args[i].type, EJIT_FPR(args[i].r)); break; - case EJIT_OPERAND_IMM: emit_insn_ai(s, ARG_I, i, args[i].type, args[i].r); break; - case EJIT_OPERAND_FLT: emit_insn_ad(s, ARG_FI, i, args[i].type, args[i].d); break; + case EJIT_OPERAND_GPR: emit_insn_ar(s, EJIT_OP_ARG, i, args[i].type, EJIT_GPR(args[i].r)); break; + case EJIT_OPERAND_FPR: emit_insn_af(s, EJIT_OP_ARG_F, i, args[i].type, EJIT_FPR(args[i].r)); break; + case EJIT_OPERAND_IMM: emit_insn_ai(s, EJIT_OP_ARG_I, i, args[i].type, args[i].r); break; + case EJIT_OPERAND_FLT: emit_insn_ad(s, EJIT_OP_ARG_FI, i, args[i].type, args[i].d); break; default: abort(); } } - emit_insn_op(s, ESCAPEI_D, f); + emit_insn_op(s, EJIT_OP_ESCAPEI_D, f); } void ejit_retval(struct ejit_func *s, struct ejit_gpr r0) { - emit_insn_or(s, RETVAL, r0); + emit_insn_or(s, EJIT_OP_RETVAL, r0); } void ejit_retval_f(struct ejit_func *s, struct ejit_fpr f0) { - emit_insn_of(s, RETVAL_F, f0); + emit_insn_of(s, EJIT_OP_RETVAL_F, f0); } void ejit_retval_d(struct ejit_func *s, struct ejit_fpr f0) { - emit_insn_of(s, RETVAL_D, f0); + emit_insn_of(s, EJIT_OP_RETVAL_D, f0); } void ejit_sti_8(struct ejit_func *s, struct ejit_gpr r0, void *p) { - emit_insn_orp(s, STI8, r0, p); + emit_insn_orp(s, EJIT_OP_STI8, r0, p); } void ejit_sti_16(struct ejit_func *s, struct ejit_gpr r0, void *p) { - emit_insn_orp(s, STI16, r0, p); + emit_insn_orp(s, EJIT_OP_STI16, r0, p); } void ejit_sti_32(struct ejit_func *s, struct ejit_gpr r0, void *p) { - emit_insn_orp(s, STI32, r0, p); + emit_insn_orp(s, EJIT_OP_STI32, r0, p); } void ejit_sti_64(struct ejit_func *s, struct ejit_gpr r0, void *p) { s->use_64 = true; - emit_insn_orp(s, STI64, r0, p); + emit_insn_orp(s, EJIT_OP_STI64, r0, p); } void ejit_sti_f(struct ejit_func *s, struct ejit_fpr f0, void *p) { - emit_insn_ofp(s, STIF, f0, p); + emit_insn_ofp(s, EJIT_OP_STIF, f0, p); } void ejit_sti_d(struct ejit_func *s, struct ejit_fpr f0, void *p) { - emit_insn_ofp(s, STID, f0, p); + emit_insn_ofp(s, EJIT_OP_STID, f0, p); } void ejit_stxi_8(struct ejit_func *s, struct ejit_gpr r0, struct ejit_gpr r1, int64_t o) { - emit_insn_orri(s, STXI8, r0, r1, o); + emit_insn_orri(s, EJIT_OP_STXI8, r0, r1, o); } void ejit_stxi_16(struct ejit_func *s, struct ejit_gpr r0, struct ejit_gpr r1, int64_t o) { - emit_insn_orri(s, STXI16, r0, r1, o); + emit_insn_orri(s, EJIT_OP_STXI16, r0, r1, o); } void ejit_stxi_32(struct ejit_func *s, struct ejit_gpr r0, struct ejit_gpr r1, int64_t o) { - emit_insn_orri(s, STXI32, r0, r1, o); + emit_insn_orri(s, EJIT_OP_STXI32, r0, r1, o); } void ejit_stxi_64(struct ejit_func *s, struct ejit_gpr r0, struct ejit_gpr r1, int64_t o) { s->use_64 = true; - emit_insn_orri(s, STXI64, r0, r1, o); + emit_insn_orri(s, EJIT_OP_STXI64, r0, r1, o); } void ejit_stxi_f(struct ejit_func *s, struct ejit_fpr f0, struct ejit_gpr r1, int64_t o) { - emit_insn_ofri(s, STXIF, f0, r1, o); + emit_insn_ofri(s, EJIT_OP_STXIF, f0, r1, o); } void ejit_stxi_d(struct ejit_func *s, struct ejit_fpr f0, struct ejit_gpr r1, int64_t o) { - emit_insn_ofri(s, STXID, f0, r1, o); + emit_insn_ofri(s, EJIT_OP_STXID, f0, r1, o); } void ejit_stxr_8(struct ejit_func *s, struct ejit_gpr r0, struct ejit_gpr r1, struct ejit_gpr r2) { - emit_insn_orrr(s, STXR8, r0, r1, r2); + emit_insn_orrr(s, EJIT_OP_STXR8, r0, r1, r2); } void ejit_stxr_16(struct ejit_func *s, struct ejit_gpr r0, struct ejit_gpr r1, struct ejit_gpr r2) { - emit_insn_orrr(s, STXR16, r0, r1, r2); + emit_insn_orrr(s, EJIT_OP_STXR16, r0, r1, r2); } void ejit_stxr_32(struct ejit_func *s, struct ejit_gpr r0, struct ejit_gpr r1, struct ejit_gpr r2) { - emit_insn_orrr(s, STXR32, r0, r1, r2); + emit_insn_orrr(s, EJIT_OP_STXR32, r0, r1, r2); } void ejit_stxr_64(struct ejit_func *s, struct ejit_gpr r0, struct ejit_gpr r1, struct ejit_gpr r2) { s->use_64 = true; - emit_insn_orrr(s, STXR64, r0, r1, r2); + emit_insn_orrr(s, EJIT_OP_STXR64, r0, r1, r2); } void ejit_stxr_f(struct ejit_func *s, struct ejit_fpr f0, struct ejit_gpr r1, struct ejit_gpr r2) { - emit_insn_ofrr(s, STXRF, f0, r1, r2); + emit_insn_ofrr(s, EJIT_OP_STXRF, f0, r1, r2); } void ejit_stxr_d(struct ejit_func *s, struct ejit_fpr f0, struct ejit_gpr r1, struct ejit_gpr r2) { - emit_insn_ofrr(s, STXRD, f0, r1, r2); + emit_insn_ofrr(s, EJIT_OP_STXRD, f0, r1, r2); } void ejit_ldi_i8(struct ejit_func *s, struct ejit_gpr r0, void *p) { - emit_insn_orp(s, LDI8, r0, p); + emit_insn_orp(s, EJIT_OP_LDI8, r0, p); } void ejit_ldi_i16(struct ejit_func *s, struct ejit_gpr r0, void *p) { - emit_insn_orp(s, LDI16, r0, p); + emit_insn_orp(s, EJIT_OP_LDI16, r0, p); } void ejit_ldi_i32(struct ejit_func *s, struct ejit_gpr r0, void *p) { - emit_insn_orp(s, LDI32, r0, p); + emit_insn_orp(s, EJIT_OP_LDI32, r0, p); } void ejit_ldi_i64(struct ejit_func *s, struct ejit_gpr r0, void *p) { - emit_insn_orp(s, LDI64, r0, p); + emit_insn_orp(s, EJIT_OP_LDI64, r0, p); } void ejit_ldi_u8(struct ejit_func *s, struct ejit_gpr r0, void *p) { - emit_insn_orp(s, LDIU8, r0, p); + emit_insn_orp(s, EJIT_OP_LDIU8, r0, p); } void ejit_ldi_u16(struct ejit_func *s, struct ejit_gpr r0, void *p) { - emit_insn_orp(s, LDIU16, r0, p); + emit_insn_orp(s, EJIT_OP_LDIU16, r0, p); } void ejit_ldi_u32(struct ejit_func *s, struct ejit_gpr r0, void *p) { s->use_64 = true; - emit_insn_orp(s, LDIU32, r0, p); + emit_insn_orp(s, EJIT_OP_LDIU32, r0, p); } void ejit_ldi_u64(struct ejit_func *s, struct ejit_gpr r0, void *p) { s->use_64 = true; - emit_insn_orp(s, LDIU64, r0, p); + emit_insn_orp(s, EJIT_OP_LDIU64, r0, p); } void ejit_ldi_f(struct ejit_func *s, struct ejit_fpr f0, void *p) { - emit_insn_ofp(s, LDIF, f0, p); + emit_insn_ofp(s, EJIT_OP_LDIF, f0, p); } void ejit_ldi_d(struct ejit_func *s, struct ejit_fpr f0, void *p) { - emit_insn_ofp(s, LDID, f0, p); + emit_insn_ofp(s, EJIT_OP_LDID, f0, p); } void ejit_ldxi_i8(struct ejit_func *s, struct ejit_gpr r0, struct ejit_gpr r1, int64_t o) { - emit_insn_orri(s, LDXI8, r0, r1, o); + emit_insn_orri(s, EJIT_OP_LDXI8, r0, r1, o); } void ejit_ldxi_i16(struct ejit_func *s, struct ejit_gpr r0, struct ejit_gpr r1, int64_t o) { - emit_insn_orri(s, LDXI16, r0, r1, o); + emit_insn_orri(s, EJIT_OP_LDXI16, r0, r1, o); } void ejit_ldxi_i32(struct ejit_func *s, struct ejit_gpr r0, struct ejit_gpr r1, int64_t o) { - emit_insn_orri(s, LDXI32, r0, r1, o); + emit_insn_orri(s, EJIT_OP_LDXI32, r0, r1, o); } void ejit_ldxi_i64(struct ejit_func *s, struct ejit_gpr r0, struct ejit_gpr r1, int64_t o) { - emit_insn_orri(s, LDXI64, r0, r1, o); + emit_insn_orri(s, EJIT_OP_LDXI64, r0, r1, o); } void ejit_ldxi_u8(struct ejit_func *s, struct ejit_gpr r0, struct ejit_gpr r1, int64_t o) { - emit_insn_orri(s, LDXIU8, r0, r1, o); + emit_insn_orri(s, EJIT_OP_LDXIU8, r0, r1, o); } void ejit_ldxi_u16(struct ejit_func *s, struct ejit_gpr r0, struct ejit_gpr r1, int64_t o) { - emit_insn_orri(s, LDXIU16, r0, r1, o); + emit_insn_orri(s, EJIT_OP_LDXIU16, r0, r1, o); } void ejit_ldxi_u32(struct ejit_func *s, struct ejit_gpr r0, struct ejit_gpr r1, int64_t o) { - emit_insn_orri(s, LDXIU32, r0, r1, o); + emit_insn_orri(s, EJIT_OP_LDXIU32, r0, r1, o); } void ejit_ldxi_u64(struct ejit_func *s, struct ejit_gpr r0, struct ejit_gpr r1, int64_t o) { - emit_insn_orri(s, LDXIU64, r0, r1, o); + emit_insn_orri(s, EJIT_OP_LDXIU64, r0, r1, o); } void ejit_ldxi_f(struct ejit_func *s, struct ejit_fpr f0, struct ejit_gpr r1, int64_t o) { - emit_insn_ofri(s, LDXIF, f0, r1, o); + emit_insn_ofri(s, EJIT_OP_LDXIF, f0, r1, o); } void ejit_ldxi_d(struct ejit_func *s, struct ejit_fpr f0, struct ejit_gpr r1, int64_t o) { - emit_insn_ofri(s, LDXID, f0, r1, o); + emit_insn_ofri(s, EJIT_OP_LDXID, f0, r1, o); } void ejit_ldxr_i8(struct ejit_func *s, struct ejit_gpr r0, struct ejit_gpr r1, struct ejit_gpr r2) { - emit_insn_orrr(s, LDXR8, r0, r1, r2); + emit_insn_orrr(s, EJIT_OP_LDXR8, r0, r1, r2); } void ejit_ldxr_i16(struct ejit_func *s, struct ejit_gpr r0, struct ejit_gpr r1, struct ejit_gpr r2) { - emit_insn_orrr(s, LDXR16, r0, r1, r2); + emit_insn_orrr(s, EJIT_OP_LDXR16, r0, r1, r2); } void ejit_ldxr_i32(struct ejit_func *s, struct ejit_gpr r0, struct ejit_gpr r1, struct ejit_gpr r2) { - emit_insn_orrr(s, LDXR32, r0, r1, r2); + emit_insn_orrr(s, EJIT_OP_LDXR32, r0, r1, r2); } void ejit_ldxr_i64(struct ejit_func *s, struct ejit_gpr r0, struct ejit_gpr r1, struct ejit_gpr r2) { - emit_insn_orrr(s, LDXR64, r0, r1, r2); + emit_insn_orrr(s, EJIT_OP_LDXR64, r0, r1, r2); } void ejit_ldxr_u8(struct ejit_func *s, struct ejit_gpr r0, struct ejit_gpr r1, struct ejit_gpr r2) { - emit_insn_orrr(s, LDXRU8, r0, r1, r2); + emit_insn_orrr(s, EJIT_OP_LDXRU8, r0, r1, r2); } void ejit_ldxr_u16(struct ejit_func *s, struct ejit_gpr r0, struct ejit_gpr r1, struct ejit_gpr r2) { - emit_insn_orrr(s, LDXRU16, r0, r1, r2); + emit_insn_orrr(s, EJIT_OP_LDXRU16, r0, r1, r2); } void ejit_ldxr_u32(struct ejit_func *s, struct ejit_gpr r0, struct ejit_gpr r1, struct ejit_gpr r2) { - emit_insn_orrr(s, LDXRU32, r0, r1, r2); + emit_insn_orrr(s, EJIT_OP_LDXRU32, r0, r1, r2); } void ejit_ldxr_u64(struct ejit_func *s, struct ejit_gpr r0, struct ejit_gpr r1, struct ejit_gpr r2) { - emit_insn_orrr(s, LDXIU64, r0, r1, r2); + emit_insn_orrr(s, EJIT_OP_LDXIU64, r0, r1, r2); } void ejit_ldxr_f(struct ejit_func *s, struct ejit_fpr f0, struct ejit_gpr r1, struct ejit_gpr r2) { - emit_insn_ofrr(s, LDXRF, f0, r1, r2); + emit_insn_ofrr(s, EJIT_OP_LDXRF, f0, r1, r2); } void ejit_ldxr_d(struct ejit_func *s, struct ejit_fpr f0, struct ejit_gpr r1, struct ejit_gpr r2) { - emit_insn_ofrr(s, LDXRD, f0, r1, r2); + emit_insn_ofrr(s, EJIT_OP_LDXRD, f0, r1, r2); } void ejit_ret(struct ejit_func *s) { - emit_insn_o(s, END); + emit_insn_o(s, EJIT_OP_END); } void ejit_retr(struct ejit_func *s, struct ejit_gpr r0) { - emit_insn_oxr(s, RETR, r0); + emit_insn_oxr(s, EJIT_OP_RETR, r0); } void ejit_retr_f(struct ejit_func *s, struct ejit_fpr f0) { - emit_insn_oxf(s, RETR_F, f0); + emit_insn_oxf(s, EJIT_OP_RETR_F, f0); } void ejit_retr_d(struct ejit_func *s, struct ejit_fpr f0) { - emit_insn_oxf(s, RETR_D, f0); + emit_insn_oxf(s, EJIT_OP_RETR_D, f0); } void ejit_reti(struct ejit_func *s, int64_t i) { - emit_insn_oi(s, RETI, i); + emit_insn_oi(s, EJIT_OP_RETI, i); } void ejit_reti_f(struct ejit_func *s, float f) { - emit_insn_oF(s, RETI_F, f); + emit_insn_oF(s, EJIT_OP_RETI_F, f); } void ejit_reti_d(struct ejit_func *s, double f) { - emit_insn_oD(s, RETI_D, f); + emit_insn_oD(s, EJIT_OP_RETI_D, f); } void ejit_extr_8(struct ejit_func *s, struct ejit_gpr r0, struct ejit_gpr r1) { - emit_insn_orr(s, EXTR8, r0, r1); + emit_insn_orr(s, EJIT_OP_EXTR8, r0, r1); } void ejit_extr_16(struct ejit_func *s, struct ejit_gpr r0, struct ejit_gpr r1) { - emit_insn_orr(s, EXTR16, r0, r1); + emit_insn_orr(s, EJIT_OP_EXTR16, r0, r1); } void ejit_extr_32(struct ejit_func *s, struct ejit_gpr r0, struct ejit_gpr r1) { s->use_64 = true; - emit_insn_orr(s, EXTR32, r0, r1); + emit_insn_orr(s, EJIT_OP_EXTR32, r0, r1); } void ejit_extr_u8(struct ejit_func *s, struct ejit_gpr r0, struct ejit_gpr r1) { - emit_insn_orr(s, EXTRU8, r0, r1); + emit_insn_orr(s, EJIT_OP_EXTRU8, r0, r1); } void ejit_extr_u16(struct ejit_func *s, struct ejit_gpr r0, struct ejit_gpr r1) { - emit_insn_orr(s, EXTRU16, r0, r1); + emit_insn_orr(s, EJIT_OP_EXTRU16, r0, r1); } void ejit_extr_u32(struct ejit_func *s, struct ejit_gpr r0, struct ejit_gpr r1) { s->use_64 = true; - emit_insn_orr(s, EXTRU32, r0, r1); + emit_insn_orr(s, EJIT_OP_EXTRU32, r0, r1); } void ejit_extr_f(struct ejit_func *s, struct ejit_fpr f0, struct ejit_gpr r1) { - emit_insn_ofr(s, EXTRF, f0, r1); + emit_insn_ofr(s, EJIT_OP_EXTRF, f0, r1); } void ejit_extr_d(struct ejit_func *s, struct ejit_fpr f0, struct ejit_gpr r1) { - emit_insn_ofr(s, EXTRD, f0, r1); + emit_insn_ofr(s, EJIT_OP_EXTRD, f0, r1); } void ejit_addr(struct ejit_func *s, struct ejit_gpr r0, struct ejit_gpr r1, struct ejit_gpr r2) { - emit_insn_orrr(s, ADDR, r0, r1, r2); + emit_insn_orrr(s, EJIT_OP_ADDR, r0, r1, r2); } void ejit_addr_f(struct ejit_func *s, struct ejit_fpr f0, struct ejit_fpr f1, struct ejit_fpr f2) { - emit_insn_offf(s, ADDR_F, f0, f1, f2); + emit_insn_offf(s, EJIT_OP_ADDR_F, f0, f1, f2); } void ejit_addr_d(struct ejit_func *s, struct ejit_fpr f0, struct ejit_fpr f1, struct ejit_fpr f2) { - emit_insn_offf(s, ADDR_D, f0, f1, f2); + emit_insn_offf(s, EJIT_OP_ADDR_D, f0, f1, f2); } void ejit_addi(struct ejit_func *s, struct ejit_gpr r0, struct ejit_gpr r1, int64_t o) { - emit_insn_orri(s, ADDI, r0, r1, o); + emit_insn_orri(s, EJIT_OP_ADDI, r0, r1, o); } void ejit_absr_f(struct ejit_func *s, struct ejit_fpr f0, struct ejit_fpr f1) { - emit_insn_off(s, ABSR_F, f0, f1); + emit_insn_off(s, EJIT_OP_ABSR_F, f0, f1); } void ejit_absr_d(struct ejit_func *s, struct ejit_fpr f0, struct ejit_fpr f1) { - emit_insn_off(s, ABSR_D, f0, f1); + emit_insn_off(s, EJIT_OP_ABSR_D, f0, f1); } void ejit_subr(struct ejit_func *s, struct ejit_gpr r0, struct ejit_gpr r1, struct ejit_gpr r2) { - emit_insn_orrr(s, SUBR, r0, r1, r2); + emit_insn_orrr(s, EJIT_OP_SUBR, r0, r1, r2); } void ejit_subr_f(struct ejit_func *s, struct ejit_fpr f0, struct ejit_fpr f1, struct ejit_fpr f2) { - emit_insn_offf(s, SUBR_F, f0, f1, f2); + emit_insn_offf(s, EJIT_OP_SUBR_F, f0, f1, f2); } void ejit_subr_d(struct ejit_func *s, struct ejit_fpr f0, struct ejit_fpr f1, struct ejit_fpr f2) { - emit_insn_offf(s, SUBR_D, f0, f1, f2); + emit_insn_offf(s, EJIT_OP_SUBR_D, f0, f1, f2); } void ejit_subi(struct ejit_func *s, struct ejit_gpr r0, struct ejit_gpr r1, int64_t o) { - emit_insn_orri(s, SUBI, r0, r1, o); + emit_insn_orri(s, EJIT_OP_SUBI, r0, r1, o); } void ejit_mulr(struct ejit_func *s, struct ejit_gpr r0, struct ejit_gpr r1, struct ejit_gpr r2) { - emit_insn_orrr(s, MULR, r0, r1, r2); + emit_insn_orrr(s, EJIT_OP_MULR, r0, r1, r2); } void ejit_mulr_f(struct ejit_func *s, struct ejit_fpr f0, struct ejit_fpr f1, struct ejit_fpr f2) { - emit_insn_offf(s, MULR_F, f0, f1, f2); + emit_insn_offf(s, EJIT_OP_MULR_F, f0, f1, f2); } void ejit_mulr_d(struct ejit_func *s, struct ejit_fpr f0, struct ejit_fpr f1, struct ejit_fpr f2) { - emit_insn_offf(s, MULR_D, f0, f1, f2); + emit_insn_offf(s, EJIT_OP_MULR_D, f0, f1, f2); } void ejit_divr(struct ejit_func *s, struct ejit_gpr r0, struct ejit_gpr r1, struct ejit_gpr r2) { - emit_insn_orrr(s, DIVR, r0, r1, r2); + emit_insn_orrr(s, EJIT_OP_DIVR, r0, r1, r2); } void ejit_divr_u(struct ejit_func *s, struct ejit_gpr r0, struct ejit_gpr r1, struct ejit_gpr r2) { - emit_insn_orrr(s, DIVR_U, r0, r1, r2); + emit_insn_orrr(s, EJIT_OP_DIVR_U, r0, r1, r2); } void ejit_divr_f(struct ejit_func *s, struct ejit_fpr f0, struct ejit_fpr f1, struct ejit_fpr f2) { - emit_insn_offf(s, DIVR_F, f0, f1, f2); + emit_insn_offf(s, EJIT_OP_DIVR_F, f0, f1, f2); } void ejit_divr_d(struct ejit_func *s, struct ejit_fpr f0, struct ejit_fpr f1, struct ejit_fpr f2) { - emit_insn_offf(s, DIVR_D, f0, f1, f2); + emit_insn_offf(s, EJIT_OP_DIVR_D, f0, f1, f2); } void ejit_remr(struct ejit_func *s, struct ejit_gpr r0, struct ejit_gpr r1, struct ejit_gpr r2) { - emit_insn_orrr(s, REMR, r0, r1, r2); + emit_insn_orrr(s, EJIT_OP_REMR, r0, r1, r2); } void ejit_remr_u(struct ejit_func *s, struct ejit_gpr r0, struct ejit_gpr r1, struct ejit_gpr r2) { - emit_insn_orrr(s, REMR_U, r0, r1, r2); + emit_insn_orrr(s, EJIT_OP_REMR_U, r0, r1, r2); } void ejit_lshi(struct ejit_func *s, struct ejit_gpr r0, struct ejit_gpr r1, int64_t o) { - emit_insn_orri(s, LSHI, r0, r1, o); + emit_insn_orri(s, EJIT_OP_LSHI, r0, r1, o); } void ejit_lshr(struct ejit_func *s, struct ejit_gpr r0, struct ejit_gpr r1, struct ejit_gpr r2) { - emit_insn_orrr(s, LSHR, r0, r1, r2); + emit_insn_orrr(s, EJIT_OP_LSHR, r0, r1, r2); } void ejit_rshi(struct ejit_func *s, struct ejit_gpr r0, struct ejit_gpr r1, int64_t o) { - emit_insn_orri(s, RSHI, r0, r1, o); + emit_insn_orri(s, EJIT_OP_RSHI, r0, r1, o); } void ejit_rshi_u(struct ejit_func *s, struct ejit_gpr r0, struct ejit_gpr r1, int64_t o) { - emit_insn_orri(s, RSHI_U, r0, r1, o); + emit_insn_orri(s, EJIT_OP_RSHI_U, r0, r1, o); } void ejit_rshr(struct ejit_func *s, struct ejit_gpr r0, struct ejit_gpr r1, struct ejit_gpr r2) { - emit_insn_orrr(s, RSHR, r0, r1, r2); + emit_insn_orrr(s, EJIT_OP_RSHR, r0, r1, r2); } void ejit_rshr_u(struct ejit_func *s, struct ejit_gpr r0, struct ejit_gpr r1, struct ejit_gpr r2) { - emit_insn_orrr(s, RSHR_U, r0, r1, r2); + emit_insn_orrr(s, EJIT_OP_RSHR_U, r0, r1, r2); } void ejit_andr(struct ejit_func *s, struct ejit_gpr r0, struct ejit_gpr r1, struct ejit_gpr r2) { - emit_insn_orrr(s, ANDR, r0, r1, r2); + emit_insn_orrr(s, EJIT_OP_ANDR, r0, r1, r2); } void ejit_andi(struct ejit_func *s, struct ejit_gpr r0, struct ejit_gpr r1, int64_t o) { - emit_insn_orri(s, ANDI, r0, r1, o); + emit_insn_orri(s, EJIT_OP_ANDI, r0, r1, o); } void ejit_orr(struct ejit_func *s, struct ejit_gpr r0, struct ejit_gpr r1, struct ejit_gpr r2) { - emit_insn_orrr(s, ORR, r0, r1, r2); + emit_insn_orrr(s, EJIT_OP_ORR, r0, r1, r2); } void ejit_ori(struct ejit_func *s, struct ejit_gpr r0, struct ejit_gpr r1, int64_t o) { - emit_insn_orri(s, ORI, r0, r1, o); + emit_insn_orri(s, EJIT_OP_ORI, r0, r1, o); } void ejit_xorr(struct ejit_func *s, struct ejit_gpr r0, struct ejit_gpr r1, struct ejit_gpr r2) { - emit_insn_orrr(s, XORR, r0, r1, r2); + emit_insn_orrr(s, EJIT_OP_XORR, r0, r1, r2); } void ejit_xori(struct ejit_func *s, struct ejit_gpr r0, struct ejit_gpr r1, int64_t o) { - emit_insn_orri(s, XORI, r0, r1, o); + emit_insn_orri(s, EJIT_OP_XORI, r0, r1, o); } void ejit_comr(struct ejit_func *s, struct ejit_gpr r0, struct ejit_gpr r1) { - emit_insn_orr(s, COMR, r0, r1); + emit_insn_orr(s, EJIT_OP_COMR, r0, r1); } void ejit_negr(struct ejit_func *s, struct ejit_gpr r0, struct ejit_gpr r1) { - emit_insn_orr(s, NEGR, r0, r1); + emit_insn_orr(s, EJIT_OP_NEGR, r0, r1); } void ejit_negr_f(struct ejit_func *s, struct ejit_fpr f0, struct ejit_fpr f1) { - emit_insn_off(s, NEGR_F, f0, f1); + emit_insn_off(s, EJIT_OP_NEGR_F, f0, f1); } void ejit_negr_d(struct ejit_func *s, struct ejit_fpr f0, struct ejit_fpr f1) { - emit_insn_off(s, NEGR_D, f0, f1); + emit_insn_off(s, EJIT_OP_NEGR_D, f0, f1); } void ejit_movi(struct ejit_func *s, struct ejit_gpr r0, int64_t o) { - emit_insn_ori(s, MOVI, r0, o); + emit_insn_ori(s, EJIT_OP_MOVI, r0, o); } void ejit_movi_f(struct ejit_func *s, struct ejit_fpr f0, float o) { - emit_insn_ofF(s, MOVI_F, f0, o); + emit_insn_ofF(s, EJIT_OP_MOVI_F, f0, o); } void ejit_movi_d(struct ejit_func *s, struct ejit_fpr f0, double o) { - emit_insn_ofD(s, MOVI_D, f0, o); + emit_insn_ofD(s, EJIT_OP_MOVI_D, f0, o); } void ejit_movr(struct ejit_func *s, struct ejit_gpr r0, struct ejit_gpr r1) @@ -1194,7 +1194,7 @@ void ejit_movr(struct ejit_func *s, struct ejit_gpr r0, struct ejit_gpr r1) if (r0.r == r1.r) return; - emit_insn_orr(s, MOVR, r0, r1); + emit_insn_orr(s, EJIT_OP_MOVR, r0, r1); } void ejit_movr_f(struct ejit_func *s, struct ejit_fpr f0, struct ejit_fpr f1) @@ -1202,7 +1202,7 @@ void ejit_movr_f(struct ejit_func *s, struct ejit_fpr f0, struct ejit_fpr f1) if (f0.f == f1.f) return; - emit_insn_off(s, MOVR_F, f0, f1); + emit_insn_off(s, EJIT_OP_MOVR_F, f0, f1); } void ejit_movr_d(struct ejit_func *s, struct ejit_fpr f0, struct ejit_fpr f1) @@ -1210,179 +1210,179 @@ void ejit_movr_d(struct ejit_func *s, struct ejit_fpr f0, struct ejit_fpr f1) if (f0.f == f1.f) return; - emit_insn_off(s, MOVR_D, f0, f1); + emit_insn_off(s, EJIT_OP_MOVR_D, f0, f1); } void ejit_eqr(struct ejit_func *s, struct ejit_gpr r0, struct ejit_gpr r1, struct ejit_gpr r2) { - emit_insn_orrr(s, EQR, r0, r1, r2); + emit_insn_orrr(s, EJIT_OP_EQR, r0, r1, r2); } void ejit_eqr_f(struct ejit_func *s, struct ejit_gpr r0, struct ejit_fpr f1, struct ejit_fpr f2) { - emit_insn_orff(s, EQR_F, r0, f1, f2); + emit_insn_orff(s, EJIT_OP_EQR_F, r0, f1, f2); } void ejit_eqr_d(struct ejit_func *s, struct ejit_gpr r0, struct ejit_fpr f1, struct ejit_fpr f2) { - emit_insn_orff(s, EQR_D, r0, f1, f2); + emit_insn_orff(s, EJIT_OP_EQR_D, r0, f1, f2); } void ejit_ner(struct ejit_func *s, struct ejit_gpr r0, struct ejit_gpr r1, struct ejit_gpr r2) { - emit_insn_orrr(s, NER, r0, r1, r2); + emit_insn_orrr(s, EJIT_OP_NER, r0, r1, r2); } void ejit_ner_f(struct ejit_func *s, struct ejit_gpr r0, struct ejit_fpr f1, struct ejit_fpr f2) { - emit_insn_orff(s, NER_F, r0, f1, f2); + emit_insn_orff(s, EJIT_OP_NER_F, r0, f1, f2); } void ejit_ner_d(struct ejit_func *s, struct ejit_gpr r0, struct ejit_fpr f1, struct ejit_fpr f2) { - emit_insn_orff(s, NER_D, r0, f1, f2); + emit_insn_orff(s, EJIT_OP_NER_D, r0, f1, f2); } void ejit_gtr(struct ejit_func *s, struct ejit_gpr r0, struct ejit_gpr r1, struct ejit_gpr r2) { - emit_insn_orrr(s, GTR, r0, r1, r2); + emit_insn_orrr(s, EJIT_OP_GTR, r0, r1, r2); } void ejit_gtr_u(struct ejit_func *s, struct ejit_gpr r0, struct ejit_gpr r1, struct ejit_gpr r2) { - emit_insn_orrr(s, GTR_U, r0, r1, r2); + emit_insn_orrr(s, EJIT_OP_GTR_U, r0, r1, r2); } void ejit_gtr_f(struct ejit_func *s, struct ejit_gpr r0, struct ejit_fpr f1, struct ejit_fpr f2) { - emit_insn_orff(s, GTR_F, r0, f1, f2); + emit_insn_orff(s, EJIT_OP_GTR_F, r0, f1, f2); } void ejit_gtr_d(struct ejit_func *s, struct ejit_gpr r0, struct ejit_fpr f1, struct ejit_fpr f2) { - emit_insn_orff(s, GTR_D, r0, f1, f2); + emit_insn_orff(s, EJIT_OP_GTR_D, r0, f1, f2); } void ejit_ltr(struct ejit_func *s, struct ejit_gpr r0, struct ejit_gpr r1, struct ejit_gpr r2) { - emit_insn_orrr(s, GTR, r0, r2, r1); + emit_insn_orrr(s, EJIT_OP_GTR, r0, r2, r1); } void ejit_ltr_u(struct ejit_func *s, struct ejit_gpr r0, struct ejit_gpr r1, struct ejit_gpr r2) { - emit_insn_orrr(s, GTR_U, r0, r2, r1); + emit_insn_orrr(s, EJIT_OP_GTR_U, r0, r2, r1); } void ejit_ltr_f(struct ejit_func *s, struct ejit_gpr r0, struct ejit_fpr f1, struct ejit_fpr f2) { - emit_insn_orff(s, GTR_F, r0, f2, f1); + emit_insn_orff(s, EJIT_OP_GTR_F, r0, f2, f1); } void ejit_ltr_d(struct ejit_func *s, struct ejit_gpr r0, struct ejit_fpr f1, struct ejit_fpr f2) { - emit_insn_orff(s, GTR_D, r0, f2, f1); + emit_insn_orff(s, EJIT_OP_GTR_D, r0, f2, f1); } void ejit_ger(struct ejit_func *s, struct ejit_gpr r0, struct ejit_gpr r1, struct ejit_gpr r2) { - emit_insn_orrr(s, GER, r0, r1, r2); + emit_insn_orrr(s, EJIT_OP_GER, r0, r1, r2); } void ejit_ger_u(struct ejit_func *s, struct ejit_gpr r0, struct ejit_gpr r1, struct ejit_gpr r2) { - emit_insn_orrr(s, GER_U, r0, r1, r2); + emit_insn_orrr(s, EJIT_OP_GER_U, r0, r1, r2); } void ejit_ger_f(struct ejit_func *s, struct ejit_gpr r0, struct ejit_fpr f1, struct ejit_fpr f2) { - emit_insn_orff(s, GER_F, r0, f1, f2); + emit_insn_orff(s, EJIT_OP_GER_F, r0, f1, f2); } void ejit_ger_d(struct ejit_func *s, struct ejit_gpr r0, struct ejit_fpr f1, struct ejit_fpr f2) { - emit_insn_orff(s, GER_D, r0, f1, f2); + emit_insn_orff(s, EJIT_OP_GER_D, r0, f1, f2); } void ejit_ler(struct ejit_func *s, struct ejit_gpr r0, struct ejit_gpr r1, struct ejit_gpr r2) { - emit_insn_orrr(s, GER, r0, r2, r1); + emit_insn_orrr(s, EJIT_OP_GER, r0, r2, r1); } void ejit_ler_u(struct ejit_func *s, struct ejit_gpr r0, struct ejit_gpr r1, struct ejit_gpr r2) { - emit_insn_orrr(s, GER_U, r0, r2, r1); + emit_insn_orrr(s, EJIT_OP_GER_U, r0, r2, r1); } void ejit_ler_f(struct ejit_func *s, struct ejit_gpr r0, struct ejit_fpr f1, struct ejit_fpr f2) { - emit_insn_orff(s, GER_F, r0, f2, f1); + emit_insn_orff(s, EJIT_OP_GER_F, r0, f2, f1); } void ejit_ler_d(struct ejit_func *s, struct ejit_gpr r0, struct ejit_fpr f1, struct ejit_fpr f2) { - emit_insn_orff(s, GER_D, r0, f2, f1); + emit_insn_orff(s, EJIT_OP_GER_D, r0, f2, f1); } void ejit_truncr_d_32(struct ejit_func *s, struct ejit_gpr r0, struct ejit_fpr f1) { - emit_insn_orf(s, TRUNCR_D_32, r0, f1); + emit_insn_orf(s, EJIT_OP_TRUNCR_D_32, r0, f1); } void ejit_truncr_d_64(struct ejit_func *s, struct ejit_gpr r0, struct ejit_fpr f1) { s->use_64 = true; - emit_insn_orf(s, TRUNCR_D_64, r0, f1); + emit_insn_orf(s, EJIT_OP_TRUNCR_D_64, r0, f1); } void ejit_truncr_f_32(struct ejit_func *s, struct ejit_gpr r0, struct ejit_fpr f1) { - emit_insn_orf(s, TRUNCR_F_32, r0, f1); + emit_insn_orf(s, EJIT_OP_TRUNCR_F_32, r0, f1); } void ejit_truncr_f_64(struct ejit_func *s, struct ejit_gpr r0, struct ejit_fpr f1) { s->use_64 = true; - emit_insn_orf(s, TRUNCR_F_64, r0, f1); + emit_insn_orf(s, EJIT_OP_TRUNCR_F_64, r0, f1); } struct ejit_reloc ejit_bner(struct ejit_func *s, struct ejit_gpr r0, struct ejit_gpr r1) { size_t addr = insns_len(&s->insns); - emit_insn_oxrr(s, BNER, r0, r1); + emit_insn_oxrr(s, EJIT_OP_BNER, r0, r1); return (struct ejit_reloc){.insn = addr}; } struct ejit_reloc ejit_bnei(struct ejit_func *s, struct ejit_gpr r0, int64_t o) { size_t addr = insns_len(&s->insns); - emit_insn_oxri(s, BNEI, r0, o); + emit_insn_oxri(s, EJIT_OP_BNEI, r0, o); return (struct ejit_reloc){.insn = addr}; } @@ -1390,7 +1390,7 @@ struct ejit_reloc ejit_bner_f(struct ejit_func *s, struct ejit_fpr f0, struct ejit_fpr f1) { size_t addr = insns_len(&s->insns); - emit_insn_oxff(s, BNER_F, f0, f1); + emit_insn_oxff(s, EJIT_OP_BNER_F, f0, f1); return (struct ejit_reloc){.insn = addr}; } @@ -1398,7 +1398,7 @@ struct ejit_reloc ejit_bner_d(struct ejit_func *s, struct ejit_fpr f0, struct ejit_fpr f1) { size_t addr = insns_len(&s->insns); - emit_insn_oxff(s, BNER_D, f0, f1); + emit_insn_oxff(s, EJIT_OP_BNER_D, f0, f1); return (struct ejit_reloc){.insn = addr}; } @@ -1406,14 +1406,14 @@ struct ejit_reloc ejit_beqr(struct ejit_func *s, struct ejit_gpr r0, struct ejit_gpr r1) { size_t addr = insns_len(&s->insns); - emit_insn_oxrr(s, BEQR, r0, r1); + emit_insn_oxrr(s, EJIT_OP_BEQR, r0, r1); return (struct ejit_reloc){.insn = addr}; } struct ejit_reloc ejit_beqi(struct ejit_func *s, struct ejit_gpr r0, int64_t o) { size_t addr = insns_len(&s->insns); - emit_insn_oxri(s, BEQI, r0, o); + emit_insn_oxri(s, EJIT_OP_BEQI, r0, o); return (struct ejit_reloc){.insn = addr}; } @@ -1421,7 +1421,7 @@ struct ejit_reloc ejit_beqr_f(struct ejit_func *s, struct ejit_fpr f0, struct ejit_fpr f1) { size_t addr = insns_len(&s->insns); - emit_insn_oxff(s, BEQR_F, f0, f1); + emit_insn_oxff(s, EJIT_OP_BEQR_F, f0, f1); return (struct ejit_reloc){.insn = addr}; } @@ -1429,7 +1429,7 @@ struct ejit_reloc ejit_beqr_d(struct ejit_func *s, struct ejit_fpr f0, struct ejit_fpr f1) { size_t addr = insns_len(&s->insns); - emit_insn_oxff(s, BEQR_D, f0, f1); + emit_insn_oxff(s, EJIT_OP_BEQR_D, f0, f1); return (struct ejit_reloc){.insn = addr}; } @@ -1437,7 +1437,7 @@ struct ejit_reloc ejit_bger(struct ejit_func *s, struct ejit_gpr r0, struct ejit_gpr r1) { size_t addr = insns_len(&s->insns); - emit_insn_oxrr(s, BGER, r0, r1); + emit_insn_oxrr(s, EJIT_OP_BGER, r0, r1); return (struct ejit_reloc){.insn = addr}; } @@ -1445,7 +1445,7 @@ struct ejit_reloc ejit_bger_u(struct ejit_func *s, struct ejit_gpr r0, struct ejit_gpr r1) { size_t addr = insns_len(&s->insns); - emit_insn_oxrr(s, BGER_U, r0, r1); + emit_insn_oxrr(s, EJIT_OP_BGER_U, r0, r1); return (struct ejit_reloc){.insn = addr}; } @@ -1453,7 +1453,7 @@ struct ejit_reloc ejit_bger_f(struct ejit_func *s, struct ejit_fpr f0, struct ejit_fpr f1) { size_t addr = insns_len(&s->insns); - emit_insn_oxff(s, BGER_F, f0, f1); + emit_insn_oxff(s, EJIT_OP_BGER_F, f0, f1); return (struct ejit_reloc){.insn = addr}; } @@ -1461,14 +1461,14 @@ struct ejit_reloc ejit_bger_d(struct ejit_func *s, struct ejit_fpr f0, struct ejit_fpr f1) { size_t addr = insns_len(&s->insns); - emit_insn_oxff(s, BGER_D, f0, f1); + emit_insn_oxff(s, EJIT_OP_BGER_D, f0, f1); return (struct ejit_reloc){.insn = addr}; } struct ejit_reloc ejit_bgei(struct ejit_func *s, struct ejit_gpr r0, int64_t o) { size_t addr = insns_len(&s->insns); - emit_insn_oxri(s, BGEI, r0, o); + emit_insn_oxri(s, EJIT_OP_BGEI, r0, o); return (struct ejit_reloc){.insn = addr}; } @@ -1476,7 +1476,7 @@ struct ejit_reloc ejit_bgei_u(struct ejit_func *s, struct ejit_gpr r0, int64_t o) { size_t addr = insns_len(&s->insns); - emit_insn_oxri(s, BGEI_U, r0, o); + emit_insn_oxri(s, EJIT_OP_BGEI_U, r0, o); return (struct ejit_reloc){.insn = addr}; } @@ -1484,7 +1484,7 @@ struct ejit_reloc ejit_bler(struct ejit_func *s, struct ejit_gpr r0, struct ejit_gpr r1) { size_t addr = insns_len(&s->insns); - emit_insn_oxrr(s, BGER, r1, r0); + emit_insn_oxrr(s, EJIT_OP_BGER, r1, r0); return (struct ejit_reloc){.insn = addr}; } @@ -1492,7 +1492,7 @@ struct ejit_reloc ejit_bler_u(struct ejit_func *s, struct ejit_gpr r0, struct ejit_gpr r1) { size_t addr = insns_len(&s->insns); - emit_insn_oxrr(s, BGER_U, r1, r0); + emit_insn_oxrr(s, EJIT_OP_BGER_U, r1, r0); return (struct ejit_reloc){.insn = addr}; } @@ -1500,7 +1500,7 @@ struct ejit_reloc ejit_bler_f(struct ejit_func *s, struct ejit_fpr f0, struct ejit_fpr f1) { size_t addr = insns_len(&s->insns); - emit_insn_oxff(s, BGER_F, f1, f0); + emit_insn_oxff(s, EJIT_OP_BGER_F, f1, f0); return (struct ejit_reloc){.insn = addr}; } @@ -1508,14 +1508,14 @@ struct ejit_reloc ejit_bler_d(struct ejit_func *s, struct ejit_fpr f0, struct ejit_fpr f1) { size_t addr = insns_len(&s->insns); - emit_insn_oxff(s, BGER_D, f1, f0); + emit_insn_oxff(s, EJIT_OP_BGER_D, f1, f0); return (struct ejit_reloc){.insn = addr}; } struct ejit_reloc ejit_blei(struct ejit_func *s, struct ejit_gpr r0, int64_t o) { size_t addr = insns_len(&s->insns); - emit_insn_oxri(s, BLEI, r0, o); + emit_insn_oxri(s, EJIT_OP_BLEI, r0, o); return (struct ejit_reloc){.insn = addr}; } @@ -1523,14 +1523,14 @@ struct ejit_reloc ejit_blei_u(struct ejit_func *s, struct ejit_gpr r0, int64_t o) { size_t addr = insns_len(&s->insns); - emit_insn_oxri(s, BLEI_U, r0, o); + emit_insn_oxri(s, EJIT_OP_BLEI_U, r0, o); return (struct ejit_reloc){.insn = addr}; } struct ejit_reloc ejit_bgti(struct ejit_func *s, struct ejit_gpr r0, int64_t o) { size_t addr = insns_len(&s->insns); - emit_insn_oxri(s, BGTI, r0, o); + emit_insn_oxri(s, EJIT_OP_BGTI, r0, o); return (struct ejit_reloc){.insn = addr}; } @@ -1538,7 +1538,7 @@ struct ejit_reloc ejit_bgti_u(struct ejit_func *s, struct ejit_gpr r0, int64_t o) { size_t addr = insns_len(&s->insns); - emit_insn_oxri(s, BGTI_U, r0, o); + emit_insn_oxri(s, EJIT_OP_BGTI_U, r0, o); return (struct ejit_reloc){.insn = addr}; } @@ -1546,7 +1546,7 @@ struct ejit_reloc ejit_bgtr(struct ejit_func *s, struct ejit_gpr r0, struct ejit_gpr r1) { size_t addr = insns_len(&s->insns); - emit_insn_oxrr(s, BGTR, r0, r1); + emit_insn_oxrr(s, EJIT_OP_BGTR, r0, r1); return (struct ejit_reloc){.insn = addr}; } @@ -1554,7 +1554,7 @@ struct ejit_reloc ejit_bgtr_u(struct ejit_func *s, struct ejit_gpr r0, struct ejit_gpr r1) { size_t addr = insns_len(&s->insns); - emit_insn_oxrr(s, BGTR_U, r0, r1); + emit_insn_oxrr(s, EJIT_OP_BGTR_U, r0, r1); return (struct ejit_reloc){.insn = addr}; } @@ -1562,7 +1562,7 @@ struct ejit_reloc ejit_bgtr_f(struct ejit_func *s, struct ejit_fpr f0, struct ejit_fpr f1) { size_t addr = insns_len(&s->insns); - emit_insn_oxff(s, BGTR_F, f0, f1); + emit_insn_oxff(s, EJIT_OP_BGTR_F, f0, f1); return (struct ejit_reloc){.insn = addr}; } @@ -1570,7 +1570,7 @@ struct ejit_reloc ejit_bgtr_d(struct ejit_func *s, struct ejit_fpr f0, struct ejit_fpr f1) { size_t addr = insns_len(&s->insns); - emit_insn_oxff(s, BGTR_D, f0, f1); + emit_insn_oxff(s, EJIT_OP_BGTR_D, f0, f1); return (struct ejit_reloc){.insn = addr}; } @@ -1578,7 +1578,7 @@ struct ejit_reloc ejit_bltr(struct ejit_func *s, struct ejit_gpr r0, struct ejit_gpr r1) { size_t addr = insns_len(&s->insns); - emit_insn_oxrr(s, BGTR, r1, r0); + emit_insn_oxrr(s, EJIT_OP_BGTR, r1, r0); return (struct ejit_reloc){.insn = addr}; } @@ -1586,7 +1586,7 @@ struct ejit_reloc ejit_bltr_u(struct ejit_func *s, struct ejit_gpr r0, struct ejit_gpr r1) { size_t addr = insns_len(&s->insns); - emit_insn_oxrr(s, BGTR_U, r1, r0); + emit_insn_oxrr(s, EJIT_OP_BGTR_U, r1, r0); return (struct ejit_reloc){.insn = addr}; } @@ -1594,7 +1594,7 @@ struct ejit_reloc ejit_bltr_f(struct ejit_func *s, struct ejit_fpr f0, struct ejit_fpr f1) { size_t addr = insns_len(&s->insns); - emit_insn_oxff(s, BGTR_F, f1, f0); + emit_insn_oxff(s, EJIT_OP_BGTR_F, f1, f0); return (struct ejit_reloc){.insn = addr}; } @@ -1602,14 +1602,14 @@ struct ejit_reloc ejit_bltr_d(struct ejit_func *s, struct ejit_fpr f0, struct ejit_fpr f1) { size_t addr = insns_len(&s->insns); - emit_insn_oxff(s, BGTR_D, f1, f0); + emit_insn_oxff(s, EJIT_OP_BGTR_D, f1, f0); return (struct ejit_reloc){.insn = addr}; } struct ejit_reloc ejit_blti(struct ejit_func *s, struct ejit_gpr r0, int64_t o) { size_t addr = insns_len(&s->insns); - emit_insn_oxri(s, BLTI, r0, o); + emit_insn_oxri(s, EJIT_OP_BLTI, r0, o); return (struct ejit_reloc){.insn = addr}; } @@ -1617,28 +1617,28 @@ struct ejit_reloc ejit_blti_u(struct ejit_func *s, struct ejit_gpr r0, int64_t o) { size_t addr = insns_len(&s->insns); - emit_insn_oxri(s, BLTI_U, r0, o); + emit_insn_oxri(s, EJIT_OP_BLTI_U, r0, o); return (struct ejit_reloc){.insn = addr}; } struct ejit_reloc ejit_jmp(struct ejit_func *s) { size_t addr = insns_len(&s->insns); - emit_insn_o(s, JMP); + emit_insn_o(s, EJIT_OP_JMP); return (struct ejit_reloc){.insn = addr}; } struct ejit_reloc ejit_jmpr(struct ejit_func *s, struct ejit_gpr r0) { size_t addr = insns_len(&s->insns); - emit_insn_oxr(s, JMPR, r0); + emit_insn_oxr(s, EJIT_OP_JMPR, r0); return (struct ejit_reloc){.insn = addr}; } struct ejit_reloc ejit_bmci(struct ejit_func *s, struct ejit_gpr r0, int64_t o) { size_t addr = insns_len(&s->insns); - emit_insn_oxri(s, BMCI, r0, o); + emit_insn_oxri(s, EJIT_OP_BMCI, r0, o); return (struct ejit_reloc){.insn = addr}; } @@ -1646,14 +1646,14 @@ struct ejit_reloc ejit_bmcr(struct ejit_func *s, struct ejit_gpr r0, struct ejit_gpr r1) { size_t addr = insns_len(&s->insns); - emit_insn_oxrr(s, BMCR, r0, r1); + emit_insn_oxrr(s, EJIT_OP_BMCR, r0, r1); return (struct ejit_reloc){.insn = addr}; } struct ejit_reloc ejit_bmsi(struct ejit_func *s, struct ejit_gpr r0, int64_t o) { size_t addr = insns_len(&s->insns); - emit_insn_oxri(s, BMSI, r0, o); + emit_insn_oxri(s, EJIT_OP_BMSI, r0, o); return (struct ejit_reloc){.insn = addr}; } @@ -1661,7 +1661,7 @@ struct ejit_reloc ejit_bmsr(struct ejit_func *s, struct ejit_gpr r0, struct ejit_gpr r1) { size_t addr = insns_len(&s->insns); - emit_insn_oxrr(s, BMSR, r0, r1); + emit_insn_oxrr(s, EJIT_OP_BMSR, r0, r1); return (struct ejit_reloc){.insn = addr}; } diff --git a/src/interp.c b/src/interp.c index aa40c53..b858f26 100644 --- a/src/interp.c +++ b/src/interp.c @@ -7,214 +7,214 @@ * be returned. Included from src/interp.c */ union interp_ret ejit_run(struct ejit_func *f, size_t paramc, struct ejit_arg params[paramc], bool run, void ***labels_wb) { - static void *labels[OPCODE_COUNT] = { - [MOVI] = &&MOVI, - [MOVI_F] = &&MOVI_F, - [MOVI_D] = &&MOVI_D, - [MOVR] = &&MOVR, - [MOVR_F] = &&MOVR_F, - [MOVR_D] = &&MOVR_D, - - [EXTR8] = &&EXTR8, - [EXTR16] = &&EXTR16, - [EXTR32] = &&EXTR32, - [EXTRU8] = &&EXTRU8, - [EXTRU16] = &&EXTRU16, - [EXTRU32] = &&EXTRU32, - [EXTRF] = &&EXTRF, - [EXTRD] = &&EXTRD, - - [ADDR] = &&ADDR, - [ADDR_F] = &&ADDR_F, - [ADDR_D] = &&ADDR_D, - [ADDI] = &&ADDI, - - [ABSR_F] = &&ABSR_F, - [ABSR_D] = &&ABSR_D, - - [SUBR] = &&SUBR, - [SUBR_F] = &&SUBR_F, - [SUBR_D] = &&SUBR_D, - [SUBI] = &&SUBI, - - [MULR] = &&MULR, - [MULR_F] = &&MULR_F, - [MULR_D] = &&MULR_D, - - [DIVR] = &&DIVR, - [DIVR_U] = &&DIVR_U, - [DIVR_F] = &&DIVR_F, - [DIVR_D] = &&DIVR_D, - - [REMR] = &&REMR, - [REMR_U] = &&REMR_U, - - [LSHI] = &&LSHI, - [LSHR] = &&LSHR, - [RSHI] = &&RSHI, - [RSHR] = &&RSHR, - [RSHI_U] = &&RSHI_U, - [RSHR_U] = &&RSHR_U, - - [ANDR] = &&ANDR, - [ANDI] = &&ANDI, - - [ORR] = &&ORR, - [ORI] = &&ORI, - - [XORR] = &&XORR, - [XORI] = &&XORI, - - [COMR] = &&COMR, - [NEGR] = &&NEGR, - [NEGR_F] = &&NEGR_F, - [NEGR_D] = &&NEGR_D, - - [EQR] = &&EQR, - [EQR_F] = &&EQR_F, - [EQR_D] = &&EQR_D, - - [NER] = &&NER, - [NER_F] = &&NER_F, - [NER_D] = &&NER_D, - - [GTR] = &>R, - [GTR_U] = &>R_U, - [GTR_F] = &>R_F, - [GTR_D] = &>R_D, - - [GER] = &&GER, - [GER_U] = &&GER_U, - [GER_F] = &&GER_F, - [GER_D] = &&GER_D, - - [STI8] = &&STI8, - [STI16] = &&STI16, - [STI32] = &&STI32, - [STI64] = &&STI64, - [STIF] = &&STIF, - [STID] = &&STID, - - [STXI8] = &&STXI8, - [STXI16] = &&STXI16, - [STXI32] = &&STXI32, - [STXI64] = &&STXI64, - [STXIF] = &&STXIF, - [STXID] = &&STXID, - - [STXR8] = &&STXR8, - [STXR16] = &&STXR16, - [STXR32] = &&STXR32, - [STXR64] = &&STXR64, - [STXRF] = &&STXRF, - [STXRD] = &&STXRD, - - [LDI8] = &&LDI8, - [LDI16] = &&LDI16, - [LDI32] = &&LDI32, - [LDI64] = &&LDI64, - [LDIU8] = &&LDIU8, - [LDIU16] = &&LDIU16, - [LDIU32] = &&LDIU32, - [LDIU64] = &&LDIU64, - [LDIF] = &&LDIF, - [LDID] = &&LDID, - - [LDXI8] = &&LDXI8, - [LDXI16] = &&LDXI16, - [LDXI32] = &&LDXI32, - [LDXI64] = &&LDXI64, - [LDXIU8] = &&LDXIU8, - [LDXIU16] = &&LDXIU16, - [LDXIU32] = &&LDXIU32, - [LDXIU64] = &&LDXIU64, - [LDXIF] = &&LDXIF, - [LDXID] = &&LDXID, - - [LDXR8] = &&LDXR8, - [LDXR16] = &&LDXR16, - [LDXR32] = &&LDXR32, - [LDXR64] = &&LDXR64, - [LDXRU8] = &&LDXRU8, - [LDXRU16] = &&LDXRU16, - [LDXRU32] = &&LDXRU32, - [LDXRU64] = &&LDXRU64, - [LDXRF] = &&LDXRF, - [LDXRD] = &&LDXRD, - - [TRUNCR_D_32] = &&TRUNCR_D_32, - [TRUNCR_D_64] = &&TRUNCR_D_64, - [TRUNCR_F_32] = &&TRUNCR_F_32, - [TRUNCR_F_64] = &&TRUNCR_F_64, - - [BNER] = &&BNER, - [BNEI] = &&BNEI, - [BNER_F] = &&BNER_F, - [BNER_D] = &&BNER_D, - - [BEQR] = &&BEQR, - [BEQI] = &&BEQI, - [BEQR_F] = &&BEQR_F, - [BEQR_D] = &&BEQR_D, - - [BGER] = &&BGER, - [BGER_U] = &&BGER_U, - [BGEI] = &&BGEI, - [BGEI_U] = &&BGEI_U, - [BGER_F] = &&BGER_F, - [BGER_D] = &&BGER_D, - - [BLEI] = &&BLEI, - [BLEI_U] = &&BLEI_U, - - [BGTR] = &&BGTR, - [BGTR_U] = &&BGTR_U, - [BGTI] = &&BGTI, - [BGTI_U] = &&BGTI_U, - [BGTR_F] = &&BGTR_F, - [BGTR_D] = &&BGTR_D, - - [BLTI] = &&BLTI, - [BLTI_U] = &&BLTI_U, - - [JMP] = &&JMP, - [JMPR] = &&JMPR, - - [BMCI] = &&BMCI, - [BMCR] = &&BMCR, - [BMSI] = &&BMSI, - [BMSR] = &&BMSR, - - [RETR] = &&RETR, - [RETI] = &&RETI, - [RETR_F] = &&RETR_F, - [RETI_F] = &&RETI_F, - [RETR_D] = &&RETR_D, - [RETI_D] = &&RETI_D, - - [RETVAL] = &&RETVAL, - [RETVAL_F] = &&RETVAL_F, - [RETVAL_D] = &&RETVAL_D, - - [ARG] = &&ARG, - [ARG_I] = &&ARG_I, - [ARG_F] = &&ARG_F, - [ARG_FI] = &&ARG_FI, - - [PARAM] = &&PARAM, - [PARAM_F] = &&PARAM_F, - - [CALLI_I] = &&CALLI_I, - [CALLI_L] = &&CALLI_L, - [CALLI_F] = &&CALLI_F, - [CALLI_D] = &&CALLI_D, - [ESCAPEI_I] = &&ESCAPEI_I, - [ESCAPEI_F] = &&ESCAPEI_F, - [ESCAPEI_L] = &&ESCAPEI_L, - [ESCAPEI_D] = &&ESCAPEI_D, - - [START] = &&START, - [END] = &&END, + static void *labels[EJIT_OPCODE_COUNT] = { + [EJIT_OP_MOVI] = &&MOVI, + [EJIT_OP_MOVI_F] = &&MOVI_F, + [EJIT_OP_MOVI_D] = &&MOVI_D, + [EJIT_OP_MOVR] = &&MOVR, + [EJIT_OP_MOVR_F] = &&MOVR_F, + [EJIT_OP_MOVR_D] = &&MOVR_D, + + [EJIT_OP_EXTR8] = &&EXTR8, + [EJIT_OP_EXTR16] = &&EXTR16, + [EJIT_OP_EXTR32] = &&EXTR32, + [EJIT_OP_EXTRU8] = &&EXTRU8, + [EJIT_OP_EXTRU16] = &&EXTRU16, + [EJIT_OP_EXTRU32] = &&EXTRU32, + [EJIT_OP_EXTRF] = &&EXTRF, + [EJIT_OP_EXTRD] = &&EXTRD, + + [EJIT_OP_ADDR] = &&ADDR, + [EJIT_OP_ADDR_F] = &&ADDR_F, + [EJIT_OP_ADDR_D] = &&ADDR_D, + [EJIT_OP_ADDI] = &&ADDI, + + [EJIT_OP_ABSR_F] = &&ABSR_F, + [EJIT_OP_ABSR_D] = &&ABSR_D, + + [EJIT_OP_SUBR] = &&SUBR, + [EJIT_OP_SUBR_F] = &&SUBR_F, + [EJIT_OP_SUBR_D] = &&SUBR_D, + [EJIT_OP_SUBI] = &&SUBI, + + [EJIT_OP_MULR] = &&MULR, + [EJIT_OP_MULR_F] = &&MULR_F, + [EJIT_OP_MULR_D] = &&MULR_D, + + [EJIT_OP_DIVR] = &&DIVR, + [EJIT_OP_DIVR_U] = &&DIVR_U, + [EJIT_OP_DIVR_F] = &&DIVR_F, + [EJIT_OP_DIVR_D] = &&DIVR_D, + + [EJIT_OP_REMR] = &&REMR, + [EJIT_OP_REMR_U] = &&REMR_U, + + [EJIT_OP_LSHI] = &&LSHI, + [EJIT_OP_LSHR] = &&LSHR, + [EJIT_OP_RSHI] = &&RSHI, + [EJIT_OP_RSHR] = &&RSHR, + [EJIT_OP_RSHI_U] = &&RSHI_U, + [EJIT_OP_RSHR_U] = &&RSHR_U, + + [EJIT_OP_ANDR] = &&ANDR, + [EJIT_OP_ANDI] = &&ANDI, + + [EJIT_OP_ORR] = &&ORR, + [EJIT_OP_ORI] = &&ORI, + + [EJIT_OP_XORR] = &&XORR, + [EJIT_OP_XORI] = &&XORI, + + [EJIT_OP_COMR] = &&COMR, + [EJIT_OP_NEGR] = &&NEGR, + [EJIT_OP_NEGR_F] = &&NEGR_F, + [EJIT_OP_NEGR_D] = &&NEGR_D, + + [EJIT_OP_EQR] = &&EQR, + [EJIT_OP_EQR_F] = &&EQR_F, + [EJIT_OP_EQR_D] = &&EQR_D, + + [EJIT_OP_NER] = &&NER, + [EJIT_OP_NER_F] = &&NER_F, + [EJIT_OP_NER_D] = &&NER_D, + + [EJIT_OP_GTR] = &>R, + [EJIT_OP_GTR_U] = &>R_U, + [EJIT_OP_GTR_F] = &>R_F, + [EJIT_OP_GTR_D] = &>R_D, + + [EJIT_OP_GER] = &&GER, + [EJIT_OP_GER_U] = &&GER_U, + [EJIT_OP_GER_F] = &&GER_F, + [EJIT_OP_GER_D] = &&GER_D, + + [EJIT_OP_STI8] = &&STI8, + [EJIT_OP_STI16] = &&STI16, + [EJIT_OP_STI32] = &&STI32, + [EJIT_OP_STI64] = &&STI64, + [EJIT_OP_STIF] = &&STIF, + [EJIT_OP_STID] = &&STID, + + [EJIT_OP_STXI8] = &&STXI8, + [EJIT_OP_STXI16] = &&STXI16, + [EJIT_OP_STXI32] = &&STXI32, + [EJIT_OP_STXI64] = &&STXI64, + [EJIT_OP_STXIF] = &&STXIF, + [EJIT_OP_STXID] = &&STXID, + + [EJIT_OP_STXR8] = &&STXR8, + [EJIT_OP_STXR16] = &&STXR16, + [EJIT_OP_STXR32] = &&STXR32, + [EJIT_OP_STXR64] = &&STXR64, + [EJIT_OP_STXRF] = &&STXRF, + [EJIT_OP_STXRD] = &&STXRD, + + [EJIT_OP_LDI8] = &&LDI8, + [EJIT_OP_LDI16] = &&LDI16, + [EJIT_OP_LDI32] = &&LDI32, + [EJIT_OP_LDI64] = &&LDI64, + [EJIT_OP_LDIU8] = &&LDIU8, + [EJIT_OP_LDIU16] = &&LDIU16, + [EJIT_OP_LDIU32] = &&LDIU32, + [EJIT_OP_LDIU64] = &&LDIU64, + [EJIT_OP_LDIF] = &&LDIF, + [EJIT_OP_LDID] = &&LDID, + + [EJIT_OP_LDXI8] = &&LDXI8, + [EJIT_OP_LDXI16] = &&LDXI16, + [EJIT_OP_LDXI32] = &&LDXI32, + [EJIT_OP_LDXI64] = &&LDXI64, + [EJIT_OP_LDXIU8] = &&LDXIU8, + [EJIT_OP_LDXIU16] = &&LDXIU16, + [EJIT_OP_LDXIU32] = &&LDXIU32, + [EJIT_OP_LDXIU64] = &&LDXIU64, + [EJIT_OP_LDXIF] = &&LDXIF, + [EJIT_OP_LDXID] = &&LDXID, + + [EJIT_OP_LDXR8] = &&LDXR8, + [EJIT_OP_LDXR16] = &&LDXR16, + [EJIT_OP_LDXR32] = &&LDXR32, + [EJIT_OP_LDXR64] = &&LDXR64, + [EJIT_OP_LDXRU8] = &&LDXRU8, + [EJIT_OP_LDXRU16] = &&LDXRU16, + [EJIT_OP_LDXRU32] = &&LDXRU32, + [EJIT_OP_LDXRU64] = &&LDXRU64, + [EJIT_OP_LDXRF] = &&LDXRF, + [EJIT_OP_LDXRD] = &&LDXRD, + + [EJIT_OP_TRUNCR_D_32] = &&TRUNCR_D_32, + [EJIT_OP_TRUNCR_D_64] = &&TRUNCR_D_64, + [EJIT_OP_TRUNCR_F_32] = &&TRUNCR_F_32, + [EJIT_OP_TRUNCR_F_64] = &&TRUNCR_F_64, + + [EJIT_OP_BNER] = &&BNER, + [EJIT_OP_BNEI] = &&BNEI, + [EJIT_OP_BNER_F] = &&BNER_F, + [EJIT_OP_BNER_D] = &&BNER_D, + + [EJIT_OP_BEQR] = &&BEQR, + [EJIT_OP_BEQI] = &&BEQI, + [EJIT_OP_BEQR_F] = &&BEQR_F, + [EJIT_OP_BEQR_D] = &&BEQR_D, + + [EJIT_OP_BGER] = &&BGER, + [EJIT_OP_BGER_U] = &&BGER_U, + [EJIT_OP_BGEI] = &&BGEI, + [EJIT_OP_BGEI_U] = &&BGEI_U, + [EJIT_OP_BGER_F] = &&BGER_F, + [EJIT_OP_BGER_D] = &&BGER_D, + + [EJIT_OP_BLEI] = &&BLEI, + [EJIT_OP_BLEI_U] = &&BLEI_U, + + [EJIT_OP_BGTR] = &&BGTR, + [EJIT_OP_BGTR_U] = &&BGTR_U, + [EJIT_OP_BGTI] = &&BGTI, + [EJIT_OP_BGTI_U] = &&BGTI_U, + [EJIT_OP_BGTR_F] = &&BGTR_F, + [EJIT_OP_BGTR_D] = &&BGTR_D, + + [EJIT_OP_BLTI] = &&BLTI, + [EJIT_OP_BLTI_U] = &&BLTI_U, + + [EJIT_OP_JMP] = &&JMP, + [EJIT_OP_JMPR] = &&JMPR, + + [EJIT_OP_BMCI] = &&BMCI, + [EJIT_OP_BMCR] = &&BMCR, + [EJIT_OP_BMSI] = &&BMSI, + [EJIT_OP_BMSR] = &&BMSR, + + [EJIT_OP_RETR] = &&RETR, + [EJIT_OP_RETI] = &&RETI, + [EJIT_OP_RETR_F] = &&RETR_F, + [EJIT_OP_RETI_F] = &&RETI_F, + [EJIT_OP_RETR_D] = &&RETR_D, + [EJIT_OP_RETI_D] = &&RETI_D, + + [EJIT_OP_RETVAL] = &&RETVAL, + [EJIT_OP_RETVAL_F] = &&RETVAL_F, + [EJIT_OP_RETVAL_D] = &&RETVAL_D, + + [EJIT_OP_ARG] = &&ARG, + [EJIT_OP_ARG_I] = &&ARG_I, + [EJIT_OP_ARG_F] = &&ARG_F, + [EJIT_OP_ARG_FI] = &&ARG_FI, + + [EJIT_OP_PARAM] = &&PARAM, + [EJIT_OP_PARAM_F] = &&PARAM_F, + + [EJIT_OP_CALLI_I] = &&CALLI_I, + [EJIT_OP_CALLI_L] = &&CALLI_L, + [EJIT_OP_CALLI_F] = &&CALLI_F, + [EJIT_OP_CALLI_D] = &&CALLI_D, + [EJIT_OP_ESCAPEI_I] = &&ESCAPEI_I, + [EJIT_OP_ESCAPEI_F] = &&ESCAPEI_F, + [EJIT_OP_ESCAPEI_L] = &&ESCAPEI_L, + [EJIT_OP_ESCAPEI_D] = &&ESCAPEI_D, + + [EJIT_OP_START] = &&START, + [EJIT_OP_END] = &&END, }; if (!run) { -- cgit v1.2.3 From 478c92b425eca53a0d884fb8f5dea8d769016858 Mon Sep 17 00:00:00 2001 From: Kimplul Date: Tue, 1 Apr 2025 22:16:25 +0300 Subject: expose sqrt + Requires linking with libm in some cases, which is fine I suppose, but kind of annoying --- include/ejit/ejit.h | 3 +++ scripts/gen-tests | 2 +- src/common.h | 3 +++ src/compile/compile.c | 20 ++++++++++++++++++++ src/ejit.c | 10 ++++++++++ src/interp.c | 11 +++++++++++ tests/sqrtr_d.c | 23 +++++++++++++++++++++++ tests/sqrtr_f.c | 23 +++++++++++++++++++++++ 8 files changed, 94 insertions(+), 1 deletion(-) create mode 100644 tests/sqrtr_d.c create mode 100644 tests/sqrtr_f.c (limited to 'src/ejit.c') diff --git a/include/ejit/ejit.h b/include/ejit/ejit.h index d4bb725..920fdc5 100644 --- a/include/ejit/ejit.h +++ b/include/ejit/ejit.h @@ -805,6 +805,9 @@ 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); + 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, diff --git a/scripts/gen-tests b/scripts/gen-tests index 5521006..deac247 100755 --- a/scripts/gen-tests +++ b/scripts/gen-tests @@ -11,5 +11,5 @@ do echo "${dep}:" >> tests.mk echo "-include ${dep}" >> tests.mk echo "${exe}: ${s} libejit.a" >> tests.mk - echo " \$(COMPILE_TEST) ${s} libejit.a -o ${exe}" >> tests.mk + echo " \$(COMPILE_TEST) ${s} libejit.a -o ${exe} -lm" >> tests.mk done diff --git a/src/common.h b/src/common.h index 6a3c754..c690f8f 100644 --- a/src/common.h +++ b/src/common.h @@ -142,6 +142,9 @@ enum ejit_opcode { EJIT_OP_TRUNCR_F_32, EJIT_OP_TRUNCR_F_64, + EJIT_OP_SQRTR_F, + EJIT_OP_SQRTR_D, + EJIT_OP_EQR, EJIT_OP_NER, EJIT_OP_GTR, diff --git a/src/compile/compile.c b/src/compile/compile.c index b90ee54..580b7fa 100644 --- a/src/compile/compile.c +++ b/src/compile/compile.c @@ -1326,6 +1326,23 @@ static void compile_truncr_f_32(struct ejit_func *f, jit_state_t *j, #endif } +static void compile_sqrtr_f(struct ejit_func *f, jit_state_t *j, + struct ejit_insn i) +{ + jit_fpr_t r0 = getfpr(f, i.r0, 0); + jit_fpr_t r1 = getloc_f(f, j, i.r1, 1); + jit_sqrtr_f(j, r0, r1); + putloc_d(f, j, i.r0, r0); +} + +static void compile_sqrtr_d(struct ejit_func *f, jit_state_t *j, + struct ejit_insn i) +{ + jit_fpr_t r0 = getfpr(f, i.r0, 0); + jit_fpr_t r1 = getloc_d(f, j, i.r1, 1); + jit_sqrtr_d(j, r0, r1); + putloc_d(f, j, i.r0, r0); +} static void compile_reg_cmp(struct ejit_func *f, jit_state_t *j, struct ejit_insn i, @@ -2084,6 +2101,9 @@ static size_t compile_fn_body(struct ejit_func *f, jit_state_t *j, void *arena, case EJIT_OP_TRUNCR_F_32: compile_truncr_f_32(f, j, i); break; case EJIT_OP_TRUNCR_F_64: compile_truncr_f_64(f, j, i); break; + case EJIT_OP_SQRTR_F: compile_sqrtr_f(f, j, i); break; + case EJIT_OP_SQRTR_D: compile_sqrtr_d(f, j, i); break; + case EJIT_OP_EQR: compile_eqr(f, j, i); break; case EJIT_OP_EQR_F: compile_eqr_f(f, j, i); break; case EJIT_OP_EQR_D: compile_eqr_d(f, j, i); break; diff --git a/src/ejit.c b/src/ejit.c index e7e2ff2..2224198 100644 --- a/src/ejit.c +++ b/src/ejit.c @@ -1371,6 +1371,16 @@ void ejit_truncr_f_64(struct ejit_func *s, struct ejit_gpr r0, emit_insn_orf(s, EJIT_OP_TRUNCR_F_64, r0, f1); } +void ejit_sqrtr_f(struct ejit_func *s, struct ejit_fpr r0, struct ejit_fpr r1) +{ + emit_insn_off(s, EJIT_OP_SQRTR_F, r0, r1); +} + +void ejit_sqrtr_d(struct ejit_func *s, struct ejit_fpr r0, struct ejit_fpr r1) +{ + emit_insn_off(s, EJIT_OP_SQRTR_D, r0, r1); +} + struct ejit_reloc ejit_bner(struct ejit_func *s, struct ejit_gpr r0, struct ejit_gpr r1) { diff --git a/src/interp.c b/src/interp.c index b858f26..2d9b7c7 100644 --- a/src/interp.c +++ b/src/interp.c @@ -147,6 +147,9 @@ union interp_ret ejit_run(struct ejit_func *f, size_t paramc, struct ejit_arg pa [EJIT_OP_TRUNCR_F_32] = &&TRUNCR_F_32, [EJIT_OP_TRUNCR_F_64] = &&TRUNCR_F_64, + [EJIT_OP_SQRTR_F] = &&SQRTR_F, + [EJIT_OP_SQRTR_D] = &&SQRTR_D, + [EJIT_OP_BNER] = &&BNER, [EJIT_OP_BNEI] = &&BNEI, [EJIT_OP_BNER_F] = &&BNER_F, @@ -784,6 +787,14 @@ union interp_ret ejit_run(struct ejit_func *f, size_t paramc, struct ejit_arg pa gpr[i.r0] = (int64_t)fpr[i.r1].f; DISPATCH(); + DO(SQRTR_F); + fpr[i.r0].f = sqrt(fpr[i.r1].f); + DISPATCH(); + + DO(SQRTR_D); + fpr[i.r0].d = sqrt(fpr[i.r1].d); + DISPATCH(); + DO(BNER); if (gpr[i.r1] != gpr[i.r2]) JUMP(i.r0); diff --git a/tests/sqrtr_d.c b/tests/sqrtr_d.c new file mode 100644 index 0000000..06e7894 --- /dev/null +++ b/tests/sqrtr_d.c @@ -0,0 +1,23 @@ +#include +#include +#include "do_jit.h" + +int main(int argc, char *argv[]) +{ + (void)argv; + bool do_jit = argc > 1; + struct ejit_operand operands[1] = { + EJIT_OPERAND_FPR(0, EJIT_TYPE(double)), + }; + struct ejit_func *f = ejit_create_func(EJIT_TYPE(double), 1, operands); + + ejit_sqrtr_d(f, EJIT_FPR(0), EJIT_FPR(0)); + ejit_retr_d(f, EJIT_FPR(0)); + + ejit_select_compile_func(f, 0, 1, EJIT_USE64(double), do_jit, true); + + assert(erfd1(f, EJIT_ARG( 0.0, double)) == 0.0); + assert(erfd1(f, EJIT_ARG( 4.0, double)) == 2.0); + assert(erfd1(f, EJIT_ARG(-4.0, double)) + != erfd1(f, EJIT_ARG(-4.0, double))); // nan +} diff --git a/tests/sqrtr_f.c b/tests/sqrtr_f.c new file mode 100644 index 0000000..3baa00d --- /dev/null +++ b/tests/sqrtr_f.c @@ -0,0 +1,23 @@ +#include +#include +#include "do_jit.h" + +int main(int argc, char *argv[]) +{ + (void)argv; + bool do_jit = argc > 1; + struct ejit_operand operands[1] = { + EJIT_OPERAND_FPR(0, EJIT_TYPE(float)), + }; + struct ejit_func *f = ejit_create_func(EJIT_TYPE(float), 1, operands); + + ejit_sqrtr_f(f, EJIT_FPR(0), EJIT_FPR(0)); + ejit_retr_f(f, EJIT_FPR(0)); + + ejit_select_compile_func(f, 0, 1, EJIT_USE64(float), do_jit, true); + + assert(erff1(f, EJIT_ARG( 0.0, float)) == 0.0); + assert(erff1(f, EJIT_ARG( 4.0, float)) == 2.0); + assert(erff1(f, EJIT_ARG(-4.0, float)) + != erff1(f, EJIT_ARG(-4.0, float))); // nan +} -- cgit v1.2.3 From d8f9699debd435da5e1aef22c94c47154be4e2be Mon Sep 17 00:00:00 2001 From: Kimplul Date: Wed, 2 Apr 2025 21:13:03 +0300 Subject: fix big endian compilation + Code used some assumptions about type aliasing that might not hold for all systems --- include/ejit/ejit.h | 124 ++++++++++++++++++++++++++++++++----------- src/ejit.c | 6 ++- src/interp.c | 13 ++++- tests/escapei_10.c | 30 ++++------- tests/escapei_double.c | 6 +-- tests/escapei_float.c | 6 +-- tests/escapei_immediate_10.c | 30 ++++------- 7 files changed, 134 insertions(+), 81 deletions(-) (limited to 'src/ejit.c') diff --git a/include/ejit/ejit.h b/include/ejit/ejit.h index 920fdc5..2afdc61 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; }; @@ -136,15 +127,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(); } @@ -251,17 +242,17 @@ void ejit_destroy_func(struct ejit_func *s); /* 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) @@ -271,22 +262,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) @@ -372,6 +363,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) diff --git a/src/ejit.c b/src/ejit.c index 2224198..0ee3986 100644 --- a/src/ejit.c +++ b/src/ejit.c @@ -1726,6 +1726,10 @@ struct ejit_arg ejit_run_func(struct ejit_func *f, size_t argc, struct ejit_arg }; case EJIT_UINT64: + return (struct ejit_arg){ + .u64 = ejit_run_func_l(f, argc, args), + .type = f->rtype + }; case EJIT_INT64: return (struct ejit_arg){ .i64 = ejit_run_func_l(f, argc, args), @@ -1734,7 +1738,7 @@ struct ejit_arg ejit_run_func(struct ejit_func *f, size_t argc, struct ejit_arg default: return (struct ejit_arg){ - .i64 = ejit_run_func_i(f, argc, args), + .l = ejit_run_func_i(f, argc, args), .type = f->rtype }; } diff --git a/src/interp.c b/src/interp.c index 2d9b7c7..049498a 100644 --- a/src/interp.c +++ b/src/interp.c @@ -984,7 +984,18 @@ union interp_ret ejit_run(struct ejit_func *f, size_t paramc, struct ejit_arg pa DISPATCH(); DO(PARAM); - gpr[i.r2] = params[i.r0].u64; + switch (i.r1) { + case EJIT_INT8: gpr[i.r2] = params[i.r0].i8; break; + case EJIT_INT16: gpr[i.r2] = params[i.r0].i16; break; + case EJIT_INT32: gpr[i.r2] = params[i.r0].i32; break; + case EJIT_INT64: gpr[i.r2] = params[i.r0].i64; break; + case EJIT_UINT8: gpr[i.r2] = params[i.r0].u8; break; + case EJIT_UINT16: gpr[i.r2] = params[i.r0].u16; break; + case EJIT_UINT32: gpr[i.r2] = params[i.r0].u32; break; + case EJIT_UINT64: gpr[i.r2] = params[i.r0].u64; break; + case EJIT_POINTER: gpr[i.r2] = (int64_t)params[i.r0].p; break; + default: abort(); + } DISPATCH(); DO(PARAM_F); diff --git a/tests/escapei_10.c b/tests/escapei_10.c index 4ae00b8..ec48df0 100644 --- a/tests/escapei_10.c +++ b/tests/escapei_10.c @@ -21,26 +21,16 @@ static int32_t func(int32_t a, int32_t b, int32_t c, int32_t d, int32_t e, static long escape_func(size_t argc, const struct ejit_arg args[argc]) { assert(argc == 10); - assert(args[0].type == EJIT_INT32); - assert(args[1].type == EJIT_INT32); - assert(args[3].type == EJIT_INT32); - assert(args[4].type == EJIT_INT32); - assert(args[5].type == EJIT_INT32); - assert(args[6].type == EJIT_INT32); - assert(args[7].type == EJIT_INT32); - assert(args[8].type == EJIT_INT32); - assert(args[9].type == EJIT_INT32); - - int32_t a = args[0].i32; - int32_t b = args[1].i32; - int32_t c = args[2].i32; - int32_t d = args[3].i32; - int32_t e = args[4].i32; - int32_t f = args[5].i32; - int32_t g = args[6].i32; - int32_t h = args[7].i32; - int32_t i = args[8].i32; - int32_t j = args[9].i32; + int32_t a = EJIT_PARAM(argc, args, 0, int32_t); + int32_t b = EJIT_PARAM(argc, args, 1, int32_t); + int32_t c = EJIT_PARAM(argc, args, 2, int32_t); + int32_t d = EJIT_PARAM(argc, args, 3, int32_t); + int32_t e = EJIT_PARAM(argc, args, 4, int32_t); + int32_t f = EJIT_PARAM(argc, args, 5, int32_t); + int32_t g = EJIT_PARAM(argc, args, 6, int32_t); + int32_t h = EJIT_PARAM(argc, args, 7, int32_t); + int32_t i = EJIT_PARAM(argc, args, 8, int32_t); + int32_t j = EJIT_PARAM(argc, args, 9, int32_t); return func(a, b, c, d, e, f, g, h, i, j); } diff --git a/tests/escapei_double.c b/tests/escapei_double.c index 6ea9f90..736e978 100644 --- a/tests/escapei_double.c +++ b/tests/escapei_double.c @@ -9,10 +9,8 @@ static double func(int32_t a, double b) { static double escape_func(size_t argc, const struct ejit_arg args[argc]) { assert(argc == 2); - assert(args[0].type == EJIT_INT32); - assert(args[1].type == EJIT_DOUBLE); - int32_t a = args[0].i32; - double b = args[1].d; + int32_t a = EJIT_PARAM(argc, args, 0, int32_t); + double b = EJIT_PARAM(argc, args, 1, double); return func(a, b); } diff --git a/tests/escapei_float.c b/tests/escapei_float.c index 7a1b923..7cdc30d 100644 --- a/tests/escapei_float.c +++ b/tests/escapei_float.c @@ -9,10 +9,8 @@ static float func(int32_t a, float b) { static float escape_func(size_t argc, const struct ejit_arg args[argc]) { assert(argc == 2); - assert(args[0].type == EJIT_INT32); - assert(args[1].type == EJIT_FLOAT); - int32_t a = args[0].i32; - float b = args[1].f; + int32_t a = EJIT_PARAM(argc, args, 0, int32_t); + float b = EJIT_PARAM(argc, args, 1, float); return func(a, b); } diff --git a/tests/escapei_immediate_10.c b/tests/escapei_immediate_10.c index 381c79f..5517c35 100644 --- a/tests/escapei_immediate_10.c +++ b/tests/escapei_immediate_10.c @@ -21,26 +21,16 @@ static int32_t func(int32_t a, int32_t b, int32_t c, int32_t d, int32_t e, static long escape_func(size_t argc, const struct ejit_arg args[argc]) { assert(argc == 10); - assert(args[0].type == EJIT_INT32); - assert(args[1].type == EJIT_INT32); - assert(args[3].type == EJIT_INT32); - assert(args[4].type == EJIT_INT32); - assert(args[5].type == EJIT_INT32); - assert(args[6].type == EJIT_INT32); - assert(args[7].type == EJIT_INT32); - assert(args[8].type == EJIT_INT32); - assert(args[9].type == EJIT_INT32); - - int32_t a = args[0].i32; - int32_t b = args[1].i32; - int32_t c = args[2].i32; - int32_t d = args[3].i32; - int32_t e = args[4].i32; - int32_t f = args[5].i32; - int32_t g = args[6].i32; - int32_t h = args[7].i32; - int32_t i = args[8].i32; - int32_t j = args[9].i32; + int32_t a = EJIT_PARAM(argc, args, 0, int32_t); + int32_t b = EJIT_PARAM(argc, args, 1, int32_t); + int32_t c = EJIT_PARAM(argc, args, 2, int32_t); + int32_t d = EJIT_PARAM(argc, args, 3, int32_t); + int32_t e = EJIT_PARAM(argc, args, 4, int32_t); + int32_t f = EJIT_PARAM(argc, args, 5, int32_t); + int32_t g = EJIT_PARAM(argc, args, 6, int32_t); + int32_t h = EJIT_PARAM(argc, args, 7, int32_t); + int32_t i = EJIT_PARAM(argc, args, 8, int32_t); + int32_t j = EJIT_PARAM(argc, args, 9, int32_t); return func(a, b, c, d, e, f, g, h, i, j); } -- cgit v1.2.3 From 89d9f5c3fc59eff3b1a46fe6d44f5ee92eeb7be4 Mon Sep 17 00:00:00 2001 From: Kimplul Date: Wed, 2 Apr 2025 21:16:13 +0300 Subject: armhf seems to work --- scripts/select-compile | 1 + src/compile/compile.c | 4 ++-- src/ejit.c | 1 + src/interp.c | 10 +++++----- 4 files changed, 9 insertions(+), 7 deletions(-) (limited to 'src/ejit.c') diff --git a/scripts/select-compile b/scripts/select-compile index 38fc7b0..37c67a1 100755 --- a/scripts/select-compile +++ b/scripts/select-compile @@ -13,6 +13,7 @@ case "$ARCH" in mips64el) echo "$JIT" ;; aarch64) echo "$JIT" ;; mipsel) echo "$JIT" ;; + armhf) echo "$JIT" ;; amd64) echo "$JIT" ;; x86*) echo "$JIT" ;; *) echo "$NOJIT" ;; diff --git a/src/compile/compile.c b/src/compile/compile.c index dac8dfd..3b5399a 100644 --- a/src/compile/compile.c +++ b/src/compile/compile.c @@ -1927,7 +1927,7 @@ static void compile_trampoline(struct ejit_func *f, jit_state_t *j) jit_leave_jit_abi(j, 0, 0, frame); jit_ret(j); /* should just forward the return value */ - f->direct_call = jit_address(j); + f->direct_call = jit_address_to_function_pointer(jit_address(j)); jit_patch_here(j, r); operands_destroy(&args); @@ -2435,7 +2435,7 @@ calli: relocs_destroy(&relocs); addrs_destroy(&addrs); - if (jit_end(j, &size)) + if ((f->extern_call = jit_end(j, &size))) return 0; return size; diff --git a/src/ejit.c b/src/ejit.c index 0ee3986..75f6a6a 100644 --- a/src/ejit.c +++ b/src/ejit.c @@ -345,6 +345,7 @@ struct ejit_func *ejit_create_func(enum ejit_type rtype, size_t argc, f->fpr = fpr_stats_create(); f->arena = NULL; f->direct_call = NULL; + f->extern_call = NULL; f->size = 0; f->prio = 1; f->use_64 = false; diff --git a/src/interp.c b/src/interp.c index 049498a..e7be77b 100644 --- a/src/interp.c +++ b/src/interp.c @@ -227,24 +227,24 @@ union interp_ret ejit_run(struct ejit_func *f, size_t paramc, struct ejit_arg pa assert(f->size && "trying to run a function that hasn't been compiled"); - if (f->arena) { + if (f->extern_call) { if (f->rtype == EJIT_INT64 || f->rtype == EJIT_UINT64) return (union interp_ret){ - .i = ((ejit_escape_l_t)f->arena)(paramc, params) + .i = ((ejit_escape_l_t)f->extern_call)(paramc, params) }; if (f->rtype == EJIT_DOUBLE) return (union interp_ret){ - .f = ((ejit_escape_d_t)f->arena)(paramc, params) + .f = ((ejit_escape_d_t)f->extern_call)(paramc, params) }; if (f->rtype == EJIT_FLOAT) return (union interp_ret){ - .f = ((ejit_escape_f_t)f->arena)(paramc, params) + .f = ((ejit_escape_f_t)f->extern_call)(paramc, params) }; return (union interp_ret){ - .i = ((ejit_escape_i_t)f->arena)(paramc, params) + .i = ((ejit_escape_i_t)f->extern_call)(paramc, params) }; } -- cgit v1.2.3 From 42f89542550033a3f22700e6b0fd71627a252f96 Mon Sep 17 00:00:00 2001 From: Kimplul Date: Sat, 5 Apr 2025 13:46:09 +0300 Subject: implement minr_d/maxr_d --- deps/lightening | 2 +- include/ejit/ejit.h | 6 ++++++ src/common.h | 6 ++++++ src/compile/compile.c | 46 ++++++++++++++++++++++++++++++++++++++++++++++ src/ejit.c | 26 ++++++++++++++++++++++++++ src/interp.c | 22 ++++++++++++++++++++++ tests/maxr_d.c | 28 ++++++++++++++++++++++++++++ tests/maxr_f.c | 28 ++++++++++++++++++++++++++++ tests/minr_d.c | 28 ++++++++++++++++++++++++++++ tests/minr_f.c | 28 ++++++++++++++++++++++++++++ 10 files changed, 219 insertions(+), 1 deletion(-) create mode 100644 tests/maxr_d.c create mode 100644 tests/maxr_f.c create mode 100644 tests/minr_d.c create mode 100644 tests/minr_f.c (limited to 'src/ejit.c') diff --git a/deps/lightening b/deps/lightening index 6421af4..5a72993 160000 --- a/deps/lightening +++ b/deps/lightening @@ -1 +1 @@ -Subproject commit 6421af4db1570a6a5fc3a15f3bcb2601d854ed0e +Subproject commit 5a72993827bc2b1735a7611c0036640cdb01b93b diff --git a/include/ejit/ejit.h b/include/ejit/ejit.h index b4b20c1..965103c 100644 --- a/include/ejit/ejit.h +++ b/include/ejit/ejit.h @@ -872,6 +872,12 @@ void ejit_truncr_d_64(struct ejit_func *s, struct ejit_gpr r0, 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, diff --git a/src/common.h b/src/common.h index 661220b..69f1441 100644 --- a/src/common.h +++ b/src/common.h @@ -145,6 +145,12 @@ enum ejit_opcode { EJIT_OP_SQRTR_F, EJIT_OP_SQRTR_D, + EJIT_OP_MINR_F, + EJIT_OP_MINR_D, + + EJIT_OP_MAXR_F, + EJIT_OP_MAXR_D, + EJIT_OP_EQR, EJIT_OP_NER, EJIT_OP_GTR, diff --git a/src/compile/compile.c b/src/compile/compile.c index 38c368f..dcf662b 100644 --- a/src/compile/compile.c +++ b/src/compile/compile.c @@ -1977,6 +1977,46 @@ static void resolve_relocs(jit_state_t *j, struct relocs *relocs, struct addrs * } } +static void compile_maxr_f(struct ejit_func *f, jit_state_t *j, + struct ejit_insn i) +{ + jit_fpr_t r0 = getfpr(f, i.r0, 0); + jit_fpr_t r1 = getloc_f(f, j, i.r1, 1); + jit_fpr_t r2 = getloc_f(f, j, i.r2, 2); + jit_maxr_f(j, r0, r1, r2); + putloc_f(f, j, i.r0, r0); +} + +static void compile_maxr_d(struct ejit_func *f, jit_state_t *j, + struct ejit_insn i) +{ + jit_fpr_t r0 = getfpr(f, i.r0, 0); + jit_fpr_t r1 = getloc_d(f, j, i.r1, 1); + jit_fpr_t r2 = getloc_d(f, j, i.r2, 2); + jit_maxr_d(j, r0, r1, r2); + putloc_d(f, j, i.r0, r0); +} + +static void compile_minr_f(struct ejit_func *f, jit_state_t *j, + struct ejit_insn i) +{ + jit_fpr_t r0 = getfpr(f, i.r0, 0); + jit_fpr_t r1 = getloc_f(f, j, i.r1, 1); + jit_fpr_t r2 = getloc_f(f, j, i.r2, 2); + jit_minr_f(j, r0, r1, r2); + putloc_f(f, j, i.r0, r0); +} + +static void compile_minr_d(struct ejit_func *f, jit_state_t *j, + struct ejit_insn i) +{ + jit_fpr_t r0 = getfpr(f, i.r0, 0); + jit_fpr_t r1 = getloc_d(f, j, i.r1, 1); + jit_fpr_t r2 = getloc_d(f, j, i.r2, 2); + jit_minr_d(j, r0, r1, r2); + putloc_d(f, j, i.r0, r0); +} + static size_t compile_fn_body(struct ejit_func *f, jit_state_t *j, void *arena, size_t size) { @@ -2143,6 +2183,12 @@ static size_t compile_fn_body(struct ejit_func *f, jit_state_t *j, void *arena, case EJIT_OP_SQRTR_F: compile_sqrtr_f(f, j, i); break; case EJIT_OP_SQRTR_D: compile_sqrtr_d(f, j, i); break; + case EJIT_OP_MINR_F: compile_minr_f(f, j, i); break; + case EJIT_OP_MINR_D: compile_minr_d(f, j, i); break; + + case EJIT_OP_MAXR_F: compile_maxr_f(f, j, i); break; + case EJIT_OP_MAXR_D: compile_maxr_d(f, j, i); break; + case EJIT_OP_EQR: compile_eqr(f, j, i); break; case EJIT_OP_EQR_F: compile_eqr_f(f, j, i); break; case EJIT_OP_EQR_D: compile_eqr_d(f, j, i); break; diff --git a/src/ejit.c b/src/ejit.c index 75f6a6a..c997a01 100644 --- a/src/ejit.c +++ b/src/ejit.c @@ -901,31 +901,37 @@ void ejit_ret(struct ejit_func *s) void ejit_retr(struct ejit_func *s, struct ejit_gpr r0) { + assert(s->rtype != EJIT_FLOAT && s->rtype != EJIT_DOUBLE); emit_insn_oxr(s, EJIT_OP_RETR, r0); } void ejit_retr_f(struct ejit_func *s, struct ejit_fpr f0) { + assert(s->rtype == EJIT_FLOAT); emit_insn_oxf(s, EJIT_OP_RETR_F, f0); } void ejit_retr_d(struct ejit_func *s, struct ejit_fpr f0) { + assert(s->rtype == EJIT_DOUBLE); emit_insn_oxf(s, EJIT_OP_RETR_D, f0); } void ejit_reti(struct ejit_func *s, int64_t i) { + assert(s->rtype != EJIT_FLOAT && s->rtype != EJIT_DOUBLE); emit_insn_oi(s, EJIT_OP_RETI, i); } void ejit_reti_f(struct ejit_func *s, float f) { + assert(s->rtype == EJIT_FLOAT); emit_insn_oF(s, EJIT_OP_RETI_F, f); } void ejit_reti_d(struct ejit_func *s, double f) { + assert(s->rtype == EJIT_DOUBLE); emit_insn_oD(s, EJIT_OP_RETI_D, f); } @@ -1382,6 +1388,26 @@ void ejit_sqrtr_d(struct ejit_func *s, struct ejit_fpr r0, struct ejit_fpr r1) emit_insn_off(s, EJIT_OP_SQRTR_D, r0, r1); } +void ejit_minr_f(struct ejit_func *s, struct ejit_fpr r0, struct ejit_fpr r1, struct ejit_fpr r2) +{ + emit_insn_offf(s, EJIT_OP_MINR_F, r0, r1, r2); +} + +void ejit_minr_d(struct ejit_func *s, struct ejit_fpr r0, struct ejit_fpr r1, struct ejit_fpr r2) +{ + emit_insn_offf(s, EJIT_OP_MINR_D, r0, r1, r2); +} + +void ejit_maxr_f(struct ejit_func *s, struct ejit_fpr r0, struct ejit_fpr r1, struct ejit_fpr r2) +{ + emit_insn_offf(s, EJIT_OP_MAXR_F, r0, r1, r2); +} + +void ejit_maxr_d(struct ejit_func *s, struct ejit_fpr r0, struct ejit_fpr r1, struct ejit_fpr r2) +{ + emit_insn_offf(s, EJIT_OP_MAXR_D, r0, r1, r2); +} + struct ejit_reloc ejit_bner(struct ejit_func *s, struct ejit_gpr r0, struct ejit_gpr r1) { diff --git a/src/interp.c b/src/interp.c index e7be77b..57dbfbe 100644 --- a/src/interp.c +++ b/src/interp.c @@ -150,6 +150,12 @@ union interp_ret ejit_run(struct ejit_func *f, size_t paramc, struct ejit_arg pa [EJIT_OP_SQRTR_F] = &&SQRTR_F, [EJIT_OP_SQRTR_D] = &&SQRTR_D, + [EJIT_OP_MINR_F] = &&MINR_F, + [EJIT_OP_MINR_D] = &&MINR_D, + + [EJIT_OP_MAXR_F] = &&MAXR_F, + [EJIT_OP_MAXR_D] = &&MAXR_D, + [EJIT_OP_BNER] = &&BNER, [EJIT_OP_BNEI] = &&BNEI, [EJIT_OP_BNER_F] = &&BNER_F, @@ -791,6 +797,22 @@ union interp_ret ejit_run(struct ejit_func *f, size_t paramc, struct ejit_arg pa fpr[i.r0].f = sqrt(fpr[i.r1].f); DISPATCH(); + DO(MINR_F); + fpr[i.r0].f = fminf(fpr[i.r1].f, fpr[i.r2].f); + DISPATCH(); + + DO(MINR_D); + fpr[i.r0].d = fmin(fpr[i.r1].d, fpr[i.r2].d); + DISPATCH(); + + DO(MAXR_F); + fpr[i.r0].f = fmaxf(fpr[i.r1].f, fpr[i.r2].f); + DISPATCH(); + + DO(MAXR_D); + fpr[i.r0].d = fmax(fpr[i.r1].d, fpr[i.r2].d); + DISPATCH(); + DO(SQRTR_D); fpr[i.r0].d = sqrt(fpr[i.r1].d); DISPATCH(); diff --git a/tests/maxr_d.c b/tests/maxr_d.c new file mode 100644 index 0000000..3e35665 --- /dev/null +++ b/tests/maxr_d.c @@ -0,0 +1,28 @@ +#include +#include +#include "do_jit.h" + +int main(int argc, char *argv[]) +{ + (void)argv; + bool do_jit = argc > 1; + struct ejit_operand operands[2] = { + EJIT_OPERAND_FPR(0, EJIT_TYPE(double)), + EJIT_OPERAND_FPR(1, EJIT_TYPE(double)) + }; + + struct ejit_func *f = ejit_create_func(EJIT_TYPE(double), 2, operands); + + ejit_maxr_d(f, EJIT_FPR(2), EJIT_FPR(0), EJIT_FPR(1)); + ejit_retr_d(f, EJIT_FPR(2)); + + ejit_select_compile_func(f, 0, 3, EJIT_USE64(double), do_jit, true); + + assert(erfd2(f, EJIT_ARG(42., double), EJIT_ARG(69., double) + ) == 69.); + + assert(erfd2(f, EJIT_ARG(-42., double), EJIT_ARG(-69., double) + ) == -42.); + + ejit_destroy_func(f); +} diff --git a/tests/maxr_f.c b/tests/maxr_f.c new file mode 100644 index 0000000..581f867 --- /dev/null +++ b/tests/maxr_f.c @@ -0,0 +1,28 @@ +#include +#include +#include "do_jit.h" + +int main(int argc, char *argv[]) +{ + (void)argv; + bool do_jit = argc > 1; + struct ejit_operand operands[2] = { + EJIT_OPERAND_FPR(0, EJIT_TYPE(float)), + EJIT_OPERAND_FPR(1, EJIT_TYPE(float)) + }; + + struct ejit_func *f = ejit_create_func(EJIT_TYPE(float), 2, operands); + + ejit_maxr_f(f, EJIT_FPR(2), EJIT_FPR(0), EJIT_FPR(1)); + ejit_retr_f(f, EJIT_FPR(2)); + + ejit_select_compile_func(f, 0, 3, EJIT_USE64(float), do_jit, true); + + assert(erff2(f, EJIT_ARG(42., float), EJIT_ARG(69., float) + ) == 69.); + + assert(erff2(f, EJIT_ARG(-42., float), EJIT_ARG(-69., float) + ) == -42.); + + ejit_destroy_func(f); +} diff --git a/tests/minr_d.c b/tests/minr_d.c new file mode 100644 index 0000000..d0fb7c8 --- /dev/null +++ b/tests/minr_d.c @@ -0,0 +1,28 @@ +#include +#include +#include "do_jit.h" + +int main(int argc, char *argv[]) +{ + (void)argv; + bool do_jit = argc > 1; + struct ejit_operand operands[2] = { + EJIT_OPERAND_FPR(0, EJIT_TYPE(double)), + EJIT_OPERAND_FPR(1, EJIT_TYPE(double)) + }; + + struct ejit_func *f = ejit_create_func(EJIT_TYPE(double), 2, operands); + + ejit_minr_d(f, EJIT_FPR(2), EJIT_FPR(0), EJIT_FPR(1)); + ejit_retr_d(f, EJIT_FPR(2)); + + ejit_select_compile_func(f, 0, 3, EJIT_USE64(double), do_jit, true); + + assert(erfd2(f, EJIT_ARG(42., double), EJIT_ARG(69., double) + ) == 42.); + + assert(erfd2(f, EJIT_ARG(-42., double), EJIT_ARG(-69., double) + ) == -69.); + + ejit_destroy_func(f); +} diff --git a/tests/minr_f.c b/tests/minr_f.c new file mode 100644 index 0000000..b02ec06 --- /dev/null +++ b/tests/minr_f.c @@ -0,0 +1,28 @@ +#include +#include +#include "do_jit.h" + +int main(int argc, char *argv[]) +{ + (void)argv; + bool do_jit = argc > 1; + struct ejit_operand operands[2] = { + EJIT_OPERAND_FPR(0, EJIT_TYPE(float)), + EJIT_OPERAND_FPR(1, EJIT_TYPE(float)) + }; + + struct ejit_func *f = ejit_create_func(EJIT_TYPE(float), 2, operands); + + ejit_minr_f(f, EJIT_FPR(2), EJIT_FPR(0), EJIT_FPR(1)); + ejit_retr_f(f, EJIT_FPR(2)); + + ejit_select_compile_func(f, 0, 3, EJIT_USE64(float), do_jit, true); + + assert(erff2(f, EJIT_ARG(42., float), EJIT_ARG(69., float) + ) == 42.); + + assert(erff2(f, EJIT_ARG(-42., float), EJIT_ARG(-69., float) + ) == -69.); + + ejit_destroy_func(f); +} -- cgit v1.2.3 From 9e367e1824d62d3759cb19b7c9a433b67b96bd99 Mon Sep 17 00:00:00 2001 From: Kimplul Date: Tue, 8 Apr 2025 22:36:15 +0300 Subject: clean up interpreter a bit --- src/ejit.c | 4 ++-- src/interp.c | 35 +++++++++++------------------------ 2 files changed, 13 insertions(+), 26 deletions(-) (limited to 'src/ejit.c') diff --git a/src/ejit.c b/src/ejit.c index c997a01..571a274 100644 --- a/src/ejit.c +++ b/src/ejit.c @@ -459,7 +459,7 @@ void ejit_patch(struct ejit_func *f, struct ejit_reloc r, struct ejit_label l) void ejit_calli_i(struct ejit_func *s, struct ejit_func *f, size_t argc, const struct ejit_operand args[argc]) { - f->max_args = argc > f->max_args ? argc : f->max_args; + s->max_args = argc > s->max_args ? argc : s->max_args; check_operands(f, argc, args); for (size_t i = 0; i < argc; ++i) { @@ -479,7 +479,7 @@ void ejit_calli_l(struct ejit_func *s, struct ejit_func *f, size_t argc, const struct ejit_operand args[argc]) { s->use_64 = true; - f->max_args = argc > f->max_args ? argc : f->max_args; + s->max_args = argc > s->max_args ? argc : s->max_args; check_operands(f, argc, args); for (size_t i = 0; i < argc; ++i) { diff --git a/src/interp.c b/src/interp.c index 57dbfbe..6ef414d 100644 --- a/src/interp.c +++ b/src/interp.c @@ -228,7 +228,7 @@ union interp_ret ejit_run(struct ejit_func *f, size_t paramc, struct ejit_arg pa if (!run) { *labels_wb = labels; - goto zero_out; + return (union interp_ret){.i = 0}; } assert(f->size && "trying to run a function that hasn't been compiled"); @@ -262,9 +262,9 @@ union interp_ret ejit_run(struct ejit_func *f, size_t paramc, struct ejit_arg pa }; size_t argc = 0; - int64_t *gpr = alloca(sizeof(int64_t) * gpr_stats_len(&f->gpr)); - union fpr *fpr = alloca(sizeof(int64_t) * fpr_stats_len(&f->fpr)); - struct ejit_arg *args = alloca(sizeof(struct ejit_arg) * f->max_args); + int64_t gpr[gpr_stats_len(&f->gpr)]; + union fpr fpr[fpr_stats_len(&f->fpr)]; + struct ejit_arg args[f->max_args]; struct ejit_insn *insns = f->insns.buf; /* retval is kind of an unfortunate extra bit of state to keep track of, @@ -282,7 +282,7 @@ union interp_ret ejit_run(struct ejit_func *f, size_t paramc, struct ejit_arg pa DISPATCH(); DO(END); - goto zero_out; + return (union interp_ret){.i = 0}; DISPATCH(); DO(MOVI); @@ -1109,45 +1109,32 @@ union interp_ret ejit_run(struct ejit_func *f, size_t paramc, struct ejit_arg pa /* dispatch is technically unnecessary for returns, but keep it for * symmetry */ DO(RETR); - retval = gpr[i.r1]; - goto out_int; + return (union interp_ret){.i = gpr[i.r1]}; DISPATCH(); DO(RETI); - retval = i.o; - goto out_int; + return (union interp_ret){.i = i.o}; DISPATCH(); DO(RETR_F); - retval_f = fpr[i.r1].f; - goto out_float; + return (union interp_ret){.f = fpr[i.r1].f}; DISPATCH(); DO(RETR_D); - retval_f = fpr[i.r1].d; - goto out_float; + return (union interp_ret){.f = fpr[i.r1].d}; DISPATCH(); DO(RETI_F); - retval_f = i.f; - goto out_float; + return (union interp_ret){.f = i.f}; DISPATCH(); DO(RETI_D); - retval_f = i.d; - goto out_float; + return (union interp_ret){.f = i.d}; DISPATCH(); #undef DISPATCH #undef JUMP #undef DO -out_float: - return (union interp_ret){.f = retval_f}; - -out_int: - return (union interp_ret){.i = retval}; - -zero_out: return (union interp_ret){.i = 0}; } -- cgit v1.2.3 From 6824dd4b1ee22184f0e600115db3998924ed39d6 Mon Sep 17 00:00:00 2001 From: Kimplul Date: Wed, 9 Apr 2025 19:56:33 +0300 Subject: initial tail call stuff --- .gitignore | 1 + deps/lightening | 2 +- examples/fib.c | 4 +- examples/sum.c | 78 +++++++++++++++++++++++++++++++++++++ include/ejit/ejit.h | 12 ++---- scripts/makefile | 5 ++- src/common.h | 7 +--- src/compile/compile.c | 106 ++++++++++++++++++++++++++++++++++++++++++-------- src/ejit.c | 79 ++++++++++++++----------------------- src/interp.c | 58 +++++++++++++-------------- 10 files changed, 236 insertions(+), 116 deletions(-) create mode 100644 examples/sum.c (limited to 'src/ejit.c') diff --git a/.gitignore b/.gitignore index 93b2293..50343e4 100644 --- a/.gitignore +++ b/.gitignore @@ -7,4 +7,5 @@ test-* examples/matrix_mult examples/loop examples/fib +examples/sum examples/*.d diff --git a/deps/lightening b/deps/lightening index 8d59c87..3f4127c 160000 --- a/deps/lightening +++ b/deps/lightening @@ -1 +1 @@ -Subproject commit 8d59c872edc5a21e7dd78768b291d0c4d8136e48 +Subproject commit 3f4127c3ef16177be55cf6153a206ca4f8a4859f diff --git a/examples/fib.c b/examples/fib.c index 999546b..fcb0659 100644 --- a/examples/fib.c +++ b/examples/fib.c @@ -20,12 +20,12 @@ struct ejit_func *compile(bool try_jit, bool im_scawed) struct ejit_operand arg[1] = { EJIT_OPERAND_GPR(0, EJIT_INT32) }; - ejit_calli_i(f, f, 1, arg); + ejit_calli(f, f, 1, arg); ejit_retval(f, EJIT_GPR(1)); /* loc 1 contains temp result */ /* fib(n - 2) */ ejit_subi(f, EJIT_GPR(0), EJIT_GPR(0), 1); - ejit_calli_i(f, f, 1, arg); + ejit_calli(f, f, 1, arg); ejit_retval(f, EJIT_GPR(0)); /* loc 0 now contains second temp result */ ejit_addr(f, EJIT_GPR(0), EJIT_GPR(0), EJIT_GPR(1)); /* add results */ diff --git a/examples/sum.c b/examples/sum.c new file mode 100644 index 0000000..cc8f54b --- /dev/null +++ b/examples/sum.c @@ -0,0 +1,78 @@ +#include +#include + +#include "../include/ejit/ejit.h" + +struct ejit_func *compile(bool try_jit, bool im_scawed) +{ + struct ejit_operand params[2] = { + EJIT_OPERAND_GPR(0, EJIT_INT32), /* loc 0 contains s */ + EJIT_OPERAND_GPR(1, EJIT_INT32) /* loc 1 contains n */ + }; + struct ejit_func *f = ejit_create_func(EJIT_INT32, 2, params); + + /* n == 0, return s */ + struct ejit_reloc recurse = ejit_bnei(f, EJIT_GPR(1), 0); + ejit_retr(f, EJIT_GPR(0)); + ejit_patch(f, recurse, ejit_label(f)); + + /* s += n */ + ejit_addr(f, EJIT_GPR(0), EJIT_GPR(0), EJIT_GPR(1)); + + /* n -= 1 */ + ejit_subi(f, EJIT_GPR(1), EJIT_GPR(1), 1); + + struct ejit_operand args[2] = { + EJIT_OPERAND_GPR(0, EJIT_INT32), /* s */ + EJIT_OPERAND_GPR(1, EJIT_INT32) /* n */ + }; + + /* recurse */ + ejit_movi(f, EJIT_GPR(2), (uintptr_t)f); + ejit_tailr(f, EJIT_GPR(2), 2, args); + + ejit_select_compile_func(f, 3, 0, EJIT_USE64(uintptr_t), try_jit, im_scawed); + return f; +} + +int main(int argc, char *argv[]) +{ + if(argc != 4){ + fprintf(stderr, "Usage: %s compile_num loop_num jit\n", argv[0]); + return -1; + } + + int jit_level = strtoull(argv[3], 0, 0); + size_t compile_num = strtoull(argv[1], 0, 0); + struct ejit_func **info = calloc(compile_num, sizeof(struct ejit_func *)); + + clock_t t = clock(); + for(size_t i = 0; i < compile_num; ++i){ + info[i] = compile(jit_level > 0, jit_level > 1); + } + t = clock() - t; + + double compile_time_total = ((double)t) / CLOCKS_PER_SEC; + double compile_time_one = compile_time_total / compile_num; + printf("Compilation for n = %zu took %fs (1/%f).\n", + compile_num, compile_time_total, compile_time_one); + + size_t run_num = strtoull(argv[2], 0, 0); + t = clock(); + struct ejit_arg args[2] = { + (struct ejit_arg){.type = EJIT_INT32, .l = 0}, /* s */ + (struct ejit_arg){.type = EJIT_INT32, .l = run_num} /* n */ + }; + int32_t result = ejit_run_func_i(info[0], 2, args); + t = clock() - t; + + double run_time_total = ((double)t) / CLOCKS_PER_SEC; + printf("Running loop for n = %zu took %fs with res %ld\n", + run_num, run_time_total, (long)result); + + for(size_t i = 0; i < compile_num; ++i) + ejit_destroy_func(info[i]); + + free(info); + return 0; +} diff --git a/include/ejit/ejit.h b/include/ejit/ejit.h index 965103c..aa42eca 100644 --- a/include/ejit/ejit.h +++ b/include/ejit/ejit.h @@ -454,18 +454,12 @@ 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_calli_l(struct ejit_func *s, struct ejit_func *f, size_t argc, +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_calli_d(struct ejit_func *s, struct ejit_func *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]); diff --git a/scripts/makefile b/scripts/makefile index 5178359..dbb7a1c 100644 --- a/scripts/makefile +++ b/scripts/makefile @@ -65,7 +65,7 @@ COMPILE_EJIT = $(COMPILE) $(EJIT_FLAGS) libejit.a: $(EJIT_OBJS) $(CROSS_COMPILE)ar rcs libejit.a $(EJIT_OBJS) -examples: examples/loop examples/fib examples/matrix_mult +examples: examples/loop examples/fib examples/sum examples/matrix_mult examples/matrix_mult: examples/matrix_mult.c libejit.a $(COMPILE_EJIT) examples/matrix_mult.c libejit.a -o $@ -lm @@ -76,6 +76,9 @@ examples/loop: examples/loop.c libejit.a examples/fib: examples/fib.c libejit.a $(COMPILE_EJIT) examples/fib.c libejit.a -o $@ -lm +examples/sum: examples/sum.c libejit.a + $(COMPILE_EJIT) examples/sum.c libejit.a -o $@ -lm + # might lint some common things twice .PHONY: lint: $(TRISCV_LINTS) diff --git a/src/common.h b/src/common.h index 69f1441..3512717 100644 --- a/src/common.h +++ b/src/common.h @@ -218,10 +218,8 @@ enum ejit_opcode { EJIT_OP_ESCAPEI_F, EJIT_OP_ESCAPEI_D, - EJIT_OP_CALLI_I, - EJIT_OP_CALLI_L, - EJIT_OP_CALLI_F, - EJIT_OP_CALLI_D, + EJIT_OP_CALLI, + EJIT_OP_TAILR, EJIT_OP_RETR, EJIT_OP_RETI, @@ -308,7 +306,6 @@ union interp_ret { union interp_ret ejit_run(struct ejit_func *f, size_t argc, struct ejit_arg args[argc], - bool run, void ***labels_wb); bool ejit_compile(struct ejit_func *f, bool use_64, bool im_scawed); diff --git a/src/compile/compile.c b/src/compile/compile.c index dcf662b..54d79f2 100644 --- a/src/compile/compile.c +++ b/src/compile/compile.c @@ -22,22 +22,22 @@ struct reloc_helper { /* skip assertions since we know they must be valid due to type checking earlier */ static long checked_run_i(struct ejit_func *f, size_t argc, struct ejit_arg args[argc]) { - return ejit_run(f, argc, args, true, NULL).i; + return ejit_run(f, argc, args, NULL).i; } static int64_t checked_run_l(struct ejit_func *f, size_t argc, struct ejit_arg args[argc]) { - return ejit_run(f, argc, args, true, NULL).i; + return ejit_run(f, argc, args, NULL).i; } static float checked_run_f(struct ejit_func *f, size_t argc, struct ejit_arg args[argc]) { - return ejit_run(f, argc, args, true, NULL).f; + return ejit_run(f, argc, args, NULL).f; } static double checked_run_d(struct ejit_func *f, size_t argc, struct ejit_arg args[argc]) { - return ejit_run(f, argc, args, true, NULL).f; + return ejit_run(f, argc, args, NULL).f; } static void *alloc_arena(size_t size, bool im_scawed) @@ -47,6 +47,11 @@ static void *alloc_arena(size_t size, bool im_scawed) MAP_PRIVATE | MAP_ANONYMOUS, -1, 0); } +static void assert_helper(const char *msg) +{ + assert(false && msg); +} + static void free_arena(void *arena, size_t size) { munmap(arena, size); @@ -2042,8 +2047,6 @@ static size_t compile_fn_body(struct ejit_func *f, jit_state_t *j, void *arena, struct addrs addrs = addrs_create(); addrs_reserve(&addrs, insns_len(&f->insns)); - void *call = NULL; - size_t label = 0; foreach_vec(ii, f->insns) { /* if we've hit a label, add it to our vector of label addresses */ @@ -2502,21 +2505,64 @@ static size_t compile_fn_body(struct ejit_func *f, jit_state_t *j, void *arena, break; } - case EJIT_OP_CALLI_L: -#if __WORDSIZE == 64 - call = checked_run_l; goto calli; -#else - assert(0 && "trying to compile calli_l on 32bit arch"); - break; + case EJIT_OP_TAILR: { + /* this is admittedly a slightly roundabout way of + * implementing tail calls and is arguably not the most + * performant way (if it works at all, heh) but for now + * I'm more interested in functionality than raw + * performance. Currently only supports two gpr + * registers, but should be fairly easy to extend with + * fprs as well */ + + assert(operands_len(&direct) <= 2); + jit_gpr_t r = getloc(f, j, i.r1, 0); + jit_ldxi(j, JIT_R0, r, offsetof(struct ejit_func, direct_call)); +#if defined(DEBUG) + jit_reloc_t assert_reloc = jit_bnei(j, JIT_R0, 0); /* null */ + jit_calli_1(j, assert_helper, + jit_operand_imm(JIT_OPERAND_ABI_POINTER, + (jit_imm_t)"trying to tail call interpreted function")); + jit_patch_here(j, assert_reloc); #endif + jit_operand_t regs[2] = { + jit_operand_gpr(JIT_OPERAND_ABI_WORD, JIT_R1), + jit_operand_gpr(JIT_OPERAND_ABI_WORD, JIT_R2) + }; + jit_move_operands(j, regs, direct.buf, operands_len(&direct)); + + /* with args safely in registers, reset stack/state + * while avoiding overwriting the call target */ + jit_gpr_t tmp = get_callr_temp(j); + jit_movr(j, tmp, JIT_R0); + + int frame_size = j->frame_size; + jit_shrink_stack(j, stack); + jit_leave_jit_abi(j, gprs, fprs, frame); + + /* now move args into place */ + jit_operand_t args[2] = {}; + foreach_vec(oi, direct) { + args[oi] = *operands_at(&direct, oi); + } - case EJIT_OP_CALLI_F: { call = checked_run_f; goto calli; } - case EJIT_OP_CALLI_D: { call = checked_run_d; goto calli; } - case EJIT_OP_CALLI_I: { call = checked_run_i; goto calli; -calli: + jit_locate_args(j, operands_len(&direct), args); + jit_move_operands(j, args, regs, operands_len(&direct)); + jit_jmpr(j, tmp); + j->frame_size = frame_size; + + operands_reset(&src); + operands_reset(&dst); + operands_reset(&direct); + break; + } + + case EJIT_OP_CALLI: { save_caller_save_regs(f, j); struct ejit_func *f = (struct ejit_func *)(uintptr_t)i.o; +#if __WORDSIZE != 64 + assert(f->rtype != EJIT_INT64 && f->rtype != EJIT_UINT64); +#endif if (f && f->direct_call) { jit_calli(j, f->direct_call, operands_len(&direct), direct.buf); restore_caller_save_regs(f, j); @@ -2535,6 +2581,16 @@ calli: * argument stack address */ jit_operand_gpr(JIT_OPERAND_ABI_POINTER, JIT_R0) }; + + void *call = NULL; + switch (f->rtype) { + case EJIT_INT64: + case EJIT_UINT64: call = checked_run_l; break; + case EJIT_FLOAT: call = checked_run_f; break; + case EJIT_DOUBLE: call = checked_run_d; break; + default: call = checked_run_i; break; + } + compile_imm_call(j, &src, &dst, call, 3, args); restore_caller_save_regs(f, j); @@ -2552,39 +2608,55 @@ calli: jit_gpr_t r = getloc(f, j, i.r1, 0); /* R0 won't get overwritten by jit_leave_jit_abi */ jit_movr(j, JIT_R0, r); + + /* keep track of frame size so we can continue + * generating code after 'leaving' the ABI. Bit of a + * hack, should maybe codify this better in the + * lightening API? */ + int frame_size = j->frame_size; jit_shrink_stack(j, stack); jit_leave_jit_abi(j, gprs, fprs, frame); jit_retr(j, JIT_R0); + j->frame_size = frame_size; break; } case EJIT_OP_RETR_F: { jit_fpr_t r = getloc_f(f, j, i.r1, 0); jit_movr_f(j, JIT_F0, r); + + int frame_size = j->frame_size; jit_shrink_stack(j, stack); jit_leave_jit_abi(j, gprs, fprs, frame); jit_retr_f(j, JIT_F0); + j->frame_size = frame_size; break; } case EJIT_OP_RETR_D: { jit_fpr_t r = getloc_d(f, j, i.r1, 0); jit_movr_d(j, JIT_F0, r); + + int frame_size = j->frame_size; jit_shrink_stack(j, stack); jit_leave_jit_abi(j, gprs, fprs, frame); jit_retr_d(j, JIT_F0); + j->frame_size = frame_size; break; } case EJIT_OP_RETI: { + int frame_size = j->frame_size; jit_shrink_stack(j, stack); jit_leave_jit_abi(j, gprs, fprs, frame); jit_reti(j, i.o); + j->frame_size = frame_size; break; } case EJIT_OP_END: { - /* 'void' return */ + /* 'void' return, must be last thing in function so no + * need to keep track of frame size */ jit_shrink_stack(j, stack); jit_leave_jit_abi(j, gprs, fprs, frame); jit_reti(j, 0); diff --git a/src/ejit.c b/src/ejit.c index 571a274..059d5d4 100644 --- a/src/ejit.c +++ b/src/ejit.c @@ -414,7 +414,7 @@ void ejit_select_compile_func(struct ejit_func *f, size_t gpr, size_t fpr, void **labels; /* just get labels, don't actually run anything yet */ - ejit_run(f, 0, NULL, false, &labels); + ejit_run(f, 0, NULL, &labels); foreach_vec(ii, f->insns) { struct ejit_insn i = *insns_at(&f->insns, ii); @@ -456,67 +456,48 @@ void ejit_patch(struct ejit_func *f, struct ejit_reloc r, struct ejit_label l) *insns_at(&f->insns, r.insn) = i; } -void ejit_calli_i(struct ejit_func *s, struct ejit_func *f, size_t argc, +void ejit_tailr(struct ejit_func *s, struct ejit_gpr target, size_t argc, const struct ejit_operand args[argc]) { s->max_args = argc > s->max_args ? argc : s->max_args; - check_operands(f, argc, args); + /** @todo check that gpr_args <= 2 and fpr_args <= 3 (?) */ + size_t gpr_args = 0, fpr_args = 0; for (size_t i = 0; i < argc; ++i) { switch (args[i].kind) { - case EJIT_OPERAND_GPR: emit_insn_ar(s, EJIT_OP_ARG, i, args[i].type, EJIT_GPR(args[i].r)); break; - case EJIT_OPERAND_FPR: emit_insn_af(s, EJIT_OP_ARG_F, i, args[i].type, EJIT_FPR(args[i].r)); break; - case EJIT_OPERAND_IMM: emit_insn_ai(s, EJIT_OP_ARG_I, i, args[i].type, args[i].r); break; - case EJIT_OPERAND_FLT: emit_insn_ad(s, EJIT_OP_ARG_FI, i, args[i].type, args[i].d); break; - default: abort(); - } - } - - emit_insn_op(s, EJIT_OP_CALLI_I, f); -} - -void ejit_calli_l(struct ejit_func *s, struct ejit_func *f, size_t argc, - const struct ejit_operand args[argc]) -{ - s->use_64 = true; - s->max_args = argc > s->max_args ? argc : s->max_args; - check_operands(f, argc, args); + case EJIT_OPERAND_GPR: + gpr_args++; + emit_insn_ar(s, EJIT_OP_ARG, i, args[i].type, EJIT_GPR(args[i].r)); + break; - for (size_t i = 0; i < argc; ++i) { - switch (args[i].kind) { - case EJIT_OPERAND_GPR: emit_insn_ar(s, EJIT_OP_ARG, i, args[i].type, EJIT_GPR(args[i].r)); break; - case EJIT_OPERAND_FPR: emit_insn_af(s, EJIT_OP_ARG_F, i, args[i].type, EJIT_FPR(args[i].r)); break; - case EJIT_OPERAND_IMM: emit_insn_ai(s, EJIT_OP_ARG_I, i, args[i].type, args[i].r); break; - case EJIT_OPERAND_FLT: emit_insn_ad(s, EJIT_OP_ARG_FI, i, args[i].type, args[i].d); break; - default: abort(); - } - } + case EJIT_OPERAND_FPR: + fpr_args++; + emit_insn_af(s, EJIT_OP_ARG_F, i, args[i].type, EJIT_FPR(args[i].r)); + break; - emit_insn_op(s, EJIT_OP_CALLI_L, f); -} + case EJIT_OPERAND_IMM: + gpr_args++; + emit_insn_ai(s, EJIT_OP_ARG_I, i, args[i].type, args[i].r); + break; -void ejit_calli_f(struct ejit_func *s, struct ejit_func *f, size_t argc, - const struct ejit_operand args[argc]) -{ - s->max_args = argc > s->max_args ? argc : s->max_args; - check_operands(f, argc, args); + case EJIT_OPERAND_FLT: + fpr_args++; + emit_insn_ad(s, EJIT_OP_ARG_FI, i, args[i].type, args[i].d); + break; - for (size_t i = 0; i < argc; ++i) { - switch (args[i].kind) { - case EJIT_OPERAND_GPR: emit_insn_ar(s, EJIT_OP_ARG, i, args[i].type, EJIT_GPR(args[i].r)); break; - case EJIT_OPERAND_FPR: emit_insn_af(s, EJIT_OP_ARG_F, i, args[i].type, EJIT_FPR(args[i].r)); break; - case EJIT_OPERAND_IMM: emit_insn_ai(s, EJIT_OP_ARG_I, i, args[i].type, args[i].r); break; - case EJIT_OPERAND_FLT: emit_insn_ad(s, EJIT_OP_ARG_FI, i, args[i].type, args[i].d); break; default: abort(); } } - emit_insn_op(s, EJIT_OP_CALLI_F, f); + assert(gpr_args <= 2 && fpr_args == 0 + && "only 2 gpr args and 0 fpr args supported in tail calls for now"); + emit_insn_oxr(s, EJIT_OP_TAILR, target); } -void ejit_calli_d(struct ejit_func *s, struct ejit_func *f, size_t argc, +void ejit_calli(struct ejit_func *s, struct ejit_func *f, size_t argc, const struct ejit_operand args[argc]) { + s->use_64 = f->rtype == EJIT_INT64 || f->rtype == EJIT_UINT64; s->max_args = argc > s->max_args ? argc : s->max_args; check_operands(f, argc, args); @@ -530,7 +511,7 @@ void ejit_calli_d(struct ejit_func *s, struct ejit_func *f, size_t argc, } } - emit_insn_op(s, EJIT_OP_CALLI_D, f); + emit_insn_op(s, EJIT_OP_CALLI, f); } void ejit_escapei_i(struct ejit_func *s, ejit_escape_i_t f, size_t argc, @@ -1712,7 +1693,7 @@ long ejit_run_func_i(struct ejit_func *f, size_t argc, #endif ); - return ejit_run(f, argc, args, true, NULL).i; + return ejit_run(f, argc, args, NULL).i; } int64_t ejit_run_func_l(struct ejit_func *f, size_t argc, @@ -1720,21 +1701,21 @@ int64_t ejit_run_func_l(struct ejit_func *f, size_t argc, { check_args(f, argc, args); assert(f->rtype == EJIT_INT64 || f->rtype == EJIT_UINT64); - return ejit_run(f, argc, args, true, NULL).i; + return ejit_run(f, argc, args, NULL).i; } float ejit_run_func_f(struct ejit_func *f, size_t argc, struct ejit_arg args[argc]) { check_args(f, argc, args); assert(f->rtype == EJIT_FLOAT); - return ejit_run(f, argc, args, true, NULL).f; + return ejit_run(f, argc, args, NULL).f; } double ejit_run_func_d(struct ejit_func *f, size_t argc, struct ejit_arg args[argc]) { check_args(f, argc, args); assert(f->rtype == EJIT_DOUBLE); - return ejit_run(f, argc, args, true, NULL).f; + return ejit_run(f, argc, args, NULL).f; } struct ejit_arg ejit_run_func(struct ejit_func *f, size_t argc, struct ejit_arg args[argc]) diff --git a/src/interp.c b/src/interp.c index 6ef414d..132ba4a 100644 --- a/src/interp.c +++ b/src/interp.c @@ -5,7 +5,7 @@ /* this is the body of a given ejit_interp function, it assumes there's an * external int64_t retval and double retval_f into which it places the value to * be returned. Included from src/interp.c */ -union interp_ret ejit_run(struct ejit_func *f, size_t paramc, struct ejit_arg params[paramc], bool run, void ***labels_wb) +union interp_ret ejit_run(struct ejit_func *f, size_t paramc, struct ejit_arg params[paramc], void ***labels_wb) { static void *labels[EJIT_OPCODE_COUNT] = { [EJIT_OP_MOVI] = &&MOVI, @@ -213,10 +213,9 @@ union interp_ret ejit_run(struct ejit_func *f, size_t paramc, struct ejit_arg pa [EJIT_OP_PARAM] = &&PARAM, [EJIT_OP_PARAM_F] = &&PARAM_F, - [EJIT_OP_CALLI_I] = &&CALLI_I, - [EJIT_OP_CALLI_L] = &&CALLI_L, - [EJIT_OP_CALLI_F] = &&CALLI_F, - [EJIT_OP_CALLI_D] = &&CALLI_D, + [EJIT_OP_CALLI] = &&CALLI, + [EJIT_OP_TAILR] = &&TAILR, + [EJIT_OP_ESCAPEI_I] = &&ESCAPEI_I, [EJIT_OP_ESCAPEI_F] = &&ESCAPEI_F, [EJIT_OP_ESCAPEI_L] = &&ESCAPEI_L, @@ -226,13 +225,12 @@ union interp_ret ejit_run(struct ejit_func *f, size_t paramc, struct ejit_arg pa [EJIT_OP_END] = &&END, }; - if (!run) { + if (labels_wb) { *labels_wb = labels; return (union interp_ret){.i = 0}; } assert(f->size && "trying to run a function that hasn't been compiled"); - if (f->extern_call) { if (f->rtype == EJIT_INT64 || f->rtype == EJIT_UINT64) return (union interp_ret){ @@ -254,8 +252,8 @@ union interp_ret ejit_run(struct ejit_func *f, size_t paramc, struct ejit_arg pa }; } - int64_t retval = 0; double retval_f = 0.0; - +top: + union interp_ret retval = {.i = 0}; union fpr { double d; float f; @@ -994,15 +992,15 @@ union interp_ret ejit_run(struct ejit_func *f, size_t paramc, struct ejit_arg pa DISPATCH(); DO(RETVAL); - gpr[i.r0] = retval; + gpr[i.r0] = retval.i; DISPATCH(); DO(RETVAL_F); - fpr[i.r0].f = retval_f; + fpr[i.r0].f = retval.f; DISPATCH(); DO(RETVAL_D); - fpr[i.r0].d = retval_f; + fpr[i.r0].d = retval.f; DISPATCH(); DO(PARAM); @@ -1058,51 +1056,47 @@ union interp_ret ejit_run(struct ejit_func *f, size_t paramc, struct ejit_arg pa args[argc++] = a; DISPATCH(); - DO(CALLI_I); - struct ejit_func *f = i.p; - retval = ejit_run(f, argc, args, true, NULL).i; - argc = 0; - DISPATCH(); + DO(TAILR); + f = (struct ejit_func *)gpr[i.r1]; - DO(CALLI_L); - struct ejit_func *f = i.p; - retval = ejit_run(f, argc, args, true, NULL).i; - argc = 0; - DISPATCH(); + /** @todo we could potentially just interpret the func as a fallback + * instead of aborting here, but this is good enough for now */ + assert(!f->direct_call && "trying to interpret compiled fun"); - DO(CALLI_F); - struct ejit_func *f = i.p; - retval_f = ejit_run(f, argc, args, true, NULL).f; - argc = 0; + paramc = argc; + for (size_t i = 0; i < argc; ++i) + params[i] = args[i]; + + goto top; DISPATCH(); - DO(CALLI_D); + DO(CALLI); struct ejit_func *f = i.p; - retval_f = ejit_run(f, argc, args, true, NULL).f; + retval = ejit_run(f, argc, args, NULL); argc = 0; DISPATCH(); DO(ESCAPEI_I); ejit_escape_i_t f = i.p; - retval = f(argc, args); + retval.i = f(argc, args); argc = 0; DISPATCH(); DO(ESCAPEI_L); ejit_escape_l_t f = i.p; - retval = f(argc, args); + retval.i = f(argc, args); argc = 0; DISPATCH(); DO(ESCAPEI_F); ejit_escape_f_t f = i.p; - retval_f = f(argc, args); + retval.f = f(argc, args); argc = 0; DISPATCH(); DO(ESCAPEI_D); ejit_escape_d_t f = i.p; - retval_f = f(argc, args); + retval.f = f(argc, args); argc = 0; DISPATCH(); -- cgit v1.2.3 From 057131cb20fb1c46e90adecfb4a16eb62f100580 Mon Sep 17 00:00:00 2001 From: Kimplul Date: Wed, 9 Apr 2025 20:20:48 +0300 Subject: add taili --- include/ejit/ejit.h | 3 +++ src/common.h | 2 ++ src/compile/compile.c | 35 +++++++++++++++++++++++++++++++++++ src/ejit.c | 44 +++++++++++++++++++++++++++++++++++++++++++- src/interp.c | 14 ++++++++++++++ tests/taili.c | 39 +++++++++++++++++++++++++++++++++++++++ tests/tailr.c | 41 +++++++++++++++++++++++++++++++++++++++++ 7 files changed, 177 insertions(+), 1 deletion(-) create mode 100644 tests/taili.c create mode 100644 tests/tailr.c (limited to 'src/ejit.c') diff --git a/include/ejit/ejit.h b/include/ejit/ejit.h index aa42eca..5baaab6 100644 --- a/include/ejit/ejit.h +++ b/include/ejit/ejit.h @@ -457,6 +457,9 @@ struct ejit_label ejit_label(struct ejit_func *s); 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(struct ejit_func *s, struct ejit_func *f, size_t argc, const struct ejit_operand args[argc]); diff --git a/src/common.h b/src/common.h index 3512717..333c794 100644 --- a/src/common.h +++ b/src/common.h @@ -219,7 +219,9 @@ enum ejit_opcode { EJIT_OP_ESCAPEI_D, EJIT_OP_CALLI, + EJIT_OP_TAILR, + EJIT_OP_TAILI, EJIT_OP_RETR, EJIT_OP_RETI, diff --git a/src/compile/compile.c b/src/compile/compile.c index 54d79f2..60059d5 100644 --- a/src/compile/compile.c +++ b/src/compile/compile.c @@ -2505,6 +2505,40 @@ static size_t compile_fn_body(struct ejit_func *f, jit_state_t *j, void *arena, break; } + case EJIT_OP_TAILI: { + /* a bit of copy-paste between this and the next func, + * hmm */ + assert(operands_len(&direct) <= 2); + struct ejit_func *f = (struct ejit_func *)(uintptr_t)i.o; + assert(f->direct_call); + + jit_operand_t regs[2] = { + jit_operand_gpr(JIT_OPERAND_ABI_WORD, JIT_R1), + jit_operand_gpr(JIT_OPERAND_ABI_WORD, JIT_R2) + }; + jit_move_operands(j, regs, direct.buf, operands_len(&direct)); + + int frame_size = j->frame_size; + jit_shrink_stack(j, stack); + jit_leave_jit_abi(j, gprs, fprs, frame); + + /* now move args into place */ + jit_operand_t args[2] = {}; + foreach_vec(oi, direct) { + args[oi] = *operands_at(&direct, oi); + } + + jit_locate_args(j, operands_len(&direct), args); + jit_move_operands(j, args, regs, operands_len(&direct)); + jit_jmpi(j, f->direct_call); + j->frame_size = frame_size; + + operands_reset(&src); + operands_reset(&dst); + operands_reset(&direct); + break; + } + case EJIT_OP_TAILR: { /* this is admittedly a slightly roundabout way of * implementing tail calls and is arguably not the most @@ -2518,6 +2552,7 @@ static size_t compile_fn_body(struct ejit_func *f, jit_state_t *j, void *arena, jit_gpr_t r = getloc(f, j, i.r1, 0); jit_ldxi(j, JIT_R0, r, offsetof(struct ejit_func, direct_call)); #if defined(DEBUG) + /** @todo other checks? */ jit_reloc_t assert_reloc = jit_bnei(j, JIT_R0, 0); /* null */ jit_calli_1(j, assert_helper, jit_operand_imm(JIT_OPERAND_ABI_POINTER, diff --git a/src/ejit.c b/src/ejit.c index 059d5d4..0701b90 100644 --- a/src/ejit.c +++ b/src/ejit.c @@ -456,12 +456,54 @@ void ejit_patch(struct ejit_func *f, struct ejit_reloc r, struct ejit_label l) *insns_at(&f->insns, r.insn) = i; } +void ejit_taili(struct ejit_func *s, struct ejit_func *f, + size_t argc, const struct ejit_operand args[argc]) +{ + assert(s->rtype == f->rtype); + + s->max_args = argc > s->max_args ? argc : s->max_args; + check_operands(f, argc, args); + + size_t gpr_args = 0, fpr_args = 0; + for (size_t i = 0; i < argc; ++i) { + switch (args[i].kind) { + case EJIT_OPERAND_GPR: + gpr_args++; + emit_insn_ar(s, EJIT_OP_ARG, i, args[i].type, EJIT_GPR(args[i].r)); + break; + + case EJIT_OPERAND_FPR: + fpr_args++; + emit_insn_af(s, EJIT_OP_ARG_F, i, args[i].type, EJIT_FPR(args[i].r)); + break; + + case EJIT_OPERAND_IMM: + gpr_args++; + emit_insn_ai(s, EJIT_OP_ARG_I, i, args[i].type, args[i].r); + break; + + case EJIT_OPERAND_FLT: + fpr_args++; + emit_insn_ad(s, EJIT_OP_ARG_FI, i, args[i].type, args[i].d); + break; + + default: abort(); + } + } + + assert(gpr_args <= 2 && fpr_args == 0 + && "only 2 gpr args and 0 fpr args supported in tail calls for now"); + emit_insn_op(s, EJIT_OP_TAILI, f); +} + void ejit_tailr(struct ejit_func *s, struct ejit_gpr target, size_t argc, const struct ejit_operand args[argc]) { s->max_args = argc > s->max_args ? argc : s->max_args; - /** @todo check that gpr_args <= 2 and fpr_args <= 3 (?) */ + /* operands must match */ + check_operands(s, argc, args); + size_t gpr_args = 0, fpr_args = 0; for (size_t i = 0; i < argc; ++i) { switch (args[i].kind) { diff --git a/src/interp.c b/src/interp.c index 132ba4a..268bfb3 100644 --- a/src/interp.c +++ b/src/interp.c @@ -214,7 +214,9 @@ union interp_ret ejit_run(struct ejit_func *f, size_t paramc, struct ejit_arg pa [EJIT_OP_PARAM_F] = &&PARAM_F, [EJIT_OP_CALLI] = &&CALLI, + [EJIT_OP_TAILR] = &&TAILR, + [EJIT_OP_TAILI] = &&TAILI, [EJIT_OP_ESCAPEI_I] = &&ESCAPEI_I, [EJIT_OP_ESCAPEI_F] = &&ESCAPEI_F, @@ -1056,6 +1058,18 @@ top: args[argc++] = a; DISPATCH(); + DO(TAILI); + f = (struct ejit_func *)(uintptr_t)i.o; + + assert(!f->direct_call && "trying to interpret compiled fun"); + + paramc = argc; + for (size_t i = 0; i < argc; ++i) + params[i] = args[i]; + + goto top; + DISPATCH(); + DO(TAILR); f = (struct ejit_func *)gpr[i.r1]; diff --git a/tests/taili.c b/tests/taili.c new file mode 100644 index 0000000..cc09f59 --- /dev/null +++ b/tests/taili.c @@ -0,0 +1,39 @@ +#include +#include +#include "do_jit.h" + +int main(int argc, char *argv[]) +{ + (void)argv; + bool do_jit = argc > 1; + struct ejit_operand operands[2] = { + EJIT_OPERAND_GPR(0, EJIT_INT32), /* s */ + EJIT_OPERAND_GPR(1, EJIT_INT32) /* n */ + }; + + struct ejit_func *f = ejit_create_func(EJIT_INT32, 2, operands); + + /* n == 0, return s */ + struct ejit_reloc r = ejit_bnei(f, EJIT_GPR(1), 0); + ejit_retr(f, EJIT_GPR(0)); + ejit_patch(f, r, ejit_label(f)); + + /* s += n */ + ejit_addr(f, EJIT_GPR(0), EJIT_GPR(0), EJIT_GPR(1)); + + /* n -= 1 */ + ejit_subi(f, EJIT_GPR(1), EJIT_GPR(1), 1); + + struct ejit_operand args[2] = { + EJIT_OPERAND_GPR(0, EJIT_INT32), /* s */ + EJIT_OPERAND_GPR(1, EJIT_INT32) /* n */ + }; + ejit_taili(f, f, 2, args); + + ejit_select_compile_func(f, 2, 0, EJIT_USE64(uintptr_t), do_jit, true); + + /* arbitrary number but large enough to most likely cause a stack fault + * if the tail call leaks memory or something */ + assert((int32_t)erfi2(f, EJIT_ARG(0, int32_t), EJIT_ARG(1000000, int32_t)) == 1784293664); + ejit_destroy_func(f); +} diff --git a/tests/tailr.c b/tests/tailr.c new file mode 100644 index 0000000..69ad44b --- /dev/null +++ b/tests/tailr.c @@ -0,0 +1,41 @@ +#include +#include +#include "do_jit.h" + +int main(int argc, char *argv[]) +{ + (void)argv; + bool do_jit = argc > 1; + struct ejit_operand operands[2] = { + EJIT_OPERAND_GPR(0, EJIT_INT32), /* s */ + EJIT_OPERAND_GPR(1, EJIT_INT32) /* n */ + }; + + struct ejit_func *f = ejit_create_func(EJIT_INT32, 2, operands); + + /* n == 0, return s */ + struct ejit_reloc r = ejit_bnei(f, EJIT_GPR(1), 0); + ejit_retr(f, EJIT_GPR(0)); + ejit_patch(f, r, ejit_label(f)); + + /* s += n */ + ejit_addr(f, EJIT_GPR(0), EJIT_GPR(0), EJIT_GPR(1)); + + /* n -= 1 */ + ejit_subi(f, EJIT_GPR(1), EJIT_GPR(1), 1); + + struct ejit_operand args[2] = { + EJIT_OPERAND_GPR(0, EJIT_INT32), /* s */ + EJIT_OPERAND_GPR(1, EJIT_INT32) /* n */ + }; + + ejit_movi(f, EJIT_GPR(2), (uintptr_t)f); + ejit_tailr(f, EJIT_GPR(2), 2, args); + + ejit_select_compile_func(f, 3, 0, EJIT_USE64(uintptr_t), do_jit, true); + + /* arbitrary number but large enough to most likely cause a stack fault + * if the tail call leaks memory or something */ + assert((int32_t)erfi2(f, EJIT_ARG(0, int32_t), EJIT_ARG(1000000, int32_t)) == 1784293664); + ejit_destroy_func(f); +} -- cgit v1.2.3 From be5c83ba8e57bc67beee41bc2c7227e6b8ebd9d5 Mon Sep 17 00:00:00 2001 From: Kimplul Date: Wed, 9 Apr 2025 22:20:01 +0300 Subject: add callr_i/l/f/d --- include/ejit/ejit.h | 33 ++++++++---- src/common.h | 6 ++- src/compile/compile.c | 73 +++++++++++++++++++++----- src/ejit.c | 142 ++++++++++++++++++++++++++++++++++---------------- src/interp.c | 41 +++++++++++---- tests/calli.c | 41 +++++++++++++++ tests/callr_i.c | 42 +++++++++++++++ 7 files changed, 298 insertions(+), 80 deletions(-) create mode 100644 tests/calli.c create mode 100644 tests/callr_i.c (limited to 'src/ejit.c') diff --git a/include/ejit/ejit.h b/include/ejit/ejit.h index 5baaab6..ab06d8f 100644 --- a/include/ejit/ejit.h +++ b/include/ejit/ejit.h @@ -460,20 +460,33 @@ void ejit_tailr(struct ejit_func *s, struct ejit_gpr target, void ejit_taili(struct ejit_func *s, struct ejit_func *f, size_t argc, const struct ejit_operand args[argc]); -void ejit_calli(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_escapei_i(struct ejit_func *s, ejit_escape_i_t 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_escapei_l(struct ejit_func *s, ejit_escape_l_t 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_f(struct ejit_func *s, ejit_escape_f_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_d(struct ejit_func *s, ejit_escape_d_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_i(struct ejit_func *s, ejit_escape_i_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); diff --git a/src/common.h b/src/common.h index 333c794..dc970f0 100644 --- a/src/common.h +++ b/src/common.h @@ -218,8 +218,12 @@ enum ejit_opcode { EJIT_OP_ESCAPEI_F, EJIT_OP_ESCAPEI_D, - EJIT_OP_CALLI, + EJIT_OP_CALLR_I, + EJIT_OP_CALLR_L, + EJIT_OP_CALLR_F, + EJIT_OP_CALLR_D, + EJIT_OP_CALLI, EJIT_OP_TAILR, EJIT_OP_TAILI, diff --git a/src/compile/compile.c b/src/compile/compile.c index 60059d5..bfcb12d 100644 --- a/src/compile/compile.c +++ b/src/compile/compile.c @@ -2476,17 +2476,10 @@ static size_t compile_fn_body(struct ejit_func *f, jit_state_t *j, void *arena, break; } + case EJIT_OP_ESCAPEI_I: case EJIT_OP_ESCAPEI_L: -#if __WORDSIZE == 64 - /* fallthrough */ -#else - assert(0 && "trying to compile escapei_l on 32bit arch"); - break; -#endif - - case EJIT_OP_ESCAPEI_D: case EJIT_OP_ESCAPEI_F: - case EJIT_OP_ESCAPEI_I: { + case EJIT_OP_ESCAPEI_D: { save_caller_save_regs(f, j); jit_operand_t args[2] = { @@ -2550,15 +2543,25 @@ static size_t compile_fn_body(struct ejit_func *f, jit_state_t *j, void *arena, assert(operands_len(&direct) <= 2); jit_gpr_t r = getloc(f, j, i.r1, 0); - jit_ldxi(j, JIT_R0, r, offsetof(struct ejit_func, direct_call)); + #if defined(DEBUG) - /** @todo other checks? */ - jit_reloc_t assert_reloc = jit_bnei(j, JIT_R0, 0); /* null */ + jit_ldxi(j, JIT_R1, r, offsetof(struct ejit_func, rtype)); + jit_reloc_t rtype_reloc = jit_beqi(j, JIT_R1, f->rtype); + jit_calli_1(j, assert_helper, + jit_operand_imm(JIT_OPERAND_ABI_POINTER, + (jit_imm_t)"trying to tail call different rtype")); + + jit_patch_here(j, rtype_reloc); + + jit_ldxi(j, JIT_R1, r, offsetof(struct ejit_func, direct_call)); + jit_reloc_t direct_reloc = jit_bnei(j, JIT_R1, 0); /* null */ jit_calli_1(j, assert_helper, jit_operand_imm(JIT_OPERAND_ABI_POINTER, (jit_imm_t)"trying to tail call interpreted function")); - jit_patch_here(j, assert_reloc); + jit_patch_here(j, direct_reloc); #endif + + jit_ldxi(j, JIT_R0, r, offsetof(struct ejit_func, direct_call)); jit_operand_t regs[2] = { jit_operand_gpr(JIT_OPERAND_ABI_WORD, JIT_R1), jit_operand_gpr(JIT_OPERAND_ABI_WORD, JIT_R2) @@ -2591,6 +2594,50 @@ static size_t compile_fn_body(struct ejit_func *f, jit_state_t *j, void *arena, break; } + case EJIT_OP_CALLR_I: + case EJIT_OP_CALLR_L: + case EJIT_OP_CALLR_F: + case EJIT_OP_CALLR_D: { + save_caller_save_regs(f, j); + + jit_gpr_t target = getgpr(f, i.r1, 0); + + /* check if there's a direct call avaiable */ + jit_ldxi(j, JIT_R1, target, offsetof(struct ejit_func, direct_call)); + jit_reloc_t direct_reloc = jit_beqi(j, JIT_R0, 0); + /* we can do a jit -> jit call */ + jit_callr(j, JIT_R1, operands_len(&direct), direct.buf); + jit_reloc_t out_reloc = jit_jmp(j); + + jit_patch_here(j, direct_reloc); + + /* we must do a jit -> bytecode call */ + jit_operand_t args[3] = { + jit_operand_gpr(JIT_OPERAND_ABI_POINTER, JIT_R1), + jit_operand_imm(JIT_OPERAND_ABI_WORD, operands_len(&src) / 2), + /* compile_imm_call populate JIT_R0 with the + * argument stack address */ + jit_operand_gpr(JIT_OPERAND_ABI_POINTER, JIT_R0) + }; + void *call = NULL; + switch (i.op) { + case EJIT_OP_CALLR_I: call = ejit_run_func_i; break; + case EJIT_OP_CALLR_L: call = ejit_run_func_l; break; + case EJIT_OP_CALLR_F: call = ejit_run_func_f; break; + case EJIT_OP_CALLR_D: call = ejit_run_func_d; break; + default: abort(); + } + + compile_imm_call(j, &src, &dst, call, 3, args); + jit_patch_here(j, out_reloc); + restore_caller_save_regs(f, j); + + operands_reset(&src); + operands_reset(&dst); + operands_reset(&direct); + break; + } + case EJIT_OP_CALLI: { save_caller_save_regs(f, j); diff --git a/src/ejit.c b/src/ejit.c index 0701b90..e8ff99e 100644 --- a/src/ejit.c +++ b/src/ejit.c @@ -545,10 +545,22 @@ void ejit_calli(struct ejit_func *s, struct ejit_func *f, size_t argc, for (size_t i = 0; i < argc; ++i) { switch (args[i].kind) { - case EJIT_OPERAND_GPR: emit_insn_ar(s, EJIT_OP_ARG, i, args[i].type, EJIT_GPR(args[i].r)); break; - case EJIT_OPERAND_FPR: emit_insn_af(s, EJIT_OP_ARG_F, i, args[i].type, EJIT_FPR(args[i].r)); break; - case EJIT_OPERAND_IMM: emit_insn_ai(s, EJIT_OP_ARG_I, i, args[i].type, args[i].r); break; - case EJIT_OPERAND_FLT: emit_insn_ad(s, EJIT_OP_ARG_FI, i, args[i].type, args[i].d); break; + case EJIT_OPERAND_GPR: + emit_insn_ar(s, EJIT_OP_ARG, i, args[i].type, EJIT_GPR(args[i].r)); + break; + + case EJIT_OPERAND_FPR: + emit_insn_af(s, EJIT_OP_ARG_F, i, args[i].type, EJIT_FPR(args[i].r)); + break; + + case EJIT_OPERAND_IMM: + emit_insn_ai(s, EJIT_OP_ARG_I, i, args[i].type, args[i].r); + break; + + case EJIT_OPERAND_FLT: + emit_insn_ad(s, EJIT_OP_ARG_FI, i, args[i].type, args[i].d); + break; + default: abort(); } } @@ -556,73 +568,113 @@ void ejit_calli(struct ejit_func *s, struct ejit_func *f, size_t argc, emit_insn_op(s, EJIT_OP_CALLI, f); } -void ejit_escapei_i(struct ejit_func *s, ejit_escape_i_t f, size_t argc, - const struct ejit_operand args[argc]) +static void ejit_callr(struct ejit_func *s, enum ejit_opcode op, struct ejit_gpr target, + size_t argc, const struct ejit_operand args[argc]) { + s->use_64 = op == EJIT_OP_CALLR_L; s->max_args = argc > s->max_args ? argc : s->max_args; + for (size_t i = 0; i < argc; ++i) { switch (args[i].kind) { - case EJIT_OPERAND_GPR: emit_insn_ar(s, EJIT_OP_ARG, i, args[i].type, EJIT_GPR(args[i].r)); break; - case EJIT_OPERAND_FPR: emit_insn_af(s, EJIT_OP_ARG_F, i, args[i].type, EJIT_FPR(args[i].r)); break; - case EJIT_OPERAND_IMM: emit_insn_ai(s, EJIT_OP_ARG_I, i, args[i].type, args[i].r); break; - case EJIT_OPERAND_FLT: emit_insn_ad(s, EJIT_OP_ARG_FI, i, args[i].type, args[i].d); break; + case EJIT_OPERAND_GPR: + emit_insn_ar(s, EJIT_OP_ARG, i, args[i].type, EJIT_GPR(args[i].r)); + break; + + case EJIT_OPERAND_FPR: + emit_insn_af(s, EJIT_OP_ARG_F, i, args[i].type, EJIT_FPR(args[i].r)); + break; + + case EJIT_OPERAND_IMM: + emit_insn_ai(s, EJIT_OP_ARG_I, i, args[i].type, args[i].r); + break; + + case EJIT_OPERAND_FLT: + emit_insn_ad(s, EJIT_OP_ARG_FI, i, args[i].type, args[i].d); + break; + default: abort(); } } - emit_insn_op(s, EJIT_OP_ESCAPEI_I, f); + emit_insn_oxr(s, op, target); } -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_i(struct ejit_func *s, struct ejit_gpr target, + size_t argc, const struct ejit_operand args[argc]) { - s->use_64 = true; - s->max_args = argc > s->max_args ? argc : s->max_args; - for (size_t i = 0; i < argc; ++i) { - switch (args[i].kind) { - case EJIT_OPERAND_GPR: emit_insn_ar(s, EJIT_OP_ARG, i, args[i].type, EJIT_GPR(args[i].r)); break; - case EJIT_OPERAND_FPR: emit_insn_af(s, EJIT_OP_ARG_F, i, args[i].type, EJIT_FPR(args[i].r)); break; - case EJIT_OPERAND_IMM: emit_insn_ai(s, EJIT_OP_ARG_I, i, args[i].type, args[i].r); break; - case EJIT_OPERAND_FLT: emit_insn_ad(s, EJIT_OP_ARG_FI, i, args[i].type, args[i].d); break; - default: abort(); - } - } + ejit_callr(s, EJIT_OP_CALLR_I, target, argc, args); +} + +void ejit_callr_l(struct ejit_func *s, struct ejit_gpr target, + size_t argc, const struct ejit_operand args[argc]) +{ + ejit_callr(s, EJIT_OP_CALLR_L, target, argc, args); +} - emit_insn_op(s, EJIT_OP_ESCAPEI_L, f); +void ejit_callr_f(struct ejit_func *s, struct ejit_gpr target, + size_t argc, const struct ejit_operand args[argc]) +{ + ejit_callr(s, EJIT_OP_CALLR_F, target, argc, args); } -void ejit_escapei_f(struct ejit_func *s, ejit_escape_f_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]) { + ejit_callr(s, EJIT_OP_CALLR_D, target, argc, args); +} + +static void ejit_escapei(struct ejit_func *s, enum ejit_opcode op, void *f, + size_t argc, const struct ejit_operand args[argc]) +{ + s->use_64 = op == EJIT_OP_ESCAPEI_L; s->max_args = argc > s->max_args ? argc : s->max_args; for (size_t i = 0; i < argc; ++i) { switch (args[i].kind) { - case EJIT_OPERAND_GPR: emit_insn_ar(s, EJIT_OP_ARG, i, args[i].type, EJIT_GPR(args[i].r)); break; - case EJIT_OPERAND_FPR: emit_insn_af(s, EJIT_OP_ARG_F, i, args[i].type, EJIT_FPR(args[i].r)); break; - case EJIT_OPERAND_IMM: emit_insn_ai(s, EJIT_OP_ARG_I, i, args[i].type, args[i].r); break; - case EJIT_OPERAND_FLT: emit_insn_ad(s, EJIT_OP_ARG_FI, i, args[i].type, args[i].d); break; + case EJIT_OPERAND_GPR: + emit_insn_ar(s, EJIT_OP_ARG, i, args[i].type, EJIT_GPR(args[i].r)); + break; + + case EJIT_OPERAND_FPR: + emit_insn_af(s, EJIT_OP_ARG_F, i, args[i].type, EJIT_FPR(args[i].r)); + break; + + case EJIT_OPERAND_IMM: + emit_insn_ai(s, EJIT_OP_ARG_I, i, args[i].type, args[i].r); + break; + + case EJIT_OPERAND_FLT: + emit_insn_ad(s, EJIT_OP_ARG_FI, i, args[i].type, args[i].d); + break; + default: abort(); } } - emit_insn_op(s, EJIT_OP_ESCAPEI_F, f); + emit_insn_op(s, op, f); } -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_i(struct ejit_func *s, ejit_escape_i_t f, + size_t argc, const struct ejit_operand args[argc]) { - s->max_args = argc > s->max_args ? argc : s->max_args; - for (size_t i = 0; i < argc; ++i) { - switch (args[i].kind) { - case EJIT_OPERAND_GPR: emit_insn_ar(s, EJIT_OP_ARG, i, args[i].type, EJIT_GPR(args[i].r)); break; - case EJIT_OPERAND_FPR: emit_insn_af(s, EJIT_OP_ARG_F, i, args[i].type, EJIT_FPR(args[i].r)); break; - case EJIT_OPERAND_IMM: emit_insn_ai(s, EJIT_OP_ARG_I, i, args[i].type, args[i].r); break; - case EJIT_OPERAND_FLT: emit_insn_ad(s, EJIT_OP_ARG_FI, i, args[i].type, args[i].d); break; - default: abort(); - } - } + ejit_escapei(s, EJIT_OP_ESCAPEI_I, f, argc, args); +} + +void ejit_escapei_l(struct ejit_func *s, ejit_escape_l_t f, + size_t argc, const struct ejit_operand args[argc]) +{ + ejit_escapei(s, EJIT_OP_ESCAPEI_L, f, argc, args); +} - emit_insn_op(s, EJIT_OP_ESCAPEI_D, f); +void ejit_escapei_f(struct ejit_func *s, ejit_escape_f_t f, + size_t argc, const struct ejit_operand args[argc]) +{ + ejit_escapei(s, EJIT_OP_ESCAPEI_F, f, argc, args); +} + +void ejit_escapei_d(struct ejit_func *s, ejit_escape_d_t f, + size_t argc, const struct ejit_operand args[argc]) +{ + ejit_escapei(s, EJIT_OP_ESCAPEI_D, f, argc, args); } void ejit_retval(struct ejit_func *s, struct ejit_gpr r0) diff --git a/src/interp.c b/src/interp.c index 268bfb3..6f94f98 100644 --- a/src/interp.c +++ b/src/interp.c @@ -213,14 +213,18 @@ union interp_ret ejit_run(struct ejit_func *f, size_t paramc, struct ejit_arg pa [EJIT_OP_PARAM] = &&PARAM, [EJIT_OP_PARAM_F] = &&PARAM_F, + [EJIT_OP_CALLR_I] = &&CALLR_I, + [EJIT_OP_CALLR_L] = &&CALLR_L, + [EJIT_OP_CALLR_F] = &&CALLR_F, + [EJIT_OP_CALLR_D] = &&CALLR_D, [EJIT_OP_CALLI] = &&CALLI, [EJIT_OP_TAILR] = &&TAILR, [EJIT_OP_TAILI] = &&TAILI, [EJIT_OP_ESCAPEI_I] = &&ESCAPEI_I, - [EJIT_OP_ESCAPEI_F] = &&ESCAPEI_F, [EJIT_OP_ESCAPEI_L] = &&ESCAPEI_L, + [EJIT_OP_ESCAPEI_F] = &&ESCAPEI_F, [EJIT_OP_ESCAPEI_D] = &&ESCAPEI_D, [EJIT_OP_START] = &&START, @@ -1084,33 +1088,48 @@ top: goto top; DISPATCH(); + DO(CALLR_I); + retval = ejit_run((struct ejit_func *)gpr[i.r1], argc, args, NULL); + argc = 0; + DISPATCH(); + + DO(CALLR_L); + retval = ejit_run((struct ejit_func *)gpr[i.r1], argc, args, NULL); + argc = 0; + DISPATCH(); + + DO(CALLR_F); + retval = ejit_run((struct ejit_func *)gpr[i.r1], argc, args, NULL); + argc = 0; + DISPATCH(); + + DO(CALLR_D); + retval = ejit_run((struct ejit_func *)gpr[i.r1], argc, args, NULL); + argc = 0; + DISPATCH(); + DO(CALLI); - struct ejit_func *f = i.p; - retval = ejit_run(f, argc, args, NULL); + retval = ejit_run((struct ejit_func *)i.p, argc, args, NULL); argc = 0; DISPATCH(); DO(ESCAPEI_I); - ejit_escape_i_t f = i.p; - retval.i = f(argc, args); + retval.i = ((ejit_escape_i_t)i.p)(argc, args); argc = 0; DISPATCH(); DO(ESCAPEI_L); - ejit_escape_l_t f = i.p; - retval.i = f(argc, args); + retval.i = ((ejit_escape_l_t)i.p)(argc, args); argc = 0; DISPATCH(); DO(ESCAPEI_F); - ejit_escape_f_t f = i.p; - retval.f = f(argc, args); + retval.f = ((ejit_escape_f_t)i.p)(argc, args); argc = 0; DISPATCH(); DO(ESCAPEI_D); - ejit_escape_d_t f = i.p; - retval.f = f(argc, args); + retval.f = ((ejit_escape_d_t)i.p)(argc, args); argc = 0; DISPATCH(); diff --git a/tests/calli.c b/tests/calli.c new file mode 100644 index 0000000..991e97d --- /dev/null +++ b/tests/calli.c @@ -0,0 +1,41 @@ +#include +#include +#include "do_jit.h" + +struct ejit_func *compile(bool do_jit) +{ + struct ejit_operand operands[2] = { + EJIT_OPERAND_GPR(0, EJIT_TYPE(long)), + EJIT_OPERAND_GPR(1, EJIT_TYPE(long)) + }; + struct ejit_func *f = ejit_create_func(EJIT_TYPE(long), 2, operands); + ejit_addr(f, EJIT_GPR(0), EJIT_GPR(0), EJIT_GPR(1)); + ejit_retr(f, EJIT_GPR(0)); + ejit_select_compile_func(f, 2, 0, EJIT_USE64(long), do_jit, true); + return f; +} + +int main(int argc, char *argv[]) +{ + (void)argv; + bool do_jit = argc > 1; + struct ejit_func *target = compile(do_jit); + + struct ejit_operand operands[2] = { + EJIT_OPERAND_GPR(0, EJIT_TYPE(long)), + EJIT_OPERAND_GPR(1, EJIT_TYPE(long)) + }; + + struct ejit_func *f = ejit_create_func(EJIT_TYPE(long), 2, operands); + ejit_calli(f, target, 2, operands); + ejit_retval(f, EJIT_GPR(0)); + ejit_retr(f, EJIT_GPR(0)); + ejit_select_compile_func(f, 2, 0, EJIT_USE64(long), do_jit, true); + + assert(erfi2(f, + EJIT_ARG(42, long), + EJIT_ARG(69, long)) == 111); + + ejit_destroy_func(target); + ejit_destroy_func(f); +} diff --git a/tests/callr_i.c b/tests/callr_i.c new file mode 100644 index 0000000..00b5374 --- /dev/null +++ b/tests/callr_i.c @@ -0,0 +1,42 @@ +#include +#include +#include "do_jit.h" + +struct ejit_func *compile(bool do_jit) +{ + struct ejit_operand operands[2] = { + EJIT_OPERAND_GPR(0, EJIT_TYPE(long)), + EJIT_OPERAND_GPR(1, EJIT_TYPE(long)) + }; + struct ejit_func *f = ejit_create_func(EJIT_TYPE(long), 2, operands); + ejit_addr(f, EJIT_GPR(0), EJIT_GPR(0), EJIT_GPR(1)); + ejit_retr(f, EJIT_GPR(0)); + ejit_select_compile_func(f, 2, 0, EJIT_USE64(long), do_jit, true); + return f; +} + +int main(int argc, char *argv[]) +{ + (void)argv; + bool do_jit = argc > 1; + struct ejit_func *target = compile(do_jit); + + struct ejit_operand operands[2] = { + EJIT_OPERAND_GPR(0, EJIT_TYPE(long)), + EJIT_OPERAND_GPR(1, EJIT_TYPE(long)) + }; + + struct ejit_func *f = ejit_create_func(EJIT_TYPE(long), 2, operands); + ejit_movi(f, EJIT_GPR(2), (uintptr_t)target); + ejit_callr_i(f, EJIT_GPR(2), 2, operands); + ejit_retval(f, EJIT_GPR(0)); + ejit_retr(f, EJIT_GPR(0)); + ejit_select_compile_func(f, 3, 0, EJIT_USE64(long), do_jit, true); + + assert(erfi2(f, + EJIT_ARG(42, long), + EJIT_ARG(69, long)) == 111); + + ejit_destroy_func(target); + ejit_destroy_func(f); +} -- cgit v1.2.3