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