summaryrefslogtreecommitdiff
path: root/src/video_core/shader/decode
diff options
context:
space:
mode:
Diffstat (limited to 'src/video_core/shader/decode')
-rw-r--r--src/video_core/shader/decode/other.cpp42
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) {