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