aboutsummaryrefslogtreecommitdiff
path: root/src/ejit.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/ejit.c
parent3bf4d1ada6df5c74aac2a371d5f1e05fd55b4f02 (diff)
downloadejit-827dec28e4c0b1c4972f1419e0ac23e4dbd9d916.tar.gz
ejit-827dec28e4c0b1c4972f1419e0ac23e4dbd9d916.zip
enough functionality to implement posthaste
Diffstat (limited to 'src/ejit.c')
-rw-r--r--src/ejit.c104
1 files changed, 89 insertions, 15 deletions
diff --git a/src/ejit.c b/src/ejit.c
index 9393dc0..246f1fc 100644
--- a/src/ejit.c
+++ b/src/ejit.c
@@ -42,8 +42,8 @@ struct ejit_func *ejit_create_func(enum ejit_type rtype, size_t argc, const stru
for (size_t i = 0; i < argc; ++i) {
switch (args[i].kind) {
- case EJIT_OPERAND_GPR: emit_insn_i(f, PARAM, args[i].r, 0, args[i].type); break;
- case EJIT_OPERAND_FPR: emit_insn_i(f, PARAM_F, args[i].r, 0, args[i].type); break;
+ 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;
default: abort();
}
}
@@ -54,6 +54,9 @@ struct ejit_func *ejit_create_func(enum ejit_type rtype, size_t argc, const stru
void ejit_compile_func(struct ejit_func *f, size_t gpr, size_t fpr)
{
+ /* emit a final end instruction in case user didn't do a return */
+ emit_insn_i(f, END, 0, 0, 0);
+
f->gpr = gpr;
f->fpr = fpr;
@@ -68,7 +71,9 @@ void ejit_compile_func(struct ejit_func *f, size_t gpr, size_t fpr)
ejit_interp(f, 0, NULL, false, &labels);
foreach_vec(ii, f->insns) {
struct ejit_insn i = vect_at(struct ejit_insn, f->insns, ii);
- i.addr = labels[i.op];
+ void *addr = labels[i.op];
+ assert(addr);
+ i.addr = addr;
vect_at(struct ejit_insn, f->insns, ii) = i;
}
}
@@ -101,10 +106,10 @@ void ejit_calli(struct ejit_func *s, struct ejit_func *f, size_t argc, const str
{
for (size_t i = 0; i < argc; ++i) {
switch (args[i].kind) {
- case EJIT_OPERAND_GPR: emit_insn_i(s, ARG, args[i].r, args[i].type, 0); break;
- case EJIT_OPERAND_FPR: emit_insn_i(s, ARG_F, args[i].r, args[i].type, 0); break;
- case EJIT_OPERAND_IMM: emit_insn_i(s, ARG_I, 0, args[i].type, args[i].r); break;
- case EJIT_OPERAND_FLT: emit_insn_f(s, ARG_FI, 0, args[i].type, args[i].d); break;
+ case EJIT_OPERAND_GPR: emit_insn_r(s, ARG, i, args[i].type, args[i].r); break;
+ case EJIT_OPERAND_FPR: emit_insn_r(s, ARG_F, i, args[i].type, args[i].r); break;
+ case EJIT_OPERAND_IMM: emit_insn_i(s, ARG_I, i, args[i].type, args[i].r); break;
+ case EJIT_OPERAND_FLT: emit_insn_f(s, ARG_FI, i, args[i].type, args[i].d); break;
default: abort();
}
}
@@ -116,10 +121,10 @@ void ejit_escapei(struct ejit_func *s, ejit_escape_t f, size_t argc, const struc
{
for (size_t i = 0; i < argc; ++i) {
switch (args[i].kind) {
- case EJIT_OPERAND_GPR: emit_insn_i(s, ARG, args[i].r, 0, 0); break;
- case EJIT_OPERAND_FPR: emit_insn_i(s, ARG_F, args[i].r, 0, 0); break;
- case EJIT_OPERAND_IMM: emit_insn_i(s, ARG_I, 0, 0, args[i].r); break;
- case EJIT_OPERAND_FLT: emit_insn_f(s, ARG_FI, 0, 0, args[i].d); break;
+ case EJIT_OPERAND_GPR: emit_insn_r(s, ARG, i, args[i].type, args[i].r); break;
+ case EJIT_OPERAND_FPR: emit_insn_r(s, ARG_F, i, args[i].type, args[i].r); break;
+ case EJIT_OPERAND_IMM: emit_insn_r(s, ARG_I, i, args[i].type, args[i].r); break;
+ case EJIT_OPERAND_FLT: emit_insn_f(s, ARG_FI, i, args[i].type, args[i].d); break;
default: abort();
}
}
@@ -131,10 +136,10 @@ void ejit_escapei_f(struct ejit_func *s, ejit_escape_f_t f, size_t argc, const s
{
for (size_t i = 0; i < argc; ++i) {
switch (args[i].kind) {
- case EJIT_OPERAND_GPR: emit_insn_i(s, ARG, args[i].r, 0, 0); break;
- case EJIT_OPERAND_FPR: emit_insn_i(s, ARG_F, args[i].r, 0, 0); break;
- case EJIT_OPERAND_IMM: emit_insn_i(s, ARG_I, 0, 0, args[i].r); break;
- case EJIT_OPERAND_FLT: emit_insn_f(s, ARG_FI, 0, 0, args[i].d); break;
+ case EJIT_OPERAND_GPR: emit_insn_r(s, ARG, i, args[i].type, args[i].r); break;
+ case EJIT_OPERAND_FPR: emit_insn_r(s, ARG_F, i, args[i].type, args[i].r); break;
+ case EJIT_OPERAND_IMM: emit_insn_r(s, ARG_I, i, args[i].type, args[i].r); break;
+ case EJIT_OPERAND_FLT: emit_insn_f(s, ARG_FI, i, args[i].type, args[i].d); break;
default: abort();
}
}
@@ -142,6 +147,21 @@ void ejit_escapei_f(struct ejit_func *s, ejit_escape_f_t f, size_t argc, const s
emit_insn_p(s, ESCAPEI_F, 0, 0, f);
}
+void ejit_retval(struct ejit_func *s, struct ejit_gpr r0)
+{
+ emit_insn_i(s, RETVAL, r0.r, 0, 0);
+}
+
+void ejit_stxi_64(struct ejit_func *s, struct ejit_gpr r0, struct ejit_gpr r1, long o)
+{
+ emit_insn_i(s, STXI64, r0.r, r1.r, o);
+}
+
+void ejit_ldxi_u64(struct ejit_func *s, struct ejit_gpr r0, struct ejit_gpr r1, long o)
+{
+ emit_insn_i(s, LDXIU64, r0.r, r1.r, o);
+}
+
void ejit_ret(struct ejit_func *s, struct ejit_gpr r0)
{
emit_insn_r(s, RET, r0.r, 0, 0);
@@ -182,11 +202,44 @@ void ejit_subr_f(struct ejit_func *s, struct ejit_fpr r0, struct ejit_fpr r1, st
emit_insn_r(s, SUBR_F, r0.f, r1.f, r2.f);
}
+void ejit_mulr(struct ejit_func *s, struct ejit_gpr r0, struct ejit_gpr r1, struct ejit_gpr r2)
+{
+ emit_insn_r(s, MULR, r0.r, r1.r, r2.r);
+}
+
+void ejit_divr(struct ejit_func *s, struct ejit_gpr r0, struct ejit_gpr r1, struct ejit_gpr r2)
+{
+ emit_insn_r(s, DIVR, r0.r, r1.r, r2.r);
+}
+
+void ejit_negr(struct ejit_func *s, struct ejit_gpr r0, struct ejit_gpr r1)
+{
+ emit_insn_i(s, NEGR, r0.r, r1.r, 0);
+}
+
void ejit_movi(struct ejit_func *s, struct ejit_gpr r0, long o)
{
emit_insn_i(s, MOVI, r0.r, 0, o);
}
+void ejit_movr(struct ejit_func *s, struct ejit_gpr r0, struct ejit_gpr r1)
+{
+ if (r0.r == r1.r)
+ return;
+
+ emit_insn_i(s, MOVR, r0.r, r1.r, 0);
+}
+
+void ejit_eqr(struct ejit_func *s, struct ejit_gpr r0, struct ejit_gpr r1, struct ejit_gpr r2)
+{
+ emit_insn_r(s, EQR, r0.r, r1.r, r2.r);
+}
+
+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);
+}
+
struct ejit_reloc ejit_bltr(struct ejit_func *s, struct ejit_gpr r0, struct ejit_gpr r1)
{
size_t addr = vec_len(&s->insns);
@@ -194,6 +247,27 @@ struct ejit_reloc ejit_bltr(struct ejit_func *s, struct ejit_gpr r0, struct ejit
return (struct ejit_reloc){.insn = addr};
}
+struct ejit_reloc ejit_bnei(struct ejit_func *s, struct ejit_gpr r0, long o)
+{
+ size_t addr = vec_len(&s->insns);
+ emit_insn_i(s, BNEI, 0, r0.r, o);
+ return (struct ejit_reloc){.insn = addr};
+}
+
+struct ejit_reloc ejit_beqi(struct ejit_func *s, struct ejit_gpr r0, long o)
+{
+ size_t addr = vec_len(&s->insns);
+ emit_insn_i(s, BEQI, 0, r0.r, o);
+ return (struct ejit_reloc){.insn = addr};
+}
+
+struct ejit_reloc ejit_jmp(struct ejit_func *s)
+{
+ size_t addr = vec_len(&s->insns);
+ emit_insn_i(s, JMP, 0, 0, 0);
+ return (struct ejit_reloc){.insn = addr};
+}
+
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");