ab_riscv_interpreter/v/zvexx/reduction/
zvexx_reduction_helpers.rs1use crate::v::vector_registers::VectorRegistersExt;
3use crate::v::zvexx::arith::zvexx_arith_helpers::{
4 read_element_u64, sign_extend, write_element_u64,
5};
6use crate::v::zvexx::load::zvexx_load_helpers::{mask_bit, snapshot_mask};
7use ab_riscv_primitives::prelude::*;
8use core::hint::cold_path;
9
10#[inline(always)]
18#[expect(clippy::too_many_arguments, reason = "Internal API")]
19#[doc(hidden)]
20#[cfg_attr(feature = "no-panic", no_panic_const::no_panic)]
21pub unsafe fn execute_reduce_op<Reg, Env, F>(
22 env: &mut Env,
23 vd: VReg,
24 vs2: VReg,
25 vs1: VReg,
26 vm: bool,
27 vl: Vl,
28 sew: Vsew,
29 op: F,
30) where
31 Reg: Register,
32 Env: VectorRegistersExt<Reg>,
33 [(); SUPPORTED_ELEN_VLEN::<{ Env::ELEN }, { Env::VLEN }>]:,
34 F: Fn(u64, u64, Vsew) -> u64,
35{
36 if vl == Vl::ZERO {
40 cold_path();
41 env.reset_vstart();
42 return;
43 }
44 let init = unsafe { read_element_u64(env.read_vregs(), vs1, 0, sew) };
46 let mask_buf = unsafe { snapshot_mask(env.read_vregs(), vm, vl) };
48 let mut acc = init;
49 for i in Vstart::ZERO.range_to(vl) {
50 if !mask_bit(&mask_buf, i) {
51 continue;
52 }
53 let elem = unsafe { read_element_u64(env.read_vregs(), vs2, i, sew) };
55 acc = op(acc, elem, sew);
56 }
57 unsafe {
59 write_element_u64(env.write_vregs(), vd, 0, sew, acc);
60 }
61 env.mark_vs_dirty();
62 env.reset_vstart();
63}
64
65#[inline(always)]
74#[expect(clippy::too_many_arguments, reason = "Internal API")]
75#[doc(hidden)]
76#[cfg_attr(feature = "no-panic", no_panic_const::no_panic)]
77pub unsafe fn execute_widening_reduce_op<const SIGN_EXTEND_SRC: bool, Reg, Env, F>(
78 env: &mut Env,
79 vd: VReg,
80 vs2: VReg,
81 vs1: VReg,
82 vm: bool,
83 vl: Vl,
84 sew: Vsew,
85 op: F,
86) where
87 Reg: Register,
88 Env: VectorRegistersExt<Reg>,
89 [(); SUPPORTED_ELEN_VLEN::<{ Env::ELEN }, { Env::VLEN }>]:,
90 F: Fn(u64, u64, Vsew) -> u64,
91{
92 let Some(wide_sew) = sew.double_width() else {
93 unsafe { core::hint::unreachable_unchecked() }
95 };
96 if vl == Vl::ZERO {
97 cold_path();
98 env.reset_vstart();
99 return;
100 }
101 let init = unsafe { read_element_u64(env.read_vregs(), vs1, 0, wide_sew) };
103 let mask_buf = unsafe { snapshot_mask(env.read_vregs(), vm, vl) };
105 let mut acc = init;
106 for i in Vstart::ZERO.range_to(vl) {
107 if !mask_bit(&mask_buf, i) {
108 continue;
109 }
110 let raw = unsafe { read_element_u64(env.read_vregs(), vs2, i, sew) };
112 let elem = if SIGN_EXTEND_SRC {
113 sign_extend(raw, sew).cast_unsigned()
114 } else {
115 raw
116 };
117 acc = op(acc, elem, wide_sew);
118 }
119 unsafe {
121 write_element_u64(env.write_vregs(), vd, 0, wide_sew, acc);
122 }
123 env.mark_vs_dirty();
124 env.reset_vstart();
125}