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