diff options
| author | 2018-11-21 14:13:28 -0800 | |
|---|---|---|
| committer | 2018-11-21 14:13:28 -0800 | |
| commit | 61586e8794caaf5042bb0b80e9abe825e883779a (patch) | |
| tree | ffbb07894c9c3aea1682ad725b3793ac2333cd22 /src | |
| parent | Merge pull request #1742 from lioncash/hle-swkbd (diff) | |
| parent | gl_shader_decompiler: Use UNIMPLEMENTED instead of LOG+UNREACHABLE when appli... (diff) | |
| download | yuzu-61586e8794caaf5042bb0b80e9abe825e883779a.tar.gz yuzu-61586e8794caaf5042bb0b80e9abe825e883779a.tar.xz yuzu-61586e8794caaf5042bb0b80e9abe825e883779a.zip | |
Merge pull request #1752 from ReinUsesLisp/unimpl-decompiler
gl_shader_decompiler: Use UNIMPLEMENTED when applicable
Diffstat (limited to 'src')
| -rw-r--r-- | src/video_core/renderer_opengl/gl_shader_decompiler.cpp | 629 |
1 files changed, 258 insertions, 371 deletions
diff --git a/src/video_core/renderer_opengl/gl_shader_decompiler.cpp b/src/video_core/renderer_opengl/gl_shader_decompiler.cpp index e8f319438..90a88b91a 100644 --- a/src/video_core/renderer_opengl/gl_shader_decompiler.cpp +++ b/src/video_core/renderer_opengl/gl_shader_decompiler.cpp | |||
| @@ -49,8 +49,7 @@ static std::string GetTopologyName(Tegra::Shader::OutputTopology topology) { | |||
| 49 | case Tegra::Shader::OutputTopology::TriangleStrip: | 49 | case Tegra::Shader::OutputTopology::TriangleStrip: |
| 50 | return "triangle_strip"; | 50 | return "triangle_strip"; |
| 51 | default: | 51 | default: |
| 52 | LOG_CRITICAL(Render_OpenGL, "Unknown output topology {}", static_cast<u32>(topology)); | 52 | UNIMPLEMENTED_MSG("Unknown output topology: {}", static_cast<u32>(topology)); |
| 53 | UNREACHABLE(); | ||
| 54 | return "points"; | 53 | return "points"; |
| 55 | } | 54 | } |
| 56 | } | 55 | } |
| @@ -167,8 +166,8 @@ private: | |||
| 167 | case OpCode::Id::SSY: | 166 | case OpCode::Id::SSY: |
| 168 | case OpCode::Id::PBK: { | 167 | case OpCode::Id::PBK: { |
| 169 | // The SSY and PBK use a similar encoding as the BRA instruction. | 168 | // The SSY and PBK use a similar encoding as the BRA instruction. |
| 170 | ASSERT_MSG(instr.bra.constant_buffer == 0, | 169 | UNIMPLEMENTED_IF_MSG(instr.bra.constant_buffer != 0, |
| 171 | "Constant buffer branching is not supported"); | 170 | "Constant buffer branching is not supported"); |
| 172 | const u32 target = offset + instr.bra.GetBranchTarget(); | 171 | const u32 target = offset + instr.bra.GetBranchTarget(); |
| 173 | labels.insert(target); | 172 | labels.insert(target); |
| 174 | // Continue scanning for an exit method. | 173 | // Continue scanning for an exit method. |
| @@ -299,8 +298,7 @@ public: | |||
| 299 | // Default - do nothing | 298 | // Default - do nothing |
| 300 | return value; | 299 | return value; |
| 301 | default: | 300 | default: |
| 302 | LOG_CRITICAL(HW_GPU, "Unimplemented conversion size {}", static_cast<u32>(size)); | 301 | UNIMPLEMENTED_MSG("Unimplemented conversion size: {}", static_cast<u32>(size)); |
| 303 | UNREACHABLE(); | ||
| 304 | } | 302 | } |
| 305 | } | 303 | } |
| 306 | 304 | ||
| @@ -363,7 +361,7 @@ public: | |||
| 363 | u64 value_num_components, bool is_saturated = false, | 361 | u64 value_num_components, bool is_saturated = false, |
| 364 | u64 dest_elem = 0, Register::Size size = Register::Size::Word, | 362 | u64 dest_elem = 0, Register::Size size = Register::Size::Word, |
| 365 | bool sets_cc = false) { | 363 | bool sets_cc = false) { |
| 366 | ASSERT_MSG(!is_saturated, "Unimplemented"); | 364 | UNIMPLEMENTED_IF(is_saturated); |
| 367 | 365 | ||
| 368 | const std::string func{is_signed ? "intBitsToFloat" : "uintBitsToFloat"}; | 366 | const std::string func{is_signed ? "intBitsToFloat" : "uintBitsToFloat"}; |
| 369 | 367 | ||
| @@ -392,7 +390,7 @@ public: | |||
| 392 | Tegra::Shader::HalfMerge merge, u64 dest_num_components, | 390 | Tegra::Shader::HalfMerge merge, u64 dest_num_components, |
| 393 | u64 value_num_components, bool is_saturated = false, | 391 | u64 value_num_components, bool is_saturated = false, |
| 394 | u64 dest_elem = 0) { | 392 | u64 dest_elem = 0) { |
| 395 | ASSERT_MSG(!is_saturated, "Unimplemented"); | 393 | UNIMPLEMENTED_IF(is_saturated); |
| 396 | 394 | ||
| 397 | const std::string result = [&]() { | 395 | const std::string result = [&]() { |
| 398 | switch (merge) { | 396 | switch (merge) { |
| @@ -461,8 +459,7 @@ public: | |||
| 461 | case Tegra::Shader::ControlCode::NEU: | 459 | case Tegra::Shader::ControlCode::NEU: |
| 462 | return "!(" + GetInternalFlag(InternalFlag::ZeroFlag) + ')'; | 460 | return "!(" + GetInternalFlag(InternalFlag::ZeroFlag) + ')'; |
| 463 | default: | 461 | default: |
| 464 | LOG_CRITICAL(HW_GPU, "Unimplemented Control Code {}", static_cast<u32>(cc)); | 462 | UNIMPLEMENTED_MSG("Unimplemented Control Code: {}", static_cast<u32>(cc)); |
| 465 | UNREACHABLE(); | ||
| 466 | return "false"; | 463 | return "false"; |
| 467 | } | 464 | } |
| 468 | } | 465 | } |
| @@ -846,16 +843,13 @@ private: | |||
| 846 | if (declr_input_attribute.count(attribute) == 0) { | 843 | if (declr_input_attribute.count(attribute) == 0) { |
| 847 | declr_input_attribute[attribute] = input_mode; | 844 | declr_input_attribute[attribute] = input_mode; |
| 848 | } else { | 845 | } else { |
| 849 | if (declr_input_attribute[attribute] != input_mode) { | 846 | UNIMPLEMENTED_IF_MSG(declr_input_attribute[attribute] != input_mode, |
| 850 | LOG_CRITICAL(HW_GPU, "Same Input multiple input modes"); | 847 | "Multiple input modes for the same attribute"); |
| 851 | UNREACHABLE(); | ||
| 852 | } | ||
| 853 | } | 848 | } |
| 854 | return GeometryPass("input_attribute_" + std::to_string(index)); | 849 | return GeometryPass("input_attribute_" + std::to_string(index)); |
| 855 | } | 850 | } |
| 856 | 851 | ||
| 857 | LOG_CRITICAL(HW_GPU, "Unhandled input attribute: {}", static_cast<u32>(attribute)); | 852 | UNIMPLEMENTED_MSG("Unhandled input attribute: {}", static_cast<u32>(attribute)); |
| 858 | UNREACHABLE(); | ||
| 859 | } | 853 | } |
| 860 | 854 | ||
| 861 | return "vec4(0, 0, 0, 0)"; | 855 | return "vec4(0, 0, 0, 0)"; |
| @@ -881,24 +875,20 @@ private: | |||
| 881 | break; | 875 | break; |
| 882 | } | 876 | } |
| 883 | default: { | 877 | default: { |
| 884 | LOG_CRITICAL(HW_GPU, "Unhandled Ipa InterpMode: {}", static_cast<u32>(interp_mode)); | 878 | UNIMPLEMENTED_MSG("Unhandled IPA interp mode: {}", static_cast<u32>(interp_mode)); |
| 885 | UNREACHABLE(); | ||
| 886 | } | 879 | } |
| 887 | } | 880 | } |
| 888 | switch (sample_mode) { | 881 | switch (sample_mode) { |
| 889 | case Tegra::Shader::IpaSampleMode::Centroid: { | 882 | case Tegra::Shader::IpaSampleMode::Centroid: |
| 890 | // Note not implemented, it can be implemented with the "centroid " keyword in glsl; | 883 | // It can be implemented with the "centroid " keyword in glsl |
| 891 | LOG_CRITICAL(HW_GPU, "Ipa Sampler Mode: centroid, not implemented"); | 884 | UNIMPLEMENTED_MSG("Unimplemented IPA sampler mode centroid"); |
| 892 | UNREACHABLE(); | ||
| 893 | break; | 885 | break; |
| 894 | } | 886 | case Tegra::Shader::IpaSampleMode::Default: |
| 895 | case Tegra::Shader::IpaSampleMode::Default: { | ||
| 896 | // Default, n/a | 887 | // Default, n/a |
| 897 | break; | 888 | break; |
| 898 | } | ||
| 899 | default: { | 889 | default: { |
| 900 | LOG_CRITICAL(HW_GPU, "Unhandled Ipa SampleMode: {}", static_cast<u32>(sample_mode)); | 890 | UNIMPLEMENTED_MSG("Unimplemented IPA sampler mode: {}", static_cast<u32>(sample_mode)); |
| 901 | UNREACHABLE(); | 891 | break; |
| 902 | } | 892 | } |
| 903 | } | 893 | } |
| 904 | return out; | 894 | return out; |
| @@ -919,8 +909,7 @@ private: | |||
| 919 | return "output_attribute_" + std::to_string(index); | 909 | return "output_attribute_" + std::to_string(index); |
| 920 | } | 910 | } |
| 921 | 911 | ||
| 922 | LOG_CRITICAL(HW_GPU, "Unhandled output attribute: {}", index); | 912 | UNIMPLEMENTED_MSG("Unhandled output attribute={}", index); |
| 923 | UNREACHABLE(); | ||
| 924 | return {}; | 913 | return {}; |
| 925 | } | 914 | } |
| 926 | } | 915 | } |
| @@ -1077,8 +1066,8 @@ private: | |||
| 1077 | {PredCondition::GreaterThanWithNan, ">"}, {PredCondition::GreaterEqualWithNan, ">="}}; | 1066 | {PredCondition::GreaterThanWithNan, ">"}, {PredCondition::GreaterEqualWithNan, ">="}}; |
| 1078 | 1067 | ||
| 1079 | const auto& comparison{PredicateComparisonStrings.find(condition)}; | 1068 | const auto& comparison{PredicateComparisonStrings.find(condition)}; |
| 1080 | ASSERT_MSG(comparison != PredicateComparisonStrings.end(), | 1069 | UNIMPLEMENTED_IF_MSG(comparison == PredicateComparisonStrings.end(), |
| 1081 | "Unknown predicate comparison operation"); | 1070 | "Unknown predicate comparison operation"); |
| 1082 | 1071 | ||
| 1083 | std::string predicate{'(' + op_a + ") " + comparison->second + " (" + op_b + ')'}; | 1072 | std::string predicate{'(' + op_a + ") " + comparison->second + " (" + op_b + ')'}; |
| 1084 | if (condition == PredCondition::LessThanWithNan || | 1073 | if (condition == PredCondition::LessThanWithNan || |
| @@ -1106,7 +1095,7 @@ private: | |||
| 1106 | }; | 1095 | }; |
| 1107 | 1096 | ||
| 1108 | auto op = PredicateOperationStrings.find(operation); | 1097 | auto op = PredicateOperationStrings.find(operation); |
| 1109 | ASSERT_MSG(op != PredicateOperationStrings.end(), "Unknown predicate operation"); | 1098 | UNIMPLEMENTED_IF_MSG(op == PredicateOperationStrings.end(), "Unknown predicate operation"); |
| 1110 | return op->second; | 1099 | return op->second; |
| 1111 | } | 1100 | } |
| 1112 | 1101 | ||
| @@ -1204,8 +1193,7 @@ private: | |||
| 1204 | break; | 1193 | break; |
| 1205 | } | 1194 | } |
| 1206 | default: | 1195 | default: |
| 1207 | LOG_CRITICAL(HW_GPU, "Unimplemented logic operation: {}", static_cast<u32>(logic_op)); | 1196 | UNIMPLEMENTED_MSG("Unimplemented logic operation={}", static_cast<u32>(logic_op)); |
| 1208 | UNREACHABLE(); | ||
| 1209 | } | 1197 | } |
| 1210 | 1198 | ||
| 1211 | if (dest != Tegra::Shader::Register::ZeroIndex) { | 1199 | if (dest != Tegra::Shader::Register::ZeroIndex) { |
| @@ -1223,9 +1211,8 @@ private: | |||
| 1223 | SetPredicate(static_cast<u64>(predicate), '(' + result + ") != 0"); | 1211 | SetPredicate(static_cast<u64>(predicate), '(' + result + ") != 0"); |
| 1224 | break; | 1212 | break; |
| 1225 | default: | 1213 | default: |
| 1226 | LOG_CRITICAL(HW_GPU, "Unimplemented predicate result mode: {}", | 1214 | UNIMPLEMENTED_MSG("Unimplemented predicate result mode: {}", |
| 1227 | static_cast<u32>(predicate_mode)); | 1215 | static_cast<u32>(predicate_mode)); |
| 1228 | UNREACHABLE(); | ||
| 1229 | } | 1216 | } |
| 1230 | } | 1217 | } |
| 1231 | 1218 | ||
| @@ -1293,19 +1280,15 @@ private: | |||
| 1293 | 1280 | ||
| 1294 | static u32 TextureCoordinates(Tegra::Shader::TextureType texture_type) { | 1281 | static u32 TextureCoordinates(Tegra::Shader::TextureType texture_type) { |
| 1295 | switch (texture_type) { | 1282 | switch (texture_type) { |
| 1296 | case Tegra::Shader::TextureType::Texture1D: { | 1283 | case Tegra::Shader::TextureType::Texture1D: |
| 1297 | return 1; | 1284 | return 1; |
| 1298 | } | 1285 | case Tegra::Shader::TextureType::Texture2D: |
| 1299 | case Tegra::Shader::TextureType::Texture2D: { | ||
| 1300 | return 2; | 1286 | return 2; |
| 1301 | } | ||
| 1302 | case Tegra::Shader::TextureType::Texture3D: | 1287 | case Tegra::Shader::TextureType::Texture3D: |
| 1303 | case Tegra::Shader::TextureType::TextureCube: { | 1288 | case Tegra::Shader::TextureType::TextureCube: |
| 1304 | return 3; | 1289 | return 3; |
| 1305 | } | ||
| 1306 | default: | 1290 | default: |
| 1307 | LOG_CRITICAL(HW_GPU, "Unhandled texture type {}", static_cast<u32>(texture_type)); | 1291 | UNIMPLEMENTED_MSG("Unhandled texture type: {}", static_cast<u32>(texture_type)); |
| 1308 | UNREACHABLE(); | ||
| 1309 | return 0; | 1292 | return 0; |
| 1310 | } | 1293 | } |
| 1311 | } | 1294 | } |
| @@ -1341,7 +1324,7 @@ private: | |||
| 1341 | void EmitFragmentOutputsWrite() { | 1324 | void EmitFragmentOutputsWrite() { |
| 1342 | ASSERT(stage == Maxwell3D::Regs::ShaderStage::Fragment); | 1325 | ASSERT(stage == Maxwell3D::Regs::ShaderStage::Fragment); |
| 1343 | 1326 | ||
| 1344 | ASSERT_MSG(header.ps.omap.sample_mask == 0, "Samplemask write is unimplemented"); | 1327 | UNIMPLEMENTED_IF_MSG(header.ps.omap.sample_mask != 0, "Samplemask write is unimplemented"); |
| 1345 | 1328 | ||
| 1346 | shader.AddLine("if (alpha_test[0] != 0) {"); | 1329 | shader.AddLine("if (alpha_test[0] != 0) {"); |
| 1347 | ++shader.scope; | 1330 | ++shader.scope; |
| @@ -1407,7 +1390,7 @@ private: | |||
| 1407 | case Tegra::Shader::VideoType::Size32: | 1390 | case Tegra::Shader::VideoType::Size32: |
| 1408 | // TODO(Rodrigo): From my hardware tests it becomes a bit "mad" when | 1391 | // TODO(Rodrigo): From my hardware tests it becomes a bit "mad" when |
| 1409 | // this type is used (1 * 1 + 0 == 0x5b800000). Until a better | 1392 | // this type is used (1 * 1 + 0 == 0x5b800000). Until a better |
| 1410 | // explanation is found: assert. | 1393 | // explanation is found: abort. |
| 1411 | UNIMPLEMENTED(); | 1394 | UNIMPLEMENTED(); |
| 1412 | return zero; | 1395 | return zero; |
| 1413 | case Tegra::Shader::VideoType::Invalid: | 1396 | case Tegra::Shader::VideoType::Invalid: |
| @@ -1463,8 +1446,7 @@ private: | |||
| 1463 | 1446 | ||
| 1464 | // Decoding failure | 1447 | // Decoding failure |
| 1465 | if (!opcode) { | 1448 | if (!opcode) { |
| 1466 | LOG_CRITICAL(HW_GPU, "Unhandled instruction: {0:x}", instr.value); | 1449 | UNIMPLEMENTED_MSG("Unhandled instruction: {0:x}", instr.value); |
| 1467 | UNREACHABLE(); | ||
| 1468 | return offset + 1; | 1450 | return offset + 1; |
| 1469 | } | 1451 | } |
| 1470 | 1452 | ||
| @@ -1472,8 +1454,8 @@ private: | |||
| 1472 | fmt::format("// {}: {} (0x{:016x})", offset, opcode->get().GetName(), instr.value)); | 1454 | fmt::format("// {}: {} (0x{:016x})", offset, opcode->get().GetName(), instr.value)); |
| 1473 | 1455 | ||
| 1474 | using Tegra::Shader::Pred; | 1456 | using Tegra::Shader::Pred; |
| 1475 | ASSERT_MSG(instr.pred.full_pred != Pred::NeverExecute, | 1457 | UNIMPLEMENTED_IF_MSG(instr.pred.full_pred == Pred::NeverExecute, |
| 1476 | "NeverExecute predicate not implemented"); | 1458 | "NeverExecute predicate not implemented"); |
| 1477 | 1459 | ||
| 1478 | // Some instructions (like SSY) don't have a predicate field, they are always | 1460 | // Some instructions (like SSY) don't have a predicate field, they are always |
| 1479 | // unconditionally executed. | 1461 | // unconditionally executed. |
| @@ -1516,37 +1498,37 @@ private: | |||
| 1516 | case OpCode::Id::FMUL_R: | 1498 | case OpCode::Id::FMUL_R: |
| 1517 | case OpCode::Id::FMUL_IMM: { | 1499 | case OpCode::Id::FMUL_IMM: { |
| 1518 | // FMUL does not have 'abs' bits and only the second operand has a 'neg' bit. | 1500 | // FMUL does not have 'abs' bits and only the second operand has a 'neg' bit. |
| 1519 | ASSERT_MSG(instr.fmul.tab5cb8_2 == 0, "FMUL tab5cb8_2({}) is not implemented", | 1501 | UNIMPLEMENTED_IF_MSG(instr.fmul.tab5cb8_2 != 0, |
| 1520 | instr.fmul.tab5cb8_2.Value()); | 1502 | "FMUL tab5cb8_2({}) is not implemented", |
| 1521 | ASSERT_MSG(instr.fmul.tab5c68_1 == 0, "FMUL tab5cb8_1({}) is not implemented", | 1503 | instr.fmul.tab5cb8_2.Value()); |
| 1522 | instr.fmul.tab5c68_1.Value()); | 1504 | UNIMPLEMENTED_IF_MSG(instr.fmul.tab5c68_1 != 0, |
| 1523 | ASSERT_MSG(instr.fmul.tab5c68_0 == 1, "FMUL tab5cb8_0({}) is not implemented", | 1505 | "FMUL tab5cb8_1({}) is not implemented", |
| 1524 | instr.fmul.tab5c68_0 | 1506 | instr.fmul.tab5c68_1.Value()); |
| 1525 | .Value()); // SMO typical sends 1 here which seems to be the default | 1507 | UNIMPLEMENTED_IF_MSG( |
| 1526 | ASSERT_MSG(instr.fmul.cc == 0, "FMUL cc is not implemented"); | 1508 | instr.fmul.tab5c68_0 != 1, "FMUL tab5cb8_0({}) is not implemented", |
| 1509 | instr.fmul.tab5c68_0 | ||
| 1510 | .Value()); // SMO typical sends 1 here which seems to be the default | ||
| 1511 | UNIMPLEMENTED_IF_MSG(instr.fmul.cc != 0, "FMUL cc is not implemented"); | ||
| 1512 | UNIMPLEMENTED_IF_MSG(instr.generates_cc, | ||
| 1513 | "FMUL Generates an unhandled Control Code"); | ||
| 1527 | 1514 | ||
| 1528 | op_b = GetOperandAbsNeg(op_b, false, instr.fmul.negate_b); | 1515 | op_b = GetOperandAbsNeg(op_b, false, instr.fmul.negate_b); |
| 1529 | 1516 | ||
| 1530 | regs.SetRegisterToFloat(instr.gpr0, 0, op_a + " * " + op_b, 1, 1, | 1517 | regs.SetRegisterToFloat(instr.gpr0, 0, op_a + " * " + op_b, 1, 1, |
| 1531 | instr.alu.saturate_d, 0, true); | 1518 | instr.alu.saturate_d, 0, true); |
| 1532 | if (instr.generates_cc) { | ||
| 1533 | LOG_CRITICAL(HW_GPU, "FMUL Generates an unhandled Control Code"); | ||
| 1534 | UNREACHABLE(); | ||
| 1535 | } | ||
| 1536 | break; | 1519 | break; |
| 1537 | } | 1520 | } |
| 1538 | case OpCode::Id::FADD_C: | 1521 | case OpCode::Id::FADD_C: |
| 1539 | case OpCode::Id::FADD_R: | 1522 | case OpCode::Id::FADD_R: |
| 1540 | case OpCode::Id::FADD_IMM: { | 1523 | case OpCode::Id::FADD_IMM: { |
| 1524 | UNIMPLEMENTED_IF_MSG(instr.generates_cc, | ||
| 1525 | "FADD Generates an unhandled Control Code"); | ||
| 1526 | |||
| 1541 | op_a = GetOperandAbsNeg(op_a, instr.alu.abs_a, instr.alu.negate_a); | 1527 | op_a = GetOperandAbsNeg(op_a, instr.alu.abs_a, instr.alu.negate_a); |
| 1542 | op_b = GetOperandAbsNeg(op_b, instr.alu.abs_b, instr.alu.negate_b); | 1528 | op_b = GetOperandAbsNeg(op_b, instr.alu.abs_b, instr.alu.negate_b); |
| 1543 | 1529 | ||
| 1544 | regs.SetRegisterToFloat(instr.gpr0, 0, op_a + " + " + op_b, 1, 1, | 1530 | regs.SetRegisterToFloat(instr.gpr0, 0, op_a + " + " + op_b, 1, 1, |
| 1545 | instr.alu.saturate_d, 0, true); | 1531 | instr.alu.saturate_d, 0, true); |
| 1546 | if (instr.generates_cc) { | ||
| 1547 | LOG_CRITICAL(HW_GPU, "FADD Generates an unhandled Control Code"); | ||
| 1548 | UNREACHABLE(); | ||
| 1549 | } | ||
| 1550 | break; | 1532 | break; |
| 1551 | } | 1533 | } |
| 1552 | case OpCode::Id::MUFU: { | 1534 | case OpCode::Id::MUFU: { |
| @@ -1581,15 +1563,17 @@ private: | |||
| 1581 | instr.alu.saturate_d, 0, true); | 1563 | instr.alu.saturate_d, 0, true); |
| 1582 | break; | 1564 | break; |
| 1583 | default: | 1565 | default: |
| 1584 | LOG_CRITICAL(HW_GPU, "Unhandled MUFU sub op: {0:x}", | 1566 | UNIMPLEMENTED_MSG("Unhandled MUFU sub op={0:x}", |
| 1585 | static_cast<unsigned>(instr.sub_op.Value())); | 1567 | static_cast<unsigned>(instr.sub_op.Value())); |
| 1586 | UNREACHABLE(); | ||
| 1587 | } | 1568 | } |
| 1588 | break; | 1569 | break; |
| 1589 | } | 1570 | } |
| 1590 | case OpCode::Id::FMNMX_C: | 1571 | case OpCode::Id::FMNMX_C: |
| 1591 | case OpCode::Id::FMNMX_R: | 1572 | case OpCode::Id::FMNMX_R: |
| 1592 | case OpCode::Id::FMNMX_IMM: { | 1573 | case OpCode::Id::FMNMX_IMM: { |
| 1574 | UNIMPLEMENTED_IF_MSG(instr.generates_cc, | ||
| 1575 | "FMNMX Generates an unhandled Control Code"); | ||
| 1576 | |||
| 1593 | op_a = GetOperandAbsNeg(op_a, instr.alu.abs_a, instr.alu.negate_a); | 1577 | op_a = GetOperandAbsNeg(op_a, instr.alu.abs_a, instr.alu.negate_a); |
| 1594 | op_b = GetOperandAbsNeg(op_b, instr.alu.abs_b, instr.alu.negate_b); | 1578 | op_b = GetOperandAbsNeg(op_b, instr.alu.abs_b, instr.alu.negate_b); |
| 1595 | 1579 | ||
| @@ -1600,10 +1584,6 @@ private: | |||
| 1600 | '(' + condition + ") ? min(" + parameters + ") : max(" + | 1584 | '(' + condition + ") ? min(" + parameters + ") : max(" + |
| 1601 | parameters + ')', | 1585 | parameters + ')', |
| 1602 | 1, 1, false, 0, true); | 1586 | 1, 1, false, 0, true); |
| 1603 | if (instr.generates_cc) { | ||
| 1604 | LOG_CRITICAL(HW_GPU, "FMNMX Generates an unhandled Control Code"); | ||
| 1605 | UNREACHABLE(); | ||
| 1606 | } | ||
| 1607 | break; | 1587 | break; |
| 1608 | } | 1588 | } |
| 1609 | case OpCode::Id::RRO_C: | 1589 | case OpCode::Id::RRO_C: |
| @@ -1616,9 +1596,7 @@ private: | |||
| 1616 | break; | 1596 | break; |
| 1617 | } | 1597 | } |
| 1618 | default: { | 1598 | default: { |
| 1619 | LOG_CRITICAL(HW_GPU, "Unhandled arithmetic instruction: {}", | 1599 | UNIMPLEMENTED_MSG("Unhandled arithmetic instruction: {}", opcode->get().GetName()); |
| 1620 | opcode->get().GetName()); | ||
| 1621 | UNREACHABLE(); | ||
| 1622 | } | 1600 | } |
| 1623 | } | 1601 | } |
| 1624 | break; | 1602 | break; |
| @@ -1630,17 +1608,19 @@ private: | |||
| 1630 | break; | 1608 | break; |
| 1631 | } | 1609 | } |
| 1632 | case OpCode::Id::FMUL32_IMM: { | 1610 | case OpCode::Id::FMUL32_IMM: { |
| 1611 | UNIMPLEMENTED_IF_MSG(instr.op_32.generates_cc, | ||
| 1612 | "FMUL32 Generates an unhandled Control Code"); | ||
| 1613 | |||
| 1633 | regs.SetRegisterToFloat(instr.gpr0, 0, | 1614 | regs.SetRegisterToFloat(instr.gpr0, 0, |
| 1634 | regs.GetRegisterAsFloat(instr.gpr8) + " * " + | 1615 | regs.GetRegisterAsFloat(instr.gpr8) + " * " + |
| 1635 | GetImmediate32(instr), | 1616 | GetImmediate32(instr), |
| 1636 | 1, 1, instr.fmul32.saturate, 0, true); | 1617 | 1, 1, instr.fmul32.saturate, 0, true); |
| 1637 | if (instr.op_32.generates_cc) { | ||
| 1638 | LOG_CRITICAL(HW_GPU, "FMUL32 Generates an unhandled Control Code"); | ||
| 1639 | UNREACHABLE(); | ||
| 1640 | } | ||
| 1641 | break; | 1618 | break; |
| 1642 | } | 1619 | } |
| 1643 | case OpCode::Id::FADD32I: { | 1620 | case OpCode::Id::FADD32I: { |
| 1621 | UNIMPLEMENTED_IF_MSG(instr.op_32.generates_cc, | ||
| 1622 | "FADD32 Generates an unhandled Control Code"); | ||
| 1623 | |||
| 1644 | std::string op_a = regs.GetRegisterAsFloat(instr.gpr8); | 1624 | std::string op_a = regs.GetRegisterAsFloat(instr.gpr8); |
| 1645 | std::string op_b = GetImmediate32(instr); | 1625 | std::string op_b = GetImmediate32(instr); |
| 1646 | 1626 | ||
| @@ -1661,23 +1641,21 @@ private: | |||
| 1661 | } | 1641 | } |
| 1662 | 1642 | ||
| 1663 | regs.SetRegisterToFloat(instr.gpr0, 0, op_a + " + " + op_b, 1, 1, false, 0, true); | 1643 | regs.SetRegisterToFloat(instr.gpr0, 0, op_a + " + " + op_b, 1, 1, false, 0, true); |
| 1664 | if (instr.op_32.generates_cc) { | ||
| 1665 | LOG_CRITICAL(HW_GPU, "FADD32 Generates an unhandled Control Code"); | ||
| 1666 | UNREACHABLE(); | ||
| 1667 | } | ||
| 1668 | break; | 1644 | break; |
| 1669 | } | 1645 | } |
| 1670 | } | 1646 | } |
| 1671 | break; | 1647 | break; |
| 1672 | } | 1648 | } |
| 1673 | case OpCode::Type::Bfe: { | 1649 | case OpCode::Type::Bfe: { |
| 1674 | ASSERT_MSG(!instr.bfe.negate_b, "Unimplemented"); | 1650 | UNIMPLEMENTED_IF(instr.bfe.negate_b); |
| 1675 | 1651 | ||
| 1676 | std::string op_a = instr.bfe.negate_a ? "-" : ""; | 1652 | std::string op_a = instr.bfe.negate_a ? "-" : ""; |
| 1677 | op_a += regs.GetRegisterAsInteger(instr.gpr8); | 1653 | op_a += regs.GetRegisterAsInteger(instr.gpr8); |
| 1678 | 1654 | ||
| 1679 | switch (opcode->get().GetId()) { | 1655 | switch (opcode->get().GetId()) { |
| 1680 | case OpCode::Id::BFE_IMM: { | 1656 | case OpCode::Id::BFE_IMM: { |
| 1657 | UNIMPLEMENTED_IF_MSG(instr.generates_cc, "BFE Generates an unhandled Control Code"); | ||
| 1658 | |||
| 1681 | std::string inner_shift = | 1659 | std::string inner_shift = |
| 1682 | '(' + op_a + " << " + std::to_string(instr.bfe.GetLeftShiftValue()) + ')'; | 1660 | '(' + op_a + " << " + std::to_string(instr.bfe.GetLeftShiftValue()) + ')'; |
| 1683 | std::string outer_shift = | 1661 | std::string outer_shift = |
| @@ -1685,15 +1663,10 @@ private: | |||
| 1685 | std::to_string(instr.bfe.GetLeftShiftValue() + instr.bfe.shift_position) + ')'; | 1663 | std::to_string(instr.bfe.GetLeftShiftValue() + instr.bfe.shift_position) + ')'; |
| 1686 | 1664 | ||
| 1687 | regs.SetRegisterToInteger(instr.gpr0, true, 0, outer_shift, 1, 1); | 1665 | regs.SetRegisterToInteger(instr.gpr0, true, 0, outer_shift, 1, 1); |
| 1688 | if (instr.generates_cc) { | ||
| 1689 | LOG_CRITICAL(HW_GPU, "BFE Generates an unhandled Control Code"); | ||
| 1690 | UNREACHABLE(); | ||
| 1691 | } | ||
| 1692 | break; | 1666 | break; |
| 1693 | } | 1667 | } |
| 1694 | default: { | 1668 | default: { |
| 1695 | LOG_CRITICAL(HW_GPU, "Unhandled BFE instruction: {}", opcode->get().GetName()); | 1669 | UNIMPLEMENTED_MSG("Unhandled BFE instruction: {}", opcode->get().GetName()); |
| 1696 | UNREACHABLE(); | ||
| 1697 | } | 1670 | } |
| 1698 | } | 1671 | } |
| 1699 | 1672 | ||
| @@ -1718,6 +1691,8 @@ private: | |||
| 1718 | case OpCode::Id::SHR_C: | 1691 | case OpCode::Id::SHR_C: |
| 1719 | case OpCode::Id::SHR_R: | 1692 | case OpCode::Id::SHR_R: |
| 1720 | case OpCode::Id::SHR_IMM: { | 1693 | case OpCode::Id::SHR_IMM: { |
| 1694 | UNIMPLEMENTED_IF_MSG(instr.generates_cc, "SHR Generates an unhandled Control Code"); | ||
| 1695 | |||
| 1721 | if (!instr.shift.is_signed) { | 1696 | if (!instr.shift.is_signed) { |
| 1722 | // Logical shift right | 1697 | // Logical shift right |
| 1723 | op_a = "uint(" + op_a + ')'; | 1698 | op_a = "uint(" + op_a + ')'; |
| @@ -1726,24 +1701,17 @@ private: | |||
| 1726 | // Cast to int is superfluous for arithmetic shift, it's only for a logical shift | 1701 | // Cast to int is superfluous for arithmetic shift, it's only for a logical shift |
| 1727 | regs.SetRegisterToInteger(instr.gpr0, true, 0, "int(" + op_a + " >> " + op_b + ')', | 1702 | regs.SetRegisterToInteger(instr.gpr0, true, 0, "int(" + op_a + " >> " + op_b + ')', |
| 1728 | 1, 1); | 1703 | 1, 1); |
| 1729 | if (instr.generates_cc) { | ||
| 1730 | LOG_CRITICAL(HW_GPU, "SHR Generates an unhandled Control Code"); | ||
| 1731 | UNREACHABLE(); | ||
| 1732 | } | ||
| 1733 | break; | 1704 | break; |
| 1734 | } | 1705 | } |
| 1735 | case OpCode::Id::SHL_C: | 1706 | case OpCode::Id::SHL_C: |
| 1736 | case OpCode::Id::SHL_R: | 1707 | case OpCode::Id::SHL_R: |
| 1737 | case OpCode::Id::SHL_IMM: | 1708 | case OpCode::Id::SHL_IMM: |
| 1709 | UNIMPLEMENTED_IF_MSG(instr.generates_cc, "SHL Generates an unhandled Control Code"); | ||
| 1710 | |||
| 1738 | regs.SetRegisterToInteger(instr.gpr0, true, 0, op_a + " << " + op_b, 1, 1); | 1711 | regs.SetRegisterToInteger(instr.gpr0, true, 0, op_a + " << " + op_b, 1, 1); |
| 1739 | if (instr.generates_cc) { | ||
| 1740 | LOG_CRITICAL(HW_GPU, "SHL Generates an unhandled Control Code"); | ||
| 1741 | UNREACHABLE(); | ||
| 1742 | } | ||
| 1743 | break; | 1712 | break; |
| 1744 | default: { | 1713 | default: { |
| 1745 | LOG_CRITICAL(HW_GPU, "Unhandled shift instruction: {}", opcode->get().GetName()); | 1714 | UNIMPLEMENTED_MSG("Unhandled shift instruction: {}", opcode->get().GetName()); |
| 1746 | UNREACHABLE(); | ||
| 1747 | } | 1715 | } |
| 1748 | } | 1716 | } |
| 1749 | break; | 1717 | break; |
| @@ -1754,17 +1722,19 @@ private: | |||
| 1754 | 1722 | ||
| 1755 | switch (opcode->get().GetId()) { | 1723 | switch (opcode->get().GetId()) { |
| 1756 | case OpCode::Id::IADD32I: | 1724 | case OpCode::Id::IADD32I: |
| 1725 | UNIMPLEMENTED_IF_MSG(instr.op_32.generates_cc, | ||
| 1726 | "IADD32 Generates an unhandled Control Code"); | ||
| 1727 | |||
| 1757 | if (instr.iadd32i.negate_a) | 1728 | if (instr.iadd32i.negate_a) |
| 1758 | op_a = "-(" + op_a + ')'; | 1729 | op_a = "-(" + op_a + ')'; |
| 1759 | 1730 | ||
| 1760 | regs.SetRegisterToInteger(instr.gpr0, true, 0, op_a + " + " + op_b, 1, 1, | 1731 | regs.SetRegisterToInteger(instr.gpr0, true, 0, op_a + " + " + op_b, 1, 1, |
| 1761 | instr.iadd32i.saturate != 0); | 1732 | instr.iadd32i.saturate != 0); |
| 1762 | if (instr.op_32.generates_cc) { | ||
| 1763 | LOG_CRITICAL(HW_GPU, "IADD32 Generates an unhandled Control Code"); | ||
| 1764 | UNREACHABLE(); | ||
| 1765 | } | ||
| 1766 | break; | 1733 | break; |
| 1767 | case OpCode::Id::LOP32I: { | 1734 | case OpCode::Id::LOP32I: { |
| 1735 | UNIMPLEMENTED_IF_MSG(instr.op_32.generates_cc, | ||
| 1736 | "LOP32I Generates an unhandled Control Code"); | ||
| 1737 | |||
| 1768 | if (instr.alu.lop32i.invert_a) | 1738 | if (instr.alu.lop32i.invert_a) |
| 1769 | op_a = "~(" + op_a + ')'; | 1739 | op_a = "~(" + op_a + ')'; |
| 1770 | 1740 | ||
| @@ -1774,16 +1744,11 @@ private: | |||
| 1774 | WriteLogicOperation(instr.gpr0, instr.alu.lop32i.operation, op_a, op_b, | 1744 | WriteLogicOperation(instr.gpr0, instr.alu.lop32i.operation, op_a, op_b, |
| 1775 | Tegra::Shader::PredicateResultMode::None, | 1745 | Tegra::Shader::PredicateResultMode::None, |
| 1776 | Tegra::Shader::Pred::UnusedIndex); | 1746 | Tegra::Shader::Pred::UnusedIndex); |
| 1777 | if (instr.op_32.generates_cc) { | ||
| 1778 | LOG_CRITICAL(HW_GPU, "LOP32I Generates an unhandled Control Code"); | ||
| 1779 | UNREACHABLE(); | ||
| 1780 | } | ||
| 1781 | break; | 1747 | break; |
| 1782 | } | 1748 | } |
| 1783 | default: { | 1749 | default: { |
| 1784 | LOG_CRITICAL(HW_GPU, "Unhandled ArithmeticIntegerImmediate instruction: {}", | 1750 | UNIMPLEMENTED_MSG("Unhandled ArithmeticIntegerImmediate instruction: {}", |
| 1785 | opcode->get().GetName()); | 1751 | opcode->get().GetName()); |
| 1786 | UNREACHABLE(); | ||
| 1787 | } | 1752 | } |
| 1788 | } | 1753 | } |
| 1789 | break; | 1754 | break; |
| @@ -1806,6 +1771,9 @@ private: | |||
| 1806 | case OpCode::Id::IADD_C: | 1771 | case OpCode::Id::IADD_C: |
| 1807 | case OpCode::Id::IADD_R: | 1772 | case OpCode::Id::IADD_R: |
| 1808 | case OpCode::Id::IADD_IMM: { | 1773 | case OpCode::Id::IADD_IMM: { |
| 1774 | UNIMPLEMENTED_IF_MSG(instr.generates_cc, | ||
| 1775 | "IADD Generates an unhandled Control Code"); | ||
| 1776 | |||
| 1809 | if (instr.alu_integer.negate_a) | 1777 | if (instr.alu_integer.negate_a) |
| 1810 | op_a = "-(" + op_a + ')'; | 1778 | op_a = "-(" + op_a + ')'; |
| 1811 | 1779 | ||
| @@ -1814,15 +1782,14 @@ private: | |||
| 1814 | 1782 | ||
| 1815 | regs.SetRegisterToInteger(instr.gpr0, true, 0, op_a + " + " + op_b, 1, 1, | 1783 | regs.SetRegisterToInteger(instr.gpr0, true, 0, op_a + " + " + op_b, 1, 1, |
| 1816 | instr.alu.saturate_d); | 1784 | instr.alu.saturate_d); |
| 1817 | if (instr.generates_cc) { | ||
| 1818 | LOG_CRITICAL(HW_GPU, "IADD Generates an unhandled Control Code"); | ||
| 1819 | UNREACHABLE(); | ||
| 1820 | } | ||
| 1821 | break; | 1785 | break; |
| 1822 | } | 1786 | } |
| 1823 | case OpCode::Id::IADD3_C: | 1787 | case OpCode::Id::IADD3_C: |
| 1824 | case OpCode::Id::IADD3_R: | 1788 | case OpCode::Id::IADD3_R: |
| 1825 | case OpCode::Id::IADD3_IMM: { | 1789 | case OpCode::Id::IADD3_IMM: { |
| 1790 | UNIMPLEMENTED_IF_MSG(instr.generates_cc, | ||
| 1791 | "IADD3 Generates an unhandled Control Code"); | ||
| 1792 | |||
| 1826 | std::string op_c = regs.GetRegisterAsInteger(instr.gpr39); | 1793 | std::string op_c = regs.GetRegisterAsInteger(instr.gpr39); |
| 1827 | 1794 | ||
| 1828 | auto apply_height = [](auto height, auto& oprand) { | 1795 | auto apply_height = [](auto height, auto& oprand) { |
| @@ -1836,9 +1803,8 @@ private: | |||
| 1836 | oprand = "((" + oprand + ") >> 16)"; | 1803 | oprand = "((" + oprand + ") >> 16)"; |
| 1837 | break; | 1804 | break; |
| 1838 | default: | 1805 | default: |
| 1839 | LOG_CRITICAL(HW_GPU, "Unhandled IADD3 height: {}", | 1806 | UNIMPLEMENTED_MSG("Unhandled IADD3 height: {}", |
| 1840 | static_cast<u32>(height.Value())); | 1807 | static_cast<u32>(height.Value())); |
| 1841 | UNREACHABLE(); | ||
| 1842 | } | 1808 | } |
| 1843 | }; | 1809 | }; |
| 1844 | 1810 | ||
| @@ -1879,16 +1845,14 @@ private: | |||
| 1879 | } | 1845 | } |
| 1880 | 1846 | ||
| 1881 | regs.SetRegisterToInteger(instr.gpr0, true, 0, result, 1, 1); | 1847 | regs.SetRegisterToInteger(instr.gpr0, true, 0, result, 1, 1); |
| 1882 | |||
| 1883 | if (instr.generates_cc) { | ||
| 1884 | LOG_CRITICAL(HW_GPU, "IADD3 Generates an unhandled Control Code"); | ||
| 1885 | UNREACHABLE(); | ||
| 1886 | } | ||
| 1887 | break; | 1848 | break; |
| 1888 | } | 1849 | } |
| 1889 | case OpCode::Id::ISCADD_C: | 1850 | case OpCode::Id::ISCADD_C: |
| 1890 | case OpCode::Id::ISCADD_R: | 1851 | case OpCode::Id::ISCADD_R: |
| 1891 | case OpCode::Id::ISCADD_IMM: { | 1852 | case OpCode::Id::ISCADD_IMM: { |
| 1853 | UNIMPLEMENTED_IF_MSG(instr.generates_cc, | ||
| 1854 | "ISCADD Generates an unhandled Control Code"); | ||
| 1855 | |||
| 1892 | if (instr.alu_integer.negate_a) | 1856 | if (instr.alu_integer.negate_a) |
| 1893 | op_a = "-(" + op_a + ')'; | 1857 | op_a = "-(" + op_a + ')'; |
| 1894 | 1858 | ||
| @@ -1899,10 +1863,6 @@ private: | |||
| 1899 | 1863 | ||
| 1900 | regs.SetRegisterToInteger(instr.gpr0, true, 0, | 1864 | regs.SetRegisterToInteger(instr.gpr0, true, 0, |
| 1901 | "((" + op_a + " << " + shift + ") + " + op_b + ')', 1, 1); | 1865 | "((" + op_a + " << " + shift + ") + " + op_b + ')', 1, 1); |
| 1902 | if (instr.generates_cc) { | ||
| 1903 | LOG_CRITICAL(HW_GPU, "ISCADD Generates an unhandled Control Code"); | ||
| 1904 | UNREACHABLE(); | ||
| 1905 | } | ||
| 1906 | break; | 1866 | break; |
| 1907 | } | 1867 | } |
| 1908 | case OpCode::Id::POPC_C: | 1868 | case OpCode::Id::POPC_C: |
| @@ -1926,6 +1886,8 @@ private: | |||
| 1926 | case OpCode::Id::LOP_C: | 1886 | case OpCode::Id::LOP_C: |
| 1927 | case OpCode::Id::LOP_R: | 1887 | case OpCode::Id::LOP_R: |
| 1928 | case OpCode::Id::LOP_IMM: { | 1888 | case OpCode::Id::LOP_IMM: { |
| 1889 | UNIMPLEMENTED_IF_MSG(instr.generates_cc, "LOP Generates an unhandled Control Code"); | ||
| 1890 | |||
| 1929 | if (instr.alu.lop.invert_a) | 1891 | if (instr.alu.lop.invert_a) |
| 1930 | op_a = "~(" + op_a + ')'; | 1892 | op_a = "~(" + op_a + ')'; |
| 1931 | 1893 | ||
| @@ -1934,15 +1896,14 @@ private: | |||
| 1934 | 1896 | ||
| 1935 | WriteLogicOperation(instr.gpr0, instr.alu.lop.operation, op_a, op_b, | 1897 | WriteLogicOperation(instr.gpr0, instr.alu.lop.operation, op_a, op_b, |
| 1936 | instr.alu.lop.pred_result_mode, instr.alu.lop.pred48); | 1898 | instr.alu.lop.pred_result_mode, instr.alu.lop.pred48); |
| 1937 | if (instr.generates_cc) { | ||
| 1938 | LOG_CRITICAL(HW_GPU, "LOP Generates an unhandled Control Code"); | ||
| 1939 | UNREACHABLE(); | ||
| 1940 | } | ||
| 1941 | break; | 1899 | break; |
| 1942 | } | 1900 | } |
| 1943 | case OpCode::Id::LOP3_C: | 1901 | case OpCode::Id::LOP3_C: |
| 1944 | case OpCode::Id::LOP3_R: | 1902 | case OpCode::Id::LOP3_R: |
| 1945 | case OpCode::Id::LOP3_IMM: { | 1903 | case OpCode::Id::LOP3_IMM: { |
| 1904 | UNIMPLEMENTED_IF_MSG(instr.generates_cc, | ||
| 1905 | "LOP3 Generates an unhandled Control Code"); | ||
| 1906 | |||
| 1946 | const std::string op_c = regs.GetRegisterAsInteger(instr.gpr39); | 1907 | const std::string op_c = regs.GetRegisterAsInteger(instr.gpr39); |
| 1947 | std::string lut; | 1908 | std::string lut; |
| 1948 | 1909 | ||
| @@ -1953,17 +1914,15 @@ private: | |||
| 1953 | } | 1914 | } |
| 1954 | 1915 | ||
| 1955 | WriteLop3Instruction(instr.gpr0, op_a, op_b, op_c, lut); | 1916 | WriteLop3Instruction(instr.gpr0, op_a, op_b, op_c, lut); |
| 1956 | if (instr.generates_cc) { | ||
| 1957 | LOG_CRITICAL(HW_GPU, "LOP3 Generates an unhandled Control Code"); | ||
| 1958 | UNREACHABLE(); | ||
| 1959 | } | ||
| 1960 | break; | 1917 | break; |
| 1961 | } | 1918 | } |
| 1962 | case OpCode::Id::IMNMX_C: | 1919 | case OpCode::Id::IMNMX_C: |
| 1963 | case OpCode::Id::IMNMX_R: | 1920 | case OpCode::Id::IMNMX_R: |
| 1964 | case OpCode::Id::IMNMX_IMM: { | 1921 | case OpCode::Id::IMNMX_IMM: { |
| 1965 | ASSERT_MSG(instr.imnmx.exchange == Tegra::Shader::IMinMaxExchange::None, | 1922 | UNIMPLEMENTED_IF(instr.imnmx.exchange != Tegra::Shader::IMinMaxExchange::None); |
| 1966 | "Unimplemented"); | 1923 | UNIMPLEMENTED_IF_MSG(instr.generates_cc, |
| 1924 | "IMNMX Generates an unhandled Control Code"); | ||
| 1925 | |||
| 1967 | const std::string condition = | 1926 | const std::string condition = |
| 1968 | GetPredicateCondition(instr.imnmx.pred, instr.imnmx.negate_pred != 0); | 1927 | GetPredicateCondition(instr.imnmx.pred, instr.imnmx.negate_pred != 0); |
| 1969 | const std::string parameters = op_a + ',' + op_b; | 1928 | const std::string parameters = op_a + ',' + op_b; |
| @@ -1971,10 +1930,6 @@ private: | |||
| 1971 | '(' + condition + ") ? min(" + parameters + ") : max(" + | 1930 | '(' + condition + ") ? min(" + parameters + ") : max(" + |
| 1972 | parameters + ')', | 1931 | parameters + ')', |
| 1973 | 1, 1); | 1932 | 1, 1); |
| 1974 | if (instr.generates_cc) { | ||
| 1975 | LOG_CRITICAL(HW_GPU, "IMNMX Generates an unhandled Control Code"); | ||
| 1976 | UNREACHABLE(); | ||
| 1977 | } | ||
| 1978 | break; | 1933 | break; |
| 1979 | } | 1934 | } |
| 1980 | case OpCode::Id::LEA_R2: | 1935 | case OpCode::Id::LEA_R2: |
| @@ -2029,24 +1984,19 @@ private: | |||
| 2029 | op_b = regs.GetRegisterAsInteger(instr.gpr8); | 1984 | op_b = regs.GetRegisterAsInteger(instr.gpr8); |
| 2030 | op_a = std::to_string(instr.lea.imm.entry_a); | 1985 | op_a = std::to_string(instr.lea.imm.entry_a); |
| 2031 | op_c = std::to_string(instr.lea.imm.entry_b); | 1986 | op_c = std::to_string(instr.lea.imm.entry_b); |
| 2032 | LOG_CRITICAL(HW_GPU, "Unhandled LEA subinstruction: {}", | 1987 | UNIMPLEMENTED_MSG("Unhandled LEA subinstruction: {}", opcode->get().GetName()); |
| 2033 | opcode->get().GetName()); | ||
| 2034 | UNREACHABLE(); | ||
| 2035 | } | 1988 | } |
| 2036 | } | 1989 | } |
| 2037 | if (instr.lea.pred48 != static_cast<u64>(Pred::UnusedIndex)) { | 1990 | UNIMPLEMENTED_IF_MSG(instr.lea.pred48 != static_cast<u64>(Pred::UnusedIndex), |
| 2038 | LOG_ERROR(HW_GPU, "Unhandled LEA Predicate"); | 1991 | "Unhandled LEA Predicate"); |
| 2039 | UNREACHABLE(); | ||
| 2040 | } | ||
| 2041 | const std::string value = '(' + op_a + " + (" + op_b + "*(1 << " + op_c + ")))"; | 1992 | const std::string value = '(' + op_a + " + (" + op_b + "*(1 << " + op_c + ")))"; |
| 2042 | regs.SetRegisterToInteger(instr.gpr0, true, 0, value, 1, 1); | 1993 | regs.SetRegisterToInteger(instr.gpr0, true, 0, value, 1, 1); |
| 2043 | 1994 | ||
| 2044 | break; | 1995 | break; |
| 2045 | } | 1996 | } |
| 2046 | default: { | 1997 | default: { |
| 2047 | LOG_CRITICAL(HW_GPU, "Unhandled ArithmeticInteger instruction: {}", | 1998 | UNIMPLEMENTED_MSG("Unhandled ArithmeticInteger instruction: {}", |
| 2048 | opcode->get().GetName()); | 1999 | opcode->get().GetName()); |
| 2049 | UNREACHABLE(); | ||
| 2050 | } | 2000 | } |
| 2051 | } | 2001 | } |
| 2052 | 2002 | ||
| @@ -2055,7 +2005,7 @@ private: | |||
| 2055 | case OpCode::Type::ArithmeticHalf: { | 2005 | case OpCode::Type::ArithmeticHalf: { |
| 2056 | if (opcode->get().GetId() == OpCode::Id::HADD2_C || | 2006 | if (opcode->get().GetId() == OpCode::Id::HADD2_C || |
| 2057 | opcode->get().GetId() == OpCode::Id::HADD2_R) { | 2007 | opcode->get().GetId() == OpCode::Id::HADD2_R) { |
| 2058 | ASSERT_MSG(instr.alu_half.ftz == 0, "Unimplemented"); | 2008 | UNIMPLEMENTED_IF(instr.alu_half.ftz != 0); |
| 2059 | } | 2009 | } |
| 2060 | const bool negate_a = | 2010 | const bool negate_a = |
| 2061 | opcode->get().GetId() != OpCode::Id::HMUL2_R && instr.alu_half.negate_a != 0; | 2011 | opcode->get().GetId() != OpCode::Id::HMUL2_R && instr.alu_half.negate_a != 0; |
| @@ -2093,9 +2043,8 @@ private: | |||
| 2093 | case OpCode::Id::HMUL2_R: | 2043 | case OpCode::Id::HMUL2_R: |
| 2094 | return '(' + op_a + " * " + op_b + ')'; | 2044 | return '(' + op_a + " * " + op_b + ')'; |
| 2095 | default: | 2045 | default: |
| 2096 | LOG_CRITICAL(HW_GPU, "Unhandled half float instruction: {}", | 2046 | UNIMPLEMENTED_MSG("Unhandled half float instruction: {}", |
| 2097 | opcode->get().GetName()); | 2047 | opcode->get().GetName()); |
| 2098 | UNREACHABLE(); | ||
| 2099 | return std::string("0"); | 2048 | return std::string("0"); |
| 2100 | } | 2049 | } |
| 2101 | }(); | 2050 | }(); |
| @@ -2106,10 +2055,10 @@ private: | |||
| 2106 | } | 2055 | } |
| 2107 | case OpCode::Type::ArithmeticHalfImmediate: { | 2056 | case OpCode::Type::ArithmeticHalfImmediate: { |
| 2108 | if (opcode->get().GetId() == OpCode::Id::HADD2_IMM) { | 2057 | if (opcode->get().GetId() == OpCode::Id::HADD2_IMM) { |
| 2109 | ASSERT_MSG(instr.alu_half_imm.ftz == 0, "Unimplemented"); | 2058 | UNIMPLEMENTED_IF(instr.alu_half_imm.ftz != 0); |
| 2110 | } else { | 2059 | } else { |
| 2111 | ASSERT_MSG(instr.alu_half_imm.precision == Tegra::Shader::HalfPrecision::None, | 2060 | UNIMPLEMENTED_IF(instr.alu_half_imm.precision != |
| 2112 | "Unimplemented"); | 2061 | Tegra::Shader::HalfPrecision::None); |
| 2113 | } | 2062 | } |
| 2114 | 2063 | ||
| 2115 | const std::string op_a = GetHalfFloat( | 2064 | const std::string op_a = GetHalfFloat( |
| @@ -2139,11 +2088,13 @@ private: | |||
| 2139 | std::string op_b = instr.ffma.negate_b ? "-" : ""; | 2088 | std::string op_b = instr.ffma.negate_b ? "-" : ""; |
| 2140 | std::string op_c = instr.ffma.negate_c ? "-" : ""; | 2089 | std::string op_c = instr.ffma.negate_c ? "-" : ""; |
| 2141 | 2090 | ||
| 2142 | ASSERT_MSG(instr.ffma.cc == 0, "FFMA cc not implemented"); | 2091 | UNIMPLEMENTED_IF_MSG(instr.ffma.cc != 0, "FFMA cc not implemented"); |
| 2143 | ASSERT_MSG(instr.ffma.tab5980_0 == 1, "FFMA tab5980_0({}) not implemented", | 2092 | UNIMPLEMENTED_IF_MSG( |
| 2144 | instr.ffma.tab5980_0.Value()); // Seems to be 1 by default based on SMO | 2093 | instr.ffma.tab5980_0 != 1, "FFMA tab5980_0({}) not implemented", |
| 2145 | ASSERT_MSG(instr.ffma.tab5980_1 == 0, "FFMA tab5980_1({}) not implemented", | 2094 | instr.ffma.tab5980_0.Value()); // Seems to be 1 by default based on SMO |
| 2146 | instr.ffma.tab5980_1.Value()); | 2095 | UNIMPLEMENTED_IF_MSG(instr.ffma.tab5980_1 != 0, "FFMA tab5980_1({}) not implemented", |
| 2096 | instr.ffma.tab5980_1.Value()); | ||
| 2097 | UNIMPLEMENTED_IF_MSG(instr.generates_cc, "FFMA Generates an unhandled Control Code"); | ||
| 2147 | 2098 | ||
| 2148 | switch (opcode->get().GetId()) { | 2099 | switch (opcode->get().GetId()) { |
| 2149 | case OpCode::Id::FFMA_CR: { | 2100 | case OpCode::Id::FFMA_CR: { |
| @@ -2169,27 +2120,19 @@ private: | |||
| 2169 | break; | 2120 | break; |
| 2170 | } | 2121 | } |
| 2171 | default: { | 2122 | default: { |
| 2172 | LOG_CRITICAL(HW_GPU, "Unhandled FFMA instruction: {}", opcode->get().GetName()); | 2123 | UNIMPLEMENTED_MSG("Unhandled FFMA instruction: {}", opcode->get().GetName()); |
| 2173 | UNREACHABLE(); | ||
| 2174 | } | 2124 | } |
| 2175 | } | 2125 | } |
| 2176 | 2126 | ||
| 2177 | regs.SetRegisterToFloat(instr.gpr0, 0, "fma(" + op_a + ", " + op_b + ", " + op_c + ')', | 2127 | regs.SetRegisterToFloat(instr.gpr0, 0, "fma(" + op_a + ", " + op_b + ", " + op_c + ')', |
| 2178 | 1, 1, instr.alu.saturate_d, 0, true); | 2128 | 1, 1, instr.alu.saturate_d, 0, true); |
| 2179 | if (instr.generates_cc) { | ||
| 2180 | LOG_CRITICAL(HW_GPU, "FFMA Generates an unhandled Control Code"); | ||
| 2181 | UNREACHABLE(); | ||
| 2182 | } | ||
| 2183 | |||
| 2184 | break; | 2129 | break; |
| 2185 | } | 2130 | } |
| 2186 | case OpCode::Type::Hfma2: { | 2131 | case OpCode::Type::Hfma2: { |
| 2187 | if (opcode->get().GetId() == OpCode::Id::HFMA2_RR) { | 2132 | if (opcode->get().GetId() == OpCode::Id::HFMA2_RR) { |
| 2188 | ASSERT_MSG(instr.hfma2.rr.precision == Tegra::Shader::HalfPrecision::None, | 2133 | UNIMPLEMENTED_IF(instr.hfma2.rr.precision != Tegra::Shader::HalfPrecision::None); |
| 2189 | "Unimplemented"); | ||
| 2190 | } else { | 2134 | } else { |
| 2191 | ASSERT_MSG(instr.hfma2.precision == Tegra::Shader::HalfPrecision::None, | 2135 | UNIMPLEMENTED_IF(instr.hfma2.precision != Tegra::Shader::HalfPrecision::None); |
| 2192 | "Unimplemented"); | ||
| 2193 | } | 2136 | } |
| 2194 | const bool saturate = opcode->get().GetId() == OpCode::Id::HFMA2_RR | 2137 | const bool saturate = opcode->get().GetId() == OpCode::Id::HFMA2_RR |
| 2195 | ? instr.hfma2.rr.saturate != 0 | 2138 | ? instr.hfma2.rr.saturate != 0 |
| @@ -2239,7 +2182,7 @@ private: | |||
| 2239 | case OpCode::Type::Conversion: { | 2182 | case OpCode::Type::Conversion: { |
| 2240 | switch (opcode->get().GetId()) { | 2183 | switch (opcode->get().GetId()) { |
| 2241 | case OpCode::Id::I2I_R: { | 2184 | case OpCode::Id::I2I_R: { |
| 2242 | ASSERT_MSG(!instr.conversion.selector, "Unimplemented"); | 2185 | UNIMPLEMENTED_IF(instr.conversion.selector); |
| 2243 | 2186 | ||
| 2244 | std::string op_a = regs.GetRegisterAsInteger( | 2187 | std::string op_a = regs.GetRegisterAsInteger( |
| 2245 | instr.gpr20, 0, instr.conversion.is_input_signed, instr.conversion.src_size); | 2188 | instr.gpr20, 0, instr.conversion.is_input_signed, instr.conversion.src_size); |
| @@ -2259,8 +2202,9 @@ private: | |||
| 2259 | } | 2202 | } |
| 2260 | case OpCode::Id::I2F_R: | 2203 | case OpCode::Id::I2F_R: |
| 2261 | case OpCode::Id::I2F_C: { | 2204 | case OpCode::Id::I2F_C: { |
| 2262 | ASSERT_MSG(instr.conversion.dest_size == Register::Size::Word, "Unimplemented"); | 2205 | UNIMPLEMENTED_IF(instr.conversion.dest_size != Register::Size::Word); |
| 2263 | ASSERT_MSG(!instr.conversion.selector, "Unimplemented"); | 2206 | UNIMPLEMENTED_IF(instr.conversion.selector); |
| 2207 | UNIMPLEMENTED_IF_MSG(instr.generates_cc, "I2F Generates an unhandled Control Code"); | ||
| 2264 | 2208 | ||
| 2265 | std::string op_a{}; | 2209 | std::string op_a{}; |
| 2266 | 2210 | ||
| @@ -2285,16 +2229,12 @@ private: | |||
| 2285 | } | 2229 | } |
| 2286 | 2230 | ||
| 2287 | regs.SetRegisterToFloat(instr.gpr0, 0, op_a, 1, 1); | 2231 | regs.SetRegisterToFloat(instr.gpr0, 0, op_a, 1, 1); |
| 2288 | |||
| 2289 | if (instr.generates_cc) { | ||
| 2290 | LOG_CRITICAL(HW_GPU, "I2F Generates an unhandled Control Code"); | ||
| 2291 | UNREACHABLE(); | ||
| 2292 | } | ||
| 2293 | break; | 2232 | break; |
| 2294 | } | 2233 | } |
| 2295 | case OpCode::Id::F2F_R: { | 2234 | case OpCode::Id::F2F_R: { |
| 2296 | ASSERT_MSG(instr.conversion.dest_size == Register::Size::Word, "Unimplemented"); | 2235 | UNIMPLEMENTED_IF(instr.conversion.dest_size != Register::Size::Word); |
| 2297 | ASSERT_MSG(instr.conversion.src_size == Register::Size::Word, "Unimplemented"); | 2236 | UNIMPLEMENTED_IF(instr.conversion.src_size != Register::Size::Word); |
| 2237 | UNIMPLEMENTED_IF_MSG(instr.generates_cc, "F2F Generates an unhandled Control Code"); | ||
| 2298 | std::string op_a = regs.GetRegisterAsFloat(instr.gpr20); | 2238 | std::string op_a = regs.GetRegisterAsFloat(instr.gpr20); |
| 2299 | 2239 | ||
| 2300 | if (instr.conversion.abs_a) { | 2240 | if (instr.conversion.abs_a) { |
| @@ -2321,23 +2261,18 @@ private: | |||
| 2321 | op_a = "trunc(" + op_a + ')'; | 2261 | op_a = "trunc(" + op_a + ')'; |
| 2322 | break; | 2262 | break; |
| 2323 | default: | 2263 | default: |
| 2324 | LOG_CRITICAL(HW_GPU, "Unimplemented f2f rounding mode {}", | 2264 | UNIMPLEMENTED_MSG("Unimplemented F2F rounding mode {}", |
| 2325 | static_cast<u32>(instr.conversion.f2f.rounding.Value())); | 2265 | static_cast<u32>(instr.conversion.f2f.rounding.Value())); |
| 2326 | UNREACHABLE(); | ||
| 2327 | break; | 2266 | break; |
| 2328 | } | 2267 | } |
| 2329 | 2268 | ||
| 2330 | regs.SetRegisterToFloat(instr.gpr0, 0, op_a, 1, 1, instr.alu.saturate_d); | 2269 | regs.SetRegisterToFloat(instr.gpr0, 0, op_a, 1, 1, instr.alu.saturate_d); |
| 2331 | |||
| 2332 | if (instr.generates_cc) { | ||
| 2333 | LOG_CRITICAL(HW_GPU, "F2F Generates an unhandled Control Code"); | ||
| 2334 | UNREACHABLE(); | ||
| 2335 | } | ||
| 2336 | break; | 2270 | break; |
| 2337 | } | 2271 | } |
| 2338 | case OpCode::Id::F2I_R: | 2272 | case OpCode::Id::F2I_R: |
| 2339 | case OpCode::Id::F2I_C: { | 2273 | case OpCode::Id::F2I_C: { |
| 2340 | ASSERT_MSG(instr.conversion.src_size == Register::Size::Word, "Unimplemented"); | 2274 | UNIMPLEMENTED_IF(instr.conversion.src_size != Register::Size::Word); |
| 2275 | UNIMPLEMENTED_IF_MSG(instr.generates_cc, "F2I Generates an unhandled Control Code"); | ||
| 2341 | std::string op_a{}; | 2276 | std::string op_a{}; |
| 2342 | 2277 | ||
| 2343 | if (instr.is_b_gpr) { | 2278 | if (instr.is_b_gpr) { |
| @@ -2368,9 +2303,8 @@ private: | |||
| 2368 | op_a = "trunc(" + op_a + ')'; | 2303 | op_a = "trunc(" + op_a + ')'; |
| 2369 | break; | 2304 | break; |
| 2370 | default: | 2305 | default: |
| 2371 | LOG_CRITICAL(HW_GPU, "Unimplemented f2i rounding mode {}", | 2306 | UNIMPLEMENTED_MSG("Unimplemented F2I rounding mode {}", |
| 2372 | static_cast<u32>(instr.conversion.f2i.rounding.Value())); | 2307 | static_cast<u32>(instr.conversion.f2i.rounding.Value())); |
| 2373 | UNREACHABLE(); | ||
| 2374 | break; | 2308 | break; |
| 2375 | } | 2309 | } |
| 2376 | 2310 | ||
| @@ -2382,16 +2316,10 @@ private: | |||
| 2382 | 2316 | ||
| 2383 | regs.SetRegisterToInteger(instr.gpr0, instr.conversion.is_output_signed, 0, op_a, 1, | 2317 | regs.SetRegisterToInteger(instr.gpr0, instr.conversion.is_output_signed, 0, op_a, 1, |
| 2384 | 1, false, 0, instr.conversion.dest_size); | 2318 | 1, false, 0, instr.conversion.dest_size); |
| 2385 | if (instr.generates_cc) { | ||
| 2386 | LOG_CRITICAL(HW_GPU, "F2I Generates an unhandled Control Code"); | ||
| 2387 | UNREACHABLE(); | ||
| 2388 | } | ||
| 2389 | break; | 2319 | break; |
| 2390 | } | 2320 | } |
| 2391 | default: { | 2321 | default: { |
| 2392 | LOG_CRITICAL(HW_GPU, "Unhandled conversion instruction: {}", | 2322 | UNIMPLEMENTED_MSG("Unhandled conversion instruction: {}", opcode->get().GetName()); |
| 2393 | opcode->get().GetName()); | ||
| 2394 | UNREACHABLE(); | ||
| 2395 | } | 2323 | } |
| 2396 | } | 2324 | } |
| 2397 | break; | 2325 | break; |
| @@ -2400,10 +2328,10 @@ private: | |||
| 2400 | switch (opcode->get().GetId()) { | 2328 | switch (opcode->get().GetId()) { |
| 2401 | case OpCode::Id::LD_A: { | 2329 | case OpCode::Id::LD_A: { |
| 2402 | // Note: Shouldn't this be interp mode flat? As in no interpolation made. | 2330 | // Note: Shouldn't this be interp mode flat? As in no interpolation made. |
| 2403 | ASSERT_MSG(instr.gpr8.Value() == Register::ZeroIndex, | 2331 | UNIMPLEMENTED_IF_MSG(instr.gpr8.Value() != Register::ZeroIndex, |
| 2404 | "Indirect attribute loads are not supported"); | 2332 | "Indirect attribute loads are not supported"); |
| 2405 | ASSERT_MSG((instr.attribute.fmt20.immediate.Value() % sizeof(u32)) == 0, | 2333 | UNIMPLEMENTED_IF_MSG((instr.attribute.fmt20.immediate.Value() % sizeof(u32)) != 0, |
| 2406 | "Unaligned attribute loads are not supported"); | 2334 | "Unaligned attribute loads are not supported"); |
| 2407 | 2335 | ||
| 2408 | Tegra::Shader::IpaMode input_mode{Tegra::Shader::IpaInterpMode::Perspective, | 2336 | Tegra::Shader::IpaMode input_mode{Tegra::Shader::IpaInterpMode::Perspective, |
| 2409 | Tegra::Shader::IpaSampleMode::Default}; | 2337 | Tegra::Shader::IpaSampleMode::Default}; |
| @@ -2430,7 +2358,7 @@ private: | |||
| 2430 | break; | 2358 | break; |
| 2431 | } | 2359 | } |
| 2432 | case OpCode::Id::LD_C: { | 2360 | case OpCode::Id::LD_C: { |
| 2433 | ASSERT_MSG(instr.ld_c.unknown == 0, "Unimplemented"); | 2361 | UNIMPLEMENTED_IF(instr.ld_c.unknown != 0); |
| 2434 | 2362 | ||
| 2435 | // Add an extra scope and declare the index register inside to prevent | 2363 | // Add an extra scope and declare the index register inside to prevent |
| 2436 | // overwriting it in case it is used as an output of the LD instruction. | 2364 | // overwriting it in case it is used as an output of the LD instruction. |
| @@ -2458,9 +2386,8 @@ private: | |||
| 2458 | break; | 2386 | break; |
| 2459 | } | 2387 | } |
| 2460 | default: | 2388 | default: |
| 2461 | LOG_CRITICAL(HW_GPU, "Unhandled type: {}", | 2389 | UNIMPLEMENTED_MSG("Unhandled type: {}", |
| 2462 | static_cast<unsigned>(instr.ld_c.type.Value())); | 2390 | static_cast<unsigned>(instr.ld_c.type.Value())); |
| 2463 | UNREACHABLE(); | ||
| 2464 | } | 2391 | } |
| 2465 | 2392 | ||
| 2466 | --shader.scope; | 2393 | --shader.scope; |
| @@ -2468,6 +2395,9 @@ private: | |||
| 2468 | break; | 2395 | break; |
| 2469 | } | 2396 | } |
| 2470 | case OpCode::Id::LD_L: { | 2397 | case OpCode::Id::LD_L: { |
| 2398 | UNIMPLEMENTED_IF_MSG(instr.ld_l.unknown == 1, "LD_L Unhandled mode: {}", | ||
| 2399 | static_cast<unsigned>(instr.ld_l.unknown.Value())); | ||
| 2400 | |||
| 2471 | // Add an extra scope and declare the index register inside to prevent | 2401 | // Add an extra scope and declare the index register inside to prevent |
| 2472 | // overwriting it in case it is used as an output of the LD instruction. | 2402 | // overwriting it in case it is used as an output of the LD instruction. |
| 2473 | shader.AddLine('{'); | 2403 | shader.AddLine('{'); |
| @@ -2480,20 +2410,13 @@ private: | |||
| 2480 | 2410 | ||
| 2481 | const std::string op_a = regs.GetLocalMemoryAsFloat("index"); | 2411 | const std::string op_a = regs.GetLocalMemoryAsFloat("index"); |
| 2482 | 2412 | ||
| 2483 | if (instr.ld_l.unknown != 1) { | ||
| 2484 | LOG_CRITICAL(HW_GPU, "LD_L Unhandled mode: {}", | ||
| 2485 | static_cast<unsigned>(instr.ld_l.unknown.Value())); | ||
| 2486 | UNREACHABLE(); | ||
| 2487 | } | ||
| 2488 | |||
| 2489 | switch (instr.ldst_sl.type.Value()) { | 2413 | switch (instr.ldst_sl.type.Value()) { |
| 2490 | case Tegra::Shader::StoreType::Bytes32: | 2414 | case Tegra::Shader::StoreType::Bytes32: |
| 2491 | regs.SetRegisterToFloat(instr.gpr0, 0, op_a, 1, 1); | 2415 | regs.SetRegisterToFloat(instr.gpr0, 0, op_a, 1, 1); |
| 2492 | break; | 2416 | break; |
| 2493 | default: | 2417 | default: |
| 2494 | LOG_CRITICAL(HW_GPU, "LD_L Unhandled type: {}", | 2418 | UNIMPLEMENTED_MSG("LD_L Unhandled type: {}", |
| 2495 | static_cast<unsigned>(instr.ldst_sl.type.Value())); | 2419 | static_cast<unsigned>(instr.ldst_sl.type.Value())); |
| 2496 | UNREACHABLE(); | ||
| 2497 | } | 2420 | } |
| 2498 | 2421 | ||
| 2499 | --shader.scope; | 2422 | --shader.scope; |
| @@ -2501,10 +2424,10 @@ private: | |||
| 2501 | break; | 2424 | break; |
| 2502 | } | 2425 | } |
| 2503 | case OpCode::Id::ST_A: { | 2426 | case OpCode::Id::ST_A: { |
| 2504 | ASSERT_MSG(instr.gpr8.Value() == Register::ZeroIndex, | 2427 | UNIMPLEMENTED_IF_MSG(instr.gpr8.Value() != Register::ZeroIndex, |
| 2505 | "Indirect attribute loads are not supported"); | 2428 | "Indirect attribute loads are not supported"); |
| 2506 | ASSERT_MSG((instr.attribute.fmt20.immediate.Value() % sizeof(u32)) == 0, | 2429 | UNIMPLEMENTED_IF_MSG((instr.attribute.fmt20.immediate.Value() % sizeof(u32)) != 0, |
| 2507 | "Unaligned attribute loads are not supported"); | 2430 | "Unaligned attribute loads are not supported"); |
| 2508 | 2431 | ||
| 2509 | u64 next_element = instr.attribute.fmt20.element; | 2432 | u64 next_element = instr.attribute.fmt20.element; |
| 2510 | u64 next_index = static_cast<u64>(instr.attribute.fmt20.index.Value()); | 2433 | u64 next_index = static_cast<u64>(instr.attribute.fmt20.index.Value()); |
| @@ -2529,6 +2452,9 @@ private: | |||
| 2529 | break; | 2452 | break; |
| 2530 | } | 2453 | } |
| 2531 | case OpCode::Id::ST_L: { | 2454 | case OpCode::Id::ST_L: { |
| 2455 | UNIMPLEMENTED_IF_MSG(instr.st_l.unknown == 0, "ST_L Unhandled mode: {}", | ||
| 2456 | static_cast<unsigned>(instr.st_l.unknown.Value())); | ||
| 2457 | |||
| 2532 | // Add an extra scope and declare the index register inside to prevent | 2458 | // Add an extra scope and declare the index register inside to prevent |
| 2533 | // overwriting it in case it is used as an output of the LD instruction. | 2459 | // overwriting it in case it is used as an output of the LD instruction. |
| 2534 | shader.AddLine('{'); | 2460 | shader.AddLine('{'); |
| @@ -2539,20 +2465,13 @@ private: | |||
| 2539 | 2465 | ||
| 2540 | shader.AddLine("uint index = (" + op + " / 4);"); | 2466 | shader.AddLine("uint index = (" + op + " / 4);"); |
| 2541 | 2467 | ||
| 2542 | if (instr.st_l.unknown != 0) { | ||
| 2543 | LOG_CRITICAL(HW_GPU, "ST_L Unhandled mode: {}", | ||
| 2544 | static_cast<unsigned>(instr.st_l.unknown.Value())); | ||
| 2545 | UNREACHABLE(); | ||
| 2546 | } | ||
| 2547 | |||
| 2548 | switch (instr.ldst_sl.type.Value()) { | 2468 | switch (instr.ldst_sl.type.Value()) { |
| 2549 | case Tegra::Shader::StoreType::Bytes32: | 2469 | case Tegra::Shader::StoreType::Bytes32: |
| 2550 | regs.SetLocalMemoryAsFloat("index", regs.GetRegisterAsFloat(instr.gpr0)); | 2470 | regs.SetLocalMemoryAsFloat("index", regs.GetRegisterAsFloat(instr.gpr0)); |
| 2551 | break; | 2471 | break; |
| 2552 | default: | 2472 | default: |
| 2553 | LOG_CRITICAL(HW_GPU, "ST_L Unhandled type: {}", | 2473 | UNIMPLEMENTED_MSG("ST_L Unhandled type: {}", |
| 2554 | static_cast<unsigned>(instr.ldst_sl.type.Value())); | 2474 | static_cast<unsigned>(instr.ldst_sl.type.Value())); |
| 2555 | UNREACHABLE(); | ||
| 2556 | } | 2475 | } |
| 2557 | 2476 | ||
| 2558 | --shader.scope; | 2477 | --shader.scope; |
| @@ -2564,10 +2483,10 @@ private: | |||
| 2564 | std::string coord; | 2483 | std::string coord; |
| 2565 | const bool is_array = instr.tex.array != 0; | 2484 | const bool is_array = instr.tex.array != 0; |
| 2566 | 2485 | ||
| 2567 | ASSERT_MSG(!instr.tex.UsesMiscMode(Tegra::Shader::TextureMiscMode::NODEP), | 2486 | UNIMPLEMENTED_IF_MSG(instr.tex.UsesMiscMode(Tegra::Shader::TextureMiscMode::NODEP), |
| 2568 | "NODEP is not implemented"); | 2487 | "NODEP is not implemented"); |
| 2569 | ASSERT_MSG(!instr.tex.UsesMiscMode(Tegra::Shader::TextureMiscMode::AOFFI), | 2488 | UNIMPLEMENTED_IF_MSG(instr.tex.UsesMiscMode(Tegra::Shader::TextureMiscMode::AOFFI), |
| 2570 | "AOFFI is not implemented"); | 2489 | "AOFFI is not implemented"); |
| 2571 | 2490 | ||
| 2572 | const bool depth_compare = | 2491 | const bool depth_compare = |
| 2573 | instr.tex.UsesMiscMode(Tegra::Shader::TextureMiscMode::DC); | 2492 | instr.tex.UsesMiscMode(Tegra::Shader::TextureMiscMode::DC); |
| @@ -2633,9 +2552,8 @@ private: | |||
| 2633 | break; | 2552 | break; |
| 2634 | } | 2553 | } |
| 2635 | default: | 2554 | default: |
| 2636 | LOG_CRITICAL(HW_GPU, "Unhandled coordinates number {}", | 2555 | UNIMPLEMENTED_MSG("Unhandled coordinates number {}", |
| 2637 | static_cast<u32>(num_coordinates)); | 2556 | static_cast<u32>(num_coordinates)); |
| 2638 | UNREACHABLE(); | ||
| 2639 | 2557 | ||
| 2640 | // Fallback to interpreting as a 2D texture for now | 2558 | // Fallback to interpreting as a 2D texture for now |
| 2641 | const std::string x = regs.GetRegisterAsFloat(instr.gpr8); | 2559 | const std::string x = regs.GetRegisterAsFloat(instr.gpr8); |
| @@ -2693,9 +2611,8 @@ private: | |||
| 2693 | } | 2611 | } |
| 2694 | default: { | 2612 | default: { |
| 2695 | texture = "texture(" + sampler + ", coords)"; | 2613 | texture = "texture(" + sampler + ", coords)"; |
| 2696 | LOG_CRITICAL(HW_GPU, "Unhandled texture process mode {}", | 2614 | UNIMPLEMENTED_MSG("Unhandled texture process mode {}", |
| 2697 | static_cast<u32>(instr.tex.GetTextureProcessMode())); | 2615 | static_cast<u32>(instr.tex.GetTextureProcessMode())); |
| 2698 | UNREACHABLE(); | ||
| 2699 | } | 2616 | } |
| 2700 | } | 2617 | } |
| 2701 | if (!depth_compare) { | 2618 | if (!depth_compare) { |
| @@ -2720,8 +2637,8 @@ private: | |||
| 2720 | Tegra::Shader::TextureType texture_type{instr.texs.GetTextureType()}; | 2637 | Tegra::Shader::TextureType texture_type{instr.texs.GetTextureType()}; |
| 2721 | bool is_array{instr.texs.IsArrayTexture()}; | 2638 | bool is_array{instr.texs.IsArrayTexture()}; |
| 2722 | 2639 | ||
| 2723 | ASSERT_MSG(!instr.texs.UsesMiscMode(Tegra::Shader::TextureMiscMode::NODEP), | 2640 | UNIMPLEMENTED_IF_MSG(instr.texs.UsesMiscMode(Tegra::Shader::TextureMiscMode::NODEP), |
| 2724 | "NODEP is not implemented"); | 2641 | "NODEP is not implemented"); |
| 2725 | 2642 | ||
| 2726 | const bool depth_compare = | 2643 | const bool depth_compare = |
| 2727 | instr.texs.UsesMiscMode(Tegra::Shader::TextureMiscMode::DC); | 2644 | instr.texs.UsesMiscMode(Tegra::Shader::TextureMiscMode::DC); |
| @@ -2760,9 +2677,8 @@ private: | |||
| 2760 | break; | 2677 | break; |
| 2761 | } | 2678 | } |
| 2762 | default: | 2679 | default: |
| 2763 | LOG_CRITICAL(HW_GPU, "Unhandled coordinates number {}", | 2680 | UNIMPLEMENTED_MSG("Unhandled coordinates number {}", |
| 2764 | static_cast<u32>(num_coordinates)); | 2681 | static_cast<u32>(num_coordinates)); |
| 2765 | UNREACHABLE(); | ||
| 2766 | 2682 | ||
| 2767 | // Fallback to interpreting as a 2D texture for now | 2683 | // Fallback to interpreting as a 2D texture for now |
| 2768 | const std::string x = regs.GetRegisterAsFloat(instr.gpr8); | 2684 | const std::string x = regs.GetRegisterAsFloat(instr.gpr8); |
| @@ -2794,9 +2710,8 @@ private: | |||
| 2794 | } | 2710 | } |
| 2795 | default: { | 2711 | default: { |
| 2796 | texture = "texture(" + sampler + ", coords)"; | 2712 | texture = "texture(" + sampler + ", coords)"; |
| 2797 | LOG_CRITICAL(HW_GPU, "Unhandled texture process mode {}", | 2713 | UNIMPLEMENTED_MSG("Unhandled texture process mode {}", |
| 2798 | static_cast<u32>(instr.texs.GetTextureProcessMode())); | 2714 | static_cast<u32>(instr.texs.GetTextureProcessMode())); |
| 2799 | UNREACHABLE(); | ||
| 2800 | } | 2715 | } |
| 2801 | } | 2716 | } |
| 2802 | if (!depth_compare) { | 2717 | if (!depth_compare) { |
| @@ -2814,12 +2729,12 @@ private: | |||
| 2814 | ASSERT(texture_type == Tegra::Shader::TextureType::Texture2D); | 2729 | ASSERT(texture_type == Tegra::Shader::TextureType::Texture2D); |
| 2815 | ASSERT(is_array == false); | 2730 | ASSERT(is_array == false); |
| 2816 | 2731 | ||
| 2817 | ASSERT_MSG(!instr.tlds.UsesMiscMode(Tegra::Shader::TextureMiscMode::NODEP), | 2732 | UNIMPLEMENTED_IF_MSG(instr.tlds.UsesMiscMode(Tegra::Shader::TextureMiscMode::NODEP), |
| 2818 | "NODEP is not implemented"); | 2733 | "NODEP is not implemented"); |
| 2819 | ASSERT_MSG(!instr.tlds.UsesMiscMode(Tegra::Shader::TextureMiscMode::AOFFI), | 2734 | UNIMPLEMENTED_IF_MSG(instr.tlds.UsesMiscMode(Tegra::Shader::TextureMiscMode::AOFFI), |
| 2820 | "AOFFI is not implemented"); | 2735 | "AOFFI is not implemented"); |
| 2821 | ASSERT_MSG(!instr.tlds.UsesMiscMode(Tegra::Shader::TextureMiscMode::MZ), | 2736 | UNIMPLEMENTED_IF_MSG(instr.tlds.UsesMiscMode(Tegra::Shader::TextureMiscMode::MZ), |
| 2822 | "MZ is not implemented"); | 2737 | "MZ is not implemented"); |
| 2823 | 2738 | ||
| 2824 | u32 op_c_offset = 0; | 2739 | u32 op_c_offset = 0; |
| 2825 | 2740 | ||
| @@ -2830,21 +2745,16 @@ private: | |||
| 2830 | break; | 2745 | break; |
| 2831 | } | 2746 | } |
| 2832 | case Tegra::Shader::TextureType::Texture2D: { | 2747 | case Tegra::Shader::TextureType::Texture2D: { |
| 2833 | if (is_array) { | 2748 | UNIMPLEMENTED_IF_MSG(is_array, "Unhandled 2d array texture"); |
| 2834 | LOG_CRITICAL(HW_GPU, "Unhandled 2d array texture"); | 2749 | |
| 2835 | UNREACHABLE(); | 2750 | const std::string x = regs.GetRegisterAsInteger(instr.gpr8); |
| 2836 | } else { | 2751 | const std::string y = regs.GetRegisterAsInteger(instr.gpr20); |
| 2837 | const std::string x = regs.GetRegisterAsInteger(instr.gpr8); | 2752 | coord = "ivec2 coords = ivec2(" + x + ", " + y + ");"; |
| 2838 | const std::string y = regs.GetRegisterAsInteger(instr.gpr20); | 2753 | op_c_offset = 1; |
| 2839 | coord = "ivec2 coords = ivec2(" + x + ", " + y + ");"; | ||
| 2840 | op_c_offset = 1; | ||
| 2841 | } | ||
| 2842 | break; | 2754 | break; |
| 2843 | } | 2755 | } |
| 2844 | default: | 2756 | default: |
| 2845 | LOG_CRITICAL(HW_GPU, "Unhandled texture type {}", | 2757 | UNIMPLEMENTED_MSG("Unhandled texture type {}", static_cast<u32>(texture_type)); |
| 2846 | static_cast<u32>(texture_type)); | ||
| 2847 | UNREACHABLE(); | ||
| 2848 | } | 2758 | } |
| 2849 | const std::string sampler = | 2759 | const std::string sampler = |
| 2850 | GetSampler(instr.sampler, texture_type, is_array, false); | 2760 | GetSampler(instr.sampler, texture_type, is_array, false); |
| @@ -2862,9 +2772,8 @@ private: | |||
| 2862 | } | 2772 | } |
| 2863 | default: { | 2773 | default: { |
| 2864 | texture = "texelFetch(" + sampler + ", coords, 0)"; | 2774 | texture = "texelFetch(" + sampler + ", coords, 0)"; |
| 2865 | LOG_CRITICAL(HW_GPU, "Unhandled texture process mode {}", | 2775 | UNIMPLEMENTED_MSG("Unhandled texture process mode {}", |
| 2866 | static_cast<u32>(instr.tlds.GetTextureProcessMode())); | 2776 | static_cast<u32>(instr.tlds.GetTextureProcessMode())); |
| 2867 | UNREACHABLE(); | ||
| 2868 | } | 2777 | } |
| 2869 | } | 2778 | } |
| 2870 | WriteTexsInstruction(instr, coord, texture); | 2779 | WriteTexsInstruction(instr, coord, texture); |
| @@ -2875,14 +2784,14 @@ private: | |||
| 2875 | ASSERT(instr.tld4.array == 0); | 2784 | ASSERT(instr.tld4.array == 0); |
| 2876 | std::string coord; | 2785 | std::string coord; |
| 2877 | 2786 | ||
| 2878 | ASSERT_MSG(!instr.tld4.UsesMiscMode(Tegra::Shader::TextureMiscMode::NODEP), | 2787 | UNIMPLEMENTED_IF_MSG(instr.tld4.UsesMiscMode(Tegra::Shader::TextureMiscMode::NODEP), |
| 2879 | "NODEP is not implemented"); | 2788 | "NODEP is not implemented"); |
| 2880 | ASSERT_MSG(!instr.tld4.UsesMiscMode(Tegra::Shader::TextureMiscMode::AOFFI), | 2789 | UNIMPLEMENTED_IF_MSG(instr.tld4.UsesMiscMode(Tegra::Shader::TextureMiscMode::AOFFI), |
| 2881 | "AOFFI is not implemented"); | 2790 | "AOFFI is not implemented"); |
| 2882 | ASSERT_MSG(!instr.tld4.UsesMiscMode(Tegra::Shader::TextureMiscMode::NDV), | 2791 | UNIMPLEMENTED_IF_MSG(instr.tld4.UsesMiscMode(Tegra::Shader::TextureMiscMode::NDV), |
| 2883 | "NDV is not implemented"); | 2792 | "NDV is not implemented"); |
| 2884 | ASSERT_MSG(!instr.tld4.UsesMiscMode(Tegra::Shader::TextureMiscMode::PTP), | 2793 | UNIMPLEMENTED_IF_MSG(instr.tld4.UsesMiscMode(Tegra::Shader::TextureMiscMode::PTP), |
| 2885 | "PTP is not implemented"); | 2794 | "PTP is not implemented"); |
| 2886 | const bool depth_compare = | 2795 | const bool depth_compare = |
| 2887 | instr.tld4.UsesMiscMode(Tegra::Shader::TextureMiscMode::DC); | 2796 | instr.tld4.UsesMiscMode(Tegra::Shader::TextureMiscMode::DC); |
| 2888 | auto texture_type = instr.tld4.texture_type.Value(); | 2797 | auto texture_type = instr.tld4.texture_type.Value(); |
| @@ -2905,9 +2814,8 @@ private: | |||
| 2905 | break; | 2814 | break; |
| 2906 | } | 2815 | } |
| 2907 | default: | 2816 | default: |
| 2908 | LOG_CRITICAL(HW_GPU, "Unhandled coordinates number {}", | 2817 | UNIMPLEMENTED_MSG("Unhandled coordinates number {}", |
| 2909 | static_cast<u32>(num_coordinates)); | 2818 | static_cast<u32>(num_coordinates)); |
| 2910 | UNREACHABLE(); | ||
| 2911 | const std::string x = regs.GetRegisterAsFloat(instr.gpr8); | 2819 | const std::string x = regs.GetRegisterAsFloat(instr.gpr8); |
| 2912 | const std::string y = regs.GetRegisterAsFloat(instr.gpr8.Value() + 1); | 2820 | const std::string y = regs.GetRegisterAsFloat(instr.gpr8.Value() + 1); |
| 2913 | coord = "vec2 coords = vec2(" + x + ", " + y + ");"; | 2821 | coord = "vec2 coords = vec2(" + x + ", " + y + ");"; |
| @@ -2941,10 +2849,12 @@ private: | |||
| 2941 | break; | 2849 | break; |
| 2942 | } | 2850 | } |
| 2943 | case OpCode::Id::TLD4S: { | 2851 | case OpCode::Id::TLD4S: { |
| 2944 | ASSERT_MSG(!instr.tld4s.UsesMiscMode(Tegra::Shader::TextureMiscMode::NODEP), | 2852 | UNIMPLEMENTED_IF_MSG( |
| 2945 | "NODEP is not implemented"); | 2853 | instr.tld4s.UsesMiscMode(Tegra::Shader::TextureMiscMode::NODEP), |
| 2946 | ASSERT_MSG(!instr.tld4s.UsesMiscMode(Tegra::Shader::TextureMiscMode::AOFFI), | 2854 | "NODEP is not implemented"); |
| 2947 | "AOFFI is not implemented"); | 2855 | UNIMPLEMENTED_IF_MSG( |
| 2856 | instr.tld4s.UsesMiscMode(Tegra::Shader::TextureMiscMode::AOFFI), | ||
| 2857 | "AOFFI is not implemented"); | ||
| 2948 | 2858 | ||
| 2949 | const bool depth_compare = | 2859 | const bool depth_compare = |
| 2950 | instr.tld4s.UsesMiscMode(Tegra::Shader::TextureMiscMode::DC); | 2860 | instr.tld4s.UsesMiscMode(Tegra::Shader::TextureMiscMode::DC); |
| @@ -2972,8 +2882,8 @@ private: | |||
| 2972 | break; | 2882 | break; |
| 2973 | } | 2883 | } |
| 2974 | case OpCode::Id::TXQ: { | 2884 | case OpCode::Id::TXQ: { |
| 2975 | ASSERT_MSG(!instr.txq.UsesMiscMode(Tegra::Shader::TextureMiscMode::NODEP), | 2885 | UNIMPLEMENTED_IF_MSG(instr.txq.UsesMiscMode(Tegra::Shader::TextureMiscMode::NODEP), |
| 2976 | "NODEP is not implemented"); | 2886 | "NODEP is not implemented"); |
| 2977 | 2887 | ||
| 2978 | // TODO: the new commits on the texture refactor, change the way samplers work. | 2888 | // TODO: the new commits on the texture refactor, change the way samplers work. |
| 2979 | // Sadly, not all texture instructions specify the type of texture their sampler | 2889 | // Sadly, not all texture instructions specify the type of texture their sampler |
| @@ -2987,18 +2897,17 @@ private: | |||
| 2987 | break; | 2897 | break; |
| 2988 | } | 2898 | } |
| 2989 | default: { | 2899 | default: { |
| 2990 | LOG_CRITICAL(HW_GPU, "Unhandled texture query type: {}", | 2900 | UNIMPLEMENTED_MSG("Unhandled texture query type: {}", |
| 2991 | static_cast<u32>(instr.txq.query_type.Value())); | 2901 | static_cast<u32>(instr.txq.query_type.Value())); |
| 2992 | UNREACHABLE(); | ||
| 2993 | } | 2902 | } |
| 2994 | } | 2903 | } |
| 2995 | break; | 2904 | break; |
| 2996 | } | 2905 | } |
| 2997 | case OpCode::Id::TMML: { | 2906 | case OpCode::Id::TMML: { |
| 2998 | ASSERT_MSG(!instr.tmml.UsesMiscMode(Tegra::Shader::TextureMiscMode::NODEP), | 2907 | UNIMPLEMENTED_IF_MSG(instr.tmml.UsesMiscMode(Tegra::Shader::TextureMiscMode::NODEP), |
| 2999 | "NODEP is not implemented"); | 2908 | "NODEP is not implemented"); |
| 3000 | ASSERT_MSG(!instr.tmml.UsesMiscMode(Tegra::Shader::TextureMiscMode::NDV), | 2909 | UNIMPLEMENTED_IF_MSG(instr.tmml.UsesMiscMode(Tegra::Shader::TextureMiscMode::NDV), |
| 3001 | "NDV is not implemented"); | 2910 | "NDV is not implemented"); |
| 3002 | 2911 | ||
| 3003 | const std::string x = regs.GetRegisterAsFloat(instr.gpr8); | 2912 | const std::string x = regs.GetRegisterAsFloat(instr.gpr8); |
| 3004 | const bool is_array = instr.tmml.array != 0; | 2913 | const bool is_array = instr.tmml.array != 0; |
| @@ -3020,9 +2929,7 @@ private: | |||
| 3020 | break; | 2929 | break; |
| 3021 | } | 2930 | } |
| 3022 | default: | 2931 | default: |
| 3023 | LOG_CRITICAL(HW_GPU, "Unhandled texture type {}", | 2932 | UNIMPLEMENTED_MSG("Unhandled texture type {}", static_cast<u32>(texture_type)); |
| 3024 | static_cast<u32>(texture_type)); | ||
| 3025 | UNREACHABLE(); | ||
| 3026 | 2933 | ||
| 3027 | // Fallback to interpreting as a 2D texture for now | 2934 | // Fallback to interpreting as a 2D texture for now |
| 3028 | const std::string y = regs.GetRegisterAsFloat(instr.gpr8.Value() + 1); | 2935 | const std::string y = regs.GetRegisterAsFloat(instr.gpr8.Value() + 1); |
| @@ -3045,8 +2952,7 @@ private: | |||
| 3045 | break; | 2952 | break; |
| 3046 | } | 2953 | } |
| 3047 | default: { | 2954 | default: { |
| 3048 | LOG_CRITICAL(HW_GPU, "Unhandled memory instruction: {}", opcode->get().GetName()); | 2955 | UNIMPLEMENTED_MSG("Unhandled memory instruction: {}", opcode->get().GetName()); |
| 3049 | UNREACHABLE(); | ||
| 3050 | } | 2956 | } |
| 3051 | } | 2957 | } |
| 3052 | break; | 2958 | break; |
| @@ -3132,7 +3038,7 @@ private: | |||
| 3132 | break; | 3038 | break; |
| 3133 | } | 3039 | } |
| 3134 | case OpCode::Type::HalfSetPredicate: { | 3040 | case OpCode::Type::HalfSetPredicate: { |
| 3135 | ASSERT_MSG(instr.hsetp2.ftz == 0, "Unimplemented"); | 3041 | UNIMPLEMENTED_IF(instr.hsetp2.ftz != 0); |
| 3136 | 3042 | ||
| 3137 | const std::string op_a = | 3043 | const std::string op_a = |
| 3138 | GetHalfFloat(regs.GetRegisterAsInteger(instr.gpr8, 0, false), instr.hsetp2.type_a, | 3044 | GetHalfFloat(regs.GetRegisterAsInteger(instr.gpr8, 0, false), instr.hsetp2.type_a, |
| @@ -3177,6 +3083,8 @@ private: | |||
| 3177 | break; | 3083 | break; |
| 3178 | } | 3084 | } |
| 3179 | case OpCode::Type::PredicateSetRegister: { | 3085 | case OpCode::Type::PredicateSetRegister: { |
| 3086 | UNIMPLEMENTED_IF_MSG(instr.generates_cc, "PSET Generates an unhandled Control Code"); | ||
| 3087 | |||
| 3180 | const std::string op_a = | 3088 | const std::string op_a = |
| 3181 | GetPredicateCondition(instr.pset.pred12, instr.pset.neg_pred12 != 0); | 3089 | GetPredicateCondition(instr.pset.pred12, instr.pset.neg_pred12 != 0); |
| 3182 | const std::string op_b = | 3090 | const std::string op_b = |
| @@ -3197,12 +3105,6 @@ private: | |||
| 3197 | const std::string value = '(' + result + ") ? 1.0 : 0.0"; | 3105 | const std::string value = '(' + result + ") ? 1.0 : 0.0"; |
| 3198 | regs.SetRegisterToFloat(instr.gpr0, 0, value, 1, 1); | 3106 | regs.SetRegisterToFloat(instr.gpr0, 0, value, 1, 1); |
| 3199 | } | 3107 | } |
| 3200 | |||
| 3201 | if (instr.generates_cc) { | ||
| 3202 | LOG_CRITICAL(HW_GPU, "PSET Generates an unhandled Control Code"); | ||
| 3203 | UNREACHABLE(); | ||
| 3204 | } | ||
| 3205 | |||
| 3206 | break; | 3108 | break; |
| 3207 | } | 3109 | } |
| 3208 | case OpCode::Type::PredicateSetPredicate: { | 3110 | case OpCode::Type::PredicateSetPredicate: { |
| @@ -3252,9 +3154,7 @@ private: | |||
| 3252 | break; | 3154 | break; |
| 3253 | } | 3155 | } |
| 3254 | default: { | 3156 | default: { |
| 3255 | LOG_CRITICAL(HW_GPU, "Unhandled predicate instruction: {}", | 3157 | UNIMPLEMENTED_MSG("Unhandled predicate instruction: {}", opcode->get().GetName()); |
| 3256 | opcode->get().GetName()); | ||
| 3257 | UNREACHABLE(); | ||
| 3258 | } | 3158 | } |
| 3259 | } | 3159 | } |
| 3260 | break; | 3160 | break; |
| @@ -3334,7 +3234,7 @@ private: | |||
| 3334 | break; | 3234 | break; |
| 3335 | } | 3235 | } |
| 3336 | case OpCode::Type::HalfSet: { | 3236 | case OpCode::Type::HalfSet: { |
| 3337 | ASSERT_MSG(instr.hset2.ftz == 0, "Unimplemented"); | 3237 | UNIMPLEMENTED_IF(instr.hset2.ftz != 0); |
| 3338 | 3238 | ||
| 3339 | const std::string op_a = | 3239 | const std::string op_a = |
| 3340 | GetHalfFloat(regs.GetRegisterAsInteger(instr.gpr8, 0, false), instr.hset2.type_a, | 3240 | GetHalfFloat(regs.GetRegisterAsInteger(instr.gpr8, 0, false), instr.hset2.type_a, |
| @@ -3378,15 +3278,16 @@ private: | |||
| 3378 | break; | 3278 | break; |
| 3379 | } | 3279 | } |
| 3380 | case OpCode::Type::Xmad: { | 3280 | case OpCode::Type::Xmad: { |
| 3381 | ASSERT_MSG(!instr.xmad.sign_a, "Unimplemented"); | 3281 | UNIMPLEMENTED_IF(instr.xmad.sign_a); |
| 3382 | ASSERT_MSG(!instr.xmad.sign_b, "Unimplemented"); | 3282 | UNIMPLEMENTED_IF(instr.xmad.sign_b); |
| 3283 | UNIMPLEMENTED_IF_MSG(instr.generates_cc, "XMAD Generates an unhandled Control Code"); | ||
| 3383 | 3284 | ||
| 3384 | std::string op_a{regs.GetRegisterAsInteger(instr.gpr8, 0, instr.xmad.sign_a)}; | 3285 | std::string op_a{regs.GetRegisterAsInteger(instr.gpr8, 0, instr.xmad.sign_a)}; |
| 3385 | std::string op_b; | 3286 | std::string op_b; |
| 3386 | std::string op_c; | 3287 | std::string op_c; |
| 3387 | 3288 | ||
| 3388 | // TODO(bunnei): Needs to be fixed once op_a or op_b is signed | 3289 | // TODO(bunnei): Needs to be fixed once op_a or op_b is signed |
| 3389 | ASSERT_MSG(instr.xmad.sign_a == instr.xmad.sign_b, "Unimplemented"); | 3290 | UNIMPLEMENTED_IF(instr.xmad.sign_a != instr.xmad.sign_b); |
| 3390 | const bool is_signed{instr.xmad.sign_a == 1}; | 3291 | const bool is_signed{instr.xmad.sign_a == 1}; |
| 3391 | 3292 | ||
| 3392 | bool is_merge{}; | 3293 | bool is_merge{}; |
| @@ -3419,8 +3320,7 @@ private: | |||
| 3419 | break; | 3320 | break; |
| 3420 | } | 3321 | } |
| 3421 | default: { | 3322 | default: { |
| 3422 | LOG_CRITICAL(HW_GPU, "Unhandled XMAD instruction: {}", opcode->get().GetName()); | 3323 | UNIMPLEMENTED_MSG("Unhandled XMAD instruction: {}", opcode->get().GetName()); |
| 3423 | UNREACHABLE(); | ||
| 3424 | } | 3324 | } |
| 3425 | } | 3325 | } |
| 3426 | 3326 | ||
| @@ -3456,9 +3356,8 @@ private: | |||
| 3456 | op_c = "((" + op_c + ") + (" + src2 + "<< 16))"; | 3356 | op_c = "((" + op_c + ") + (" + src2 + "<< 16))"; |
| 3457 | break; | 3357 | break; |
| 3458 | default: { | 3358 | default: { |
| 3459 | LOG_CRITICAL(HW_GPU, "Unhandled XMAD mode: {}", | 3359 | UNIMPLEMENTED_MSG("Unhandled XMAD mode: {}", |
| 3460 | static_cast<u32>(instr.xmad.mode.Value())); | 3360 | static_cast<u32>(instr.xmad.mode.Value())); |
| 3461 | UNREACHABLE(); | ||
| 3462 | } | 3361 | } |
| 3463 | } | 3362 | } |
| 3464 | 3363 | ||
| @@ -3468,25 +3367,19 @@ private: | |||
| 3468 | } | 3367 | } |
| 3469 | 3368 | ||
| 3470 | regs.SetRegisterToInteger(instr.gpr0, is_signed, 0, sum, 1, 1); | 3369 | regs.SetRegisterToInteger(instr.gpr0, is_signed, 0, sum, 1, 1); |
| 3471 | if (instr.generates_cc) { | ||
| 3472 | LOG_CRITICAL(HW_GPU, "XMAD Generates an unhandled Control Code"); | ||
| 3473 | UNREACHABLE(); | ||
| 3474 | } | ||
| 3475 | break; | 3370 | break; |
| 3476 | } | 3371 | } |
| 3477 | default: { | 3372 | default: { |
| 3478 | switch (opcode->get().GetId()) { | 3373 | switch (opcode->get().GetId()) { |
| 3479 | case OpCode::Id::EXIT: { | 3374 | case OpCode::Id::EXIT: { |
| 3375 | const Tegra::Shader::ControlCode cc = instr.flow_control_code; | ||
| 3376 | UNIMPLEMENTED_IF_MSG(cc != Tegra::Shader::ControlCode::T, | ||
| 3377 | "EXIT Control Code used: {}", static_cast<u32>(cc)); | ||
| 3378 | |||
| 3480 | if (stage == Maxwell3D::Regs::ShaderStage::Fragment) { | 3379 | if (stage == Maxwell3D::Regs::ShaderStage::Fragment) { |
| 3481 | EmitFragmentOutputsWrite(); | 3380 | EmitFragmentOutputsWrite(); |
| 3482 | } | 3381 | } |
| 3483 | 3382 | ||
| 3484 | const Tegra::Shader::ControlCode cc = instr.flow_control_code; | ||
| 3485 | if (cc != Tegra::Shader::ControlCode::T) { | ||
| 3486 | LOG_CRITICAL(HW_GPU, "EXIT Control Code used: {}", static_cast<u32>(cc)); | ||
| 3487 | UNREACHABLE(); | ||
| 3488 | } | ||
| 3489 | |||
| 3490 | switch (instr.flow.cond) { | 3383 | switch (instr.flow.cond) { |
| 3491 | case Tegra::Shader::FlowCondition::Always: | 3384 | case Tegra::Shader::FlowCondition::Always: |
| 3492 | shader.AddLine("return true;"); | 3385 | shader.AddLine("return true;"); |
| @@ -3501,26 +3394,24 @@ private: | |||
| 3501 | case Tegra::Shader::FlowCondition::Fcsm_Tr: | 3394 | case Tegra::Shader::FlowCondition::Fcsm_Tr: |
| 3502 | // TODO(bunnei): What is this used for? If we assume this conditon is not | 3395 | // TODO(bunnei): What is this used for? If we assume this conditon is not |
| 3503 | // satisifed, dual vertex shaders in Farming Simulator make more sense | 3396 | // satisifed, dual vertex shaders in Farming Simulator make more sense |
| 3504 | LOG_CRITICAL(HW_GPU, "Skipping unknown FlowCondition::Fcsm_Tr"); | 3397 | UNIMPLEMENTED_MSG("Skipping unknown FlowCondition::Fcsm_Tr"); |
| 3505 | break; | 3398 | break; |
| 3506 | 3399 | ||
| 3507 | default: | 3400 | default: |
| 3508 | LOG_CRITICAL(HW_GPU, "Unhandled flow condition: {}", | 3401 | UNIMPLEMENTED_MSG("Unhandled flow condition: {}", |
| 3509 | static_cast<u32>(instr.flow.cond.Value())); | 3402 | static_cast<u32>(instr.flow.cond.Value())); |
| 3510 | UNREACHABLE(); | ||
| 3511 | } | 3403 | } |
| 3512 | break; | 3404 | break; |
| 3513 | } | 3405 | } |
| 3514 | case OpCode::Id::KIL: { | 3406 | case OpCode::Id::KIL: { |
| 3515 | ASSERT(instr.flow.cond == Tegra::Shader::FlowCondition::Always); | 3407 | UNIMPLEMENTED_IF(instr.flow.cond != Tegra::Shader::FlowCondition::Always); |
| 3408 | |||
| 3409 | const Tegra::Shader::ControlCode cc = instr.flow_control_code; | ||
| 3410 | UNIMPLEMENTED_IF_MSG(cc != Tegra::Shader::ControlCode::T, | ||
| 3411 | "KIL Control Code used: {}", static_cast<u32>(cc)); | ||
| 3516 | 3412 | ||
| 3517 | // Enclose "discard" in a conditional, so that GLSL compilation does not complain | 3413 | // Enclose "discard" in a conditional, so that GLSL compilation does not complain |
| 3518 | // about unexecuted instructions that may follow this. | 3414 | // about unexecuted instructions that may follow this. |
| 3519 | const Tegra::Shader::ControlCode cc = instr.flow_control_code; | ||
| 3520 | if (cc != Tegra::Shader::ControlCode::T) { | ||
| 3521 | LOG_CRITICAL(HW_GPU, "KIL Control Code used: {}", static_cast<u32>(cc)); | ||
| 3522 | UNREACHABLE(); | ||
| 3523 | } | ||
| 3524 | shader.AddLine("if (true) {"); | 3415 | shader.AddLine("if (true) {"); |
| 3525 | ++shader.scope; | 3416 | ++shader.scope; |
| 3526 | shader.AddLine("discard;"); | 3417 | shader.AddLine("discard;"); |
| @@ -3530,7 +3421,8 @@ private: | |||
| 3530 | break; | 3421 | break; |
| 3531 | } | 3422 | } |
| 3532 | case OpCode::Id::OUT_R: { | 3423 | case OpCode::Id::OUT_R: { |
| 3533 | ASSERT(instr.gpr20.Value() == Register::ZeroIndex); | 3424 | UNIMPLEMENTED_IF_MSG(instr.gpr20.Value() != Register::ZeroIndex, |
| 3425 | "Stream buffer is not supported"); | ||
| 3534 | ASSERT_MSG(stage == Maxwell3D::Regs::ShaderStage::Geometry, | 3426 | ASSERT_MSG(stage == Maxwell3D::Regs::ShaderStage::Geometry, |
| 3535 | "OUT is expected to be used in a geometry shader."); | 3427 | "OUT is expected to be used in a geometry shader."); |
| 3536 | 3428 | ||
| @@ -3557,18 +3449,17 @@ private: | |||
| 3557 | break; | 3449 | break; |
| 3558 | } | 3450 | } |
| 3559 | default: { | 3451 | default: { |
| 3560 | LOG_CRITICAL(HW_GPU, "Unhandled system move: {}", | 3452 | UNIMPLEMENTED_MSG("Unhandled system move: {}", |
| 3561 | static_cast<u32>(instr.sys20.Value())); | 3453 | static_cast<u32>(instr.sys20.Value())); |
| 3562 | UNREACHABLE(); | ||
| 3563 | } | 3454 | } |
| 3564 | } | 3455 | } |
| 3565 | break; | 3456 | break; |
| 3566 | } | 3457 | } |
| 3567 | case OpCode::Id::ISBERD: { | 3458 | case OpCode::Id::ISBERD: { |
| 3568 | ASSERT(instr.isberd.o == 0); | 3459 | UNIMPLEMENTED_IF(instr.isberd.o != 0); |
| 3569 | ASSERT(instr.isberd.skew == 0); | 3460 | UNIMPLEMENTED_IF(instr.isberd.skew != 0); |
| 3570 | ASSERT(instr.isberd.shift == Tegra::Shader::IsberdShift::None); | 3461 | UNIMPLEMENTED_IF(instr.isberd.shift != Tegra::Shader::IsberdShift::None); |
| 3571 | ASSERT(instr.isberd.mode == Tegra::Shader::IsberdMode::None); | 3462 | UNIMPLEMENTED_IF(instr.isberd.mode != Tegra::Shader::IsberdMode::None); |
| 3572 | ASSERT_MSG(stage == Maxwell3D::Regs::ShaderStage::Geometry, | 3463 | ASSERT_MSG(stage == Maxwell3D::Regs::ShaderStage::Geometry, |
| 3573 | "ISBERD is expected to be used in a geometry shader."); | 3464 | "ISBERD is expected to be used in a geometry shader."); |
| 3574 | LOG_WARNING(HW_GPU, "ISBERD instruction is incomplete"); | 3465 | LOG_WARNING(HW_GPU, "ISBERD instruction is incomplete"); |
| @@ -3576,13 +3467,13 @@ private: | |||
| 3576 | break; | 3467 | break; |
| 3577 | } | 3468 | } |
| 3578 | case OpCode::Id::BRA: { | 3469 | case OpCode::Id::BRA: { |
| 3579 | ASSERT_MSG(instr.bra.constant_buffer == 0, | 3470 | UNIMPLEMENTED_IF_MSG(instr.bra.constant_buffer != 0, |
| 3580 | "BRA with constant buffers are not implemented"); | 3471 | "BRA with constant buffers are not implemented"); |
| 3472 | |||
| 3581 | const Tegra::Shader::ControlCode cc = instr.flow_control_code; | 3473 | const Tegra::Shader::ControlCode cc = instr.flow_control_code; |
| 3582 | if (cc != Tegra::Shader::ControlCode::T) { | 3474 | UNIMPLEMENTED_IF_MSG(cc != Tegra::Shader::ControlCode::T, |
| 3583 | LOG_CRITICAL(HW_GPU, "BRA Control Code used: {}", static_cast<u32>(cc)); | 3475 | "BRA Control Code used: {}", static_cast<u32>(cc)); |
| 3584 | UNREACHABLE(); | 3476 | |
| 3585 | } | ||
| 3586 | const u32 target = offset + instr.bra.GetBranchTarget(); | 3477 | const u32 target = offset + instr.bra.GetBranchTarget(); |
| 3587 | shader.AddLine("{ jmp_to = " + std::to_string(target) + "u; break; }"); | 3478 | shader.AddLine("{ jmp_to = " + std::to_string(target) + "u; break; }"); |
| 3588 | break; | 3479 | break; |
| @@ -3605,7 +3496,8 @@ private: | |||
| 3605 | // The SSY opcode tells the GPU where to re-converge divergent execution paths, it | 3496 | // The SSY opcode tells the GPU where to re-converge divergent execution paths, it |
| 3606 | // sets the target of the jump that the SYNC instruction will make. The SSY opcode | 3497 | // sets the target of the jump that the SYNC instruction will make. The SSY opcode |
| 3607 | // has a similar structure to the BRA opcode. | 3498 | // has a similar structure to the BRA opcode. |
| 3608 | ASSERT_MSG(instr.bra.constant_buffer == 0, "Constant buffer flow is not supported"); | 3499 | UNIMPLEMENTED_IF_MSG(instr.bra.constant_buffer != 0, |
| 3500 | "Constant buffer flow is not supported"); | ||
| 3609 | 3501 | ||
| 3610 | const u32 target = offset + instr.bra.GetBranchTarget(); | 3502 | const u32 target = offset + instr.bra.GetBranchTarget(); |
| 3611 | EmitPushToFlowStack(target); | 3503 | EmitPushToFlowStack(target); |
| @@ -3615,19 +3507,19 @@ private: | |||
| 3615 | // PBK pushes to a stack the address where BRK will jump to. This shares stack with | 3507 | // PBK pushes to a stack the address where BRK will jump to. This shares stack with |
| 3616 | // SSY but using SYNC on a PBK address will kill the shader execution. We don't | 3508 | // SSY but using SYNC on a PBK address will kill the shader execution. We don't |
| 3617 | // emulate this because it's very unlikely a driver will emit such invalid shader. | 3509 | // emulate this because it's very unlikely a driver will emit such invalid shader. |
| 3618 | ASSERT_MSG(instr.bra.constant_buffer == 0, "Constant buffer PBK is not supported"); | 3510 | UNIMPLEMENTED_IF_MSG(instr.bra.constant_buffer != 0, |
| 3511 | "Constant buffer PBK is not supported"); | ||
| 3619 | 3512 | ||
| 3620 | const u32 target = offset + instr.bra.GetBranchTarget(); | 3513 | const u32 target = offset + instr.bra.GetBranchTarget(); |
| 3621 | EmitPushToFlowStack(target); | 3514 | EmitPushToFlowStack(target); |
| 3622 | break; | 3515 | break; |
| 3623 | } | 3516 | } |
| 3624 | case OpCode::Id::SYNC: { | 3517 | case OpCode::Id::SYNC: { |
| 3625 | // The SYNC opcode jumps to the address previously set by the SSY opcode | ||
| 3626 | const Tegra::Shader::ControlCode cc = instr.flow_control_code; | 3518 | const Tegra::Shader::ControlCode cc = instr.flow_control_code; |
| 3627 | if (cc != Tegra::Shader::ControlCode::T) { | 3519 | UNIMPLEMENTED_IF_MSG(cc != Tegra::Shader::ControlCode::T, |
| 3628 | LOG_CRITICAL(HW_GPU, "SYNC Control Code used: {}", static_cast<u32>(cc)); | 3520 | "SYNC Control Code used: {}", static_cast<u32>(cc)); |
| 3629 | UNREACHABLE(); | 3521 | |
| 3630 | } | 3522 | // The SYNC opcode jumps to the address previously set by the SSY opcode |
| 3631 | EmitPopFromFlowStack(); | 3523 | EmitPopFromFlowStack(); |
| 3632 | break; | 3524 | break; |
| 3633 | } | 3525 | } |
| @@ -3635,8 +3527,7 @@ private: | |||
| 3635 | // The BRK opcode jumps to the address previously set by the PBK opcode | 3527 | // The BRK opcode jumps to the address previously set by the PBK opcode |
| 3636 | const Tegra::Shader::ControlCode cc = instr.flow_control_code; | 3528 | const Tegra::Shader::ControlCode cc = instr.flow_control_code; |
| 3637 | if (cc != Tegra::Shader::ControlCode::T) { | 3529 | if (cc != Tegra::Shader::ControlCode::T) { |
| 3638 | LOG_CRITICAL(HW_GPU, "BRK Control Code used: {}", static_cast<u32>(cc)); | 3530 | UNIMPLEMENTED_MSG("BRK Control Code used: {}", static_cast<u32>(cc)); |
| 3639 | UNREACHABLE(); | ||
| 3640 | } | 3531 | } |
| 3641 | EmitPopFromFlowStack(); | 3532 | EmitPopFromFlowStack(); |
| 3642 | break; | 3533 | break; |
| @@ -3668,8 +3559,7 @@ private: | |||
| 3668 | instr.vmad.saturate == 1, 0, Register::Size::Word, | 3559 | instr.vmad.saturate == 1, 0, Register::Size::Word, |
| 3669 | instr.vmad.cc); | 3560 | instr.vmad.cc); |
| 3670 | if (instr.generates_cc) { | 3561 | if (instr.generates_cc) { |
| 3671 | LOG_CRITICAL(HW_GPU, "VMAD Generates an unhandled Control Code"); | 3562 | UNIMPLEMENTED_MSG("VMAD Generates an unhandled Control Code"); |
| 3672 | UNREACHABLE(); | ||
| 3673 | } | 3563 | } |
| 3674 | 3564 | ||
| 3675 | break; | 3565 | break; |
| @@ -3698,10 +3588,7 @@ private: | |||
| 3698 | } | 3588 | } |
| 3699 | break; | 3589 | break; |
| 3700 | } | 3590 | } |
| 3701 | default: { | 3591 | default: { UNIMPLEMENTED_MSG("Unhandled instruction: {}", opcode->get().GetName()); } |
| 3702 | LOG_CRITICAL(HW_GPU, "Unhandled instruction: {}", opcode->get().GetName()); | ||
| 3703 | UNREACHABLE(); | ||
| 3704 | } | ||
| 3705 | } | 3592 | } |
| 3706 | 3593 | ||
| 3707 | break; | 3594 | break; |