diff options
| author | 2019-07-11 17:36:23 -0400 | |
|---|---|---|
| committer | 2019-07-11 17:36:23 -0400 | |
| commit | bb67091c774611ce2be1aa461438be3989601e59 (patch) | |
| tree | 58e29bd5d7114019a48a62ffadb8076d73627bee /src/video_core/shader/decode | |
| parent | Merge pull request #2717 from SciresM/unmirror_memory (diff) | |
| parent | shader_ir: Add comments on missing instruction. (diff) | |
| download | yuzu-bb67091c774611ce2be1aa461438be3989601e59.tar.gz yuzu-bb67091c774611ce2be1aa461438be3989601e59.tar.xz yuzu-bb67091c774611ce2be1aa461438be3989601e59.zip | |
Merge pull request #2609 from FernandoS27/new-scan
Implement a New Shader Scanner, Decompile Flow Stack and implement BRX BRA.CC
Diffstat (limited to 'src/video_core/shader/decode')
| -rw-r--r-- | src/video_core/shader/decode/other.cpp | 58 |
1 files changed, 54 insertions, 4 deletions
diff --git a/src/video_core/shader/decode/other.cpp b/src/video_core/shader/decode/other.cpp index d46a8ab82..42e3de02f 100644 --- a/src/video_core/shader/decode/other.cpp +++ b/src/video_core/shader/decode/other.cpp | |||
| @@ -91,11 +91,46 @@ 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, true, | ||
| 102 | PRECISE, op_a, Immediate(3)); | ||
| 103 | const Node operand = | ||
| 104 | Operation(OperationCode::IAdd, PRECISE, convert, Immediate(target)); | ||
| 105 | branch = Operation(OperationCode::BranchIndirect, convert); | ||
| 106 | } | ||
| 96 | 107 | ||
| 97 | const u32 target = pc + instr.bra.GetBranchTarget(); | 108 | const Tegra::Shader::ConditionCode cc = instr.flow_condition_code; |
| 98 | const Node branch = Operation(OperationCode::Branch, Immediate(target)); | 109 | if (cc != Tegra::Shader::ConditionCode::T) { |
| 110 | bb.push_back(Conditional(GetConditionCode(cc), {branch})); | ||
| 111 | } else { | ||
| 112 | bb.push_back(branch); | ||
| 113 | } | ||
| 114 | break; | ||
| 115 | } | ||
| 116 | case OpCode::Id::BRX: { | ||
| 117 | Node operand; | ||
| 118 | if (instr.brx.constant_buffer != 0) { | ||
| 119 | const s32 target = pc + 1; | ||
| 120 | const Node index = GetRegister(instr.gpr8); | ||
| 121 | const Node op_a = | ||
| 122 | GetConstBufferIndirect(instr.cbuf36.index, instr.cbuf36.GetOffset() + 0, index); | ||
| 123 | const Node convert = SignedOperation(OperationCode::IArithmeticShiftRight, true, | ||
| 124 | PRECISE, op_a, Immediate(3)); | ||
| 125 | operand = Operation(OperationCode::IAdd, PRECISE, convert, Immediate(target)); | ||
| 126 | } else { | ||
| 127 | const s32 target = pc + instr.brx.GetBranchExtend(); | ||
| 128 | const Node op_a = GetRegister(instr.gpr8); | ||
| 129 | const Node convert = SignedOperation(OperationCode::IArithmeticShiftRight, true, | ||
| 130 | PRECISE, op_a, Immediate(3)); | ||
| 131 | operand = Operation(OperationCode::IAdd, PRECISE, convert, Immediate(target)); | ||
| 132 | } | ||
| 133 | const Node branch = Operation(OperationCode::BranchIndirect, operand); | ||
| 99 | 134 | ||
| 100 | const Tegra::Shader::ConditionCode cc = instr.flow_condition_code; | 135 | const Tegra::Shader::ConditionCode cc = instr.flow_condition_code; |
| 101 | if (cc != Tegra::Shader::ConditionCode::T) { | 136 | if (cc != Tegra::Shader::ConditionCode::T) { |
| @@ -109,6 +144,10 @@ u32 ShaderIR::DecodeOther(NodeBlock& bb, u32 pc) { | |||
| 109 | UNIMPLEMENTED_IF_MSG(instr.bra.constant_buffer != 0, | 144 | UNIMPLEMENTED_IF_MSG(instr.bra.constant_buffer != 0, |
| 110 | "Constant buffer flow is not supported"); | 145 | "Constant buffer flow is not supported"); |
| 111 | 146 | ||
| 147 | if (disable_flow_stack) { | ||
| 148 | break; | ||
| 149 | } | ||
| 150 | |||
| 112 | // The SSY opcode tells the GPU where to re-converge divergent execution paths with SYNC. | 151 | // The SSY opcode tells the GPU where to re-converge divergent execution paths with SYNC. |
| 113 | const u32 target = pc + instr.bra.GetBranchTarget(); | 152 | const u32 target = pc + instr.bra.GetBranchTarget(); |
| 114 | bb.push_back( | 153 | bb.push_back( |
| @@ -119,6 +158,10 @@ u32 ShaderIR::DecodeOther(NodeBlock& bb, u32 pc) { | |||
| 119 | UNIMPLEMENTED_IF_MSG(instr.bra.constant_buffer != 0, | 158 | UNIMPLEMENTED_IF_MSG(instr.bra.constant_buffer != 0, |
| 120 | "Constant buffer PBK is not supported"); | 159 | "Constant buffer PBK is not supported"); |
| 121 | 160 | ||
| 161 | if (disable_flow_stack) { | ||
| 162 | break; | ||
| 163 | } | ||
| 164 | |||
| 122 | // PBK pushes to a stack the address where BRK will jump to. | 165 | // PBK pushes to a stack the address where BRK will jump to. |
| 123 | const u32 target = pc + instr.bra.GetBranchTarget(); | 166 | const u32 target = pc + instr.bra.GetBranchTarget(); |
| 124 | bb.push_back( | 167 | bb.push_back( |
| @@ -130,6 +173,10 @@ u32 ShaderIR::DecodeOther(NodeBlock& bb, u32 pc) { | |||
| 130 | UNIMPLEMENTED_IF_MSG(cc != Tegra::Shader::ConditionCode::T, "SYNC condition code used: {}", | 173 | UNIMPLEMENTED_IF_MSG(cc != Tegra::Shader::ConditionCode::T, "SYNC condition code used: {}", |
| 131 | static_cast<u32>(cc)); | 174 | static_cast<u32>(cc)); |
| 132 | 175 | ||
| 176 | if (disable_flow_stack) { | ||
| 177 | break; | ||
| 178 | } | ||
| 179 | |||
| 133 | // The SYNC opcode jumps to the address previously set by the SSY opcode | 180 | // The SYNC opcode jumps to the address previously set by the SSY opcode |
| 134 | bb.push_back(Operation(OperationCode::PopFlowStack, MetaStackClass::Ssy)); | 181 | bb.push_back(Operation(OperationCode::PopFlowStack, MetaStackClass::Ssy)); |
| 135 | break; | 182 | break; |
| @@ -138,6 +185,9 @@ u32 ShaderIR::DecodeOther(NodeBlock& bb, u32 pc) { | |||
| 138 | const Tegra::Shader::ConditionCode cc = instr.flow_condition_code; | 185 | const Tegra::Shader::ConditionCode cc = instr.flow_condition_code; |
| 139 | UNIMPLEMENTED_IF_MSG(cc != Tegra::Shader::ConditionCode::T, "BRK condition code used: {}", | 186 | UNIMPLEMENTED_IF_MSG(cc != Tegra::Shader::ConditionCode::T, "BRK condition code used: {}", |
| 140 | static_cast<u32>(cc)); | 187 | static_cast<u32>(cc)); |
| 188 | if (disable_flow_stack) { | ||
| 189 | break; | ||
| 190 | } | ||
| 141 | 191 | ||
| 142 | // The BRK opcode jumps to the address previously set by the PBK opcode | 192 | // The BRK opcode jumps to the address previously set by the PBK opcode |
| 143 | bb.push_back(Operation(OperationCode::PopFlowStack, MetaStackClass::Pbk)); | 193 | bb.push_back(Operation(OperationCode::PopFlowStack, MetaStackClass::Pbk)); |