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