From 49483c67ca8a689eed961d4e1fc004e0b3c2776b Mon Sep 17 00:00:00 2001 From: Dani Messerman Date: Thu, 30 Apr 2015 22:37:41 +0300 Subject: [PATCH] Loading and running the translated file --- CMakeLists.txt | 1 + src/citra/CMakeLists.txt | 3 + src/core/CMakeLists.txt | 11 +++ .../arm/dyncom/arm_dyncom_interpreter.cpp | 13 +++ .../BinaryTranslationLoader.cpp | 84 +++++++++++++++++++ .../BinaryTranslationLoader.h | 14 ++++ src/core/loader/loader.cpp | 32 +++++-- 7 files changed, 153 insertions(+), 5 deletions(-) create mode 100644 src/core/binary_translation/BinaryTranslationLoader.cpp create mode 100644 src/core/binary_translation/BinaryTranslationLoader.h diff --git a/CMakeLists.txt b/CMakeLists.txt index 68377390b..e4be67e19 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -195,6 +195,7 @@ endif() option(ENABLE_BINARY_TRANSLATION "Enable binary translation. Requires LLVM" OFF) if(ENABLE_BINARY_TRANSLATION) + add_definitions(-DENABLE_BINARY_TRANSLATION) find_package(LLVM REQUIRED CONFIG) include_directories(${LLVM_INCLUDE_DIRS}) add_definitions(${LLVM_DEFINITIONS}) diff --git a/src/citra/CMakeLists.txt b/src/citra/CMakeLists.txt index 713f49193..0aafbfa5a 100644 --- a/src/citra/CMakeLists.txt +++ b/src/citra/CMakeLists.txt @@ -17,5 +17,8 @@ add_executable(citra ${SRCS} ${HEADERS}) target_link_libraries(citra core common video_core) target_link_libraries(citra ${GLFW_LIBRARIES} ${OPENGL_gl_LIBRARY} inih) target_link_libraries(citra ${PLATFORM_LIBRARIES}) +if(ENABLE_BINARY_TRANSLATION) + target_link_libraries(citra ${llvm_libs}) +endif() #install(TARGETS citra RUNTIME DESTINATION ${bindir}) diff --git a/src/core/CMakeLists.txt b/src/core/CMakeLists.txt index ebedcb710..2cdd578b7 100644 --- a/src/core/CMakeLists.txt +++ b/src/core/CMakeLists.txt @@ -215,6 +215,17 @@ set(HEADERS system.h ) +if(ENABLE_BINARY_TRANSLATION) + set(SRCS + ${SRCS} + binary_translation/BinaryTranslationLoader.cpp + ) + set(HEADERS + ${HEADERS} + binary_translation/BinaryTranslationLoader.h + ) +endif() + create_directory_groups(${SRCS} ${HEADERS}) add_library(core STATIC ${SRCS} ${HEADERS}) diff --git a/src/core/arm/dyncom/arm_dyncom_interpreter.cpp b/src/core/arm/dyncom/arm_dyncom_interpreter.cpp index c2973fb39..5f60b1fdc 100644 --- a/src/core/arm/dyncom/arm_dyncom_interpreter.cpp +++ b/src/core/arm/dyncom/arm_dyncom_interpreter.cpp @@ -20,6 +20,10 @@ #include "core/arm/skyeye_common/armmmu.h" #include "core/arm/skyeye_common/vfp/vfp.h" +#if ENABLE_BINARY_TRANSLATION +#include "core/binary_translation/BinaryTranslationLoader.h" +#endif + Common::Profiling::TimingCategory profile_execute("DynCom::Execute"); Common::Profiling::TimingCategory profile_decode("DynCom::Decode"); @@ -3675,6 +3679,10 @@ static int clz(unsigned int x) { unsigned InterpreterMainLoop(ARMul_State* cpu) { Common::Profiling::ScopeTimer timer_execute(profile_execute); +#if ENABLE_BINARY_TRANSLATION + BinaryTranslationLoader::SetCpuState(state); +#endif + #undef RM #undef RS @@ -3974,6 +3982,11 @@ unsigned InterpreterMainLoop(ARMul_State* cpu) { } } + +#if ENABLE_BINARY_TRANSLATION + BinaryTranslationLoader::Run(); +#endif + if (cpu->TFlag) cpu->Reg[15] &= 0xfffffffe; else diff --git a/src/core/binary_translation/BinaryTranslationLoader.cpp b/src/core/binary_translation/BinaryTranslationLoader.cpp new file mode 100644 index 000000000..81d4fb6f3 --- /dev/null +++ b/src/core/binary_translation/BinaryTranslationLoader.cpp @@ -0,0 +1,84 @@ +#include "BinaryTranslationLoader.h" +#include "core/arm/skyeye_common/armdefs.h" +#include +#include +#include +#include +#include +#include + +using namespace llvm; + +bool g_enabled = false; + +std::unique_ptr g_memory_manager; +std::unique_ptr g_dyld; +std::unique_ptr g_loaded_object_info; + +void (*g_run_function)(); + +void BinaryTranslationLoader::Load(FileUtil::IOFile& file) +{ + if (offsetof(ARMul_State, ZFlag) - offsetof(ARMul_State, NFlag) != 4 || + offsetof(ARMul_State, CFlag) - offsetof(ARMul_State, NFlag) != 8 || + offsetof(ARMul_State, VFlag) - offsetof(ARMul_State, NFlag) != 12) + { + LOG_WARNING(Loader, "Flags are unordered, cannot run optimized file"); + return; + } + + InitializeNativeTarget(); + + g_memory_manager = make_unique(); + g_dyld = make_unique(g_memory_manager.get()); + + auto size = file.GetSize(); + auto buffer = make_unique(size); + + file.ReadBytes(buffer.get(), size); + if (!file.IsGood()) + { + LOG_WARNING(Loader, "Cannot read optimized file"); + return; + } + + auto object_file = object::ObjectFile::createObjectFile(MemoryBufferRef(StringRef(buffer.get(), size), "")); + if (!object_file) + { + LOG_WARNING(Loader, "Cannot load optimized file"); + return; + } + + g_loaded_object_info = g_dyld->loadObject(*object_file->get()); + if (g_dyld->hasError()) + { + LOG_WARNING(Loader, "Cannot load optimized file, error %s", g_dyld->getErrorString().str().c_str()); + return; + } + + g_dyld->resolveRelocations(); + g_dyld->registerEHFrames(); + g_memory_manager->finalizeMemory(); + + g_run_function = static_cast(g_dyld->getSymbolAddress("Run")); + + g_enabled = true; +} + +void BinaryTranslationLoader::SetCpuState(ARMul_State* state) +{ + if (!g_enabled) return; + + auto regs_ptr = static_cast(g_dyld->getSymbolAddress("Registers")); + auto flags_ptr = static_cast(g_dyld->getSymbolAddress("Flags")); + + *regs_ptr = state->Reg; + *flags_ptr = &state->NFlag; +} + +void BinaryTranslationLoader::Run() +{ + if (!g_enabled) return; + + g_run_function(); +} \ No newline at end of file diff --git a/src/core/binary_translation/BinaryTranslationLoader.h b/src/core/binary_translation/BinaryTranslationLoader.h new file mode 100644 index 000000000..51f72ea3a --- /dev/null +++ b/src/core/binary_translation/BinaryTranslationLoader.h @@ -0,0 +1,14 @@ +#include "common/common.h" +#include "common/file_util.h" +#include + +struct ARMul_State; + +class BinaryTranslationLoader +{ +public: + static void Load(FileUtil::IOFile& file); + static void SetCpuState(ARMul_State *state); + // Runs the state provided at SetCpuState. + static void Run(); +}; \ No newline at end of file diff --git a/src/core/loader/loader.cpp b/src/core/loader/loader.cpp index faf1af51a..09059921a 100644 --- a/src/core/loader/loader.cpp +++ b/src/core/loader/loader.cpp @@ -15,6 +15,10 @@ #include "core/loader/ncch.h" #include "core/mem_map.h" +#if ENABLE_BINARY_TRANSLATION +#include "core/binary_translation/BinaryTranslationLoader.h" +#endif + //////////////////////////////////////////////////////////////////////////////////////////////////// namespace Loader { @@ -113,15 +117,18 @@ ResultStatus LoadFile(const std::string& filename) { LOG_INFO(Loader, "Loading file %s as %s...", filename.c_str(), GetFileTypeString(type)); + ResultStatus status = ResultStatus::Error; switch (type) { //3DSX file format... case FileType::THREEDSX: - return AppLoader_THREEDSX(std::move(file), filename_filename).Load(); + status = AppLoader_THREEDSX(std::move(file), filename_filename).Load(); + break; // Standard ELF file format... case FileType::ELF: - return AppLoader_ELF(std::move(file), filename_filename).Load(); + status = AppLoader_ELF(std::move(file), filename_filename).Load(); + break; // NCCH/NCSD container formats... case FileType::CXI: @@ -132,7 +139,7 @@ ResultStatus LoadFile(const std::string& filename) { // Load application and RomFS if (ResultStatus::Success == app_loader.Load()) { Service::FS::RegisterArchiveType(Common::make_unique(app_loader), Service::FS::ArchiveIdCode::RomFS); - return ResultStatus::Success; + status = ResultStatus::Success; } break; } @@ -144,10 +151,25 @@ ResultStatus LoadFile(const std::string& filename) { case FileType::Unknown: { LOG_CRITICAL(Loader, "File %s is of unknown type.", filename.c_str()); - return ResultStatus::ErrorInvalidFormat; + status = ResultStatus::ErrorInvalidFormat; + break; } } - return ResultStatus::Error; +#if ENABLE_BINARY_TRANSLATION + if (status == ResultStatus::Success) + { + std::unique_ptr optimized_file(new FileUtil::IOFile(filename + ".obj", "rb")); + if (!optimized_file->IsOpen()) + { + LOG_WARNING(Loader, "Failed to load optimized file %s.obj", filename.c_str()); + } + else + { + BinaryTranslationLoader::Load(*optimized_file); + } + } +#endif + return status; } } // namespace Loader