ab_riscv_interpreter/v/zvexx/mask/
zvexx_mask_helpers.rs1use crate::v::vector_config::{BoundedVl, VectorConfig};
4use crate::v::vector_registers::{VRegGroup, VectorRegistersExt};
5use crate::v::zvexx::arith::zvexx_arith_helpers::write_mask_bit;
6use crate::v::zvexx::load::zvexx_load_helpers::{mask_bit, snapshot_mask};
7use ab_riscv_primitives::prelude::*;
8
9#[inline(always)]
17#[doc(hidden)]
18#[cfg_attr(feature = "no-panic", no_panic_const::no_panic)]
19pub fn execute_mask_logical_op<Reg, Env, F>(
20 env: &mut Env,
21 config: VectorConfig<Env::Hart>,
22 vd: VReg,
23 vs2: VReg,
24 vs1: VReg,
25 op: F,
26) where
27 Reg: Register,
28 Env: VectorRegistersExt<Hart: HartConfig<Reg = Reg>>,
29 F: Fn(bool, bool) -> bool,
30{
31 let vl = config.vl();
32 let vs2_snap = *env.read_vregs().get(vs2);
34 let vs1_snap = *env.read_vregs().get(vs1);
35 for i in vl.indices() {
38 let a = mask_bit(&vs2_snap, i);
39 let b = mask_bit(&vs1_snap, i);
40 write_mask_bit(env.write_vregs(), vd, i, op(a, b))
41 .expect("`i < vl <= VLEN`, so the mask bit is within `vd`; qed");
42 }
43 env.mark_vs_dirty();
44}
45
46#[inline(always)]
54#[doc(hidden)]
55#[cfg_attr(feature = "no-panic", no_panic_const::no_panic)]
56pub fn execute_vcpop<Reg, Env>(
57 env: &mut Env,
58 config: VectorConfig<Env::Hart>,
59 vs2: VReg,
60 vm: bool,
61) -> Reg::Type
62where
63 Reg: Register,
64 Env: VectorRegistersExt<Hart: HartConfig<Reg = Reg>>,
65{
66 let vl = config.vl().get();
67 let mask_buf = snapshot_mask(env.read_vregs(), vm);
68 let vs2_reg = *env.read_vregs().get(vs2);
69 let mut count = 0u32;
70 for i in Vstart::ZERO.range_to(vl) {
71 if !mask_bit(&mask_buf, i) {
72 continue;
73 }
74 if mask_bit(&vs2_reg, i) {
75 count += 1;
76 }
77 }
78
79 env.mark_vs_dirty();
80
81 Reg::Type::from(count)
82}
83
84#[inline(always)]
92#[doc(hidden)]
93#[cfg_attr(feature = "no-panic", no_panic_const::no_panic)]
94pub fn execute_vfirst<Reg, Env>(
95 env: &mut Env,
96 config: VectorConfig<Env::Hart>,
97 vs2: VReg,
98 vm: bool,
99) -> Reg::Type
100where
101 Reg: Register,
102 Env: VectorRegistersExt<Hart: HartConfig<Reg = Reg>>,
103{
104 let vl = config.vl().get();
105 let mask_buf = snapshot_mask(env.read_vregs(), vm);
106 let vs2_reg = *env.read_vregs().get(vs2);
107 let not_found = u64::MAX;
109 let mut result = not_found;
110 for i in Vstart::ZERO.range_to(vl) {
111 if !mask_bit(&mask_buf, i) {
112 continue;
113 }
114 if mask_bit(&vs2_reg, i) {
115 result = u64::from(i);
116 break;
117 }
118 }
119 let rd_value = if result == not_found {
125 !Reg::Type::from(0u8)
126 } else {
127 Reg::Type::from(result as u32)
128 };
129 env.mark_vs_dirty();
130
131 rd_value
132}
133
134#[inline(always)]
142#[doc(hidden)]
143#[cfg_attr(feature = "no-panic", no_panic_const::no_panic)]
144pub fn execute_vmsbf<Reg, Env>(
145 env: &mut Env,
146 vd: VReg,
147 vs2: VReg,
148 vm: bool,
149 vl: BoundedVl<Env::Hart>,
150) where
151 Reg: Register,
152 Env: VectorRegistersExt<Hart: HartConfig<Reg = Reg>>,
153{
154 let mask_buf = snapshot_mask(env.read_vregs(), vm);
155 let vs2_snap = *env.read_vregs().get(vs2);
156 let mut found_first = false;
157 for i in vl.indices() {
158 if !mask_bit(&mask_buf, i) {
160 continue;
161 }
162 let vs2_bit = mask_bit(&vs2_snap, i);
163 let result = !found_first && !vs2_bit;
165 if vs2_bit {
166 found_first = true;
167 }
168 write_mask_bit(env.write_vregs(), vd, i, result)
169 .expect("`i < vl <= VLEN`, so the mask bit is within `vd`; qed");
170 }
171 env.mark_vs_dirty();
172}
173
174#[inline(always)]
179#[doc(hidden)]
180#[cfg_attr(feature = "no-panic", no_panic_const::no_panic)]
181pub fn execute_vmsof<Reg, Env>(
182 env: &mut Env,
183 vd: VReg,
184 vs2: VReg,
185 vm: bool,
186 vl: BoundedVl<Env::Hart>,
187) where
188 Reg: Register,
189 Env: VectorRegistersExt<Hart: HartConfig<Reg = Reg>>,
190{
191 let mask_buf = snapshot_mask(env.read_vregs(), vm);
192 let vs2_snap = *env.read_vregs().get(vs2);
193 let mut found_first = false;
194 for i in vl.indices() {
195 if !mask_bit(&mask_buf, i) {
196 continue;
197 }
198 let vs2_bit = mask_bit(&vs2_snap, i);
199 let result = !found_first && vs2_bit;
201 if vs2_bit && !found_first {
202 found_first = true;
203 }
204 write_mask_bit(env.write_vregs(), vd, i, result)
205 .expect("`i < vl <= VLEN`, so the mask bit is within `vd`; qed");
206 }
207 env.mark_vs_dirty();
208}
209
210#[inline(always)]
216#[doc(hidden)]
217#[cfg_attr(feature = "no-panic", no_panic_const::no_panic)]
218pub fn execute_vmsif<Reg, Env>(
219 env: &mut Env,
220 vd: VReg,
221 vs2: VReg,
222 vm: bool,
223 vl: BoundedVl<Env::Hart>,
224) where
225 Reg: Register,
226 Env: VectorRegistersExt<Hart: HartConfig<Reg = Reg>>,
227{
228 let mask_buf = snapshot_mask(env.read_vregs(), vm);
229 let vs2_snap = *env.read_vregs().get(vs2);
230 let mut found_first = false;
231 for i in vl.indices() {
232 if !mask_bit(&mask_buf, i) {
233 continue;
234 }
235 let vs2_bit = mask_bit(&vs2_snap, i);
236 let result = !found_first;
238 if vs2_bit {
239 found_first = true;
240 }
241 write_mask_bit(env.write_vregs(), vd, i, result)
242 .expect("`i < vl <= VLEN`, so the mask bit is within `vd`; qed");
243 }
244 env.mark_vs_dirty();
245}
246
247#[inline(always)]
260#[doc(hidden)]
261#[cfg_attr(feature = "no-panic", no_panic_const::no_panic)]
262pub fn execute_viota<Reg, Env>(env: &mut Env, vd: VRegGroup<Env::Hart>, vs2: VReg, vm: bool)
263where
264 Reg: Register,
265 Env: VectorRegistersExt<Hart: HartConfig<Reg = Reg>>,
266{
267 let vl = vd.vl();
268 let mask_buf = snapshot_mask(env.read_vregs(), vm);
269 let vs2_snap = *env.read_vregs().get(vs2);
270 let mut prefix_count = 0u64;
274 for i in vl.indices() {
275 if !mask_bit(&mask_buf, i) {
276 continue;
277 }
278 env.write_vregs()
279 .write(vd, i, prefix_count)
280 .expect("`i < vl` of `vd`; qed");
281 if mask_bit(&vs2_snap, i) {
282 prefix_count += 1;
283 }
284 }
285 env.mark_vs_dirty();
286}
287
288#[inline(always)]
296#[doc(hidden)]
297#[cfg_attr(feature = "no-panic", no_panic_const::no_panic)]
298pub fn execute_vid<Reg, Env>(env: &mut Env, vd: VRegGroup<Env::Hart>, vm: bool)
299where
300 Reg: Register,
301 Env: VectorRegistersExt<Hart: HartConfig<Reg = Reg>>,
302{
303 let vl = vd.vl();
304 let mask_buf = snapshot_mask(env.read_vregs(), vm);
305 for i in vl.indices() {
306 if !mask_bit(&mask_buf, i) {
307 continue;
308 }
309 env.write_vregs()
310 .write(vd, i, u64::from(i))
311 .expect("`i < vl` of `vd`; qed");
312 }
313 env.mark_vs_dirty();
314}