1#[cfg(test)]
4mod tests;
5pub mod zvexx_widen_narrow_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 ZveXxWidenNarrowInstruction<Reg> where
20 Reg: Register
21{
22}
23
24#[instruction_execution]
25const impl<Reg, Env> ExecutableInstructionCsr<Env> for ZveXxWidenNarrowInstruction<Reg> where
26 Reg: Register
27{
28}
29
30#[instruction_execution]
31impl<Reg, Regs, Env, Memory, PC> ExecutableInstruction<Regs, Env, Memory, PC>
32 for ZveXxWidenNarrowInstruction<Reg>
33where
34 Reg: Register,
35 Regs: RegisterFile<Reg>,
36 Env: VectorRegistersExt<Reg>,
37 [(); SUPPORTED_ELEN_VLEN::<{ Env::ELEN }, { Env::VLEN }>]:,
38 Memory: VirtualMemory,
39 PC: ProgramCounter<Reg::Type, Memory>,
40{
41 #[inline(always)]
42 #[cfg_attr(feature = "no-panic", no_panic_const::no_panic)]
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 env: &mut Env,
51 _memory: &mut Memory,
52 program_counter: &mut PC,
53 ) -> ExecutionResult<Self::Reg> {
54 match self {
55 Self::VwadduVv { vd, vs2, vs1, vm } => {
57 if !env.vector_instructions_allowed() {
58 ::core::hint::cold_path();
59 return ExecutionResult::Err(ExecutionError::IllegalInstruction {
60 address: PackedAddress::new(
61 program_counter.old_pc(zvexx_helpers::INSTRUCTION_SIZE),
62 ),
63 });
64 }
65 let Some(vtype) = env.vtype() else {
66 ::core::hint::cold_path();
67 return ExecutionResult::Err(ExecutionError::IllegalInstruction {
68 address: PackedAddress::new(
69 program_counter.old_pc(zvexx_helpers::INSTRUCTION_SIZE),
70 ),
71 });
72 };
73 let sew = vtype.vsew();
74 let group_regs = vtype.vlmul().register_count();
76 let wide_eew = match sew {
77 Vsew::E8 => Eew::E16,
78 Vsew::E16 => Eew::E32,
79 Vsew::E32 => Eew::E64,
80 Vsew::E64 => {
81 ::core::hint::cold_path();
82 return ExecutionResult::Err(ExecutionError::IllegalInstruction {
83 address: PackedAddress::new(
84 program_counter.old_pc(zvexx_helpers::INSTRUCTION_SIZE),
85 ),
86 });
87 }
88 };
89 if u32::from(wide_eew.bits_width()) > u32::from(Env::ELEN) {
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 wide_group_regs = vtype.vlmul().data_register_count(wide_eew, sew).ok_or(
98 ExecutionError::IllegalInstruction {
99 address: PackedAddress::new(
100 program_counter.old_pc(zvexx_helpers::INSTRUCTION_SIZE),
101 ),
102 },
103 )?;
104 zvexx_widen_narrow_helpers::check_vd_widen_alignment::<Reg, _, _>(
105 program_counter,
106 vd,
107 vs2,
108 Some(vs1),
109 group_regs,
110 wide_group_regs,
111 )?;
112 zvexx_widen_narrow_helpers::check_vreg_group_alignment::<Reg, _, _>(
113 program_counter,
114 vs2,
115 group_regs,
116 )?;
117 zvexx_widen_narrow_helpers::check_vreg_group_alignment::<Reg, _, _>(
118 program_counter,
119 vs1,
120 group_regs,
121 )?;
122 if !vm && vd == VReg::V0 {
123 ::core::hint::cold_path();
124 return ExecutionResult::Err(ExecutionError::IllegalInstruction {
125 address: PackedAddress::new(
126 program_counter.old_pc(zvexx_helpers::INSTRUCTION_SIZE),
127 ),
128 });
129 }
130 unsafe {
132 zvexx_widen_narrow_helpers::execute_widen_op::<true, _, _, _>(
133 env,
134 vd,
135 vs2,
136 zvexx_widen_narrow_helpers::OpSrc::Vreg(vs1),
137 vm,
138 sew,
139 u64::wrapping_add,
140 );
141 }
142 }
143 Self::VwadduVx {
145 vd,
146 vs2,
147 rs1: _,
148 vm,
149 } => {
150 if !env.vector_instructions_allowed() {
151 ::core::hint::cold_path();
152 return ExecutionResult::Err(ExecutionError::IllegalInstruction {
153 address: PackedAddress::new(
154 program_counter.old_pc(zvexx_helpers::INSTRUCTION_SIZE),
155 ),
156 });
157 }
158 let Some(vtype) = env.vtype() else {
159 ::core::hint::cold_path();
160 return ExecutionResult::Err(ExecutionError::IllegalInstruction {
161 address: PackedAddress::new(
162 program_counter.old_pc(zvexx_helpers::INSTRUCTION_SIZE),
163 ),
164 });
165 };
166 let sew = vtype.vsew();
167 let group_regs = vtype.vlmul().register_count();
168 let wide_eew = match sew {
169 Vsew::E8 => Eew::E16,
170 Vsew::E16 => Eew::E32,
171 Vsew::E32 => Eew::E64,
172 Vsew::E64 => {
173 ::core::hint::cold_path();
174 return ExecutionResult::Err(ExecutionError::IllegalInstruction {
175 address: PackedAddress::new(
176 program_counter.old_pc(zvexx_helpers::INSTRUCTION_SIZE),
177 ),
178 });
179 }
180 };
181 if u32::from(wide_eew.bits_width()) > u32::from(Env::ELEN) {
182 ::core::hint::cold_path();
183 return ExecutionResult::Err(ExecutionError::IllegalInstruction {
184 address: PackedAddress::new(
185 program_counter.old_pc(zvexx_helpers::INSTRUCTION_SIZE),
186 ),
187 });
188 }
189 let wide_group_regs = vtype.vlmul().data_register_count(wide_eew, sew).ok_or(
190 ExecutionError::IllegalInstruction {
191 address: PackedAddress::new(
192 program_counter.old_pc(zvexx_helpers::INSTRUCTION_SIZE),
193 ),
194 },
195 )?;
196 zvexx_widen_narrow_helpers::check_vd_widen_alignment::<Reg, _, _>(
197 program_counter,
198 vd,
199 vs2,
200 None,
201 group_regs,
202 wide_group_regs,
203 )?;
204 zvexx_widen_narrow_helpers::check_vreg_group_alignment::<Reg, _, _>(
205 program_counter,
206 vs2,
207 group_regs,
208 )?;
209 if !vm && vd == VReg::V0 {
210 ::core::hint::cold_path();
211 return ExecutionResult::Err(ExecutionError::IllegalInstruction {
212 address: PackedAddress::new(
213 program_counter.old_pc(zvexx_helpers::INSTRUCTION_SIZE),
214 ),
215 });
216 }
217 let scalar = rs1_value.as_u64();
219 unsafe {
221 zvexx_widen_narrow_helpers::execute_widen_op::<true, _, _, _>(
222 env,
223 vd,
224 vs2,
225 zvexx_widen_narrow_helpers::OpSrc::Scalar(scalar),
226 vm,
227 sew,
228 u64::wrapping_add,
229 );
230 }
231 }
232 Self::VwaddVv { vd, vs2, vs1, vm } => {
234 if !env.vector_instructions_allowed() {
235 ::core::hint::cold_path();
236 return ExecutionResult::Err(ExecutionError::IllegalInstruction {
237 address: PackedAddress::new(
238 program_counter.old_pc(zvexx_helpers::INSTRUCTION_SIZE),
239 ),
240 });
241 }
242 let Some(vtype) = env.vtype() else {
243 ::core::hint::cold_path();
244 return ExecutionResult::Err(ExecutionError::IllegalInstruction {
245 address: PackedAddress::new(
246 program_counter.old_pc(zvexx_helpers::INSTRUCTION_SIZE),
247 ),
248 });
249 };
250 let sew = vtype.vsew();
251 let group_regs = vtype.vlmul().register_count();
252 let wide_eew = match sew {
253 Vsew::E8 => Eew::E16,
254 Vsew::E16 => Eew::E32,
255 Vsew::E32 => Eew::E64,
256 Vsew::E64 => {
257 ::core::hint::cold_path();
258 return ExecutionResult::Err(ExecutionError::IllegalInstruction {
259 address: PackedAddress::new(
260 program_counter.old_pc(zvexx_helpers::INSTRUCTION_SIZE),
261 ),
262 });
263 }
264 };
265 if u32::from(wide_eew.bits_width()) > u32::from(Env::ELEN) {
266 ::core::hint::cold_path();
267 return ExecutionResult::Err(ExecutionError::IllegalInstruction {
268 address: PackedAddress::new(
269 program_counter.old_pc(zvexx_helpers::INSTRUCTION_SIZE),
270 ),
271 });
272 }
273 let wide_group_regs = vtype.vlmul().data_register_count(wide_eew, sew).ok_or(
274 ExecutionError::IllegalInstruction {
275 address: PackedAddress::new(
276 program_counter.old_pc(zvexx_helpers::INSTRUCTION_SIZE),
277 ),
278 },
279 )?;
280 zvexx_widen_narrow_helpers::check_vd_widen_alignment::<Reg, _, _>(
281 program_counter,
282 vd,
283 vs2,
284 Some(vs1),
285 group_regs,
286 wide_group_regs,
287 )?;
288 zvexx_widen_narrow_helpers::check_vreg_group_alignment::<Reg, _, _>(
289 program_counter,
290 vs2,
291 group_regs,
292 )?;
293 zvexx_widen_narrow_helpers::check_vreg_group_alignment::<Reg, _, _>(
294 program_counter,
295 vs1,
296 group_regs,
297 )?;
298 if !vm && vd == VReg::V0 {
299 ::core::hint::cold_path();
300 return ExecutionResult::Err(ExecutionError::IllegalInstruction {
301 address: PackedAddress::new(
302 program_counter.old_pc(zvexx_helpers::INSTRUCTION_SIZE),
303 ),
304 });
305 }
306 unsafe {
308 zvexx_widen_narrow_helpers::execute_widen_op::<false, _, _, _>(
309 env,
310 vd,
311 vs2,
312 zvexx_widen_narrow_helpers::OpSrc::Vreg(vs1),
313 vm,
314 sew,
315 u64::wrapping_add,
316 );
317 }
318 }
319 Self::VwaddVx {
321 vd,
322 vs2,
323 rs1: _,
324 vm,
325 } => {
326 if !env.vector_instructions_allowed() {
327 ::core::hint::cold_path();
328 return ExecutionResult::Err(ExecutionError::IllegalInstruction {
329 address: PackedAddress::new(
330 program_counter.old_pc(zvexx_helpers::INSTRUCTION_SIZE),
331 ),
332 });
333 }
334 let Some(vtype) = env.vtype() else {
335 ::core::hint::cold_path();
336 return ExecutionResult::Err(ExecutionError::IllegalInstruction {
337 address: PackedAddress::new(
338 program_counter.old_pc(zvexx_helpers::INSTRUCTION_SIZE),
339 ),
340 });
341 };
342 let sew = vtype.vsew();
343 let group_regs = vtype.vlmul().register_count();
344 let wide_eew = match sew {
345 Vsew::E8 => Eew::E16,
346 Vsew::E16 => Eew::E32,
347 Vsew::E32 => Eew::E64,
348 Vsew::E64 => {
349 ::core::hint::cold_path();
350 return ExecutionResult::Err(ExecutionError::IllegalInstruction {
351 address: PackedAddress::new(
352 program_counter.old_pc(zvexx_helpers::INSTRUCTION_SIZE),
353 ),
354 });
355 }
356 };
357 if u32::from(wide_eew.bits_width()) > u32::from(Env::ELEN) {
358 ::core::hint::cold_path();
359 return ExecutionResult::Err(ExecutionError::IllegalInstruction {
360 address: PackedAddress::new(
361 program_counter.old_pc(zvexx_helpers::INSTRUCTION_SIZE),
362 ),
363 });
364 }
365 let wide_group_regs = vtype.vlmul().data_register_count(wide_eew, sew).ok_or(
366 ExecutionError::IllegalInstruction {
367 address: PackedAddress::new(
368 program_counter.old_pc(zvexx_helpers::INSTRUCTION_SIZE),
369 ),
370 },
371 )?;
372 zvexx_widen_narrow_helpers::check_vd_widen_alignment::<Reg, _, _>(
373 program_counter,
374 vd,
375 vs2,
376 None,
377 group_regs,
378 wide_group_regs,
379 )?;
380 zvexx_widen_narrow_helpers::check_vreg_group_alignment::<Reg, _, _>(
381 program_counter,
382 vs2,
383 group_regs,
384 )?;
385 if !vm && vd == VReg::V0 {
386 ::core::hint::cold_path();
387 return ExecutionResult::Err(ExecutionError::IllegalInstruction {
388 address: PackedAddress::new(
389 program_counter.old_pc(zvexx_helpers::INSTRUCTION_SIZE),
390 ),
391 });
392 }
393 let scalar = zvexx_widen_narrow_helpers::sign_extend_bits(
395 rs1_value.as_u64(),
396 Vsew::from_xlen::<Reg>(),
397 )
398 .cast_unsigned();
399 unsafe {
401 zvexx_widen_narrow_helpers::execute_widen_op::<false, _, _, _>(
402 env,
403 vd,
404 vs2,
405 zvexx_widen_narrow_helpers::OpSrc::Scalar(scalar),
406 vm,
407 sew,
408 u64::wrapping_add,
409 );
410 }
411 }
412 Self::VwsubuVv { vd, vs2, vs1, vm } => {
414 if !env.vector_instructions_allowed() {
415 ::core::hint::cold_path();
416 return ExecutionResult::Err(ExecutionError::IllegalInstruction {
417 address: PackedAddress::new(
418 program_counter.old_pc(zvexx_helpers::INSTRUCTION_SIZE),
419 ),
420 });
421 }
422 let Some(vtype) = env.vtype() else {
423 ::core::hint::cold_path();
424 return ExecutionResult::Err(ExecutionError::IllegalInstruction {
425 address: PackedAddress::new(
426 program_counter.old_pc(zvexx_helpers::INSTRUCTION_SIZE),
427 ),
428 });
429 };
430 let sew = vtype.vsew();
431 let group_regs = vtype.vlmul().register_count();
432 let wide_eew = match sew {
433 Vsew::E8 => Eew::E16,
434 Vsew::E16 => Eew::E32,
435 Vsew::E32 => Eew::E64,
436 Vsew::E64 => {
437 ::core::hint::cold_path();
438 return ExecutionResult::Err(ExecutionError::IllegalInstruction {
439 address: PackedAddress::new(
440 program_counter.old_pc(zvexx_helpers::INSTRUCTION_SIZE),
441 ),
442 });
443 }
444 };
445 if u32::from(wide_eew.bits_width()) > u32::from(Env::ELEN) {
446 ::core::hint::cold_path();
447 return ExecutionResult::Err(ExecutionError::IllegalInstruction {
448 address: PackedAddress::new(
449 program_counter.old_pc(zvexx_helpers::INSTRUCTION_SIZE),
450 ),
451 });
452 }
453 let wide_group_regs = vtype.vlmul().data_register_count(wide_eew, sew).ok_or(
454 ExecutionError::IllegalInstruction {
455 address: PackedAddress::new(
456 program_counter.old_pc(zvexx_helpers::INSTRUCTION_SIZE),
457 ),
458 },
459 )?;
460 zvexx_widen_narrow_helpers::check_vd_widen_alignment::<Reg, _, _>(
461 program_counter,
462 vd,
463 vs2,
464 Some(vs1),
465 group_regs,
466 wide_group_regs,
467 )?;
468 zvexx_widen_narrow_helpers::check_vreg_group_alignment::<Reg, _, _>(
469 program_counter,
470 vs2,
471 group_regs,
472 )?;
473 zvexx_widen_narrow_helpers::check_vreg_group_alignment::<Reg, _, _>(
474 program_counter,
475 vs1,
476 group_regs,
477 )?;
478 if !vm && vd == VReg::V0 {
479 ::core::hint::cold_path();
480 return ExecutionResult::Err(ExecutionError::IllegalInstruction {
481 address: PackedAddress::new(
482 program_counter.old_pc(zvexx_helpers::INSTRUCTION_SIZE),
483 ),
484 });
485 }
486 unsafe {
488 zvexx_widen_narrow_helpers::execute_widen_op::<true, _, _, _>(
489 env,
490 vd,
491 vs2,
492 zvexx_widen_narrow_helpers::OpSrc::Vreg(vs1),
493 vm,
494 sew,
495 u64::wrapping_sub,
496 );
497 }
498 }
499 Self::VwsubuVx {
501 vd,
502 vs2,
503 rs1: _,
504 vm,
505 } => {
506 if !env.vector_instructions_allowed() {
507 ::core::hint::cold_path();
508 return ExecutionResult::Err(ExecutionError::IllegalInstruction {
509 address: PackedAddress::new(
510 program_counter.old_pc(zvexx_helpers::INSTRUCTION_SIZE),
511 ),
512 });
513 }
514 let Some(vtype) = env.vtype() else {
515 ::core::hint::cold_path();
516 return ExecutionResult::Err(ExecutionError::IllegalInstruction {
517 address: PackedAddress::new(
518 program_counter.old_pc(zvexx_helpers::INSTRUCTION_SIZE),
519 ),
520 });
521 };
522 let sew = vtype.vsew();
523 let group_regs = vtype.vlmul().register_count();
524 let wide_eew = match sew {
525 Vsew::E8 => Eew::E16,
526 Vsew::E16 => Eew::E32,
527 Vsew::E32 => Eew::E64,
528 Vsew::E64 => {
529 ::core::hint::cold_path();
530 return ExecutionResult::Err(ExecutionError::IllegalInstruction {
531 address: PackedAddress::new(
532 program_counter.old_pc(zvexx_helpers::INSTRUCTION_SIZE),
533 ),
534 });
535 }
536 };
537 if u32::from(wide_eew.bits_width()) > u32::from(Env::ELEN) {
538 ::core::hint::cold_path();
539 return ExecutionResult::Err(ExecutionError::IllegalInstruction {
540 address: PackedAddress::new(
541 program_counter.old_pc(zvexx_helpers::INSTRUCTION_SIZE),
542 ),
543 });
544 }
545 let wide_group_regs = vtype.vlmul().data_register_count(wide_eew, sew).ok_or(
546 ExecutionError::IllegalInstruction {
547 address: PackedAddress::new(
548 program_counter.old_pc(zvexx_helpers::INSTRUCTION_SIZE),
549 ),
550 },
551 )?;
552 zvexx_widen_narrow_helpers::check_vd_widen_alignment::<Reg, _, _>(
553 program_counter,
554 vd,
555 vs2,
556 None,
557 group_regs,
558 wide_group_regs,
559 )?;
560 zvexx_widen_narrow_helpers::check_vreg_group_alignment::<Reg, _, _>(
561 program_counter,
562 vs2,
563 group_regs,
564 )?;
565 if !vm && vd == VReg::V0 {
566 ::core::hint::cold_path();
567 return ExecutionResult::Err(ExecutionError::IllegalInstruction {
568 address: PackedAddress::new(
569 program_counter.old_pc(zvexx_helpers::INSTRUCTION_SIZE),
570 ),
571 });
572 }
573 let scalar = rs1_value.as_u64();
574 unsafe {
576 zvexx_widen_narrow_helpers::execute_widen_op::<true, _, _, _>(
577 env,
578 vd,
579 vs2,
580 zvexx_widen_narrow_helpers::OpSrc::Scalar(scalar),
581 vm,
582 sew,
583 u64::wrapping_sub,
584 );
585 }
586 }
587 Self::VwsubVv { vd, vs2, vs1, vm } => {
589 if !env.vector_instructions_allowed() {
590 ::core::hint::cold_path();
591 return ExecutionResult::Err(ExecutionError::IllegalInstruction {
592 address: PackedAddress::new(
593 program_counter.old_pc(zvexx_helpers::INSTRUCTION_SIZE),
594 ),
595 });
596 }
597 let Some(vtype) = env.vtype() else {
598 ::core::hint::cold_path();
599 return ExecutionResult::Err(ExecutionError::IllegalInstruction {
600 address: PackedAddress::new(
601 program_counter.old_pc(zvexx_helpers::INSTRUCTION_SIZE),
602 ),
603 });
604 };
605 let sew = vtype.vsew();
606 let group_regs = vtype.vlmul().register_count();
607 let wide_eew = match sew {
608 Vsew::E8 => Eew::E16,
609 Vsew::E16 => Eew::E32,
610 Vsew::E32 => Eew::E64,
611 Vsew::E64 => {
612 ::core::hint::cold_path();
613 return ExecutionResult::Err(ExecutionError::IllegalInstruction {
614 address: PackedAddress::new(
615 program_counter.old_pc(zvexx_helpers::INSTRUCTION_SIZE),
616 ),
617 });
618 }
619 };
620 if u32::from(wide_eew.bits_width()) > u32::from(Env::ELEN) {
621 ::core::hint::cold_path();
622 return ExecutionResult::Err(ExecutionError::IllegalInstruction {
623 address: PackedAddress::new(
624 program_counter.old_pc(zvexx_helpers::INSTRUCTION_SIZE),
625 ),
626 });
627 }
628 let wide_group_regs = vtype.vlmul().data_register_count(wide_eew, sew).ok_or(
629 ExecutionError::IllegalInstruction {
630 address: PackedAddress::new(
631 program_counter.old_pc(zvexx_helpers::INSTRUCTION_SIZE),
632 ),
633 },
634 )?;
635 zvexx_widen_narrow_helpers::check_vd_widen_alignment::<Reg, _, _>(
636 program_counter,
637 vd,
638 vs2,
639 Some(vs1),
640 group_regs,
641 wide_group_regs,
642 )?;
643 zvexx_widen_narrow_helpers::check_vreg_group_alignment::<Reg, _, _>(
644 program_counter,
645 vs2,
646 group_regs,
647 )?;
648 zvexx_widen_narrow_helpers::check_vreg_group_alignment::<Reg, _, _>(
649 program_counter,
650 vs1,
651 group_regs,
652 )?;
653 if !vm && vd == VReg::V0 {
654 ::core::hint::cold_path();
655 return ExecutionResult::Err(ExecutionError::IllegalInstruction {
656 address: PackedAddress::new(
657 program_counter.old_pc(zvexx_helpers::INSTRUCTION_SIZE),
658 ),
659 });
660 }
661 unsafe {
663 zvexx_widen_narrow_helpers::execute_widen_op::<false, _, _, _>(
664 env,
665 vd,
666 vs2,
667 zvexx_widen_narrow_helpers::OpSrc::Vreg(vs1),
668 vm,
669 sew,
670 u64::wrapping_sub,
671 );
672 }
673 }
674 Self::VwsubVx {
676 vd,
677 vs2,
678 rs1: _,
679 vm,
680 } => {
681 if !env.vector_instructions_allowed() {
682 ::core::hint::cold_path();
683 return ExecutionResult::Err(ExecutionError::IllegalInstruction {
684 address: PackedAddress::new(
685 program_counter.old_pc(zvexx_helpers::INSTRUCTION_SIZE),
686 ),
687 });
688 }
689 let Some(vtype) = env.vtype() else {
690 ::core::hint::cold_path();
691 return ExecutionResult::Err(ExecutionError::IllegalInstruction {
692 address: PackedAddress::new(
693 program_counter.old_pc(zvexx_helpers::INSTRUCTION_SIZE),
694 ),
695 });
696 };
697 let sew = vtype.vsew();
698 let group_regs = vtype.vlmul().register_count();
699 let wide_eew = match sew {
700 Vsew::E8 => Eew::E16,
701 Vsew::E16 => Eew::E32,
702 Vsew::E32 => Eew::E64,
703 Vsew::E64 => {
704 ::core::hint::cold_path();
705 return ExecutionResult::Err(ExecutionError::IllegalInstruction {
706 address: PackedAddress::new(
707 program_counter.old_pc(zvexx_helpers::INSTRUCTION_SIZE),
708 ),
709 });
710 }
711 };
712 if u32::from(wide_eew.bits_width()) > u32::from(Env::ELEN) {
713 ::core::hint::cold_path();
714 return ExecutionResult::Err(ExecutionError::IllegalInstruction {
715 address: PackedAddress::new(
716 program_counter.old_pc(zvexx_helpers::INSTRUCTION_SIZE),
717 ),
718 });
719 }
720 let wide_group_regs = vtype.vlmul().data_register_count(wide_eew, sew).ok_or(
721 ExecutionError::IllegalInstruction {
722 address: PackedAddress::new(
723 program_counter.old_pc(zvexx_helpers::INSTRUCTION_SIZE),
724 ),
725 },
726 )?;
727 zvexx_widen_narrow_helpers::check_vd_widen_alignment::<Reg, _, _>(
728 program_counter,
729 vd,
730 vs2,
731 None,
732 group_regs,
733 wide_group_regs,
734 )?;
735 zvexx_widen_narrow_helpers::check_vreg_group_alignment::<Reg, _, _>(
736 program_counter,
737 vs2,
738 group_regs,
739 )?;
740 if !vm && vd == VReg::V0 {
741 ::core::hint::cold_path();
742 return ExecutionResult::Err(ExecutionError::IllegalInstruction {
743 address: PackedAddress::new(
744 program_counter.old_pc(zvexx_helpers::INSTRUCTION_SIZE),
745 ),
746 });
747 }
748 let scalar = zvexx_widen_narrow_helpers::sign_extend_bits(
749 rs1_value.as_u64(),
750 Vsew::from_xlen::<Reg>(),
751 )
752 .cast_unsigned();
753 unsafe {
755 zvexx_widen_narrow_helpers::execute_widen_op::<false, _, _, _>(
756 env,
757 vd,
758 vs2,
759 zvexx_widen_narrow_helpers::OpSrc::Scalar(scalar),
760 vm,
761 sew,
762 u64::wrapping_sub,
763 );
764 }
765 }
766 Self::VwadduWv { vd, vs2, vs1, vm } => {
768 if !env.vector_instructions_allowed() {
769 ::core::hint::cold_path();
770 return ExecutionResult::Err(ExecutionError::IllegalInstruction {
771 address: PackedAddress::new(
772 program_counter.old_pc(zvexx_helpers::INSTRUCTION_SIZE),
773 ),
774 });
775 }
776 let Some(vtype) = env.vtype() else {
777 ::core::hint::cold_path();
778 return ExecutionResult::Err(ExecutionError::IllegalInstruction {
779 address: PackedAddress::new(
780 program_counter.old_pc(zvexx_helpers::INSTRUCTION_SIZE),
781 ),
782 });
783 };
784 let sew = vtype.vsew();
785 let group_regs = vtype.vlmul().register_count();
786 let wide_eew = match sew {
787 Vsew::E8 => Eew::E16,
788 Vsew::E16 => Eew::E32,
789 Vsew::E32 => Eew::E64,
790 Vsew::E64 => {
791 ::core::hint::cold_path();
792 return ExecutionResult::Err(ExecutionError::IllegalInstruction {
793 address: PackedAddress::new(
794 program_counter.old_pc(zvexx_helpers::INSTRUCTION_SIZE),
795 ),
796 });
797 }
798 };
799 if u32::from(wide_eew.bits_width()) > u32::from(Env::ELEN) {
800 ::core::hint::cold_path();
801 return ExecutionResult::Err(ExecutionError::IllegalInstruction {
802 address: PackedAddress::new(
803 program_counter.old_pc(zvexx_helpers::INSTRUCTION_SIZE),
804 ),
805 });
806 }
807 let wide_group_regs = vtype.vlmul().data_register_count(wide_eew, sew).ok_or(
808 ExecutionError::IllegalInstruction {
809 address: PackedAddress::new(
810 program_counter.old_pc(zvexx_helpers::INSTRUCTION_SIZE),
811 ),
812 },
813 )?;
814 zvexx_widen_narrow_helpers::check_vs_wide_alignment::<Reg, _, _>(
816 program_counter,
817 vs2,
818 wide_group_regs,
819 )?;
820 zvexx_widen_narrow_helpers::check_vreg_group_alignment::<Reg, _, _>(
821 program_counter,
822 vs1,
823 group_regs,
824 )?;
825 zvexx_widen_narrow_helpers::check_vd_widen_alignment::<Reg, _, _>(
826 program_counter,
827 vd,
828 vs1,
829 None,
830 group_regs,
831 wide_group_regs,
832 )?;
833 if !vm && vd == VReg::V0 {
834 ::core::hint::cold_path();
835 return ExecutionResult::Err(ExecutionError::IllegalInstruction {
836 address: PackedAddress::new(
837 program_counter.old_pc(zvexx_helpers::INSTRUCTION_SIZE),
838 ),
839 });
840 }
841 unsafe {
843 zvexx_widen_narrow_helpers::execute_widen_w_op::<true, _, _, _>(
844 env,
845 vd,
846 vs2,
847 zvexx_widen_narrow_helpers::OpSrc::Vreg(vs1),
848 vm,
849 sew,
850 u64::wrapping_add,
851 );
852 }
853 }
854 Self::VwadduWx {
856 vd,
857 vs2,
858 rs1: _,
859 vm,
860 } => {
861 if !env.vector_instructions_allowed() {
862 ::core::hint::cold_path();
863 return ExecutionResult::Err(ExecutionError::IllegalInstruction {
864 address: PackedAddress::new(
865 program_counter.old_pc(zvexx_helpers::INSTRUCTION_SIZE),
866 ),
867 });
868 }
869 let Some(vtype) = env.vtype() else {
870 ::core::hint::cold_path();
871 return ExecutionResult::Err(ExecutionError::IllegalInstruction {
872 address: PackedAddress::new(
873 program_counter.old_pc(zvexx_helpers::INSTRUCTION_SIZE),
874 ),
875 });
876 };
877 let sew = vtype.vsew();
878 let wide_eew = match sew {
879 Vsew::E8 => Eew::E16,
880 Vsew::E16 => Eew::E32,
881 Vsew::E32 => Eew::E64,
882 Vsew::E64 => {
883 ::core::hint::cold_path();
884 return ExecutionResult::Err(ExecutionError::IllegalInstruction {
885 address: PackedAddress::new(
886 program_counter.old_pc(zvexx_helpers::INSTRUCTION_SIZE),
887 ),
888 });
889 }
890 };
891 if u32::from(wide_eew.bits_width()) > u32::from(Env::ELEN) {
892 ::core::hint::cold_path();
893 return ExecutionResult::Err(ExecutionError::IllegalInstruction {
894 address: PackedAddress::new(
895 program_counter.old_pc(zvexx_helpers::INSTRUCTION_SIZE),
896 ),
897 });
898 }
899 let wide_group_regs = vtype.vlmul().data_register_count(wide_eew, sew).ok_or(
900 ExecutionError::IllegalInstruction {
901 address: PackedAddress::new(
902 program_counter.old_pc(zvexx_helpers::INSTRUCTION_SIZE),
903 ),
904 },
905 )?;
906 zvexx_widen_narrow_helpers::check_vs_wide_alignment::<Reg, _, _>(
908 program_counter,
909 vs2,
910 wide_group_regs,
911 )?;
912 zvexx_widen_narrow_helpers::check_vd_widen_no_src_check::<Reg, _, _>(
913 program_counter,
914 vd,
915 wide_group_regs,
916 )?;
917 if !vm && vd == VReg::V0 {
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 let scalar = rs1_value.as_u64();
926 unsafe {
928 zvexx_widen_narrow_helpers::execute_widen_w_op::<true, _, _, _>(
929 env,
930 vd,
931 vs2,
932 zvexx_widen_narrow_helpers::OpSrc::Scalar(scalar),
933 vm,
934 sew,
935 u64::wrapping_add,
936 );
937 }
938 }
939 Self::VwaddWv { vd, vs2, vs1, vm } => {
941 if !env.vector_instructions_allowed() {
942 ::core::hint::cold_path();
943 return ExecutionResult::Err(ExecutionError::IllegalInstruction {
944 address: PackedAddress::new(
945 program_counter.old_pc(zvexx_helpers::INSTRUCTION_SIZE),
946 ),
947 });
948 }
949 let Some(vtype) = env.vtype() else {
950 ::core::hint::cold_path();
951 return ExecutionResult::Err(ExecutionError::IllegalInstruction {
952 address: PackedAddress::new(
953 program_counter.old_pc(zvexx_helpers::INSTRUCTION_SIZE),
954 ),
955 });
956 };
957 let sew = vtype.vsew();
958 let group_regs = vtype.vlmul().register_count();
959 let wide_eew = match sew {
960 Vsew::E8 => Eew::E16,
961 Vsew::E16 => Eew::E32,
962 Vsew::E32 => Eew::E64,
963 Vsew::E64 => {
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 };
972 if u32::from(wide_eew.bits_width()) > u32::from(Env::ELEN) {
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 let wide_group_regs = vtype.vlmul().data_register_count(wide_eew, sew).ok_or(
981 ExecutionError::IllegalInstruction {
982 address: PackedAddress::new(
983 program_counter.old_pc(zvexx_helpers::INSTRUCTION_SIZE),
984 ),
985 },
986 )?;
987 zvexx_widen_narrow_helpers::check_vs_wide_alignment::<Reg, _, _>(
988 program_counter,
989 vs2,
990 wide_group_regs,
991 )?;
992 zvexx_widen_narrow_helpers::check_vreg_group_alignment::<Reg, _, _>(
993 program_counter,
994 vs1,
995 group_regs,
996 )?;
997 zvexx_widen_narrow_helpers::check_vd_widen_alignment::<Reg, _, _>(
998 program_counter,
999 vd,
1000 vs1,
1001 None,
1002 group_regs,
1003 wide_group_regs,
1004 )?;
1005 if !vm && vd == VReg::V0 {
1006 ::core::hint::cold_path();
1007 return ExecutionResult::Err(ExecutionError::IllegalInstruction {
1008 address: PackedAddress::new(
1009 program_counter.old_pc(zvexx_helpers::INSTRUCTION_SIZE),
1010 ),
1011 });
1012 }
1013 unsafe {
1015 zvexx_widen_narrow_helpers::execute_widen_w_op::<false, _, _, _>(
1016 env,
1017 vd,
1018 vs2,
1019 zvexx_widen_narrow_helpers::OpSrc::Vreg(vs1),
1020 vm,
1021 sew,
1022 u64::wrapping_add,
1023 );
1024 }
1025 }
1026 Self::VwaddWx {
1028 vd,
1029 vs2,
1030 rs1: _,
1031 vm,
1032 } => {
1033 if !env.vector_instructions_allowed() {
1034 ::core::hint::cold_path();
1035 return ExecutionResult::Err(ExecutionError::IllegalInstruction {
1036 address: PackedAddress::new(
1037 program_counter.old_pc(zvexx_helpers::INSTRUCTION_SIZE),
1038 ),
1039 });
1040 }
1041 let Some(vtype) = env.vtype() else {
1042 ::core::hint::cold_path();
1043 return ExecutionResult::Err(ExecutionError::IllegalInstruction {
1044 address: PackedAddress::new(
1045 program_counter.old_pc(zvexx_helpers::INSTRUCTION_SIZE),
1046 ),
1047 });
1048 };
1049 let sew = vtype.vsew();
1050 let wide_eew = match sew {
1051 Vsew::E8 => Eew::E16,
1052 Vsew::E16 => Eew::E32,
1053 Vsew::E32 => Eew::E64,
1054 Vsew::E64 => {
1055 ::core::hint::cold_path();
1056 return ExecutionResult::Err(ExecutionError::IllegalInstruction {
1057 address: PackedAddress::new(
1058 program_counter.old_pc(zvexx_helpers::INSTRUCTION_SIZE),
1059 ),
1060 });
1061 }
1062 };
1063 if u32::from(wide_eew.bits_width()) > u32::from(Env::ELEN) {
1064 ::core::hint::cold_path();
1065 return ExecutionResult::Err(ExecutionError::IllegalInstruction {
1066 address: PackedAddress::new(
1067 program_counter.old_pc(zvexx_helpers::INSTRUCTION_SIZE),
1068 ),
1069 });
1070 }
1071 let wide_group_regs = vtype.vlmul().data_register_count(wide_eew, sew).ok_or(
1072 ExecutionError::IllegalInstruction {
1073 address: PackedAddress::new(
1074 program_counter.old_pc(zvexx_helpers::INSTRUCTION_SIZE),
1075 ),
1076 },
1077 )?;
1078 zvexx_widen_narrow_helpers::check_vs_wide_alignment::<Reg, _, _>(
1079 program_counter,
1080 vs2,
1081 wide_group_regs,
1082 )?;
1083 zvexx_widen_narrow_helpers::check_vd_widen_no_src_check::<Reg, _, _>(
1084 program_counter,
1085 vd,
1086 wide_group_regs,
1087 )?;
1088 if !vm && vd == VReg::V0 {
1089 ::core::hint::cold_path();
1090 return ExecutionResult::Err(ExecutionError::IllegalInstruction {
1091 address: PackedAddress::new(
1092 program_counter.old_pc(zvexx_helpers::INSTRUCTION_SIZE),
1093 ),
1094 });
1095 }
1096 let scalar = zvexx_widen_narrow_helpers::sign_extend_bits(
1097 rs1_value.as_u64(),
1098 Vsew::from_xlen::<Reg>(),
1099 )
1100 .cast_unsigned();
1101 unsafe {
1103 zvexx_widen_narrow_helpers::execute_widen_w_op::<false, _, _, _>(
1104 env,
1105 vd,
1106 vs2,
1107 zvexx_widen_narrow_helpers::OpSrc::Scalar(scalar),
1108 vm,
1109 sew,
1110 u64::wrapping_add,
1111 );
1112 }
1113 }
1114 Self::VwsubuWv { vd, vs2, vs1, vm } => {
1116 if !env.vector_instructions_allowed() {
1117 ::core::hint::cold_path();
1118 return ExecutionResult::Err(ExecutionError::IllegalInstruction {
1119 address: PackedAddress::new(
1120 program_counter.old_pc(zvexx_helpers::INSTRUCTION_SIZE),
1121 ),
1122 });
1123 }
1124 let Some(vtype) = env.vtype() else {
1125 ::core::hint::cold_path();
1126 return ExecutionResult::Err(ExecutionError::IllegalInstruction {
1127 address: PackedAddress::new(
1128 program_counter.old_pc(zvexx_helpers::INSTRUCTION_SIZE),
1129 ),
1130 });
1131 };
1132 let sew = vtype.vsew();
1133 let group_regs = vtype.vlmul().register_count();
1134 let wide_eew = match sew {
1135 Vsew::E8 => Eew::E16,
1136 Vsew::E16 => Eew::E32,
1137 Vsew::E32 => Eew::E64,
1138 Vsew::E64 => {
1139 ::core::hint::cold_path();
1140 return ExecutionResult::Err(ExecutionError::IllegalInstruction {
1141 address: PackedAddress::new(
1142 program_counter.old_pc(zvexx_helpers::INSTRUCTION_SIZE),
1143 ),
1144 });
1145 }
1146 };
1147 if u32::from(wide_eew.bits_width()) > u32::from(Env::ELEN) {
1148 ::core::hint::cold_path();
1149 return ExecutionResult::Err(ExecutionError::IllegalInstruction {
1150 address: PackedAddress::new(
1151 program_counter.old_pc(zvexx_helpers::INSTRUCTION_SIZE),
1152 ),
1153 });
1154 }
1155 let wide_group_regs = vtype.vlmul().data_register_count(wide_eew, sew).ok_or(
1156 ExecutionError::IllegalInstruction {
1157 address: PackedAddress::new(
1158 program_counter.old_pc(zvexx_helpers::INSTRUCTION_SIZE),
1159 ),
1160 },
1161 )?;
1162 zvexx_widen_narrow_helpers::check_vs_wide_alignment::<Reg, _, _>(
1163 program_counter,
1164 vs2,
1165 wide_group_regs,
1166 )?;
1167 zvexx_widen_narrow_helpers::check_vreg_group_alignment::<Reg, _, _>(
1168 program_counter,
1169 vs1,
1170 group_regs,
1171 )?;
1172 zvexx_widen_narrow_helpers::check_vd_widen_alignment::<Reg, _, _>(
1173 program_counter,
1174 vd,
1175 vs1,
1176 None,
1177 group_regs,
1178 wide_group_regs,
1179 )?;
1180 if !vm && vd == VReg::V0 {
1181 ::core::hint::cold_path();
1182 return ExecutionResult::Err(ExecutionError::IllegalInstruction {
1183 address: PackedAddress::new(
1184 program_counter.old_pc(zvexx_helpers::INSTRUCTION_SIZE),
1185 ),
1186 });
1187 }
1188 unsafe {
1190 zvexx_widen_narrow_helpers::execute_widen_w_op::<true, _, _, _>(
1191 env,
1192 vd,
1193 vs2,
1194 zvexx_widen_narrow_helpers::OpSrc::Vreg(vs1),
1195 vm,
1196 sew,
1197 u64::wrapping_sub,
1198 );
1199 }
1200 }
1201 Self::VwsubuWx {
1203 vd,
1204 vs2,
1205 rs1: _,
1206 vm,
1207 } => {
1208 if !env.vector_instructions_allowed() {
1209 ::core::hint::cold_path();
1210 return ExecutionResult::Err(ExecutionError::IllegalInstruction {
1211 address: PackedAddress::new(
1212 program_counter.old_pc(zvexx_helpers::INSTRUCTION_SIZE),
1213 ),
1214 });
1215 }
1216 let Some(vtype) = env.vtype() else {
1217 ::core::hint::cold_path();
1218 return ExecutionResult::Err(ExecutionError::IllegalInstruction {
1219 address: PackedAddress::new(
1220 program_counter.old_pc(zvexx_helpers::INSTRUCTION_SIZE),
1221 ),
1222 });
1223 };
1224 let sew = vtype.vsew();
1225 let wide_eew = match sew {
1226 Vsew::E8 => Eew::E16,
1227 Vsew::E16 => Eew::E32,
1228 Vsew::E32 => Eew::E64,
1229 Vsew::E64 => {
1230 ::core::hint::cold_path();
1231 return ExecutionResult::Err(ExecutionError::IllegalInstruction {
1232 address: PackedAddress::new(
1233 program_counter.old_pc(zvexx_helpers::INSTRUCTION_SIZE),
1234 ),
1235 });
1236 }
1237 };
1238 if u32::from(wide_eew.bits_width()) > u32::from(Env::ELEN) {
1239 ::core::hint::cold_path();
1240 return ExecutionResult::Err(ExecutionError::IllegalInstruction {
1241 address: PackedAddress::new(
1242 program_counter.old_pc(zvexx_helpers::INSTRUCTION_SIZE),
1243 ),
1244 });
1245 }
1246 let wide_group_regs = vtype.vlmul().data_register_count(wide_eew, sew).ok_or(
1247 ExecutionError::IllegalInstruction {
1248 address: PackedAddress::new(
1249 program_counter.old_pc(zvexx_helpers::INSTRUCTION_SIZE),
1250 ),
1251 },
1252 )?;
1253 zvexx_widen_narrow_helpers::check_vs_wide_alignment::<Reg, _, _>(
1254 program_counter,
1255 vs2,
1256 wide_group_regs,
1257 )?;
1258 zvexx_widen_narrow_helpers::check_vd_widen_no_src_check::<Reg, _, _>(
1259 program_counter,
1260 vd,
1261 wide_group_regs,
1262 )?;
1263 if !vm && vd == VReg::V0 {
1264 ::core::hint::cold_path();
1265 return ExecutionResult::Err(ExecutionError::IllegalInstruction {
1266 address: PackedAddress::new(
1267 program_counter.old_pc(zvexx_helpers::INSTRUCTION_SIZE),
1268 ),
1269 });
1270 }
1271 let scalar = rs1_value.as_u64();
1272 unsafe {
1274 zvexx_widen_narrow_helpers::execute_widen_w_op::<true, _, _, _>(
1275 env,
1276 vd,
1277 vs2,
1278 zvexx_widen_narrow_helpers::OpSrc::Scalar(scalar),
1279 vm,
1280 sew,
1281 u64::wrapping_sub,
1282 );
1283 }
1284 }
1285 Self::VwsubWv { vd, vs2, vs1, vm } => {
1287 if !env.vector_instructions_allowed() {
1288 ::core::hint::cold_path();
1289 return ExecutionResult::Err(ExecutionError::IllegalInstruction {
1290 address: PackedAddress::new(
1291 program_counter.old_pc(zvexx_helpers::INSTRUCTION_SIZE),
1292 ),
1293 });
1294 }
1295 let Some(vtype) = env.vtype() else {
1296 ::core::hint::cold_path();
1297 return ExecutionResult::Err(ExecutionError::IllegalInstruction {
1298 address: PackedAddress::new(
1299 program_counter.old_pc(zvexx_helpers::INSTRUCTION_SIZE),
1300 ),
1301 });
1302 };
1303 let sew = vtype.vsew();
1304 let group_regs = vtype.vlmul().register_count();
1305 let wide_eew = match sew {
1306 Vsew::E8 => Eew::E16,
1307 Vsew::E16 => Eew::E32,
1308 Vsew::E32 => Eew::E64,
1309 Vsew::E64 => {
1310 ::core::hint::cold_path();
1311 return ExecutionResult::Err(ExecutionError::IllegalInstruction {
1312 address: PackedAddress::new(
1313 program_counter.old_pc(zvexx_helpers::INSTRUCTION_SIZE),
1314 ),
1315 });
1316 }
1317 };
1318 if u32::from(wide_eew.bits_width()) > u32::from(Env::ELEN) {
1319 ::core::hint::cold_path();
1320 return ExecutionResult::Err(ExecutionError::IllegalInstruction {
1321 address: PackedAddress::new(
1322 program_counter.old_pc(zvexx_helpers::INSTRUCTION_SIZE),
1323 ),
1324 });
1325 }
1326 let wide_group_regs = vtype.vlmul().data_register_count(wide_eew, sew).ok_or(
1327 ExecutionError::IllegalInstruction {
1328 address: PackedAddress::new(
1329 program_counter.old_pc(zvexx_helpers::INSTRUCTION_SIZE),
1330 ),
1331 },
1332 )?;
1333 zvexx_widen_narrow_helpers::check_vs_wide_alignment::<Reg, _, _>(
1334 program_counter,
1335 vs2,
1336 wide_group_regs,
1337 )?;
1338 zvexx_widen_narrow_helpers::check_vreg_group_alignment::<Reg, _, _>(
1339 program_counter,
1340 vs1,
1341 group_regs,
1342 )?;
1343 zvexx_widen_narrow_helpers::check_vd_widen_alignment::<Reg, _, _>(
1344 program_counter,
1345 vd,
1346 vs1,
1347 None,
1348 group_regs,
1349 wide_group_regs,
1350 )?;
1351 if !vm && vd == VReg::V0 {
1352 ::core::hint::cold_path();
1353 return ExecutionResult::Err(ExecutionError::IllegalInstruction {
1354 address: PackedAddress::new(
1355 program_counter.old_pc(zvexx_helpers::INSTRUCTION_SIZE),
1356 ),
1357 });
1358 }
1359 unsafe {
1361 zvexx_widen_narrow_helpers::execute_widen_w_op::<false, _, _, _>(
1362 env,
1363 vd,
1364 vs2,
1365 zvexx_widen_narrow_helpers::OpSrc::Vreg(vs1),
1366 vm,
1367 sew,
1368 u64::wrapping_sub,
1369 );
1370 }
1371 }
1372 Self::VwsubWx {
1374 vd,
1375 vs2,
1376 rs1: _,
1377 vm,
1378 } => {
1379 if !env.vector_instructions_allowed() {
1380 ::core::hint::cold_path();
1381 return ExecutionResult::Err(ExecutionError::IllegalInstruction {
1382 address: PackedAddress::new(
1383 program_counter.old_pc(zvexx_helpers::INSTRUCTION_SIZE),
1384 ),
1385 });
1386 }
1387 let Some(vtype) = env.vtype() else {
1388 ::core::hint::cold_path();
1389 return ExecutionResult::Err(ExecutionError::IllegalInstruction {
1390 address: PackedAddress::new(
1391 program_counter.old_pc(zvexx_helpers::INSTRUCTION_SIZE),
1392 ),
1393 });
1394 };
1395 let sew = vtype.vsew();
1396 let wide_eew = match sew {
1397 Vsew::E8 => Eew::E16,
1398 Vsew::E16 => Eew::E32,
1399 Vsew::E32 => Eew::E64,
1400 Vsew::E64 => {
1401 ::core::hint::cold_path();
1402 return ExecutionResult::Err(ExecutionError::IllegalInstruction {
1403 address: PackedAddress::new(
1404 program_counter.old_pc(zvexx_helpers::INSTRUCTION_SIZE),
1405 ),
1406 });
1407 }
1408 };
1409 if u32::from(wide_eew.bits_width()) > u32::from(Env::ELEN) {
1410 ::core::hint::cold_path();
1411 return ExecutionResult::Err(ExecutionError::IllegalInstruction {
1412 address: PackedAddress::new(
1413 program_counter.old_pc(zvexx_helpers::INSTRUCTION_SIZE),
1414 ),
1415 });
1416 }
1417 let wide_group_regs = vtype.vlmul().data_register_count(wide_eew, sew).ok_or(
1418 ExecutionError::IllegalInstruction {
1419 address: PackedAddress::new(
1420 program_counter.old_pc(zvexx_helpers::INSTRUCTION_SIZE),
1421 ),
1422 },
1423 )?;
1424 zvexx_widen_narrow_helpers::check_vs_wide_alignment::<Reg, _, _>(
1425 program_counter,
1426 vs2,
1427 wide_group_regs,
1428 )?;
1429 zvexx_widen_narrow_helpers::check_vd_widen_no_src_check::<Reg, _, _>(
1430 program_counter,
1431 vd,
1432 wide_group_regs,
1433 )?;
1434 if !vm && vd == VReg::V0 {
1435 ::core::hint::cold_path();
1436 return ExecutionResult::Err(ExecutionError::IllegalInstruction {
1437 address: PackedAddress::new(
1438 program_counter.old_pc(zvexx_helpers::INSTRUCTION_SIZE),
1439 ),
1440 });
1441 }
1442 let scalar = zvexx_widen_narrow_helpers::sign_extend_bits(
1443 rs1_value.as_u64(),
1444 Vsew::from_xlen::<Reg>(),
1445 )
1446 .cast_unsigned();
1447 unsafe {
1449 zvexx_widen_narrow_helpers::execute_widen_w_op::<false, _, _, _>(
1450 env,
1451 vd,
1452 vs2,
1453 zvexx_widen_narrow_helpers::OpSrc::Scalar(scalar),
1454 vm,
1455 sew,
1456 u64::wrapping_sub,
1457 );
1458 }
1459 }
1460 Self::VnsrlWv { vd, vs2, vs1, vm } => {
1462 if !env.vector_instructions_allowed() {
1463 ::core::hint::cold_path();
1464 return ExecutionResult::Err(ExecutionError::IllegalInstruction {
1465 address: PackedAddress::new(
1466 program_counter.old_pc(zvexx_helpers::INSTRUCTION_SIZE),
1467 ),
1468 });
1469 }
1470 let Some(vtype) = env.vtype() else {
1471 ::core::hint::cold_path();
1472 return ExecutionResult::Err(ExecutionError::IllegalInstruction {
1473 address: PackedAddress::new(
1474 program_counter.old_pc(zvexx_helpers::INSTRUCTION_SIZE),
1475 ),
1476 });
1477 };
1478 let sew = vtype.vsew();
1479 let group_regs = vtype.vlmul().register_count();
1481 let wide_eew = match sew {
1482 Vsew::E8 => Eew::E16,
1483 Vsew::E16 => Eew::E32,
1484 Vsew::E32 => Eew::E64,
1485 Vsew::E64 => {
1486 ::core::hint::cold_path();
1487 return ExecutionResult::Err(ExecutionError::IllegalInstruction {
1488 address: PackedAddress::new(
1489 program_counter.old_pc(zvexx_helpers::INSTRUCTION_SIZE),
1490 ),
1491 });
1492 }
1493 };
1494 if u32::from(wide_eew.bits_width()) > u32::from(Env::ELEN) {
1495 ::core::hint::cold_path();
1496 return ExecutionResult::Err(ExecutionError::IllegalInstruction {
1497 address: PackedAddress::new(
1498 program_counter.old_pc(zvexx_helpers::INSTRUCTION_SIZE),
1499 ),
1500 });
1501 }
1502 let wide_group_regs = vtype.vlmul().data_register_count(wide_eew, sew).ok_or(
1503 ExecutionError::IllegalInstruction {
1504 address: PackedAddress::new(
1505 program_counter.old_pc(zvexx_helpers::INSTRUCTION_SIZE),
1506 ),
1507 },
1508 )?;
1509 zvexx_widen_narrow_helpers::check_vd_narrow_alignment::<Reg, _, _>(
1510 program_counter,
1511 vd,
1512 group_regs,
1513 )?;
1514 zvexx_widen_narrow_helpers::check_vs_wide_alignment::<Reg, _, _>(
1515 program_counter,
1516 vs2,
1517 wide_group_regs,
1518 )?;
1519 zvexx_widen_narrow_helpers::check_vreg_group_alignment::<Reg, _, _>(
1520 program_counter,
1521 vs1,
1522 group_regs,
1523 )?;
1524 if !vm && vd == VReg::V0 {
1525 ::core::hint::cold_path();
1526 return ExecutionResult::Err(ExecutionError::IllegalInstruction {
1527 address: PackedAddress::new(
1528 program_counter.old_pc(zvexx_helpers::INSTRUCTION_SIZE),
1529 ),
1530 });
1531 }
1532 unsafe {
1534 zvexx_widen_narrow_helpers::execute_narrow_shift::<false, _, _>(
1535 env,
1536 vd,
1537 vs2,
1538 zvexx_widen_narrow_helpers::OpSrc::Vreg(vs1),
1539 vm,
1540 sew,
1541 );
1542 }
1543 }
1544 Self::VnsrlWx {
1546 vd,
1547 vs2,
1548 rs1: _,
1549 vm,
1550 } => {
1551 if !env.vector_instructions_allowed() {
1552 ::core::hint::cold_path();
1553 return ExecutionResult::Err(ExecutionError::IllegalInstruction {
1554 address: PackedAddress::new(
1555 program_counter.old_pc(zvexx_helpers::INSTRUCTION_SIZE),
1556 ),
1557 });
1558 }
1559 let Some(vtype) = env.vtype() else {
1560 ::core::hint::cold_path();
1561 return ExecutionResult::Err(ExecutionError::IllegalInstruction {
1562 address: PackedAddress::new(
1563 program_counter.old_pc(zvexx_helpers::INSTRUCTION_SIZE),
1564 ),
1565 });
1566 };
1567 let sew = vtype.vsew();
1568 let group_regs = vtype.vlmul().register_count();
1569 let wide_eew = match sew {
1570 Vsew::E8 => Eew::E16,
1571 Vsew::E16 => Eew::E32,
1572 Vsew::E32 => Eew::E64,
1573 Vsew::E64 => {
1574 ::core::hint::cold_path();
1575 return ExecutionResult::Err(ExecutionError::IllegalInstruction {
1576 address: PackedAddress::new(
1577 program_counter.old_pc(zvexx_helpers::INSTRUCTION_SIZE),
1578 ),
1579 });
1580 }
1581 };
1582 if u32::from(wide_eew.bits_width()) > u32::from(Env::ELEN) {
1583 ::core::hint::cold_path();
1584 return ExecutionResult::Err(ExecutionError::IllegalInstruction {
1585 address: PackedAddress::new(
1586 program_counter.old_pc(zvexx_helpers::INSTRUCTION_SIZE),
1587 ),
1588 });
1589 }
1590 let wide_group_regs = vtype.vlmul().data_register_count(wide_eew, sew).ok_or(
1591 ExecutionError::IllegalInstruction {
1592 address: PackedAddress::new(
1593 program_counter.old_pc(zvexx_helpers::INSTRUCTION_SIZE),
1594 ),
1595 },
1596 )?;
1597 zvexx_widen_narrow_helpers::check_vd_narrow_alignment::<Reg, _, _>(
1598 program_counter,
1599 vd,
1600 group_regs,
1601 )?;
1602 zvexx_widen_narrow_helpers::check_vs_wide_alignment::<Reg, _, _>(
1603 program_counter,
1604 vs2,
1605 wide_group_regs,
1606 )?;
1607 if !vm && vd == VReg::V0 {
1608 ::core::hint::cold_path();
1609 return ExecutionResult::Err(ExecutionError::IllegalInstruction {
1610 address: PackedAddress::new(
1611 program_counter.old_pc(zvexx_helpers::INSTRUCTION_SIZE),
1612 ),
1613 });
1614 }
1615 let scalar = rs1_value.as_u64();
1616 unsafe {
1618 zvexx_widen_narrow_helpers::execute_narrow_shift::<false, _, _>(
1619 env,
1620 vd,
1621 vs2,
1622 zvexx_widen_narrow_helpers::OpSrc::Scalar(scalar),
1623 vm,
1624 sew,
1625 );
1626 }
1627 }
1628 Self::VnsrlWi { vd, vs2, uimm, vm } => {
1630 if !env.vector_instructions_allowed() {
1631 ::core::hint::cold_path();
1632 return ExecutionResult::Err(ExecutionError::IllegalInstruction {
1633 address: PackedAddress::new(
1634 program_counter.old_pc(zvexx_helpers::INSTRUCTION_SIZE),
1635 ),
1636 });
1637 }
1638 let Some(vtype) = env.vtype() else {
1639 ::core::hint::cold_path();
1640 return ExecutionResult::Err(ExecutionError::IllegalInstruction {
1641 address: PackedAddress::new(
1642 program_counter.old_pc(zvexx_helpers::INSTRUCTION_SIZE),
1643 ),
1644 });
1645 };
1646 let sew = vtype.vsew();
1647 let group_regs = vtype.vlmul().register_count();
1648 let wide_eew = match sew {
1649 Vsew::E8 => Eew::E16,
1650 Vsew::E16 => Eew::E32,
1651 Vsew::E32 => Eew::E64,
1652 Vsew::E64 => {
1653 ::core::hint::cold_path();
1654 return ExecutionResult::Err(ExecutionError::IllegalInstruction {
1655 address: PackedAddress::new(
1656 program_counter.old_pc(zvexx_helpers::INSTRUCTION_SIZE),
1657 ),
1658 });
1659 }
1660 };
1661 if u32::from(wide_eew.bits_width()) > u32::from(Env::ELEN) {
1662 ::core::hint::cold_path();
1663 return ExecutionResult::Err(ExecutionError::IllegalInstruction {
1664 address: PackedAddress::new(
1665 program_counter.old_pc(zvexx_helpers::INSTRUCTION_SIZE),
1666 ),
1667 });
1668 }
1669 let wide_group_regs = vtype.vlmul().data_register_count(wide_eew, sew).ok_or(
1670 ExecutionError::IllegalInstruction {
1671 address: PackedAddress::new(
1672 program_counter.old_pc(zvexx_helpers::INSTRUCTION_SIZE),
1673 ),
1674 },
1675 )?;
1676 zvexx_widen_narrow_helpers::check_vd_narrow_alignment::<Reg, _, _>(
1677 program_counter,
1678 vd,
1679 group_regs,
1680 )?;
1681 zvexx_widen_narrow_helpers::check_vs_wide_alignment::<Reg, _, _>(
1682 program_counter,
1683 vs2,
1684 wide_group_regs,
1685 )?;
1686 if !vm && vd == VReg::V0 {
1687 ::core::hint::cold_path();
1688 return ExecutionResult::Err(ExecutionError::IllegalInstruction {
1689 address: PackedAddress::new(
1690 program_counter.old_pc(zvexx_helpers::INSTRUCTION_SIZE),
1691 ),
1692 });
1693 }
1694 unsafe {
1696 zvexx_widen_narrow_helpers::execute_narrow_shift::<false, _, _>(
1697 env,
1698 vd,
1699 vs2,
1700 zvexx_widen_narrow_helpers::OpSrc::Scalar(u64::from(uimm)),
1701 vm,
1702 sew,
1703 );
1704 }
1705 }
1706 Self::VnsraWv { vd, vs2, vs1, vm } => {
1708 if !env.vector_instructions_allowed() {
1709 ::core::hint::cold_path();
1710 return ExecutionResult::Err(ExecutionError::IllegalInstruction {
1711 address: PackedAddress::new(
1712 program_counter.old_pc(zvexx_helpers::INSTRUCTION_SIZE),
1713 ),
1714 });
1715 }
1716 let Some(vtype) = env.vtype() else {
1717 ::core::hint::cold_path();
1718 return ExecutionResult::Err(ExecutionError::IllegalInstruction {
1719 address: PackedAddress::new(
1720 program_counter.old_pc(zvexx_helpers::INSTRUCTION_SIZE),
1721 ),
1722 });
1723 };
1724 let sew = vtype.vsew();
1725 let group_regs = vtype.vlmul().register_count();
1726 let wide_eew = match sew {
1727 Vsew::E8 => Eew::E16,
1728 Vsew::E16 => Eew::E32,
1729 Vsew::E32 => Eew::E64,
1730 Vsew::E64 => {
1731 ::core::hint::cold_path();
1732 return ExecutionResult::Err(ExecutionError::IllegalInstruction {
1733 address: PackedAddress::new(
1734 program_counter.old_pc(zvexx_helpers::INSTRUCTION_SIZE),
1735 ),
1736 });
1737 }
1738 };
1739 if u32::from(wide_eew.bits_width()) > u32::from(Env::ELEN) {
1740 ::core::hint::cold_path();
1741 return ExecutionResult::Err(ExecutionError::IllegalInstruction {
1742 address: PackedAddress::new(
1743 program_counter.old_pc(zvexx_helpers::INSTRUCTION_SIZE),
1744 ),
1745 });
1746 }
1747 let wide_group_regs = vtype.vlmul().data_register_count(wide_eew, sew).ok_or(
1748 ExecutionError::IllegalInstruction {
1749 address: PackedAddress::new(
1750 program_counter.old_pc(zvexx_helpers::INSTRUCTION_SIZE),
1751 ),
1752 },
1753 )?;
1754 zvexx_widen_narrow_helpers::check_vd_narrow_alignment::<Reg, _, _>(
1755 program_counter,
1756 vd,
1757 group_regs,
1758 )?;
1759 zvexx_widen_narrow_helpers::check_vs_wide_alignment::<Reg, _, _>(
1760 program_counter,
1761 vs2,
1762 wide_group_regs,
1763 )?;
1764 zvexx_widen_narrow_helpers::check_vreg_group_alignment::<Reg, _, _>(
1765 program_counter,
1766 vs1,
1767 group_regs,
1768 )?;
1769 if !vm && vd == VReg::V0 {
1770 ::core::hint::cold_path();
1771 return ExecutionResult::Err(ExecutionError::IllegalInstruction {
1772 address: PackedAddress::new(
1773 program_counter.old_pc(zvexx_helpers::INSTRUCTION_SIZE),
1774 ),
1775 });
1776 }
1777 unsafe {
1779 zvexx_widen_narrow_helpers::execute_narrow_shift::<true, _, _>(
1780 env,
1781 vd,
1782 vs2,
1783 zvexx_widen_narrow_helpers::OpSrc::Vreg(vs1),
1784 vm,
1785 sew,
1786 );
1787 }
1788 }
1789 Self::VnsraWx {
1791 vd,
1792 vs2,
1793 rs1: _,
1794 vm,
1795 } => {
1796 if !env.vector_instructions_allowed() {
1797 ::core::hint::cold_path();
1798 return ExecutionResult::Err(ExecutionError::IllegalInstruction {
1799 address: PackedAddress::new(
1800 program_counter.old_pc(zvexx_helpers::INSTRUCTION_SIZE),
1801 ),
1802 });
1803 }
1804 let Some(vtype) = env.vtype() else {
1805 ::core::hint::cold_path();
1806 return ExecutionResult::Err(ExecutionError::IllegalInstruction {
1807 address: PackedAddress::new(
1808 program_counter.old_pc(zvexx_helpers::INSTRUCTION_SIZE),
1809 ),
1810 });
1811 };
1812 let sew = vtype.vsew();
1813 let group_regs = vtype.vlmul().register_count();
1814 let wide_eew = match sew {
1815 Vsew::E8 => Eew::E16,
1816 Vsew::E16 => Eew::E32,
1817 Vsew::E32 => Eew::E64,
1818 Vsew::E64 => {
1819 ::core::hint::cold_path();
1820 return ExecutionResult::Err(ExecutionError::IllegalInstruction {
1821 address: PackedAddress::new(
1822 program_counter.old_pc(zvexx_helpers::INSTRUCTION_SIZE),
1823 ),
1824 });
1825 }
1826 };
1827 if u32::from(wide_eew.bits_width()) > u32::from(Env::ELEN) {
1828 ::core::hint::cold_path();
1829 return ExecutionResult::Err(ExecutionError::IllegalInstruction {
1830 address: PackedAddress::new(
1831 program_counter.old_pc(zvexx_helpers::INSTRUCTION_SIZE),
1832 ),
1833 });
1834 }
1835 let wide_group_regs = vtype.vlmul().data_register_count(wide_eew, sew).ok_or(
1836 ExecutionError::IllegalInstruction {
1837 address: PackedAddress::new(
1838 program_counter.old_pc(zvexx_helpers::INSTRUCTION_SIZE),
1839 ),
1840 },
1841 )?;
1842 zvexx_widen_narrow_helpers::check_vd_narrow_alignment::<Reg, _, _>(
1843 program_counter,
1844 vd,
1845 group_regs,
1846 )?;
1847 zvexx_widen_narrow_helpers::check_vs_wide_alignment::<Reg, _, _>(
1848 program_counter,
1849 vs2,
1850 wide_group_regs,
1851 )?;
1852 if !vm && vd == VReg::V0 {
1853 ::core::hint::cold_path();
1854 return ExecutionResult::Err(ExecutionError::IllegalInstruction {
1855 address: PackedAddress::new(
1856 program_counter.old_pc(zvexx_helpers::INSTRUCTION_SIZE),
1857 ),
1858 });
1859 }
1860 let scalar = rs1_value.as_u64();
1861 unsafe {
1863 zvexx_widen_narrow_helpers::execute_narrow_shift::<true, _, _>(
1864 env,
1865 vd,
1866 vs2,
1867 zvexx_widen_narrow_helpers::OpSrc::Scalar(scalar),
1868 vm,
1869 sew,
1870 );
1871 }
1872 }
1873 Self::VnsraWi { vd, vs2, uimm, vm } => {
1875 if !env.vector_instructions_allowed() {
1876 ::core::hint::cold_path();
1877 return ExecutionResult::Err(ExecutionError::IllegalInstruction {
1878 address: PackedAddress::new(
1879 program_counter.old_pc(zvexx_helpers::INSTRUCTION_SIZE),
1880 ),
1881 });
1882 }
1883 let Some(vtype) = env.vtype() else {
1884 ::core::hint::cold_path();
1885 return ExecutionResult::Err(ExecutionError::IllegalInstruction {
1886 address: PackedAddress::new(
1887 program_counter.old_pc(zvexx_helpers::INSTRUCTION_SIZE),
1888 ),
1889 });
1890 };
1891 let sew = vtype.vsew();
1892 let group_regs = vtype.vlmul().register_count();
1893 let wide_eew = match sew {
1894 Vsew::E8 => Eew::E16,
1895 Vsew::E16 => Eew::E32,
1896 Vsew::E32 => Eew::E64,
1897 Vsew::E64 => {
1898 ::core::hint::cold_path();
1899 return ExecutionResult::Err(ExecutionError::IllegalInstruction {
1900 address: PackedAddress::new(
1901 program_counter.old_pc(zvexx_helpers::INSTRUCTION_SIZE),
1902 ),
1903 });
1904 }
1905 };
1906 if u32::from(wide_eew.bits_width()) > u32::from(Env::ELEN) {
1907 ::core::hint::cold_path();
1908 return ExecutionResult::Err(ExecutionError::IllegalInstruction {
1909 address: PackedAddress::new(
1910 program_counter.old_pc(zvexx_helpers::INSTRUCTION_SIZE),
1911 ),
1912 });
1913 }
1914 let wide_group_regs = vtype.vlmul().data_register_count(wide_eew, sew).ok_or(
1915 ExecutionError::IllegalInstruction {
1916 address: PackedAddress::new(
1917 program_counter.old_pc(zvexx_helpers::INSTRUCTION_SIZE),
1918 ),
1919 },
1920 )?;
1921 zvexx_widen_narrow_helpers::check_vd_narrow_alignment::<Reg, _, _>(
1922 program_counter,
1923 vd,
1924 group_regs,
1925 )?;
1926 zvexx_widen_narrow_helpers::check_vs_wide_alignment::<Reg, _, _>(
1927 program_counter,
1928 vs2,
1929 wide_group_regs,
1930 )?;
1931 if !vm && vd == VReg::V0 {
1932 ::core::hint::cold_path();
1933 return ExecutionResult::Err(ExecutionError::IllegalInstruction {
1934 address: PackedAddress::new(
1935 program_counter.old_pc(zvexx_helpers::INSTRUCTION_SIZE),
1936 ),
1937 });
1938 }
1939 unsafe {
1941 zvexx_widen_narrow_helpers::execute_narrow_shift::<true, _, _>(
1942 env,
1943 vd,
1944 vs2,
1945 zvexx_widen_narrow_helpers::OpSrc::Scalar(u64::from(uimm)),
1946 vm,
1947 sew,
1948 );
1949 }
1950 }
1951 Self::VzextVf2 { vd, vs2, vm } => {
1953 if !env.vector_instructions_allowed() {
1954 ::core::hint::cold_path();
1955 return ExecutionResult::Err(ExecutionError::IllegalInstruction {
1956 address: PackedAddress::new(
1957 program_counter.old_pc(zvexx_helpers::INSTRUCTION_SIZE),
1958 ),
1959 });
1960 }
1961 let Some(vtype) = env.vtype() else {
1962 ::core::hint::cold_path();
1963 return ExecutionResult::Err(ExecutionError::IllegalInstruction {
1964 address: PackedAddress::new(
1965 program_counter.old_pc(zvexx_helpers::INSTRUCTION_SIZE),
1966 ),
1967 });
1968 };
1969 let sew = vtype.vsew();
1970 if u32::from(sew.bits_width()) < 16 {
1972 ::core::hint::cold_path();
1973 return ExecutionResult::Err(ExecutionError::IllegalInstruction {
1974 address: PackedAddress::new(
1975 program_counter.old_pc(zvexx_helpers::INSTRUCTION_SIZE),
1976 ),
1977 });
1978 }
1979 let group_regs = vtype.vlmul().register_count();
1980 let src_group = ::core::num::NonZeroU8::new(group_regs.get().max(2) / 2)
1982 .expect("Not zero; qed");
1983 zvexx_widen_narrow_helpers::check_vs_ext_alignment::<Reg, _, _>(
1984 program_counter,
1985 vs2,
1986 src_group,
1987 vd,
1988 group_regs,
1989 )?;
1990 zvexx_widen_narrow_helpers::check_vreg_group_alignment::<Reg, _, _>(
1991 program_counter,
1992 vd,
1993 group_regs,
1994 )?;
1995 if !vm && vd == VReg::V0 {
1996 ::core::hint::cold_path();
1997 return ExecutionResult::Err(ExecutionError::IllegalInstruction {
1998 address: PackedAddress::new(
1999 program_counter.old_pc(zvexx_helpers::INSTRUCTION_SIZE),
2000 ),
2001 });
2002 }
2003 unsafe {
2005 zvexx_widen_narrow_helpers::execute_extension::<false, _, _>(
2006 env,
2007 vd,
2008 vs2,
2009 vm,
2010 sew,
2011 VsewFactor::F2,
2012 );
2013 }
2014 }
2015 Self::VzextVf4 { vd, vs2, vm } => {
2017 if !env.vector_instructions_allowed() {
2018 ::core::hint::cold_path();
2019 return ExecutionResult::Err(ExecutionError::IllegalInstruction {
2020 address: PackedAddress::new(
2021 program_counter.old_pc(zvexx_helpers::INSTRUCTION_SIZE),
2022 ),
2023 });
2024 }
2025 let Some(vtype) = env.vtype() else {
2026 ::core::hint::cold_path();
2027 return ExecutionResult::Err(ExecutionError::IllegalInstruction {
2028 address: PackedAddress::new(
2029 program_counter.old_pc(zvexx_helpers::INSTRUCTION_SIZE),
2030 ),
2031 });
2032 };
2033 let sew = vtype.vsew();
2034 if u32::from(sew.bits_width()) < 32 {
2036 ::core::hint::cold_path();
2037 return ExecutionResult::Err(ExecutionError::IllegalInstruction {
2038 address: PackedAddress::new(
2039 program_counter.old_pc(zvexx_helpers::INSTRUCTION_SIZE),
2040 ),
2041 });
2042 }
2043 let group_regs = vtype.vlmul().register_count();
2044 let src_group = ::core::num::NonZeroU8::new(group_regs.get().max(4) / 4)
2045 .expect("Not zero; qed");
2046 zvexx_widen_narrow_helpers::check_vs_ext_alignment::<Reg, _, _>(
2047 program_counter,
2048 vs2,
2049 src_group,
2050 vd,
2051 group_regs,
2052 )?;
2053 zvexx_widen_narrow_helpers::check_vreg_group_alignment::<Reg, _, _>(
2054 program_counter,
2055 vd,
2056 group_regs,
2057 )?;
2058 if !vm && vd == VReg::V0 {
2059 ::core::hint::cold_path();
2060 return ExecutionResult::Err(ExecutionError::IllegalInstruction {
2061 address: PackedAddress::new(
2062 program_counter.old_pc(zvexx_helpers::INSTRUCTION_SIZE),
2063 ),
2064 });
2065 }
2066 unsafe {
2068 zvexx_widen_narrow_helpers::execute_extension::<false, _, _>(
2069 env,
2070 vd,
2071 vs2,
2072 vm,
2073 sew,
2074 VsewFactor::F4,
2075 );
2076 }
2077 }
2078 Self::VzextVf8 { vd, vs2, vm } => {
2080 if !env.vector_instructions_allowed() {
2081 ::core::hint::cold_path();
2082 return ExecutionResult::Err(ExecutionError::IllegalInstruction {
2083 address: PackedAddress::new(
2084 program_counter.old_pc(zvexx_helpers::INSTRUCTION_SIZE),
2085 ),
2086 });
2087 }
2088 let Some(vtype) = env.vtype() else {
2089 ::core::hint::cold_path();
2090 return ExecutionResult::Err(ExecutionError::IllegalInstruction {
2091 address: PackedAddress::new(
2092 program_counter.old_pc(zvexx_helpers::INSTRUCTION_SIZE),
2093 ),
2094 });
2095 };
2096 let sew = vtype.vsew();
2097 if u32::from(sew.bits_width()) < 64 {
2099 ::core::hint::cold_path();
2100 return ExecutionResult::Err(ExecutionError::IllegalInstruction {
2101 address: PackedAddress::new(
2102 program_counter.old_pc(zvexx_helpers::INSTRUCTION_SIZE),
2103 ),
2104 });
2105 }
2106 let group_regs = vtype.vlmul().register_count();
2107 let src_group = ::core::num::NonZeroU8::new(group_regs.get().max(8) / 8)
2108 .expect("Not zero; qed");
2109 zvexx_widen_narrow_helpers::check_vs_ext_alignment::<Reg, _, _>(
2110 program_counter,
2111 vs2,
2112 src_group,
2113 vd,
2114 group_regs,
2115 )?;
2116 zvexx_widen_narrow_helpers::check_vreg_group_alignment::<Reg, _, _>(
2117 program_counter,
2118 vd,
2119 group_regs,
2120 )?;
2121 if !vm && vd == VReg::V0 {
2122 ::core::hint::cold_path();
2123 return ExecutionResult::Err(ExecutionError::IllegalInstruction {
2124 address: PackedAddress::new(
2125 program_counter.old_pc(zvexx_helpers::INSTRUCTION_SIZE),
2126 ),
2127 });
2128 }
2129 unsafe {
2131 zvexx_widen_narrow_helpers::execute_extension::<false, _, _>(
2132 env,
2133 vd,
2134 vs2,
2135 vm,
2136 sew,
2137 VsewFactor::F8,
2138 );
2139 }
2140 }
2141 Self::VsextVf2 { vd, vs2, vm } => {
2143 if !env.vector_instructions_allowed() {
2144 ::core::hint::cold_path();
2145 return ExecutionResult::Err(ExecutionError::IllegalInstruction {
2146 address: PackedAddress::new(
2147 program_counter.old_pc(zvexx_helpers::INSTRUCTION_SIZE),
2148 ),
2149 });
2150 }
2151 let Some(vtype) = env.vtype() else {
2152 ::core::hint::cold_path();
2153 return ExecutionResult::Err(ExecutionError::IllegalInstruction {
2154 address: PackedAddress::new(
2155 program_counter.old_pc(zvexx_helpers::INSTRUCTION_SIZE),
2156 ),
2157 });
2158 };
2159 let sew = vtype.vsew();
2160 if u32::from(sew.bits_width()) < 16 {
2161 ::core::hint::cold_path();
2162 return ExecutionResult::Err(ExecutionError::IllegalInstruction {
2163 address: PackedAddress::new(
2164 program_counter.old_pc(zvexx_helpers::INSTRUCTION_SIZE),
2165 ),
2166 });
2167 }
2168 let group_regs = vtype.vlmul().register_count();
2169 let src_group = ::core::num::NonZeroU8::new(group_regs.get().max(2) / 2)
2170 .expect("Not zero; qed");
2171 zvexx_widen_narrow_helpers::check_vs_ext_alignment::<Reg, _, _>(
2172 program_counter,
2173 vs2,
2174 src_group,
2175 vd,
2176 group_regs,
2177 )?;
2178 zvexx_widen_narrow_helpers::check_vreg_group_alignment::<Reg, _, _>(
2179 program_counter,
2180 vd,
2181 group_regs,
2182 )?;
2183 if !vm && vd == VReg::V0 {
2184 ::core::hint::cold_path();
2185 return ExecutionResult::Err(ExecutionError::IllegalInstruction {
2186 address: PackedAddress::new(
2187 program_counter.old_pc(zvexx_helpers::INSTRUCTION_SIZE),
2188 ),
2189 });
2190 }
2191 unsafe {
2193 zvexx_widen_narrow_helpers::execute_extension::<true, _, _>(
2194 env,
2195 vd,
2196 vs2,
2197 vm,
2198 sew,
2199 VsewFactor::F2,
2200 );
2201 }
2202 }
2203 Self::VsextVf4 { vd, vs2, vm } => {
2205 if !env.vector_instructions_allowed() {
2206 ::core::hint::cold_path();
2207 return ExecutionResult::Err(ExecutionError::IllegalInstruction {
2208 address: PackedAddress::new(
2209 program_counter.old_pc(zvexx_helpers::INSTRUCTION_SIZE),
2210 ),
2211 });
2212 }
2213 let Some(vtype) = env.vtype() else {
2214 ::core::hint::cold_path();
2215 return ExecutionResult::Err(ExecutionError::IllegalInstruction {
2216 address: PackedAddress::new(
2217 program_counter.old_pc(zvexx_helpers::INSTRUCTION_SIZE),
2218 ),
2219 });
2220 };
2221 let sew = vtype.vsew();
2222 if u32::from(sew.bits_width()) < 32 {
2223 ::core::hint::cold_path();
2224 return ExecutionResult::Err(ExecutionError::IllegalInstruction {
2225 address: PackedAddress::new(
2226 program_counter.old_pc(zvexx_helpers::INSTRUCTION_SIZE),
2227 ),
2228 });
2229 }
2230 let group_regs = vtype.vlmul().register_count();
2231 let src_group = ::core::num::NonZeroU8::new(group_regs.get().max(4) / 4)
2232 .expect("Not zero; qed");
2233 zvexx_widen_narrow_helpers::check_vs_ext_alignment::<Reg, _, _>(
2234 program_counter,
2235 vs2,
2236 src_group,
2237 vd,
2238 group_regs,
2239 )?;
2240 zvexx_widen_narrow_helpers::check_vreg_group_alignment::<Reg, _, _>(
2241 program_counter,
2242 vd,
2243 group_regs,
2244 )?;
2245 if !vm && vd == VReg::V0 {
2246 ::core::hint::cold_path();
2247 return ExecutionResult::Err(ExecutionError::IllegalInstruction {
2248 address: PackedAddress::new(
2249 program_counter.old_pc(zvexx_helpers::INSTRUCTION_SIZE),
2250 ),
2251 });
2252 }
2253 unsafe {
2255 zvexx_widen_narrow_helpers::execute_extension::<true, _, _>(
2256 env,
2257 vd,
2258 vs2,
2259 vm,
2260 sew,
2261 VsewFactor::F4,
2262 );
2263 }
2264 }
2265 Self::VsextVf8 { vd, vs2, vm } => {
2267 if !env.vector_instructions_allowed() {
2268 ::core::hint::cold_path();
2269 return ExecutionResult::Err(ExecutionError::IllegalInstruction {
2270 address: PackedAddress::new(
2271 program_counter.old_pc(zvexx_helpers::INSTRUCTION_SIZE),
2272 ),
2273 });
2274 }
2275 let Some(vtype) = env.vtype() else {
2276 ::core::hint::cold_path();
2277 return ExecutionResult::Err(ExecutionError::IllegalInstruction {
2278 address: PackedAddress::new(
2279 program_counter.old_pc(zvexx_helpers::INSTRUCTION_SIZE),
2280 ),
2281 });
2282 };
2283 let sew = vtype.vsew();
2284 if u32::from(sew.bits_width()) < 64 {
2285 ::core::hint::cold_path();
2286 return ExecutionResult::Err(ExecutionError::IllegalInstruction {
2287 address: PackedAddress::new(
2288 program_counter.old_pc(zvexx_helpers::INSTRUCTION_SIZE),
2289 ),
2290 });
2291 }
2292 let group_regs = vtype.vlmul().register_count();
2293 let src_group = ::core::num::NonZeroU8::new(group_regs.get().max(8) / 8)
2294 .expect("Not zero; qed");
2295 zvexx_widen_narrow_helpers::check_vs_ext_alignment::<Reg, _, _>(
2296 program_counter,
2297 vs2,
2298 src_group,
2299 vd,
2300 group_regs,
2301 )?;
2302 zvexx_widen_narrow_helpers::check_vreg_group_alignment::<Reg, _, _>(
2303 program_counter,
2304 vd,
2305 group_regs,
2306 )?;
2307 if !vm && vd == VReg::V0 {
2308 ::core::hint::cold_path();
2309 return ExecutionResult::Err(ExecutionError::IllegalInstruction {
2310 address: PackedAddress::new(
2311 program_counter.old_pc(zvexx_helpers::INSTRUCTION_SIZE),
2312 ),
2313 });
2314 }
2315 unsafe {
2317 zvexx_widen_narrow_helpers::execute_extension::<true, _, _>(
2318 env,
2319 vd,
2320 vs2,
2321 vm,
2322 sew,
2323 VsewFactor::F8,
2324 );
2325 }
2326 }
2327 }
2328
2329 ExecutionResult::ContinueNoWrite
2330 }
2331}