diff --git a/include/generator.h b/include/generator.h index 486cd09..3614ddc 100644 --- a/include/generator.h +++ b/include/generator.h @@ -1,10 +1,10 @@ #ifndef __GENERATOR_H__ #define __GENERATOR_H__ -#include "recomp_port.h" +#include "n64recomp.h" #include "operations.h" -namespace RecompPort { +namespace N64Recomp { struct InstructionContext { int rd; int rs; diff --git a/include/recomp_port.h b/include/n64recomp.h similarity index 99% rename from include/recomp_port.h rename to include/n64recomp.h index ff5407b..42f0ffd 100644 --- a/include/recomp_port.h +++ b/include/n64recomp.h @@ -21,7 +21,7 @@ constexpr uint32_t byteswap(uint32_t val) { } #endif -namespace RecompPort { +namespace N64Recomp { struct Function { uint32_t vram; uint32_t rom; diff --git a/include/operations.h b/include/operations.h index cda57e6..5cb407e 100644 --- a/include/operations.h +++ b/include/operations.h @@ -5,7 +5,7 @@ #include "rabbitizer.hpp" -namespace RecompPort { +namespace N64Recomp { using InstrId = rabbitizer::InstrId::UniqueId; using Cop0Reg = rabbitizer::Registers::Cpu::Cop0; diff --git a/src/analysis.cpp b/src/analysis.cpp index 36cff76..0310875 100644 --- a/src/analysis.cpp +++ b/src/analysis.cpp @@ -4,7 +4,7 @@ #include "rabbitizer.hpp" #include "fmt/format.h" -#include "recomp_port.h" +#include "n64recomp.h" #include "analysis.h" extern "C" const char* RabbitizerRegister_getNameGpr(uint8_t regValue); @@ -50,7 +50,7 @@ struct RegState { using InstrId = rabbitizer::InstrId::UniqueId; using RegId = rabbitizer::Registers::Cpu::GprO32; -bool analyze_instruction(const rabbitizer::InstructionCpu& instr, const RecompPort::Function& func, RecompPort::FunctionStats& stats, +bool analyze_instruction(const rabbitizer::InstructionCpu& instr, const N64Recomp::Function& func, N64Recomp::FunctionStats& stats, RegState reg_states[32], std::vector& stack_states) { // Temporary register state for tracking the register being operated on RegState temp{}; @@ -220,8 +220,8 @@ bool analyze_instruction(const rabbitizer::InstructionCpu& instr, const RecompPo return true; } -bool RecompPort::analyze_function(const RecompPort::Context& context, const RecompPort::Function& func, - const std::vector& instructions, RecompPort::FunctionStats& stats) { +bool N64Recomp::analyze_function(const N64Recomp::Context& context, const N64Recomp::Function& func, + const std::vector& instructions, N64Recomp::FunctionStats& stats) { // Create a state to track each register (r0 won't be used) RegState reg_states[32] {}; std::vector stack_states{}; diff --git a/src/analysis.h b/src/analysis.h index b450660..eafd1e7 100644 --- a/src/analysis.h +++ b/src/analysis.h @@ -4,9 +4,9 @@ #include #include -#include "recomp_port.h" +#include "n64recomp.h" -namespace RecompPort { +namespace N64Recomp { struct JumpTable { uint32_t vram; uint32_t addend_reg; diff --git a/src/cgenerator.cpp b/src/cgenerator.cpp index 78410a0..c4602cf 100644 --- a/src/cgenerator.cpp +++ b/src/cgenerator.cpp @@ -10,11 +10,11 @@ struct BinaryOpFields { std::string func_string; std::string infix_string; }; std::vector c_op_fields = []() { std::vector ret{}; - ret.resize(static_cast(RecompPort::BinaryOpType::COUNT)); + ret.resize(static_cast(N64Recomp::BinaryOpType::COUNT)); std::vector ops_setup{}; - ops_setup.resize(static_cast(RecompPort::BinaryOpType::COUNT)); + ops_setup.resize(static_cast(N64Recomp::BinaryOpType::COUNT)); - auto setup_op = [&ret, &ops_setup](RecompPort::BinaryOpType op_type, const std::string& func_string, const std::string& infix_string) { + auto setup_op = [&ret, &ops_setup](N64Recomp::BinaryOpType op_type, const std::string& func_string, const std::string& infix_string) { size_t index = static_cast(op_type); // Prevent setting up an operation twice. assert(ops_setup[index] == false && "Operation already setup!"); @@ -22,47 +22,47 @@ std::vector c_op_fields = []() { ret[index] = { func_string, infix_string }; }; - setup_op(RecompPort::BinaryOpType::Add32, "ADD32", ""); - setup_op(RecompPort::BinaryOpType::Sub32, "SUB32", ""); - setup_op(RecompPort::BinaryOpType::Add64, "", "+"); - setup_op(RecompPort::BinaryOpType::Sub64, "", "-"); - setup_op(RecompPort::BinaryOpType::And64, "", "&"); - setup_op(RecompPort::BinaryOpType::AddFloat, "", "+"); - setup_op(RecompPort::BinaryOpType::AddDouble, "", "+"); - setup_op(RecompPort::BinaryOpType::SubFloat, "", "-"); - setup_op(RecompPort::BinaryOpType::SubDouble, "", "-"); - setup_op(RecompPort::BinaryOpType::MulFloat, "MUL_S", ""); - setup_op(RecompPort::BinaryOpType::MulDouble, "MUL_D", ""); - setup_op(RecompPort::BinaryOpType::DivFloat, "DIV_S", ""); - setup_op(RecompPort::BinaryOpType::DivDouble, "DIV_D", ""); - setup_op(RecompPort::BinaryOpType::Or64, "", "|"); - setup_op(RecompPort::BinaryOpType::Nor64, "~", "|"); - setup_op(RecompPort::BinaryOpType::Xor64, "", "^"); - setup_op(RecompPort::BinaryOpType::Sll32, "S32", "<<"); - setup_op(RecompPort::BinaryOpType::Sll64, "", "<<"); - setup_op(RecompPort::BinaryOpType::Srl32, "S32", ">>"); - setup_op(RecompPort::BinaryOpType::Srl64, "", ">>"); - setup_op(RecompPort::BinaryOpType::Sra32, "S32", ">>"); // Arithmetic aspect will be taken care of by unary op for first operand. - setup_op(RecompPort::BinaryOpType::Sra64, "", ">>"); // Arithmetic aspect will be taken care of by unary op for first operand. - setup_op(RecompPort::BinaryOpType::Equal, "", "=="); - setup_op(RecompPort::BinaryOpType::NotEqual, "", "!="); - setup_op(RecompPort::BinaryOpType::Less, "", "<"); - setup_op(RecompPort::BinaryOpType::LessEq, "", "<="); - setup_op(RecompPort::BinaryOpType::Greater, "", ">"); - setup_op(RecompPort::BinaryOpType::GreaterEq, "", ">="); - setup_op(RecompPort::BinaryOpType::LD, "LD", ""); - setup_op(RecompPort::BinaryOpType::LW, "MEM_W", ""); - setup_op(RecompPort::BinaryOpType::LWU, "MEM_WU", ""); - setup_op(RecompPort::BinaryOpType::LH, "MEM_H", ""); - setup_op(RecompPort::BinaryOpType::LHU, "MEM_HU", ""); - setup_op(RecompPort::BinaryOpType::LB, "MEM_B", ""); - setup_op(RecompPort::BinaryOpType::LBU, "MEM_BU", ""); - setup_op(RecompPort::BinaryOpType::LDL, "do_ldl", ""); - setup_op(RecompPort::BinaryOpType::LDR, "do_ldr", ""); - setup_op(RecompPort::BinaryOpType::LWL, "do_lwl", ""); - setup_op(RecompPort::BinaryOpType::LWR, "do_lwr", ""); - setup_op(RecompPort::BinaryOpType::True, "", ""); - setup_op(RecompPort::BinaryOpType::False, "", ""); + setup_op(N64Recomp::BinaryOpType::Add32, "ADD32", ""); + setup_op(N64Recomp::BinaryOpType::Sub32, "SUB32", ""); + setup_op(N64Recomp::BinaryOpType::Add64, "", "+"); + setup_op(N64Recomp::BinaryOpType::Sub64, "", "-"); + setup_op(N64Recomp::BinaryOpType::And64, "", "&"); + setup_op(N64Recomp::BinaryOpType::AddFloat, "", "+"); + setup_op(N64Recomp::BinaryOpType::AddDouble, "", "+"); + setup_op(N64Recomp::BinaryOpType::SubFloat, "", "-"); + setup_op(N64Recomp::BinaryOpType::SubDouble, "", "-"); + setup_op(N64Recomp::BinaryOpType::MulFloat, "MUL_S", ""); + setup_op(N64Recomp::BinaryOpType::MulDouble, "MUL_D", ""); + setup_op(N64Recomp::BinaryOpType::DivFloat, "DIV_S", ""); + setup_op(N64Recomp::BinaryOpType::DivDouble, "DIV_D", ""); + setup_op(N64Recomp::BinaryOpType::Or64, "", "|"); + setup_op(N64Recomp::BinaryOpType::Nor64, "~", "|"); + setup_op(N64Recomp::BinaryOpType::Xor64, "", "^"); + setup_op(N64Recomp::BinaryOpType::Sll32, "S32", "<<"); + setup_op(N64Recomp::BinaryOpType::Sll64, "", "<<"); + setup_op(N64Recomp::BinaryOpType::Srl32, "S32", ">>"); + setup_op(N64Recomp::BinaryOpType::Srl64, "", ">>"); + setup_op(N64Recomp::BinaryOpType::Sra32, "S32", ">>"); // Arithmetic aspect will be taken care of by unary op for first operand. + setup_op(N64Recomp::BinaryOpType::Sra64, "", ">>"); // Arithmetic aspect will be taken care of by unary op for first operand. + setup_op(N64Recomp::BinaryOpType::Equal, "", "=="); + setup_op(N64Recomp::BinaryOpType::NotEqual, "", "!="); + setup_op(N64Recomp::BinaryOpType::Less, "", "<"); + setup_op(N64Recomp::BinaryOpType::LessEq, "", "<="); + setup_op(N64Recomp::BinaryOpType::Greater, "", ">"); + setup_op(N64Recomp::BinaryOpType::GreaterEq, "", ">="); + setup_op(N64Recomp::BinaryOpType::LD, "LD", ""); + setup_op(N64Recomp::BinaryOpType::LW, "MEM_W", ""); + setup_op(N64Recomp::BinaryOpType::LWU, "MEM_WU", ""); + setup_op(N64Recomp::BinaryOpType::LH, "MEM_H", ""); + setup_op(N64Recomp::BinaryOpType::LHU, "MEM_HU", ""); + setup_op(N64Recomp::BinaryOpType::LB, "MEM_B", ""); + setup_op(N64Recomp::BinaryOpType::LBU, "MEM_BU", ""); + setup_op(N64Recomp::BinaryOpType::LDL, "do_ldl", ""); + setup_op(N64Recomp::BinaryOpType::LDR, "do_ldr", ""); + setup_op(N64Recomp::BinaryOpType::LWL, "do_lwl", ""); + setup_op(N64Recomp::BinaryOpType::LWR, "do_lwr", ""); + setup_op(N64Recomp::BinaryOpType::True, "", ""); + setup_op(N64Recomp::BinaryOpType::False, "", ""); // Ensure every operation has been setup. for (char is_set : ops_setup) { @@ -100,22 +100,22 @@ std::string fpr_u64_to_string(int fpr_index) { return fmt::format("ctx->f{}.u64", fpr_index); } -std::string unsigned_reloc(const RecompPort::InstructionContext& context) { +std::string unsigned_reloc(const N64Recomp::InstructionContext& context) { switch (context.reloc_type) { - case RecompPort::RelocType::R_MIPS_HI16: + case N64Recomp::RelocType::R_MIPS_HI16: return fmt::format("RELOC_HI16({}, {:#X})", context.reloc_section_index, context.reloc_target_section_offset); - case RecompPort::RelocType::R_MIPS_LO16: + case N64Recomp::RelocType::R_MIPS_LO16: return fmt::format("RELOC_LO16({}, {:#X})", context.reloc_section_index, context.reloc_target_section_offset); default: throw std::runtime_error(fmt::format("Unexpected reloc type {}\n", static_cast(context.reloc_type))); } } -std::string signed_reloc(const RecompPort::InstructionContext& context) { +std::string signed_reloc(const N64Recomp::InstructionContext& context) { return "(int16_t)" + unsigned_reloc(context); } -void RecompPort::CGenerator::get_operand_string(Operand operand, UnaryOpType operation, const InstructionContext& context, std::string& operand_string) const { +void N64Recomp::CGenerator::get_operand_string(Operand operand, UnaryOpType operation, const InstructionContext& context, std::string& operand_string) const { switch (operand) { case Operand::Rd: operand_string = gpr_to_string(context.rd); @@ -172,7 +172,7 @@ void RecompPort::CGenerator::get_operand_string(Operand operand, UnaryOpType ope operand_string = fpr_u64_to_string(context.ft); break; case Operand::ImmU16: - if (context.reloc_type != RecompPort::RelocType::R_MIPS_NONE) { + if (context.reloc_type != N64Recomp::RelocType::R_MIPS_NONE) { operand_string = unsigned_reloc(context); } else { @@ -180,7 +180,7 @@ void RecompPort::CGenerator::get_operand_string(Operand operand, UnaryOpType ope } break; case Operand::ImmS16: - if (context.reloc_type != RecompPort::RelocType::R_MIPS_NONE) { + if (context.reloc_type != N64Recomp::RelocType::R_MIPS_NONE) { operand_string = signed_reloc(context); } else { @@ -311,12 +311,12 @@ void RecompPort::CGenerator::get_operand_string(Operand operand, UnaryOpType ope } } -void RecompPort::CGenerator::get_notation(BinaryOpType op_type, std::string& func_string, std::string& infix_string) const { +void N64Recomp::CGenerator::get_notation(BinaryOpType op_type, std::string& func_string, std::string& infix_string) const { func_string = c_op_fields[static_cast(op_type)].func_string; infix_string = c_op_fields[static_cast(op_type)].infix_string; } -void RecompPort::CGenerator::get_binary_expr_string(BinaryOpType type, const BinaryOperands& operands, const InstructionContext& ctx, const std::string& output, std::string& expr_string) const { +void N64Recomp::CGenerator::get_binary_expr_string(BinaryOpType type, const BinaryOperands& operands, const InstructionContext& ctx, const std::string& output, std::string& expr_string) const { thread_local std::string input_a{}; thread_local std::string input_b{}; thread_local std::string func_string{}; @@ -363,7 +363,7 @@ void RecompPort::CGenerator::get_binary_expr_string(BinaryOpType type, const Bin } } -void RecompPort::CGenerator::emit_branch_condition(std::ostream& output_file, const ConditionalBranchOp& op, const InstructionContext& ctx) const { +void N64Recomp::CGenerator::emit_branch_condition(std::ostream& output_file, const ConditionalBranchOp& op, const InstructionContext& ctx) const { // Thread local variables to prevent allocations when possible. // TODO these thread locals probably don't actually help right now, so figure out a better way to prevent allocations. thread_local std::string expr_string{}; @@ -371,19 +371,19 @@ void RecompPort::CGenerator::emit_branch_condition(std::ostream& output_file, co fmt::print(output_file, "if ({}) {{\n", expr_string); } -void RecompPort::CGenerator::emit_branch_close(std::ostream& output_file) const { +void N64Recomp::CGenerator::emit_branch_close(std::ostream& output_file) const { fmt::print(output_file, " }}\n"); } -void RecompPort::CGenerator::emit_check_fr(std::ostream& output_file, int fpr) const { +void N64Recomp::CGenerator::emit_check_fr(std::ostream& output_file, int fpr) const { fmt::print(output_file, "CHECK_FR(ctx, {});\n ", fpr); } -void RecompPort::CGenerator::emit_check_nan(std::ostream& output_file, int fpr, bool is_double) const { +void N64Recomp::CGenerator::emit_check_nan(std::ostream& output_file, int fpr, bool is_double) const { fmt::print(output_file, "NAN_CHECK(ctx->f{}.{}); ", fpr, is_double ? "d" : "fl"); } -void RecompPort::CGenerator::process_binary_op(std::ostream& output_file, const BinaryOp& op, const InstructionContext& ctx) const { +void N64Recomp::CGenerator::process_binary_op(std::ostream& output_file, const BinaryOp& op, const InstructionContext& ctx) const { // Thread local variables to prevent allocations when possible. // TODO these thread locals probably don't actually help right now, so figure out a better way to prevent allocations. thread_local std::string output{}; @@ -393,7 +393,7 @@ void RecompPort::CGenerator::process_binary_op(std::ostream& output_file, const fmt::print(output_file, "{} = {};\n", output, expression); } -void RecompPort::CGenerator::process_unary_op(std::ostream& output_file, const UnaryOp& op, const InstructionContext& ctx) const { +void N64Recomp::CGenerator::process_unary_op(std::ostream& output_file, const UnaryOp& op, const InstructionContext& ctx) const { // Thread local variables to prevent allocations when possible. // TODO these thread locals probably don't actually help right now, so figure out a better way to prevent allocations. thread_local std::string output{}; @@ -404,7 +404,7 @@ void RecompPort::CGenerator::process_unary_op(std::ostream& output_file, const U fmt::print(output_file, "{} = {};\n", output, input); } -void RecompPort::CGenerator::process_store_op(std::ostream& output_file, const StoreOp& op, const InstructionContext& ctx) const { +void N64Recomp::CGenerator::process_store_op(std::ostream& output_file, const StoreOp& op, const InstructionContext& ctx) const { // Thread local variables to prevent allocations when possible. // TODO these thread locals probably don't actually help right now, so figure out a better way to prevent allocations. thread_local std::string base_str{}; diff --git a/src/config.cpp b/src/config.cpp index fb2b6b3..2fc0b58 100644 --- a/src/config.cpp +++ b/src/config.cpp @@ -3,7 +3,7 @@ #include #include "fmt/format.h" #include "config.h" -#include "recomp_port.h" +#include "n64recomp.h" std::filesystem::path concat_if_not_empty(const std::filesystem::path& parent, const std::filesystem::path& child) { if (!child.empty()) { @@ -12,8 +12,8 @@ std::filesystem::path concat_if_not_empty(const std::filesystem::path& parent, c return child; } -std::vector get_manual_funcs(const toml::array* manual_funcs_array) { - std::vector ret; +std::vector get_manual_funcs(const toml::array* manual_funcs_array) { + std::vector ret; // Reserve room for all the funcs in the map. ret.reserve(manual_funcs_array->size()); @@ -104,8 +104,8 @@ std::vector get_ignored_funcs(const toml::table* patches_data) { return ignored_funcs; } -std::vector get_func_sizes(const toml::table* patches_data) { - std::vector func_sizes{}; +std::vector get_func_sizes(const toml::table* patches_data) { + std::vector func_sizes{}; // Check if the func size array exists. const toml::node_view funcs_data = (*patches_data)["function_sizes"]; @@ -143,8 +143,8 @@ std::vector get_func_sizes(const toml::table* patches_ return func_sizes; } -std::vector get_instruction_patches(const toml::table* patches_data) { - std::vector ret; +std::vector get_instruction_patches(const toml::table* patches_data) { + std::vector ret; // Check if the instruction patch array exists. const toml::node_view insn_patch_data = (*patches_data)["instruction"]; @@ -172,7 +172,7 @@ std::vector get_instruction_patches(const toml::ta throw toml::parse_error("Instruction patch is not word-aligned", el.source()); } - ret.push_back(RecompPort::InstructionPatch{ + ret.push_back(N64Recomp::InstructionPatch{ .func_name = func_name.value(), .vram = (int32_t)vram.value(), .value = value.value(), @@ -187,8 +187,8 @@ std::vector get_instruction_patches(const toml::ta return ret; } -std::vector get_function_hooks(const toml::table* patches_data) { - std::vector ret; +std::vector get_function_hooks(const toml::table* patches_data) { + std::vector ret; // Check if the function hook array exists. const toml::node_view func_hook_data = (*patches_data)["hook"]; @@ -216,7 +216,7 @@ std::vector get_function_hooks(const toml::table* patc throw toml::parse_error("before_vram is not word-aligned", el.source()); } - ret.push_back(RecompPort::FunctionHook{ + ret.push_back(N64Recomp::FunctionHook{ .func_name = func_name.value(), .before_vram = before_vram.has_value() ? (int32_t)before_vram.value() : 0, .text = text.value(), @@ -231,7 +231,7 @@ std::vector get_function_hooks(const toml::table* patc return ret; } -RecompPort::Config::Config(const char* path) { +N64Recomp::Config::Config(const char* path) { // Start this config out as bad so that it has to finish parsing without errors to be good. entrypoint = 0; bad = true; @@ -418,27 +418,27 @@ RecompPort::Config::Config(const char* path) { bad = false; } -const std::unordered_map reloc_type_name_map { - { "R_MIPS_NONE", RecompPort::RelocType::R_MIPS_NONE }, - { "R_MIPS_16", RecompPort::RelocType::R_MIPS_16 }, - { "R_MIPS_32", RecompPort::RelocType::R_MIPS_32 }, - { "R_MIPS_REL32", RecompPort::RelocType::R_MIPS_REL32 }, - { "R_MIPS_26", RecompPort::RelocType::R_MIPS_26 }, - { "R_MIPS_HI16", RecompPort::RelocType::R_MIPS_HI16 }, - { "R_MIPS_LO16", RecompPort::RelocType::R_MIPS_LO16 }, - { "R_MIPS_GPREL16", RecompPort::RelocType::R_MIPS_GPREL16 }, +const std::unordered_map reloc_type_name_map { + { "R_MIPS_NONE", N64Recomp::RelocType::R_MIPS_NONE }, + { "R_MIPS_16", N64Recomp::RelocType::R_MIPS_16 }, + { "R_MIPS_32", N64Recomp::RelocType::R_MIPS_32 }, + { "R_MIPS_REL32", N64Recomp::RelocType::R_MIPS_REL32 }, + { "R_MIPS_26", N64Recomp::RelocType::R_MIPS_26 }, + { "R_MIPS_HI16", N64Recomp::RelocType::R_MIPS_HI16 }, + { "R_MIPS_LO16", N64Recomp::RelocType::R_MIPS_LO16 }, + { "R_MIPS_GPREL16", N64Recomp::RelocType::R_MIPS_GPREL16 }, }; -RecompPort::RelocType reloc_type_from_name(const std::string& reloc_type_name) { +N64Recomp::RelocType reloc_type_from_name(const std::string& reloc_type_name) { auto find_it = reloc_type_name_map.find(reloc_type_name); if (find_it != reloc_type_name_map.end()) { return find_it->second; } - return RecompPort::RelocType::R_MIPS_NONE; + return N64Recomp::RelocType::R_MIPS_NONE; } -bool RecompPort::Context::from_symbol_file(const std::filesystem::path& symbol_file_path, std::vector&& rom, RecompPort::Context& out, bool with_relocs) { - RecompPort::Context ret{}; +bool N64Recomp::Context::from_symbol_file(const std::filesystem::path& symbol_file_path, std::vector&& rom, N64Recomp::Context& out, bool with_relocs) { + N64Recomp::Context ret{}; try { const toml::table config_data = toml::parse_file(symbol_file_path.u8string()); @@ -592,15 +592,15 @@ bool RecompPort::Context::from_symbol_file(const std::filesystem::path& symbol_f return true; } -void RecompPort::Context::import_reference_context(const RecompPort::Context& reference_context) { +void N64Recomp::Context::import_reference_context(const N64Recomp::Context& reference_context) { reference_sections.resize(reference_context.sections.size()); reference_symbols.reserve(reference_context.functions.size()); reference_symbol_names.reserve(reference_context.functions.size()); // Copy the reference context's sections into the real context's reference sections. for (size_t section_index = 0; section_index < reference_context.sections.size(); section_index++) { - const RecompPort::Section& section_in = reference_context.sections[section_index]; - RecompPort::ReferenceSection& section_out = reference_sections[section_index]; + const N64Recomp::Section& section_in = reference_context.sections[section_index]; + N64Recomp::ReferenceSection& section_out = reference_sections[section_index]; section_out.rom_addr = section_in.rom_addr; section_out.ram_addr = section_in.ram_addr; @@ -609,12 +609,12 @@ void RecompPort::Context::import_reference_context(const RecompPort::Context& re } // Copy the functions from the reference context into the reference context's function map. - for (const RecompPort::Function& func_in: reference_context.functions) { - const RecompPort::Section& func_section = reference_context.sections[func_in.section_index]; + for (const N64Recomp::Function& func_in: reference_context.functions) { + const N64Recomp::Section& func_section = reference_context.sections[func_in.section_index]; reference_symbols_by_name.emplace(func_in.name, reference_symbols.size()); - reference_symbols.emplace_back(RecompPort::ReferenceSymbol{ + reference_symbols.emplace_back(N64Recomp::ReferenceSymbol{ .section_index = func_in.section_index, .section_offset = func_in.vram - static_cast(func_section.ram_addr), .is_function = true @@ -624,7 +624,7 @@ void RecompPort::Context::import_reference_context(const RecompPort::Context& re } // Reads a data symbol file and adds its contents into this context's reference data symbols. -bool RecompPort::Context::read_data_reference_syms(const std::filesystem::path& data_syms_file_path) { +bool N64Recomp::Context::read_data_reference_syms(const std::filesystem::path& data_syms_file_path) { try { const toml::table data_syms_file_data = toml::parse_file(data_syms_file_path.u8string()); const toml::node_view data_sections_value = data_syms_file_data["section"]; @@ -655,7 +655,7 @@ bool RecompPort::Context::read_data_reference_syms(const std::filesystem::path& uint16_t ref_section_index; if (!rom_addr.has_value()) { - ref_section_index = RecompPort::SectionAbsolute; // Non-relocatable bss section or absolute symbols, mark this as an absolute symbol + ref_section_index = N64Recomp::SectionAbsolute; // Non-relocatable bss section or absolute symbols, mark this as an absolute symbol } else if (rom_addr.value() > 0xFFFFFFFF) { throw toml::parse_error("Section has invalid ROM address", el.source()); @@ -667,7 +667,7 @@ bool RecompPort::Context::read_data_reference_syms(const std::filesystem::path& ref_section_index = find_section_it->second; } else { - ref_section_index = RecompPort::SectionAbsolute; // Not in the function symbol reference file, so this section can be treated as non-relocatable. + ref_section_index = N64Recomp::SectionAbsolute; // Not in the function symbol reference file, so this section can be treated as non-relocatable. } } @@ -677,10 +677,10 @@ bool RecompPort::Context::read_data_reference_syms(const std::filesystem::path& .size = 0, .relocatable = 0 }; - const ReferenceSection& ref_section = ref_section_index == RecompPort::SectionAbsolute ? dummy_absolute_section : this->reference_sections[ref_section_index]; + const ReferenceSection& ref_section = ref_section_index == N64Recomp::SectionAbsolute ? dummy_absolute_section : this->reference_sections[ref_section_index]; // Sanity check this section against the matching one in the function reference symbol file if one exists. - if (ref_section_index != RecompPort::SectionAbsolute) { + if (ref_section_index != N64Recomp::SectionAbsolute) { if (ref_section.ram_addr != vram_addr.value()) { throw toml::parse_error("Section vram address differs from matching ROM address section in the function symbol reference file", el.source()); } diff --git a/src/config.h b/src/config.h index 2e2e15b..988c00b 100644 --- a/src/config.h +++ b/src/config.h @@ -5,7 +5,7 @@ #include #include -namespace RecompPort { +namespace N64Recomp { struct InstructionPatch { std::string func_name; int32_t vram; diff --git a/src/main.cpp b/src/main.cpp index 84248d8..b74ddc7 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -10,7 +10,7 @@ #include "fmt/format.h" #include "fmt/ostream.h" -#include "recomp_port.h" +#include "n64recomp.h" #include "config.h" #include @@ -680,7 +680,7 @@ struct DataSymbol { DataSymbol(uint32_t vram, std::string&& name) : vram(vram), name(std::move(name)) {} }; -bool read_symbols(RecompPort::Context& context, const ELFIO::elfio& elf_file, ELFIO::section* symtab_section, uint32_t entrypoint, bool has_entrypoint, bool use_absolute_symbols, bool dumping_context, std::unordered_map>& data_syms) { +bool read_symbols(N64Recomp::Context& context, const ELFIO::elfio& elf_file, ELFIO::section* symtab_section, uint32_t entrypoint, bool has_entrypoint, bool use_absolute_symbols, bool dumping_context, std::unordered_map>& data_syms) { bool found_entrypoint_func = false; ELFIO::symbol_section_accessor symbols{ elf_file, symtab_section }; fmt::print("Num symbols: {}\n", symbols.get_symbols_num()); @@ -692,7 +692,7 @@ bool read_symbols(RecompPort::Context& context, const ELFIO::elfio& elf_file, EL if (dumping_context) { // Process bss and reloc sections for (size_t cur_section_index = 0; cur_section_index < context.sections.size(); cur_section_index++) { - const RecompPort::Section& cur_section = context.sections[cur_section_index]; + const N64Recomp::Section& cur_section = context.sections[cur_section_index]; // Check if a bss section was found that corresponds with this section. if (cur_section.bss_section_index != (uint16_t)-1) { bss_section_to_target_section[cur_section.bss_section_index] = cur_section_index; @@ -844,7 +844,7 @@ bool read_symbols(RecompPort::Context& context, const ELFIO::elfio& elf_file, EL // Place this symbol in the absolute symbol list if it's in the absolute section. uint16_t target_section_index = section_index; if (section_index == ELFIO::SHN_ABS) { - target_section_index = RecompPort::SectionAbsolute; + target_section_index = N64Recomp::SectionAbsolute; } else if (section_index >= context.sections.size()) { fmt::print("Symbol \"{}\" not in a valid section ({})\n", name, section_index); @@ -867,7 +867,7 @@ bool read_symbols(RecompPort::Context& context, const ELFIO::elfio& elf_file, EL return found_entrypoint_func; } -void add_manual_functions(RecompPort::Context& context, const ELFIO::elfio& elf_file, const std::vector& manual_funcs) { +void add_manual_functions(N64Recomp::Context& context, const ELFIO::elfio& elf_file, const std::vector& manual_funcs) { auto exit_failure = [](const std::string& error_str) { fmt::vprint(stderr, error_str, fmt::make_format_args()); std::exit(EXIT_FAILURE); @@ -881,7 +881,7 @@ void add_manual_functions(RecompPort::Context& context, const ELFIO::elfio& elf_ section_indices_by_name.emplace(context.sections[i].name, i); } - for (const RecompPort::ManualFunction& cur_func_def : manual_funcs) { + for (const N64Recomp::ManualFunction& cur_func_def : manual_funcs) { const auto section_find_it = section_indices_by_name.find(cur_func_def.section_name); if (section_find_it == section_indices_by_name.end()) { exit_failure(fmt::format("Manual function {} specified with section {}, which doesn't exist!\n", cur_func_def.func_name, cur_func_def.section_name)); @@ -946,7 +946,7 @@ std::optional get_segment(const std::vector& segments, ELF return std::nullopt; } -ELFIO::section* read_sections(RecompPort::Context& context, const RecompPort::Config& config, const ELFIO::elfio& elf_file) { +ELFIO::section* read_sections(N64Recomp::Context& context, const N64Recomp::Config& config, const ELFIO::elfio& elf_file) { ELFIO::section* symtab_section = nullptr; std::vector segments{}; segments.resize(elf_file.segments.size()); @@ -1076,7 +1076,7 @@ ELFIO::section* read_sections(RecompPort::Context& context, const RecompPort::Co // Process bss and reloc sections for (size_t section_index = 0; section_index < context.sections.size(); section_index++) { - RecompPort::Section& section_out = context.sections[section_index]; + N64Recomp::Section& section_out = context.sections[section_index]; // Check if a bss section was found that corresponds with this section auto bss_find = bss_sections_by_name.find(section_out.name); if (bss_find != bss_sections_by_name.end()) { @@ -1106,7 +1106,7 @@ ELFIO::section* read_sections(RecompPort::Context& context, const RecompPort::Co ELFIO::Elf_Sxword bad_rel_addend; // Addends aren't encoded in the reloc, so ignore this one rel_accessor.get_entry(i, rel_offset, rel_symbol, rel_type, bad_rel_addend); - RecompPort::Reloc& reloc_out = section_out.relocs[i]; + N64Recomp::Reloc& reloc_out = section_out.relocs[i]; // Get the real full_immediate by extracting the immediate from the instruction uint32_t reloc_rom_addr = section_out.rom_addr + rel_offset - section_out.ram_addr; @@ -1116,7 +1116,7 @@ ELFIO::section* read_sections(RecompPort::Context& context, const RecompPort::Co reloc_out.address = rel_offset; reloc_out.symbol_index = rel_symbol; - reloc_out.type = static_cast(rel_type); + reloc_out.type = static_cast(rel_type); std::string rel_symbol_name; ELFIO::Elf64_Addr rel_symbol_value; @@ -1151,11 +1151,11 @@ ELFIO::section* read_sections(RecompPort::Context& context, const RecompPort::Co bool target_section_relocatable = false; - if (reloc_out.target_section != RecompPort::SectionAbsolute && context.reference_sections[reloc_out.target_section].relocatable) { + if (reloc_out.target_section != N64Recomp::SectionAbsolute && context.reference_sections[reloc_out.target_section].relocatable) { target_section_relocatable = true; } - if (reloc_out.type == RecompPort::RelocType::R_MIPS_32 && target_section_relocatable) { + if (reloc_out.type == N64Recomp::RelocType::R_MIPS_32 && target_section_relocatable) { fmt::print(stderr, "Cannot reference {} in a statically initialized variable as it's defined in a relocatable section!\n", rel_symbol_name); return nullptr; @@ -1167,7 +1167,7 @@ ELFIO::section* read_sections(RecompPort::Context& context, const RecompPort::Co } // Reloc pairing, see MIPS System V ABI documentation page 4-18 (https://refspecs.linuxfoundation.org/elf/mipsabi.pdf) - if (reloc_out.type == RecompPort::RelocType::R_MIPS_LO16) { + if (reloc_out.type == N64Recomp::RelocType::R_MIPS_LO16) { uint32_t rel_immediate = instr.getProcessedImmediate(); uint32_t full_immediate = (prev_hi_immediate << 16) + (int16_t)rel_immediate; reloc_out.section_offset = full_immediate + rel_symbol_offset - rel_section_vram; @@ -1215,7 +1215,7 @@ ELFIO::section* read_sections(RecompPort::Context& context, const RecompPort::Co prev_lo = false; } - if (reloc_out.type == RecompPort::RelocType::R_MIPS_HI16) { + if (reloc_out.type == N64Recomp::RelocType::R_MIPS_HI16) { uint32_t rel_immediate = instr.getProcessedImmediate(); prev_hi = true; prev_hi_immediate = rel_immediate; @@ -1224,7 +1224,7 @@ ELFIO::section* read_sections(RecompPort::Context& context, const RecompPort::Co prev_hi = false; } - if (reloc_out.type == RecompPort::RelocType::R_MIPS_32) { + if (reloc_out.type == N64Recomp::RelocType::R_MIPS_32) { // The reloc addend is just the existing word before relocation, so the section offset can just be the symbol's section offset. // Incorporating the addend will be handled at load-time. reloc_out.section_offset = rel_symbol_offset; @@ -1232,7 +1232,7 @@ ELFIO::section* read_sections(RecompPort::Context& context, const RecompPort::Co if (reloc_out.reference_symbol) { uint32_t reloc_target_section_addr = 0; - if (reloc_out.target_section != RecompPort::SectionAbsolute) { + if (reloc_out.target_section != N64Recomp::SectionAbsolute) { reloc_target_section_addr = context.reference_sections[reloc_out.target_section].ram_addr; } // Patch the word in the ROM to incorporate the symbol's value. @@ -1241,7 +1241,7 @@ ELFIO::section* read_sections(RecompPort::Context& context, const RecompPort::Co } } - if (reloc_out.type == RecompPort::RelocType::R_MIPS_26) { + if (reloc_out.type == N64Recomp::RelocType::R_MIPS_26) { uint32_t rel_immediate = instr.getProcessedImmediate(); reloc_out.section_offset = rel_immediate + rel_symbol_offset; } @@ -1252,7 +1252,7 @@ ELFIO::section* read_sections(RecompPort::Context& context, const RecompPort::Co // This is safe to do as the entire full_immediate in present in relocs due to the pairing that was done earlier, so the HI16 does not // need to directly preceed the matching LO16 anymore. std::sort(section_out.relocs.begin(), section_out.relocs.end(), - [](const RecompPort::Reloc& a, const RecompPort::Reloc& b) { + [](const N64Recomp::Reloc& a, const N64Recomp::Reloc& b) { return a.address < b.address; } ); @@ -1271,22 +1271,22 @@ for_each_if(Iterator begin, Iterator end, Pred p, Operation op) { } } -void analyze_sections(RecompPort::Context& context, const ELFIO::elfio& elf_file) { - std::vector executable_sections{}; +void analyze_sections(N64Recomp::Context& context, const ELFIO::elfio& elf_file) { + std::vector executable_sections{}; executable_sections.reserve(context.executable_section_count); for_each_if(context.sections.begin(), context.sections.end(), - [](const RecompPort::Section& section) { + [](const N64Recomp::Section& section) { return section.executable && section.rom_addr >= 0x1000; }, - [&](RecompPort::Section& section) { + [&](N64Recomp::Section& section) { executable_sections.push_back(§ion); } ); std::sort(executable_sections.begin(), executable_sections.end(), - [](const RecompPort::Section* a, const RecompPort::Section* b) { + [](const N64Recomp::Section* a, const N64Recomp::Section* b) { return a->ram_addr < b->ram_addr; } ); @@ -1331,7 +1331,7 @@ bool compare_files(const std::filesystem::path& file1_path, const std::filesyste return std::equal(begin1, std::istreambuf_iterator(), begin2); //Second argument is end-of-range iterator } -bool recompile_single_function(const RecompPort::Context& context, const RecompPort::Function& func, const std::string& recomp_include, const std::filesystem::path& output_path, std::span> static_funcs_out) { +bool recompile_single_function(const N64Recomp::Context& context, const N64Recomp::Function& func, const std::string& recomp_include, const std::filesystem::path& output_path, std::span> static_funcs_out) { // Open the temporary output file std::filesystem::path temp_path = output_path; temp_path.replace_extension(".tmp"); @@ -1341,7 +1341,7 @@ bool recompile_single_function(const RecompPort::Context& context, const RecompP return false; } - if (!RecompPort::recompile_function(context, func, recomp_include, output_file, static_funcs_out, true)) { + if (!N64Recomp::recompile_function(context, func, recomp_include, output_file, static_funcs_out, true)) { return false; } @@ -1371,7 +1371,7 @@ std::vector reloc_names { "R_MIPS_GPREL16", }; -void dump_context(const RecompPort::Context& context, const std::unordered_map>& data_syms, const std::filesystem::path& func_path, const std::filesystem::path& data_path) { +void dump_context(const N64Recomp::Context& context, const std::unordered_map>& data_syms, const std::filesystem::path& func_path, const std::filesystem::path& data_path) { std::ofstream func_context_file {func_path}; std::ofstream data_context_file {data_path}; @@ -1401,7 +1401,7 @@ void dump_context(const RecompPort::Context& context, const std::unordered_map& section_funcs = context.section_functions[section_index]; if (!section_funcs.empty()) { print_section(func_context_file, section.name, section.rom_addr, section.ram_addr, section.size); @@ -1410,10 +1410,10 @@ void dump_context(const RecompPort::Context& context, const std::unordered_map(reloc.type)], reloc.address, reloc.section_offset + section.ram_addr); } @@ -1427,7 +1427,7 @@ void dump_context(const RecompPort::Context& context, const std::unordered_map read_file(const std::filesystem::path& path) { return ret; } -static void setup_context_for_elf(RecompPort::Context& context, const ELFIO::elfio& elf_file) { +static void setup_context_for_elf(N64Recomp::Context& context, const ELFIO::elfio& elf_file) { context.sections.resize(elf_file.sections.size()); context.section_functions.resize(elf_file.sections.size()); context.functions.reserve(1024); @@ -1509,7 +1509,7 @@ int main(int argc, char** argv) { const char* config_path = argv[1]; - RecompPort::Config config{ config_path }; + N64Recomp::Config config{ config_path }; if (!config.good()) { exit_failure(fmt::format("Failed to load config file: {}\n", config_path)); } @@ -1531,7 +1531,7 @@ int main(int argc, char** argv) { std::unordered_set relocatable_sections{}; relocatable_sections.insert(relocatable_sections_ordered.begin(), relocatable_sections_ordered.end()); - RecompPort::Context context{}; + N64Recomp::Context context{}; if (!config.elf_path.empty() && !config.symbols_file_path.empty()) { exit_failure("Config file cannot provide both an elf and a symbols file\n"); @@ -1561,8 +1561,8 @@ int main(int argc, char** argv) { { // Create a new temporary context to read the function reference symbol file into, since it's the same format as the recompilation symbol file. std::vector dummy_rom{}; - RecompPort::Context reference_context{}; - if (!RecompPort::Context::from_symbol_file(config.func_reference_syms_file_path, std::move(dummy_rom), reference_context, false)) { + N64Recomp::Context reference_context{}; + if (!N64Recomp::Context::from_symbol_file(config.func_reference_syms_file_path, std::move(dummy_rom), reference_context, false)) { exit_failure("Failed to load provided function reference symbol file\n"); } @@ -1636,12 +1636,12 @@ int main(int argc, char** argv) { exit_failure("Failed to load ROM file: " + config.rom_file_path.string() + "\n"); } - if (!RecompPort::Context::from_symbol_file(config.symbols_file_path, std::move(rom), context, true)) { + if (!N64Recomp::Context::from_symbol_file(config.symbols_file_path, std::move(rom), context, true)) { exit_failure("Failed to load symbols file\n"); } auto rename_function = [&context](size_t func_index, const std::string& new_name) { - RecompPort::Function& func = context.functions[func_index]; + N64Recomp::Function& func = context.functions[func_index]; context.functions_by_name.erase(func.name); func.name = new_name; @@ -1649,7 +1649,7 @@ int main(int argc, char** argv) { }; for (size_t func_index = 0; func_index < context.functions.size(); func_index++) { - RecompPort::Function& func = context.functions[func_index]; + N64Recomp::Function& func = context.functions[func_index]; if (reimplemented_funcs.contains(func.name)) { rename_function(func_index, func.name + "_recomp"); func.reimplemented = true; @@ -1734,7 +1734,7 @@ int main(int argc, char** argv) { } // Apply any single-instruction patches. - for (const RecompPort::InstructionPatch& patch : config.instruction_patches) { + for (const N64Recomp::InstructionPatch& patch : config.instruction_patches) { // Check if the specified function exists. auto func_find = context.functions_by_name.find(patch.func_name); if (func_find == context.functions_by_name.end()) { @@ -1743,7 +1743,7 @@ int main(int argc, char** argv) { exit_failure(fmt::format("Function {} has an instruction patch but does not exist!", patch.func_name)); } - RecompPort::Function& func = context.functions[func_find->second]; + N64Recomp::Function& func = context.functions[func_find->second]; int32_t func_vram = func.vram; // Check that the function actually contains this vram address. @@ -1757,7 +1757,7 @@ int main(int argc, char** argv) { } // Apply any function hooks. - for (const RecompPort::FunctionHook& patch : config.function_hooks) { + for (const N64Recomp::FunctionHook& patch : config.function_hooks) { // Check if the specified function exists. auto func_find = context.functions_by_name.find(patch.func_name); if (func_find == context.functions_by_name.end()) { @@ -1766,7 +1766,7 @@ int main(int argc, char** argv) { exit_failure(fmt::format("Function {} has a function hook but does not exist!", patch.func_name)); } - RecompPort::Function& func = context.functions[func_find->second]; + N64Recomp::Function& func = context.functions[func_find->second]; int32_t func_vram = func.vram; // Check that the function actually contains this vram address. @@ -1829,7 +1829,7 @@ int main(int argc, char** argv) { "void {}(uint8_t* rdram, recomp_context* ctx);\n", func.name); bool result; if (config.single_file_output || config.functions_per_output_file > 1) { - result = RecompPort::recompile_function(context, func, config.recomp_include, current_output_file, static_funcs_by_section, false); + result = N64Recomp::recompile_function(context, func, config.recomp_include, 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) { @@ -1892,7 +1892,7 @@ int main(int argc, char** argv) { std::vector insn_words((cur_func_end - static_func_addr) / sizeof(uint32_t)); insn_words.assign(func_rom_start, func_rom_start + insn_words.size()); - RecompPort::Function func { + N64Recomp::Function func { static_func_addr, rom_addr, std::move(insn_words), @@ -1906,9 +1906,8 @@ 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 = RecompPort::recompile_function(context, func, config.recomp_include, current_output_file, static_funcs_by_section, false); + result = N64Recomp::recompile_function(context, func, config.recomp_include, 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) { diff --git a/src/operations.cpp b/src/operations.cpp index 30fd822..d73b278 100644 --- a/src/operations.cpp +++ b/src/operations.cpp @@ -1,6 +1,6 @@ #include "operations.h" -namespace RecompPort { +namespace N64Recomp { const std::unordered_map unary_ops { { InstrId::cpu_lui, { UnaryOpType::Lui, Operand::Rt, Operand::ImmU16 } }, { InstrId::cpu_mthi, { UnaryOpType::None, Operand::Hi, Operand::Rs } }, diff --git a/src/recompilation.cpp b/src/recompilation.cpp index 38b8ea3..64dac35 100644 --- a/src/recompilation.cpp +++ b/src/recompilation.cpp @@ -8,7 +8,7 @@ #include "fmt/format.h" #include "fmt/ostream.h" -#include "recomp_port.h" +#include "n64recomp.h" #include "analysis.h" #include "operations.h" #include "generator.h" @@ -21,9 +21,9 @@ enum class JalResolutionResult { Error }; -JalResolutionResult resolve_jal(const RecompPort::Context& context, size_t cur_section_index, uint32_t target_func_vram, size_t& matched_function_index) { +JalResolutionResult resolve_jal(const N64Recomp::Context& context, size_t cur_section_index, uint32_t target_func_vram, size_t& matched_function_index) { // Look for symbols with the target vram address - const RecompPort::Section& cur_section = context.sections[cur_section_index]; + const N64Recomp::Section& cur_section = context.sections[cur_section_index]; const auto matching_funcs_find = context.functions_by_vram.find(target_func_vram); uint32_t section_vram_start = cur_section.ram_addr; uint32_t section_vram_end = cur_section.ram_addr + cur_section.size; @@ -110,8 +110,8 @@ 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 RecompPort::Context& context, const RecompPort::Function& func, const RecompPort::FunctionStats& stats, const std::unordered_set& skipped_insns, size_t instr_index, const std::vector& 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> static_funcs_out) { - using namespace RecompPort; +bool process_instruction(const N64Recomp::Context& context, const N64Recomp::Function& func, const N64Recomp::FunctionStats& stats, const std::unordered_set& skipped_insns, size_t instr_index, const std::vector& 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> static_funcs_out) { + using namespace N64Recomp; const auto& section = context.sections[func.section_index]; const auto& instr = instructions[instr_index]; @@ -144,7 +144,7 @@ bool process_instruction(const RecompPort::Context& context, const RecompPort::F return true; } - RecompPort::RelocType reloc_type = RecompPort::RelocType::R_MIPS_NONE; + N64Recomp::RelocType reloc_type = N64Recomp::RelocType::R_MIPS_NONE; uint32_t reloc_section = 0; uint32_t reloc_target_section_offset = 0; size_t reloc_reference_symbol = (size_t)-1; @@ -172,31 +172,31 @@ bool process_instruction(const RecompPort::Context& context, const RecompPort::F reloc_type = reloc.type; reloc_target_section_offset = reloc.section_offset; // Ignore all relocs that aren't HI16 or LO16. - if (reloc_type == RecompPort::RelocType::R_MIPS_HI16 || reloc_type == RecompPort::RelocType::R_MIPS_LO16 || reloc_type == RecompPort::RelocType::R_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; - static RecompPort::ReferenceSection dummy_section{ + static N64Recomp::ReferenceSection dummy_section{ .rom_addr = 0, .ram_addr = 0, .size = 0, .relocatable = false }; - const auto& reloc_reference_section = reloc.target_section == RecompPort::SectionAbsolute ? dummy_section : context.reference_sections[reloc.target_section]; + const auto& reloc_reference_section = reloc.target_section == N64Recomp::SectionAbsolute ? dummy_section : context.reference_sections[reloc.target_section]; // Resolve HI16 and LO16 reference symbol relocs to non-relocatable sections by patching the instruction immediate. - if (!reloc_reference_section.relocatable && (reloc_type == RecompPort::RelocType::R_MIPS_HI16 || reloc_type == RecompPort::RelocType::R_MIPS_LO16)) { + if (!reloc_reference_section.relocatable && (reloc_type == N64Recomp::RelocType::R_MIPS_HI16 || reloc_type == N64Recomp::RelocType::R_MIPS_LO16)) { uint32_t full_immediate = reloc.section_offset + reloc_reference_section.ram_addr; - if (reloc_type == RecompPort::RelocType::R_MIPS_HI16) { + if (reloc_type == N64Recomp::RelocType::R_MIPS_HI16) { imm = (full_immediate >> 16) + ((full_immediate >> 15) & 1); - reloc_type = RecompPort::RelocType::R_MIPS_NONE; + reloc_type = N64Recomp::RelocType::R_MIPS_NONE; } - else if (reloc_type == RecompPort::RelocType::R_MIPS_LO16) { + else if (reloc_type == N64Recomp::RelocType::R_MIPS_LO16) { imm = full_immediate & 0xFFFF; - reloc_type = RecompPort::RelocType::R_MIPS_NONE; + reloc_type = N64Recomp::RelocType::R_MIPS_NONE; } // The reloc has been processed, so delete it to none to prevent it getting processed a second time during instruction code generation. - reloc_type = RecompPort::RelocType::R_MIPS_NONE; + reloc_type = N64Recomp::RelocType::R_MIPS_NONE; reloc_reference_symbol = (size_t)-1; } } @@ -248,7 +248,7 @@ bool process_instruction(const RecompPort::Context& context, const RecompPort::F const auto& ref_symbol = context.reference_symbols[reloc_reference_symbol]; const std::string& ref_symbol_name = context.reference_symbol_names[reloc_reference_symbol]; - if (reloc_type != RecompPort::RelocType::R_MIPS_26) { + if (reloc_type != N64Recomp::RelocType::R_MIPS_26) { fmt::print(stderr, "Unsupported reloc type {} on jal instruction in {}\n", (int)reloc_type, func.name); return false; } @@ -388,12 +388,12 @@ bool process_instruction(const RecompPort::Context& context, const RecompPort::F { // Check if this addu belongs to a jump table load auto find_result = std::find_if(stats.jump_tables.begin(), stats.jump_tables.end(), - [instr_vram](const RecompPort::JumpTable& jtbl) { + [instr_vram](const N64Recomp::JumpTable& jtbl) { return jtbl.addu_vram == instr_vram; }); // If so, create a temp to preserve the addend register's value if (find_result != stats.jump_tables.end()) { - const RecompPort::JumpTable& cur_jtbl = *find_result; + const N64Recomp::JumpTable& cur_jtbl = *find_result; print_line("gpr jr_addend_{:08X} = {}{}", cur_jtbl.jr_vram, ctx_gpr_prefix(cur_jtbl.addend_reg), cur_jtbl.addend_reg); } } @@ -479,12 +479,12 @@ bool process_instruction(const RecompPort::Context& context, const RecompPort::F print_unconditional_branch("return"); } else { auto jtbl_find_result = std::find_if(stats.jump_tables.begin(), stats.jump_tables.end(), - [instr_vram](const RecompPort::JumpTable& jtbl) { + [instr_vram](const N64Recomp::JumpTable& jtbl) { return jtbl.jr_vram == instr_vram; }); if (jtbl_find_result != stats.jump_tables.end()) { - const RecompPort::JumpTable& cur_jtbl = *jtbl_find_result; + const N64Recomp::JumpTable& cur_jtbl = *jtbl_find_result; bool dummy_needs_link_branch, dummy_is_branch_likely; size_t next_reloc_index = reloc_index; uint32_t next_vram = instr_vram + 4; @@ -508,7 +508,7 @@ bool process_instruction(const RecompPort::Context& context, const RecompPort::F } auto jump_find_result = std::find_if(stats.absolute_jumps.begin(), stats.absolute_jumps.end(), - [instr_vram](const RecompPort::AbsoluteJump& jump) { + [instr_vram](const N64Recomp::AbsoluteJump& jump) { return jump.instruction_vram == instr_vram; }); @@ -718,7 +718,7 @@ bool process_instruction(const RecompPort::Context& context, const RecompPort::F return true; } -bool RecompPort::recompile_function(const RecompPort::Context& context, const RecompPort::Function& func, const std::string& recomp_include, std::ofstream& output_file, std::span> static_funcs_out, bool write_header) { +bool N64Recomp::recompile_function(const N64Recomp::Context& context, const N64Recomp::Function& func, const std::string& recomp_include, std::ofstream& output_file, std::span> static_funcs_out, bool write_header) { //fmt::print("Recompiling {}\n", func.name); std::vector instructions; @@ -764,8 +764,8 @@ bool RecompPort::recompile_function(const RecompPort::Context& context, const Re } // Analyze function - RecompPort::FunctionStats stats{}; - if (!RecompPort::analyze_function(context, func, instructions, stats)) { + N64Recomp::FunctionStats stats{}; + if (!N64Recomp::analyze_function(context, func, instructions, stats)) { fmt::print(stderr, "Failed to analyze {}\n", func.name); output_file.clear(); return false;