From 15a0e1481d9a1efb3e3aa61cbaf2fa1ba0392d71 Mon Sep 17 00:00:00 2001 From: ReinUsesLisp Date: Thu, 20 Dec 2018 19:09:21 -0300 Subject: shader_ir: Initial implementation --- .../shader/decode/arithmetic_integer.cpp | 24 ++++++++++++++++++++++ 1 file changed, 24 insertions(+) create mode 100644 src/video_core/shader/decode/arithmetic_integer.cpp (limited to 'src/video_core/shader/decode/arithmetic_integer.cpp') diff --git a/src/video_core/shader/decode/arithmetic_integer.cpp b/src/video_core/shader/decode/arithmetic_integer.cpp new file mode 100644 index 000000000..12c64e97a --- /dev/null +++ b/src/video_core/shader/decode/arithmetic_integer.cpp @@ -0,0 +1,24 @@ +// Copyright 2018 yuzu Emulator Project +// Licensed under GPLv2 or any later version +// Refer to the license.txt file included. + +#include "common/assert.h" +#include "common/common_types.h" +#include "video_core/engines/shader_bytecode.h" +#include "video_core/shader/shader_ir.h" + +namespace VideoCommon::Shader { + +using Tegra::Shader::Instruction; +using Tegra::Shader::OpCode; + +u32 ShaderIR::DecodeArithmeticInteger(BasicBlock& bb, u32 pc) { + const Instruction instr = {program_code[pc]}; + const auto opcode = OpCode::Decode(instr); + + UNIMPLEMENTED(); + + return pc; +} + +} // namespace VideoCommon::Shader \ No newline at end of file -- cgit v1.2.3 From ccb71bece9e6e6c9ceabc0826624f645c5140c53 Mon Sep 17 00:00:00 2001 From: ReinUsesLisp Date: Fri, 21 Dec 2018 02:22:18 -0300 Subject: shader_decode: Implement IADD --- .../shader/decode/arithmetic_integer.cpp | 29 +++++++++++++++++++++- 1 file changed, 28 insertions(+), 1 deletion(-) (limited to 'src/video_core/shader/decode/arithmetic_integer.cpp') diff --git a/src/video_core/shader/decode/arithmetic_integer.cpp b/src/video_core/shader/decode/arithmetic_integer.cpp index 12c64e97a..47b27ac5b 100644 --- a/src/video_core/shader/decode/arithmetic_integer.cpp +++ b/src/video_core/shader/decode/arithmetic_integer.cpp @@ -16,7 +16,34 @@ u32 ShaderIR::DecodeArithmeticInteger(BasicBlock& bb, u32 pc) { const Instruction instr = {program_code[pc]}; const auto opcode = OpCode::Decode(instr); - UNIMPLEMENTED(); + Node op_a = GetRegister(instr.gpr8); + Node op_b = [&]() { + if (instr.is_b_imm) { + return Immediate(instr.alu.GetSignedImm20_20()); + } else if (instr.is_b_gpr) { + return GetRegister(instr.gpr20); + } else { + return GetConstBuffer(instr.cbuf34.index, instr.cbuf34.offset); + } + }(); + + switch (opcode->get().GetId()) { + case OpCode::Id::IADD_C: + case OpCode::Id::IADD_R: + case OpCode::Id::IADD_IMM: { + UNIMPLEMENTED_IF_MSG(instr.generates_cc, + "Condition codes generation in IADD is not implemented"); + UNIMPLEMENTED_IF_MSG(instr.alu.saturate_d, "IADD saturation not implemented"); + + op_a = GetOperandAbsNegInteger(op_a, false, instr.alu_integer.negate_a, true); + op_b = GetOperandAbsNegInteger(op_b, false, instr.alu_integer.negate_b, true); + + SetRegister(bb, instr.gpr0, Operation(OperationCode::IAdd, PRECISE, op_a, op_b)); + break; + } + default: + UNIMPLEMENTED_MSG("Unhandled ArithmeticInteger instruction: {}", opcode->get().GetName()); + } return pc; } -- cgit v1.2.3 From 8486e7f8c8367a7cc225da9fbac262a116744108 Mon Sep 17 00:00:00 2001 From: ReinUsesLisp Date: Fri, 21 Dec 2018 02:22:44 -0300 Subject: shader_decode: Implement SEL --- src/video_core/shader/decode/arithmetic_integer.cpp | 8 ++++++++ 1 file changed, 8 insertions(+) (limited to 'src/video_core/shader/decode/arithmetic_integer.cpp') diff --git a/src/video_core/shader/decode/arithmetic_integer.cpp b/src/video_core/shader/decode/arithmetic_integer.cpp index 47b27ac5b..429b86813 100644 --- a/src/video_core/shader/decode/arithmetic_integer.cpp +++ b/src/video_core/shader/decode/arithmetic_integer.cpp @@ -41,6 +41,14 @@ u32 ShaderIR::DecodeArithmeticInteger(BasicBlock& bb, u32 pc) { SetRegister(bb, instr.gpr0, Operation(OperationCode::IAdd, PRECISE, op_a, op_b)); break; } + case OpCode::Id::SEL_C: + case OpCode::Id::SEL_R: + case OpCode::Id::SEL_IMM: { + const Node condition = GetPredicate(instr.sel.pred, instr.sel.neg_pred != 0); + const Node value = Operation(OperationCode::Select, PRECISE, condition, op_a, op_b); + SetRegister(bb, instr.gpr0, value); + break; + } default: UNIMPLEMENTED_MSG("Unhandled ArithmeticInteger instruction: {}", opcode->get().GetName()); } -- cgit v1.2.3 From 8f37531f8ef94e9a43d33232f4c2da980ce7bf80 Mon Sep 17 00:00:00 2001 From: ReinUsesLisp Date: Fri, 21 Dec 2018 02:22:57 -0300 Subject: shader_decode: Implement LOP --- src/video_core/shader/decode/arithmetic_integer.cpp | 15 +++++++++++++++ 1 file changed, 15 insertions(+) (limited to 'src/video_core/shader/decode/arithmetic_integer.cpp') diff --git a/src/video_core/shader/decode/arithmetic_integer.cpp b/src/video_core/shader/decode/arithmetic_integer.cpp index 429b86813..d01336e0e 100644 --- a/src/video_core/shader/decode/arithmetic_integer.cpp +++ b/src/video_core/shader/decode/arithmetic_integer.cpp @@ -49,6 +49,21 @@ u32 ShaderIR::DecodeArithmeticInteger(BasicBlock& bb, u32 pc) { SetRegister(bb, instr.gpr0, value); break; } + case OpCode::Id::LOP_C: + case OpCode::Id::LOP_R: + case OpCode::Id::LOP_IMM: { + UNIMPLEMENTED_IF_MSG(instr.generates_cc, + "Condition codes generation in LOP is not implemented"); + + if (instr.alu.lop.invert_a) + op_a = Operation(OperationCode::IBitwiseNot, NO_PRECISE, op_a); + if (instr.alu.lop.invert_b) + op_b = Operation(OperationCode::IBitwiseNot, NO_PRECISE, op_b); + + WriteLogicOperation(bb, instr.gpr0, instr.alu.lop.operation, op_a, op_b, + instr.alu.lop.pred_result_mode, instr.alu.lop.pred48); + break; + } default: UNIMPLEMENTED_MSG("Unhandled ArithmeticInteger instruction: {}", opcode->get().GetName()); } -- cgit v1.2.3 From 210620ff314c774cd0da5a6b50501dec45914751 Mon Sep 17 00:00:00 2001 From: ReinUsesLisp Date: Mon, 17 Dec 2018 18:49:48 -0300 Subject: shader_decode: Implement ISCADD --- src/video_core/shader/decode/arithmetic_integer.cpp | 15 +++++++++++++++ 1 file changed, 15 insertions(+) (limited to 'src/video_core/shader/decode/arithmetic_integer.cpp') diff --git a/src/video_core/shader/decode/arithmetic_integer.cpp b/src/video_core/shader/decode/arithmetic_integer.cpp index d01336e0e..d494af736 100644 --- a/src/video_core/shader/decode/arithmetic_integer.cpp +++ b/src/video_core/shader/decode/arithmetic_integer.cpp @@ -41,6 +41,21 @@ u32 ShaderIR::DecodeArithmeticInteger(BasicBlock& bb, u32 pc) { SetRegister(bb, instr.gpr0, Operation(OperationCode::IAdd, PRECISE, op_a, op_b)); break; } + case OpCode::Id::ISCADD_C: + case OpCode::Id::ISCADD_R: + case OpCode::Id::ISCADD_IMM: { + UNIMPLEMENTED_IF_MSG(instr.generates_cc, + "Condition codes generation in ISCADD is not implemented"); + + op_a = GetOperandAbsNegInteger(op_a, false, instr.alu_integer.negate_a, true); + op_b = GetOperandAbsNegInteger(op_b, false, instr.alu_integer.negate_b, true); + + const Node shift = Immediate(static_cast(instr.alu_integer.shift_amount)); + const Node shifted_a = Operation(OperationCode::ILogicalShiftLeft, NO_PRECISE, op_a, shift); + const Node value = Operation(OperationCode::IAdd, NO_PRECISE, shifted_a, op_b); + SetRegister(bb, instr.gpr0, value); + break; + } case OpCode::Id::SEL_C: case OpCode::Id::SEL_R: case OpCode::Id::SEL_IMM: { -- cgit v1.2.3 From 518a2bd2060a5c1e6b9acb987439e0009d74fb43 Mon Sep 17 00:00:00 2001 From: ReinUsesLisp Date: Mon, 17 Dec 2018 22:01:23 -0300 Subject: shader_decode: Implement IMNMX --- src/video_core/shader/decode/arithmetic_integer.cpp | 16 ++++++++++++++++ 1 file changed, 16 insertions(+) (limited to 'src/video_core/shader/decode/arithmetic_integer.cpp') diff --git a/src/video_core/shader/decode/arithmetic_integer.cpp b/src/video_core/shader/decode/arithmetic_integer.cpp index d494af736..dbdcebbb4 100644 --- a/src/video_core/shader/decode/arithmetic_integer.cpp +++ b/src/video_core/shader/decode/arithmetic_integer.cpp @@ -79,6 +79,22 @@ u32 ShaderIR::DecodeArithmeticInteger(BasicBlock& bb, u32 pc) { instr.alu.lop.pred_result_mode, instr.alu.lop.pred48); break; } + case OpCode::Id::IMNMX_C: + case OpCode::Id::IMNMX_R: + case OpCode::Id::IMNMX_IMM: { + UNIMPLEMENTED_IF(instr.imnmx.exchange != Tegra::Shader::IMinMaxExchange::None); + UNIMPLEMENTED_IF_MSG(instr.generates_cc, + "Condition codes generation in IMNMX is not implemented"); + + const bool is_signed = instr.imnmx.is_signed; + + const Node condition = GetPredicate(instr.imnmx.pred, instr.imnmx.negate_pred != 0); + const Node min = SignedOperation(OperationCode::IMin, is_signed, NO_PRECISE, op_a, op_b); + const Node max = SignedOperation(OperationCode::IMax, is_signed, NO_PRECISE, op_a, op_b); + const Node value = Operation(OperationCode::Select, NO_PRECISE, condition, min, max); + SetRegister(bb, instr.gpr0, value); + break; + } default: UNIMPLEMENTED_MSG("Unhandled ArithmeticInteger instruction: {}", opcode->get().GetName()); } -- cgit v1.2.3 From a40fd075164a5f86367dfa7bea4d7815148e63b7 Mon Sep 17 00:00:00 2001 From: ReinUsesLisp Date: Tue, 18 Dec 2018 22:18:44 -0300 Subject: shader_decode: Implement LOP3 --- .../shader/decode/arithmetic_integer.cpp | 60 ++++++++++++++++++++++ 1 file changed, 60 insertions(+) (limited to 'src/video_core/shader/decode/arithmetic_integer.cpp') diff --git a/src/video_core/shader/decode/arithmetic_integer.cpp b/src/video_core/shader/decode/arithmetic_integer.cpp index dbdcebbb4..145bbcfc8 100644 --- a/src/video_core/shader/decode/arithmetic_integer.cpp +++ b/src/video_core/shader/decode/arithmetic_integer.cpp @@ -11,6 +11,7 @@ namespace VideoCommon::Shader { using Tegra::Shader::Instruction; using Tegra::Shader::OpCode; +using Tegra::Shader::Register; u32 ShaderIR::DecodeArithmeticInteger(BasicBlock& bb, u32 pc) { const Instruction instr = {program_code[pc]}; @@ -79,6 +80,24 @@ u32 ShaderIR::DecodeArithmeticInteger(BasicBlock& bb, u32 pc) { instr.alu.lop.pred_result_mode, instr.alu.lop.pred48); break; } + case OpCode::Id::LOP3_C: + case OpCode::Id::LOP3_R: + case OpCode::Id::LOP3_IMM: { + UNIMPLEMENTED_IF_MSG(instr.generates_cc, + "Condition codes generation in LOP3 is not implemented"); + + const Node op_c = GetRegister(instr.gpr39); + const Node lut = [&]() { + if (opcode->get().GetId() == OpCode::Id::LOP3_R) { + return Immediate(instr.alu.lop3.GetImmLut28()); + } else { + return Immediate(instr.alu.lop3.GetImmLut48()); + } + }(); + + WriteLop3Instruction(bb, instr.gpr0, op_a, op_b, op_c, lut); + break; + } case OpCode::Id::IMNMX_C: case OpCode::Id::IMNMX_R: case OpCode::Id::IMNMX_IMM: { @@ -102,4 +121,45 @@ u32 ShaderIR::DecodeArithmeticInteger(BasicBlock& bb, u32 pc) { return pc; } +void ShaderIR::WriteLop3Instruction(BasicBlock& bb, Register dest, Node op_a, Node op_b, Node op_c, + Node imm_lut) { + constexpr u32 lop_iterations = 32; + const Node one = Immediate(1); + const Node two = Immediate(2); + + Node value{}; + for (u32 i = 0; i < lop_iterations; ++i) { + const Node shift_amount = Immediate(i); + + const Node a = Operation(OperationCode::ILogicalShiftRight, NO_PRECISE, op_c, shift_amount); + const Node pack_0 = Operation(OperationCode::IBitwiseAnd, NO_PRECISE, a, one); + + const Node b = Operation(OperationCode::ILogicalShiftRight, NO_PRECISE, op_b, shift_amount); + const Node c = Operation(OperationCode::IBitwiseAnd, NO_PRECISE, b, one); + const Node pack_1 = Operation(OperationCode::ILogicalShiftLeft, NO_PRECISE, c, one); + + const Node d = Operation(OperationCode::ILogicalShiftRight, NO_PRECISE, op_a, shift_amount); + const Node e = Operation(OperationCode::IBitwiseAnd, NO_PRECISE, d, one); + const Node pack_2 = Operation(OperationCode::ILogicalShiftLeft, NO_PRECISE, e, two); + + const Node pack_01 = Operation(OperationCode::IBitwiseAnd, NO_PRECISE, pack_0, pack_1); + const Node pack_012 = Operation(OperationCode::IBitwiseAnd, NO_PRECISE, pack_01, pack_2); + + const Node shifted_bit = + Operation(OperationCode::ILogicalShiftRight, NO_PRECISE, imm_lut, pack_012); + const Node bit = Operation(OperationCode::IBitwiseAnd, NO_PRECISE, shifted_bit, one); + + const Node right = + Operation(OperationCode::ILogicalShiftLeft, NO_PRECISE, bit, shift_amount); + + if (i > 0) { + value = Operation(OperationCode::IBitwiseOr, NO_PRECISE, value, right); + } else { + value = right; + } + } + + SetRegister(bb, dest, value); +} + } // namespace VideoCommon::Shader \ No newline at end of file -- cgit v1.2.3 From 4fd06efeb94ff5fc5af4c5e4b9e8a4fa95d3b383 Mon Sep 17 00:00:00 2001 From: ReinUsesLisp Date: Wed, 19 Dec 2018 00:31:58 -0300 Subject: shader_decode: Implement IADD3 --- .../shader/decode/arithmetic_integer.cpp | 61 ++++++++++++++++++++++ 1 file changed, 61 insertions(+) (limited to 'src/video_core/shader/decode/arithmetic_integer.cpp') diff --git a/src/video_core/shader/decode/arithmetic_integer.cpp b/src/video_core/shader/decode/arithmetic_integer.cpp index 145bbcfc8..3b9b9d6d9 100644 --- a/src/video_core/shader/decode/arithmetic_integer.cpp +++ b/src/video_core/shader/decode/arithmetic_integer.cpp @@ -9,6 +9,7 @@ namespace VideoCommon::Shader { +using Tegra::Shader::IAdd3Height; using Tegra::Shader::Instruction; using Tegra::Shader::OpCode; using Tegra::Shader::Register; @@ -42,6 +43,66 @@ u32 ShaderIR::DecodeArithmeticInteger(BasicBlock& bb, u32 pc) { SetRegister(bb, instr.gpr0, Operation(OperationCode::IAdd, PRECISE, op_a, op_b)); break; } + case OpCode::Id::IADD3_C: + case OpCode::Id::IADD3_R: + case OpCode::Id::IADD3_IMM: { + UNIMPLEMENTED_IF_MSG(instr.generates_cc, + "Condition codes generation in IADD3 is not implemented"); + + Node op_c = GetRegister(instr.gpr39); + + const auto ApplyHeight = [&](IAdd3Height height, Node value) { + switch (height) { + case IAdd3Height::None: + return value; + case IAdd3Height::LowerHalfWord: + return Operation(OperationCode::IBitwiseAnd, NO_PRECISE, value, Immediate(0xffff)); + case IAdd3Height::UpperHalfWord: + return Operation(OperationCode::ILogicalShiftRight, NO_PRECISE, value, + Immediate(16)); + default: + UNIMPLEMENTED_MSG("Unhandled IADD3 height: {}", static_cast(height)); + return Immediate(0); + } + }; + + if (opcode->get().GetId() == OpCode::Id::IADD3_R) { + op_a = ApplyHeight(instr.iadd3.height_a, op_a); + op_b = ApplyHeight(instr.iadd3.height_b, op_b); + op_c = ApplyHeight(instr.iadd3.height_c, op_c); + } + + op_a = GetOperandAbsNegInteger(op_a, false, instr.iadd3.neg_a, true); + op_b = GetOperandAbsNegInteger(op_b, false, instr.iadd3.neg_b, true); + op_c = GetOperandAbsNegInteger(op_c, false, instr.iadd3.neg_c, true); + + const Node value = [&]() { + const Node add_ab = Operation(OperationCode::IAdd, NO_PRECISE, op_a, op_b); + if (opcode->get().GetId() != OpCode::Id::IADD3_R) { + return Operation(OperationCode::IAdd, NO_PRECISE, add_ab, op_c); + } + const Node shifted = [&]() { + switch (instr.iadd3.mode) { + case Tegra::Shader::IAdd3Mode::RightShift: + // TODO(tech4me): According to + // https://envytools.readthedocs.io/en/latest/hw/graph/maxwell/cuda/int.html?highlight=iadd3 + // The addition between op_a and op_b should be done in uint33, more + // investigation required + return Operation(OperationCode::ILogicalShiftRight, NO_PRECISE, add_ab, + Immediate(16)); + case Tegra::Shader::IAdd3Mode::LeftShift: + return Operation(OperationCode::ILogicalShiftLeft, NO_PRECISE, add_ab, + Immediate(16)); + default: + return add_ab; + } + }(); + return Operation(OperationCode::IAdd, NO_PRECISE, shifted, op_c); + }(); + + SetRegister(bb, instr.gpr0, value); + break; + } case OpCode::Id::ISCADD_C: case OpCode::Id::ISCADD_R: case OpCode::Id::ISCADD_IMM: { -- cgit v1.2.3 From c9cf899d1852da73e90ead3d5c0eeee58de6152d Mon Sep 17 00:00:00 2001 From: ReinUsesLisp Date: Wed, 19 Dec 2018 00:43:23 -0300 Subject: shader_decode: Implement LEA --- .../shader/decode/arithmetic_integer.cpp | 55 ++++++++++++++++++++++ 1 file changed, 55 insertions(+) (limited to 'src/video_core/shader/decode/arithmetic_integer.cpp') diff --git a/src/video_core/shader/decode/arithmetic_integer.cpp b/src/video_core/shader/decode/arithmetic_integer.cpp index 3b9b9d6d9..b12dc5ba8 100644 --- a/src/video_core/shader/decode/arithmetic_integer.cpp +++ b/src/video_core/shader/decode/arithmetic_integer.cpp @@ -12,6 +12,7 @@ namespace VideoCommon::Shader { using Tegra::Shader::IAdd3Height; using Tegra::Shader::Instruction; using Tegra::Shader::OpCode; +using Tegra::Shader::Pred; using Tegra::Shader::Register; u32 ShaderIR::DecodeArithmeticInteger(BasicBlock& bb, u32 pc) { @@ -175,6 +176,60 @@ u32 ShaderIR::DecodeArithmeticInteger(BasicBlock& bb, u32 pc) { SetRegister(bb, instr.gpr0, value); break; } + case OpCode::Id::LEA_R2: + case OpCode::Id::LEA_R1: + case OpCode::Id::LEA_IMM: + case OpCode::Id::LEA_RZ: + case OpCode::Id::LEA_HI: { + const auto [op_a, op_b, op_c] = [&]() -> std::tuple { + switch (opcode->get().GetId()) { + case OpCode::Id::LEA_R2: { + return {GetRegister(instr.gpr20), GetRegister(instr.gpr39), + Immediate(static_cast(instr.lea.r2.entry_a))}; + } + + case OpCode::Id::LEA_R1: { + const bool neg = instr.lea.r1.neg != 0; + return {GetOperandAbsNegInteger(GetRegister(instr.gpr8), false, neg, true), + GetRegister(instr.gpr20), + Immediate(static_cast(instr.lea.r1.entry_a))}; + } + + case OpCode::Id::LEA_IMM: { + const bool neg = instr.lea.imm.neg != 0; + return {Immediate(static_cast(instr.lea.imm.entry_a)), + GetOperandAbsNegInteger(GetRegister(instr.gpr8), false, neg, true), + Immediate(static_cast(instr.lea.imm.entry_b))}; + } + + case OpCode::Id::LEA_RZ: { + const bool neg = instr.lea.rz.neg != 0; + return {GetConstBuffer(instr.lea.rz.cb_index, instr.lea.rz.cb_offset), + GetOperandAbsNegInteger(GetRegister(instr.gpr8), false, neg, true), + Immediate(static_cast(instr.lea.rz.entry_a))}; + } + + case OpCode::Id::LEA_HI: + default: + UNIMPLEMENTED_MSG("Unhandled LEA subinstruction: {}", opcode->get().GetName()); + + return {Immediate(static_cast(instr.lea.imm.entry_a)), GetRegister(instr.gpr8), + Immediate(static_cast(instr.lea.imm.entry_b))}; + } + }(); + + UNIMPLEMENTED_IF_MSG(instr.lea.pred48 != static_cast(Pred::UnusedIndex), + "Unhandled LEA Predicate"); + + const Node shifted_c = + Operation(OperationCode::ILogicalShiftLeft, NO_PRECISE, Immediate(1), op_c); + const Node mul_bc = Operation(OperationCode::IMul, NO_PRECISE, op_b, shifted_c); + const Node value = Operation(OperationCode::IAdd, NO_PRECISE, op_a, mul_bc); + + SetRegister(bb, instr.gpr0, value); + + break; + } default: UNIMPLEMENTED_MSG("Unhandled ArithmeticInteger instruction: {}", opcode->get().GetName()); } -- cgit v1.2.3 From 027f443e699652fc30a849efaf8c12725a7b5729 Mon Sep 17 00:00:00 2001 From: ReinUsesLisp Date: Sun, 23 Dec 2018 01:33:47 -0300 Subject: shader_decode: Implement POPC --- src/video_core/shader/decode/arithmetic_integer.cpp | 10 ++++++++++ 1 file changed, 10 insertions(+) (limited to 'src/video_core/shader/decode/arithmetic_integer.cpp') diff --git a/src/video_core/shader/decode/arithmetic_integer.cpp b/src/video_core/shader/decode/arithmetic_integer.cpp index b12dc5ba8..271ce205b 100644 --- a/src/video_core/shader/decode/arithmetic_integer.cpp +++ b/src/video_core/shader/decode/arithmetic_integer.cpp @@ -119,6 +119,16 @@ u32 ShaderIR::DecodeArithmeticInteger(BasicBlock& bb, u32 pc) { SetRegister(bb, instr.gpr0, value); break; } + case OpCode::Id::POPC_C: + case OpCode::Id::POPC_R: + case OpCode::Id::POPC_IMM: { + if (instr.popc.invert) { + op_b = Operation(OperationCode::IBitwiseNot, NO_PRECISE, op_b); + } + const Node value = Operation(OperationCode::IBitCount, PRECISE, op_b); + SetRegister(bb, instr.gpr0, value); + break; + } case OpCode::Id::SEL_C: case OpCode::Id::SEL_R: case OpCode::Id::SEL_IMM: { -- cgit v1.2.3 From 2faad9bf23dbcedc80dca7ed9ad4b81c0416dd5e Mon Sep 17 00:00:00 2001 From: ReinUsesLisp Date: Wed, 26 Dec 2018 02:58:47 -0300 Subject: shader_decode: Use BitfieldExtract instead of shift + and --- src/video_core/shader/decode/arithmetic_integer.cpp | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) (limited to 'src/video_core/shader/decode/arithmetic_integer.cpp') diff --git a/src/video_core/shader/decode/arithmetic_integer.cpp b/src/video_core/shader/decode/arithmetic_integer.cpp index 271ce205b..931e0fa1d 100644 --- a/src/video_core/shader/decode/arithmetic_integer.cpp +++ b/src/video_core/shader/decode/arithmetic_integer.cpp @@ -57,10 +57,9 @@ u32 ShaderIR::DecodeArithmeticInteger(BasicBlock& bb, u32 pc) { case IAdd3Height::None: return value; case IAdd3Height::LowerHalfWord: - return Operation(OperationCode::IBitwiseAnd, NO_PRECISE, value, Immediate(0xffff)); + return BitfieldExtract(value, 0, 16); case IAdd3Height::UpperHalfWord: - return Operation(OperationCode::ILogicalShiftRight, NO_PRECISE, value, - Immediate(16)); + return BitfieldExtract(value, 16, 16); default: UNIMPLEMENTED_MSG("Unhandled IADD3 height: {}", static_cast(height)); return Immediate(0); -- cgit v1.2.3 From 2d6c064e66bac4cb871aa26a12066441a8852008 Mon Sep 17 00:00:00 2001 From: ReinUsesLisp Date: Thu, 27 Dec 2018 16:50:36 -0300 Subject: shader_decode: Improve zero flag implementation --- .../shader/decode/arithmetic_integer.cpp | 31 ++++++++++------------ 1 file changed, 14 insertions(+), 17 deletions(-) (limited to 'src/video_core/shader/decode/arithmetic_integer.cpp') diff --git a/src/video_core/shader/decode/arithmetic_integer.cpp b/src/video_core/shader/decode/arithmetic_integer.cpp index 931e0fa1d..edd1695f4 100644 --- a/src/video_core/shader/decode/arithmetic_integer.cpp +++ b/src/video_core/shader/decode/arithmetic_integer.cpp @@ -34,22 +34,20 @@ u32 ShaderIR::DecodeArithmeticInteger(BasicBlock& bb, u32 pc) { case OpCode::Id::IADD_C: case OpCode::Id::IADD_R: case OpCode::Id::IADD_IMM: { - UNIMPLEMENTED_IF_MSG(instr.generates_cc, - "Condition codes generation in IADD is not implemented"); UNIMPLEMENTED_IF_MSG(instr.alu.saturate_d, "IADD saturation not implemented"); op_a = GetOperandAbsNegInteger(op_a, false, instr.alu_integer.negate_a, true); op_b = GetOperandAbsNegInteger(op_b, false, instr.alu_integer.negate_b, true); - SetRegister(bb, instr.gpr0, Operation(OperationCode::IAdd, PRECISE, op_a, op_b)); + const Node value = Operation(OperationCode::IAdd, PRECISE, op_a, op_b); + + SetInternalFlagsFromInteger(bb, value, instr.op_32.generates_cc); + SetRegister(bb, instr.gpr0, value); break; } case OpCode::Id::IADD3_C: case OpCode::Id::IADD3_R: case OpCode::Id::IADD3_IMM: { - UNIMPLEMENTED_IF_MSG(instr.generates_cc, - "Condition codes generation in IADD3 is not implemented"); - Node op_c = GetRegister(instr.gpr39); const auto ApplyHeight = [&](IAdd3Height height, Node value) { @@ -100,6 +98,7 @@ u32 ShaderIR::DecodeArithmeticInteger(BasicBlock& bb, u32 pc) { return Operation(OperationCode::IAdd, NO_PRECISE, shifted, op_c); }(); + SetInternalFlagsFromInteger(bb, value, instr.generates_cc); SetRegister(bb, instr.gpr0, value); break; } @@ -115,6 +114,8 @@ u32 ShaderIR::DecodeArithmeticInteger(BasicBlock& bb, u32 pc) { const Node shift = Immediate(static_cast(instr.alu_integer.shift_amount)); const Node shifted_a = Operation(OperationCode::ILogicalShiftLeft, NO_PRECISE, op_a, shift); const Node value = Operation(OperationCode::IAdd, NO_PRECISE, shifted_a, op_b); + + SetInternalFlagsFromInteger(bb, value, instr.generates_cc); SetRegister(bb, instr.gpr0, value); break; } @@ -139,24 +140,19 @@ u32 ShaderIR::DecodeArithmeticInteger(BasicBlock& bb, u32 pc) { case OpCode::Id::LOP_C: case OpCode::Id::LOP_R: case OpCode::Id::LOP_IMM: { - UNIMPLEMENTED_IF_MSG(instr.generates_cc, - "Condition codes generation in LOP is not implemented"); - if (instr.alu.lop.invert_a) op_a = Operation(OperationCode::IBitwiseNot, NO_PRECISE, op_a); if (instr.alu.lop.invert_b) op_b = Operation(OperationCode::IBitwiseNot, NO_PRECISE, op_b); WriteLogicOperation(bb, instr.gpr0, instr.alu.lop.operation, op_a, op_b, - instr.alu.lop.pred_result_mode, instr.alu.lop.pred48); + instr.alu.lop.pred_result_mode, instr.alu.lop.pred48, + instr.generates_cc); break; } case OpCode::Id::LOP3_C: case OpCode::Id::LOP3_R: case OpCode::Id::LOP3_IMM: { - UNIMPLEMENTED_IF_MSG(instr.generates_cc, - "Condition codes generation in LOP3 is not implemented"); - const Node op_c = GetRegister(instr.gpr39); const Node lut = [&]() { if (opcode->get().GetId() == OpCode::Id::LOP3_R) { @@ -166,15 +162,13 @@ u32 ShaderIR::DecodeArithmeticInteger(BasicBlock& bb, u32 pc) { } }(); - WriteLop3Instruction(bb, instr.gpr0, op_a, op_b, op_c, lut); + WriteLop3Instruction(bb, instr.gpr0, op_a, op_b, op_c, lut, instr.generates_cc); break; } case OpCode::Id::IMNMX_C: case OpCode::Id::IMNMX_R: case OpCode::Id::IMNMX_IMM: { UNIMPLEMENTED_IF(instr.imnmx.exchange != Tegra::Shader::IMinMaxExchange::None); - UNIMPLEMENTED_IF_MSG(instr.generates_cc, - "Condition codes generation in IMNMX is not implemented"); const bool is_signed = instr.imnmx.is_signed; @@ -182,6 +176,8 @@ u32 ShaderIR::DecodeArithmeticInteger(BasicBlock& bb, u32 pc) { const Node min = SignedOperation(OperationCode::IMin, is_signed, NO_PRECISE, op_a, op_b); const Node max = SignedOperation(OperationCode::IMax, is_signed, NO_PRECISE, op_a, op_b); const Node value = Operation(OperationCode::Select, NO_PRECISE, condition, min, max); + + SetInternalFlagsFromInteger(bb, value, instr.generates_cc); SetRegister(bb, instr.gpr0, value); break; } @@ -247,7 +243,7 @@ u32 ShaderIR::DecodeArithmeticInteger(BasicBlock& bb, u32 pc) { } void ShaderIR::WriteLop3Instruction(BasicBlock& bb, Register dest, Node op_a, Node op_b, Node op_c, - Node imm_lut) { + Node imm_lut, bool sets_cc) { constexpr u32 lop_iterations = 32; const Node one = Immediate(1); const Node two = Immediate(2); @@ -284,6 +280,7 @@ void ShaderIR::WriteLop3Instruction(BasicBlock& bb, Register dest, Node op_a, No } } + SetInternalFlagsFromInteger(bb, value, sets_cc); SetRegister(bb, dest, value); } -- cgit v1.2.3 From 170c8212bbb10129dfbaed8eb7ab67138c932af2 Mon Sep 17 00:00:00 2001 From: ReinUsesLisp Date: Fri, 28 Dec 2018 20:00:36 -0300 Subject: shader_ir: Pass to decoder functions basic block's code --- src/video_core/shader/decode/arithmetic_integer.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'src/video_core/shader/decode/arithmetic_integer.cpp') diff --git a/src/video_core/shader/decode/arithmetic_integer.cpp b/src/video_core/shader/decode/arithmetic_integer.cpp index edd1695f4..4a8cc1a1c 100644 --- a/src/video_core/shader/decode/arithmetic_integer.cpp +++ b/src/video_core/shader/decode/arithmetic_integer.cpp @@ -15,7 +15,7 @@ using Tegra::Shader::OpCode; using Tegra::Shader::Pred; using Tegra::Shader::Register; -u32 ShaderIR::DecodeArithmeticInteger(BasicBlock& bb, u32 pc) { +u32 ShaderIR::DecodeArithmeticInteger(BasicBlock& bb, const BasicBlock& code, u32 pc) { const Instruction instr = {program_code[pc]}; const auto opcode = OpCode::Decode(instr); -- cgit v1.2.3