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