1#[cfg(test)]
4mod tests;
5pub mod zicsr_helpers;
6
7use crate::{
8 CsrError, Csrs, ExecutableInstruction, ExecutableInstructionCsr, ExecutableInstructionOperands,
9 ExecutionError, RegisterFile, Rs1Rs2OperandValues, Rs1Rs2Operands,
10};
11use ab_riscv_macros::instruction_execution;
12use ab_riscv_primitives::prelude::*;
13use core::ops::ControlFlow;
14
15#[instruction_execution]
16impl<Reg> ExecutableInstructionOperands for ZicsrInstruction<Reg> where Reg: Register {}
17
18#[instruction_execution]
19impl<Reg, ExtState, CustomError> ExecutableInstructionCsr<ExtState, CustomError>
20 for ZicsrInstruction<Reg>
21where
22 Reg: Register,
23{
24}
25
26#[instruction_execution]
27impl<Reg, Regs, ExtState, Memory, PC, InstructionHandler, CustomError>
28 ExecutableInstruction<Regs, ExtState, Memory, PC, InstructionHandler, CustomError>
29 for ZicsrInstruction<Reg>
30where
31 Reg: Register,
32 Regs: RegisterFile<Reg>,
33 ExtState: Csrs<Reg, CustomError>,
34{
35 #[inline(always)]
36 fn execute(
37 self,
38 Rs1Rs2OperandValues {
39 rs1_value,
40 rs2_value: _,
41 }: Rs1Rs2OperandValues<<Self::Reg as Register>::Type>,
42 regs: &mut Regs,
43 ext_state: &mut ExtState,
44 _memory: &mut Memory,
45 _program_counter: &mut PC,
46 _system_instruction_handler: &mut InstructionHandler,
47 ) -> Result<
48 ControlFlow<(), (Self::Reg, <Self::Reg as Register>::Type)>,
49 ExecutionError<Reg::Type, CustomError>,
50 > {
51 match self {
52 Self::Csrrw {
57 rd,
58 rs1: _,
59 csr_index,
60 } => {
61 let csr_is_read_only = (csr_index >> 10) == 0b11;
62 if csr_is_read_only {
63 return Err(ExecutionError::CsrError(CsrError::ReadOnly { csr_index }));
64 }
65 zicsr_helpers::check_csr_privilege_level(ext_state, csr_index)?;
66
67 let write_value = rs1_value;
68
69 if rd != Reg::ZERO {
71 let raw_value = ext_state.read_csr(csr_index)?;
72 let output_value = ext_state.process_csr_read::<Self>(csr_index, raw_value)?;
73 regs.write(rd, output_value);
74 }
75
76 let output_value = ext_state.process_csr_write::<Self>(csr_index, write_value)?;
77 ext_state.write_csr(csr_index, output_value)?;
78 }
79
80 Self::Csrrs { rd, rs1, csr_index } => {
85 let csr_is_read_only = (csr_index >> 10) == 0b11;
86 if rs1 != Reg::ZERO && csr_is_read_only {
87 return Err(ExecutionError::CsrError(CsrError::ReadOnly { csr_index }));
88 }
89 zicsr_helpers::check_csr_privilege_level(ext_state, csr_index)?;
90
91 let raw_value = ext_state.read_csr(csr_index)?;
92 let read_output = ext_state.process_csr_read::<Self>(csr_index, raw_value)?;
93 regs.write(rd, read_output);
94
95 if rs1 != Reg::ZERO {
96 let write_value = raw_value | rs1_value;
97 let write_output =
98 ext_state.process_csr_write::<Self>(csr_index, write_value)?;
99 ext_state.write_csr(csr_index, write_output)?;
100 }
101 }
102
103 Self::Csrrc { rd, rs1, csr_index } => {
108 let csr_is_read_only = (csr_index >> 10) == 0b11;
109 if rs1 != Reg::ZERO && csr_is_read_only {
110 return Err(ExecutionError::CsrError(CsrError::ReadOnly { csr_index }));
111 }
112 zicsr_helpers::check_csr_privilege_level(ext_state, csr_index)?;
113
114 let raw_value = ext_state.read_csr(csr_index)?;
115 let read_output = ext_state.process_csr_read::<Self>(csr_index, raw_value)?;
116 regs.write(rd, read_output);
117
118 if rs1 != Reg::ZERO {
119 let write_value = raw_value & !rs1_value;
120 let write_output =
121 ext_state.process_csr_write::<Self>(csr_index, write_value)?;
122 ext_state.write_csr(csr_index, write_output)?;
123 }
124 }
125
126 Self::Csrrwi {
130 rd,
131 zimm,
132 csr_index,
133 } => {
134 let csr_is_read_only = (csr_index >> 10) == 0b11;
135 if csr_is_read_only {
136 return Err(ExecutionError::CsrError(CsrError::ReadOnly { csr_index }));
137 }
138 zicsr_helpers::check_csr_privilege_level(ext_state, csr_index)?;
139
140 if rd != Reg::ZERO {
141 let raw_value = ext_state.read_csr(csr_index)?;
142 let output_value = ext_state.process_csr_read::<Self>(csr_index, raw_value)?;
143 regs.write(rd, output_value);
144 }
145
146 let output_value = ext_state.process_csr_write::<Self>(csr_index, zimm.into())?;
147 ext_state.write_csr(csr_index, output_value)?;
148 }
149
150 Self::Csrrsi {
155 rd,
156 zimm,
157 csr_index,
158 } => {
159 let csr_is_read_only = (csr_index >> 10) == 0b11;
160 if zimm != 0 && csr_is_read_only {
161 return Err(ExecutionError::CsrError(CsrError::ReadOnly { csr_index }));
162 }
163 zicsr_helpers::check_csr_privilege_level(ext_state, csr_index)?;
164
165 let raw_value = ext_state.read_csr(csr_index)?;
166 let read_output = ext_state.process_csr_read::<Self>(csr_index, raw_value)?;
167 regs.write(rd, read_output);
168
169 if zimm != 0 {
170 let write_value = raw_value | Reg::Type::from(zimm);
171 let write_output =
172 ext_state.process_csr_write::<Self>(csr_index, write_value)?;
173 ext_state.write_csr(csr_index, write_output)?;
174 }
175 }
176
177 Self::Csrrci {
182 rd,
183 zimm,
184 csr_index,
185 } => {
186 let csr_is_read_only = (csr_index >> 10) == 0b11;
187 if zimm != 0 && csr_is_read_only {
188 return Err(ExecutionError::CsrError(CsrError::ReadOnly { csr_index }));
189 }
190 zicsr_helpers::check_csr_privilege_level(ext_state, csr_index)?;
191
192 let raw_value = ext_state.read_csr(csr_index)?;
193 let read_output = ext_state.process_csr_read::<Self>(csr_index, raw_value)?;
194 regs.write(rd, read_output);
195
196 if zimm != 0 {
197 let write_value = raw_value & !Reg::Type::from(zimm);
198 let write_output =
199 ext_state.process_csr_write::<Self>(csr_index, write_value)?;
200 ext_state.write_csr(csr_index, write_output)?;
201 }
202 }
203 }
204
205 Ok(ControlFlow::Continue(Default::default()))
206 }
207}