Move recompiler core logic into a core library and make the existing CLI consume the core library

This commit is contained in:
Mr-Wiseguy 2024-07-07 17:27:49 -04:00
parent bce3baa99a
commit ddb8a08482
5 changed files with 45 additions and 26 deletions

View file

@ -62,24 +62,38 @@ add_subdirectory(lib/fmt)
set(TOML_ENABLE_FORMATTERS OFF) set(TOML_ENABLE_FORMATTERS OFF)
add_subdirectory(lib/tomlplusplus) add_subdirectory(lib/tomlplusplus)
# N64 recompiler # N64 recompiler core library
project(N64Recomp) project(N64Recomp)
add_executable(N64Recomp) add_library(N64Recomp)
target_sources(N64Recomp PRIVATE target_sources(N64Recomp PRIVATE
${CMAKE_SOURCE_DIR}/src/analysis.cpp ${CMAKE_SOURCE_DIR}/src/analysis.cpp
${CMAKE_SOURCE_DIR}/src/config.cpp
${CMAKE_SOURCE_DIR}/src/main.cpp
${CMAKE_SOURCE_DIR}/src/operations.cpp ${CMAKE_SOURCE_DIR}/src/operations.cpp
${CMAKE_SOURCE_DIR}/src/cgenerator.cpp ${CMAKE_SOURCE_DIR}/src/cgenerator.cpp
${CMAKE_SOURCE_DIR}/src/recompilation.cpp) ${CMAKE_SOURCE_DIR}/src/recompilation.cpp
)
target_include_directories(N64Recomp PRIVATE target_include_directories(N64Recomp PRIVATE
"${CMAKE_SOURCE_DIR}/lib/ELFIO"
"${CMAKE_SOURCE_DIR}/include") "${CMAKE_SOURCE_DIR}/include")
target_link_libraries(N64Recomp fmt rabbitizer tomlplusplus::tomlplusplus) target_link_libraries(N64Recomp fmt rabbitizer tomlplusplus::tomlplusplus)
# N64 recompiler executable
project(N64RecompCLI)
add_executable(N64RecompCLI)
target_sources(N64RecompCLI PRIVATE
${CMAKE_SOURCE_DIR}/src/config.cpp
${CMAKE_SOURCE_DIR}/src/main.cpp
)
target_include_directories(N64RecompCLI PRIVATE
"${CMAKE_SOURCE_DIR}/lib/ELFIO"
"${CMAKE_SOURCE_DIR}/include")
target_link_libraries(N64RecompCLI fmt rabbitizer tomlplusplus::tomlplusplus N64Recomp)
set_target_properties(N64RecompCLI PROPERTIES OUTPUT_NAME N64Recomp)
# RSP recompiler # RSP recompiler
project(RSPRecomp) project(RSPRecomp)
add_executable(RSPRecomp) add_executable(RSPRecomp)

View file

@ -11,7 +11,6 @@
#include <unordered_set> #include <unordered_set>
#include <filesystem> #include <filesystem>
#include "rabbitizer.hpp" #include "rabbitizer.hpp"
#include "elfio/elfio.hpp"
#ifdef _MSC_VER #ifdef _MSC_VER
inline uint32_t byteswap(uint32_t val) { inline uint32_t byteswap(uint32_t val) {
@ -119,13 +118,13 @@ namespace RecompPort {
uint32_t rom; uint32_t rom;
std::vector<uint32_t> words; std::vector<uint32_t> words;
std::string name; std::string name;
ELFIO::Elf_Half section_index; uint16_t section_index;
bool ignored; bool ignored;
bool reimplemented; bool reimplemented;
bool stubbed; bool stubbed;
std::unordered_map<int32_t, std::string> function_hooks; std::unordered_map<int32_t, std::string> function_hooks;
Function(uint32_t vram, uint32_t rom, std::vector<uint32_t> words, std::string name, ELFIO::Elf_Half section_index, bool ignored = false, bool reimplemented = false, bool stubbed = false) Function(uint32_t vram, uint32_t rom, std::vector<uint32_t> words, std::string name, uint16_t section_index, bool ignored = false, bool reimplemented = false, bool stubbed = false)
: vram(vram), rom(rom), words(std::move(words)), name(std::move(name)), section_index(section_index), ignored(ignored), reimplemented(reimplemented), stubbed(stubbed) {} : vram(vram), rom(rom), words(std::move(words)), name(std::move(name)), section_index(section_index), ignored(ignored), reimplemented(reimplemented), stubbed(stubbed) {}
Function() = default; Function() = default;
}; };
@ -153,13 +152,13 @@ namespace RecompPort {
constexpr uint16_t SectionSelf = (uint16_t)-1; constexpr uint16_t SectionSelf = (uint16_t)-1;
constexpr uint16_t SectionAbsolute = (uint16_t)-2; constexpr uint16_t SectionAbsolute = (uint16_t)-2;
struct Section { struct Section {
ELFIO::Elf_Xword rom_addr = 0; uint32_t rom_addr = 0;
ELFIO::Elf64_Addr ram_addr = 0; uint32_t ram_addr = 0;
ELFIO::Elf_Xword size = 0; uint32_t size = 0;
std::vector<uint32_t> function_addrs; std::vector<uint32_t> function_addrs;
std::vector<Reloc> relocs; std::vector<Reloc> relocs;
std::string name; std::string name;
ELFIO::Elf_Half bss_section_index = (ELFIO::Elf_Half)-1; uint16_t bss_section_index = (uint16_t)-1;
bool executable = false; bool executable = false;
bool relocatable = false; bool relocatable = false;
bool has_mips32_relocs = false; bool has_mips32_relocs = false;
@ -209,16 +208,6 @@ namespace RecompPort {
std::unordered_map<std::string, size_t> reference_symbols_by_name; std::unordered_map<std::string, size_t> reference_symbols_by_name;
int executable_section_count; int executable_section_count;
Context(const ELFIO::elfio& elf_file) {
sections.resize(elf_file.sections.size());
section_functions.resize(elf_file.sections.size());
functions.reserve(1024);
functions_by_vram.reserve(functions.capacity());
functions_by_name.reserve(functions.capacity());
rom.reserve(8 * 1024 * 1024);
executable_section_count = 0;
}
// Imports sections and function symbols from a provided context into this context's reference sections and reference functions. // Imports sections and function symbols from a provided context into this context's reference sections and reference functions.
void import_reference_context(const Context& reference_context); void import_reference_context(const Context& reference_context);
// Reads a data symbol file and adds its contents into this context's reference data symbols. // Reads a data symbol file and adds its contents into this context's reference data symbols.

View file

@ -1,4 +1,4 @@
#include <source_location> #include <iostream>
#include <toml++/toml.hpp> #include <toml++/toml.hpp>
#include "fmt/format.h" #include "fmt/format.h"

View file

@ -1053,7 +1053,7 @@ ELFIO::section* read_sections(RecompPort::Context& context, const RecompPort::Co
std::copy(section->get_data(), section->get_data() + section->get_size(), &context.rom[section_out.rom_addr]); std::copy(section->get_data(), section->get_data() + section->get_size(), &context.rom[section_out.rom_addr]);
} else { } else {
// Otherwise mark this section as having an invalid rom address // Otherwise mark this section as having an invalid rom address
section_out.rom_addr = (ELFIO::Elf_Xword)-1; section_out.rom_addr = (uint32_t)-1;
} }
// Check if this section is marked as executable, which means it has code in it // Check if this section is marked as executable, which means it has code in it
if (section->get_flags() & ELFIO::SHF_EXECINSTR) { if (section->get_flags() & ELFIO::SHF_EXECINSTR) {
@ -1482,6 +1482,16 @@ static std::vector<uint8_t> read_file(const std::filesystem::path& path) {
return ret; return ret;
} }
static void setup_context_for_elf(RecompPort::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);
context.functions_by_vram.reserve(context.functions.capacity());
context.functions_by_name.reserve(context.functions.capacity());
context.rom.reserve(8 * 1024 * 1024);
context.executable_section_count = 0;
}
int main(int argc, char** argv) { int main(int argc, char** argv) {
auto exit_failure = [] (const std::string& error_str) { auto exit_failure = [] (const std::string& error_str) {
fmt::vprint(stderr, error_str, fmt::make_format_args()); fmt::vprint(stderr, error_str, fmt::make_format_args());
@ -1542,7 +1552,7 @@ int main(int argc, char** argv) {
exit_failure("Incorrect endianness\n"); exit_failure("Incorrect endianness\n");
} }
context = { elf_file }; setup_context_for_elf(context, elf_file);
context.relocatable_sections = std::move(relocatable_sections); context.relocatable_sections = std::move(relocatable_sections);
// Import symbols from any reference symbols files that were provided. // Import symbols from any reference symbols files that were provided.

View file

@ -596,6 +596,9 @@ bool process_instruction(const RecompPort::Context& context, const RecompPort::C
case Operand::FtU64: case Operand::FtU64:
generator.emit_check_fr(output_file, ctx.ft); generator.emit_check_fr(output_file, ctx.ft);
break; break;
default:
// No MIPS3 float check needed for non-float operands.
break;
} }
}; };
@ -619,6 +622,9 @@ bool process_instruction(const RecompPort::Context& context, const RecompPort::C
case Operand::FtDouble: case Operand::FtDouble:
generator.emit_check_nan(output_file, ctx.ft, true); generator.emit_check_nan(output_file, ctx.ft, true);
break; break;
default:
// No NaN checks needed for non-float operands.
break;
} }
}; };