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
|
||||
}
|
||||
|
||||
static void repl() {
|
||||
ScopeTable st;
|
||||
char line[1024];
|
||||
for (;;) {
|
||||
printf("> ");
|
||||
//static void repl() {
|
||||
// ScopeTable st;
|
||||
// char line[1024];
|
||||
// for (;;) {
|
||||
// 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)) {
|
||||
printf("\n");
|
||||
break;
|
||||
}
|
||||
void fib() {
|
||||
u8 fib_ptr = 10;
|
||||
code[cp++] = OP_PUSH_8;
|
||||
code[cp++] = 35;
|
||||
code[cp++] = OP_PUSH_8;
|
||||
code[cp++] = fib_ptr;
|
||||
code[cp++] = OP_CALL;
|
||||
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;
|
||||
|
||||
reset();
|
||||
|
||||
compile(&st, line);
|
||||
|
||||
while(step_vm()) {}
|
||||
|
||||
syscall(SYSCALL_CONSOLE_WRITE, stack[0]);
|
||||
}
|
||||
while(step_vm()) {}
|
||||
}
|
||||
|
||||
i32 main() {
|
||||
init_vm();
|
||||
|
||||
repl();
|
||||
fib();
|
||||
//repl();
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -4,6 +4,11 @@
|
|||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
|
||||
Token operator_stack[128];
|
||||
u8 osp;
|
||||
Token value_stack[256];
|
||||
u8 vsp;
|
||||
|
||||
Parser parser;
|
||||
|
||||
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() {
|
||||
|
||||
u8 opcode = code[pc++];
|
||||
/*u32 *locals = (u32*)(&mem[fp]);*/
|
||||
u32 *globals = (u32*)(mem);
|
||||
u16 opcode = code[pc++];
|
||||
|
||||
switch (opcode) {
|
||||
case OP_HALT: {
|
||||
/* no need to decode, all are zeros */
|
||||
return false;
|
||||
}
|
||||
case OP_CALL: {
|
||||
/* function to jump to */
|
||||
u32 fn_ptr = stack[--sp];
|
||||
/* get mp in 'global indexing mode' */
|
||||
u32 *header = &globals[mp / 4];
|
||||
/* 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 */
|
||||
frames[fp].return_pc = pc;
|
||||
frames[fp++].start_mp = mp;
|
||||
pc = fn_ptr;
|
||||
return false;
|
||||
return true;
|
||||
}
|
||||
case OP_RETURN: {
|
||||
/* TODO: Fix this one so it makes sense with a stack based system */
|
||||
u32 size = 0;
|
||||
u32 return_value = stack[--sp];
|
||||
bool is_ptr = (((u32)(1)) << 15) & return_value;
|
||||
|
||||
/* 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;
|
||||
u32 return_pc = frames[--fp].return_pc;
|
||||
u32 return_mp = frames[fp].start_mp;
|
||||
mp = return_mp;
|
||||
pc = return_pc;
|
||||
return true;
|
||||
}
|
||||
case OP_SYSCALL: {
|
||||
u32 id = stack[--sp]; /* syscall id */
|
||||
|
|
@ -115,10 +74,48 @@ bool step_vm() {
|
|||
stack[sp++] = value;
|
||||
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: {
|
||||
--sp;
|
||||
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: {
|
||||
u32 ptr = stack[--sp];
|
||||
u32 value = mem[ptr];
|
||||
|
|
@ -180,6 +177,7 @@ bool step_vm() {
|
|||
|
||||
ptr_dest = &mem[dest];
|
||||
ptr_src = &mem[src];
|
||||
if (ptr_dest == ptr_src) { return true; }
|
||||
mcpy(ptr_dest, ptr_src, count*sizeof(u8));
|
||||
|
||||
status = 0;
|
||||
|
|
@ -199,6 +197,7 @@ bool step_vm() {
|
|||
|
||||
ptr_dest = &mem[dest];
|
||||
ptr_src = &mem[src];
|
||||
if (ptr_dest == ptr_src) { return true; }
|
||||
mcpy(ptr_dest, ptr_src, count*sizeof(u16));
|
||||
|
||||
status = 0;
|
||||
|
|
@ -218,6 +217,7 @@ bool step_vm() {
|
|||
|
||||
ptr_dest = &mem[dest];
|
||||
ptr_src = &mem[src];
|
||||
if (ptr_dest == ptr_src) { return true; }
|
||||
mcpy(ptr_dest, ptr_src, count*sizeof(u32));
|
||||
|
||||
status = 0;
|
||||
|
|
@ -472,9 +472,9 @@ bool step_vm() {
|
|||
return true;
|
||||
}
|
||||
case OP_JNZ: {
|
||||
u32 mask, target;
|
||||
u32 mask;
|
||||
u32 target = stack[--sp];
|
||||
i32 cond = stack[--sp];
|
||||
target = stack[--sp];
|
||||
mask = -(u32)cond;
|
||||
pc = (target & mask) | (pc & ~mask);
|
||||
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_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_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_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 */
|
||||
|
|
@ -89,6 +95,7 @@ typedef enum {
|
|||
|
||||
typedef struct frame_s Frame;
|
||||
struct frame_s {
|
||||
u32 locals[256];
|
||||
u32 return_pc;
|
||||
u32 start_mp;
|
||||
};
|
||||
|
|
|
|||
Loading…
Reference in New Issue