1#[cfg(test)]
4mod tests;
5pub mod zvkb_helpers;
6
7use crate::v::vector_registers::{VectorRegisters, 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, Hart> ExecutableInstructionOperands for ZvkbInstruction<Hart>
33where
34 Reg: Register,
35 Hart: VectorHartConfig<Reg = Reg>,
36{
37}
38
39#[instruction_execution]
40const impl<Reg, Hart, Env> ExecutableInstructionCsr<Env> for ZvkbInstruction<Hart>
41where
42 Reg: Register,
43 Hart: VectorHartConfig<Reg = Reg>,
44{
45}
46
47#[instruction_execution]
48impl<Reg, Hart, Regs, Env, Memory, PC> ExecutableInstruction<Regs, Env, Memory, PC>
49 for ZvkbInstruction<Hart>
50where
51 Reg: Register,
52 Hart: VectorHartConfig<Reg = Reg>,
53 Regs: RegisterFile<Reg>,
54 Env: VectorRegistersExt<Hart = Hart>,
55 Memory: VirtualMemory,
56 PC: ProgramCounter<Reg::Type, Memory>,
57{
58 #[inline(always)]
59 #[cfg_attr(feature = "no-panic", no_panic_const::no_panic)]
60 fn execute(
61 self,
62 Rs1Rs2OperandValues {
63 rs1_value,
64 rs2_value,
65 }: Rs1Rs2OperandValues<Reg::Type>,
66 _regs: &mut Regs,
67 env: &mut Env,
68 memory: &mut Memory,
69 program_counter: &PC,
70 ) -> ExecutionResult<Reg> {
71 match self {
72 Self::VandnVv { vd, vs2, vs1, vm } => {
74 if !zvexx_helpers::non_memory_instruction_allowed::<Reg, _>(env) {
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(config) = env.vector_config() 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 sew = config.vtype().vsew();
91 let vd = zvexx_helpers::vreg_group::<Reg, Env, _, _>(
92 program_counter,
93 config,
94 vd,
95 sew.as_eew(),
96 )?;
97 let vs2 = zvexx_helpers::vreg_group::<Reg, Env, _, _>(
98 program_counter,
99 config,
100 vs2,
101 sew.as_eew(),
102 )?;
103 let vs1 = zvexx_helpers::vreg_group::<Reg, Env, _, _>(
104 program_counter,
105 config,
106 vs1,
107 sew.as_eew(),
108 )?;
109 zvkb_helpers::execute_vandn::<Reg, _>(
110 env,
111 vd,
112 vs2,
113 zvkb_helpers::OpSrc::Vreg(vs1),
114 vm,
115 );
116 }
117 Self::VandnVx {
118 vm,
119 vd,
120 vs2,
121 rs1: _,
122 } => {
123 if !zvexx_helpers::non_memory_instruction_allowed::<Reg, _>(env) {
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 let Some(config) = env.vector_config() else {
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 sew = config.vtype().vsew();
140 let vd = zvexx_helpers::vreg_group::<Reg, Env, _, _>(
141 program_counter,
142 config,
143 vd,
144 sew.as_eew(),
145 )?;
146 let vs2 = zvexx_helpers::vreg_group::<Reg, Env, _, _>(
147 program_counter,
148 config,
149 vs2,
150 sew.as_eew(),
151 )?;
152 let scalar = rs1_value.as_i64().cast_unsigned();
153 zvkb_helpers::execute_vandn::<Reg, _>(
154 env,
155 vd,
156 vs2,
157 zvkb_helpers::OpSrc::Scalar(scalar),
158 vm,
159 );
160 }
161 Self::Vbrev8V { vd, vs2, vm } => {
163 if !zvexx_helpers::non_memory_instruction_allowed::<Reg, _>(env) {
164 ::core::hint::cold_path();
165 return ExecutionResult::Err(ExecutionError::IllegalInstruction {
166 address: PackedAddress::new(
167 program_counter.old_pc(zvexx_helpers::INSTRUCTION_SIZE),
168 ),
169 });
170 }
171 let Some(config) = env.vector_config() else {
172 ::core::hint::cold_path();
173 return ExecutionResult::Err(ExecutionError::IllegalInstruction {
174 address: PackedAddress::new(
175 program_counter.old_pc(zvexx_helpers::INSTRUCTION_SIZE),
176 ),
177 });
178 };
179 let sew = config.vtype().vsew();
180 let vd = zvexx_helpers::vreg_group::<Reg, Env, _, _>(
181 program_counter,
182 config,
183 vd,
184 sew.as_eew(),
185 )?;
186 let vs2 = zvexx_helpers::vreg_group::<Reg, Env, _, _>(
187 program_counter,
188 config,
189 vs2,
190 sew.as_eew(),
191 )?;
192 zvkb_helpers::execute_vbrev8::<Reg, _>(env, vd, vs2, sew, vm);
193 }
194 Self::Vrev8V { vd, vs2, vm } => {
196 if !zvexx_helpers::non_memory_instruction_allowed::<Reg, _>(env) {
197 ::core::hint::cold_path();
198 return ExecutionResult::Err(ExecutionError::IllegalInstruction {
199 address: PackedAddress::new(
200 program_counter.old_pc(zvexx_helpers::INSTRUCTION_SIZE),
201 ),
202 });
203 }
204 let Some(config) = env.vector_config() else {
205 ::core::hint::cold_path();
206 return ExecutionResult::Err(ExecutionError::IllegalInstruction {
207 address: PackedAddress::new(
208 program_counter.old_pc(zvexx_helpers::INSTRUCTION_SIZE),
209 ),
210 });
211 };
212 let sew = config.vtype().vsew();
213 let vd = zvexx_helpers::vreg_group::<Reg, Env, _, _>(
214 program_counter,
215 config,
216 vd,
217 sew.as_eew(),
218 )?;
219 let vs2 = zvexx_helpers::vreg_group::<Reg, Env, _, _>(
220 program_counter,
221 config,
222 vs2,
223 sew.as_eew(),
224 )?;
225 zvkb_helpers::execute_vrev8::<Reg, _>(env, vd, vs2, sew, vm);
226 }
227 Self::VrolVv { vd, vs2, vs1, vm } => {
229 if !zvexx_helpers::non_memory_instruction_allowed::<Reg, _>(env) {
230 ::core::hint::cold_path();
231 return ExecutionResult::Err(ExecutionError::IllegalInstruction {
232 address: PackedAddress::new(
233 program_counter.old_pc(zvexx_helpers::INSTRUCTION_SIZE),
234 ),
235 });
236 }
237 let Some(config) = env.vector_config() else {
238 ::core::hint::cold_path();
239 return ExecutionResult::Err(ExecutionError::IllegalInstruction {
240 address: PackedAddress::new(
241 program_counter.old_pc(zvexx_helpers::INSTRUCTION_SIZE),
242 ),
243 });
244 };
245 let sew = config.vtype().vsew();
246 let vd = zvexx_helpers::vreg_group::<Reg, Env, _, _>(
247 program_counter,
248 config,
249 vd,
250 sew.as_eew(),
251 )?;
252 let vs2 = zvexx_helpers::vreg_group::<Reg, Env, _, _>(
253 program_counter,
254 config,
255 vs2,
256 sew.as_eew(),
257 )?;
258 let vs1 = zvexx_helpers::vreg_group::<Reg, Env, _, _>(
259 program_counter,
260 config,
261 vs1,
262 sew.as_eew(),
263 )?;
264 zvkb_helpers::execute_vrol::<Reg, _>(
265 env,
266 vd,
267 vs2,
268 zvkb_helpers::OpSrc::Vreg(vs1),
269 sew,
270 vm,
271 );
272 }
273 Self::VrolVx {
274 vm,
275 vd,
276 vs2,
277 rs1: _,
278 } => {
279 if !zvexx_helpers::non_memory_instruction_allowed::<Reg, _>(env) {
280 ::core::hint::cold_path();
281 return ExecutionResult::Err(ExecutionError::IllegalInstruction {
282 address: PackedAddress::new(
283 program_counter.old_pc(zvexx_helpers::INSTRUCTION_SIZE),
284 ),
285 });
286 }
287 let Some(config) = env.vector_config() else {
288 ::core::hint::cold_path();
289 return ExecutionResult::Err(ExecutionError::IllegalInstruction {
290 address: PackedAddress::new(
291 program_counter.old_pc(zvexx_helpers::INSTRUCTION_SIZE),
292 ),
293 });
294 };
295 let sew = config.vtype().vsew();
296 let vd = zvexx_helpers::vreg_group::<Reg, Env, _, _>(
297 program_counter,
298 config,
299 vd,
300 sew.as_eew(),
301 )?;
302 let vs2 = zvexx_helpers::vreg_group::<Reg, Env, _, _>(
303 program_counter,
304 config,
305 vs2,
306 sew.as_eew(),
307 )?;
308 let scalar = rs1_value.as_i64().cast_unsigned();
309 zvkb_helpers::execute_vrol::<Reg, _>(
310 env,
311 vd,
312 vs2,
313 zvkb_helpers::OpSrc::Scalar(scalar),
314 sew,
315 vm,
316 );
317 }
318 Self::VrorVv { vd, vs2, vs1, vm } => {
320 if !zvexx_helpers::non_memory_instruction_allowed::<Reg, _>(env) {
321 ::core::hint::cold_path();
322 return ExecutionResult::Err(ExecutionError::IllegalInstruction {
323 address: PackedAddress::new(
324 program_counter.old_pc(zvexx_helpers::INSTRUCTION_SIZE),
325 ),
326 });
327 }
328 let Some(config) = env.vector_config() else {
329 ::core::hint::cold_path();
330 return ExecutionResult::Err(ExecutionError::IllegalInstruction {
331 address: PackedAddress::new(
332 program_counter.old_pc(zvexx_helpers::INSTRUCTION_SIZE),
333 ),
334 });
335 };
336 let sew = config.vtype().vsew();
337 let vd = zvexx_helpers::vreg_group::<Reg, Env, _, _>(
338 program_counter,
339 config,
340 vd,
341 sew.as_eew(),
342 )?;
343 let vs2 = zvexx_helpers::vreg_group::<Reg, Env, _, _>(
344 program_counter,
345 config,
346 vs2,
347 sew.as_eew(),
348 )?;
349 let vs1 = zvexx_helpers::vreg_group::<Reg, Env, _, _>(
350 program_counter,
351 config,
352 vs1,
353 sew.as_eew(),
354 )?;
355 zvkb_helpers::execute_vror::<Reg, _>(
356 env,
357 vd,
358 vs2,
359 zvkb_helpers::OpSrc::Vreg(vs1),
360 sew,
361 vm,
362 );
363 }
364 Self::VrorVx {
365 vm,
366 vd,
367 vs2,
368 rs1: _,
369 } => {
370 if !zvexx_helpers::non_memory_instruction_allowed::<Reg, _>(env) {
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 let Some(config) = env.vector_config() else {
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 sew = config.vtype().vsew();
387 let vd = zvexx_helpers::vreg_group::<Reg, Env, _, _>(
388 program_counter,
389 config,
390 vd,
391 sew.as_eew(),
392 )?;
393 let vs2 = zvexx_helpers::vreg_group::<Reg, Env, _, _>(
394 program_counter,
395 config,
396 vs2,
397 sew.as_eew(),
398 )?;
399 let scalar = rs1_value.as_i64().cast_unsigned();
400 zvkb_helpers::execute_vror::<Reg, _>(
401 env,
402 vd,
403 vs2,
404 zvkb_helpers::OpSrc::Scalar(scalar),
405 sew,
406 vm,
407 );
408 }
409 Self::VrorVi { vd, vs2, uimm, vm } => {
411 if !zvexx_helpers::non_memory_instruction_allowed::<Reg, _>(env) {
412 ::core::hint::cold_path();
413 return ExecutionResult::Err(ExecutionError::IllegalInstruction {
414 address: PackedAddress::new(
415 program_counter.old_pc(zvexx_helpers::INSTRUCTION_SIZE),
416 ),
417 });
418 }
419 let Some(config) = env.vector_config() else {
420 ::core::hint::cold_path();
421 return ExecutionResult::Err(ExecutionError::IllegalInstruction {
422 address: PackedAddress::new(
423 program_counter.old_pc(zvexx_helpers::INSTRUCTION_SIZE),
424 ),
425 });
426 };
427 let sew = config.vtype().vsew();
428 let vd = zvexx_helpers::vreg_group::<Reg, Env, _, _>(
429 program_counter,
430 config,
431 vd,
432 sew.as_eew(),
433 )?;
434 let vs2 = zvexx_helpers::vreg_group::<Reg, Env, _, _>(
435 program_counter,
436 config,
437 vs2,
438 sew.as_eew(),
439 )?;
440 zvkb_helpers::execute_vror::<Reg, _>(
441 env,
442 vd,
443 vs2,
444 zvkb_helpers::OpSrc::Scalar(u64::from(uimm)),
445 sew,
446 vm,
447 );
448 }
449 }
450 ExecutionResult::ContinueNoWrite
451 }
452}