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