|
|
|
@ -91,11 +91,45 @@ u32 ShaderIR::DecodeOther(NodeBlock& bb, u32 pc) { |
|
|
|
break; |
|
|
|
} |
|
|
|
case OpCode::Id::BRA: { |
|
|
|
UNIMPLEMENTED_IF_MSG(instr.bra.constant_buffer != 0, |
|
|
|
"BRA with constant buffers are not implemented"); |
|
|
|
Node branch; |
|
|
|
if (instr.bra.constant_buffer == 0) { |
|
|
|
const u32 target = pc + instr.bra.GetBranchTarget(); |
|
|
|
branch = Operation(OperationCode::Branch, Immediate(target)); |
|
|
|
} else { |
|
|
|
const u32 target = pc + 1; |
|
|
|
const Node op_a = GetConstBuffer(instr.cbuf36.index, instr.cbuf36.GetOffset()); |
|
|
|
const Node convert = SignedOperation(OperationCode::IArithmeticShiftRight, |
|
|
|
true, PRECISE, op_a, Immediate(3)); |
|
|
|
const Node operand = Operation(OperationCode::IAdd, PRECISE, convert, Immediate(target)); |
|
|
|
branch = Operation(OperationCode::BranchIndirect, convert); |
|
|
|
} |
|
|
|
|
|
|
|
const u32 target = pc + instr.bra.GetBranchTarget(); |
|
|
|
const Node branch = Operation(OperationCode::Branch, Immediate(target)); |
|
|
|
const Tegra::Shader::ConditionCode cc = instr.flow_condition_code; |
|
|
|
if (cc != Tegra::Shader::ConditionCode::T) { |
|
|
|
bb.push_back(Conditional(GetConditionCode(cc), {branch})); |
|
|
|
} else { |
|
|
|
bb.push_back(branch); |
|
|
|
} |
|
|
|
break; |
|
|
|
} |
|
|
|
case OpCode::Id::BRX: { |
|
|
|
Node operand; |
|
|
|
if (instr.brx.constant_buffer != 0) { |
|
|
|
const s32 target = pc + 1; |
|
|
|
const Node index = GetRegister(instr.gpr8); |
|
|
|
const Node op_a = |
|
|
|
GetConstBufferIndirect(instr.cbuf36.index, instr.cbuf36.GetOffset() + 0, index); |
|
|
|
const Node convert = SignedOperation(OperationCode::IArithmeticShiftRight, |
|
|
|
true, PRECISE, op_a, Immediate(3)); |
|
|
|
operand = Operation(OperationCode::IAdd, PRECISE, convert, Immediate(target)); |
|
|
|
} else { |
|
|
|
const s32 target = pc + instr.brx.GetBranchExtend(); |
|
|
|
const Node op_a = GetRegister(instr.gpr8); |
|
|
|
const Node convert = SignedOperation(OperationCode::IArithmeticShiftRight, |
|
|
|
true, PRECISE, op_a, Immediate(3)); |
|
|
|
operand = Operation(OperationCode::IAdd, PRECISE, convert, Immediate(target)); |
|
|
|
} |
|
|
|
const Node branch = Operation(OperationCode::BranchIndirect, operand); |
|
|
|
|
|
|
|
const Tegra::Shader::ConditionCode cc = instr.flow_condition_code; |
|
|
|
if (cc != Tegra::Shader::ConditionCode::T) { |
|
|
|
|