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::{ExecutableInstruction, ExecutionError, ProgramCounter, RegisterFile, VirtualMemory};
10use ab_riscv_macros::instruction_execution;
11use ab_riscv_primitives::prelude::*;
12use core::fmt;
13use core::ops::ControlFlow;
14
15#[instruction_execution]
16impl<Reg, Regs, ExtState, Memory, PC, InstructionHandler, CustomError>
17 ExecutableInstruction<Regs, ExtState, Memory, PC, InstructionHandler, CustomError>
18 for Zve64xMaskInstruction<Reg>
19where
20 Reg: Register,
21 Regs: RegisterFile<Reg>,
22 ExtState: VectorRegistersExt<Reg, CustomError>,
23 [(); ExtState::ELEN as usize]:,
24 [(); ExtState::VLEN as usize]:,
25 [(); ExtState::VLENB as usize]:,
26 Memory: VirtualMemory,
27 PC: ProgramCounter<Reg::Type, Memory, CustomError>,
28 CustomError: fmt::Debug,
29{
30 #[inline(always)]
31 fn execute(
32 self,
33 regs: &mut Regs,
34 ext_state: &mut ExtState,
35 _memory: &mut Memory,
36 program_counter: &mut PC,
37 _system_instruction_handler: &mut InstructionHandler,
38 ) -> Result<ControlFlow<()>, ExecutionError<Reg::Type, CustomError>> {
39 match self {
40 Self::Vmandn { vd, vs2, vs1 } => {
45 if !ext_state.vector_instructions_allowed() {
46 Err(ExecutionError::IllegalInstruction {
47 address: program_counter.old_pc(zve64x_helpers::INSTRUCTION_SIZE),
48 })?;
49 }
50 ext_state
51 .vtype()
52 .ok_or(ExecutionError::IllegalInstruction {
53 address: program_counter.old_pc(zve64x_helpers::INSTRUCTION_SIZE),
54 })?;
55 unsafe {
58 zve64x_mask_helpers::execute_mask_logical_op(
59 ext_state,
60 vd,
61 vs2,
62 vs1,
63 |a, b| a & !b,
64 );
65 }
66 }
67 Self::Vmand { vd, vs2, vs1 } => {
68 if !ext_state.vector_instructions_allowed() {
69 Err(ExecutionError::IllegalInstruction {
70 address: program_counter.old_pc(zve64x_helpers::INSTRUCTION_SIZE),
71 })?;
72 }
73 ext_state
74 .vtype()
75 .ok_or(ExecutionError::IllegalInstruction {
76 address: program_counter.old_pc(zve64x_helpers::INSTRUCTION_SIZE),
77 })?;
78 unsafe {
80 zve64x_mask_helpers::execute_mask_logical_op(
81 ext_state,
82 vd,
83 vs2,
84 vs1,
85 |a, b| a & b,
86 );
87 }
88 }
89 Self::Vmor { vd, vs2, vs1 } => {
90 if !ext_state.vector_instructions_allowed() {
91 Err(ExecutionError::IllegalInstruction {
92 address: program_counter.old_pc(zve64x_helpers::INSTRUCTION_SIZE),
93 })?;
94 }
95 ext_state
96 .vtype()
97 .ok_or(ExecutionError::IllegalInstruction {
98 address: program_counter.old_pc(zve64x_helpers::INSTRUCTION_SIZE),
99 })?;
100 unsafe {
102 zve64x_mask_helpers::execute_mask_logical_op(
103 ext_state,
104 vd,
105 vs2,
106 vs1,
107 |a, b| a | b,
108 );
109 }
110 }
111 Self::Vmxor { vd, vs2, vs1 } => {
112 if !ext_state.vector_instructions_allowed() {
113 Err(ExecutionError::IllegalInstruction {
114 address: program_counter.old_pc(zve64x_helpers::INSTRUCTION_SIZE),
115 })?;
116 }
117 ext_state
118 .vtype()
119 .ok_or(ExecutionError::IllegalInstruction {
120 address: program_counter.old_pc(zve64x_helpers::INSTRUCTION_SIZE),
121 })?;
122 unsafe {
124 zve64x_mask_helpers::execute_mask_logical_op(
125 ext_state,
126 vd,
127 vs2,
128 vs1,
129 |a, b| a ^ b,
130 );
131 }
132 }
133 Self::Vmorn { vd, vs2, vs1 } => {
134 if !ext_state.vector_instructions_allowed() {
135 Err(ExecutionError::IllegalInstruction {
136 address: program_counter.old_pc(zve64x_helpers::INSTRUCTION_SIZE),
137 })?;
138 }
139 ext_state
140 .vtype()
141 .ok_or(ExecutionError::IllegalInstruction {
142 address: program_counter.old_pc(zve64x_helpers::INSTRUCTION_SIZE),
143 })?;
144 unsafe {
146 zve64x_mask_helpers::execute_mask_logical_op(
147 ext_state,
148 vd,
149 vs2,
150 vs1,
151 |a, b| a | !b,
152 );
153 }
154 }
155 Self::Vmnand { vd, vs2, vs1 } => {
156 if !ext_state.vector_instructions_allowed() {
157 Err(ExecutionError::IllegalInstruction {
158 address: program_counter.old_pc(zve64x_helpers::INSTRUCTION_SIZE),
159 })?;
160 }
161 ext_state
162 .vtype()
163 .ok_or(ExecutionError::IllegalInstruction {
164 address: program_counter.old_pc(zve64x_helpers::INSTRUCTION_SIZE),
165 })?;
166 unsafe {
168 zve64x_mask_helpers::execute_mask_logical_op(
169 ext_state,
170 vd,
171 vs2,
172 vs1,
173 |a, b| !(a & b),
174 );
175 }
176 }
177 Self::Vmnor { vd, vs2, vs1 } => {
178 if !ext_state.vector_instructions_allowed() {
179 Err(ExecutionError::IllegalInstruction {
180 address: program_counter.old_pc(zve64x_helpers::INSTRUCTION_SIZE),
181 })?;
182 }
183 ext_state
184 .vtype()
185 .ok_or(ExecutionError::IllegalInstruction {
186 address: program_counter.old_pc(zve64x_helpers::INSTRUCTION_SIZE),
187 })?;
188 unsafe {
190 zve64x_mask_helpers::execute_mask_logical_op(
191 ext_state,
192 vd,
193 vs2,
194 vs1,
195 |a, b| !(a | b),
196 );
197 }
198 }
199 Self::Vmxnor { vd, vs2, vs1 } => {
200 if !ext_state.vector_instructions_allowed() {
201 Err(ExecutionError::IllegalInstruction {
202 address: program_counter.old_pc(zve64x_helpers::INSTRUCTION_SIZE),
203 })?;
204 }
205 ext_state
206 .vtype()
207 .ok_or(ExecutionError::IllegalInstruction {
208 address: program_counter.old_pc(zve64x_helpers::INSTRUCTION_SIZE),
209 })?;
210 unsafe {
212 zve64x_mask_helpers::execute_mask_logical_op(
213 ext_state,
214 vd,
215 vs2,
216 vs1,
217 |a, b| !(a ^ b),
218 );
219 }
220 }
221 Self::Vcpop { rd, vs2, vm } => {
223 if !ext_state.vector_instructions_allowed() {
224 Err(ExecutionError::IllegalInstruction {
225 address: program_counter.old_pc(zve64x_helpers::INSTRUCTION_SIZE),
226 })?;
227 }
228 ext_state
230 .vtype()
231 .ok_or(ExecutionError::IllegalInstruction {
232 address: program_counter.old_pc(zve64x_helpers::INSTRUCTION_SIZE),
233 })?;
234 let vl = ext_state.vl();
235 let vstart = u32::from(ext_state.vstart());
236 unsafe {
239 zve64x_mask_helpers::execute_vcpop(regs, ext_state, rd, vs2, vm, vl, vstart);
240 }
241 }
242 Self::Vfirst { 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
250 .vtype()
251 .ok_or(ExecutionError::IllegalInstruction {
252 address: program_counter.old_pc(zve64x_helpers::INSTRUCTION_SIZE),
253 })?;
254 let vl = ext_state.vl();
255 let vstart = u32::from(ext_state.vstart());
256 unsafe {
258 zve64x_mask_helpers::execute_vfirst(regs, ext_state, rd, vs2, vm, vl, vstart);
259 }
260 }
261 Self::Vmsbf { vd, vs2, vm } => {
264 if !ext_state.vector_instructions_allowed() {
265 Err(ExecutionError::IllegalInstruction {
266 address: program_counter.old_pc(zve64x_helpers::INSTRUCTION_SIZE),
267 })?;
268 }
269 ext_state
270 .vtype()
271 .ok_or(ExecutionError::IllegalInstruction {
272 address: program_counter.old_pc(zve64x_helpers::INSTRUCTION_SIZE),
273 })?;
274 if ext_state.vstart() != 0 {
277 Err(ExecutionError::IllegalInstruction {
278 address: program_counter.old_pc(zve64x_helpers::INSTRUCTION_SIZE),
279 })?;
280 }
281 if vd.bits() == vs2.bits() {
283 Err(ExecutionError::IllegalInstruction {
284 address: program_counter.old_pc(zve64x_helpers::INSTRUCTION_SIZE),
285 })?;
286 }
287 if !vm && vd.bits() == 0 {
288 Err(ExecutionError::IllegalInstruction {
289 address: program_counter.old_pc(zve64x_helpers::INSTRUCTION_SIZE),
290 })?;
291 }
292 let vl = ext_state.vl();
293 unsafe {
296 zve64x_mask_helpers::execute_vmsbf(ext_state, vd, vs2, vm, vl);
297 }
298 }
299 Self::Vmsof { vd, vs2, vm } => {
302 if !ext_state.vector_instructions_allowed() {
303 Err(ExecutionError::IllegalInstruction {
304 address: program_counter.old_pc(zve64x_helpers::INSTRUCTION_SIZE),
305 })?;
306 }
307 ext_state
308 .vtype()
309 .ok_or(ExecutionError::IllegalInstruction {
310 address: program_counter.old_pc(zve64x_helpers::INSTRUCTION_SIZE),
311 })?;
312 if ext_state.vstart() != 0 {
315 Err(ExecutionError::IllegalInstruction {
316 address: program_counter.old_pc(zve64x_helpers::INSTRUCTION_SIZE),
317 })?;
318 }
319 if vd.bits() == vs2.bits() {
320 Err(ExecutionError::IllegalInstruction {
321 address: program_counter.old_pc(zve64x_helpers::INSTRUCTION_SIZE),
322 })?;
323 }
324 if !vm && vd.bits() == 0 {
325 Err(ExecutionError::IllegalInstruction {
326 address: program_counter.old_pc(zve64x_helpers::INSTRUCTION_SIZE),
327 })?;
328 }
329 let vl = ext_state.vl();
330 unsafe {
332 zve64x_mask_helpers::execute_vmsof(ext_state, vd, vs2, vm, vl);
333 }
334 }
335 Self::Vmsif { vd, vs2, vm } => {
338 if !ext_state.vector_instructions_allowed() {
339 Err(ExecutionError::IllegalInstruction {
340 address: program_counter.old_pc(zve64x_helpers::INSTRUCTION_SIZE),
341 })?;
342 }
343 ext_state
344 .vtype()
345 .ok_or(ExecutionError::IllegalInstruction {
346 address: program_counter.old_pc(zve64x_helpers::INSTRUCTION_SIZE),
347 })?;
348 if ext_state.vstart() != 0 {
351 Err(ExecutionError::IllegalInstruction {
352 address: program_counter.old_pc(zve64x_helpers::INSTRUCTION_SIZE),
353 })?;
354 }
355 if vd.bits() == vs2.bits() {
356 Err(ExecutionError::IllegalInstruction {
357 address: program_counter.old_pc(zve64x_helpers::INSTRUCTION_SIZE),
358 })?;
359 }
360 if !vm && vd.bits() == 0 {
361 Err(ExecutionError::IllegalInstruction {
362 address: program_counter.old_pc(zve64x_helpers::INSTRUCTION_SIZE),
363 })?;
364 }
365 let vl = ext_state.vl();
366 unsafe {
368 zve64x_mask_helpers::execute_vmsif(ext_state, vd, vs2, vm, vl);
369 }
370 }
371 Self::Viota { vd, vs2, vm } => {
376 if !ext_state.vector_instructions_allowed() {
377 Err(ExecutionError::IllegalInstruction {
378 address: program_counter.old_pc(zve64x_helpers::INSTRUCTION_SIZE),
379 })?;
380 }
381 let vtype = ext_state
382 .vtype()
383 .ok_or(ExecutionError::IllegalInstruction {
384 address: program_counter.old_pc(zve64x_helpers::INSTRUCTION_SIZE),
385 })?;
386 if u32::from(ext_state.vstart()) != 0 {
388 Err(ExecutionError::IllegalInstruction {
389 address: program_counter.old_pc(zve64x_helpers::INSTRUCTION_SIZE),
390 })?;
391 }
392 let group_regs = vtype.vlmul().register_count();
393 let vd_idx = vd.bits();
394 if !vd_idx.is_multiple_of(group_regs) || vd_idx + group_regs > 32 {
395 Err(ExecutionError::IllegalInstruction {
396 address: program_counter.old_pc(zve64x_helpers::INSTRUCTION_SIZE),
397 })?;
398 }
399 let vd_start = u32::from(vd.bits());
401 let vs2_start = u32::from(vs2.bits());
402 if vd_start < vs2_start + 1 && vs2_start < vd_start + u32::from(group_regs) {
403 Err(ExecutionError::IllegalInstruction {
404 address: program_counter.old_pc(zve64x_helpers::INSTRUCTION_SIZE),
405 })?;
406 }
407 if !vm && vd.bits() == 0 {
408 Err(ExecutionError::IllegalInstruction {
409 address: program_counter.old_pc(zve64x_helpers::INSTRUCTION_SIZE),
410 })?;
411 }
412 let sew = vtype.vsew();
413 let sew_bits = u32::from(sew.bits());
414 let vlmax = vtype.vlmul().vlmax(ExtState::VLEN, sew_bits);
415 if u64::from(vlmax).unbounded_shr(sew_bits) != 0 {
416 Err(ExecutionError::IllegalInstruction {
417 address: program_counter.old_pc(zve64x_helpers::INSTRUCTION_SIZE),
418 })?;
419 }
420 let vl = ext_state.vl();
421 unsafe {
426 zve64x_mask_helpers::execute_viota(ext_state, vd, vs2, vm, vl, sew);
427 }
428 }
429 Self::Vid { vd, vm } => {
432 if !ext_state.vector_instructions_allowed() {
433 Err(ExecutionError::IllegalInstruction {
434 address: program_counter.old_pc(zve64x_helpers::INSTRUCTION_SIZE),
435 })?;
436 }
437 let vtype = ext_state
438 .vtype()
439 .ok_or(ExecutionError::IllegalInstruction {
440 address: program_counter.old_pc(zve64x_helpers::INSTRUCTION_SIZE),
441 })?;
442 let group_regs = vtype.vlmul().register_count();
443 let vd_idx = vd.bits();
444 if !vd_idx.is_multiple_of(group_regs) || vd_idx + group_regs > 32 {
445 Err(ExecutionError::IllegalInstruction {
446 address: program_counter.old_pc(zve64x_helpers::INSTRUCTION_SIZE),
447 })?;
448 }
449 if !vm && vd.bits() == 0 {
450 Err(ExecutionError::IllegalInstruction {
451 address: program_counter.old_pc(zve64x_helpers::INSTRUCTION_SIZE),
452 })?;
453 }
454 let sew = vtype.vsew();
455 let vl = ext_state.vl();
456 let vstart = u32::from(ext_state.vstart());
457 unsafe {
460 zve64x_mask_helpers::execute_vid(ext_state, vd, vm, vl, vstart, sew);
461 }
462 }
463 }
464
465 Ok(ControlFlow::Continue(()))
466 }
467}