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