diff --git a/src/nouveau/compiler/nak_encode_sm75.rs b/src/nouveau/compiler/nak_encode_sm75.rs index d755422158f..77582a2cb5b 100644 --- a/src/nouveau/compiler/nak_encode_sm75.rs +++ b/src/nouveau/compiler/nak_encode_sm75.rs @@ -357,6 +357,24 @@ impl SM75Instr { self.set_bit(80, false /* HI */); } + fn encode_i2f(&mut self, op: &OpI2F) { + self.encode_alu(0x106, Some(op.dst), None, op.src.into(), None); + + self.set_field(60..62, 0_u8); /* TODO: subop */ + self.set_bit(74, op.src_type.is_signed()); + self.set_field(75..77, op.dst_type.bytes().trailing_zeros()); + self.set_field( + 78..80, + match op.rnd_mode { + FRndMode::NearestEven => 0_u8, + FRndMode::NegInf => 1_u8, + FRndMode::PosInf => 2_u8, + FRndMode::Zero => 3_u8, + }, + ); + self.set_field(84..86, op.src_type.bytes().trailing_zeros()); + } + fn encode_mov(&mut self, op: &OpMov) { self.encode_alu(0x002, Some(op.dst), None, op.src.into(), None); self.set_field(72..76, op.quad_lanes); @@ -515,6 +533,7 @@ impl SM75Instr { Op::ISetP(op) => si.encode_isetp(&op), Op::Lop3(op) => si.encode_lop3(&op), Op::Shl(op) => si.encode_shl(&op), + Op::I2F(op) => si.encode_i2f(&op), Op::Mov(op) => si.encode_mov(&op), Op::Sel(op) => si.encode_sel(&op), Op::PLop3(op) => si.encode_plop3(&op), diff --git a/src/nouveau/compiler/nak_from_nir.rs b/src/nouveau/compiler/nak_from_nir.rs index 7cf6a448df2..77c7f11340b 100644 --- a/src/nouveau/compiler/nak_from_nir.rs +++ b/src/nouveau/compiler/nak_from_nir.rs @@ -90,6 +90,9 @@ impl<'a> ShaderFromNir<'a> { self.instrs .push(Instr::new_sel(dst, srcs[0], srcs[1], srcs[2])); } + nir_op_i2f32 => { + self.instrs.push(Instr::new_i2f(dst, srcs[0])); + } nir_op_iadd => { self.instrs.push(Instr::new_iadd(dst, srcs[0], srcs[1])); } diff --git a/src/nouveau/compiler/nak_ir.rs b/src/nouveau/compiler/nak_ir.rs index abde7a9541d..ef05d5ca42c 100644 --- a/src/nouveau/compiler/nak_ir.rs +++ b/src/nouveau/compiler/nak_ir.rs @@ -545,6 +545,94 @@ impl fmt::Display for LogicOp { } } +pub enum FloatType { + F16, + F32, + F64, +} + +impl FloatType { + pub fn bytes(&self) -> usize { + match self { + FloatType::F16 => 2, + FloatType::F32 => 4, + FloatType::F64 => 8, + } + } +} + +impl fmt::Display for FloatType { + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { + match self { + FloatType::F16 => write!(f, "F16"), + FloatType::F32 => write!(f, "F32"), + FloatType::F64 => write!(f, "F64"), + } + } +} + +pub enum FRndMode { + NearestEven, + NegInf, + PosInf, + Zero, +} + +impl fmt::Display for FRndMode { + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { + match self { + FRndMode::NearestEven => write!(f, "RE"), + FRndMode::NegInf => write!(f, "RM"), + FRndMode::PosInf => write!(f, "RP"), + FRndMode::Zero => write!(f, "RZ"), + } + } +} + +pub enum IntType { + U8, + I8, + U16, + I16, + U32, + I32, + U64, + I64, +} + +impl IntType { + pub fn is_signed(&self) -> bool { + match self { + IntType::U8 | IntType::U16 | IntType::U32 | IntType::U64 => false, + IntType::I8 | IntType::I16 | IntType::I32 | IntType::I64 => true, + } + } + + pub fn bytes(&self) -> usize { + match self { + IntType::U8 | IntType::I8 => 1, + IntType::U16 | IntType::I16 => 2, + IntType::U32 | IntType::I32 => 4, + IntType::U64 | IntType::I64 => 8, + } + } +} + +impl fmt::Display for IntType { + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { + match self { + IntType::U8 => write!(f, "U8"), + IntType::I8 => write!(f, "I8"), + IntType::U16 => write!(f, "U16"), + IntType::I16 => write!(f, "I16"), + IntType::U32 => write!(f, "U32"), + IntType::I32 => write!(f, "I32"), + IntType::U64 => write!(f, "U64"), + IntType::I64 => write!(f, "I64"), + } + } +} + pub enum MemAddrType { A32, A64, @@ -751,6 +839,26 @@ impl fmt::Display for OpShl { } } +#[repr(C)] +#[derive(SrcsAsSlice, DstsAsSlice, SrcModsAsSlice)] +pub struct OpI2F { + pub dst: Dst, + pub src: Src, + pub dst_type: FloatType, + pub src_type: IntType, + pub rnd_mode: FRndMode, +} + +impl fmt::Display for OpI2F { + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { + write!( + f, + "I2F.{}.{}.{} {} {}", + self.dst_type, self.src_type, self.rnd_mode, self.dst, self.src, + ) + } +} + #[repr(C)] #[derive(SrcsAsSlice, DstsAsSlice, SrcModsAsSlice)] pub struct OpMov { @@ -1011,6 +1119,7 @@ pub enum Op { ISetP(OpISetP), Lop3(OpLop3), Shl(OpShl), + I2F(OpI2F), Mov(OpMov), Sel(OpSel), PLop3(OpPLop3), @@ -1198,6 +1307,16 @@ impl Instr { })) } + pub fn new_i2f(dst: Dst, src: Src) -> Instr { + Instr::new(Op::I2F(OpI2F { + dst: dst, + src: src, + dst_type: FloatType::F32, + src_type: IntType::I32, + rnd_mode: FRndMode::NearestEven, + })) + } + pub fn new_isetp( dst: Dst, cmp_type: IntCmpType, @@ -1360,7 +1479,7 @@ impl Instr { | Op::PLop3(_) | Op::ISetP(_) | Op::Shl(_) => Some(6), - Op::Mov(_) => Some(15), + Op::I2F(_) | Op::Mov(_) => Some(15), Op::Sel(_) => Some(15), Op::S2R(_) => None, Op::ALd(_) => None,