]> git.sesse.net Git - interpreter_trials/commitdiff
first stab at interpreter
authorRune Holm <rune.holm@arm.com>
Wed, 16 Jun 2021 21:20:19 +0000 (23:20 +0200)
committerRune Holm <rune.holm@arm.com>
Wed, 16 Jun 2021 21:20:19 +0000 (23:20 +0200)
bytecode.cpp [new file with mode: 0644]
bytecode.h [new file with mode: 0644]
interpreter.h [new file with mode: 0644]
interpreter1.cpp [new file with mode: 0644]
meson.build

diff --git a/bytecode.cpp b/bytecode.cpp
new file mode 100644 (file)
index 0000000..52be7db
--- /dev/null
@@ -0,0 +1,37 @@
+#include "bytecode.h"
+
+
+uint8_t cycle_table[8] = {
+    1,
+    2,
+    2,
+    2,
+    6,
+    2,
+    2,
+};
+
+
+uint8_t fibonacci[] = {
+
+    // initializer
+
+    OP_MOV, REGS(X3, X0),
+    OP_MOVI, REGS(X0, 0), IMM(0),
+    OP_MOVI, REGS(X1, 0), IMM(1),
+    OP_MOV, REGS(X4, X1),
+
+    OP_SUB, REGS(X3, X0),
+    OP_BNZ, 1,
+    OP_RETURN, // early-out for fibonacci(0)
+
+
+    // loop start
+    OP_MOV, REGS(X2, X0),
+    OP_MOV, REGS(X0, X1),
+    OP_ADD, REGS(X1, X2),
+    OP_SUB, REGS(X3, X4),
+    OP_BNZ, uint8_t(-10),
+
+    OP_RETURN,
+};
diff --git a/bytecode.h b/bytecode.h
new file mode 100644 (file)
index 0000000..db99e86
--- /dev/null
@@ -0,0 +1,47 @@
+#ifndef BYTECODE_H
+#define BYTECODE_H
+
+#include <cstdint>
+
+enum Opcode
+{
+    OP_RETURN = 0, /* no args */
+    OP_ADD = 1,       /* 8-bit dest, src */
+    OP_SUB = 2,       /* 8-bit dest, src */
+    OP_MOV = 3,       /* 8-bit dest, src */
+    OP_MOVI = 4,      /* 8-bit dest, 0. 32-bit immediate */
+    OP_B = 5,         /* 8-bit relative */
+    OP_BNZ = 6        /* 8-bit relative */
+};
+
+
+enum Register
+{
+    X0 = 0,
+    X1 = 1,
+    X2 = 2,
+    X3 = 3,
+    X4 = 4,
+    X5 = 5,
+    X6 = 6,
+    X7 = 7,
+    X8 = 8,
+    X9 = 9,
+    X10 = 10,
+    X11 = 11,
+    X12 = 12,
+    X13 = 13,
+    X14 = 14,
+    X15 = 15
+
+};
+
+#define REGS(dest, src) ((((dest)&0xf)<<4)|((src)&0xf))
+#define IMM(imm) (((imm)>>0)&0xff), (((imm)>>8)&0xff), (((imm)>>16)&0xff), (((imm)>>24)&0xff)
+
+
+extern uint8_t cycle_table[];
+
+extern uint8_t fibonacci[];
+
+#endif //BYTECODE_H
diff --git a/interpreter.h b/interpreter.h
new file mode 100644 (file)
index 0000000..27fc43b
--- /dev/null
@@ -0,0 +1,12 @@
+#ifndef INTERPRETER_H
+#define INTERPRETER_H
+
+#include <utility>
+#include <cstdint>
+
+namespace interpreter1
+{
+    std::pair<int32_t, uint32_t> interpreter1_run(uint8_t *program, int32_t param);
+}
+
+#endif
diff --git a/interpreter1.cpp b/interpreter1.cpp
new file mode 100644 (file)
index 0000000..77924d1
--- /dev/null
@@ -0,0 +1,127 @@
+#include "bytecode.h"
+#include <utility>
+#include "interpreter.h"
+
+namespace interpreter1
+{
+
+    struct CpuState
+    {
+        int32_t regs[16] = {0};
+        bool zero_flag = false;
+        bool negative_flag = false;
+        uint8_t *pc = nullptr;
+        uint32_t cycle_count = 0;
+    };
+
+    CpuState global_state;
+
+    struct ReturnException
+    {
+    };
+
+    void op_return()
+    {
+        throw ReturnException();
+    }
+
+    void op_add()
+    {
+        uint8_t reg = *global_state.pc++;
+        uint8_t dest = reg>>4, src = reg & 0xf;
+
+        int32_t v = global_state.regs[dest];
+        v += global_state.regs[src];
+
+        global_state.zero_flag = (v == 0);
+        global_state.negative_flag = (v < 0);
+        global_state.regs[dest] = v;
+
+    }
+
+    void op_sub()
+    {
+        uint8_t reg = *global_state.pc++;
+        uint8_t dest = reg>>4, src = reg & 0xf;
+
+        int32_t v = global_state.regs[dest];
+        v -= global_state.regs[src];
+
+        global_state.zero_flag = (v == 0);
+        global_state.negative_flag = (v < 0);
+        global_state.regs[dest] = v;
+    }
+
+    void op_mov()
+    {
+        uint8_t reg = *global_state.pc++;
+        uint8_t dest = reg>>4, src = reg & 0xf;
+
+        global_state.regs[dest] = global_state.regs[src];
+
+    }
+
+    void op_movi()
+    {
+        uint8_t reg = *global_state.pc++;
+        uint8_t dest = reg>>4;
+
+        int32_t imm = *(int32_t *)global_state.pc;
+        global_state.pc += 4;
+
+        global_state.regs[dest] = imm;
+
+    }
+
+    void op_b()
+    {
+        int8_t rel = *global_state.pc++;
+        global_state.pc += rel;
+    }
+
+    void op_bnz()
+    {
+        int8_t rel = *global_state.pc++;
+        if(!global_state.zero_flag)
+        {
+            global_state.pc += rel;
+        }
+    }
+
+    void (*dispatch_table[])() =
+    {
+        op_return,
+        op_add,
+        op_sub,
+        op_mov,
+        op_movi,
+        op_b,
+        op_bnz
+    };
+
+    std::pair<int32_t, uint32_t> interpreter1_run(uint8_t *program, int32_t param)
+    {
+        global_state.pc = program;
+        global_state.regs[X0] = param;
+        global_state.cycle_count = 0;
+        try
+        {
+            while(true)
+            {
+                uint8_t opcode = *global_state.pc++;
+                dispatch_table[opcode]();
+                global_state.cycle_count += cycle_table[opcode];
+
+
+            }
+
+
+        } catch(ReturnException ex)
+        {
+            return std::make_pair(global_state.regs[X0], global_state.cycle_count);
+        }
+
+    }
+
+
+}
index a0e3e29dd2815847287ea3b0761003a48e47fd4a..a82b33053800699a35ca88dfd294be805bc8ffbf 100644 (file)
@@ -4,4 +4,8 @@ project('interpreter_trials', 'cpp',
 benchmark_proj = subproject('google-benchmark')
 benchmark_dep = benchmark_proj.get_variable('google_benchmark_dep')
 
-executable('interpreter_trials', 'interpreter_trials.cpp', dependencies : benchmark_dep)
+executable('interpreter_trials',
+       'interpreter_trials.cpp',
+       'bytecode.cpp',
+       'interpreter1.cpp',
+                                       dependencies : benchmark_dep)