summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorGravatar bunnei2018-11-21 14:13:28 -0800
committerGravatar GitHub2018-11-21 14:13:28 -0800
commit61586e8794caaf5042bb0b80e9abe825e883779a (patch)
treeffbb07894c9c3aea1682ad725b3793ac2333cd22
parentMerge pull request #1742 from lioncash/hle-swkbd (diff)
parentgl_shader_decompiler: Use UNIMPLEMENTED instead of LOG+UNREACHABLE when appli... (diff)
downloadyuzu-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
-rw-r--r--src/video_core/renderer_opengl/gl_shader_decompiler.cpp629
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;