diff options
| author | 2021-03-01 01:30:09 -0500 | |
|---|---|---|
| committer | 2021-07-22 21:51:23 -0400 | |
| commit | e0389286165805258fa2e54014c2dc506ffb9f35 (patch) | |
| tree | d7830153aac3a2ad93fd93f8b74516bbeb8f3718 /src/shader_recompiler/frontend | |
| parent | shader: Make IMNMX, SHR, SEL stylistically more consistent (diff) | |
| download | yuzu-e0389286165805258fa2e54014c2dc506ffb9f35.tar.gz yuzu-e0389286165805258fa2e54014c2dc506ffb9f35.tar.xz yuzu-e0389286165805258fa2e54014c2dc506ffb9f35.zip | |
shader: Implement ISET, add common_funcs
Diffstat (limited to 'src/shader_recompiler/frontend')
7 files changed, 147 insertions, 50 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 new file mode 100644 index 000000000..3ec146b1a --- /dev/null +++ b/src/shader_recompiler/frontend/maxwell/translate/impl/common_funcs.cpp | |||
| @@ -0,0 +1,46 @@ | |||
| 1 | // Copyright 2021 yuzu Emulator Project | ||
| 2 | // Licensed under GPLv2 or any later version | ||
| 3 | // Refer to the license.txt file included. | ||
| 4 | |||
| 5 | #include "shader_recompiler/frontend/maxwell/translate/impl/common_funcs.h" | ||
| 6 | |||
| 7 | namespace Shader::Maxwell { | ||
| 8 | [[nodiscard]] IR::U1 IntegerCompare(TranslatorVisitor& v, const IR::U32& operand_1, | ||
| 9 | const IR::U32& operand_2, ComparisonOp compare_op, | ||
| 10 | bool is_signed) { | ||
| 11 | switch (compare_op) { | ||
| 12 | case ComparisonOp::False: | ||
| 13 | return v.ir.Imm1(false); | ||
| 14 | case ComparisonOp::LessThan: | ||
| 15 | return v.ir.ILessThan(operand_1, operand_2, is_signed); | ||
| 16 | case ComparisonOp::Equal: | ||
| 17 | return v.ir.IEqual(operand_1, operand_2); | ||
| 18 | case ComparisonOp::LessThanEqual: | ||
| 19 | return v.ir.ILessThanEqual(operand_1, operand_2, is_signed); | ||
| 20 | case ComparisonOp::GreaterThan: | ||
| 21 | return v.ir.IGreaterThan(operand_1, operand_2, is_signed); | ||
| 22 | case ComparisonOp::NotEqual: | ||
| 23 | return v.ir.INotEqual(operand_1, operand_2); | ||
| 24 | case ComparisonOp::GreaterThanEqual: | ||
| 25 | return v.ir.IGreaterThanEqual(operand_1, operand_2, is_signed); | ||
| 26 | case ComparisonOp::True: | ||
| 27 | return v.ir.Imm1(true); | ||
| 28 | default: | ||
| 29 | throw NotImplementedException("CMP"); | ||
| 30 | } | ||
| 31 | } | ||
| 32 | |||
| 33 | [[nodiscard]] IR::U1 PredicateCombine(TranslatorVisitor& v, const IR::U1& predicate_1, | ||
| 34 | const IR::U1& predicate_2, BooleanOp bop) { | ||
| 35 | switch (bop) { | ||
| 36 | case BooleanOp::And: | ||
| 37 | return v.ir.LogicalAnd(predicate_1, predicate_2); | ||
| 38 | case BooleanOp::Or: | ||
| 39 | return v.ir.LogicalOr(predicate_1, predicate_2); | ||
| 40 | case BooleanOp::Xor: | ||
| 41 | return v.ir.LogicalXor(predicate_1, predicate_2); | ||
| 42 | default: | ||
| 43 | throw NotImplementedException("BOP"); | ||
| 44 | } | ||
| 45 | } | ||
| 46 | } // namespace Shader::Maxwell | ||
diff --git a/src/shader_recompiler/frontend/maxwell/translate/impl/common_funcs.h b/src/shader_recompiler/frontend/maxwell/translate/impl/common_funcs.h new file mode 100644 index 000000000..293fcce2e --- /dev/null +++ b/src/shader_recompiler/frontend/maxwell/translate/impl/common_funcs.h | |||
| @@ -0,0 +1,17 @@ | |||
| 1 | // Copyright 2021 yuzu Emulator Project | ||
| 2 | // Licensed under GPLv2 or any later version | ||
| 3 | // Refer to the license.txt file included. | ||
| 4 | |||
| 5 | #pragma once | ||
| 6 | |||
| 7 | #include "common/common_types.h" | ||
| 8 | #include "shader_recompiler/frontend/maxwell/translate/impl/impl.h" | ||
| 9 | |||
| 10 | namespace Shader::Maxwell { | ||
| 11 | [[nodiscard]] IR::U1 IntegerCompare(TranslatorVisitor& v, const IR::U32& operand_1, | ||
| 12 | const IR::U32& operand_2, ComparisonOp compare_op, | ||
| 13 | bool is_signed); | ||
| 14 | |||
| 15 | [[nodiscard]] IR::U1 PredicateCombine(TranslatorVisitor& v, const IR::U1& predicate_1, | ||
| 16 | const IR::U1& predicate_2, BooleanOp bop); | ||
| 17 | } // namespace Shader::Maxwell | ||
diff --git a/src/shader_recompiler/frontend/maxwell/translate/impl/impl.h b/src/shader_recompiler/frontend/maxwell/translate/impl/impl.h index 672e140b2..232f8c894 100644 --- a/src/shader_recompiler/frontend/maxwell/translate/impl/impl.h +++ b/src/shader_recompiler/frontend/maxwell/translate/impl/impl.h | |||
| @@ -2,6 +2,8 @@ | |||
| 2 | // Licensed under GPLv2 or any later version | 2 | // Licensed under GPLv2 or any later version |
| 3 | // Refer to the license.txt file included. | 3 | // Refer to the license.txt file included. |
| 4 | 4 | ||
| 5 | #pragma once | ||
| 6 | |||
| 5 | #include "shader_recompiler/environment.h" | 7 | #include "shader_recompiler/environment.h" |
| 6 | #include "shader_recompiler/frontend/ir/basic_block.h" | 8 | #include "shader_recompiler/frontend/ir/basic_block.h" |
| 7 | #include "shader_recompiler/frontend/ir/ir_emitter.h" | 9 | #include "shader_recompiler/frontend/ir/ir_emitter.h" |
| @@ -9,6 +11,23 @@ | |||
| 9 | 11 | ||
| 10 | namespace Shader::Maxwell { | 12 | namespace Shader::Maxwell { |
| 11 | 13 | ||
| 14 | enum class ComparisonOp : u64 { | ||
| 15 | False, | ||
| 16 | LessThan, | ||
| 17 | Equal, | ||
| 18 | LessThanEqual, | ||
| 19 | GreaterThan, | ||
| 20 | NotEqual, | ||
| 21 | GreaterThanEqual, | ||
| 22 | True, | ||
| 23 | }; | ||
| 24 | |||
| 25 | enum class BooleanOp : u64 { | ||
| 26 | And, | ||
| 27 | Or, | ||
| 28 | Xor, | ||
| 29 | }; | ||
| 30 | |||
| 12 | class TranslatorVisitor { | 31 | class TranslatorVisitor { |
| 13 | public: | 32 | public: |
| 14 | explicit TranslatorVisitor(Environment& env_, IR::Block& block) : env{env_}, ir(block) {} | 33 | explicit TranslatorVisitor(Environment& env_, IR::Block& block) : env{env_}, ir(block) {} |
diff --git a/src/shader_recompiler/frontend/maxwell/translate/impl/integer_compare.cpp b/src/shader_recompiler/frontend/maxwell/translate/impl/integer_compare.cpp index 1f604b0ee..d844974d8 100644 --- a/src/shader_recompiler/frontend/maxwell/translate/impl/integer_compare.cpp +++ b/src/shader_recompiler/frontend/maxwell/translate/impl/integer_compare.cpp | |||
| @@ -4,46 +4,11 @@ | |||
| 4 | 4 | ||
| 5 | #include "common/bit_field.h" | 5 | #include "common/bit_field.h" |
| 6 | #include "common/common_types.h" | 6 | #include "common/common_types.h" |
| 7 | #include "shader_recompiler/frontend/maxwell/translate/impl/common_funcs.h" | ||
| 7 | #include "shader_recompiler/frontend/maxwell/translate/impl/impl.h" | 8 | #include "shader_recompiler/frontend/maxwell/translate/impl/impl.h" |
| 8 | 9 | ||
| 9 | namespace Shader::Maxwell { | 10 | namespace Shader::Maxwell { |
| 10 | namespace { | 11 | namespace { |
| 11 | enum class ComparisonOp : u64 { | ||
| 12 | False, | ||
| 13 | LessThan, | ||
| 14 | Equal, | ||
| 15 | LessThanEqual, | ||
| 16 | GreaterThan, | ||
| 17 | NotEqual, | ||
| 18 | GreaterThanEqual, | ||
| 19 | True, | ||
| 20 | }; | ||
| 21 | |||
| 22 | [[nodiscard]] IR::U1 CompareToZero(TranslatorVisitor& v, const IR::U32& operand, | ||
| 23 | ComparisonOp compare_op, bool is_signed) { | ||
| 24 | const IR::U32 zero{v.ir.Imm32(0)}; | ||
| 25 | switch (compare_op) { | ||
| 26 | case ComparisonOp::False: | ||
| 27 | return v.ir.Imm1(false); | ||
| 28 | case ComparisonOp::LessThan: | ||
| 29 | return v.ir.ILessThan(operand, zero, is_signed); | ||
| 30 | case ComparisonOp::Equal: | ||
| 31 | return v.ir.IEqual(operand, zero); | ||
| 32 | case ComparisonOp::LessThanEqual: | ||
| 33 | return v.ir.ILessThanEqual(operand, zero, is_signed); | ||
| 34 | case ComparisonOp::GreaterThan: | ||
| 35 | return v.ir.IGreaterThan(operand, zero, is_signed); | ||
| 36 | case ComparisonOp::NotEqual: | ||
| 37 | return v.ir.INotEqual(operand, zero); | ||
| 38 | case ComparisonOp::GreaterThanEqual: | ||
| 39 | return v.ir.IGreaterThanEqual(operand, zero, is_signed); | ||
| 40 | case ComparisonOp::True: | ||
| 41 | return v.ir.Imm1(true); | ||
| 42 | default: | ||
| 43 | throw NotImplementedException("ICMP.CMP"); | ||
| 44 | } | ||
| 45 | } | ||
| 46 | |||
| 47 | void ICMP(TranslatorVisitor& v, u64 insn, const IR::U32& src_a, const IR::U32& operand) { | 12 | void ICMP(TranslatorVisitor& v, u64 insn, const IR::U32& src_a, const IR::U32& operand) { |
| 48 | union { | 13 | union { |
| 49 | u64 insn; | 14 | u64 insn; |
| @@ -55,7 +20,7 @@ void ICMP(TranslatorVisitor& v, u64 insn, const IR::U32& src_a, const IR::U32& o | |||
| 55 | 20 | ||
| 56 | const IR::U32 zero{v.ir.Imm32(0)}; | 21 | const IR::U32 zero{v.ir.Imm32(0)}; |
| 57 | const bool is_signed{icmp.is_signed != 0}; | 22 | const bool is_signed{icmp.is_signed != 0}; |
| 58 | const IR::U1 cmp_result{CompareToZero(v, operand, icmp.compare_op, is_signed)}; | 23 | const IR::U1 cmp_result{IntegerCompare(v, operand, zero, icmp.compare_op, is_signed)}; |
| 59 | 24 | ||
| 60 | const IR::U32 src_reg{v.X(icmp.src_reg)}; | 25 | const IR::U32 src_reg{v.X(icmp.src_reg)}; |
| 61 | const IR::U32 result{v.ir.Select(cmp_result, src_reg, src_a)}; | 26 | const IR::U32 result{v.ir.Select(cmp_result, src_reg, src_a)}; |
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 new file mode 100644 index 000000000..b6a7b593d --- /dev/null +++ b/src/shader_recompiler/frontend/maxwell/translate/impl/integer_compare_and_set.cpp | |||
| @@ -0,0 +1,62 @@ | |||
| 1 | // Copyright 2021 yuzu Emulator Project | ||
| 2 | // Licensed under GPLv2 or any later version | ||
| 3 | // Refer to the license.txt file included. | ||
| 4 | |||
| 5 | #include "common/bit_field.h" | ||
| 6 | #include "common/common_types.h" | ||
| 7 | #include "shader_recompiler/frontend/maxwell/translate/impl/common_funcs.h" | ||
| 8 | #include "shader_recompiler/frontend/maxwell/translate/impl/impl.h" | ||
| 9 | |||
| 10 | namespace Shader::Maxwell { | ||
| 11 | namespace { | ||
| 12 | void ISET(TranslatorVisitor& v, u64 insn, const IR::U32& src_a) { | ||
| 13 | union { | ||
| 14 | u64 insn; | ||
| 15 | BitField<0, 8, IR::Reg> dest_reg; | ||
| 16 | BitField<8, 8, IR::Reg> src_reg; | ||
| 17 | BitField<39, 3, IR::Pred> pred; | ||
| 18 | BitField<42, 1, u64> neg_pred; | ||
| 19 | BitField<43, 1, u64> x; | ||
| 20 | BitField<44, 1, u64> bf; | ||
| 21 | BitField<45, 2, BooleanOp> bop; | ||
| 22 | BitField<48, 1, u64> is_signed; | ||
| 23 | BitField<49, 3, ComparisonOp> compare_op; | ||
| 24 | } const iset{insn}; | ||
| 25 | |||
| 26 | if (iset.x != 0) { | ||
| 27 | throw NotImplementedException("ISET.X"); | ||
| 28 | } | ||
| 29 | |||
| 30 | const IR::U32 src_reg{v.X(iset.src_reg)}; | ||
| 31 | const bool is_signed{iset.is_signed != 0}; | ||
| 32 | IR::U1 pred{v.ir.GetPred(iset.pred)}; | ||
| 33 | if (iset.neg_pred != 0) { | ||
| 34 | pred = v.ir.LogicalNot(pred); | ||
| 35 | } | ||
| 36 | const IR::U1 cmp_result{IntegerCompare(v, src_reg, src_a, iset.compare_op, is_signed)}; | ||
| 37 | const IR::U1 bop_result{PredicateCombine(v, cmp_result, pred, iset.bop)}; | ||
| 38 | |||
| 39 | const IR::U32 one_mask{v.ir.Imm32(-1)}; | ||
| 40 | const IR::U32 fp_one{v.ir.Imm32(0x3f800000)}; | ||
| 41 | const IR::U32 fail_result{v.ir.Imm32(0)}; | ||
| 42 | const IR::U32 pass_result{iset.bf == 0 ? one_mask : fp_one}; | ||
| 43 | |||
| 44 | const IR::U32 result{v.ir.Select(bop_result, pass_result, fail_result)}; | ||
| 45 | |||
| 46 | v.X(iset.dest_reg, result); | ||
| 47 | } | ||
| 48 | } // Anonymous namespace | ||
| 49 | |||
| 50 | void TranslatorVisitor::ISET_reg(u64 insn) { | ||
| 51 | ISET(*this, insn, GetReg20(insn)); | ||
| 52 | } | ||
| 53 | |||
| 54 | void TranslatorVisitor::ISET_cbuf(u64 insn) { | ||
| 55 | ISET(*this, insn, GetCbuf(insn)); | ||
| 56 | } | ||
| 57 | |||
| 58 | void TranslatorVisitor::ISET_imm(u64 insn) { | ||
| 59 | ISET(*this, insn, GetImm20(insn)); | ||
| 60 | } | ||
| 61 | |||
| 62 | } // namespace Shader::Maxwell | ||
diff --git a/src/shader_recompiler/frontend/maxwell/translate/impl/integer_minimum_maximum.cpp b/src/shader_recompiler/frontend/maxwell/translate/impl/integer_minimum_maximum.cpp index 5303db612..40f14ab8a 100644 --- a/src/shader_recompiler/frontend/maxwell/translate/impl/integer_minimum_maximum.cpp +++ b/src/shader_recompiler/frontend/maxwell/translate/impl/integer_minimum_maximum.cpp | |||
| @@ -23,7 +23,7 @@ void IMNMX(TranslatorVisitor& v, u64 insn, const IR::U32& op_b) { | |||
| 23 | throw NotImplementedException("IMNMX.MODE"); | 23 | throw NotImplementedException("IMNMX.MODE"); |
| 24 | } | 24 | } |
| 25 | 25 | ||
| 26 | IR::U1 pred{v.ir.GetPred(imnmx.pred)}; | 26 | const IR::U1 pred{v.ir.GetPred(imnmx.pred)}; |
| 27 | const IR::U32 op_a{v.X(imnmx.src_reg)}; | 27 | const IR::U32 op_a{v.X(imnmx.src_reg)}; |
| 28 | IR::U32 min; | 28 | IR::U32 min; |
| 29 | IR::U32 max; | 29 | IR::U32 max; |
diff --git a/src/shader_recompiler/frontend/maxwell/translate/impl/not_implemented.cpp b/src/shader_recompiler/frontend/maxwell/translate/impl/not_implemented.cpp index 8d4044ee8..f327e6fa5 100644 --- a/src/shader_recompiler/frontend/maxwell/translate/impl/not_implemented.cpp +++ b/src/shader_recompiler/frontend/maxwell/translate/impl/not_implemented.cpp | |||
| @@ -457,18 +457,6 @@ void TranslatorVisitor::ISBERD(u64) { | |||
| 457 | ThrowNotImplemented(Opcode::ISBERD); | 457 | ThrowNotImplemented(Opcode::ISBERD); |
| 458 | } | 458 | } |
| 459 | 459 | ||
| 460 | void TranslatorVisitor::ISET_reg(u64) { | ||
| 461 | ThrowNotImplemented(Opcode::ISET_reg); | ||
| 462 | } | ||
| 463 | |||
| 464 | void TranslatorVisitor::ISET_cbuf(u64) { | ||
| 465 | ThrowNotImplemented(Opcode::ISET_cbuf); | ||
| 466 | } | ||
| 467 | |||
| 468 | void TranslatorVisitor::ISET_imm(u64) { | ||
| 469 | ThrowNotImplemented(Opcode::ISET_imm); | ||
| 470 | } | ||
| 471 | |||
| 472 | void TranslatorVisitor::JCAL(u64) { | 460 | void TranslatorVisitor::JCAL(u64) { |
| 473 | ThrowNotImplemented(Opcode::JCAL); | 461 | ThrowNotImplemented(Opcode::JCAL); |
| 474 | } | 462 | } |