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, Hart> ExecutableInstructionOperands for ZveXxMaskInstruction<Hart>
20where
21 Reg: Register,
22 Hart: VectorHartConfig<Reg = Reg>,
23{
24}
25
26#[instruction_execution]
27const impl<Reg, Hart, Env> ExecutableInstructionCsr<Env> for ZveXxMaskInstruction<Hart>
28where
29 Reg: Register,
30 Hart: VectorHartConfig<Reg = Reg>,
31{
32}
33
34#[instruction_execution]
35impl<Reg, Hart, Regs, Env, Memory, PC> ExecutableInstruction<Regs, Env, Memory, PC>
36 for ZveXxMaskInstruction<Hart>
37where
38 Reg: Register,
39 Hart: VectorHartConfig<Reg = Reg>,
40 Regs: RegisterFile<Reg>,
41 Env: VectorRegistersExt<Hart = Hart>,
42 Memory: VirtualMemory,
43 PC: ProgramCounter<Reg::Type, Memory>,
44{
45 #[inline(always)]
46 #[cfg_attr(feature = "no-panic", no_panic_const::no_panic)]
47 fn execute(
48 self,
49 Rs1Rs2OperandValues {
50 rs1_value: _,
51 rs2_value: _,
52 }: Rs1Rs2OperandValues<Reg::Type>,
53 _regs: &mut Regs,
54 env: &mut Env,
55 _memory: &mut Memory,
56 program_counter: &PC,
57 ) -> ExecutionResult<Reg> {
58 match self {
59 Self::Vmandn { vd, vs2, vs1 } => {
65 if !zvexx_helpers::non_memory_instruction_allowed::<Reg, _>(env) {
66 ::core::hint::cold_path();
67 return ExecutionResult::Err(ExecutionError::IllegalInstruction {
68 address: PackedAddress::new(
69 program_counter.old_pc(zvexx_helpers::INSTRUCTION_SIZE),
70 ),
71 });
72 }
73 let Some(config) = env.vector_config() else {
74 ::core::hint::cold_path();
75 return ExecutionResult::Err(ExecutionError::IllegalInstruction {
76 address: PackedAddress::new(
77 program_counter.old_pc(zvexx_helpers::INSTRUCTION_SIZE),
78 ),
79 });
80 };
81 zvexx_mask_helpers::execute_mask_logical_op(env, config, vd, vs2, vs1, |a, b| {
82 a && !b
83 });
84 }
85 Self::Vmand { vd, vs2, vs1 } => {
86 if !zvexx_helpers::non_memory_instruction_allowed::<Reg, _>(env) {
87 ::core::hint::cold_path();
88 return ExecutionResult::Err(ExecutionError::IllegalInstruction {
89 address: PackedAddress::new(
90 program_counter.old_pc(zvexx_helpers::INSTRUCTION_SIZE),
91 ),
92 });
93 }
94 let Some(config) = env.vector_config() else {
95 ::core::hint::cold_path();
96 return ExecutionResult::Err(ExecutionError::IllegalInstruction {
97 address: PackedAddress::new(
98 program_counter.old_pc(zvexx_helpers::INSTRUCTION_SIZE),
99 ),
100 });
101 };
102 zvexx_mask_helpers::execute_mask_logical_op(env, config, vd, vs2, vs1, |a, b| {
103 a & b
104 });
105 }
106 Self::Vmor { vd, vs2, vs1 } => {
107 if !zvexx_helpers::non_memory_instruction_allowed::<Reg, _>(env) {
108 ::core::hint::cold_path();
109 return ExecutionResult::Err(ExecutionError::IllegalInstruction {
110 address: PackedAddress::new(
111 program_counter.old_pc(zvexx_helpers::INSTRUCTION_SIZE),
112 ),
113 });
114 }
115 let Some(config) = env.vector_config() else {
116 ::core::hint::cold_path();
117 return ExecutionResult::Err(ExecutionError::IllegalInstruction {
118 address: PackedAddress::new(
119 program_counter.old_pc(zvexx_helpers::INSTRUCTION_SIZE),
120 ),
121 });
122 };
123 zvexx_mask_helpers::execute_mask_logical_op(env, config, vd, vs2, vs1, |a, b| {
124 a | b
125 });
126 }
127 Self::Vmxor { vd, vs2, vs1 } => {
128 if !zvexx_helpers::non_memory_instruction_allowed::<Reg, _>(env) {
129 ::core::hint::cold_path();
130 return ExecutionResult::Err(ExecutionError::IllegalInstruction {
131 address: PackedAddress::new(
132 program_counter.old_pc(zvexx_helpers::INSTRUCTION_SIZE),
133 ),
134 });
135 }
136 let Some(config) = env.vector_config() else {
137 ::core::hint::cold_path();
138 return ExecutionResult::Err(ExecutionError::IllegalInstruction {
139 address: PackedAddress::new(
140 program_counter.old_pc(zvexx_helpers::INSTRUCTION_SIZE),
141 ),
142 });
143 };
144 zvexx_mask_helpers::execute_mask_logical_op(env, config, vd, vs2, vs1, |a, b| {
145 a ^ b
146 });
147 }
148 Self::Vmorn { vd, vs2, vs1 } => {
149 if !zvexx_helpers::non_memory_instruction_allowed::<Reg, _>(env) {
150 ::core::hint::cold_path();
151 return ExecutionResult::Err(ExecutionError::IllegalInstruction {
152 address: PackedAddress::new(
153 program_counter.old_pc(zvexx_helpers::INSTRUCTION_SIZE),
154 ),
155 });
156 }
157 let Some(config) = env.vector_config() else {
158 ::core::hint::cold_path();
159 return ExecutionResult::Err(ExecutionError::IllegalInstruction {
160 address: PackedAddress::new(
161 program_counter.old_pc(zvexx_helpers::INSTRUCTION_SIZE),
162 ),
163 });
164 };
165 zvexx_mask_helpers::execute_mask_logical_op(env, config, vd, vs2, vs1, |a, b| {
166 a || !b
167 });
168 }
169 Self::Vmnand { vd, vs2, vs1 } => {
170 if !zvexx_helpers::non_memory_instruction_allowed::<Reg, _>(env) {
171 ::core::hint::cold_path();
172 return ExecutionResult::Err(ExecutionError::IllegalInstruction {
173 address: PackedAddress::new(
174 program_counter.old_pc(zvexx_helpers::INSTRUCTION_SIZE),
175 ),
176 });
177 }
178 let Some(config) = env.vector_config() else {
179 ::core::hint::cold_path();
180 return ExecutionResult::Err(ExecutionError::IllegalInstruction {
181 address: PackedAddress::new(
182 program_counter.old_pc(zvexx_helpers::INSTRUCTION_SIZE),
183 ),
184 });
185 };
186 zvexx_mask_helpers::execute_mask_logical_op(env, config, vd, vs2, vs1, |a, b| {
187 !(a & b)
188 });
189 }
190 Self::Vmnor { vd, vs2, vs1 } => {
191 if !zvexx_helpers::non_memory_instruction_allowed::<Reg, _>(env) {
192 ::core::hint::cold_path();
193 return ExecutionResult::Err(ExecutionError::IllegalInstruction {
194 address: PackedAddress::new(
195 program_counter.old_pc(zvexx_helpers::INSTRUCTION_SIZE),
196 ),
197 });
198 }
199 let Some(config) = env.vector_config() else {
200 ::core::hint::cold_path();
201 return ExecutionResult::Err(ExecutionError::IllegalInstruction {
202 address: PackedAddress::new(
203 program_counter.old_pc(zvexx_helpers::INSTRUCTION_SIZE),
204 ),
205 });
206 };
207 zvexx_mask_helpers::execute_mask_logical_op(env, config, vd, vs2, vs1, |a, b| {
208 !(a | b)
209 });
210 }
211 Self::Vmxnor { vd, vs2, vs1 } => {
212 if !zvexx_helpers::non_memory_instruction_allowed::<Reg, _>(env) {
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 let Some(config) = env.vector_config() else {
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 zvexx_mask_helpers::execute_mask_logical_op(env, config, vd, vs2, vs1, |a, b| {
229 !(a ^ b)
230 });
231 }
232 Self::Vcpop { rd, vs2, vm } => {
234 if !zvexx_helpers::non_memory_instruction_allowed::<Reg, _>(env) {
235 ::core::hint::cold_path();
236 return ExecutionResult::Err(ExecutionError::IllegalInstruction {
237 address: PackedAddress::new(
238 program_counter.old_pc(zvexx_helpers::INSTRUCTION_SIZE),
239 ),
240 });
241 }
242 let Some(config) = env.vector_config() else {
244 ::core::hint::cold_path();
245 return ExecutionResult::Err(ExecutionError::IllegalInstruction {
246 address: PackedAddress::new(
247 program_counter.old_pc(zvexx_helpers::INSTRUCTION_SIZE),
248 ),
249 });
250 };
251 let rd_value = zvexx_mask_helpers::execute_vcpop(env, config, vs2, vm);
252
253 return ExecutionResult::Continue {
254 rd,
255 value: rd_value,
256 };
257 }
258 Self::Vfirst { rd, vs2, vm } => {
260 if !zvexx_helpers::non_memory_instruction_allowed::<Reg, _>(env) {
261 ::core::hint::cold_path();
262 return ExecutionResult::Err(ExecutionError::IllegalInstruction {
263 address: PackedAddress::new(
264 program_counter.old_pc(zvexx_helpers::INSTRUCTION_SIZE),
265 ),
266 });
267 }
268 let Some(config) = env.vector_config() else {
269 ::core::hint::cold_path();
270 return ExecutionResult::Err(ExecutionError::IllegalInstruction {
271 address: PackedAddress::new(
272 program_counter.old_pc(zvexx_helpers::INSTRUCTION_SIZE),
273 ),
274 });
275 };
276 let rd_value = zvexx_mask_helpers::execute_vfirst(env, config, vs2, vm);
277
278 return ExecutionResult::Continue {
279 rd,
280 value: rd_value,
281 };
282 }
283 Self::Vmsbf { vd, vs2, vm } => {
286 if !zvexx_helpers::non_memory_instruction_allowed::<Reg, _>(env) {
287 ::core::hint::cold_path();
288 return ExecutionResult::Err(ExecutionError::IllegalInstruction {
289 address: PackedAddress::new(
290 program_counter.old_pc(zvexx_helpers::INSTRUCTION_SIZE),
291 ),
292 });
293 }
294 let Some(config) = env.vector_config() else {
295 ::core::hint::cold_path();
296 return ExecutionResult::Err(ExecutionError::IllegalInstruction {
297 address: PackedAddress::new(
298 program_counter.old_pc(zvexx_helpers::INSTRUCTION_SIZE),
299 ),
300 });
301 };
302 if vd == vs2 {
304 ::core::hint::cold_path();
305 return ExecutionResult::Err(ExecutionError::IllegalInstruction {
306 address: PackedAddress::new(
307 program_counter.old_pc(zvexx_helpers::INSTRUCTION_SIZE),
308 ),
309 });
310 }
311 let vl = config.vl();
312 zvexx_mask_helpers::execute_vmsbf(env, vd, vs2, vm, vl);
313 }
314 Self::Vmsof { vd, vs2, vm } => {
317 if !zvexx_helpers::non_memory_instruction_allowed::<Reg, _>(env) {
318 ::core::hint::cold_path();
319 return ExecutionResult::Err(ExecutionError::IllegalInstruction {
320 address: PackedAddress::new(
321 program_counter.old_pc(zvexx_helpers::INSTRUCTION_SIZE),
322 ),
323 });
324 }
325 let Some(config) = env.vector_config() else {
326 ::core::hint::cold_path();
327 return ExecutionResult::Err(ExecutionError::IllegalInstruction {
328 address: PackedAddress::new(
329 program_counter.old_pc(zvexx_helpers::INSTRUCTION_SIZE),
330 ),
331 });
332 };
333 if vd == vs2 {
334 ::core::hint::cold_path();
335 return ExecutionResult::Err(ExecutionError::IllegalInstruction {
336 address: PackedAddress::new(
337 program_counter.old_pc(zvexx_helpers::INSTRUCTION_SIZE),
338 ),
339 });
340 }
341 let vl = config.vl();
342 zvexx_mask_helpers::execute_vmsof(env, vd, vs2, vm, vl);
343 }
344 Self::Vmsif { vd, vs2, vm } => {
347 if !zvexx_helpers::non_memory_instruction_allowed::<Reg, _>(env) {
348 ::core::hint::cold_path();
349 return ExecutionResult::Err(ExecutionError::IllegalInstruction {
350 address: PackedAddress::new(
351 program_counter.old_pc(zvexx_helpers::INSTRUCTION_SIZE),
352 ),
353 });
354 }
355 let Some(config) = env.vector_config() else {
356 ::core::hint::cold_path();
357 return ExecutionResult::Err(ExecutionError::IllegalInstruction {
358 address: PackedAddress::new(
359 program_counter.old_pc(zvexx_helpers::INSTRUCTION_SIZE),
360 ),
361 });
362 };
363 if vd == vs2 {
364 ::core::hint::cold_path();
365 return ExecutionResult::Err(ExecutionError::IllegalInstruction {
366 address: PackedAddress::new(
367 program_counter.old_pc(zvexx_helpers::INSTRUCTION_SIZE),
368 ),
369 });
370 }
371 let vl = config.vl();
372 zvexx_mask_helpers::execute_vmsif(env, vd, vs2, vm, vl);
373 }
374 Self::Viota { vd, vs2, vm } => {
381 if !zvexx_helpers::non_memory_instruction_allowed::<Reg, _>(env) {
382 ::core::hint::cold_path();
383 return ExecutionResult::Err(ExecutionError::IllegalInstruction {
384 address: PackedAddress::new(
385 program_counter.old_pc(zvexx_helpers::INSTRUCTION_SIZE),
386 ),
387 });
388 }
389 let Some(config) = env.vector_config() else {
390 ::core::hint::cold_path();
391 return ExecutionResult::Err(ExecutionError::IllegalInstruction {
392 address: PackedAddress::new(
393 program_counter.old_pc(zvexx_helpers::INSTRUCTION_SIZE),
394 ),
395 });
396 };
397 let vd = zvexx_helpers::vreg_group::<Reg, Env, _, _>(
398 program_counter,
399 config,
400 vd,
401 config.vtype().vsew().as_eew(),
402 )?;
403 let vs2_start = vs2.to_bits();
405 let vd_start = vd.base().to_bits();
406 if vd_start <= vs2_start && vs2_start < vd_start + vd.group_regs().get() {
407 ::core::hint::cold_path();
408 return ExecutionResult::Err(ExecutionError::IllegalInstruction {
409 address: PackedAddress::new(
410 program_counter.old_pc(zvexx_helpers::INSTRUCTION_SIZE),
411 ),
412 });
413 }
414 zvexx_mask_helpers::execute_viota(env, vd, vs2, vm);
415 }
416 Self::Vid { vd, vm } => {
419 if !zvexx_helpers::non_memory_instruction_allowed::<Reg, _>(env) {
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 let Some(config) = env.vector_config() else {
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 vd = zvexx_helpers::vreg_group::<Reg, Env, _, _>(
436 program_counter,
437 config,
438 vd,
439 config.vtype().vsew().as_eew(),
440 )?;
441 zvexx_mask_helpers::execute_vid(env, vd, vm);
442 }
443 }
444
445 ExecutionResult::ContinueNoWrite
446 }
447}