1#[cfg(test)]
4mod tests;
5pub mod zvexx_perm_helpers;
6
7use crate::v::vector_registers::VectorRegistersExt;
8use crate::v::zvexx::zvexx_helpers;
9use crate::{
10 ExecutableInstruction, ExecutableInstructionCsr, ExecutableInstructionOperands, ExecutionError,
11 ProgramCounter, RegisterFile, Rs1Rs2OperandValues, Rs1Rs2Operands, VirtualMemory,
12};
13use ab_riscv_macros::instruction_execution;
14use ab_riscv_primitives::prelude::*;
15use core::fmt;
16use core::ops::ControlFlow;
17
18#[instruction_execution]
19impl<Reg> ExecutableInstructionOperands for ZveXxPermInstruction<Reg> where Reg: Register {}
20
21#[instruction_execution]
22impl<Reg, ExtState, CustomError> ExecutableInstructionCsr<ExtState, CustomError>
23 for ZveXxPermInstruction<Reg>
24where
25 Reg: Register,
26{
27}
28
29#[instruction_execution]
30impl<Reg, Regs, ExtState, Memory, PC, InstructionHandler, CustomError>
31 ExecutableInstruction<Regs, ExtState, Memory, PC, InstructionHandler, CustomError>
32 for ZveXxPermInstruction<Reg>
33where
34 Reg: Register,
35 Regs: RegisterFile<Reg>,
36 ExtState: VectorRegistersExt<Reg, CustomError>,
37 [(); SUPPORTED_ELEN_VLEN::<{ ExtState::ELEN }, { ExtState::VLEN }>]:,
38 Memory: VirtualMemory,
39 PC: ProgramCounter<Reg::Type, Memory, CustomError>,
40 CustomError: fmt::Debug,
41{
42 #[inline(always)]
43 fn execute(
44 self,
45 Rs1Rs2OperandValues {
46 rs1_value,
47 rs2_value: _,
48 }: Rs1Rs2OperandValues<<Self::Reg as Register>::Type>,
49 _regs: &mut Regs,
50 ext_state: &mut ExtState,
51 _memory: &mut Memory,
52 program_counter: &mut PC,
53 _system_instruction_handler: &mut InstructionHandler,
54 ) -> Result<
55 ControlFlow<(), (Self::Reg, <Self::Reg as Register>::Type)>,
56 ExecutionError<Reg::Type, CustomError>,
57 > {
58 match self {
59 Self::VmvXS { rd, vs2 } => {
65 if !ext_state.vector_instructions_allowed() {
66 ::core::hint::cold_path();
67 return Err(ExecutionError::IllegalInstruction {
68 address: program_counter.old_pc(zvexx_helpers::INSTRUCTION_SIZE),
69 });
70 }
71 let Some(vtype) = ext_state.vtype() else {
72 ::core::hint::cold_path();
73 return Err(ExecutionError::IllegalInstruction {
74 address: program_counter.old_pc(zvexx_helpers::INSTRUCTION_SIZE),
75 });
76 };
77 let sew = vtype.vsew();
78 let raw = unsafe {
81 zvexx_perm_helpers::read_element_0_u64(ext_state.read_vregs(), vs2, sew)
82 };
83 let sign_extended = zvexx_perm_helpers::sign_extend_to_reg::<Reg>(raw, sew);
84 ext_state.mark_vs_dirty();
85 ext_state.reset_vstart();
86
87 return Ok(ControlFlow::Continue((rd, sign_extended)));
88 }
89 Self::VmvSX { vd, rs1: _ } => {
94 if !ext_state.vector_instructions_allowed() {
95 ::core::hint::cold_path();
96 return Err(ExecutionError::IllegalInstruction {
97 address: program_counter.old_pc(zvexx_helpers::INSTRUCTION_SIZE),
98 });
99 }
100 let Some(vtype) = ext_state.vtype() else {
101 ::core::hint::cold_path();
102 return Err(ExecutionError::IllegalInstruction {
103 address: program_counter.old_pc(zvexx_helpers::INSTRUCTION_SIZE),
104 });
105 };
106 let sew = vtype.vsew();
107 let vl = ext_state.vl();
108 let vstart = ext_state.vstart();
109 if vstart < vl {
111 let scalar = rs1_value.as_i64().cast_unsigned();
112 unsafe {
114 zvexx_perm_helpers::write_element_0_u64(
115 ext_state.write_vregs(),
116 vd,
117 sew,
118 scalar,
119 );
120 }
121 }
122 ext_state.mark_vs_dirty();
123 ext_state.reset_vstart();
124 }
125 Self::VslideupVx {
131 vd,
132 vs2,
133 rs1: _,
134 vm,
135 } => {
136 if !ext_state.vector_instructions_allowed() {
137 ::core::hint::cold_path();
138 return Err(ExecutionError::IllegalInstruction {
139 address: program_counter.old_pc(zvexx_helpers::INSTRUCTION_SIZE),
140 });
141 }
142 let Some(vtype) = ext_state.vtype() else {
143 ::core::hint::cold_path();
144 return Err(ExecutionError::IllegalInstruction {
145 address: program_counter.old_pc(zvexx_helpers::INSTRUCTION_SIZE),
146 });
147 };
148 let group_regs = vtype.vlmul().register_count();
149 zvexx_perm_helpers::check_vreg_group_alignment::<Reg, _, _, _>(
150 program_counter,
151 vd,
152 group_regs,
153 )?;
154 zvexx_perm_helpers::check_vreg_group_alignment::<Reg, _, _, _>(
155 program_counter,
156 vs2,
157 group_regs,
158 )?;
159 zvexx_perm_helpers::check_no_overlap::<Reg, _, _, _>(
161 program_counter,
162 vd,
163 vs2,
164 group_regs,
165 )?;
166 if !vm && vd == VReg::V0 {
167 ::core::hint::cold_path();
168 return Err(ExecutionError::IllegalInstruction {
169 address: program_counter.old_pc(zvexx_helpers::INSTRUCTION_SIZE),
170 });
171 }
172 let sew = vtype.vsew();
173 let offset = rs1_value.as_u64();
174 unsafe {
176 zvexx_perm_helpers::execute_slideup(ext_state, vd, vs2, vm, sew, offset);
177 }
178 }
179 Self::VslideupVi { vd, vs2, uimm, vm } => {
182 if !ext_state.vector_instructions_allowed() {
183 ::core::hint::cold_path();
184 return Err(ExecutionError::IllegalInstruction {
185 address: program_counter.old_pc(zvexx_helpers::INSTRUCTION_SIZE),
186 });
187 }
188 let Some(vtype) = ext_state.vtype() else {
189 ::core::hint::cold_path();
190 return Err(ExecutionError::IllegalInstruction {
191 address: program_counter.old_pc(zvexx_helpers::INSTRUCTION_SIZE),
192 });
193 };
194 let group_regs = vtype.vlmul().register_count();
195 zvexx_perm_helpers::check_vreg_group_alignment::<Reg, _, _, _>(
196 program_counter,
197 vd,
198 group_regs,
199 )?;
200 zvexx_perm_helpers::check_vreg_group_alignment::<Reg, _, _, _>(
201 program_counter,
202 vs2,
203 group_regs,
204 )?;
205 zvexx_perm_helpers::check_no_overlap::<Reg, _, _, _>(
206 program_counter,
207 vd,
208 vs2,
209 group_regs,
210 )?;
211 if !vm && vd == VReg::V0 {
212 ::core::hint::cold_path();
213 return Err(ExecutionError::IllegalInstruction {
214 address: program_counter.old_pc(zvexx_helpers::INSTRUCTION_SIZE),
215 });
216 }
217 let sew = vtype.vsew();
218 let offset = u64::from(uimm);
219 unsafe {
221 zvexx_perm_helpers::execute_slideup(ext_state, vd, vs2, vm, sew, offset);
222 }
223 }
224 Self::VslidedownVx {
228 vd,
229 vs2,
230 rs1: _,
231 vm,
232 } => {
233 if !ext_state.vector_instructions_allowed() {
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 zvexx_perm_helpers::check_vreg_group_alignment::<Reg, _, _, _>(
247 program_counter,
248 vd,
249 group_regs,
250 )?;
251 zvexx_perm_helpers::check_vreg_group_alignment::<Reg, _, _, _>(
252 program_counter,
253 vs2,
254 group_regs,
255 )?;
256 if !vm && vd == VReg::V0 {
257 ::core::hint::cold_path();
258 return Err(ExecutionError::IllegalInstruction {
259 address: program_counter.old_pc(zvexx_helpers::INSTRUCTION_SIZE),
260 });
261 }
262 let sew = vtype.vsew();
263 let vlmax = ext_state.vlmax_for_vtype(vtype);
264 let offset = rs1_value.as_u64();
265 unsafe {
267 zvexx_perm_helpers::execute_slidedown(
268 ext_state, vd, vs2, vm, sew, vlmax, offset,
269 );
270 }
271 }
272 Self::VslidedownVi { vd, vs2, uimm, vm } => {
275 if !ext_state.vector_instructions_allowed() {
276 ::core::hint::cold_path();
277 return Err(ExecutionError::IllegalInstruction {
278 address: program_counter.old_pc(zvexx_helpers::INSTRUCTION_SIZE),
279 });
280 }
281 let Some(vtype) = ext_state.vtype() else {
282 ::core::hint::cold_path();
283 return Err(ExecutionError::IllegalInstruction {
284 address: program_counter.old_pc(zvexx_helpers::INSTRUCTION_SIZE),
285 });
286 };
287 let group_regs = vtype.vlmul().register_count();
288 zvexx_perm_helpers::check_vreg_group_alignment::<Reg, _, _, _>(
289 program_counter,
290 vd,
291 group_regs,
292 )?;
293 zvexx_perm_helpers::check_vreg_group_alignment::<Reg, _, _, _>(
294 program_counter,
295 vs2,
296 group_regs,
297 )?;
298 if !vm && vd == VReg::V0 {
299 ::core::hint::cold_path();
300 return Err(ExecutionError::IllegalInstruction {
301 address: program_counter.old_pc(zvexx_helpers::INSTRUCTION_SIZE),
302 });
303 }
304 let sew = vtype.vsew();
305 let vlmax = ext_state.vlmax_for_vtype(vtype);
306 let offset = u64::from(uimm);
307 unsafe {
309 zvexx_perm_helpers::execute_slidedown(
310 ext_state, vd, vs2, vm, sew, vlmax, offset,
311 );
312 }
313 }
314 Self::Vslide1upVx {
319 vd,
320 vs2,
321 rs1: _,
322 vm,
323 } => {
324 if !ext_state.vector_instructions_allowed() {
325 ::core::hint::cold_path();
326 return Err(ExecutionError::IllegalInstruction {
327 address: program_counter.old_pc(zvexx_helpers::INSTRUCTION_SIZE),
328 });
329 }
330 let Some(vtype) = ext_state.vtype() else {
331 ::core::hint::cold_path();
332 return Err(ExecutionError::IllegalInstruction {
333 address: program_counter.old_pc(zvexx_helpers::INSTRUCTION_SIZE),
334 });
335 };
336 let group_regs = vtype.vlmul().register_count();
337 zvexx_perm_helpers::check_vreg_group_alignment::<Reg, _, _, _>(
338 program_counter,
339 vd,
340 group_regs,
341 )?;
342 zvexx_perm_helpers::check_vreg_group_alignment::<Reg, _, _, _>(
343 program_counter,
344 vs2,
345 group_regs,
346 )?;
347 zvexx_perm_helpers::check_no_overlap::<Reg, _, _, _>(
348 program_counter,
349 vd,
350 vs2,
351 group_regs,
352 )?;
353 if !vm && vd == VReg::V0 {
354 ::core::hint::cold_path();
355 return Err(ExecutionError::IllegalInstruction {
356 address: program_counter.old_pc(zvexx_helpers::INSTRUCTION_SIZE),
357 });
358 }
359 let sew = vtype.vsew();
360 let scalar = rs1_value.as_i64().cast_unsigned();
361 unsafe {
363 zvexx_perm_helpers::execute_slide1up(ext_state, vd, vs2, vm, sew, scalar);
364 }
365 }
366 Self::Vslide1downVx {
371 vd,
372 vs2,
373 rs1: _,
374 vm,
375 } => {
376 if !ext_state.vector_instructions_allowed() {
377 ::core::hint::cold_path();
378 return Err(ExecutionError::IllegalInstruction {
379 address: program_counter.old_pc(zvexx_helpers::INSTRUCTION_SIZE),
380 });
381 }
382 let Some(vtype) = ext_state.vtype() else {
383 ::core::hint::cold_path();
384 return Err(ExecutionError::IllegalInstruction {
385 address: program_counter.old_pc(zvexx_helpers::INSTRUCTION_SIZE),
386 });
387 };
388 let group_regs = vtype.vlmul().register_count();
389 zvexx_perm_helpers::check_vreg_group_alignment::<Reg, _, _, _>(
390 program_counter,
391 vd,
392 group_regs,
393 )?;
394 zvexx_perm_helpers::check_vreg_group_alignment::<Reg, _, _, _>(
395 program_counter,
396 vs2,
397 group_regs,
398 )?;
399 if !vm && vd == VReg::V0 {
400 ::core::hint::cold_path();
401 return Err(ExecutionError::IllegalInstruction {
402 address: program_counter.old_pc(zvexx_helpers::INSTRUCTION_SIZE),
403 });
404 }
405 let sew = vtype.vsew();
406 let scalar = rs1_value.as_i64().cast_unsigned();
407 unsafe {
409 zvexx_perm_helpers::execute_slide1down(ext_state, vd, vs2, vm, sew, scalar);
410 }
411 }
412 Self::VrgatherVv { vd, vs2, vs1, vm } => {
416 if !ext_state.vector_instructions_allowed() {
417 ::core::hint::cold_path();
418 return Err(ExecutionError::IllegalInstruction {
419 address: program_counter.old_pc(zvexx_helpers::INSTRUCTION_SIZE),
420 });
421 }
422 let Some(vtype) = ext_state.vtype() else {
423 ::core::hint::cold_path();
424 return Err(ExecutionError::IllegalInstruction {
425 address: program_counter.old_pc(zvexx_helpers::INSTRUCTION_SIZE),
426 });
427 };
428 let group_regs = vtype.vlmul().register_count();
429 zvexx_perm_helpers::check_vreg_group_alignment::<Reg, _, _, _>(
430 program_counter,
431 vd,
432 group_regs,
433 )?;
434 zvexx_perm_helpers::check_vreg_group_alignment::<Reg, _, _, _>(
435 program_counter,
436 vs2,
437 group_regs,
438 )?;
439 zvexx_perm_helpers::check_vreg_group_alignment::<Reg, _, _, _>(
440 program_counter,
441 vs1,
442 group_regs,
443 )?;
444 zvexx_perm_helpers::check_no_overlap::<Reg, _, _, _>(
445 program_counter,
446 vd,
447 vs2,
448 group_regs,
449 )?;
450 zvexx_perm_helpers::check_no_overlap::<Reg, _, _, _>(
451 program_counter,
452 vd,
453 vs1,
454 group_regs,
455 )?;
456 if !vm && vd == VReg::V0 {
457 ::core::hint::cold_path();
458 return Err(ExecutionError::IllegalInstruction {
459 address: program_counter.old_pc(zvexx_helpers::INSTRUCTION_SIZE),
460 });
461 }
462 let sew = vtype.vsew();
463 let vlmax = ext_state.vlmax_for_vtype(vtype);
464 unsafe {
466 zvexx_perm_helpers::execute_rgather_vv(ext_state, vd, vs2, vs1, vm, sew, vlmax);
467 }
468 }
469 Self::VrgatherVx {
473 vd,
474 vs2,
475 rs1: _,
476 vm,
477 } => {
478 if !ext_state.vector_instructions_allowed() {
479 ::core::hint::cold_path();
480 return Err(ExecutionError::IllegalInstruction {
481 address: program_counter.old_pc(zvexx_helpers::INSTRUCTION_SIZE),
482 });
483 }
484 let Some(vtype) = ext_state.vtype() else {
485 ::core::hint::cold_path();
486 return Err(ExecutionError::IllegalInstruction {
487 address: program_counter.old_pc(zvexx_helpers::INSTRUCTION_SIZE),
488 });
489 };
490 let group_regs = vtype.vlmul().register_count();
491 zvexx_perm_helpers::check_vreg_group_alignment::<Reg, _, _, _>(
492 program_counter,
493 vd,
494 group_regs,
495 )?;
496 zvexx_perm_helpers::check_vreg_group_alignment::<Reg, _, _, _>(
497 program_counter,
498 vs2,
499 group_regs,
500 )?;
501 zvexx_perm_helpers::check_no_overlap::<Reg, _, _, _>(
502 program_counter,
503 vd,
504 vs2,
505 group_regs,
506 )?;
507 if !vm && vd == VReg::V0 {
508 ::core::hint::cold_path();
509 return Err(ExecutionError::IllegalInstruction {
510 address: program_counter.old_pc(zvexx_helpers::INSTRUCTION_SIZE),
511 });
512 }
513 let sew = vtype.vsew();
514 let vlmax = ext_state.vlmax_for_vtype(vtype);
515 let index = rs1_value.as_u64();
516 unsafe {
518 zvexx_perm_helpers::execute_rgather_scalar(
519 ext_state, vd, vs2, vm, sew, vlmax, index,
520 );
521 }
522 }
523 Self::VrgatherVi { vd, vs2, uimm, vm } => {
526 if !ext_state.vector_instructions_allowed() {
527 ::core::hint::cold_path();
528 return Err(ExecutionError::IllegalInstruction {
529 address: program_counter.old_pc(zvexx_helpers::INSTRUCTION_SIZE),
530 });
531 }
532 let Some(vtype) = ext_state.vtype() else {
533 ::core::hint::cold_path();
534 return Err(ExecutionError::IllegalInstruction {
535 address: program_counter.old_pc(zvexx_helpers::INSTRUCTION_SIZE),
536 });
537 };
538 let group_regs = vtype.vlmul().register_count();
539 zvexx_perm_helpers::check_vreg_group_alignment::<Reg, _, _, _>(
540 program_counter,
541 vd,
542 group_regs,
543 )?;
544 zvexx_perm_helpers::check_vreg_group_alignment::<Reg, _, _, _>(
545 program_counter,
546 vs2,
547 group_regs,
548 )?;
549 zvexx_perm_helpers::check_no_overlap::<Reg, _, _, _>(
550 program_counter,
551 vd,
552 vs2,
553 group_regs,
554 )?;
555 if !vm && vd == VReg::V0 {
556 ::core::hint::cold_path();
557 return Err(ExecutionError::IllegalInstruction {
558 address: program_counter.old_pc(zvexx_helpers::INSTRUCTION_SIZE),
559 });
560 }
561 let sew = vtype.vsew();
562 let vlmax = ext_state.vlmax_for_vtype(vtype);
563 let index = u64::from(uimm);
564 unsafe {
566 zvexx_perm_helpers::execute_rgather_scalar(
567 ext_state, vd, vs2, vm, sew, vlmax, index,
568 );
569 }
570 }
571 Self::Vrgatherei16Vv { vd, vs2, vs1, vm } => {
576 if !ext_state.vector_instructions_allowed() {
577 ::core::hint::cold_path();
578 return Err(ExecutionError::IllegalInstruction {
579 address: program_counter.old_pc(zvexx_helpers::INSTRUCTION_SIZE),
580 });
581 }
582 let Some(vtype) = ext_state.vtype() else {
583 ::core::hint::cold_path();
584 return Err(ExecutionError::IllegalInstruction {
585 address: program_counter.old_pc(zvexx_helpers::INSTRUCTION_SIZE),
586 });
587 };
588 let group_regs = vtype.vlmul().register_count();
589 zvexx_perm_helpers::check_vreg_group_alignment::<Reg, _, _, _>(
590 program_counter,
591 vd,
592 group_regs,
593 )?;
594 zvexx_perm_helpers::check_vreg_group_alignment::<Reg, _, _, _>(
595 program_counter,
596 vs2,
597 group_regs,
598 )?;
599 let index_group_regs = vtype
601 .vlmul()
602 .index_register_count(
603 ab_riscv_primitives::instructions::v::Eew::E16,
604 vtype.vsew(),
605 )
606 .ok_or(ExecutionError::IllegalInstruction {
607 address: program_counter.old_pc(zvexx_helpers::INSTRUCTION_SIZE),
608 })?;
609 zvexx_perm_helpers::check_vreg_group_alignment::<Reg, _, _, _>(
610 program_counter,
611 vs1,
612 index_group_regs,
613 )?;
614 zvexx_perm_helpers::check_no_overlap::<Reg, _, _, _>(
615 program_counter,
616 vd,
617 vs2,
618 group_regs,
619 )?;
620 zvexx_perm_helpers::check_no_overlap_asymmetric::<Reg, _, _, _>(
623 program_counter,
624 vd,
625 group_regs,
626 vs1,
627 index_group_regs,
628 )?;
629 if !vm && vd == VReg::V0 {
630 ::core::hint::cold_path();
631 return Err(ExecutionError::IllegalInstruction {
632 address: program_counter.old_pc(zvexx_helpers::INSTRUCTION_SIZE),
633 });
634 }
635 let sew = vtype.vsew();
636 let vlmax = ext_state.vlmax_for_vtype(vtype);
637 unsafe {
640 zvexx_perm_helpers::execute_rgatherei16(
641 ext_state,
642 vd,
643 vs2,
644 vs1,
645 vm,
646 sew,
647 vlmax,
648 index_group_regs,
649 );
650 }
651 }
652 Self::VmergeVvm { vd, vs2, vs1, vm } => {
659 if !ext_state.vector_instructions_allowed() {
660 ::core::hint::cold_path();
661 return Err(ExecutionError::IllegalInstruction {
662 address: program_counter.old_pc(zvexx_helpers::INSTRUCTION_SIZE),
663 });
664 }
665 let Some(vtype) = ext_state.vtype() else {
666 ::core::hint::cold_path();
667 return Err(ExecutionError::IllegalInstruction {
668 address: program_counter.old_pc(zvexx_helpers::INSTRUCTION_SIZE),
669 });
670 };
671 let group_regs = vtype.vlmul().register_count();
672 zvexx_perm_helpers::check_vreg_group_alignment::<Reg, _, _, _>(
673 program_counter,
674 vd,
675 group_regs,
676 )?;
677 zvexx_perm_helpers::check_vreg_group_alignment::<Reg, _, _, _>(
678 program_counter,
679 vs1,
680 group_regs,
681 )?;
682 if !vm {
683 zvexx_perm_helpers::check_vreg_group_alignment::<Reg, _, _, _>(
685 program_counter,
686 vs2,
687 group_regs,
688 )?;
689 zvexx_perm_helpers::check_no_overlap::<Reg, _, _, _>(
690 program_counter,
691 vd,
692 VReg::V0,
693 group_regs,
694 )?;
695 }
696 let sew = vtype.vsew();
697 unsafe {
699 zvexx_perm_helpers::execute_merge_vv(ext_state, vd, vs2, vs1, vm, sew);
700 }
701 }
702 Self::VmergeVxm {
706 vd,
707 vs2,
708 rs1: _,
709 vm,
710 } => {
711 if !ext_state.vector_instructions_allowed() {
712 ::core::hint::cold_path();
713 return Err(ExecutionError::IllegalInstruction {
714 address: program_counter.old_pc(zvexx_helpers::INSTRUCTION_SIZE),
715 });
716 }
717 let Some(vtype) = ext_state.vtype() else {
718 ::core::hint::cold_path();
719 return Err(ExecutionError::IllegalInstruction {
720 address: program_counter.old_pc(zvexx_helpers::INSTRUCTION_SIZE),
721 });
722 };
723 let group_regs = vtype.vlmul().register_count();
724 zvexx_perm_helpers::check_vreg_group_alignment::<Reg, _, _, _>(
725 program_counter,
726 vd,
727 group_regs,
728 )?;
729 if !vm {
730 zvexx_perm_helpers::check_vreg_group_alignment::<Reg, _, _, _>(
731 program_counter,
732 vs2,
733 group_regs,
734 )?;
735 zvexx_perm_helpers::check_no_overlap::<Reg, _, _, _>(
736 program_counter,
737 vd,
738 VReg::V0,
739 group_regs,
740 )?;
741 }
742 let sew = vtype.vsew();
743 let scalar = rs1_value.as_i64().cast_unsigned();
744 unsafe {
746 zvexx_perm_helpers::execute_merge_scalar(ext_state, vd, vs2, vm, sew, scalar);
747 }
748 }
749 Self::VmergeVim { vd, vs2, simm5, vm } => {
753 if !ext_state.vector_instructions_allowed() {
754 ::core::hint::cold_path();
755 return Err(ExecutionError::IllegalInstruction {
756 address: program_counter.old_pc(zvexx_helpers::INSTRUCTION_SIZE),
757 });
758 }
759 let Some(vtype) = ext_state.vtype() else {
760 ::core::hint::cold_path();
761 return Err(ExecutionError::IllegalInstruction {
762 address: program_counter.old_pc(zvexx_helpers::INSTRUCTION_SIZE),
763 });
764 };
765 let group_regs = vtype.vlmul().register_count();
766 zvexx_perm_helpers::check_vreg_group_alignment::<Reg, _, _, _>(
767 program_counter,
768 vd,
769 group_regs,
770 )?;
771 if !vm {
772 zvexx_perm_helpers::check_vreg_group_alignment::<Reg, _, _, _>(
773 program_counter,
774 vs2,
775 group_regs,
776 )?;
777 zvexx_perm_helpers::check_no_overlap::<Reg, _, _, _>(
778 program_counter,
779 vd,
780 VReg::V0,
781 group_regs,
782 )?;
783 }
784 let sew = vtype.vsew();
785 let scalar = i64::from(simm5).cast_unsigned();
787 unsafe {
789 zvexx_perm_helpers::execute_merge_scalar(ext_state, vd, vs2, vm, sew, scalar);
790 }
791 }
792 Self::VcompressVm { vd, vs2, vs1 } => {
797 if !ext_state.vector_instructions_allowed() {
798 ::core::hint::cold_path();
799 return Err(ExecutionError::IllegalInstruction {
800 address: program_counter.old_pc(zvexx_helpers::INSTRUCTION_SIZE),
801 });
802 }
803 let Some(vtype) = ext_state.vtype() else {
804 ::core::hint::cold_path();
805 return Err(ExecutionError::IllegalInstruction {
806 address: program_counter.old_pc(zvexx_helpers::INSTRUCTION_SIZE),
807 });
808 };
809 if ext_state.vstart() != Vstart::ZERO {
811 ::core::hint::cold_path();
812 return Err(ExecutionError::IllegalInstruction {
813 address: program_counter.old_pc(zvexx_helpers::INSTRUCTION_SIZE),
814 });
815 }
816 let group_regs = vtype.vlmul().register_count();
817 zvexx_perm_helpers::check_vreg_group_alignment::<Reg, _, _, _>(
818 program_counter,
819 vd,
820 group_regs,
821 )?;
822 zvexx_perm_helpers::check_vreg_group_alignment::<Reg, _, _, _>(
823 program_counter,
824 vs2,
825 group_regs,
826 )?;
827 zvexx_perm_helpers::check_no_overlap::<Reg, _, _, _>(
829 program_counter,
830 vd,
831 vs2,
832 group_regs,
833 )?;
834 zvexx_perm_helpers::check_no_overlap::<Reg, _, _, _>(
836 program_counter,
837 vd,
838 vs1,
839 ::core::num::NonZeroU8::new(1).expect("Not zero; qed"),
840 )?;
841 let sew = vtype.vsew();
842 let vl = ext_state.vl();
843 unsafe {
844 zvexx_perm_helpers::execute_compress(ext_state, vd, vs2, vs1, vl, sew);
845 }
846 }
847 Self::Vmv1rV { vd, vs2 } => {
851 if !ext_state.vector_instructions_allowed() {
852 ::core::hint::cold_path();
853 return Err(ExecutionError::IllegalInstruction {
854 address: program_counter.old_pc(zvexx_helpers::INSTRUCTION_SIZE),
855 });
856 }
857 unsafe {
860 zvexx_perm_helpers::execute_whole_reg_move::<1, _>(
861 ext_state.write_vregs(),
862 vd,
863 vs2,
864 );
865 }
866 ext_state.mark_vs_dirty();
867 ext_state.reset_vstart();
868 }
869 Self::Vmv2rV { vd, vs2 } => {
873 if !ext_state.vector_instructions_allowed() {
874 ::core::hint::cold_path();
875 return Err(ExecutionError::IllegalInstruction {
876 address: program_counter.old_pc(zvexx_helpers::INSTRUCTION_SIZE),
877 });
878 }
879 if !vd.to_bits().is_multiple_of(2) || !vs2.to_bits().is_multiple_of(2) {
880 ::core::hint::cold_path();
881 return Err(ExecutionError::IllegalInstruction {
882 address: program_counter.old_pc(zvexx_helpers::INSTRUCTION_SIZE),
883 });
884 }
885 unsafe {
887 zvexx_perm_helpers::execute_whole_reg_move::<2, _>(
888 ext_state.write_vregs(),
889 vd,
890 vs2,
891 );
892 }
893 ext_state.mark_vs_dirty();
894 ext_state.reset_vstart();
895 }
896 Self::Vmv4rV { vd, vs2 } => {
899 if !ext_state.vector_instructions_allowed() {
900 ::core::hint::cold_path();
901 return Err(ExecutionError::IllegalInstruction {
902 address: program_counter.old_pc(zvexx_helpers::INSTRUCTION_SIZE),
903 });
904 }
905 if !vd.to_bits().is_multiple_of(4) || !vs2.to_bits().is_multiple_of(4) {
906 ::core::hint::cold_path();
907 return Err(ExecutionError::IllegalInstruction {
908 address: program_counter.old_pc(zvexx_helpers::INSTRUCTION_SIZE),
909 });
910 }
911 unsafe {
913 zvexx_perm_helpers::execute_whole_reg_move::<4, _>(
914 ext_state.write_vregs(),
915 vd,
916 vs2,
917 );
918 }
919 ext_state.mark_vs_dirty();
920 ext_state.reset_vstart();
921 }
922 Self::Vmv8rV { vd, vs2 } => {
925 if !ext_state.vector_instructions_allowed() {
926 ::core::hint::cold_path();
927 return Err(ExecutionError::IllegalInstruction {
928 address: program_counter.old_pc(zvexx_helpers::INSTRUCTION_SIZE),
929 });
930 }
931 if !vd.to_bits().is_multiple_of(8) || !vs2.to_bits().is_multiple_of(8) {
932 ::core::hint::cold_path();
933 return Err(ExecutionError::IllegalInstruction {
934 address: program_counter.old_pc(zvexx_helpers::INSTRUCTION_SIZE),
935 });
936 }
937 unsafe {
939 zvexx_perm_helpers::execute_whole_reg_move::<8, _>(
940 ext_state.write_vregs(),
941 vd,
942 vs2,
943 );
944 }
945 ext_state.mark_vs_dirty();
946 ext_state.reset_vstart();
947 }
948 }
949
950 Ok(ControlFlow::Continue(Default::default()))
951 }
952}