diff options
8 files changed, 105 insertions, 12 deletions
| diff --git a/src/shader_recompiler/CMakeLists.txt b/src/shader_recompiler/CMakeLists.txt index 2e5de7f95..e0568a058 100644 --- a/src/shader_recompiler/CMakeLists.txt +++ b/src/shader_recompiler/CMakeLists.txt @@ -71,6 +71,7 @@ add_library(shader_recompiler STATIC      frontend/maxwell/translate/impl/impl.cpp      frontend/maxwell/translate/impl/impl.h      frontend/maxwell/translate/impl/integer_add.cpp +    frontend/maxwell/translate/impl/integer_minimum_maximum.cpp      frontend/maxwell/translate/impl/integer_popcount.cpp      frontend/maxwell/translate/impl/integer_scaled_add.cpp      frontend/maxwell/translate/impl/integer_set_predicate.cpp diff --git a/src/shader_recompiler/backend/spirv/emit_spirv.h b/src/shader_recompiler/backend/spirv/emit_spirv.h index 64c8e9ef6..4d00b235d 100644 --- a/src/shader_recompiler/backend/spirv/emit_spirv.h +++ b/src/shader_recompiler/backend/spirv/emit_spirv.h @@ -230,6 +230,10 @@ Id EmitBitFieldUExtract(EmitContext& ctx, Id base, Id offset, Id count);  Id EmitBitReverse32(EmitContext& ctx, Id value);  Id EmitBitCount32(EmitContext& ctx, Id value);  Id EmitBitwiseNot32(EmitContext& ctx, Id a); +Id EmitSMin32(EmitContext& ctx, Id a, Id b); +Id EmitUMin32(EmitContext& ctx, Id a, Id b); +Id EmitSMax32(EmitContext& ctx, Id a, Id b); +Id EmitUMax32(EmitContext& ctx, Id a, Id b);  Id EmitSLessThan(EmitContext& ctx, Id lhs, Id rhs);  Id EmitULessThan(EmitContext& ctx, Id lhs, Id rhs);  Id EmitIEqual(EmitContext& ctx, Id lhs, Id rhs); diff --git a/src/shader_recompiler/backend/spirv/emit_spirv_integer.cpp b/src/shader_recompiler/backend/spirv/emit_spirv_integer.cpp index e49ca7bde..5bdd943a4 100644 --- a/src/shader_recompiler/backend/spirv/emit_spirv_integer.cpp +++ b/src/shader_recompiler/backend/spirv/emit_spirv_integer.cpp @@ -114,6 +114,22 @@ Id EmitBitwiseNot32(EmitContext& ctx, Id a) {      return ctx.OpNot(ctx.U32[1], a);  } +Id EmitSMin32(EmitContext& ctx, Id a, Id b) { +    return ctx.OpSMin(ctx.U32[1], a, b); +} + +Id EmitUMin32(EmitContext& ctx, Id a, Id b) { +    return ctx.OpUMin(ctx.U32[1], a, b); +} + +Id EmitSMax32(EmitContext& ctx, Id a, Id b) { +    return ctx.OpSMax(ctx.U32[1], a, b); +} + +Id EmitUMax32(EmitContext& ctx, Id a, Id b) { +    return ctx.OpUMax(ctx.U32[1], a, b); +} +  Id EmitSLessThan(EmitContext& ctx, Id lhs, Id rhs) {      return ctx.OpSLessThan(ctx.U1, lhs, rhs);  } diff --git a/src/shader_recompiler/frontend/ir/ir_emitter.cpp b/src/shader_recompiler/frontend/ir/ir_emitter.cpp index 54fdf9559..04edcdfd8 100644 --- a/src/shader_recompiler/frontend/ir/ir_emitter.cpp +++ b/src/shader_recompiler/frontend/ir/ir_emitter.cpp @@ -816,6 +816,22 @@ U32 IREmitter::BitwiseNot(const U32& a) {      return Inst<U32>(Opcode::BitwiseNot32, a);  } +U32 IREmitter::SMin(const U32& a, const U32& b) { +    return Inst<U32>(Opcode::SMin32, a, b); +} + +U32 IREmitter::UMin(const U32& a, const U32& b) { +    return Inst<U32>(Opcode::UMin32, a, b); +} + +U32 IREmitter::SMax(const U32& a, const U32& b) { +    return Inst<U32>(Opcode::SMax32, a, b); +} + +U32 IREmitter::UMax(const U32& a, const U32& b) { +    return Inst<U32>(Opcode::UMax32, a, b); +} +  U1 IREmitter::ILessThan(const U32& lhs, const U32& rhs, bool is_signed) {      return Inst<U1>(is_signed ? Opcode::SLessThan : Opcode::ULessThan, lhs, rhs);  } diff --git a/src/shader_recompiler/frontend/ir/ir_emitter.h b/src/shader_recompiler/frontend/ir/ir_emitter.h index 9dec22145..00ba2e4cd 100644 --- a/src/shader_recompiler/frontend/ir/ir_emitter.h +++ b/src/shader_recompiler/frontend/ir/ir_emitter.h @@ -163,6 +163,11 @@ public:      [[nodiscard]] U32 BitCount(const U32& value);      [[nodiscard]] U32 BitwiseNot(const U32& a); +    [[nodiscard]] U32 SMin(const U32& a, const U32& b); +    [[nodiscard]] U32 UMin(const U32& a, const U32& b); +    [[nodiscard]] U32 SMax(const U32& a, const U32& b); +    [[nodiscard]] U32 UMax(const U32& a, const U32& b); +      [[nodiscard]] U1 ILessThan(const U32& lhs, const U32& rhs, bool is_signed);      [[nodiscard]] U1 IEqual(const U32& lhs, const U32& rhs);      [[nodiscard]] U1 ILessThanEqual(const U32& lhs, const U32& rhs, bool is_signed); diff --git a/src/shader_recompiler/frontend/ir/opcodes.inc b/src/shader_recompiler/frontend/ir/opcodes.inc index 59a13e911..2c4a997dc 100644 --- a/src/shader_recompiler/frontend/ir/opcodes.inc +++ b/src/shader_recompiler/frontend/ir/opcodes.inc @@ -235,6 +235,10 @@ OPCODE(BitReverse32,                                        U32,            U32,  OPCODE(BitCount32,                                          U32,            U32,                                                            )  OPCODE(BitwiseNot32,                                        U32,            U32,                                                            ) +OPCODE(SMin32,                                              U32,            U32,            U32,                                            ) +OPCODE(UMin32,                                              U32,            U32,            U32,                                            ) +OPCODE(SMax32,                                              U32,            U32,            U32,                                            ) +OPCODE(UMax32,                                              U32,            U32,            U32,                                            )  OPCODE(SLessThan,                                           U1,             U32,            U32,                                            )  OPCODE(ULessThan,                                           U1,             U32,            U32,                                            )  OPCODE(IEqual,                                              U1,             U32,            U32,                                            ) 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 new file mode 100644 index 000000000..12c6aae3d --- /dev/null +++ b/src/shader_recompiler/frontend/maxwell/translate/impl/integer_minimum_maximum.cpp @@ -0,0 +1,59 @@ +// 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/impl.h" + +namespace Shader::Maxwell { +namespace { +void IMNMX(TranslatorVisitor& v, u64 insn, const IR::U32& op_b) { +    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, 2, u64> mode; +        BitField<48, 1, u64> is_signed; +    } const imnmx{insn}; + +    if (imnmx.mode != 0) { +        throw NotImplementedException("IMNMX.MODE"); +    } + +    IR::U1 pred = v.ir.GetPred(imnmx.pred); +    const IR::U32 op_a{v.X(imnmx.src_reg)}; +    IR::U32 min; +    IR::U32 max; + +    if (imnmx.is_signed != 0) { +        min = IR::U32{v.ir.SMin(op_a, op_b)}; +        max = IR::U32{v.ir.SMax(op_a, op_b)}; +    } else { +        min = IR::U32{v.ir.UMin(op_a, op_b)}; +        max = IR::U32{v.ir.UMax(op_a, op_b)}; +    } +    if (imnmx.neg_pred != 0) { +        std::swap(min, max); +    } + +    const IR::U32 result{v.ir.Select(pred, min, max)}; +    v.X(imnmx.dest_reg, result); +} +} // Anonymous namespace + +void TranslatorVisitor::IMNMX_reg(u64 insn) { +    IMNMX(*this, insn, GetReg20(insn)); +} + +void TranslatorVisitor::IMNMX_cbuf(u64 insn) { +    IMNMX(*this, insn, GetCbuf(insn)); +} + +void TranslatorVisitor::IMNMX_imm(u64 insn) { +    IMNMX(*this, insn, GetImm20(insn)); +} + +} // 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 ed2cfac60..615e3c3b5 100644 --- a/src/shader_recompiler/frontend/maxwell/translate/impl/not_implemented.cpp +++ b/src/shader_recompiler/frontend/maxwell/translate/impl/not_implemented.cpp @@ -453,18 +453,6 @@ void TranslatorVisitor::IMADSP_imm(u64) {      ThrowNotImplemented(Opcode::IMADSP_imm);  } -void TranslatorVisitor::IMNMX_reg(u64) { -    ThrowNotImplemented(Opcode::IMNMX_reg); -} - -void TranslatorVisitor::IMNMX_cbuf(u64) { -    ThrowNotImplemented(Opcode::IMNMX_cbuf); -} - -void TranslatorVisitor::IMNMX_imm(u64) { -    ThrowNotImplemented(Opcode::IMNMX_imm); -} -  void TranslatorVisitor::IMUL_reg(u64) {      ThrowNotImplemented(Opcode::IMUL_reg);  } | 
