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