Skip to main content

ab_riscv_interpreter/v/zvexx/
widen_narrow.rs

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