diff options
| author | 2021-07-12 19:56:14 -0400 | |
|---|---|---|
| committer | 2021-07-22 21:51:40 -0400 | |
| commit | fc7bed21b539aac4fdde74a41217066eaf8ed3f9 (patch) | |
| tree | b76c4c93772f468d44e065cb3cae468060454b08 /src/shader_recompiler/frontend/maxwell | |
| parent | shader: Avoid usage of C++20 ranges to build in clang (diff) | |
| download | yuzu-fc7bed21b539aac4fdde74a41217066eaf8ed3f9.tar.gz yuzu-fc7bed21b539aac4fdde74a41217066eaf8ed3f9.tar.xz yuzu-fc7bed21b539aac4fdde74a41217066eaf8ed3f9.zip | |
shader: Implement ISETP.X
Diffstat (limited to 'src/shader_recompiler/frontend/maxwell')
4 files changed, 57 insertions, 44 deletions
diff --git a/src/shader_recompiler/frontend/maxwell/translate/impl/common_funcs.cpp b/src/shader_recompiler/frontend/maxwell/translate/impl/common_funcs.cpp index 10bb01d99..20458d2ad 100644 --- a/src/shader_recompiler/frontend/maxwell/translate/impl/common_funcs.cpp +++ b/src/shader_recompiler/frontend/maxwell/translate/impl/common_funcs.cpp | |||
| @@ -29,6 +29,49 @@ IR::U1 IntegerCompare(IR::IREmitter& ir, const IR::U32& operand_1, const IR::U32 | |||
| 29 | } | 29 | } |
| 30 | } | 30 | } |
| 31 | 31 | ||
| 32 | IR::U1 ExtendedIntegerCompare(IR::IREmitter& ir, const IR::U32& operand_1, const IR::U32& operand_2, | ||
| 33 | CompareOp compare_op, bool is_signed) { | ||
| 34 | const IR::U32 zero{ir.Imm32(0)}; | ||
| 35 | const IR::U32 carry{ir.Select(ir.GetCFlag(), ir.Imm32(1), zero)}; | ||
| 36 | const IR::U1 z_flag{ir.GetZFlag()}; | ||
| 37 | const IR::U32 intermediate{ir.IAdd(ir.IAdd(operand_1, ir.BitwiseNot(operand_2)), carry)}; | ||
| 38 | const IR::U1 flip_logic{is_signed ? ir.Imm1(false) | ||
| 39 | : ir.LogicalXor(ir.ILessThan(operand_1, zero, true), | ||
| 40 | ir.ILessThan(operand_2, zero, true))}; | ||
| 41 | switch (compare_op) { | ||
| 42 | case CompareOp::False: | ||
| 43 | return ir.Imm1(false); | ||
| 44 | case CompareOp::LessThan: | ||
| 45 | return IR::U1{ir.Select(flip_logic, ir.IGreaterThanEqual(intermediate, zero, true), | ||
| 46 | ir.ILessThan(intermediate, zero, true))}; | ||
| 47 | case CompareOp::Equal: | ||
| 48 | return ir.LogicalAnd(ir.IEqual(intermediate, zero), z_flag); | ||
| 49 | case CompareOp::LessThanEqual: { | ||
| 50 | const IR::U1 base_cmp{ir.Select(flip_logic, ir.IGreaterThanEqual(intermediate, zero, true), | ||
| 51 | ir.ILessThan(intermediate, zero, true))}; | ||
| 52 | return ir.LogicalOr(base_cmp, ir.LogicalAnd(ir.IEqual(intermediate, zero), z_flag)); | ||
| 53 | } | ||
| 54 | case CompareOp::GreaterThan: { | ||
| 55 | const IR::U1 base_cmp{ir.Select(flip_logic, ir.ILessThanEqual(intermediate, zero, true), | ||
| 56 | ir.IGreaterThan(intermediate, zero, true))}; | ||
| 57 | const IR::U1 not_z{ir.LogicalNot(z_flag)}; | ||
| 58 | return ir.LogicalOr(base_cmp, ir.LogicalAnd(ir.IEqual(intermediate, zero), not_z)); | ||
| 59 | } | ||
| 60 | case CompareOp::NotEqual: | ||
| 61 | return ir.LogicalOr(ir.INotEqual(intermediate, zero), | ||
| 62 | ir.LogicalAnd(ir.IEqual(intermediate, zero), ir.LogicalNot(z_flag))); | ||
| 63 | case CompareOp::GreaterThanEqual: { | ||
| 64 | const IR::U1 base_cmp{ir.Select(flip_logic, ir.ILessThan(intermediate, zero, true), | ||
| 65 | ir.IGreaterThanEqual(intermediate, zero, true))}; | ||
| 66 | return ir.LogicalOr(base_cmp, ir.LogicalAnd(ir.IEqual(intermediate, zero), z_flag)); | ||
| 67 | } | ||
| 68 | case CompareOp::True: | ||
| 69 | return ir.Imm1(true); | ||
| 70 | default: | ||
| 71 | throw NotImplementedException("Invalid compare op {}", compare_op); | ||
| 72 | } | ||
| 73 | } | ||
| 74 | |||
| 32 | IR::U1 PredicateCombine(IR::IREmitter& ir, const IR::U1& predicate_1, const IR::U1& predicate_2, | 75 | IR::U1 PredicateCombine(IR::IREmitter& ir, const IR::U1& predicate_1, const IR::U1& predicate_2, |
| 33 | BooleanOp bop) { | 76 | BooleanOp bop) { |
| 34 | switch (bop) { | 77 | switch (bop) { |
diff --git a/src/shader_recompiler/frontend/maxwell/translate/impl/common_funcs.h b/src/shader_recompiler/frontend/maxwell/translate/impl/common_funcs.h index f584060b3..214d0af3c 100644 --- a/src/shader_recompiler/frontend/maxwell/translate/impl/common_funcs.h +++ b/src/shader_recompiler/frontend/maxwell/translate/impl/common_funcs.h | |||
| @@ -11,6 +11,10 @@ namespace Shader::Maxwell { | |||
| 11 | [[nodiscard]] IR::U1 IntegerCompare(IR::IREmitter& ir, const IR::U32& operand_1, | 11 | [[nodiscard]] IR::U1 IntegerCompare(IR::IREmitter& ir, const IR::U32& operand_1, |
| 12 | const IR::U32& operand_2, CompareOp compare_op, bool is_signed); | 12 | const IR::U32& operand_2, CompareOp compare_op, bool is_signed); |
| 13 | 13 | ||
| 14 | [[nodiscard]] IR::U1 ExtendedIntegerCompare(IR::IREmitter& ir, const IR::U32& operand_1, | ||
| 15 | const IR::U32& operand_2, CompareOp compare_op, | ||
| 16 | bool is_signed); | ||
| 17 | |||
| 14 | [[nodiscard]] IR::U1 PredicateCombine(IR::IREmitter& ir, const IR::U1& predicate_1, | 18 | [[nodiscard]] IR::U1 PredicateCombine(IR::IREmitter& ir, const IR::U1& predicate_1, |
| 15 | const IR::U1& predicate_2, BooleanOp bop); | 19 | const IR::U1& predicate_2, BooleanOp bop); |
| 16 | 20 | ||
diff --git a/src/shader_recompiler/frontend/maxwell/translate/impl/integer_compare_and_set.cpp b/src/shader_recompiler/frontend/maxwell/translate/impl/integer_compare_and_set.cpp index 34fa7345c..8ce1aee04 100644 --- a/src/shader_recompiler/frontend/maxwell/translate/impl/integer_compare_and_set.cpp +++ b/src/shader_recompiler/frontend/maxwell/translate/impl/integer_compare_and_set.cpp | |||
| @@ -9,49 +9,6 @@ | |||
| 9 | 9 | ||
| 10 | namespace Shader::Maxwell { | 10 | namespace Shader::Maxwell { |
| 11 | namespace { | 11 | namespace { |
| 12 | IR::U1 ExtendedIntegerCompare(IR::IREmitter& ir, const IR::U32& operand_1, const IR::U32& operand_2, | ||
| 13 | CompareOp compare_op, bool is_signed) { | ||
| 14 | const IR::U32 zero{ir.Imm32(0)}; | ||
| 15 | const IR::U32 carry{ir.Select(ir.GetCFlag(), ir.Imm32(1), zero)}; | ||
| 16 | const IR::U1 z_flag{ir.GetZFlag()}; | ||
| 17 | const IR::U32 intermediate{ir.IAdd(ir.IAdd(operand_1, ir.BitwiseNot(operand_2)), carry)}; | ||
| 18 | const IR::U1 flip_logic{is_signed ? ir.Imm1(false) | ||
| 19 | : ir.LogicalXor(ir.ILessThan(operand_1, zero, true), | ||
| 20 | ir.ILessThan(operand_2, zero, true))}; | ||
| 21 | switch (compare_op) { | ||
| 22 | case CompareOp::False: | ||
| 23 | return ir.Imm1(false); | ||
| 24 | case CompareOp::LessThan: | ||
| 25 | return IR::U1{ir.Select(flip_logic, ir.IGreaterThanEqual(intermediate, zero, true), | ||
| 26 | ir.ILessThan(intermediate, zero, true))}; | ||
| 27 | case CompareOp::Equal: | ||
| 28 | return ir.LogicalAnd(ir.IEqual(intermediate, zero), z_flag); | ||
| 29 | case CompareOp::LessThanEqual: { | ||
| 30 | const IR::U1 base_cmp{ir.Select(flip_logic, ir.IGreaterThanEqual(intermediate, zero, true), | ||
| 31 | ir.ILessThan(intermediate, zero, true))}; | ||
| 32 | return ir.LogicalOr(base_cmp, ir.LogicalAnd(ir.IEqual(intermediate, zero), z_flag)); | ||
| 33 | } | ||
| 34 | case CompareOp::GreaterThan: { | ||
| 35 | const IR::U1 base_cmp{ir.Select(flip_logic, ir.ILessThanEqual(intermediate, zero, true), | ||
| 36 | ir.IGreaterThan(intermediate, zero, true))}; | ||
| 37 | const IR::U1 not_z{ir.LogicalNot(z_flag)}; | ||
| 38 | return ir.LogicalOr(base_cmp, ir.LogicalAnd(ir.IEqual(intermediate, zero), not_z)); | ||
| 39 | } | ||
| 40 | case CompareOp::NotEqual: | ||
| 41 | return ir.LogicalOr(ir.INotEqual(intermediate, zero), | ||
| 42 | ir.LogicalAnd(ir.IEqual(intermediate, zero), ir.LogicalNot(z_flag))); | ||
| 43 | case CompareOp::GreaterThanEqual: { | ||
| 44 | const IR::U1 base_cmp{ir.Select(flip_logic, ir.ILessThan(intermediate, zero, true), | ||
| 45 | ir.IGreaterThanEqual(intermediate, zero, true))}; | ||
| 46 | return ir.LogicalOr(base_cmp, ir.LogicalAnd(ir.IEqual(intermediate, zero), z_flag)); | ||
| 47 | } | ||
| 48 | case CompareOp::True: | ||
| 49 | return ir.Imm1(true); | ||
| 50 | default: | ||
| 51 | throw NotImplementedException("Invalid compare op {}", compare_op); | ||
| 52 | } | ||
| 53 | } | ||
| 54 | |||
| 55 | IR::U1 IsetCompare(IR::IREmitter& ir, const IR::U32& operand_1, const IR::U32& operand_2, | 12 | IR::U1 IsetCompare(IR::IREmitter& ir, const IR::U32& operand_1, const IR::U32& operand_2, |
| 56 | CompareOp compare_op, bool is_signed, bool x) { | 13 | CompareOp compare_op, bool is_signed, bool x) { |
| 57 | return x ? ExtendedIntegerCompare(ir, operand_1, operand_2, compare_op, is_signed) | 14 | return x ? ExtendedIntegerCompare(ir, operand_1, operand_2, compare_op, is_signed) |
diff --git a/src/shader_recompiler/frontend/maxwell/translate/impl/integer_set_predicate.cpp b/src/shader_recompiler/frontend/maxwell/translate/impl/integer_set_predicate.cpp index 7743701d0..bee10e5b9 100644 --- a/src/shader_recompiler/frontend/maxwell/translate/impl/integer_set_predicate.cpp +++ b/src/shader_recompiler/frontend/maxwell/translate/impl/integer_set_predicate.cpp | |||
| @@ -9,6 +9,12 @@ | |||
| 9 | 9 | ||
| 10 | namespace Shader::Maxwell { | 10 | namespace Shader::Maxwell { |
| 11 | namespace { | 11 | namespace { |
| 12 | IR::U1 IsetpCompare(IR::IREmitter& ir, const IR::U32& operand_1, const IR::U32& operand_2, | ||
| 13 | CompareOp compare_op, bool is_signed, bool x) { | ||
| 14 | return x ? ExtendedIntegerCompare(ir, operand_1, operand_2, compare_op, is_signed) | ||
| 15 | : IntegerCompare(ir, operand_1, operand_2, compare_op, is_signed); | ||
| 16 | } | ||
| 17 | |||
| 12 | void ISETP(TranslatorVisitor& v, u64 insn, const IR::U32& op_b) { | 18 | void ISETP(TranslatorVisitor& v, u64 insn, const IR::U32& op_b) { |
| 13 | union { | 19 | union { |
| 14 | u64 raw; | 20 | u64 raw; |
| @@ -17,15 +23,18 @@ void ISETP(TranslatorVisitor& v, u64 insn, const IR::U32& op_b) { | |||
| 17 | BitField<8, 8, IR::Reg> src_reg_a; | 23 | BitField<8, 8, IR::Reg> src_reg_a; |
| 18 | BitField<39, 3, IR::Pred> bop_pred; | 24 | BitField<39, 3, IR::Pred> bop_pred; |
| 19 | BitField<42, 1, u64> neg_bop_pred; | 25 | BitField<42, 1, u64> neg_bop_pred; |
| 26 | BitField<43, 1, u64> x; | ||
| 20 | BitField<45, 2, BooleanOp> bop; | 27 | BitField<45, 2, BooleanOp> bop; |
| 21 | BitField<48, 1, u64> is_signed; | 28 | BitField<48, 1, u64> is_signed; |
| 22 | BitField<49, 3, CompareOp> compare_op; | 29 | BitField<49, 3, CompareOp> compare_op; |
| 23 | } const isetp{insn}; | 30 | } const isetp{insn}; |
| 24 | 31 | ||
| 32 | const bool is_signed{isetp.is_signed != 0}; | ||
| 33 | const bool x{isetp.x != 0}; | ||
| 25 | const BooleanOp bop{isetp.bop}; | 34 | const BooleanOp bop{isetp.bop}; |
| 26 | const CompareOp compare_op{isetp.compare_op}; | 35 | const CompareOp compare_op{isetp.compare_op}; |
| 27 | const IR::U32 op_a{v.X(isetp.src_reg_a)}; | 36 | const IR::U32 op_a{v.X(isetp.src_reg_a)}; |
| 28 | const IR::U1 comparison{IntegerCompare(v.ir, op_a, op_b, compare_op, isetp.is_signed != 0)}; | 37 | const IR::U1 comparison{IsetpCompare(v.ir, op_a, op_b, compare_op, is_signed, x)}; |
| 29 | const IR::U1 bop_pred{v.ir.GetPred(isetp.bop_pred, isetp.neg_bop_pred != 0)}; | 38 | const IR::U1 bop_pred{v.ir.GetPred(isetp.bop_pred, isetp.neg_bop_pred != 0)}; |
| 30 | const IR::U1 result_a{PredicateCombine(v.ir, comparison, bop_pred, bop)}; | 39 | const IR::U1 result_a{PredicateCombine(v.ir, comparison, bop_pred, bop)}; |
| 31 | const IR::U1 result_b{PredicateCombine(v.ir, v.ir.LogicalNot(comparison), bop_pred, bop)}; | 40 | const IR::U1 result_b{PredicateCombine(v.ir, v.ir.LogicalNot(comparison), bop_pred, bop)}; |