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