1#[cfg(test)]
4mod tests;
5pub mod zvexx_mask_helpers;
6
7use crate::v::vector_registers::VectorRegistersExt;
8use crate::v::zvexx::zvexx_helpers;
9use crate::{
10 ExecutableInstruction, ExecutableInstructionCsr, ExecutableInstructionOperands, ExecutionError,
11 ExecutionResult, FetchInstructionResult, InstructionFetcher, OpaqueThreadedExecutionResult,
12 PackedAddress, ProgramCounter, RegisterFile, Rs1Rs2OperandValues, Rs1Rs2Operands,
13 ThreadedExecutableInstruction, ThreadedExecutionResult, VirtualMemory,
14};
15use ab_riscv_macros::instruction_execution;
16use ab_riscv_primitives::prelude::*;
17
18#[instruction_execution]
19const impl<Reg> ExecutableInstructionOperands for ZveXxMaskInstruction<Reg> where Reg: Register {}
20
21#[instruction_execution]
22const impl<Reg, Env> ExecutableInstructionCsr<Env> for ZveXxMaskInstruction<Reg> where Reg: Register {}
23
24#[instruction_execution]
25impl<Reg, Regs, Env, Memory, PC> ExecutableInstruction<Regs, Env, Memory, PC>
26 for ZveXxMaskInstruction<Reg>
27where
28 Reg: Register,
29 Regs: RegisterFile<Reg>,
30 Env: VectorRegistersExt<Reg>,
31 [(); SUPPORTED_ELEN_VLEN::<{ Env::ELEN }, { Env::VLEN }>]:,
32 Memory: VirtualMemory,
33 PC: ProgramCounter<Reg::Type, Memory>,
34{
35 #[inline(always)]
36 #[cfg_attr(feature = "no-panic", no_panic_const::no_panic)]
37 fn execute(
38 self,
39 Rs1Rs2OperandValues {
40 rs1_value: _,
41 rs2_value: _,
42 }: Rs1Rs2OperandValues<<Self::Reg as Register>::Type>,
43 _regs: &mut Regs,
44 env: &mut Env,
45 _memory: &mut Memory,
46 program_counter: &mut PC,
47 ) -> ExecutionResult<Self::Reg> {
48 match self {
49 Self::Vmandn { vd, vs2, vs1 } => {
56 if !env.vector_instructions_allowed() {
57 ::core::hint::cold_path();
58 return ExecutionResult::Err(ExecutionError::IllegalInstruction {
59 address: PackedAddress::new(
60 program_counter.old_pc(zvexx_helpers::INSTRUCTION_SIZE),
61 ),
62 });
63 }
64 if env.vtype().is_none() {
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 unsafe {
76 zvexx_mask_helpers::execute_mask_logical_op(env, vd, vs2, vs1, |a, b| a && !b);
77 }
78 }
79 Self::Vmand { vd, vs2, vs1 } => {
80 if !env.vector_instructions_allowed() {
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 if env.vtype().is_none() {
89 ::core::hint::cold_path();
90 return ExecutionResult::Err(ExecutionError::IllegalInstruction {
91 address: PackedAddress::new(
92 program_counter.old_pc(zvexx_helpers::INSTRUCTION_SIZE),
93 ),
94 });
95 }
96 unsafe {
98 zvexx_mask_helpers::execute_mask_logical_op(env, vd, vs2, vs1, |a, b| a & b);
99 }
100 }
101 Self::Vmor { vd, vs2, vs1 } => {
102 if !env.vector_instructions_allowed() {
103 ::core::hint::cold_path();
104 return ExecutionResult::Err(ExecutionError::IllegalInstruction {
105 address: PackedAddress::new(
106 program_counter.old_pc(zvexx_helpers::INSTRUCTION_SIZE),
107 ),
108 });
109 }
110 if env.vtype().is_none() {
111 ::core::hint::cold_path();
112 return ExecutionResult::Err(ExecutionError::IllegalInstruction {
113 address: PackedAddress::new(
114 program_counter.old_pc(zvexx_helpers::INSTRUCTION_SIZE),
115 ),
116 });
117 }
118 unsafe {
120 zvexx_mask_helpers::execute_mask_logical_op(env, vd, vs2, vs1, |a, b| a | b);
121 }
122 }
123 Self::Vmxor { vd, vs2, vs1 } => {
124 if !env.vector_instructions_allowed() {
125 ::core::hint::cold_path();
126 return ExecutionResult::Err(ExecutionError::IllegalInstruction {
127 address: PackedAddress::new(
128 program_counter.old_pc(zvexx_helpers::INSTRUCTION_SIZE),
129 ),
130 });
131 }
132 if env.vtype().is_none() {
133 ::core::hint::cold_path();
134 return ExecutionResult::Err(ExecutionError::IllegalInstruction {
135 address: PackedAddress::new(
136 program_counter.old_pc(zvexx_helpers::INSTRUCTION_SIZE),
137 ),
138 });
139 }
140 unsafe {
142 zvexx_mask_helpers::execute_mask_logical_op(env, vd, vs2, vs1, |a, b| a ^ b);
143 }
144 }
145 Self::Vmorn { vd, vs2, vs1 } => {
146 if !env.vector_instructions_allowed() {
147 ::core::hint::cold_path();
148 return ExecutionResult::Err(ExecutionError::IllegalInstruction {
149 address: PackedAddress::new(
150 program_counter.old_pc(zvexx_helpers::INSTRUCTION_SIZE),
151 ),
152 });
153 }
154 if env.vtype().is_none() {
155 ::core::hint::cold_path();
156 return ExecutionResult::Err(ExecutionError::IllegalInstruction {
157 address: PackedAddress::new(
158 program_counter.old_pc(zvexx_helpers::INSTRUCTION_SIZE),
159 ),
160 });
161 }
162 unsafe {
164 zvexx_mask_helpers::execute_mask_logical_op(env, vd, vs2, vs1, |a, b| a || !b);
165 }
166 }
167 Self::Vmnand { vd, vs2, vs1 } => {
168 if !env.vector_instructions_allowed() {
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 if env.vtype().is_none() {
177 ::core::hint::cold_path();
178 return ExecutionResult::Err(ExecutionError::IllegalInstruction {
179 address: PackedAddress::new(
180 program_counter.old_pc(zvexx_helpers::INSTRUCTION_SIZE),
181 ),
182 });
183 }
184 unsafe {
186 zvexx_mask_helpers::execute_mask_logical_op(env, vd, vs2, vs1, |a, b| !(a & b));
187 }
188 }
189 Self::Vmnor { vd, vs2, vs1 } => {
190 if !env.vector_instructions_allowed() {
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 if env.vtype().is_none() {
199 ::core::hint::cold_path();
200 return ExecutionResult::Err(ExecutionError::IllegalInstruction {
201 address: PackedAddress::new(
202 program_counter.old_pc(zvexx_helpers::INSTRUCTION_SIZE),
203 ),
204 });
205 }
206 unsafe {
208 zvexx_mask_helpers::execute_mask_logical_op(env, vd, vs2, vs1, |a, b| !(a | b));
209 }
210 }
211 Self::Vmxnor { vd, vs2, vs1 } => {
212 if !env.vector_instructions_allowed() {
213 ::core::hint::cold_path();
214 return ExecutionResult::Err(ExecutionError::IllegalInstruction {
215 address: PackedAddress::new(
216 program_counter.old_pc(zvexx_helpers::INSTRUCTION_SIZE),
217 ),
218 });
219 }
220 if env.vtype().is_none() {
221 ::core::hint::cold_path();
222 return ExecutionResult::Err(ExecutionError::IllegalInstruction {
223 address: PackedAddress::new(
224 program_counter.old_pc(zvexx_helpers::INSTRUCTION_SIZE),
225 ),
226 });
227 }
228 unsafe {
230 zvexx_mask_helpers::execute_mask_logical_op(env, vd, vs2, vs1, |a, b| !(a ^ b));
231 }
232 }
233 Self::Vcpop { rd, vs2, vm } => {
235 if !env.vector_instructions_allowed() {
236 ::core::hint::cold_path();
237 return ExecutionResult::Err(ExecutionError::IllegalInstruction {
238 address: PackedAddress::new(
239 program_counter.old_pc(zvexx_helpers::INSTRUCTION_SIZE),
240 ),
241 });
242 }
243 if env.vtype().is_none() {
245 ::core::hint::cold_path();
246 return ExecutionResult::Err(ExecutionError::IllegalInstruction {
247 address: PackedAddress::new(
248 program_counter.old_pc(zvexx_helpers::INSTRUCTION_SIZE),
249 ),
250 });
251 }
252 let rd_value = unsafe { zvexx_mask_helpers::execute_vcpop(env, vs2, vm) };
254
255 return ExecutionResult::Continue {
256 rd,
257 value: rd_value,
258 };
259 }
260 Self::Vfirst { rd, vs2, vm } => {
262 if !env.vector_instructions_allowed() {
263 ::core::hint::cold_path();
264 return ExecutionResult::Err(ExecutionError::IllegalInstruction {
265 address: PackedAddress::new(
266 program_counter.old_pc(zvexx_helpers::INSTRUCTION_SIZE),
267 ),
268 });
269 }
270 if env.vtype().is_none() {
271 ::core::hint::cold_path();
272 return ExecutionResult::Err(ExecutionError::IllegalInstruction {
273 address: PackedAddress::new(
274 program_counter.old_pc(zvexx_helpers::INSTRUCTION_SIZE),
275 ),
276 });
277 }
278 let rd_value = unsafe { zvexx_mask_helpers::execute_vfirst(env, vs2, vm) };
280
281 return ExecutionResult::Continue {
282 rd,
283 value: rd_value,
284 };
285 }
286 Self::Vmsbf { vd, vs2, vm } => {
289 if !env.vector_instructions_allowed() {
290 ::core::hint::cold_path();
291 return ExecutionResult::Err(ExecutionError::IllegalInstruction {
292 address: PackedAddress::new(
293 program_counter.old_pc(zvexx_helpers::INSTRUCTION_SIZE),
294 ),
295 });
296 }
297 if env.vtype().is_none() {
298 ::core::hint::cold_path();
299 return ExecutionResult::Err(ExecutionError::IllegalInstruction {
300 address: PackedAddress::new(
301 program_counter.old_pc(zvexx_helpers::INSTRUCTION_SIZE),
302 ),
303 });
304 }
305 if env.vstart() != Vstart::ZERO {
308 ::core::hint::cold_path();
309 return ExecutionResult::Err(ExecutionError::IllegalInstruction {
310 address: PackedAddress::new(
311 program_counter.old_pc(zvexx_helpers::INSTRUCTION_SIZE),
312 ),
313 });
314 }
315 if vd == vs2 {
317 ::core::hint::cold_path();
318 return ExecutionResult::Err(ExecutionError::IllegalInstruction {
319 address: PackedAddress::new(
320 program_counter.old_pc(zvexx_helpers::INSTRUCTION_SIZE),
321 ),
322 });
323 }
324 if !vm && vd == VReg::V0 {
325 ::core::hint::cold_path();
326 return ExecutionResult::Err(ExecutionError::IllegalInstruction {
327 address: PackedAddress::new(
328 program_counter.old_pc(zvexx_helpers::INSTRUCTION_SIZE),
329 ),
330 });
331 }
332 let vl = env.vl();
333 unsafe {
336 zvexx_mask_helpers::execute_vmsbf(env, vd, vs2, vm, vl);
337 }
338 }
339 Self::Vmsof { vd, vs2, vm } => {
342 if !env.vector_instructions_allowed() {
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 if env.vtype().is_none() {
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 if env.vstart() != Vstart::ZERO {
361 ::core::hint::cold_path();
362 return ExecutionResult::Err(ExecutionError::IllegalInstruction {
363 address: PackedAddress::new(
364 program_counter.old_pc(zvexx_helpers::INSTRUCTION_SIZE),
365 ),
366 });
367 }
368 if vd == vs2 {
369 ::core::hint::cold_path();
370 return ExecutionResult::Err(ExecutionError::IllegalInstruction {
371 address: PackedAddress::new(
372 program_counter.old_pc(zvexx_helpers::INSTRUCTION_SIZE),
373 ),
374 });
375 }
376 if !vm && vd == VReg::V0 {
377 ::core::hint::cold_path();
378 return ExecutionResult::Err(ExecutionError::IllegalInstruction {
379 address: PackedAddress::new(
380 program_counter.old_pc(zvexx_helpers::INSTRUCTION_SIZE),
381 ),
382 });
383 }
384 let vl = env.vl();
385 unsafe {
387 zvexx_mask_helpers::execute_vmsof(env, vd, vs2, vm, vl);
388 }
389 }
390 Self::Vmsif { vd, vs2, vm } => {
393 if !env.vector_instructions_allowed() {
394 ::core::hint::cold_path();
395 return ExecutionResult::Err(ExecutionError::IllegalInstruction {
396 address: PackedAddress::new(
397 program_counter.old_pc(zvexx_helpers::INSTRUCTION_SIZE),
398 ),
399 });
400 }
401 if env.vtype().is_none() {
402 ::core::hint::cold_path();
403 return ExecutionResult::Err(ExecutionError::IllegalInstruction {
404 address: PackedAddress::new(
405 program_counter.old_pc(zvexx_helpers::INSTRUCTION_SIZE),
406 ),
407 });
408 }
409 if env.vstart() != Vstart::ZERO {
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 if vd == vs2 {
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 if !vm && vd == VReg::V0 {
428 ::core::hint::cold_path();
429 return ExecutionResult::Err(ExecutionError::IllegalInstruction {
430 address: PackedAddress::new(
431 program_counter.old_pc(zvexx_helpers::INSTRUCTION_SIZE),
432 ),
433 });
434 }
435 let vl = env.vl();
436 unsafe {
438 zvexx_mask_helpers::execute_vmsif(env, vd, vs2, vm, vl);
439 }
440 }
441 Self::Viota { vd, vs2, vm } => {
448 if !env.vector_instructions_allowed() {
449 ::core::hint::cold_path();
450 return ExecutionResult::Err(ExecutionError::IllegalInstruction {
451 address: PackedAddress::new(
452 program_counter.old_pc(zvexx_helpers::INSTRUCTION_SIZE),
453 ),
454 });
455 }
456 let Some(vtype) = env.vtype() else {
457 ::core::hint::cold_path();
458 return ExecutionResult::Err(ExecutionError::IllegalInstruction {
459 address: PackedAddress::new(
460 program_counter.old_pc(zvexx_helpers::INSTRUCTION_SIZE),
461 ),
462 });
463 };
464 if env.vstart() != Vstart::ZERO {
466 ::core::hint::cold_path();
467 return ExecutionResult::Err(ExecutionError::IllegalInstruction {
468 address: PackedAddress::new(
469 program_counter.old_pc(zvexx_helpers::INSTRUCTION_SIZE),
470 ),
471 });
472 }
473 let group_regs = vtype.vlmul().register_count().get();
474 let vd_idx = vd.to_bits();
475 if !vd_idx.is_multiple_of(group_regs) || vd_idx + group_regs > 32 {
476 ::core::hint::cold_path();
477 return ExecutionResult::Err(ExecutionError::IllegalInstruction {
478 address: PackedAddress::new(
479 program_counter.old_pc(zvexx_helpers::INSTRUCTION_SIZE),
480 ),
481 });
482 }
483 let vd_start = u32::from(vd.to_bits());
485 let vs2_start = u32::from(vs2.to_bits());
486 if vd_start < vs2_start + 1 && vs2_start < vd_start + u32::from(group_regs) {
487 ::core::hint::cold_path();
488 return ExecutionResult::Err(ExecutionError::IllegalInstruction {
489 address: PackedAddress::new(
490 program_counter.old_pc(zvexx_helpers::INSTRUCTION_SIZE),
491 ),
492 });
493 }
494 if !vm && vd == VReg::V0 {
495 ::core::hint::cold_path();
496 return ExecutionResult::Err(ExecutionError::IllegalInstruction {
497 address: PackedAddress::new(
498 program_counter.old_pc(zvexx_helpers::INSTRUCTION_SIZE),
499 ),
500 });
501 }
502 let sew = vtype.vsew();
503 let vl = env.vl();
504 unsafe {
508 zvexx_mask_helpers::execute_viota(env, vd, vs2, vm, vl, sew);
509 }
510 }
511 Self::Vid { vd, vm } => {
514 if !env.vector_instructions_allowed() {
515 ::core::hint::cold_path();
516 return ExecutionResult::Err(ExecutionError::IllegalInstruction {
517 address: PackedAddress::new(
518 program_counter.old_pc(zvexx_helpers::INSTRUCTION_SIZE),
519 ),
520 });
521 }
522 let Some(vtype) = env.vtype() else {
523 ::core::hint::cold_path();
524 return ExecutionResult::Err(ExecutionError::IllegalInstruction {
525 address: PackedAddress::new(
526 program_counter.old_pc(zvexx_helpers::INSTRUCTION_SIZE),
527 ),
528 });
529 };
530 let group_regs = vtype.vlmul().register_count().get();
531 let vd_idx = vd.to_bits();
532 if !vd_idx.is_multiple_of(group_regs) || vd_idx + group_regs > 32 {
533 ::core::hint::cold_path();
534 return ExecutionResult::Err(ExecutionError::IllegalInstruction {
535 address: PackedAddress::new(
536 program_counter.old_pc(zvexx_helpers::INSTRUCTION_SIZE),
537 ),
538 });
539 }
540 if !vm && vd == VReg::V0 {
541 ::core::hint::cold_path();
542 return ExecutionResult::Err(ExecutionError::IllegalInstruction {
543 address: PackedAddress::new(
544 program_counter.old_pc(zvexx_helpers::INSTRUCTION_SIZE),
545 ),
546 });
547 }
548 let sew = vtype.vsew();
549 unsafe {
552 zvexx_mask_helpers::execute_vid(env, vd, vm, sew);
553 }
554 }
555 }
556
557 ExecutionResult::ContinueNoWrite
558 }
559}