Skip to main content

ab_riscv_interpreter/v/zvexx/
carry.rs

1//! ZveXx carry/borrow arithmetic instructions
2
3#[cfg(test)]
4mod tests;
5pub mod zvexx_carry_helpers;
6
7use crate::v::vector_registers::VectorRegistersExt;
8use crate::v::zvexx::zvexx_helpers;
9use crate::{
10    ExecutableInstruction, ExecutableInstructionCsr, ExecutableInstructionOperands, ExecutionError,
11    ExecutionResult, FetchInstructionResult, InstructionFetcher, OpaqueThreadedExecutionResult,
12    PackedAddress, ProgramCounter, RegisterFile, Rs1Rs2OperandValues, Rs1Rs2Operands,
13    ThreadedExecutableInstruction, ThreadedExecutionResult, VirtualMemory,
14};
15use ab_riscv_macros::instruction_execution;
16use ab_riscv_primitives::prelude::*;
17
18#[instruction_execution]
19const impl<Reg, Hart> ExecutableInstructionOperands for ZveXxCarryInstruction<Hart>
20where
21    Reg: Register,
22    Hart: VectorHartConfig<Reg = Reg>,
23{
24}
25
26#[instruction_execution]
27const impl<Reg, Hart, Env> ExecutableInstructionCsr<Env> for ZveXxCarryInstruction<Hart>
28where
29    Reg: Register,
30    Hart: VectorHartConfig<Reg = Reg>,
31{
32}
33
34#[instruction_execution]
35impl<Reg, Hart, Regs, Env, Memory, PC> ExecutableInstruction<Regs, Env, Memory, PC>
36    for ZveXxCarryInstruction<Hart>
37where
38    Reg: Register,
39    Hart: VectorHartConfig<Reg = Reg>,
40    Regs: RegisterFile<Reg>,
41    Env: VectorRegistersExt<Hart = Hart>,
42    Memory: VirtualMemory,
43    PC: ProgramCounter<Reg::Type, Memory>,
44{
45    #[inline(always)]
46    #[cfg_attr(feature = "no-panic", no_panic_const::no_panic)]
47    fn execute(
48        self,
49        Rs1Rs2OperandValues {
50            rs1_value,
51            rs2_value: _,
52        }: Rs1Rs2OperandValues<Reg::Type>,
53        _regs: &mut Regs,
54        env: &mut Env,
55        _memory: &mut Memory,
56        program_counter: &PC,
57    ) -> ExecutionResult<Reg> {
58        match self {
59            // vadc: add with carry-in from v0, data result
60            Self::VadcVvm { vd, vs2, vs1 } => {
61                if !zvexx_helpers::non_memory_instruction_allowed::<Reg, _>(env) {
62                    ::core::hint::cold_path();
63                    return ExecutionResult::Err(ExecutionError::IllegalInstruction {
64                        address: PackedAddress::new(
65                            program_counter.old_pc(zvexx_helpers::INSTRUCTION_SIZE),
66                        ),
67                    });
68                }
69                let Some(config) = env.vector_config() else {
70                    ::core::hint::cold_path();
71                    return ExecutionResult::Err(ExecutionError::IllegalInstruction {
72                        address: PackedAddress::new(
73                            program_counter.old_pc(zvexx_helpers::INSTRUCTION_SIZE),
74                        ),
75                    });
76                };
77                let sew = config.vtype().vsew();
78                let vd = zvexx_helpers::vreg_group::<Reg, Env, _, _>(
79                    program_counter,
80                    config,
81                    vd,
82                    sew.as_eew(),
83                )?;
84                let vs2 = zvexx_helpers::vreg_group::<Reg, Env, _, _>(
85                    program_counter,
86                    config,
87                    vs2,
88                    sew.as_eew(),
89                )?;
90                let vs1 = zvexx_helpers::vreg_group::<Reg, Env, _, _>(
91                    program_counter,
92                    config,
93                    vs1,
94                    sew.as_eew(),
95                )?;
96                zvexx_carry_helpers::execute_carry_add::<true, Reg, _>(
97                    env,
98                    vd,
99                    vs2,
100                    zvexx_carry_helpers::OpSrc::Vreg(vs1),
101                );
102            }
103
104            Self::VadcVxm { vd, vs2, rs1: _ } => {
105                if !zvexx_helpers::non_memory_instruction_allowed::<Reg, _>(env) {
106                    ::core::hint::cold_path();
107                    return ExecutionResult::Err(ExecutionError::IllegalInstruction {
108                        address: PackedAddress::new(
109                            program_counter.old_pc(zvexx_helpers::INSTRUCTION_SIZE),
110                        ),
111                    });
112                }
113                let Some(config) = env.vector_config() else {
114                    ::core::hint::cold_path();
115                    return ExecutionResult::Err(ExecutionError::IllegalInstruction {
116                        address: PackedAddress::new(
117                            program_counter.old_pc(zvexx_helpers::INSTRUCTION_SIZE),
118                        ),
119                    });
120                };
121                let sew = config.vtype().vsew();
122                let vd = zvexx_helpers::vreg_group::<Reg, Env, _, _>(
123                    program_counter,
124                    config,
125                    vd,
126                    sew.as_eew(),
127                )?;
128                let vs2 = zvexx_helpers::vreg_group::<Reg, Env, _, _>(
129                    program_counter,
130                    config,
131                    vs2,
132                    sew.as_eew(),
133                )?;
134                let scalar = rs1_value.as_i64().cast_unsigned();
135                zvexx_carry_helpers::execute_carry_add::<true, Reg, _>(
136                    env,
137                    vd,
138                    vs2,
139                    zvexx_carry_helpers::OpSrc::Scalar(scalar),
140                );
141            }
142
143            Self::VadcVim { vd, vs2, imm } => {
144                if !zvexx_helpers::non_memory_instruction_allowed::<Reg, _>(env) {
145                    ::core::hint::cold_path();
146                    return ExecutionResult::Err(ExecutionError::IllegalInstruction {
147                        address: PackedAddress::new(
148                            program_counter.old_pc(zvexx_helpers::INSTRUCTION_SIZE),
149                        ),
150                    });
151                }
152                let Some(config) = env.vector_config() else {
153                    ::core::hint::cold_path();
154                    return ExecutionResult::Err(ExecutionError::IllegalInstruction {
155                        address: PackedAddress::new(
156                            program_counter.old_pc(zvexx_helpers::INSTRUCTION_SIZE),
157                        ),
158                    });
159                };
160                let sew = config.vtype().vsew();
161                let vd = zvexx_helpers::vreg_group::<Reg, Env, _, _>(
162                    program_counter,
163                    config,
164                    vd,
165                    sew.as_eew(),
166                )?;
167                let vs2 = zvexx_helpers::vreg_group::<Reg, Env, _, _>(
168                    program_counter,
169                    config,
170                    vs2,
171                    sew.as_eew(),
172                )?;
173                let scalar = i64::from(imm).cast_unsigned();
174                zvexx_carry_helpers::execute_carry_add::<true, Reg, _>(
175                    env,
176                    vd,
177                    vs2,
178                    zvexx_carry_helpers::OpSrc::Scalar(scalar),
179                );
180            }
181
182            // vmadc: add and write carry-out mask
183            Self::VmadcVvm { vd, vs2, vs1 } => {
184                if !zvexx_helpers::non_memory_instruction_allowed::<Reg, _>(env) {
185                    ::core::hint::cold_path();
186                    return ExecutionResult::Err(ExecutionError::IllegalInstruction {
187                        address: PackedAddress::new(
188                            program_counter.old_pc(zvexx_helpers::INSTRUCTION_SIZE),
189                        ),
190                    });
191                }
192                let Some(config) = env.vector_config() else {
193                    ::core::hint::cold_path();
194                    return ExecutionResult::Err(ExecutionError::IllegalInstruction {
195                        address: PackedAddress::new(
196                            program_counter.old_pc(zvexx_helpers::INSTRUCTION_SIZE),
197                        ),
198                    });
199                };
200                let sew = config.vtype().vsew();
201                let vs2 = zvexx_helpers::vreg_group::<Reg, Env, _, _>(
202                    program_counter,
203                    config,
204                    vs2,
205                    sew.as_eew(),
206                )?;
207                let vs1 = zvexx_helpers::vreg_group::<Reg, Env, _, _>(
208                    program_counter,
209                    config,
210                    vs1,
211                    sew.as_eew(),
212                )?;
213                zvexx_carry_helpers::check_mask_dest_overlap::<Reg, Env, _, _>(
214                    program_counter,
215                    vd,
216                    vs2,
217                )?;
218                zvexx_carry_helpers::check_mask_dest_overlap::<Reg, Env, _, _>(
219                    program_counter,
220                    vd,
221                    vs1,
222                )?;
223                zvexx_carry_helpers::execute_carry_add_mask::<true, Reg, _>(
224                    env,
225                    vd,
226                    vs2,
227                    zvexx_carry_helpers::OpSrc::Vreg(vs1),
228                    sew,
229                );
230            }
231
232            Self::VmadcVxm { vd, vs2, rs1: _ } => {
233                if !zvexx_helpers::non_memory_instruction_allowed::<Reg, _>(env) {
234                    ::core::hint::cold_path();
235                    return ExecutionResult::Err(ExecutionError::IllegalInstruction {
236                        address: PackedAddress::new(
237                            program_counter.old_pc(zvexx_helpers::INSTRUCTION_SIZE),
238                        ),
239                    });
240                }
241                let Some(config) = env.vector_config() else {
242                    ::core::hint::cold_path();
243                    return ExecutionResult::Err(ExecutionError::IllegalInstruction {
244                        address: PackedAddress::new(
245                            program_counter.old_pc(zvexx_helpers::INSTRUCTION_SIZE),
246                        ),
247                    });
248                };
249                let sew = config.vtype().vsew();
250                let vs2 = zvexx_helpers::vreg_group::<Reg, Env, _, _>(
251                    program_counter,
252                    config,
253                    vs2,
254                    sew.as_eew(),
255                )?;
256                zvexx_carry_helpers::check_mask_dest_overlap::<Reg, Env, _, _>(
257                    program_counter,
258                    vd,
259                    vs2,
260                )?;
261                let scalar = rs1_value.as_i64().cast_unsigned();
262                zvexx_carry_helpers::execute_carry_add_mask::<true, Reg, _>(
263                    env,
264                    vd,
265                    vs2,
266                    zvexx_carry_helpers::OpSrc::Scalar(scalar),
267                    sew,
268                );
269            }
270
271            Self::VmadcVim { vd, vs2, imm } => {
272                if !zvexx_helpers::non_memory_instruction_allowed::<Reg, _>(env) {
273                    ::core::hint::cold_path();
274                    return ExecutionResult::Err(ExecutionError::IllegalInstruction {
275                        address: PackedAddress::new(
276                            program_counter.old_pc(zvexx_helpers::INSTRUCTION_SIZE),
277                        ),
278                    });
279                }
280                let Some(config) = env.vector_config() else {
281                    ::core::hint::cold_path();
282                    return ExecutionResult::Err(ExecutionError::IllegalInstruction {
283                        address: PackedAddress::new(
284                            program_counter.old_pc(zvexx_helpers::INSTRUCTION_SIZE),
285                        ),
286                    });
287                };
288                let sew = config.vtype().vsew();
289                let vs2 = zvexx_helpers::vreg_group::<Reg, Env, _, _>(
290                    program_counter,
291                    config,
292                    vs2,
293                    sew.as_eew(),
294                )?;
295                zvexx_carry_helpers::check_mask_dest_overlap::<Reg, Env, _, _>(
296                    program_counter,
297                    vd,
298                    vs2,
299                )?;
300                let scalar = i64::from(imm).cast_unsigned();
301                zvexx_carry_helpers::execute_carry_add_mask::<true, Reg, _>(
302                    env,
303                    vd,
304                    vs2,
305                    zvexx_carry_helpers::OpSrc::Scalar(scalar),
306                    sew,
307                );
308            }
309
310            Self::VmadcVv { vd, vs2, vs1 } => {
311                if !zvexx_helpers::non_memory_instruction_allowed::<Reg, _>(env) {
312                    ::core::hint::cold_path();
313                    return ExecutionResult::Err(ExecutionError::IllegalInstruction {
314                        address: PackedAddress::new(
315                            program_counter.old_pc(zvexx_helpers::INSTRUCTION_SIZE),
316                        ),
317                    });
318                }
319                let Some(config) = env.vector_config() else {
320                    ::core::hint::cold_path();
321                    return ExecutionResult::Err(ExecutionError::IllegalInstruction {
322                        address: PackedAddress::new(
323                            program_counter.old_pc(zvexx_helpers::INSTRUCTION_SIZE),
324                        ),
325                    });
326                };
327                let sew = config.vtype().vsew();
328                let vs2 = zvexx_helpers::vreg_group::<Reg, Env, _, _>(
329                    program_counter,
330                    config,
331                    vs2,
332                    sew.as_eew(),
333                )?;
334                let vs1 = zvexx_helpers::vreg_group::<Reg, Env, _, _>(
335                    program_counter,
336                    config,
337                    vs1,
338                    sew.as_eew(),
339                )?;
340                zvexx_carry_helpers::check_mask_dest_overlap::<Reg, Env, _, _>(
341                    program_counter,
342                    vd,
343                    vs2,
344                )?;
345                zvexx_carry_helpers::check_mask_dest_overlap::<Reg, Env, _, _>(
346                    program_counter,
347                    vd,
348                    vs1,
349                )?;
350                zvexx_carry_helpers::execute_carry_add_mask::<false, Reg, _>(
351                    env,
352                    vd,
353                    vs2,
354                    zvexx_carry_helpers::OpSrc::Vreg(vs1),
355                    sew,
356                );
357            }
358
359            Self::VmadcVx { vd, vs2, rs1: _ } => {
360                if !zvexx_helpers::non_memory_instruction_allowed::<Reg, _>(env) {
361                    ::core::hint::cold_path();
362                    return ExecutionResult::Err(ExecutionError::IllegalInstruction {
363                        address: PackedAddress::new(
364                            program_counter.old_pc(zvexx_helpers::INSTRUCTION_SIZE),
365                        ),
366                    });
367                }
368                let Some(config) = env.vector_config() else {
369                    ::core::hint::cold_path();
370                    return ExecutionResult::Err(ExecutionError::IllegalInstruction {
371                        address: PackedAddress::new(
372                            program_counter.old_pc(zvexx_helpers::INSTRUCTION_SIZE),
373                        ),
374                    });
375                };
376                let sew = config.vtype().vsew();
377                let vs2 = zvexx_helpers::vreg_group::<Reg, Env, _, _>(
378                    program_counter,
379                    config,
380                    vs2,
381                    sew.as_eew(),
382                )?;
383                zvexx_carry_helpers::check_mask_dest_overlap::<Reg, Env, _, _>(
384                    program_counter,
385                    vd,
386                    vs2,
387                )?;
388                let scalar = rs1_value.as_i64().cast_unsigned();
389                zvexx_carry_helpers::execute_carry_add_mask::<false, Reg, _>(
390                    env,
391                    vd,
392                    vs2,
393                    zvexx_carry_helpers::OpSrc::Scalar(scalar),
394                    sew,
395                );
396            }
397
398            Self::VmadcVi { vd, vs2, imm } => {
399                if !zvexx_helpers::non_memory_instruction_allowed::<Reg, _>(env) {
400                    ::core::hint::cold_path();
401                    return ExecutionResult::Err(ExecutionError::IllegalInstruction {
402                        address: PackedAddress::new(
403                            program_counter.old_pc(zvexx_helpers::INSTRUCTION_SIZE),
404                        ),
405                    });
406                }
407                let Some(config) = env.vector_config() else {
408                    ::core::hint::cold_path();
409                    return ExecutionResult::Err(ExecutionError::IllegalInstruction {
410                        address: PackedAddress::new(
411                            program_counter.old_pc(zvexx_helpers::INSTRUCTION_SIZE),
412                        ),
413                    });
414                };
415                let sew = config.vtype().vsew();
416                let vs2 = zvexx_helpers::vreg_group::<Reg, Env, _, _>(
417                    program_counter,
418                    config,
419                    vs2,
420                    sew.as_eew(),
421                )?;
422                zvexx_carry_helpers::check_mask_dest_overlap::<Reg, Env, _, _>(
423                    program_counter,
424                    vd,
425                    vs2,
426                )?;
427                let scalar = i64::from(imm).cast_unsigned();
428                zvexx_carry_helpers::execute_carry_add_mask::<false, Reg, _>(
429                    env,
430                    vd,
431                    vs2,
432                    zvexx_carry_helpers::OpSrc::Scalar(scalar),
433                    sew,
434                );
435            }
436
437            // vsbc: subtract with borrow-in from v0, data result
438            Self::VsbcVvm { vd, vs2, vs1 } => {
439                if !zvexx_helpers::non_memory_instruction_allowed::<Reg, _>(env) {
440                    ::core::hint::cold_path();
441                    return ExecutionResult::Err(ExecutionError::IllegalInstruction {
442                        address: PackedAddress::new(
443                            program_counter.old_pc(zvexx_helpers::INSTRUCTION_SIZE),
444                        ),
445                    });
446                }
447                let Some(config) = env.vector_config() else {
448                    ::core::hint::cold_path();
449                    return ExecutionResult::Err(ExecutionError::IllegalInstruction {
450                        address: PackedAddress::new(
451                            program_counter.old_pc(zvexx_helpers::INSTRUCTION_SIZE),
452                        ),
453                    });
454                };
455                let sew = config.vtype().vsew();
456                let vd = zvexx_helpers::vreg_group::<Reg, Env, _, _>(
457                    program_counter,
458                    config,
459                    vd,
460                    sew.as_eew(),
461                )?;
462                let vs2 = zvexx_helpers::vreg_group::<Reg, Env, _, _>(
463                    program_counter,
464                    config,
465                    vs2,
466                    sew.as_eew(),
467                )?;
468                let vs1 = zvexx_helpers::vreg_group::<Reg, Env, _, _>(
469                    program_counter,
470                    config,
471                    vs1,
472                    sew.as_eew(),
473                )?;
474                zvexx_carry_helpers::execute_carry_sub::<Reg, _>(
475                    env,
476                    vd,
477                    vs2,
478                    zvexx_carry_helpers::OpSrc::Vreg(vs1),
479                );
480            }
481
482            Self::VsbcVxm { vd, vs2, rs1: _ } => {
483                if !zvexx_helpers::non_memory_instruction_allowed::<Reg, _>(env) {
484                    ::core::hint::cold_path();
485                    return ExecutionResult::Err(ExecutionError::IllegalInstruction {
486                        address: PackedAddress::new(
487                            program_counter.old_pc(zvexx_helpers::INSTRUCTION_SIZE),
488                        ),
489                    });
490                }
491                let Some(config) = env.vector_config() else {
492                    ::core::hint::cold_path();
493                    return ExecutionResult::Err(ExecutionError::IllegalInstruction {
494                        address: PackedAddress::new(
495                            program_counter.old_pc(zvexx_helpers::INSTRUCTION_SIZE),
496                        ),
497                    });
498                };
499                let sew = config.vtype().vsew();
500                let vd = zvexx_helpers::vreg_group::<Reg, Env, _, _>(
501                    program_counter,
502                    config,
503                    vd,
504                    sew.as_eew(),
505                )?;
506                let vs2 = zvexx_helpers::vreg_group::<Reg, Env, _, _>(
507                    program_counter,
508                    config,
509                    vs2,
510                    sew.as_eew(),
511                )?;
512                let scalar = rs1_value.as_i64().cast_unsigned();
513                zvexx_carry_helpers::execute_carry_sub::<Reg, _>(
514                    env,
515                    vd,
516                    vs2,
517                    zvexx_carry_helpers::OpSrc::Scalar(scalar),
518                );
519            }
520
521            // vmsbc: subtract and write borrow-out mask
522            Self::VmsbcVvm { vd, vs2, vs1 } => {
523                if !zvexx_helpers::non_memory_instruction_allowed::<Reg, _>(env) {
524                    ::core::hint::cold_path();
525                    return ExecutionResult::Err(ExecutionError::IllegalInstruction {
526                        address: PackedAddress::new(
527                            program_counter.old_pc(zvexx_helpers::INSTRUCTION_SIZE),
528                        ),
529                    });
530                }
531                let Some(config) = env.vector_config() else {
532                    ::core::hint::cold_path();
533                    return ExecutionResult::Err(ExecutionError::IllegalInstruction {
534                        address: PackedAddress::new(
535                            program_counter.old_pc(zvexx_helpers::INSTRUCTION_SIZE),
536                        ),
537                    });
538                };
539                let sew = config.vtype().vsew();
540                let vs2 = zvexx_helpers::vreg_group::<Reg, Env, _, _>(
541                    program_counter,
542                    config,
543                    vs2,
544                    sew.as_eew(),
545                )?;
546                let vs1 = zvexx_helpers::vreg_group::<Reg, Env, _, _>(
547                    program_counter,
548                    config,
549                    vs1,
550                    sew.as_eew(),
551                )?;
552                zvexx_carry_helpers::check_mask_dest_overlap::<Reg, Env, _, _>(
553                    program_counter,
554                    vd,
555                    vs2,
556                )?;
557                zvexx_carry_helpers::check_mask_dest_overlap::<Reg, Env, _, _>(
558                    program_counter,
559                    vd,
560                    vs1,
561                )?;
562                zvexx_carry_helpers::execute_carry_sub_mask::<true, Reg, _>(
563                    env,
564                    vd,
565                    vs2,
566                    zvexx_carry_helpers::OpSrc::Vreg(vs1),
567                    sew,
568                );
569            }
570
571            Self::VmsbcVxm { vd, vs2, rs1: _ } => {
572                if !zvexx_helpers::non_memory_instruction_allowed::<Reg, _>(env) {
573                    ::core::hint::cold_path();
574                    return ExecutionResult::Err(ExecutionError::IllegalInstruction {
575                        address: PackedAddress::new(
576                            program_counter.old_pc(zvexx_helpers::INSTRUCTION_SIZE),
577                        ),
578                    });
579                }
580                let Some(config) = env.vector_config() else {
581                    ::core::hint::cold_path();
582                    return ExecutionResult::Err(ExecutionError::IllegalInstruction {
583                        address: PackedAddress::new(
584                            program_counter.old_pc(zvexx_helpers::INSTRUCTION_SIZE),
585                        ),
586                    });
587                };
588                let sew = config.vtype().vsew();
589                let vs2 = zvexx_helpers::vreg_group::<Reg, Env, _, _>(
590                    program_counter,
591                    config,
592                    vs2,
593                    sew.as_eew(),
594                )?;
595                zvexx_carry_helpers::check_mask_dest_overlap::<Reg, Env, _, _>(
596                    program_counter,
597                    vd,
598                    vs2,
599                )?;
600                let scalar = rs1_value.as_i64().cast_unsigned();
601                zvexx_carry_helpers::execute_carry_sub_mask::<true, Reg, _>(
602                    env,
603                    vd,
604                    vs2,
605                    zvexx_carry_helpers::OpSrc::Scalar(scalar),
606                    sew,
607                );
608            }
609
610            Self::VmsbcVv { vd, vs2, vs1 } => {
611                if !zvexx_helpers::non_memory_instruction_allowed::<Reg, _>(env) {
612                    ::core::hint::cold_path();
613                    return ExecutionResult::Err(ExecutionError::IllegalInstruction {
614                        address: PackedAddress::new(
615                            program_counter.old_pc(zvexx_helpers::INSTRUCTION_SIZE),
616                        ),
617                    });
618                }
619                let Some(config) = env.vector_config() else {
620                    ::core::hint::cold_path();
621                    return ExecutionResult::Err(ExecutionError::IllegalInstruction {
622                        address: PackedAddress::new(
623                            program_counter.old_pc(zvexx_helpers::INSTRUCTION_SIZE),
624                        ),
625                    });
626                };
627                let sew = config.vtype().vsew();
628                let vs2 = zvexx_helpers::vreg_group::<Reg, Env, _, _>(
629                    program_counter,
630                    config,
631                    vs2,
632                    sew.as_eew(),
633                )?;
634                let vs1 = zvexx_helpers::vreg_group::<Reg, Env, _, _>(
635                    program_counter,
636                    config,
637                    vs1,
638                    sew.as_eew(),
639                )?;
640                zvexx_carry_helpers::check_mask_dest_overlap::<Reg, Env, _, _>(
641                    program_counter,
642                    vd,
643                    vs2,
644                )?;
645                zvexx_carry_helpers::check_mask_dest_overlap::<Reg, Env, _, _>(
646                    program_counter,
647                    vd,
648                    vs1,
649                )?;
650                zvexx_carry_helpers::execute_carry_sub_mask::<false, Reg, _>(
651                    env,
652                    vd,
653                    vs2,
654                    zvexx_carry_helpers::OpSrc::Vreg(vs1),
655                    sew,
656                );
657            }
658
659            Self::VmsbcVx { vd, vs2, rs1: _ } => {
660                if !zvexx_helpers::non_memory_instruction_allowed::<Reg, _>(env) {
661                    ::core::hint::cold_path();
662                    return ExecutionResult::Err(ExecutionError::IllegalInstruction {
663                        address: PackedAddress::new(
664                            program_counter.old_pc(zvexx_helpers::INSTRUCTION_SIZE),
665                        ),
666                    });
667                }
668                let Some(config) = env.vector_config() else {
669                    ::core::hint::cold_path();
670                    return ExecutionResult::Err(ExecutionError::IllegalInstruction {
671                        address: PackedAddress::new(
672                            program_counter.old_pc(zvexx_helpers::INSTRUCTION_SIZE),
673                        ),
674                    });
675                };
676                let sew = config.vtype().vsew();
677                let vs2 = zvexx_helpers::vreg_group::<Reg, Env, _, _>(
678                    program_counter,
679                    config,
680                    vs2,
681                    sew.as_eew(),
682                )?;
683                zvexx_carry_helpers::check_mask_dest_overlap::<Reg, Env, _, _>(
684                    program_counter,
685                    vd,
686                    vs2,
687                )?;
688                let scalar = rs1_value.as_i64().cast_unsigned();
689                zvexx_carry_helpers::execute_carry_sub_mask::<false, Reg, _>(
690                    env,
691                    vd,
692                    vs2,
693                    zvexx_carry_helpers::OpSrc::Scalar(scalar),
694                    sew,
695                );
696            }
697        }
698
699        ExecutionResult::ContinueNoWrite
700    }
701}