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