diff options
author | Aryadev Chavali <aryadev@aryadevchavali.com> | 2023-11-02 23:25:33 +0000 |
---|---|---|
committer | Aryadev Chavali <aryadev@aryadevchavali.com> | 2023-11-02 23:25:33 +0000 |
commit | 4eee6e1a0a17465756f1b4156727c55bc17214f1 (patch) | |
tree | 818e3265163a6b07478817ab39782a688f94232b /vm/runtime.c | |
parent | 86977fe3c140e6b5d6c09bc1d26d9f97d89a6488 (diff) | |
download | ovm-4eee6e1a0a17465756f1b4156727c55bc17214f1.tar.gz ovm-4eee6e1a0a17465756f1b4156727c55bc17214f1.tar.bz2 ovm-4eee6e1a0a17465756f1b4156727c55bc17214f1.zip |
Implemented subroutine instructions in runtime
Very easy overall, printing the call stack not so much.
Diffstat (limited to 'vm/runtime.c')
-rw-r--r-- | vm/runtime.c | 80 |
1 files changed, 71 insertions, 9 deletions
diff --git a/vm/runtime.c b/vm/runtime.c index c927662..996eb58 100644 --- a/vm/runtime.c +++ b/vm/runtime.c @@ -25,25 +25,22 @@ const char *err_as_cstr(err_t err) { case ERR_OK: return "OK"; - break; case ERR_STACK_UNDERFLOW: return "STACK_UNDERFLOW"; - break; case ERR_STACK_OVERFLOW: return "STACK_OVERFLOW"; - break; + case ERR_CALL_STACK_UNDERFLOW: + return "CALL_STACK_UNDERFLOW"; + case ERR_CALL_STACK_OVERFLOW: + return "CALL_STACK_OVERFLOW"; case ERR_INVALID_OPCODE: return "INVALID_OPCODE"; - break; case ERR_INVALID_REGISTER_BYTE: return "INVALID_REGISTER_BYTE"; - break; case ERR_INVALID_REGISTER_HWORD: return "INVALID_REGISTER_HWORD"; - break; case ERR_INVALID_REGISTER_WORD: return "INVALID_REGISTER_WORD"; - break; case ERR_INVALID_PROGRAM_ADDRESS: return "INVALID_PROGRAM_ADDRESS"; case ERR_INVALID_PAGE_ADDRESS: @@ -52,7 +49,6 @@ const char *err_as_cstr(err_t err) return "OUT_OF_BOUNDS"; case ERR_END_OF_PROGRAM: return "END_OF_PROGRAM"; - break; default: return ""; } @@ -60,7 +56,7 @@ const char *err_as_cstr(err_t err) err_t vm_execute(vm_t *vm) { - static_assert(NUMBER_OF_OPCODES == 95, "vm_execute: Out of date"); + static_assert(NUMBER_OF_OPCODES == 98, "vm_execute: Out of date"); struct Program *prog = &vm->program; if (prog->ptr >= prog->max) return ERR_END_OF_PROGRAM; @@ -153,6 +149,30 @@ err_t vm_execute(vm_t *vm) else ++prog->ptr; } + else if (instruction.opcode == OP_CALL) + { + if (vm->call_stack.ptr >= vm->call_stack.max) + return ERR_CALL_STACK_OVERFLOW; + vm->call_stack.address_pointers[vm->call_stack.ptr++] = vm->program.ptr + 1; + return vm_jump(vm, instruction.operand.as_word); + } + else if (instruction.opcode == OP_CALL_STACK) + { + if (vm->call_stack.ptr >= vm->call_stack.max) + return ERR_CALL_STACK_OVERFLOW; + vm->call_stack.address_pointers[vm->call_stack.ptr++] = vm->program.ptr + 1; + data_t ret = {0}; + err_t err = vm_pop_word(vm, &ret); + if (err) + return err; + return vm_jump(vm, ret.as_word); + } + else if (instruction.opcode == OP_RET) + { + if (vm->call_stack.ptr == 0) + return ERR_CALL_STACK_UNDERFLOW; + return vm_jump(vm, vm->call_stack.address_pointers[--vm->call_stack.ptr]); + } else if (OPCODE_IS_TYPE(instruction.opcode, OP_PRINT)) { data_t datum = {0}; @@ -259,6 +279,7 @@ err_t vm_execute_all(vm_t *vm) registers_t prev_registers = vm->registers; size_t prev_sptr = 0; size_t prev_pages = 0; + size_t prev_cptr = 0; #endif while (program->instructions[program->ptr].opcode != OP_HALT && program->ptr < program->max) @@ -274,6 +295,15 @@ err_t vm_execute_all(vm_t *vm) "----------------------------------------------------------------------" "----------\n", stdout); + if (prev_cptr != vm->call_stack.ptr) + { + vm_print_call_stack(vm, stdout); + prev_cptr = vm->call_stack.ptr; + fputs("------------------------------------------------------------------" + "----" + "----------\n", + stdout); + } if (prev_pages != vm->heap.pages) { vm_print_heap(vm, stdout); @@ -342,6 +372,12 @@ void vm_load_heap(vm_t *vm, heap_t heap) vm->heap = heap; } +void vm_load_call_stack(vm_t *vm, word *buffer, size_t size) +{ + vm->call_stack = + (struct CallStack){.address_pointers = buffer, .ptr = 0, .max = size}; +} + void vm_stop(vm_t *vm) { free(vm->registers.data); @@ -460,6 +496,28 @@ void vm_print_heap(vm_t *vm, FILE *fp) fprintf(fp, "]\n"); } +void vm_print_call_stack(vm_t *vm, FILE *fp) +{ + struct CallStack cs = vm->call_stack; + fprintf(fp, "CallStack.max = %lu\nCallStack.ptr = %lu\nCallStack.data = [", + cs.max, cs.ptr); + if (cs.ptr == 0) + { + fprintf(fp, "]\n"); + return; + } + printf("\n"); + for (size_t i = cs.ptr; i > 0; --i) + { + word w = cs.address_pointers[i - 1]; + fprintf(fp, "\t%lu: %lX", cs.ptr - i, w); + if (i != 1) + fprintf(fp, ", "); + fprintf(fp, "\n"); + } + fprintf(fp, "]\n"); +} + void vm_print_all(vm_t *vm, FILE *fp) { fputs("----------------------------------------------------------------------" @@ -469,6 +527,10 @@ void vm_print_all(vm_t *vm, FILE *fp) fputs("----------------------------------------------------------------------" "----------\n", fp); + vm_print_call_stack(vm, fp); + fputs("----------------------------------------------------------------------" + "----------\n", + fp); vm_print_heap(vm, fp); fputs("----------------------------------------------------------------------" "----------\n", |