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 vs2,
1514 wide_group_regs,
1515 )?;
1516 zvexx_widen_narrow_helpers::check_vs_wide_alignment::<Reg, _, _>(
1517 program_counter,
1518 vs2,
1519 wide_group_regs,
1520 )?;
1521 zvexx_widen_narrow_helpers::check_vreg_group_alignment::<Reg, _, _>(
1522 program_counter,
1523 vs1,
1524 group_regs,
1525 )?;
1526 if !vm && vd == VReg::V0 {
1527 ::core::hint::cold_path();
1528 return ExecutionResult::Err(ExecutionError::IllegalInstruction {
1529 address: PackedAddress::new(
1530 program_counter.old_pc(zvexx_helpers::INSTRUCTION_SIZE),
1531 ),
1532 });
1533 }
1534 unsafe {
1536 zvexx_widen_narrow_helpers::execute_narrow_shift::<false, _, _>(
1537 env,
1538 vd,
1539 vs2,
1540 zvexx_widen_narrow_helpers::OpSrc::Vreg(vs1),
1541 vm,
1542 sew,
1543 );
1544 }
1545 }
1546 Self::VnsrlWx {
1548 vd,
1549 vs2,
1550 rs1: _,
1551 vm,
1552 } => {
1553 if !env.vector_instructions_allowed() {
1554 ::core::hint::cold_path();
1555 return ExecutionResult::Err(ExecutionError::IllegalInstruction {
1556 address: PackedAddress::new(
1557 program_counter.old_pc(zvexx_helpers::INSTRUCTION_SIZE),
1558 ),
1559 });
1560 }
1561 let Some(vtype) = env.vtype() else {
1562 ::core::hint::cold_path();
1563 return ExecutionResult::Err(ExecutionError::IllegalInstruction {
1564 address: PackedAddress::new(
1565 program_counter.old_pc(zvexx_helpers::INSTRUCTION_SIZE),
1566 ),
1567 });
1568 };
1569 let sew = vtype.vsew();
1570 let group_regs = vtype.vlmul().register_count();
1571 let wide_eew = match sew {
1572 Vsew::E8 => Eew::E16,
1573 Vsew::E16 => Eew::E32,
1574 Vsew::E32 => Eew::E64,
1575 Vsew::E64 => {
1576 ::core::hint::cold_path();
1577 return ExecutionResult::Err(ExecutionError::IllegalInstruction {
1578 address: PackedAddress::new(
1579 program_counter.old_pc(zvexx_helpers::INSTRUCTION_SIZE),
1580 ),
1581 });
1582 }
1583 };
1584 if u32::from(wide_eew.bits_width()) > u32::from(Env::ELEN) {
1585 ::core::hint::cold_path();
1586 return ExecutionResult::Err(ExecutionError::IllegalInstruction {
1587 address: PackedAddress::new(
1588 program_counter.old_pc(zvexx_helpers::INSTRUCTION_SIZE),
1589 ),
1590 });
1591 }
1592 let wide_group_regs = vtype.vlmul().data_register_count(wide_eew, sew).ok_or(
1593 ExecutionError::IllegalInstruction {
1594 address: PackedAddress::new(
1595 program_counter.old_pc(zvexx_helpers::INSTRUCTION_SIZE),
1596 ),
1597 },
1598 )?;
1599 zvexx_widen_narrow_helpers::check_vd_narrow_alignment::<Reg, _, _>(
1600 program_counter,
1601 vd,
1602 group_regs,
1603 vs2,
1604 wide_group_regs,
1605 )?;
1606 zvexx_widen_narrow_helpers::check_vs_wide_alignment::<Reg, _, _>(
1607 program_counter,
1608 vs2,
1609 wide_group_regs,
1610 )?;
1611 if !vm && vd == VReg::V0 {
1612 ::core::hint::cold_path();
1613 return ExecutionResult::Err(ExecutionError::IllegalInstruction {
1614 address: PackedAddress::new(
1615 program_counter.old_pc(zvexx_helpers::INSTRUCTION_SIZE),
1616 ),
1617 });
1618 }
1619 let scalar = rs1_value.as_u64();
1620 unsafe {
1622 zvexx_widen_narrow_helpers::execute_narrow_shift::<false, _, _>(
1623 env,
1624 vd,
1625 vs2,
1626 zvexx_widen_narrow_helpers::OpSrc::Scalar(scalar),
1627 vm,
1628 sew,
1629 );
1630 }
1631 }
1632 Self::VnsrlWi { vd, vs2, uimm, vm } => {
1634 if !env.vector_instructions_allowed() {
1635 ::core::hint::cold_path();
1636 return ExecutionResult::Err(ExecutionError::IllegalInstruction {
1637 address: PackedAddress::new(
1638 program_counter.old_pc(zvexx_helpers::INSTRUCTION_SIZE),
1639 ),
1640 });
1641 }
1642 let Some(vtype) = env.vtype() else {
1643 ::core::hint::cold_path();
1644 return ExecutionResult::Err(ExecutionError::IllegalInstruction {
1645 address: PackedAddress::new(
1646 program_counter.old_pc(zvexx_helpers::INSTRUCTION_SIZE),
1647 ),
1648 });
1649 };
1650 let sew = vtype.vsew();
1651 let group_regs = vtype.vlmul().register_count();
1652 let wide_eew = match sew {
1653 Vsew::E8 => Eew::E16,
1654 Vsew::E16 => Eew::E32,
1655 Vsew::E32 => Eew::E64,
1656 Vsew::E64 => {
1657 ::core::hint::cold_path();
1658 return ExecutionResult::Err(ExecutionError::IllegalInstruction {
1659 address: PackedAddress::new(
1660 program_counter.old_pc(zvexx_helpers::INSTRUCTION_SIZE),
1661 ),
1662 });
1663 }
1664 };
1665 if u32::from(wide_eew.bits_width()) > u32::from(Env::ELEN) {
1666 ::core::hint::cold_path();
1667 return ExecutionResult::Err(ExecutionError::IllegalInstruction {
1668 address: PackedAddress::new(
1669 program_counter.old_pc(zvexx_helpers::INSTRUCTION_SIZE),
1670 ),
1671 });
1672 }
1673 let wide_group_regs = vtype.vlmul().data_register_count(wide_eew, sew).ok_or(
1674 ExecutionError::IllegalInstruction {
1675 address: PackedAddress::new(
1676 program_counter.old_pc(zvexx_helpers::INSTRUCTION_SIZE),
1677 ),
1678 },
1679 )?;
1680 zvexx_widen_narrow_helpers::check_vd_narrow_alignment::<Reg, _, _>(
1681 program_counter,
1682 vd,
1683 group_regs,
1684 vs2,
1685 wide_group_regs,
1686 )?;
1687 zvexx_widen_narrow_helpers::check_vs_wide_alignment::<Reg, _, _>(
1688 program_counter,
1689 vs2,
1690 wide_group_regs,
1691 )?;
1692 if !vm && vd == VReg::V0 {
1693 ::core::hint::cold_path();
1694 return ExecutionResult::Err(ExecutionError::IllegalInstruction {
1695 address: PackedAddress::new(
1696 program_counter.old_pc(zvexx_helpers::INSTRUCTION_SIZE),
1697 ),
1698 });
1699 }
1700 unsafe {
1702 zvexx_widen_narrow_helpers::execute_narrow_shift::<false, _, _>(
1703 env,
1704 vd,
1705 vs2,
1706 zvexx_widen_narrow_helpers::OpSrc::Scalar(u64::from(uimm)),
1707 vm,
1708 sew,
1709 );
1710 }
1711 }
1712 Self::VnsraWv { vd, vs2, vs1, vm } => {
1714 if !env.vector_instructions_allowed() {
1715 ::core::hint::cold_path();
1716 return ExecutionResult::Err(ExecutionError::IllegalInstruction {
1717 address: PackedAddress::new(
1718 program_counter.old_pc(zvexx_helpers::INSTRUCTION_SIZE),
1719 ),
1720 });
1721 }
1722 let Some(vtype) = env.vtype() else {
1723 ::core::hint::cold_path();
1724 return ExecutionResult::Err(ExecutionError::IllegalInstruction {
1725 address: PackedAddress::new(
1726 program_counter.old_pc(zvexx_helpers::INSTRUCTION_SIZE),
1727 ),
1728 });
1729 };
1730 let sew = vtype.vsew();
1731 let group_regs = vtype.vlmul().register_count();
1732 let wide_eew = match sew {
1733 Vsew::E8 => Eew::E16,
1734 Vsew::E16 => Eew::E32,
1735 Vsew::E32 => Eew::E64,
1736 Vsew::E64 => {
1737 ::core::hint::cold_path();
1738 return ExecutionResult::Err(ExecutionError::IllegalInstruction {
1739 address: PackedAddress::new(
1740 program_counter.old_pc(zvexx_helpers::INSTRUCTION_SIZE),
1741 ),
1742 });
1743 }
1744 };
1745 if u32::from(wide_eew.bits_width()) > u32::from(Env::ELEN) {
1746 ::core::hint::cold_path();
1747 return ExecutionResult::Err(ExecutionError::IllegalInstruction {
1748 address: PackedAddress::new(
1749 program_counter.old_pc(zvexx_helpers::INSTRUCTION_SIZE),
1750 ),
1751 });
1752 }
1753 let wide_group_regs = vtype.vlmul().data_register_count(wide_eew, sew).ok_or(
1754 ExecutionError::IllegalInstruction {
1755 address: PackedAddress::new(
1756 program_counter.old_pc(zvexx_helpers::INSTRUCTION_SIZE),
1757 ),
1758 },
1759 )?;
1760 zvexx_widen_narrow_helpers::check_vd_narrow_alignment::<Reg, _, _>(
1761 program_counter,
1762 vd,
1763 group_regs,
1764 vs2,
1765 wide_group_regs,
1766 )?;
1767 zvexx_widen_narrow_helpers::check_vs_wide_alignment::<Reg, _, _>(
1768 program_counter,
1769 vs2,
1770 wide_group_regs,
1771 )?;
1772 zvexx_widen_narrow_helpers::check_vreg_group_alignment::<Reg, _, _>(
1773 program_counter,
1774 vs1,
1775 group_regs,
1776 )?;
1777 if !vm && vd == VReg::V0 {
1778 ::core::hint::cold_path();
1779 return ExecutionResult::Err(ExecutionError::IllegalInstruction {
1780 address: PackedAddress::new(
1781 program_counter.old_pc(zvexx_helpers::INSTRUCTION_SIZE),
1782 ),
1783 });
1784 }
1785 unsafe {
1787 zvexx_widen_narrow_helpers::execute_narrow_shift::<true, _, _>(
1788 env,
1789 vd,
1790 vs2,
1791 zvexx_widen_narrow_helpers::OpSrc::Vreg(vs1),
1792 vm,
1793 sew,
1794 );
1795 }
1796 }
1797 Self::VnsraWx {
1799 vd,
1800 vs2,
1801 rs1: _,
1802 vm,
1803 } => {
1804 if !env.vector_instructions_allowed() {
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 Some(vtype) = env.vtype() else {
1813 ::core::hint::cold_path();
1814 return ExecutionResult::Err(ExecutionError::IllegalInstruction {
1815 address: PackedAddress::new(
1816 program_counter.old_pc(zvexx_helpers::INSTRUCTION_SIZE),
1817 ),
1818 });
1819 };
1820 let sew = vtype.vsew();
1821 let group_regs = vtype.vlmul().register_count();
1822 let wide_eew = match sew {
1823 Vsew::E8 => Eew::E16,
1824 Vsew::E16 => Eew::E32,
1825 Vsew::E32 => Eew::E64,
1826 Vsew::E64 => {
1827 ::core::hint::cold_path();
1828 return ExecutionResult::Err(ExecutionError::IllegalInstruction {
1829 address: PackedAddress::new(
1830 program_counter.old_pc(zvexx_helpers::INSTRUCTION_SIZE),
1831 ),
1832 });
1833 }
1834 };
1835 if u32::from(wide_eew.bits_width()) > u32::from(Env::ELEN) {
1836 ::core::hint::cold_path();
1837 return ExecutionResult::Err(ExecutionError::IllegalInstruction {
1838 address: PackedAddress::new(
1839 program_counter.old_pc(zvexx_helpers::INSTRUCTION_SIZE),
1840 ),
1841 });
1842 }
1843 let wide_group_regs = vtype.vlmul().data_register_count(wide_eew, sew).ok_or(
1844 ExecutionError::IllegalInstruction {
1845 address: PackedAddress::new(
1846 program_counter.old_pc(zvexx_helpers::INSTRUCTION_SIZE),
1847 ),
1848 },
1849 )?;
1850 zvexx_widen_narrow_helpers::check_vd_narrow_alignment::<Reg, _, _>(
1851 program_counter,
1852 vd,
1853 group_regs,
1854 vs2,
1855 wide_group_regs,
1856 )?;
1857 zvexx_widen_narrow_helpers::check_vs_wide_alignment::<Reg, _, _>(
1858 program_counter,
1859 vs2,
1860 wide_group_regs,
1861 )?;
1862 if !vm && vd == VReg::V0 {
1863 ::core::hint::cold_path();
1864 return ExecutionResult::Err(ExecutionError::IllegalInstruction {
1865 address: PackedAddress::new(
1866 program_counter.old_pc(zvexx_helpers::INSTRUCTION_SIZE),
1867 ),
1868 });
1869 }
1870 let scalar = rs1_value.as_u64();
1871 unsafe {
1873 zvexx_widen_narrow_helpers::execute_narrow_shift::<true, _, _>(
1874 env,
1875 vd,
1876 vs2,
1877 zvexx_widen_narrow_helpers::OpSrc::Scalar(scalar),
1878 vm,
1879 sew,
1880 );
1881 }
1882 }
1883 Self::VnsraWi { vd, vs2, uimm, vm } => {
1885 if !env.vector_instructions_allowed() {
1886 ::core::hint::cold_path();
1887 return ExecutionResult::Err(ExecutionError::IllegalInstruction {
1888 address: PackedAddress::new(
1889 program_counter.old_pc(zvexx_helpers::INSTRUCTION_SIZE),
1890 ),
1891 });
1892 }
1893 let Some(vtype) = env.vtype() else {
1894 ::core::hint::cold_path();
1895 return ExecutionResult::Err(ExecutionError::IllegalInstruction {
1896 address: PackedAddress::new(
1897 program_counter.old_pc(zvexx_helpers::INSTRUCTION_SIZE),
1898 ),
1899 });
1900 };
1901 let sew = vtype.vsew();
1902 let group_regs = vtype.vlmul().register_count();
1903 let wide_eew = match sew {
1904 Vsew::E8 => Eew::E16,
1905 Vsew::E16 => Eew::E32,
1906 Vsew::E32 => Eew::E64,
1907 Vsew::E64 => {
1908 ::core::hint::cold_path();
1909 return ExecutionResult::Err(ExecutionError::IllegalInstruction {
1910 address: PackedAddress::new(
1911 program_counter.old_pc(zvexx_helpers::INSTRUCTION_SIZE),
1912 ),
1913 });
1914 }
1915 };
1916 if u32::from(wide_eew.bits_width()) > u32::from(Env::ELEN) {
1917 ::core::hint::cold_path();
1918 return ExecutionResult::Err(ExecutionError::IllegalInstruction {
1919 address: PackedAddress::new(
1920 program_counter.old_pc(zvexx_helpers::INSTRUCTION_SIZE),
1921 ),
1922 });
1923 }
1924 let wide_group_regs = vtype.vlmul().data_register_count(wide_eew, sew).ok_or(
1925 ExecutionError::IllegalInstruction {
1926 address: PackedAddress::new(
1927 program_counter.old_pc(zvexx_helpers::INSTRUCTION_SIZE),
1928 ),
1929 },
1930 )?;
1931 zvexx_widen_narrow_helpers::check_vd_narrow_alignment::<Reg, _, _>(
1932 program_counter,
1933 vd,
1934 group_regs,
1935 vs2,
1936 wide_group_regs,
1937 )?;
1938 zvexx_widen_narrow_helpers::check_vs_wide_alignment::<Reg, _, _>(
1939 program_counter,
1940 vs2,
1941 wide_group_regs,
1942 )?;
1943 if !vm && vd == VReg::V0 {
1944 ::core::hint::cold_path();
1945 return ExecutionResult::Err(ExecutionError::IllegalInstruction {
1946 address: PackedAddress::new(
1947 program_counter.old_pc(zvexx_helpers::INSTRUCTION_SIZE),
1948 ),
1949 });
1950 }
1951 unsafe {
1953 zvexx_widen_narrow_helpers::execute_narrow_shift::<true, _, _>(
1954 env,
1955 vd,
1956 vs2,
1957 zvexx_widen_narrow_helpers::OpSrc::Scalar(u64::from(uimm)),
1958 vm,
1959 sew,
1960 );
1961 }
1962 }
1963 Self::VzextVf2 { vd, vs2, vm } => {
1965 if !env.vector_instructions_allowed() {
1966 ::core::hint::cold_path();
1967 return ExecutionResult::Err(ExecutionError::IllegalInstruction {
1968 address: PackedAddress::new(
1969 program_counter.old_pc(zvexx_helpers::INSTRUCTION_SIZE),
1970 ),
1971 });
1972 }
1973 let Some(vtype) = env.vtype() else {
1974 ::core::hint::cold_path();
1975 return ExecutionResult::Err(ExecutionError::IllegalInstruction {
1976 address: PackedAddress::new(
1977 program_counter.old_pc(zvexx_helpers::INSTRUCTION_SIZE),
1978 ),
1979 });
1980 };
1981 let sew = vtype.vsew();
1982 if u32::from(sew.bits_width()) < 16 {
1984 ::core::hint::cold_path();
1985 return ExecutionResult::Err(ExecutionError::IllegalInstruction {
1986 address: PackedAddress::new(
1987 program_counter.old_pc(zvexx_helpers::INSTRUCTION_SIZE),
1988 ),
1989 });
1990 }
1991 let group_regs = vtype.vlmul().register_count();
1992 let src_group = group_regs.divide_by_factor(VsewFactor::F2);
1994 zvexx_widen_narrow_helpers::check_vs_ext_alignment::<Reg, _, _>(
1995 program_counter,
1996 vs2,
1997 src_group,
1998 vd,
1999 group_regs,
2000 )?;
2001 zvexx_widen_narrow_helpers::check_vreg_group_alignment::<Reg, _, _>(
2002 program_counter,
2003 vd,
2004 group_regs,
2005 )?;
2006 if !vm && vd == VReg::V0 {
2007 ::core::hint::cold_path();
2008 return ExecutionResult::Err(ExecutionError::IllegalInstruction {
2009 address: PackedAddress::new(
2010 program_counter.old_pc(zvexx_helpers::INSTRUCTION_SIZE),
2011 ),
2012 });
2013 }
2014 unsafe {
2016 zvexx_widen_narrow_helpers::execute_extension::<false, _, _>(
2017 env,
2018 vd,
2019 vs2,
2020 vm,
2021 sew,
2022 VsewFactor::F2,
2023 );
2024 }
2025 }
2026 Self::VzextVf4 { vd, vs2, vm } => {
2028 if !env.vector_instructions_allowed() {
2029 ::core::hint::cold_path();
2030 return ExecutionResult::Err(ExecutionError::IllegalInstruction {
2031 address: PackedAddress::new(
2032 program_counter.old_pc(zvexx_helpers::INSTRUCTION_SIZE),
2033 ),
2034 });
2035 }
2036 let Some(vtype) = env.vtype() else {
2037 ::core::hint::cold_path();
2038 return ExecutionResult::Err(ExecutionError::IllegalInstruction {
2039 address: PackedAddress::new(
2040 program_counter.old_pc(zvexx_helpers::INSTRUCTION_SIZE),
2041 ),
2042 });
2043 };
2044 let sew = vtype.vsew();
2045 if u32::from(sew.bits_width()) < 32 {
2047 ::core::hint::cold_path();
2048 return ExecutionResult::Err(ExecutionError::IllegalInstruction {
2049 address: PackedAddress::new(
2050 program_counter.old_pc(zvexx_helpers::INSTRUCTION_SIZE),
2051 ),
2052 });
2053 }
2054 let group_regs = vtype.vlmul().register_count();
2055 let src_group = group_regs.divide_by_factor(VsewFactor::F4);
2056 zvexx_widen_narrow_helpers::check_vs_ext_alignment::<Reg, _, _>(
2057 program_counter,
2058 vs2,
2059 src_group,
2060 vd,
2061 group_regs,
2062 )?;
2063 zvexx_widen_narrow_helpers::check_vreg_group_alignment::<Reg, _, _>(
2064 program_counter,
2065 vd,
2066 group_regs,
2067 )?;
2068 if !vm && vd == VReg::V0 {
2069 ::core::hint::cold_path();
2070 return ExecutionResult::Err(ExecutionError::IllegalInstruction {
2071 address: PackedAddress::new(
2072 program_counter.old_pc(zvexx_helpers::INSTRUCTION_SIZE),
2073 ),
2074 });
2075 }
2076 unsafe {
2078 zvexx_widen_narrow_helpers::execute_extension::<false, _, _>(
2079 env,
2080 vd,
2081 vs2,
2082 vm,
2083 sew,
2084 VsewFactor::F4,
2085 );
2086 }
2087 }
2088 Self::VzextVf8 { vd, vs2, vm } => {
2090 if !env.vector_instructions_allowed() {
2091 ::core::hint::cold_path();
2092 return ExecutionResult::Err(ExecutionError::IllegalInstruction {
2093 address: PackedAddress::new(
2094 program_counter.old_pc(zvexx_helpers::INSTRUCTION_SIZE),
2095 ),
2096 });
2097 }
2098 let Some(vtype) = env.vtype() else {
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 sew = vtype.vsew();
2107 if u32::from(sew.bits_width()) < 64 {
2109 ::core::hint::cold_path();
2110 return ExecutionResult::Err(ExecutionError::IllegalInstruction {
2111 address: PackedAddress::new(
2112 program_counter.old_pc(zvexx_helpers::INSTRUCTION_SIZE),
2113 ),
2114 });
2115 }
2116 let group_regs = vtype.vlmul().register_count();
2117 let src_group = group_regs.divide_by_factor(VsewFactor::F8);
2118 zvexx_widen_narrow_helpers::check_vs_ext_alignment::<Reg, _, _>(
2119 program_counter,
2120 vs2,
2121 src_group,
2122 vd,
2123 group_regs,
2124 )?;
2125 zvexx_widen_narrow_helpers::check_vreg_group_alignment::<Reg, _, _>(
2126 program_counter,
2127 vd,
2128 group_regs,
2129 )?;
2130 if !vm && vd == VReg::V0 {
2131 ::core::hint::cold_path();
2132 return ExecutionResult::Err(ExecutionError::IllegalInstruction {
2133 address: PackedAddress::new(
2134 program_counter.old_pc(zvexx_helpers::INSTRUCTION_SIZE),
2135 ),
2136 });
2137 }
2138 unsafe {
2140 zvexx_widen_narrow_helpers::execute_extension::<false, _, _>(
2141 env,
2142 vd,
2143 vs2,
2144 vm,
2145 sew,
2146 VsewFactor::F8,
2147 );
2148 }
2149 }
2150 Self::VsextVf2 { vd, vs2, vm } => {
2152 if !env.vector_instructions_allowed() {
2153 ::core::hint::cold_path();
2154 return ExecutionResult::Err(ExecutionError::IllegalInstruction {
2155 address: PackedAddress::new(
2156 program_counter.old_pc(zvexx_helpers::INSTRUCTION_SIZE),
2157 ),
2158 });
2159 }
2160 let Some(vtype) = env.vtype() else {
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 sew = vtype.vsew();
2169 if u32::from(sew.bits_width()) < 16 {
2170 ::core::hint::cold_path();
2171 return ExecutionResult::Err(ExecutionError::IllegalInstruction {
2172 address: PackedAddress::new(
2173 program_counter.old_pc(zvexx_helpers::INSTRUCTION_SIZE),
2174 ),
2175 });
2176 }
2177 let group_regs = vtype.vlmul().register_count();
2178 let src_group = group_regs.divide_by_factor(VsewFactor::F2);
2179 zvexx_widen_narrow_helpers::check_vs_ext_alignment::<Reg, _, _>(
2180 program_counter,
2181 vs2,
2182 src_group,
2183 vd,
2184 group_regs,
2185 )?;
2186 zvexx_widen_narrow_helpers::check_vreg_group_alignment::<Reg, _, _>(
2187 program_counter,
2188 vd,
2189 group_regs,
2190 )?;
2191 if !vm && vd == VReg::V0 {
2192 ::core::hint::cold_path();
2193 return ExecutionResult::Err(ExecutionError::IllegalInstruction {
2194 address: PackedAddress::new(
2195 program_counter.old_pc(zvexx_helpers::INSTRUCTION_SIZE),
2196 ),
2197 });
2198 }
2199 unsafe {
2201 zvexx_widen_narrow_helpers::execute_extension::<true, _, _>(
2202 env,
2203 vd,
2204 vs2,
2205 vm,
2206 sew,
2207 VsewFactor::F2,
2208 );
2209 }
2210 }
2211 Self::VsextVf4 { vd, vs2, vm } => {
2213 if !env.vector_instructions_allowed() {
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 Some(vtype) = env.vtype() else {
2222 ::core::hint::cold_path();
2223 return ExecutionResult::Err(ExecutionError::IllegalInstruction {
2224 address: PackedAddress::new(
2225 program_counter.old_pc(zvexx_helpers::INSTRUCTION_SIZE),
2226 ),
2227 });
2228 };
2229 let sew = vtype.vsew();
2230 if u32::from(sew.bits_width()) < 32 {
2231 ::core::hint::cold_path();
2232 return ExecutionResult::Err(ExecutionError::IllegalInstruction {
2233 address: PackedAddress::new(
2234 program_counter.old_pc(zvexx_helpers::INSTRUCTION_SIZE),
2235 ),
2236 });
2237 }
2238 let group_regs = vtype.vlmul().register_count();
2239 let src_group = group_regs.divide_by_factor(VsewFactor::F4);
2240 zvexx_widen_narrow_helpers::check_vs_ext_alignment::<Reg, _, _>(
2241 program_counter,
2242 vs2,
2243 src_group,
2244 vd,
2245 group_regs,
2246 )?;
2247 zvexx_widen_narrow_helpers::check_vreg_group_alignment::<Reg, _, _>(
2248 program_counter,
2249 vd,
2250 group_regs,
2251 )?;
2252 if !vm && vd == VReg::V0 {
2253 ::core::hint::cold_path();
2254 return ExecutionResult::Err(ExecutionError::IllegalInstruction {
2255 address: PackedAddress::new(
2256 program_counter.old_pc(zvexx_helpers::INSTRUCTION_SIZE),
2257 ),
2258 });
2259 }
2260 unsafe {
2262 zvexx_widen_narrow_helpers::execute_extension::<true, _, _>(
2263 env,
2264 vd,
2265 vs2,
2266 vm,
2267 sew,
2268 VsewFactor::F4,
2269 );
2270 }
2271 }
2272 Self::VsextVf8 { vd, vs2, vm } => {
2274 if !env.vector_instructions_allowed() {
2275 ::core::hint::cold_path();
2276 return ExecutionResult::Err(ExecutionError::IllegalInstruction {
2277 address: PackedAddress::new(
2278 program_counter.old_pc(zvexx_helpers::INSTRUCTION_SIZE),
2279 ),
2280 });
2281 }
2282 let Some(vtype) = env.vtype() else {
2283 ::core::hint::cold_path();
2284 return ExecutionResult::Err(ExecutionError::IllegalInstruction {
2285 address: PackedAddress::new(
2286 program_counter.old_pc(zvexx_helpers::INSTRUCTION_SIZE),
2287 ),
2288 });
2289 };
2290 let sew = vtype.vsew();
2291 if u32::from(sew.bits_width()) < 64 {
2292 ::core::hint::cold_path();
2293 return ExecutionResult::Err(ExecutionError::IllegalInstruction {
2294 address: PackedAddress::new(
2295 program_counter.old_pc(zvexx_helpers::INSTRUCTION_SIZE),
2296 ),
2297 });
2298 }
2299 let group_regs = vtype.vlmul().register_count();
2300 let src_group = group_regs.divide_by_factor(VsewFactor::F8);
2301 zvexx_widen_narrow_helpers::check_vs_ext_alignment::<Reg, _, _>(
2302 program_counter,
2303 vs2,
2304 src_group,
2305 vd,
2306 group_regs,
2307 )?;
2308 zvexx_widen_narrow_helpers::check_vreg_group_alignment::<Reg, _, _>(
2309 program_counter,
2310 vd,
2311 group_regs,
2312 )?;
2313 if !vm && vd == VReg::V0 {
2314 ::core::hint::cold_path();
2315 return ExecutionResult::Err(ExecutionError::IllegalInstruction {
2316 address: PackedAddress::new(
2317 program_counter.old_pc(zvexx_helpers::INSTRUCTION_SIZE),
2318 ),
2319 });
2320 }
2321 unsafe {
2323 zvexx_widen_narrow_helpers::execute_extension::<true, _, _>(
2324 env,
2325 vd,
2326 vs2,
2327 vm,
2328 sew,
2329 VsewFactor::F8,
2330 );
2331 }
2332 }
2333 }
2334
2335 ExecutionResult::ContinueNoWrite
2336 }
2337}