]> git.sesse.net Git - interpreter_trials/blob - interpreter3.cpp
Add a tail-call variant with state as global variables in locked registers.
[interpreter_trials] / interpreter3.cpp
1 #include "bytecode.h"
2 #include <utility>
3 #include "interpreter.h"
4
5 namespace interpreter3
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
19     void op_return(CpuState *state)
20     {
21         state->cycle_count += 1;
22         state->exit = true;
23     }
24
25     void op_add(CpuState *state)
26     {
27         uint8_t reg = *state->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
38     }
39
40     void op_sub(CpuState *state)
41     {
42         uint8_t reg = *state->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     }
53
54     void op_mov(CpuState *state)
55     {
56         uint8_t reg = *state->pc++;
57         uint8_t dest = reg>>4, src = reg & 0xf;
58
59         state->regs[dest] = state->regs[src];
60         state->cycle_count += 2;
61
62     }
63
64     void op_movi(CpuState *state)
65     {
66         uint8_t reg = *state->pc++;
67         uint8_t dest = reg>>4;
68
69         int32_t imm = *(int32_t *)state->pc;
70         state->pc += 4;
71
72         state->regs[dest] = imm;
73         state->cycle_count += 6;
74
75     }
76
77     void op_b(CpuState *state)
78     {
79         int8_t rel = *state->pc++;
80         state->pc += rel;
81         state->cycle_count += 2;
82     }
83
84     void op_bnz(CpuState *state)
85     {
86         int8_t rel = *state->pc++;
87         if(!state->zero_flag)
88         {
89             state->pc += rel;
90         }
91         state->cycle_count += 2;
92     }
93
94     void (*dispatch_table[])(CpuState *) =
95     {
96         op_return,
97         op_add,
98         op_sub,
99         op_mov,
100         op_movi,
101         op_b,
102         op_bnz
103     };
104
105     std::pair<int32_t, uint32_t> interpreter_run(uint8_t *program, int32_t param)
106     {
107         CpuState local_state;
108         CpuState *state = &local_state;
109         state->pc = program;
110         state->regs[X0] = param;
111         state->cycle_count = 0;
112         state->exit = false;
113
114         while(!state->exit)
115         {
116             uint8_t opcode = *state->pc++;
117             dispatch_table[opcode](state);
118         }
119
120         return std::make_pair(state->regs[X0], state->cycle_count);
121
122     }
123
124
125 }