1#[cfg(test)]
4mod tests;
5pub mod zvexx_perm_helpers;
6
7use crate::v::vector_registers::{VectorRegisters, 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, Hart> ExecutableInstructionOperands for ZveXxPermInstruction<Hart>
20where
21 Reg: Register,
22 Hart: VectorHartConfig<Reg = Reg>,
23{
24}
25
26#[instruction_execution]
27const impl<Reg, Hart, Env> ExecutableInstructionCsr<Env> for ZveXxPermInstruction<Hart>
28where
29 Reg: Register,
30 Hart: VectorHartConfig<Reg = Reg>,
31{
32}
33
34#[instruction_execution]
35impl<Reg, Hart, Regs, Env, Memory, PC> ExecutableInstruction<Regs, Env, Memory, PC>
36 for ZveXxPermInstruction<Hart>
37where
38 Reg: Register,
39 Hart: VectorHartConfig<Reg = Reg>,
40 Regs: RegisterFile<Reg>,
41 Env: VectorRegistersExt<Hart = Hart>,
42 Memory: VirtualMemory,
43 PC: ProgramCounter<Reg::Type, Memory>,
44{
45 #[inline(always)]
46 #[cfg_attr(feature = "no-panic", no_panic_const::no_panic)]
47 fn execute(
48 self,
49 Rs1Rs2OperandValues {
50 rs1_value,
51 rs2_value: _,
52 }: Rs1Rs2OperandValues<Reg::Type>,
53 _regs: &mut Regs,
54 env: &mut Env,
55 _memory: &mut Memory,
56 program_counter: &PC,
57 ) -> ExecutionResult<Reg> {
58 match self {
59 Self::VmvXS { rd, vs2 } => {
64 if !zvexx_helpers::non_memory_instruction_allowed::<Reg, _>(env) {
65 ::core::hint::cold_path();
66 return ExecutionResult::Err(ExecutionError::IllegalInstruction {
67 address: PackedAddress::new(
68 program_counter.old_pc(zvexx_helpers::INSTRUCTION_SIZE),
69 ),
70 });
71 }
72 let Some(config) = env.vector_config() else {
73 ::core::hint::cold_path();
74 return ExecutionResult::Err(ExecutionError::IllegalInstruction {
75 address: PackedAddress::new(
76 program_counter.old_pc(zvexx_helpers::INSTRUCTION_SIZE),
77 ),
78 });
79 };
80 let vtype = config.vtype();
81 let sew = vtype.vsew();
82 let raw = env
83 .read_vregs()
84 .read_first(vs2, sew.as_eew())
85 .expect("SEW never exceeds `ELEN`, which never exceeds `VLEN`; qed");
86 let sign_extended = zvexx_perm_helpers::sign_extend_to_reg::<Reg>(raw, sew);
87 env.mark_vs_dirty();
88
89 return ExecutionResult::Continue {
90 rd,
91 value: sign_extended,
92 };
93 }
94 Self::VmvSX { vd, rs1: _ } => {
98 if !zvexx_helpers::non_memory_instruction_allowed::<Reg, _>(env) {
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 Some(config) = env.vector_config() else {
107 ::core::hint::cold_path();
108 return ExecutionResult::Err(ExecutionError::IllegalInstruction {
109 address: PackedAddress::new(
110 program_counter.old_pc(zvexx_helpers::INSTRUCTION_SIZE),
111 ),
112 });
113 };
114 let vtype = config.vtype();
115 let sew = vtype.vsew();
116 let vl = config.vl().get();
117 if vl != Vl::ZERO {
119 let scalar = rs1_value.as_i64().cast_unsigned();
120 env.write_vregs()
121 .write_first(vd, sew.as_eew(), scalar)
122 .expect("SEW never exceeds `ELEN`, which never exceeds `VLEN`; qed");
123 }
124 env.mark_vs_dirty();
125 }
126 Self::VslideupVx {
132 vd,
133 vs2,
134 rs1: _,
135 vm,
136 } => {
137 if !zvexx_helpers::non_memory_instruction_allowed::<Reg, _>(env) {
138 ::core::hint::cold_path();
139 return ExecutionResult::Err(ExecutionError::IllegalInstruction {
140 address: PackedAddress::new(
141 program_counter.old_pc(zvexx_helpers::INSTRUCTION_SIZE),
142 ),
143 });
144 }
145 let Some(config) = env.vector_config() else {
146 ::core::hint::cold_path();
147 return ExecutionResult::Err(ExecutionError::IllegalInstruction {
148 address: PackedAddress::new(
149 program_counter.old_pc(zvexx_helpers::INSTRUCTION_SIZE),
150 ),
151 });
152 };
153 let sew = config.vtype().vsew();
154 let vd = zvexx_helpers::vreg_group::<Reg, Env, _, _>(
155 program_counter,
156 config,
157 vd,
158 sew.as_eew(),
159 )?;
160 let vs2 = zvexx_helpers::vreg_group::<Reg, Env, _, _>(
161 program_counter,
162 config,
163 vs2,
164 sew.as_eew(),
165 )?;
166 zvexx_helpers::check_groups_disjoint::<Reg, Env, _, _>(program_counter, vd, vs2)?;
168 let offset = rs1_value.as_u64();
169 zvexx_perm_helpers::execute_slideup(env, vd, vs2, vm, offset);
170 }
171 Self::VslideupVi { vd, vs2, uimm, vm } => {
174 if !zvexx_helpers::non_memory_instruction_allowed::<Reg, _>(env) {
175 ::core::hint::cold_path();
176 return ExecutionResult::Err(ExecutionError::IllegalInstruction {
177 address: PackedAddress::new(
178 program_counter.old_pc(zvexx_helpers::INSTRUCTION_SIZE),
179 ),
180 });
181 }
182 let Some(config) = env.vector_config() else {
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 sew = config.vtype().vsew();
191 let vd = zvexx_helpers::vreg_group::<Reg, Env, _, _>(
192 program_counter,
193 config,
194 vd,
195 sew.as_eew(),
196 )?;
197 let vs2 = zvexx_helpers::vreg_group::<Reg, Env, _, _>(
198 program_counter,
199 config,
200 vs2,
201 sew.as_eew(),
202 )?;
203 zvexx_helpers::check_groups_disjoint::<Reg, Env, _, _>(program_counter, vd, vs2)?;
205 let offset = u64::from(uimm);
206 zvexx_perm_helpers::execute_slideup(env, vd, vs2, vm, offset);
207 }
208 Self::VslidedownVx {
212 vd,
213 vs2,
214 rs1: _,
215 vm,
216 } => {
217 if !zvexx_helpers::non_memory_instruction_allowed::<Reg, _>(env) {
218 ::core::hint::cold_path();
219 return ExecutionResult::Err(ExecutionError::IllegalInstruction {
220 address: PackedAddress::new(
221 program_counter.old_pc(zvexx_helpers::INSTRUCTION_SIZE),
222 ),
223 });
224 }
225 let Some(config) = env.vector_config() else {
226 ::core::hint::cold_path();
227 return ExecutionResult::Err(ExecutionError::IllegalInstruction {
228 address: PackedAddress::new(
229 program_counter.old_pc(zvexx_helpers::INSTRUCTION_SIZE),
230 ),
231 });
232 };
233 let sew = config.vtype().vsew();
234 let vd = zvexx_helpers::vreg_group::<Reg, Env, _, _>(
235 program_counter,
236 config,
237 vd,
238 sew.as_eew(),
239 )?;
240 let vs2 = zvexx_helpers::vreg_group::<Reg, Env, _, _>(
241 program_counter,
242 config,
243 vs2,
244 sew.as_eew(),
245 )?;
246 let offset = rs1_value.as_u64();
247 zvexx_perm_helpers::execute_slidedown(env, vd, vs2, vm, offset);
248 }
249 Self::VslidedownVi { vd, vs2, uimm, vm } => {
252 if !zvexx_helpers::non_memory_instruction_allowed::<Reg, _>(env) {
253 ::core::hint::cold_path();
254 return ExecutionResult::Err(ExecutionError::IllegalInstruction {
255 address: PackedAddress::new(
256 program_counter.old_pc(zvexx_helpers::INSTRUCTION_SIZE),
257 ),
258 });
259 }
260 let Some(config) = env.vector_config() else {
261 ::core::hint::cold_path();
262 return ExecutionResult::Err(ExecutionError::IllegalInstruction {
263 address: PackedAddress::new(
264 program_counter.old_pc(zvexx_helpers::INSTRUCTION_SIZE),
265 ),
266 });
267 };
268 let sew = config.vtype().vsew();
269 let vd = zvexx_helpers::vreg_group::<Reg, Env, _, _>(
270 program_counter,
271 config,
272 vd,
273 sew.as_eew(),
274 )?;
275 let vs2 = zvexx_helpers::vreg_group::<Reg, Env, _, _>(
276 program_counter,
277 config,
278 vs2,
279 sew.as_eew(),
280 )?;
281 let offset = u64::from(uimm);
282 zvexx_perm_helpers::execute_slidedown(env, vd, vs2, vm, offset);
283 }
284 Self::Vslide1upVx {
289 vd,
290 vs2,
291 rs1: _,
292 vm,
293 } => {
294 if !zvexx_helpers::non_memory_instruction_allowed::<Reg, _>(env) {
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 Some(config) = env.vector_config() else {
303 ::core::hint::cold_path();
304 return ExecutionResult::Err(ExecutionError::IllegalInstruction {
305 address: PackedAddress::new(
306 program_counter.old_pc(zvexx_helpers::INSTRUCTION_SIZE),
307 ),
308 });
309 };
310 let sew = config.vtype().vsew();
311 let vd = zvexx_helpers::vreg_group::<Reg, Env, _, _>(
312 program_counter,
313 config,
314 vd,
315 sew.as_eew(),
316 )?;
317 let vs2 = zvexx_helpers::vreg_group::<Reg, Env, _, _>(
318 program_counter,
319 config,
320 vs2,
321 sew.as_eew(),
322 )?;
323 zvexx_helpers::check_groups_disjoint::<Reg, Env, _, _>(program_counter, vd, vs2)?;
325 let scalar = rs1_value.as_i64().cast_unsigned();
326 zvexx_perm_helpers::execute_slide1up(env, vd, vs2, vm, scalar);
327 }
328 Self::Vslide1downVx {
333 vd,
334 vs2,
335 rs1: _,
336 vm,
337 } => {
338 if !zvexx_helpers::non_memory_instruction_allowed::<Reg, _>(env) {
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(config) = env.vector_config() 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 sew = config.vtype().vsew();
355 let vd = zvexx_helpers::vreg_group::<Reg, Env, _, _>(
356 program_counter,
357 config,
358 vd,
359 sew.as_eew(),
360 )?;
361 let vs2 = zvexx_helpers::vreg_group::<Reg, Env, _, _>(
362 program_counter,
363 config,
364 vs2,
365 sew.as_eew(),
366 )?;
367 let scalar = rs1_value.as_i64().cast_unsigned();
368 zvexx_perm_helpers::execute_slide1down(env, vd, vs2, vm, scalar);
369 }
370 Self::VrgatherVv { vd, vs2, vs1, vm } => {
374 if !zvexx_helpers::non_memory_instruction_allowed::<Reg, _>(env) {
375 ::core::hint::cold_path();
376 return ExecutionResult::Err(ExecutionError::IllegalInstruction {
377 address: PackedAddress::new(
378 program_counter.old_pc(zvexx_helpers::INSTRUCTION_SIZE),
379 ),
380 });
381 }
382 let Some(config) = env.vector_config() else {
383 ::core::hint::cold_path();
384 return ExecutionResult::Err(ExecutionError::IllegalInstruction {
385 address: PackedAddress::new(
386 program_counter.old_pc(zvexx_helpers::INSTRUCTION_SIZE),
387 ),
388 });
389 };
390 let sew = config.vtype().vsew();
391 let vd = zvexx_helpers::vreg_group::<Reg, Env, _, _>(
392 program_counter,
393 config,
394 vd,
395 sew.as_eew(),
396 )?;
397 let vs2 = zvexx_helpers::vreg_group::<Reg, Env, _, _>(
398 program_counter,
399 config,
400 vs2,
401 sew.as_eew(),
402 )?;
403 let vs1 = zvexx_helpers::vreg_group::<Reg, Env, _, _>(
404 program_counter,
405 config,
406 vs1,
407 sew.as_eew(),
408 )?;
409 zvexx_helpers::check_groups_disjoint::<Reg, Env, _, _>(program_counter, vd, vs2)?;
411 zvexx_helpers::check_groups_disjoint::<Reg, Env, _, _>(program_counter, vd, vs1)?;
412 zvexx_perm_helpers::execute_rgather_vv(env, vd, vs2, vs1, vm);
413 }
414 Self::VrgatherVx {
418 vd,
419 vs2,
420 rs1: _,
421 vm,
422 } => {
423 if !zvexx_helpers::non_memory_instruction_allowed::<Reg, _>(env) {
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 Some(config) = env.vector_config() else {
432 ::core::hint::cold_path();
433 return ExecutionResult::Err(ExecutionError::IllegalInstruction {
434 address: PackedAddress::new(
435 program_counter.old_pc(zvexx_helpers::INSTRUCTION_SIZE),
436 ),
437 });
438 };
439 let sew = config.vtype().vsew();
440 let vd = zvexx_helpers::vreg_group::<Reg, Env, _, _>(
441 program_counter,
442 config,
443 vd,
444 sew.as_eew(),
445 )?;
446 let vs2 = zvexx_helpers::vreg_group::<Reg, Env, _, _>(
447 program_counter,
448 config,
449 vs2,
450 sew.as_eew(),
451 )?;
452 zvexx_helpers::check_groups_disjoint::<Reg, Env, _, _>(program_counter, vd, vs2)?;
454 let index = rs1_value.as_u64();
455 zvexx_perm_helpers::execute_rgather_scalar(env, vd, vs2, vm, index);
456 }
457 Self::VrgatherVi { vd, vs2, uimm, vm } => {
460 if !zvexx_helpers::non_memory_instruction_allowed::<Reg, _>(env) {
461 ::core::hint::cold_path();
462 return ExecutionResult::Err(ExecutionError::IllegalInstruction {
463 address: PackedAddress::new(
464 program_counter.old_pc(zvexx_helpers::INSTRUCTION_SIZE),
465 ),
466 });
467 }
468 let Some(config) = env.vector_config() else {
469 ::core::hint::cold_path();
470 return ExecutionResult::Err(ExecutionError::IllegalInstruction {
471 address: PackedAddress::new(
472 program_counter.old_pc(zvexx_helpers::INSTRUCTION_SIZE),
473 ),
474 });
475 };
476 let sew = config.vtype().vsew();
477 let vd = zvexx_helpers::vreg_group::<Reg, Env, _, _>(
478 program_counter,
479 config,
480 vd,
481 sew.as_eew(),
482 )?;
483 let vs2 = zvexx_helpers::vreg_group::<Reg, Env, _, _>(
484 program_counter,
485 config,
486 vs2,
487 sew.as_eew(),
488 )?;
489 zvexx_helpers::check_groups_disjoint::<Reg, Env, _, _>(program_counter, vd, vs2)?;
491 let index = u64::from(uimm);
492 zvexx_perm_helpers::execute_rgather_scalar(env, vd, vs2, vm, index);
493 }
494 Self::Vrgatherei16Vv { vd, vs2, vs1, vm } => {
499 if !zvexx_helpers::non_memory_instruction_allowed::<Reg, _>(env) {
500 ::core::hint::cold_path();
501 return ExecutionResult::Err(ExecutionError::IllegalInstruction {
502 address: PackedAddress::new(
503 program_counter.old_pc(zvexx_helpers::INSTRUCTION_SIZE),
504 ),
505 });
506 }
507 let Some(config) = env.vector_config() else {
508 ::core::hint::cold_path();
509 return ExecutionResult::Err(ExecutionError::IllegalInstruction {
510 address: PackedAddress::new(
511 program_counter.old_pc(zvexx_helpers::INSTRUCTION_SIZE),
512 ),
513 });
514 };
515 let sew = config.vtype().vsew();
516 let vd = zvexx_helpers::vreg_group::<Reg, Env, _, _>(
517 program_counter,
518 config,
519 vd,
520 sew.as_eew(),
521 )?;
522 let vs2 = zvexx_helpers::vreg_group::<Reg, Env, _, _>(
523 program_counter,
524 config,
525 vs2,
526 sew.as_eew(),
527 )?;
528 let vs1 = zvexx_helpers::vreg_group::<Reg, Env, _, _>(
529 program_counter,
530 config,
531 vs1,
532 Eew::E16,
533 )?;
534 zvexx_helpers::check_groups_disjoint::<Reg, Env, _, _>(program_counter, vd, vs2)?;
536 zvexx_helpers::check_groups_disjoint::<Reg, Env, _, _>(program_counter, vd, vs1)?;
537 if sew != Vsew::E16 {
539 zvexx_helpers::check_groups_disjoint::<Reg, Env, _, _>(
540 program_counter,
541 vs2,
542 vs1,
543 )?;
544 }
545 zvexx_perm_helpers::execute_rgatherei16(env, vd, vs2, vs1, vm);
546 }
547 Self::VmergeVvm { vd, vs2, vs1, vm } => {
554 if !zvexx_helpers::non_memory_instruction_allowed::<Reg, _>(env) {
555 ::core::hint::cold_path();
556 return ExecutionResult::Err(ExecutionError::IllegalInstruction {
557 address: PackedAddress::new(
558 program_counter.old_pc(zvexx_helpers::INSTRUCTION_SIZE),
559 ),
560 });
561 }
562 let Some(config) = env.vector_config() else {
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 sew = config.vtype().vsew();
571 let vd = zvexx_helpers::vreg_group::<Reg, Env, _, _>(
572 program_counter,
573 config,
574 vd,
575 sew.as_eew(),
576 )?;
577 let vs1 = zvexx_helpers::vreg_group::<Reg, Env, _, _>(
578 program_counter,
579 config,
580 vs1,
581 sew.as_eew(),
582 )?;
583 let vs2 = zvexx_helpers::vreg_group::<Reg, Env, _, _>(
586 program_counter,
587 config,
588 vs2,
589 sew.as_eew(),
590 )?;
591 zvexx_perm_helpers::execute_merge_vv(env, vd, vs2, vs1, vm);
592 }
593 Self::VmergeVxm {
597 vd,
598 vs2,
599 rs1: _,
600 vm,
601 } => {
602 if !zvexx_helpers::non_memory_instruction_allowed::<Reg, _>(env) {
603 ::core::hint::cold_path();
604 return ExecutionResult::Err(ExecutionError::IllegalInstruction {
605 address: PackedAddress::new(
606 program_counter.old_pc(zvexx_helpers::INSTRUCTION_SIZE),
607 ),
608 });
609 }
610 let Some(config) = env.vector_config() else {
611 ::core::hint::cold_path();
612 return ExecutionResult::Err(ExecutionError::IllegalInstruction {
613 address: PackedAddress::new(
614 program_counter.old_pc(zvexx_helpers::INSTRUCTION_SIZE),
615 ),
616 });
617 };
618 let sew = config.vtype().vsew();
619 let vd = zvexx_helpers::vreg_group::<Reg, Env, _, _>(
620 program_counter,
621 config,
622 vd,
623 sew.as_eew(),
624 )?;
625 let vs2 = zvexx_helpers::vreg_group::<Reg, Env, _, _>(
628 program_counter,
629 config,
630 vs2,
631 sew.as_eew(),
632 )?;
633 let scalar = rs1_value.as_i64().cast_unsigned();
634 zvexx_perm_helpers::execute_merge_scalar(env, vd, vs2, vm, scalar);
635 }
636 Self::VmergeVim { vd, vs2, simm5, vm } => {
640 if !zvexx_helpers::non_memory_instruction_allowed::<Reg, _>(env) {
641 ::core::hint::cold_path();
642 return ExecutionResult::Err(ExecutionError::IllegalInstruction {
643 address: PackedAddress::new(
644 program_counter.old_pc(zvexx_helpers::INSTRUCTION_SIZE),
645 ),
646 });
647 }
648 let Some(config) = env.vector_config() else {
649 ::core::hint::cold_path();
650 return ExecutionResult::Err(ExecutionError::IllegalInstruction {
651 address: PackedAddress::new(
652 program_counter.old_pc(zvexx_helpers::INSTRUCTION_SIZE),
653 ),
654 });
655 };
656 let sew = config.vtype().vsew();
657 let vd = zvexx_helpers::vreg_group::<Reg, Env, _, _>(
658 program_counter,
659 config,
660 vd,
661 sew.as_eew(),
662 )?;
663 let vs2 = zvexx_helpers::vreg_group::<Reg, Env, _, _>(
666 program_counter,
667 config,
668 vs2,
669 sew.as_eew(),
670 )?;
671 let scalar = i64::from(simm5).cast_unsigned();
672 zvexx_perm_helpers::execute_merge_scalar(env, vd, vs2, vm, scalar);
673 }
674 Self::VcompressVm { vd, vs2, vs1 } => {
679 if !zvexx_helpers::non_memory_instruction_allowed::<Reg, _>(env) {
680 ::core::hint::cold_path();
681 return ExecutionResult::Err(ExecutionError::IllegalInstruction {
682 address: PackedAddress::new(
683 program_counter.old_pc(zvexx_helpers::INSTRUCTION_SIZE),
684 ),
685 });
686 }
687 let Some(config) = env.vector_config() else {
688 ::core::hint::cold_path();
689 return ExecutionResult::Err(ExecutionError::IllegalInstruction {
690 address: PackedAddress::new(
691 program_counter.old_pc(zvexx_helpers::INSTRUCTION_SIZE),
692 ),
693 });
694 };
695 let sew = config.vtype().vsew();
696 let vd = zvexx_helpers::vreg_group::<Reg, Env, _, _>(
697 program_counter,
698 config,
699 vd,
700 sew.as_eew(),
701 )?;
702 let vs2 = zvexx_helpers::vreg_group::<Reg, Env, _, _>(
703 program_counter,
704 config,
705 vs2,
706 sew.as_eew(),
707 )?;
708 zvexx_helpers::check_groups_disjoint::<Reg, Env, _, _>(program_counter, vd, vs2)?;
710 zvexx_helpers::check_register_outside_group::<Reg, Env, _, _>(
712 program_counter,
713 vd,
714 vs1,
715 )?;
716 zvexx_helpers::check_register_outside_group::<Reg, Env, _, _>(
718 program_counter,
719 vs2,
720 vs1,
721 )?;
722 zvexx_perm_helpers::execute_compress(env, vd, vs2, vs1);
723 }
724 Self::Vmv1rV { vd, vs2 } => {
729 if !zvexx_helpers::non_memory_instruction_allowed::<Reg, _>(env) {
730 ::core::hint::cold_path();
731 return ExecutionResult::Err(ExecutionError::IllegalInstruction {
732 address: PackedAddress::new(
733 program_counter.old_pc(zvexx_helpers::INSTRUCTION_SIZE),
734 ),
735 });
736 }
737 if env.vector_config().is_none() {
738 ::core::hint::cold_path();
739 return ExecutionResult::Err(ExecutionError::IllegalInstruction {
740 address: PackedAddress::new(
741 program_counter.old_pc(zvexx_helpers::INSTRUCTION_SIZE),
742 ),
743 });
744 }
745 if zvexx_perm_helpers::execute_whole_reg_move::<1, _>(env.write_vregs(), vd, vs2)
746 .is_none()
747 {
748 ::core::hint::cold_path();
749 return ExecutionResult::Err(ExecutionError::IllegalInstruction {
750 address: PackedAddress::new(
751 program_counter.old_pc(zvexx_helpers::INSTRUCTION_SIZE),
752 ),
753 });
754 }
755 env.mark_vs_dirty();
756 }
757 Self::Vmv2rV { vd, vs2 } => {
761 if !zvexx_helpers::non_memory_instruction_allowed::<Reg, _>(env) {
762 ::core::hint::cold_path();
763 return ExecutionResult::Err(ExecutionError::IllegalInstruction {
764 address: PackedAddress::new(
765 program_counter.old_pc(zvexx_helpers::INSTRUCTION_SIZE),
766 ),
767 });
768 }
769 if env.vector_config().is_none() {
770 ::core::hint::cold_path();
771 return ExecutionResult::Err(ExecutionError::IllegalInstruction {
772 address: PackedAddress::new(
773 program_counter.old_pc(zvexx_helpers::INSTRUCTION_SIZE),
774 ),
775 });
776 }
777 if !vd.to_bits().is_multiple_of(2) || !vs2.to_bits().is_multiple_of(2) {
778 ::core::hint::cold_path();
779 return ExecutionResult::Err(ExecutionError::IllegalInstruction {
780 address: PackedAddress::new(
781 program_counter.old_pc(zvexx_helpers::INSTRUCTION_SIZE),
782 ),
783 });
784 }
785 if zvexx_perm_helpers::execute_whole_reg_move::<2, _>(env.write_vregs(), vd, vs2)
786 .is_none()
787 {
788 ::core::hint::cold_path();
789 return ExecutionResult::Err(ExecutionError::IllegalInstruction {
790 address: PackedAddress::new(
791 program_counter.old_pc(zvexx_helpers::INSTRUCTION_SIZE),
792 ),
793 });
794 }
795 env.mark_vs_dirty();
796 }
797 Self::Vmv4rV { vd, vs2 } => {
800 if !zvexx_helpers::non_memory_instruction_allowed::<Reg, _>(env) {
801 ::core::hint::cold_path();
802 return ExecutionResult::Err(ExecutionError::IllegalInstruction {
803 address: PackedAddress::new(
804 program_counter.old_pc(zvexx_helpers::INSTRUCTION_SIZE),
805 ),
806 });
807 }
808 if env.vector_config().is_none() {
809 ::core::hint::cold_path();
810 return ExecutionResult::Err(ExecutionError::IllegalInstruction {
811 address: PackedAddress::new(
812 program_counter.old_pc(zvexx_helpers::INSTRUCTION_SIZE),
813 ),
814 });
815 }
816 if !vd.to_bits().is_multiple_of(4) || !vs2.to_bits().is_multiple_of(4) {
817 ::core::hint::cold_path();
818 return ExecutionResult::Err(ExecutionError::IllegalInstruction {
819 address: PackedAddress::new(
820 program_counter.old_pc(zvexx_helpers::INSTRUCTION_SIZE),
821 ),
822 });
823 }
824 if zvexx_perm_helpers::execute_whole_reg_move::<4, _>(env.write_vregs(), vd, vs2)
825 .is_none()
826 {
827 ::core::hint::cold_path();
828 return ExecutionResult::Err(ExecutionError::IllegalInstruction {
829 address: PackedAddress::new(
830 program_counter.old_pc(zvexx_helpers::INSTRUCTION_SIZE),
831 ),
832 });
833 }
834 env.mark_vs_dirty();
835 }
836 Self::Vmv8rV { vd, vs2 } => {
839 if !zvexx_helpers::non_memory_instruction_allowed::<Reg, _>(env) {
840 ::core::hint::cold_path();
841 return ExecutionResult::Err(ExecutionError::IllegalInstruction {
842 address: PackedAddress::new(
843 program_counter.old_pc(zvexx_helpers::INSTRUCTION_SIZE),
844 ),
845 });
846 }
847 if env.vector_config().is_none() {
848 ::core::hint::cold_path();
849 return ExecutionResult::Err(ExecutionError::IllegalInstruction {
850 address: PackedAddress::new(
851 program_counter.old_pc(zvexx_helpers::INSTRUCTION_SIZE),
852 ),
853 });
854 }
855 if !vd.to_bits().is_multiple_of(8) || !vs2.to_bits().is_multiple_of(8) {
856 ::core::hint::cold_path();
857 return ExecutionResult::Err(ExecutionError::IllegalInstruction {
858 address: PackedAddress::new(
859 program_counter.old_pc(zvexx_helpers::INSTRUCTION_SIZE),
860 ),
861 });
862 }
863 if zvexx_perm_helpers::execute_whole_reg_move::<8, _>(env.write_vregs(), vd, vs2)
864 .is_none()
865 {
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 env.mark_vs_dirty();
874 }
875 }
876
877 ExecutionResult::ContinueNoWrite
878 }
879}