nak: Implement 32-bit logic ops

Part-of: <https://gitlab.freedesktop.org/mesa/mesa/-/merge_requests/24998>
This commit is contained in:
Faith Ekstrand 2023-01-30 20:53:17 -06:00 committed by Marge Bot
parent 8cf12d6a3f
commit de073a10e6
3 changed files with 100 additions and 1 deletions

View file

@ -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),

View file

@ -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]));
}

View file

@ -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<F: Fn(u8, u8, u8) -> u8>(f: &F) -> LogicOp {
LogicOp {
lut: f(0xf0, 0xcc, 0xaa),
}
}
pub fn eval<
T: BitAnd<Output = T> + BitOr<Output = T> + Copy + Not<Output = T>,
>(
&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"),