tinyvm/include/tvm/tvm.h
2017-02-12 11:38:01 -08:00

86 lines
2.7 KiB
C

#ifndef TVM_H_
#define TVM_H_
#include <stddef.h>
#include "tvm_file.h"
#include "tvm_preprocessor.h"
#include "tvm_stack.h"
#include "tvm_memory.h"
#include "tvm_program.h"
#include "tvm_tokens.h"
struct tvm_ctx {
struct tvm_prog *prog;
struct tvm_mem *mem;
};
struct tvm_ctx *tvm_vm_create();
void tvm_vm_destroy(struct tvm_ctx *vm);
int tvm_vm_interpret(struct tvm_ctx *vm, char *filename);
void tvm_vm_run(struct tvm_ctx *vm);
static inline void tvm_step(struct tvm_ctx *vm, int *instr_idx)
{
int **args = vm->prog->args[*instr_idx];
switch (vm->prog->instr[*instr_idx]) {
/* nop */ case 0x0: break;
/* int */ case 0x1: /* unimplemented */ break;
/* mov */ case 0x2: *args[0] = *args[1]; break;
/* push */ case 0x3: tvm_stack_push(vm->mem, args[0]); break;
/* pop */ case 0x4: tvm_stack_pop(vm->mem, args[0]); break;
/* pushf */ case 0x5: tvm_stack_push(vm->mem, &vm->mem->FLAGS); break;
/* popf */ case 0x6: tvm_stack_pop(vm->mem, args[0]); break;
/* inc */ case 0x7: ++(*args[0]); break;
/* dec */ case 0x8: --(*args[0]); break;
/* add */ case 0x9: *args[0] += *args[1]; break;
/* sub */ case 0xA: *args[0] -= *args[1]; break;
/* mul */ case 0xB: *args[0] *= *args[1]; break;
/* div */ case 0xC: *args[0] /= *args[1]; break;
/* mod */ case 0xD: vm->mem->remainder = *args[0] % *args[1]; break;
/* rem */ case 0xE: *args[0] = vm->mem->remainder; break;
/* not */ case 0xF: *args[0] = ~(*args[0]); break;
/* xor */ case 0x10: *args[0] ^= *args[1]; break;
/* or */ case 0x11: *args[0] |= *args[1]; break;
/* and */ case 0x12: *args[0] &= *args[1]; break;
/* shl */ case 0x13: *args[0] <<= *args[1]; break;
/* shr */ case 0x14: *args[0] >>= *args[1]; break;
/* cmp */ case 0x15: vm->mem->FLAGS =
((*args[0] == *args[1]) | (*args[0] > *args[1]) << 1);
break;
/* call */ case 0x17: tvm_stack_push(vm->mem, instr_idx);
/* jmp */ case 0x16: *instr_idx = *args[0] - 1; break;
/* ret */ case 0x18: tvm_stack_pop(vm->mem, instr_idx);
break;
/* je */ case 0x19:
*instr_idx = (vm->mem->FLAGS & 0x1)
? *args[0] - 1 : *instr_idx;
break;
/* jne */ case 0x1A:
*instr_idx = (!(vm->mem->FLAGS & 0x1))
? *args[0] - 1 : *instr_idx;
break;
/* jg */ case 0x1B:
*instr_idx = (vm->mem->FLAGS & 0x2)
? *args[0] - 1 : *instr_idx;
break;
/* jge */ case 0x1C:
*instr_idx = (vm->mem->FLAGS & 0x3)
? *args[0] - 1 : *instr_idx;
break;
/* jl */ case 0x1D:
*instr_idx = (!(vm->mem->FLAGS & 0x3))
? *args[0] - 1 : *instr_idx;
break;
/* jle */ case 0x1E:
*instr_idx = (!(vm->mem->FLAGS & 0x2))
? *args[0] - 1 : *instr_idx;
break;
/* prn */ case 0x1F: printf("%i\n", *args[0]);
};
}
#endif