diff --git a/src/nouveau/compiler/nak_encode_sm75.rs b/src/nouveau/compiler/nak_encode_sm75.rs index 055d59fbbd5..67134572c2f 100644 --- a/src/nouveau/compiler/nak_encode_sm75.rs +++ b/src/nouveau/compiler/nak_encode_sm75.rs @@ -1481,6 +1481,19 @@ 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) + } + pub fn encode( instr: &Instr, sm: u8, @@ -1539,6 +1552,7 @@ impl SM75Instr { Op::Exit(op) => si.encode_exit(&op), Op::Bar(op) => si.encode_bar(&op), Op::S2R(op) => si.encode_s2r(&op), + Op::PopC(op) => si.encode_popc(&op), _ => panic!("Unhandled instruction"), } diff --git a/src/nouveau/compiler/nak_from_nir.rs b/src/nouveau/compiler/nak_from_nir.rs index 5d542d38517..53e00277842 100644 --- a/src/nouveau/compiler/nak_from_nir.rs +++ b/src/nouveau/compiler/nak_from_nir.rs @@ -208,6 +208,14 @@ impl<'a> ShaderFromNir<'a> { Src::new_imm_u32(0x3f800000), ), nir_op_bcsel => b.sel(srcs[0], srcs[1], srcs[2]), + nir_op_bit_count => { + let dst = b.alloc_ssa(RegFile::GPR, 1); + b.push_op(OpPopC { + dst: dst.into(), + src: srcs[0], + }); + 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(); diff --git a/src/nouveau/compiler/nak_ir.rs b/src/nouveau/compiler/nak_ir.rs index 020f0090f79..beb9e10410a 100644 --- a/src/nouveau/compiler/nak_ir.rs +++ b/src/nouveau/compiler/nak_ir.rs @@ -3135,6 +3135,21 @@ 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,) + } +} + #[derive(Display, DstsAsSlice, SrcsAsSlice, FromVariants)] pub enum Op { FAdd(OpFAdd), @@ -3189,6 +3204,7 @@ pub enum Op { Swap(OpSwap), ParCopy(OpParCopy), FSOut(OpFSOut), + PopC(OpPopC), } #[derive(Clone, Copy, Eq, Hash, PartialEq)] @@ -3505,6 +3521,7 @@ impl Instr { | Op::FSOut(_) => { panic!("Not a hardware opcode") } + Op::PopC(_) => Some(15), } } } diff --git a/src/nouveau/compiler/nak_legalize.rs b/src/nouveau/compiler/nak_legalize.rs index 3aa5d8278a5..2602de141bd 100644 --- a/src/nouveau/compiler/nak_legalize.rs +++ b/src/nouveau/compiler/nak_legalize.rs @@ -182,9 +182,12 @@ impl<'a> LegalizeInstr<'a> { self.mov_src_if_not_reg(&mut op.low, RegFile::GPR); self.mov_src_if_not_reg(&mut op.high, RegFile::GPR); } - Op::F2F(_) | Op::F2I(_) | Op::I2F(_) | Op::Mov(_) | Op::FRnd(_) => { - () - } + Op::F2F(_) + | Op::F2I(_) + | Op::I2F(_) + | Op::Mov(_) + | Op::FRnd(_) + | Op::PopC(_) => (), Op::Sel(op) => { let [ref mut src0, ref mut src1] = op.srcs; if !src_is_reg(src0) && src_is_reg(src1) {