Path: blob/main/cranelift/codegen/src/isa/riscv64/inst/vector.rs
1693 views
use crate::Reg;1use crate::isa::riscv64::lower::isle::generated_code::VecAluOpRRRR;2use crate::isa::riscv64::lower::isle::generated_code::{3VecAMode, VecAluOpRImm5, VecAluOpRR, VecAluOpRRImm5, VecAluOpRRR, VecAluOpRRRImm5, VecAvl,4VecElementWidth, VecLmul, VecMaskMode, VecOpCategory, VecOpMasking, VecTailMode,5};6use crate::machinst::{OperandVisitor, RegClass};7use core::fmt;89use super::{Type, UImm5};1011impl VecAvl {12pub fn _static(size: u32) -> Self {13VecAvl::Static {14size: UImm5::maybe_from_u8(size as u8).expect("Invalid size for AVL"),15}16}1718pub fn is_static(&self) -> bool {19match self {20VecAvl::Static { .. } => true,21}22}2324pub fn unwrap_static(&self) -> UImm5 {25match self {26VecAvl::Static { size } => *size,27}28}29}3031// TODO: Can we tell ISLE to derive this?32impl Copy for VecAvl {}3334// TODO: Can we tell ISLE to derive this?35impl PartialEq for VecAvl {36fn eq(&self, other: &Self) -> bool {37match (self, other) {38(VecAvl::Static { size: lhs }, VecAvl::Static { size: rhs }) => lhs == rhs,39}40}41}4243impl fmt::Display for VecAvl {44fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {45match self {46VecAvl::Static { size } => write!(f, "{size}"),47}48}49}5051impl VecElementWidth {52pub fn from_type(ty: Type) -> Self {53Self::from_bits(ty.lane_bits())54}5556pub fn from_bits(bits: u32) -> Self {57match bits {588 => VecElementWidth::E8,5916 => VecElementWidth::E16,6032 => VecElementWidth::E32,6164 => VecElementWidth::E64,62_ => panic!("Invalid number of bits for VecElementWidth: {bits}"),63}64}6566pub fn bits(&self) -> u32 {67match self {68VecElementWidth::E8 => 8,69VecElementWidth::E16 => 16,70VecElementWidth::E32 => 32,71VecElementWidth::E64 => 64,72}73}7475pub fn encode(&self) -> u32 {76match self {77VecElementWidth::E8 => 0b000,78VecElementWidth::E16 => 0b001,79VecElementWidth::E32 => 0b010,80VecElementWidth::E64 => 0b011,81}82}83}8485impl fmt::Display for VecElementWidth {86fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {87write!(f, "e{}", self.bits())88}89}9091impl VecLmul {92pub fn encode(&self) -> u32 {93match self {94VecLmul::LmulF8 => 0b101,95VecLmul::LmulF4 => 0b110,96VecLmul::LmulF2 => 0b111,97VecLmul::Lmul1 => 0b000,98VecLmul::Lmul2 => 0b001,99VecLmul::Lmul4 => 0b010,100VecLmul::Lmul8 => 0b011,101}102}103}104105impl fmt::Display for VecLmul {106fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {107match self {108VecLmul::LmulF8 => write!(f, "mf8"),109VecLmul::LmulF4 => write!(f, "mf4"),110VecLmul::LmulF2 => write!(f, "mf2"),111VecLmul::Lmul1 => write!(f, "m1"),112VecLmul::Lmul2 => write!(f, "m2"),113VecLmul::Lmul4 => write!(f, "m4"),114VecLmul::Lmul8 => write!(f, "m8"),115}116}117}118119impl VecTailMode {120pub fn encode(&self) -> u32 {121match self {122VecTailMode::Agnostic => 1,123VecTailMode::Undisturbed => 0,124}125}126}127128impl fmt::Display for VecTailMode {129fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {130match self {131VecTailMode::Agnostic => write!(f, "ta"),132VecTailMode::Undisturbed => write!(f, "tu"),133}134}135}136137impl VecMaskMode {138pub fn encode(&self) -> u32 {139match self {140VecMaskMode::Agnostic => 1,141VecMaskMode::Undisturbed => 0,142}143}144}145146impl fmt::Display for VecMaskMode {147fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {148match self {149VecMaskMode::Agnostic => write!(f, "ma"),150VecMaskMode::Undisturbed => write!(f, "mu"),151}152}153}154155/// 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)]159pub struct VType {160pub sew: VecElementWidth,161pub lmul: VecLmul,162pub tail_mode: VecTailMode,163pub mask_mode: VecMaskMode,164}165166impl VType {167// https://github.com/riscv/riscv-v-spec/blob/master/vtype-format.adoc168pub fn encode(&self) -> u32 {169let mut bits = 0;170bits |= self.lmul.encode();171bits |= self.sew.encode() << 3;172bits |= self.tail_mode.encode() << 6;173bits |= self.mask_mode.encode() << 7;174bits175}176}177178impl fmt::Display for VType {179fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {180write!(181f,182"{}, {}, {}, {}",183self.sew, self.lmul, self.tail_mode, self.mask_mode184)185}186}187188/// 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 is192/// used by our instruction emission code to ensure that the vector unit is in the correct state.193#[derive(Clone, Copy, Debug, PartialEq)]194pub struct VState {195pub avl: VecAvl,196pub vtype: VType,197}198199impl VState {200pub fn from_type(ty: Type) -> Self {201VState {202avl: VecAvl::_static(ty.lane_count()),203vtype: VType {204sew: VecElementWidth::from_type(ty),205lmul: VecLmul::Lmul1,206tail_mode: VecTailMode::Agnostic,207mask_mode: VecMaskMode::Agnostic,208},209}210}211}212213impl fmt::Display for VState {214fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {215write!(f, "#avl={}, #vtype=({})", self.avl, self.vtype)216}217}218219impl VecOpCategory {220pub fn encode(&self) -> u32 {221// See: https://github.com/riscv/riscv-v-spec/blob/master/v-spec.adoc#101-vector-arithmetic-instruction-encoding222match self {223VecOpCategory::OPIVV => 0b000,224VecOpCategory::OPFVV => 0b001,225VecOpCategory::OPMVV => 0b010,226VecOpCategory::OPIVI => 0b011,227VecOpCategory::OPIVX => 0b100,228VecOpCategory::OPFVF => 0b101,229VecOpCategory::OPMVX => 0b110,230VecOpCategory::OPCFG => 0b111,231}232}233}234235impl Copy for VecOpMasking {}236impl VecOpMasking {237pub fn is_enabled(&self) -> bool {238match self {239VecOpMasking::Enabled { .. } => true,240VecOpMasking::Disabled => false,241}242}243244pub fn encode(&self) -> u32 {245match self {246VecOpMasking::Enabled { .. } => 0,247VecOpMasking::Disabled => 1,248}249}250}251252impl VecAluOpRRRR {253pub fn opcode(&self) -> u32 {254// Vector Opcode2550x57256}257pub fn funct3(&self) -> u32 {258self.category().encode()259}260261pub fn funct6(&self) -> u32 {262// See: https://github.com/riscv/riscv-v-spec/blob/master/inst-table.adoc263match self {264VecAluOpRRRR::VmaccVV | VecAluOpRRRR::VmaccVX => 0b101101,265VecAluOpRRRR::VnmsacVV | VecAluOpRRRR::VnmsacVX => 0b101111,266VecAluOpRRRR::VfmaccVV | VecAluOpRRRR::VfmaccVF => 0b101100,267VecAluOpRRRR::VfnmaccVV | VecAluOpRRRR::VfnmaccVF => 0b101101,268VecAluOpRRRR::VfmsacVV | VecAluOpRRRR::VfmsacVF => 0b101110,269VecAluOpRRRR::VfnmsacVV | VecAluOpRRRR::VfnmsacVF => 0b101111,270VecAluOpRRRR::Vslide1upVX => 0b001110,271}272}273274pub fn category(&self) -> VecOpCategory {275match self {276VecAluOpRRRR::VmaccVV | VecAluOpRRRR::VnmsacVV => VecOpCategory::OPMVV,277VecAluOpRRRR::VmaccVX | VecAluOpRRRR::VnmsacVX | VecAluOpRRRR::Vslide1upVX => {278VecOpCategory::OPMVX279}280VecAluOpRRRR::VfmaccVV281| VecAluOpRRRR::VfnmaccVV282| VecAluOpRRRR::VfmsacVV283| VecAluOpRRRR::VfnmsacVV => VecOpCategory::OPFVV,284VecAluOpRRRR::VfmaccVF285| VecAluOpRRRR::VfnmaccVF286| VecAluOpRRRR::VfmsacVF287| VecAluOpRRRR::VfnmsacVF => VecOpCategory::OPFVF,288}289}290291// vs1 is the only variable source, vs2 is fixed.292pub fn vs1_regclass(&self) -> RegClass {293match self.category() {294VecOpCategory::OPMVV | VecOpCategory::OPFVV => RegClass::Vector,295VecOpCategory::OPMVX => RegClass::Int,296VecOpCategory::OPFVF => RegClass::Float,297_ => unreachable!(),298}299}300}301302impl VecInstOverlapInfo for VecAluOpRRRR {303fn forbids_src_dst_overlaps(&self) -> bool {304match self {305VecAluOpRRRR::Vslide1upVX => true,306_ => false,307}308}309}310311impl fmt::Display for VecAluOpRRRR {312fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {313let mut s = format!("{self:?}");314s.make_ascii_lowercase();315let (opcode, category) = s.split_at(s.len() - 2);316f.write_str(&format!("{opcode}.{category}"))317}318}319320impl VecAluOpRRRImm5 {321pub fn opcode(&self) -> u32 {322// Vector Opcode3230x57324}325pub fn funct3(&self) -> u32 {326self.category().encode()327}328329pub fn funct6(&self) -> u32 {330// See: https://github.com/riscv/riscv-v-spec/blob/master/inst-table.adoc331match self {332VecAluOpRRRImm5::VslideupVI => 0b001110,333}334}335336pub fn category(&self) -> VecOpCategory {337match self {338VecAluOpRRRImm5::VslideupVI => VecOpCategory::OPIVI,339}340}341342pub fn imm_is_unsigned(&self) -> bool {343match self {344VecAluOpRRRImm5::VslideupVI => true,345}346}347}348349impl VecInstOverlapInfo for VecAluOpRRRImm5 {350fn forbids_src_dst_overlaps(&self) -> bool {351match self {352VecAluOpRRRImm5::VslideupVI => true,353}354}355}356357impl fmt::Display for VecAluOpRRRImm5 {358fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {359let mut s = format!("{self:?}");360s.make_ascii_lowercase();361let (opcode, category) = s.split_at(s.len() - 2);362f.write_str(&format!("{opcode}.{category}"))363}364}365366impl VecAluOpRRR {367pub fn opcode(&self) -> u32 {368// Vector Opcode3690x57370}371pub fn funct3(&self) -> u32 {372self.category().encode()373}374pub fn funct6(&self) -> u32 {375// See: https://github.com/riscv/riscv-v-spec/blob/master/inst-table.adoc376match self {377VecAluOpRRR::VaddVV378| VecAluOpRRR::VaddVX379| VecAluOpRRR::VfaddVV380| VecAluOpRRR::VfaddVF => 0b000000,381VecAluOpRRR::VsubVV382| VecAluOpRRR::VsubVX383| VecAluOpRRR::VfsubVV384| VecAluOpRRR::VfsubVF => 0b000010,385VecAluOpRRR::VrsubVX => 0b000011,386VecAluOpRRR::VmulVV | VecAluOpRRR::VmulVX => 0b100101,387VecAluOpRRR::VmulhVV | VecAluOpRRR::VmulhVX => 0b100111,388VecAluOpRRR::VmulhuVV389| VecAluOpRRR::VmulhuVX390| VecAluOpRRR::VfmulVV391| VecAluOpRRR::VfmulVF => 0b100100,392VecAluOpRRR::VsmulVV | VecAluOpRRR::VsmulVX => 0b100111,393VecAluOpRRR::VsllVV | VecAluOpRRR::VsllVX => 0b100101,394VecAluOpRRR::VsrlVV | VecAluOpRRR::VsrlVX => 0b101000,395VecAluOpRRR::VsraVV | VecAluOpRRR::VsraVX => 0b101001,396VecAluOpRRR::VandVV | VecAluOpRRR::VandVX => 0b001001,397VecAluOpRRR::VorVV | VecAluOpRRR::VorVX => 0b001010,398VecAluOpRRR::VxorVV | VecAluOpRRR::VxorVX => 0b001011,399VecAluOpRRR::VminuVV | VecAluOpRRR::VminuVX | VecAluOpRRR::VredminuVS => 0b000100,400VecAluOpRRR::VminVV | VecAluOpRRR::VminVX => 0b000101,401VecAluOpRRR::VmaxuVV | VecAluOpRRR::VmaxuVX | VecAluOpRRR::VredmaxuVS => 0b000110,402VecAluOpRRR::VmaxVV | VecAluOpRRR::VmaxVX => 0b000111,403VecAluOpRRR::VslidedownVX => 0b001111,404VecAluOpRRR::VfrsubVF => 0b100111,405VecAluOpRRR::VmergeVVM406| VecAluOpRRR::VmergeVXM407| VecAluOpRRR::VfmergeVFM408| VecAluOpRRR::VcompressVM => 0b010111,409VecAluOpRRR::VfdivVV410| VecAluOpRRR::VfdivVF411| VecAluOpRRR::VsadduVV412| VecAluOpRRR::VsadduVX => 0b100000,413VecAluOpRRR::VfrdivVF | VecAluOpRRR::VsaddVV | VecAluOpRRR::VsaddVX => 0b100001,414VecAluOpRRR::VfminVV => 0b000100,415VecAluOpRRR::VfmaxVV => 0b000110,416VecAluOpRRR::VssubuVV | VecAluOpRRR::VssubuVX => 0b100010,417VecAluOpRRR::VssubVV | VecAluOpRRR::VssubVX => 0b100011,418VecAluOpRRR::VfsgnjVV | VecAluOpRRR::VfsgnjVF => 0b001000,419VecAluOpRRR::VfsgnjnVV => 0b001001,420VecAluOpRRR::VfsgnjxVV => 0b001010,421VecAluOpRRR::VrgatherVV | VecAluOpRRR::VrgatherVX => 0b001100,422VecAluOpRRR::VwadduVV | VecAluOpRRR::VwadduVX => 0b110000,423VecAluOpRRR::VwaddVV | VecAluOpRRR::VwaddVX => 0b110001,424VecAluOpRRR::VwsubuVV | VecAluOpRRR::VwsubuVX => 0b110010,425VecAluOpRRR::VwsubVV | VecAluOpRRR::VwsubVX => 0b110011,426VecAluOpRRR::VwadduWV | VecAluOpRRR::VwadduWX => 0b110100,427VecAluOpRRR::VwaddWV | VecAluOpRRR::VwaddWX => 0b110101,428VecAluOpRRR::VwsubuWV | VecAluOpRRR::VwsubuWX => 0b110110,429VecAluOpRRR::VwsubWV | VecAluOpRRR::VwsubWX => 0b110111,430VecAluOpRRR::VmseqVV431| VecAluOpRRR::VmseqVX432| VecAluOpRRR::VmfeqVV433| VecAluOpRRR::VmfeqVF => 0b011000,434VecAluOpRRR::VmsneVV435| VecAluOpRRR::VmsneVX436| VecAluOpRRR::VmfleVV437| VecAluOpRRR::VmfleVF438| VecAluOpRRR::VmandMM => 0b011001,439VecAluOpRRR::VmsltuVV | VecAluOpRRR::VmsltuVX | VecAluOpRRR::VmorMM => 0b011010,440VecAluOpRRR::VmsltVV441| VecAluOpRRR::VmsltVX442| VecAluOpRRR::VmfltVV443| VecAluOpRRR::VmfltVF => 0b011011,444VecAluOpRRR::VmsleuVV445| VecAluOpRRR::VmsleuVX446| VecAluOpRRR::VmfneVV447| VecAluOpRRR::VmfneVF => 0b011100,448VecAluOpRRR::VmsleVV449| VecAluOpRRR::VmsleVX450| VecAluOpRRR::VmfgtVF451| VecAluOpRRR::VmnandMM => 0b011101,452VecAluOpRRR::VmsgtuVX | VecAluOpRRR::VmnorMM => 0b011110,453VecAluOpRRR::VmsgtVX | VecAluOpRRR::VmfgeVF => 0b011111,454}455}456457pub fn category(&self) -> VecOpCategory {458match self {459VecAluOpRRR::VaddVV460| VecAluOpRRR::VsaddVV461| VecAluOpRRR::VsadduVV462| VecAluOpRRR::VsubVV463| VecAluOpRRR::VssubVV464| VecAluOpRRR::VssubuVV465| VecAluOpRRR::VsmulVV466| VecAluOpRRR::VsllVV467| VecAluOpRRR::VsrlVV468| VecAluOpRRR::VsraVV469| VecAluOpRRR::VandVV470| VecAluOpRRR::VorVV471| VecAluOpRRR::VxorVV472| VecAluOpRRR::VminuVV473| VecAluOpRRR::VminVV474| VecAluOpRRR::VmaxuVV475| VecAluOpRRR::VmaxVV476| VecAluOpRRR::VmergeVVM477| VecAluOpRRR::VrgatherVV478| VecAluOpRRR::VmseqVV479| VecAluOpRRR::VmsneVV480| VecAluOpRRR::VmsltuVV481| VecAluOpRRR::VmsltVV482| VecAluOpRRR::VmsleuVV483| VecAluOpRRR::VmsleVV => VecOpCategory::OPIVV,484VecAluOpRRR::VwaddVV485| VecAluOpRRR::VwaddWV486| VecAluOpRRR::VwadduVV487| VecAluOpRRR::VwadduWV488| VecAluOpRRR::VwsubVV489| VecAluOpRRR::VwsubWV490| VecAluOpRRR::VwsubuVV491| VecAluOpRRR::VwsubuWV492| VecAluOpRRR::VmulVV493| VecAluOpRRR::VmulhVV494| VecAluOpRRR::VmulhuVV495| VecAluOpRRR::VredmaxuVS496| VecAluOpRRR::VredminuVS497| VecAluOpRRR::VcompressVM498| VecAluOpRRR::VmandMM499| VecAluOpRRR::VmorMM500| VecAluOpRRR::VmnandMM501| VecAluOpRRR::VmnorMM => VecOpCategory::OPMVV,502VecAluOpRRR::VwaddVX503| VecAluOpRRR::VwadduVX504| VecAluOpRRR::VwadduWX505| VecAluOpRRR::VwaddWX506| VecAluOpRRR::VwsubVX507| VecAluOpRRR::VwsubuVX508| VecAluOpRRR::VwsubuWX509| VecAluOpRRR::VwsubWX510| VecAluOpRRR::VmulVX511| VecAluOpRRR::VmulhVX512| VecAluOpRRR::VmulhuVX => VecOpCategory::OPMVX,513VecAluOpRRR::VaddVX514| VecAluOpRRR::VsaddVX515| VecAluOpRRR::VsadduVX516| VecAluOpRRR::VsubVX517| VecAluOpRRR::VssubVX518| VecAluOpRRR::VssubuVX519| VecAluOpRRR::VrsubVX520| VecAluOpRRR::VsmulVX521| VecAluOpRRR::VsllVX522| VecAluOpRRR::VsrlVX523| VecAluOpRRR::VsraVX524| VecAluOpRRR::VandVX525| VecAluOpRRR::VorVX526| VecAluOpRRR::VxorVX527| VecAluOpRRR::VminuVX528| VecAluOpRRR::VminVX529| VecAluOpRRR::VmaxuVX530| VecAluOpRRR::VmaxVX531| VecAluOpRRR::VslidedownVX532| VecAluOpRRR::VmergeVXM533| VecAluOpRRR::VrgatherVX534| VecAluOpRRR::VmseqVX535| VecAluOpRRR::VmsneVX536| VecAluOpRRR::VmsltuVX537| VecAluOpRRR::VmsltVX538| VecAluOpRRR::VmsleuVX539| VecAluOpRRR::VmsleVX540| VecAluOpRRR::VmsgtuVX541| VecAluOpRRR::VmsgtVX => VecOpCategory::OPIVX,542VecAluOpRRR::VfaddVV543| VecAluOpRRR::VfsubVV544| VecAluOpRRR::VfmulVV545| VecAluOpRRR::VfdivVV546| VecAluOpRRR::VfmaxVV547| VecAluOpRRR::VfminVV548| VecAluOpRRR::VfsgnjVV549| VecAluOpRRR::VfsgnjnVV550| VecAluOpRRR::VfsgnjxVV551| VecAluOpRRR::VmfeqVV552| VecAluOpRRR::VmfneVV553| VecAluOpRRR::VmfltVV554| VecAluOpRRR::VmfleVV => VecOpCategory::OPFVV,555VecAluOpRRR::VfaddVF556| VecAluOpRRR::VfsubVF557| VecAluOpRRR::VfrsubVF558| VecAluOpRRR::VfmulVF559| VecAluOpRRR::VfdivVF560| VecAluOpRRR::VfrdivVF561| VecAluOpRRR::VfmergeVFM562| VecAluOpRRR::VfsgnjVF563| VecAluOpRRR::VmfeqVF564| VecAluOpRRR::VmfneVF565| VecAluOpRRR::VmfltVF566| VecAluOpRRR::VmfleVF567| VecAluOpRRR::VmfgtVF568| VecAluOpRRR::VmfgeVF => VecOpCategory::OPFVF,569}570}571572// vs1 is the only variable source, vs2 is fixed.573pub fn vs1_regclass(&self) -> RegClass {574match self.category() {575VecOpCategory::OPIVV | VecOpCategory::OPFVV | VecOpCategory::OPMVV => RegClass::Vector,576VecOpCategory::OPIVX | VecOpCategory::OPMVX => RegClass::Int,577VecOpCategory::OPFVF => RegClass::Float,578_ => unreachable!(),579}580}581}582583impl VecInstOverlapInfo for VecAluOpRRR {584fn forbids_src_dst_overlaps(&self) -> bool {585match self {586VecAluOpRRR::VrgatherVV587| VecAluOpRRR::VrgatherVX588| VecAluOpRRR::VcompressVM589| VecAluOpRRR::VwadduVV590| VecAluOpRRR::VwadduVX591| VecAluOpRRR::VwaddVV592| VecAluOpRRR::VwaddVX593| VecAluOpRRR::VwadduWV594| VecAluOpRRR::VwadduWX595| VecAluOpRRR::VwaddWV596| VecAluOpRRR::VwaddWX597| VecAluOpRRR::VwsubuVV598| VecAluOpRRR::VwsubuVX599| VecAluOpRRR::VwsubVV600| VecAluOpRRR::VwsubVX601| VecAluOpRRR::VwsubuWV602| VecAluOpRRR::VwsubuWX603| VecAluOpRRR::VwsubWV604| VecAluOpRRR::VwsubWX => true,605_ => false,606}607}608609// Only mask writing operations, and reduction operations (`vred*`) allow mask / dst overlaps.610fn forbids_mask_dst_overlaps(&self) -> bool {611match self {612VecAluOpRRR::VredmaxuVS613| VecAluOpRRR::VredminuVS614| VecAluOpRRR::VmandMM615| VecAluOpRRR::VmorMM616| VecAluOpRRR::VmnandMM617| VecAluOpRRR::VmnorMM618| VecAluOpRRR::VmseqVX619| VecAluOpRRR::VmsneVX620| VecAluOpRRR::VmsltuVX621| VecAluOpRRR::VmsltVX622| VecAluOpRRR::VmsleuVX623| VecAluOpRRR::VmsleVX624| VecAluOpRRR::VmsgtuVX625| VecAluOpRRR::VmsgtVX626| VecAluOpRRR::VmfeqVV627| VecAluOpRRR::VmfneVV628| VecAluOpRRR::VmfltVV629| VecAluOpRRR::VmfleVV630| VecAluOpRRR::VmfeqVF631| VecAluOpRRR::VmfneVF632| VecAluOpRRR::VmfltVF633| VecAluOpRRR::VmfleVF634| VecAluOpRRR::VmfgtVF635| VecAluOpRRR::VmfgeVF => false,636_ => true,637}638}639}640641impl fmt::Display for VecAluOpRRR {642fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {643let suffix_length = match self {644VecAluOpRRR::VmergeVVM | VecAluOpRRR::VmergeVXM | VecAluOpRRR::VfmergeVFM => 3,645_ => 2,646};647648let mut s = format!("{self:?}");649s.make_ascii_lowercase();650let (opcode, category) = s.split_at(s.len() - suffix_length);651f.write_str(&format!("{opcode}.{category}"))652}653}654655impl VecAluOpRRImm5 {656pub fn opcode(&self) -> u32 {657// Vector Opcode6580x57659}660pub fn funct3(&self) -> u32 {661self.category().encode()662}663664pub fn funct6(&self) -> u32 {665// See: https://github.com/riscv/riscv-v-spec/blob/master/inst-table.adoc666match self {667VecAluOpRRImm5::VaddVI => 0b000000,668VecAluOpRRImm5::VrsubVI => 0b000011,669VecAluOpRRImm5::VsllVI => 0b100101,670VecAluOpRRImm5::VsrlVI => 0b101000,671VecAluOpRRImm5::VsraVI => 0b101001,672VecAluOpRRImm5::VandVI => 0b001001,673VecAluOpRRImm5::VorVI => 0b001010,674VecAluOpRRImm5::VxorVI => 0b001011,675VecAluOpRRImm5::VslidedownVI => 0b001111,676VecAluOpRRImm5::VssrlVI => 0b101010,677VecAluOpRRImm5::VmergeVIM => 0b010111,678VecAluOpRRImm5::VsadduVI => 0b100000,679VecAluOpRRImm5::VsaddVI => 0b100001,680VecAluOpRRImm5::VrgatherVI => 0b001100,681VecAluOpRRImm5::VmvrV => 0b100111,682VecAluOpRRImm5::VnclipWI => 0b101111,683VecAluOpRRImm5::VnclipuWI => 0b101110,684VecAluOpRRImm5::VmseqVI => 0b011000,685VecAluOpRRImm5::VmsneVI => 0b011001,686VecAluOpRRImm5::VmsleuVI => 0b011100,687VecAluOpRRImm5::VmsleVI => 0b011101,688VecAluOpRRImm5::VmsgtuVI => 0b011110,689VecAluOpRRImm5::VmsgtVI => 0b011111,690}691}692693pub fn category(&self) -> VecOpCategory {694match self {695VecAluOpRRImm5::VaddVI696| VecAluOpRRImm5::VrsubVI697| VecAluOpRRImm5::VsllVI698| VecAluOpRRImm5::VsrlVI699| VecAluOpRRImm5::VsraVI700| VecAluOpRRImm5::VandVI701| VecAluOpRRImm5::VorVI702| VecAluOpRRImm5::VxorVI703| VecAluOpRRImm5::VssrlVI704| VecAluOpRRImm5::VslidedownVI705| VecAluOpRRImm5::VmergeVIM706| VecAluOpRRImm5::VsadduVI707| VecAluOpRRImm5::VsaddVI708| VecAluOpRRImm5::VrgatherVI709| VecAluOpRRImm5::VmvrV710| VecAluOpRRImm5::VnclipWI711| VecAluOpRRImm5::VnclipuWI712| VecAluOpRRImm5::VmseqVI713| VecAluOpRRImm5::VmsneVI714| VecAluOpRRImm5::VmsleuVI715| VecAluOpRRImm5::VmsleVI716| VecAluOpRRImm5::VmsgtuVI717| VecAluOpRRImm5::VmsgtVI => VecOpCategory::OPIVI,718}719}720721pub fn imm_is_unsigned(&self) -> bool {722match self {723VecAluOpRRImm5::VsllVI724| VecAluOpRRImm5::VsrlVI725| VecAluOpRRImm5::VssrlVI726| VecAluOpRRImm5::VsraVI727| VecAluOpRRImm5::VslidedownVI728| VecAluOpRRImm5::VrgatherVI729| VecAluOpRRImm5::VmvrV730| VecAluOpRRImm5::VnclipWI731| VecAluOpRRImm5::VnclipuWI => true,732VecAluOpRRImm5::VaddVI733| VecAluOpRRImm5::VrsubVI734| VecAluOpRRImm5::VandVI735| VecAluOpRRImm5::VorVI736| VecAluOpRRImm5::VxorVI737| VecAluOpRRImm5::VmergeVIM738| VecAluOpRRImm5::VsadduVI739| VecAluOpRRImm5::VsaddVI740| VecAluOpRRImm5::VmseqVI741| VecAluOpRRImm5::VmsneVI742| VecAluOpRRImm5::VmsleuVI743| VecAluOpRRImm5::VmsleVI744| VecAluOpRRImm5::VmsgtuVI745| VecAluOpRRImm5::VmsgtVI => false,746}747}748}749750impl VecInstOverlapInfo for VecAluOpRRImm5 {751fn forbids_src_dst_overlaps(&self) -> bool {752match self {753VecAluOpRRImm5::VrgatherVI => true,754_ => false,755}756}757758// Only mask writing operations, and reduction operations (`vred*`) allow mask / dst overlaps.759fn forbids_mask_dst_overlaps(&self) -> bool {760match self {761VecAluOpRRImm5::VmseqVI762| VecAluOpRRImm5::VmsneVI763| VecAluOpRRImm5::VmsleuVI764| VecAluOpRRImm5::VmsleVI765| VecAluOpRRImm5::VmsgtuVI766| VecAluOpRRImm5::VmsgtVI => false,767_ => true,768}769}770}771772impl fmt::Display for VecAluOpRRImm5 {773fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {774let suffix_length = match self {775VecAluOpRRImm5::VmergeVIM => 3,776_ => 2,777};778779let mut s = format!("{self:?}");780s.make_ascii_lowercase();781let (opcode, category) = s.split_at(s.len() - suffix_length);782f.write_str(&format!("{opcode}.{category}"))783}784}785786impl VecAluOpRR {787pub fn opcode(&self) -> u32 {788// Vector Opcode7890x57790}791792pub fn funct3(&self) -> u32 {793self.category().encode()794}795796pub fn funct6(&self) -> u32 {797// See: https://github.com/riscv/riscv-v-spec/blob/master/inst-table.adoc798match self {799VecAluOpRR::VmvSX | VecAluOpRR::VmvXS | VecAluOpRR::VfmvSF | VecAluOpRR::VfmvFS => {8000b010000801}802VecAluOpRR::VzextVF2803| VecAluOpRR::VzextVF4804| VecAluOpRR::VzextVF8805| VecAluOpRR::VsextVF2806| VecAluOpRR::VsextVF4807| VecAluOpRR::VsextVF8 => 0b010010,808VecAluOpRR::VfsqrtV => 0b010011,809VecAluOpRR::VmvVV | VecAluOpRR::VmvVX | VecAluOpRR::VfmvVF => 0b010111,810VecAluOpRR::VfcvtxufV811| VecAluOpRR::VfcvtxfV812| VecAluOpRR::VfcvtrtzxufV813| VecAluOpRR::VfcvtrtzxfV814| VecAluOpRR::VfcvtfxuV815| VecAluOpRR::VfcvtfxV816| VecAluOpRR::VfwcvtffV817| VecAluOpRR::VfncvtffW => 0b010010,818}819}820821pub fn category(&self) -> VecOpCategory {822match self {823VecAluOpRR::VmvSX => VecOpCategory::OPMVX,824VecAluOpRR::VmvXS825| VecAluOpRR::VzextVF2826| VecAluOpRR::VzextVF4827| VecAluOpRR::VzextVF8828| VecAluOpRR::VsextVF2829| VecAluOpRR::VsextVF4830| VecAluOpRR::VsextVF8 => VecOpCategory::OPMVV,831VecAluOpRR::VfmvSF | VecAluOpRR::VfmvVF => VecOpCategory::OPFVF,832VecAluOpRR::VfmvFS833| VecAluOpRR::VfsqrtV834| VecAluOpRR::VfcvtxufV835| VecAluOpRR::VfcvtxfV836| VecAluOpRR::VfcvtrtzxufV837| VecAluOpRR::VfcvtrtzxfV838| VecAluOpRR::VfcvtfxuV839| VecAluOpRR::VfcvtfxV840| VecAluOpRR::VfwcvtffV841| VecAluOpRR::VfncvtffW => VecOpCategory::OPFVV,842VecAluOpRR::VmvVV => VecOpCategory::OPIVV,843VecAluOpRR::VmvVX => VecOpCategory::OPIVX,844}845}846847/// Returns the auxiliary encoding field for the instruction, if any.848pub fn aux_encoding(&self) -> u32 {849match self {850// VRXUNARY0851VecAluOpRR::VmvSX => 0b00000,852// VWXUNARY0853VecAluOpRR::VmvXS => 0b00000,854// VRFUNARY0855VecAluOpRR::VfmvSF => 0b00000,856// VWFUNARY0857VecAluOpRR::VfmvFS => 0b00000,858// VFUNARY1859VecAluOpRR::VfsqrtV => 0b00000,860// VXUNARY0861VecAluOpRR::VzextVF8 => 0b00010,862VecAluOpRR::VsextVF8 => 0b00011,863VecAluOpRR::VzextVF4 => 0b00100,864VecAluOpRR::VsextVF4 => 0b00101,865VecAluOpRR::VzextVF2 => 0b00110,866VecAluOpRR::VsextVF2 => 0b00111,867// VFUNARY0868// single-width converts869VecAluOpRR::VfcvtxufV => 0b00000,870VecAluOpRR::VfcvtxfV => 0b00001,871VecAluOpRR::VfcvtrtzxufV => 0b00110,872VecAluOpRR::VfcvtrtzxfV => 0b00111,873VecAluOpRR::VfcvtfxuV => 0b00010,874VecAluOpRR::VfcvtfxV => 0b00011,875// widening converts876VecAluOpRR::VfwcvtffV => 0b01100,877// narrowing converts878VecAluOpRR::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.881VecAluOpRR::VmvVV | VecAluOpRR::VmvVX | VecAluOpRR::VfmvVF => 0,882}883}884885/// Most of these opcodes have the source register encoded in the VS2 field and886/// the `aux_encoding` field in VS1. However some special snowflakes have it the887/// other way around. As far as I can tell only vmv.v.* are backwards.888pub fn vs_is_vs2_encoded(&self) -> bool {889match self {890VecAluOpRR::VmvXS891| VecAluOpRR::VfmvFS892| VecAluOpRR::VfsqrtV893| VecAluOpRR::VzextVF2894| VecAluOpRR::VzextVF4895| VecAluOpRR::VzextVF8896| VecAluOpRR::VsextVF2897| VecAluOpRR::VsextVF4898| VecAluOpRR::VsextVF8899| VecAluOpRR::VfcvtxufV900| VecAluOpRR::VfcvtxfV901| VecAluOpRR::VfcvtrtzxufV902| VecAluOpRR::VfcvtrtzxfV903| VecAluOpRR::VfcvtfxuV904| VecAluOpRR::VfcvtfxV905| VecAluOpRR::VfwcvtffV906| VecAluOpRR::VfncvtffW => true,907VecAluOpRR::VmvSX908| VecAluOpRR::VfmvSF909| VecAluOpRR::VmvVV910| VecAluOpRR::VmvVX911| VecAluOpRR::VfmvVF => false,912}913}914915pub fn dst_regclass(&self) -> RegClass {916match self {917VecAluOpRR::VfmvSF918| VecAluOpRR::VmvSX919| VecAluOpRR::VmvVV920| VecAluOpRR::VmvVX921| VecAluOpRR::VfmvVF922| VecAluOpRR::VfsqrtV923| VecAluOpRR::VzextVF2924| VecAluOpRR::VzextVF4925| VecAluOpRR::VzextVF8926| VecAluOpRR::VsextVF2927| VecAluOpRR::VsextVF4928| VecAluOpRR::VsextVF8929| VecAluOpRR::VfcvtxufV930| VecAluOpRR::VfcvtxfV931| VecAluOpRR::VfcvtrtzxufV932| VecAluOpRR::VfcvtrtzxfV933| VecAluOpRR::VfcvtfxuV934| VecAluOpRR::VfcvtfxV935| VecAluOpRR::VfwcvtffV936| VecAluOpRR::VfncvtffW => RegClass::Vector,937VecAluOpRR::VmvXS => RegClass::Int,938VecAluOpRR::VfmvFS => RegClass::Float,939}940}941942pub fn src_regclass(&self) -> RegClass {943match self {944VecAluOpRR::VmvXS945| VecAluOpRR::VfmvFS946| VecAluOpRR::VmvVV947| VecAluOpRR::VfsqrtV948| VecAluOpRR::VzextVF2949| VecAluOpRR::VzextVF4950| VecAluOpRR::VzextVF8951| VecAluOpRR::VsextVF2952| VecAluOpRR::VsextVF4953| VecAluOpRR::VsextVF8954| VecAluOpRR::VfcvtxufV955| VecAluOpRR::VfcvtxfV956| VecAluOpRR::VfcvtrtzxufV957| VecAluOpRR::VfcvtrtzxfV958| VecAluOpRR::VfcvtfxuV959| VecAluOpRR::VfcvtfxV960| VecAluOpRR::VfwcvtffV961| VecAluOpRR::VfncvtffW => RegClass::Vector,962VecAluOpRR::VfmvSF | VecAluOpRR::VfmvVF => RegClass::Float,963VecAluOpRR::VmvSX | VecAluOpRR::VmvVX => RegClass::Int,964}965}966}967968impl VecInstOverlapInfo for VecAluOpRR {969fn forbids_src_dst_overlaps(&self) -> bool {970match self {971VecAluOpRR::VzextVF2972| VecAluOpRR::VzextVF4973| VecAluOpRR::VzextVF8974| VecAluOpRR::VsextVF2975| VecAluOpRR::VsextVF4976| VecAluOpRR::VsextVF8977| VecAluOpRR::VfwcvtffV978| VecAluOpRR::VfncvtffW => true,979_ => false,980}981}982}983984impl fmt::Display for VecAluOpRR {985fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {986f.write_str(match self {987VecAluOpRR::VmvSX => "vmv.s.x",988VecAluOpRR::VmvXS => "vmv.x.s",989VecAluOpRR::VfmvSF => "vfmv.s.f",990VecAluOpRR::VfmvFS => "vfmv.f.s",991VecAluOpRR::VfsqrtV => "vfsqrt.v",992VecAluOpRR::VzextVF2 => "vzext.vf2",993VecAluOpRR::VzextVF4 => "vzext.vf4",994VecAluOpRR::VzextVF8 => "vzext.vf8",995VecAluOpRR::VsextVF2 => "vsext.vf2",996VecAluOpRR::VsextVF4 => "vsext.vf4",997VecAluOpRR::VsextVF8 => "vsext.vf8",998VecAluOpRR::VmvVV => "vmv.v.v",999VecAluOpRR::VmvVX => "vmv.v.x",1000VecAluOpRR::VfmvVF => "vfmv.v.f",1001VecAluOpRR::VfcvtxufV => "vfcvt.xu.f.v",1002VecAluOpRR::VfcvtxfV => "vfcvt.x.f.v",1003VecAluOpRR::VfcvtrtzxufV => "vfcvt.rtz.xu.f.v",1004VecAluOpRR::VfcvtrtzxfV => "vfcvt.rtz.x.f.v",1005VecAluOpRR::VfcvtfxuV => "vfcvt.f.xu.v",1006VecAluOpRR::VfcvtfxV => "vfcvt.f.x.v",1007VecAluOpRR::VfwcvtffV => "vfwcvt.f.f.v",1008VecAluOpRR::VfncvtffW => "vfncvt.f.f.w",1009})1010}1011}10121013impl VecAluOpRImm5 {1014pub fn opcode(&self) -> u32 {1015// Vector Opcode10160x571017}1018pub fn funct3(&self) -> u32 {1019self.category().encode()1020}10211022pub fn funct6(&self) -> u32 {1023// See: https://github.com/riscv/riscv-v-spec/blob/master/inst-table.adoc1024match self {1025VecAluOpRImm5::VmvVI => 0b010111,1026}1027}10281029pub fn category(&self) -> VecOpCategory {1030match self {1031VecAluOpRImm5::VmvVI => VecOpCategory::OPIVI,1032}1033}10341035/// Returns the auxiliary encoding field for the instruction, if any.1036pub fn aux_encoding(&self) -> u32 {1037match 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.1040VecAluOpRImm5::VmvVI => 0,1041}1042}1043}10441045impl VecInstOverlapInfo for VecAluOpRImm5 {1046fn forbids_src_dst_overlaps(&self) -> bool {1047match self {1048VecAluOpRImm5::VmvVI => false,1049}1050}1051}10521053impl fmt::Display for VecAluOpRImm5 {1054fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {1055f.write_str(match self {1056VecAluOpRImm5::VmvVI => "vmv.v.i",1057})1058}1059}10601061impl VecAMode {1062pub fn get_base_register(&self) -> Option<Reg> {1063match self {1064VecAMode::UnitStride { base, .. } => base.get_base_register(),1065}1066}10671068pub fn get_operands(&mut self, collector: &mut impl OperandVisitor) {1069match self {1070VecAMode::UnitStride { base, .. } => base.get_operands(collector),1071}1072}10731074/// `mop` field, described in Table 7 of Section 7.2. Vector Load/Store Addressing Modes1075/// https://github.com/riscv/riscv-v-spec/blob/master/v-spec.adoc#72-vector-loadstore-addressing-modes1076pub fn mop(&self) -> u32 {1077match self {1078VecAMode::UnitStride { .. } => 0b00,1079}1080}10811082/// `lumop` field, described in Table 9 of Section 7.2. Vector Load/Store Addressing Modes1083/// https://github.com/riscv/riscv-v-spec/blob/master/v-spec.adoc#72-vector-loadstore-addressing-modes1084pub fn lumop(&self) -> u32 {1085match self {1086VecAMode::UnitStride { .. } => 0b00000,1087}1088}10891090/// `sumop` field, described in Table 10 of Section 7.2. Vector Load/Store Addressing Modes1091/// https://github.com/riscv/riscv-v-spec/blob/master/v-spec.adoc#72-vector-loadstore-addressing-modes1092pub fn sumop(&self) -> u32 {1093match self {1094VecAMode::UnitStride { .. } => 0b00000,1095}1096}10971098/// The `nf[2:0]` field encodes the number of fields in each segment. For regular vector loads and1099/// stores, nf=0, indicating that a single value is moved between a vector register group and memory1100/// at each element position. Larger values in the nf field are used to access multiple contiguous1101/// fields within a segment as described in Section 7.8 Vector Load/Store Segment Instructions.1102///1103/// https://github.com/riscv/riscv-v-spec/blob/master/v-spec.adoc#72-vector-loadstore-addressing-modes1104pub fn nf(&self) -> u32 {1105match self {1106VecAMode::UnitStride { .. } => 0b000,1107}1108}1109}11101111pub trait VecInstOverlapInfo {1112/// § 5.2 Vector Operands states:1113///1114/// A destination vector register group can overlap a source vector register group1115/// only if one of the following holds:1116///1117/// * The destination EEW equals the source EEW.1118///1119/// * The destination EEW is smaller than the source EEW and the overlap is1120/// in the lowest-numbered part of the source register group (e.g., when LMUL=1,1121/// vnsrl.wi v0, v0, 3 is legal, but a destination of v1 is not).1122///1123/// * The destination EEW is greater than the source EEW, the source EMUL is at1124/// least 1, and the overlap is in the highest-numbered part of the destination register1125/// group (e.g., when LMUL=8, vzext.vf4 v0, v6 is legal, but a source of v0, v2, or v4 is not).1126///1127/// For the purpose of determining register group overlap constraints, mask elements have EEW=1.1128fn forbids_src_dst_overlaps(&self) -> bool;11291130/// § 5.3 Vector Masking states:1131///1132/// > The destination vector register group for a masked vector instruction1133/// > cannot overlap the source mask register (v0), unless the destination1134/// > vector register is being written with a mask value (e.g., compares) or1135/// > the scalar result of a reduction. These instruction encodings are reserved.1136///1137/// In almost all instructions we should not allow the mask to be re-used as1138/// a destination register.1139fn forbids_mask_dst_overlaps(&self) -> bool {1140true1141}11421143/// There are two broad categories of overlaps (see above). But we can't represent such1144/// fine grained overlaps to regalloc. So if any of the two come into play we forbid1145/// all source and destination overlaps (including masks).1146fn forbids_overlaps(&self, mask: &VecOpMasking) -> bool {1147self.forbids_src_dst_overlaps() || (mask.is_enabled() && self.forbids_mask_dst_overlaps())1148}1149}115011511152