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