mirror of
https://github.com/yuzu-mirror/yuzu
synced 2024-12-19 17:53:08 +00:00
shader: Implement CC for ISET, FSET, PSET, CSET, and DSET
Throw when other instructions are missing CC.
This commit is contained in:
parent
8cea39b5a6
commit
1be6705408
18 changed files with 136 additions and 13 deletions
|
@ -14,9 +14,14 @@ void BFE(TranslatorVisitor& v, u64 insn, const IR::U32& src) {
|
|||
BitField<0, 8, IR::Reg> dest_reg;
|
||||
BitField<8, 8, IR::Reg> offset_reg;
|
||||
BitField<40, 1, u64> brev;
|
||||
BitField<47, 1, u64> cc;
|
||||
BitField<48, 1, u64> is_signed;
|
||||
} const bfe{insn};
|
||||
|
||||
if (bfe.cc != 0) {
|
||||
throw NotImplementedException("BFE CC");
|
||||
}
|
||||
|
||||
const IR::U32 offset{v.ir.BitFieldExtract(src, v.ir.Imm32(0), v.ir.Imm32(8), false)};
|
||||
const IR::U32 count{v.ir.BitFieldExtract(src, v.ir.Imm32(8), v.ir.Imm32(8), false)};
|
||||
|
||||
|
|
|
@ -13,8 +13,13 @@ void BFI(TranslatorVisitor& v, u64 insn, const IR::U32& src_a, const IR::U32& ba
|
|||
u64 insn;
|
||||
BitField<0, 8, IR::Reg> dest_reg;
|
||||
BitField<8, 8, IR::Reg> insert_reg;
|
||||
BitField<47, 1, u64> cc;
|
||||
} const bfi{insn};
|
||||
|
||||
if (bfi.cc != 0) {
|
||||
throw NotImplementedException("BFI CC");
|
||||
}
|
||||
|
||||
const IR::U32 offset{v.ir.BitFieldExtract(src_a, v.ir.Imm32(0), v.ir.Imm32(8), false)};
|
||||
const IR::U32 unsafe_count{v.ir.BitFieldExtract(src_a, v.ir.Imm32(8), v.ir.Imm32(8), false)};
|
||||
const IR::U32 max_size{v.ir.Imm32(32)};
|
||||
|
|
|
@ -18,17 +18,29 @@ void TranslatorVisitor::CSET(u64 insn) {
|
|||
BitField<42, 1, u64> neg_bop_pred;
|
||||
BitField<44, 1, u64> bf;
|
||||
BitField<45, 2, BooleanOp> bop;
|
||||
BitField<47, 1, u64> cc;
|
||||
} const cset{insn};
|
||||
|
||||
const IR::U32 one_mask{ir.Imm32(-1)};
|
||||
const IR::U32 fp_one{ir.Imm32(0x3f800000)};
|
||||
const IR::U32 fail_result{ir.Imm32(0)};
|
||||
const IR::U32 zero{ir.Imm32(0)};
|
||||
const IR::U32 pass_result{cset.bf == 0 ? one_mask : fp_one};
|
||||
const IR::U1 cc_test_result{ir.GetFlowTestResult(cset.cc_test)};
|
||||
const IR::U1 bop_pred{ir.GetPred(cset.bop_pred, cset.neg_bop_pred != 0)};
|
||||
const IR::U1 pred_result{PredicateCombine(ir, cc_test_result, bop_pred, cset.bop)};
|
||||
const IR::U32 result{ir.Select(pred_result, pass_result, fail_result)};
|
||||
const IR::U32 result{ir.Select(pred_result, pass_result, zero)};
|
||||
X(cset.dest_reg, result);
|
||||
if (cset.cc != 0) {
|
||||
const IR::U1 is_zero{ir.IEqual(result, zero)};
|
||||
SetZFlag(is_zero);
|
||||
if (cset.bf != 0) {
|
||||
ResetSFlag();
|
||||
} else {
|
||||
SetSFlag(ir.LogicalNot(is_zero));
|
||||
}
|
||||
ResetOFlag();
|
||||
ResetCFlag();
|
||||
}
|
||||
}
|
||||
|
||||
void TranslatorVisitor::CSETP(u64 insn) {
|
||||
|
|
|
@ -19,6 +19,7 @@ void DSET(TranslatorVisitor& v, u64 insn, const IR::F64& src_b) {
|
|||
BitField<43, 1, u64> negate_a;
|
||||
BitField<44, 1, u64> abs_b;
|
||||
BitField<45, 2, BooleanOp> bop;
|
||||
BitField<47, 1, u64> cc;
|
||||
BitField<48, 4, FPCompareOp> compare_op;
|
||||
BitField<52, 1, u64> bf;
|
||||
BitField<53, 1, u64> negate_b;
|
||||
|
@ -37,10 +38,22 @@ void DSET(TranslatorVisitor& v, u64 insn, const IR::F64& src_b) {
|
|||
|
||||
const IR::U32 one_mask{v.ir.Imm32(-1)};
|
||||
const IR::U32 fp_one{v.ir.Imm32(0x3f800000)};
|
||||
const IR::U32 fail_result{v.ir.Imm32(0)};
|
||||
const IR::U32 zero{v.ir.Imm32(0)};
|
||||
const IR::U32 pass_result{dset.bf == 0 ? one_mask : fp_one};
|
||||
const IR::U32 result{v.ir.Select(bop_result, pass_result, zero)};
|
||||
|
||||
v.X(dset.dest_reg, IR::U32{v.ir.Select(bop_result, pass_result, fail_result)});
|
||||
v.X(dset.dest_reg, result);
|
||||
if (dset.cc != 0) {
|
||||
const IR::U1 is_zero{v.ir.IEqual(result, zero)};
|
||||
v.SetZFlag(is_zero);
|
||||
if (dset.bf != 0) {
|
||||
v.ResetSFlag();
|
||||
} else {
|
||||
v.SetSFlag(v.ir.LogicalNot(is_zero));
|
||||
}
|
||||
v.ResetCFlag();
|
||||
v.ResetOFlag();
|
||||
}
|
||||
}
|
||||
} // Anonymous namespace
|
||||
|
||||
|
|
|
@ -16,10 +16,15 @@ void DFMA(TranslatorVisitor& v, u64 insn, const IR::F64& src_b, const IR::F64& s
|
|||
BitField<0, 8, IR::Reg> dest_reg;
|
||||
BitField<8, 8, IR::Reg> src_a_reg;
|
||||
BitField<50, 2, FpRounding> fp_rounding;
|
||||
BitField<47, 1, u64> cc;
|
||||
BitField<48, 1, u64> neg_b;
|
||||
BitField<49, 1, u64> neg_c;
|
||||
} const dfma{insn};
|
||||
|
||||
if (dfma.cc != 0) {
|
||||
throw NotImplementedException("DFMA CC");
|
||||
}
|
||||
|
||||
const IR::F64 src_a{v.D(dfma.src_a_reg)};
|
||||
const IR::F64 op_b{v.ir.FPAbsNeg(src_b, false, dfma.neg_b != 0)};
|
||||
const IR::F64 op_c{v.ir.FPAbsNeg(src_c, false, dfma.neg_c != 0)};
|
||||
|
|
|
@ -17,10 +17,15 @@ void DMNMX(TranslatorVisitor& v, u64 insn, const IR::F64& src_b) {
|
|||
BitField<42, 1, u64> neg_pred;
|
||||
BitField<45, 1, u64> negate_b;
|
||||
BitField<46, 1, u64> abs_a;
|
||||
BitField<47, 1, u64> cc;
|
||||
BitField<48, 1, u64> negate_a;
|
||||
BitField<49, 1, u64> abs_b;
|
||||
} const dmnmx{insn};
|
||||
|
||||
if (dmnmx.cc != 0) {
|
||||
throw NotImplementedException("DMNMX CC");
|
||||
}
|
||||
|
||||
const IR::U1 pred{v.ir.GetPred(dmnmx.pred)};
|
||||
const IR::F64 op_a{v.ir.FPAbsNeg(v.D(dmnmx.src_a_reg), dmnmx.abs_a != 0, dmnmx.negate_a != 0)};
|
||||
const IR::F64 op_b{v.ir.FPAbsNeg(src_b, dmnmx.abs_b != 0, dmnmx.negate_b != 0)};
|
||||
|
|
|
@ -16,9 +16,14 @@ void DMUL(TranslatorVisitor& v, u64 insn, const IR::F64& src_b) {
|
|||
BitField<0, 8, IR::Reg> dest_reg;
|
||||
BitField<8, 8, IR::Reg> src_a_reg;
|
||||
BitField<39, 2, FpRounding> fp_rounding;
|
||||
BitField<47, 1, u64> cc;
|
||||
BitField<48, 1, u64> neg;
|
||||
} const dmul{insn};
|
||||
|
||||
if (dmul.cc != 0) {
|
||||
throw NotImplementedException("DMUL CC");
|
||||
}
|
||||
|
||||
const IR::F64 src_a{v.ir.FPAbsNeg(v.D(dmul.src_a_reg), false, dmul.neg != 0)};
|
||||
const IR::FpControl control{
|
||||
.no_contraction = true,
|
||||
|
|
|
@ -19,6 +19,7 @@ void FSET(TranslatorVisitor& v, u64 insn, const IR::F32& src_b) {
|
|||
BitField<43, 1, u64> negate_a;
|
||||
BitField<44, 1, u64> abs_b;
|
||||
BitField<45, 2, BooleanOp> bop;
|
||||
BitField<47, 1, u64> cc;
|
||||
BitField<48, 4, FPCompareOp> compare_op;
|
||||
BitField<52, 1, u64> bf;
|
||||
BitField<53, 1, u64> negate_b;
|
||||
|
@ -43,10 +44,22 @@ void FSET(TranslatorVisitor& v, u64 insn, const IR::F32& src_b) {
|
|||
|
||||
const IR::U32 one_mask{v.ir.Imm32(-1)};
|
||||
const IR::U32 fp_one{v.ir.Imm32(0x3f800000)};
|
||||
const IR::U32 fail_result{v.ir.Imm32(0)};
|
||||
const IR::U32 zero{v.ir.Imm32(0)};
|
||||
const IR::U32 pass_result{fset.bf == 0 ? one_mask : fp_one};
|
||||
const IR::U32 result{v.ir.Select(bop_result, pass_result, zero)};
|
||||
|
||||
v.X(fset.dest_reg, IR::U32{v.ir.Select(bop_result, pass_result, fail_result)});
|
||||
v.X(fset.dest_reg, result);
|
||||
if (fset.cc != 0) {
|
||||
const IR::U1 is_zero{v.ir.IEqual(result, zero)};
|
||||
v.SetZFlag(is_zero);
|
||||
if (fset.bf != 0) {
|
||||
v.ResetSFlag();
|
||||
} else {
|
||||
v.SetSFlag(v.ir.LogicalNot(is_zero));
|
||||
}
|
||||
v.ResetCFlag();
|
||||
v.ResetOFlag();
|
||||
}
|
||||
}
|
||||
} // Anonymous namespace
|
||||
|
||||
|
|
|
@ -41,6 +41,7 @@ void F2F(TranslatorVisitor& v, u64 insn, const IR::F16F32F64& src_a, bool abs) {
|
|||
BitField<0, 8, IR::Reg> dest_reg;
|
||||
BitField<44, 1, u64> ftz;
|
||||
BitField<45, 1, u64> neg;
|
||||
BitField<47, 1, u64> cc;
|
||||
BitField<50, 1, u64> sat;
|
||||
BitField<39, 4, u64> rounding_op;
|
||||
BitField<39, 2, FpRounding> rounding;
|
||||
|
@ -53,6 +54,10 @@ void F2F(TranslatorVisitor& v, u64 insn, const IR::F16F32F64& src_a, bool abs) {
|
|||
}
|
||||
} const f2f{insn};
|
||||
|
||||
if (f2f.cc != 0) {
|
||||
throw NotImplementedException("F2F CC");
|
||||
}
|
||||
|
||||
IR::F16F32F64 input{v.ir.FPAbsNeg(src_a, abs, f2f.neg != 0)};
|
||||
|
||||
const bool any_fp64{f2f.src_size == FloatFormat::F64 || f2f.dst_size == FloatFormat::F64};
|
||||
|
|
|
@ -18,10 +18,15 @@ void FMNMX(TranslatorVisitor& v, u64 insn, const IR::F32& src_b) {
|
|||
BitField<44, 1, u64> ftz;
|
||||
BitField<45, 1, u64> negate_b;
|
||||
BitField<46, 1, u64> abs_a;
|
||||
BitField<47, 1, u64> cc;
|
||||
BitField<48, 1, u64> negate_a;
|
||||
BitField<49, 1, u64> abs_b;
|
||||
} const fmnmx{insn};
|
||||
|
||||
if (fmnmx.cc) {
|
||||
throw NotImplementedException("FMNMX CC");
|
||||
}
|
||||
|
||||
const IR::U1 pred{v.ir.GetPred(fmnmx.pred)};
|
||||
const IR::F32 op_a{v.ir.FPAbsNeg(v.F(fmnmx.src_a_reg), fmnmx.abs_a != 0, fmnmx.negate_a != 0)};
|
||||
const IR::F32 op_b{v.ir.FPAbsNeg(src_b, fmnmx.abs_b != 0, fmnmx.negate_b != 0)};
|
||||
|
|
|
@ -19,6 +19,7 @@ void ISET(TranslatorVisitor& v, u64 insn, const IR::U32& src_a) {
|
|||
BitField<43, 1, u64> x;
|
||||
BitField<44, 1, u64> bf;
|
||||
BitField<45, 2, BooleanOp> bop;
|
||||
BitField<47, 1, u64> cc;
|
||||
BitField<48, 1, u64> is_signed;
|
||||
BitField<49, 3, CompareOp> compare_op;
|
||||
} const iset{insn};
|
||||
|
@ -38,12 +39,22 @@ void ISET(TranslatorVisitor& v, u64 insn, const IR::U32& src_a) {
|
|||
|
||||
const IR::U32 one_mask{v.ir.Imm32(-1)};
|
||||
const IR::U32 fp_one{v.ir.Imm32(0x3f800000)};
|
||||
const IR::U32 fail_result{v.ir.Imm32(0)};
|
||||
const IR::U32 zero{v.ir.Imm32(0)};
|
||||
const IR::U32 pass_result{iset.bf == 0 ? one_mask : fp_one};
|
||||
|
||||
const IR::U32 result{v.ir.Select(bop_result, pass_result, fail_result)};
|
||||
const IR::U32 result{v.ir.Select(bop_result, pass_result, zero)};
|
||||
|
||||
v.X(iset.dest_reg, result);
|
||||
if (iset.cc != 0) {
|
||||
const IR::U1 is_zero{v.ir.IEqual(result, zero)};
|
||||
v.SetZFlag(is_zero);
|
||||
if (iset.bf != 0) {
|
||||
v.ResetSFlag();
|
||||
} else {
|
||||
v.SetSFlag(v.ir.LogicalNot(is_zero));
|
||||
}
|
||||
v.ResetCFlag();
|
||||
v.ResetOFlag();
|
||||
}
|
||||
}
|
||||
} // Anonymous namespace
|
||||
|
||||
|
|
|
@ -62,7 +62,7 @@ IR::U32 SmallAbs(TranslatorVisitor& v, const IR::U32& value, int bitsize) {
|
|||
void I2F(TranslatorVisitor& v, u64 insn, IR::U32U64 src) {
|
||||
const Encoding i2f{insn};
|
||||
if (i2f.cc != 0) {
|
||||
throw NotImplementedException("CC");
|
||||
throw NotImplementedException("I2F CC");
|
||||
}
|
||||
const bool is_signed{i2f.is_signed != 0};
|
||||
int src_bitsize{};
|
||||
|
|
|
@ -33,9 +33,14 @@ void SHF(TranslatorVisitor& v, u64 insn, const IR::U32& shift, const IR::U32& hi
|
|||
BitField<0, 8, IR::Reg> dest_reg;
|
||||
BitField<0, 8, IR::Reg> lo_bits_reg;
|
||||
BitField<37, 2, MaxShift> max_shift;
|
||||
BitField<47, 1, u64> cc;
|
||||
BitField<48, 2, u64> x_mode;
|
||||
BitField<50, 1, u64> wrap;
|
||||
} const shf{insn};
|
||||
|
||||
if (shf.cc != 0) {
|
||||
throw NotImplementedException("SHF CC");
|
||||
}
|
||||
if (shf.x_mode != 0) {
|
||||
throw NotImplementedException("SHF X Mode");
|
||||
}
|
||||
|
|
|
@ -16,9 +16,14 @@ void IMNMX(TranslatorVisitor& v, u64 insn, const IR::U32& op_b) {
|
|||
BitField<39, 3, IR::Pred> pred;
|
||||
BitField<42, 1, u64> neg_pred;
|
||||
BitField<43, 2, u64> mode;
|
||||
BitField<47, 1, u64> cc;
|
||||
BitField<48, 1, u64> is_signed;
|
||||
} const imnmx{insn};
|
||||
|
||||
if (imnmx.cc != 0) {
|
||||
throw NotImplementedException("IMNMX CC");
|
||||
}
|
||||
|
||||
if (imnmx.mode != 0) {
|
||||
throw NotImplementedException("IMNMX.MODE");
|
||||
}
|
||||
|
|
|
@ -16,12 +16,16 @@ void SHR(TranslatorVisitor& v, u64 insn, const IR::U32& shift) {
|
|||
BitField<39, 1, u64> is_wrapped;
|
||||
BitField<40, 1, u64> brev;
|
||||
BitField<43, 1, u64> xmode;
|
||||
BitField<47, 1, u64> cc;
|
||||
BitField<48, 1, u64> is_signed;
|
||||
} const shr{insn};
|
||||
|
||||
if (shr.xmode != 0) {
|
||||
throw NotImplementedException("SHR.XMODE");
|
||||
}
|
||||
if (shr.cc != 0) {
|
||||
throw NotImplementedException("SHR.CC");
|
||||
}
|
||||
|
||||
IR::U32 base{v.X(shr.src_reg_a)};
|
||||
if (shr.brev == 1) {
|
||||
|
|
|
@ -14,6 +14,7 @@ void LEA_hi(TranslatorVisitor& v, u64 insn, const IR::U32& base, IR::U32 offset_
|
|||
u64 insn;
|
||||
BitField<0, 8, IR::Reg> dest_reg;
|
||||
BitField<8, 8, IR::Reg> offset_lo_reg;
|
||||
BitField<47, 1, u64> cc;
|
||||
BitField<48, 3, IR::Pred> pred;
|
||||
} const lea{insn};
|
||||
|
||||
|
@ -21,7 +22,10 @@ void LEA_hi(TranslatorVisitor& v, u64 insn, const IR::U32& base, IR::U32 offset_
|
|||
throw NotImplementedException("LEA.HI X");
|
||||
}
|
||||
if (lea.pred != IR::Pred::PT) {
|
||||
throw NotImplementedException("LEA.LO Pred");
|
||||
throw NotImplementedException("LEA.HI Pred");
|
||||
}
|
||||
if (lea.cc != 0) {
|
||||
throw NotImplementedException("LEA.HI CC");
|
||||
}
|
||||
|
||||
const IR::U32 offset_lo{v.X(lea.offset_lo_reg)};
|
||||
|
@ -44,6 +48,7 @@ void LEA_lo(TranslatorVisitor& v, u64 insn, const IR::U32& base) {
|
|||
BitField<39, 5, u64> scale;
|
||||
BitField<45, 1, u64> neg;
|
||||
BitField<46, 1, u64> x;
|
||||
BitField<47, 1, u64> cc;
|
||||
BitField<48, 3, IR::Pred> pred;
|
||||
} const lea{insn};
|
||||
if (lea.x != 0) {
|
||||
|
@ -52,6 +57,9 @@ void LEA_lo(TranslatorVisitor& v, u64 insn, const IR::U32& base) {
|
|||
if (lea.pred != IR::Pred::PT) {
|
||||
throw NotImplementedException("LEA.LO Pred");
|
||||
}
|
||||
if (lea.cc != 0) {
|
||||
throw NotImplementedException("LEA.LO CC");
|
||||
}
|
||||
|
||||
const IR::U32 offset_lo{v.X(lea.offset_lo_reg)};
|
||||
const s32 scale{static_cast<s32>(lea.scale)};
|
||||
|
|
|
@ -73,8 +73,13 @@ IR::U32 LOP3(TranslatorVisitor& v, u64 insn, const IR::U32& op_b, const IR::U32&
|
|||
u64 insn;
|
||||
BitField<0, 8, IR::Reg> dest_reg;
|
||||
BitField<8, 8, IR::Reg> src_reg;
|
||||
BitField<47, 1, u64> cc;
|
||||
} const lop3{insn};
|
||||
|
||||
if (lop3.cc != 0) {
|
||||
throw NotImplementedException("LOP3 CC");
|
||||
}
|
||||
|
||||
const IR::U32 op_a{v.X(lop3.src_reg)};
|
||||
const IR::U32 result{ApplyLUT(v.ir, op_a, op_b, op_c, lut)};
|
||||
v.X(lop3.dest_reg, result);
|
||||
|
|
|
@ -21,6 +21,7 @@ void TranslatorVisitor::PSET(u64 insn) {
|
|||
BitField<42, 1, u64> neg_pred_c;
|
||||
BitField<44, 1, u64> bf;
|
||||
BitField<45, 2, BooleanOp> bop_2;
|
||||
BitField<47, 1, u64> cc;
|
||||
} const pset{insn};
|
||||
|
||||
const IR::U1 pred_a{ir.GetPred(pset.pred_a, pset.neg_pred_a != 0)};
|
||||
|
@ -31,11 +32,22 @@ void TranslatorVisitor::PSET(u64 insn) {
|
|||
const IR::U1 res_2{PredicateCombine(ir, res_1, pred_c, pset.bop_2)};
|
||||
|
||||
const IR::U32 true_result{pset.bf != 0 ? ir.Imm32(0x3f800000) : ir.Imm32(-1)};
|
||||
const IR::U32 false_result{ir.Imm32(0)};
|
||||
const IR::U32 zero{ir.Imm32(0)};
|
||||
|
||||
const IR::U32 result{ir.Select(res_2, true_result, false_result)};
|
||||
const IR::U32 result{ir.Select(res_2, true_result, zero)};
|
||||
|
||||
X(pset.dest_reg, result);
|
||||
if (pset.cc != 0) {
|
||||
const IR::U1 is_zero{ir.IEqual(result, zero)};
|
||||
SetZFlag(is_zero);
|
||||
if (pset.bf != 0) {
|
||||
ResetSFlag();
|
||||
} else {
|
||||
SetSFlag(ir.LogicalNot(is_zero));
|
||||
}
|
||||
ResetOFlag();
|
||||
ResetCFlag();
|
||||
}
|
||||
}
|
||||
|
||||
} // namespace Shader::Maxwell
|
||||
|
|
Loading…
Reference in a new issue