1#[cfg(test)]
4mod tests;
5pub mod zvbc_helpers;
6
7use crate::v::vector_registers::VectorRegistersExt;
8use crate::v::zvexx::arith::zvexx_arith_helpers;
9use crate::v::zvexx::carry::zvexx_carry_helpers;
10use crate::v::zvexx::config::zvexx_config_helpers;
11use crate::v::zvexx::fixed_point::zvexx_fixed_point_helpers;
12use crate::v::zvexx::load::zvexx_load_helpers;
13use crate::v::zvexx::mask::zvexx_mask_helpers;
14use crate::v::zvexx::muldiv::zvexx_muldiv_helpers;
15use crate::v::zvexx::perm::zvexx_perm_helpers;
16use crate::v::zvexx::reduction::zvexx_reduction_helpers;
17use crate::v::zvexx::store::zvexx_store_helpers;
18use crate::v::zvexx::widen_narrow::zvexx_widen_narrow_helpers;
19use crate::v::zvexx::zvexx_helpers;
20use crate::zicsr::zicsr_helpers;
21use crate::{
22 CsrError, Csrs, ExecutableInstruction, ExecutableInstructionCsr, ExecutableInstructionOperands,
23 ExecutionError, ProgramCounter, RegisterFile, Rs1Rs2OperandValues, Rs1Rs2Operands,
24 VirtualMemory,
25};
26use ab_riscv_macros::instruction_execution;
27use ab_riscv_primitives::prelude::*;
28use core::fmt;
29use core::ops::ControlFlow;
30
31#[instruction_execution]
32impl<Reg> ExecutableInstructionOperands for ZvbcInstruction<Reg> where Reg: Register {}
33
34#[instruction_execution]
35impl<Reg, ExtState, CustomError> ExecutableInstructionCsr<ExtState, CustomError>
36 for ZvbcInstruction<Reg>
37where
38 Reg: Register,
39{
40}
41
42#[instruction_execution]
43impl<Reg, Regs, ExtState, Memory, PC, InstructionHandler, CustomError>
44 ExecutableInstruction<Regs, ExtState, Memory, PC, InstructionHandler, CustomError>
45 for ZvbcInstruction<Reg>
46where
47 Reg: Register,
48 Regs: RegisterFile<Reg>,
49 ExtState: VectorRegistersExt<Reg, CustomError>,
50 [(); SUPPORTED_ELEN_VLEN::<{ ExtState::ELEN }, { ExtState::VLEN }>]:,
51 Memory: VirtualMemory,
52 PC: ProgramCounter<Reg::Type, Memory, CustomError>,
53 CustomError: fmt::Debug,
54{
55 #[inline(always)]
56 fn execute(
57 self,
58 Rs1Rs2OperandValues {
59 rs1_value,
60 rs2_value,
61 }: Rs1Rs2OperandValues<<Self::Reg as Register>::Type>,
62 _regs: &mut Regs,
63 ext_state: &mut ExtState,
64 memory: &mut Memory,
65 program_counter: &mut PC,
66 _system_instruction_handler: &mut InstructionHandler,
67 ) -> Result<
68 ControlFlow<(), (Self::Reg, <Self::Reg as Register>::Type)>,
69 ExecutionError<Reg::Type, CustomError>,
70 > {
71 match self {
72 Self::VclmulVv { vd, vs2, vs1, vm } => {
74 if !ext_state.vector_instructions_allowed() {
75 ::core::hint::cold_path();
76 return Err(ExecutionError::IllegalInstruction {
77 address: program_counter.old_pc(zvexx_helpers::INSTRUCTION_SIZE),
78 });
79 }
80 if !vm && vd == VReg::V0 {
81 ::core::hint::cold_path();
82 return Err(ExecutionError::IllegalInstruction {
83 address: program_counter.old_pc(zvexx_helpers::INSTRUCTION_SIZE),
84 });
85 }
86 let Some(vtype) = ext_state.vtype() else {
87 ::core::hint::cold_path();
88 return Err(ExecutionError::IllegalInstruction {
89 address: program_counter.old_pc(zvexx_helpers::INSTRUCTION_SIZE),
90 });
91 };
92 let group_regs = vtype.vlmul().register_count();
93 zvbc_helpers::check_vreg_group_alignment::<Reg, _, _, _>(
94 program_counter,
95 vd,
96 group_regs,
97 )?;
98 zvbc_helpers::check_vreg_group_alignment::<Reg, _, _, _>(
99 program_counter,
100 vs2,
101 group_regs,
102 )?;
103 zvbc_helpers::check_vreg_group_alignment::<Reg, _, _, _>(
104 program_counter,
105 vs1,
106 group_regs,
107 )?;
108 let sew = vtype.vsew();
109 unsafe {
111 zvbc_helpers::execute_vclmul::<Reg, _, _>(
112 ext_state,
113 vd,
114 vs2,
115 zvbc_helpers::OpSrc::Vreg(vs1),
116 sew,
117 vm,
118 );
119 }
120 }
121 Self::VclmulVx {
122 vm,
123 vd,
124 vs2,
125 rs1: _,
126 } => {
127 if !ext_state.vector_instructions_allowed() {
128 ::core::hint::cold_path();
129 return Err(ExecutionError::IllegalInstruction {
130 address: program_counter.old_pc(zvexx_helpers::INSTRUCTION_SIZE),
131 });
132 }
133 if !vm && vd == VReg::V0 {
134 ::core::hint::cold_path();
135 return Err(ExecutionError::IllegalInstruction {
136 address: program_counter.old_pc(zvexx_helpers::INSTRUCTION_SIZE),
137 });
138 }
139 let Some(vtype) = ext_state.vtype() else {
140 ::core::hint::cold_path();
141 return Err(ExecutionError::IllegalInstruction {
142 address: program_counter.old_pc(zvexx_helpers::INSTRUCTION_SIZE),
143 });
144 };
145 let group_regs = vtype.vlmul().register_count();
146 zvbc_helpers::check_vreg_group_alignment::<Reg, _, _, _>(
147 program_counter,
148 vd,
149 group_regs,
150 )?;
151 zvbc_helpers::check_vreg_group_alignment::<Reg, _, _, _>(
152 program_counter,
153 vs2,
154 group_regs,
155 )?;
156 let sew = vtype.vsew();
157 let scalar = rs1_value.as_i64().cast_unsigned();
158 unsafe {
160 zvbc_helpers::execute_vclmul::<Reg, _, _>(
161 ext_state,
162 vd,
163 vs2,
164 zvbc_helpers::OpSrc::Scalar(scalar),
165 sew,
166 vm,
167 );
168 }
169 }
170 Self::VclmulhVv { vd, vs2, vs1, vm } => {
172 if !ext_state.vector_instructions_allowed() {
173 ::core::hint::cold_path();
174 return Err(ExecutionError::IllegalInstruction {
175 address: program_counter.old_pc(zvexx_helpers::INSTRUCTION_SIZE),
176 });
177 }
178 if !vm && vd == VReg::V0 {
179 ::core::hint::cold_path();
180 return Err(ExecutionError::IllegalInstruction {
181 address: program_counter.old_pc(zvexx_helpers::INSTRUCTION_SIZE),
182 });
183 }
184 let Some(vtype) = ext_state.vtype() else {
185 ::core::hint::cold_path();
186 return Err(ExecutionError::IllegalInstruction {
187 address: program_counter.old_pc(zvexx_helpers::INSTRUCTION_SIZE),
188 });
189 };
190 let group_regs = vtype.vlmul().register_count();
191 zvbc_helpers::check_vreg_group_alignment::<Reg, _, _, _>(
192 program_counter,
193 vd,
194 group_regs,
195 )?;
196 zvbc_helpers::check_vreg_group_alignment::<Reg, _, _, _>(
197 program_counter,
198 vs2,
199 group_regs,
200 )?;
201 zvbc_helpers::check_vreg_group_alignment::<Reg, _, _, _>(
202 program_counter,
203 vs1,
204 group_regs,
205 )?;
206 let sew = vtype.vsew();
207 unsafe {
209 zvbc_helpers::execute_vclmulh::<Reg, _, _>(
210 ext_state,
211 vd,
212 vs2,
213 zvbc_helpers::OpSrc::Vreg(vs1),
214 sew,
215 vm,
216 );
217 }
218 }
219 Self::VclmulhVx {
220 vm,
221 vd,
222 vs2,
223 rs1: _,
224 } => {
225 if !ext_state.vector_instructions_allowed() {
226 ::core::hint::cold_path();
227 return Err(ExecutionError::IllegalInstruction {
228 address: program_counter.old_pc(zvexx_helpers::INSTRUCTION_SIZE),
229 });
230 }
231 if !vm && vd == VReg::V0 {
232 ::core::hint::cold_path();
233 return Err(ExecutionError::IllegalInstruction {
234 address: program_counter.old_pc(zvexx_helpers::INSTRUCTION_SIZE),
235 });
236 }
237 let Some(vtype) = ext_state.vtype() else {
238 ::core::hint::cold_path();
239 return Err(ExecutionError::IllegalInstruction {
240 address: program_counter.old_pc(zvexx_helpers::INSTRUCTION_SIZE),
241 });
242 };
243 let group_regs = vtype.vlmul().register_count();
244 zvbc_helpers::check_vreg_group_alignment::<Reg, _, _, _>(
245 program_counter,
246 vd,
247 group_regs,
248 )?;
249 zvbc_helpers::check_vreg_group_alignment::<Reg, _, _, _>(
250 program_counter,
251 vs2,
252 group_regs,
253 )?;
254 let sew = vtype.vsew();
255 let scalar = rs1_value.as_i64().cast_unsigned();
256 unsafe {
258 zvbc_helpers::execute_vclmulh::<Reg, _, _>(
259 ext_state,
260 vd,
261 vs2,
262 zvbc_helpers::OpSrc::Scalar(scalar),
263 sew,
264 vm,
265 );
266 }
267 }
268 }
269 Ok(ControlFlow::Continue(Default::default()))
270 }
271}