--- /dev/null
+#include "bytecode.h"
+#include <utility>
+#include "interpreter.h"
+
+namespace interpreter12
+{
+
+ struct Flags
+ {
+ unsigned int zero:16;
+ unsigned int negative:16;
+ };
+
+ struct CpuState
+ {
+ int32_t regs[16] = {0};
+ uint32_t final_cycle_count = 0;
+ };
+
+#ifdef __arm__
+register CpuState *state asm("r4");
+register uint8_t *pc asm("r5");
+register Flags flags asm("r6");
+register uint32_t cycle_count asm("r7");
+#elif __x86_64__
+register CpuState *state asm("r12");
+register uint8_t *pc asm("r13");
+register Flags flags asm("r14");
+register uint32_t cycle_count asm("rbx");
+#else
+static CpuState *state;
+static uint8_t *pc;
+static Flags flags;
+static uint32_t cycle_count;
+#endif
+
+ extern void (*dispatch_table[])();
+
+ void op_return()
+ {
+ cycle_count += 1;
+ state->final_cycle_count = cycle_count;
+ return;
+ }
+
+ void op_add()
+ {
+ 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++;
+ dispatch_table[opcode]();
+ }
+
+ void op_sub()
+ {
+ 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++;
+ dispatch_table[opcode]();
+ }
+
+ void op_mov()
+ {
+ 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++;
+ dispatch_table[opcode]();
+ }
+
+ void op_movi()
+ {
+ 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++;
+ dispatch_table[opcode]();
+ }
+
+ void op_b()
+ {
+ int8_t rel = *pc++;
+ pc += rel;
+ cycle_count += 2;
+
+ uint8_t opcode = *pc++;
+ dispatch_table[opcode]();
+ }
+
+ void op_bnz()
+ {
+ int8_t rel = *pc++;
+ if(!flags.zero)
+ {
+ pc += rel;
+ }
+ cycle_count += 2;
+
+ uint8_t opcode = *pc++;
+ dispatch_table[opcode]();
+ }
+
+ void (*dispatch_table[])() =
+ {
+ 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)
+ {
+ // Save the previous value of our locked registers.
+ CpuState *save_state = state;
+ uint8_t *save_pc = pc;
+ Flags save_flags = {flags.zero, flags.negative};
+ uint32_t save_cycle_count = cycle_count;
+
+ CpuState local_state;
+ state = &local_state;
+ pc = program;
+ state->regs[X0] = param;
+ cycle_count = 0;
+ flags.zero = flags.negative = 0;
+
+ uint8_t opcode = *pc++;
+ dispatch_table[opcode]();
+
+ auto ret = std::make_pair(state->regs[X0], state->final_cycle_count);
+
+ // Restore locked registers. (Note that on 64-bit platforms, this will
+ // corrupt the high 32 bits of flags and cycle_count, so this is really
+ // only safe on 32-bit as it stands.)
+ state = save_state;
+ pc = save_pc;
+ flags.zero = save_flags.zero;
+ flags.negative = save_flags.negative;
+ cycle_count = save_cycle_count;
+
+ return ret;
+ }
+
+
+}