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