diff --git a/src/nouveau/compiler/nak/api.rs b/src/nouveau/compiler/nak/api.rs index 317a53eaf2c..9c5b439d664 100644 --- a/src/nouveau/compiler/nak/api.rs +++ b/src/nouveau/compiler/nak/api.rs @@ -138,6 +138,7 @@ fn nir_options(dev: &nv_device_info) -> nir_shader_compiler_options { op.has_fmulz_no_denorms = true; op.has_find_msb_rev = true; op.has_pack_half_2x16_rtz = true; + op.has_bfm = dev.sm >= 70; op.max_unroll_iterations = 32; diff --git a/src/nouveau/compiler/nak/encode_sm70.rs b/src/nouveau/compiler/nak/encode_sm70.rs index 96584b9fefa..fc927a2fe4d 100644 --- a/src/nouveau/compiler/nak/encode_sm70.rs +++ b/src/nouveau/compiler/nak/encode_sm70.rs @@ -643,6 +643,18 @@ impl SM70Instr { self.set_pred_src(87..90, 90, op.accum); } + fn encode_bmsk(&mut self, op: &OpBMsk) { + self.encode_alu( + 0x01b, + Some(op.dst), + ALUSrc::from_src(&op.pos), + ALUSrc::from_src(&op.width), + ALUSrc::None, + ); + + self.set_bit(75, op.wrap); + } + fn encode_brev(&mut self, op: &OpBRev) { self.encode_alu( 0x101, @@ -1995,6 +2007,7 @@ impl SM70Instr { Op::DMul(op) => si.encode_dmul(&op), Op::DSetP(op) => si.encode_dsetp(&op), Op::MuFu(op) => si.encode_mufu(&op), + Op::BMsk(op) => si.encode_bmsk(&op), Op::BRev(op) => si.encode_brev(&op), Op::Flo(op) => si.encode_flo(&op), Op::IAbs(op) => si.encode_iabs(&op), diff --git a/src/nouveau/compiler/nak/from_nir.rs b/src/nouveau/compiler/nak/from_nir.rs index 5e050741e85..e1846806ef0 100644 --- a/src/nouveau/compiler/nak/from_nir.rs +++ b/src/nouveau/compiler/nak/from_nir.rs @@ -525,6 +525,16 @@ impl<'a> ShaderFromNir<'a> { [lo[0], hi[0]].into() } nir_op_bcsel => b.sel(srcs[0], srcs[1], srcs[2]), + nir_op_bfm => { + let dst = b.alloc_ssa(RegFile::GPR, 1); + b.push_op(OpBMsk { + dst: dst.into(), + pos: srcs[1], + width: srcs[0], + wrap: true, + }); + dst + } nir_op_bit_count => { let dst = b.alloc_ssa(RegFile::GPR, 1); b.push_op(OpPopC { diff --git a/src/nouveau/compiler/nak/ir.rs b/src/nouveau/compiler/nak/ir.rs index 2cd4a9889f6..248e444591b 100644 --- a/src/nouveau/compiler/nak/ir.rs +++ b/src/nouveau/compiler/nak/ir.rs @@ -2578,6 +2578,28 @@ impl DisplayOp for OpDSetP { } impl_display_for_op!(OpDSetP); +#[repr(C)] +#[derive(SrcsAsSlice, DstsAsSlice)] +pub struct OpBMsk { + pub dst: Dst, + + #[src_type(ALU)] + pub pos: Src, + + #[src_type(ALU)] + pub width: Src, + + pub wrap: bool, +} + +impl DisplayOp for OpBMsk { + fn fmt_op(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { + let wrap = if self.wrap { ".wrap" } else { ".clamp" }; + write!(f, "bmsk{} {} {}", wrap, self.pos, self.width) + } +} +impl_display_for_op!(OpBMsk); + #[repr(C)] #[derive(SrcsAsSlice, DstsAsSlice)] pub struct OpBRev { @@ -4727,6 +4749,7 @@ pub enum Op { DMnMx(OpDMnMx), DMul(OpDMul), DSetP(OpDSetP), + BMsk(OpBMsk), BRev(OpBRev), Flo(OpFlo), IAbs(OpIAbs), @@ -5172,7 +5195,8 @@ impl Instr { // Integer ALU Op::BRev(_) | Op::Flo(_) | Op::PopC(_) => false, - Op::IAbs(_) + Op::BMsk(_) + | Op::IAbs(_) | Op::INeg(_) | Op::IAdd2(_) | Op::IAdd3(_) diff --git a/src/nouveau/compiler/nak/legalize.rs b/src/nouveau/compiler/nak/legalize.rs index e3c9adfa687..f751c55a3fd 100644 --- a/src/nouveau/compiler/nak/legalize.rs +++ b/src/nouveau/compiler/nak/legalize.rs @@ -432,7 +432,8 @@ fn legalize_sm70_instr( } copy_alu_src_if_not_reg(b, src0, SrcType::F64); } - Op::BRev(_) | Op::Flo(_) | Op::IAbs(_) | Op::INeg(_) => (), + Op::BMsk(_) | Op::BRev(_) | Op::Flo(_) => (), + 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);