aboutsummaryrefslogtreecommitdiff
path: root/src/main.c
diff options
context:
space:
mode:
authorAryadev Chavali <aryadev@aryadevchavali.com>2023-10-15 05:52:58 +0100
committerAryadev Chavali <aryadev@aryadevchavali.com>2023-10-15 05:52:58 +0100
commitea14b3beb626102a2e0de80240f89413c0b6b72a (patch)
treeb906b1e387833a69949b85847faa34f1e585a7c0 /src/main.c
parent3786b7d785f6c99faef13374c23c4ccff660e119 (diff)
downloadovm-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.
Diffstat (limited to 'src/main.c')
-rw-r--r--src/main.c61
1 files changed, 61 insertions, 0 deletions
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)