1#[cfg(test)]
4mod tests;
5pub mod zve64x_mask_helpers;
6
7use crate::v::vector_registers::VectorRegistersExt;
8use crate::v::zve64x::zve64x_helpers;
9use crate::{
10 ExecutableInstruction, ExecutableInstructionCsr, ExecutableInstructionOperands, ExecutionError,
11 ProgramCounter, RegisterFile, Rs1Rs2OperandValues, Rs1Rs2Operands, VirtualMemory,
12};
13use ab_riscv_macros::instruction_execution;
14use ab_riscv_primitives::prelude::*;
15use core::fmt;
16use core::ops::ControlFlow;
17
18#[instruction_execution]
19impl<Reg> ExecutableInstructionOperands for Zve64xMaskInstruction<Reg> where Reg: Register {}
20
21#[instruction_execution]
22impl<Reg, ExtState, CustomError> ExecutableInstructionCsr<ExtState, CustomError>
23 for Zve64xMaskInstruction<Reg>
24where
25 Reg: Register,
26{
27}
28
29#[instruction_execution]
30impl<Reg, Regs, ExtState, Memory, PC, InstructionHandler, CustomError>
31 ExecutableInstruction<Regs, ExtState, Memory, PC, InstructionHandler, CustomError>
32 for Zve64xMaskInstruction<Reg>
33where
34 Reg: Register,
35 Regs: RegisterFile<Reg>,
36 ExtState: VectorRegistersExt<Reg, CustomError>,
37 [(); ExtState::ELEN as usize]:,
38 [(); ExtState::VLEN as usize]:,
39 [(); ExtState::VLENB as usize]:,
40 Memory: VirtualMemory,
41 PC: ProgramCounter<Reg::Type, Memory, CustomError>,
42 CustomError: fmt::Debug,
43{
44 #[inline(always)]
45 fn execute(
46 self,
47 Rs1Rs2OperandValues {
48 rs1_value: _,
49 rs2_value: _,
50 }: Rs1Rs2OperandValues<<Self::Reg as Register>::Type>,
51 regs: &mut Regs,
52 ext_state: &mut ExtState,
53 _memory: &mut Memory,
54 program_counter: &mut PC,
55 _system_instruction_handler: &mut InstructionHandler,
56 ) -> Result<
57 ControlFlow<(), (Self::Reg, <Self::Reg as Register>::Type)>,
58 ExecutionError<Reg::Type, CustomError>,
59 > {
60 match self {
61 Self::Vmandn { vd, vs2, vs1 } => {
66 if !ext_state.vector_instructions_allowed() {
67 Err(ExecutionError::IllegalInstruction {
68 address: program_counter.old_pc(zve64x_helpers::INSTRUCTION_SIZE),
69 })?;
70 }
71 ext_state
72 .vtype()
73 .ok_or(ExecutionError::IllegalInstruction {
74 address: program_counter.old_pc(zve64x_helpers::INSTRUCTION_SIZE),
75 })?;
76 unsafe {
79 zve64x_mask_helpers::execute_mask_logical_op(
80 ext_state,
81 vd,
82 vs2,
83 vs1,
84 |a, b| a & !b,
85 );
86 }
87 }
88 Self::Vmand { vd, vs2, vs1 } => {
89 if !ext_state.vector_instructions_allowed() {
90 Err(ExecutionError::IllegalInstruction {
91 address: program_counter.old_pc(zve64x_helpers::INSTRUCTION_SIZE),
92 })?;
93 }
94 ext_state
95 .vtype()
96 .ok_or(ExecutionError::IllegalInstruction {
97 address: program_counter.old_pc(zve64x_helpers::INSTRUCTION_SIZE),
98 })?;
99 unsafe {
101 zve64x_mask_helpers::execute_mask_logical_op(
102 ext_state,
103 vd,
104 vs2,
105 vs1,
106 |a, b| a & b,
107 );
108 }
109 }
110 Self::Vmor { vd, vs2, vs1 } => {
111 if !ext_state.vector_instructions_allowed() {
112 Err(ExecutionError::IllegalInstruction {
113 address: program_counter.old_pc(zve64x_helpers::INSTRUCTION_SIZE),
114 })?;
115 }
116 ext_state
117 .vtype()
118 .ok_or(ExecutionError::IllegalInstruction {
119 address: program_counter.old_pc(zve64x_helpers::INSTRUCTION_SIZE),
120 })?;
121 unsafe {
123 zve64x_mask_helpers::execute_mask_logical_op(
124 ext_state,
125 vd,
126 vs2,
127 vs1,
128 |a, b| a | b,
129 );
130 }
131 }
132 Self::Vmxor { vd, vs2, vs1 } => {
133 if !ext_state.vector_instructions_allowed() {
134 Err(ExecutionError::IllegalInstruction {
135 address: program_counter.old_pc(zve64x_helpers::INSTRUCTION_SIZE),
136 })?;
137 }
138 ext_state
139 .vtype()
140 .ok_or(ExecutionError::IllegalInstruction {
141 address: program_counter.old_pc(zve64x_helpers::INSTRUCTION_SIZE),
142 })?;
143 unsafe {
145 zve64x_mask_helpers::execute_mask_logical_op(
146 ext_state,
147 vd,
148 vs2,
149 vs1,
150 |a, b| a ^ b,
151 );
152 }
153 }
154 Self::Vmorn { vd, vs2, vs1 } => {
155 if !ext_state.vector_instructions_allowed() {
156 Err(ExecutionError::IllegalInstruction {
157 address: program_counter.old_pc(zve64x_helpers::INSTRUCTION_SIZE),
158 })?;
159 }
160 ext_state
161 .vtype()
162 .ok_or(ExecutionError::IllegalInstruction {
163 address: program_counter.old_pc(zve64x_helpers::INSTRUCTION_SIZE),
164 })?;
165 unsafe {
167 zve64x_mask_helpers::execute_mask_logical_op(
168 ext_state,
169 vd,
170 vs2,
171 vs1,
172 |a, b| a | !b,
173 );
174 }
175 }
176 Self::Vmnand { vd, vs2, vs1 } => {
177 if !ext_state.vector_instructions_allowed() {
178 Err(ExecutionError::IllegalInstruction {
179 address: program_counter.old_pc(zve64x_helpers::INSTRUCTION_SIZE),
180 })?;
181 }
182 ext_state
183 .vtype()
184 .ok_or(ExecutionError::IllegalInstruction {
185 address: program_counter.old_pc(zve64x_helpers::INSTRUCTION_SIZE),
186 })?;
187 unsafe {
189 zve64x_mask_helpers::execute_mask_logical_op(
190 ext_state,
191 vd,
192 vs2,
193 vs1,
194 |a, b| !(a & b),
195 );
196 }
197 }
198 Self::Vmnor { vd, vs2, vs1 } => {
199 if !ext_state.vector_instructions_allowed() {
200 Err(ExecutionError::IllegalInstruction {
201 address: program_counter.old_pc(zve64x_helpers::INSTRUCTION_SIZE),
202 })?;
203 }
204 ext_state
205 .vtype()
206 .ok_or(ExecutionError::IllegalInstruction {
207 address: program_counter.old_pc(zve64x_helpers::INSTRUCTION_SIZE),
208 })?;
209 unsafe {
211 zve64x_mask_helpers::execute_mask_logical_op(
212 ext_state,
213 vd,
214 vs2,
215 vs1,
216 |a, b| !(a | b),
217 );
218 }
219 }
220 Self::Vmxnor { vd, vs2, vs1 } => {
221 if !ext_state.vector_instructions_allowed() {
222 Err(ExecutionError::IllegalInstruction {
223 address: program_counter.old_pc(zve64x_helpers::INSTRUCTION_SIZE),
224 })?;
225 }
226 ext_state
227 .vtype()
228 .ok_or(ExecutionError::IllegalInstruction {
229 address: program_counter.old_pc(zve64x_helpers::INSTRUCTION_SIZE),
230 })?;
231 unsafe {
233 zve64x_mask_helpers::execute_mask_logical_op(
234 ext_state,
235 vd,
236 vs2,
237 vs1,
238 |a, b| !(a ^ b),
239 );
240 }
241 }
242 Self::Vcpop { rd, vs2, vm } => {
244 if !ext_state.vector_instructions_allowed() {
245 Err(ExecutionError::IllegalInstruction {
246 address: program_counter.old_pc(zve64x_helpers::INSTRUCTION_SIZE),
247 })?;
248 }
249 ext_state
251 .vtype()
252 .ok_or(ExecutionError::IllegalInstruction {
253 address: program_counter.old_pc(zve64x_helpers::INSTRUCTION_SIZE),
254 })?;
255 let vl = ext_state.vl();
256 let vstart = u32::from(ext_state.vstart());
257 unsafe {
260 zve64x_mask_helpers::execute_vcpop(regs, ext_state, rd, vs2, vm, vl, vstart);
261 }
262 }
263 Self::Vfirst { rd, vs2, vm } => {
265 if !ext_state.vector_instructions_allowed() {
266 Err(ExecutionError::IllegalInstruction {
267 address: program_counter.old_pc(zve64x_helpers::INSTRUCTION_SIZE),
268 })?;
269 }
270 ext_state
271 .vtype()
272 .ok_or(ExecutionError::IllegalInstruction {
273 address: program_counter.old_pc(zve64x_helpers::INSTRUCTION_SIZE),
274 })?;
275 let vl = ext_state.vl();
276 let vstart = u32::from(ext_state.vstart());
277 unsafe {
279 zve64x_mask_helpers::execute_vfirst(regs, ext_state, rd, vs2, vm, vl, vstart);
280 }
281 }
282 Self::Vmsbf { vd, vs2, vm } => {
285 if !ext_state.vector_instructions_allowed() {
286 Err(ExecutionError::IllegalInstruction {
287 address: program_counter.old_pc(zve64x_helpers::INSTRUCTION_SIZE),
288 })?;
289 }
290 ext_state
291 .vtype()
292 .ok_or(ExecutionError::IllegalInstruction {
293 address: program_counter.old_pc(zve64x_helpers::INSTRUCTION_SIZE),
294 })?;
295 if ext_state.vstart() != 0 {
298 Err(ExecutionError::IllegalInstruction {
299 address: program_counter.old_pc(zve64x_helpers::INSTRUCTION_SIZE),
300 })?;
301 }
302 if vd.bits() == vs2.bits() {
304 Err(ExecutionError::IllegalInstruction {
305 address: program_counter.old_pc(zve64x_helpers::INSTRUCTION_SIZE),
306 })?;
307 }
308 if !vm && vd.bits() == 0 {
309 Err(ExecutionError::IllegalInstruction {
310 address: program_counter.old_pc(zve64x_helpers::INSTRUCTION_SIZE),
311 })?;
312 }
313 let vl = ext_state.vl();
314 unsafe {
317 zve64x_mask_helpers::execute_vmsbf(ext_state, vd, vs2, vm, vl);
318 }
319 }
320 Self::Vmsof { vd, vs2, vm } => {
323 if !ext_state.vector_instructions_allowed() {
324 Err(ExecutionError::IllegalInstruction {
325 address: program_counter.old_pc(zve64x_helpers::INSTRUCTION_SIZE),
326 })?;
327 }
328 ext_state
329 .vtype()
330 .ok_or(ExecutionError::IllegalInstruction {
331 address: program_counter.old_pc(zve64x_helpers::INSTRUCTION_SIZE),
332 })?;
333 if ext_state.vstart() != 0 {
336 Err(ExecutionError::IllegalInstruction {
337 address: program_counter.old_pc(zve64x_helpers::INSTRUCTION_SIZE),
338 })?;
339 }
340 if vd.bits() == vs2.bits() {
341 Err(ExecutionError::IllegalInstruction {
342 address: program_counter.old_pc(zve64x_helpers::INSTRUCTION_SIZE),
343 })?;
344 }
345 if !vm && vd.bits() == 0 {
346 Err(ExecutionError::IllegalInstruction {
347 address: program_counter.old_pc(zve64x_helpers::INSTRUCTION_SIZE),
348 })?;
349 }
350 let vl = ext_state.vl();
351 unsafe {
353 zve64x_mask_helpers::execute_vmsof(ext_state, vd, vs2, vm, vl);
354 }
355 }
356 Self::Vmsif { vd, vs2, vm } => {
359 if !ext_state.vector_instructions_allowed() {
360 Err(ExecutionError::IllegalInstruction {
361 address: program_counter.old_pc(zve64x_helpers::INSTRUCTION_SIZE),
362 })?;
363 }
364 ext_state
365 .vtype()
366 .ok_or(ExecutionError::IllegalInstruction {
367 address: program_counter.old_pc(zve64x_helpers::INSTRUCTION_SIZE),
368 })?;
369 if ext_state.vstart() != 0 {
372 Err(ExecutionError::IllegalInstruction {
373 address: program_counter.old_pc(zve64x_helpers::INSTRUCTION_SIZE),
374 })?;
375 }
376 if vd.bits() == vs2.bits() {
377 Err(ExecutionError::IllegalInstruction {
378 address: program_counter.old_pc(zve64x_helpers::INSTRUCTION_SIZE),
379 })?;
380 }
381 if !vm && vd.bits() == 0 {
382 Err(ExecutionError::IllegalInstruction {
383 address: program_counter.old_pc(zve64x_helpers::INSTRUCTION_SIZE),
384 })?;
385 }
386 let vl = ext_state.vl();
387 unsafe {
389 zve64x_mask_helpers::execute_vmsif(ext_state, vd, vs2, vm, vl);
390 }
391 }
392 Self::Viota { vd, vs2, vm } => {
397 if !ext_state.vector_instructions_allowed() {
398 Err(ExecutionError::IllegalInstruction {
399 address: program_counter.old_pc(zve64x_helpers::INSTRUCTION_SIZE),
400 })?;
401 }
402 let vtype = ext_state
403 .vtype()
404 .ok_or(ExecutionError::IllegalInstruction {
405 address: program_counter.old_pc(zve64x_helpers::INSTRUCTION_SIZE),
406 })?;
407 if u32::from(ext_state.vstart()) != 0 {
409 Err(ExecutionError::IllegalInstruction {
410 address: program_counter.old_pc(zve64x_helpers::INSTRUCTION_SIZE),
411 })?;
412 }
413 let group_regs = vtype.vlmul().register_count();
414 let vd_idx = vd.bits();
415 if !vd_idx.is_multiple_of(group_regs) || vd_idx + group_regs > 32 {
416 Err(ExecutionError::IllegalInstruction {
417 address: program_counter.old_pc(zve64x_helpers::INSTRUCTION_SIZE),
418 })?;
419 }
420 let vd_start = u32::from(vd.bits());
422 let vs2_start = u32::from(vs2.bits());
423 if vd_start < vs2_start + 1 && vs2_start < vd_start + u32::from(group_regs) {
424 Err(ExecutionError::IllegalInstruction {
425 address: program_counter.old_pc(zve64x_helpers::INSTRUCTION_SIZE),
426 })?;
427 }
428 if !vm && vd.bits() == 0 {
429 Err(ExecutionError::IllegalInstruction {
430 address: program_counter.old_pc(zve64x_helpers::INSTRUCTION_SIZE),
431 })?;
432 }
433 let sew = vtype.vsew();
434 let sew_bits = u32::from(sew.bits());
435 let vlmax = vtype.vlmul().vlmax(ExtState::VLEN, sew_bits);
436 if u64::from(vlmax).unbounded_shr(sew_bits) != 0 {
437 Err(ExecutionError::IllegalInstruction {
438 address: program_counter.old_pc(zve64x_helpers::INSTRUCTION_SIZE),
439 })?;
440 }
441 let vl = ext_state.vl();
442 unsafe {
447 zve64x_mask_helpers::execute_viota(ext_state, vd, vs2, vm, vl, sew);
448 }
449 }
450 Self::Vid { vd, vm } => {
453 if !ext_state.vector_instructions_allowed() {
454 Err(ExecutionError::IllegalInstruction {
455 address: program_counter.old_pc(zve64x_helpers::INSTRUCTION_SIZE),
456 })?;
457 }
458 let vtype = ext_state
459 .vtype()
460 .ok_or(ExecutionError::IllegalInstruction {
461 address: program_counter.old_pc(zve64x_helpers::INSTRUCTION_SIZE),
462 })?;
463 let group_regs = vtype.vlmul().register_count();
464 let vd_idx = vd.bits();
465 if !vd_idx.is_multiple_of(group_regs) || vd_idx + group_regs > 32 {
466 Err(ExecutionError::IllegalInstruction {
467 address: program_counter.old_pc(zve64x_helpers::INSTRUCTION_SIZE),
468 })?;
469 }
470 if !vm && vd.bits() == 0 {
471 Err(ExecutionError::IllegalInstruction {
472 address: program_counter.old_pc(zve64x_helpers::INSTRUCTION_SIZE),
473 })?;
474 }
475 let sew = vtype.vsew();
476 let vl = ext_state.vl();
477 let vstart = u32::from(ext_state.vstart());
478 unsafe {
481 zve64x_mask_helpers::execute_vid(ext_state, vd, vm, vl, vstart, sew);
482 }
483 }
484 }
485
486 Ok(ControlFlow::Continue(Default::default()))
487 }
488}