mirror of
https://github.com/N64Recomp/N64Recomp.git
synced 2025-10-30 08:02:11 +00:00
Rename gp to got in various places to better reflect what's actually going on
This commit is contained in:
parent
361568071a
commit
875ea3f584
3 changed files with 15 additions and 20 deletions
|
|
@ -102,7 +102,7 @@ namespace N64Recomp {
|
|||
bool executable = false;
|
||||
bool relocatable = false; // TODO is this needed? relocs being non-empty should be an equivalent check.
|
||||
bool has_mips32_relocs = false;
|
||||
std::optional<uint32_t> gp_ram_addr = std::nullopt;
|
||||
std::optional<uint32_t> got_ram_addr = std::nullopt;
|
||||
};
|
||||
|
||||
struct ReferenceSection {
|
||||
|
|
|
|||
|
|
@ -57,7 +57,7 @@ using InstrId = rabbitizer::InstrId::UniqueId;
|
|||
using RegId = rabbitizer::Registers::Cpu::GprO32;
|
||||
|
||||
bool analyze_instruction(const rabbitizer::InstructionCpu& instr, const N64Recomp::Function& func, N64Recomp::FunctionStats& stats,
|
||||
RegState reg_states[32], std::vector<RegState>& stack_states, bool is_gp_reg_defined) {
|
||||
RegState reg_states[32], std::vector<RegState>& stack_states, bool is_got_addr_defined) {
|
||||
// Temporary register state for tracking the register being operated on
|
||||
RegState temp{};
|
||||
|
||||
|
|
@ -118,9 +118,9 @@ bool analyze_instruction(const rabbitizer::InstructionCpu& instr, const N64Recom
|
|||
&& reg_states[rs].valid_got_loaded != reg_states[rt].valid_got_loaded) {
|
||||
// `addu rd, rs, $gp` or `addu rd, $gp, rt` after valid GOT load, this is the last part of a position independent
|
||||
// jump table call. Keep the register state intact.
|
||||
int valid_gp_loaded_reg = reg_states[rs].valid_got_loaded ? rs : rt;
|
||||
int valid_got_loaded_reg = reg_states[rs].valid_got_loaded ? rs : rt;
|
||||
|
||||
temp = reg_states[valid_gp_loaded_reg];
|
||||
temp = reg_states[valid_got_loaded_reg];
|
||||
}
|
||||
// Exactly one of the two addend register states should have a valid lui at this time
|
||||
else if (reg_states[rs].valid_lui != reg_states[rt].valid_lui) {
|
||||
|
|
@ -212,13 +212,8 @@ bool analyze_instruction(const rabbitizer::InstructionCpu& instr, const N64Recom
|
|||
temp.loaded_addend_reg = reg_states[base].prev_addend_reg;
|
||||
temp.loaded_addu_vram = reg_states[base].prev_addu_vram;
|
||||
temp.prev_got_offset = reg_states[base].prev_got_offset;
|
||||
} else if (base == (int)RegId::GPR_O32_gp) {
|
||||
} else if (base == (int)RegId::GPR_O32_gp && is_got_addr_defined) {
|
||||
// lw from the $gp register implies a read from the global offset table
|
||||
if (!is_gp_reg_defined) {
|
||||
fmt::print(stderr, "Found $gp register usage in section without a defined $gp value at 0x{:08X} in {}\n",
|
||||
instr.getVram(), func.name);
|
||||
return false;
|
||||
}
|
||||
temp.prev_got_offset = imm;
|
||||
temp.valid_got_offset = true;
|
||||
}
|
||||
|
|
@ -272,7 +267,7 @@ bool analyze_instruction(const rabbitizer::InstructionCpu& instr, const N64Recom
|
|||
bool N64Recomp::analyze_function(const N64Recomp::Context& context, const N64Recomp::Function& func,
|
||||
const std::vector<rabbitizer::InstructionCpu>& instructions, N64Recomp::FunctionStats& stats) {
|
||||
const Section* section = &context.sections[func.section_index];
|
||||
std::optional<uint32_t> gp_ram_addr = section->gp_ram_addr;
|
||||
std::optional<uint32_t> got_ram_addr = section->got_ram_addr;
|
||||
|
||||
// Create a state to track each register (r0 won't be used)
|
||||
RegState reg_states[32] {};
|
||||
|
|
@ -281,20 +276,20 @@ bool N64Recomp::analyze_function(const N64Recomp::Context& context, const N64Rec
|
|||
// Look for jump tables
|
||||
// A linear search through the func won't be accurate due to not taking control flow into account, but it'll work for finding jtables
|
||||
for (const auto& instr : instructions) {
|
||||
if (!analyze_instruction(instr, func, stats, reg_states, stack_states, gp_ram_addr.has_value())) {
|
||||
if (!analyze_instruction(instr, func, stats, reg_states, stack_states, got_ram_addr.has_value())) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
// Calculate absolute addresses for position-independent jump tables
|
||||
if (gp_ram_addr.has_value()) {
|
||||
uint32_t gp_rom_addr = gp_ram_addr.value() + func.rom - func.vram;
|
||||
if (got_ram_addr.has_value()) {
|
||||
uint32_t got_rom_addr = got_ram_addr.value() + func.rom - func.vram;
|
||||
|
||||
for (size_t i = 0; i < stats.jump_tables.size(); i++) {
|
||||
JumpTable& cur_jtbl = stats.jump_tables[i];
|
||||
|
||||
if (cur_jtbl.got_offset.has_value()) {
|
||||
uint32_t got_word = byteswap(*reinterpret_cast<const uint32_t*>(&context.rom[gp_rom_addr + cur_jtbl.got_offset.value()]));
|
||||
uint32_t got_word = byteswap(*reinterpret_cast<const uint32_t*>(&context.rom[got_rom_addr + cur_jtbl.got_offset.value()]));
|
||||
|
||||
cur_jtbl.vram += (section->ram_addr + got_word);
|
||||
}
|
||||
|
|
@ -329,10 +324,10 @@ bool N64Recomp::analyze_function(const N64Recomp::Context& context, const N64Rec
|
|||
uint32_t rom_addr = vram + func.rom - func.vram;
|
||||
uint32_t jtbl_word = byteswap(*reinterpret_cast<const uint32_t*>(&context.rom[rom_addr]));
|
||||
|
||||
if (cur_jtbl.got_offset.has_value() && gp_ram_addr.has_value()) {
|
||||
// Position independent jump tables have values that are offsets from $gp,
|
||||
if (cur_jtbl.got_offset.has_value() && got_ram_addr.has_value()) {
|
||||
// Position independent jump tables have values that are offsets from the GOT,
|
||||
// convert those to absolute addresses
|
||||
jtbl_word += gp_ram_addr.value();
|
||||
jtbl_word += got_ram_addr.value();
|
||||
}
|
||||
|
||||
// Check if the entry is a valid address in the current function
|
||||
|
|
|
|||
|
|
@ -509,7 +509,7 @@ bool N64Recomp::Context::from_symbol_file(const std::filesystem::path& symbol_fi
|
|||
std::optional<uint32_t> vram_addr = el["vram"].template value<uint32_t>();
|
||||
std::optional<uint32_t> size = el["size"].template value<uint32_t>();
|
||||
std::optional<std::string> name = el["name"].template value<std::string>();
|
||||
std::optional<uint32_t> gp_ram_addr = el["gp"].template value<uint32_t>();
|
||||
std::optional<uint32_t> got_ram_addr = el["got_address"].template value<uint32_t>();
|
||||
|
||||
if (!rom_addr.has_value() || !vram_addr.has_value() || !size.has_value() || !name.has_value()) {
|
||||
throw toml::parse_error("Section entry missing required field(s)", el.source());
|
||||
|
|
@ -522,7 +522,7 @@ bool N64Recomp::Context::from_symbol_file(const std::filesystem::path& symbol_fi
|
|||
section.ram_addr = vram_addr.value();
|
||||
section.size = size.value();
|
||||
section.name = name.value();
|
||||
section.gp_ram_addr = gp_ram_addr;
|
||||
section.got_ram_addr = got_ram_addr;
|
||||
section.executable = true;
|
||||
|
||||
// Read functions for the section.
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue