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