ab_riscv_interpreter/zvbb/zvkb/
zvkb_helpers.rs1use crate::v::vector_registers::{VRegGroup, VectorRegistersExt};
4pub use crate::v::zvexx::arith::zvexx_arith_helpers::OpSrc;
5use crate::v::zvexx::arith::zvexx_arith_helpers::sew_mask;
6use crate::v::zvexx::load::zvexx_load_helpers::mask_bit;
7use ab_riscv_primitives::prelude::*;
8use core::hint::cold_path;
9
10#[inline(always)]
20#[doc(hidden)]
21#[cfg_attr(feature = "no-panic", no_panic_const::no_panic)]
22pub fn execute_vandn<Reg, Env>(
23 env: &mut Env,
24 vd: VRegGroup<Env::Hart>,
25 vs2: VRegGroup<Env::Hart>,
26 src: OpSrc<VRegGroup<Env::Hart>>,
27 vm: bool,
28) where
29 Reg: Register,
30 Env: VectorRegistersExt<Hart: HartConfig<Reg = Reg>>,
31{
32 let vl = vd.vl();
33 let (Some(vs2), Some(src)) = (vs2.with_same_vl(vl), src.with_same_vl(vl)) else {
34 cold_path();
35 return;
36 };
37 for i in vl.indices() {
38 if !vm && !mask_bit(env.read_vregs().get(VReg::V0), i) {
39 continue;
40 }
41 let a = env
42 .read_vregs()
43 .read(vs2, i)
44 .expect("`vs2` has the same `vl` as `vd`, checked above; qed");
45 let b = match src.vreg {
46 Some(vs1) => env
47 .read_vregs()
48 .read(vs1, i)
49 .expect("`vs1` has the same `vl` as `vd`, checked above; qed"),
50 None => src.scalar,
51 };
52 let result = !b & a;
55 env.write_vregs()
56 .write(vd, i, result)
57 .expect("`i < vl` of `vd`; qed");
58 }
59 env.mark_vs_dirty();
60}
61
62#[inline(always)]
72#[doc(hidden)]
73#[cfg_attr(feature = "no-panic", no_panic_const::no_panic)]
74pub fn execute_vbrev8<Reg, Env>(
75 env: &mut Env,
76 vd: VRegGroup<Env::Hart>,
77 vs2: VRegGroup<Env::Hart>,
78 sew: Vsew,
79 vm: bool,
80) where
81 Reg: Register,
82 Env: VectorRegistersExt<Hart: HartConfig<Reg = Reg>>,
83{
84 let vl = vd.vl();
85 let Some(vs2) = vs2.with_same_vl(vl) else {
86 cold_path();
87 return;
88 };
89 let sew_bytes = u32::from(sew.bytes_width());
90 for i in vl.indices() {
91 if !vm && !mask_bit(env.read_vregs().get(VReg::V0), i) {
92 continue;
93 }
94 let elem = env
95 .read_vregs()
96 .read(vs2, i)
97 .expect("`vs2` has the same `vl` as `vd`, checked above; qed");
98 let mut bytes = elem.to_le_bytes();
102 for byte in &mut bytes[..sew_bytes as usize] {
103 *byte = byte.reverse_bits();
104 }
105 let result = u64::from_le_bytes(bytes);
106 env.write_vregs()
107 .write(vd, i, result)
108 .expect("`i < vl` of `vd`; qed");
109 }
110 env.mark_vs_dirty();
111}
112
113#[inline(always)]
122#[doc(hidden)]
123#[cfg_attr(feature = "no-panic", no_panic_const::no_panic)]
124pub fn execute_vrev8<Reg, Env>(
125 env: &mut Env,
126 vd: VRegGroup<Env::Hart>,
127 vs2: VRegGroup<Env::Hart>,
128 sew: Vsew,
129 vm: bool,
130) where
131 Reg: Register,
132 Env: VectorRegistersExt<Hart: HartConfig<Reg = Reg>>,
133{
134 let vl = vd.vl();
135 let Some(vs2) = vs2.with_same_vl(vl) else {
136 cold_path();
137 return;
138 };
139 let sew_bytes = u32::from(sew.bytes_width());
140 for i in vl.indices() {
141 if !vm && !mask_bit(env.read_vregs().get(VReg::V0), i) {
142 continue;
143 }
144 let elem = env
145 .read_vregs()
146 .read(vs2, i)
147 .expect("`vs2` has the same `vl` as `vd`, checked above; qed");
148 let mut bytes = elem.to_le_bytes();
151 bytes[..sew_bytes as usize].reverse();
152 let result = u64::from_le_bytes(bytes);
153 env.write_vregs()
154 .write(vd, i, result)
155 .expect("`i < vl` of `vd`; qed");
156 }
157 env.mark_vs_dirty();
158}
159
160#[inline(always)]
169#[doc(hidden)]
170#[cfg_attr(feature = "no-panic", no_panic_const::no_panic)]
171pub fn execute_vrol<Reg, Env>(
172 env: &mut Env,
173 vd: VRegGroup<Env::Hart>,
174 vs2: VRegGroup<Env::Hart>,
175 src: OpSrc<VRegGroup<Env::Hart>>,
176 sew: Vsew,
177 vm: bool,
178) where
179 Reg: Register,
180 Env: VectorRegistersExt<Hart: HartConfig<Reg = Reg>>,
181{
182 let vl = vd.vl();
183 let (Some(vs2), Some(src)) = (vs2.with_same_vl(vl), src.with_same_vl(vl)) else {
184 cold_path();
185 return;
186 };
187 let sew_bits = u64::from(sew.bits_width());
188 let mask = sew_mask(sew);
189 for i in vl.indices() {
190 if !vm && !mask_bit(env.read_vregs().get(VReg::V0), i) {
191 continue;
192 }
193 let a = env
194 .read_vregs()
195 .read(vs2, i)
196 .expect("`vs2` has the same `vl` as `vd`, checked above; qed");
197 let amount = match src.vreg {
198 Some(vs1) => env
199 .read_vregs()
200 .read(vs1, i)
201 .expect("`vs1` has the same `vl` as `vd`, checked above; qed"),
202 None => src.scalar,
203 };
204 let shift = (amount % sew_bits) as u32;
208 let hi = (a << shift) & mask;
209 let lo = a.unbounded_shr(sew_bits as u32 - shift);
210 let result = hi | lo;
211 env.write_vregs()
212 .write(vd, i, result)
213 .expect("`i < vl` of `vd`; qed");
214 }
215 env.mark_vs_dirty();
216}
217
218#[inline(always)]
229#[doc(hidden)]
230#[cfg_attr(feature = "no-panic", no_panic_const::no_panic)]
231pub fn execute_vror<Reg, Env>(
232 env: &mut Env,
233 vd: VRegGroup<Env::Hart>,
234 vs2: VRegGroup<Env::Hart>,
235 src: OpSrc<VRegGroup<Env::Hart>>,
236 sew: Vsew,
237 vm: bool,
238) where
239 Reg: Register,
240 Env: VectorRegistersExt<Hart: HartConfig<Reg = Reg>>,
241{
242 let vl = vd.vl();
243 let (Some(vs2), Some(src)) = (vs2.with_same_vl(vl), src.with_same_vl(vl)) else {
244 cold_path();
245 return;
246 };
247 let sew_bits = u64::from(sew.bits_width());
248 let mask = sew_mask(sew);
249 for i in vl.indices() {
250 if !vm && !mask_bit(env.read_vregs().get(VReg::V0), i) {
251 continue;
252 }
253 let a = env
254 .read_vregs()
255 .read(vs2, i)
256 .expect("`vs2` has the same `vl` as `vd`, checked above; qed");
257 let amount = match src.vreg {
258 Some(vs1) => env
259 .read_vregs()
260 .read(vs1, i)
261 .expect("`vs1` has the same `vl` as `vd`, checked above; qed"),
262 None => src.scalar,
263 };
264 let shift = (amount % sew_bits) as u32;
268 let lo = a >> shift;
269 let hi = a.unbounded_shl(sew_bits as u32 - shift) & mask;
270 let result = lo | hi;
271 env.write_vregs()
272 .write(vd, i, result)
273 .expect("`i < vl` of `vd`; qed");
274 }
275 env.mark_vs_dirty();
276}