diff options
| author | 2018-11-23 23:31:04 -0500 | |
|---|---|---|
| committer | 2018-11-23 23:31:04 -0500 | |
| commit | b6b78203ccbbf5e7f3306e84203448583c3394e6 (patch) | |
| tree | 4d1aeceb566594e3f396bf686524b29d06b62c42 /src | |
| parent | Merge pull request #1744 from degasus/shader_cache (diff) | |
| parent | gl_shader_decompiler: Add a message for unimplemented cc generation (diff) | |
| download | yuzu-b6b78203ccbbf5e7f3306e84203448583c3394e6.tar.gz yuzu-b6b78203ccbbf5e7f3306e84203448583c3394e6.tar.xz yuzu-b6b78203ccbbf5e7f3306e84203448583c3394e6.zip | |
Merge pull request #1769 from ReinUsesLisp/cc
gl_shader_decompiler: Rename cc to condition code and name internal flags
Diffstat (limited to 'src')
| -rw-r--r-- | src/video_core/engines/shader_bytecode.h | 7 | ||||
| -rw-r--r-- | src/video_core/renderer_opengl/gl_shader_decompiler.cpp | 144 |
2 files changed, 81 insertions, 70 deletions
diff --git a/src/video_core/engines/shader_bytecode.h b/src/video_core/engines/shader_bytecode.h index c5f502ce1..7e8449bc4 100644 --- a/src/video_core/engines/shader_bytecode.h +++ b/src/video_core/engines/shader_bytecode.h | |||
| @@ -262,7 +262,7 @@ enum class FlowCondition : u64 { | |||
| 262 | Fcsm_Tr = 0x1C, // TODO(bunnei): What is this used for? | 262 | Fcsm_Tr = 0x1C, // TODO(bunnei): What is this used for? |
| 263 | }; | 263 | }; |
| 264 | 264 | ||
| 265 | enum class ControlCode : u64 { | 265 | enum class ConditionCode : u64 { |
| 266 | F = 0, | 266 | F = 0, |
| 267 | LT = 1, | 267 | LT = 1, |
| 268 | EQ = 2, | 268 | EQ = 2, |
| @@ -570,7 +570,6 @@ union Instruction { | |||
| 570 | BitField<39, 2, u64> tab5cb8_2; | 570 | BitField<39, 2, u64> tab5cb8_2; |
| 571 | BitField<41, 3, u64> tab5c68_1; | 571 | BitField<41, 3, u64> tab5c68_1; |
| 572 | BitField<44, 2, u64> tab5c68_0; | 572 | BitField<44, 2, u64> tab5c68_0; |
| 573 | BitField<47, 1, u64> cc; | ||
| 574 | BitField<48, 1, u64> negate_b; | 573 | BitField<48, 1, u64> negate_b; |
| 575 | } fmul; | 574 | } fmul; |
| 576 | 575 | ||
| @@ -832,7 +831,7 @@ union Instruction { | |||
| 832 | union { | 831 | union { |
| 833 | BitField<0, 3, u64> pred0; | 832 | BitField<0, 3, u64> pred0; |
| 834 | BitField<3, 3, u64> pred3; | 833 | BitField<3, 3, u64> pred3; |
| 835 | BitField<8, 5, ControlCode> cc; // flag in cc | 834 | BitField<8, 5, ConditionCode> cc; // flag in cc |
| 836 | BitField<39, 3, u64> pred39; | 835 | BitField<39, 3, u64> pred39; |
| 837 | BitField<42, 1, u64> neg_pred39; | 836 | BitField<42, 1, u64> neg_pred39; |
| 838 | BitField<45, 4, PredOperation> op; // op with pred39 | 837 | BitField<45, 4, PredOperation> op; // op with pred39 |
| @@ -1236,7 +1235,7 @@ union Instruction { | |||
| 1236 | BitField<60, 1, u64> is_b_gpr; | 1235 | BitField<60, 1, u64> is_b_gpr; |
| 1237 | BitField<59, 1, u64> is_c_gpr; | 1236 | BitField<59, 1, u64> is_c_gpr; |
| 1238 | BitField<20, 24, s64> smem_imm; | 1237 | BitField<20, 24, s64> smem_imm; |
| 1239 | BitField<0, 5, ControlCode> flow_control_code; | 1238 | BitField<0, 5, ConditionCode> flow_condition_code; |
| 1240 | 1239 | ||
| 1241 | Attribute attribute; | 1240 | Attribute attribute; |
| 1242 | Sampler sampler; | 1241 | Sampler sampler; |
diff --git a/src/video_core/renderer_opengl/gl_shader_decompiler.cpp b/src/video_core/renderer_opengl/gl_shader_decompiler.cpp index 9cd95dadc..97b9028c5 100644 --- a/src/video_core/renderer_opengl/gl_shader_decompiler.cpp +++ b/src/video_core/renderer_opengl/gl_shader_decompiler.cpp | |||
| @@ -34,6 +34,17 @@ constexpr u32 PROGRAM_HEADER_SIZE = sizeof(Tegra::Shader::Header); | |||
| 34 | constexpr u32 MAX_GEOMETRY_BUFFERS = 6; | 34 | constexpr u32 MAX_GEOMETRY_BUFFERS = 6; |
| 35 | constexpr u32 MAX_ATTRIBUTES = 0x100; // Size in vec4s, this value is untested | 35 | constexpr u32 MAX_ATTRIBUTES = 0x100; // Size in vec4s, this value is untested |
| 36 | 36 | ||
| 37 | static const char* INTERNAL_FLAG_NAMES[] = {"zero_flag", "sign_flag", "carry_flag", | ||
| 38 | "overflow_flag"}; | ||
| 39 | |||
| 40 | enum class InternalFlag : u64 { | ||
| 41 | ZeroFlag = 0, | ||
| 42 | SignFlag = 1, | ||
| 43 | CarryFlag = 2, | ||
| 44 | OverflowFlag = 3, | ||
| 45 | Amount | ||
| 46 | }; | ||
| 47 | |||
| 37 | class DecompileFail : public std::runtime_error { | 48 | class DecompileFail : public std::runtime_error { |
| 38 | public: | 49 | public: |
| 39 | using std::runtime_error::runtime_error; | 50 | using std::runtime_error::runtime_error; |
| @@ -267,14 +278,6 @@ private: | |||
| 267 | const std::string& suffix; | 278 | const std::string& suffix; |
| 268 | }; | 279 | }; |
| 269 | 280 | ||
| 270 | enum class InternalFlag : u64 { | ||
| 271 | ZeroFlag = 0, | ||
| 272 | CarryFlag = 1, | ||
| 273 | OverflowFlag = 2, | ||
| 274 | NaNFlag = 3, | ||
| 275 | Amount | ||
| 276 | }; | ||
| 277 | |||
| 278 | /** | 281 | /** |
| 279 | * Used to manage shader registers that are emulated with GLSL. This class keeps track of the state | 282 | * Used to manage shader registers that are emulated with GLSL. This class keeps track of the state |
| 280 | * of all registers (e.g. whether they are currently being used as Floats or Integers), and | 283 | * of all registers (e.g. whether they are currently being used as Floats or Integers), and |
| @@ -381,7 +384,7 @@ public: | |||
| 381 | if (sets_cc) { | 384 | if (sets_cc) { |
| 382 | const std::string zero_condition = "( " + ConvertIntegerSize(value, size) + " == 0 )"; | 385 | const std::string zero_condition = "( " + ConvertIntegerSize(value, size) + " == 0 )"; |
| 383 | SetInternalFlag(InternalFlag::ZeroFlag, zero_condition); | 386 | SetInternalFlag(InternalFlag::ZeroFlag, zero_condition); |
| 384 | LOG_WARNING(HW_GPU, "Control Codes Imcomplete."); | 387 | LOG_WARNING(HW_GPU, "Condition codes implementation is incomplete."); |
| 385 | } | 388 | } |
| 386 | } | 389 | } |
| 387 | 390 | ||
| @@ -464,23 +467,25 @@ public: | |||
| 464 | shader.AddLine("lmem[" + index + "] = " + func + '(' + value + ");"); | 467 | shader.AddLine("lmem[" + index + "] = " + func + '(' + value + ");"); |
| 465 | } | 468 | } |
| 466 | 469 | ||
| 467 | std::string GetControlCode(const Tegra::Shader::ControlCode cc) const { | 470 | std::string GetConditionCode(const Tegra::Shader::ConditionCode cc) const { |
| 468 | switch (cc) { | 471 | switch (cc) { |
| 469 | case Tegra::Shader::ControlCode::NEU: | 472 | case Tegra::Shader::ConditionCode::NEU: |
| 470 | return "!(" + GetInternalFlag(InternalFlag::ZeroFlag) + ')'; | 473 | return "!(" + GetInternalFlag(InternalFlag::ZeroFlag) + ')'; |
| 471 | default: | 474 | default: |
| 472 | UNIMPLEMENTED_MSG("Unimplemented Control Code: {}", static_cast<u32>(cc)); | 475 | UNIMPLEMENTED_MSG("Unimplemented condition code: {}", static_cast<u32>(cc)); |
| 473 | return "false"; | 476 | return "false"; |
| 474 | } | 477 | } |
| 475 | } | 478 | } |
| 476 | 479 | ||
| 477 | std::string GetInternalFlag(const InternalFlag ii) const { | 480 | std::string GetInternalFlag(const InternalFlag flag) const { |
| 478 | const u32 code = static_cast<u32>(ii); | 481 | const auto index = static_cast<u32>(flag); |
| 479 | return "internalFlag_" + std::to_string(code) + suffix; | 482 | ASSERT(index < static_cast<u32>(InternalFlag::Amount)); |
| 483 | |||
| 484 | return std::string(INTERNAL_FLAG_NAMES[index]) + '_' + suffix; | ||
| 480 | } | 485 | } |
| 481 | 486 | ||
| 482 | void SetInternalFlag(const InternalFlag ii, const std::string& value) const { | 487 | void SetInternalFlag(const InternalFlag flag, const std::string& value) const { |
| 483 | shader.AddLine(GetInternalFlag(ii) + " = " + value + ';'); | 488 | shader.AddLine(GetInternalFlag(flag) + " = " + value + ';'); |
| 484 | } | 489 | } |
| 485 | 490 | ||
| 486 | /** | 491 | /** |
| @@ -631,8 +636,8 @@ private: | |||
| 631 | 636 | ||
| 632 | /// Generates declarations for internal flags. | 637 | /// Generates declarations for internal flags. |
| 633 | void GenerateInternalFlags() { | 638 | void GenerateInternalFlags() { |
| 634 | for (u32 ii = 0; ii < static_cast<u64>(InternalFlag::Amount); ii++) { | 639 | for (u32 flag = 0; flag < static_cast<u32>(InternalFlag::Amount); flag++) { |
| 635 | const InternalFlag code = static_cast<InternalFlag>(ii); | 640 | const InternalFlag code = static_cast<InternalFlag>(flag); |
| 636 | declarations.AddLine("bool " + GetInternalFlag(code) + " = false;"); | 641 | declarations.AddLine("bool " + GetInternalFlag(code) + " = false;"); |
| 637 | } | 642 | } |
| 638 | declarations.AddNewLine(); | 643 | declarations.AddNewLine(); |
| @@ -1516,9 +1521,8 @@ private: | |||
| 1516 | instr.fmul.tab5c68_0 != 1, "FMUL tab5cb8_0({}) is not implemented", | 1521 | instr.fmul.tab5c68_0 != 1, "FMUL tab5cb8_0({}) is not implemented", |
| 1517 | instr.fmul.tab5c68_0 | 1522 | instr.fmul.tab5c68_0 |
| 1518 | .Value()); // SMO typical sends 1 here which seems to be the default | 1523 | .Value()); // SMO typical sends 1 here which seems to be the default |
| 1519 | UNIMPLEMENTED_IF_MSG(instr.fmul.cc != 0, "FMUL cc is not implemented"); | ||
| 1520 | UNIMPLEMENTED_IF_MSG(instr.generates_cc, | 1524 | UNIMPLEMENTED_IF_MSG(instr.generates_cc, |
| 1521 | "FMUL Generates an unhandled Control Code"); | 1525 | "Condition codes generation in FMUL is not implemented"); |
| 1522 | 1526 | ||
| 1523 | op_b = GetOperandAbsNeg(op_b, false, instr.fmul.negate_b); | 1527 | op_b = GetOperandAbsNeg(op_b, false, instr.fmul.negate_b); |
| 1524 | 1528 | ||
| @@ -1530,7 +1534,7 @@ private: | |||
| 1530 | case OpCode::Id::FADD_R: | 1534 | case OpCode::Id::FADD_R: |
| 1531 | case OpCode::Id::FADD_IMM: { | 1535 | case OpCode::Id::FADD_IMM: { |
| 1532 | UNIMPLEMENTED_IF_MSG(instr.generates_cc, | 1536 | UNIMPLEMENTED_IF_MSG(instr.generates_cc, |
| 1533 | "FADD Generates an unhandled Control Code"); | 1537 | "Condition codes generation in FADD is not implemented"); |
| 1534 | 1538 | ||
| 1535 | op_a = GetOperandAbsNeg(op_a, instr.alu.abs_a, instr.alu.negate_a); | 1539 | op_a = GetOperandAbsNeg(op_a, instr.alu.abs_a, instr.alu.negate_a); |
| 1536 | op_b = GetOperandAbsNeg(op_b, instr.alu.abs_b, instr.alu.negate_b); | 1540 | op_b = GetOperandAbsNeg(op_b, instr.alu.abs_b, instr.alu.negate_b); |
| @@ -1580,7 +1584,7 @@ private: | |||
| 1580 | case OpCode::Id::FMNMX_R: | 1584 | case OpCode::Id::FMNMX_R: |
| 1581 | case OpCode::Id::FMNMX_IMM: { | 1585 | case OpCode::Id::FMNMX_IMM: { |
| 1582 | UNIMPLEMENTED_IF_MSG(instr.generates_cc, | 1586 | UNIMPLEMENTED_IF_MSG(instr.generates_cc, |
| 1583 | "FMNMX Generates an unhandled Control Code"); | 1587 | "Condition codes generation in FMNMX is not implemented"); |
| 1584 | 1588 | ||
| 1585 | op_a = GetOperandAbsNeg(op_a, instr.alu.abs_a, instr.alu.negate_a); | 1589 | op_a = GetOperandAbsNeg(op_a, instr.alu.abs_a, instr.alu.negate_a); |
| 1586 | op_b = GetOperandAbsNeg(op_b, instr.alu.abs_b, instr.alu.negate_b); | 1590 | op_b = GetOperandAbsNeg(op_b, instr.alu.abs_b, instr.alu.negate_b); |
| @@ -1617,7 +1621,7 @@ private: | |||
| 1617 | } | 1621 | } |
| 1618 | case OpCode::Id::FMUL32_IMM: { | 1622 | case OpCode::Id::FMUL32_IMM: { |
| 1619 | UNIMPLEMENTED_IF_MSG(instr.op_32.generates_cc, | 1623 | UNIMPLEMENTED_IF_MSG(instr.op_32.generates_cc, |
| 1620 | "FMUL32 Generates an unhandled Control Code"); | 1624 | "Condition codes generation in FMUL32 is not implemented"); |
| 1621 | 1625 | ||
| 1622 | regs.SetRegisterToFloat(instr.gpr0, 0, | 1626 | regs.SetRegisterToFloat(instr.gpr0, 0, |
| 1623 | regs.GetRegisterAsFloat(instr.gpr8) + " * " + | 1627 | regs.GetRegisterAsFloat(instr.gpr8) + " * " + |
| @@ -1627,7 +1631,7 @@ private: | |||
| 1627 | } | 1631 | } |
| 1628 | case OpCode::Id::FADD32I: { | 1632 | case OpCode::Id::FADD32I: { |
| 1629 | UNIMPLEMENTED_IF_MSG(instr.op_32.generates_cc, | 1633 | UNIMPLEMENTED_IF_MSG(instr.op_32.generates_cc, |
| 1630 | "FADD32 Generates an unhandled Control Code"); | 1634 | "Condition codes generation in FADD32I is not implemented"); |
| 1631 | 1635 | ||
| 1632 | std::string op_a = regs.GetRegisterAsFloat(instr.gpr8); | 1636 | std::string op_a = regs.GetRegisterAsFloat(instr.gpr8); |
| 1633 | std::string op_b = GetImmediate32(instr); | 1637 | std::string op_b = GetImmediate32(instr); |
| @@ -1662,7 +1666,8 @@ private: | |||
| 1662 | 1666 | ||
| 1663 | switch (opcode->get().GetId()) { | 1667 | switch (opcode->get().GetId()) { |
| 1664 | case OpCode::Id::BFE_IMM: { | 1668 | case OpCode::Id::BFE_IMM: { |
| 1665 | UNIMPLEMENTED_IF_MSG(instr.generates_cc, "BFE Generates an unhandled Control Code"); | 1669 | UNIMPLEMENTED_IF_MSG(instr.generates_cc, |
| 1670 | "Condition codes generation in BFE is not implemented"); | ||
| 1666 | 1671 | ||
| 1667 | std::string inner_shift = | 1672 | std::string inner_shift = |
| 1668 | '(' + op_a + " << " + std::to_string(instr.bfe.GetLeftShiftValue()) + ')'; | 1673 | '(' + op_a + " << " + std::to_string(instr.bfe.GetLeftShiftValue()) + ')'; |
| @@ -1699,7 +1704,8 @@ private: | |||
| 1699 | case OpCode::Id::SHR_C: | 1704 | case OpCode::Id::SHR_C: |
| 1700 | case OpCode::Id::SHR_R: | 1705 | case OpCode::Id::SHR_R: |
| 1701 | case OpCode::Id::SHR_IMM: { | 1706 | case OpCode::Id::SHR_IMM: { |
| 1702 | UNIMPLEMENTED_IF_MSG(instr.generates_cc, "SHR Generates an unhandled Control Code"); | 1707 | UNIMPLEMENTED_IF_MSG(instr.generates_cc, |
| 1708 | "Condition codes generation in SHR is not implemented"); | ||
| 1703 | 1709 | ||
| 1704 | if (!instr.shift.is_signed) { | 1710 | if (!instr.shift.is_signed) { |
| 1705 | // Logical shift right | 1711 | // Logical shift right |
| @@ -1714,8 +1720,8 @@ private: | |||
| 1714 | case OpCode::Id::SHL_C: | 1720 | case OpCode::Id::SHL_C: |
| 1715 | case OpCode::Id::SHL_R: | 1721 | case OpCode::Id::SHL_R: |
| 1716 | case OpCode::Id::SHL_IMM: | 1722 | case OpCode::Id::SHL_IMM: |
| 1717 | UNIMPLEMENTED_IF_MSG(instr.generates_cc, "SHL Generates an unhandled Control Code"); | 1723 | UNIMPLEMENTED_IF_MSG(instr.generates_cc, |
| 1718 | 1724 | "Condition codes generation in SHL is not implemented"); | |
| 1719 | regs.SetRegisterToInteger(instr.gpr0, true, 0, op_a + " << " + op_b, 1, 1); | 1725 | regs.SetRegisterToInteger(instr.gpr0, true, 0, op_a + " << " + op_b, 1, 1); |
| 1720 | break; | 1726 | break; |
| 1721 | default: { | 1727 | default: { |
| @@ -1731,7 +1737,7 @@ private: | |||
| 1731 | switch (opcode->get().GetId()) { | 1737 | switch (opcode->get().GetId()) { |
| 1732 | case OpCode::Id::IADD32I: | 1738 | case OpCode::Id::IADD32I: |
| 1733 | UNIMPLEMENTED_IF_MSG(instr.op_32.generates_cc, | 1739 | UNIMPLEMENTED_IF_MSG(instr.op_32.generates_cc, |
| 1734 | "IADD32 Generates an unhandled Control Code"); | 1740 | "Condition codes generation in IADD32I is not implemented"); |
| 1735 | 1741 | ||
| 1736 | if (instr.iadd32i.negate_a) | 1742 | if (instr.iadd32i.negate_a) |
| 1737 | op_a = "-(" + op_a + ')'; | 1743 | op_a = "-(" + op_a + ')'; |
| @@ -1741,7 +1747,7 @@ private: | |||
| 1741 | break; | 1747 | break; |
| 1742 | case OpCode::Id::LOP32I: { | 1748 | case OpCode::Id::LOP32I: { |
| 1743 | UNIMPLEMENTED_IF_MSG(instr.op_32.generates_cc, | 1749 | UNIMPLEMENTED_IF_MSG(instr.op_32.generates_cc, |
| 1744 | "LOP32I Generates an unhandled Control Code"); | 1750 | "Condition codes generation in LOP32I is not implemented"); |
| 1745 | 1751 | ||
| 1746 | if (instr.alu.lop32i.invert_a) | 1752 | if (instr.alu.lop32i.invert_a) |
| 1747 | op_a = "~(" + op_a + ')'; | 1753 | op_a = "~(" + op_a + ')'; |
| @@ -1780,7 +1786,7 @@ private: | |||
| 1780 | case OpCode::Id::IADD_R: | 1786 | case OpCode::Id::IADD_R: |
| 1781 | case OpCode::Id::IADD_IMM: { | 1787 | case OpCode::Id::IADD_IMM: { |
| 1782 | UNIMPLEMENTED_IF_MSG(instr.generates_cc, | 1788 | UNIMPLEMENTED_IF_MSG(instr.generates_cc, |
| 1783 | "IADD Generates an unhandled Control Code"); | 1789 | "Condition codes generation in IADD is not implemented"); |
| 1784 | 1790 | ||
| 1785 | if (instr.alu_integer.negate_a) | 1791 | if (instr.alu_integer.negate_a) |
| 1786 | op_a = "-(" + op_a + ')'; | 1792 | op_a = "-(" + op_a + ')'; |
| @@ -1796,7 +1802,7 @@ private: | |||
| 1796 | case OpCode::Id::IADD3_R: | 1802 | case OpCode::Id::IADD3_R: |
| 1797 | case OpCode::Id::IADD3_IMM: { | 1803 | case OpCode::Id::IADD3_IMM: { |
| 1798 | UNIMPLEMENTED_IF_MSG(instr.generates_cc, | 1804 | UNIMPLEMENTED_IF_MSG(instr.generates_cc, |
| 1799 | "IADD3 Generates an unhandled Control Code"); | 1805 | "Condition codes generation in IADD3 is not implemented"); |
| 1800 | 1806 | ||
| 1801 | std::string op_c = regs.GetRegisterAsInteger(instr.gpr39); | 1807 | std::string op_c = regs.GetRegisterAsInteger(instr.gpr39); |
| 1802 | 1808 | ||
| @@ -1859,7 +1865,7 @@ private: | |||
| 1859 | case OpCode::Id::ISCADD_R: | 1865 | case OpCode::Id::ISCADD_R: |
| 1860 | case OpCode::Id::ISCADD_IMM: { | 1866 | case OpCode::Id::ISCADD_IMM: { |
| 1861 | UNIMPLEMENTED_IF_MSG(instr.generates_cc, | 1867 | UNIMPLEMENTED_IF_MSG(instr.generates_cc, |
| 1862 | "ISCADD Generates an unhandled Control Code"); | 1868 | "Condition codes generation in ISCADD is not implemented"); |
| 1863 | 1869 | ||
| 1864 | if (instr.alu_integer.negate_a) | 1870 | if (instr.alu_integer.negate_a) |
| 1865 | op_a = "-(" + op_a + ')'; | 1871 | op_a = "-(" + op_a + ')'; |
| @@ -1894,7 +1900,8 @@ private: | |||
| 1894 | case OpCode::Id::LOP_C: | 1900 | case OpCode::Id::LOP_C: |
| 1895 | case OpCode::Id::LOP_R: | 1901 | case OpCode::Id::LOP_R: |
| 1896 | case OpCode::Id::LOP_IMM: { | 1902 | case OpCode::Id::LOP_IMM: { |
| 1897 | UNIMPLEMENTED_IF_MSG(instr.generates_cc, "LOP Generates an unhandled Control Code"); | 1903 | UNIMPLEMENTED_IF_MSG(instr.generates_cc, |
| 1904 | "Condition codes generation in LOP is not implemented"); | ||
| 1898 | 1905 | ||
| 1899 | if (instr.alu.lop.invert_a) | 1906 | if (instr.alu.lop.invert_a) |
| 1900 | op_a = "~(" + op_a + ')'; | 1907 | op_a = "~(" + op_a + ')'; |
| @@ -1910,7 +1917,7 @@ private: | |||
| 1910 | case OpCode::Id::LOP3_R: | 1917 | case OpCode::Id::LOP3_R: |
| 1911 | case OpCode::Id::LOP3_IMM: { | 1918 | case OpCode::Id::LOP3_IMM: { |
| 1912 | UNIMPLEMENTED_IF_MSG(instr.generates_cc, | 1919 | UNIMPLEMENTED_IF_MSG(instr.generates_cc, |
| 1913 | "LOP3 Generates an unhandled Control Code"); | 1920 | "Condition codes generation in LOP3 is not implemented"); |
| 1914 | 1921 | ||
| 1915 | const std::string op_c = regs.GetRegisterAsInteger(instr.gpr39); | 1922 | const std::string op_c = regs.GetRegisterAsInteger(instr.gpr39); |
| 1916 | std::string lut; | 1923 | std::string lut; |
| @@ -1929,7 +1936,7 @@ private: | |||
| 1929 | case OpCode::Id::IMNMX_IMM: { | 1936 | case OpCode::Id::IMNMX_IMM: { |
| 1930 | UNIMPLEMENTED_IF(instr.imnmx.exchange != Tegra::Shader::IMinMaxExchange::None); | 1937 | UNIMPLEMENTED_IF(instr.imnmx.exchange != Tegra::Shader::IMinMaxExchange::None); |
| 1931 | UNIMPLEMENTED_IF_MSG(instr.generates_cc, | 1938 | UNIMPLEMENTED_IF_MSG(instr.generates_cc, |
| 1932 | "IMNMX Generates an unhandled Control Code"); | 1939 | "Condition codes generation in IMNMX is not implemented"); |
| 1933 | 1940 | ||
| 1934 | const std::string condition = | 1941 | const std::string condition = |
| 1935 | GetPredicateCondition(instr.imnmx.pred, instr.imnmx.negate_pred != 0); | 1942 | GetPredicateCondition(instr.imnmx.pred, instr.imnmx.negate_pred != 0); |
| @@ -2102,7 +2109,8 @@ private: | |||
| 2102 | instr.ffma.tab5980_0.Value()); // Seems to be 1 by default based on SMO | 2109 | instr.ffma.tab5980_0.Value()); // Seems to be 1 by default based on SMO |
| 2103 | UNIMPLEMENTED_IF_MSG(instr.ffma.tab5980_1 != 0, "FFMA tab5980_1({}) not implemented", | 2110 | UNIMPLEMENTED_IF_MSG(instr.ffma.tab5980_1 != 0, "FFMA tab5980_1({}) not implemented", |
| 2104 | instr.ffma.tab5980_1.Value()); | 2111 | instr.ffma.tab5980_1.Value()); |
| 2105 | UNIMPLEMENTED_IF_MSG(instr.generates_cc, "FFMA Generates an unhandled Control Code"); | 2112 | UNIMPLEMENTED_IF_MSG(instr.generates_cc, |
| 2113 | "Condition codes generation in FFMA is not implemented"); | ||
| 2106 | 2114 | ||
| 2107 | switch (opcode->get().GetId()) { | 2115 | switch (opcode->get().GetId()) { |
| 2108 | case OpCode::Id::FFMA_CR: { | 2116 | case OpCode::Id::FFMA_CR: { |
| @@ -2212,7 +2220,8 @@ private: | |||
| 2212 | case OpCode::Id::I2F_C: { | 2220 | case OpCode::Id::I2F_C: { |
| 2213 | UNIMPLEMENTED_IF(instr.conversion.dest_size != Register::Size::Word); | 2221 | UNIMPLEMENTED_IF(instr.conversion.dest_size != Register::Size::Word); |
| 2214 | UNIMPLEMENTED_IF(instr.conversion.selector); | 2222 | UNIMPLEMENTED_IF(instr.conversion.selector); |
| 2215 | UNIMPLEMENTED_IF_MSG(instr.generates_cc, "I2F Generates an unhandled Control Code"); | 2223 | UNIMPLEMENTED_IF_MSG(instr.generates_cc, |
| 2224 | "Condition codes generation in I2F is not implemented"); | ||
| 2216 | 2225 | ||
| 2217 | std::string op_a{}; | 2226 | std::string op_a{}; |
| 2218 | 2227 | ||
| @@ -2242,7 +2251,8 @@ private: | |||
| 2242 | case OpCode::Id::F2F_R: { | 2251 | case OpCode::Id::F2F_R: { |
| 2243 | UNIMPLEMENTED_IF(instr.conversion.dest_size != Register::Size::Word); | 2252 | UNIMPLEMENTED_IF(instr.conversion.dest_size != Register::Size::Word); |
| 2244 | UNIMPLEMENTED_IF(instr.conversion.src_size != Register::Size::Word); | 2253 | UNIMPLEMENTED_IF(instr.conversion.src_size != Register::Size::Word); |
| 2245 | UNIMPLEMENTED_IF_MSG(instr.generates_cc, "F2F Generates an unhandled Control Code"); | 2254 | UNIMPLEMENTED_IF_MSG(instr.generates_cc, |
| 2255 | "Condition codes generation in F2F is not implemented"); | ||
| 2246 | std::string op_a = regs.GetRegisterAsFloat(instr.gpr20); | 2256 | std::string op_a = regs.GetRegisterAsFloat(instr.gpr20); |
| 2247 | 2257 | ||
| 2248 | if (instr.conversion.abs_a) { | 2258 | if (instr.conversion.abs_a) { |
| @@ -2280,7 +2290,8 @@ private: | |||
| 2280 | case OpCode::Id::F2I_R: | 2290 | case OpCode::Id::F2I_R: |
| 2281 | case OpCode::Id::F2I_C: { | 2291 | case OpCode::Id::F2I_C: { |
| 2282 | UNIMPLEMENTED_IF(instr.conversion.src_size != Register::Size::Word); | 2292 | UNIMPLEMENTED_IF(instr.conversion.src_size != Register::Size::Word); |
| 2283 | UNIMPLEMENTED_IF_MSG(instr.generates_cc, "F2I Generates an unhandled Control Code"); | 2293 | UNIMPLEMENTED_IF_MSG(instr.generates_cc, |
| 2294 | "Condition codes generation in F2I is not implemented"); | ||
| 2284 | std::string op_a{}; | 2295 | std::string op_a{}; |
| 2285 | 2296 | ||
| 2286 | if (instr.is_b_gpr) { | 2297 | if (instr.is_b_gpr) { |
| @@ -3129,7 +3140,8 @@ private: | |||
| 3129 | break; | 3140 | break; |
| 3130 | } | 3141 | } |
| 3131 | case OpCode::Type::PredicateSetRegister: { | 3142 | case OpCode::Type::PredicateSetRegister: { |
| 3132 | UNIMPLEMENTED_IF_MSG(instr.generates_cc, "PSET Generates an unhandled Control Code"); | 3143 | UNIMPLEMENTED_IF_MSG(instr.generates_cc, |
| 3144 | "Condition codes generation in PSET is not implemented"); | ||
| 3133 | 3145 | ||
| 3134 | const std::string op_a = | 3146 | const std::string op_a = |
| 3135 | GetPredicateCondition(instr.pset.pred12, instr.pset.neg_pred12 != 0); | 3147 | GetPredicateCondition(instr.pset.pred12, instr.pset.neg_pred12 != 0); |
| @@ -3188,14 +3200,14 @@ private: | |||
| 3188 | const std::string pred = | 3200 | const std::string pred = |
| 3189 | GetPredicateCondition(instr.csetp.pred39, instr.csetp.neg_pred39 != 0); | 3201 | GetPredicateCondition(instr.csetp.pred39, instr.csetp.neg_pred39 != 0); |
| 3190 | const std::string combiner = GetPredicateCombiner(instr.csetp.op); | 3202 | const std::string combiner = GetPredicateCombiner(instr.csetp.op); |
| 3191 | const std::string control_code = regs.GetControlCode(instr.csetp.cc); | 3203 | const std::string condition_code = regs.GetConditionCode(instr.csetp.cc); |
| 3192 | if (instr.csetp.pred3 != static_cast<u64>(Pred::UnusedIndex)) { | 3204 | if (instr.csetp.pred3 != static_cast<u64>(Pred::UnusedIndex)) { |
| 3193 | SetPredicate(instr.csetp.pred3, | 3205 | SetPredicate(instr.csetp.pred3, |
| 3194 | '(' + control_code + ") " + combiner + " (" + pred + ')'); | 3206 | '(' + condition_code + ") " + combiner + " (" + pred + ')'); |
| 3195 | } | 3207 | } |
| 3196 | if (instr.csetp.pred0 != static_cast<u64>(Pred::UnusedIndex)) { | 3208 | if (instr.csetp.pred0 != static_cast<u64>(Pred::UnusedIndex)) { |
| 3197 | SetPredicate(instr.csetp.pred0, | 3209 | SetPredicate(instr.csetp.pred0, |
| 3198 | "!(" + control_code + ") " + combiner + " (" + pred + ')'); | 3210 | "!(" + condition_code + ") " + combiner + " (" + pred + ')'); |
| 3199 | } | 3211 | } |
| 3200 | break; | 3212 | break; |
| 3201 | } | 3213 | } |
| @@ -3326,7 +3338,8 @@ private: | |||
| 3326 | case OpCode::Type::Xmad: { | 3338 | case OpCode::Type::Xmad: { |
| 3327 | UNIMPLEMENTED_IF(instr.xmad.sign_a); | 3339 | UNIMPLEMENTED_IF(instr.xmad.sign_a); |
| 3328 | UNIMPLEMENTED_IF(instr.xmad.sign_b); | 3340 | UNIMPLEMENTED_IF(instr.xmad.sign_b); |
| 3329 | UNIMPLEMENTED_IF_MSG(instr.generates_cc, "XMAD Generates an unhandled Control Code"); | 3341 | UNIMPLEMENTED_IF_MSG(instr.generates_cc, |
| 3342 | "Condition codes generation in XMAD is not implemented"); | ||
| 3330 | 3343 | ||
| 3331 | std::string op_a{regs.GetRegisterAsInteger(instr.gpr8, 0, instr.xmad.sign_a)}; | 3344 | std::string op_a{regs.GetRegisterAsInteger(instr.gpr8, 0, instr.xmad.sign_a)}; |
| 3332 | std::string op_b; | 3345 | std::string op_b; |
| @@ -3418,9 +3431,9 @@ private: | |||
| 3418 | default: { | 3431 | default: { |
| 3419 | switch (opcode->get().GetId()) { | 3432 | switch (opcode->get().GetId()) { |
| 3420 | case OpCode::Id::EXIT: { | 3433 | case OpCode::Id::EXIT: { |
| 3421 | const Tegra::Shader::ControlCode cc = instr.flow_control_code; | 3434 | const Tegra::Shader::ConditionCode cc = instr.flow_condition_code; |
| 3422 | UNIMPLEMENTED_IF_MSG(cc != Tegra::Shader::ControlCode::T, | 3435 | UNIMPLEMENTED_IF_MSG(cc != Tegra::Shader::ConditionCode::T, |
| 3423 | "EXIT Control Code used: {}", static_cast<u32>(cc)); | 3436 | "EXIT condition code used: {}", static_cast<u32>(cc)); |
| 3424 | 3437 | ||
| 3425 | if (stage == Maxwell3D::Regs::ShaderStage::Fragment) { | 3438 | if (stage == Maxwell3D::Regs::ShaderStage::Fragment) { |
| 3426 | EmitFragmentOutputsWrite(); | 3439 | EmitFragmentOutputsWrite(); |
| @@ -3452,9 +3465,9 @@ private: | |||
| 3452 | case OpCode::Id::KIL: { | 3465 | case OpCode::Id::KIL: { |
| 3453 | UNIMPLEMENTED_IF(instr.flow.cond != Tegra::Shader::FlowCondition::Always); | 3466 | UNIMPLEMENTED_IF(instr.flow.cond != Tegra::Shader::FlowCondition::Always); |
| 3454 | 3467 | ||
| 3455 | const Tegra::Shader::ControlCode cc = instr.flow_control_code; | 3468 | const Tegra::Shader::ConditionCode cc = instr.flow_condition_code; |
| 3456 | UNIMPLEMENTED_IF_MSG(cc != Tegra::Shader::ControlCode::T, | 3469 | UNIMPLEMENTED_IF_MSG(cc != Tegra::Shader::ConditionCode::T, |
| 3457 | "KIL Control Code used: {}", static_cast<u32>(cc)); | 3470 | "KIL condition code used: {}", static_cast<u32>(cc)); |
| 3458 | 3471 | ||
| 3459 | // Enclose "discard" in a conditional, so that GLSL compilation does not complain | 3472 | // Enclose "discard" in a conditional, so that GLSL compilation does not complain |
| 3460 | // about unexecuted instructions that may follow this. | 3473 | // about unexecuted instructions that may follow this. |
| @@ -3516,9 +3529,9 @@ private: | |||
| 3516 | UNIMPLEMENTED_IF_MSG(instr.bra.constant_buffer != 0, | 3529 | UNIMPLEMENTED_IF_MSG(instr.bra.constant_buffer != 0, |
| 3517 | "BRA with constant buffers are not implemented"); | 3530 | "BRA with constant buffers are not implemented"); |
| 3518 | 3531 | ||
| 3519 | const Tegra::Shader::ControlCode cc = instr.flow_control_code; | 3532 | const Tegra::Shader::ConditionCode cc = instr.flow_condition_code; |
| 3520 | UNIMPLEMENTED_IF_MSG(cc != Tegra::Shader::ControlCode::T, | 3533 | UNIMPLEMENTED_IF_MSG(cc != Tegra::Shader::ConditionCode::T, |
| 3521 | "BRA Control Code used: {}", static_cast<u32>(cc)); | 3534 | "BRA condition code used: {}", static_cast<u32>(cc)); |
| 3522 | 3535 | ||
| 3523 | const u32 target = offset + instr.bra.GetBranchTarget(); | 3536 | const u32 target = offset + instr.bra.GetBranchTarget(); |
| 3524 | shader.AddLine("{ jmp_to = " + std::to_string(target) + "u; break; }"); | 3537 | shader.AddLine("{ jmp_to = " + std::to_string(target) + "u; break; }"); |
| @@ -3561,9 +3574,9 @@ private: | |||
| 3561 | break; | 3574 | break; |
| 3562 | } | 3575 | } |
| 3563 | case OpCode::Id::SYNC: { | 3576 | case OpCode::Id::SYNC: { |
| 3564 | const Tegra::Shader::ControlCode cc = instr.flow_control_code; | 3577 | const Tegra::Shader::ConditionCode cc = instr.flow_condition_code; |
| 3565 | UNIMPLEMENTED_IF_MSG(cc != Tegra::Shader::ControlCode::T, | 3578 | UNIMPLEMENTED_IF_MSG(cc != Tegra::Shader::ConditionCode::T, |
| 3566 | "SYNC Control Code used: {}", static_cast<u32>(cc)); | 3579 | "SYNC condition code used: {}", static_cast<u32>(cc)); |
| 3567 | 3580 | ||
| 3568 | // The SYNC opcode jumps to the address previously set by the SSY opcode | 3581 | // The SYNC opcode jumps to the address previously set by the SSY opcode |
| 3569 | EmitPopFromFlowStack(); | 3582 | EmitPopFromFlowStack(); |
| @@ -3571,10 +3584,10 @@ private: | |||
| 3571 | } | 3584 | } |
| 3572 | case OpCode::Id::BRK: { | 3585 | case OpCode::Id::BRK: { |
| 3573 | // The BRK opcode jumps to the address previously set by the PBK opcode | 3586 | // The BRK opcode jumps to the address previously set by the PBK opcode |
| 3574 | const Tegra::Shader::ControlCode cc = instr.flow_control_code; | 3587 | const Tegra::Shader::ConditionCode cc = instr.flow_condition_code; |
| 3575 | if (cc != Tegra::Shader::ControlCode::T) { | 3588 | UNIMPLEMENTED_IF_MSG(cc != Tegra::Shader::ConditionCode::T, |
| 3576 | UNIMPLEMENTED_MSG("BRK Control Code used: {}", static_cast<u32>(cc)); | 3589 | "BRK condition code used: {}", static_cast<u32>(cc)); |
| 3577 | } | 3590 | |
| 3578 | EmitPopFromFlowStack(); | 3591 | EmitPopFromFlowStack(); |
| 3579 | break; | 3592 | break; |
| 3580 | } | 3593 | } |
| @@ -3585,6 +3598,9 @@ private: | |||
| 3585 | break; | 3598 | break; |
| 3586 | } | 3599 | } |
| 3587 | case OpCode::Id::VMAD: { | 3600 | case OpCode::Id::VMAD: { |
| 3601 | UNIMPLEMENTED_IF_MSG(instr.generates_cc, | ||
| 3602 | "Condition codes generation in VMAD is not implemented"); | ||
| 3603 | |||
| 3588 | const bool result_signed = instr.video.signed_a == 1 || instr.video.signed_b == 1; | 3604 | const bool result_signed = instr.video.signed_a == 1 || instr.video.signed_b == 1; |
| 3589 | const std::string op_a = GetVideoOperandA(instr); | 3605 | const std::string op_a = GetVideoOperandA(instr); |
| 3590 | const std::string op_b = GetVideoOperandB(instr); | 3606 | const std::string op_b = GetVideoOperandB(instr); |
| @@ -3604,10 +3620,6 @@ private: | |||
| 3604 | regs.SetRegisterToInteger(instr.gpr0, result_signed, 1, result, 1, 1, | 3620 | regs.SetRegisterToInteger(instr.gpr0, result_signed, 1, result, 1, 1, |
| 3605 | instr.vmad.saturate == 1, 0, Register::Size::Word, | 3621 | instr.vmad.saturate == 1, 0, Register::Size::Word, |
| 3606 | instr.vmad.cc); | 3622 | instr.vmad.cc); |
| 3607 | if (instr.generates_cc) { | ||
| 3608 | UNIMPLEMENTED_MSG("VMAD Generates an unhandled Control Code"); | ||
| 3609 | } | ||
| 3610 | |||
| 3611 | break; | 3623 | break; |
| 3612 | } | 3624 | } |
| 3613 | case OpCode::Id::VSETP: { | 3625 | case OpCode::Id::VSETP: { |