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, ProgramCounter, RegisterFile, Rs1Rs2OperandValues, Rs1Rs2Operands,
24 VirtualMemory,
25};
26use ab_riscv_macros::instruction_execution;
27use ab_riscv_primitives::prelude::*;
28use core::fmt;
29use core::ops::ControlFlow;
30
31#[instruction_execution]
32impl<Reg> ExecutableInstructionOperands for ZvkbInstruction<Reg> where Reg: Register {}
33
34#[instruction_execution]
35impl<Reg, ExtState, CustomError> ExecutableInstructionCsr<ExtState, CustomError>
36 for ZvkbInstruction<Reg>
37where
38 Reg: Register,
39{
40}
41
42#[instruction_execution]
43impl<Reg, Regs, ExtState, Memory, PC, InstructionHandler, CustomError>
44 ExecutableInstruction<Regs, ExtState, Memory, PC, InstructionHandler, CustomError>
45 for ZvkbInstruction<Reg>
46where
47 Reg: Register,
48 Regs: RegisterFile<Reg>,
49 ExtState: VectorRegistersExt<Reg, CustomError>,
50 [(); SUPPORTED_ELEN_VLEN::<{ ExtState::ELEN }, { ExtState::VLEN }>]:,
51 Memory: VirtualMemory,
52 PC: ProgramCounter<Reg::Type, Memory, CustomError>,
53 CustomError: fmt::Debug,
54{
55 #[inline(always)]
56 fn execute(
57 self,
58 Rs1Rs2OperandValues {
59 rs1_value,
60 rs2_value,
61 }: Rs1Rs2OperandValues<<Self::Reg as Register>::Type>,
62 _regs: &mut Regs,
63 ext_state: &mut ExtState,
64 memory: &mut Memory,
65 program_counter: &mut PC,
66 _system_instruction_handler: &mut InstructionHandler,
67 ) -> Result<
68 ControlFlow<(), (Self::Reg, <Self::Reg as Register>::Type)>,
69 ExecutionError<Reg::Type, CustomError>,
70 > {
71 match self {
72 Self::VandnVv { vd, vs2, vs1, vm } => {
74 if !ext_state.vector_instructions_allowed() {
75 ::core::hint::cold_path();
76 return Err(ExecutionError::IllegalInstruction {
77 address: program_counter.old_pc(zvexx_helpers::INSTRUCTION_SIZE),
78 });
79 }
80 if !vm && vd == VReg::V0 {
81 ::core::hint::cold_path();
82 return Err(ExecutionError::IllegalInstruction {
83 address: program_counter.old_pc(zvexx_helpers::INSTRUCTION_SIZE),
84 });
85 }
86 let Some(vtype) = ext_state.vtype() else {
87 ::core::hint::cold_path();
88 return Err(ExecutionError::IllegalInstruction {
89 address: program_counter.old_pc(zvexx_helpers::INSTRUCTION_SIZE),
90 });
91 };
92 let group_regs = vtype.vlmul().register_count();
93 zvkb_helpers::check_vreg_group_alignment::<Reg, _, _, _>(
94 program_counter,
95 vd,
96 group_regs,
97 )?;
98 zvkb_helpers::check_vreg_group_alignment::<Reg, _, _, _>(
99 program_counter,
100 vs2,
101 group_regs,
102 )?;
103 zvkb_helpers::check_vreg_group_alignment::<Reg, _, _, _>(
104 program_counter,
105 vs1,
106 group_regs,
107 )?;
108 let sew = vtype.vsew();
109 unsafe {
111 zvkb_helpers::execute_vandn::<Reg, _, _>(
112 ext_state,
113 vd,
114 vs2,
115 zvkb_helpers::OpSrc::Vreg(vs1),
116 sew,
117 vm,
118 );
119 }
120 }
121 Self::VandnVx {
122 vm,
123 vd,
124 vs2,
125 rs1: _,
126 } => {
127 if !ext_state.vector_instructions_allowed() {
128 ::core::hint::cold_path();
129 return Err(ExecutionError::IllegalInstruction {
130 address: program_counter.old_pc(zvexx_helpers::INSTRUCTION_SIZE),
131 });
132 }
133 if !vm && vd == VReg::V0 {
134 ::core::hint::cold_path();
135 return Err(ExecutionError::IllegalInstruction {
136 address: program_counter.old_pc(zvexx_helpers::INSTRUCTION_SIZE),
137 });
138 }
139 let Some(vtype) = ext_state.vtype() else {
140 ::core::hint::cold_path();
141 return Err(ExecutionError::IllegalInstruction {
142 address: program_counter.old_pc(zvexx_helpers::INSTRUCTION_SIZE),
143 });
144 };
145 let group_regs = vtype.vlmul().register_count();
146 zvkb_helpers::check_vreg_group_alignment::<Reg, _, _, _>(
147 program_counter,
148 vd,
149 group_regs,
150 )?;
151 zvkb_helpers::check_vreg_group_alignment::<Reg, _, _, _>(
152 program_counter,
153 vs2,
154 group_regs,
155 )?;
156 let sew = vtype.vsew();
157 let scalar = rs1_value.as_i64().cast_unsigned();
158 unsafe {
160 zvkb_helpers::execute_vandn::<Reg, _, _>(
161 ext_state,
162 vd,
163 vs2,
164 zvkb_helpers::OpSrc::Scalar(scalar),
165 sew,
166 vm,
167 );
168 }
169 }
170 Self::Vbrev8V { vd, vs2, vm } => {
172 if !ext_state.vector_instructions_allowed() {
173 ::core::hint::cold_path();
174 return Err(ExecutionError::IllegalInstruction {
175 address: program_counter.old_pc(zvexx_helpers::INSTRUCTION_SIZE),
176 });
177 }
178 if !vm && vd == VReg::V0 {
179 ::core::hint::cold_path();
180 return Err(ExecutionError::IllegalInstruction {
181 address: program_counter.old_pc(zvexx_helpers::INSTRUCTION_SIZE),
182 });
183 }
184 let Some(vtype) = ext_state.vtype() else {
185 ::core::hint::cold_path();
186 return Err(ExecutionError::IllegalInstruction {
187 address: program_counter.old_pc(zvexx_helpers::INSTRUCTION_SIZE),
188 });
189 };
190 let group_regs = vtype.vlmul().register_count();
191 zvkb_helpers::check_vreg_group_alignment::<Reg, _, _, _>(
192 program_counter,
193 vd,
194 group_regs,
195 )?;
196 zvkb_helpers::check_vreg_group_alignment::<Reg, _, _, _>(
197 program_counter,
198 vs2,
199 group_regs,
200 )?;
201 let sew = vtype.vsew();
202 unsafe {
204 zvkb_helpers::execute_vbrev8::<Reg, _, _>(ext_state, vd, vs2, sew, vm);
205 }
206 }
207 Self::Vrev8V { vd, vs2, vm } => {
209 if !ext_state.vector_instructions_allowed() {
210 ::core::hint::cold_path();
211 return Err(ExecutionError::IllegalInstruction {
212 address: program_counter.old_pc(zvexx_helpers::INSTRUCTION_SIZE),
213 });
214 }
215 if !vm && vd == VReg::V0 {
216 ::core::hint::cold_path();
217 return Err(ExecutionError::IllegalInstruction {
218 address: program_counter.old_pc(zvexx_helpers::INSTRUCTION_SIZE),
219 });
220 }
221 let Some(vtype) = ext_state.vtype() else {
222 ::core::hint::cold_path();
223 return Err(ExecutionError::IllegalInstruction {
224 address: program_counter.old_pc(zvexx_helpers::INSTRUCTION_SIZE),
225 });
226 };
227 let group_regs = vtype.vlmul().register_count();
228 zvkb_helpers::check_vreg_group_alignment::<Reg, _, _, _>(
229 program_counter,
230 vd,
231 group_regs,
232 )?;
233 zvkb_helpers::check_vreg_group_alignment::<Reg, _, _, _>(
234 program_counter,
235 vs2,
236 group_regs,
237 )?;
238 let sew = vtype.vsew();
239 unsafe {
241 zvkb_helpers::execute_vrev8::<Reg, _, _>(ext_state, vd, vs2, sew, vm);
242 }
243 }
244 Self::VrolVv { vd, vs2, vs1, vm } => {
246 if !ext_state.vector_instructions_allowed() {
247 ::core::hint::cold_path();
248 return Err(ExecutionError::IllegalInstruction {
249 address: program_counter.old_pc(zvexx_helpers::INSTRUCTION_SIZE),
250 });
251 }
252 if !vm && vd == VReg::V0 {
253 ::core::hint::cold_path();
254 return Err(ExecutionError::IllegalInstruction {
255 address: program_counter.old_pc(zvexx_helpers::INSTRUCTION_SIZE),
256 });
257 }
258 let Some(vtype) = ext_state.vtype() else {
259 ::core::hint::cold_path();
260 return Err(ExecutionError::IllegalInstruction {
261 address: program_counter.old_pc(zvexx_helpers::INSTRUCTION_SIZE),
262 });
263 };
264 let group_regs = vtype.vlmul().register_count();
265 zvkb_helpers::check_vreg_group_alignment::<Reg, _, _, _>(
266 program_counter,
267 vd,
268 group_regs,
269 )?;
270 zvkb_helpers::check_vreg_group_alignment::<Reg, _, _, _>(
271 program_counter,
272 vs2,
273 group_regs,
274 )?;
275 zvkb_helpers::check_vreg_group_alignment::<Reg, _, _, _>(
276 program_counter,
277 vs1,
278 group_regs,
279 )?;
280 let sew = vtype.vsew();
281 unsafe {
283 zvkb_helpers::execute_vrol::<Reg, _, _>(
284 ext_state,
285 vd,
286 vs2,
287 zvkb_helpers::OpSrc::Vreg(vs1),
288 sew,
289 vm,
290 );
291 }
292 }
293 Self::VrolVx {
294 vm,
295 vd,
296 vs2,
297 rs1: _,
298 } => {
299 if !ext_state.vector_instructions_allowed() {
300 ::core::hint::cold_path();
301 return Err(ExecutionError::IllegalInstruction {
302 address: program_counter.old_pc(zvexx_helpers::INSTRUCTION_SIZE),
303 });
304 }
305 if !vm && vd == VReg::V0 {
306 ::core::hint::cold_path();
307 return Err(ExecutionError::IllegalInstruction {
308 address: program_counter.old_pc(zvexx_helpers::INSTRUCTION_SIZE),
309 });
310 }
311 let Some(vtype) = ext_state.vtype() else {
312 ::core::hint::cold_path();
313 return Err(ExecutionError::IllegalInstruction {
314 address: program_counter.old_pc(zvexx_helpers::INSTRUCTION_SIZE),
315 });
316 };
317 let group_regs = vtype.vlmul().register_count();
318 zvkb_helpers::check_vreg_group_alignment::<Reg, _, _, _>(
319 program_counter,
320 vd,
321 group_regs,
322 )?;
323 zvkb_helpers::check_vreg_group_alignment::<Reg, _, _, _>(
324 program_counter,
325 vs2,
326 group_regs,
327 )?;
328 let sew = vtype.vsew();
329 let scalar = rs1_value.as_i64().cast_unsigned();
330 unsafe {
332 zvkb_helpers::execute_vrol::<Reg, _, _>(
333 ext_state,
334 vd,
335 vs2,
336 zvkb_helpers::OpSrc::Scalar(scalar),
337 sew,
338 vm,
339 );
340 }
341 }
342 Self::VrorVv { vd, vs2, vs1, vm } => {
344 if !ext_state.vector_instructions_allowed() {
345 ::core::hint::cold_path();
346 return Err(ExecutionError::IllegalInstruction {
347 address: program_counter.old_pc(zvexx_helpers::INSTRUCTION_SIZE),
348 });
349 }
350 if !vm && vd == VReg::V0 {
351 ::core::hint::cold_path();
352 return Err(ExecutionError::IllegalInstruction {
353 address: program_counter.old_pc(zvexx_helpers::INSTRUCTION_SIZE),
354 });
355 }
356 let Some(vtype) = ext_state.vtype() else {
357 ::core::hint::cold_path();
358 return Err(ExecutionError::IllegalInstruction {
359 address: program_counter.old_pc(zvexx_helpers::INSTRUCTION_SIZE),
360 });
361 };
362 let group_regs = vtype.vlmul().register_count();
363 zvkb_helpers::check_vreg_group_alignment::<Reg, _, _, _>(
364 program_counter,
365 vd,
366 group_regs,
367 )?;
368 zvkb_helpers::check_vreg_group_alignment::<Reg, _, _, _>(
369 program_counter,
370 vs2,
371 group_regs,
372 )?;
373 zvkb_helpers::check_vreg_group_alignment::<Reg, _, _, _>(
374 program_counter,
375 vs1,
376 group_regs,
377 )?;
378 let sew = vtype.vsew();
379 unsafe {
381 zvkb_helpers::execute_vror::<Reg, _, _>(
382 ext_state,
383 vd,
384 vs2,
385 zvkb_helpers::OpSrc::Vreg(vs1),
386 sew,
387 vm,
388 );
389 }
390 }
391 Self::VrorVx {
392 vm,
393 vd,
394 vs2,
395 rs1: _,
396 } => {
397 if !ext_state.vector_instructions_allowed() {
398 ::core::hint::cold_path();
399 return Err(ExecutionError::IllegalInstruction {
400 address: program_counter.old_pc(zvexx_helpers::INSTRUCTION_SIZE),
401 });
402 }
403 if !vm && vd == VReg::V0 {
404 ::core::hint::cold_path();
405 return Err(ExecutionError::IllegalInstruction {
406 address: program_counter.old_pc(zvexx_helpers::INSTRUCTION_SIZE),
407 });
408 }
409 let Some(vtype) = ext_state.vtype() else {
410 ::core::hint::cold_path();
411 return Err(ExecutionError::IllegalInstruction {
412 address: program_counter.old_pc(zvexx_helpers::INSTRUCTION_SIZE),
413 });
414 };
415 let group_regs = vtype.vlmul().register_count();
416 zvkb_helpers::check_vreg_group_alignment::<Reg, _, _, _>(
417 program_counter,
418 vd,
419 group_regs,
420 )?;
421 zvkb_helpers::check_vreg_group_alignment::<Reg, _, _, _>(
422 program_counter,
423 vs2,
424 group_regs,
425 )?;
426 let sew = vtype.vsew();
427 let scalar = rs1_value.as_i64().cast_unsigned();
428 unsafe {
430 zvkb_helpers::execute_vror::<Reg, _, _>(
431 ext_state,
432 vd,
433 vs2,
434 zvkb_helpers::OpSrc::Scalar(scalar),
435 sew,
436 vm,
437 );
438 }
439 }
440 Self::VrorVi { vd, vs2, uimm, vm } => {
442 if !ext_state.vector_instructions_allowed() {
443 ::core::hint::cold_path();
444 return Err(ExecutionError::IllegalInstruction {
445 address: program_counter.old_pc(zvexx_helpers::INSTRUCTION_SIZE),
446 });
447 }
448 if !vm && vd == VReg::V0 {
449 ::core::hint::cold_path();
450 return Err(ExecutionError::IllegalInstruction {
451 address: program_counter.old_pc(zvexx_helpers::INSTRUCTION_SIZE),
452 });
453 }
454 let Some(vtype) = ext_state.vtype() else {
455 ::core::hint::cold_path();
456 return Err(ExecutionError::IllegalInstruction {
457 address: program_counter.old_pc(zvexx_helpers::INSTRUCTION_SIZE),
458 });
459 };
460 let group_regs = vtype.vlmul().register_count();
461 zvkb_helpers::check_vreg_group_alignment::<Reg, _, _, _>(
462 program_counter,
463 vd,
464 group_regs,
465 )?;
466 zvkb_helpers::check_vreg_group_alignment::<Reg, _, _, _>(
467 program_counter,
468 vs2,
469 group_regs,
470 )?;
471 let sew = vtype.vsew();
472 unsafe {
474 zvkb_helpers::execute_vror::<Reg, _, _>(
475 ext_state,
476 vd,
477 vs2,
478 zvkb_helpers::OpSrc::Scalar(u64::from(uimm)),
479 sew,
480 vm,
481 );
482 }
483 }
484 }
485 Ok(ControlFlow::Continue(Default::default()))
486 }
487}