]> git.sesse.net Git - interpreter_trials/blob - interpreter1.cpp
Add a tail-call variant with state as global variables in locked registers.
[interpreter_trials] / interpreter1.cpp
1 #include "bytecode.h"
2 #include <utility>
3 #include "interpreter.h"
4
5 namespace interpreter1
6 {
7
8     struct CpuState
9     {
10         int32_t regs[16] = {0};
11         bool zero_flag = false;
12         bool negative_flag = false;
13         uint8_t *pc = nullptr;
14         uint32_t cycle_count = 0;
15         bool exit = false;
16     };
17
18     CpuState global_state;
19
20     void op_return()
21     {
22         global_state.exit = true;
23     }
24
25     void op_add()
26     {
27         uint8_t reg = *global_state.pc++;
28         uint8_t dest = reg>>4, src = reg & 0xf;
29
30         int32_t v = global_state.regs[dest];
31         v += global_state.regs[src];
32
33         global_state.zero_flag = (v == 0);
34         global_state.negative_flag = (v < 0);
35         global_state.regs[dest] = v;
36
37     }
38
39     void op_sub()
40     {
41         uint8_t reg = *global_state.pc++;
42         uint8_t dest = reg>>4, src = reg & 0xf;
43
44         int32_t v = global_state.regs[dest];
45         v -= global_state.regs[src];
46
47         global_state.zero_flag = (v == 0);
48         global_state.negative_flag = (v < 0);
49         global_state.regs[dest] = v;
50     }
51
52     void op_mov()
53     {
54         uint8_t reg = *global_state.pc++;
55         uint8_t dest = reg>>4, src = reg & 0xf;
56
57         global_state.regs[dest] = global_state.regs[src];
58
59     }
60
61     void op_movi()
62     {
63         uint8_t reg = *global_state.pc++;
64         uint8_t dest = reg>>4;
65
66         int32_t imm = *(int32_t *)global_state.pc;
67         global_state.pc += 4;
68
69         global_state.regs[dest] = imm;
70
71     }
72
73     void op_b()
74     {
75         int8_t rel = *global_state.pc++;
76         global_state.pc += rel;
77     }
78
79     void op_bnz()
80     {
81         int8_t rel = *global_state.pc++;
82         if(!global_state.zero_flag)
83         {
84             global_state.pc += rel;
85         }
86     }
87
88     void (*dispatch_table[])() =
89     {
90         op_return,
91         op_add,
92         op_sub,
93         op_mov,
94         op_movi,
95         op_b,
96         op_bnz
97     };
98
99     std::pair<int32_t, uint32_t> interpreter_run(uint8_t *program, int32_t param)
100     {
101         global_state.pc = program;
102         global_state.regs[X0] = param;
103         global_state.cycle_count = 0;
104         global_state.exit = false;
105
106         while(!global_state.exit)
107         {
108             uint8_t opcode = *global_state.pc++;
109             global_state.cycle_count += cycle_table[opcode];
110             dispatch_table[opcode]();
111         }
112
113         return std::make_pair(global_state.regs[X0], global_state.cycle_count);
114     }
115
116
117 }