diff options
| author | 2021-03-05 01:15:16 -0500 | |
|---|---|---|
| committer | 2021-07-22 21:51:23 -0400 | |
| commit | 5465cb156107a27df525dfedbfd4e920b7f71253 (patch) | |
| tree | 3bc5940f90e31e09820af69cd845eef92a7d7201 /src/shader_recompiler/frontend | |
| parent | shader: Deduplicate HADD2 code (diff) | |
| download | yuzu-5465cb156107a27df525dfedbfd4e920b7f71253.tar.gz yuzu-5465cb156107a27df525dfedbfd4e920b7f71253.tar.xz yuzu-5465cb156107a27df525dfedbfd4e920b7f71253.zip | |
shader: Implement LEA
Diffstat (limited to 'src/shader_recompiler/frontend')
5 files changed, 122 insertions, 26 deletions
diff --git a/src/shader_recompiler/frontend/ir/ir_emitter.cpp b/src/shader_recompiler/frontend/ir/ir_emitter.cpp index 186920d8f..01f52183c 100644 --- a/src/shader_recompiler/frontend/ir/ir_emitter.cpp +++ b/src/shader_recompiler/frontend/ir/ir_emitter.cpp | |||
| @@ -798,8 +798,15 @@ U32 IREmitter::IMul(const U32& a, const U32& b) { | |||
| 798 | return Inst<U32>(Opcode::IMul32, a, b); | 798 | return Inst<U32>(Opcode::IMul32, a, b); |
| 799 | } | 799 | } |
| 800 | 800 | ||
| 801 | U32 IREmitter::INeg(const U32& value) { | 801 | U32U64 IREmitter::INeg(const U32U64& value) { |
| 802 | return Inst<U32>(Opcode::INeg32, value); | 802 | switch (value.Type()) { |
| 803 | case Type::U32: | ||
| 804 | return Inst<U32>(Opcode::INeg32, value); | ||
| 805 | case Type::U64: | ||
| 806 | return Inst<U64>(Opcode::INeg64, value); | ||
| 807 | default: | ||
| 808 | ThrowInvalidType(value.Type()); | ||
| 809 | } | ||
| 803 | } | 810 | } |
| 804 | 811 | ||
| 805 | U32 IREmitter::IAbs(const U32& value) { | 812 | U32 IREmitter::IAbs(const U32& value) { |
| @@ -810,8 +817,15 @@ U32 IREmitter::ShiftLeftLogical(const U32& base, const U32& shift) { | |||
| 810 | return Inst<U32>(Opcode::ShiftLeftLogical32, base, shift); | 817 | return Inst<U32>(Opcode::ShiftLeftLogical32, base, shift); |
| 811 | } | 818 | } |
| 812 | 819 | ||
| 813 | U32 IREmitter::ShiftRightLogical(const U32& base, const U32& shift) { | 820 | U32U64 IREmitter::ShiftRightLogical(const U32U64& base, const U32& shift) { |
| 814 | return Inst<U32>(Opcode::ShiftRightLogical32, base, shift); | 821 | switch (base.Type()) { |
| 822 | case Type::U32: | ||
| 823 | return Inst<U32>(Opcode::ShiftRightLogical32, base, shift); | ||
| 824 | case Type::U64: | ||
| 825 | return Inst<U64>(Opcode::ShiftRightLogical64, base, shift); | ||
| 826 | default: | ||
| 827 | ThrowInvalidType(base.Type()); | ||
| 828 | } | ||
| 815 | } | 829 | } |
| 816 | 830 | ||
| 817 | U32 IREmitter::ShiftRightArithmetic(const U32& base, const U32& shift) { | 831 | U32 IREmitter::ShiftRightArithmetic(const U32& base, const U32& shift) { |
diff --git a/src/shader_recompiler/frontend/ir/ir_emitter.h b/src/shader_recompiler/frontend/ir/ir_emitter.h index 5beb99895..33bf2a7d0 100644 --- a/src/shader_recompiler/frontend/ir/ir_emitter.h +++ b/src/shader_recompiler/frontend/ir/ir_emitter.h | |||
| @@ -148,10 +148,10 @@ public: | |||
| 148 | [[nodiscard]] U32U64 IAdd(const U32U64& a, const U32U64& b); | 148 | [[nodiscard]] U32U64 IAdd(const U32U64& a, const U32U64& b); |
| 149 | [[nodiscard]] U32U64 ISub(const U32U64& a, const U32U64& b); | 149 | [[nodiscard]] U32U64 ISub(const U32U64& a, const U32U64& b); |
| 150 | [[nodiscard]] U32 IMul(const U32& a, const U32& b); | 150 | [[nodiscard]] U32 IMul(const U32& a, const U32& b); |
| 151 | [[nodiscard]] U32 INeg(const U32& 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]] U32 ShiftLeftLogical(const U32& base, const U32& shift); |
| 154 | [[nodiscard]] U32 ShiftRightLogical(const U32& 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]] U32 ShiftRightArithmetic(const U32& 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); |
diff --git a/src/shader_recompiler/frontend/ir/opcodes.inc b/src/shader_recompiler/frontend/ir/opcodes.inc index acfc0a829..b51aaaef5 100644 --- a/src/shader_recompiler/frontend/ir/opcodes.inc +++ b/src/shader_recompiler/frontend/ir/opcodes.inc | |||
| @@ -233,9 +233,11 @@ OPCODE(ISub32, U32, U32, | |||
| 233 | OPCODE(ISub64, U64, U64, U64, ) | 233 | OPCODE(ISub64, U64, U64, U64, ) |
| 234 | OPCODE(IMul32, U32, U32, U32, ) | 234 | OPCODE(IMul32, U32, U32, U32, ) |
| 235 | OPCODE(INeg32, U32, U32, ) | 235 | OPCODE(INeg32, U32, U32, ) |
| 236 | OPCODE(INeg64, U64, U64, ) | ||
| 236 | OPCODE(IAbs32, U32, U32, ) | 237 | OPCODE(IAbs32, U32, U32, ) |
| 237 | OPCODE(ShiftLeftLogical32, U32, U32, U32, ) | 238 | OPCODE(ShiftLeftLogical32, U32, U32, U32, ) |
| 238 | OPCODE(ShiftRightLogical32, U32, U32, U32, ) | 239 | OPCODE(ShiftRightLogical32, U32, U32, U32, ) |
| 240 | OPCODE(ShiftRightLogical64, U64, U64, U32, ) | ||
| 239 | OPCODE(ShiftRightArithmetic32, U32, U32, U32, ) | 241 | OPCODE(ShiftRightArithmetic32, U32, U32, U32, ) |
| 240 | OPCODE(BitwiseAnd32, U32, U32, U32, ) | 242 | OPCODE(BitwiseAnd32, U32, U32, U32, ) |
| 241 | OPCODE(BitwiseOr32, U32, U32, U32, ) | 243 | OPCODE(BitwiseOr32, U32, U32, U32, ) |
diff --git a/src/shader_recompiler/frontend/maxwell/translate/impl/load_effective_address.cpp b/src/shader_recompiler/frontend/maxwell/translate/impl/load_effective_address.cpp new file mode 100644 index 000000000..784588e83 --- /dev/null +++ b/src/shader_recompiler/frontend/maxwell/translate/impl/load_effective_address.cpp | |||
| @@ -0,0 +1,100 @@ | |||
| 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 LEA_hi(TranslatorVisitor& v, u64 insn, const IR::U32& base, IR::U32 offset_hi, u64 scale, | ||
| 12 | bool neg, bool x) { | ||
| 13 | union { | ||
| 14 | u64 insn; | ||
| 15 | BitField<0, 8, IR::Reg> dest_reg; | ||
| 16 | BitField<8, 8, IR::Reg> offset_lo_reg; | ||
| 17 | BitField<48, 3, IR::Pred> pred; | ||
| 18 | } const lea{insn}; | ||
| 19 | |||
| 20 | if (x) { | ||
| 21 | throw NotImplementedException("LEA.HI X"); | ||
| 22 | } | ||
| 23 | if (lea.pred != IR::Pred::PT) { | ||
| 24 | throw NotImplementedException("LEA.LO Pred"); | ||
| 25 | } | ||
| 26 | |||
| 27 | const IR::U32 offset_lo{v.X(lea.offset_lo_reg)}; | ||
| 28 | const IR::U64 packed_offset{v.ir.PackUint2x32(v.ir.CompositeConstruct(offset_lo, offset_hi))}; | ||
| 29 | const IR::U64 offset{neg ? IR::U64{v.ir.INeg(packed_offset)} : packed_offset}; | ||
| 30 | |||
| 31 | const s32 hi_scale{32 - static_cast<s32>(scale)}; | ||
| 32 | const IR::U64 scaled_offset{v.ir.ShiftRightLogical(offset, v.ir.Imm32(hi_scale))}; | ||
| 33 | const IR::U32 scaled_offset_w0{v.ir.CompositeExtract(v.ir.UnpackUint2x32(scaled_offset), 0)}; | ||
| 34 | |||
| 35 | IR::U32 result{v.ir.IAdd(base, scaled_offset_w0)}; | ||
| 36 | v.X(lea.dest_reg, result); | ||
| 37 | } | ||
| 38 | |||
| 39 | void LEA_lo(TranslatorVisitor& v, u64 insn, const IR::U32& base) { | ||
| 40 | union { | ||
| 41 | u64 insn; | ||
| 42 | BitField<0, 8, IR::Reg> dest_reg; | ||
| 43 | BitField<8, 8, IR::Reg> offset_lo_reg; | ||
| 44 | BitField<39, 5, u64> scale; | ||
| 45 | BitField<45, 1, u64> neg; | ||
| 46 | BitField<46, 1, u64> x; | ||
| 47 | BitField<48, 3, IR::Pred> pred; | ||
| 48 | } const lea{insn}; | ||
| 49 | if (lea.x != 0) { | ||
| 50 | throw NotImplementedException("LEA.LO X"); | ||
| 51 | } | ||
| 52 | if (lea.pred != IR::Pred::PT) { | ||
| 53 | throw NotImplementedException("LEA.LO Pred"); | ||
| 54 | } | ||
| 55 | |||
| 56 | const IR::U32 offset_lo{v.X(lea.offset_lo_reg)}; | ||
| 57 | const s32 scale{static_cast<s32>(lea.scale)}; | ||
| 58 | const IR::U32 offset{lea.neg != 0 ? IR::U32{v.ir.INeg(offset_lo)} : offset_lo}; | ||
| 59 | const IR::U32 scaled_offset{v.ir.ShiftLeftLogical(offset, v.ir.Imm32(scale))}; | ||
| 60 | |||
| 61 | IR::U32 result{v.ir.IAdd(base, scaled_offset)}; | ||
| 62 | v.X(lea.dest_reg, result); | ||
| 63 | } | ||
| 64 | } // Anonymous namespace | ||
| 65 | |||
| 66 | void TranslatorVisitor::LEA_hi_reg(u64 insn) { | ||
| 67 | union { | ||
| 68 | u64 insn; | ||
| 69 | BitField<28, 5, u64> scale; | ||
| 70 | BitField<37, 1, u64> neg; | ||
| 71 | BitField<38, 1, u64> x; | ||
| 72 | } const lea{insn}; | ||
| 73 | |||
| 74 | LEA_hi(*this, insn, GetReg20(insn), GetReg39(insn), lea.scale, lea.neg != 0, lea.x != 0); | ||
| 75 | } | ||
| 76 | |||
| 77 | void TranslatorVisitor::LEA_hi_cbuf(u64 insn) { | ||
| 78 | union { | ||
| 79 | u64 insn; | ||
| 80 | BitField<51, 5, u64> scale; | ||
| 81 | BitField<56, 1, u64> neg; | ||
| 82 | BitField<57, 1, u64> x; | ||
| 83 | } const lea{insn}; | ||
| 84 | |||
| 85 | LEA_hi(*this, insn, GetCbuf(insn), GetReg39(insn), lea.scale, lea.neg != 0, lea.x != 0); | ||
| 86 | } | ||
| 87 | |||
| 88 | void TranslatorVisitor::LEA_lo_reg(u64 insn) { | ||
| 89 | LEA_lo(*this, insn, GetReg20(insn)); | ||
| 90 | } | ||
| 91 | |||
| 92 | void TranslatorVisitor::LEA_lo_cbuf(u64 insn) { | ||
| 93 | LEA_lo(*this, insn, GetCbuf(insn)); | ||
| 94 | } | ||
| 95 | |||
| 96 | void TranslatorVisitor::LEA_lo_imm(u64 insn) { | ||
| 97 | LEA_lo(*this, insn, GetImm20(insn)); | ||
| 98 | } | ||
| 99 | |||
| 100 | } // 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 bd7a7a8b7..62863aff6 100644 --- a/src/shader_recompiler/frontend/maxwell/translate/impl/not_implemented.cpp +++ b/src/shader_recompiler/frontend/maxwell/translate/impl/not_implemented.cpp | |||
| @@ -437,26 +437,6 @@ void TranslatorVisitor::LDS(u64) { | |||
| 437 | ThrowNotImplemented(Opcode::LDS); | 437 | ThrowNotImplemented(Opcode::LDS); |
| 438 | } | 438 | } |
| 439 | 439 | ||
| 440 | void TranslatorVisitor::LEA_hi_reg(u64) { | ||
| 441 | ThrowNotImplemented(Opcode::LEA_hi_reg); | ||
| 442 | } | ||
| 443 | |||
| 444 | void TranslatorVisitor::LEA_hi_cbuf(u64) { | ||
| 445 | ThrowNotImplemented(Opcode::LEA_hi_cbuf); | ||
| 446 | } | ||
| 447 | |||
| 448 | void TranslatorVisitor::LEA_lo_reg(u64) { | ||
| 449 | ThrowNotImplemented(Opcode::LEA_lo_reg); | ||
| 450 | } | ||
| 451 | |||
| 452 | void TranslatorVisitor::LEA_lo_cbuf(u64) { | ||
| 453 | ThrowNotImplemented(Opcode::LEA_lo_cbuf); | ||
| 454 | } | ||
| 455 | |||
| 456 | void TranslatorVisitor::LEA_lo_imm(u64) { | ||
| 457 | ThrowNotImplemented(Opcode::LEA_lo_imm); | ||
| 458 | } | ||
| 459 | |||
| 460 | void TranslatorVisitor::LEPC(u64) { | 440 | void TranslatorVisitor::LEPC(u64) { |
| 461 | ThrowNotImplemented(Opcode::LEPC); | 441 | ThrowNotImplemented(Opcode::LEPC); |
| 462 | } | 442 | } |