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 ProgramCounter, RegisterFile, Rs1Rs2OperandValues, Rs1Rs2Operands, VirtualMemory,
12};
13use ab_riscv_macros::instruction_execution;
14use ab_riscv_primitives::prelude::*;
15use core::fmt;
16use core::ops::ControlFlow;
17
18#[instruction_execution]
19impl<Reg> ExecutableInstructionOperands for ZveXxWidenNarrowInstruction<Reg> where Reg: Register {}
20
21#[instruction_execution]
22impl<Reg, ExtState, CustomError> ExecutableInstructionCsr<ExtState, CustomError>
23 for ZveXxWidenNarrowInstruction<Reg>
24where
25 Reg: Register,
26{
27}
28
29#[instruction_execution]
30impl<Reg, Regs, ExtState, Memory, PC, InstructionHandler, CustomError>
31 ExecutableInstruction<Regs, ExtState, Memory, PC, InstructionHandler, CustomError>
32 for ZveXxWidenNarrowInstruction<Reg>
33where
34 Reg: Register,
35 Regs: RegisterFile<Reg>,
36 ExtState: VectorRegistersExt<Reg, CustomError>,
37 [(); ExtState::ELEN as usize]:,
38 [(); ExtState::VLEN as usize]:,
39 [(); ExtState::VLENB as usize]:,
40 Memory: VirtualMemory,
41 PC: ProgramCounter<Reg::Type, Memory, CustomError>,
42 CustomError: fmt::Debug,
43{
44 #[inline(always)]
45 fn execute(
46 self,
47 Rs1Rs2OperandValues {
48 rs1_value,
49 rs2_value: _,
50 }: Rs1Rs2OperandValues<<Self::Reg as Register>::Type>,
51 _regs: &mut Regs,
52 ext_state: &mut ExtState,
53 _memory: &mut Memory,
54 program_counter: &mut PC,
55 _system_instruction_handler: &mut InstructionHandler,
56 ) -> Result<
57 ControlFlow<(), (Self::Reg, <Self::Reg as Register>::Type)>,
58 ExecutionError<Reg::Type, CustomError>,
59 > {
60 match self {
61 Self::VwadduVv { vd, vs2, vs1, vm } => {
63 if !ext_state.vector_instructions_allowed() {
64 ::core::hint::cold_path();
65 return Err(ExecutionError::IllegalInstruction {
66 address: program_counter.old_pc(zvexx_helpers::INSTRUCTION_SIZE),
67 });
68 }
69 let Some(vtype) = ext_state.vtype() else {
70 ::core::hint::cold_path();
71 return Err(ExecutionError::IllegalInstruction {
72 address: program_counter.old_pc(zvexx_helpers::INSTRUCTION_SIZE),
73 });
74 };
75 let sew = vtype.vsew();
76 if u32::from(sew.bits_width()) * 2 > ExtState::ELEN {
78 ::core::hint::cold_path();
79 return Err(ExecutionError::IllegalInstruction {
80 address: program_counter.old_pc(zvexx_helpers::INSTRUCTION_SIZE),
81 });
82 }
83 let group_regs = vtype.vlmul().register_count();
84 let wide_eew = match sew {
85 Vsew::E8 => Eew::E16,
86 Vsew::E16 => Eew::E32,
87 Vsew::E32 => Eew::E64,
88 Vsew::E64 => unreachable!("SEW=64 already rejected above"),
89 };
90 let wide_group_regs = vtype.vlmul().data_register_count(wide_eew, sew).ok_or(
91 ExecutionError::IllegalInstruction {
92 address: program_counter.old_pc(zvexx_helpers::INSTRUCTION_SIZE),
93 },
94 )?;
95 zvexx_widen_narrow_helpers::check_vd_widen_alignment::<Reg, _, _, _>(
96 program_counter,
97 vd,
98 vs2,
99 Some(vs1),
100 group_regs,
101 wide_group_regs,
102 )?;
103 zvexx_widen_narrow_helpers::check_vreg_group_alignment::<Reg, _, _, _>(
104 program_counter,
105 vs2,
106 group_regs,
107 )?;
108 zvexx_widen_narrow_helpers::check_vreg_group_alignment::<Reg, _, _, _>(
109 program_counter,
110 vs1,
111 group_regs,
112 )?;
113 if !vm && vd == VReg::V0 {
114 ::core::hint::cold_path();
115 return Err(ExecutionError::IllegalInstruction {
116 address: program_counter.old_pc(zvexx_helpers::INSTRUCTION_SIZE),
117 });
118 }
119 unsafe {
121 zvexx_widen_narrow_helpers::execute_widen_op::<true, _, _, _, _>(
122 ext_state,
123 vd,
124 vs2,
125 zvexx_widen_narrow_helpers::OpSrc::Vreg(vs1),
126 vm,
127 sew,
128 u64::wrapping_add,
129 );
130 }
131 }
132 Self::VwadduVx {
134 vd,
135 vs2,
136 rs1: _,
137 vm,
138 } => {
139 if !ext_state.vector_instructions_allowed() {
140 ::core::hint::cold_path();
141 return Err(ExecutionError::IllegalInstruction {
142 address: program_counter.old_pc(zvexx_helpers::INSTRUCTION_SIZE),
143 });
144 }
145 let Some(vtype) = ext_state.vtype() else {
146 ::core::hint::cold_path();
147 return Err(ExecutionError::IllegalInstruction {
148 address: program_counter.old_pc(zvexx_helpers::INSTRUCTION_SIZE),
149 });
150 };
151 let sew = vtype.vsew();
152 if u32::from(sew.bits_width()) * 2 > ExtState::ELEN {
153 ::core::hint::cold_path();
154 return Err(ExecutionError::IllegalInstruction {
155 address: program_counter.old_pc(zvexx_helpers::INSTRUCTION_SIZE),
156 });
157 }
158 let group_regs = vtype.vlmul().register_count();
159 let wide_eew = match sew {
160 Vsew::E8 => Eew::E16,
161 Vsew::E16 => Eew::E32,
162 Vsew::E32 => Eew::E64,
163 Vsew::E64 => unreachable!("SEW=64 already rejected above"),
164 };
165 let wide_group_regs = vtype.vlmul().data_register_count(wide_eew, sew).ok_or(
166 ExecutionError::IllegalInstruction {
167 address: program_counter.old_pc(zvexx_helpers::INSTRUCTION_SIZE),
168 },
169 )?;
170 zvexx_widen_narrow_helpers::check_vd_widen_alignment::<Reg, _, _, _>(
171 program_counter,
172 vd,
173 vs2,
174 None,
175 group_regs,
176 wide_group_regs,
177 )?;
178 zvexx_widen_narrow_helpers::check_vreg_group_alignment::<Reg, _, _, _>(
179 program_counter,
180 vs2,
181 group_regs,
182 )?;
183 if !vm && vd == VReg::V0 {
184 ::core::hint::cold_path();
185 return Err(ExecutionError::IllegalInstruction {
186 address: program_counter.old_pc(zvexx_helpers::INSTRUCTION_SIZE),
187 });
188 }
189 let scalar = rs1_value.as_u64();
191 unsafe {
193 zvexx_widen_narrow_helpers::execute_widen_op::<true, _, _, _, _>(
194 ext_state,
195 vd,
196 vs2,
197 zvexx_widen_narrow_helpers::OpSrc::Scalar(scalar),
198 vm,
199 sew,
200 u64::wrapping_add,
201 );
202 }
203 }
204 Self::VwaddVv { vd, vs2, vs1, vm } => {
206 if !ext_state.vector_instructions_allowed() {
207 ::core::hint::cold_path();
208 return Err(ExecutionError::IllegalInstruction {
209 address: program_counter.old_pc(zvexx_helpers::INSTRUCTION_SIZE),
210 });
211 }
212 let Some(vtype) = ext_state.vtype() else {
213 ::core::hint::cold_path();
214 return Err(ExecutionError::IllegalInstruction {
215 address: program_counter.old_pc(zvexx_helpers::INSTRUCTION_SIZE),
216 });
217 };
218 let sew = vtype.vsew();
219 if u32::from(sew.bits_width()) * 2 > ExtState::ELEN {
220 ::core::hint::cold_path();
221 return Err(ExecutionError::IllegalInstruction {
222 address: program_counter.old_pc(zvexx_helpers::INSTRUCTION_SIZE),
223 });
224 }
225 let group_regs = vtype.vlmul().register_count();
226 let wide_eew = match sew {
227 Vsew::E8 => Eew::E16,
228 Vsew::E16 => Eew::E32,
229 Vsew::E32 => Eew::E64,
230 Vsew::E64 => unreachable!("SEW=64 already rejected above"),
231 };
232 let wide_group_regs = vtype.vlmul().data_register_count(wide_eew, sew).ok_or(
233 ExecutionError::IllegalInstruction {
234 address: program_counter.old_pc(zvexx_helpers::INSTRUCTION_SIZE),
235 },
236 )?;
237 zvexx_widen_narrow_helpers::check_vd_widen_alignment::<Reg, _, _, _>(
238 program_counter,
239 vd,
240 vs2,
241 Some(vs1),
242 group_regs,
243 wide_group_regs,
244 )?;
245 zvexx_widen_narrow_helpers::check_vreg_group_alignment::<Reg, _, _, _>(
246 program_counter,
247 vs2,
248 group_regs,
249 )?;
250 zvexx_widen_narrow_helpers::check_vreg_group_alignment::<Reg, _, _, _>(
251 program_counter,
252 vs1,
253 group_regs,
254 )?;
255 if !vm && vd == VReg::V0 {
256 ::core::hint::cold_path();
257 return Err(ExecutionError::IllegalInstruction {
258 address: program_counter.old_pc(zvexx_helpers::INSTRUCTION_SIZE),
259 });
260 }
261 unsafe {
263 zvexx_widen_narrow_helpers::execute_widen_op::<false, _, _, _, _>(
264 ext_state,
265 vd,
266 vs2,
267 zvexx_widen_narrow_helpers::OpSrc::Vreg(vs1),
268 vm,
269 sew,
270 u64::wrapping_add,
271 );
272 }
273 }
274 Self::VwaddVx {
276 vd,
277 vs2,
278 rs1: _,
279 vm,
280 } => {
281 if !ext_state.vector_instructions_allowed() {
282 ::core::hint::cold_path();
283 return Err(ExecutionError::IllegalInstruction {
284 address: program_counter.old_pc(zvexx_helpers::INSTRUCTION_SIZE),
285 });
286 }
287 let Some(vtype) = ext_state.vtype() else {
288 ::core::hint::cold_path();
289 return Err(ExecutionError::IllegalInstruction {
290 address: program_counter.old_pc(zvexx_helpers::INSTRUCTION_SIZE),
291 });
292 };
293 let sew = vtype.vsew();
294 if u32::from(sew.bits_width()) * 2 > ExtState::ELEN {
295 ::core::hint::cold_path();
296 return Err(ExecutionError::IllegalInstruction {
297 address: program_counter.old_pc(zvexx_helpers::INSTRUCTION_SIZE),
298 });
299 }
300 let group_regs = vtype.vlmul().register_count();
301 let wide_eew = match sew {
302 Vsew::E8 => Eew::E16,
303 Vsew::E16 => Eew::E32,
304 Vsew::E32 => Eew::E64,
305 Vsew::E64 => unreachable!("SEW=64 already rejected above"),
306 };
307 let wide_group_regs = vtype.vlmul().data_register_count(wide_eew, sew).ok_or(
308 ExecutionError::IllegalInstruction {
309 address: program_counter.old_pc(zvexx_helpers::INSTRUCTION_SIZE),
310 },
311 )?;
312 zvexx_widen_narrow_helpers::check_vd_widen_alignment::<Reg, _, _, _>(
313 program_counter,
314 vd,
315 vs2,
316 None,
317 group_regs,
318 wide_group_regs,
319 )?;
320 zvexx_widen_narrow_helpers::check_vreg_group_alignment::<Reg, _, _, _>(
321 program_counter,
322 vs2,
323 group_regs,
324 )?;
325 if !vm && vd == VReg::V0 {
326 ::core::hint::cold_path();
327 return Err(ExecutionError::IllegalInstruction {
328 address: program_counter.old_pc(zvexx_helpers::INSTRUCTION_SIZE),
329 });
330 }
331 let scalar =
333 zvexx_widen_narrow_helpers::sign_extend_bits(rs1_value.as_u64(), Reg::XLEN)
334 .cast_unsigned();
335 unsafe {
337 zvexx_widen_narrow_helpers::execute_widen_op::<false, _, _, _, _>(
338 ext_state,
339 vd,
340 vs2,
341 zvexx_widen_narrow_helpers::OpSrc::Scalar(scalar),
342 vm,
343 sew,
344 u64::wrapping_add,
345 );
346 }
347 }
348 Self::VwsubuVv { vd, vs2, vs1, vm } => {
350 if !ext_state.vector_instructions_allowed() {
351 ::core::hint::cold_path();
352 return Err(ExecutionError::IllegalInstruction {
353 address: program_counter.old_pc(zvexx_helpers::INSTRUCTION_SIZE),
354 });
355 }
356 let Some(vtype) = ext_state.vtype() else {
357 ::core::hint::cold_path();
358 return Err(ExecutionError::IllegalInstruction {
359 address: program_counter.old_pc(zvexx_helpers::INSTRUCTION_SIZE),
360 });
361 };
362 let sew = vtype.vsew();
363 if u32::from(sew.bits_width()) * 2 > ExtState::ELEN {
364 ::core::hint::cold_path();
365 return Err(ExecutionError::IllegalInstruction {
366 address: program_counter.old_pc(zvexx_helpers::INSTRUCTION_SIZE),
367 });
368 }
369 let group_regs = vtype.vlmul().register_count();
370 let wide_eew = match sew {
371 Vsew::E8 => Eew::E16,
372 Vsew::E16 => Eew::E32,
373 Vsew::E32 => Eew::E64,
374 Vsew::E64 => unreachable!("SEW=64 already rejected above"),
375 };
376 let wide_group_regs = vtype.vlmul().data_register_count(wide_eew, sew).ok_or(
377 ExecutionError::IllegalInstruction {
378 address: program_counter.old_pc(zvexx_helpers::INSTRUCTION_SIZE),
379 },
380 )?;
381 zvexx_widen_narrow_helpers::check_vd_widen_alignment::<Reg, _, _, _>(
382 program_counter,
383 vd,
384 vs2,
385 Some(vs1),
386 group_regs,
387 wide_group_regs,
388 )?;
389 zvexx_widen_narrow_helpers::check_vreg_group_alignment::<Reg, _, _, _>(
390 program_counter,
391 vs2,
392 group_regs,
393 )?;
394 zvexx_widen_narrow_helpers::check_vreg_group_alignment::<Reg, _, _, _>(
395 program_counter,
396 vs1,
397 group_regs,
398 )?;
399 if !vm && vd == VReg::V0 {
400 ::core::hint::cold_path();
401 return Err(ExecutionError::IllegalInstruction {
402 address: program_counter.old_pc(zvexx_helpers::INSTRUCTION_SIZE),
403 });
404 }
405 unsafe {
407 zvexx_widen_narrow_helpers::execute_widen_op::<true, _, _, _, _>(
408 ext_state,
409 vd,
410 vs2,
411 zvexx_widen_narrow_helpers::OpSrc::Vreg(vs1),
412 vm,
413 sew,
414 u64::wrapping_sub,
415 );
416 }
417 }
418 Self::VwsubuVx {
420 vd,
421 vs2,
422 rs1: _,
423 vm,
424 } => {
425 if !ext_state.vector_instructions_allowed() {
426 ::core::hint::cold_path();
427 return Err(ExecutionError::IllegalInstruction {
428 address: program_counter.old_pc(zvexx_helpers::INSTRUCTION_SIZE),
429 });
430 }
431 let Some(vtype) = ext_state.vtype() else {
432 ::core::hint::cold_path();
433 return Err(ExecutionError::IllegalInstruction {
434 address: program_counter.old_pc(zvexx_helpers::INSTRUCTION_SIZE),
435 });
436 };
437 let sew = vtype.vsew();
438 if u32::from(sew.bits_width()) * 2 > ExtState::ELEN {
439 ::core::hint::cold_path();
440 return Err(ExecutionError::IllegalInstruction {
441 address: program_counter.old_pc(zvexx_helpers::INSTRUCTION_SIZE),
442 });
443 }
444 let group_regs = vtype.vlmul().register_count();
445 let wide_eew = match sew {
446 Vsew::E8 => Eew::E16,
447 Vsew::E16 => Eew::E32,
448 Vsew::E32 => Eew::E64,
449 Vsew::E64 => unreachable!("SEW=64 already rejected above"),
450 };
451 let wide_group_regs = vtype.vlmul().data_register_count(wide_eew, sew).ok_or(
452 ExecutionError::IllegalInstruction {
453 address: program_counter.old_pc(zvexx_helpers::INSTRUCTION_SIZE),
454 },
455 )?;
456 zvexx_widen_narrow_helpers::check_vd_widen_alignment::<Reg, _, _, _>(
457 program_counter,
458 vd,
459 vs2,
460 None,
461 group_regs,
462 wide_group_regs,
463 )?;
464 zvexx_widen_narrow_helpers::check_vreg_group_alignment::<Reg, _, _, _>(
465 program_counter,
466 vs2,
467 group_regs,
468 )?;
469 if !vm && vd == VReg::V0 {
470 ::core::hint::cold_path();
471 return Err(ExecutionError::IllegalInstruction {
472 address: program_counter.old_pc(zvexx_helpers::INSTRUCTION_SIZE),
473 });
474 }
475 let scalar = rs1_value.as_u64();
476 unsafe {
478 zvexx_widen_narrow_helpers::execute_widen_op::<true, _, _, _, _>(
479 ext_state,
480 vd,
481 vs2,
482 zvexx_widen_narrow_helpers::OpSrc::Scalar(scalar),
483 vm,
484 sew,
485 u64::wrapping_sub,
486 );
487 }
488 }
489 Self::VwsubVv { vd, vs2, vs1, vm } => {
491 if !ext_state.vector_instructions_allowed() {
492 ::core::hint::cold_path();
493 return Err(ExecutionError::IllegalInstruction {
494 address: program_counter.old_pc(zvexx_helpers::INSTRUCTION_SIZE),
495 });
496 }
497 let Some(vtype) = ext_state.vtype() else {
498 ::core::hint::cold_path();
499 return Err(ExecutionError::IllegalInstruction {
500 address: program_counter.old_pc(zvexx_helpers::INSTRUCTION_SIZE),
501 });
502 };
503 let sew = vtype.vsew();
504 if u32::from(sew.bits_width()) * 2 > ExtState::ELEN {
505 ::core::hint::cold_path();
506 return Err(ExecutionError::IllegalInstruction {
507 address: program_counter.old_pc(zvexx_helpers::INSTRUCTION_SIZE),
508 });
509 }
510 let group_regs = vtype.vlmul().register_count();
511 let wide_eew = match sew {
512 Vsew::E8 => Eew::E16,
513 Vsew::E16 => Eew::E32,
514 Vsew::E32 => Eew::E64,
515 Vsew::E64 => unreachable!("SEW=64 already rejected above"),
516 };
517 let wide_group_regs = vtype.vlmul().data_register_count(wide_eew, sew).ok_or(
518 ExecutionError::IllegalInstruction {
519 address: program_counter.old_pc(zvexx_helpers::INSTRUCTION_SIZE),
520 },
521 )?;
522 zvexx_widen_narrow_helpers::check_vd_widen_alignment::<Reg, _, _, _>(
523 program_counter,
524 vd,
525 vs2,
526 Some(vs1),
527 group_regs,
528 wide_group_regs,
529 )?;
530 zvexx_widen_narrow_helpers::check_vreg_group_alignment::<Reg, _, _, _>(
531 program_counter,
532 vs2,
533 group_regs,
534 )?;
535 zvexx_widen_narrow_helpers::check_vreg_group_alignment::<Reg, _, _, _>(
536 program_counter,
537 vs1,
538 group_regs,
539 )?;
540 if !vm && vd == VReg::V0 {
541 ::core::hint::cold_path();
542 return Err(ExecutionError::IllegalInstruction {
543 address: program_counter.old_pc(zvexx_helpers::INSTRUCTION_SIZE),
544 });
545 }
546 unsafe {
548 zvexx_widen_narrow_helpers::execute_widen_op::<false, _, _, _, _>(
549 ext_state,
550 vd,
551 vs2,
552 zvexx_widen_narrow_helpers::OpSrc::Vreg(vs1),
553 vm,
554 sew,
555 u64::wrapping_sub,
556 );
557 }
558 }
559 Self::VwsubVx {
561 vd,
562 vs2,
563 rs1: _,
564 vm,
565 } => {
566 if !ext_state.vector_instructions_allowed() {
567 ::core::hint::cold_path();
568 return Err(ExecutionError::IllegalInstruction {
569 address: program_counter.old_pc(zvexx_helpers::INSTRUCTION_SIZE),
570 });
571 }
572 let Some(vtype) = ext_state.vtype() else {
573 ::core::hint::cold_path();
574 return Err(ExecutionError::IllegalInstruction {
575 address: program_counter.old_pc(zvexx_helpers::INSTRUCTION_SIZE),
576 });
577 };
578 let sew = vtype.vsew();
579 if u32::from(sew.bits_width()) * 2 > ExtState::ELEN {
580 ::core::hint::cold_path();
581 return Err(ExecutionError::IllegalInstruction {
582 address: program_counter.old_pc(zvexx_helpers::INSTRUCTION_SIZE),
583 });
584 }
585 let group_regs = vtype.vlmul().register_count();
586 let wide_eew = match sew {
587 Vsew::E8 => Eew::E16,
588 Vsew::E16 => Eew::E32,
589 Vsew::E32 => Eew::E64,
590 Vsew::E64 => unreachable!("SEW=64 already rejected above"),
591 };
592 let wide_group_regs = vtype.vlmul().data_register_count(wide_eew, sew).ok_or(
593 ExecutionError::IllegalInstruction {
594 address: program_counter.old_pc(zvexx_helpers::INSTRUCTION_SIZE),
595 },
596 )?;
597 zvexx_widen_narrow_helpers::check_vd_widen_alignment::<Reg, _, _, _>(
598 program_counter,
599 vd,
600 vs2,
601 None,
602 group_regs,
603 wide_group_regs,
604 )?;
605 zvexx_widen_narrow_helpers::check_vreg_group_alignment::<Reg, _, _, _>(
606 program_counter,
607 vs2,
608 group_regs,
609 )?;
610 if !vm && vd == VReg::V0 {
611 ::core::hint::cold_path();
612 return Err(ExecutionError::IllegalInstruction {
613 address: program_counter.old_pc(zvexx_helpers::INSTRUCTION_SIZE),
614 });
615 }
616 let scalar =
617 zvexx_widen_narrow_helpers::sign_extend_bits(rs1_value.as_u64(), Reg::XLEN)
618 .cast_unsigned();
619 unsafe {
621 zvexx_widen_narrow_helpers::execute_widen_op::<false, _, _, _, _>(
622 ext_state,
623 vd,
624 vs2,
625 zvexx_widen_narrow_helpers::OpSrc::Scalar(scalar),
626 vm,
627 sew,
628 u64::wrapping_sub,
629 );
630 }
631 }
632 Self::VwadduWv { vd, vs2, vs1, vm } => {
634 if !ext_state.vector_instructions_allowed() {
635 ::core::hint::cold_path();
636 return Err(ExecutionError::IllegalInstruction {
637 address: program_counter.old_pc(zvexx_helpers::INSTRUCTION_SIZE),
638 });
639 }
640 let Some(vtype) = ext_state.vtype() else {
641 ::core::hint::cold_path();
642 return Err(ExecutionError::IllegalInstruction {
643 address: program_counter.old_pc(zvexx_helpers::INSTRUCTION_SIZE),
644 });
645 };
646 let sew = vtype.vsew();
647 if u32::from(sew.bits_width()) * 2 > ExtState::ELEN {
648 ::core::hint::cold_path();
649 return Err(ExecutionError::IllegalInstruction {
650 address: program_counter.old_pc(zvexx_helpers::INSTRUCTION_SIZE),
651 });
652 }
653 let group_regs = vtype.vlmul().register_count();
654 let wide_eew = match sew {
655 Vsew::E8 => Eew::E16,
656 Vsew::E16 => Eew::E32,
657 Vsew::E32 => Eew::E64,
658 Vsew::E64 => unreachable!("SEW=64 already rejected above"),
659 };
660 let wide_group_regs = vtype.vlmul().data_register_count(wide_eew, sew).ok_or(
661 ExecutionError::IllegalInstruction {
662 address: program_counter.old_pc(zvexx_helpers::INSTRUCTION_SIZE),
663 },
664 )?;
665 zvexx_widen_narrow_helpers::check_vs_wide_alignment::<Reg, _, _, _>(
667 program_counter,
668 vs2,
669 wide_group_regs,
670 )?;
671 zvexx_widen_narrow_helpers::check_vreg_group_alignment::<Reg, _, _, _>(
672 program_counter,
673 vs1,
674 group_regs,
675 )?;
676 zvexx_widen_narrow_helpers::check_vd_widen_alignment::<Reg, _, _, _>(
677 program_counter,
678 vd,
679 vs1,
680 None,
681 group_regs,
682 wide_group_regs,
683 )?;
684 if !vm && vd == VReg::V0 {
685 ::core::hint::cold_path();
686 return Err(ExecutionError::IllegalInstruction {
687 address: program_counter.old_pc(zvexx_helpers::INSTRUCTION_SIZE),
688 });
689 }
690 unsafe {
692 zvexx_widen_narrow_helpers::execute_widen_w_op::<true, _, _, _, _>(
693 ext_state,
694 vd,
695 vs2,
696 zvexx_widen_narrow_helpers::OpSrc::Vreg(vs1),
697 vm,
698 sew,
699 u64::wrapping_add,
700 );
701 }
702 }
703 Self::VwadduWx {
705 vd,
706 vs2,
707 rs1: _,
708 vm,
709 } => {
710 if !ext_state.vector_instructions_allowed() {
711 ::core::hint::cold_path();
712 return Err(ExecutionError::IllegalInstruction {
713 address: program_counter.old_pc(zvexx_helpers::INSTRUCTION_SIZE),
714 });
715 }
716 let Some(vtype) = ext_state.vtype() else {
717 ::core::hint::cold_path();
718 return Err(ExecutionError::IllegalInstruction {
719 address: program_counter.old_pc(zvexx_helpers::INSTRUCTION_SIZE),
720 });
721 };
722 let sew = vtype.vsew();
723 if u32::from(sew.bits_width()) * 2 > ExtState::ELEN {
724 ::core::hint::cold_path();
725 return Err(ExecutionError::IllegalInstruction {
726 address: program_counter.old_pc(zvexx_helpers::INSTRUCTION_SIZE),
727 });
728 }
729 let wide_eew = match sew {
730 Vsew::E8 => Eew::E16,
731 Vsew::E16 => Eew::E32,
732 Vsew::E32 => Eew::E64,
733 Vsew::E64 => unreachable!("SEW=64 already rejected above"),
734 };
735 let wide_group_regs = vtype.vlmul().data_register_count(wide_eew, sew).ok_or(
736 ExecutionError::IllegalInstruction {
737 address: program_counter.old_pc(zvexx_helpers::INSTRUCTION_SIZE),
738 },
739 )?;
740 zvexx_widen_narrow_helpers::check_vs_wide_alignment::<Reg, _, _, _>(
742 program_counter,
743 vs2,
744 wide_group_regs,
745 )?;
746 zvexx_widen_narrow_helpers::check_vd_widen_no_src_check::<Reg, _, _, _>(
747 program_counter,
748 vd,
749 wide_group_regs,
750 )?;
751 if !vm && vd == VReg::V0 {
752 ::core::hint::cold_path();
753 return Err(ExecutionError::IllegalInstruction {
754 address: program_counter.old_pc(zvexx_helpers::INSTRUCTION_SIZE),
755 });
756 }
757 let scalar = rs1_value.as_u64();
758 unsafe {
760 zvexx_widen_narrow_helpers::execute_widen_w_op::<true, _, _, _, _>(
761 ext_state,
762 vd,
763 vs2,
764 zvexx_widen_narrow_helpers::OpSrc::Scalar(scalar),
765 vm,
766 sew,
767 u64::wrapping_add,
768 );
769 }
770 }
771 Self::VwaddWv { vd, vs2, vs1, vm } => {
773 if !ext_state.vector_instructions_allowed() {
774 ::core::hint::cold_path();
775 return Err(ExecutionError::IllegalInstruction {
776 address: program_counter.old_pc(zvexx_helpers::INSTRUCTION_SIZE),
777 });
778 }
779 let Some(vtype) = ext_state.vtype() else {
780 ::core::hint::cold_path();
781 return Err(ExecutionError::IllegalInstruction {
782 address: program_counter.old_pc(zvexx_helpers::INSTRUCTION_SIZE),
783 });
784 };
785 let sew = vtype.vsew();
786 if u32::from(sew.bits_width()) * 2 > ExtState::ELEN {
787 ::core::hint::cold_path();
788 return Err(ExecutionError::IllegalInstruction {
789 address: program_counter.old_pc(zvexx_helpers::INSTRUCTION_SIZE),
790 });
791 }
792 let group_regs = vtype.vlmul().register_count();
793 let wide_eew = match sew {
794 Vsew::E8 => Eew::E16,
795 Vsew::E16 => Eew::E32,
796 Vsew::E32 => Eew::E64,
797 Vsew::E64 => unreachable!("SEW=64 already rejected above"),
798 };
799 let wide_group_regs = vtype.vlmul().data_register_count(wide_eew, sew).ok_or(
800 ExecutionError::IllegalInstruction {
801 address: program_counter.old_pc(zvexx_helpers::INSTRUCTION_SIZE),
802 },
803 )?;
804 zvexx_widen_narrow_helpers::check_vs_wide_alignment::<Reg, _, _, _>(
805 program_counter,
806 vs2,
807 wide_group_regs,
808 )?;
809 zvexx_widen_narrow_helpers::check_vreg_group_alignment::<Reg, _, _, _>(
810 program_counter,
811 vs1,
812 group_regs,
813 )?;
814 zvexx_widen_narrow_helpers::check_vd_widen_alignment::<Reg, _, _, _>(
815 program_counter,
816 vd,
817 vs1,
818 None,
819 group_regs,
820 wide_group_regs,
821 )?;
822 if !vm && vd == VReg::V0 {
823 ::core::hint::cold_path();
824 return Err(ExecutionError::IllegalInstruction {
825 address: program_counter.old_pc(zvexx_helpers::INSTRUCTION_SIZE),
826 });
827 }
828 unsafe {
830 zvexx_widen_narrow_helpers::execute_widen_w_op::<false, _, _, _, _>(
831 ext_state,
832 vd,
833 vs2,
834 zvexx_widen_narrow_helpers::OpSrc::Vreg(vs1),
835 vm,
836 sew,
837 u64::wrapping_add,
838 );
839 }
840 }
841 Self::VwaddWx {
843 vd,
844 vs2,
845 rs1: _,
846 vm,
847 } => {
848 if !ext_state.vector_instructions_allowed() {
849 ::core::hint::cold_path();
850 return Err(ExecutionError::IllegalInstruction {
851 address: program_counter.old_pc(zvexx_helpers::INSTRUCTION_SIZE),
852 });
853 }
854 let Some(vtype) = ext_state.vtype() else {
855 ::core::hint::cold_path();
856 return Err(ExecutionError::IllegalInstruction {
857 address: program_counter.old_pc(zvexx_helpers::INSTRUCTION_SIZE),
858 });
859 };
860 let sew = vtype.vsew();
861 if u32::from(sew.bits_width()) * 2 > ExtState::ELEN {
862 ::core::hint::cold_path();
863 return Err(ExecutionError::IllegalInstruction {
864 address: program_counter.old_pc(zvexx_helpers::INSTRUCTION_SIZE),
865 });
866 }
867 let wide_eew = match sew {
868 Vsew::E8 => Eew::E16,
869 Vsew::E16 => Eew::E32,
870 Vsew::E32 => Eew::E64,
871 Vsew::E64 => unreachable!("SEW=64 already rejected above"),
872 };
873 let wide_group_regs = vtype.vlmul().data_register_count(wide_eew, sew).ok_or(
874 ExecutionError::IllegalInstruction {
875 address: program_counter.old_pc(zvexx_helpers::INSTRUCTION_SIZE),
876 },
877 )?;
878 zvexx_widen_narrow_helpers::check_vs_wide_alignment::<Reg, _, _, _>(
879 program_counter,
880 vs2,
881 wide_group_regs,
882 )?;
883 zvexx_widen_narrow_helpers::check_vd_widen_no_src_check::<Reg, _, _, _>(
884 program_counter,
885 vd,
886 wide_group_regs,
887 )?;
888 if !vm && vd == VReg::V0 {
889 ::core::hint::cold_path();
890 return Err(ExecutionError::IllegalInstruction {
891 address: program_counter.old_pc(zvexx_helpers::INSTRUCTION_SIZE),
892 });
893 }
894 let scalar =
895 zvexx_widen_narrow_helpers::sign_extend_bits(rs1_value.as_u64(), Reg::XLEN)
896 .cast_unsigned();
897 unsafe {
899 zvexx_widen_narrow_helpers::execute_widen_w_op::<false, _, _, _, _>(
900 ext_state,
901 vd,
902 vs2,
903 zvexx_widen_narrow_helpers::OpSrc::Scalar(scalar),
904 vm,
905 sew,
906 u64::wrapping_add,
907 );
908 }
909 }
910 Self::VwsubuWv { vd, vs2, vs1, vm } => {
912 if !ext_state.vector_instructions_allowed() {
913 ::core::hint::cold_path();
914 return Err(ExecutionError::IllegalInstruction {
915 address: program_counter.old_pc(zvexx_helpers::INSTRUCTION_SIZE),
916 });
917 }
918 let Some(vtype) = ext_state.vtype() else {
919 ::core::hint::cold_path();
920 return Err(ExecutionError::IllegalInstruction {
921 address: program_counter.old_pc(zvexx_helpers::INSTRUCTION_SIZE),
922 });
923 };
924 let sew = vtype.vsew();
925 if u32::from(sew.bits_width()) * 2 > ExtState::ELEN {
926 ::core::hint::cold_path();
927 return Err(ExecutionError::IllegalInstruction {
928 address: program_counter.old_pc(zvexx_helpers::INSTRUCTION_SIZE),
929 });
930 }
931 let group_regs = vtype.vlmul().register_count();
932 let wide_eew = match sew {
933 Vsew::E8 => Eew::E16,
934 Vsew::E16 => Eew::E32,
935 Vsew::E32 => Eew::E64,
936 Vsew::E64 => unreachable!("SEW=64 already rejected above"),
937 };
938 let wide_group_regs = vtype.vlmul().data_register_count(wide_eew, sew).ok_or(
939 ExecutionError::IllegalInstruction {
940 address: program_counter.old_pc(zvexx_helpers::INSTRUCTION_SIZE),
941 },
942 )?;
943 zvexx_widen_narrow_helpers::check_vs_wide_alignment::<Reg, _, _, _>(
944 program_counter,
945 vs2,
946 wide_group_regs,
947 )?;
948 zvexx_widen_narrow_helpers::check_vreg_group_alignment::<Reg, _, _, _>(
949 program_counter,
950 vs1,
951 group_regs,
952 )?;
953 zvexx_widen_narrow_helpers::check_vd_widen_alignment::<Reg, _, _, _>(
954 program_counter,
955 vd,
956 vs1,
957 None,
958 group_regs,
959 wide_group_regs,
960 )?;
961 if !vm && vd == VReg::V0 {
962 ::core::hint::cold_path();
963 return Err(ExecutionError::IllegalInstruction {
964 address: program_counter.old_pc(zvexx_helpers::INSTRUCTION_SIZE),
965 });
966 }
967 unsafe {
969 zvexx_widen_narrow_helpers::execute_widen_w_op::<true, _, _, _, _>(
970 ext_state,
971 vd,
972 vs2,
973 zvexx_widen_narrow_helpers::OpSrc::Vreg(vs1),
974 vm,
975 sew,
976 u64::wrapping_sub,
977 );
978 }
979 }
980 Self::VwsubuWx {
982 vd,
983 vs2,
984 rs1: _,
985 vm,
986 } => {
987 if !ext_state.vector_instructions_allowed() {
988 ::core::hint::cold_path();
989 return Err(ExecutionError::IllegalInstruction {
990 address: program_counter.old_pc(zvexx_helpers::INSTRUCTION_SIZE),
991 });
992 }
993 let Some(vtype) = ext_state.vtype() else {
994 ::core::hint::cold_path();
995 return Err(ExecutionError::IllegalInstruction {
996 address: program_counter.old_pc(zvexx_helpers::INSTRUCTION_SIZE),
997 });
998 };
999 let sew = vtype.vsew();
1000 if u32::from(sew.bits_width()) * 2 > ExtState::ELEN {
1001 ::core::hint::cold_path();
1002 return Err(ExecutionError::IllegalInstruction {
1003 address: program_counter.old_pc(zvexx_helpers::INSTRUCTION_SIZE),
1004 });
1005 }
1006 let wide_eew = match sew {
1007 Vsew::E8 => Eew::E16,
1008 Vsew::E16 => Eew::E32,
1009 Vsew::E32 => Eew::E64,
1010 Vsew::E64 => unreachable!("SEW=64 already rejected above"),
1011 };
1012 let wide_group_regs = vtype.vlmul().data_register_count(wide_eew, sew).ok_or(
1013 ExecutionError::IllegalInstruction {
1014 address: program_counter.old_pc(zvexx_helpers::INSTRUCTION_SIZE),
1015 },
1016 )?;
1017 zvexx_widen_narrow_helpers::check_vs_wide_alignment::<Reg, _, _, _>(
1018 program_counter,
1019 vs2,
1020 wide_group_regs,
1021 )?;
1022 zvexx_widen_narrow_helpers::check_vd_widen_no_src_check::<Reg, _, _, _>(
1023 program_counter,
1024 vd,
1025 wide_group_regs,
1026 )?;
1027 if !vm && vd == VReg::V0 {
1028 ::core::hint::cold_path();
1029 return Err(ExecutionError::IllegalInstruction {
1030 address: program_counter.old_pc(zvexx_helpers::INSTRUCTION_SIZE),
1031 });
1032 }
1033 let scalar = rs1_value.as_u64();
1034 unsafe {
1036 zvexx_widen_narrow_helpers::execute_widen_w_op::<true, _, _, _, _>(
1037 ext_state,
1038 vd,
1039 vs2,
1040 zvexx_widen_narrow_helpers::OpSrc::Scalar(scalar),
1041 vm,
1042 sew,
1043 u64::wrapping_sub,
1044 );
1045 }
1046 }
1047 Self::VwsubWv { vd, vs2, vs1, vm } => {
1049 if !ext_state.vector_instructions_allowed() {
1050 ::core::hint::cold_path();
1051 return Err(ExecutionError::IllegalInstruction {
1052 address: program_counter.old_pc(zvexx_helpers::INSTRUCTION_SIZE),
1053 });
1054 }
1055 let Some(vtype) = ext_state.vtype() else {
1056 ::core::hint::cold_path();
1057 return Err(ExecutionError::IllegalInstruction {
1058 address: program_counter.old_pc(zvexx_helpers::INSTRUCTION_SIZE),
1059 });
1060 };
1061 let sew = vtype.vsew();
1062 if u32::from(sew.bits_width()) * 2 > ExtState::ELEN {
1063 ::core::hint::cold_path();
1064 return Err(ExecutionError::IllegalInstruction {
1065 address: program_counter.old_pc(zvexx_helpers::INSTRUCTION_SIZE),
1066 });
1067 }
1068 let group_regs = vtype.vlmul().register_count();
1069 let wide_eew = match sew {
1070 Vsew::E8 => Eew::E16,
1071 Vsew::E16 => Eew::E32,
1072 Vsew::E32 => Eew::E64,
1073 Vsew::E64 => unreachable!("SEW=64 already rejected above"),
1074 };
1075 let wide_group_regs = vtype.vlmul().data_register_count(wide_eew, sew).ok_or(
1076 ExecutionError::IllegalInstruction {
1077 address: program_counter.old_pc(zvexx_helpers::INSTRUCTION_SIZE),
1078 },
1079 )?;
1080 zvexx_widen_narrow_helpers::check_vs_wide_alignment::<Reg, _, _, _>(
1081 program_counter,
1082 vs2,
1083 wide_group_regs,
1084 )?;
1085 zvexx_widen_narrow_helpers::check_vreg_group_alignment::<Reg, _, _, _>(
1086 program_counter,
1087 vs1,
1088 group_regs,
1089 )?;
1090 zvexx_widen_narrow_helpers::check_vd_widen_alignment::<Reg, _, _, _>(
1091 program_counter,
1092 vd,
1093 vs1,
1094 None,
1095 group_regs,
1096 wide_group_regs,
1097 )?;
1098 if !vm && vd == VReg::V0 {
1099 ::core::hint::cold_path();
1100 return Err(ExecutionError::IllegalInstruction {
1101 address: program_counter.old_pc(zvexx_helpers::INSTRUCTION_SIZE),
1102 });
1103 }
1104 unsafe {
1106 zvexx_widen_narrow_helpers::execute_widen_w_op::<false, _, _, _, _>(
1107 ext_state,
1108 vd,
1109 vs2,
1110 zvexx_widen_narrow_helpers::OpSrc::Vreg(vs1),
1111 vm,
1112 sew,
1113 u64::wrapping_sub,
1114 );
1115 }
1116 }
1117 Self::VwsubWx {
1119 vd,
1120 vs2,
1121 rs1: _,
1122 vm,
1123 } => {
1124 if !ext_state.vector_instructions_allowed() {
1125 ::core::hint::cold_path();
1126 return Err(ExecutionError::IllegalInstruction {
1127 address: program_counter.old_pc(zvexx_helpers::INSTRUCTION_SIZE),
1128 });
1129 }
1130 let Some(vtype) = ext_state.vtype() else {
1131 ::core::hint::cold_path();
1132 return Err(ExecutionError::IllegalInstruction {
1133 address: program_counter.old_pc(zvexx_helpers::INSTRUCTION_SIZE),
1134 });
1135 };
1136 let sew = vtype.vsew();
1137 if u32::from(sew.bits_width()) * 2 > ExtState::ELEN {
1138 ::core::hint::cold_path();
1139 return Err(ExecutionError::IllegalInstruction {
1140 address: program_counter.old_pc(zvexx_helpers::INSTRUCTION_SIZE),
1141 });
1142 }
1143 let wide_eew = match sew {
1144 Vsew::E8 => Eew::E16,
1145 Vsew::E16 => Eew::E32,
1146 Vsew::E32 => Eew::E64,
1147 Vsew::E64 => unreachable!("SEW=64 already rejected above"),
1148 };
1149 let wide_group_regs = vtype.vlmul().data_register_count(wide_eew, sew).ok_or(
1150 ExecutionError::IllegalInstruction {
1151 address: program_counter.old_pc(zvexx_helpers::INSTRUCTION_SIZE),
1152 },
1153 )?;
1154 zvexx_widen_narrow_helpers::check_vs_wide_alignment::<Reg, _, _, _>(
1155 program_counter,
1156 vs2,
1157 wide_group_regs,
1158 )?;
1159 zvexx_widen_narrow_helpers::check_vd_widen_no_src_check::<Reg, _, _, _>(
1160 program_counter,
1161 vd,
1162 wide_group_regs,
1163 )?;
1164 if !vm && vd == VReg::V0 {
1165 ::core::hint::cold_path();
1166 return Err(ExecutionError::IllegalInstruction {
1167 address: program_counter.old_pc(zvexx_helpers::INSTRUCTION_SIZE),
1168 });
1169 }
1170 let scalar =
1171 zvexx_widen_narrow_helpers::sign_extend_bits(rs1_value.as_u64(), Reg::XLEN)
1172 .cast_unsigned();
1173 unsafe {
1175 zvexx_widen_narrow_helpers::execute_widen_w_op::<false, _, _, _, _>(
1176 ext_state,
1177 vd,
1178 vs2,
1179 zvexx_widen_narrow_helpers::OpSrc::Scalar(scalar),
1180 vm,
1181 sew,
1182 u64::wrapping_sub,
1183 );
1184 }
1185 }
1186 Self::VnsrlWv { vd, vs2, vs1, vm } => {
1188 if !ext_state.vector_instructions_allowed() {
1189 ::core::hint::cold_path();
1190 return Err(ExecutionError::IllegalInstruction {
1191 address: program_counter.old_pc(zvexx_helpers::INSTRUCTION_SIZE),
1192 });
1193 }
1194 let Some(vtype) = ext_state.vtype() else {
1195 ::core::hint::cold_path();
1196 return Err(ExecutionError::IllegalInstruction {
1197 address: program_counter.old_pc(zvexx_helpers::INSTRUCTION_SIZE),
1198 });
1199 };
1200 let sew = vtype.vsew();
1201 if u32::from(sew.bits_width()) * 2 > ExtState::ELEN {
1203 ::core::hint::cold_path();
1204 return Err(ExecutionError::IllegalInstruction {
1205 address: program_counter.old_pc(zvexx_helpers::INSTRUCTION_SIZE),
1206 });
1207 }
1208 let group_regs = vtype.vlmul().register_count();
1209 let wide_eew = match sew {
1210 Vsew::E8 => Eew::E16,
1211 Vsew::E16 => Eew::E32,
1212 Vsew::E32 => Eew::E64,
1213 Vsew::E64 => unreachable!("SEW=64 already rejected above"),
1214 };
1215 let wide_group_regs = vtype.vlmul().data_register_count(wide_eew, sew).ok_or(
1216 ExecutionError::IllegalInstruction {
1217 address: program_counter.old_pc(zvexx_helpers::INSTRUCTION_SIZE),
1218 },
1219 )?;
1220 zvexx_widen_narrow_helpers::check_vd_narrow_alignment::<Reg, _, _, _>(
1221 program_counter,
1222 vd,
1223 group_regs,
1224 )?;
1225 zvexx_widen_narrow_helpers::check_vs_wide_alignment::<Reg, _, _, _>(
1226 program_counter,
1227 vs2,
1228 wide_group_regs,
1229 )?;
1230 zvexx_widen_narrow_helpers::check_vreg_group_alignment::<Reg, _, _, _>(
1231 program_counter,
1232 vs1,
1233 group_regs,
1234 )?;
1235 if !vm && vd == VReg::V0 {
1236 ::core::hint::cold_path();
1237 return Err(ExecutionError::IllegalInstruction {
1238 address: program_counter.old_pc(zvexx_helpers::INSTRUCTION_SIZE),
1239 });
1240 }
1241 unsafe {
1243 zvexx_widen_narrow_helpers::execute_narrow_shift::<false, _, _, _>(
1244 ext_state,
1245 vd,
1246 vs2,
1247 zvexx_widen_narrow_helpers::OpSrc::Vreg(vs1),
1248 vm,
1249 sew,
1250 );
1251 }
1252 }
1253 Self::VnsrlWx {
1255 vd,
1256 vs2,
1257 rs1: _,
1258 vm,
1259 } => {
1260 if !ext_state.vector_instructions_allowed() {
1261 ::core::hint::cold_path();
1262 return Err(ExecutionError::IllegalInstruction {
1263 address: program_counter.old_pc(zvexx_helpers::INSTRUCTION_SIZE),
1264 });
1265 }
1266 let Some(vtype) = ext_state.vtype() else {
1267 ::core::hint::cold_path();
1268 return Err(ExecutionError::IllegalInstruction {
1269 address: program_counter.old_pc(zvexx_helpers::INSTRUCTION_SIZE),
1270 });
1271 };
1272 let sew = vtype.vsew();
1273 if u32::from(sew.bits_width()) * 2 > ExtState::ELEN {
1274 ::core::hint::cold_path();
1275 return Err(ExecutionError::IllegalInstruction {
1276 address: program_counter.old_pc(zvexx_helpers::INSTRUCTION_SIZE),
1277 });
1278 }
1279 let group_regs = vtype.vlmul().register_count();
1280 let wide_eew = match sew {
1281 Vsew::E8 => Eew::E16,
1282 Vsew::E16 => Eew::E32,
1283 Vsew::E32 => Eew::E64,
1284 Vsew::E64 => unreachable!("SEW=64 already rejected above"),
1285 };
1286 let wide_group_regs = vtype.vlmul().data_register_count(wide_eew, sew).ok_or(
1287 ExecutionError::IllegalInstruction {
1288 address: program_counter.old_pc(zvexx_helpers::INSTRUCTION_SIZE),
1289 },
1290 )?;
1291 zvexx_widen_narrow_helpers::check_vd_narrow_alignment::<Reg, _, _, _>(
1292 program_counter,
1293 vd,
1294 group_regs,
1295 )?;
1296 zvexx_widen_narrow_helpers::check_vs_wide_alignment::<Reg, _, _, _>(
1297 program_counter,
1298 vs2,
1299 wide_group_regs,
1300 )?;
1301 if !vm && vd == VReg::V0 {
1302 ::core::hint::cold_path();
1303 return Err(ExecutionError::IllegalInstruction {
1304 address: program_counter.old_pc(zvexx_helpers::INSTRUCTION_SIZE),
1305 });
1306 }
1307 let scalar = rs1_value.as_u64();
1308 unsafe {
1310 zvexx_widen_narrow_helpers::execute_narrow_shift::<false, _, _, _>(
1311 ext_state,
1312 vd,
1313 vs2,
1314 zvexx_widen_narrow_helpers::OpSrc::Scalar(scalar),
1315 vm,
1316 sew,
1317 );
1318 }
1319 }
1320 Self::VnsrlWi { vd, vs2, uimm, vm } => {
1322 if !ext_state.vector_instructions_allowed() {
1323 ::core::hint::cold_path();
1324 return Err(ExecutionError::IllegalInstruction {
1325 address: program_counter.old_pc(zvexx_helpers::INSTRUCTION_SIZE),
1326 });
1327 }
1328 let Some(vtype) = ext_state.vtype() else {
1329 ::core::hint::cold_path();
1330 return Err(ExecutionError::IllegalInstruction {
1331 address: program_counter.old_pc(zvexx_helpers::INSTRUCTION_SIZE),
1332 });
1333 };
1334 let sew = vtype.vsew();
1335 if u32::from(sew.bits_width()) * 2 > ExtState::ELEN {
1336 ::core::hint::cold_path();
1337 return Err(ExecutionError::IllegalInstruction {
1338 address: program_counter.old_pc(zvexx_helpers::INSTRUCTION_SIZE),
1339 });
1340 }
1341 let group_regs = vtype.vlmul().register_count();
1342 let wide_eew = match sew {
1343 Vsew::E8 => Eew::E16,
1344 Vsew::E16 => Eew::E32,
1345 Vsew::E32 => Eew::E64,
1346 Vsew::E64 => unreachable!("SEW=64 already rejected above"),
1347 };
1348 let wide_group_regs = vtype.vlmul().data_register_count(wide_eew, sew).ok_or(
1349 ExecutionError::IllegalInstruction {
1350 address: program_counter.old_pc(zvexx_helpers::INSTRUCTION_SIZE),
1351 },
1352 )?;
1353 zvexx_widen_narrow_helpers::check_vd_narrow_alignment::<Reg, _, _, _>(
1354 program_counter,
1355 vd,
1356 group_regs,
1357 )?;
1358 zvexx_widen_narrow_helpers::check_vs_wide_alignment::<Reg, _, _, _>(
1359 program_counter,
1360 vs2,
1361 wide_group_regs,
1362 )?;
1363 if !vm && vd == VReg::V0 {
1364 ::core::hint::cold_path();
1365 return Err(ExecutionError::IllegalInstruction {
1366 address: program_counter.old_pc(zvexx_helpers::INSTRUCTION_SIZE),
1367 });
1368 }
1369 unsafe {
1371 zvexx_widen_narrow_helpers::execute_narrow_shift::<false, _, _, _>(
1372 ext_state,
1373 vd,
1374 vs2,
1375 zvexx_widen_narrow_helpers::OpSrc::Scalar(u64::from(uimm)),
1376 vm,
1377 sew,
1378 );
1379 }
1380 }
1381 Self::VnsraWv { vd, vs2, vs1, vm } => {
1383 if !ext_state.vector_instructions_allowed() {
1384 ::core::hint::cold_path();
1385 return Err(ExecutionError::IllegalInstruction {
1386 address: program_counter.old_pc(zvexx_helpers::INSTRUCTION_SIZE),
1387 });
1388 }
1389 let Some(vtype) = ext_state.vtype() else {
1390 ::core::hint::cold_path();
1391 return Err(ExecutionError::IllegalInstruction {
1392 address: program_counter.old_pc(zvexx_helpers::INSTRUCTION_SIZE),
1393 });
1394 };
1395 let sew = vtype.vsew();
1396 if u32::from(sew.bits_width()) * 2 > ExtState::ELEN {
1397 ::core::hint::cold_path();
1398 return Err(ExecutionError::IllegalInstruction {
1399 address: program_counter.old_pc(zvexx_helpers::INSTRUCTION_SIZE),
1400 });
1401 }
1402 let group_regs = vtype.vlmul().register_count();
1403 let wide_eew = match sew {
1404 Vsew::E8 => Eew::E16,
1405 Vsew::E16 => Eew::E32,
1406 Vsew::E32 => Eew::E64,
1407 Vsew::E64 => unreachable!("SEW=64 already rejected above"),
1408 };
1409 let wide_group_regs = vtype.vlmul().data_register_count(wide_eew, sew).ok_or(
1410 ExecutionError::IllegalInstruction {
1411 address: program_counter.old_pc(zvexx_helpers::INSTRUCTION_SIZE),
1412 },
1413 )?;
1414 zvexx_widen_narrow_helpers::check_vd_narrow_alignment::<Reg, _, _, _>(
1415 program_counter,
1416 vd,
1417 group_regs,
1418 )?;
1419 zvexx_widen_narrow_helpers::check_vs_wide_alignment::<Reg, _, _, _>(
1420 program_counter,
1421 vs2,
1422 wide_group_regs,
1423 )?;
1424 zvexx_widen_narrow_helpers::check_vreg_group_alignment::<Reg, _, _, _>(
1425 program_counter,
1426 vs1,
1427 group_regs,
1428 )?;
1429 if !vm && vd == VReg::V0 {
1430 ::core::hint::cold_path();
1431 return Err(ExecutionError::IllegalInstruction {
1432 address: program_counter.old_pc(zvexx_helpers::INSTRUCTION_SIZE),
1433 });
1434 }
1435 unsafe {
1437 zvexx_widen_narrow_helpers::execute_narrow_shift::<true, _, _, _>(
1438 ext_state,
1439 vd,
1440 vs2,
1441 zvexx_widen_narrow_helpers::OpSrc::Vreg(vs1),
1442 vm,
1443 sew,
1444 );
1445 }
1446 }
1447 Self::VnsraWx {
1449 vd,
1450 vs2,
1451 rs1: _,
1452 vm,
1453 } => {
1454 if !ext_state.vector_instructions_allowed() {
1455 ::core::hint::cold_path();
1456 return Err(ExecutionError::IllegalInstruction {
1457 address: program_counter.old_pc(zvexx_helpers::INSTRUCTION_SIZE),
1458 });
1459 }
1460 let Some(vtype) = ext_state.vtype() else {
1461 ::core::hint::cold_path();
1462 return Err(ExecutionError::IllegalInstruction {
1463 address: program_counter.old_pc(zvexx_helpers::INSTRUCTION_SIZE),
1464 });
1465 };
1466 let sew = vtype.vsew();
1467 if u32::from(sew.bits_width()) * 2 > ExtState::ELEN {
1468 ::core::hint::cold_path();
1469 return Err(ExecutionError::IllegalInstruction {
1470 address: program_counter.old_pc(zvexx_helpers::INSTRUCTION_SIZE),
1471 });
1472 }
1473 let group_regs = vtype.vlmul().register_count();
1474 let wide_eew = match sew {
1475 Vsew::E8 => Eew::E16,
1476 Vsew::E16 => Eew::E32,
1477 Vsew::E32 => Eew::E64,
1478 Vsew::E64 => unreachable!("SEW=64 already rejected above"),
1479 };
1480 let wide_group_regs = vtype.vlmul().data_register_count(wide_eew, sew).ok_or(
1481 ExecutionError::IllegalInstruction {
1482 address: program_counter.old_pc(zvexx_helpers::INSTRUCTION_SIZE),
1483 },
1484 )?;
1485 zvexx_widen_narrow_helpers::check_vd_narrow_alignment::<Reg, _, _, _>(
1486 program_counter,
1487 vd,
1488 group_regs,
1489 )?;
1490 zvexx_widen_narrow_helpers::check_vs_wide_alignment::<Reg, _, _, _>(
1491 program_counter,
1492 vs2,
1493 wide_group_regs,
1494 )?;
1495 if !vm && vd == VReg::V0 {
1496 ::core::hint::cold_path();
1497 return Err(ExecutionError::IllegalInstruction {
1498 address: program_counter.old_pc(zvexx_helpers::INSTRUCTION_SIZE),
1499 });
1500 }
1501 let scalar = rs1_value.as_u64();
1502 unsafe {
1504 zvexx_widen_narrow_helpers::execute_narrow_shift::<true, _, _, _>(
1505 ext_state,
1506 vd,
1507 vs2,
1508 zvexx_widen_narrow_helpers::OpSrc::Scalar(scalar),
1509 vm,
1510 sew,
1511 );
1512 }
1513 }
1514 Self::VnsraWi { vd, vs2, uimm, vm } => {
1516 if !ext_state.vector_instructions_allowed() {
1517 ::core::hint::cold_path();
1518 return Err(ExecutionError::IllegalInstruction {
1519 address: program_counter.old_pc(zvexx_helpers::INSTRUCTION_SIZE),
1520 });
1521 }
1522 let Some(vtype) = ext_state.vtype() else {
1523 ::core::hint::cold_path();
1524 return Err(ExecutionError::IllegalInstruction {
1525 address: program_counter.old_pc(zvexx_helpers::INSTRUCTION_SIZE),
1526 });
1527 };
1528 let sew = vtype.vsew();
1529 if u32::from(sew.bits_width()) * 2 > ExtState::ELEN {
1530 ::core::hint::cold_path();
1531 return Err(ExecutionError::IllegalInstruction {
1532 address: program_counter.old_pc(zvexx_helpers::INSTRUCTION_SIZE),
1533 });
1534 }
1535 let group_regs = vtype.vlmul().register_count();
1536 let wide_eew = match sew {
1537 Vsew::E8 => Eew::E16,
1538 Vsew::E16 => Eew::E32,
1539 Vsew::E32 => Eew::E64,
1540 Vsew::E64 => unreachable!("SEW=64 already rejected above"),
1541 };
1542 let wide_group_regs = vtype.vlmul().data_register_count(wide_eew, sew).ok_or(
1543 ExecutionError::IllegalInstruction {
1544 address: program_counter.old_pc(zvexx_helpers::INSTRUCTION_SIZE),
1545 },
1546 )?;
1547 zvexx_widen_narrow_helpers::check_vd_narrow_alignment::<Reg, _, _, _>(
1548 program_counter,
1549 vd,
1550 group_regs,
1551 )?;
1552 zvexx_widen_narrow_helpers::check_vs_wide_alignment::<Reg, _, _, _>(
1553 program_counter,
1554 vs2,
1555 wide_group_regs,
1556 )?;
1557 if !vm && vd == VReg::V0 {
1558 ::core::hint::cold_path();
1559 return Err(ExecutionError::IllegalInstruction {
1560 address: program_counter.old_pc(zvexx_helpers::INSTRUCTION_SIZE),
1561 });
1562 }
1563 unsafe {
1565 zvexx_widen_narrow_helpers::execute_narrow_shift::<true, _, _, _>(
1566 ext_state,
1567 vd,
1568 vs2,
1569 zvexx_widen_narrow_helpers::OpSrc::Scalar(u64::from(uimm)),
1570 vm,
1571 sew,
1572 );
1573 }
1574 }
1575 Self::VzextVf2 { vd, vs2, vm } => {
1577 if !ext_state.vector_instructions_allowed() {
1578 ::core::hint::cold_path();
1579 return Err(ExecutionError::IllegalInstruction {
1580 address: program_counter.old_pc(zvexx_helpers::INSTRUCTION_SIZE),
1581 });
1582 }
1583 let Some(vtype) = ext_state.vtype() else {
1584 ::core::hint::cold_path();
1585 return Err(ExecutionError::IllegalInstruction {
1586 address: program_counter.old_pc(zvexx_helpers::INSTRUCTION_SIZE),
1587 });
1588 };
1589 let sew = vtype.vsew();
1590 if u32::from(sew.bits_width()) < 16 {
1592 ::core::hint::cold_path();
1593 return Err(ExecutionError::IllegalInstruction {
1594 address: program_counter.old_pc(zvexx_helpers::INSTRUCTION_SIZE),
1595 });
1596 }
1597 let group_regs = vtype.vlmul().register_count();
1598 let src_group = group_regs.max(2) / 2;
1600 zvexx_widen_narrow_helpers::check_vs_ext_alignment::<Reg, _, _, _>(
1601 program_counter,
1602 vs2,
1603 src_group,
1604 vd,
1605 group_regs,
1606 )?;
1607 zvexx_widen_narrow_helpers::check_vreg_group_alignment::<Reg, _, _, _>(
1608 program_counter,
1609 vd,
1610 group_regs,
1611 )?;
1612 if !vm && vd == VReg::V0 {
1613 ::core::hint::cold_path();
1614 return Err(ExecutionError::IllegalInstruction {
1615 address: program_counter.old_pc(zvexx_helpers::INSTRUCTION_SIZE),
1616 });
1617 }
1618 unsafe {
1620 zvexx_widen_narrow_helpers::execute_extension::<false, _, _, _>(
1621 ext_state,
1622 vd,
1623 vs2,
1624 vm,
1625 sew,
1626 VsewFactor::F2,
1627 );
1628 }
1629 }
1630 Self::VzextVf4 { vd, vs2, vm } => {
1632 if !ext_state.vector_instructions_allowed() {
1633 ::core::hint::cold_path();
1634 return Err(ExecutionError::IllegalInstruction {
1635 address: program_counter.old_pc(zvexx_helpers::INSTRUCTION_SIZE),
1636 });
1637 }
1638 let Some(vtype) = ext_state.vtype() else {
1639 ::core::hint::cold_path();
1640 return Err(ExecutionError::IllegalInstruction {
1641 address: program_counter.old_pc(zvexx_helpers::INSTRUCTION_SIZE),
1642 });
1643 };
1644 let sew = vtype.vsew();
1645 if u32::from(sew.bits_width()) < 32 {
1647 ::core::hint::cold_path();
1648 return Err(ExecutionError::IllegalInstruction {
1649 address: program_counter.old_pc(zvexx_helpers::INSTRUCTION_SIZE),
1650 });
1651 }
1652 let group_regs = vtype.vlmul().register_count();
1653 let src_group = group_regs.max(4) / 4;
1654 zvexx_widen_narrow_helpers::check_vs_ext_alignment::<Reg, _, _, _>(
1655 program_counter,
1656 vs2,
1657 src_group,
1658 vd,
1659 group_regs,
1660 )?;
1661 zvexx_widen_narrow_helpers::check_vreg_group_alignment::<Reg, _, _, _>(
1662 program_counter,
1663 vd,
1664 group_regs,
1665 )?;
1666 if !vm && vd == VReg::V0 {
1667 ::core::hint::cold_path();
1668 return Err(ExecutionError::IllegalInstruction {
1669 address: program_counter.old_pc(zvexx_helpers::INSTRUCTION_SIZE),
1670 });
1671 }
1672 unsafe {
1674 zvexx_widen_narrow_helpers::execute_extension::<false, _, _, _>(
1675 ext_state,
1676 vd,
1677 vs2,
1678 vm,
1679 sew,
1680 VsewFactor::F4,
1681 );
1682 }
1683 }
1684 Self::VzextVf8 { vd, vs2, vm } => {
1686 if !ext_state.vector_instructions_allowed() {
1687 ::core::hint::cold_path();
1688 return Err(ExecutionError::IllegalInstruction {
1689 address: program_counter.old_pc(zvexx_helpers::INSTRUCTION_SIZE),
1690 });
1691 }
1692 let Some(vtype) = ext_state.vtype() else {
1693 ::core::hint::cold_path();
1694 return Err(ExecutionError::IllegalInstruction {
1695 address: program_counter.old_pc(zvexx_helpers::INSTRUCTION_SIZE),
1696 });
1697 };
1698 let sew = vtype.vsew();
1699 if u32::from(sew.bits_width()) < 64 {
1701 ::core::hint::cold_path();
1702 return Err(ExecutionError::IllegalInstruction {
1703 address: program_counter.old_pc(zvexx_helpers::INSTRUCTION_SIZE),
1704 });
1705 }
1706 let group_regs = vtype.vlmul().register_count();
1707 let src_group = group_regs.max(8) / 8;
1708 zvexx_widen_narrow_helpers::check_vs_ext_alignment::<Reg, _, _, _>(
1709 program_counter,
1710 vs2,
1711 src_group,
1712 vd,
1713 group_regs,
1714 )?;
1715 zvexx_widen_narrow_helpers::check_vreg_group_alignment::<Reg, _, _, _>(
1716 program_counter,
1717 vd,
1718 group_regs,
1719 )?;
1720 if !vm && vd == VReg::V0 {
1721 ::core::hint::cold_path();
1722 return Err(ExecutionError::IllegalInstruction {
1723 address: program_counter.old_pc(zvexx_helpers::INSTRUCTION_SIZE),
1724 });
1725 }
1726 unsafe {
1728 zvexx_widen_narrow_helpers::execute_extension::<false, _, _, _>(
1729 ext_state,
1730 vd,
1731 vs2,
1732 vm,
1733 sew,
1734 VsewFactor::F8,
1735 );
1736 }
1737 }
1738 Self::VsextVf2 { vd, vs2, vm } => {
1740 if !ext_state.vector_instructions_allowed() {
1741 ::core::hint::cold_path();
1742 return Err(ExecutionError::IllegalInstruction {
1743 address: program_counter.old_pc(zvexx_helpers::INSTRUCTION_SIZE),
1744 });
1745 }
1746 let Some(vtype) = ext_state.vtype() else {
1747 ::core::hint::cold_path();
1748 return Err(ExecutionError::IllegalInstruction {
1749 address: program_counter.old_pc(zvexx_helpers::INSTRUCTION_SIZE),
1750 });
1751 };
1752 let sew = vtype.vsew();
1753 if u32::from(sew.bits_width()) < 16 {
1754 ::core::hint::cold_path();
1755 return Err(ExecutionError::IllegalInstruction {
1756 address: program_counter.old_pc(zvexx_helpers::INSTRUCTION_SIZE),
1757 });
1758 }
1759 let group_regs = vtype.vlmul().register_count();
1760 let src_group = group_regs.max(2) / 2;
1761 zvexx_widen_narrow_helpers::check_vs_ext_alignment::<Reg, _, _, _>(
1762 program_counter,
1763 vs2,
1764 src_group,
1765 vd,
1766 group_regs,
1767 )?;
1768 zvexx_widen_narrow_helpers::check_vreg_group_alignment::<Reg, _, _, _>(
1769 program_counter,
1770 vd,
1771 group_regs,
1772 )?;
1773 if !vm && vd == VReg::V0 {
1774 ::core::hint::cold_path();
1775 return Err(ExecutionError::IllegalInstruction {
1776 address: program_counter.old_pc(zvexx_helpers::INSTRUCTION_SIZE),
1777 });
1778 }
1779 unsafe {
1781 zvexx_widen_narrow_helpers::execute_extension::<true, _, _, _>(
1782 ext_state,
1783 vd,
1784 vs2,
1785 vm,
1786 sew,
1787 VsewFactor::F2,
1788 );
1789 }
1790 }
1791 Self::VsextVf4 { vd, vs2, vm } => {
1793 if !ext_state.vector_instructions_allowed() {
1794 ::core::hint::cold_path();
1795 return Err(ExecutionError::IllegalInstruction {
1796 address: program_counter.old_pc(zvexx_helpers::INSTRUCTION_SIZE),
1797 });
1798 }
1799 let Some(vtype) = ext_state.vtype() else {
1800 ::core::hint::cold_path();
1801 return Err(ExecutionError::IllegalInstruction {
1802 address: program_counter.old_pc(zvexx_helpers::INSTRUCTION_SIZE),
1803 });
1804 };
1805 let sew = vtype.vsew();
1806 if u32::from(sew.bits_width()) < 32 {
1807 ::core::hint::cold_path();
1808 return Err(ExecutionError::IllegalInstruction {
1809 address: program_counter.old_pc(zvexx_helpers::INSTRUCTION_SIZE),
1810 });
1811 }
1812 let group_regs = vtype.vlmul().register_count();
1813 let src_group = group_regs.max(4) / 4;
1814 zvexx_widen_narrow_helpers::check_vs_ext_alignment::<Reg, _, _, _>(
1815 program_counter,
1816 vs2,
1817 src_group,
1818 vd,
1819 group_regs,
1820 )?;
1821 zvexx_widen_narrow_helpers::check_vreg_group_alignment::<Reg, _, _, _>(
1822 program_counter,
1823 vd,
1824 group_regs,
1825 )?;
1826 if !vm && vd == VReg::V0 {
1827 ::core::hint::cold_path();
1828 return Err(ExecutionError::IllegalInstruction {
1829 address: program_counter.old_pc(zvexx_helpers::INSTRUCTION_SIZE),
1830 });
1831 }
1832 unsafe {
1834 zvexx_widen_narrow_helpers::execute_extension::<true, _, _, _>(
1835 ext_state,
1836 vd,
1837 vs2,
1838 vm,
1839 sew,
1840 VsewFactor::F4,
1841 );
1842 }
1843 }
1844 Self::VsextVf8 { vd, vs2, vm } => {
1846 if !ext_state.vector_instructions_allowed() {
1847 ::core::hint::cold_path();
1848 return Err(ExecutionError::IllegalInstruction {
1849 address: program_counter.old_pc(zvexx_helpers::INSTRUCTION_SIZE),
1850 });
1851 }
1852 let Some(vtype) = ext_state.vtype() else {
1853 ::core::hint::cold_path();
1854 return Err(ExecutionError::IllegalInstruction {
1855 address: program_counter.old_pc(zvexx_helpers::INSTRUCTION_SIZE),
1856 });
1857 };
1858 let sew = vtype.vsew();
1859 if u32::from(sew.bits_width()) < 64 {
1860 ::core::hint::cold_path();
1861 return Err(ExecutionError::IllegalInstruction {
1862 address: program_counter.old_pc(zvexx_helpers::INSTRUCTION_SIZE),
1863 });
1864 }
1865 let group_regs = vtype.vlmul().register_count();
1866 let src_group = group_regs.max(8) / 8;
1867 zvexx_widen_narrow_helpers::check_vs_ext_alignment::<Reg, _, _, _>(
1868 program_counter,
1869 vs2,
1870 src_group,
1871 vd,
1872 group_regs,
1873 )?;
1874 zvexx_widen_narrow_helpers::check_vreg_group_alignment::<Reg, _, _, _>(
1875 program_counter,
1876 vd,
1877 group_regs,
1878 )?;
1879 if !vm && vd == VReg::V0 {
1880 ::core::hint::cold_path();
1881 return Err(ExecutionError::IllegalInstruction {
1882 address: program_counter.old_pc(zvexx_helpers::INSTRUCTION_SIZE),
1883 });
1884 }
1885 unsafe {
1887 zvexx_widen_narrow_helpers::execute_extension::<true, _, _, _>(
1888 ext_state,
1889 vd,
1890 vs2,
1891 vm,
1892 sew,
1893 VsewFactor::F8,
1894 );
1895 }
1896 }
1897 }
1898
1899 Ok(ControlFlow::Continue(Default::default()))
1900 }
1901}