123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432 |
- #include <stdint.h>
- #include <stdlib.h>
- #include <stdio.h>
- #include <assert.h>
- #include "fvm.h"
- int fvm_init(struct fvm *vm, void *code, int64_t stack_size) {
- void *stack_vm = malloc(stack_size);
- vm->sp = (fvm_word_t)(stack_vm + stack_size);
- vm->bp = vm->sp;
- vm->pc = (fvm_word_t)code;
- vm->rv = 0;
- return 1;
- }
- void fvm_push(struct fvm *vm, fvm_word_t val) {
- vm->sp -= sizeof(fvm_word_t);
- fvm_store(vm, vm->sp, val);
- }
- int64_t fvm_pop(struct fvm *vm) {
- int64_t r = fvm_load(vm, vm->sp);
- vm->sp += sizeof(fvm_word_t);
- return r;
- }
- void fvm_pushf(struct fvm *vm, fvm_float_t val) {
- assert(sizeof(fvm_word_t) >= sizeof(fvm_float_t));
- vm->sp -= sizeof(fvm_word_t);
- fvm_storef(vm, vm->sp, val);
- }
- fvm_float_t fvm_popf(struct fvm *vm) {
- assert(sizeof(fvm_word_t) >= sizeof(fvm_float_t));
- fvm_float_t r = fvm_loadf(vm, vm->sp);
- vm->sp += sizeof(fvm_word_t);
- return r;
- }
- fvm_float_t fvm_loadf(struct fvm *vm, fvm_word_t addr) {
- return *(fvm_float_t*)addr;
- }
- void fvm_storef(struct fvm *vm, fvm_word_t addr, fvm_float_t val) {
- *(fvm_float_t*)addr = val;
- }
- fvm_word_t fvm_load(struct fvm *vm, fvm_word_t addr) {
- return *(fvm_word_t*)addr;
- }
- void fvm_store(struct fvm *vm, fvm_word_t addr, int64_t value) {
- *(fvm_word_t*)addr = value;
- }
- int32_t fvm_load32(struct fvm *vm, fvm_word_t addr) {
- return *(int32_t*)addr;
- }
- void fvm_store32(struct fvm *vm, fvm_word_t addr, int32_t value) {
- *(int32_t*)addr = value;
- }
- int16_t fvm_load16(struct fvm *vm, fvm_word_t addr) {
- return *(int16_t*)addr;
- }
- void fvm_store16(struct fvm *vm, fvm_word_t addr, int16_t value) {
- *(int16_t*)addr = value;
- }
- int8_t fvm_load8(struct fvm *vm, fvm_word_t addr) {
- return *(int8_t*)addr;
- }
- void fvm_store8(struct fvm *vm, fvm_word_t addr, int8_t value) {
- *(int8_t*)addr = value;
- }
- int64_t fvm_execute(struct fvm *vm) {
- fvm_word_t a, b, c;
- fvm_float_t x, y, z;
- while (1) {
- enum fvm_op op = (enum fvm_op)(uint8_t)fvm_load8(vm, vm->pc);
- switch (op) {
- case FVM_OP_SP:
- a = vm->sp;
- fvm_push(vm, a);
- vm->pc++;
- break;
- case FVM_OP_SSP:
- vm->sp = fvm_pop(vm);
- vm->pc++;
- break;
- case FVM_OP_BP:
- fvm_push(vm, vm->bp);
- vm->pc++;
- break;
- case FVM_OP_SBP:
- vm->bp = fvm_pop(vm);
- vm->pc++;
- break;
- case FVM_OP_RV:
- a = vm->rv;
- fvm_push(vm, a);
- vm->pc++;
- break;
- case FVM_OP_SRV:
- vm->rv = fvm_pop(vm);
- vm->pc++;
- break;
- case FVM_OP_PC:
- fvm_push(vm, vm->pc);
- vm->pc++;
- break;
- case FVM_OP_IMM:
- fvm_push(vm, fvm_load(vm, vm->pc + 1));
- vm->pc += sizeof(fvm_word_t) + 1;
- break;
- case FVM_OP_LD:
- fvm_push(vm, fvm_load(vm, fvm_pop(vm)));
- vm->pc++;
- break;
- case FVM_OP_LD32:
- fvm_push(vm, fvm_load32(vm, fvm_pop(vm)));
- vm->pc++;
- break;
- case FVM_OP_LD16:
- fvm_push(vm, fvm_load16(vm, fvm_pop(vm)));
- vm->pc++;
- break;
- case FVM_OP_LD8:
- fvm_push(vm, fvm_load8(vm, fvm_pop(vm)));
- vm->pc++;
- break;
- case FVM_OP_ST:
- b = fvm_pop(vm);
- a = fvm_pop(vm);
- fvm_store(vm, b, a);
- vm->pc++;
- break;
- case FVM_OP_ST32:
- b = fvm_pop(vm);
- a = fvm_pop(vm);
- fvm_store32(vm, b, a);
- vm->pc++;
- break;
- case FVM_OP_ST16:
- b = fvm_pop(vm);
- a = fvm_pop(vm);
- fvm_store16(vm, b, a);
- vm->pc++;
- break;
- case FVM_OP_ST8:
- b = fvm_pop(vm);
- a = fvm_pop(vm);
- fvm_store8(vm, b, a);
- vm->pc++;
- break;
- case FVM_OP_DUP:
- a = fvm_pop(vm);
- fvm_push(vm, a);
- fvm_push(vm, a);
- vm->pc++;
- break;
- case FVM_OP_POP:
- fvm_pop(vm);
- vm->pc++;
- break;
- case FVM_OP_SWAP:
- a = fvm_pop(vm);
- b = fvm_pop(vm);
- fvm_push(vm, a);
- fvm_push(vm, b);
- vm->pc++;
- break;
- case FVM_OP_OVER:
- a = fvm_pop(vm);
- b = fvm_pop(vm);
- fvm_push(vm, b);
- fvm_push(vm, a);
- fvm_push(vm, b);
- vm->pc++;
- break;
- case FVM_OP_ROT:
- a = fvm_pop(vm);
- b = fvm_pop(vm);
- c = fvm_pop(vm);
- fvm_push(vm, b);
- fvm_push(vm, a);
- fvm_push(vm, c);
- vm->pc++;
- break;
- case FVM_OP_ADD:
- a = fvm_pop(vm);
- b = fvm_pop(vm);
- fvm_push(vm, a + b);
- vm->pc++;
- break;
- case FVM_OP_SUB:
- b = fvm_pop(vm);
- a = fvm_pop(vm);
- fvm_push(vm, a - b);
- vm->pc++;
- break;
- case FVM_OP_MUL:
- b = fvm_pop(vm);
- a = fvm_pop(vm);
- fvm_push(vm, a * b);
- vm->pc++;
- break;
- case FVM_OP_DIV:
- b = fvm_pop(vm);
- a = fvm_pop(vm);
- fvm_push(vm, a / b);
- vm->pc++;
- break;
- case FVM_OP_MOD:
- b = fvm_pop(vm);
- a = fvm_pop(vm);
- fvm_push(vm, a % b);
- vm->pc++;
- break;
- case FVM_OP_SHR:
- b = fvm_pop(vm);
- a = fvm_pop(vm);
- fvm_push(vm, (int64_t)(((uint64_t)a) >> b));
- vm->pc++;
- break;
- case FVM_OP_SHL:
- b = fvm_pop(vm);
- a = fvm_pop(vm);
- fvm_push(vm, a << b);
- vm->pc++;
- break;
- case FVM_OP_SAR:
- b = fvm_pop(vm);
- a = fvm_pop(vm);
- fvm_push(vm, a >> b);
- vm->pc++;
- break;
- case FVM_OP_AND:
- b = fvm_pop(vm);
- a = fvm_pop(vm);
- fvm_push(vm, a && b);
- vm->pc++;
- break;
- case FVM_OP_OR:
- b = fvm_pop(vm);
- a = fvm_pop(vm);
- fvm_push(vm, a || b);
- vm->pc++;
- break;
- case FVM_OP_NOT:
- a = fvm_pop(vm);
- fvm_push(vm, !a);
- vm->pc++;
- break;
- case FVM_OP_BITAND:
- b = fvm_pop(vm);
- a = fvm_pop(vm);
- fvm_push(vm, a & b);
- vm->pc++;
- break;
- case FVM_OP_BITOR:
- b = fvm_pop(vm);
- a = fvm_pop(vm);
- fvm_push(vm, a | b);
- vm->pc++;
- break;
- case FVM_OP_XOR:
- b = fvm_pop(vm);
- a = fvm_pop(vm);
- fvm_push(vm, a ^ b);
- vm->pc++;
- break;
- case FVM_OP_INVERT:
- a = fvm_pop(vm);
- fvm_push(vm, ~a);
- vm->pc++;
- break;
- case FVM_OP_GE:
- b = fvm_pop(vm);
- a = fvm_pop(vm);
- fvm_push(vm, a >= b);
- vm->pc++;
- break;
- case FVM_OP_LE:
- b = fvm_pop(vm);
- a = fvm_pop(vm);
- fvm_push(vm, a <= b);
- vm->pc++;
- break;
- case FVM_OP_GT:
- b = fvm_pop(vm);
- a = fvm_pop(vm);
- fvm_push(vm, a > b);
- vm->pc++;
- break;
- case FVM_OP_LT:
- b = fvm_pop(vm);
- a = fvm_pop(vm);
- fvm_push(vm, a < b);
- vm->pc++;
- break;
- case FVM_OP_EQ:
- b = fvm_pop(vm);
- a = fvm_pop(vm);
- fvm_push(vm, a == b);
- vm->pc++;
- break;
- case FVM_OP_NEQ:
- b = fvm_pop(vm);
- a = fvm_pop(vm);
- fvm_push(vm, a != b);
- vm->pc++;
- break;
- case FVM_OP_JMP:
- vm->pc = fvm_pop(vm);
- break;
- case FVM_OP_JZ:
- b = fvm_pop(vm);
- a = fvm_pop(vm);
- if (a) {
- vm->pc++;
- break;
- } else {
- vm->pc = b;
- break;
- }
- case FVM_OP_JNZ:
- b = fvm_pop(vm);
- a = fvm_pop(vm);
- if (a) {
- vm->pc = b;
- break;
- } else {
- vm->pc++;
- break;
- }
- case FVM_OP_CALL:
- a = fvm_pop(vm);
- fvm_push(vm, vm->pc);
- vm->pc = a;
- break;
- case FVM_OP_RET:
- a = fvm_pop(vm);
- vm->pc = a;
- break;
- case FVM_OP_SYSCALL:
- a = fvm_pop(vm);
- vm->pc++;
- (*(vm->syscall_table[a]))(vm);
- break;
- case FVM_OP_FADD:
- y = fvm_popf(vm);
- x = fvm_popf(vm);
- fvm_pushf(vm, x + y);
- vm->pc++;
- break;
- case FVM_OP_FSUB:
- y = fvm_popf(vm);
- x = fvm_popf(vm);
- fvm_pushf(vm, x - y);
- vm->pc++;
- break;
- case FVM_OP_FMUL:
- y = fvm_popf(vm);
- x = fvm_popf(vm);
- fvm_pushf(vm, x * y);
- vm->pc++;
- break;
- case FVM_OP_FDIV:
- y = fvm_popf(vm);
- x = fvm_popf(vm);
- fvm_pushf(vm, x / y);
- vm->pc++;
- break;
- case FVM_OP_FGE:
- y = fvm_popf(vm);
- x = fvm_popf(vm);
- fvm_push(vm, x >= y);
- vm->pc++;
- break;
- case FVM_OP_FGT:
- y = fvm_popf(vm);
- x = fvm_popf(vm);
- fvm_push(vm, x > y);
- vm->pc++;
- break;
- case FVM_OP_FLE:
- y = fvm_popf(vm);
- x = fvm_popf(vm);
- fvm_push(vm, x <= y);
- vm->pc++;
- break;
- case FVM_OP_FLT:
- y = fvm_popf(vm);
- x = fvm_popf(vm);
- fvm_push(vm, x < y);
- vm->pc++;
- break;
- case FVM_OP_FEQ:
- y = fvm_popf(vm);
- x = fvm_popf(vm);
- fvm_push(vm, x == y);
- vm->pc++;
- break;
- case FVM_OP_FNEQ:
- y = fvm_popf(vm);
- x = fvm_popf(vm);
- fvm_push(vm, x != y);
- vm->pc++;
- break;
- case FVM_OP_FTI:
- x = fvm_popf(vm);
- fvm_push(vm, (fvm_word_t)x);
- vm->pc++;
- break;
- case FVM_OP_ITF:
- a = fvm_pop(vm);
- fvm_pushf(vm, (fvm_float_t)x);
- vm->pc++;
- break;
- case FVM_OP_EXIT:
- return vm->rv;
- default:
- fprintf(stderr, "unknown opcode.\n");
- exit(-1);
- break;
- }
- }
- return -1;
- }
|