]> git.sesse.net Git - interpreter_trials/blob - interpreter10.cpp
Add a tail-call variant with state as global variables in locked registers.
[interpreter_trials] / interpreter10.cpp
1 #include "bytecode.h"
2 #include <utility>
3 #include "interpreter.h"
4
5 namespace interpreter10
6 {
7
8     struct CpuState
9     {
10         int32_t regs[16] = {0};
11         uint32_t final_cycle_count = 0;
12         bool flags_zero = false;
13         bool flags_negative = false;
14     };
15
16
17
18 #define PARAMS CpuState *state, uint8_t *pc, uint32_t cycle_count, void *dispatch_table_void
19 #define ARGS state, pc, cycle_count, dispatch_table_void
20
21     typedef void (*DispatchFun)(PARAMS);
22
23     void op_return(PARAMS)
24     {
25         cycle_count += 1;
26         state->final_cycle_count = cycle_count;
27         return;
28     }
29
30     void op_add(PARAMS)
31     {
32         uint8_t reg = *pc++;
33         uint8_t dest = reg>>4, src = reg & 0xf;
34
35         int32_t v = state->regs[dest];
36         v += state->regs[src];
37
38         state->flags_zero = (v == 0);
39         state->flags_negative = (v < 0);
40         state->regs[dest] = v;
41         cycle_count += 2;
42
43         uint8_t opcode = *pc++;
44         DispatchFun *dispatch_table = (DispatchFun *)dispatch_table_void;
45         dispatch_table[opcode](ARGS);
46     }
47
48     void op_sub(PARAMS)
49     {
50         uint8_t reg = *pc++;
51         uint8_t dest = reg>>4, src = reg & 0xf;
52
53         int32_t v = state->regs[dest];
54         v -= state->regs[src];
55
56         state->flags_zero = (v == 0);
57         state->flags_negative = (v < 0);
58         state->regs[dest] = v;
59         cycle_count += 2;
60
61         uint8_t opcode = *pc++;
62         DispatchFun *dispatch_table = (DispatchFun *)dispatch_table_void;
63         dispatch_table[opcode](ARGS);
64     }
65
66     void op_mov(PARAMS)
67     {
68         uint8_t reg = *pc++;
69         uint8_t dest = reg>>4, src = reg & 0xf;
70
71         state->regs[dest] = state->regs[src];
72         cycle_count += 2;
73
74         uint8_t opcode = *pc++;
75         DispatchFun *dispatch_table = (DispatchFun *)dispatch_table_void;
76         dispatch_table[opcode](ARGS);
77     }
78
79     void op_movi(PARAMS)
80     {
81         uint8_t reg = *pc++;
82         uint8_t dest = reg>>4;
83
84         int32_t imm = *(int32_t *)pc;
85         pc += 4;
86
87         state->regs[dest] = imm;
88         cycle_count += 6;
89
90         uint8_t opcode = *pc++;
91         DispatchFun *dispatch_table = (DispatchFun *)dispatch_table_void;
92         dispatch_table[opcode](ARGS);
93     }
94
95     void op_b(PARAMS)
96     {
97         int8_t rel = *pc++;
98         pc += rel;
99         cycle_count += 2;
100
101         uint8_t opcode = *pc++;
102         DispatchFun *dispatch_table = (DispatchFun *)dispatch_table_void;
103         dispatch_table[opcode](ARGS);
104     }
105
106     void op_bnz(PARAMS)
107     {
108         int8_t rel = *pc++;
109         if(!state->flags_zero)
110         {
111             pc += rel;
112         }
113         cycle_count += 2;
114
115         uint8_t opcode = *pc++;
116         DispatchFun *dispatch_table = (DispatchFun *)dispatch_table_void;
117         dispatch_table[opcode](ARGS);
118     }
119
120     void (*dispatch_table[])(PARAMS) =
121     {
122         op_return,
123         op_add,
124         op_sub,
125         op_mov,
126         op_movi,
127         op_b,
128         op_bnz
129     };
130
131     std::pair<int32_t, uint32_t> interpreter_run(uint8_t *program, int32_t param)
132     {
133         CpuState local_state;
134         CpuState *state = &local_state;
135         uint8_t *pc = program;
136         state->regs[X0] = param;
137         uint32_t cycle_count = 0;
138         void *dispatch_table_void = (void*)&dispatch_table[0];
139
140         uint8_t opcode = *pc++;
141         dispatch_table[opcode](ARGS);
142
143         return std::make_pair(state->regs[X0], state->final_cycle_count);
144
145     }
146
147
148 }