ab_riscv_interpreter/
zicsr.rs1#[cfg(test)]
4mod tests;
5pub mod zicsr_helpers;
6
7use crate::{CsrError, Csrs, ExecutableInstruction, ExecutionError, RegisterFile};
8use ab_riscv_macros::instruction_execution;
9use ab_riscv_primitives::prelude::*;
10use core::ops::ControlFlow;
11
12#[instruction_execution]
13impl<Reg, Regs, ExtState, Memory, PC, InstructionHandler, CustomError>
14 ExecutableInstruction<Regs, ExtState, Memory, PC, InstructionHandler, CustomError>
15 for ZicsrInstruction<Reg>
16where
17 Reg: Register,
18 Regs: RegisterFile<Reg>,
19 ExtState: Csrs<Reg, CustomError>,
20{
21 #[inline(always)]
22 fn execute(
23 self,
24 regs: &mut Regs,
25 ext_state: &mut ExtState,
26 _memory: &mut Memory,
27 _program_counter: &mut PC,
28 _system_instruction_handler: &mut InstructionHandler,
29 ) -> Result<ControlFlow<()>, ExecutionError<Reg::Type, CustomError>> {
30 match self {
31 Self::Csrrw { rd, rs1, csr } => {
36 let csr_is_read_only = (csr >> 10) == 0b11;
37 if csr_is_read_only {
38 return Err(ExecutionError::CsrError(CsrError::ReadOnly {
39 csr_index: csr,
40 }));
41 }
42 zicsr_helpers::check_csr_privilege_level(ext_state, csr)?;
43
44 let write_value = regs.read(rs1);
45
46 if rd != Reg::ZERO {
48 let raw_value = ext_state.read_csr(csr)?;
49 let output_value = ext_state.process_csr_read(csr, raw_value)?;
50 regs.write(rd, output_value);
51 }
52
53 let output_value = ext_state.process_csr_write(csr, write_value)?;
54 ext_state.write_csr(csr, output_value)?;
55 }
56
57 Self::Csrrs { rd, rs1, csr } => {
62 let csr_is_read_only = (csr >> 10) == 0b11;
63 if rs1 != Reg::ZERO && csr_is_read_only {
64 return Err(ExecutionError::CsrError(CsrError::ReadOnly {
65 csr_index: csr,
66 }));
67 }
68 zicsr_helpers::check_csr_privilege_level(ext_state, csr)?;
69
70 let rs1_value = regs.read(rs1);
71
72 let raw_value = ext_state.read_csr(csr)?;
73 let read_output = ext_state.process_csr_read(csr, raw_value)?;
74 regs.write(rd, read_output);
75
76 if rs1 != Reg::ZERO {
77 let write_value = raw_value | rs1_value;
78 let write_output = ext_state.process_csr_write(csr, write_value)?;
79 ext_state.write_csr(csr, write_output)?;
80 }
81 }
82
83 Self::Csrrc { rd, rs1, csr } => {
88 let csr_is_read_only = (csr >> 10) == 0b11;
89 if rs1 != Reg::ZERO && csr_is_read_only {
90 return Err(ExecutionError::CsrError(CsrError::ReadOnly {
91 csr_index: csr,
92 }));
93 }
94 zicsr_helpers::check_csr_privilege_level(ext_state, csr)?;
95
96 let rs1_value = regs.read(rs1);
97
98 let raw_value = ext_state.read_csr(csr)?;
99 let read_output = ext_state.process_csr_read(csr, raw_value)?;
100 regs.write(rd, read_output);
101
102 if rs1 != Reg::ZERO {
103 let write_value = raw_value & !rs1_value;
104 let write_output = ext_state.process_csr_write(csr, write_value)?;
105 ext_state.write_csr(csr, write_output)?;
106 }
107 }
108
109 Self::Csrrwi { rd, zimm, csr } => {
113 let csr_is_read_only = (csr >> 10) == 0b11;
114 if csr_is_read_only {
115 return Err(ExecutionError::CsrError(CsrError::ReadOnly {
116 csr_index: csr,
117 }));
118 }
119 zicsr_helpers::check_csr_privilege_level(ext_state, csr)?;
120
121 if rd != Reg::ZERO {
122 let raw_value = ext_state.read_csr(csr)?;
123 let output_value = ext_state.process_csr_read(csr, raw_value)?;
124 regs.write(rd, output_value);
125 }
126
127 let output_value = ext_state.process_csr_write(csr, zimm.into())?;
128 ext_state.write_csr(csr, output_value)?;
129 }
130
131 Self::Csrrsi { rd, zimm, csr } => {
136 let csr_is_read_only = (csr >> 10) == 0b11;
137 if zimm != 0 && csr_is_read_only {
138 return Err(ExecutionError::CsrError(CsrError::ReadOnly {
139 csr_index: csr,
140 }));
141 }
142 zicsr_helpers::check_csr_privilege_level(ext_state, csr)?;
143
144 let raw_value = ext_state.read_csr(csr)?;
145 let read_output = ext_state.process_csr_read(csr, raw_value)?;
146 regs.write(rd, read_output);
147
148 if zimm != 0 {
149 let write_value = raw_value | Reg::Type::from(zimm);
150 let write_output = ext_state.process_csr_write(csr, write_value)?;
151 ext_state.write_csr(csr, write_output)?;
152 }
153 }
154
155 Self::Csrrci { rd, zimm, csr } => {
160 let csr_is_read_only = (csr >> 10) == 0b11;
161 if zimm != 0 && csr_is_read_only {
162 return Err(ExecutionError::CsrError(CsrError::ReadOnly {
163 csr_index: csr,
164 }));
165 }
166 zicsr_helpers::check_csr_privilege_level(ext_state, csr)?;
167
168 let raw_value = ext_state.read_csr(csr)?;
169 let read_output = ext_state.process_csr_read(csr, raw_value)?;
170 regs.write(rd, read_output);
171
172 if zimm != 0 {
173 let write_value = raw_value & !Reg::Type::from(zimm);
174 let write_output = ext_state.process_csr_write(csr, write_value)?;
175 ext_state.write_csr(csr, write_output)?;
176 }
177 }
178 }
179
180 Ok(ControlFlow::Continue(()))
181 }
182}