From ea14b3beb626102a2e0de80240f89413c0b6b72a Mon Sep 17 00:00:00 2001
From: Aryadev Chavali <aryadev@aryadevchavali.com>
Date: Sun, 15 Oct 2023 05:52:58 +0100
Subject: 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.
---
 src/main.c | 61 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
 1 file changed, 61 insertions(+)

diff --git a/src/main.c b/src/main.c
index db914ad..1283b8b 100644
--- a/src/main.c
+++ b/src/main.c
@@ -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)
-- 
cgit v1.2.3-13-gbd6f