aboutsummaryrefslogtreecommitdiff
path: root/src/interp.c
diff options
context:
space:
mode:
authorKimplul <kimi.h.kuparinen@gmail.com>2024-06-26 21:51:15 +0300
committerKimplul <kimi.h.kuparinen@gmail.com>2024-06-26 21:51:15 +0300
commit827dec28e4c0b1c4972f1419e0ac23e4dbd9d916 (patch)
treeac2c01e1b0b7acdf8ce06823e416a49e19257aa5 /src/interp.c
parent3bf4d1ada6df5c74aac2a371d5f1e05fd55b4f02 (diff)
downloadejit-827dec28e4c0b1c4972f1419e0ac23e4dbd9d916.tar.gz
ejit-827dec28e4c0b1c4972f1419e0ac23e4dbd9d916.zip
enough functionality to implement posthaste
Diffstat (limited to 'src/interp.c')
-rw-r--r--src/interp.c166
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] = &&LTR,
- [ARG] = &&arg,
- [ARG_I] = &&arg_i,
- [ARG_F] = &&arg_f,
- [ARG_FI] = &&arg_fi,
+ [STXI64] = &&STXI64,
+ [LDXIU64] = &&LDXIU64,
- [PARAM] = &&param,
- [PARAM_F] = &&param_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();