diff options
Diffstat (limited to 'src/shader_recompiler/frontend/ir')
| -rw-r--r-- | src/shader_recompiler/frontend/ir/ir_emitter.cpp | 145 | ||||
| -rw-r--r-- | src/shader_recompiler/frontend/ir/ir_emitter.h | 14 | ||||
| -rw-r--r-- | src/shader_recompiler/frontend/ir/opcodes.inc | 13 |
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 | ||
| 56 | U64 IREmitter::Imm64(s64 value) const { | ||
| 57 | return U64{Value{static_cast<u64>(value)}}; | ||
| 58 | } | ||
| 59 | |||
| 56 | F64 IREmitter::Imm64(f64 value) const { | 60 | F64 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 | ||
| 365 | F16F32F64 IREmitter::FPAdd(const F16F32F64& a, const F16F32F64& b, FpControl control) { | 369 | F16F32F64 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 | ||
| 977 | U32 IREmitter::IAbs(const U32& value) { | 981 | U32U64 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 | ||
| 981 | U32U64 IREmitter::ShiftLeftLogical(const U32U64& base, const U32& shift) { | 992 | U32U64 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 | ||
| 1077 | U1 IREmitter::IEqual(const U32& lhs, const U32& rhs) { | 1088 | U1 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 | ||
| 1081 | U1 IREmitter::ILessThanEqual(const U32& lhs, const U32& rhs, bool is_signed) { | 1109 | U1 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 | ||
| 1201 | F16F32F64 IREmitter::ConvertSToF(size_t bitsize, const U32U64& value) { | 1229 | F16F32F64 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 | ||
| 1235 | F16F32F64 IREmitter::ConvertUToF(size_t bitsize, const U32U64& value) { | 1271 | F16F32F64 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 | ||
| 1269 | F16F32F64 IREmitter::ConvertIToF(size_t bitsize, bool is_signed, const U32U64& value) { | 1313 | F16F32F64 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, | |||
| 247 | OPCODE(INeg32, U32, U32, ) | 247 | OPCODE(INeg32, U32, U32, ) |
| 248 | OPCODE(INeg64, U64, U64, ) | 248 | OPCODE(INeg64, U64, U64, ) |
| 249 | OPCODE(IAbs32, U32, U32, ) | 249 | OPCODE(IAbs32, U32, U32, ) |
| 250 | OPCODE(IAbs64, U64, U64, ) | ||
| 250 | OPCODE(ShiftLeftLogical32, U32, U32, U32, ) | 251 | OPCODE(ShiftLeftLogical32, U32, U32, U32, ) |
| 251 | OPCODE(ShiftLeftLogical64, U64, U64, U32, ) | 252 | OPCODE(ShiftLeftLogical64, U64, U64, U32, ) |
| 252 | OPCODE(ShiftRightLogical32, U32, U32, U32, ) | 253 | OPCODE(ShiftRightLogical32, U32, U32, U32, ) |
| @@ -311,16 +312,28 @@ OPCODE(ConvertF16F32, F16, F32, | |||
| 311 | OPCODE(ConvertF32F16, F32, F16, ) | 312 | OPCODE(ConvertF32F16, F32, F16, ) |
| 312 | OPCODE(ConvertF32F64, F32, F64, ) | 313 | OPCODE(ConvertF32F64, F32, F64, ) |
| 313 | OPCODE(ConvertF64F32, F64, F32, ) | 314 | OPCODE(ConvertF64F32, F64, F32, ) |
| 315 | OPCODE(ConvertF16S8, F16, U32, ) | ||
| 316 | OPCODE(ConvertF16S16, F16, U32, ) | ||
| 314 | OPCODE(ConvertF16S32, F16, U32, ) | 317 | OPCODE(ConvertF16S32, F16, U32, ) |
| 315 | OPCODE(ConvertF16S64, F16, U64, ) | 318 | OPCODE(ConvertF16S64, F16, U64, ) |
| 319 | OPCODE(ConvertF16U8, F16, U32, ) | ||
| 320 | OPCODE(ConvertF16U16, F16, U32, ) | ||
| 316 | OPCODE(ConvertF16U32, F16, U32, ) | 321 | OPCODE(ConvertF16U32, F16, U32, ) |
| 317 | OPCODE(ConvertF16U64, F16, U64, ) | 322 | OPCODE(ConvertF16U64, F16, U64, ) |
| 323 | OPCODE(ConvertF32S8, F32, U32, ) | ||
| 324 | OPCODE(ConvertF32S16, F32, U32, ) | ||
| 318 | OPCODE(ConvertF32S32, F32, U32, ) | 325 | OPCODE(ConvertF32S32, F32, U32, ) |
| 319 | OPCODE(ConvertF32S64, F32, U64, ) | 326 | OPCODE(ConvertF32S64, F32, U64, ) |
| 327 | OPCODE(ConvertF32U8, F32, U32, ) | ||
| 328 | OPCODE(ConvertF32U16, F32, U32, ) | ||
| 320 | OPCODE(ConvertF32U32, F32, U32, ) | 329 | OPCODE(ConvertF32U32, F32, U32, ) |
| 321 | OPCODE(ConvertF32U64, F32, U64, ) | 330 | OPCODE(ConvertF32U64, F32, U64, ) |
| 331 | OPCODE(ConvertF64S8, F64, U32, ) | ||
| 332 | OPCODE(ConvertF64S16, F64, U32, ) | ||
| 322 | OPCODE(ConvertF64S32, F64, U32, ) | 333 | OPCODE(ConvertF64S32, F64, U32, ) |
| 323 | OPCODE(ConvertF64S64, F64, U64, ) | 334 | OPCODE(ConvertF64S64, F64, U64, ) |
| 335 | OPCODE(ConvertF64U8, F64, U32, ) | ||
| 336 | OPCODE(ConvertF64U16, F64, U32, ) | ||
| 324 | OPCODE(ConvertF64U32, F64, U32, ) | 337 | OPCODE(ConvertF64U32, F64, U32, ) |
| 325 | OPCODE(ConvertF64U64, F64, U64, ) | 338 | OPCODE(ConvertF64U64, F64, U64, ) |
| 326 | 339 | ||