summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--src/shader_recompiler/frontend/maxwell/translate/impl/load_store_local_shared.cpp25
1 files changed, 21 insertions, 4 deletions
diff --git a/src/shader_recompiler/frontend/maxwell/translate/impl/load_store_local_shared.cpp b/src/shader_recompiler/frontend/maxwell/translate/impl/load_store_local_shared.cpp
index 20df163f2..d2a1dbf61 100644
--- a/src/shader_recompiler/frontend/maxwell/translate/impl/load_store_local_shared.cpp
+++ b/src/shader_recompiler/frontend/maxwell/translate/impl/load_store_local_shared.cpp
@@ -85,21 +85,28 @@ IR::U32 ByteOffset(IR::IREmitter& ir, const IR::U32& offset) {
85IR::U32 ShortOffset(IR::IREmitter& ir, const IR::U32& offset) { 85IR::U32 ShortOffset(IR::IREmitter& ir, const IR::U32& offset) {
86 return ir.BitwiseAnd(ir.ShiftLeftLogical(offset, ir.Imm32(3)), ir.Imm32(16)); 86 return ir.BitwiseAnd(ir.ShiftLeftLogical(offset, ir.Imm32(3)), ir.Imm32(16));
87} 87}
88
89IR::U32 LoadLocal(TranslatorVisitor& v, const IR::U32& word_offset, const IR::U32& offset) {
90 const IR::U32 local_memory_size{v.ir.Imm32(v.env.LocalMemorySize())};
91 const IR::U1 in_bounds{v.ir.ILessThan(offset, local_memory_size, false)};
92 return IR::U32{v.ir.Select(in_bounds, v.ir.LoadLocal(word_offset), v.ir.Imm32(0))};
93}
88} // Anonymous namespace 94} // Anonymous namespace
89 95
90void TranslatorVisitor::LDL(u64 insn) { 96void TranslatorVisitor::LDL(u64 insn) {
91 const auto [word_offset, offset]{WordOffset(*this, insn)}; 97 const auto [word_offset, offset]{WordOffset(*this, insn)};
98 const IR::U32 word{LoadLocal(*this, word_offset, offset)};
92 const IR::Reg dest{Reg(insn)}; 99 const IR::Reg dest{Reg(insn)};
93 const auto [bit_size, is_signed]{GetSize(insn)}; 100 const auto [bit_size, is_signed]{GetSize(insn)};
94 switch (bit_size) { 101 switch (bit_size) {
95 case 8: { 102 case 8: {
96 const IR::U32 bit{ByteOffset(ir, offset)}; 103 const IR::U32 bit{ByteOffset(ir, offset)};
97 X(dest, ir.BitFieldExtract(ir.LoadLocal(word_offset), bit, ir.Imm32(8), is_signed)); 104 X(dest, ir.BitFieldExtract(word, bit, ir.Imm32(8), is_signed));
98 break; 105 break;
99 } 106 }
100 case 16: { 107 case 16: {
101 const IR::U32 bit{ShortOffset(ir, offset)}; 108 const IR::U32 bit{ShortOffset(ir, offset)};
102 X(dest, ir.BitFieldExtract(ir.LoadLocal(word_offset), bit, ir.Imm32(16), is_signed)); 109 X(dest, ir.BitFieldExtract(word, bit, ir.Imm32(16), is_signed));
103 break; 110 break;
104 } 111 }
105 case 32: 112 case 32:
@@ -108,9 +115,11 @@ void TranslatorVisitor::LDL(u64 insn) {
108 if (!IR::IsAligned(dest, static_cast<size_t>(bit_size / 32))) { 115 if (!IR::IsAligned(dest, static_cast<size_t>(bit_size / 32))) {
109 throw NotImplementedException("Unaligned destination register {}", dest); 116 throw NotImplementedException("Unaligned destination register {}", dest);
110 } 117 }
111 X(dest, ir.LoadLocal(word_offset)); 118 X(dest, word);
112 for (int i = 1; i < bit_size / 32; ++i) { 119 for (int i = 1; i < bit_size / 32; ++i) {
113 X(dest + i, ir.LoadLocal(ir.IAdd(word_offset, ir.Imm32(i)))); 120 const IR::U32 sub_word_offset{ir.IAdd(word_offset, ir.Imm32(i))};
121 const IR::U32 sub_offset{ir.IAdd(offset, ir.Imm32(i * 4))};
122 X(dest + i, LoadLocal(*this, sub_word_offset, sub_offset));
114 } 123 }
115 break; 124 break;
116 } 125 }
@@ -141,6 +150,14 @@ void TranslatorVisitor::LDS(u64 insn) {
141 150
142void TranslatorVisitor::STL(u64 insn) { 151void TranslatorVisitor::STL(u64 insn) {
143 const auto [word_offset, offset]{WordOffset(*this, insn)}; 152 const auto [word_offset, offset]{WordOffset(*this, insn)};
153 if (offset.IsImmediate()) {
154 // TODO: Support storing out of bounds at runtime
155 if (offset.U32() >= env.LocalMemorySize()) {
156 LOG_WARNING(Shader, "Storing local memory at 0x{:x} with a size of 0x{:x}, dropping",
157 offset.U32(), env.LocalMemorySize());
158 return;
159 }
160 }
144 const IR::Reg reg{Reg(insn)}; 161 const IR::Reg reg{Reg(insn)};
145 const IR::U32 src{X(reg)}; 162 const IR::U32 src{X(reg)};
146 const int bit_size{GetSize(insn).first}; 163 const int bit_size{GetSize(insn).first};