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