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 [(); ExtState::ELEN as usize]:,
51 [(); ExtState::VLEN as usize]:,
52 [(); ExtState::VLENB as usize]:,
53 Memory: VirtualMemory,
54 PC: ProgramCounter<Reg::Type, Memory, CustomError>,
55 CustomError: fmt::Debug,
56{
57 #[inline(always)]
58 fn execute(
59 self,
60 Rs1Rs2OperandValues {
61 rs1_value,
62 rs2_value,
63 }: Rs1Rs2OperandValues<<Self::Reg as Register>::Type>,
64 _regs: &mut Regs,
65 ext_state: &mut ExtState,
66 memory: &mut Memory,
67 program_counter: &mut PC,
68 _system_instruction_handler: &mut InstructionHandler,
69 ) -> Result<
70 ControlFlow<(), (Self::Reg, <Self::Reg as Register>::Type)>,
71 ExecutionError<Reg::Type, CustomError>,
72 > {
73 match self {
74 Self::VclmulVv { vd, vs2, vs1, vm } => {
76 if !ext_state.vector_instructions_allowed() {
77 ::core::hint::cold_path();
78 return Err(ExecutionError::IllegalInstruction {
79 address: program_counter.old_pc(zvexx_helpers::INSTRUCTION_SIZE),
80 });
81 }
82 if !vm && vd == VReg::V0 {
83 ::core::hint::cold_path();
84 return Err(ExecutionError::IllegalInstruction {
85 address: program_counter.old_pc(zvexx_helpers::INSTRUCTION_SIZE),
86 });
87 }
88 let Some(vtype) = ext_state.vtype() else {
89 ::core::hint::cold_path();
90 return Err(ExecutionError::IllegalInstruction {
91 address: program_counter.old_pc(zvexx_helpers::INSTRUCTION_SIZE),
92 });
93 };
94 let group_regs = vtype.vlmul().register_count();
95 zvbc_helpers::check_vreg_group_alignment::<Reg, _, _, _>(
96 program_counter,
97 vd,
98 group_regs,
99 )?;
100 zvbc_helpers::check_vreg_group_alignment::<Reg, _, _, _>(
101 program_counter,
102 vs2,
103 group_regs,
104 )?;
105 zvbc_helpers::check_vreg_group_alignment::<Reg, _, _, _>(
106 program_counter,
107 vs1,
108 group_regs,
109 )?;
110 let sew = vtype.vsew();
111 unsafe {
113 zvbc_helpers::execute_vclmul::<Reg, _, _>(
114 ext_state,
115 vd,
116 vs2,
117 zvbc_helpers::OpSrc::Vreg(vs1),
118 sew,
119 vm,
120 );
121 }
122 }
123 Self::VclmulVx {
124 vm,
125 vd,
126 vs2,
127 rs1: _,
128 } => {
129 if !ext_state.vector_instructions_allowed() {
130 ::core::hint::cold_path();
131 return Err(ExecutionError::IllegalInstruction {
132 address: program_counter.old_pc(zvexx_helpers::INSTRUCTION_SIZE),
133 });
134 }
135 if !vm && vd == VReg::V0 {
136 ::core::hint::cold_path();
137 return Err(ExecutionError::IllegalInstruction {
138 address: program_counter.old_pc(zvexx_helpers::INSTRUCTION_SIZE),
139 });
140 }
141 let Some(vtype) = ext_state.vtype() else {
142 ::core::hint::cold_path();
143 return Err(ExecutionError::IllegalInstruction {
144 address: program_counter.old_pc(zvexx_helpers::INSTRUCTION_SIZE),
145 });
146 };
147 let group_regs = vtype.vlmul().register_count();
148 zvbc_helpers::check_vreg_group_alignment::<Reg, _, _, _>(
149 program_counter,
150 vd,
151 group_regs,
152 )?;
153 zvbc_helpers::check_vreg_group_alignment::<Reg, _, _, _>(
154 program_counter,
155 vs2,
156 group_regs,
157 )?;
158 let sew = vtype.vsew();
159 let scalar = rs1_value.as_i64().cast_unsigned();
160 unsafe {
162 zvbc_helpers::execute_vclmul::<Reg, _, _>(
163 ext_state,
164 vd,
165 vs2,
166 zvbc_helpers::OpSrc::Scalar(scalar),
167 sew,
168 vm,
169 );
170 }
171 }
172 Self::VclmulhVv { vd, vs2, vs1, vm } => {
174 if !ext_state.vector_instructions_allowed() {
175 ::core::hint::cold_path();
176 return Err(ExecutionError::IllegalInstruction {
177 address: program_counter.old_pc(zvexx_helpers::INSTRUCTION_SIZE),
178 });
179 }
180 if !vm && vd == VReg::V0 {
181 ::core::hint::cold_path();
182 return Err(ExecutionError::IllegalInstruction {
183 address: program_counter.old_pc(zvexx_helpers::INSTRUCTION_SIZE),
184 });
185 }
186 let Some(vtype) = ext_state.vtype() else {
187 ::core::hint::cold_path();
188 return Err(ExecutionError::IllegalInstruction {
189 address: program_counter.old_pc(zvexx_helpers::INSTRUCTION_SIZE),
190 });
191 };
192 let group_regs = vtype.vlmul().register_count();
193 zvbc_helpers::check_vreg_group_alignment::<Reg, _, _, _>(
194 program_counter,
195 vd,
196 group_regs,
197 )?;
198 zvbc_helpers::check_vreg_group_alignment::<Reg, _, _, _>(
199 program_counter,
200 vs2,
201 group_regs,
202 )?;
203 zvbc_helpers::check_vreg_group_alignment::<Reg, _, _, _>(
204 program_counter,
205 vs1,
206 group_regs,
207 )?;
208 let sew = vtype.vsew();
209 unsafe {
211 zvbc_helpers::execute_vclmulh::<Reg, _, _>(
212 ext_state,
213 vd,
214 vs2,
215 zvbc_helpers::OpSrc::Vreg(vs1),
216 sew,
217 vm,
218 );
219 }
220 }
221 Self::VclmulhVx {
222 vm,
223 vd,
224 vs2,
225 rs1: _,
226 } => {
227 if !ext_state.vector_instructions_allowed() {
228 ::core::hint::cold_path();
229 return Err(ExecutionError::IllegalInstruction {
230 address: program_counter.old_pc(zvexx_helpers::INSTRUCTION_SIZE),
231 });
232 }
233 if !vm && vd == VReg::V0 {
234 ::core::hint::cold_path();
235 return Err(ExecutionError::IllegalInstruction {
236 address: program_counter.old_pc(zvexx_helpers::INSTRUCTION_SIZE),
237 });
238 }
239 let Some(vtype) = ext_state.vtype() else {
240 ::core::hint::cold_path();
241 return Err(ExecutionError::IllegalInstruction {
242 address: program_counter.old_pc(zvexx_helpers::INSTRUCTION_SIZE),
243 });
244 };
245 let group_regs = vtype.vlmul().register_count();
246 zvbc_helpers::check_vreg_group_alignment::<Reg, _, _, _>(
247 program_counter,
248 vd,
249 group_regs,
250 )?;
251 zvbc_helpers::check_vreg_group_alignment::<Reg, _, _, _>(
252 program_counter,
253 vs2,
254 group_regs,
255 )?;
256 let sew = vtype.vsew();
257 let scalar = rs1_value.as_i64().cast_unsigned();
258 unsafe {
260 zvbc_helpers::execute_vclmulh::<Reg, _, _>(
261 ext_state,
262 vd,
263 vs2,
264 zvbc_helpers::OpSrc::Scalar(scalar),
265 sew,
266 vm,
267 );
268 }
269 }
270 }
271 Ok(ControlFlow::Continue(Default::default()))
272 }
273}