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