1#[cfg(test)]
4mod tests;
5pub mod zvexx_carry_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 ZveXxCarryInstruction<Reg> where Reg: Register {}
20
21#[instruction_execution]
22impl<Reg, ExtState, CustomError> ExecutableInstructionCsr<ExtState, CustomError>
23 for ZveXxCarryInstruction<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 ZveXxCarryInstruction<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::VadcVvm { vd, vs2, vs1 } => {
63 if !ext_state.vector_instructions_allowed() {
64 return Err(ExecutionError::IllegalInstruction {
65 address: program_counter.old_pc(zvexx_helpers::INSTRUCTION_SIZE),
66 });
67 }
68 let vtype = ext_state
69 .vtype()
70 .ok_or(ExecutionError::IllegalInstruction {
71 address: program_counter.old_pc(zvexx_helpers::INSTRUCTION_SIZE),
72 })?;
73 let group_regs = vtype.vlmul().register_count();
74 zvexx_carry_helpers::check_vreg_group_alignment::<Reg, _, _, _>(
75 program_counter,
76 vd,
77 group_regs,
78 )?;
79 zvexx_carry_helpers::check_vreg_group_alignment::<Reg, _, _, _>(
80 program_counter,
81 vs2,
82 group_regs,
83 )?;
84 zvexx_carry_helpers::check_vreg_group_alignment::<Reg, _, _, _>(
85 program_counter,
86 vs1,
87 group_regs,
88 )?;
89 if vd == VReg::V0 {
91 return Err(ExecutionError::IllegalInstruction {
92 address: program_counter.old_pc(zvexx_helpers::INSTRUCTION_SIZE),
93 });
94 }
95 let sew = vtype.vsew();
96 unsafe {
98 zvexx_carry_helpers::execute_carry_add::<Reg, _, _>(
99 ext_state,
100 vd,
101 vs2,
102 zvexx_carry_helpers::OpSrc::Vreg(vs1),
103 true,
104 sew,
105 );
106 }
107 }
108
109 Self::VadcVxm { vd, vs2, rs1: _ } => {
110 if !ext_state.vector_instructions_allowed() {
111 return Err(ExecutionError::IllegalInstruction {
112 address: program_counter.old_pc(zvexx_helpers::INSTRUCTION_SIZE),
113 });
114 }
115 let vtype = ext_state
116 .vtype()
117 .ok_or(ExecutionError::IllegalInstruction {
118 address: program_counter.old_pc(zvexx_helpers::INSTRUCTION_SIZE),
119 })?;
120 let group_regs = vtype.vlmul().register_count();
121 zvexx_carry_helpers::check_vreg_group_alignment::<Reg, _, _, _>(
122 program_counter,
123 vd,
124 group_regs,
125 )?;
126 zvexx_carry_helpers::check_vreg_group_alignment::<Reg, _, _, _>(
127 program_counter,
128 vs2,
129 group_regs,
130 )?;
131 if vd == VReg::V0 {
132 return Err(ExecutionError::IllegalInstruction {
133 address: program_counter.old_pc(zvexx_helpers::INSTRUCTION_SIZE),
134 });
135 }
136 let sew = vtype.vsew();
137 let scalar = rs1_value.as_i64().cast_unsigned();
138 unsafe {
140 zvexx_carry_helpers::execute_carry_add::<Reg, _, _>(
141 ext_state,
142 vd,
143 vs2,
144 zvexx_carry_helpers::OpSrc::Scalar(scalar),
145 true,
146 sew,
147 );
148 }
149 }
150
151 Self::VadcVim { vd, vs2, imm } => {
152 if !ext_state.vector_instructions_allowed() {
153 return Err(ExecutionError::IllegalInstruction {
154 address: program_counter.old_pc(zvexx_helpers::INSTRUCTION_SIZE),
155 });
156 }
157 let vtype = ext_state
158 .vtype()
159 .ok_or(ExecutionError::IllegalInstruction {
160 address: program_counter.old_pc(zvexx_helpers::INSTRUCTION_SIZE),
161 })?;
162 let group_regs = vtype.vlmul().register_count();
163 zvexx_carry_helpers::check_vreg_group_alignment::<Reg, _, _, _>(
164 program_counter,
165 vd,
166 group_regs,
167 )?;
168 zvexx_carry_helpers::check_vreg_group_alignment::<Reg, _, _, _>(
169 program_counter,
170 vs2,
171 group_regs,
172 )?;
173 if vd == VReg::V0 {
174 return Err(ExecutionError::IllegalInstruction {
175 address: program_counter.old_pc(zvexx_helpers::INSTRUCTION_SIZE),
176 });
177 }
178 let sew = vtype.vsew();
179 let scalar = i64::from(imm).cast_unsigned();
180 unsafe {
182 zvexx_carry_helpers::execute_carry_add::<Reg, _, _>(
183 ext_state,
184 vd,
185 vs2,
186 zvexx_carry_helpers::OpSrc::Scalar(scalar),
187 true,
188 sew,
189 );
190 }
191 }
192
193 Self::VmadcVvm { vd, vs2, vs1 } => {
195 if !ext_state.vector_instructions_allowed() {
196 return Err(ExecutionError::IllegalInstruction {
197 address: program_counter.old_pc(zvexx_helpers::INSTRUCTION_SIZE),
198 });
199 }
200 let vtype = ext_state
201 .vtype()
202 .ok_or(ExecutionError::IllegalInstruction {
203 address: program_counter.old_pc(zvexx_helpers::INSTRUCTION_SIZE),
204 })?;
205 let group_regs = vtype.vlmul().register_count();
206 zvexx_carry_helpers::check_vreg_group_alignment::<Reg, _, _, _>(
207 program_counter,
208 vs2,
209 group_regs,
210 )?;
211 zvexx_carry_helpers::check_vreg_group_alignment::<Reg, _, _, _>(
212 program_counter,
213 vs1,
214 group_regs,
215 )?;
216 zvexx_carry_helpers::check_mask_dest_no_overlap::<Reg, _, _, _>(
217 program_counter,
218 vd,
219 vs2,
220 group_regs,
221 )?;
222 zvexx_carry_helpers::check_mask_dest_no_overlap::<Reg, _, _, _>(
223 program_counter,
224 vd,
225 vs1,
226 group_regs,
227 )?;
228 let sew = vtype.vsew();
229 unsafe {
231 zvexx_carry_helpers::execute_carry_add_mask::<Reg, _, _>(
232 ext_state,
233 vd,
234 vs2,
235 zvexx_carry_helpers::OpSrc::Vreg(vs1),
236 true,
237 sew,
238 );
239 }
240 }
241
242 Self::VmadcVxm { vd, vs2, rs1: _ } => {
243 if !ext_state.vector_instructions_allowed() {
244 return Err(ExecutionError::IllegalInstruction {
245 address: program_counter.old_pc(zvexx_helpers::INSTRUCTION_SIZE),
246 });
247 }
248 let vtype = ext_state
249 .vtype()
250 .ok_or(ExecutionError::IllegalInstruction {
251 address: program_counter.old_pc(zvexx_helpers::INSTRUCTION_SIZE),
252 })?;
253 let group_regs = vtype.vlmul().register_count();
254 zvexx_carry_helpers::check_vreg_group_alignment::<Reg, _, _, _>(
255 program_counter,
256 vs2,
257 group_regs,
258 )?;
259 zvexx_carry_helpers::check_mask_dest_no_overlap::<Reg, _, _, _>(
260 program_counter,
261 vd,
262 vs2,
263 group_regs,
264 )?;
265 let sew = vtype.vsew();
266 let scalar = rs1_value.as_i64().cast_unsigned();
267 unsafe {
269 zvexx_carry_helpers::execute_carry_add_mask::<Reg, _, _>(
270 ext_state,
271 vd,
272 vs2,
273 zvexx_carry_helpers::OpSrc::Scalar(scalar),
274 true,
275 sew,
276 );
277 }
278 }
279
280 Self::VmadcVim { vd, vs2, imm } => {
281 if !ext_state.vector_instructions_allowed() {
282 return Err(ExecutionError::IllegalInstruction {
283 address: program_counter.old_pc(zvexx_helpers::INSTRUCTION_SIZE),
284 });
285 }
286 let vtype = ext_state
287 .vtype()
288 .ok_or(ExecutionError::IllegalInstruction {
289 address: program_counter.old_pc(zvexx_helpers::INSTRUCTION_SIZE),
290 })?;
291 let group_regs = vtype.vlmul().register_count();
292 zvexx_carry_helpers::check_vreg_group_alignment::<Reg, _, _, _>(
293 program_counter,
294 vs2,
295 group_regs,
296 )?;
297 zvexx_carry_helpers::check_mask_dest_no_overlap::<Reg, _, _, _>(
298 program_counter,
299 vd,
300 vs2,
301 group_regs,
302 )?;
303 let sew = vtype.vsew();
304 let scalar = i64::from(imm).cast_unsigned();
305 unsafe {
307 zvexx_carry_helpers::execute_carry_add_mask::<Reg, _, _>(
308 ext_state,
309 vd,
310 vs2,
311 zvexx_carry_helpers::OpSrc::Scalar(scalar),
312 true,
313 sew,
314 );
315 }
316 }
317
318 Self::VmadcVv { vd, vs2, vs1 } => {
319 if !ext_state.vector_instructions_allowed() {
320 return Err(ExecutionError::IllegalInstruction {
321 address: program_counter.old_pc(zvexx_helpers::INSTRUCTION_SIZE),
322 });
323 }
324 let vtype = ext_state
325 .vtype()
326 .ok_or(ExecutionError::IllegalInstruction {
327 address: program_counter.old_pc(zvexx_helpers::INSTRUCTION_SIZE),
328 })?;
329 let group_regs = vtype.vlmul().register_count();
330 zvexx_carry_helpers::check_vreg_group_alignment::<Reg, _, _, _>(
331 program_counter,
332 vs2,
333 group_regs,
334 )?;
335 zvexx_carry_helpers::check_vreg_group_alignment::<Reg, _, _, _>(
336 program_counter,
337 vs1,
338 group_regs,
339 )?;
340 zvexx_carry_helpers::check_mask_dest_no_overlap::<Reg, _, _, _>(
341 program_counter,
342 vd,
343 vs2,
344 group_regs,
345 )?;
346 zvexx_carry_helpers::check_mask_dest_no_overlap::<Reg, _, _, _>(
347 program_counter,
348 vd,
349 vs1,
350 group_regs,
351 )?;
352 let sew = vtype.vsew();
353 unsafe {
355 zvexx_carry_helpers::execute_carry_add_mask::<Reg, _, _>(
356 ext_state,
357 vd,
358 vs2,
359 zvexx_carry_helpers::OpSrc::Vreg(vs1),
360 false,
361 sew,
362 );
363 }
364 }
365
366 Self::VmadcVx { vd, vs2, rs1: _ } => {
367 if !ext_state.vector_instructions_allowed() {
368 return Err(ExecutionError::IllegalInstruction {
369 address: program_counter.old_pc(zvexx_helpers::INSTRUCTION_SIZE),
370 });
371 }
372 let vtype = ext_state
373 .vtype()
374 .ok_or(ExecutionError::IllegalInstruction {
375 address: program_counter.old_pc(zvexx_helpers::INSTRUCTION_SIZE),
376 })?;
377 let group_regs = vtype.vlmul().register_count();
378 zvexx_carry_helpers::check_vreg_group_alignment::<Reg, _, _, _>(
379 program_counter,
380 vs2,
381 group_regs,
382 )?;
383 zvexx_carry_helpers::check_mask_dest_no_overlap::<Reg, _, _, _>(
384 program_counter,
385 vd,
386 vs2,
387 group_regs,
388 )?;
389 let sew = vtype.vsew();
390 let scalar = rs1_value.as_i64().cast_unsigned();
391 unsafe {
393 zvexx_carry_helpers::execute_carry_add_mask::<Reg, _, _>(
394 ext_state,
395 vd,
396 vs2,
397 zvexx_carry_helpers::OpSrc::Scalar(scalar),
398 false,
399 sew,
400 );
401 }
402 }
403
404 Self::VmadcVi { vd, vs2, imm } => {
405 if !ext_state.vector_instructions_allowed() {
406 return Err(ExecutionError::IllegalInstruction {
407 address: program_counter.old_pc(zvexx_helpers::INSTRUCTION_SIZE),
408 });
409 }
410 let vtype = ext_state
411 .vtype()
412 .ok_or(ExecutionError::IllegalInstruction {
413 address: program_counter.old_pc(zvexx_helpers::INSTRUCTION_SIZE),
414 })?;
415 let group_regs = vtype.vlmul().register_count();
416 zvexx_carry_helpers::check_vreg_group_alignment::<Reg, _, _, _>(
417 program_counter,
418 vs2,
419 group_regs,
420 )?;
421 zvexx_carry_helpers::check_mask_dest_no_overlap::<Reg, _, _, _>(
422 program_counter,
423 vd,
424 vs2,
425 group_regs,
426 )?;
427 let sew = vtype.vsew();
428 let scalar = i64::from(imm).cast_unsigned();
429 unsafe {
431 zvexx_carry_helpers::execute_carry_add_mask::<Reg, _, _>(
432 ext_state,
433 vd,
434 vs2,
435 zvexx_carry_helpers::OpSrc::Scalar(scalar),
436 false,
437 sew,
438 );
439 }
440 }
441
442 Self::VsbcVvm { vd, vs2, vs1 } => {
444 if !ext_state.vector_instructions_allowed() {
445 return Err(ExecutionError::IllegalInstruction {
446 address: program_counter.old_pc(zvexx_helpers::INSTRUCTION_SIZE),
447 });
448 }
449 let vtype = ext_state
450 .vtype()
451 .ok_or(ExecutionError::IllegalInstruction {
452 address: program_counter.old_pc(zvexx_helpers::INSTRUCTION_SIZE),
453 })?;
454 let group_regs = vtype.vlmul().register_count();
455 zvexx_carry_helpers::check_vreg_group_alignment::<Reg, _, _, _>(
456 program_counter,
457 vd,
458 group_regs,
459 )?;
460 zvexx_carry_helpers::check_vreg_group_alignment::<Reg, _, _, _>(
461 program_counter,
462 vs2,
463 group_regs,
464 )?;
465 zvexx_carry_helpers::check_vreg_group_alignment::<Reg, _, _, _>(
466 program_counter,
467 vs1,
468 group_regs,
469 )?;
470 if vd == VReg::V0 {
471 return Err(ExecutionError::IllegalInstruction {
472 address: program_counter.old_pc(zvexx_helpers::INSTRUCTION_SIZE),
473 });
474 }
475 let sew = vtype.vsew();
476 unsafe {
478 zvexx_carry_helpers::execute_carry_sub::<Reg, _, _>(
479 ext_state,
480 vd,
481 vs2,
482 zvexx_carry_helpers::OpSrc::Vreg(vs1),
483 sew,
484 );
485 }
486 }
487
488 Self::VsbcVxm { vd, vs2, rs1: _ } => {
489 if !ext_state.vector_instructions_allowed() {
490 return Err(ExecutionError::IllegalInstruction {
491 address: program_counter.old_pc(zvexx_helpers::INSTRUCTION_SIZE),
492 });
493 }
494 let vtype = ext_state
495 .vtype()
496 .ok_or(ExecutionError::IllegalInstruction {
497 address: program_counter.old_pc(zvexx_helpers::INSTRUCTION_SIZE),
498 })?;
499 let group_regs = vtype.vlmul().register_count();
500 zvexx_carry_helpers::check_vreg_group_alignment::<Reg, _, _, _>(
501 program_counter,
502 vd,
503 group_regs,
504 )?;
505 zvexx_carry_helpers::check_vreg_group_alignment::<Reg, _, _, _>(
506 program_counter,
507 vs2,
508 group_regs,
509 )?;
510 if vd == VReg::V0 {
511 return Err(ExecutionError::IllegalInstruction {
512 address: program_counter.old_pc(zvexx_helpers::INSTRUCTION_SIZE),
513 });
514 }
515 let sew = vtype.vsew();
516 let scalar = rs1_value.as_i64().cast_unsigned();
517 unsafe {
519 zvexx_carry_helpers::execute_carry_sub::<Reg, _, _>(
520 ext_state,
521 vd,
522 vs2,
523 zvexx_carry_helpers::OpSrc::Scalar(scalar),
524 sew,
525 );
526 }
527 }
528
529 Self::VmsbcVvm { vd, vs2, vs1 } => {
531 if !ext_state.vector_instructions_allowed() {
532 return Err(ExecutionError::IllegalInstruction {
533 address: program_counter.old_pc(zvexx_helpers::INSTRUCTION_SIZE),
534 });
535 }
536 let vtype = ext_state
537 .vtype()
538 .ok_or(ExecutionError::IllegalInstruction {
539 address: program_counter.old_pc(zvexx_helpers::INSTRUCTION_SIZE),
540 })?;
541 let group_regs = vtype.vlmul().register_count();
542 zvexx_carry_helpers::check_vreg_group_alignment::<Reg, _, _, _>(
543 program_counter,
544 vs2,
545 group_regs,
546 )?;
547 zvexx_carry_helpers::check_vreg_group_alignment::<Reg, _, _, _>(
548 program_counter,
549 vs1,
550 group_regs,
551 )?;
552 zvexx_carry_helpers::check_mask_dest_no_overlap::<Reg, _, _, _>(
553 program_counter,
554 vd,
555 vs2,
556 group_regs,
557 )?;
558 zvexx_carry_helpers::check_mask_dest_no_overlap::<Reg, _, _, _>(
559 program_counter,
560 vd,
561 vs1,
562 group_regs,
563 )?;
564 let sew = vtype.vsew();
565 unsafe {
567 zvexx_carry_helpers::execute_carry_sub_mask::<Reg, _, _>(
568 ext_state,
569 vd,
570 vs2,
571 zvexx_carry_helpers::OpSrc::Vreg(vs1),
572 true,
573 sew,
574 );
575 }
576 }
577
578 Self::VmsbcVxm { vd, vs2, rs1: _ } => {
579 if !ext_state.vector_instructions_allowed() {
580 return Err(ExecutionError::IllegalInstruction {
581 address: program_counter.old_pc(zvexx_helpers::INSTRUCTION_SIZE),
582 });
583 }
584 let vtype = ext_state
585 .vtype()
586 .ok_or(ExecutionError::IllegalInstruction {
587 address: program_counter.old_pc(zvexx_helpers::INSTRUCTION_SIZE),
588 })?;
589 let group_regs = vtype.vlmul().register_count();
590 zvexx_carry_helpers::check_vreg_group_alignment::<Reg, _, _, _>(
591 program_counter,
592 vs2,
593 group_regs,
594 )?;
595 zvexx_carry_helpers::check_mask_dest_no_overlap::<Reg, _, _, _>(
596 program_counter,
597 vd,
598 vs2,
599 group_regs,
600 )?;
601 let sew = vtype.vsew();
602 let scalar = rs1_value.as_i64().cast_unsigned();
603 unsafe {
605 zvexx_carry_helpers::execute_carry_sub_mask::<Reg, _, _>(
606 ext_state,
607 vd,
608 vs2,
609 zvexx_carry_helpers::OpSrc::Scalar(scalar),
610 true,
611 sew,
612 );
613 }
614 }
615
616 Self::VmsbcVv { vd, vs2, vs1 } => {
617 if !ext_state.vector_instructions_allowed() {
618 return Err(ExecutionError::IllegalInstruction {
619 address: program_counter.old_pc(zvexx_helpers::INSTRUCTION_SIZE),
620 });
621 }
622 let vtype = ext_state
623 .vtype()
624 .ok_or(ExecutionError::IllegalInstruction {
625 address: program_counter.old_pc(zvexx_helpers::INSTRUCTION_SIZE),
626 })?;
627 let group_regs = vtype.vlmul().register_count();
628 zvexx_carry_helpers::check_vreg_group_alignment::<Reg, _, _, _>(
629 program_counter,
630 vs2,
631 group_regs,
632 )?;
633 zvexx_carry_helpers::check_vreg_group_alignment::<Reg, _, _, _>(
634 program_counter,
635 vs1,
636 group_regs,
637 )?;
638 zvexx_carry_helpers::check_mask_dest_no_overlap::<Reg, _, _, _>(
639 program_counter,
640 vd,
641 vs2,
642 group_regs,
643 )?;
644 zvexx_carry_helpers::check_mask_dest_no_overlap::<Reg, _, _, _>(
645 program_counter,
646 vd,
647 vs1,
648 group_regs,
649 )?;
650 let sew = vtype.vsew();
651 unsafe {
653 zvexx_carry_helpers::execute_carry_sub_mask::<Reg, _, _>(
654 ext_state,
655 vd,
656 vs2,
657 zvexx_carry_helpers::OpSrc::Vreg(vs1),
658 false,
659 sew,
660 );
661 }
662 }
663
664 Self::VmsbcVx { vd, vs2, rs1: _ } => {
665 if !ext_state.vector_instructions_allowed() {
666 return Err(ExecutionError::IllegalInstruction {
667 address: program_counter.old_pc(zvexx_helpers::INSTRUCTION_SIZE),
668 });
669 }
670 let vtype = ext_state
671 .vtype()
672 .ok_or(ExecutionError::IllegalInstruction {
673 address: program_counter.old_pc(zvexx_helpers::INSTRUCTION_SIZE),
674 })?;
675 let group_regs = vtype.vlmul().register_count();
676 zvexx_carry_helpers::check_vreg_group_alignment::<Reg, _, _, _>(
677 program_counter,
678 vs2,
679 group_regs,
680 )?;
681 zvexx_carry_helpers::check_mask_dest_no_overlap::<Reg, _, _, _>(
682 program_counter,
683 vd,
684 vs2,
685 group_regs,
686 )?;
687 let sew = vtype.vsew();
688 let scalar = rs1_value.as_i64().cast_unsigned();
689 unsafe {
691 zvexx_carry_helpers::execute_carry_sub_mask::<Reg, _, _>(
692 ext_state,
693 vd,
694 vs2,
695 zvexx_carry_helpers::OpSrc::Scalar(scalar),
696 false,
697 sew,
698 );
699 }
700 }
701 }
702
703 Ok(ControlFlow::Continue(Default::default()))
704 }
705}