summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorGravatar Rodolfo Bogado2018-12-11 00:47:17 -0300
committerGravatar Rodolfo Bogado2018-12-22 19:19:18 -0300
commit7e72b5e453ee4c2a62021f6b3c8ad21267c8b24a (patch)
treebf21d7c278c9ba7985e55c7cc94078d27b0dd7a3
parentMerge pull request #1921 from ogniK5377/no-unit (diff)
downloadyuzu-7e72b5e453ee4c2a62021f6b3c8ad21267c8b24a.tar.gz
yuzu-7e72b5e453ee4c2a62021f6b3c8ad21267c8b24a.tar.xz
yuzu-7e72b5e453ee4c2a62021f6b3c8ad21267c8b24a.zip
complete emulation of ZeroFlag
-rw-r--r--src/video_core/renderer_opengl/gl_shader_decompiler.cpp197
1 files changed, 97 insertions, 100 deletions
diff --git a/src/video_core/renderer_opengl/gl_shader_decompiler.cpp b/src/video_core/renderer_opengl/gl_shader_decompiler.cpp
index 4e685fa2c..3828b8762 100644
--- a/src/video_core/renderer_opengl/gl_shader_decompiler.cpp
+++ b/src/video_core/renderer_opengl/gl_shader_decompiler.cpp
@@ -405,10 +405,17 @@ public:
405 */ 405 */
406 void SetRegisterToFloat(const Register& reg, u64 elem, const std::string& value, 406 void SetRegisterToFloat(const Register& reg, u64 elem, const std::string& value,
407 u64 dest_num_components, u64 value_num_components, 407 u64 dest_num_components, u64 value_num_components,
408 bool is_saturated = false, u64 dest_elem = 0, bool precise = false) { 408 bool is_saturated = false, bool sets_cc = false, u64 dest_elem = 0,
409 bool precise = false) {
409 410
410 SetRegister(reg, elem, is_saturated ? "clamp(" + value + ", 0.0, 1.0)" : value, 411 SetRegister(reg, elem, is_saturated ? "clamp(" + value + ", 0.0, 1.0)" : value,
411 dest_num_components, value_num_components, dest_elem, precise); 412 dest_num_components, value_num_components, dest_elem, precise);
413 if (sets_cc) {
414 const std::string zero_condition =
415 "( " + GetRegister(reg, static_cast<u32>(dest_elem)) + " == 0 )";
416 SetInternalFlag(InternalFlag::ZeroFlag, zero_condition);
417 LOG_WARNING(HW_GPU, "Condition codes implementation is incomplete.");
418 }
412 } 419 }
413 420
414 /** 421 /**
@@ -425,8 +432,8 @@ public:
425 void SetRegisterToInteger(const Register& reg, bool is_signed, u64 elem, 432 void SetRegisterToInteger(const Register& reg, bool is_signed, u64 elem,
426 const std::string& value, u64 dest_num_components, 433 const std::string& value, u64 dest_num_components,
427 u64 value_num_components, bool is_saturated = false, 434 u64 value_num_components, bool is_saturated = false,
428 u64 dest_elem = 0, Register::Size size = Register::Size::Word, 435 bool sets_cc = false, u64 dest_elem = 0,
429 bool sets_cc = false) { 436 Register::Size size = Register::Size::Word) {
430 UNIMPLEMENTED_IF(is_saturated); 437 UNIMPLEMENTED_IF(is_saturated);
431 438
432 const std::string func{is_signed ? "intBitsToFloat" : "uintBitsToFloat"}; 439 const std::string func{is_signed ? "intBitsToFloat" : "uintBitsToFloat"};
@@ -435,7 +442,8 @@ public:
435 dest_num_components, value_num_components, dest_elem, false); 442 dest_num_components, value_num_components, dest_elem, false);
436 443
437 if (sets_cc) { 444 if (sets_cc) {
438 const std::string zero_condition = "( " + ConvertIntegerSize(value, size) + " == 0 )"; 445 const std::string zero_condition =
446 "( " + GetRegister(reg, static_cast<u32>(dest_elem)) + " == 0 )";
439 SetInternalFlag(InternalFlag::ZeroFlag, zero_condition); 447 SetInternalFlag(InternalFlag::ZeroFlag, zero_condition);
440 LOG_WARNING(HW_GPU, "Condition codes implementation is incomplete."); 448 LOG_WARNING(HW_GPU, "Condition codes implementation is incomplete.");
441 } 449 }
@@ -1275,7 +1283,7 @@ private:
1275 void WriteLogicOperation(Register dest, LogicOperation logic_op, const std::string& op_a, 1283 void WriteLogicOperation(Register dest, LogicOperation logic_op, const std::string& op_a,
1276 const std::string& op_b, 1284 const std::string& op_b,
1277 Tegra::Shader::PredicateResultMode predicate_mode, 1285 Tegra::Shader::PredicateResultMode predicate_mode,
1278 Tegra::Shader::Pred predicate) { 1286 Tegra::Shader::Pred predicate, const bool set_cc) {
1279 std::string result{}; 1287 std::string result{};
1280 switch (logic_op) { 1288 switch (logic_op) {
1281 case LogicOperation::And: { 1289 case LogicOperation::And: {
@@ -1299,7 +1307,7 @@ private:
1299 } 1307 }
1300 1308
1301 if (dest != Tegra::Shader::Register::ZeroIndex) { 1309 if (dest != Tegra::Shader::Register::ZeroIndex) {
1302 regs.SetRegisterToInteger(dest, true, 0, result, 1, 1); 1310 regs.SetRegisterToInteger(dest, true, 0, result, 1, 1, false, set_cc);
1303 } 1311 }
1304 1312
1305 using Tegra::Shader::PredicateResultMode; 1313 using Tegra::Shader::PredicateResultMode;
@@ -1319,7 +1327,8 @@ private:
1319 } 1327 }
1320 1328
1321 void WriteLop3Instruction(Register dest, const std::string& op_a, const std::string& op_b, 1329 void WriteLop3Instruction(Register dest, const std::string& op_a, const std::string& op_b,
1322 const std::string& op_c, const std::string& imm_lut) { 1330 const std::string& op_c, const std::string& imm_lut,
1331 const bool set_cc) {
1323 if (dest == Tegra::Shader::Register::ZeroIndex) { 1332 if (dest == Tegra::Shader::Register::ZeroIndex) {
1324 return; 1333 return;
1325 } 1334 }
@@ -1342,7 +1351,7 @@ private:
1342 1351
1343 result += ')'; 1352 result += ')';
1344 1353
1345 regs.SetRegisterToInteger(dest, true, 0, result, 1, 1); 1354 regs.SetRegisterToInteger(dest, true, 0, result, 1, 1, false, set_cc);
1346 } 1355 }
1347 1356
1348 void WriteTexsInstructionFloat(const Instruction& instr, const std::string& texture) { 1357 void WriteTexsInstructionFloat(const Instruction& instr, const std::string& texture) {
@@ -1357,12 +1366,12 @@ private:
1357 1366
1358 if (written_components < 2) { 1367 if (written_components < 2) {
1359 // Write the first two swizzle components to gpr0 and gpr0+1 1368 // Write the first two swizzle components to gpr0 and gpr0+1
1360 regs.SetRegisterToFloat(instr.gpr0, component, texture, 1, 4, false, 1369 regs.SetRegisterToFloat(instr.gpr0, component, texture, 1, 4, false, false,
1361 written_components % 2); 1370 written_components % 2);
1362 } else { 1371 } else {
1363 ASSERT(instr.texs.HasTwoDestinations()); 1372 ASSERT(instr.texs.HasTwoDestinations());
1364 // Write the rest of the swizzle components to gpr28 and gpr28+1 1373 // Write the rest of the swizzle components to gpr28 and gpr28+1
1365 regs.SetRegisterToFloat(instr.gpr28, component, texture, 1, 4, false, 1374 regs.SetRegisterToFloat(instr.gpr28, component, texture, 1, 4, false, false,
1366 written_components % 2); 1375 written_components % 2);
1367 } 1376 }
1368 1377
@@ -1608,7 +1617,7 @@ private:
1608 if (process_mode != Tegra::Shader::TextureProcessMode::None && gl_lod_supported) { 1617 if (process_mode != Tegra::Shader::TextureProcessMode::None && gl_lod_supported) {
1609 if (process_mode == Tegra::Shader::TextureProcessMode::LZ) { 1618 if (process_mode == Tegra::Shader::TextureProcessMode::LZ) {
1610 texture += ", 0.0"; 1619 texture += ", 0.0";
1611 } else { 1620 } else {
1612 // If present, lod or bias are always stored in the register indexed by the 1621 // If present, lod or bias are always stored in the register indexed by the
1613 // gpr20 1622 // gpr20
1614 // field with an offset depending on the usage of the other registers 1623 // field with an offset depending on the usage of the other registers
@@ -1871,8 +1880,6 @@ private:
1871 instr.fmul.tab5c68_0 != 1, "FMUL tab5cb8_0({}) is not implemented", 1880 instr.fmul.tab5c68_0 != 1, "FMUL tab5cb8_0({}) is not implemented",
1872 instr.fmul.tab5c68_0 1881 instr.fmul.tab5c68_0
1873 .Value()); // SMO typical sends 1 here which seems to be the default 1882 .Value()); // SMO typical sends 1 here which seems to be the default
1874 UNIMPLEMENTED_IF_MSG(instr.generates_cc,
1875 "Condition codes generation in FMUL is not implemented");
1876 1883
1877 op_b = GetOperandAbsNeg(op_b, false, instr.fmul.negate_b); 1884 op_b = GetOperandAbsNeg(op_b, false, instr.fmul.negate_b);
1878 1885
@@ -1896,20 +1903,17 @@ private:
1896 } 1903 }
1897 1904
1898 regs.SetRegisterToFloat(instr.gpr0, 0, op_a + " * " + op_b + postfactor_op, 1, 1, 1905 regs.SetRegisterToFloat(instr.gpr0, 0, op_a + " * " + op_b + postfactor_op, 1, 1,
1899 instr.alu.saturate_d, 0, true); 1906 instr.alu.saturate_d, instr.generates_cc, 0, true);
1900 break; 1907 break;
1901 } 1908 }
1902 case OpCode::Id::FADD_C: 1909 case OpCode::Id::FADD_C:
1903 case OpCode::Id::FADD_R: 1910 case OpCode::Id::FADD_R:
1904 case OpCode::Id::FADD_IMM: { 1911 case OpCode::Id::FADD_IMM: {
1905 UNIMPLEMENTED_IF_MSG(instr.generates_cc,
1906 "Condition codes generation in FADD is not implemented");
1907
1908 op_a = GetOperandAbsNeg(op_a, instr.alu.abs_a, instr.alu.negate_a); 1912 op_a = GetOperandAbsNeg(op_a, instr.alu.abs_a, instr.alu.negate_a);
1909 op_b = GetOperandAbsNeg(op_b, instr.alu.abs_b, instr.alu.negate_b); 1913 op_b = GetOperandAbsNeg(op_b, instr.alu.abs_b, instr.alu.negate_b);
1910 1914
1911 regs.SetRegisterToFloat(instr.gpr0, 0, op_a + " + " + op_b, 1, 1, 1915 regs.SetRegisterToFloat(instr.gpr0, 0, op_a + " + " + op_b, 1, 1,
1912 instr.alu.saturate_d, 0, true); 1916 instr.alu.saturate_d, instr.generates_cc, 0, true);
1913 break; 1917 break;
1914 } 1918 }
1915 case OpCode::Id::MUFU: { 1919 case OpCode::Id::MUFU: {
@@ -1917,31 +1921,31 @@ private:
1917 switch (instr.sub_op) { 1921 switch (instr.sub_op) {
1918 case SubOp::Cos: 1922 case SubOp::Cos:
1919 regs.SetRegisterToFloat(instr.gpr0, 0, "cos(" + op_a + ')', 1, 1, 1923 regs.SetRegisterToFloat(instr.gpr0, 0, "cos(" + op_a + ')', 1, 1,
1920 instr.alu.saturate_d, 0, true); 1924 instr.alu.saturate_d, false, 0, true);
1921 break; 1925 break;
1922 case SubOp::Sin: 1926 case SubOp::Sin:
1923 regs.SetRegisterToFloat(instr.gpr0, 0, "sin(" + op_a + ')', 1, 1, 1927 regs.SetRegisterToFloat(instr.gpr0, 0, "sin(" + op_a + ')', 1, 1,
1924 instr.alu.saturate_d, 0, true); 1928 instr.alu.saturate_d, false, 0, true);
1925 break; 1929 break;
1926 case SubOp::Ex2: 1930 case SubOp::Ex2:
1927 regs.SetRegisterToFloat(instr.gpr0, 0, "exp2(" + op_a + ')', 1, 1, 1931 regs.SetRegisterToFloat(instr.gpr0, 0, "exp2(" + op_a + ')', 1, 1,
1928 instr.alu.saturate_d, 0, true); 1932 instr.alu.saturate_d, false, 0, true);
1929 break; 1933 break;
1930 case SubOp::Lg2: 1934 case SubOp::Lg2:
1931 regs.SetRegisterToFloat(instr.gpr0, 0, "log2(" + op_a + ')', 1, 1, 1935 regs.SetRegisterToFloat(instr.gpr0, 0, "log2(" + op_a + ')', 1, 1,
1932 instr.alu.saturate_d, 0, true); 1936 instr.alu.saturate_d, false, 0, true);
1933 break; 1937 break;
1934 case SubOp::Rcp: 1938 case SubOp::Rcp:
1935 regs.SetRegisterToFloat(instr.gpr0, 0, "1.0 / " + op_a, 1, 1, 1939 regs.SetRegisterToFloat(instr.gpr0, 0, "1.0 / " + op_a, 1, 1,
1936 instr.alu.saturate_d, 0, true); 1940 instr.alu.saturate_d, false, 0, true);
1937 break; 1941 break;
1938 case SubOp::Rsq: 1942 case SubOp::Rsq:
1939 regs.SetRegisterToFloat(instr.gpr0, 0, "inversesqrt(" + op_a + ')', 1, 1, 1943 regs.SetRegisterToFloat(instr.gpr0, 0, "inversesqrt(" + op_a + ')', 1, 1,
1940 instr.alu.saturate_d, 0, true); 1944 instr.alu.saturate_d, false, 0, true);
1941 break; 1945 break;
1942 case SubOp::Sqrt: 1946 case SubOp::Sqrt:
1943 regs.SetRegisterToFloat(instr.gpr0, 0, "sqrt(" + op_a + ')', 1, 1, 1947 regs.SetRegisterToFloat(instr.gpr0, 0, "sqrt(" + op_a + ')', 1, 1,
1944 instr.alu.saturate_d, 0, true); 1948 instr.alu.saturate_d, false, 0, true);
1945 break; 1949 break;
1946 default: 1950 default:
1947 UNIMPLEMENTED_MSG("Unhandled MUFU sub op={0:x}", 1951 UNIMPLEMENTED_MSG("Unhandled MUFU sub op={0:x}",
@@ -1952,8 +1956,9 @@ private:
1952 case OpCode::Id::FMNMX_C: 1956 case OpCode::Id::FMNMX_C:
1953 case OpCode::Id::FMNMX_R: 1957 case OpCode::Id::FMNMX_R:
1954 case OpCode::Id::FMNMX_IMM: { 1958 case OpCode::Id::FMNMX_IMM: {
1955 UNIMPLEMENTED_IF_MSG(instr.generates_cc, 1959 UNIMPLEMENTED_IF_MSG(
1956 "Condition codes generation in FMNMX is not implemented"); 1960 instr.generates_cc,
1961 "Condition codes generation in FMNMX is partially implemented");
1957 1962
1958 op_a = GetOperandAbsNeg(op_a, instr.alu.abs_a, instr.alu.negate_a); 1963 op_a = GetOperandAbsNeg(op_a, instr.alu.abs_a, instr.alu.negate_a);
1959 op_b = GetOperandAbsNeg(op_b, instr.alu.abs_b, instr.alu.negate_b); 1964 op_b = GetOperandAbsNeg(op_b, instr.alu.abs_b, instr.alu.negate_b);
@@ -1964,7 +1969,7 @@ private:
1964 regs.SetRegisterToFloat(instr.gpr0, 0, 1969 regs.SetRegisterToFloat(instr.gpr0, 0,
1965 '(' + condition + ") ? min(" + parameters + ") : max(" + 1970 '(' + condition + ") ? min(" + parameters + ") : max(" +
1966 parameters + ')', 1971 parameters + ')',
1967 1, 1, false, 0, true); 1972 1, 1, false, instr.generates_cc, 0, true);
1968 break; 1973 break;
1969 } 1974 }
1970 case OpCode::Id::RRO_C: 1975 case OpCode::Id::RRO_C:
@@ -1989,18 +1994,16 @@ private:
1989 break; 1994 break;
1990 } 1995 }
1991 case OpCode::Id::FMUL32_IMM: { 1996 case OpCode::Id::FMUL32_IMM: {
1992 UNIMPLEMENTED_IF_MSG(instr.op_32.generates_cc, 1997 regs.SetRegisterToFloat(
1993 "Condition codes generation in FMUL32 is not implemented"); 1998 instr.gpr0, 0,
1994 1999 regs.GetRegisterAsFloat(instr.gpr8) + " * " + GetImmediate32(instr), 1, 1,
1995 regs.SetRegisterToFloat(instr.gpr0, 0, 2000 instr.fmul32.saturate, instr.op_32.generates_cc, 0, true);
1996 regs.GetRegisterAsFloat(instr.gpr8) + " * " +
1997 GetImmediate32(instr),
1998 1, 1, instr.fmul32.saturate, 0, true);
1999 break; 2001 break;
2000 } 2002 }
2001 case OpCode::Id::FADD32I: { 2003 case OpCode::Id::FADD32I: {
2002 UNIMPLEMENTED_IF_MSG(instr.op_32.generates_cc, 2004 UNIMPLEMENTED_IF_MSG(
2003 "Condition codes generation in FADD32I is not implemented"); 2005 instr.op_32.generates_cc,
2006 "Condition codes generation in FADD32I is partially implemented");
2004 2007
2005 std::string op_a = regs.GetRegisterAsFloat(instr.gpr8); 2008 std::string op_a = regs.GetRegisterAsFloat(instr.gpr8);
2006 std::string op_b = GetImmediate32(instr); 2009 std::string op_b = GetImmediate32(instr);
@@ -2021,7 +2024,8 @@ private:
2021 op_b = "-(" + op_b + ')'; 2024 op_b = "-(" + op_b + ')';
2022 } 2025 }
2023 2026
2024 regs.SetRegisterToFloat(instr.gpr0, 0, op_a + " + " + op_b, 1, 1, false, 0, true); 2027 regs.SetRegisterToFloat(instr.gpr0, 0, op_a + " + " + op_b, 1, 1, false,
2028 instr.op_32.generates_cc, 0, true);
2025 break; 2029 break;
2026 } 2030 }
2027 } 2031 }
@@ -2035,16 +2039,14 @@ private:
2035 2039
2036 switch (opcode->get().GetId()) { 2040 switch (opcode->get().GetId()) {
2037 case OpCode::Id::BFE_IMM: { 2041 case OpCode::Id::BFE_IMM: {
2038 UNIMPLEMENTED_IF_MSG(instr.generates_cc,
2039 "Condition codes generation in BFE is not implemented");
2040
2041 std::string inner_shift = 2042 std::string inner_shift =
2042 '(' + op_a + " << " + std::to_string(instr.bfe.GetLeftShiftValue()) + ')'; 2043 '(' + op_a + " << " + std::to_string(instr.bfe.GetLeftShiftValue()) + ')';
2043 std::string outer_shift = 2044 std::string outer_shift =
2044 '(' + inner_shift + " >> " + 2045 '(' + inner_shift + " >> " +
2045 std::to_string(instr.bfe.GetLeftShiftValue() + instr.bfe.shift_position) + ')'; 2046 std::to_string(instr.bfe.GetLeftShiftValue() + instr.bfe.shift_position) + ')';
2046 2047
2047 regs.SetRegisterToInteger(instr.gpr0, true, 0, outer_shift, 1, 1); 2048 regs.SetRegisterToInteger(instr.gpr0, true, 0, outer_shift, 1, 1, false,
2049 instr.generates_cc);
2048 break; 2050 break;
2049 } 2051 }
2050 default: { 2052 default: {
@@ -2055,8 +2057,6 @@ private:
2055 break; 2057 break;
2056 } 2058 }
2057 case OpCode::Type::Bfi: { 2059 case OpCode::Type::Bfi: {
2058 UNIMPLEMENTED_IF(instr.generates_cc);
2059
2060 const auto [base, packed_shift] = [&]() -> std::tuple<std::string, std::string> { 2060 const auto [base, packed_shift] = [&]() -> std::tuple<std::string, std::string> {
2061 switch (opcode->get().GetId()) { 2061 switch (opcode->get().GetId()) {
2062 case OpCode::Id::BFI_IMM_R: 2062 case OpCode::Id::BFI_IMM_R:
@@ -2071,9 +2071,10 @@ private:
2071 const std::string offset = '(' + packed_shift + " & 0xff)"; 2071 const std::string offset = '(' + packed_shift + " & 0xff)";
2072 const std::string bits = "((" + packed_shift + " >> 8) & 0xff)"; 2072 const std::string bits = "((" + packed_shift + " >> 8) & 0xff)";
2073 const std::string insert = regs.GetRegisterAsInteger(instr.gpr8, 0, false); 2073 const std::string insert = regs.GetRegisterAsInteger(instr.gpr8, 0, false);
2074 regs.SetRegisterToInteger( 2074 regs.SetRegisterToInteger(instr.gpr0, false, 0,
2075 instr.gpr0, false, 0, 2075 "bitfieldInsert(" + base + ", " + insert + ", " + offset +
2076 "bitfieldInsert(" + base + ", " + insert + ", " + offset + ", " + bits + ')', 1, 1); 2076 ", " + bits + ')',
2077 1, 1, false, instr.generates_cc);
2077 break; 2078 break;
2078 } 2079 }
2079 case OpCode::Type::Shift: { 2080 case OpCode::Type::Shift: {
@@ -2095,9 +2096,6 @@ private:
2095 case OpCode::Id::SHR_C: 2096 case OpCode::Id::SHR_C:
2096 case OpCode::Id::SHR_R: 2097 case OpCode::Id::SHR_R:
2097 case OpCode::Id::SHR_IMM: { 2098 case OpCode::Id::SHR_IMM: {
2098 UNIMPLEMENTED_IF_MSG(instr.generates_cc,
2099 "Condition codes generation in SHR is not implemented");
2100
2101 if (!instr.shift.is_signed) { 2099 if (!instr.shift.is_signed) {
2102 // Logical shift right 2100 // Logical shift right
2103 op_a = "uint(" + op_a + ')'; 2101 op_a = "uint(" + op_a + ')';
@@ -2105,7 +2103,7 @@ private:
2105 2103
2106 // Cast to int is superfluous for arithmetic shift, it's only for a logical shift 2104 // Cast to int is superfluous for arithmetic shift, it's only for a logical shift
2107 regs.SetRegisterToInteger(instr.gpr0, true, 0, "int(" + op_a + " >> " + op_b + ')', 2105 regs.SetRegisterToInteger(instr.gpr0, true, 0, "int(" + op_a + " >> " + op_b + ')',
2108 1, 1); 2106 1, 1, false, instr.generates_cc);
2109 break; 2107 break;
2110 } 2108 }
2111 case OpCode::Id::SHL_C: 2109 case OpCode::Id::SHL_C:
@@ -2113,7 +2111,8 @@ private:
2113 case OpCode::Id::SHL_IMM: 2111 case OpCode::Id::SHL_IMM:
2114 UNIMPLEMENTED_IF_MSG(instr.generates_cc, 2112 UNIMPLEMENTED_IF_MSG(instr.generates_cc,
2115 "Condition codes generation in SHL is not implemented"); 2113 "Condition codes generation in SHL is not implemented");
2116 regs.SetRegisterToInteger(instr.gpr0, true, 0, op_a + " << " + op_b, 1, 1); 2114 regs.SetRegisterToInteger(instr.gpr0, true, 0, op_a + " << " + op_b, 1, 1, false,
2115 instr.generates_cc);
2117 break; 2116 break;
2118 default: { 2117 default: {
2119 UNIMPLEMENTED_MSG("Unhandled shift instruction: {}", opcode->get().GetName()); 2118 UNIMPLEMENTED_MSG("Unhandled shift instruction: {}", opcode->get().GetName());
@@ -2127,18 +2126,17 @@ private:
2127 2126
2128 switch (opcode->get().GetId()) { 2127 switch (opcode->get().GetId()) {
2129 case OpCode::Id::IADD32I: 2128 case OpCode::Id::IADD32I:
2130 UNIMPLEMENTED_IF_MSG(instr.op_32.generates_cc, 2129 UNIMPLEMENTED_IF_MSG(
2131 "Condition codes generation in IADD32I is not implemented"); 2130 instr.op_32.generates_cc,
2131 "Condition codes generation in IADD32I is partially implemented");
2132 2132
2133 if (instr.iadd32i.negate_a) 2133 if (instr.iadd32i.negate_a)
2134 op_a = "-(" + op_a + ')'; 2134 op_a = "-(" + op_a + ')';
2135 2135
2136 regs.SetRegisterToInteger(instr.gpr0, true, 0, op_a + " + " + op_b, 1, 1, 2136 regs.SetRegisterToInteger(instr.gpr0, true, 0, op_a + " + " + op_b, 1, 1,
2137 instr.iadd32i.saturate != 0); 2137 instr.iadd32i.saturate, instr.op_32.generates_cc);
2138 break; 2138 break;
2139 case OpCode::Id::LOP32I: { 2139 case OpCode::Id::LOP32I: {
2140 UNIMPLEMENTED_IF_MSG(instr.op_32.generates_cc,
2141 "Condition codes generation in LOP32I is not implemented");
2142 2140
2143 if (instr.alu.lop32i.invert_a) 2141 if (instr.alu.lop32i.invert_a)
2144 op_a = "~(" + op_a + ')'; 2142 op_a = "~(" + op_a + ')';
@@ -2148,7 +2146,7 @@ private:
2148 2146
2149 WriteLogicOperation(instr.gpr0, instr.alu.lop32i.operation, op_a, op_b, 2147 WriteLogicOperation(instr.gpr0, instr.alu.lop32i.operation, op_a, op_b,
2150 Tegra::Shader::PredicateResultMode::None, 2148 Tegra::Shader::PredicateResultMode::None,
2151 Tegra::Shader::Pred::UnusedIndex); 2149 Tegra::Shader::Pred::UnusedIndex, instr.op_32.generates_cc);
2152 break; 2150 break;
2153 } 2151 }
2154 default: { 2152 default: {
@@ -2177,7 +2175,7 @@ private:
2177 case OpCode::Id::IADD_R: 2175 case OpCode::Id::IADD_R:
2178 case OpCode::Id::IADD_IMM: { 2176 case OpCode::Id::IADD_IMM: {
2179 UNIMPLEMENTED_IF_MSG(instr.generates_cc, 2177 UNIMPLEMENTED_IF_MSG(instr.generates_cc,
2180 "Condition codes generation in IADD is not implemented"); 2178 "Condition codes generation in IADD is partially implemented");
2181 2179
2182 if (instr.alu_integer.negate_a) 2180 if (instr.alu_integer.negate_a)
2183 op_a = "-(" + op_a + ')'; 2181 op_a = "-(" + op_a + ')';
@@ -2186,14 +2184,15 @@ private:
2186 op_b = "-(" + op_b + ')'; 2184 op_b = "-(" + op_b + ')';
2187 2185
2188 regs.SetRegisterToInteger(instr.gpr0, true, 0, op_a + " + " + op_b, 1, 1, 2186 regs.SetRegisterToInteger(instr.gpr0, true, 0, op_a + " + " + op_b, 1, 1,
2189 instr.alu.saturate_d); 2187 instr.alu.saturate_d, instr.generates_cc);
2190 break; 2188 break;
2191 } 2189 }
2192 case OpCode::Id::IADD3_C: 2190 case OpCode::Id::IADD3_C:
2193 case OpCode::Id::IADD3_R: 2191 case OpCode::Id::IADD3_R:
2194 case OpCode::Id::IADD3_IMM: { 2192 case OpCode::Id::IADD3_IMM: {
2195 UNIMPLEMENTED_IF_MSG(instr.generates_cc, 2193 UNIMPLEMENTED_IF_MSG(
2196 "Condition codes generation in IADD3 is not implemented"); 2194 instr.generates_cc,
2195 "Condition codes generation in IADD3 is partially implemented");
2197 2196
2198 std::string op_c = regs.GetRegisterAsInteger(instr.gpr39); 2197 std::string op_c = regs.GetRegisterAsInteger(instr.gpr39);
2199 2198
@@ -2249,14 +2248,16 @@ private:
2249 result = '(' + op_a + " + " + op_b + " + " + op_c + ')'; 2248 result = '(' + op_a + " + " + op_b + " + " + op_c + ')';
2250 } 2249 }
2251 2250
2252 regs.SetRegisterToInteger(instr.gpr0, true, 0, result, 1, 1); 2251 regs.SetRegisterToInteger(instr.gpr0, true, 0, result, 1, 1, false,
2252 instr.generates_cc);
2253 break; 2253 break;
2254 } 2254 }
2255 case OpCode::Id::ISCADD_C: 2255 case OpCode::Id::ISCADD_C:
2256 case OpCode::Id::ISCADD_R: 2256 case OpCode::Id::ISCADD_R:
2257 case OpCode::Id::ISCADD_IMM: { 2257 case OpCode::Id::ISCADD_IMM: {
2258 UNIMPLEMENTED_IF_MSG(instr.generates_cc, 2258 UNIMPLEMENTED_IF_MSG(
2259 "Condition codes generation in ISCADD is not implemented"); 2259 instr.generates_cc,
2260 "Condition codes generation in ISCADD is partially implemented");
2260 2261
2261 if (instr.alu_integer.negate_a) 2262 if (instr.alu_integer.negate_a)
2262 op_a = "-(" + op_a + ')'; 2263 op_a = "-(" + op_a + ')';
@@ -2267,7 +2268,8 @@ private:
2267 const std::string shift = std::to_string(instr.alu_integer.shift_amount.Value()); 2268 const std::string shift = std::to_string(instr.alu_integer.shift_amount.Value());
2268 2269
2269 regs.SetRegisterToInteger(instr.gpr0, true, 0, 2270 regs.SetRegisterToInteger(instr.gpr0, true, 0,
2270 "((" + op_a + " << " + shift + ") + " + op_b + ')', 1, 1); 2271 "((" + op_a + " << " + shift + ") + " + op_b + ')', 1, 1,
2272 false, instr.generates_cc);
2271 break; 2273 break;
2272 } 2274 }
2273 case OpCode::Id::POPC_C: 2275 case OpCode::Id::POPC_C:
@@ -2291,8 +2293,6 @@ private:
2291 case OpCode::Id::LOP_C: 2293 case OpCode::Id::LOP_C:
2292 case OpCode::Id::LOP_R: 2294 case OpCode::Id::LOP_R:
2293 case OpCode::Id::LOP_IMM: { 2295 case OpCode::Id::LOP_IMM: {
2294 UNIMPLEMENTED_IF_MSG(instr.generates_cc,
2295 "Condition codes generation in LOP is not implemented");
2296 2296
2297 if (instr.alu.lop.invert_a) 2297 if (instr.alu.lop.invert_a)
2298 op_a = "~(" + op_a + ')'; 2298 op_a = "~(" + op_a + ')';
@@ -2301,15 +2301,13 @@ private:
2301 op_b = "~(" + op_b + ')'; 2301 op_b = "~(" + op_b + ')';
2302 2302
2303 WriteLogicOperation(instr.gpr0, instr.alu.lop.operation, op_a, op_b, 2303 WriteLogicOperation(instr.gpr0, instr.alu.lop.operation, op_a, op_b,
2304 instr.alu.lop.pred_result_mode, instr.alu.lop.pred48); 2304 instr.alu.lop.pred_result_mode, instr.alu.lop.pred48,
2305 instr.generates_cc);
2305 break; 2306 break;
2306 } 2307 }
2307 case OpCode::Id::LOP3_C: 2308 case OpCode::Id::LOP3_C:
2308 case OpCode::Id::LOP3_R: 2309 case OpCode::Id::LOP3_R:
2309 case OpCode::Id::LOP3_IMM: { 2310 case OpCode::Id::LOP3_IMM: {
2310 UNIMPLEMENTED_IF_MSG(instr.generates_cc,
2311 "Condition codes generation in LOP3 is not implemented");
2312
2313 const std::string op_c = regs.GetRegisterAsInteger(instr.gpr39); 2311 const std::string op_c = regs.GetRegisterAsInteger(instr.gpr39);
2314 std::string lut; 2312 std::string lut;
2315 2313
@@ -2319,15 +2317,16 @@ private:
2319 lut = '(' + std::to_string(instr.alu.lop3.GetImmLut48()) + ')'; 2317 lut = '(' + std::to_string(instr.alu.lop3.GetImmLut48()) + ')';
2320 } 2318 }
2321 2319
2322 WriteLop3Instruction(instr.gpr0, op_a, op_b, op_c, lut); 2320 WriteLop3Instruction(instr.gpr0, op_a, op_b, op_c, lut, instr.generates_cc);
2323 break; 2321 break;
2324 } 2322 }
2325 case OpCode::Id::IMNMX_C: 2323 case OpCode::Id::IMNMX_C:
2326 case OpCode::Id::IMNMX_R: 2324 case OpCode::Id::IMNMX_R:
2327 case OpCode::Id::IMNMX_IMM: { 2325 case OpCode::Id::IMNMX_IMM: {
2328 UNIMPLEMENTED_IF(instr.imnmx.exchange != Tegra::Shader::IMinMaxExchange::None); 2326 UNIMPLEMENTED_IF(instr.imnmx.exchange != Tegra::Shader::IMinMaxExchange::None);
2329 UNIMPLEMENTED_IF_MSG(instr.generates_cc, 2327 UNIMPLEMENTED_IF_MSG(
2330 "Condition codes generation in IMNMX is not implemented"); 2328 instr.generates_cc,
2329 "Condition codes generation in IMNMX is partially implemented");
2331 2330
2332 const std::string condition = 2331 const std::string condition =
2333 GetPredicateCondition(instr.imnmx.pred, instr.imnmx.negate_pred != 0); 2332 GetPredicateCondition(instr.imnmx.pred, instr.imnmx.negate_pred != 0);
@@ -2335,7 +2334,7 @@ private:
2335 regs.SetRegisterToInteger(instr.gpr0, instr.imnmx.is_signed, 0, 2334 regs.SetRegisterToInteger(instr.gpr0, instr.imnmx.is_signed, 0,
2336 '(' + condition + ") ? min(" + parameters + ") : max(" + 2335 '(' + condition + ") ? min(" + parameters + ") : max(" +
2337 parameters + ')', 2336 parameters + ')',
2338 1, 1); 2337 1, 1, false, instr.generates_cc);
2339 break; 2338 break;
2340 } 2339 }
2341 case OpCode::Id::LEA_R2: 2340 case OpCode::Id::LEA_R2:
@@ -2396,7 +2395,8 @@ private:
2396 UNIMPLEMENTED_IF_MSG(instr.lea.pred48 != static_cast<u64>(Pred::UnusedIndex), 2395 UNIMPLEMENTED_IF_MSG(instr.lea.pred48 != static_cast<u64>(Pred::UnusedIndex),
2397 "Unhandled LEA Predicate"); 2396 "Unhandled LEA Predicate");
2398 const std::string value = '(' + op_a + " + (" + op_b + "*(1 << " + op_c + ")))"; 2397 const std::string value = '(' + op_a + " + (" + op_b + "*(1 << " + op_c + ")))";
2399 regs.SetRegisterToInteger(instr.gpr0, true, 0, value, 1, 1); 2398 regs.SetRegisterToInteger(instr.gpr0, true, 0, value, 1, 1, false,
2399 instr.generates_cc);
2400 2400
2401 break; 2401 break;
2402 } 2402 }
@@ -2501,7 +2501,7 @@ private:
2501 UNIMPLEMENTED_IF_MSG(instr.ffma.tab5980_1 != 0, "FFMA tab5980_1({}) not implemented", 2501 UNIMPLEMENTED_IF_MSG(instr.ffma.tab5980_1 != 0, "FFMA tab5980_1({}) not implemented",
2502 instr.ffma.tab5980_1.Value()); 2502 instr.ffma.tab5980_1.Value());
2503 UNIMPLEMENTED_IF_MSG(instr.generates_cc, 2503 UNIMPLEMENTED_IF_MSG(instr.generates_cc,
2504 "Condition codes generation in FFMA is not implemented"); 2504 "Condition codes generation in FFMA is partially implemented");
2505 2505
2506 switch (opcode->get().GetId()) { 2506 switch (opcode->get().GetId()) {
2507 case OpCode::Id::FFMA_CR: { 2507 case OpCode::Id::FFMA_CR: {
@@ -2532,7 +2532,7 @@ private:
2532 } 2532 }
2533 2533
2534 regs.SetRegisterToFloat(instr.gpr0, 0, "fma(" + op_a + ", " + op_b + ", " + op_c + ')', 2534 regs.SetRegisterToFloat(instr.gpr0, 0, "fma(" + op_a + ", " + op_b + ", " + op_c + ')',
2535 1, 1, instr.alu.saturate_d, 0, true); 2535 1, 1, instr.alu.saturate_d, instr.generates_cc, 0, true);
2536 break; 2536 break;
2537 } 2537 }
2538 case OpCode::Type::Hfma2: { 2538 case OpCode::Type::Hfma2: {
@@ -2603,16 +2603,14 @@ private:
2603 } 2603 }
2604 2604
2605 regs.SetRegisterToInteger(instr.gpr0, instr.conversion.is_output_signed, 0, op_a, 1, 2605 regs.SetRegisterToInteger(instr.gpr0, instr.conversion.is_output_signed, 0, op_a, 1,
2606 1, instr.alu.saturate_d, 0, instr.conversion.dest_size, 2606 1, instr.alu.saturate_d, instr.generates_cc, 0,
2607 instr.generates_cc.Value() != 0); 2607 instr.conversion.dest_size);
2608 break; 2608 break;
2609 } 2609 }
2610 case OpCode::Id::I2F_R: 2610 case OpCode::Id::I2F_R:
2611 case OpCode::Id::I2F_C: { 2611 case OpCode::Id::I2F_C: {
2612 UNIMPLEMENTED_IF(instr.conversion.dest_size != Register::Size::Word); 2612 UNIMPLEMENTED_IF(instr.conversion.dest_size != Register::Size::Word);
2613 UNIMPLEMENTED_IF(instr.conversion.selector); 2613 UNIMPLEMENTED_IF(instr.conversion.selector);
2614 UNIMPLEMENTED_IF_MSG(instr.generates_cc,
2615 "Condition codes generation in I2F is not implemented");
2616 std::string op_a; 2614 std::string op_a;
2617 2615
2618 if (instr.is_b_gpr) { 2616 if (instr.is_b_gpr) {
@@ -2635,14 +2633,12 @@ private:
2635 op_a = "-(" + op_a + ')'; 2633 op_a = "-(" + op_a + ')';
2636 } 2634 }
2637 2635
2638 regs.SetRegisterToFloat(instr.gpr0, 0, op_a, 1, 1); 2636 regs.SetRegisterToFloat(instr.gpr0, 0, op_a, 1, 1, false, instr.generates_cc);
2639 break; 2637 break;
2640 } 2638 }
2641 case OpCode::Id::F2F_R: { 2639 case OpCode::Id::F2F_R: {
2642 UNIMPLEMENTED_IF(instr.conversion.dest_size != Register::Size::Word); 2640 UNIMPLEMENTED_IF(instr.conversion.dest_size != Register::Size::Word);
2643 UNIMPLEMENTED_IF(instr.conversion.src_size != Register::Size::Word); 2641 UNIMPLEMENTED_IF(instr.conversion.src_size != Register::Size::Word);
2644 UNIMPLEMENTED_IF_MSG(instr.generates_cc,
2645 "Condition codes generation in F2F is not implemented");
2646 std::string op_a = regs.GetRegisterAsFloat(instr.gpr20); 2642 std::string op_a = regs.GetRegisterAsFloat(instr.gpr20);
2647 2643
2648 if (instr.conversion.abs_a) { 2644 if (instr.conversion.abs_a) {
@@ -2674,14 +2670,13 @@ private:
2674 break; 2670 break;
2675 } 2671 }
2676 2672
2677 regs.SetRegisterToFloat(instr.gpr0, 0, op_a, 1, 1, instr.alu.saturate_d); 2673 regs.SetRegisterToFloat(instr.gpr0, 0, op_a, 1, 1, instr.alu.saturate_d,
2674 instr.generates_cc);
2678 break; 2675 break;
2679 } 2676 }
2680 case OpCode::Id::F2I_R: 2677 case OpCode::Id::F2I_R:
2681 case OpCode::Id::F2I_C: { 2678 case OpCode::Id::F2I_C: {
2682 UNIMPLEMENTED_IF(instr.conversion.src_size != Register::Size::Word); 2679 UNIMPLEMENTED_IF(instr.conversion.src_size != Register::Size::Word);
2683 UNIMPLEMENTED_IF_MSG(instr.generates_cc,
2684 "Condition codes generation in F2I is not implemented");
2685 std::string op_a{}; 2680 std::string op_a{};
2686 2681
2687 if (instr.is_b_gpr) { 2682 if (instr.is_b_gpr) {
@@ -2724,7 +2719,8 @@ private:
2724 } 2719 }
2725 2720
2726 regs.SetRegisterToInteger(instr.gpr0, instr.conversion.is_output_signed, 0, op_a, 1, 2721 regs.SetRegisterToInteger(instr.gpr0, instr.conversion.is_output_signed, 0, op_a, 1,
2727 1, false, 0, instr.conversion.dest_size); 2722 1, false, instr.generates_cc, 0,
2723 instr.conversion.dest_size);
2728 break; 2724 break;
2729 } 2725 }
2730 default: { 2726 default: {
@@ -2887,7 +2883,7 @@ private:
2887 shader.AddLine(coord); 2883 shader.AddLine(coord);
2888 2884
2889 if (depth_compare) { 2885 if (depth_compare) {
2890 regs.SetRegisterToFloat(instr.gpr0, 0, texture, 1, 1, false); 2886 regs.SetRegisterToFloat(instr.gpr0, 0, texture, 1, 1);
2891 } else { 2887 } else {
2892 shader.AddLine("vec4 texture_tmp = " + texture + ';'); 2888 shader.AddLine("vec4 texture_tmp = " + texture + ';');
2893 std::size_t dest_elem{}; 2889 std::size_t dest_elem{};
@@ -2896,7 +2892,7 @@ private:
2896 // Skip disabled components 2892 // Skip disabled components
2897 continue; 2893 continue;
2898 } 2894 }
2899 regs.SetRegisterToFloat(instr.gpr0, elem, "texture_tmp", 1, 4, false, 2895 regs.SetRegisterToFloat(instr.gpr0, elem, "texture_tmp", 1, 4, false, false,
2900 dest_elem); 2896 dest_elem);
2901 ++dest_elem; 2897 ++dest_elem;
2902 } 2898 }
@@ -2982,7 +2978,7 @@ private:
2982 // Skip disabled components 2978 // Skip disabled components
2983 continue; 2979 continue;
2984 } 2980 }
2985 regs.SetRegisterToFloat(instr.gpr0, elem, "texture_tmp", 1, 4, false, 2981 regs.SetRegisterToFloat(instr.gpr0, elem, "texture_tmp", 1, 4, false, false,
2986 dest_elem); 2982 dest_elem);
2987 ++dest_elem; 2983 ++dest_elem;
2988 } 2984 }
@@ -3231,7 +3227,7 @@ private:
3231 } 3227 }
3232 case OpCode::Type::PredicateSetRegister: { 3228 case OpCode::Type::PredicateSetRegister: {
3233 UNIMPLEMENTED_IF_MSG(instr.generates_cc, 3229 UNIMPLEMENTED_IF_MSG(instr.generates_cc,
3234 "Condition codes generation in PSET is not implemented"); 3230 "Condition codes generation in PSET is partially implemented");
3235 3231
3236 const std::string op_a = 3232 const std::string op_a =
3237 GetPredicateCondition(instr.pset.pred12, instr.pset.neg_pred12 != 0); 3233 GetPredicateCondition(instr.pset.pred12, instr.pset.neg_pred12 != 0);
@@ -3248,10 +3244,11 @@ private:
3248 const std::string result = '(' + predicate + ") " + combiner + " (" + second_pred + ')'; 3244 const std::string result = '(' + predicate + ") " + combiner + " (" + second_pred + ')';
3249 if (instr.pset.bf == 0) { 3245 if (instr.pset.bf == 0) {
3250 const std::string value = '(' + result + ") ? 0xFFFFFFFF : 0"; 3246 const std::string value = '(' + result + ") ? 0xFFFFFFFF : 0";
3251 regs.SetRegisterToInteger(instr.gpr0, false, 0, value, 1, 1); 3247 regs.SetRegisterToInteger(instr.gpr0, false, 0, value, 1, 1, false,
3248 instr.generates_cc);
3252 } else { 3249 } else {
3253 const std::string value = '(' + result + ") ? 1.0 : 0.0"; 3250 const std::string value = '(' + result + ") ? 1.0 : 0.0";
3254 regs.SetRegisterToFloat(instr.gpr0, 0, value, 1, 1); 3251 regs.SetRegisterToFloat(instr.gpr0, 0, value, 1, 1, false, instr.generates_cc);
3255 } 3252 }
3256 break; 3253 break;
3257 } 3254 }
@@ -3462,7 +3459,7 @@ private:
3462 UNIMPLEMENTED_IF(instr.xmad.sign_a); 3459 UNIMPLEMENTED_IF(instr.xmad.sign_a);
3463 UNIMPLEMENTED_IF(instr.xmad.sign_b); 3460 UNIMPLEMENTED_IF(instr.xmad.sign_b);
3464 UNIMPLEMENTED_IF_MSG(instr.generates_cc, 3461 UNIMPLEMENTED_IF_MSG(instr.generates_cc,
3465 "Condition codes generation in XMAD is not implemented"); 3462 "Condition codes generation in XMAD is partially implemented");
3466 3463
3467 std::string op_a{regs.GetRegisterAsInteger(instr.gpr8, 0, instr.xmad.sign_a)}; 3464 std::string op_a{regs.GetRegisterAsInteger(instr.gpr8, 0, instr.xmad.sign_a)};
3468 std::string op_b; 3465 std::string op_b;
@@ -3548,7 +3545,8 @@ private:
3548 sum = "((" + sum + " & 0xFFFF) | (" + src2 + "<< 16))"; 3545 sum = "((" + sum + " & 0xFFFF) | (" + src2 + "<< 16))";
3549 } 3546 }
3550 3547
3551 regs.SetRegisterToInteger(instr.gpr0, is_signed, 0, sum, 1, 1); 3548 regs.SetRegisterToInteger(instr.gpr0, is_signed, 0, sum, 1, 1, false,
3549 instr.generates_cc);
3552 break; 3550 break;
3553 } 3551 }
3554 default: { 3552 default: {
@@ -3752,8 +3750,7 @@ private:
3752 } 3750 }
3753 3751
3754 regs.SetRegisterToInteger(instr.gpr0, result_signed, 1, result, 1, 1, 3752 regs.SetRegisterToInteger(instr.gpr0, result_signed, 1, result, 1, 1,
3755 instr.vmad.saturate == 1, 0, Register::Size::Word, 3753 instr.vmad.saturate, instr.vmad.cc);
3756 instr.vmad.cc);
3757 break; 3754 break;
3758 } 3755 }
3759 case OpCode::Id::VSETP: { 3756 case OpCode::Id::VSETP: {