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