aboutsummaryrefslogtreecommitdiff
path: root/src/interp.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/interp.c')
-rw-r--r--src/interp.c32
1 files changed, 24 insertions, 8 deletions
diff --git a/src/interp.c b/src/interp.c
index 9c3aea3..25f723a 100644
--- a/src/interp.c
+++ b/src/interp.c
@@ -2,7 +2,6 @@
#include "common.h"
-
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] = {
@@ -12,8 +11,11 @@ union interp_ret ejit_interp(struct ejit_func *f, size_t argc, struct ejit_arg a
[ADDR] = &&ADDR,
[ADDR_F] = &&ADDR_F,
+ [ADDI] = &&ADDI,
+
[SUBR] = &&SUBR,
[SUBR_F] = &&SUBR_F,
+ [SUBI] = &&SUBI,
[MULR] = &&MULR,
[DIVR] = &&DIVR,
@@ -27,6 +29,8 @@ union interp_ret ejit_interp(struct ejit_func *f, size_t argc, struct ejit_arg a
[BLTR] = &&BLTR,
[BNEI] = &&BNEI,
[BEQI] = &&BEQI,
+ [BGTI] = &&BGTI,
+
[JMP] = &&JMP,
[RET] = &&RET,
@@ -57,21 +61,19 @@ union interp_ret ejit_interp(struct ejit_func *f, size_t argc, struct ejit_arg a
return (union interp_ret){.r = 0};
}
- /** @todo this can be optimized by for example using a common buffer
- * 'stack' */
long *gpr = malloc(f->gpr * sizeof(long));
- long *fpr = malloc(f->fpr * sizeof(long));
+ double *fpr = malloc(f->fpr * sizeof(double));
+
struct vec call_args = vec_create(sizeof(struct ejit_arg));
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;
-#define DO(x) x: { i = insns[pc];
+#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;
@@ -104,6 +106,10 @@ union interp_ret ejit_interp(struct ejit_func *f, size_t argc, struct ejit_arg a
fpr[i.r0] = fpr[i.r1] + fpr[i.r2];
DISPATCH();
+ DO(ADDI);
+ gpr[i.r0] = gpr[i.r1] + i.o;
+ DISPATCH();
+
DO(SUBR);
gpr[i.r0] = gpr[i.r1] - gpr[i.r2];
DISPATCH();
@@ -112,6 +118,10 @@ union interp_ret ejit_interp(struct ejit_func *f, size_t argc, struct ejit_arg a
fpr[i.r0] = fpr[i.r1] - fpr[i.r2];
DISPATCH();
+ DO(SUBI);
+ gpr[i.r0] = gpr[i.r1] - i.o;
+ DISPATCH();
+
DO(MULR);
gpr[i.r0] = gpr[i.r1] * gpr[i.r2];
DISPATCH();
@@ -156,6 +166,12 @@ union interp_ret ejit_interp(struct ejit_func *f, size_t argc, struct ejit_arg a
DISPATCH();
+ DO(BGTI);
+ if (gpr[i.r1] > i.o)
+ JUMP(i.r0);
+
+ DISPATCH();
+
DO(JMP);
JUMP(i.r0);
DISPATCH();
@@ -237,14 +253,14 @@ union interp_ret ejit_interp(struct ejit_func *f, size_t argc, struct ejit_arg a
#undef DO
out_int:
- vec_destroy(&call_args);
free(gpr);
free(fpr);
+ vec_destroy(&call_args);
return (union interp_ret){.r = retval};
out_float:
- vec_destroy(&call_args);
free(gpr);
free(fpr);
+ vec_destroy(&call_args);
return (union interp_ret){.d = retval_f};
}