]> git.sesse.net Git - interpreter_trials/blob - interpreter6.cpp
interpreter 9: flags in separate registers
[interpreter_trials] / interpreter6.cpp
1 #include "bytecode.h"
2 #include <utility>
3 #include "interpreter.h"
4
5 namespace interpreter6
6 {
7
8     struct Flags
9     {
10         unsigned int zero:16;
11         unsigned int negative:16;
12     };
13
14     struct CpuState
15     {
16         int32_t regs[16] = {0};
17         uint32_t final_cycle_count = 0;
18     };
19
20
21     struct ReturnException
22     {
23     };
24
25
26     struct ReturnVal
27     {
28         uint8_t *pc;
29         Flags flags;
30         uint32_t cycle_count;
31     };
32
33
34 #define PARAMS CpuState *state, uint8_t *pc, Flags flags, uint32_t cycle_count
35 #define ARGS state, pc, flags, cycle_count
36 #define RETURN_VAL {pc, flags, cycle_count}
37
38     ReturnVal op_return(PARAMS)
39     {
40         cycle_count += 1;
41         state->final_cycle_count = cycle_count;
42         throw ReturnException();
43     }
44
45     ReturnVal op_add(PARAMS)
46     {
47         uint8_t reg = *pc++;
48         uint8_t dest = reg>>4, src = reg & 0xf;
49
50         int32_t v = state->regs[dest];
51         v += state->regs[src];
52
53         flags.zero = (v == 0);
54         flags.negative = (v < 0);
55         state->regs[dest] = v;
56         cycle_count += 2;
57         return RETURN_VAL;
58     }
59
60     ReturnVal op_sub(PARAMS)
61     {
62         uint8_t reg = *pc++;
63         uint8_t dest = reg>>4, src = reg & 0xf;
64
65         int32_t v = state->regs[dest];
66         v -= state->regs[src];
67
68         flags.zero = (v == 0);
69         flags.negative = (v < 0);
70         state->regs[dest] = v;
71         cycle_count += 2;
72         return RETURN_VAL;
73     }
74
75     ReturnVal op_mov(PARAMS)
76     {
77         uint8_t reg = *pc++;
78         uint8_t dest = reg>>4, src = reg & 0xf;
79
80         state->regs[dest] = state->regs[src];
81         cycle_count += 2;
82         return RETURN_VAL;
83
84     }
85
86     ReturnVal op_movi(PARAMS)
87     {
88         uint8_t reg = *pc++;
89         uint8_t dest = reg>>4;
90
91         int32_t imm = *(int32_t *)pc;
92         pc += 4;
93
94         state->regs[dest] = imm;
95         cycle_count += 6;
96         return RETURN_VAL;
97
98     }
99
100     ReturnVal op_b(PARAMS)
101     {
102         int8_t rel = *pc++;
103         pc += rel;
104         cycle_count += 2;
105         return RETURN_VAL;
106     }
107
108     ReturnVal op_bnz(PARAMS)
109     {
110         int8_t rel = *pc++;
111         if(!flags.zero)
112         {
113             pc += rel;
114         }
115         cycle_count += 2;
116         return RETURN_VAL;
117     }
118
119     ReturnVal (*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         Flags flags = {0, 0};
138         try
139         {
140             while(true)
141             {
142                 uint8_t opcode = *pc++;
143                 ReturnVal ret = dispatch_table[opcode](ARGS);
144                 pc = ret.pc;
145                 flags = ret.flags;
146                 cycle_count = ret.cycle_count;
147             }
148
149
150         } catch(ReturnException ex)
151         {
152             return std::make_pair(state->regs[X0], state->final_cycle_count);
153         }
154
155     }
156
157
158 }