Skip to main content

ab_riscv_interpreter/v/zvexx/
arith.rs

1//! ZveXx integer arithmetic instructions
2
3#[cfg(test)]
4mod tests;
5pub mod zvexx_arith_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 ZveXxArithInstruction<Reg> where Reg: Register {}
20
21#[instruction_execution]
22impl<Reg, ExtState, CustomError> ExecutableInstructionCsr<ExtState, CustomError>
23    for ZveXxArithInstruction<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 ZveXxArithInstruction<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            // vadd
62            Self::VaddVv { vd, vs2, vs1, vm } => {
63                if !ext_state.vector_instructions_allowed() {
64                    ::core::hint::cold_path();
65                    return Err(ExecutionError::IllegalInstruction {
66                        address: program_counter.old_pc(zvexx_helpers::INSTRUCTION_SIZE),
67                    });
68                }
69                let Some(vtype) = ext_state.vtype() else {
70                    ::core::hint::cold_path();
71                    return Err(ExecutionError::IllegalInstruction {
72                        address: program_counter.old_pc(zvexx_helpers::INSTRUCTION_SIZE),
73                    });
74                };
75                let group_regs = vtype.vlmul().register_count();
76                zvexx_arith_helpers::check_vreg_group_alignment::<Reg, _, _, _>(
77                    program_counter,
78                    vd,
79                    group_regs,
80                )?;
81                zvexx_arith_helpers::check_vreg_group_alignment::<Reg, _, _, _>(
82                    program_counter,
83                    vs2,
84                    group_regs,
85                )?;
86                zvexx_arith_helpers::check_vreg_group_alignment::<Reg, _, _, _>(
87                    program_counter,
88                    vs1,
89                    group_regs,
90                )?;
91                if !vm && vd == VReg::V0 {
92                    ::core::hint::cold_path();
93                    return Err(ExecutionError::IllegalInstruction {
94                        address: program_counter.old_pc(zvexx_helpers::INSTRUCTION_SIZE),
95                    });
96                }
97                let sew = vtype.vsew();
98                // SAFETY: alignment checked above; `vl <= VLMAX = group_regs * VLENB / sew_bytes`;
99                // masked vd != v0 checked above.
100                unsafe {
101                    zvexx_arith_helpers::execute_arith_op(
102                        ext_state,
103                        vd,
104                        vs2,
105                        zvexx_arith_helpers::OpSrc::Vreg(vs1),
106                        vm,
107                        sew,
108                        |a, b, _| a.wrapping_add(b),
109                    );
110                }
111            }
112            Self::VaddVx {
113                vd,
114                vs2,
115                rs1: _,
116                vm,
117            } => {
118                if !ext_state.vector_instructions_allowed() {
119                    ::core::hint::cold_path();
120                    return Err(ExecutionError::IllegalInstruction {
121                        address: program_counter.old_pc(zvexx_helpers::INSTRUCTION_SIZE),
122                    });
123                }
124                let Some(vtype) = ext_state.vtype() else {
125                    ::core::hint::cold_path();
126                    return Err(ExecutionError::IllegalInstruction {
127                        address: program_counter.old_pc(zvexx_helpers::INSTRUCTION_SIZE),
128                    });
129                };
130                let group_regs = vtype.vlmul().register_count();
131                zvexx_arith_helpers::check_vreg_group_alignment::<Reg, _, _, _>(
132                    program_counter,
133                    vd,
134                    group_regs,
135                )?;
136                zvexx_arith_helpers::check_vreg_group_alignment::<Reg, _, _, _>(
137                    program_counter,
138                    vs2,
139                    group_regs,
140                )?;
141                if !vm && vd == VReg::V0 {
142                    ::core::hint::cold_path();
143                    return Err(ExecutionError::IllegalInstruction {
144                        address: program_counter.old_pc(zvexx_helpers::INSTRUCTION_SIZE),
145                    });
146                }
147                let sew = vtype.vsew();
148                let scalar = rs1_value.as_i64().cast_unsigned();
149                // SAFETY: alignment checked above; scalar source has no register constraints
150                unsafe {
151                    zvexx_arith_helpers::execute_arith_op(
152                        ext_state,
153                        vd,
154                        vs2,
155                        zvexx_arith_helpers::OpSrc::Scalar(scalar),
156                        vm,
157                        sew,
158                        |a, b, _| a.wrapping_add(b),
159                    );
160                }
161            }
162            Self::VaddVi { vd, vs2, imm, vm } => {
163                if !ext_state.vector_instructions_allowed() {
164                    ::core::hint::cold_path();
165                    return Err(ExecutionError::IllegalInstruction {
166                        address: program_counter.old_pc(zvexx_helpers::INSTRUCTION_SIZE),
167                    });
168                }
169                let Some(vtype) = ext_state.vtype() else {
170                    ::core::hint::cold_path();
171                    return Err(ExecutionError::IllegalInstruction {
172                        address: program_counter.old_pc(zvexx_helpers::INSTRUCTION_SIZE),
173                    });
174                };
175                let group_regs = vtype.vlmul().register_count();
176                zvexx_arith_helpers::check_vreg_group_alignment::<Reg, _, _, _>(
177                    program_counter,
178                    vd,
179                    group_regs,
180                )?;
181                zvexx_arith_helpers::check_vreg_group_alignment::<Reg, _, _, _>(
182                    program_counter,
183                    vs2,
184                    group_regs,
185                )?;
186                if !vm && vd == VReg::V0 {
187                    ::core::hint::cold_path();
188                    return Err(ExecutionError::IllegalInstruction {
189                        address: program_counter.old_pc(zvexx_helpers::INSTRUCTION_SIZE),
190                    });
191                }
192                let sew = vtype.vsew();
193                // Sign-extend imm to u64 so wrapping_add works correctly for all SEW
194                let scalar = i64::from(imm).cast_unsigned();
195                // SAFETY: alignment checked above
196                unsafe {
197                    zvexx_arith_helpers::execute_arith_op(
198                        ext_state,
199                        vd,
200                        vs2,
201                        zvexx_arith_helpers::OpSrc::Scalar(scalar),
202                        vm,
203                        sew,
204                        |a, b, _| a.wrapping_add(b),
205                    );
206                }
207            }
208            // vsub / vrsub
209            Self::VsubVv { vd, vs2, vs1, vm } => {
210                if !ext_state.vector_instructions_allowed() {
211                    ::core::hint::cold_path();
212                    return Err(ExecutionError::IllegalInstruction {
213                        address: program_counter.old_pc(zvexx_helpers::INSTRUCTION_SIZE),
214                    });
215                }
216                let Some(vtype) = ext_state.vtype() else {
217                    ::core::hint::cold_path();
218                    return Err(ExecutionError::IllegalInstruction {
219                        address: program_counter.old_pc(zvexx_helpers::INSTRUCTION_SIZE),
220                    });
221                };
222                let group_regs = vtype.vlmul().register_count();
223                zvexx_arith_helpers::check_vreg_group_alignment::<Reg, _, _, _>(
224                    program_counter,
225                    vd,
226                    group_regs,
227                )?;
228                zvexx_arith_helpers::check_vreg_group_alignment::<Reg, _, _, _>(
229                    program_counter,
230                    vs2,
231                    group_regs,
232                )?;
233                zvexx_arith_helpers::check_vreg_group_alignment::<Reg, _, _, _>(
234                    program_counter,
235                    vs1,
236                    group_regs,
237                )?;
238                if !vm && vd == VReg::V0 {
239                    ::core::hint::cold_path();
240                    return Err(ExecutionError::IllegalInstruction {
241                        address: program_counter.old_pc(zvexx_helpers::INSTRUCTION_SIZE),
242                    });
243                }
244                let sew = vtype.vsew();
245                // SAFETY: alignment checked above
246                unsafe {
247                    zvexx_arith_helpers::execute_arith_op(
248                        ext_state,
249                        vd,
250                        vs2,
251                        zvexx_arith_helpers::OpSrc::Vreg(vs1),
252                        vm,
253                        sew,
254                        |a, b, _| a.wrapping_sub(b),
255                    );
256                }
257            }
258            Self::VsubVx {
259                vd,
260                vs2,
261                rs1: _,
262                vm,
263            } => {
264                if !ext_state.vector_instructions_allowed() {
265                    ::core::hint::cold_path();
266                    return Err(ExecutionError::IllegalInstruction {
267                        address: program_counter.old_pc(zvexx_helpers::INSTRUCTION_SIZE),
268                    });
269                }
270                let Some(vtype) = ext_state.vtype() else {
271                    ::core::hint::cold_path();
272                    return Err(ExecutionError::IllegalInstruction {
273                        address: program_counter.old_pc(zvexx_helpers::INSTRUCTION_SIZE),
274                    });
275                };
276                let group_regs = vtype.vlmul().register_count();
277                zvexx_arith_helpers::check_vreg_group_alignment::<Reg, _, _, _>(
278                    program_counter,
279                    vd,
280                    group_regs,
281                )?;
282                zvexx_arith_helpers::check_vreg_group_alignment::<Reg, _, _, _>(
283                    program_counter,
284                    vs2,
285                    group_regs,
286                )?;
287                if !vm && vd == VReg::V0 {
288                    ::core::hint::cold_path();
289                    return Err(ExecutionError::IllegalInstruction {
290                        address: program_counter.old_pc(zvexx_helpers::INSTRUCTION_SIZE),
291                    });
292                }
293                let sew = vtype.vsew();
294                let scalar = rs1_value.as_i64().cast_unsigned();
295                // SAFETY: alignment checked above
296                unsafe {
297                    zvexx_arith_helpers::execute_arith_op(
298                        ext_state,
299                        vd,
300                        vs2,
301                        zvexx_arith_helpers::OpSrc::Scalar(scalar),
302                        vm,
303                        sew,
304                        |a, b, _| a.wrapping_sub(b),
305                    );
306                }
307            }
308            Self::VrsubVx {
309                vd,
310                vs2,
311                rs1: _,
312                vm,
313            } => {
314                if !ext_state.vector_instructions_allowed() {
315                    ::core::hint::cold_path();
316                    return Err(ExecutionError::IllegalInstruction {
317                        address: program_counter.old_pc(zvexx_helpers::INSTRUCTION_SIZE),
318                    });
319                }
320                let Some(vtype) = ext_state.vtype() else {
321                    ::core::hint::cold_path();
322                    return Err(ExecutionError::IllegalInstruction {
323                        address: program_counter.old_pc(zvexx_helpers::INSTRUCTION_SIZE),
324                    });
325                };
326                let group_regs = vtype.vlmul().register_count();
327                zvexx_arith_helpers::check_vreg_group_alignment::<Reg, _, _, _>(
328                    program_counter,
329                    vd,
330                    group_regs,
331                )?;
332                zvexx_arith_helpers::check_vreg_group_alignment::<Reg, _, _, _>(
333                    program_counter,
334                    vs2,
335                    group_regs,
336                )?;
337                if !vm && vd == VReg::V0 {
338                    ::core::hint::cold_path();
339                    return Err(ExecutionError::IllegalInstruction {
340                        address: program_counter.old_pc(zvexx_helpers::INSTRUCTION_SIZE),
341                    });
342                }
343                let sew = vtype.vsew();
344                let scalar = rs1_value.as_i64().cast_unsigned();
345                // vrsub: result = src - vs2[i]
346                // SAFETY: alignment checked above
347                unsafe {
348                    zvexx_arith_helpers::execute_arith_op(
349                        ext_state,
350                        vd,
351                        vs2,
352                        zvexx_arith_helpers::OpSrc::Scalar(scalar),
353                        vm,
354                        sew,
355                        |a, b, _| b.wrapping_sub(a),
356                    );
357                }
358            }
359            Self::VrsubVi { vd, vs2, imm, vm } => {
360                if !ext_state.vector_instructions_allowed() {
361                    ::core::hint::cold_path();
362                    return Err(ExecutionError::IllegalInstruction {
363                        address: program_counter.old_pc(zvexx_helpers::INSTRUCTION_SIZE),
364                    });
365                }
366                let Some(vtype) = ext_state.vtype() else {
367                    ::core::hint::cold_path();
368                    return Err(ExecutionError::IllegalInstruction {
369                        address: program_counter.old_pc(zvexx_helpers::INSTRUCTION_SIZE),
370                    });
371                };
372                let group_regs = vtype.vlmul().register_count();
373                zvexx_arith_helpers::check_vreg_group_alignment::<Reg, _, _, _>(
374                    program_counter,
375                    vd,
376                    group_regs,
377                )?;
378                zvexx_arith_helpers::check_vreg_group_alignment::<Reg, _, _, _>(
379                    program_counter,
380                    vs2,
381                    group_regs,
382                )?;
383                if !vm && vd == VReg::V0 {
384                    ::core::hint::cold_path();
385                    return Err(ExecutionError::IllegalInstruction {
386                        address: program_counter.old_pc(zvexx_helpers::INSTRUCTION_SIZE),
387                    });
388                }
389                let sew = vtype.vsew();
390                let scalar = i64::from(imm).cast_unsigned();
391                // SAFETY: alignment checked above
392                unsafe {
393                    zvexx_arith_helpers::execute_arith_op(
394                        ext_state,
395                        vd,
396                        vs2,
397                        zvexx_arith_helpers::OpSrc::Scalar(scalar),
398                        vm,
399                        sew,
400                        |a, b, _| b.wrapping_sub(a),
401                    );
402                }
403            }
404            // vand
405            Self::VandVv { vd, vs2, vs1, vm } => {
406                if !ext_state.vector_instructions_allowed() {
407                    ::core::hint::cold_path();
408                    return Err(ExecutionError::IllegalInstruction {
409                        address: program_counter.old_pc(zvexx_helpers::INSTRUCTION_SIZE),
410                    });
411                }
412                let Some(vtype) = ext_state.vtype() else {
413                    ::core::hint::cold_path();
414                    return Err(ExecutionError::IllegalInstruction {
415                        address: program_counter.old_pc(zvexx_helpers::INSTRUCTION_SIZE),
416                    });
417                };
418                let group_regs = vtype.vlmul().register_count();
419                zvexx_arith_helpers::check_vreg_group_alignment::<Reg, _, _, _>(
420                    program_counter,
421                    vd,
422                    group_regs,
423                )?;
424                zvexx_arith_helpers::check_vreg_group_alignment::<Reg, _, _, _>(
425                    program_counter,
426                    vs2,
427                    group_regs,
428                )?;
429                zvexx_arith_helpers::check_vreg_group_alignment::<Reg, _, _, _>(
430                    program_counter,
431                    vs1,
432                    group_regs,
433                )?;
434                if !vm && vd == VReg::V0 {
435                    ::core::hint::cold_path();
436                    return Err(ExecutionError::IllegalInstruction {
437                        address: program_counter.old_pc(zvexx_helpers::INSTRUCTION_SIZE),
438                    });
439                }
440                let sew = vtype.vsew();
441                // SAFETY: alignment checked above
442                unsafe {
443                    zvexx_arith_helpers::execute_arith_op(
444                        ext_state,
445                        vd,
446                        vs2,
447                        zvexx_arith_helpers::OpSrc::Vreg(vs1),
448                        vm,
449                        sew,
450                        |a, b, _| a & b,
451                    );
452                }
453            }
454            Self::VandVx {
455                vd,
456                vs2,
457                rs1: _,
458                vm,
459            } => {
460                if !ext_state.vector_instructions_allowed() {
461                    ::core::hint::cold_path();
462                    return Err(ExecutionError::IllegalInstruction {
463                        address: program_counter.old_pc(zvexx_helpers::INSTRUCTION_SIZE),
464                    });
465                }
466                let Some(vtype) = ext_state.vtype() else {
467                    ::core::hint::cold_path();
468                    return Err(ExecutionError::IllegalInstruction {
469                        address: program_counter.old_pc(zvexx_helpers::INSTRUCTION_SIZE),
470                    });
471                };
472                let group_regs = vtype.vlmul().register_count();
473                zvexx_arith_helpers::check_vreg_group_alignment::<Reg, _, _, _>(
474                    program_counter,
475                    vd,
476                    group_regs,
477                )?;
478                zvexx_arith_helpers::check_vreg_group_alignment::<Reg, _, _, _>(
479                    program_counter,
480                    vs2,
481                    group_regs,
482                )?;
483                if !vm && vd == VReg::V0 {
484                    ::core::hint::cold_path();
485                    return Err(ExecutionError::IllegalInstruction {
486                        address: program_counter.old_pc(zvexx_helpers::INSTRUCTION_SIZE),
487                    });
488                }
489                let sew = vtype.vsew();
490                let scalar = rs1_value.as_i64().cast_unsigned();
491                // SAFETY: alignment checked above
492                unsafe {
493                    zvexx_arith_helpers::execute_arith_op(
494                        ext_state,
495                        vd,
496                        vs2,
497                        zvexx_arith_helpers::OpSrc::Scalar(scalar),
498                        vm,
499                        sew,
500                        |a, b, _| a & b,
501                    );
502                }
503            }
504            Self::VandVi { vd, vs2, imm, vm } => {
505                if !ext_state.vector_instructions_allowed() {
506                    ::core::hint::cold_path();
507                    return Err(ExecutionError::IllegalInstruction {
508                        address: program_counter.old_pc(zvexx_helpers::INSTRUCTION_SIZE),
509                    });
510                }
511                let Some(vtype) = ext_state.vtype() else {
512                    ::core::hint::cold_path();
513                    return Err(ExecutionError::IllegalInstruction {
514                        address: program_counter.old_pc(zvexx_helpers::INSTRUCTION_SIZE),
515                    });
516                };
517                let group_regs = vtype.vlmul().register_count();
518                zvexx_arith_helpers::check_vreg_group_alignment::<Reg, _, _, _>(
519                    program_counter,
520                    vd,
521                    group_regs,
522                )?;
523                zvexx_arith_helpers::check_vreg_group_alignment::<Reg, _, _, _>(
524                    program_counter,
525                    vs2,
526                    group_regs,
527                )?;
528                if !vm && vd == VReg::V0 {
529                    ::core::hint::cold_path();
530                    return Err(ExecutionError::IllegalInstruction {
531                        address: program_counter.old_pc(zvexx_helpers::INSTRUCTION_SIZE),
532                    });
533                }
534                let sew = vtype.vsew();
535                let scalar = i64::from(imm).cast_unsigned();
536                // SAFETY: alignment checked above
537                unsafe {
538                    zvexx_arith_helpers::execute_arith_op(
539                        ext_state,
540                        vd,
541                        vs2,
542                        zvexx_arith_helpers::OpSrc::Scalar(scalar),
543                        vm,
544                        sew,
545                        |a, b, _| a & b,
546                    );
547                }
548            }
549            // vor
550            Self::VorVv { vd, vs2, vs1, vm } => {
551                if !ext_state.vector_instructions_allowed() {
552                    ::core::hint::cold_path();
553                    return Err(ExecutionError::IllegalInstruction {
554                        address: program_counter.old_pc(zvexx_helpers::INSTRUCTION_SIZE),
555                    });
556                }
557                let Some(vtype) = ext_state.vtype() else {
558                    ::core::hint::cold_path();
559                    return Err(ExecutionError::IllegalInstruction {
560                        address: program_counter.old_pc(zvexx_helpers::INSTRUCTION_SIZE),
561                    });
562                };
563                let group_regs = vtype.vlmul().register_count();
564                zvexx_arith_helpers::check_vreg_group_alignment::<Reg, _, _, _>(
565                    program_counter,
566                    vd,
567                    group_regs,
568                )?;
569                zvexx_arith_helpers::check_vreg_group_alignment::<Reg, _, _, _>(
570                    program_counter,
571                    vs2,
572                    group_regs,
573                )?;
574                zvexx_arith_helpers::check_vreg_group_alignment::<Reg, _, _, _>(
575                    program_counter,
576                    vs1,
577                    group_regs,
578                )?;
579                if !vm && vd == VReg::V0 {
580                    ::core::hint::cold_path();
581                    return Err(ExecutionError::IllegalInstruction {
582                        address: program_counter.old_pc(zvexx_helpers::INSTRUCTION_SIZE),
583                    });
584                }
585                let sew = vtype.vsew();
586                // SAFETY: alignment checked above
587                unsafe {
588                    zvexx_arith_helpers::execute_arith_op(
589                        ext_state,
590                        vd,
591                        vs2,
592                        zvexx_arith_helpers::OpSrc::Vreg(vs1),
593                        vm,
594                        sew,
595                        |a, b, _| a | b,
596                    );
597                }
598            }
599            Self::VorVx {
600                vd,
601                vs2,
602                rs1: _,
603                vm,
604            } => {
605                if !ext_state.vector_instructions_allowed() {
606                    ::core::hint::cold_path();
607                    return Err(ExecutionError::IllegalInstruction {
608                        address: program_counter.old_pc(zvexx_helpers::INSTRUCTION_SIZE),
609                    });
610                }
611                let Some(vtype) = ext_state.vtype() else {
612                    ::core::hint::cold_path();
613                    return Err(ExecutionError::IllegalInstruction {
614                        address: program_counter.old_pc(zvexx_helpers::INSTRUCTION_SIZE),
615                    });
616                };
617                let group_regs = vtype.vlmul().register_count();
618                zvexx_arith_helpers::check_vreg_group_alignment::<Reg, _, _, _>(
619                    program_counter,
620                    vd,
621                    group_regs,
622                )?;
623                zvexx_arith_helpers::check_vreg_group_alignment::<Reg, _, _, _>(
624                    program_counter,
625                    vs2,
626                    group_regs,
627                )?;
628                if !vm && vd == VReg::V0 {
629                    ::core::hint::cold_path();
630                    return Err(ExecutionError::IllegalInstruction {
631                        address: program_counter.old_pc(zvexx_helpers::INSTRUCTION_SIZE),
632                    });
633                }
634                let sew = vtype.vsew();
635                let scalar = rs1_value.as_i64().cast_unsigned();
636                // SAFETY: alignment checked above
637                unsafe {
638                    zvexx_arith_helpers::execute_arith_op(
639                        ext_state,
640                        vd,
641                        vs2,
642                        zvexx_arith_helpers::OpSrc::Scalar(scalar),
643                        vm,
644                        sew,
645                        |a, b, _| a | b,
646                    );
647                }
648            }
649            Self::VorVi { vd, vs2, imm, vm } => {
650                if !ext_state.vector_instructions_allowed() {
651                    ::core::hint::cold_path();
652                    return Err(ExecutionError::IllegalInstruction {
653                        address: program_counter.old_pc(zvexx_helpers::INSTRUCTION_SIZE),
654                    });
655                }
656                let Some(vtype) = ext_state.vtype() else {
657                    ::core::hint::cold_path();
658                    return Err(ExecutionError::IllegalInstruction {
659                        address: program_counter.old_pc(zvexx_helpers::INSTRUCTION_SIZE),
660                    });
661                };
662                let group_regs = vtype.vlmul().register_count();
663                zvexx_arith_helpers::check_vreg_group_alignment::<Reg, _, _, _>(
664                    program_counter,
665                    vd,
666                    group_regs,
667                )?;
668                zvexx_arith_helpers::check_vreg_group_alignment::<Reg, _, _, _>(
669                    program_counter,
670                    vs2,
671                    group_regs,
672                )?;
673                if !vm && vd == VReg::V0 {
674                    ::core::hint::cold_path();
675                    return Err(ExecutionError::IllegalInstruction {
676                        address: program_counter.old_pc(zvexx_helpers::INSTRUCTION_SIZE),
677                    });
678                }
679                let sew = vtype.vsew();
680                let scalar = i64::from(imm).cast_unsigned();
681                // SAFETY: alignment checked above
682                unsafe {
683                    zvexx_arith_helpers::execute_arith_op(
684                        ext_state,
685                        vd,
686                        vs2,
687                        zvexx_arith_helpers::OpSrc::Scalar(scalar),
688                        vm,
689                        sew,
690                        |a, b, _| a | b,
691                    );
692                }
693            }
694            // vxor
695            Self::VxorVv { vd, vs2, vs1, vm } => {
696                if !ext_state.vector_instructions_allowed() {
697                    ::core::hint::cold_path();
698                    return Err(ExecutionError::IllegalInstruction {
699                        address: program_counter.old_pc(zvexx_helpers::INSTRUCTION_SIZE),
700                    });
701                }
702                let Some(vtype) = ext_state.vtype() else {
703                    ::core::hint::cold_path();
704                    return Err(ExecutionError::IllegalInstruction {
705                        address: program_counter.old_pc(zvexx_helpers::INSTRUCTION_SIZE),
706                    });
707                };
708                let group_regs = vtype.vlmul().register_count();
709                zvexx_arith_helpers::check_vreg_group_alignment::<Reg, _, _, _>(
710                    program_counter,
711                    vd,
712                    group_regs,
713                )?;
714                zvexx_arith_helpers::check_vreg_group_alignment::<Reg, _, _, _>(
715                    program_counter,
716                    vs2,
717                    group_regs,
718                )?;
719                zvexx_arith_helpers::check_vreg_group_alignment::<Reg, _, _, _>(
720                    program_counter,
721                    vs1,
722                    group_regs,
723                )?;
724                if !vm && vd == VReg::V0 {
725                    ::core::hint::cold_path();
726                    return Err(ExecutionError::IllegalInstruction {
727                        address: program_counter.old_pc(zvexx_helpers::INSTRUCTION_SIZE),
728                    });
729                }
730                let sew = vtype.vsew();
731                // SAFETY: alignment checked above
732                unsafe {
733                    zvexx_arith_helpers::execute_arith_op(
734                        ext_state,
735                        vd,
736                        vs2,
737                        zvexx_arith_helpers::OpSrc::Vreg(vs1),
738                        vm,
739                        sew,
740                        |a, b, _| a ^ b,
741                    );
742                }
743            }
744            Self::VxorVx {
745                vd,
746                vs2,
747                rs1: _,
748                vm,
749            } => {
750                if !ext_state.vector_instructions_allowed() {
751                    ::core::hint::cold_path();
752                    return Err(ExecutionError::IllegalInstruction {
753                        address: program_counter.old_pc(zvexx_helpers::INSTRUCTION_SIZE),
754                    });
755                }
756                let Some(vtype) = ext_state.vtype() else {
757                    ::core::hint::cold_path();
758                    return Err(ExecutionError::IllegalInstruction {
759                        address: program_counter.old_pc(zvexx_helpers::INSTRUCTION_SIZE),
760                    });
761                };
762                let group_regs = vtype.vlmul().register_count();
763                zvexx_arith_helpers::check_vreg_group_alignment::<Reg, _, _, _>(
764                    program_counter,
765                    vd,
766                    group_regs,
767                )?;
768                zvexx_arith_helpers::check_vreg_group_alignment::<Reg, _, _, _>(
769                    program_counter,
770                    vs2,
771                    group_regs,
772                )?;
773                if !vm && vd == VReg::V0 {
774                    ::core::hint::cold_path();
775                    return Err(ExecutionError::IllegalInstruction {
776                        address: program_counter.old_pc(zvexx_helpers::INSTRUCTION_SIZE),
777                    });
778                }
779                let sew = vtype.vsew();
780                let scalar = rs1_value.as_i64().cast_unsigned();
781                // SAFETY: alignment checked above
782                unsafe {
783                    zvexx_arith_helpers::execute_arith_op(
784                        ext_state,
785                        vd,
786                        vs2,
787                        zvexx_arith_helpers::OpSrc::Scalar(scalar),
788                        vm,
789                        sew,
790                        |a, b, _| a ^ b,
791                    );
792                }
793            }
794            Self::VxorVi { vd, vs2, imm, vm } => {
795                if !ext_state.vector_instructions_allowed() {
796                    ::core::hint::cold_path();
797                    return Err(ExecutionError::IllegalInstruction {
798                        address: program_counter.old_pc(zvexx_helpers::INSTRUCTION_SIZE),
799                    });
800                }
801                let Some(vtype) = ext_state.vtype() else {
802                    ::core::hint::cold_path();
803                    return Err(ExecutionError::IllegalInstruction {
804                        address: program_counter.old_pc(zvexx_helpers::INSTRUCTION_SIZE),
805                    });
806                };
807                let group_regs = vtype.vlmul().register_count();
808                zvexx_arith_helpers::check_vreg_group_alignment::<Reg, _, _, _>(
809                    program_counter,
810                    vd,
811                    group_regs,
812                )?;
813                zvexx_arith_helpers::check_vreg_group_alignment::<Reg, _, _, _>(
814                    program_counter,
815                    vs2,
816                    group_regs,
817                )?;
818                if !vm && vd == VReg::V0 {
819                    ::core::hint::cold_path();
820                    return Err(ExecutionError::IllegalInstruction {
821                        address: program_counter.old_pc(zvexx_helpers::INSTRUCTION_SIZE),
822                    });
823                }
824                let sew = vtype.vsew();
825                let scalar = i64::from(imm).cast_unsigned();
826                // SAFETY: alignment checked above
827                unsafe {
828                    zvexx_arith_helpers::execute_arith_op(
829                        ext_state,
830                        vd,
831                        vs2,
832                        zvexx_arith_helpers::OpSrc::Scalar(scalar),
833                        vm,
834                        sew,
835                        |a, b, _| a ^ b,
836                    );
837                }
838            }
839            // vsll
840            Self::VsllVv { vd, vs2, vs1, vm } => {
841                if !ext_state.vector_instructions_allowed() {
842                    ::core::hint::cold_path();
843                    return Err(ExecutionError::IllegalInstruction {
844                        address: program_counter.old_pc(zvexx_helpers::INSTRUCTION_SIZE),
845                    });
846                }
847                let Some(vtype) = ext_state.vtype() else {
848                    ::core::hint::cold_path();
849                    return Err(ExecutionError::IllegalInstruction {
850                        address: program_counter.old_pc(zvexx_helpers::INSTRUCTION_SIZE),
851                    });
852                };
853                let group_regs = vtype.vlmul().register_count();
854                zvexx_arith_helpers::check_vreg_group_alignment::<Reg, _, _, _>(
855                    program_counter,
856                    vd,
857                    group_regs,
858                )?;
859                zvexx_arith_helpers::check_vreg_group_alignment::<Reg, _, _, _>(
860                    program_counter,
861                    vs2,
862                    group_regs,
863                )?;
864                zvexx_arith_helpers::check_vreg_group_alignment::<Reg, _, _, _>(
865                    program_counter,
866                    vs1,
867                    group_regs,
868                )?;
869                if !vm && vd == VReg::V0 {
870                    ::core::hint::cold_path();
871                    return Err(ExecutionError::IllegalInstruction {
872                        address: program_counter.old_pc(zvexx_helpers::INSTRUCTION_SIZE),
873                    });
874                }
875                let sew = vtype.vsew();
876                // SAFETY: alignment checked above
877                unsafe {
878                    zvexx_arith_helpers::execute_arith_op(
879                        ext_state,
880                        vd,
881                        vs2,
882                        zvexx_arith_helpers::OpSrc::Vreg(vs1),
883                        vm,
884                        sew,
885                        // Shift amount masked to log2(SEW) bits per spec ยง12.6
886                        |a, b, sew| a << (b & u64::from(sew.bits_width() - 1)),
887                    );
888                }
889            }
890            Self::VsllVx {
891                vd,
892                vs2,
893                rs1: _,
894                vm,
895            } => {
896                if !ext_state.vector_instructions_allowed() {
897                    ::core::hint::cold_path();
898                    return Err(ExecutionError::IllegalInstruction {
899                        address: program_counter.old_pc(zvexx_helpers::INSTRUCTION_SIZE),
900                    });
901                }
902                let Some(vtype) = ext_state.vtype() else {
903                    ::core::hint::cold_path();
904                    return Err(ExecutionError::IllegalInstruction {
905                        address: program_counter.old_pc(zvexx_helpers::INSTRUCTION_SIZE),
906                    });
907                };
908                let group_regs = vtype.vlmul().register_count();
909                zvexx_arith_helpers::check_vreg_group_alignment::<Reg, _, _, _>(
910                    program_counter,
911                    vd,
912                    group_regs,
913                )?;
914                zvexx_arith_helpers::check_vreg_group_alignment::<Reg, _, _, _>(
915                    program_counter,
916                    vs2,
917                    group_regs,
918                )?;
919                if !vm && vd == VReg::V0 {
920                    ::core::hint::cold_path();
921                    return Err(ExecutionError::IllegalInstruction {
922                        address: program_counter.old_pc(zvexx_helpers::INSTRUCTION_SIZE),
923                    });
924                }
925                let sew = vtype.vsew();
926                let scalar = rs1_value.as_u64();
927                // SAFETY: alignment checked above
928                unsafe {
929                    zvexx_arith_helpers::execute_arith_op(
930                        ext_state,
931                        vd,
932                        vs2,
933                        zvexx_arith_helpers::OpSrc::Scalar(scalar),
934                        vm,
935                        sew,
936                        |a, b, sew| a << (b & u64::from(sew.bits_width() - 1)),
937                    );
938                }
939            }
940            Self::VsllVi { vd, vs2, uimm, vm } => {
941                if !ext_state.vector_instructions_allowed() {
942                    ::core::hint::cold_path();
943                    return Err(ExecutionError::IllegalInstruction {
944                        address: program_counter.old_pc(zvexx_helpers::INSTRUCTION_SIZE),
945                    });
946                }
947                let Some(vtype) = ext_state.vtype() else {
948                    ::core::hint::cold_path();
949                    return Err(ExecutionError::IllegalInstruction {
950                        address: program_counter.old_pc(zvexx_helpers::INSTRUCTION_SIZE),
951                    });
952                };
953                let group_regs = vtype.vlmul().register_count();
954                zvexx_arith_helpers::check_vreg_group_alignment::<Reg, _, _, _>(
955                    program_counter,
956                    vd,
957                    group_regs,
958                )?;
959                zvexx_arith_helpers::check_vreg_group_alignment::<Reg, _, _, _>(
960                    program_counter,
961                    vs2,
962                    group_regs,
963                )?;
964                if !vm && vd == VReg::V0 {
965                    ::core::hint::cold_path();
966                    return Err(ExecutionError::IllegalInstruction {
967                        address: program_counter.old_pc(zvexx_helpers::INSTRUCTION_SIZE),
968                    });
969                }
970                let sew = vtype.vsew();
971                // Immediate is already unsigned 5-bit; mask to log2(SEW) here too
972                let shamt = u64::from(uimm) & u64::from(sew.bits_width() - 1);
973                // SAFETY: alignment checked above
974                unsafe {
975                    zvexx_arith_helpers::execute_arith_op(
976                        ext_state,
977                        vd,
978                        vs2,
979                        zvexx_arith_helpers::OpSrc::Scalar(shamt),
980                        vm,
981                        sew,
982                        |a, b, _| a << b,
983                    );
984                }
985            }
986            // vsrl
987            Self::VsrlVv { vd, vs2, vs1, vm } => {
988                if !ext_state.vector_instructions_allowed() {
989                    ::core::hint::cold_path();
990                    return Err(ExecutionError::IllegalInstruction {
991                        address: program_counter.old_pc(zvexx_helpers::INSTRUCTION_SIZE),
992                    });
993                }
994                let Some(vtype) = ext_state.vtype() else {
995                    ::core::hint::cold_path();
996                    return Err(ExecutionError::IllegalInstruction {
997                        address: program_counter.old_pc(zvexx_helpers::INSTRUCTION_SIZE),
998                    });
999                };
1000                let group_regs = vtype.vlmul().register_count();
1001                zvexx_arith_helpers::check_vreg_group_alignment::<Reg, _, _, _>(
1002                    program_counter,
1003                    vd,
1004                    group_regs,
1005                )?;
1006                zvexx_arith_helpers::check_vreg_group_alignment::<Reg, _, _, _>(
1007                    program_counter,
1008                    vs2,
1009                    group_regs,
1010                )?;
1011                zvexx_arith_helpers::check_vreg_group_alignment::<Reg, _, _, _>(
1012                    program_counter,
1013                    vs1,
1014                    group_regs,
1015                )?;
1016                if !vm && vd == VReg::V0 {
1017                    ::core::hint::cold_path();
1018                    return Err(ExecutionError::IllegalInstruction {
1019                        address: program_counter.old_pc(zvexx_helpers::INSTRUCTION_SIZE),
1020                    });
1021                }
1022                let sew = vtype.vsew();
1023                // SAFETY: alignment checked above
1024                unsafe {
1025                    zvexx_arith_helpers::execute_arith_op(
1026                        ext_state,
1027                        vd,
1028                        vs2,
1029                        zvexx_arith_helpers::OpSrc::Vreg(vs1),
1030                        vm,
1031                        sew,
1032                        // Logical right shift; operate on the SEW-wide portion only
1033                        |a, b, sew| {
1034                            let mask = zvexx_arith_helpers::sew_mask(sew);
1035                            let shamt = b & u64::from(sew.bits_width() - 1);
1036                            (a & mask) >> shamt
1037                        },
1038                    );
1039                }
1040            }
1041            Self::VsrlVx {
1042                vd,
1043                vs2,
1044                rs1: _,
1045                vm,
1046            } => {
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 group_regs = vtype.vlmul().register_count();
1060                zvexx_arith_helpers::check_vreg_group_alignment::<Reg, _, _, _>(
1061                    program_counter,
1062                    vd,
1063                    group_regs,
1064                )?;
1065                zvexx_arith_helpers::check_vreg_group_alignment::<Reg, _, _, _>(
1066                    program_counter,
1067                    vs2,
1068                    group_regs,
1069                )?;
1070                if !vm && vd == VReg::V0 {
1071                    ::core::hint::cold_path();
1072                    return Err(ExecutionError::IllegalInstruction {
1073                        address: program_counter.old_pc(zvexx_helpers::INSTRUCTION_SIZE),
1074                    });
1075                }
1076                let sew = vtype.vsew();
1077                let scalar = rs1_value.as_u64();
1078                // SAFETY: alignment checked above
1079                unsafe {
1080                    zvexx_arith_helpers::execute_arith_op(
1081                        ext_state,
1082                        vd,
1083                        vs2,
1084                        zvexx_arith_helpers::OpSrc::Scalar(scalar),
1085                        vm,
1086                        sew,
1087                        |a, b, sew| {
1088                            let mask = zvexx_arith_helpers::sew_mask(sew);
1089                            let shamt = b & u64::from(sew.bits_width() - 1);
1090                            (a & mask) >> shamt
1091                        },
1092                    );
1093                }
1094            }
1095            Self::VsrlVi { vd, vs2, uimm, vm } => {
1096                if !ext_state.vector_instructions_allowed() {
1097                    ::core::hint::cold_path();
1098                    return Err(ExecutionError::IllegalInstruction {
1099                        address: program_counter.old_pc(zvexx_helpers::INSTRUCTION_SIZE),
1100                    });
1101                }
1102                let Some(vtype) = ext_state.vtype() else {
1103                    ::core::hint::cold_path();
1104                    return Err(ExecutionError::IllegalInstruction {
1105                        address: program_counter.old_pc(zvexx_helpers::INSTRUCTION_SIZE),
1106                    });
1107                };
1108                let group_regs = vtype.vlmul().register_count();
1109                zvexx_arith_helpers::check_vreg_group_alignment::<Reg, _, _, _>(
1110                    program_counter,
1111                    vd,
1112                    group_regs,
1113                )?;
1114                zvexx_arith_helpers::check_vreg_group_alignment::<Reg, _, _, _>(
1115                    program_counter,
1116                    vs2,
1117                    group_regs,
1118                )?;
1119                if !vm && vd == VReg::V0 {
1120                    ::core::hint::cold_path();
1121                    return Err(ExecutionError::IllegalInstruction {
1122                        address: program_counter.old_pc(zvexx_helpers::INSTRUCTION_SIZE),
1123                    });
1124                }
1125                let sew = vtype.vsew();
1126                let shamt = u64::from(uimm) & u64::from(sew.bits_width() - 1);
1127                // SAFETY: alignment checked above
1128                unsafe {
1129                    zvexx_arith_helpers::execute_arith_op(
1130                        ext_state,
1131                        vd,
1132                        vs2,
1133                        zvexx_arith_helpers::OpSrc::Scalar(shamt),
1134                        vm,
1135                        sew,
1136                        |a, b, sew| (a & zvexx_arith_helpers::sew_mask(sew)) >> b,
1137                    );
1138                }
1139            }
1140            // vsra
1141            Self::VsraVv { vd, vs2, vs1, vm } => {
1142                if !ext_state.vector_instructions_allowed() {
1143                    ::core::hint::cold_path();
1144                    return Err(ExecutionError::IllegalInstruction {
1145                        address: program_counter.old_pc(zvexx_helpers::INSTRUCTION_SIZE),
1146                    });
1147                }
1148                let Some(vtype) = ext_state.vtype() else {
1149                    ::core::hint::cold_path();
1150                    return Err(ExecutionError::IllegalInstruction {
1151                        address: program_counter.old_pc(zvexx_helpers::INSTRUCTION_SIZE),
1152                    });
1153                };
1154                let group_regs = vtype.vlmul().register_count();
1155                zvexx_arith_helpers::check_vreg_group_alignment::<Reg, _, _, _>(
1156                    program_counter,
1157                    vd,
1158                    group_regs,
1159                )?;
1160                zvexx_arith_helpers::check_vreg_group_alignment::<Reg, _, _, _>(
1161                    program_counter,
1162                    vs2,
1163                    group_regs,
1164                )?;
1165                zvexx_arith_helpers::check_vreg_group_alignment::<Reg, _, _, _>(
1166                    program_counter,
1167                    vs1,
1168                    group_regs,
1169                )?;
1170                if !vm && vd == VReg::V0 {
1171                    ::core::hint::cold_path();
1172                    return Err(ExecutionError::IllegalInstruction {
1173                        address: program_counter.old_pc(zvexx_helpers::INSTRUCTION_SIZE),
1174                    });
1175                }
1176                let sew = vtype.vsew();
1177                // SAFETY: alignment checked above
1178                unsafe {
1179                    zvexx_arith_helpers::execute_arith_op(
1180                        ext_state,
1181                        vd,
1182                        vs2,
1183                        zvexx_arith_helpers::OpSrc::Vreg(vs1),
1184                        vm,
1185                        sew,
1186                        |a, b, sew| {
1187                            let shamt = b & u64::from(sew.bits_width() - 1);
1188                            let signed = zvexx_arith_helpers::sign_extend(a, sew);
1189                            (signed >> shamt).cast_unsigned()
1190                        },
1191                    );
1192                }
1193            }
1194            Self::VsraVx {
1195                vd,
1196                vs2,
1197                rs1: _,
1198                vm,
1199            } => {
1200                if !ext_state.vector_instructions_allowed() {
1201                    ::core::hint::cold_path();
1202                    return Err(ExecutionError::IllegalInstruction {
1203                        address: program_counter.old_pc(zvexx_helpers::INSTRUCTION_SIZE),
1204                    });
1205                }
1206                let Some(vtype) = ext_state.vtype() else {
1207                    ::core::hint::cold_path();
1208                    return Err(ExecutionError::IllegalInstruction {
1209                        address: program_counter.old_pc(zvexx_helpers::INSTRUCTION_SIZE),
1210                    });
1211                };
1212                let group_regs = vtype.vlmul().register_count();
1213                zvexx_arith_helpers::check_vreg_group_alignment::<Reg, _, _, _>(
1214                    program_counter,
1215                    vd,
1216                    group_regs,
1217                )?;
1218                zvexx_arith_helpers::check_vreg_group_alignment::<Reg, _, _, _>(
1219                    program_counter,
1220                    vs2,
1221                    group_regs,
1222                )?;
1223                if !vm && vd == VReg::V0 {
1224                    ::core::hint::cold_path();
1225                    return Err(ExecutionError::IllegalInstruction {
1226                        address: program_counter.old_pc(zvexx_helpers::INSTRUCTION_SIZE),
1227                    });
1228                }
1229                let sew = vtype.vsew();
1230                let scalar = rs1_value.as_u64();
1231                // SAFETY: alignment checked above
1232                unsafe {
1233                    zvexx_arith_helpers::execute_arith_op(
1234                        ext_state,
1235                        vd,
1236                        vs2,
1237                        zvexx_arith_helpers::OpSrc::Scalar(scalar),
1238                        vm,
1239                        sew,
1240                        |a, b, sew| {
1241                            let shamt = b & u64::from(sew.bits_width() - 1);
1242                            let signed = zvexx_arith_helpers::sign_extend(a, sew);
1243                            (signed >> shamt).cast_unsigned()
1244                        },
1245                    );
1246                }
1247            }
1248            Self::VsraVi { vd, vs2, uimm, vm } => {
1249                if !ext_state.vector_instructions_allowed() {
1250                    ::core::hint::cold_path();
1251                    return Err(ExecutionError::IllegalInstruction {
1252                        address: program_counter.old_pc(zvexx_helpers::INSTRUCTION_SIZE),
1253                    });
1254                }
1255                let Some(vtype) = ext_state.vtype() else {
1256                    ::core::hint::cold_path();
1257                    return Err(ExecutionError::IllegalInstruction {
1258                        address: program_counter.old_pc(zvexx_helpers::INSTRUCTION_SIZE),
1259                    });
1260                };
1261                let group_regs = vtype.vlmul().register_count();
1262                zvexx_arith_helpers::check_vreg_group_alignment::<Reg, _, _, _>(
1263                    program_counter,
1264                    vd,
1265                    group_regs,
1266                )?;
1267                zvexx_arith_helpers::check_vreg_group_alignment::<Reg, _, _, _>(
1268                    program_counter,
1269                    vs2,
1270                    group_regs,
1271                )?;
1272                if !vm && vd == VReg::V0 {
1273                    ::core::hint::cold_path();
1274                    return Err(ExecutionError::IllegalInstruction {
1275                        address: program_counter.old_pc(zvexx_helpers::INSTRUCTION_SIZE),
1276                    });
1277                }
1278                let sew = vtype.vsew();
1279                let shamt = u64::from(uimm) & u64::from(sew.bits_width() - 1);
1280                // SAFETY: alignment checked above
1281                unsafe {
1282                    zvexx_arith_helpers::execute_arith_op(
1283                        ext_state,
1284                        vd,
1285                        vs2,
1286                        zvexx_arith_helpers::OpSrc::Scalar(shamt),
1287                        vm,
1288                        sew,
1289                        |a, b, sew| {
1290                            let signed = zvexx_arith_helpers::sign_extend(a, sew);
1291                            (signed >> b).cast_unsigned()
1292                        },
1293                    );
1294                }
1295            }
1296            // vminu / vmin
1297            Self::VminuVv { vd, vs2, vs1, vm } => {
1298                if !ext_state.vector_instructions_allowed() {
1299                    ::core::hint::cold_path();
1300                    return Err(ExecutionError::IllegalInstruction {
1301                        address: program_counter.old_pc(zvexx_helpers::INSTRUCTION_SIZE),
1302                    });
1303                }
1304                let Some(vtype) = ext_state.vtype() else {
1305                    ::core::hint::cold_path();
1306                    return Err(ExecutionError::IllegalInstruction {
1307                        address: program_counter.old_pc(zvexx_helpers::INSTRUCTION_SIZE),
1308                    });
1309                };
1310                let group_regs = vtype.vlmul().register_count();
1311                zvexx_arith_helpers::check_vreg_group_alignment::<Reg, _, _, _>(
1312                    program_counter,
1313                    vd,
1314                    group_regs,
1315                )?;
1316                zvexx_arith_helpers::check_vreg_group_alignment::<Reg, _, _, _>(
1317                    program_counter,
1318                    vs2,
1319                    group_regs,
1320                )?;
1321                zvexx_arith_helpers::check_vreg_group_alignment::<Reg, _, _, _>(
1322                    program_counter,
1323                    vs1,
1324                    group_regs,
1325                )?;
1326                if !vm && vd == VReg::V0 {
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                // SAFETY: alignment checked above
1334                unsafe {
1335                    zvexx_arith_helpers::execute_arith_op(
1336                        ext_state,
1337                        vd,
1338                        vs2,
1339                        zvexx_arith_helpers::OpSrc::Vreg(vs1),
1340                        vm,
1341                        sew,
1342                        |a, b, sew| {
1343                            let mask = zvexx_arith_helpers::sew_mask(sew);
1344                            if a & mask <= b & mask { a } else { b }
1345                        },
1346                    );
1347                }
1348            }
1349            Self::VminuVx {
1350                vd,
1351                vs2,
1352                rs1: _,
1353                vm,
1354            } => {
1355                if !ext_state.vector_instructions_allowed() {
1356                    ::core::hint::cold_path();
1357                    return Err(ExecutionError::IllegalInstruction {
1358                        address: program_counter.old_pc(zvexx_helpers::INSTRUCTION_SIZE),
1359                    });
1360                }
1361                let Some(vtype) = ext_state.vtype() else {
1362                    ::core::hint::cold_path();
1363                    return Err(ExecutionError::IllegalInstruction {
1364                        address: program_counter.old_pc(zvexx_helpers::INSTRUCTION_SIZE),
1365                    });
1366                };
1367                let group_regs = vtype.vlmul().register_count();
1368                zvexx_arith_helpers::check_vreg_group_alignment::<Reg, _, _, _>(
1369                    program_counter,
1370                    vd,
1371                    group_regs,
1372                )?;
1373                zvexx_arith_helpers::check_vreg_group_alignment::<Reg, _, _, _>(
1374                    program_counter,
1375                    vs2,
1376                    group_regs,
1377                )?;
1378                if !vm && vd == VReg::V0 {
1379                    ::core::hint::cold_path();
1380                    return Err(ExecutionError::IllegalInstruction {
1381                        address: program_counter.old_pc(zvexx_helpers::INSTRUCTION_SIZE),
1382                    });
1383                }
1384                let sew = vtype.vsew();
1385                let scalar = rs1_value.as_i64().cast_unsigned();
1386                // SAFETY: alignment checked above
1387                unsafe {
1388                    zvexx_arith_helpers::execute_arith_op(
1389                        ext_state,
1390                        vd,
1391                        vs2,
1392                        zvexx_arith_helpers::OpSrc::Scalar(scalar),
1393                        vm,
1394                        sew,
1395                        |a, b, sew| {
1396                            let mask = zvexx_arith_helpers::sew_mask(sew);
1397                            if a & mask <= b & mask { a } else { b }
1398                        },
1399                    );
1400                }
1401            }
1402            Self::VminVv { vd, vs2, vs1, vm } => {
1403                if !ext_state.vector_instructions_allowed() {
1404                    ::core::hint::cold_path();
1405                    return Err(ExecutionError::IllegalInstruction {
1406                        address: program_counter.old_pc(zvexx_helpers::INSTRUCTION_SIZE),
1407                    });
1408                }
1409                let Some(vtype) = ext_state.vtype() else {
1410                    ::core::hint::cold_path();
1411                    return Err(ExecutionError::IllegalInstruction {
1412                        address: program_counter.old_pc(zvexx_helpers::INSTRUCTION_SIZE),
1413                    });
1414                };
1415                let group_regs = vtype.vlmul().register_count();
1416                zvexx_arith_helpers::check_vreg_group_alignment::<Reg, _, _, _>(
1417                    program_counter,
1418                    vd,
1419                    group_regs,
1420                )?;
1421                zvexx_arith_helpers::check_vreg_group_alignment::<Reg, _, _, _>(
1422                    program_counter,
1423                    vs2,
1424                    group_regs,
1425                )?;
1426                zvexx_arith_helpers::check_vreg_group_alignment::<Reg, _, _, _>(
1427                    program_counter,
1428                    vs1,
1429                    group_regs,
1430                )?;
1431                if !vm && vd == VReg::V0 {
1432                    ::core::hint::cold_path();
1433                    return Err(ExecutionError::IllegalInstruction {
1434                        address: program_counter.old_pc(zvexx_helpers::INSTRUCTION_SIZE),
1435                    });
1436                }
1437                let sew = vtype.vsew();
1438                // SAFETY: alignment checked above
1439                unsafe {
1440                    zvexx_arith_helpers::execute_arith_op(
1441                        ext_state,
1442                        vd,
1443                        vs2,
1444                        zvexx_arith_helpers::OpSrc::Vreg(vs1),
1445                        vm,
1446                        sew,
1447                        |a, b, sew| {
1448                            if zvexx_arith_helpers::sign_extend(a, sew)
1449                                <= zvexx_arith_helpers::sign_extend(b, sew)
1450                            {
1451                                a
1452                            } else {
1453                                b
1454                            }
1455                        },
1456                    );
1457                }
1458            }
1459            Self::VminVx {
1460                vd,
1461                vs2,
1462                rs1: _,
1463                vm,
1464            } => {
1465                if !ext_state.vector_instructions_allowed() {
1466                    ::core::hint::cold_path();
1467                    return Err(ExecutionError::IllegalInstruction {
1468                        address: program_counter.old_pc(zvexx_helpers::INSTRUCTION_SIZE),
1469                    });
1470                }
1471                let Some(vtype) = ext_state.vtype() else {
1472                    ::core::hint::cold_path();
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                zvexx_arith_helpers::check_vreg_group_alignment::<Reg, _, _, _>(
1479                    program_counter,
1480                    vd,
1481                    group_regs,
1482                )?;
1483                zvexx_arith_helpers::check_vreg_group_alignment::<Reg, _, _, _>(
1484                    program_counter,
1485                    vs2,
1486                    group_regs,
1487                )?;
1488                if !vm && vd == VReg::V0 {
1489                    ::core::hint::cold_path();
1490                    return Err(ExecutionError::IllegalInstruction {
1491                        address: program_counter.old_pc(zvexx_helpers::INSTRUCTION_SIZE),
1492                    });
1493                }
1494                let sew = vtype.vsew();
1495                let scalar = rs1_value.as_i64().cast_unsigned();
1496                // SAFETY: alignment checked above
1497                unsafe {
1498                    zvexx_arith_helpers::execute_arith_op(
1499                        ext_state,
1500                        vd,
1501                        vs2,
1502                        zvexx_arith_helpers::OpSrc::Scalar(scalar),
1503                        vm,
1504                        sew,
1505                        |a, b, sew| {
1506                            if zvexx_arith_helpers::sign_extend(a, sew)
1507                                <= zvexx_arith_helpers::sign_extend(b, sew)
1508                            {
1509                                a
1510                            } else {
1511                                b
1512                            }
1513                        },
1514                    );
1515                }
1516            }
1517            // vmaxu / vmax
1518            Self::VmaxuVv { vd, vs2, vs1, vm } => {
1519                if !ext_state.vector_instructions_allowed() {
1520                    ::core::hint::cold_path();
1521                    return Err(ExecutionError::IllegalInstruction {
1522                        address: program_counter.old_pc(zvexx_helpers::INSTRUCTION_SIZE),
1523                    });
1524                }
1525                let Some(vtype) = ext_state.vtype() else {
1526                    ::core::hint::cold_path();
1527                    return Err(ExecutionError::IllegalInstruction {
1528                        address: program_counter.old_pc(zvexx_helpers::INSTRUCTION_SIZE),
1529                    });
1530                };
1531                let group_regs = vtype.vlmul().register_count();
1532                zvexx_arith_helpers::check_vreg_group_alignment::<Reg, _, _, _>(
1533                    program_counter,
1534                    vd,
1535                    group_regs,
1536                )?;
1537                zvexx_arith_helpers::check_vreg_group_alignment::<Reg, _, _, _>(
1538                    program_counter,
1539                    vs2,
1540                    group_regs,
1541                )?;
1542                zvexx_arith_helpers::check_vreg_group_alignment::<Reg, _, _, _>(
1543                    program_counter,
1544                    vs1,
1545                    group_regs,
1546                )?;
1547                if !vm && vd == VReg::V0 {
1548                    ::core::hint::cold_path();
1549                    return Err(ExecutionError::IllegalInstruction {
1550                        address: program_counter.old_pc(zvexx_helpers::INSTRUCTION_SIZE),
1551                    });
1552                }
1553                let sew = vtype.vsew();
1554                // SAFETY: alignment checked above
1555                unsafe {
1556                    zvexx_arith_helpers::execute_arith_op(
1557                        ext_state,
1558                        vd,
1559                        vs2,
1560                        zvexx_arith_helpers::OpSrc::Vreg(vs1),
1561                        vm,
1562                        sew,
1563                        |a, b, sew| {
1564                            let mask = zvexx_arith_helpers::sew_mask(sew);
1565                            if a & mask >= b & mask { a } else { b }
1566                        },
1567                    );
1568                }
1569            }
1570            Self::VmaxuVx {
1571                vd,
1572                vs2,
1573                rs1: _,
1574                vm,
1575            } => {
1576                if !ext_state.vector_instructions_allowed() {
1577                    ::core::hint::cold_path();
1578                    return Err(ExecutionError::IllegalInstruction {
1579                        address: program_counter.old_pc(zvexx_helpers::INSTRUCTION_SIZE),
1580                    });
1581                }
1582                let Some(vtype) = ext_state.vtype() else {
1583                    ::core::hint::cold_path();
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                zvexx_arith_helpers::check_vreg_group_alignment::<Reg, _, _, _>(
1590                    program_counter,
1591                    vd,
1592                    group_regs,
1593                )?;
1594                zvexx_arith_helpers::check_vreg_group_alignment::<Reg, _, _, _>(
1595                    program_counter,
1596                    vs2,
1597                    group_regs,
1598                )?;
1599                if !vm && vd == VReg::V0 {
1600                    ::core::hint::cold_path();
1601                    return Err(ExecutionError::IllegalInstruction {
1602                        address: program_counter.old_pc(zvexx_helpers::INSTRUCTION_SIZE),
1603                    });
1604                }
1605                let sew = vtype.vsew();
1606                let scalar = rs1_value.as_i64().cast_unsigned();
1607                // SAFETY: alignment checked above
1608                unsafe {
1609                    zvexx_arith_helpers::execute_arith_op(
1610                        ext_state,
1611                        vd,
1612                        vs2,
1613                        zvexx_arith_helpers::OpSrc::Scalar(scalar),
1614                        vm,
1615                        sew,
1616                        |a, b, sew| {
1617                            let mask = zvexx_arith_helpers::sew_mask(sew);
1618                            if a & mask >= b & mask { a } else { b }
1619                        },
1620                    );
1621                }
1622            }
1623            Self::VmaxVv { vd, vs2, vs1, vm } => {
1624                if !ext_state.vector_instructions_allowed() {
1625                    ::core::hint::cold_path();
1626                    return Err(ExecutionError::IllegalInstruction {
1627                        address: program_counter.old_pc(zvexx_helpers::INSTRUCTION_SIZE),
1628                    });
1629                }
1630                let Some(vtype) = ext_state.vtype() else {
1631                    ::core::hint::cold_path();
1632                    return Err(ExecutionError::IllegalInstruction {
1633                        address: program_counter.old_pc(zvexx_helpers::INSTRUCTION_SIZE),
1634                    });
1635                };
1636                let group_regs = vtype.vlmul().register_count();
1637                zvexx_arith_helpers::check_vreg_group_alignment::<Reg, _, _, _>(
1638                    program_counter,
1639                    vd,
1640                    group_regs,
1641                )?;
1642                zvexx_arith_helpers::check_vreg_group_alignment::<Reg, _, _, _>(
1643                    program_counter,
1644                    vs2,
1645                    group_regs,
1646                )?;
1647                zvexx_arith_helpers::check_vreg_group_alignment::<Reg, _, _, _>(
1648                    program_counter,
1649                    vs1,
1650                    group_regs,
1651                )?;
1652                if !vm && vd == VReg::V0 {
1653                    ::core::hint::cold_path();
1654                    return Err(ExecutionError::IllegalInstruction {
1655                        address: program_counter.old_pc(zvexx_helpers::INSTRUCTION_SIZE),
1656                    });
1657                }
1658                let sew = vtype.vsew();
1659                // SAFETY: alignment checked above
1660                unsafe {
1661                    zvexx_arith_helpers::execute_arith_op(
1662                        ext_state,
1663                        vd,
1664                        vs2,
1665                        zvexx_arith_helpers::OpSrc::Vreg(vs1),
1666                        vm,
1667                        sew,
1668                        |a, b, sew| {
1669                            if zvexx_arith_helpers::sign_extend(a, sew)
1670                                >= zvexx_arith_helpers::sign_extend(b, sew)
1671                            {
1672                                a
1673                            } else {
1674                                b
1675                            }
1676                        },
1677                    );
1678                }
1679            }
1680            Self::VmaxVx {
1681                vd,
1682                vs2,
1683                rs1: _,
1684                vm,
1685            } => {
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 group_regs = vtype.vlmul().register_count();
1699                zvexx_arith_helpers::check_vreg_group_alignment::<Reg, _, _, _>(
1700                    program_counter,
1701                    vd,
1702                    group_regs,
1703                )?;
1704                zvexx_arith_helpers::check_vreg_group_alignment::<Reg, _, _, _>(
1705                    program_counter,
1706                    vs2,
1707                    group_regs,
1708                )?;
1709                if !vm && vd == VReg::V0 {
1710                    ::core::hint::cold_path();
1711                    return Err(ExecutionError::IllegalInstruction {
1712                        address: program_counter.old_pc(zvexx_helpers::INSTRUCTION_SIZE),
1713                    });
1714                }
1715                let sew = vtype.vsew();
1716                let scalar = rs1_value.as_i64().cast_unsigned();
1717                // SAFETY: alignment checked above
1718                unsafe {
1719                    zvexx_arith_helpers::execute_arith_op(
1720                        ext_state,
1721                        vd,
1722                        vs2,
1723                        zvexx_arith_helpers::OpSrc::Scalar(scalar),
1724                        vm,
1725                        sew,
1726                        |a, b, sew| {
1727                            if zvexx_arith_helpers::sign_extend(a, sew)
1728                                >= zvexx_arith_helpers::sign_extend(b, sew)
1729                            {
1730                                a
1731                            } else {
1732                                b
1733                            }
1734                        },
1735                    );
1736                }
1737            }
1738            // vmseq
1739            Self::VmseqVv { vd, vs2, vs1, vm } => {
1740                if !ext_state.vector_instructions_allowed() {
1741                    ::core::hint::cold_path();
1742                    return Err(ExecutionError::IllegalInstruction {
1743                        address: program_counter.old_pc(zvexx_helpers::INSTRUCTION_SIZE),
1744                    });
1745                }
1746                let Some(vtype) = ext_state.vtype() else {
1747                    ::core::hint::cold_path();
1748                    return Err(ExecutionError::IllegalInstruction {
1749                        address: program_counter.old_pc(zvexx_helpers::INSTRUCTION_SIZE),
1750                    });
1751                };
1752                let group_regs = vtype.vlmul().register_count();
1753                zvexx_arith_helpers::check_vreg_group_alignment::<Reg, _, _, _>(
1754                    program_counter,
1755                    vs2,
1756                    group_regs,
1757                )?;
1758                zvexx_arith_helpers::check_vreg_group_alignment::<Reg, _, _, _>(
1759                    program_counter,
1760                    vs1,
1761                    group_regs,
1762                )?;
1763                zvexx_arith_helpers::check_mask_dest_no_overlap::<Reg, _, _, _>(
1764                    program_counter,
1765                    vd,
1766                    vs2,
1767                    group_regs,
1768                )?;
1769                zvexx_arith_helpers::check_mask_dest_no_overlap::<Reg, _, _, _>(
1770                    program_counter,
1771                    vd,
1772                    vs1,
1773                    group_regs,
1774                )?;
1775                let sew = vtype.vsew();
1776                // SAFETY: `vs2` and `vs1` alignment checked; `vd` is a single mask register,
1777                // no alignment constraint; `vl <= VLMAX <= VLEN` so all element indices fit
1778                // within the mask register. Mask-dest overlap rule (ยง11.8) checked above.
1779                unsafe {
1780                    zvexx_arith_helpers::execute_compare_op(
1781                        ext_state,
1782                        vd,
1783                        vs2,
1784                        zvexx_arith_helpers::OpSrc::Vreg(vs1),
1785                        vm,
1786                        sew,
1787                        |a, b, sew| {
1788                            (a & zvexx_arith_helpers::sew_mask(sew))
1789                                == (b & zvexx_arith_helpers::sew_mask(sew))
1790                        },
1791                    );
1792                }
1793            }
1794            Self::VmseqVx {
1795                vd,
1796                vs2,
1797                rs1: _,
1798                vm,
1799            } => {
1800                if !ext_state.vector_instructions_allowed() {
1801                    ::core::hint::cold_path();
1802                    return Err(ExecutionError::IllegalInstruction {
1803                        address: program_counter.old_pc(zvexx_helpers::INSTRUCTION_SIZE),
1804                    });
1805                }
1806                let Some(vtype) = ext_state.vtype() else {
1807                    ::core::hint::cold_path();
1808                    return Err(ExecutionError::IllegalInstruction {
1809                        address: program_counter.old_pc(zvexx_helpers::INSTRUCTION_SIZE),
1810                    });
1811                };
1812                let group_regs = vtype.vlmul().register_count();
1813                zvexx_arith_helpers::check_vreg_group_alignment::<Reg, _, _, _>(
1814                    program_counter,
1815                    vs2,
1816                    group_regs,
1817                )?;
1818                zvexx_arith_helpers::check_mask_dest_no_overlap::<Reg, _, _, _>(
1819                    program_counter,
1820                    vd,
1821                    vs2,
1822                    group_regs,
1823                )?;
1824                let sew = vtype.vsew();
1825                let scalar = rs1_value.as_i64().cast_unsigned();
1826                // SAFETY: see `VmseqVv`
1827                unsafe {
1828                    zvexx_arith_helpers::execute_compare_op(
1829                        ext_state,
1830                        vd,
1831                        vs2,
1832                        zvexx_arith_helpers::OpSrc::Scalar(scalar),
1833                        vm,
1834                        sew,
1835                        |a, b, sew| {
1836                            (a & zvexx_arith_helpers::sew_mask(sew))
1837                                == (b & zvexx_arith_helpers::sew_mask(sew))
1838                        },
1839                    );
1840                }
1841            }
1842            Self::VmseqVi { vd, vs2, imm, vm } => {
1843                if !ext_state.vector_instructions_allowed() {
1844                    ::core::hint::cold_path();
1845                    return Err(ExecutionError::IllegalInstruction {
1846                        address: program_counter.old_pc(zvexx_helpers::INSTRUCTION_SIZE),
1847                    });
1848                }
1849                let Some(vtype) = ext_state.vtype() else {
1850                    ::core::hint::cold_path();
1851                    return Err(ExecutionError::IllegalInstruction {
1852                        address: program_counter.old_pc(zvexx_helpers::INSTRUCTION_SIZE),
1853                    });
1854                };
1855                let group_regs = vtype.vlmul().register_count();
1856                zvexx_arith_helpers::check_vreg_group_alignment::<Reg, _, _, _>(
1857                    program_counter,
1858                    vs2,
1859                    group_regs,
1860                )?;
1861                zvexx_arith_helpers::check_mask_dest_no_overlap::<Reg, _, _, _>(
1862                    program_counter,
1863                    vd,
1864                    vs2,
1865                    group_regs,
1866                )?;
1867                let sew = vtype.vsew();
1868                let scalar = i64::from(imm).cast_unsigned();
1869                // SAFETY: see `VmseqVv`
1870                unsafe {
1871                    zvexx_arith_helpers::execute_compare_op(
1872                        ext_state,
1873                        vd,
1874                        vs2,
1875                        zvexx_arith_helpers::OpSrc::Scalar(scalar),
1876                        vm,
1877                        sew,
1878                        |a, b, sew| {
1879                            (a & zvexx_arith_helpers::sew_mask(sew))
1880                                == (b & zvexx_arith_helpers::sew_mask(sew))
1881                        },
1882                    );
1883                }
1884            }
1885            // vmsne
1886            Self::VmsneVv { vd, vs2, vs1, vm } => {
1887                if !ext_state.vector_instructions_allowed() {
1888                    ::core::hint::cold_path();
1889                    return Err(ExecutionError::IllegalInstruction {
1890                        address: program_counter.old_pc(zvexx_helpers::INSTRUCTION_SIZE),
1891                    });
1892                }
1893                let Some(vtype) = ext_state.vtype() else {
1894                    ::core::hint::cold_path();
1895                    return Err(ExecutionError::IllegalInstruction {
1896                        address: program_counter.old_pc(zvexx_helpers::INSTRUCTION_SIZE),
1897                    });
1898                };
1899                let group_regs = vtype.vlmul().register_count();
1900                zvexx_arith_helpers::check_vreg_group_alignment::<Reg, _, _, _>(
1901                    program_counter,
1902                    vs2,
1903                    group_regs,
1904                )?;
1905                zvexx_arith_helpers::check_vreg_group_alignment::<Reg, _, _, _>(
1906                    program_counter,
1907                    vs1,
1908                    group_regs,
1909                )?;
1910                zvexx_arith_helpers::check_mask_dest_no_overlap::<Reg, _, _, _>(
1911                    program_counter,
1912                    vd,
1913                    vs2,
1914                    group_regs,
1915                )?;
1916                zvexx_arith_helpers::check_mask_dest_no_overlap::<Reg, _, _, _>(
1917                    program_counter,
1918                    vd,
1919                    vs1,
1920                    group_regs,
1921                )?;
1922                let sew = vtype.vsew();
1923                // SAFETY: see `VmseqVv`
1924                unsafe {
1925                    zvexx_arith_helpers::execute_compare_op(
1926                        ext_state,
1927                        vd,
1928                        vs2,
1929                        zvexx_arith_helpers::OpSrc::Vreg(vs1),
1930                        vm,
1931                        sew,
1932                        |a, b, sew| {
1933                            (a & zvexx_arith_helpers::sew_mask(sew))
1934                                != (b & zvexx_arith_helpers::sew_mask(sew))
1935                        },
1936                    );
1937                }
1938            }
1939            Self::VmsneVx {
1940                vd,
1941                vs2,
1942                rs1: _,
1943                vm,
1944            } => {
1945                if !ext_state.vector_instructions_allowed() {
1946                    ::core::hint::cold_path();
1947                    return Err(ExecutionError::IllegalInstruction {
1948                        address: program_counter.old_pc(zvexx_helpers::INSTRUCTION_SIZE),
1949                    });
1950                }
1951                let Some(vtype) = ext_state.vtype() else {
1952                    ::core::hint::cold_path();
1953                    return Err(ExecutionError::IllegalInstruction {
1954                        address: program_counter.old_pc(zvexx_helpers::INSTRUCTION_SIZE),
1955                    });
1956                };
1957                let group_regs = vtype.vlmul().register_count();
1958                zvexx_arith_helpers::check_vreg_group_alignment::<Reg, _, _, _>(
1959                    program_counter,
1960                    vs2,
1961                    group_regs,
1962                )?;
1963                zvexx_arith_helpers::check_mask_dest_no_overlap::<Reg, _, _, _>(
1964                    program_counter,
1965                    vd,
1966                    vs2,
1967                    group_regs,
1968                )?;
1969                let sew = vtype.vsew();
1970                let scalar = rs1_value.as_i64().cast_unsigned();
1971                // SAFETY: see `VmseqVv`
1972                unsafe {
1973                    zvexx_arith_helpers::execute_compare_op(
1974                        ext_state,
1975                        vd,
1976                        vs2,
1977                        zvexx_arith_helpers::OpSrc::Scalar(scalar),
1978                        vm,
1979                        sew,
1980                        |a, b, sew| {
1981                            (a & zvexx_arith_helpers::sew_mask(sew))
1982                                != (b & zvexx_arith_helpers::sew_mask(sew))
1983                        },
1984                    );
1985                }
1986            }
1987            Self::VmsneVi { vd, vs2, imm, vm } => {
1988                if !ext_state.vector_instructions_allowed() {
1989                    ::core::hint::cold_path();
1990                    return Err(ExecutionError::IllegalInstruction {
1991                        address: program_counter.old_pc(zvexx_helpers::INSTRUCTION_SIZE),
1992                    });
1993                }
1994                let Some(vtype) = ext_state.vtype() else {
1995                    ::core::hint::cold_path();
1996                    return Err(ExecutionError::IllegalInstruction {
1997                        address: program_counter.old_pc(zvexx_helpers::INSTRUCTION_SIZE),
1998                    });
1999                };
2000                let group_regs = vtype.vlmul().register_count();
2001                zvexx_arith_helpers::check_vreg_group_alignment::<Reg, _, _, _>(
2002                    program_counter,
2003                    vs2,
2004                    group_regs,
2005                )?;
2006                zvexx_arith_helpers::check_mask_dest_no_overlap::<Reg, _, _, _>(
2007                    program_counter,
2008                    vd,
2009                    vs2,
2010                    group_regs,
2011                )?;
2012                let sew = vtype.vsew();
2013                let scalar = i64::from(imm).cast_unsigned();
2014                // SAFETY: see `VmseqVv`
2015                unsafe {
2016                    zvexx_arith_helpers::execute_compare_op(
2017                        ext_state,
2018                        vd,
2019                        vs2,
2020                        zvexx_arith_helpers::OpSrc::Scalar(scalar),
2021                        vm,
2022                        sew,
2023                        |a, b, sew| {
2024                            (a & zvexx_arith_helpers::sew_mask(sew))
2025                                != (b & zvexx_arith_helpers::sew_mask(sew))
2026                        },
2027                    );
2028                }
2029            }
2030            // vmsltu (unsigned <)
2031            Self::VmsltuVv { vd, vs2, vs1, vm } => {
2032                if !ext_state.vector_instructions_allowed() {
2033                    ::core::hint::cold_path();
2034                    return Err(ExecutionError::IllegalInstruction {
2035                        address: program_counter.old_pc(zvexx_helpers::INSTRUCTION_SIZE),
2036                    });
2037                }
2038                let Some(vtype) = ext_state.vtype() else {
2039                    ::core::hint::cold_path();
2040                    return Err(ExecutionError::IllegalInstruction {
2041                        address: program_counter.old_pc(zvexx_helpers::INSTRUCTION_SIZE),
2042                    });
2043                };
2044                let group_regs = vtype.vlmul().register_count();
2045                zvexx_arith_helpers::check_vreg_group_alignment::<Reg, _, _, _>(
2046                    program_counter,
2047                    vs2,
2048                    group_regs,
2049                )?;
2050                zvexx_arith_helpers::check_vreg_group_alignment::<Reg, _, _, _>(
2051                    program_counter,
2052                    vs1,
2053                    group_regs,
2054                )?;
2055                zvexx_arith_helpers::check_mask_dest_no_overlap::<Reg, _, _, _>(
2056                    program_counter,
2057                    vd,
2058                    vs2,
2059                    group_regs,
2060                )?;
2061                zvexx_arith_helpers::check_mask_dest_no_overlap::<Reg, _, _, _>(
2062                    program_counter,
2063                    vd,
2064                    vs1,
2065                    group_regs,
2066                )?;
2067                let sew = vtype.vsew();
2068                // SAFETY: see `VmseqVv`
2069                unsafe {
2070                    zvexx_arith_helpers::execute_compare_op(
2071                        ext_state,
2072                        vd,
2073                        vs2,
2074                        zvexx_arith_helpers::OpSrc::Vreg(vs1),
2075                        vm,
2076                        sew,
2077                        |a, b, sew| {
2078                            (a & zvexx_arith_helpers::sew_mask(sew))
2079                                < (b & zvexx_arith_helpers::sew_mask(sew))
2080                        },
2081                    );
2082                }
2083            }
2084            Self::VmsltuVx {
2085                vd,
2086                vs2,
2087                rs1: _,
2088                vm,
2089            } => {
2090                if !ext_state.vector_instructions_allowed() {
2091                    ::core::hint::cold_path();
2092                    return Err(ExecutionError::IllegalInstruction {
2093                        address: program_counter.old_pc(zvexx_helpers::INSTRUCTION_SIZE),
2094                    });
2095                }
2096                let Some(vtype) = ext_state.vtype() else {
2097                    ::core::hint::cold_path();
2098                    return Err(ExecutionError::IllegalInstruction {
2099                        address: program_counter.old_pc(zvexx_helpers::INSTRUCTION_SIZE),
2100                    });
2101                };
2102                let group_regs = vtype.vlmul().register_count();
2103                zvexx_arith_helpers::check_vreg_group_alignment::<Reg, _, _, _>(
2104                    program_counter,
2105                    vs2,
2106                    group_regs,
2107                )?;
2108                zvexx_arith_helpers::check_mask_dest_no_overlap::<Reg, _, _, _>(
2109                    program_counter,
2110                    vd,
2111                    vs2,
2112                    group_regs,
2113                )?;
2114                let sew = vtype.vsew();
2115                let scalar = rs1_value.as_i64().cast_unsigned();
2116                // SAFETY: see `VmseqVv`
2117                unsafe {
2118                    zvexx_arith_helpers::execute_compare_op(
2119                        ext_state,
2120                        vd,
2121                        vs2,
2122                        zvexx_arith_helpers::OpSrc::Scalar(scalar),
2123                        vm,
2124                        sew,
2125                        |a, b, sew| {
2126                            (a & zvexx_arith_helpers::sew_mask(sew))
2127                                < (b & zvexx_arith_helpers::sew_mask(sew))
2128                        },
2129                    );
2130                }
2131            }
2132            // vmslt (signed <)
2133            Self::VmsltVv { vd, vs2, vs1, vm } => {
2134                if !ext_state.vector_instructions_allowed() {
2135                    ::core::hint::cold_path();
2136                    return Err(ExecutionError::IllegalInstruction {
2137                        address: program_counter.old_pc(zvexx_helpers::INSTRUCTION_SIZE),
2138                    });
2139                }
2140                let Some(vtype) = ext_state.vtype() else {
2141                    ::core::hint::cold_path();
2142                    return Err(ExecutionError::IllegalInstruction {
2143                        address: program_counter.old_pc(zvexx_helpers::INSTRUCTION_SIZE),
2144                    });
2145                };
2146                let group_regs = vtype.vlmul().register_count();
2147                zvexx_arith_helpers::check_vreg_group_alignment::<Reg, _, _, _>(
2148                    program_counter,
2149                    vs2,
2150                    group_regs,
2151                )?;
2152                zvexx_arith_helpers::check_vreg_group_alignment::<Reg, _, _, _>(
2153                    program_counter,
2154                    vs1,
2155                    group_regs,
2156                )?;
2157                zvexx_arith_helpers::check_mask_dest_no_overlap::<Reg, _, _, _>(
2158                    program_counter,
2159                    vd,
2160                    vs2,
2161                    group_regs,
2162                )?;
2163                zvexx_arith_helpers::check_mask_dest_no_overlap::<Reg, _, _, _>(
2164                    program_counter,
2165                    vd,
2166                    vs1,
2167                    group_regs,
2168                )?;
2169                let sew = vtype.vsew();
2170                // SAFETY: see `VmseqVv`
2171                unsafe {
2172                    zvexx_arith_helpers::execute_compare_op(
2173                        ext_state,
2174                        vd,
2175                        vs2,
2176                        zvexx_arith_helpers::OpSrc::Vreg(vs1),
2177                        vm,
2178                        sew,
2179                        |a, b, sew| {
2180                            zvexx_arith_helpers::sign_extend(a, sew)
2181                                < zvexx_arith_helpers::sign_extend(b, sew)
2182                        },
2183                    );
2184                }
2185            }
2186            Self::VmsltVx {
2187                vd,
2188                vs2,
2189                rs1: _,
2190                vm,
2191            } => {
2192                if !ext_state.vector_instructions_allowed() {
2193                    ::core::hint::cold_path();
2194                    return Err(ExecutionError::IllegalInstruction {
2195                        address: program_counter.old_pc(zvexx_helpers::INSTRUCTION_SIZE),
2196                    });
2197                }
2198                let Some(vtype) = ext_state.vtype() else {
2199                    ::core::hint::cold_path();
2200                    return Err(ExecutionError::IllegalInstruction {
2201                        address: program_counter.old_pc(zvexx_helpers::INSTRUCTION_SIZE),
2202                    });
2203                };
2204                let group_regs = vtype.vlmul().register_count();
2205                zvexx_arith_helpers::check_vreg_group_alignment::<Reg, _, _, _>(
2206                    program_counter,
2207                    vs2,
2208                    group_regs,
2209                )?;
2210                zvexx_arith_helpers::check_mask_dest_no_overlap::<Reg, _, _, _>(
2211                    program_counter,
2212                    vd,
2213                    vs2,
2214                    group_regs,
2215                )?;
2216                let sew = vtype.vsew();
2217                let scalar = rs1_value.as_i64().cast_unsigned();
2218                // SAFETY: see `VmseqVv`
2219                unsafe {
2220                    zvexx_arith_helpers::execute_compare_op(
2221                        ext_state,
2222                        vd,
2223                        vs2,
2224                        zvexx_arith_helpers::OpSrc::Scalar(scalar),
2225                        vm,
2226                        sew,
2227                        |a, b, sew| {
2228                            zvexx_arith_helpers::sign_extend(a, sew)
2229                                < zvexx_arith_helpers::sign_extend(b, sew)
2230                        },
2231                    );
2232                }
2233            }
2234            // vmsleu (unsigned <=)
2235            Self::VmsleuVv { vd, vs2, vs1, vm } => {
2236                if !ext_state.vector_instructions_allowed() {
2237                    ::core::hint::cold_path();
2238                    return Err(ExecutionError::IllegalInstruction {
2239                        address: program_counter.old_pc(zvexx_helpers::INSTRUCTION_SIZE),
2240                    });
2241                }
2242                let Some(vtype) = ext_state.vtype() else {
2243                    ::core::hint::cold_path();
2244                    return Err(ExecutionError::IllegalInstruction {
2245                        address: program_counter.old_pc(zvexx_helpers::INSTRUCTION_SIZE),
2246                    });
2247                };
2248                let group_regs = vtype.vlmul().register_count();
2249                zvexx_arith_helpers::check_vreg_group_alignment::<Reg, _, _, _>(
2250                    program_counter,
2251                    vs2,
2252                    group_regs,
2253                )?;
2254                zvexx_arith_helpers::check_vreg_group_alignment::<Reg, _, _, _>(
2255                    program_counter,
2256                    vs1,
2257                    group_regs,
2258                )?;
2259                zvexx_arith_helpers::check_mask_dest_no_overlap::<Reg, _, _, _>(
2260                    program_counter,
2261                    vd,
2262                    vs2,
2263                    group_regs,
2264                )?;
2265                zvexx_arith_helpers::check_mask_dest_no_overlap::<Reg, _, _, _>(
2266                    program_counter,
2267                    vd,
2268                    vs1,
2269                    group_regs,
2270                )?;
2271                let sew = vtype.vsew();
2272                // SAFETY: see `VmseqVv`
2273                unsafe {
2274                    zvexx_arith_helpers::execute_compare_op(
2275                        ext_state,
2276                        vd,
2277                        vs2,
2278                        zvexx_arith_helpers::OpSrc::Vreg(vs1),
2279                        vm,
2280                        sew,
2281                        |a, b, sew| {
2282                            (a & zvexx_arith_helpers::sew_mask(sew))
2283                                <= (b & zvexx_arith_helpers::sew_mask(sew))
2284                        },
2285                    );
2286                }
2287            }
2288            Self::VmsleuVx {
2289                vd,
2290                vs2,
2291                rs1: _,
2292                vm,
2293            } => {
2294                if !ext_state.vector_instructions_allowed() {
2295                    ::core::hint::cold_path();
2296                    return Err(ExecutionError::IllegalInstruction {
2297                        address: program_counter.old_pc(zvexx_helpers::INSTRUCTION_SIZE),
2298                    });
2299                }
2300                let Some(vtype) = ext_state.vtype() else {
2301                    ::core::hint::cold_path();
2302                    return Err(ExecutionError::IllegalInstruction {
2303                        address: program_counter.old_pc(zvexx_helpers::INSTRUCTION_SIZE),
2304                    });
2305                };
2306                let group_regs = vtype.vlmul().register_count();
2307                zvexx_arith_helpers::check_vreg_group_alignment::<Reg, _, _, _>(
2308                    program_counter,
2309                    vs2,
2310                    group_regs,
2311                )?;
2312                zvexx_arith_helpers::check_mask_dest_no_overlap::<Reg, _, _, _>(
2313                    program_counter,
2314                    vd,
2315                    vs2,
2316                    group_regs,
2317                )?;
2318                let sew = vtype.vsew();
2319                let scalar = rs1_value.as_i64().cast_unsigned();
2320                // SAFETY: see `VmseqVv`
2321                unsafe {
2322                    zvexx_arith_helpers::execute_compare_op(
2323                        ext_state,
2324                        vd,
2325                        vs2,
2326                        zvexx_arith_helpers::OpSrc::Scalar(scalar),
2327                        vm,
2328                        sew,
2329                        |a, b, sew| {
2330                            (a & zvexx_arith_helpers::sew_mask(sew))
2331                                <= (b & zvexx_arith_helpers::sew_mask(sew))
2332                        },
2333                    );
2334                }
2335            }
2336            Self::VmsleuVi { vd, vs2, imm, vm } => {
2337                if !ext_state.vector_instructions_allowed() {
2338                    ::core::hint::cold_path();
2339                    return Err(ExecutionError::IllegalInstruction {
2340                        address: program_counter.old_pc(zvexx_helpers::INSTRUCTION_SIZE),
2341                    });
2342                }
2343                let Some(vtype) = ext_state.vtype() else {
2344                    ::core::hint::cold_path();
2345                    return Err(ExecutionError::IllegalInstruction {
2346                        address: program_counter.old_pc(zvexx_helpers::INSTRUCTION_SIZE),
2347                    });
2348                };
2349                let group_regs = vtype.vlmul().register_count();
2350                zvexx_arith_helpers::check_vreg_group_alignment::<Reg, _, _, _>(
2351                    program_counter,
2352                    vs2,
2353                    group_regs,
2354                )?;
2355                zvexx_arith_helpers::check_mask_dest_no_overlap::<Reg, _, _, _>(
2356                    program_counter,
2357                    vd,
2358                    vs2,
2359                    group_regs,
2360                )?;
2361                let sew = vtype.vsew();
2362                // Per spec ยง12.8: for vmsleu.vi, the immediate is sign-extended to XLEN
2363                // then the comparison is unsigned. A negative i8 immediate sign-extends to
2364                // a large u64 (e.g. -1 -> 0xFFFF...FF). Both operands are masked to SEW
2365                // before comparing, so the effective immediate is (0xFFFF...FF &
2366                // zve64x_arith_helpers::sew_mask), which equals
2367                // zve64x_arith_helpers::sew_mask (the maximum SEW-wide unsigned value). This means
2368                // vs2[i] <= imm is always true for SEW < XLEN when imm < 0.
2369                let scalar = i64::from(imm).cast_unsigned();
2370                // SAFETY: see `VmseqVv`
2371                unsafe {
2372                    zvexx_arith_helpers::execute_compare_op(
2373                        ext_state,
2374                        vd,
2375                        vs2,
2376                        zvexx_arith_helpers::OpSrc::Scalar(scalar),
2377                        vm,
2378                        sew,
2379                        |a, b, sew| {
2380                            (a & zvexx_arith_helpers::sew_mask(sew))
2381                                <= (b & zvexx_arith_helpers::sew_mask(sew))
2382                        },
2383                    );
2384                }
2385            }
2386            // vmsle (signed <=)
2387            Self::VmsleVv { vd, vs2, vs1, vm } => {
2388                if !ext_state.vector_instructions_allowed() {
2389                    ::core::hint::cold_path();
2390                    return Err(ExecutionError::IllegalInstruction {
2391                        address: program_counter.old_pc(zvexx_helpers::INSTRUCTION_SIZE),
2392                    });
2393                }
2394                let Some(vtype) = ext_state.vtype() else {
2395                    ::core::hint::cold_path();
2396                    return Err(ExecutionError::IllegalInstruction {
2397                        address: program_counter.old_pc(zvexx_helpers::INSTRUCTION_SIZE),
2398                    });
2399                };
2400                let group_regs = vtype.vlmul().register_count();
2401                zvexx_arith_helpers::check_vreg_group_alignment::<Reg, _, _, _>(
2402                    program_counter,
2403                    vs2,
2404                    group_regs,
2405                )?;
2406                zvexx_arith_helpers::check_vreg_group_alignment::<Reg, _, _, _>(
2407                    program_counter,
2408                    vs1,
2409                    group_regs,
2410                )?;
2411                zvexx_arith_helpers::check_mask_dest_no_overlap::<Reg, _, _, _>(
2412                    program_counter,
2413                    vd,
2414                    vs2,
2415                    group_regs,
2416                )?;
2417                zvexx_arith_helpers::check_mask_dest_no_overlap::<Reg, _, _, _>(
2418                    program_counter,
2419                    vd,
2420                    vs1,
2421                    group_regs,
2422                )?;
2423                let sew = vtype.vsew();
2424                // SAFETY: see `VmseqVv`
2425                unsafe {
2426                    zvexx_arith_helpers::execute_compare_op(
2427                        ext_state,
2428                        vd,
2429                        vs2,
2430                        zvexx_arith_helpers::OpSrc::Vreg(vs1),
2431                        vm,
2432                        sew,
2433                        |a, b, sew| {
2434                            zvexx_arith_helpers::sign_extend(a, sew)
2435                                <= zvexx_arith_helpers::sign_extend(b, sew)
2436                        },
2437                    );
2438                }
2439            }
2440            Self::VmsleVx {
2441                vd,
2442                vs2,
2443                rs1: _,
2444                vm,
2445            } => {
2446                if !ext_state.vector_instructions_allowed() {
2447                    ::core::hint::cold_path();
2448                    return Err(ExecutionError::IllegalInstruction {
2449                        address: program_counter.old_pc(zvexx_helpers::INSTRUCTION_SIZE),
2450                    });
2451                }
2452                let Some(vtype) = ext_state.vtype() else {
2453                    ::core::hint::cold_path();
2454                    return Err(ExecutionError::IllegalInstruction {
2455                        address: program_counter.old_pc(zvexx_helpers::INSTRUCTION_SIZE),
2456                    });
2457                };
2458                let group_regs = vtype.vlmul().register_count();
2459                zvexx_arith_helpers::check_vreg_group_alignment::<Reg, _, _, _>(
2460                    program_counter,
2461                    vs2,
2462                    group_regs,
2463                )?;
2464                zvexx_arith_helpers::check_mask_dest_no_overlap::<Reg, _, _, _>(
2465                    program_counter,
2466                    vd,
2467                    vs2,
2468                    group_regs,
2469                )?;
2470                let sew = vtype.vsew();
2471                let scalar = rs1_value.as_i64().cast_unsigned();
2472                // SAFETY: see `VmseqVv`
2473                unsafe {
2474                    zvexx_arith_helpers::execute_compare_op(
2475                        ext_state,
2476                        vd,
2477                        vs2,
2478                        zvexx_arith_helpers::OpSrc::Scalar(scalar),
2479                        vm,
2480                        sew,
2481                        |a, b, sew| {
2482                            zvexx_arith_helpers::sign_extend(a, sew)
2483                                <= zvexx_arith_helpers::sign_extend(b, sew)
2484                        },
2485                    );
2486                }
2487            }
2488            Self::VmsleVi { vd, vs2, imm, vm } => {
2489                if !ext_state.vector_instructions_allowed() {
2490                    ::core::hint::cold_path();
2491                    return Err(ExecutionError::IllegalInstruction {
2492                        address: program_counter.old_pc(zvexx_helpers::INSTRUCTION_SIZE),
2493                    });
2494                }
2495                let Some(vtype) = ext_state.vtype() else {
2496                    ::core::hint::cold_path();
2497                    return Err(ExecutionError::IllegalInstruction {
2498                        address: program_counter.old_pc(zvexx_helpers::INSTRUCTION_SIZE),
2499                    });
2500                };
2501                let group_regs = vtype.vlmul().register_count();
2502                zvexx_arith_helpers::check_vreg_group_alignment::<Reg, _, _, _>(
2503                    program_counter,
2504                    vs2,
2505                    group_regs,
2506                )?;
2507                zvexx_arith_helpers::check_mask_dest_no_overlap::<Reg, _, _, _>(
2508                    program_counter,
2509                    vd,
2510                    vs2,
2511                    group_regs,
2512                )?;
2513                let sew = vtype.vsew();
2514                let scalar = i64::from(imm).cast_unsigned();
2515                // SAFETY: see `VmseqVv`
2516                unsafe {
2517                    zvexx_arith_helpers::execute_compare_op(
2518                        ext_state,
2519                        vd,
2520                        vs2,
2521                        zvexx_arith_helpers::OpSrc::Scalar(scalar),
2522                        vm,
2523                        sew,
2524                        |a, b, sew| {
2525                            zvexx_arith_helpers::sign_extend(a, sew)
2526                                <= zvexx_arith_helpers::sign_extend(b, sew)
2527                        },
2528                    );
2529                }
2530            }
2531            // vmsgtu (unsigned >): no vv form; vx and vi only
2532            Self::VmsgtuVx {
2533                vd,
2534                vs2,
2535                rs1: _,
2536                vm,
2537            } => {
2538                if !ext_state.vector_instructions_allowed() {
2539                    ::core::hint::cold_path();
2540                    return Err(ExecutionError::IllegalInstruction {
2541                        address: program_counter.old_pc(zvexx_helpers::INSTRUCTION_SIZE),
2542                    });
2543                }
2544                let Some(vtype) = ext_state.vtype() else {
2545                    ::core::hint::cold_path();
2546                    return Err(ExecutionError::IllegalInstruction {
2547                        address: program_counter.old_pc(zvexx_helpers::INSTRUCTION_SIZE),
2548                    });
2549                };
2550                let group_regs = vtype.vlmul().register_count();
2551                zvexx_arith_helpers::check_vreg_group_alignment::<Reg, _, _, _>(
2552                    program_counter,
2553                    vs2,
2554                    group_regs,
2555                )?;
2556                zvexx_arith_helpers::check_mask_dest_no_overlap::<Reg, _, _, _>(
2557                    program_counter,
2558                    vd,
2559                    vs2,
2560                    group_regs,
2561                )?;
2562                let sew = vtype.vsew();
2563                let scalar = rs1_value.as_i64().cast_unsigned();
2564                // SAFETY: see `VmseqVv`
2565                unsafe {
2566                    zvexx_arith_helpers::execute_compare_op(
2567                        ext_state,
2568                        vd,
2569                        vs2,
2570                        zvexx_arith_helpers::OpSrc::Scalar(scalar),
2571                        vm,
2572                        sew,
2573                        |a, b, sew| {
2574                            (a & zvexx_arith_helpers::sew_mask(sew))
2575                                > (b & zvexx_arith_helpers::sew_mask(sew))
2576                        },
2577                    );
2578                }
2579            }
2580            Self::VmsgtuVi { vd, vs2, imm, vm } => {
2581                if !ext_state.vector_instructions_allowed() {
2582                    ::core::hint::cold_path();
2583                    return Err(ExecutionError::IllegalInstruction {
2584                        address: program_counter.old_pc(zvexx_helpers::INSTRUCTION_SIZE),
2585                    });
2586                }
2587                let Some(vtype) = ext_state.vtype() else {
2588                    ::core::hint::cold_path();
2589                    return Err(ExecutionError::IllegalInstruction {
2590                        address: program_counter.old_pc(zvexx_helpers::INSTRUCTION_SIZE),
2591                    });
2592                };
2593                let group_regs = vtype.vlmul().register_count();
2594                zvexx_arith_helpers::check_vreg_group_alignment::<Reg, _, _, _>(
2595                    program_counter,
2596                    vs2,
2597                    group_regs,
2598                )?;
2599                zvexx_arith_helpers::check_mask_dest_no_overlap::<Reg, _, _, _>(
2600                    program_counter,
2601                    vd,
2602                    vs2,
2603                    group_regs,
2604                )?;
2605                let sew = vtype.vsew();
2606                let scalar = i64::from(imm).cast_unsigned();
2607                // SAFETY: see `VmseqVv`
2608                unsafe {
2609                    zvexx_arith_helpers::execute_compare_op(
2610                        ext_state,
2611                        vd,
2612                        vs2,
2613                        zvexx_arith_helpers::OpSrc::Scalar(scalar),
2614                        vm,
2615                        sew,
2616                        |a, b, sew| {
2617                            (a & zvexx_arith_helpers::sew_mask(sew))
2618                                > (b & zvexx_arith_helpers::sew_mask(sew))
2619                        },
2620                    );
2621                }
2622            }
2623            // vmsgt (signed >): no vv form; vx and vi only
2624            Self::VmsgtVx {
2625                vd,
2626                vs2,
2627                rs1: _,
2628                vm,
2629            } => {
2630                if !ext_state.vector_instructions_allowed() {
2631                    ::core::hint::cold_path();
2632                    return Err(ExecutionError::IllegalInstruction {
2633                        address: program_counter.old_pc(zvexx_helpers::INSTRUCTION_SIZE),
2634                    });
2635                }
2636                let Some(vtype) = ext_state.vtype() else {
2637                    ::core::hint::cold_path();
2638                    return Err(ExecutionError::IllegalInstruction {
2639                        address: program_counter.old_pc(zvexx_helpers::INSTRUCTION_SIZE),
2640                    });
2641                };
2642                let group_regs = vtype.vlmul().register_count();
2643                zvexx_arith_helpers::check_vreg_group_alignment::<Reg, _, _, _>(
2644                    program_counter,
2645                    vs2,
2646                    group_regs,
2647                )?;
2648                zvexx_arith_helpers::check_mask_dest_no_overlap::<Reg, _, _, _>(
2649                    program_counter,
2650                    vd,
2651                    vs2,
2652                    group_regs,
2653                )?;
2654                let sew = vtype.vsew();
2655                let scalar = rs1_value.as_i64().cast_unsigned();
2656                // SAFETY: see `VmseqVv`
2657                unsafe {
2658                    zvexx_arith_helpers::execute_compare_op(
2659                        ext_state,
2660                        vd,
2661                        vs2,
2662                        zvexx_arith_helpers::OpSrc::Scalar(scalar),
2663                        vm,
2664                        sew,
2665                        |a, b, sew| {
2666                            zvexx_arith_helpers::sign_extend(a, sew)
2667                                > zvexx_arith_helpers::sign_extend(b, sew)
2668                        },
2669                    );
2670                }
2671            }
2672            Self::VmsgtVi { vd, vs2, imm, vm } => {
2673                if !ext_state.vector_instructions_allowed() {
2674                    ::core::hint::cold_path();
2675                    return Err(ExecutionError::IllegalInstruction {
2676                        address: program_counter.old_pc(zvexx_helpers::INSTRUCTION_SIZE),
2677                    });
2678                }
2679                let Some(vtype) = ext_state.vtype() else {
2680                    ::core::hint::cold_path();
2681                    return Err(ExecutionError::IllegalInstruction {
2682                        address: program_counter.old_pc(zvexx_helpers::INSTRUCTION_SIZE),
2683                    });
2684                };
2685                let group_regs = vtype.vlmul().register_count();
2686                zvexx_arith_helpers::check_vreg_group_alignment::<Reg, _, _, _>(
2687                    program_counter,
2688                    vs2,
2689                    group_regs,
2690                )?;
2691                zvexx_arith_helpers::check_mask_dest_no_overlap::<Reg, _, _, _>(
2692                    program_counter,
2693                    vd,
2694                    vs2,
2695                    group_regs,
2696                )?;
2697                let sew = vtype.vsew();
2698                let scalar = i64::from(imm).cast_unsigned();
2699                // SAFETY: see `VmseqVv`
2700                unsafe {
2701                    zvexx_arith_helpers::execute_compare_op(
2702                        ext_state,
2703                        vd,
2704                        vs2,
2705                        zvexx_arith_helpers::OpSrc::Scalar(scalar),
2706                        vm,
2707                        sew,
2708                        |a, b, sew| {
2709                            zvexx_arith_helpers::sign_extend(a, sew)
2710                                > zvexx_arith_helpers::sign_extend(b, sew)
2711                        },
2712                    );
2713                }
2714            }
2715        }
2716
2717        Ok(ControlFlow::Continue(Default::default()))
2718    }
2719}