--- /dev/null
+#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,
+};
--- /dev/null
+#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
--- /dev/null
+#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);
+ }
+
+ }
+
+
+}
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)