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