diff --git a/src/nouveau/compiler/nak/hw_tests.rs b/src/nouveau/compiler/nak/hw_tests.rs index 640c9ebc3ce..f3ced38c557 100644 --- a/src/nouveau/compiler/nak/hw_tests.rs +++ b/src/nouveau/compiler/nak/hw_tests.rs @@ -515,6 +515,30 @@ pub fn test_foldable_op(op: impl Foldable + Clone + Into) { test_foldable_op_with(op, &mut |_| a.get_u32()); } +#[test] +fn test_op_flo() { + for i in 0..4 { + let op = OpFlo { + dst: Dst::None, + src: 0.into(), + signed: i & 0x1 != 0, + return_shift_amount: i & 0x2 != 0, + }; + + let mut a = Acorn::new(); + test_foldable_op_with(op, &mut |_| { + let x = a.get_uint(36); + let signed = x & (1 << 32) != 0; + let shift = x >> 33; + if signed { + ((x as i32) >> shift) as u32 + } else { + (x as u32) >> shift + } + }); + } +} + #[test] fn test_op_iabs() { if RunSingleton::get().sm.sm() >= 70 { diff --git a/src/nouveau/compiler/nak/ir.rs b/src/nouveau/compiler/nak/ir.rs index fe39d7760cb..77370a9be20 100644 --- a/src/nouveau/compiler/nak/ir.rs +++ b/src/nouveau/compiler/nak/ir.rs @@ -3225,7 +3225,7 @@ impl DisplayOp for OpBfe { impl_display_for_op!(OpBfe); #[repr(C)] -#[derive(SrcsAsSlice, DstsAsSlice)] +#[derive(Clone, SrcsAsSlice, DstsAsSlice)] pub struct OpFlo { #[dst_type(GPR)] pub dst: Dst, @@ -3237,6 +3237,23 @@ pub struct OpFlo { pub return_shift_amount: bool, } +impl Foldable for OpFlo { + fn fold(&self, _sm: &dyn ShaderModel, f: &mut OpFoldData<'_>) { + let src = f.get_u32_src(self, &self.src); + let leading = if self.signed && (src & 0x80000000) != 0 { + (!src).leading_zeros() + } else { + src.leading_zeros() + }; + let dst = if self.return_shift_amount { + leading + } else { + 31 - leading + }; + f.set_u32_dst(self, &self.dst, dst); + } +} + impl DisplayOp for OpFlo { fn fmt_op(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { write!(f, "flo")?;