mirror of
https://git.h3cjp.net/H3cJP/citra.git
synced 2024-11-23 19:32:52 +00:00
Shader_IR: Implement BRX tracking.
This commit is contained in:
parent
5ee4fb6e12
commit
2ef696c85a
|
@ -124,6 +124,111 @@ enum class ParseResult : u32 {
|
|||
AbnormalFlow,
|
||||
};
|
||||
|
||||
struct BranchIndirectInfo {
|
||||
u32 buffer{};
|
||||
u32 offset{};
|
||||
u32 entries{};
|
||||
s32 relative_position{};
|
||||
};
|
||||
|
||||
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();
|
||||
result.relative_position = instr.brx.GetBranchExtend();
|
||||
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};
|
||||
}
|
||||
|
||||
std::pair<ParseResult, ParseInfo> ParseCode(CFGRebuildState& state, u32 address) {
|
||||
u32 offset = static_cast<u32>(address);
|
||||
const u32 end_address = static_cast<u32>(state.program_size / sizeof(Instruction));
|
||||
|
@ -298,6 +403,14 @@ std::pair<ParseResult, ParseInfo> ParseCode(CFGRebuildState& state, u32 address)
|
|||
break;
|
||||
}
|
||||
case OpCode::Id::BRX: {
|
||||
auto tmp = TrackBranchIndirectInfo(state, address, offset);
|
||||
if (tmp) {
|
||||
auto result = *tmp;
|
||||
LOG_CRITICAL(HW_GPU, "Track Successful, BRX: buffer:{}, offset:{}, entries:{}",
|
||||
result.buffer, result.offset, result.entries);
|
||||
} else {
|
||||
LOG_CRITICAL(HW_GPU, "Track Unsuccesful");
|
||||
}
|
||||
return {ParseResult::AbnormalFlow, parse_info};
|
||||
}
|
||||
default:
|
||||
|
|
Loading…
Reference in a new issue