aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorBad Diode <bd@badd10de.dev>2024-06-19 15:56:21 +0200
committerBad Diode <bd@badd10de.dev>2024-06-19 15:56:21 +0200
commit211515623f498d952d507e4bbbf5869a26a8419c (patch)
tree02db5e81f2f73eb27360697f2c30d9b7272b0214
parentaeca71546bb8c94d1aeae6fe3e15835a2541317d (diff)
downloadbdl-211515623f498d952d507e4bbbf5869a26a8419c.tar.gz
bdl-211515623f498d952d507e4bbbf5869a26a8419c.zip
Add a bunch of op types to the VM
-rw-r--r--src/main.c236
-rw-r--r--tests/expressions.bad8
2 files changed, 192 insertions, 52 deletions
diff --git a/src/main.c b/src/main.c
index 2c24eaf..8d0cb6e 100644
--- a/src/main.c
+++ b/src/main.c
@@ -31,7 +31,7 @@ typedef struct Instruction {
31typedef union Constant { 31typedef union Constant {
32 s64 i; 32 s64 i;
33 u64 u; 33 u64 u;
34 double d; 34 double f;
35 ptrsize ptr; 35 ptrsize ptr;
36} Constant; 36} Constant;
37 37
@@ -43,29 +43,164 @@ typedef struct Chunk {
43} Chunk; 43} Chunk;
44 44
45typedef enum OpCode { 45typedef enum OpCode {
46 OP_HALT, 46 // OP DST A B
47 OP_INT_ADD, 47 // ---------------------------------------------------------------
48 OP_INT_SUB, 48 OP_HALT, // halt
49 OP_INT_MUL, 49 OP_LD8K, // ld8k rx, ca -> u8 rx = ca
50 OP_INT_DIV, 50 OP_LD16K, // ld16k rx, ca -> u16 rx = ca
51 OP_INT_MOD, 51 OP_LD32K, // ld32k rx, ca -> u32 rx = ca
52 OP_LD64K, // ld64k rx, ca -> u64 rx = ca
53 OP_LD8I, // ld8i rx, ra, cb -> u8 *p; rx = p[ra + cb]
54 OP_LD16I, // ld16i rx, ra, cb -> u16 *p; rx = p[ra + cb]
55 OP_LD32I, // ld32i rx, ra, cb -> u32 *p; rx = p[ra + cb]
56 OP_LD64I, // ld64i rx, ra, cb -> u64 *p; rx = p[ra + cb]
57 OP_LD8, // ld8 rx, ra, rb -> u8 *p; rx = p[ra + rb]
58 OP_LD16, // ld16 rx, ra, rb -> u16 *p; rx = p[ra + rb]
59 OP_LD32, // ld32 rx, ra, rb -> u32 *p; rx = p[ra + rb]
60 OP_LD64, // ld64 rx, ra, rb -> u64 *p; rx = p[ra + rb]
61 OP_ST8I, // st8i rx, ra, cb -> u8 *p; p[ra + cb] = rx
62 OP_ST16I, // st16i rx, ra, cb -> u16 *p; p[ra + cb] = rx
63 OP_ST32I, // st32i rx, ra, cb -> u32 *p; p[ra + cb] = rx
64 OP_ST64I, // st64i rx, ra, cb -> u64 *p; p[ra + cb] = rx
65 OP_ST8, // st8 rx, ra, rb -> u8 *p; p[ra + rb] = rx
66 OP_ST16, // st16 rx, ra, rb -> u16 *p; p[ra + rb] = rx
67 OP_ST32, // st32 rx, ra, rb -> u32 *p; p[ra + rb] = rx
68 OP_ST64, // st64 rx, ra, rb -> u64 *p; p[ra + rb] = rx
69 OP_ADDI, // addk rx, ra, cb
70 OP_SUBI, // subk rx, ra, cb
71 OP_MULI, // mulk rx, ra, cb
72 OP_DIVI, // divk rx, ra, cb
73 OP_MODI, // modk rx, ra, cb
74 OP_ADD, // add rx, ra, rb
75 OP_SUB, // sub rx, ra, rb
76 OP_MUL, // mul rx, ra, rb
77 OP_DIV, // div rx, ra, rb
78 OP_MOD, // mod rx, ra, rb
79 OP_ADDFI, // addk rx, ra, cb
80 OP_SUBFI, // subk rx, ra, cb
81 OP_MULFI, // mulk rx, ra, cb
82 OP_DIVFI, // divk rx, ra, cb
83 OP_MODFI, // modk rx, ra, cb
84 OP_ADDF, // add rx, ra, rb
85 OP_SUBF, // sub rx, ra, rb
86 OP_MULF, // mul rx, ra, rb
87 OP_DIVF, // div rx, ra, rb
88 OP_MODF, // mod rx, ra, rb
89 OP_MOV8, // mov8 rx, ra -> rx = ra & 0xFF
90 OP_MOV16, // mov16 rx, ra -> rx = ra & 0xFFFF
91 OP_MOV32, // mov32 rx, ra -> rx = ra & 0xFFFFFFFF
92 OP_MOV64, // mov64 rx, ra -> rx = ra & 0xFFFFFFFFFFFFFFFF
52} OpCode; 93} OpCode;
53 94
54Str op_str[] = { 95Str op_str[] = {
55 [OP_HALT] = cstr("HALT "), [OP_INT_ADD] = cstr("ADD "), 96 [OP_HALT] = cstr("HALT "),
56 [OP_INT_SUB] = cstr("SUB "), [OP_INT_MUL] = cstr("MUL "), 97 // Load ops.
57 [OP_INT_DIV] = cstr("DIV "), [OP_INT_MOD] = cstr("MOD "), 98 [OP_LD8K] = cstr("LD8K "),
99 [OP_LD16K] = cstr("LD16K "),
100 [OP_LD32K] = cstr("LD32K "),
101 [OP_LD64K] = cstr("LD64K "),
102 [OP_LD8I] = cstr("LD8I "),
103 [OP_LD16I] = cstr("LD16I "),
104 [OP_LD32I] = cstr("LD32I "),
105 [OP_LD64I] = cstr("LD64I "),
106 [OP_LD8] = cstr("LD8 "),
107 [OP_LD16] = cstr("LD16 "),
108 [OP_LD32] = cstr("LD32 "),
109 [OP_LD64] = cstr("LD64 "),
110 // Store ops.
111 [OP_ST8I] = cstr("ST8I "),
112 [OP_ST16I] = cstr("ST16I "),
113 [OP_ST32I] = cstr("ST32I "),
114 [OP_ST64I] = cstr("ST64I "),
115 [OP_ST8] = cstr("ST8 "),
116 [OP_ST16] = cstr("ST16 "),
117 [OP_ST32] = cstr("ST32 "),
118 [OP_ST64] = cstr("ST64 "),
119 // Arithmetic.
120 [OP_ADDI] = cstr("ADDI "),
121 [OP_SUBI] = cstr("SUBI "),
122 [OP_MULI] = cstr("MULI "),
123 [OP_DIVI] = cstr("DIVI "),
124 [OP_MODI] = cstr("MODI "),
125 [OP_ADD] = cstr("ADD "),
126 [OP_SUB] = cstr("SUB "),
127 [OP_MUL] = cstr("MUL "),
128 [OP_DIV] = cstr("DIV "),
129 [OP_MOD] = cstr("MOD "),
130 [OP_ADDFI] = cstr("ADDFI "),
131 [OP_SUBFI] = cstr("SUBFI "),
132 [OP_MULFI] = cstr("MULFI "),
133 [OP_DIVFI] = cstr("DIVFI "),
134 [OP_MODFI] = cstr("MODFI "),
135 [OP_ADDF] = cstr("ADDF "),
136 [OP_SUBF] = cstr("SUBF "),
137 [OP_MULF] = cstr("MULF "),
138 [OP_DIVF] = cstr("DIVF "),
139 // Reg copy/move.
140 [OP_MODF] = cstr("MODF "),
141 [OP_MOV8] = cstr("MOV8 "),
142 [OP_MOV16] = cstr("MOV16 "),
143 [OP_MOV32] = cstr("MOV32 "),
144 [OP_MOV64] = cstr("MOV64 "),
58}; 145};
59 146
60void 147void
61disassemble_instruction(Instruction instruction) { 148disassemble_instruction(Instruction instruction) {
62 switch (instruction.op) { 149 switch (instruction.op) {
63 case OP_INT_SUB: 150 case OP_MOV8:
64 case OP_INT_MUL: 151 case OP_MOV16:
65 case OP_INT_DIV: 152 case OP_MOV32:
66 case OP_INT_MOD: 153 case OP_MOV64:
67 case OP_INT_ADD: 154 println("%s r%d, r%d", op_str[instruction.op], instruction.dst,
68 println("%s %d %d %d", op_str[instruction.op], instruction.dst, 155 instruction.a, instruction.b);
156 break;
157 case OP_LD8K:
158 case OP_LD16K:
159 case OP_LD32K:
160 case OP_LD64K:
161 println("%s r%d, c%d", op_str[instruction.op], instruction.dst,
162 instruction.a, instruction.b);
163 break;
164 case OP_LD8I:
165 case OP_LD16I:
166 case OP_LD32I:
167 case OP_LD64I:
168 case OP_ST8I:
169 case OP_ST16I:
170 case OP_ST32I:
171 case OP_ST64I:
172 case OP_ADDI:
173 case OP_SUBI:
174 case OP_MULI:
175 case OP_DIVI:
176 case OP_MODI:
177 case OP_ADDFI:
178 case OP_SUBFI:
179 case OP_MULFI:
180 case OP_DIVFI:
181 case OP_MODFI:
182 println("%s r%d, r%d, c%d", op_str[instruction.op], instruction.dst,
183 instruction.a, instruction.b);
184 break;
185 case OP_LD8:
186 case OP_LD16:
187 case OP_LD32:
188 case OP_LD64:
189 case OP_ST8:
190 case OP_ST16:
191 case OP_ST32:
192 case OP_ST64:
193 case OP_ADD:
194 case OP_SUB:
195 case OP_MUL:
196 case OP_DIV:
197 case OP_MOD:
198 case OP_ADDF:
199 case OP_SUBF:
200 case OP_MULF:
201 case OP_DIVF:
202 case OP_MODF:
203 println("%s r%d, r%d, r%d", op_str[instruction.op], instruction.dst,
69 instruction.a, instruction.b); 204 instruction.a, instruction.b);
70 break; 205 break;
71 case OP_HALT: println("%s", op_str[instruction.op]); break; 206 case OP_HALT: println("%s", op_str[instruction.op]); break;
@@ -107,6 +242,25 @@ vm_init(VM *vm, Chunk *chunk) {
107 vm->ip = vm->chunk->code; 242 vm->ip = vm->chunk->code;
108} 243}
109 244
245#define OP_ARITHMETIC(OP, TYPE) \
246 do { \
247 u8 dst = instruction.dst; \
248 u8 src_a = instruction.a; \
249 u8 src_b = instruction.b; \
250 vm->regs[dst].TYPE = vm->regs[src_a].TYPE OP vm->regs[src_b].TYPE; \
251 } while (0);
252
253#define OP_ARITHMETIC_CONST(OP, TYPE) \
254 do { \
255 u8 dst = instruction.dst; \
256 u8 src_a = instruction.a; \
257 u8 src_b = instruction.b; \
258 vm->regs[dst].TYPE = \
259 vm->regs[src_a].TYPE OP vm->chunk->constants[src_b].TYPE; \
260 } while (0);
261
262#include <math.h>
263
110void 264void
111vm_run(VM *vm) { 265vm_run(VM *vm) {
112 assert(vm); 266 assert(vm);
@@ -119,37 +273,23 @@ vm_run(VM *vm) {
119 print("IP: %d -> ", vm->ip - vm->chunk->code - 1); 273 print("IP: %d -> ", vm->ip - vm->chunk->code - 1);
120 disassemble_instruction(instruction); 274 disassemble_instruction(instruction);
121#endif 275#endif
276
122 switch (instruction.op) { 277 switch (instruction.op) {
123 // TODO: Other numeric types 278 case OP_ADD: OP_ARITHMETIC(+, i) break;
124 case OP_INT_ADD: { 279 case OP_SUB: OP_ARITHMETIC(-, i) break;
125 u8 dst = instruction.dst; 280 case OP_MUL: OP_ARITHMETIC(*, i) break;
126 u8 src_a = instruction.a; 281 case OP_DIV: OP_ARITHMETIC(/, i) break;
127 u8 src_b = instruction.b; 282 case OP_MOD: OP_ARITHMETIC(%, i) break;
128 vm->regs[dst].i = vm->regs[src_a].i + vm->regs[src_b].i; 283 case OP_ADDF: OP_ARITHMETIC(+, f) break;
129 } break; 284 case OP_SUBF: OP_ARITHMETIC(-, f) break;
130 case OP_INT_SUB: { 285 case OP_MULF: OP_ARITHMETIC(*, f) break;
131 u8 dst = instruction.dst; 286 case OP_DIVF: OP_ARITHMETIC(/, f) break;
132 u8 src_a = instruction.a; 287 case OP_MODF: {
133 u8 src_b = instruction.b;
134 vm->regs[dst].i = vm->regs[src_a].i - vm->regs[src_b].i;
135 } break;
136 case OP_INT_MUL: {
137 u8 dst = instruction.dst;
138 u8 src_a = instruction.a;
139 u8 src_b = instruction.b;
140 vm->regs[dst].i = vm->regs[src_a].i * vm->regs[src_b].i;
141 } break;
142 case OP_INT_DIV: {
143 u8 dst = instruction.dst;
144 u8 src_a = instruction.a;
145 u8 src_b = instruction.b;
146 vm->regs[dst].i = vm->regs[src_a].i / vm->regs[src_b].i;
147 } break;
148 case OP_INT_MOD: {
149 u8 dst = instruction.dst; 288 u8 dst = instruction.dst;
150 u8 src_a = instruction.a; 289 u8 src_a = instruction.a;
151 u8 src_b = instruction.b; 290 u8 src_b = instruction.b;
152 vm->regs[dst].i = vm->regs[src_a].i % vm->regs[src_b].i; 291 vm->regs[dst].f =
292 fmod(vm->regs[src_a].f, vm->chunk->constants[src_b].f);
153 } break; 293 } break;
154 case OP_HALT: { 294 case OP_HALT: {
155 return; 295 return;
@@ -179,11 +319,11 @@ compile_binary(OpCode op, Chunk *chunk, Node *node, Arena *a) {
179sz 319sz
180compile_expr(Chunk *chunk, Node *node, Arena *a) { 320compile_expr(Chunk *chunk, Node *node, Arena *a) {
181 switch (node->kind) { 321 switch (node->kind) {
182 case NODE_ADD: return compile_binary(OP_INT_ADD, chunk, node, a); break; 322 case NODE_ADD: return compile_binary(OP_ADD, chunk, node, a); break;
183 case NODE_SUB: return compile_binary(OP_INT_SUB, chunk, node, a); break; 323 case NODE_SUB: return compile_binary(OP_SUB, chunk, node, a); break;
184 case NODE_MUL: return compile_binary(OP_INT_MUL, chunk, node, a); break; 324 case NODE_MUL: return compile_binary(OP_MUL, chunk, node, a); break;
185 case NODE_DIV: return compile_binary(OP_INT_DIV, chunk, node, a); break; 325 case NODE_DIV: return compile_binary(OP_DIV, chunk, node, a); break;
186 case NODE_MOD: return compile_binary(OP_INT_MOD, chunk, node, a); break; 326 case NODE_MOD: return compile_binary(OP_MOD, chunk, node, a); break;
187 case NODE_NUM_INT: { 327 case NODE_NUM_INT: {
188 chunk->constants[reg_idx] = (Constant){.i = node->value.i}; 328 chunk->constants[reg_idx] = (Constant){.i = node->value.i};
189 return reg_idx++; 329 return reg_idx++;
diff --git a/tests/expressions.bad b/tests/expressions.bad
index 5b114d1..0213694 100644
--- a/tests/expressions.bad
+++ b/tests/expressions.bad
@@ -1,9 +1,9 @@
11 + -2 11 + -2
2 2
31 + 2 * 3 3; 1 + 2 * 3
4 4
51 + 2 * 3 - 4 5; 1 + 2 * 3 - 4
6 6
71 + 2 * (3 - 4) 7; 1 + 2 * (3 - 4)
8 8
91.0 - 1234.56e-3 9; 1.0 - 1234.56e-3