diff --git a/src/nouveau/compiler/nak_encode_sm75.rs b/src/nouveau/compiler/nak_encode_sm75.rs index 25be2d56e92..86b6b5de50a 100644 --- a/src/nouveau/compiler/nak_encode_sm75.rs +++ b/src/nouveau/compiler/nak_encode_sm75.rs @@ -1504,6 +1504,21 @@ impl SM75Instr { ); } + 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) + } + pub fn encode( instr: &Instr, sm: u8, @@ -1564,6 +1579,7 @@ impl SM75Instr { 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), _ => panic!("Unhandled instruction"), } diff --git a/src/nouveau/compiler/nak_from_nir.rs b/src/nouveau/compiler/nak_from_nir.rs index 764895234ba..1528530ad21 100644 --- a/src/nouveau/compiler/nak_from_nir.rs +++ b/src/nouveau/compiler/nak_from_nir.rs @@ -224,6 +224,21 @@ impl<'a> ShaderFromNir<'a> { }); dst } + nir_op_find_lsb => { + let tmp = b.alloc_ssa(RegFile::GPR, 1); + b.push_op(OpBrev { + dst: tmp.into(), + src: srcs[0], + }); + let dst = b.alloc_ssa(RegFile::GPR, 1); + b.push_op(OpBFind { + dst: dst.into(), + src: tmp.into(), + signed: alu.op == nir_op_ifind_msb, + return_shift_amount: true, + }); + dst + } nir_op_f2i32 | nir_op_f2u32 => { let src_bits = usize::from(alu.get_src(0).bit_size()); let dst_bits = alu.def.bit_size(); @@ -450,6 +465,16 @@ impl<'a> ShaderFromNir<'a> { b.isetp(IntCmpType::I32, IntCmpOp::Eq, srcs[0], srcs[1]) } } + nir_op_ifind_msb | nir_op_ufind_msb => { + let dst = b.alloc_ssa(RegFile::GPR, 1); + b.push_op(OpBFind { + dst: dst.into(), + src: srcs[0], + signed: alu.op == nir_op_ifind_msb, + return_shift_amount: false, + }); + dst + } nir_op_ige => { b.isetp(IntCmpType::I32, IntCmpOp::Ge, srcs[0], srcs[1]) } diff --git a/src/nouveau/compiler/nak_ir.rs b/src/nouveau/compiler/nak_ir.rs index 48d58082d1f..81ea4dc568e 100644 --- a/src/nouveau/compiler/nak_ir.rs +++ b/src/nouveau/compiler/nak_ir.rs @@ -3165,6 +3165,28 @@ impl fmt::Display for OpBrev { } } +#[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(Display, DstsAsSlice, SrcsAsSlice, FromVariants)] pub enum Op { FAdd(OpFAdd), @@ -3221,6 +3243,7 @@ pub enum Op { FSOut(OpFSOut), PopC(OpPopC), Brev(OpBrev), + BFind(OpBFind), } #[derive(Clone, Copy, Eq, Hash, PartialEq)] @@ -3537,7 +3560,7 @@ impl Instr { | Op::FSOut(_) => { panic!("Not a hardware opcode") } - Op::PopC(_) | Op::Brev(_) => Some(15), + Op::PopC(_) | Op::Brev(_) | Op::BFind(_) => Some(15), } } } diff --git a/src/nouveau/compiler/nak_legalize.rs b/src/nouveau/compiler/nak_legalize.rs index 42e63e3e3fa..b44cd6f0373 100644 --- a/src/nouveau/compiler/nak_legalize.rs +++ b/src/nouveau/compiler/nak_legalize.rs @@ -188,7 +188,8 @@ impl<'a> LegalizeInstr<'a> { | Op::Mov(_) | Op::FRnd(_) | Op::PopC(_) - | Op::Brev(_) => (), + | Op::Brev(_) + | Op::BFind(_) => (), Op::Sel(op) => { let [ref mut src0, ref mut src1] = op.srcs; if !src_is_reg(src0) && src_is_reg(src1) {