summaryrefslogtreecommitdiff
path: root/src/shader_recompiler/frontend/maxwell/translate/impl
diff options
context:
space:
mode:
authorGravatar ReinUsesLisp2021-01-09 03:30:07 -0300
committerGravatar ameerj2021-07-22 21:51:21 -0400
commit2d48a7b4d0666ad16d03a22d85712617a0849046 (patch)
treedd1069afca86f66e77e3438da77421a43adf5091 /src/shader_recompiler/frontend/maxwell/translate/impl
parentthread_worker: Fix compile time error (diff)
downloadyuzu-2d48a7b4d0666ad16d03a22d85712617a0849046.tar.gz
yuzu-2d48a7b4d0666ad16d03a22d85712617a0849046.tar.xz
yuzu-2d48a7b4d0666ad16d03a22d85712617a0849046.zip
shader: Initial recompiler work
Diffstat (limited to 'src/shader_recompiler/frontend/maxwell/translate/impl')
-rw-r--r--src/shader_recompiler/frontend/maxwell/translate/impl/exit.cpp15
-rw-r--r--src/shader_recompiler/frontend/maxwell/translate/impl/floating_point_conversion_integer.cpp133
-rw-r--r--src/shader_recompiler/frontend/maxwell/translate/impl/floating_point_multi_function.cpp71
-rw-r--r--src/shader_recompiler/frontend/maxwell/translate/impl/impl.cpp79
-rw-r--r--src/shader_recompiler/frontend/maxwell/translate/impl/impl.h316
-rw-r--r--src/shader_recompiler/frontend/maxwell/translate/impl/load_store_attribute.cpp92
-rw-r--r--src/shader_recompiler/frontend/maxwell/translate/impl/load_store_memory.cpp90
-rw-r--r--src/shader_recompiler/frontend/maxwell/translate/impl/not_implemented.cpp1105
-rw-r--r--src/shader_recompiler/frontend/maxwell/translate/impl/register_move.cpp45
9 files changed, 1946 insertions, 0 deletions
diff --git a/src/shader_recompiler/frontend/maxwell/translate/impl/exit.cpp b/src/shader_recompiler/frontend/maxwell/translate/impl/exit.cpp
new file mode 100644
index 000000000..e98bbd0d1
--- /dev/null
+++ b/src/shader_recompiler/frontend/maxwell/translate/impl/exit.cpp
@@ -0,0 +1,15 @@
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/common_types.h"
6#include "shader_recompiler/exception.h"
7#include "shader_recompiler/frontend/maxwell/translate/impl/impl.h"
8
9namespace Shader::Maxwell {
10
11void TranslatorVisitor::EXIT(u64) {
12 ir.Exit();
13}
14
15} // namespace Shader::Maxwell
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
new file mode 100644
index 000000000..c4288d9a8
--- /dev/null
+++ b/src/shader_recompiler/frontend/maxwell/translate/impl/floating_point_conversion_integer.cpp
@@ -0,0 +1,133 @@
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/common_types.h"
6#include "shader_recompiler/exception.h"
7#include "shader_recompiler/frontend/maxwell/opcode.h"
8#include "shader_recompiler/frontend/maxwell/translate/impl/impl.h"
9
10namespace Shader::Maxwell {
11namespace {
12enum class DestFormat : u64 {
13 Invalid,
14 I16,
15 I32,
16 I64,
17};
18enum class SrcFormat : u64 {
19 Invalid,
20 F16,
21 F32,
22 F64,
23};
24enum class Rounding : u64 {
25 Round,
26 Floor,
27 Ceil,
28 Trunc,
29};
30
31union F2I {
32 u64 raw;
33 BitField<0, 8, IR::Reg> dest_reg;
34 BitField<8, 2, DestFormat> dest_format;
35 BitField<10, 2, SrcFormat> src_format;
36 BitField<12, 1, u64> is_signed;
37 BitField<39, 1, Rounding> rounding;
38 BitField<49, 1, u64> half;
39 BitField<44, 1, u64> ftz;
40 BitField<45, 1, u64> abs;
41 BitField<47, 1, u64> cc;
42 BitField<49, 1, u64> neg;
43};
44
45size_t BitSize(DestFormat dest_format) {
46 switch (dest_format) {
47 case DestFormat::I16:
48 return 16;
49 case DestFormat::I32:
50 return 32;
51 case DestFormat::I64:
52 return 64;
53 default:
54 throw NotImplementedException("Invalid destination format {}", dest_format);
55 }
56}
57
58void TranslateF2I(TranslatorVisitor& v, u64 insn, const IR::U16U32U64& op_a) {
59 // F2I is used to convert from a floating point value to an integer
60 const F2I f2i{insn};
61
62 const IR::U16U32U64 float_value{v.ir.FPAbsNeg(op_a, f2i.abs != 0, f2i.neg != 0)};
63 const IR::U16U32U64 rounded_value{[&] {
64 switch (f2i.rounding) {
65 case Rounding::Round:
66 return v.ir.FPRoundEven(float_value);
67 case Rounding::Floor:
68 return v.ir.FPFloor(float_value);
69 case Rounding::Ceil:
70 return v.ir.FPCeil(float_value);
71 case Rounding::Trunc:
72 return v.ir.FPTrunc(float_value);
73 default:
74 throw NotImplementedException("Invalid F2I rounding {}", f2i.rounding.Value());
75 }
76 }()};
77
78 // TODO: Handle out of bounds conversions.
79 // For example converting F32 65537.0 to U16, the expected value is 0xffff,
80
81 const bool is_signed{f2i.is_signed != 0};
82 const size_t bitsize{BitSize(f2i.dest_format)};
83 const IR::U16U32U64 result{v.ir.ConvertFToI(bitsize, is_signed, rounded_value)};
84
85 v.X(f2i.dest_reg, result);
86
87 if (f2i.cc != 0) {
88 v.SetZFlag(v.ir.GetZeroFromOp(result));
89 if (is_signed) {
90 v.SetSFlag(v.ir.GetSignFromOp(result));
91 } else {
92 v.ResetSFlag();
93 }
94 v.ResetCFlag();
95
96 // TODO: Investigate if out of bound conversions sets the overflow flag
97 v.ResetOFlag();
98 }
99}
100} // Anonymous namespace
101
102void TranslatorVisitor::F2I_reg(u64 insn) {
103 union {
104 F2I base;
105 BitField<20, 8, IR::Reg> src_reg;
106 } const f2i{insn};
107
108 const IR::U16U32U64 op_a{[&]() -> IR::U16U32U64 {
109 switch (f2i.base.src_format) {
110 case SrcFormat::F16:
111 return ir.CompositeExtract(ir.UnpackFloat2x16(X(f2i.src_reg)), f2i.base.half);
112 case SrcFormat::F32:
113 return X(f2i.src_reg);
114 case SrcFormat::F64:
115 return ir.PackDouble2x32(ir.CompositeConstruct(X(f2i.src_reg), X(f2i.src_reg + 1)));
116 default:
117 throw NotImplementedException("Invalid F2I source format {}",
118 f2i.base.src_format.Value());
119 }
120 }()};
121
122 TranslateF2I(*this, insn, op_a);
123}
124
125void TranslatorVisitor::F2I_cbuf(u64) {
126 throw NotImplementedException("{}", Opcode::F2I_cbuf);
127}
128
129void TranslatorVisitor::F2I_imm(u64) {
130 throw NotImplementedException("{}", Opcode::F2I_imm);
131}
132
133} // namespace Shader::Maxwell
diff --git a/src/shader_recompiler/frontend/maxwell/translate/impl/floating_point_multi_function.cpp b/src/shader_recompiler/frontend/maxwell/translate/impl/floating_point_multi_function.cpp
new file mode 100644
index 000000000..e2ab0dab2
--- /dev/null
+++ b/src/shader_recompiler/frontend/maxwell/translate/impl/floating_point_multi_function.cpp
@@ -0,0 +1,71 @@
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/exception.h"
8#include "shader_recompiler/frontend/maxwell/opcode.h"
9#include "shader_recompiler/frontend/maxwell/translate/impl/impl.h"
10
11namespace Shader::Maxwell {
12namespace {
13enum class Operation {
14 Cos = 0,
15 Sin = 1,
16 Ex2 = 2, // Base 2 exponent
17 Lg2 = 3, // Base 2 logarithm
18 Rcp = 4, // Reciprocal
19 Rsq = 5, // Reciprocal square root
20 Rcp64H = 6, // 64-bit reciprocal
21 Rsq64H = 7, // 64-bit reciprocal square root
22 Sqrt = 8,
23};
24} // Anonymous namespace
25
26void TranslatorVisitor::MUFU(u64 insn) {
27 // MUFU is used to implement a bunch of special functions. See Operation.
28 union {
29 u64 raw;
30 BitField<0, 8, IR::Reg> dest_reg;
31 BitField<8, 8, IR::Reg> src_reg;
32 BitField<20, 4, Operation> operation;
33 BitField<46, 1, u64> abs;
34 BitField<48, 1, u64> neg;
35 BitField<50, 1, u64> sat;
36 } const mufu{insn};
37
38 const IR::U32 op_a{ir.FPAbsNeg(X(mufu.src_reg), mufu.abs != 0, mufu.neg != 0)};
39 IR::U32 value{[&]() -> IR::U32 {
40 switch (mufu.operation) {
41 case Operation::Cos:
42 return ir.FPCosNotReduced(op_a);
43 case Operation::Sin:
44 return ir.FPSinNotReduced(op_a);
45 case Operation::Ex2:
46 return ir.FPExp2NotReduced(op_a);
47 case Operation::Lg2:
48 return ir.FPLog2(op_a);
49 case Operation::Rcp:
50 return ir.FPRecip(op_a);
51 case Operation::Rsq:
52 return ir.FPRecipSqrt(op_a);
53 case Operation::Rcp64H:
54 throw NotImplementedException("MUFU.RCP64H");
55 case Operation::Rsq64H:
56 throw NotImplementedException("MUFU.RSQ64H");
57 case Operation::Sqrt:
58 return ir.FPSqrt(op_a);
59 default:
60 throw NotImplementedException("Invalid MUFU operation {}", mufu.operation.Value());
61 }
62 }()};
63
64 if (mufu.sat) {
65 value = ir.FPSaturate(value);
66 }
67
68 X(mufu.dest_reg, value);
69}
70
71} // namespace Shader::Maxwell
diff --git a/src/shader_recompiler/frontend/maxwell/translate/impl/impl.cpp b/src/shader_recompiler/frontend/maxwell/translate/impl/impl.cpp
new file mode 100644
index 000000000..7bc7ce9f2
--- /dev/null
+++ b/src/shader_recompiler/frontend/maxwell/translate/impl/impl.cpp
@@ -0,0 +1,79 @@
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/frontend/ir/ir_emitter.h"
7#include "shader_recompiler/frontend/maxwell/translate/impl/impl.h"
8
9namespace Shader::Maxwell {
10
11IR::U32 TranslatorVisitor::X(IR::Reg reg) {
12 return ir.GetReg(reg);
13}
14
15void TranslatorVisitor::X(IR::Reg dest_reg, const IR::U32& value) {
16 ir.SetReg(dest_reg, value);
17}
18
19IR::U32 TranslatorVisitor::GetCbuf(u64 insn) {
20 union {
21 u64 raw;
22 BitField<20, 14, s64> offset;
23 BitField<34, 5, u64> binding;
24 } const cbuf{insn};
25 if (cbuf.binding >= 18) {
26 throw NotImplementedException("Out of bounds constant buffer binding {}", cbuf.binding);
27 }
28 if (cbuf.offset >= 0x10'000 || cbuf.offset < 0) {
29 throw NotImplementedException("Out of bounds constant buffer offset {}", cbuf.offset);
30 }
31 const IR::U32 binding{ir.Imm32(static_cast<u32>(cbuf.binding))};
32 const IR::U32 byte_offset{ir.Imm32(static_cast<u32>(cbuf.offset) * 4)};
33 return ir.GetCbuf(binding, byte_offset);
34}
35
36IR::U32 TranslatorVisitor::GetImm(u64 insn) {
37 union {
38 u64 raw;
39 BitField<20, 19, u64> value;
40 BitField<56, 1, u64> is_negative;
41 } const imm{insn};
42 const s32 positive_value{static_cast<s32>(imm.value)};
43 const s32 value{imm.is_negative != 0 ? -positive_value : positive_value};
44 return ir.Imm32(value);
45}
46
47void TranslatorVisitor::SetZFlag(const IR::U1& value) {
48 ir.SetZFlag(value);
49}
50
51void TranslatorVisitor::SetSFlag(const IR::U1& value) {
52 ir.SetSFlag(value);
53}
54
55void TranslatorVisitor::SetCFlag(const IR::U1& value) {
56 ir.SetCFlag(value);
57}
58
59void TranslatorVisitor::SetOFlag(const IR::U1& value) {
60 ir.SetOFlag(value);
61}
62
63void TranslatorVisitor::ResetZero() {
64 SetZFlag(ir.Imm1(false));
65}
66
67void TranslatorVisitor::ResetSFlag() {
68 SetSFlag(ir.Imm1(false));
69}
70
71void TranslatorVisitor::ResetCFlag() {
72 SetCFlag(ir.Imm1(false));
73}
74
75void TranslatorVisitor::ResetOFlag() {
76 SetOFlag(ir.Imm1(false));
77}
78
79} // namespace Shader::Maxwell
diff --git a/src/shader_recompiler/frontend/maxwell/translate/impl/impl.h b/src/shader_recompiler/frontend/maxwell/translate/impl/impl.h
new file mode 100644
index 000000000..bc607b002
--- /dev/null
+++ b/src/shader_recompiler/frontend/maxwell/translate/impl/impl.h
@@ -0,0 +1,316 @@
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 "shader_recompiler/environment.h"
6#include "shader_recompiler/frontend/ir/basic_block.h"
7#include "shader_recompiler/frontend/ir/ir_emitter.h"
8#include "shader_recompiler/frontend/maxwell/instruction.h"
9
10namespace Shader::Maxwell {
11
12class TranslatorVisitor {
13public:
14 explicit TranslatorVisitor(Environment& env_, IR::Block& block) : env{env_} ,ir(block) {}
15
16 Environment& env;
17 IR::IREmitter ir;
18
19 void AL2P(u64 insn);
20 void ALD(u64 insn);
21 void AST(u64 insn);
22 void ATOM_cas(u64 insn);
23 void ATOM(u64 insn);
24 void ATOMS_cas(u64 insn);
25 void ATOMS(u64 insn);
26 void B2R(u64 insn);
27 void BAR(u64 insn);
28 void BFE_reg(u64 insn);
29 void BFE_cbuf(u64 insn);
30 void BFE_imm(u64 insn);
31 void BFI_reg(u64 insn);
32 void BFI_rc(u64 insn);
33 void BFI_cr(u64 insn);
34 void BFI_imm(u64 insn);
35 void BPT(u64 insn);
36 void BRA(u64 insn);
37 void BRK(u64 insn);
38 void BRX(u64 insn);
39 void CAL(u64 insn);
40 void CCTL(u64 insn);
41 void CCTLL(u64 insn);
42 void CONT(u64 insn);
43 void CS2R(u64 insn);
44 void CSET(u64 insn);
45 void CSETP(u64 insn);
46 void DADD_reg(u64 insn);
47 void DADD_cbuf(u64 insn);
48 void DADD_imm(u64 insn);
49 void DEPBAR(u64 insn);
50 void DFMA_reg(u64 insn);
51 void DFMA_rc(u64 insn);
52 void DFMA_cr(u64 insn);
53 void DFMA_imm(u64 insn);
54 void DMNMX_reg(u64 insn);
55 void DMNMX_cbuf(u64 insn);
56 void DMNMX_imm(u64 insn);
57 void DMUL_reg(u64 insn);
58 void DMUL_cbuf(u64 insn);
59 void DMUL_imm(u64 insn);
60 void DSET_reg(u64 insn);
61 void DSET_cbuf(u64 insn);
62 void DSET_imm(u64 insn);
63 void DSETP_reg(u64 insn);
64 void DSETP_cbuf(u64 insn);
65 void DSETP_imm(u64 insn);
66 void EXIT(u64 insn);
67 void F2F_reg(u64 insn);
68 void F2F_cbuf(u64 insn);
69 void F2F_imm(u64 insn);
70 void F2I_reg(u64 insn);
71 void F2I_cbuf(u64 insn);
72 void F2I_imm(u64 insn);
73 void FADD_reg(u64 insn);
74 void FADD_cbuf(u64 insn);
75 void FADD_imm(u64 insn);
76 void FADD32I(u64 insn);
77 void FCHK_reg(u64 insn);
78 void FCHK_cbuf(u64 insn);
79 void FCHK_imm(u64 insn);
80 void FCMP_reg(u64 insn);
81 void FCMP_rc(u64 insn);
82 void FCMP_cr(u64 insn);
83 void FCMP_imm(u64 insn);
84 void FFMA_reg(u64 insn);
85 void FFMA_rc(u64 insn);
86 void FFMA_cr(u64 insn);
87 void FFMA_imm(u64 insn);
88 void FFMA32I(u64 insn);
89 void FLO_reg(u64 insn);
90 void FLO_cbuf(u64 insn);
91 void FLO_imm(u64 insn);
92 void FMNMX_reg(u64 insn);
93 void FMNMX_cbuf(u64 insn);
94 void FMNMX_imm(u64 insn);
95 void FMUL_reg(u64 insn);
96 void FMUL_cbuf(u64 insn);
97 void FMUL_imm(u64 insn);
98 void FMUL32I(u64 insn);
99 void FSET_reg(u64 insn);
100 void FSET_cbuf(u64 insn);
101 void FSET_imm(u64 insn);
102 void FSETP_reg(u64 insn);
103 void FSETP_cbuf(u64 insn);
104 void FSETP_imm(u64 insn);
105 void FSWZADD(u64 insn);
106 void GETCRSPTR(u64 insn);
107 void GETLMEMBASE(u64 insn);
108 void HADD2_reg(u64 insn);
109 void HADD2_cbuf(u64 insn);
110 void HADD2_imm(u64 insn);
111 void HADD2_32I(u64 insn);
112 void HFMA2_reg(u64 insn);
113 void HFMA2_rc(u64 insn);
114 void HFMA2_cr(u64 insn);
115 void HFMA2_imm(u64 insn);
116 void HFMA2_32I(u64 insn);
117 void HMUL2_reg(u64 insn);
118 void HMUL2_cbuf(u64 insn);
119 void HMUL2_imm(u64 insn);
120 void HMUL2_32I(u64 insn);
121 void HSET2_reg(u64 insn);
122 void HSET2_cbuf(u64 insn);
123 void HSET2_imm(u64 insn);
124 void HSETP2_reg(u64 insn);
125 void HSETP2_cbuf(u64 insn);
126 void HSETP2_imm(u64 insn);
127 void I2F_reg(u64 insn);
128 void I2F_cbuf(u64 insn);
129 void I2F_imm(u64 insn);
130 void I2I_reg(u64 insn);
131 void I2I_cbuf(u64 insn);
132 void I2I_imm(u64 insn);
133 void IADD_reg(u64 insn);
134 void IADD_cbuf(u64 insn);
135 void IADD_imm(u64 insn);
136 void IADD3_reg(u64 insn);
137 void IADD3_cbuf(u64 insn);
138 void IADD3_imm(u64 insn);
139 void IADD32I(u64 insn);
140 void ICMP_reg(u64 insn);
141 void ICMP_rc(u64 insn);
142 void ICMP_cr(u64 insn);
143 void ICMP_imm(u64 insn);
144 void IDE(u64 insn);
145 void IDP_reg(u64 insn);
146 void IDP_imm(u64 insn);
147 void IMAD_reg(u64 insn);
148 void IMAD_rc(u64 insn);
149 void IMAD_cr(u64 insn);
150 void IMAD_imm(u64 insn);
151 void IMAD32I(u64 insn);
152 void IMADSP_reg(u64 insn);
153 void IMADSP_rc(u64 insn);
154 void IMADSP_cr(u64 insn);
155 void IMADSP_imm(u64 insn);
156 void IMNMX_reg(u64 insn);
157 void IMNMX_cbuf(u64 insn);
158 void IMNMX_imm(u64 insn);
159 void IMUL_reg(u64 insn);
160 void IMUL_cbuf(u64 insn);
161 void IMUL_imm(u64 insn);
162 void IMUL32I(u64 insn);
163 void IPA(u64 insn);
164 void ISBERD(u64 insn);
165 void ISCADD_reg(u64 insn);
166 void ISCADD_cbuf(u64 insn);
167 void ISCADD_imm(u64 insn);
168 void ISCADD32I(u64 insn);
169 void ISET_reg(u64 insn);
170 void ISET_cbuf(u64 insn);
171 void ISET_imm(u64 insn);
172 void ISETP_reg(u64 insn);
173 void ISETP_cbuf(u64 insn);
174 void ISETP_imm(u64 insn);
175 void JCAL(u64 insn);
176 void JMP(u64 insn);
177 void JMX(u64 insn);
178 void KIL(u64 insn);
179 void LD(u64 insn);
180 void LDC(u64 insn);
181 void LDG(u64 insn);
182 void LDL(u64 insn);
183 void LDS(u64 insn);
184 void LEA_hi_reg(u64 insn);
185 void LEA_hi_cbuf(u64 insn);
186 void LEA_lo_reg(u64 insn);
187 void LEA_lo_cbuf(u64 insn);
188 void LEA_lo_imm(u64 insn);
189 void LEPC(u64 insn);
190 void LONGJMP(u64 insn);
191 void LOP_reg(u64 insn);
192 void LOP_cbuf(u64 insn);
193 void LOP_imm(u64 insn);
194 void LOP3_reg(u64 insn);
195 void LOP3_cbuf(u64 insn);
196 void LOP3_imm(u64 insn);
197 void LOP32I(u64 insn);
198 void MEMBAR(u64 insn);
199 void MOV_reg(u64 insn);
200 void MOV_cbuf(u64 insn);
201 void MOV_imm(u64 insn);
202 void MOV32I(u64 insn);
203 void MUFU(u64 insn);
204 void NOP(u64 insn);
205 void OUT_reg(u64 insn);
206 void OUT_cbuf(u64 insn);
207 void OUT_imm(u64 insn);
208 void P2R_reg(u64 insn);
209 void P2R_cbuf(u64 insn);
210 void P2R_imm(u64 insn);
211 void PBK(u64 insn);
212 void PCNT(u64 insn);
213 void PEXIT(u64 insn);
214 void PIXLD(u64 insn);
215 void PLONGJMP(u64 insn);
216 void POPC_reg(u64 insn);
217 void POPC_cbuf(u64 insn);
218 void POPC_imm(u64 insn);
219 void PRET(u64 insn);
220 void PRMT_reg(u64 insn);
221 void PRMT_rc(u64 insn);
222 void PRMT_cr(u64 insn);
223 void PRMT_imm(u64 insn);
224 void PSET(u64 insn);
225 void PSETP(u64 insn);
226 void R2B(u64 insn);
227 void R2P_reg(u64 insn);
228 void R2P_cbuf(u64 insn);
229 void R2P_imm(u64 insn);
230 void RAM(u64 insn);
231 void RED(u64 insn);
232 void RET(u64 insn);
233 void RRO_reg(u64 insn);
234 void RRO_cbuf(u64 insn);
235 void RRO_imm(u64 insn);
236 void RTT(u64 insn);
237 void S2R(u64 insn);
238 void SAM(u64 insn);
239 void SEL_reg(u64 insn);
240 void SEL_cbuf(u64 insn);
241 void SEL_imm(u64 insn);
242 void SETCRSPTR(u64 insn);
243 void SETLMEMBASE(u64 insn);
244 void SHF_l_reg(u64 insn);
245 void SHF_l_imm(u64 insn);
246 void SHF_r_reg(u64 insn);
247 void SHF_r_imm(u64 insn);
248 void SHFL(u64 insn);
249 void SHL_reg(u64 insn);
250 void SHL_cbuf(u64 insn);
251 void SHL_imm(u64 insn);
252 void SHR_reg(u64 insn);
253 void SHR_cbuf(u64 insn);
254 void SHR_imm(u64 insn);
255 void SSY(u64 insn);
256 void ST(u64 insn);
257 void STG(u64 insn);
258 void STL(u64 insn);
259 void STP(u64 insn);
260 void STS(u64 insn);
261 void SUATOM_cas(u64 insn);
262 void SULD(u64 insn);
263 void SURED(u64 insn);
264 void SUST(u64 insn);
265 void SYNC(u64 insn);
266 void TEX(u64 insn);
267 void TEX_b(u64 insn);
268 void TEXS(u64 insn);
269 void TLD(u64 insn);
270 void TLD_b(u64 insn);
271 void TLD4(u64 insn);
272 void TLD4_b(u64 insn);
273 void TLD4S(u64 insn);
274 void TLDS(u64 insn);
275 void TMML(u64 insn);
276 void TMML_b(u64 insn);
277 void TXA(u64 insn);
278 void TXD(u64 insn);
279 void TXD_b(u64 insn);
280 void TXQ(u64 insn);
281 void TXQ_b(u64 insn);
282 void VABSDIFF(u64 insn);
283 void VABSDIFF4(u64 insn);
284 void VADD(u64 insn);
285 void VMAD(u64 insn);
286 void VMNMX(u64 insn);
287 void VOTE(u64 insn);
288 void VOTE_vtg(u64 insn);
289 void VSET(u64 insn);
290 void VSETP(u64 insn);
291 void VSHL(u64 insn);
292 void VSHR(u64 insn);
293 void XMAD_reg(u64 insn);
294 void XMAD_rc(u64 insn);
295 void XMAD_cr(u64 insn);
296 void XMAD_imm(u64 insn);
297
298 [[nodiscard]] IR::U32 X(IR::Reg reg);
299 void X(IR::Reg dest_reg, const IR::U32& value);
300
301 [[nodiscard]] IR::U32 GetCbuf(u64 insn);
302
303 [[nodiscard]] IR::U32 GetImm(u64 insn);
304
305 void SetZFlag(const IR::U1& value);
306 void SetSFlag(const IR::U1& value);
307 void SetCFlag(const IR::U1& value);
308 void SetOFlag(const IR::U1& value);
309
310 void ResetZero();
311 void ResetSFlag();
312 void ResetCFlag();
313 void ResetOFlag();
314};
315
316} // namespace Shader::Maxwell
diff --git a/src/shader_recompiler/frontend/maxwell/translate/impl/load_store_attribute.cpp b/src/shader_recompiler/frontend/maxwell/translate/impl/load_store_attribute.cpp
new file mode 100644
index 000000000..23512db1a
--- /dev/null
+++ b/src/shader_recompiler/frontend/maxwell/translate/impl/load_store_attribute.cpp
@@ -0,0 +1,92 @@
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/exception.h"
8#include "shader_recompiler/frontend/maxwell/opcode.h"
9#include "shader_recompiler/frontend/maxwell/translate/impl/impl.h"
10
11namespace Shader::Maxwell {
12namespace {
13enum class InterpolationMode : u64 {
14 Pass = 0,
15 Multiply = 1,
16 Constant = 2,
17 Sc = 3,
18};
19
20enum class SampleMode : u64 {
21 Default = 0,
22 Centroid = 1,
23 Offset = 2,
24};
25} // Anonymous namespace
26
27void TranslatorVisitor::IPA(u64 insn) {
28 // IPA is the instruction used to read varyings from a fragment shader.
29 // gl_FragCoord is mapped to the gl_Position attribute.
30 // It yields unknown results when used outside of the fragment shader stage.
31 union {
32 u64 raw;
33 BitField<0, 8, IR::Reg> dest_reg;
34 BitField<8, 8, IR::Reg> index_reg;
35 BitField<20, 8, IR::Reg> multiplier;
36 BitField<30, 8, IR::Attribute> attribute;
37 BitField<38, 1, u64> idx;
38 BitField<51, 1, u64> sat;
39 BitField<52, 2, SampleMode> sample_mode;
40 BitField<54, 2, InterpolationMode> interpolation_mode;
41 } const ipa{insn};
42
43 // Indexed IPAs are used for indexed varyings.
44 // For example:
45 //
46 // in vec4 colors[4];
47 // uniform int idx;
48 // void main() {
49 // gl_FragColor = colors[idx];
50 // }
51 const bool is_indexed{ipa.idx != 0 && ipa.index_reg != IR::Reg::RZ};
52 if (is_indexed) {
53 throw NotImplementedException("IPA.IDX");
54 }
55
56 const IR::Attribute attribute{ipa.attribute};
57 IR::U32 value{ir.GetAttribute(attribute)};
58 if (IR::IsGeneric(attribute)) {
59 // const bool is_perspective{UnimplementedReadHeader(GenericAttributeIndex(attribute))};
60 const bool is_perspective{false};
61 if (is_perspective) {
62 const IR::U32 rcp_position_w{ir.FPRecip(ir.GetAttribute(IR::Attribute::PositionW))};
63 value = ir.FPMul(value, rcp_position_w);
64 }
65 }
66
67 switch (ipa.interpolation_mode) {
68 case InterpolationMode::Pass:
69 break;
70 case InterpolationMode::Multiply:
71 value = ir.FPMul(value, ir.GetReg(ipa.multiplier));
72 break;
73 case InterpolationMode::Constant:
74 throw NotImplementedException("IPA.CONSTANT");
75 case InterpolationMode::Sc:
76 throw NotImplementedException("IPA.SC");
77 }
78
79 // Saturated IPAs are generally generated out of clamped varyings.
80 // For example: clamp(some_varying, 0.0, 1.0)
81 const bool is_saturated{ipa.sat != 0};
82 if (is_saturated) {
83 if (attribute == IR::Attribute::FrontFace) {
84 throw NotImplementedException("IPA.SAT on FrontFace");
85 }
86 value = ir.FPSaturate(value);
87 }
88
89 ir.SetReg(ipa.dest_reg, value);
90}
91
92} // namespace Shader::Maxwell
diff --git a/src/shader_recompiler/frontend/maxwell/translate/impl/load_store_memory.cpp b/src/shader_recompiler/frontend/maxwell/translate/impl/load_store_memory.cpp
new file mode 100644
index 000000000..d8fd387cf
--- /dev/null
+++ b/src/shader_recompiler/frontend/maxwell/translate/impl/load_store_memory.cpp
@@ -0,0 +1,90 @@
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/exception.h"
8#include "shader_recompiler/frontend/maxwell/opcode.h"
9#include "shader_recompiler/frontend/maxwell/translate/impl/impl.h"
10
11namespace Shader::Maxwell {
12namespace {
13enum class StoreSize : u64 {
14 U8,
15 S8,
16 U16,
17 S16,
18 B32,
19 B64,
20 B128,
21};
22
23// See Table 28 in https://docs.nvidia.com/cuda/parallel-thread-execution/index.html
24enum class StoreCache : u64 {
25 WB, // Cache write-back all coherent levels
26 CG, // Cache at global level
27 CS, // Cache streaming, likely to be accessed once
28 WT, // Cache write-through (to system memory)
29};
30} // Anonymous namespace
31
32void TranslatorVisitor::STG(u64 insn) {
33 // STG stores registers into global memory.
34 union {
35 u64 raw;
36 BitField<0, 8, IR::Reg> data_reg;
37 BitField<8, 8, IR::Reg> addr_reg;
38 BitField<45, 1, u64> e;
39 BitField<46, 2, StoreCache> cache;
40 BitField<48, 3, StoreSize> size;
41 } const stg{insn};
42
43 const IR::U64 address{[&]() -> IR::U64 {
44 if (stg.e == 0) {
45 // STG without .E uses a 32-bit pointer, zero-extend it
46 return ir.ConvertU(64, X(stg.addr_reg));
47 }
48 if (!IR::IsAligned(stg.addr_reg, 2)) {
49 throw NotImplementedException("Unaligned address register");
50 }
51 // Pack two registers to build the 32-bit address
52 return ir.PackUint2x32(ir.CompositeConstruct(X(stg.addr_reg), X(stg.addr_reg + 1)));
53 }()};
54
55 switch (stg.size) {
56 case StoreSize::U8:
57 ir.WriteGlobalU8(address, X(stg.data_reg));
58 break;
59 case StoreSize::S8:
60 ir.WriteGlobalS8(address, X(stg.data_reg));
61 break;
62 case StoreSize::U16:
63 ir.WriteGlobalU16(address, X(stg.data_reg));
64 break;
65 case StoreSize::S16:
66 ir.WriteGlobalS16(address, X(stg.data_reg));
67 break;
68 case StoreSize::B32:
69 ir.WriteGlobal32(address, X(stg.data_reg));
70 break;
71 case StoreSize::B64: {
72 if (!IR::IsAligned(stg.data_reg, 2)) {
73 throw NotImplementedException("Unaligned data registers");
74 }
75 const IR::Value vector{ir.CompositeConstruct(X(stg.data_reg), X(stg.data_reg + 1))};
76 ir.WriteGlobal64(address, vector);
77 break;
78 }
79 case StoreSize::B128:
80 if (!IR::IsAligned(stg.data_reg, 4)) {
81 throw NotImplementedException("Unaligned data registers");
82 }
83 const IR::Value vector{ir.CompositeConstruct(X(stg.data_reg), X(stg.data_reg + 1),
84 X(stg.data_reg + 2), X(stg.data_reg + 3))};
85 ir.WriteGlobal128(address, vector);
86 break;
87 }
88}
89
90} // 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
new file mode 100644
index 000000000..c907c1ffb
--- /dev/null
+++ b/src/shader_recompiler/frontend/maxwell/translate/impl/not_implemented.cpp
@@ -0,0 +1,1105 @@
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/common_types.h"
6#include "shader_recompiler/exception.h"
7#include "shader_recompiler/frontend/maxwell/opcode.h"
8#include "shader_recompiler/frontend/maxwell/translate/impl/impl.h"
9
10#include "shader_recompiler/ir_opt/passes.h"
11
12namespace Shader::Maxwell {
13
14[[maybe_unused]] static inline void DumpOptimized(IR::Block& block) {
15 auto raw{IR::DumpBlock(block)};
16
17 Optimization::GetSetElimination(block);
18 Optimization::DeadCodeEliminationPass(block);
19 Optimization::IdentityRemovalPass(block);
20 auto dumped{IR::DumpBlock(block)};
21
22 fmt::print(stderr, "{}", dumped);
23}
24
25[[noreturn]] static void ThrowNotImplemented(Opcode opcode) {
26 throw NotImplementedException("Instruction {} is not implemented", opcode);
27}
28
29void TranslatorVisitor::AL2P(u64) {
30 ThrowNotImplemented(Opcode::AL2P);
31}
32
33void TranslatorVisitor::ALD(u64) {
34 ThrowNotImplemented(Opcode::ALD);
35}
36
37void TranslatorVisitor::AST(u64) {
38 ThrowNotImplemented(Opcode::AST);
39}
40
41void TranslatorVisitor::ATOM_cas(u64) {
42 ThrowNotImplemented(Opcode::ATOM_cas);
43}
44
45void TranslatorVisitor::ATOM(u64) {
46 ThrowNotImplemented(Opcode::ATOM);
47}
48
49void TranslatorVisitor::ATOMS_cas(u64) {
50 ThrowNotImplemented(Opcode::ATOMS_cas);
51}
52
53void TranslatorVisitor::ATOMS(u64) {
54 ThrowNotImplemented(Opcode::ATOMS);
55}
56
57void TranslatorVisitor::B2R(u64) {
58 ThrowNotImplemented(Opcode::B2R);
59}
60
61void TranslatorVisitor::BAR(u64) {
62 ThrowNotImplemented(Opcode::BAR);
63}
64
65void TranslatorVisitor::BFE_reg(u64) {
66 ThrowNotImplemented(Opcode::BFE_reg);
67}
68
69void TranslatorVisitor::BFE_cbuf(u64) {
70 ThrowNotImplemented(Opcode::BFE_cbuf);
71}
72
73void TranslatorVisitor::BFE_imm(u64) {
74 ThrowNotImplemented(Opcode::BFE_imm);
75}
76
77void TranslatorVisitor::BFI_reg(u64) {
78 ThrowNotImplemented(Opcode::BFI_reg);
79}
80
81void TranslatorVisitor::BFI_rc(u64) {
82 ThrowNotImplemented(Opcode::BFI_rc);
83}
84
85void TranslatorVisitor::BFI_cr(u64) {
86 ThrowNotImplemented(Opcode::BFI_cr);
87}
88
89void TranslatorVisitor::BFI_imm(u64) {
90 ThrowNotImplemented(Opcode::BFI_imm);
91}
92
93void TranslatorVisitor::BPT(u64) {
94 ThrowNotImplemented(Opcode::BPT);
95}
96
97void TranslatorVisitor::BRA(u64) {
98 ThrowNotImplemented(Opcode::BRA);
99}
100
101void TranslatorVisitor::BRK(u64) {
102 ThrowNotImplemented(Opcode::BRK);
103}
104
105void TranslatorVisitor::BRX(u64) {
106 ThrowNotImplemented(Opcode::BRX);
107}
108
109void TranslatorVisitor::CAL(u64) {
110 ThrowNotImplemented(Opcode::CAL);
111}
112
113void TranslatorVisitor::CCTL(u64) {
114 ThrowNotImplemented(Opcode::CCTL);
115}
116
117void TranslatorVisitor::CCTLL(u64) {
118 ThrowNotImplemented(Opcode::CCTLL);
119}
120
121void TranslatorVisitor::CONT(u64) {
122 ThrowNotImplemented(Opcode::CONT);
123}
124
125void TranslatorVisitor::CS2R(u64) {
126 ThrowNotImplemented(Opcode::CS2R);
127}
128
129void TranslatorVisitor::CSET(u64) {
130 ThrowNotImplemented(Opcode::CSET);
131}
132
133void TranslatorVisitor::CSETP(u64) {
134 ThrowNotImplemented(Opcode::CSETP);
135}
136
137void TranslatorVisitor::DADD_reg(u64) {
138 ThrowNotImplemented(Opcode::DADD_reg);
139}
140
141void TranslatorVisitor::DADD_cbuf(u64) {
142 ThrowNotImplemented(Opcode::DADD_cbuf);
143}
144
145void TranslatorVisitor::DADD_imm(u64) {
146 ThrowNotImplemented(Opcode::DADD_imm);
147}
148
149void TranslatorVisitor::DEPBAR(u64) {
150 ThrowNotImplemented(Opcode::DEPBAR);
151}
152
153void TranslatorVisitor::DFMA_reg(u64) {
154 ThrowNotImplemented(Opcode::DFMA_reg);
155}
156
157void TranslatorVisitor::DFMA_rc(u64) {
158 ThrowNotImplemented(Opcode::DFMA_rc);
159}
160
161void TranslatorVisitor::DFMA_cr(u64) {
162 ThrowNotImplemented(Opcode::DFMA_cr);
163}
164
165void TranslatorVisitor::DFMA_imm(u64) {
166 ThrowNotImplemented(Opcode::DFMA_imm);
167}
168
169void TranslatorVisitor::DMNMX_reg(u64) {
170 ThrowNotImplemented(Opcode::DMNMX_reg);
171}
172
173void TranslatorVisitor::DMNMX_cbuf(u64) {
174 ThrowNotImplemented(Opcode::DMNMX_cbuf);
175}
176
177void TranslatorVisitor::DMNMX_imm(u64) {
178 ThrowNotImplemented(Opcode::DMNMX_imm);
179}
180
181void TranslatorVisitor::DMUL_reg(u64) {
182 ThrowNotImplemented(Opcode::DMUL_reg);
183}
184
185void TranslatorVisitor::DMUL_cbuf(u64) {
186 ThrowNotImplemented(Opcode::DMUL_cbuf);
187}
188
189void TranslatorVisitor::DMUL_imm(u64) {
190 ThrowNotImplemented(Opcode::DMUL_imm);
191}
192
193void TranslatorVisitor::DSET_reg(u64) {
194 ThrowNotImplemented(Opcode::DSET_reg);
195}
196
197void TranslatorVisitor::DSET_cbuf(u64) {
198 ThrowNotImplemented(Opcode::DSET_cbuf);
199}
200
201void TranslatorVisitor::DSET_imm(u64) {
202 ThrowNotImplemented(Opcode::DSET_imm);
203}
204
205void TranslatorVisitor::DSETP_reg(u64) {
206 ThrowNotImplemented(Opcode::DSETP_reg);
207}
208
209void TranslatorVisitor::DSETP_cbuf(u64) {
210 ThrowNotImplemented(Opcode::DSETP_cbuf);
211}
212
213void TranslatorVisitor::DSETP_imm(u64) {
214 ThrowNotImplemented(Opcode::DSETP_imm);
215}
216
217void TranslatorVisitor::EXIT(u64) {
218 throw LogicError("Visting EXIT instruction");
219}
220
221void TranslatorVisitor::F2F_reg(u64) {
222 ThrowNotImplemented(Opcode::F2F_reg);
223}
224
225void TranslatorVisitor::F2F_cbuf(u64) {
226 ThrowNotImplemented(Opcode::F2F_cbuf);
227}
228
229void TranslatorVisitor::F2F_imm(u64) {
230 ThrowNotImplemented(Opcode::F2F_imm);
231}
232
233void TranslatorVisitor::FADD_reg(u64) {
234 ThrowNotImplemented(Opcode::FADD_reg);
235}
236
237void TranslatorVisitor::FADD_cbuf(u64) {
238 ThrowNotImplemented(Opcode::FADD_cbuf);
239}
240
241void TranslatorVisitor::FADD_imm(u64) {
242 ThrowNotImplemented(Opcode::FADD_imm);
243}
244
245void TranslatorVisitor::FADD32I(u64) {
246 ThrowNotImplemented(Opcode::FADD32I);
247}
248
249void TranslatorVisitor::FCHK_reg(u64) {
250 ThrowNotImplemented(Opcode::FCHK_reg);
251}
252
253void TranslatorVisitor::FCHK_cbuf(u64) {
254 ThrowNotImplemented(Opcode::FCHK_cbuf);
255}
256
257void TranslatorVisitor::FCHK_imm(u64) {
258 ThrowNotImplemented(Opcode::FCHK_imm);
259}
260
261void TranslatorVisitor::FCMP_reg(u64) {
262 ThrowNotImplemented(Opcode::FCMP_reg);
263}
264
265void TranslatorVisitor::FCMP_rc(u64) {
266 ThrowNotImplemented(Opcode::FCMP_rc);
267}
268
269void TranslatorVisitor::FCMP_cr(u64) {
270 ThrowNotImplemented(Opcode::FCMP_cr);
271}
272
273void TranslatorVisitor::FCMP_imm(u64) {
274 ThrowNotImplemented(Opcode::FCMP_imm);
275}
276
277void TranslatorVisitor::FFMA_reg(u64) {
278 ThrowNotImplemented(Opcode::FFMA_reg);
279}
280
281void TranslatorVisitor::FFMA_rc(u64) {
282 ThrowNotImplemented(Opcode::FFMA_rc);
283}
284
285void TranslatorVisitor::FFMA_cr(u64) {
286 ThrowNotImplemented(Opcode::FFMA_cr);
287}
288
289void TranslatorVisitor::FFMA_imm(u64) {
290 ThrowNotImplemented(Opcode::FFMA_imm);
291}
292
293void TranslatorVisitor::FFMA32I(u64) {
294 ThrowNotImplemented(Opcode::FFMA32I);
295}
296
297void TranslatorVisitor::FLO_reg(u64) {
298 ThrowNotImplemented(Opcode::FLO_reg);
299}
300
301void TranslatorVisitor::FLO_cbuf(u64) {
302 ThrowNotImplemented(Opcode::FLO_cbuf);
303}
304
305void TranslatorVisitor::FLO_imm(u64) {
306 ThrowNotImplemented(Opcode::FLO_imm);
307}
308
309void TranslatorVisitor::FMNMX_reg(u64) {
310 ThrowNotImplemented(Opcode::FMNMX_reg);
311}
312
313void TranslatorVisitor::FMNMX_cbuf(u64) {
314 ThrowNotImplemented(Opcode::FMNMX_cbuf);
315}
316
317void TranslatorVisitor::FMNMX_imm(u64) {
318 ThrowNotImplemented(Opcode::FMNMX_imm);
319}
320
321void TranslatorVisitor::FMUL_reg(u64) {
322 ThrowNotImplemented(Opcode::FMUL_reg);
323}
324
325void TranslatorVisitor::FMUL_cbuf(u64) {
326 ThrowNotImplemented(Opcode::FMUL_cbuf);
327}
328
329void TranslatorVisitor::FMUL_imm(u64) {
330 ThrowNotImplemented(Opcode::FMUL_imm);
331}
332
333void TranslatorVisitor::FMUL32I(u64) {
334 ThrowNotImplemented(Opcode::FMUL32I);
335}
336
337void TranslatorVisitor::FSET_reg(u64) {
338 ThrowNotImplemented(Opcode::FSET_reg);
339}
340
341void TranslatorVisitor::FSET_cbuf(u64) {
342 ThrowNotImplemented(Opcode::FSET_cbuf);
343}
344
345void TranslatorVisitor::FSET_imm(u64) {
346 ThrowNotImplemented(Opcode::FSET_imm);
347}
348
349void TranslatorVisitor::FSETP_reg(u64) {
350 ThrowNotImplemented(Opcode::FSETP_reg);
351}
352
353void TranslatorVisitor::FSETP_cbuf(u64) {
354 ThrowNotImplemented(Opcode::FSETP_cbuf);
355}
356
357void TranslatorVisitor::FSETP_imm(u64) {
358 ThrowNotImplemented(Opcode::FSETP_imm);
359}
360
361void TranslatorVisitor::FSWZADD(u64) {
362 ThrowNotImplemented(Opcode::FSWZADD);
363}
364
365void TranslatorVisitor::GETCRSPTR(u64) {
366 ThrowNotImplemented(Opcode::GETCRSPTR);
367}
368
369void TranslatorVisitor::GETLMEMBASE(u64) {
370 ThrowNotImplemented(Opcode::GETLMEMBASE);
371}
372
373void TranslatorVisitor::HADD2_reg(u64) {
374 ThrowNotImplemented(Opcode::HADD2_reg);
375}
376
377void TranslatorVisitor::HADD2_cbuf(u64) {
378 ThrowNotImplemented(Opcode::HADD2_cbuf);
379}
380
381void TranslatorVisitor::HADD2_imm(u64) {
382 ThrowNotImplemented(Opcode::HADD2_imm);
383}
384
385void TranslatorVisitor::HADD2_32I(u64) {
386 ThrowNotImplemented(Opcode::HADD2_32I);
387}
388
389void TranslatorVisitor::HFMA2_reg(u64) {
390 ThrowNotImplemented(Opcode::HFMA2_reg);
391}
392
393void TranslatorVisitor::HFMA2_rc(u64) {
394 ThrowNotImplemented(Opcode::HFMA2_rc);
395}
396
397void TranslatorVisitor::HFMA2_cr(u64) {
398 ThrowNotImplemented(Opcode::HFMA2_cr);
399}
400
401void TranslatorVisitor::HFMA2_imm(u64) {
402 ThrowNotImplemented(Opcode::HFMA2_imm);
403}
404
405void TranslatorVisitor::HFMA2_32I(u64) {
406 ThrowNotImplemented(Opcode::HFMA2_32I);
407}
408
409void TranslatorVisitor::HMUL2_reg(u64) {
410 ThrowNotImplemented(Opcode::HMUL2_reg);
411}
412
413void TranslatorVisitor::HMUL2_cbuf(u64) {
414 ThrowNotImplemented(Opcode::HMUL2_cbuf);
415}
416
417void TranslatorVisitor::HMUL2_imm(u64) {
418 ThrowNotImplemented(Opcode::HMUL2_imm);
419}
420
421void TranslatorVisitor::HMUL2_32I(u64) {
422 ThrowNotImplemented(Opcode::HMUL2_32I);
423}
424
425void TranslatorVisitor::HSET2_reg(u64) {
426 ThrowNotImplemented(Opcode::HSET2_reg);
427}
428
429void TranslatorVisitor::HSET2_cbuf(u64) {
430 ThrowNotImplemented(Opcode::HSET2_cbuf);
431}
432
433void TranslatorVisitor::HSET2_imm(u64) {
434 ThrowNotImplemented(Opcode::HSET2_imm);
435}
436
437void TranslatorVisitor::HSETP2_reg(u64) {
438 ThrowNotImplemented(Opcode::HSETP2_reg);
439}
440
441void TranslatorVisitor::HSETP2_cbuf(u64) {
442 ThrowNotImplemented(Opcode::HSETP2_cbuf);
443}
444
445void TranslatorVisitor::HSETP2_imm(u64) {
446 ThrowNotImplemented(Opcode::HSETP2_imm);
447}
448
449void TranslatorVisitor::I2F_reg(u64) {
450 ThrowNotImplemented(Opcode::I2F_reg);
451}
452
453void TranslatorVisitor::I2F_cbuf(u64) {
454 ThrowNotImplemented(Opcode::I2F_cbuf);
455}
456
457void TranslatorVisitor::I2F_imm(u64) {
458 ThrowNotImplemented(Opcode::I2F_imm);
459}
460
461void TranslatorVisitor::I2I_reg(u64) {
462 ThrowNotImplemented(Opcode::I2I_reg);
463}
464
465void TranslatorVisitor::I2I_cbuf(u64) {
466 ThrowNotImplemented(Opcode::I2I_cbuf);
467}
468
469void TranslatorVisitor::I2I_imm(u64) {
470 ThrowNotImplemented(Opcode::I2I_imm);
471}
472
473void TranslatorVisitor::IADD_reg(u64) {
474 ThrowNotImplemented(Opcode::IADD_reg);
475}
476
477void TranslatorVisitor::IADD_cbuf(u64) {
478 ThrowNotImplemented(Opcode::IADD_cbuf);
479}
480
481void TranslatorVisitor::IADD_imm(u64) {
482 ThrowNotImplemented(Opcode::IADD_imm);
483}
484
485void TranslatorVisitor::IADD3_reg(u64) {
486 ThrowNotImplemented(Opcode::IADD3_reg);
487}
488
489void TranslatorVisitor::IADD3_cbuf(u64) {
490 ThrowNotImplemented(Opcode::IADD3_cbuf);
491}
492
493void TranslatorVisitor::IADD3_imm(u64) {
494 ThrowNotImplemented(Opcode::IADD3_imm);
495}
496
497void TranslatorVisitor::IADD32I(u64) {
498 ThrowNotImplemented(Opcode::IADD32I);
499}
500
501void TranslatorVisitor::ICMP_reg(u64) {
502 ThrowNotImplemented(Opcode::ICMP_reg);
503}
504
505void TranslatorVisitor::ICMP_rc(u64) {
506 ThrowNotImplemented(Opcode::ICMP_rc);
507}
508
509void TranslatorVisitor::ICMP_cr(u64) {
510 ThrowNotImplemented(Opcode::ICMP_cr);
511}
512
513void TranslatorVisitor::ICMP_imm(u64) {
514 ThrowNotImplemented(Opcode::ICMP_imm);
515}
516
517void TranslatorVisitor::IDE(u64) {
518 ThrowNotImplemented(Opcode::IDE);
519}
520
521void TranslatorVisitor::IDP_reg(u64) {
522 ThrowNotImplemented(Opcode::IDP_reg);
523}
524
525void TranslatorVisitor::IDP_imm(u64) {
526 ThrowNotImplemented(Opcode::IDP_imm);
527}
528
529void TranslatorVisitor::IMAD_reg(u64) {
530 ThrowNotImplemented(Opcode::IMAD_reg);
531}
532
533void TranslatorVisitor::IMAD_rc(u64) {
534 ThrowNotImplemented(Opcode::IMAD_rc);
535}
536
537void TranslatorVisitor::IMAD_cr(u64) {
538 ThrowNotImplemented(Opcode::IMAD_cr);
539}
540
541void TranslatorVisitor::IMAD_imm(u64) {
542 ThrowNotImplemented(Opcode::IMAD_imm);
543}
544
545void TranslatorVisitor::IMAD32I(u64) {
546 ThrowNotImplemented(Opcode::IMAD32I);
547}
548
549void TranslatorVisitor::IMADSP_reg(u64) {
550 ThrowNotImplemented(Opcode::IMADSP_reg);
551}
552
553void TranslatorVisitor::IMADSP_rc(u64) {
554 ThrowNotImplemented(Opcode::IMADSP_rc);
555}
556
557void TranslatorVisitor::IMADSP_cr(u64) {
558 ThrowNotImplemented(Opcode::IMADSP_cr);
559}
560
561void TranslatorVisitor::IMADSP_imm(u64) {
562 ThrowNotImplemented(Opcode::IMADSP_imm);
563}
564
565void TranslatorVisitor::IMNMX_reg(u64) {
566 ThrowNotImplemented(Opcode::IMNMX_reg);
567}
568
569void TranslatorVisitor::IMNMX_cbuf(u64) {
570 ThrowNotImplemented(Opcode::IMNMX_cbuf);
571}
572
573void TranslatorVisitor::IMNMX_imm(u64) {
574 ThrowNotImplemented(Opcode::IMNMX_imm);
575}
576
577void TranslatorVisitor::IMUL_reg(u64) {
578 ThrowNotImplemented(Opcode::IMUL_reg);
579}
580
581void TranslatorVisitor::IMUL_cbuf(u64) {
582 ThrowNotImplemented(Opcode::IMUL_cbuf);
583}
584
585void TranslatorVisitor::IMUL_imm(u64) {
586 ThrowNotImplemented(Opcode::IMUL_imm);
587}
588
589void TranslatorVisitor::IMUL32I(u64) {
590 ThrowNotImplemented(Opcode::IMUL32I);
591}
592
593void TranslatorVisitor::ISBERD(u64) {
594 ThrowNotImplemented(Opcode::ISBERD);
595}
596
597void TranslatorVisitor::ISCADD_reg(u64) {
598 ThrowNotImplemented(Opcode::ISCADD_reg);
599}
600
601void TranslatorVisitor::ISCADD_cbuf(u64) {
602 ThrowNotImplemented(Opcode::ISCADD_cbuf);
603}
604
605void TranslatorVisitor::ISCADD_imm(u64) {
606 ThrowNotImplemented(Opcode::ISCADD_imm);
607}
608
609void TranslatorVisitor::ISCADD32I(u64) {
610 ThrowNotImplemented(Opcode::ISCADD32I);
611}
612
613void TranslatorVisitor::ISET_reg(u64) {
614 ThrowNotImplemented(Opcode::ISET_reg);
615}
616
617void TranslatorVisitor::ISET_cbuf(u64) {
618 ThrowNotImplemented(Opcode::ISET_cbuf);
619}
620
621void TranslatorVisitor::ISET_imm(u64) {
622 ThrowNotImplemented(Opcode::ISET_imm);
623}
624
625void TranslatorVisitor::ISETP_reg(u64) {
626 ThrowNotImplemented(Opcode::ISETP_reg);
627}
628
629void TranslatorVisitor::ISETP_cbuf(u64) {
630 ThrowNotImplemented(Opcode::ISETP_cbuf);
631}
632
633void TranslatorVisitor::ISETP_imm(u64) {
634 ThrowNotImplemented(Opcode::ISETP_imm);
635}
636
637void TranslatorVisitor::JCAL(u64) {
638 ThrowNotImplemented(Opcode::JCAL);
639}
640
641void TranslatorVisitor::JMP(u64) {
642 ThrowNotImplemented(Opcode::JMP);
643}
644
645void TranslatorVisitor::JMX(u64) {
646 ThrowNotImplemented(Opcode::JMX);
647}
648
649void TranslatorVisitor::KIL(u64) {
650 ThrowNotImplemented(Opcode::KIL);
651}
652
653void TranslatorVisitor::LD(u64) {
654 ThrowNotImplemented(Opcode::LD);
655}
656
657void TranslatorVisitor::LDC(u64) {
658 ThrowNotImplemented(Opcode::LDC);
659}
660
661void TranslatorVisitor::LDG(u64) {
662 ThrowNotImplemented(Opcode::LDG);
663}
664
665void TranslatorVisitor::LDL(u64) {
666 ThrowNotImplemented(Opcode::LDL);
667}
668
669void TranslatorVisitor::LDS(u64) {
670 ThrowNotImplemented(Opcode::LDS);
671}
672
673void TranslatorVisitor::LEA_hi_reg(u64) {
674 ThrowNotImplemented(Opcode::LEA_hi_reg);
675}
676
677void TranslatorVisitor::LEA_hi_cbuf(u64) {
678 ThrowNotImplemented(Opcode::LEA_hi_cbuf);
679}
680
681void TranslatorVisitor::LEA_lo_reg(u64) {
682 ThrowNotImplemented(Opcode::LEA_lo_reg);
683}
684
685void TranslatorVisitor::LEA_lo_cbuf(u64) {
686 ThrowNotImplemented(Opcode::LEA_lo_cbuf);
687}
688
689void TranslatorVisitor::LEA_lo_imm(u64) {
690 ThrowNotImplemented(Opcode::LEA_lo_imm);
691}
692
693void TranslatorVisitor::LEPC(u64) {
694 ThrowNotImplemented(Opcode::LEPC);
695}
696
697void TranslatorVisitor::LONGJMP(u64) {
698 ThrowNotImplemented(Opcode::LONGJMP);
699}
700
701void TranslatorVisitor::LOP_reg(u64) {
702 ThrowNotImplemented(Opcode::LOP_reg);
703}
704
705void TranslatorVisitor::LOP_cbuf(u64) {
706 ThrowNotImplemented(Opcode::LOP_cbuf);
707}
708
709void TranslatorVisitor::LOP_imm(u64) {
710 ThrowNotImplemented(Opcode::LOP_imm);
711}
712
713void TranslatorVisitor::LOP3_reg(u64) {
714 ThrowNotImplemented(Opcode::LOP3_reg);
715}
716
717void TranslatorVisitor::LOP3_cbuf(u64) {
718 ThrowNotImplemented(Opcode::LOP3_cbuf);
719}
720
721void TranslatorVisitor::LOP3_imm(u64) {
722 ThrowNotImplemented(Opcode::LOP3_imm);
723}
724
725void TranslatorVisitor::LOP32I(u64) {
726 ThrowNotImplemented(Opcode::LOP32I);
727}
728
729void TranslatorVisitor::MEMBAR(u64) {
730 ThrowNotImplemented(Opcode::MEMBAR);
731}
732
733void TranslatorVisitor::MOV32I(u64) {
734 ThrowNotImplemented(Opcode::MOV32I);
735}
736
737void TranslatorVisitor::NOP(u64) {
738 ThrowNotImplemented(Opcode::NOP);
739}
740
741void TranslatorVisitor::OUT_reg(u64) {
742 ThrowNotImplemented(Opcode::OUT_reg);
743}
744
745void TranslatorVisitor::OUT_cbuf(u64) {
746 ThrowNotImplemented(Opcode::OUT_cbuf);
747}
748
749void TranslatorVisitor::OUT_imm(u64) {
750 ThrowNotImplemented(Opcode::OUT_imm);
751}
752
753void TranslatorVisitor::P2R_reg(u64) {
754 ThrowNotImplemented(Opcode::P2R_reg);
755}
756
757void TranslatorVisitor::P2R_cbuf(u64) {
758 ThrowNotImplemented(Opcode::P2R_cbuf);
759}
760
761void TranslatorVisitor::P2R_imm(u64) {
762 ThrowNotImplemented(Opcode::P2R_imm);
763}
764
765void TranslatorVisitor::PBK(u64) {
766 // PBK is a no-op
767}
768
769void TranslatorVisitor::PCNT(u64) {
770 ThrowNotImplemented(Opcode::PCNT);
771}
772
773void TranslatorVisitor::PEXIT(u64) {
774 ThrowNotImplemented(Opcode::PEXIT);
775}
776
777void TranslatorVisitor::PIXLD(u64) {
778 ThrowNotImplemented(Opcode::PIXLD);
779}
780
781void TranslatorVisitor::PLONGJMP(u64) {
782 ThrowNotImplemented(Opcode::PLONGJMP);
783}
784
785void TranslatorVisitor::POPC_reg(u64) {
786 ThrowNotImplemented(Opcode::POPC_reg);
787}
788
789void TranslatorVisitor::POPC_cbuf(u64) {
790 ThrowNotImplemented(Opcode::POPC_cbuf);
791}
792
793void TranslatorVisitor::POPC_imm(u64) {
794 ThrowNotImplemented(Opcode::POPC_imm);
795}
796
797void TranslatorVisitor::PRET(u64) {
798 ThrowNotImplemented(Opcode::PRET);
799}
800
801void TranslatorVisitor::PRMT_reg(u64) {
802 ThrowNotImplemented(Opcode::PRMT_reg);
803}
804
805void TranslatorVisitor::PRMT_rc(u64) {
806 ThrowNotImplemented(Opcode::PRMT_rc);
807}
808
809void TranslatorVisitor::PRMT_cr(u64) {
810 ThrowNotImplemented(Opcode::PRMT_cr);
811}
812
813void TranslatorVisitor::PRMT_imm(u64) {
814 ThrowNotImplemented(Opcode::PRMT_imm);
815}
816
817void TranslatorVisitor::PSET(u64) {
818 ThrowNotImplemented(Opcode::PSET);
819}
820
821void TranslatorVisitor::PSETP(u64) {
822 ThrowNotImplemented(Opcode::PSETP);
823}
824
825void TranslatorVisitor::R2B(u64) {
826 ThrowNotImplemented(Opcode::R2B);
827}
828
829void TranslatorVisitor::R2P_reg(u64) {
830 ThrowNotImplemented(Opcode::R2P_reg);
831}
832
833void TranslatorVisitor::R2P_cbuf(u64) {
834 ThrowNotImplemented(Opcode::R2P_cbuf);
835}
836
837void TranslatorVisitor::R2P_imm(u64) {
838 ThrowNotImplemented(Opcode::R2P_imm);
839}
840
841void TranslatorVisitor::RAM(u64) {
842 ThrowNotImplemented(Opcode::RAM);
843}
844
845void TranslatorVisitor::RED(u64) {
846 ThrowNotImplemented(Opcode::RED);
847}
848
849void TranslatorVisitor::RET(u64) {
850 ThrowNotImplemented(Opcode::RET);
851}
852
853void TranslatorVisitor::RRO_reg(u64) {
854 ThrowNotImplemented(Opcode::RRO_reg);
855}
856
857void TranslatorVisitor::RRO_cbuf(u64) {
858 ThrowNotImplemented(Opcode::RRO_cbuf);
859}
860
861void TranslatorVisitor::RRO_imm(u64) {
862 ThrowNotImplemented(Opcode::RRO_imm);
863}
864
865void TranslatorVisitor::RTT(u64) {
866 ThrowNotImplemented(Opcode::RTT);
867}
868
869void TranslatorVisitor::S2R(u64) {
870 ThrowNotImplemented(Opcode::S2R);
871}
872
873void TranslatorVisitor::SAM(u64) {
874 ThrowNotImplemented(Opcode::SAM);
875}
876
877void TranslatorVisitor::SEL_reg(u64) {
878 ThrowNotImplemented(Opcode::SEL_reg);
879}
880
881void TranslatorVisitor::SEL_cbuf(u64) {
882 ThrowNotImplemented(Opcode::SEL_cbuf);
883}
884
885void TranslatorVisitor::SEL_imm(u64) {
886 ThrowNotImplemented(Opcode::SEL_imm);
887}
888
889void TranslatorVisitor::SETCRSPTR(u64) {
890 ThrowNotImplemented(Opcode::SETCRSPTR);
891}
892
893void TranslatorVisitor::SETLMEMBASE(u64) {
894 ThrowNotImplemented(Opcode::SETLMEMBASE);
895}
896
897void TranslatorVisitor::SHF_l_reg(u64) {
898 ThrowNotImplemented(Opcode::SHF_l_reg);
899}
900
901void TranslatorVisitor::SHF_l_imm(u64) {
902 ThrowNotImplemented(Opcode::SHF_l_imm);
903}
904
905void TranslatorVisitor::SHF_r_reg(u64) {
906 ThrowNotImplemented(Opcode::SHF_r_reg);
907}
908
909void TranslatorVisitor::SHF_r_imm(u64) {
910 ThrowNotImplemented(Opcode::SHF_r_imm);
911}
912
913void TranslatorVisitor::SHFL(u64) {
914 ThrowNotImplemented(Opcode::SHFL);
915}
916
917void TranslatorVisitor::SHL_reg(u64) {
918 ThrowNotImplemented(Opcode::SHL_reg);
919}
920
921void TranslatorVisitor::SHL_cbuf(u64) {
922 ThrowNotImplemented(Opcode::SHL_cbuf);
923}
924
925void TranslatorVisitor::SHL_imm(u64) {
926 ThrowNotImplemented(Opcode::SHL_imm);
927}
928
929void TranslatorVisitor::SHR_reg(u64) {
930 ThrowNotImplemented(Opcode::SHR_reg);
931}
932
933void TranslatorVisitor::SHR_cbuf(u64) {
934 ThrowNotImplemented(Opcode::SHR_cbuf);
935}
936
937void TranslatorVisitor::SHR_imm(u64) {
938 ThrowNotImplemented(Opcode::SHR_imm);
939}
940
941void TranslatorVisitor::SSY(u64) {
942 ThrowNotImplemented(Opcode::SSY);
943}
944
945void TranslatorVisitor::ST(u64) {
946 ThrowNotImplemented(Opcode::ST);
947}
948
949void TranslatorVisitor::STL(u64) {
950 ThrowNotImplemented(Opcode::STL);
951}
952
953void TranslatorVisitor::STP(u64) {
954 ThrowNotImplemented(Opcode::STP);
955}
956
957void TranslatorVisitor::STS(u64) {
958 ThrowNotImplemented(Opcode::STS);
959}
960
961void TranslatorVisitor::SUATOM_cas(u64) {
962 ThrowNotImplemented(Opcode::SUATOM_cas);
963}
964
965void TranslatorVisitor::SULD(u64) {
966 ThrowNotImplemented(Opcode::SULD);
967}
968
969void TranslatorVisitor::SURED(u64) {
970 ThrowNotImplemented(Opcode::SURED);
971}
972
973void TranslatorVisitor::SUST(u64) {
974 ThrowNotImplemented(Opcode::SUST);
975}
976
977void TranslatorVisitor::SYNC(u64) {
978 ThrowNotImplemented(Opcode::SYNC);
979}
980
981void TranslatorVisitor::TEX(u64) {
982 ThrowNotImplemented(Opcode::TEX);
983}
984
985void TranslatorVisitor::TEX_b(u64) {
986 ThrowNotImplemented(Opcode::TEX_b);
987}
988
989void TranslatorVisitor::TEXS(u64) {
990 ThrowNotImplemented(Opcode::TEXS);
991}
992
993void TranslatorVisitor::TLD(u64) {
994 ThrowNotImplemented(Opcode::TLD);
995}
996
997void TranslatorVisitor::TLD_b(u64) {
998 ThrowNotImplemented(Opcode::TLD_b);
999}
1000
1001void TranslatorVisitor::TLD4(u64) {
1002 ThrowNotImplemented(Opcode::TLD4);
1003}
1004
1005void TranslatorVisitor::TLD4_b(u64) {
1006 ThrowNotImplemented(Opcode::TLD4_b);
1007}
1008
1009void TranslatorVisitor::TLD4S(u64) {
1010 ThrowNotImplemented(Opcode::TLD4S);
1011}
1012
1013void TranslatorVisitor::TLDS(u64) {
1014 ThrowNotImplemented(Opcode::TLDS);
1015}
1016
1017void TranslatorVisitor::TMML(u64) {
1018 ThrowNotImplemented(Opcode::TMML);
1019}
1020
1021void TranslatorVisitor::TMML_b(u64) {
1022 ThrowNotImplemented(Opcode::TMML_b);
1023}
1024
1025void TranslatorVisitor::TXA(u64) {
1026 ThrowNotImplemented(Opcode::TXA);
1027}
1028
1029void TranslatorVisitor::TXD(u64) {
1030 ThrowNotImplemented(Opcode::TXD);
1031}
1032
1033void TranslatorVisitor::TXD_b(u64) {
1034 ThrowNotImplemented(Opcode::TXD_b);
1035}
1036
1037void TranslatorVisitor::TXQ(u64) {
1038 ThrowNotImplemented(Opcode::TXQ);
1039}
1040
1041void TranslatorVisitor::TXQ_b(u64) {
1042 ThrowNotImplemented(Opcode::TXQ_b);
1043}
1044
1045void TranslatorVisitor::VABSDIFF(u64) {
1046 ThrowNotImplemented(Opcode::VABSDIFF);
1047}
1048
1049void TranslatorVisitor::VABSDIFF4(u64) {
1050 ThrowNotImplemented(Opcode::VABSDIFF4);
1051}
1052
1053void TranslatorVisitor::VADD(u64) {
1054 ThrowNotImplemented(Opcode::VADD);
1055}
1056
1057void TranslatorVisitor::VMAD(u64) {
1058 ThrowNotImplemented(Opcode::VMAD);
1059}
1060
1061void TranslatorVisitor::VMNMX(u64) {
1062 ThrowNotImplemented(Opcode::VMNMX);
1063}
1064
1065void TranslatorVisitor::VOTE(u64) {
1066 ThrowNotImplemented(Opcode::VOTE);
1067}
1068
1069void TranslatorVisitor::VOTE_vtg(u64) {
1070 ThrowNotImplemented(Opcode::VOTE_vtg);
1071}
1072
1073void TranslatorVisitor::VSET(u64) {
1074 ThrowNotImplemented(Opcode::VSET);
1075}
1076
1077void TranslatorVisitor::VSETP(u64) {
1078 ThrowNotImplemented(Opcode::VSETP);
1079}
1080
1081void TranslatorVisitor::VSHL(u64) {
1082 ThrowNotImplemented(Opcode::VSHL);
1083}
1084
1085void TranslatorVisitor::VSHR(u64) {
1086 ThrowNotImplemented(Opcode::VSHR);
1087}
1088
1089void TranslatorVisitor::XMAD_reg(u64) {
1090 ThrowNotImplemented(Opcode::XMAD_reg);
1091}
1092
1093void TranslatorVisitor::XMAD_rc(u64) {
1094 ThrowNotImplemented(Opcode::XMAD_rc);
1095}
1096
1097void TranslatorVisitor::XMAD_cr(u64) {
1098 ThrowNotImplemented(Opcode::XMAD_cr);
1099}
1100
1101void TranslatorVisitor::XMAD_imm(u64) {
1102 ThrowNotImplemented(Opcode::XMAD_imm);
1103}
1104
1105} // namespace Shader::Maxwell
diff --git a/src/shader_recompiler/frontend/maxwell/translate/impl/register_move.cpp b/src/shader_recompiler/frontend/maxwell/translate/impl/register_move.cpp
new file mode 100644
index 000000000..7fa35ba3a
--- /dev/null
+++ b/src/shader_recompiler/frontend/maxwell/translate/impl/register_move.cpp
@@ -0,0 +1,45 @@
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/exception.h"
8#include "shader_recompiler/frontend/maxwell/opcode.h"
9#include "shader_recompiler/frontend/maxwell/translate/impl/impl.h"
10
11namespace Shader::Maxwell {
12namespace {
13union MOV {
14 u64 raw;
15 BitField<0, 8, IR::Reg> dest_reg;
16 BitField<20, 8, IR::Reg> src_reg;
17 BitField<39, 4, u64> mask;
18};
19
20void CheckMask(MOV mov) {
21 if (mov.mask != 0xf) {
22 throw NotImplementedException("Non-full move mask");
23 }
24}
25} // Anonymous namespace
26
27void TranslatorVisitor::MOV_reg(u64 insn) {
28 const MOV mov{insn};
29 CheckMask(mov);
30 X(mov.dest_reg, X(mov.src_reg));
31}
32
33void TranslatorVisitor::MOV_cbuf(u64 insn) {
34 const MOV mov{insn};
35 CheckMask(mov);
36 X(mov.dest_reg, GetCbuf(insn));
37}
38
39void TranslatorVisitor::MOV_imm(u64 insn) {
40 const MOV mov{insn};
41 CheckMask(mov);
42 X(mov.dest_reg, GetImm(insn));
43}
44
45} // namespace Shader::Maxwell