diff options
-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) |