diff --git a/src/nouveau/compiler/nak_encode_tu102.rs b/src/nouveau/compiler/nak_encode_tu102.rs index 0538e97aa07..55b29a77d6f 100644 --- a/src/nouveau/compiler/nak_encode_tu102.rs +++ b/src/nouveau/compiler/nak_encode_tu102.rs @@ -232,6 +232,40 @@ fn encode_lop3(bs: &mut impl BitSetMut, instr: &Instr, op: &LogicOp) { bs.set_bit(90, true); } +fn encode_cmp_op(bs: &mut impl BitSetMut, range: Range, op: &CmpOp) { + assert!(range.len() == 3); + bs.set_field( + range, + match op { + CmpOp::Eq => 2_u8, + CmpOp::Ne => 5_u8, + CmpOp::Lt => 1_u8, + CmpOp::Le => 3_u8, + CmpOp::Gt => 4_u8, + CmpOp::Ge => 6_u8, + }, + ); +} + +fn encode_isetp(bs: &mut impl BitSetMut, instr: &Instr, op: &IntCmpOp) { + encode_alu(bs, instr, 0x00c); + + bs.set_field( + 73..74, + match op.cmp_type { + IntCmpType::U32 => 0_u32, + IntCmpType::I32 => 1_u32, + }, + ); + bs.set_field(74..76, 0_u32); /* pred combine op */ + encode_cmp_op(bs, 76..79, &op.cmp_op); + + bs.set_field(84..87, 7_u32); /* dst1 */ + + bs.set_field(87..90, 7_u32); /* src pred */ + bs.set_bit(90, false); /* src pred neg */ +} + fn encode_shl(bs: &mut impl BitSetMut, instr: &Instr) { encode_alu(bs, instr, 0x019); @@ -345,6 +379,7 @@ pub fn encode_instr(instr: &Instr) -> [u32; 4] { Opcode::MOV => encode_mov(&mut bs, instr), Opcode::IADD3 => encode_iadd3(&mut bs, instr), Opcode::LOP3(op) => encode_lop3(&mut bs, instr, &op), + Opcode::ISETP(op) => encode_isetp(&mut bs, instr, &op), Opcode::SHL => encode_shl(&mut bs, instr), Opcode::ALD(a) => encode_ald(&mut bs, instr, &a), Opcode::AST(a) => encode_ast(&mut bs, instr, &a), diff --git a/src/nouveau/compiler/nak_from_nir.rs b/src/nouveau/compiler/nak_from_nir.rs index 091539d6df5..12a413b9c3f 100644 --- a/src/nouveau/compiler/nak_from_nir.rs +++ b/src/nouveau/compiler/nak_from_nir.rs @@ -101,6 +101,42 @@ impl<'a> ShaderFromNir<'a> { Src::Zero, )); } + nir_op_ieq => { + self.instrs.push(Instr::new_isetp( + dst, + IntCmpType::I32, + CmpOp::Eq, + srcs[0], + srcs[1], + )); + } + nir_op_ige => { + self.instrs.push(Instr::new_isetp( + dst, + IntCmpType::I32, + CmpOp::Ge, + srcs[0], + srcs[1], + )); + } + nir_op_ilt => { + self.instrs.push(Instr::new_isetp( + dst, + IntCmpType::I32, + CmpOp::Lt, + srcs[0], + srcs[1], + )); + } + nir_op_ine => { + self.instrs.push(Instr::new_isetp( + dst, + IntCmpType::I32, + CmpOp::Ne, + srcs[0], + srcs[1], + )); + } nir_op_inot => { self.instrs.push(Instr::new_lop3( dst, @@ -128,6 +164,24 @@ impl<'a> ShaderFromNir<'a> { nir_op_pack_64_2x32_split => { self.instrs.push(Instr::new_vec(dst, &[srcs[0], srcs[1]])); } + nir_op_uge => { + self.instrs.push(Instr::new_isetp( + dst, + IntCmpType::U32, + CmpOp::Ge, + srcs[0], + srcs[1], + )); + } + nir_op_ult => { + self.instrs.push(Instr::new_isetp( + dst, + IntCmpType::U32, + CmpOp::Lt, + srcs[0], + srcs[1], + )); + } _ => panic!("Unsupported ALU instruction"), } } diff --git a/src/nouveau/compiler/nak_ir.rs b/src/nouveau/compiler/nak_ir.rs index 83b3984333e..09979c4b969 100644 --- a/src/nouveau/compiler/nak_ir.rs +++ b/src/nouveau/compiler/nak_ir.rs @@ -440,6 +440,63 @@ impl InstrRefs { } } +pub enum PredSetOp { + Set, + And, + Or, + Xor, + AndNot, + OrNot, + XorNot, +} + +pub enum CmpOp { + Eq, + Ne, + Lt, + Le, + Gt, + Ge, +} + +impl fmt::Display for CmpOp { + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { + match self { + CmpOp::Eq => write!(f, "EQ"), + CmpOp::Ne => write!(f, "NE"), + CmpOp::Lt => write!(f, "LT"), + CmpOp::Le => write!(f, "LE"), + CmpOp::Gt => write!(f, "GT"), + CmpOp::Ge => write!(f, "GE"), + } + } +} + +pub enum IntCmpType { + U32, + I32, +} + +impl fmt::Display for IntCmpType { + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { + match self { + IntCmpType::U32 => write!(f, "U32"), + IntCmpType::I32 => write!(f, "I32"), + } + } +} + +pub struct IntCmpOp { + pub cmp_op: CmpOp, + pub cmp_type: IntCmpType, +} + +impl fmt::Display for IntCmpOp { + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { + write!(f, "{}.{}", self.cmp_op, self.cmp_type) + } +} + pub struct LogicOp { pub lut: u8, } @@ -745,6 +802,20 @@ impl Instr { Instr::new(Opcode::IADD3, slice::from_ref(&dst), &[Src::Zero, x, y]) } + pub fn new_isetp( + dst: Dst, + cmp_type: IntCmpType, + cmp_op: CmpOp, + x: Src, + y: Src, + ) -> Instr { + let op = IntCmpOp { + cmp_type: cmp_type, + cmp_op: cmp_op, + }; + Instr::new(Opcode::ISETP(op), slice::from_ref(&dst), &[x, y]) + } + pub fn new_lop3(dst: Dst, op: LogicOp, x: Src, y: Src, z: Src) -> Instr { Instr::new(Opcode::LOP3(op), slice::from_ref(&dst), &[x, y, z]) } @@ -872,6 +943,7 @@ impl Instr { | Opcode::FMUL | Opcode::IADD3 | Opcode::LOP3(_) + | Opcode::ISETP(_) | Opcode::SHL => Some(6), Opcode::MOV => Some(15), Opcode::S2R(_) => None, @@ -919,6 +991,7 @@ pub enum Opcode { IADD3, LOP3(LogicOp), + ISETP(IntCmpOp), SHL, S2R(u8), @@ -947,6 +1020,7 @@ impl fmt::Display for Opcode { Opcode::FMUL => write!(f, "FMUL"), Opcode::IADD3 => write!(f, "IADD3"), Opcode::LOP3(op) => write!(f, "LOP3.{}", op), + Opcode::ISETP(op) => write!(f, "ISETP.{}", op), Opcode::SHL => write!(f, "SHL"), Opcode::S2R(i) => write!(f, "S2R({})", i), Opcode::MOV => write!(f, "MOV"),