Skip to content

Instantly share code, notes, and snippets.

@karino2
Created April 19, 2019 03:37
Show Gist options
  • Save karino2/b0aeb68883d6d40377e9d3ba769e160b to your computer and use it in GitHub Desktop.
Save karino2/b0aeb68883d6d40377e9d3ba769e160b to your computer and use it in GitHub Desktop.
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <sys/mman.h>
#include "parser.h"
#include "test_util.h"
extern int eval(int r0, int r1, char *str);
/*
JIT
*/
int *binary_buf = NULL;
int* allocate_executable_buf(int size) {
return (int*)mmap(0, size,
PROT_READ | PROT_WRITE | PROT_EXEC,
MAP_PRIVATE | MAP_ANONYMOUS, -1, 0);
}
void init_jit() {
if(binary_buf == NULL) {
binary_buf = allocate_executable_buf(1024);
}
}
int binary_pos = 0;
void emit_word(int word) {
binary_buf[binary_pos++] = word;
}
int asm_mov_reg(int reg_1st, int reg_2nd) {
int oneword = 0xE1A00000;
oneword += reg_1st << 12;
oneword += reg_2nd;
return oneword;
}
void emit_mov_reg(int reg1, int reg2) {
emit_word(asm_mov_reg(reg1, reg2));
}
int asm_mov_imm(int reg, int imm_value) {
int oneword = 0xE3A00000;
oneword += reg << 12;
oneword += imm_value;
return oneword;
}
int asm_add_sub_common(int reg1, int dest_reg, int reg3, int baseword) {
int oneword = baseword;
oneword += reg1 << 16;
oneword += dest_reg << 12;
oneword += reg3;
return oneword;
}
int asm_add_reg(int reg1, int dest_reg, int reg3) {
// p29
// 00I OPCODE = 000 0100 = 0000 100
// OPCODE S = 100 0 = 8
return asm_add_sub_common(reg1, dest_reg, reg3, 0xE0800000);
// return asm_add_sub_common(reg1, dest_reg, reg3, 0xE2800000);
}
int asm_sub_reg(int reg1, int dest_reg, int reg3) {
// return asm_add_sub_common(reg1, dest_reg, reg3, 0xE2400000);
return asm_add_sub_common(reg1, dest_reg, reg3, 0xE0400000);
}
// mul r3, r1, r2
// r3 = r1*r2
int asm_mul_reg(int reg_dest, int reg1, int reg2) {
// p40.
// 0000
// 00AS = 0000
// rd XXXX rs 1001 rm
// XXXX is ignored.
int oneword = 0xe0000090;
oneword += reg_dest<<16;
oneword += reg1<<8;
oneword += reg2;
return oneword;
}
// always write back.
int asm_stmdb(int basereg, int registerlist) {
int stmdb = 0xe9200000;
stmdb += basereg << 16;
stmdb += registerlist;
return stmdb;
}
int asm_ldmia(int basereg, int registerlist) {
int ldmia = 0xe8b00000;
ldmia += basereg << 16;
ldmia += registerlist;
return ldmia;
}
// strdb r0, [r1]!
int asm_strdb(int basereg, int destreg) {
// p42.
// int oneword = 0xE5000000;
// int stmdb = 0xe9200000;
// 01IP = 0101 = 5
// UBWL = 0010 = 2
int oneword = 0xE5200000;
oneword += basereg << 16;
oneword += destreg << 12;
return oneword;
}
// ldria r0, [r1]!
int asm_ldria(int basereg, int srcreg) {
// int ldmia = 0xe8b00000;
// 01IP = 0100 = 4
// UBWL = 0011 = 3
int oneword = 0xE4300000;
oneword += basereg << 16;
oneword += srcreg << 12;
return oneword;
}
void emit_push_reg(int reg) {
int word;
// word = asm_strdb(reg, 13);
word = asm_stmdb(13, 1<<reg);
emit_word(word);
}
// mov r2, val
// ldr r2, [r13]!
void emit_push_val(int val) {
int word;
word = asm_mov_imm(2, val);
emit_word(word);
emit_push_reg(2);
}
void emit_pop_reg(int reg) {
int word;
// word = asm_ldria(reg, 13);
word = asm_ldmia(13, 1 << reg);
emit_word(word);
}
/*
ldria r3 [r13]!
ldria r2 [r13]!
*/
void emit_pop_r2_r3() {
emit_pop_reg(3);
emit_pop_reg(2);
}
// add r2, r2, r3
void emit_add_r2_r3() {
int word = asm_add_reg(2, 2, 3);
emit_word(word);
}
void emit_sub_r2_r3() {
int word = asm_sub_reg(2, 2, 3);
emit_word(word);
}
void emit_mul_r2_r3() {
int word = asm_mul_reg(2, 2, 3);
emit_word(word);
}
int* jit_script(char *input) {
binary_pos = 0;
struct Substr remain={input, strlen(input)};
int val;
while(!is_end(&remain)) {
skip_space(&remain);
if(is_number(remain.ptr)) {
val = parse_number(remain.ptr);
emit_push_val(val);
skip_token(&remain);
continue;
}else if(is_register(remain.ptr)) {
if(remain.ptr[1] == '1') {
emit_push_reg(1);
} else {
emit_push_reg(0);
}
skip_token(&remain);
continue;
} else {
// must be op.
val = parse_word(&remain);
skip_token(&remain);
emit_pop_r2_r3();
switch(val) {
case OP_ADD:
emit_add_r2_r3();
break;
case OP_SUB:
emit_sub_r2_r3();
break;
case OP_MUL:
emit_mul_r2_r3();
break;
case OP_DIV:
fprintf(stderr, "div not supported\n");
exit(1);
break;
}
// result is in r2.
emit_push_reg(2);
continue;
}
}
// final result, pop to r0
emit_pop_reg(0);
emit_mov_reg(15, 14);
return binary_buf;
}
static void run_unit_tests() {
printf("all test done\n");
}
int main() {
int res;
int (*funcvar)(int, int);
run_unit_tests();
res = eval(1, 5, "3 7 add r1 sub 4 mul");
printf("res=%d\n", res);
/*
TODO: Make below test pass.
*/
init_jit();
funcvar = (int(*)(int,int))jit_script("3 7 add r1 sub 4 mul");
// funcvar = (int(*)(int,int))jit_script("3 7 add 5 sub 4 mul");
// funcvar = (int(*)(int,int))jit_script("3 7 add");
/*
// mov r0, #5
binary_buf[0] = 0xe3a00005;
// mov r15, r14
binary_buf[1] = 0xe1a0f00e;
*/
/* OK
binary_pos = 0;
int word = asm_mov_imm(2, 3);
printf("%x\n", word);
emit_word(word);
word = asm_stmdb(13, 1<<2);
printf("%x\n", word);
emit_word(word);
word = asm_mov_imm(2, 7);
printf("%x\n", word);
emit_word(word);
word = asm_stmdb(13, 1<<2);
printf("%x\n", word);
emit_word(word);
// 1100 = c
word = asm_ldmia(13, 0x0c);
printf("%x\n", word);
emit_word(word);
word = asm_add_reg(2, 2, 3);
printf("%x\n", word);
emit_word(word);
word = asm_stmdb(13, 1<<2);
printf("%x\n", word);
emit_word(word);
word = asm_ldmia(13, 0x01);
printf("%x\n", word);
emit_word(word);
word = asm_mov_reg(15, 14);
printf("%x\n", word);
emit_word(word);
funcvar = (int(*)(int,int))binary_buf;
*/
/* OK
binary_pos = 0;
int word = asm_mov_imm(2, 8);
printf("%x\n", word);
emit_word(word);
// word = asm_strdb(2, 13);
word = asm_stmdb(13, 0x04);
printf("%x\n", word);
emit_word(word);
word = asm_ldmia(13, 0x01);
printf("%x\n", word);
emit_word(word);
word = asm_mov_reg(15, 14);
printf("%x\n", word);
emit_word(word);
funcvar = (int(*)(int,int))binary_buf;
*/
/*
asm_ldria(0, 13);
printf("%x\n", word);
emit_word(word);
*/
/*OK
int word = asm_mov_imm(2, 3);
printf("%x\n", word);
emit_word(word);
word = asm_mov_imm(3, 7);
printf("%x\n", word);
emit_word(word);
word = asm_add_reg(2, 0, 3);
printf("%x\n", word);
emit_word(word);
word = asm_mov_reg(15, 14);
printf("%x\n", word);
emit_word(word);
funcvar = (int(*)(int,int))binary_buf;
*/
/* OK.
int word = asm_mov_imm(0, 5);
printf("%x\n", word);
emit_word(word);
word = asm_mov_reg(15, 14);
printf("%x\n", word);
emit_word(word);
funcvar = (int(*)(int,int))binary_buf;
*/
res = funcvar(1, 5);
printf("res jit =%d\n", res);
assert_int_eq(20, res);
res = funcvar(1, 4);
assert_int_eq(24, res);
return 0;
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment