From fc6db97a09e2de5eff10131ddcab9cf8fb2f736c Mon Sep 17 00:00:00 2001 From: Lioncash Date: Tue, 3 Nov 2020 19:54:53 -0500 Subject: [PATCH] core: Remove usage of unicorn Unicorn long-since lost most of its use, due to dynarmic gaining support for handling most instructions. At this point any further issues encountered should be used to make dynarmic better. This also allows us to remove our dependency on Python. --- .gitmodules | 3 - .travis/linux-mingw/docker.sh | 10 +- .travis/linux/docker.sh | 2 +- .travis/macos/build.sh | 3 +- CMakeLists.txt | 77 ------ CMakeModules/CopyYuzuUnicornDeps.cmake | 9 - externals/unicorn | 1 - src/core/CMakeLists.txt | 4 +- src/core/arm/dynarmic/arm_dynarmic_32.cpp | 1 + src/core/arm/dynarmic/arm_dynarmic_64.cpp | 29 +-- src/core/arm/dynarmic/arm_dynarmic_64.h | 2 - src/core/arm/unicorn/arm_unicorn.cpp | 295 ---------------------- src/core/arm/unicorn/arm_unicorn.h | 63 ----- src/core/hle/kernel/physical_core.cpp | 16 +- src/core/hle/kernel/thread.cpp | 17 +- src/yuzu/CMakeLists.txt | 2 - src/yuzu_cmd/CMakeLists.txt | 2 - src/yuzu_tester/CMakeLists.txt | 2 - 18 files changed, 18 insertions(+), 520 deletions(-) delete mode 100644 CMakeModules/CopyYuzuUnicornDeps.cmake delete mode 160000 externals/unicorn delete mode 100644 src/core/arm/unicorn/arm_unicorn.cpp delete mode 100644 src/core/arm/unicorn/arm_unicorn.h diff --git a/.gitmodules b/.gitmodules index 6931a641d..41022615b 100644 --- a/.gitmodules +++ b/.gitmodules @@ -7,9 +7,6 @@ [submodule "dynarmic"] path = externals/dynarmic url = https://github.com/MerryMage/dynarmic.git -[submodule "unicorn"] - path = externals/unicorn - url = https://github.com/yuzu-emu/unicorn [submodule "soundtouch"] path = externals/soundtouch url = https://github.com/citra-emu/ext-soundtouch.git diff --git a/.travis/linux-mingw/docker.sh b/.travis/linux-mingw/docker.sh index 28033acfb..80d7dfe9b 100755 --- a/.travis/linux-mingw/docker.sh +++ b/.travis/linux-mingw/docker.sh @@ -4,16 +4,8 @@ cd /yuzu # override Travis CI unreasonable ccache size echo 'max_size = 3.0G' > "$HOME/.ccache/ccache.conf" -# Dirty hack to trick unicorn makefile into believing we are in a MINGW system -mv /bin/uname /bin/uname1 && echo -e '#!/bin/sh\necho MINGW64' >> /bin/uname -chmod +x /bin/uname - -# Dirty hack to trick unicorn makefile into believing we have cmd -echo '' >> /bin/cmd -chmod +x /bin/cmd - mkdir build && cd build -cmake .. -G Ninja -DCMAKE_TOOLCHAIN_FILE="$(pwd)/../CMakeModules/MinGWCross.cmake" -DUSE_CCACHE=ON -DYUZU_USE_BUNDLED_UNICORN=ON -DENABLE_COMPATIBILITY_LIST_DOWNLOAD=ON -DCMAKE_BUILD_TYPE=Release +cmake .. -G Ninja -DCMAKE_TOOLCHAIN_FILE="$(pwd)/../CMakeModules/MinGWCross.cmake" -DUSE_CCACHE=ON -DENABLE_COMPATIBILITY_LIST_DOWNLOAD=ON -DCMAKE_BUILD_TYPE=Release ninja # Clean up the dirty hacks diff --git a/.travis/linux/docker.sh b/.travis/linux/docker.sh index 3a9970384..166fb6d4c 100755 --- a/.travis/linux/docker.sh +++ b/.travis/linux/docker.sh @@ -3,7 +3,7 @@ cd /yuzu mkdir build && cd build -cmake .. -G Ninja -DYUZU_USE_BUNDLED_UNICORN=ON -DYUZU_USE_QT_WEB_ENGINE=ON -DCMAKE_BUILD_TYPE=Release -DCMAKE_C_COMPILER=/usr/lib/ccache/gcc -DCMAKE_CXX_COMPILER=/usr/lib/ccache/g++ -DYUZU_ENABLE_COMPATIBILITY_REPORTING=${ENABLE_COMPATIBILITY_REPORTING:-"OFF"} -DENABLE_COMPATIBILITY_LIST_DOWNLOAD=ON -DUSE_DISCORD_PRESENCE=ON +cmake .. -G Ninja -DYUZU_USE_QT_WEB_ENGINE=ON -DCMAKE_BUILD_TYPE=Release -DCMAKE_C_COMPILER=/usr/lib/ccache/gcc -DCMAKE_CXX_COMPILER=/usr/lib/ccache/g++ -DYUZU_ENABLE_COMPATIBILITY_REPORTING=${ENABLE_COMPATIBILITY_REPORTING:-"OFF"} -DENABLE_COMPATIBILITY_LIST_DOWNLOAD=ON -DUSE_DISCORD_PRESENCE=ON ninja ccache -s diff --git a/.travis/macos/build.sh b/.travis/macos/build.sh index 0abd1a93a..db1c7cae7 100755 --- a/.travis/macos/build.sh +++ b/.travis/macos/build.sh @@ -4,13 +4,12 @@ set -o pipefail export MACOSX_DEPLOYMENT_TARGET=10.14 export Qt5_DIR=$(brew --prefix)/opt/qt5 -export UNICORNDIR=$(pwd)/externals/unicorn export PATH="/usr/local/opt/ccache/libexec:$PATH" # TODO: Build using ninja instead of make mkdir build && cd build cmake --version -cmake .. -DYUZU_USE_BUNDLED_UNICORN=ON -DYUZU_USE_QT_WEB_ENGINE=ON -DCMAKE_BUILD_TYPE=Release -DENABLE_COMPATIBILITY_LIST_DOWNLOAD=ON -DYUZU_ENABLE_COMPATIBILITY_REPORTING=${ENABLE_COMPATIBILITY_REPORTING:-"OFF"} -DUSE_DISCORD_PRESENCE=ON +cmake .. -DYUZU_USE_QT_WEB_ENGINE=ON -DCMAKE_BUILD_TYPE=Release -DENABLE_COMPATIBILITY_LIST_DOWNLOAD=ON -DYUZU_ENABLE_COMPATIBILITY_REPORTING=${ENABLE_COMPATIBILITY_REPORTING:-"OFF"} -DUSE_DISCORD_PRESENCE=ON make -j4 ccache -s diff --git a/CMakeLists.txt b/CMakeLists.txt index 1bd9d2aa7..8fc2de042 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -18,8 +18,6 @@ CMAKE_DEPENDENT_OPTION(YUZU_USE_BUNDLED_QT "Download bundled Qt binaries" ON "EN option(ENABLE_WEB_SERVICE "Enable web services (telemetry, etc.)" ON) -option(YUZU_USE_BUNDLED_UNICORN "Build/Download bundled Unicorn" ON) - option(YUZU_USE_QT_WEB_ENGINE "Use QtWebEngine for web applet implementation" OFF) option(YUZU_ENABLE_BOXCAT "Enable the Boxcat service, a yuzu high-level implementation of BCAT" ON) @@ -372,81 +370,6 @@ endif() set(THREADS_PREFER_PTHREAD_FLAG ON) find_package(Threads REQUIRED) -# If unicorn isn't found, msvc -> download bundled unicorn; everyone else -> build external -if (YUZU_USE_BUNDLED_UNICORN) - if (MSVC) - message(STATUS "unicorn not found, falling back to bundled") - # Detect toolchain and platform - if ((MSVC_VERSION GREATER_EQUAL 1910 AND MSVC_VERSION LESS 1930) AND ARCHITECTURE_x86_64) - set(UNICORN_VER "unicorn-yuzu") - else() - message(FATAL_ERROR "No bundled Unicorn binaries for your toolchain. Disable YUZU_USE_BUNDLED_UNICORN and provide your own.") - endif() - - if (DEFINED UNICORN_VER) - download_bundled_external("unicorn/" ${UNICORN_VER} UNICORN_PREFIX) - endif() - - if (DEFINED UNICORN_VER) - download_bundled_external("unicorn/" ${UNICORN_VER} UNICORN_PREFIX) - endif() - - set(UNICORN_FOUND YES) - set(LIBUNICORN_INCLUDE_DIR "${UNICORN_PREFIX}/include" CACHE PATH "Path to Unicorn headers" FORCE) - set(LIBUNICORN_LIBRARY "${UNICORN_PREFIX}/lib/x64/unicorn_dynload.lib" CACHE PATH "Path to Unicorn library" FORCE) - set(UNICORN_DLL_DIR "${UNICORN_PREFIX}/lib/x64/" CACHE PATH "Path to unicorn.dll" FORCE) - else() - message(STATUS "unicorn not found, falling back to externals") - if (MINGW) - set(UNICORN_LIB_NAME "unicorn.a") - else() - set(UNICORN_LIB_NAME "libunicorn.a") - endif() - - set(UNICORN_FOUND YES) - set(UNICORN_PREFIX ${PROJECT_SOURCE_DIR}/externals/unicorn) - set(LIBUNICORN_LIBRARY "${UNICORN_PREFIX}/${UNICORN_LIB_NAME}" CACHE PATH "Path to Unicorn library" FORCE) - set(LIBUNICORN_INCLUDE_DIR "${UNICORN_PREFIX}/include" CACHE PATH "Path to Unicorn headers" FORCE) - set(UNICORN_DLL_DIR "${UNICORN_PREFIX}/" CACHE PATH "Path to unicorn dynamic library" FORCE) - - find_package(PythonInterp 2.7 REQUIRED) - - if (MINGW) - # Intentionally call the unicorn makefile directly instead of using make.sh so that we can override the - # UNAME_S makefile variable to MINGW. This way we don't have to hack at the uname binary to build - # Additionally, overriding DO_WINDOWS_EXPORT prevents unicorn from patching the static unicorn.a by using msvc and cmd, - # which are both things we don't have in a mingw cross compiling environment. - add_custom_command(OUTPUT ${LIBUNICORN_LIBRARY} - COMMAND ${CMAKE_COMMAND} -E env UNICORN_ARCHS="aarch64" PYTHON="${PYTHON_EXECUTABLE}" CC=x86_64-w64-mingw32-gcc AR=x86_64-w64-mingw32-gcc-ar RANLIB=x86_64-w64-mingw32-gcc-ranlib make UNAME_S=MINGW DO_WINDOWS_EXPORT=0 - WORKING_DIRECTORY ${UNICORN_PREFIX} - ) - else() - add_custom_command(OUTPUT ${LIBUNICORN_LIBRARY} - COMMAND ${CMAKE_COMMAND} -E env UNICORN_ARCHS="aarch64" PYTHON="${PYTHON_EXECUTABLE}" /bin/sh make.sh macos-universal-no - WORKING_DIRECTORY ${UNICORN_PREFIX} - ) - endif() - - # ALL makes this custom target build every time - # but it won't actually build if LIBUNICORN_LIBRARY is up to date - add_custom_target(unicorn-build ALL - DEPENDS ${LIBUNICORN_LIBRARY} - ) - unset(UNICORN_LIB_NAME) - endif() -else() - find_package(Unicorn REQUIRED) -endif() - -if (UNICORN_FOUND) - add_library(unicorn INTERFACE) - add_dependencies(unicorn unicorn-build) - target_link_libraries(unicorn INTERFACE "${LIBUNICORN_LIBRARY}") - target_include_directories(unicorn INTERFACE "${LIBUNICORN_INCLUDE_DIR}") -else() - message(FATAL_ERROR "Could not find or build unicorn which is required.") -endif() - # Platform-specific library requirements # ====================================== diff --git a/CMakeModules/CopyYuzuUnicornDeps.cmake b/CMakeModules/CopyYuzuUnicornDeps.cmake deleted file mode 100644 index 7af0ef023..000000000 --- a/CMakeModules/CopyYuzuUnicornDeps.cmake +++ /dev/null @@ -1,9 +0,0 @@ -function(copy_yuzu_unicorn_deps target_dir) - include(WindowsCopyFiles) - set(DLL_DEST "${CMAKE_BINARY_DIR}/bin/$/") - windows_copy_files(${target_dir} ${UNICORN_DLL_DIR} ${DLL_DEST} - libgcc_s_seh-1.dll - libwinpthread-1.dll - unicorn.dll - ) -endfunction(copy_yuzu_unicorn_deps) diff --git a/externals/unicorn b/externals/unicorn deleted file mode 160000 index 73f457353..000000000 --- a/externals/unicorn +++ /dev/null @@ -1 +0,0 @@ -Subproject commit 73f45735354396766a4bfb26d0b96b06e5cf31b2 diff --git a/src/core/CMakeLists.txt b/src/core/CMakeLists.txt index e0f207f3e..19c926662 100644 --- a/src/core/CMakeLists.txt +++ b/src/core/CMakeLists.txt @@ -13,8 +13,6 @@ add_library(core STATIC arm/dynarmic/arm_exclusive_monitor.h arm/exclusive_monitor.cpp arm/exclusive_monitor.h - arm/unicorn/arm_unicorn.cpp - arm/unicorn/arm_unicorn.h constants.cpp constants.h core.cpp @@ -644,7 +642,7 @@ endif() create_target_directory_groups(core) target_link_libraries(core PUBLIC common PRIVATE audio_core video_core) -target_link_libraries(core PUBLIC Boost::boost PRIVATE fmt::fmt nlohmann_json::nlohmann_json mbedtls opus unicorn zip) +target_link_libraries(core PUBLIC Boost::boost PRIVATE fmt::fmt nlohmann_json::nlohmann_json mbedtls opus zip) if (YUZU_ENABLE_BOXCAT) target_compile_definitions(core PRIVATE -DYUZU_ENABLE_BOXCAT) diff --git a/src/core/arm/dynarmic/arm_dynarmic_32.cpp b/src/core/arm/dynarmic/arm_dynarmic_32.cpp index b5f28a86e..6dc03f3b1 100644 --- a/src/core/arm/dynarmic/arm_dynarmic_32.cpp +++ b/src/core/arm/dynarmic/arm_dynarmic_32.cpp @@ -7,6 +7,7 @@ #include #include #include +#include "common/assert.h" #include "common/logging/log.h" #include "common/page_table.h" #include "core/arm/cpu_interrupt_handler.h" diff --git a/src/core/arm/dynarmic/arm_dynarmic_64.cpp b/src/core/arm/dynarmic/arm_dynarmic_64.cpp index ce9968724..9f170a224 100644 --- a/src/core/arm/dynarmic/arm_dynarmic_64.cpp +++ b/src/core/arm/dynarmic/arm_dynarmic_64.cpp @@ -6,6 +6,7 @@ #include #include #include +#include "common/assert.h" #include "common/logging/log.h" #include "common/page_table.h" #include "core/arm/cpu_interrupt_handler.h" @@ -13,7 +14,6 @@ #include "core/arm/dynarmic/arm_exclusive_monitor.h" #include "core/core.h" #include "core/core_timing.h" -#include "core/core_timing_util.h" #include "core/gdbstub/gdbstub.h" #include "core/hardware_properties.h" #include "core/hle/kernel/process.h" @@ -82,16 +82,9 @@ public: } void InterpreterFallback(u64 pc, std::size_t num_instructions) override { - LOG_INFO(Core_ARM, "Unicorn fallback @ 0x{:X} for {} instructions (instr = {:08X})", pc, - num_instructions, MemoryReadCode(pc)); - - ARM_Interface::ThreadContext64 ctx; - parent.SaveContext(ctx); - parent.inner_unicorn.LoadContext(ctx); - parent.inner_unicorn.ExecuteInstructions(num_instructions); - parent.inner_unicorn.SaveContext(ctx); - parent.LoadContext(ctx); - num_interpreted_instructions += num_instructions; + LOG_ERROR(Core_ARM, + "Unimplemented instruction @ 0x{:X} for {} instructions (instr = {:08X})", pc, + num_instructions, MemoryReadCode(pc)); } void ExceptionRaised(u64 pc, Dynarmic::A64::Exception exception) override { @@ -127,18 +120,17 @@ public: if (parent.uses_wall_clock) { return; } + // Divide the number of ticks by the amount of CPU cores. TODO(Subv): This yields only a // rough approximation of the amount of executed ticks in the system, it may be thrown off // if not all cores are doing a similar amount of work. Instead of doing this, we should // device a way so that timing is consistent across all cores without increasing the ticks 4 // times. - u64 amortized_ticks = - (ticks - num_interpreted_instructions) / Core::Hardware::NUM_CPU_CORES; + u64 amortized_ticks = ticks / Core::Hardware::NUM_CPU_CORES; // Always execute at least one tick. amortized_ticks = std::max(amortized_ticks, 1); parent.system.CoreTiming().AddTicks(amortized_ticks); - num_interpreted_instructions = 0; } u64 GetTicksRemaining() override { @@ -156,7 +148,6 @@ public: } ARM_Dynarmic_64& parent; - std::size_t num_interpreted_instructions = 0; u64 tpidrro_el0 = 0; u64 tpidr_el0 = 0; static constexpr u64 minimum_run_cycles = 1000U; @@ -248,12 +239,8 @@ ARM_Dynarmic_64::ARM_Dynarmic_64(System& system, CPUInterrupts& interrupt_handle bool uses_wall_clock, ExclusiveMonitor& exclusive_monitor, std::size_t core_index) : ARM_Interface{system, interrupt_handlers, uses_wall_clock}, - cb(std::make_unique(*this)), inner_unicorn{system, interrupt_handlers, - uses_wall_clock, - ARM_Unicorn::Arch::AArch64, - core_index}, - core_index{core_index}, exclusive_monitor{ - dynamic_cast(exclusive_monitor)} {} + cb(std::make_unique(*this)), core_index{core_index}, + exclusive_monitor{dynamic_cast(exclusive_monitor)} {} ARM_Dynarmic_64::~ARM_Dynarmic_64() = default; diff --git a/src/core/arm/dynarmic/arm_dynarmic_64.h b/src/core/arm/dynarmic/arm_dynarmic_64.h index 403c55961..28e11a17d 100644 --- a/src/core/arm/dynarmic/arm_dynarmic_64.h +++ b/src/core/arm/dynarmic/arm_dynarmic_64.h @@ -12,7 +12,6 @@ #include "common/hash.h" #include "core/arm/arm_interface.h" #include "core/arm/exclusive_monitor.h" -#include "core/arm/unicorn/arm_unicorn.h" namespace Core::Memory { class Memory; @@ -71,7 +70,6 @@ private: std::unique_ptr cb; JitCacheType jit_cache; std::shared_ptr jit; - ARM_Unicorn inner_unicorn; std::size_t core_index; DynarmicExclusiveMonitor& exclusive_monitor; diff --git a/src/core/arm/unicorn/arm_unicorn.cpp b/src/core/arm/unicorn/arm_unicorn.cpp deleted file mode 100644 index 1df3f3ed1..000000000 --- a/src/core/arm/unicorn/arm_unicorn.cpp +++ /dev/null @@ -1,295 +0,0 @@ -// Copyright 2018 yuzu emulator team -// Licensed under GPLv2 or any later version -// Refer to the license.txt file included. - -#include -#include -#include "common/assert.h" -#include "common/microprofile.h" -#include "core/arm/cpu_interrupt_handler.h" -#include "core/arm/unicorn/arm_unicorn.h" -#include "core/core.h" -#include "core/core_timing.h" -#include "core/hle/kernel/scheduler.h" -#include "core/hle/kernel/svc.h" -#include "core/memory.h" - -namespace Core { - -// Load Unicorn DLL once on Windows using RAII -#ifdef _MSC_VER -#include -struct LoadDll { -private: - LoadDll() { - ASSERT(uc_dyn_load(NULL, 0)); - } - ~LoadDll() { - ASSERT(uc_dyn_free()); - } - static LoadDll g_load_dll; -}; -LoadDll LoadDll::g_load_dll; -#endif - -#define CHECKED(expr) \ - do { \ - if (auto _cerr = (expr)) { \ - ASSERT_MSG(false, "Call " #expr " failed with error: {} ({})\n", _cerr, \ - uc_strerror(_cerr)); \ - } \ - } while (0) - -static void CodeHook(uc_engine* uc, uint64_t address, uint32_t size, void* user_data) { - GDBStub::BreakpointAddress bkpt = - GDBStub::GetNextBreakpointFromAddress(address, GDBStub::BreakpointType::Execute); - if (GDBStub::IsMemoryBreak() || - (bkpt.type != GDBStub::BreakpointType::None && address == bkpt.address)) { - auto core = static_cast(user_data); - core->RecordBreak(bkpt); - uc_emu_stop(uc); - } -} - -static bool UnmappedMemoryHook(uc_engine* uc, uc_mem_type type, u64 addr, int size, u64 value, - void* user_data) { - auto* const system = static_cast(user_data); - - ARM_Interface::ThreadContext64 ctx{}; - system->CurrentArmInterface().SaveContext(ctx); - ASSERT_MSG(false, "Attempted to read from unmapped memory: 0x{:X}, pc=0x{:X}, lr=0x{:X}", addr, - ctx.pc, ctx.cpu_registers[30]); - - return false; -} - -ARM_Unicorn::ARM_Unicorn(System& system, CPUInterrupts& interrupt_handlers, bool uses_wall_clock, - Arch architecture, std::size_t core_index) - : ARM_Interface{system, interrupt_handlers, uses_wall_clock}, core_index{core_index} { - const auto arch = architecture == Arch::AArch32 ? UC_ARCH_ARM : UC_ARCH_ARM64; - CHECKED(uc_open(arch, UC_MODE_ARM, &uc)); - - auto fpv = 3 << 20; - CHECKED(uc_reg_write(uc, UC_ARM64_REG_CPACR_EL1, &fpv)); - - uc_hook hook{}; - CHECKED(uc_hook_add(uc, &hook, UC_HOOK_INTR, (void*)InterruptHook, this, 0, UINT64_MAX)); - CHECKED(uc_hook_add(uc, &hook, UC_HOOK_MEM_INVALID, (void*)UnmappedMemoryHook, &system, 0, - UINT64_MAX)); - if (GDBStub::IsServerEnabled()) { - CHECKED(uc_hook_add(uc, &hook, UC_HOOK_CODE, (void*)CodeHook, this, 0, UINT64_MAX)); - last_bkpt_hit = false; - } -} - -ARM_Unicorn::~ARM_Unicorn() { - CHECKED(uc_close(uc)); -} - -void ARM_Unicorn::SetPC(u64 pc) { - CHECKED(uc_reg_write(uc, UC_ARM64_REG_PC, &pc)); -} - -u64 ARM_Unicorn::GetPC() const { - u64 val{}; - CHECKED(uc_reg_read(uc, UC_ARM64_REG_PC, &val)); - return val; -} - -u64 ARM_Unicorn::GetReg(int regn) const { - u64 val{}; - auto treg = UC_ARM64_REG_SP; - if (regn <= 28) { - treg = (uc_arm64_reg)(UC_ARM64_REG_X0 + regn); - } else if (regn < 31) { - treg = (uc_arm64_reg)(UC_ARM64_REG_X29 + regn - 29); - } - CHECKED(uc_reg_read(uc, treg, &val)); - return val; -} - -void ARM_Unicorn::SetReg(int regn, u64 val) { - auto treg = UC_ARM64_REG_SP; - if (regn <= 28) { - treg = (uc_arm64_reg)(UC_ARM64_REG_X0 + regn); - } else if (regn < 31) { - treg = (uc_arm64_reg)(UC_ARM64_REG_X29 + regn - 29); - } - CHECKED(uc_reg_write(uc, treg, &val)); -} - -u128 ARM_Unicorn::GetVectorReg(int /*index*/) const { - UNIMPLEMENTED(); - static constexpr u128 res{}; - return res; -} - -void ARM_Unicorn::SetVectorReg(int /*index*/, u128 /*value*/) { - UNIMPLEMENTED(); -} - -u32 ARM_Unicorn::GetPSTATE() const { - u64 nzcv{}; - CHECKED(uc_reg_read(uc, UC_ARM64_REG_NZCV, &nzcv)); - return static_cast(nzcv); -} - -void ARM_Unicorn::SetPSTATE(u32 pstate) { - u64 nzcv = pstate; - CHECKED(uc_reg_write(uc, UC_ARM64_REG_NZCV, &nzcv)); -} - -VAddr ARM_Unicorn::GetTlsAddress() const { - u64 base{}; - CHECKED(uc_reg_read(uc, UC_ARM64_REG_TPIDRRO_EL0, &base)); - return base; -} - -void ARM_Unicorn::SetTlsAddress(VAddr base) { - CHECKED(uc_reg_write(uc, UC_ARM64_REG_TPIDRRO_EL0, &base)); -} - -u64 ARM_Unicorn::GetTPIDR_EL0() const { - u64 value{}; - CHECKED(uc_reg_read(uc, UC_ARM64_REG_TPIDR_EL0, &value)); - return value; -} - -void ARM_Unicorn::SetTPIDR_EL0(u64 value) { - CHECKED(uc_reg_write(uc, UC_ARM64_REG_TPIDR_EL0, &value)); -} - -void ARM_Unicorn::ChangeProcessorID(std::size_t new_core_id) { - core_index = new_core_id; -} - -void ARM_Unicorn::Run() { - if (GDBStub::IsServerEnabled()) { - ExecuteInstructions(std::max(4000000U, 0U)); - } else { - while (true) { - if (interrupt_handlers[core_index].IsInterrupted()) { - return; - } - ExecuteInstructions(10); - } - } -} - -void ARM_Unicorn::Step() { - ExecuteInstructions(1); -} - -MICROPROFILE_DEFINE(ARM_Jit_Unicorn, "ARM JIT", "Unicorn", MP_RGB(255, 64, 64)); - -void ARM_Unicorn::ExecuteInstructions(std::size_t num_instructions) { - MICROPROFILE_SCOPE(ARM_Jit_Unicorn); - - // Temporarily map the code page for Unicorn - u64 map_addr{GetPC() & ~Memory::PAGE_MASK}; - std::vector page_buffer(Memory::PAGE_SIZE); - system.Memory().ReadBlock(map_addr, page_buffer.data(), page_buffer.size()); - - CHECKED(uc_mem_map_ptr(uc, map_addr, page_buffer.size(), - UC_PROT_READ | UC_PROT_WRITE | UC_PROT_EXEC, page_buffer.data())); - CHECKED(uc_emu_start(uc, GetPC(), 1ULL << 63, 0, num_instructions)); - CHECKED(uc_mem_unmap(uc, map_addr, page_buffer.size())); - if (GDBStub::IsServerEnabled()) { - if (last_bkpt_hit && last_bkpt.type == GDBStub::BreakpointType::Execute) { - uc_reg_write(uc, UC_ARM64_REG_PC, &last_bkpt.address); - } - - Kernel::Thread* const thread = system.CurrentScheduler().GetCurrentThread(); - SaveContext(thread->GetContext64()); - if (last_bkpt_hit || GDBStub::IsMemoryBreak() || GDBStub::GetCpuStepFlag()) { - last_bkpt_hit = false; - GDBStub::Break(); - GDBStub::SendTrap(thread, 5); - } - } -} - -void ARM_Unicorn::SaveContext(ThreadContext64& ctx) { - int uregs[32]; - void* tregs[32]; - - CHECKED(uc_reg_read(uc, UC_ARM64_REG_SP, &ctx.sp)); - CHECKED(uc_reg_read(uc, UC_ARM64_REG_PC, &ctx.pc)); - CHECKED(uc_reg_read(uc, UC_ARM64_REG_NZCV, &ctx.pstate)); - - for (auto i = 0; i < 29; ++i) { - uregs[i] = UC_ARM64_REG_X0 + i; - tregs[i] = &ctx.cpu_registers[i]; - } - uregs[29] = UC_ARM64_REG_X29; - tregs[29] = (void*)&ctx.cpu_registers[29]; - uregs[30] = UC_ARM64_REG_X30; - tregs[30] = (void*)&ctx.cpu_registers[30]; - - CHECKED(uc_reg_read_batch(uc, uregs, tregs, 31)); - - for (int i = 0; i < 32; ++i) { - uregs[i] = UC_ARM64_REG_Q0 + i; - tregs[i] = &ctx.vector_registers[i]; - } - - CHECKED(uc_reg_read_batch(uc, uregs, tregs, 32)); -} - -void ARM_Unicorn::LoadContext(const ThreadContext64& ctx) { - int uregs[32]; - void* tregs[32]; - - CHECKED(uc_reg_write(uc, UC_ARM64_REG_SP, &ctx.sp)); - CHECKED(uc_reg_write(uc, UC_ARM64_REG_PC, &ctx.pc)); - CHECKED(uc_reg_write(uc, UC_ARM64_REG_NZCV, &ctx.pstate)); - - for (int i = 0; i < 29; ++i) { - uregs[i] = UC_ARM64_REG_X0 + i; - tregs[i] = (void*)&ctx.cpu_registers[i]; - } - uregs[29] = UC_ARM64_REG_X29; - tregs[29] = (void*)&ctx.cpu_registers[29]; - uregs[30] = UC_ARM64_REG_X30; - tregs[30] = (void*)&ctx.cpu_registers[30]; - - CHECKED(uc_reg_write_batch(uc, uregs, tregs, 31)); - - for (auto i = 0; i < 32; ++i) { - uregs[i] = UC_ARM64_REG_Q0 + i; - tregs[i] = (void*)&ctx.vector_registers[i]; - } - - CHECKED(uc_reg_write_batch(uc, uregs, tregs, 32)); -} - -void ARM_Unicorn::PrepareReschedule() { - CHECKED(uc_emu_stop(uc)); -} - -void ARM_Unicorn::ClearExclusiveState() {} - -void ARM_Unicorn::ClearInstructionCache() {} - -void ARM_Unicorn::RecordBreak(GDBStub::BreakpointAddress bkpt) { - last_bkpt = bkpt; - last_bkpt_hit = true; -} - -void ARM_Unicorn::InterruptHook(uc_engine* uc, u32 int_no, void* user_data) { - u32 esr{}; - CHECKED(uc_reg_read(uc, UC_ARM64_REG_ESR, &esr)); - - const auto ec = esr >> 26; - const auto iss = esr & 0xFFFFFF; - - auto* const arm_instance = static_cast(user_data); - - switch (ec) { - case 0x15: // SVC - Kernel::Svc::Call(arm_instance->system, iss); - break; - } -} - -} // namespace Core diff --git a/src/core/arm/unicorn/arm_unicorn.h b/src/core/arm/unicorn/arm_unicorn.h deleted file mode 100644 index 810aff311..000000000 --- a/src/core/arm/unicorn/arm_unicorn.h +++ /dev/null @@ -1,63 +0,0 @@ -// Copyright 2018 yuzu emulator team -// Licensed under GPLv2 or any later version -// Refer to the license.txt file included. - -#pragma once - -#include -#include "common/common_types.h" -#include "core/arm/arm_interface.h" -#include "core/gdbstub/gdbstub.h" - -namespace Core { - -class System; - -class ARM_Unicorn final : public ARM_Interface { -public: - enum class Arch { - AArch32, // 32-bit ARM - AArch64, // 64-bit ARM - }; - - explicit ARM_Unicorn(System& system, CPUInterrupts& interrupt_handlers, bool uses_wall_clock, - Arch architecture, std::size_t core_index); - ~ARM_Unicorn() override; - - void SetPC(u64 pc) override; - u64 GetPC() const override; - u64 GetReg(int index) const override; - void SetReg(int index, u64 value) override; - u128 GetVectorReg(int index) const override; - void SetVectorReg(int index, u128 value) override; - u32 GetPSTATE() const override; - void SetPSTATE(u32 pstate) override; - VAddr GetTlsAddress() const override; - void SetTlsAddress(VAddr address) override; - void SetTPIDR_EL0(u64 value) override; - u64 GetTPIDR_EL0() const override; - void ChangeProcessorID(std::size_t new_core_id) override; - void PrepareReschedule() override; - void ClearExclusiveState() override; - void ExecuteInstructions(std::size_t num_instructions); - void Run() override; - void Step() override; - void ClearInstructionCache() override; - void PageTableChanged(Common::PageTable&, std::size_t) override {} - void RecordBreak(GDBStub::BreakpointAddress bkpt); - - void SaveContext(ThreadContext32& ctx) override {} - void SaveContext(ThreadContext64& ctx) override; - void LoadContext(const ThreadContext32& ctx) override {} - void LoadContext(const ThreadContext64& ctx) override; - -private: - static void InterruptHook(uc_engine* uc, u32 int_no, void* user_data); - - uc_engine* uc{}; - GDBStub::BreakpointAddress last_bkpt{}; - bool last_bkpt_hit = false; - std::size_t core_index; -}; - -} // namespace Core diff --git a/src/core/hle/kernel/physical_core.cpp b/src/core/hle/kernel/physical_core.cpp index c6bbdb080..6e04d025f 100644 --- a/src/core/hle/kernel/physical_core.cpp +++ b/src/core/hle/kernel/physical_core.cpp @@ -2,30 +2,18 @@ // Licensed under GPLv2 or any later version // Refer to the license.txt file included. -#include "common/assert.h" -#include "common/logging/log.h" #include "common/spin_lock.h" -#include "core/arm/arm_interface.h" -#ifdef ARCHITECTURE_x86_64 -#include "core/arm/dynarmic/arm_dynarmic_32.h" -#include "core/arm/dynarmic/arm_dynarmic_64.h" -#endif #include "core/arm/cpu_interrupt_handler.h" -#include "core/arm/exclusive_monitor.h" -#include "core/arm/unicorn/arm_unicorn.h" #include "core/core.h" #include "core/hle/kernel/physical_core.h" #include "core/hle/kernel/scheduler.h" -#include "core/hle/kernel/thread.h" namespace Kernel { PhysicalCore::PhysicalCore(Core::System& system, std::size_t id, Kernel::Scheduler& scheduler, Core::CPUInterruptHandler& interrupt_handler) - : interrupt_handler{interrupt_handler}, core_index{id}, scheduler{scheduler} { - - guard = std::make_unique(); -} + : interrupt_handler{interrupt_handler}, + core_index{id}, scheduler{scheduler}, guard{std::make_unique()} {} PhysicalCore::~PhysicalCore() = default; diff --git a/src/core/hle/kernel/thread.cpp b/src/core/hle/kernel/thread.cpp index d132aba34..da0cb26b6 100644 --- a/src/core/hle/kernel/thread.cpp +++ b/src/core/hle/kernel/thread.cpp @@ -13,7 +13,6 @@ #include "common/logging/log.h" #include "common/thread_queue_list.h" #include "core/arm/arm_interface.h" -#include "core/arm/unicorn/arm_unicorn.h" #include "core/core.h" #include "core/cpu_manager.h" #include "core/hardware_properties.h" @@ -217,8 +216,7 @@ ResultVal> Thread::Create(Core::System& system, ThreadTy } else { thread->tls_address = 0; } - // TODO(peachum): move to ScheduleThread() when scheduler is added so selected core is used - // to initialize the context + thread->arm_interface.reset(); if ((type_flags & THREADTYPE_HLE) == 0) { #ifdef ARCHITECTURE_x86_64 @@ -231,19 +229,10 @@ ResultVal> Thread::Create(Core::System& system, ThreadTy system, kernel.Interrupts(), kernel.IsMulticore(), kernel.GetExclusiveMonitor(), processor_id); } - #else - if (owner_process && !owner_process->Is64BitProcess()) { - thread->arm_interface = std::make_shared( - system, kernel.Interrupts(), kernel.IsMulticore(), ARM_Unicorn::Arch::AArch32, - processor_id); - } else { - thread->arm_interface = std::make_shared( - system, kernel.Interrupts(), kernel.IsMulticore(), ARM_Unicorn::Arch::AArch64, - processor_id); - } - LOG_WARNING(Core, "CPU JIT requested, but Dynarmic not available"); +#error Platform not supported yet. #endif + ResetThreadContext32(thread->context_32, static_cast(stack_top), static_cast(entry_point), static_cast(arg)); ResetThreadContext64(thread->context_64, stack_top, entry_point, arg); diff --git a/src/yuzu/CMakeLists.txt b/src/yuzu/CMakeLists.txt index 4659e1f89..8abb74d56 100644 --- a/src/yuzu/CMakeLists.txt +++ b/src/yuzu/CMakeLists.txt @@ -264,11 +264,9 @@ endif() if (MSVC) include(CopyYuzuQt5Deps) include(CopyYuzuSDLDeps) - include(CopyYuzuUnicornDeps) include(CopyYuzuFFmpegDeps) copy_yuzu_Qt5_deps(yuzu) copy_yuzu_SDL_deps(yuzu) - copy_yuzu_unicorn_deps(yuzu) copy_yuzu_FFmpeg_deps(yuzu) endif() diff --git a/src/yuzu_cmd/CMakeLists.txt b/src/yuzu_cmd/CMakeLists.txt index a15719a0f..57f9916f6 100644 --- a/src/yuzu_cmd/CMakeLists.txt +++ b/src/yuzu_cmd/CMakeLists.txt @@ -39,7 +39,5 @@ endif() if (MSVC) include(CopyYuzuSDLDeps) - include(CopyYuzuUnicornDeps) copy_yuzu_SDL_deps(yuzu-cmd) - copy_yuzu_unicorn_deps(yuzu-cmd) endif() diff --git a/src/yuzu_tester/CMakeLists.txt b/src/yuzu_tester/CMakeLists.txt index 06c2ee011..d8a2a1511 100644 --- a/src/yuzu_tester/CMakeLists.txt +++ b/src/yuzu_tester/CMakeLists.txt @@ -28,7 +28,5 @@ endif() if (MSVC) include(CopyYuzuSDLDeps) - include(CopyYuzuUnicornDeps) copy_yuzu_SDL_deps(yuzu-tester) - copy_yuzu_unicorn_deps(yuzu-tester) endif()