Skip to content

Instantly share code, notes, and snippets.

@FernandoS27
Created September 23, 2019 15:23
Show Gist options
  • Save FernandoS27/57f749b54abafd424f8922d04d779882 to your computer and use it in GitHub Desktop.
Save FernandoS27/57f749b54abafd424f8922d04d779882 to your computer and use it in GitHub Desktop.
struct BranchIndirectInfo {
u32 buffer{};
u32 offset{};
u32 entries{};
};
std::optional<BranchIndirectInfo> TrackBranchIndirectInfo(const CFGRebuildState& state,
u32 start_address, u32 current_position) {
const u32 shader_start = state.start;
u32 pos = current_position;
BranchIndirectInfo result{};
u64 track_register = 0;
// Step 0 Get BRX Info
const Instruction instr = {state.program_code[pos]};
const auto opcode = OpCode::Decode(instr);
if (opcode->get().GetId() != OpCode::Id::BRX) {
return {};
}
if (instr.brx.constant_buffer != 0) {
return {};
}
track_register = instr.gpr8.Value();
pos--;
bool found_track = false;
// Step 1 Track LDC
while (pos >= shader_start) {
if (IsSchedInstruction(pos, shader_start)) {
pos--;
continue;
}
const Instruction instr = {state.program_code[pos]};
const auto opcode = OpCode::Decode(instr);
if (opcode->get().GetId() == OpCode::Id::LD_C) {
if (instr.gpr0.Value() == track_register &&
instr.ld_c.type.Value() == Tegra::Shader::UniformType::Single) {
result.buffer = instr.cbuf36.index;
result.offset = instr.cbuf36.GetOffset();
track_register = instr.gpr8.Value();
pos--;
found_track = true;
break;
}
}
pos--;
}
if (!found_track) {
return {};
}
found_track = false;
// Step 2 Track SHL
while (pos >= shader_start) {
if (IsSchedInstruction(pos, shader_start)) {
pos--;
continue;
}
const Instruction instr = {state.program_code[pos]};
const auto opcode = OpCode::Decode(instr);
if (opcode->get().GetId() == OpCode::Id::SHL_IMM) {
if (instr.gpr0.Value() == track_register) {
track_register = instr.gpr8.Value();
pos--;
found_track = true;
break;
}
}
pos--;
}
if (!found_track) {
return {};
}
found_track = false;
// Step 3 Track IMNMX
while (pos >= shader_start) {
if (IsSchedInstruction(pos, shader_start)) {
pos--;
continue;
}
const Instruction instr = {state.program_code[pos]};
const auto opcode = OpCode::Decode(instr);
if (opcode->get().GetId() == OpCode::Id::IMNMX_IMM) {
if (instr.gpr0.Value() == track_register) {
track_register = instr.gpr8.Value();
result.entries = instr.alu.GetSignedImm20_20();
pos--;
found_track = true;
break;
}
}
pos--;
}
if (!found_track) {
return {};
}
return {result};
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment