diff --git a/src/compiler.c b/src/compiler.c index a5132f4..8a3377c 100644 --- a/src/compiler.c +++ b/src/compiler.c @@ -1,20 +1,8 @@ #include "compiler.h" #include "parser.h" -#define MEMORY_SIZE 1024 - -Code *demo_add_compile() { - Code *code = (Code *)malloc(sizeof(Code)); - Value memory[MEMORY_SIZE] = {0}; /* Memory array */ - code->memory = memory; - code->size = MEMORY_SIZE; - code->current.pc = 1; - - uint32_t i = 1; - memory[0].c[0] = 0; - memory[0].c[1] = 'z'; - memory[0].c[2] = 'r'; - memory[0].c[3] = 'e'; +void demo_add_compile(Value *memory) { + uint32_t i = 0; memory[i++].u = OP(OP_LOADU, 0, 0, 0); memory[i++].u = 0; memory[i++].u = OP(OP_LOADU, 1, 0, 0); @@ -43,26 +31,13 @@ Code *demo_add_compile() { memory[i++].u = OP(OP_READ_STRING, 7, 0, 0); memory[i++].u = OP(OP_PRINT_STRING, 0, 7, 0); memory[i++].u = OP(OP_HALT, 0, 0, 0); - - return code; } -Code *compile(char *buffer) { - Code *code = (Code *)malloc(sizeof(Code)); - Value memory[MEMORY_SIZE] = {0}; /* Memory array */ - code->memory = memory; - code->size = MEMORY_SIZE; - - /* char number[100]; */ - memory[0].c[0] = 0; - memory[0].c[1] = 'z'; - memory[0].c[2] = 'r'; - memory[0].c[3] = 'e'; - +void compile(Value *memory, char *buffer) { initTokenizer(buffer); Token t = nextToken(); do { - debug_printToken(t); + printToken(t); switch (t.type) { case TOKEN_LEFT_PAREN: break; @@ -195,6 +170,4 @@ Code *compile(char *buffer) { } t = nextToken(); } while (t.type != TOKEN_EOF); - - return code; } diff --git a/src/compiler.h b/src/compiler.h index bf30279..9fc12e0 100644 --- a/src/compiler.h +++ b/src/compiler.h @@ -3,14 +3,7 @@ #include "opcodes.h" -typedef struct Code Code; -struct Code { - Value *memory; - uint32_t size; - Frame current; -}; - -Code* demo_add_compile (); -Code* compile (char *buffer); +void demo_add_compile (Value* memory); +void compile (Value* memory, char *buffer); #endif diff --git a/src/debug.c b/src/debug.c index 43d3008..693f9b0 100644 --- a/src/debug.c +++ b/src/debug.c @@ -1,15 +1,15 @@ #include "debug.h" -int core_dump(Value *memory, uint32_t memory_size) { +int core_dump(VM *vm) { FILE *file = fopen("memory_dump.bin", "wb"); if (!file) { perror("Failed to open file"); return EXIT_FAILURE; } - size_t written = fwrite(memory, 1, memory_size, file); - if (written != memory_size) { + size_t written = fwrite(vm->memory, 1, vm->memory_size, file); + if (written != vm->memory_size) { fprintf(stderr, "Incomplete write: %zu bytes written out of %u\n", written, - memory_size); + vm->memory_size); fclose(file); return EXIT_FAILURE; } @@ -17,3 +17,147 @@ int core_dump(Value *memory, uint32_t memory_size) { fclose(file); return EXIT_SUCCESS; } + +void printOp(uint8_t op, uint8_t dest, uint8_t src1, uint8_t src2) { + switch (op) { + case OP_HALT: + printf("[HALT] $%d, $%d, $%d\n", dest, src1, src2); + break; + case OP_LOADI: + printf("[LOADI] $%d, $%d, $%d\n", dest, src1, src2); + break; + case OP_LOADU: + printf("[LOADU] $%d, $%d, $%d\n", dest, src1, src2); + break; + case OP_LOADF: + printf("[LOADF] $%d, $%d, $%d\n", dest, src1, src2); + break; + case OP_STOREI: + printf("[STOREI] $%d, $%d, $%d\n", dest, src1, src2); + break; + case OP_STOREU: + printf("[STOREU] $%d, $%d, $%d\n", dest, src1, src2); + break; + case OP_STOREF: + printf("[STOREF] $%d, $%d, $%d\n", dest, src1, src2); + break; + case OP_ADD_INT: + printf("[ADD_INT] $%d, $%d, $%d\n", dest, src1, src2); + break; + case OP_SUB_INT: + printf("[SUB_INT] $%d, $%d, $%d\n", dest, src1, src2); + break; + case OP_MUL_INT: + printf("[MUL_INT] $%d, $%d, $%d\n", dest, src1, src2); + break; + case OP_DIV_INT: + printf("[DIV_INT] $%d, $%d, $%d\n", dest, src1, src2); + break; + case OP_JEQ_INT: + printf("[JEQ_INT] $%d, $%d, $%d\n", dest, src1, src2); + break; + case OP_JGT_INT: + printf("[JGT_INT] $%d, $%d, $%d\n", dest, src1, src2); + break; + case OP_JLT_INT: + printf("[JLT_INT] $%d, $%d, $%d\n", dest, src1, src2); + break; + case OP_JLE_INT: + printf("[JLE_INT] $%d, $%d, $%d\n", dest, src1, src2); + break; + case OP_JGE_INT: + printf("[JGE_INT] $%d, $%d, $%d\n", dest, src1, src2); + break; + case OP_INT_TO_REAL: + printf("[INT_TO_REAL] $%d, $%d, $%d\n", dest, src1, src2); + break; + case OP_ADD_UINT: + printf("[ADD_UINT] $%d, $%d, $%d\n", dest, src1, src2); + break; + case OP_SUB_UINT: + printf("[SUB_UINT] $%d, $%d, $%d\n", dest, src1, src2); + break; + case OP_MUL_UINT: + printf("[MUL_UINT] $%d, $%d, $%d\n", dest, src1, src2); + break; + case OP_DIV_UINT: + printf("[DIV_UINT] $%d, $%d, $%d\n", dest, src1, src2); + break; + case OP_JEQ_UINT: + printf("[JEQ_UINT] $%d, $%d, $%d\n", dest, src1, src2); + break; + case OP_JGT_UINT: + printf("[JGT_UINT] $%d, $%d, $%d\n", dest, src1, src2); + break; + case OP_JLT_UINT: + printf("[JLT_UINT] $%d, $%d, $%d\n", dest, src1, src2); + break; + case OP_JLE_UINT: + printf("[JLE_UINT] $%d, $%d, $%d\n", dest, src1, src2); + break; + case OP_JGE_UINT: + printf("[JGE_UINT] $%d, $%d, $%d\n", dest, src1, src2); + break; + case OP_UINT_TO_REAL: + printf("[UINT_TO_REAL] $%d, $%d, $%d\n", dest, src1, src2); + break; + case OP_ADD_REAL: + printf("[ADD_REAL] $%d, $%d, $%d\n", dest, src1, src2); + break; + case OP_SUB_REAL: + printf("[SUB_REAL] $%d, $%d, $%d\n", dest, src1, src2); + break; + case OP_MUL_REAL: + printf("[MUL_REAL] $%d, $%d, $%d\n", dest, src1, src2); + break; + case OP_DIV_REAL: + printf("[DIV_REAL] $%d, $%d, $%d\n", dest, src1, src2); + break; + case OP_JEQ_REAL: + printf("[JEQ_REAL] $%d, $%d, $%d\n", dest, src1, src2); + break; + case OP_JGE_REAL: + printf("[JGE_REAL] $%d, $%d, $%d\n", dest, src1, src2); + break; + case OP_JGT_REAL: + printf("[JGT_REAL] $%d, $%d, $%d\n", dest, src1, src2); + break; + case OP_JLT_REAL: + printf("[JLT_REAL] $%d, $%d, $%d\n", dest, src1, src2); + break; + case OP_JLE_REAL: + printf("[JLE_REAL] $%d, $%d, $%d\n", dest, src1, src2); + break; + case OP_REAL_TO_INT: + printf("[REAL_TO_INT] $%d, $%d, $%d\n", dest, src1, src2); + break; + case OP_REAL_TO_UINT: + printf("[REAL_TO_UINT] $%d, $%d, $%d\n", dest, src1, src2); + break; + case OP_MOV: + printf("[MOV] $%d, $%d, $%d\n", dest, src1, src2); + break; + case OP_JMP: + printf("[JMP] $%d, $%d, $%d\n", dest, src1, src2); + break; + case OP_INT_TO_STRING: + printf("[INT_TO_STRING] $%d, $%d, $%d\n", dest, src1, src2); + break; + case OP_UINT_TO_STRING: + printf("[UINT_TO_STRING] $%d, $%d, $%d\n", dest, src1, src2); + break; + case OP_REAL_TO_STRING: + printf("[REAL_TO_STRING] $%d, $%d, $%d\n", dest, src1, src2); + break; + case OP_READ_STRING: + printf("[READ_STRING] $%d, $%d, $%d\n", dest, src1, src2); + break; + case OP_PRINT_STRING: + printf("[PRINT_STRING] $%d, $%d, $%d\n", dest, src1, src2); + break; + case OP_CMP_STRING: + printf("[CMP_STRING] $%d, $%d, $%d\n", dest, src1, src2); + break; + } +} + diff --git a/src/debug.h b/src/debug.h index aa4290e..ef3a074 100644 --- a/src/debug.h +++ b/src/debug.h @@ -2,7 +2,10 @@ #define ZRE_DEBUG_H #include "vm.h" +#include "parser.h" +#include "opcodes.h" -int core_dump(Value *memory, uint32_t memory_size); +int core_dump(VM *vm); +void printOp(uint8_t op, uint8_t dest, uint8_t src1, uint8_t src2); #endif diff --git a/src/main.c b/src/main.c index 1928d34..38ccea5 100644 --- a/src/main.c +++ b/src/main.c @@ -16,14 +16,14 @@ #include #endif -Code *code; +VM *vm; void mainloop() { - if (!step_vm(&code->current, code->memory)) { + if (!step_vm(vm)) { #ifdef __EMSCRIPTEN__ emscripten_cancel_main_loop(); /* this should "kill" the app. */ #else - core_dump(code->memory, code->size); + core_dump(vm); exit(0); #endif } @@ -50,8 +50,10 @@ int main(int argc, char **argv) { } initTokenMap(); - compile(buffer); - code = demo_add_compile(); + vm = init_vm(); + vm->frame = (Frame*)malloc(sizeof(Frame)); + compile(vm->memory, buffer); + demo_add_compile(vm->memory); #ifdef __EMSCRIPTEN__ emscripten_set_main_loop(mainloop, 0, 1); diff --git a/src/opcodes.h b/src/opcodes.h index eef8c43..24f535c 100644 --- a/src/opcodes.h +++ b/src/opcodes.h @@ -10,13 +10,29 @@ typedef union { char c[4]; /* 4 Byte char array for string packing */ } Value; -#define MAX_REGS 255 +typedef union { + uint32_t length; + char *string; + Value *array; + Value *code; +} Object; +#define MAX_REGS 256 typedef struct { Value registers[MAX_REGS]; /* R0-R255 */ - uint32_t pc; /* Program counter */ + Object *locals; /* Short lived object */ } Frame; +#define STACK_SIZE 128 +typedef struct { + Value stack[STACK_SIZE]; + uint32_t stack_size; + uint32_t pc; /* Program counter */ + Value *memory; + uint32_t memory_size; + Frame *frame; +} VM; + typedef enum { OP_HALT, /* terminate execution */ OP_LOADI, /* dest = next memory location as int */ diff --git a/src/parser.c b/src/parser.c index 217baf5..b82fd99 100644 --- a/src/parser.c +++ b/src/parser.c @@ -229,7 +229,8 @@ Token nextToken() { return errorToken("Unexpected character."); } -void debug_printToken(Token t) { + +void printToken(Token t) { char *str = currentTokenToS(); switch (t.type) { diff --git a/src/parser.h b/src/parser.h index 32decf6..d89f0aa 100644 --- a/src/parser.h +++ b/src/parser.h @@ -109,7 +109,7 @@ struct TokenMap void initTokenMap(); void initTokenizer (char *src); -void debug_printToken (Token t); +void printToken (Token t); Token nextToken(); #endif diff --git a/src/vm.c b/src/vm.c index 515bb3e..6fb142a 100644 --- a/src/vm.c +++ b/src/vm.c @@ -1,18 +1,21 @@ #include "vm.h" +#include "debug.h" #define COMPARE_AND_JUMP(type, accessor, op) \ do { \ - type value = frame->registers[src1].accessor; \ - type value2 = frame->registers[src2].accessor; \ - frame->pc = (value op value2) ? dest : frame->pc; \ - return frame->pc; \ + type value = vm->frame->registers[src1].accessor; \ + type value2 = vm->frame->registers[src2].accessor; \ + vm->pc = (value op value2) ? dest : vm->pc; \ + return true; \ } while (0) #define MATH_OP(accessor, op) \ do { \ - frame->registers[dest].accessor = \ - frame->registers[src1].accessor op frame->registers[src2].accessor; \ - return frame->pc; \ + vm->frame->registers[dest].accessor = \ + vm->frame->registers[src1] \ + .accessor op vm->frame->registers[src2] \ + .accessor; \ + return true; \ } while (0) /** @@ -28,11 +31,23 @@ void mem_strcpy(Value *memory, const char *str, uint32_t length, } } +#define MEMORY_SIZE 1024 + +VM *init_vm() { + Value memory[MEMORY_SIZE] = {0}; /* Memory array */ + VM *vm = (VM *)malloc(sizeof(VM)); + vm->memory = memory; + vm->memory_size = MEMORY_SIZE; + vm->stack_size = 0; + + return vm; +} + /** * Step to the next opcode in the vm. */ -uint32_t step_vm(Frame *frame, Value *memory) { - uint32_t instruction = memory[frame->pc].u; +bool step_vm(VM *vm) { + uint32_t instruction = vm->memory[vm->pc].u; /* Extract 8-bit register indices from 32-bit instruction */ uint8_t opcode = (instruction >> 24) & 0xFF; @@ -40,29 +55,31 @@ uint32_t step_vm(Frame *frame, Value *memory) { uint8_t src1 = (instruction >> 8) & 0xFF; uint8_t src2 = instruction & 0xFF; /* Advance to next instruction */ - frame->pc++; + vm->pc++; + + printOp(opcode, dest, src1, src2); switch (opcode) { case OP_HALT: - return 0; + return false; case OP_LOADI: - frame->registers[dest].i = memory[frame->pc++].i; - return frame->pc; + vm->frame->registers[dest].i = vm->memory[vm->pc++].i; + return true; case OP_LOADU: - frame->registers[dest].u = memory[frame->pc++].u; - return frame->pc; + vm->frame->registers[dest].u = vm->memory[vm->pc++].u; + return true; case OP_LOADF: - frame->registers[dest].f = memory[frame->pc++].f; - return frame->pc; + vm->frame->registers[dest].f = vm->memory[vm->pc++].f; + return true; case OP_STOREI: - memory[frame->pc++].i = frame->registers[src1].i; - return frame->pc; + vm->memory[vm->pc++].i = vm->frame->registers[src1].i; + return true; case OP_STOREU: - memory[frame->pc++].u = frame->registers[src1].u; - return frame->pc; + vm->memory[vm->pc++].u = vm->frame->registers[src1].u; + return true; case OP_STOREF: - memory[frame->pc++].f = frame->registers[src1].f; - return frame->pc; + vm->memory[vm->pc++].f = vm->frame->registers[src1].f; + return true; case OP_ADD_INT: MATH_OP(i, +); case OP_SUB_INT: @@ -88,23 +105,23 @@ uint32_t step_vm(Frame *frame, Value *memory) { case OP_DIV_REAL: MATH_OP(f, /); case OP_REAL_TO_INT: - frame->registers[dest].i = (int32_t)(frame->registers[src1].f); - return frame->pc; + vm->frame->registers[dest].i = (int32_t)(vm->frame->registers[src1].f); + return true; case OP_INT_TO_REAL: - frame->registers[dest].f = (float)(frame->registers[src1].i); - return frame->pc; + vm->frame->registers[dest].f = (float)(vm->frame->registers[src1].i); + return true; case OP_REAL_TO_UINT: - frame->registers[dest].u = (uint32_t)(frame->registers[src1].f); - return frame->pc; + vm->frame->registers[dest].u = (uint32_t)(vm->frame->registers[src1].f); + return true; case OP_UINT_TO_REAL: - frame->registers[dest].f = (float)(frame->registers[src1].u); - return frame->pc; + vm->frame->registers[dest].f = (float)(vm->frame->registers[src1].u); + return true; case OP_MOV: - frame->registers[dest] = frame->registers[src1]; - return frame->pc; + vm->frame->registers[dest] = vm->frame->registers[src1]; + return true; case OP_JMP: - frame->pc = frame->registers[src1].u; /* Jump to address */ - return frame->pc; + vm->pc = vm->frame->registers[src1].u; /* Jump to address */ + return true; case OP_JEQ_UINT: { COMPARE_AND_JUMP(uint32_t, u, ==); } @@ -151,64 +168,64 @@ uint32_t step_vm(Frame *frame, Value *memory) { COMPARE_AND_JUMP(float, u, <=); } case OP_INT_TO_STRING: { - int32_t a = (int32_t)frame->registers[src1].i; - uint32_t str_dest = (uint32_t)frame->registers[dest].u; + int32_t a = (int32_t)vm->frame->registers[src1].i; + uint32_t str_dest = (uint32_t)vm->frame->registers[dest].u; char buffer[32]; int len = sprintf(buffer, "%d", a); - mem_strcpy(memory, buffer, len, str_dest); - return frame->pc; + mem_strcpy(vm->memory, buffer, len, str_dest); + return true; } case OP_UINT_TO_STRING: { - uint32_t a = (uint32_t)frame->registers[src1].u; - uint32_t str_dest = (uint32_t)frame->registers[dest].u; + uint32_t a = (uint32_t)vm->frame->registers[src1].u; + uint32_t str_dest = (uint32_t)vm->frame->registers[dest].u; char buffer[32]; int len = sprintf(buffer, "%d", a); - mem_strcpy(memory, buffer, len, str_dest); - return frame->pc; + mem_strcpy(vm->memory, buffer, len, str_dest); + return true; } case OP_REAL_TO_STRING: { - float a = (float)frame->registers[src1].f; - uint32_t str_dest = (uint32_t)frame->registers[dest].u; + float a = (float)vm->frame->registers[src1].f; + uint32_t str_dest = (uint32_t)vm->frame->registers[dest].u; char buffer[32]; int len = sprintf(buffer, "%f", a); - mem_strcpy(memory, buffer, len, str_dest); - return frame->pc; + mem_strcpy(vm->memory, buffer, len, str_dest); + return true; } case OP_READ_STRING: { - uint32_t str_dest = (uint32_t)frame->registers[dest].u; + uint32_t str_dest = (uint32_t)vm->frame->registers[dest].u; uint32_t buffer = str_dest + 1; uint32_t length = 0; while (1) { int ch = getchar(); if (ch == '\n' || ch == EOF) { - memory[buffer + (length / 4)].c[length % 4] = '\0'; + vm->memory[buffer + (length / 4)].c[length % 4] = '\0'; break; } - memory[buffer + (length / 4)].c[length % 4] = ch; + vm->memory[buffer + (length / 4)].c[length % 4] = ch; length++; } - memory[str_dest].u = length; - return frame->pc; + vm->memory[str_dest].u = length; + return true; } case OP_PRINT_STRING: { - uint32_t ptr = (uint32_t)frame->registers[src1].u; - uint32_t length = memory[ptr].u; + uint32_t ptr = (uint32_t)vm->frame->registers[src1].u; + uint32_t length = vm->memory[ptr].u; uint32_t str_src = ptr + 1; uint32_t i; for (i = 0; i < length; i++) { - uint8_t ch = memory[str_src + (i / 4)].c[i % 4]; + uint8_t ch = vm->memory[str_src + (i / 4)].c[i % 4]; if (ch == '\0') break; putchar(ch); } putchar('\n'); - return frame->pc; + return true; } case OP_CMP_STRING: { - uint32_t addr1 = (uint32_t)frame->registers[src1].u; - uint32_t addr2 = (uint32_t)frame->registers[src2].u; - uint32_t length1 = memory[addr1 - 1].u; - uint32_t length2 = memory[addr2 - 1].u; + uint32_t addr1 = (uint32_t)vm->frame->registers[src1].u; + uint32_t addr2 = (uint32_t)vm->frame->registers[src2].u; + uint32_t length1 = vm->memory[addr1 - 1].u; + uint32_t length2 = vm->memory[addr2 - 1].u; uint32_t equal = 1; if (length1 != length2) { @@ -216,19 +233,19 @@ uint32_t step_vm(Frame *frame, Value *memory) { } else { uint32_t i = 0; while (i < length1) { - uint32_t char1 = memory[addr1 + i].u; - uint32_t char2 = memory[addr2 + i].u; + uint32_t char1 = vm->memory[addr1 + i].u; + uint32_t char2 = vm->memory[addr2 + i].u; if (char1 != char2) { equal = 0; break; } if ((char1 & 0xFF) == '\0' && (char2 & 0xFF) == '\0') - return frame->pc; + return true; } } - memory[dest].u = equal; - return frame->pc; + vm->memory[dest].u = equal; + return true; } } - return 0; + return false; } diff --git a/src/vm.h b/src/vm.h index 9ff7d5e..25423c5 100644 --- a/src/vm.h +++ b/src/vm.h @@ -3,6 +3,7 @@ #include "opcodes.h" -uint32_t step_vm(Frame *frame, Value *memory); +VM* init_vm(); +bool step_vm(VM *vm); #endif