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 fn prepare_csr_read(
33 _ext_state: &ExtState,
34 csr_index: u16,
35 raw_value: Reg::Type,
36 output_value: &mut Reg::Type,
37 ) -> Result<bool, CsrError<CustomError>> {
38 if VectorCsr::from_csr_index(csr_index).is_some() {
39 *output_value = raw_value;
40 Ok(true)
41 } else {
42 Ok(false)
44 }
45 }
46
47 #[inline(always)]
56 fn prepare_csr_write(
57 ext_state: &mut ExtState,
58 csr_index: u16,
59 write_value: Reg::Type,
60 output_value: &mut Reg::Type,
61 ) -> Result<bool, CsrError<CustomError>> {
62 if let Some(vcsr) = VectorCsr::from_csr_index(csr_index) {
63 *output_value = match vcsr {
65 VectorCsr::Vstart => {
66 let max = Reg::Type::from(u16::MAX);
68 write_value.min(max)
69 }
70 VectorCsr::Vxsat => {
71 let masked = write_value & Reg::Type::from(1u8);
72 let old_vcsr = ext_state.read_csr(VectorCsr::Vcsr.to_csr_index())?;
74 let new_vcsr = (old_vcsr & !Reg::Type::from(1u8)) | masked;
75 ext_state.write_csr(VectorCsr::Vcsr.to_csr_index(), new_vcsr)?;
76 masked
77 }
78 VectorCsr::Vxrm => {
79 let masked = write_value & Reg::Type::from(0b11u8);
80 let old_vcsr = ext_state.read_csr(VectorCsr::Vcsr.to_csr_index())?;
82 let new_vcsr = (old_vcsr & !Reg::Type::from(0b110u8)) | (masked << 1u8);
83 ext_state.write_csr(VectorCsr::Vcsr.to_csr_index(), new_vcsr)?;
84 masked
85 }
86 VectorCsr::Vcsr => {
87 let new_vxsat = write_value & Reg::Type::from(1u8);
89 ext_state.write_csr(VectorCsr::Vxsat.to_csr_index(), new_vxsat)?;
90
91 let new_vxrm = (write_value >> 1u8) & Reg::Type::from(0b11u8);
93 ext_state.write_csr(VectorCsr::Vxrm.to_csr_index(), new_vxrm)?;
94
95 write_value & Reg::Type::from(0b111u8)
96 }
97 VectorCsr::Vl | VectorCsr::Vtype | VectorCsr::Vlenb => {
98 Err(CsrError::ReadOnly { csr_index })?
100 }
101 };
102 Ok(true)
103 } else {
104 Ok(false)
105 }
106 }
107}
108
109#[instruction_execution]
110impl<Reg, Regs, ExtState, Memory, PC, InstructionHandler, CustomError>
111 ExecutableInstruction<Regs, ExtState, Memory, PC, InstructionHandler, CustomError>
112 for ZveXxConfigInstruction<Reg>
113where
114 Reg: Register,
115 Regs: RegisterFile<Reg>,
116 ExtState: VectorRegistersExt<Reg, CustomError>,
117 [(); ExtState::ELEN as usize]:,
118 [(); ExtState::VLEN as usize]:,
119 PC: ProgramCounter<Reg::Type, Memory, CustomError>,
120 CustomError: fmt::Debug,
121{
122 #[inline(always)]
123 fn execute(
124 self,
125 Rs1Rs2OperandValues {
126 rs1_value,
127 rs2_value,
128 }: Rs1Rs2OperandValues<<Self::Reg as Register>::Type>,
129 _regs: &mut Regs,
130 ext_state: &mut ExtState,
131 _memory: &mut Memory,
132 program_counter: &mut PC,
133 _system_instruction_handler: &mut InstructionHandler,
134 ) -> Result<
135 ControlFlow<(), (Self::Reg, <Self::Reg as Register>::Type)>,
136 ExecutionError<Reg::Type, CustomError>,
137 > {
138 match self {
139 Self::Vsetvli { rd, rs1, vtypei } => {
140 let rd_value = zvexx_config_helpers::apply_vsetvl(
141 ext_state,
142 program_counter,
143 rd,
144 rs1,
145 rs1_value,
146 Reg::Type::from(vtypei),
147 )?;
148
149 Ok(ControlFlow::Continue((rd, rd_value)))
150 }
151 Self::Vsetivli { rd, uimm, vtypei } => {
152 let rd_value =
153 zvexx_config_helpers::apply_vsetivli(ext_state, program_counter, uimm, vtypei)?;
154
155 Ok(ControlFlow::Continue((rd, rd_value)))
156 }
157 Self::Vsetvl { rd, rs1, rs2: _ } => {
158 let vtype_raw = rs2_value;
159 let rd_value = zvexx_config_helpers::apply_vsetvl(
160 ext_state,
161 program_counter,
162 rd,
163 rs1,
164 rs1_value,
165 vtype_raw,
166 )?;
167
168 Ok(ControlFlow::Continue((rd, rd_value)))
169 }
170 }
171 }
172}