1#[cfg(test)]
4mod tests;
5pub mod zvbb_helpers;
6pub mod zvkb;
7
8use crate::v::vector_registers::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> ExecutableInstructionOperands for ZvbbInstruction<Reg> where Reg: Register {}
35
36#[instruction_execution]
37const impl<Reg, Env> ExecutableInstructionCsr<Env> for ZvbbInstruction<Reg> where Reg: Register {}
38
39#[instruction_execution]
40impl<Reg, Regs, Env, Memory, PC> ExecutableInstruction<Regs, Env, Memory, PC>
41 for ZvbbInstruction<Reg>
42where
43 Reg: Register,
44 Regs: RegisterFile<Reg>,
45 Env: VectorRegistersExt<Reg>,
46 [(); SUPPORTED_ELEN_VLEN::<{ Env::ELEN }, { Env::VLEN }>]:,
47 Memory: VirtualMemory,
48 PC: ProgramCounter<Reg::Type, Memory>,
49{
50 #[inline(always)]
51 #[cfg_attr(feature = "no-panic", no_panic_const::no_panic)]
52 fn execute(
53 self,
54 Rs1Rs2OperandValues {
55 rs1_value,
56 rs2_value,
57 }: Rs1Rs2OperandValues<<Self::Reg as Register>::Type>,
58 _regs: &mut Regs,
59 env: &mut Env,
60 memory: &mut Memory,
61 program_counter: &mut PC,
62 ) -> ExecutionResult<Self::Reg> {
63 match self {
64 Self::VbrevV { vd, vs2, vm } => {
66 if !env.vector_instructions_allowed() {
67 ::core::hint::cold_path();
68 return ExecutionResult::Err(ExecutionError::IllegalInstruction {
69 address: PackedAddress::new(
70 program_counter.old_pc(zvexx_helpers::INSTRUCTION_SIZE),
71 ),
72 });
73 }
74 if !vm && vd == VReg::V0 {
75 ::core::hint::cold_path();
76 return ExecutionResult::Err(ExecutionError::IllegalInstruction {
77 address: PackedAddress::new(
78 program_counter.old_pc(zvexx_helpers::INSTRUCTION_SIZE),
79 ),
80 });
81 }
82 let Some(vtype) = env.vtype() else {
83 ::core::hint::cold_path();
84 return ExecutionResult::Err(ExecutionError::IllegalInstruction {
85 address: PackedAddress::new(
86 program_counter.old_pc(zvexx_helpers::INSTRUCTION_SIZE),
87 ),
88 });
89 };
90 let group_regs = vtype.vlmul().register_count();
91 zvbb_helpers::check_vreg_group_alignment::<Reg, _, _>(
92 program_counter,
93 vd,
94 group_regs,
95 )?;
96 zvbb_helpers::check_vreg_group_alignment::<Reg, _, _>(
97 program_counter,
98 vs2,
99 group_regs,
100 )?;
101 let sew = vtype.vsew();
102 unsafe {
104 zvbb_helpers::execute_vbrev::<Reg, _>(env, vd, vs2, sew, vm);
105 }
106 }
107 Self::VclzV { vd, vs2, vm } => {
109 if !env.vector_instructions_allowed() {
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 if !vm && vd == VReg::V0 {
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 Some(vtype) = env.vtype() else {
126 ::core::hint::cold_path();
127 return ExecutionResult::Err(ExecutionError::IllegalInstruction {
128 address: PackedAddress::new(
129 program_counter.old_pc(zvexx_helpers::INSTRUCTION_SIZE),
130 ),
131 });
132 };
133 let group_regs = vtype.vlmul().register_count();
134 zvbb_helpers::check_vreg_group_alignment::<Reg, _, _>(
135 program_counter,
136 vd,
137 group_regs,
138 )?;
139 zvbb_helpers::check_vreg_group_alignment::<Reg, _, _>(
140 program_counter,
141 vs2,
142 group_regs,
143 )?;
144 let sew = vtype.vsew();
145 unsafe {
147 zvbb_helpers::execute_vclz::<Reg, _>(env, vd, vs2, sew, vm);
148 }
149 }
150 Self::VctzV { vd, vs2, vm } => {
152 if !env.vector_instructions_allowed() {
153 ::core::hint::cold_path();
154 return ExecutionResult::Err(ExecutionError::IllegalInstruction {
155 address: PackedAddress::new(
156 program_counter.old_pc(zvexx_helpers::INSTRUCTION_SIZE),
157 ),
158 });
159 }
160 if !vm && vd == VReg::V0 {
161 ::core::hint::cold_path();
162 return ExecutionResult::Err(ExecutionError::IllegalInstruction {
163 address: PackedAddress::new(
164 program_counter.old_pc(zvexx_helpers::INSTRUCTION_SIZE),
165 ),
166 });
167 }
168 let Some(vtype) = env.vtype() else {
169 ::core::hint::cold_path();
170 return ExecutionResult::Err(ExecutionError::IllegalInstruction {
171 address: PackedAddress::new(
172 program_counter.old_pc(zvexx_helpers::INSTRUCTION_SIZE),
173 ),
174 });
175 };
176 let group_regs = vtype.vlmul().register_count();
177 zvbb_helpers::check_vreg_group_alignment::<Reg, _, _>(
178 program_counter,
179 vd,
180 group_regs,
181 )?;
182 zvbb_helpers::check_vreg_group_alignment::<Reg, _, _>(
183 program_counter,
184 vs2,
185 group_regs,
186 )?;
187 let sew = vtype.vsew();
188 unsafe {
190 zvbb_helpers::execute_vctz::<Reg, _>(env, vd, vs2, sew, vm);
191 }
192 }
193 Self::VcpopV { vd, vs2, vm } => {
195 if !env.vector_instructions_allowed() {
196 ::core::hint::cold_path();
197 return ExecutionResult::Err(ExecutionError::IllegalInstruction {
198 address: PackedAddress::new(
199 program_counter.old_pc(zvexx_helpers::INSTRUCTION_SIZE),
200 ),
201 });
202 }
203 if !vm && vd == VReg::V0 {
204 ::core::hint::cold_path();
205 return ExecutionResult::Err(ExecutionError::IllegalInstruction {
206 address: PackedAddress::new(
207 program_counter.old_pc(zvexx_helpers::INSTRUCTION_SIZE),
208 ),
209 });
210 }
211 let Some(vtype) = env.vtype() else {
212 ::core::hint::cold_path();
213 return ExecutionResult::Err(ExecutionError::IllegalInstruction {
214 address: PackedAddress::new(
215 program_counter.old_pc(zvexx_helpers::INSTRUCTION_SIZE),
216 ),
217 });
218 };
219 let group_regs = vtype.vlmul().register_count();
220 zvbb_helpers::check_vreg_group_alignment::<Reg, _, _>(
221 program_counter,
222 vd,
223 group_regs,
224 )?;
225 zvbb_helpers::check_vreg_group_alignment::<Reg, _, _>(
226 program_counter,
227 vs2,
228 group_regs,
229 )?;
230 let sew = vtype.vsew();
231 unsafe {
233 zvbb_helpers::execute_vcpop::<Reg, _>(env, vd, vs2, sew, vm);
234 }
235 }
236 Self::VwsllVv { vd, vs2, vs1, vm } => {
239 if !env.vector_instructions_allowed() {
240 ::core::hint::cold_path();
241 return ExecutionResult::Err(ExecutionError::IllegalInstruction {
242 address: PackedAddress::new(
243 program_counter.old_pc(zvexx_helpers::INSTRUCTION_SIZE),
244 ),
245 });
246 }
247 if !vm && vd == VReg::V0 {
248 ::core::hint::cold_path();
249 return ExecutionResult::Err(ExecutionError::IllegalInstruction {
250 address: PackedAddress::new(
251 program_counter.old_pc(zvexx_helpers::INSTRUCTION_SIZE),
252 ),
253 });
254 }
255 let Some(vtype) = env.vtype() else {
256 ::core::hint::cold_path();
257 return ExecutionResult::Err(ExecutionError::IllegalInstruction {
258 address: PackedAddress::new(
259 program_counter.old_pc(zvexx_helpers::INSTRUCTION_SIZE),
260 ),
261 });
262 };
263 let sew = vtype.vsew();
264 let Some(double_sew) = sew.double_width() else {
265 ::core::hint::cold_path();
266 return ExecutionResult::Err(ExecutionError::IllegalInstruction {
267 address: PackedAddress::new(
268 program_counter.old_pc(zvexx_helpers::INSTRUCTION_SIZE),
269 ),
270 });
271 };
272 let group_regs = vtype.vlmul().register_count();
273 let Some(dest_group_regs) =
274 vtype.vlmul().data_register_count(double_sew.as_eew(), sew)
275 else {
276 ::core::hint::cold_path();
277 return ExecutionResult::Err(ExecutionError::IllegalInstruction {
278 address: PackedAddress::new(
279 program_counter.old_pc(zvexx_helpers::INSTRUCTION_SIZE),
280 ),
281 });
282 };
283 zvbb_helpers::check_vreg_group_alignment::<Reg, _, _>(
284 program_counter,
285 vd,
286 dest_group_regs,
287 )?;
288 zvbb_helpers::check_vreg_group_alignment::<Reg, _, _>(
289 program_counter,
290 vs2,
291 group_regs,
292 )?;
293 zvbb_helpers::check_vreg_group_alignment::<Reg, _, _>(
294 program_counter,
295 vs1,
296 group_regs,
297 )?;
298 unsafe {
300 zvbb_helpers::execute_vwsll::<Reg, _>(
301 env,
302 vd,
303 vs2,
304 zvbb_helpers::OpSrc::Vreg(vs1),
305 sew,
306 double_sew,
307 vm,
308 );
309 }
310 }
311 Self::VwsllVx {
312 vm,
313 vd,
314 vs2,
315 rs1: _,
316 } => {
317 if !env.vector_instructions_allowed() {
318 ::core::hint::cold_path();
319 return ExecutionResult::Err(ExecutionError::IllegalInstruction {
320 address: PackedAddress::new(
321 program_counter.old_pc(zvexx_helpers::INSTRUCTION_SIZE),
322 ),
323 });
324 }
325 if !vm && vd == VReg::V0 {
326 ::core::hint::cold_path();
327 return ExecutionResult::Err(ExecutionError::IllegalInstruction {
328 address: PackedAddress::new(
329 program_counter.old_pc(zvexx_helpers::INSTRUCTION_SIZE),
330 ),
331 });
332 }
333 let Some(vtype) = env.vtype() else {
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 sew = vtype.vsew();
342 let Some(double_sew) = sew.double_width() else {
343 ::core::hint::cold_path();
344 return ExecutionResult::Err(ExecutionError::IllegalInstruction {
345 address: PackedAddress::new(
346 program_counter.old_pc(zvexx_helpers::INSTRUCTION_SIZE),
347 ),
348 });
349 };
350 let group_regs = vtype.vlmul().register_count();
351 let Some(dest_group_regs) =
352 vtype.vlmul().data_register_count(double_sew.as_eew(), sew)
353 else {
354 ::core::hint::cold_path();
355 return ExecutionResult::Err(ExecutionError::IllegalInstruction {
356 address: PackedAddress::new(
357 program_counter.old_pc(zvexx_helpers::INSTRUCTION_SIZE),
358 ),
359 });
360 };
361 zvbb_helpers::check_vreg_group_alignment::<Reg, _, _>(
362 program_counter,
363 vd,
364 dest_group_regs,
365 )?;
366 zvbb_helpers::check_vreg_group_alignment::<Reg, _, _>(
367 program_counter,
368 vs2,
369 group_regs,
370 )?;
371 let scalar = rs1_value.as_i64().cast_unsigned();
372 unsafe {
374 zvbb_helpers::execute_vwsll::<Reg, _>(
375 env,
376 vd,
377 vs2,
378 zvbb_helpers::OpSrc::Scalar(scalar),
379 sew,
380 double_sew,
381 vm,
382 );
383 }
384 }
385 Self::VwsllVi { vd, vs2, uimm, vm } => {
387 if !env.vector_instructions_allowed() {
388 ::core::hint::cold_path();
389 return ExecutionResult::Err(ExecutionError::IllegalInstruction {
390 address: PackedAddress::new(
391 program_counter.old_pc(zvexx_helpers::INSTRUCTION_SIZE),
392 ),
393 });
394 }
395 if !vm && vd == VReg::V0 {
396 ::core::hint::cold_path();
397 return ExecutionResult::Err(ExecutionError::IllegalInstruction {
398 address: PackedAddress::new(
399 program_counter.old_pc(zvexx_helpers::INSTRUCTION_SIZE),
400 ),
401 });
402 }
403 let Some(vtype) = env.vtype() else {
404 ::core::hint::cold_path();
405 return ExecutionResult::Err(ExecutionError::IllegalInstruction {
406 address: PackedAddress::new(
407 program_counter.old_pc(zvexx_helpers::INSTRUCTION_SIZE),
408 ),
409 });
410 };
411 let sew = vtype.vsew();
412 let Some(double_sew) = sew.double_width() else {
413 ::core::hint::cold_path();
414 return ExecutionResult::Err(ExecutionError::IllegalInstruction {
415 address: PackedAddress::new(
416 program_counter.old_pc(zvexx_helpers::INSTRUCTION_SIZE),
417 ),
418 });
419 };
420 let group_regs = vtype.vlmul().register_count();
421 let Some(dest_group_regs) =
422 vtype.vlmul().data_register_count(double_sew.as_eew(), sew)
423 else {
424 ::core::hint::cold_path();
425 return ExecutionResult::Err(ExecutionError::IllegalInstruction {
426 address: PackedAddress::new(
427 program_counter.old_pc(zvexx_helpers::INSTRUCTION_SIZE),
428 ),
429 });
430 };
431 zvbb_helpers::check_vreg_group_alignment::<Reg, _, _>(
432 program_counter,
433 vd,
434 dest_group_regs,
435 )?;
436 zvbb_helpers::check_vreg_group_alignment::<Reg, _, _>(
437 program_counter,
438 vs2,
439 group_regs,
440 )?;
441 unsafe {
443 zvbb_helpers::execute_vwsll::<Reg, _>(
444 env,
445 vd,
446 vs2,
447 zvbb_helpers::OpSrc::Scalar(u64::from(uimm)),
448 sew,
449 double_sew,
450 vm,
451 );
452 }
453 }
454 }
455 ExecutionResult::ContinueNoWrite
456 }
457}