Browse Source

add test case for basic opcodes

Mistivia 4 months ago
parent
commit
04f8a72b14
4 changed files with 313 additions and 19 deletions
  1. 1 1
      .gitignore
  2. 14 4
      src/fvm.c
  3. 7 4
      src/fvm.h
  4. 291 10
      tests/test_opcodes.c

+ 1 - 1
.gitignore

@@ -1,4 +1,4 @@
-foo
+fvm
 *.o
 *.d
 *.bin

+ 14 - 4
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; 

+ 7 - 4
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);

+ 291 - 10
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;
 }