diff options
| author | 2018-12-18 19:54:12 -0300 | |
|---|---|---|
| committer | 2019-01-15 17:54:52 -0300 | |
| commit | 21f9e9da092ddd96fe9f149660a5bf4f676c8413 (patch) | |
| tree | 12228a6205e317165b48074eb12e8d0efc41f38f /src | |
| parent | shader_decode: Implement HADD2 and HMUL2 (diff) | |
| download | yuzu-21f9e9da092ddd96fe9f149660a5bf4f676c8413.tar.gz yuzu-21f9e9da092ddd96fe9f149660a5bf4f676c8413.tar.xz yuzu-21f9e9da092ddd96fe9f149660a5bf4f676c8413.zip | |
shader_decode: Implement HSETP2
Diffstat (limited to 'src')
| -rw-r--r-- | src/video_core/shader/decode/half_set_predicate.cpp | 38 |
1 files changed, 37 insertions, 1 deletions
diff --git a/src/video_core/shader/decode/half_set_predicate.cpp b/src/video_core/shader/decode/half_set_predicate.cpp index 5fe123ea5..d7d63d50a 100644 --- a/src/video_core/shader/decode/half_set_predicate.cpp +++ b/src/video_core/shader/decode/half_set_predicate.cpp | |||
| @@ -11,12 +11,48 @@ namespace VideoCommon::Shader { | |||
| 11 | 11 | ||
| 12 | using Tegra::Shader::Instruction; | 12 | using Tegra::Shader::Instruction; |
| 13 | using Tegra::Shader::OpCode; | 13 | using Tegra::Shader::OpCode; |
| 14 | using Tegra::Shader::Pred; | ||
| 14 | 15 | ||
| 15 | u32 ShaderIR::DecodeHalfSetPredicate(BasicBlock& bb, u32 pc) { | 16 | u32 ShaderIR::DecodeHalfSetPredicate(BasicBlock& bb, u32 pc) { |
| 16 | const Instruction instr = {program_code[pc]}; | 17 | const Instruction instr = {program_code[pc]}; |
| 17 | const auto opcode = OpCode::Decode(instr); | 18 | const auto opcode = OpCode::Decode(instr); |
| 18 | 19 | ||
| 19 | UNIMPLEMENTED(); | 20 | UNIMPLEMENTED_IF(instr.hsetp2.ftz != 0); |
| 21 | |||
| 22 | Node op_a = GetRegister(instr.gpr8); | ||
| 23 | op_a = GetOperandAbsNegHalf(op_a, instr.hsetp2.abs_a, instr.hsetp2.negate_a); | ||
| 24 | |||
| 25 | const Node op_b = [&]() { | ||
| 26 | switch (opcode->get().GetId()) { | ||
| 27 | case OpCode::Id::HSETP2_R: | ||
| 28 | return GetOperandAbsNegHalf(GetRegister(instr.gpr20), instr.hsetp2.abs_a, | ||
| 29 | instr.hsetp2.negate_b); | ||
| 30 | default: | ||
| 31 | UNREACHABLE(); | ||
| 32 | return Immediate(0); | ||
| 33 | } | ||
| 34 | }(); | ||
| 35 | |||
| 36 | // We can't use the constant predicate as destination. | ||
| 37 | ASSERT(instr.hsetp2.pred3 != static_cast<u64>(Pred::UnusedIndex)); | ||
| 38 | |||
| 39 | const Node second_pred = GetPredicate(instr.hsetp2.pred39, instr.hsetp2.neg_pred != 0); | ||
| 40 | |||
| 41 | const OperationCode combiner = GetPredicateCombiner(instr.hsetp2.op); | ||
| 42 | |||
| 43 | MetaHalfArithmetic meta = { | ||
| 44 | false, {instr.hsetp2.type_a, instr.hsetp2.type_b}, instr.hsetp2.h_and != 0}; | ||
| 45 | const Node first_pred = GetPredicateComparisonHalf(instr.hsetp2.cond, meta, op_a, op_b); | ||
| 46 | |||
| 47 | // Set the primary predicate to the result of Predicate OP SecondPredicate | ||
| 48 | const Node value = Operation(combiner, first_pred, second_pred); | ||
| 49 | SetPredicate(bb, instr.hsetp2.pred3, value); | ||
| 50 | |||
| 51 | if (instr.hsetp2.pred0 != static_cast<u64>(Pred::UnusedIndex)) { | ||
| 52 | // Set the secondary predicate to the result of !Predicate OP SecondPredicate, if enabled | ||
| 53 | const Node negated_pred = Operation(OperationCode::LogicalNegate, first_pred); | ||
| 54 | SetPredicate(bb, instr.hsetp2.pred0, Operation(combiner, negated_pred, second_pred)); | ||
| 55 | } | ||
| 20 | 56 | ||
| 21 | return pc; | 57 | return pc; |
| 22 | } | 58 | } |