karlos/include/jit.h

69 lines
2 KiB
C

#ifndef KARLOS_JIT_H
#define KARLOS_JIT_H
#include <stdint.h>
#include <stddef.h>
#include <stdbool.h>
// jit call: arguments in R0, R1, R2, ...
// returns value in R0
enum op {
ADDI, // ra += imm
ADD, // ra += rb
MOV, // ra = rb
MOVI, // ra = imm
SHLI,
AND,
ANDI,
OR,
RET, // return
LD, // ra = mem[rb + imm]
SD, // mem[rb + imm] = ra
LW,
LWU,
SW,
// TODO other load types
};
enum reg {
R0 = 0,
R1,
R2,
R3,
R4,
R5,
R6,
R7,
// used internally, do not use
RSCRATCH
};
#define GEN_ADDI(my_ra, i) ((struct insn) { .op = ADDI, .ra = my_ra, .rb = 0, .imm = i })
#define GEN_ADD(my_ra, my_rb) ((struct insn) { .op = ADD, .ra = my_ra, .rb = my_rb })
#define GEN_ANDI(my_ra, i) ((struct insn) { .op = ANDI, .ra = my_ra, .rb = 0, .imm = i })
#define GEN_AND(my_ra, my_rb) ((struct insn) { .op = AND, .ra = my_ra, .rb = my_rb })
#define GEN_MOV(my_ra, my_rb) ((struct insn) { .op = MOV, .ra = my_ra, .rb = my_rb })
#define GEN_MOVI(my_ra, i) ((struct insn) { .op = MOVI, .ra = my_ra, .rb = 0, .imm = i })
#define GEN_SHLI(my_ra, i) ((struct insn) { .op = SHLI, .ra = my_ra, .rb = 0, .imm = i })
#define GEN_OR(my_ra, my_rb) ((struct insn) { .op = OR, .ra = my_ra, .rb = my_rb })
#define GEN_RET() ((struct insn) { .op = RET, .ra = 0, .rb = 0 })
#define GEN_LD(reg, addr, i) ((struct insn) { .op = LD, .ra = reg, .rb = addr, .imm = i })
#define GEN_LW(reg, addr, i) ((struct insn) { .op = LW, .ra = reg, .rb = addr, .imm = i })
#define GEN_LWU(reg, addr, i) ((struct insn) { .op = LWU, .ra = reg, .rb = addr, .imm = i })
#define GEN_SD(reg, addr, i) ((struct insn) { .op = SD, .ra = reg, .rb = addr, .imm = i })
#define GEN_SW(reg, addr, i) ((struct insn) { .op = SW, .ra = reg, .rb = addr, .imm = i })
struct insn {
enum op op;
enum reg ra;
enum reg rb;
uint64_t imm;
};
bool jit_compile(struct insn *insns, size_t n, uint8_t *mem);
uint64_t jit_call(uint8_t *mem, uint64_t r0, uint64_t r1);
void jit_test(void);
#endif