ab_riscv_interpreter/v/zvexx/
config.rs1#[cfg(test)]
4mod tests;
5pub mod zvexx_config_helpers;
6
7use crate::v::vector_registers::VectorRegistersExt;
8use crate::{
9 CsrError, Csrs, ExecutableInstruction, ExecutableInstructionCsr, ExecutableInstructionOperands,
10 ExecutionError, ProgramCounter, RegisterFile, Rs1Rs2OperandValues, Rs1Rs2Operands,
11};
12use ab_riscv_macros::instruction_execution;
13use ab_riscv_primitives::prelude::*;
14use core::fmt;
15use core::ops::ControlFlow;
16
17#[instruction_execution]
18impl<Reg> ExecutableInstructionOperands for ZveXxConfigInstruction<Reg> where Reg: Register {}
19
20#[instruction_execution]
21impl<Reg, ExtState, CustomError> ExecutableInstructionCsr<ExtState, CustomError>
22 for ZveXxConfigInstruction<Reg>
23where
24 Reg: Register,
25 ExtState: Csrs<Reg, CustomError>,
26{
27 #[inline(always)]
32 #[cfg_attr(feature = "no-panic", no_panic_const::no_panic)]
33 fn prepare_csr_read(
34 ext_state: &ExtState,
35 csr_index: u16,
36 raw_value: Reg::Type,
37 output_value: &mut Reg::Type,
38 ) -> Result<bool, CsrError<CustomError>> {
39 let _: &ExtState = ext_state;
41 if VectorCsr::from_csr_index(csr_index).is_some() {
42 *output_value = raw_value;
43 Ok(true)
44 } else {
45 Ok(false)
47 }
48 }
49
50 #[inline(always)]
59 #[cfg_attr(feature = "no-panic", no_panic_const::no_panic)]
60 fn prepare_csr_write(
61 ext_state: &mut ExtState,
62 csr_index: u16,
63 write_value: Reg::Type,
64 output_value: &mut Reg::Type,
65 ) -> Result<bool, CsrError<CustomError>> {
66 if let Some(vcsr) = VectorCsr::from_csr_index(csr_index) {
67 *output_value = match vcsr {
69 VectorCsr::Vstart => {
70 let max = Reg::Type::from(u16::MAX);
72 write_value.min(max)
73 }
74 VectorCsr::Vxsat => {
75 let masked = write_value & Reg::Type::from(1u8);
76 let old_vcsr = ext_state.read_csr(VectorCsr::Vcsr.to_csr_index())?;
78 let new_vcsr = (old_vcsr & !Reg::Type::from(1u8)) | masked;
79 ext_state.write_csr(VectorCsr::Vcsr.to_csr_index(), new_vcsr)?;
80 masked
81 }
82 VectorCsr::Vxrm => {
83 let masked = write_value & Reg::Type::from(0b11u8);
84 let old_vcsr = ext_state.read_csr(VectorCsr::Vcsr.to_csr_index())?;
86 let new_vcsr = (old_vcsr & !Reg::Type::from(0b110u8)) | (masked << 1u8);
87 ext_state.write_csr(VectorCsr::Vcsr.to_csr_index(), new_vcsr)?;
88 masked
89 }
90 VectorCsr::Vcsr => {
91 let new_vxsat = write_value & Reg::Type::from(1u8);
93 ext_state.write_csr(VectorCsr::Vxsat.to_csr_index(), new_vxsat)?;
94
95 let new_vxrm = (write_value >> 1u8) & Reg::Type::from(0b11u8);
97 ext_state.write_csr(VectorCsr::Vxrm.to_csr_index(), new_vxrm)?;
98
99 write_value & Reg::Type::from(0b111u8)
100 }
101 VectorCsr::Vl | VectorCsr::Vtype | VectorCsr::Vlenb => {
102 Err(CsrError::ReadOnly { csr_index })?
104 }
105 };
106 Ok(true)
107 } else {
108 Ok(false)
109 }
110 }
111}
112
113#[instruction_execution]
114impl<Reg, Regs, ExtState, Memory, PC, InstructionHandler, CustomError>
115 ExecutableInstruction<Regs, ExtState, Memory, PC, InstructionHandler, CustomError>
116 for ZveXxConfigInstruction<Reg>
117where
118 Reg: Register,
119 Regs: RegisterFile<Reg>,
120 ExtState: VectorRegistersExt<Reg, CustomError>,
121 [(); SUPPORTED_ELEN_VLEN::<{ ExtState::ELEN }, { ExtState::VLEN }>]:,
122 PC: ProgramCounter<Reg::Type, Memory, CustomError>,
123 CustomError: fmt::Debug,
124{
125 #[inline(always)]
126 fn execute(
127 self,
128 Rs1Rs2OperandValues {
129 rs1_value,
130 rs2_value,
131 }: Rs1Rs2OperandValues<<Self::Reg as Register>::Type>,
132 _regs: &mut Regs,
133 ext_state: &mut ExtState,
134 _memory: &mut Memory,
135 program_counter: &mut PC,
136 _system_instruction_handler: &mut InstructionHandler,
137 ) -> Result<
138 ControlFlow<(), (Self::Reg, <Self::Reg as Register>::Type)>,
139 ExecutionError<Reg::Type, CustomError>,
140 > {
141 match self {
142 Self::Vsetvli { rd, rs1, vtypei } => {
143 let rd_value = zvexx_config_helpers::apply_vsetvl(
144 ext_state,
145 program_counter,
146 rd,
147 rs1,
148 rs1_value,
149 Reg::Type::from(vtypei),
150 )?;
151
152 Ok(ControlFlow::Continue((rd, rd_value)))
153 }
154 Self::Vsetivli { rd, uimm, vtypei } => {
155 let rd_value =
156 zvexx_config_helpers::apply_vsetivli(ext_state, program_counter, uimm, vtypei)?;
157
158 Ok(ControlFlow::Continue((rd, rd_value)))
159 }
160 Self::Vsetvl { rd, rs1, rs2: _ } => {
161 let vtype_raw = rs2_value;
162 let rd_value = zvexx_config_helpers::apply_vsetvl(
163 ext_state,
164 program_counter,
165 rd,
166 rs1,
167 rs1_value,
168 vtype_raw,
169 )?;
170
171 Ok(ControlFlow::Continue((rd, rd_value)))
172 }
173 }
174 }
175}