From 39f1c6246a3c5140f4c2b9a2ba3cbcaecf9521dd Mon Sep 17 00:00:00 2001 From: ReinUsesLisp Date: Fri, 21 Dec 2018 02:02:15 -0300 Subject: shader_decode: Implement LOP32I --- .../shader/decode/arithmetic_integer_immediate.cpp | 68 +++++++++++++++++++++- 1 file changed, 67 insertions(+), 1 deletion(-) (limited to 'src/video_core/shader/decode/arithmetic_integer_immediate.cpp') diff --git a/src/video_core/shader/decode/arithmetic_integer_immediate.cpp b/src/video_core/shader/decode/arithmetic_integer_immediate.cpp index 46f340235..ee5754161 100644 --- a/src/video_core/shader/decode/arithmetic_integer_immediate.cpp +++ b/src/video_core/shader/decode/arithmetic_integer_immediate.cpp @@ -10,15 +10,81 @@ namespace VideoCommon::Shader { using Tegra::Shader::Instruction; +using Tegra::Shader::LogicOperation; using Tegra::Shader::OpCode; +using Tegra::Shader::Pred; +using Tegra::Shader::PredicateResultMode; +using Tegra::Shader::Register; u32 ShaderIR::DecodeArithmeticIntegerImmediate(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 = Immediate(static_cast(instr.alu.imm20_32)); + + switch (opcode->get().GetId()) { + case OpCode::Id::LOP32I: { + UNIMPLEMENTED_IF_MSG(instr.op_32.generates_cc, + "Condition codes generation in LOP32I is not implemented"); + + if (instr.alu.lop32i.invert_a) + op_a = Operation(OperationCode::IBitwiseNot, NO_PRECISE, op_a); + + if (instr.alu.lop32i.invert_b) + op_b = Operation(OperationCode::IBitwiseNot, NO_PRECISE, op_b); + + WriteLogicOperation(bb, instr.gpr0, instr.alu.lop32i.operation, op_a, op_b, + Tegra::Shader::PredicateResultMode::None, + Tegra::Shader::Pred::UnusedIndex); + break; + } + default: + UNIMPLEMENTED_MSG("Unhandled ArithmeticIntegerImmediate instruction: {}", + opcode->get().GetName()); + } return pc; } +void ShaderIR::WriteLogicOperation(BasicBlock& bb, Register dest, LogicOperation logic_op, + Node op_a, Node op_b, PredicateResultMode predicate_mode, + Pred predicate) { + const Node result = [&]() { + switch (logic_op) { + case LogicOperation::And: + return Operation(OperationCode::IBitwiseAnd, PRECISE, op_a, op_b); + case LogicOperation::Or: + return Operation(OperationCode::IBitwiseOr, PRECISE, op_a, op_b); + case LogicOperation::Xor: + return Operation(OperationCode::IBitwiseXor, PRECISE, op_a, op_b); + case LogicOperation::PassB: + return op_b; + default: + UNIMPLEMENTED_MSG("Unimplemented logic operation={}", static_cast(logic_op)); + } + }(); + + if (dest != Register::ZeroIndex) { + SetRegister(bb, dest, result); + } + + using Tegra::Shader::PredicateResultMode; + // Write the predicate value depending on the predicate mode. + switch (predicate_mode) { + case PredicateResultMode::None: + // Do nothing. + return; + case PredicateResultMode::NotZero: { + // Set the predicate to true if the result is not zero. + const Node compare = Operation(OperationCode::LogicalIEqual, result, Immediate(0)); + SetPredicate(bb, static_cast(predicate), compare); + break; + } + default: + UNIMPLEMENTED_MSG("Unimplemented predicate result mode: {}", + static_cast(predicate_mode)); + } +} + } // namespace VideoCommon::Shader \ No newline at end of file -- cgit v1.2.3