diff options
| author | 2018-12-16 03:57:10 -0300 | |
|---|---|---|
| committer | 2019-01-15 17:54:51 -0300 | |
| commit | e444a6553faa019b20a81a3b7380ecccfd7d3725 (patch) | |
| tree | cd1b46717b88a2f3de9565e150cac715ab0b49fd /src | |
| parent | shader_decode: Implement F2I (diff) | |
| download | yuzu-e444a6553faa019b20a81a3b7380ecccfd7d3725.tar.gz yuzu-e444a6553faa019b20a81a3b7380ecccfd7d3725.tar.xz yuzu-e444a6553faa019b20a81a3b7380ecccfd7d3725.zip | |
shader_decode: Implement FSET
Diffstat (limited to 'src')
| -rw-r--r-- | src/video_core/shader/decode/float_set.cpp | 37 |
1 files changed, 36 insertions, 1 deletions
diff --git a/src/video_core/shader/decode/float_set.cpp b/src/video_core/shader/decode/float_set.cpp index 17d47c17a..355fabc09 100644 --- a/src/video_core/shader/decode/float_set.cpp +++ b/src/video_core/shader/decode/float_set.cpp | |||
| @@ -16,7 +16,42 @@ u32 ShaderIR::DecodeFloatSet(BasicBlock& bb, u32 pc) { | |||
| 16 | const Instruction instr = {program_code[pc]}; | 16 | const Instruction instr = {program_code[pc]}; |
| 17 | const auto opcode = OpCode::Decode(instr); | 17 | const auto opcode = OpCode::Decode(instr); |
| 18 | 18 | ||
| 19 | UNIMPLEMENTED(); | 19 | const Node op_a = GetOperandAbsNegFloat(GetRegister(instr.gpr8), instr.fset.abs_a != 0, |
| 20 | instr.fset.neg_a != 0); | ||
| 21 | |||
| 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 | |||
| 32 | op_b = GetOperandAbsNegFloat(op_b, instr.fset.abs_b != 0, instr.fset.neg_b != 0); | ||
| 33 | |||
| 34 | // The fset instruction sets a register to 1.0 or -1 (depending on the bf bit) if the | ||
| 35 | // condition is true, and to 0 otherwise. | ||
| 36 | const Node second_pred = GetPredicate(instr.fset.pred39, instr.fset.neg_pred != 0); | ||
| 37 | |||
| 38 | const OperationCode combiner = GetPredicateCombiner(instr.fset.op); | ||
| 39 | const Node first_pred = GetPredicateComparisonFloat(instr.fset.cond, op_a, op_b); | ||
| 40 | |||
| 41 | const Node predicate = Operation(combiner, first_pred, second_pred); | ||
| 42 | |||
| 43 | const Node true_value = instr.fset.bf ? Immediate(1.0f) : Immediate(-1); | ||
| 44 | const Node false_value = instr.fset.bf ? Immediate(0.0f) : Immediate(0); | ||
| 45 | const Node value = | ||
| 46 | Operation(OperationCode::Select, PRECISE, predicate, true_value, false_value); | ||
| 47 | |||
| 48 | SetRegister(bb, instr.gpr0, value); | ||
| 49 | |||
| 50 | if (instr.generates_cc.Value() != 0) { | ||
| 51 | const Node is_zero = Operation(OperationCode::LogicalFEqual, predicate, Immediate(0.0f)); | ||
| 52 | SetInternalFlag(bb, InternalFlag::Zero, is_zero); | ||
| 53 | LOG_WARNING(HW_GPU, "FSET condition code is incomplete"); | ||
| 54 | } | ||
| 20 | 55 | ||
| 21 | return pc; | 56 | return pc; |
| 22 | } | 57 | } |