1#[cfg(test)]
4mod tests;
5pub mod zvexx_muldiv_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 ZveXxMulDivInstruction<Hart>
20where
21 Reg: Register,
22 Hart: VectorHartConfig<Reg = Reg>,
23{
24}
25
26#[instruction_execution]
27const impl<Reg, Hart, Env> ExecutableInstructionCsr<Env> for ZveXxMulDivInstruction<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 ZveXxMulDivInstruction<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 Self::VmulVv { vd, vs2, vs1, vm } => {
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_muldiv_helpers::execute_arith_op(
97 env,
98 vd,
99 vs2,
100 zvexx_muldiv_helpers::OpSrc::Vreg(vs1),
101 vm,
102 sew,
103 |a, b, _| a.wrapping_mul(b),
104 );
105 }
106 Self::VmulVx {
107 vd,
108 vs2,
109 rs1: _,
110 vm,
111 } => {
112 if !zvexx_helpers::non_memory_instruction_allowed::<Reg, _>(env) {
113 ::core::hint::cold_path();
114 return ExecutionResult::Err(ExecutionError::IllegalInstruction {
115 address: PackedAddress::new(
116 program_counter.old_pc(zvexx_helpers::INSTRUCTION_SIZE),
117 ),
118 });
119 }
120 let Some(config) = env.vector_config() else {
121 ::core::hint::cold_path();
122 return ExecutionResult::Err(ExecutionError::IllegalInstruction {
123 address: PackedAddress::new(
124 program_counter.old_pc(zvexx_helpers::INSTRUCTION_SIZE),
125 ),
126 });
127 };
128 let sew = config.vtype().vsew();
129 let vd = zvexx_helpers::vreg_group::<Reg, Env, _, _>(
130 program_counter,
131 config,
132 vd,
133 sew.as_eew(),
134 )?;
135 let vs2 = zvexx_helpers::vreg_group::<Reg, Env, _, _>(
136 program_counter,
137 config,
138 vs2,
139 sew.as_eew(),
140 )?;
141 let scalar = rs1_value.as_i64().cast_unsigned();
142 zvexx_muldiv_helpers::execute_arith_op(
143 env,
144 vd,
145 vs2,
146 zvexx_muldiv_helpers::OpSrc::Scalar(scalar),
147 vm,
148 sew,
149 |a, b, _| a.wrapping_mul(b),
150 );
151 }
152 Self::VmulhVv { vd, vs2, vs1, vm } => {
154 if !zvexx_helpers::non_memory_instruction_allowed::<Reg, _>(env) {
155 ::core::hint::cold_path();
156 return ExecutionResult::Err(ExecutionError::IllegalInstruction {
157 address: PackedAddress::new(
158 program_counter.old_pc(zvexx_helpers::INSTRUCTION_SIZE),
159 ),
160 });
161 }
162 let Some(config) = env.vector_config() else {
163 ::core::hint::cold_path();
164 return ExecutionResult::Err(ExecutionError::IllegalInstruction {
165 address: PackedAddress::new(
166 program_counter.old_pc(zvexx_helpers::INSTRUCTION_SIZE),
167 ),
168 });
169 };
170 let sew = config.vtype().vsew();
171 if !Self::implements_extension::<V<_>>() && sew == Vsew::E64 {
175 ::core::hint::cold_path();
176 return ExecutionResult::Err(ExecutionError::IllegalInstruction {
177 address: PackedAddress::new(
178 program_counter.old_pc(zvexx_helpers::INSTRUCTION_SIZE),
179 ),
180 });
181 }
182 let vd = zvexx_helpers::vreg_group::<Reg, Env, _, _>(
183 program_counter,
184 config,
185 vd,
186 sew.as_eew(),
187 )?;
188 let vs2 = zvexx_helpers::vreg_group::<Reg, Env, _, _>(
189 program_counter,
190 config,
191 vs2,
192 sew.as_eew(),
193 )?;
194 let vs1 = zvexx_helpers::vreg_group::<Reg, Env, _, _>(
195 program_counter,
196 config,
197 vs1,
198 sew.as_eew(),
199 )?;
200 zvexx_muldiv_helpers::execute_arith_op(
201 env,
202 vd,
203 vs2,
204 zvexx_muldiv_helpers::OpSrc::Vreg(vs1),
205 vm,
206 sew,
207 zvexx_muldiv_helpers::mulh_ss,
208 );
209 }
210 Self::VmulhVx {
211 vd,
212 vs2,
213 rs1: _,
214 vm,
215 } => {
216 if !zvexx_helpers::non_memory_instruction_allowed::<Reg, _>(env) {
217 ::core::hint::cold_path();
218 return ExecutionResult::Err(ExecutionError::IllegalInstruction {
219 address: PackedAddress::new(
220 program_counter.old_pc(zvexx_helpers::INSTRUCTION_SIZE),
221 ),
222 });
223 }
224 let Some(config) = env.vector_config() else {
225 ::core::hint::cold_path();
226 return ExecutionResult::Err(ExecutionError::IllegalInstruction {
227 address: PackedAddress::new(
228 program_counter.old_pc(zvexx_helpers::INSTRUCTION_SIZE),
229 ),
230 });
231 };
232 let sew = config.vtype().vsew();
233 if !Self::implements_extension::<V<_>>() && sew == Vsew::E64 {
237 ::core::hint::cold_path();
238 return ExecutionResult::Err(ExecutionError::IllegalInstruction {
239 address: PackedAddress::new(
240 program_counter.old_pc(zvexx_helpers::INSTRUCTION_SIZE),
241 ),
242 });
243 }
244 let vd = zvexx_helpers::vreg_group::<Reg, Env, _, _>(
245 program_counter,
246 config,
247 vd,
248 sew.as_eew(),
249 )?;
250 let vs2 = zvexx_helpers::vreg_group::<Reg, Env, _, _>(
251 program_counter,
252 config,
253 vs2,
254 sew.as_eew(),
255 )?;
256 let scalar = rs1_value.as_u64();
257 zvexx_muldiv_helpers::execute_arith_op(
258 env,
259 vd,
260 vs2,
261 zvexx_muldiv_helpers::OpSrc::Scalar(scalar),
262 vm,
263 sew,
264 zvexx_muldiv_helpers::mulh_ss,
265 );
266 }
267 Self::VmulhuVv { vd, vs2, vs1, vm } => {
269 if !zvexx_helpers::non_memory_instruction_allowed::<Reg, _>(env) {
270 ::core::hint::cold_path();
271 return ExecutionResult::Err(ExecutionError::IllegalInstruction {
272 address: PackedAddress::new(
273 program_counter.old_pc(zvexx_helpers::INSTRUCTION_SIZE),
274 ),
275 });
276 }
277 let Some(config) = env.vector_config() else {
278 ::core::hint::cold_path();
279 return ExecutionResult::Err(ExecutionError::IllegalInstruction {
280 address: PackedAddress::new(
281 program_counter.old_pc(zvexx_helpers::INSTRUCTION_SIZE),
282 ),
283 });
284 };
285 let sew = config.vtype().vsew();
286 if !Self::implements_extension::<V<_>>() && sew == Vsew::E64 {
290 ::core::hint::cold_path();
291 return ExecutionResult::Err(ExecutionError::IllegalInstruction {
292 address: PackedAddress::new(
293 program_counter.old_pc(zvexx_helpers::INSTRUCTION_SIZE),
294 ),
295 });
296 }
297 let vd = zvexx_helpers::vreg_group::<Reg, Env, _, _>(
298 program_counter,
299 config,
300 vd,
301 sew.as_eew(),
302 )?;
303 let vs2 = zvexx_helpers::vreg_group::<Reg, Env, _, _>(
304 program_counter,
305 config,
306 vs2,
307 sew.as_eew(),
308 )?;
309 let vs1 = zvexx_helpers::vreg_group::<Reg, Env, _, _>(
310 program_counter,
311 config,
312 vs1,
313 sew.as_eew(),
314 )?;
315 zvexx_muldiv_helpers::execute_arith_op(
316 env,
317 vd,
318 vs2,
319 zvexx_muldiv_helpers::OpSrc::Vreg(vs1),
320 vm,
321 sew,
322 zvexx_muldiv_helpers::mulhu_uu,
323 );
324 }
325 Self::VmulhuVx {
326 vd,
327 vs2,
328 rs1: _,
329 vm,
330 } => {
331 if !zvexx_helpers::non_memory_instruction_allowed::<Reg, _>(env) {
332 ::core::hint::cold_path();
333 return ExecutionResult::Err(ExecutionError::IllegalInstruction {
334 address: PackedAddress::new(
335 program_counter.old_pc(zvexx_helpers::INSTRUCTION_SIZE),
336 ),
337 });
338 }
339 let Some(config) = env.vector_config() else {
340 ::core::hint::cold_path();
341 return ExecutionResult::Err(ExecutionError::IllegalInstruction {
342 address: PackedAddress::new(
343 program_counter.old_pc(zvexx_helpers::INSTRUCTION_SIZE),
344 ),
345 });
346 };
347 let sew = config.vtype().vsew();
348 if !Self::implements_extension::<V<_>>() && sew == Vsew::E64 {
352 ::core::hint::cold_path();
353 return ExecutionResult::Err(ExecutionError::IllegalInstruction {
354 address: PackedAddress::new(
355 program_counter.old_pc(zvexx_helpers::INSTRUCTION_SIZE),
356 ),
357 });
358 }
359 let vd = zvexx_helpers::vreg_group::<Reg, Env, _, _>(
360 program_counter,
361 config,
362 vd,
363 sew.as_eew(),
364 )?;
365 let vs2 = zvexx_helpers::vreg_group::<Reg, Env, _, _>(
366 program_counter,
367 config,
368 vs2,
369 sew.as_eew(),
370 )?;
371 let scalar = rs1_value.as_u64();
372 zvexx_muldiv_helpers::execute_arith_op(
373 env,
374 vd,
375 vs2,
376 zvexx_muldiv_helpers::OpSrc::Scalar(scalar),
377 vm,
378 sew,
379 zvexx_muldiv_helpers::mulhu_uu,
380 );
381 }
382 Self::VmulhsuVv { vd, vs2, vs1, vm } => {
384 if !zvexx_helpers::non_memory_instruction_allowed::<Reg, _>(env) {
385 ::core::hint::cold_path();
386 return ExecutionResult::Err(ExecutionError::IllegalInstruction {
387 address: PackedAddress::new(
388 program_counter.old_pc(zvexx_helpers::INSTRUCTION_SIZE),
389 ),
390 });
391 }
392 let Some(config) = env.vector_config() else {
393 ::core::hint::cold_path();
394 return ExecutionResult::Err(ExecutionError::IllegalInstruction {
395 address: PackedAddress::new(
396 program_counter.old_pc(zvexx_helpers::INSTRUCTION_SIZE),
397 ),
398 });
399 };
400 let sew = config.vtype().vsew();
401 if !Self::implements_extension::<V<_>>() && sew == Vsew::E64 {
405 ::core::hint::cold_path();
406 return ExecutionResult::Err(ExecutionError::IllegalInstruction {
407 address: PackedAddress::new(
408 program_counter.old_pc(zvexx_helpers::INSTRUCTION_SIZE),
409 ),
410 });
411 }
412 let vd = zvexx_helpers::vreg_group::<Reg, Env, _, _>(
413 program_counter,
414 config,
415 vd,
416 sew.as_eew(),
417 )?;
418 let vs2 = zvexx_helpers::vreg_group::<Reg, Env, _, _>(
419 program_counter,
420 config,
421 vs2,
422 sew.as_eew(),
423 )?;
424 let vs1 = zvexx_helpers::vreg_group::<Reg, Env, _, _>(
425 program_counter,
426 config,
427 vs1,
428 sew.as_eew(),
429 )?;
430 zvexx_muldiv_helpers::execute_arith_op(
431 env,
432 vd,
433 vs2,
434 zvexx_muldiv_helpers::OpSrc::Vreg(vs1),
435 vm,
436 sew,
437 zvexx_muldiv_helpers::mulhsu_su,
439 );
440 }
441 Self::VmulhsuVx {
442 vd,
443 vs2,
444 rs1: _,
445 vm,
446 } => {
447 if !zvexx_helpers::non_memory_instruction_allowed::<Reg, _>(env) {
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 Some(config) = env.vector_config() else {
456 ::core::hint::cold_path();
457 return ExecutionResult::Err(ExecutionError::IllegalInstruction {
458 address: PackedAddress::new(
459 program_counter.old_pc(zvexx_helpers::INSTRUCTION_SIZE),
460 ),
461 });
462 };
463 let sew = config.vtype().vsew();
464 if !Self::implements_extension::<V<_>>() && sew == Vsew::E64 {
468 ::core::hint::cold_path();
469 return ExecutionResult::Err(ExecutionError::IllegalInstruction {
470 address: PackedAddress::new(
471 program_counter.old_pc(zvexx_helpers::INSTRUCTION_SIZE),
472 ),
473 });
474 }
475 let vd = zvexx_helpers::vreg_group::<Reg, Env, _, _>(
476 program_counter,
477 config,
478 vd,
479 sew.as_eew(),
480 )?;
481 let vs2 = zvexx_helpers::vreg_group::<Reg, Env, _, _>(
482 program_counter,
483 config,
484 vs2,
485 sew.as_eew(),
486 )?;
487 let scalar = rs1_value.as_u64();
489 zvexx_muldiv_helpers::execute_arith_op(
490 env,
491 vd,
492 vs2,
493 zvexx_muldiv_helpers::OpSrc::Scalar(scalar),
494 vm,
495 sew,
496 zvexx_muldiv_helpers::mulhsu_su,
498 );
499 }
500 Self::VdivuVv { vd, vs2, vs1, vm } => {
502 if !zvexx_helpers::non_memory_instruction_allowed::<Reg, _>(env) {
503 ::core::hint::cold_path();
504 return ExecutionResult::Err(ExecutionError::IllegalInstruction {
505 address: PackedAddress::new(
506 program_counter.old_pc(zvexx_helpers::INSTRUCTION_SIZE),
507 ),
508 });
509 }
510 let Some(config) = env.vector_config() else {
511 ::core::hint::cold_path();
512 return ExecutionResult::Err(ExecutionError::IllegalInstruction {
513 address: PackedAddress::new(
514 program_counter.old_pc(zvexx_helpers::INSTRUCTION_SIZE),
515 ),
516 });
517 };
518 let sew = config.vtype().vsew();
519 let vd = zvexx_helpers::vreg_group::<Reg, Env, _, _>(
520 program_counter,
521 config,
522 vd,
523 sew.as_eew(),
524 )?;
525 let vs2 = zvexx_helpers::vreg_group::<Reg, Env, _, _>(
526 program_counter,
527 config,
528 vs2,
529 sew.as_eew(),
530 )?;
531 let vs1 = zvexx_helpers::vreg_group::<Reg, Env, _, _>(
532 program_counter,
533 config,
534 vs1,
535 sew.as_eew(),
536 )?;
537 zvexx_muldiv_helpers::execute_arith_op(
538 env,
539 vd,
540 vs2,
541 zvexx_muldiv_helpers::OpSrc::Vreg(vs1),
542 vm,
543 sew,
544 |a, b, sew| {
546 let mask = zvexx_muldiv_helpers::sew_mask(sew);
547 let dividend = a & mask;
548 let divisor = b & mask;
549 dividend.checked_div(divisor).unwrap_or(mask)
550 },
551 );
552 }
553 Self::VdivuVx {
554 vd,
555 vs2,
556 rs1: _,
557 vm,
558 } => {
559 if !zvexx_helpers::non_memory_instruction_allowed::<Reg, _>(env) {
560 ::core::hint::cold_path();
561 return ExecutionResult::Err(ExecutionError::IllegalInstruction {
562 address: PackedAddress::new(
563 program_counter.old_pc(zvexx_helpers::INSTRUCTION_SIZE),
564 ),
565 });
566 }
567 let Some(config) = env.vector_config() else {
568 ::core::hint::cold_path();
569 return ExecutionResult::Err(ExecutionError::IllegalInstruction {
570 address: PackedAddress::new(
571 program_counter.old_pc(zvexx_helpers::INSTRUCTION_SIZE),
572 ),
573 });
574 };
575 let sew = config.vtype().vsew();
576 let vd = zvexx_helpers::vreg_group::<Reg, Env, _, _>(
577 program_counter,
578 config,
579 vd,
580 sew.as_eew(),
581 )?;
582 let vs2 = zvexx_helpers::vreg_group::<Reg, Env, _, _>(
583 program_counter,
584 config,
585 vs2,
586 sew.as_eew(),
587 )?;
588 let scalar = rs1_value.as_i64().cast_unsigned();
589 zvexx_muldiv_helpers::execute_arith_op(
590 env,
591 vd,
592 vs2,
593 zvexx_muldiv_helpers::OpSrc::Scalar(scalar),
594 vm,
595 sew,
596 |a, b, sew| {
597 let mask = zvexx_muldiv_helpers::sew_mask(sew);
598 let dividend = a & mask;
599 let divisor = b & mask;
600 dividend.checked_div(divisor).unwrap_or(mask)
601 },
602 );
603 }
604 Self::VdivVv { vd, vs2, vs1, vm } => {
606 if !zvexx_helpers::non_memory_instruction_allowed::<Reg, _>(env) {
607 ::core::hint::cold_path();
608 return ExecutionResult::Err(ExecutionError::IllegalInstruction {
609 address: PackedAddress::new(
610 program_counter.old_pc(zvexx_helpers::INSTRUCTION_SIZE),
611 ),
612 });
613 }
614 let Some(config) = env.vector_config() else {
615 ::core::hint::cold_path();
616 return ExecutionResult::Err(ExecutionError::IllegalInstruction {
617 address: PackedAddress::new(
618 program_counter.old_pc(zvexx_helpers::INSTRUCTION_SIZE),
619 ),
620 });
621 };
622 let sew = config.vtype().vsew();
623 let vd = zvexx_helpers::vreg_group::<Reg, Env, _, _>(
624 program_counter,
625 config,
626 vd,
627 sew.as_eew(),
628 )?;
629 let vs2 = zvexx_helpers::vreg_group::<Reg, Env, _, _>(
630 program_counter,
631 config,
632 vs2,
633 sew.as_eew(),
634 )?;
635 let vs1 = zvexx_helpers::vreg_group::<Reg, Env, _, _>(
636 program_counter,
637 config,
638 vs1,
639 sew.as_eew(),
640 )?;
641 zvexx_muldiv_helpers::execute_arith_op(
642 env,
643 vd,
644 vs2,
645 zvexx_muldiv_helpers::OpSrc::Vreg(vs1),
646 vm,
647 sew,
648 zvexx_muldiv_helpers::sdiv,
649 );
650 }
651 Self::VdivVx {
652 vd,
653 vs2,
654 rs1: _,
655 vm,
656 } => {
657 if !zvexx_helpers::non_memory_instruction_allowed::<Reg, _>(env) {
658 ::core::hint::cold_path();
659 return ExecutionResult::Err(ExecutionError::IllegalInstruction {
660 address: PackedAddress::new(
661 program_counter.old_pc(zvexx_helpers::INSTRUCTION_SIZE),
662 ),
663 });
664 }
665 let Some(config) = env.vector_config() else {
666 ::core::hint::cold_path();
667 return ExecutionResult::Err(ExecutionError::IllegalInstruction {
668 address: PackedAddress::new(
669 program_counter.old_pc(zvexx_helpers::INSTRUCTION_SIZE),
670 ),
671 });
672 };
673 let sew = config.vtype().vsew();
674 let vd = zvexx_helpers::vreg_group::<Reg, Env, _, _>(
675 program_counter,
676 config,
677 vd,
678 sew.as_eew(),
679 )?;
680 let vs2 = zvexx_helpers::vreg_group::<Reg, Env, _, _>(
681 program_counter,
682 config,
683 vs2,
684 sew.as_eew(),
685 )?;
686 let scalar = rs1_value.as_i64().cast_unsigned();
687 zvexx_muldiv_helpers::execute_arith_op(
688 env,
689 vd,
690 vs2,
691 zvexx_muldiv_helpers::OpSrc::Scalar(scalar),
692 vm,
693 sew,
694 zvexx_muldiv_helpers::sdiv,
695 );
696 }
697 Self::VremuVv { vd, vs2, vs1, vm } => {
699 if !zvexx_helpers::non_memory_instruction_allowed::<Reg, _>(env) {
700 ::core::hint::cold_path();
701 return ExecutionResult::Err(ExecutionError::IllegalInstruction {
702 address: PackedAddress::new(
703 program_counter.old_pc(zvexx_helpers::INSTRUCTION_SIZE),
704 ),
705 });
706 }
707 let Some(config) = env.vector_config() else {
708 ::core::hint::cold_path();
709 return ExecutionResult::Err(ExecutionError::IllegalInstruction {
710 address: PackedAddress::new(
711 program_counter.old_pc(zvexx_helpers::INSTRUCTION_SIZE),
712 ),
713 });
714 };
715 let sew = config.vtype().vsew();
716 let vd = zvexx_helpers::vreg_group::<Reg, Env, _, _>(
717 program_counter,
718 config,
719 vd,
720 sew.as_eew(),
721 )?;
722 let vs2 = zvexx_helpers::vreg_group::<Reg, Env, _, _>(
723 program_counter,
724 config,
725 vs2,
726 sew.as_eew(),
727 )?;
728 let vs1 = zvexx_helpers::vreg_group::<Reg, Env, _, _>(
729 program_counter,
730 config,
731 vs1,
732 sew.as_eew(),
733 )?;
734 zvexx_muldiv_helpers::execute_arith_op(
735 env,
736 vd,
737 vs2,
738 zvexx_muldiv_helpers::OpSrc::Vreg(vs1),
739 vm,
740 sew,
741 |a, b, sew| {
743 let mask = zvexx_muldiv_helpers::sew_mask(sew);
744 let dividend = a & mask;
745 let divisor = b & mask;
746 if divisor == 0 {
747 dividend
748 } else {
749 dividend % divisor
750 }
751 },
752 );
753 }
754 Self::VremuVx {
755 vd,
756 vs2,
757 rs1: _,
758 vm,
759 } => {
760 if !zvexx_helpers::non_memory_instruction_allowed::<Reg, _>(env) {
761 ::core::hint::cold_path();
762 return ExecutionResult::Err(ExecutionError::IllegalInstruction {
763 address: PackedAddress::new(
764 program_counter.old_pc(zvexx_helpers::INSTRUCTION_SIZE),
765 ),
766 });
767 }
768 let Some(config) = env.vector_config() else {
769 ::core::hint::cold_path();
770 return ExecutionResult::Err(ExecutionError::IllegalInstruction {
771 address: PackedAddress::new(
772 program_counter.old_pc(zvexx_helpers::INSTRUCTION_SIZE),
773 ),
774 });
775 };
776 let sew = config.vtype().vsew();
777 let vd = zvexx_helpers::vreg_group::<Reg, Env, _, _>(
778 program_counter,
779 config,
780 vd,
781 sew.as_eew(),
782 )?;
783 let vs2 = zvexx_helpers::vreg_group::<Reg, Env, _, _>(
784 program_counter,
785 config,
786 vs2,
787 sew.as_eew(),
788 )?;
789 let scalar = rs1_value.as_i64().cast_unsigned();
790 zvexx_muldiv_helpers::execute_arith_op(
791 env,
792 vd,
793 vs2,
794 zvexx_muldiv_helpers::OpSrc::Scalar(scalar),
795 vm,
796 sew,
797 |a, b, sew| {
798 let mask = zvexx_muldiv_helpers::sew_mask(sew);
799 let dividend = a & mask;
800 let divisor = b & mask;
801 if divisor == 0 {
802 dividend
803 } else {
804 dividend % divisor
805 }
806 },
807 );
808 }
809 Self::VremVv { vd, vs2, vs1, vm } => {
811 if !zvexx_helpers::non_memory_instruction_allowed::<Reg, _>(env) {
812 ::core::hint::cold_path();
813 return ExecutionResult::Err(ExecutionError::IllegalInstruction {
814 address: PackedAddress::new(
815 program_counter.old_pc(zvexx_helpers::INSTRUCTION_SIZE),
816 ),
817 });
818 }
819 let Some(config) = env.vector_config() else {
820 ::core::hint::cold_path();
821 return ExecutionResult::Err(ExecutionError::IllegalInstruction {
822 address: PackedAddress::new(
823 program_counter.old_pc(zvexx_helpers::INSTRUCTION_SIZE),
824 ),
825 });
826 };
827 let sew = config.vtype().vsew();
828 let vd = zvexx_helpers::vreg_group::<Reg, Env, _, _>(
829 program_counter,
830 config,
831 vd,
832 sew.as_eew(),
833 )?;
834 let vs2 = zvexx_helpers::vreg_group::<Reg, Env, _, _>(
835 program_counter,
836 config,
837 vs2,
838 sew.as_eew(),
839 )?;
840 let vs1 = zvexx_helpers::vreg_group::<Reg, Env, _, _>(
841 program_counter,
842 config,
843 vs1,
844 sew.as_eew(),
845 )?;
846 zvexx_muldiv_helpers::execute_arith_op(
847 env,
848 vd,
849 vs2,
850 zvexx_muldiv_helpers::OpSrc::Vreg(vs1),
851 vm,
852 sew,
853 zvexx_muldiv_helpers::srem,
854 );
855 }
856 Self::VremVx {
857 vd,
858 vs2,
859 rs1: _,
860 vm,
861 } => {
862 if !zvexx_helpers::non_memory_instruction_allowed::<Reg, _>(env) {
863 ::core::hint::cold_path();
864 return ExecutionResult::Err(ExecutionError::IllegalInstruction {
865 address: PackedAddress::new(
866 program_counter.old_pc(zvexx_helpers::INSTRUCTION_SIZE),
867 ),
868 });
869 }
870 let Some(config) = env.vector_config() else {
871 ::core::hint::cold_path();
872 return ExecutionResult::Err(ExecutionError::IllegalInstruction {
873 address: PackedAddress::new(
874 program_counter.old_pc(zvexx_helpers::INSTRUCTION_SIZE),
875 ),
876 });
877 };
878 let sew = config.vtype().vsew();
879 let vd = zvexx_helpers::vreg_group::<Reg, Env, _, _>(
880 program_counter,
881 config,
882 vd,
883 sew.as_eew(),
884 )?;
885 let vs2 = zvexx_helpers::vreg_group::<Reg, Env, _, _>(
886 program_counter,
887 config,
888 vs2,
889 sew.as_eew(),
890 )?;
891 let scalar = rs1_value.as_i64().cast_unsigned();
892 zvexx_muldiv_helpers::execute_arith_op(
893 env,
894 vd,
895 vs2,
896 zvexx_muldiv_helpers::OpSrc::Scalar(scalar),
897 vm,
898 sew,
899 zvexx_muldiv_helpers::srem,
900 );
901 }
902 Self::VwmuluVv { vd, vs2, vs1, vm } => {
904 if !zvexx_helpers::non_memory_instruction_allowed::<Reg, _>(env) {
905 ::core::hint::cold_path();
906 return ExecutionResult::Err(ExecutionError::IllegalInstruction {
907 address: PackedAddress::new(
908 program_counter.old_pc(zvexx_helpers::INSTRUCTION_SIZE),
909 ),
910 });
911 }
912 let Some(config) = env.vector_config() else {
913 ::core::hint::cold_path();
914 return ExecutionResult::Err(ExecutionError::IllegalInstruction {
915 address: PackedAddress::new(
916 program_counter.old_pc(zvexx_helpers::INSTRUCTION_SIZE),
917 ),
918 });
919 };
920 let Some(sew) = zvexx_helpers::WideningSew::<Env::Hart>::new(config.vtype().vsew())
923 else {
924 ::core::hint::cold_path();
925 return ExecutionResult::Err(ExecutionError::IllegalInstruction {
926 address: PackedAddress::new(
927 program_counter.old_pc(zvexx_helpers::INSTRUCTION_SIZE),
928 ),
929 });
930 };
931 let vd = zvexx_helpers::vreg_group::<Reg, Env, _, _>(
932 program_counter,
933 config,
934 vd,
935 sew.wide().as_eew(),
936 )?;
937 let vs2 = zvexx_helpers::vreg_group::<Reg, Env, _, _>(
938 program_counter,
939 config,
940 vs2,
941 sew.narrow().as_eew(),
942 )?;
943 let vs1 = zvexx_helpers::vreg_group::<Reg, Env, _, _>(
944 program_counter,
945 config,
946 vs1,
947 sew.narrow().as_eew(),
948 )?;
949 zvexx_helpers::check_destination_overlap::<Reg, Env, _, _>(
951 program_counter,
952 vd,
953 vs2,
954 )?;
955 zvexx_helpers::check_destination_overlap::<Reg, Env, _, _>(
956 program_counter,
957 vd,
958 vs1,
959 )?;
960 zvexx_muldiv_helpers::execute_widening_op(
961 env,
962 vd,
963 vs2,
964 zvexx_muldiv_helpers::OpSrc::Vreg(vs1),
965 vm,
966 sew,
967 |a, b, sew| {
968 let mask = zvexx_muldiv_helpers::sew_mask(sew);
969 (a & mask).wrapping_mul(b & mask)
970 },
971 );
972 }
973 Self::VwmuluVx {
974 vd,
975 vs2,
976 rs1: _,
977 vm,
978 } => {
979 if !zvexx_helpers::non_memory_instruction_allowed::<Reg, _>(env) {
980 ::core::hint::cold_path();
981 return ExecutionResult::Err(ExecutionError::IllegalInstruction {
982 address: PackedAddress::new(
983 program_counter.old_pc(zvexx_helpers::INSTRUCTION_SIZE),
984 ),
985 });
986 }
987 let Some(config) = env.vector_config() else {
988 ::core::hint::cold_path();
989 return ExecutionResult::Err(ExecutionError::IllegalInstruction {
990 address: PackedAddress::new(
991 program_counter.old_pc(zvexx_helpers::INSTRUCTION_SIZE),
992 ),
993 });
994 };
995 let Some(sew) = zvexx_helpers::WideningSew::<Env::Hart>::new(config.vtype().vsew())
998 else {
999 ::core::hint::cold_path();
1000 return ExecutionResult::Err(ExecutionError::IllegalInstruction {
1001 address: PackedAddress::new(
1002 program_counter.old_pc(zvexx_helpers::INSTRUCTION_SIZE),
1003 ),
1004 });
1005 };
1006 let vd = zvexx_helpers::vreg_group::<Reg, Env, _, _>(
1007 program_counter,
1008 config,
1009 vd,
1010 sew.wide().as_eew(),
1011 )?;
1012 let vs2 = zvexx_helpers::vreg_group::<Reg, Env, _, _>(
1013 program_counter,
1014 config,
1015 vs2,
1016 sew.narrow().as_eew(),
1017 )?;
1018 zvexx_helpers::check_destination_overlap::<Reg, Env, _, _>(
1019 program_counter,
1020 vd,
1021 vs2,
1022 )?;
1023 let scalar = rs1_value.as_u64();
1024 zvexx_muldiv_helpers::execute_widening_op(
1025 env,
1026 vd,
1027 vs2,
1028 zvexx_muldiv_helpers::OpSrc::Scalar(scalar),
1029 vm,
1030 sew,
1031 |a, b, sew| {
1032 let mask = zvexx_muldiv_helpers::sew_mask(sew);
1033 (a & mask).wrapping_mul(b & mask)
1034 },
1035 );
1036 }
1037 Self::VwmulsuVv { vd, vs2, vs1, vm } => {
1039 if !zvexx_helpers::non_memory_instruction_allowed::<Reg, _>(env) {
1040 ::core::hint::cold_path();
1041 return ExecutionResult::Err(ExecutionError::IllegalInstruction {
1042 address: PackedAddress::new(
1043 program_counter.old_pc(zvexx_helpers::INSTRUCTION_SIZE),
1044 ),
1045 });
1046 }
1047 let Some(config) = env.vector_config() else {
1048 ::core::hint::cold_path();
1049 return ExecutionResult::Err(ExecutionError::IllegalInstruction {
1050 address: PackedAddress::new(
1051 program_counter.old_pc(zvexx_helpers::INSTRUCTION_SIZE),
1052 ),
1053 });
1054 };
1055 let Some(sew) = zvexx_helpers::WideningSew::<Env::Hart>::new(config.vtype().vsew())
1058 else {
1059 ::core::hint::cold_path();
1060 return ExecutionResult::Err(ExecutionError::IllegalInstruction {
1061 address: PackedAddress::new(
1062 program_counter.old_pc(zvexx_helpers::INSTRUCTION_SIZE),
1063 ),
1064 });
1065 };
1066 let vd = zvexx_helpers::vreg_group::<Reg, Env, _, _>(
1067 program_counter,
1068 config,
1069 vd,
1070 sew.wide().as_eew(),
1071 )?;
1072 let vs2 = zvexx_helpers::vreg_group::<Reg, Env, _, _>(
1073 program_counter,
1074 config,
1075 vs2,
1076 sew.narrow().as_eew(),
1077 )?;
1078 let vs1 = zvexx_helpers::vreg_group::<Reg, Env, _, _>(
1079 program_counter,
1080 config,
1081 vs1,
1082 sew.narrow().as_eew(),
1083 )?;
1084 zvexx_helpers::check_destination_overlap::<Reg, Env, _, _>(
1085 program_counter,
1086 vd,
1087 vs2,
1088 )?;
1089 zvexx_helpers::check_destination_overlap::<Reg, Env, _, _>(
1090 program_counter,
1091 vd,
1092 vs1,
1093 )?;
1094 zvexx_muldiv_helpers::execute_widening_op(
1095 env,
1096 vd,
1097 vs2,
1098 zvexx_muldiv_helpers::OpSrc::Vreg(vs1),
1099 vm,
1100 sew,
1101 |a, b, sew| {
1103 let sa = zvexx_muldiv_helpers::sign_extend(a, sew);
1104 let ub = b & zvexx_muldiv_helpers::sew_mask(sew);
1105 sa.cast_unsigned().wrapping_mul(ub)
1106 },
1107 );
1108 }
1109 Self::VwmulsuVx {
1110 vd,
1111 vs2,
1112 rs1: _,
1113 vm,
1114 } => {
1115 if !zvexx_helpers::non_memory_instruction_allowed::<Reg, _>(env) {
1116 ::core::hint::cold_path();
1117 return ExecutionResult::Err(ExecutionError::IllegalInstruction {
1118 address: PackedAddress::new(
1119 program_counter.old_pc(zvexx_helpers::INSTRUCTION_SIZE),
1120 ),
1121 });
1122 }
1123 let Some(config) = env.vector_config() else {
1124 ::core::hint::cold_path();
1125 return ExecutionResult::Err(ExecutionError::IllegalInstruction {
1126 address: PackedAddress::new(
1127 program_counter.old_pc(zvexx_helpers::INSTRUCTION_SIZE),
1128 ),
1129 });
1130 };
1131 let Some(sew) = zvexx_helpers::WideningSew::<Env::Hart>::new(config.vtype().vsew())
1134 else {
1135 ::core::hint::cold_path();
1136 return ExecutionResult::Err(ExecutionError::IllegalInstruction {
1137 address: PackedAddress::new(
1138 program_counter.old_pc(zvexx_helpers::INSTRUCTION_SIZE),
1139 ),
1140 });
1141 };
1142 let vd = zvexx_helpers::vreg_group::<Reg, Env, _, _>(
1143 program_counter,
1144 config,
1145 vd,
1146 sew.wide().as_eew(),
1147 )?;
1148 let vs2 = zvexx_helpers::vreg_group::<Reg, Env, _, _>(
1149 program_counter,
1150 config,
1151 vs2,
1152 sew.narrow().as_eew(),
1153 )?;
1154 zvexx_helpers::check_destination_overlap::<Reg, Env, _, _>(
1155 program_counter,
1156 vd,
1157 vs2,
1158 )?;
1159 let scalar = rs1_value.as_u64();
1161 zvexx_muldiv_helpers::execute_widening_op(
1162 env,
1163 vd,
1164 vs2,
1165 zvexx_muldiv_helpers::OpSrc::Scalar(scalar),
1166 vm,
1167 sew,
1168 |a, b, sew| {
1169 let sa = zvexx_muldiv_helpers::sign_extend(a, sew);
1170 let ub = b & zvexx_muldiv_helpers::sew_mask(sew);
1171 sa.cast_unsigned().wrapping_mul(ub)
1172 },
1173 );
1174 }
1175 Self::VwmulVv { vd, vs2, vs1, vm } => {
1177 if !zvexx_helpers::non_memory_instruction_allowed::<Reg, _>(env) {
1178 ::core::hint::cold_path();
1179 return ExecutionResult::Err(ExecutionError::IllegalInstruction {
1180 address: PackedAddress::new(
1181 program_counter.old_pc(zvexx_helpers::INSTRUCTION_SIZE),
1182 ),
1183 });
1184 }
1185 let Some(config) = env.vector_config() else {
1186 ::core::hint::cold_path();
1187 return ExecutionResult::Err(ExecutionError::IllegalInstruction {
1188 address: PackedAddress::new(
1189 program_counter.old_pc(zvexx_helpers::INSTRUCTION_SIZE),
1190 ),
1191 });
1192 };
1193 let Some(sew) = zvexx_helpers::WideningSew::<Env::Hart>::new(config.vtype().vsew())
1196 else {
1197 ::core::hint::cold_path();
1198 return ExecutionResult::Err(ExecutionError::IllegalInstruction {
1199 address: PackedAddress::new(
1200 program_counter.old_pc(zvexx_helpers::INSTRUCTION_SIZE),
1201 ),
1202 });
1203 };
1204 let vd = zvexx_helpers::vreg_group::<Reg, Env, _, _>(
1205 program_counter,
1206 config,
1207 vd,
1208 sew.wide().as_eew(),
1209 )?;
1210 let vs2 = zvexx_helpers::vreg_group::<Reg, Env, _, _>(
1211 program_counter,
1212 config,
1213 vs2,
1214 sew.narrow().as_eew(),
1215 )?;
1216 let vs1 = zvexx_helpers::vreg_group::<Reg, Env, _, _>(
1217 program_counter,
1218 config,
1219 vs1,
1220 sew.narrow().as_eew(),
1221 )?;
1222 zvexx_helpers::check_destination_overlap::<Reg, Env, _, _>(
1223 program_counter,
1224 vd,
1225 vs2,
1226 )?;
1227 zvexx_helpers::check_destination_overlap::<Reg, Env, _, _>(
1228 program_counter,
1229 vd,
1230 vs1,
1231 )?;
1232 zvexx_muldiv_helpers::execute_widening_op(
1233 env,
1234 vd,
1235 vs2,
1236 zvexx_muldiv_helpers::OpSrc::Vreg(vs1),
1237 vm,
1238 sew,
1239 |a, b, sew| {
1241 let sa = zvexx_muldiv_helpers::sign_extend(a, sew);
1242 let sb = zvexx_muldiv_helpers::sign_extend(b, sew);
1243 sa.cast_unsigned().wrapping_mul(sb.cast_unsigned())
1244 },
1245 );
1246 }
1247 Self::VwmulVx {
1248 vd,
1249 vs2,
1250 rs1: _,
1251 vm,
1252 } => {
1253 if !zvexx_helpers::non_memory_instruction_allowed::<Reg, _>(env) {
1254 ::core::hint::cold_path();
1255 return ExecutionResult::Err(ExecutionError::IllegalInstruction {
1256 address: PackedAddress::new(
1257 program_counter.old_pc(zvexx_helpers::INSTRUCTION_SIZE),
1258 ),
1259 });
1260 }
1261 let Some(config) = env.vector_config() else {
1262 ::core::hint::cold_path();
1263 return ExecutionResult::Err(ExecutionError::IllegalInstruction {
1264 address: PackedAddress::new(
1265 program_counter.old_pc(zvexx_helpers::INSTRUCTION_SIZE),
1266 ),
1267 });
1268 };
1269 let Some(sew) = zvexx_helpers::WideningSew::<Env::Hart>::new(config.vtype().vsew())
1272 else {
1273 ::core::hint::cold_path();
1274 return ExecutionResult::Err(ExecutionError::IllegalInstruction {
1275 address: PackedAddress::new(
1276 program_counter.old_pc(zvexx_helpers::INSTRUCTION_SIZE),
1277 ),
1278 });
1279 };
1280 let vd = zvexx_helpers::vreg_group::<Reg, Env, _, _>(
1281 program_counter,
1282 config,
1283 vd,
1284 sew.wide().as_eew(),
1285 )?;
1286 let vs2 = zvexx_helpers::vreg_group::<Reg, Env, _, _>(
1287 program_counter,
1288 config,
1289 vs2,
1290 sew.narrow().as_eew(),
1291 )?;
1292 zvexx_helpers::check_destination_overlap::<Reg, Env, _, _>(
1293 program_counter,
1294 vd,
1295 vs2,
1296 )?;
1297 let scalar = rs1_value.as_u64();
1299 zvexx_muldiv_helpers::execute_widening_op(
1300 env,
1301 vd,
1302 vs2,
1303 zvexx_muldiv_helpers::OpSrc::Scalar(scalar),
1304 vm,
1305 sew,
1306 |a, b, sew| {
1307 let sa = zvexx_muldiv_helpers::sign_extend(a, sew);
1308 let sb = zvexx_muldiv_helpers::sign_extend(b, sew);
1309 sa.cast_unsigned().wrapping_mul(sb.cast_unsigned())
1310 },
1311 );
1312 }
1313 Self::VmaccVv { vd, vs1, vs2, vm } => {
1315 if !zvexx_helpers::non_memory_instruction_allowed::<Reg, _>(env) {
1316 ::core::hint::cold_path();
1317 return ExecutionResult::Err(ExecutionError::IllegalInstruction {
1318 address: PackedAddress::new(
1319 program_counter.old_pc(zvexx_helpers::INSTRUCTION_SIZE),
1320 ),
1321 });
1322 }
1323 let Some(config) = env.vector_config() else {
1324 ::core::hint::cold_path();
1325 return ExecutionResult::Err(ExecutionError::IllegalInstruction {
1326 address: PackedAddress::new(
1327 program_counter.old_pc(zvexx_helpers::INSTRUCTION_SIZE),
1328 ),
1329 });
1330 };
1331 let sew = config.vtype().vsew();
1332 let vd = zvexx_helpers::vreg_group::<Reg, Env, _, _>(
1333 program_counter,
1334 config,
1335 vd,
1336 sew.as_eew(),
1337 )?;
1338 let vs2 = zvexx_helpers::vreg_group::<Reg, Env, _, _>(
1339 program_counter,
1340 config,
1341 vs2,
1342 sew.as_eew(),
1343 )?;
1344 let vs1 = zvexx_helpers::vreg_group::<Reg, Env, _, _>(
1345 program_counter,
1346 config,
1347 vs1,
1348 sew.as_eew(),
1349 )?;
1350 zvexx_muldiv_helpers::execute_muladd_op(
1351 env,
1352 vd,
1353 vs1,
1354 zvexx_muldiv_helpers::OpSrc::Vreg(vs2),
1355 vm,
1356 sew,
1357 |acc, a, b, _| acc.wrapping_add(a.wrapping_mul(b)),
1359 );
1360 }
1361 Self::VmaccVx {
1362 vd,
1363 rs1: _,
1364 vs2,
1365 vm,
1366 } => {
1367 if !zvexx_helpers::non_memory_instruction_allowed::<Reg, _>(env) {
1368 ::core::hint::cold_path();
1369 return ExecutionResult::Err(ExecutionError::IllegalInstruction {
1370 address: PackedAddress::new(
1371 program_counter.old_pc(zvexx_helpers::INSTRUCTION_SIZE),
1372 ),
1373 });
1374 }
1375 let Some(config) = env.vector_config() else {
1376 ::core::hint::cold_path();
1377 return ExecutionResult::Err(ExecutionError::IllegalInstruction {
1378 address: PackedAddress::new(
1379 program_counter.old_pc(zvexx_helpers::INSTRUCTION_SIZE),
1380 ),
1381 });
1382 };
1383 let sew = config.vtype().vsew();
1384 let vd = zvexx_helpers::vreg_group::<Reg, Env, _, _>(
1385 program_counter,
1386 config,
1387 vd,
1388 sew.as_eew(),
1389 )?;
1390 let vs2 = zvexx_helpers::vreg_group::<Reg, Env, _, _>(
1391 program_counter,
1392 config,
1393 vs2,
1394 sew.as_eew(),
1395 )?;
1396 let scalar = rs1_value.as_i64().cast_unsigned();
1397 zvexx_muldiv_helpers::execute_muladd_scalar_op(
1398 env,
1399 vd,
1400 scalar,
1401 zvexx_muldiv_helpers::OpSrc::Vreg(vs2),
1402 vm,
1403 sew,
1404 |acc, a, b, _| acc.wrapping_add(a.wrapping_mul(b)),
1405 );
1406 }
1407 Self::VnmsacVv { vd, vs1, vs2, vm } => {
1409 if !zvexx_helpers::non_memory_instruction_allowed::<Reg, _>(env) {
1410 ::core::hint::cold_path();
1411 return ExecutionResult::Err(ExecutionError::IllegalInstruction {
1412 address: PackedAddress::new(
1413 program_counter.old_pc(zvexx_helpers::INSTRUCTION_SIZE),
1414 ),
1415 });
1416 }
1417 let Some(config) = env.vector_config() else {
1418 ::core::hint::cold_path();
1419 return ExecutionResult::Err(ExecutionError::IllegalInstruction {
1420 address: PackedAddress::new(
1421 program_counter.old_pc(zvexx_helpers::INSTRUCTION_SIZE),
1422 ),
1423 });
1424 };
1425 let sew = config.vtype().vsew();
1426 let vd = zvexx_helpers::vreg_group::<Reg, Env, _, _>(
1427 program_counter,
1428 config,
1429 vd,
1430 sew.as_eew(),
1431 )?;
1432 let vs2 = zvexx_helpers::vreg_group::<Reg, Env, _, _>(
1433 program_counter,
1434 config,
1435 vs2,
1436 sew.as_eew(),
1437 )?;
1438 let vs1 = zvexx_helpers::vreg_group::<Reg, Env, _, _>(
1439 program_counter,
1440 config,
1441 vs1,
1442 sew.as_eew(),
1443 )?;
1444 zvexx_muldiv_helpers::execute_muladd_op(
1445 env,
1446 vd,
1447 vs1,
1448 zvexx_muldiv_helpers::OpSrc::Vreg(vs2),
1449 vm,
1450 sew,
1451 |acc, a, b, _| acc.wrapping_sub(a.wrapping_mul(b)),
1453 );
1454 }
1455 Self::VnmsacVx {
1456 vd,
1457 rs1: _,
1458 vs2,
1459 vm,
1460 } => {
1461 if !zvexx_helpers::non_memory_instruction_allowed::<Reg, _>(env) {
1462 ::core::hint::cold_path();
1463 return ExecutionResult::Err(ExecutionError::IllegalInstruction {
1464 address: PackedAddress::new(
1465 program_counter.old_pc(zvexx_helpers::INSTRUCTION_SIZE),
1466 ),
1467 });
1468 }
1469 let Some(config) = env.vector_config() else {
1470 ::core::hint::cold_path();
1471 return ExecutionResult::Err(ExecutionError::IllegalInstruction {
1472 address: PackedAddress::new(
1473 program_counter.old_pc(zvexx_helpers::INSTRUCTION_SIZE),
1474 ),
1475 });
1476 };
1477 let sew = config.vtype().vsew();
1478 let vd = zvexx_helpers::vreg_group::<Reg, Env, _, _>(
1479 program_counter,
1480 config,
1481 vd,
1482 sew.as_eew(),
1483 )?;
1484 let vs2 = zvexx_helpers::vreg_group::<Reg, Env, _, _>(
1485 program_counter,
1486 config,
1487 vs2,
1488 sew.as_eew(),
1489 )?;
1490 let scalar = rs1_value.as_i64().cast_unsigned();
1491 zvexx_muldiv_helpers::execute_muladd_scalar_op(
1492 env,
1493 vd,
1494 scalar,
1495 zvexx_muldiv_helpers::OpSrc::Vreg(vs2),
1496 vm,
1497 sew,
1498 |acc, a, b, _| acc.wrapping_sub(a.wrapping_mul(b)),
1499 );
1500 }
1501 Self::VmaddVv { vd, vs1, vs2, vm } => {
1503 if !zvexx_helpers::non_memory_instruction_allowed::<Reg, _>(env) {
1504 ::core::hint::cold_path();
1505 return ExecutionResult::Err(ExecutionError::IllegalInstruction {
1506 address: PackedAddress::new(
1507 program_counter.old_pc(zvexx_helpers::INSTRUCTION_SIZE),
1508 ),
1509 });
1510 }
1511 let Some(config) = env.vector_config() else {
1512 ::core::hint::cold_path();
1513 return ExecutionResult::Err(ExecutionError::IllegalInstruction {
1514 address: PackedAddress::new(
1515 program_counter.old_pc(zvexx_helpers::INSTRUCTION_SIZE),
1516 ),
1517 });
1518 };
1519 let sew = config.vtype().vsew();
1520 let vd = zvexx_helpers::vreg_group::<Reg, Env, _, _>(
1521 program_counter,
1522 config,
1523 vd,
1524 sew.as_eew(),
1525 )?;
1526 let vs2 = zvexx_helpers::vreg_group::<Reg, Env, _, _>(
1527 program_counter,
1528 config,
1529 vs2,
1530 sew.as_eew(),
1531 )?;
1532 let vs1 = zvexx_helpers::vreg_group::<Reg, Env, _, _>(
1533 program_counter,
1534 config,
1535 vs1,
1536 sew.as_eew(),
1537 )?;
1538 zvexx_muldiv_helpers::execute_muladd_op(
1539 env,
1540 vd,
1541 vs1,
1542 zvexx_muldiv_helpers::OpSrc::Vreg(vs2),
1543 vm,
1544 sew,
1545 |acc, a, b, _| a.wrapping_mul(acc).wrapping_add(b),
1547 );
1548 }
1549 Self::VmaddVx {
1550 vd,
1551 rs1: _,
1552 vs2,
1553 vm,
1554 } => {
1555 if !zvexx_helpers::non_memory_instruction_allowed::<Reg, _>(env) {
1556 ::core::hint::cold_path();
1557 return ExecutionResult::Err(ExecutionError::IllegalInstruction {
1558 address: PackedAddress::new(
1559 program_counter.old_pc(zvexx_helpers::INSTRUCTION_SIZE),
1560 ),
1561 });
1562 }
1563 let Some(config) = env.vector_config() else {
1564 ::core::hint::cold_path();
1565 return ExecutionResult::Err(ExecutionError::IllegalInstruction {
1566 address: PackedAddress::new(
1567 program_counter.old_pc(zvexx_helpers::INSTRUCTION_SIZE),
1568 ),
1569 });
1570 };
1571 let sew = config.vtype().vsew();
1572 let vd = zvexx_helpers::vreg_group::<Reg, Env, _, _>(
1573 program_counter,
1574 config,
1575 vd,
1576 sew.as_eew(),
1577 )?;
1578 let vs2 = zvexx_helpers::vreg_group::<Reg, Env, _, _>(
1579 program_counter,
1580 config,
1581 vs2,
1582 sew.as_eew(),
1583 )?;
1584 let scalar = rs1_value.as_i64().cast_unsigned();
1585 zvexx_muldiv_helpers::execute_muladd_scalar_op(
1586 env,
1587 vd,
1588 scalar,
1589 zvexx_muldiv_helpers::OpSrc::Vreg(vs2),
1590 vm,
1591 sew,
1592 |acc, a, b, _| a.wrapping_mul(acc).wrapping_add(b),
1594 );
1595 }
1596 Self::VnmsubVv { vd, vs1, vs2, vm } => {
1598 if !zvexx_helpers::non_memory_instruction_allowed::<Reg, _>(env) {
1599 ::core::hint::cold_path();
1600 return ExecutionResult::Err(ExecutionError::IllegalInstruction {
1601 address: PackedAddress::new(
1602 program_counter.old_pc(zvexx_helpers::INSTRUCTION_SIZE),
1603 ),
1604 });
1605 }
1606 let Some(config) = env.vector_config() else {
1607 ::core::hint::cold_path();
1608 return ExecutionResult::Err(ExecutionError::IllegalInstruction {
1609 address: PackedAddress::new(
1610 program_counter.old_pc(zvexx_helpers::INSTRUCTION_SIZE),
1611 ),
1612 });
1613 };
1614 let sew = config.vtype().vsew();
1615 let vd = zvexx_helpers::vreg_group::<Reg, Env, _, _>(
1616 program_counter,
1617 config,
1618 vd,
1619 sew.as_eew(),
1620 )?;
1621 let vs2 = zvexx_helpers::vreg_group::<Reg, Env, _, _>(
1622 program_counter,
1623 config,
1624 vs2,
1625 sew.as_eew(),
1626 )?;
1627 let vs1 = zvexx_helpers::vreg_group::<Reg, Env, _, _>(
1628 program_counter,
1629 config,
1630 vs1,
1631 sew.as_eew(),
1632 )?;
1633 zvexx_muldiv_helpers::execute_muladd_op(
1634 env,
1635 vd,
1636 vs1,
1637 zvexx_muldiv_helpers::OpSrc::Vreg(vs2),
1638 vm,
1639 sew,
1640 |acc, a, b, _| b.wrapping_sub(a.wrapping_mul(acc)),
1642 );
1643 }
1644 Self::VnmsubVx {
1645 vd,
1646 rs1: _,
1647 vs2,
1648 vm,
1649 } => {
1650 if !zvexx_helpers::non_memory_instruction_allowed::<Reg, _>(env) {
1651 ::core::hint::cold_path();
1652 return ExecutionResult::Err(ExecutionError::IllegalInstruction {
1653 address: PackedAddress::new(
1654 program_counter.old_pc(zvexx_helpers::INSTRUCTION_SIZE),
1655 ),
1656 });
1657 }
1658 let Some(config) = env.vector_config() else {
1659 ::core::hint::cold_path();
1660 return ExecutionResult::Err(ExecutionError::IllegalInstruction {
1661 address: PackedAddress::new(
1662 program_counter.old_pc(zvexx_helpers::INSTRUCTION_SIZE),
1663 ),
1664 });
1665 };
1666 let sew = config.vtype().vsew();
1667 let vd = zvexx_helpers::vreg_group::<Reg, Env, _, _>(
1668 program_counter,
1669 config,
1670 vd,
1671 sew.as_eew(),
1672 )?;
1673 let vs2 = zvexx_helpers::vreg_group::<Reg, Env, _, _>(
1674 program_counter,
1675 config,
1676 vs2,
1677 sew.as_eew(),
1678 )?;
1679 let scalar = rs1_value.as_i64().cast_unsigned();
1680 zvexx_muldiv_helpers::execute_muladd_scalar_op(
1681 env,
1682 vd,
1683 scalar,
1684 zvexx_muldiv_helpers::OpSrc::Vreg(vs2),
1685 vm,
1686 sew,
1687 |acc, a, b, _| b.wrapping_sub(a.wrapping_mul(acc)),
1689 );
1690 }
1691 Self::VwmaccuVv { vd, vs1, vs2, vm } => {
1693 if !zvexx_helpers::non_memory_instruction_allowed::<Reg, _>(env) {
1694 ::core::hint::cold_path();
1695 return ExecutionResult::Err(ExecutionError::IllegalInstruction {
1696 address: PackedAddress::new(
1697 program_counter.old_pc(zvexx_helpers::INSTRUCTION_SIZE),
1698 ),
1699 });
1700 }
1701 let Some(config) = env.vector_config() else {
1702 ::core::hint::cold_path();
1703 return ExecutionResult::Err(ExecutionError::IllegalInstruction {
1704 address: PackedAddress::new(
1705 program_counter.old_pc(zvexx_helpers::INSTRUCTION_SIZE),
1706 ),
1707 });
1708 };
1709 let Some(sew) = zvexx_helpers::WideningSew::<Env::Hart>::new(config.vtype().vsew())
1712 else {
1713 ::core::hint::cold_path();
1714 return ExecutionResult::Err(ExecutionError::IllegalInstruction {
1715 address: PackedAddress::new(
1716 program_counter.old_pc(zvexx_helpers::INSTRUCTION_SIZE),
1717 ),
1718 });
1719 };
1720 let vd = zvexx_helpers::vreg_group::<Reg, Env, _, _>(
1722 program_counter,
1723 config,
1724 vd,
1725 sew.wide().as_eew(),
1726 )?;
1727 let vs2 = zvexx_helpers::vreg_group::<Reg, Env, _, _>(
1728 program_counter,
1729 config,
1730 vs2,
1731 sew.narrow().as_eew(),
1732 )?;
1733 let vs1 = zvexx_helpers::vreg_group::<Reg, Env, _, _>(
1734 program_counter,
1735 config,
1736 vs1,
1737 sew.narrow().as_eew(),
1738 )?;
1739 zvexx_helpers::check_groups_disjoint::<Reg, Env, _, _>(program_counter, vd, vs2)?;
1742 zvexx_helpers::check_groups_disjoint::<Reg, Env, _, _>(program_counter, vd, vs1)?;
1743 zvexx_muldiv_helpers::execute_widening_muladd_op(
1744 env,
1745 vd,
1746 vs1,
1747 zvexx_muldiv_helpers::OpSrc::Vreg(vs2),
1748 vm,
1749 sew,
1750 |acc, a, b, sew| {
1752 let mask = zvexx_muldiv_helpers::sew_mask(sew);
1753 acc.wrapping_add((a & mask).wrapping_mul(b & mask))
1754 },
1755 );
1756 }
1757 Self::VwmaccuVx {
1758 vd,
1759 rs1: _,
1760 vs2,
1761 vm,
1762 } => {
1763 if !zvexx_helpers::non_memory_instruction_allowed::<Reg, _>(env) {
1764 ::core::hint::cold_path();
1765 return ExecutionResult::Err(ExecutionError::IllegalInstruction {
1766 address: PackedAddress::new(
1767 program_counter.old_pc(zvexx_helpers::INSTRUCTION_SIZE),
1768 ),
1769 });
1770 }
1771 let Some(config) = env.vector_config() else {
1772 ::core::hint::cold_path();
1773 return ExecutionResult::Err(ExecutionError::IllegalInstruction {
1774 address: PackedAddress::new(
1775 program_counter.old_pc(zvexx_helpers::INSTRUCTION_SIZE),
1776 ),
1777 });
1778 };
1779 let Some(sew) = zvexx_helpers::WideningSew::<Env::Hart>::new(config.vtype().vsew())
1782 else {
1783 ::core::hint::cold_path();
1784 return ExecutionResult::Err(ExecutionError::IllegalInstruction {
1785 address: PackedAddress::new(
1786 program_counter.old_pc(zvexx_helpers::INSTRUCTION_SIZE),
1787 ),
1788 });
1789 };
1790 let vd = zvexx_helpers::vreg_group::<Reg, Env, _, _>(
1791 program_counter,
1792 config,
1793 vd,
1794 sew.wide().as_eew(),
1795 )?;
1796 let vs2 = zvexx_helpers::vreg_group::<Reg, Env, _, _>(
1797 program_counter,
1798 config,
1799 vs2,
1800 sew.narrow().as_eew(),
1801 )?;
1802 zvexx_helpers::check_groups_disjoint::<Reg, Env, _, _>(program_counter, vd, vs2)?;
1805 let scalar = rs1_value.as_u64();
1806 zvexx_muldiv_helpers::execute_widening_muladd_scalar_op(
1807 env,
1808 vd,
1809 scalar,
1810 zvexx_muldiv_helpers::OpSrc::Vreg(vs2),
1811 vm,
1812 sew,
1813 |acc, a, b, sew| {
1814 let mask = zvexx_muldiv_helpers::sew_mask(sew);
1815 acc.wrapping_add((a & mask).wrapping_mul(b & mask))
1816 },
1817 );
1818 }
1819 Self::VwmaccVv { vd, vs1, vs2, vm } => {
1821 if !zvexx_helpers::non_memory_instruction_allowed::<Reg, _>(env) {
1822 ::core::hint::cold_path();
1823 return ExecutionResult::Err(ExecutionError::IllegalInstruction {
1824 address: PackedAddress::new(
1825 program_counter.old_pc(zvexx_helpers::INSTRUCTION_SIZE),
1826 ),
1827 });
1828 }
1829 let Some(config) = env.vector_config() else {
1830 ::core::hint::cold_path();
1831 return ExecutionResult::Err(ExecutionError::IllegalInstruction {
1832 address: PackedAddress::new(
1833 program_counter.old_pc(zvexx_helpers::INSTRUCTION_SIZE),
1834 ),
1835 });
1836 };
1837 let Some(sew) = zvexx_helpers::WideningSew::<Env::Hart>::new(config.vtype().vsew())
1840 else {
1841 ::core::hint::cold_path();
1842 return ExecutionResult::Err(ExecutionError::IllegalInstruction {
1843 address: PackedAddress::new(
1844 program_counter.old_pc(zvexx_helpers::INSTRUCTION_SIZE),
1845 ),
1846 });
1847 };
1848 let vd = zvexx_helpers::vreg_group::<Reg, Env, _, _>(
1849 program_counter,
1850 config,
1851 vd,
1852 sew.wide().as_eew(),
1853 )?;
1854 let vs2 = zvexx_helpers::vreg_group::<Reg, Env, _, _>(
1855 program_counter,
1856 config,
1857 vs2,
1858 sew.narrow().as_eew(),
1859 )?;
1860 let vs1 = zvexx_helpers::vreg_group::<Reg, Env, _, _>(
1861 program_counter,
1862 config,
1863 vs1,
1864 sew.narrow().as_eew(),
1865 )?;
1866 zvexx_helpers::check_groups_disjoint::<Reg, Env, _, _>(program_counter, vd, vs2)?;
1869 zvexx_helpers::check_groups_disjoint::<Reg, Env, _, _>(program_counter, vd, vs1)?;
1870 zvexx_muldiv_helpers::execute_widening_muladd_op(
1871 env,
1872 vd,
1873 vs1,
1874 zvexx_muldiv_helpers::OpSrc::Vreg(vs2),
1875 vm,
1876 sew,
1877 |acc, a, b, sew| {
1879 let sa = zvexx_muldiv_helpers::sign_extend(a, sew);
1880 let sb = zvexx_muldiv_helpers::sign_extend(b, sew);
1881 acc.wrapping_add(sa.cast_unsigned().wrapping_mul(sb.cast_unsigned()))
1882 },
1883 );
1884 }
1885 Self::VwmaccVx {
1886 vd,
1887 rs1: _,
1888 vs2,
1889 vm,
1890 } => {
1891 if !zvexx_helpers::non_memory_instruction_allowed::<Reg, _>(env) {
1892 ::core::hint::cold_path();
1893 return ExecutionResult::Err(ExecutionError::IllegalInstruction {
1894 address: PackedAddress::new(
1895 program_counter.old_pc(zvexx_helpers::INSTRUCTION_SIZE),
1896 ),
1897 });
1898 }
1899 let Some(config) = env.vector_config() else {
1900 ::core::hint::cold_path();
1901 return ExecutionResult::Err(ExecutionError::IllegalInstruction {
1902 address: PackedAddress::new(
1903 program_counter.old_pc(zvexx_helpers::INSTRUCTION_SIZE),
1904 ),
1905 });
1906 };
1907 let Some(sew) = zvexx_helpers::WideningSew::<Env::Hart>::new(config.vtype().vsew())
1910 else {
1911 ::core::hint::cold_path();
1912 return ExecutionResult::Err(ExecutionError::IllegalInstruction {
1913 address: PackedAddress::new(
1914 program_counter.old_pc(zvexx_helpers::INSTRUCTION_SIZE),
1915 ),
1916 });
1917 };
1918 let vd = zvexx_helpers::vreg_group::<Reg, Env, _, _>(
1919 program_counter,
1920 config,
1921 vd,
1922 sew.wide().as_eew(),
1923 )?;
1924 let vs2 = zvexx_helpers::vreg_group::<Reg, Env, _, _>(
1925 program_counter,
1926 config,
1927 vs2,
1928 sew.narrow().as_eew(),
1929 )?;
1930 zvexx_helpers::check_groups_disjoint::<Reg, Env, _, _>(program_counter, vd, vs2)?;
1933 let scalar = rs1_value.as_u64();
1934 zvexx_muldiv_helpers::execute_widening_muladd_scalar_op(
1935 env,
1936 vd,
1937 scalar,
1938 zvexx_muldiv_helpers::OpSrc::Vreg(vs2),
1939 vm,
1940 sew,
1941 |acc, a, b, sew| {
1942 let sa = zvexx_muldiv_helpers::sign_extend(a, sew);
1943 let sb = zvexx_muldiv_helpers::sign_extend(b, sew);
1944 acc.wrapping_add(sa.cast_unsigned().wrapping_mul(sb.cast_unsigned()))
1945 },
1946 );
1947 }
1948 Self::VwmaccsuVv { vd, vs1, vs2, vm } => {
1950 if !zvexx_helpers::non_memory_instruction_allowed::<Reg, _>(env) {
1951 ::core::hint::cold_path();
1952 return ExecutionResult::Err(ExecutionError::IllegalInstruction {
1953 address: PackedAddress::new(
1954 program_counter.old_pc(zvexx_helpers::INSTRUCTION_SIZE),
1955 ),
1956 });
1957 }
1958 let Some(config) = env.vector_config() else {
1959 ::core::hint::cold_path();
1960 return ExecutionResult::Err(ExecutionError::IllegalInstruction {
1961 address: PackedAddress::new(
1962 program_counter.old_pc(zvexx_helpers::INSTRUCTION_SIZE),
1963 ),
1964 });
1965 };
1966 let Some(sew) = zvexx_helpers::WideningSew::<Env::Hart>::new(config.vtype().vsew())
1969 else {
1970 ::core::hint::cold_path();
1971 return ExecutionResult::Err(ExecutionError::IllegalInstruction {
1972 address: PackedAddress::new(
1973 program_counter.old_pc(zvexx_helpers::INSTRUCTION_SIZE),
1974 ),
1975 });
1976 };
1977 let vd = zvexx_helpers::vreg_group::<Reg, Env, _, _>(
1978 program_counter,
1979 config,
1980 vd,
1981 sew.wide().as_eew(),
1982 )?;
1983 let vs2 = zvexx_helpers::vreg_group::<Reg, Env, _, _>(
1984 program_counter,
1985 config,
1986 vs2,
1987 sew.narrow().as_eew(),
1988 )?;
1989 let vs1 = zvexx_helpers::vreg_group::<Reg, Env, _, _>(
1990 program_counter,
1991 config,
1992 vs1,
1993 sew.narrow().as_eew(),
1994 )?;
1995 zvexx_helpers::check_groups_disjoint::<Reg, Env, _, _>(program_counter, vd, vs2)?;
1998 zvexx_helpers::check_groups_disjoint::<Reg, Env, _, _>(program_counter, vd, vs1)?;
1999 zvexx_muldiv_helpers::execute_widening_muladd_op(
2000 env,
2001 vd,
2002 vs1,
2003 zvexx_muldiv_helpers::OpSrc::Vreg(vs2),
2004 vm,
2005 sew,
2006 |acc, a, b, sew| {
2008 let sa = zvexx_muldiv_helpers::sign_extend(a, sew);
2009 let ub = b & zvexx_muldiv_helpers::sew_mask(sew);
2010 acc.wrapping_add(sa.cast_unsigned().wrapping_mul(ub))
2011 },
2012 );
2013 }
2014 Self::VwmaccsuVx {
2015 vd,
2016 rs1: _,
2017 vs2,
2018 vm,
2019 } => {
2020 if !zvexx_helpers::non_memory_instruction_allowed::<Reg, _>(env) {
2021 ::core::hint::cold_path();
2022 return ExecutionResult::Err(ExecutionError::IllegalInstruction {
2023 address: PackedAddress::new(
2024 program_counter.old_pc(zvexx_helpers::INSTRUCTION_SIZE),
2025 ),
2026 });
2027 }
2028 let Some(config) = env.vector_config() else {
2029 ::core::hint::cold_path();
2030 return ExecutionResult::Err(ExecutionError::IllegalInstruction {
2031 address: PackedAddress::new(
2032 program_counter.old_pc(zvexx_helpers::INSTRUCTION_SIZE),
2033 ),
2034 });
2035 };
2036 let Some(sew) = zvexx_helpers::WideningSew::<Env::Hart>::new(config.vtype().vsew())
2039 else {
2040 ::core::hint::cold_path();
2041 return ExecutionResult::Err(ExecutionError::IllegalInstruction {
2042 address: PackedAddress::new(
2043 program_counter.old_pc(zvexx_helpers::INSTRUCTION_SIZE),
2044 ),
2045 });
2046 };
2047 let vd = zvexx_helpers::vreg_group::<Reg, Env, _, _>(
2048 program_counter,
2049 config,
2050 vd,
2051 sew.wide().as_eew(),
2052 )?;
2053 let vs2 = zvexx_helpers::vreg_group::<Reg, Env, _, _>(
2054 program_counter,
2055 config,
2056 vs2,
2057 sew.narrow().as_eew(),
2058 )?;
2059 zvexx_helpers::check_groups_disjoint::<Reg, Env, _, _>(program_counter, vd, vs2)?;
2062 let scalar = rs1_value.as_u64();
2064 zvexx_muldiv_helpers::execute_widening_muladd_scalar_op(
2065 env,
2066 vd,
2067 scalar,
2068 zvexx_muldiv_helpers::OpSrc::Vreg(vs2),
2069 vm,
2070 sew,
2071 |acc, a, b, sew| {
2075 let sa = zvexx_muldiv_helpers::sign_extend(a, sew);
2076 let ub = b & zvexx_muldiv_helpers::sew_mask(sew);
2077 acc.wrapping_add(sa.cast_unsigned().wrapping_mul(ub))
2078 },
2079 );
2080 }
2081 Self::VwmaccusVx {
2083 vd,
2084 rs1: _,
2085 vs2,
2086 vm,
2087 } => {
2088 if !zvexx_helpers::non_memory_instruction_allowed::<Reg, _>(env) {
2089 ::core::hint::cold_path();
2090 return ExecutionResult::Err(ExecutionError::IllegalInstruction {
2091 address: PackedAddress::new(
2092 program_counter.old_pc(zvexx_helpers::INSTRUCTION_SIZE),
2093 ),
2094 });
2095 }
2096 let Some(config) = env.vector_config() else {
2097 ::core::hint::cold_path();
2098 return ExecutionResult::Err(ExecutionError::IllegalInstruction {
2099 address: PackedAddress::new(
2100 program_counter.old_pc(zvexx_helpers::INSTRUCTION_SIZE),
2101 ),
2102 });
2103 };
2104 let Some(sew) = zvexx_helpers::WideningSew::<Env::Hart>::new(config.vtype().vsew())
2107 else {
2108 ::core::hint::cold_path();
2109 return ExecutionResult::Err(ExecutionError::IllegalInstruction {
2110 address: PackedAddress::new(
2111 program_counter.old_pc(zvexx_helpers::INSTRUCTION_SIZE),
2112 ),
2113 });
2114 };
2115 let vd = zvexx_helpers::vreg_group::<Reg, Env, _, _>(
2116 program_counter,
2117 config,
2118 vd,
2119 sew.wide().as_eew(),
2120 )?;
2121 let vs2 = zvexx_helpers::vreg_group::<Reg, Env, _, _>(
2122 program_counter,
2123 config,
2124 vs2,
2125 sew.narrow().as_eew(),
2126 )?;
2127 zvexx_helpers::check_groups_disjoint::<Reg, Env, _, _>(program_counter, vd, vs2)?;
2130 let scalar = rs1_value.as_u64();
2132 zvexx_muldiv_helpers::execute_widening_muladd_scalar_op(
2133 env,
2134 vd,
2135 scalar,
2136 zvexx_muldiv_helpers::OpSrc::Vreg(vs2),
2137 vm,
2138 sew,
2139 |acc, a, b, sew| {
2143 let ua = a & zvexx_muldiv_helpers::sew_mask(sew);
2144 let sb = zvexx_muldiv_helpers::sign_extend(b, sew);
2145 acc.wrapping_add(sb.cast_unsigned().wrapping_mul(ua))
2146 },
2147 );
2148 }
2149 }
2150
2151 ExecutionResult::ContinueNoWrite
2152 }
2153}