diff options
author | Kimplul <kimi.h.kuparinen@gmail.com> | 2024-06-26 21:51:15 +0300 |
---|---|---|
committer | Kimplul <kimi.h.kuparinen@gmail.com> | 2024-06-26 21:51:15 +0300 |
commit | 827dec28e4c0b1c4972f1419e0ac23e4dbd9d916 (patch) | |
tree | ac2c01e1b0b7acdf8ce06823e416a49e19257aa5 /src/interp.c | |
parent | 3bf4d1ada6df5c74aac2a371d5f1e05fd55b4f02 (diff) | |
download | ejit-827dec28e4c0b1c4972f1419e0ac23e4dbd9d916.tar.gz ejit-827dec28e4c0b1c4972f1419e0ac23e4dbd9d916.zip |
enough functionality to implement posthaste
Diffstat (limited to 'src/interp.c')
-rw-r--r-- | src/interp.c | 166 |
1 files changed, 118 insertions, 48 deletions
diff --git a/src/interp.c b/src/interp.c index 158606b..f15adc5 100644 --- a/src/interp.c +++ b/src/interp.c @@ -6,35 +6,49 @@ union interp_ret ejit_interp(struct ejit_func *f, size_t argc, struct ejit_arg args[argc], bool run, void ***labels_wb) { static void *labels[OPCODE_COUNT] = { - [MOVI] = &&movi, - [MOVR] = &&movr, - [MOVR_F] = &&movr_f, + [MOVI] = &&MOVI, + [MOVR] = &&MOVR, + [MOVR_F] = &&MOVR_F, - [ADDR] = &&addr, - [ADDR_F] = &&addr_f, - [SUBR] = &&subr, - [SUBR_F] = &&subr_f, + [ADDR] = &&ADDR, + [ADDR_F] = &&ADDR_F, + [SUBR] = &&SUBR, + [SUBR_F] = &&SUBR_F, - [BLTR] = &&bltr, + [MULR] = &&MULR, + [DIVR] = &&DIVR, - [RET] = &&ret, - [RET_I] = &&ret_i, - [RET_F] = &&ret_f, - [RET_FI] = &&ret_fi, + [EQR] = &&EQR, + [LTR] = &<R, - [ARG] = &&arg, - [ARG_I] = &&arg_i, - [ARG_F] = &&arg_f, - [ARG_FI] = &&arg_fi, + [STXI64] = &&STXI64, + [LDXIU64] = &&LDXIU64, - [PARAM] = &¶m, - [PARAM_F] = &¶m_f, + [BLTR] = &&BLTR, + [BNEI] = &&BNEI, + [BEQI] = &&BEQI, + [JMP] = &&JMP, - [CALLI] = &&calli, - [CALLI_F] = &&calli_f, + [RET] = &&RET, + [RET_I] = &&RET_I, + [RET_F] = &&RET_F, + [RET_FI] = &&RET_FI, - [START] = &&start, - [END] = &&end, + [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, + + [LABEL] = &&LABEL, + [START] = &&START, + [END] = &&END, }; if (!run) { @@ -50,6 +64,9 @@ union interp_ret ejit_interp(struct ejit_func *f, size_t argc, struct ejit_arg a struct ejit_insn *insns = f->insns.buf; struct ejit_insn i; + /* 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.; size_t pc = 0; @@ -57,105 +74,158 @@ union interp_ret ejit_interp(struct ejit_func *f, size_t argc, struct ejit_arg a #define JUMP(a) goto *insns[pc = a].addr; #define DISPATCH() } goto *insns[++pc].addr; - DO(start); + JUMP(0); + + DO(START); DISPATCH(); - DO(end); + DO(LABEL); + DISPATCH(); + + DO(END); goto out_int; DISPATCH(); - DO(movi); + DO(MOVI); gpr[i.r0] = i.o; DISPATCH(); - DO(movr); + DO(MOVR); gpr[i.r0] = gpr[i.r1]; DISPATCH(); - DO(movr_f); + DO(MOVR_F); fpr[i.r0] = fpr[i.r1]; DISPATCH(); - DO(addr); + DO(ADDR); gpr[i.r0] = gpr[i.r1] + gpr[i.r2]; DISPATCH(); - DO(addr_f); + DO(ADDR_F); fpr[i.r0] = fpr[i.r1] + fpr[i.r2]; DISPATCH(); - DO(subr); + DO(SUBR); gpr[i.r0] = gpr[i.r1] - gpr[i.r2]; DISPATCH(); - DO(subr_f); + DO(SUBR_F); fpr[i.r0] = fpr[i.r1] - fpr[i.r2]; DISPATCH(); - DO(bltr); + DO(MULR); + gpr[i.r0] = gpr[i.r1] * gpr[i.r2]; + DISPATCH(); + + DO(DIVR); + gpr[i.r0] = gpr[i.r1] / gpr[i.r2]; + DISPATCH(); + + DO(EQR); + gpr[i.r0] = gpr[i.r1] == gpr[i.r2]; + DISPATCH(); + + DO(LTR); + gpr[i.r0] = gpr[i.r1] < gpr[i.r2]; + DISPATCH(); + + DO(STXI64); + int64_t *addr = (int64_t *)(gpr[i.r1] + i.o); + *addr = gpr[i.r0]; + DISPATCH(); + + DO(LDXIU64); + uint64_t *addr = (uint64_t *)(gpr[i.r1] + i.o); + gpr[i.r0] = *addr; + DISPATCH(); + + DO(BLTR); if (gpr[i.r1] < gpr[i.r2]) JUMP(i.r0); DISPATCH(); - DO(param); - gpr[i.r0] = args[i.o].l; + DO(BNEI); + if (gpr[i.r1] != i.o) + JUMP(i.r0); + + DISPATCH(); + + DO(BEQI); + if (gpr[i.r1] == i.o) + JUMP(i.r0); + DISPATCH(); - DO(param_f); - fpr[i.r0] = args[i.o].d; + DO(JMP); + JUMP(i.r0); DISPATCH(); - DO(arg); - struct ejit_arg a = ejit_build_arg(i.r1, gpr[i.r0]); + DO(PARAM); + gpr[i.r2] = args[i.r0].l; + DISPATCH(); + + DO(PARAM_F); + fpr[i.r2] = args[i.r0].d; + DISPATCH(); + + DO(ARG); + struct ejit_arg a = ejit_build_arg(i.r1, gpr[i.r2]); vec_append(&call_args, &a); DISPATCH(); - DO(arg_i); + DO(ARG_I); struct ejit_arg a = ejit_build_arg(i.r1, i.o); vec_append(&call_args, &a); DISPATCH(); - DO(arg_f); - struct ejit_arg a = ejit_build_arg_f(i.r1, fpr[i.r0]); + DO(ARG_F); + struct ejit_arg a = ejit_build_arg_f(i.r1, fpr[i.r2]); vec_append(&call_args, &a); DISPATCH(); - DO(arg_fi); + DO(ARG_FI); struct ejit_arg a = ejit_build_arg_f(i.r1, i.d); vec_append(&call_args, &a); DISPATCH(); - DO(calli); + DO(CALLI); struct ejit_func *f = i.p; retval = ejit_run_func(f, vec_len(&call_args), call_args.buf); vec_reset(&call_args); DISPATCH(); - DO(calli_f); + DO(CALLI_F); struct ejit_func *f = i.p; retval_f = ejit_run_func_f(f, vec_len(&call_args), call_args.buf); vec_reset(&call_args); DISPATCH(); + DO(ESCAPEI); + ejit_escape_t f = i.p; + retval = f(vec_len(&call_args), call_args.buf); + vec_reset(&call_args); + DISPATCH(); + /* dispatch is technically unnecessary for returns, but keep it for * symmetry */ - DO(ret); + DO(RET); retval = gpr[i.r0]; goto out_int; DISPATCH(); - DO(ret_i); + DO(RET_I); retval = i.o; goto out_int; DISPATCH(); - DO(ret_f); + DO(RET_F); retval_f = fpr[i.r0]; goto out_float; DISPATCH(); - DO(ret_fi); + DO(RET_FI); retval_f = i.d; goto out_float; DISPATCH(); |