summaryrefslogtreecommitdiff
path: root/src/shader_recompiler/backend/glsl/emit_glsl_integer.cpp
diff options
context:
space:
mode:
authorGravatar bunnei2021-07-25 11:39:04 -0700
committerGravatar GitHub2021-07-25 11:39:04 -0700
commit98b26b6e126d4775fdf3f773fe8a8ac808a8ff8f (patch)
tree816faa96c2c4d291825063433331a8ea4b3d08f1 /src/shader_recompiler/backend/glsl/emit_glsl_integer.cpp
parentMerge pull request #6699 from lat9nq/common-threads (diff)
parentshader: Support out of bound local memory reads and immediate writes (diff)
downloadyuzu-98b26b6e126d4775fdf3f773fe8a8ac808a8ff8f.tar.gz
yuzu-98b26b6e126d4775fdf3f773fe8a8ac808a8ff8f.tar.xz
yuzu-98b26b6e126d4775fdf3f773fe8a8ac808a8ff8f.zip
Merge pull request #6585 from ameerj/hades
Shader Decompiler Rewrite
Diffstat (limited to 'src/shader_recompiler/backend/glsl/emit_glsl_integer.cpp')
-rw-r--r--src/shader_recompiler/backend/glsl/emit_glsl_integer.cpp253
1 files changed, 253 insertions, 0 deletions
diff --git a/src/shader_recompiler/backend/glsl/emit_glsl_integer.cpp b/src/shader_recompiler/backend/glsl/emit_glsl_integer.cpp
new file mode 100644
index 000000000..38419f88f
--- /dev/null
+++ b/src/shader_recompiler/backend/glsl/emit_glsl_integer.cpp
@@ -0,0 +1,253 @@
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 <string_view>
6
7#include "shader_recompiler/backend/glsl/emit_context.h"
8#include "shader_recompiler/backend/glsl/emit_glsl_instructions.h"
9#include "shader_recompiler/frontend/ir/value.h"
10
11namespace Shader::Backend::GLSL {
12namespace {
13void SetZeroFlag(EmitContext& ctx, IR::Inst& inst, std::string_view result) {
14 IR::Inst* const zero{inst.GetAssociatedPseudoOperation(IR::Opcode::GetZeroFromOp)};
15 if (!zero) {
16 return;
17 }
18 ctx.AddU1("{}={}==0;", *zero, result);
19 zero->Invalidate();
20}
21
22void SetSignFlag(EmitContext& ctx, IR::Inst& inst, std::string_view result) {
23 IR::Inst* const sign{inst.GetAssociatedPseudoOperation(IR::Opcode::GetSignFromOp)};
24 if (!sign) {
25 return;
26 }
27 ctx.AddU1("{}=int({})<0;", *sign, result);
28 sign->Invalidate();
29}
30
31void BitwiseLogicalOp(EmitContext& ctx, IR::Inst& inst, std::string_view a, std::string_view b,
32 char lop) {
33 const auto result{ctx.var_alloc.Define(inst, GlslVarType::U32)};
34 ctx.Add("{}={}{}{};", result, a, lop, b);
35 SetZeroFlag(ctx, inst, result);
36 SetSignFlag(ctx, inst, result);
37}
38} // Anonymous namespace
39
40void EmitIAdd32(EmitContext& ctx, IR::Inst& inst, std::string_view a, std::string_view b) {
41 // Compute the overflow CC first as it requires the original operand values,
42 // which may be overwritten by the result of the addition
43 if (IR::Inst * overflow{inst.GetAssociatedPseudoOperation(IR::Opcode::GetOverflowFromOp)}) {
44 // https://stackoverflow.com/questions/55468823/how-to-detect-integer-overflow-in-c
45 constexpr u32 s32_max{static_cast<u32>(std::numeric_limits<s32>::max())};
46 const auto sub_a{fmt::format("{}u-{}", s32_max, a)};
47 const auto positive_result{fmt::format("int({})>int({})", b, sub_a)};
48 const auto negative_result{fmt::format("int({})<int({})", b, sub_a)};
49 ctx.AddU1("{}=int({})>=0?{}:{};", *overflow, a, positive_result, negative_result);
50 overflow->Invalidate();
51 }
52 const auto result{ctx.var_alloc.Define(inst, GlslVarType::U32)};
53 if (IR::Inst* const carry{inst.GetAssociatedPseudoOperation(IR::Opcode::GetCarryFromOp)}) {
54 ctx.uses_cc_carry = true;
55 ctx.Add("{}=uaddCarry({},{},carry);", result, a, b);
56 ctx.AddU1("{}=carry!=0;", *carry);
57 carry->Invalidate();
58 } else {
59 ctx.Add("{}={}+{};", result, a, b);
60 }
61 SetZeroFlag(ctx, inst, result);
62 SetSignFlag(ctx, inst, result);
63}
64
65void EmitIAdd64(EmitContext& ctx, IR::Inst& inst, std::string_view a, std::string_view b) {
66 ctx.AddU64("{}={}+{};", inst, a, b);
67}
68
69void EmitISub32(EmitContext& ctx, IR::Inst& inst, std::string_view a, std::string_view b) {
70 ctx.AddU32("{}={}-{};", inst, a, b);
71}
72
73void EmitISub64(EmitContext& ctx, IR::Inst& inst, std::string_view a, std::string_view b) {
74 ctx.AddU64("{}={}-{};", inst, a, b);
75}
76
77void EmitIMul32(EmitContext& ctx, IR::Inst& inst, std::string_view a, std::string_view b) {
78 ctx.AddU32("{}=uint({}*{});", inst, a, b);
79}
80
81void EmitINeg32(EmitContext& ctx, IR::Inst& inst, std::string_view value) {
82 ctx.AddU32("{}=uint(-({}));", inst, value);
83}
84
85void EmitINeg64(EmitContext& ctx, IR::Inst& inst, std::string_view value) {
86 ctx.AddU64("{}=-({});", inst, value);
87}
88
89void EmitIAbs32(EmitContext& ctx, IR::Inst& inst, std::string_view value) {
90 ctx.AddU32("{}=abs(int({}));", inst, value);
91}
92
93void EmitShiftLeftLogical32(EmitContext& ctx, IR::Inst& inst, std::string_view base,
94 std::string_view shift) {
95 ctx.AddU32("{}={}<<{};", inst, base, shift);
96}
97
98void EmitShiftLeftLogical64(EmitContext& ctx, IR::Inst& inst, std::string_view base,
99 std::string_view shift) {
100 ctx.AddU64("{}={}<<{};", inst, base, shift);
101}
102
103void EmitShiftRightLogical32(EmitContext& ctx, IR::Inst& inst, std::string_view base,
104 std::string_view shift) {
105 ctx.AddU32("{}={}>>{};", inst, base, shift);
106}
107
108void EmitShiftRightLogical64(EmitContext& ctx, IR::Inst& inst, std::string_view base,
109 std::string_view shift) {
110 ctx.AddU64("{}={}>>{};", inst, base, shift);
111}
112
113void EmitShiftRightArithmetic32(EmitContext& ctx, IR::Inst& inst, std::string_view base,
114 std::string_view shift) {
115 ctx.AddU32("{}=int({})>>{};", inst, base, shift);
116}
117
118void EmitShiftRightArithmetic64(EmitContext& ctx, IR::Inst& inst, std::string_view base,
119 std::string_view shift) {
120 ctx.AddU64("{}=int64_t({})>>{};", inst, base, shift);
121}
122
123void EmitBitwiseAnd32(EmitContext& ctx, IR::Inst& inst, std::string_view a, std::string_view b) {
124 BitwiseLogicalOp(ctx, inst, a, b, '&');
125}
126
127void EmitBitwiseOr32(EmitContext& ctx, IR::Inst& inst, std::string_view a, std::string_view b) {
128 BitwiseLogicalOp(ctx, inst, a, b, '|');
129}
130
131void EmitBitwiseXor32(EmitContext& ctx, IR::Inst& inst, std::string_view a, std::string_view b) {
132 BitwiseLogicalOp(ctx, inst, a, b, '^');
133}
134
135void EmitBitFieldInsert(EmitContext& ctx, IR::Inst& inst, std::string_view base,
136 std::string_view insert, std::string_view offset, std::string_view count) {
137 ctx.AddU32("{}=bitfieldInsert({},{},int({}),int({}));", inst, base, insert, offset, count);
138}
139
140void EmitBitFieldSExtract(EmitContext& ctx, IR::Inst& inst, std::string_view base,
141 std::string_view offset, std::string_view count) {
142 const auto result{ctx.var_alloc.Define(inst, GlslVarType::U32)};
143 ctx.Add("{}=uint(bitfieldExtract(int({}),int({}),int({})));", result, base, offset, count);
144 SetZeroFlag(ctx, inst, result);
145 SetSignFlag(ctx, inst, result);
146}
147
148void EmitBitFieldUExtract(EmitContext& ctx, IR::Inst& inst, std::string_view base,
149 std::string_view offset, std::string_view count) {
150 const auto result{ctx.var_alloc.Define(inst, GlslVarType::U32)};
151 ctx.Add("{}=uint(bitfieldExtract(uint({}),int({}),int({})));", result, base, offset, count);
152 SetZeroFlag(ctx, inst, result);
153 SetSignFlag(ctx, inst, result);
154}
155
156void EmitBitReverse32(EmitContext& ctx, IR::Inst& inst, std::string_view value) {
157 ctx.AddU32("{}=bitfieldReverse({});", inst, value);
158}
159
160void EmitBitCount32(EmitContext& ctx, IR::Inst& inst, std::string_view value) {
161 ctx.AddU32("{}=bitCount({});", inst, value);
162}
163
164void EmitBitwiseNot32(EmitContext& ctx, IR::Inst& inst, std::string_view value) {
165 ctx.AddU32("{}=~{};", inst, value);
166}
167
168void EmitFindSMsb32(EmitContext& ctx, IR::Inst& inst, std::string_view value) {
169 ctx.AddU32("{}=findMSB(int({}));", inst, value);
170}
171
172void EmitFindUMsb32(EmitContext& ctx, IR::Inst& inst, std::string_view value) {
173 ctx.AddU32("{}=findMSB(uint({}));", inst, value);
174}
175
176void EmitSMin32(EmitContext& ctx, IR::Inst& inst, std::string_view a, std::string_view b) {
177 ctx.AddU32("{}=min(int({}),int({}));", inst, a, b);
178}
179
180void EmitUMin32(EmitContext& ctx, IR::Inst& inst, std::string_view a, std::string_view b) {
181 ctx.AddU32("{}=min(uint({}),uint({}));", inst, a, b);
182}
183
184void EmitSMax32(EmitContext& ctx, IR::Inst& inst, std::string_view a, std::string_view b) {
185 ctx.AddU32("{}=max(int({}),int({}));", inst, a, b);
186}
187
188void EmitUMax32(EmitContext& ctx, IR::Inst& inst, std::string_view a, std::string_view b) {
189 ctx.AddU32("{}=max(uint({}),uint({}));", inst, a, b);
190}
191
192void EmitSClamp32(EmitContext& ctx, IR::Inst& inst, std::string_view value, std::string_view min,
193 std::string_view max) {
194 const auto result{ctx.var_alloc.Define(inst, GlslVarType::U32)};
195 ctx.Add("{}=clamp(int({}),int({}),int({}));", result, value, min, max);
196 SetZeroFlag(ctx, inst, result);
197 SetSignFlag(ctx, inst, result);
198}
199
200void EmitUClamp32(EmitContext& ctx, IR::Inst& inst, std::string_view value, std::string_view min,
201 std::string_view max) {
202 const auto result{ctx.var_alloc.Define(inst, GlslVarType::U32)};
203 ctx.Add("{}=clamp(uint({}),uint({}),uint({}));", result, value, min, max);
204 SetZeroFlag(ctx, inst, result);
205 SetSignFlag(ctx, inst, result);
206}
207
208void EmitSLessThan(EmitContext& ctx, IR::Inst& inst, std::string_view lhs, std::string_view rhs) {
209 ctx.AddU1("{}=int({})<int({});", inst, lhs, rhs);
210}
211
212void EmitULessThan(EmitContext& ctx, IR::Inst& inst, std::string_view lhs, std::string_view rhs) {
213 ctx.AddU1("{}=uint({})<uint({});", inst, lhs, rhs);
214}
215
216void EmitIEqual(EmitContext& ctx, IR::Inst& inst, std::string_view lhs, std::string_view rhs) {
217 ctx.AddU1("{}={}=={};", inst, lhs, rhs);
218}
219
220void EmitSLessThanEqual(EmitContext& ctx, IR::Inst& inst, std::string_view lhs,
221 std::string_view rhs) {
222 ctx.AddU1("{}=int({})<=int({});", inst, lhs, rhs);
223}
224
225void EmitULessThanEqual(EmitContext& ctx, IR::Inst& inst, std::string_view lhs,
226 std::string_view rhs) {
227 ctx.AddU1("{}=uint({})<=uint({});", inst, lhs, rhs);
228}
229
230void EmitSGreaterThan(EmitContext& ctx, IR::Inst& inst, std::string_view lhs,
231 std::string_view rhs) {
232 ctx.AddU1("{}=int({})>int({});", inst, lhs, rhs);
233}
234
235void EmitUGreaterThan(EmitContext& ctx, IR::Inst& inst, std::string_view lhs,
236 std::string_view rhs) {
237 ctx.AddU1("{}=uint({})>uint({});", inst, lhs, rhs);
238}
239
240void EmitINotEqual(EmitContext& ctx, IR::Inst& inst, std::string_view lhs, std::string_view rhs) {
241 ctx.AddU1("{}={}!={};", inst, lhs, rhs);
242}
243
244void EmitSGreaterThanEqual(EmitContext& ctx, IR::Inst& inst, std::string_view lhs,
245 std::string_view rhs) {
246 ctx.AddU1("{}=int({})>=int({});", inst, lhs, rhs);
247}
248
249void EmitUGreaterThanEqual(EmitContext& ctx, IR::Inst& inst, std::string_view lhs,
250 std::string_view rhs) {
251 ctx.AddU1("{}=uint({})>=uint({});", inst, lhs, rhs);
252}
253} // namespace Shader::Backend::GLSL