Compare commits
2 Commits
1ff7135691
...
b9275b54a1
Author | SHA1 | Date | |
---|---|---|---|
|
b9275b54a1 | ||
|
28d077838f |
@@ -547,3 +547,48 @@ pub fn test_lea() {
|
|||||||
c.check(sm);
|
c.check(sm);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
pub fn test_hfma2() {
|
||||||
|
let r0 = RegRef::new(RegFile::GPR, 0, 1);
|
||||||
|
let r1 = RegRef::new(RegFile::GPR, 1, 1);
|
||||||
|
let r2 = RegRef::new(RegFile::GPR, 2, 1);
|
||||||
|
let r3 = RegRef::new(RegFile::GPR, 3, 1);
|
||||||
|
|
||||||
|
let src_mods = [SrcMod::None, SrcMod::FAbs, SrcMod::FNeg, SrcMod::FNegAbs];
|
||||||
|
|
||||||
|
for sm in SM_LIST {
|
||||||
|
let mut c = DisasmCheck::new();
|
||||||
|
|
||||||
|
for a_mod in src_mods {
|
||||||
|
for b_mod in src_mods {
|
||||||
|
for c_mod in src_mods {
|
||||||
|
let mut instr = OpHFma2 {
|
||||||
|
dst: Dst::Reg(r0),
|
||||||
|
|
||||||
|
srcs: [
|
||||||
|
SrcRef::Reg(r1).into(),
|
||||||
|
SrcRef::Reg(r2).into(),
|
||||||
|
SrcRef::Reg(r3).into(),
|
||||||
|
],
|
||||||
|
|
||||||
|
saturate: false,
|
||||||
|
ftz: false,
|
||||||
|
dnz: false,
|
||||||
|
f32: false,
|
||||||
|
};
|
||||||
|
instr.srcs[0].src_mod = a_mod;
|
||||||
|
instr.srcs[1].src_mod = b_mod;
|
||||||
|
instr.srcs[2].src_mod = c_mod;
|
||||||
|
let disasm = format!(
|
||||||
|
"hfma2 r0, {}, {}, {};",
|
||||||
|
instr.srcs[0], instr.srcs[1], instr.srcs[2],
|
||||||
|
);
|
||||||
|
c.push(instr, disasm);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
c.check(sm);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
@@ -326,14 +326,6 @@ impl ALUSrc {
|
|||||||
_ => panic!("Invalid ALU source"),
|
_ => panic!("Invalid ALU source"),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn has_src_mod(&self) -> bool {
|
|
||||||
match self {
|
|
||||||
ALUSrc::Reg(reg) | ALUSrc::UReg(reg) => reg.abs || reg.neg,
|
|
||||||
ALUSrc::CBuf(cb) => cb.abs || cb.neg,
|
|
||||||
_ => false,
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
impl SM70Encoder<'_> {
|
impl SM70Encoder<'_> {
|
||||||
@@ -358,7 +350,6 @@ impl SM70Encoder<'_> {
|
|||||||
swizzle_range: Range<usize>,
|
swizzle_range: Range<usize>,
|
||||||
file: RegFile,
|
file: RegFile,
|
||||||
is_fp16_alu: bool,
|
is_fp16_alu: bool,
|
||||||
has_mod: bool,
|
|
||||||
reg: &ALURegRef,
|
reg: &ALURegRef,
|
||||||
) {
|
) {
|
||||||
match file {
|
match file {
|
||||||
@@ -367,12 +358,8 @@ impl SM70Encoder<'_> {
|
|||||||
_ => panic!("Invalid ALU src register file"),
|
_ => panic!("Invalid ALU src register file"),
|
||||||
}
|
}
|
||||||
|
|
||||||
if has_mod {
|
self.set_bit(abs_bit, reg.abs);
|
||||||
self.set_bit(abs_bit, reg.abs);
|
self.set_bit(neg_bit, reg.neg);
|
||||||
self.set_bit(neg_bit, reg.neg);
|
|
||||||
} else {
|
|
||||||
assert!(!reg.abs && !reg.neg);
|
|
||||||
}
|
|
||||||
|
|
||||||
if is_fp16_alu {
|
if is_fp16_alu {
|
||||||
self.set_swizzle(swizzle_range, reg.swizzle);
|
self.set_swizzle(swizzle_range, reg.swizzle);
|
||||||
@@ -392,7 +379,7 @@ impl SM70Encoder<'_> {
|
|||||||
ALUSrc::Reg(reg) => reg,
|
ALUSrc::Reg(reg) => reg,
|
||||||
_ => panic!("Invalid ALU src"),
|
_ => panic!("Invalid ALU src"),
|
||||||
};
|
};
|
||||||
self.set_alu_reg(24..32, 73, 72, 74..76, file, is_fp16_alu, true, reg);
|
self.set_alu_reg(24..32, 73, 72, 74..76, file, is_fp16_alu, reg);
|
||||||
}
|
}
|
||||||
|
|
||||||
fn encode_alu_src2(
|
fn encode_alu_src2(
|
||||||
@@ -400,7 +387,6 @@ impl SM70Encoder<'_> {
|
|||||||
src: &ALUSrc,
|
src: &ALUSrc,
|
||||||
file: RegFile,
|
file: RegFile,
|
||||||
is_fp16_alu: bool,
|
is_fp16_alu: bool,
|
||||||
bit74_75_are_mod: bool,
|
|
||||||
) {
|
) {
|
||||||
let reg = match src {
|
let reg = match src {
|
||||||
ALUSrc::None => return,
|
ALUSrc::None => return,
|
||||||
@@ -409,12 +395,11 @@ impl SM70Encoder<'_> {
|
|||||||
};
|
};
|
||||||
self.set_alu_reg(
|
self.set_alu_reg(
|
||||||
64..72,
|
64..72,
|
||||||
74,
|
if is_fp16_alu { 83 } else { 74 },
|
||||||
75,
|
if is_fp16_alu { 84 } else { 75 },
|
||||||
81..83,
|
81..83,
|
||||||
file,
|
file,
|
||||||
is_fp16_alu,
|
is_fp16_alu,
|
||||||
bit74_75_are_mod,
|
|
||||||
reg,
|
reg,
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
@@ -427,7 +412,6 @@ impl SM70Encoder<'_> {
|
|||||||
60..62,
|
60..62,
|
||||||
RegFile::GPR,
|
RegFile::GPR,
|
||||||
is_fp16_alu,
|
is_fp16_alu,
|
||||||
true,
|
|
||||||
reg,
|
reg,
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
@@ -479,25 +463,11 @@ impl SM70Encoder<'_> {
|
|||||||
let src1 = ALUSrc::from_src(self, src1, false);
|
let src1 = ALUSrc::from_src(self, src1, false);
|
||||||
let src2 = ALUSrc::from_src(self, src2, false);
|
let src2 = ALUSrc::from_src(self, src2, false);
|
||||||
|
|
||||||
// Bits 74..76 are used both for the swizzle on src0 and for the source
|
|
||||||
// modifier for the register source of src1 and src2. When both are
|
|
||||||
// registers, it's used for src2. The hardware elects to always support
|
|
||||||
// a swizzle and not support source modifiers in that case.
|
|
||||||
let bit74_75_are_mod = !is_fp16_alu
|
|
||||||
|| matches!(src1, ALUSrc::None)
|
|
||||||
|| matches!(src2, ALUSrc::None);
|
|
||||||
debug_assert!(bit74_75_are_mod || !src2.has_src_mod());
|
|
||||||
|
|
||||||
self.encode_alu_src0(&src0, RegFile::GPR, is_fp16_alu);
|
self.encode_alu_src0(&src0, RegFile::GPR, is_fp16_alu);
|
||||||
|
|
||||||
let form = match &src2 {
|
let form = match &src2 {
|
||||||
ALUSrc::None | ALUSrc::Reg(_) => {
|
ALUSrc::None | ALUSrc::Reg(_) => {
|
||||||
self.encode_alu_src2(
|
self.encode_alu_src2(&src2, RegFile::GPR, is_fp16_alu);
|
||||||
&src2,
|
|
||||||
RegFile::GPR,
|
|
||||||
is_fp16_alu,
|
|
||||||
bit74_75_are_mod,
|
|
||||||
);
|
|
||||||
match &src1 {
|
match &src1 {
|
||||||
ALUSrc::None => 1_u8, // form
|
ALUSrc::None => 1_u8, // form
|
||||||
ALUSrc::Reg(reg1) => {
|
ALUSrc::Reg(reg1) => {
|
||||||
@@ -520,33 +490,18 @@ impl SM70Encoder<'_> {
|
|||||||
}
|
}
|
||||||
ALUSrc::UReg(reg2) => {
|
ALUSrc::UReg(reg2) => {
|
||||||
self.encode_alu_ureg(reg2, is_fp16_alu);
|
self.encode_alu_ureg(reg2, is_fp16_alu);
|
||||||
self.encode_alu_src2(
|
self.encode_alu_src2(&src1, RegFile::GPR, is_fp16_alu);
|
||||||
&src1,
|
|
||||||
RegFile::GPR,
|
|
||||||
is_fp16_alu,
|
|
||||||
bit74_75_are_mod,
|
|
||||||
);
|
|
||||||
7_u8 // form
|
7_u8 // form
|
||||||
}
|
}
|
||||||
ALUSrc::Imm32(imm2) => {
|
ALUSrc::Imm32(imm2) => {
|
||||||
self.encode_alu_imm(imm2);
|
self.encode_alu_imm(imm2);
|
||||||
self.encode_alu_src2(
|
self.encode_alu_src2(&src1, RegFile::GPR, is_fp16_alu);
|
||||||
&src1,
|
|
||||||
RegFile::GPR,
|
|
||||||
is_fp16_alu,
|
|
||||||
bit74_75_are_mod,
|
|
||||||
);
|
|
||||||
2_u8 // form
|
2_u8 // form
|
||||||
}
|
}
|
||||||
ALUSrc::CBuf(cb2) => {
|
ALUSrc::CBuf(cb2) => {
|
||||||
// TODO set_src_cx
|
// TODO set_src_cx
|
||||||
self.encode_alu_cb(cb2, is_fp16_alu);
|
self.encode_alu_cb(cb2, is_fp16_alu);
|
||||||
self.encode_alu_src2(
|
self.encode_alu_src2(&src1, RegFile::GPR, is_fp16_alu);
|
||||||
&src1,
|
|
||||||
RegFile::GPR,
|
|
||||||
is_fp16_alu,
|
|
||||||
bit74_75_are_mod,
|
|
||||||
);
|
|
||||||
3_u8 // form
|
3_u8 // form
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
@@ -599,7 +554,7 @@ impl SM70Encoder<'_> {
|
|||||||
self.encode_alu_src0(&src0, RegFile::UGPR, false);
|
self.encode_alu_src0(&src0, RegFile::UGPR, false);
|
||||||
let form = match &src2 {
|
let form = match &src2 {
|
||||||
ALUSrc::None | ALUSrc::Reg(_) => {
|
ALUSrc::None | ALUSrc::Reg(_) => {
|
||||||
self.encode_alu_src2(&src2, RegFile::UGPR, false, true);
|
self.encode_alu_src2(&src2, RegFile::UGPR, false);
|
||||||
match &src1 {
|
match &src1 {
|
||||||
ALUSrc::None => 1_u8, // form
|
ALUSrc::None => 1_u8, // form
|
||||||
ALUSrc::Reg(reg1) => {
|
ALUSrc::Reg(reg1) => {
|
||||||
@@ -617,7 +572,7 @@ impl SM70Encoder<'_> {
|
|||||||
ALUSrc::UReg(_) => panic!("UALU never has UReg"),
|
ALUSrc::UReg(_) => panic!("UALU never has UReg"),
|
||||||
ALUSrc::Imm32(imm2) => {
|
ALUSrc::Imm32(imm2) => {
|
||||||
self.encode_alu_imm(imm2);
|
self.encode_alu_imm(imm2);
|
||||||
self.encode_alu_src2(&src1, RegFile::UGPR, false, true);
|
self.encode_alu_src2(&src1, RegFile::UGPR, false);
|
||||||
2_u8 // form
|
2_u8 // form
|
||||||
}
|
}
|
||||||
ALUSrc::CBuf(_) => panic!("UALU does not support cbufs"),
|
ALUSrc::CBuf(_) => panic!("UALU does not support cbufs"),
|
||||||
@@ -1112,19 +1067,9 @@ impl SM70Op for OpHFma2 {
|
|||||||
b.copy_alu_src_if_not_reg(src0, gpr, SrcType::F16v2);
|
b.copy_alu_src_if_not_reg(src0, gpr, SrcType::F16v2);
|
||||||
b.copy_alu_src_if_not_reg(src1, gpr, SrcType::F16v2);
|
b.copy_alu_src_if_not_reg(src1, gpr, SrcType::F16v2);
|
||||||
b.copy_alu_src_if_both_not_reg(src1, src2, gpr, SrcType::F16v2);
|
b.copy_alu_src_if_both_not_reg(src1, src2, gpr, SrcType::F16v2);
|
||||||
|
|
||||||
if !src1.src_mod.is_none() {
|
|
||||||
b.copy_alu_src_and_lower_fmod(src1, gpr, SrcType::F16v2);
|
|
||||||
}
|
|
||||||
if !src2.src_mod.is_none() {
|
|
||||||
b.copy_alu_src_and_lower_fmod(src2, gpr, SrcType::F16v2);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
fn encode(&self, e: &mut SM70Encoder<'_>) {
|
fn encode(&self, e: &mut SM70Encoder<'_>) {
|
||||||
assert!(self.srcs[1].src_mod.is_none());
|
|
||||||
assert!(self.srcs[2].src_mod.is_none());
|
|
||||||
|
|
||||||
e.encode_fp16_alu(
|
e.encode_fp16_alu(
|
||||||
0x031,
|
0x031,
|
||||||
Some(&self.dst),
|
Some(&self.dst),
|
||||||
|
Reference in New Issue
Block a user