nak: Fix instruction ordering in nak_ir.rs

I'm trying to stick to the ordering in the NVIDIA docs.

Part-of: <https://gitlab.freedesktop.org/mesa/mesa/-/merge_requests/24998>
This commit is contained in:
Faith Ekstrand 2023-09-11 14:00:43 -05:00 committed by Marge Bot
parent 3e8344a4c8
commit eb10a778fd
3 changed files with 234 additions and 236 deletions

View file

@ -540,6 +540,31 @@ impl SM75Instr {
);
}
fn encode_brev(&mut self, op: &OpBrev) {
self.encode_alu(
0x101,
Some(op.dst),
ALUSrc::None,
ALUSrc::from_src(&op.src),
ALUSrc::None,
);
}
fn encode_bfind(&mut self, op: &OpBFind) {
self.encode_alu(
0x100,
Some(op.dst),
ALUSrc::None,
ALUSrc::from_src(&op.src),
ALUSrc::None,
);
self.set_pred_dst(81..84, Dst::None);
self.set_field(74..75, op.return_shift_amount as u8);
self.set_field(73..74, op.signed as u8);
let not_mod = matches!(op.src.src_mod, SrcMod::BNot);
self.set_field(63..64, not_mod)
}
fn encode_iabs(&mut self, op: &OpIAbs) {
self.encode_alu(
0x013,
@ -687,6 +712,19 @@ impl SM75Instr {
self.set_pred_src(87..90, 90, SrcRef::False.into());
}
fn encode_popc(&mut self, op: &OpPopC) {
self.encode_alu(
0x109,
Some(op.dst),
ALUSrc::None,
ALUSrc::from_src(&op.src),
ALUSrc::None,
);
let not_mod = matches!(op.src.src_mod, SrcMod::BNot);
self.set_field(63..64, not_mod)
}
fn encode_shf(&mut self, op: &OpShf) {
self.encode_alu(
0x019,
@ -794,6 +832,16 @@ impl SM75Instr {
self.set_field(72..76, op.quad_lanes);
}
fn encode_prmt(&mut self, op: &OpPrmt) {
self.encode_alu(
0x16,
Some(op.dst),
ALUSrc::from_src(&op.srcs[0]),
ALUSrc::Imm32(op.selection.inner()),
ALUSrc::from_src(&op.srcs[1]),
);
}
fn encode_sel(&mut self, op: &OpSel) {
self.encode_alu(
0x007,
@ -1494,54 +1542,6 @@ impl SM75Instr {
self.set_field(72..80, op.idx);
}
fn encode_popc(&mut self, op: &OpPopC) {
self.encode_alu(
0x109,
Some(op.dst),
ALUSrc::None,
ALUSrc::from_src(&op.src),
ALUSrc::None,
);
let not_mod = matches!(op.src.src_mod, SrcMod::BNot);
self.set_field(63..64, not_mod)
}
fn encode_brev(&mut self, op: &OpBrev) {
self.encode_alu(
0x101,
Some(op.dst),
ALUSrc::None,
ALUSrc::from_src(&op.src),
ALUSrc::None,
);
}
fn encode_bfind(&mut self, op: &OpBFind) {
self.encode_alu(
0x100,
Some(op.dst),
ALUSrc::None,
ALUSrc::from_src(&op.src),
ALUSrc::None,
);
self.set_pred_dst(81..84, Dst::None);
self.set_field(74..75, op.return_shift_amount as u8);
self.set_field(73..74, op.signed as u8);
let not_mod = matches!(op.src.src_mod, SrcMod::BNot);
self.set_field(63..64, not_mod)
}
fn encode_prmt(&mut self, op: &OpPrmt) {
self.encode_alu(
0x16,
Some(op.dst),
ALUSrc::from_src(&op.srcs[0]),
ALUSrc::Imm32(op.selection.inner()),
ALUSrc::from_src(&op.srcs[1]),
);
}
pub fn encode(
instr: &Instr,
sm: u8,
@ -1563,6 +1563,8 @@ impl SM75Instr {
Op::FSet(op) => si.encode_fset(&op),
Op::FSetP(op) => si.encode_fsetp(&op),
Op::MuFu(op) => si.encode_mufu(&op),
Op::Brev(op) => si.encode_brev(&op),
Op::BFind(op) => si.encode_bfind(&op),
Op::IAbs(op) => si.encode_iabs(&op),
Op::IAdd3(op) => si.encode_iadd3(&op),
Op::IAdd3X(op) => si.encode_iadd3x(&op),
@ -1571,12 +1573,14 @@ impl SM75Instr {
Op::IMnMx(op) => si.encode_imnmx(&op),
Op::ISetP(op) => si.encode_isetp(&op),
Op::Lop3(op) => si.encode_lop3(&op),
Op::PopC(op) => si.encode_popc(&op),
Op::Shf(op) => si.encode_shf(&op),
Op::F2F(op) => si.encode_f2f(&op),
Op::F2I(op) => si.encode_f2i(&op),
Op::I2F(op) => si.encode_i2f(&op),
Op::FRnd(op) => si.encode_frnd(&op),
Op::Mov(op) => si.encode_mov(&op),
Op::Prmt(op) => si.encode_prmt(&op),
Op::Sel(op) => si.encode_sel(&op),
Op::PLop3(op) => si.encode_plop3(&op),
Op::Tex(op) => si.encode_tex(&op),
@ -1602,10 +1606,6 @@ impl SM75Instr {
Op::Bar(op) => si.encode_bar(&op),
Op::CS2R(op) => si.encode_cs2r(&op),
Op::S2R(op) => si.encode_s2r(&op),
Op::PopC(op) => si.encode_popc(&op),
Op::Brev(op) => si.encode_brev(&op),
Op::BFind(op) => si.encode_bfind(&op),
Op::Prmt(op) => si.encode_prmt(&op),
_ => panic!("Unhandled instruction"),
}

View file

@ -2061,6 +2061,43 @@ impl fmt::Display for OpDAdd {
}
}
#[repr(C)]
#[derive(SrcsAsSlice, DstsAsSlice)]
pub struct OpBrev {
pub dst: Dst,
#[src_type(ALU)]
pub src: Src,
}
impl fmt::Display for OpBrev {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
write!(f, "BREV {} {}", self.dst, self.src,)
}
}
#[repr(C)]
#[derive(SrcsAsSlice, DstsAsSlice)]
pub struct OpBFind {
pub dst: Dst,
#[src_type(ALU)]
pub src: Src,
pub signed: bool,
pub return_shift_amount: bool,
}
impl fmt::Display for OpBFind {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
write!(f, "BFIND")?;
if self.return_shift_amount {
write!(f, ".SAMT")?;
}
write!(f, " {} {}", self.dst, self.src)
}
}
#[repr(C)]
#[derive(SrcsAsSlice, DstsAsSlice)]
pub struct OpIAbs {
@ -2443,6 +2480,130 @@ impl fmt::Display for OpMov {
}
}
#[derive(Copy, Clone, Debug)]
pub enum PrmtSrc {
Byte0 = 0,
Byte1 = 1,
Byte2 = 2,
Byte3 = 3,
Byte4 = 4,
Byte5 = 5,
Byte6 = 6,
Byte7 = 7,
}
impl TryFrom<u32> for PrmtSrc {
type Error = String;
fn try_from(value: u32) -> Result<Self, Self::Error> {
match value {
0 => Ok(Self::Byte0),
1 => Ok(Self::Byte1),
2 => Ok(Self::Byte2),
3 => Ok(Self::Byte3),
4 => Ok(Self::Byte4),
5 => Ok(Self::Byte5),
6 => Ok(Self::Byte6),
7 => Ok(Self::Byte7),
_ => Err(format!("Invalid value {}", value)),
}
}
}
#[derive(Copy, Clone, Debug)]
pub struct PrmtSelection {
pub src: PrmtSrc,
pub sign_extend: bool,
}
impl From<PrmtSelectionEval> for [PrmtSelection; 4] {
fn from(value: PrmtSelectionEval) -> Self {
let sel0 = value.0 & 0x7;
let sel1 = (value.0 & 0x70) >> 4;
let sel2 = (value.0 & 0x700) >> 8;
let sel3 = (value.0 & 0x7000) >> 12;
let sign0 = value.0 & 0x8;
let sign1 = value.0 & 0x80;
let sign2 = value.0 & 0x800;
let sign3 = value.0 & 0x8000;
[
PrmtSelection {
src: sel3.try_into().unwrap(),
sign_extend: sign3 != 0,
},
PrmtSelection {
src: sel2.try_into().unwrap(),
sign_extend: sign2 != 0,
},
PrmtSelection {
src: sel1.try_into().unwrap(),
sign_extend: sign1 != 0,
},
PrmtSelection {
src: sel0.try_into().unwrap(),
sign_extend: sign0 != 0,
},
]
}
}
#[derive(Copy, Clone, Debug)]
pub struct PrmtSelectionEval(u32);
impl PrmtSelectionEval {
pub fn inner(&self) -> u32 {
self.0
}
}
impl From<[PrmtSelection; 4]> for PrmtSelectionEval {
fn from(selections: [PrmtSelection; 4]) -> Self {
let mut selection = 0;
for v in selections {
let src = if v.sign_extend {
v.src as u32 | 0x8
} else {
v.src as u32
};
selection = selection << 4 | src;
}
Self(selection)
}
}
#[repr(C)]
#[derive(SrcsAsSlice, DstsAsSlice)]
/// Permutes `srcs` into `dst` using `selection`.
pub struct OpPrmt {
pub dst: Dst,
#[src_type(ALU)]
pub srcs: [Src; 2],
pub selection: PrmtSelectionEval,
}
impl fmt::Display for OpPrmt {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
let sel: [PrmtSelection; 4] = self.selection.into();
write!(
f,
"PRMT {}, {} [{:?}, {:?}, {:?}, {:?}], {}",
self.dst,
self.srcs[0],
sel[0].src,
sel[1].src,
sel[2].src,
sel[3].src,
self.srcs[1],
)
}
}
#[repr(C)]
#[derive(SrcsAsSlice, DstsAsSlice)]
pub struct OpSel {
@ -2492,6 +2653,21 @@ impl fmt::Display for OpPLop3 {
}
}
#[repr(C)]
#[derive(SrcsAsSlice, DstsAsSlice)]
pub struct OpPopC {
pub dst: Dst,
#[src_type(ALU)]
pub src: Src,
}
impl fmt::Display for OpPopC {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
write!(f, "POPC {} {}", self.dst, self.src,)
}
}
#[repr(C)]
#[derive(SrcsAsSlice, DstsAsSlice)]
pub struct OpTex {
@ -3431,182 +3607,6 @@ impl fmt::Display for OpFSOut {
}
}
#[repr(C)]
#[derive(SrcsAsSlice, DstsAsSlice)]
pub struct OpPopC {
pub dst: Dst,
#[src_type(ALU)]
pub src: Src,
}
impl fmt::Display for OpPopC {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
write!(f, "POPC {} {}", self.dst, self.src,)
}
}
#[repr(C)]
#[derive(SrcsAsSlice, DstsAsSlice)]
pub struct OpBrev {
pub dst: Dst,
#[src_type(ALU)]
pub src: Src,
}
impl fmt::Display for OpBrev {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
write!(f, "BREV {} {}", self.dst, self.src,)
}
}
#[repr(C)]
#[derive(SrcsAsSlice, DstsAsSlice)]
pub struct OpBFind {
pub dst: Dst,
#[src_type(ALU)]
pub src: Src,
pub signed: bool,
pub return_shift_amount: bool,
}
impl fmt::Display for OpBFind {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
write!(f, "BFIND")?;
if self.return_shift_amount {
write!(f, ".SAMT")?;
}
write!(f, " {} {}", self.dst, self.src)
}
}
#[derive(Copy, Clone, Debug)]
pub enum PrmtSrc {
Byte0 = 0,
Byte1 = 1,
Byte2 = 2,
Byte3 = 3,
Byte4 = 4,
Byte5 = 5,
Byte6 = 6,
Byte7 = 7,
}
impl TryFrom<u32> for PrmtSrc {
type Error = String;
fn try_from(value: u32) -> Result<Self, Self::Error> {
match value {
0 => Ok(Self::Byte0),
1 => Ok(Self::Byte1),
2 => Ok(Self::Byte2),
3 => Ok(Self::Byte3),
4 => Ok(Self::Byte4),
5 => Ok(Self::Byte5),
6 => Ok(Self::Byte6),
7 => Ok(Self::Byte7),
_ => Err(format!("Invalid value {}", value)),
}
}
}
#[derive(Copy, Clone, Debug)]
pub struct PrmtSelection {
pub src: PrmtSrc,
pub sign_extend: bool,
}
impl From<PrmtSelectionEval> for [PrmtSelection; 4] {
fn from(value: PrmtSelectionEval) -> Self {
let sel0 = value.0 & 0x7;
let sel1 = (value.0 & 0x70) >> 4;
let sel2 = (value.0 & 0x700) >> 8;
let sel3 = (value.0 & 0x7000) >> 12;
let sign0 = value.0 & 0x8;
let sign1 = value.0 & 0x80;
let sign2 = value.0 & 0x800;
let sign3 = value.0 & 0x8000;
[
PrmtSelection {
src: sel3.try_into().unwrap(),
sign_extend: sign3 != 0,
},
PrmtSelection {
src: sel2.try_into().unwrap(),
sign_extend: sign2 != 0,
},
PrmtSelection {
src: sel1.try_into().unwrap(),
sign_extend: sign1 != 0,
},
PrmtSelection {
src: sel0.try_into().unwrap(),
sign_extend: sign0 != 0,
},
]
}
}
#[derive(Copy, Clone, Debug)]
pub struct PrmtSelectionEval(u32);
impl PrmtSelectionEval {
pub fn inner(&self) -> u32 {
self.0
}
}
impl From<[PrmtSelection; 4]> for PrmtSelectionEval {
fn from(selections: [PrmtSelection; 4]) -> Self {
let mut selection = 0;
for v in selections {
let src = if v.sign_extend {
v.src as u32 | 0x8
} else {
v.src as u32
};
selection = selection << 4 | src;
}
Self(selection)
}
}
#[repr(C)]
#[derive(SrcsAsSlice, DstsAsSlice)]
/// Permutes `srcs` into `dst` using `selection`.
pub struct OpPrmt {
pub dst: Dst,
#[src_type(ALU)]
pub srcs: [Src; 2],
pub selection: PrmtSelectionEval,
}
impl fmt::Display for OpPrmt {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
let sel: [PrmtSelection; 4] = self.selection.into();
write!(
f,
"PRMT {}, {} [{:?}, {:?}, {:?}, {:?}], {}",
self.dst,
self.srcs[0],
sel[0].src,
sel[1].src,
sel[2].src,
sel[3].src,
self.srcs[1],
)
}
}
#[derive(Display, DstsAsSlice, SrcsAsSlice, FromVariants)]
pub enum Op {
FAdd(OpFAdd),
@ -3617,6 +3617,8 @@ pub enum Op {
FSet(OpFSet),
FSetP(OpFSetP),
DAdd(OpDAdd),
Brev(OpBrev),
BFind(OpBFind),
IAbs(OpIAbs),
INeg(OpINeg),
IAdd3(OpIAdd3),
@ -3626,12 +3628,14 @@ pub enum Op {
IMnMx(OpIMnMx),
ISetP(OpISetP),
Lop3(OpLop3),
PopC(OpPopC),
Shf(OpShf),
F2F(OpF2F),
F2I(OpF2I),
I2F(OpI2F),
FRnd(OpFRnd),
Mov(OpMov),
Prmt(OpPrmt),
Sel(OpSel),
PLop3(OpPLop3),
Tex(OpTex),
@ -3664,10 +3668,6 @@ pub enum Op {
Swap(OpSwap),
ParCopy(OpParCopy),
FSOut(OpFSOut),
PopC(OpPopC),
Brev(OpBrev),
BFind(OpBFind),
Prmt(OpPrmt),
}
#[derive(Clone, Copy, Eq, Hash, PartialEq)]

View file

@ -103,7 +103,7 @@ fn legalize_instr(b: &mut impl SSABuilder, instr: &mut Instr) {
swap_srcs_if_not_reg(src0, src1);
copy_src_if_not_reg(b, src0, RegFile::GPR);
}
Op::IAbs(_) | Op::INeg(_) => (), /* Nothing to do */
Op::Brev(_) | Op::BFind(_) | Op::IAbs(_) | Op::INeg(_) => (),
Op::IAdd3(op) => {
let [ref mut src0, ref mut src1, ref mut src2] = op.srcs;
swap_srcs_if_not_reg(src0, src1);
@ -179,6 +179,7 @@ fn legalize_instr(b: &mut impl SSABuilder, instr: &mut Instr) {
copy_src_if_not_reg(b, src0, RegFile::GPR);
copy_src_if_not_reg(b, src2, RegFile::GPR);
}
Op::PopC(_) => (),
Op::Shf(op) => {
copy_src_if_not_reg(b, &mut op.low, RegFile::GPR);
copy_src_if_not_reg(b, &mut op.high, RegFile::GPR);
@ -188,9 +189,6 @@ fn legalize_instr(b: &mut impl SSABuilder, instr: &mut Instr) {
| Op::I2F(_)
| Op::Mov(_)
| Op::FRnd(_)
| Op::PopC(_)
| Op::Brev(_)
| Op::BFind(_)
| Op::Prmt(_) => (),
Op::Sel(op) => {
let [ref mut src0, ref mut src1] = op.srcs;