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)
add_subdirectory(lib/tomlplusplus)
# N64 recompiler
# N64 recompiler core library
project(N64Recomp)
add_executable(N64Recomp)
add_library(N64Recomp)
target_sources(N64Recomp PRIVATE
${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/cgenerator.cpp
${CMAKE_SOURCE_DIR}/src/recompilation.cpp)
${CMAKE_SOURCE_DIR}/src/recompilation.cpp
)
target_include_directories(N64Recomp PRIVATE
"${CMAKE_SOURCE_DIR}/lib/ELFIO"
"${CMAKE_SOURCE_DIR}/include")
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
project(RSPRecomp)
add_executable(RSPRecomp)

View file

@ -11,7 +11,6 @@
#include <unordered_set>
#include <filesystem>
#include "rabbitizer.hpp"
#include "elfio/elfio.hpp"
#ifdef _MSC_VER
inline uint32_t byteswap(uint32_t val) {
@ -119,13 +118,13 @@ namespace RecompPort {
uint32_t rom;
std::vector<uint32_t> words;
std::string name;
ELFIO::Elf_Half section_index;
uint16_t section_index;
bool ignored;
bool reimplemented;
bool stubbed;
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) {}
Function() = default;
};
@ -153,13 +152,13 @@ namespace RecompPort {
constexpr uint16_t SectionSelf = (uint16_t)-1;
constexpr uint16_t SectionAbsolute = (uint16_t)-2;
struct Section {
ELFIO::Elf_Xword rom_addr = 0;
ELFIO::Elf64_Addr ram_addr = 0;
ELFIO::Elf_Xword size = 0;
uint32_t rom_addr = 0;
uint32_t ram_addr = 0;
uint32_t size = 0;
std::vector<uint32_t> function_addrs;
std::vector<Reloc> relocs;
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 relocatable = false;
bool has_mips32_relocs = false;
@ -209,16 +208,6 @@ namespace RecompPort {
std::unordered_map<std::string, size_t> reference_symbols_by_name;
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.
void import_reference_context(const Context& reference_context);
// 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 "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]);
} else {
// 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
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;
}
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) {
auto exit_failure = [] (const std::string& error_str) {
fmt::vprint(stderr, error_str, fmt::make_format_args());
@ -1542,7 +1552,7 @@ int main(int argc, char** argv) {
exit_failure("Incorrect endianness\n");
}
context = { elf_file };
setup_context_for_elf(context, elf_file);
context.relocatable_sections = std::move(relocatable_sections);
// 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:
generator.emit_check_fr(output_file, ctx.ft);
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:
generator.emit_check_nan(output_file, ctx.ft, true);
break;
default:
// No NaN checks needed for non-float operands.
break;
}
};