diff options
Diffstat (limited to 'src/shader_recompiler/frontend/maxwell')
3 files changed, 97 insertions, 8 deletions
diff --git a/src/shader_recompiler/frontend/maxwell/translate/impl/impl.cpp b/src/shader_recompiler/frontend/maxwell/translate/impl/impl.cpp index a5a0e1a9b..7564aeeb2 100644 --- a/src/shader_recompiler/frontend/maxwell/translate/impl/impl.cpp +++ b/src/shader_recompiler/frontend/maxwell/translate/impl/impl.cpp | |||
| @@ -56,25 +56,32 @@ IR::F32 TranslatorVisitor::GetFloatReg39(u64 insn) { | |||
| 56 | return ir.BitCast<IR::F32>(GetReg39(insn)); | 56 | return ir.BitCast<IR::F32>(GetReg39(insn)); |
| 57 | } | 57 | } |
| 58 | 58 | ||
| 59 | IR::U32 TranslatorVisitor::GetCbuf(u64 insn) { | 59 | static std::pair<IR::U32, IR::U32> CbufAddr(u64 insn) { |
| 60 | union { | 60 | union { |
| 61 | u64 raw; | 61 | u64 raw; |
| 62 | BitField<20, 14, s64> offset; | 62 | BitField<20, 14, s64> offset; |
| 63 | BitField<34, 5, u64> binding; | 63 | BitField<34, 5, u64> binding; |
| 64 | } const cbuf{insn}; | 64 | } const cbuf{insn}; |
| 65 | |||
| 65 | if (cbuf.binding >= 18) { | 66 | if (cbuf.binding >= 18) { |
| 66 | throw NotImplementedException("Out of bounds constant buffer binding {}", cbuf.binding); | 67 | throw NotImplementedException("Out of bounds constant buffer binding {}", cbuf.binding); |
| 67 | } | 68 | } |
| 68 | if (cbuf.offset >= 0x10'000 || cbuf.offset < 0) { | 69 | if (cbuf.offset >= 0x10'000 || cbuf.offset < 0) { |
| 69 | throw NotImplementedException("Out of bounds constant buffer offset {}", cbuf.offset); | 70 | throw NotImplementedException("Out of bounds constant buffer offset {}", cbuf.offset); |
| 70 | } | 71 | } |
| 71 | const IR::U32 binding{ir.Imm32(static_cast<u32>(cbuf.binding))}; | 72 | const IR::Value binding{static_cast<u32>(cbuf.binding)}; |
| 72 | const IR::U32 byte_offset{ir.Imm32(static_cast<u32>(cbuf.offset) * 4)}; | 73 | const IR::Value byte_offset{static_cast<u32>(cbuf.offset) * 4}; |
| 74 | return {IR::U32{binding}, IR::U32{byte_offset}}; | ||
| 75 | } | ||
| 76 | |||
| 77 | IR::U32 TranslatorVisitor::GetCbuf(u64 insn) { | ||
| 78 | const auto[binding, byte_offset]{CbufAddr(insn)}; | ||
| 73 | return ir.GetCbuf(binding, byte_offset); | 79 | return ir.GetCbuf(binding, byte_offset); |
| 74 | } | 80 | } |
| 75 | 81 | ||
| 76 | IR::F32 TranslatorVisitor::GetFloatCbuf(u64 insn) { | 82 | IR::F32 TranslatorVisitor::GetFloatCbuf(u64 insn) { |
| 77 | return ir.BitCast<IR::F32>(GetCbuf(insn)); | 83 | const auto[binding, byte_offset]{CbufAddr(insn)}; |
| 84 | return ir.GetFloatCbuf(binding, byte_offset); | ||
| 78 | } | 85 | } |
| 79 | 86 | ||
| 80 | IR::U32 TranslatorVisitor::GetImm20(u64 insn) { | 87 | IR::U32 TranslatorVisitor::GetImm20(u64 insn) { |
| @@ -83,6 +90,7 @@ IR::U32 TranslatorVisitor::GetImm20(u64 insn) { | |||
| 83 | BitField<20, 19, u64> value; | 90 | BitField<20, 19, u64> value; |
| 84 | BitField<56, 1, u64> is_negative; | 91 | BitField<56, 1, u64> is_negative; |
| 85 | } const imm{insn}; | 92 | } const imm{insn}; |
| 93 | |||
| 86 | if (imm.is_negative != 0) { | 94 | if (imm.is_negative != 0) { |
| 87 | const s64 raw{static_cast<s64>(imm.value)}; | 95 | const s64 raw{static_cast<s64>(imm.value)}; |
| 88 | return ir.Imm32(static_cast<s32>(-(1LL << 19) + raw)); | 96 | return ir.Imm32(static_cast<s32>(-(1LL << 19) + raw)); |
diff --git a/src/shader_recompiler/frontend/maxwell/translate/impl/load_constant.cpp b/src/shader_recompiler/frontend/maxwell/translate/impl/load_constant.cpp new file mode 100644 index 000000000..39becf93c --- /dev/null +++ b/src/shader_recompiler/frontend/maxwell/translate/impl/load_constant.cpp | |||
| @@ -0,0 +1,85 @@ | |||
| 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 Mode : u64 { | ||
| 12 | Default, | ||
| 13 | IL, | ||
| 14 | IS, | ||
| 15 | ISL, | ||
| 16 | }; | ||
| 17 | |||
| 18 | enum class Size : u64 { | ||
| 19 | U8, | ||
| 20 | S8, | ||
| 21 | U16, | ||
| 22 | S16, | ||
| 23 | B32, | ||
| 24 | B64, | ||
| 25 | }; | ||
| 26 | |||
| 27 | std::pair<IR::U32, IR::U32> Slot(IR::IREmitter& ir, Mode mode, const IR::U32& imm_index, | ||
| 28 | const IR::U32& reg, const IR::U32& imm) { | ||
| 29 | switch (mode) { | ||
| 30 | case Mode::Default: | ||
| 31 | return {imm_index, ir.IAdd(reg, imm)}; | ||
| 32 | default: | ||
| 33 | break; | ||
| 34 | } | ||
| 35 | throw NotImplementedException("Mode {}", mode); | ||
| 36 | } | ||
| 37 | } // Anonymous namespace | ||
| 38 | |||
| 39 | void TranslatorVisitor::LDC(u64 insn) { | ||
| 40 | union { | ||
| 41 | u64 raw; | ||
| 42 | BitField<0, 8, IR::Reg> dest_reg; | ||
| 43 | BitField<8, 8, IR::Reg> src_reg; | ||
| 44 | BitField<20, 16, s64> offset; | ||
| 45 | BitField<36, 5, u64> index; | ||
| 46 | BitField<44, 2, Mode> mode; | ||
| 47 | BitField<48, 3, Size> size; | ||
| 48 | } const ldc{insn}; | ||
| 49 | |||
| 50 | const IR::U32 imm_index{ir.Imm32(static_cast<u32>(ldc.index))}; | ||
| 51 | const IR::U32 reg{X(ldc.src_reg)}; | ||
| 52 | const IR::U32 imm{ir.Imm32(static_cast<s32>(ldc.offset))}; | ||
| 53 | const auto [index, offset]{Slot(ir, ldc.mode, imm_index, reg, imm)}; | ||
| 54 | switch (ldc.size) { | ||
| 55 | case Size::U8: | ||
| 56 | X(ldc.dest_reg, ir.GetCbuf(index, offset, 8, false)); | ||
| 57 | break; | ||
| 58 | case Size::S8: | ||
| 59 | X(ldc.dest_reg, ir.GetCbuf(index, offset, 8, true)); | ||
| 60 | break; | ||
| 61 | case Size::U16: | ||
| 62 | X(ldc.dest_reg, ir.GetCbuf(index, offset, 16, false)); | ||
| 63 | break; | ||
| 64 | case Size::S16: | ||
| 65 | X(ldc.dest_reg, ir.GetCbuf(index, offset, 16, true)); | ||
| 66 | break; | ||
| 67 | case Size::B32: | ||
| 68 | X(ldc.dest_reg, ir.GetCbuf(index, offset, 32, false)); | ||
| 69 | break; | ||
| 70 | case Size::B64: { | ||
| 71 | if (!IR::IsAligned(ldc.dest_reg, 2)) { | ||
| 72 | throw NotImplementedException("Unaligned destination register"); | ||
| 73 | } | ||
| 74 | const IR::Value vector{ir.UnpackUint2x32(ir.GetCbuf(index, offset, 64, false))}; | ||
| 75 | for (int i = 0; i < 2; ++i) { | ||
| 76 | X(ldc.dest_reg + i, IR::U32{ir.CompositeExtract(vector, i)}); | ||
| 77 | } | ||
| 78 | break; | ||
| 79 | } | ||
| 80 | default: | ||
| 81 | throw NotImplementedException("Invalid size {}", ldc.size.Value()); | ||
| 82 | } | ||
| 83 | } | ||
| 84 | |||
| 85 | } // 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 ff429c126..5b153acff 100644 --- a/src/shader_recompiler/frontend/maxwell/translate/impl/not_implemented.cpp +++ b/src/shader_recompiler/frontend/maxwell/translate/impl/not_implemented.cpp | |||
| @@ -425,10 +425,6 @@ void TranslatorVisitor::LD(u64) { | |||
| 425 | ThrowNotImplemented(Opcode::LD); | 425 | ThrowNotImplemented(Opcode::LD); |
| 426 | } | 426 | } |
| 427 | 427 | ||
| 428 | void TranslatorVisitor::LDC(u64) { | ||
| 429 | ThrowNotImplemented(Opcode::LDC); | ||
| 430 | } | ||
| 431 | |||
| 432 | void TranslatorVisitor::LDL(u64) { | 428 | void TranslatorVisitor::LDL(u64) { |
| 433 | ThrowNotImplemented(Opcode::LDL); | 429 | ThrowNotImplemented(Opcode::LDL); |
| 434 | } | 430 | } |