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