summaryrefslogtreecommitdiff
path: root/src/shader_recompiler
diff options
context:
space:
mode:
Diffstat (limited to 'src/shader_recompiler')
-rw-r--r--src/shader_recompiler/CMakeLists.txt3
-rw-r--r--src/shader_recompiler/backend/spirv/emit_spirv.h40
-rw-r--r--src/shader_recompiler/backend/spirv/emit_spirv_floating_point.cpp58
-rw-r--r--src/shader_recompiler/backend/spirv/emit_spirv_integer.cpp75
-rw-r--r--src/shader_recompiler/backend/spirv/emit_spirv_select.cpp4
-rw-r--r--src/shader_recompiler/frontend/ir/ir_emitter.cpp16
-rw-r--r--src/shader_recompiler/frontend/ir/pred.h4
-rw-r--r--src/shader_recompiler/frontend/maxwell/program.cpp2
-rw-r--r--src/shader_recompiler/frontend/maxwell/translate/impl/floating_point_add.cpp20
-rw-r--r--src/shader_recompiler/frontend/maxwell/translate/impl/floating_point_conversion_integer.cpp2
-rw-r--r--src/shader_recompiler/frontend/maxwell/translate/impl/floating_point_fused_multiply_add.cpp4
-rw-r--r--src/shader_recompiler/frontend/maxwell/translate/impl/floating_point_multiply.cpp2
-rw-r--r--src/shader_recompiler/frontend/maxwell/translate/impl/impl.cpp17
-rw-r--r--src/shader_recompiler/frontend/maxwell/translate/impl/impl.h7
-rw-r--r--src/shader_recompiler/frontend/maxwell/translate/impl/integer_add.cpp4
-rw-r--r--src/shader_recompiler/frontend/maxwell/translate/impl/move_predicate_to_register.cpp66
-rw-r--r--src/shader_recompiler/frontend/maxwell/translate/impl/not_implemented.cpp12
17 files changed, 211 insertions, 125 deletions
diff --git a/src/shader_recompiler/CMakeLists.txt b/src/shader_recompiler/CMakeLists.txt
index fbd4ec6dc..802527255 100644
--- a/src/shader_recompiler/CMakeLists.txt
+++ b/src/shader_recompiler/CMakeLists.txt
@@ -74,9 +74,10 @@ add_library(shader_recompiler STATIC
74 frontend/maxwell/translate/impl/integer_short_multiply_add.cpp 74 frontend/maxwell/translate/impl/integer_short_multiply_add.cpp
75 frontend/maxwell/translate/impl/load_store_attribute.cpp 75 frontend/maxwell/translate/impl/load_store_attribute.cpp
76 frontend/maxwell/translate/impl/load_store_memory.cpp 76 frontend/maxwell/translate/impl/load_store_memory.cpp
77 frontend/maxwell/translate/impl/not_implemented.cpp 77 frontend/maxwell/translate/impl/move_predicate_to_register.cpp
78 frontend/maxwell/translate/impl/move_register.cpp 78 frontend/maxwell/translate/impl/move_register.cpp
79 frontend/maxwell/translate/impl/move_special_register.cpp 79 frontend/maxwell/translate/impl/move_special_register.cpp
80 frontend/maxwell/translate/impl/not_implemented.cpp
80 frontend/maxwell/translate/translate.cpp 81 frontend/maxwell/translate/translate.cpp
81 frontend/maxwell/translate/translate.h 82 frontend/maxwell/translate/translate.h
82 ir_opt/collect_shader_info_pass.cpp 83 ir_opt/collect_shader_info_pass.cpp
diff --git a/src/shader_recompiler/backend/spirv/emit_spirv.h b/src/shader_recompiler/backend/spirv/emit_spirv.h
index de624a151..922e294a7 100644
--- a/src/shader_recompiler/backend/spirv/emit_spirv.h
+++ b/src/shader_recompiler/backend/spirv/emit_spirv.h
@@ -110,7 +110,7 @@ void EmitCompositeExtractF64x3(EmitContext& ctx);
110void EmitCompositeExtractF64x4(EmitContext& ctx); 110void EmitCompositeExtractF64x4(EmitContext& ctx);
111void EmitSelect8(EmitContext& ctx); 111void EmitSelect8(EmitContext& ctx);
112void EmitSelect16(EmitContext& ctx); 112void EmitSelect16(EmitContext& ctx);
113void EmitSelect32(EmitContext& ctx); 113Id EmitSelect32(EmitContext& ctx, Id cond, Id true_value, Id false_value);
114void EmitSelect64(EmitContext& ctx); 114void EmitSelect64(EmitContext& ctx);
115void EmitBitCastU16F16(EmitContext& ctx); 115void EmitBitCastU16F16(EmitContext& ctx);
116Id EmitBitCastU32F32(EmitContext& ctx, Id value); 116Id EmitBitCastU32F32(EmitContext& ctx, Id value);
@@ -130,9 +130,9 @@ void EmitGetZeroFromOp(EmitContext& ctx);
130void EmitGetSignFromOp(EmitContext& ctx); 130void EmitGetSignFromOp(EmitContext& ctx);
131void EmitGetCarryFromOp(EmitContext& ctx); 131void EmitGetCarryFromOp(EmitContext& ctx);
132void EmitGetOverflowFromOp(EmitContext& ctx); 132void EmitGetOverflowFromOp(EmitContext& ctx);
133void EmitFPAbs16(EmitContext& ctx); 133Id EmitFPAbs16(EmitContext& ctx, Id value);
134void EmitFPAbs32(EmitContext& ctx); 134Id EmitFPAbs32(EmitContext& ctx, Id value);
135void EmitFPAbs64(EmitContext& ctx); 135Id EmitFPAbs64(EmitContext& ctx, Id value);
136Id EmitFPAdd16(EmitContext& ctx, IR::Inst* inst, Id a, Id b); 136Id EmitFPAdd16(EmitContext& ctx, IR::Inst* inst, Id a, Id b);
137Id EmitFPAdd32(EmitContext& ctx, IR::Inst* inst, Id a, Id b); 137Id EmitFPAdd32(EmitContext& ctx, IR::Inst* inst, Id a, Id b);
138Id EmitFPAdd64(EmitContext& ctx, IR::Inst* inst, Id a, Id b); 138Id EmitFPAdd64(EmitContext& ctx, IR::Inst* inst, Id a, Id b);
@@ -146,9 +146,9 @@ void EmitFPMin64(EmitContext& ctx);
146Id EmitFPMul16(EmitContext& ctx, IR::Inst* inst, Id a, Id b); 146Id EmitFPMul16(EmitContext& ctx, IR::Inst* inst, Id a, Id b);
147Id EmitFPMul32(EmitContext& ctx, IR::Inst* inst, Id a, Id b); 147Id EmitFPMul32(EmitContext& ctx, IR::Inst* inst, Id a, Id b);
148Id EmitFPMul64(EmitContext& ctx, IR::Inst* inst, Id a, Id b); 148Id EmitFPMul64(EmitContext& ctx, IR::Inst* inst, Id a, Id b);
149void EmitFPNeg16(EmitContext& ctx); 149Id EmitFPNeg16(EmitContext& ctx, Id value);
150void EmitFPNeg32(EmitContext& ctx); 150Id EmitFPNeg32(EmitContext& ctx, Id value);
151void EmitFPNeg64(EmitContext& ctx); 151Id EmitFPNeg64(EmitContext& ctx, Id value);
152void EmitFPRecip32(EmitContext& ctx); 152void EmitFPRecip32(EmitContext& ctx);
153void EmitFPRecip64(EmitContext& ctx); 153void EmitFPRecip64(EmitContext& ctx);
154void EmitFPRecipSqrt32(EmitContext& ctx); 154void EmitFPRecipSqrt32(EmitContext& ctx);
@@ -161,9 +161,9 @@ void EmitFPExp2NotReduced(EmitContext& ctx);
161void EmitFPCos(EmitContext& ctx); 161void EmitFPCos(EmitContext& ctx);
162void EmitFPCosNotReduced(EmitContext& ctx); 162void EmitFPCosNotReduced(EmitContext& ctx);
163void EmitFPLog2(EmitContext& ctx); 163void EmitFPLog2(EmitContext& ctx);
164void EmitFPSaturate16(EmitContext& ctx); 164Id EmitFPSaturate16(EmitContext& ctx, Id value);
165void EmitFPSaturate32(EmitContext& ctx); 165Id EmitFPSaturate32(EmitContext& ctx, Id value);
166void EmitFPSaturate64(EmitContext& ctx); 166Id EmitFPSaturate64(EmitContext& ctx, Id value);
167Id EmitFPRoundEven16(EmitContext& ctx, Id value); 167Id EmitFPRoundEven16(EmitContext& ctx, Id value);
168Id EmitFPRoundEven32(EmitContext& ctx, Id value); 168Id EmitFPRoundEven32(EmitContext& ctx, Id value);
169Id EmitFPRoundEven64(EmitContext& ctx, Id value); 169Id EmitFPRoundEven64(EmitContext& ctx, Id value);
@@ -186,21 +186,21 @@ void EmitIAbs32(EmitContext& ctx);
186Id EmitShiftLeftLogical32(EmitContext& ctx, Id base, Id shift); 186Id EmitShiftLeftLogical32(EmitContext& ctx, Id base, Id shift);
187void EmitShiftRightLogical32(EmitContext& ctx); 187void EmitShiftRightLogical32(EmitContext& ctx);
188void EmitShiftRightArithmetic32(EmitContext& ctx); 188void EmitShiftRightArithmetic32(EmitContext& ctx);
189void EmitBitwiseAnd32(EmitContext& ctx); 189Id EmitBitwiseAnd32(EmitContext& ctx, Id a, Id b);
190void EmitBitwiseOr32(EmitContext& ctx); 190Id EmitBitwiseOr32(EmitContext& ctx, Id a, Id b);
191void EmitBitwiseXor32(EmitContext& ctx); 191Id EmitBitwiseXor32(EmitContext& ctx, Id a, Id b);
192void EmitBitFieldInsert(EmitContext& ctx); 192void EmitBitFieldInsert(EmitContext& ctx);
193void EmitBitFieldSExtract(EmitContext& ctx); 193void EmitBitFieldSExtract(EmitContext& ctx);
194Id EmitBitFieldUExtract(EmitContext& ctx, Id base, Id offset, Id count); 194Id EmitBitFieldUExtract(EmitContext& ctx, Id base, Id offset, Id count);
195Id EmitSLessThan(EmitContext& ctx, Id lhs, Id rhs); 195Id EmitSLessThan(EmitContext& ctx, Id lhs, Id rhs);
196void EmitULessThan(EmitContext& ctx); 196Id EmitULessThan(EmitContext& ctx, Id lhs, Id rhs);
197void EmitIEqual(EmitContext& ctx); 197Id EmitIEqual(EmitContext& ctx, Id lhs, Id rhs);
198void EmitSLessThanEqual(EmitContext& ctx); 198Id EmitSLessThanEqual(EmitContext& ctx, Id lhs, Id rhs);
199void EmitULessThanEqual(EmitContext& ctx); 199Id EmitULessThanEqual(EmitContext& ctx, Id lhs, Id rhs);
200Id EmitSGreaterThan(EmitContext& ctx, Id lhs, Id rhs); 200Id EmitSGreaterThan(EmitContext& ctx, Id lhs, Id rhs);
201void EmitUGreaterThan(EmitContext& ctx); 201Id EmitUGreaterThan(EmitContext& ctx, Id lhs, Id rhs);
202void EmitINotEqual(EmitContext& ctx); 202Id EmitINotEqual(EmitContext& ctx, Id lhs, Id rhs);
203void EmitSGreaterThanEqual(EmitContext& ctx); 203Id EmitSGreaterThanEqual(EmitContext& ctx, Id lhs, Id rhs);
204Id EmitUGreaterThanEqual(EmitContext& ctx, Id lhs, Id rhs); 204Id EmitUGreaterThanEqual(EmitContext& ctx, Id lhs, Id rhs);
205void EmitLogicalOr(EmitContext& ctx); 205void EmitLogicalOr(EmitContext& ctx);
206void EmitLogicalAnd(EmitContext& ctx); 206void EmitLogicalAnd(EmitContext& ctx);
diff --git a/src/shader_recompiler/backend/spirv/emit_spirv_floating_point.cpp b/src/shader_recompiler/backend/spirv/emit_spirv_floating_point.cpp
index c9687de37..47f87054b 100644
--- a/src/shader_recompiler/backend/spirv/emit_spirv_floating_point.cpp
+++ b/src/shader_recompiler/backend/spirv/emit_spirv_floating_point.cpp
@@ -12,37 +12,21 @@ Id Decorate(EmitContext& ctx, IR::Inst* inst, Id op) {
12 if (flags.no_contraction) { 12 if (flags.no_contraction) {
13 ctx.Decorate(op, spv::Decoration::NoContraction); 13 ctx.Decorate(op, spv::Decoration::NoContraction);
14 } 14 }
15 switch (flags.rounding) {
16 case IR::FpRounding::DontCare:
17 break;
18 case IR::FpRounding::RN:
19 ctx.Decorate(op, spv::Decoration::FPRoundingMode, spv::FPRoundingMode::RTE);
20 break;
21 case IR::FpRounding::RM:
22 ctx.Decorate(op, spv::Decoration::FPRoundingMode, spv::FPRoundingMode::RTN);
23 break;
24 case IR::FpRounding::RP:
25 ctx.Decorate(op, spv::Decoration::FPRoundingMode, spv::FPRoundingMode::RTP);
26 break;
27 case IR::FpRounding::RZ:
28 ctx.Decorate(op, spv::Decoration::FPRoundingMode, spv::FPRoundingMode::RTZ);
29 break;
30 }
31 return op; 15 return op;
32} 16}
33 17
34} // Anonymous namespace 18} // Anonymous namespace
35 19
36void EmitFPAbs16(EmitContext&) { 20Id EmitFPAbs16(EmitContext& ctx, Id value) {
37 throw NotImplementedException("SPIR-V Instruction"); 21 return ctx.OpFAbs(ctx.F16[1], value);
38} 22}
39 23
40void EmitFPAbs32(EmitContext&) { 24Id EmitFPAbs32(EmitContext& ctx, Id value) {
41 throw NotImplementedException("SPIR-V Instruction"); 25 return ctx.OpFAbs(ctx.F32[1], value);
42} 26}
43 27
44void EmitFPAbs64(EmitContext&) { 28Id EmitFPAbs64(EmitContext& ctx, Id value) {
45 throw NotImplementedException("SPIR-V Instruction"); 29 return ctx.OpFAbs(ctx.F64[1], value);
46} 30}
47 31
48Id EmitFPAdd16(EmitContext& ctx, IR::Inst* inst, Id a, Id b) { 32Id EmitFPAdd16(EmitContext& ctx, IR::Inst* inst, Id a, Id b) {
@@ -97,16 +81,16 @@ Id EmitFPMul64(EmitContext& ctx, IR::Inst* inst, Id a, Id b) {
97 return Decorate(ctx, inst, ctx.OpFMul(ctx.F64[1], a, b)); 81 return Decorate(ctx, inst, ctx.OpFMul(ctx.F64[1], a, b));
98} 82}
99 83
100void EmitFPNeg16(EmitContext&) { 84Id EmitFPNeg16(EmitContext& ctx, Id value) {
101 throw NotImplementedException("SPIR-V Instruction"); 85 return ctx.OpFNegate(ctx.F16[1], value);
102} 86}
103 87
104void EmitFPNeg32(EmitContext&) { 88Id EmitFPNeg32(EmitContext& ctx, Id value) {
105 throw NotImplementedException("SPIR-V Instruction"); 89 return ctx.OpFNegate(ctx.F32[1], value);
106} 90}
107 91
108void EmitFPNeg64(EmitContext&) { 92Id EmitFPNeg64(EmitContext& ctx, Id value) {
109 throw NotImplementedException("SPIR-V Instruction"); 93 return ctx.OpFNegate(ctx.F64[1], value);
110} 94}
111 95
112void EmitFPRecip32(EmitContext&) { 96void EmitFPRecip32(EmitContext&) {
@@ -157,16 +141,22 @@ void EmitFPLog2(EmitContext&) {
157 throw NotImplementedException("SPIR-V Instruction"); 141 throw NotImplementedException("SPIR-V Instruction");
158} 142}
159 143
160void EmitFPSaturate16(EmitContext&) { 144Id EmitFPSaturate16(EmitContext& ctx, Id value) {
161 throw NotImplementedException("SPIR-V Instruction"); 145 const Id zero{ctx.Constant(ctx.F16[1], u16{0})};
146 const Id one{ctx.Constant(ctx.F16[1], u16{0x3c00})};
147 return ctx.OpFClamp(ctx.F32[1], value, zero, one);
162} 148}
163 149
164void EmitFPSaturate32(EmitContext&) { 150Id EmitFPSaturate32(EmitContext& ctx, Id value) {
165 throw NotImplementedException("SPIR-V Instruction"); 151 const Id zero{ctx.Constant(ctx.F32[1], f32{0.0})};
152 const Id one{ctx.Constant(ctx.F32[1], f32{1.0})};
153 return ctx.OpFClamp(ctx.F32[1], value, zero, one);
166} 154}
167 155
168void EmitFPSaturate64(EmitContext&) { 156Id EmitFPSaturate64(EmitContext& ctx, Id value) {
169 throw NotImplementedException("SPIR-V Instruction"); 157 const Id zero{ctx.Constant(ctx.F64[1], f64{0.0})};
158 const Id one{ctx.Constant(ctx.F64[1], f64{1.0})};
159 return ctx.OpFClamp(ctx.F64[1], value, zero, one);
170} 160}
171 161
172Id EmitFPRoundEven16(EmitContext& ctx, Id value) { 162Id EmitFPRoundEven16(EmitContext& ctx, Id value) {
diff --git a/src/shader_recompiler/backend/spirv/emit_spirv_integer.cpp b/src/shader_recompiler/backend/spirv/emit_spirv_integer.cpp
index 22117a4ee..4c0b5990d 100644
--- a/src/shader_recompiler/backend/spirv/emit_spirv_integer.cpp
+++ b/src/shader_recompiler/backend/spirv/emit_spirv_integer.cpp
@@ -7,10 +7,39 @@
7namespace Shader::Backend::SPIRV { 7namespace Shader::Backend::SPIRV {
8 8
9Id EmitIAdd32(EmitContext& ctx, IR::Inst* inst, Id a, Id b) { 9Id EmitIAdd32(EmitContext& ctx, IR::Inst* inst, Id a, Id b) {
10 if (inst->HasAssociatedPseudoOperation()) { 10 Id result{};
11 throw NotImplementedException("Pseudo-operations on IAdd32"); 11 if (IR::Inst* const carry{inst->GetAssociatedPseudoOperation(IR::Opcode::GetCarryFromOp)}) {
12 const Id carry_type{ctx.TypeStruct(ctx.U32[1], ctx.U32[1])};
13 const Id carry_result{ctx.OpIAddCarry(carry_type, a, b)};
14 result = ctx.OpCompositeExtract(ctx.U32[1], carry_result, 0U);
15
16 const Id carry_value{ctx.OpCompositeExtract(ctx.U32[1], carry_result, 1U)};
17 carry->SetDefinition(ctx.OpINotEqual(ctx.U1, carry_value, ctx.u32_zero_value));
18 carry->Invalidate();
19 } else {
20 result = ctx.OpIAdd(ctx.U32[1], a, b);
12 } 21 }
13 return ctx.OpIAdd(ctx.U32[1], a, b); 22 if (IR::Inst* const zero{inst->GetAssociatedPseudoOperation(IR::Opcode::GetZeroFromOp)}) {
23 zero->SetDefinition(ctx.OpIEqual(ctx.U1, result, ctx.u32_zero_value));
24 zero->Invalidate();
25 }
26 if (IR::Inst* const sign{inst->GetAssociatedPseudoOperation(IR::Opcode::GetSignFromOp)}) {
27 sign->SetDefinition(ctx.OpSLessThan(ctx.U1, result, ctx.u32_zero_value));
28 sign->Invalidate();
29 }
30 if (IR::Inst * overflow{inst->GetAssociatedPseudoOperation(IR::Opcode::GetOverflowFromOp)}) {
31 // https://stackoverflow.com/questions/55468823/how-to-detect-integer-overflow-in-c
32 constexpr u32 s32_max{static_cast<u32>(std::numeric_limits<s32>::max())};
33 const Id is_positive{ctx.OpSGreaterThanEqual(ctx.U1, a, ctx.u32_zero_value)};
34 const Id sub_a{ctx.OpISub(ctx.U32[1], ctx.Constant(ctx.U32[1], s32_max), a)};
35
36 const Id positive_test{ctx.OpSGreaterThan(ctx.U1, b, sub_a)};
37 const Id negative_test{ctx.OpSLessThan(ctx.U1, b, sub_a)};
38 const Id carry_flag{ctx.OpSelect(ctx.U1, is_positive, positive_test, negative_test)};
39 overflow->SetDefinition(carry_flag);
40 overflow->Invalidate();
41 }
42 return result;
14} 43}
15 44
16void EmitIAdd64(EmitContext&) { 45void EmitIAdd64(EmitContext&) {
@@ -49,16 +78,16 @@ void EmitShiftRightArithmetic32(EmitContext&) {
49 throw NotImplementedException("SPIR-V Instruction"); 78 throw NotImplementedException("SPIR-V Instruction");
50} 79}
51 80
52void EmitBitwiseAnd32(EmitContext&) { 81Id EmitBitwiseAnd32(EmitContext& ctx, Id a, Id b) {
53 throw NotImplementedException("SPIR-V Instruction"); 82 return ctx.OpBitwiseAnd(ctx.U32[1], a, b);
54} 83}
55 84
56void EmitBitwiseOr32(EmitContext&) { 85Id EmitBitwiseOr32(EmitContext& ctx, Id a, Id b) {
57 throw NotImplementedException("SPIR-V Instruction"); 86 return ctx.OpBitwiseOr(ctx.U32[1], a, b);
58} 87}
59 88
60void EmitBitwiseXor32(EmitContext&) { 89Id EmitBitwiseXor32(EmitContext& ctx, Id a, Id b) {
61 throw NotImplementedException("SPIR-V Instruction"); 90 return ctx.OpBitwiseXor(ctx.U32[1], a, b);
62} 91}
63 92
64void EmitBitFieldInsert(EmitContext&) { 93void EmitBitFieldInsert(EmitContext&) {
@@ -77,36 +106,36 @@ Id EmitSLessThan(EmitContext& ctx, Id lhs, Id rhs) {
77 return ctx.OpSLessThan(ctx.U1, lhs, rhs); 106 return ctx.OpSLessThan(ctx.U1, lhs, rhs);
78} 107}
79 108
80void EmitULessThan(EmitContext&) { 109Id EmitULessThan(EmitContext& ctx, Id lhs, Id rhs) {
81 throw NotImplementedException("SPIR-V Instruction"); 110 return ctx.OpULessThan(ctx.U1, lhs, rhs);
82} 111}
83 112
84void EmitIEqual(EmitContext&) { 113Id EmitIEqual(EmitContext& ctx, Id lhs, Id rhs) {
85 throw NotImplementedException("SPIR-V Instruction"); 114 return ctx.OpIEqual(ctx.U1, lhs, rhs);
86} 115}
87 116
88void EmitSLessThanEqual(EmitContext&) { 117Id EmitSLessThanEqual(EmitContext& ctx, Id lhs, Id rhs) {
89 throw NotImplementedException("SPIR-V Instruction"); 118 return ctx.OpSLessThanEqual(ctx.U1, lhs, rhs);
90} 119}
91 120
92void EmitULessThanEqual(EmitContext&) { 121Id EmitULessThanEqual(EmitContext& ctx, Id lhs, Id rhs) {
93 throw NotImplementedException("SPIR-V Instruction"); 122 return ctx.OpULessThanEqual(ctx.U1, lhs, rhs);
94} 123}
95 124
96Id EmitSGreaterThan(EmitContext& ctx, Id lhs, Id rhs) { 125Id EmitSGreaterThan(EmitContext& ctx, Id lhs, Id rhs) {
97 return ctx.OpSGreaterThan(ctx.U1, lhs, rhs); 126 return ctx.OpSGreaterThan(ctx.U1, lhs, rhs);
98} 127}
99 128
100void EmitUGreaterThan(EmitContext&) { 129Id EmitUGreaterThan(EmitContext& ctx, Id lhs, Id rhs) {
101 throw NotImplementedException("SPIR-V Instruction"); 130 return ctx.OpUGreaterThan(ctx.U1, lhs, rhs);
102} 131}
103 132
104void EmitINotEqual(EmitContext&) { 133Id EmitINotEqual(EmitContext& ctx, Id lhs, Id rhs) {
105 throw NotImplementedException("SPIR-V Instruction"); 134 return ctx.OpINotEqual(ctx.U1, lhs, rhs);
106} 135}
107 136
108void EmitSGreaterThanEqual(EmitContext&) { 137Id EmitSGreaterThanEqual(EmitContext& ctx, Id lhs, Id rhs) {
109 throw NotImplementedException("SPIR-V Instruction"); 138 return ctx.OpSGreaterThanEqual(ctx.U1, lhs, rhs);
110} 139}
111 140
112Id EmitUGreaterThanEqual(EmitContext& ctx, Id lhs, Id rhs) { 141Id EmitUGreaterThanEqual(EmitContext& ctx, Id lhs, Id rhs) {
diff --git a/src/shader_recompiler/backend/spirv/emit_spirv_select.cpp b/src/shader_recompiler/backend/spirv/emit_spirv_select.cpp
index 8d5062724..eb1926a4d 100644
--- a/src/shader_recompiler/backend/spirv/emit_spirv_select.cpp
+++ b/src/shader_recompiler/backend/spirv/emit_spirv_select.cpp
@@ -14,8 +14,8 @@ void EmitSelect16(EmitContext&) {
14 throw NotImplementedException("SPIR-V Instruction"); 14 throw NotImplementedException("SPIR-V Instruction");
15} 15}
16 16
17void EmitSelect32(EmitContext&) { 17Id EmitSelect32(EmitContext& ctx, Id cond, Id true_value, Id false_value) {
18 throw NotImplementedException("SPIR-V Instruction"); 18 return ctx.OpSelect(ctx.U32[1], cond, true_value, false_value);
19} 19}
20 20
21void EmitSelect64(EmitContext&) { 21void EmitSelect64(EmitContext&) {
diff --git a/src/shader_recompiler/frontend/ir/ir_emitter.cpp b/src/shader_recompiler/frontend/ir/ir_emitter.cpp
index 8f120a2f6..34c2f67fb 100644
--- a/src/shader_recompiler/frontend/ir/ir_emitter.cpp
+++ b/src/shader_recompiler/frontend/ir/ir_emitter.cpp
@@ -468,11 +468,11 @@ F16F32F64 IREmitter::FPFma(const F16F32F64& a, const F16F32F64& b, const F16F32F
468 468
469F16F32F64 IREmitter::FPAbs(const F16F32F64& value) { 469F16F32F64 IREmitter::FPAbs(const F16F32F64& value) {
470 switch (value.Type()) { 470 switch (value.Type()) {
471 case Type::U16: 471 case Type::F16:
472 return Inst<F16>(Opcode::FPAbs16, value); 472 return Inst<F16>(Opcode::FPAbs16, value);
473 case Type::U32: 473 case Type::F32:
474 return Inst<F32>(Opcode::FPAbs32, value); 474 return Inst<F32>(Opcode::FPAbs32, value);
475 case Type::U64: 475 case Type::F64:
476 return Inst<F64>(Opcode::FPAbs64, value); 476 return Inst<F64>(Opcode::FPAbs64, value);
477 default: 477 default:
478 ThrowInvalidType(value.Type()); 478 ThrowInvalidType(value.Type());
@@ -481,11 +481,11 @@ F16F32F64 IREmitter::FPAbs(const F16F32F64& value) {
481 481
482F16F32F64 IREmitter::FPNeg(const F16F32F64& value) { 482F16F32F64 IREmitter::FPNeg(const F16F32F64& value) {
483 switch (value.Type()) { 483 switch (value.Type()) {
484 case Type::U16: 484 case Type::F16:
485 return Inst<F16>(Opcode::FPNeg16, value); 485 return Inst<F16>(Opcode::FPNeg16, value);
486 case Type::U32: 486 case Type::F32:
487 return Inst<F32>(Opcode::FPNeg32, value); 487 return Inst<F32>(Opcode::FPNeg32, value);
488 case Type::U64: 488 case Type::F64:
489 return Inst<F64>(Opcode::FPNeg64, value); 489 return Inst<F64>(Opcode::FPNeg64, value);
490 default: 490 default:
491 ThrowInvalidType(value.Type()); 491 ThrowInvalidType(value.Type());
@@ -495,10 +495,10 @@ F16F32F64 IREmitter::FPNeg(const F16F32F64& value) {
495F16F32F64 IREmitter::FPAbsNeg(const F16F32F64& value, bool abs, bool neg) { 495F16F32F64 IREmitter::FPAbsNeg(const F16F32F64& value, bool abs, bool neg) {
496 F16F32F64 result{value}; 496 F16F32F64 result{value};
497 if (abs) { 497 if (abs) {
498 result = FPAbs(value); 498 result = FPAbs(result);
499 } 499 }
500 if (neg) { 500 if (neg) {
501 result = FPNeg(value); 501 result = FPNeg(result);
502 } 502 }
503 return result; 503 return result;
504} 504}
diff --git a/src/shader_recompiler/frontend/ir/pred.h b/src/shader_recompiler/frontend/ir/pred.h
index c6f2f82bf..4e7f32423 100644
--- a/src/shader_recompiler/frontend/ir/pred.h
+++ b/src/shader_recompiler/frontend/ir/pred.h
@@ -19,8 +19,8 @@ enum class Pred : u64 {
19 PT, 19 PT,
20}; 20};
21 21
22constexpr size_t NUM_USER_PREDS = 6; 22constexpr size_t NUM_USER_PREDS = 7;
23constexpr size_t NUM_PREDS = 7; 23constexpr size_t NUM_PREDS = 8;
24 24
25[[nodiscard]] constexpr size_t PredIndex(Pred pred) noexcept { 25[[nodiscard]] constexpr size_t PredIndex(Pred pred) noexcept {
26 return static_cast<size_t>(pred); 26 return static_cast<size_t>(pred);
diff --git a/src/shader_recompiler/frontend/maxwell/program.cpp b/src/shader_recompiler/frontend/maxwell/program.cpp
index 16cdc12e2..ed5dbf41f 100644
--- a/src/shader_recompiler/frontend/maxwell/program.cpp
+++ b/src/shader_recompiler/frontend/maxwell/program.cpp
@@ -56,12 +56,12 @@ IR::Program TranslateProgram(ObjectPool<IR::Inst>& inst_pool, ObjectPool<IR::Blo
56 .post_order_blocks{}, 56 .post_order_blocks{},
57 }); 57 });
58 } 58 }
59 fmt::print(stdout, "{}\n", IR::DumpProgram(program));
59 Optimization::LowerFp16ToFp32(program); 60 Optimization::LowerFp16ToFp32(program);
60 for (IR::Function& function : functions) { 61 for (IR::Function& function : functions) {
61 function.post_order_blocks = PostOrder(function.blocks); 62 function.post_order_blocks = PostOrder(function.blocks);
62 Optimization::SsaRewritePass(function.post_order_blocks); 63 Optimization::SsaRewritePass(function.post_order_blocks);
63 } 64 }
64 fmt::print(stdout, "{}\n", IR::DumpProgram(program));
65 Optimization::GlobalMemoryToStorageBufferPass(program); 65 Optimization::GlobalMemoryToStorageBufferPass(program);
66 for (IR::Function& function : functions) { 66 for (IR::Function& function : functions) {
67 Optimization::PostOrderInvoke(Optimization::ConstantPropagationPass, function); 67 Optimization::PostOrderInvoke(Optimization::ConstantPropagationPass, function);
diff --git a/src/shader_recompiler/frontend/maxwell/translate/impl/floating_point_add.cpp b/src/shader_recompiler/frontend/maxwell/translate/impl/floating_point_add.cpp
index cb3a326cf..219ffcc6a 100644
--- a/src/shader_recompiler/frontend/maxwell/translate/impl/floating_point_add.cpp
+++ b/src/shader_recompiler/frontend/maxwell/translate/impl/floating_point_add.cpp
@@ -9,7 +9,6 @@
9 9
10namespace Shader::Maxwell { 10namespace Shader::Maxwell {
11namespace { 11namespace {
12
13void FADD(TranslatorVisitor& v, u64 insn, bool sat, bool cc, bool ftz, FpRounding fp_rounding, 12void FADD(TranslatorVisitor& v, u64 insn, bool sat, bool cc, bool ftz, FpRounding fp_rounding,
14 const IR::F32& src_b, bool abs_a, bool neg_a, bool abs_b, bool neg_b) { 13 const IR::F32& src_b, bool abs_a, bool neg_a, bool abs_b, bool neg_b) {
15 union { 14 union {
@@ -18,9 +17,6 @@ void FADD(TranslatorVisitor& v, u64 insn, bool sat, bool cc, bool ftz, FpRoundin
18 BitField<8, 8, IR::Reg> src_a; 17 BitField<8, 8, IR::Reg> src_a;
19 } const fadd{insn}; 18 } const fadd{insn};
20 19
21 if (sat) {
22 throw NotImplementedException("FADD SAT");
23 }
24 if (cc) { 20 if (cc) {
25 throw NotImplementedException("FADD CC"); 21 throw NotImplementedException("FADD CC");
26 } 22 }
@@ -31,7 +27,11 @@ void FADD(TranslatorVisitor& v, u64 insn, bool sat, bool cc, bool ftz, FpRoundin
31 .rounding{CastFpRounding(fp_rounding)}, 27 .rounding{CastFpRounding(fp_rounding)},
32 .fmz_mode{ftz ? IR::FmzMode::FTZ : IR::FmzMode::None}, 28 .fmz_mode{ftz ? IR::FmzMode::FTZ : IR::FmzMode::None},
33 }; 29 };
34 v.F(fadd.dest_reg, v.ir.FPAdd(op_a, op_b, control)); 30 IR::F32 value{v.ir.FPAdd(op_a, op_b, control)};
31 if (sat) {
32 value = v.ir.FPSaturate(value);
33 }
34 v.F(fadd.dest_reg, value);
35} 35}
36 36
37void FADD(TranslatorVisitor& v, u64 insn, const IR::F32& src_b) { 37void FADD(TranslatorVisitor& v, u64 insn, const IR::F32& src_b) {
@@ -53,15 +53,15 @@ void FADD(TranslatorVisitor& v, u64 insn, const IR::F32& src_b) {
53} // Anonymous namespace 53} // Anonymous namespace
54 54
55void TranslatorVisitor::FADD_reg(u64 insn) { 55void TranslatorVisitor::FADD_reg(u64 insn) {
56 FADD(*this, insn, GetReg20F(insn)); 56 FADD(*this, insn, GetRegFloat20(insn));
57} 57}
58 58
59void TranslatorVisitor::FADD_cbuf(u64) { 59void TranslatorVisitor::FADD_cbuf(u64 insn) {
60 throw NotImplementedException("FADD (cbuf)"); 60 FADD(*this, insn, GetFloatCbuf(insn));
61} 61}
62 62
63void TranslatorVisitor::FADD_imm(u64) { 63void TranslatorVisitor::FADD_imm(u64 insn) {
64 throw NotImplementedException("FADD (imm)"); 64 FADD(*this, insn, GetFloatImm20(insn));
65} 65}
66 66
67void TranslatorVisitor::FADD32I(u64) { 67void TranslatorVisitor::FADD32I(u64) {
diff --git a/src/shader_recompiler/frontend/maxwell/translate/impl/floating_point_conversion_integer.cpp b/src/shader_recompiler/frontend/maxwell/translate/impl/floating_point_conversion_integer.cpp
index 4d82a0009..81175627f 100644
--- a/src/shader_recompiler/frontend/maxwell/translate/impl/floating_point_conversion_integer.cpp
+++ b/src/shader_recompiler/frontend/maxwell/translate/impl/floating_point_conversion_integer.cpp
@@ -158,7 +158,7 @@ void TranslatorVisitor::F2I_cbuf(u64 insn) {
158 case SrcFormat::F16: 158 case SrcFormat::F16:
159 return IR::F16{ir.CompositeExtract(ir.UnpackFloat2x16(GetCbuf(insn)), f2i.half)}; 159 return IR::F16{ir.CompositeExtract(ir.UnpackFloat2x16(GetCbuf(insn)), f2i.half)};
160 case SrcFormat::F32: 160 case SrcFormat::F32:
161 return GetCbufF(insn); 161 return GetFloatCbuf(insn);
162 case SrcFormat::F64: { 162 case SrcFormat::F64: {
163 return UnpackCbuf(*this, insn); 163 return UnpackCbuf(*this, insn);
164 } 164 }
diff --git a/src/shader_recompiler/frontend/maxwell/translate/impl/floating_point_fused_multiply_add.cpp b/src/shader_recompiler/frontend/maxwell/translate/impl/floating_point_fused_multiply_add.cpp
index 1464f2807..758700d3c 100644
--- a/src/shader_recompiler/frontend/maxwell/translate/impl/floating_point_fused_multiply_add.cpp
+++ b/src/shader_recompiler/frontend/maxwell/translate/impl/floating_point_fused_multiply_add.cpp
@@ -51,7 +51,7 @@ void FFMA(TranslatorVisitor& v, u64 insn, const IR::F32& src_b, const IR::F32& s
51} // Anonymous namespace 51} // Anonymous namespace
52 52
53void TranslatorVisitor::FFMA_reg(u64 insn) { 53void TranslatorVisitor::FFMA_reg(u64 insn) {
54 FFMA(*this, insn, GetReg20F(insn), GetReg39F(insn)); 54 FFMA(*this, insn, GetRegFloat20(insn), GetRegFloat39(insn));
55} 55}
56 56
57void TranslatorVisitor::FFMA_rc(u64) { 57void TranslatorVisitor::FFMA_rc(u64) {
@@ -59,7 +59,7 @@ void TranslatorVisitor::FFMA_rc(u64) {
59} 59}
60 60
61void TranslatorVisitor::FFMA_cr(u64 insn) { 61void TranslatorVisitor::FFMA_cr(u64 insn) {
62 FFMA(*this, insn, GetCbufF(insn), GetReg39F(insn)); 62 FFMA(*this, insn, GetFloatCbuf(insn), GetRegFloat39(insn));
63} 63}
64 64
65void TranslatorVisitor::FFMA_imm(u64) { 65void TranslatorVisitor::FFMA_imm(u64) {
diff --git a/src/shader_recompiler/frontend/maxwell/translate/impl/floating_point_multiply.cpp b/src/shader_recompiler/frontend/maxwell/translate/impl/floating_point_multiply.cpp
index 1b1d38be7..5c38d3fc1 100644
--- a/src/shader_recompiler/frontend/maxwell/translate/impl/floating_point_multiply.cpp
+++ b/src/shader_recompiler/frontend/maxwell/translate/impl/floating_point_multiply.cpp
@@ -91,7 +91,7 @@ void FMUL(TranslatorVisitor& v, u64 insn, const IR::F32& src_b) {
91} // Anonymous namespace 91} // Anonymous namespace
92 92
93void TranslatorVisitor::FMUL_reg(u64 insn) { 93void TranslatorVisitor::FMUL_reg(u64 insn) {
94 return FMUL(*this, insn, GetReg20F(insn)); 94 return FMUL(*this, insn, GetRegFloat20(insn));
95} 95}
96 96
97void TranslatorVisitor::FMUL_cbuf(u64) { 97void TranslatorVisitor::FMUL_cbuf(u64) {
diff --git a/src/shader_recompiler/frontend/maxwell/translate/impl/impl.cpp b/src/shader_recompiler/frontend/maxwell/translate/impl/impl.cpp
index 079e3497f..be17bb0d9 100644
--- a/src/shader_recompiler/frontend/maxwell/translate/impl/impl.cpp
+++ b/src/shader_recompiler/frontend/maxwell/translate/impl/impl.cpp
@@ -48,11 +48,11 @@ IR::U32 TranslatorVisitor::GetReg39(u64 insn) {
48 return X(reg.index); 48 return X(reg.index);
49} 49}
50 50
51IR::F32 TranslatorVisitor::GetReg20F(u64 insn) { 51IR::F32 TranslatorVisitor::GetRegFloat20(u64 insn) {
52 return ir.BitCast<IR::F32>(GetReg20(insn)); 52 return ir.BitCast<IR::F32>(GetReg20(insn));
53} 53}
54 54
55IR::F32 TranslatorVisitor::GetReg39F(u64 insn) { 55IR::F32 TranslatorVisitor::GetRegFloat39(u64 insn) {
56 return ir.BitCast<IR::F32>(GetReg39(insn)); 56 return ir.BitCast<IR::F32>(GetReg39(insn));
57} 57}
58 58
@@ -73,7 +73,7 @@ IR::U32 TranslatorVisitor::GetCbuf(u64 insn) {
73 return ir.GetCbuf(binding, byte_offset); 73 return ir.GetCbuf(binding, byte_offset);
74} 74}
75 75
76IR::F32 TranslatorVisitor::GetCbufF(u64 insn) { 76IR::F32 TranslatorVisitor::GetFloatCbuf(u64 insn) {
77 return ir.BitCast<IR::F32>(GetCbuf(insn)); 77 return ir.BitCast<IR::F32>(GetCbuf(insn));
78} 78}
79 79
@@ -88,6 +88,17 @@ IR::U32 TranslatorVisitor::GetImm20(u64 insn) {
88 return ir.Imm32(value); 88 return ir.Imm32(value);
89} 89}
90 90
91IR::F32 TranslatorVisitor::GetFloatImm20(u64 insn) {
92 union {
93 u64 raw;
94 BitField<20, 19, u64> value;
95 BitField<56, 1, u64> is_negative;
96 } const imm{insn};
97 const f32 positive_value{Common::BitCast<f32>(static_cast<u32>(imm.value) << 12)};
98 const f32 value{imm.is_negative != 0 ? -positive_value : positive_value};
99 return ir.Imm32(value);
100}
101
91IR::U32 TranslatorVisitor::GetImm32(u64 insn) { 102IR::U32 TranslatorVisitor::GetImm32(u64 insn) {
92 union { 103 union {
93 u64 raw; 104 u64 raw;
diff --git a/src/shader_recompiler/frontend/maxwell/translate/impl/impl.h b/src/shader_recompiler/frontend/maxwell/translate/impl/impl.h
index 27aba2cf8..4d4cf2ebf 100644
--- a/src/shader_recompiler/frontend/maxwell/translate/impl/impl.h
+++ b/src/shader_recompiler/frontend/maxwell/translate/impl/impl.h
@@ -304,13 +304,14 @@ public:
304 [[nodiscard]] IR::U32 GetReg8(u64 insn); 304 [[nodiscard]] IR::U32 GetReg8(u64 insn);
305 [[nodiscard]] IR::U32 GetReg20(u64 insn); 305 [[nodiscard]] IR::U32 GetReg20(u64 insn);
306 [[nodiscard]] IR::U32 GetReg39(u64 insn); 306 [[nodiscard]] IR::U32 GetReg39(u64 insn);
307 [[nodiscard]] IR::F32 GetReg20F(u64 insn); 307 [[nodiscard]] IR::F32 GetRegFloat20(u64 insn);
308 [[nodiscard]] IR::F32 GetReg39F(u64 insn); 308 [[nodiscard]] IR::F32 GetRegFloat39(u64 insn);
309 309
310 [[nodiscard]] IR::U32 GetCbuf(u64 insn); 310 [[nodiscard]] IR::U32 GetCbuf(u64 insn);
311 [[nodiscard]] IR::F32 GetCbufF(u64 insn); 311 [[nodiscard]] IR::F32 GetFloatCbuf(u64 insn);
312 312
313 [[nodiscard]] IR::U32 GetImm20(u64 insn); 313 [[nodiscard]] IR::U32 GetImm20(u64 insn);
314 [[nodiscard]] IR::F32 GetFloatImm20(u64 insn);
314 315
315 [[nodiscard]] IR::U32 GetImm32(u64 insn); 316 [[nodiscard]] IR::U32 GetImm32(u64 insn);
316 317
diff --git a/src/shader_recompiler/frontend/maxwell/translate/impl/integer_add.cpp b/src/shader_recompiler/frontend/maxwell/translate/impl/integer_add.cpp
index 623e78ff8..1493e1815 100644
--- a/src/shader_recompiler/frontend/maxwell/translate/impl/integer_add.cpp
+++ b/src/shader_recompiler/frontend/maxwell/translate/impl/integer_add.cpp
@@ -84,8 +84,8 @@ void TranslatorVisitor::IADD_cbuf(u64 insn) {
84 IADD(*this, insn, GetCbuf(insn)); 84 IADD(*this, insn, GetCbuf(insn));
85} 85}
86 86
87void TranslatorVisitor::IADD_imm(u64) { 87void TranslatorVisitor::IADD_imm(u64 insn) {
88 throw NotImplementedException("IADD (imm)"); 88 IADD(*this, insn, GetImm20(insn));
89} 89}
90 90
91void TranslatorVisitor::IADD32I(u64 insn) { 91void TranslatorVisitor::IADD32I(u64 insn) {
diff --git a/src/shader_recompiler/frontend/maxwell/translate/impl/move_predicate_to_register.cpp b/src/shader_recompiler/frontend/maxwell/translate/impl/move_predicate_to_register.cpp
new file mode 100644
index 000000000..4324fd443
--- /dev/null
+++ b/src/shader_recompiler/frontend/maxwell/translate/impl/move_predicate_to_register.cpp
@@ -0,0 +1,66 @@
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 "shader_recompiler/exception.h"
7#include "shader_recompiler/frontend/maxwell/translate/impl/impl.h"
8
9namespace Shader::Maxwell {
10namespace {
11enum class Mode : u64 {
12 PR,
13 CC,
14};
15} // Anonymous namespace
16
17void TranslatorVisitor::P2R_reg(u64) {
18 throw NotImplementedException("P2R (reg)");
19}
20
21void TranslatorVisitor::P2R_cbuf(u64) {
22 throw NotImplementedException("P2R (cbuf)");
23}
24
25void TranslatorVisitor::P2R_imm(u64 insn) {
26 union {
27 u64 raw;
28 BitField<0, 8, IR::Reg> dest_reg;
29 BitField<8, 8, IR::Reg> src;
30 BitField<40, 1, Mode> mode;
31 BitField<41, 2, u64> byte_selector;
32 } const p2r{insn};
33
34 const u32 mask{GetImm20(insn).U32()};
35 const bool pr_mode{p2r.mode == Mode::PR};
36 const u32 num_items{pr_mode ? 7U : 4U};
37 const u32 offset{static_cast<u32>(p2r.byte_selector) * 8};
38 IR::U32 insert{ir.Imm32(0)};
39 for (u32 index = 0; index < num_items; ++index) {
40 if (((mask >> index) & 1) == 0) {
41 continue;
42 }
43 const IR::U1 cond{[this, index, pr_mode] {
44 if (pr_mode) {
45 return ir.GetPred(IR::Pred{index});
46 }
47 switch (index) {
48 case 0:
49 return ir.GetZFlag();
50 case 1:
51 return ir.GetSFlag();
52 case 2:
53 return ir.GetCFlag();
54 case 3:
55 return ir.GetOFlag();
56 }
57 throw LogicError("Unreachable P2R index");
58 }()};
59 const IR::U32 bit{ir.Select(cond, ir.Imm32(1U << (index + offset)), ir.Imm32(0))};
60 insert = ir.BitwiseOr(insert, bit);
61 }
62 const IR::U32 masked_out{ir.BitwiseAnd(X(p2r.src), ir.Imm32(~(mask << offset)))};
63 X(p2r.dest_reg, ir.BitwiseOr(masked_out, insert));
64}
65
66} // 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 6b2a1356b..628cf1c14 100644
--- a/src/shader_recompiler/frontend/maxwell/translate/impl/not_implemented.cpp
+++ b/src/shader_recompiler/frontend/maxwell/translate/impl/not_implemented.cpp
@@ -633,18 +633,6 @@ void TranslatorVisitor::OUT_imm(u64) {
633 ThrowNotImplemented(Opcode::OUT_imm); 633 ThrowNotImplemented(Opcode::OUT_imm);
634} 634}
635 635
636void TranslatorVisitor::P2R_reg(u64) {
637 ThrowNotImplemented(Opcode::P2R_reg);
638}
639
640void TranslatorVisitor::P2R_cbuf(u64) {
641 ThrowNotImplemented(Opcode::P2R_cbuf);
642}
643
644void TranslatorVisitor::P2R_imm(u64) {
645 ThrowNotImplemented(Opcode::P2R_imm);
646}
647
648void TranslatorVisitor::PBK() { 636void TranslatorVisitor::PBK() {
649 // PBK is a no-op 637 // PBK is a no-op
650} 638}