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