aboutsummaryrefslogtreecommitdiff
path: root/include
diff options
context:
space:
mode:
authorKimplul <kimi.h.kuparinen@gmail.com>2024-06-23 23:31:46 +0300
committerKimplul <kimi.h.kuparinen@gmail.com>2024-06-23 23:38:49 +0300
commit5a4da8bac457f0e70e690a572eba9cf754e69a37 (patch)
tree58e48f1b12722eadbc1b2587b690b30afac54140 /include
downloadejit-5a4da8bac457f0e70e690a572eba9cf754e69a37.tar.gz
ejit-5a4da8bac457f0e70e690a572eba9cf754e69a37.zip
initial interpeter testing
Diffstat (limited to 'include')
-rw-r--r--include/ejit/ejit.h256
1 files changed, 256 insertions, 0 deletions
diff --git a/include/ejit/ejit.h b/include/ejit/ejit.h
new file mode 100644
index 0000000..56582be
--- /dev/null
+++ b/include/ejit/ejit.h
@@ -0,0 +1,256 @@
+#ifndef EJIT_H
+#define EJIT_H
+
+#include <stdint.h>
+#include <stddef.h>
+#include <stdlib.h>
+#include <assert.h>
+#include <stdbool.h>
+
+enum ejit_type
+{
+ /* special case, only to be used to indicate return value of function */
+ EJIT_VOID,
+ /* free to use wherever */
+ EJIT_UINT8,
+ EJIT_INT8,
+ EJIT_UINT16,
+ EJIT_INT16,
+ EJIT_UINT32,
+ EJIT_INT32,
+ EJIT_UINT64,
+ EJIT_INT64,
+ EJIT_POINTER,
+ EJIT_FLOAT,
+ EJIT_DOUBLE,
+};
+
+struct ejit_arg {
+ union {
+ int8_t c;
+ uint8_t uc;
+ int16_t s;
+ uint16_t us;
+ int32_t i;
+ uint32_t ui;
+ int64_t l;
+ uint64_t ul;
+ float f;
+ double d;
+ void *p;
+ };
+ enum ejit_type type;
+};
+
+static inline bool ejit_int_type(enum ejit_type t)
+{
+ switch (t) {
+ case EJIT_INT8:
+ case EJIT_INT16:
+ case EJIT_INT32:
+ case EJIT_INT64:
+ case EJIT_UINT8:
+ case EJIT_UINT16:
+ case EJIT_UINT32:
+ case EJIT_UINT64:
+ case EJIT_POINTER:
+ return true;
+ default:
+ }
+
+ return false;
+}
+
+static inline bool ejit_float_type(enum ejit_type t)
+{
+ switch (t) {
+ case EJIT_FLOAT:
+ case EJIT_DOUBLE:
+ return true;
+ default:
+ }
+
+ return false;
+}
+
+static inline struct ejit_arg ejit_build_arg(enum ejit_type type, long x)
+{
+ assert(ejit_int_type(type));
+
+ struct ejit_arg a;
+ a.type = type;
+
+ switch (type) {
+ case EJIT_INT8: a.c = x; break;
+ case EJIT_INT16: a.s = x; break;
+ case EJIT_INT32: a.i = x; break;
+ case EJIT_INT64: a.l = x; break;
+ case EJIT_UINT8: a.uc = x; break;
+ case EJIT_UINT16: a.us = x; break;
+ case EJIT_UINT32: a.ui = x; break;
+ case EJIT_UINT64: a.ul = x; break;
+ case EJIT_POINTER: a.p = (void *)x; break;
+ default: abort();
+ }
+
+ return a;
+}
+
+static inline struct ejit_arg ejit_build_arg_f(enum ejit_type type, double x)
+{
+ assert(ejit_float_type(type));
+
+ struct ejit_arg a;
+ a.type = type;
+
+ switch (type) {
+ case EJIT_FLOAT: a.f = x; break;
+ case EJIT_DOUBLE: a.d = x; break;
+ default: abort();
+ }
+
+ return a;
+}
+
+#define EJIT_C(x) ((struct ejit_arg){.c = (int8_t)(x), .type = EJIT_INT8})
+
+/* register allocator could be just pushing everything above V0 or whatever onto
+ * the stack, heh */
+struct ejit_gpr {
+ size_t r;
+};
+
+struct ejit_fpr {
+ size_t f;
+};
+
+struct ejit_reloc {
+ size_t insn;
+};
+
+struct ejit_label {
+ size_t addr;
+};
+
+struct ejit_operand {
+ enum {
+ EJIT_OPERAND_GPR,
+ EJIT_OPERAND_FPR,
+ EJIT_OPERAND_IMM,
+ EJIT_OPERAND_FLT,
+ } kind;
+
+ enum ejit_type type;
+
+ union {
+ long r;
+ double d;
+ };
+};
+
+struct ejit_func;
+
+struct ejit_func *ejit_create_func(enum ejit_type rtype, size_t argc, const struct ejit_operand args[argc]);
+void ejit_compile_func(struct ejit_func *f, size_t gpr, size_t fpr);
+long ejit_run_func(struct ejit_func *f, size_t argc, struct ejit_arg args[argc]);
+double ejit_run_func_f(struct ejit_func *f, size_t argc, struct ejit_arg args[argc]);
+
+void ejit_destroy_func(struct ejit_func *s);
+
+#define EJIT_GPR(x) ((struct ejit_gpr){.r = (x)})
+#define EJIT_FPR(x) ((struct ejit_fpr){.f = (x)})
+
+#define EJIT_OPERAND_GPR(x, type) (struct ejit_operand { .kind = EJIT_OPERAND_GPR, .r = (long)(x), .type = (type)})
+#define EJIT_OPERAND_FPR(x, type) (struct ejit_operand { .kind = EJIT_OPERAND_FPR, .r = (long)(x)})
+#define EJIT_OPERAND_IMM(x, type) (struct ejit_operand { .kind = EJIT_OPERAND_IMM, .r = (long)(x)})
+#define EJIT_OPERAND_FLT(x, type) (struct ejit_operand { .kind = EJIT_OPERAND_FLT, .r = (double)(x)})
+
+typedef long (*ejit_escape_t)(size_t argc, const struct ejit_arg args[argc]);
+typedef double (*ejit_escape_f_t)(size_t argc, const struct ejit_arg args[argc]);
+
+struct ejit_label ejit_label(struct ejit_func *s);
+
+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_escapei(struct ejit_func *s, ejit_escape_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_ret(struct ejit_func *s, struct ejit_gpr r0);
+void ejit_ret_f(struct ejit_func *s, struct ejit_fpr r0);
+void ejit_ret_i(struct ejit_func *s, long i);
+void ejit_ret_fi(struct ejit_func *s, double f);
+
+/* move from r1 to r0 */
+void ejit_movi(struct ejit_func *s, struct ejit_gpr r0, long i);
+void ejit_movr(struct ejit_func *s, struct ejit_gpr r0, struct ejit_gpr r1);
+void ejit_movr_d(struct ejit_func *s, struct ejit_fpr r0, struct ejit_fpr r1);
+
+void ejit_ldi_8(struct ejit_func *s, struct ejit_gpr r0, void *p);
+void ejit_ldi_16(struct ejit_func *s, struct ejit_gpr r0, void *p);
+void ejit_ldi_32(struct ejit_func *s, struct ejit_gpr r0, void *p);
+void ejit_ldi_64(struct ejit_func *s, struct ejit_gpr r0, void *p);
+
+void ejit_ldi_u8(struct ejit_func *s, struct ejit_gpr r0, void *p);
+void ejit_ldi_u16(struct ejit_func *s, struct ejit_gpr r0, void *p);
+void ejit_ldi_u32(struct ejit_func *s, struct ejit_gpr r0, void *p);
+void ejit_ldi_u64(struct ejit_func *s, struct ejit_gpr r0, void *p);
+
+void ejit_ldi_f(struct ejit_func *s, struct ejit_fpr r0, void *p);
+void ejit_ldi_d(struct ejit_func *s, struct ejit_fpr r0, void *p);
+
+/* from r1 + o to r0 */
+void ejit_ldxi_8(struct ejit_func *s, struct ejit_gpr r0, struct ejit_gpr r1, long o);
+void ejit_ldxi_16(struct ejit_func *s, struct ejit_gpr r0, struct ejit_gpr r1, long o);
+void ejit_ldxi_32(struct ejit_func *s, struct ejit_gpr r0, struct ejit_gpr r1, long o);
+void ejit_ldxi_64(struct ejit_func *s, struct ejit_gpr r0, struct ejit_gpr r1, long o);
+
+void ejit_ldxi_uc(struct ejit_func *s, struct ejit_gpr r0, struct ejit_gpr r1, long o);
+void ejit_ldxi_us(struct ejit_func *s, struct ejit_gpr r0, struct ejit_gpr r1, long o);
+void ejit_ldxi_ui(struct ejit_func *s, struct ejit_gpr r0, struct ejit_gpr r1, long o);
+void ejit_ldxi_ul(struct ejit_func *s, struct ejit_gpr r0, struct ejit_gpr r1, long o);
+
+void ejit_ldxi_f(struct ejit_func *s, struct ejit_fpr r0, struct ejit_gpr r1, long o);
+void ejit_ldxi_d(struct ejit_func *s, struct ejit_fpr r0, struct ejit_gpr r1, long o);
+
+void ejit_sti_8(struct ejit_func *s, struct ejit_gpr r0, void *p);
+void ejit_sti_16(struct ejit_func *s, struct ejit_gpr r0, void *p);
+void ejit_sti_32(struct ejit_func *s, struct ejit_gpr r0, void *p);
+void ejit_sti_64(struct ejit_func *s, struct ejit_gpr r0, void *p);
+
+void ejit_sti_u8(struct ejit_func *s, struct ejit_gpr r0, void *p);
+void ejit_sti_u16(struct ejit_func *s, struct ejit_gpr r0, void *p);
+void ejit_sti_u32(struct ejit_func *s, struct ejit_gpr r0, void *p);
+void ejit_sti_u64(struct ejit_func *s, struct ejit_gpr r0, void *p);
+
+void ejit_sti_f(struct ejit_func *s, struct ejit_fpr r0, void *p);
+void ejit_sti_d(struct ejit_func *s, struct ejit_fpr r0, void *p);
+
+/* from r0 to r1 + o */
+void ejit_stxi_8(struct ejit_func *s, struct ejit_gpr r0, struct ejit_gpr r1, long o);
+void ejit_stxi_16(struct ejit_func *s, struct ejit_gpr r0, struct ejit_gpr r1, long o);
+void ejit_stxi_32(struct ejit_func *s, struct ejit_gpr r0, struct ejit_gpr r1, long o);
+void ejit_stxi_64(struct ejit_func *s, struct ejit_gpr r0, struct ejit_gpr r1, long o);
+
+void ejit_stxi_u8(struct ejit_func *s, struct ejit_gpr r0, struct ejit_gpr r1, long o);
+void ejit_stxi_u16(struct ejit_func *s, struct ejit_gpr r0, struct ejit_gpr r1, long o);
+void ejit_stxi_u32(struct ejit_func *s, struct ejit_gpr r0, struct ejit_gpr r1, long o);
+void ejit_stxi_u64(struct ejit_func *s, struct ejit_gpr r0, struct ejit_gpr r1, long o);
+
+void ejit_stxi_f(struct ejit_func *s, struct ejit_fpr r0, struct ejit_gpr r1, long o);
+void ejit_stxi_d(struct ejit_func *s, struct ejit_fpr r0, struct ejit_gpr r1, long o);
+
+void ejit_addr(struct ejit_func *s, struct ejit_gpr r0, struct ejit_gpr r1, struct ejit_gpr r2);
+void ejit_addr_f(struct ejit_func *s, struct ejit_fpr r0, struct ejit_fpr r1, struct ejit_fpr r2);
+
+void ejit_subr(struct ejit_func *s, struct ejit_gpr r0, struct ejit_gpr r1, struct ejit_gpr r2);
+void ejit_subr_f(struct ejit_func *s, struct ejit_fpr r0, struct ejit_fpr r1, struct ejit_fpr r2);
+
+/** @todo branches, should I do the nifty label trick again? */
+struct ejit_reloc ejit_bltr(struct ejit_func *s, struct ejit_gpr r0, struct ejit_gpr r1);
+
+void ejit_patch(struct ejit_func *s, struct ejit_reloc r, struct ejit_label l);
+
+#endif /* EJIT_H */