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