Skip to content

Instantly share code, notes, and snippets.

Embed
What would you like to do?
#ifdef __TINYC__
#if _WIN32
// TODO VirtualAlloc, VirtualFree
#else
// mmap
#define PROT_READ 1
#define PROT_WRITE 2
#define PROT_EXEC 4
#define MAP_PRIVATE 0x02
#define MAP_ANON 0x1000
void *mmap(void *, size_t, int, int, int, int64_t);
int munmap (void *, size_t);
int mprotect(void *, size_t, int);
// dlfcn
#define RTLD_LAZY 0x1
#define RTLD_GLOBAL 0x8
void* dlsym(void* handle, const char* symbol);
void *dlopen(const char *filename, int flag);
int dlclose(void *handle);
#endif
#elif _WIN32
#include <windows.h>
#else
#include <sys/mman.h>
#include <dlfcn.h>
#ifndef MAP_ANON
#define MAP_ANON 0x1000
#endif
#endif
//////////////////////////////////////////// X86-64
void x8664_encode_rex(uint8_t *buffer, int dest, int src, int op64)
{
buffer[0] = (dest > 0x7) | ((src > 0x7) << 2) | (op64 << 3) | (0x40);
}
void x8664_encode_modrm(uint8_t *buffer, int dest, int src, int mod)
{
buffer[0] = (dest & 0x7) | ((src & 0x7) << 3) | (mod << 6);
}
void x8664_encode(uint8_t *buffer, int dest, int src, int i, int mod, int op64)
{
x8664_encode_rex(buffer, dest, src, op64);
x8664_encode_modrm(buffer + i, dest, src, mod);
}
// registers
#define RAX 0
#define RCX 1
#define RDX 2
#define RBX 3
#define RSP 4
#define RBP 5
#define RSI 6
#define RDI 7
#define R8 8
#define R9 9
#define R10 10
#define R11 11
#define R12 12
#define R13 13
#define R14 14
#define R15 15
#define XMM0 0
#define XMM1 1
#define XMM2 2
#define XMM3 3
#define XMM4 4
#define XMM5 5
#define XMM6 6
#define XMM7 7
#define XMM8 8
#define XMM9 9
#define XMM10 10
#define XMM11 11
#define XMM12 12
#define XMM13 13
#define XMM14 14
#define XMM15 15
#define AL RAX
// integer arguments
#ifdef _WIN32
#define RA1 RCX
#define RA2 RDX
#define RA3 R8
#define RA4 R9
// (...stack)
#else // System V
#define RA1 RDI
#define RA2 RSI
#define RA3 RDX
#define RA4 RCX
#define RA5 R8
#define RA6 R9
// (...stack)
#endif
#define OPI32(opcode, buffer, im) {\
buffer[0] = opcode;\
*(uint32_t *)(buffer + 1) = im;\
buffer += 5;\
}
#define OP0(opcode, buffer, dest, src) {\
buffer[0] = 0x0f;\
buffer[1] = opcode;\
x8664_encode_modrm(buffer + 2, dest, src, 3);\
buffer += 3;\
}
#define RR(opcode, buffer, dest, src, op64) {\
buffer[1] = opcode;\
x8664_encode(buffer, dest, src, 2, 3, op64);\
buffer += 3;\
}
#define RR0(opcode, buffer, dest, src, mod, op64) {\
buffer[1] = 0x0f;\
buffer[2] = opcode;\
x8664_encode(buffer, dest, src, 3, mod, op64);\
buffer += 4;\
}
#define RRF(prefix, opcode, buffer, dest, src, op64) {\
buffer[0] = prefix;\
buffer[2] = 0x0f;\
buffer[3] = opcode;\
x8664_encode(buffer + 1, src, dest, 3, 3, op64);\
buffer += 5;\
}
#define RMF(opcode, buffer, dest, src, off) {\
buffer[0] = 0xf3;\
buffer[2] = 0x0f;\
buffer[3] = opcode;\
*(uint32_t *)(buffer + 5) = off;\
x8664_encode(buffer + 1, dest, src, 3, 2, 0);\
buffer += 9;\
}
#define RMF4(opcode, buffer, dest, src, off) {\
buffer[1] = 0x0f;\
buffer[2] = opcode;\
*(uint32_t *)(buffer + 4) = off;\
x8664_encode(buffer, dest, src, 3, 2, 0);\
buffer += 8;\
}
#define RI8(opcode, buffer, dest, src, im, mod, op64) {\
buffer[1] = opcode;\
buffer[3] = im;\
x8664_encode(buffer, dest, src, 2, mod, op64);\
buffer += 4;\
}
#define RI32(opcode, buffer, dest, src, im, mod, op64) {\
buffer[1] = opcode;\
*(uint32_t *)(buffer + 3) = im;\
x8664_encode(buffer, dest, src, 2, mod, op64);\
buffer += 7;\
}
#define JZ(buffer, off) {\
*(uint32_t *)(buffer) = 0x840fc085;\
*(uint32_t *)(buffer + 4) = off;\
buffer += 8;\
}
#define JNZ(buffer, off) {\
*(uint32_t *)(buffer) = 0x850fc085;\
*(uint32_t *)(buffer + 4) = off;\
buffer += 8;\
}
#define PUSH(buffer, src) {\
if (src < 8) { buffer[0] = 80 + src; }\
else {\
buffer[0] = 0b1000001; buffer++;\
buffer[0] = 80 + src - 8;\
}\
buffer++;\
}
#define POP(buffer, src) {\
if (src < 8) { buffer[0] = 88 + src; }\
else {\
buffer[0] = 0b1000001; buffer++;\
buffer[0] = 88 + src - 8;\
}\
buffer++;\
}
#define CDQ(buffer) { buffer[0] = 0x99; buffer++; }
#define RET(buffer) { buffer[0] = 0xc3; buffer++; }
#define JMP(buffer, off) OPI32(0xe9, buffer, off)
#define CALLI32(buffer, off) OPI32(0xe8, buffer, off)
#define SETL(buffer, src) OP0(0x9c, buffer, 0, src)
#define SETG(buffer, src) OP0(0x9f, buffer, 0, src)
#define SETE(buffer, src) OP0(0x94, buffer, 0, src)
#define SETA(buffer, src) OP0(0x97, buffer, 0, src)
#define SETNE(buffer, src) OP0(0x95, buffer, 0, src)
#define MOVZX(buffer, dest, src) OP0(0xb6, buffer, dest, src)
#define MOV(buffer, dest, src) RR(0x89, buffer, dest, src, 1)
#define ADD(buffer, dest, src) RR(0x01, buffer, dest, src, 1)
#define SUB(buffer, dest, src) RR(0x29, buffer, dest, src, 1)
#define AND(buffer, dest, src) RR(0x21, buffer, dest, src, 1)
#define OR(buffer, dest, src) RR(0x09, buffer, dest, src, 1)
#define XOR(buffer, dest, src) RR(0x31, buffer, dest, src, 1)
#define IDIV32(buffer, src) RR(0xf7, buffer, src, 0b111, 0)
#define IDIV64(buffer, src) RR(0xf7, buffer, src, 0b111, 1)
#define SAR1(buffer, src) RR(0xd1, buffer, src, 0b111, 1)
#define SAL1(buffer, src) RR(0xd1, buffer, src, 0b100, 1)
#define SAR(buffer, src) RR(0xd3, buffer, src, 0b111, 1)
#define SAL(buffer, src) RR(0xd3, buffer, src, 0b100, 1)
#define CMP32(buffer, dest, src) RR(0x39, buffer, dest, src, 0)
#define CMP64(buffer, dest, src) RR(0x39, buffer, dest, src, 1)
#define CALL64(buffer, src) RR(0xff, buffer, src, 0b010, 1)
#define IMUL(buffer, dest, src) RR0(0xaf, buffer, src, dest, 3, 1)
#define UCOMISS(buffer, dest, src) RR0(0x2e, buffer, src, dest, 3, 0)
#define MOVUPS(buffer, dest, src) RR0(0x10, buffer, src, dest, 3, 0)
#define ADDPS(buffer, dest, src) RR0(0x58, buffer, src, dest, 3, 0)
#define SUBPS(buffer, dest, src) RR0(0x5c, buffer, src, dest, 3, 0)
#define MULPS(buffer, dest, src) RR0(0x59, buffer, src, dest, 3, 0)
#define DIVPS(buffer, dest, src) RR0(0x5e, buffer, src, dest, 3, 0)
#define MINPS(buffer, dest, src) RR0(0x5d, buffer, src, dest, 3, 0)
#define MAXPS(buffer, dest, src) RR0(0x5f, buffer, src, dest, 3, 0)
#define SQRTPS(buffer, dest, src) RR0(0x51, buffer, src, dest, 3, 0)
#define ADDI8(buffer, dest, im) RI8(0x83, buffer, dest, 0b000, im, 3, 1)
#define SUBI8(buffer, dest, im) RI8(0x83, buffer, dest, 0b101, im, 3, 1)
#define SARI(buffer, src, im) RI8(0xc1, buffer, src, 0b111, im, 3, 1)
#define SALI(buffer, src, im) RI8(0xc1, buffer, src, 0b100, im, 3, 1)
#define CMPI8(buffer, dest, im) RI8(0x83, buffer, dest, 0b111, im, 3, 1)
#define MOVI32(buffer, dest, im) RI32(0xc7, buffer, dest, 0b000, im, 3, 1)
#define ADDI32(buffer, dest, im) RI32(0x81, buffer, dest, 0b000, im, 3, 1)
#define LOAD64(buffer, dest, src, off) RI32(0x8b, buffer, src, dest, off, 2, 1)
#define STORE64(buffer, dest, off, src) RI32(0x89, buffer, dest, src, off, 2, 1)
#define LOAD32(buffer, dest, src, off) RI32(0x8b, buffer, src, dest, off, 2, 0)
#define STORE32(buffer, dest, off, src) RI32(0x89, buffer, dest, src, off, 2, 0)
#define MOVSS(buffer, dest, src) RRF(0xf3, 0x10, buffer, dest, src, 0)
#define ADDSS(buffer, dest, src) RRF(0xf3, 0x58, buffer, dest, src, 0)
#define SUBSS(buffer, dest, src) RRF(0xf3, 0x5c, buffer, dest, src, 0)
#define MULSS(buffer, dest, src) RRF(0xf3, 0x59, buffer, dest, src, 0)
#define DIVSS(buffer, dest, src) RRF(0xf3, 0x5e, buffer, dest, src, 0)
#define MINSS(buffer, dest, src) RRF(0xf3, 0x5d, buffer, dest, src, 0)
#define MAXSS(buffer, dest, src) RRF(0xf3, 0x5f, buffer, dest, src, 0)
#define SQRTSS(buffer, dest, src) RRF(0xf3, 0x51, buffer, dest, src, 0)
#define CVTSI2SS(buffer, dest, src) RRF(0xf3, 0x2a, buffer, dest, src, 1)
#define CVTSS2SI(buffer, dest, src) RRF(0xf3, 0x2d, buffer, dest, src, 1)
#define PXOR(buffer, dest, src) RRF(0x66, 0xef, buffer, dest, src, 0)
#define LOADSS(buffer, dest, src, off) RMF(0x10, buffer, src, dest, off)
#define STORESS(buffer, dest, off, src) RMF(0x11, buffer, dest, src, off)
#define LOADUPS(buffer, dest, src, off) RMF4(0x10, buffer, src, dest, off)
#define STOREUPS(buffer, dest, off, src) RMF4(0x11, buffer, dest, src, off)
//////////////////////////////////////////// JIT MIPS-like
struct jit_parsing
{
uint8_t *buffer;
uint8_t **info1;
uint16_t *info2;
uint16_t i1;
};
struct jit_state
{
struct jit_parsing p;
uint8_t **info1;
uint16_t *info2;
void *buffer;
int buffer_size;
};
// registers
#define JIT_R0 -1 // always zero
#ifdef _WIN32
#define JIT_R1 R10 // volatile
#define JIT_R2 R11 // volatile
#else
#define JIT_R1 R8 // volatile
#define JIT_R2 R9 // volatile
#endif
#define JIT_R3 RBX // callee must save
#define JIT_R4 R12 // callee must save
#define JIT_R5 R13 // callee must save
#define JIT_R6 R14 // callee must save
#define JIT_R7 R15 // callee must save
#define JIT_RE RAX // return (very volatile (used internally), use just before calling JIT_RETURN)
#define JIT_SP RSP // stack pointer
// arguments
#define JIT_A1 RA1
#define JIT_A2 RA2
#define JIT_A3 RA3
#define JIT_A4 RA4
// float registers (all volatile)
#define JIT_RF0 XMM0 // arg1, return
#define JIT_RF1 XMM1 // arg2
#define JIT_RF2 XMM2 // arg3
#define JIT_RF3 XMM3 // arg4
#define JIT_RF4 XMM4
#define JIT_RF5 XMM5
#define JIT_RF6 XMM6
#define JIT_RF7 XMM7
#define JIT_RF8 XMM8
#define JIT_RF9 XMM9
#define JIT_RF10 XMM10
#define JIT_RF11 XMM11
#define JIT_RF12 XMM12
#define JIT_RF13 XMM13
#define JIT_RF14 XMM14
#define JIT_RF15 XMM15
// instructions
void JIT_LOAD32(struct jit_parsing *p, int d, int s, int o);
void JIT_STORE32(struct jit_parsing *p, int d, int o, int s);
void JIT_LOAD64(struct jit_parsing *p, int d, int s, int o);
void JIT_STORE64(struct jit_parsing *p, int d, int o, int s);
void JIT_ADD(struct jit_parsing *p, int d, int s, int t);
void JIT_ADDI(struct jit_parsing *p, int d, int s, int i);
void JIT_SUB(struct jit_parsing *p, int d, int s, int t);
void JIT_MUL(struct jit_parsing *p, int d, int s, int t);
void JIT_DIV(struct jit_parsing *p, int d, int s, int t);
void JIT_SHIFTL(struct jit_parsing *p, int d, int s, int t);
void JIT_SHIFTR(struct jit_parsing *p, int d, int s, int t);
void JIT_SHIFTLI(struct jit_parsing *p, int d, int s, int i);
void JIT_SHIFTRI(struct jit_parsing *p, int d, int s, int i);
void JIT_AND(struct jit_parsing *p, int d, int s, int t);
void JIT_OR(struct jit_parsing *p, int d, int s, int t);
void JIT_XOR(struct jit_parsing *p, int d, int s, int t);
void JIT_LESS(struct jit_parsing *p, int d, int s, int t);
void JIT_JUMP(struct jit_parsing *p, int o);
void JIT_BRANCH(struct jit_parsing *p, int s, int t, int o);
void JIT_NBRANCH(struct jit_parsing *p, int s, int t, int o);
void JIT_CALL(struct jit_parsing *p, int o);
void JIT_CALLEX(struct jit_parsing *p, int s);
void JIT_RETURN(struct jit_parsing *p);
void JIT_LOADF(struct jit_parsing *p, int d, int s, int o);
void JIT_STOREF(struct jit_parsing *p, int d, int o, int s);
void JIT_ITOF(struct jit_parsing *p, int d, int s);
void JIT_FTOI(struct jit_parsing *p, int d, int s);
void JIT_ADDF(struct jit_parsing *p, int d, int s, int t);
void JIT_SUBF(struct jit_parsing *p, int d, int s, int t);
void JIT_MULF(struct jit_parsing *p, int d, int s, int t);
void JIT_DIVF(struct jit_parsing *p, int d, int s, int t);
void JIT_LESSF(struct jit_parsing *p, int d, int s, int t);
void JIT_MINF(struct jit_parsing *p, int d, int s, int t);
void JIT_MAXF(struct jit_parsing *p, int d, int s, int t);
void JIT_LOADF4(struct jit_parsing *p, int d, int s, int o);
void JIT_STOREF4(struct jit_parsing *p, int d, int o, int s);
void JIT_ADDF4(struct jit_parsing *p, int d, int s, int t);
void JIT_SUBF4(struct jit_parsing *p, int d, int s, int t);
void JIT_MULF4(struct jit_parsing *p, int d, int s, int t);
void JIT_DIVF4(struct jit_parsing *p, int d, int s, int t);
void JIT_MINF4(struct jit_parsing *p, int d, int s, int t);
void JIT_MAXF4(struct jit_parsing *p, int d, int s, int t);
#define JIT__INFO(p)\
p->info1[0] = p->buffer;\
p->info1++;\
p->i1++;
#define JIT__INFO2(p)\
p->info2[0] = p->i1;\
p->info2++;
void JIT_LOAD32(struct jit_parsing *p, int d, int s, int o)
{
JIT__INFO(p)
if (d != JIT_R0 && s != JIT_R0) {
if (s == JIT_SP) {
MOV(p->buffer, RAX, s)
LOAD32(p->buffer, d, RAX, o)
}
else {
LOAD32(p->buffer, d, s, o)
}
}
}
void JIT_STORE32(struct jit_parsing *p, int d, int o, int s)
{
JIT__INFO(p)
if (d != JIT_R0 && s != JIT_R0) {
if (d == JIT_SP) {
MOV(p->buffer, RAX, d)
STORE32(p->buffer, RAX, o, s)
}
else {
STORE32(p->buffer, d, o, s)
}
}
}
void JIT_LOAD64(struct jit_parsing *p, int d, int s, int o)
{
JIT__INFO(p)
if (d != JIT_R0 && s != JIT_R0) {
if (s == JIT_SP) {
MOV(p->buffer, RAX, s)
LOAD64(p->buffer, d, RAX, o)
}
else {
LOAD64(p->buffer, d, s, o)
}
}
}
void JIT_STORE64(struct jit_parsing *p, int d, int o, int s)
{
JIT__INFO(p)
if (d != JIT_R0 && s != JIT_R0) {
if (d == JIT_SP) {
MOV(p->buffer, RAX, d)
STORE64(p->buffer, RAX, o, s)
}
else {
STORE64(p->buffer, d, o, s)
}
}
}
void JIT_ADD(struct jit_parsing *p, int d, int s, int t)
{
JIT__INFO(p)
if (d != JIT_R0) {
if (s == JIT_R0 && t == JIT_R0) {
MOVI32(p->buffer, d, 0)
}
else if (s == JIT_R0) {
if (t != d) MOV(p->buffer, d, t)
}
else if (t == JIT_R0) {
if (s != d) MOV(p->buffer, d, s)
}
else {
if (s != d) MOV(p->buffer, d, s)
ADD(p->buffer, d, t)
}
}
}
void JIT_ADDI(struct jit_parsing *p, int d, int s, int i)
{
JIT__INFO(p)
if (d != JIT_R0) {
if (s == JIT_R0) {
MOVI32(p->buffer, d, i)
}
else {
if (s != d) MOV(p->buffer, d, s)
if (i != 0) ADDI32(p->buffer, d, i)
}
}
}
void JIT_SUB(struct jit_parsing *p, int d, int s, int t)
{
JIT__INFO(p)
if (d != JIT_R0) {
if (s == t) {
MOVI32(p->buffer, d, 0)
}
else if (s == JIT_R0) {
if (t != d) MOV(p->buffer, d, t)
}
else if (t == JIT_R0) {
if (s != d) MOV(p->buffer, d, s)
}
else {
if (s != d) MOV(p->buffer, d, s)
SUB(p->buffer, d, t)
}
}
}
void JIT_MUL(struct jit_parsing *p, int d, int s, int t)
{
JIT__INFO(p)
if (d != JIT_R0) {
if (s == JIT_R0 || t == JIT_R0) {
MOVI32(p->buffer, d, 0)
}
else {
if (s != d) MOV(p->buffer, d, s)
IMUL(p->buffer, d, t)
}
}
}
void JIT_DIV(struct jit_parsing *p, int d, int s, int t)
{
JIT__INFO(p)
if (d != JIT_R0) {
if (s == JIT_R0 || t == JIT_R0) {
MOVI32(p->buffer, d, 0)
}
else {
// use rax / rdx
PUSH(p->buffer, RDX)
MOV(p->buffer, RAX, s)
CDQ(p->buffer)
IDIV64(p->buffer, t)
MOV(p->buffer, d, RAX)
POP(p->buffer, RDX)
}
}
}
void JIT_SHIFTL(struct jit_parsing *p, int d, int s, int t)
{
JIT__INFO(p)
if (d != JIT_R0) {
if (s == JIT_R0) {
MOVI32(p->buffer, d, 0)
}
else if (t == JIT_R0) {
if (s != d) MOV(p->buffer, d, s)
}
else {
if (s != d) MOV(p->buffer, d, s)
PUSH(p->buffer, RCX)
MOV(p->buffer, RCX, t)
SAL(p->buffer, d)
POP(p->buffer, RCX)
}
}
}
void JIT_SHIFTR(struct jit_parsing *p, int d, int s, int t)
{
JIT__INFO(p)
if (d != JIT_R0) {
if (s == JIT_R0) {
MOVI32(p->buffer, d, 0)
}
else if (t == JIT_R0) {
if (s != d) MOV(p->buffer, d, s)
}
else {
if (s != d) MOV(p->buffer, d, s)
PUSH(p->buffer, RCX)
MOV(p->buffer, RCX, t)
SAR(p->buffer, d)
POP(p->buffer, RCX)
}
}
}
void JIT_SHIFTLI(struct jit_parsing *p, int d, int s, int i)
{
JIT__INFO(p)
if (d != JIT_R0) {
if (s == JIT_R0) {
MOVI32(p->buffer, d, 0)
}
else {
if (s != d) MOV(p->buffer, d, s)
SALI(p->buffer, d, i)
}
}
}
void JIT_SHIFTRI(struct jit_parsing *p, int d, int s, int i)
{
JIT__INFO(p)
if (d != JIT_R0) {
if (s == JIT_R0) {
MOVI32(p->buffer, d, 0)
}
else {
if (s != d) MOV(p->buffer, d, s)
SARI(p->buffer, d, i)
}
}
}
void JIT_AND(struct jit_parsing *p, int d, int s, int t)
{
JIT__INFO(p)
if (d != JIT_R0) {
if (s == t) {
if (s == JIT_R0) MOVI32(p->buffer, d, 0)
else if (s != d) MOV(p->buffer, d, s)
}
else if (s == JIT_R0) {
MOVI32(p->buffer, d, 0)
}
else if (t == JIT_R0) {
MOVI32(p->buffer, d, 0)
}
else {
if (s != d) MOV(p->buffer, d, s)
AND(p->buffer, d, t)
}
}
}
void JIT_OR(struct jit_parsing *p, int d, int s, int t)
{
JIT__INFO(p)
if (d != JIT_R0) {
if (s == t) {
if (s == JIT_R0) MOVI32(p->buffer, d, 0)
else if (s != d) MOV(p->buffer, d, s)
}
else if (s == JIT_R0) {
if (t != d) MOV(p->buffer, d, t)
}
else if (t == JIT_R0) {
if (s != d) MOV(p->buffer, d, s)
}
else {
if (s != d) MOV(p->buffer, d, s)
OR(p->buffer, d, t)
}
}
}
void JIT_XOR(struct jit_parsing *p, int d, int s, int t)
{
JIT__INFO(p)
if (d != JIT_R0) {
if (s == t) {
MOVI32(p->buffer, d, 0)
}
else if (s == JIT_R0) {
if (t != d) MOV(p->buffer, d, t)
}
else if (t == JIT_R0) {
if (s != d) MOV(p->buffer, d, s)
}
else {
if (s != d) MOV(p->buffer, d, s)
XOR(p->buffer, d, t)
}
}
}
void JIT_LESS(struct jit_parsing *p, int d, int s, int t)
{
JIT__INFO(p)
if (d != JIT_R0) {
if (s == t) {
MOVI32(p->buffer, d, 0)
}
else {
if (s == JIT_R0) CMPI8(p->buffer, t, 0)
else if (t == JIT_R0) CMPI8(p->buffer, s, 0)
else CMP64(p->buffer, s, t)
SETL(p->buffer, AL)
MOVZX(p->buffer, RAX, AL)
MOV(p->buffer, d, RAX)
}
}
}
void JIT_JUMP(struct jit_parsing *p, int o)
{
JIT__INFO(p)
if (o > 0 || o < -1) {
JMP(p->buffer, o)
JIT__INFO2(p)
}
}
void JIT_BRANCH(struct jit_parsing *p, int s, int t, int o)
{
if (s == t) {
JIT_JUMP(p, o);
return;
}
JIT__INFO(p)
if (o > 0 || o < -1) {
if (s == JIT_R0) CMPI8(p->buffer, t, 0)
else if (t == JIT_R0) CMPI8(p->buffer, s, 0)
else CMP64(p->buffer, s, t)
SETE(p->buffer, AL)
MOVZX(p->buffer, RAX, AL)
JNZ(p->buffer, o)
JIT__INFO2(p)
}
}
void JIT_NBRANCH(struct jit_parsing *p, int s, int t, int o)
{
JIT__INFO(p)
if ((o > 0 || o < -1) && (s != t)) {
if (s == JIT_R0) CMPI8(p->buffer, t, 0)
else if (t == JIT_R0) CMPI8(p->buffer, s, 0)
else CMP64(p->buffer, s, t)
SETE(p->buffer, AL)
MOVZX(p->buffer, RAX, AL)
JZ(p->buffer, o)
JIT__INFO2(p)
}
}
void JIT_CALL(struct jit_parsing *p, int o)
{
JIT__INFO(p)
if (o > 0 || o < -1) {
CALLI32(p->buffer, o)
JIT__INFO2(p)
}
}
void JIT_CALLEX(struct jit_parsing *p, int s)
{
JIT__INFO(p)
if (s != JIT_R0) CALL64(p->buffer, s)
}
void JIT_RETURN(struct jit_parsing *p)
{
JIT__INFO(p)
RET(p->buffer)
}
void JIT_LOADF(struct jit_parsing *p, int d, int s, int o)
{
JIT__INFO(p)
if (d != JIT_R0 && s != JIT_R0) {
if (s == JIT_SP) {
MOV(p->buffer, RAX, s)
LOADSS(p->buffer, d, RAX, o)
}
else {
LOADSS(p->buffer, d, s, o)
}
}
}
void JIT_STOREF(struct jit_parsing *p, int d, int o, int s)
{
JIT__INFO(p)
if (d != JIT_R0 && s != JIT_R0) {
if (d == JIT_SP) {
MOV(p->buffer, RAX, d)
STORESS(p->buffer, RAX, o, s)
}
else {
STORESS(p->buffer, d, o, s)
}
}
}
void JIT_ITOF(struct jit_parsing *p, int d, int s)
{
JIT__INFO(p)
PXOR(p->buffer, d, d)
if (s != JIT_R0) CVTSI2SS(p->buffer, d, s)
}
void JIT_FTOI(struct jit_parsing *p, int d, int s)
{
JIT__INFO(p)
if (d != JIT_R0) CVTSS2SI(p->buffer, d, s)
}
void JIT_ADDF(struct jit_parsing *p, int d, int s, int t)
{
JIT__INFO(p)
if (s != d) MOVSS(p->buffer, d, s)
ADDSS(p->buffer, d, t)
}
void JIT_SUBF(struct jit_parsing *p, int d, int s, int t)
{
JIT__INFO(p)
if (s != d) MOVSS(p->buffer, d, s)
SUBSS(p->buffer, d, t)
}
void JIT_MULF(struct jit_parsing *p, int d, int s, int t)
{
JIT__INFO(p)
if (s != d) MOVSS(p->buffer, d, s)
MULSS(p->buffer, d, t)
}
void JIT_DIVF(struct jit_parsing *p, int d, int s, int t)
{
JIT__INFO(p)
if (s != d) MOVSS(p->buffer, d, s)
DIVSS(p->buffer, d, t)
}
void JIT_LESSF(struct jit_parsing *p, int d, int s, int t)
{
JIT__INFO(p)
UCOMISS(p->buffer, s, t)
SETA(p->buffer, AL)
MOVZX(p->buffer, RAX, AL)
MOV(p->buffer, d, RAX)
}
void JIT_MINF(struct jit_parsing *p, int d, int s, int t)
{
JIT__INFO(p)
if (s != d) MOVSS(p->buffer, d, s)
MINSS(p->buffer, d, t)
}
void JIT_MAXF(struct jit_parsing *p, int d, int s, int t)
{
JIT__INFO(p)
if (s != d) MOVSS(p->buffer, d, s)
MAXSS(p->buffer, d, t)
}
void JIT_LOADF4(struct jit_parsing *p, int d, int s, int o)
{
JIT__INFO(p)
if (d != JIT_R0 && s != JIT_R0) {
if (s == JIT_SP) {
MOV(p->buffer, RAX, s)
LOADUPS(p->buffer, d, RAX, o)
}
else {
LOADUPS(p->buffer, d, s, o)
}
}
}
void JIT_STOREF4(struct jit_parsing *p, int d, int o, int s)
{
JIT__INFO(p)
if (d != JIT_R0 && s != JIT_R0) {
if (d == JIT_SP) {
MOV(p->buffer, RAX, d)
STOREUPS(p->buffer, RAX, o, s)
}
else {
STOREUPS(p->buffer, d, o, s)
}
}
}
void JIT_ADDF4(struct jit_parsing *p, int d, int s, int t)
{
JIT__INFO(p)
if (s != d) MOVUPS(p->buffer, d, s)
ADDPS(p->buffer, d, t)
}
void JIT_SUBF4(struct jit_parsing *p, int d, int s, int t)
{
JIT__INFO(p)
if (s != d) MOVUPS(p->buffer, d, s)
SUBPS(p->buffer, d, t)
}
void JIT_MULF4(struct jit_parsing *p, int d, int s, int t)
{
JIT__INFO(p)
if (s != d) MOVUPS(p->buffer, d, s)
MULPS(p->buffer, d, t)
}
void JIT_DIVF4(struct jit_parsing *p, int d, int s, int t)
{
JIT__INFO(p)
if (s != d) MOVUPS(p->buffer, d, s)
DIVPS(p->buffer, d, t)
}
void JIT_MINF4(struct jit_parsing *p, int d, int s, int t)
{
JIT__INFO(p)
if (s != d) MOVUPS(p->buffer, d, s)
MINPS(p->buffer, d, t)
}
void JIT_MAXF4(struct jit_parsing *p, int d, int s, int t)
{
JIT__INFO(p)
if (s != d) MOVUPS(p->buffer, d, s)
MAXPS(p->buffer, d, t)
}
void jit_create(struct jit_state *s, int size)
{
s->buffer_size = size * 32;
#ifdef _WIN32
s->buffer = VirtualAlloc(NULL, s->buffer_size, MEM_COMMIT, PAGE_EXECUTE_READWRITE);
#else
s->buffer = mmap(0, s->buffer_size, PROT_READ|PROT_WRITE|PROT_EXEC, MAP_PRIVATE|MAP_ANON, -1, 0);
#endif
if (s->buffer == (void*)-1) {
printf("jit mmap error\n");
return;
}
s->info1 = malloc(size * sizeof(uint8_t *));
s->info2 = malloc(size * sizeof(uint16_t));
}
void jit_destroy(struct jit_state *s)
{
free(s->info2);
free(s->info1);
#ifdef _WIN32
VirtualFree(s->buffer, 0, MEM_RELEASE);
#else
munmap(s->buffer, s->buffer_size);
#endif
}
void jit_begin(struct jit_state *s)
{
s->p.buffer = s->buffer;
s->p.info1 = s->info1;
s->p.info2 = s->info2;
s->p.i1 = 0;
}
void jit_relocate(struct jit_state *s)
{
uint8_t **info1 = s->info1;
uint16_t *info2 = s->info2;
struct jit_parsing *p = &s->p;
uint16_t *i = info2;
while (i < p->info2) {
int i2o;
int i2 = i[0];
int32_t *o = (int32_t *)(info1[i2] - 4);
i2o = info1[i2 + *o] - info1[i2];
*o = i2o;
i++;
}
}
struct jit_state jit_s;
void test_x8664(uint8_t *buffer)
{
RET(buffer)
}
void test_risc_equ(struct jit_parsing *p)
{
// ==
JIT_BRANCH(p, JIT_A1, JIT_A2, 2);
JIT_ADDI(p, JIT_RE, JIT_R0, 0);
JIT_RETURN(p);
JIT_ADDI(p, JIT_RE, JIT_R0, 1);
JIT_RETURN(p);
//JIT_LESS(p, JIT_RE, JIT_A1, JIT_A2);
//JIT_RETURN(p);
// == avec jump < 0
/*
JIT_JUMP(p, 2);
JIT_ADDI(p, JIT_RE, JIT_R0, 1);
JIT_RETURN(p);
JIT_BRANCH(p, JIT_A1, JIT_A2, -3);
JIT_ADDI(p, JIT_RE, JIT_R0, 0);
JIT_RETURN(p);
*/
}
void test_risc(struct jit_parsing *p)
{
// push stack
JIT_ADDI(p, JIT_SP, JIT_SP, -8);
// save R3
JIT_STORE64(p, JIT_SP, 0, JIT_R3);
// add
JIT_ADD(p, JIT_R1, JIT_A1, JIT_A2);
// counter
JIT_LOAD32(p, JIT_R2, JIT_A3, 0);
JIT_ADDI(p, JIT_R2, JIT_R2, 1);
JIT_STORE32(p, JIT_A3, 0, JIT_R2);
// restore R3
JIT_LOAD64(p, JIT_R3, JIT_SP, 0);
// pop stack
JIT_ADDI(p, JIT_SP, JIT_SP, 8);
JIT_ADDI(p, JIT_RE, JIT_R1, 0);
JIT_RETURN(p);
}
void test_risc_float(struct jit_parsing *p)
{
JIT_ADDF(p, JIT_RF0, JIT_RF0, JIT_RF1);
JIT_RETURN(p);
}
void test_risc_float4(struct jit_parsing *p)
{
JIT_LOADF4(p, JIT_RF0, JIT_A1, 0);
JIT_LOADF4(p, JIT_RF1, JIT_A1, 16);
JIT_ADDF4(p, JIT_RF0, JIT_RF0, JIT_RF1);
JIT_STOREF4(p, JIT_A1, 32, JIT_RF0);
JIT_RETURN(p);
}
void test_int()
{
int mem[4] = {1, 10, 0, 0};
typedef int (*fun_t)(int, int, int *);
int i;
jit_begin(&jit_s);
test_risc(&jit_s.p);
jit_relocate(&jit_s);
fun_t func = (fun_t)jit_s.buffer;
for (i = 0; i < 10; i++)
mem[2] = func(mem[0], mem[1], &mem[3]);
printf("result = %d %d\n", mem[2], mem[3]);
}
void test_float()
{
float mem[4] = {2.2, 10.10, 22.22, 0.1};
typedef float (*fun_t)(float, float, float *);
int i;
jit_begin(&jit_s);
test_risc_float(&jit_s.p);
jit_relocate(&jit_s);
fun_t func = (fun_t)jit_s.buffer;
//void *dl = dlopen(0, RTLD_LAZY | RTLD_GLOBAL);
//void *ptr = dlsym(dl, "sinf");
//dlclose(dl);
float d;
for (i = 0; i < 1000; i++)
d = func(mem[0], mem[1], mem);
printf("result = %f\n", d);
}
void test_float4()
{
float mem[12] = {
2.2, 10.10, 22.22, 0.1,
0.1, 0.20, 0.3, 0.4,
0.0, 0.0, 0.0, 0.0
};
typedef void (*fun_t)(float *);
int i;
jit_begin(&jit_s);
test_risc_float4(&jit_s.p);
jit_relocate(&jit_s);
fun_t func = (fun_t)jit_s.buffer;
for (i = 0; i < 1000; i++)
func(mem);
printf("result = %f %f %f %f\n", mem[8], mem[9], mem[10], mem[11]);
}
void test_jit()
{
//test_int();
test_float4();
}
void ctoy_begin(void)
{
jit_create(&jit_s, 256);
double t = ctoy_get_time();
test_jit();
printf("(%f sec)\n", ctoy_get_time() - t);
jit_destroy(&jit_s);
}
void ctoy_main_loop(void)
{
ctoy_sleep(0, 1000000);
}
void ctoy_end(void)
{}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
You can’t perform that action at this time.