diff options
Diffstat (limited to 'src/shader_recompiler')
8 files changed, 119 insertions, 31 deletions
diff --git a/src/shader_recompiler/CMakeLists.txt b/src/shader_recompiler/CMakeLists.txt index a8df03f90..ddd34e915 100644 --- a/src/shader_recompiler/CMakeLists.txt +++ b/src/shader_recompiler/CMakeLists.txt | |||
| @@ -78,6 +78,7 @@ add_library(shader_recompiler STATIC | |||
| 78 | frontend/maxwell/translate/impl/integer_add_three_input.cpp | 78 | frontend/maxwell/translate/impl/integer_add_three_input.cpp |
| 79 | frontend/maxwell/translate/impl/integer_compare.cpp | 79 | frontend/maxwell/translate/impl/integer_compare.cpp |
| 80 | frontend/maxwell/translate/impl/integer_compare_and_set.cpp | 80 | frontend/maxwell/translate/impl/integer_compare_and_set.cpp |
| 81 | frontend/maxwell/translate/impl/integer_funnel_shift.cpp | ||
| 81 | frontend/maxwell/translate/impl/integer_minimum_maximum.cpp | 82 | frontend/maxwell/translate/impl/integer_minimum_maximum.cpp |
| 82 | frontend/maxwell/translate/impl/integer_popcount.cpp | 83 | frontend/maxwell/translate/impl/integer_popcount.cpp |
| 83 | frontend/maxwell/translate/impl/integer_scaled_add.cpp | 84 | frontend/maxwell/translate/impl/integer_scaled_add.cpp |
diff --git a/src/shader_recompiler/backend/spirv/emit_spirv.h b/src/shader_recompiler/backend/spirv/emit_spirv.h index 1f7d84871..bf1b5ace6 100644 --- a/src/shader_recompiler/backend/spirv/emit_spirv.h +++ b/src/shader_recompiler/backend/spirv/emit_spirv.h | |||
| @@ -232,9 +232,11 @@ Id EmitINeg32(EmitContext& ctx, Id value); | |||
| 232 | Id EmitINeg64(EmitContext& ctx, Id value); | 232 | Id EmitINeg64(EmitContext& ctx, Id value); |
| 233 | Id EmitIAbs32(EmitContext& ctx, Id value); | 233 | Id EmitIAbs32(EmitContext& ctx, Id value); |
| 234 | Id EmitShiftLeftLogical32(EmitContext& ctx, Id base, Id shift); | 234 | Id EmitShiftLeftLogical32(EmitContext& ctx, Id base, Id shift); |
| 235 | Id EmitShiftRightLogical32(EmitContext& ctx, Id a, Id b); | 235 | Id EmitShiftLeftLogical64(EmitContext& ctx, Id base, Id shift); |
| 236 | Id EmitShiftRightLogical64(EmitContext& ctx, Id a, Id b); | 236 | Id EmitShiftRightLogical32(EmitContext& ctx, Id base, Id shift); |
| 237 | Id EmitShiftRightArithmetic32(EmitContext& ctx, Id a, Id b); | 237 | Id EmitShiftRightLogical64(EmitContext& ctx, Id base, Id shift); |
| 238 | Id EmitShiftRightArithmetic32(EmitContext& ctx, Id base, Id shift); | ||
| 239 | Id EmitShiftRightArithmetic64(EmitContext& ctx, Id base, Id shift); | ||
| 238 | Id EmitBitwiseAnd32(EmitContext& ctx, Id a, Id b); | 240 | Id EmitBitwiseAnd32(EmitContext& ctx, Id a, Id b); |
| 239 | Id EmitBitwiseOr32(EmitContext& ctx, Id a, Id b); | 241 | Id EmitBitwiseOr32(EmitContext& ctx, Id a, Id b); |
| 240 | Id EmitBitwiseXor32(EmitContext& ctx, Id a, Id b); | 242 | Id EmitBitwiseXor32(EmitContext& ctx, Id a, Id b); |
diff --git a/src/shader_recompiler/backend/spirv/emit_spirv_integer.cpp b/src/shader_recompiler/backend/spirv/emit_spirv_integer.cpp index f5001cdaa..5ab3b5e86 100644 --- a/src/shader_recompiler/backend/spirv/emit_spirv_integer.cpp +++ b/src/shader_recompiler/backend/spirv/emit_spirv_integer.cpp | |||
| @@ -74,16 +74,24 @@ Id EmitShiftLeftLogical32(EmitContext& ctx, Id base, Id shift) { | |||
| 74 | return ctx.OpShiftLeftLogical(ctx.U32[1], base, shift); | 74 | return ctx.OpShiftLeftLogical(ctx.U32[1], base, shift); |
| 75 | } | 75 | } |
| 76 | 76 | ||
| 77 | Id EmitShiftRightLogical32(EmitContext& ctx, Id a, Id b) { | 77 | Id EmitShiftLeftLogical64(EmitContext& ctx, Id base, Id shift) { |
| 78 | return ctx.OpShiftRightLogical(ctx.U32[1], a, b); | 78 | return ctx.OpShiftLeftLogical(ctx.U64, base, shift); |
| 79 | } | 79 | } |
| 80 | 80 | ||
| 81 | Id EmitShiftRightLogical64(EmitContext& ctx, Id a, Id b) { | 81 | Id EmitShiftRightLogical32(EmitContext& ctx, Id base, Id shift) { |
| 82 | return ctx.OpShiftRightLogical(ctx.U64, a, b); | 82 | return ctx.OpShiftRightLogical(ctx.U32[1], base, shift); |
| 83 | } | 83 | } |
| 84 | 84 | ||
| 85 | Id EmitShiftRightArithmetic32(EmitContext& ctx, Id a, Id b) { | 85 | Id EmitShiftRightLogical64(EmitContext& ctx, Id base, Id shift) { |
| 86 | return ctx.OpShiftRightArithmetic(ctx.U32[1], a, b); | 86 | return ctx.OpShiftRightLogical(ctx.U64, base, shift); |
| 87 | } | ||
| 88 | |||
| 89 | Id EmitShiftRightArithmetic32(EmitContext& ctx, Id base, Id shift) { | ||
| 90 | return ctx.OpShiftRightArithmetic(ctx.U32[1], base, shift); | ||
| 91 | } | ||
| 92 | |||
| 93 | Id EmitShiftRightArithmetic64(EmitContext& ctx, Id base, Id shift) { | ||
| 94 | return ctx.OpShiftRightArithmetic(ctx.U64, base, shift); | ||
| 87 | } | 95 | } |
| 88 | 96 | ||
| 89 | Id EmitBitwiseAnd32(EmitContext& ctx, Id a, Id b) { | 97 | Id EmitBitwiseAnd32(EmitContext& ctx, Id a, Id b) { |
diff --git a/src/shader_recompiler/frontend/ir/ir_emitter.cpp b/src/shader_recompiler/frontend/ir/ir_emitter.cpp index 01f52183c..1659b7f3b 100644 --- a/src/shader_recompiler/frontend/ir/ir_emitter.cpp +++ b/src/shader_recompiler/frontend/ir/ir_emitter.cpp | |||
| @@ -813,8 +813,15 @@ U32 IREmitter::IAbs(const U32& value) { | |||
| 813 | return Inst<U32>(Opcode::IAbs32, value); | 813 | return Inst<U32>(Opcode::IAbs32, value); |
| 814 | } | 814 | } |
| 815 | 815 | ||
| 816 | U32 IREmitter::ShiftLeftLogical(const U32& base, const U32& shift) { | 816 | U32U64 IREmitter::ShiftLeftLogical(const U32U64& base, const U32& shift) { |
| 817 | return Inst<U32>(Opcode::ShiftLeftLogical32, base, shift); | 817 | switch (base.Type()) { |
| 818 | case Type::U32: | ||
| 819 | return Inst<U32>(Opcode::ShiftLeftLogical32, base, shift); | ||
| 820 | case Type::U64: | ||
| 821 | return Inst<U64>(Opcode::ShiftLeftLogical64, base, shift); | ||
| 822 | default: | ||
| 823 | ThrowInvalidType(base.Type()); | ||
| 824 | } | ||
| 818 | } | 825 | } |
| 819 | 826 | ||
| 820 | U32U64 IREmitter::ShiftRightLogical(const U32U64& base, const U32& shift) { | 827 | U32U64 IREmitter::ShiftRightLogical(const U32U64& base, const U32& shift) { |
| @@ -828,8 +835,15 @@ U32U64 IREmitter::ShiftRightLogical(const U32U64& base, const U32& shift) { | |||
| 828 | } | 835 | } |
| 829 | } | 836 | } |
| 830 | 837 | ||
| 831 | U32 IREmitter::ShiftRightArithmetic(const U32& base, const U32& shift) { | 838 | U32U64 IREmitter::ShiftRightArithmetic(const U32U64& base, const U32& shift) { |
| 832 | return Inst<U32>(Opcode::ShiftRightArithmetic32, base, shift); | 839 | switch (base.Type()) { |
| 840 | case Type::U32: | ||
| 841 | return Inst<U32>(Opcode::ShiftRightArithmetic32, base, shift); | ||
| 842 | case Type::U64: | ||
| 843 | return Inst<U64>(Opcode::ShiftRightArithmetic64, base, shift); | ||
| 844 | default: | ||
| 845 | ThrowInvalidType(base.Type()); | ||
| 846 | } | ||
| 833 | } | 847 | } |
| 834 | 848 | ||
| 835 | U32 IREmitter::BitwiseAnd(const U32& a, const U32& b) { | 849 | U32 IREmitter::BitwiseAnd(const U32& a, const U32& b) { |
diff --git a/src/shader_recompiler/frontend/ir/ir_emitter.h b/src/shader_recompiler/frontend/ir/ir_emitter.h index 33bf2a7d0..6e29bf0e2 100644 --- a/src/shader_recompiler/frontend/ir/ir_emitter.h +++ b/src/shader_recompiler/frontend/ir/ir_emitter.h | |||
| @@ -150,9 +150,9 @@ public: | |||
| 150 | [[nodiscard]] U32 IMul(const U32& a, const U32& b); | 150 | [[nodiscard]] U32 IMul(const U32& a, const U32& b); |
| 151 | [[nodiscard]] U32U64 INeg(const U32U64& value); | 151 | [[nodiscard]] U32U64 INeg(const U32U64& value); |
| 152 | [[nodiscard]] U32 IAbs(const U32& value); | 152 | [[nodiscard]] U32 IAbs(const U32& value); |
| 153 | [[nodiscard]] U32 ShiftLeftLogical(const U32& base, const U32& shift); | 153 | [[nodiscard]] U32U64 ShiftLeftLogical(const U32U64& base, const U32& shift); |
| 154 | [[nodiscard]] U32U64 ShiftRightLogical(const U32U64& base, const U32& shift); | 154 | [[nodiscard]] U32U64 ShiftRightLogical(const U32U64& base, const U32& shift); |
| 155 | [[nodiscard]] U32 ShiftRightArithmetic(const U32& base, const U32& shift); | 155 | [[nodiscard]] U32U64 ShiftRightArithmetic(const U32U64& base, const U32& shift); |
| 156 | [[nodiscard]] U32 BitwiseAnd(const U32& a, const U32& b); | 156 | [[nodiscard]] U32 BitwiseAnd(const U32& a, const U32& b); |
| 157 | [[nodiscard]] U32 BitwiseOr(const U32& a, const U32& b); | 157 | [[nodiscard]] U32 BitwiseOr(const U32& a, const U32& b); |
| 158 | [[nodiscard]] U32 BitwiseXor(const U32& a, const U32& b); | 158 | [[nodiscard]] U32 BitwiseXor(const U32& a, const U32& b); |
diff --git a/src/shader_recompiler/frontend/ir/opcodes.inc b/src/shader_recompiler/frontend/ir/opcodes.inc index b51aaaef5..75f09ebfc 100644 --- a/src/shader_recompiler/frontend/ir/opcodes.inc +++ b/src/shader_recompiler/frontend/ir/opcodes.inc | |||
| @@ -236,9 +236,11 @@ OPCODE(INeg32, U32, U32, | |||
| 236 | OPCODE(INeg64, U64, U64, ) | 236 | OPCODE(INeg64, U64, U64, ) |
| 237 | OPCODE(IAbs32, U32, U32, ) | 237 | OPCODE(IAbs32, U32, U32, ) |
| 238 | OPCODE(ShiftLeftLogical32, U32, U32, U32, ) | 238 | OPCODE(ShiftLeftLogical32, U32, U32, U32, ) |
| 239 | OPCODE(ShiftLeftLogical64, U64, U64, U32, ) | ||
| 239 | OPCODE(ShiftRightLogical32, U32, U32, U32, ) | 240 | OPCODE(ShiftRightLogical32, U32, U32, U32, ) |
| 240 | OPCODE(ShiftRightLogical64, U64, U64, U32, ) | 241 | OPCODE(ShiftRightLogical64, U64, U64, U32, ) |
| 241 | OPCODE(ShiftRightArithmetic32, U32, U32, U32, ) | 242 | OPCODE(ShiftRightArithmetic32, U32, U32, U32, ) |
| 243 | OPCODE(ShiftRightArithmetic64, U64, U64, U32, ) | ||
| 242 | OPCODE(BitwiseAnd32, U32, U32, U32, ) | 244 | OPCODE(BitwiseAnd32, U32, U32, U32, ) |
| 243 | OPCODE(BitwiseOr32, U32, U32, U32, ) | 245 | OPCODE(BitwiseOr32, U32, U32, U32, ) |
| 244 | OPCODE(BitwiseXor32, U32, U32, U32, ) | 246 | OPCODE(BitwiseXor32, U32, U32, U32, ) |
diff --git a/src/shader_recompiler/frontend/maxwell/translate/impl/integer_funnel_shift.cpp b/src/shader_recompiler/frontend/maxwell/translate/impl/integer_funnel_shift.cpp new file mode 100644 index 000000000..d8d6c939e --- /dev/null +++ b/src/shader_recompiler/frontend/maxwell/translate/impl/integer_funnel_shift.cpp | |||
| @@ -0,0 +1,77 @@ | |||
| 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 MaxShift : u64 { | ||
| 12 | U32, | ||
| 13 | Undefined, | ||
| 14 | U64, | ||
| 15 | S64, | ||
| 16 | }; | ||
| 17 | |||
| 18 | IR::U64 PackedShift(IR::IREmitter& ir, const IR::U64& packed_int, const IR::U32& safe_shift, | ||
| 19 | bool right_shift, bool is_signed) { | ||
| 20 | if (!right_shift) { | ||
| 21 | return ir.ShiftLeftLogical(packed_int, safe_shift); | ||
| 22 | } | ||
| 23 | if (is_signed) { | ||
| 24 | return ir.ShiftRightArithmetic(packed_int, safe_shift); | ||
| 25 | } | ||
| 26 | return ir.ShiftRightLogical(packed_int, safe_shift); | ||
| 27 | } | ||
| 28 | |||
| 29 | void SHF(TranslatorVisitor& v, u64 insn, const IR::U32& shift, const IR::U32& high_bits, | ||
| 30 | bool right_shift) { | ||
| 31 | union { | ||
| 32 | u64 insn; | ||
| 33 | BitField<0, 8, IR::Reg> dest_reg; | ||
| 34 | BitField<0, 8, IR::Reg> lo_bits_reg; | ||
| 35 | BitField<37, 2, MaxShift> max_shift; | ||
| 36 | BitField<48, 2, u64> x_mode; | ||
| 37 | BitField<50, 1, u64> wrap; | ||
| 38 | } const shf{insn}; | ||
| 39 | if (shf.x_mode != 0) { | ||
| 40 | throw NotImplementedException("SHF X Mode"); | ||
| 41 | } | ||
| 42 | if (shf.max_shift == MaxShift::Undefined) { | ||
| 43 | throw NotImplementedException("SHF Use of undefined MaxShift value"); | ||
| 44 | } | ||
| 45 | const IR::U32 low_bits{v.X(shf.lo_bits_reg)}; | ||
| 46 | const IR::U64 packed_int{v.ir.PackUint2x32(v.ir.CompositeConstruct(low_bits, high_bits))}; | ||
| 47 | const IR::U32 max_shift{shf.max_shift == MaxShift::U32 ? v.ir.Imm32(32) : v.ir.Imm32(63)}; | ||
| 48 | const IR::U32 safe_shift{shf.wrap != 0 | ||
| 49 | ? v.ir.BitwiseAnd(shift, v.ir.ISub(max_shift, v.ir.Imm32(1))) | ||
| 50 | : v.ir.UMin(shift, max_shift)}; | ||
| 51 | |||
| 52 | const bool is_signed{shf.max_shift == MaxShift::S64}; | ||
| 53 | const IR::U64 shifted_value{PackedShift(v.ir, packed_int, safe_shift, right_shift, is_signed)}; | ||
| 54 | const IR::Value unpacked_value{v.ir.UnpackUint2x32(shifted_value)}; | ||
| 55 | |||
| 56 | const IR::U32 result{v.ir.CompositeExtract(unpacked_value, right_shift ? 0 : 1)}; | ||
| 57 | v.X(shf.dest_reg, result); | ||
| 58 | } | ||
| 59 | } // Anonymous namespace | ||
| 60 | |||
| 61 | void TranslatorVisitor::SHF_l_reg(u64 insn) { | ||
| 62 | SHF(*this, insn, GetReg20(insn), GetReg39(insn), false); | ||
| 63 | } | ||
| 64 | |||
| 65 | void TranslatorVisitor::SHF_l_imm(u64 insn) { | ||
| 66 | SHF(*this, insn, GetImm20(insn), GetReg39(insn), false); | ||
| 67 | } | ||
| 68 | |||
| 69 | void TranslatorVisitor::SHF_r_reg(u64 insn) { | ||
| 70 | SHF(*this, insn, GetReg20(insn), GetReg39(insn), true); | ||
| 71 | } | ||
| 72 | |||
| 73 | void TranslatorVisitor::SHF_r_imm(u64 insn) { | ||
| 74 | SHF(*this, insn, GetImm20(insn), GetReg39(insn), true); | ||
| 75 | } | ||
| 76 | |||
| 77 | } // 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 62863aff6..2ab90d1bf 100644 --- a/src/shader_recompiler/frontend/maxwell/translate/impl/not_implemented.cpp +++ b/src/shader_recompiler/frontend/maxwell/translate/impl/not_implemented.cpp | |||
| @@ -553,22 +553,6 @@ void TranslatorVisitor::SETLMEMBASE(u64) { | |||
| 553 | ThrowNotImplemented(Opcode::SETLMEMBASE); | 553 | ThrowNotImplemented(Opcode::SETLMEMBASE); |
| 554 | } | 554 | } |
| 555 | 555 | ||
| 556 | void TranslatorVisitor::SHF_l_reg(u64) { | ||
| 557 | ThrowNotImplemented(Opcode::SHF_l_reg); | ||
| 558 | } | ||
| 559 | |||
| 560 | void TranslatorVisitor::SHF_l_imm(u64) { | ||
| 561 | ThrowNotImplemented(Opcode::SHF_l_imm); | ||
| 562 | } | ||
| 563 | |||
| 564 | void TranslatorVisitor::SHF_r_reg(u64) { | ||
| 565 | ThrowNotImplemented(Opcode::SHF_r_reg); | ||
| 566 | } | ||
| 567 | |||
| 568 | void TranslatorVisitor::SHF_r_imm(u64) { | ||
| 569 | ThrowNotImplemented(Opcode::SHF_r_imm); | ||
| 570 | } | ||
| 571 | |||
| 572 | void TranslatorVisitor::SHFL(u64) { | 556 | void TranslatorVisitor::SHFL(u64) { |
| 573 | ThrowNotImplemented(Opcode::SHFL); | 557 | ThrowNotImplemented(Opcode::SHFL); |
| 574 | } | 558 | } |