diff options
author | ReinUsesLisp <reinuseslisp@airmail.cc> | 2018-12-21 06:02:15 +0100 |
---|---|---|
committer | ReinUsesLisp <reinuseslisp@airmail.cc> | 2019-01-15 21:54:51 +0100 |
commit | 39f1c6246a3c5140f4c2b9a2ba3cbcaecf9521dd (patch) | |
tree | a619359c0feefa8d035a754f03194b5adcf9cb25 | |
parent | shader_decode: Implement BFE (diff) | |
download | yuzu-39f1c6246a3c5140f4c2b9a2ba3cbcaecf9521dd.tar yuzu-39f1c6246a3c5140f4c2b9a2ba3cbcaecf9521dd.tar.gz yuzu-39f1c6246a3c5140f4c2b9a2ba3cbcaecf9521dd.tar.bz2 yuzu-39f1c6246a3c5140f4c2b9a2ba3cbcaecf9521dd.tar.lz yuzu-39f1c6246a3c5140f4c2b9a2ba3cbcaecf9521dd.tar.xz yuzu-39f1c6246a3c5140f4c2b9a2ba3cbcaecf9521dd.tar.zst yuzu-39f1c6246a3c5140f4c2b9a2ba3cbcaecf9521dd.zip |
-rw-r--r-- | src/video_core/shader/decode/arithmetic_integer_immediate.cpp | 68 | ||||
-rw-r--r-- | src/video_core/shader/shader_ir.h | 5 |
2 files changed, 72 insertions, 1 deletions
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<s32>(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<u32>(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<u64>(predicate), compare); + break; + } + default: + UNIMPLEMENTED_MSG("Unimplemented predicate result mode: {}", + static_cast<u32>(predicate_mode)); + } +} + } // namespace VideoCommon::Shader
\ No newline at end of file diff --git a/src/video_core/shader/shader_ir.h b/src/video_core/shader/shader_ir.h index 23a4de2a7..b67fd6531 100644 --- a/src/video_core/shader/shader_ir.h +++ b/src/video_core/shader/shader_ir.h @@ -697,6 +697,11 @@ private: Tegra::Shader::TextureProcessMode process_mode, bool depth_compare, bool is_array, std::size_t bias_offset, std::vector<Node>&& coords); + void WriteLogicOperation(BasicBlock& bb, Tegra::Shader::Register dest, + Tegra::Shader::LogicOperation logic_op, Node op_a, Node op_b, + Tegra::Shader::PredicateResultMode predicate_mode, + Tegra::Shader::Pred predicate); + template <typename... T> inline Node Operation(OperationCode code, const T*... operands) { return StoreNode(OperationNode(code, operands...)); |