diff options
author | Aryadev Chavali <aryadev@aryadevchavali.com> | 2023-10-15 05:52:58 +0100 |
---|---|---|
committer | Aryadev Chavali <aryadev@aryadevchavali.com> | 2023-10-15 05:52:58 +0100 |
commit | ea14b3beb626102a2e0de80240f89413c0b6b72a (patch) | |
tree | b906b1e387833a69949b85847faa34f1e585a7c0 | |
parent | 3786b7d785f6c99faef13374c23c4ccff660e119 (diff) | |
download | ovm-ea14b3beb626102a2e0de80240f89413c0b6b72a.tar.gz ovm-ea14b3beb626102a2e0de80240f89413c0b6b72a.tar.bz2 ovm-ea14b3beb626102a2e0de80240f89413c0b6b72a.zip |
Added an instruction setup
op_t provides opcodes, inst_t provides a wrapper with operands. vm_t
carries around a pointer to a set of instructions, and vm_execute
attempts to execute that one. I do some weird stuff here, and it's
definitely not complete.
-rw-r--r-- | src/main.c | 61 |
1 files changed, 61 insertions, 0 deletions
@@ -15,6 +15,28 @@ #include "./base.h" +typedef enum +{ + OP_PUSH_BYTE = 1, + OP_PUSH_WORD, + OP_PUSH_FLOAT, +} op_t; + +typedef struct +{ + op_t opcode; + data_t operand; +} inst_t; + +#define INST_BPUSH(BYTE) \ + ((inst_t){.opcode = OP_PUSH_BYTE, .operand = DBYTE(BYTE)}) + +#define INST_WPUSH(WORD) \ + ((inst_t){.opcode = OP_PUSH_WORD, .operand = DWORD(WORD)}) + +#define INST_FPUSH(FLOAT) \ + ((inst_t){.opcode = OP_PUSH_FLOAT, .operand = DFLOAT(FLOAT)}) + typedef struct { struct Stack @@ -22,8 +44,20 @@ typedef struct byte *data; word ptr, max; } stack; + struct Program + { + inst_t *instructions; + word ptr, max; + } program; } vm_t; +void vm_load_program(vm_t *vm, inst_t *instructions, size_t size) +{ + vm->program.instructions = instructions; + vm->program.max = size; + vm->program.ptr = 0; +} + void vm_load_stack(vm_t *vm, byte *bytes, size_t size) { vm->stack.data = bytes; @@ -101,6 +135,33 @@ f64 vm_pop_float(vm_t *vm) return f; } +typedef void (*push_f)(vm_t *, data_t); + +void vm_execute(vm_t *vm) +{ + struct Program *prog = &vm->program; + if (prog->ptr >= prog->max) + // TODO: Error (Went past end of program) + return; + inst_t instruction = prog->instructions[prog->ptr]; + // NOTE: This is ballsy; I'm essentially saying I will never use the + // last 2 bits unless it's a push routine + if ((instruction.opcode & 0b11) != 0) + { + // Push routine + const push_f routines[] = {[OP_PUSH_BYTE] = vm_push_byte, + [OP_PUSH_WORD] = vm_push_word, + [OP_PUSH_FLOAT] = vm_push_float}; + routines[instruction.opcode](vm, instruction.operand); + prog->ptr++; + } + else + { + // TODO: Error (Unknown opcode) + return; + } +} + #define ARR_SIZE(xs) (sizeof(xs) / sizeof(xs[0])) int main(void) |