diff options
Diffstat (limited to 'src/video_core/shader/decode')
| -rw-r--r-- | src/video_core/shader/decode/other.cpp | 42 |
1 files changed, 38 insertions, 4 deletions
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) { |