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