Instructions are no longer member functions
[riscv-isa-sim.git] / riscv / processor.cc
1 // See LICENSE for license details.
2
3 #include "processor.h"
4 #include "common.h"
5 #include "config.h"
6 #include "sim.h"
7 #include "disasm.h"
8 #include <cinttypes>
9 #include <cmath>
10 #include <cstdlib>
11 #include <iostream>
12 #include <assert.h>
13 #include <limits.h>
14
15 processor_t::processor_t(sim_t* _sim, mmu_t* _mmu, uint32_t _id)
16 : sim(*_sim), mmu(*_mmu), id(_id), opcode_bits(0)
17 {
18 reset(true);
19 mmu.set_processor(this);
20
21 #define DECLARE_INSN(name, match, mask) \
22 extern reg_t rv32_##name(processor_t*, insn_t, reg_t); \
23 extern reg_t rv64_##name(processor_t*, insn_t, reg_t); \
24 register_insn(match, mask, rv32_##name, rv64_##name);
25 #include "opcodes.h"
26 #undef DECLARE_INSN
27 }
28
29 processor_t::~processor_t()
30 {
31 }
32
33 void state_t::reset()
34 {
35 // the ISA guarantees on boot that the PC is 0x2000 and the the processor
36 // is in supervisor mode, and in 64-bit mode, if supported, with traps
37 // and virtual memory disabled.
38 sr = SR_S;
39 #ifdef RISCV_ENABLE_64BIT
40 sr |= SR_S64;
41 #endif
42 pc = 0x2000;
43
44 // the following state is undefined upon boot-up,
45 // but we zero it for determinism
46 XPR.reset();
47 FPR.reset();
48
49 evec = 0;
50 epc = 0;
51 badvaddr = 0;
52 cause = 0;
53 pcr_k0 = 0;
54 pcr_k1 = 0;
55 count = 0;
56 compare = 0;
57 cycle = 0;
58 fsr = 0;
59
60 load_reservation = -1;
61 }
62
63 void processor_t::reset(bool value)
64 {
65 if (run == !value)
66 return;
67 run = !value;
68
69 state.reset();
70 }
71
72 uint32_t processor_t::set_fsr(uint32_t val)
73 {
74 uint32_t old_fsr = state.fsr;
75 state.fsr = val & ~FSR_ZERO; // clear FSR bits that read as zero
76 return old_fsr;
77 }
78
79 void processor_t::take_interrupt()
80 {
81 uint32_t interrupts = (state.sr & SR_IP) >> SR_IP_SHIFT;
82 interrupts &= (state.sr & SR_IM) >> SR_IM_SHIFT;
83
84 if (interrupts && (state.sr & SR_EI))
85 for (int i = 0; ; i++, interrupts >>= 1)
86 if (interrupts & 1)
87 throw trap_t((1ULL << ((state.sr & SR_S64) ? 63 : 31)) + i);
88 }
89
90 void processor_t::step(size_t n, bool noisy)
91 {
92 if(!run)
93 return;
94
95 size_t i = 0;
96 reg_t npc = state.pc;
97 mmu_t& _mmu = mmu;
98
99 try
100 {
101 take_interrupt();
102
103 // execute_insn fetches and executes one instruction
104 #define execute_insn(noisy) \
105 do { \
106 mmu_t::insn_fetch_t fetch = _mmu.load_insn(npc); \
107 if(noisy) disasm(fetch.insn, npc); \
108 npc = fetch.func(this, fetch.insn, npc); \
109 } while(0)
110
111 if(noisy) for( ; i < n; i++) // print out instructions as we go
112 execute_insn(true);
113 else
114 {
115 // unrolled for speed
116 for( ; n > 3 && i < n-3; i+=4)
117 {
118 execute_insn(false);
119 execute_insn(false);
120 execute_insn(false);
121 execute_insn(false);
122 }
123 for( ; i < n; i++)
124 execute_insn(false);
125 }
126
127 state.pc = npc;
128 }
129 catch(trap_t& t)
130 {
131 take_trap(npc, t, noisy);
132 }
133
134 state.cycle += i;
135
136 // update timer and possibly register a timer interrupt
137 uint32_t old_count = state.count;
138 state.count += i;
139 if(old_count < state.compare && uint64_t(old_count) + i >= state.compare)
140 set_interrupt(IRQ_TIMER, true);
141 }
142
143 void processor_t::take_trap(reg_t pc, trap_t& t, bool noisy)
144 {
145 if(noisy)
146 {
147 if ((sreg_t)t.cause() < 0)
148 fprintf(stderr, "core %3d: interrupt %d, epc 0x%016" PRIx64 "\n",
149 id, uint8_t(t.cause()), pc);
150 else
151 fprintf(stderr, "core %3d: trap %s, epc 0x%016" PRIx64 "\n",
152 id, t.name(), pc);
153 }
154
155 // switch to supervisor, set previous supervisor bit, disable interrupts
156 set_pcr(PCR_SR, (((state.sr & ~SR_EI) | SR_S) & ~SR_PS & ~SR_PEI) |
157 ((state.sr & SR_S) ? SR_PS : 0) |
158 ((state.sr & SR_EI) ? SR_PEI : 0));
159 yield_load_reservation();
160 state.cause = t.cause();
161 state.epc = pc;
162 state.pc = state.evec;
163
164 t.side_effects(&state); // might set badvaddr etc.
165 }
166
167 void processor_t::deliver_ipi()
168 {
169 if (run)
170 set_pcr(PCR_CLR_IPI, 1);
171 }
172
173 void processor_t::disasm(insn_t insn, reg_t pc)
174 {
175 // the disassembler is stateless, so we share it
176 static disassembler disasm;
177 fprintf(stderr, "core %3d: 0x%016" PRIx64 " (0x%08" PRIxFAST32 ") %s\n",
178 id, state.pc, insn.bits, disasm.disassemble(insn).c_str());
179 }
180
181 reg_t processor_t::set_pcr(int which, reg_t val)
182 {
183 reg_t old_pcr = get_pcr(which);
184
185 switch (which)
186 {
187 case PCR_SR:
188 state.sr = (val & ~SR_IP) | (state.sr & SR_IP);
189 #ifndef RISCV_ENABLE_64BIT
190 state.sr &= ~(SR_S64 | SR_U64);
191 #endif
192 #ifndef RISCV_ENABLE_FPU
193 state.sr &= ~SR_EF;
194 #endif
195 #ifndef RISCV_ENABLE_VEC
196 state.sr &= ~SR_EV;
197 #endif
198 state.sr &= ~SR_ZERO;
199 mmu.flush_tlb();
200 break;
201 case PCR_EPC:
202 state.epc = val;
203 break;
204 case PCR_EVEC:
205 state.evec = val;
206 break;
207 case PCR_COUNT:
208 state.count = val;
209 break;
210 case PCR_COMPARE:
211 set_interrupt(IRQ_TIMER, false);
212 state.compare = val;
213 break;
214 case PCR_PTBR:
215 state.ptbr = val & ~(PGSIZE-1);
216 break;
217 case PCR_SEND_IPI:
218 sim.send_ipi(val);
219 break;
220 case PCR_CLR_IPI:
221 set_interrupt(IRQ_IPI, val & 1);
222 break;
223 case PCR_K0:
224 state.pcr_k0 = val;
225 break;
226 case PCR_K1:
227 state.pcr_k1 = val;
228 break;
229 case PCR_TOHOST:
230 if (state.tohost == 0)
231 state.tohost = val;
232 break;
233 case PCR_FROMHOST:
234 set_interrupt(IRQ_HOST, val != 0);
235 state.fromhost = val;
236 break;
237 }
238
239 return old_pcr;
240 }
241
242 reg_t processor_t::get_pcr(int which)
243 {
244 switch (which)
245 {
246 case PCR_SR:
247 return state.sr;
248 case PCR_EPC:
249 return state.epc;
250 case PCR_BADVADDR:
251 return state.badvaddr;
252 case PCR_EVEC:
253 return state.evec;
254 case PCR_COUNT:
255 return state.count;
256 case PCR_COMPARE:
257 return state.compare;
258 case PCR_CAUSE:
259 return state.cause;
260 case PCR_PTBR:
261 return state.ptbr;
262 case PCR_ASID:
263 return 0;
264 case PCR_FATC:
265 mmu.flush_tlb();
266 return 0;
267 case PCR_HARTID:
268 return id;
269 case PCR_IMPL:
270 return 1;
271 case PCR_K0:
272 return state.pcr_k0;
273 case PCR_K1:
274 return state.pcr_k1;
275 case PCR_TOHOST:
276 return state.tohost;
277 case PCR_FROMHOST:
278 return state.fromhost;
279 }
280 return -1;
281 }
282
283 void processor_t::set_interrupt(int which, bool on)
284 {
285 uint32_t mask = (1 << (which + SR_IP_SHIFT)) & SR_IP;
286 if (on)
287 state.sr |= mask;
288 else
289 state.sr &= ~mask;
290 }
291
292 static reg_t illegal_instruction(processor_t* p, insn_t insn, reg_t pc)
293 {
294 throw trap_illegal_instruction();
295 }
296
297 insn_func_t processor_t::decode_insn(insn_t insn)
298 {
299 bool rv64 = (state.sr & SR_S) ? (state.sr & SR_S64) : (state.sr & SR_U64);
300
301 auto key = insn.bits & ((1L << opcode_bits)-1);
302 for (auto it = opcode_map.find(key); it != opcode_map.end() && it->first == key; ++it)
303 if ((insn.bits & it->second.mask) == it->second.match)
304 return rv64 ? it->second.rv64 : it->second.rv32;
305
306 return &illegal_instruction;
307 }
308
309 void processor_t::register_insn(uint32_t match, uint32_t mask, insn_func_t rv32, insn_func_t rv64)
310 {
311 assert(mask & 1);
312 if (opcode_bits == 0 || (mask & ((1L << opcode_bits)-1)) != ((1L << opcode_bits)-1))
313 {
314 unsigned x = 0;
315 while ((mask & ((1L << (x+1))-1)) == ((1L << (x+1))-1) &&
316 (opcode_bits == 0 || x <= opcode_bits))
317 x++;
318 opcode_bits = x;
319
320 decltype(opcode_map) new_map;
321 for (auto it = opcode_map.begin(); it != opcode_map.end(); ++it)
322 new_map.insert(std::make_pair(it->second.match & ((1L<<x)-1), it->second));
323 opcode_map = new_map;
324 }
325
326 opcode_map.insert(std::make_pair(match & ((1L<<opcode_bits)-1),
327 (opcode_map_entry_t){match, mask, rv32, rv64}));
328 }