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