aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
m---------deps/lightening0
-rw-r--r--include/ejit/ejit.h6
-rw-r--r--scripts/makefile6
-rwxr-xr-xscripts/select-compile1
-rw-r--r--src/common.h6
-rw-r--r--src/compile/compile.c294
-rw-r--r--src/ejit.c31
-rw-r--r--src/interp.c67
-rw-r--r--tests/maxr_d.c28
-rw-r--r--tests/maxr_f.c28
-rw-r--r--tests/minr_d.c28
-rw-r--r--tests/minr_f.c28
12 files changed, 449 insertions, 74 deletions
diff --git a/deps/lightening b/deps/lightening
-Subproject 6421af4db1570a6a5fc3a15f3bcb2601d854ed0
+Subproject 8d59c872edc5a21e7dd78768b291d0c4d8136e4
diff --git a/include/ejit/ejit.h b/include/ejit/ejit.h
index b4b20c1..965103c 100644
--- a/include/ejit/ejit.h
+++ b/include/ejit/ejit.h
@@ -872,6 +872,12 @@ void ejit_truncr_d_64(struct ejit_func *s, struct ejit_gpr r0,
void ejit_sqrtr_f(struct ejit_func *s, struct ejit_fpr r0, struct ejit_fpr r1);
void ejit_sqrtr_d(struct ejit_func *s, struct ejit_fpr r0, struct ejit_fpr r1);
+void ejit_minr_f(struct ejit_func *s, struct ejit_fpr r0, struct ejit_fpr r1, struct ejit_fpr r2);
+void ejit_minr_d(struct ejit_func *s, struct ejit_fpr r0, struct ejit_fpr r1, struct ejit_fpr r2);
+
+void ejit_maxr_f(struct ejit_func *s, struct ejit_fpr r0, struct ejit_fpr r1, struct ejit_fpr r2);
+void ejit_maxr_d(struct ejit_func *s, struct ejit_fpr r0, struct ejit_fpr r1, struct ejit_fpr r2);
+
struct ejit_reloc ejit_bltr(struct ejit_func *s, struct ejit_gpr r0,
struct ejit_gpr r1);
struct ejit_reloc ejit_bner(struct ejit_func *s, struct ejit_gpr r0,
diff --git a/scripts/makefile b/scripts/makefile
index bd02c98..5178359 100644
--- a/scripts/makefile
+++ b/scripts/makefile
@@ -68,13 +68,13 @@ libejit.a: $(EJIT_OBJS)
examples: examples/loop examples/fib examples/matrix_mult
examples/matrix_mult: examples/matrix_mult.c libejit.a
- $(COMPILE_EJIT) examples/matrix_mult.c libejit.a -o $@
+ $(COMPILE_EJIT) examples/matrix_mult.c libejit.a -o $@ -lm
examples/loop: examples/loop.c libejit.a
- $(COMPILE_EJIT) examples/loop.c libejit.a -o $@
+ $(COMPILE_EJIT) examples/loop.c libejit.a -o $@ -lm
examples/fib: examples/fib.c libejit.a
- $(COMPILE_EJIT) examples/fib.c libejit.a -o $@
+ $(COMPILE_EJIT) examples/fib.c libejit.a -o $@ -lm
# might lint some common things twice
.PHONY:
diff --git a/scripts/select-compile b/scripts/select-compile
index 38fc7b0..37c67a1 100755
--- a/scripts/select-compile
+++ b/scripts/select-compile
@@ -13,6 +13,7 @@ case "$ARCH" in
mips64el) echo "$JIT" ;;
aarch64) echo "$JIT" ;;
mipsel) echo "$JIT" ;;
+ armhf) echo "$JIT" ;;
amd64) echo "$JIT" ;;
x86*) echo "$JIT" ;;
*) echo "$NOJIT" ;;
diff --git a/src/common.h b/src/common.h
index 661220b..69f1441 100644
--- a/src/common.h
+++ b/src/common.h
@@ -145,6 +145,12 @@ enum ejit_opcode {
EJIT_OP_SQRTR_F,
EJIT_OP_SQRTR_D,
+ EJIT_OP_MINR_F,
+ EJIT_OP_MINR_D,
+
+ EJIT_OP_MAXR_F,
+ EJIT_OP_MAXR_D,
+
EJIT_OP_EQR,
EJIT_OP_NER,
EJIT_OP_GTR,
diff --git a/src/compile/compile.c b/src/compile/compile.c
index dac8dfd..dcf662b 100644
--- a/src/compile/compile.c
+++ b/src/compile/compile.c
@@ -1927,7 +1927,7 @@ static void compile_trampoline(struct ejit_func *f, jit_state_t *j)
jit_leave_jit_abi(j, 0, 0, frame);
jit_ret(j); /* should just forward the return value */
- f->direct_call = jit_address(j);
+ f->direct_call = jit_address_to_function_pointer(jit_address(j));
jit_patch_here(j, r);
operands_destroy(&args);
@@ -1939,6 +1939,84 @@ static void compile_trampoline(struct ejit_func *f, jit_state_t *j)
}
}
+static void resolve_top_reloc(jit_state_t *j, struct relocs *relocs, struct addrs *addrs, size_t ii)
+{
+ assert(relocs_len(relocs) != 0);
+
+ struct reloc_helper h = *relocs_back(relocs);
+ if (h.to >= ii)
+ return;
+
+ jit_addr_t a = *addrs_at(addrs, h.to);
+ jit_reloc_t r = h.r;
+
+ assert(a);
+ jit_patch_there(j, r, a);
+ relocs_pop(relocs);
+}
+
+static void resolve_relocs(jit_state_t *j, struct relocs *relocs, struct addrs *addrs, size_t ii)
+{
+ foreach_vec(ri, *relocs) {
+ struct reloc_helper h = *relocs_at(relocs, ri);
+ if (h.to != ii)
+ continue;
+
+ jit_addr_t a = *addrs_at(addrs, ii);
+ jit_reloc_t r = h.r;
+
+ assert(a);
+ jit_patch_there(j, r, a);
+
+ /* 'shift' down */
+ if (ri != relocs_len(relocs) - 1)
+ *relocs_at(relocs, ri) = *relocs_back(relocs);
+
+ assert(relocs_len(relocs) != 0);
+ relocs_shrink(relocs, relocs_len(relocs) - 1);
+ }
+}
+
+static void compile_maxr_f(struct ejit_func *f, jit_state_t *j,
+ struct ejit_insn i)
+{
+ jit_fpr_t r0 = getfpr(f, i.r0, 0);
+ jit_fpr_t r1 = getloc_f(f, j, i.r1, 1);
+ jit_fpr_t r2 = getloc_f(f, j, i.r2, 2);
+ jit_maxr_f(j, r0, r1, r2);
+ putloc_f(f, j, i.r0, r0);
+}
+
+static void compile_maxr_d(struct ejit_func *f, jit_state_t *j,
+ struct ejit_insn i)
+{
+ jit_fpr_t r0 = getfpr(f, i.r0, 0);
+ jit_fpr_t r1 = getloc_d(f, j, i.r1, 1);
+ jit_fpr_t r2 = getloc_d(f, j, i.r2, 2);
+ jit_maxr_d(j, r0, r1, r2);
+ putloc_d(f, j, i.r0, r0);
+}
+
+static void compile_minr_f(struct ejit_func *f, jit_state_t *j,
+ struct ejit_insn i)
+{
+ jit_fpr_t r0 = getfpr(f, i.r0, 0);
+ jit_fpr_t r1 = getloc_f(f, j, i.r1, 1);
+ jit_fpr_t r2 = getloc_f(f, j, i.r2, 2);
+ jit_minr_f(j, r0, r1, r2);
+ putloc_f(f, j, i.r0, r0);
+}
+
+static void compile_minr_d(struct ejit_func *f, jit_state_t *j,
+ struct ejit_insn i)
+{
+ jit_fpr_t r0 = getfpr(f, i.r0, 0);
+ jit_fpr_t r1 = getloc_d(f, j, i.r1, 1);
+ jit_fpr_t r2 = getloc_d(f, j, i.r2, 2);
+ jit_minr_d(j, r0, r1, r2);
+ putloc_d(f, j, i.r0, r0);
+}
+
static size_t compile_fn_body(struct ejit_func *f, jit_state_t *j, void *arena,
size_t size)
{
@@ -1960,7 +2038,7 @@ static size_t compile_fn_body(struct ejit_func *f, jit_state_t *j, void *arena,
struct operands dst = operands_create();
struct operands direct = operands_create();
- struct relocs relocs = relocs_create(sizeof(struct reloc_helper));
+ struct relocs relocs = relocs_create();
struct addrs addrs = addrs_create();
addrs_reserve(&addrs, insns_len(&f->insns));
@@ -1972,6 +2050,7 @@ static size_t compile_fn_body(struct ejit_func *f, jit_state_t *j, void *arena,
if (label < labels_len(&f->labels)) {
if (*labels_at(&f->labels, label) == ii) {
compile_label(j, ii, &addrs);
+ resolve_relocs(j, &relocs, &addrs, ii);
label++;
}
}
@@ -2104,6 +2183,12 @@ static size_t compile_fn_body(struct ejit_func *f, jit_state_t *j, void *arena,
case EJIT_OP_SQRTR_F: compile_sqrtr_f(f, j, i); break;
case EJIT_OP_SQRTR_D: compile_sqrtr_d(f, j, i); break;
+ case EJIT_OP_MINR_F: compile_minr_f(f, j, i); break;
+ case EJIT_OP_MINR_D: compile_minr_d(f, j, i); break;
+
+ case EJIT_OP_MAXR_F: compile_maxr_f(f, j, i); break;
+ case EJIT_OP_MAXR_D: compile_maxr_d(f, j, i); break;
+
case EJIT_OP_EQR: compile_eqr(f, j, i); break;
case EJIT_OP_EQR_F: compile_eqr_f(f, j, i); break;
case EJIT_OP_EQR_D: compile_eqr_d(f, j, i); break;
@@ -2122,43 +2207,179 @@ static size_t compile_fn_body(struct ejit_func *f, jit_state_t *j, void *arena,
case EJIT_OP_GTR_F: compile_gtr_f(f, j, i); break;
case EJIT_OP_GTR_D: compile_gtr_d(f, j, i); break;
- case EJIT_OP_BMCI: compile_bmci(f, j, i, &relocs); break;
- case EJIT_OP_BMCR: compile_bmcr(f, j, i, &relocs); break;
+ case EJIT_OP_BMCI: {
+ compile_bmci(f, j, i, &relocs);
+ resolve_top_reloc(j, &relocs, &addrs, ii);
+ break;
+ }
+
+ case EJIT_OP_BMCR: {
+ compile_bmcr(f, j, i, &relocs);
+ resolve_top_reloc(j, &relocs, &addrs, ii);
+ break;
+ }
+
+ case EJIT_OP_BMSI: {
+ compile_bmsi(f, j, i, &relocs);
+ resolve_top_reloc(j, &relocs, &addrs, ii);
+ break;
+ }
+
+ case EJIT_OP_BMSR: {
+ compile_bmsr(f, j, i, &relocs);
+ resolve_top_reloc(j, &relocs, &addrs, ii);
+ break;
+ }
+
+ case EJIT_OP_BEQR: {
+ compile_beqr(f, j, i, &relocs);
+ resolve_top_reloc(j, &relocs, &addrs, ii);
+ break;
+ }
+
+ case EJIT_OP_BEQI: {
+ compile_beqi(f, j, i, &relocs);
+ resolve_top_reloc(j, &relocs, &addrs, ii);
+ break;
+ }
+
+ case EJIT_OP_BEQR_F: {
+ compile_beqr_f(f, j, i, &relocs);
+ resolve_top_reloc(j, &relocs, &addrs, ii);
+ break;
+ }
+
+ case EJIT_OP_BEQR_D: {
+ compile_beqr_d(f, j, i, &relocs);
+ resolve_top_reloc(j, &relocs, &addrs, ii);
+ break;
+ }
+
+ case EJIT_OP_BNER: {
+ compile_bner(f, j, i, &relocs);
+ resolve_top_reloc(j, &relocs, &addrs, ii);
+ break;
+ }
+
+ case EJIT_OP_BNEI: {
+ compile_bnei(f, j, i, &relocs);
+ resolve_top_reloc(j, &relocs, &addrs, ii);
+ break;
+ }
+
+ case EJIT_OP_BNER_F: {
+ compile_bner_f(f, j, i, &relocs);
+ resolve_top_reloc(j, &relocs, &addrs, ii);
+ break;
+ }
+
+ case EJIT_OP_BNER_D: {
+ compile_bner_d(f, j, i, &relocs);
+ resolve_top_reloc(j, &relocs, &addrs, ii);
+ break;
+ }
+
+ case EJIT_OP_BGER: {
+ compile_bger(f, j, i, &relocs);
+ resolve_top_reloc(j, &relocs, &addrs, ii);
+ break;
+ }
+
+ case EJIT_OP_BGER_U: {
+ compile_bger_u(f, j, i, &relocs);
+ resolve_top_reloc(j, &relocs, &addrs, ii);
+ break;
+ }
+
+ case EJIT_OP_BGEI: {
+ compile_bgei(f, j, i, &relocs);
+ resolve_top_reloc(j, &relocs, &addrs, ii);
+ break;
+ }
+
+ case EJIT_OP_BGEI_U: {
+ compile_bgei_u(f, j, i, &relocs);
+ resolve_top_reloc(j, &relocs, &addrs, ii);
+ break;
+ }
+
+ case EJIT_OP_BGER_F: {
+ compile_bger_f(f, j, i, &relocs);
+ resolve_top_reloc(j, &relocs, &addrs, ii);
+ break;
+ }
- case EJIT_OP_BMSI: compile_bmsi(f, j, i, &relocs); break;
- case EJIT_OP_BMSR: compile_bmsr(f, j, i, &relocs); break;
+ case EJIT_OP_BGER_D: {
+ compile_bger_d(f, j, i, &relocs);
+ resolve_top_reloc(j, &relocs, &addrs, ii);
+ break;
+ }
+
+ case EJIT_OP_BGTR: {
+ compile_bgtr(f, j, i, &relocs);
+ resolve_top_reloc(j, &relocs, &addrs, ii);
+ break;
+ }
+
+ case EJIT_OP_BGTR_U: {
+ compile_bgtr_u(f, j, i, &relocs);
+ resolve_top_reloc(j, &relocs, &addrs, ii);
+ break;
+ }
- case EJIT_OP_BEQR: compile_beqr(f, j, i, &relocs); break;
- case EJIT_OP_BEQI: compile_beqi(f, j, i, &relocs); break;
- case EJIT_OP_BEQR_F: compile_beqr_f(f, j, i, &relocs); break;
- case EJIT_OP_BEQR_D: compile_beqr_d(f, j, i, &relocs); break;
+ case EJIT_OP_BGTI: {
+ compile_bgti(f, j, i, &relocs);
+ resolve_top_reloc(j, &relocs, &addrs, ii);
+ break;
+ }
+
+ case EJIT_OP_BGTI_U: {
+ compile_bgti_u(f, j, i, &relocs);
+ resolve_top_reloc(j, &relocs, &addrs, ii);
+ break;
+ }
+
+ case EJIT_OP_BGTR_F: {
+ compile_bgtr_f(f, j, i, &relocs);
+ resolve_top_reloc(j, &relocs, &addrs, ii);
+ break;
+ }
- case EJIT_OP_BNER: compile_bner(f, j, i, &relocs); break;
- case EJIT_OP_BNEI: compile_bnei(f, j, i, &relocs); break;
- case EJIT_OP_BNER_F: compile_bner_f(f, j, i, &relocs); break;
- case EJIT_OP_BNER_D: compile_bner_d(f, j, i, &relocs); break;
+ case EJIT_OP_BGTR_D: {
+ compile_bgtr_d(f, j, i, &relocs);
+ resolve_top_reloc(j, &relocs, &addrs, ii);
+ break;
+ }
- case EJIT_OP_BGER: compile_bger(f, j, i, &relocs); break;
- case EJIT_OP_BGER_U: compile_bger_u(f, j, i, &relocs); break;
- case EJIT_OP_BGEI: compile_bgei(f, j, i, &relocs); break;
- case EJIT_OP_BGEI_U: compile_bgei_u(f, j, i, &relocs); break;
- case EJIT_OP_BGER_F: compile_bger_f(f, j, i, &relocs); break;
- case EJIT_OP_BGER_D: compile_bger_d(f, j, i, &relocs); break;
+ case EJIT_OP_BLEI: {
+ compile_blei(f, j, i, &relocs);
+ resolve_top_reloc(j, &relocs, &addrs, ii);
+ break;
+ }
- case EJIT_OP_BGTR: compile_bgtr(f, j, i, &relocs); break;
- case EJIT_OP_BGTR_U: compile_bgtr_u(f, j, i, &relocs); break;
- case EJIT_OP_BGTI: compile_bgti(f, j, i, &relocs); break;
- case EJIT_OP_BGTI_U: compile_bgti_u(f, j, i, &relocs); break;
- case EJIT_OP_BGTR_F: compile_bgtr_f(f, j, i, &relocs); break;
- case EJIT_OP_BGTR_D: compile_bgtr_d(f, j, i, &relocs); break;
+ case EJIT_OP_BLEI_U: {
+ compile_blei_u(f, j, i, &relocs);
+ resolve_top_reloc(j, &relocs, &addrs, ii);
+ break;
+ }
- case EJIT_OP_BLEI: compile_blei(f, j, i, &relocs); break;
- case EJIT_OP_BLEI_U: compile_blei_u(f, j, i, &relocs); break;
+ case EJIT_OP_BLTI: {
+ compile_blti(f, j, i, &relocs);
+ resolve_top_reloc(j, &relocs, &addrs, ii);
+ break;
+ }
- case EJIT_OP_BLTI: compile_blti(f, j, i, &relocs); break;
- case EJIT_OP_BLTI_U: compile_blti_u(f, j, i, &relocs); break;
+ case EJIT_OP_BLTI_U: {
+ compile_blti_u(f, j, i, &relocs);
+ resolve_top_reloc(j, &relocs, &addrs, ii);
+ break;
+ }
- case EJIT_OP_JMP: compile_jmp(f, j, i, &relocs); break;
+ case EJIT_OP_JMP: {
+ compile_jmp(f, j, i, &relocs);
+ resolve_top_reloc(j, &relocs, &addrs, ii);
+ break;
+ }
case EJIT_OP_ARG_I: {
jit_operand_t type = jit_operand_imm(JIT_OPERAND_ABI_WORD, i.r1);
@@ -2420,14 +2641,7 @@ calli:
}
}
- foreach_vec(ri, relocs) {
- struct reloc_helper h = *relocs_at(&relocs, ri);
- jit_addr_t a = *addrs_at(&addrs, h.to);
- jit_reloc_t r = h.r;
-
- assert(a);
- jit_patch_there(j, r, a);
- }
+ assert(relocs_len(&relocs) == 0);
operands_destroy(&src);
operands_destroy(&dst);
@@ -2435,7 +2649,7 @@ calli:
relocs_destroy(&relocs);
addrs_destroy(&addrs);
- if (jit_end(j, &size))
+ if ((f->extern_call = jit_end(j, &size)))
return 0;
return size;
diff --git a/src/ejit.c b/src/ejit.c
index 0ee3986..571a274 100644
--- a/src/ejit.c
+++ b/src/ejit.c
@@ -345,6 +345,7 @@ struct ejit_func *ejit_create_func(enum ejit_type rtype, size_t argc,
f->fpr = fpr_stats_create();
f->arena = NULL;
f->direct_call = NULL;
+ f->extern_call = NULL;
f->size = 0;
f->prio = 1;
f->use_64 = false;
@@ -458,7 +459,7 @@ void ejit_patch(struct ejit_func *f, struct ejit_reloc r, struct ejit_label l)
void ejit_calli_i(struct ejit_func *s, struct ejit_func *f, size_t argc,
const struct ejit_operand args[argc])
{
- f->max_args = argc > f->max_args ? argc : f->max_args;
+ s->max_args = argc > s->max_args ? argc : s->max_args;
check_operands(f, argc, args);
for (size_t i = 0; i < argc; ++i) {
@@ -478,7 +479,7 @@ void ejit_calli_l(struct ejit_func *s, struct ejit_func *f, size_t argc,
const struct ejit_operand args[argc])
{
s->use_64 = true;
- f->max_args = argc > f->max_args ? argc : f->max_args;
+ s->max_args = argc > s->max_args ? argc : s->max_args;
check_operands(f, argc, args);
for (size_t i = 0; i < argc; ++i) {
@@ -900,31 +901,37 @@ void ejit_ret(struct ejit_func *s)
void ejit_retr(struct ejit_func *s, struct ejit_gpr r0)
{
+ assert(s->rtype != EJIT_FLOAT && s->rtype != EJIT_DOUBLE);
emit_insn_oxr(s, EJIT_OP_RETR, r0);
}
void ejit_retr_f(struct ejit_func *s, struct ejit_fpr f0)
{
+ assert(s->rtype == EJIT_FLOAT);
emit_insn_oxf(s, EJIT_OP_RETR_F, f0);
}
void ejit_retr_d(struct ejit_func *s, struct ejit_fpr f0)
{
+ assert(s->rtype == EJIT_DOUBLE);
emit_insn_oxf(s, EJIT_OP_RETR_D, f0);
}
void ejit_reti(struct ejit_func *s, int64_t i)
{
+ assert(s->rtype != EJIT_FLOAT && s->rtype != EJIT_DOUBLE);
emit_insn_oi(s, EJIT_OP_RETI, i);
}
void ejit_reti_f(struct ejit_func *s, float f)
{
+ assert(s->rtype == EJIT_FLOAT);
emit_insn_oF(s, EJIT_OP_RETI_F, f);
}
void ejit_reti_d(struct ejit_func *s, double f)
{
+ assert(s->rtype == EJIT_DOUBLE);
emit_insn_oD(s, EJIT_OP_RETI_D, f);
}
@@ -1381,6 +1388,26 @@ void ejit_sqrtr_d(struct ejit_func *s, struct ejit_fpr r0, struct ejit_fpr r1)
emit_insn_off(s, EJIT_OP_SQRTR_D, r0, r1);
}
+void ejit_minr_f(struct ejit_func *s, struct ejit_fpr r0, struct ejit_fpr r1, struct ejit_fpr r2)
+{
+ emit_insn_offf(s, EJIT_OP_MINR_F, r0, r1, r2);
+}
+
+void ejit_minr_d(struct ejit_func *s, struct ejit_fpr r0, struct ejit_fpr r1, struct ejit_fpr r2)
+{
+ emit_insn_offf(s, EJIT_OP_MINR_D, r0, r1, r2);
+}
+
+void ejit_maxr_f(struct ejit_func *s, struct ejit_fpr r0, struct ejit_fpr r1, struct ejit_fpr r2)
+{
+ emit_insn_offf(s, EJIT_OP_MAXR_F, r0, r1, r2);
+}
+
+void ejit_maxr_d(struct ejit_func *s, struct ejit_fpr r0, struct ejit_fpr r1, struct ejit_fpr r2)
+{
+ emit_insn_offf(s, EJIT_OP_MAXR_D, r0, r1, r2);
+}
+
struct ejit_reloc ejit_bner(struct ejit_func *s, struct ejit_gpr r0,
struct ejit_gpr r1)
{
diff --git a/src/interp.c b/src/interp.c
index 049498a..6ef414d 100644
--- a/src/interp.c
+++ b/src/interp.c
@@ -150,6 +150,12 @@ union interp_ret ejit_run(struct ejit_func *f, size_t paramc, struct ejit_arg pa
[EJIT_OP_SQRTR_F] = &&SQRTR_F,
[EJIT_OP_SQRTR_D] = &&SQRTR_D,
+ [EJIT_OP_MINR_F] = &&MINR_F,
+ [EJIT_OP_MINR_D] = &&MINR_D,
+
+ [EJIT_OP_MAXR_F] = &&MAXR_F,
+ [EJIT_OP_MAXR_D] = &&MAXR_D,
+
[EJIT_OP_BNER] = &&BNER,
[EJIT_OP_BNEI] = &&BNEI,
[EJIT_OP_BNER_F] = &&BNER_F,
@@ -222,29 +228,29 @@ union interp_ret ejit_run(struct ejit_func *f, size_t paramc, struct ejit_arg pa
if (!run) {
*labels_wb = labels;
- goto zero_out;
+ return (union interp_ret){.i = 0};
}
assert(f->size && "trying to run a function that hasn't been compiled");
- if (f->arena) {
+ if (f->extern_call) {
if (f->rtype == EJIT_INT64 || f->rtype == EJIT_UINT64)
return (union interp_ret){
- .i = ((ejit_escape_l_t)f->arena)(paramc, params)
+ .i = ((ejit_escape_l_t)f->extern_call)(paramc, params)
};
if (f->rtype == EJIT_DOUBLE)
return (union interp_ret){
- .f = ((ejit_escape_d_t)f->arena)(paramc, params)
+ .f = ((ejit_escape_d_t)f->extern_call)(paramc, params)
};
if (f->rtype == EJIT_FLOAT)
return (union interp_ret){
- .f = ((ejit_escape_f_t)f->arena)(paramc, params)
+ .f = ((ejit_escape_f_t)f->extern_call)(paramc, params)
};
return (union interp_ret){
- .i = ((ejit_escape_i_t)f->arena)(paramc, params)
+ .i = ((ejit_escape_i_t)f->extern_call)(paramc, params)
};
}
@@ -256,9 +262,9 @@ union interp_ret ejit_run(struct ejit_func *f, size_t paramc, struct ejit_arg pa
};
size_t argc = 0;
- int64_t *gpr = alloca(sizeof(int64_t) * gpr_stats_len(&f->gpr));
- union fpr *fpr = alloca(sizeof(int64_t) * fpr_stats_len(&f->fpr));
- struct ejit_arg *args = alloca(sizeof(struct ejit_arg) * f->max_args);
+ int64_t gpr[gpr_stats_len(&f->gpr)];
+ union fpr fpr[fpr_stats_len(&f->fpr)];
+ struct ejit_arg args[f->max_args];
struct ejit_insn *insns = f->insns.buf;
/* retval is kind of an unfortunate extra bit of state to keep track of,
@@ -276,7 +282,7 @@ union interp_ret ejit_run(struct ejit_func *f, size_t paramc, struct ejit_arg pa
DISPATCH();
DO(END);
- goto zero_out;
+ return (union interp_ret){.i = 0};
DISPATCH();
DO(MOVI);
@@ -791,6 +797,22 @@ union interp_ret ejit_run(struct ejit_func *f, size_t paramc, struct ejit_arg pa
fpr[i.r0].f = sqrt(fpr[i.r1].f);
DISPATCH();
+ DO(MINR_F);
+ fpr[i.r0].f = fminf(fpr[i.r1].f, fpr[i.r2].f);
+ DISPATCH();
+
+ DO(MINR_D);
+ fpr[i.r0].d = fmin(fpr[i.r1].d, fpr[i.r2].d);
+ DISPATCH();
+
+ DO(MAXR_F);
+ fpr[i.r0].f = fmaxf(fpr[i.r1].f, fpr[i.r2].f);
+ DISPATCH();
+
+ DO(MAXR_D);
+ fpr[i.r0].d = fmax(fpr[i.r1].d, fpr[i.r2].d);
+ DISPATCH();
+
DO(SQRTR_D);
fpr[i.r0].d = sqrt(fpr[i.r1].d);
DISPATCH();
@@ -1087,45 +1109,32 @@ union interp_ret ejit_run(struct ejit_func *f, size_t paramc, struct ejit_arg pa
/* dispatch is technically unnecessary for returns, but keep it for
* symmetry */
DO(RETR);
- retval = gpr[i.r1];
- goto out_int;
+ return (union interp_ret){.i = gpr[i.r1]};
DISPATCH();
DO(RETI);
- retval = i.o;
- goto out_int;
+ return (union interp_ret){.i = i.o};
DISPATCH();
DO(RETR_F);
- retval_f = fpr[i.r1].f;
- goto out_float;
+ return (union interp_ret){.f = fpr[i.r1].f};
DISPATCH();
DO(RETR_D);
- retval_f = fpr[i.r1].d;
- goto out_float;
+ return (union interp_ret){.f = fpr[i.r1].d};
DISPATCH();
DO(RETI_F);
- retval_f = i.f;
- goto out_float;
+ return (union interp_ret){.f = i.f};
DISPATCH();
DO(RETI_D);
- retval_f = i.d;
- goto out_float;
+ return (union interp_ret){.f = i.d};
DISPATCH();
#undef DISPATCH
#undef JUMP
#undef DO
-out_float:
- return (union interp_ret){.f = retval_f};
-
-out_int:
- return (union interp_ret){.i = retval};
-
-zero_out:
return (union interp_ret){.i = 0};
}
diff --git a/tests/maxr_d.c b/tests/maxr_d.c
new file mode 100644
index 0000000..3e35665
--- /dev/null
+++ b/tests/maxr_d.c
@@ -0,0 +1,28 @@
+#include <ejit/ejit.h>
+#include <assert.h>
+#include "do_jit.h"
+
+int main(int argc, char *argv[])
+{
+ (void)argv;
+ bool do_jit = argc > 1;
+ struct ejit_operand operands[2] = {
+ EJIT_OPERAND_FPR(0, EJIT_TYPE(double)),
+ EJIT_OPERAND_FPR(1, EJIT_TYPE(double))
+ };
+
+ struct ejit_func *f = ejit_create_func(EJIT_TYPE(double), 2, operands);
+
+ ejit_maxr_d(f, EJIT_FPR(2), EJIT_FPR(0), EJIT_FPR(1));
+ ejit_retr_d(f, EJIT_FPR(2));
+
+ ejit_select_compile_func(f, 0, 3, EJIT_USE64(double), do_jit, true);
+
+ assert(erfd2(f, EJIT_ARG(42., double), EJIT_ARG(69., double)
+ ) == 69.);
+
+ assert(erfd2(f, EJIT_ARG(-42., double), EJIT_ARG(-69., double)
+ ) == -42.);
+
+ ejit_destroy_func(f);
+}
diff --git a/tests/maxr_f.c b/tests/maxr_f.c
new file mode 100644
index 0000000..581f867
--- /dev/null
+++ b/tests/maxr_f.c
@@ -0,0 +1,28 @@
+#include <ejit/ejit.h>
+#include <assert.h>
+#include "do_jit.h"
+
+int main(int argc, char *argv[])
+{
+ (void)argv;
+ bool do_jit = argc > 1;
+ struct ejit_operand operands[2] = {
+ EJIT_OPERAND_FPR(0, EJIT_TYPE(float)),
+ EJIT_OPERAND_FPR(1, EJIT_TYPE(float))
+ };
+
+ struct ejit_func *f = ejit_create_func(EJIT_TYPE(float), 2, operands);
+
+ ejit_maxr_f(f, EJIT_FPR(2), EJIT_FPR(0), EJIT_FPR(1));
+ ejit_retr_f(f, EJIT_FPR(2));
+
+ ejit_select_compile_func(f, 0, 3, EJIT_USE64(float), do_jit, true);
+
+ assert(erff2(f, EJIT_ARG(42., float), EJIT_ARG(69., float)
+ ) == 69.);
+
+ assert(erff2(f, EJIT_ARG(-42., float), EJIT_ARG(-69., float)
+ ) == -42.);
+
+ ejit_destroy_func(f);
+}
diff --git a/tests/minr_d.c b/tests/minr_d.c
new file mode 100644
index 0000000..d0fb7c8
--- /dev/null
+++ b/tests/minr_d.c
@@ -0,0 +1,28 @@
+#include <ejit/ejit.h>
+#include <assert.h>
+#include "do_jit.h"
+
+int main(int argc, char *argv[])
+{
+ (void)argv;
+ bool do_jit = argc > 1;
+ struct ejit_operand operands[2] = {
+ EJIT_OPERAND_FPR(0, EJIT_TYPE(double)),
+ EJIT_OPERAND_FPR(1, EJIT_TYPE(double))
+ };
+
+ struct ejit_func *f = ejit_create_func(EJIT_TYPE(double), 2, operands);
+
+ ejit_minr_d(f, EJIT_FPR(2), EJIT_FPR(0), EJIT_FPR(1));
+ ejit_retr_d(f, EJIT_FPR(2));
+
+ ejit_select_compile_func(f, 0, 3, EJIT_USE64(double), do_jit, true);
+
+ assert(erfd2(f, EJIT_ARG(42., double), EJIT_ARG(69., double)
+ ) == 42.);
+
+ assert(erfd2(f, EJIT_ARG(-42., double), EJIT_ARG(-69., double)
+ ) == -69.);
+
+ ejit_destroy_func(f);
+}
diff --git a/tests/minr_f.c b/tests/minr_f.c
new file mode 100644
index 0000000..b02ec06
--- /dev/null
+++ b/tests/minr_f.c
@@ -0,0 +1,28 @@
+#include <ejit/ejit.h>
+#include <assert.h>
+#include "do_jit.h"
+
+int main(int argc, char *argv[])
+{
+ (void)argv;
+ bool do_jit = argc > 1;
+ struct ejit_operand operands[2] = {
+ EJIT_OPERAND_FPR(0, EJIT_TYPE(float)),
+ EJIT_OPERAND_FPR(1, EJIT_TYPE(float))
+ };
+
+ struct ejit_func *f = ejit_create_func(EJIT_TYPE(float), 2, operands);
+
+ ejit_minr_f(f, EJIT_FPR(2), EJIT_FPR(0), EJIT_FPR(1));
+ ejit_retr_f(f, EJIT_FPR(2));
+
+ ejit_select_compile_func(f, 0, 3, EJIT_USE64(float), do_jit, true);
+
+ assert(erff2(f, EJIT_ARG(42., float), EJIT_ARG(69., float)
+ ) == 42.);
+
+ assert(erff2(f, EJIT_ARG(-42., float), EJIT_ARG(-69., float)
+ ) == -69.);
+
+ ejit_destroy_func(f);
+}