ab_riscv_interpreter/v/zve64x/store/
zve64x_store_helpers.rs1use crate::v::vector_registers::VectorRegistersExt;
4use crate::v::zve64x::load::zve64x_load_helpers::{
5 check_register_group_alignment, mask_bit, read_group_element, snapshot_mask,
6};
7use crate::v::zve64x::zve64x_helpers::INSTRUCTION_SIZE;
8use crate::{ExecutionError, ProgramCounter, VirtualMemory, VirtualMemoryError};
9use ab_riscv_primitives::prelude::*;
10use core::fmt;
11
12#[inline(always)]
18unsafe fn index_buf_to_u64(buf: [u8; Eew::MAX_BYTES as usize], index_eew: Eew) -> u64 {
19 match index_eew {
20 Eew::E8 => u64::from(buf[0]),
21 Eew::E16 => u64::from(u16::from_le_bytes([buf[0], buf[1]])),
22 Eew::E32 => u64::from(u32::from_le_bytes([buf[0], buf[1], buf[2], buf[3]])),
23 Eew::E64 => u64::from_le_bytes(buf),
24 }
25}
26
27#[inline(always)]
29fn write_mem_element(
30 memory: &mut impl VirtualMemory,
31 addr: u64,
32 eew: Eew,
33 buf: [u8; Eew::MAX_BYTES as usize],
34) -> Result<(), VirtualMemoryError> {
35 memory.write_slice(addr, &buf[..usize::from(eew.bytes())])
36}
37
38#[inline(always)]
44#[doc(hidden)]
45pub fn validate_segment_store_registers<Reg, Memory, PC, CustomError>(
46 program_counter: &PC,
47 vs3: VReg,
48 group_regs: u8,
49 nf: u8,
50) -> Result<(), ExecutionError<Reg::Type, CustomError>>
51where
52 Reg: Register,
53 PC: ProgramCounter<Reg::Type, Memory, CustomError>,
54{
55 check_register_group_alignment::<Reg, _, _, _>(program_counter, vs3, group_regs)?;
56 let total = u32::from(vs3.bits()) + u32::from(nf) * u32::from(group_regs);
57 if total > 32 {
58 return Err(ExecutionError::IllegalInstruction {
59 address: program_counter.old_pc(INSTRUCTION_SIZE),
60 });
61 }
62 Ok(())
63}
64
65#[inline(always)]
79#[expect(clippy::too_many_arguments, reason = "Internal API")]
80#[doc(hidden)]
81pub unsafe fn execute_unit_stride_store<Reg, ExtState, Memory, CustomError>(
82 ext_state: &mut ExtState,
83 memory: &mut Memory,
84 vs3: VReg,
85 vm: bool,
86 vl: u32,
87 vstart: u16,
88 base: u64,
89 eew: Eew,
90 group_regs: u8,
91 nf: u8,
92) -> Result<(), ExecutionError<Reg::Type, CustomError>>
93where
94 Reg: Register,
95 ExtState: VectorRegistersExt<Reg, CustomError>,
96 [(); ExtState::ELEN as usize]:,
97 [(); ExtState::VLEN as usize]:,
98 [(); ExtState::VLENB as usize]:,
99 Memory: VirtualMemory,
100 CustomError: fmt::Debug,
101{
102 let elem_bytes = eew.bytes();
103 let segment_stride = u64::from(nf * elem_bytes);
104 let mask_buf = unsafe { snapshot_mask(ext_state.read_vreg(), vm, vl) };
106 for i in u32::from(vstart)..vl {
107 if !vm && !mask_bit(&mask_buf, i) {
108 continue;
109 }
110 let elem_base = base.wrapping_add(u64::from(i) * segment_stride);
111 for f in 0..nf {
112 let addr = elem_base.wrapping_add(u64::from(f) * u64::from(elem_bytes));
113 let field_base_reg = vs3.bits() + f * group_regs;
114 let data = unsafe {
128 read_group_element(ext_state.read_vreg(), usize::from(field_base_reg), i, eew)
129 };
130 if let Err(error) = write_mem_element(memory, addr, eew, data) {
133 ext_state.set_vstart(i as u16);
134 return Err(ExecutionError::MemoryAccess(error));
135 }
136 }
137 }
138 ext_state.reset_vstart();
139 Ok(())
140}
141
142#[inline(always)]
156#[expect(clippy::too_many_arguments, reason = "Internal API")]
157#[doc(hidden)]
158pub unsafe fn execute_strided_store<Reg, ExtState, Memory, CustomError>(
159 ext_state: &mut ExtState,
160 memory: &mut Memory,
161 vs3: VReg,
162 vm: bool,
163 vl: u32,
164 vstart: u16,
165 base: u64,
166 stride: i64,
167 eew: Eew,
168 group_regs: u8,
169 nf: u8,
170) -> Result<(), ExecutionError<Reg::Type, CustomError>>
171where
172 Reg: Register,
173 ExtState: VectorRegistersExt<Reg, CustomError>,
174 [(); ExtState::ELEN as usize]:,
175 [(); ExtState::VLEN as usize]:,
176 [(); ExtState::VLENB as usize]:,
177 Memory: VirtualMemory,
178 CustomError: fmt::Debug,
179{
180 let elem_bytes = eew.bytes();
181 let mask_buf = unsafe { snapshot_mask(ext_state.read_vreg(), vm, vl) };
183 for i in u32::from(vstart)..vl {
184 if !vm && !mask_bit(&mask_buf, i) {
185 continue;
186 }
187 let elem_base = base.wrapping_add(i64::from(i).wrapping_mul(stride).cast_unsigned());
188 for f in 0..nf {
189 let addr = elem_base.wrapping_add(u64::from(f) * u64::from(elem_bytes));
190 let field_base_reg = vs3.bits() + f * group_regs;
191 let data = unsafe {
195 read_group_element(ext_state.read_vreg(), usize::from(field_base_reg), i, eew)
196 };
197 if let Err(error) = write_mem_element(memory, addr, eew, data) {
200 ext_state.set_vstart(i as u16);
201 return Err(ExecutionError::MemoryAccess(error));
202 }
203 }
204 }
205 ext_state.reset_vstart();
206 Ok(())
207}
208
209#[inline(always)]
228#[expect(clippy::too_many_arguments, reason = "Internal API")]
229#[doc(hidden)]
230pub unsafe fn execute_indexed_store<Reg, ExtState, Memory, CustomError>(
231 ext_state: &mut ExtState,
232 memory: &mut Memory,
233 vs3: VReg,
234 vs2: VReg,
235 vm: bool,
236 vl: u32,
237 vstart: u32,
238 base: u64,
239 data_eew: Eew,
240 index_eew: Eew,
241 data_group_regs: u8,
242 nf: u8,
243) -> Result<(), ExecutionError<Reg::Type, CustomError>>
244where
245 Reg: Register,
246 ExtState: VectorRegistersExt<Reg, CustomError>,
247 [(); ExtState::ELEN as usize]:,
248 [(); ExtState::VLEN as usize]:,
249 [(); ExtState::VLENB as usize]:,
250 Memory: VirtualMemory,
251 CustomError: fmt::Debug,
252{
253 let data_elem_bytes = data_eew.bytes();
254 let mask_buf = unsafe { snapshot_mask(ext_state.read_vreg(), vm, vl) };
256 for i in vstart..vl {
257 if !vm && !mask_bit(&mask_buf, i) {
258 continue;
259 }
260 let index_buf = unsafe {
263 read_group_element(ext_state.read_vreg(), usize::from(vs2.bits()), i, index_eew)
264 };
265 let offset = unsafe { index_buf_to_u64(index_buf, index_eew) };
267 let elem_base = base.wrapping_add(offset);
268 for f in 0..nf {
269 let addr = elem_base.wrapping_add(u64::from(f) * u64::from(data_elem_bytes));
270 let field_base_reg = vs3.bits() + f * data_group_regs;
271 let data = unsafe {
275 read_group_element(
276 ext_state.read_vreg(),
277 usize::from(field_base_reg),
278 i,
279 data_eew,
280 )
281 };
282 if let Err(error) = write_mem_element(memory, addr, data_eew, data) {
285 ext_state.set_vstart(i as u16);
286 return Err(ExecutionError::MemoryAccess(error));
287 }
288 }
289 }
290 ext_state.reset_vstart();
291 Ok(())
292}