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