1 use crate::Reg;
2 use crate::isa::riscv64::lower::isle::generated_code::VecAluOpRRRR;
3 use crate::isa::riscv64::lower::isle::generated_code::{
4     VecAMode, VecAluOpRImm5, VecAluOpRR, VecAluOpRRImm5, VecAluOpRRR, VecAluOpRRRImm5, VecAvl,
5     VecElementWidth, VecLmul, VecMaskMode, VecOpCategory, VecOpMasking, VecTailMode,
6 };
7 use crate::machinst::{OperandVisitor, RegClass};
8 use core::fmt;
9 
10 use super::{Type, UImm5};
11 
12 impl VecAvl {
13     pub fn _static(size: u32) -> Self {
14         VecAvl::Static {
15             size: UImm5::maybe_from_u8(size as u8).expect("Invalid size for AVL"),
16         }
17     }
18 
19     pub fn is_static(&self) -> bool {
20         match self {
21             VecAvl::Static { .. } => true,
22         }
23     }
24 
25     pub fn unwrap_static(&self) -> UImm5 {
26         match self {
27             VecAvl::Static { size } => *size,
28         }
29     }
30 }
31 
32 // TODO: Can we tell ISLE to derive this?
33 impl Copy for VecAvl {}
34 
35 // TODO: Can we tell ISLE to derive this?
36 impl PartialEq for VecAvl {
37     fn eq(&self, other: &Self) -> bool {
38         match (self, other) {
39             (VecAvl::Static { size: lhs }, VecAvl::Static { size: rhs }) => lhs == rhs,
40         }
41     }
42 }
43 
44 impl fmt::Display for VecAvl {
45     fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
46         match self {
47             VecAvl::Static { size } => write!(f, "{size}"),
48         }
49     }
50 }
51 
52 impl VecElementWidth {
53     pub fn from_type(ty: Type) -> Self {
54         Self::from_bits(ty.lane_bits())
55     }
56 
57     pub fn from_bits(bits: u32) -> Self {
58         match bits {
59             8 => VecElementWidth::E8,
60             16 => VecElementWidth::E16,
61             32 => VecElementWidth::E32,
62             64 => VecElementWidth::E64,
63             _ => panic!("Invalid number of bits for VecElementWidth: {bits}"),
64         }
65     }
66 
67     pub fn bits(&self) -> u32 {
68         match self {
69             VecElementWidth::E8 => 8,
70             VecElementWidth::E16 => 16,
71             VecElementWidth::E32 => 32,
72             VecElementWidth::E64 => 64,
73         }
74     }
75 
76     pub fn encode(&self) -> u32 {
77         match self {
78             VecElementWidth::E8 => 0b000,
79             VecElementWidth::E16 => 0b001,
80             VecElementWidth::E32 => 0b010,
81             VecElementWidth::E64 => 0b011,
82         }
83     }
84 }
85 
86 impl fmt::Display for VecElementWidth {
87     fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
88         write!(f, "e{}", self.bits())
89     }
90 }
91 
92 impl VecLmul {
93     pub fn encode(&self) -> u32 {
94         match self {
95             VecLmul::LmulF8 => 0b101,
96             VecLmul::LmulF4 => 0b110,
97             VecLmul::LmulF2 => 0b111,
98             VecLmul::Lmul1 => 0b000,
99             VecLmul::Lmul2 => 0b001,
100             VecLmul::Lmul4 => 0b010,
101             VecLmul::Lmul8 => 0b011,
102         }
103     }
104 }
105 
106 impl fmt::Display for VecLmul {
107     fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
108         match self {
109             VecLmul::LmulF8 => write!(f, "mf8"),
110             VecLmul::LmulF4 => write!(f, "mf4"),
111             VecLmul::LmulF2 => write!(f, "mf2"),
112             VecLmul::Lmul1 => write!(f, "m1"),
113             VecLmul::Lmul2 => write!(f, "m2"),
114             VecLmul::Lmul4 => write!(f, "m4"),
115             VecLmul::Lmul8 => write!(f, "m8"),
116         }
117     }
118 }
119 
120 impl VecTailMode {
121     pub fn encode(&self) -> u32 {
122         match self {
123             VecTailMode::Agnostic => 1,
124             VecTailMode::Undisturbed => 0,
125         }
126     }
127 }
128 
129 impl fmt::Display for VecTailMode {
130     fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
131         match self {
132             VecTailMode::Agnostic => write!(f, "ta"),
133             VecTailMode::Undisturbed => write!(f, "tu"),
134         }
135     }
136 }
137 
138 impl VecMaskMode {
139     pub fn encode(&self) -> u32 {
140         match self {
141             VecMaskMode::Agnostic => 1,
142             VecMaskMode::Undisturbed => 0,
143         }
144     }
145 }
146 
147 impl fmt::Display for VecMaskMode {
148     fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
149         match self {
150             VecMaskMode::Agnostic => write!(f, "ma"),
151             VecMaskMode::Undisturbed => write!(f, "mu"),
152         }
153     }
154 }
155 
156 /// Vector Type (VType)
157 ///
158 /// vtype provides the default type used to interpret the contents of the vector register file.
159 #[derive(Clone, Copy, Debug, PartialEq)]
160 pub struct VType {
161     pub sew: VecElementWidth,
162     pub lmul: VecLmul,
163     pub tail_mode: VecTailMode,
164     pub mask_mode: VecMaskMode,
165 }
166 
167 impl VType {
168     // https://github.com/riscv/riscv-v-spec/blob/master/vtype-format.adoc
169     pub fn encode(&self) -> u32 {
170         let mut bits = 0;
171         bits |= self.lmul.encode();
172         bits |= self.sew.encode() << 3;
173         bits |= self.tail_mode.encode() << 6;
174         bits |= self.mask_mode.encode() << 7;
175         bits
176     }
177 }
178 
179 impl fmt::Display for VType {
180     fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
181         write!(
182             f,
183             "{}, {}, {}, {}",
184             self.sew, self.lmul, self.tail_mode, self.mask_mode
185         )
186     }
187 }
188 
189 /// Vector State (VState)
190 ///
191 /// VState represents the state of the vector unit that each instruction expects before execution.
192 /// Unlike VType or any of the other types here, VState is not a part of the RISC-V ISA. It is
193 /// used by our instruction emission code to ensure that the vector unit is in the correct state.
194 #[derive(Clone, Copy, Debug, PartialEq)]
195 pub struct VState {
196     pub avl: VecAvl,
197     pub vtype: VType,
198 }
199 
200 impl VState {
201     pub fn from_type(ty: Type) -> Self {
202         VState {
203             avl: VecAvl::_static(ty.lane_count()),
204             vtype: VType {
205                 sew: VecElementWidth::from_type(ty),
206                 lmul: VecLmul::Lmul1,
207                 tail_mode: VecTailMode::Agnostic,
208                 mask_mode: VecMaskMode::Agnostic,
209             },
210         }
211     }
212 }
213 
214 impl fmt::Display for VState {
215     fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
216         write!(f, "#avl={}, #vtype=({})", self.avl, self.vtype)
217     }
218 }
219 
220 impl VecOpCategory {
221     pub fn encode(&self) -> u32 {
222         // See: https://github.com/riscv/riscv-v-spec/blob/master/v-spec.adoc#101-vector-arithmetic-instruction-encoding
223         match self {
224             VecOpCategory::OPIVV => 0b000,
225             VecOpCategory::OPFVV => 0b001,
226             VecOpCategory::OPMVV => 0b010,
227             VecOpCategory::OPIVI => 0b011,
228             VecOpCategory::OPIVX => 0b100,
229             VecOpCategory::OPFVF => 0b101,
230             VecOpCategory::OPMVX => 0b110,
231             VecOpCategory::OPCFG => 0b111,
232         }
233     }
234 }
235 
236 impl Copy for VecOpMasking {}
237 impl VecOpMasking {
238     pub fn is_enabled(&self) -> bool {
239         match self {
240             VecOpMasking::Enabled { .. } => true,
241             VecOpMasking::Disabled => false,
242         }
243     }
244 
245     pub fn encode(&self) -> u32 {
246         match self {
247             VecOpMasking::Enabled { .. } => 0,
248             VecOpMasking::Disabled => 1,
249         }
250     }
251 }
252 
253 impl VecAluOpRRRR {
254     pub fn opcode(&self) -> u32 {
255         // Vector Opcode
256         0x57
257     }
258     pub fn funct3(&self) -> u32 {
259         self.category().encode()
260     }
261 
262     pub fn funct6(&self) -> u32 {
263         // See: https://github.com/riscv/riscv-v-spec/blob/master/inst-table.adoc
264         match self {
265             VecAluOpRRRR::VmaccVV | VecAluOpRRRR::VmaccVX => 0b101101,
266             VecAluOpRRRR::VnmsacVV | VecAluOpRRRR::VnmsacVX => 0b101111,
267             VecAluOpRRRR::VfmaccVV | VecAluOpRRRR::VfmaccVF => 0b101100,
268             VecAluOpRRRR::VfnmaccVV | VecAluOpRRRR::VfnmaccVF => 0b101101,
269             VecAluOpRRRR::VfmsacVV | VecAluOpRRRR::VfmsacVF => 0b101110,
270             VecAluOpRRRR::VfnmsacVV | VecAluOpRRRR::VfnmsacVF => 0b101111,
271             VecAluOpRRRR::Vslide1upVX => 0b001110,
272         }
273     }
274 
275     pub fn category(&self) -> VecOpCategory {
276         match self {
277             VecAluOpRRRR::VmaccVV | VecAluOpRRRR::VnmsacVV => VecOpCategory::OPMVV,
278             VecAluOpRRRR::VmaccVX | VecAluOpRRRR::VnmsacVX | VecAluOpRRRR::Vslide1upVX => {
279                 VecOpCategory::OPMVX
280             }
281             VecAluOpRRRR::VfmaccVV
282             | VecAluOpRRRR::VfnmaccVV
283             | VecAluOpRRRR::VfmsacVV
284             | VecAluOpRRRR::VfnmsacVV => VecOpCategory::OPFVV,
285             VecAluOpRRRR::VfmaccVF
286             | VecAluOpRRRR::VfnmaccVF
287             | VecAluOpRRRR::VfmsacVF
288             | VecAluOpRRRR::VfnmsacVF => VecOpCategory::OPFVF,
289         }
290     }
291 
292     // vs1 is the only variable source, vs2 is fixed.
293     pub fn vs1_regclass(&self) -> RegClass {
294         match self.category() {
295             VecOpCategory::OPMVV | VecOpCategory::OPFVV => RegClass::Vector,
296             VecOpCategory::OPMVX => RegClass::Int,
297             VecOpCategory::OPFVF => RegClass::Float,
298             _ => unreachable!(),
299         }
300     }
301 }
302 
303 impl VecInstOverlapInfo for VecAluOpRRRR {
304     fn forbids_src_dst_overlaps(&self) -> bool {
305         match self {
306             VecAluOpRRRR::Vslide1upVX => true,
307             _ => false,
308         }
309     }
310 }
311 
312 impl fmt::Display for VecAluOpRRRR {
313     fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
314         let mut s = format!("{self:?}");
315         s.make_ascii_lowercase();
316         let (opcode, category) = s.split_at(s.len() - 2);
317         f.write_str(&format!("{opcode}.{category}"))
318     }
319 }
320 
321 impl VecAluOpRRRImm5 {
322     pub fn opcode(&self) -> u32 {
323         // Vector Opcode
324         0x57
325     }
326     pub fn funct3(&self) -> u32 {
327         self.category().encode()
328     }
329 
330     pub fn funct6(&self) -> u32 {
331         // See: https://github.com/riscv/riscv-v-spec/blob/master/inst-table.adoc
332         match self {
333             VecAluOpRRRImm5::VslideupVI => 0b001110,
334         }
335     }
336 
337     pub fn category(&self) -> VecOpCategory {
338         match self {
339             VecAluOpRRRImm5::VslideupVI => VecOpCategory::OPIVI,
340         }
341     }
342 
343     pub fn imm_is_unsigned(&self) -> bool {
344         match self {
345             VecAluOpRRRImm5::VslideupVI => true,
346         }
347     }
348 }
349 
350 impl VecInstOverlapInfo for VecAluOpRRRImm5 {
351     fn forbids_src_dst_overlaps(&self) -> bool {
352         match self {
353             VecAluOpRRRImm5::VslideupVI => true,
354         }
355     }
356 }
357 
358 impl fmt::Display for VecAluOpRRRImm5 {
359     fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
360         let mut s = format!("{self:?}");
361         s.make_ascii_lowercase();
362         let (opcode, category) = s.split_at(s.len() - 2);
363         f.write_str(&format!("{opcode}.{category}"))
364     }
365 }
366 
367 impl VecAluOpRRR {
368     pub fn opcode(&self) -> u32 {
369         // Vector Opcode
370         0x57
371     }
372     pub fn funct3(&self) -> u32 {
373         self.category().encode()
374     }
375     pub fn funct6(&self) -> u32 {
376         // See: https://github.com/riscv/riscv-v-spec/blob/master/inst-table.adoc
377         match self {
378             VecAluOpRRR::VaddVV
379             | VecAluOpRRR::VaddVX
380             | VecAluOpRRR::VfaddVV
381             | VecAluOpRRR::VfaddVF => 0b000000,
382             VecAluOpRRR::VsubVV
383             | VecAluOpRRR::VsubVX
384             | VecAluOpRRR::VfsubVV
385             | VecAluOpRRR::VfsubVF => 0b000010,
386             VecAluOpRRR::VrsubVX => 0b000011,
387             VecAluOpRRR::VmulVV | VecAluOpRRR::VmulVX => 0b100101,
388             VecAluOpRRR::VmulhVV | VecAluOpRRR::VmulhVX => 0b100111,
389             VecAluOpRRR::VmulhuVV
390             | VecAluOpRRR::VmulhuVX
391             | VecAluOpRRR::VfmulVV
392             | VecAluOpRRR::VfmulVF => 0b100100,
393             VecAluOpRRR::VsmulVV | VecAluOpRRR::VsmulVX => 0b100111,
394             VecAluOpRRR::VsllVV | VecAluOpRRR::VsllVX => 0b100101,
395             VecAluOpRRR::VsrlVV | VecAluOpRRR::VsrlVX => 0b101000,
396             VecAluOpRRR::VsraVV | VecAluOpRRR::VsraVX => 0b101001,
397             VecAluOpRRR::VandVV | VecAluOpRRR::VandVX => 0b001001,
398             VecAluOpRRR::VorVV | VecAluOpRRR::VorVX => 0b001010,
399             VecAluOpRRR::VxorVV | VecAluOpRRR::VxorVX => 0b001011,
400             VecAluOpRRR::VminuVV | VecAluOpRRR::VminuVX | VecAluOpRRR::VredminuVS => 0b000100,
401             VecAluOpRRR::VminVV | VecAluOpRRR::VminVX => 0b000101,
402             VecAluOpRRR::VmaxuVV | VecAluOpRRR::VmaxuVX | VecAluOpRRR::VredmaxuVS => 0b000110,
403             VecAluOpRRR::VmaxVV | VecAluOpRRR::VmaxVX => 0b000111,
404             VecAluOpRRR::VslidedownVX => 0b001111,
405             VecAluOpRRR::VfrsubVF => 0b100111,
406             VecAluOpRRR::VmergeVVM
407             | VecAluOpRRR::VmergeVXM
408             | VecAluOpRRR::VfmergeVFM
409             | VecAluOpRRR::VcompressVM => 0b010111,
410             VecAluOpRRR::VfdivVV
411             | VecAluOpRRR::VfdivVF
412             | VecAluOpRRR::VsadduVV
413             | VecAluOpRRR::VsadduVX => 0b100000,
414             VecAluOpRRR::VfrdivVF | VecAluOpRRR::VsaddVV | VecAluOpRRR::VsaddVX => 0b100001,
415             VecAluOpRRR::VfminVV => 0b000100,
416             VecAluOpRRR::VfmaxVV => 0b000110,
417             VecAluOpRRR::VssubuVV | VecAluOpRRR::VssubuVX => 0b100010,
418             VecAluOpRRR::VssubVV | VecAluOpRRR::VssubVX => 0b100011,
419             VecAluOpRRR::VfsgnjVV | VecAluOpRRR::VfsgnjVF => 0b001000,
420             VecAluOpRRR::VfsgnjnVV => 0b001001,
421             VecAluOpRRR::VfsgnjxVV => 0b001010,
422             VecAluOpRRR::VrgatherVV | VecAluOpRRR::VrgatherVX => 0b001100,
423             VecAluOpRRR::VwadduVV | VecAluOpRRR::VwadduVX => 0b110000,
424             VecAluOpRRR::VwaddVV | VecAluOpRRR::VwaddVX => 0b110001,
425             VecAluOpRRR::VwsubuVV | VecAluOpRRR::VwsubuVX => 0b110010,
426             VecAluOpRRR::VwsubVV | VecAluOpRRR::VwsubVX => 0b110011,
427             VecAluOpRRR::VwadduWV | VecAluOpRRR::VwadduWX => 0b110100,
428             VecAluOpRRR::VwaddWV | VecAluOpRRR::VwaddWX => 0b110101,
429             VecAluOpRRR::VwsubuWV | VecAluOpRRR::VwsubuWX => 0b110110,
430             VecAluOpRRR::VwsubWV | VecAluOpRRR::VwsubWX => 0b110111,
431             VecAluOpRRR::VmseqVV
432             | VecAluOpRRR::VmseqVX
433             | VecAluOpRRR::VmfeqVV
434             | VecAluOpRRR::VmfeqVF => 0b011000,
435             VecAluOpRRR::VmsneVV
436             | VecAluOpRRR::VmsneVX
437             | VecAluOpRRR::VmfleVV
438             | VecAluOpRRR::VmfleVF
439             | VecAluOpRRR::VmandMM => 0b011001,
440             VecAluOpRRR::VmsltuVV | VecAluOpRRR::VmsltuVX | VecAluOpRRR::VmorMM => 0b011010,
441             VecAluOpRRR::VmsltVV
442             | VecAluOpRRR::VmsltVX
443             | VecAluOpRRR::VmfltVV
444             | VecAluOpRRR::VmfltVF => 0b011011,
445             VecAluOpRRR::VmsleuVV
446             | VecAluOpRRR::VmsleuVX
447             | VecAluOpRRR::VmfneVV
448             | VecAluOpRRR::VmfneVF => 0b011100,
449             VecAluOpRRR::VmsleVV
450             | VecAluOpRRR::VmsleVX
451             | VecAluOpRRR::VmfgtVF
452             | VecAluOpRRR::VmnandMM => 0b011101,
453             VecAluOpRRR::VmsgtuVX | VecAluOpRRR::VmnorMM => 0b011110,
454             VecAluOpRRR::VmsgtVX | VecAluOpRRR::VmfgeVF => 0b011111,
455         }
456     }
457 
458     pub fn category(&self) -> VecOpCategory {
459         match self {
460             VecAluOpRRR::VaddVV
461             | VecAluOpRRR::VsaddVV
462             | VecAluOpRRR::VsadduVV
463             | VecAluOpRRR::VsubVV
464             | VecAluOpRRR::VssubVV
465             | VecAluOpRRR::VssubuVV
466             | VecAluOpRRR::VsmulVV
467             | VecAluOpRRR::VsllVV
468             | VecAluOpRRR::VsrlVV
469             | VecAluOpRRR::VsraVV
470             | VecAluOpRRR::VandVV
471             | VecAluOpRRR::VorVV
472             | VecAluOpRRR::VxorVV
473             | VecAluOpRRR::VminuVV
474             | VecAluOpRRR::VminVV
475             | VecAluOpRRR::VmaxuVV
476             | VecAluOpRRR::VmaxVV
477             | VecAluOpRRR::VmergeVVM
478             | VecAluOpRRR::VrgatherVV
479             | VecAluOpRRR::VmseqVV
480             | VecAluOpRRR::VmsneVV
481             | VecAluOpRRR::VmsltuVV
482             | VecAluOpRRR::VmsltVV
483             | VecAluOpRRR::VmsleuVV
484             | VecAluOpRRR::VmsleVV => VecOpCategory::OPIVV,
485             VecAluOpRRR::VwaddVV
486             | VecAluOpRRR::VwaddWV
487             | VecAluOpRRR::VwadduVV
488             | VecAluOpRRR::VwadduWV
489             | VecAluOpRRR::VwsubVV
490             | VecAluOpRRR::VwsubWV
491             | VecAluOpRRR::VwsubuVV
492             | VecAluOpRRR::VwsubuWV
493             | VecAluOpRRR::VmulVV
494             | VecAluOpRRR::VmulhVV
495             | VecAluOpRRR::VmulhuVV
496             | VecAluOpRRR::VredmaxuVS
497             | VecAluOpRRR::VredminuVS
498             | VecAluOpRRR::VcompressVM
499             | VecAluOpRRR::VmandMM
500             | VecAluOpRRR::VmorMM
501             | VecAluOpRRR::VmnandMM
502             | VecAluOpRRR::VmnorMM => VecOpCategory::OPMVV,
503             VecAluOpRRR::VwaddVX
504             | VecAluOpRRR::VwadduVX
505             | VecAluOpRRR::VwadduWX
506             | VecAluOpRRR::VwaddWX
507             | VecAluOpRRR::VwsubVX
508             | VecAluOpRRR::VwsubuVX
509             | VecAluOpRRR::VwsubuWX
510             | VecAluOpRRR::VwsubWX
511             | VecAluOpRRR::VmulVX
512             | VecAluOpRRR::VmulhVX
513             | VecAluOpRRR::VmulhuVX => VecOpCategory::OPMVX,
514             VecAluOpRRR::VaddVX
515             | VecAluOpRRR::VsaddVX
516             | VecAluOpRRR::VsadduVX
517             | VecAluOpRRR::VsubVX
518             | VecAluOpRRR::VssubVX
519             | VecAluOpRRR::VssubuVX
520             | VecAluOpRRR::VrsubVX
521             | VecAluOpRRR::VsmulVX
522             | VecAluOpRRR::VsllVX
523             | VecAluOpRRR::VsrlVX
524             | VecAluOpRRR::VsraVX
525             | VecAluOpRRR::VandVX
526             | VecAluOpRRR::VorVX
527             | VecAluOpRRR::VxorVX
528             | VecAluOpRRR::VminuVX
529             | VecAluOpRRR::VminVX
530             | VecAluOpRRR::VmaxuVX
531             | VecAluOpRRR::VmaxVX
532             | VecAluOpRRR::VslidedownVX
533             | VecAluOpRRR::VmergeVXM
534             | VecAluOpRRR::VrgatherVX
535             | VecAluOpRRR::VmseqVX
536             | VecAluOpRRR::VmsneVX
537             | VecAluOpRRR::VmsltuVX
538             | VecAluOpRRR::VmsltVX
539             | VecAluOpRRR::VmsleuVX
540             | VecAluOpRRR::VmsleVX
541             | VecAluOpRRR::VmsgtuVX
542             | VecAluOpRRR::VmsgtVX => VecOpCategory::OPIVX,
543             VecAluOpRRR::VfaddVV
544             | VecAluOpRRR::VfsubVV
545             | VecAluOpRRR::VfmulVV
546             | VecAluOpRRR::VfdivVV
547             | VecAluOpRRR::VfmaxVV
548             | VecAluOpRRR::VfminVV
549             | VecAluOpRRR::VfsgnjVV
550             | VecAluOpRRR::VfsgnjnVV
551             | VecAluOpRRR::VfsgnjxVV
552             | VecAluOpRRR::VmfeqVV
553             | VecAluOpRRR::VmfneVV
554             | VecAluOpRRR::VmfltVV
555             | VecAluOpRRR::VmfleVV => VecOpCategory::OPFVV,
556             VecAluOpRRR::VfaddVF
557             | VecAluOpRRR::VfsubVF
558             | VecAluOpRRR::VfrsubVF
559             | VecAluOpRRR::VfmulVF
560             | VecAluOpRRR::VfdivVF
561             | VecAluOpRRR::VfrdivVF
562             | VecAluOpRRR::VfmergeVFM
563             | VecAluOpRRR::VfsgnjVF
564             | VecAluOpRRR::VmfeqVF
565             | VecAluOpRRR::VmfneVF
566             | VecAluOpRRR::VmfltVF
567             | VecAluOpRRR::VmfleVF
568             | VecAluOpRRR::VmfgtVF
569             | VecAluOpRRR::VmfgeVF => VecOpCategory::OPFVF,
570         }
571     }
572 
573     // vs1 is the only variable source, vs2 is fixed.
574     pub fn vs1_regclass(&self) -> RegClass {
575         match self.category() {
576             VecOpCategory::OPIVV | VecOpCategory::OPFVV | VecOpCategory::OPMVV => RegClass::Vector,
577             VecOpCategory::OPIVX | VecOpCategory::OPMVX => RegClass::Int,
578             VecOpCategory::OPFVF => RegClass::Float,
579             _ => unreachable!(),
580         }
581     }
582 }
583 
584 impl VecInstOverlapInfo for VecAluOpRRR {
585     fn forbids_src_dst_overlaps(&self) -> bool {
586         match self {
587             VecAluOpRRR::VrgatherVV
588             | VecAluOpRRR::VrgatherVX
589             | VecAluOpRRR::VcompressVM
590             | VecAluOpRRR::VwadduVV
591             | VecAluOpRRR::VwadduVX
592             | VecAluOpRRR::VwaddVV
593             | VecAluOpRRR::VwaddVX
594             | VecAluOpRRR::VwadduWV
595             | VecAluOpRRR::VwadduWX
596             | VecAluOpRRR::VwaddWV
597             | VecAluOpRRR::VwaddWX
598             | VecAluOpRRR::VwsubuVV
599             | VecAluOpRRR::VwsubuVX
600             | VecAluOpRRR::VwsubVV
601             | VecAluOpRRR::VwsubVX
602             | VecAluOpRRR::VwsubuWV
603             | VecAluOpRRR::VwsubuWX
604             | VecAluOpRRR::VwsubWV
605             | VecAluOpRRR::VwsubWX => true,
606             _ => false,
607         }
608     }
609 
610     // Only mask writing operations, and reduction operations (`vred*`) allow mask / dst overlaps.
611     fn forbids_mask_dst_overlaps(&self) -> bool {
612         match self {
613             VecAluOpRRR::VredmaxuVS
614             | VecAluOpRRR::VredminuVS
615             | VecAluOpRRR::VmandMM
616             | VecAluOpRRR::VmorMM
617             | VecAluOpRRR::VmnandMM
618             | VecAluOpRRR::VmnorMM
619             | VecAluOpRRR::VmseqVX
620             | VecAluOpRRR::VmsneVX
621             | VecAluOpRRR::VmsltuVX
622             | VecAluOpRRR::VmsltVX
623             | VecAluOpRRR::VmsleuVX
624             | VecAluOpRRR::VmsleVX
625             | VecAluOpRRR::VmsgtuVX
626             | VecAluOpRRR::VmsgtVX
627             | VecAluOpRRR::VmfeqVV
628             | VecAluOpRRR::VmfneVV
629             | VecAluOpRRR::VmfltVV
630             | VecAluOpRRR::VmfleVV
631             | VecAluOpRRR::VmfeqVF
632             | VecAluOpRRR::VmfneVF
633             | VecAluOpRRR::VmfltVF
634             | VecAluOpRRR::VmfleVF
635             | VecAluOpRRR::VmfgtVF
636             | VecAluOpRRR::VmfgeVF => false,
637             _ => true,
638         }
639     }
640 }
641 
642 impl fmt::Display for VecAluOpRRR {
643     fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
644         let suffix_length = match self {
645             VecAluOpRRR::VmergeVVM | VecAluOpRRR::VmergeVXM | VecAluOpRRR::VfmergeVFM => 3,
646             _ => 2,
647         };
648 
649         let mut s = format!("{self:?}");
650         s.make_ascii_lowercase();
651         let (opcode, category) = s.split_at(s.len() - suffix_length);
652         f.write_str(&format!("{opcode}.{category}"))
653     }
654 }
655 
656 impl VecAluOpRRImm5 {
657     pub fn opcode(&self) -> u32 {
658         // Vector Opcode
659         0x57
660     }
661     pub fn funct3(&self) -> u32 {
662         self.category().encode()
663     }
664 
665     pub fn funct6(&self) -> u32 {
666         // See: https://github.com/riscv/riscv-v-spec/blob/master/inst-table.adoc
667         match self {
668             VecAluOpRRImm5::VaddVI => 0b000000,
669             VecAluOpRRImm5::VrsubVI => 0b000011,
670             VecAluOpRRImm5::VsllVI => 0b100101,
671             VecAluOpRRImm5::VsrlVI => 0b101000,
672             VecAluOpRRImm5::VsraVI => 0b101001,
673             VecAluOpRRImm5::VandVI => 0b001001,
674             VecAluOpRRImm5::VorVI => 0b001010,
675             VecAluOpRRImm5::VxorVI => 0b001011,
676             VecAluOpRRImm5::VslidedownVI => 0b001111,
677             VecAluOpRRImm5::VssrlVI => 0b101010,
678             VecAluOpRRImm5::VmergeVIM => 0b010111,
679             VecAluOpRRImm5::VsadduVI => 0b100000,
680             VecAluOpRRImm5::VsaddVI => 0b100001,
681             VecAluOpRRImm5::VrgatherVI => 0b001100,
682             VecAluOpRRImm5::VmvrV => 0b100111,
683             VecAluOpRRImm5::VnclipWI => 0b101111,
684             VecAluOpRRImm5::VnclipuWI => 0b101110,
685             VecAluOpRRImm5::VmseqVI => 0b011000,
686             VecAluOpRRImm5::VmsneVI => 0b011001,
687             VecAluOpRRImm5::VmsleuVI => 0b011100,
688             VecAluOpRRImm5::VmsleVI => 0b011101,
689             VecAluOpRRImm5::VmsgtuVI => 0b011110,
690             VecAluOpRRImm5::VmsgtVI => 0b011111,
691         }
692     }
693 
694     pub fn category(&self) -> VecOpCategory {
695         match self {
696             VecAluOpRRImm5::VaddVI
697             | VecAluOpRRImm5::VrsubVI
698             | VecAluOpRRImm5::VsllVI
699             | VecAluOpRRImm5::VsrlVI
700             | VecAluOpRRImm5::VsraVI
701             | VecAluOpRRImm5::VandVI
702             | VecAluOpRRImm5::VorVI
703             | VecAluOpRRImm5::VxorVI
704             | VecAluOpRRImm5::VssrlVI
705             | VecAluOpRRImm5::VslidedownVI
706             | VecAluOpRRImm5::VmergeVIM
707             | VecAluOpRRImm5::VsadduVI
708             | VecAluOpRRImm5::VsaddVI
709             | VecAluOpRRImm5::VrgatherVI
710             | VecAluOpRRImm5::VmvrV
711             | VecAluOpRRImm5::VnclipWI
712             | VecAluOpRRImm5::VnclipuWI
713             | VecAluOpRRImm5::VmseqVI
714             | VecAluOpRRImm5::VmsneVI
715             | VecAluOpRRImm5::VmsleuVI
716             | VecAluOpRRImm5::VmsleVI
717             | VecAluOpRRImm5::VmsgtuVI
718             | VecAluOpRRImm5::VmsgtVI => VecOpCategory::OPIVI,
719         }
720     }
721 
722     pub fn imm_is_unsigned(&self) -> bool {
723         match self {
724             VecAluOpRRImm5::VsllVI
725             | VecAluOpRRImm5::VsrlVI
726             | VecAluOpRRImm5::VssrlVI
727             | VecAluOpRRImm5::VsraVI
728             | VecAluOpRRImm5::VslidedownVI
729             | VecAluOpRRImm5::VrgatherVI
730             | VecAluOpRRImm5::VmvrV
731             | VecAluOpRRImm5::VnclipWI
732             | VecAluOpRRImm5::VnclipuWI => true,
733             VecAluOpRRImm5::VaddVI
734             | VecAluOpRRImm5::VrsubVI
735             | VecAluOpRRImm5::VandVI
736             | VecAluOpRRImm5::VorVI
737             | VecAluOpRRImm5::VxorVI
738             | VecAluOpRRImm5::VmergeVIM
739             | VecAluOpRRImm5::VsadduVI
740             | VecAluOpRRImm5::VsaddVI
741             | VecAluOpRRImm5::VmseqVI
742             | VecAluOpRRImm5::VmsneVI
743             | VecAluOpRRImm5::VmsleuVI
744             | VecAluOpRRImm5::VmsleVI
745             | VecAluOpRRImm5::VmsgtuVI
746             | VecAluOpRRImm5::VmsgtVI => false,
747         }
748     }
749 }
750 
751 impl VecInstOverlapInfo for VecAluOpRRImm5 {
752     fn forbids_src_dst_overlaps(&self) -> bool {
753         match self {
754             VecAluOpRRImm5::VrgatherVI => true,
755             _ => false,
756         }
757     }
758 
759     // Only mask writing operations, and reduction operations (`vred*`) allow mask / dst overlaps.
760     fn forbids_mask_dst_overlaps(&self) -> bool {
761         match self {
762             VecAluOpRRImm5::VmseqVI
763             | VecAluOpRRImm5::VmsneVI
764             | VecAluOpRRImm5::VmsleuVI
765             | VecAluOpRRImm5::VmsleVI
766             | VecAluOpRRImm5::VmsgtuVI
767             | VecAluOpRRImm5::VmsgtVI => false,
768             _ => true,
769         }
770     }
771 }
772 
773 impl fmt::Display for VecAluOpRRImm5 {
774     fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
775         let suffix_length = match self {
776             VecAluOpRRImm5::VmergeVIM => 3,
777             _ => 2,
778         };
779 
780         let mut s = format!("{self:?}");
781         s.make_ascii_lowercase();
782         let (opcode, category) = s.split_at(s.len() - suffix_length);
783         f.write_str(&format!("{opcode}.{category}"))
784     }
785 }
786 
787 impl VecAluOpRR {
788     pub fn opcode(&self) -> u32 {
789         // Vector Opcode
790         0x57
791     }
792 
793     pub fn funct3(&self) -> u32 {
794         self.category().encode()
795     }
796 
797     pub fn funct6(&self) -> u32 {
798         // See: https://github.com/riscv/riscv-v-spec/blob/master/inst-table.adoc
799         match self {
800             VecAluOpRR::VmvSX | VecAluOpRR::VmvXS | VecAluOpRR::VfmvSF | VecAluOpRR::VfmvFS => {
801                 0b010000
802             }
803             VecAluOpRR::VzextVF2
804             | VecAluOpRR::VzextVF4
805             | VecAluOpRR::VzextVF8
806             | VecAluOpRR::VsextVF2
807             | VecAluOpRR::VsextVF4
808             | VecAluOpRR::VsextVF8 => 0b010010,
809             VecAluOpRR::VfsqrtV => 0b010011,
810             VecAluOpRR::VmvVV | VecAluOpRR::VmvVX | VecAluOpRR::VfmvVF => 0b010111,
811             VecAluOpRR::VfcvtxufV
812             | VecAluOpRR::VfcvtxfV
813             | VecAluOpRR::VfcvtrtzxufV
814             | VecAluOpRR::VfcvtrtzxfV
815             | VecAluOpRR::VfcvtfxuV
816             | VecAluOpRR::VfcvtfxV
817             | VecAluOpRR::VfwcvtffV
818             | VecAluOpRR::VfncvtffW => 0b010010,
819         }
820     }
821 
822     pub fn category(&self) -> VecOpCategory {
823         match self {
824             VecAluOpRR::VmvSX => VecOpCategory::OPMVX,
825             VecAluOpRR::VmvXS
826             | VecAluOpRR::VzextVF2
827             | VecAluOpRR::VzextVF4
828             | VecAluOpRR::VzextVF8
829             | VecAluOpRR::VsextVF2
830             | VecAluOpRR::VsextVF4
831             | VecAluOpRR::VsextVF8 => VecOpCategory::OPMVV,
832             VecAluOpRR::VfmvSF | VecAluOpRR::VfmvVF => VecOpCategory::OPFVF,
833             VecAluOpRR::VfmvFS
834             | VecAluOpRR::VfsqrtV
835             | VecAluOpRR::VfcvtxufV
836             | VecAluOpRR::VfcvtxfV
837             | VecAluOpRR::VfcvtrtzxufV
838             | VecAluOpRR::VfcvtrtzxfV
839             | VecAluOpRR::VfcvtfxuV
840             | VecAluOpRR::VfcvtfxV
841             | VecAluOpRR::VfwcvtffV
842             | VecAluOpRR::VfncvtffW => VecOpCategory::OPFVV,
843             VecAluOpRR::VmvVV => VecOpCategory::OPIVV,
844             VecAluOpRR::VmvVX => VecOpCategory::OPIVX,
845         }
846     }
847 
848     /// Returns the auxiliary encoding field for the instruction, if any.
849     pub fn aux_encoding(&self) -> u32 {
850         match self {
851             // VRXUNARY0
852             VecAluOpRR::VmvSX => 0b00000,
853             // VWXUNARY0
854             VecAluOpRR::VmvXS => 0b00000,
855             // VRFUNARY0
856             VecAluOpRR::VfmvSF => 0b00000,
857             // VWFUNARY0
858             VecAluOpRR::VfmvFS => 0b00000,
859             // VFUNARY1
860             VecAluOpRR::VfsqrtV => 0b00000,
861             // VXUNARY0
862             VecAluOpRR::VzextVF8 => 0b00010,
863             VecAluOpRR::VsextVF8 => 0b00011,
864             VecAluOpRR::VzextVF4 => 0b00100,
865             VecAluOpRR::VsextVF4 => 0b00101,
866             VecAluOpRR::VzextVF2 => 0b00110,
867             VecAluOpRR::VsextVF2 => 0b00111,
868             // VFUNARY0
869             // single-width converts
870             VecAluOpRR::VfcvtxufV => 0b00000,
871             VecAluOpRR::VfcvtxfV => 0b00001,
872             VecAluOpRR::VfcvtrtzxufV => 0b00110,
873             VecAluOpRR::VfcvtrtzxfV => 0b00111,
874             VecAluOpRR::VfcvtfxuV => 0b00010,
875             VecAluOpRR::VfcvtfxV => 0b00011,
876             // widening converts
877             VecAluOpRR::VfwcvtffV => 0b01100,
878             // narrowing converts
879             VecAluOpRR::VfncvtffW => 0b10100,
880             // These don't have a explicit encoding table, but Section 11.16 Vector Integer Move Instruction states:
881             // > The first operand specifier (vs2) must contain v0, and any other vector register number in vs2 is reserved.
882             VecAluOpRR::VmvVV | VecAluOpRR::VmvVX | VecAluOpRR::VfmvVF => 0,
883         }
884     }
885 
886     /// Most of these opcodes have the source register encoded in the VS2 field and
887     /// the `aux_encoding` field in VS1. However some special snowflakes have it the
888     /// other way around. As far as I can tell only vmv.v.* are backwards.
889     pub fn vs_is_vs2_encoded(&self) -> bool {
890         match self {
891             VecAluOpRR::VmvXS
892             | VecAluOpRR::VfmvFS
893             | VecAluOpRR::VfsqrtV
894             | VecAluOpRR::VzextVF2
895             | VecAluOpRR::VzextVF4
896             | VecAluOpRR::VzextVF8
897             | VecAluOpRR::VsextVF2
898             | VecAluOpRR::VsextVF4
899             | VecAluOpRR::VsextVF8
900             | VecAluOpRR::VfcvtxufV
901             | VecAluOpRR::VfcvtxfV
902             | VecAluOpRR::VfcvtrtzxufV
903             | VecAluOpRR::VfcvtrtzxfV
904             | VecAluOpRR::VfcvtfxuV
905             | VecAluOpRR::VfcvtfxV
906             | VecAluOpRR::VfwcvtffV
907             | VecAluOpRR::VfncvtffW => true,
908             VecAluOpRR::VmvSX
909             | VecAluOpRR::VfmvSF
910             | VecAluOpRR::VmvVV
911             | VecAluOpRR::VmvVX
912             | VecAluOpRR::VfmvVF => false,
913         }
914     }
915 
916     pub fn dst_regclass(&self) -> RegClass {
917         match self {
918             VecAluOpRR::VfmvSF
919             | VecAluOpRR::VmvSX
920             | VecAluOpRR::VmvVV
921             | VecAluOpRR::VmvVX
922             | VecAluOpRR::VfmvVF
923             | VecAluOpRR::VfsqrtV
924             | VecAluOpRR::VzextVF2
925             | VecAluOpRR::VzextVF4
926             | VecAluOpRR::VzextVF8
927             | VecAluOpRR::VsextVF2
928             | VecAluOpRR::VsextVF4
929             | VecAluOpRR::VsextVF8
930             | VecAluOpRR::VfcvtxufV
931             | VecAluOpRR::VfcvtxfV
932             | VecAluOpRR::VfcvtrtzxufV
933             | VecAluOpRR::VfcvtrtzxfV
934             | VecAluOpRR::VfcvtfxuV
935             | VecAluOpRR::VfcvtfxV
936             | VecAluOpRR::VfwcvtffV
937             | VecAluOpRR::VfncvtffW => RegClass::Vector,
938             VecAluOpRR::VmvXS => RegClass::Int,
939             VecAluOpRR::VfmvFS => RegClass::Float,
940         }
941     }
942 
943     pub fn src_regclass(&self) -> RegClass {
944         match self {
945             VecAluOpRR::VmvXS
946             | VecAluOpRR::VfmvFS
947             | VecAluOpRR::VmvVV
948             | VecAluOpRR::VfsqrtV
949             | VecAluOpRR::VzextVF2
950             | VecAluOpRR::VzextVF4
951             | VecAluOpRR::VzextVF8
952             | VecAluOpRR::VsextVF2
953             | VecAluOpRR::VsextVF4
954             | VecAluOpRR::VsextVF8
955             | VecAluOpRR::VfcvtxufV
956             | VecAluOpRR::VfcvtxfV
957             | VecAluOpRR::VfcvtrtzxufV
958             | VecAluOpRR::VfcvtrtzxfV
959             | VecAluOpRR::VfcvtfxuV
960             | VecAluOpRR::VfcvtfxV
961             | VecAluOpRR::VfwcvtffV
962             | VecAluOpRR::VfncvtffW => RegClass::Vector,
963             VecAluOpRR::VfmvSF | VecAluOpRR::VfmvVF => RegClass::Float,
964             VecAluOpRR::VmvSX | VecAluOpRR::VmvVX => RegClass::Int,
965         }
966     }
967 }
968 
969 impl VecInstOverlapInfo for VecAluOpRR {
970     fn forbids_src_dst_overlaps(&self) -> bool {
971         match self {
972             VecAluOpRR::VzextVF2
973             | VecAluOpRR::VzextVF4
974             | VecAluOpRR::VzextVF8
975             | VecAluOpRR::VsextVF2
976             | VecAluOpRR::VsextVF4
977             | VecAluOpRR::VsextVF8
978             | VecAluOpRR::VfwcvtffV
979             | VecAluOpRR::VfncvtffW => true,
980             _ => false,
981         }
982     }
983 }
984 
985 impl fmt::Display for VecAluOpRR {
986     fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
987         f.write_str(match self {
988             VecAluOpRR::VmvSX => "vmv.s.x",
989             VecAluOpRR::VmvXS => "vmv.x.s",
990             VecAluOpRR::VfmvSF => "vfmv.s.f",
991             VecAluOpRR::VfmvFS => "vfmv.f.s",
992             VecAluOpRR::VfsqrtV => "vfsqrt.v",
993             VecAluOpRR::VzextVF2 => "vzext.vf2",
994             VecAluOpRR::VzextVF4 => "vzext.vf4",
995             VecAluOpRR::VzextVF8 => "vzext.vf8",
996             VecAluOpRR::VsextVF2 => "vsext.vf2",
997             VecAluOpRR::VsextVF4 => "vsext.vf4",
998             VecAluOpRR::VsextVF8 => "vsext.vf8",
999             VecAluOpRR::VmvVV => "vmv.v.v",
1000             VecAluOpRR::VmvVX => "vmv.v.x",
1001             VecAluOpRR::VfmvVF => "vfmv.v.f",
1002             VecAluOpRR::VfcvtxufV => "vfcvt.xu.f.v",
1003             VecAluOpRR::VfcvtxfV => "vfcvt.x.f.v",
1004             VecAluOpRR::VfcvtrtzxufV => "vfcvt.rtz.xu.f.v",
1005             VecAluOpRR::VfcvtrtzxfV => "vfcvt.rtz.x.f.v",
1006             VecAluOpRR::VfcvtfxuV => "vfcvt.f.xu.v",
1007             VecAluOpRR::VfcvtfxV => "vfcvt.f.x.v",
1008             VecAluOpRR::VfwcvtffV => "vfwcvt.f.f.v",
1009             VecAluOpRR::VfncvtffW => "vfncvt.f.f.w",
1010         })
1011     }
1012 }
1013 
1014 impl VecAluOpRImm5 {
1015     pub fn opcode(&self) -> u32 {
1016         // Vector Opcode
1017         0x57
1018     }
1019     pub fn funct3(&self) -> u32 {
1020         self.category().encode()
1021     }
1022 
1023     pub fn funct6(&self) -> u32 {
1024         // See: https://github.com/riscv/riscv-v-spec/blob/master/inst-table.adoc
1025         match self {
1026             VecAluOpRImm5::VmvVI => 0b010111,
1027         }
1028     }
1029 
1030     pub fn category(&self) -> VecOpCategory {
1031         match self {
1032             VecAluOpRImm5::VmvVI => VecOpCategory::OPIVI,
1033         }
1034     }
1035 
1036     /// Returns the auxiliary encoding field for the instruction, if any.
1037     pub fn aux_encoding(&self) -> u32 {
1038         match self {
1039             // These don't have a explicit encoding table, but Section 11.16 Vector Integer Move Instruction states:
1040             // > The first operand specifier (vs2) must contain v0, and any other vector register number in vs2 is reserved.
1041             VecAluOpRImm5::VmvVI => 0,
1042         }
1043     }
1044 }
1045 
1046 impl VecInstOverlapInfo for VecAluOpRImm5 {
1047     fn forbids_src_dst_overlaps(&self) -> bool {
1048         match self {
1049             VecAluOpRImm5::VmvVI => false,
1050         }
1051     }
1052 }
1053 
1054 impl fmt::Display for VecAluOpRImm5 {
1055     fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
1056         f.write_str(match self {
1057             VecAluOpRImm5::VmvVI => "vmv.v.i",
1058         })
1059     }
1060 }
1061 
1062 impl VecAMode {
1063     pub fn get_base_register(&self) -> Option<Reg> {
1064         match self {
1065             VecAMode::UnitStride { base, .. } => base.get_base_register(),
1066         }
1067     }
1068 
1069     pub fn get_operands(&mut self, collector: &mut impl OperandVisitor) {
1070         match self {
1071             VecAMode::UnitStride { base, .. } => base.get_operands(collector),
1072         }
1073     }
1074 
1075     /// `mop` field, described in Table 7 of Section 7.2. Vector Load/Store Addressing Modes
1076     /// https://github.com/riscv/riscv-v-spec/blob/master/v-spec.adoc#72-vector-loadstore-addressing-modes
1077     pub fn mop(&self) -> u32 {
1078         match self {
1079             VecAMode::UnitStride { .. } => 0b00,
1080         }
1081     }
1082 
1083     /// `lumop` field, described in Table 9 of Section 7.2. Vector Load/Store Addressing Modes
1084     /// https://github.com/riscv/riscv-v-spec/blob/master/v-spec.adoc#72-vector-loadstore-addressing-modes
1085     pub fn lumop(&self) -> u32 {
1086         match self {
1087             VecAMode::UnitStride { .. } => 0b00000,
1088         }
1089     }
1090 
1091     /// `sumop` field, described in Table 10 of Section 7.2. Vector Load/Store Addressing Modes
1092     /// https://github.com/riscv/riscv-v-spec/blob/master/v-spec.adoc#72-vector-loadstore-addressing-modes
1093     pub fn sumop(&self) -> u32 {
1094         match self {
1095             VecAMode::UnitStride { .. } => 0b00000,
1096         }
1097     }
1098 
1099     /// The `nf[2:0]` field encodes the number of fields in each segment. For regular vector loads and
1100     /// stores, nf=0, indicating that a single value is moved between a vector register group and memory
1101     /// at each element position. Larger values in the nf field are used to access multiple contiguous
1102     /// fields within a segment as described in Section 7.8 Vector Load/Store Segment Instructions.
1103     ///
1104     /// https://github.com/riscv/riscv-v-spec/blob/master/v-spec.adoc#72-vector-loadstore-addressing-modes
1105     pub fn nf(&self) -> u32 {
1106         match self {
1107             VecAMode::UnitStride { .. } => 0b000,
1108         }
1109     }
1110 }
1111 
1112 pub trait VecInstOverlapInfo {
1113     /// § 5.2 Vector Operands states:
1114     ///
1115     /// A destination vector register group can overlap a source vector register group
1116     /// only if one of the following holds:
1117     ///
1118     ///  * The destination EEW equals the source EEW.
1119     ///
1120     ///  * The destination EEW is smaller than the source EEW and the overlap is
1121     ///    in the lowest-numbered part of the source register group (e.g., when LMUL=1,
1122     ///    vnsrl.wi v0, v0, 3 is legal, but a destination of v1 is not).
1123     ///
1124     ///  * The destination EEW is greater than the source EEW, the source EMUL is at
1125     ///    least 1, and the overlap is in the highest-numbered part of the destination register
1126     ///    group (e.g., when LMUL=8, vzext.vf4 v0, v6 is legal, but a source of v0, v2, or v4 is not).
1127     ///
1128     /// For the purpose of determining register group overlap constraints, mask elements have EEW=1.
1129     fn forbids_src_dst_overlaps(&self) -> bool;
1130 
1131     /// § 5.3 Vector Masking states:
1132     ///
1133     /// > The destination vector register group for a masked vector instruction
1134     /// > cannot overlap the source mask register (v0), unless the destination
1135     /// > vector register is being written with a mask value (e.g., compares) or
1136     /// > the scalar result of a reduction. These instruction encodings are reserved.
1137     ///
1138     /// In almost all instructions we should not allow the mask to be re-used as
1139     /// a destination register.
1140     fn forbids_mask_dst_overlaps(&self) -> bool {
1141         true
1142     }
1143 
1144     /// There are two broad categories of overlaps (see above). But we can't represent such
1145     /// fine grained overlaps to regalloc. So if any of the two come into play we forbid
1146     /// all source and destination overlaps (including masks).
1147     fn forbids_overlaps(&self, mask: &VecOpMasking) -> bool {
1148         self.forbids_src_dst_overlaps() || (mask.is_enabled() && self.forbids_mask_dst_overlaps())
1149     }
1150 }
1151