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