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 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 ZveXxMaskInstruction<Reg> where Reg: Register {}
20
21#[instruction_execution]
22impl<Reg, ExtState, CustomError> ExecutableInstructionCsr<ExtState, CustomError>
23 for ZveXxMaskInstruction<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 ZveXxMaskInstruction<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 } => {
68 if !ext_state.vector_instructions_allowed() {
69 return Err(ExecutionError::IllegalInstruction {
70 address: program_counter.old_pc(zvexx_helpers::INSTRUCTION_SIZE),
71 });
72 }
73 ext_state
74 .vtype()
75 .ok_or(ExecutionError::IllegalInstruction {
76 address: program_counter.old_pc(zvexx_helpers::INSTRUCTION_SIZE),
77 })?;
78 unsafe {
82 zvexx_mask_helpers::execute_mask_logical_op(ext_state, vd, vs2, vs1, |a, b| {
83 a && !b
84 });
85 }
86 }
87 Self::Vmand { vd, vs2, vs1 } => {
88 if !ext_state.vector_instructions_allowed() {
89 return Err(ExecutionError::IllegalInstruction {
90 address: program_counter.old_pc(zvexx_helpers::INSTRUCTION_SIZE),
91 });
92 }
93 ext_state
94 .vtype()
95 .ok_or(ExecutionError::IllegalInstruction {
96 address: program_counter.old_pc(zvexx_helpers::INSTRUCTION_SIZE),
97 })?;
98 unsafe {
100 zvexx_mask_helpers::execute_mask_logical_op(ext_state, vd, vs2, vs1, |a, b| {
101 a & b
102 });
103 }
104 }
105 Self::Vmor { vd, vs2, vs1 } => {
106 if !ext_state.vector_instructions_allowed() {
107 return Err(ExecutionError::IllegalInstruction {
108 address: program_counter.old_pc(zvexx_helpers::INSTRUCTION_SIZE),
109 });
110 }
111 ext_state
112 .vtype()
113 .ok_or(ExecutionError::IllegalInstruction {
114 address: program_counter.old_pc(zvexx_helpers::INSTRUCTION_SIZE),
115 })?;
116 unsafe {
118 zvexx_mask_helpers::execute_mask_logical_op(ext_state, vd, vs2, vs1, |a, b| {
119 a | b
120 });
121 }
122 }
123 Self::Vmxor { vd, vs2, vs1 } => {
124 if !ext_state.vector_instructions_allowed() {
125 return Err(ExecutionError::IllegalInstruction {
126 address: program_counter.old_pc(zvexx_helpers::INSTRUCTION_SIZE),
127 });
128 }
129 ext_state
130 .vtype()
131 .ok_or(ExecutionError::IllegalInstruction {
132 address: program_counter.old_pc(zvexx_helpers::INSTRUCTION_SIZE),
133 })?;
134 unsafe {
136 zvexx_mask_helpers::execute_mask_logical_op(ext_state, vd, vs2, vs1, |a, b| {
137 a ^ b
138 });
139 }
140 }
141 Self::Vmorn { vd, vs2, vs1 } => {
142 if !ext_state.vector_instructions_allowed() {
143 return Err(ExecutionError::IllegalInstruction {
144 address: program_counter.old_pc(zvexx_helpers::INSTRUCTION_SIZE),
145 });
146 }
147 ext_state
148 .vtype()
149 .ok_or(ExecutionError::IllegalInstruction {
150 address: program_counter.old_pc(zvexx_helpers::INSTRUCTION_SIZE),
151 })?;
152 unsafe {
154 zvexx_mask_helpers::execute_mask_logical_op(ext_state, vd, vs2, vs1, |a, b| {
155 a || !b
156 });
157 }
158 }
159 Self::Vmnand { vd, vs2, vs1 } => {
160 if !ext_state.vector_instructions_allowed() {
161 return Err(ExecutionError::IllegalInstruction {
162 address: program_counter.old_pc(zvexx_helpers::INSTRUCTION_SIZE),
163 });
164 }
165 ext_state
166 .vtype()
167 .ok_or(ExecutionError::IllegalInstruction {
168 address: program_counter.old_pc(zvexx_helpers::INSTRUCTION_SIZE),
169 })?;
170 unsafe {
172 zvexx_mask_helpers::execute_mask_logical_op(ext_state, vd, vs2, vs1, |a, b| {
173 !(a & b)
174 });
175 }
176 }
177 Self::Vmnor { vd, vs2, vs1 } => {
178 if !ext_state.vector_instructions_allowed() {
179 return Err(ExecutionError::IllegalInstruction {
180 address: program_counter.old_pc(zvexx_helpers::INSTRUCTION_SIZE),
181 });
182 }
183 ext_state
184 .vtype()
185 .ok_or(ExecutionError::IllegalInstruction {
186 address: program_counter.old_pc(zvexx_helpers::INSTRUCTION_SIZE),
187 })?;
188 unsafe {
190 zvexx_mask_helpers::execute_mask_logical_op(ext_state, vd, vs2, vs1, |a, b| {
191 !(a | b)
192 });
193 }
194 }
195 Self::Vmxnor { vd, vs2, vs1 } => {
196 if !ext_state.vector_instructions_allowed() {
197 return Err(ExecutionError::IllegalInstruction {
198 address: program_counter.old_pc(zvexx_helpers::INSTRUCTION_SIZE),
199 });
200 }
201 ext_state
202 .vtype()
203 .ok_or(ExecutionError::IllegalInstruction {
204 address: program_counter.old_pc(zvexx_helpers::INSTRUCTION_SIZE),
205 })?;
206 unsafe {
208 zvexx_mask_helpers::execute_mask_logical_op(ext_state, vd, vs2, vs1, |a, b| {
209 !(a ^ b)
210 });
211 }
212 }
213 Self::Vcpop { rd, vs2, vm } => {
215 if !ext_state.vector_instructions_allowed() {
216 return Err(ExecutionError::IllegalInstruction {
217 address: program_counter.old_pc(zvexx_helpers::INSTRUCTION_SIZE),
218 });
219 }
220 ext_state
222 .vtype()
223 .ok_or(ExecutionError::IllegalInstruction {
224 address: program_counter.old_pc(zvexx_helpers::INSTRUCTION_SIZE),
225 })?;
226 unsafe {
229 zvexx_mask_helpers::execute_vcpop(regs, ext_state, rd, vs2, vm);
230 }
231 }
232 Self::Vfirst { rd, vs2, vm } => {
234 if !ext_state.vector_instructions_allowed() {
235 return Err(ExecutionError::IllegalInstruction {
236 address: program_counter.old_pc(zvexx_helpers::INSTRUCTION_SIZE),
237 });
238 }
239 ext_state
240 .vtype()
241 .ok_or(ExecutionError::IllegalInstruction {
242 address: program_counter.old_pc(zvexx_helpers::INSTRUCTION_SIZE),
243 })?;
244 unsafe {
246 zvexx_mask_helpers::execute_vfirst(regs, ext_state, rd, vs2, vm);
247 }
248 }
249 Self::Vmsbf { vd, vs2, vm } => {
252 if !ext_state.vector_instructions_allowed() {
253 return Err(ExecutionError::IllegalInstruction {
254 address: program_counter.old_pc(zvexx_helpers::INSTRUCTION_SIZE),
255 });
256 }
257 ext_state
258 .vtype()
259 .ok_or(ExecutionError::IllegalInstruction {
260 address: program_counter.old_pc(zvexx_helpers::INSTRUCTION_SIZE),
261 })?;
262 if ext_state.vstart() != 0 {
265 return Err(ExecutionError::IllegalInstruction {
266 address: program_counter.old_pc(zvexx_helpers::INSTRUCTION_SIZE),
267 });
268 }
269 if vd == vs2 {
271 return Err(ExecutionError::IllegalInstruction {
272 address: program_counter.old_pc(zvexx_helpers::INSTRUCTION_SIZE),
273 });
274 }
275 if !vm && vd == VReg::V0 {
276 return Err(ExecutionError::IllegalInstruction {
277 address: program_counter.old_pc(zvexx_helpers::INSTRUCTION_SIZE),
278 });
279 }
280 let vl = ext_state.vl();
281 unsafe {
284 zvexx_mask_helpers::execute_vmsbf(ext_state, vd, vs2, vm, vl);
285 }
286 }
287 Self::Vmsof { vd, vs2, vm } => {
290 if !ext_state.vector_instructions_allowed() {
291 return Err(ExecutionError::IllegalInstruction {
292 address: program_counter.old_pc(zvexx_helpers::INSTRUCTION_SIZE),
293 });
294 }
295 ext_state
296 .vtype()
297 .ok_or(ExecutionError::IllegalInstruction {
298 address: program_counter.old_pc(zvexx_helpers::INSTRUCTION_SIZE),
299 })?;
300 if ext_state.vstart() != 0 {
303 return Err(ExecutionError::IllegalInstruction {
304 address: program_counter.old_pc(zvexx_helpers::INSTRUCTION_SIZE),
305 });
306 }
307 if vd == vs2 {
308 return Err(ExecutionError::IllegalInstruction {
309 address: program_counter.old_pc(zvexx_helpers::INSTRUCTION_SIZE),
310 });
311 }
312 if !vm && vd == VReg::V0 {
313 return Err(ExecutionError::IllegalInstruction {
314 address: program_counter.old_pc(zvexx_helpers::INSTRUCTION_SIZE),
315 });
316 }
317 let vl = ext_state.vl();
318 unsafe {
320 zvexx_mask_helpers::execute_vmsof(ext_state, vd, vs2, vm, vl);
321 }
322 }
323 Self::Vmsif { vd, vs2, vm } => {
326 if !ext_state.vector_instructions_allowed() {
327 return Err(ExecutionError::IllegalInstruction {
328 address: program_counter.old_pc(zvexx_helpers::INSTRUCTION_SIZE),
329 });
330 }
331 ext_state
332 .vtype()
333 .ok_or(ExecutionError::IllegalInstruction {
334 address: program_counter.old_pc(zvexx_helpers::INSTRUCTION_SIZE),
335 })?;
336 if ext_state.vstart() != 0 {
339 return Err(ExecutionError::IllegalInstruction {
340 address: program_counter.old_pc(zvexx_helpers::INSTRUCTION_SIZE),
341 });
342 }
343 if vd == vs2 {
344 return Err(ExecutionError::IllegalInstruction {
345 address: program_counter.old_pc(zvexx_helpers::INSTRUCTION_SIZE),
346 });
347 }
348 if !vm && vd == VReg::V0 {
349 return Err(ExecutionError::IllegalInstruction {
350 address: program_counter.old_pc(zvexx_helpers::INSTRUCTION_SIZE),
351 });
352 }
353 let vl = ext_state.vl();
354 unsafe {
356 zvexx_mask_helpers::execute_vmsif(ext_state, vd, vs2, vm, vl);
357 }
358 }
359 Self::Viota { vd, vs2, vm } => {
366 if !ext_state.vector_instructions_allowed() {
367 return Err(ExecutionError::IllegalInstruction {
368 address: program_counter.old_pc(zvexx_helpers::INSTRUCTION_SIZE),
369 });
370 }
371 let vtype = ext_state
372 .vtype()
373 .ok_or(ExecutionError::IllegalInstruction {
374 address: program_counter.old_pc(zvexx_helpers::INSTRUCTION_SIZE),
375 })?;
376 if ext_state.vstart() != 0 {
378 return Err(ExecutionError::IllegalInstruction {
379 address: program_counter.old_pc(zvexx_helpers::INSTRUCTION_SIZE),
380 });
381 }
382 let group_regs = vtype.vlmul().register_count();
383 let vd_idx = vd.to_bits();
384 if !vd_idx.is_multiple_of(group_regs) || vd_idx + group_regs > 32 {
385 return Err(ExecutionError::IllegalInstruction {
386 address: program_counter.old_pc(zvexx_helpers::INSTRUCTION_SIZE),
387 });
388 }
389 let vd_start = u32::from(vd.to_bits());
391 let vs2_start = u32::from(vs2.to_bits());
392 if vd_start < vs2_start + 1 && vs2_start < vd_start + u32::from(group_regs) {
393 return Err(ExecutionError::IllegalInstruction {
394 address: program_counter.old_pc(zvexx_helpers::INSTRUCTION_SIZE),
395 });
396 }
397 if !vm && vd == VReg::V0 {
398 return Err(ExecutionError::IllegalInstruction {
399 address: program_counter.old_pc(zvexx_helpers::INSTRUCTION_SIZE),
400 });
401 }
402 let sew = vtype.vsew();
403 let vl = ext_state.vl();
404 unsafe {
408 zvexx_mask_helpers::execute_viota(ext_state, vd, vs2, vm, vl, sew);
409 }
410 }
411 Self::Vid { vd, vm } => {
414 if !ext_state.vector_instructions_allowed() {
415 return Err(ExecutionError::IllegalInstruction {
416 address: program_counter.old_pc(zvexx_helpers::INSTRUCTION_SIZE),
417 });
418 }
419 let vtype = ext_state
420 .vtype()
421 .ok_or(ExecutionError::IllegalInstruction {
422 address: program_counter.old_pc(zvexx_helpers::INSTRUCTION_SIZE),
423 })?;
424 let group_regs = vtype.vlmul().register_count();
425 let vd_idx = vd.to_bits();
426 if !vd_idx.is_multiple_of(group_regs) || vd_idx + group_regs > 32 {
427 return Err(ExecutionError::IllegalInstruction {
428 address: program_counter.old_pc(zvexx_helpers::INSTRUCTION_SIZE),
429 });
430 }
431 if !vm && vd == VReg::V0 {
432 return Err(ExecutionError::IllegalInstruction {
433 address: program_counter.old_pc(zvexx_helpers::INSTRUCTION_SIZE),
434 });
435 }
436 let sew = vtype.vsew();
437 unsafe {
440 zvexx_mask_helpers::execute_vid(ext_state, vd, vm, sew);
441 }
442 }
443 }
444
445 Ok(ControlFlow::Continue(Default::default()))
446 }
447}