diff options
| author | 2019-06-24 21:25:38 -0400 | |
|---|---|---|
| committer | 2019-07-09 08:14:37 -0400 | |
| commit | 8a6fc529a968e007f01464abadd32f9b5eb0a26c (patch) | |
| tree | 189d2d4189d9e87d933eddab5260b472e6838588 /src/video_core/shader | |
| parent | shader_ir: Remove the old scanner. (diff) | |
| download | yuzu-8a6fc529a968e007f01464abadd32f9b5eb0a26c.tar.gz yuzu-8a6fc529a968e007f01464abadd32f9b5eb0a26c.tar.xz yuzu-8a6fc529a968e007f01464abadd32f9b5eb0a26c.zip | |
shader_ir: Implement BRX & BRA.CC
Diffstat (limited to 'src/video_core/shader')
| -rw-r--r-- | src/video_core/shader/control_flow.cpp | 3 | ||||
| -rw-r--r-- | src/video_core/shader/decode/other.cpp | 42 | ||||
| -rw-r--r-- | src/video_core/shader/node.h | 1 |
3 files changed, 42 insertions, 4 deletions
diff --git a/src/video_core/shader/control_flow.cpp b/src/video_core/shader/control_flow.cpp index fcf22c7f2..a9de8f814 100644 --- a/src/video_core/shader/control_flow.cpp +++ b/src/video_core/shader/control_flow.cpp | |||
| @@ -284,6 +284,9 @@ ParseResult ParseCode(CFGRebuildState& state, u32 address, ParseInfo& parse_info | |||
| 284 | state.pbk_labels.emplace(offset, target); | 284 | state.pbk_labels.emplace(offset, target); |
| 285 | break; | 285 | break; |
| 286 | } | 286 | } |
| 287 | case OpCode::Id::BRX: { | ||
| 288 | return ParseResult::AbnormalFlow; | ||
| 289 | } | ||
| 287 | default: | 290 | default: |
| 288 | break; | 291 | break; |
| 289 | } | 292 | } |
diff --git a/src/video_core/shader/decode/other.cpp b/src/video_core/shader/decode/other.cpp index d46a8ab82..ed3c63781 100644 --- a/src/video_core/shader/decode/other.cpp +++ b/src/video_core/shader/decode/other.cpp | |||
| @@ -91,11 +91,45 @@ u32 ShaderIR::DecodeOther(NodeBlock& bb, u32 pc) { | |||
| 91 | break; | 91 | break; |
| 92 | } | 92 | } |
| 93 | case OpCode::Id::BRA: { | 93 | case OpCode::Id::BRA: { |
| 94 | UNIMPLEMENTED_IF_MSG(instr.bra.constant_buffer != 0, | 94 | Node branch; |
| 95 | "BRA with constant buffers are not implemented"); | 95 | if (instr.bra.constant_buffer == 0) { |
| 96 | const u32 target = pc + instr.bra.GetBranchTarget(); | ||
| 97 | branch = Operation(OperationCode::Branch, Immediate(target)); | ||
| 98 | } else { | ||
| 99 | const u32 target = pc + 1; | ||
| 100 | const Node op_a = GetConstBuffer(instr.cbuf36.index, instr.cbuf36.GetOffset()); | ||
| 101 | const Node convert = SignedOperation(OperationCode::IArithmeticShiftRight, | ||
| 102 | true, PRECISE, op_a, Immediate(3)); | ||
| 103 | const Node operand = Operation(OperationCode::IAdd, PRECISE, convert, Immediate(target)); | ||
| 104 | branch = Operation(OperationCode::BranchIndirect, convert); | ||
| 105 | } | ||
| 96 | 106 | ||
| 97 | const u32 target = pc + instr.bra.GetBranchTarget(); | 107 | const Tegra::Shader::ConditionCode cc = instr.flow_condition_code; |
| 98 | const Node branch = Operation(OperationCode::Branch, Immediate(target)); | 108 | if (cc != Tegra::Shader::ConditionCode::T) { |
| 109 | bb.push_back(Conditional(GetConditionCode(cc), {branch})); | ||
| 110 | } else { | ||
| 111 | bb.push_back(branch); | ||
| 112 | } | ||
| 113 | break; | ||
| 114 | } | ||
| 115 | case OpCode::Id::BRX: { | ||
| 116 | Node operand; | ||
| 117 | if (instr.brx.constant_buffer != 0) { | ||
| 118 | const s32 target = pc + 1; | ||
| 119 | const Node index = GetRegister(instr.gpr8); | ||
| 120 | const Node op_a = | ||
| 121 | GetConstBufferIndirect(instr.cbuf36.index, instr.cbuf36.GetOffset() + 0, index); | ||
| 122 | const Node convert = SignedOperation(OperationCode::IArithmeticShiftRight, | ||
| 123 | true, PRECISE, op_a, Immediate(3)); | ||
| 124 | operand = Operation(OperationCode::IAdd, PRECISE, convert, Immediate(target)); | ||
| 125 | } else { | ||
| 126 | const s32 target = pc + instr.brx.GetBranchExtend(); | ||
| 127 | const Node op_a = GetRegister(instr.gpr8); | ||
| 128 | const Node convert = SignedOperation(OperationCode::IArithmeticShiftRight, | ||
| 129 | true, PRECISE, op_a, Immediate(3)); | ||
| 130 | operand = Operation(OperationCode::IAdd, PRECISE, convert, Immediate(target)); | ||
| 131 | } | ||
| 132 | const Node branch = Operation(OperationCode::BranchIndirect, operand); | ||
| 99 | 133 | ||
| 100 | const Tegra::Shader::ConditionCode cc = instr.flow_condition_code; | 134 | const Tegra::Shader::ConditionCode cc = instr.flow_condition_code; |
| 101 | if (cc != Tegra::Shader::ConditionCode::T) { | 135 | if (cc != Tegra::Shader::ConditionCode::T) { |
diff --git a/src/video_core/shader/node.h b/src/video_core/shader/node.h index 0ac83fcf0..e468758a6 100644 --- a/src/video_core/shader/node.h +++ b/src/video_core/shader/node.h | |||
| @@ -149,6 +149,7 @@ enum class OperationCode { | |||
| 149 | ImageStore, /// (MetaImage, float[N] coords) -> void | 149 | ImageStore, /// (MetaImage, float[N] coords) -> void |
| 150 | 150 | ||
| 151 | Branch, /// (uint branch_target) -> void | 151 | Branch, /// (uint branch_target) -> void |
| 152 | BranchIndirect,/// (uint branch_target) -> void | ||
| 152 | PushFlowStack, /// (uint branch_target) -> void | 153 | PushFlowStack, /// (uint branch_target) -> void |
| 153 | PopFlowStack, /// () -> void | 154 | PopFlowStack, /// () -> void |
| 154 | Exit, /// () -> void | 155 | Exit, /// () -> void |