split up code and memory

This commit is contained in:
zongor 2025-07-20 11:17:28 -04:00
parent 035397209d
commit 5184b60136
9 changed files with 142 additions and 145 deletions

View File

@ -10,13 +10,11 @@ int main(int argc, char **argv) {
vm.stack_size = STACK_SIZE; vm.stack_size = STACK_SIZE;
vm.memory_size = MEMORY_SIZE; vm.memory_size = MEMORY_SIZE;
uint32_t end = 0; /* test_add_compile(&vm); */
/* test_add_function_compile(&vm); */
/* test_add_compile(vm.memory); */ /* test_loop_compile(&vm); */
/* test_add_function_compile(vm.memory); */ test_hello_world_compile(&vm);
/* end = test_loop_compile(vm.memory); */ /* test_recursive_function_compile(&vm); */
end = test_hello_world_compile(vm.memory);
/* test_recursive_function_compile(vm.memory); */
uint32_t buffer_size = 640 * 480 * sizeof(uint32_t); uint32_t buffer_size = 640 * 480 * sizeof(uint32_t);
@ -24,8 +22,8 @@ int main(int argc, char **argv) {
screen.type = SCREEN; screen.type = SCREEN;
screen.s = (Screen){.width = (uint8_t)480, screen.s = (Screen){.width = (uint8_t)480,
.height = (uint8_t)640, .height = (uint8_t)640,
.allocated = {end, buffer_size}, .allocated = {vm.mp, buffer_size},
.buffer = &vm.memory[end]}; .buffer = &vm.memory[vm.mp]};
vm.devices[vm.dp++] = screen; vm.devices[vm.dp++] = screen;
vm.mp += buffer_size; vm.mp += buffer_size;

View File

@ -55,15 +55,17 @@ typedef union device_u {
} Device; } Device;
#define MEMORY_SIZE 65536 #define MEMORY_SIZE 65536
#define CODE_SIZE 8192
#define FRAMES_SIZE 128 #define FRAMES_SIZE 128
#define STACK_SIZE 256 #define STACK_SIZE 256
#define DEVICES_SIZE 8 #define DEVICES_SIZE 8
typedef struct vm_s { typedef struct vm_s {
uint32_t pc; /* Program counter */ uint32_t pc; /* program counter */
uint32_t fp; /* Frame pointer (current frame) */ uint32_t cp; /* code pointer (last allocated opcode) */
uint32_t fp; /* frame pointer (current frame) */
uint32_t sp; /* stack pointer (top of stack) */ uint32_t sp; /* stack pointer (top of stack) */
uint32_t rp; /* return stack pointer (top of stack) */ uint32_t rp; /* return stack pointer (top of stack) */
uint32_t mp; /* Memory pointer (last allocated value) */ uint32_t mp; /* memory pointer (last allocated value) */
uint32_t dp; /* device pointer (last allocated device) */ uint32_t dp; /* device pointer (last allocated device) */
uint8_t devices_size; uint8_t devices_size;
Device devices[DEVICES_SIZE]; Device devices[DEVICES_SIZE];
@ -73,8 +75,10 @@ typedef struct vm_s {
Value stack[STACK_SIZE]; /* main stack */ Value stack[STACK_SIZE]; /* main stack */
uint32_t return_stack_size; uint32_t return_stack_size;
Value return_stack[STACK_SIZE]; /* return stack (for recursion) */ Value return_stack[STACK_SIZE]; /* return stack (for recursion) */
uint32_t code_size;
Value code[CODE_SIZE]; /* code block */
uint32_t memory_size; uint32_t memory_size;
Value memory[MEMORY_SIZE]; /* memory array */ Value memory[MEMORY_SIZE]; /* memory block */
} VM; } VM;
typedef enum { typedef enum {

View File

@ -1,130 +1,125 @@
#include "test.h" #include "test.h"
uint32_t test_hello_world_compile(Value *memory) { bool test_hello_world_compile(VM *vm) {
uint32_t i = 0; vm->code[vm->cp++].u = OP(OP_LOADU, 1, 0, 0);
memory[i++].u = OP(OP_LOADU, 1, 0, 0); vm->code[vm->cp++].u = 0;
memory[i++].u = 4; vm->code[vm->cp++].u = OP(OP_PRINT_STRING, 0, 1, 0); /* print("nuqneH 'u'?"); */
memory[i++].u = OP(OP_PRINT_STRING, 0, 1, 0); /* print("nuqneH 'u'?"); */ vm->code[vm->cp++].u = OP(OP_HALT, 0, 0, 0); /* explicit halt */
memory[i++].u = OP(OP_HALT, 0, 0, 0); /* explicit halt */ vm->memory[vm->mp++].u = 12;
memory[i++].u = 12; vm->memory[vm->mp].c[0] = 'n';
memory[i].c[0] = 'n'; vm->memory[vm->mp].c[1] = 'u';
memory[i].c[1] = 'u'; vm->memory[vm->mp].c[2] = 'q';
memory[i].c[2] = 'q'; vm->memory[vm->mp++].c[3] = 'n';
memory[i++].c[3] = 'n'; vm->memory[vm->mp].c[0] = 'e';
memory[i].c[0] = 'e'; vm->memory[vm->mp].c[1] = 'H';
memory[i].c[1] = 'H'; vm->memory[vm->mp].c[2] = ' ';
memory[i].c[2] = ' '; vm->memory[vm->mp++].c[3] = '\'';
memory[i++].c[3] = '\''; vm->memory[vm->mp].c[0] = 'u';
memory[i].c[0] = 'u'; vm->memory[vm->mp].c[1] = '\'';
memory[i].c[1] = '\''; vm->memory[vm->mp].c[2] = '?';
memory[i].c[2] = '?'; vm->memory[vm->mp++].c[3] = '\0';
memory[i++].c[3] = '\0'; return true;
return i;
} }
uint32_t test_add_compile(Value *memory) { bool test_add_compile(VM *vm) {
uint32_t i = 0; vm->code[vm->cp++].u = OP(OP_LOADU, 0, 0, 0);
memory[i++].u = OP(OP_LOADU, 0, 0, 0); vm->code[vm->cp++].u = 1;
memory[i++].u = 1; vm->code[vm->cp++].u = OP(OP_LOADU, 1, 0, 0);
memory[i++].u = OP(OP_LOADU, 1, 0, 0); vm->code[vm->cp++].u = 2;
memory[i++].u = 2; vm->code[vm->cp++].u = OP(OP_ADD_UINT, 2, 1, 0); /* let sum = 1 + 2; */
memory[i++].u = OP(OP_ADD_UINT, 2, 1, 0); /* let sum = 1 + 2; */ vm->code[vm->cp++].u = OP(OP_UINT_TO_STRING, 3, 2, 0);
memory[i++].u = OP(OP_UINT_TO_STRING, 3, 2, 0); vm->code[vm->cp++].u = OP(OP_PRINT_STRING, 0, 3, 0); /* print(sum.toS()); */
memory[i++].u = OP(OP_PRINT_STRING, 0, 3, 0); /* print(sum.toS()); */ vm->code[vm->cp++].u = OP(OP_HALT, 0, 0, 0); /* explicit halt */
memory[i++].u = OP(OP_HALT, 0, 0, 0); /* explicit halt */ return true;
return i;
} }
uint32_t test_loop_compile(Value *memory) { bool test_loop_compile(VM *vm) {
uint32_t i = 0; vm->code[vm->cp++].u = OP(OP_LOADF, 0, 0, 0); /* let a = 5.0 */
memory[i++].u = OP(OP_LOADF, 0, 0, 0); /* let a = 5.0 */ vm->code[vm->cp++].f = 5.0f;
memory[i++].f = 5.0f; vm->code[vm->cp++].u = OP(OP_LOADI, 1, 0, 0); /* do (i = 50000, 0, -1) { */
memory[i++].u = OP(OP_LOADI, 1, 0, 0); /* do (i = 5, 0, -1) { */ vm->code[vm->cp++].i = 50000;
memory[i++].i = 5000; vm->code[vm->cp++].u = OP(OP_LOADI, 2, 0, 0); /* loop check value */
memory[i++].u = OP(OP_LOADI, 2, 0, 0); /* loop check value */ vm->code[vm->cp++].i = 0;
memory[i++].i = 0; vm->code[vm->cp++].u = OP(OP_LOADI, 3, 0, 0); /* loop incriment value */
memory[i++].u = OP(OP_LOADI, 3, 0, 0); /* loop incriment value */ vm->code[vm->cp++].i = -1;
memory[i++].i = -1; vm->code[vm->cp++].u = OP(OP_LOADU, 4, 0, 0); /* loop start */
memory[i++].u = OP(OP_LOADU, 4, 0, 0); /* loop start */ uint32_t jmp = vm->cp + 1;
uint32_t jmp = i + 1; vm->code[vm->cp++].u = jmp;
memory[i++].u = jmp; vm->code[vm->cp++].u = OP(OP_LOADF, 5, 0, 0);
memory[i++].u = OP(OP_LOADF, 5, 0, 0); vm->code[vm->cp++].f = 5.0f;
memory[i++].f = 5.0f; vm->code[vm->cp++].u = OP(OP_ADD_REAL, 0, 0, 5); /* a += 5.0; */
memory[i++].u = OP(OP_ADD_REAL, 0, 0, 5); /* a += 5.0; */ vm->code[vm->cp++].u = OP(OP_ADD_INT, 1, 1, 3); /* (implied by loop) i = i + (-1) */
memory[i++].u = OP(OP_ADD_INT, 1, 1, 3); /* (implied by loop) i = i + (-1) */ vm->code[vm->cp++].u = OP(OP_JGE_INT, 4, 1, 2); /* } */
memory[i++].u = OP(OP_JGE_INT, 4, 1, 2); /* } */ vm->code[vm->cp++].u = OP(OP_REAL_TO_UINT, 1, 0, 0); /* let b = a as nat; */
memory[i++].u = OP(OP_REAL_TO_UINT, 1, 0, 0); /* let b = a as nat; */ vm->code[vm->cp++].u = OP(OP_READ_STRING, 2, 0, 0); /* let user_string = gets(); */
memory[i++].u = OP(OP_READ_STRING, 2, 0, 0); /* let user_string = gets(); */ vm->code[vm->cp++].u = OP(OP_UINT_TO_STRING, 3, 1, 0);
memory[i++].u = OP(OP_UINT_TO_STRING, 3, 1, 0); vm->code[vm->cp++].u = OP(OP_PRINT_STRING, 0, 3, 0); /* print(a.toS()); */
memory[i++].u = OP(OP_PRINT_STRING, 0, 3, 0); /* print(a.toS()); */ vm->code[vm->cp++].u = OP(OP_REAL_TO_STRING, 3, 0, 0);
memory[i++].u = OP(OP_REAL_TO_STRING, 3, 0, 0); vm->code[vm->cp++].u = OP(OP_PRINT_STRING, 0, 3, 0); /* print(b.toS()); */
memory[i++].u = OP(OP_PRINT_STRING, 0, 3, 0); /* print(b.toS()); */ vm->code[vm->cp++].u = OP(OP_PRINT_STRING, 0, 2, 0); /* print(user_string); */
memory[i++].u = OP(OP_PRINT_STRING, 0, 2, 0); /* print(user_string); */ vm->code[vm->cp++].u = OP(OP_HALT, 0, 0, 0); /* program done */
memory[i++].u = OP(OP_HALT, 0, 0, 0); /* program done */ return true;
return i;
} }
uint32_t test_add_function_compile(Value *memory) { bool test_add_function_compile(VM *vm) {
uint32_t i = 0;
/* fn main() */ /* fn main() */
memory[i++].u = OP(OP_LOADI, 0, 0, 0); /* 1 */ vm->code[vm->cp++].u = OP(OP_LOADI, 0, 0, 0); /* 1 */
memory[i++].i = 1; vm->code[vm->cp++].i = 1;
memory[i++].u = OP(OP_PUSHI, 0, 0, 0); vm->code[vm->cp++].u = OP(OP_PUSHI, 0, 0, 0);
memory[i++].u = OP(OP_LOADI, 0, 0, 0); /* 1 */ vm->code[vm->cp++].u = OP(OP_LOADI, 0, 0, 0); /* 1 */
memory[i++].i = 1; vm->code[vm->cp++].i = 1;
memory[i++].u = OP(OP_PUSHI, 0, 0, 0); vm->code[vm->cp++].u = OP(OP_PUSHI, 0, 0, 0);
memory[i++].u = OP(OP_CALL, 0, 0, 0); /* ); */ vm->code[vm->cp++].u = OP(OP_CALL, 0, 0, 0); /* ); */
memory[i++].u = 12; vm->code[vm->cp++].u = 12;
memory[i++].u = OP(OP_POPI, 0, 0, 0); /* get return value */ vm->code[vm->cp++].u = OP(OP_POPI, 0, 0, 0); /* get return value */
memory[i++].u = OP(OP_INT_TO_STRING, 1, 0, 0); vm->code[vm->cp++].u = OP(OP_INT_TO_STRING, 1, 0, 0);
memory[i++].u = OP(OP_PRINT_STRING, 0, 1, 0); /* print(sum.toS()); */ vm->code[vm->cp++].u = OP(OP_PRINT_STRING, 0, 1, 0); /* print(sum.toS()); */
memory[i++].u = OP(OP_HALT, 0, 0, 0); vm->code[vm->cp++].u = OP(OP_HALT, 0, 0, 0);
/* fn add() */ /* fn add() */
memory[i++].u = OP(OP_POPI, 0, 0, 0); /* a int */ vm->code[vm->cp++].u = OP(OP_POPI, 0, 0, 0); /* a int */
memory[i++].u = OP(OP_POPI, 1, 0, 0); /* b int */ vm->code[vm->cp++].u = OP(OP_POPI, 1, 0, 0); /* b int */
memory[i++].u = OP(OP_ADD_INT, 2, 1, 0); /* a + b */ vm->code[vm->cp++].u = OP(OP_ADD_INT, 2, 1, 0); /* a + b */
memory[i++].u = OP(OP_PUSHI, 2, 0, 0); /* push on stack */ vm->code[vm->cp++].u = OP(OP_PUSHI, 2, 0, 0); /* push on stack */
memory[i++].u = OP(OP_RETURN, 0, 0, 0); vm->code[vm->cp++].u = OP(OP_RETURN, 0, 0, 0);
return i; return true;
} }
uint32_t test_recursive_function_compile(Value *memory) { bool test_recursive_function_compile(VM *vm) {
uint32_t i = 0;
/* fn main() */ /* fn main() */
memory[i++].u = OP(OP_LOADI, 0, 0, 0); /* 35 */ vm->code[vm->cp++].u = OP(OP_LOADI, 0, 0, 0); /* 35 */
memory[i++].i = 35; vm->code[vm->cp++].i = 35;
memory[i++].u = OP(OP_PUSHI, 0, 0, 0); vm->code[vm->cp++].u = OP(OP_PUSHI, 0, 0, 0);
memory[i++].u = OP(OP_CALL, 0, 0, 0); /* ); */ vm->code[vm->cp++].u = OP(OP_CALL, 0, 0, 0); /* ); */
memory[i++].u = 9; vm->code[vm->cp++].u = 9;
memory[i++].u = OP(OP_POPI, 0, 0, 0); /* get return value */ vm->code[vm->cp++].u = OP(OP_POPI, 0, 0, 0); /* get return value */
memory[i++].u = OP(OP_INT_TO_STRING, 1, 0, 0); vm->code[vm->cp++].u = OP(OP_INT_TO_STRING, 1, 0, 0);
memory[i++].u = OP(OP_PRINT_STRING, 0, 1, 0); /* print(fib(35).toS()); */ vm->code[vm->cp++].u = OP(OP_PRINT_STRING, 0, 1, 0); /* print(fib(35).toS()); */
memory[i++].u = OP(OP_HALT, 0, 0, 0); vm->code[vm->cp++].u = OP(OP_HALT, 0, 0, 0);
/* fn fib() */ /* fn fib() */
memory[i++].u = OP(OP_POPI, 0, 0, 0); /* n int */ vm->code[vm->cp++].u = OP(OP_POPI, 0, 0, 0); /* n int */
memory[i++].u = OP(OP_LOADI, 1, 0, 0); /* 2 */ vm->code[vm->cp++].u = OP(OP_LOADI, 1, 0, 0); /* 2 */
memory[i++].i = 2; vm->code[vm->cp++].i = 2;
memory[i++].u = OP(OP_LOADI, 2, 0, 0); /* &fib */ vm->code[vm->cp++].u = OP(OP_LOADI, 2, 0, 0); /* &fib */
memory[i++].i = 32; vm->code[vm->cp++].i = 32;
memory[i++].u = OP(OP_JLT_INT, 2, 0, 1); vm->code[vm->cp++].u = OP(OP_JLT_INT, 2, 0, 1);
memory[i++].u = OP(OP_LOADI, 3, 0, 0); /* 2 */ vm->code[vm->cp++].u = OP(OP_LOADI, 3, 0, 0); /* 2 */
memory[i++].i = 2; vm->code[vm->cp++].i = 2;
memory[i++].u = OP(OP_SUB_INT, 4, 0, 3); vm->code[vm->cp++].u = OP(OP_SUB_INT, 4, 0, 3);
memory[i++].u = OP(OP_PUSHI, 4, 0, 0); vm->code[vm->cp++].u = OP(OP_PUSHI, 4, 0, 0);
memory[i++].u = OP(OP_CALL, 0, 0, 0); /* fib(n - 2) */ vm->code[vm->cp++].u = OP(OP_CALL, 0, 0, 0); /* fib(n - 2) */
memory[i++].u = 9; vm->code[vm->cp++].u = 9;
memory[i++].u = OP(OP_LOADI, 3, 0, 0); /* 1 */ vm->code[vm->cp++].u = OP(OP_LOADI, 3, 0, 0); /* 1 */
memory[i++].i = 1; vm->code[vm->cp++].i = 1;
memory[i++].u = OP(OP_SUB_INT, 4, 0, 3); vm->code[vm->cp++].u = OP(OP_SUB_INT, 4, 0, 3);
memory[i++].u = OP(OP_PUSHI, 4, 0, 0); vm->code[vm->cp++].u = OP(OP_PUSHI, 4, 0, 0);
memory[i++].u = OP(OP_CALL, 0, 0, 0); /* fib(n - 1) */ vm->code[vm->cp++].u = OP(OP_CALL, 0, 0, 0); /* fib(n - 1) */
memory[i++].u = 9; vm->code[vm->cp++].u = 9;
memory[i++].u = OP(OP_POPI, 4, 0, 0); vm->code[vm->cp++].u = OP(OP_POPI, 4, 0, 0);
memory[i++].u = OP(OP_POPI, 5, 0, 0); vm->code[vm->cp++].u = OP(OP_POPI, 5, 0, 0);
memory[i++].u = OP(OP_ADD_INT, 6, 5, 4); vm->code[vm->cp++].u = OP(OP_ADD_INT, 6, 5, 4);
memory[i++].u = OP(OP_PUSHI, 6, 0, 0); vm->code[vm->cp++].u = OP(OP_PUSHI, 6, 0, 0);
memory[i++].u = OP(OP_RETURN, 0, 0, 0); vm->code[vm->cp++].u = OP(OP_RETURN, 0, 0, 0);
memory[i++].u = OP(OP_PUSHI, 0, 0, 0); vm->code[vm->cp++].u = OP(OP_PUSHI, 0, 0, 0);
memory[i++].u = OP(OP_RETURN, 0, 0, 0); vm->code[vm->cp++].u = OP(OP_RETURN, 0, 0, 0);
return i; return true;
} }

View File

@ -3,10 +3,10 @@
#include "opcodes.h" #include "opcodes.h"
uint32_t test_hello_world_compile (Value *memory); bool test_hello_world_compile (VM *vm);
uint32_t test_add_compile (Value *memory); bool test_add_compile (VM *vm);
uint32_t test_loop_compile (Value *memory); bool test_loop_compile (VM *vm);
uint32_t test_add_function_compile(Value *memory); bool test_add_function_compile(VM *vm);
uint32_t test_recursive_function_compile(Value *memory); bool test_recursive_function_compile(VM *vm);
#endif #endif

View File

@ -41,7 +41,7 @@ void mem_strcpy(Value *memory, const char *str, uint32_t length,
*/ */
bool step_vm(VM *vm) { bool step_vm(VM *vm) {
/* Get current instruction & Advance to next instruction */ /* Get current instruction & Advance to next instruction */
uint32_t instruction = vm->memory[vm->pc++].u; uint32_t instruction = vm->code[vm->pc++].u;
uint8_t opcode = (instruction >> 24) & 0xFF; uint8_t opcode = (instruction >> 24) & 0xFF;
uint8_t dest = (instruction >> 16) & 0xFF; uint8_t dest = (instruction >> 16) & 0xFF;
@ -52,7 +52,7 @@ bool step_vm(VM *vm) {
case OP_HALT: case OP_HALT:
return false; return false;
case OP_CALL:; /* whats up with this semicolon? ANSI C does not allow you to create a variabel after a case, so this noop is here */ case OP_CALL:; /* whats up with this semicolon? ANSI C does not allow you to create a variabel after a case, so this noop is here */
uint32_t jmp = vm->memory[vm->pc++].u; /* location of function in memory */ uint32_t jmp = vm->code[vm->pc++].u; /* location of function in code */
vm->return_stack[vm->rp++].u = vm->pc; /* set return address */ vm->return_stack[vm->rp++].u = vm->pc; /* set return address */
vm->fp++; /* increment to the next free frame */ vm->fp++; /* increment to the next free frame */
vm->frames[vm->fp].allocated.start = vm->mp; /* set start of new memory block */ vm->frames[vm->fp].allocated.start = vm->mp; /* set start of new memory block */
@ -63,22 +63,22 @@ bool step_vm(VM *vm) {
vm->mp = vm->frames[vm->fp--].allocated.start; /* reset memory pointer to start of old slice, pop the frame */ vm->mp = vm->frames[vm->fp--].allocated.start; /* reset memory pointer to start of old slice, pop the frame */
return true; return true;
case OP_LOADI: case OP_LOADI:
vm->frames[vm->fp].registers[dest].i = vm->memory[vm->pc++].i; vm->frames[vm->fp].registers[dest].i = vm->code[vm->pc++].i;
return true; return true;
case OP_LOADU: case OP_LOADU:
vm->frames[vm->fp].registers[dest].u = vm->memory[vm->pc++].u; vm->frames[vm->fp].registers[dest].u = vm->code[vm->pc++].u;
return true; return true;
case OP_LOADF: case OP_LOADF:
vm->frames[vm->fp].registers[dest].f = vm->memory[vm->pc++].f; vm->frames[vm->fp].registers[dest].f = vm->code[vm->pc++].f;
return true; return true;
case OP_STOREI: case OP_STOREI:
vm->memory[vm->pc++].i = vm->frames[vm->fp].registers[dest].i; vm->code[vm->pc++].i = vm->frames[vm->fp].registers[dest].i;
return true; return true;
case OP_STOREU: case OP_STOREU:
vm->memory[vm->pc++].u = vm->frames[vm->fp].registers[dest].u; vm->code[vm->pc++].u = vm->frames[vm->fp].registers[dest].u;
return true; return true;
case OP_STOREF: case OP_STOREF:
vm->memory[vm->pc++].f = vm->frames[vm->fp].registers[dest].f; vm->code[vm->pc++].f = vm->frames[vm->fp].registers[dest].f;
return true; return true;
case OP_PUSHI: case OP_PUSHI:
vm->stack[++vm->sp].i = vm->frames[vm->fp].registers[dest].i; vm->stack[++vm->sp].i = vm->frames[vm->fp].registers[dest].i;

View File

@ -1,5 +1,5 @@
local a = 5.0 local a = 5.0
for i = 5, 0, -1 do for i = 50000, 0, -1 do
a = a + 5.0 a = a + 5.0
end end
local b = math.floor(a) local b = math.floor(a)

View File

@ -1,5 +1,5 @@
my $a = 5.0; my $a = 5.0;
for (my $i = 5; $i >= 0; $i--) { for (my $i = 50000; $i >= 0; $i--) {
$a += 5.0; $a += 5.0;
} }
my $b = int($a); my $b = int($a);

View File

@ -1,5 +1,5 @@
a = 5.0 a = 5.0
for i in range(5, -1, -1): for i in range(50000, -1, -1):
a += 5.0 a += 5.0
b = int(a) b = int(a)
user_string = input("Enter a string: ") user_string = input("Enter a string: ")

View File

@ -1,5 +1,5 @@
let a = 5.0; let a = 5.0;
do (let i = 5, 0, -1) { do (let i = 50000, 0, -1) {
a += 5.0; a += 5.0;
} }
let b = a as nat; let b = a as nat;