1#[cfg(test)]
4mod tests;
5pub mod zvbb_helpers;
6pub mod zvkb;
7
8use crate::v::vector_registers::VectorRegistersExt;
9use crate::v::zvexx::arith::zvexx_arith_helpers;
10use crate::v::zvexx::carry::zvexx_carry_helpers;
11use crate::v::zvexx::config::zvexx_config_helpers;
12use crate::v::zvexx::fixed_point::zvexx_fixed_point_helpers;
13use crate::v::zvexx::load::zvexx_load_helpers;
14use crate::v::zvexx::mask::zvexx_mask_helpers;
15use crate::v::zvexx::muldiv::zvexx_muldiv_helpers;
16use crate::v::zvexx::perm::zvexx_perm_helpers;
17use crate::v::zvexx::reduction::zvexx_reduction_helpers;
18use crate::v::zvexx::store::zvexx_store_helpers;
19use crate::v::zvexx::widen_narrow::zvexx_widen_narrow_helpers;
20use crate::v::zvexx::zvexx_helpers;
21use crate::zicsr::zicsr_helpers;
22use crate::zvbb::zvkb::zvkb_helpers;
23use crate::{
24 CsrError, Csrs, ExecutableInstruction, ExecutableInstructionCsr, ExecutableInstructionOperands,
25 ExecutionError, ProgramCounter, RegisterFile, Rs1Rs2OperandValues, Rs1Rs2Operands,
26 VirtualMemory,
27};
28use ab_riscv_macros::instruction_execution;
29use ab_riscv_primitives::prelude::*;
30use core::fmt;
31use core::ops::ControlFlow;
32
33#[instruction_execution]
34impl<Reg> ExecutableInstructionOperands for ZvbbInstruction<Reg> where Reg: Register {}
35
36#[instruction_execution]
37impl<Reg, ExtState, CustomError> ExecutableInstructionCsr<ExtState, CustomError>
38 for ZvbbInstruction<Reg>
39where
40 Reg: Register,
41{
42}
43
44#[instruction_execution]
45impl<Reg, Regs, ExtState, Memory, PC, InstructionHandler, CustomError>
46 ExecutableInstruction<Regs, ExtState, Memory, PC, InstructionHandler, CustomError>
47 for ZvbbInstruction<Reg>
48where
49 Reg: Register,
50 Regs: RegisterFile<Reg>,
51 ExtState: VectorRegistersExt<Reg, CustomError>,
52 [(); ExtState::ELEN as usize]:,
53 [(); ExtState::VLEN as usize]:,
54 [(); ExtState::VLENB as usize]:,
55 Memory: VirtualMemory,
56 PC: ProgramCounter<Reg::Type, Memory, CustomError>,
57 CustomError: fmt::Debug,
58{
59 #[inline(always)]
60 fn execute(
61 self,
62 Rs1Rs2OperandValues {
63 rs1_value,
64 rs2_value,
65 }: Rs1Rs2OperandValues<<Self::Reg as Register>::Type>,
66 _regs: &mut Regs,
67 ext_state: &mut ExtState,
68 memory: &mut Memory,
69 program_counter: &mut PC,
70 _system_instruction_handler: &mut InstructionHandler,
71 ) -> Result<
72 ControlFlow<(), (Self::Reg, <Self::Reg as Register>::Type)>,
73 ExecutionError<Reg::Type, CustomError>,
74 > {
75 match self {
76 Self::VbrevV { vd, vs2, vm } => {
78 if !ext_state.vector_instructions_allowed() {
79 ::core::hint::cold_path();
80 return Err(ExecutionError::IllegalInstruction {
81 address: program_counter.old_pc(zvexx_helpers::INSTRUCTION_SIZE),
82 });
83 }
84 if !vm && vd == VReg::V0 {
85 ::core::hint::cold_path();
86 return Err(ExecutionError::IllegalInstruction {
87 address: program_counter.old_pc(zvexx_helpers::INSTRUCTION_SIZE),
88 });
89 }
90 let Some(vtype) = ext_state.vtype() else {
91 ::core::hint::cold_path();
92 return Err(ExecutionError::IllegalInstruction {
93 address: program_counter.old_pc(zvexx_helpers::INSTRUCTION_SIZE),
94 });
95 };
96 let group_regs = vtype.vlmul().register_count();
97 zvbb_helpers::check_vreg_group_alignment::<Reg, _, _, _>(
98 program_counter,
99 vd,
100 group_regs,
101 )?;
102 zvbb_helpers::check_vreg_group_alignment::<Reg, _, _, _>(
103 program_counter,
104 vs2,
105 group_regs,
106 )?;
107 let sew = vtype.vsew();
108 unsafe {
110 zvbb_helpers::execute_vbrev::<Reg, _, _>(ext_state, vd, vs2, sew, vm);
111 }
112 }
113 Self::VclzV { vd, vs2, vm } => {
115 if !ext_state.vector_instructions_allowed() {
116 ::core::hint::cold_path();
117 return Err(ExecutionError::IllegalInstruction {
118 address: program_counter.old_pc(zvexx_helpers::INSTRUCTION_SIZE),
119 });
120 }
121 if !vm && vd == VReg::V0 {
122 ::core::hint::cold_path();
123 return Err(ExecutionError::IllegalInstruction {
124 address: program_counter.old_pc(zvexx_helpers::INSTRUCTION_SIZE),
125 });
126 }
127 let Some(vtype) = ext_state.vtype() else {
128 ::core::hint::cold_path();
129 return Err(ExecutionError::IllegalInstruction {
130 address: program_counter.old_pc(zvexx_helpers::INSTRUCTION_SIZE),
131 });
132 };
133 let group_regs = vtype.vlmul().register_count();
134 zvbb_helpers::check_vreg_group_alignment::<Reg, _, _, _>(
135 program_counter,
136 vd,
137 group_regs,
138 )?;
139 zvbb_helpers::check_vreg_group_alignment::<Reg, _, _, _>(
140 program_counter,
141 vs2,
142 group_regs,
143 )?;
144 let sew = vtype.vsew();
145 unsafe {
147 zvbb_helpers::execute_vclz::<Reg, _, _>(ext_state, vd, vs2, sew, vm);
148 }
149 }
150 Self::VctzV { vd, vs2, vm } => {
152 if !ext_state.vector_instructions_allowed() {
153 ::core::hint::cold_path();
154 return Err(ExecutionError::IllegalInstruction {
155 address: program_counter.old_pc(zvexx_helpers::INSTRUCTION_SIZE),
156 });
157 }
158 if !vm && vd == VReg::V0 {
159 ::core::hint::cold_path();
160 return Err(ExecutionError::IllegalInstruction {
161 address: program_counter.old_pc(zvexx_helpers::INSTRUCTION_SIZE),
162 });
163 }
164 let Some(vtype) = ext_state.vtype() else {
165 ::core::hint::cold_path();
166 return Err(ExecutionError::IllegalInstruction {
167 address: program_counter.old_pc(zvexx_helpers::INSTRUCTION_SIZE),
168 });
169 };
170 let group_regs = vtype.vlmul().register_count();
171 zvbb_helpers::check_vreg_group_alignment::<Reg, _, _, _>(
172 program_counter,
173 vd,
174 group_regs,
175 )?;
176 zvbb_helpers::check_vreg_group_alignment::<Reg, _, _, _>(
177 program_counter,
178 vs2,
179 group_regs,
180 )?;
181 let sew = vtype.vsew();
182 unsafe {
184 zvbb_helpers::execute_vctz::<Reg, _, _>(ext_state, vd, vs2, sew, vm);
185 }
186 }
187 Self::VcpopV { vd, vs2, vm } => {
189 if !ext_state.vector_instructions_allowed() {
190 ::core::hint::cold_path();
191 return Err(ExecutionError::IllegalInstruction {
192 address: program_counter.old_pc(zvexx_helpers::INSTRUCTION_SIZE),
193 });
194 }
195 if !vm && vd == VReg::V0 {
196 ::core::hint::cold_path();
197 return Err(ExecutionError::IllegalInstruction {
198 address: program_counter.old_pc(zvexx_helpers::INSTRUCTION_SIZE),
199 });
200 }
201 let Some(vtype) = ext_state.vtype() else {
202 ::core::hint::cold_path();
203 return Err(ExecutionError::IllegalInstruction {
204 address: program_counter.old_pc(zvexx_helpers::INSTRUCTION_SIZE),
205 });
206 };
207 let group_regs = vtype.vlmul().register_count();
208 zvbb_helpers::check_vreg_group_alignment::<Reg, _, _, _>(
209 program_counter,
210 vd,
211 group_regs,
212 )?;
213 zvbb_helpers::check_vreg_group_alignment::<Reg, _, _, _>(
214 program_counter,
215 vs2,
216 group_regs,
217 )?;
218 let sew = vtype.vsew();
219 unsafe {
221 zvbb_helpers::execute_vcpop::<Reg, _, _>(ext_state, vd, vs2, sew, vm);
222 }
223 }
224 Self::VwsllVv { vd, vs2, vs1, vm } => {
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 sew = vtype.vsew();
246 let Some(double_sew) = sew.double_width() else {
247 ::core::hint::cold_path();
248 return Err(ExecutionError::IllegalInstruction {
249 address: program_counter.old_pc(zvexx_helpers::INSTRUCTION_SIZE),
250 });
251 };
252 let group_regs = vtype.vlmul().register_count();
253 let Some(dest_group_regs) =
254 vtype.vlmul().data_register_count(double_sew.as_eew(), sew)
255 else {
256 ::core::hint::cold_path();
257 return Err(ExecutionError::IllegalInstruction {
258 address: program_counter.old_pc(zvexx_helpers::INSTRUCTION_SIZE),
259 });
260 };
261 zvbb_helpers::check_vreg_group_alignment::<Reg, _, _, _>(
262 program_counter,
263 vd,
264 dest_group_regs,
265 )?;
266 zvbb_helpers::check_vreg_group_alignment::<Reg, _, _, _>(
267 program_counter,
268 vs2,
269 group_regs,
270 )?;
271 zvbb_helpers::check_vreg_group_alignment::<Reg, _, _, _>(
272 program_counter,
273 vs1,
274 group_regs,
275 )?;
276 unsafe {
278 zvbb_helpers::execute_vwsll::<Reg, _, _>(
279 ext_state,
280 vd,
281 vs2,
282 zvbb_helpers::OpSrc::Vreg(vs1),
283 sew,
284 double_sew,
285 vm,
286 );
287 }
288 }
289 Self::VwsllVx {
290 vm,
291 vd,
292 vs2,
293 rs1: _,
294 } => {
295 if !ext_state.vector_instructions_allowed() {
296 ::core::hint::cold_path();
297 return Err(ExecutionError::IllegalInstruction {
298 address: program_counter.old_pc(zvexx_helpers::INSTRUCTION_SIZE),
299 });
300 }
301 if !vm && vd == VReg::V0 {
302 ::core::hint::cold_path();
303 return Err(ExecutionError::IllegalInstruction {
304 address: program_counter.old_pc(zvexx_helpers::INSTRUCTION_SIZE),
305 });
306 }
307 let Some(vtype) = ext_state.vtype() else {
308 ::core::hint::cold_path();
309 return Err(ExecutionError::IllegalInstruction {
310 address: program_counter.old_pc(zvexx_helpers::INSTRUCTION_SIZE),
311 });
312 };
313 let sew = vtype.vsew();
314 let Some(double_sew) = sew.double_width() else {
315 ::core::hint::cold_path();
316 return Err(ExecutionError::IllegalInstruction {
317 address: program_counter.old_pc(zvexx_helpers::INSTRUCTION_SIZE),
318 });
319 };
320 let group_regs = vtype.vlmul().register_count();
321 let Some(dest_group_regs) =
322 vtype.vlmul().data_register_count(double_sew.as_eew(), sew)
323 else {
324 ::core::hint::cold_path();
325 return Err(ExecutionError::IllegalInstruction {
326 address: program_counter.old_pc(zvexx_helpers::INSTRUCTION_SIZE),
327 });
328 };
329 zvbb_helpers::check_vreg_group_alignment::<Reg, _, _, _>(
330 program_counter,
331 vd,
332 dest_group_regs,
333 )?;
334 zvbb_helpers::check_vreg_group_alignment::<Reg, _, _, _>(
335 program_counter,
336 vs2,
337 group_regs,
338 )?;
339 let scalar = rs1_value.as_i64().cast_unsigned();
340 unsafe {
342 zvbb_helpers::execute_vwsll::<Reg, _, _>(
343 ext_state,
344 vd,
345 vs2,
346 zvbb_helpers::OpSrc::Scalar(scalar),
347 sew,
348 double_sew,
349 vm,
350 );
351 }
352 }
353 Self::VwsllVi { vd, vs2, uimm, vm } => {
355 if !ext_state.vector_instructions_allowed() {
356 ::core::hint::cold_path();
357 return Err(ExecutionError::IllegalInstruction {
358 address: program_counter.old_pc(zvexx_helpers::INSTRUCTION_SIZE),
359 });
360 }
361 if !vm && vd == VReg::V0 {
362 ::core::hint::cold_path();
363 return Err(ExecutionError::IllegalInstruction {
364 address: program_counter.old_pc(zvexx_helpers::INSTRUCTION_SIZE),
365 });
366 }
367 let Some(vtype) = ext_state.vtype() else {
368 ::core::hint::cold_path();
369 return Err(ExecutionError::IllegalInstruction {
370 address: program_counter.old_pc(zvexx_helpers::INSTRUCTION_SIZE),
371 });
372 };
373 let sew = vtype.vsew();
374 let Some(double_sew) = sew.double_width() else {
375 ::core::hint::cold_path();
376 return Err(ExecutionError::IllegalInstruction {
377 address: program_counter.old_pc(zvexx_helpers::INSTRUCTION_SIZE),
378 });
379 };
380 let group_regs = vtype.vlmul().register_count();
381 let Some(dest_group_regs) =
382 vtype.vlmul().data_register_count(double_sew.as_eew(), sew)
383 else {
384 ::core::hint::cold_path();
385 return Err(ExecutionError::IllegalInstruction {
386 address: program_counter.old_pc(zvexx_helpers::INSTRUCTION_SIZE),
387 });
388 };
389 zvbb_helpers::check_vreg_group_alignment::<Reg, _, _, _>(
390 program_counter,
391 vd,
392 dest_group_regs,
393 )?;
394 zvbb_helpers::check_vreg_group_alignment::<Reg, _, _, _>(
395 program_counter,
396 vs2,
397 group_regs,
398 )?;
399 unsafe {
401 zvbb_helpers::execute_vwsll::<Reg, _, _>(
402 ext_state,
403 vd,
404 vs2,
405 zvbb_helpers::OpSrc::Scalar(u64::from(uimm)),
406 sew,
407 double_sew,
408 vm,
409 );
410 }
411 }
412 }
413 Ok(ControlFlow::Continue(Default::default()))
414 }
415}