aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorKimplul <kimi.h.kuparinen@gmail.com>2025-04-10 22:23:08 +0300
committerKimplul <kimi.h.kuparinen@gmail.com>2025-04-10 22:23:08 +0300
commit7628ce2432108ae6306457f242e7cc3ac75b9ac0 (patch)
tree32a7b59f0e91b4c82bdeb4de3f75c1a04cc247da
parent0ba52d9043985baff61d4fae225420274d9ad9ab (diff)
parent531d307d310881e69efc8ae8c8119f5f5799e0f9 (diff)
downloadejit-7628ce2432108ae6306457f242e7cc3ac75b9ac0.tar.gz
ejit-7628ce2432108ae6306457f242e7cc3ac75b9ac0.zip
Merge branch 'tail'HEADmaster
-rw-r--r--.gitignore1
-rw-r--r--Makefile127
m---------deps/lightening0
-rw-r--r--examples/fib.c4
-rw-r--r--examples/sum.c78
-rw-r--r--include/ejit/ejit.h196
-rwxr-xr-xscripts/gen-tests4
-rw-r--r--scripts/makefile24
-rwxr-xr-xscripts/select-compile5
-rw-r--r--src/common.h444
-rw-r--r--src/compile/compile.c1115
-rw-r--r--src/ejit.c706
-rw-r--r--src/interp.c657
-rw-r--r--tests/calli.c41
-rw-r--r--tests/callr_i.c42
-rw-r--r--tests/escapei_10.c30
-rw-r--r--tests/escapei_double.c6
-rw-r--r--tests/escapei_float.c6
-rw-r--r--tests/escapei_immediate_10.c63
-rw-r--r--tests/makefile44
-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
-rw-r--r--tests/sqrtr_d.c23
-rw-r--r--tests/sqrtr_f.c23
-rw-r--r--tests/taili.c39
-rw-r--r--tests/tailr.c41
28 files changed, 2588 insertions, 1243 deletions
diff --git a/.gitignore b/.gitignore
index 93b2293..50343e4 100644
--- a/.gitignore
+++ b/.gitignore
@@ -7,4 +7,5 @@ test-*
examples/matrix_mult
examples/loop
examples/fib
+examples/sum
examples/*.d
diff --git a/Makefile b/Makefile
index 133d796..548e5b8 100644
--- a/Makefile
+++ b/Makefile
@@ -12,16 +12,121 @@ check: all
@./scripts/gen-tests $$(echo tests/*.c)
$(MAKE) -f tests/makefile check
-# this kicks all unrecognised targets to the client script.
-# note that trying to compile individual files, e.g.
-#
-# make kernel.elf
-#
-# will not work, you would need
-#
-# make -f scripts/makefile kernel.elf
-#
-# instead
+# supported by jit
+.PHONY: check_linux_amd64
+check_linux_amd64:
+ $(MAKE) clean
+ QEMU_LD_PREFIX=/usr/x86_64-linux-gnu \
+ $(MAKE) ARCH=amd64 CROSS_COMPILE=x86_64-linux-gnu- check
+
+.PHONY: check_linux_x86
+check_linux_x86:
+ $(MAKE) clean
+ QEMU_LD_PREFIX=/usr/i686-linux-gnu \
+ $(MAKE) ARCH=x86 CROSS_COMPILE=i686-linux-gnu- check
+
+.PHONY: check_linux_aarch64
+check_linux_aarch64:
+ $(MAKE) clean
+ QEMU_LD_PREFIX=/usr/aarch64-linux-gnu \
+ $(MAKE) ARCH=aarch64 CROSS_COMPILE=aarch64-linux-gnu- check
+
+.PHONY: check_linux_armhf
+check_linux_armhf:
+ $(MAKE) clean
+ QEMU_LD_PREFIX=/usr/arm-linux-gnueabihf \
+ $(MAKE) ARCH=armhf CROSS_COMPILE=arm-linux-gnueabihf- check
+
+.PHONY: check_linux_powerpc64le
+check_linux_powerpc64le:
+ $(MAKE) clean
+ QEMU_LD_PREFIX=/usr/powerpc64le-linux-gnu \
+ $(MAKE) ARCH=powerpc64le CROSS_COMPILE=powerpc64le-linux-gnu- check
+
+# note: older than revision 6
+.PHONY: check_linux_mips64el
+check_linux_mips64el:
+ $(MAKE) clean
+ QEMU_LD_PREFIX=/usr/mips64el-linux-gnuabi64 \
+ $(MAKE) ARCH=mips64el CROSS_COMPILE=mips64el-linux-gnuabi64- check
+
+.PHONY: check_linux_mipsel
+check_linux_mipsel:
+ $(MAKE) clean
+ QEMU_LD_PREFIX=/usr/mipsel-linux-gnu \
+ $(MAKE) ARCH=mipsel CROSS_COMPILE=mipsel-linux-gnu- check
+
+# not supported by jit atm
+.PHONY: check_linux_powerpc64
+check_linux_powerpc64:
+ $(MAKE) clean
+ QEMU_LD_PREFIX=/usr/powerpc64-linux-gnu \
+ $(MAKE) ARCH=powerpc64 CROSS_COMPILE=powerpc64-linux-gnu- check
+
+.PHONY: check_linux_powerpc
+check_linux_powerpc:
+ $(MAKE) clean
+ QEMU_LD_PREFIX=/usr/powerpc-linux-gnu \
+ $(MAKE) ARCH=powerpc CROSS_COMPILE=powerpc-linux-gnu- check
+
+.PHONY: check_linux_sparc64
+check_linux_sparc64:
+ $(MAKE) clean
+ QEMU_LD_PREFIX=/usr/sparc64-linux-gnu \
+ $(MAKE) ARCH=sparc64 CROSS_COMPILE=sparc64-linux-gnu- check
+
+.PHONY: check_linux_riscv64
+check_linux_riscv64:
+ $(MAKE) clean
+ QEMU_LD_PREFIX=/usr/riscv64-linux-gnu \
+ $(MAKE) ARCH=riscv64 CROSS_COMPILE=riscv64-linux-gnu- check
+
+.PHONY: check_linux_s390x
+check_linux_s390x:
+ $(MAKE) clean
+ QEMU_LD_PREFIX=/usr/s390x-linux-gnu \
+ $(MAKE) ARCH=s390x CROSS_COMPILE=s390x-linux-gnu- check
+
+.PHONY: check_linux_alpha
+check_linux_alpha:
+ $(MAKE) clean
+ QEMU_LD_PREFIX=/usr/alpha-linux-gnu \
+ $(MAKE) ARCH=alpha CROSS_COMPILE=alpha-linux-gnu- check
+
+.PHONY: check_linux_hppa
+check_linux_hppa:
+ $(MAKE) clean
+ QEMU_LD_PREFIX=/usr/hppa-linux-gnu \
+ $(MAKE) ARCH=hppa CROSS_COMPILE=hppa-linux-gnu- check
+
+.PHONY: check_linux_m68k
+check_linux_m68k:
+ $(MAKE) clean
+ QEMU_LD_PREFIX=/usr/m68k-linux-gnu \
+ $(MAKE) ARCH=m68k CROSS_COMPILE=m68k-linux-gnu- check
+
+.PHONY: check_linux
+check_linux:
+ $(MAKE) check_linux_amd64
+ $(MAKE) check_linux_x86
+ $(MAKE) check_linux_aarch64
+ $(MAKE) check_linux_armhf
+ $(MAKE) check_linux_powerpc64le
+ $(MAKE) check_linux_mips64el
+ $(MAKE) check_linux_mipsel
+ $(MAKE) check_linux_powerpc64
+ $(MAKE) check_linux_powerpc
+ $(MAKE) check_linux_sparc64
+ $(MAKE) check_linux_riscv64
+ $(MAKE) check_linux_s390x
+ $(MAKE) check_linux_alpha
+ $(MAKE) check_linux_hppa
+ $(MAKE) check_linux_m68k
+ # compiler+emulator not available or broken
+ #$(MAKE) check_linux_hppa64
+ #$(MAKE) check_linux_arc
+ #$(MAKE) check_linux_sh4
+
.DEFAULT: setup
$(MAKE) -f scripts/makefile $<
@@ -30,7 +135,7 @@ setup:
@echo -n > deps.mk
@./scripts/gen-deps -p EJIT -c COMPILE_EJIT -b ejit "$(EJIT_SOURCES)"
-CLEANUP := build deps.mk tests.md ejit.o examples/fib examples/loop \
+CLEANUP := build deps.mk tests.md libejit.a examples/fib examples/loop \
examples/*.d tests/test-*
CLEANUP_CMD :=
EJIT_SOURCES :=
diff --git a/deps/lightening b/deps/lightening
-Subproject 1cc7a2d159d8cbfc46708d24bfe49f6c23c6e44
+Subproject 3f4127c3ef16177be55cf6153a206ca4f8a4859
diff --git a/examples/fib.c b/examples/fib.c
index 999546b..fcb0659 100644
--- a/examples/fib.c
+++ b/examples/fib.c
@@ -20,12 +20,12 @@ struct ejit_func *compile(bool try_jit, bool im_scawed)
struct ejit_operand arg[1] = {
EJIT_OPERAND_GPR(0, EJIT_INT32)
};
- ejit_calli_i(f, f, 1, arg);
+ ejit_calli(f, f, 1, arg);
ejit_retval(f, EJIT_GPR(1)); /* loc 1 contains temp result */
/* fib(n - 2) */
ejit_subi(f, EJIT_GPR(0), EJIT_GPR(0), 1);
- ejit_calli_i(f, f, 1, arg);
+ ejit_calli(f, f, 1, arg);
ejit_retval(f, EJIT_GPR(0)); /* loc 0 now contains second temp result */
ejit_addr(f, EJIT_GPR(0), EJIT_GPR(0), EJIT_GPR(1)); /* add results */
diff --git a/examples/sum.c b/examples/sum.c
new file mode 100644
index 0000000..cc8f54b
--- /dev/null
+++ b/examples/sum.c
@@ -0,0 +1,78 @@
+#include <stdio.h>
+#include <time.h>
+
+#include "../include/ejit/ejit.h"
+
+struct ejit_func *compile(bool try_jit, bool im_scawed)
+{
+ struct ejit_operand params[2] = {
+ EJIT_OPERAND_GPR(0, EJIT_INT32), /* loc 0 contains s */
+ EJIT_OPERAND_GPR(1, EJIT_INT32) /* loc 1 contains n */
+ };
+ struct ejit_func *f = ejit_create_func(EJIT_INT32, 2, params);
+
+ /* n == 0, return s */
+ struct ejit_reloc recurse = ejit_bnei(f, EJIT_GPR(1), 0);
+ ejit_retr(f, EJIT_GPR(0));
+ ejit_patch(f, recurse, ejit_label(f));
+
+ /* s += n */
+ ejit_addr(f, EJIT_GPR(0), EJIT_GPR(0), EJIT_GPR(1));
+
+ /* n -= 1 */
+ ejit_subi(f, EJIT_GPR(1), EJIT_GPR(1), 1);
+
+ struct ejit_operand args[2] = {
+ EJIT_OPERAND_GPR(0, EJIT_INT32), /* s */
+ EJIT_OPERAND_GPR(1, EJIT_INT32) /* n */
+ };
+
+ /* recurse */
+ ejit_movi(f, EJIT_GPR(2), (uintptr_t)f);
+ ejit_tailr(f, EJIT_GPR(2), 2, args);
+
+ ejit_select_compile_func(f, 3, 0, EJIT_USE64(uintptr_t), try_jit, im_scawed);
+ return f;
+}
+
+int main(int argc, char *argv[])
+{
+ if(argc != 4){
+ fprintf(stderr, "Usage: %s compile_num loop_num jit\n", argv[0]);
+ return -1;
+ }
+
+ int jit_level = strtoull(argv[3], 0, 0);
+ size_t compile_num = strtoull(argv[1], 0, 0);
+ struct ejit_func **info = calloc(compile_num, sizeof(struct ejit_func *));
+
+ clock_t t = clock();
+ for(size_t i = 0; i < compile_num; ++i){
+ info[i] = compile(jit_level > 0, jit_level > 1);
+ }
+ t = clock() - t;
+
+ double compile_time_total = ((double)t) / CLOCKS_PER_SEC;
+ double compile_time_one = compile_time_total / compile_num;
+ printf("Compilation for n = %zu took %fs (1/%f).\n",
+ compile_num, compile_time_total, compile_time_one);
+
+ size_t run_num = strtoull(argv[2], 0, 0);
+ t = clock();
+ struct ejit_arg args[2] = {
+ (struct ejit_arg){.type = EJIT_INT32, .l = 0}, /* s */
+ (struct ejit_arg){.type = EJIT_INT32, .l = run_num} /* n */
+ };
+ int32_t result = ejit_run_func_i(info[0], 2, args);
+ t = clock() - t;
+
+ double run_time_total = ((double)t) / CLOCKS_PER_SEC;
+ printf("Running loop for n = %zu took %fs with res %ld\n",
+ run_num, run_time_total, (long)result);
+
+ for(size_t i = 0; i < compile_num; ++i)
+ ejit_destroy_func(info[i]);
+
+ free(info);
+ return 0;
+}
diff --git a/include/ejit/ejit.h b/include/ejit/ejit.h
index 4ab2bbc..ab06d8f 100644
--- a/include/ejit/ejit.h
+++ b/include/ejit/ejit.h
@@ -72,29 +72,20 @@ static inline enum ejit_type ejit_signed_type(size_t w)
struct ejit_arg {
union {
- int8_t i8;
- uint8_t u8;
+ int8_t i8;
int16_t i16;
- uint16_t u16;
int32_t i32;
- uint32_t u32;
int64_t i64;
- uint64_t u64;
- signed char c;
- unsigned char uc;
- signed short s;
- unsigned short us;
- signed int i;
- unsigned int ui;
- signed long l;
- unsigned long ul;
- signed long long ll;
- unsigned long long ull;
+ uint8_t u8;
+ uint16_t u16;
+ uint32_t u32;
+ uint64_t u64;
float f;
double d;
void *p;
+ long l;
};
enum ejit_type type;
};
@@ -113,6 +104,7 @@ static inline bool ejit_int_type(enum ejit_type t)
case EJIT_POINTER:
return true;
default:
+ break;
}
return false;
@@ -125,6 +117,7 @@ static inline bool ejit_float_type(enum ejit_type t)
case EJIT_DOUBLE:
return true;
default:
+ break;
}
return false;
@@ -136,15 +129,15 @@ static inline struct ejit_arg ejit_build_arg(enum ejit_type type, uint64_t x)
a.type = type;
switch (type) {
- case EJIT_INT8: a.u64 = (int8_t)x; break;
- case EJIT_INT16: a.u64 = (int16_t)x; break;
- case EJIT_INT32: a.u64 = (int32_t)x; break;
- case EJIT_INT64: a.u64 = (int64_t)x; break;
- case EJIT_UINT8: a.u64 = (uint8_t)x; break;
- case EJIT_UINT16: a.u64 = (uint16_t)x; break;
- case EJIT_UINT32: a.u64 = (uint32_t)x; break;
- case EJIT_UINT64: a.u64 = (uint64_t)x; break;
- case EJIT_POINTER: a.p = (void *)(uintptr_t)x; break;
+ case EJIT_INT8: a.i8 = (int8_t)x; break;
+ case EJIT_INT16: a.i16 = (int16_t)x; break;
+ case EJIT_INT32: a.i32 = (int32_t)x; break;
+ case EJIT_INT64: a.i64 = (int64_t)x; break;
+ case EJIT_UINT8: a.u8 = (uint8_t)x; break;
+ case EJIT_UINT16: a.u16 = (uint16_t)x; break;
+ case EJIT_UINT32: a.u32 = (uint32_t)x; break;
+ case EJIT_UINT64: a.u64 = (uint64_t)x; break;
+ case EJIT_POINTER: a.p = (void *)(uintptr_t)x; break;
default: abort();
}
@@ -157,7 +150,7 @@ static inline struct ejit_arg ejit_build_arg_f(enum ejit_type type, double x)
a.type = type;
switch (type) {
- case EJIT_FLOAT: a.f = x; break;
+ case EJIT_FLOAT: a.f = (float)x; break;
case EJIT_DOUBLE: a.d = x; break;
default: abort();
}
@@ -223,21 +216,6 @@ double ejit_run_func_d(struct ejit_func *f, size_t argc,
struct ejit_arg ejit_run_func(struct ejit_func *f, size_t argc, struct ejit_arg args[argc]);
-
-/* currently unused, the idea is that an escape could get the interpreter state
- * and pass it on to speed up entering/exiting the VM, could be useful for more
- * dynamic languages */
-struct interp_state;
-
-long ejit_run_func_ctx_i(struct ejit_func *f, size_t argc, struct ejit_arg args[argc], struct interp_state *ctx);
-
-int64_t ejit_run_func_ctx_l(struct ejit_func *f, size_t argc, struct ejit_arg args[argc], struct interp_state *ctx);
-
-float ejit_run_func_ctx_f(struct ejit_func *f, size_t argc, struct ejit_arg args[argc], struct interp_state *ctx);
-
-double ejit_run_func_ctx_d(struct ejit_func *f, size_t argc, struct ejit_arg args[argc], struct interp_state *ctx);
-
-
void ejit_destroy_func(struct ejit_func *s);
#define EJIT_GPR(x) ((struct ejit_gpr){.r = (x)})
@@ -260,23 +238,23 @@ void ejit_destroy_func(struct ejit_func *s);
.type = (t)})
#define EJIT_OPERAND_FLT(x, t) \
((struct ejit_operand){ .kind = EJIT_OPERAND_FLT, \
- .r = (double)(x), \
+ .d = (double)(x), \
.type = (t)})
/* maybe slight hack, but increase width to interpeter register width */
static inline struct ejit_arg ejit_i8(int8_t a)
{
- return (struct ejit_arg){.i64 = a, .type = EJIT_INT8};
+ return (struct ejit_arg){.i8 = a, .type = EJIT_INT8};
}
static inline struct ejit_arg ejit_i16(int16_t a)
{
- return (struct ejit_arg){.i64 = a, .type = EJIT_INT16};
+ return (struct ejit_arg){.i16 = a, .type = EJIT_INT16};
}
static inline struct ejit_arg ejit_i32(int32_t a)
{
- return (struct ejit_arg){.i64 = a, .type = EJIT_INT32};
+ return (struct ejit_arg){.i32 = a, .type = EJIT_INT32};
}
static inline struct ejit_arg ejit_i64(int64_t a)
@@ -286,22 +264,22 @@ static inline struct ejit_arg ejit_i64(int64_t a)
static inline struct ejit_arg ejit_u8(uint8_t a)
{
- return (struct ejit_arg){.i64 = a, .type = EJIT_UINT8};
+ return (struct ejit_arg){.u8 = a, .type = EJIT_UINT8};
}
static inline struct ejit_arg ejit_u16(uint16_t a)
{
- return (struct ejit_arg){.i64 = a, .type = EJIT_UINT16};
+ return (struct ejit_arg){.u16 = a, .type = EJIT_UINT16};
}
static inline struct ejit_arg ejit_u32(uint32_t a)
{
- return (struct ejit_arg){.i64 = a, .type = EJIT_UINT32};
+ return (struct ejit_arg){.u32 = a, .type = EJIT_UINT32};
}
static inline struct ejit_arg ejit_u64(uint64_t a)
{
- return (struct ejit_arg){.i64 = a, .type = EJIT_UINT64};
+ return (struct ejit_arg){.u64 = a, .type = EJIT_UINT64};
}
static inline struct ejit_arg ejit_pointer(void *p)
@@ -387,6 +365,77 @@ static inline struct ejit_arg ejit_pointer_arg(void *p, size_t w)
#define EJIT_AUTO(x) \
EJIT_ARG(x, typeof(x))
+static inline int64_t ejit_signed_param(size_t argc, const struct ejit_arg args[argc],
+ size_t idx, enum ejit_type type)
+{
+ assert(idx < argc);
+ assert(args[idx].type == type);
+ switch (type) {
+ case EJIT_INT64: return args[idx].i64;
+ case EJIT_INT32: return args[idx].i32;
+ case EJIT_INT16: return args[idx].i16;
+ case EJIT_INT8: return args[idx].i8;
+ default: abort();
+ }
+
+ return 0;
+}
+
+static inline uint64_t ejit_unsigned_param(size_t argc, const struct ejit_arg args[argc],
+ size_t idx, enum ejit_type type)
+{
+ assert(idx < argc);
+ assert(args[idx].type == type);
+ switch (type) {
+ case EJIT_UINT64: return args[idx].u64;
+ case EJIT_UINT32: return args[idx].u32;
+ case EJIT_UINT16: return args[idx].u16;
+ case EJIT_UINT8: return args[idx].u8;
+ default: abort();
+ }
+}
+
+static inline float ejit_float_param(size_t argc, const struct ejit_arg args[argc],
+ size_t idx, enum ejit_type type)
+{
+ assert(idx < argc);
+ assert(args[idx].type == type && type == EJIT_FLOAT);
+ return args[idx].f;
+}
+
+static inline double ejit_double_param(size_t argc, const struct ejit_arg args[argc],
+ size_t idx, enum ejit_type type)
+{
+ assert(idx < argc);
+ assert(args[idx].type == type && type == EJIT_DOUBLE);
+ return args[idx].d;
+}
+
+static inline void *ejit_pointer_param(size_t argc, const struct ejit_arg args[argc],
+ size_t idx, enum ejit_type type)
+{
+ assert(idx < argc);
+ assert(args[idx].type == type && type == EJIT_POINTER);
+ return args[idx].p;
+}
+
+#define EJIT_PARAM(argc, args, idx, t) \
+ _Generic((t)(0), \
+ signed char : ejit_signed_param, \
+ signed short : ejit_signed_param, \
+ signed int : ejit_signed_param, \
+ signed long : ejit_signed_param, \
+ signed long long : ejit_signed_param, \
+ unsigned char : ejit_unsigned_param, \
+ unsigned short : ejit_unsigned_param, \
+ unsigned int : ejit_unsigned_param, \
+ unsigned long : ejit_unsigned_param, \
+ unsigned long long: ejit_unsigned_param, \
+ float : ejit_float_param, \
+ double : ejit_double_param, \
+ default : ejit_pointer_param \
+ )(argc, args, idx, EJIT_TYPE(t))
+
static inline bool ejit_use64(struct ejit_arg a)
{
if (a.type == EJIT_INT64 || a.type == EJIT_UINT64)
@@ -405,29 +454,39 @@ typedef double (*ejit_escape_d_t)(size_t argc, const struct ejit_arg args[argc])
struct ejit_label ejit_label(struct ejit_func *s);
-void ejit_calli_i(struct ejit_func *s, struct ejit_func *f, size_t argc,
- const struct ejit_operand args[argc]);
+void ejit_tailr(struct ejit_func *s, struct ejit_gpr target,
+ size_t argc, const struct ejit_operand args[argc]);
+
+void ejit_taili(struct ejit_func *s, struct ejit_func *f,
+ size_t argc, const struct ejit_operand args[argc]);
-void ejit_calli_l(struct ejit_func *s, struct ejit_func *f, size_t argc,
- const struct ejit_operand args[argc]);
+/* return type can be deduced */
+void ejit_calli(struct ejit_func *s, struct ejit_func *f,
+ size_t argc, const struct ejit_operand args[argc]);
-void ejit_calli_f(struct ejit_func *s, struct ejit_func *f, size_t argc,
- const struct ejit_operand args[argc]);
+void ejit_callr_i(struct ejit_func *s, struct ejit_gpr target,
+ size_t argc, const struct ejit_operand args[argc]);
-void ejit_calli_d(struct ejit_func *s, struct ejit_func *f, size_t argc,
- const struct ejit_operand args[argc]);
+void ejit_callr_l(struct ejit_func *s, struct ejit_gpr target,
+ size_t argc, const struct ejit_operand args[argc]);
-void ejit_escapei_i(struct ejit_func *s, ejit_escape_i_t f, size_t argc,
- const struct ejit_operand args[argc]);
+void ejit_callr_f(struct ejit_func *s, struct ejit_gpr target,
+ size_t argc, const struct ejit_operand args[argc]);
-void ejit_escapei_l(struct ejit_func *s, ejit_escape_l_t f, size_t argc,
- const struct ejit_operand args[argc]);
+void ejit_callr_d(struct ejit_func *s, struct ejit_gpr target,
+ size_t argc, const struct ejit_operand args[argc]);
-void ejit_escapei_f(struct ejit_func *s, ejit_escape_f_t f, size_t argc,
- const struct ejit_operand args[argc]);
+void ejit_escapei_i(struct ejit_func *s, ejit_escape_i_t f,
+ size_t argc, const struct ejit_operand args[argc]);
-void ejit_escapei_d(struct ejit_func *s, ejit_escape_d_t f, size_t argc,
- const struct ejit_operand args[argc]);
+void ejit_escapei_l(struct ejit_func *s, ejit_escape_l_t f,
+ size_t argc, const struct ejit_operand args[argc]);
+
+void ejit_escapei_f(struct ejit_func *s, ejit_escape_f_t f,
+ size_t argc, const struct ejit_operand args[argc]);
+
+void ejit_escapei_d(struct ejit_func *s, ejit_escape_d_t f,
+ size_t argc, const struct ejit_operand args[argc]);
void ejit_ret(struct ejit_func *s);
void ejit_retr(struct ejit_func *s, struct ejit_gpr r0);
@@ -820,6 +879,15 @@ void ejit_truncr_d_32(struct ejit_func *s, struct ejit_gpr r0,
void ejit_truncr_d_64(struct ejit_func *s, struct ejit_gpr r0,
struct ejit_fpr r1);
+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/gen-tests b/scripts/gen-tests
index 5521006..47ff9c9 100755
--- a/scripts/gen-tests
+++ b/scripts/gen-tests
@@ -11,5 +11,7 @@ do
echo "${dep}:" >> tests.mk
echo "-include ${dep}" >> tests.mk
echo "${exe}: ${s} libejit.a" >> tests.mk
- echo " \$(COMPILE_TEST) ${s} libejit.a -o ${exe}" >> tests.mk
+ echo " \$(COMPILE_TEST) ${s} libejit.a -o ${exe} -lm" >> tests.mk
+ echo " ./${exe} \t# bytecode" >> tests.mk
+ echo " ./${exe} 1\t# jit" >> tests.mk
done
diff --git a/scripts/makefile b/scripts/makefile
index 3a4f200..dbb7a1c 100644
--- a/scripts/makefile
+++ b/scripts/makefile
@@ -29,16 +29,21 @@ OBJCOPY != [ "$(LLVM)" != "0" ] \
&& echo llvm-objcopy \
|| echo $(CROSS_COMPILE)objcopy
-COMPILER != [ "$(LLVM)" != "0" ] \
- && echo clang --target="$(CROSS_COMPILE)" \
- || echo $(CROSS_COMPILE)gcc
+COMPILER != [ -n "$(CROSS_COMPILE)" ] \
+ && { \
+ [ "$(LLVM)" != "0" ] \
+ && echo clang --target="$(CROSS_COMPILE)" \
+ || echo $(CROSS_COMPILE)gcc \
+ ; \
+ } \
+ || echo $(CC)
OBFLAGS := -g
WARNFLAGS := -Wall -Wextra
COMPILE_FLAGS := $(CFLAGS) $(WARNFLAGS) $(OPTFLAGS) $(LTOFLAGS) \
- $(OBFLAGS) $(ASSERTFLAGS) $(DEBUGFLAGS)
+ $(OBFLAGS) $(DEBUGFLAGS)
INCLUDE_FLAGS := -I include
@@ -60,16 +65,19 @@ COMPILE_EJIT = $(COMPILE) $(EJIT_FLAGS)
libejit.a: $(EJIT_OBJS)
$(CROSS_COMPILE)ar rcs libejit.a $(EJIT_OBJS)
-examples: examples/loop examples/fib examples/matrix_mult
+examples: examples/loop examples/fib examples/sum 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
+
+examples/sum: examples/sum.c libejit.a
+ $(COMPILE_EJIT) examples/sum.c libejit.a -o $@ -lm
# might lint some common things twice
.PHONY:
diff --git a/scripts/select-compile b/scripts/select-compile
index fca7350..37c67a1 100755
--- a/scripts/select-compile
+++ b/scripts/select-compile
@@ -9,6 +9,11 @@ JIT="src/compile/compile.c"
NOJIT="src/compile/nocompile.c"
case "$ARCH" in
+ powerpc64le) echo "$JIT" ;;
+ 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 6ee0df7..dc970f0 100644
--- a/src/common.h
+++ b/src/common.h
@@ -21,214 +21,227 @@
#include "vec.h"
enum ejit_opcode {
- MOVI,
- MOVI_F,
- MOVI_D,
- MOVR,
- MOVR_F,
- MOVR_D,
-
- LDI8,
- LDI16,
- LDI32,
- LDI64,
- LDIU8,
- LDIU16,
- LDIU32,
- LDIU64,
- LDIF,
- LDID,
-
- LDXI8,
- LDXI16,
- LDXI32,
- LDXI64,
- LDXIU8,
- LDXIU16,
- LDXIU32,
- LDXIU64,
- LDXIF,
- LDXID,
-
- LDXR8,
- LDXR16,
- LDXR32,
- LDXR64,
- LDXRU8,
- LDXRU16,
- LDXRU32,
- LDXRU64,
- LDXRF,
- LDXRD,
-
- STI8,
- STI16,
- STI32,
- STI64,
- STIF,
- STID,
-
- STXI8,
- STXI16,
- STXI32,
- STXI64,
- STXIF,
- STXID,
-
- STXR8,
- STXR16,
- STXR32,
- STXR64,
- STXRF,
- STXRD,
-
- EXTR8,
- EXTR16,
- EXTR32,
- EXTRU8,
- EXTRU16,
- EXTRU32,
- EXTRF,
- EXTRD,
-
- ADDR,
- ADDR_F,
- ADDR_D,
- ADDI,
-
- ABSR_F,
- ABSR_D,
-
- SUBR,
- SUBR_F,
- SUBR_D,
- SUBI,
-
- MULR,
- MULR_F,
- MULR_D,
-
- DIVR,
- DIVR_U,
- DIVR_F,
- DIVR_D,
-
- REMR,
- REMR_U,
-
- COMR,
- NEGR,
- NEGR_F,
- NEGR_D,
-
- LSHI,
- LSHR,
- RSHI,
- RSHI_U,
- RSHR,
- RSHR_U,
-
- ANDR,
- ANDI,
-
- ORR,
- ORI,
-
- XORR,
- XORI,
-
- TRUNCR_D_32,
- TRUNCR_D_64,
- TRUNCR_F_32,
- TRUNCR_F_64,
-
- EQR,
- NER,
- GTR,
- GTR_U,
- GER,
- GER_U,
-
- EQR_F,
- NER_F,
- GTR_F,
- GER_F,
- EQR_D,
- NER_D,
- GTR_D,
- GER_D,
-
- BNER,
- BNEI,
- BNER_F,
- BNER_D,
-
- BEQR,
- BEQI,
- BEQR_F,
- BEQR_D,
-
- BGER,
- BGER_U,
- BGEI,
- BGEI_U,
- BGER_F,
- BGER_D,
-
- BLEI,
- BLEI_U,
-
- BGTR,
- BGTR_U,
- BGTI,
- BGTI_U,
- BGTR_F,
- BGTR_D,
-
- BLTI,
- BLTI_U,
-
- JMP,
- JMPR,
-
- BMCI,
- BMCR,
- BMSI,
- BMSR,
-
- PARAM,
- PARAM_F,
-
- ARG,
- ARG_I,
- ARG_F,
- ARG_FI,
-
- ESCAPEI_I,
- ESCAPEI_L,
- ESCAPEI_F,
- ESCAPEI_D,
-
- CALLI_I,
- CALLI_L,
- CALLI_F,
- CALLI_D,
-
- RETR,
- RETI,
- RETR_F,
- RETR_D,
- RETI_F,
- RETI_D,
-
- RETVAL,
- RETVAL_F,
- RETVAL_D,
-
- START,
- END,
-
- OPCODE_COUNT,
+ EJIT_OP_MOVI,
+ EJIT_OP_MOVI_F,
+ EJIT_OP_MOVI_D,
+ EJIT_OP_MOVR,
+ EJIT_OP_MOVR_F,
+ EJIT_OP_MOVR_D,
+
+ EJIT_OP_LDI8,
+ EJIT_OP_LDI16,
+ EJIT_OP_LDI32,
+ EJIT_OP_LDI64,
+ EJIT_OP_LDIU8,
+ EJIT_OP_LDIU16,
+ EJIT_OP_LDIU32,
+ EJIT_OP_LDIU64,
+ EJIT_OP_LDIF,
+ EJIT_OP_LDID,
+
+ EJIT_OP_LDXI8,
+ EJIT_OP_LDXI16,
+ EJIT_OP_LDXI32,
+ EJIT_OP_LDXI64,
+ EJIT_OP_LDXIU8,
+ EJIT_OP_LDXIU16,
+ EJIT_OP_LDXIU32,
+ EJIT_OP_LDXIU64,
+ EJIT_OP_LDXIF,
+ EJIT_OP_LDXID,
+
+ EJIT_OP_LDXR8,
+ EJIT_OP_LDXR16,
+ EJIT_OP_LDXR32,
+ EJIT_OP_LDXR64,
+ EJIT_OP_LDXRU8,
+ EJIT_OP_LDXRU16,
+ EJIT_OP_LDXRU32,
+ EJIT_OP_LDXRU64,
+ EJIT_OP_LDXRF,
+ EJIT_OP_LDXRD,
+
+ EJIT_OP_STI8,
+ EJIT_OP_STI16,
+ EJIT_OP_STI32,
+ EJIT_OP_STI64,
+ EJIT_OP_STIF,
+ EJIT_OP_STID,
+
+ EJIT_OP_STXI8,
+ EJIT_OP_STXI16,
+ EJIT_OP_STXI32,
+ EJIT_OP_STXI64,
+ EJIT_OP_STXIF,
+ EJIT_OP_STXID,
+
+ EJIT_OP_STXR8,
+ EJIT_OP_STXR16,
+ EJIT_OP_STXR32,
+ EJIT_OP_STXR64,
+ EJIT_OP_STXRF,
+ EJIT_OP_STXRD,
+
+ EJIT_OP_EXTR8,
+ EJIT_OP_EXTR16,
+ EJIT_OP_EXTR32,
+ EJIT_OP_EXTRU8,
+ EJIT_OP_EXTRU16,
+ EJIT_OP_EXTRU32,
+ EJIT_OP_EXTRF,
+ EJIT_OP_EXTRD,
+
+ EJIT_OP_ADDR,
+ EJIT_OP_ADDR_F,
+ EJIT_OP_ADDR_D,
+ EJIT_OP_ADDI,
+
+ EJIT_OP_ABSR_F,
+ EJIT_OP_ABSR_D,
+
+ EJIT_OP_SUBR,
+ EJIT_OP_SUBR_F,
+ EJIT_OP_SUBR_D,
+ EJIT_OP_SUBI,
+
+ EJIT_OP_MULR,
+ EJIT_OP_MULR_F,
+ EJIT_OP_MULR_D,
+
+ EJIT_OP_DIVR,
+ EJIT_OP_DIVR_U,
+ EJIT_OP_DIVR_F,
+ EJIT_OP_DIVR_D,
+
+ EJIT_OP_REMR,
+ EJIT_OP_REMR_U,
+
+ EJIT_OP_COMR,
+ EJIT_OP_NEGR,
+ EJIT_OP_NEGR_F,
+ EJIT_OP_NEGR_D,
+
+ EJIT_OP_LSHI,
+ EJIT_OP_LSHR,
+ EJIT_OP_RSHI,
+ EJIT_OP_RSHI_U,
+ EJIT_OP_RSHR,
+ EJIT_OP_RSHR_U,
+
+ EJIT_OP_ANDR,
+ EJIT_OP_ANDI,
+
+ EJIT_OP_ORR,
+ EJIT_OP_ORI,
+
+ EJIT_OP_XORR,
+ EJIT_OP_XORI,
+
+ EJIT_OP_TRUNCR_D_32,
+ EJIT_OP_TRUNCR_D_64,
+ EJIT_OP_TRUNCR_F_32,
+ EJIT_OP_TRUNCR_F_64,
+
+ 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,
+ EJIT_OP_GTR_U,
+ EJIT_OP_GER,
+ EJIT_OP_GER_U,
+
+ EJIT_OP_EQR_F,
+ EJIT_OP_NER_F,
+ EJIT_OP_GTR_F,
+ EJIT_OP_GER_F,
+ EJIT_OP_EQR_D,
+ EJIT_OP_NER_D,
+ EJIT_OP_GTR_D,
+ EJIT_OP_GER_D,
+
+ EJIT_OP_BNER,
+ EJIT_OP_BNEI,
+ EJIT_OP_BNER_F,
+ EJIT_OP_BNER_D,
+
+ EJIT_OP_BEQR,
+ EJIT_OP_BEQI,
+ EJIT_OP_BEQR_F,
+ EJIT_OP_BEQR_D,
+
+ EJIT_OP_BGER,
+ EJIT_OP_BGER_U,
+ EJIT_OP_BGEI,
+ EJIT_OP_BGEI_U,
+ EJIT_OP_BGER_F,
+ EJIT_OP_BGER_D,
+
+ EJIT_OP_BLEI,
+ EJIT_OP_BLEI_U,
+
+ EJIT_OP_BGTR,
+ EJIT_OP_BGTR_U,
+ EJIT_OP_BGTI,
+ EJIT_OP_BGTI_U,
+ EJIT_OP_BGTR_F,
+ EJIT_OP_BGTR_D,
+
+ EJIT_OP_BLTI,
+ EJIT_OP_BLTI_U,
+
+ EJIT_OP_JMP,
+ EJIT_OP_JMPR,
+
+ EJIT_OP_BMCI,
+ EJIT_OP_BMCR,
+ EJIT_OP_BMSI,
+ EJIT_OP_BMSR,
+
+ EJIT_OP_PARAM,
+ EJIT_OP_PARAM_F,
+
+ EJIT_OP_ARG,
+ EJIT_OP_ARG_I,
+ EJIT_OP_ARG_F,
+ EJIT_OP_ARG_FI,
+
+ EJIT_OP_ESCAPEI_I,
+ EJIT_OP_ESCAPEI_L,
+ EJIT_OP_ESCAPEI_F,
+ EJIT_OP_ESCAPEI_D,
+
+ EJIT_OP_CALLR_I,
+ EJIT_OP_CALLR_L,
+ EJIT_OP_CALLR_F,
+ EJIT_OP_CALLR_D,
+
+ EJIT_OP_CALLI,
+ EJIT_OP_TAILR,
+ EJIT_OP_TAILI,
+
+ EJIT_OP_RETR,
+ EJIT_OP_RETI,
+ EJIT_OP_RETR_F,
+ EJIT_OP_RETR_D,
+ EJIT_OP_RETI_F,
+ EJIT_OP_RETI_D,
+
+ EJIT_OP_RETVAL,
+ EJIT_OP_RETVAL_F,
+ EJIT_OP_RETVAL_D,
+
+ EJIT_OP_START,
+ EJIT_OP_END,
+
+ EJIT_OPCODE_COUNT,
};
struct ejit_insn {
@@ -258,7 +271,7 @@ struct ejit_insn {
struct fpr_stat {
struct ejit_fpr f;
- size_t prio, fno;
+ size_t prio, fno, start, end;
};
#define VEC_NAME fpr_stats
@@ -267,7 +280,7 @@ struct fpr_stat {
struct gpr_stat {
struct ejit_gpr r;
- size_t prio, rno;
+ size_t prio, rno, start, end;
};
#define VEC_NAME gpr_stats
@@ -286,15 +299,10 @@ struct ejit_func {
void *arena;
void *direct_call;
+ void *extern_call;
size_t size;
size_t prio;
-};
-
-
-struct interp_state {
- struct gprs gprs;
- struct fprs fprs;
- struct args args;
+ size_t max_args;
};
union interp_ret {
@@ -304,8 +312,6 @@ union interp_ret {
union interp_ret ejit_run(struct ejit_func *f, size_t argc,
struct ejit_arg args[argc],
- struct interp_state *state,
- bool run,
void ***labels_wb);
bool ejit_compile(struct ejit_func *f, bool use_64, bool im_scawed);
diff --git a/src/compile/compile.c b/src/compile/compile.c
index 490bc43..5432bc1 100644
--- a/src/compile/compile.c
+++ b/src/compile/compile.c
@@ -19,6 +19,27 @@ struct reloc_helper {
#define VEC_NAME addrs
#include "../vec.h"
+/* skip assertions since we know they must be valid due to type checking earlier */
+static long checked_run_i(struct ejit_func *f, size_t argc, struct ejit_arg args[argc])
+{
+ return ejit_run(f, argc, args, NULL).i;
+}
+
+static int64_t checked_run_l(struct ejit_func *f, size_t argc, struct ejit_arg args[argc])
+{
+ return ejit_run(f, argc, args, NULL).i;
+}
+
+static float checked_run_f(struct ejit_func *f, size_t argc, struct ejit_arg args[argc])
+{
+ return ejit_run(f, argc, args, NULL).f;
+}
+
+static double checked_run_d(struct ejit_func *f, size_t argc, struct ejit_arg args[argc])
+{
+ return ejit_run(f, argc, args, NULL).f;
+}
+
static void *alloc_arena(size_t size, bool im_scawed)
{
return mmap(NULL, size,
@@ -26,6 +47,24 @@ static void *alloc_arena(size_t size, bool im_scawed)
MAP_PRIVATE | MAP_ANONYMOUS, -1, 0);
}
+static void assert_helper(const char *msg)
+{
+ assert(false && msg);
+}
+
+static bool gpr_free(size_t argc, jit_operand_t args[argc], jit_gpr_t r)
+{
+ for (size_t i = 0; i < argc; ++i) {
+ if (args[i].kind != JIT_OPERAND_KIND_GPR)
+ continue;
+
+ if (jit_gpr_regno(args[i].loc.gpr.gpr) == jit_gpr_regno(r))
+ return false;
+ }
+
+ return true;
+}
+
static void free_arena(void *arena, size_t size)
{
munmap(arena, size);
@@ -545,7 +584,7 @@ static void compile_absr_d(struct ejit_func *f, jit_state_t *j,
{
jit_fpr_t r0 = getfpr(f, i.r0, 0);
jit_fpr_t r1 = getloc_d(f, j, i.r1, 1);
- jit_absr_f(j, r0, r1);
+ jit_absr_d(j, r0, r1);
putloc_d(f, j, i.r0, r0);
}
@@ -1305,6 +1344,23 @@ static void compile_truncr_f_32(struct ejit_func *f, jit_state_t *j,
#endif
}
+static void compile_sqrtr_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_sqrtr_f(j, r0, r1);
+ putloc_d(f, j, i.r0, r0);
+}
+
+static void compile_sqrtr_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_sqrtr_d(j, r0, r1);
+ putloc_d(f, j, i.r0, r0);
+}
static void compile_reg_cmp(struct ejit_func *f, jit_state_t *j,
struct ejit_insn i,
@@ -1783,7 +1839,7 @@ static enum jit_operand_abi jit_abi_from(enum ejit_type t)
case EJIT_POINTER: return JIT_OPERAND_ABI_POINTER;
case EJIT_FLOAT: return JIT_OPERAND_ABI_FLOAT;
case EJIT_DOUBLE: return JIT_OPERAND_ABI_DOUBLE;
- default:
+ default: break;
}
abort();
@@ -1803,7 +1859,7 @@ static size_t arg_offsetof(enum ejit_type t)
case EJIT_POINTER: return offsetof(struct ejit_arg, p);
case EJIT_FLOAT: return offsetof(struct ejit_arg, f);
case EJIT_DOUBLE: return offsetof(struct ejit_arg, d);
- default:
+ default: break;
};
abort();
@@ -1869,19 +1925,19 @@ static void compile_trampoline(struct ejit_func *f, jit_state_t *j)
foreach_vec(ii, f->insns) {
struct ejit_insn i = *insns_at(&f->insns, ii);
switch (i.op) {
- case PARAM: {
+ case EJIT_OP_PARAM: {
jit_operand_t p = jit_operand_mem(jit_abi_from(i.r1), JIT_R1, arg_offset(i));
operands_append(&args, p);
break;
}
- case PARAM_F: {
+ case EJIT_OP_PARAM_F: {
jit_operand_t p = jit_operand_mem(jit_abi_from(i.r1), JIT_R1, arg_offset(i));
operands_append(&args, p);
break;
}
- case START: {
+ case EJIT_OP_START: {
/* callr should be smart enough to avoid JIT_R0 if some
* other register wants to write to it */
jit_reloc_t r = jit_mov_addr(j, JIT_R0);
@@ -1889,7 +1945,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);
@@ -1901,6 +1957,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)
{
@@ -1922,204 +2056,373 @@ 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));
- void *call = NULL;
-
size_t label = 0;
foreach_vec(ii, f->insns) {
/* if we've hit a label, add it to our vector of label addresses */
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++;
}
}
struct ejit_insn i = *insns_at(&f->insns, ii);
switch (i.op) {
- case MOVR: compile_movr(f, j, i); break;
- case MOVR_F: compile_movr_f(f, j, i); break;
- case MOVR_D: compile_movr_d(f, j, i); break;
-
- case MOVI: compile_movi(f, j, i); break;
- case MOVI_F: compile_movi_f(f, j, i); break;
- case MOVI_D: compile_movi_d(f, j, i); break;
-
- case ADDR: compile_addr(f, j, i); break;
- case ADDI: compile_addi(f, j, i); break;
- case ADDR_F: compile_addr_f(f, j, i); break;
- case ADDR_D: compile_addr_d(f, j, i); break;
-
- case SUBR: compile_subr(f, j, i); break;
- case SUBI: compile_subi(f, j, i); break;
- case SUBR_F: compile_subr_f(f, j, i); break;
- case SUBR_D: compile_subr_d(f, j, i); break;
-
- case MULR: compile_mulr(f, j, i); break;
- case MULR_F: compile_mulr_f(f, j, i); break;
- case MULR_D: compile_mulr_d(f, j, i); break;
-
- case ANDI: compile_andi(f, j, i); break;
- case ANDR: compile_andr(f, j, i); break;
-
- case ORI: compile_ori(f, j, i); break;
- case ORR: compile_orr(f, j, i); break;
-
- case XORI: compile_xori(f, j, i); break;
- case XORR: compile_xorr(f, j, i); break;
-
- case DIVR: compile_divr(f, j, i); break;
- case DIVR_U: compile_divr_u(f, j, i); break;
- case DIVR_F: compile_divr_f(f, j, i); break;
- case DIVR_D: compile_divr_d(f, j, i); break;
-
- case REMR: compile_remr(f, j, i); break;
- case REMR_U: compile_remr_u(f, j, i); break;
-
- case ABSR_F: compile_absr_f(f, j, i); break;
- case ABSR_D: compile_absr_d(f, j, i); break;
-
- case LSHI: compile_lshi(f, j, i); break;
- case LSHR: compile_lshr(f, j, i); break;
- case RSHI: compile_rshi(f, j, i); break;
- case RSHI_U: compile_rshi_u(f, j, i); break;
- case RSHR: compile_rshr(f, j, i); break;
- case RSHR_U: compile_rshr_u(f, j, i); break;
-
- case STI8: compile_sti8(f, j, i); break;
- case STI16: compile_sti16(f, j, i); break;
- case STI32: compile_sti32(f, j, i); break;
- case STI64: compile_sti64(f, j, i); break;
- case STIF: compile_stif(f, j, i); break;
- case STID: compile_stid(f, j, i); break;
-
- case STXI8: compile_stxi8(f, j, i); break;
- case STXI16: compile_stxi16(f, j, i); break;
- case STXI32: compile_stxi32(f, j, i); break;
- case STXI64: compile_stxi64(f, j, i); break;
- case STXIF: compile_stxif(f, j, i); break;
- case STXID: compile_stxid(f, j, i); break;
-
- case STXR8: compile_stxr8(f, j, i); break;
- case STXR16: compile_stxr16(f, j, i); break;
- case STXR32: compile_stxr32(f, j, i); break;
- case STXR64: compile_stxr64(f, j, i); break;
- case STXRF: compile_stxrf(f, j, i); break;
- case STXRD: compile_stxrd(f, j, i); break;
-
- case LDI8: compile_ldi8(f, j, i); break;
- case LDI16: compile_ldi16(f, j, i); break;
- case LDI32: compile_ldi32(f, j, i); break;
- case LDI64: compile_ldi64(f, j, i); break;
- case LDIU8: compile_ldiu8(f, j, i); break;
- case LDIU16: compile_ldiu16(f, j, i); break;
- case LDIU32: compile_ldiu32(f, j, i); break;
- case LDIU64: compile_ldiu64(f, j, i); break;
- case LDIF: compile_ldif(f, j, i); break;
- case LDID: compile_ldid(f, j, i); break;
-
- case LDXI8: compile_ldxi8(f, j, i); break;
- case LDXI16: compile_ldxi16(f, j, i); break;
- case LDXI32: compile_ldxi32(f, j, i); break;
- case LDXI64: compile_ldxi64(f, j, i); break;
- case LDXIU8: compile_ldxiu8(f, j, i); break;
- case LDXIU16: compile_ldxiu16(f, j, i); break;
- case LDXIU32: compile_ldxiu32(f, j, i); break;
- case LDXIU64: compile_ldxiu64(f, j, i); break;
- case LDXIF: compile_ldxif(f, j, i); break;
- case LDXID: compile_ldxid(f, j, i); break;
-
- case LDXR8: compile_ldxr8(f, j, i); break;
- case LDXR16: compile_ldxr16(f, j, i); break;
- case LDXR32: compile_ldxr32(f, j, i); break;
- case LDXR64: compile_ldxr64(f, j, i); break;
- case LDXRU8: compile_ldxru8(f, j, i); break;
- case LDXRU16: compile_ldxru16(f, j, i); break;
- case LDXRU32: compile_ldxru32(f, j, i); break;
- case LDXRU64: compile_ldxru64(f, j, i); break;
- case LDXRF: compile_ldxrf(f, j, i); break;
- case LDXRD: compile_ldxrd(f, j, i); break;
-
- case COMR: compile_comr(f, j, i); break;
-
- case NEGR: compile_negr(f, j, i); break;
- case NEGR_F: compile_negr_f(f, j, i); break;
- case NEGR_D: compile_negr_d(f, j, i); break;
-
- case EXTR8: compile_extr8(f, j, i); break;
- case EXTR16: compile_extr16(f, j, i); break;
- case EXTR32: compile_extr32(f, j, i); break;
- case EXTRU8: compile_extru8(f, j, i); break;
- case EXTRU16: compile_extru16(f, j, i); break;
- case EXTRU32: compile_extru32(f, j, i); break;
- case EXTRF: compile_extrf(f, j, i); break;
- case EXTRD: compile_extrd(f, j, i); break;
-
- case TRUNCR_D_32: compile_truncr_d_32(f, j, i); break;
- case TRUNCR_D_64: compile_truncr_d_64(f, j, i); break;
- case TRUNCR_F_32: compile_truncr_f_32(f, j, i); break;
- case TRUNCR_F_64: compile_truncr_f_64(f, j, i); break;
-
- case EQR: compile_eqr(f, j, i); break;
- case EQR_F: compile_eqr_f(f, j, i); break;
- case EQR_D: compile_eqr_d(f, j, i); break;
-
- case NER: compile_ner(f, j, i); break;
- case NER_F: compile_ner_f(f, j, i); break;
- case NER_D: compile_ner_d(f, j, i); break;
-
- case GER: compile_ger(f, j, i); break;
- case GER_U: compile_ger_u(f, j, i); break;
- case GER_F: compile_ger_f(f, j, i); break;
- case GER_D: compile_ger_d(f, j, i); break;
-
- case GTR: compile_gtr(f, j, i); break;
- case GTR_U: compile_gtr_u(f, j, i); break;
- case GTR_F: compile_gtr_f(f, j, i); break;
- case GTR_D: compile_gtr_d(f, j, i); break;
-
- case BMCI: compile_bmci(f, j, i, &relocs); break;
- case BMCR: compile_bmcr(f, j, i, &relocs); break;
-
- case BMSI: compile_bmsi(f, j, i, &relocs); break;
- case BMSR: compile_bmsr(f, j, i, &relocs); break;
-
- case BEQR: compile_beqr(f, j, i, &relocs); break;
- case BEQI: compile_beqi(f, j, i, &relocs); break;
- case BEQR_F: compile_beqr_f(f, j, i, &relocs); break;
- case BEQR_D: compile_beqr_d(f, j, i, &relocs); break;
-
- case BNER: compile_bner(f, j, i, &relocs); break;
- case BNEI: compile_bnei(f, j, i, &relocs); break;
- case BNER_F: compile_bner_f(f, j, i, &relocs); break;
- case BNER_D: compile_bner_d(f, j, i, &relocs); break;
-
- case BGER: compile_bger(f, j, i, &relocs); break;
- case BGER_U: compile_bger_u(f, j, i, &relocs); break;
- case BGEI: compile_bgei(f, j, i, &relocs); break;
- case BGEI_U: compile_bgei_u(f, j, i, &relocs); break;
- case BGER_F: compile_bger_f(f, j, i, &relocs); break;
- case BGER_D: compile_bger_d(f, j, i, &relocs); break;
-
- case BGTR: compile_bgtr(f, j, i, &relocs); break;
- case BGTR_U: compile_bgtr_u(f, j, i, &relocs); break;
- case BGTI: compile_bgti(f, j, i, &relocs); break;
- case BGTI_U: compile_bgti_u(f, j, i, &relocs); break;
- case BGTR_F: compile_bgtr_f(f, j, i, &relocs); break;
- case BGTR_D: compile_bgtr_d(f, j, i, &relocs); break;
-
- case BLEI: compile_blei(f, j, i, &relocs); break;
- case BLEI_U: compile_blei_u(f, j, i, &relocs); break;
-
- case BLTI: compile_blti(f, j, i, &relocs); break;
- case BLTI_U: compile_blti_u(f, j, i, &relocs); break;
-
- case JMP: compile_jmp(f, j, i, &relocs); break;
-
- case ARG: {
+ case EJIT_OP_MOVR: compile_movr(f, j, i); break;
+ case EJIT_OP_MOVR_F: compile_movr_f(f, j, i); break;
+ case EJIT_OP_MOVR_D: compile_movr_d(f, j, i); break;
+
+ case EJIT_OP_MOVI: compile_movi(f, j, i); break;
+ case EJIT_OP_MOVI_F: compile_movi_f(f, j, i); break;
+ case EJIT_OP_MOVI_D: compile_movi_d(f, j, i); break;
+
+ case EJIT_OP_ADDR: compile_addr(f, j, i); break;
+ case EJIT_OP_ADDI: compile_addi(f, j, i); break;
+ case EJIT_OP_ADDR_F: compile_addr_f(f, j, i); break;
+ case EJIT_OP_ADDR_D: compile_addr_d(f, j, i); break;
+
+ case EJIT_OP_SUBR: compile_subr(f, j, i); break;
+ case EJIT_OP_SUBI: compile_subi(f, j, i); break;
+ case EJIT_OP_SUBR_F: compile_subr_f(f, j, i); break;
+ case EJIT_OP_SUBR_D: compile_subr_d(f, j, i); break;
+
+ case EJIT_OP_MULR: compile_mulr(f, j, i); break;
+ case EJIT_OP_MULR_F: compile_mulr_f(f, j, i); break;
+ case EJIT_OP_MULR_D: compile_mulr_d(f, j, i); break;
+
+ case EJIT_OP_ANDI: compile_andi(f, j, i); break;
+ case EJIT_OP_ANDR: compile_andr(f, j, i); break;
+
+ case EJIT_OP_ORI: compile_ori(f, j, i); break;
+ case EJIT_OP_ORR: compile_orr(f, j, i); break;
+
+ case EJIT_OP_XORI: compile_xori(f, j, i); break;
+ case EJIT_OP_XORR: compile_xorr(f, j, i); break;
+
+ case EJIT_OP_DIVR: compile_divr(f, j, i); break;
+ case EJIT_OP_DIVR_U: compile_divr_u(f, j, i); break;
+ case EJIT_OP_DIVR_F: compile_divr_f(f, j, i); break;
+ case EJIT_OP_DIVR_D: compile_divr_d(f, j, i); break;
+
+ case EJIT_OP_REMR: compile_remr(f, j, i); break;
+ case EJIT_OP_REMR_U: compile_remr_u(f, j, i); break;
+
+ case EJIT_OP_ABSR_F: compile_absr_f(f, j, i); break;
+ case EJIT_OP_ABSR_D: compile_absr_d(f, j, i); break;
+
+ case EJIT_OP_LSHI: compile_lshi(f, j, i); break;
+ case EJIT_OP_LSHR: compile_lshr(f, j, i); break;
+ case EJIT_OP_RSHI: compile_rshi(f, j, i); break;
+ case EJIT_OP_RSHI_U: compile_rshi_u(f, j, i); break;
+ case EJIT_OP_RSHR: compile_rshr(f, j, i); break;
+ case EJIT_OP_RSHR_U: compile_rshr_u(f, j, i); break;
+
+ case EJIT_OP_STI8: compile_sti8(f, j, i); break;
+ case EJIT_OP_STI16: compile_sti16(f, j, i); break;
+ case EJIT_OP_STI32: compile_sti32(f, j, i); break;
+ case EJIT_OP_STI64: compile_sti64(f, j, i); break;
+ case EJIT_OP_STIF: compile_stif(f, j, i); break;
+ case EJIT_OP_STID: compile_stid(f, j, i); break;
+
+ case EJIT_OP_STXI8: compile_stxi8(f, j, i); break;
+ case EJIT_OP_STXI16: compile_stxi16(f, j, i); break;
+ case EJIT_OP_STXI32: compile_stxi32(f, j, i); break;
+ case EJIT_OP_STXI64: compile_stxi64(f, j, i); break;
+ case EJIT_OP_STXIF: compile_stxif(f, j, i); break;
+ case EJIT_OP_STXID: compile_stxid(f, j, i); break;
+
+ case EJIT_OP_STXR8: compile_stxr8(f, j, i); break;
+ case EJIT_OP_STXR16: compile_stxr16(f, j, i); break;
+ case EJIT_OP_STXR32: compile_stxr32(f, j, i); break;
+ case EJIT_OP_STXR64: compile_stxr64(f, j, i); break;
+ case EJIT_OP_STXRF: compile_stxrf(f, j, i); break;
+ case EJIT_OP_STXRD: compile_stxrd(f, j, i); break;
+
+ case EJIT_OP_LDI8: compile_ldi8(f, j, i); break;
+ case EJIT_OP_LDI16: compile_ldi16(f, j, i); break;
+ case EJIT_OP_LDI32: compile_ldi32(f, j, i); break;
+ case EJIT_OP_LDI64: compile_ldi64(f, j, i); break;
+ case EJIT_OP_LDIU8: compile_ldiu8(f, j, i); break;
+ case EJIT_OP_LDIU16: compile_ldiu16(f, j, i); break;
+ case EJIT_OP_LDIU32: compile_ldiu32(f, j, i); break;
+ case EJIT_OP_LDIU64: compile_ldiu64(f, j, i); break;
+ case EJIT_OP_LDIF: compile_ldif(f, j, i); break;
+ case EJIT_OP_LDID: compile_ldid(f, j, i); break;
+
+ case EJIT_OP_LDXI8: compile_ldxi8(f, j, i); break;
+ case EJIT_OP_LDXI16: compile_ldxi16(f, j, i); break;
+ case EJIT_OP_LDXI32: compile_ldxi32(f, j, i); break;
+ case EJIT_OP_LDXI64: compile_ldxi64(f, j, i); break;
+ case EJIT_OP_LDXIU8: compile_ldxiu8(f, j, i); break;
+ case EJIT_OP_LDXIU16: compile_ldxiu16(f, j, i); break;
+ case EJIT_OP_LDXIU32: compile_ldxiu32(f, j, i); break;
+ case EJIT_OP_LDXIU64: compile_ldxiu64(f, j, i); break;
+ case EJIT_OP_LDXIF: compile_ldxif(f, j, i); break;
+ case EJIT_OP_LDXID: compile_ldxid(f, j, i); break;
+
+ case EJIT_OP_LDXR8: compile_ldxr8(f, j, i); break;
+ case EJIT_OP_LDXR16: compile_ldxr16(f, j, i); break;
+ case EJIT_OP_LDXR32: compile_ldxr32(f, j, i); break;
+ case EJIT_OP_LDXR64: compile_ldxr64(f, j, i); break;
+ case EJIT_OP_LDXRU8: compile_ldxru8(f, j, i); break;
+ case EJIT_OP_LDXRU16: compile_ldxru16(f, j, i); break;
+ case EJIT_OP_LDXRU32: compile_ldxru32(f, j, i); break;
+ case EJIT_OP_LDXRU64: compile_ldxru64(f, j, i); break;
+ case EJIT_OP_LDXRF: compile_ldxrf(f, j, i); break;
+ case EJIT_OP_LDXRD: compile_ldxrd(f, j, i); break;
+
+ case EJIT_OP_COMR: compile_comr(f, j, i); break;
+
+ case EJIT_OP_NEGR: compile_negr(f, j, i); break;
+ case EJIT_OP_NEGR_F: compile_negr_f(f, j, i); break;
+ case EJIT_OP_NEGR_D: compile_negr_d(f, j, i); break;
+
+ case EJIT_OP_EXTR8: compile_extr8(f, j, i); break;
+ case EJIT_OP_EXTR16: compile_extr16(f, j, i); break;
+ case EJIT_OP_EXTR32: compile_extr32(f, j, i); break;
+ case EJIT_OP_EXTRU8: compile_extru8(f, j, i); break;
+ case EJIT_OP_EXTRU16: compile_extru16(f, j, i); break;
+ case EJIT_OP_EXTRU32: compile_extru32(f, j, i); break;
+ case EJIT_OP_EXTRF: compile_extrf(f, j, i); break;
+ case EJIT_OP_EXTRD: compile_extrd(f, j, i); break;
+
+ case EJIT_OP_TRUNCR_D_32: compile_truncr_d_32(f, j, i); break;
+ case EJIT_OP_TRUNCR_D_64: compile_truncr_d_64(f, j, i); break;
+ case EJIT_OP_TRUNCR_F_32: compile_truncr_f_32(f, j, i); break;
+ case EJIT_OP_TRUNCR_F_64: compile_truncr_f_64(f, j, i); break;
+
+ 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;
+
+ case EJIT_OP_NER: compile_ner(f, j, i); break;
+ case EJIT_OP_NER_F: compile_ner_f(f, j, i); break;
+ case EJIT_OP_NER_D: compile_ner_d(f, j, i); break;
+
+ case EJIT_OP_GER: compile_ger(f, j, i); break;
+ case EJIT_OP_GER_U: compile_ger_u(f, j, i); break;
+ case EJIT_OP_GER_F: compile_ger_f(f, j, i); break;
+ case EJIT_OP_GER_D: compile_ger_d(f, j, i); break;
+
+ case EJIT_OP_GTR: compile_gtr(f, j, i); break;
+ case EJIT_OP_GTR_U: compile_gtr_u(f, j, i); break;
+ 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);
+ 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_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_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_BGTR_D: {
+ compile_bgtr_d(f, j, i, &relocs);
+ resolve_top_reloc(j, &relocs, &addrs, ii);
+ break;
+ }
+
+ case EJIT_OP_BLEI: {
+ compile_blei(f, j, i, &relocs);
+ resolve_top_reloc(j, &relocs, &addrs, ii);
+ break;
+ }
+
+ case EJIT_OP_BLEI_U: {
+ compile_blei_u(f, j, i, &relocs);
+ resolve_top_reloc(j, &relocs, &addrs, ii);
+ break;
+ }
+
+ case EJIT_OP_BLTI: {
+ compile_blti(f, j, i, &relocs);
+ resolve_top_reloc(j, &relocs, &addrs, ii);
+ 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);
+ 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);
+ jit_operand_t arg = jit_operand_imm(jit_abi_from(i.r1), i.o);
+ operands_append(&src, type);
+ operands_append(&src, arg);
+ operands_append(&direct, arg);
+
+ jit_operand_t to[2] = {
+ jit_operand_mem(JIT_OPERAND_ABI_WORD, JIT_SP,
+ type_offset(i)),
+ jit_operand_mem(jit_abi_from(i.r1), JIT_SP,
+ arg_offset(i))
+ };
+
+ operands_append(&dst, to[0]);
+ operands_append(&dst, to[1]);
+ break;
+ }
+
+ case EJIT_OP_ARG_FI: {
+ assert(false && "immediate floats (currently?) not supported");
+ abort();
+ break;
+ }
+
+ case EJIT_OP_ARG: {
size_t r2 = gpr_stats_at(&f->gpr, i.r2)->rno;
jit_operand_t type = jit_operand_imm(JIT_OPERAND_ABI_WORD, i.r1);
@@ -2152,12 +2455,12 @@ static size_t compile_fn_body(struct ejit_func *f, jit_state_t *j, void *arena,
break;
}
- case ARG_F: {
+ case EJIT_OP_ARG_F: {
size_t f2 = fpr_stats_at(&f->fpr, i.r2)->fno;
jit_operand_t type = jit_operand_imm(JIT_OPERAND_ABI_WORD, i.r1);
jit_operand_t arg;
- if (i.r2 < physfpr_count()) {
+ if (f2 < physfpr_count()) {
/* regular register */
arg = jit_operand_fpr(jit_abi_from(i.r1),
physfpr_at(f2));
@@ -2186,17 +2489,10 @@ static size_t compile_fn_body(struct ejit_func *f, jit_state_t *j, void *arena,
break;
}
- case ESCAPEI_L:
-#if __WORDSIZE == 64
- /* fallthrough */
-#else
- assert(0 && "trying to compile escapei_l on 32bit arch");
- break;
-#endif
-
- case ESCAPEI_D:
- case ESCAPEI_F:
- case ESCAPEI_I: {
+ case EJIT_OP_ESCAPEI_I:
+ case EJIT_OP_ESCAPEI_L:
+ case EJIT_OP_ESCAPEI_F:
+ case EJIT_OP_ESCAPEI_D: {
save_caller_save_regs(f, j);
jit_operand_t args[2] = {
@@ -2206,7 +2502,7 @@ static size_t compile_fn_body(struct ejit_func *f, jit_state_t *j, void *arena,
* argument stack address */
jit_operand_gpr(JIT_OPERAND_ABI_POINTER, JIT_R0)
};
- compile_imm_call(j, &src, &dst, (void *)(uintptr_t)i.o, 2, args);
+ compile_imm_call(j, &src, &dst, (void *)i.p, 2, args);
restore_caller_save_regs(f, j);
operands_reset(&src);
@@ -2215,21 +2511,165 @@ static size_t compile_fn_body(struct ejit_func *f, jit_state_t *j, void *arena,
break;
}
- case CALLI_L:
-#if __WORDSIZE == 64
- call = ejit_run_func_l; goto calli;
-#else
- assert(0 && "trying to compile calli_l on 32bit arch");
- break;
+ case EJIT_OP_TAILI: {
+ /* a bit of copy-paste between this and the next func,
+ * hmm */
+ assert(operands_len(&direct) <= 2);
+ struct ejit_func *f = (struct ejit_func *)i.p;
+ assert(f->direct_call);
+
+ jit_operand_t regs[2] = {
+ jit_operand_gpr(JIT_OPERAND_ABI_WORD, JIT_R1),
+ jit_operand_gpr(JIT_OPERAND_ABI_WORD, JIT_R2)
+ };
+ jit_move_operands(j, regs, direct.buf, operands_len(&direct));
+
+ int frame_size = j->frame_size;
+ jit_shrink_stack(j, stack);
+ jit_leave_jit_abi(j, gprs, fprs, frame);
+
+ /* now move args into place */
+ jit_operand_t args[2] = {};
+ foreach_vec(oi, direct) {
+ args[oi] = *operands_at(&direct, oi);
+ }
+
+ jit_locate_args(j, operands_len(&direct), args);
+ jit_move_operands(j, args, regs, operands_len(&direct));
+ jit_jmpi(j, f->direct_call);
+ j->frame_size = frame_size;
+
+ operands_reset(&src);
+ operands_reset(&dst);
+ operands_reset(&direct);
+ break;
+ }
+
+ case EJIT_OP_TAILR: {
+ /* this is admittedly a slightly roundabout way of
+ * implementing tail calls and is arguably not the most
+ * performant way (if it works at all, heh) but for now
+ * I'm more interested in functionality than raw
+ * performance. Currently only supports two gpr
+ * registers, but should be fairly easy to extend with
+ * fprs as well */
+
+ assert(operands_len(&direct) <= 2);
+ jit_gpr_t r = getloc(f, j, i.r1, 0);
+
+#if defined(DEBUG)
+ jit_ldxi(j, JIT_R1, r, offsetof(struct ejit_func, rtype));
+ jit_reloc_t rtype_reloc = jit_beqi(j, JIT_R1, f->rtype);
+ jit_calli_1(j, assert_helper,
+ jit_operand_imm(JIT_OPERAND_ABI_POINTER,
+ (jit_imm_t)"trying to tail call different rtype"));
+
+ jit_patch_here(j, rtype_reloc);
+
+ jit_ldxi(j, JIT_R1, r, offsetof(struct ejit_func, direct_call));
+ jit_reloc_t direct_reloc = jit_bnei(j, JIT_R1, 0); /* null */
+ jit_calli_1(j, assert_helper,
+ jit_operand_imm(JIT_OPERAND_ABI_POINTER,
+ (jit_imm_t)"trying to tail call interpreted function"));
+ jit_patch_here(j, direct_reloc);
#endif
+ size_t argc = operands_len(&direct);
+
+ /* r0 = target, r1 = arg1, r2 = arg2 */
+ jit_ldxi(j, JIT_R0, r, offsetof(struct ejit_func, direct_call));
+ jit_operand_t regs[3] = {
+ jit_operand_gpr(JIT_OPERAND_ABI_WORD, JIT_R1),
+ jit_operand_gpr(JIT_OPERAND_ABI_WORD, JIT_R2)
+ };
+ jit_move_operands(j, regs, direct.buf, argc);
+
+ /* with args safely in registers, reset stack/state
+ * while avoiding overwriting the call target */
+ int frame_size = j->frame_size;
+ jit_shrink_stack(j, stack);
+ jit_leave_jit_abi(j, gprs, fprs, frame);
+
+ /* now move args into place, making sure we avoid our
+ * target register */
+ jit_operand_t args[3] = {};
+ for (size_t oi = 0; oi < argc; ++oi) {
+ args[oi] = *operands_at(&direct, oi);
+ }
+
+ jit_locate_args(j, argc, args);
+
+ /* we know that at least one gpr must be free */
+ jit_gpr_t target = gpr_free(argc, args, JIT_R0) ? JIT_R0
+ : gpr_free(argc, args, JIT_R1) ? JIT_R1
+ : gpr_free(argc, args, JIT_R2) ? JIT_R2
+ : (abort(), JIT_R0);
+
+ /* move our target in JIT_R0 to whatever the free
+ * register is to avoid it being clobbered when we move
+ * the actual arguments */
+ args[argc] = jit_operand_gpr(JIT_OPERAND_ABI_POINTER, target);
+ regs[argc] = jit_operand_gpr(JIT_OPERAND_ABI_POINTER, JIT_R0);
+ jit_move_operands(j, args, regs, argc + 1);
+ jit_jmpr(j, target);
+ j->frame_size = frame_size;
+
+ operands_reset(&src);
+ operands_reset(&dst);
+ operands_reset(&direct);
+ break;
+ }
+
+ case EJIT_OP_CALLR_I:
+ case EJIT_OP_CALLR_L:
+ case EJIT_OP_CALLR_F:
+ case EJIT_OP_CALLR_D: {
+ save_caller_save_regs(f, j);
+
+ jit_gpr_t target = getgpr(f, i.r1, 0);
+
+ /* check if there's a direct call avaiable */
+ jit_ldxi(j, JIT_R1, target, offsetof(struct ejit_func, direct_call));
+ jit_reloc_t direct_reloc = jit_beqi(j, JIT_R0, 0);
+ /* we can do a jit -> jit call */
+ jit_callr(j, JIT_R1, operands_len(&direct), direct.buf);
+ jit_reloc_t out_reloc = jit_jmp(j);
+
+ jit_patch_here(j, direct_reloc);
- case CALLI_F: { call = ejit_run_func_f; goto calli; }
- case CALLI_D: { call = ejit_run_func_d; goto calli; }
- case CALLI_I: { call = ejit_run_func_i; goto calli;
-calli:
+ /* we must do a jit -> bytecode call */
+ jit_operand_t args[3] = {
+ jit_operand_gpr(JIT_OPERAND_ABI_POINTER, JIT_R1),
+ jit_operand_imm(JIT_OPERAND_ABI_WORD, operands_len(&src) / 2),
+ /* compile_imm_call populate JIT_R0 with the
+ * argument stack address */
+ jit_operand_gpr(JIT_OPERAND_ABI_POINTER, JIT_R0)
+ };
+ void *call = NULL;
+ switch (i.op) {
+ case EJIT_OP_CALLR_I: call = ejit_run_func_i; break;
+ case EJIT_OP_CALLR_L: call = ejit_run_func_l; break;
+ case EJIT_OP_CALLR_F: call = ejit_run_func_f; break;
+ case EJIT_OP_CALLR_D: call = ejit_run_func_d; break;
+ default: abort();
+ }
+
+ compile_imm_call(j, &src, &dst, call, 3, args);
+ jit_patch_here(j, out_reloc);
+ restore_caller_save_regs(f, j);
+
+ operands_reset(&src);
+ operands_reset(&dst);
+ operands_reset(&direct);
+ break;
+ }
+
+ case EJIT_OP_CALLI: {
save_caller_save_regs(f, j);
- struct ejit_func *f = (struct ejit_func *)(uintptr_t)i.o;
+ struct ejit_func *f = (struct ejit_func *)i.p;
+#if __WORDSIZE != 64
+ assert(f->rtype != EJIT_INT64 && f->rtype != EJIT_UINT64);
+#endif
if (f && f->direct_call) {
jit_calli(j, f->direct_call, operands_len(&direct), direct.buf);
restore_caller_save_regs(f, j);
@@ -2248,6 +2688,16 @@ calli:
* argument stack address */
jit_operand_gpr(JIT_OPERAND_ABI_POINTER, JIT_R0)
};
+
+ void *call = NULL;
+ switch (f->rtype) {
+ case EJIT_INT64:
+ case EJIT_UINT64: call = checked_run_l; break;
+ case EJIT_FLOAT: call = checked_run_f; break;
+ case EJIT_DOUBLE: call = checked_run_d; break;
+ default: call = checked_run_i; break;
+ }
+
compile_imm_call(j, &src, &dst, call, 3, args);
restore_caller_save_regs(f, j);
@@ -2257,54 +2707,70 @@ calli:
break;
}
- case RETVAL: compile_retval(f, j, i); break;
- case RETVAL_F: compile_retval_f(f, j, i); break;
- case RETVAL_D: compile_retval_d(f, j, i); break;
+ case EJIT_OP_RETVAL: compile_retval(f, j, i); break;
+ case EJIT_OP_RETVAL_F: compile_retval_f(f, j, i); break;
+ case EJIT_OP_RETVAL_D: compile_retval_d(f, j, i); break;
- case RETR: {
+ case EJIT_OP_RETR: {
jit_gpr_t r = getloc(f, j, i.r1, 0);
/* R0 won't get overwritten by jit_leave_jit_abi */
jit_movr(j, JIT_R0, r);
+
+ /* keep track of frame size so we can continue
+ * generating code after 'leaving' the ABI. Bit of a
+ * hack, should maybe codify this better in the
+ * lightening API? */
+ int frame_size = j->frame_size;
jit_shrink_stack(j, stack);
jit_leave_jit_abi(j, gprs, fprs, frame);
jit_retr(j, JIT_R0);
+ j->frame_size = frame_size;
break;
}
- case RETR_F: {
+ case EJIT_OP_RETR_F: {
jit_fpr_t r = getloc_f(f, j, i.r1, 0);
jit_movr_f(j, JIT_F0, r);
+
+ int frame_size = j->frame_size;
jit_shrink_stack(j, stack);
jit_leave_jit_abi(j, gprs, fprs, frame);
jit_retr_f(j, JIT_F0);
+ j->frame_size = frame_size;
break;
}
- case RETR_D: {
+ case EJIT_OP_RETR_D: {
jit_fpr_t r = getloc_d(f, j, i.r1, 0);
jit_movr_d(j, JIT_F0, r);
+
+ int frame_size = j->frame_size;
jit_shrink_stack(j, stack);
jit_leave_jit_abi(j, gprs, fprs, frame);
jit_retr_d(j, JIT_F0);
+ j->frame_size = frame_size;
break;
}
- case RETI: {
+ case EJIT_OP_RETI: {
+ int frame_size = j->frame_size;
jit_shrink_stack(j, stack);
jit_leave_jit_abi(j, gprs, fprs, frame);
jit_reti(j, i.o);
+ j->frame_size = frame_size;
break;
}
- case END: {
- /* 'void' return */
+ case EJIT_OP_END: {
+ /* 'void' return, must be last thing in function so no
+ * need to keep track of frame size */
jit_shrink_stack(j, stack);
jit_leave_jit_abi(j, gprs, fprs, frame);
jit_reti(j, 0);
break;
}
- case PARAM_F: {
+ case EJIT_OP_PARAM_F: {
size_t f2 = fpr_stats_at(&f->fpr, i.r2)->fno;
jit_operand_t to;
@@ -2323,7 +2789,7 @@ calli:
break;
}
- case PARAM: {
+ case EJIT_OP_PARAM: {
size_t r2 = gpr_stats_at(&f->gpr, i.r2)->rno;
jit_operand_t to;
@@ -2342,7 +2808,7 @@ calli:
break;
}
- case START: {
+ case EJIT_OP_START: {
/* parameters should be done by now */
jit_load_args(j, operands_len(&dst), dst.buf);
/* reuse for arguments */
@@ -2354,14 +2820,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);
@@ -2369,49 +2828,189 @@ calli:
relocs_destroy(&relocs);
addrs_destroy(&addrs);
- if (jit_end(j, &size))
+ if ((f->extern_call = jit_end(j, &size)))
return 0;
return size;
}
-/* highest prio first */
-static int gpr_sort_prio(struct gpr_stat *a, struct gpr_stat *b)
+struct alive_slot {
+ long r;
+ size_t cost;
+ size_t idx;
+ size_t remap;
+};
+
+#define VEC_NAME alive
+#define VEC_TYPE struct alive_slot
+#include "../vec.h"
+
+static int spill_cost_sort(struct alive_slot *a, struct alive_slot *b)
{
- return (int)b->prio - (int)a->prio;
+ if (a->cost > b->cost)
+ return -1;
+
+ return a->cost < b->cost;
}
-static int fpr_sort_prio(struct fpr_stat *a, struct fpr_stat *b)
+/* slightly more parameters than I would like but I guess it's fine */
+static void calculate_alive(struct alive *alive, size_t idx,
+ size_t prio, size_t start, size_t end, size_t *rno,
+ void *regs, int (*dead)(void *regs, size_t idx, size_t start))
{
- return (int)b->prio - (int)a->prio;
+ /* single-shot registers go in the special reserved slot */
+ if (end <= start + 1) {
+ *rno = 0;
+
+ struct alive_slot *a = alive_at(alive, 0);
+ a->cost += prio;
+ return;
+ }
+
+ /* kill registers whose lifetime has ended */
+ long max_cost_idx = -1;
+ size_t max_cost = 0;
+ long counter = 0;
+ foreach_vec(ai, *alive) {
+ /* skip oneshot */
+ if (ai == 0)
+ goto next;
+
+ struct alive_slot *a = alive_at(alive, ai);
+ if (a->r >= 0 && dead(regs, a->r, start))
+ a->r = -1; /* gravestone */
+
+ if (a->r < 0 && a->cost > max_cost) {
+ max_cost = a->cost;
+ max_cost_idx = counter;
+ }
+
+next:
+ counter++;
+ }
+
+ /* there's a suitable slot for us */
+ if (max_cost_idx >= 0) {
+ *rno = max_cost_idx;
+
+ struct alive_slot *a = alive_at(alive, max_cost_idx);
+ a->cost += prio;
+ a->r = idx;
+ return;
+ }
+
+ *rno = alive_len(alive);
+ struct alive_slot a = {
+ .cost = prio,
+ .r = idx,
+ .idx = *rno
+ };
+ alive_append(alive, a);
}
-/* sort registers by highest priority first, then renumber registers in the
- * given order. Higher priority is given a physical register first.
- *
- * Note that the `->r` field becomes 'meaningless' after sorting, and you should
- * only use the `->rno` field after this point. Essentially, if you have a
- * register EJIT_GPR(2), you should use `gpr_stats_at(2)->rno` for the 'actual'
- * register number in `getloc` and the like.
- *
- * Can be a bit confusing, but this way we don't have to allocate any new
- * arrays, which is cool. */
+static int gpr_dead(void *regs, size_t idx, size_t start)
+{
+ struct gpr_stats *gprs = regs;
+ return gpr_stats_at(gprs, idx)->end <= start;
+}
+
+static void linear_gpr_alloc(struct ejit_func *f)
+{
+ foreach_vec(gi, f->gpr) {
+ gpr_stats_at(&f->gpr, gi)->rno = gi;
+ }
+}
+
+/* there's a fair bit of repetition between this and the gpr case, hmm */
static void assign_gprs(struct ejit_func *f)
{
- gpr_stats_sort(&f->gpr, (vec_comp_t)gpr_sort_prio);
+ /* everything fits into registers, no need to start optimizing */
+ if (gpr_stats_len(&f->gpr) <= physgpr_count())
+ return linear_gpr_alloc(f);
+
+ struct alive alive = alive_create(gpr_stats_len(&f->gpr));
+
+ /* special oneshot register class */
+ struct alive_slot a = {.r = -1, .cost = 0, .idx = 0};
+ alive_append(&alive, a);
+
+ foreach_vec(gi, f->gpr) {
+ struct gpr_stat *gpr = gpr_stats_at(&f->gpr, gi);
+ calculate_alive(&alive, gi,
+ gpr->prio, gpr->start, gpr->end, &gpr->rno,
+ &f->gpr, gpr_dead);
+ }
+
+ /* sort so that the highest spill cost register classes are at the front and
+ * as such more likely to be placed in registers */
+ alive_sort(&alive, (vec_comp_t)spill_cost_sort);
+
+ /* update remapping info */
+ for(size_t i = 0; i < alive_len(&alive); ++i) {
+ struct alive_slot *a = alive_at(&alive, i);
+ alive_at(&alive, a->idx)->remap = i;
+ }
+
+ /* remap locations */
for (size_t i = 0; i < gpr_stats_len(&f->gpr); ++i) {
- size_t rno = gpr_stats_at(&f->gpr, i)->r.r;
- gpr_stats_at(&f->gpr, rno)->rno = i;
+ struct gpr_stat *gpr = gpr_stats_at(&f->gpr, i);
+ struct alive_slot *a = alive_at(&alive, gpr->rno);
+ gpr->rno = a->remap;
+ }
+
+ alive_destroy(&alive);
+}
+
+static int fpr_dead(void *regs, size_t idx, size_t start)
+{
+ struct fpr_stats *fprs = regs;
+ return fpr_stats_at(fprs, idx)->end <= start;
+}
+
+static void linear_fpr_alloc(struct ejit_func *f)
+{
+ foreach_vec(fi, f->fpr) {
+ fpr_stats_at(&f->fpr, fi)->fno = fi;
}
}
static void assign_fprs(struct ejit_func *f)
{
- fpr_stats_sort(&f->fpr, (vec_comp_t)fpr_sort_prio);
+ /* everything fits into registers, no need to start optimizing */
+ if (fpr_stats_len(&f->fpr) <= physfpr_count())
+ return linear_fpr_alloc(f);
+
+ struct alive alive = alive_create(fpr_stats_len(&f->fpr));
+
+ /* special oneshot register class */
+ struct alive_slot a = {.r = -1, .cost = 0, .idx = 0};
+ alive_append(&alive, a);
+
+ foreach_vec(fi, f->fpr) {
+ struct fpr_stat *fpr = fpr_stats_at(&f->fpr, fi);
+ calculate_alive(&alive, fi,
+ fpr->prio, fpr->start, fpr->end, &fpr->fno,
+ &f->fpr, fpr_dead);
+ }
+
+ /* sort so that the highest spill cost register classes are at the front and
+ * as such more likely to be placed in registers */
+ alive_sort(&alive, (vec_comp_t)spill_cost_sort);
+
+ /* update remapping info */
+ for(size_t i = 0; i < alive_len(&alive); ++i) {
+ struct alive_slot *a = alive_at(&alive, i);
+ alive_at(&alive, a->idx)->remap = i;
+ }
+
+ /* remap locations */
for (size_t i = 0; i < fpr_stats_len(&f->fpr); ++i) {
- size_t rno = fpr_stats_at(&f->fpr, i)->f.f;
- fpr_stats_at(&f->fpr, rno)->fno = i;
+ struct fpr_stat *fpr = fpr_stats_at(&f->fpr, i);
+ struct alive_slot *a = alive_at(&alive, fpr->fno);
+ fpr->fno = a->remap;
}
+
+ alive_destroy(&alive);
}
static size_t align_up(size_t a, size_t n)
@@ -2425,7 +3024,7 @@ static size_t align_up(size_t a, size_t n)
bool ejit_compile(struct ejit_func *f, bool use_64, bool im_scawed)
{
(void)use_64;
-#if __WORDSIZE == 32
+#if __WORDSIZE != 64
/* can't compile 64bit code on 32bit systems, give up early */
if (use_64)
return false;
diff --git a/src/ejit.c b/src/ejit.c
index 265acea..e8ff99e 100644
--- a/src/ejit.c
+++ b/src/ejit.c
@@ -1,4 +1,5 @@
#include <assert.h>
+#include <stdio.h>
#include <sys/mman.h>
#include <ejit/ejit.h>
@@ -47,9 +48,12 @@ static void update_gpr(struct ejit_func *f, struct ejit_gpr r0)
struct gpr_stat *gpr = gpr_stats_at(&f->gpr, r0.r);
/* presumably first time we see this gpr */
/** @todo are branches faster than a memory write? */
- if (gpr->prio == 0)
+ if (gpr->prio == 0) {
+ gpr->start = insns_len(&f->insns);
gpr->r = r0;
+ }
+ gpr->end = insns_len(&f->insns);
gpr->prio += f->prio;
}
@@ -59,9 +63,12 @@ static void update_fpr(struct ejit_func *f, struct ejit_fpr f0)
fpr_stats_append(&f->fpr, zero_fpr_stat());
struct fpr_stat *fpr = fpr_stats_at(&f->fpr, f0.f);
- if (fpr->prio == 0)
+ if (fpr->prio == 0) {
+ fpr->start = insns_len(&f->insns);
fpr->f = f0;
+ }
+ fpr->end = insns_len(&f->insns);
fpr->prio += f->prio;
}
@@ -161,6 +168,8 @@ static void emit_insn_af(struct ejit_func *f, enum ejit_opcode op, size_t idx, e
static void emit_insn_ad(struct ejit_func *f, enum ejit_opcode op, size_t idx, enum ejit_type type, double d)
{
+ fprintf(stderr, "warning: immediate floats are currently not supported.\n"
+ "Consider moving values into FPRs.\n");
struct ejit_insn i = {.op = op, .r0 = idx, .r1 = type, .d = d};
insns_append(&f->insns, i);
}
@@ -336,9 +345,11 @@ 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;
+ f->max_args = 0;
for (size_t i = 0; i < argc; ++i) {
types_append(&f->sign, args[i].type);
@@ -346,20 +357,20 @@ struct ejit_func *ejit_create_func(enum ejit_type rtype, size_t argc,
switch (args[i].kind) {
case EJIT_OPERAND_GPR: {
assert(ejit_int_type(args[i].type));
- emit_insn_ar(f, PARAM, i, args[i].type, EJIT_GPR(args[i].r));
+ emit_insn_ar(f, EJIT_OP_PARAM, i, args[i].type, EJIT_GPR(args[i].r));
break;
}
case EJIT_OPERAND_FPR: {
assert(ejit_float_type(args[i].type));
- emit_insn_af(f, PARAM_F, i, args[i].type, EJIT_FPR(args[i].r));
+ emit_insn_af(f, EJIT_OP_PARAM_F, i, args[i].type, EJIT_FPR(args[i].r));
break;
}
default: abort();
}
}
- emit_insn_o(f, START);
+ emit_insn_o(f, EJIT_OP_START);
return f;
}
@@ -388,7 +399,7 @@ void ejit_select_compile_func(struct ejit_func *f, size_t gpr, size_t fpr,
bool use_64, bool try_jit, bool im_scawed)
{
/* emit a final end instruction in case user didn't do a return */
- emit_insn_o(f, END);
+ emit_insn_o(f, EJIT_OP_END);
/* user can get some sanity checking done by passing these explicitly */
assert(gpr >= gpr_stats_len(&f->gpr));
@@ -403,7 +414,7 @@ void ejit_select_compile_func(struct ejit_func *f, size_t gpr, size_t fpr,
void **labels;
/* just get labels, don't actually run anything yet */
- ejit_run(f, 0, NULL, NULL, false, &labels);
+ ejit_run(f, 0, NULL, &labels);
foreach_vec(ii, f->insns) {
struct ejit_insn i = *insns_at(&f->insns, ii);
@@ -445,730 +456,819 @@ void ejit_patch(struct ejit_func *f, struct ejit_reloc r, struct ejit_label l)
*insns_at(&f->insns, r.insn) = i;
}
-void ejit_calli_i(struct ejit_func *s, struct ejit_func *f, size_t argc,
- const struct ejit_operand args[argc])
+void ejit_taili(struct ejit_func *s, struct ejit_func *f,
+ size_t argc, const struct ejit_operand args[argc])
{
+ assert(s->rtype == f->rtype);
+
+ s->max_args = argc > s->max_args ? argc : s->max_args;
check_operands(f, argc, args);
+ size_t gpr_args = 0, fpr_args = 0;
for (size_t i = 0; i < argc; ++i) {
switch (args[i].kind) {
- case EJIT_OPERAND_GPR: emit_insn_ar(s, ARG, i, args[i].type, EJIT_GPR(args[i].r)); break;
- case EJIT_OPERAND_FPR: emit_insn_af(s, ARG_F, i, args[i].type, EJIT_FPR(args[i].r)); break;
- case EJIT_OPERAND_IMM: emit_insn_ai(s, ARG_I, i, args[i].type, args[i].r); break;
- case EJIT_OPERAND_FLT: emit_insn_ad(s, ARG_FI, i, args[i].type, args[i].d); break;
+ case EJIT_OPERAND_GPR:
+ gpr_args++;
+ emit_insn_ar(s, EJIT_OP_ARG, i, args[i].type, EJIT_GPR(args[i].r));
+ break;
+
+ case EJIT_OPERAND_FPR:
+ fpr_args++;
+ emit_insn_af(s, EJIT_OP_ARG_F, i, args[i].type, EJIT_FPR(args[i].r));
+ break;
+
+ case EJIT_OPERAND_IMM:
+ gpr_args++;
+ emit_insn_ai(s, EJIT_OP_ARG_I, i, args[i].type, args[i].r);
+ break;
+
+ case EJIT_OPERAND_FLT:
+ fpr_args++;
+ emit_insn_ad(s, EJIT_OP_ARG_FI, i, args[i].type, args[i].d);
+ break;
+
default: abort();
}
}
- emit_insn_op(s, CALLI_I, f);
+ assert(gpr_args <= 2 && fpr_args == 0
+ && "only 2 gpr args and 0 fpr args supported in tail calls for now");
+ emit_insn_op(s, EJIT_OP_TAILI, f);
}
-void ejit_calli_l(struct ejit_func *s, struct ejit_func *f, size_t argc,
+void ejit_tailr(struct ejit_func *s, struct ejit_gpr target, size_t argc,
const struct ejit_operand args[argc])
{
- s->use_64 = true;
- check_operands(f, argc, args);
+ s->max_args = argc > s->max_args ? argc : s->max_args;
+ /* operands must match */
+ check_operands(s, argc, args);
+
+ size_t gpr_args = 0, fpr_args = 0;
for (size_t i = 0; i < argc; ++i) {
switch (args[i].kind) {
- case EJIT_OPERAND_GPR: emit_insn_ar(s, ARG, i, args[i].type, EJIT_GPR(args[i].r)); break;
- case EJIT_OPERAND_FPR: emit_insn_af(s, ARG_F, i, args[i].type, EJIT_FPR(args[i].r)); break;
- case EJIT_OPERAND_IMM: emit_insn_ai(s, ARG_I, i, args[i].type, args[i].r); break;
- case EJIT_OPERAND_FLT: emit_insn_ad(s, ARG_FI, i, args[i].type, args[i].d); break;
+ case EJIT_OPERAND_GPR:
+ gpr_args++;
+ emit_insn_ar(s, EJIT_OP_ARG, i, args[i].type, EJIT_GPR(args[i].r));
+ break;
+
+ case EJIT_OPERAND_FPR:
+ fpr_args++;
+ emit_insn_af(s, EJIT_OP_ARG_F, i, args[i].type, EJIT_FPR(args[i].r));
+ break;
+
+ case EJIT_OPERAND_IMM:
+ gpr_args++;
+ emit_insn_ai(s, EJIT_OP_ARG_I, i, args[i].type, args[i].r);
+ break;
+
+ case EJIT_OPERAND_FLT:
+ fpr_args++;
+ emit_insn_ad(s, EJIT_OP_ARG_FI, i, args[i].type, args[i].d);
+ break;
+
default: abort();
}
}
- emit_insn_op(s, CALLI_L, f);
+ assert(gpr_args <= 2 && fpr_args == 0
+ && "only 2 gpr args and 0 fpr args supported in tail calls for now");
+ emit_insn_oxr(s, EJIT_OP_TAILR, target);
}
-void ejit_calli_f(struct ejit_func *s, struct ejit_func *f, size_t argc,
+void ejit_calli(struct ejit_func *s, struct ejit_func *f, size_t argc,
const struct ejit_operand args[argc])
{
+ s->use_64 = f->rtype == EJIT_INT64 || f->rtype == EJIT_UINT64;
+ s->max_args = argc > s->max_args ? argc : s->max_args;
check_operands(f, argc, args);
for (size_t i = 0; i < argc; ++i) {
switch (args[i].kind) {
- case EJIT_OPERAND_GPR: emit_insn_ar(s, ARG, i, args[i].type, EJIT_GPR(args[i].r)); break;
- case EJIT_OPERAND_FPR: emit_insn_af(s, ARG_F, i, args[i].type, EJIT_FPR(args[i].r)); break;
- case EJIT_OPERAND_IMM: emit_insn_ai(s, ARG_I, i, args[i].type, args[i].r); break;
- case EJIT_OPERAND_FLT: emit_insn_ad(s, ARG_FI, i, args[i].type, args[i].d); break;
+ case EJIT_OPERAND_GPR:
+ emit_insn_ar(s, EJIT_OP_ARG, i, args[i].type, EJIT_GPR(args[i].r));
+ break;
+
+ case EJIT_OPERAND_FPR:
+ emit_insn_af(s, EJIT_OP_ARG_F, i, args[i].type, EJIT_FPR(args[i].r));
+ break;
+
+ case EJIT_OPERAND_IMM:
+ emit_insn_ai(s, EJIT_OP_ARG_I, i, args[i].type, args[i].r);
+ break;
+
+ case EJIT_OPERAND_FLT:
+ emit_insn_ad(s, EJIT_OP_ARG_FI, i, args[i].type, args[i].d);
+ break;
+
default: abort();
}
}
- emit_insn_op(s, CALLI_F, f);
+ emit_insn_op(s, EJIT_OP_CALLI, f);
}
-void ejit_calli_d(struct ejit_func *s, struct ejit_func *f, size_t argc,
- const struct ejit_operand args[argc])
+static void ejit_callr(struct ejit_func *s, enum ejit_opcode op, struct ejit_gpr target,
+ size_t argc, const struct ejit_operand args[argc])
{
- check_operands(f, argc, args);
+ s->use_64 = op == EJIT_OP_CALLR_L;
+ s->max_args = argc > s->max_args ? argc : s->max_args;
for (size_t i = 0; i < argc; ++i) {
switch (args[i].kind) {
- case EJIT_OPERAND_GPR: emit_insn_ar(s, ARG, i, args[i].type, EJIT_GPR(args[i].r)); break;
- case EJIT_OPERAND_FPR: emit_insn_af(s, ARG_F, i, args[i].type, EJIT_FPR(args[i].r)); break;
- case EJIT_OPERAND_IMM: emit_insn_ai(s, ARG_I, i, args[i].type, args[i].r); break;
- case EJIT_OPERAND_FLT: emit_insn_ad(s, ARG_FI, i, args[i].type, args[i].d); break;
+ case EJIT_OPERAND_GPR:
+ emit_insn_ar(s, EJIT_OP_ARG, i, args[i].type, EJIT_GPR(args[i].r));
+ break;
+
+ case EJIT_OPERAND_FPR:
+ emit_insn_af(s, EJIT_OP_ARG_F, i, args[i].type, EJIT_FPR(args[i].r));
+ break;
+
+ case EJIT_OPERAND_IMM:
+ emit_insn_ai(s, EJIT_OP_ARG_I, i, args[i].type, args[i].r);
+ break;
+
+ case EJIT_OPERAND_FLT:
+ emit_insn_ad(s, EJIT_OP_ARG_FI, i, args[i].type, args[i].d);
+ break;
+
default: abort();
}
}
- emit_insn_op(s, CALLI_D, f);
+ emit_insn_oxr(s, op, target);
}
-void ejit_escapei_i(struct ejit_func *s, ejit_escape_i_t f, size_t argc,
- const struct ejit_operand args[argc])
+void ejit_callr_i(struct ejit_func *s, struct ejit_gpr target,
+ size_t argc, const struct ejit_operand args[argc])
{
- for (size_t i = 0; i < argc; ++i) {
- switch (args[i].kind) {
- case EJIT_OPERAND_GPR: emit_insn_ar(s, ARG, i, args[i].type, EJIT_GPR(args[i].r)); break;
- case EJIT_OPERAND_FPR: emit_insn_af(s, ARG_F, i, args[i].type, EJIT_FPR(args[i].r)); break;
- case EJIT_OPERAND_IMM: emit_insn_ai(s, ARG_I, i, args[i].type, args[i].r); break;
- case EJIT_OPERAND_FLT: emit_insn_ad(s, ARG_FI, i, args[i].type, args[i].d); break;
- default: abort();
- }
- }
+ ejit_callr(s, EJIT_OP_CALLR_I, target, argc, args);
+}
- emit_insn_op(s, ESCAPEI_I, f);
+void ejit_callr_l(struct ejit_func *s, struct ejit_gpr target,
+ size_t argc, const struct ejit_operand args[argc])
+{
+ ejit_callr(s, EJIT_OP_CALLR_L, target, argc, args);
}
-void ejit_escapei_l(struct ejit_func *s, ejit_escape_l_t f, size_t argc,
- const struct ejit_operand args[argc])
+void ejit_callr_f(struct ejit_func *s, struct ejit_gpr target,
+ size_t argc, const struct ejit_operand args[argc])
{
- s->use_64 = true;
- for (size_t i = 0; i < argc; ++i) {
- switch (args[i].kind) {
- case EJIT_OPERAND_GPR: emit_insn_ar(s, ARG, i, args[i].type, EJIT_GPR(args[i].r)); break;
- case EJIT_OPERAND_FPR: emit_insn_af(s, ARG_F, i, args[i].type, EJIT_FPR(args[i].r)); break;
- case EJIT_OPERAND_IMM: emit_insn_ai(s, ARG_I, i, args[i].type, args[i].r); break;
- case EJIT_OPERAND_FLT: emit_insn_ad(s, ARG_FI, i, args[i].type, args[i].d); break;
- default: abort();
- }
- }
+ ejit_callr(s, EJIT_OP_CALLR_F, target, argc, args);
+}
- emit_insn_op(s, ESCAPEI_L, f);
+void ejit_callr_d(struct ejit_func *s, struct ejit_gpr target,
+ size_t argc, const struct ejit_operand args[argc])
+{
+ ejit_callr(s, EJIT_OP_CALLR_D, target, argc, args);
}
-void ejit_escapei_f(struct ejit_func *s, ejit_escape_f_t f, size_t argc,
- const struct ejit_operand args[argc])
+static void ejit_escapei(struct ejit_func *s, enum ejit_opcode op, void *f,
+ size_t argc, const struct ejit_operand args[argc])
{
+ s->use_64 = op == EJIT_OP_ESCAPEI_L;
+ s->max_args = argc > s->max_args ? argc : s->max_args;
for (size_t i = 0; i < argc; ++i) {
switch (args[i].kind) {
- case EJIT_OPERAND_GPR: emit_insn_ar(s, ARG, i, args[i].type, EJIT_GPR(args[i].r)); break;
- case EJIT_OPERAND_FPR: emit_insn_af(s, ARG_F, i, args[i].type, EJIT_FPR(args[i].r)); break;
- case EJIT_OPERAND_IMM: emit_insn_ai(s, ARG_I, i, args[i].type, args[i].r); break;
- case EJIT_OPERAND_FLT: emit_insn_ad(s, ARG_FI, i, args[i].type, args[i].d); break;
+ case EJIT_OPERAND_GPR:
+ emit_insn_ar(s, EJIT_OP_ARG, i, args[i].type, EJIT_GPR(args[i].r));
+ break;
+
+ case EJIT_OPERAND_FPR:
+ emit_insn_af(s, EJIT_OP_ARG_F, i, args[i].type, EJIT_FPR(args[i].r));
+ break;
+
+ case EJIT_OPERAND_IMM:
+ emit_insn_ai(s, EJIT_OP_ARG_I, i, args[i].type, args[i].r);
+ break;
+
+ case EJIT_OPERAND_FLT:
+ emit_insn_ad(s, EJIT_OP_ARG_FI, i, args[i].type, args[i].d);
+ break;
+
default: abort();
}
}
- emit_insn_op(s, ESCAPEI_F, f);
+ emit_insn_op(s, op, f);
}
-void ejit_escapei_d(struct ejit_func *s, ejit_escape_d_t f, size_t argc,
- const struct ejit_operand args[argc])
+void ejit_escapei_i(struct ejit_func *s, ejit_escape_i_t f,
+ size_t argc, const struct ejit_operand args[argc])
{
- for (size_t i = 0; i < argc; ++i) {
- switch (args[i].kind) {
- case EJIT_OPERAND_GPR: emit_insn_ar(s, ARG, i, args[i].type, EJIT_GPR(args[i].r)); break;
- case EJIT_OPERAND_FPR: emit_insn_af(s, ARG_F, i, args[i].type, EJIT_FPR(args[i].r)); break;
- case EJIT_OPERAND_IMM: emit_insn_ai(s, ARG_I, i, args[i].type, args[i].r); break;
- case EJIT_OPERAND_FLT: emit_insn_ad(s, ARG_FI, i, args[i].type, args[i].d); break;
- default: abort();
- }
- }
+ ejit_escapei(s, EJIT_OP_ESCAPEI_I, f, argc, args);
+}
+
+void ejit_escapei_l(struct ejit_func *s, ejit_escape_l_t f,
+ size_t argc, const struct ejit_operand args[argc])
+{
+ ejit_escapei(s, EJIT_OP_ESCAPEI_L, f, argc, args);
+}
- emit_insn_op(s, ESCAPEI_D, f);
+void ejit_escapei_f(struct ejit_func *s, ejit_escape_f_t f,
+ size_t argc, const struct ejit_operand args[argc])
+{
+ ejit_escapei(s, EJIT_OP_ESCAPEI_F, f, argc, args);
+}
+
+void ejit_escapei_d(struct ejit_func *s, ejit_escape_d_t f,
+ size_t argc, const struct ejit_operand args[argc])
+{
+ ejit_escapei(s, EJIT_OP_ESCAPEI_D, f, argc, args);
}
void ejit_retval(struct ejit_func *s, struct ejit_gpr r0)
{
- emit_insn_or(s, RETVAL, r0);
+ emit_insn_or(s, EJIT_OP_RETVAL, r0);
}
void ejit_retval_f(struct ejit_func *s, struct ejit_fpr f0)
{
- emit_insn_of(s, RETVAL_F, f0);
+ emit_insn_of(s, EJIT_OP_RETVAL_F, f0);
}
void ejit_retval_d(struct ejit_func *s, struct ejit_fpr f0)
{
- emit_insn_of(s, RETVAL_D, f0);
+ emit_insn_of(s, EJIT_OP_RETVAL_D, f0);
}
void ejit_sti_8(struct ejit_func *s, struct ejit_gpr r0, void *p)
{
- emit_insn_orp(s, STI8, r0, p);
+ emit_insn_orp(s, EJIT_OP_STI8, r0, p);
}
void ejit_sti_16(struct ejit_func *s, struct ejit_gpr r0, void *p)
{
- emit_insn_orp(s, STI16, r0, p);
+ emit_insn_orp(s, EJIT_OP_STI16, r0, p);
}
void ejit_sti_32(struct ejit_func *s, struct ejit_gpr r0, void *p)
{
- emit_insn_orp(s, STI32, r0, p);
+ emit_insn_orp(s, EJIT_OP_STI32, r0, p);
}
void ejit_sti_64(struct ejit_func *s, struct ejit_gpr r0, void *p)
{
s->use_64 = true;
- emit_insn_orp(s, STI64, r0, p);
+ emit_insn_orp(s, EJIT_OP_STI64, r0, p);
}
void ejit_sti_f(struct ejit_func *s, struct ejit_fpr f0, void *p)
{
- emit_insn_ofp(s, STIF, f0, p);
+ emit_insn_ofp(s, EJIT_OP_STIF, f0, p);
}
void ejit_sti_d(struct ejit_func *s, struct ejit_fpr f0, void *p)
{
- emit_insn_ofp(s, STID, f0, p);
+ emit_insn_ofp(s, EJIT_OP_STID, f0, p);
}
void ejit_stxi_8(struct ejit_func *s, struct ejit_gpr r0, struct ejit_gpr r1,
int64_t o)
{
- emit_insn_orri(s, STXI8, r0, r1, o);
+ emit_insn_orri(s, EJIT_OP_STXI8, r0, r1, o);
}
void ejit_stxi_16(struct ejit_func *s, struct ejit_gpr r0, struct ejit_gpr r1,
int64_t o)
{
- emit_insn_orri(s, STXI16, r0, r1, o);
+ emit_insn_orri(s, EJIT_OP_STXI16, r0, r1, o);
}
void ejit_stxi_32(struct ejit_func *s, struct ejit_gpr r0, struct ejit_gpr r1,
int64_t o)
{
- emit_insn_orri(s, STXI32, r0, r1, o);
+ emit_insn_orri(s, EJIT_OP_STXI32, r0, r1, o);
}
void ejit_stxi_64(struct ejit_func *s, struct ejit_gpr r0, struct ejit_gpr r1,
int64_t o)
{
s->use_64 = true;
- emit_insn_orri(s, STXI64, r0, r1, o);
+ emit_insn_orri(s, EJIT_OP_STXI64, r0, r1, o);
}
void ejit_stxi_f(struct ejit_func *s, struct ejit_fpr f0, struct ejit_gpr r1,
int64_t o)
{
- emit_insn_ofri(s, STXIF, f0, r1, o);
+ emit_insn_ofri(s, EJIT_OP_STXIF, f0, r1, o);
}
void ejit_stxi_d(struct ejit_func *s, struct ejit_fpr f0, struct ejit_gpr r1,
int64_t o)
{
- emit_insn_ofri(s, STXID, f0, r1, o);
+ emit_insn_ofri(s, EJIT_OP_STXID, f0, r1, o);
}
void ejit_stxr_8(struct ejit_func *s, struct ejit_gpr r0, struct ejit_gpr r1,
struct ejit_gpr r2)
{
- emit_insn_orrr(s, STXR8, r0, r1, r2);
+ emit_insn_orrr(s, EJIT_OP_STXR8, r0, r1, r2);
}
void ejit_stxr_16(struct ejit_func *s, struct ejit_gpr r0, struct ejit_gpr r1,
struct ejit_gpr r2)
{
- emit_insn_orrr(s, STXR16, r0, r1, r2);
+ emit_insn_orrr(s, EJIT_OP_STXR16, r0, r1, r2);
}
void ejit_stxr_32(struct ejit_func *s, struct ejit_gpr r0, struct ejit_gpr r1,
struct ejit_gpr r2)
{
- emit_insn_orrr(s, STXR32, r0, r1, r2);
+ emit_insn_orrr(s, EJIT_OP_STXR32, r0, r1, r2);
}
void ejit_stxr_64(struct ejit_func *s, struct ejit_gpr r0, struct ejit_gpr r1,
struct ejit_gpr r2)
{
s->use_64 = true;
- emit_insn_orrr(s, STXR64, r0, r1, r2);
+ emit_insn_orrr(s, EJIT_OP_STXR64, r0, r1, r2);
}
void ejit_stxr_f(struct ejit_func *s, struct ejit_fpr f0, struct ejit_gpr r1,
struct ejit_gpr r2)
{
- emit_insn_ofrr(s, STXRF, f0, r1, r2);
+ emit_insn_ofrr(s, EJIT_OP_STXRF, f0, r1, r2);
}
void ejit_stxr_d(struct ejit_func *s, struct ejit_fpr f0, struct ejit_gpr r1,
struct ejit_gpr r2)
{
- emit_insn_ofrr(s, STXRD, f0, r1, r2);
+ emit_insn_ofrr(s, EJIT_OP_STXRD, f0, r1, r2);
}
void ejit_ldi_i8(struct ejit_func *s, struct ejit_gpr r0, void *p)
{
- emit_insn_orp(s, LDI8, r0, p);
+ emit_insn_orp(s, EJIT_OP_LDI8, r0, p);
}
void ejit_ldi_i16(struct ejit_func *s, struct ejit_gpr r0, void *p)
{
- emit_insn_orp(s, LDI16, r0, p);
+ emit_insn_orp(s, EJIT_OP_LDI16, r0, p);
}
void ejit_ldi_i32(struct ejit_func *s, struct ejit_gpr r0, void *p)
{
- emit_insn_orp(s, LDI32, r0, p);
+ emit_insn_orp(s, EJIT_OP_LDI32, r0, p);
}
void ejit_ldi_i64(struct ejit_func *s, struct ejit_gpr r0, void *p)
{
- emit_insn_orp(s, LDI64, r0, p);
+ emit_insn_orp(s, EJIT_OP_LDI64, r0, p);
}
void ejit_ldi_u8(struct ejit_func *s, struct ejit_gpr r0, void *p)
{
- emit_insn_orp(s, LDIU8, r0, p);
+ emit_insn_orp(s, EJIT_OP_LDIU8, r0, p);
}
void ejit_ldi_u16(struct ejit_func *s, struct ejit_gpr r0, void *p)
{
- emit_insn_orp(s, LDIU16, r0, p);
+ emit_insn_orp(s, EJIT_OP_LDIU16, r0, p);
}
void ejit_ldi_u32(struct ejit_func *s, struct ejit_gpr r0, void *p)
{
s->use_64 = true;
- emit_insn_orp(s, LDIU32, r0, p);
+ emit_insn_orp(s, EJIT_OP_LDIU32, r0, p);
}
void ejit_ldi_u64(struct ejit_func *s, struct ejit_gpr r0, void *p)
{
s->use_64 = true;
- emit_insn_orp(s, LDIU64, r0, p);
+ emit_insn_orp(s, EJIT_OP_LDIU64, r0, p);
}
void ejit_ldi_f(struct ejit_func *s, struct ejit_fpr f0, void *p)
{
- emit_insn_ofp(s, LDIF, f0, p);
+ emit_insn_ofp(s, EJIT_OP_LDIF, f0, p);
}
void ejit_ldi_d(struct ejit_func *s, struct ejit_fpr f0, void *p)
{
- emit_insn_ofp(s, LDID, f0, p);
+ emit_insn_ofp(s, EJIT_OP_LDID, f0, p);
}
void ejit_ldxi_i8(struct ejit_func *s, struct ejit_gpr r0, struct ejit_gpr r1,
int64_t o)
{
- emit_insn_orri(s, LDXI8, r0, r1, o);
+ emit_insn_orri(s, EJIT_OP_LDXI8, r0, r1, o);
}
void ejit_ldxi_i16(struct ejit_func *s, struct ejit_gpr r0, struct ejit_gpr r1,
int64_t o)
{
- emit_insn_orri(s, LDXI16, r0, r1, o);
+ emit_insn_orri(s, EJIT_OP_LDXI16, r0, r1, o);
}
void ejit_ldxi_i32(struct ejit_func *s, struct ejit_gpr r0, struct ejit_gpr r1,
int64_t o)
{
- emit_insn_orri(s, LDXI32, r0, r1, o);
+ emit_insn_orri(s, EJIT_OP_LDXI32, r0, r1, o);
}
void ejit_ldxi_i64(struct ejit_func *s, struct ejit_gpr r0, struct ejit_gpr r1,
int64_t o)
{
- emit_insn_orri(s, LDXI64, r0, r1, o);
+ emit_insn_orri(s, EJIT_OP_LDXI64, r0, r1, o);
}
void ejit_ldxi_u8(struct ejit_func *s, struct ejit_gpr r0, struct ejit_gpr r1,
int64_t o)
{
- emit_insn_orri(s, LDXIU8, r0, r1, o);
+ emit_insn_orri(s, EJIT_OP_LDXIU8, r0, r1, o);
}
void ejit_ldxi_u16(struct ejit_func *s, struct ejit_gpr r0, struct ejit_gpr r1,
int64_t o)
{
- emit_insn_orri(s, LDXIU16, r0, r1, o);
+ emit_insn_orri(s, EJIT_OP_LDXIU16, r0, r1, o);
}
void ejit_ldxi_u32(struct ejit_func *s, struct ejit_gpr r0, struct ejit_gpr r1,
int64_t o)
{
- emit_insn_orri(s, LDXIU32, r0, r1, o);
+ emit_insn_orri(s, EJIT_OP_LDXIU32, r0, r1, o);
}
void ejit_ldxi_u64(struct ejit_func *s, struct ejit_gpr r0, struct ejit_gpr r1,
int64_t o)
{
- emit_insn_orri(s, LDXIU64, r0, r1, o);
+ emit_insn_orri(s, EJIT_OP_LDXIU64, r0, r1, o);
}
void ejit_ldxi_f(struct ejit_func *s, struct ejit_fpr f0, struct ejit_gpr r1,
int64_t o)
{
- emit_insn_ofri(s, LDXIF, f0, r1, o);
+ emit_insn_ofri(s, EJIT_OP_LDXIF, f0, r1, o);
}
void ejit_ldxi_d(struct ejit_func *s, struct ejit_fpr f0, struct ejit_gpr r1,
int64_t o)
{
- emit_insn_ofri(s, LDXID, f0, r1, o);
+ emit_insn_ofri(s, EJIT_OP_LDXID, f0, r1, o);
}
void ejit_ldxr_i8(struct ejit_func *s, struct ejit_gpr r0, struct ejit_gpr r1,
struct ejit_gpr r2)
{
- emit_insn_orrr(s, LDXR8, r0, r1, r2);
+ emit_insn_orrr(s, EJIT_OP_LDXR8, r0, r1, r2);
}
void ejit_ldxr_i16(struct ejit_func *s, struct ejit_gpr r0, struct ejit_gpr r1,
struct ejit_gpr r2)
{
- emit_insn_orrr(s, LDXR16, r0, r1, r2);
+ emit_insn_orrr(s, EJIT_OP_LDXR16, r0, r1, r2);
}
void ejit_ldxr_i32(struct ejit_func *s, struct ejit_gpr r0, struct ejit_gpr r1,
struct ejit_gpr r2)
{
- emit_insn_orrr(s, LDXR32, r0, r1, r2);
+ emit_insn_orrr(s, EJIT_OP_LDXR32, r0, r1, r2);
}
void ejit_ldxr_i64(struct ejit_func *s, struct ejit_gpr r0, struct ejit_gpr r1,
struct ejit_gpr r2)
{
- emit_insn_orrr(s, LDXR64, r0, r1, r2);
+ emit_insn_orrr(s, EJIT_OP_LDXR64, r0, r1, r2);
}
void ejit_ldxr_u8(struct ejit_func *s, struct ejit_gpr r0, struct ejit_gpr r1,
struct ejit_gpr r2)
{
- emit_insn_orrr(s, LDXRU8, r0, r1, r2);
+ emit_insn_orrr(s, EJIT_OP_LDXRU8, r0, r1, r2);
}
void ejit_ldxr_u16(struct ejit_func *s, struct ejit_gpr r0, struct ejit_gpr r1,
struct ejit_gpr r2)
{
- emit_insn_orrr(s, LDXRU16, r0, r1, r2);
+ emit_insn_orrr(s, EJIT_OP_LDXRU16, r0, r1, r2);
}
void ejit_ldxr_u32(struct ejit_func *s, struct ejit_gpr r0, struct ejit_gpr r1,
struct ejit_gpr r2)
{
- emit_insn_orrr(s, LDXRU32, r0, r1, r2);
+ emit_insn_orrr(s, EJIT_OP_LDXRU32, r0, r1, r2);
}
void ejit_ldxr_u64(struct ejit_func *s, struct ejit_gpr r0, struct ejit_gpr r1,
struct ejit_gpr r2)
{
- emit_insn_orrr(s, LDXIU64, r0, r1, r2);
+ emit_insn_orrr(s, EJIT_OP_LDXIU64, r0, r1, r2);
}
void ejit_ldxr_f(struct ejit_func *s, struct ejit_fpr f0, struct ejit_gpr r1,
struct ejit_gpr r2)
{
- emit_insn_ofrr(s, LDXRF, f0, r1, r2);
+ emit_insn_ofrr(s, EJIT_OP_LDXRF, f0, r1, r2);
}
void ejit_ldxr_d(struct ejit_func *s, struct ejit_fpr f0, struct ejit_gpr r1,
struct ejit_gpr r2)
{
- emit_insn_ofrr(s, LDXRD, f0, r1, r2);
+ emit_insn_ofrr(s, EJIT_OP_LDXRD, f0, r1, r2);
}
void ejit_ret(struct ejit_func *s)
{
- emit_insn_o(s, END);
+ emit_insn_o(s, EJIT_OP_END);
}
void ejit_retr(struct ejit_func *s, struct ejit_gpr r0)
{
- emit_insn_oxr(s, RETR, 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)
{
- emit_insn_oxf(s, RETR_F, 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)
{
- emit_insn_oxf(s, RETR_D, 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)
{
- emit_insn_oi(s, RETI, 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)
{
- emit_insn_oF(s, RETI_F, 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)
{
- emit_insn_oD(s, RETI_D, f);
+ assert(s->rtype == EJIT_DOUBLE);
+ emit_insn_oD(s, EJIT_OP_RETI_D, f);
}
void ejit_extr_8(struct ejit_func *s, struct ejit_gpr r0, struct ejit_gpr r1)
{
- emit_insn_orr(s, EXTR8, r0, r1);
+ emit_insn_orr(s, EJIT_OP_EXTR8, r0, r1);
}
void ejit_extr_16(struct ejit_func *s, struct ejit_gpr r0, struct ejit_gpr r1)
{
- emit_insn_orr(s, EXTR16, r0, r1);
+ emit_insn_orr(s, EJIT_OP_EXTR16, r0, r1);
}
void ejit_extr_32(struct ejit_func *s, struct ejit_gpr r0, struct ejit_gpr r1)
{
s->use_64 = true;
- emit_insn_orr(s, EXTR32, r0, r1);
+ emit_insn_orr(s, EJIT_OP_EXTR32, r0, r1);
}
void ejit_extr_u8(struct ejit_func *s, struct ejit_gpr r0, struct ejit_gpr r1)
{
- emit_insn_orr(s, EXTRU8, r0, r1);
+ emit_insn_orr(s, EJIT_OP_EXTRU8, r0, r1);
}
void ejit_extr_u16(struct ejit_func *s, struct ejit_gpr r0, struct ejit_gpr r1)
{
- emit_insn_orr(s, EXTRU16, r0, r1);
+ emit_insn_orr(s, EJIT_OP_EXTRU16, r0, r1);
}
void ejit_extr_u32(struct ejit_func *s, struct ejit_gpr r0, struct ejit_gpr r1)
{
s->use_64 = true;
- emit_insn_orr(s, EXTRU32, r0, r1);
+ emit_insn_orr(s, EJIT_OP_EXTRU32, r0, r1);
}
void ejit_extr_f(struct ejit_func *s, struct ejit_fpr f0, struct ejit_gpr r1)
{
- emit_insn_ofr(s, EXTRF, f0, r1);
+ emit_insn_ofr(s, EJIT_OP_EXTRF, f0, r1);
}
void ejit_extr_d(struct ejit_func *s, struct ejit_fpr f0, struct ejit_gpr r1)
{
- emit_insn_ofr(s, EXTRD, f0, r1);
+ emit_insn_ofr(s, EJIT_OP_EXTRD, f0, r1);
}
void ejit_addr(struct ejit_func *s, struct ejit_gpr r0, struct ejit_gpr r1,
struct ejit_gpr r2)
{
- emit_insn_orrr(s, ADDR, r0, r1, r2);
+ emit_insn_orrr(s, EJIT_OP_ADDR, r0, r1, r2);
}
void ejit_addr_f(struct ejit_func *s, struct ejit_fpr f0, struct ejit_fpr f1,
struct ejit_fpr f2)
{
- emit_insn_offf(s, ADDR_F, f0, f1, f2);
+ emit_insn_offf(s, EJIT_OP_ADDR_F, f0, f1, f2);
}
void ejit_addr_d(struct ejit_func *s, struct ejit_fpr f0, struct ejit_fpr f1,
struct ejit_fpr f2)
{
- emit_insn_offf(s, ADDR_D, f0, f1, f2);
+ emit_insn_offf(s, EJIT_OP_ADDR_D, f0, f1, f2);
}
void ejit_addi(struct ejit_func *s, struct ejit_gpr r0, struct ejit_gpr r1,
int64_t o)
{
- emit_insn_orri(s, ADDI, r0, r1, o);
+ emit_insn_orri(s, EJIT_OP_ADDI, r0, r1, o);
}
void ejit_absr_f(struct ejit_func *s, struct ejit_fpr f0, struct ejit_fpr f1)
{
- emit_insn_off(s, ABSR_F, f0, f1);
+ emit_insn_off(s, EJIT_OP_ABSR_F, f0, f1);
}
void ejit_absr_d(struct ejit_func *s, struct ejit_fpr f0, struct ejit_fpr f1)
{
- emit_insn_off(s, ABSR_D, f0, f1);
+ emit_insn_off(s, EJIT_OP_ABSR_D, f0, f1);
}
void ejit_subr(struct ejit_func *s, struct ejit_gpr r0, struct ejit_gpr r1,
struct ejit_gpr r2)
{
- emit_insn_orrr(s, SUBR, r0, r1, r2);
+ emit_insn_orrr(s, EJIT_OP_SUBR, r0, r1, r2);
}
void ejit_subr_f(struct ejit_func *s, struct ejit_fpr f0, struct ejit_fpr f1,
struct ejit_fpr f2)
{
- emit_insn_offf(s, SUBR_F, f0, f1, f2);
+ emit_insn_offf(s, EJIT_OP_SUBR_F, f0, f1, f2);
}
void ejit_subr_d(struct ejit_func *s, struct ejit_fpr f0, struct ejit_fpr f1,
struct ejit_fpr f2)
{
- emit_insn_offf(s, SUBR_D, f0, f1, f2);
+ emit_insn_offf(s, EJIT_OP_SUBR_D, f0, f1, f2);
}
void ejit_subi(struct ejit_func *s, struct ejit_gpr r0, struct ejit_gpr r1,
int64_t o)
{
- emit_insn_orri(s, SUBI, r0, r1, o);
+ emit_insn_orri(s, EJIT_OP_SUBI, r0, r1, o);
}
void ejit_mulr(struct ejit_func *s, struct ejit_gpr r0, struct ejit_gpr r1,
struct ejit_gpr r2)
{
- emit_insn_orrr(s, MULR, r0, r1, r2);
+ emit_insn_orrr(s, EJIT_OP_MULR, r0, r1, r2);
}
void ejit_mulr_f(struct ejit_func *s, struct ejit_fpr f0, struct ejit_fpr f1,
struct ejit_fpr f2)
{
- emit_insn_offf(s, MULR_F, f0, f1, f2);
+ emit_insn_offf(s, EJIT_OP_MULR_F, f0, f1, f2);
}
void ejit_mulr_d(struct ejit_func *s, struct ejit_fpr f0, struct ejit_fpr f1,
struct ejit_fpr f2)
{
- emit_insn_offf(s, MULR_D, f0, f1, f2);
+ emit_insn_offf(s, EJIT_OP_MULR_D, f0, f1, f2);
}
void ejit_divr(struct ejit_func *s, struct ejit_gpr r0, struct ejit_gpr r1,
struct ejit_gpr r2)
{
- emit_insn_orrr(s, DIVR, r0, r1, r2);
+ emit_insn_orrr(s, EJIT_OP_DIVR, r0, r1, r2);
}
void ejit_divr_u(struct ejit_func *s, struct ejit_gpr r0, struct ejit_gpr r1,
struct ejit_gpr r2)
{
- emit_insn_orrr(s, DIVR_U, r0, r1, r2);
+ emit_insn_orrr(s, EJIT_OP_DIVR_U, r0, r1, r2);
}
void ejit_divr_f(struct ejit_func *s, struct ejit_fpr f0, struct ejit_fpr f1,
struct ejit_fpr f2)
{
- emit_insn_offf(s, DIVR_F, f0, f1, f2);
+ emit_insn_offf(s, EJIT_OP_DIVR_F, f0, f1, f2);
}
void ejit_divr_d(struct ejit_func *s, struct ejit_fpr f0, struct ejit_fpr f1,
struct ejit_fpr f2)
{
- emit_insn_offf(s, DIVR_D, f0, f1, f2);
+ emit_insn_offf(s, EJIT_OP_DIVR_D, f0, f1, f2);
}
void ejit_remr(struct ejit_func *s, struct ejit_gpr r0, struct ejit_gpr r1,
struct ejit_gpr r2)
{
- emit_insn_orrr(s, REMR, r0, r1, r2);
+ emit_insn_orrr(s, EJIT_OP_REMR, r0, r1, r2);
}
void ejit_remr_u(struct ejit_func *s, struct ejit_gpr r0, struct ejit_gpr r1,
struct ejit_gpr r2)
{
- emit_insn_orrr(s, REMR_U, r0, r1, r2);
+ emit_insn_orrr(s, EJIT_OP_REMR_U, r0, r1, r2);
}
void ejit_lshi(struct ejit_func *s, struct ejit_gpr r0, struct ejit_gpr r1,
int64_t o)
{
- emit_insn_orri(s, LSHI, r0, r1, o);
+ emit_insn_orri(s, EJIT_OP_LSHI, r0, r1, o);
}
void ejit_lshr(struct ejit_func *s, struct ejit_gpr r0, struct ejit_gpr r1,
struct ejit_gpr r2)
{
- emit_insn_orrr(s, LSHR, r0, r1, r2);
+ emit_insn_orrr(s, EJIT_OP_LSHR, r0, r1, r2);
}
void ejit_rshi(struct ejit_func *s, struct ejit_gpr r0, struct ejit_gpr r1,
int64_t o)
{
- emit_insn_orri(s, RSHI, r0, r1, o);
+ emit_insn_orri(s, EJIT_OP_RSHI, r0, r1, o);
}
void ejit_rshi_u(struct ejit_func *s, struct ejit_gpr r0, struct ejit_gpr r1,
int64_t o)
{
- emit_insn_orri(s, RSHI_U, r0, r1, o);
+ emit_insn_orri(s, EJIT_OP_RSHI_U, r0, r1, o);
}
void ejit_rshr(struct ejit_func *s, struct ejit_gpr r0, struct ejit_gpr r1,
struct ejit_gpr r2)
{
- emit_insn_orrr(s, RSHR, r0, r1, r2);
+ emit_insn_orrr(s, EJIT_OP_RSHR, r0, r1, r2);
}
void ejit_rshr_u(struct ejit_func *s, struct ejit_gpr r0, struct ejit_gpr r1,
struct ejit_gpr r2)
{
- emit_insn_orrr(s, RSHR_U, r0, r1, r2);
+ emit_insn_orrr(s, EJIT_OP_RSHR_U, r0, r1, r2);
}
void ejit_andr(struct ejit_func *s, struct ejit_gpr r0, struct ejit_gpr r1,
struct ejit_gpr r2)
{
- emit_insn_orrr(s, ANDR, r0, r1, r2);
+ emit_insn_orrr(s, EJIT_OP_ANDR, r0, r1, r2);
}
void ejit_andi(struct ejit_func *s, struct ejit_gpr r0, struct ejit_gpr r1,
int64_t o)
{
- emit_insn_orri(s, ANDI, r0, r1, o);
+ emit_insn_orri(s, EJIT_OP_ANDI, r0, r1, o);
}
void ejit_orr(struct ejit_func *s, struct ejit_gpr r0, struct ejit_gpr r1,
struct ejit_gpr r2)
{
- emit_insn_orrr(s, ORR, r0, r1, r2);
+ emit_insn_orrr(s, EJIT_OP_ORR, r0, r1, r2);
}
void ejit_ori(struct ejit_func *s, struct ejit_gpr r0, struct ejit_gpr r1,
int64_t o)
{
- emit_insn_orri(s, ORI, r0, r1, o);
+ emit_insn_orri(s, EJIT_OP_ORI, r0, r1, o);
}
void ejit_xorr(struct ejit_func *s, struct ejit_gpr r0, struct ejit_gpr r1,
struct ejit_gpr r2)
{
- emit_insn_orrr(s, XORR, r0, r1, r2);
+ emit_insn_orrr(s, EJIT_OP_XORR, r0, r1, r2);
}
void ejit_xori(struct ejit_func *s, struct ejit_gpr r0, struct ejit_gpr r1,
int64_t o)
{
- emit_insn_orri(s, XORI, r0, r1, o);
+ emit_insn_orri(s, EJIT_OP_XORI, r0, r1, o);
}
void ejit_comr(struct ejit_func *s, struct ejit_gpr r0, struct ejit_gpr r1)
{
- emit_insn_orr(s, COMR, r0, r1);
+ emit_insn_orr(s, EJIT_OP_COMR, r0, r1);
}
void ejit_negr(struct ejit_func *s, struct ejit_gpr r0, struct ejit_gpr r1)
{
- emit_insn_orr(s, NEGR, r0, r1);
+ emit_insn_orr(s, EJIT_OP_NEGR, r0, r1);
}
void ejit_negr_f(struct ejit_func *s, struct ejit_fpr f0, struct ejit_fpr f1)
{
- emit_insn_off(s, NEGR_F, f0, f1);
+ emit_insn_off(s, EJIT_OP_NEGR_F, f0, f1);
}
void ejit_negr_d(struct ejit_func *s, struct ejit_fpr f0, struct ejit_fpr f1)
{
- emit_insn_off(s, NEGR_D, f0, f1);
+ emit_insn_off(s, EJIT_OP_NEGR_D, f0, f1);
}
void ejit_movi(struct ejit_func *s, struct ejit_gpr r0, int64_t o)
{
- emit_insn_ori(s, MOVI, r0, o);
+ emit_insn_ori(s, EJIT_OP_MOVI, r0, o);
}
void ejit_movi_f(struct ejit_func *s, struct ejit_fpr f0, float o)
{
- emit_insn_ofF(s, MOVI_F, f0, o);
+ emit_insn_ofF(s, EJIT_OP_MOVI_F, f0, o);
}
void ejit_movi_d(struct ejit_func *s, struct ejit_fpr f0, double o)
{
- emit_insn_ofD(s, MOVI_D, f0, o);
+ emit_insn_ofD(s, EJIT_OP_MOVI_D, f0, o);
}
void ejit_movr(struct ejit_func *s, struct ejit_gpr r0, struct ejit_gpr r1)
@@ -1176,7 +1276,7 @@ void ejit_movr(struct ejit_func *s, struct ejit_gpr r0, struct ejit_gpr r1)
if (r0.r == r1.r)
return;
- emit_insn_orr(s, MOVR, r0, r1);
+ emit_insn_orr(s, EJIT_OP_MOVR, r0, r1);
}
void ejit_movr_f(struct ejit_func *s, struct ejit_fpr f0, struct ejit_fpr f1)
@@ -1184,7 +1284,7 @@ void ejit_movr_f(struct ejit_func *s, struct ejit_fpr f0, struct ejit_fpr f1)
if (f0.f == f1.f)
return;
- emit_insn_off(s, MOVR_F, f0, f1);
+ emit_insn_off(s, EJIT_OP_MOVR_F, f0, f1);
}
void ejit_movr_d(struct ejit_func *s, struct ejit_fpr f0, struct ejit_fpr f1)
@@ -1192,179 +1292,209 @@ void ejit_movr_d(struct ejit_func *s, struct ejit_fpr f0, struct ejit_fpr f1)
if (f0.f == f1.f)
return;
- emit_insn_off(s, MOVR_D, f0, f1);
+ emit_insn_off(s, EJIT_OP_MOVR_D, f0, f1);
}
void ejit_eqr(struct ejit_func *s, struct ejit_gpr r0, struct ejit_gpr r1,
struct ejit_gpr r2)
{
- emit_insn_orrr(s, EQR, r0, r1, r2);
+ emit_insn_orrr(s, EJIT_OP_EQR, r0, r1, r2);
}
void ejit_eqr_f(struct ejit_func *s, struct ejit_gpr r0, struct ejit_fpr f1,
struct ejit_fpr f2)
{
- emit_insn_orff(s, EQR_F, r0, f1, f2);
+ emit_insn_orff(s, EJIT_OP_EQR_F, r0, f1, f2);
}
void ejit_eqr_d(struct ejit_func *s, struct ejit_gpr r0, struct ejit_fpr f1,
struct ejit_fpr f2)
{
- emit_insn_orff(s, EQR_D, r0, f1, f2);
+ emit_insn_orff(s, EJIT_OP_EQR_D, r0, f1, f2);
}
void ejit_ner(struct ejit_func *s, struct ejit_gpr r0, struct ejit_gpr r1,
struct ejit_gpr r2)
{
- emit_insn_orrr(s, NER, r0, r1, r2);
+ emit_insn_orrr(s, EJIT_OP_NER, r0, r1, r2);
}
void ejit_ner_f(struct ejit_func *s, struct ejit_gpr r0, struct ejit_fpr f1,
struct ejit_fpr f2)
{
- emit_insn_orff(s, NER_F, r0, f1, f2);
+ emit_insn_orff(s, EJIT_OP_NER_F, r0, f1, f2);
}
void ejit_ner_d(struct ejit_func *s, struct ejit_gpr r0, struct ejit_fpr f1,
struct ejit_fpr f2)
{
- emit_insn_orff(s, NER_D, r0, f1, f2);
+ emit_insn_orff(s, EJIT_OP_NER_D, r0, f1, f2);
}
void ejit_gtr(struct ejit_func *s, struct ejit_gpr r0, struct ejit_gpr r1,
struct ejit_gpr r2)
{
- emit_insn_orrr(s, GTR, r0, r1, r2);
+ emit_insn_orrr(s, EJIT_OP_GTR, r0, r1, r2);
}
void ejit_gtr_u(struct ejit_func *s, struct ejit_gpr r0, struct ejit_gpr r1,
struct ejit_gpr r2)
{
- emit_insn_orrr(s, GTR_U, r0, r1, r2);
+ emit_insn_orrr(s, EJIT_OP_GTR_U, r0, r1, r2);
}
void ejit_gtr_f(struct ejit_func *s, struct ejit_gpr r0, struct ejit_fpr f1,
struct ejit_fpr f2)
{
- emit_insn_orff(s, GTR_F, r0, f1, f2);
+ emit_insn_orff(s, EJIT_OP_GTR_F, r0, f1, f2);
}
void ejit_gtr_d(struct ejit_func *s, struct ejit_gpr r0, struct ejit_fpr f1,
struct ejit_fpr f2)
{
- emit_insn_orff(s, GTR_D, r0, f1, f2);
+ emit_insn_orff(s, EJIT_OP_GTR_D, r0, f1, f2);
}
void ejit_ltr(struct ejit_func *s, struct ejit_gpr r0, struct ejit_gpr r1,
struct ejit_gpr r2)
{
- emit_insn_orrr(s, GTR, r0, r2, r1);
+ emit_insn_orrr(s, EJIT_OP_GTR, r0, r2, r1);
}
void ejit_ltr_u(struct ejit_func *s, struct ejit_gpr r0, struct ejit_gpr r1,
struct ejit_gpr r2)
{
- emit_insn_orrr(s, GTR_U, r0, r2, r1);
+ emit_insn_orrr(s, EJIT_OP_GTR_U, r0, r2, r1);
}
void ejit_ltr_f(struct ejit_func *s, struct ejit_gpr r0, struct ejit_fpr f1,
struct ejit_fpr f2)
{
- emit_insn_orff(s, GTR_F, r0, f2, f1);
+ emit_insn_orff(s, EJIT_OP_GTR_F, r0, f2, f1);
}
void ejit_ltr_d(struct ejit_func *s, struct ejit_gpr r0, struct ejit_fpr f1,
struct ejit_fpr f2)
{
- emit_insn_orff(s, GTR_D, r0, f2, f1);
+ emit_insn_orff(s, EJIT_OP_GTR_D, r0, f2, f1);
}
void ejit_ger(struct ejit_func *s, struct ejit_gpr r0, struct ejit_gpr r1,
struct ejit_gpr r2)
{
- emit_insn_orrr(s, GER, r0, r1, r2);
+ emit_insn_orrr(s, EJIT_OP_GER, r0, r1, r2);
}
void ejit_ger_u(struct ejit_func *s, struct ejit_gpr r0, struct ejit_gpr r1,
struct ejit_gpr r2)
{
- emit_insn_orrr(s, GER_U, r0, r1, r2);
+ emit_insn_orrr(s, EJIT_OP_GER_U, r0, r1, r2);
}
void ejit_ger_f(struct ejit_func *s, struct ejit_gpr r0, struct ejit_fpr f1,
struct ejit_fpr f2)
{
- emit_insn_orff(s, GER_F, r0, f1, f2);
+ emit_insn_orff(s, EJIT_OP_GER_F, r0, f1, f2);
}
void ejit_ger_d(struct ejit_func *s, struct ejit_gpr r0, struct ejit_fpr f1,
struct ejit_fpr f2)
{
- emit_insn_orff(s, GER_D, r0, f1, f2);
+ emit_insn_orff(s, EJIT_OP_GER_D, r0, f1, f2);
}
void ejit_ler(struct ejit_func *s, struct ejit_gpr r0, struct ejit_gpr r1,
struct ejit_gpr r2)
{
- emit_insn_orrr(s, GER, r0, r2, r1);
+ emit_insn_orrr(s, EJIT_OP_GER, r0, r2, r1);
}
void ejit_ler_u(struct ejit_func *s, struct ejit_gpr r0, struct ejit_gpr r1,
struct ejit_gpr r2)
{
- emit_insn_orrr(s, GER_U, r0, r2, r1);
+ emit_insn_orrr(s, EJIT_OP_GER_U, r0, r2, r1);
}
void ejit_ler_f(struct ejit_func *s, struct ejit_gpr r0, struct ejit_fpr f1,
struct ejit_fpr f2)
{
- emit_insn_orff(s, GER_F, r0, f2, f1);
+ emit_insn_orff(s, EJIT_OP_GER_F, r0, f2, f1);
}
void ejit_ler_d(struct ejit_func *s, struct ejit_gpr r0, struct ejit_fpr f1,
struct ejit_fpr f2)
{
- emit_insn_orff(s, GER_D, r0, f2, f1);
+ emit_insn_orff(s, EJIT_OP_GER_D, r0, f2, f1);
}
void ejit_truncr_d_32(struct ejit_func *s, struct ejit_gpr r0,
struct ejit_fpr f1)
{
- emit_insn_orf(s, TRUNCR_D_32, r0, f1);
+ emit_insn_orf(s, EJIT_OP_TRUNCR_D_32, r0, f1);
}
void ejit_truncr_d_64(struct ejit_func *s, struct ejit_gpr r0,
struct ejit_fpr f1)
{
s->use_64 = true;
- emit_insn_orf(s, TRUNCR_D_64, r0, f1);
+ emit_insn_orf(s, EJIT_OP_TRUNCR_D_64, r0, f1);
}
void ejit_truncr_f_32(struct ejit_func *s, struct ejit_gpr r0,
struct ejit_fpr f1)
{
- emit_insn_orf(s, TRUNCR_F_32, r0, f1);
+ emit_insn_orf(s, EJIT_OP_TRUNCR_F_32, r0, f1);
}
void ejit_truncr_f_64(struct ejit_func *s, struct ejit_gpr r0,
struct ejit_fpr f1)
{
s->use_64 = true;
- emit_insn_orf(s, TRUNCR_F_64, r0, f1);
+ emit_insn_orf(s, EJIT_OP_TRUNCR_F_64, r0, f1);
+}
+
+void ejit_sqrtr_f(struct ejit_func *s, struct ejit_fpr r0, struct ejit_fpr r1)
+{
+ emit_insn_off(s, EJIT_OP_SQRTR_F, r0, r1);
+}
+
+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)
{
size_t addr = insns_len(&s->insns);
- emit_insn_oxrr(s, BNER, r0, r1);
+ emit_insn_oxrr(s, EJIT_OP_BNER, r0, r1);
return (struct ejit_reloc){.insn = addr};
}
struct ejit_reloc ejit_bnei(struct ejit_func *s, struct ejit_gpr r0, int64_t o)
{
size_t addr = insns_len(&s->insns);
- emit_insn_oxri(s, BNEI, r0, o);
+ emit_insn_oxri(s, EJIT_OP_BNEI, r0, o);
return (struct ejit_reloc){.insn = addr};
}
@@ -1372,7 +1502,7 @@ struct ejit_reloc ejit_bner_f(struct ejit_func *s, struct ejit_fpr f0,
struct ejit_fpr f1)
{
size_t addr = insns_len(&s->insns);
- emit_insn_oxff(s, BNER_F, f0, f1);
+ emit_insn_oxff(s, EJIT_OP_BNER_F, f0, f1);
return (struct ejit_reloc){.insn = addr};
}
@@ -1380,7 +1510,7 @@ struct ejit_reloc ejit_bner_d(struct ejit_func *s, struct ejit_fpr f0,
struct ejit_fpr f1)
{
size_t addr = insns_len(&s->insns);
- emit_insn_oxff(s, BNER_D, f0, f1);
+ emit_insn_oxff(s, EJIT_OP_BNER_D, f0, f1);
return (struct ejit_reloc){.insn = addr};
}
@@ -1388,14 +1518,14 @@ struct ejit_reloc ejit_beqr(struct ejit_func *s, struct ejit_gpr r0,
struct ejit_gpr r1)
{
size_t addr = insns_len(&s->insns);
- emit_insn_oxrr(s, BEQR, r0, r1);
+ emit_insn_oxrr(s, EJIT_OP_BEQR, r0, r1);
return (struct ejit_reloc){.insn = addr};
}
struct ejit_reloc ejit_beqi(struct ejit_func *s, struct ejit_gpr r0, int64_t o)
{
size_t addr = insns_len(&s->insns);
- emit_insn_oxri(s, BEQI, r0, o);
+ emit_insn_oxri(s, EJIT_OP_BEQI, r0, o);
return (struct ejit_reloc){.insn = addr};
}
@@ -1403,7 +1533,7 @@ struct ejit_reloc ejit_beqr_f(struct ejit_func *s, struct ejit_fpr f0,
struct ejit_fpr f1)
{
size_t addr = insns_len(&s->insns);
- emit_insn_oxff(s, BEQR_F, f0, f1);
+ emit_insn_oxff(s, EJIT_OP_BEQR_F, f0, f1);
return (struct ejit_reloc){.insn = addr};
}
@@ -1411,7 +1541,7 @@ struct ejit_reloc ejit_beqr_d(struct ejit_func *s, struct ejit_fpr f0,
struct ejit_fpr f1)
{
size_t addr = insns_len(&s->insns);
- emit_insn_oxff(s, BEQR_D, f0, f1);
+ emit_insn_oxff(s, EJIT_OP_BEQR_D, f0, f1);
return (struct ejit_reloc){.insn = addr};
}
@@ -1419,7 +1549,7 @@ struct ejit_reloc ejit_bger(struct ejit_func *s, struct ejit_gpr r0,
struct ejit_gpr r1)
{
size_t addr = insns_len(&s->insns);
- emit_insn_oxrr(s, BGER, r0, r1);
+ emit_insn_oxrr(s, EJIT_OP_BGER, r0, r1);
return (struct ejit_reloc){.insn = addr};
}
@@ -1427,7 +1557,7 @@ struct ejit_reloc ejit_bger_u(struct ejit_func *s, struct ejit_gpr r0,
struct ejit_gpr r1)
{
size_t addr = insns_len(&s->insns);
- emit_insn_oxrr(s, BGER_U, r0, r1);
+ emit_insn_oxrr(s, EJIT_OP_BGER_U, r0, r1);
return (struct ejit_reloc){.insn = addr};
}
@@ -1435,7 +1565,7 @@ struct ejit_reloc ejit_bger_f(struct ejit_func *s, struct ejit_fpr f0,
struct ejit_fpr f1)
{
size_t addr = insns_len(&s->insns);
- emit_insn_oxff(s, BGER_F, f0, f1);
+ emit_insn_oxff(s, EJIT_OP_BGER_F, f0, f1);
return (struct ejit_reloc){.insn = addr};
}
@@ -1443,14 +1573,14 @@ struct ejit_reloc ejit_bger_d(struct ejit_func *s, struct ejit_fpr f0,
struct ejit_fpr f1)
{
size_t addr = insns_len(&s->insns);
- emit_insn_oxff(s, BGER_D, f0, f1);
+ emit_insn_oxff(s, EJIT_OP_BGER_D, f0, f1);
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 = insns_len(&s->insns);
- emit_insn_oxri(s, BGEI, r0, o);
+ emit_insn_oxri(s, EJIT_OP_BGEI, r0, o);
return (struct ejit_reloc){.insn = addr};
}
@@ -1458,7 +1588,7 @@ struct ejit_reloc ejit_bgei_u(struct ejit_func *s, struct ejit_gpr r0,
int64_t o)
{
size_t addr = insns_len(&s->insns);
- emit_insn_oxri(s, BGEI_U, r0, o);
+ emit_insn_oxri(s, EJIT_OP_BGEI_U, r0, o);
return (struct ejit_reloc){.insn = addr};
}
@@ -1466,7 +1596,7 @@ struct ejit_reloc ejit_bler(struct ejit_func *s, struct ejit_gpr r0,
struct ejit_gpr r1)
{
size_t addr = insns_len(&s->insns);
- emit_insn_oxrr(s, BGER, r1, r0);
+ emit_insn_oxrr(s, EJIT_OP_BGER, r1, r0);
return (struct ejit_reloc){.insn = addr};
}
@@ -1474,7 +1604,7 @@ struct ejit_reloc ejit_bler_u(struct ejit_func *s, struct ejit_gpr r0,
struct ejit_gpr r1)
{
size_t addr = insns_len(&s->insns);
- emit_insn_oxrr(s, BGER_U, r1, r0);
+ emit_insn_oxrr(s, EJIT_OP_BGER_U, r1, r0);
return (struct ejit_reloc){.insn = addr};
}
@@ -1482,7 +1612,7 @@ struct ejit_reloc ejit_bler_f(struct ejit_func *s, struct ejit_fpr f0,
struct ejit_fpr f1)
{
size_t addr = insns_len(&s->insns);
- emit_insn_oxff(s, BGER_F, f1, f0);
+ emit_insn_oxff(s, EJIT_OP_BGER_F, f1, f0);
return (struct ejit_reloc){.insn = addr};
}
@@ -1490,14 +1620,14 @@ struct ejit_reloc ejit_bler_d(struct ejit_func *s, struct ejit_fpr f0,
struct ejit_fpr f1)
{
size_t addr = insns_len(&s->insns);
- emit_insn_oxff(s, BGER_D, f1, f0);
+ emit_insn_oxff(s, EJIT_OP_BGER_D, f1, f0);
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 = insns_len(&s->insns);
- emit_insn_oxri(s, BLEI, r0, o);
+ emit_insn_oxri(s, EJIT_OP_BLEI, r0, o);
return (struct ejit_reloc){.insn = addr};
}
@@ -1505,14 +1635,14 @@ struct ejit_reloc ejit_blei_u(struct ejit_func *s, struct ejit_gpr r0,
int64_t o)
{
size_t addr = insns_len(&s->insns);
- emit_insn_oxri(s, BLEI_U, r0, o);
+ emit_insn_oxri(s, EJIT_OP_BLEI_U, r0, 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 = insns_len(&s->insns);
- emit_insn_oxri(s, BGTI, r0, o);
+ emit_insn_oxri(s, EJIT_OP_BGTI, r0, o);
return (struct ejit_reloc){.insn = addr};
}
@@ -1520,7 +1650,7 @@ struct ejit_reloc ejit_bgti_u(struct ejit_func *s, struct ejit_gpr r0,
int64_t o)
{
size_t addr = insns_len(&s->insns);
- emit_insn_oxri(s, BGTI_U, r0, o);
+ emit_insn_oxri(s, EJIT_OP_BGTI_U, r0, o);
return (struct ejit_reloc){.insn = addr};
}
@@ -1528,7 +1658,7 @@ struct ejit_reloc ejit_bgtr(struct ejit_func *s, struct ejit_gpr r0,
struct ejit_gpr r1)
{
size_t addr = insns_len(&s->insns);
- emit_insn_oxrr(s, BGTR, r0, r1);
+ emit_insn_oxrr(s, EJIT_OP_BGTR, r0, r1);
return (struct ejit_reloc){.insn = addr};
}
@@ -1536,7 +1666,7 @@ struct ejit_reloc ejit_bgtr_u(struct ejit_func *s, struct ejit_gpr r0,
struct ejit_gpr r1)
{
size_t addr = insns_len(&s->insns);
- emit_insn_oxrr(s, BGTR_U, r0, r1);
+ emit_insn_oxrr(s, EJIT_OP_BGTR_U, r0, r1);
return (struct ejit_reloc){.insn = addr};
}
@@ -1544,7 +1674,7 @@ struct ejit_reloc ejit_bgtr_f(struct ejit_func *s, struct ejit_fpr f0,
struct ejit_fpr f1)
{
size_t addr = insns_len(&s->insns);
- emit_insn_oxff(s, BGTR_F, f0, f1);
+ emit_insn_oxff(s, EJIT_OP_BGTR_F, f0, f1);
return (struct ejit_reloc){.insn = addr};
}
@@ -1552,7 +1682,7 @@ struct ejit_reloc ejit_bgtr_d(struct ejit_func *s, struct ejit_fpr f0,
struct ejit_fpr f1)
{
size_t addr = insns_len(&s->insns);
- emit_insn_oxff(s, BGTR_D, f0, f1);
+ emit_insn_oxff(s, EJIT_OP_BGTR_D, f0, f1);
return (struct ejit_reloc){.insn = addr};
}
@@ -1560,7 +1690,7 @@ struct ejit_reloc ejit_bltr(struct ejit_func *s, struct ejit_gpr r0,
struct ejit_gpr r1)
{
size_t addr = insns_len(&s->insns);
- emit_insn_oxrr(s, BGTR, r1, r0);
+ emit_insn_oxrr(s, EJIT_OP_BGTR, r1, r0);
return (struct ejit_reloc){.insn = addr};
}
@@ -1568,7 +1698,7 @@ struct ejit_reloc ejit_bltr_u(struct ejit_func *s, struct ejit_gpr r0,
struct ejit_gpr r1)
{
size_t addr = insns_len(&s->insns);
- emit_insn_oxrr(s, BGTR_U, r1, r0);
+ emit_insn_oxrr(s, EJIT_OP_BGTR_U, r1, r0);
return (struct ejit_reloc){.insn = addr};
}
@@ -1576,7 +1706,7 @@ struct ejit_reloc ejit_bltr_f(struct ejit_func *s, struct ejit_fpr f0,
struct ejit_fpr f1)
{
size_t addr = insns_len(&s->insns);
- emit_insn_oxff(s, BGTR_F, f1, f0);
+ emit_insn_oxff(s, EJIT_OP_BGTR_F, f1, f0);
return (struct ejit_reloc){.insn = addr};
}
@@ -1584,14 +1714,14 @@ struct ejit_reloc ejit_bltr_d(struct ejit_func *s, struct ejit_fpr f0,
struct ejit_fpr f1)
{
size_t addr = insns_len(&s->insns);
- emit_insn_oxff(s, BGTR_D, f1, f0);
+ emit_insn_oxff(s, EJIT_OP_BGTR_D, f1, f0);
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 = insns_len(&s->insns);
- emit_insn_oxri(s, BLTI, r0, o);
+ emit_insn_oxri(s, EJIT_OP_BLTI, r0, o);
return (struct ejit_reloc){.insn = addr};
}
@@ -1599,28 +1729,28 @@ struct ejit_reloc ejit_blti_u(struct ejit_func *s, struct ejit_gpr r0,
int64_t o)
{
size_t addr = insns_len(&s->insns);
- emit_insn_oxri(s, BLTI_U, r0, o);
+ emit_insn_oxri(s, EJIT_OP_BLTI_U, r0, o);
return (struct ejit_reloc){.insn = addr};
}
struct ejit_reloc ejit_jmp(struct ejit_func *s)
{
size_t addr = insns_len(&s->insns);
- emit_insn_o(s, JMP);
+ emit_insn_o(s, EJIT_OP_JMP);
return (struct ejit_reloc){.insn = addr};
}
struct ejit_reloc ejit_jmpr(struct ejit_func *s, struct ejit_gpr r0)
{
size_t addr = insns_len(&s->insns);
- emit_insn_oxr(s, JMPR, r0);
+ emit_insn_oxr(s, EJIT_OP_JMPR, r0);
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 = insns_len(&s->insns);
- emit_insn_oxri(s, BMCI, r0, o);
+ emit_insn_oxri(s, EJIT_OP_BMCI, r0, o);
return (struct ejit_reloc){.insn = addr};
}
@@ -1628,14 +1758,14 @@ struct ejit_reloc ejit_bmcr(struct ejit_func *s, struct ejit_gpr r0,
struct ejit_gpr r1)
{
size_t addr = insns_len(&s->insns);
- emit_insn_oxrr(s, BMCR, r0, r1);
+ emit_insn_oxrr(s, EJIT_OP_BMCR, r0, r1);
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 = insns_len(&s->insns);
- emit_insn_oxri(s, BMSI, r0, o);
+ emit_insn_oxri(s, EJIT_OP_BMSI, r0, o);
return (struct ejit_reloc){.insn = addr};
}
@@ -1643,27 +1773,12 @@ struct ejit_reloc ejit_bmsr(struct ejit_func *s, struct ejit_gpr r0,
struct ejit_gpr r1)
{
size_t addr = insns_len(&s->insns);
- emit_insn_oxrr(s, BMSR, r0, r1);
+ emit_insn_oxrr(s, EJIT_OP_BMSR, r0, r1);
return (struct ejit_reloc){.insn = addr};
}
-static struct interp_state create_interp_state()
-{
- struct interp_state state;
- state.gprs = gprs_create();
- state.fprs = fprs_create();
- state.args = args_create();
- return state;
-}
-
-static void destroy_interp_state(struct interp_state state)
-{
- gprs_destroy(&state.gprs);
- fprs_destroy(&state.fprs);
- args_destroy(&state.args);
-}
-
-long ejit_run_func_ctx_i(struct ejit_func *f, size_t argc, struct ejit_arg args[argc], struct interp_state *ctx)
+long ejit_run_func_i(struct ejit_func *f, size_t argc,
+ struct ejit_arg args[argc])
{
check_args(f, argc, args);
assert((f->rtype == EJIT_VOID || ejit_int_type(f->rtype))
@@ -1672,64 +1787,29 @@ long ejit_run_func_ctx_i(struct ejit_func *f, size_t argc, struct ejit_arg args[
#endif
);
- return ejit_run(f, argc, args, ctx, true, NULL).i;
+ return ejit_run(f, argc, args, NULL).i;
}
-long ejit_run_func_i(struct ejit_func *f, size_t argc,
+int64_t ejit_run_func_l(struct ejit_func *f, size_t argc,
struct ejit_arg args[argc])
{
- struct interp_state state = create_interp_state();
- long r = ejit_run_func_ctx_i(f, argc, args, &state);
- destroy_interp_state(state);
- return r;
-}
-
-int64_t ejit_run_func_ctx_l(struct ejit_func *f, size_t argc, struct ejit_arg args[argc], struct interp_state *ctx)
-{
check_args(f, argc, args);
assert(f->rtype == EJIT_INT64 || f->rtype == EJIT_UINT64);
- return ejit_run(f, argc, args, ctx, true, NULL).i;
-}
-
-int64_t ejit_run_func_l(struct ejit_func *f, size_t argc,
- struct ejit_arg args[argc])
-{
- struct interp_state state = create_interp_state();
- int64_t r = ejit_run_func_ctx_l(f, argc, args, &state);
- destroy_interp_state(state);
- return r;
+ return ejit_run(f, argc, args, NULL).i;
}
-float ejit_run_func_ctx_f(struct ejit_func *f, size_t argc, struct ejit_arg args[argc], struct interp_state *ctx)
+float ejit_run_func_f(struct ejit_func *f, size_t argc, struct ejit_arg args[argc])
{
check_args(f, argc, args);
assert(f->rtype == EJIT_FLOAT);
- return ejit_run(f, argc, args, ctx, true, NULL).f;
+ return ejit_run(f, argc, args, NULL).f;
}
-float ejit_run_func_f(struct ejit_func *f, size_t argc,
- struct ejit_arg args[argc])
-{
- struct interp_state state = create_interp_state();
- float r = ejit_run_func_ctx_f(f, argc, args, &state);
- destroy_interp_state(state);
- return r;
-}
-
-double ejit_run_func_ctx_d(struct ejit_func *f, size_t argc, struct ejit_arg args[argc], struct interp_state *ctx)
+double ejit_run_func_d(struct ejit_func *f, size_t argc, struct ejit_arg args[argc])
{
check_args(f, argc, args);
assert(f->rtype == EJIT_DOUBLE);
- return ejit_run(f, argc, args, ctx, true, NULL).f;
-}
-
-double ejit_run_func_d(struct ejit_func *f, size_t argc,
- struct ejit_arg args[argc])
-{
- struct interp_state state = create_interp_state();
- double r = ejit_run_func_ctx_d(f, argc, args, &state);
- destroy_interp_state(state);
- return r;
+ return ejit_run(f, argc, args, NULL).f;
}
struct ejit_arg ejit_run_func(struct ejit_func *f, size_t argc, struct ejit_arg args[argc])
@@ -1748,6 +1828,10 @@ struct ejit_arg ejit_run_func(struct ejit_func *f, size_t argc, struct ejit_arg
};
case EJIT_UINT64:
+ return (struct ejit_arg){
+ .u64 = ejit_run_func_l(f, argc, args),
+ .type = f->rtype
+ };
case EJIT_INT64:
return (struct ejit_arg){
.i64 = ejit_run_func_l(f, argc, args),
@@ -1756,7 +1840,7 @@ struct ejit_arg ejit_run_func(struct ejit_func *f, size_t argc, struct ejit_arg
default:
return (struct ejit_arg){
- .i64 = ejit_run_func_i(f, argc, args),
+ .l = ejit_run_func_i(f, argc, args),
.type = f->rtype
};
}
diff --git a/src/interp.c b/src/interp.c
index f8ba927..894be30 100644
--- a/src/interp.c
+++ b/src/interp.c
@@ -5,262 +5,270 @@
/* this is the body of a given ejit_interp function, it assumes there's an
* external int64_t retval and double retval_f into which it places the value to
* be returned. Included from src/interp.c */
-union interp_ret ejit_run(struct ejit_func *f, size_t argc, struct ejit_arg args[argc], struct interp_state *state, bool run, void ***labels_wb)
+union interp_ret ejit_run(struct ejit_func *f, size_t paramc, struct ejit_arg params[paramc], void ***labels_wb)
{
- static void *labels[OPCODE_COUNT] = {
- [MOVI] = &&MOVI,
- [MOVI_F] = &&MOVI_F,
- [MOVI_D] = &&MOVI_D,
- [MOVR] = &&MOVR,
- [MOVR_F] = &&MOVR_F,
- [MOVR_D] = &&MOVR_D,
-
- [EXTR8] = &&EXTR8,
- [EXTR16] = &&EXTR16,
- [EXTR32] = &&EXTR32,
- [EXTRU8] = &&EXTRU8,
- [EXTRU16] = &&EXTRU16,
- [EXTRU32] = &&EXTRU32,
- [EXTRF] = &&EXTRF,
- [EXTRD] = &&EXTRD,
-
- [ADDR] = &&ADDR,
- [ADDR_F] = &&ADDR_F,
- [ADDR_D] = &&ADDR_D,
- [ADDI] = &&ADDI,
-
- [ABSR_F] = &&ABSR_F,
- [ABSR_D] = &&ABSR_D,
-
- [SUBR] = &&SUBR,
- [SUBR_F] = &&SUBR_F,
- [SUBR_D] = &&SUBR_D,
- [SUBI] = &&SUBI,
-
- [MULR] = &&MULR,
- [MULR_F] = &&MULR_F,
- [MULR_D] = &&MULR_D,
-
- [DIVR] = &&DIVR,
- [DIVR_U] = &&DIVR_U,
- [DIVR_F] = &&DIVR_F,
- [DIVR_D] = &&DIVR_D,
-
- [REMR] = &&REMR,
- [REMR_U] = &&REMR_U,
-
- [LSHI] = &&LSHI,
- [LSHR] = &&LSHR,
- [RSHI] = &&RSHI,
- [RSHR] = &&RSHR,
- [RSHI_U] = &&RSHI_U,
- [RSHR_U] = &&RSHR_U,
-
- [ANDR] = &&ANDR,
- [ANDI] = &&ANDI,
-
- [ORR] = &&ORR,
- [ORI] = &&ORI,
-
- [XORR] = &&XORR,
- [XORI] = &&XORI,
-
- [COMR] = &&COMR,
- [NEGR] = &&NEGR,
- [NEGR_F] = &&NEGR_F,
- [NEGR_D] = &&NEGR_D,
-
- [EQR] = &&EQR,
- [EQR_F] = &&EQR_F,
- [EQR_D] = &&EQR_D,
-
- [NER] = &&NER,
- [NER_F] = &&NER_F,
- [NER_D] = &&NER_D,
-
- [GTR] = &&GTR,
- [GTR_U] = &&GTR_U,
- [GTR_F] = &&GTR_F,
- [GTR_D] = &&GTR_D,
-
- [GER] = &&GER,
- [GER_U] = &&GER_U,
- [GER_F] = &&GER_F,
- [GER_D] = &&GER_D,
-
- [STI8] = &&STI8,
- [STI16] = &&STI16,
- [STI32] = &&STI32,
- [STI64] = &&STI64,
- [STIF] = &&STIF,
- [STID] = &&STID,
-
- [STXI8] = &&STXI8,
- [STXI16] = &&STXI16,
- [STXI32] = &&STXI32,
- [STXI64] = &&STXI64,
- [STXIF] = &&STXIF,
- [STXID] = &&STXID,
-
- [STXR8] = &&STXR8,
- [STXR16] = &&STXR16,
- [STXR32] = &&STXR32,
- [STXR64] = &&STXR64,
- [STXRF] = &&STXRF,
- [STXRD] = &&STXRD,
-
- [LDI8] = &&LDI8,
- [LDI16] = &&LDI16,
- [LDI32] = &&LDI32,
- [LDI64] = &&LDI64,
- [LDIU8] = &&LDIU8,
- [LDIU16] = &&LDIU16,
- [LDIU32] = &&LDIU32,
- [LDIU64] = &&LDIU64,
- [LDIF] = &&LDIF,
- [LDID] = &&LDID,
-
- [LDXI8] = &&LDXI8,
- [LDXI16] = &&LDXI16,
- [LDXI32] = &&LDXI32,
- [LDXI64] = &&LDXI64,
- [LDXIU8] = &&LDXIU8,
- [LDXIU16] = &&LDXIU16,
- [LDXIU32] = &&LDXIU32,
- [LDXIU64] = &&LDXIU64,
- [LDXIF] = &&LDXIF,
- [LDXID] = &&LDXID,
-
- [LDXR8] = &&LDXR8,
- [LDXR16] = &&LDXR16,
- [LDXR32] = &&LDXR32,
- [LDXR64] = &&LDXR64,
- [LDXRU8] = &&LDXRU8,
- [LDXRU16] = &&LDXRU16,
- [LDXRU32] = &&LDXRU32,
- [LDXRU64] = &&LDXRU64,
- [LDXRF] = &&LDXRF,
- [LDXRD] = &&LDXRD,
-
- [TRUNCR_D_32] = &&TRUNCR_D_32,
- [TRUNCR_D_64] = &&TRUNCR_D_64,
- [TRUNCR_F_32] = &&TRUNCR_F_32,
- [TRUNCR_F_64] = &&TRUNCR_F_64,
-
- [BNER] = &&BNER,
- [BNEI] = &&BNEI,
- [BNER_F] = &&BNER_F,
- [BNER_D] = &&BNER_D,
-
- [BEQR] = &&BEQR,
- [BEQI] = &&BEQI,
- [BEQR_F] = &&BEQR_F,
- [BEQR_D] = &&BEQR_D,
-
- [BGER] = &&BGER,
- [BGER_U] = &&BGER_U,
- [BGEI] = &&BGEI,
- [BGEI_U] = &&BGEI_U,
- [BGER_F] = &&BGER_F,
- [BGER_D] = &&BGER_D,
-
- [BLEI] = &&BLEI,
- [BLEI_U] = &&BLEI_U,
-
- [BGTR] = &&BGTR,
- [BGTR_U] = &&BGTR_U,
- [BGTI] = &&BGTI,
- [BGTI_U] = &&BGTI_U,
- [BGTR_F] = &&BGTR_F,
- [BGTR_D] = &&BGTR_D,
-
- [BLTI] = &&BLTI,
- [BLTI_U] = &&BLTI_U,
-
- [JMP] = &&JMP,
- [JMPR] = &&JMPR,
-
- [BMCI] = &&BMCI,
- [BMCR] = &&BMCR,
- [BMSI] = &&BMSI,
- [BMSR] = &&BMSR,
-
- [RETR] = &&RETR,
- [RETI] = &&RETI,
- [RETR_F] = &&RETR_F,
- [RETI_F] = &&RETI_F,
- [RETR_D] = &&RETR_D,
- [RETI_D] = &&RETI_D,
-
- [RETVAL] = &&RETVAL,
- [RETVAL_F] = &&RETVAL_F,
- [RETVAL_D] = &&RETVAL_D,
-
- [ARG] = &&ARG,
- [ARG_I] = &&ARG_I,
- [ARG_F] = &&ARG_F,
- [ARG_FI] = &&ARG_FI,
-
- [PARAM] = &&PARAM,
- [PARAM_F] = &&PARAM_F,
-
- [CALLI_I] = &&CALLI_I,
- [CALLI_L] = &&CALLI_L,
- [CALLI_F] = &&CALLI_F,
- [CALLI_D] = &&CALLI_D,
- [ESCAPEI_I] = &&ESCAPEI_I,
- [ESCAPEI_F] = &&ESCAPEI_F,
- [ESCAPEI_L] = &&ESCAPEI_L,
- [ESCAPEI_D] = &&ESCAPEI_D,
-
- [START] = &&START,
- [END] = &&END,
+ static void *labels[EJIT_OPCODE_COUNT] = {
+ [EJIT_OP_MOVI] = &&MOVI,
+ [EJIT_OP_MOVI_F] = &&MOVI_F,
+ [EJIT_OP_MOVI_D] = &&MOVI_D,
+ [EJIT_OP_MOVR] = &&MOVR,
+ [EJIT_OP_MOVR_F] = &&MOVR_F,
+ [EJIT_OP_MOVR_D] = &&MOVR_D,
+
+ [EJIT_OP_EXTR8] = &&EXTR8,
+ [EJIT_OP_EXTR16] = &&EXTR16,
+ [EJIT_OP_EXTR32] = &&EXTR32,
+ [EJIT_OP_EXTRU8] = &&EXTRU8,
+ [EJIT_OP_EXTRU16] = &&EXTRU16,
+ [EJIT_OP_EXTRU32] = &&EXTRU32,
+ [EJIT_OP_EXTRF] = &&EXTRF,
+ [EJIT_OP_EXTRD] = &&EXTRD,
+
+ [EJIT_OP_ADDR] = &&ADDR,
+ [EJIT_OP_ADDR_F] = &&ADDR_F,
+ [EJIT_OP_ADDR_D] = &&ADDR_D,
+ [EJIT_OP_ADDI] = &&ADDI,
+
+ [EJIT_OP_ABSR_F] = &&ABSR_F,
+ [EJIT_OP_ABSR_D] = &&ABSR_D,
+
+ [EJIT_OP_SUBR] = &&SUBR,
+ [EJIT_OP_SUBR_F] = &&SUBR_F,
+ [EJIT_OP_SUBR_D] = &&SUBR_D,
+ [EJIT_OP_SUBI] = &&SUBI,
+
+ [EJIT_OP_MULR] = &&MULR,
+ [EJIT_OP_MULR_F] = &&MULR_F,
+ [EJIT_OP_MULR_D] = &&MULR_D,
+
+ [EJIT_OP_DIVR] = &&DIVR,
+ [EJIT_OP_DIVR_U] = &&DIVR_U,
+ [EJIT_OP_DIVR_F] = &&DIVR_F,
+ [EJIT_OP_DIVR_D] = &&DIVR_D,
+
+ [EJIT_OP_REMR] = &&REMR,
+ [EJIT_OP_REMR_U] = &&REMR_U,
+
+ [EJIT_OP_LSHI] = &&LSHI,
+ [EJIT_OP_LSHR] = &&LSHR,
+ [EJIT_OP_RSHI] = &&RSHI,
+ [EJIT_OP_RSHR] = &&RSHR,
+ [EJIT_OP_RSHI_U] = &&RSHI_U,
+ [EJIT_OP_RSHR_U] = &&RSHR_U,
+
+ [EJIT_OP_ANDR] = &&ANDR,
+ [EJIT_OP_ANDI] = &&ANDI,
+
+ [EJIT_OP_ORR] = &&ORR,
+ [EJIT_OP_ORI] = &&ORI,
+
+ [EJIT_OP_XORR] = &&XORR,
+ [EJIT_OP_XORI] = &&XORI,
+
+ [EJIT_OP_COMR] = &&COMR,
+ [EJIT_OP_NEGR] = &&NEGR,
+ [EJIT_OP_NEGR_F] = &&NEGR_F,
+ [EJIT_OP_NEGR_D] = &&NEGR_D,
+
+ [EJIT_OP_EQR] = &&EQR,
+ [EJIT_OP_EQR_F] = &&EQR_F,
+ [EJIT_OP_EQR_D] = &&EQR_D,
+
+ [EJIT_OP_NER] = &&NER,
+ [EJIT_OP_NER_F] = &&NER_F,
+ [EJIT_OP_NER_D] = &&NER_D,
+
+ [EJIT_OP_GTR] = &&GTR,
+ [EJIT_OP_GTR_U] = &&GTR_U,
+ [EJIT_OP_GTR_F] = &&GTR_F,
+ [EJIT_OP_GTR_D] = &&GTR_D,
+
+ [EJIT_OP_GER] = &&GER,
+ [EJIT_OP_GER_U] = &&GER_U,
+ [EJIT_OP_GER_F] = &&GER_F,
+ [EJIT_OP_GER_D] = &&GER_D,
+
+ [EJIT_OP_STI8] = &&STI8,
+ [EJIT_OP_STI16] = &&STI16,
+ [EJIT_OP_STI32] = &&STI32,
+ [EJIT_OP_STI64] = &&STI64,
+ [EJIT_OP_STIF] = &&STIF,
+ [EJIT_OP_STID] = &&STID,
+
+ [EJIT_OP_STXI8] = &&STXI8,
+ [EJIT_OP_STXI16] = &&STXI16,
+ [EJIT_OP_STXI32] = &&STXI32,
+ [EJIT_OP_STXI64] = &&STXI64,
+ [EJIT_OP_STXIF] = &&STXIF,
+ [EJIT_OP_STXID] = &&STXID,
+
+ [EJIT_OP_STXR8] = &&STXR8,
+ [EJIT_OP_STXR16] = &&STXR16,
+ [EJIT_OP_STXR32] = &&STXR32,
+ [EJIT_OP_STXR64] = &&STXR64,
+ [EJIT_OP_STXRF] = &&STXRF,
+ [EJIT_OP_STXRD] = &&STXRD,
+
+ [EJIT_OP_LDI8] = &&LDI8,
+ [EJIT_OP_LDI16] = &&LDI16,
+ [EJIT_OP_LDI32] = &&LDI32,
+ [EJIT_OP_LDI64] = &&LDI64,
+ [EJIT_OP_LDIU8] = &&LDIU8,
+ [EJIT_OP_LDIU16] = &&LDIU16,
+ [EJIT_OP_LDIU32] = &&LDIU32,
+ [EJIT_OP_LDIU64] = &&LDIU64,
+ [EJIT_OP_LDIF] = &&LDIF,
+ [EJIT_OP_LDID] = &&LDID,
+
+ [EJIT_OP_LDXI8] = &&LDXI8,
+ [EJIT_OP_LDXI16] = &&LDXI16,
+ [EJIT_OP_LDXI32] = &&LDXI32,
+ [EJIT_OP_LDXI64] = &&LDXI64,
+ [EJIT_OP_LDXIU8] = &&LDXIU8,
+ [EJIT_OP_LDXIU16] = &&LDXIU16,
+ [EJIT_OP_LDXIU32] = &&LDXIU32,
+ [EJIT_OP_LDXIU64] = &&LDXIU64,
+ [EJIT_OP_LDXIF] = &&LDXIF,
+ [EJIT_OP_LDXID] = &&LDXID,
+
+ [EJIT_OP_LDXR8] = &&LDXR8,
+ [EJIT_OP_LDXR16] = &&LDXR16,
+ [EJIT_OP_LDXR32] = &&LDXR32,
+ [EJIT_OP_LDXR64] = &&LDXR64,
+ [EJIT_OP_LDXRU8] = &&LDXRU8,
+ [EJIT_OP_LDXRU16] = &&LDXRU16,
+ [EJIT_OP_LDXRU32] = &&LDXRU32,
+ [EJIT_OP_LDXRU64] = &&LDXRU64,
+ [EJIT_OP_LDXRF] = &&LDXRF,
+ [EJIT_OP_LDXRD] = &&LDXRD,
+
+ [EJIT_OP_TRUNCR_D_32] = &&TRUNCR_D_32,
+ [EJIT_OP_TRUNCR_D_64] = &&TRUNCR_D_64,
+ [EJIT_OP_TRUNCR_F_32] = &&TRUNCR_F_32,
+ [EJIT_OP_TRUNCR_F_64] = &&TRUNCR_F_64,
+
+ [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,
+ [EJIT_OP_BNER_D] = &&BNER_D,
+
+ [EJIT_OP_BEQR] = &&BEQR,
+ [EJIT_OP_BEQI] = &&BEQI,
+ [EJIT_OP_BEQR_F] = &&BEQR_F,
+ [EJIT_OP_BEQR_D] = &&BEQR_D,
+
+ [EJIT_OP_BGER] = &&BGER,
+ [EJIT_OP_BGER_U] = &&BGER_U,
+ [EJIT_OP_BGEI] = &&BGEI,
+ [EJIT_OP_BGEI_U] = &&BGEI_U,
+ [EJIT_OP_BGER_F] = &&BGER_F,
+ [EJIT_OP_BGER_D] = &&BGER_D,
+
+ [EJIT_OP_BLEI] = &&BLEI,
+ [EJIT_OP_BLEI_U] = &&BLEI_U,
+
+ [EJIT_OP_BGTR] = &&BGTR,
+ [EJIT_OP_BGTR_U] = &&BGTR_U,
+ [EJIT_OP_BGTI] = &&BGTI,
+ [EJIT_OP_BGTI_U] = &&BGTI_U,
+ [EJIT_OP_BGTR_F] = &&BGTR_F,
+ [EJIT_OP_BGTR_D] = &&BGTR_D,
+
+ [EJIT_OP_BLTI] = &&BLTI,
+ [EJIT_OP_BLTI_U] = &&BLTI_U,
+
+ [EJIT_OP_JMP] = &&JMP,
+ [EJIT_OP_JMPR] = &&JMPR,
+
+ [EJIT_OP_BMCI] = &&BMCI,
+ [EJIT_OP_BMCR] = &&BMCR,
+ [EJIT_OP_BMSI] = &&BMSI,
+ [EJIT_OP_BMSR] = &&BMSR,
+
+ [EJIT_OP_RETR] = &&RETR,
+ [EJIT_OP_RETI] = &&RETI,
+ [EJIT_OP_RETR_F] = &&RETR_F,
+ [EJIT_OP_RETI_F] = &&RETI_F,
+ [EJIT_OP_RETR_D] = &&RETR_D,
+ [EJIT_OP_RETI_D] = &&RETI_D,
+
+ [EJIT_OP_RETVAL] = &&RETVAL,
+ [EJIT_OP_RETVAL_F] = &&RETVAL_F,
+ [EJIT_OP_RETVAL_D] = &&RETVAL_D,
+
+ [EJIT_OP_ARG] = &&ARG,
+ [EJIT_OP_ARG_I] = &&ARG_I,
+ [EJIT_OP_ARG_F] = &&ARG_F,
+ [EJIT_OP_ARG_FI] = &&ARG_FI,
+
+ [EJIT_OP_PARAM] = &&PARAM,
+ [EJIT_OP_PARAM_F] = &&PARAM_F,
+
+ [EJIT_OP_CALLR_I] = &&CALLR_I,
+ [EJIT_OP_CALLR_L] = &&CALLR_L,
+ [EJIT_OP_CALLR_F] = &&CALLR_F,
+ [EJIT_OP_CALLR_D] = &&CALLR_D,
+ [EJIT_OP_CALLI] = &&CALLI,
+
+ [EJIT_OP_TAILR] = &&TAILR,
+ [EJIT_OP_TAILI] = &&TAILI,
+
+ [EJIT_OP_ESCAPEI_I] = &&ESCAPEI_I,
+ [EJIT_OP_ESCAPEI_L] = &&ESCAPEI_L,
+ [EJIT_OP_ESCAPEI_F] = &&ESCAPEI_F,
+ [EJIT_OP_ESCAPEI_D] = &&ESCAPEI_D,
+
+ [EJIT_OP_START] = &&START,
+ [EJIT_OP_END] = &&END,
};
- if (!run) {
+ if (labels_wb) {
*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)(argc, args)
+ .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)(argc, args)
+ .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)(argc, args)
+ .f = ((ejit_escape_f_t)f->extern_call)(paramc, params)
};
return (union interp_ret){
- .i = ((ejit_escape_i_t)f->arena)(argc, args)
+ .i = ((ejit_escape_i_t)f->extern_call)(paramc, params)
};
}
- int64_t retval = 0; double retval_f = 0.0;
-
- size_t prev_gprs = gprs_len(&state->gprs);
- size_t prev_fprs = fprs_len(&state->fprs);
- size_t prev_argc = args_len(&state->args);
-
- gprs_reserve(&state->gprs, prev_gprs + gpr_stats_len(&f->gpr));
- fprs_reserve(&state->fprs, prev_fprs + fpr_stats_len(&f->fpr));
-
+top:
+ union interp_ret retval = {.i = 0};
union fpr {
double d;
float f;
};
- int64_t *gpr = ((int64_t *)state->gprs.buf) + prev_gprs;
- union fpr *fpr = ((union fpr *)state->fprs.buf) + prev_fprs;
+ size_t argc = 0;
+ 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,
@@ -278,7 +286,7 @@ union interp_ret ejit_run(struct ejit_func *f, size_t argc, struct ejit_arg args
DISPATCH();
DO(END);
- goto zero_out;
+ return (union interp_ret){.i = 0};
DISPATCH();
DO(MOVI);
@@ -789,6 +797,30 @@ union interp_ret ejit_run(struct ejit_func *f, size_t argc, struct ejit_arg args
gpr[i.r0] = (int64_t)fpr[i.r1].f;
DISPATCH();
+ DO(SQRTR_F);
+ 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();
+
DO(BNER);
if (gpr[i.r1] != gpr[i.r2])
JUMP(i.r0);
@@ -966,37 +998,48 @@ union interp_ret ejit_run(struct ejit_func *f, size_t argc, struct ejit_arg args
DISPATCH();
DO(RETVAL);
- gpr[i.r0] = retval;
+ gpr[i.r0] = retval.i;
DISPATCH();
DO(RETVAL_F);
- fpr[i.r0].f = retval_f;
+ fpr[i.r0].f = retval.f;
DISPATCH();
DO(RETVAL_D);
- fpr[i.r0].d = retval_f;
+ fpr[i.r0].d = retval.f;
DISPATCH();
DO(PARAM);
- gpr[i.r2] = args[i.r0].u64;
+ switch (i.r1) {
+ case EJIT_INT8: gpr[i.r2] = params[i.r0].i8; break;
+ case EJIT_INT16: gpr[i.r2] = params[i.r0].i16; break;
+ case EJIT_INT32: gpr[i.r2] = params[i.r0].i32; break;
+ case EJIT_INT64: gpr[i.r2] = params[i.r0].i64; break;
+ case EJIT_UINT8: gpr[i.r2] = params[i.r0].u8; break;
+ case EJIT_UINT16: gpr[i.r2] = params[i.r0].u16; break;
+ case EJIT_UINT32: gpr[i.r2] = params[i.r0].u32; break;
+ case EJIT_UINT64: gpr[i.r2] = params[i.r0].u64; break;
+ case EJIT_POINTER: gpr[i.r2] = (int64_t)params[i.r0].p; break;
+ default: abort();
+ }
DISPATCH();
DO(PARAM_F);
if (i.r1 == EJIT_FLOAT)
- fpr[i.r2].f = args[i.r0].f;
+ fpr[i.r2].f = params[i.r0].f;
else
- fpr[i.r2].d = args[i.r0].d;
+ fpr[i.r2].d = params[i.r0].d;
DISPATCH();
DO(ARG);
struct ejit_arg a = ejit_build_arg(i.r1, gpr[i.r2]);
- args_append(&state->args, a);
+ args[argc++] = a;
DISPATCH();
DO(ARG_I);
struct ejit_arg a = ejit_build_arg(i.r1, i.o);
- args_append(&state->args, a);
+ args[argc++] = a;
DISPATCH();
DO(ARG_F);
@@ -1006,7 +1049,7 @@ union interp_ret ejit_run(struct ejit_func *f, size_t argc, struct ejit_arg args
else
a = ejit_build_arg_f(i.r1, fpr[i.r2].f);
- args_append(&state->args, a);
+ args[argc++] = a;
DISPATCH();
DO(ARG_FI);
@@ -1014,145 +1057,111 @@ union interp_ret ejit_run(struct ejit_func *f, size_t argc, struct ejit_arg args
if (i.r1 == EJIT_DOUBLE)
a = ejit_build_arg_f(i.r1, i.d);
else
- a = ejit_build_arg_f(i.r1, i.f);
+ a = ejit_build_arg_f(i.r1, i.d);
- args_append(&state->args, a);
+ args[argc++] = a;
DISPATCH();
- DO(CALLI_I);
- struct ejit_func *f = i.p;
- size_t argc = args_len(&state->args) - prev_argc;
- struct ejit_arg *args = state->args.buf + prev_argc;
+ DO(TAILI);
+ f = (struct ejit_func *)i.p;
+
+ assert(!f->direct_call && "trying to interpret compiled fun");
- retval = ejit_run(f, argc, args, state, true, NULL).i;
+ paramc = argc;
+ for (size_t i = 0; i < argc; ++i)
+ params[i] = args[i];
- gpr = state->gprs.buf + prev_gprs;
- fpr = (union fpr *)state->fprs.buf + prev_fprs;
- args_shrink(&state->args, prev_argc);
+ goto top;
DISPATCH();
- DO(CALLI_L);
- struct ejit_func *f = i.p;
- size_t argc = args_len(&state->args) - prev_argc;
- struct ejit_arg *args = state->args.buf + prev_argc;
+ DO(TAILR);
+ f = (struct ejit_func *)gpr[i.r1];
- retval = ejit_run(f, argc, args, state, true, NULL).i;
+ /** @todo we could potentially just interpret the func as a fallback
+ * instead of aborting here, but this is good enough for now */
+ assert(!f->direct_call && "trying to interpret compiled fun");
- gpr = state->gprs.buf + prev_gprs;
- fpr = (union fpr *)state->fprs.buf + prev_fprs;
- args_shrink(&state->args, prev_argc);
- DISPATCH();
+ paramc = argc;
+ for (size_t i = 0; i < argc; ++i)
+ params[i] = args[i];
- DO(CALLI_F);
- struct ejit_func *f = i.p;
- size_t argc = args_len(&state->args) - prev_argc;
- struct ejit_arg *args = state->args.buf + prev_argc;
+ goto top;
+ DISPATCH();
- retval_f = ejit_run(f, argc, args, state, true, NULL).f;
+ DO(CALLR_I);
+ retval = ejit_run((struct ejit_func *)gpr[i.r1], argc, args, NULL);
+ argc = 0;
+ DISPATCH();
- gpr = state->gprs.buf + prev_gprs;
- fpr = (union fpr *)state->fprs.buf + prev_fprs;
- args_shrink(&state->args, prev_argc);
+ DO(CALLR_L);
+ retval = ejit_run((struct ejit_func *)gpr[i.r1], argc, args, NULL);
+ argc = 0;
DISPATCH();
- DO(CALLI_D);
- struct ejit_func *f = i.p;
- size_t argc = args_len(&state->args) - prev_argc;
- struct ejit_arg *args = state->args.buf + prev_argc;
+ DO(CALLR_F);
+ retval = ejit_run((struct ejit_func *)gpr[i.r1], argc, args, NULL);
+ argc = 0;
+ DISPATCH();
- retval_f = ejit_run(f, argc, args, state, true, NULL).f;
+ DO(CALLR_D);
+ retval = ejit_run((struct ejit_func *)gpr[i.r1], argc, args, NULL);
+ argc = 0;
+ DISPATCH();
- gpr = state->gprs.buf + prev_gprs;
- fpr = (union fpr *)state->fprs.buf + prev_fprs;
- args_shrink(&state->args, prev_argc);
+ DO(CALLI);
+ retval = ejit_run((struct ejit_func *)i.p, argc, args, NULL);
+ argc = 0;
DISPATCH();
DO(ESCAPEI_I);
- ejit_escape_i_t f = i.p;
- size_t argc = args_len(&state->args) - prev_argc;
- struct ejit_arg *args = state->args.buf + prev_argc;
-
- retval = f(argc, args);
-
- args_shrink(&state->args, prev_argc);
+ retval.i = ((ejit_escape_i_t)i.p)(argc, args);
+ argc = 0;
DISPATCH();
DO(ESCAPEI_L);
- ejit_escape_l_t f = i.p;
- size_t argc = args_len(&state->args) - prev_argc;
- struct ejit_arg *args = state->args.buf + prev_argc;
-
- retval = f(argc, args);
-
- args_shrink(&state->args, prev_argc);
+ retval.i = ((ejit_escape_l_t)i.p)(argc, args);
+ argc = 0;
DISPATCH();
DO(ESCAPEI_F);
- ejit_escape_f_t f = i.p;
- size_t argc = args_len(&state->args) - prev_argc;
- struct ejit_arg *args = state->args.buf + prev_argc;
-
- retval_f = f(argc, args);
-
- args_shrink(&state->args, prev_argc);
+ retval.f = ((ejit_escape_f_t)i.p)(argc, args);
+ argc = 0;
DISPATCH();
DO(ESCAPEI_D);
- ejit_escape_d_t f = i.p;
- size_t argc = args_len(&state->args) - prev_argc;
- struct ejit_arg *args = state->args.buf + prev_argc;
-
- retval_f = f(argc, args);
-
- args_shrink(&state->args, prev_argc);
+ retval.f = ((ejit_escape_d_t)i.p)(argc, args);
+ argc = 0;
DISPATCH();
/* 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:
- gprs_shrink(&state->gprs, prev_gprs);
- fprs_shrink(&state->fprs, prev_fprs);
- return (union interp_ret){.f = retval_f};
-
-out_int:
- gprs_shrink(&state->gprs, prev_gprs);
- fprs_shrink(&state->fprs, prev_fprs);
- return (union interp_ret){.i = retval};
-
-zero_out:
return (union interp_ret){.i = 0};
}
diff --git a/tests/calli.c b/tests/calli.c
new file mode 100644
index 0000000..991e97d
--- /dev/null
+++ b/tests/calli.c
@@ -0,0 +1,41 @@
+#include <ejit/ejit.h>
+#include <assert.h>
+#include "do_jit.h"
+
+struct ejit_func *compile(bool do_jit)
+{
+ struct ejit_operand operands[2] = {
+ EJIT_OPERAND_GPR(0, EJIT_TYPE(long)),
+ EJIT_OPERAND_GPR(1, EJIT_TYPE(long))
+ };
+ struct ejit_func *f = ejit_create_func(EJIT_TYPE(long), 2, operands);
+ ejit_addr(f, EJIT_GPR(0), EJIT_GPR(0), EJIT_GPR(1));
+ ejit_retr(f, EJIT_GPR(0));
+ ejit_select_compile_func(f, 2, 0, EJIT_USE64(long), do_jit, true);
+ return f;
+}
+
+int main(int argc, char *argv[])
+{
+ (void)argv;
+ bool do_jit = argc > 1;
+ struct ejit_func *target = compile(do_jit);
+
+ struct ejit_operand operands[2] = {
+ EJIT_OPERAND_GPR(0, EJIT_TYPE(long)),
+ EJIT_OPERAND_GPR(1, EJIT_TYPE(long))
+ };
+
+ struct ejit_func *f = ejit_create_func(EJIT_TYPE(long), 2, operands);
+ ejit_calli(f, target, 2, operands);
+ ejit_retval(f, EJIT_GPR(0));
+ ejit_retr(f, EJIT_GPR(0));
+ ejit_select_compile_func(f, 2, 0, EJIT_USE64(long), do_jit, true);
+
+ assert(erfi2(f,
+ EJIT_ARG(42, long),
+ EJIT_ARG(69, long)) == 111);
+
+ ejit_destroy_func(target);
+ ejit_destroy_func(f);
+}
diff --git a/tests/callr_i.c b/tests/callr_i.c
new file mode 100644
index 0000000..00b5374
--- /dev/null
+++ b/tests/callr_i.c
@@ -0,0 +1,42 @@
+#include <ejit/ejit.h>
+#include <assert.h>
+#include "do_jit.h"
+
+struct ejit_func *compile(bool do_jit)
+{
+ struct ejit_operand operands[2] = {
+ EJIT_OPERAND_GPR(0, EJIT_TYPE(long)),
+ EJIT_OPERAND_GPR(1, EJIT_TYPE(long))
+ };
+ struct ejit_func *f = ejit_create_func(EJIT_TYPE(long), 2, operands);
+ ejit_addr(f, EJIT_GPR(0), EJIT_GPR(0), EJIT_GPR(1));
+ ejit_retr(f, EJIT_GPR(0));
+ ejit_select_compile_func(f, 2, 0, EJIT_USE64(long), do_jit, true);
+ return f;
+}
+
+int main(int argc, char *argv[])
+{
+ (void)argv;
+ bool do_jit = argc > 1;
+ struct ejit_func *target = compile(do_jit);
+
+ struct ejit_operand operands[2] = {
+ EJIT_OPERAND_GPR(0, EJIT_TYPE(long)),
+ EJIT_OPERAND_GPR(1, EJIT_TYPE(long))
+ };
+
+ struct ejit_func *f = ejit_create_func(EJIT_TYPE(long), 2, operands);
+ ejit_movi(f, EJIT_GPR(2), (uintptr_t)target);
+ ejit_callr_i(f, EJIT_GPR(2), 2, operands);
+ ejit_retval(f, EJIT_GPR(0));
+ ejit_retr(f, EJIT_GPR(0));
+ ejit_select_compile_func(f, 3, 0, EJIT_USE64(long), do_jit, true);
+
+ assert(erfi2(f,
+ EJIT_ARG(42, long),
+ EJIT_ARG(69, long)) == 111);
+
+ ejit_destroy_func(target);
+ ejit_destroy_func(f);
+}
diff --git a/tests/escapei_10.c b/tests/escapei_10.c
index 4ae00b8..ec48df0 100644
--- a/tests/escapei_10.c
+++ b/tests/escapei_10.c
@@ -21,26 +21,16 @@ static int32_t func(int32_t a, int32_t b, int32_t c, int32_t d, int32_t e,
static long escape_func(size_t argc, const struct ejit_arg args[argc])
{
assert(argc == 10);
- assert(args[0].type == EJIT_INT32);
- assert(args[1].type == EJIT_INT32);
- assert(args[3].type == EJIT_INT32);
- assert(args[4].type == EJIT_INT32);
- assert(args[5].type == EJIT_INT32);
- assert(args[6].type == EJIT_INT32);
- assert(args[7].type == EJIT_INT32);
- assert(args[8].type == EJIT_INT32);
- assert(args[9].type == EJIT_INT32);
-
- int32_t a = args[0].i32;
- int32_t b = args[1].i32;
- int32_t c = args[2].i32;
- int32_t d = args[3].i32;
- int32_t e = args[4].i32;
- int32_t f = args[5].i32;
- int32_t g = args[6].i32;
- int32_t h = args[7].i32;
- int32_t i = args[8].i32;
- int32_t j = args[9].i32;
+ int32_t a = EJIT_PARAM(argc, args, 0, int32_t);
+ int32_t b = EJIT_PARAM(argc, args, 1, int32_t);
+ int32_t c = EJIT_PARAM(argc, args, 2, int32_t);
+ int32_t d = EJIT_PARAM(argc, args, 3, int32_t);
+ int32_t e = EJIT_PARAM(argc, args, 4, int32_t);
+ int32_t f = EJIT_PARAM(argc, args, 5, int32_t);
+ int32_t g = EJIT_PARAM(argc, args, 6, int32_t);
+ int32_t h = EJIT_PARAM(argc, args, 7, int32_t);
+ int32_t i = EJIT_PARAM(argc, args, 8, int32_t);
+ int32_t j = EJIT_PARAM(argc, args, 9, int32_t);
return func(a, b, c, d, e, f, g, h, i, j);
}
diff --git a/tests/escapei_double.c b/tests/escapei_double.c
index 6ea9f90..736e978 100644
--- a/tests/escapei_double.c
+++ b/tests/escapei_double.c
@@ -9,10 +9,8 @@ static double func(int32_t a, double b) {
static double escape_func(size_t argc, const struct ejit_arg args[argc])
{
assert(argc == 2);
- assert(args[0].type == EJIT_INT32);
- assert(args[1].type == EJIT_DOUBLE);
- int32_t a = args[0].i32;
- double b = args[1].d;
+ int32_t a = EJIT_PARAM(argc, args, 0, int32_t);
+ double b = EJIT_PARAM(argc, args, 1, double);
return func(a, b);
}
diff --git a/tests/escapei_float.c b/tests/escapei_float.c
index 7a1b923..7cdc30d 100644
--- a/tests/escapei_float.c
+++ b/tests/escapei_float.c
@@ -9,10 +9,8 @@ static float func(int32_t a, float b) {
static float escape_func(size_t argc, const struct ejit_arg args[argc])
{
assert(argc == 2);
- assert(args[0].type == EJIT_INT32);
- assert(args[1].type == EJIT_FLOAT);
- int32_t a = args[0].i32;
- float b = args[1].f;
+ int32_t a = EJIT_PARAM(argc, args, 0, int32_t);
+ float b = EJIT_PARAM(argc, args, 1, float);
return func(a, b);
}
diff --git a/tests/escapei_immediate_10.c b/tests/escapei_immediate_10.c
new file mode 100644
index 0000000..5517c35
--- /dev/null
+++ b/tests/escapei_immediate_10.c
@@ -0,0 +1,63 @@
+#include <ejit/ejit.h>
+#include <assert.h>
+#include "do_jit.h"
+
+static int32_t func(int32_t a, int32_t b, int32_t c, int32_t d, int32_t e,
+ int32_t f, int32_t g, int32_t h, int32_t i, int32_t j)
+{
+ assert(a == 0);
+ assert(b == 1);
+ assert(c == 2);
+ assert(d == 3);
+ assert(e == 4);
+ assert(f == 5);
+ assert(g == 6);
+ assert(h == 7);
+ assert(i == 8);
+ assert(j == 9);
+ return 42;
+}
+
+static long escape_func(size_t argc, const struct ejit_arg args[argc])
+{
+ assert(argc == 10);
+ int32_t a = EJIT_PARAM(argc, args, 0, int32_t);
+ int32_t b = EJIT_PARAM(argc, args, 1, int32_t);
+ int32_t c = EJIT_PARAM(argc, args, 2, int32_t);
+ int32_t d = EJIT_PARAM(argc, args, 3, int32_t);
+ int32_t e = EJIT_PARAM(argc, args, 4, int32_t);
+ int32_t f = EJIT_PARAM(argc, args, 5, int32_t);
+ int32_t g = EJIT_PARAM(argc, args, 6, int32_t);
+ int32_t h = EJIT_PARAM(argc, args, 7, int32_t);
+ int32_t i = EJIT_PARAM(argc, args, 8, int32_t);
+ int32_t j = EJIT_PARAM(argc, args, 9, int32_t);
+ return func(a, b, c, d, e, f, g, h, i, j);
+}
+
+int main(int argc, char *argv[])
+{
+ (void)argv;
+ bool do_jit = argc > 1;
+ struct ejit_func *f = ejit_create_func(EJIT_INT32, 0, NULL);
+ struct ejit_operand args[10] = {
+ EJIT_OPERAND_IMM(0, EJIT_INT32),
+ EJIT_OPERAND_IMM(1, EJIT_INT32),
+ EJIT_OPERAND_IMM(2, EJIT_INT32),
+ EJIT_OPERAND_IMM(3, EJIT_INT32),
+ EJIT_OPERAND_IMM(4, EJIT_INT32),
+ EJIT_OPERAND_IMM(5, EJIT_INT32),
+ EJIT_OPERAND_IMM(6, EJIT_INT32),
+ EJIT_OPERAND_IMM(7, EJIT_INT32),
+ EJIT_OPERAND_IMM(8, EJIT_INT32),
+ EJIT_OPERAND_IMM(9, EJIT_INT32),
+ };
+ ejit_escapei_i(f, escape_func, 10, args);
+ ejit_retval(f, EJIT_GPR(0));
+ ejit_retr(f, EJIT_GPR(0));
+
+ ejit_select_compile_func(f, 11, 0, false, do_jit, true);
+
+ assert(ejit_run_func_i(f, 0, NULL) == 42);
+
+ ejit_destroy_func(f);
+}
diff --git a/tests/makefile b/tests/makefile
index 5aeef98..53115de 100644
--- a/tests/makefile
+++ b/tests/makefile
@@ -1,25 +1,35 @@
include ./tests.mk
-LLVM ?= 0
-CROSS_COMPILE :=
-COMPILER != [ "$(LLVM)" != "0" ] \
- && echo clang --target="$(CROSS_COMPILE)" \
- || echo $(CROSS_COMPILE)gcc
+LLVM ?= 0
+COMPILER != [ -n "$(CROSS_COMPILE)" ] \
+ && { \
+ [ "$(LLVM)" != "0" ] \
+ && echo clang --target="$(CROSS_COMPILE)" \
+ || echo $(CROSS_COMPILE)gcc \
+ ; \
+ } \
+ || echo $(CC)
-CFLAGS := -Wall -Wextra -O0 -g
+RELEASE ?= 0
+OPTFLAGS != [ "$(RELEASE)" != "0" ] \
+ && echo "-O2" \
+ || echo "-O0"
+
+LTO ?= 0
+LTOFLAGS != [ "$(LTO)" != "0" ] \
+ && echo "-flto=auto"
+
+DEBUG ?= 1
+DEBUGFLAGS != [ "$(DEBUG)" != "0" ] \
+ && echo "-DDEBUG=1" \
+ || echo "-DNDEBUG=1"
+
+OBFLAGS := -g
+WARNFLAGS := -Wall -Wextra
INCLUDE_FLAGS := -I include
-COMPILE_TEST := $(COMPILER) $(CFLAGS) $(INCLUDE_FLAGS)
+COMPILE_TEST := $(COMPILER) $(WARNFLAGS) $(OPTFLAGS) $(LTOFLAGS) \
+ $(OBFLAGS) $(CFLAGS) $(DEBUGFLAGS) $(INCLUDE_FLAGS)
.PHONY: check
check: $(TESTS)
- @echo "Running bytecode tests..."
- @set -e; for test in $(TESTS); do \
- echo "Testing: $$test"; \
- ./$$test; \
- done
- @echo "Running jit tests..."
- @set -e; for test in $(TESTS); do \
- echo "Testing: $$test"; \
- ./$$test 1; \
- done
@echo "Success!"
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);
+}
diff --git a/tests/sqrtr_d.c b/tests/sqrtr_d.c
new file mode 100644
index 0000000..06e7894
--- /dev/null
+++ b/tests/sqrtr_d.c
@@ -0,0 +1,23 @@
+#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[1] = {
+ EJIT_OPERAND_FPR(0, EJIT_TYPE(double)),
+ };
+ struct ejit_func *f = ejit_create_func(EJIT_TYPE(double), 1, operands);
+
+ ejit_sqrtr_d(f, EJIT_FPR(0), EJIT_FPR(0));
+ ejit_retr_d(f, EJIT_FPR(0));
+
+ ejit_select_compile_func(f, 0, 1, EJIT_USE64(double), do_jit, true);
+
+ assert(erfd1(f, EJIT_ARG( 0.0, double)) == 0.0);
+ assert(erfd1(f, EJIT_ARG( 4.0, double)) == 2.0);
+ assert(erfd1(f, EJIT_ARG(-4.0, double))
+ != erfd1(f, EJIT_ARG(-4.0, double))); // nan
+}
diff --git a/tests/sqrtr_f.c b/tests/sqrtr_f.c
new file mode 100644
index 0000000..3baa00d
--- /dev/null
+++ b/tests/sqrtr_f.c
@@ -0,0 +1,23 @@
+#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[1] = {
+ EJIT_OPERAND_FPR(0, EJIT_TYPE(float)),
+ };
+ struct ejit_func *f = ejit_create_func(EJIT_TYPE(float), 1, operands);
+
+ ejit_sqrtr_f(f, EJIT_FPR(0), EJIT_FPR(0));
+ ejit_retr_f(f, EJIT_FPR(0));
+
+ ejit_select_compile_func(f, 0, 1, EJIT_USE64(float), do_jit, true);
+
+ assert(erff1(f, EJIT_ARG( 0.0, float)) == 0.0);
+ assert(erff1(f, EJIT_ARG( 4.0, float)) == 2.0);
+ assert(erff1(f, EJIT_ARG(-4.0, float))
+ != erff1(f, EJIT_ARG(-4.0, float))); // nan
+}
diff --git a/tests/taili.c b/tests/taili.c
new file mode 100644
index 0000000..cc09f59
--- /dev/null
+++ b/tests/taili.c
@@ -0,0 +1,39 @@
+#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_GPR(0, EJIT_INT32), /* s */
+ EJIT_OPERAND_GPR(1, EJIT_INT32) /* n */
+ };
+
+ struct ejit_func *f = ejit_create_func(EJIT_INT32, 2, operands);
+
+ /* n == 0, return s */
+ struct ejit_reloc r = ejit_bnei(f, EJIT_GPR(1), 0);
+ ejit_retr(f, EJIT_GPR(0));
+ ejit_patch(f, r, ejit_label(f));
+
+ /* s += n */
+ ejit_addr(f, EJIT_GPR(0), EJIT_GPR(0), EJIT_GPR(1));
+
+ /* n -= 1 */
+ ejit_subi(f, EJIT_GPR(1), EJIT_GPR(1), 1);
+
+ struct ejit_operand args[2] = {
+ EJIT_OPERAND_GPR(0, EJIT_INT32), /* s */
+ EJIT_OPERAND_GPR(1, EJIT_INT32) /* n */
+ };
+ ejit_taili(f, f, 2, args);
+
+ ejit_select_compile_func(f, 2, 0, EJIT_USE64(uintptr_t), do_jit, true);
+
+ /* arbitrary number but large enough to most likely cause a stack fault
+ * if the tail call leaks memory or something */
+ assert((int32_t)erfi2(f, EJIT_ARG(0, int32_t), EJIT_ARG(1000000, int32_t)) == 1784293664);
+ ejit_destroy_func(f);
+}
diff --git a/tests/tailr.c b/tests/tailr.c
new file mode 100644
index 0000000..69ad44b
--- /dev/null
+++ b/tests/tailr.c
@@ -0,0 +1,41 @@
+#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_GPR(0, EJIT_INT32), /* s */
+ EJIT_OPERAND_GPR(1, EJIT_INT32) /* n */
+ };
+
+ struct ejit_func *f = ejit_create_func(EJIT_INT32, 2, operands);
+
+ /* n == 0, return s */
+ struct ejit_reloc r = ejit_bnei(f, EJIT_GPR(1), 0);
+ ejit_retr(f, EJIT_GPR(0));
+ ejit_patch(f, r, ejit_label(f));
+
+ /* s += n */
+ ejit_addr(f, EJIT_GPR(0), EJIT_GPR(0), EJIT_GPR(1));
+
+ /* n -= 1 */
+ ejit_subi(f, EJIT_GPR(1), EJIT_GPR(1), 1);
+
+ struct ejit_operand args[2] = {
+ EJIT_OPERAND_GPR(0, EJIT_INT32), /* s */
+ EJIT_OPERAND_GPR(1, EJIT_INT32) /* n */
+ };
+
+ ejit_movi(f, EJIT_GPR(2), (uintptr_t)f);
+ ejit_tailr(f, EJIT_GPR(2), 2, args);
+
+ ejit_select_compile_func(f, 3, 0, EJIT_USE64(uintptr_t), do_jit, true);
+
+ /* arbitrary number but large enough to most likely cause a stack fault
+ * if the tail call leaks memory or something */
+ assert((int32_t)erfi2(f, EJIT_ARG(0, int32_t), EJIT_ARG(1000000, int32_t)) == 1784293664);
+ ejit_destroy_func(f);
+}