diff options
| author | 2018-12-21 02:02:15 -0300 | |
|---|---|---|
| committer | 2019-01-15 17:54:51 -0300 | |
| commit | 39f1c6246a3c5140f4c2b9a2ba3cbcaecf9521dd (patch) | |
| tree | a619359c0feefa8d035a754f03194b5adcf9cb25 /src | |
| parent | shader_decode: Implement BFE (diff) | |
| download | yuzu-39f1c6246a3c5140f4c2b9a2ba3cbcaecf9521dd.tar.gz yuzu-39f1c6246a3c5140f4c2b9a2ba3cbcaecf9521dd.tar.xz yuzu-39f1c6246a3c5140f4c2b9a2ba3cbcaecf9521dd.zip | |
shader_decode: Implement LOP32I
Diffstat (limited to 'src')
| -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 @@ | |||
| 10 | namespace VideoCommon::Shader { | 10 | namespace VideoCommon::Shader { |
| 11 | 11 | ||
| 12 | using Tegra::Shader::Instruction; | 12 | using Tegra::Shader::Instruction; |
| 13 | using Tegra::Shader::LogicOperation; | ||
| 13 | using Tegra::Shader::OpCode; | 14 | using Tegra::Shader::OpCode; |
| 15 | using Tegra::Shader::Pred; | ||
| 16 | using Tegra::Shader::PredicateResultMode; | ||
| 17 | using Tegra::Shader::Register; | ||
| 14 | 18 | ||
| 15 | u32 ShaderIR::DecodeArithmeticIntegerImmediate(BasicBlock& bb, u32 pc) { | 19 | u32 ShaderIR::DecodeArithmeticIntegerImmediate(BasicBlock& bb, u32 pc) { |
| 16 | const Instruction instr = {program_code[pc]}; | 20 | const Instruction instr = {program_code[pc]}; |
| 17 | const auto opcode = OpCode::Decode(instr); | 21 | const auto opcode = OpCode::Decode(instr); |
| 18 | 22 | ||
| 19 | UNIMPLEMENTED(); | 23 | Node op_a = GetRegister(instr.gpr8); |
| 24 | Node op_b = Immediate(static_cast<s32>(instr.alu.imm20_32)); | ||
| 25 | |||
| 26 | switch (opcode->get().GetId()) { | ||
| 27 | case OpCode::Id::LOP32I: { | ||
| 28 | UNIMPLEMENTED_IF_MSG(instr.op_32.generates_cc, | ||
| 29 | "Condition codes generation in LOP32I is not implemented"); | ||
| 30 | |||
| 31 | if (instr.alu.lop32i.invert_a) | ||
| 32 | op_a = Operation(OperationCode::IBitwiseNot, NO_PRECISE, op_a); | ||
| 33 | |||
| 34 | if (instr.alu.lop32i.invert_b) | ||
| 35 | op_b = Operation(OperationCode::IBitwiseNot, NO_PRECISE, op_b); | ||
| 36 | |||
| 37 | WriteLogicOperation(bb, instr.gpr0, instr.alu.lop32i.operation, op_a, op_b, | ||
| 38 | Tegra::Shader::PredicateResultMode::None, | ||
| 39 | Tegra::Shader::Pred::UnusedIndex); | ||
| 40 | break; | ||
| 41 | } | ||
| 42 | default: | ||
| 43 | UNIMPLEMENTED_MSG("Unhandled ArithmeticIntegerImmediate instruction: {}", | ||
| 44 | opcode->get().GetName()); | ||
| 45 | } | ||
| 20 | 46 | ||
| 21 | return pc; | 47 | return pc; |
| 22 | } | 48 | } |
| 23 | 49 | ||
| 50 | void ShaderIR::WriteLogicOperation(BasicBlock& bb, Register dest, LogicOperation logic_op, | ||
| 51 | Node op_a, Node op_b, PredicateResultMode predicate_mode, | ||
| 52 | Pred predicate) { | ||
| 53 | const Node result = [&]() { | ||
| 54 | switch (logic_op) { | ||
| 55 | case LogicOperation::And: | ||
| 56 | return Operation(OperationCode::IBitwiseAnd, PRECISE, op_a, op_b); | ||
| 57 | case LogicOperation::Or: | ||
| 58 | return Operation(OperationCode::IBitwiseOr, PRECISE, op_a, op_b); | ||
| 59 | case LogicOperation::Xor: | ||
| 60 | return Operation(OperationCode::IBitwiseXor, PRECISE, op_a, op_b); | ||
| 61 | case LogicOperation::PassB: | ||
| 62 | return op_b; | ||
| 63 | default: | ||
| 64 | UNIMPLEMENTED_MSG("Unimplemented logic operation={}", static_cast<u32>(logic_op)); | ||
| 65 | } | ||
| 66 | }(); | ||
| 67 | |||
| 68 | if (dest != Register::ZeroIndex) { | ||
| 69 | SetRegister(bb, dest, result); | ||
| 70 | } | ||
| 71 | |||
| 72 | using Tegra::Shader::PredicateResultMode; | ||
| 73 | // Write the predicate value depending on the predicate mode. | ||
| 74 | switch (predicate_mode) { | ||
| 75 | case PredicateResultMode::None: | ||
| 76 | // Do nothing. | ||
| 77 | return; | ||
| 78 | case PredicateResultMode::NotZero: { | ||
| 79 | // Set the predicate to true if the result is not zero. | ||
| 80 | const Node compare = Operation(OperationCode::LogicalIEqual, result, Immediate(0)); | ||
| 81 | SetPredicate(bb, static_cast<u64>(predicate), compare); | ||
| 82 | break; | ||
| 83 | } | ||
| 84 | default: | ||
| 85 | UNIMPLEMENTED_MSG("Unimplemented predicate result mode: {}", | ||
| 86 | static_cast<u32>(predicate_mode)); | ||
| 87 | } | ||
| 88 | } | ||
| 89 | |||
| 24 | } // namespace VideoCommon::Shader \ No newline at end of file | 90 | } // 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: | |||
| 697 | Tegra::Shader::TextureProcessMode process_mode, bool depth_compare, | 697 | Tegra::Shader::TextureProcessMode process_mode, bool depth_compare, |
| 698 | bool is_array, std::size_t bias_offset, std::vector<Node>&& coords); | 698 | bool is_array, std::size_t bias_offset, std::vector<Node>&& coords); |
| 699 | 699 | ||
| 700 | void WriteLogicOperation(BasicBlock& bb, Tegra::Shader::Register dest, | ||
| 701 | Tegra::Shader::LogicOperation logic_op, Node op_a, Node op_b, | ||
| 702 | Tegra::Shader::PredicateResultMode predicate_mode, | ||
| 703 | Tegra::Shader::Pred predicate); | ||
| 704 | |||
| 700 | template <typename... T> | 705 | template <typename... T> |
| 701 | inline Node Operation(OperationCode code, const T*... operands) { | 706 | inline Node Operation(OperationCode code, const T*... operands) { |
| 702 | return StoreNode(OperationNode(code, operands...)); | 707 | return StoreNode(OperationNode(code, operands...)); |