aboutsummaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/common.h43
-rw-r--r--src/compile/compile.c17
-rw-r--r--src/ejit.c234
-rw-r--r--src/interp.c208
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;
diff --git a/src/ejit.c b/src/ejit.c
index e708740..adba1cc 100644
--- a/src/ejit.c
+++ b/src/ejit.c
@@ -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] = &&LTR,
+ [EQR_F] = &&EQR_F,
+
+ [NER] = &&NER,
+ [NER_F] = &&NER_F,
+
+ [GTR] = &&GTR,
+ [GTR_U] = &&GTR_U,
+ [GTR_F] = &&GTR_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();