mirror of
https://github.com/N64Recomp/N64Recomp.git
synced 2026-04-28 13:01:58 +00:00
Allow cross-section relocations, encode exact target section in mod relocations, add way to tag reference symbol relocations
This commit is contained in:
parent
008b1177fa
commit
293b97817b
8 changed files with 142 additions and 86 deletions
|
|
@ -230,19 +230,21 @@ N64Recomp::Context build_mod_context(const N64Recomp::Context& input_context, st
|
|||
section_order.resize(input_context.sections.size());
|
||||
std::iota(section_order.begin(), section_order.end(), 0);
|
||||
|
||||
// Sort the vector based on the rom address of the corresponding section.
|
||||
std::sort(section_order.begin(), section_order.end(),
|
||||
[&](uint16_t a, uint16_t b) {
|
||||
const auto& section_a = input_context.sections[a];
|
||||
const auto& section_b = input_context.sections[b];
|
||||
// Sort primarily by ROM address.
|
||||
if (section_a.rom_addr != section_b.rom_addr) {
|
||||
return section_a.rom_addr < section_b.rom_addr;
|
||||
}
|
||||
// Sort secondarily by RAM address.
|
||||
return section_a.ram_addr < section_b.ram_addr;
|
||||
}
|
||||
);
|
||||
// TODO this sort is currently disabled because sections seem to already be ordered
|
||||
// by elf offset. Determine if this is always the case and remove this if so.
|
||||
//// Sort the vector based on the rom address of the corresponding section.
|
||||
//std::sort(section_order.begin(), section_order.end(),
|
||||
// [&](uint16_t a, uint16_t b) {
|
||||
// const auto& section_a = input_context.sections[a];
|
||||
// const auto& section_b = input_context.sections[b];
|
||||
// // Sort primarily by ROM address.
|
||||
// if (section_a.rom_addr != section_b.rom_addr) {
|
||||
// return section_a.rom_addr < section_b.rom_addr;
|
||||
// }
|
||||
// // Sort secondarily by RAM address.
|
||||
// return section_a.ram_addr < section_b.ram_addr;
|
||||
// }
|
||||
//);
|
||||
|
||||
// TODO avoid a copy here.
|
||||
ret.rom = input_context.rom;
|
||||
|
|
@ -254,6 +256,9 @@ N64Recomp::Context build_mod_context(const N64Recomp::Context& input_context, st
|
|||
|
||||
size_t num_imports = ret.import_symbols.size();
|
||||
|
||||
// Mapping of input section to output section for fixing up relocations.
|
||||
std::unordered_map<uint16_t, uint16_t> input_section_to_output_section{};
|
||||
|
||||
// Iterate over the input sections in their sorted order.
|
||||
for (uint16_t section_index : section_order) {
|
||||
const auto& cur_section = input_context.sections[section_index];
|
||||
|
|
@ -271,6 +276,7 @@ N64Recomp::Context build_mod_context(const N64Recomp::Context& input_context, st
|
|||
if (cur_section.ram_addr >= output_section_bss_end && cur_section.ram_addr <= round_up_16(output_section_bss_end)) {
|
||||
// Calculate the output section's bss size by using its non-bss end address and the current section's end address.
|
||||
section_out.bss_size = cur_section.ram_addr + cur_section.size - output_section_bss_start;
|
||||
input_section_to_output_section[section_index] = output_section_index;
|
||||
}
|
||||
}
|
||||
continue;
|
||||
|
|
@ -294,6 +300,9 @@ N64Recomp::Context build_mod_context(const N64Recomp::Context& input_context, st
|
|||
new_section.ram_addr = cur_section.ram_addr;
|
||||
new_section.size = cur_section.size;
|
||||
}
|
||||
|
||||
// Map this section to the current output section.
|
||||
input_section_to_output_section[section_index] = output_section_index;
|
||||
|
||||
// Check for special section names.
|
||||
bool patch_section = cur_section.name == N64Recomp::PatchSectionName;
|
||||
|
|
@ -508,9 +517,11 @@ N64Recomp::Context build_mod_context(const N64Recomp::Context& input_context, st
|
|||
}
|
||||
section_out.relocs.emplace_back(N64Recomp::Reloc{
|
||||
.address = cur_reloc.address,
|
||||
.target_section_offset = output_section_offset,
|
||||
// Use the original target section offset, this will be recalculated based on the output section afterwards.
|
||||
.target_section_offset = cur_reloc.target_section_offset,
|
||||
.symbol_index = 0,
|
||||
.target_section = N64Recomp::SectionSelf,
|
||||
// Use the input section index in the reloc, this will be converted to the output section afterwards.
|
||||
.target_section = cur_reloc.target_section,
|
||||
.type = cur_reloc.type,
|
||||
.reference_symbol = false,
|
||||
});
|
||||
|
|
@ -520,6 +531,28 @@ N64Recomp::Context build_mod_context(const N64Recomp::Context& input_context, st
|
|||
}
|
||||
}
|
||||
|
||||
// Fix up every internal reloc's target section based on the input to output section mapping.
|
||||
for (auto& section : ret.sections) {
|
||||
for (auto& reloc : section.relocs) {
|
||||
if (!reloc.reference_symbol) {
|
||||
uint16_t input_section_index = reloc.target_section;
|
||||
auto find_it = input_section_to_output_section.find(input_section_index);
|
||||
if (find_it == input_section_to_output_section.end()) {
|
||||
fmt::print("Reloc at address 0x{:08X} references section {}, which didn't get mapped to an output section\n",
|
||||
reloc.address, input_context.sections[input_section_index].name);
|
||||
return {};
|
||||
}
|
||||
uint16_t output_section_index = find_it->second;
|
||||
const auto& input_section = input_context.sections[input_section_index];
|
||||
const auto& output_section = ret.sections[output_section_index];
|
||||
// Adjust the reloc's target section offset based on the reloc's new section.
|
||||
reloc.target_section_offset = reloc.target_section_offset + input_section.ram_addr - output_section.ram_addr;
|
||||
// Replace the target section with the mapped output section.
|
||||
reloc.target_section = find_it->second;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Copy the import reference symbols from the input context as-is to this context.
|
||||
ret.import_symbols = input_context.import_symbols;
|
||||
|
||||
|
|
@ -607,6 +640,10 @@ int main(int argc, const char** argv) {
|
|||
bool mod_context_good;
|
||||
N64Recomp::Context mod_context = build_mod_context(context, std::move(dependencies), mod_context_good);
|
||||
std::vector<uint8_t> symbols_bin = N64Recomp::symbols_to_bin_v1(mod_context);
|
||||
if (symbols_bin.empty()) {
|
||||
fmt::print(stderr, "Failed to create symbol file\n");
|
||||
return EXIT_FAILURE;
|
||||
}
|
||||
|
||||
std::ofstream output_syms_file{ config.output_syms_path, std::ios::binary };
|
||||
output_syms_file.write(reinterpret_cast<const char*>(symbols_bin.data()), symbols_bin.size());
|
||||
|
|
|
|||
|
|
@ -19,6 +19,7 @@ namespace N64Recomp {
|
|||
|
||||
uint16_t imm16;
|
||||
|
||||
bool reloc_tag_as_reference;
|
||||
RelocType reloc_type;
|
||||
uint32_t reloc_section_index;
|
||||
uint32_t reloc_target_section_offset;
|
||||
|
|
|
|||
|
|
@ -57,7 +57,6 @@ namespace N64Recomp {
|
|||
bool reference_symbol;
|
||||
};
|
||||
|
||||
constexpr uint16_t SectionSelf = (uint16_t)-1;
|
||||
constexpr uint16_t SectionAbsolute = (uint16_t)-2;
|
||||
constexpr uint16_t SectionImport = (uint16_t)-3; // Imported symbols for mods
|
||||
constexpr uint16_t SectionEvent = (uint16_t)-4;
|
||||
|
|
@ -181,6 +180,8 @@ namespace N64Recomp {
|
|||
std::vector<std::vector<size_t>> section_functions;
|
||||
// A mapping of vram address to every function with that address.
|
||||
std::unordered_map<uint32_t, std::vector<size_t>> functions_by_vram;
|
||||
// A mapping of bss section index to the corresponding non-bss section index.
|
||||
std::unordered_map<uint16_t, uint16_t> bss_section_to_section;
|
||||
// The target ROM being recompiled, TODO move this outside of the context to avoid making a copy for mod contexts.
|
||||
// Used for reading relocations and for the output binary feature.
|
||||
std::vector<uint8_t> rom;
|
||||
|
|
@ -469,7 +470,7 @@ namespace N64Recomp {
|
|||
}
|
||||
};
|
||||
|
||||
bool recompile_function(const Context& context, const Function& func, std::ofstream& output_file, std::span<std::vector<uint32_t>> static_funcs);
|
||||
bool recompile_function(const Context& context, const Function& func, std::ofstream& output_file, std::span<std::vector<uint32_t>> static_funcs, bool tag_reference_relocs);
|
||||
|
||||
enum class ModSymbolsError {
|
||||
Good,
|
||||
|
|
|
|||
|
|
@ -103,9 +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_section_index, context.reloc_target_section_offset);
|
||||
return fmt::format("{}RELOC_HI16({}, {:#X})",
|
||||
context.reloc_tag_as_reference ? "REF_" : "", context.reloc_section_index, context.reloc_target_section_offset);
|
||||
case N64Recomp::RelocType::R_MIPS_LO16:
|
||||
return fmt::format("RELOC_LO16({}, {:#X})", context.reloc_section_index, context.reloc_target_section_offset);
|
||||
return fmt::format("{}RELOC_LO16({}, {:#X})",
|
||||
context.reloc_tag_as_reference ? "REF_" : "", 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)));
|
||||
}
|
||||
|
|
|
|||
22
src/elf.cpp
22
src/elf.cpp
|
|
@ -345,6 +345,7 @@ ELFIO::section* read_sections(N64Recomp::Context& context, const N64Recomp::ElfP
|
|||
if (bss_find != bss_sections_by_name.end()) {
|
||||
section_out.bss_section_index = bss_find->second->get_index();
|
||||
section_out.bss_size = bss_find->second->get_size();
|
||||
context.bss_section_to_section[section_out.bss_section_index] = section_index;
|
||||
}
|
||||
|
||||
if (context.has_reference_symbols() || section_out.relocatable) {
|
||||
|
|
@ -427,24 +428,21 @@ ELFIO::section* read_sections(N64Recomp::Context& context, const N64Recomp::ElfP
|
|||
return nullptr;
|
||||
}
|
||||
}
|
||||
else if (rel_symbol_section_index == ELFIO::SHN_ABS) {
|
||||
reloc_out.reference_symbol = false;
|
||||
reloc_out.target_section = N64Recomp::SectionAbsolute;
|
||||
rel_section_vram = 0;
|
||||
}
|
||||
else {
|
||||
reloc_out.reference_symbol = false;
|
||||
reloc_out.target_section = rel_symbol_section_index;
|
||||
// Handle special sections.
|
||||
if (rel_symbol_section_index >= context.sections.size()) {
|
||||
switch (rel_symbol_section_index) {
|
||||
case ELFIO::SHN_ABS:
|
||||
rel_section_vram = 0;
|
||||
break;
|
||||
default:
|
||||
fmt::print(stderr, "Reloc {} references symbol {} which is in an unknown section 0x{:04X}!\n",
|
||||
i, rel_symbol_name, rel_symbol_section_index);
|
||||
return nullptr;
|
||||
}
|
||||
}
|
||||
else {
|
||||
rel_section_vram = context.sections[rel_symbol_section_index].ram_addr;
|
||||
fmt::print(stderr, "Reloc {} references symbol {} which is in an unknown section 0x{:04X}!\n",
|
||||
i, rel_symbol_name, rel_symbol_section_index);
|
||||
return nullptr;
|
||||
}
|
||||
rel_section_vram = context.sections[rel_symbol_section_index].ram_addr;
|
||||
}
|
||||
|
||||
// Reloc pairing, see MIPS System V ABI documentation page 4-18 (https://refspecs.linuxfoundation.org/elf/mipsabi.pdf)
|
||||
|
|
|
|||
|
|
@ -127,7 +127,7 @@ bool recompile_single_function(const N64Recomp::Context& context, const N64Recom
|
|||
"\n",
|
||||
recomp_include);
|
||||
|
||||
if (!N64Recomp::recompile_function(context, func, output_file, static_funcs_out)) {
|
||||
if (!N64Recomp::recompile_function(context, func, output_file, static_funcs_out, false)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
|
|
@ -617,7 +617,7 @@ int main(int argc, char** argv) {
|
|||
|
||||
// Recompile the function.
|
||||
if (config.single_file_output || config.functions_per_output_file > 1) {
|
||||
result = N64Recomp::recompile_function(context, func, current_output_file, static_funcs_by_section);
|
||||
result = N64Recomp::recompile_function(context, func, current_output_file, static_funcs_by_section, false);
|
||||
if (!config.single_file_output) {
|
||||
cur_file_function_count++;
|
||||
if (cur_file_function_count >= config.functions_per_output_file) {
|
||||
|
|
@ -704,7 +704,7 @@ int main(int argc, char** argv) {
|
|||
bool result;
|
||||
size_t prev_num_statics = static_funcs_by_section[func.section_index].size();
|
||||
if (config.single_file_output || config.functions_per_output_file > 1) {
|
||||
result = N64Recomp::recompile_function(context, func, current_output_file, static_funcs_by_section);
|
||||
result = N64Recomp::recompile_function(context, func, current_output_file, static_funcs_by_section, false);
|
||||
if (!config.single_file_output) {
|
||||
cur_file_function_count++;
|
||||
if (cur_file_function_count >= config.functions_per_output_file) {
|
||||
|
|
|
|||
|
|
@ -32,7 +32,8 @@ struct FuncV1 {
|
|||
uint32_t size;
|
||||
};
|
||||
|
||||
constexpr uint32_t SectionSelfVromV1 = 0xFFFFFFFF;
|
||||
// Local section flag, if set then the reloc is pointing to a section within the mod and the vrom is the section index.
|
||||
constexpr uint32_t SectionSelfVromFlagV1 = 0x80000000;
|
||||
|
||||
// Special sections
|
||||
constexpr uint32_t SectionImportVromV1 = 0xFFFFFFFE;
|
||||
|
|
@ -211,12 +212,7 @@ bool parse_v1(std::span<const char> data, const std::unordered_map<uint32_t, uin
|
|||
uint16_t reloc_target_section;
|
||||
uint32_t reloc_target_section_offset;
|
||||
uint32_t reloc_symbol_index;
|
||||
if (target_section_vrom == SectionSelfVromV1) {
|
||||
reloc_target_section = N64Recomp::SectionSelf;
|
||||
reloc_target_section_offset = reloc_in.target_section_offset_or_index;
|
||||
reloc_symbol_index = 0; // Not used for normal relocs.
|
||||
}
|
||||
else if (target_section_vrom == SectionImportVromV1) {
|
||||
if (target_section_vrom == SectionImportVromV1) {
|
||||
reloc_target_section = N64Recomp::SectionImport;
|
||||
reloc_target_section_offset = 0; // Not used for imports or reference symbols.
|
||||
reloc_symbol_index = reloc_in.target_section_offset_or_index;
|
||||
|
|
@ -228,6 +224,16 @@ bool parse_v1(std::span<const char> data, const std::unordered_map<uint32_t, uin
|
|||
reloc_symbol_index = reloc_in.target_section_offset_or_index;
|
||||
cur_reloc.reference_symbol = true;
|
||||
}
|
||||
else if (target_section_vrom & SectionSelfVromFlagV1) {
|
||||
reloc_target_section = static_cast<uint16_t>(target_section_vrom & ~SectionSelfVromFlagV1);
|
||||
reloc_target_section_offset = reloc_in.target_section_offset_or_index;
|
||||
reloc_symbol_index = 0; // Not used for normal relocs.
|
||||
cur_reloc.reference_symbol = false;
|
||||
if (reloc_target_section >= mod_context.sections.size()) {
|
||||
printf("Reloc %zu in section %zu references local section %u, but only %zu exist\n",
|
||||
reloc_index, section_index, reloc_target_section, mod_context.sections.size());
|
||||
}
|
||||
}
|
||||
else {
|
||||
// TODO lookup by section index by original vrom
|
||||
auto find_section_it = sections_by_vrom.find(target_section_vrom);
|
||||
|
|
@ -593,11 +599,14 @@ std::vector<uint8_t> N64Recomp::symbols_to_bin_v1(const N64Recomp::Context& cont
|
|||
vec_put(ret, &func_out);
|
||||
}
|
||||
|
||||
for (const Reloc& cur_reloc : cur_section.relocs) {
|
||||
for (size_t reloc_index = 0; reloc_index < cur_section.relocs.size(); reloc_index++) {
|
||||
const Reloc& cur_reloc = cur_section.relocs[reloc_index];
|
||||
uint32_t target_section_vrom;
|
||||
uint32_t target_section_offset_or_index = cur_reloc.target_section_offset;
|
||||
if (cur_reloc.target_section == SectionSelf) {
|
||||
target_section_vrom = SectionSelfVromV1;
|
||||
if (cur_reloc.target_section == SectionAbsolute) {
|
||||
printf("Internal error: reloc %zu in section %zu references an absolute symbol and should have been relocated already\n",
|
||||
reloc_index, section_index);
|
||||
return {};
|
||||
}
|
||||
else if (cur_reloc.target_section == SectionImport) {
|
||||
target_section_vrom = SectionImportVromV1;
|
||||
|
|
@ -611,7 +620,12 @@ std::vector<uint8_t> N64Recomp::symbols_to_bin_v1(const N64Recomp::Context& cont
|
|||
target_section_vrom = context.get_reference_section_rom(cur_reloc.target_section);
|
||||
}
|
||||
else {
|
||||
target_section_vrom = context.sections[cur_reloc.target_section].rom_addr;
|
||||
if (cur_reloc.target_section >= context.sections.size()) {
|
||||
printf("Internal error: reloc %zu in section %zu references section %u, but only %zu exist\n",
|
||||
reloc_index, section_index, cur_reloc.target_section, context.sections.size());
|
||||
return {};
|
||||
}
|
||||
target_section_vrom = SectionSelfVromFlagV1 | cur_reloc.target_section;
|
||||
}
|
||||
RelocV1 reloc_out {
|
||||
.section_offset = cur_reloc.address - cur_section.ram_addr,
|
||||
|
|
|
|||
|
|
@ -110,7 +110,7 @@ std::string_view ctx_gpr_prefix(int reg) {
|
|||
}
|
||||
|
||||
// Major TODO, this function grew very organically and needs to be cleaned up. Ideally, it'll get split up into some sort of lookup table grouped by similar instruction types.
|
||||
bool process_instruction(const N64Recomp::Context& context, const N64Recomp::Function& func, const N64Recomp::FunctionStats& stats, const std::unordered_set<uint32_t>& skipped_insns, size_t instr_index, const std::vector<rabbitizer::InstructionCpu>& instructions, std::ofstream& output_file, bool indent, bool emit_link_branch, int link_branch_index, size_t reloc_index, bool& needs_link_branch, bool& is_branch_likely, std::span<std::vector<uint32_t>> static_funcs_out) {
|
||||
bool process_instruction(const N64Recomp::Context& context, const N64Recomp::Function& func, const N64Recomp::FunctionStats& stats, const std::unordered_set<uint32_t>& skipped_insns, size_t instr_index, const std::vector<rabbitizer::InstructionCpu>& instructions, std::ofstream& output_file, bool indent, bool emit_link_branch, int link_branch_index, size_t reloc_index, bool& needs_link_branch, bool& is_branch_likely, bool tag_reference_relocs, std::span<std::vector<uint32_t>> static_funcs_out) {
|
||||
using namespace N64Recomp;
|
||||
|
||||
const auto& section = context.sections[func.section_index];
|
||||
|
|
@ -158,48 +158,50 @@ bool process_instruction(const N64Recomp::Context& context, const N64Recomp::Fun
|
|||
// Get the reloc data for this instruction
|
||||
const auto& reloc = section.relocs[reloc_index];
|
||||
reloc_section = reloc.target_section;
|
||||
// Only process this relocation if this section is relocatable or if this relocation targets a reference symbol.
|
||||
if (section.relocatable || reloc.reference_symbol) {
|
||||
// Ignore this reloc if it points to a different section.
|
||||
// Also check if the reloc points to the bss section since that will also be relocated with the section.
|
||||
// Additionally, always process reference symbol relocations.
|
||||
if (reloc_section == func.section_index || reloc_section == section.bss_section_index || reloc_section == N64Recomp::SectionSelf || reloc.reference_symbol) {
|
||||
// Record the reloc's data.
|
||||
reloc_type = reloc.type;
|
||||
reloc_target_section_offset = reloc.target_section_offset;
|
||||
// Ignore all relocs that aren't HI16 or LO16.
|
||||
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) {
|
||||
reloc_reference_symbol = reloc.symbol_index;
|
||||
// Don't try to relocate special section symbols.
|
||||
if (context.is_regular_reference_section(reloc.target_section)) {
|
||||
bool ref_section_relocatable = context.is_reference_section_relocatable(reloc.target_section);
|
||||
uint32_t ref_section_vram = context.get_reference_section_vram(reloc.target_section);
|
||||
// Resolve HI16 and LO16 reference symbol relocs to non-relocatable sections by patching the instruction immediate.
|
||||
if (!ref_section_relocatable && (reloc_type == N64Recomp::RelocType::R_MIPS_HI16 || reloc_type == N64Recomp::RelocType::R_MIPS_LO16)) {
|
||||
uint32_t full_immediate = reloc.target_section_offset + ref_section_vram;
|
||||
|
||||
if (reloc_type == N64Recomp::RelocType::R_MIPS_HI16) {
|
||||
imm = (full_immediate >> 16) + ((full_immediate >> 15) & 1);
|
||||
reloc_type = N64Recomp::RelocType::R_MIPS_NONE;
|
||||
}
|
||||
else if (reloc_type == N64Recomp::RelocType::R_MIPS_LO16) {
|
||||
imm = full_immediate & 0xFFFF;
|
||||
reloc_type = N64Recomp::RelocType::R_MIPS_NONE;
|
||||
}
|
||||
// Check if the relocation references a relocatable section.
|
||||
bool target_relocatable = false;
|
||||
if (!reloc.reference_symbol && reloc_section != N64Recomp::SectionAbsolute) {
|
||||
const auto& target_section = context.sections[reloc_section];
|
||||
target_relocatable = target_section.relocatable;
|
||||
}
|
||||
|
||||
// The reloc has been processed, so set it to none to prevent it getting processed a second time during instruction code generation.
|
||||
reloc_type = N64Recomp::RelocType::R_MIPS_NONE;
|
||||
reloc_reference_symbol = (size_t)-1;
|
||||
// Only process this relocation if the target section is relocatable or if this relocation targets a reference symbol.
|
||||
if (target_relocatable || reloc.reference_symbol) {
|
||||
// Record the reloc's data.
|
||||
reloc_type = reloc.type;
|
||||
reloc_target_section_offset = reloc.target_section_offset;
|
||||
// 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) {
|
||||
reloc_reference_symbol = reloc.symbol_index;
|
||||
// Don't try to relocate special section symbols.
|
||||
if (context.is_regular_reference_section(reloc.target_section) || reloc_section == N64Recomp::SectionAbsolute) {
|
||||
bool ref_section_relocatable = context.is_reference_section_relocatable(reloc.target_section);
|
||||
uint32_t ref_section_vram = context.get_reference_section_vram(reloc.target_section);
|
||||
// Resolve HI16 and LO16 reference symbol relocs to non-relocatable sections by patching the instruction immediate.
|
||||
if (!ref_section_relocatable && (reloc_type == N64Recomp::RelocType::R_MIPS_HI16 || reloc_type == N64Recomp::RelocType::R_MIPS_LO16)) {
|
||||
uint32_t full_immediate = reloc.target_section_offset + ref_section_vram;
|
||||
|
||||
if (reloc_type == N64Recomp::RelocType::R_MIPS_HI16) {
|
||||
imm = (full_immediate >> 16) + ((full_immediate >> 15) & 1);
|
||||
}
|
||||
else if (reloc_type == N64Recomp::RelocType::R_MIPS_LO16) {
|
||||
imm = full_immediate & 0xFFFF;
|
||||
}
|
||||
|
||||
// The reloc has been processed, so set it to none to prevent it getting processed a second time during instruction code generation.
|
||||
reloc_type = N64Recomp::RelocType::R_MIPS_NONE;
|
||||
reloc_reference_symbol = (size_t)-1;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Repoint bss relocations at their non-bss counterpart section.
|
||||
if (reloc_section != N64Recomp::SectionSelf && reloc_section == section.bss_section_index) {
|
||||
reloc_section = func.section_index;
|
||||
}
|
||||
// Repoint bss relocations at their non-bss counterpart section.
|
||||
auto find_bss_it = context.bss_section_to_section.find(reloc_section);
|
||||
if (find_bss_it != context.bss_section_to_section.end()) {
|
||||
reloc_section = find_bss_it->second;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -219,7 +221,7 @@ bool process_instruction(const N64Recomp::Context& context, const N64Recomp::Fun
|
|||
if (reloc_index + 1 < section.relocs.size() && next_vram > section.relocs[reloc_index].address) {
|
||||
next_reloc_index++;
|
||||
}
|
||||
if (!process_instruction(context, func, stats, skipped_insns, instr_index + 1, instructions, output_file, false, false, link_branch_index, next_reloc_index, dummy_needs_link_branch, dummy_is_branch_likely, static_funcs_out)) {
|
||||
if (!process_instruction(context, func, stats, skipped_insns, instr_index + 1, instructions, output_file, false, false, link_branch_index, next_reloc_index, dummy_needs_link_branch, dummy_is_branch_likely, tag_reference_relocs, static_funcs_out)) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
|
@ -333,7 +335,7 @@ bool process_instruction(const N64Recomp::Context& context, const N64Recomp::Fun
|
|||
if (reloc_index + 1 < section.relocs.size() && next_vram > section.relocs[reloc_index].address) {
|
||||
next_reloc_index++;
|
||||
}
|
||||
if (!process_instruction(context, func, stats, skipped_insns, instr_index + 1, instructions, output_file, true, false, link_branch_index, next_reloc_index, dummy_needs_link_branch, dummy_is_branch_likely, static_funcs_out)) {
|
||||
if (!process_instruction(context, func, stats, skipped_insns, instr_index + 1, instructions, output_file, true, false, link_branch_index, next_reloc_index, dummy_needs_link_branch, dummy_is_branch_likely, tag_reference_relocs, static_funcs_out)) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
|
@ -503,7 +505,7 @@ bool process_instruction(const N64Recomp::Context& context, const N64Recomp::Fun
|
|||
if (reloc_index + 1 < section.relocs.size() && next_vram > section.relocs[reloc_index].address) {
|
||||
next_reloc_index++;
|
||||
}
|
||||
if (!process_instruction(context, func, stats, skipped_insns, instr_index + 1, instructions, output_file, false, false, link_branch_index, next_reloc_index, dummy_needs_link_branch, dummy_is_branch_likely, static_funcs_out)) {
|
||||
if (!process_instruction(context, func, stats, skipped_insns, instr_index + 1, instructions, output_file, false, false, link_branch_index, next_reloc_index, dummy_needs_link_branch, dummy_is_branch_likely, tag_reference_relocs, static_funcs_out)) {
|
||||
return false;
|
||||
}
|
||||
print_indent();
|
||||
|
|
@ -582,6 +584,7 @@ bool process_instruction(const N64Recomp::Context& context, const N64Recomp::Fun
|
|||
instruction_context.ft = ft;
|
||||
instruction_context.cop1_cs = cop1_cs;
|
||||
instruction_context.imm16 = imm;
|
||||
instruction_context.reloc_tag_as_reference = (reloc_reference_symbol != (size_t)-1) && tag_reference_relocs;
|
||||
instruction_context.reloc_type = reloc_type;
|
||||
instruction_context.reloc_section_index = reloc_section;
|
||||
instruction_context.reloc_target_section_offset = reloc_target_section_offset;
|
||||
|
|
@ -730,7 +733,7 @@ bool process_instruction(const N64Recomp::Context& context, const N64Recomp::Fun
|
|||
return true;
|
||||
}
|
||||
|
||||
bool N64Recomp::recompile_function(const N64Recomp::Context& context, const N64Recomp::Function& func, std::ofstream& output_file, std::span<std::vector<uint32_t>> static_funcs_out) {
|
||||
bool N64Recomp::recompile_function(const N64Recomp::Context& context, const N64Recomp::Function& func, std::ofstream& output_file, std::span<std::vector<uint32_t>> static_funcs_out, bool tag_reference_relocs) {
|
||||
//fmt::print("Recompiling {}\n", func.name);
|
||||
std::vector<rabbitizer::InstructionCpu> instructions;
|
||||
|
||||
|
|
@ -813,7 +816,7 @@ bool N64Recomp::recompile_function(const N64Recomp::Context& context, const N64R
|
|||
}
|
||||
|
||||
// Process the current instruction and check for errors
|
||||
if (process_instruction(context, func, stats, skipped_insns, instr_index, instructions, output_file, false, needs_link_branch, num_link_branches, reloc_index, needs_link_branch, is_branch_likely, static_funcs_out) == false) {
|
||||
if (process_instruction(context, func, stats, skipped_insns, instr_index, instructions, output_file, false, needs_link_branch, num_link_branches, reloc_index, needs_link_branch, is_branch_likely, tag_reference_relocs, static_funcs_out) == false) {
|
||||
fmt::print(stderr, "Error in recompiling {}, clearing output file\n", func.name);
|
||||
output_file.clear();
|
||||
return false;
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue