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