mirror of
https://github.com/citra-emu/citra.git
synced 2024-11-24 13:21:03 +00:00
Loading and running the translated file
This commit is contained in:
parent
3731d28ca9
commit
49483c67ca
@ -195,6 +195,7 @@ endif()
|
|||||||
|
|
||||||
option(ENABLE_BINARY_TRANSLATION "Enable binary translation. Requires LLVM" OFF)
|
option(ENABLE_BINARY_TRANSLATION "Enable binary translation. Requires LLVM" OFF)
|
||||||
if(ENABLE_BINARY_TRANSLATION)
|
if(ENABLE_BINARY_TRANSLATION)
|
||||||
|
add_definitions(-DENABLE_BINARY_TRANSLATION)
|
||||||
find_package(LLVM REQUIRED CONFIG)
|
find_package(LLVM REQUIRED CONFIG)
|
||||||
include_directories(${LLVM_INCLUDE_DIRS})
|
include_directories(${LLVM_INCLUDE_DIRS})
|
||||||
add_definitions(${LLVM_DEFINITIONS})
|
add_definitions(${LLVM_DEFINITIONS})
|
||||||
|
@ -17,5 +17,8 @@ add_executable(citra ${SRCS} ${HEADERS})
|
|||||||
target_link_libraries(citra core common video_core)
|
target_link_libraries(citra core common video_core)
|
||||||
target_link_libraries(citra ${GLFW_LIBRARIES} ${OPENGL_gl_LIBRARY} inih)
|
target_link_libraries(citra ${GLFW_LIBRARIES} ${OPENGL_gl_LIBRARY} inih)
|
||||||
target_link_libraries(citra ${PLATFORM_LIBRARIES})
|
target_link_libraries(citra ${PLATFORM_LIBRARIES})
|
||||||
|
if(ENABLE_BINARY_TRANSLATION)
|
||||||
|
target_link_libraries(citra ${llvm_libs})
|
||||||
|
endif()
|
||||||
|
|
||||||
#install(TARGETS citra RUNTIME DESTINATION ${bindir})
|
#install(TARGETS citra RUNTIME DESTINATION ${bindir})
|
||||||
|
@ -215,6 +215,17 @@ set(HEADERS
|
|||||||
system.h
|
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})
|
create_directory_groups(${SRCS} ${HEADERS})
|
||||||
|
|
||||||
add_library(core STATIC ${SRCS} ${HEADERS})
|
add_library(core STATIC ${SRCS} ${HEADERS})
|
||||||
|
@ -20,6 +20,10 @@
|
|||||||
#include "core/arm/skyeye_common/armmmu.h"
|
#include "core/arm/skyeye_common/armmmu.h"
|
||||||
#include "core/arm/skyeye_common/vfp/vfp.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_execute("DynCom::Execute");
|
||||||
Common::Profiling::TimingCategory profile_decode("DynCom::Decode");
|
Common::Profiling::TimingCategory profile_decode("DynCom::Decode");
|
||||||
|
|
||||||
@ -3675,6 +3679,10 @@ static int clz(unsigned int x) {
|
|||||||
unsigned InterpreterMainLoop(ARMul_State* cpu) {
|
unsigned InterpreterMainLoop(ARMul_State* cpu) {
|
||||||
Common::Profiling::ScopeTimer timer_execute(profile_execute);
|
Common::Profiling::ScopeTimer timer_execute(profile_execute);
|
||||||
|
|
||||||
|
#if ENABLE_BINARY_TRANSLATION
|
||||||
|
BinaryTranslationLoader::SetCpuState(state);
|
||||||
|
#endif
|
||||||
|
|
||||||
#undef RM
|
#undef RM
|
||||||
#undef RS
|
#undef RS
|
||||||
|
|
||||||
@ -3974,6 +3982,11 @@ unsigned InterpreterMainLoop(ARMul_State* cpu) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
#if ENABLE_BINARY_TRANSLATION
|
||||||
|
BinaryTranslationLoader::Run();
|
||||||
|
#endif
|
||||||
|
|
||||||
if (cpu->TFlag)
|
if (cpu->TFlag)
|
||||||
cpu->Reg[15] &= 0xfffffffe;
|
cpu->Reg[15] &= 0xfffffffe;
|
||||||
else
|
else
|
||||||
|
84
src/core/binary_translation/BinaryTranslationLoader.cpp
Normal file
84
src/core/binary_translation/BinaryTranslationLoader.cpp
Normal 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();
|
||||||
|
}
|
14
src/core/binary_translation/BinaryTranslationLoader.h
Normal file
14
src/core/binary_translation/BinaryTranslationLoader.h
Normal 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();
|
||||||
|
};
|
@ -15,6 +15,10 @@
|
|||||||
#include "core/loader/ncch.h"
|
#include "core/loader/ncch.h"
|
||||||
#include "core/mem_map.h"
|
#include "core/mem_map.h"
|
||||||
|
|
||||||
|
#if ENABLE_BINARY_TRANSLATION
|
||||||
|
#include "core/binary_translation/BinaryTranslationLoader.h"
|
||||||
|
#endif
|
||||||
|
|
||||||
////////////////////////////////////////////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
namespace Loader {
|
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));
|
LOG_INFO(Loader, "Loading file %s as %s...", filename.c_str(), GetFileTypeString(type));
|
||||||
|
|
||||||
|
ResultStatus status = ResultStatus::Error;
|
||||||
switch (type) {
|
switch (type) {
|
||||||
|
|
||||||
//3DSX file format...
|
//3DSX file format...
|
||||||
case FileType::THREEDSX:
|
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...
|
// Standard ELF file format...
|
||||||
case FileType::ELF:
|
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...
|
// NCCH/NCSD container formats...
|
||||||
case FileType::CXI:
|
case FileType::CXI:
|
||||||
@ -132,7 +139,7 @@ ResultStatus LoadFile(const std::string& filename) {
|
|||||||
// Load application and RomFS
|
// Load application and RomFS
|
||||||
if (ResultStatus::Success == app_loader.Load()) {
|
if (ResultStatus::Success == app_loader.Load()) {
|
||||||
Service::FS::RegisterArchiveType(Common::make_unique<FileSys::ArchiveFactory_RomFS>(app_loader), Service::FS::ArchiveIdCode::RomFS);
|
Service::FS::RegisterArchiveType(Common::make_unique<FileSys::ArchiveFactory_RomFS>(app_loader), Service::FS::ArchiveIdCode::RomFS);
|
||||||
return ResultStatus::Success;
|
status = ResultStatus::Success;
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
@ -144,10 +151,25 @@ ResultStatus LoadFile(const std::string& filename) {
|
|||||||
case FileType::Unknown:
|
case FileType::Unknown:
|
||||||
{
|
{
|
||||||
LOG_CRITICAL(Loader, "File %s is of unknown type.", filename.c_str());
|
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
|
} // namespace Loader
|
||||||
|
Loading…
Reference in New Issue
Block a user