summaryrefslogtreecommitdiff
path: root/src/shader_recompiler/frontend/ir
diff options
context:
space:
mode:
Diffstat (limited to 'src/shader_recompiler/frontend/ir')
-rw-r--r--src/shader_recompiler/frontend/ir/ir_emitter.cpp145
-rw-r--r--src/shader_recompiler/frontend/ir/ir_emitter.h14
-rw-r--r--src/shader_recompiler/frontend/ir/opcodes.inc13
3 files changed, 117 insertions, 55 deletions
diff --git a/src/shader_recompiler/frontend/ir/ir_emitter.cpp b/src/shader_recompiler/frontend/ir/ir_emitter.cpp
index 672836c0b..652f6949e 100644
--- a/src/shader_recompiler/frontend/ir/ir_emitter.cpp
+++ b/src/shader_recompiler/frontend/ir/ir_emitter.cpp
@@ -53,6 +53,10 @@ U64 IREmitter::Imm64(u64 value) const {
53 return U64{Value{value}}; 53 return U64{Value{value}};
54} 54}
55 55
56U64 IREmitter::Imm64(s64 value) const {
57 return U64{Value{static_cast<u64>(value)}};
58}
59
56F64 IREmitter::Imm64(f64 value) const { 60F64 IREmitter::Imm64(f64 value) const {
57 return F64{Value{value}}; 61 return F64{Value{value}};
58} 62}
@@ -363,7 +367,7 @@ U1 IREmitter::GetSparseFromOp(const Value& op) {
363} 367}
364 368
365F16F32F64 IREmitter::FPAdd(const F16F32F64& a, const F16F32F64& b, FpControl control) { 369F16F32F64 IREmitter::FPAdd(const F16F32F64& a, const F16F32F64& b, FpControl control) {
366 if (a.Type() != a.Type()) { 370 if (a.Type() != b.Type()) {
367 throw InvalidArgument("Mismatching types {} and {}", a.Type(), b.Type()); 371 throw InvalidArgument("Mismatching types {} and {}", a.Type(), b.Type());
368 } 372 }
369 switch (a.Type()) { 373 switch (a.Type()) {
@@ -974,8 +978,15 @@ U32U64 IREmitter::INeg(const U32U64& value) {
974 } 978 }
975} 979}
976 980
977U32 IREmitter::IAbs(const U32& value) { 981U32U64 IREmitter::IAbs(const U32U64& value) {
978 return Inst<U32>(Opcode::IAbs32, value); 982 switch (value.Type()) {
983 case Type::U32:
984 return Inst<U32>(Opcode::IAbs32, value);
985 case Type::U64:
986 return Inst<U64>(Opcode::IAbs64, value);
987 default:
988 ThrowInvalidType(value.Type());
989 }
979} 990}
980 991
981U32U64 IREmitter::ShiftLeftLogical(const U32U64& base, const U32& shift) { 992U32U64 IREmitter::ShiftLeftLogical(const U32U64& base, const U32& shift) {
@@ -1074,8 +1085,25 @@ U1 IREmitter::ILessThan(const U32& lhs, const U32& rhs, bool is_signed) {
1074 return Inst<U1>(is_signed ? Opcode::SLessThan : Opcode::ULessThan, lhs, rhs); 1085 return Inst<U1>(is_signed ? Opcode::SLessThan : Opcode::ULessThan, lhs, rhs);
1075} 1086}
1076 1087
1077U1 IREmitter::IEqual(const U32& lhs, const U32& rhs) { 1088U1 IREmitter::IEqual(const U32U64& lhs, const U32U64& rhs) {
1078 return Inst<U1>(Opcode::IEqual, lhs, rhs); 1089 if (lhs.Type() != rhs.Type()) {
1090 throw InvalidArgument("Mismatching types {} and {}", lhs.Type(), rhs.Type());
1091 }
1092 switch (lhs.Type()) {
1093 case Type::U32:
1094 return Inst<U1>(Opcode::IEqual, lhs, rhs);
1095 case Type::U64: {
1096 // Manually compare the unpacked values
1097 const Value lhs_vector{UnpackUint2x32(lhs)};
1098 const Value rhs_vector{UnpackUint2x32(rhs)};
1099 return LogicalAnd(IEqual(IR::U32{CompositeExtract(lhs_vector, 0)},
1100 IR::U32{CompositeExtract(rhs_vector, 0)}),
1101 IEqual(IR::U32{CompositeExtract(lhs_vector, 1)},
1102 IR::U32{CompositeExtract(rhs_vector, 1)}));
1103 }
1104 default:
1105 ThrowInvalidType(lhs.Type());
1106 }
1079} 1107}
1080 1108
1081U1 IREmitter::ILessThanEqual(const U32& lhs, const U32& rhs, bool is_signed) { 1109U1 IREmitter::ILessThanEqual(const U32& lhs, const U32& rhs, bool is_signed) {
@@ -1198,79 +1226,96 @@ U32U64 IREmitter::ConvertFToI(size_t bitsize, bool is_signed, const F16F32F64& v
1198 } 1226 }
1199} 1227}
1200 1228
1201F16F32F64 IREmitter::ConvertSToF(size_t bitsize, const U32U64& value) { 1229F16F32F64 IREmitter::ConvertSToF(size_t dest_bitsize, size_t src_bitsize, const Value& value) {
1202 switch (bitsize) { 1230 switch (dest_bitsize) {
1203 case 16: 1231 case 16:
1204 switch (value.Type()) { 1232 switch (src_bitsize) {
1205 case Type::U32: 1233 case 8:
1234 return Inst<F16>(Opcode::ConvertF16S8, value);
1235 case 16:
1236 return Inst<F16>(Opcode::ConvertF16S16, value);
1237 case 32:
1206 return Inst<F16>(Opcode::ConvertF16S32, value); 1238 return Inst<F16>(Opcode::ConvertF16S32, value);
1207 case Type::U64: 1239 case 64:
1208 return Inst<F16>(Opcode::ConvertF16S64, value); 1240 return Inst<F16>(Opcode::ConvertF16S64, value);
1209 default:
1210 ThrowInvalidType(value.Type());
1211 } 1241 }
1242 break;
1212 case 32: 1243 case 32:
1213 switch (value.Type()) { 1244 switch (src_bitsize) {
1214 case Type::U32: 1245 case 8:
1246 return Inst<F32>(Opcode::ConvertF32S8, value);
1247 case 16:
1248 return Inst<F32>(Opcode::ConvertF32S16, value);
1249 case 32:
1215 return Inst<F32>(Opcode::ConvertF32S32, value); 1250 return Inst<F32>(Opcode::ConvertF32S32, value);
1216 case Type::U64: 1251 case 64:
1217 return Inst<F32>(Opcode::ConvertF32S64, value); 1252 return Inst<F32>(Opcode::ConvertF32S64, value);
1218 default:
1219 ThrowInvalidType(value.Type());
1220 } 1253 }
1254 break;
1221 case 64: 1255 case 64:
1222 switch (value.Type()) { 1256 switch (src_bitsize) {
1223 case Type::U32: 1257 case 8:
1224 return Inst<F16>(Opcode::ConvertF64S32, value); 1258 return Inst<F64>(Opcode::ConvertF64S8, value);
1225 case Type::U64: 1259 case 16:
1226 return Inst<F16>(Opcode::ConvertF64S64, value); 1260 return Inst<F64>(Opcode::ConvertF64S16, value);
1227 default: 1261 case 32:
1228 ThrowInvalidType(value.Type()); 1262 return Inst<F64>(Opcode::ConvertF64S32, value);
1263 case 64:
1264 return Inst<F64>(Opcode::ConvertF64S64, value);
1229 } 1265 }
1230 default: 1266 break;
1231 throw InvalidArgument("Invalid destination bitsize {}", bitsize);
1232 } 1267 }
1268 throw InvalidArgument("Invalid bit size combination dst={} src={}", dest_bitsize, src_bitsize);
1233} 1269}
1234 1270
1235F16F32F64 IREmitter::ConvertUToF(size_t bitsize, const U32U64& value) { 1271F16F32F64 IREmitter::ConvertUToF(size_t dest_bitsize, size_t src_bitsize, const Value& value) {
1236 switch (bitsize) { 1272 switch (dest_bitsize) {
1237 case 16: 1273 case 16:
1238 switch (value.Type()) { 1274 switch (src_bitsize) {
1239 case Type::U32: 1275 case 8:
1276 return Inst<F16>(Opcode::ConvertF16U8, value);
1277 case 16:
1278 return Inst<F16>(Opcode::ConvertF16U16, value);
1279 case 32:
1240 return Inst<F16>(Opcode::ConvertF16U32, value); 1280 return Inst<F16>(Opcode::ConvertF16U32, value);
1241 case Type::U64: 1281 case 64:
1242 return Inst<F16>(Opcode::ConvertF16U64, value); 1282 return Inst<F16>(Opcode::ConvertF16U64, value);
1243 default:
1244 ThrowInvalidType(value.Type());
1245 } 1283 }
1284 break;
1246 case 32: 1285 case 32:
1247 switch (value.Type()) { 1286 switch (src_bitsize) {
1248 case Type::U32: 1287 case 8:
1288 return Inst<F32>(Opcode::ConvertF32U8, value);
1289 case 16:
1290 return Inst<F32>(Opcode::ConvertF32U16, value);
1291 case 32:
1249 return Inst<F32>(Opcode::ConvertF32U32, value); 1292 return Inst<F32>(Opcode::ConvertF32U32, value);
1250 case Type::U64: 1293 case 64:
1251 return Inst<F32>(Opcode::ConvertF32U64, value); 1294 return Inst<F32>(Opcode::ConvertF32U64, value);
1252 default:
1253 ThrowInvalidType(value.Type());
1254 } 1295 }
1296 break;
1255 case 64: 1297 case 64:
1256 switch (value.Type()) { 1298 switch (src_bitsize) {
1257 case Type::U32: 1299 case 8:
1258 return Inst<F16>(Opcode::ConvertF64U32, value); 1300 return Inst<F64>(Opcode::ConvertF64U8, value);
1259 case Type::U64: 1301 case 16:
1260 return Inst<F16>(Opcode::ConvertF64U64, value); 1302 return Inst<F64>(Opcode::ConvertF64U16, value);
1261 default: 1303 case 32:
1262 ThrowInvalidType(value.Type()); 1304 return Inst<F64>(Opcode::ConvertF64U32, value);
1305 case 64:
1306 return Inst<F64>(Opcode::ConvertF64U64, value);
1263 } 1307 }
1264 default: 1308 break;
1265 throw InvalidArgument("Invalid destination bitsize {}", bitsize);
1266 } 1309 }
1310 throw InvalidArgument("Invalid bit size combination dst={} src={}", dest_bitsize, src_bitsize);
1267} 1311}
1268 1312
1269F16F32F64 IREmitter::ConvertIToF(size_t bitsize, bool is_signed, const U32U64& value) { 1313F16F32F64 IREmitter::ConvertIToF(size_t dest_bitsize, size_t src_bitsize, bool is_signed,
1314 const Value& value) {
1270 if (is_signed) { 1315 if (is_signed) {
1271 return ConvertSToF(bitsize, value); 1316 return ConvertSToF(dest_bitsize, src_bitsize, value);
1272 } else { 1317 } else {
1273 return ConvertUToF(bitsize, value); 1318 return ConvertUToF(dest_bitsize, src_bitsize, value);
1274 } 1319 }
1275} 1320}
1276 1321
diff --git a/src/shader_recompiler/frontend/ir/ir_emitter.h b/src/shader_recompiler/frontend/ir/ir_emitter.h
index 72af5db37..8edb11154 100644
--- a/src/shader_recompiler/frontend/ir/ir_emitter.h
+++ b/src/shader_recompiler/frontend/ir/ir_emitter.h
@@ -29,6 +29,7 @@ public:
29 [[nodiscard]] U32 Imm32(s32 value) const; 29 [[nodiscard]] U32 Imm32(s32 value) const;
30 [[nodiscard]] F32 Imm32(f32 value) const; 30 [[nodiscard]] F32 Imm32(f32 value) const;
31 [[nodiscard]] U64 Imm64(u64 value) const; 31 [[nodiscard]] U64 Imm64(u64 value) const;
32 [[nodiscard]] U64 Imm64(s64 value) const;
32 [[nodiscard]] F64 Imm64(f64 value) const; 33 [[nodiscard]] F64 Imm64(f64 value) const;
33 34
34 void Branch(Block* label); 35 void Branch(Block* label);
@@ -170,7 +171,7 @@ public:
170 [[nodiscard]] U32U64 ISub(const U32U64& a, const U32U64& b); 171 [[nodiscard]] U32U64 ISub(const U32U64& a, const U32U64& b);
171 [[nodiscard]] U32 IMul(const U32& a, const U32& b); 172 [[nodiscard]] U32 IMul(const U32& a, const U32& b);
172 [[nodiscard]] U32U64 INeg(const U32U64& value); 173 [[nodiscard]] U32U64 INeg(const U32U64& value);
173 [[nodiscard]] U32 IAbs(const U32& value); 174 [[nodiscard]] U32U64 IAbs(const U32U64& value);
174 [[nodiscard]] U32U64 ShiftLeftLogical(const U32U64& base, const U32& shift); 175 [[nodiscard]] U32U64 ShiftLeftLogical(const U32U64& base, const U32& shift);
175 [[nodiscard]] U32U64 ShiftRightLogical(const U32U64& base, const U32& shift); 176 [[nodiscard]] U32U64 ShiftRightLogical(const U32U64& base, const U32& shift);
176 [[nodiscard]] U32U64 ShiftRightArithmetic(const U32U64& base, const U32& shift); 177 [[nodiscard]] U32U64 ShiftRightArithmetic(const U32U64& base, const U32& shift);
@@ -193,7 +194,7 @@ public:
193 [[nodiscard]] U32 UMax(const U32& a, const U32& b); 194 [[nodiscard]] U32 UMax(const U32& a, const U32& b);
194 195
195 [[nodiscard]] U1 ILessThan(const U32& lhs, const U32& rhs, bool is_signed); 196 [[nodiscard]] U1 ILessThan(const U32& lhs, const U32& rhs, bool is_signed);
196 [[nodiscard]] U1 IEqual(const U32& lhs, const U32& rhs); 197 [[nodiscard]] U1 IEqual(const U32U64& lhs, const U32U64& rhs);
197 [[nodiscard]] U1 ILessThanEqual(const U32& lhs, const U32& rhs, bool is_signed); 198 [[nodiscard]] U1 ILessThanEqual(const U32& lhs, const U32& rhs, bool is_signed);
198 [[nodiscard]] U1 IGreaterThan(const U32& lhs, const U32& rhs, bool is_signed); 199 [[nodiscard]] U1 IGreaterThan(const U32& lhs, const U32& rhs, bool is_signed);
199 [[nodiscard]] U1 INotEqual(const U32& lhs, const U32& rhs); 200 [[nodiscard]] U1 INotEqual(const U32& lhs, const U32& rhs);
@@ -207,9 +208,12 @@ public:
207 [[nodiscard]] U32U64 ConvertFToS(size_t bitsize, const F16F32F64& value); 208 [[nodiscard]] U32U64 ConvertFToS(size_t bitsize, const F16F32F64& value);
208 [[nodiscard]] U32U64 ConvertFToU(size_t bitsize, const F16F32F64& value); 209 [[nodiscard]] U32U64 ConvertFToU(size_t bitsize, const F16F32F64& value);
209 [[nodiscard]] U32U64 ConvertFToI(size_t bitsize, bool is_signed, const F16F32F64& value); 210 [[nodiscard]] U32U64 ConvertFToI(size_t bitsize, bool is_signed, const F16F32F64& value);
210 [[nodiscard]] F16F32F64 ConvertSToF(size_t bitsize, const U32U64& value); 211 [[nodiscard]] F16F32F64 ConvertSToF(size_t dest_bitsize, size_t src_bitsize,
211 [[nodiscard]] F16F32F64 ConvertUToF(size_t bitsize, const U32U64& value); 212 const Value& value);
212 [[nodiscard]] F16F32F64 ConvertIToF(size_t bitsize, bool is_signed, const U32U64& value); 213 [[nodiscard]] F16F32F64 ConvertUToF(size_t dest_bitsize, size_t src_bitsize,
214 const Value& value);
215 [[nodiscard]] F16F32F64 ConvertIToF(size_t dest_bitsize, size_t src_bitsize, bool is_signed,
216 const Value& value);
213 217
214 [[nodiscard]] U32U64 UConvert(size_t result_bitsize, const U32U64& value); 218 [[nodiscard]] U32U64 UConvert(size_t result_bitsize, const U32U64& value);
215 [[nodiscard]] F16F32F64 FPConvert(size_t result_bitsize, const F16F32F64& value); 219 [[nodiscard]] F16F32F64 FPConvert(size_t result_bitsize, const F16F32F64& value);
diff --git a/src/shader_recompiler/frontend/ir/opcodes.inc b/src/shader_recompiler/frontend/ir/opcodes.inc
index 593faca52..8471db7b9 100644
--- a/src/shader_recompiler/frontend/ir/opcodes.inc
+++ b/src/shader_recompiler/frontend/ir/opcodes.inc
@@ -247,6 +247,7 @@ OPCODE(IMul32, U32, U32,
247OPCODE(INeg32, U32, U32, ) 247OPCODE(INeg32, U32, U32, )
248OPCODE(INeg64, U64, U64, ) 248OPCODE(INeg64, U64, U64, )
249OPCODE(IAbs32, U32, U32, ) 249OPCODE(IAbs32, U32, U32, )
250OPCODE(IAbs64, U64, U64, )
250OPCODE(ShiftLeftLogical32, U32, U32, U32, ) 251OPCODE(ShiftLeftLogical32, U32, U32, U32, )
251OPCODE(ShiftLeftLogical64, U64, U64, U32, ) 252OPCODE(ShiftLeftLogical64, U64, U64, U32, )
252OPCODE(ShiftRightLogical32, U32, U32, U32, ) 253OPCODE(ShiftRightLogical32, U32, U32, U32, )
@@ -311,16 +312,28 @@ OPCODE(ConvertF16F32, F16, F32,
311OPCODE(ConvertF32F16, F32, F16, ) 312OPCODE(ConvertF32F16, F32, F16, )
312OPCODE(ConvertF32F64, F32, F64, ) 313OPCODE(ConvertF32F64, F32, F64, )
313OPCODE(ConvertF64F32, F64, F32, ) 314OPCODE(ConvertF64F32, F64, F32, )
315OPCODE(ConvertF16S8, F16, U32, )
316OPCODE(ConvertF16S16, F16, U32, )
314OPCODE(ConvertF16S32, F16, U32, ) 317OPCODE(ConvertF16S32, F16, U32, )
315OPCODE(ConvertF16S64, F16, U64, ) 318OPCODE(ConvertF16S64, F16, U64, )
319OPCODE(ConvertF16U8, F16, U32, )
320OPCODE(ConvertF16U16, F16, U32, )
316OPCODE(ConvertF16U32, F16, U32, ) 321OPCODE(ConvertF16U32, F16, U32, )
317OPCODE(ConvertF16U64, F16, U64, ) 322OPCODE(ConvertF16U64, F16, U64, )
323OPCODE(ConvertF32S8, F32, U32, )
324OPCODE(ConvertF32S16, F32, U32, )
318OPCODE(ConvertF32S32, F32, U32, ) 325OPCODE(ConvertF32S32, F32, U32, )
319OPCODE(ConvertF32S64, F32, U64, ) 326OPCODE(ConvertF32S64, F32, U64, )
327OPCODE(ConvertF32U8, F32, U32, )
328OPCODE(ConvertF32U16, F32, U32, )
320OPCODE(ConvertF32U32, F32, U32, ) 329OPCODE(ConvertF32U32, F32, U32, )
321OPCODE(ConvertF32U64, F32, U64, ) 330OPCODE(ConvertF32U64, F32, U64, )
331OPCODE(ConvertF64S8, F64, U32, )
332OPCODE(ConvertF64S16, F64, U32, )
322OPCODE(ConvertF64S32, F64, U32, ) 333OPCODE(ConvertF64S32, F64, U32, )
323OPCODE(ConvertF64S64, F64, U64, ) 334OPCODE(ConvertF64S64, F64, U64, )
335OPCODE(ConvertF64U8, F64, U32, )
336OPCODE(ConvertF64U16, F64, U32, )
324OPCODE(ConvertF64U32, F64, U32, ) 337OPCODE(ConvertF64U32, F64, U32, )
325OPCODE(ConvertF64U64, F64, U64, ) 338OPCODE(ConvertF64U64, F64, U64, )
326 339