diff options
| author | 2018-12-21 00:12:48 -0300 | |
|---|---|---|
| committer | 2019-01-15 17:54:50 -0300 | |
| commit | c703f0aee41ba08219f10217169813ac97da06c2 (patch) | |
| tree | baf010a6068b0ab2f1dc571f2cb069b6fd9bd0e5 /src | |
| parent | shader_decode: Partially implement BRA (diff) | |
| download | yuzu-c703f0aee41ba08219f10217169813ac97da06c2.tar.gz yuzu-c703f0aee41ba08219f10217169813ac97da06c2.tar.xz yuzu-c703f0aee41ba08219f10217169813ac97da06c2.zip | |
shader_decode: Implement FSETP
Diffstat (limited to 'src')
| -rw-r--r-- | src/video_core/shader/decode/float_set_predicate.cpp | 34 |
1 files changed, 33 insertions, 1 deletions
diff --git a/src/video_core/shader/decode/float_set_predicate.cpp b/src/video_core/shader/decode/float_set_predicate.cpp index 1dbe34353..5dd085fea 100644 --- a/src/video_core/shader/decode/float_set_predicate.cpp +++ b/src/video_core/shader/decode/float_set_predicate.cpp | |||
| @@ -11,12 +11,44 @@ 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::DecodeFloatSetPredicate(BasicBlock& bb, u32 pc) { | 16 | u32 ShaderIR::DecodeFloatSetPredicate(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 | const Node op_a = GetOperandAbsNegFloat(GetRegister(instr.gpr8), instr.fsetp.abs_a != 0, |
| 21 | instr.fsetp.neg_a != 0); | ||
| 22 | Node op_b = [&]() { | ||
| 23 | if (instr.is_b_imm) { | ||
| 24 | return GetImmediate19(instr); | ||
| 25 | } else if (instr.is_b_gpr) { | ||
| 26 | return GetRegister(instr.gpr20); | ||
| 27 | } else { | ||
| 28 | return GetConstBuffer(instr.cbuf34.index, instr.cbuf34.offset); | ||
| 29 | } | ||
| 30 | }(); | ||
| 31 | op_b = GetOperandAbsNegFloat(op_b, instr.fsetp.abs_b, false); | ||
| 32 | |||
| 33 | // We can't use the constant predicate as destination. | ||
| 34 | ASSERT(instr.fsetp.pred3 != static_cast<u64>(Pred::UnusedIndex)); | ||
| 35 | |||
| 36 | const Node predicate = GetPredicateComparisonFloat(instr.fsetp.cond, op_a, op_b); | ||
| 37 | const Node second_pred = GetPredicate(instr.fsetp.pred39, instr.fsetp.neg_pred != 0); | ||
| 38 | |||
| 39 | const OperationCode combiner = GetPredicateCombiner(instr.fsetp.op); | ||
| 40 | const Node value = Operation(combiner, predicate, second_pred); | ||
| 41 | |||
| 42 | // Set the primary predicate to the result of Predicate OP SecondPredicate | ||
| 43 | SetPredicate(bb, instr.fsetp.pred3, value); | ||
| 44 | |||
| 45 | if (instr.fsetp.pred0 != static_cast<u64>(Pred::UnusedIndex)) { | ||
| 46 | // Set the secondary predicate to the result of !Predicate OP SecondPredicate, | ||
| 47 | // if enabled | ||
| 48 | const Node negated_pred = Operation(OperationCode::LogicalNegate, predicate); | ||
| 49 | const Node second_value = Operation(combiner, negated_pred, second_pred); | ||
| 50 | SetPredicate(bb, instr.fsetp.pred0, second_value); | ||
| 51 | } | ||
| 20 | 52 | ||
| 21 | return pc; | 53 | return pc; |
| 22 | } | 54 | } |