From 8b84163c5680f3c88f30e2eaba99fb19a024e5a9 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Felix=20Quei=C3=9Fner?= Date: Thu, 19 May 2016 13:19:38 +0200 Subject: [PATCH] Adds push/pop/peek to VM. Corrects some mistakes in the instructions. --- prototypes/supervm/instructions.md | 1 + prototypes/supervm/main.c | 32 +++++++++++++++++++++++++-- prototypes/supervm/vm.c | 35 +++++++++++++++++++++++++++++- prototypes/supervm/vm.h | 23 ++++++++++++++++++++ 4 files changed, 88 insertions(+), 3 deletions(-) diff --git a/prototypes/supervm/instructions.md b/prototypes/supervm/instructions.md index bbca7ce..d45a857 100644 --- a/prototypes/supervm/instructions.md +++ b/prototypes/supervm/instructions.md @@ -17,6 +17,7 @@ control stack access or control flow. |----------|---------------|-------------------------------------------------| | SP | Stack Pointer | Stores the current 'top' position of the stack. | | BP | Base Pointer | Stores the current stack frame position. | +| CP | Code Pointer | Stores the instruction which is executed next. | | FG | Flag Register | Stores the state of the flags. | ### Stack Pointer diff --git a/prototypes/supervm/main.c b/prototypes/supervm/main.c index a136688..0520341 100644 --- a/prototypes/supervm/main.c +++ b/prototypes/supervm/main.c @@ -3,10 +3,38 @@ #include #include +Instruction code[] = +{ + { VM_EXEC_X, VM_EXEC_X, VM_INPUT_ZERO, VM_INPUT_ZERO, VM_CMD_COPY, 0, VM_FLAG_NO, VM_OUTPUT_DISCARD, 0 }, +}; + +void dump_proc(Process *process) +{ + printf("[ "); + for(int i = 1; i <= process->stackPointer; i++) { + printf("%d ", process->stack[i]); + } + printf("]\n"); +} + +void vm_assert(int assertion, const char *msg) +{ + if(assertion != 0) + return; + printf("Assertion failed: %s\n", msg); + exit(1); +} + int main(int argc, const char **argv) { + Module module = { code, 1 }; + + Process process = { &module, 0, 0, 0, 0 }; + Process *p = &process; + + int stillAlive = vm_step_process(p); + + printf("Process %s.\n", (stillAlive ? "still running" : "terminated")); - - return 0; } \ No newline at end of file diff --git a/prototypes/supervm/vm.c b/prototypes/supervm/vm.c index d10e0a0..4b29ea8 100644 --- a/prototypes/supervm/vm.c +++ b/prototypes/supervm/vm.c @@ -1 +1,34 @@ -#include "vm.h" \ No newline at end of file +#include "vm.h" + +int vm_step_process(Process *process) +{ + vm_assert(process != NULL, "process must not be NULL."); + Instruction instr = process->module->code[process->codePointer]; + + return 0; +} + +void vm_push(Process *process, uint32_t value) +{ + vm_assert(process != NULL, "process must not be NULL."); + vm_assert(process->stackPointer < VM_STACKSIZE, "Stack overflow"); + process->stack[++process->stackPointer] = value; +} + +uint32_t vm_pop(Process *process) +{ + vm_assert(process != NULL, "process must not be NULL."); + uint32_t psp = process->stackPointer; + uint32_t val = process->stack[process->stackPointer--]; + + // Underflow check works because unsigned overflow is defined ;) + vm_assert(psp >= process->stackPointer, "Stack underflow"); + + return val; +} + +uint32_t vm_peek(Process *process) +{ + vm_assert(process != NULL, "process must not be NULL."); + return process->stack[process->stackPointer]; +} diff --git a/prototypes/supervm/vm.h b/prototypes/supervm/vm.h index c7e8fc1..b77f06d 100644 --- a/prototypes/supervm/vm.h +++ b/prototypes/supervm/vm.h @@ -72,8 +72,16 @@ typedef struct _Static_assert(sizeof(Instruction) == 8, "Instruction must be 8 bytes large."); _Static_assert(offsetof(Instruction, argument) == 4, "Argument must be must be 8 bytes large."); +typedef struct +{ + Instruction *code; + uint32_t length; +} Module; + typedef struct { + Module *module; + uint32_t codePointer; uint32_t stackPointer; uint32_t basePointer; @@ -82,8 +90,23 @@ typedef struct uint32_t stack[VM_STACKSIZE]; } Process; +/** + * @brief Steps a given process. + * + * Executes a single instruction and processes input and output. + * + * @param process The process to be stepped. + * @returns 1 if the process is still running or 0 if the process is terminated. + */ +int vm_step_process(Process *process); +void vm_push(Process *process, uint32_t value); +uint32_t vm_pop(Process *process); + +uint32_t vm_peek(Process *process); + +void vm_assert(int assertion, const char *msg); #if defined(__cplusplus) }