Loading and running the translated file

This commit is contained in:
Dani Messerman 2015-04-30 22:37:41 +03:00
parent 3731d28ca9
commit 49483c67ca
7 changed files with 153 additions and 5 deletions

View File

@ -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})

View File

@ -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})

View File

@ -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})

View File

@ -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

View File

@ -0,0 +1,84 @@
#include "BinaryTranslationLoader.h"
#include "core/arm/skyeye_common/armdefs.h"
#include <llvm/Support/TargetSelect.h>
#include <llvm/ADT/STLExtras.h>
#include <llvm/Support/MemoryBuffer.h>
#include <llvm/Object/ObjectFile.h>
#include <llvm/ExecutionEngine/RuntimeDyld.h>
#include <llvm/ExecutionEngine/SectionMemoryManager.h>
using namespace llvm;
bool g_enabled = false;
std::unique_ptr<SectionMemoryManager> g_memory_manager;
std::unique_ptr<RuntimeDyld> g_dyld;
std::unique_ptr<RuntimeDyld::LoadedObjectInfo> 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<SectionMemoryManager>();
g_dyld = make_unique<RuntimeDyld>(g_memory_manager.get());
auto size = file.GetSize();
auto buffer = make_unique<char[]>(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<decltype(g_run_function)>(g_dyld->getSymbolAddress("Run"));
g_enabled = true;
}
void BinaryTranslationLoader::SetCpuState(ARMul_State* state)
{
if (!g_enabled) return;
auto regs_ptr = static_cast<u32 **>(g_dyld->getSymbolAddress("Registers"));
auto flags_ptr = static_cast<u32 **>(g_dyld->getSymbolAddress("Flags"));
*regs_ptr = state->Reg;
*flags_ptr = &state->NFlag;
}
void BinaryTranslationLoader::Run()
{
if (!g_enabled) return;
g_run_function();
}

View File

@ -0,0 +1,14 @@
#include "common/common.h"
#include "common/file_util.h"
#include <memory>
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();
};

View File

@ -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<FileSys::ArchiveFactory_RomFS>(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<FileUtil::IOFile> 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