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