aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--.gitignore2
-rw-r--r--src/fvm.c18
-rw-r--r--src/fvm.h11
-rw-r--r--tests/test_opcodes.c301
4 files changed, 313 insertions, 19 deletions
diff --git a/.gitignore b/.gitignore
index 8bc6794..6f1c27d 100644
--- a/.gitignore
+++ b/.gitignore
@@ -1,4 +1,4 @@
-foo
+fvm
*.o
*.d
*.bin
diff --git a/src/fvm.c b/src/fvm.c
index 858bd4a..6326dc8 100644
--- a/src/fvm.c
+++ b/src/fvm.c
@@ -10,6 +10,7 @@ int fvm_init(struct fvm *vm, void *code, int64_t 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;
}
@@ -74,14 +75,15 @@ void fvm_store8(struct fvm *vm, fvm_word_t addr, int8_t value) {
}
-int fvm_execute(struct fvm *vm) {
+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:
- fvm_push(vm, vm->sp);
+ a = vm->sp;
+ fvm_push(vm, a);
vm->pc++;
break;
case FVM_OP_SSP:
@@ -96,6 +98,15 @@ int fvm_execute(struct fvm *vm) {
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++;
@@ -410,8 +421,7 @@ int fvm_execute(struct fvm *vm) {
vm->pc++;
break;
case FVM_OP_EXIT:
- a = fvm_pop(vm);
- return a;
+ return vm->rv;
default:
fprintf(stderr, "unknown opcode.\n");
break;
diff --git a/src/fvm.h b/src/fvm.h
index bfa5888..8d8cb87 100644
--- a/src/fvm.h
+++ b/src/fvm.h
@@ -12,9 +12,10 @@ struct fvm;
typedef int64_t (*fvm_syscall_fn_t)(struct fvm* vm);
struct fvm {
- fvm_word_t sp;
- fvm_word_t bp;
- fvm_word_t pc;
+ fvm_word_t sp; // stack pointer
+ fvm_word_t bp; // base pointer
+ fvm_word_t pc; // programm counter
+ fvm_word_t rv; // return value
fvm_syscall_fn_t *syscall_table;
};
@@ -24,6 +25,8 @@ enum fvm_op {
FVM_OP_BP,
FVM_OP_SBP,
FVM_OP_PC,
+ FVM_OP_RV,
+ FVM_OP_SRV,
FVM_OP_IMM,
@@ -95,7 +98,7 @@ enum fvm_op {
};
int fvm_init(struct fvm *vm, void *code, int64_t stack_size);
-int fvm_execute(struct fvm *vm);
+int64_t fvm_execute(struct fvm *vm);
void fvm_push(struct fvm *vm, fvm_word_t value);
int64_t fvm_pop(struct fvm *vm);
diff --git a/tests/test_opcodes.c b/tests/test_opcodes.c
index 27bfbf3..9751b00 100644
--- a/tests/test_opcodes.c
+++ b/tests/test_opcodes.c
@@ -1,4 +1,5 @@
#include <assert.h>
+#include <stdint.h>
#include <stdio.h>
#include "fvm.h"
@@ -12,6 +13,7 @@ static void reset() {
vm.pc = (int64_t)code;
vm.sp = (int64_t)stack + 4095;
vm.bp = (int64_t)stack + 4095;
+ vm.rv = 0;
code_cursor = 0;
}
@@ -24,22 +26,301 @@ static void emit_num(int64_t x) {
code_cursor += 8;
}
-void test_imm() {
- printf("[TEST] imm\n");
+#define OP(op) emit_op(FVM_OP_##op)
+#define IMM(num) \
+ emit_op(FVM_OP_IMM); \
+ emit_num(num);
+#define EXPECT(n) assert(fvm_execute(&vm) == (n));
+#define BEGIN(name) void test_##name () { printf("[TEST] " #name "\n");
+#define END(name) printf("[PASS] " #name "\n"); }
- reset();
- emit_op(FVM_OP_IMM);
- emit_num(3);
- emit_op(FVM_OP_EXIT);
+BEGIN(imm)
+reset();
+IMM(3);
+OP(SRV);OP(EXIT);
+EXPECT(3);
+END(imm)
- assert(fvm_execute(&vm) == 3);
- printf("[PASS] imm\n");
-}
+BEGIN(sp)
+reset();
+int64_t expected = vm.sp;
+OP(SP);
+OP(SRV);OP(EXIT);
+EXPECT(expected);
+END(sp)
+
+
+BEGIN(ssp)
+int64_t expected = vm.sp + 4;
+//===
+reset();
+OP(SP);
+IMM(4);
+OP(ADD);
+OP(SSP);
+OP(SP);
+OP(SRV);OP(EXIT);
+EXPECT(expected);
+END(ssp)
+//===
+BEGIN(ld)
+int64_t e1 = 0xfefefefefefefefe;
+int32_t e2 = 0xfdfdfdfd;
+int16_t e3 = 0xfcfc;
+int8_t e4 = 0xfb;
+//===
+reset();
+IMM((int64_t)(&e1));
+OP(LD);
+OP(SRV);OP(EXIT);
+EXPECT(e1);
+//===
+reset();
+IMM((int64_t)(&e2));
+OP(LD32);
+OP(SRV);OP(EXIT);
+EXPECT(e2);
+//===
+reset();
+IMM((int64_t)(&e3));
+OP(LD16);
+OP(SRV);OP(EXIT);
+EXPECT(e3);
+//===
+reset();
+IMM((int64_t)(&e4));
+OP(LD8);
+OP(SRV);OP(EXIT);
+EXPECT(e4);
+END(ld)
+
+
+BEGIN(st)
+int64_t loc = 0;
+int32_t loc32 = 0;
+int16_t loc16 = 0;
+int8_t loc8 = 0;
+int64_t e1 = 0xfefefefefefefefe;
+int32_t e2 = 0xfdfdfdfd;
+int16_t e3 = 0xfcfc;
+int8_t e4 = 0xfb;
+//===
+reset();
+IMM(42);
+IMM(e1);
+IMM((int64_t)(&loc));
+OP(ST);
+OP(SRV);OP(EXIT);
+assert(fvm_execute(&vm) == 42);
+assert(loc == e1);
+//===
+reset();
+IMM(42);
+IMM(e2);
+IMM((int64_t)(&loc32));
+OP(ST32);
+OP(SRV);OP(EXIT);
+assert(fvm_execute(&vm) == 42);
+assert(loc32 == e2);
+//===
+reset();
+IMM(42);
+IMM(e3);
+IMM((int64_t)(&loc16));
+OP(ST16);
+OP(SRV);OP(EXIT);
+assert(fvm_execute(&vm) == 42);
+assert(loc16 == e3);
+//===
+reset();
+IMM(42);
+IMM(e4);
+IMM((int64_t)(&loc8));
+OP(ST8);
+OP(SRV);OP(EXIT);
+assert(fvm_execute(&vm) == 42);
+assert(loc8 == e4);
+END(st)
+
+
+BEGIN(dup)
+reset();
+IMM(42);
+OP(DUP);
+OP(SRV);OP(EXIT);
+EXPECT(42);
+//===
+reset();
+IMM(42);
+OP(DUP);
+OP(POP);
+OP(SRV);OP(EXIT);
+EXPECT(42);
+//===
+reset();
+IMM(3);
+IMM(42);
+OP(DUP);
+OP(POP);
+OP(POP);
+OP(SRV);OP(EXIT);
+EXPECT(3);
+END(dup)
+
+BEGIN(swap)
+reset();
+IMM(1);
+IMM(2);
+OP(SWAP);
+OP(SRV);OP(EXIT);
+EXPECT(1);
+//===
+reset();
+IMM(1);
+IMM(2);
+OP(SWAP);
+OP(POP);
+OP(SRV);OP(EXIT);
+EXPECT(2);
+END(swap)
+
+BEGIN(over)
+reset();
+IMM(1);
+IMM(2);
+OP(OVER);
+OP(SRV);OP(EXIT);
+EXPECT(1);
+//===
+reset();
+IMM(1);
+IMM(2);
+OP(OVER);
+OP(POP);
+OP(SRV);OP(EXIT);
+EXPECT(2);
+//===
+reset();
+IMM(1);
+IMM(2);
+OP(OVER);
+OP(POP);
+OP(POP);
+OP(SRV);OP(EXIT);
+EXPECT(1);
+END(over)
+
+BEGIN(add)
+reset();
+IMM(1);
+IMM(2);
+OP(ADD);
+OP(SRV);OP(EXIT);
+EXPECT(3);
+//===
+reset();
+IMM(42);
+IMM(1);
+IMM(2);
+OP(ADD);
+OP(POP);
+OP(SRV);OP(EXIT);
+EXPECT(42);
+END(add)
+
+BEGIN(sub)
+reset();
+IMM(1);
+IMM(2);
+OP(SUB);
+OP(SRV);OP(EXIT);
+EXPECT(-1);
+//===
+reset();
+IMM(42);
+IMM(1);
+IMM(2);
+OP(ADD);
+OP(POP);
+OP(SRV);OP(EXIT);
+EXPECT(42);
+END(sub)
+
+BEGIN(jmp)
+reset();
+IMM((int64_t)code + 14);
+OP(JMP);
+OP(SRV);OP(EXIT);
+OP(SRV);OP(EXIT);
+IMM(42);
+OP(SRV);OP(EXIT);
+EXPECT(42);
+END(jmp)
+
+BEGIN(jz)
+reset();
+IMM(0);
+IMM((int64_t)code + 32);
+OP(JZ);
+IMM(21);
+OP(SRV);OP(EXIT);
+OP(SRV);OP(EXIT);
+IMM(42);
+OP(SRV);OP(EXIT);
+EXPECT(42);
+//===
+reset();
+IMM(-1);
+IMM((int64_t)code + 30);
+OP(JZ);
+IMM(21);
+OP(SRV);OP(EXIT);
+OP(SRV);OP(EXIT);
+IMM(42);
+OP(SRV);OP(EXIT);
+EXPECT(21);
+END(jz)
+
+BEGIN(jnz)
+reset();
+IMM(0);
+IMM((int64_t)code + 32);
+OP(JNZ);
+IMM(21);
+OP(SRV);OP(EXIT);
+OP(SRV);OP(EXIT);
+IMM(42);
+OP(SRV);OP(EXIT);
+EXPECT(21);
+//===
+reset();
+IMM(-1);
+IMM((int64_t)code + 32);
+OP(JNZ);
+IMM(21);
+OP(SRV);OP(EXIT);
+OP(SRV);OP(EXIT);
+IMM(42);
+OP(SRV);OP(EXIT);
+EXPECT(42);
+END(jnz)
int main()
{
- test_imm();
+ test_imm();
+ test_sp();
+ test_ssp();
+ test_ld();
+ test_st();
+ test_dup();
+ test_swap();
+ test_over();
+ test_add();
+ test_sub();
+ test_jmp();
+ test_jz();
+ test_jnz();
return 0;
}