]> git.sesse.net Git - interpreter_trials/commitdiff
interpreter 9: flags in separate registers
authorRune Holm <rune.holm@arm.com>
Wed, 16 Jun 2021 22:54:15 +0000 (00:54 +0200)
committerRune Holm <rune.holm@arm.com>
Wed, 16 Jun 2021 22:54:15 +0000 (00:54 +0200)
interpreter9.cpp [new file with mode: 0644]
interpreter_trials.cpp
meson.build

diff --git a/interpreter9.cpp b/interpreter9.cpp
new file mode 100644 (file)
index 0000000..5a80fda
--- /dev/null
@@ -0,0 +1,161 @@
+#include "bytecode.h"
+#include <utility>
+#include "interpreter.h"
+
+namespace interpreter9
+{
+
+    struct CpuState
+    {
+        int32_t regs[16] = {0};
+        uint32_t final_cycle_count = 0;
+    };
+
+
+    struct ReturnException
+    {
+    };
+
+
+
+#define PARAMS CpuState *state, uint8_t *pc, bool flags_zero, bool flags_negative, uint32_t cycle_count, void *dispatch_table_void
+#define ARGS state, pc, flags_zero, flags_negative, cycle_count, dispatch_table_void
+
+    typedef void (*DispatchFun)(PARAMS);
+
+    void op_return(PARAMS)
+    {
+        cycle_count += 1;
+        state->final_cycle_count = cycle_count;
+        throw ReturnException();
+    }
+
+    void op_add(PARAMS)
+    {
+        uint8_t reg = *pc++;
+        uint8_t dest = reg>>4, src = reg & 0xf;
+
+        int32_t v = state->regs[dest];
+        v += state->regs[src];
+
+        flags_zero = (v == 0);
+        flags_negative = (v < 0);
+        state->regs[dest] = v;
+        cycle_count += 2;
+
+        uint8_t opcode = *pc++;
+        DispatchFun *dispatch_table = (DispatchFun *)dispatch_table_void;
+        dispatch_table[opcode](ARGS);
+    }
+
+    void op_sub(PARAMS)
+    {
+        uint8_t reg = *pc++;
+        uint8_t dest = reg>>4, src = reg & 0xf;
+
+        int32_t v = state->regs[dest];
+        v -= state->regs[src];
+
+        flags_zero = (v == 0);
+        flags_negative = (v < 0);
+        state->regs[dest] = v;
+        cycle_count += 2;
+
+        uint8_t opcode = *pc++;
+        DispatchFun *dispatch_table = (DispatchFun *)dispatch_table_void;
+        dispatch_table[opcode](ARGS);
+    }
+
+    void op_mov(PARAMS)
+    {
+        uint8_t reg = *pc++;
+        uint8_t dest = reg>>4, src = reg & 0xf;
+
+        state->regs[dest] = state->regs[src];
+        cycle_count += 2;
+
+        uint8_t opcode = *pc++;
+        DispatchFun *dispatch_table = (DispatchFun *)dispatch_table_void;
+        dispatch_table[opcode](ARGS);
+    }
+
+    void op_movi(PARAMS)
+    {
+        uint8_t reg = *pc++;
+        uint8_t dest = reg>>4;
+
+        int32_t imm = *(int32_t *)pc;
+        pc += 4;
+
+        state->regs[dest] = imm;
+        cycle_count += 6;
+
+        uint8_t opcode = *pc++;
+        DispatchFun *dispatch_table = (DispatchFun *)dispatch_table_void;
+        dispatch_table[opcode](ARGS);
+    }
+
+    void op_b(PARAMS)
+    {
+        int8_t rel = *pc++;
+        pc += rel;
+        cycle_count += 2;
+
+        uint8_t opcode = *pc++;
+        DispatchFun *dispatch_table = (DispatchFun *)dispatch_table_void;
+        dispatch_table[opcode](ARGS);
+    }
+
+    void op_bnz(PARAMS)
+    {
+        int8_t rel = *pc++;
+        if(!flags_zero)
+        {
+            pc += rel;
+        }
+        cycle_count += 2;
+
+        uint8_t opcode = *pc++;
+        DispatchFun *dispatch_table = (DispatchFun *)dispatch_table_void;
+        dispatch_table[opcode](ARGS);
+    }
+
+    void (*dispatch_table[])(PARAMS) =
+    {
+        op_return,
+        op_add,
+        op_sub,
+        op_mov,
+        op_movi,
+        op_b,
+        op_bnz
+    };
+
+    std::pair<int32_t, uint32_t> interpreter_run(uint8_t *program, int32_t param)
+    {
+        CpuState local_state;
+        CpuState *state = &local_state;
+        uint8_t *pc = program;
+        state->regs[X0] = param;
+        uint32_t cycle_count = 0;
+        bool flags_zero = false;
+        bool flags_negative = false;
+        void *dispatch_table_void = (void*)&dispatch_table[0];
+        try
+        {
+            while(true)
+            {
+                uint8_t opcode = *pc++;
+                dispatch_table[opcode](ARGS);
+            }
+
+
+        } catch(ReturnException ex)
+        {
+            return std::make_pair(state->regs[X0], state->final_cycle_count);
+        }
+
+    }
+
+
+}
index 12c5529f99593956c0250fa9148002a0d028032c..fa5476de9616a9d9a0b94830fd1da840086fc424 100644 (file)
@@ -84,4 +84,12 @@ static void interpreter8_dispatch_table_in_registers(benchmark::State& state) {
 }
 BENCHMARK(interpreter8_dispatch_table_in_registers);
 
+static void interpreter9_separate_flags(benchmark::State& state) {
+    for (auto _ : state)
+    {
+        run(interpreter9::interpreter_run);
+    }
+}
+BENCHMARK(interpreter9_separate_flags);
+
 BENCHMARK_MAIN();
index 64e0ed2a30cd016be963f98ffee28fb9bb730bb8..9fd7fc2108359f1ca404680f8578be142a7a6ef9 100644 (file)
@@ -15,4 +15,5 @@ executable('interpreter_trials',
        'interpreter6.cpp',
        'interpreter7.cpp',
        'interpreter8.cpp',
+       'interpreter9.cpp',
                                        dependencies : benchmark_dep)