diff options
Diffstat (limited to 'src/shader_recompiler/frontend/ir/ir_emitter.cpp')
| -rw-r--r-- | src/shader_recompiler/frontend/ir/ir_emitter.cpp | 145 |
1 files changed, 95 insertions, 50 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 | ||