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