1#[cfg(test)]
4mod tests;
5pub mod zvkb_helpers;
6
7use crate::v::vector_registers::VectorRegistersExt;
8use crate::v::zvexx::arith::zvexx_arith_helpers;
9use crate::v::zvexx::carry::zvexx_carry_helpers;
10use crate::v::zvexx::config::zvexx_config_helpers;
11use crate::v::zvexx::fixed_point::zvexx_fixed_point_helpers;
12use crate::v::zvexx::load::zvexx_load_helpers;
13use crate::v::zvexx::mask::zvexx_mask_helpers;
14use crate::v::zvexx::muldiv::zvexx_muldiv_helpers;
15use crate::v::zvexx::perm::zvexx_perm_helpers;
16use crate::v::zvexx::reduction::zvexx_reduction_helpers;
17use crate::v::zvexx::store::zvexx_store_helpers;
18use crate::v::zvexx::widen_narrow::zvexx_widen_narrow_helpers;
19use crate::v::zvexx::zvexx_helpers;
20use crate::zicsr::zicsr_helpers;
21use crate::{
22 CsrError, Csrs, ExecutableInstruction, ExecutableInstructionCsr, ExecutableInstructionOperands,
23 ExecutionError, ExecutionResult, FetchInstructionResult, InstructionFetcher,
24 OpaqueThreadedExecutionResult, PackedAddress, ProgramCounter, RegisterFile,
25 Rs1Rs2OperandValues, Rs1Rs2Operands, ThreadedExecutableInstruction, ThreadedExecutionResult,
26 VirtualMemory,
27};
28use ab_riscv_macros::instruction_execution;
29use ab_riscv_primitives::prelude::*;
30
31#[instruction_execution]
32const impl<Reg> ExecutableInstructionOperands for ZvkbInstruction<Reg> where Reg: Register {}
33
34#[instruction_execution]
35const impl<Reg, Env> ExecutableInstructionCsr<Env> for ZvkbInstruction<Reg> where Reg: Register {}
36
37#[instruction_execution]
38impl<Reg, Regs, Env, Memory, PC> ExecutableInstruction<Regs, Env, Memory, PC>
39 for ZvkbInstruction<Reg>
40where
41 Reg: Register,
42 Regs: RegisterFile<Reg>,
43 Env: VectorRegistersExt<Reg>,
44 [(); SUPPORTED_ELEN_VLEN::<{ Env::ELEN }, { Env::VLEN }>]:,
45 Memory: VirtualMemory,
46 PC: ProgramCounter<Reg::Type, Memory>,
47{
48 #[inline(always)]
49 #[cfg_attr(feature = "no-panic", no_panic_const::no_panic)]
50 fn execute(
51 self,
52 Rs1Rs2OperandValues {
53 rs1_value,
54 rs2_value,
55 }: Rs1Rs2OperandValues<<Self::Reg as Register>::Type>,
56 _regs: &mut Regs,
57 env: &mut Env,
58 memory: &mut Memory,
59 program_counter: &mut PC,
60 ) -> ExecutionResult<Self::Reg> {
61 match self {
62 Self::VandnVv { vd, vs2, vs1, vm } => {
64 if !env.vector_instructions_allowed() {
65 ::core::hint::cold_path();
66 return ExecutionResult::Err(ExecutionError::IllegalInstruction {
67 address: PackedAddress::new(
68 program_counter.old_pc(zvexx_helpers::INSTRUCTION_SIZE),
69 ),
70 });
71 }
72 if !vm && vd == VReg::V0 {
73 ::core::hint::cold_path();
74 return ExecutionResult::Err(ExecutionError::IllegalInstruction {
75 address: PackedAddress::new(
76 program_counter.old_pc(zvexx_helpers::INSTRUCTION_SIZE),
77 ),
78 });
79 }
80 let Some(vtype) = env.vtype() else {
81 ::core::hint::cold_path();
82 return ExecutionResult::Err(ExecutionError::IllegalInstruction {
83 address: PackedAddress::new(
84 program_counter.old_pc(zvexx_helpers::INSTRUCTION_SIZE),
85 ),
86 });
87 };
88 let group_regs = vtype.vlmul().register_count();
89 zvkb_helpers::check_vreg_group_alignment::<Reg, _, _>(
90 program_counter,
91 vd,
92 group_regs,
93 )?;
94 zvkb_helpers::check_vreg_group_alignment::<Reg, _, _>(
95 program_counter,
96 vs2,
97 group_regs,
98 )?;
99 zvkb_helpers::check_vreg_group_alignment::<Reg, _, _>(
100 program_counter,
101 vs1,
102 group_regs,
103 )?;
104 let sew = vtype.vsew();
105 unsafe {
107 zvkb_helpers::execute_vandn::<Reg, _>(
108 env,
109 vd,
110 vs2,
111 zvkb_helpers::OpSrc::Vreg(vs1),
112 sew,
113 vm,
114 );
115 }
116 }
117 Self::VandnVx {
118 vm,
119 vd,
120 vs2,
121 rs1: _,
122 } => {
123 if !env.vector_instructions_allowed() {
124 ::core::hint::cold_path();
125 return ExecutionResult::Err(ExecutionError::IllegalInstruction {
126 address: PackedAddress::new(
127 program_counter.old_pc(zvexx_helpers::INSTRUCTION_SIZE),
128 ),
129 });
130 }
131 if !vm && vd == VReg::V0 {
132 ::core::hint::cold_path();
133 return ExecutionResult::Err(ExecutionError::IllegalInstruction {
134 address: PackedAddress::new(
135 program_counter.old_pc(zvexx_helpers::INSTRUCTION_SIZE),
136 ),
137 });
138 }
139 let Some(vtype) = env.vtype() else {
140 ::core::hint::cold_path();
141 return ExecutionResult::Err(ExecutionError::IllegalInstruction {
142 address: PackedAddress::new(
143 program_counter.old_pc(zvexx_helpers::INSTRUCTION_SIZE),
144 ),
145 });
146 };
147 let group_regs = vtype.vlmul().register_count();
148 zvkb_helpers::check_vreg_group_alignment::<Reg, _, _>(
149 program_counter,
150 vd,
151 group_regs,
152 )?;
153 zvkb_helpers::check_vreg_group_alignment::<Reg, _, _>(
154 program_counter,
155 vs2,
156 group_regs,
157 )?;
158 let sew = vtype.vsew();
159 let scalar = rs1_value.as_i64().cast_unsigned();
160 unsafe {
162 zvkb_helpers::execute_vandn::<Reg, _>(
163 env,
164 vd,
165 vs2,
166 zvkb_helpers::OpSrc::Scalar(scalar),
167 sew,
168 vm,
169 );
170 }
171 }
172 Self::Vbrev8V { vd, vs2, vm } => {
174 if !env.vector_instructions_allowed() {
175 ::core::hint::cold_path();
176 return ExecutionResult::Err(ExecutionError::IllegalInstruction {
177 address: PackedAddress::new(
178 program_counter.old_pc(zvexx_helpers::INSTRUCTION_SIZE),
179 ),
180 });
181 }
182 if !vm && vd == VReg::V0 {
183 ::core::hint::cold_path();
184 return ExecutionResult::Err(ExecutionError::IllegalInstruction {
185 address: PackedAddress::new(
186 program_counter.old_pc(zvexx_helpers::INSTRUCTION_SIZE),
187 ),
188 });
189 }
190 let Some(vtype) = env.vtype() else {
191 ::core::hint::cold_path();
192 return ExecutionResult::Err(ExecutionError::IllegalInstruction {
193 address: PackedAddress::new(
194 program_counter.old_pc(zvexx_helpers::INSTRUCTION_SIZE),
195 ),
196 });
197 };
198 let group_regs = vtype.vlmul().register_count();
199 zvkb_helpers::check_vreg_group_alignment::<Reg, _, _>(
200 program_counter,
201 vd,
202 group_regs,
203 )?;
204 zvkb_helpers::check_vreg_group_alignment::<Reg, _, _>(
205 program_counter,
206 vs2,
207 group_regs,
208 )?;
209 let sew = vtype.vsew();
210 unsafe {
212 zvkb_helpers::execute_vbrev8::<Reg, _>(env, vd, vs2, sew, vm);
213 }
214 }
215 Self::Vrev8V { vd, vs2, vm } => {
217 if !env.vector_instructions_allowed() {
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 if !vm && vd == VReg::V0 {
226 ::core::hint::cold_path();
227 return ExecutionResult::Err(ExecutionError::IllegalInstruction {
228 address: PackedAddress::new(
229 program_counter.old_pc(zvexx_helpers::INSTRUCTION_SIZE),
230 ),
231 });
232 }
233 let Some(vtype) = env.vtype() else {
234 ::core::hint::cold_path();
235 return ExecutionResult::Err(ExecutionError::IllegalInstruction {
236 address: PackedAddress::new(
237 program_counter.old_pc(zvexx_helpers::INSTRUCTION_SIZE),
238 ),
239 });
240 };
241 let group_regs = vtype.vlmul().register_count();
242 zvkb_helpers::check_vreg_group_alignment::<Reg, _, _>(
243 program_counter,
244 vd,
245 group_regs,
246 )?;
247 zvkb_helpers::check_vreg_group_alignment::<Reg, _, _>(
248 program_counter,
249 vs2,
250 group_regs,
251 )?;
252 let sew = vtype.vsew();
253 unsafe {
255 zvkb_helpers::execute_vrev8::<Reg, _>(env, vd, vs2, sew, vm);
256 }
257 }
258 Self::VrolVv { vd, vs2, vs1, vm } => {
260 if !env.vector_instructions_allowed() {
261 ::core::hint::cold_path();
262 return ExecutionResult::Err(ExecutionError::IllegalInstruction {
263 address: PackedAddress::new(
264 program_counter.old_pc(zvexx_helpers::INSTRUCTION_SIZE),
265 ),
266 });
267 }
268 if !vm && vd == VReg::V0 {
269 ::core::hint::cold_path();
270 return ExecutionResult::Err(ExecutionError::IllegalInstruction {
271 address: PackedAddress::new(
272 program_counter.old_pc(zvexx_helpers::INSTRUCTION_SIZE),
273 ),
274 });
275 }
276 let Some(vtype) = env.vtype() else {
277 ::core::hint::cold_path();
278 return ExecutionResult::Err(ExecutionError::IllegalInstruction {
279 address: PackedAddress::new(
280 program_counter.old_pc(zvexx_helpers::INSTRUCTION_SIZE),
281 ),
282 });
283 };
284 let group_regs = vtype.vlmul().register_count();
285 zvkb_helpers::check_vreg_group_alignment::<Reg, _, _>(
286 program_counter,
287 vd,
288 group_regs,
289 )?;
290 zvkb_helpers::check_vreg_group_alignment::<Reg, _, _>(
291 program_counter,
292 vs2,
293 group_regs,
294 )?;
295 zvkb_helpers::check_vreg_group_alignment::<Reg, _, _>(
296 program_counter,
297 vs1,
298 group_regs,
299 )?;
300 let sew = vtype.vsew();
301 unsafe {
303 zvkb_helpers::execute_vrol::<Reg, _>(
304 env,
305 vd,
306 vs2,
307 zvkb_helpers::OpSrc::Vreg(vs1),
308 sew,
309 vm,
310 );
311 }
312 }
313 Self::VrolVx {
314 vm,
315 vd,
316 vs2,
317 rs1: _,
318 } => {
319 if !env.vector_instructions_allowed() {
320 ::core::hint::cold_path();
321 return ExecutionResult::Err(ExecutionError::IllegalInstruction {
322 address: PackedAddress::new(
323 program_counter.old_pc(zvexx_helpers::INSTRUCTION_SIZE),
324 ),
325 });
326 }
327 if !vm && vd == VReg::V0 {
328 ::core::hint::cold_path();
329 return ExecutionResult::Err(ExecutionError::IllegalInstruction {
330 address: PackedAddress::new(
331 program_counter.old_pc(zvexx_helpers::INSTRUCTION_SIZE),
332 ),
333 });
334 }
335 let Some(vtype) = env.vtype() else {
336 ::core::hint::cold_path();
337 return ExecutionResult::Err(ExecutionError::IllegalInstruction {
338 address: PackedAddress::new(
339 program_counter.old_pc(zvexx_helpers::INSTRUCTION_SIZE),
340 ),
341 });
342 };
343 let group_regs = vtype.vlmul().register_count();
344 zvkb_helpers::check_vreg_group_alignment::<Reg, _, _>(
345 program_counter,
346 vd,
347 group_regs,
348 )?;
349 zvkb_helpers::check_vreg_group_alignment::<Reg, _, _>(
350 program_counter,
351 vs2,
352 group_regs,
353 )?;
354 let sew = vtype.vsew();
355 let scalar = rs1_value.as_i64().cast_unsigned();
356 unsafe {
358 zvkb_helpers::execute_vrol::<Reg, _>(
359 env,
360 vd,
361 vs2,
362 zvkb_helpers::OpSrc::Scalar(scalar),
363 sew,
364 vm,
365 );
366 }
367 }
368 Self::VrorVv { vd, vs2, vs1, vm } => {
370 if !env.vector_instructions_allowed() {
371 ::core::hint::cold_path();
372 return ExecutionResult::Err(ExecutionError::IllegalInstruction {
373 address: PackedAddress::new(
374 program_counter.old_pc(zvexx_helpers::INSTRUCTION_SIZE),
375 ),
376 });
377 }
378 if !vm && vd == VReg::V0 {
379 ::core::hint::cold_path();
380 return ExecutionResult::Err(ExecutionError::IllegalInstruction {
381 address: PackedAddress::new(
382 program_counter.old_pc(zvexx_helpers::INSTRUCTION_SIZE),
383 ),
384 });
385 }
386 let Some(vtype) = env.vtype() else {
387 ::core::hint::cold_path();
388 return ExecutionResult::Err(ExecutionError::IllegalInstruction {
389 address: PackedAddress::new(
390 program_counter.old_pc(zvexx_helpers::INSTRUCTION_SIZE),
391 ),
392 });
393 };
394 let group_regs = vtype.vlmul().register_count();
395 zvkb_helpers::check_vreg_group_alignment::<Reg, _, _>(
396 program_counter,
397 vd,
398 group_regs,
399 )?;
400 zvkb_helpers::check_vreg_group_alignment::<Reg, _, _>(
401 program_counter,
402 vs2,
403 group_regs,
404 )?;
405 zvkb_helpers::check_vreg_group_alignment::<Reg, _, _>(
406 program_counter,
407 vs1,
408 group_regs,
409 )?;
410 let sew = vtype.vsew();
411 unsafe {
413 zvkb_helpers::execute_vror::<Reg, _>(
414 env,
415 vd,
416 vs2,
417 zvkb_helpers::OpSrc::Vreg(vs1),
418 sew,
419 vm,
420 );
421 }
422 }
423 Self::VrorVx {
424 vm,
425 vd,
426 vs2,
427 rs1: _,
428 } => {
429 if !env.vector_instructions_allowed() {
430 ::core::hint::cold_path();
431 return ExecutionResult::Err(ExecutionError::IllegalInstruction {
432 address: PackedAddress::new(
433 program_counter.old_pc(zvexx_helpers::INSTRUCTION_SIZE),
434 ),
435 });
436 }
437 if !vm && vd == VReg::V0 {
438 ::core::hint::cold_path();
439 return ExecutionResult::Err(ExecutionError::IllegalInstruction {
440 address: PackedAddress::new(
441 program_counter.old_pc(zvexx_helpers::INSTRUCTION_SIZE),
442 ),
443 });
444 }
445 let Some(vtype) = env.vtype() else {
446 ::core::hint::cold_path();
447 return ExecutionResult::Err(ExecutionError::IllegalInstruction {
448 address: PackedAddress::new(
449 program_counter.old_pc(zvexx_helpers::INSTRUCTION_SIZE),
450 ),
451 });
452 };
453 let group_regs = vtype.vlmul().register_count();
454 zvkb_helpers::check_vreg_group_alignment::<Reg, _, _>(
455 program_counter,
456 vd,
457 group_regs,
458 )?;
459 zvkb_helpers::check_vreg_group_alignment::<Reg, _, _>(
460 program_counter,
461 vs2,
462 group_regs,
463 )?;
464 let sew = vtype.vsew();
465 let scalar = rs1_value.as_i64().cast_unsigned();
466 unsafe {
468 zvkb_helpers::execute_vror::<Reg, _>(
469 env,
470 vd,
471 vs2,
472 zvkb_helpers::OpSrc::Scalar(scalar),
473 sew,
474 vm,
475 );
476 }
477 }
478 Self::VrorVi { vd, vs2, uimm, vm } => {
480 if !env.vector_instructions_allowed() {
481 ::core::hint::cold_path();
482 return ExecutionResult::Err(ExecutionError::IllegalInstruction {
483 address: PackedAddress::new(
484 program_counter.old_pc(zvexx_helpers::INSTRUCTION_SIZE),
485 ),
486 });
487 }
488 if !vm && vd == VReg::V0 {
489 ::core::hint::cold_path();
490 return ExecutionResult::Err(ExecutionError::IllegalInstruction {
491 address: PackedAddress::new(
492 program_counter.old_pc(zvexx_helpers::INSTRUCTION_SIZE),
493 ),
494 });
495 }
496 let Some(vtype) = env.vtype() else {
497 ::core::hint::cold_path();
498 return ExecutionResult::Err(ExecutionError::IllegalInstruction {
499 address: PackedAddress::new(
500 program_counter.old_pc(zvexx_helpers::INSTRUCTION_SIZE),
501 ),
502 });
503 };
504 let group_regs = vtype.vlmul().register_count();
505 zvkb_helpers::check_vreg_group_alignment::<Reg, _, _>(
506 program_counter,
507 vd,
508 group_regs,
509 )?;
510 zvkb_helpers::check_vreg_group_alignment::<Reg, _, _>(
511 program_counter,
512 vs2,
513 group_regs,
514 )?;
515 let sew = vtype.vsew();
516 unsafe {
518 zvkb_helpers::execute_vror::<Reg, _>(
519 env,
520 vd,
521 vs2,
522 zvkb_helpers::OpSrc::Scalar(u64::from(uimm)),
523 sew,
524 vm,
525 );
526 }
527 }
528 }
529 ExecutionResult::ContinueNoWrite
530 }
531}