1#[cfg(test)]
4mod tests;
5pub mod zvexx_fixed_point_helpers;
6
7use crate::v::vector_registers::VectorRegistersExt;
8use crate::v::zvexx::zvexx_helpers;
9use crate::{
10 ExecutableInstruction, ExecutableInstructionCsr, ExecutableInstructionOperands, ExecutionError,
11 ExecutionResult, FetchInstructionResult, InstructionFetcher, OpaqueThreadedExecutionResult,
12 PackedAddress, ProgramCounter, RegisterFile, Rs1Rs2OperandValues, Rs1Rs2Operands,
13 ThreadedExecutableInstruction, ThreadedExecutionResult, VirtualMemory,
14};
15use ab_riscv_macros::instruction_execution;
16use ab_riscv_primitives::prelude::*;
17
18#[instruction_execution]
19const impl<Reg> ExecutableInstructionOperands for ZveXxFixedPointInstruction<Reg> where Reg: Register
20{}
21
22#[instruction_execution]
23const impl<Reg, Env> ExecutableInstructionCsr<Env> for ZveXxFixedPointInstruction<Reg> where
24 Reg: Register
25{
26}
27
28#[instruction_execution]
29impl<Reg, Regs, Env, Memory, PC> ExecutableInstruction<Regs, Env, Memory, PC>
30 for ZveXxFixedPointInstruction<Reg>
31where
32 Reg: Register,
33 Regs: RegisterFile<Reg>,
34 Env: VectorRegistersExt<Reg>,
35 [(); SUPPORTED_ELEN_VLEN::<{ Env::ELEN }, { Env::VLEN }>]:,
36 Memory: VirtualMemory,
37 PC: ProgramCounter<Reg::Type, Memory>,
38{
39 #[inline(always)]
40 #[cfg_attr(feature = "no-panic", no_panic_const::no_panic)]
41 fn execute(
42 self,
43 Rs1Rs2OperandValues {
44 rs1_value,
45 rs2_value: _,
46 }: Rs1Rs2OperandValues<<Self::Reg as Register>::Type>,
47 _regs: &mut Regs,
48 env: &mut Env,
49 _memory: &mut Memory,
50 program_counter: &mut PC,
51 ) -> ExecutionResult<Self::Reg> {
52 match self {
53 Self::VsadduVv { vd, vs2, vs1, vm } => {
55 if !env.vector_instructions_allowed() {
56 ::core::hint::cold_path();
57 return ExecutionResult::Err(ExecutionError::IllegalInstruction {
58 address: PackedAddress::new(
59 program_counter.old_pc(zvexx_helpers::INSTRUCTION_SIZE),
60 ),
61 });
62 }
63 let Some(vtype) = env.vtype() else {
64 ::core::hint::cold_path();
65 return ExecutionResult::Err(ExecutionError::IllegalInstruction {
66 address: PackedAddress::new(
67 program_counter.old_pc(zvexx_helpers::INSTRUCTION_SIZE),
68 ),
69 });
70 };
71 let group_regs = vtype.vlmul().register_count();
72 zvexx_fixed_point_helpers::check_vreg_group_alignment::<Reg, _, _>(
73 program_counter,
74 vd,
75 group_regs,
76 )?;
77 zvexx_fixed_point_helpers::check_vreg_group_alignment::<Reg, _, _>(
78 program_counter,
79 vs2,
80 group_regs,
81 )?;
82 zvexx_fixed_point_helpers::check_vreg_group_alignment::<Reg, _, _>(
83 program_counter,
84 vs1,
85 group_regs,
86 )?;
87 if !vm && vd == VReg::V0 {
88 ::core::hint::cold_path();
89 return ExecutionResult::Err(ExecutionError::IllegalInstruction {
90 address: PackedAddress::new(
91 program_counter.old_pc(zvexx_helpers::INSTRUCTION_SIZE),
92 ),
93 });
94 }
95 let sew = vtype.vsew();
96 unsafe {
98 zvexx_fixed_point_helpers::execute_fixed_point_op(
99 env,
100 vd,
101 vs2,
102 zvexx_fixed_point_helpers::OpSrc::Vreg(vs1),
103 vm,
104 sew,
105 |a, b, sew, _vxrm, vxsat| {
106 zvexx_fixed_point_helpers::sat_addu(a, b, sew, vxsat)
107 },
108 );
109 }
110 }
111 Self::VsadduVx {
112 vd,
113 vs2,
114 rs1: _,
115 vm,
116 } => {
117 if !env.vector_instructions_allowed() {
118 ::core::hint::cold_path();
119 return ExecutionResult::Err(ExecutionError::IllegalInstruction {
120 address: PackedAddress::new(
121 program_counter.old_pc(zvexx_helpers::INSTRUCTION_SIZE),
122 ),
123 });
124 }
125 let Some(vtype) = env.vtype() else {
126 ::core::hint::cold_path();
127 return ExecutionResult::Err(ExecutionError::IllegalInstruction {
128 address: PackedAddress::new(
129 program_counter.old_pc(zvexx_helpers::INSTRUCTION_SIZE),
130 ),
131 });
132 };
133 let group_regs = vtype.vlmul().register_count();
134 zvexx_fixed_point_helpers::check_vreg_group_alignment::<Reg, _, _>(
135 program_counter,
136 vd,
137 group_regs,
138 )?;
139 zvexx_fixed_point_helpers::check_vreg_group_alignment::<Reg, _, _>(
140 program_counter,
141 vs2,
142 group_regs,
143 )?;
144 if !vm && vd == VReg::V0 {
145 ::core::hint::cold_path();
146 return ExecutionResult::Err(ExecutionError::IllegalInstruction {
147 address: PackedAddress::new(
148 program_counter.old_pc(zvexx_helpers::INSTRUCTION_SIZE),
149 ),
150 });
151 }
152 let sew = vtype.vsew();
153 let scalar = rs1_value.as_i64().cast_unsigned();
154 unsafe {
156 zvexx_fixed_point_helpers::execute_fixed_point_op(
157 env,
158 vd,
159 vs2,
160 zvexx_fixed_point_helpers::OpSrc::Scalar(scalar),
161 vm,
162 sew,
163 |a, b, sew, _vxrm, vxsat| {
164 zvexx_fixed_point_helpers::sat_addu(a, b, sew, vxsat)
165 },
166 );
167 }
168 }
169 Self::VsadduVi { vd, vs2, imm, vm } => {
170 if !env.vector_instructions_allowed() {
171 ::core::hint::cold_path();
172 return ExecutionResult::Err(ExecutionError::IllegalInstruction {
173 address: PackedAddress::new(
174 program_counter.old_pc(zvexx_helpers::INSTRUCTION_SIZE),
175 ),
176 });
177 }
178 let Some(vtype) = env.vtype() else {
179 ::core::hint::cold_path();
180 return ExecutionResult::Err(ExecutionError::IllegalInstruction {
181 address: PackedAddress::new(
182 program_counter.old_pc(zvexx_helpers::INSTRUCTION_SIZE),
183 ),
184 });
185 };
186 let group_regs = vtype.vlmul().register_count();
187 zvexx_fixed_point_helpers::check_vreg_group_alignment::<Reg, _, _>(
188 program_counter,
189 vd,
190 group_regs,
191 )?;
192 zvexx_fixed_point_helpers::check_vreg_group_alignment::<Reg, _, _>(
193 program_counter,
194 vs2,
195 group_regs,
196 )?;
197 if !vm && vd == VReg::V0 {
198 ::core::hint::cold_path();
199 return ExecutionResult::Err(ExecutionError::IllegalInstruction {
200 address: PackedAddress::new(
201 program_counter.old_pc(zvexx_helpers::INSTRUCTION_SIZE),
202 ),
203 });
204 }
205 let sew = vtype.vsew();
206 let scalar = i64::from(imm).cast_unsigned();
210 unsafe {
211 zvexx_fixed_point_helpers::execute_fixed_point_op(
212 env,
213 vd,
214 vs2,
215 zvexx_fixed_point_helpers::OpSrc::Scalar(scalar),
216 vm,
217 sew,
218 |a, b, sew, _vxrm, vxsat| {
219 zvexx_fixed_point_helpers::sat_addu(a, b, sew, vxsat)
220 },
221 );
222 }
223 }
224 Self::VsaddVv { vd, vs2, vs1, vm } => {
226 if !env.vector_instructions_allowed() {
227 ::core::hint::cold_path();
228 return ExecutionResult::Err(ExecutionError::IllegalInstruction {
229 address: PackedAddress::new(
230 program_counter.old_pc(zvexx_helpers::INSTRUCTION_SIZE),
231 ),
232 });
233 }
234 let Some(vtype) = env.vtype() else {
235 ::core::hint::cold_path();
236 return ExecutionResult::Err(ExecutionError::IllegalInstruction {
237 address: PackedAddress::new(
238 program_counter.old_pc(zvexx_helpers::INSTRUCTION_SIZE),
239 ),
240 });
241 };
242 let group_regs = vtype.vlmul().register_count();
243 zvexx_fixed_point_helpers::check_vreg_group_alignment::<Reg, _, _>(
244 program_counter,
245 vd,
246 group_regs,
247 )?;
248 zvexx_fixed_point_helpers::check_vreg_group_alignment::<Reg, _, _>(
249 program_counter,
250 vs2,
251 group_regs,
252 )?;
253 zvexx_fixed_point_helpers::check_vreg_group_alignment::<Reg, _, _>(
254 program_counter,
255 vs1,
256 group_regs,
257 )?;
258 if !vm && vd == VReg::V0 {
259 ::core::hint::cold_path();
260 return ExecutionResult::Err(ExecutionError::IllegalInstruction {
261 address: PackedAddress::new(
262 program_counter.old_pc(zvexx_helpers::INSTRUCTION_SIZE),
263 ),
264 });
265 }
266 let sew = vtype.vsew();
267 unsafe {
269 zvexx_fixed_point_helpers::execute_fixed_point_op(
270 env,
271 vd,
272 vs2,
273 zvexx_fixed_point_helpers::OpSrc::Vreg(vs1),
274 vm,
275 sew,
276 |a, b, sew, _vxrm, vxsat| {
277 zvexx_fixed_point_helpers::sat_add(a, b, sew, vxsat)
278 },
279 );
280 }
281 }
282 Self::VsaddVx {
283 vd,
284 vs2,
285 rs1: _,
286 vm,
287 } => {
288 if !env.vector_instructions_allowed() {
289 ::core::hint::cold_path();
290 return ExecutionResult::Err(ExecutionError::IllegalInstruction {
291 address: PackedAddress::new(
292 program_counter.old_pc(zvexx_helpers::INSTRUCTION_SIZE),
293 ),
294 });
295 }
296 let Some(vtype) = env.vtype() else {
297 ::core::hint::cold_path();
298 return ExecutionResult::Err(ExecutionError::IllegalInstruction {
299 address: PackedAddress::new(
300 program_counter.old_pc(zvexx_helpers::INSTRUCTION_SIZE),
301 ),
302 });
303 };
304 let group_regs = vtype.vlmul().register_count();
305 zvexx_fixed_point_helpers::check_vreg_group_alignment::<Reg, _, _>(
306 program_counter,
307 vd,
308 group_regs,
309 )?;
310 zvexx_fixed_point_helpers::check_vreg_group_alignment::<Reg, _, _>(
311 program_counter,
312 vs2,
313 group_regs,
314 )?;
315 if !vm && vd == VReg::V0 {
316 ::core::hint::cold_path();
317 return ExecutionResult::Err(ExecutionError::IllegalInstruction {
318 address: PackedAddress::new(
319 program_counter.old_pc(zvexx_helpers::INSTRUCTION_SIZE),
320 ),
321 });
322 }
323 let sew = vtype.vsew();
324 let scalar = rs1_value.as_i64().cast_unsigned();
325 unsafe {
327 zvexx_fixed_point_helpers::execute_fixed_point_op(
328 env,
329 vd,
330 vs2,
331 zvexx_fixed_point_helpers::OpSrc::Scalar(scalar),
332 vm,
333 sew,
334 |a, b, sew, _vxrm, vxsat| {
335 zvexx_fixed_point_helpers::sat_add(a, b, sew, vxsat)
336 },
337 );
338 }
339 }
340 Self::VsaddVi { vd, vs2, imm, vm } => {
341 if !env.vector_instructions_allowed() {
342 ::core::hint::cold_path();
343 return ExecutionResult::Err(ExecutionError::IllegalInstruction {
344 address: PackedAddress::new(
345 program_counter.old_pc(zvexx_helpers::INSTRUCTION_SIZE),
346 ),
347 });
348 }
349 let Some(vtype) = env.vtype() else {
350 ::core::hint::cold_path();
351 return ExecutionResult::Err(ExecutionError::IllegalInstruction {
352 address: PackedAddress::new(
353 program_counter.old_pc(zvexx_helpers::INSTRUCTION_SIZE),
354 ),
355 });
356 };
357 let group_regs = vtype.vlmul().register_count();
358 zvexx_fixed_point_helpers::check_vreg_group_alignment::<Reg, _, _>(
359 program_counter,
360 vd,
361 group_regs,
362 )?;
363 zvexx_fixed_point_helpers::check_vreg_group_alignment::<Reg, _, _>(
364 program_counter,
365 vs2,
366 group_regs,
367 )?;
368 if !vm && vd == VReg::V0 {
369 ::core::hint::cold_path();
370 return ExecutionResult::Err(ExecutionError::IllegalInstruction {
371 address: PackedAddress::new(
372 program_counter.old_pc(zvexx_helpers::INSTRUCTION_SIZE),
373 ),
374 });
375 }
376 let sew = vtype.vsew();
377 let scalar = i64::from(imm).cast_unsigned();
379 unsafe {
381 zvexx_fixed_point_helpers::execute_fixed_point_op(
382 env,
383 vd,
384 vs2,
385 zvexx_fixed_point_helpers::OpSrc::Scalar(scalar),
386 vm,
387 sew,
388 |a, b, sew, _vxrm, vxsat| {
389 zvexx_fixed_point_helpers::sat_add(a, b, sew, vxsat)
390 },
391 );
392 }
393 }
394 Self::VssubuVv { vd, vs2, vs1, vm } => {
396 if !env.vector_instructions_allowed() {
397 ::core::hint::cold_path();
398 return ExecutionResult::Err(ExecutionError::IllegalInstruction {
399 address: PackedAddress::new(
400 program_counter.old_pc(zvexx_helpers::INSTRUCTION_SIZE),
401 ),
402 });
403 }
404 let Some(vtype) = env.vtype() else {
405 ::core::hint::cold_path();
406 return ExecutionResult::Err(ExecutionError::IllegalInstruction {
407 address: PackedAddress::new(
408 program_counter.old_pc(zvexx_helpers::INSTRUCTION_SIZE),
409 ),
410 });
411 };
412 let group_regs = vtype.vlmul().register_count();
413 zvexx_fixed_point_helpers::check_vreg_group_alignment::<Reg, _, _>(
414 program_counter,
415 vd,
416 group_regs,
417 )?;
418 zvexx_fixed_point_helpers::check_vreg_group_alignment::<Reg, _, _>(
419 program_counter,
420 vs2,
421 group_regs,
422 )?;
423 zvexx_fixed_point_helpers::check_vreg_group_alignment::<Reg, _, _>(
424 program_counter,
425 vs1,
426 group_regs,
427 )?;
428 if !vm && vd == VReg::V0 {
429 ::core::hint::cold_path();
430 return ExecutionResult::Err(ExecutionError::IllegalInstruction {
431 address: PackedAddress::new(
432 program_counter.old_pc(zvexx_helpers::INSTRUCTION_SIZE),
433 ),
434 });
435 }
436 let sew = vtype.vsew();
437 unsafe {
439 zvexx_fixed_point_helpers::execute_fixed_point_op(
440 env,
441 vd,
442 vs2,
443 zvexx_fixed_point_helpers::OpSrc::Vreg(vs1),
444 vm,
445 sew,
446 |a, b, sew, _vxrm, vxsat| {
447 zvexx_fixed_point_helpers::sat_subu(a, b, sew, vxsat)
448 },
449 );
450 }
451 }
452 Self::VssubuVx {
453 vd,
454 vs2,
455 rs1: _,
456 vm,
457 } => {
458 if !env.vector_instructions_allowed() {
459 ::core::hint::cold_path();
460 return ExecutionResult::Err(ExecutionError::IllegalInstruction {
461 address: PackedAddress::new(
462 program_counter.old_pc(zvexx_helpers::INSTRUCTION_SIZE),
463 ),
464 });
465 }
466 let Some(vtype) = env.vtype() else {
467 ::core::hint::cold_path();
468 return ExecutionResult::Err(ExecutionError::IllegalInstruction {
469 address: PackedAddress::new(
470 program_counter.old_pc(zvexx_helpers::INSTRUCTION_SIZE),
471 ),
472 });
473 };
474 let group_regs = vtype.vlmul().register_count();
475 zvexx_fixed_point_helpers::check_vreg_group_alignment::<Reg, _, _>(
476 program_counter,
477 vd,
478 group_regs,
479 )?;
480 zvexx_fixed_point_helpers::check_vreg_group_alignment::<Reg, _, _>(
481 program_counter,
482 vs2,
483 group_regs,
484 )?;
485 if !vm && vd == VReg::V0 {
486 ::core::hint::cold_path();
487 return ExecutionResult::Err(ExecutionError::IllegalInstruction {
488 address: PackedAddress::new(
489 program_counter.old_pc(zvexx_helpers::INSTRUCTION_SIZE),
490 ),
491 });
492 }
493 let sew = vtype.vsew();
494 let scalar = rs1_value.as_i64().cast_unsigned();
495 unsafe {
497 zvexx_fixed_point_helpers::execute_fixed_point_op(
498 env,
499 vd,
500 vs2,
501 zvexx_fixed_point_helpers::OpSrc::Scalar(scalar),
502 vm,
503 sew,
504 |a, b, sew, _vxrm, vxsat| {
505 zvexx_fixed_point_helpers::sat_subu(a, b, sew, vxsat)
506 },
507 );
508 }
509 }
510 Self::VssubVv { vd, vs2, vs1, vm } => {
512 if !env.vector_instructions_allowed() {
513 ::core::hint::cold_path();
514 return ExecutionResult::Err(ExecutionError::IllegalInstruction {
515 address: PackedAddress::new(
516 program_counter.old_pc(zvexx_helpers::INSTRUCTION_SIZE),
517 ),
518 });
519 }
520 let Some(vtype) = env.vtype() else {
521 ::core::hint::cold_path();
522 return ExecutionResult::Err(ExecutionError::IllegalInstruction {
523 address: PackedAddress::new(
524 program_counter.old_pc(zvexx_helpers::INSTRUCTION_SIZE),
525 ),
526 });
527 };
528 let group_regs = vtype.vlmul().register_count();
529 zvexx_fixed_point_helpers::check_vreg_group_alignment::<Reg, _, _>(
530 program_counter,
531 vd,
532 group_regs,
533 )?;
534 zvexx_fixed_point_helpers::check_vreg_group_alignment::<Reg, _, _>(
535 program_counter,
536 vs2,
537 group_regs,
538 )?;
539 zvexx_fixed_point_helpers::check_vreg_group_alignment::<Reg, _, _>(
540 program_counter,
541 vs1,
542 group_regs,
543 )?;
544 if !vm && vd == VReg::V0 {
545 ::core::hint::cold_path();
546 return ExecutionResult::Err(ExecutionError::IllegalInstruction {
547 address: PackedAddress::new(
548 program_counter.old_pc(zvexx_helpers::INSTRUCTION_SIZE),
549 ),
550 });
551 }
552 let sew = vtype.vsew();
553 unsafe {
555 zvexx_fixed_point_helpers::execute_fixed_point_op(
556 env,
557 vd,
558 vs2,
559 zvexx_fixed_point_helpers::OpSrc::Vreg(vs1),
560 vm,
561 sew,
562 |a, b, sew, _vxrm, vxsat| {
563 zvexx_fixed_point_helpers::sat_sub(a, b, sew, vxsat)
564 },
565 );
566 }
567 }
568 Self::VssubVx {
569 vd,
570 vs2,
571 rs1: _,
572 vm,
573 } => {
574 if !env.vector_instructions_allowed() {
575 ::core::hint::cold_path();
576 return ExecutionResult::Err(ExecutionError::IllegalInstruction {
577 address: PackedAddress::new(
578 program_counter.old_pc(zvexx_helpers::INSTRUCTION_SIZE),
579 ),
580 });
581 }
582 let Some(vtype) = env.vtype() else {
583 ::core::hint::cold_path();
584 return ExecutionResult::Err(ExecutionError::IllegalInstruction {
585 address: PackedAddress::new(
586 program_counter.old_pc(zvexx_helpers::INSTRUCTION_SIZE),
587 ),
588 });
589 };
590 let group_regs = vtype.vlmul().register_count();
591 zvexx_fixed_point_helpers::check_vreg_group_alignment::<Reg, _, _>(
592 program_counter,
593 vd,
594 group_regs,
595 )?;
596 zvexx_fixed_point_helpers::check_vreg_group_alignment::<Reg, _, _>(
597 program_counter,
598 vs2,
599 group_regs,
600 )?;
601 if !vm && vd == VReg::V0 {
602 ::core::hint::cold_path();
603 return ExecutionResult::Err(ExecutionError::IllegalInstruction {
604 address: PackedAddress::new(
605 program_counter.old_pc(zvexx_helpers::INSTRUCTION_SIZE),
606 ),
607 });
608 }
609 let sew = vtype.vsew();
610 let scalar = rs1_value.as_i64().cast_unsigned();
611 unsafe {
613 zvexx_fixed_point_helpers::execute_fixed_point_op(
614 env,
615 vd,
616 vs2,
617 zvexx_fixed_point_helpers::OpSrc::Scalar(scalar),
618 vm,
619 sew,
620 |a, b, sew, _vxrm, vxsat| {
621 zvexx_fixed_point_helpers::sat_sub(a, b, sew, vxsat)
622 },
623 );
624 }
625 }
626 Self::VaadduVv { vd, vs2, vs1, vm } => {
628 if !env.vector_instructions_allowed() {
629 ::core::hint::cold_path();
630 return ExecutionResult::Err(ExecutionError::IllegalInstruction {
631 address: PackedAddress::new(
632 program_counter.old_pc(zvexx_helpers::INSTRUCTION_SIZE),
633 ),
634 });
635 }
636 let Some(vtype) = env.vtype() else {
637 ::core::hint::cold_path();
638 return ExecutionResult::Err(ExecutionError::IllegalInstruction {
639 address: PackedAddress::new(
640 program_counter.old_pc(zvexx_helpers::INSTRUCTION_SIZE),
641 ),
642 });
643 };
644 let group_regs = vtype.vlmul().register_count();
645 zvexx_fixed_point_helpers::check_vreg_group_alignment::<Reg, _, _>(
646 program_counter,
647 vd,
648 group_regs,
649 )?;
650 zvexx_fixed_point_helpers::check_vreg_group_alignment::<Reg, _, _>(
651 program_counter,
652 vs2,
653 group_regs,
654 )?;
655 zvexx_fixed_point_helpers::check_vreg_group_alignment::<Reg, _, _>(
656 program_counter,
657 vs1,
658 group_regs,
659 )?;
660 if !vm && vd == VReg::V0 {
661 ::core::hint::cold_path();
662 return ExecutionResult::Err(ExecutionError::IllegalInstruction {
663 address: PackedAddress::new(
664 program_counter.old_pc(zvexx_helpers::INSTRUCTION_SIZE),
665 ),
666 });
667 }
668 let sew = vtype.vsew();
669 unsafe {
671 zvexx_fixed_point_helpers::execute_fixed_point_op(
672 env,
673 vd,
674 vs2,
675 zvexx_fixed_point_helpers::OpSrc::Vreg(vs1),
676 vm,
677 sew,
678 |a, b, sew, vxrm, _vxsat| {
679 zvexx_fixed_point_helpers::avg_addu(a, b, sew, vxrm)
680 },
681 );
682 }
683 }
684 Self::VaadduVx {
685 vd,
686 vs2,
687 rs1: _,
688 vm,
689 } => {
690 if !env.vector_instructions_allowed() {
691 ::core::hint::cold_path();
692 return ExecutionResult::Err(ExecutionError::IllegalInstruction {
693 address: PackedAddress::new(
694 program_counter.old_pc(zvexx_helpers::INSTRUCTION_SIZE),
695 ),
696 });
697 }
698 let Some(vtype) = env.vtype() else {
699 ::core::hint::cold_path();
700 return ExecutionResult::Err(ExecutionError::IllegalInstruction {
701 address: PackedAddress::new(
702 program_counter.old_pc(zvexx_helpers::INSTRUCTION_SIZE),
703 ),
704 });
705 };
706 let group_regs = vtype.vlmul().register_count();
707 zvexx_fixed_point_helpers::check_vreg_group_alignment::<Reg, _, _>(
708 program_counter,
709 vd,
710 group_regs,
711 )?;
712 zvexx_fixed_point_helpers::check_vreg_group_alignment::<Reg, _, _>(
713 program_counter,
714 vs2,
715 group_regs,
716 )?;
717 if !vm && vd == VReg::V0 {
718 ::core::hint::cold_path();
719 return ExecutionResult::Err(ExecutionError::IllegalInstruction {
720 address: PackedAddress::new(
721 program_counter.old_pc(zvexx_helpers::INSTRUCTION_SIZE),
722 ),
723 });
724 }
725 let sew = vtype.vsew();
726 let scalar = rs1_value.as_i64().cast_unsigned();
727 unsafe {
729 zvexx_fixed_point_helpers::execute_fixed_point_op(
730 env,
731 vd,
732 vs2,
733 zvexx_fixed_point_helpers::OpSrc::Scalar(scalar),
734 vm,
735 sew,
736 |a, b, sew, vxrm, _vxsat| {
737 zvexx_fixed_point_helpers::avg_addu(a, b, sew, vxrm)
738 },
739 );
740 }
741 }
742 Self::VaaddVv { vd, vs2, vs1, vm } => {
744 if !env.vector_instructions_allowed() {
745 ::core::hint::cold_path();
746 return ExecutionResult::Err(ExecutionError::IllegalInstruction {
747 address: PackedAddress::new(
748 program_counter.old_pc(zvexx_helpers::INSTRUCTION_SIZE),
749 ),
750 });
751 }
752 let Some(vtype) = env.vtype() else {
753 ::core::hint::cold_path();
754 return ExecutionResult::Err(ExecutionError::IllegalInstruction {
755 address: PackedAddress::new(
756 program_counter.old_pc(zvexx_helpers::INSTRUCTION_SIZE),
757 ),
758 });
759 };
760 let group_regs = vtype.vlmul().register_count();
761 zvexx_fixed_point_helpers::check_vreg_group_alignment::<Reg, _, _>(
762 program_counter,
763 vd,
764 group_regs,
765 )?;
766 zvexx_fixed_point_helpers::check_vreg_group_alignment::<Reg, _, _>(
767 program_counter,
768 vs2,
769 group_regs,
770 )?;
771 zvexx_fixed_point_helpers::check_vreg_group_alignment::<Reg, _, _>(
772 program_counter,
773 vs1,
774 group_regs,
775 )?;
776 if !vm && vd == VReg::V0 {
777 ::core::hint::cold_path();
778 return ExecutionResult::Err(ExecutionError::IllegalInstruction {
779 address: PackedAddress::new(
780 program_counter.old_pc(zvexx_helpers::INSTRUCTION_SIZE),
781 ),
782 });
783 }
784 let sew = vtype.vsew();
785 unsafe {
787 zvexx_fixed_point_helpers::execute_fixed_point_op(
788 env,
789 vd,
790 vs2,
791 zvexx_fixed_point_helpers::OpSrc::Vreg(vs1),
792 vm,
793 sew,
794 |a, b, sew, vxrm, _vxsat| {
795 zvexx_fixed_point_helpers::avg_add(a, b, sew, vxrm)
796 },
797 );
798 }
799 }
800 Self::VaaddVx {
801 vd,
802 vs2,
803 rs1: _,
804 vm,
805 } => {
806 if !env.vector_instructions_allowed() {
807 ::core::hint::cold_path();
808 return ExecutionResult::Err(ExecutionError::IllegalInstruction {
809 address: PackedAddress::new(
810 program_counter.old_pc(zvexx_helpers::INSTRUCTION_SIZE),
811 ),
812 });
813 }
814 let Some(vtype) = env.vtype() else {
815 ::core::hint::cold_path();
816 return ExecutionResult::Err(ExecutionError::IllegalInstruction {
817 address: PackedAddress::new(
818 program_counter.old_pc(zvexx_helpers::INSTRUCTION_SIZE),
819 ),
820 });
821 };
822 let group_regs = vtype.vlmul().register_count();
823 zvexx_fixed_point_helpers::check_vreg_group_alignment::<Reg, _, _>(
824 program_counter,
825 vd,
826 group_regs,
827 )?;
828 zvexx_fixed_point_helpers::check_vreg_group_alignment::<Reg, _, _>(
829 program_counter,
830 vs2,
831 group_regs,
832 )?;
833 if !vm && vd == VReg::V0 {
834 ::core::hint::cold_path();
835 return ExecutionResult::Err(ExecutionError::IllegalInstruction {
836 address: PackedAddress::new(
837 program_counter.old_pc(zvexx_helpers::INSTRUCTION_SIZE),
838 ),
839 });
840 }
841 let sew = vtype.vsew();
842 let scalar = rs1_value.as_i64().cast_unsigned();
843 unsafe {
845 zvexx_fixed_point_helpers::execute_fixed_point_op(
846 env,
847 vd,
848 vs2,
849 zvexx_fixed_point_helpers::OpSrc::Scalar(scalar),
850 vm,
851 sew,
852 |a, b, sew, vxrm, _vxsat| {
853 zvexx_fixed_point_helpers::avg_add(a, b, sew, vxrm)
854 },
855 );
856 }
857 }
858 Self::VasubuVv { vd, vs2, vs1, vm } => {
860 if !env.vector_instructions_allowed() {
861 ::core::hint::cold_path();
862 return ExecutionResult::Err(ExecutionError::IllegalInstruction {
863 address: PackedAddress::new(
864 program_counter.old_pc(zvexx_helpers::INSTRUCTION_SIZE),
865 ),
866 });
867 }
868 let Some(vtype) = env.vtype() else {
869 ::core::hint::cold_path();
870 return ExecutionResult::Err(ExecutionError::IllegalInstruction {
871 address: PackedAddress::new(
872 program_counter.old_pc(zvexx_helpers::INSTRUCTION_SIZE),
873 ),
874 });
875 };
876 let group_regs = vtype.vlmul().register_count();
877 zvexx_fixed_point_helpers::check_vreg_group_alignment::<Reg, _, _>(
878 program_counter,
879 vd,
880 group_regs,
881 )?;
882 zvexx_fixed_point_helpers::check_vreg_group_alignment::<Reg, _, _>(
883 program_counter,
884 vs2,
885 group_regs,
886 )?;
887 zvexx_fixed_point_helpers::check_vreg_group_alignment::<Reg, _, _>(
888 program_counter,
889 vs1,
890 group_regs,
891 )?;
892 if !vm && vd == VReg::V0 {
893 ::core::hint::cold_path();
894 return ExecutionResult::Err(ExecutionError::IllegalInstruction {
895 address: PackedAddress::new(
896 program_counter.old_pc(zvexx_helpers::INSTRUCTION_SIZE),
897 ),
898 });
899 }
900 let sew = vtype.vsew();
901 unsafe {
903 zvexx_fixed_point_helpers::execute_fixed_point_op(
904 env,
905 vd,
906 vs2,
907 zvexx_fixed_point_helpers::OpSrc::Vreg(vs1),
908 vm,
909 sew,
910 |a, b, sew, vxrm, _vxsat| {
911 zvexx_fixed_point_helpers::avg_subu(a, b, sew, vxrm)
912 },
913 );
914 }
915 }
916 Self::VasubuVx {
917 vd,
918 vs2,
919 rs1: _,
920 vm,
921 } => {
922 if !env.vector_instructions_allowed() {
923 ::core::hint::cold_path();
924 return ExecutionResult::Err(ExecutionError::IllegalInstruction {
925 address: PackedAddress::new(
926 program_counter.old_pc(zvexx_helpers::INSTRUCTION_SIZE),
927 ),
928 });
929 }
930 let Some(vtype) = env.vtype() else {
931 ::core::hint::cold_path();
932 return ExecutionResult::Err(ExecutionError::IllegalInstruction {
933 address: PackedAddress::new(
934 program_counter.old_pc(zvexx_helpers::INSTRUCTION_SIZE),
935 ),
936 });
937 };
938 let group_regs = vtype.vlmul().register_count();
939 zvexx_fixed_point_helpers::check_vreg_group_alignment::<Reg, _, _>(
940 program_counter,
941 vd,
942 group_regs,
943 )?;
944 zvexx_fixed_point_helpers::check_vreg_group_alignment::<Reg, _, _>(
945 program_counter,
946 vs2,
947 group_regs,
948 )?;
949 if !vm && vd == VReg::V0 {
950 ::core::hint::cold_path();
951 return ExecutionResult::Err(ExecutionError::IllegalInstruction {
952 address: PackedAddress::new(
953 program_counter.old_pc(zvexx_helpers::INSTRUCTION_SIZE),
954 ),
955 });
956 }
957 let sew = vtype.vsew();
958 let scalar = rs1_value.as_i64().cast_unsigned();
959 unsafe {
961 zvexx_fixed_point_helpers::execute_fixed_point_op(
962 env,
963 vd,
964 vs2,
965 zvexx_fixed_point_helpers::OpSrc::Scalar(scalar),
966 vm,
967 sew,
968 |a, b, sew, vxrm, _vxsat| {
969 zvexx_fixed_point_helpers::avg_subu(a, b, sew, vxrm)
970 },
971 );
972 }
973 }
974 Self::VasubVv { vd, vs2, vs1, vm } => {
976 if !env.vector_instructions_allowed() {
977 ::core::hint::cold_path();
978 return ExecutionResult::Err(ExecutionError::IllegalInstruction {
979 address: PackedAddress::new(
980 program_counter.old_pc(zvexx_helpers::INSTRUCTION_SIZE),
981 ),
982 });
983 }
984 let Some(vtype) = env.vtype() else {
985 ::core::hint::cold_path();
986 return ExecutionResult::Err(ExecutionError::IllegalInstruction {
987 address: PackedAddress::new(
988 program_counter.old_pc(zvexx_helpers::INSTRUCTION_SIZE),
989 ),
990 });
991 };
992 let group_regs = vtype.vlmul().register_count();
993 zvexx_fixed_point_helpers::check_vreg_group_alignment::<Reg, _, _>(
994 program_counter,
995 vd,
996 group_regs,
997 )?;
998 zvexx_fixed_point_helpers::check_vreg_group_alignment::<Reg, _, _>(
999 program_counter,
1000 vs2,
1001 group_regs,
1002 )?;
1003 zvexx_fixed_point_helpers::check_vreg_group_alignment::<Reg, _, _>(
1004 program_counter,
1005 vs1,
1006 group_regs,
1007 )?;
1008 if !vm && vd == VReg::V0 {
1009 ::core::hint::cold_path();
1010 return ExecutionResult::Err(ExecutionError::IllegalInstruction {
1011 address: PackedAddress::new(
1012 program_counter.old_pc(zvexx_helpers::INSTRUCTION_SIZE),
1013 ),
1014 });
1015 }
1016 let sew = vtype.vsew();
1017 unsafe {
1019 zvexx_fixed_point_helpers::execute_fixed_point_op(
1020 env,
1021 vd,
1022 vs2,
1023 zvexx_fixed_point_helpers::OpSrc::Vreg(vs1),
1024 vm,
1025 sew,
1026 |a, b, sew, vxrm, _vxsat| {
1027 zvexx_fixed_point_helpers::avg_sub(a, b, sew, vxrm)
1028 },
1029 );
1030 }
1031 }
1032 Self::VasubVx {
1033 vd,
1034 vs2,
1035 rs1: _,
1036 vm,
1037 } => {
1038 if !env.vector_instructions_allowed() {
1039 ::core::hint::cold_path();
1040 return ExecutionResult::Err(ExecutionError::IllegalInstruction {
1041 address: PackedAddress::new(
1042 program_counter.old_pc(zvexx_helpers::INSTRUCTION_SIZE),
1043 ),
1044 });
1045 }
1046 let Some(vtype) = env.vtype() else {
1047 ::core::hint::cold_path();
1048 return ExecutionResult::Err(ExecutionError::IllegalInstruction {
1049 address: PackedAddress::new(
1050 program_counter.old_pc(zvexx_helpers::INSTRUCTION_SIZE),
1051 ),
1052 });
1053 };
1054 let group_regs = vtype.vlmul().register_count();
1055 zvexx_fixed_point_helpers::check_vreg_group_alignment::<Reg, _, _>(
1056 program_counter,
1057 vd,
1058 group_regs,
1059 )?;
1060 zvexx_fixed_point_helpers::check_vreg_group_alignment::<Reg, _, _>(
1061 program_counter,
1062 vs2,
1063 group_regs,
1064 )?;
1065 if !vm && vd == VReg::V0 {
1066 ::core::hint::cold_path();
1067 return ExecutionResult::Err(ExecutionError::IllegalInstruction {
1068 address: PackedAddress::new(
1069 program_counter.old_pc(zvexx_helpers::INSTRUCTION_SIZE),
1070 ),
1071 });
1072 }
1073 let sew = vtype.vsew();
1074 let scalar = rs1_value.as_i64().cast_unsigned();
1075 unsafe {
1077 zvexx_fixed_point_helpers::execute_fixed_point_op(
1078 env,
1079 vd,
1080 vs2,
1081 zvexx_fixed_point_helpers::OpSrc::Scalar(scalar),
1082 vm,
1083 sew,
1084 |a, b, sew, vxrm, _vxsat| {
1085 zvexx_fixed_point_helpers::avg_sub(a, b, sew, vxrm)
1086 },
1087 );
1088 }
1089 }
1090 Self::VsmulVv { vd, vs2, vs1, vm } => {
1092 if !env.vector_instructions_allowed() {
1093 ::core::hint::cold_path();
1094 return ExecutionResult::Err(ExecutionError::IllegalInstruction {
1095 address: PackedAddress::new(
1096 program_counter.old_pc(zvexx_helpers::INSTRUCTION_SIZE),
1097 ),
1098 });
1099 }
1100 let Some(vtype) = env.vtype() else {
1101 ::core::hint::cold_path();
1102 return ExecutionResult::Err(ExecutionError::IllegalInstruction {
1103 address: PackedAddress::new(
1104 program_counter.old_pc(zvexx_helpers::INSTRUCTION_SIZE),
1105 ),
1106 });
1107 };
1108 if !Self::implements_extension::<V<_>>() && vtype.vsew() == Vsew::E64 {
1110 ::core::hint::cold_path();
1111 return ExecutionResult::Err(ExecutionError::IllegalInstruction {
1112 address: PackedAddress::new(
1113 program_counter.old_pc(zvexx_helpers::INSTRUCTION_SIZE),
1114 ),
1115 });
1116 }
1117 let group_regs = vtype.vlmul().register_count();
1118 zvexx_fixed_point_helpers::check_vreg_group_alignment::<Reg, _, _>(
1119 program_counter,
1120 vd,
1121 group_regs,
1122 )?;
1123 zvexx_fixed_point_helpers::check_vreg_group_alignment::<Reg, _, _>(
1124 program_counter,
1125 vs2,
1126 group_regs,
1127 )?;
1128 zvexx_fixed_point_helpers::check_vreg_group_alignment::<Reg, _, _>(
1129 program_counter,
1130 vs1,
1131 group_regs,
1132 )?;
1133 if !vm && vd == VReg::V0 {
1134 ::core::hint::cold_path();
1135 return ExecutionResult::Err(ExecutionError::IllegalInstruction {
1136 address: PackedAddress::new(
1137 program_counter.old_pc(zvexx_helpers::INSTRUCTION_SIZE),
1138 ),
1139 });
1140 }
1141 let sew = vtype.vsew();
1142 unsafe {
1144 zvexx_fixed_point_helpers::execute_fixed_point_op(
1145 env,
1146 vd,
1147 vs2,
1148 zvexx_fixed_point_helpers::OpSrc::Vreg(vs1),
1149 vm,
1150 sew,
1151 |a, b, sew, vxrm, vxsat| {
1152 zvexx_fixed_point_helpers::smul(a, b, sew, vxrm, vxsat)
1153 },
1154 );
1155 }
1156 }
1157 Self::VsmulVx {
1158 vd,
1159 vs2,
1160 rs1: _,
1161 vm,
1162 } => {
1163 if !env.vector_instructions_allowed() {
1164 ::core::hint::cold_path();
1165 return ExecutionResult::Err(ExecutionError::IllegalInstruction {
1166 address: PackedAddress::new(
1167 program_counter.old_pc(zvexx_helpers::INSTRUCTION_SIZE),
1168 ),
1169 });
1170 }
1171 let Some(vtype) = env.vtype() else {
1172 ::core::hint::cold_path();
1173 return ExecutionResult::Err(ExecutionError::IllegalInstruction {
1174 address: PackedAddress::new(
1175 program_counter.old_pc(zvexx_helpers::INSTRUCTION_SIZE),
1176 ),
1177 });
1178 };
1179 if !Self::implements_extension::<V<_>>() && vtype.vsew() == Vsew::E64 {
1181 ::core::hint::cold_path();
1182 return ExecutionResult::Err(ExecutionError::IllegalInstruction {
1183 address: PackedAddress::new(
1184 program_counter.old_pc(zvexx_helpers::INSTRUCTION_SIZE),
1185 ),
1186 });
1187 }
1188 let group_regs = vtype.vlmul().register_count();
1189 zvexx_fixed_point_helpers::check_vreg_group_alignment::<Reg, _, _>(
1190 program_counter,
1191 vd,
1192 group_regs,
1193 )?;
1194 zvexx_fixed_point_helpers::check_vreg_group_alignment::<Reg, _, _>(
1195 program_counter,
1196 vs2,
1197 group_regs,
1198 )?;
1199 if !vm && vd == VReg::V0 {
1200 ::core::hint::cold_path();
1201 return ExecutionResult::Err(ExecutionError::IllegalInstruction {
1202 address: PackedAddress::new(
1203 program_counter.old_pc(zvexx_helpers::INSTRUCTION_SIZE),
1204 ),
1205 });
1206 }
1207 let sew = vtype.vsew();
1208 let scalar = rs1_value.as_u64();
1209 unsafe {
1211 zvexx_fixed_point_helpers::execute_fixed_point_op(
1212 env,
1213 vd,
1214 vs2,
1215 zvexx_fixed_point_helpers::OpSrc::Scalar(scalar),
1216 vm,
1217 sew,
1218 |a, b, sew, vxrm, vxsat| {
1219 zvexx_fixed_point_helpers::smul(a, b, sew, vxrm, vxsat)
1220 },
1221 );
1222 }
1223 }
1224 Self::VssrlVv { vd, vs2, vs1, vm } => {
1226 if !env.vector_instructions_allowed() {
1227 ::core::hint::cold_path();
1228 return ExecutionResult::Err(ExecutionError::IllegalInstruction {
1229 address: PackedAddress::new(
1230 program_counter.old_pc(zvexx_helpers::INSTRUCTION_SIZE),
1231 ),
1232 });
1233 }
1234 let Some(vtype) = env.vtype() else {
1235 ::core::hint::cold_path();
1236 return ExecutionResult::Err(ExecutionError::IllegalInstruction {
1237 address: PackedAddress::new(
1238 program_counter.old_pc(zvexx_helpers::INSTRUCTION_SIZE),
1239 ),
1240 });
1241 };
1242 let group_regs = vtype.vlmul().register_count();
1243 zvexx_fixed_point_helpers::check_vreg_group_alignment::<Reg, _, _>(
1244 program_counter,
1245 vd,
1246 group_regs,
1247 )?;
1248 zvexx_fixed_point_helpers::check_vreg_group_alignment::<Reg, _, _>(
1249 program_counter,
1250 vs2,
1251 group_regs,
1252 )?;
1253 zvexx_fixed_point_helpers::check_vreg_group_alignment::<Reg, _, _>(
1254 program_counter,
1255 vs1,
1256 group_regs,
1257 )?;
1258 if !vm && vd == VReg::V0 {
1259 ::core::hint::cold_path();
1260 return ExecutionResult::Err(ExecutionError::IllegalInstruction {
1261 address: PackedAddress::new(
1262 program_counter.old_pc(zvexx_helpers::INSTRUCTION_SIZE),
1263 ),
1264 });
1265 }
1266 let sew = vtype.vsew();
1267 unsafe {
1269 zvexx_fixed_point_helpers::execute_fixed_point_op(
1270 env,
1271 vd,
1272 vs2,
1273 zvexx_fixed_point_helpers::OpSrc::Vreg(vs1),
1274 vm,
1275 sew,
1276 |a, b, sew, vxrm, _vxsat| {
1277 let shamt = (b & u64::from(sew.bits_width() - 1)) as u32;
1279 let masked_a = a & zvexx_fixed_point_helpers::sew_mask(sew);
1280 zvexx_fixed_point_helpers::rounded_srl(masked_a, shamt, vxrm)
1281 & zvexx_fixed_point_helpers::sew_mask(sew)
1282 },
1283 );
1284 }
1285 }
1286 Self::VssrlVx {
1287 vd,
1288 vs2,
1289 rs1: _,
1290 vm,
1291 } => {
1292 if !env.vector_instructions_allowed() {
1293 ::core::hint::cold_path();
1294 return ExecutionResult::Err(ExecutionError::IllegalInstruction {
1295 address: PackedAddress::new(
1296 program_counter.old_pc(zvexx_helpers::INSTRUCTION_SIZE),
1297 ),
1298 });
1299 }
1300 let Some(vtype) = env.vtype() else {
1301 ::core::hint::cold_path();
1302 return ExecutionResult::Err(ExecutionError::IllegalInstruction {
1303 address: PackedAddress::new(
1304 program_counter.old_pc(zvexx_helpers::INSTRUCTION_SIZE),
1305 ),
1306 });
1307 };
1308 let group_regs = vtype.vlmul().register_count();
1309 zvexx_fixed_point_helpers::check_vreg_group_alignment::<Reg, _, _>(
1310 program_counter,
1311 vd,
1312 group_regs,
1313 )?;
1314 zvexx_fixed_point_helpers::check_vreg_group_alignment::<Reg, _, _>(
1315 program_counter,
1316 vs2,
1317 group_regs,
1318 )?;
1319 if !vm && vd == VReg::V0 {
1320 ::core::hint::cold_path();
1321 return ExecutionResult::Err(ExecutionError::IllegalInstruction {
1322 address: PackedAddress::new(
1323 program_counter.old_pc(zvexx_helpers::INSTRUCTION_SIZE),
1324 ),
1325 });
1326 }
1327 let sew = vtype.vsew();
1328 let scalar = rs1_value.as_u64();
1329 unsafe {
1331 zvexx_fixed_point_helpers::execute_fixed_point_op(
1332 env,
1333 vd,
1334 vs2,
1335 zvexx_fixed_point_helpers::OpSrc::Scalar(scalar),
1336 vm,
1337 sew,
1338 |a, b, sew, vxrm, _vxsat| {
1339 let shamt = (b & u64::from(sew.bits_width() - 1)) as u32;
1340 let masked_a = a & zvexx_fixed_point_helpers::sew_mask(sew);
1341 zvexx_fixed_point_helpers::rounded_srl(masked_a, shamt, vxrm)
1342 & zvexx_fixed_point_helpers::sew_mask(sew)
1343 },
1344 );
1345 }
1346 }
1347 Self::VssrlVi { vd, vs2, imm, vm } => {
1348 if !env.vector_instructions_allowed() {
1349 ::core::hint::cold_path();
1350 return ExecutionResult::Err(ExecutionError::IllegalInstruction {
1351 address: PackedAddress::new(
1352 program_counter.old_pc(zvexx_helpers::INSTRUCTION_SIZE),
1353 ),
1354 });
1355 }
1356 let Some(vtype) = env.vtype() else {
1357 ::core::hint::cold_path();
1358 return ExecutionResult::Err(ExecutionError::IllegalInstruction {
1359 address: PackedAddress::new(
1360 program_counter.old_pc(zvexx_helpers::INSTRUCTION_SIZE),
1361 ),
1362 });
1363 };
1364 let group_regs = vtype.vlmul().register_count();
1365 zvexx_fixed_point_helpers::check_vreg_group_alignment::<Reg, _, _>(
1366 program_counter,
1367 vd,
1368 group_regs,
1369 )?;
1370 zvexx_fixed_point_helpers::check_vreg_group_alignment::<Reg, _, _>(
1371 program_counter,
1372 vs2,
1373 group_regs,
1374 )?;
1375 if !vm && vd == VReg::V0 {
1376 ::core::hint::cold_path();
1377 return ExecutionResult::Err(ExecutionError::IllegalInstruction {
1378 address: PackedAddress::new(
1379 program_counter.old_pc(zvexx_helpers::INSTRUCTION_SIZE),
1380 ),
1381 });
1382 }
1383 let sew = vtype.vsew();
1384 let shamt = (u64::from(imm) & u64::from(sew.bits_width() - 1)) as u32;
1386 unsafe {
1388 zvexx_fixed_point_helpers::execute_fixed_point_op(
1389 env,
1390 vd,
1391 vs2,
1392 zvexx_fixed_point_helpers::OpSrc::Scalar(u64::from(shamt)),
1393 vm,
1394 sew,
1395 |a, b, sew, vxrm, _vxsat| {
1396 let shamt = b as u32;
1397 let masked_a = a & zvexx_fixed_point_helpers::sew_mask(sew);
1398 zvexx_fixed_point_helpers::rounded_srl(masked_a, shamt, vxrm)
1399 & zvexx_fixed_point_helpers::sew_mask(sew)
1400 },
1401 );
1402 }
1403 }
1404 Self::VssraVv { vd, vs2, vs1, vm } => {
1406 if !env.vector_instructions_allowed() {
1407 ::core::hint::cold_path();
1408 return ExecutionResult::Err(ExecutionError::IllegalInstruction {
1409 address: PackedAddress::new(
1410 program_counter.old_pc(zvexx_helpers::INSTRUCTION_SIZE),
1411 ),
1412 });
1413 }
1414 let Some(vtype) = env.vtype() else {
1415 ::core::hint::cold_path();
1416 return ExecutionResult::Err(ExecutionError::IllegalInstruction {
1417 address: PackedAddress::new(
1418 program_counter.old_pc(zvexx_helpers::INSTRUCTION_SIZE),
1419 ),
1420 });
1421 };
1422 let group_regs = vtype.vlmul().register_count();
1423 zvexx_fixed_point_helpers::check_vreg_group_alignment::<Reg, _, _>(
1424 program_counter,
1425 vd,
1426 group_regs,
1427 )?;
1428 zvexx_fixed_point_helpers::check_vreg_group_alignment::<Reg, _, _>(
1429 program_counter,
1430 vs2,
1431 group_regs,
1432 )?;
1433 zvexx_fixed_point_helpers::check_vreg_group_alignment::<Reg, _, _>(
1434 program_counter,
1435 vs1,
1436 group_regs,
1437 )?;
1438 if !vm && vd == VReg::V0 {
1439 ::core::hint::cold_path();
1440 return ExecutionResult::Err(ExecutionError::IllegalInstruction {
1441 address: PackedAddress::new(
1442 program_counter.old_pc(zvexx_helpers::INSTRUCTION_SIZE),
1443 ),
1444 });
1445 }
1446 let sew = vtype.vsew();
1447 unsafe {
1449 zvexx_fixed_point_helpers::execute_fixed_point_op(
1450 env,
1451 vd,
1452 vs2,
1453 zvexx_fixed_point_helpers::OpSrc::Vreg(vs1),
1454 vm,
1455 sew,
1456 |a, b, sew, vxrm, _vxsat| {
1457 let shamt = (b & u64::from(sew.bits_width() - 1)) as u32;
1458 zvexx_fixed_point_helpers::rounded_sra(a, shamt, vxrm, sew)
1459 & zvexx_fixed_point_helpers::sew_mask(sew)
1460 },
1461 );
1462 }
1463 }
1464 Self::VssraVx {
1465 vd,
1466 vs2,
1467 rs1: _,
1468 vm,
1469 } => {
1470 if !env.vector_instructions_allowed() {
1471 ::core::hint::cold_path();
1472 return ExecutionResult::Err(ExecutionError::IllegalInstruction {
1473 address: PackedAddress::new(
1474 program_counter.old_pc(zvexx_helpers::INSTRUCTION_SIZE),
1475 ),
1476 });
1477 }
1478 let Some(vtype) = env.vtype() else {
1479 ::core::hint::cold_path();
1480 return ExecutionResult::Err(ExecutionError::IllegalInstruction {
1481 address: PackedAddress::new(
1482 program_counter.old_pc(zvexx_helpers::INSTRUCTION_SIZE),
1483 ),
1484 });
1485 };
1486 let group_regs = vtype.vlmul().register_count();
1487 zvexx_fixed_point_helpers::check_vreg_group_alignment::<Reg, _, _>(
1488 program_counter,
1489 vd,
1490 group_regs,
1491 )?;
1492 zvexx_fixed_point_helpers::check_vreg_group_alignment::<Reg, _, _>(
1493 program_counter,
1494 vs2,
1495 group_regs,
1496 )?;
1497 if !vm && vd == VReg::V0 {
1498 ::core::hint::cold_path();
1499 return ExecutionResult::Err(ExecutionError::IllegalInstruction {
1500 address: PackedAddress::new(
1501 program_counter.old_pc(zvexx_helpers::INSTRUCTION_SIZE),
1502 ),
1503 });
1504 }
1505 let sew = vtype.vsew();
1506 let scalar = rs1_value.as_u64();
1507 unsafe {
1509 zvexx_fixed_point_helpers::execute_fixed_point_op(
1510 env,
1511 vd,
1512 vs2,
1513 zvexx_fixed_point_helpers::OpSrc::Scalar(scalar),
1514 vm,
1515 sew,
1516 |a, b, sew, vxrm, _vxsat| {
1517 let shamt = (b & u64::from(sew.bits_width() - 1)) as u32;
1518 zvexx_fixed_point_helpers::rounded_sra(a, shamt, vxrm, sew)
1519 & zvexx_fixed_point_helpers::sew_mask(sew)
1520 },
1521 );
1522 }
1523 }
1524 Self::VssraVi { vd, vs2, imm, vm } => {
1525 if !env.vector_instructions_allowed() {
1526 ::core::hint::cold_path();
1527 return ExecutionResult::Err(ExecutionError::IllegalInstruction {
1528 address: PackedAddress::new(
1529 program_counter.old_pc(zvexx_helpers::INSTRUCTION_SIZE),
1530 ),
1531 });
1532 }
1533 let Some(vtype) = env.vtype() else {
1534 ::core::hint::cold_path();
1535 return ExecutionResult::Err(ExecutionError::IllegalInstruction {
1536 address: PackedAddress::new(
1537 program_counter.old_pc(zvexx_helpers::INSTRUCTION_SIZE),
1538 ),
1539 });
1540 };
1541 let group_regs = vtype.vlmul().register_count();
1542 zvexx_fixed_point_helpers::check_vreg_group_alignment::<Reg, _, _>(
1543 program_counter,
1544 vd,
1545 group_regs,
1546 )?;
1547 zvexx_fixed_point_helpers::check_vreg_group_alignment::<Reg, _, _>(
1548 program_counter,
1549 vs2,
1550 group_regs,
1551 )?;
1552 if !vm && vd == VReg::V0 {
1553 ::core::hint::cold_path();
1554 return ExecutionResult::Err(ExecutionError::IllegalInstruction {
1555 address: PackedAddress::new(
1556 program_counter.old_pc(zvexx_helpers::INSTRUCTION_SIZE),
1557 ),
1558 });
1559 }
1560 let sew = vtype.vsew();
1561 let shamt = (u64::from(imm) & u64::from(sew.bits_width() - 1)) as u32;
1562 unsafe {
1564 zvexx_fixed_point_helpers::execute_fixed_point_op(
1565 env,
1566 vd,
1567 vs2,
1568 zvexx_fixed_point_helpers::OpSrc::Scalar(u64::from(shamt)),
1569 vm,
1570 sew,
1571 |a, b, sew, vxrm, _vxsat| {
1572 let shamt = b as u32;
1573 zvexx_fixed_point_helpers::rounded_sra(a, shamt, vxrm, sew)
1574 & zvexx_fixed_point_helpers::sew_mask(sew)
1575 },
1576 );
1577 }
1578 }
1579 Self::VnclipuWv { vd, vs2, vs1, vm } => {
1581 if !env.vector_instructions_allowed() {
1582 ::core::hint::cold_path();
1583 return ExecutionResult::Err(ExecutionError::IllegalInstruction {
1584 address: PackedAddress::new(
1585 program_counter.old_pc(zvexx_helpers::INSTRUCTION_SIZE),
1586 ),
1587 });
1588 }
1589 let Some(vtype) = env.vtype() else {
1590 ::core::hint::cold_path();
1591 return ExecutionResult::Err(ExecutionError::IllegalInstruction {
1592 address: PackedAddress::new(
1593 program_counter.old_pc(zvexx_helpers::INSTRUCTION_SIZE),
1594 ),
1595 });
1596 };
1597 let sew = vtype.vsew();
1599 zvexx_fixed_point_helpers::check_narrowing_sew::<Reg, _, _>(program_counter, sew)?;
1600 let group_regs = vtype.vlmul().register_count();
1601 zvexx_fixed_point_helpers::check_vreg_group_alignment::<Reg, _, _>(
1602 program_counter,
1603 vd,
1604 group_regs,
1605 )?;
1606 zvexx_fixed_point_helpers::check_vs2_narrowing_alignment::<Reg, _, _>(
1608 program_counter,
1609 vs2,
1610 vtype.vlmul(),
1611 sew,
1612 )?;
1613 zvexx_fixed_point_helpers::check_vreg_group_alignment::<Reg, _, _>(
1615 program_counter,
1616 vs1,
1617 group_regs,
1618 )?;
1619 if !vm && vd == VReg::V0 {
1620 ::core::hint::cold_path();
1621 return ExecutionResult::Err(ExecutionError::IllegalInstruction {
1622 address: PackedAddress::new(
1623 program_counter.old_pc(zvexx_helpers::INSTRUCTION_SIZE),
1624 ),
1625 });
1626 }
1627 unsafe {
1629 zvexx_fixed_point_helpers::execute_narrowing_clip_op(
1630 env,
1631 vd,
1632 vs2,
1633 zvexx_fixed_point_helpers::OpSrc::Vreg(vs1),
1634 vm,
1635 sew,
1636 |wide, shamt, sew, vxrm, vxsat| {
1637 zvexx_fixed_point_helpers::nclipu(wide, shamt, sew, vxrm, vxsat)
1638 },
1639 );
1640 }
1641 }
1642 Self::VnclipuWx {
1643 vd,
1644 vs2,
1645 rs1: _,
1646 vm,
1647 } => {
1648 if !env.vector_instructions_allowed() {
1649 ::core::hint::cold_path();
1650 return ExecutionResult::Err(ExecutionError::IllegalInstruction {
1651 address: PackedAddress::new(
1652 program_counter.old_pc(zvexx_helpers::INSTRUCTION_SIZE),
1653 ),
1654 });
1655 }
1656 let Some(vtype) = env.vtype() else {
1657 ::core::hint::cold_path();
1658 return ExecutionResult::Err(ExecutionError::IllegalInstruction {
1659 address: PackedAddress::new(
1660 program_counter.old_pc(zvexx_helpers::INSTRUCTION_SIZE),
1661 ),
1662 });
1663 };
1664 let sew = vtype.vsew();
1665 zvexx_fixed_point_helpers::check_narrowing_sew::<Reg, _, _>(program_counter, sew)?;
1666 let group_regs = vtype.vlmul().register_count();
1667 zvexx_fixed_point_helpers::check_vreg_group_alignment::<Reg, _, _>(
1668 program_counter,
1669 vd,
1670 group_regs,
1671 )?;
1672 zvexx_fixed_point_helpers::check_vs2_narrowing_alignment::<Reg, _, _>(
1673 program_counter,
1674 vs2,
1675 vtype.vlmul(),
1676 sew,
1677 )?;
1678 if !vm && vd == VReg::V0 {
1679 ::core::hint::cold_path();
1680 return ExecutionResult::Err(ExecutionError::IllegalInstruction {
1681 address: PackedAddress::new(
1682 program_counter.old_pc(zvexx_helpers::INSTRUCTION_SIZE),
1683 ),
1684 });
1685 }
1686 let scalar = rs1_value.as_u64();
1687 unsafe {
1689 zvexx_fixed_point_helpers::execute_narrowing_clip_op(
1690 env,
1691 vd,
1692 vs2,
1693 zvexx_fixed_point_helpers::OpSrc::Scalar(scalar),
1694 vm,
1695 sew,
1696 |wide, shamt, sew, vxrm, vxsat| {
1697 zvexx_fixed_point_helpers::nclipu(wide, shamt, sew, vxrm, vxsat)
1698 },
1699 );
1700 }
1701 }
1702 Self::VnclipuWi { vd, vs2, imm, vm } => {
1703 if !env.vector_instructions_allowed() {
1704 ::core::hint::cold_path();
1705 return ExecutionResult::Err(ExecutionError::IllegalInstruction {
1706 address: PackedAddress::new(
1707 program_counter.old_pc(zvexx_helpers::INSTRUCTION_SIZE),
1708 ),
1709 });
1710 }
1711 let Some(vtype) = env.vtype() else {
1712 ::core::hint::cold_path();
1713 return ExecutionResult::Err(ExecutionError::IllegalInstruction {
1714 address: PackedAddress::new(
1715 program_counter.old_pc(zvexx_helpers::INSTRUCTION_SIZE),
1716 ),
1717 });
1718 };
1719 let sew = vtype.vsew();
1720 zvexx_fixed_point_helpers::check_narrowing_sew::<Reg, _, _>(program_counter, sew)?;
1721 let group_regs = vtype.vlmul().register_count();
1722 zvexx_fixed_point_helpers::check_vreg_group_alignment::<Reg, _, _>(
1723 program_counter,
1724 vd,
1725 group_regs,
1726 )?;
1727 zvexx_fixed_point_helpers::check_vs2_narrowing_alignment::<Reg, _, _>(
1728 program_counter,
1729 vs2,
1730 vtype.vlmul(),
1731 sew,
1732 )?;
1733 if !vm && vd == VReg::V0 {
1734 ::core::hint::cold_path();
1735 return ExecutionResult::Err(ExecutionError::IllegalInstruction {
1736 address: PackedAddress::new(
1737 program_counter.old_pc(zvexx_helpers::INSTRUCTION_SIZE),
1738 ),
1739 });
1740 }
1741 unsafe {
1743 zvexx_fixed_point_helpers::execute_narrowing_clip_op(
1744 env,
1745 vd,
1746 vs2,
1747 zvexx_fixed_point_helpers::OpSrc::Scalar(u64::from(imm)),
1749 vm,
1750 sew,
1751 |wide, shamt, sew, vxrm, vxsat| {
1752 zvexx_fixed_point_helpers::nclipu(wide, shamt, sew, vxrm, vxsat)
1753 },
1754 );
1755 }
1756 }
1757 Self::VnclipWv { vd, vs2, vs1, vm } => {
1759 if !env.vector_instructions_allowed() {
1760 ::core::hint::cold_path();
1761 return ExecutionResult::Err(ExecutionError::IllegalInstruction {
1762 address: PackedAddress::new(
1763 program_counter.old_pc(zvexx_helpers::INSTRUCTION_SIZE),
1764 ),
1765 });
1766 }
1767 let Some(vtype) = env.vtype() else {
1768 ::core::hint::cold_path();
1769 return ExecutionResult::Err(ExecutionError::IllegalInstruction {
1770 address: PackedAddress::new(
1771 program_counter.old_pc(zvexx_helpers::INSTRUCTION_SIZE),
1772 ),
1773 });
1774 };
1775 let sew = vtype.vsew();
1776 zvexx_fixed_point_helpers::check_narrowing_sew::<Reg, _, _>(program_counter, sew)?;
1777 let group_regs = vtype.vlmul().register_count();
1778 zvexx_fixed_point_helpers::check_vreg_group_alignment::<Reg, _, _>(
1779 program_counter,
1780 vd,
1781 group_regs,
1782 )?;
1783 zvexx_fixed_point_helpers::check_vs2_narrowing_alignment::<Reg, _, _>(
1784 program_counter,
1785 vs2,
1786 vtype.vlmul(),
1787 sew,
1788 )?;
1789 zvexx_fixed_point_helpers::check_vreg_group_alignment::<Reg, _, _>(
1790 program_counter,
1791 vs1,
1792 group_regs,
1793 )?;
1794 if !vm && vd == VReg::V0 {
1795 ::core::hint::cold_path();
1796 return ExecutionResult::Err(ExecutionError::IllegalInstruction {
1797 address: PackedAddress::new(
1798 program_counter.old_pc(zvexx_helpers::INSTRUCTION_SIZE),
1799 ),
1800 });
1801 }
1802 unsafe {
1804 zvexx_fixed_point_helpers::execute_narrowing_clip_op(
1805 env,
1806 vd,
1807 vs2,
1808 zvexx_fixed_point_helpers::OpSrc::Vreg(vs1),
1809 vm,
1810 sew,
1811 |wide, shamt, sew, vxrm, vxsat| {
1812 zvexx_fixed_point_helpers::nclip(wide, shamt, sew, vxrm, vxsat)
1813 },
1814 );
1815 }
1816 }
1817 Self::VnclipWx {
1818 vd,
1819 vs2,
1820 rs1: _,
1821 vm,
1822 } => {
1823 if !env.vector_instructions_allowed() {
1824 ::core::hint::cold_path();
1825 return ExecutionResult::Err(ExecutionError::IllegalInstruction {
1826 address: PackedAddress::new(
1827 program_counter.old_pc(zvexx_helpers::INSTRUCTION_SIZE),
1828 ),
1829 });
1830 }
1831 let Some(vtype) = env.vtype() else {
1832 ::core::hint::cold_path();
1833 return ExecutionResult::Err(ExecutionError::IllegalInstruction {
1834 address: PackedAddress::new(
1835 program_counter.old_pc(zvexx_helpers::INSTRUCTION_SIZE),
1836 ),
1837 });
1838 };
1839 let sew = vtype.vsew();
1840 zvexx_fixed_point_helpers::check_narrowing_sew::<Reg, _, _>(program_counter, sew)?;
1841 let group_regs = vtype.vlmul().register_count();
1842 zvexx_fixed_point_helpers::check_vreg_group_alignment::<Reg, _, _>(
1843 program_counter,
1844 vd,
1845 group_regs,
1846 )?;
1847 zvexx_fixed_point_helpers::check_vs2_narrowing_alignment::<Reg, _, _>(
1848 program_counter,
1849 vs2,
1850 vtype.vlmul(),
1851 sew,
1852 )?;
1853 if !vm && vd == VReg::V0 {
1854 ::core::hint::cold_path();
1855 return ExecutionResult::Err(ExecutionError::IllegalInstruction {
1856 address: PackedAddress::new(
1857 program_counter.old_pc(zvexx_helpers::INSTRUCTION_SIZE),
1858 ),
1859 });
1860 }
1861 let scalar = rs1_value.as_u64();
1862 unsafe {
1864 zvexx_fixed_point_helpers::execute_narrowing_clip_op(
1865 env,
1866 vd,
1867 vs2,
1868 zvexx_fixed_point_helpers::OpSrc::Scalar(scalar),
1869 vm,
1870 sew,
1871 |wide, shamt, sew, vxrm, vxsat| {
1872 zvexx_fixed_point_helpers::nclip(wide, shamt, sew, vxrm, vxsat)
1873 },
1874 );
1875 }
1876 }
1877 Self::VnclipWi { vd, vs2, imm, vm } => {
1878 if !env.vector_instructions_allowed() {
1879 ::core::hint::cold_path();
1880 return ExecutionResult::Err(ExecutionError::IllegalInstruction {
1881 address: PackedAddress::new(
1882 program_counter.old_pc(zvexx_helpers::INSTRUCTION_SIZE),
1883 ),
1884 });
1885 }
1886 let Some(vtype) = env.vtype() else {
1887 ::core::hint::cold_path();
1888 return ExecutionResult::Err(ExecutionError::IllegalInstruction {
1889 address: PackedAddress::new(
1890 program_counter.old_pc(zvexx_helpers::INSTRUCTION_SIZE),
1891 ),
1892 });
1893 };
1894 let sew = vtype.vsew();
1895 zvexx_fixed_point_helpers::check_narrowing_sew::<Reg, _, _>(program_counter, sew)?;
1896 let group_regs = vtype.vlmul().register_count();
1897 zvexx_fixed_point_helpers::check_vreg_group_alignment::<Reg, _, _>(
1898 program_counter,
1899 vd,
1900 group_regs,
1901 )?;
1902 zvexx_fixed_point_helpers::check_vs2_narrowing_alignment::<Reg, _, _>(
1903 program_counter,
1904 vs2,
1905 vtype.vlmul(),
1906 sew,
1907 )?;
1908 if !vm && vd == VReg::V0 {
1909 ::core::hint::cold_path();
1910 return ExecutionResult::Err(ExecutionError::IllegalInstruction {
1911 address: PackedAddress::new(
1912 program_counter.old_pc(zvexx_helpers::INSTRUCTION_SIZE),
1913 ),
1914 });
1915 }
1916 unsafe {
1918 zvexx_fixed_point_helpers::execute_narrowing_clip_op(
1919 env,
1920 vd,
1921 vs2,
1922 zvexx_fixed_point_helpers::OpSrc::Scalar(u64::from(imm)),
1923 vm,
1924 sew,
1925 |wide, shamt, sew, vxrm, vxsat| {
1926 zvexx_fixed_point_helpers::nclip(wide, shamt, sew, vxrm, vxsat)
1927 },
1928 );
1929 }
1930 }
1931 }
1932
1933 ExecutionResult::ContinueNoWrite
1934 }
1935}