diff options
Diffstat (limited to 'src/shader_recompiler')
8 files changed, 80 insertions, 18 deletions
diff --git a/src/shader_recompiler/CMakeLists.txt b/src/shader_recompiler/CMakeLists.txt index 17ccb3d98..14dc51b5f 100644 --- a/src/shader_recompiler/CMakeLists.txt +++ b/src/shader_recompiler/CMakeLists.txt | |||
| @@ -72,6 +72,7 @@ add_library(shader_recompiler STATIC | |||
| 72 | frontend/maxwell/translate/impl/integer_scaled_add.cpp | 72 | frontend/maxwell/translate/impl/integer_scaled_add.cpp |
| 73 | frontend/maxwell/translate/impl/integer_set_predicate.cpp | 73 | frontend/maxwell/translate/impl/integer_set_predicate.cpp |
| 74 | frontend/maxwell/translate/impl/integer_shift_left.cpp | 74 | frontend/maxwell/translate/impl/integer_shift_left.cpp |
| 75 | frontend/maxwell/translate/impl/integer_shift_right.cpp | ||
| 75 | frontend/maxwell/translate/impl/integer_short_multiply_add.cpp | 76 | frontend/maxwell/translate/impl/integer_short_multiply_add.cpp |
| 76 | frontend/maxwell/translate/impl/load_store_attribute.cpp | 77 | frontend/maxwell/translate/impl/load_store_attribute.cpp |
| 77 | frontend/maxwell/translate/impl/load_store_memory.cpp | 78 | frontend/maxwell/translate/impl/load_store_memory.cpp |
diff --git a/src/shader_recompiler/backend/spirv/emit_spirv.h b/src/shader_recompiler/backend/spirv/emit_spirv.h index 4b74cf04d..90afbcc90 100644 --- a/src/shader_recompiler/backend/spirv/emit_spirv.h +++ b/src/shader_recompiler/backend/spirv/emit_spirv.h | |||
| @@ -219,14 +219,15 @@ Id EmitIMul32(EmitContext& ctx, Id a, Id b); | |||
| 219 | Id EmitINeg32(EmitContext& ctx, Id value); | 219 | Id EmitINeg32(EmitContext& ctx, Id value); |
| 220 | Id EmitIAbs32(EmitContext& ctx, Id value); | 220 | Id EmitIAbs32(EmitContext& ctx, Id value); |
| 221 | Id EmitShiftLeftLogical32(EmitContext& ctx, Id base, Id shift); | 221 | Id EmitShiftLeftLogical32(EmitContext& ctx, Id base, Id shift); |
| 222 | void EmitShiftRightLogical32(EmitContext& ctx); | 222 | Id EmitShiftRightLogical32(EmitContext& ctx, Id a, Id b); |
| 223 | void EmitShiftRightArithmetic32(EmitContext& ctx); | 223 | Id EmitShiftRightArithmetic32(EmitContext& ctx, Id a, Id b); |
| 224 | Id EmitBitwiseAnd32(EmitContext& ctx, Id a, Id b); | 224 | Id EmitBitwiseAnd32(EmitContext& ctx, Id a, Id b); |
| 225 | Id EmitBitwiseOr32(EmitContext& ctx, Id a, Id b); | 225 | Id EmitBitwiseOr32(EmitContext& ctx, Id a, Id b); |
| 226 | Id EmitBitwiseXor32(EmitContext& ctx, Id a, Id b); | 226 | Id EmitBitwiseXor32(EmitContext& ctx, Id a, Id b); |
| 227 | Id EmitBitFieldInsert(EmitContext& ctx, Id base, Id insert, Id offset, Id count); | 227 | Id EmitBitFieldInsert(EmitContext& ctx, Id base, Id insert, Id offset, Id count); |
| 228 | Id EmitBitFieldSExtract(EmitContext& ctx, Id base, Id offset, Id count); | 228 | Id EmitBitFieldSExtract(EmitContext& ctx, Id base, Id offset, Id count); |
| 229 | Id EmitBitFieldUExtract(EmitContext& ctx, Id base, Id offset, Id count); | 229 | Id EmitBitFieldUExtract(EmitContext& ctx, Id base, Id offset, Id count); |
| 230 | Id EmitBitReverse32(EmitContext& ctx, Id value); | ||
| 230 | Id EmitSLessThan(EmitContext& ctx, Id lhs, Id rhs); | 231 | Id EmitSLessThan(EmitContext& ctx, Id lhs, Id rhs); |
| 231 | Id EmitULessThan(EmitContext& ctx, Id lhs, Id rhs); | 232 | Id EmitULessThan(EmitContext& ctx, Id lhs, Id rhs); |
| 232 | Id EmitIEqual(EmitContext& ctx, Id lhs, Id rhs); | 233 | 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 8aaa0e381..406df1b78 100644 --- a/src/shader_recompiler/backend/spirv/emit_spirv_integer.cpp +++ b/src/shader_recompiler/backend/spirv/emit_spirv_integer.cpp | |||
| @@ -70,12 +70,12 @@ Id EmitShiftLeftLogical32(EmitContext& ctx, Id base, Id shift) { | |||
| 70 | return ctx.OpShiftLeftLogical(ctx.U32[1], base, shift); | 70 | return ctx.OpShiftLeftLogical(ctx.U32[1], base, shift); |
| 71 | } | 71 | } |
| 72 | 72 | ||
| 73 | void EmitShiftRightLogical32(EmitContext&) { | 73 | Id EmitShiftRightLogical32(EmitContext& ctx, Id a, Id b) { |
| 74 | throw NotImplementedException("SPIR-V Instruction"); | 74 | return ctx.OpShiftRightLogical(ctx.U32[1], a, b); |
| 75 | } | 75 | } |
| 76 | 76 | ||
| 77 | void EmitShiftRightArithmetic32(EmitContext&) { | 77 | Id EmitShiftRightArithmetic32(EmitContext& ctx, Id a, Id b) { |
| 78 | throw NotImplementedException("SPIR-V Instruction"); | 78 | return ctx.OpShiftRightArithmetic(ctx.U32[1], a, b); |
| 79 | } | 79 | } |
| 80 | 80 | ||
| 81 | Id EmitBitwiseAnd32(EmitContext& ctx, Id a, Id b) { | 81 | Id EmitBitwiseAnd32(EmitContext& ctx, Id a, Id b) { |
| @@ -102,6 +102,10 @@ Id EmitBitFieldUExtract(EmitContext& ctx, Id base, Id offset, Id count) { | |||
| 102 | return ctx.OpBitFieldUExtract(ctx.U32[1], base, offset, count); | 102 | return ctx.OpBitFieldUExtract(ctx.U32[1], base, offset, count); |
| 103 | } | 103 | } |
| 104 | 104 | ||
| 105 | Id EmitBitReverse32(EmitContext& ctx, Id value) { | ||
| 106 | return ctx.OpBitReverse(ctx.U32[1], value); | ||
| 107 | } | ||
| 108 | |||
| 105 | Id EmitSLessThan(EmitContext& ctx, Id lhs, Id rhs) { | 109 | Id EmitSLessThan(EmitContext& ctx, Id lhs, Id rhs) { |
| 106 | return ctx.OpSLessThan(ctx.U1, lhs, rhs); | 110 | return ctx.OpSLessThan(ctx.U1, lhs, rhs); |
| 107 | } | 111 | } |
diff --git a/src/shader_recompiler/frontend/ir/ir_emitter.cpp b/src/shader_recompiler/frontend/ir/ir_emitter.cpp index 0209d5540..7c3908398 100644 --- a/src/shader_recompiler/frontend/ir/ir_emitter.cpp +++ b/src/shader_recompiler/frontend/ir/ir_emitter.cpp | |||
| @@ -804,6 +804,10 @@ U32 IREmitter::BitFieldExtract(const U32& base, const U32& offset, const U32& co | |||
| 804 | count); | 804 | count); |
| 805 | } | 805 | } |
| 806 | 806 | ||
| 807 | U32 IREmitter::BitReverse(const U32& value) { | ||
| 808 | return Inst<U32>(Opcode::BitReverse32, value); | ||
| 809 | } | ||
| 810 | |||
| 807 | U1 IREmitter::ILessThan(const U32& lhs, const U32& rhs, bool is_signed) { | 811 | U1 IREmitter::ILessThan(const U32& lhs, const U32& rhs, bool is_signed) { |
| 808 | return Inst<U1>(is_signed ? Opcode::SLessThan : Opcode::ULessThan, lhs, rhs); | 812 | return Inst<U1>(is_signed ? Opcode::SLessThan : Opcode::ULessThan, lhs, rhs); |
| 809 | } | 813 | } |
diff --git a/src/shader_recompiler/frontend/ir/ir_emitter.h b/src/shader_recompiler/frontend/ir/ir_emitter.h index 2c923716a..f7998e156 100644 --- a/src/shader_recompiler/frontend/ir/ir_emitter.h +++ b/src/shader_recompiler/frontend/ir/ir_emitter.h | |||
| @@ -159,6 +159,7 @@ public: | |||
| 159 | const U32& count); | 159 | const U32& count); |
| 160 | [[nodiscard]] U32 BitFieldExtract(const U32& base, const U32& offset, const U32& count, | 160 | [[nodiscard]] U32 BitFieldExtract(const U32& base, const U32& offset, const U32& count, |
| 161 | bool is_signed); | 161 | bool is_signed); |
| 162 | [[nodiscard]] U32 BitReverse(const U32& value); | ||
| 162 | 163 | ||
| 163 | [[nodiscard]] U1 ILessThan(const U32& lhs, const U32& rhs, bool is_signed); | 164 | [[nodiscard]] U1 ILessThan(const U32& lhs, const U32& rhs, bool is_signed); |
| 164 | [[nodiscard]] U1 IEqual(const U32& lhs, const U32& rhs); | 165 | [[nodiscard]] U1 IEqual(const U32& lhs, const U32& rhs); |
diff --git a/src/shader_recompiler/frontend/ir/opcodes.inc b/src/shader_recompiler/frontend/ir/opcodes.inc index 289e76f32..f420f1161 100644 --- a/src/shader_recompiler/frontend/ir/opcodes.inc +++ b/src/shader_recompiler/frontend/ir/opcodes.inc | |||
| @@ -231,6 +231,7 @@ OPCODE(BitwiseXor32, U32, U32, | |||
| 231 | OPCODE(BitFieldInsert, U32, U32, U32, U32, U32, ) | 231 | OPCODE(BitFieldInsert, U32, U32, U32, U32, U32, ) |
| 232 | OPCODE(BitFieldSExtract, U32, U32, U32, U32, ) | 232 | OPCODE(BitFieldSExtract, U32, U32, U32, U32, ) |
| 233 | OPCODE(BitFieldUExtract, U32, U32, U32, U32, ) | 233 | OPCODE(BitFieldUExtract, U32, U32, U32, U32, ) |
| 234 | OPCODE(BitReverse32, U32, U32, ) | ||
| 234 | 235 | ||
| 235 | OPCODE(SLessThan, U1, U32, U32, ) | 236 | OPCODE(SLessThan, U1, U32, U32, ) |
| 236 | OPCODE(ULessThan, U1, U32, U32, ) | 237 | OPCODE(ULessThan, U1, U32, U32, ) |
diff --git a/src/shader_recompiler/frontend/maxwell/translate/impl/integer_shift_right.cpp b/src/shader_recompiler/frontend/maxwell/translate/impl/integer_shift_right.cpp new file mode 100644 index 000000000..a34ccb851 --- /dev/null +++ b/src/shader_recompiler/frontend/maxwell/translate/impl/integer_shift_right.cpp | |||
| @@ -0,0 +1,62 @@ | |||
| 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 SHR(TranslatorVisitor& v, u64 insn, const IR::U32& shift) { | ||
| 12 | union { | ||
| 13 | u64 insn; | ||
| 14 | BitField<0, 8, IR::Reg> dest_reg; | ||
| 15 | BitField<8, 8, IR::Reg> src_reg_a; | ||
| 16 | BitField<39, 1, u64> is_wrapped; | ||
| 17 | BitField<40, 1, u64> brev; | ||
| 18 | BitField<43, 1, u64> xmode; | ||
| 19 | BitField<48, 1, u64> is_arithmetic; | ||
| 20 | } const shr{insn}; | ||
| 21 | |||
| 22 | if (shr.xmode != 0) { | ||
| 23 | throw NotImplementedException("SHR.XMODE"); | ||
| 24 | } | ||
| 25 | |||
| 26 | IR::U32 base{v.X(shr.src_reg_a)}; | ||
| 27 | if (shr.brev == 1) { | ||
| 28 | base = v.ir.BitReverse(base); | ||
| 29 | } | ||
| 30 | IR::U32 result; | ||
| 31 | const IR::U32 safe_shift = shr.is_wrapped == 0 ? shift : v.ir.BitwiseAnd(shift, v.ir.Imm32(31)); | ||
| 32 | if (shr.is_arithmetic == 1) { | ||
| 33 | result = IR::U32{v.ir.ShiftRightArithmetic(base, safe_shift)}; | ||
| 34 | } else { | ||
| 35 | result = IR::U32{v.ir.ShiftRightLogical(base, safe_shift)}; | ||
| 36 | } | ||
| 37 | |||
| 38 | if (shr.is_wrapped == 0) { | ||
| 39 | const IR::U32 zero{v.ir.Imm32(0)}; | ||
| 40 | const IR::U32 safe_bits{v.ir.Imm32(32)}; | ||
| 41 | |||
| 42 | const IR::U1 is_negative{v.ir.ILessThan(result, zero, true)}; | ||
| 43 | const IR::U1 is_safe{v.ir.ILessThan(shift, safe_bits, false)}; | ||
| 44 | const IR::U32 clamped_value{v.ir.Select(is_negative, v.ir.Imm32(-1), zero)}; | ||
| 45 | result = IR::U32{v.ir.Select(is_safe, result, clamped_value)}; | ||
| 46 | } | ||
| 47 | v.X(shr.dest_reg, result); | ||
| 48 | } | ||
| 49 | } // Anonymous namespace | ||
| 50 | |||
| 51 | void TranslatorVisitor::SHR_reg(u64 insn) { | ||
| 52 | SHR(*this, insn, GetReg20(insn)); | ||
| 53 | } | ||
| 54 | |||
| 55 | void TranslatorVisitor::SHR_cbuf(u64 insn) { | ||
| 56 | SHR(*this, insn, GetCbuf(insn)); | ||
| 57 | } | ||
| 58 | |||
| 59 | void TranslatorVisitor::SHR_imm(u64 insn) { | ||
| 60 | SHR(*this, insn, GetImm20(insn)); | ||
| 61 | } | ||
| 62 | } // 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 82c73bf8c..45ed04e25 100644 --- a/src/shader_recompiler/frontend/maxwell/translate/impl/not_implemented.cpp +++ b/src/shader_recompiler/frontend/maxwell/translate/impl/not_implemented.cpp | |||
| @@ -757,18 +757,6 @@ void TranslatorVisitor::SHFL(u64) { | |||
| 757 | ThrowNotImplemented(Opcode::SHFL); | 757 | ThrowNotImplemented(Opcode::SHFL); |
| 758 | } | 758 | } |
| 759 | 759 | ||
| 760 | void TranslatorVisitor::SHR_reg(u64) { | ||
| 761 | ThrowNotImplemented(Opcode::SHR_reg); | ||
| 762 | } | ||
| 763 | |||
| 764 | void TranslatorVisitor::SHR_cbuf(u64) { | ||
| 765 | ThrowNotImplemented(Opcode::SHR_cbuf); | ||
| 766 | } | ||
| 767 | |||
| 768 | void TranslatorVisitor::SHR_imm(u64) { | ||
| 769 | ThrowNotImplemented(Opcode::SHR_imm); | ||
| 770 | } | ||
| 771 | |||
| 772 | void TranslatorVisitor::SSY() { | 760 | void TranslatorVisitor::SSY() { |
| 773 | // SSY is a no-op | 761 | // SSY is a no-op |
| 774 | } | 762 | } |