1#[cfg(test)]
4mod tests;
5pub mod zvbb_helpers;
6pub mod zvkb;
7
8use crate::v::vector_registers::{VectorRegisters, VectorRegistersExt};
9use crate::v::zvexx::arith::zvexx_arith_helpers;
10use crate::v::zvexx::carry::zvexx_carry_helpers;
11use crate::v::zvexx::config::zvexx_config_helpers;
12use crate::v::zvexx::fixed_point::zvexx_fixed_point_helpers;
13use crate::v::zvexx::load::zvexx_load_helpers;
14use crate::v::zvexx::mask::zvexx_mask_helpers;
15use crate::v::zvexx::muldiv::zvexx_muldiv_helpers;
16use crate::v::zvexx::perm::zvexx_perm_helpers;
17use crate::v::zvexx::reduction::zvexx_reduction_helpers;
18use crate::v::zvexx::store::zvexx_store_helpers;
19use crate::v::zvexx::widen_narrow::zvexx_widen_narrow_helpers;
20use crate::v::zvexx::zvexx_helpers;
21use crate::zicsr::zicsr_helpers;
22use crate::zvbb::zvkb::zvkb_helpers;
23use crate::{
24 CsrError, Csrs, ExecutableInstruction, ExecutableInstructionCsr, ExecutableInstructionOperands,
25 ExecutionError, ExecutionResult, FetchInstructionResult, InstructionFetcher,
26 OpaqueThreadedExecutionResult, PackedAddress, ProgramCounter, RegisterFile,
27 Rs1Rs2OperandValues, Rs1Rs2Operands, ThreadedExecutableInstruction, ThreadedExecutionResult,
28 VirtualMemory,
29};
30use ab_riscv_macros::instruction_execution;
31use ab_riscv_primitives::prelude::*;
32
33#[instruction_execution]
34const impl<Reg, Hart> ExecutableInstructionOperands for ZvbbInstruction<Hart>
35where
36 Reg: Register,
37 Hart: VectorHartConfig<Reg = Reg>,
38{
39}
40
41#[instruction_execution]
42const impl<Reg, Hart, Env> ExecutableInstructionCsr<Env> for ZvbbInstruction<Hart>
43where
44 Reg: Register,
45 Hart: VectorHartConfig<Reg = Reg>,
46{
47}
48
49#[instruction_execution]
50impl<Reg, Hart, Regs, Env, Memory, PC> ExecutableInstruction<Regs, Env, Memory, PC>
51 for ZvbbInstruction<Hart>
52where
53 Reg: Register,
54 Hart: VectorHartConfig<Reg = Reg>,
55 Regs: RegisterFile<Reg>,
56 Env: VectorRegistersExt<Hart = Hart>,
57 Memory: VirtualMemory,
58 PC: ProgramCounter<Reg::Type, Memory>,
59{
60 #[inline(always)]
61 #[cfg_attr(feature = "no-panic", no_panic_const::no_panic)]
62 fn execute(
63 self,
64 Rs1Rs2OperandValues {
65 rs1_value,
66 rs2_value,
67 }: Rs1Rs2OperandValues<Reg::Type>,
68 _regs: &mut Regs,
69 env: &mut Env,
70 memory: &mut Memory,
71 program_counter: &PC,
72 ) -> ExecutionResult<Reg> {
73 match self {
74 Self::VbrevV { vd, vs2, vm } => {
76 if !zvexx_helpers::non_memory_instruction_allowed::<Reg, _>(env) {
77 ::core::hint::cold_path();
78 return ExecutionResult::Err(ExecutionError::IllegalInstruction {
79 address: PackedAddress::new(
80 program_counter.old_pc(zvexx_helpers::INSTRUCTION_SIZE),
81 ),
82 });
83 }
84 let Some(config) = env.vector_config() else {
85 ::core::hint::cold_path();
86 return ExecutionResult::Err(ExecutionError::IllegalInstruction {
87 address: PackedAddress::new(
88 program_counter.old_pc(zvexx_helpers::INSTRUCTION_SIZE),
89 ),
90 });
91 };
92 let sew = config.vtype().vsew();
93 let vd = zvexx_helpers::vreg_group::<Reg, Env, _, _>(
94 program_counter,
95 config,
96 vd,
97 sew.as_eew(),
98 )?;
99 let vs2 = zvexx_helpers::vreg_group::<Reg, Env, _, _>(
100 program_counter,
101 config,
102 vs2,
103 sew.as_eew(),
104 )?;
105 zvbb_helpers::execute_vbrev::<Reg, _>(env, vd, vs2, sew, vm);
106 }
107 Self::VclzV { vd, vs2, vm } => {
109 if !zvexx_helpers::non_memory_instruction_allowed::<Reg, _>(env) {
110 ::core::hint::cold_path();
111 return ExecutionResult::Err(ExecutionError::IllegalInstruction {
112 address: PackedAddress::new(
113 program_counter.old_pc(zvexx_helpers::INSTRUCTION_SIZE),
114 ),
115 });
116 }
117 let Some(config) = env.vector_config() else {
118 ::core::hint::cold_path();
119 return ExecutionResult::Err(ExecutionError::IllegalInstruction {
120 address: PackedAddress::new(
121 program_counter.old_pc(zvexx_helpers::INSTRUCTION_SIZE),
122 ),
123 });
124 };
125 let sew = config.vtype().vsew();
126 let vd = zvexx_helpers::vreg_group::<Reg, Env, _, _>(
127 program_counter,
128 config,
129 vd,
130 sew.as_eew(),
131 )?;
132 let vs2 = zvexx_helpers::vreg_group::<Reg, Env, _, _>(
133 program_counter,
134 config,
135 vs2,
136 sew.as_eew(),
137 )?;
138 zvbb_helpers::execute_vclz::<Reg, _>(env, vd, vs2, sew, vm);
139 }
140 Self::VctzV { vd, vs2, vm } => {
142 if !zvexx_helpers::non_memory_instruction_allowed::<Reg, _>(env) {
143 ::core::hint::cold_path();
144 return ExecutionResult::Err(ExecutionError::IllegalInstruction {
145 address: PackedAddress::new(
146 program_counter.old_pc(zvexx_helpers::INSTRUCTION_SIZE),
147 ),
148 });
149 }
150 let Some(config) = env.vector_config() else {
151 ::core::hint::cold_path();
152 return ExecutionResult::Err(ExecutionError::IllegalInstruction {
153 address: PackedAddress::new(
154 program_counter.old_pc(zvexx_helpers::INSTRUCTION_SIZE),
155 ),
156 });
157 };
158 let sew = config.vtype().vsew();
159 let vd = zvexx_helpers::vreg_group::<Reg, Env, _, _>(
160 program_counter,
161 config,
162 vd,
163 sew.as_eew(),
164 )?;
165 let vs2 = zvexx_helpers::vreg_group::<Reg, Env, _, _>(
166 program_counter,
167 config,
168 vs2,
169 sew.as_eew(),
170 )?;
171 zvbb_helpers::execute_vctz::<Reg, _>(env, vd, vs2, sew, vm);
172 }
173 Self::VcpopV { vd, vs2, vm } => {
175 if !zvexx_helpers::non_memory_instruction_allowed::<Reg, _>(env) {
176 ::core::hint::cold_path();
177 return ExecutionResult::Err(ExecutionError::IllegalInstruction {
178 address: PackedAddress::new(
179 program_counter.old_pc(zvexx_helpers::INSTRUCTION_SIZE),
180 ),
181 });
182 }
183 let Some(config) = env.vector_config() else {
184 ::core::hint::cold_path();
185 return ExecutionResult::Err(ExecutionError::IllegalInstruction {
186 address: PackedAddress::new(
187 program_counter.old_pc(zvexx_helpers::INSTRUCTION_SIZE),
188 ),
189 });
190 };
191 let sew = config.vtype().vsew();
192 let vd = zvexx_helpers::vreg_group::<Reg, Env, _, _>(
193 program_counter,
194 config,
195 vd,
196 sew.as_eew(),
197 )?;
198 let vs2 = zvexx_helpers::vreg_group::<Reg, Env, _, _>(
199 program_counter,
200 config,
201 vs2,
202 sew.as_eew(),
203 )?;
204 zvbb_helpers::execute_vcpop::<Reg, _>(env, vd, vs2, vm);
205 }
206 Self::VwsllVv { vd, vs2, vs1, vm } => {
209 if !zvexx_helpers::non_memory_instruction_allowed::<Reg, _>(env) {
210 ::core::hint::cold_path();
211 return ExecutionResult::Err(ExecutionError::IllegalInstruction {
212 address: PackedAddress::new(
213 program_counter.old_pc(zvexx_helpers::INSTRUCTION_SIZE),
214 ),
215 });
216 }
217 let Some(config) = env.vector_config() else {
218 ::core::hint::cold_path();
219 return ExecutionResult::Err(ExecutionError::IllegalInstruction {
220 address: PackedAddress::new(
221 program_counter.old_pc(zvexx_helpers::INSTRUCTION_SIZE),
222 ),
223 });
224 };
225 let sew = config.vtype().vsew();
226 let Some(widening_sew) = zvexx_helpers::WideningSew::<Env::Hart>::new(sew) else {
227 ::core::hint::cold_path();
228 return ExecutionResult::Err(ExecutionError::IllegalInstruction {
229 address: PackedAddress::new(
230 program_counter.old_pc(zvexx_helpers::INSTRUCTION_SIZE),
231 ),
232 });
233 };
234 let vd = zvexx_helpers::vreg_group::<Reg, Env, _, _>(
235 program_counter,
236 config,
237 vd,
238 widening_sew.wide().as_eew(),
239 )?;
240 let vs2 = zvexx_helpers::vreg_group::<Reg, Env, _, _>(
241 program_counter,
242 config,
243 vs2,
244 sew.as_eew(),
245 )?;
246 let vs1 = zvexx_helpers::vreg_group::<Reg, Env, _, _>(
247 program_counter,
248 config,
249 vs1,
250 sew.as_eew(),
251 )?;
252 zvexx_helpers::check_destination_overlap::<Reg, Env, _, _>(
254 program_counter,
255 vd,
256 vs2,
257 )?;
258 zvexx_helpers::check_destination_overlap::<Reg, Env, _, _>(
259 program_counter,
260 vd,
261 vs1,
262 )?;
263 zvbb_helpers::execute_vwsll::<Reg, _>(
264 env,
265 vd,
266 vs2,
267 zvbb_helpers::OpSrc::Vreg(vs1),
268 widening_sew,
269 vm,
270 );
271 }
272 Self::VwsllVx {
273 vm,
274 vd,
275 vs2,
276 rs1: _,
277 } => {
278 if !zvexx_helpers::non_memory_instruction_allowed::<Reg, _>(env) {
279 ::core::hint::cold_path();
280 return ExecutionResult::Err(ExecutionError::IllegalInstruction {
281 address: PackedAddress::new(
282 program_counter.old_pc(zvexx_helpers::INSTRUCTION_SIZE),
283 ),
284 });
285 }
286 let Some(config) = env.vector_config() else {
287 ::core::hint::cold_path();
288 return ExecutionResult::Err(ExecutionError::IllegalInstruction {
289 address: PackedAddress::new(
290 program_counter.old_pc(zvexx_helpers::INSTRUCTION_SIZE),
291 ),
292 });
293 };
294 let sew = config.vtype().vsew();
295 let Some(widening_sew) = zvexx_helpers::WideningSew::<Env::Hart>::new(sew) else {
296 ::core::hint::cold_path();
297 return ExecutionResult::Err(ExecutionError::IllegalInstruction {
298 address: PackedAddress::new(
299 program_counter.old_pc(zvexx_helpers::INSTRUCTION_SIZE),
300 ),
301 });
302 };
303 let vd = zvexx_helpers::vreg_group::<Reg, Env, _, _>(
304 program_counter,
305 config,
306 vd,
307 widening_sew.wide().as_eew(),
308 )?;
309 let vs2 = zvexx_helpers::vreg_group::<Reg, Env, _, _>(
310 program_counter,
311 config,
312 vs2,
313 sew.as_eew(),
314 )?;
315 zvexx_helpers::check_destination_overlap::<Reg, Env, _, _>(
317 program_counter,
318 vd,
319 vs2,
320 )?;
321 let scalar = rs1_value.as_i64().cast_unsigned();
322 zvbb_helpers::execute_vwsll::<Reg, _>(
323 env,
324 vd,
325 vs2,
326 zvbb_helpers::OpSrc::Scalar(scalar),
327 widening_sew,
328 vm,
329 );
330 }
331 Self::VwsllVi { vd, vs2, uimm, 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 Some(widening_sew) = zvexx_helpers::WideningSew::<Env::Hart>::new(sew) else {
351 ::core::hint::cold_path();
352 return ExecutionResult::Err(ExecutionError::IllegalInstruction {
353 address: PackedAddress::new(
354 program_counter.old_pc(zvexx_helpers::INSTRUCTION_SIZE),
355 ),
356 });
357 };
358 let vd = zvexx_helpers::vreg_group::<Reg, Env, _, _>(
359 program_counter,
360 config,
361 vd,
362 widening_sew.wide().as_eew(),
363 )?;
364 let vs2 = zvexx_helpers::vreg_group::<Reg, Env, _, _>(
365 program_counter,
366 config,
367 vs2,
368 sew.as_eew(),
369 )?;
370 zvexx_helpers::check_destination_overlap::<Reg, Env, _, _>(
372 program_counter,
373 vd,
374 vs2,
375 )?;
376 zvbb_helpers::execute_vwsll::<Reg, _>(
377 env,
378 vd,
379 vs2,
380 zvbb_helpers::OpSrc::Scalar(u64::from(uimm)),
381 widening_sew,
382 vm,
383 );
384 }
385 }
386 ExecutionResult::ContinueNoWrite
387 }
388}