From de073a10e6ee90658d2ff760d8fb0467d29656f8 Mon Sep 17 00:00:00 2001 From: Faith Ekstrand Date: Mon, 30 Jan 2023 20:53:17 -0600 Subject: [PATCH] nak: Implement 32-bit logic ops Part-of: --- src/nouveau/compiler/nak_encode_tu102.rs | 10 ++++ src/nouveau/compiler/nak_from_nir.rs | 27 ++++++++++ src/nouveau/compiler/nak_ir.rs | 64 +++++++++++++++++++++++- 3 files changed, 100 insertions(+), 1 deletion(-) diff --git a/src/nouveau/compiler/nak_encode_tu102.rs b/src/nouveau/compiler/nak_encode_tu102.rs index f0a6b4d8c47..6f45b6621a6 100644 --- a/src/nouveau/compiler/nak_encode_tu102.rs +++ b/src/nouveau/compiler/nak_encode_tu102.rs @@ -204,6 +204,15 @@ fn encode_iadd3(bs: &mut impl BitSetMut, instr: &Instr) { bs.set_field(84..87, 7_u32); /* pred */ } +fn encode_lop3(bs: &mut impl BitSetMut, instr: &Instr, op: &LogicOp) { + encode_alu(bs, instr, 0x012); + bs.set_field(72..80, op.lut); + bs.set_bit(80, false); /* .PAND */ + bs.set_field(81..84, 7_u32); /* pred */ + bs.set_field(84..87, 7_u32); /* pred */ + bs.set_bit(90, true); +} + fn encode_shl(bs: &mut impl BitSetMut, instr: &Instr) { encode_alu(bs, instr, 0x019); @@ -316,6 +325,7 @@ pub fn encode_instr(instr: &Instr) -> [u32; 4] { Opcode::S2R(i) => encode_s2r(&mut bs, instr, *i), Opcode::MOV => encode_mov(&mut bs, instr), Opcode::IADD3 => encode_iadd3(&mut bs, instr), + Opcode::LOP3(op) => encode_lop3(&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 e5cf2d82854..9fb2efa6953 100644 --- a/src/nouveau/compiler/nak_from_nir.rs +++ b/src/nouveau/compiler/nak_from_nir.rs @@ -88,6 +88,33 @@ impl<'a> ShaderFromNir<'a> { nir_op_iadd => { self.instrs.push(Instr::new_iadd(dst, srcs[0], srcs[1])); } + nir_op_iand => { + self.instrs.push(Instr::new_lop3( + dst, + LogicOp::new_lut(&|x, y, _| x & y), + srcs[0], + srcs[1], + Src::Zero, + )); + } + nir_op_inot => { + self.instrs.push(Instr::new_lop3( + dst, + LogicOp::new_lut(&|x, _, _| !x), + srcs[0], + Src::Zero, + Src::Zero, + )); + } + nir_op_ior => { + self.instrs.push(Instr::new_lop3( + dst, + LogicOp::new_lut(&|x, y, _| x | y), + srcs[0], + srcs[1], + Src::Zero, + )); + } nir_op_ishl => { self.instrs.push(Instr::new_shl(dst, srcs[0], srcs[1])); } diff --git a/src/nouveau/compiler/nak_ir.rs b/src/nouveau/compiler/nak_ir.rs index 9ab969cd0af..7753e44a108 100644 --- a/src/nouveau/compiler/nak_ir.rs +++ b/src/nouveau/compiler/nak_ir.rs @@ -4,7 +4,7 @@ */ use std::fmt; -use std::ops::Range; +use std::ops::{BitAnd, BitOr, Not, Range}; use std::slice; #[derive(Clone, Copy)] @@ -386,6 +386,61 @@ impl InstrRefs { } } +pub struct LogicOp { + pub lut: u8, +} + +impl LogicOp { + #[inline] + pub fn new_lut u8>(f: &F) -> LogicOp { + LogicOp { + lut: f(0xf0, 0xcc, 0xaa), + } + } + + pub fn eval< + T: BitAnd + BitOr + Copy + Not, + >( + &self, + x: T, + y: T, + z: T, + ) -> T { + let mut res = x & !x; /* zero */ + if (self.lut & (1 << 0)) != 0 { + res = res | (!x & !y & !z); + } + if (self.lut & (1 << 1)) != 0 { + res = res | (!x & !y & z); + } + if (self.lut & (1 << 2)) != 0 { + res = res | (!x & y & !z); + } + if (self.lut & (1 << 3)) != 0 { + res = res | (!x & y & z); + } + if (self.lut & (1 << 4)) != 0 { + res = res | (x & !y & !z); + } + if (self.lut & (1 << 5)) != 0 { + res = res | (x & !y & z); + } + if (self.lut & (1 << 6)) != 0 { + res = res | (x & y & !z); + } + if (self.lut & (1 << 7)) != 0 { + res = res | (x & y & z); + } + res + } +} + +impl fmt::Display for LogicOp { + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { + write!(f, "LUT[{:#x}]", self.lut) + } +} + pub struct AttrAccess { pub addr: u16, pub comps: u8, @@ -632,6 +687,10 @@ impl Instr { Instr::new(Opcode::IADD3, slice::from_ref(&dst), &[Src::Zero, 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]) + } + pub fn new_shl(dst: Dst, x: Src, shift: Src) -> Instr { Instr::new(Opcode::SHL, slice::from_ref(&dst), &[x, shift]) } @@ -754,6 +813,7 @@ impl Instr { | Opcode::FMNMX | Opcode::FMUL | Opcode::IADD3 + | Opcode::LOP3(_) | Opcode::SHL => Some(6), Opcode::MOV => Some(15), Opcode::S2R(_) => None, @@ -800,6 +860,7 @@ pub enum Opcode { FMUL, IADD3, + LOP3(LogicOp), SHL, S2R(u8), @@ -827,6 +888,7 @@ impl fmt::Display for Opcode { Opcode::FMNMX => write!(f, "FMNMX"), Opcode::FMUL => write!(f, "FMUL"), Opcode::IADD3 => write!(f, "IADD3"), + Opcode::LOP3(op) => write!(f, "LOP3.{}", op), Opcode::SHL => write!(f, "SHL"), Opcode::S2R(i) => write!(f, "S2R({})", i), Opcode::MOV => write!(f, "MOV"),