diff options
| author | 2021-01-09 03:30:07 -0300 | |
|---|---|---|
| committer | 2021-07-22 21:51:21 -0400 | |
| commit | 2d48a7b4d0666ad16d03a22d85712617a0849046 (patch) | |
| tree | dd1069afca86f66e77e3438da77421a43adf5091 /src/shader_recompiler/frontend/maxwell/termination_code.cpp | |
| parent | thread_worker: Fix compile time error (diff) | |
| download | yuzu-2d48a7b4d0666ad16d03a22d85712617a0849046.tar.gz yuzu-2d48a7b4d0666ad16d03a22d85712617a0849046.tar.xz yuzu-2d48a7b4d0666ad16d03a22d85712617a0849046.zip | |
shader: Initial recompiler work
Diffstat (limited to 'src/shader_recompiler/frontend/maxwell/termination_code.cpp')
| -rw-r--r-- | src/shader_recompiler/frontend/maxwell/termination_code.cpp | 79 |
1 files changed, 79 insertions, 0 deletions
diff --git a/src/shader_recompiler/frontend/maxwell/termination_code.cpp b/src/shader_recompiler/frontend/maxwell/termination_code.cpp new file mode 100644 index 000000000..a4ea5c5e3 --- /dev/null +++ b/src/shader_recompiler/frontend/maxwell/termination_code.cpp | |||
| @@ -0,0 +1,79 @@ | |||
| 1 | // Copyright 2021 yuzu Emulator Project | ||
| 2 | // Licensed under GPLv2 or any later version | ||
| 3 | // Refer to the license.txt file included. | ||
| 4 | |||
| 5 | #include <span> | ||
| 6 | |||
| 7 | #include "shader_recompiler/exception.h" | ||
| 8 | #include "shader_recompiler/frontend/ir/basic_block.h" | ||
| 9 | #include "shader_recompiler/frontend/ir/ir_emitter.h" | ||
| 10 | #include "shader_recompiler/frontend/maxwell/control_flow.h" | ||
| 11 | #include "shader_recompiler/frontend/maxwell/termination_code.h" | ||
| 12 | |||
| 13 | namespace Shader::Maxwell { | ||
| 14 | |||
| 15 | static void EmitExit(IR::IREmitter& ir) { | ||
| 16 | ir.Exit(); | ||
| 17 | } | ||
| 18 | |||
| 19 | static IR::U1 GetFlowTest(IR::FlowTest flow_test, IR::IREmitter& ir) { | ||
| 20 | switch (flow_test) { | ||
| 21 | case IR::FlowTest::T: | ||
| 22 | return ir.Imm1(true); | ||
| 23 | case IR::FlowTest::F: | ||
| 24 | return ir.Imm1(false); | ||
| 25 | case IR::FlowTest::NE: | ||
| 26 | // FIXME: Verify this | ||
| 27 | return ir.LogicalNot(ir.GetZFlag()); | ||
| 28 | case IR::FlowTest::NaN: | ||
| 29 | // FIXME: Verify this | ||
| 30 | return ir.LogicalAnd(ir.GetSFlag(), ir.GetZFlag()); | ||
| 31 | default: | ||
| 32 | throw NotImplementedException("Flow test {}", flow_test); | ||
| 33 | } | ||
| 34 | } | ||
| 35 | |||
| 36 | static IR::U1 GetCond(IR::Condition cond, IR::IREmitter& ir) { | ||
| 37 | const IR::FlowTest flow_test{cond.FlowTest()}; | ||
| 38 | const auto [pred, pred_negated]{cond.Pred()}; | ||
| 39 | if (pred == IR::Pred::PT && !pred_negated) { | ||
| 40 | return GetFlowTest(flow_test, ir); | ||
| 41 | } | ||
| 42 | if (flow_test == IR::FlowTest::T) { | ||
| 43 | return ir.GetPred(pred, pred_negated); | ||
| 44 | } | ||
| 45 | return ir.LogicalAnd(ir.GetPred(pred, pred_negated), GetFlowTest(flow_test, ir)); | ||
| 46 | } | ||
| 47 | |||
| 48 | static void EmitBranch(const Flow::Block& flow_block, std::span<IR::Block* const> block_map, | ||
| 49 | IR::IREmitter& ir) { | ||
| 50 | if (flow_block.cond == true) { | ||
| 51 | return ir.Branch(block_map[flow_block.branch_true]); | ||
| 52 | } | ||
| 53 | if (flow_block.cond == false) { | ||
| 54 | return ir.Branch(block_map[flow_block.branch_false]); | ||
| 55 | } | ||
| 56 | return ir.BranchConditional(GetCond(flow_block.cond, ir), block_map[flow_block.branch_true], | ||
| 57 | block_map[flow_block.branch_false]); | ||
| 58 | } | ||
| 59 | |||
| 60 | void EmitTerminationCode(const Flow::Block& flow_block, std::span<IR::Block* const> block_map) { | ||
| 61 | IR::Block* const block{block_map[flow_block.id]}; | ||
| 62 | IR::IREmitter ir(*block); | ||
| 63 | switch (flow_block.end_class) { | ||
| 64 | case Flow::EndClass::Branch: | ||
| 65 | EmitBranch(flow_block, block_map, ir); | ||
| 66 | break; | ||
| 67 | case Flow::EndClass::Exit: | ||
| 68 | EmitExit(ir); | ||
| 69 | break; | ||
| 70 | case Flow::EndClass::Return: | ||
| 71 | ir.Return(); | ||
| 72 | break; | ||
| 73 | case Flow::EndClass::Unreachable: | ||
| 74 | ir.Unreachable(); | ||
| 75 | break; | ||
| 76 | } | ||
| 77 | } | ||
| 78 | |||
| 79 | } // namespace Shader::Maxwell | ||