diff options
Diffstat (limited to 'src')
-rw-r--r-- | src/common.h | 43 | ||||
-rw-r--r-- | src/compile/compile.c | 17 | ||||
-rw-r--r-- | src/ejit.c | 234 | ||||
-rw-r--r-- | src/interp.c | 208 |
4 files changed, 466 insertions, 36 deletions
diff --git a/src/common.h b/src/common.h index 37332aa..1f21c74 100644 --- a/src/common.h +++ b/src/common.h @@ -71,15 +71,52 @@ enum ejit_opcode { ANDI, EQR, - LTR, - - BLTR, + NER, + GTR, + GTR_U, + GER, + GER_U, + + EQR_F, + NER_F, + GTR_F, + GER_F, + + BNER, BNEI, + BNER_F, + BEQR, BEQI, + BEQR_F, + + BGER, + BGER_U, + BGEI, + BGEI_U, + BGER_F, + + BLEI, + BLEI_U, + + BGTR, + BGTR_U, BGTI, + BGTI_U, + BGTR_F, + + BLTI, + BLTI_U, + + BLTGTR_F, + JMP, + BMCI, + BMCR, + BMSI, + BMSR, + PARAM, PARAM_F, diff --git a/src/compile/compile.c b/src/compile/compile.c index 4ac68d3..014b7d3 100644 --- a/src/compile/compile.c +++ b/src/compile/compile.c @@ -190,21 +190,6 @@ static void compile_eqr(struct ejit_func *f, jit_state_t *j, struct ejit_insn i) compile_reg_cmp(f, j, i, jit_beqr, 1); } -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) -{ - jit_gpr_t c0 = getloc(f, j, i.r1, 0); - jit_gpr_t c1 = getloc(f, j, i.r2, 1); - jit_reloc_t r = jit_bltr(j, c0, c1); - struct reloc_helper h = {.r = r, .to = i.r0}; - 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) { @@ -377,9 +362,7 @@ static size_t compile_fn_body(struct ejit_func *f, jit_state_t *j, void *arena, case LDXIU64: compile_ldxiu64(f, j, i); break; case EQR: compile_eqr(f, j, i); break; - case LTR: compile_ltr(f, j, i); break; - case BLTR: compile_bltr(f, j, i, &relocs); break; case BEQI: compile_beqi(f, j, i, &relocs); break; case BNEI: compile_bnei(f, j, i, &relocs); break; case BGTI: compile_bgti(f, j, i, &relocs); break; @@ -48,10 +48,17 @@ struct ejit_func *ejit_create_func(enum ejit_type rtype, size_t argc, 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: { + assert(ejit_int_type(args[i].type)); + emit_insn_r(f, PARAM, i, args[i].type, args[i].r); + break; + } + + case EJIT_OPERAND_FPR: { + assert(ejit_float_type(args[i].type)); + emit_insn_r(f, PARAM_F, i, args[i].type, args[i].r); + break; + } default: abort(); } } @@ -90,6 +97,9 @@ void ejit_select_compile_func(struct ejit_func *f, size_t gpr, size_t fpr, i.addr = addr; vect_at(struct ejit_insn, f->insns, ii) = i; } + + /* doesn't really matter what we put here as long as it isn't 0 */ + f->size = 1; } void ejit_destroy_func(struct ejit_func *f) @@ -306,14 +316,14 @@ void ejit_eqr(struct ejit_func *s, struct ejit_gpr r0, struct ejit_gpr r1, 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); + emit_insn_r(s, GER, r0.r, r2.r, r1.r); } -struct ejit_reloc ejit_bltr(struct ejit_func *s, struct ejit_gpr r0, +struct ejit_reloc ejit_bner(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); + emit_insn_r(s, BNER, 0, r0.r, r1.r); return (struct ejit_reloc){.insn = addr}; } @@ -324,7 +334,16 @@ struct ejit_reloc ejit_bnei(struct ejit_func *s, struct ejit_gpr r0, int64_t o) return (struct ejit_reloc){.insn = addr}; } -struct ejit_reloc ejit_beqr(struct ejit_func *s, struct ejit_gpr r0, struct ejit_gpr r1) +struct ejit_reloc ejit_bner_f(struct ejit_func *s, struct ejit_fpr r0, + struct ejit_fpr r1) +{ + size_t addr = vec_len(&s->insns); + emit_insn_r(s, BNER_F, 0, r0.f, r1.f); + return (struct ejit_reloc){.insn = addr}; +} + +struct ejit_reloc ejit_beqr(struct ejit_func *s, struct ejit_gpr r0, + struct ejit_gpr r1) { size_t addr = vec_len(&s->insns); emit_insn_r(s, BEQR, 0, r0.r, r1.r); @@ -338,6 +357,92 @@ struct ejit_reloc ejit_beqi(struct ejit_func *s, struct ejit_gpr r0, int64_t o) return (struct ejit_reloc){.insn = addr}; } +struct ejit_reloc ejit_beqr_f(struct ejit_func *s, struct ejit_fpr r0, + struct ejit_fpr r1) +{ + size_t addr = vec_len(&s->insns); + emit_insn_r(s, BEQR_F, 0, r0.f, r1.f); + return (struct ejit_reloc){.insn = addr}; +} + +struct ejit_reloc ejit_bger(struct ejit_func *s, struct ejit_gpr r0, + struct ejit_gpr r1) +{ + size_t addr = vec_len(&s->insns); + emit_insn_r(s, BGER, 0, r0.r, r1.r); + return (struct ejit_reloc){.insn = addr}; +} + +struct ejit_reloc ejit_bger_u(struct ejit_func *s, struct ejit_gpr r0, + struct ejit_gpr r1) +{ + size_t addr = vec_len(&s->insns); + emit_insn_r(s, BGER_U, 0, r0.r, r1.r); + return (struct ejit_reloc){.insn = addr}; +} + +struct ejit_reloc ejit_bger_f(struct ejit_func *s, struct ejit_fpr r0, + struct ejit_fpr r1) +{ + size_t addr = vec_len(&s->insns); + emit_insn_r(s, BGER_F, 0, r0.f, r1.f); + return (struct ejit_reloc){.insn = addr}; +} + +struct ejit_reloc ejit_bgei(struct ejit_func *s, struct ejit_gpr r0, int64_t o) +{ + size_t addr = vec_len(&s->insns); + emit_insn_i(s, BGEI, 0, r0.r, o); + return (struct ejit_reloc){.insn = addr}; +} + +struct ejit_reloc ejit_bgei_u(struct ejit_func *s, struct ejit_gpr r0, + int64_t o) +{ + size_t addr = vec_len(&s->insns); + emit_insn_i(s, BGEI_U, 0, r0.r, o); + return (struct ejit_reloc){.insn = addr}; +} + +struct ejit_reloc ejit_bler(struct ejit_func *s, struct ejit_gpr r0, + struct ejit_gpr r1) +{ + size_t addr = vec_len(&s->insns); + emit_insn_r(s, BGER, 0, r1.r, r0.r); + return (struct ejit_reloc){.insn = addr}; +} + +struct ejit_reloc ejit_bler_u(struct ejit_func *s, struct ejit_gpr r0, + struct ejit_gpr r1) +{ + size_t addr = vec_len(&s->insns); + emit_insn_r(s, BGER_U, 0, r1.r, r0.r); + return (struct ejit_reloc){.insn = addr}; +} + +struct ejit_reloc ejit_bler_f(struct ejit_func *s, struct ejit_fpr r0, + struct ejit_fpr r1) +{ + size_t addr = vec_len(&s->insns); + emit_insn_r(s, BGER_F, 0, r1.f, r0.f); + return (struct ejit_reloc){.insn = addr}; +} + +struct ejit_reloc ejit_blei(struct ejit_func *s, struct ejit_gpr r0, int64_t o) +{ + size_t addr = vec_len(&s->insns); + emit_insn_i(s, BLEI, 0, r0.r, o); + return (struct ejit_reloc){.insn = addr}; +} + +struct ejit_reloc ejit_blei_u(struct ejit_func *s, struct ejit_gpr r0, + int64_t o) +{ + size_t addr = vec_len(&s->insns); + emit_insn_i(s, BLEI_U, 0, r0.r, o); + return (struct ejit_reloc){.insn = addr}; +} + struct ejit_reloc ejit_bgti(struct ejit_func *s, struct ejit_gpr r0, int64_t o) { size_t addr = vec_len(&s->insns); @@ -345,6 +450,85 @@ struct ejit_reloc ejit_bgti(struct ejit_func *s, struct ejit_gpr r0, int64_t o) return (struct ejit_reloc){.insn = addr}; } +struct ejit_reloc ejit_bgti_u(struct ejit_func *s, struct ejit_gpr r0, + int64_t o) +{ + size_t addr = vec_len(&s->insns); + emit_insn_i(s, BGTI_U, 0, r0.r, o); + return (struct ejit_reloc){.insn = addr}; +} + +struct ejit_reloc ejit_bgtr(struct ejit_func *s, struct ejit_gpr r0, + struct ejit_gpr r1) +{ + size_t addr = vec_len(&s->insns); + emit_insn_r(s, BGTR, 0, r0.r, r1.r); + return (struct ejit_reloc){.insn = addr}; +} + +struct ejit_reloc ejit_bgtr_u(struct ejit_func *s, struct ejit_gpr r0, + struct ejit_gpr r1) +{ + size_t addr = vec_len(&s->insns); + emit_insn_r(s, BGTR_U, 0, r0.r, r1.r); + return (struct ejit_reloc){.insn = addr}; +} + +struct ejit_reloc ejit_bgtr_f(struct ejit_func *s, struct ejit_fpr r0, + struct ejit_fpr r1) +{ + size_t addr = vec_len(&s->insns); + emit_insn_r(s, BGTR_F, 0, r0.f, r1.f); + return (struct ejit_reloc){.insn = addr}; +} + +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, BGTR, 0, r1.r, r0.r); + return (struct ejit_reloc){.insn = addr}; +} + +struct ejit_reloc ejit_bltr_u(struct ejit_func *s, struct ejit_gpr r0, + struct ejit_gpr r1) +{ + size_t addr = vec_len(&s->insns); + emit_insn_r(s, BGTR_U, 0, r1.r, r0.r); + return (struct ejit_reloc){.insn = addr}; +} + +struct ejit_reloc ejit_bltr_f(struct ejit_func *s, struct ejit_fpr r0, + struct ejit_fpr r1) +{ + size_t addr = vec_len(&s->insns); + emit_insn_r(s, BGTR_F, 0, r1.f, r0.f); + return (struct ejit_reloc){.insn = addr}; +} + +struct ejit_reloc ejit_blti(struct ejit_func *s, struct ejit_gpr r0, int64_t o) +{ + size_t addr = vec_len(&s->insns); + emit_insn_i(s, BLTI, 0, r0.r, o); + return (struct ejit_reloc){.insn = addr}; +} + +struct ejit_reloc ejit_blti_u(struct ejit_func *s, struct ejit_gpr r0, + int64_t o) +{ + size_t addr = vec_len(&s->insns); + emit_insn_i(s, BLTI_U, 0, r0.r, o); + return (struct ejit_reloc){.insn = addr}; +} + +struct ejit_reloc ejit_bltgtr_f(struct ejit_func *s, struct ejit_fpr r0, + struct ejit_fpr r1) +{ + size_t addr = vec_len(&s->insns); + emit_insn_r(s, BLTGTR_F, 0, r0.f, r1.f); + return (struct ejit_reloc){.insn = addr}; +} + struct ejit_reloc ejit_jmp(struct ejit_func *s) { size_t addr = vec_len(&s->insns); @@ -352,6 +536,36 @@ struct ejit_reloc ejit_jmp(struct ejit_func *s) return (struct ejit_reloc){.insn = addr}; } +struct ejit_reloc ejit_bmci(struct ejit_func *s, struct ejit_gpr r0, int64_t o) +{ + size_t addr = vec_len(&s->insns); + emit_insn_i(s, BMCI, 0, r0.r, o); + return (struct ejit_reloc){.insn = addr}; +} + +struct ejit_reloc ejit_bmcr(struct ejit_func *s, struct ejit_gpr r0, + struct ejit_gpr r1) +{ + size_t addr = vec_len(&s->insns); + emit_insn_i(s, BMCR, 0, r0.r, r1.r); + return (struct ejit_reloc){.insn = addr}; +} + +struct ejit_reloc ejit_bmsi(struct ejit_func *s, struct ejit_gpr r0, int64_t o) +{ + size_t addr = vec_len(&s->insns); + emit_insn_i(s, BMSI, 0, r0.r, o); + return (struct ejit_reloc){.insn = addr}; +} + +struct ejit_reloc ejit_bmsr(struct ejit_func *s, struct ejit_gpr r0, + struct ejit_gpr r1) +{ + size_t addr = vec_len(&s->insns); + emit_insn_i(s, BMSR, 0, r0.r, r1.r); + return (struct ejit_reloc){.insn = addr}; +} + static struct interp_state create_interp_state() { struct interp_state state; @@ -381,7 +595,7 @@ long ejit_run_interp(struct ejit_func *f, size_t argc, long ejit_run_func(struct ejit_func *f, size_t argc, struct ejit_arg args[argc]) { - assert(f->gpr && "trying to run a function that hasn't been compiled"); + assert(f->size && "trying to run a function that hasn't been compiled"); assert(f->rtype == EJIT_VOID || ejit_int_type(f->rtype)); if (f->arena) return ((ejit_escape_t)f->arena)(argc, args); @@ -395,7 +609,7 @@ long ejit_run_func(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(f->size && "trying to run a function that hasn't been compiled"); assert(ejit_float_type(f->rtype)); if (f->arena) return ((ejit_escape_f_t)f->arena)(argc, args); diff --git a/src/interp.c b/src/interp.c index 059b1d3..fe61c36 100644 --- a/src/interp.c +++ b/src/interp.c @@ -30,19 +30,57 @@ union interp_ret ejit_interp(struct ejit_func *f, size_t argc, [ANDI] = &&ANDI, [EQR] = &&EQR, - [LTR] = &<R, + [EQR_F] = &&EQR_F, + + [NER] = &&NER, + [NER_F] = &&NER_F, + + [GTR] = &>R, + [GTR_U] = &>R_U, + [GTR_F] = &>R_F, + + [GER] = &&GER, + [GER_U] = &&GER_U, + [GER_F] = &&GER_F, [STXI64] = &&STXI64, [LDXIU64] = &&LDXIU64, - [BLTR] = &&BLTR, + [BNER] = &&BNER, [BNEI] = &&BNEI, + [BNER_F] = &&BNER_F, + [BEQR] = &&BEQR, [BEQI] = &&BEQI, + [BEQR_F] = &&BEQR_F, + + [BGER] = &&BGER, + [BGER_U] = &&BGER_U, + [BGEI] = &&BGEI, + [BGEI_U] = &&BGEI_U, + [BGER_F] = &&BGER_F, + + [BLEI] = &&BLEI, + [BLEI_U] = &&BLEI_U, + + [BGTR] = &&BGTR, + [BGTR_U] = &&BGTR_U, [BGTI] = &&BGTI, + [BGTI_U] = &&BGTI_U, + [BGTR_F] = &&BGTR_F, + + [BLTI] = &&BLTI, + [BLTI_U] = &&BLTI_U, + + [BLTGTR_F] = &&BLTGTR_F, [JMP] = &&JMP, + [BMCI] = &&BMCI, + [BMCR] = &&BMCR, + [BMSI] = &&BMSI, + [BMSR] = &&BMSR, + [RETR] = &&RETR, [RETI] = &&RETI, [RETR_F] = &&RETR_F, @@ -162,8 +200,40 @@ union interp_ret ejit_interp(struct ejit_func *f, size_t argc, gpr[i.r0] = gpr[i.r1] == gpr[i.r2]; DISPATCH(); - DO(LTR); - gpr[i.r0] = gpr[i.r1] < gpr[i.r2]; + DO(EQR_F); + gpr[i.r0] = fpr[i.r1] == fpr[i.r2]; + DISPATCH(); + + DO(NER); + gpr[i.r0] = gpr[i.r1] != gpr[i.r2]; + DISPATCH(); + + DO(NER_F); + gpr[i.r0] = fpr[i.r1] != fpr[i.r2]; + DISPATCH(); + + DO(GTR); + gpr[i.r0] = gpr[i.r1] > gpr[i.r2]; + DISPATCH(); + + DO(GTR_U); + gpr[i.r0] = (uint64_t)gpr[i.r1] > (uint64_t)gpr[i.r2]; + DISPATCH(); + + DO(GTR_F); + gpr[i.r0] = fpr[i.r1] > fpr[i.r2]; + DISPATCH(); + + DO(GER); + gpr[i.r0] = gpr[i.r1] >= gpr[i.r2]; + DISPATCH(); + + DO(GER_U); + gpr[i.r0] = (uint64_t)gpr[i.r1] >= (uint64_t)gpr[i.r2]; + DISPATCH(); + + DO(GER_F); + gpr[i.r0] = fpr[i.r1] >= fpr[i.r2]; DISPATCH(); DO(STXI64); @@ -176,8 +246,8 @@ union interp_ret ejit_interp(struct ejit_func *f, size_t argc, gpr[i.r0] = *addr; DISPATCH(); - DO(BLTR); - if (gpr[i.r1] < gpr[i.r2]) + DO(BNER); + if (gpr[i.r1] != gpr[i.r2]) JUMP(i.r0); DISPATCH(); @@ -188,6 +258,12 @@ union interp_ret ejit_interp(struct ejit_func *f, size_t argc, DISPATCH(); + DO(BNER_F); + if (fpr[i.r1] != fpr[i.r2]) + JUMP(i.r0); + + DISPATCH(); + DO(BEQR); if (gpr[i.r1] == gpr[i.r2]) JUMP(i.r0); @@ -200,16 +276,136 @@ union interp_ret ejit_interp(struct ejit_func *f, size_t argc, DISPATCH(); + DO(BEQR_F); + if (fpr[i.r1] == fpr[i.r2]) + JUMP(i.r0); + + DISPATCH(); + + DO(BGTR); + if (gpr[i.r1] > gpr[i.r2]) + JUMP(i.r0); + + DISPATCH(); + + DO(BGTR_U); + if ((uint64_t)gpr[i.r1] > (uint64_t)gpr[i.r2]) + JUMP(i.r0); + + DISPATCH(); + DO(BGTI); if (gpr[i.r1] > i.o) JUMP(i.r0); DISPATCH(); + DO(BGTI_U); + if ((uint64_t)gpr[i.r1] > (uint64_t)i.o) + JUMP(i.r0); + + DISPATCH(); + + DO(BGTR_F); + if (fpr[i.r1] > fpr[i.r2]) + JUMP(i.r0); + + DISPATCH(); + + DO(BLTI); + if (gpr[i.r1] < i.o) + JUMP(i.r0); + + DISPATCH(); + + DO(BLTI_U); + if ((uint64_t)gpr[i.r1] < (uint64_t)i.o) + JUMP(i.r0); + + DISPATCH(); + + DO(BGER); + if (gpr[i.r1] >= gpr[i.r2]) + JUMP(i.r0); + + DISPATCH(); + + DO(BGER_U); + if ((uint64_t)gpr[i.r1] >= (uint64_t)gpr[i.r2]) + JUMP(i.r0); + + DISPATCH(); + + DO(BGEI); + if (gpr[i.r1] >= i.o) + JUMP(i.r0); + + DISPATCH(); + + DO(BGEI_U); + if ((uint64_t)gpr[i.r1] >= (uint64_t)i.o) + JUMP(i.r0); + + DISPATCH(); + + DO(BGER_F); + if (fpr[i.r1] >= fpr[i.r2]) + JUMP(i.r0); + + DISPATCH(); + + DO(BLEI); + if (gpr[i.r1] <= i.o) + JUMP(i.r0); + + DISPATCH(); + + DO(BLEI_U); + if ((uint64_t)gpr[i.r1] <= (uint64_t)i.o) + JUMP(i.r0); + + DISPATCH(); + + DO(BLTGTR_F); + double f0 = fpr[i.r1]; + double f1 = fpr[i.r2]; + + if (isnan(f0) || isnan(f1)) + JUMP(++pc); + + if (!(f0 >= f1) || !(f0 <= f1)) + JUMP(i.r0); + + DISPATCH(); + DO(JMP); JUMP(i.r0); DISPATCH(); + DO(BMSR); + if (gpr[i.r1] & gpr[i.r2]) + JUMP(i.r0); + + DISPATCH(); + + DO(BMSI); + if (gpr[i.r1] & i.o) + JUMP(i.r0); + + DISPATCH(); + + DO(BMCR); + if (!(gpr[i.r1] & gpr[i.r2])) + JUMP(i.r0); + + DISPATCH(); + + DO(BMCI); + if (!(gpr[i.r1] & i.o)) + JUMP(i.r0); + + DISPATCH(); + DO(RETVAL); gpr[i.r0] = retval; DISPATCH(); |