diff options
author | Kimplul <kimi.h.kuparinen@gmail.com> | 2024-06-29 14:20:07 +0300 |
---|---|---|
committer | Kimplul <kimi.h.kuparinen@gmail.com> | 2024-06-29 14:20:07 +0300 |
commit | 49aa680ccdac46d1d2a7f9f250999b7ff7099548 (patch) | |
tree | 1de3bd5209feadfd147f7a05d1ac925f98b747b1 /src | |
parent | 29718f2e84478b296c3198ae6d35cfd5d79efb14 (diff) | |
download | ejit-49aa680ccdac46d1d2a7f9f250999b7ff7099548.tar.gz ejit-49aa680ccdac46d1d2a7f9f250999b7ff7099548.zip |
start adding tests
Diffstat (limited to 'src')
-rw-r--r-- | src/common.h | 20 | ||||
-rw-r--r-- | src/compile/compile.c | 127 | ||||
-rw-r--r-- | src/ejit.c | 137 | ||||
-rw-r--r-- | src/interp.c | 40 |
4 files changed, 207 insertions, 117 deletions
diff --git a/src/common.h b/src/common.h index 1f2289d..c3442c6 100644 --- a/src/common.h +++ b/src/common.h @@ -57,6 +57,8 @@ enum ejit_opcode { ADDR_F, ADDI, + ABSR_F, + SUBR, SUBR_F, SUBI, @@ -88,10 +90,10 @@ enum ejit_opcode { CALLI, CALLI_F, - RET, - RET_I, - RET_F, - RET_FI, + RETR, + RETI, + RETR_F, + RETI_F, RETVAL, RETVAL_F, @@ -132,7 +134,7 @@ struct ejit_func { union interp_ret { - long r; + int64_t r; double d; }; @@ -142,9 +144,13 @@ struct interp_state { struct vec args; }; -union interp_ret ejit_interp(struct ejit_func *f, size_t argc, struct ejit_arg args[argc], struct interp_state *state, bool run, void ***labels_wb); +union interp_ret ejit_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_interp(struct ejit_func *f, size_t argc, struct ejit_arg args[argc], struct interp_state *state); +int64_t ejit_run_interp(struct ejit_func *f, size_t argc, + struct ejit_arg args[argc], struct interp_state *state); bool ejit_compile(struct ejit_func *f); diff --git a/src/compile/compile.c b/src/compile/compile.c index c07a46a..c9a92a2 100644 --- a/src/compile/compile.c +++ b/src/compile/compile.c @@ -5,8 +5,8 @@ static void *alloc_arena(size_t size) { return mmap(NULL, size, - PROT_EXEC | PROT_READ | PROT_WRITE, - MAP_PRIVATE | MAP_ANONYMOUS, -1, 0); + PROT_EXEC | PROT_READ | PROT_WRITE, + MAP_PRIVATE | MAP_ANONYMOUS, -1, 0); } static void free_arena(void *arena, size_t size) @@ -27,7 +27,7 @@ static size_t frploc_count(struct ejit_func *f) static size_t stack_size(struct ejit_func *f) { return grploc_count(f) * sizeof(jit_uword_t) - + frploc_count(f) * sizeof(jit_float64_t); + + frploc_count(f) * sizeof(jit_float64_t); } static jit_off_t stack_loc(size_t l) @@ -40,7 +40,7 @@ static jit_off_t stack_loc_f(struct ejit_func *f, size_t l) { assert(l >= jit_vf_num()); return grploc_count(f) * sizeof(jit_uword_t) - + (l - jit_vf_num()) * sizeof(jit_float64_t); + + (l - jit_vf_num()) * sizeof(jit_float64_t); } @@ -84,14 +84,16 @@ static void compile_label(jit_state_t *j, size_t ii, struct vec *labels) vect_at(jit_addr_t, *labels, ii) = jit_address(j); } -static void compile_movi(struct ejit_func *f, jit_state_t *j, struct ejit_insn i) +static void compile_movi(struct ejit_func *f, jit_state_t *j, + struct ejit_insn i) { jit_gpr_t r = getreg(f, i.r0, 0); jit_movi(j, r, i.o); putloc(f, j, i.r0, r); } -static void compile_movr(struct ejit_func *f, jit_state_t *j, struct ejit_insn i) +static void compile_movr(struct ejit_func *f, jit_state_t *j, + struct ejit_insn i) { jit_gpr_t to = getreg(f, i.r0, 0); jit_gpr_t from = getreg(f, i.r1, 1); @@ -99,7 +101,8 @@ static void compile_movr(struct ejit_func *f, jit_state_t *j, struct ejit_insn i putloc(f, j, i.r0, to); } -static void compile_addr(struct ejit_func *f, jit_state_t *j, struct ejit_insn i) +static void compile_addr(struct ejit_func *f, jit_state_t *j, + struct ejit_insn i) { jit_gpr_t dst = getreg(f, i.r0, 0); jit_gpr_t src0 = getloc(f, j, i.r1, 1); @@ -108,7 +111,8 @@ static void compile_addr(struct ejit_func *f, jit_state_t *j, struct ejit_insn i putloc(f, j, i.r0, dst); } -static void compile_addi(struct ejit_func *f, jit_state_t *j, struct ejit_insn i) +static void compile_addi(struct ejit_func *f, jit_state_t *j, + struct ejit_insn i) { jit_gpr_t dst = getreg(f, i.r0, 0); jit_gpr_t src0 = getloc(f, j, i.r1, 1); @@ -116,7 +120,8 @@ static void compile_addi(struct ejit_func *f, jit_state_t *j, struct ejit_insn i putloc(f, j, i.r0, dst); } -static void compile_subr(struct ejit_func *f, jit_state_t *j, struct ejit_insn i) +static void compile_subr(struct ejit_func *f, jit_state_t *j, + struct ejit_insn i) { jit_gpr_t dst = getreg(f, i.r0, 0); jit_gpr_t src0 = getloc(f, j, i.r1, 1); @@ -125,7 +130,8 @@ static void compile_subr(struct ejit_func *f, jit_state_t *j, struct ejit_insn i putloc(f, j, i.r0, dst); } -static void compile_subi(struct ejit_func *f, jit_state_t *j, struct ejit_insn i) +static void compile_subi(struct ejit_func *f, jit_state_t *j, + struct ejit_insn i) { jit_gpr_t dst = getreg(f, i.r0, 0); jit_gpr_t src0 = getloc(f, j, i.r1, 1); @@ -133,14 +139,16 @@ static void compile_subi(struct ejit_func *f, jit_state_t *j, struct ejit_insn i putloc(f, j, i.r0, dst); } -static void compile_stxi64(struct ejit_func *f, jit_state_t *j, struct ejit_insn i) +static void compile_stxi64(struct ejit_func *f, jit_state_t *j, + struct ejit_insn i) { 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); } -static void compile_ldxiu64(struct ejit_func *f, jit_state_t *j, struct ejit_insn i) +static void compile_ldxiu64(struct ejit_func *f, jit_state_t *j, + struct ejit_insn i) { jit_gpr_t r0 = getreg(f, i.r0, 0); jit_gpr_t r1 = getloc(f, j, i.r1, 1); @@ -148,8 +156,10 @@ static void compile_ldxiu64(struct ejit_func *f, jit_state_t *j, struct ejit_ins putloc(f, j, i.r0, r0); } -static void compile_reg_cmp(struct ejit_func *f, jit_state_t *j, struct ejit_insn i, - jit_reloc_t (*bcomp)(jit_state_t *, jit_gpr_t, jit_gpr_t), long same) +static void compile_reg_cmp(struct ejit_func *f, jit_state_t *j, + struct ejit_insn i, + jit_reloc_t (*bcomp)(jit_state_t *, jit_gpr_t, + jit_gpr_t), long same) { jit_gpr_t r0 = getreg(f, i.r0, 0); if (i.r1 == i.r2) { @@ -185,7 +195,8 @@ static void compile_ltr(struct ejit_func *f, jit_state_t *j, struct ejit_insn i) compile_reg_cmp(f, j, i, jit_bltr, 0); } -static void compile_bltr(struct ejit_func *f, jit_state_t *j, struct ejit_insn i, struct vec *relocs) +static void compile_bltr(struct ejit_func *f, jit_state_t *j, + struct ejit_insn i, struct vec *relocs) { jit_gpr_t c0 = getloc(f, j, i.r1, 0); jit_gpr_t c1 = getloc(f, j, i.r2, 1); @@ -194,7 +205,8 @@ static void compile_bltr(struct ejit_func *f, jit_state_t *j, struct ejit_insn i vect_append(struct reloc_helper, *relocs, &h); } -static void compile_beqi(struct ejit_func *f, jit_state_t *j, struct ejit_insn i, struct vec *relocs) +static void compile_beqi(struct ejit_func *f, jit_state_t *j, + struct ejit_insn i, struct vec *relocs) { jit_gpr_t r1 = getloc(f, j, i.r1, 0); jit_reloc_t r = jit_beqi(j, r1, i.o); @@ -202,7 +214,8 @@ static void compile_beqi(struct ejit_func *f, jit_state_t *j, struct ejit_insn i vect_append(struct reloc_helper, *relocs, &h); } -static void compile_bnei(struct ejit_func *f, jit_state_t *j, struct ejit_insn i, struct vec *relocs) +static void compile_bnei(struct ejit_func *f, jit_state_t *j, + struct ejit_insn i, struct vec *relocs) { jit_gpr_t r1 = getloc(f, j, i.r1, 0); jit_reloc_t r = jit_bnei(j, r1, i.o); @@ -210,7 +223,8 @@ static void compile_bnei(struct ejit_func *f, jit_state_t *j, struct ejit_insn i vect_append(struct reloc_helper, *relocs, &h); } -static void compile_bgti(struct ejit_func *f, jit_state_t *j, struct ejit_insn i, struct vec *relocs) +static void compile_bgti(struct ejit_func *f, jit_state_t *j, + struct ejit_insn i, struct vec *relocs) { jit_gpr_t r1 = getloc(f, j, i.r1, 0); jit_reloc_t r = jit_bgti(j, r1, i.o); @@ -218,7 +232,8 @@ static void compile_bgti(struct ejit_func *f, jit_state_t *j, struct ejit_insn i vect_append(struct reloc_helper, *relocs, &h); } -static void compile_jmp(struct ejit_func *f, jit_state_t *j, struct ejit_insn i, struct vec *relocs) +static void compile_jmp(struct ejit_func *f, jit_state_t *j, struct ejit_insn i, + struct vec *relocs) { (void)(f); jit_reloc_t r = jit_jmp(j); @@ -226,7 +241,8 @@ static void compile_jmp(struct ejit_func *f, jit_state_t *j, struct ejit_insn i, vect_append(struct reloc_helper, *relocs, &h); } -static void compile_retval(struct ejit_func *f, jit_state_t *j, struct ejit_insn i) +static void compile_retval(struct ejit_func *f, jit_state_t *j, + struct ejit_insn i) { jit_gpr_t r0 = getreg(f, i.r0, 0); jit_retval(j, r0); @@ -256,14 +272,14 @@ static enum jit_operand_abi jit_abi_from(enum ejit_type t) static size_t arg_offsetof(enum ejit_type t) { switch (t) { - case EJIT_INT8: return offsetof(struct ejit_arg, c); - case EJIT_INT16: return offsetof(struct ejit_arg, s); - case EJIT_INT32: return offsetof(struct ejit_arg, i); - case EJIT_INT64: return offsetof(struct ejit_arg, l); - case EJIT_UINT8: return offsetof(struct ejit_arg, uc); - case EJIT_UINT16: return offsetof(struct ejit_arg, us); - case EJIT_UINT32: return offsetof(struct ejit_arg, ui); - case EJIT_UINT64: return offsetof(struct ejit_arg, ul); + case EJIT_INT8: return offsetof(struct ejit_arg, i8); + case EJIT_INT16: return offsetof(struct ejit_arg, i16); + case EJIT_INT32: return offsetof(struct ejit_arg, i32); + case EJIT_INT64: return offsetof(struct ejit_arg, i64); + case EJIT_UINT8: return offsetof(struct ejit_arg, u8); + case EJIT_UINT16: return offsetof(struct ejit_arg, u16); + case EJIT_UINT32: return offsetof(struct ejit_arg, u32); + case EJIT_UINT64: return offsetof(struct ejit_arg, u64); case EJIT_POINTER: return offsetof(struct ejit_arg, p); case EJIT_FLOAT: return offsetof(struct ejit_arg, f); case EJIT_DOUBLE: return offsetof(struct ejit_arg, d); @@ -282,7 +298,8 @@ static jit_off_t arg_offset(struct ejit_insn i) static jit_off_t type_offset(struct ejit_insn i) { - return (sizeof(struct ejit_arg) * i.r0) + offsetof(struct ejit_arg, type); + return (sizeof(struct ejit_arg) * i.r0) + offsetof(struct ejit_arg, + type); } static void fixup_operands(struct vec *operands, size_t fixup) @@ -297,7 +314,8 @@ static void fixup_operands(struct vec *operands, size_t fixup) } } -static void compile_imm_call(jit_state_t *j, struct vec *src, struct vec *dst, void *addr, size_t argc, jit_operand_t args[argc]) +static void compile_imm_call(jit_state_t *j, struct vec *src, struct vec *dst, + void *addr, size_t argc, jit_operand_t args[argc]) { /* each move is type + arg, so twofold */ size_t movec = vec_len(src) / 2; @@ -313,7 +331,8 @@ static void compile_imm_call(jit_state_t *j, struct vec *src, struct vec *dst, v vec_reset(dst); } -static size_t compile_fn_body(struct ejit_func *f, jit_state_t *j, void *arena, size_t size) +static size_t compile_fn_body(struct ejit_func *f, jit_state_t *j, void *arena, + size_t size) { jit_begin(j, arena, size); size_t gprs = f->gpr >= jit_v_num() ? jit_v_num() : f->gpr; @@ -323,8 +342,8 @@ static size_t compile_fn_body(struct ejit_func *f, jit_state_t *j, void *arena, /* very important, argc we don't really do anything with but JIR_R1 * contains the argument stack! */ jit_load_args_2(j, - jit_operand_gpr(JIT_OPERAND_ABI_WORD, JIT_R0), - jit_operand_gpr(JIT_OPERAND_ABI_POINTER, JIT_R1)); + jit_operand_gpr(JIT_OPERAND_ABI_WORD, JIT_R0), + jit_operand_gpr(JIT_OPERAND_ABI_POINTER, JIT_R1)); size_t stack = jit_align_stack(j, stack_size(f)); @@ -367,24 +386,29 @@ 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: { - jit_operand_t type = jit_operand_imm(JIT_OPERAND_ABI_WORD, i.r1); + jit_operand_t type = + jit_operand_imm(JIT_OPERAND_ABI_WORD, i.r1); jit_operand_t arg; if (i.r0 < jit_v_num()) { /* regular register */ - arg = jit_operand_gpr(jit_abi_from(i.r1), jit_v(i.r2)); + arg = jit_operand_gpr(jit_abi_from(i.r1), + jit_v(i.r2)); } else { /* stack location, note that we'll fix up the SP * offset before doing the actual call */ - arg = jit_operand_mem(jit_abi_from(i.r1), JIT_SP, stack_loc(i.r0)); + arg = jit_operand_mem(jit_abi_from(i.r1), + JIT_SP, stack_loc(i.r0)); } vec_append(&src, &type); vec_append(&src, &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)) + 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)) }; vec_append(&dst, &to[0]); @@ -394,7 +418,8 @@ static size_t compile_fn_body(struct ejit_func *f, jit_state_t *j, void *arena, case ESCAPEI: { jit_operand_t args[2] = { - jit_operand_imm(JIT_OPERAND_ABI_WORD, vec_len(&src) / 2), + jit_operand_imm(JIT_OPERAND_ABI_WORD, + vec_len(&src) / 2), jit_operand_gpr(JIT_OPERAND_ABI_POINTER, JIT_SP) }; compile_imm_call(j, &src, &dst, (void *)i.o, 2, args); @@ -404,7 +429,8 @@ static size_t compile_fn_body(struct ejit_func *f, jit_state_t *j, void *arena, case CALLI: { jit_operand_t args[3] = { jit_operand_imm(JIT_OPERAND_ABI_POINTER, i.o), - jit_operand_imm(JIT_OPERAND_ABI_WORD, vec_len(&src) / 2), + jit_operand_imm(JIT_OPERAND_ABI_WORD, + vec_len(&src) / 2), jit_operand_gpr(JIT_OPERAND_ABI_POINTER, JIT_SP) }; compile_imm_call(j, &src, &dst, ejit_run_func, 3, args); @@ -412,7 +438,7 @@ static size_t compile_fn_body(struct ejit_func *f, jit_state_t *j, void *arena, } case RETVAL: compile_retval(f, j, i); break; - case RET: { + case RETR: { jit_gpr_t r = getloc(f, j, i.r0, 0); /* R0 won't get overwritten by jit_leave_jit_abi */ jit_movr(j, JIT_R0, r); @@ -422,7 +448,7 @@ static size_t compile_fn_body(struct ejit_func *f, jit_state_t *j, void *arena, break; } - case RET_I: { + case RETI: { jit_shrink_stack(j, stack); jit_leave_jit_abi(j, gprs, fprs, frame); jit_reti(j, i.o); @@ -440,19 +466,21 @@ static size_t compile_fn_body(struct ejit_func *f, jit_state_t *j, void *arena, case PARAM: { /* move from argument stack to location */ jit_operand_t from = jit_operand_mem( - jit_abi_from(i.r1), - JIT_R1, - arg_offset(i) - ); + jit_abi_from(i.r1), + JIT_R1, + arg_offset(i) + ); jit_operand_t to; if (i.r0 < jit_v_num()) { /* regular register */ - to = jit_operand_gpr(jit_abi_from(i.r1), jit_v(i.r2)); + to = jit_operand_gpr(jit_abi_from(i.r1), + jit_v(i.r2)); } else { /* stack location */ - to = jit_operand_mem(jit_abi_from(i.r1), JIT_SP, stack_loc(i.r2)); + to = jit_operand_mem(jit_abi_from(i.r1), JIT_SP, + stack_loc(i.r2)); } vec_append(&src, &from); @@ -474,7 +502,8 @@ static size_t compile_fn_body(struct ejit_func *f, jit_state_t *j, void *arena, } foreach_vec(ri, relocs) { - struct reloc_helper h = vect_at(struct reloc_helper, relocs, ri); + struct reloc_helper h = vect_at(struct reloc_helper, relocs, + ri); jit_addr_t a = vect_at(jit_addr_t, labels, h.to); jit_reloc_t r = h.r; @@ -5,31 +5,36 @@ #include "common.h" -static void emit_insn_i(struct ejit_func *f, enum ejit_opcode op, size_t r0, size_t r1, long o) +static void emit_insn_i(struct ejit_func *f, enum ejit_opcode op, size_t r0, + size_t r1, long o) { struct ejit_insn i = {.op = op, .r0 = r0, .r1 = r1, .o = o}; vec_append(&f->insns, &i); } -static void emit_insn_r(struct ejit_func *f, enum ejit_opcode op, size_t r0, size_t r1, size_t r2) +static void emit_insn_r(struct ejit_func *f, enum ejit_opcode op, size_t r0, + size_t r1, size_t r2) { struct ejit_insn i = {.op = op, .r0 = r0, .r1 = r1, .r2 = r2}; vec_append(&f->insns, &i); } -static void emit_insn_p(struct ejit_func *f, enum ejit_opcode op, size_t r0, size_t r1, void *p) +static void emit_insn_p(struct ejit_func *f, enum ejit_opcode op, size_t r0, + size_t r1, void *p) { struct ejit_insn i = {.op = op, .r0 = r0, .r1 = r1, .p = p}; vec_append(&f->insns, &i); } -static void emit_insn_f(struct ejit_func *f, enum ejit_opcode op, size_t r0, size_t r1, double d) +static void emit_insn_f(struct ejit_func *f, enum ejit_opcode op, size_t r0, + size_t r1, double d) { struct ejit_insn i = {.op = op, .r0 = r0, .r1 = r1, .d = d}; vec_append(&f->insns, &i); } -struct ejit_func *ejit_create_func(enum ejit_type rtype, size_t argc, const struct ejit_operand args[argc]) +struct ejit_func *ejit_create_func(enum ejit_type rtype, size_t argc, + const struct ejit_operand args[argc]) { struct ejit_func *f = malloc(sizeof(struct ejit_func)); assert(f); @@ -43,8 +48,10 @@ struct ejit_func *ejit_create_func(enum ejit_type rtype, size_t argc, const stru for (size_t i = 0; i < argc; ++i) { switch (args[i].kind) { - case EJIT_OPERAND_GPR: emit_insn_r(f, PARAM, i, args[i].type, args[i].r); break; - case EJIT_OPERAND_FPR: emit_insn_r(f, PARAM_F, i, args[i].type, args[i].r); break; + case EJIT_OPERAND_GPR: emit_insn_r(f, PARAM, i, args[i].type, + args[i].r); break; + case EJIT_OPERAND_FPR: emit_insn_r(f, PARAM_F, i, args[i].type, + args[i].r); break; default: abort(); } } @@ -58,7 +65,8 @@ void ejit_compile_func(struct ejit_func *f, size_t gpr, size_t fpr) ejit_select_compile_func(f, gpr, fpr, true); } -void ejit_select_compile_func(struct ejit_func *f, size_t gpr, size_t fpr, bool try_jit) +void ejit_select_compile_func(struct ejit_func *f, size_t gpr, size_t fpr, + bool try_jit) { /* emit a final end instruction in case user didn't do a return */ emit_insn_i(f, END, 0, 0, 0); @@ -109,14 +117,19 @@ void ejit_patch(struct ejit_func *f, struct ejit_reloc r, struct ejit_label l) vect_at(struct ejit_insn, f->insns, r.insn) = i; } -void ejit_calli(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]) { for (size_t i = 0; i < argc; ++i) { switch (args[i].kind) { - case EJIT_OPERAND_GPR: emit_insn_r(s, ARG, i, args[i].type, args[i].r); break; - case EJIT_OPERAND_FPR: emit_insn_r(s, ARG_F, i, args[i].type, args[i].r); break; - case EJIT_OPERAND_IMM: emit_insn_i(s, ARG_I, i, args[i].type, args[i].r); break; - case EJIT_OPERAND_FLT: emit_insn_f(s, ARG_FI, i, args[i].type, args[i].d); break; + case EJIT_OPERAND_GPR: emit_insn_r(s, ARG, i, args[i].type, + args[i].r); break; + case EJIT_OPERAND_FPR: emit_insn_r(s, ARG_F, i, args[i].type, + args[i].r); break; + case EJIT_OPERAND_IMM: emit_insn_i(s, ARG_I, i, args[i].type, + args[i].r); break; + case EJIT_OPERAND_FLT: emit_insn_f(s, ARG_FI, i, args[i].type, + args[i].d); break; default: abort(); } } @@ -124,14 +137,19 @@ void ejit_calli(struct ejit_func *s, struct ejit_func *f, size_t argc, const str emit_insn_p(s, CALLI, 0, 0, f); } -void ejit_escapei(struct ejit_func *s, ejit_escape_t f, size_t argc, const struct ejit_operand args[argc]) +void ejit_escapei(struct ejit_func *s, ejit_escape_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_r(s, ARG, i, args[i].type, args[i].r); break; - case EJIT_OPERAND_FPR: emit_insn_r(s, ARG_F, i, args[i].type, args[i].r); break; - case EJIT_OPERAND_IMM: emit_insn_r(s, ARG_I, i, args[i].type, args[i].r); break; - case EJIT_OPERAND_FLT: emit_insn_f(s, ARG_FI, i, args[i].type, args[i].d); break; + case EJIT_OPERAND_GPR: emit_insn_r(s, ARG, i, args[i].type, + args[i].r); break; + case EJIT_OPERAND_FPR: emit_insn_r(s, ARG_F, i, args[i].type, + args[i].r); break; + case EJIT_OPERAND_IMM: emit_insn_r(s, ARG_I, i, args[i].type, + args[i].r); break; + case EJIT_OPERAND_FLT: emit_insn_f(s, ARG_FI, i, args[i].type, + args[i].d); break; default: abort(); } } @@ -139,14 +157,19 @@ void ejit_escapei(struct ejit_func *s, ejit_escape_t f, size_t argc, const struc emit_insn_p(s, ESCAPEI, 0, 0, f); } -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_f(struct ejit_func *s, ejit_escape_f_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_r(s, ARG, i, args[i].type, args[i].r); break; - case EJIT_OPERAND_FPR: emit_insn_r(s, ARG_F, i, args[i].type, args[i].r); break; - case EJIT_OPERAND_IMM: emit_insn_r(s, ARG_I, i, args[i].type, args[i].r); break; - case EJIT_OPERAND_FLT: emit_insn_f(s, ARG_FI, i, args[i].type, args[i].d); break; + case EJIT_OPERAND_GPR: emit_insn_r(s, ARG, i, args[i].type, + args[i].r); break; + case EJIT_OPERAND_FPR: emit_insn_r(s, ARG_F, i, args[i].type, + args[i].r); break; + case EJIT_OPERAND_IMM: emit_insn_r(s, ARG_I, i, args[i].type, + args[i].r); break; + case EJIT_OPERAND_FLT: emit_insn_f(s, ARG_FI, i, args[i].type, + args[i].d); break; default: abort(); } } @@ -159,72 +182,87 @@ void ejit_retval(struct ejit_func *s, struct ejit_gpr r0) emit_insn_i(s, RETVAL, r0.r, 0, 0); } -void ejit_stxi_64(struct ejit_func *s, struct ejit_gpr r0, struct ejit_gpr r1, long o) +void ejit_stxi_64(struct ejit_func *s, struct ejit_gpr r0, struct ejit_gpr r1, + long o) { emit_insn_i(s, STXI64, r0.r, r1.r, o); } -void ejit_ldxi_u64(struct ejit_func *s, struct ejit_gpr r0, struct ejit_gpr r1, long o) +void ejit_ldxi_u64(struct ejit_func *s, struct ejit_gpr r0, struct ejit_gpr r1, + long o) { emit_insn_i(s, LDXIU64, r0.r, r1.r, o); } -void ejit_ret(struct ejit_func *s, struct ejit_gpr r0) +void ejit_retr(struct ejit_func *s, struct ejit_gpr r0) { - emit_insn_r(s, RET, r0.r, 0, 0); + emit_insn_r(s, RETR, r0.r, 0, 0); } -void ejit_ret_f(struct ejit_func *s, struct ejit_fpr r0) +void ejit_retr_f(struct ejit_func *s, struct ejit_fpr r0) { - emit_insn_r(s, RET_F, r0.f, 0, 0); + emit_insn_r(s, RETR_F, r0.f, 0, 0); } -void ejit_ret_i(struct ejit_func *s, long i) +void ejit_reti(struct ejit_func *s, long i) { - emit_insn_i(s, RET_I, 0, 0, i); + emit_insn_i(s, RETI, 0, 0, i); } -void ejit_ret_fi(struct ejit_func *s, double f) +void ejit_reti_f(struct ejit_func *s, double f) { - emit_insn_f(s, RET_FI, 0, 0, f); + emit_insn_f(s, RETI_F, 0, 0, f); } -void ejit_addr(struct ejit_func *s, struct ejit_gpr r0, struct ejit_gpr r1, struct ejit_gpr r2) +void ejit_addr(struct ejit_func *s, struct ejit_gpr r0, struct ejit_gpr r1, + struct ejit_gpr r2) { emit_insn_r(s, ADDR, r0.r, r1.r, r2.r); } -void ejit_addr_f(struct ejit_func *s, struct ejit_fpr r0, struct ejit_fpr r1, struct ejit_fpr r2) +void ejit_addr_f(struct ejit_func *s, struct ejit_fpr r0, struct ejit_fpr r1, + struct ejit_fpr r2) { emit_insn_r(s, ADDR_F, r0.f, r1.f, r2.f); } -void ejit_addi(struct ejit_func *s, struct ejit_gpr r0, struct ejit_gpr r1, long o) +void ejit_addi(struct ejit_func *s, struct ejit_gpr r0, struct ejit_gpr r1, + long o) { emit_insn_i(s, ADDI, r0.r, r1.r, o); } -void ejit_subr(struct ejit_func *s, struct ejit_gpr r0, struct ejit_gpr r1, struct ejit_gpr r2) +void ejit_absr_f(struct ejit_func *s, struct ejit_fpr r0, struct ejit_fpr r1) +{ + emit_insn_i(s, ABSR_F, r0.f, r1.f, 0); +} + +void ejit_subr(struct ejit_func *s, struct ejit_gpr r0, struct ejit_gpr r1, + struct ejit_gpr r2) { emit_insn_r(s, SUBR, r0.r, r1.r, r2.r); } -void ejit_subr_f(struct ejit_func *s, struct ejit_fpr r0, struct ejit_fpr r1, struct ejit_fpr r2) +void ejit_subr_f(struct ejit_func *s, struct ejit_fpr r0, struct ejit_fpr r1, + struct ejit_fpr r2) { emit_insn_r(s, SUBR_F, r0.f, r1.f, r2.f); } -void ejit_subi(struct ejit_func *s, struct ejit_gpr r0, struct ejit_gpr r1, long o) +void ejit_subi(struct ejit_func *s, struct ejit_gpr r0, struct ejit_gpr r1, + long o) { emit_insn_i(s, SUBI, r0.r, r1.r, o); } -void ejit_mulr(struct ejit_func *s, struct ejit_gpr r0, struct ejit_gpr r1, struct ejit_gpr r2) +void ejit_mulr(struct ejit_func *s, struct ejit_gpr r0, struct ejit_gpr r1, + struct ejit_gpr r2) { emit_insn_r(s, MULR, r0.r, r1.r, r2.r); } -void ejit_divr(struct ejit_func *s, struct ejit_gpr r0, struct ejit_gpr r1, struct ejit_gpr r2) +void ejit_divr(struct ejit_func *s, struct ejit_gpr r0, struct ejit_gpr r1, + struct ejit_gpr r2) { emit_insn_r(s, DIVR, r0.r, r1.r, r2.r); } @@ -247,17 +285,20 @@ void ejit_movr(struct ejit_func *s, struct ejit_gpr r0, struct ejit_gpr r1) emit_insn_i(s, MOVR, r0.r, r1.r, 0); } -void ejit_eqr(struct ejit_func *s, struct ejit_gpr r0, struct ejit_gpr r1, struct ejit_gpr r2) +void ejit_eqr(struct ejit_func *s, struct ejit_gpr r0, struct ejit_gpr r1, + struct ejit_gpr r2) { emit_insn_r(s, EQR, r0.r, r1.r, r2.r); } -void ejit_ltr(struct ejit_func *s, struct ejit_gpr r0, struct ejit_gpr r1, struct ejit_gpr r2) +void ejit_ltr(struct ejit_func *s, struct ejit_gpr r0, struct ejit_gpr r1, + struct ejit_gpr r2) { emit_insn_r(s, LTR, r0.r, r1.r, r2.r); } -struct ejit_reloc ejit_bltr(struct ejit_func *s, struct ejit_gpr r0, struct ejit_gpr r1) +struct ejit_reloc ejit_bltr(struct ejit_func *s, struct ejit_gpr r0, + struct ejit_gpr r1) { size_t addr = vec_len(&s->insns); emit_insn_r(s, BLTR, 0, r0.r, r1.r); @@ -296,7 +337,7 @@ static struct interp_state create_interp_state() { struct interp_state state; state.gprs = vec_create(sizeof(long)); - state.gprs = vec_create(sizeof(double)); + state.fprs = vec_create(sizeof(double)); state.args = vec_create(sizeof(struct ejit_arg)); return state; } @@ -308,7 +349,8 @@ static void destroy_interp_state(struct interp_state state) vec_destroy(&state.args); } -long ejit_run_interp(struct ejit_func *f, size_t argc, struct ejit_arg args[argc], struct interp_state *state) +long ejit_run_interp(struct ejit_func *f, size_t argc, + struct ejit_arg args[argc], struct interp_state *state) { assert(f->gpr && "trying to run a function that hasn't been compiled"); assert(f->rtype == EJIT_VOID || ejit_int_type(f->rtype)); @@ -331,7 +373,8 @@ long ejit_run_func(struct ejit_func *f, size_t argc, struct ejit_arg args[argc]) return r; } -double ejit_run_func_f(struct ejit_func *f, size_t argc, struct ejit_arg args[argc]) +double ejit_run_func_f(struct ejit_func *f, size_t argc, + struct ejit_arg args[argc]) { assert(f->fpr && "trying to run a function that hasn't been compiled"); assert(ejit_float_type(f->rtype)); diff --git a/src/interp.c b/src/interp.c index ed7e59c..3395537 100644 --- a/src/interp.c +++ b/src/interp.c @@ -1,8 +1,12 @@ #include <ejit/ejit.h> +#include <math.h> #include "common.h" -union interp_ret ejit_interp(struct ejit_func *f, size_t argc, struct ejit_arg args[argc], struct interp_state *state, bool run, void ***labels_wb) +union interp_ret ejit_interp(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, @@ -13,6 +17,8 @@ union interp_ret ejit_interp(struct ejit_func *f, size_t argc, struct ejit_arg a [ADDR_F] = &&ADDR_F, [ADDI] = &&ADDI, + [ABSR_F] = &&ABSR_F, + [SUBR] = &&SUBR, [SUBR_F] = &&SUBR_F, [SUBI] = &&SUBI, @@ -33,10 +39,10 @@ union interp_ret ejit_interp(struct ejit_func *f, size_t argc, struct ejit_arg a [JMP] = &&JMP, - [RET] = &&RET, - [RET_I] = &&RET_I, - [RET_F] = &&RET_F, - [RET_FI] = &&RET_FI, + [RETR] = &&RETR, + [RETI] = &&RETI, + [RETR_F] = &&RETR_F, + [RETI_F] = &&RETI_F, [RETVAL] = &&RETVAL, @@ -76,10 +82,10 @@ union interp_ret ejit_interp(struct ejit_func *f, size_t argc, struct ejit_arg a /* 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? */ - long retval = 0; double retval_f = 0.; + int64_t retval = 0; double retval_f = 0.; size_t pc = 0; -#define DO(x) x: { struct ejit_insn i = insns[pc]; (void)i; +#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; @@ -116,6 +122,10 @@ union interp_ret ejit_interp(struct ejit_func *f, size_t argc, struct ejit_arg a gpr[i.r0] = gpr[i.r1] + i.o; DISPATCH(); + DO(ABSR_F); + fpr[i.r0] = fabs(fpr[i.r1]); + DISPATCH(); + DO(SUBR); gpr[i.r0] = gpr[i.r1] - gpr[i.r2]; DISPATCH(); @@ -187,7 +197,7 @@ union interp_ret ejit_interp(struct ejit_func *f, size_t argc, struct ejit_arg a DISPATCH(); DO(PARAM); - gpr[i.r2] = args[i.r0].l; + gpr[i.r2] = args[i.r0].u64; DISPATCH(); DO(PARAM_F); @@ -217,7 +227,8 @@ union interp_ret ejit_interp(struct ejit_func *f, size_t argc, struct ejit_arg a DO(CALLI); struct ejit_func *f = i.p; size_t argc = vec_len(&state->args) - prev_argc; - struct ejit_arg *args = ((struct ejit_arg *)state->args.buf) + prev_argc; + struct ejit_arg *args = ((struct ejit_arg *)state->args.buf) + + prev_argc; retval = ejit_run_interp(f, argc, args, state); @@ -232,7 +243,8 @@ union interp_ret ejit_interp(struct ejit_func *f, size_t argc, struct ejit_arg a DO(ESCAPEI); ejit_escape_t f = i.p; size_t argc = vec_len(&state->args) - prev_argc; - struct ejit_arg *args = ((struct ejit_arg *)state->args.buf) + prev_argc; + struct ejit_arg *args = ((struct ejit_arg *)state->args.buf) + + prev_argc; retval = f(argc, args); @@ -241,22 +253,22 @@ union interp_ret ejit_interp(struct ejit_func *f, size_t argc, struct ejit_arg a /* dispatch is technically unnecessary for returns, but keep it for * symmetry */ - DO(RET); + DO(RETR); retval = gpr[i.r0]; goto out_int; DISPATCH(); - DO(RET_I); + DO(RETI); retval = i.o; goto out_int; DISPATCH(); - DO(RET_F); + DO(RETR_F); retval_f = fpr[i.r0]; goto out_float; DISPATCH(); - DO(RET_FI); + DO(RETI_F); retval_f = i.d; goto out_float; DISPATCH(); |