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