diff --git a/src/nouveau/compiler/nak_encode_sm75.rs b/src/nouveau/compiler/nak_encode_sm75.rs index 87a94bc15e8..a5276c87018 100644 --- a/src/nouveau/compiler/nak_encode_sm75.rs +++ b/src/nouveau/compiler/nak_encode_sm75.rs @@ -540,6 +540,31 @@ impl SM75Instr { ); } + fn encode_brev(&mut self, op: &OpBrev) { + self.encode_alu( + 0x101, + Some(op.dst), + ALUSrc::None, + ALUSrc::from_src(&op.src), + ALUSrc::None, + ); + } + + fn encode_bfind(&mut self, op: &OpBFind) { + self.encode_alu( + 0x100, + Some(op.dst), + ALUSrc::None, + ALUSrc::from_src(&op.src), + ALUSrc::None, + ); + self.set_pred_dst(81..84, Dst::None); + self.set_field(74..75, op.return_shift_amount as u8); + self.set_field(73..74, op.signed as u8); + let not_mod = matches!(op.src.src_mod, SrcMod::BNot); + self.set_field(63..64, not_mod) + } + fn encode_iabs(&mut self, op: &OpIAbs) { self.encode_alu( 0x013, @@ -687,6 +712,19 @@ impl SM75Instr { self.set_pred_src(87..90, 90, SrcRef::False.into()); } + fn encode_popc(&mut self, op: &OpPopC) { + self.encode_alu( + 0x109, + Some(op.dst), + ALUSrc::None, + ALUSrc::from_src(&op.src), + ALUSrc::None, + ); + + let not_mod = matches!(op.src.src_mod, SrcMod::BNot); + self.set_field(63..64, not_mod) + } + fn encode_shf(&mut self, op: &OpShf) { self.encode_alu( 0x019, @@ -794,6 +832,16 @@ impl SM75Instr { self.set_field(72..76, op.quad_lanes); } + fn encode_prmt(&mut self, op: &OpPrmt) { + self.encode_alu( + 0x16, + Some(op.dst), + ALUSrc::from_src(&op.srcs[0]), + ALUSrc::Imm32(op.selection.inner()), + ALUSrc::from_src(&op.srcs[1]), + ); + } + fn encode_sel(&mut self, op: &OpSel) { self.encode_alu( 0x007, @@ -1494,54 +1542,6 @@ impl SM75Instr { self.set_field(72..80, op.idx); } - fn encode_popc(&mut self, op: &OpPopC) { - self.encode_alu( - 0x109, - Some(op.dst), - ALUSrc::None, - ALUSrc::from_src(&op.src), - ALUSrc::None, - ); - - let not_mod = matches!(op.src.src_mod, SrcMod::BNot); - self.set_field(63..64, not_mod) - } - - fn encode_brev(&mut self, op: &OpBrev) { - self.encode_alu( - 0x101, - Some(op.dst), - ALUSrc::None, - ALUSrc::from_src(&op.src), - ALUSrc::None, - ); - } - - fn encode_bfind(&mut self, op: &OpBFind) { - self.encode_alu( - 0x100, - Some(op.dst), - ALUSrc::None, - ALUSrc::from_src(&op.src), - ALUSrc::None, - ); - self.set_pred_dst(81..84, Dst::None); - self.set_field(74..75, op.return_shift_amount as u8); - self.set_field(73..74, op.signed as u8); - let not_mod = matches!(op.src.src_mod, SrcMod::BNot); - self.set_field(63..64, not_mod) - } - - fn encode_prmt(&mut self, op: &OpPrmt) { - self.encode_alu( - 0x16, - Some(op.dst), - ALUSrc::from_src(&op.srcs[0]), - ALUSrc::Imm32(op.selection.inner()), - ALUSrc::from_src(&op.srcs[1]), - ); - } - pub fn encode( instr: &Instr, sm: u8, @@ -1563,6 +1563,8 @@ impl SM75Instr { Op::FSet(op) => si.encode_fset(&op), Op::FSetP(op) => si.encode_fsetp(&op), Op::MuFu(op) => si.encode_mufu(&op), + Op::Brev(op) => si.encode_brev(&op), + Op::BFind(op) => si.encode_bfind(&op), Op::IAbs(op) => si.encode_iabs(&op), Op::IAdd3(op) => si.encode_iadd3(&op), Op::IAdd3X(op) => si.encode_iadd3x(&op), @@ -1571,12 +1573,14 @@ impl SM75Instr { Op::IMnMx(op) => si.encode_imnmx(&op), Op::ISetP(op) => si.encode_isetp(&op), Op::Lop3(op) => si.encode_lop3(&op), + Op::PopC(op) => si.encode_popc(&op), Op::Shf(op) => si.encode_shf(&op), Op::F2F(op) => si.encode_f2f(&op), Op::F2I(op) => si.encode_f2i(&op), Op::I2F(op) => si.encode_i2f(&op), Op::FRnd(op) => si.encode_frnd(&op), Op::Mov(op) => si.encode_mov(&op), + Op::Prmt(op) => si.encode_prmt(&op), Op::Sel(op) => si.encode_sel(&op), Op::PLop3(op) => si.encode_plop3(&op), Op::Tex(op) => si.encode_tex(&op), @@ -1602,10 +1606,6 @@ impl SM75Instr { Op::Bar(op) => si.encode_bar(&op), Op::CS2R(op) => si.encode_cs2r(&op), Op::S2R(op) => si.encode_s2r(&op), - Op::PopC(op) => si.encode_popc(&op), - Op::Brev(op) => si.encode_brev(&op), - Op::BFind(op) => si.encode_bfind(&op), - Op::Prmt(op) => si.encode_prmt(&op), _ => panic!("Unhandled instruction"), } diff --git a/src/nouveau/compiler/nak_ir.rs b/src/nouveau/compiler/nak_ir.rs index c003fb472ed..28fafdd3031 100644 --- a/src/nouveau/compiler/nak_ir.rs +++ b/src/nouveau/compiler/nak_ir.rs @@ -2061,6 +2061,43 @@ impl fmt::Display for OpDAdd { } } +#[repr(C)] +#[derive(SrcsAsSlice, DstsAsSlice)] +pub struct OpBrev { + pub dst: Dst, + + #[src_type(ALU)] + pub src: Src, +} + +impl fmt::Display for OpBrev { + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { + write!(f, "BREV {} {}", self.dst, self.src,) + } +} + +#[repr(C)] +#[derive(SrcsAsSlice, DstsAsSlice)] +pub struct OpBFind { + pub dst: Dst, + + #[src_type(ALU)] + pub src: Src, + + pub signed: bool, + pub return_shift_amount: bool, +} + +impl fmt::Display for OpBFind { + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { + write!(f, "BFIND")?; + if self.return_shift_amount { + write!(f, ".SAMT")?; + } + write!(f, " {} {}", self.dst, self.src) + } +} + #[repr(C)] #[derive(SrcsAsSlice, DstsAsSlice)] pub struct OpIAbs { @@ -2443,6 +2480,130 @@ impl fmt::Display for OpMov { } } +#[derive(Copy, Clone, Debug)] +pub enum PrmtSrc { + Byte0 = 0, + Byte1 = 1, + Byte2 = 2, + Byte3 = 3, + Byte4 = 4, + Byte5 = 5, + Byte6 = 6, + Byte7 = 7, +} + +impl TryFrom for PrmtSrc { + type Error = String; + + fn try_from(value: u32) -> Result { + match value { + 0 => Ok(Self::Byte0), + 1 => Ok(Self::Byte1), + 2 => Ok(Self::Byte2), + 3 => Ok(Self::Byte3), + 4 => Ok(Self::Byte4), + 5 => Ok(Self::Byte5), + 6 => Ok(Self::Byte6), + 7 => Ok(Self::Byte7), + _ => Err(format!("Invalid value {}", value)), + } + } +} + +#[derive(Copy, Clone, Debug)] +pub struct PrmtSelection { + pub src: PrmtSrc, + pub sign_extend: bool, +} + +impl From for [PrmtSelection; 4] { + fn from(value: PrmtSelectionEval) -> Self { + let sel0 = value.0 & 0x7; + let sel1 = (value.0 & 0x70) >> 4; + let sel2 = (value.0 & 0x700) >> 8; + let sel3 = (value.0 & 0x7000) >> 12; + + let sign0 = value.0 & 0x8; + let sign1 = value.0 & 0x80; + let sign2 = value.0 & 0x800; + let sign3 = value.0 & 0x8000; + + [ + PrmtSelection { + src: sel3.try_into().unwrap(), + sign_extend: sign3 != 0, + }, + PrmtSelection { + src: sel2.try_into().unwrap(), + sign_extend: sign2 != 0, + }, + PrmtSelection { + src: sel1.try_into().unwrap(), + sign_extend: sign1 != 0, + }, + PrmtSelection { + src: sel0.try_into().unwrap(), + sign_extend: sign0 != 0, + }, + ] + } +} + +#[derive(Copy, Clone, Debug)] +pub struct PrmtSelectionEval(u32); + +impl PrmtSelectionEval { + pub fn inner(&self) -> u32 { + self.0 + } +} + +impl From<[PrmtSelection; 4]> for PrmtSelectionEval { + fn from(selections: [PrmtSelection; 4]) -> Self { + let mut selection = 0; + + for v in selections { + let src = if v.sign_extend { + v.src as u32 | 0x8 + } else { + v.src as u32 + }; + selection = selection << 4 | src; + } + + Self(selection) + } +} + +#[repr(C)] +#[derive(SrcsAsSlice, DstsAsSlice)] +/// Permutes `srcs` into `dst` using `selection`. +pub struct OpPrmt { + pub dst: Dst, + + #[src_type(ALU)] + pub srcs: [Src; 2], + + pub selection: PrmtSelectionEval, +} + +impl fmt::Display for OpPrmt { + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { + let sel: [PrmtSelection; 4] = self.selection.into(); + write!( + f, + "PRMT {}, {} [{:?}, {:?}, {:?}, {:?}], {}", + self.dst, + self.srcs[0], + sel[0].src, + sel[1].src, + sel[2].src, + sel[3].src, + self.srcs[1], + ) + } +} + #[repr(C)] #[derive(SrcsAsSlice, DstsAsSlice)] pub struct OpSel { @@ -2492,6 +2653,21 @@ impl fmt::Display for OpPLop3 { } } +#[repr(C)] +#[derive(SrcsAsSlice, DstsAsSlice)] +pub struct OpPopC { + pub dst: Dst, + + #[src_type(ALU)] + pub src: Src, +} + +impl fmt::Display for OpPopC { + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { + write!(f, "POPC {} {}", self.dst, self.src,) + } +} + #[repr(C)] #[derive(SrcsAsSlice, DstsAsSlice)] pub struct OpTex { @@ -3431,182 +3607,6 @@ impl fmt::Display for OpFSOut { } } -#[repr(C)] -#[derive(SrcsAsSlice, DstsAsSlice)] -pub struct OpPopC { - pub dst: Dst, - - #[src_type(ALU)] - pub src: Src, -} - -impl fmt::Display for OpPopC { - fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { - write!(f, "POPC {} {}", self.dst, self.src,) - } -} - -#[repr(C)] -#[derive(SrcsAsSlice, DstsAsSlice)] -pub struct OpBrev { - pub dst: Dst, - - #[src_type(ALU)] - pub src: Src, -} - -impl fmt::Display for OpBrev { - fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { - write!(f, "BREV {} {}", self.dst, self.src,) - } -} - -#[repr(C)] -#[derive(SrcsAsSlice, DstsAsSlice)] -pub struct OpBFind { - pub dst: Dst, - - #[src_type(ALU)] - pub src: Src, - - pub signed: bool, - pub return_shift_amount: bool, -} - -impl fmt::Display for OpBFind { - fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { - write!(f, "BFIND")?; - if self.return_shift_amount { - write!(f, ".SAMT")?; - } - write!(f, " {} {}", self.dst, self.src) - } -} - -#[derive(Copy, Clone, Debug)] -pub enum PrmtSrc { - Byte0 = 0, - Byte1 = 1, - Byte2 = 2, - Byte3 = 3, - Byte4 = 4, - Byte5 = 5, - Byte6 = 6, - Byte7 = 7, -} - -impl TryFrom for PrmtSrc { - type Error = String; - - fn try_from(value: u32) -> Result { - match value { - 0 => Ok(Self::Byte0), - 1 => Ok(Self::Byte1), - 2 => Ok(Self::Byte2), - 3 => Ok(Self::Byte3), - 4 => Ok(Self::Byte4), - 5 => Ok(Self::Byte5), - 6 => Ok(Self::Byte6), - 7 => Ok(Self::Byte7), - _ => Err(format!("Invalid value {}", value)), - } - } -} - -#[derive(Copy, Clone, Debug)] -pub struct PrmtSelection { - pub src: PrmtSrc, - pub sign_extend: bool, -} - -impl From for [PrmtSelection; 4] { - fn from(value: PrmtSelectionEval) -> Self { - let sel0 = value.0 & 0x7; - let sel1 = (value.0 & 0x70) >> 4; - let sel2 = (value.0 & 0x700) >> 8; - let sel3 = (value.0 & 0x7000) >> 12; - - let sign0 = value.0 & 0x8; - let sign1 = value.0 & 0x80; - let sign2 = value.0 & 0x800; - let sign3 = value.0 & 0x8000; - - [ - PrmtSelection { - src: sel3.try_into().unwrap(), - sign_extend: sign3 != 0, - }, - PrmtSelection { - src: sel2.try_into().unwrap(), - sign_extend: sign2 != 0, - }, - PrmtSelection { - src: sel1.try_into().unwrap(), - sign_extend: sign1 != 0, - }, - PrmtSelection { - src: sel0.try_into().unwrap(), - sign_extend: sign0 != 0, - }, - ] - } -} - -#[derive(Copy, Clone, Debug)] -pub struct PrmtSelectionEval(u32); - -impl PrmtSelectionEval { - pub fn inner(&self) -> u32 { - self.0 - } -} - -impl From<[PrmtSelection; 4]> for PrmtSelectionEval { - fn from(selections: [PrmtSelection; 4]) -> Self { - let mut selection = 0; - - for v in selections { - let src = if v.sign_extend { - v.src as u32 | 0x8 - } else { - v.src as u32 - }; - selection = selection << 4 | src; - } - - Self(selection) - } -} - -#[repr(C)] -#[derive(SrcsAsSlice, DstsAsSlice)] -/// Permutes `srcs` into `dst` using `selection`. -pub struct OpPrmt { - pub dst: Dst, - - #[src_type(ALU)] - pub srcs: [Src; 2], - - pub selection: PrmtSelectionEval, -} - -impl fmt::Display for OpPrmt { - fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { - let sel: [PrmtSelection; 4] = self.selection.into(); - write!( - f, - "PRMT {}, {} [{:?}, {:?}, {:?}, {:?}], {}", - self.dst, - self.srcs[0], - sel[0].src, - sel[1].src, - sel[2].src, - sel[3].src, - self.srcs[1], - ) - } -} - #[derive(Display, DstsAsSlice, SrcsAsSlice, FromVariants)] pub enum Op { FAdd(OpFAdd), @@ -3617,6 +3617,8 @@ pub enum Op { FSet(OpFSet), FSetP(OpFSetP), DAdd(OpDAdd), + Brev(OpBrev), + BFind(OpBFind), IAbs(OpIAbs), INeg(OpINeg), IAdd3(OpIAdd3), @@ -3626,12 +3628,14 @@ pub enum Op { IMnMx(OpIMnMx), ISetP(OpISetP), Lop3(OpLop3), + PopC(OpPopC), Shf(OpShf), F2F(OpF2F), F2I(OpF2I), I2F(OpI2F), FRnd(OpFRnd), Mov(OpMov), + Prmt(OpPrmt), Sel(OpSel), PLop3(OpPLop3), Tex(OpTex), @@ -3664,10 +3668,6 @@ pub enum Op { Swap(OpSwap), ParCopy(OpParCopy), FSOut(OpFSOut), - PopC(OpPopC), - Brev(OpBrev), - BFind(OpBFind), - Prmt(OpPrmt), } #[derive(Clone, Copy, Eq, Hash, PartialEq)] diff --git a/src/nouveau/compiler/nak_legalize.rs b/src/nouveau/compiler/nak_legalize.rs index c8e1fb1178d..0b39fd6f2cd 100644 --- a/src/nouveau/compiler/nak_legalize.rs +++ b/src/nouveau/compiler/nak_legalize.rs @@ -103,7 +103,7 @@ fn legalize_instr(b: &mut impl SSABuilder, instr: &mut Instr) { swap_srcs_if_not_reg(src0, src1); copy_src_if_not_reg(b, src0, RegFile::GPR); } - Op::IAbs(_) | Op::INeg(_) => (), /* Nothing to do */ + Op::Brev(_) | Op::BFind(_) | Op::IAbs(_) | Op::INeg(_) => (), Op::IAdd3(op) => { let [ref mut src0, ref mut src1, ref mut src2] = op.srcs; swap_srcs_if_not_reg(src0, src1); @@ -179,6 +179,7 @@ fn legalize_instr(b: &mut impl SSABuilder, instr: &mut Instr) { copy_src_if_not_reg(b, src0, RegFile::GPR); copy_src_if_not_reg(b, src2, RegFile::GPR); } + Op::PopC(_) => (), Op::Shf(op) => { copy_src_if_not_reg(b, &mut op.low, RegFile::GPR); copy_src_if_not_reg(b, &mut op.high, RegFile::GPR); @@ -188,9 +189,6 @@ fn legalize_instr(b: &mut impl SSABuilder, instr: &mut Instr) { | Op::I2F(_) | Op::Mov(_) | Op::FRnd(_) - | Op::PopC(_) - | Op::Brev(_) - | Op::BFind(_) | Op::Prmt(_) => (), Op::Sel(op) => { let [ref mut src0, ref mut src1] = op.srcs;