Compare commits

..

No commits in common. "experiment/static-frame" and "main" have entirely different histories.

3 changed files with 61 additions and 64 deletions

View File

@ -1,28 +1,20 @@
#include "../../../vm/vm.h" #include "../../../vm/vm.h"
#include <stdio.h> #include <stdio.h>
#define STACK_SIZE 1024
#define CODE_SIZE 8192 #define CODE_SIZE 8192
#define MEMORY_SIZE 65536 #define MEMORY_SIZE 65536
u8 lmem[MEMORY_SIZE] = {0}; u8 lmem[MEMORY_SIZE] = {0};
u32 lcode[CODE_SIZE] = {0}; u32 lcode[CODE_SIZE] = {0};
Frame lframes[STACK_SIZE] = {0};
void reset() {
pc = 0;
cp = 0;
mp = 0;
fp = 0;
sp = 0;
interrupt = 0;
status = 0;
}
bool init_vm() { bool init_vm() {
mem = lmem; mem = lmem;
code = lcode; code = lcode;
frames = lframes; lc = 0;
reset(); mp = 0;
cp = 0;
pc = 0;
interrupt = 0;
status = 0;
return true; return true;
} }
@ -68,7 +60,7 @@ void test_add_two_num() {
i32 add = cp + 5; i32 add = cp + 5;
code[cp++] = ENCODE_B(OP_LOAD_IMM, 2, add); code[cp++] = ENCODE_B(OP_LOAD_IMM, 2, add);
code[cp++] = ENCODE_A(OP_CALL, 2, 0, 0); code[cp++] = ENCODE_A(OP_CALL, 2, 3, 0);
code[cp++] = ENCODE_A(OP_INT_TO_STR, 4, 3, 0); code[cp++] = ENCODE_A(OP_INT_TO_STR, 4, 3, 0);
code[cp++] = ENCODE_A(OP_SYSCALL, SYSCALL_CONSOLE_WRITE, 1, 4); code[cp++] = ENCODE_A(OP_SYSCALL, SYSCALL_CONSOLE_WRITE, 1, 4);
code[cp++] = ENCODE_A(OP_HALT, 0, 0, 0); code[cp++] = ENCODE_A(OP_HALT, 0, 0, 0);
@ -88,7 +80,7 @@ void test_fibonacci() {
code[cp++] = ENCODE_B(OP_LOAD_IMM, 0, 35); code[cp++] = ENCODE_B(OP_LOAD_IMM, 0, 35);
code[cp++] = ENCODE_B(OP_PARG, 0, 0); code[cp++] = ENCODE_B(OP_PARG, 0, 0);
code[cp++] = ENCODE_B(OP_LOAD_IMM, 1, fib); code[cp++] = ENCODE_B(OP_LOAD_IMM, 1, fib);
code[cp++] = ENCODE_A(OP_CALL, 1, 2, 0); code[cp++] = ENCODE_A(OP_CALL, 1, 9, 2);
/* print */ /* print */
code[cp++] = ENCODE_A(OP_INT_TO_STR, 3, 2, 0); code[cp++] = ENCODE_A(OP_INT_TO_STR, 3, 2, 0);
code[cp++] = ENCODE_A(OP_SYSCALL, SYSCALL_CONSOLE_WRITE, 1, 3); code[cp++] = ENCODE_A(OP_SYSCALL, SYSCALL_CONSOLE_WRITE, 1, 3);
@ -101,11 +93,11 @@ void test_fibonacci() {
code[cp++] = ENCODE_B(OP_LOAD_IMM, 3, 2); code[cp++] = ENCODE_B(OP_LOAD_IMM, 3, 2);
code[cp++] = ENCODE_A(OP_SUB_INT, 4, 0, 3); code[cp++] = ENCODE_A(OP_SUB_INT, 4, 0, 3);
code[cp++] = ENCODE_B(OP_PARG, 4, 0); code[cp++] = ENCODE_B(OP_PARG, 4, 0);
code[cp++] = ENCODE_A(OP_CALL, 8, 5, 0); code[cp++] = ENCODE_A(OP_CALL, 8, 9, 5);
code[cp++] = ENCODE_B(OP_LOAD_IMM, 3, 1); code[cp++] = ENCODE_B(OP_LOAD_IMM, 3, 1);
code[cp++] = ENCODE_A(OP_SUB_INT, 4, 0, 3); code[cp++] = ENCODE_A(OP_SUB_INT, 4, 0, 3);
code[cp++] = ENCODE_B(OP_PARG, 4, 0); code[cp++] = ENCODE_B(OP_PARG, 4, 0);
code[cp++] = ENCODE_A(OP_CALL, 8, 6, 0); code[cp++] = ENCODE_A(OP_CALL, 8, 9, 6);
code[cp++] = ENCODE_A(OP_ADD_INT, 7, 6, 5); code[cp++] = ENCODE_A(OP_ADD_INT, 7, 6, 5);
code[cp++] = ENCODE_B(OP_RETURN, 7, 0); code[cp++] = ENCODE_B(OP_RETURN, 7, 0);
code[cp++] = ENCODE_B(OP_RETURN, 0, 0); code[cp++] = ENCODE_B(OP_RETURN, 0, 0);

62
vm/vm.c
View File

@ -1,17 +1,15 @@
#include "vm.h" #include "vm.h"
#define FRAME_HEADER_SIZE 12 #define FRAME_HEADER_SIZE 12
u32 *stack; /* stack */
u32 sp; /* stack pointer */
u32 *code; /* code */
u32 cp; /* code pointer */
u8 *mem; /* memory */
u32 mp; /* memory pointer */
Frame *frames; /* call frames */
u32 fp; /* frame pointer */
u32 pc; /* program counter */ u32 pc; /* program counter */
u32 cp; /* code pointer */
u32 mp; /* memory pointer */
u32 fp; /* frame pointer */
u8 lc; /* child local count */
u8 status; /* status flag */ u8 status; /* status flag */
u8 interrupt; /* device interrupt */ u8 interrupt; /* device interrupt */
u32 *code; /* code */
u8 *mem; /* memory */
#define MAX_LEN_INT32 11 #define MAX_LEN_INT32 11
const char radix_set[11] = "0123456789"; const char radix_set[11] = "0123456789";
@ -30,7 +28,7 @@ u32 str_alloc(char *str, u32 length) {
bool step_vm() { bool step_vm() {
u32 instruction = code[pc++]; u32 instruction = code[pc++];
u8 opcode = DECODE_OP(instruction); u8 opcode = DECODE_OP(instruction);
u32 *locals = frames[fp].locals; u32 *locals = (u32*)(&mem[fp]);
u32 *globals = (u32*)(mem); u32 *globals = (u32*)(mem);
switch (opcode) { switch (opcode) {
@ -42,10 +40,22 @@ bool step_vm() {
DECODE_A(instruction) DECODE_A(instruction)
/* function to jump to */ /* function to jump to */
u32 fn_ptr = locals[dest]; u32 fn_ptr = locals[dest];
frames[fp].return_reg = src1; /* get mp in 'global indexing mode' */
frames[fp].return_pc = pc; u32 *header = &globals[mp / 4];
frames[fp++].start_mp = mp; /* reset child locals counter */
USED(src2); lc = 0;
/* push parents frame value to reset the heap to */
(*header++) = fp;
/* push return address to child frame */
(*header++) = pc;
/* push local address to return the value to */
(*header++) = fp + (src2 * 4);
/* 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 += (src1 * 4);
/* jump to dest_ptr */ /* jump to dest_ptr */
pc = fn_ptr; pc = fn_ptr;
return true; return true;
@ -58,18 +68,21 @@ bool step_vm() {
bool replaces_value = (((u32)(1)) << 14) & imm; bool replaces_value = (((u32)(1)) << 14) & imm;
/* reset mp to saved mp, use header size to get "real" start of frame */ /* reset mp to saved mp, use header size to get "real" start of frame */
u32 return_pc = frames[--fp].return_pc; u32 *frame_start = &globals[(fp / 4) - 3];
u32 return_mp = frames[fp].start_mp; u32 parent_fp = *frame_start++;
u32 parent_local_return_address = frames[fp].return_reg; u32 return_address = *frame_start++;
mp = return_mp; u32 parent_local_return_address = *frame_start++;
pc = return_pc;
USED(replaces_value); USED(replaces_value);
/* reset memory to parents end of memory */
mp = fp - FRAME_HEADER_SIZE;
/* reset the frame pointer */
fp = parent_fp;
if (parent_local_return_address != 255) { if (parent_local_return_address != 255) {
if (is_ptr) { if (is_ptr) {
/* copy value to end of mp if it is a pointer */ /* copy value to end of mp if it is a pointer */
frames[fp].locals[parent_local_return_address] = mp; globals[parent_local_return_address/4] = mp;
size = globals[return_value/4]; size = globals[return_value/4];
globals[mp/4] = size; globals[mp/4] = size;
mp += 4; mp += 4;
@ -77,10 +90,12 @@ bool step_vm() {
mp += size; mp += size;
} else { } else {
/* otherwise just write the return value to its location */ /* otherwise just write the return value to its location */
frames[fp].locals[parent_local_return_address] = return_value; globals[(parent_local_return_address / 4)] = return_value;
} }
} }
/* jump to parent frame */
pc = return_address;
return true; return true;
} }
case OP_SYSCALL: { case OP_SYSCALL: {
@ -90,9 +105,10 @@ bool step_vm() {
return true; return true;
} }
case OP_PARG: { case OP_PARG: {
DECODE_A(instruction) DECODE_B(instruction)
USED(src2); USED(imm);
frames[fp + 1].locals[src1] = locals[dest]; globals[(mp / 4) + lc + 3] = locals[dest];
lc++;
return true; return true;
} }
case OP_LOAD_IMM: { case OP_LOAD_IMM: {

23
vm/vm.h
View File

@ -122,26 +122,15 @@ typedef enum {
SYSCALL_MAX SYSCALL_MAX
} Syscall; } Syscall;
typedef struct frame_s Frame;
struct frame_s {
u32 locals[256];
u32 return_pc;
u32 start_mp;
u8 return_reg;
};
extern u32 *code; /* code */
extern u32 cp; /* code pointer */
extern u8 *mem; /* memory */
extern u32 mp; /* memory pointer */
extern u32 *stack; /* stack */
extern u32 sp; /* stack pointer */
extern Frame *frames; /* call frames */
extern u32 fp; /* frame pointer */
extern u32 pc; /* program counter */ extern u32 pc; /* program counter */
extern u32 cp; /* code pointer */
extern u32 mp; /* memory pointer */
extern u32 fp; /* frame pointer */
extern u8 lc; /* child local count */
extern u8 status; /* status flag */ extern u8 status; /* status flag */
extern u8 interrupt; /* device interrupt */ extern u8 interrupt; /* device interrupt */
extern u32 *code; /* code */
extern u8 *mem; /* memory */
#define READ_U8(addr) (mem[addr]) #define READ_U8(addr) (mem[addr])