diff options
Diffstat (limited to 'src/shader_recompiler/frontend')
5 files changed, 88 insertions, 13 deletions
diff --git a/src/shader_recompiler/frontend/ir/ir_emitter.cpp b/src/shader_recompiler/frontend/ir/ir_emitter.cpp index 5d475207e..556961fa4 100644 --- a/src/shader_recompiler/frontend/ir/ir_emitter.cpp +++ b/src/shader_recompiler/frontend/ir/ir_emitter.cpp | |||
| @@ -831,6 +831,34 @@ U1 IREmitter::FPUnordered(const F32& lhs, const F32& rhs) { | |||
| 831 | return LogicalOr(FPIsNan(lhs), FPIsNan(rhs)); | 831 | return LogicalOr(FPIsNan(lhs), FPIsNan(rhs)); |
| 832 | } | 832 | } |
| 833 | 833 | ||
| 834 | F32F64 IREmitter::FPMax(const F32F64& lhs, const F32F64& rhs, FpControl control) { | ||
| 835 | if (lhs.Type() != rhs.Type()) { | ||
| 836 | throw InvalidArgument("Mismatching types {} and {}", lhs.Type(), rhs.Type()); | ||
| 837 | } | ||
| 838 | switch (lhs.Type()) { | ||
| 839 | case Type::F32: | ||
| 840 | return Inst<F32>(Opcode::FPMax32, Flags{control}, lhs, rhs); | ||
| 841 | case Type::F64: | ||
| 842 | return Inst<F64>(Opcode::FPMax64, Flags{control}, lhs, rhs); | ||
| 843 | default: | ||
| 844 | ThrowInvalidType(lhs.Type()); | ||
| 845 | } | ||
| 846 | } | ||
| 847 | |||
| 848 | F32F64 IREmitter::FPMin(const F32F64& lhs, const F32F64& rhs, FpControl control) { | ||
| 849 | if (lhs.Type() != rhs.Type()) { | ||
| 850 | throw InvalidArgument("Mismatching types {} and {}", lhs.Type(), rhs.Type()); | ||
| 851 | } | ||
| 852 | switch (lhs.Type()) { | ||
| 853 | case Type::F32: | ||
| 854 | return Inst<F32>(Opcode::FPMin32, Flags{control}, lhs, rhs); | ||
| 855 | case Type::F64: | ||
| 856 | return Inst<F64>(Opcode::FPMin64, Flags{control}, lhs, rhs); | ||
| 857 | default: | ||
| 858 | ThrowInvalidType(lhs.Type()); | ||
| 859 | } | ||
| 860 | } | ||
| 861 | |||
| 834 | U32U64 IREmitter::IAdd(const U32U64& a, const U32U64& b) { | 862 | U32U64 IREmitter::IAdd(const U32U64& a, const U32U64& b) { |
| 835 | if (a.Type() != b.Type()) { | 863 | if (a.Type() != b.Type()) { |
| 836 | throw InvalidArgument("Mismatching types {} and {}", a.Type(), b.Type()); | 864 | throw InvalidArgument("Mismatching types {} and {}", a.Type(), b.Type()); |
diff --git a/src/shader_recompiler/frontend/ir/ir_emitter.h b/src/shader_recompiler/frontend/ir/ir_emitter.h index 5cfe1a54a..74fb3dbcb 100644 --- a/src/shader_recompiler/frontend/ir/ir_emitter.h +++ b/src/shader_recompiler/frontend/ir/ir_emitter.h | |||
| @@ -155,6 +155,8 @@ public: | |||
| 155 | [[nodiscard]] U1 FPIsNan(const F32& value); | 155 | [[nodiscard]] U1 FPIsNan(const F32& value); |
| 156 | [[nodiscard]] U1 FPOrdered(const F32& lhs, const F32& rhs); | 156 | [[nodiscard]] U1 FPOrdered(const F32& lhs, const F32& rhs); |
| 157 | [[nodiscard]] U1 FPUnordered(const F32& lhs, const F32& rhs); | 157 | [[nodiscard]] U1 FPUnordered(const F32& lhs, const F32& rhs); |
| 158 | [[nodiscard]] F32F64 FPMax(const F32F64& lhs, const F32F64& rhs, FpControl control = {}); | ||
| 159 | [[nodiscard]] F32F64 FPMin(const F32F64& lhs, const F32F64& rhs, FpControl control = {}); | ||
| 158 | 160 | ||
| 159 | [[nodiscard]] U32U64 IAdd(const U32U64& a, const U32U64& b); | 161 | [[nodiscard]] U32U64 IAdd(const U32U64& a, const U32U64& b); |
| 160 | [[nodiscard]] U32U64 ISub(const U32U64& a, const U32U64& b); | 162 | [[nodiscard]] U32U64 ISub(const U32U64& a, const U32U64& b); |
diff --git a/src/shader_recompiler/frontend/maxwell/translate/impl/floating_point_compare.cpp b/src/shader_recompiler/frontend/maxwell/translate/impl/floating_point_compare.cpp index 21cb80d67..f254ecb3a 100644 --- a/src/shader_recompiler/frontend/maxwell/translate/impl/floating_point_compare.cpp +++ b/src/shader_recompiler/frontend/maxwell/translate/impl/floating_point_compare.cpp | |||
| @@ -88,7 +88,7 @@ void FCMP(TranslatorVisitor& v, u64 insn, const IR::U32& src_a, const IR::F32& o | |||
| 88 | 88 | ||
| 89 | const IR::F32 zero{v.ir.Imm32(0.0f)}; | 89 | const IR::F32 zero{v.ir.Imm32(0.0f)}; |
| 90 | const IR::F32 neg_zero{v.ir.Imm32(-0.0f)}; | 90 | const IR::F32 neg_zero{v.ir.Imm32(-0.0f)}; |
| 91 | IR::FpControl control{.fmz_mode{fcmp.ftz != 0 ? IR::FmzMode::FTZ : IR::FmzMode::None}}; | 91 | const IR::FpControl control{.fmz_mode{fcmp.ftz != 0 ? IR::FmzMode::FTZ : IR::FmzMode::None}}; |
| 92 | const IR::U1 cmp_result{FloatingPointCompare(v.ir, operand, zero, fcmp.compare_op, control)}; | 92 | const IR::U1 cmp_result{FloatingPointCompare(v.ir, operand, zero, fcmp.compare_op, control)}; |
| 93 | const IR::U32 src_reg{v.X(fcmp.src_reg)}; | 93 | const IR::U32 src_reg{v.X(fcmp.src_reg)}; |
| 94 | const IR::U32 result{v.ir.Select(cmp_result, src_reg, src_a)}; | 94 | const IR::U32 result{v.ir.Select(cmp_result, src_reg, src_a)}; |
diff --git a/src/shader_recompiler/frontend/maxwell/translate/impl/floating_point_min_max.cpp b/src/shader_recompiler/frontend/maxwell/translate/impl/floating_point_min_max.cpp new file mode 100644 index 000000000..c3180a9bd --- /dev/null +++ b/src/shader_recompiler/frontend/maxwell/translate/impl/floating_point_min_max.cpp | |||
| @@ -0,0 +1,57 @@ | |||
| 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/impl.h" | ||
| 8 | |||
| 9 | namespace Shader::Maxwell { | ||
| 10 | namespace { | ||
| 11 | void FMNMX(TranslatorVisitor& v, u64 insn, const IR::F32& src_b) { | ||
| 12 | union { | ||
| 13 | u64 insn; | ||
| 14 | BitField<0, 8, IR::Reg> dest_reg; | ||
| 15 | BitField<8, 8, IR::Reg> src_a_reg; | ||
| 16 | BitField<39, 3, IR::Pred> pred; | ||
| 17 | BitField<42, 1, u64> neg_pred; | ||
| 18 | BitField<44, 1, u64> ftz; | ||
| 19 | BitField<45, 1, u64> negate_b; | ||
| 20 | BitField<46, 1, u64> abs_a; | ||
| 21 | BitField<48, 1, u64> negate_a; | ||
| 22 | BitField<49, 1, u64> abs_b; | ||
| 23 | } const fmnmx{insn}; | ||
| 24 | |||
| 25 | const IR::U1 pred{v.ir.GetPred(fmnmx.pred)}; | ||
| 26 | const IR::F32 op_a{v.ir.FPAbsNeg(v.F(fmnmx.src_a_reg), fmnmx.abs_a != 0, fmnmx.negate_a != 0)}; | ||
| 27 | const IR::F32 op_b = v.ir.FPAbsNeg(src_b, fmnmx.abs_b != 0, fmnmx.negate_b != 0); | ||
| 28 | |||
| 29 | const IR::FpControl control{ | ||
| 30 | .no_contraction{false}, | ||
| 31 | .rounding{IR::FpRounding::DontCare}, | ||
| 32 | .fmz_mode{fmnmx.ftz != 0 ? IR::FmzMode::FTZ : IR::FmzMode::None}, | ||
| 33 | }; | ||
| 34 | IR::F32 max{v.ir.FPMax(op_a, op_b, control)}; | ||
| 35 | IR::F32 min{v.ir.FPMin(op_a, op_b, control)}; | ||
| 36 | |||
| 37 | if (fmnmx.neg_pred != 0) { | ||
| 38 | std::swap(min, max); | ||
| 39 | } | ||
| 40 | |||
| 41 | v.F(fmnmx.dest_reg, IR::F32{v.ir.Select(pred, min, max)}); | ||
| 42 | } | ||
| 43 | } // Anonymous namespace | ||
| 44 | |||
| 45 | void TranslatorVisitor::FMNMX_reg(u64 insn) { | ||
| 46 | FMNMX(*this, insn, GetFloatReg20(insn)); | ||
| 47 | } | ||
| 48 | |||
| 49 | void TranslatorVisitor::FMNMX_cbuf(u64 insn) { | ||
| 50 | FMNMX(*this, insn, GetFloatCbuf(insn)); | ||
| 51 | } | ||
| 52 | |||
| 53 | void TranslatorVisitor::FMNMX_imm(u64 insn) { | ||
| 54 | FMNMX(*this, insn, GetFloatImm20(insn)); | ||
| 55 | } | ||
| 56 | |||
| 57 | } // namespace Shader::Maxwell | ||
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 e1904472f..01ecbb4cc 100644 --- a/src/shader_recompiler/frontend/maxwell/translate/impl/not_implemented.cpp +++ b/src/shader_recompiler/frontend/maxwell/translate/impl/not_implemented.cpp | |||
| @@ -201,18 +201,6 @@ void TranslatorVisitor::FCHK_imm(u64) { | |||
| 201 | ThrowNotImplemented(Opcode::FCHK_imm); | 201 | ThrowNotImplemented(Opcode::FCHK_imm); |
| 202 | } | 202 | } |
| 203 | 203 | ||
| 204 | void TranslatorVisitor::FMNMX_reg(u64) { | ||
| 205 | ThrowNotImplemented(Opcode::FMNMX_reg); | ||
| 206 | } | ||
| 207 | |||
| 208 | void TranslatorVisitor::FMNMX_cbuf(u64) { | ||
| 209 | ThrowNotImplemented(Opcode::FMNMX_cbuf); | ||
| 210 | } | ||
| 211 | |||
| 212 | void TranslatorVisitor::FMNMX_imm(u64) { | ||
| 213 | ThrowNotImplemented(Opcode::FMNMX_imm); | ||
| 214 | } | ||
| 215 | |||
| 216 | void TranslatorVisitor::FSET_reg(u64) { | 204 | void TranslatorVisitor::FSET_reg(u64) { |
| 217 | ThrowNotImplemented(Opcode::FSET_reg); | 205 | ThrowNotImplemented(Opcode::FSET_reg); |
| 218 | } | 206 | } |