shader: Implement ISET, add common_funcs
This commit is contained in:
		| @@ -62,6 +62,8 @@ add_library(shader_recompiler STATIC | ||||
|     frontend/maxwell/translate/impl/bitfield_extract.cpp | ||||
|     frontend/maxwell/translate/impl/bitfield_insert.cpp | ||||
|     frontend/maxwell/translate/impl/common_encoding.h | ||||
|     frontend/maxwell/translate/impl/common_funcs.cpp | ||||
|     frontend/maxwell/translate/impl/common_funcs.h | ||||
|     frontend/maxwell/translate/impl/floating_point_add.cpp | ||||
|     frontend/maxwell/translate/impl/floating_point_conversion_integer.cpp | ||||
|     frontend/maxwell/translate/impl/floating_point_fused_multiply_add.cpp | ||||
| @@ -72,6 +74,7 @@ add_library(shader_recompiler STATIC | ||||
|     frontend/maxwell/translate/impl/impl.h | ||||
|     frontend/maxwell/translate/impl/integer_add.cpp | ||||
|     frontend/maxwell/translate/impl/integer_compare.cpp | ||||
|     frontend/maxwell/translate/impl/integer_compare_and_set.cpp | ||||
|     frontend/maxwell/translate/impl/integer_minimum_maximum.cpp | ||||
|     frontend/maxwell/translate/impl/integer_popcount.cpp | ||||
|     frontend/maxwell/translate/impl/integer_scaled_add.cpp | ||||
|   | ||||
| @@ -0,0 +1,46 @@ | ||||
| // Copyright 2021 yuzu Emulator Project | ||||
| // Licensed under GPLv2 or any later version | ||||
| // Refer to the license.txt file included. | ||||
|  | ||||
| #include "shader_recompiler/frontend/maxwell/translate/impl/common_funcs.h" | ||||
|  | ||||
| namespace Shader::Maxwell { | ||||
| [[nodiscard]] IR::U1 IntegerCompare(TranslatorVisitor& v, const IR::U32& operand_1, | ||||
|                                     const IR::U32& operand_2, ComparisonOp compare_op, | ||||
|                                     bool is_signed) { | ||||
|     switch (compare_op) { | ||||
|     case ComparisonOp::False: | ||||
|         return v.ir.Imm1(false); | ||||
|     case ComparisonOp::LessThan: | ||||
|         return v.ir.ILessThan(operand_1, operand_2, is_signed); | ||||
|     case ComparisonOp::Equal: | ||||
|         return v.ir.IEqual(operand_1, operand_2); | ||||
|     case ComparisonOp::LessThanEqual: | ||||
|         return v.ir.ILessThanEqual(operand_1, operand_2, is_signed); | ||||
|     case ComparisonOp::GreaterThan: | ||||
|         return v.ir.IGreaterThan(operand_1, operand_2, is_signed); | ||||
|     case ComparisonOp::NotEqual: | ||||
|         return v.ir.INotEqual(operand_1, operand_2); | ||||
|     case ComparisonOp::GreaterThanEqual: | ||||
|         return v.ir.IGreaterThanEqual(operand_1, operand_2, is_signed); | ||||
|     case ComparisonOp::True: | ||||
|         return v.ir.Imm1(true); | ||||
|     default: | ||||
|         throw NotImplementedException("CMP"); | ||||
|     } | ||||
| } | ||||
|  | ||||
| [[nodiscard]] IR::U1 PredicateCombine(TranslatorVisitor& v, const IR::U1& predicate_1, | ||||
|                                       const IR::U1& predicate_2, BooleanOp bop) { | ||||
|     switch (bop) { | ||||
|     case BooleanOp::And: | ||||
|         return v.ir.LogicalAnd(predicate_1, predicate_2); | ||||
|     case BooleanOp::Or: | ||||
|         return v.ir.LogicalOr(predicate_1, predicate_2); | ||||
|     case BooleanOp::Xor: | ||||
|         return v.ir.LogicalXor(predicate_1, predicate_2); | ||||
|     default: | ||||
|         throw NotImplementedException("BOP"); | ||||
|     } | ||||
| } | ||||
| } // namespace Shader::Maxwell | ||||
| @@ -0,0 +1,17 @@ | ||||
| // Copyright 2021 yuzu Emulator Project | ||||
| // Licensed under GPLv2 or any later version | ||||
| // Refer to the license.txt file included. | ||||
|  | ||||
| #pragma once | ||||
|  | ||||
| #include "common/common_types.h" | ||||
| #include "shader_recompiler/frontend/maxwell/translate/impl/impl.h" | ||||
|  | ||||
| namespace Shader::Maxwell { | ||||
| [[nodiscard]] IR::U1 IntegerCompare(TranslatorVisitor& v, const IR::U32& operand_1, | ||||
|                                     const IR::U32& operand_2, ComparisonOp compare_op, | ||||
|                                     bool is_signed); | ||||
|  | ||||
| [[nodiscard]] IR::U1 PredicateCombine(TranslatorVisitor& v, const IR::U1& predicate_1, | ||||
|                                       const IR::U1& predicate_2, BooleanOp bop); | ||||
| } // namespace Shader::Maxwell | ||||
| @@ -2,6 +2,8 @@ | ||||
| // Licensed under GPLv2 or any later version | ||||
| // Refer to the license.txt file included. | ||||
|  | ||||
| #pragma once | ||||
|  | ||||
| #include "shader_recompiler/environment.h" | ||||
| #include "shader_recompiler/frontend/ir/basic_block.h" | ||||
| #include "shader_recompiler/frontend/ir/ir_emitter.h" | ||||
| @@ -9,6 +11,23 @@ | ||||
|  | ||||
| namespace Shader::Maxwell { | ||||
|  | ||||
| enum class ComparisonOp : u64 { | ||||
|     False, | ||||
|     LessThan, | ||||
|     Equal, | ||||
|     LessThanEqual, | ||||
|     GreaterThan, | ||||
|     NotEqual, | ||||
|     GreaterThanEqual, | ||||
|     True, | ||||
| }; | ||||
|  | ||||
| enum class BooleanOp : u64 { | ||||
|     And, | ||||
|     Or, | ||||
|     Xor, | ||||
| }; | ||||
|  | ||||
| class TranslatorVisitor { | ||||
| public: | ||||
|     explicit TranslatorVisitor(Environment& env_, IR::Block& block) : env{env_}, ir(block) {} | ||||
|   | ||||
| @@ -4,46 +4,11 @@ | ||||
|  | ||||
| #include "common/bit_field.h" | ||||
| #include "common/common_types.h" | ||||
| #include "shader_recompiler/frontend/maxwell/translate/impl/common_funcs.h" | ||||
| #include "shader_recompiler/frontend/maxwell/translate/impl/impl.h" | ||||
|  | ||||
| namespace Shader::Maxwell { | ||||
| namespace { | ||||
| enum class ComparisonOp : u64 { | ||||
|     False, | ||||
|     LessThan, | ||||
|     Equal, | ||||
|     LessThanEqual, | ||||
|     GreaterThan, | ||||
|     NotEqual, | ||||
|     GreaterThanEqual, | ||||
|     True, | ||||
| }; | ||||
|  | ||||
| [[nodiscard]] IR::U1 CompareToZero(TranslatorVisitor& v, const IR::U32& operand, | ||||
|                                    ComparisonOp compare_op, bool is_signed) { | ||||
|     const IR::U32 zero{v.ir.Imm32(0)}; | ||||
|     switch (compare_op) { | ||||
|     case ComparisonOp::False: | ||||
|         return v.ir.Imm1(false); | ||||
|     case ComparisonOp::LessThan: | ||||
|         return v.ir.ILessThan(operand, zero, is_signed); | ||||
|     case ComparisonOp::Equal: | ||||
|         return v.ir.IEqual(operand, zero); | ||||
|     case ComparisonOp::LessThanEqual: | ||||
|         return v.ir.ILessThanEqual(operand, zero, is_signed); | ||||
|     case ComparisonOp::GreaterThan: | ||||
|         return v.ir.IGreaterThan(operand, zero, is_signed); | ||||
|     case ComparisonOp::NotEqual: | ||||
|         return v.ir.INotEqual(operand, zero); | ||||
|     case ComparisonOp::GreaterThanEqual: | ||||
|         return v.ir.IGreaterThanEqual(operand, zero, is_signed); | ||||
|     case ComparisonOp::True: | ||||
|         return v.ir.Imm1(true); | ||||
|     default: | ||||
|         throw NotImplementedException("ICMP.CMP"); | ||||
|     } | ||||
| } | ||||
|  | ||||
| void ICMP(TranslatorVisitor& v, u64 insn, const IR::U32& src_a, const IR::U32& operand) { | ||||
|     union { | ||||
|         u64 insn; | ||||
| @@ -55,7 +20,7 @@ void ICMP(TranslatorVisitor& v, u64 insn, const IR::U32& src_a, const IR::U32& o | ||||
|  | ||||
|     const IR::U32 zero{v.ir.Imm32(0)}; | ||||
|     const bool is_signed{icmp.is_signed != 0}; | ||||
|     const IR::U1 cmp_result{CompareToZero(v, operand, icmp.compare_op, is_signed)}; | ||||
|     const IR::U1 cmp_result{IntegerCompare(v, operand, zero, icmp.compare_op, is_signed)}; | ||||
|  | ||||
|     const IR::U32 src_reg{v.X(icmp.src_reg)}; | ||||
|     const IR::U32 result{v.ir.Select(cmp_result, src_reg, src_a)}; | ||||
|   | ||||
| @@ -0,0 +1,62 @@ | ||||
| // Copyright 2021 yuzu Emulator Project | ||||
| // Licensed under GPLv2 or any later version | ||||
| // Refer to the license.txt file included. | ||||
|  | ||||
| #include "common/bit_field.h" | ||||
| #include "common/common_types.h" | ||||
| #include "shader_recompiler/frontend/maxwell/translate/impl/common_funcs.h" | ||||
| #include "shader_recompiler/frontend/maxwell/translate/impl/impl.h" | ||||
|  | ||||
| namespace Shader::Maxwell { | ||||
| namespace { | ||||
| void ISET(TranslatorVisitor& v, u64 insn, const IR::U32& src_a) { | ||||
|     union { | ||||
|         u64 insn; | ||||
|         BitField<0, 8, IR::Reg> dest_reg; | ||||
|         BitField<8, 8, IR::Reg> src_reg; | ||||
|         BitField<39, 3, IR::Pred> pred; | ||||
|         BitField<42, 1, u64> neg_pred; | ||||
|         BitField<43, 1, u64> x; | ||||
|         BitField<44, 1, u64> bf; | ||||
|         BitField<45, 2, BooleanOp> bop; | ||||
|         BitField<48, 1, u64> is_signed; | ||||
|         BitField<49, 3, ComparisonOp> compare_op; | ||||
|     } const iset{insn}; | ||||
|  | ||||
|     if (iset.x != 0) { | ||||
|         throw NotImplementedException("ISET.X"); | ||||
|     } | ||||
|  | ||||
|     const IR::U32 src_reg{v.X(iset.src_reg)}; | ||||
|     const bool is_signed{iset.is_signed != 0}; | ||||
|     IR::U1 pred{v.ir.GetPred(iset.pred)}; | ||||
|     if (iset.neg_pred != 0) { | ||||
|         pred = v.ir.LogicalNot(pred); | ||||
|     } | ||||
|     const IR::U1 cmp_result{IntegerCompare(v, src_reg, src_a, iset.compare_op, is_signed)}; | ||||
|     const IR::U1 bop_result{PredicateCombine(v, cmp_result, pred, iset.bop)}; | ||||
|  | ||||
|     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 pass_result{iset.bf == 0 ? one_mask : fp_one}; | ||||
|  | ||||
|     const IR::U32 result{v.ir.Select(bop_result, pass_result, fail_result)}; | ||||
|  | ||||
|     v.X(iset.dest_reg, result); | ||||
| } | ||||
| } // Anonymous namespace | ||||
|  | ||||
| void TranslatorVisitor::ISET_reg(u64 insn) { | ||||
|     ISET(*this, insn, GetReg20(insn)); | ||||
| } | ||||
|  | ||||
| void TranslatorVisitor::ISET_cbuf(u64 insn) { | ||||
|     ISET(*this, insn, GetCbuf(insn)); | ||||
| } | ||||
|  | ||||
| void TranslatorVisitor::ISET_imm(u64 insn) { | ||||
|     ISET(*this, insn, GetImm20(insn)); | ||||
| } | ||||
|  | ||||
| } // namespace Shader::Maxwell | ||||
| @@ -23,7 +23,7 @@ void IMNMX(TranslatorVisitor& v, u64 insn, const IR::U32& op_b) { | ||||
|         throw NotImplementedException("IMNMX.MODE"); | ||||
|     } | ||||
|  | ||||
|     IR::U1 pred{v.ir.GetPred(imnmx.pred)}; | ||||
|     const IR::U1 pred{v.ir.GetPred(imnmx.pred)}; | ||||
|     const IR::U32 op_a{v.X(imnmx.src_reg)}; | ||||
|     IR::U32 min; | ||||
|     IR::U32 max; | ||||
|   | ||||
| @@ -457,18 +457,6 @@ void TranslatorVisitor::ISBERD(u64) { | ||||
|     ThrowNotImplemented(Opcode::ISBERD); | ||||
| } | ||||
|  | ||||
| void TranslatorVisitor::ISET_reg(u64) { | ||||
|     ThrowNotImplemented(Opcode::ISET_reg); | ||||
| } | ||||
|  | ||||
| void TranslatorVisitor::ISET_cbuf(u64) { | ||||
|     ThrowNotImplemented(Opcode::ISET_cbuf); | ||||
| } | ||||
|  | ||||
| void TranslatorVisitor::ISET_imm(u64) { | ||||
|     ThrowNotImplemented(Opcode::ISET_imm); | ||||
| } | ||||
|  | ||||
| void TranslatorVisitor::JCAL(u64) { | ||||
|     ThrowNotImplemented(Opcode::JCAL); | ||||
| } | ||||
|   | ||||
		Reference in New Issue
	
	Block a user