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, ExecutionResult, FetchInstructionResult, InstructionFetcher,
11 OpaqueThreadedExecutionResult, ProgramCounter, RegisterFile, Rs1Rs2OperandValues,
12 Rs1Rs2Operands, ThreadedExecutableInstruction, ThreadedExecutionResult,
13};
14use ab_riscv_macros::instruction_execution;
15use ab_riscv_primitives::prelude::*;
16
17#[instruction_execution]
18const impl<Reg> ExecutableInstructionOperands for ZveXxConfigInstruction<Reg> where Reg: Register {}
19
20#[instruction_execution]
21const impl<Reg, Env> ExecutableInstructionCsr<Env> for ZveXxConfigInstruction<Reg>
22where
23 Reg: [const] Register,
24 Env: [const] Csrs<Reg>,
25{
26 #[inline(always)]
31 #[cfg_attr(feature = "no-panic", no_panic_const::no_panic(const))]
32 fn prepare_csr_read(
33 _env: &Env,
34 csr_index: u16,
35 _will_write: bool,
36 raw_value: Reg::Type,
37 output_value: &mut Reg::Type,
38 ) -> Result<bool, CsrError> {
39 if VectorCsr::from_csr_index(csr_index).is_some() {
40 *output_value = raw_value;
41 Ok(true)
42 } else {
43 Ok(false)
45 }
46 }
47
48 #[inline(always)]
57 #[cfg_attr(feature = "no-panic", no_panic_const::no_panic(const))]
58 fn prepare_csr_write(
59 env: &mut Env,
60 csr_index: u16,
61 write_value: Reg::Type,
62 output_value: &mut Reg::Type,
63 ) -> Result<bool, CsrError> {
64 if let Some(vcsr) = VectorCsr::from_csr_index(csr_index) {
65 *output_value = match vcsr {
67 VectorCsr::Vstart => {
68 let max = Reg::Type::from(u16::MAX);
70 write_value.min(max)
71 }
72 VectorCsr::Vxsat => {
73 let masked = write_value & Reg::Type::from(1u8);
74 let old_vcsr = env.read_csr(VectorCsr::Vcsr.to_csr_index())?;
76 let new_vcsr = (old_vcsr & !Reg::Type::from(1u8)) | masked;
77 env.write_csr(VectorCsr::Vcsr.to_csr_index(), new_vcsr)?;
78 masked
79 }
80 VectorCsr::Vxrm => {
81 let masked = write_value & Reg::Type::from(0b11u8);
82 let old_vcsr = env.read_csr(VectorCsr::Vcsr.to_csr_index())?;
84 let new_vcsr = (old_vcsr & !Reg::Type::from(0b110u8)) | (masked << 1u8);
85 env.write_csr(VectorCsr::Vcsr.to_csr_index(), new_vcsr)?;
86 masked
87 }
88 VectorCsr::Vcsr => {
89 let new_vxsat = write_value & Reg::Type::from(1u8);
91 env.write_csr(VectorCsr::Vxsat.to_csr_index(), new_vxsat)?;
92
93 let new_vxrm = (write_value >> 1u8) & Reg::Type::from(0b11u8);
95 env.write_csr(VectorCsr::Vxrm.to_csr_index(), new_vxrm)?;
96
97 write_value & Reg::Type::from(0b111u8)
98 }
99 VectorCsr::Vl | VectorCsr::Vtype | VectorCsr::Vlenb => {
100 Err(CsrError::ReadOnly { csr_index })?
102 }
103 };
104 Ok(true)
105 } else {
106 Ok(false)
107 }
108 }
109}
110
111#[instruction_execution]
112const impl<Reg, Regs, Env, Memory, PC> ExecutableInstruction<Regs, Env, Memory, PC>
113 for ZveXxConfigInstruction<Reg>
114where
115 Reg: [const] Register,
116 Regs: [const] RegisterFile<Reg>,
117 Env: [const] VectorRegistersExt<Reg>,
118 [(); SUPPORTED_ELEN_VLEN::<{ Env::ELEN }, { Env::VLEN }>]:,
119 PC: [const] ProgramCounter<Reg::Type, Memory>,
120{
121 #[inline(always)]
122 #[cfg_attr(feature = "no-panic", no_panic_const::no_panic(const))]
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 env: &mut Env,
131 _memory: &mut Memory,
132 program_counter: &mut PC,
133 ) -> ExecutionResult<Self::Reg> {
134 match self {
135 Self::Vsetvli { rd, rs1, vtypei } => {
136 let rd_value = zvexx_config_helpers::apply_vsetvl(
137 env,
138 program_counter,
139 rd,
140 rs1,
141 rs1_value,
142 Reg::Type::from(vtypei),
143 )?;
144
145 ExecutionResult::Continue {
146 rd,
147 value: rd_value,
148 }
149 }
150 Self::Vsetivli { rd, uimm, vtypei } => {
151 let rd_value =
152 zvexx_config_helpers::apply_vsetivli(env, program_counter, uimm, vtypei)?;
153
154 ExecutionResult::Continue {
155 rd,
156 value: rd_value,
157 }
158 }
159 Self::Vsetvl { rd, rs1, rs2: _ } => {
160 let vtype_raw = rs2_value;
161 let rd_value = zvexx_config_helpers::apply_vsetvl(
162 env,
163 program_counter,
164 rd,
165 rs1,
166 rs1_value,
167 vtype_raw,
168 )?;
169
170 ExecutionResult::Continue {
171 rd,
172 value: rd_value,
173 }
174 }
175 }
176 }
177}