Add the concept of unaligned relocs

This commit is contained in:
Ethan Lafrenais 2024-11-02 13:59:14 -04:00
parent 63345aed55
commit 75a51d2491
No known key found for this signature in database
GPG key ID: 928A0136009E2745
5 changed files with 11 additions and 4 deletions

View file

@ -23,6 +23,7 @@ namespace N64Recomp {
RelocType reloc_type;
uint32_t reloc_section_index;
uint32_t reloc_target_section_offset;
bool reloc_unaligned;
};
class Generator {

View file

@ -56,6 +56,7 @@ namespace N64Recomp {
uint16_t target_section;
RelocType type;
bool reference_symbol;
bool unaligned;
};
// Special section indices.

View file

@ -103,11 +103,11 @@ std::string fpr_u64_to_string(int fpr_index) {
std::string unsigned_reloc(const N64Recomp::InstructionContext& context) {
switch (context.reloc_type) {
case N64Recomp::RelocType::R_MIPS_HI16:
return fmt::format("{}RELOC_HI16({}, {:#X})",
context.reloc_tag_as_reference ? "REF_" : "", context.reloc_section_index, context.reloc_target_section_offset);
return fmt::format("{}RELOC_HI16{}({}, {:#X})",
context.reloc_tag_as_reference ? "REF_" : "", context.reloc_unaligned ? "_UNALIGNED" : "", context.reloc_section_index, context.reloc_target_section_offset);
case N64Recomp::RelocType::R_MIPS_LO16:
return fmt::format("{}RELOC_LO16({}, {:#X})",
context.reloc_tag_as_reference ? "REF_" : "", context.reloc_section_index, context.reloc_target_section_offset);
return fmt::format("{}RELOC_LO16{}({}, {:#X})",
context.reloc_tag_as_reference ? "REF_" : "", context.reloc_unaligned ? "_UNALIGNED" : "", context.reloc_section_index, context.reloc_target_section_offset);
default:
throw std::runtime_error(fmt::format("Unexpected reloc type {}\n", static_cast<int>(context.reloc_type)));
}

View file

@ -569,6 +569,7 @@ bool N64Recomp::Context::from_symbol_file(const std::filesystem::path& symbol_fi
std::optional<uint32_t> vram = reloc_el["vram"].template value<uint32_t>();
std::optional<uint32_t> target_vram = reloc_el["target_vram"].template value<uint32_t>();
std::optional<std::string> type_string = reloc_el["type"].template value<std::string>();
std::optional<bool> unaligned = reloc_el["unaligned"].template value<bool>();
if (!vram.has_value() || !target_vram.has_value() || !type_string.has_value()) {
throw toml::parse_error("Reloc entry missing required field(s)", reloc_el.source());
@ -586,6 +587,7 @@ bool N64Recomp::Context::from_symbol_file(const std::filesystem::path& symbol_fi
cur_reloc.symbol_index = (uint32_t)-1;
cur_reloc.target_section = section_index;
cur_reloc.type = reloc_type;
cur_reloc.unaligned = unaligned.value_or(false);
section.relocs.emplace_back(cur_reloc);
}

View file

@ -148,6 +148,7 @@ bool process_instruction(const N64Recomp::Context& context, const N64Recomp::Fun
uint32_t reloc_section = 0;
uint32_t reloc_target_section_offset = 0;
size_t reloc_reference_symbol = (size_t)-1;
bool reloc_unaligned = false;
uint32_t func_vram_end = func.vram + func.words.size() * sizeof(func.words[0]);
@ -171,6 +172,7 @@ bool process_instruction(const N64Recomp::Context& context, const N64Recomp::Fun
// Record the reloc's data.
reloc_type = reloc.type;
reloc_target_section_offset = reloc.target_section_offset;
reloc_unaligned = reloc.unaligned;
// Ignore all relocs that aren't MIPS_HI16, MIPS_LO16 or MIPS_26.
if (reloc_type == N64Recomp::RelocType::R_MIPS_HI16 || reloc_type == N64Recomp::RelocType::R_MIPS_LO16 || reloc_type == N64Recomp::RelocType::R_MIPS_26) {
if (reloc.reference_symbol) {
@ -587,6 +589,7 @@ bool process_instruction(const N64Recomp::Context& context, const N64Recomp::Fun
instruction_context.reloc_type = reloc_type;
instruction_context.reloc_section_index = reloc_section;
instruction_context.reloc_target_section_offset = reloc_target_section_offset;
instruction_context.reloc_unaligned = reloc_unaligned;
auto do_check_fr = [](std::ostream& output_file, const CGenerator& generator, const InstructionContext& ctx, Operand operand) {
switch (operand) {