diff options
8 files changed, 150 insertions, 50 deletions
| diff --git a/src/shader_recompiler/CMakeLists.txt b/src/shader_recompiler/CMakeLists.txt index a227ce21b..89fc24f62 100644 --- a/src/shader_recompiler/CMakeLists.txt +++ b/src/shader_recompiler/CMakeLists.txt @@ -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 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 @@ +// 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 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 @@ +// 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 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 @@  // 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) {} 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 @@  #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)}; 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 @@ +// 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 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) {          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; 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) {      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);  } | 
