diff options
Diffstat (limited to 'src')
| -rw-r--r-- | src/video_core/renderer_opengl/gl_shader_decompiler.cpp | 197 |
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: { |