diff options
| author | Mistivia <i@mistivia.com> | 2024-11-17 12:29:47 +0800 |
|---|---|---|
| committer | Mistivia <i@mistivia.com> | 2024-11-17 12:29:47 +0800 |
| commit | 04f8a72b1436a91cfecf73567a59626c7bdc664f (patch) | |
| tree | 18b060712715e032e02a951e2d5368a1fba0a111 | |
| parent | 789ebeb7d097d2824ff62c73438af4cb77f882bc (diff) | |
add test case for basic opcodes
| -rw-r--r-- | .gitignore | 2 | ||||
| -rw-r--r-- | src/fvm.c | 18 | ||||
| -rw-r--r-- | src/fvm.h | 11 | ||||
| -rw-r--r-- | tests/test_opcodes.c | 301 |
4 files changed, 313 insertions, 19 deletions
@@ -1,4 +1,4 @@ -foo +fvm *.o *.d *.bin @@ -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; @@ -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; } |
