shader_ir: Implement BRX & BRA.CC

This commit is contained in:
Fernando Sahmkow 2019-06-24 21:25:38 -04:00 committed by FernandoS27
parent c218ae4b02
commit 8a6fc529a9
6 changed files with 76 additions and 4 deletions

View file

@ -284,6 +284,9 @@ ParseResult ParseCode(CFGRebuildState& state, u32 address, ParseInfo& parse_info
state.pbk_labels.emplace(offset, target);
break;
}
case OpCode::Id::BRX: {
return ParseResult::AbnormalFlow;
}
default:
break;
}

View file

@ -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) {

View file

@ -149,6 +149,7 @@ enum class OperationCode {
ImageStore, /// (MetaImage, float[N] coords) -> void
Branch, /// (uint branch_target) -> void
BranchIndirect,/// (uint branch_target) -> void
PushFlowStack, /// (uint branch_target) -> void
PopFlowStack, /// () -> void
Exit, /// () -> void