diff --git a/src/nouveau/compiler/nak_encode_sm75.rs b/src/nouveau/compiler/nak_encode_sm75.rs index 7099825189a..ea95e3a1dc0 100644 --- a/src/nouveau/compiler/nak_encode_sm75.rs +++ b/src/nouveau/compiler/nak_encode_sm75.rs @@ -321,6 +321,19 @@ impl SM75Instr { ); } + fn encode_fset(&mut self, op: &OpFSet) { + self.encode_alu( + 0x00a, + Some(op.dst), + Some(op.mod_src(0)), + op.mod_src(1), + None, + ); + self.set_float_cmp_op(76..80, op.cmp_op); + self.set_bit(80, false); /* TODO: Denorm mode */ + self.set_field(87..90, 0x7_u8); /* TODO: src predicate */ + } + fn encode_fsetp(&mut self, op: &OpFSetP) { self.encode_alu(0x00b, None, Some(op.mod_src(0)), op.mod_src(1), None); @@ -597,6 +610,7 @@ impl SM75Instr { match &instr.op { Op::FAdd(op) => si.encode_fadd(&op), + Op::FSet(op) => si.encode_fset(&op), Op::FSetP(op) => si.encode_fsetp(&op), Op::IAdd3(op) => si.encode_iadd3(&op), Op::ISetP(op) => si.encode_isetp(&op), diff --git a/src/nouveau/compiler/nak_from_nir.rs b/src/nouveau/compiler/nak_from_nir.rs index 8e296d2e151..43621a51bc7 100644 --- a/src/nouveau/compiler/nak_from_nir.rs +++ b/src/nouveau/compiler/nak_from_nir.rs @@ -161,6 +161,32 @@ impl<'a> ShaderFromNir<'a> { saturate: true, }))); } + nir_op_fsign => { + let lz = self.alloc_ssa(RegFile::GPR, 1); + self.instrs.push(Instr::new_fset( + lz, + FloatCmpOp::OrdLt, + srcs[0].into(), + Src::Zero.into(), + )); + + let gz = self.alloc_ssa(RegFile::GPR, 1); + self.instrs.push(Instr::new_fset( + gz, + FloatCmpOp::OrdGt, + srcs[0].into(), + Src::Zero.into(), + )); + + self.instrs.push(Instr::new_fadd( + dst, + gz.into(), + ModSrc { + src: lz, + src_mod: SrcMod::FNeg, + }, + )); + } nir_op_i2f32 => { self.instrs.push(Instr::new_i2f(dst, srcs[0])); } diff --git a/src/nouveau/compiler/nak_ir.rs b/src/nouveau/compiler/nak_ir.rs index 7d730788be8..33cb746dba0 100644 --- a/src/nouveau/compiler/nak_ir.rs +++ b/src/nouveau/compiler/nak_ir.rs @@ -835,6 +835,28 @@ impl fmt::Display for OpFAdd { } } +#[repr(C)] +#[derive(SrcsAsSlice, DstsAsSlice, SrcModsAsSlice)] +pub struct OpFSet { + pub dst: Dst, + pub cmp_op: FloatCmpOp, + pub srcs: [Src; 2], + pub src_mods: [SrcMod; 2], +} + +impl fmt::Display for OpFSet { + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { + write!( + f, + "FSET.{} {} {{ {}, {} }}", + self.cmp_op, + self.dst, + self.mod_src(0), + self.mod_src(1), + ) + } +} + #[repr(C)] #[derive(SrcsAsSlice, DstsAsSlice, SrcModsAsSlice)] pub struct OpFSetP { @@ -1249,6 +1271,7 @@ impl fmt::Display for OpFSOut { #[derive(Display, DstsAsSlice, SrcsAsSlice)] pub enum Op { FAdd(OpFAdd), + FSet(OpFSet), FSetP(OpFSetP), IAdd3(OpIAdd3), ISetP(OpISetP), @@ -1445,6 +1468,20 @@ impl Instr { })) } + pub fn new_fset( + dst: Dst, + cmp_op: FloatCmpOp, + x: ModSrc, + y: ModSrc, + ) -> Instr { + Instr::new(Op::FSet(OpFSet { + dst: dst, + cmp_op: cmp_op, + srcs: [x.src, y.src], + src_mods: [x.src_mod, y.src_mod], + })) + } + pub fn new_fsetp( dst: Dst, cmp_op: FloatCmpOp, @@ -1636,6 +1673,7 @@ impl Instr { pub fn get_latency(&self) -> Option { match self.op { Op::FAdd(_) + | Op::FSet(_) | Op::FSetP(_) | Op::IAdd3(_) | Op::Lop3(_)