#ifndef VM_C #define VM_C #include "badlib.h" #include "compiler.c" #define N_CONST 256 #define STACK_SIZE KB(64) typedef struct VM { Chunk *chunk; Constant regs[N_CONST]; u8 stack[STACK_SIZE]; Instruction *ip; } VM; void vm_init(VM *vm, Chunk *chunk) { assert(vm); assert(chunk); assert(chunk->code); vm->chunk = chunk; vm->ip = vm->chunk->code; } #define OP_UNARY(OP, TYPE) \ do { \ u8 dst = instruction.dst; \ u8 src_a = instruction.a; \ vm->regs[dst].TYPE = OP vm->regs[src_a].TYPE; \ } while (0); #define OP_UNARY_CONST(OP, TYPE) \ do { \ u8 dst = instruction.dst; \ u8 src_a = instruction.a; \ vm->regs[dst].TYPE = OP vm->chunk->constants[src_a].TYPE; \ } while (0); #define OP_BINARY(OP, TYPE) \ do { \ u8 dst = instruction.dst; \ u8 src_a = instruction.a; \ u8 src_b = instruction.b; \ vm->regs[dst].TYPE = vm->regs[src_a].TYPE OP vm->regs[src_b].TYPE; \ } while (0); #define OP_BINARY_CONST(OP, TYPE) \ do { \ u8 dst = instruction.dst; \ u8 src_a = instruction.a; \ u8 src_b = instruction.b; \ vm->regs[dst].TYPE = \ vm->regs[src_a].TYPE OP vm->chunk->constants[src_b].TYPE; \ } while (0); #include void vm_run(VM *vm) { assert(vm); assert(vm->chunk); assert(vm->ip); println("VM running..."); while (true) { Instruction instruction = *vm->ip++; #if DEBUG == 1 print("IP: %d -> ", vm->ip - vm->chunk->code - 1); disassemble_instruction(instruction); #endif switch (instruction.op) { case OP_LD64K: { u8 dst = instruction.dst; u8 src_a = instruction.a; vm->regs[dst].i = vm->chunk->constants[src_a].i; } break; case OP_NOT: OP_UNARY(!, i) break; case OP_BITNOT: OP_UNARY(~, i) break; case OP_BITOR: OP_BINARY(|, i) break; case OP_BITAND: OP_BINARY(&, i) break; case OP_BITLSHIFT: OP_BINARY(<<, i) break; case OP_BITRSHIFT: OP_BINARY(>>, i) break; case OP_EQ: OP_BINARY(==, i) break; case OP_NEQ: OP_BINARY(!=, i) break; case OP_LT: OP_BINARY(<, i) break; case OP_GT: OP_BINARY(>, i) break; case OP_LE: OP_BINARY(<=, i) break; case OP_GE: OP_BINARY(>=, i) break; case OP_AND: OP_BINARY(&&, i) break; case OP_OR: OP_BINARY(||, i) break; case OP_ADD: OP_BINARY(+, i) break; case OP_SUB: OP_BINARY(-, i) break; case OP_MUL: OP_BINARY(*, i) break; case OP_DIV: OP_BINARY(/, i) break; case OP_MOD: OP_BINARY(%, i) break; case OP_ADDF: OP_BINARY(+, f) break; case OP_SUBF: OP_BINARY(-, f) break; case OP_MULF: OP_BINARY(*, f) break; case OP_DIVF: OP_BINARY(/, f) break; case OP_MODF: { u8 dst = instruction.dst; u8 src_a = instruction.a; u8 src_b = instruction.b; vm->regs[dst].f = fmod(vm->regs[src_a].f, vm->chunk->constants[src_b].f); } break; case OP_NOTI: OP_UNARY_CONST(!, i) break; case OP_BITNOTI: OP_UNARY_CONST(~, i) break; case OP_BITORI: OP_BINARY_CONST(|, i) break; case OP_BITANDI: OP_BINARY_CONST(&, i) break; case OP_BITLSHIFTI: OP_BINARY_CONST(<<, i) break; case OP_BITRSHIFTI: OP_BINARY_CONST(>>, i) break; case OP_EQI: OP_BINARY_CONST(==, i) break; case OP_NEQI: OP_BINARY_CONST(!=, i) break; case OP_LTI: OP_BINARY_CONST(<, i) break; case OP_GTI: OP_BINARY_CONST(>, i) break; case OP_LEI: OP_BINARY_CONST(<=, i) break; case OP_GEI: OP_BINARY_CONST(>=, i) break; case OP_ANDI: OP_BINARY_CONST(&&, i) break; case OP_ORI: OP_BINARY_CONST(||, i) break; case OP_ADDI: OP_BINARY_CONST(+, i) break; case OP_SUBI: OP_BINARY_CONST(-, i) break; case OP_MULI: OP_BINARY_CONST(*, i) break; case OP_DIVI: OP_BINARY_CONST(/, i) break; case OP_MODI: OP_BINARY_CONST(%, i) break; case OP_ADDFI: OP_BINARY_CONST(+, f) break; case OP_SUBFI: OP_BINARY_CONST(-, f) break; case OP_MULFI: OP_BINARY_CONST(*, f) break; case OP_DIVFI: OP_BINARY_CONST(/, f) break; case OP_MODFI: { u8 dst = instruction.dst; u8 src_a = instruction.a; u8 src_b = instruction.b; vm->regs[dst].f = fmod(vm->regs[src_a].f, vm->chunk->constants[src_b].f); } break; case OP_LDVAR: { u8 dst = instruction.dst; u8 src = instruction.a; println("dst: %d src: %d", dst, src); Variable var = vm->chunk->vars[src]; s64 *stack = (s64 *)&vm->stack[var.offset]; vm->regs[dst].i = *stack; } break; case OP_STVAR: { u8 dst = instruction.dst; u8 src = instruction.a; Variable var = vm->chunk->vars[dst]; s64 *stack = (s64 *)&vm->stack[var.offset]; *stack = vm->regs[src].i; } break; case OP_STVARI: { u8 dst = instruction.dst; u8 src = instruction.a; Variable var = vm->chunk->vars[dst]; s64 *stack = (s64 *)&vm->stack[var.offset]; *stack = vm->chunk->constants[src].i; } break; case OP_HALT: { println("VM HALT (int) -> %d", vm->regs[instruction.dst]); println("VM HALT (float) -> %f", vm->regs[instruction.dst]); println("VM HALT (hex) -> %x", vm->regs[instruction.dst]); return; } default: { eprintln("unimplemented OP code: %d", instruction.op); return; } } } } #endif // VM_C