fib example
This commit is contained in:
parent
ee39c8ba95
commit
18697c92b6
|
|
@ -71,31 +71,86 @@ u32 syscall(u32 id, u32 mem_ptr) {
|
||||||
return 1; // generic error
|
return 1; // generic error
|
||||||
}
|
}
|
||||||
|
|
||||||
static void repl() {
|
//static void repl() {
|
||||||
ScopeTable st;
|
// ScopeTable st;
|
||||||
char line[1024];
|
// char line[1024];
|
||||||
for (;;) {
|
// for (;;) {
|
||||||
printf("> ");
|
// printf("> ");
|
||||||
|
//
|
||||||
|
// if (!fgets(line, sizeof(line), stdin)) {
|
||||||
|
// printf("\n");
|
||||||
|
// break;
|
||||||
|
// }
|
||||||
|
//
|
||||||
|
// reset();
|
||||||
|
//
|
||||||
|
// compile(&st, line);
|
||||||
|
//
|
||||||
|
// while(step_vm()) {}
|
||||||
|
//
|
||||||
|
// syscall(SYSCALL_CONSOLE_WRITE, stack[0]);
|
||||||
|
// }
|
||||||
|
//}
|
||||||
|
|
||||||
if (!fgets(line, sizeof(line), stdin)) {
|
void fib() {
|
||||||
printf("\n");
|
u8 fib_ptr = 10;
|
||||||
break;
|
code[cp++] = OP_PUSH_8;
|
||||||
}
|
code[cp++] = 35;
|
||||||
|
code[cp++] = OP_PUSH_8;
|
||||||
reset();
|
code[cp++] = fib_ptr;
|
||||||
|
code[cp++] = OP_CALL;
|
||||||
compile(&st, line);
|
code[cp++] = OP_INT_TO_STR;
|
||||||
|
code[cp++] = OP_PUSH_8;
|
||||||
|
code[cp++] = SYSCALL_CONSOLE_WRITE;
|
||||||
|
code[cp++] = OP_SYSCALL;
|
||||||
|
code[cp++] = OP_HALT;
|
||||||
|
/* fib (int n) int */
|
||||||
|
code[cp++] = OP_SET_IMM;
|
||||||
|
code[cp++] = 0;
|
||||||
|
/* if (n < 2) { */
|
||||||
|
code[cp++] = OP_GET_IMM;
|
||||||
|
code[cp++] = 0;
|
||||||
|
code[cp++] = OP_PUSH_8;
|
||||||
|
code[cp++] = 2;
|
||||||
|
code[cp++] = OP_LTS;
|
||||||
|
code[cp++] = OP_PUSH_8;
|
||||||
|
u8 if_true = cp + 5;
|
||||||
|
code[cp++] = if_true;
|
||||||
|
code[cp++] = OP_JNZ;
|
||||||
|
code[cp++] = OP_PUSH_8;
|
||||||
|
u8 if_false = cp + 5;
|
||||||
|
code[cp++] = if_false;
|
||||||
|
code[cp++] = OP_JMP;
|
||||||
|
code[cp++] = OP_GET_IMM;
|
||||||
|
code[cp++] = 0;
|
||||||
|
code[cp++] = OP_RETURN;
|
||||||
|
code[cp++] = OP_GET_IMM;
|
||||||
|
code[cp++] = 0;
|
||||||
|
code[cp++] = OP_PUSH_8;
|
||||||
|
code[cp++] = 2;
|
||||||
|
code[cp++] = OP_SUB_INT;
|
||||||
|
code[cp++] = OP_PUSH_8;
|
||||||
|
code[cp++] = fib_ptr;
|
||||||
|
code[cp++] = OP_CALL;
|
||||||
|
code[cp++] = OP_GET_IMM;
|
||||||
|
code[cp++] = 0;
|
||||||
|
code[cp++] = OP_PUSH_8;
|
||||||
|
code[cp++] = 1;
|
||||||
|
code[cp++] = OP_SUB_INT;
|
||||||
|
code[cp++] = OP_PUSH_8;
|
||||||
|
code[cp++] = fib_ptr;
|
||||||
|
code[cp++] = OP_CALL;
|
||||||
|
code[cp++] = OP_ADD_INT;
|
||||||
|
code[cp++] = OP_RETURN;
|
||||||
|
|
||||||
while(step_vm()) {}
|
while(step_vm()) {}
|
||||||
|
|
||||||
syscall(SYSCALL_CONSOLE_WRITE, stack[0]);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
i32 main() {
|
i32 main() {
|
||||||
init_vm();
|
init_vm();
|
||||||
|
|
||||||
repl();
|
fib();
|
||||||
|
//repl();
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -4,6 +4,11 @@
|
||||||
#include <stdio.h>
|
#include <stdio.h>
|
||||||
#include <stdlib.h>
|
#include <stdlib.h>
|
||||||
|
|
||||||
|
Token operator_stack[128];
|
||||||
|
u8 osp;
|
||||||
|
Token value_stack[256];
|
||||||
|
u8 vsp;
|
||||||
|
|
||||||
Parser parser;
|
Parser parser;
|
||||||
|
|
||||||
Symbol *symbol_table_lookup(ScopeTable *table, const char *name, u32 length,
|
Symbol *symbol_table_lookup(ScopeTable *table, const char *name, u32 length,
|
||||||
|
|
|
||||||
104
vm/vm.c
104
vm/vm.c
|
|
@ -28,66 +28,25 @@ u32 str_alloc(char *str, u32 length) {
|
||||||
}
|
}
|
||||||
|
|
||||||
bool step_vm() {
|
bool step_vm() {
|
||||||
|
u16 opcode = code[pc++];
|
||||||
u8 opcode = code[pc++];
|
|
||||||
/*u32 *locals = (u32*)(&mem[fp]);*/
|
|
||||||
u32 *globals = (u32*)(mem);
|
|
||||||
|
|
||||||
switch (opcode) {
|
switch (opcode) {
|
||||||
case OP_HALT: {
|
case OP_HALT: {
|
||||||
/* no need to decode, all are zeros */
|
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
case OP_CALL: {
|
case OP_CALL: {
|
||||||
/* function to jump to */
|
|
||||||
u32 fn_ptr = stack[--sp];
|
u32 fn_ptr = stack[--sp];
|
||||||
/* get mp in 'global indexing mode' */
|
frames[fp].return_pc = pc;
|
||||||
u32 *header = &globals[mp / 4];
|
frames[fp++].start_mp = mp;
|
||||||
/* push parents frame value to reset the heap to */
|
|
||||||
(*header++) = fp;
|
|
||||||
/* increase the mp to new size */
|
|
||||||
mp += FRAME_HEADER_SIZE;
|
|
||||||
/* now set the frame pointer, where the locals start */
|
|
||||||
fp = mp;
|
|
||||||
/* move mp forward by count many locals */
|
|
||||||
mp += stack[--sp];
|
|
||||||
/* jump to dest_ptr */
|
|
||||||
pc = fn_ptr;
|
pc = fn_ptr;
|
||||||
return false;
|
return true;
|
||||||
}
|
}
|
||||||
case OP_RETURN: {
|
case OP_RETURN: {
|
||||||
/* TODO: Fix this one so it makes sense with a stack based system */
|
u32 return_pc = frames[--fp].return_pc;
|
||||||
u32 size = 0;
|
u32 return_mp = frames[fp].start_mp;
|
||||||
u32 return_value = stack[--sp];
|
mp = return_mp;
|
||||||
bool is_ptr = (((u32)(1)) << 15) & return_value;
|
pc = return_pc;
|
||||||
|
return true;
|
||||||
/* reset mp to saved mp, use header size to get "real" start of frame */
|
|
||||||
u32 *frame_start = &globals[(fp / 4) - 3];
|
|
||||||
u32 parent_fp = *frame_start++;
|
|
||||||
u32 return_address = *frame_start++;
|
|
||||||
u32 parent_local_return_address = *frame_start++;
|
|
||||||
|
|
||||||
/* reset memory to parents end of memory */
|
|
||||||
mp = fp - FRAME_HEADER_SIZE;
|
|
||||||
/* reset the frame pointer */
|
|
||||||
fp = parent_fp;
|
|
||||||
|
|
||||||
if (is_ptr) {
|
|
||||||
/* copy value to end of mp if it is a pointer */
|
|
||||||
globals[parent_local_return_address/4] = mp;
|
|
||||||
size = globals[return_value/4];
|
|
||||||
globals[mp/4] = size;
|
|
||||||
mp += 4;
|
|
||||||
mcpy(&mem[mp], &mem[return_value], size);
|
|
||||||
mp += size;
|
|
||||||
} else {
|
|
||||||
/* otherwise just write the return value to its location */
|
|
||||||
mcpy(&mem[parent_local_return_address], &return_value, sizeof(u32));
|
|
||||||
}
|
|
||||||
|
|
||||||
/* jump to parent frame */
|
|
||||||
pc = return_address;
|
|
||||||
return false;
|
|
||||||
}
|
}
|
||||||
case OP_SYSCALL: {
|
case OP_SYSCALL: {
|
||||||
u32 id = stack[--sp]; /* syscall id */
|
u32 id = stack[--sp]; /* syscall id */
|
||||||
|
|
@ -115,10 +74,48 @@ bool step_vm() {
|
||||||
stack[sp++] = value;
|
stack[sp++] = value;
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
case OP_PUSH_MP: {
|
||||||
|
stack[sp++] = mp;
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
case OP_PUSH_START_MP: {
|
||||||
|
stack[sp++] = frames[fp - 1].start_mp;
|
||||||
|
return true;
|
||||||
|
}
|
||||||
case OP_POP: {
|
case OP_POP: {
|
||||||
--sp;
|
--sp;
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
case OP_SET:{
|
||||||
|
Frame *f = &frames[fp - 1];
|
||||||
|
u32 *locals = f->locals;
|
||||||
|
u8 ptr = (u8)stack[--sp];
|
||||||
|
u32 value = stack[--sp];
|
||||||
|
locals[ptr] = value;
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
case OP_SET_IMM:{
|
||||||
|
Frame *f = &frames[fp - 1];
|
||||||
|
u32 *locals = f->locals;
|
||||||
|
u8 ptr = code[pc++];
|
||||||
|
u32 value = stack[--sp];
|
||||||
|
locals[ptr] = value;
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
case OP_GET:{
|
||||||
|
Frame *f = &frames[fp - 1];
|
||||||
|
u32 *locals = f->locals;
|
||||||
|
u8 ptr = (u8)stack[--sp];
|
||||||
|
stack[sp++] = locals[ptr];
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
case OP_GET_IMM:{
|
||||||
|
Frame *f = &frames[fp - 1];
|
||||||
|
u32 *locals = f->locals;
|
||||||
|
u8 ptr = code[pc++];
|
||||||
|
stack[sp++] = locals[ptr];
|
||||||
|
return true;
|
||||||
|
}
|
||||||
case OP_LOAD_8: {
|
case OP_LOAD_8: {
|
||||||
u32 ptr = stack[--sp];
|
u32 ptr = stack[--sp];
|
||||||
u32 value = mem[ptr];
|
u32 value = mem[ptr];
|
||||||
|
|
@ -180,6 +177,7 @@ bool step_vm() {
|
||||||
|
|
||||||
ptr_dest = &mem[dest];
|
ptr_dest = &mem[dest];
|
||||||
ptr_src = &mem[src];
|
ptr_src = &mem[src];
|
||||||
|
if (ptr_dest == ptr_src) { return true; }
|
||||||
mcpy(ptr_dest, ptr_src, count*sizeof(u8));
|
mcpy(ptr_dest, ptr_src, count*sizeof(u8));
|
||||||
|
|
||||||
status = 0;
|
status = 0;
|
||||||
|
|
@ -199,6 +197,7 @@ bool step_vm() {
|
||||||
|
|
||||||
ptr_dest = &mem[dest];
|
ptr_dest = &mem[dest];
|
||||||
ptr_src = &mem[src];
|
ptr_src = &mem[src];
|
||||||
|
if (ptr_dest == ptr_src) { return true; }
|
||||||
mcpy(ptr_dest, ptr_src, count*sizeof(u16));
|
mcpy(ptr_dest, ptr_src, count*sizeof(u16));
|
||||||
|
|
||||||
status = 0;
|
status = 0;
|
||||||
|
|
@ -218,6 +217,7 @@ bool step_vm() {
|
||||||
|
|
||||||
ptr_dest = &mem[dest];
|
ptr_dest = &mem[dest];
|
||||||
ptr_src = &mem[src];
|
ptr_src = &mem[src];
|
||||||
|
if (ptr_dest == ptr_src) { return true; }
|
||||||
mcpy(ptr_dest, ptr_src, count*sizeof(u32));
|
mcpy(ptr_dest, ptr_src, count*sizeof(u32));
|
||||||
|
|
||||||
status = 0;
|
status = 0;
|
||||||
|
|
@ -472,9 +472,9 @@ bool step_vm() {
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
case OP_JNZ: {
|
case OP_JNZ: {
|
||||||
u32 mask, target;
|
u32 mask;
|
||||||
|
u32 target = stack[--sp];
|
||||||
i32 cond = stack[--sp];
|
i32 cond = stack[--sp];
|
||||||
target = stack[--sp];
|
|
||||||
mask = -(u32)cond;
|
mask = -(u32)cond;
|
||||||
pc = (target & mask) | (pc & ~mask);
|
pc = (target & mask) | (pc & ~mask);
|
||||||
return true;
|
return true;
|
||||||
|
|
|
||||||
7
vm/vm.h
7
vm/vm.h
|
|
@ -18,6 +18,12 @@ typedef enum {
|
||||||
OP_PUSH_8, /* const `push8` obj1 | push a 8 bit const onto the stack */
|
OP_PUSH_8, /* const `push8` obj1 | push a 8 bit const onto the stack */
|
||||||
OP_PUSH_16, /* const `push16` obj1 | push a 16 bit const onto the stack */
|
OP_PUSH_16, /* const `push16` obj1 | push a 16 bit const onto the stack */
|
||||||
OP_PUSH_32, /* const `push32` obj1 | push a 32 bit const onto the stack */
|
OP_PUSH_32, /* const `push32` obj1 | push a 32 bit const onto the stack */
|
||||||
|
OP_PUSH_MP, /* - `pmp` mp | push current mp to stack */
|
||||||
|
OP_PUSH_START_MP, /* - `psmp` mp | push the frames start mp to stack (parent frames end mp); used for returning heap values to parent */
|
||||||
|
OP_SET, /* obj dest `set` - | sets a local to the next value on top of the stack (max 255) */
|
||||||
|
OP_GET, /* dest `get` obj | pushes a local from the value on top of the stack (max 255) */
|
||||||
|
OP_SET_IMM, /* obj #dest `seti` - | sets a local to the next immediate location (max 255) */
|
||||||
|
OP_GET_IMM, /* #dest `geti` obj | pushes a local from the immediate location (max 255) */
|
||||||
OP_POP, /* - `pop` - | removes top item from the stack */
|
OP_POP, /* - `pop` - | removes top item from the stack */
|
||||||
OP_DUP, /* obj1 `dup` obj1 obj1 | duplicates the top of the stack */
|
OP_DUP, /* obj1 `dup` obj1 obj1 | duplicates the top of the stack */
|
||||||
OP_EXCH, /* obj2 obj1 `exch` obj1 obj2 | swaps the top two values on the stack */
|
OP_EXCH, /* obj2 obj1 `exch` obj1 obj2 | swaps the top two values on the stack */
|
||||||
|
|
@ -89,6 +95,7 @@ typedef enum {
|
||||||
|
|
||||||
typedef struct frame_s Frame;
|
typedef struct frame_s Frame;
|
||||||
struct frame_s {
|
struct frame_s {
|
||||||
|
u32 locals[256];
|
||||||
u32 return_pc;
|
u32 return_pc;
|
||||||
u32 start_mp;
|
u32 start_mp;
|
||||||
};
|
};
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue