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