diff options
3 files changed, 84 insertions, 16 deletions
diff --git a/src/shader_recompiler/CMakeLists.txt b/src/shader_recompiler/CMakeLists.txt index e0568a058..a227ce21b 100644 --- a/src/shader_recompiler/CMakeLists.txt +++ b/src/shader_recompiler/CMakeLists.txt | |||
| @@ -71,6 +71,7 @@ add_library(shader_recompiler STATIC | |||
| 71 | frontend/maxwell/translate/impl/impl.cpp | 71 | frontend/maxwell/translate/impl/impl.cpp |
| 72 | frontend/maxwell/translate/impl/impl.h | 72 | frontend/maxwell/translate/impl/impl.h |
| 73 | frontend/maxwell/translate/impl/integer_add.cpp | 73 | frontend/maxwell/translate/impl/integer_add.cpp |
| 74 | frontend/maxwell/translate/impl/integer_compare.cpp | ||
| 74 | frontend/maxwell/translate/impl/integer_minimum_maximum.cpp | 75 | frontend/maxwell/translate/impl/integer_minimum_maximum.cpp |
| 75 | frontend/maxwell/translate/impl/integer_popcount.cpp | 76 | frontend/maxwell/translate/impl/integer_popcount.cpp |
| 76 | frontend/maxwell/translate/impl/integer_scaled_add.cpp | 77 | frontend/maxwell/translate/impl/integer_scaled_add.cpp |
diff --git a/src/shader_recompiler/frontend/maxwell/translate/impl/integer_compare.cpp b/src/shader_recompiler/frontend/maxwell/translate/impl/integer_compare.cpp new file mode 100644 index 000000000..1f604b0ee --- /dev/null +++ b/src/shader_recompiler/frontend/maxwell/translate/impl/integer_compare.cpp | |||
| @@ -0,0 +1,83 @@ | |||
| 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 | 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) { | ||
| 48 | union { | ||
| 49 | u64 insn; | ||
| 50 | BitField<0, 8, IR::Reg> dest_reg; | ||
| 51 | BitField<8, 8, IR::Reg> src_reg; | ||
| 52 | BitField<48, 1, u64> is_signed; | ||
| 53 | BitField<49, 3, ComparisonOp> compare_op; | ||
| 54 | } const icmp{insn}; | ||
| 55 | |||
| 56 | const IR::U32 zero{v.ir.Imm32(0)}; | ||
| 57 | const bool is_signed{icmp.is_signed != 0}; | ||
| 58 | const IR::U1 cmp_result{CompareToZero(v, operand, icmp.compare_op, is_signed)}; | ||
| 59 | |||
| 60 | const IR::U32 src_reg{v.X(icmp.src_reg)}; | ||
| 61 | const IR::U32 result{v.ir.Select(cmp_result, src_reg, src_a)}; | ||
| 62 | |||
| 63 | v.X(icmp.dest_reg, result); | ||
| 64 | } | ||
| 65 | } // Anonymous namespace | ||
| 66 | |||
| 67 | void TranslatorVisitor::ICMP_reg(u64 insn) { | ||
| 68 | ICMP(*this, insn, GetReg20(insn), GetReg39(insn)); | ||
| 69 | } | ||
| 70 | |||
| 71 | void TranslatorVisitor::ICMP_rc(u64 insn) { | ||
| 72 | ICMP(*this, insn, GetReg39(insn), GetCbuf(insn)); | ||
| 73 | } | ||
| 74 | |||
| 75 | void TranslatorVisitor::ICMP_cr(u64 insn) { | ||
| 76 | ICMP(*this, insn, GetCbuf(insn), GetReg39(insn)); | ||
| 77 | } | ||
| 78 | |||
| 79 | void TranslatorVisitor::ICMP_imm(u64 insn) { | ||
| 80 | ICMP(*this, insn, GetImm20(insn), GetReg39(insn)); | ||
| 81 | } | ||
| 82 | |||
| 83 | } // 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 615e3c3b5..8d4044ee8 100644 --- a/src/shader_recompiler/frontend/maxwell/translate/impl/not_implemented.cpp +++ b/src/shader_recompiler/frontend/maxwell/translate/impl/not_implemented.cpp | |||
| @@ -389,22 +389,6 @@ void TranslatorVisitor::IADD3_imm(u64) { | |||
| 389 | ThrowNotImplemented(Opcode::IADD3_imm); | 389 | ThrowNotImplemented(Opcode::IADD3_imm); |
| 390 | } | 390 | } |
| 391 | 391 | ||
| 392 | void TranslatorVisitor::ICMP_reg(u64) { | ||
| 393 | ThrowNotImplemented(Opcode::ICMP_reg); | ||
| 394 | } | ||
| 395 | |||
| 396 | void TranslatorVisitor::ICMP_rc(u64) { | ||
| 397 | ThrowNotImplemented(Opcode::ICMP_rc); | ||
| 398 | } | ||
| 399 | |||
| 400 | void TranslatorVisitor::ICMP_cr(u64) { | ||
| 401 | ThrowNotImplemented(Opcode::ICMP_cr); | ||
| 402 | } | ||
| 403 | |||
| 404 | void TranslatorVisitor::ICMP_imm(u64) { | ||
| 405 | ThrowNotImplemented(Opcode::ICMP_imm); | ||
| 406 | } | ||
| 407 | |||
| 408 | void TranslatorVisitor::IDE(u64) { | 392 | void TranslatorVisitor::IDE(u64) { |
| 409 | ThrowNotImplemented(Opcode::IDE); | 393 | ThrowNotImplemented(Opcode::IDE); |
| 410 | } | 394 | } |