1 // See LICENSE for license details.
2 
3 #include "csrs.h"
4 // For processor_t:
5 #include "processor.h"
6 #include "mmu.h"
7 // For get_field():
8 #include "decode.h"
9 // For trap_virtual_instruction and trap_illegal_instruction:
10 #include "trap.h"
11 
12 // STATE macro used by require_privilege() macro:
13 #undef STATE
14 #define STATE (*state)
15 
16 
17 // implement class csr_t
csr_t(processor_t * const proc,const reg_t addr)18 csr_t::csr_t(processor_t* const proc, const reg_t addr):
19   proc(proc),
20   state(proc->get_state()),
21   address(addr),
22   csr_priv(get_field(addr, 0x300)),
23   csr_read_only(get_field(addr, 0xC00) == 3) {
24 }
25 
verify_permissions(insn_t insn,bool write) const26 void csr_t::verify_permissions(insn_t insn, bool write) const {
27   // Check permissions. Raise virtual-instruction exception if V=1,
28   // privileges are insufficient, and the CSR belongs to supervisor or
29   // hypervisor. Raise illegal-instruction exception otherwise.
30   unsigned priv = state->prv == PRV_S && !state->v ? PRV_HS : state->prv;
31 
32   if ((csr_priv == PRV_S && !proc->extension_enabled('S')) ||
33       (csr_priv == PRV_HS && !proc->extension_enabled('H')))
34     throw trap_illegal_instruction(insn.bits());
35 
36   if (write && csr_read_only)
37     throw trap_illegal_instruction(insn.bits());
38   if (priv < csr_priv) {
39     if (state->v && csr_priv <= PRV_HS)
40       throw trap_virtual_instruction(insn.bits());
41     throw trap_illegal_instruction(insn.bits());
42   }
43 }
44 
45 
~csr_t()46 csr_t::~csr_t() {
47 }
48 
write(const reg_t val)49 void csr_t::write(const reg_t val) noexcept {
50   const bool success = unlogged_write(val);
51   if (success) {
52     log_write();
53   }
54 }
55 
log_write() const56 void csr_t::log_write() const noexcept {
57   log_special_write(address, written_value());
58 }
59 
log_special_write(const reg_t address,const reg_t val) const60 void csr_t::log_special_write(const reg_t address, const reg_t val) const noexcept {
61 #if defined(RISCV_ENABLE_COMMITLOG)
62   proc->get_state()->log_reg_write[((address) << 4) | 4] = {val, 0};
63 #endif
64 }
65 
written_value() const66 reg_t csr_t::written_value() const noexcept {
67   return read();
68 }
69 
70 // implement class basic_csr_t
basic_csr_t(processor_t * const proc,const reg_t addr,const reg_t init)71 basic_csr_t::basic_csr_t(processor_t* const proc, const reg_t addr, const reg_t init):
72   csr_t(proc, addr),
73   val(init) {
74 }
75 
read() const76 reg_t basic_csr_t::read() const noexcept {
77   return val;
78 }
79 
unlogged_write(const reg_t val)80 bool basic_csr_t::unlogged_write(const reg_t val) noexcept {
81   this->val = val;
82   return true;
83 }
84 
85 
86 // implement class pmpaddr_csr_t
pmpaddr_csr_t(processor_t * const proc,const reg_t addr)87 pmpaddr_csr_t::pmpaddr_csr_t(processor_t* const proc, const reg_t addr):
88   csr_t(proc, addr),
89   val(0),
90   cfg(0),
91   pmpidx(address - CSR_PMPADDR0) {
92 }
93 
94 
verify_permissions(insn_t insn,bool write) const95 void pmpaddr_csr_t::verify_permissions(insn_t insn, bool write) const {
96   csr_t::verify_permissions(insn, write);
97   // If n_pmp is zero, that means pmp is not implemented hence raise
98   // trap if it tries to access the csr. I would prefer to implement
99   // this by not instantiating any pmpaddr_csr_t for these regs, but
100   // n_pmp can change after reset() is run.
101   if (proc->n_pmp == 0)
102     throw trap_illegal_instruction(insn.bits());
103 }
104 
105 
read() const106 reg_t pmpaddr_csr_t::read() const noexcept {
107   if ((cfg & PMP_A) >= PMP_NAPOT)
108     return val | (~proc->pmp_tor_mask() >> 1);
109   return val & proc->pmp_tor_mask();
110 }
111 
112 
unlogged_write(const reg_t val)113 bool pmpaddr_csr_t::unlogged_write(const reg_t val) noexcept {
114   // If no PMPs are configured, disallow access to all. Otherwise,
115   // allow access to all, but unimplemented ones are hardwired to
116   // zero. Note that n_pmp can change after reset(); otherwise I would
117   // implement this in state_t::reset() by instantiating the correct
118   // number of pmpaddr_csr_t.
119   if (proc->n_pmp == 0)
120     return false;
121 
122   bool locked = cfg & PMP_L;
123   if (pmpidx < proc->n_pmp && !locked && !next_locked_and_tor()) {
124     this->val = val & ((reg_t(1) << (MAX_PADDR_BITS - PMP_SHIFT)) - 1);
125   }
126   else
127     return false;
128   proc->get_mmu()->flush_tlb();
129   return true;
130 }
131 
next_locked_and_tor() const132 bool pmpaddr_csr_t::next_locked_and_tor() const noexcept {
133   if (pmpidx+1 >= state->max_pmp) return false;  // this is the last entry
134   bool next_locked = state->pmpaddr[pmpidx+1]->cfg & PMP_L;
135   bool next_tor = (state->pmpaddr[pmpidx+1]->cfg & PMP_A) == PMP_TOR;
136   return next_locked && next_tor;
137 }
138 
139 
tor_paddr() const140 reg_t pmpaddr_csr_t::tor_paddr() const noexcept {
141   return (val & proc->pmp_tor_mask()) << PMP_SHIFT;
142 }
143 
144 
tor_base_paddr() const145 reg_t pmpaddr_csr_t::tor_base_paddr() const noexcept {
146   if (pmpidx == 0) return 0;  // entry 0 always uses 0 as base
147   return state->pmpaddr[pmpidx-1]->tor_paddr();
148 }
149 
150 
napot_mask() const151 reg_t pmpaddr_csr_t::napot_mask() const noexcept {
152   bool is_na4 = (cfg & PMP_A) == PMP_NA4;
153   reg_t mask = (val << 1) | (!is_na4) | ~proc->pmp_tor_mask();
154   return ~(mask & ~(mask + 1)) << PMP_SHIFT;
155 }
156 
157 
match4(reg_t addr) const158 bool pmpaddr_csr_t::match4(reg_t addr) const noexcept {
159   if ((cfg & PMP_A) == 0) return false;
160   bool is_tor = (cfg & PMP_A) == PMP_TOR;
161   if (is_tor) return tor_base_paddr() <= addr && addr < tor_paddr();
162   // NAPOT or NA4:
163   return ((addr ^ tor_paddr()) & napot_mask()) == 0;
164 }
165 
166 
subset_match(reg_t addr,reg_t len) const167 bool pmpaddr_csr_t::subset_match(reg_t addr, reg_t len) const noexcept {
168   if ((addr | len) & (len - 1))
169     abort();
170   reg_t base = tor_base_paddr();
171   reg_t tor = tor_paddr();
172 
173   if ((cfg & PMP_A) == 0) return false;
174 
175   bool is_tor = (cfg & PMP_A) == PMP_TOR;
176   bool begins_after_lower = addr >= base;
177   bool begins_after_upper = addr >= tor;
178   bool ends_before_lower = (addr & -len) < (base & -len);
179   bool ends_before_upper = (addr & -len) < (tor & -len);
180   bool tor_homogeneous = ends_before_lower || begins_after_upper ||
181     (begins_after_lower && ends_before_upper);
182 
183   bool mask_homogeneous = ~(napot_mask() << 1) & len;
184   bool napot_homogeneous = mask_homogeneous || ((addr ^ tor) / len) != 0;
185 
186   return !(is_tor ? tor_homogeneous : napot_homogeneous);
187 }
188 
189 
access_ok(access_type type,reg_t mode) const190 bool pmpaddr_csr_t::access_ok(access_type type, reg_t mode) const noexcept {
191   return
192     (mode == PRV_M && !(cfg & PMP_L)) ||
193     (type == LOAD && (cfg & PMP_R)) ||
194     (type == STORE && (cfg & PMP_W)) ||
195     (type == FETCH && (cfg & PMP_X));
196 }
197 
198 
199 // implement class pmpcfg_csr_t
pmpcfg_csr_t(processor_t * const proc,const reg_t addr)200 pmpcfg_csr_t::pmpcfg_csr_t(processor_t* const proc, const reg_t addr):
201   csr_t(proc, addr) {
202 }
203 
read() const204 reg_t pmpcfg_csr_t::read() const noexcept {
205   reg_t cfg_res = 0;
206   for (size_t i0 = (address - CSR_PMPCFG0) * 4, i = i0; i < i0 + proc->get_xlen() / 8 && i < state->max_pmp; i++)
207     cfg_res |= reg_t(state->pmpaddr[i]->cfg) << (8 * (i - i0));
208   return cfg_res;
209 }
210 
unlogged_write(const reg_t val)211 bool pmpcfg_csr_t::unlogged_write(const reg_t val) noexcept {
212   if (proc->n_pmp == 0)
213     return false;
214 
215   bool write_success = false;
216   for (size_t i0 = (address - CSR_PMPCFG0) * 4, i = i0; i < i0 + proc->get_xlen() / 8; i++) {
217     if (i < proc->n_pmp) {
218       if (!(state->pmpaddr[i]->cfg & PMP_L)) {
219         uint8_t cfg = (val >> (8 * (i - i0))) & (PMP_R | PMP_W | PMP_X | PMP_A | PMP_L);
220         cfg &= ~PMP_W | ((cfg & PMP_R) ? PMP_W : 0); // Disallow R=0 W=1
221         if (proc->lg_pmp_granularity != PMP_SHIFT && (cfg & PMP_A) == PMP_NA4)
222           cfg |= PMP_NAPOT; // Disallow A=NA4 when granularity > 4
223         state->pmpaddr[i]->cfg = cfg;
224       }
225       write_success = true;
226     }
227   }
228   proc->get_mmu()->flush_tlb();
229   return write_success;
230 }
231 
232 
233 // implement class virtualized_csr_t
virtualized_csr_t(processor_t * const proc,csr_t_p orig,csr_t_p virt)234 virtualized_csr_t::virtualized_csr_t(processor_t* const proc, csr_t_p orig, csr_t_p virt):
235   csr_t(proc, orig->address),
236   orig_csr(orig),
237   virt_csr(virt) {
238 }
239 
240 
read() const241 reg_t virtualized_csr_t::read() const noexcept {
242   return readvirt(state->v);
243 }
244 
readvirt(bool virt) const245 reg_t virtualized_csr_t::readvirt(bool virt) const noexcept {
246   return virt ? virt_csr->read() : orig_csr->read();
247 }
248 
unlogged_write(const reg_t val)249 bool virtualized_csr_t::unlogged_write(const reg_t val) noexcept {
250   if (state->v)
251     virt_csr->write(val);
252   else
253     orig_csr->write(val);
254   return false; // virt_csr or orig_csr has already logged
255 }
256 
257 
258 // implement class epc_csr_t
epc_csr_t(processor_t * const proc,const reg_t addr)259 epc_csr_t::epc_csr_t(processor_t* const proc, const reg_t addr):
260   csr_t(proc, addr),
261   val(0) {
262 }
263 
264 
read() const265 reg_t epc_csr_t::read() const noexcept {
266   return val & proc->pc_alignment_mask();
267 }
268 
269 
unlogged_write(const reg_t val)270 bool epc_csr_t::unlogged_write(const reg_t val) noexcept {
271   this->val = val & ~(reg_t)1;
272   return true;
273 }
274 
275 
276 // implement class tvec_csr_t
tvec_csr_t(processor_t * const proc,const reg_t addr)277 tvec_csr_t::tvec_csr_t(processor_t* const proc, const reg_t addr):
278   csr_t(proc, addr),
279   val(0) {
280 }
281 
282 
read() const283 reg_t tvec_csr_t::read() const noexcept {
284   return val;
285 }
286 
287 
unlogged_write(const reg_t val)288 bool tvec_csr_t::unlogged_write(const reg_t val) noexcept {
289   this->val = val & ~(reg_t)2;
290   return true;
291 }
292 
293 
294 // implement class cause_csr_t
cause_csr_t(processor_t * const proc,const reg_t addr)295 cause_csr_t::cause_csr_t(processor_t* const proc, const reg_t addr):
296   basic_csr_t(proc, addr, 0) {
297 }
298 
299 
read() const300 reg_t cause_csr_t::read() const noexcept {
301   reg_t val = basic_csr_t::read();
302   // When reading, the interrupt bit needs to adjust to xlen. Spike does
303   // not generally support dynamic xlen, but this code was (partly)
304   // there since at least 2015 (ea58df8 and c4350ef).
305   if (proc->get_max_xlen() > proc->get_xlen()) // Move interrupt bit to top of xlen
306     return val | ((val >> (proc->get_max_xlen()-1)) << (proc->get_xlen()-1));
307   return val;
308 }
309 
310 
311 // implement class base_status_csr_t
base_status_csr_t(processor_t * const proc,const reg_t addr)312 base_status_csr_t::base_status_csr_t(processor_t* const proc, const reg_t addr):
313   csr_t(proc, addr),
314   has_page(proc->extension_enabled_const('S') && proc->supports_impl(IMPL_MMU)),
315   sstatus_write_mask(compute_sstatus_write_mask()),
316   sstatus_read_mask(sstatus_write_mask | SSTATUS_UBE | SSTATUS_UXL
317                     | (proc->get_const_xlen() == 32 ? SSTATUS32_SD : SSTATUS64_SD)) {
318 }
319 
320 
enabled(const reg_t which)321 bool base_status_csr_t::enabled(const reg_t which) {
322   // If the field doesn't exist, it is always enabled. See #823.
323   if ((sstatus_write_mask & which) == 0) return true;
324   return (read() & which) != 0;
325 }
326 
compute_sstatus_write_mask() const327 reg_t base_status_csr_t::compute_sstatus_write_mask() const noexcept {
328   // If a configuration has FS bits, they will always be accessible no
329   // matter the state of misa.
330   const bool has_fs = proc->extension_enabled('S') || proc->extension_enabled('F')
331               || proc->extension_enabled_const('V');
332   const bool has_vs = proc->extension_enabled_const('V');
333   return 0
334     | (proc->extension_enabled('S') ? (SSTATUS_SIE | SSTATUS_SPIE | SSTATUS_SPP) : 0)
335     | (has_page ? (SSTATUS_SUM | SSTATUS_MXR) : 0)
336     | (has_fs ? SSTATUS_FS : 0)
337     | (proc->any_custom_extensions() ? SSTATUS_XS : 0)
338     | (has_vs ? SSTATUS_VS : 0)
339     ;
340 }
341 
342 
adjust_sd(const reg_t val) const343 reg_t base_status_csr_t::adjust_sd(const reg_t val) const noexcept {
344   // This uses get_const_xlen() instead of get_xlen() not only because
345   // the variable is static, so it's only called once, but also
346   // because the SD bit moves when XLEN changes, which means we would
347   // need to call adjust_sd() on every read, instead of on every
348   // write.
349   static const reg_t sd_bit = proc->get_const_xlen() == 64 ? SSTATUS64_SD : SSTATUS32_SD;
350   if (((val & SSTATUS_FS) == SSTATUS_FS) ||
351       ((val & SSTATUS_VS) == SSTATUS_VS) ||
352       ((val & SSTATUS_XS) == SSTATUS_XS)) {
353     return val | sd_bit;
354   }
355   return val & ~sd_bit;
356 }
357 
358 
maybe_flush_tlb(const reg_t newval)359 void base_status_csr_t::maybe_flush_tlb(const reg_t newval) noexcept {
360   if ((newval ^ read()) &
361       (MSTATUS_MPP | MSTATUS_MPRV
362        | (has_page ? (MSTATUS_MXR | MSTATUS_SUM) : 0)
363       ))
364     proc->get_mmu()->flush_tlb();
365 }
366 
367 
368 namespace {
xlen_to_uxl(int xlen)369   int xlen_to_uxl(int xlen) {
370     if (xlen == 32)
371       return 1;
372     if (xlen == 64)
373       return 2;
374     abort();
375   }
376 }
377 
378 
379 // implement class vsstatus_csr_t
vsstatus_csr_t(processor_t * const proc,const reg_t addr)380 vsstatus_csr_t::vsstatus_csr_t(processor_t* const proc, const reg_t addr):
381   base_status_csr_t(proc, addr),
382   val(proc->get_state()->mstatus->read() & sstatus_read_mask) {
383 }
384 
read() const385 reg_t vsstatus_csr_t::read() const noexcept {
386   return val;
387 }
388 
unlogged_write(const reg_t val)389 bool vsstatus_csr_t::unlogged_write(const reg_t val) noexcept {
390   const reg_t newval = (this->val & ~sstatus_write_mask) | (val & sstatus_write_mask);
391   if (state->v) maybe_flush_tlb(newval);
392   this->val = adjust_sd(newval);
393   return true;
394 }
395 
396 
397 // implement class sstatus_proxy_csr_t
sstatus_proxy_csr_t(processor_t * const proc,const reg_t addr,csr_t_p mstatus)398 sstatus_proxy_csr_t::sstatus_proxy_csr_t(processor_t* const proc, const reg_t addr, csr_t_p mstatus):
399   base_status_csr_t(proc, addr),
400   mstatus(mstatus) {
401 }
402 
read() const403 reg_t sstatus_proxy_csr_t::read() const noexcept {
404   return mstatus->read() & sstatus_read_mask;
405 }
406 
unlogged_write(const reg_t val)407 bool sstatus_proxy_csr_t::unlogged_write(const reg_t val) noexcept {
408   const reg_t new_mstatus = (mstatus->read() & ~sstatus_write_mask) | (val & sstatus_write_mask);
409 
410   mstatus->write(new_mstatus);
411   return false; // avoid double logging: already logged by mstatus->write()
412 }
413 
414 
415 // implement class mstatus_csr_t
mstatus_csr_t(processor_t * const proc,const reg_t addr)416 mstatus_csr_t::mstatus_csr_t(processor_t* const proc, const reg_t addr):
417   base_status_csr_t(proc, addr),
418   val(0
419       | (proc->extension_enabled_const('U') ? set_field((reg_t)0, MSTATUS_UXL, xlen_to_uxl(proc->get_const_xlen())) : 0)
420       | (proc->extension_enabled_const('S') ? set_field((reg_t)0, MSTATUS_SXL, xlen_to_uxl(proc->get_const_xlen())) : 0)
421 #ifdef RISCV_ENABLE_DUAL_ENDIAN
422       | (proc->get_mmu()->is_target_big_endian() ? MSTATUS_UBE | MSTATUS_SBE | MSTATUS_MBE : 0)
423 #endif
424       | 0  // initial value for mstatus
425   ) {
426 }
427 
428 
read() const429 reg_t mstatus_csr_t::read() const noexcept {
430   return val;
431 }
432 
433 
unlogged_write(const reg_t val)434 bool mstatus_csr_t::unlogged_write(const reg_t val) noexcept {
435   const bool has_mpv = proc->extension_enabled('S') && proc->extension_enabled('H');
436   const bool has_gva = has_mpv;
437 
438   const reg_t mask = sstatus_write_mask
439                    | MSTATUS_MIE | MSTATUS_MPIE | MSTATUS_MPRV
440                    | MSTATUS_MPP | MSTATUS_TW | MSTATUS_TSR
441                    | (has_page ? MSTATUS_TVM : 0)
442                    | (has_gva ? MSTATUS_GVA : 0)
443                    | (has_mpv ? MSTATUS_MPV : 0);
444 
445   const reg_t requested_mpp = proc->legalize_privilege(get_field(val, MSTATUS_MPP));
446   const reg_t adjusted_val = set_field(val, MSTATUS_MPP, requested_mpp);
447   const reg_t new_mstatus = (read() & ~mask) | (adjusted_val & mask);
448   maybe_flush_tlb(new_mstatus);
449   this->val = adjust_sd(new_mstatus);
450   return true;
451 }
452 
453 // implement class mstatush_csr_t
mstatush_csr_t(processor_t * const proc,const reg_t addr,mstatus_csr_t_p mstatus)454 mstatush_csr_t::mstatush_csr_t(processor_t* const proc, const reg_t addr, mstatus_csr_t_p mstatus):
455   csr_t(proc, addr),
456   mstatus(mstatus),
457   mask(MSTATUSH_MPV | MSTATUSH_GVA | MSTATUSH_SBE | MSTATUSH_MBE) {
458 }
459 
read() const460 reg_t mstatush_csr_t::read() const noexcept {
461   return (mstatus->read() >> 32) & mask;
462 }
463 
unlogged_write(const reg_t val)464 bool mstatush_csr_t::unlogged_write(const reg_t val) noexcept {
465   return mstatus->unlogged_write((mstatus->written_value() & ~(mask << 32)) | ((val & mask) << 32));
466 }
467 
468 // implement class sstatus_csr_t
sstatus_csr_t(processor_t * const proc,base_status_csr_t_p orig,base_status_csr_t_p virt)469 sstatus_csr_t::sstatus_csr_t(processor_t* const proc, base_status_csr_t_p orig, base_status_csr_t_p virt):
470   virtualized_csr_t(proc, orig, virt),
471   orig_sstatus(orig),
472   virt_sstatus(virt) {
473 }
474 
dirty(const reg_t dirties)475 void sstatus_csr_t::dirty(const reg_t dirties) {
476   // Catch problems like #823 where P-extension instructions were not
477   // checking for mstatus.VS!=Off:
478   if (!enabled(dirties)) abort();
479 
480   orig_csr->write(orig_csr->read() | dirties);
481   if (state->v) {
482     virt_csr->write(virt_csr->read() | dirties);
483   }
484 }
485 
enabled(const reg_t which)486 bool sstatus_csr_t::enabled(const reg_t which) {
487   if (!orig_sstatus->enabled(which))
488     return false;
489   if (state->v && !virt_sstatus->enabled(which))
490     return false;
491   return true;
492 }
493 
494 
495 // implement class misa_csr_t
misa_csr_t(processor_t * const proc,const reg_t addr,const reg_t max_isa)496 misa_csr_t::misa_csr_t(processor_t* const proc, const reg_t addr, const reg_t max_isa):
497   basic_csr_t(proc, addr, max_isa),
498   max_isa(max_isa),
499   write_mask(max_isa & (0  // allow MAFDCH bits in MISA to be modified
500                         | (1L << ('M' - 'A'))
501                         | (1L << ('A' - 'A'))
502                         | (1L << ('F' - 'A'))
503                         | (1L << ('D' - 'A'))
504                         | (1L << ('C' - 'A'))
505                         | (1L << ('H' - 'A'))
506                         )
507              ) {
508 }
509 
unlogged_write(const reg_t val)510 bool misa_csr_t::unlogged_write(const reg_t val) noexcept {
511   // the write is ignored if increasing IALIGN would misalign the PC
512   if (!(val & (1L << ('C' - 'A'))) && (state->pc & 2))
513     return false;
514 
515   const bool val_supports_f = val & (1L << ('F' - 'A'));
516   const reg_t val_without_d = val & ~(1L << ('D' - 'A'));
517   const reg_t adjusted_val = val_supports_f ? val : val_without_d;
518 
519   const reg_t old_misa = read();
520   const bool prev_h = old_misa & (1L << ('H' - 'A'));
521   const reg_t new_misa = (adjusted_val & write_mask) | (old_misa & ~write_mask);
522   const bool new_h = new_misa & (1L << ('H' - 'A'));
523 
524   // update the hypervisor-only bits in MEDELEG and other CSRs
525   if (!new_h && prev_h) {
526     reg_t hypervisor_exceptions = 0
527       | (1 << CAUSE_VIRTUAL_SUPERVISOR_ECALL)
528       | (1 << CAUSE_FETCH_GUEST_PAGE_FAULT)
529       | (1 << CAUSE_LOAD_GUEST_PAGE_FAULT)
530       | (1 << CAUSE_VIRTUAL_INSTRUCTION)
531       | (1 << CAUSE_STORE_GUEST_PAGE_FAULT)
532       ;
533     state->medeleg->write(state->medeleg->read() & ~hypervisor_exceptions);
534     state->mstatus->write(state->mstatus->read() & ~(MSTATUS_GVA | MSTATUS_MPV));
535     state->mie->write_with_mask(MIP_HS_MASK, 0);  // also takes care of hie, sie
536     state->mip->write_with_mask(MIP_HS_MASK, 0);  // also takes care of hip, sip, hvip
537     state->hstatus->write(0);
538   }
539 
540   return basic_csr_t::unlogged_write(new_misa);
541 }
542 
extension_enabled(unsigned char ext) const543 bool misa_csr_t::extension_enabled(unsigned char ext) const noexcept {
544   assert(ext >= 'A' && ext <= 'Z');
545   return (read() >> (ext - 'A')) & 1;
546 }
547 
extension_enabled_const(unsigned char ext) const548 bool misa_csr_t::extension_enabled_const(unsigned char ext) const noexcept {
549   assert(!(1 & (write_mask >> (ext - 'A'))));
550   return extension_enabled(ext);
551 }
552 
553 
554 // implement class mip_or_mie_csr_t
mip_or_mie_csr_t(processor_t * const proc,const reg_t addr)555 mip_or_mie_csr_t::mip_or_mie_csr_t(processor_t* const proc, const reg_t addr):
556   csr_t(proc, addr),
557   val(0) {
558 }
559 
read() const560 reg_t mip_or_mie_csr_t::read() const noexcept {
561   return val;
562 }
563 
write_with_mask(const reg_t mask,const reg_t val)564 void mip_or_mie_csr_t::write_with_mask(const reg_t mask, const reg_t val) noexcept {
565   this->val = (this->val & ~mask) | (val & mask);
566   log_write();
567 }
568 
unlogged_write(const reg_t val)569 bool mip_or_mie_csr_t::unlogged_write(const reg_t val) noexcept {
570   write_with_mask(write_mask(), val);
571   return false; // avoid double logging: already logged by write_with_mask()
572 }
573 
574 
mip_csr_t(processor_t * const proc,const reg_t addr)575 mip_csr_t::mip_csr_t(processor_t* const proc, const reg_t addr):
576   mip_or_mie_csr_t(proc, addr) {
577 }
578 
backdoor_write_with_mask(const reg_t mask,const reg_t val)579 void mip_csr_t::backdoor_write_with_mask(const reg_t mask, const reg_t val) noexcept {
580   this->val = (this->val & ~mask) | (val & mask);
581 }
582 
write_mask() const583 reg_t mip_csr_t::write_mask() const noexcept {
584   const reg_t supervisor_ints = proc->extension_enabled('S') ? MIP_SSIP | MIP_STIP | MIP_SEIP : 0;
585   const reg_t vssip_int = proc->extension_enabled('H') ? MIP_VSSIP : 0;
586   const reg_t hypervisor_ints = proc->extension_enabled('H') ? MIP_HS_MASK : 0;
587   // We must mask off sgeip, vstip, and vseip. All three of these
588   // bits are aliases for the same bits in hip. The hip spec says:
589   //  * sgeip is read-only -- write hgeip instead
590   //  * vseip is read-only -- write hvip instead
591   //  * vstip is read-only -- write hvip instead
592   return (supervisor_ints | hypervisor_ints) &
593          (MIP_SEIP | MIP_SSIP | MIP_STIP | vssip_int);
594 }
595 
596 
mie_csr_t(processor_t * const proc,const reg_t addr)597 mie_csr_t::mie_csr_t(processor_t* const proc, const reg_t addr):
598   mip_or_mie_csr_t(proc, addr) {
599 }
600 
601 
write_mask() const602 reg_t mie_csr_t::write_mask() const noexcept {
603   const reg_t supervisor_ints = proc->extension_enabled('S') ? MIP_SSIP | MIP_STIP | MIP_SEIP : 0;
604   const reg_t hypervisor_ints = proc->extension_enabled('H') ? MIP_HS_MASK : 0;
605   const reg_t coprocessor_ints = (reg_t)proc->any_custom_extensions() << IRQ_COP;
606   const reg_t delegable_ints = supervisor_ints | coprocessor_ints;
607   const reg_t all_ints = delegable_ints | hypervisor_ints | MIP_MSIP | MIP_MTIP | MIP_MEIP;
608   return all_ints;
609 }
610 
611 
612 // implement class generic_int_accessor_t
generic_int_accessor_t(state_t * const state,const reg_t read_mask,const reg_t ip_write_mask,const reg_t ie_write_mask,const bool mask_mideleg,const bool mask_hideleg,const int shiftamt)613 generic_int_accessor_t::generic_int_accessor_t(state_t* const state,
614                                                const reg_t read_mask,
615                                                const reg_t ip_write_mask,
616                                                const reg_t ie_write_mask,
617                                                const bool mask_mideleg,
618                                                const bool mask_hideleg,
619                                                const int shiftamt):
620   state(state),
621   read_mask(read_mask),
622   ip_write_mask(ip_write_mask),
623   ie_write_mask(ie_write_mask),
624   mask_mideleg(mask_mideleg),
625   mask_hideleg(mask_hideleg),
626   shiftamt(shiftamt) {
627 }
628 
ip_read() const629 reg_t generic_int_accessor_t::ip_read() const noexcept {
630   return (state->mip->read() & deleg_mask() & read_mask) >> shiftamt;
631 }
632 
ip_write(const reg_t val)633 void generic_int_accessor_t::ip_write(const reg_t val) noexcept {
634   const reg_t mask = deleg_mask() & ip_write_mask;
635   state->mip->write_with_mask(mask, val << shiftamt);
636 }
637 
ie_read() const638 reg_t generic_int_accessor_t::ie_read() const noexcept {
639   return (state->mie->read() & deleg_mask() & read_mask) >> shiftamt;
640 }
641 
ie_write(const reg_t val)642 void generic_int_accessor_t::ie_write(const reg_t val) noexcept {
643   const reg_t mask = deleg_mask() & ie_write_mask;
644   state->mie->write_with_mask(mask, val << shiftamt);
645 }
646 
deleg_mask() const647 reg_t generic_int_accessor_t::deleg_mask() const {
648   const reg_t hideleg_mask = mask_hideleg ? state->hideleg->read() : (reg_t)~0;
649   const reg_t mideleg_mask = mask_mideleg ? state->mideleg->read() : (reg_t)~0;
650   return hideleg_mask & mideleg_mask;
651 }
652 
653 
654 // implement class mip_proxy_csr_t
mip_proxy_csr_t(processor_t * const proc,const reg_t addr,generic_int_accessor_t_p accr)655 mip_proxy_csr_t::mip_proxy_csr_t(processor_t* const proc, const reg_t addr, generic_int_accessor_t_p accr):
656   csr_t(proc, addr),
657   accr(accr) {
658 }
659 
read() const660 reg_t mip_proxy_csr_t::read() const noexcept {
661   return accr->ip_read();
662 }
663 
unlogged_write(const reg_t val)664 bool mip_proxy_csr_t::unlogged_write(const reg_t val) noexcept {
665   accr->ip_write(val);
666   return false;  // accr has already logged
667 }
668 
669 // implement class mie_proxy_csr_t
mie_proxy_csr_t(processor_t * const proc,const reg_t addr,generic_int_accessor_t_p accr)670 mie_proxy_csr_t::mie_proxy_csr_t(processor_t* const proc, const reg_t addr, generic_int_accessor_t_p accr):
671   csr_t(proc, addr),
672   accr(accr) {
673 }
674 
read() const675 reg_t mie_proxy_csr_t::read() const noexcept {
676   return accr->ie_read();
677 }
678 
unlogged_write(const reg_t val)679 bool mie_proxy_csr_t::unlogged_write(const reg_t val) noexcept {
680   accr->ie_write(val);
681   return false;  // accr has already logged
682 }
683 
684 
685 // implement class mideleg_csr_t
mideleg_csr_t(processor_t * const proc,const reg_t addr)686 mideleg_csr_t::mideleg_csr_t(processor_t* const proc, const reg_t addr):
687   basic_csr_t(proc, addr, 0) {
688 }
689 
read() const690 reg_t mideleg_csr_t::read() const noexcept {
691   reg_t val = basic_csr_t::read();
692   if (proc->extension_enabled('H')) return val | MIDELEG_FORCED_MASK;
693   // No need to clear MIDELEG_FORCED_MASK because those bits can never
694   // get set in val.
695   return val;
696 }
697 
verify_permissions(insn_t insn,bool write) const698 void mideleg_csr_t::verify_permissions(insn_t insn, bool write) const {
699   basic_csr_t::verify_permissions(insn, write);
700   if (!proc->extension_enabled('S'))
701     throw trap_illegal_instruction(insn.bits());
702 }
703 
unlogged_write(const reg_t val)704 bool mideleg_csr_t::unlogged_write(const reg_t val) noexcept {
705   const reg_t supervisor_ints = proc->extension_enabled('S') ? MIP_SSIP | MIP_STIP | MIP_SEIP : 0;
706   const reg_t coprocessor_ints = (reg_t)proc->any_custom_extensions() << IRQ_COP;
707   const reg_t delegable_ints = supervisor_ints | coprocessor_ints;
708 
709   return basic_csr_t::unlogged_write(val & delegable_ints);
710 }
711 
712 
713 // implement class medeleg_csr_t
medeleg_csr_t(processor_t * const proc,const reg_t addr)714 medeleg_csr_t::medeleg_csr_t(processor_t* const proc, const reg_t addr):
715   basic_csr_t(proc, addr, 0),
716   hypervisor_exceptions(0
717                         | (1 << CAUSE_VIRTUAL_SUPERVISOR_ECALL)
718                         | (1 << CAUSE_FETCH_GUEST_PAGE_FAULT)
719                         | (1 << CAUSE_LOAD_GUEST_PAGE_FAULT)
720                         | (1 << CAUSE_VIRTUAL_INSTRUCTION)
721                         | (1 << CAUSE_STORE_GUEST_PAGE_FAULT)
722                         ) {
723 }
724 
verify_permissions(insn_t insn,bool write) const725 void medeleg_csr_t::verify_permissions(insn_t insn, bool write) const {
726   basic_csr_t::verify_permissions(insn, write);
727   if (!proc->extension_enabled('S'))
728     throw trap_illegal_instruction(insn.bits());
729 }
730 
unlogged_write(const reg_t val)731 bool medeleg_csr_t::unlogged_write(const reg_t val) noexcept {
732   const reg_t mask = 0
733     | (1 << CAUSE_MISALIGNED_FETCH)
734     | (1 << CAUSE_BREAKPOINT)
735     | (1 << CAUSE_USER_ECALL)
736     | (1 << CAUSE_SUPERVISOR_ECALL)
737     | (1 << CAUSE_FETCH_PAGE_FAULT)
738     | (1 << CAUSE_LOAD_PAGE_FAULT)
739     | (1 << CAUSE_STORE_PAGE_FAULT)
740     | (proc->extension_enabled('H') ? hypervisor_exceptions : 0)
741     ;
742   return basic_csr_t::unlogged_write((read() & ~mask) | (val & mask));
743 }
744 
745 
746 // implement class masked_csr_t
masked_csr_t(processor_t * const proc,const reg_t addr,const reg_t mask,const reg_t init)747 masked_csr_t::masked_csr_t(processor_t* const proc, const reg_t addr, const reg_t mask, const reg_t init):
748   basic_csr_t(proc, addr, init),
749   mask(mask) {
750 }
751 
unlogged_write(const reg_t val)752 bool masked_csr_t::unlogged_write(const reg_t val) noexcept {
753   return basic_csr_t::unlogged_write((read() & ~mask) | (val & mask));
754 }
755 
756 
757 // implement class base_atp_csr_t and family
base_atp_csr_t(processor_t * const proc,const reg_t addr)758 base_atp_csr_t::base_atp_csr_t(processor_t* const proc, const reg_t addr):
759   basic_csr_t(proc, addr, 0) {
760 }
761 
762 
unlogged_write(const reg_t val)763 bool base_atp_csr_t::unlogged_write(const reg_t val) noexcept {
764   const reg_t newval = proc->supports_impl(IMPL_MMU) ? compute_new_satp(val) : 0;
765   if (newval != read())
766     proc->get_mmu()->flush_tlb();
767   return basic_csr_t::unlogged_write(newval);
768 }
769 
satp_valid(reg_t val) const770 bool base_atp_csr_t::satp_valid(reg_t val) const noexcept {
771   if (proc->get_xlen() == 32) {
772     switch (get_field(val, SATP32_MODE)) {
773       case SATP_MODE_SV32: return proc->supports_impl(IMPL_MMU_SV32);
774       case SATP_MODE_OFF: return true;
775       default: return false;
776     }
777   } else {
778     switch (get_field(val, SATP64_MODE)) {
779       case SATP_MODE_SV39: return proc->supports_impl(IMPL_MMU_SV39);
780       case SATP_MODE_SV48: return proc->supports_impl(IMPL_MMU_SV48);
781       case SATP_MODE_OFF: return true;
782       default: return false;
783     }
784   }
785 }
786 
compute_new_satp(reg_t val) const787 reg_t base_atp_csr_t::compute_new_satp(reg_t val) const noexcept {
788   reg_t rv64_ppn_mask = (reg_t(1) << (MAX_PADDR_BITS - PGSHIFT)) - 1;
789 
790   reg_t mode_mask = proc->get_xlen() == 32 ? SATP32_MODE : SATP64_MODE;
791   reg_t ppn_mask = proc->get_xlen() == 32 ? SATP32_PPN : SATP64_PPN & rv64_ppn_mask;
792   reg_t new_mask = (satp_valid(val) ? mode_mask : 0) | ppn_mask;
793   reg_t old_mask = satp_valid(val) ? 0 : mode_mask;
794 
795   return (new_mask & val) | (old_mask & read());
796 }
797 
satp_csr_t(processor_t * const proc,const reg_t addr)798 satp_csr_t::satp_csr_t(processor_t* const proc, const reg_t addr):
799   base_atp_csr_t(proc, addr) {
800 }
801 
verify_permissions(insn_t insn,bool write) const802 void satp_csr_t::verify_permissions(insn_t insn, bool write) const {
803   base_atp_csr_t::verify_permissions(insn, write);
804   if (get_field(state->mstatus->read(), MSTATUS_TVM))
805     require(state->prv >= PRV_M);
806 }
807 
virtualized_satp_csr_t(processor_t * const proc,satp_csr_t_p orig,csr_t_p virt)808 virtualized_satp_csr_t::virtualized_satp_csr_t(processor_t* const proc, satp_csr_t_p orig, csr_t_p virt):
809   virtualized_csr_t(proc, orig, virt),
810   orig_satp(orig) {
811 }
812 
verify_permissions(insn_t insn,bool write) const813 void virtualized_satp_csr_t::verify_permissions(insn_t insn, bool write) const {
814   virtualized_csr_t::verify_permissions(insn, write);
815 
816   // If satp is accessed from VS mode, it's really accessing vsatp,
817   // and the hstatus.VTVM bit controls.
818   if (state->v) {
819     if (get_field(state->hstatus->read(), HSTATUS_VTVM))
820       throw trap_virtual_instruction(insn.bits());
821   }
822   else {
823     orig_csr->verify_permissions(insn, write);
824   }
825 }
826 
unlogged_write(const reg_t val)827 bool virtualized_satp_csr_t::unlogged_write(const reg_t val) noexcept {
828   // If unsupported Mode field: no change to contents
829   const reg_t newval = orig_satp->satp_valid(val) ? val : read();
830   return virtualized_csr_t::unlogged_write(newval);
831 }
832 
833 
834 // implement class minstret_csr_t
minstret_csr_t(processor_t * const proc,const reg_t addr)835 minstret_csr_t::minstret_csr_t(processor_t* const proc, const reg_t addr):
836   csr_t(proc, addr),
837   val(0) {
838 }
839 
read() const840 reg_t minstret_csr_t::read() const noexcept {
841   return val;
842 }
843 
bump(const reg_t howmuch)844 void minstret_csr_t::bump(const reg_t howmuch) noexcept {
845   val += howmuch;  // to keep log reasonable size, don't log every bump
846 }
847 
unlogged_write(const reg_t val)848 bool minstret_csr_t::unlogged_write(const reg_t val) noexcept {
849   if (proc->get_xlen() == 32)
850     this->val = (this->val >> 32 << 32) | (val & 0xffffffffU);
851   else
852     this->val = val;
853   // The ISA mandates that if an instruction writes instret, the write
854   // takes precedence over the increment to instret.  However, Spike
855   // unconditionally increments instret after executing an instruction.
856   // Correct for this artifact by decrementing instret here.
857   this->val--;
858   return true;
859 }
860 
written_value() const861 reg_t minstret_csr_t::written_value() const noexcept {
862   // Re-adjust for upcoming bump()
863   return this->val + 1;
864 }
865 
write_upper_half(const reg_t val)866 void minstret_csr_t::write_upper_half(const reg_t val) noexcept {
867   this->val = (val << 32) | (this->val << 32 >> 32);
868   this->val--; // See comment above.
869   // Log upper half only.
870   log_special_write(address + (CSR_MINSTRETH - CSR_MINSTRET), written_value() >> 32);
871 }
872 
873 
minstreth_csr_t(processor_t * const proc,const reg_t addr,minstret_csr_t_p minstret)874 minstreth_csr_t::minstreth_csr_t(processor_t* const proc, const reg_t addr, minstret_csr_t_p minstret):
875   csr_t(proc, addr),
876   minstret(minstret) {
877 }
878 
read() const879 reg_t minstreth_csr_t::read() const noexcept {
880   return minstret->read() >> 32;
881 }
882 
unlogged_write(const reg_t val)883 bool minstreth_csr_t::unlogged_write(const reg_t val) noexcept {
884   minstret->write_upper_half(val);
885   return true;
886 }
887 
888 
proxy_csr_t(processor_t * const proc,const reg_t addr,csr_t_p delegate)889 proxy_csr_t::proxy_csr_t(processor_t* const proc, const reg_t addr, csr_t_p delegate):
890   csr_t(proc, addr),
891   delegate(delegate) {
892 }
893 
read() const894 reg_t proxy_csr_t::read() const noexcept {
895   return delegate->read();
896 }
897 
unlogged_write(const reg_t val)898 bool proxy_csr_t::unlogged_write(const reg_t val) noexcept {
899   delegate->write(val);  // log only under the original (delegate's) name
900   return false;
901 }
902 
903 
const_csr_t(processor_t * const proc,const reg_t addr,reg_t val)904 const_csr_t::const_csr_t(processor_t* const proc, const reg_t addr, reg_t val):
905   csr_t(proc, addr),
906   val(val) {
907 }
908 
read() const909 reg_t const_csr_t::read() const noexcept {
910   return val;
911 }
912 
unlogged_write(const reg_t val)913 bool const_csr_t::unlogged_write(const reg_t val) noexcept {
914   return false;
915 }
916 
917 
counter_proxy_csr_t(processor_t * const proc,const reg_t addr,csr_t_p delegate)918 counter_proxy_csr_t::counter_proxy_csr_t(processor_t* const proc, const reg_t addr, csr_t_p delegate):
919   proxy_csr_t(proc, addr, delegate) {
920 }
921 
myenable(csr_t_p counteren) const922 bool counter_proxy_csr_t::myenable(csr_t_p counteren) const noexcept {
923   return 1 & (counteren->read() >> (address & 31));
924 }
925 
verify_permissions(insn_t insn,bool write) const926 void counter_proxy_csr_t::verify_permissions(insn_t insn, bool write) const {
927   proxy_csr_t::verify_permissions(insn, write);
928 
929   const bool mctr_ok = (state->prv < PRV_M) ? myenable(state->mcounteren) : true;
930   const bool hctr_ok = state->v ? myenable(state->hcounteren) : true;
931   const bool sctr_ok = (proc->extension_enabled('S') && state->prv < PRV_S) ? myenable(state->scounteren) : true;
932 
933   if (!mctr_ok)
934     throw trap_illegal_instruction(insn.bits());
935   if (!hctr_ok)
936       throw trap_virtual_instruction(insn.bits());
937   if (!sctr_ok) {
938     if (state->v)
939       throw trap_virtual_instruction(insn.bits());
940     else
941       throw trap_illegal_instruction(insn.bits());
942   }
943 }
944 
945 
hypervisor_csr_t(processor_t * const proc,const reg_t addr)946 hypervisor_csr_t::hypervisor_csr_t(processor_t* const proc, const reg_t addr):
947   basic_csr_t(proc, addr, 0) {
948 }
949 
verify_permissions(insn_t insn,bool write) const950 void hypervisor_csr_t::verify_permissions(insn_t insn, bool write) const {
951   basic_csr_t::verify_permissions(insn, write);
952   if (!proc->extension_enabled('H'))
953     throw trap_illegal_instruction(insn.bits());
954 }
955 
956 
hgatp_csr_t(processor_t * const proc,const reg_t addr)957 hgatp_csr_t::hgatp_csr_t(processor_t* const proc, const reg_t addr):
958   basic_csr_t(proc, addr, 0) {
959 }
960 
verify_permissions(insn_t insn,bool write) const961 void hgatp_csr_t::verify_permissions(insn_t insn, bool write) const {
962   basic_csr_t::verify_permissions(insn, write);
963   if (!state->v && get_field(state->mstatus->read(), MSTATUS_TVM))
964      require_privilege(PRV_M);
965 }
966 
unlogged_write(const reg_t val)967 bool hgatp_csr_t::unlogged_write(const reg_t val) noexcept {
968   proc->get_mmu()->flush_tlb();
969 
970   reg_t mask;
971   if (proc->get_const_xlen() == 32) {
972     mask = HGATP32_PPN | HGATP32_MODE;
973   } else {
974     mask = HGATP64_PPN & ((reg_t(1) << (MAX_PADDR_BITS - PGSHIFT)) - 1);
975 
976     if (get_field(val, HGATP64_MODE) == HGATP_MODE_OFF ||
977         get_field(val, HGATP64_MODE) == HGATP_MODE_SV39X4 ||
978         get_field(val, HGATP64_MODE) == HGATP_MODE_SV48X4)
979       mask |= HGATP64_MODE;
980   }
981   mask &= ~(reg_t)3;
982   return basic_csr_t::unlogged_write((read() & ~mask) | (val & mask));
983 }
984 
985 
tselect_csr_t(processor_t * const proc,const reg_t addr)986 tselect_csr_t::tselect_csr_t(processor_t* const proc, const reg_t addr):
987   basic_csr_t(proc, addr, 0) {
988 }
989 
unlogged_write(const reg_t val)990 bool tselect_csr_t::unlogged_write(const reg_t val) noexcept {
991   return basic_csr_t::unlogged_write((val < state->num_triggers) ? val : read());
992 }
993 
994 
tdata1_csr_t(processor_t * const proc,const reg_t addr)995 tdata1_csr_t::tdata1_csr_t(processor_t* const proc, const reg_t addr):
996   csr_t(proc, addr) {
997 }
998 
read() const999 reg_t tdata1_csr_t::read() const noexcept {
1000   reg_t v = 0;
1001   auto xlen = proc->get_xlen();
1002   mcontrol_t *mc = &state->mcontrol[state->tselect->read()];
1003   v = set_field(v, MCONTROL_TYPE(xlen), mc->type);
1004   v = set_field(v, MCONTROL_DMODE(xlen), mc->dmode);
1005   v = set_field(v, MCONTROL_MASKMAX(xlen), mc->maskmax);
1006   v = set_field(v, MCONTROL_SELECT, mc->select);
1007   v = set_field(v, MCONTROL_TIMING, mc->timing);
1008   v = set_field(v, MCONTROL_ACTION, mc->action);
1009   v = set_field(v, MCONTROL_CHAIN, mc->chain);
1010   v = set_field(v, MCONTROL_MATCH, mc->match);
1011   v = set_field(v, MCONTROL_M, mc->m);
1012   v = set_field(v, MCONTROL_H, mc->h);
1013   v = set_field(v, MCONTROL_S, mc->s);
1014   v = set_field(v, MCONTROL_U, mc->u);
1015   v = set_field(v, MCONTROL_EXECUTE, mc->execute);
1016   v = set_field(v, MCONTROL_STORE, mc->store);
1017   v = set_field(v, MCONTROL_LOAD, mc->load);
1018   return v;
1019 }
1020 
unlogged_write(const reg_t val)1021 bool tdata1_csr_t::unlogged_write(const reg_t val) noexcept {
1022   mcontrol_t *mc = &state->mcontrol[state->tselect->read()];
1023   if (mc->dmode && !state->debug_mode) {
1024     return false;
1025   }
1026   auto xlen = proc->get_xlen();
1027   mc->dmode = get_field(val, MCONTROL_DMODE(xlen));
1028   mc->select = get_field(val, MCONTROL_SELECT);
1029   mc->timing = get_field(val, MCONTROL_TIMING);
1030   mc->action = (mcontrol_action_t) get_field(val, MCONTROL_ACTION);
1031   mc->chain = get_field(val, MCONTROL_CHAIN);
1032   mc->match = (mcontrol_match_t) get_field(val, MCONTROL_MATCH);
1033   mc->m = get_field(val, MCONTROL_M);
1034   mc->h = get_field(val, MCONTROL_H);
1035   mc->s = get_field(val, MCONTROL_S);
1036   mc->u = get_field(val, MCONTROL_U);
1037   mc->execute = get_field(val, MCONTROL_EXECUTE);
1038   mc->store = get_field(val, MCONTROL_STORE);
1039   mc->load = get_field(val, MCONTROL_LOAD);
1040   // Assume we're here because of csrw.
1041   if (mc->execute)
1042     mc->timing = 0;
1043   proc->trigger_updated();
1044   return true;
1045 }
1046 
1047 
tdata2_csr_t(processor_t * const proc,const reg_t addr,const size_t count)1048 tdata2_csr_t::tdata2_csr_t(processor_t* const proc, const reg_t addr, const size_t count):
1049   csr_t(proc, addr),
1050   vals(count, 0) {
1051 }
1052 
read() const1053 reg_t tdata2_csr_t::read() const noexcept {
1054   return read(state->tselect->read());
1055 }
1056 
read(const size_t idx) const1057 reg_t tdata2_csr_t::read(const size_t idx) const noexcept {
1058   return vals[idx];
1059 }
1060 
unlogged_write(const reg_t val)1061 bool tdata2_csr_t::unlogged_write(const reg_t val) noexcept {
1062   if (state->mcontrol[state->tselect->read()].dmode && !state->debug_mode) {
1063     return false;
1064   }
1065   vals[state->tselect->read()] = val;
1066   return true;
1067 }
1068 
1069 
debug_mode_csr_t(processor_t * const proc,const reg_t addr)1070 debug_mode_csr_t::debug_mode_csr_t(processor_t* const proc, const reg_t addr):
1071   basic_csr_t(proc, addr, 0) {
1072 }
1073 
verify_permissions(insn_t insn,bool write) const1074 void debug_mode_csr_t::verify_permissions(insn_t insn, bool write) const {
1075   basic_csr_t::verify_permissions(insn, write);
1076   if (!state->debug_mode)
1077     throw trap_illegal_instruction(insn.bits());
1078 }
1079 
dpc_csr_t(processor_t * const proc,const reg_t addr)1080 dpc_csr_t::dpc_csr_t(processor_t* const proc, const reg_t addr):
1081   epc_csr_t(proc, addr) {
1082 }
1083 
verify_permissions(insn_t insn,bool write) const1084 void dpc_csr_t::verify_permissions(insn_t insn, bool write) const {
1085   epc_csr_t::verify_permissions(insn, write);
1086   if (!state->debug_mode)
1087     throw trap_illegal_instruction(insn.bits());
1088 }
1089 
1090 
dcsr_csr_t(processor_t * const proc,const reg_t addr)1091 dcsr_csr_t::dcsr_csr_t(processor_t* const proc, const reg_t addr):
1092   csr_t(proc, addr),
1093   prv(0),
1094   step(false),
1095   ebreakm(false),
1096   ebreakh(false),
1097   ebreaks(false),
1098   ebreaku(false),
1099   halt(false),
1100   cause(0) {
1101 }
1102 
verify_permissions(insn_t insn,bool write) const1103 void dcsr_csr_t::verify_permissions(insn_t insn, bool write) const {
1104   csr_t::verify_permissions(insn, write);
1105   if (!state->debug_mode)
1106     throw trap_illegal_instruction(insn.bits());
1107 }
1108 
read() const1109 reg_t dcsr_csr_t::read() const noexcept {
1110   uint32_t v = 0;
1111   v = set_field(v, DCSR_XDEBUGVER, 1);
1112   v = set_field(v, DCSR_EBREAKM, ebreakm);
1113   v = set_field(v, DCSR_EBREAKH, ebreakh);
1114   v = set_field(v, DCSR_EBREAKS, ebreaks);
1115   v = set_field(v, DCSR_EBREAKU, ebreaku);
1116   v = set_field(v, DCSR_STOPCYCLE, 0);
1117   v = set_field(v, DCSR_STOPTIME, 0);
1118   v = set_field(v, DCSR_CAUSE, cause);
1119   v = set_field(v, DCSR_STEP, step);
1120   v = set_field(v, DCSR_PRV, prv);
1121   return v;
1122 }
1123 
unlogged_write(const reg_t val)1124 bool dcsr_csr_t::unlogged_write(const reg_t val) noexcept {
1125   prv = get_field(val, DCSR_PRV);
1126   step = get_field(val, DCSR_STEP);
1127   // TODO: ndreset and fullreset
1128   ebreakm = get_field(val, DCSR_EBREAKM);
1129   ebreakh = get_field(val, DCSR_EBREAKH);
1130   ebreaks = get_field(val, DCSR_EBREAKS);
1131   ebreaku = get_field(val, DCSR_EBREAKU);
1132   halt = get_field(val, DCSR_HALT);
1133   return true;
1134 }
1135 
write_cause_and_prv(uint8_t cause,reg_t prv)1136 void dcsr_csr_t::write_cause_and_prv(uint8_t cause, reg_t prv) noexcept {
1137   this->cause = cause;
1138   this->prv = prv;
1139   log_write();
1140 }
1141 
1142 
float_csr_t(processor_t * const proc,const reg_t addr,const reg_t mask,const reg_t init)1143 float_csr_t::float_csr_t(processor_t* const proc, const reg_t addr, const reg_t mask, const reg_t init):
1144   masked_csr_t(proc, addr, mask, init) {
1145 }
1146 
verify_permissions(insn_t insn,bool write) const1147 void float_csr_t::verify_permissions(insn_t insn, bool write) const {
1148   masked_csr_t::verify_permissions(insn, write);
1149   require_fp;
1150   if (!proc->extension_enabled('F'))
1151     throw trap_illegal_instruction(insn.bits());
1152 }
1153 
unlogged_write(const reg_t val)1154 bool float_csr_t::unlogged_write(const reg_t val) noexcept {
1155   dirty_fp_state;
1156   return masked_csr_t::unlogged_write(val);
1157 }
1158 
1159 
composite_csr_t(processor_t * const proc,const reg_t addr,csr_t_p upper_csr,csr_t_p lower_csr,const unsigned upper_lsb)1160 composite_csr_t::composite_csr_t(processor_t* const proc, const reg_t addr, csr_t_p upper_csr, csr_t_p lower_csr, const unsigned upper_lsb):
1161   csr_t(proc, addr),
1162   upper_csr(upper_csr),
1163   lower_csr(lower_csr),
1164   upper_lsb(upper_lsb) {
1165 }
1166 
verify_permissions(insn_t insn,bool write) const1167 void composite_csr_t::verify_permissions(insn_t insn, bool write) const {
1168   // It is reasonable to assume that either underlying CSR will have
1169   // the same permissions as this composite.
1170   upper_csr->verify_permissions(insn, write);
1171 }
1172 
read() const1173 reg_t composite_csr_t::read() const noexcept {
1174   return (upper_csr->read() << upper_lsb) | lower_csr->read();
1175 }
1176 
unlogged_write(const reg_t val)1177 bool composite_csr_t::unlogged_write(const reg_t val) noexcept {
1178   upper_csr->write(val >> upper_lsb);
1179   lower_csr->write(val);
1180   return false;  // logging is done only by the underlying CSRs
1181 }
1182 
1183 
sentropy_csr_t(processor_t * const proc,const reg_t addr)1184 sentropy_csr_t::sentropy_csr_t(processor_t* const proc, const reg_t addr):
1185   csr_t(proc, addr) {
1186 }
1187 
verify_permissions(insn_t insn,bool write) const1188 void sentropy_csr_t::verify_permissions(insn_t insn, bool write) const {
1189   /* Read-only access disallowed due to wipe-on-read side effect */
1190   if (!proc->extension_enabled(EXT_ZKR) || !write)
1191     throw trap_illegal_instruction(insn.bits());
1192   csr_t::verify_permissions(insn, write);
1193 }
1194 
read() const1195 reg_t sentropy_csr_t::read() const noexcept {
1196   return proc->es.get_sentropy();
1197 }
1198 
unlogged_write(const reg_t val)1199 bool sentropy_csr_t::unlogged_write(const reg_t val) noexcept {
1200   proc->es.set_sentropy(val);
1201   return true;
1202 }
1203 
1204 
1205 
vector_csr_t(processor_t * const proc,const reg_t addr,const reg_t mask,const reg_t init)1206 vector_csr_t::vector_csr_t(processor_t* const proc, const reg_t addr, const reg_t mask, const reg_t init):
1207   basic_csr_t(proc, addr, init),
1208   mask(mask) {
1209 }
1210 
verify_permissions(insn_t insn,bool write) const1211 void vector_csr_t::verify_permissions(insn_t insn, bool write) const {
1212   require_vector_vs;
1213   if (!proc->extension_enabled('V'))
1214     throw trap_illegal_instruction(insn.bits());
1215   basic_csr_t::verify_permissions(insn, write);
1216 }
1217 
write_raw(const reg_t val)1218 void vector_csr_t::write_raw(const reg_t val) noexcept {
1219   const bool success = basic_csr_t::unlogged_write(val);
1220   if (success)
1221     log_write();
1222 }
1223 
unlogged_write(const reg_t val)1224 bool vector_csr_t::unlogged_write(const reg_t val) noexcept {
1225   if (mask == 0) return false;
1226   dirty_vs_state;
1227   return basic_csr_t::unlogged_write(val & mask);
1228 }
1229 
1230 
vxsat_csr_t(processor_t * const proc,const reg_t addr)1231 vxsat_csr_t::vxsat_csr_t(processor_t* const proc, const reg_t addr):
1232   masked_csr_t(proc, addr, /*mask*/ 1, /*init*/ 0) {
1233 }
1234 
verify_permissions(insn_t insn,bool write) const1235 void vxsat_csr_t::verify_permissions(insn_t insn, bool write) const {
1236   require_vector_vs;
1237   if (!proc->extension_enabled('V') && !proc->extension_enabled(EXT_ZPN))
1238     throw trap_illegal_instruction(insn.bits());
1239   masked_csr_t::verify_permissions(insn, write);
1240 }
1241 
unlogged_write(const reg_t val)1242 bool vxsat_csr_t::unlogged_write(const reg_t val) noexcept {
1243   dirty_vs_state;
1244   return masked_csr_t::unlogged_write(val);
1245 }
1246