1#[cfg(test)]
4mod tests;
5pub mod zvexx;
6
7use crate::hart::{HartConfig, VectorHartConfig};
8use crate::instructions::{ImplementedExtension, Instruction, IsaExtension};
9use crate::registers::general_purpose::{RegType, Register};
10use core::hint::{assert_unchecked, cold_path};
11use core::marker::{ConstParamTy, PhantomData};
12use core::ops::RangeInclusive;
13use core::{cmp, fmt};
14
15const HART_VLEN<Hart: VectorHartConfig>: Vlen = Hart::VECTOR_LENGTHS.vlen;
17
18#[derive(Debug, Clone, Copy)]
20#[derive_const(Default, PartialEq, Eq, Ord, PartialOrd)]
21pub struct Vstart(u16);
22
23impl fmt::Display for Vstart {
24 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
25 write!(f, "{}", self.0)
26 }
27}
28
29const impl From<u16> for Vstart {
30 #[inline(always)]
31 fn from(value: u16) -> Self {
32 Self(value)
33 }
34}
35
36const impl From<Vstart> for u16 {
37 #[inline(always)]
38 fn from(value: Vstart) -> Self {
39 value.0
40 }
41}
42
43impl PartialEq<Vl> for Vstart {
44 fn eq(&self, other: &Vl) -> bool {
45 u32::from(self.0) == u32::from(*other)
46 }
47}
48
49impl PartialOrd<Vl> for Vstart {
50 #[inline(always)]
51 fn partial_cmp(&self, other: &Vl) -> Option<cmp::Ordering> {
52 Some(u32::from(self.0).cmp(&u32::from(*other)))
53 }
54}
55
56impl Vstart {
57 pub const ZERO: Self = Self(0);
59
60 #[inline(always)]
64 pub const fn range_to(self, vl: Vl) -> RangeInclusive<u16> {
65 let vl = u32::from(vl);
66 if vl == 0 {
67 #[expect(clippy::reversed_empty_ranges, reason = "Intentional empty range")]
69 {
70 1..=0
71 }
72 } else {
73 self.0..=(vl - 1) as u16
74 }
75 }
76}
77
78#[derive(Debug, Clone, Copy)]
80#[derive_const(Default, PartialEq, Eq, Ord, PartialOrd)]
81pub struct Vl(u32);
82
83impl fmt::Display for Vl {
84 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
85 write!(f, "{}", self.0)
86 }
87}
88
89const impl From<u8> for Vl {
90 #[inline(always)]
91 fn from(value: u8) -> Self {
92 Self(u32::from(value))
93 }
94}
95
96const impl From<u16> for Vl {
97 #[inline(always)]
98 fn from(value: u16) -> Self {
99 Self(u32::from(value))
100 }
101}
102
103const impl From<Vl> for u32 {
104 #[inline(always)]
105 fn from(value: Vl) -> Self {
106 value.0
107 }
108}
109
110const impl From<Vl> for u64 {
111 #[inline(always)]
112 fn from(value: Vl) -> Self {
113 u64::from(value.0)
114 }
115}
116
117impl PartialEq<Vstart> for Vl {
118 fn eq(&self, other: &Vstart) -> bool {
119 self.0 == u32::from(u16::from(*other))
120 }
121}
122
123impl PartialOrd<Vstart> for Vl {
124 #[inline(always)]
125 fn partial_cmp(&self, other: &Vstart) -> Option<cmp::Ordering> {
126 Some(self.0.cmp(&u32::from(u16::from(*other))))
127 }
128}
129
130impl Vl {
131 pub const ZERO: Self = Self(0);
133
134 #[inline(always)]
138 pub const fn new(n: u32) -> Option<Self> {
139 if n > u32::from(Vlen::L65_536) {
140 None
141 } else {
142 Some(Self(n))
143 }
144 }
145
146 #[inline(always)]
148 pub const fn new_saturating(n: u32) -> Self {
149 let n = u32::from(Vlen::L65_536).min(n);
150 Self(n)
151 }
152
153 #[inline(always)]
155 pub const fn bytes(self) -> u16 {
156 self.0.div_ceil(u8::BITS) as u16
157 }
158}
159
160#[derive(ConstParamTy, Debug, Clone, Copy)]
162#[derive_const(PartialEq, Eq, PartialOrd, Ord)]
163#[repr(u32)]
164pub enum Elen {
165 L8 = 8,
167 L16 = 16,
169 L32 = 32,
171 L64 = 64,
173 L128 = 128,
175 L256 = 256,
177 L512 = 512,
179 L1024 = 1024,
181 L2048 = 2048,
183 L4096 = 4096,
185 L8192 = 8192,
187 L16_384 = 16_384,
189 L32_768 = 32_768,
191 L65_536 = 65_536,
193}
194
195const impl From<Elen> for u32 {
196 #[inline(always)]
197 fn from(value: Elen) -> Self {
198 value as u32
199 }
200}
201
202impl Elen {
203 #[inline(always)]
205 pub const fn supports(self, eew: Eew) -> bool {
206 u32::from(eew.bits_width()) <= u32::from(self)
207 }
208}
209
210#[derive(ConstParamTy, Debug, Clone, Copy)]
212#[derive_const(PartialEq, Eq, PartialOrd, Ord)]
213#[repr(u32)]
214pub enum Vlen {
215 L8 = 8,
217 L16 = 16,
219 L32 = 32,
221 L64 = 64,
223 L128 = 128,
225 L256 = 256,
227 L512 = 512,
229 L1024 = 1024,
231 L2048 = 2048,
233 L4096 = 4096,
235 L8192 = 8192,
237 L16_384 = 16_384,
239 L32_768 = 32_768,
241 L65_536 = 65_536,
243}
244
245const impl From<Vlen> for u32 {
246 #[inline(always)]
247 fn from(value: Vlen) -> Self {
248 value as u32
249 }
250}
251
252impl Vlen {
253 #[inline(always)]
255 pub const fn bytes(self) -> u32 {
256 self as u32 / u8::BITS
257 }
258}
259
260#[derive(Debug, Clone, Copy)]
265#[derive_const(PartialEq, Eq)]
266#[repr(u8)]
267pub enum VsStatus {
268 Off = 0,
270 Initial = 1,
272 Clean = 2,
274 Dirty = 3,
276}
277
278impl VsStatus {
279 #[inline(always)]
281 pub const fn from_bits(bits: u8) -> Self {
282 match bits & 0b11 {
283 0 => Self::Off,
284 1 => Self::Initial,
285 2 => Self::Clean,
286 _ => Self::Dirty,
287 }
288 }
289
290 #[inline(always)]
292 pub const fn to_bits(self) -> u8 {
293 self as u8
294 }
295}
296
297#[derive(Debug, Clone, Copy)]
303#[derive_const(PartialEq, Eq)]
304#[repr(u8)]
305pub enum Vlmul {
306 M1 = 0b000,
308 M2 = 0b001,
310 M4 = 0b010,
312 M8 = 0b011,
314 Mf8 = 0b101,
316 Mf4 = 0b110,
318 Mf2 = 0b111,
320}
321
322impl Vlmul {
323 #[inline(always)]
325 pub const fn from_bits(bits: u8) -> Option<Self> {
326 match bits & 0b111 {
327 0b000 => Some(Self::M1),
328 0b001 => Some(Self::M2),
329 0b010 => Some(Self::M4),
330 0b011 => Some(Self::M8),
331 0b101 => Some(Self::Mf8),
332 0b110 => Some(Self::Mf4),
333 0b111 => Some(Self::Mf2),
334 _ => None,
335 }
336 }
337
338 #[inline(always)]
340 pub const fn to_bits(self) -> u8 {
341 self as u8
342 }
343
344 #[inline(always)]
349 #[cfg_attr(feature = "no-panic", no_panic_const::no_panic)]
350 pub const fn vlmax<const VLEN: Vlen>(self, sew: Vsew) -> Vl {
351 let sew_bits = u32::from(sew.bits_width());
352 let vl = match self {
353 Self::M1 => u32::from(VLEN) / sew_bits,
354 Self::M2 => (u32::from(VLEN) * 2) / sew_bits,
355 Self::M4 => (u32::from(VLEN) * 4) / sew_bits,
356 Self::M8 => (u32::from(VLEN) * 8) / sew_bits,
357 Self::Mf2 => u32::from(VLEN) / (sew_bits * 2),
358 Self::Mf4 => u32::from(VLEN) / (sew_bits * 4),
359 Self::Mf8 => u32::from(VLEN) / (sew_bits * 8),
360 };
361 Vl::new(vl).expect(
362 "At most `8 * VLEN / 8` (`LMUL = 8`, `SEW = 8`), which never exceeds the maximum \
363 vector length; qed",
364 )
365 }
366
367 #[inline(always)]
372 #[cfg_attr(feature = "no-panic", no_panic_const::no_panic)]
373 pub const fn register_count(self) -> VRegGroupSize {
374 match self {
375 Self::Mf8 | Self::Mf4 | Self::Mf2 | Self::M1 => VRegGroupSize::R1,
376 Self::M2 => VRegGroupSize::R2,
377 Self::M4 => VRegGroupSize::R4,
378 Self::M8 => VRegGroupSize::R8,
379 }
380 }
381
382 #[inline(always)]
384 pub const fn is_fractional(self) -> bool {
385 matches!(self, Self::Mf8 | Self::Mf4 | Self::Mf2)
386 }
387
388 #[inline(always)]
390 pub const fn double(self) -> Option<Self> {
391 match self {
392 Self::Mf8 => Some(Self::Mf4),
393 Self::Mf4 => Some(Self::Mf2),
394 Self::Mf2 => Some(Self::M1),
395 Self::M1 => Some(Self::M2),
396 Self::M2 => Some(Self::M4),
397 Self::M4 => Some(Self::M8),
398 Self::M8 => {
399 cold_path();
400 None
401 }
402 }
403 }
404
405 #[inline(always)]
407 const fn eighths(self) -> u32 {
408 let eighths: u32 = match self {
409 Self::Mf8 => 1,
410 Self::Mf4 => 2,
411 Self::Mf2 => 4,
412 Self::M1 => 8,
413 Self::M2 => 16,
414 Self::M4 => 32,
415 Self::M8 => 64,
416 };
417 unsafe {
421 assert_unchecked(eighths.is_power_of_two());
422 }
423 eighths
424 }
425
426 #[inline(always)]
428 const fn from_eighths(eighths: u32) -> Option<Self> {
429 match eighths {
430 1 => Some(Self::Mf8),
431 2 => Some(Self::Mf4),
432 4 => Some(Self::Mf2),
433 8 => Some(Self::M1),
434 16 => Some(Self::M2),
435 32 => Some(Self::M4),
436 64 => Some(Self::M8),
437 _ => {
438 cold_path();
439 None
440 }
441 }
442 }
443
444 #[inline(always)]
449 #[cfg_attr(feature = "no-panic", no_panic_const::no_panic)]
450 pub const fn emul(self, eew: Eew, sew: Vsew) -> Option<Self> {
451 let eighths = self.eighths() * u32::from(eew.bits_width()) / u32::from(sew.bits_width());
452 Self::from_eighths(eighths)
453 }
454
455 #[inline(always)]
460 #[cfg_attr(feature = "no-panic", no_panic_const::no_panic)]
461 pub const fn widening_register_count(self) -> Option<VRegGroupSize> {
462 Some(self.double()?.register_count())
463 }
464
465 #[inline(always)]
470 #[cfg_attr(feature = "no-panic", no_panic_const::no_panic)]
471 pub const fn index_register_count(self, index_eew: Eew, sew: Vsew) -> Option<VRegGroupSize> {
472 Some(self.emul(index_eew, sew)?.register_count())
473 }
474
475 #[inline(always)]
485 #[cfg_attr(feature = "no-panic", no_panic_const::no_panic)]
486 pub const fn data_register_count(self, eew: Eew, sew: Vsew) -> Option<VRegGroupSize> {
487 self.index_register_count(eew, sew)
488 }
489}
490
491impl fmt::Display for Vlmul {
492 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
493 match self {
494 Self::M1 => write!(f, "m1"),
495 Self::M2 => write!(f, "m2"),
496 Self::M4 => write!(f, "m4"),
497 Self::M8 => write!(f, "m8"),
498 Self::Mf8 => write!(f, "mf8"),
499 Self::Mf4 => write!(f, "mf4"),
500 Self::Mf2 => write!(f, "mf2"),
501 }
502 }
503}
504
505#[derive(Debug, Clone, Copy)]
510#[derive_const(PartialEq, Eq)]
511#[repr(u8)]
512pub enum VRegGroupSize {
513 R1 = 1,
515 R2 = 2,
517 R4 = 4,
519 R8 = 8,
521}
522
523impl VRegGroupSize {
524 #[inline(always)]
526 pub const fn get(self) -> u8 {
527 let count = self as u8;
528 unsafe {
532 assert_unchecked(count.is_power_of_two());
533 }
534 count
535 }
536
537 #[inline(always)]
541 pub const fn divide_by_factor(self, factor: VsewFactor) -> Self {
542 match self.get() / factor.factor() {
543 2 => Self::R2,
544 4 => Self::R4,
545 _ => Self::R1,
546 }
547 }
548}
549
550impl fmt::Display for VRegGroupSize {
551 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
552 write!(f, "{}", self.get())
553 }
554}
555
556#[derive(Debug, Clone, Copy)]
558#[derive_const(PartialEq, Eq)]
559#[repr(u8)]
560pub enum VsewFactor {
561 F2 = 2,
563 F4 = 4,
565 F8 = 8,
567}
568
569impl VsewFactor {
570 #[inline(always)]
572 pub const fn factor(self) -> u8 {
573 let factor = self as u8;
574 unsafe {
578 assert_unchecked(factor.is_power_of_two());
579 }
580 factor
581 }
582}
583
584#[derive(ConstParamTy, Debug, Clone, Copy)]
588#[derive_const(PartialEq, Eq)]
589#[repr(u8)]
590pub enum Vsew {
591 E8 = 8,
593 E16 = 16,
595 E32 = 32,
597 E64 = 64,
599}
600
601impl Vsew {
602 #[inline(always)]
604 pub const fn from_bits(bits: u8) -> Option<Self> {
605 match bits & 0b111 {
606 0b000 => Some(Self::E8),
607 0b001 => Some(Self::E16),
608 0b010 => Some(Self::E32),
609 0b011 => Some(Self::E64),
610 _ => {
611 cold_path();
612 None
613 }
614 }
615 }
616
617 #[inline(always)]
619 #[cfg_attr(feature = "no-panic", no_panic_const::no_panic)]
620 pub const fn from_xlen<Reg>() -> Self
621 where
622 Reg: [const] Register,
623 {
624 const {
625 match Reg::XLEN {
626 32 => Self::E32,
627 64 => Self::E64,
628 _ => {
629 panic!("Invalid register width")
632 }
633 }
634 }
635 }
636
637 #[inline(always)]
639 pub const fn to_bits(self) -> u8 {
640 match self {
641 Vsew::E8 => 0b000,
642 Vsew::E16 => 0b001,
643 Vsew::E32 => 0b010,
644 Vsew::E64 => 0b011,
645 }
646 }
647
648 #[inline(always)]
650 pub const fn double_width(self) -> Option<Self> {
651 match self {
652 Self::E8 => Some(Self::E16),
653 Self::E16 => Some(Self::E32),
654 Self::E32 => Some(Self::E64),
655 Self::E64 => {
656 cold_path();
657 None
658 }
659 }
660 }
661
662 #[inline(always)]
664 #[cfg_attr(feature = "no-panic", no_panic_const::no_panic)]
665 pub const fn divide_by_factor(self, factor: VsewFactor) -> Option<Self> {
666 let Some(divide_by_factor) = self.bits_width().div_exact(factor.factor()) else {
667 cold_path();
668 return None;
669 };
670 match divide_by_factor {
671 8 => Some(Self::E8),
672 16 => Some(Self::E16),
673 32 => Some(Self::E32),
674 _ => {
675 cold_path();
676 None
677 }
678 }
679 }
680
681 #[inline(always)]
683 pub const fn bits_width(self) -> u8 {
684 let bits: u8 = match self {
685 Self::E8 => 8,
686 Self::E16 => 16,
687 Self::E32 => 32,
688 Self::E64 => 64,
689 };
690 unsafe {
694 assert_unchecked(bits.is_power_of_two());
695 }
696 bits
697 }
698
699 #[inline(always)]
701 pub const fn bytes_width(self) -> u8 {
702 let bytes: u8 = match self {
703 Self::E8 => 1,
704 Self::E16 => 2,
705 Self::E32 => 4,
706 Self::E64 => 8,
707 };
708 unsafe {
712 assert_unchecked(bytes.is_power_of_two());
713 }
714 bytes
715 }
716
717 #[inline(always)]
723 pub const fn as_eew(self) -> Eew {
724 match self {
725 Self::E8 => Eew::E8,
726 Self::E16 => Eew::E16,
727 Self::E32 => Eew::E32,
728 Self::E64 => Eew::E64,
729 }
730 }
731}
732
733impl fmt::Display for Vsew {
734 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
735 match self {
736 Self::E8 => write!(f, "e8"),
737 Self::E16 => write!(f, "e16"),
738 Self::E32 => write!(f, "e32"),
739 Self::E64 => write!(f, "e64"),
740 }
741 }
742}
743
744#[derive(ConstParamTy, Debug, Clone, Copy)]
748#[derive_const(PartialEq, Eq)]
749#[repr(u8)]
750pub enum Eew {
751 E8 = 1,
753 E16 = 2,
755 E32 = 4,
757 E64 = 8,
759}
760
761impl Eew {
762 pub const MAX_BYTES: u8 = Self::E64.bytes_width();
764
765 #[inline(always)]
767 pub const fn from_width(width: u8) -> Option<Self> {
768 match width {
769 0b000 => Some(Self::E8),
770 0b101 => Some(Self::E16),
771 0b110 => Some(Self::E32),
772 0b111 => Some(Self::E64),
773 _ => {
774 cold_path();
775 None
776 }
777 }
778 }
779
780 #[inline(always)]
782 pub const fn to_bits(self) -> u8 {
783 match self {
784 Eew::E8 => 0b000,
785 Eew::E16 => 0b101,
786 Eew::E32 => 0b110,
787 Eew::E64 => 0b111,
788 }
789 }
790
791 #[inline(always)]
793 pub const fn bits_width(self) -> u8 {
794 let bits: u8 = match self {
795 Self::E8 => 8,
796 Self::E16 => 16,
797 Self::E32 => 32,
798 Self::E64 => 64,
799 };
800 unsafe {
804 assert_unchecked(bits.is_power_of_two());
805 }
806 bits
807 }
808
809 #[inline(always)]
813 pub const fn bytes_width(self) -> u8 {
814 let bytes: u8 = match self {
815 Self::E8 => 1,
816 Self::E16 => 2,
817 Self::E32 => 4,
818 Self::E64 => 8,
819 };
820 unsafe {
824 assert_unchecked(bytes.is_power_of_two());
825 }
826 bytes
827 }
828}
829
830const impl From<Vsew> for Eew {
831 #[inline(always)]
832 fn from(sew: Vsew) -> Self {
833 sew.as_eew()
834 }
835}
836
837impl fmt::Display for Eew {
838 #[inline]
839 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
840 fmt::Display::fmt(&self.bits_width(), f)
841 }
842}
843
844#[derive(Debug, Clone, Copy)]
848#[derive_const(Default, PartialEq, Eq)]
849#[repr(u8)]
850pub enum Vxrm {
851 #[default]
853 Rnu = 0b00,
854 Rne = 0b01,
856 Rdn = 0b10,
858 Rod = 0b11,
860}
861
862impl Vxrm {
863 #[inline(always)]
865 pub const fn from_bits(bits: u8) -> Self {
866 match bits & 0b11 {
867 0b00 => Self::Rnu,
868 0b01 => Self::Rne,
869 0b10 => Self::Rdn,
870 _ => Self::Rod,
871 }
872 }
873
874 #[inline(always)]
876 pub const fn to_bits(self) -> u8 {
877 self as u8
878 }
879}
880
881#[derive(Debug, Clone, Copy)]
889pub struct Vtype<Hart>
890where
891 Hart: VectorHartConfig,
892{
893 vma: bool,
895 vta: bool,
897 vsew: Vsew,
899 vlmul: Vlmul,
901 hart: PhantomData<Hart>,
902}
903
904const impl<Hart> PartialEq for Vtype<Hart>
905where
906 Hart: VectorHartConfig,
907{
908 #[inline(always)]
909 fn eq(&self, other: &Self) -> bool {
910 self.vma == other.vma
911 && self.vta == other.vta
912 && self.vsew == other.vsew
913 && self.vlmul == other.vlmul
914 }
915}
916
917const impl<Hart> Eq for Vtype<Hart> where Hart: VectorHartConfig {}
918
919impl<Hart> Vtype<Hart>
920where
921 Hart: VectorHartConfig,
922{
923 pub const fn vma(&self) -> bool {
925 self.vma
926 }
927
928 pub const fn vta(&self) -> bool {
930 self.vta
931 }
932
933 pub const fn vsew(&self) -> Vsew {
935 self.vsew
936 }
937
938 pub const fn vlmul(&self) -> Vlmul {
940 self.vlmul
941 }
942
943 #[inline(always)]
949 #[cfg_attr(feature = "no-panic", no_panic_const::no_panic)]
950 pub const fn eew_register_count(&self, eew: Eew) -> Option<VRegGroupSize> {
951 if !Hart::VECTOR_LENGTHS.elen.supports(eew) {
952 cold_path();
953 return None;
954 }
955 self.vlmul.index_register_count(eew, self.vsew)
956 }
957
958 #[inline(always)]
960 #[cfg_attr(feature = "no-panic", no_panic_const::no_panic)]
961 pub const fn vlmax(&self) -> Vl {
962 self.vlmul.vlmax::<{ HART_VLEN::<Hart> }>(self.vsew)
963 }
964
965 #[inline(always)]
973 #[cfg_attr(feature = "no-panic", no_panic_const::no_panic)]
974 pub const fn from_raw<Reg>(raw: Reg::Type) -> Option<Self>
975 where
976 Reg: [const] Register,
977 {
978 let raw = raw.as_u64();
979
980 if (raw >> 8u8) != 0 {
982 cold_path();
983 return None;
984 }
985
986 let vlmul_bits = (raw & 0b111) as u8;
987 let vsew_bits = ((raw >> 3u8) & 0b111) as u8;
988 let vta = ((raw >> 6u8) & 1) != 0;
989 let vma = ((raw >> 7u8) & 1) != 0;
990
991 let Some(vlmul) = Vlmul::from_bits(vlmul_bits) else {
992 cold_path();
993 return None;
994 };
995 let Some(vsew) = Vsew::from_bits(vsew_bits) else {
996 cold_path();
997 return None;
998 };
999
1000 let elen = Hart::VECTOR_LENGTHS.elen;
1001 let sew = vsew.bits_width();
1002 if u32::from(sew) > u32::from(elen) {
1003 cold_path();
1004 return None;
1005 }
1006
1007 if u32::from(sew) * 8 > u32::from(elen) * vlmul.eighths() {
1011 cold_path();
1012 return None;
1013 }
1014
1015 Some(Self {
1016 vma,
1017 vta,
1018 vsew,
1019 vlmul,
1020 hart: PhantomData,
1021 })
1022 }
1023
1024 #[inline(always)]
1030 #[cfg_attr(feature = "no-panic", no_panic_const::no_panic)]
1031 pub const fn to_raw<Reg>(self) -> Reg::Type
1032 where
1033 Reg: [const] Register,
1034 {
1035 let mut raw = 0u8;
1036 raw |= self.vlmul.to_bits();
1037 raw |= self.vsew.to_bits() << 3u8;
1038
1039 if self.vta {
1040 raw |= 1 << 6u8;
1041 }
1042
1043 if self.vma {
1044 raw |= 1 << 7u8;
1045 }
1046
1047 Reg::Type::from(raw)
1048 }
1049
1050 #[inline(always)]
1056 #[cfg_attr(feature = "no-panic", no_panic_const::no_panic)]
1057 pub const fn illegal_raw<Reg>() -> Reg::Type
1058 where
1059 Reg: [const] Register,
1060 {
1061 let vill_bit = Reg::XLEN - 1;
1062 Reg::Type::from(1u8) << vill_bit
1063 }
1064}
1065
1066#[derive(Debug, Clone, Copy)]
1068#[derive_const(PartialEq, Eq)]
1069#[doc(hidden)]
1070pub enum V<Hart>
1071where
1072 Hart: HartConfig,
1073{
1074 V(Hart::Reg, !),
1075}
1076
1077const impl<Reg, Hart> Instruction for V<Hart>
1078where
1079 Reg: [const] Register,
1080 Hart: [const] VectorHartConfig<Reg = Reg>,
1081{
1082 const IMPLEMENTED_EXTENSIONS: &'static [ImplementedExtension] = &[];
1083
1084 const OWN_ISA_EXTENSIONS: &'static [IsaExtension] = &[];
1085
1086 const ALIGNMENT: u8 = align_of::<u32>() as u8;
1087
1088 type Hart = Hart;
1089
1090 #[inline(always)]
1091 fn try_decode(_instruction: u32) -> Option<Self> {
1092 None
1093 }
1094
1095 #[inline(always)]
1096 fn size(&self) -> u8 {
1097 size_of::<u32>() as u8
1098 }
1099}
1100
1101impl<Reg, Hart> fmt::Display for V<Hart>
1102where
1103 Reg: fmt::Display,
1104 Hart: HartConfig<Reg = Reg>,
1105{
1106 fn fmt(&self, _f: &mut fmt::Formatter<'_>) -> fmt::Result {
1107 match self {
1108 V::V(_, _) => {
1109 unreachable!("Impossible to construct V instruction")
1110 }
1111 }
1112 }
1113}