Skip to main content

ab_riscv_interpreter/v/zve64x/
arith.rs

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