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 ExecutionResult, FetchInstructionResult, InstructionFetcher, OpaqueThreadedExecutionResult,
12 PackedAddress, ProgramCounter, RegisterFile, Rs1Rs2OperandValues, Rs1Rs2Operands,
13 ThreadedExecutableInstruction, ThreadedExecutionResult, VirtualMemory,
14};
15use ab_riscv_macros::instruction_execution;
16use ab_riscv_primitives::prelude::*;
17
18#[instruction_execution]
19const impl<Reg> ExecutableInstructionOperands for ZveXxPermInstruction<Reg> where Reg: Register {}
20
21#[instruction_execution]
22const impl<Reg, Env> ExecutableInstructionCsr<Env> for ZveXxPermInstruction<Reg> where Reg: Register {}
23
24#[instruction_execution]
25impl<Reg, Regs, Env, Memory, PC> ExecutableInstruction<Regs, Env, Memory, PC>
26 for ZveXxPermInstruction<Reg>
27where
28 Reg: Register,
29 Regs: RegisterFile<Reg>,
30 Env: VectorRegistersExt<Reg>,
31 [(); SUPPORTED_ELEN_VLEN::<{ Env::ELEN }, { Env::VLEN }>]:,
32 Memory: VirtualMemory,
33 PC: ProgramCounter<Reg::Type, Memory>,
34{
35 #[inline(always)]
36 #[cfg_attr(feature = "no-panic", no_panic_const::no_panic)]
37 fn execute(
38 self,
39 Rs1Rs2OperandValues {
40 rs1_value,
41 rs2_value: _,
42 }: Rs1Rs2OperandValues<<Self::Reg as Register>::Type>,
43 _regs: &mut Regs,
44 env: &mut Env,
45 _memory: &mut Memory,
46 program_counter: &mut PC,
47 ) -> ExecutionResult<Self::Reg> {
48 match self {
49 Self::VmvXS { rd, vs2 } => {
55 if !env.vector_instructions_allowed() {
56 ::core::hint::cold_path();
57 return ExecutionResult::Err(ExecutionError::IllegalInstruction {
58 address: PackedAddress::new(
59 program_counter.old_pc(zvexx_helpers::INSTRUCTION_SIZE),
60 ),
61 });
62 }
63 let Some(vtype) = env.vtype() else {
64 ::core::hint::cold_path();
65 return ExecutionResult::Err(ExecutionError::IllegalInstruction {
66 address: PackedAddress::new(
67 program_counter.old_pc(zvexx_helpers::INSTRUCTION_SIZE),
68 ),
69 });
70 };
71 let sew = vtype.vsew();
72 let raw = unsafe { env.read_vregs().read_element(vs2, 0, sew) };
75 let sign_extended = zvexx_perm_helpers::sign_extend_to_reg::<Reg>(raw, sew);
76 env.mark_vs_dirty();
77 env.reset_vstart();
78
79 return ExecutionResult::Continue {
80 rd,
81 value: sign_extended,
82 };
83 }
84 Self::VmvSX { vd, rs1: _ } => {
89 if !env.vector_instructions_allowed() {
90 ::core::hint::cold_path();
91 return ExecutionResult::Err(ExecutionError::IllegalInstruction {
92 address: PackedAddress::new(
93 program_counter.old_pc(zvexx_helpers::INSTRUCTION_SIZE),
94 ),
95 });
96 }
97 let Some(vtype) = env.vtype() else {
98 ::core::hint::cold_path();
99 return ExecutionResult::Err(ExecutionError::IllegalInstruction {
100 address: PackedAddress::new(
101 program_counter.old_pc(zvexx_helpers::INSTRUCTION_SIZE),
102 ),
103 });
104 };
105 let sew = vtype.vsew();
106 let vl = env.vl();
107 let vstart = env.vstart();
108 if vstart < vl {
110 let scalar = rs1_value.as_i64().cast_unsigned();
111 unsafe {
113 env.write_vregs().write_element(vd, 0, sew, scalar);
114 }
115 }
116 env.mark_vs_dirty();
117 env.reset_vstart();
118 }
119 Self::VslideupVx {
125 vd,
126 vs2,
127 rs1: _,
128 vm,
129 } => {
130 if !env.vector_instructions_allowed() {
131 ::core::hint::cold_path();
132 return ExecutionResult::Err(ExecutionError::IllegalInstruction {
133 address: PackedAddress::new(
134 program_counter.old_pc(zvexx_helpers::INSTRUCTION_SIZE),
135 ),
136 });
137 }
138 let Some(vtype) = env.vtype() else {
139 ::core::hint::cold_path();
140 return ExecutionResult::Err(ExecutionError::IllegalInstruction {
141 address: PackedAddress::new(
142 program_counter.old_pc(zvexx_helpers::INSTRUCTION_SIZE),
143 ),
144 });
145 };
146 let group_regs = vtype.vlmul().register_count();
147 zvexx_perm_helpers::check_vreg_group_alignment::<Reg, _, _>(
148 program_counter,
149 vd,
150 group_regs,
151 )?;
152 zvexx_perm_helpers::check_vreg_group_alignment::<Reg, _, _>(
153 program_counter,
154 vs2,
155 group_regs,
156 )?;
157 zvexx_perm_helpers::check_no_overlap::<Reg, _, _>(
159 program_counter,
160 vd,
161 vs2,
162 group_regs,
163 )?;
164 if !vm && vd == VReg::V0 {
165 ::core::hint::cold_path();
166 return ExecutionResult::Err(ExecutionError::IllegalInstruction {
167 address: PackedAddress::new(
168 program_counter.old_pc(zvexx_helpers::INSTRUCTION_SIZE),
169 ),
170 });
171 }
172 let sew = vtype.vsew();
173 let offset = rs1_value.as_u64();
174 unsafe {
176 zvexx_perm_helpers::execute_slideup(env, vd, vs2, vm, sew, offset);
177 }
178 }
179 Self::VslideupVi { vd, vs2, uimm, vm } => {
182 if !env.vector_instructions_allowed() {
183 ::core::hint::cold_path();
184 return ExecutionResult::Err(ExecutionError::IllegalInstruction {
185 address: PackedAddress::new(
186 program_counter.old_pc(zvexx_helpers::INSTRUCTION_SIZE),
187 ),
188 });
189 }
190 let Some(vtype) = env.vtype() else {
191 ::core::hint::cold_path();
192 return ExecutionResult::Err(ExecutionError::IllegalInstruction {
193 address: PackedAddress::new(
194 program_counter.old_pc(zvexx_helpers::INSTRUCTION_SIZE),
195 ),
196 });
197 };
198 let group_regs = vtype.vlmul().register_count();
199 zvexx_perm_helpers::check_vreg_group_alignment::<Reg, _, _>(
200 program_counter,
201 vd,
202 group_regs,
203 )?;
204 zvexx_perm_helpers::check_vreg_group_alignment::<Reg, _, _>(
205 program_counter,
206 vs2,
207 group_regs,
208 )?;
209 zvexx_perm_helpers::check_no_overlap::<Reg, _, _>(
210 program_counter,
211 vd,
212 vs2,
213 group_regs,
214 )?;
215 if !vm && vd == VReg::V0 {
216 ::core::hint::cold_path();
217 return ExecutionResult::Err(ExecutionError::IllegalInstruction {
218 address: PackedAddress::new(
219 program_counter.old_pc(zvexx_helpers::INSTRUCTION_SIZE),
220 ),
221 });
222 }
223 let sew = vtype.vsew();
224 let offset = u64::from(uimm);
225 unsafe {
227 zvexx_perm_helpers::execute_slideup(env, vd, vs2, vm, sew, offset);
228 }
229 }
230 Self::VslidedownVx {
234 vd,
235 vs2,
236 rs1: _,
237 vm,
238 } => {
239 if !env.vector_instructions_allowed() {
240 ::core::hint::cold_path();
241 return ExecutionResult::Err(ExecutionError::IllegalInstruction {
242 address: PackedAddress::new(
243 program_counter.old_pc(zvexx_helpers::INSTRUCTION_SIZE),
244 ),
245 });
246 }
247 let Some(vtype) = env.vtype() else {
248 ::core::hint::cold_path();
249 return ExecutionResult::Err(ExecutionError::IllegalInstruction {
250 address: PackedAddress::new(
251 program_counter.old_pc(zvexx_helpers::INSTRUCTION_SIZE),
252 ),
253 });
254 };
255 let group_regs = vtype.vlmul().register_count();
256 zvexx_perm_helpers::check_vreg_group_alignment::<Reg, _, _>(
257 program_counter,
258 vd,
259 group_regs,
260 )?;
261 zvexx_perm_helpers::check_vreg_group_alignment::<Reg, _, _>(
262 program_counter,
263 vs2,
264 group_regs,
265 )?;
266 if !vm && vd == VReg::V0 {
267 ::core::hint::cold_path();
268 return ExecutionResult::Err(ExecutionError::IllegalInstruction {
269 address: PackedAddress::new(
270 program_counter.old_pc(zvexx_helpers::INSTRUCTION_SIZE),
271 ),
272 });
273 }
274 let sew = vtype.vsew();
275 let vlmax = env.vlmax_for_vtype(vtype);
276 let offset = rs1_value.as_u64();
277 unsafe {
279 zvexx_perm_helpers::execute_slidedown(env, vd, vs2, vm, sew, vlmax, offset);
280 }
281 }
282 Self::VslidedownVi { vd, vs2, uimm, vm } => {
285 if !env.vector_instructions_allowed() {
286 ::core::hint::cold_path();
287 return ExecutionResult::Err(ExecutionError::IllegalInstruction {
288 address: PackedAddress::new(
289 program_counter.old_pc(zvexx_helpers::INSTRUCTION_SIZE),
290 ),
291 });
292 }
293 let Some(vtype) = env.vtype() else {
294 ::core::hint::cold_path();
295 return ExecutionResult::Err(ExecutionError::IllegalInstruction {
296 address: PackedAddress::new(
297 program_counter.old_pc(zvexx_helpers::INSTRUCTION_SIZE),
298 ),
299 });
300 };
301 let group_regs = vtype.vlmul().register_count();
302 zvexx_perm_helpers::check_vreg_group_alignment::<Reg, _, _>(
303 program_counter,
304 vd,
305 group_regs,
306 )?;
307 zvexx_perm_helpers::check_vreg_group_alignment::<Reg, _, _>(
308 program_counter,
309 vs2,
310 group_regs,
311 )?;
312 if !vm && vd == VReg::V0 {
313 ::core::hint::cold_path();
314 return ExecutionResult::Err(ExecutionError::IllegalInstruction {
315 address: PackedAddress::new(
316 program_counter.old_pc(zvexx_helpers::INSTRUCTION_SIZE),
317 ),
318 });
319 }
320 let sew = vtype.vsew();
321 let vlmax = env.vlmax_for_vtype(vtype);
322 let offset = u64::from(uimm);
323 unsafe {
325 zvexx_perm_helpers::execute_slidedown(env, vd, vs2, vm, sew, vlmax, offset);
326 }
327 }
328 Self::Vslide1upVx {
333 vd,
334 vs2,
335 rs1: _,
336 vm,
337 } => {
338 if !env.vector_instructions_allowed() {
339 ::core::hint::cold_path();
340 return ExecutionResult::Err(ExecutionError::IllegalInstruction {
341 address: PackedAddress::new(
342 program_counter.old_pc(zvexx_helpers::INSTRUCTION_SIZE),
343 ),
344 });
345 }
346 let Some(vtype) = env.vtype() else {
347 ::core::hint::cold_path();
348 return ExecutionResult::Err(ExecutionError::IllegalInstruction {
349 address: PackedAddress::new(
350 program_counter.old_pc(zvexx_helpers::INSTRUCTION_SIZE),
351 ),
352 });
353 };
354 let group_regs = vtype.vlmul().register_count();
355 zvexx_perm_helpers::check_vreg_group_alignment::<Reg, _, _>(
356 program_counter,
357 vd,
358 group_regs,
359 )?;
360 zvexx_perm_helpers::check_vreg_group_alignment::<Reg, _, _>(
361 program_counter,
362 vs2,
363 group_regs,
364 )?;
365 zvexx_perm_helpers::check_no_overlap::<Reg, _, _>(
366 program_counter,
367 vd,
368 vs2,
369 group_regs,
370 )?;
371 if !vm && vd == VReg::V0 {
372 ::core::hint::cold_path();
373 return ExecutionResult::Err(ExecutionError::IllegalInstruction {
374 address: PackedAddress::new(
375 program_counter.old_pc(zvexx_helpers::INSTRUCTION_SIZE),
376 ),
377 });
378 }
379 let sew = vtype.vsew();
380 let scalar = rs1_value.as_i64().cast_unsigned();
381 unsafe {
383 zvexx_perm_helpers::execute_slide1up(env, vd, vs2, vm, sew, scalar);
384 }
385 }
386 Self::Vslide1downVx {
391 vd,
392 vs2,
393 rs1: _,
394 vm,
395 } => {
396 if !env.vector_instructions_allowed() {
397 ::core::hint::cold_path();
398 return ExecutionResult::Err(ExecutionError::IllegalInstruction {
399 address: PackedAddress::new(
400 program_counter.old_pc(zvexx_helpers::INSTRUCTION_SIZE),
401 ),
402 });
403 }
404 let Some(vtype) = env.vtype() else {
405 ::core::hint::cold_path();
406 return ExecutionResult::Err(ExecutionError::IllegalInstruction {
407 address: PackedAddress::new(
408 program_counter.old_pc(zvexx_helpers::INSTRUCTION_SIZE),
409 ),
410 });
411 };
412 let group_regs = vtype.vlmul().register_count();
413 zvexx_perm_helpers::check_vreg_group_alignment::<Reg, _, _>(
414 program_counter,
415 vd,
416 group_regs,
417 )?;
418 zvexx_perm_helpers::check_vreg_group_alignment::<Reg, _, _>(
419 program_counter,
420 vs2,
421 group_regs,
422 )?;
423 if !vm && vd == VReg::V0 {
424 ::core::hint::cold_path();
425 return ExecutionResult::Err(ExecutionError::IllegalInstruction {
426 address: PackedAddress::new(
427 program_counter.old_pc(zvexx_helpers::INSTRUCTION_SIZE),
428 ),
429 });
430 }
431 let sew = vtype.vsew();
432 let scalar = rs1_value.as_i64().cast_unsigned();
433 unsafe {
435 zvexx_perm_helpers::execute_slide1down(env, vd, vs2, vm, sew, scalar);
436 }
437 }
438 Self::VrgatherVv { vd, vs2, vs1, vm } => {
442 if !env.vector_instructions_allowed() {
443 ::core::hint::cold_path();
444 return ExecutionResult::Err(ExecutionError::IllegalInstruction {
445 address: PackedAddress::new(
446 program_counter.old_pc(zvexx_helpers::INSTRUCTION_SIZE),
447 ),
448 });
449 }
450 let Some(vtype) = env.vtype() else {
451 ::core::hint::cold_path();
452 return ExecutionResult::Err(ExecutionError::IllegalInstruction {
453 address: PackedAddress::new(
454 program_counter.old_pc(zvexx_helpers::INSTRUCTION_SIZE),
455 ),
456 });
457 };
458 let group_regs = vtype.vlmul().register_count();
459 zvexx_perm_helpers::check_vreg_group_alignment::<Reg, _, _>(
460 program_counter,
461 vd,
462 group_regs,
463 )?;
464 zvexx_perm_helpers::check_vreg_group_alignment::<Reg, _, _>(
465 program_counter,
466 vs2,
467 group_regs,
468 )?;
469 zvexx_perm_helpers::check_vreg_group_alignment::<Reg, _, _>(
470 program_counter,
471 vs1,
472 group_regs,
473 )?;
474 zvexx_perm_helpers::check_no_overlap::<Reg, _, _>(
475 program_counter,
476 vd,
477 vs2,
478 group_regs,
479 )?;
480 zvexx_perm_helpers::check_no_overlap::<Reg, _, _>(
481 program_counter,
482 vd,
483 vs1,
484 group_regs,
485 )?;
486 if !vm && vd == VReg::V0 {
487 ::core::hint::cold_path();
488 return ExecutionResult::Err(ExecutionError::IllegalInstruction {
489 address: PackedAddress::new(
490 program_counter.old_pc(zvexx_helpers::INSTRUCTION_SIZE),
491 ),
492 });
493 }
494 let sew = vtype.vsew();
495 let vlmax = env.vlmax_for_vtype(vtype);
496 unsafe {
498 zvexx_perm_helpers::execute_rgather_vv(env, vd, vs2, vs1, vm, sew, vlmax);
499 }
500 }
501 Self::VrgatherVx {
505 vd,
506 vs2,
507 rs1: _,
508 vm,
509 } => {
510 if !env.vector_instructions_allowed() {
511 ::core::hint::cold_path();
512 return ExecutionResult::Err(ExecutionError::IllegalInstruction {
513 address: PackedAddress::new(
514 program_counter.old_pc(zvexx_helpers::INSTRUCTION_SIZE),
515 ),
516 });
517 }
518 let Some(vtype) = env.vtype() else {
519 ::core::hint::cold_path();
520 return ExecutionResult::Err(ExecutionError::IllegalInstruction {
521 address: PackedAddress::new(
522 program_counter.old_pc(zvexx_helpers::INSTRUCTION_SIZE),
523 ),
524 });
525 };
526 let group_regs = vtype.vlmul().register_count();
527 zvexx_perm_helpers::check_vreg_group_alignment::<Reg, _, _>(
528 program_counter,
529 vd,
530 group_regs,
531 )?;
532 zvexx_perm_helpers::check_vreg_group_alignment::<Reg, _, _>(
533 program_counter,
534 vs2,
535 group_regs,
536 )?;
537 zvexx_perm_helpers::check_no_overlap::<Reg, _, _>(
538 program_counter,
539 vd,
540 vs2,
541 group_regs,
542 )?;
543 if !vm && vd == VReg::V0 {
544 ::core::hint::cold_path();
545 return ExecutionResult::Err(ExecutionError::IllegalInstruction {
546 address: PackedAddress::new(
547 program_counter.old_pc(zvexx_helpers::INSTRUCTION_SIZE),
548 ),
549 });
550 }
551 let sew = vtype.vsew();
552 let vlmax = env.vlmax_for_vtype(vtype);
553 let index = rs1_value.as_u64();
554 unsafe {
556 zvexx_perm_helpers::execute_rgather_scalar(env, vd, vs2, vm, sew, vlmax, index);
557 }
558 }
559 Self::VrgatherVi { vd, vs2, uimm, vm } => {
562 if !env.vector_instructions_allowed() {
563 ::core::hint::cold_path();
564 return ExecutionResult::Err(ExecutionError::IllegalInstruction {
565 address: PackedAddress::new(
566 program_counter.old_pc(zvexx_helpers::INSTRUCTION_SIZE),
567 ),
568 });
569 }
570 let Some(vtype) = env.vtype() else {
571 ::core::hint::cold_path();
572 return ExecutionResult::Err(ExecutionError::IllegalInstruction {
573 address: PackedAddress::new(
574 program_counter.old_pc(zvexx_helpers::INSTRUCTION_SIZE),
575 ),
576 });
577 };
578 let group_regs = vtype.vlmul().register_count();
579 zvexx_perm_helpers::check_vreg_group_alignment::<Reg, _, _>(
580 program_counter,
581 vd,
582 group_regs,
583 )?;
584 zvexx_perm_helpers::check_vreg_group_alignment::<Reg, _, _>(
585 program_counter,
586 vs2,
587 group_regs,
588 )?;
589 zvexx_perm_helpers::check_no_overlap::<Reg, _, _>(
590 program_counter,
591 vd,
592 vs2,
593 group_regs,
594 )?;
595 if !vm && vd == VReg::V0 {
596 ::core::hint::cold_path();
597 return ExecutionResult::Err(ExecutionError::IllegalInstruction {
598 address: PackedAddress::new(
599 program_counter.old_pc(zvexx_helpers::INSTRUCTION_SIZE),
600 ),
601 });
602 }
603 let sew = vtype.vsew();
604 let vlmax = env.vlmax_for_vtype(vtype);
605 let index = u64::from(uimm);
606 unsafe {
608 zvexx_perm_helpers::execute_rgather_scalar(env, vd, vs2, vm, sew, vlmax, index);
609 }
610 }
611 Self::Vrgatherei16Vv { vd, vs2, vs1, vm } => {
616 if !env.vector_instructions_allowed() {
617 ::core::hint::cold_path();
618 return ExecutionResult::Err(ExecutionError::IllegalInstruction {
619 address: PackedAddress::new(
620 program_counter.old_pc(zvexx_helpers::INSTRUCTION_SIZE),
621 ),
622 });
623 }
624 let Some(vtype) = env.vtype() else {
625 ::core::hint::cold_path();
626 return ExecutionResult::Err(ExecutionError::IllegalInstruction {
627 address: PackedAddress::new(
628 program_counter.old_pc(zvexx_helpers::INSTRUCTION_SIZE),
629 ),
630 });
631 };
632 let group_regs = vtype.vlmul().register_count();
633 zvexx_perm_helpers::check_vreg_group_alignment::<Reg, _, _>(
634 program_counter,
635 vd,
636 group_regs,
637 )?;
638 zvexx_perm_helpers::check_vreg_group_alignment::<Reg, _, _>(
639 program_counter,
640 vs2,
641 group_regs,
642 )?;
643 let index_group_regs = vtype
645 .vlmul()
646 .index_register_count(
647 ab_riscv_primitives::instructions::v::Eew::E16,
648 vtype.vsew(),
649 )
650 .ok_or(ExecutionError::IllegalInstruction {
651 address: PackedAddress::new(
652 program_counter.old_pc(zvexx_helpers::INSTRUCTION_SIZE),
653 ),
654 })?;
655 zvexx_perm_helpers::check_vreg_group_alignment::<Reg, _, _>(
656 program_counter,
657 vs1,
658 index_group_regs,
659 )?;
660 zvexx_perm_helpers::check_no_overlap::<Reg, _, _>(
661 program_counter,
662 vd,
663 vs2,
664 group_regs,
665 )?;
666 zvexx_perm_helpers::check_no_overlap_asymmetric::<Reg, _, _>(
669 program_counter,
670 vd,
671 group_regs,
672 vs1,
673 index_group_regs,
674 )?;
675 if !vm && vd == VReg::V0 {
676 ::core::hint::cold_path();
677 return ExecutionResult::Err(ExecutionError::IllegalInstruction {
678 address: PackedAddress::new(
679 program_counter.old_pc(zvexx_helpers::INSTRUCTION_SIZE),
680 ),
681 });
682 }
683 let sew = vtype.vsew();
684 let vlmax = env.vlmax_for_vtype(vtype);
685 unsafe {
688 zvexx_perm_helpers::execute_rgatherei16(
689 env,
690 vd,
691 vs2,
692 vs1,
693 vm,
694 sew,
695 vlmax,
696 index_group_regs,
697 );
698 }
699 }
700 Self::VmergeVvm { vd, vs2, vs1, vm } => {
707 if !env.vector_instructions_allowed() {
708 ::core::hint::cold_path();
709 return ExecutionResult::Err(ExecutionError::IllegalInstruction {
710 address: PackedAddress::new(
711 program_counter.old_pc(zvexx_helpers::INSTRUCTION_SIZE),
712 ),
713 });
714 }
715 let Some(vtype) = env.vtype() else {
716 ::core::hint::cold_path();
717 return ExecutionResult::Err(ExecutionError::IllegalInstruction {
718 address: PackedAddress::new(
719 program_counter.old_pc(zvexx_helpers::INSTRUCTION_SIZE),
720 ),
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 zvexx_perm_helpers::check_vreg_group_alignment::<Reg, _, _>(
730 program_counter,
731 vs1,
732 group_regs,
733 )?;
734 if !vm {
735 zvexx_perm_helpers::check_vreg_group_alignment::<Reg, _, _>(
737 program_counter,
738 vs2,
739 group_regs,
740 )?;
741 zvexx_perm_helpers::check_no_overlap::<Reg, _, _>(
742 program_counter,
743 vd,
744 VReg::V0,
745 group_regs,
746 )?;
747 }
748 let sew = vtype.vsew();
749 unsafe {
751 zvexx_perm_helpers::execute_merge_vv(env, vd, vs2, vs1, vm, sew);
752 }
753 }
754 Self::VmergeVxm {
758 vd,
759 vs2,
760 rs1: _,
761 vm,
762 } => {
763 if !env.vector_instructions_allowed() {
764 ::core::hint::cold_path();
765 return ExecutionResult::Err(ExecutionError::IllegalInstruction {
766 address: PackedAddress::new(
767 program_counter.old_pc(zvexx_helpers::INSTRUCTION_SIZE),
768 ),
769 });
770 }
771 let Some(vtype) = env.vtype() else {
772 ::core::hint::cold_path();
773 return ExecutionResult::Err(ExecutionError::IllegalInstruction {
774 address: PackedAddress::new(
775 program_counter.old_pc(zvexx_helpers::INSTRUCTION_SIZE),
776 ),
777 });
778 };
779 let group_regs = vtype.vlmul().register_count();
780 zvexx_perm_helpers::check_vreg_group_alignment::<Reg, _, _>(
781 program_counter,
782 vd,
783 group_regs,
784 )?;
785 if !vm {
786 zvexx_perm_helpers::check_vreg_group_alignment::<Reg, _, _>(
787 program_counter,
788 vs2,
789 group_regs,
790 )?;
791 zvexx_perm_helpers::check_no_overlap::<Reg, _, _>(
792 program_counter,
793 vd,
794 VReg::V0,
795 group_regs,
796 )?;
797 }
798 let sew = vtype.vsew();
799 let scalar = rs1_value.as_i64().cast_unsigned();
800 unsafe {
802 zvexx_perm_helpers::execute_merge_scalar(env, vd, vs2, vm, sew, scalar);
803 }
804 }
805 Self::VmergeVim { vd, vs2, simm5, vm } => {
809 if !env.vector_instructions_allowed() {
810 ::core::hint::cold_path();
811 return ExecutionResult::Err(ExecutionError::IllegalInstruction {
812 address: PackedAddress::new(
813 program_counter.old_pc(zvexx_helpers::INSTRUCTION_SIZE),
814 ),
815 });
816 }
817 let Some(vtype) = env.vtype() else {
818 ::core::hint::cold_path();
819 return ExecutionResult::Err(ExecutionError::IllegalInstruction {
820 address: PackedAddress::new(
821 program_counter.old_pc(zvexx_helpers::INSTRUCTION_SIZE),
822 ),
823 });
824 };
825 let group_regs = vtype.vlmul().register_count();
826 zvexx_perm_helpers::check_vreg_group_alignment::<Reg, _, _>(
827 program_counter,
828 vd,
829 group_regs,
830 )?;
831 if !vm {
832 zvexx_perm_helpers::check_vreg_group_alignment::<Reg, _, _>(
833 program_counter,
834 vs2,
835 group_regs,
836 )?;
837 zvexx_perm_helpers::check_no_overlap::<Reg, _, _>(
838 program_counter,
839 vd,
840 VReg::V0,
841 group_regs,
842 )?;
843 }
844 let sew = vtype.vsew();
845 let scalar = i64::from(simm5).cast_unsigned();
847 unsafe {
849 zvexx_perm_helpers::execute_merge_scalar(env, vd, vs2, vm, sew, scalar);
850 }
851 }
852 Self::VcompressVm { vd, vs2, vs1 } => {
857 if !env.vector_instructions_allowed() {
858 ::core::hint::cold_path();
859 return ExecutionResult::Err(ExecutionError::IllegalInstruction {
860 address: PackedAddress::new(
861 program_counter.old_pc(zvexx_helpers::INSTRUCTION_SIZE),
862 ),
863 });
864 }
865 let Some(vtype) = env.vtype() else {
866 ::core::hint::cold_path();
867 return ExecutionResult::Err(ExecutionError::IllegalInstruction {
868 address: PackedAddress::new(
869 program_counter.old_pc(zvexx_helpers::INSTRUCTION_SIZE),
870 ),
871 });
872 };
873 if env.vstart() != Vstart::ZERO {
875 ::core::hint::cold_path();
876 return ExecutionResult::Err(ExecutionError::IllegalInstruction {
877 address: PackedAddress::new(
878 program_counter.old_pc(zvexx_helpers::INSTRUCTION_SIZE),
879 ),
880 });
881 }
882 let group_regs = vtype.vlmul().register_count();
883 zvexx_perm_helpers::check_vreg_group_alignment::<Reg, _, _>(
884 program_counter,
885 vd,
886 group_regs,
887 )?;
888 zvexx_perm_helpers::check_vreg_group_alignment::<Reg, _, _>(
889 program_counter,
890 vs2,
891 group_regs,
892 )?;
893 zvexx_perm_helpers::check_no_overlap::<Reg, _, _>(
895 program_counter,
896 vd,
897 vs2,
898 group_regs,
899 )?;
900 zvexx_perm_helpers::check_no_overlap::<Reg, _, _>(
902 program_counter,
903 vd,
904 vs1,
905 VRegGroupSize::R1,
906 )?;
907 let sew = vtype.vsew();
908 let vl = env.vl();
909 unsafe {
910 zvexx_perm_helpers::execute_compress(env, vd, vs2, vs1, vl, sew);
911 }
912 }
913 Self::Vmv1rV { vd, vs2 } => {
917 if !env.vector_instructions_allowed() {
918 ::core::hint::cold_path();
919 return ExecutionResult::Err(ExecutionError::IllegalInstruction {
920 address: PackedAddress::new(
921 program_counter.old_pc(zvexx_helpers::INSTRUCTION_SIZE),
922 ),
923 });
924 }
925 unsafe {
928 zvexx_perm_helpers::execute_whole_reg_move::<1, _>(env.write_vregs(), vd, vs2);
929 }
930 env.mark_vs_dirty();
931 env.reset_vstart();
932 }
933 Self::Vmv2rV { vd, vs2 } => {
937 if !env.vector_instructions_allowed() {
938 ::core::hint::cold_path();
939 return ExecutionResult::Err(ExecutionError::IllegalInstruction {
940 address: PackedAddress::new(
941 program_counter.old_pc(zvexx_helpers::INSTRUCTION_SIZE),
942 ),
943 });
944 }
945 if !vd.to_bits().is_multiple_of(2) || !vs2.to_bits().is_multiple_of(2) {
946 ::core::hint::cold_path();
947 return ExecutionResult::Err(ExecutionError::IllegalInstruction {
948 address: PackedAddress::new(
949 program_counter.old_pc(zvexx_helpers::INSTRUCTION_SIZE),
950 ),
951 });
952 }
953 unsafe {
955 zvexx_perm_helpers::execute_whole_reg_move::<2, _>(env.write_vregs(), vd, vs2);
956 }
957 env.mark_vs_dirty();
958 env.reset_vstart();
959 }
960 Self::Vmv4rV { vd, vs2 } => {
963 if !env.vector_instructions_allowed() {
964 ::core::hint::cold_path();
965 return ExecutionResult::Err(ExecutionError::IllegalInstruction {
966 address: PackedAddress::new(
967 program_counter.old_pc(zvexx_helpers::INSTRUCTION_SIZE),
968 ),
969 });
970 }
971 if !vd.to_bits().is_multiple_of(4) || !vs2.to_bits().is_multiple_of(4) {
972 ::core::hint::cold_path();
973 return ExecutionResult::Err(ExecutionError::IllegalInstruction {
974 address: PackedAddress::new(
975 program_counter.old_pc(zvexx_helpers::INSTRUCTION_SIZE),
976 ),
977 });
978 }
979 unsafe {
981 zvexx_perm_helpers::execute_whole_reg_move::<4, _>(env.write_vregs(), vd, vs2);
982 }
983 env.mark_vs_dirty();
984 env.reset_vstart();
985 }
986 Self::Vmv8rV { vd, vs2 } => {
989 if !env.vector_instructions_allowed() {
990 ::core::hint::cold_path();
991 return ExecutionResult::Err(ExecutionError::IllegalInstruction {
992 address: PackedAddress::new(
993 program_counter.old_pc(zvexx_helpers::INSTRUCTION_SIZE),
994 ),
995 });
996 }
997 if !vd.to_bits().is_multiple_of(8) || !vs2.to_bits().is_multiple_of(8) {
998 ::core::hint::cold_path();
999 return ExecutionResult::Err(ExecutionError::IllegalInstruction {
1000 address: PackedAddress::new(
1001 program_counter.old_pc(zvexx_helpers::INSTRUCTION_SIZE),
1002 ),
1003 });
1004 }
1005 unsafe {
1007 zvexx_perm_helpers::execute_whole_reg_move::<8, _>(env.write_vregs(), vd, vs2);
1008 }
1009 env.mark_vs_dirty();
1010 env.reset_vstart();
1011 }
1012 }
1013
1014 ExecutionResult::ContinueNoWrite
1015 }
1016}