1#[cfg(test)]
4mod tests;
5pub mod zvkb_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 ZvkbInstruction<Reg> where Reg: Register {}
33
34#[instruction_execution]
35impl<Reg, ExtState, CustomError> ExecutableInstructionCsr<ExtState, CustomError>
36 for ZvkbInstruction<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 ZvkbInstruction<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::VandnVv { 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 zvkb_helpers::check_vreg_group_alignment::<Reg, _, _, _>(
96 program_counter,
97 vd,
98 group_regs,
99 )?;
100 zvkb_helpers::check_vreg_group_alignment::<Reg, _, _, _>(
101 program_counter,
102 vs2,
103 group_regs,
104 )?;
105 zvkb_helpers::check_vreg_group_alignment::<Reg, _, _, _>(
106 program_counter,
107 vs1,
108 group_regs,
109 )?;
110 let sew = vtype.vsew();
111 unsafe {
113 zvkb_helpers::execute_vandn::<Reg, _, _>(
114 ext_state,
115 vd,
116 vs2,
117 zvkb_helpers::OpSrc::Vreg(vs1),
118 sew,
119 vm,
120 );
121 }
122 }
123 Self::VandnVx {
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 zvkb_helpers::check_vreg_group_alignment::<Reg, _, _, _>(
149 program_counter,
150 vd,
151 group_regs,
152 )?;
153 zvkb_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 zvkb_helpers::execute_vandn::<Reg, _, _>(
163 ext_state,
164 vd,
165 vs2,
166 zvkb_helpers::OpSrc::Scalar(scalar),
167 sew,
168 vm,
169 );
170 }
171 }
172 Self::Vbrev8V { vd, vs2, 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 zvkb_helpers::check_vreg_group_alignment::<Reg, _, _, _>(
194 program_counter,
195 vd,
196 group_regs,
197 )?;
198 zvkb_helpers::check_vreg_group_alignment::<Reg, _, _, _>(
199 program_counter,
200 vs2,
201 group_regs,
202 )?;
203 let sew = vtype.vsew();
204 unsafe {
206 zvkb_helpers::execute_vbrev8::<Reg, _, _>(ext_state, vd, vs2, sew, vm);
207 }
208 }
209 Self::Vrev8V { vd, vs2, vm } => {
211 if !ext_state.vector_instructions_allowed() {
212 ::core::hint::cold_path();
213 return Err(ExecutionError::IllegalInstruction {
214 address: program_counter.old_pc(zvexx_helpers::INSTRUCTION_SIZE),
215 });
216 }
217 if !vm && vd == VReg::V0 {
218 ::core::hint::cold_path();
219 return Err(ExecutionError::IllegalInstruction {
220 address: program_counter.old_pc(zvexx_helpers::INSTRUCTION_SIZE),
221 });
222 }
223 let Some(vtype) = ext_state.vtype() else {
224 ::core::hint::cold_path();
225 return Err(ExecutionError::IllegalInstruction {
226 address: program_counter.old_pc(zvexx_helpers::INSTRUCTION_SIZE),
227 });
228 };
229 let group_regs = vtype.vlmul().register_count();
230 zvkb_helpers::check_vreg_group_alignment::<Reg, _, _, _>(
231 program_counter,
232 vd,
233 group_regs,
234 )?;
235 zvkb_helpers::check_vreg_group_alignment::<Reg, _, _, _>(
236 program_counter,
237 vs2,
238 group_regs,
239 )?;
240 let sew = vtype.vsew();
241 unsafe {
243 zvkb_helpers::execute_vrev8::<Reg, _, _>(ext_state, vd, vs2, sew, vm);
244 }
245 }
246 Self::VrolVv { vd, vs2, vs1, vm } => {
248 if !ext_state.vector_instructions_allowed() {
249 ::core::hint::cold_path();
250 return Err(ExecutionError::IllegalInstruction {
251 address: program_counter.old_pc(zvexx_helpers::INSTRUCTION_SIZE),
252 });
253 }
254 if !vm && vd == VReg::V0 {
255 ::core::hint::cold_path();
256 return Err(ExecutionError::IllegalInstruction {
257 address: program_counter.old_pc(zvexx_helpers::INSTRUCTION_SIZE),
258 });
259 }
260 let Some(vtype) = ext_state.vtype() else {
261 ::core::hint::cold_path();
262 return Err(ExecutionError::IllegalInstruction {
263 address: program_counter.old_pc(zvexx_helpers::INSTRUCTION_SIZE),
264 });
265 };
266 let group_regs = vtype.vlmul().register_count();
267 zvkb_helpers::check_vreg_group_alignment::<Reg, _, _, _>(
268 program_counter,
269 vd,
270 group_regs,
271 )?;
272 zvkb_helpers::check_vreg_group_alignment::<Reg, _, _, _>(
273 program_counter,
274 vs2,
275 group_regs,
276 )?;
277 zvkb_helpers::check_vreg_group_alignment::<Reg, _, _, _>(
278 program_counter,
279 vs1,
280 group_regs,
281 )?;
282 let sew = vtype.vsew();
283 unsafe {
285 zvkb_helpers::execute_vrol::<Reg, _, _>(
286 ext_state,
287 vd,
288 vs2,
289 zvkb_helpers::OpSrc::Vreg(vs1),
290 sew,
291 vm,
292 );
293 }
294 }
295 Self::VrolVx {
296 vm,
297 vd,
298 vs2,
299 rs1: _,
300 } => {
301 if !ext_state.vector_instructions_allowed() {
302 ::core::hint::cold_path();
303 return Err(ExecutionError::IllegalInstruction {
304 address: program_counter.old_pc(zvexx_helpers::INSTRUCTION_SIZE),
305 });
306 }
307 if !vm && vd == VReg::V0 {
308 ::core::hint::cold_path();
309 return Err(ExecutionError::IllegalInstruction {
310 address: program_counter.old_pc(zvexx_helpers::INSTRUCTION_SIZE),
311 });
312 }
313 let Some(vtype) = ext_state.vtype() else {
314 ::core::hint::cold_path();
315 return Err(ExecutionError::IllegalInstruction {
316 address: program_counter.old_pc(zvexx_helpers::INSTRUCTION_SIZE),
317 });
318 };
319 let group_regs = vtype.vlmul().register_count();
320 zvkb_helpers::check_vreg_group_alignment::<Reg, _, _, _>(
321 program_counter,
322 vd,
323 group_regs,
324 )?;
325 zvkb_helpers::check_vreg_group_alignment::<Reg, _, _, _>(
326 program_counter,
327 vs2,
328 group_regs,
329 )?;
330 let sew = vtype.vsew();
331 let scalar = rs1_value.as_i64().cast_unsigned();
332 unsafe {
334 zvkb_helpers::execute_vrol::<Reg, _, _>(
335 ext_state,
336 vd,
337 vs2,
338 zvkb_helpers::OpSrc::Scalar(scalar),
339 sew,
340 vm,
341 );
342 }
343 }
344 Self::VrorVv { vd, vs2, vs1, vm } => {
346 if !ext_state.vector_instructions_allowed() {
347 ::core::hint::cold_path();
348 return Err(ExecutionError::IllegalInstruction {
349 address: program_counter.old_pc(zvexx_helpers::INSTRUCTION_SIZE),
350 });
351 }
352 if !vm && vd == VReg::V0 {
353 ::core::hint::cold_path();
354 return Err(ExecutionError::IllegalInstruction {
355 address: program_counter.old_pc(zvexx_helpers::INSTRUCTION_SIZE),
356 });
357 }
358 let Some(vtype) = ext_state.vtype() else {
359 ::core::hint::cold_path();
360 return Err(ExecutionError::IllegalInstruction {
361 address: program_counter.old_pc(zvexx_helpers::INSTRUCTION_SIZE),
362 });
363 };
364 let group_regs = vtype.vlmul().register_count();
365 zvkb_helpers::check_vreg_group_alignment::<Reg, _, _, _>(
366 program_counter,
367 vd,
368 group_regs,
369 )?;
370 zvkb_helpers::check_vreg_group_alignment::<Reg, _, _, _>(
371 program_counter,
372 vs2,
373 group_regs,
374 )?;
375 zvkb_helpers::check_vreg_group_alignment::<Reg, _, _, _>(
376 program_counter,
377 vs1,
378 group_regs,
379 )?;
380 let sew = vtype.vsew();
381 unsafe {
383 zvkb_helpers::execute_vror::<Reg, _, _>(
384 ext_state,
385 vd,
386 vs2,
387 zvkb_helpers::OpSrc::Vreg(vs1),
388 sew,
389 vm,
390 );
391 }
392 }
393 Self::VrorVx {
394 vm,
395 vd,
396 vs2,
397 rs1: _,
398 } => {
399 if !ext_state.vector_instructions_allowed() {
400 ::core::hint::cold_path();
401 return Err(ExecutionError::IllegalInstruction {
402 address: program_counter.old_pc(zvexx_helpers::INSTRUCTION_SIZE),
403 });
404 }
405 if !vm && vd == VReg::V0 {
406 ::core::hint::cold_path();
407 return Err(ExecutionError::IllegalInstruction {
408 address: program_counter.old_pc(zvexx_helpers::INSTRUCTION_SIZE),
409 });
410 }
411 let Some(vtype) = ext_state.vtype() else {
412 ::core::hint::cold_path();
413 return Err(ExecutionError::IllegalInstruction {
414 address: program_counter.old_pc(zvexx_helpers::INSTRUCTION_SIZE),
415 });
416 };
417 let group_regs = vtype.vlmul().register_count();
418 zvkb_helpers::check_vreg_group_alignment::<Reg, _, _, _>(
419 program_counter,
420 vd,
421 group_regs,
422 )?;
423 zvkb_helpers::check_vreg_group_alignment::<Reg, _, _, _>(
424 program_counter,
425 vs2,
426 group_regs,
427 )?;
428 let sew = vtype.vsew();
429 let scalar = rs1_value.as_i64().cast_unsigned();
430 unsafe {
432 zvkb_helpers::execute_vror::<Reg, _, _>(
433 ext_state,
434 vd,
435 vs2,
436 zvkb_helpers::OpSrc::Scalar(scalar),
437 sew,
438 vm,
439 );
440 }
441 }
442 Self::VrorVi { vd, vs2, uimm, vm } => {
444 if !ext_state.vector_instructions_allowed() {
445 ::core::hint::cold_path();
446 return Err(ExecutionError::IllegalInstruction {
447 address: program_counter.old_pc(zvexx_helpers::INSTRUCTION_SIZE),
448 });
449 }
450 if !vm && vd == VReg::V0 {
451 ::core::hint::cold_path();
452 return Err(ExecutionError::IllegalInstruction {
453 address: program_counter.old_pc(zvexx_helpers::INSTRUCTION_SIZE),
454 });
455 }
456 let Some(vtype) = ext_state.vtype() else {
457 ::core::hint::cold_path();
458 return Err(ExecutionError::IllegalInstruction {
459 address: program_counter.old_pc(zvexx_helpers::INSTRUCTION_SIZE),
460 });
461 };
462 let group_regs = vtype.vlmul().register_count();
463 zvkb_helpers::check_vreg_group_alignment::<Reg, _, _, _>(
464 program_counter,
465 vd,
466 group_regs,
467 )?;
468 zvkb_helpers::check_vreg_group_alignment::<Reg, _, _, _>(
469 program_counter,
470 vs2,
471 group_regs,
472 )?;
473 let sew = vtype.vsew();
474 unsafe {
476 zvkb_helpers::execute_vror::<Reg, _, _>(
477 ext_state,
478 vd,
479 vs2,
480 zvkb_helpers::OpSrc::Scalar(u64::from(uimm)),
481 sew,
482 vm,
483 );
484 }
485 }
486 }
487 Ok(ControlFlow::Continue(Default::default()))
488 }
489}