From f5c729ea59d227a507f83bd94d07f4366b46d72b Mon Sep 17 00:00:00 2001 From: Kimplul Date: Fri, 14 Mar 2025 21:08:01 +0200 Subject: start supporting 32bit arches --- src/common.h | 43 +- src/compile/compile.c | 182 ++++++-- src/ejit.c | 248 ++++++++--- src/interp.c | 1158 +++++++++++++++++++++++++++++++++++++++++++++++++ src/interp.inc | 1077 --------------------------------------------- src/vec.h | 4 + 6 files changed, 1531 insertions(+), 1181 deletions(-) create mode 100644 src/interp.c delete mode 100644 src/interp.inc (limited to 'src') diff --git a/src/common.h b/src/common.h index df150c1..b845e1c 100644 --- a/src/common.h +++ b/src/common.h @@ -204,11 +204,15 @@ enum ejit_opcode { ARG_F, ARG_FI, - ESCAPEI, + ESCAPEI_I, + ESCAPEI_L, ESCAPEI_F, + ESCAPEI_D, - CALLI, + CALLI_I, + CALLI_L, CALLI_F, + CALLI_D, RETR, RETI, @@ -248,6 +252,9 @@ struct ejit_insn { #define VEC_NAME insns #include "vec.h" +#define VEC_TYPE enum ejit_type +#define VEC_NAME types +#include "vec.h" struct fpr_stat { struct ejit_fpr f; @@ -268,6 +275,7 @@ struct gpr_stat { #include "vec.h" struct ejit_func { + struct types sign; struct insns insns; struct labels labels; enum ejit_type rtype; @@ -289,27 +297,16 @@ struct interp_state { struct args args; }; -int64_t ejit_interp(struct ejit_func *f, size_t argc, - struct ejit_arg args[argc], - struct interp_state *state, bool run, - void ***labels_wb); - -double ejit_interp_f(struct ejit_func *f, size_t argc, - struct ejit_arg args[argc], - struct interp_state *state, bool run, - void ***labels_wb); - -int64_t ejit_run_interp(struct ejit_func *f, size_t argc, - struct ejit_arg args[argc], - struct interp_state *state, - bool run, - void ***labels_wb); - -double ejit_run_interp_f(struct ejit_func *f, size_t argc, - struct ejit_arg args[argc], - struct interp_state *state, - bool run, - void ***labels_wb); +union interp_ret { + int64_t i; + double f; +}; + +union interp_ret ejit_run(struct ejit_func *f, size_t argc, + struct ejit_arg args[argc], + struct interp_state *state, + bool run, + void ***labels_wb); bool ejit_compile(struct ejit_func *f, bool use_64); diff --git a/src/compile/compile.c b/src/compile/compile.c index c9c7652..e741a0f 100644 --- a/src/compile/compile.c +++ b/src/compile/compile.c @@ -650,8 +650,15 @@ static void compile_sti32(struct ejit_func *f, jit_state_t *j, static void compile_sti64(struct ejit_func *f, jit_state_t *j, struct ejit_insn i) { +#if __WORDSIZE == 64 jit_gpr_t r0 = getloc(f, j, i.r0, 0); jit_sti_l(j, i.p, r0); +#else + (void)f; + (void)j; + (void)i; + assert(0 && "trying to compile sti64 on 32bit arch"); +#endif } static void compile_stif(struct ejit_func *f, jit_state_t *j, @@ -695,9 +702,16 @@ static void compile_stxi32(struct ejit_func *f, jit_state_t *j, static void compile_stxi64(struct ejit_func *f, jit_state_t *j, struct ejit_insn i) { +#if __WORDSIZE == 64 jit_gpr_t r0 = getloc(f, j, i.r0, 0); jit_gpr_t r1 = getloc(f, j, i.r1, 1); jit_stxi_l(j, i.o, r1, r0); +#else + (void)f; + (void)j; + (void)i; + assert(0 && "trying to compile stxi64 on 32bit arch"); +#endif } static void compile_stxif(struct ejit_func *f, jit_state_t *j, @@ -746,10 +760,17 @@ static void compile_stxr32(struct ejit_func *f, jit_state_t *j, static void compile_stxr64(struct ejit_func *f, jit_state_t *j, struct ejit_insn i) { +#if __WORDSIZE == 64 jit_gpr_t r0 = getloc(f, j, i.r0, 0); jit_gpr_t r1 = getloc(f, j, i.r1, 1); jit_gpr_t r2 = getloc(f, j, i.r2, 2); jit_stxr_l(j, r2, r1, r0); +#else + (void)f; + (void)j; + (void)i; + assert(0 && "trying to compile stxr64 on 32bit arch"); +#endif } static void compile_stxrf(struct ejit_func *f, jit_state_t *j, @@ -789,17 +810,31 @@ static void compile_ldiu16(struct ejit_func *f, jit_state_t *j, static void compile_ldiu32(struct ejit_func *f, jit_state_t *j, struct ejit_insn i) { +#if __WORDSIZE == 64 jit_gpr_t r0 = getgpr(f, i.r0, 0); jit_ldi_ui(j, r0, i.p); putloc(f, j, i.r0, r0); +#else + (void)f; + (void)j; + (void)i; + assert(0 && "trying to compile ldiu32 on 32bit arch"); +#endif } static void compile_ldiu64(struct ejit_func *f, jit_state_t *j, struct ejit_insn i) { +#if __WORDSIZE == 64 jit_gpr_t r0 = getgpr(f, i.r0, 0); jit_ldi_l(j, r0, i.p); putloc(f, j, i.r0, r0); +#else + (void)f; + (void)j; + (void)i; + assert(0 && "trying to compile ldiu64 on 32bit arch"); +#endif } static void compile_ldif(struct ejit_func *f, jit_state_t *j, @@ -845,9 +880,16 @@ static void compile_ldi32(struct ejit_func *f, jit_state_t *j, static void compile_ldi64(struct ejit_func *f, jit_state_t *j, struct ejit_insn i) { +#if __WORDSIZE == 64 jit_gpr_t r0 = getgpr(f, i.r0, 0); jit_ldi_l(j, r0, i.p); putloc(f, j, i.r0, r0); +#else + (void)f; + (void)j; + (void)i; + assert(0 && "trying to compile ldi64 on 32bit arch"); +#endif } static void compile_ldxiu8(struct ejit_func *f, jit_state_t *j, @@ -871,19 +913,33 @@ static void compile_ldxiu16(struct ejit_func *f, jit_state_t *j, static void compile_ldxiu32(struct ejit_func *f, jit_state_t *j, struct ejit_insn i) { +#if __WORDSIZE == 64 jit_gpr_t r0 = getgpr(f, i.r0, 0); jit_gpr_t r1 = getloc(f, j, i.r1, 1); jit_ldxi_ui(j, r0, r1, i.o); putloc(f, j, i.r0, r0); +#else + (void)f; + (void)j; + (void)i; + assert(0 && "trying to compile ldxiu32 on 32bit arch"); +#endif } static void compile_ldxiu64(struct ejit_func *f, jit_state_t *j, struct ejit_insn i) { +#if __WORDSIZE == 64 jit_gpr_t r0 = getgpr(f, i.r0, 0); jit_gpr_t r1 = getloc(f, j, i.r1, 1); jit_ldxi_l(j, r0, r1, i.o); putloc(f, j, i.r0, r0); +#else + (void)f; + (void)j; + (void)i; + assert(0 && "trying to compile ldxiu64 on 32bit arch"); +#endif } static void compile_ldxif(struct ejit_func *f, jit_state_t *j, @@ -934,10 +990,17 @@ static void compile_ldxi32(struct ejit_func *f, jit_state_t *j, static void compile_ldxi64(struct ejit_func *f, jit_state_t *j, struct ejit_insn i) { +#if __WORDSIZE == 64 jit_gpr_t r0 = getgpr(f, i.r0, 0); jit_gpr_t r1 = getloc(f, j, i.r1, 1); jit_ldxi_l(j, r0, r1, i.o); putloc(f, j, i.r0, r0); +#else + (void)f; + (void)j; + (void)i; + assert(0 && "trying to compile ldxi64 on 32bit arch"); +#endif } static void compile_ldxru8(struct ejit_func *f, jit_state_t *j, @@ -963,21 +1026,35 @@ static void compile_ldxru16(struct ejit_func *f, jit_state_t *j, static void compile_ldxru32(struct ejit_func *f, jit_state_t *j, struct ejit_insn i) { +#if __WORDSIZE == 64 jit_gpr_t r0 = getgpr(f, i.r0, 0); jit_gpr_t r1 = getloc(f, j, i.r1, 1); jit_gpr_t r2 = getloc(f, j, i.r2, 2); jit_ldxr_ui(j, r0, r1, r2); putloc(f, j, i.r0, r0); +#else + (void)f; + (void)j; + (void)i; + assert(0 && "trying to compile ldxru32 on 32bit arch"); +#endif } static void compile_ldxru64(struct ejit_func *f, jit_state_t *j, struct ejit_insn i) { +#if __WORDSIZE == 64 jit_gpr_t r0 = getgpr(f, i.r0, 0); jit_gpr_t r1 = getloc(f, j, i.r1, 1); jit_gpr_t r2 = getloc(f, j, i.r2, 2); jit_ldxr_l(j, r0, r1, r2); putloc(f, j, i.r0, r0); +#else + (void)f; + (void)j; + (void)i; + assert(0 && "trying to compile ldxru64 on 32bit arch"); +#endif } static void compile_ldxr8(struct ejit_func *f, jit_state_t *j, @@ -1013,11 +1090,18 @@ static void compile_ldxr32(struct ejit_func *f, jit_state_t *j, static void compile_ldxr64(struct ejit_func *f, jit_state_t *j, struct ejit_insn i) { +#if __WORDSIZE == 64 jit_gpr_t r0 = getgpr(f, i.r0, 0); jit_gpr_t r1 = getloc(f, j, i.r1, 1); jit_gpr_t r2 = getloc(f, j, i.r2, 2); jit_ldxr_l(j, r0, r1, r2); putloc(f, j, i.r0, r0); +#else + (void)f; + (void)j; + (void)i; + assert(0 && "trying to compile ldxr64 on 32bit arch"); +#endif } static void compile_ldxrf(struct ejit_func *f, jit_state_t *j, @@ -1097,10 +1181,17 @@ static void compile_extr16(struct ejit_func *f, jit_state_t *j, static void compile_extr32(struct ejit_func *f, jit_state_t *j, struct ejit_insn i) { +#if __WORDSIZE == 64 jit_gpr_t r0 = getgpr(f, i.r0, 0); jit_gpr_t r1 = getloc(f, j, i.r1, 1); jit_extr_i(j, r0, r1); putloc(f, j, i.r0, r0); +#else + (void)f; + (void)j; + (void)i; + assert(0 && "trying to compile extr32 on 32bit arch"); +#endif } static void compile_extru8(struct ejit_func *f, jit_state_t *j, @@ -1124,10 +1215,17 @@ static void compile_extru16(struct ejit_func *f, jit_state_t *j, static void compile_extru32(struct ejit_func *f, jit_state_t *j, struct ejit_insn i) { +#if __WORDSIZE == 64 jit_gpr_t r0 = getgpr(f, i.r0, 0); jit_gpr_t r1 = getloc(f, j, i.r1, 1); jit_extr_ui(j, r0, r1); putloc(f, j, i.r0, r0); +#else + (void)f; + (void)j; + (void)i; + assert(0 && "trying to compile extru32 on 32bit arch"); +#endif } static void compile_extrf(struct ejit_func *f, jit_state_t *j, @@ -1151,10 +1249,17 @@ static void compile_extrd(struct ejit_func *f, jit_state_t *j, static void compile_truncr_d_64(struct ejit_func *f, jit_state_t *j, struct ejit_insn i) { +#if __WORDSIZE == 64 jit_gpr_t r0 = getgpr(f, i.r0, 0); jit_fpr_t r1 = getloc_d(f, j, i.r1, 1); jit_truncr_d_l(j, r0, r1); putloc(f, j, i.r0, r0); +#else + (void)f; + (void)j; + (void)i; + assert(0 && "trying to compile truncr_d_64 on 32bit arch"); +#endif } static void compile_truncr_d_32(struct ejit_func *f, jit_state_t *j, @@ -1174,10 +1279,17 @@ static void compile_truncr_d_32(struct ejit_func *f, jit_state_t *j, static void compile_truncr_f_64(struct ejit_func *f, jit_state_t *j, struct ejit_insn i) { +#if __WORDSIZE == 64 jit_gpr_t r0 = getgpr(f, i.r0, 0); jit_fpr_t r1 = getloc_f(f, j, i.r1, 1); jit_truncr_f_l(j, r0, r1); putloc(f, j, i.r0, r0); +#else + (void)f; + (void)j; + (void)i; + assert(0 && "trying to compile truncr_f_64 on 32bit arch"); +#endif } static void compile_truncr_f_32(struct ejit_func *f, jit_state_t *j, @@ -1645,9 +1757,7 @@ static void compile_retval_f(struct ejit_func *f, jit_state_t *j, struct ejit_insn i) { jit_fpr_t r0 = getfpr(f, i.r0, 0); - jit_retval_d(j, r0); - /* convert double to float */ - jit_extr_d_f(j, r0, r0); + jit_retval_f(j, r0); putloc_f(f, j, i.r0, r0); } @@ -1734,6 +1844,8 @@ static void compile_imm_call(jit_state_t *j, struct operands *src, struct operan /* note, do not fix up destination! */ /* remember to move all operands */ jit_move_operands(j, dst->buf, src->buf, movec * 2); + + jit_movr(j, JIT_R0, JIT_SP); jit_calli(j, addr, argc, args); jit_shrink_stack(j, fixup); @@ -1814,6 +1926,8 @@ 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 */ @@ -2072,32 +2186,27 @@ static size_t compile_fn_body(struct ejit_func *f, jit_state_t *j, void *arena, break; } - case ESCAPEI: { - save_caller_save_regs(f, j); - - jit_operand_t args[2] = { - jit_operand_imm(JIT_OPERAND_ABI_WORD, - operands_len(&src) / 2), - jit_operand_gpr(JIT_OPERAND_ABI_POINTER, JIT_SP) - }; - compile_imm_call(j, &src, &dst, (void *)i.o, 2, args); - restore_caller_save_regs(f, j); - - operands_reset(&src); - operands_reset(&dst); - operands_reset(&direct); - break; - } + case ESCAPEI_L: +#if __WORDSIZE == 64 + /* fallthrough */ +#else + assert(0 && "trying to compile escapei_l on 32bit arch"); + break; +#endif - case ESCAPEI_F: { + case ESCAPEI_D: + case ESCAPEI_F: + case ESCAPEI_I: { save_caller_save_regs(f, j); jit_operand_t args[2] = { jit_operand_imm(JIT_OPERAND_ABI_WORD, operands_len(&src) / 2), - jit_operand_gpr(JIT_OPERAND_ABI_POINTER, JIT_SP) + /* compile_imm_call populates JIT_R0 with the + * argument stack address */ + jit_operand_gpr(JIT_OPERAND_ABI_POINTER, JIT_R0) }; - compile_imm_call(j, &src, &dst, (void *)i.o, 2, args); + compile_imm_call(j, &src, &dst, (void *)(uintptr_t)i.o, 2, args); restore_caller_save_regs(f, j); operands_reset(&src); @@ -2106,10 +2215,21 @@ static size_t compile_fn_body(struct ejit_func *f, jit_state_t *j, void *arena, break; } - case CALLI: { + case CALLI_L: +#if __WORDSIZE == 64 + call = ejit_run_func_l; goto calli; +#else + assert(0 && "trying to compile calli_l on 32bit arch"); + break; +#endif + + case CALLI_F: { call = ejit_run_func_f; goto calli; } + case CALLI_D: { call = ejit_run_func_d; goto calli; } + case CALLI_I: { call = ejit_run_func_i; goto calli; +calli: save_caller_save_regs(f, j); - struct ejit_func *f = (struct ejit_func *)i.o; + struct ejit_func *f = (struct ejit_func *)(uintptr_t)i.o; if (f && f->direct_call) { jit_calli(j, f->direct_call, operands_len(&direct), direct.buf); restore_caller_save_regs(f, j); @@ -2124,9 +2244,11 @@ static size_t compile_fn_body(struct ejit_func *f, jit_state_t *j, void *arena, jit_operand_imm(JIT_OPERAND_ABI_POINTER, i.o), jit_operand_imm(JIT_OPERAND_ABI_WORD, operands_len(&src) / 2), - jit_operand_gpr(JIT_OPERAND_ABI_POINTER, JIT_SP) + /* compile_imm_call populates JIT_R0 with the + * argument stack address */ + jit_operand_gpr(JIT_OPERAND_ABI_POINTER, JIT_R0) }; - compile_imm_call(j, &src, &dst, ejit_run_func, 3, args); + compile_imm_call(j, &src, &dst, call, 3, args); restore_caller_save_regs(f, j); operands_reset(&src); @@ -2151,8 +2273,7 @@ static size_t compile_fn_body(struct ejit_func *f, jit_state_t *j, void *arena, case RETR_F: { jit_fpr_t r = getloc_f(f, j, i.r1, 0); - /* convert float to double so the return types match */ - jit_extr_f_d(j, JIT_F0, r); + jit_movr_f(j, JIT_F0, r); jit_shrink_stack(j, stack); jit_leave_jit_abi(j, gprs, fprs, frame); jit_retr_f(j, JIT_F0); @@ -2319,7 +2440,10 @@ bool ejit_compile(struct ejit_func *f, bool use_64) while (1) { arena = alloc_arena(size); - assert(arena); + if (arena == (void *)(-1)) { + jit_destroy_state(j); + return false; + } size_t required_size = compile_fn_body(f, j, arena, size); if (required_size == 0) diff --git a/src/ejit.c b/src/ejit.c index b0a0d51..660d476 100644 --- a/src/ejit.c +++ b/src/ejit.c @@ -1,4 +1,3 @@ -#include #include #include @@ -6,6 +5,22 @@ #include "common.h" +static void check_operands(struct ejit_func *f, size_t argc, const struct ejit_operand args[argc]) +{ + assert(argc == types_len(&f->sign)); + for (size_t i = 0; i < types_len(&f->sign); ++i) { + assert(args[i].type == *types_at(&f->sign, i)); + } +} + +static void check_args(struct ejit_func *f, size_t argc, const struct ejit_arg args[argc]) +{ + assert(argc == types_len(&f->sign)); + for (size_t i = 0; i < types_len(&f->sign); ++i) { + assert(args[i].type == *types_at(&f->sign, i)); + } +} + static struct gpr_stat zero_gpr_stat() { return (struct gpr_stat){ @@ -314,6 +329,7 @@ struct ejit_func *ejit_create_func(enum ejit_type rtype, size_t argc, f->rtype = rtype; + f->sign = types_create(); f->insns = insns_create(); f->labels = labels_create(); f->gpr = gpr_stats_create(); @@ -325,6 +341,8 @@ struct ejit_func *ejit_create_func(enum ejit_type rtype, size_t argc, f->use_64 = false; for (size_t i = 0; i < argc; ++i) { + types_append(&f->sign, args[i].type); + switch (args[i].kind) { case EJIT_OPERAND_GPR: { assert(ejit_int_type(args[i].type)); @@ -373,10 +391,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 */ - if (ejit_float_type(f->rtype)) - ejit_run_interp_f(f, 0, NULL, NULL, false, &labels); - else - ejit_run_interp(f, 0, NULL, NULL, false, &labels); + ejit_run(f, 0, NULL, NULL, false, &labels); foreach_vec(ii, f->insns) { struct ejit_insn i = *insns_at(&f->insns, ii); @@ -395,6 +410,7 @@ void ejit_destroy_func(struct ejit_func *f) if (f->arena) munmap(f->arena, f->size); + types_destroy(&f->sign); insns_destroy(&f->insns); labels_destroy(&f->labels); gpr_stats_destroy(&f->gpr); @@ -417,8 +433,81 @@ 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(struct ejit_func *s, struct ejit_func *f, size_t argc, +void ejit_calli_i(struct ejit_func *s, struct ejit_func *f, size_t argc, + const struct ejit_operand args[argc]) +{ + check_operands(f, argc, 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; + default: abort(); + } + } + + emit_insn_op(s, 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; + check_operands(f, argc, 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; + default: abort(); + } + } + + emit_insn_op(s, CALLI_L, f); +} + +void ejit_calli_f(struct ejit_func *s, struct ejit_func *f, size_t argc, const struct ejit_operand args[argc]) +{ + check_operands(f, argc, 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; + default: abort(); + } + } + + emit_insn_op(s, CALLI_F, f); +} + +void ejit_calli_d(struct ejit_func *s, struct ejit_func *f, size_t argc, + const struct ejit_operand args[argc]) +{ + check_operands(f, argc, 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; + default: abort(); + } + } + + emit_insn_op(s, CALLI_D, f); +} + +void ejit_escapei_i(struct ejit_func *s, ejit_escape_i_t f, size_t argc, + const struct ejit_operand args[argc]) { for (size_t i = 0; i < argc; ++i) { switch (args[i].kind) { @@ -430,12 +519,13 @@ void ejit_calli(struct ejit_func *s, struct ejit_func *f, size_t argc, } } - emit_insn_op(s, CALLI, f); + emit_insn_op(s, ESCAPEI_I, f); } -void ejit_escapei(struct ejit_func *s, ejit_escape_t f, size_t argc, +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; 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; @@ -446,7 +536,7 @@ void ejit_escapei(struct ejit_func *s, ejit_escape_t f, size_t argc, } } - emit_insn_op(s, ESCAPEI, f); + emit_insn_op(s, ESCAPEI_L, f); } void ejit_escapei_f(struct ejit_func *s, ejit_escape_f_t f, size_t argc, @@ -465,6 +555,22 @@ void ejit_escapei_f(struct ejit_func *s, ejit_escape_f_t f, size_t argc, emit_insn_op(s, ESCAPEI_F, f); } +void ejit_escapei_d(struct ejit_func *s, ejit_escape_d_t f, size_t argc, + const struct ejit_operand args[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; + default: abort(); + } + } + + emit_insn_op(s, ESCAPEI_D, f); +} + void ejit_retval(struct ejit_func *s, struct ejit_gpr r0) { emit_insn_or(s, RETVAL, r0); @@ -617,11 +723,13 @@ void ejit_ldi_u16(struct ejit_func *s, struct ejit_gpr r0, void *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); } 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); } @@ -802,6 +910,7 @@ void ejit_extr_16(struct ejit_func *s, struct ejit_gpr r0, struct ejit_gpr 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); } @@ -817,6 +926,7 @@ void ejit_extr_u16(struct ejit_func *s, struct ejit_gpr r0, struct ejit_gpr 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); } @@ -883,7 +993,7 @@ void ejit_subr_d(struct ejit_func *s, struct ejit_fpr f0, struct ejit_fpr f1, } void ejit_subi(struct ejit_func *s, struct ejit_gpr r0, struct ejit_gpr r1, - long o) + int64_t o) { emit_insn_orri(s, SUBI, r0, r1, o); } @@ -1541,71 +1651,105 @@ static void destroy_interp_state(struct interp_state state) args_destroy(&state.args); } -int64_t ejit_run_interp(struct ejit_func *f, size_t argc, - struct ejit_arg args[argc], - struct interp_state *state, - bool run, - void ***labels_wb) +long ejit_run_func_ctx_i(struct ejit_func *f, size_t argc, struct ejit_arg args[argc], struct interp_state *ctx) { - if (run) { - assert(f->size && "trying to run a function that hasn't been compiled"); - assert(f->rtype == EJIT_VOID || ejit_int_type(f->rtype)); - if (f->arena) - return ((ejit_escape_t)f->arena)(argc, args); - } + check_args(f, argc, args); + assert((f->rtype == EJIT_VOID || ejit_int_type(f->rtype)) +#if __WORDSIZE != 64 + && f->rtype != EJIT_INT64 && f->rtype != EJIT_UINT64 +#endif + ); - int64_t retval = 0; double retval_f = 0.0; -#include "interp.inc" - return retval; + return ejit_run(f, argc, args, ctx, true, NULL).i; } -double ejit_run_interp_f(struct ejit_func *f, size_t argc, - struct ejit_arg args[argc], - struct interp_state *state, - bool run, - void ***labels_wb) +long ejit_run_func_i(struct ejit_func *f, size_t argc, + struct ejit_arg args[argc]) { - if (run) { - assert(f->size && "trying to run a function that hasn't been compiled"); - /* void functions should use ejit_run_interp */ - assert(ejit_float_type(f->rtype)); - if (f->arena) - return ((ejit_escape_f_t)f->arena)(argc, args); - } + 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 retval = 0; double retval_f = 0.0; -#include "interp.inc" - return retval_f; +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(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]) { - assert(f->size && "trying to run a function that hasn't been compiled"); - assert(f->rtype == EJIT_VOID || ejit_int_type(f->rtype)); - if (f->arena) - return (int64_t)((ejit_escape_t)f->arena)(argc, args); - struct interp_state state = create_interp_state(); - long r = ejit_run_interp(f, argc, args, &state, true, NULL); + int64_t r = ejit_run_func_ctx_l(f, argc, args, &state); destroy_interp_state(state); return r; } -double ejit_run_func_f(struct ejit_func *f, size_t argc, +float ejit_run_func_ctx_f(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_FLOAT); + return ejit_run(f, argc, args, ctx, true, NULL).f; +} + +float ejit_run_func_f(struct ejit_func *f, size_t argc, struct ejit_arg args[argc]) { - assert(f->size && "trying to run a function that hasn't been compiled"); - assert(ejit_float_type(f->rtype)); - if (f->arena) - return ((ejit_escape_f_t)f->arena)(argc, args); + 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) +{ + 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_interp_f(f, argc, args, &state, true, NULL); + double r = ejit_run_func_ctx_d(f, argc, args, &state); destroy_interp_state(state); return r; } +struct ejit_arg ejit_run_func(struct ejit_func *f, size_t argc, struct ejit_arg args[argc]) +{ + switch (f->rtype) { + case EJIT_DOUBLE: + return (struct ejit_arg){ + .d = ejit_run_func_d(f, argc, args), + .type = EJIT_DOUBLE + }; + + case EJIT_FLOAT: + return (struct ejit_arg){ + .f = ejit_run_func_f(f, argc, args), + .type = EJIT_FLOAT + }; + + case EJIT_UINT64: + case EJIT_INT64: + return (struct ejit_arg){ + .i64 = ejit_run_func_l(f, argc, args), + .type = f->rtype + }; + + default: + return (struct ejit_arg){ + .i64 = ejit_run_func_i(f, argc, args), + .type = f->rtype + }; + } +} + size_t ejit_get_prio(struct ejit_func *s) { return s->prio; diff --git a/src/interp.c b/src/interp.c new file mode 100644 index 0000000..f8ba927 --- /dev/null +++ b/src/interp.c @@ -0,0 +1,1158 @@ +#include +#include +#include "common.h" + +/* 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 argc, struct ejit_arg args[argc], struct interp_state *state, 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, + }; + + if (!run) { + *labels_wb = labels; + goto zero_out; + } + + assert(f->size && "trying to run a function that hasn't been compiled"); + + if (f->arena) { + if (f->rtype == EJIT_INT64 || f->rtype == EJIT_UINT64) + return (union interp_ret){ + .i = ((ejit_escape_l_t)f->arena)(argc, args) + }; + + if (f->rtype == EJIT_DOUBLE) + return (union interp_ret){ + .f = ((ejit_escape_d_t)f->arena)(argc, args) + }; + + if (f->rtype == EJIT_FLOAT) + return (union interp_ret){ + .f = ((ejit_escape_f_t)f->arena)(argc, args) + }; + + return (union interp_ret){ + .i = ((ejit_escape_i_t)f->arena)(argc, args) + }; + } + + int64_t retval = 0; double retval_f = 0.0; + + size_t prev_gprs = gprs_len(&state->gprs); + size_t prev_fprs = fprs_len(&state->fprs); + size_t prev_argc = args_len(&state->args); + + gprs_reserve(&state->gprs, prev_gprs + gpr_stats_len(&f->gpr)); + fprs_reserve(&state->fprs, prev_fprs + fpr_stats_len(&f->fpr)); + + union fpr { + double d; + float f; + }; + int64_t *gpr = ((int64_t *)state->gprs.buf) + prev_gprs; + union fpr *fpr = ((union fpr *)state->fprs.buf) + prev_fprs; + + struct ejit_insn *insns = f->insns.buf; + + /* retval is kind of an unfortunate extra bit of state to keep track of, + * but having call and return value separated is pretty convenient for + * void calls so I guess I don't mind? */ + size_t pc = 0; + +#define DO(x) x : { struct ejit_insn i = insns[pc]; (void)i; +#define JUMP(a) goto *insns[pc = a].addr; +#define DISPATCH() } goto *insns[++pc].addr; + + JUMP(0); + + DO(START); + DISPATCH(); + + DO(END); + goto zero_out; + DISPATCH(); + + DO(MOVI); + gpr[i.r0] = i.o; + DISPATCH(); + + DO(MOVI_F); + fpr[i.r0].f = i.f; + DISPATCH(); + + DO(MOVI_D); + fpr[i.r0].d = i.d; + DISPATCH(); + + DO(MOVR); + gpr[i.r0] = gpr[i.r1]; + DISPATCH(); + + DO(MOVR_F); + fpr[i.r0].f = fpr[i.r1].f; + DISPATCH(); + + DO(MOVR_D); + fpr[i.r0].d = fpr[i.r1].d; + DISPATCH(); + + DO(EXTR8); + gpr[i.r0] = (int8_t)gpr[i.r1]; + DISPATCH(); + + DO(EXTR16); + gpr[i.r0] = (int16_t)gpr[i.r1]; + DISPATCH(); + + DO(EXTR32); + gpr[i.r0] = (int32_t)gpr[i.r1]; + DISPATCH(); + + DO(EXTRU8); + gpr[i.r0] = (uint8_t)gpr[i.r1]; + DISPATCH(); + + DO(EXTRU16); + gpr[i.r0] = (uint16_t)gpr[i.r1]; + DISPATCH(); + + DO(EXTRU32); + gpr[i.r0] = (uint32_t)gpr[i.r1]; + DISPATCH(); + + DO(EXTRF); + fpr[i.r0].f = (float)gpr[i.r1]; + DISPATCH(); + + DO(EXTRD); + fpr[i.r0].d = (double)gpr[i.r1]; + DISPATCH(); + + DO(ADDR); + gpr[i.r0] = gpr[i.r1] + gpr[i.r2]; + DISPATCH(); + + DO(ADDR_F); + fpr[i.r0].f = fpr[i.r1].f + fpr[i.r2].f; + DISPATCH(); + + DO(ADDR_D); + fpr[i.r0].d = fpr[i.r1].d + fpr[i.r2].d; + DISPATCH(); + + DO(ADDI); + gpr[i.r0] = gpr[i.r1] + i.o; + DISPATCH(); + + DO(ABSR_F); + fpr[i.r0].f = fabs(fpr[i.r1].f); + DISPATCH(); + + DO(ABSR_D); + fpr[i.r0].d = fabs(fpr[i.r1].d); + DISPATCH(); + + DO(SUBR); + gpr[i.r0] = gpr[i.r1] - gpr[i.r2]; + DISPATCH(); + + DO(SUBR_F); + fpr[i.r0].f = fpr[i.r1].f - fpr[i.r2].f; + DISPATCH(); + + DO(SUBR_D); + fpr[i.r0].d = fpr[i.r1].d - fpr[i.r2].d; + DISPATCH(); + + DO(SUBI); + gpr[i.r0] = gpr[i.r1] - i.o; + DISPATCH(); + + DO(MULR); + gpr[i.r0] = gpr[i.r1] * gpr[i.r2]; + DISPATCH(); + + DO(MULR_F); + fpr[i.r0].f = fpr[i.r1].f * fpr[i.r2].f; + DISPATCH(); + + DO(MULR_D); + fpr[i.r0].d = fpr[i.r1].d * fpr[i.r2].d; + DISPATCH(); + + DO(DIVR); + gpr[i.r0] = gpr[i.r1] / gpr[i.r2]; + DISPATCH(); + + DO(DIVR_U); + gpr[i.r0] = (uint64_t)gpr[i.r1] / (uint64_t)gpr[i.r2]; + DISPATCH(); + + DO(REMR); + gpr[i.r0] = gpr[i.r1] % gpr[i.r2]; + DISPATCH(); + + DO(REMR_U); + gpr[i.r0] = (uint64_t)gpr[i.r1] % (uint64_t)gpr[i.r2]; + DISPATCH(); + + DO(DIVR_F); + fpr[i.r0].f = fpr[i.r1].f / fpr[i.r2].f; + DISPATCH(); + + DO(DIVR_D); + fpr[i.r0].d = fpr[i.r1].d / fpr[i.r2].d; + DISPATCH(); + + DO(LSHI); + gpr[i.r0] = gpr[i.r1] << i.o; + DISPATCH(); + + DO(LSHR); + gpr[i.r0] = gpr[i.r1] << gpr[i.r2]; + DISPATCH(); + + DO(RSHI); + gpr[i.r0] = gpr[i.r1] >> i.o; + DISPATCH(); + + DO(RSHR); + gpr[i.r0] = gpr[i.r1] >> gpr[i.r2]; + DISPATCH(); + + DO(RSHI_U); + gpr[i.r0] = (uint64_t)gpr[i.r1] >> i.o; + DISPATCH(); + + DO(RSHR_U); + gpr[i.r0] = (uint64_t)gpr[i.r1] >> gpr[i.r2]; + DISPATCH(); + + DO(ANDR); + gpr[i.r0] = gpr[i.r1] & gpr[i.r2]; + DISPATCH(); + + DO(ANDI); + gpr[i.r0] = gpr[i.r1] & i.o; + DISPATCH(); + + DO(ORR); + gpr[i.r0] = gpr[i.r1] | gpr[i.r2]; + DISPATCH(); + + DO(ORI); + gpr[i.r0] = gpr[i.r1] | i.o; + DISPATCH(); + + DO(XORR); + gpr[i.r0] = gpr[i.r1] ^ gpr[i.r2]; + DISPATCH(); + + DO(XORI); + gpr[i.r0] = gpr[i.r1] ^ i.o; + DISPATCH(); + + DO(COMR); + gpr[i.r0] = ~gpr[i.r1]; + DISPATCH(); + + DO(NEGR); + gpr[i.r0] = -gpr[i.r1]; + DISPATCH(); + + DO(NEGR_F); + fpr[i.r0].f = -fpr[i.r1].f; + DISPATCH(); + + DO(NEGR_D); + fpr[i.r0].d = -fpr[i.r1].d; + DISPATCH(); + + DO(EQR); + gpr[i.r0] = gpr[i.r1] == gpr[i.r2]; + DISPATCH(); + + DO(EQR_F); + gpr[i.r0] = fpr[i.r1].f == fpr[i.r2].f; + DISPATCH(); + + DO(EQR_D); + gpr[i.r0] = fpr[i.r1].d == fpr[i.r2].d; + DISPATCH(); + + DO(NER); + gpr[i.r0] = gpr[i.r1] != gpr[i.r2]; + DISPATCH(); + + DO(NER_F); + gpr[i.r0] = fpr[i.r1].f != fpr[i.r2].f; + DISPATCH(); + + DO(NER_D); + gpr[i.r0] = fpr[i.r1].d != fpr[i.r2].d; + DISPATCH(); + + DO(GTR); + gpr[i.r0] = gpr[i.r1] > gpr[i.r2]; + DISPATCH(); + + DO(GTR_U); + gpr[i.r0] = (uint64_t)gpr[i.r1] > (uint64_t)gpr[i.r2]; + DISPATCH(); + + DO(GTR_F); + gpr[i.r0] = fpr[i.r1].f > fpr[i.r2].f; + DISPATCH(); + + DO(GTR_D); + gpr[i.r0] = fpr[i.r1].d > fpr[i.r2].d; + DISPATCH(); + + DO(GER); + gpr[i.r0] = gpr[i.r1] >= gpr[i.r2]; + DISPATCH(); + + DO(GER_U); + gpr[i.r0] = (uint64_t)gpr[i.r1] >= (uint64_t)gpr[i.r2]; + DISPATCH(); + + DO(GER_F); + gpr[i.r0] = fpr[i.r1].f >= fpr[i.r2].f; + DISPATCH(); + + DO(GER_D); + gpr[i.r0] = fpr[i.r1].d >= fpr[i.r2].d; + DISPATCH(); + + DO(STI8); + int8_t *addr = (int8_t *)(i.p); + *addr = gpr[i.r0]; + DISPATCH(); + + DO(STI16); + int16_t *addr = (int16_t *)(i.p); + *addr = gpr[i.r0]; + DISPATCH(); + + DO(STI32); + int32_t *addr = (int32_t *)(i.p); + *addr = gpr[i.r0]; + DISPATCH(); + + DO(STI64); + int64_t *addr = (int64_t *)(i.p); + *addr = gpr[i.r0]; + DISPATCH(); + + DO(STIF); + float *addr = (float *)(i.p); + *addr = fpr[i.r0].f; + DISPATCH(); + + DO(STID); + double *addr = (double *)(i.p); + *addr = fpr[i.r0].d; + DISPATCH(); + + DO(STXI8); + int8_t *addr = (int8_t *)(uintptr_t)(gpr[i.r1] + i.o); + *addr = gpr[i.r0]; + DISPATCH(); + + DO(STXI16); + int16_t *addr = (int16_t *)(uintptr_t)(gpr[i.r1] + i.o); + *addr = gpr[i.r0]; + DISPATCH(); + + DO(STXI32); + int32_t *addr = (int32_t *)(uintptr_t)(gpr[i.r1] + i.o); + *addr = gpr[i.r0]; + DISPATCH(); + + DO(STXI64); + int64_t *addr = (int64_t *)(uintptr_t)(gpr[i.r1] + i.o); + *addr = gpr[i.r0]; + DISPATCH(); + + DO(STXIF); + float *addr = (float *)(uintptr_t)(gpr[i.r1] + i.o); + *addr = fpr[i.r0].f; + DISPATCH(); + + DO(STXID); + double *addr = (double *)(uintptr_t)(gpr[i.r1] + i.o); + *addr = fpr[i.r0].d; + DISPATCH(); + + DO(STXR8); + int8_t *addr = (int8_t *)(uintptr_t)(gpr[i.r1] + gpr[i.r2]); + *addr = gpr[i.r0]; + DISPATCH(); + + DO(STXR16); + int16_t *addr = (int16_t *)(uintptr_t)(gpr[i.r1] + gpr[i.r2]); + *addr = gpr[i.r0]; + DISPATCH(); + + DO(STXR32); + int32_t *addr = (int32_t *)(uintptr_t)(gpr[i.r1] + gpr[i.r2]); + *addr = gpr[i.r0]; + DISPATCH(); + + DO(STXR64); + int64_t *addr = (int64_t *)(uintptr_t)(gpr[i.r1] + gpr[i.r2]); + *addr = gpr[i.r0]; + DISPATCH(); + + DO(STXRF); + float *addr = (float *)(uintptr_t)(gpr[i.r1] + gpr[i.r2]); + *addr = fpr[i.r0].f; + DISPATCH(); + + DO(STXRD); + double *addr = (double *)(uintptr_t)(gpr[i.r1] + gpr[i.r2]); + *addr = fpr[i.r0].d; + DISPATCH(); + + DO(LDI8); + int8_t *addr = (int8_t *)i.p; + gpr[i.r0] = *addr; + DISPATCH(); + + DO(LDI16); + int16_t *addr = (int16_t *)i.p; + gpr[i.r0] = *addr; + DISPATCH(); + + DO(LDI32); + int32_t *addr = (int32_t *)i.p; + gpr[i.r0] = *addr; + DISPATCH(); + + DO(LDI64); + int64_t *addr = (int64_t *)i.p; + gpr[i.r0] = *addr; + DISPATCH(); + + DO(LDIU8); + uint8_t *addr = (uint8_t *)i.p; + gpr[i.r0] = *addr; + DISPATCH(); + + DO(LDIU16); + uint16_t *addr = (uint16_t *)i.p; + gpr[i.r0] = *addr; + DISPATCH(); + + DO(LDIU32); + uint32_t *addr = (uint32_t *)i.p; + gpr[i.r0] = *addr; + DISPATCH(); + + DO(LDIU64); + uint64_t *addr = (uint64_t *)i.p; + gpr[i.r0] = *addr; + DISPATCH(); + + DO(LDIF); + float *addr = (float *)i.p; + fpr[i.r0].f = *addr; + DISPATCH(); + + DO(LDID); + double *addr = (double *)i.p; + fpr[i.r0].d = *addr; + DISPATCH(); + + DO(LDXI8); + int8_t *addr = (int8_t *)(uintptr_t)(gpr[i.r1] + i.o); + gpr[i.r0] = *addr; + DISPATCH(); + + DO(LDXI16); + int16_t *addr = (int16_t *)(uintptr_t)(gpr[i.r1] + i.o); + gpr[i.r0] = *addr; + DISPATCH(); + + DO(LDXI32); + int32_t *addr = (int32_t *)(uintptr_t)(gpr[i.r1] + i.o); + gpr[i.r0] = *addr; + DISPATCH(); + + DO(LDXI64); + int64_t *addr = (int64_t *)(uintptr_t)(gpr[i.r1] + i.o); + gpr[i.r0] = *addr; + DISPATCH(); + + DO(LDXIU8); + uint8_t *addr = (uint8_t *)(uintptr_t)(gpr[i.r1] + i.o); + gpr[i.r0] = *addr; + DISPATCH(); + + DO(LDXIU16); + uint16_t *addr = (uint16_t *)(uintptr_t)(gpr[i.r1] + i.o); + gpr[i.r0] = *addr; + DISPATCH(); + + DO(LDXIU32); + uint32_t *addr = (uint32_t *)(uintptr_t)(gpr[i.r1] + i.o); + gpr[i.r0] = *addr; + DISPATCH(); + + DO(LDXIU64); + uint64_t *addr = (uint64_t *)(uintptr_t)(gpr[i.r1] + i.o); + gpr[i.r0] = *addr; + DISPATCH(); + + DO(LDXIF); + float *addr = (float *)(uintptr_t)(gpr[i.r1] + i.o); + fpr[i.r0].f = *addr; + DISPATCH(); + + DO(LDXID); + double *addr = (double *)(uintptr_t)(gpr[i.r1] + i.o); + fpr[i.r0].d = *addr; + DISPATCH(); + + DO(LDXR8); + int8_t *addr = (int8_t *)(uintptr_t)(gpr[i.r1] + gpr[i.r2]); + gpr[i.r0] = *addr; + DISPATCH(); + + DO(LDXR16); + int16_t *addr = (int16_t *)(uintptr_t)(gpr[i.r1] + gpr[i.r2]); + gpr[i.r0] = *addr; + DISPATCH(); + + DO(LDXR32); + int32_t *addr = (int32_t *)(uintptr_t)(gpr[i.r1] + gpr[i.r2]); + gpr[i.r0] = *addr; + DISPATCH(); + + DO(LDXR64); + int64_t *addr = (int64_t *)(uintptr_t)(gpr[i.r1] + gpr[i.r2]); + gpr[i.r0] = *addr; + DISPATCH(); + + DO(LDXRU8); + uint8_t *addr = (uint8_t *)(uintptr_t)(gpr[i.r1] + gpr[i.r2]); + gpr[i.r0] = *addr; + DISPATCH(); + + DO(LDXRU16); + uint16_t *addr = (uint16_t *)(uintptr_t)(gpr[i.r1] + gpr[i.r2]); + gpr[i.r0] = *addr; + DISPATCH(); + + DO(LDXRU32); + uint32_t *addr = (uint32_t *)(uintptr_t)(gpr[i.r1] + gpr[i.r2]); + gpr[i.r0] = *addr; + DISPATCH(); + + DO(LDXRU64); + uint64_t *addr = (uint64_t *)(uintptr_t)(gpr[i.r1] + gpr[i.r2]); + gpr[i.r0] = *addr; + DISPATCH(); + + DO(LDXRF); + float *addr = (float *)(uintptr_t)(gpr[i.r1] + gpr[i.r2]); + fpr[i.r0].f = *addr; + DISPATCH(); + + DO(LDXRD); + double *addr = (double *)(uintptr_t)(gpr[i.r1] + gpr[i.r2]); + fpr[i.r0].d = *addr; + DISPATCH(); + + DO(TRUNCR_D_32); + gpr[i.r0] = (int32_t)fpr[i.r1].d; + DISPATCH(); + + DO(TRUNCR_D_64); + gpr[i.r0] = (int64_t)fpr[i.r1].d; + DISPATCH(); + + DO(TRUNCR_F_32); + gpr[i.r0] = (int32_t)fpr[i.r1].f; + DISPATCH(); + + DO(TRUNCR_F_64); + gpr[i.r0] = (int64_t)fpr[i.r1].f; + DISPATCH(); + + DO(BNER); + if (gpr[i.r1] != gpr[i.r2]) + JUMP(i.r0); + + DISPATCH(); + + DO(BNEI); + if (gpr[i.r1] != i.o) + JUMP(i.r0); + + DISPATCH(); + + DO(BNER_F); + if (fpr[i.r1].f != fpr[i.r2].f) + JUMP(i.r0); + + DISPATCH(); + + DO(BNER_D); + if (fpr[i.r1].d != fpr[i.r2].d) + JUMP(i.r0); + + DISPATCH(); + + DO(BEQR); + if (gpr[i.r1] == gpr[i.r2]) + JUMP(i.r0); + + DISPATCH(); + + DO(BEQI); + if (gpr[i.r1] == i.o) + JUMP(i.r0); + + DISPATCH(); + + DO(BEQR_F); + if (fpr[i.r1].f == fpr[i.r2].f) + JUMP(i.r0); + + DISPATCH(); + + DO(BEQR_D); + if (fpr[i.r1].d == fpr[i.r2].d) + JUMP(i.r0); + + DISPATCH(); + + DO(BGTR); + if (gpr[i.r1] > gpr[i.r2]) + JUMP(i.r0); + + DISPATCH(); + + DO(BGTR_U); + if ((uint64_t)gpr[i.r1] > (uint64_t)gpr[i.r2]) + JUMP(i.r0); + + DISPATCH(); + + DO(BGTI); + if (gpr[i.r1] > i.o) + JUMP(i.r0); + + DISPATCH(); + + DO(BGTI_U); + if ((uint64_t)gpr[i.r1] > (uint64_t)i.o) + JUMP(i.r0); + + DISPATCH(); + + DO(BGTR_F); + if (fpr[i.r1].f > fpr[i.r2].f) + JUMP(i.r0); + + DISPATCH(); + + DO(BGTR_D); + if (fpr[i.r1].d > fpr[i.r2].d) + JUMP(i.r0); + + DISPATCH(); + + DO(BLTI); + if (gpr[i.r1] < i.o) + JUMP(i.r0); + + DISPATCH(); + + DO(BLTI_U); + if ((uint64_t)gpr[i.r1] < (uint64_t)i.o) + JUMP(i.r0); + + DISPATCH(); + + DO(BGER); + if (gpr[i.r1] >= gpr[i.r2]) + JUMP(i.r0); + + DISPATCH(); + + DO(BGER_U); + if ((uint64_t)gpr[i.r1] >= (uint64_t)gpr[i.r2]) + JUMP(i.r0); + + DISPATCH(); + + DO(BGEI); + if (gpr[i.r1] >= i.o) + JUMP(i.r0); + + DISPATCH(); + + DO(BGEI_U); + if ((uint64_t)gpr[i.r1] >= (uint64_t)i.o) + JUMP(i.r0); + + DISPATCH(); + + DO(BGER_F); + if (fpr[i.r1].f >= fpr[i.r2].f) + JUMP(i.r0); + + DISPATCH(); + + DO(BGER_D); + if (fpr[i.r1].d >= fpr[i.r2].d) + JUMP(i.r0); + + DISPATCH(); + + DO(BLEI); + if (gpr[i.r1] <= i.o) + JUMP(i.r0); + + DISPATCH(); + + DO(BLEI_U); + if ((uint64_t)gpr[i.r1] <= (uint64_t)i.o) + JUMP(i.r0); + + DISPATCH(); + + DO(JMP); + JUMP(i.r0); + DISPATCH(); + + DO(JMPR); + JUMP(gpr[i.r1]); + DISPATCH(); + + DO(BMSR); + if (gpr[i.r1] & gpr[i.r2]) + JUMP(i.r0); + + DISPATCH(); + + DO(BMSI); + if (gpr[i.r1] & i.o) + JUMP(i.r0); + + DISPATCH(); + + DO(BMCR); + if (!(gpr[i.r1] & gpr[i.r2])) + JUMP(i.r0); + + DISPATCH(); + + DO(BMCI); + if (!(gpr[i.r1] & i.o)) + JUMP(i.r0); + + DISPATCH(); + + DO(RETVAL); + gpr[i.r0] = retval; + DISPATCH(); + + DO(RETVAL_F); + fpr[i.r0].f = retval_f; + DISPATCH(); + + DO(RETVAL_D); + fpr[i.r0].d = retval_f; + DISPATCH(); + + DO(PARAM); + gpr[i.r2] = args[i.r0].u64; + DISPATCH(); + + DO(PARAM_F); + if (i.r1 == EJIT_FLOAT) + fpr[i.r2].f = args[i.r0].f; + else + fpr[i.r2].d = args[i.r0].d; + + DISPATCH(); + + DO(ARG); + struct ejit_arg a = ejit_build_arg(i.r1, gpr[i.r2]); + args_append(&state->args, a); + DISPATCH(); + + DO(ARG_I); + struct ejit_arg a = ejit_build_arg(i.r1, i.o); + args_append(&state->args, a); + DISPATCH(); + + DO(ARG_F); + struct ejit_arg a; + if (i.r1 == EJIT_DOUBLE) + a = ejit_build_arg_f(i.r1, fpr[i.r2].d); + else + a = ejit_build_arg_f(i.r1, fpr[i.r2].f); + + args_append(&state->args, a); + DISPATCH(); + + DO(ARG_FI); + struct ejit_arg a; + if (i.r1 == EJIT_DOUBLE) + a = ejit_build_arg_f(i.r1, i.d); + else + a = ejit_build_arg_f(i.r1, i.f); + + args_append(&state->args, a); + DISPATCH(); + + DO(CALLI_I); + struct ejit_func *f = i.p; + size_t argc = args_len(&state->args) - prev_argc; + struct ejit_arg *args = state->args.buf + prev_argc; + + retval = ejit_run(f, argc, args, state, true, NULL).i; + + gpr = state->gprs.buf + prev_gprs; + fpr = (union fpr *)state->fprs.buf + prev_fprs; + args_shrink(&state->args, prev_argc); + DISPATCH(); + + DO(CALLI_L); + struct ejit_func *f = i.p; + size_t argc = args_len(&state->args) - prev_argc; + struct ejit_arg *args = state->args.buf + prev_argc; + + retval = ejit_run(f, argc, args, state, true, NULL).i; + + gpr = state->gprs.buf + prev_gprs; + fpr = (union fpr *)state->fprs.buf + prev_fprs; + args_shrink(&state->args, prev_argc); + DISPATCH(); + + DO(CALLI_F); + struct ejit_func *f = i.p; + size_t argc = args_len(&state->args) - prev_argc; + struct ejit_arg *args = state->args.buf + prev_argc; + + retval_f = ejit_run(f, argc, args, state, true, NULL).f; + + gpr = state->gprs.buf + prev_gprs; + fpr = (union fpr *)state->fprs.buf + prev_fprs; + args_shrink(&state->args, prev_argc); + DISPATCH(); + + DO(CALLI_D); + struct ejit_func *f = i.p; + size_t argc = args_len(&state->args) - prev_argc; + struct ejit_arg *args = state->args.buf + prev_argc; + + retval_f = ejit_run(f, argc, args, state, true, NULL).f; + + gpr = state->gprs.buf + prev_gprs; + fpr = (union fpr *)state->fprs.buf + prev_fprs; + args_shrink(&state->args, prev_argc); + DISPATCH(); + + DO(ESCAPEI_I); + ejit_escape_i_t f = i.p; + size_t argc = args_len(&state->args) - prev_argc; + struct ejit_arg *args = state->args.buf + prev_argc; + + retval = f(argc, args); + + args_shrink(&state->args, prev_argc); + DISPATCH(); + + DO(ESCAPEI_L); + ejit_escape_l_t f = i.p; + size_t argc = args_len(&state->args) - prev_argc; + struct ejit_arg *args = state->args.buf + prev_argc; + + retval = f(argc, args); + + args_shrink(&state->args, prev_argc); + DISPATCH(); + + DO(ESCAPEI_F); + ejit_escape_f_t f = i.p; + size_t argc = args_len(&state->args) - prev_argc; + struct ejit_arg *args = state->args.buf + prev_argc; + + retval_f = f(argc, args); + + args_shrink(&state->args, prev_argc); + DISPATCH(); + + DO(ESCAPEI_D); + ejit_escape_d_t f = i.p; + size_t argc = args_len(&state->args) - prev_argc; + struct ejit_arg *args = state->args.buf + prev_argc; + + retval_f = f(argc, args); + + args_shrink(&state->args, prev_argc); + DISPATCH(); + + /* dispatch is technically unnecessary for returns, but keep it for + * symmetry */ + DO(RETR); + retval = gpr[i.r1]; + goto out_int; + DISPATCH(); + + DO(RETI); + retval = i.o; + goto out_int; + DISPATCH(); + + DO(RETR_F); + retval_f = fpr[i.r1].f; + goto out_float; + DISPATCH(); + + DO(RETR_D); + retval_f = fpr[i.r1].d; + goto out_float; + DISPATCH(); + + DO(RETI_F); + retval_f = i.f; + goto out_float; + DISPATCH(); + + DO(RETI_D); + retval_f = i.d; + goto out_float; + DISPATCH(); + +#undef DISPATCH +#undef JUMP +#undef DO + +out_float: + gprs_shrink(&state->gprs, prev_gprs); + fprs_shrink(&state->fprs, prev_fprs); + return (union interp_ret){.f = retval_f}; + +out_int: + gprs_shrink(&state->gprs, prev_gprs); + fprs_shrink(&state->fprs, prev_fprs); + return (union interp_ret){.i = retval}; + +zero_out: + return (union interp_ret){.i = 0}; +} diff --git a/src/interp.inc b/src/interp.inc deleted file mode 100644 index a88bec8..0000000 --- a/src/interp.inc +++ /dev/null @@ -1,1077 +0,0 @@ -/* 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 */ -{ - 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] = &&CALLI, - [CALLI_F] = &&CALLI_F, - [ESCAPEI] = &&ESCAPEI, - [ESCAPEI_F] = &&ESCAPEI_F, - - [START] = &&START, - [END] = &&END, - }; - - if (!run) { - *labels_wb = labels; - goto zero_out; - } - - size_t prev_gprs = gprs_len(&state->gprs); - size_t prev_fprs = fprs_len(&state->fprs); - size_t prev_argc = args_len(&state->args); - - gprs_reserve(&state->gprs, prev_gprs + gpr_stats_len(&f->gpr)); - fprs_reserve(&state->fprs, prev_fprs + fpr_stats_len(&f->fpr)); - - union fpr { - double d; - float f; - }; - long *gpr = ((long *)state->gprs.buf) + prev_gprs; - union fpr *fpr = ((union fpr *)state->fprs.buf) + prev_fprs; - - struct ejit_insn *insns = f->insns.buf; - - /* retval is kind of an unfortunate extra bit of state to keep track of, - * but having call and return value separated is pretty convenient for - * void calls so I guess I don't mind? */ - size_t pc = 0; - -#define DO(x) x : { struct ejit_insn i = insns[pc]; (void)i; -#define JUMP(a) goto *insns[pc = a].addr; -#define DISPATCH() } goto *insns[++pc].addr; - - JUMP(0); - - DO(START); - DISPATCH(); - - DO(END); - goto out; - DISPATCH(); - - DO(MOVI); - gpr[i.r0] = i.o; - DISPATCH(); - - DO(MOVI_F); - fpr[i.r0].f = i.f; - DISPATCH(); - - DO(MOVI_D); - fpr[i.r0].d = i.d; - DISPATCH(); - - DO(MOVR); - gpr[i.r0] = gpr[i.r1]; - DISPATCH(); - - DO(MOVR_F); - fpr[i.r0].f = fpr[i.r1].f; - DISPATCH(); - - DO(MOVR_D); - fpr[i.r0].d = fpr[i.r1].d; - DISPATCH(); - - DO(EXTR8); - gpr[i.r0] = (int8_t)gpr[i.r1]; - DISPATCH(); - - DO(EXTR16); - gpr[i.r0] = (int16_t)gpr[i.r1]; - DISPATCH(); - - DO(EXTR32); - gpr[i.r0] = (int32_t)gpr[i.r1]; - DISPATCH(); - - DO(EXTRU8); - gpr[i.r0] = (uint8_t)gpr[i.r1]; - DISPATCH(); - - DO(EXTRU16); - gpr[i.r0] = (uint16_t)gpr[i.r1]; - DISPATCH(); - - DO(EXTRU32); - gpr[i.r0] = (uint32_t)gpr[i.r1]; - DISPATCH(); - - DO(EXTRF); - fpr[i.r0].f = (float)gpr[i.r1]; - DISPATCH(); - - DO(EXTRD); - fpr[i.r0].d = (double)gpr[i.r1]; - DISPATCH(); - - DO(ADDR); - gpr[i.r0] = gpr[i.r1] + gpr[i.r2]; - DISPATCH(); - - DO(ADDR_F); - fpr[i.r0].f = fpr[i.r1].f + fpr[i.r2].f; - DISPATCH(); - - DO(ADDR_D); - fpr[i.r0].d = fpr[i.r1].d + fpr[i.r2].d; - DISPATCH(); - - DO(ADDI); - gpr[i.r0] = gpr[i.r1] + i.o; - DISPATCH(); - - DO(ABSR_F); - fpr[i.r0].f = fabs(fpr[i.r1].f); - DISPATCH(); - - DO(ABSR_D); - fpr[i.r0].d = fabs(fpr[i.r1].d); - DISPATCH(); - - DO(SUBR); - gpr[i.r0] = gpr[i.r1] - gpr[i.r2]; - DISPATCH(); - - DO(SUBR_F); - fpr[i.r0].f = fpr[i.r1].f - fpr[i.r2].f; - DISPATCH(); - - DO(SUBR_D); - fpr[i.r0].d = fpr[i.r1].d - fpr[i.r2].d; - DISPATCH(); - - DO(SUBI); - gpr[i.r0] = gpr[i.r1] - i.o; - DISPATCH(); - - DO(MULR); - gpr[i.r0] = gpr[i.r1] * gpr[i.r2]; - DISPATCH(); - - DO(MULR_F); - fpr[i.r0].f = fpr[i.r1].f * fpr[i.r2].f; - DISPATCH(); - - DO(MULR_D); - fpr[i.r0].d = fpr[i.r1].d * fpr[i.r2].d; - DISPATCH(); - - DO(DIVR); - gpr[i.r0] = gpr[i.r1] / gpr[i.r2]; - DISPATCH(); - - DO(DIVR_U); - gpr[i.r0] = (uint64_t)gpr[i.r1] / (uint64_t)gpr[i.r2]; - DISPATCH(); - - DO(REMR); - gpr[i.r0] = gpr[i.r1] % gpr[i.r2]; - DISPATCH(); - - DO(REMR_U); - gpr[i.r0] = (uint64_t)gpr[i.r1] % (uint64_t)gpr[i.r2]; - DISPATCH(); - - DO(DIVR_F); - fpr[i.r0].f = fpr[i.r1].f / fpr[i.r2].f; - DISPATCH(); - - DO(DIVR_D); - fpr[i.r0].d = fpr[i.r1].d / fpr[i.r2].d; - DISPATCH(); - - DO(LSHI); - gpr[i.r0] = gpr[i.r1] << i.o; - DISPATCH(); - - DO(LSHR); - gpr[i.r0] = gpr[i.r1] << gpr[i.r2]; - DISPATCH(); - - DO(RSHI); - gpr[i.r0] = gpr[i.r1] >> i.o; - DISPATCH(); - - DO(RSHR); - gpr[i.r0] = gpr[i.r1] >> gpr[i.r2]; - DISPATCH(); - - DO(RSHI_U); - gpr[i.r0] = (uint64_t)gpr[i.r1] >> i.o; - DISPATCH(); - - DO(RSHR_U); - gpr[i.r0] = (uint64_t)gpr[i.r1] >> gpr[i.r2]; - DISPATCH(); - - DO(ANDR); - gpr[i.r0] = gpr[i.r1] & gpr[i.r2]; - DISPATCH(); - - DO(ANDI); - gpr[i.r0] = gpr[i.r1] & i.o; - DISPATCH(); - - DO(ORR); - gpr[i.r0] = gpr[i.r1] | gpr[i.r2]; - DISPATCH(); - - DO(ORI); - gpr[i.r0] = gpr[i.r1] | i.o; - DISPATCH(); - - DO(XORR); - gpr[i.r0] = gpr[i.r1] ^ gpr[i.r2]; - DISPATCH(); - - DO(XORI); - gpr[i.r0] = gpr[i.r1] ^ i.o; - DISPATCH(); - - DO(COMR); - gpr[i.r0] = ~gpr[i.r1]; - DISPATCH(); - - DO(NEGR); - gpr[i.r0] = -gpr[i.r1]; - DISPATCH(); - - DO(NEGR_F); - fpr[i.r0].f = -fpr[i.r1].f; - DISPATCH(); - - DO(NEGR_D); - fpr[i.r0].d = -fpr[i.r1].d; - DISPATCH(); - - DO(EQR); - gpr[i.r0] = gpr[i.r1] == gpr[i.r2]; - DISPATCH(); - - DO(EQR_F); - gpr[i.r0] = fpr[i.r1].f == fpr[i.r2].f; - DISPATCH(); - - DO(EQR_D); - gpr[i.r0] = fpr[i.r1].d == fpr[i.r2].d; - DISPATCH(); - - DO(NER); - gpr[i.r0] = gpr[i.r1] != gpr[i.r2]; - DISPATCH(); - - DO(NER_F); - gpr[i.r0] = fpr[i.r1].f != fpr[i.r2].f; - DISPATCH(); - - DO(NER_D); - gpr[i.r0] = fpr[i.r1].d != fpr[i.r2].d; - DISPATCH(); - - DO(GTR); - gpr[i.r0] = gpr[i.r1] > gpr[i.r2]; - DISPATCH(); - - DO(GTR_U); - gpr[i.r0] = (uint64_t)gpr[i.r1] > (uint64_t)gpr[i.r2]; - DISPATCH(); - - DO(GTR_F); - gpr[i.r0] = fpr[i.r1].f > fpr[i.r2].f; - DISPATCH(); - - DO(GTR_D); - gpr[i.r0] = fpr[i.r1].d > fpr[i.r2].d; - DISPATCH(); - - DO(GER); - gpr[i.r0] = gpr[i.r1] >= gpr[i.r2]; - DISPATCH(); - - DO(GER_U); - gpr[i.r0] = (uint64_t)gpr[i.r1] >= (uint64_t)gpr[i.r2]; - DISPATCH(); - - DO(GER_F); - gpr[i.r0] = fpr[i.r1].f >= fpr[i.r2].f; - DISPATCH(); - - DO(GER_D); - gpr[i.r0] = fpr[i.r1].d >= fpr[i.r2].d; - DISPATCH(); - - DO(STI8); - int8_t *addr = (int8_t *)(i.p); - *addr = gpr[i.r0]; - DISPATCH(); - - DO(STI16); - int16_t *addr = (int16_t *)(i.p); - *addr = gpr[i.r0]; - DISPATCH(); - - DO(STI32); - int32_t *addr = (int32_t *)(i.p); - *addr = gpr[i.r0]; - DISPATCH(); - - DO(STI64); - int64_t *addr = (int64_t *)(i.p); - *addr = gpr[i.r0]; - DISPATCH(); - - DO(STIF); - float *addr = (float *)(i.p); - *addr = fpr[i.r0].f; - DISPATCH(); - - DO(STID); - double *addr = (double *)(i.p); - *addr = fpr[i.r0].d; - DISPATCH(); - - DO(STXI8); - int8_t *addr = (int8_t *)(gpr[i.r1] + i.o); - *addr = gpr[i.r0]; - DISPATCH(); - - DO(STXI16); - int16_t *addr = (int16_t *)(gpr[i.r1] + i.o); - *addr = gpr[i.r0]; - DISPATCH(); - - DO(STXI32); - int32_t *addr = (int32_t *)(gpr[i.r1] + i.o); - *addr = gpr[i.r0]; - DISPATCH(); - - DO(STXI64); - int64_t *addr = (int64_t *)(gpr[i.r1] + i.o); - *addr = gpr[i.r0]; - DISPATCH(); - - DO(STXIF); - float *addr = (float *)(gpr[i.r1] + i.o); - *addr = fpr[i.r0].f; - DISPATCH(); - - DO(STXID); - double *addr = (double *)(gpr[i.r1] + i.o); - *addr = fpr[i.r0].d; - DISPATCH(); - - DO(STXR8); - int8_t *addr = (int8_t *)(gpr[i.r1] + gpr[i.r2]); - *addr = gpr[i.r0]; - DISPATCH(); - - DO(STXR16); - int16_t *addr = (int16_t *)(gpr[i.r1] + gpr[i.r2]); - *addr = gpr[i.r0]; - DISPATCH(); - - DO(STXR32); - int32_t *addr = (int32_t *)(gpr[i.r1] + gpr[i.r2]); - *addr = gpr[i.r0]; - DISPATCH(); - - DO(STXR64); - int64_t *addr = (int64_t *)(gpr[i.r1] + gpr[i.r2]); - *addr = gpr[i.r0]; - DISPATCH(); - - DO(STXRF); - float *addr = (float *)(gpr[i.r1] + gpr[i.r2]); - *addr = fpr[i.r0].f; - DISPATCH(); - - DO(STXRD); - double *addr = (double *)(gpr[i.r1] + gpr[i.r2]); - *addr = fpr[i.r0].d; - DISPATCH(); - - DO(LDI8); - int8_t *addr = (int8_t *)i.p; - gpr[i.r0] = *addr; - DISPATCH(); - - DO(LDI16); - int16_t *addr = (int16_t *)i.p; - gpr[i.r0] = *addr; - DISPATCH(); - - DO(LDI32); - int32_t *addr = (int32_t *)i.p; - gpr[i.r0] = *addr; - DISPATCH(); - - DO(LDI64); - int64_t *addr = (int64_t *)i.p; - gpr[i.r0] = *addr; - DISPATCH(); - - DO(LDIU8); - uint8_t *addr = (uint8_t *)i.p; - gpr[i.r0] = *addr; - DISPATCH(); - - DO(LDIU16); - uint16_t *addr = (uint16_t *)i.p; - gpr[i.r0] = *addr; - DISPATCH(); - - DO(LDIU32); - uint32_t *addr = (uint32_t *)i.p; - gpr[i.r0] = *addr; - DISPATCH(); - - DO(LDIU64); - uint64_t *addr = (uint64_t *)i.p; - gpr[i.r0] = *addr; - DISPATCH(); - - DO(LDIF); - float *addr = (float *)i.p; - fpr[i.r0].f = *addr; - DISPATCH(); - - DO(LDID); - double *addr = (double *)i.p; - fpr[i.r0].d = *addr; - DISPATCH(); - - DO(LDXI8); - int8_t *addr = (int8_t *)(gpr[i.r1] + i.o); - gpr[i.r0] = *addr; - DISPATCH(); - - DO(LDXI16); - int16_t *addr = (int16_t *)(gpr[i.r1] + i.o); - gpr[i.r0] = *addr; - DISPATCH(); - - DO(LDXI32); - int32_t *addr = (int32_t *)(gpr[i.r1] + i.o); - gpr[i.r0] = *addr; - DISPATCH(); - - DO(LDXI64); - int64_t *addr = (int64_t *)(gpr[i.r1] + i.o); - gpr[i.r0] = *addr; - DISPATCH(); - - DO(LDXIU8); - uint8_t *addr = (uint8_t *)(gpr[i.r1] + i.o); - gpr[i.r0] = *addr; - DISPATCH(); - - DO(LDXIU16); - uint16_t *addr = (uint16_t *)(gpr[i.r1] + i.o); - gpr[i.r0] = *addr; - DISPATCH(); - - DO(LDXIU32); - uint32_t *addr = (uint32_t *)(gpr[i.r1] + i.o); - gpr[i.r0] = *addr; - DISPATCH(); - - DO(LDXIU64); - uint64_t *addr = (uint64_t *)(gpr[i.r1] + i.o); - gpr[i.r0] = *addr; - DISPATCH(); - - DO(LDXIF); - float *addr = (float *)(gpr[i.r1] + i.o); - fpr[i.r0].f = *addr; - DISPATCH(); - - DO(LDXID); - double *addr = (double *)(gpr[i.r1] + i.o); - fpr[i.r0].d = *addr; - DISPATCH(); - - DO(LDXR8); - int8_t *addr = (int8_t *)(gpr[i.r1] + gpr[i.r2]); - gpr[i.r0] = *addr; - DISPATCH(); - - DO(LDXR16); - int16_t *addr = (int16_t *)(gpr[i.r1] + gpr[i.r2]); - gpr[i.r0] = *addr; - DISPATCH(); - - DO(LDXR32); - int32_t *addr = (int32_t *)(gpr[i.r1] + gpr[i.r2]); - gpr[i.r0] = *addr; - DISPATCH(); - - DO(LDXR64); - int64_t *addr = (int64_t *)(gpr[i.r1] + gpr[i.r2]); - gpr[i.r0] = *addr; - DISPATCH(); - - DO(LDXRU8); - uint8_t *addr = (uint8_t *)(gpr[i.r1] + gpr[i.r2]); - gpr[i.r0] = *addr; - DISPATCH(); - - DO(LDXRU16); - uint16_t *addr = (uint16_t *)(gpr[i.r1] + gpr[i.r2]); - gpr[i.r0] = *addr; - DISPATCH(); - - DO(LDXRU32); - uint32_t *addr = (uint32_t *)(gpr[i.r1] + gpr[i.r2]); - gpr[i.r0] = *addr; - DISPATCH(); - - DO(LDXRU64); - uint64_t *addr = (uint64_t *)(gpr[i.r1] + gpr[i.r2]); - gpr[i.r0] = *addr; - DISPATCH(); - - DO(LDXRF); - float *addr = (float *)(gpr[i.r1] + gpr[i.r2]); - fpr[i.r0].f = *addr; - DISPATCH(); - - DO(LDXRD); - double *addr = (double *)(gpr[i.r1] + gpr[i.r2]); - fpr[i.r0].d = *addr; - DISPATCH(); - - DO(TRUNCR_D_32); - gpr[i.r0] = (int32_t)fpr[i.r1].d; - DISPATCH(); - - DO(TRUNCR_D_64); - gpr[i.r0] = (int64_t)fpr[i.r1].d; - DISPATCH(); - - DO(TRUNCR_F_32); - gpr[i.r0] = (int32_t)fpr[i.r1].f; - DISPATCH(); - - DO(TRUNCR_F_64); - gpr[i.r0] = (int64_t)fpr[i.r1].f; - DISPATCH(); - - DO(BNER); - if (gpr[i.r1] != gpr[i.r2]) - JUMP(i.r0); - - DISPATCH(); - - DO(BNEI); - if (gpr[i.r1] != i.o) - JUMP(i.r0); - - DISPATCH(); - - DO(BNER_F); - if (fpr[i.r1].f != fpr[i.r2].f) - JUMP(i.r0); - - DISPATCH(); - - DO(BNER_D); - if (fpr[i.r1].d != fpr[i.r2].d) - JUMP(i.r0); - - DISPATCH(); - - DO(BEQR); - if (gpr[i.r1] == gpr[i.r2]) - JUMP(i.r0); - - DISPATCH(); - - DO(BEQI); - if (gpr[i.r1] == i.o) - JUMP(i.r0); - - DISPATCH(); - - DO(BEQR_F); - if (fpr[i.r1].f == fpr[i.r2].f) - JUMP(i.r0); - - DISPATCH(); - - DO(BEQR_D); - if (fpr[i.r1].d == fpr[i.r2].d) - JUMP(i.r0); - - DISPATCH(); - - DO(BGTR); - if (gpr[i.r1] > gpr[i.r2]) - JUMP(i.r0); - - DISPATCH(); - - DO(BGTR_U); - if ((uint64_t)gpr[i.r1] > (uint64_t)gpr[i.r2]) - JUMP(i.r0); - - DISPATCH(); - - DO(BGTI); - if (gpr[i.r1] > i.o) - JUMP(i.r0); - - DISPATCH(); - - DO(BGTI_U); - if ((uint64_t)gpr[i.r1] > (uint64_t)i.o) - JUMP(i.r0); - - DISPATCH(); - - DO(BGTR_F); - if (fpr[i.r1].f > fpr[i.r2].f) - JUMP(i.r0); - - DISPATCH(); - - DO(BGTR_D); - if (fpr[i.r1].d > fpr[i.r2].d) - JUMP(i.r0); - - DISPATCH(); - - DO(BLTI); - if (gpr[i.r1] < i.o) - JUMP(i.r0); - - DISPATCH(); - - DO(BLTI_U); - if ((uint64_t)gpr[i.r1] < (uint64_t)i.o) - JUMP(i.r0); - - DISPATCH(); - - DO(BGER); - if (gpr[i.r1] >= gpr[i.r2]) - JUMP(i.r0); - - DISPATCH(); - - DO(BGER_U); - if ((uint64_t)gpr[i.r1] >= (uint64_t)gpr[i.r2]) - JUMP(i.r0); - - DISPATCH(); - - DO(BGEI); - if (gpr[i.r1] >= i.o) - JUMP(i.r0); - - DISPATCH(); - - DO(BGEI_U); - if ((uint64_t)gpr[i.r1] >= (uint64_t)i.o) - JUMP(i.r0); - - DISPATCH(); - - DO(BGER_F); - if (fpr[i.r1].f >= fpr[i.r2].f) - JUMP(i.r0); - - DISPATCH(); - - DO(BGER_D); - if (fpr[i.r1].d >= fpr[i.r2].d) - JUMP(i.r0); - - DISPATCH(); - - DO(BLEI); - if (gpr[i.r1] <= i.o) - JUMP(i.r0); - - DISPATCH(); - - DO(BLEI_U); - if ((uint64_t)gpr[i.r1] <= (uint64_t)i.o) - JUMP(i.r0); - - DISPATCH(); - - DO(JMP); - JUMP(i.r0); - DISPATCH(); - - DO(JMPR); - JUMP(gpr[i.r1]); - DISPATCH(); - - DO(BMSR); - if (gpr[i.r1] & gpr[i.r2]) - JUMP(i.r0); - - DISPATCH(); - - DO(BMSI); - if (gpr[i.r1] & i.o) - JUMP(i.r0); - - DISPATCH(); - - DO(BMCR); - if (!(gpr[i.r1] & gpr[i.r2])) - JUMP(i.r0); - - DISPATCH(); - - DO(BMCI); - if (!(gpr[i.r1] & i.o)) - JUMP(i.r0); - - DISPATCH(); - - DO(RETVAL); - gpr[i.r0] = retval; - DISPATCH(); - - DO(RETVAL_F); - fpr[i.r0].f = retval_f; - DISPATCH(); - - DO(RETVAL_D); - fpr[i.r0].d = retval_f; - DISPATCH(); - - DO(PARAM); - gpr[i.r2] = args[i.r0].u64; - DISPATCH(); - - DO(PARAM_F); - if (i.r1 == EJIT_FLOAT) - fpr[i.r2].f = args[i.r0].f; - else - fpr[i.r2].d = args[i.r0].d; - - DISPATCH(); - - DO(ARG); - struct ejit_arg a = ejit_build_arg(i.r1, gpr[i.r2]); - args_append(&state->args, a); - DISPATCH(); - - DO(ARG_I); - struct ejit_arg a = ejit_build_arg(i.r1, i.o); - args_append(&state->args, a); - DISPATCH(); - - DO(ARG_F); - struct ejit_arg a; - if (i.r1 == EJIT_DOUBLE) - a = ejit_build_arg_f(i.r1, fpr[i.r2].d); - else - a = ejit_build_arg_f(i.r1, fpr[i.r2].f); - - args_append(&state->args, a); - DISPATCH(); - - DO(ARG_FI); - struct ejit_arg a; - if (i.r1 == EJIT_DOUBLE) - a = ejit_build_arg_f(i.r1, i.d); - else - a = ejit_build_arg_f(i.r1, i.f); - - args_append(&state->args, a); - DISPATCH(); - - DO(CALLI); - struct ejit_func *f = i.p; - size_t argc = args_len(&state->args) - prev_argc; - struct ejit_arg *args = ((struct ejit_arg *)state->args.buf) + - prev_argc; - - retval = ejit_run_interp(f, argc, args, state, true, NULL); - - gpr = ((long *)state->gprs.buf) + prev_gprs; - fpr = ((union fpr *)state->fprs.buf) + prev_fprs; - args_shrink(&state->args, prev_argc); - DISPATCH(); - - DO(CALLI_F); - struct ejit_func *f = i.p; - size_t argc = args_len(&state->args) - prev_argc; - struct ejit_arg *args = ((struct ejit_arg *)state->args.buf) + - prev_argc; - - retval_f = ejit_run_interp_f(f, argc, args, state, true, NULL); - - gpr = ((long *)state->gprs.buf) + prev_gprs; - fpr = ((union fpr *)state->fprs.buf) + prev_fprs; - args_shrink(&state->args, prev_argc); - DISPATCH(); - - DO(ESCAPEI); - ejit_escape_t f = i.p; - size_t argc = args_len(&state->args) - prev_argc; - struct ejit_arg *args = ((struct ejit_arg *)state->args.buf) + - prev_argc; - - retval = f(argc, args); - - args_shrink(&state->args, prev_argc); - DISPATCH(); - - DO(ESCAPEI_F); - ejit_escape_f_t f = i.p; - size_t argc = args_len(&state->args) - prev_argc; - struct ejit_arg *args = ((struct ejit_arg *)state->args.buf) + - prev_argc; - - retval_f = f(argc, args); - - args_shrink(&state->args, prev_argc); - DISPATCH(); - - /* dispatch is technically unnecessary for returns, but keep it for - * symmetry */ - DO(RETR); - retval = gpr[i.r1]; - goto out; - DISPATCH(); - - DO(RETI); - retval = i.o; - goto out; - DISPATCH(); - - DO(RETR_F); - retval_f = fpr[i.r1].f; - goto out; - DISPATCH(); - - DO(RETR_D); - retval_f = fpr[i.r1].d; - goto out; - DISPATCH(); - - DO(RETI_F); - retval_f = i.f; - goto out; - DISPATCH(); - - DO(RETI_D); - retval_f = i.d; - goto out; - DISPATCH(); - -#undef DISPATCH -#undef JUMP -#undef DO - -out: - gprs_shrink(&state->gprs, prev_gprs); - fprs_shrink(&state->fprs, prev_fprs); - -zero_out: -} diff --git a/src/vec.h b/src/vec.h index f982bac..f5a6fd9 100644 --- a/src/vec.h +++ b/src/vec.h @@ -73,6 +73,7 @@ static inline void VEC(append)(struct VEC_STRUCT *v, VEC_TYPE n) if (v->n >= v->s) { v->s *= 2; v->buf = realloc(v->buf, v->s * sizeof(VEC_TYPE)); + assert(v->buf); } v->buf[v->n - 1] = n; @@ -99,6 +100,9 @@ static inline void VEC(reserve)(struct VEC_STRUCT *v, size_t n) return; v->n = n; + if (v->s >= v->n) + return; + while (v->s < v->n) v->s *= 2; -- cgit v1.2.3