1#[cfg(test)]
4pub(super) mod tests;
5pub mod zvexx_load_helpers;
6
7use crate::v::vector_registers::{VectorRegisters, 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 ZveXxLoadInstruction<Hart>
20where
21 Reg: Register,
22 Hart: VectorHartConfig<Reg = Reg>,
23{
24}
25
26#[instruction_execution]
27const impl<Reg, Hart, Env> ExecutableInstructionCsr<Env> for ZveXxLoadInstruction<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 ZveXxLoadInstruction<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::Vlr {
62 vd,
63 rs1: _,
64 nreg,
65 eew,
66 } => {
67 let nreg = nreg.num_registers();
68 if !env.vector_instructions_allowed() {
69 ::core::hint::cold_path();
70 return ExecutionResult::Err(ExecutionError::IllegalInstruction {
71 address: PackedAddress::new(
72 program_counter.old_pc(zvexx_helpers::INSTRUCTION_SIZE),
73 ),
74 });
75 }
76 let Some(vd) = zvexx_load_helpers::VRegGroup::whole_registers(vd, nreg, eew) else {
77 ::core::hint::cold_path();
78 return ExecutionResult::Err(ExecutionError::IllegalInstruction {
79 address: PackedAddress::new(
80 program_counter.old_pc(zvexx_helpers::INSTRUCTION_SIZE),
81 ),
82 });
83 };
84 let vl = vd.vl().get();
86 if env.vstart() >= vl {
88 ::core::hint::cold_path();
89 return ExecutionResult::Err(ExecutionError::IllegalInstruction {
90 address: PackedAddress::new(
91 program_counter.old_pc(zvexx_helpers::INSTRUCTION_SIZE),
92 ),
93 });
94 }
95 zvexx_load_helpers::execute_unit_stride_load(
96 env,
97 memory,
98 zvexx_load_helpers::VRegSegmentGroup::single(vd),
99 true,
100 rs1_value.as_u64(),
101 None,
102 )?;
103 }
104
105 Self::Vlm { vd, rs1: _ } => {
108 if !env.vector_instructions_allowed() {
109 ::core::hint::cold_path();
110 return ExecutionResult::Err(ExecutionError::IllegalInstruction {
111 address: PackedAddress::new(
112 program_counter.old_pc(zvexx_helpers::INSTRUCTION_SIZE),
113 ),
114 });
115 }
116 let Some(config) = env.vector_config() else {
117 ::core::hint::cold_path();
118 return ExecutionResult::Err(ExecutionError::IllegalInstruction {
119 address: PackedAddress::new(
120 program_counter.old_pc(zvexx_helpers::INSTRUCTION_SIZE),
121 ),
122 });
123 };
124 let Some(vd) =
127 zvexx_load_helpers::VRegGroup::whole_registers(vd, VRegGroupSize::R1, Eew::E8)
128 .and_then(|vd| vd.with_vl(Vl::from(config.vl().bytes())))
129 else {
130 ::core::hint::cold_path();
131 return ExecutionResult::Err(ExecutionError::IllegalInstruction {
132 address: PackedAddress::new(
133 program_counter.old_pc(zvexx_helpers::INSTRUCTION_SIZE),
134 ),
135 });
136 };
137 zvexx_load_helpers::execute_unit_stride_load(
138 env,
139 memory,
140 zvexx_load_helpers::VRegSegmentGroup::single(vd),
141 true,
142 rs1_value.as_u64(),
143 None,
144 )?;
145 }
146
147 Self::Vle {
153 vd,
154 rs1: _,
155 vm,
156 eew,
157 } => {
158 if !env.vector_instructions_allowed() {
159 ::core::hint::cold_path();
160 return ExecutionResult::Err(ExecutionError::IllegalInstruction {
161 address: PackedAddress::new(
162 program_counter.old_pc(zvexx_helpers::INSTRUCTION_SIZE),
163 ),
164 });
165 }
166 let Some(config) = env.vector_config() else {
167 ::core::hint::cold_path();
168 return ExecutionResult::Err(ExecutionError::IllegalInstruction {
169 address: PackedAddress::new(
170 program_counter.old_pc(zvexx_helpers::INSTRUCTION_SIZE),
171 ),
172 });
173 };
174 let vd =
175 zvexx_helpers::vreg_group::<Reg, Env, _, _>(program_counter, config, vd, eew)?;
176 zvexx_load_helpers::execute_unit_stride_load(
177 env,
178 memory,
179 zvexx_load_helpers::VRegSegmentGroup::single(vd),
180 vm,
181 rs1_value.as_u64(),
182 None,
183 )?;
184 }
185
186 Self::Vleff {
188 vd,
189 rs1: _,
190 vm,
191 eew,
192 } => {
193 if !env.vector_instructions_allowed() {
194 ::core::hint::cold_path();
195 return ExecutionResult::Err(ExecutionError::IllegalInstruction {
196 address: PackedAddress::new(
197 program_counter.old_pc(zvexx_helpers::INSTRUCTION_SIZE),
198 ),
199 });
200 }
201 let Some(config) = env.vector_config() else {
202 ::core::hint::cold_path();
203 return ExecutionResult::Err(ExecutionError::IllegalInstruction {
204 address: PackedAddress::new(
205 program_counter.old_pc(zvexx_helpers::INSTRUCTION_SIZE),
206 ),
207 });
208 };
209 let vd =
210 zvexx_helpers::vreg_group::<Reg, Env, _, _>(program_counter, config, vd, eew)?;
211 zvexx_load_helpers::execute_unit_stride_load(
212 env,
213 memory,
214 zvexx_load_helpers::VRegSegmentGroup::single(vd),
215 vm,
216 rs1_value.as_u64(),
217 Some(config),
218 )?;
219 }
220
221 Self::Vlse {
223 vd,
224 rs1: _,
225 rs2: _,
226 vm,
227 eew,
228 } => {
229 if !env.vector_instructions_allowed() {
230 ::core::hint::cold_path();
231 return ExecutionResult::Err(ExecutionError::IllegalInstruction {
232 address: PackedAddress::new(
233 program_counter.old_pc(zvexx_helpers::INSTRUCTION_SIZE),
234 ),
235 });
236 }
237 let Some(config) = env.vector_config() else {
238 ::core::hint::cold_path();
239 return ExecutionResult::Err(ExecutionError::IllegalInstruction {
240 address: PackedAddress::new(
241 program_counter.old_pc(zvexx_helpers::INSTRUCTION_SIZE),
242 ),
243 });
244 };
245 let vd =
246 zvexx_helpers::vreg_group::<Reg, Env, _, _>(program_counter, config, vd, eew)?;
247 let stride = rs2_value.as_i64();
249 zvexx_load_helpers::execute_strided_load(
250 env,
251 memory,
252 zvexx_load_helpers::VRegSegmentGroup::single(vd),
253 vm,
254 rs1_value.as_u64(),
255 stride,
256 )?;
257 }
258
259 Self::Vluxei {
262 vd,
263 rs1: _,
264 vs2,
265 vm,
266 eew: index_eew,
267 } => {
268 if !env.vector_instructions_allowed() {
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 Some(config) = env.vector_config() else {
277 ::core::hint::cold_path();
278 return ExecutionResult::Err(ExecutionError::IllegalInstruction {
279 address: PackedAddress::new(
280 program_counter.old_pc(zvexx_helpers::INSTRUCTION_SIZE),
281 ),
282 });
283 };
284 let sew = config.vtype().vsew();
285 let vd = zvexx_helpers::vreg_group::<Reg, Env, _, _>(
286 program_counter,
287 config,
288 vd,
289 sew.as_eew(),
290 )?;
291 let vs2 = zvexx_helpers::vreg_group::<Reg, Env, _, _>(
292 program_counter,
293 config,
294 vs2,
295 index_eew,
296 )?;
297 zvexx_helpers::check_destination_overlap::<Reg, Env, _, _>(
301 program_counter,
302 vd,
303 vs2,
304 )?;
305 zvexx_load_helpers::execute_indexed_load(
306 env,
307 memory,
308 zvexx_load_helpers::VRegSegmentGroup::single(vd),
309 vs2,
310 vm,
311 rs1_value.as_u64(),
312 )?;
313 }
314
315 Self::Vloxei {
318 vd,
319 rs1: _,
320 vs2,
321 vm,
322 eew: index_eew,
323 } => {
324 if !env.vector_instructions_allowed() {
325 ::core::hint::cold_path();
326 return ExecutionResult::Err(ExecutionError::IllegalInstruction {
327 address: PackedAddress::new(
328 program_counter.old_pc(zvexx_helpers::INSTRUCTION_SIZE),
329 ),
330 });
331 }
332 let Some(config) = env.vector_config() else {
333 ::core::hint::cold_path();
334 return ExecutionResult::Err(ExecutionError::IllegalInstruction {
335 address: PackedAddress::new(
336 program_counter.old_pc(zvexx_helpers::INSTRUCTION_SIZE),
337 ),
338 });
339 };
340 let sew = config.vtype().vsew();
341 let vd = zvexx_helpers::vreg_group::<Reg, Env, _, _>(
342 program_counter,
343 config,
344 vd,
345 sew.as_eew(),
346 )?;
347 let vs2 = zvexx_helpers::vreg_group::<Reg, Env, _, _>(
348 program_counter,
349 config,
350 vs2,
351 index_eew,
352 )?;
353 zvexx_helpers::check_destination_overlap::<Reg, Env, _, _>(
357 program_counter,
358 vd,
359 vs2,
360 )?;
361 zvexx_load_helpers::execute_indexed_load(
362 env,
363 memory,
364 zvexx_load_helpers::VRegSegmentGroup::single(vd),
365 vs2,
366 vm,
367 rs1_value.as_u64(),
368 )?;
369 }
370
371 Self::Vlseg {
373 vd,
374 rs1: _,
375 eew,
376 vm_nf,
377 } => {
378 let vm = vm_nf.vm();
379 let nf = vm_nf.nf();
380 if !env.vector_instructions_allowed() {
381 ::core::hint::cold_path();
382 return ExecutionResult::Err(ExecutionError::IllegalInstruction {
383 address: PackedAddress::new(
384 program_counter.old_pc(zvexx_helpers::INSTRUCTION_SIZE),
385 ),
386 });
387 }
388 let Some(config) = env.vector_config() else {
389 ::core::hint::cold_path();
390 return ExecutionResult::Err(ExecutionError::IllegalInstruction {
391 address: PackedAddress::new(
392 program_counter.old_pc(zvexx_helpers::INSTRUCTION_SIZE),
393 ),
394 });
395 };
396 let vd =
397 zvexx_helpers::vreg_group::<Reg, Env, _, _>(program_counter, config, vd, eew)?;
398 let vd =
399 zvexx_helpers::vreg_segment_group::<Reg, Env, _, _>(program_counter, vd, nf)?;
400 zvexx_load_helpers::execute_unit_stride_load(
401 env,
402 memory,
403 vd,
404 vm,
405 rs1_value.as_u64(),
406 None,
407 )?;
408 }
409
410 Self::Vlsegff {
412 vd,
413 rs1: _,
414 eew,
415 vm_nf,
416 } => {
417 let vm = vm_nf.vm();
418 let nf = vm_nf.nf();
419 if !env.vector_instructions_allowed() {
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 =
436 zvexx_helpers::vreg_group::<Reg, Env, _, _>(program_counter, config, vd, eew)?;
437 let vd =
438 zvexx_helpers::vreg_segment_group::<Reg, Env, _, _>(program_counter, vd, nf)?;
439 zvexx_load_helpers::execute_unit_stride_load(
440 env,
441 memory,
442 vd,
443 vm,
444 rs1_value.as_u64(),
445 Some(config),
446 )?;
447 }
448
449 Self::Vlsseg {
451 vd,
452 rs1: _,
453 rs2: _,
454 eew,
455 vm_nf,
456 } => {
457 let vm = vm_nf.vm();
458 let nf = vm_nf.nf();
459 if !env.vector_instructions_allowed() {
460 ::core::hint::cold_path();
461 return ExecutionResult::Err(ExecutionError::IllegalInstruction {
462 address: PackedAddress::new(
463 program_counter.old_pc(zvexx_helpers::INSTRUCTION_SIZE),
464 ),
465 });
466 }
467 let Some(config) = env.vector_config() else {
468 ::core::hint::cold_path();
469 return ExecutionResult::Err(ExecutionError::IllegalInstruction {
470 address: PackedAddress::new(
471 program_counter.old_pc(zvexx_helpers::INSTRUCTION_SIZE),
472 ),
473 });
474 };
475 let vd =
476 zvexx_helpers::vreg_group::<Reg, Env, _, _>(program_counter, config, vd, eew)?;
477 let vd =
478 zvexx_helpers::vreg_segment_group::<Reg, Env, _, _>(program_counter, vd, nf)?;
479 let stride = rs2_value.as_i64();
480 zvexx_load_helpers::execute_strided_load(
481 env,
482 memory,
483 vd,
484 vm,
485 rs1_value.as_u64(),
486 stride,
487 )?;
488 }
489
490 Self::Vluxseg {
492 vd,
493 rs1: _,
494 vs2,
495 eew: index_eew,
496 vm_nf,
497 } => {
498 let vm = vm_nf.vm();
499 let nf = vm_nf.nf();
500 if !env.vector_instructions_allowed() {
501 ::core::hint::cold_path();
502 return ExecutionResult::Err(ExecutionError::IllegalInstruction {
503 address: PackedAddress::new(
504 program_counter.old_pc(zvexx_helpers::INSTRUCTION_SIZE),
505 ),
506 });
507 }
508 let Some(config) = env.vector_config() else {
509 ::core::hint::cold_path();
510 return ExecutionResult::Err(ExecutionError::IllegalInstruction {
511 address: PackedAddress::new(
512 program_counter.old_pc(zvexx_helpers::INSTRUCTION_SIZE),
513 ),
514 });
515 };
516 let sew = config.vtype().vsew();
517 let vd = zvexx_helpers::vreg_group::<Reg, Env, _, _>(
518 program_counter,
519 config,
520 vd,
521 sew.as_eew(),
522 )?;
523 let vd =
524 zvexx_helpers::vreg_segment_group::<Reg, Env, _, _>(program_counter, vd, nf)?;
525 let vs2 = zvexx_helpers::vreg_group::<Reg, Env, _, _>(
526 program_counter,
527 config,
528 vs2,
529 index_eew,
530 )?;
531 if vd.fields().any(|field| field.overlaps(vs2)) {
533 ::core::hint::cold_path();
534 return ExecutionResult::Err(ExecutionError::IllegalInstruction {
535 address: PackedAddress::new(
536 program_counter.old_pc(zvexx_helpers::INSTRUCTION_SIZE),
537 ),
538 });
539 }
540 zvexx_load_helpers::execute_indexed_load(
541 env,
542 memory,
543 vd,
544 vs2,
545 vm,
546 rs1_value.as_u64(),
547 )?;
548 }
549
550 Self::Vloxseg {
553 vd,
554 rs1: _,
555 vs2,
556 eew: index_eew,
557 vm_nf,
558 } => {
559 let vm = vm_nf.vm();
560 let nf = vm_nf.nf();
561 if !env.vector_instructions_allowed() {
562 ::core::hint::cold_path();
563 return ExecutionResult::Err(ExecutionError::IllegalInstruction {
564 address: PackedAddress::new(
565 program_counter.old_pc(zvexx_helpers::INSTRUCTION_SIZE),
566 ),
567 });
568 }
569 let Some(config) = env.vector_config() else {
570 ::core::hint::cold_path();
571 return ExecutionResult::Err(ExecutionError::IllegalInstruction {
572 address: PackedAddress::new(
573 program_counter.old_pc(zvexx_helpers::INSTRUCTION_SIZE),
574 ),
575 });
576 };
577 let sew = config.vtype().vsew();
578 let vd = zvexx_helpers::vreg_group::<Reg, Env, _, _>(
579 program_counter,
580 config,
581 vd,
582 sew.as_eew(),
583 )?;
584 let vd =
585 zvexx_helpers::vreg_segment_group::<Reg, Env, _, _>(program_counter, vd, nf)?;
586 let vs2 = zvexx_helpers::vreg_group::<Reg, Env, _, _>(
587 program_counter,
588 config,
589 vs2,
590 index_eew,
591 )?;
592 if vd.fields().any(|field| field.overlaps(vs2)) {
594 ::core::hint::cold_path();
595 return ExecutionResult::Err(ExecutionError::IllegalInstruction {
596 address: PackedAddress::new(
597 program_counter.old_pc(zvexx_helpers::INSTRUCTION_SIZE),
598 ),
599 });
600 }
601 zvexx_load_helpers::execute_indexed_load(
602 env,
603 memory,
604 vd,
605 vs2,
606 vm,
607 rs1_value.as_u64(),
608 )?;
609 }
610 }
611
612 ExecutionResult::ContinueNoWrite
613 }
614}