diff options
Diffstat (limited to 'src/interp.c')
-rw-r--r-- | src/interp.c | 32 |
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}; } |