diff options
author | Kimplul <kimi.h.kuparinen@gmail.com> | 2024-06-23 23:31:46 +0300 |
---|---|---|
committer | Kimplul <kimi.h.kuparinen@gmail.com> | 2024-06-23 23:38:49 +0300 |
commit | 5a4da8bac457f0e70e690a572eba9cf754e69a37 (patch) | |
tree | 58e48f1b12722eadbc1b2587b690b30afac54140 /include | |
download | ejit-5a4da8bac457f0e70e690a572eba9cf754e69a37.tar.gz ejit-5a4da8bac457f0e70e690a572eba9cf754e69a37.zip |
initial interpeter testing
Diffstat (limited to 'include')
-rw-r--r-- | include/ejit/ejit.h | 256 |
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 */ |