mirror of
https://github.com/citra-emu/citra.git
synced 2024-11-24 12:01:04 +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)
|
||||
if(ENABLE_BINARY_TRANSLATION)
|
||||
add_definitions(-DENABLE_BINARY_TRANSLATION)
|
||||
find_package(LLVM REQUIRED CONFIG)
|
||||
include_directories(${LLVM_INCLUDE_DIRS})
|
||||
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 ${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})
|
||||
|
@ -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})
|
||||
|
@ -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
|
||||
|
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/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
|
||||
|
Loading…
Reference in New Issue
Block a user