diff options
author | Fernando Sahmkow <fsahmkow27@gmail.com> | 2019-06-25 11:10:45 -0400 |
---|---|---|
committer | FernandoS27 <fsahmkow27@gmail.com> | 2019-07-09 08:14:38 -0400 |
commit | 926b80102f1c00675a9f3956258a066bfe0c3642 (patch) | |
tree | 616288030c9e72f8cf6a3ee12ae89faa07b9da79 /src/video_core/shader/decode.cpp | |
parent | 459fce3a8f26241ff2a68c323e75fb70e7e1ba79 (diff) |
shader_ir: Decompile Flow Stack
Diffstat (limited to 'src/video_core/shader/decode.cpp')
-rw-r--r-- | src/video_core/shader/decode.cpp | 46 |
1 files changed, 46 insertions, 0 deletions
diff --git a/src/video_core/shader/decode.cpp b/src/video_core/shader/decode.cpp index 09f55bd214..1a74b70cb4 100644 --- a/src/video_core/shader/decode.cpp +++ b/src/video_core/shader/decode.cpp @@ -44,6 +44,17 @@ void ShaderIR::Decode() { coverage_begin = shader_info.start; coverage_end = shader_info.end; if (shader_info.decompilable) { + std::list<ShaderBlock>& blocks = shader_info.blocks; + for (auto& block : blocks) { + NodeBlock nodes; + if (!block.ignore_branch) { + nodes = DecodeRange(block.start, block.end); + InsertControlFlow(nodes, block); + } else { + nodes = DecodeRange(block.start, block.end + 1); + } + basic_blocks.insert({block.start, nodes}); + } return; } // we can't decompile it, fallback to standard method @@ -73,6 +84,41 @@ NodeBlock ShaderIR::DecodeRange(u32 begin, u32 end) { return basic_block; } +void ShaderIR::InsertControlFlow(NodeBlock& bb, const ShaderBlock& block) { + auto apply_conditions = ([&](const Condition& cond, Node n) -> Node { + Node result = n; + if (cond.cc != ConditionCode::T) { + result = Conditional(GetConditionCode(cond.cc), {result}); + } + if (cond.predicate != Pred::UnusedIndex) { + u32 pred = static_cast<u32>(cond.predicate); + bool is_neg = pred > 7; + if (is_neg) + pred -= 8; + result = Conditional(GetPredicate(pred, is_neg), {result}); + } + return result; + }); + if (block.branch.address < 0) { + if (block.branch.kills) { + Node n = Operation(OperationCode::Discard); + n = apply_conditions(block.branch.cond, n); + bb.push_back(n); + global_code.push_back(n); + return; + } + Node n = Operation(OperationCode::Exit); + n = apply_conditions(block.branch.cond, n); + bb.push_back(n); + global_code.push_back(n); + return; + } + Node n = Operation(OperationCode::Branch, Immediate(block.branch.address)); + n = apply_conditions(block.branch.cond, n); + bb.push_back(n); + global_code.push_back(n); +} + u32 ShaderIR::DecodeInstr(NodeBlock& bb, u32 pc) { // Ignore sched instructions when generating code. if (IsSchedInstruction(pc, main_offset)) { |