summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorGravatar Lioncash2020-11-03 19:54:53 -0500
committerGravatar Lioncash2020-11-03 20:22:05 -0500
commitfc6db97a09e2de5eff10131ddcab9cf8fb2f736c (patch)
tree32a7b408286eb84360bcaff2961dbaa874f5a5d3
parentMerge pull request #4887 from lioncash/common-build (diff)
downloadyuzu-fc6db97a09e2de5eff10131ddcab9cf8fb2f736c.tar.gz
yuzu-fc6db97a09e2de5eff10131ddcab9cf8fb2f736c.tar.xz
yuzu-fc6db97a09e2de5eff10131ddcab9cf8fb2f736c.zip
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.
Diffstat (limited to '')
-rw-r--r--.gitmodules3
-rwxr-xr-x.travis/linux-mingw/docker.sh10
-rwxr-xr-x.travis/linux/docker.sh2
-rwxr-xr-x.travis/macos/build.sh3
-rw-r--r--CMakeLists.txt77
-rw-r--r--CMakeModules/CopyYuzuUnicornDeps.cmake9
m---------externals/unicorn0
-rw-r--r--src/core/CMakeLists.txt4
-rw-r--r--src/core/arm/dynarmic/arm_dynarmic_32.cpp1
-rw-r--r--src/core/arm/dynarmic/arm_dynarmic_64.cpp29
-rw-r--r--src/core/arm/dynarmic/arm_dynarmic_64.h2
-rw-r--r--src/core/arm/unicorn/arm_unicorn.cpp295
-rw-r--r--src/core/arm/unicorn/arm_unicorn.h63
-rw-r--r--src/core/hle/kernel/physical_core.cpp16
-rw-r--r--src/core/hle/kernel/thread.cpp17
-rw-r--r--src/yuzu/CMakeLists.txt2
-rw-r--r--src/yuzu_cmd/CMakeLists.txt2
-rw-r--r--src/yuzu_tester/CMakeLists.txt2
18 files changed, 18 insertions, 519 deletions
diff --git a/.gitmodules b/.gitmodules
index 6931a641d..41022615b 100644
--- a/.gitmodules
+++ b/.gitmodules
@@ -7,9 +7,6 @@
7[submodule "dynarmic"] 7[submodule "dynarmic"]
8 path = externals/dynarmic 8 path = externals/dynarmic
9 url = https://github.com/MerryMage/dynarmic.git 9 url = https://github.com/MerryMage/dynarmic.git
10[submodule "unicorn"]
11 path = externals/unicorn
12 url = https://github.com/yuzu-emu/unicorn
13[submodule "soundtouch"] 10[submodule "soundtouch"]
14 path = externals/soundtouch 11 path = externals/soundtouch
15 url = https://github.com/citra-emu/ext-soundtouch.git 12 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
4# override Travis CI unreasonable ccache size 4# override Travis CI unreasonable ccache size
5echo 'max_size = 3.0G' > "$HOME/.ccache/ccache.conf" 5echo 'max_size = 3.0G' > "$HOME/.ccache/ccache.conf"
6 6
7# Dirty hack to trick unicorn makefile into believing we are in a MINGW system
8mv /bin/uname /bin/uname1 && echo -e '#!/bin/sh\necho MINGW64' >> /bin/uname
9chmod +x /bin/uname
10
11# Dirty hack to trick unicorn makefile into believing we have cmd
12echo '' >> /bin/cmd
13chmod +x /bin/cmd
14
15mkdir build && cd build 7mkdir build && cd build
16cmake .. -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 8cmake .. -G Ninja -DCMAKE_TOOLCHAIN_FILE="$(pwd)/../CMakeModules/MinGWCross.cmake" -DUSE_CCACHE=ON -DENABLE_COMPATIBILITY_LIST_DOWNLOAD=ON -DCMAKE_BUILD_TYPE=Release
17ninja 9ninja
18 10
19# Clean up the dirty hacks 11# 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 @@
3cd /yuzu 3cd /yuzu
4 4
5mkdir build && cd build 5mkdir build && cd build
6cmake .. -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 6cmake .. -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
7ninja 7ninja
8 8
9ccache -s 9ccache -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
4 4
5export MACOSX_DEPLOYMENT_TARGET=10.14 5export MACOSX_DEPLOYMENT_TARGET=10.14
6export Qt5_DIR=$(brew --prefix)/opt/qt5 6export Qt5_DIR=$(brew --prefix)/opt/qt5
7export UNICORNDIR=$(pwd)/externals/unicorn
8export PATH="/usr/local/opt/ccache/libexec:$PATH" 7export PATH="/usr/local/opt/ccache/libexec:$PATH"
9 8
10# TODO: Build using ninja instead of make 9# TODO: Build using ninja instead of make
11mkdir build && cd build 10mkdir build && cd build
12cmake --version 11cmake --version
13cmake .. -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 12cmake .. -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
14make -j4 13make -j4
15 14
16ccache -s 15ccache -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
18 18
19option(ENABLE_WEB_SERVICE "Enable web services (telemetry, etc.)" ON) 19option(ENABLE_WEB_SERVICE "Enable web services (telemetry, etc.)" ON)
20 20
21option(YUZU_USE_BUNDLED_UNICORN "Build/Download bundled Unicorn" ON)
22
23option(YUZU_USE_QT_WEB_ENGINE "Use QtWebEngine for web applet implementation" OFF) 21option(YUZU_USE_QT_WEB_ENGINE "Use QtWebEngine for web applet implementation" OFF)
24 22
25option(YUZU_ENABLE_BOXCAT "Enable the Boxcat service, a yuzu high-level implementation of BCAT" ON) 23option(YUZU_ENABLE_BOXCAT "Enable the Boxcat service, a yuzu high-level implementation of BCAT" ON)
@@ -372,81 +370,6 @@ endif()
372set(THREADS_PREFER_PTHREAD_FLAG ON) 370set(THREADS_PREFER_PTHREAD_FLAG ON)
373find_package(Threads REQUIRED) 371find_package(Threads REQUIRED)
374 372
375# If unicorn isn't found, msvc -> download bundled unicorn; everyone else -> build external
376if (YUZU_USE_BUNDLED_UNICORN)
377 if (MSVC)
378 message(STATUS "unicorn not found, falling back to bundled")
379 # Detect toolchain and platform
380 if ((MSVC_VERSION GREATER_EQUAL 1910 AND MSVC_VERSION LESS 1930) AND ARCHITECTURE_x86_64)
381 set(UNICORN_VER "unicorn-yuzu")
382 else()
383 message(FATAL_ERROR "No bundled Unicorn binaries for your toolchain. Disable YUZU_USE_BUNDLED_UNICORN and provide your own.")
384 endif()
385
386 if (DEFINED UNICORN_VER)
387 download_bundled_external("unicorn/" ${UNICORN_VER} UNICORN_PREFIX)
388 endif()
389
390 if (DEFINED UNICORN_VER)
391 download_bundled_external("unicorn/" ${UNICORN_VER} UNICORN_PREFIX)
392 endif()
393
394 set(UNICORN_FOUND YES)
395 set(LIBUNICORN_INCLUDE_DIR "${UNICORN_PREFIX}/include" CACHE PATH "Path to Unicorn headers" FORCE)
396 set(LIBUNICORN_LIBRARY "${UNICORN_PREFIX}/lib/x64/unicorn_dynload.lib" CACHE PATH "Path to Unicorn library" FORCE)
397 set(UNICORN_DLL_DIR "${UNICORN_PREFIX}/lib/x64/" CACHE PATH "Path to unicorn.dll" FORCE)
398 else()
399 message(STATUS "unicorn not found, falling back to externals")
400 if (MINGW)
401 set(UNICORN_LIB_NAME "unicorn.a")
402 else()
403 set(UNICORN_LIB_NAME "libunicorn.a")
404 endif()
405
406 set(UNICORN_FOUND YES)
407 set(UNICORN_PREFIX ${PROJECT_SOURCE_DIR}/externals/unicorn)
408 set(LIBUNICORN_LIBRARY "${UNICORN_PREFIX}/${UNICORN_LIB_NAME}" CACHE PATH "Path to Unicorn library" FORCE)
409 set(LIBUNICORN_INCLUDE_DIR "${UNICORN_PREFIX}/include" CACHE PATH "Path to Unicorn headers" FORCE)
410 set(UNICORN_DLL_DIR "${UNICORN_PREFIX}/" CACHE PATH "Path to unicorn dynamic library" FORCE)
411
412 find_package(PythonInterp 2.7 REQUIRED)
413
414 if (MINGW)
415 # Intentionally call the unicorn makefile directly instead of using make.sh so that we can override the
416 # UNAME_S makefile variable to MINGW. This way we don't have to hack at the uname binary to build
417 # Additionally, overriding DO_WINDOWS_EXPORT prevents unicorn from patching the static unicorn.a by using msvc and cmd,
418 # which are both things we don't have in a mingw cross compiling environment.
419 add_custom_command(OUTPUT ${LIBUNICORN_LIBRARY}
420 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
421 WORKING_DIRECTORY ${UNICORN_PREFIX}
422 )
423 else()
424 add_custom_command(OUTPUT ${LIBUNICORN_LIBRARY}
425 COMMAND ${CMAKE_COMMAND} -E env UNICORN_ARCHS="aarch64" PYTHON="${PYTHON_EXECUTABLE}" /bin/sh make.sh macos-universal-no
426 WORKING_DIRECTORY ${UNICORN_PREFIX}
427 )
428 endif()
429
430 # ALL makes this custom target build every time
431 # but it won't actually build if LIBUNICORN_LIBRARY is up to date
432 add_custom_target(unicorn-build ALL
433 DEPENDS ${LIBUNICORN_LIBRARY}
434 )
435 unset(UNICORN_LIB_NAME)
436 endif()
437else()
438 find_package(Unicorn REQUIRED)
439endif()
440
441if (UNICORN_FOUND)
442 add_library(unicorn INTERFACE)
443 add_dependencies(unicorn unicorn-build)
444 target_link_libraries(unicorn INTERFACE "${LIBUNICORN_LIBRARY}")
445 target_include_directories(unicorn INTERFACE "${LIBUNICORN_INCLUDE_DIR}")
446else()
447 message(FATAL_ERROR "Could not find or build unicorn which is required.")
448endif()
449
450# Platform-specific library requirements 373# Platform-specific library requirements
451# ====================================== 374# ======================================
452 375
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 @@
1function(copy_yuzu_unicorn_deps target_dir)
2 include(WindowsCopyFiles)
3 set(DLL_DEST "${CMAKE_BINARY_DIR}/bin/$<CONFIG>/")
4 windows_copy_files(${target_dir} ${UNICORN_DLL_DIR} ${DLL_DEST}
5 libgcc_s_seh-1.dll
6 libwinpthread-1.dll
7 unicorn.dll
8 )
9endfunction(copy_yuzu_unicorn_deps)
diff --git a/externals/unicorn b/externals/unicorn
deleted file mode 160000
Subproject 73f45735354396766a4bfb26d0b96b06e5cf31b
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
13 arm/dynarmic/arm_exclusive_monitor.h 13 arm/dynarmic/arm_exclusive_monitor.h
14 arm/exclusive_monitor.cpp 14 arm/exclusive_monitor.cpp
15 arm/exclusive_monitor.h 15 arm/exclusive_monitor.h
16 arm/unicorn/arm_unicorn.cpp
17 arm/unicorn/arm_unicorn.h
18 constants.cpp 16 constants.cpp
19 constants.h 17 constants.h
20 core.cpp 18 core.cpp
@@ -644,7 +642,7 @@ endif()
644create_target_directory_groups(core) 642create_target_directory_groups(core)
645 643
646target_link_libraries(core PUBLIC common PRIVATE audio_core video_core) 644target_link_libraries(core PUBLIC common PRIVATE audio_core video_core)
647target_link_libraries(core PUBLIC Boost::boost PRIVATE fmt::fmt nlohmann_json::nlohmann_json mbedtls opus unicorn zip) 645target_link_libraries(core PUBLIC Boost::boost PRIVATE fmt::fmt nlohmann_json::nlohmann_json mbedtls opus zip)
648 646
649if (YUZU_ENABLE_BOXCAT) 647if (YUZU_ENABLE_BOXCAT)
650 target_compile_definitions(core PRIVATE -DYUZU_ENABLE_BOXCAT) 648 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 @@
7#include <dynarmic/A32/a32.h> 7#include <dynarmic/A32/a32.h>
8#include <dynarmic/A32/config.h> 8#include <dynarmic/A32/config.h>
9#include <dynarmic/A32/context.h> 9#include <dynarmic/A32/context.h>
10#include "common/assert.h"
10#include "common/logging/log.h" 11#include "common/logging/log.h"
11#include "common/page_table.h" 12#include "common/page_table.h"
12#include "core/arm/cpu_interrupt_handler.h" 13#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 @@
6#include <memory> 6#include <memory>
7#include <dynarmic/A64/a64.h> 7#include <dynarmic/A64/a64.h>
8#include <dynarmic/A64/config.h> 8#include <dynarmic/A64/config.h>
9#include "common/assert.h"
9#include "common/logging/log.h" 10#include "common/logging/log.h"
10#include "common/page_table.h" 11#include "common/page_table.h"
11#include "core/arm/cpu_interrupt_handler.h" 12#include "core/arm/cpu_interrupt_handler.h"
@@ -13,7 +14,6 @@
13#include "core/arm/dynarmic/arm_exclusive_monitor.h" 14#include "core/arm/dynarmic/arm_exclusive_monitor.h"
14#include "core/core.h" 15#include "core/core.h"
15#include "core/core_timing.h" 16#include "core/core_timing.h"
16#include "core/core_timing_util.h"
17#include "core/gdbstub/gdbstub.h" 17#include "core/gdbstub/gdbstub.h"
18#include "core/hardware_properties.h" 18#include "core/hardware_properties.h"
19#include "core/hle/kernel/process.h" 19#include "core/hle/kernel/process.h"
@@ -82,16 +82,9 @@ public:
82 } 82 }
83 83
84 void InterpreterFallback(u64 pc, std::size_t num_instructions) override { 84 void InterpreterFallback(u64 pc, std::size_t num_instructions) override {
85 LOG_INFO(Core_ARM, "Unicorn fallback @ 0x{:X} for {} instructions (instr = {:08X})", pc, 85 LOG_ERROR(Core_ARM,
86 num_instructions, MemoryReadCode(pc)); 86 "Unimplemented instruction @ 0x{:X} for {} instructions (instr = {:08X})", pc,
87 87 num_instructions, MemoryReadCode(pc));
88 ARM_Interface::ThreadContext64 ctx;
89 parent.SaveContext(ctx);
90 parent.inner_unicorn.LoadContext(ctx);
91 parent.inner_unicorn.ExecuteInstructions(num_instructions);
92 parent.inner_unicorn.SaveContext(ctx);
93 parent.LoadContext(ctx);
94 num_interpreted_instructions += num_instructions;
95 } 88 }
96 89
97 void ExceptionRaised(u64 pc, Dynarmic::A64::Exception exception) override { 90 void ExceptionRaised(u64 pc, Dynarmic::A64::Exception exception) override {
@@ -127,18 +120,17 @@ public:
127 if (parent.uses_wall_clock) { 120 if (parent.uses_wall_clock) {
128 return; 121 return;
129 } 122 }
123
130 // Divide the number of ticks by the amount of CPU cores. TODO(Subv): This yields only a 124 // Divide the number of ticks by the amount of CPU cores. TODO(Subv): This yields only a
131 // rough approximation of the amount of executed ticks in the system, it may be thrown off 125 // rough approximation of the amount of executed ticks in the system, it may be thrown off
132 // if not all cores are doing a similar amount of work. Instead of doing this, we should 126 // if not all cores are doing a similar amount of work. Instead of doing this, we should
133 // device a way so that timing is consistent across all cores without increasing the ticks 4 127 // device a way so that timing is consistent across all cores without increasing the ticks 4
134 // times. 128 // times.
135 u64 amortized_ticks = 129 u64 amortized_ticks = ticks / Core::Hardware::NUM_CPU_CORES;
136 (ticks - num_interpreted_instructions) / Core::Hardware::NUM_CPU_CORES;
137 // Always execute at least one tick. 130 // Always execute at least one tick.
138 amortized_ticks = std::max<u64>(amortized_ticks, 1); 131 amortized_ticks = std::max<u64>(amortized_ticks, 1);
139 132
140 parent.system.CoreTiming().AddTicks(amortized_ticks); 133 parent.system.CoreTiming().AddTicks(amortized_ticks);
141 num_interpreted_instructions = 0;
142 } 134 }
143 135
144 u64 GetTicksRemaining() override { 136 u64 GetTicksRemaining() override {
@@ -156,7 +148,6 @@ public:
156 } 148 }
157 149
158 ARM_Dynarmic_64& parent; 150 ARM_Dynarmic_64& parent;
159 std::size_t num_interpreted_instructions = 0;
160 u64 tpidrro_el0 = 0; 151 u64 tpidrro_el0 = 0;
161 u64 tpidr_el0 = 0; 152 u64 tpidr_el0 = 0;
162 static constexpr u64 minimum_run_cycles = 1000U; 153 static constexpr u64 minimum_run_cycles = 1000U;
@@ -248,12 +239,8 @@ ARM_Dynarmic_64::ARM_Dynarmic_64(System& system, CPUInterrupts& interrupt_handle
248 bool uses_wall_clock, ExclusiveMonitor& exclusive_monitor, 239 bool uses_wall_clock, ExclusiveMonitor& exclusive_monitor,
249 std::size_t core_index) 240 std::size_t core_index)
250 : ARM_Interface{system, interrupt_handlers, uses_wall_clock}, 241 : ARM_Interface{system, interrupt_handlers, uses_wall_clock},
251 cb(std::make_unique<DynarmicCallbacks64>(*this)), inner_unicorn{system, interrupt_handlers, 242 cb(std::make_unique<DynarmicCallbacks64>(*this)), core_index{core_index},
252 uses_wall_clock, 243 exclusive_monitor{dynamic_cast<DynarmicExclusiveMonitor&>(exclusive_monitor)} {}
253 ARM_Unicorn::Arch::AArch64,
254 core_index},
255 core_index{core_index}, exclusive_monitor{
256 dynamic_cast<DynarmicExclusiveMonitor&>(exclusive_monitor)} {}
257 244
258ARM_Dynarmic_64::~ARM_Dynarmic_64() = default; 245ARM_Dynarmic_64::~ARM_Dynarmic_64() = default;
259 246
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 @@
12#include "common/hash.h" 12#include "common/hash.h"
13#include "core/arm/arm_interface.h" 13#include "core/arm/arm_interface.h"
14#include "core/arm/exclusive_monitor.h" 14#include "core/arm/exclusive_monitor.h"
15#include "core/arm/unicorn/arm_unicorn.h"
16 15
17namespace Core::Memory { 16namespace Core::Memory {
18class Memory; 17class Memory;
@@ -71,7 +70,6 @@ private:
71 std::unique_ptr<DynarmicCallbacks64> cb; 70 std::unique_ptr<DynarmicCallbacks64> cb;
72 JitCacheType jit_cache; 71 JitCacheType jit_cache;
73 std::shared_ptr<Dynarmic::A64::Jit> jit; 72 std::shared_ptr<Dynarmic::A64::Jit> jit;
74 ARM_Unicorn inner_unicorn;
75 73
76 std::size_t core_index; 74 std::size_t core_index;
77 DynarmicExclusiveMonitor& exclusive_monitor; 75 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 @@
1// Copyright 2018 yuzu emulator team
2// Licensed under GPLv2 or any later version
3// Refer to the license.txt file included.
4
5#include <algorithm>
6#include <unicorn/arm64.h>
7#include "common/assert.h"
8#include "common/microprofile.h"
9#include "core/arm/cpu_interrupt_handler.h"
10#include "core/arm/unicorn/arm_unicorn.h"
11#include "core/core.h"
12#include "core/core_timing.h"
13#include "core/hle/kernel/scheduler.h"
14#include "core/hle/kernel/svc.h"
15#include "core/memory.h"
16
17namespace Core {
18
19// Load Unicorn DLL once on Windows using RAII
20#ifdef _MSC_VER
21#include <unicorn_dynload.h>
22struct LoadDll {
23private:
24 LoadDll() {
25 ASSERT(uc_dyn_load(NULL, 0));
26 }
27 ~LoadDll() {
28 ASSERT(uc_dyn_free());
29 }
30 static LoadDll g_load_dll;
31};
32LoadDll LoadDll::g_load_dll;
33#endif
34
35#define CHECKED(expr) \
36 do { \
37 if (auto _cerr = (expr)) { \
38 ASSERT_MSG(false, "Call " #expr " failed with error: {} ({})\n", _cerr, \
39 uc_strerror(_cerr)); \
40 } \
41 } while (0)
42
43static void CodeHook(uc_engine* uc, uint64_t address, uint32_t size, void* user_data) {
44 GDBStub::BreakpointAddress bkpt =
45 GDBStub::GetNextBreakpointFromAddress(address, GDBStub::BreakpointType::Execute);
46 if (GDBStub::IsMemoryBreak() ||
47 (bkpt.type != GDBStub::BreakpointType::None && address == bkpt.address)) {
48 auto core = static_cast<ARM_Unicorn*>(user_data);
49 core->RecordBreak(bkpt);
50 uc_emu_stop(uc);
51 }
52}
53
54static bool UnmappedMemoryHook(uc_engine* uc, uc_mem_type type, u64 addr, int size, u64 value,
55 void* user_data) {
56 auto* const system = static_cast<System*>(user_data);
57
58 ARM_Interface::ThreadContext64 ctx{};
59 system->CurrentArmInterface().SaveContext(ctx);
60 ASSERT_MSG(false, "Attempted to read from unmapped memory: 0x{:X}, pc=0x{:X}, lr=0x{:X}", addr,
61 ctx.pc, ctx.cpu_registers[30]);
62
63 return false;
64}
65
66ARM_Unicorn::ARM_Unicorn(System& system, CPUInterrupts& interrupt_handlers, bool uses_wall_clock,
67 Arch architecture, std::size_t core_index)
68 : ARM_Interface{system, interrupt_handlers, uses_wall_clock}, core_index{core_index} {
69 const auto arch = architecture == Arch::AArch32 ? UC_ARCH_ARM : UC_ARCH_ARM64;
70 CHECKED(uc_open(arch, UC_MODE_ARM, &uc));
71
72 auto fpv = 3 << 20;
73 CHECKED(uc_reg_write(uc, UC_ARM64_REG_CPACR_EL1, &fpv));
74
75 uc_hook hook{};
76 CHECKED(uc_hook_add(uc, &hook, UC_HOOK_INTR, (void*)InterruptHook, this, 0, UINT64_MAX));
77 CHECKED(uc_hook_add(uc, &hook, UC_HOOK_MEM_INVALID, (void*)UnmappedMemoryHook, &system, 0,
78 UINT64_MAX));
79 if (GDBStub::IsServerEnabled()) {
80 CHECKED(uc_hook_add(uc, &hook, UC_HOOK_CODE, (void*)CodeHook, this, 0, UINT64_MAX));
81 last_bkpt_hit = false;
82 }
83}
84
85ARM_Unicorn::~ARM_Unicorn() {
86 CHECKED(uc_close(uc));
87}
88
89void ARM_Unicorn::SetPC(u64 pc) {
90 CHECKED(uc_reg_write(uc, UC_ARM64_REG_PC, &pc));
91}
92
93u64 ARM_Unicorn::GetPC() const {
94 u64 val{};
95 CHECKED(uc_reg_read(uc, UC_ARM64_REG_PC, &val));
96 return val;
97}
98
99u64 ARM_Unicorn::GetReg(int regn) const {
100 u64 val{};
101 auto treg = UC_ARM64_REG_SP;
102 if (regn <= 28) {
103 treg = (uc_arm64_reg)(UC_ARM64_REG_X0 + regn);
104 } else if (regn < 31) {
105 treg = (uc_arm64_reg)(UC_ARM64_REG_X29 + regn - 29);
106 }
107 CHECKED(uc_reg_read(uc, treg, &val));
108 return val;
109}
110
111void ARM_Unicorn::SetReg(int regn, u64 val) {
112 auto treg = UC_ARM64_REG_SP;
113 if (regn <= 28) {
114 treg = (uc_arm64_reg)(UC_ARM64_REG_X0 + regn);
115 } else if (regn < 31) {
116 treg = (uc_arm64_reg)(UC_ARM64_REG_X29 + regn - 29);
117 }
118 CHECKED(uc_reg_write(uc, treg, &val));
119}
120
121u128 ARM_Unicorn::GetVectorReg(int /*index*/) const {
122 UNIMPLEMENTED();
123 static constexpr u128 res{};
124 return res;
125}
126
127void ARM_Unicorn::SetVectorReg(int /*index*/, u128 /*value*/) {
128 UNIMPLEMENTED();
129}
130
131u32 ARM_Unicorn::GetPSTATE() const {
132 u64 nzcv{};
133 CHECKED(uc_reg_read(uc, UC_ARM64_REG_NZCV, &nzcv));
134 return static_cast<u32>(nzcv);
135}
136
137void ARM_Unicorn::SetPSTATE(u32 pstate) {
138 u64 nzcv = pstate;
139 CHECKED(uc_reg_write(uc, UC_ARM64_REG_NZCV, &nzcv));
140}
141
142VAddr ARM_Unicorn::GetTlsAddress() const {
143 u64 base{};
144 CHECKED(uc_reg_read(uc, UC_ARM64_REG_TPIDRRO_EL0, &base));
145 return base;
146}
147
148void ARM_Unicorn::SetTlsAddress(VAddr base) {
149 CHECKED(uc_reg_write(uc, UC_ARM64_REG_TPIDRRO_EL0, &base));
150}
151
152u64 ARM_Unicorn::GetTPIDR_EL0() const {
153 u64 value{};
154 CHECKED(uc_reg_read(uc, UC_ARM64_REG_TPIDR_EL0, &value));
155 return value;
156}
157
158void ARM_Unicorn::SetTPIDR_EL0(u64 value) {
159 CHECKED(uc_reg_write(uc, UC_ARM64_REG_TPIDR_EL0, &value));
160}
161
162void ARM_Unicorn::ChangeProcessorID(std::size_t new_core_id) {
163 core_index = new_core_id;
164}
165
166void ARM_Unicorn::Run() {
167 if (GDBStub::IsServerEnabled()) {
168 ExecuteInstructions(std::max(4000000U, 0U));
169 } else {
170 while (true) {
171 if (interrupt_handlers[core_index].IsInterrupted()) {
172 return;
173 }
174 ExecuteInstructions(10);
175 }
176 }
177}
178
179void ARM_Unicorn::Step() {
180 ExecuteInstructions(1);
181}
182
183MICROPROFILE_DEFINE(ARM_Jit_Unicorn, "ARM JIT", "Unicorn", MP_RGB(255, 64, 64));
184
185void ARM_Unicorn::ExecuteInstructions(std::size_t num_instructions) {
186 MICROPROFILE_SCOPE(ARM_Jit_Unicorn);
187
188 // Temporarily map the code page for Unicorn
189 u64 map_addr{GetPC() & ~Memory::PAGE_MASK};
190 std::vector<u8> page_buffer(Memory::PAGE_SIZE);
191 system.Memory().ReadBlock(map_addr, page_buffer.data(), page_buffer.size());
192
193 CHECKED(uc_mem_map_ptr(uc, map_addr, page_buffer.size(),
194 UC_PROT_READ | UC_PROT_WRITE | UC_PROT_EXEC, page_buffer.data()));
195 CHECKED(uc_emu_start(uc, GetPC(), 1ULL << 63, 0, num_instructions));
196 CHECKED(uc_mem_unmap(uc, map_addr, page_buffer.size()));
197 if (GDBStub::IsServerEnabled()) {
198 if (last_bkpt_hit && last_bkpt.type == GDBStub::BreakpointType::Execute) {
199 uc_reg_write(uc, UC_ARM64_REG_PC, &last_bkpt.address);
200 }
201
202 Kernel::Thread* const thread = system.CurrentScheduler().GetCurrentThread();
203 SaveContext(thread->GetContext64());
204 if (last_bkpt_hit || GDBStub::IsMemoryBreak() || GDBStub::GetCpuStepFlag()) {
205 last_bkpt_hit = false;
206 GDBStub::Break();
207 GDBStub::SendTrap(thread, 5);
208 }
209 }
210}
211
212void ARM_Unicorn::SaveContext(ThreadContext64& ctx) {
213 int uregs[32];
214 void* tregs[32];
215
216 CHECKED(uc_reg_read(uc, UC_ARM64_REG_SP, &ctx.sp));
217 CHECKED(uc_reg_read(uc, UC_ARM64_REG_PC, &ctx.pc));
218 CHECKED(uc_reg_read(uc, UC_ARM64_REG_NZCV, &ctx.pstate));
219
220 for (auto i = 0; i < 29; ++i) {
221 uregs[i] = UC_ARM64_REG_X0 + i;
222 tregs[i] = &ctx.cpu_registers[i];
223 }
224 uregs[29] = UC_ARM64_REG_X29;
225 tregs[29] = (void*)&ctx.cpu_registers[29];
226 uregs[30] = UC_ARM64_REG_X30;
227 tregs[30] = (void*)&ctx.cpu_registers[30];
228
229 CHECKED(uc_reg_read_batch(uc, uregs, tregs, 31));
230
231 for (int i = 0; i < 32; ++i) {
232 uregs[i] = UC_ARM64_REG_Q0 + i;
233 tregs[i] = &ctx.vector_registers[i];
234 }
235
236 CHECKED(uc_reg_read_batch(uc, uregs, tregs, 32));
237}
238
239void ARM_Unicorn::LoadContext(const ThreadContext64& ctx) {
240 int uregs[32];
241 void* tregs[32];
242
243 CHECKED(uc_reg_write(uc, UC_ARM64_REG_SP, &ctx.sp));
244 CHECKED(uc_reg_write(uc, UC_ARM64_REG_PC, &ctx.pc));
245 CHECKED(uc_reg_write(uc, UC_ARM64_REG_NZCV, &ctx.pstate));
246
247 for (int i = 0; i < 29; ++i) {
248 uregs[i] = UC_ARM64_REG_X0 + i;
249 tregs[i] = (void*)&ctx.cpu_registers[i];
250 }
251 uregs[29] = UC_ARM64_REG_X29;
252 tregs[29] = (void*)&ctx.cpu_registers[29];
253 uregs[30] = UC_ARM64_REG_X30;
254 tregs[30] = (void*)&ctx.cpu_registers[30];
255
256 CHECKED(uc_reg_write_batch(uc, uregs, tregs, 31));
257
258 for (auto i = 0; i < 32; ++i) {
259 uregs[i] = UC_ARM64_REG_Q0 + i;
260 tregs[i] = (void*)&ctx.vector_registers[i];
261 }
262
263 CHECKED(uc_reg_write_batch(uc, uregs, tregs, 32));
264}
265
266void ARM_Unicorn::PrepareReschedule() {
267 CHECKED(uc_emu_stop(uc));
268}
269
270void ARM_Unicorn::ClearExclusiveState() {}
271
272void ARM_Unicorn::ClearInstructionCache() {}
273
274void ARM_Unicorn::RecordBreak(GDBStub::BreakpointAddress bkpt) {
275 last_bkpt = bkpt;
276 last_bkpt_hit = true;
277}
278
279void ARM_Unicorn::InterruptHook(uc_engine* uc, u32 int_no, void* user_data) {
280 u32 esr{};
281 CHECKED(uc_reg_read(uc, UC_ARM64_REG_ESR, &esr));
282
283 const auto ec = esr >> 26;
284 const auto iss = esr & 0xFFFFFF;
285
286 auto* const arm_instance = static_cast<ARM_Unicorn*>(user_data);
287
288 switch (ec) {
289 case 0x15: // SVC
290 Kernel::Svc::Call(arm_instance->system, iss);
291 break;
292 }
293}
294
295} // 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 @@
1// Copyright 2018 yuzu emulator team
2// Licensed under GPLv2 or any later version
3// Refer to the license.txt file included.
4
5#pragma once
6
7#include <unicorn/unicorn.h>
8#include "common/common_types.h"
9#include "core/arm/arm_interface.h"
10#include "core/gdbstub/gdbstub.h"
11
12namespace Core {
13
14class System;
15
16class ARM_Unicorn final : public ARM_Interface {
17public:
18 enum class Arch {
19 AArch32, // 32-bit ARM
20 AArch64, // 64-bit ARM
21 };
22
23 explicit ARM_Unicorn(System& system, CPUInterrupts& interrupt_handlers, bool uses_wall_clock,
24 Arch architecture, std::size_t core_index);
25 ~ARM_Unicorn() override;
26
27 void SetPC(u64 pc) override;
28 u64 GetPC() const override;
29 u64 GetReg(int index) const override;
30 void SetReg(int index, u64 value) override;
31 u128 GetVectorReg(int index) const override;
32 void SetVectorReg(int index, u128 value) override;
33 u32 GetPSTATE() const override;
34 void SetPSTATE(u32 pstate) override;
35 VAddr GetTlsAddress() const override;
36 void SetTlsAddress(VAddr address) override;
37 void SetTPIDR_EL0(u64 value) override;
38 u64 GetTPIDR_EL0() const override;
39 void ChangeProcessorID(std::size_t new_core_id) override;
40 void PrepareReschedule() override;
41 void ClearExclusiveState() override;
42 void ExecuteInstructions(std::size_t num_instructions);
43 void Run() override;
44 void Step() override;
45 void ClearInstructionCache() override;
46 void PageTableChanged(Common::PageTable&, std::size_t) override {}
47 void RecordBreak(GDBStub::BreakpointAddress bkpt);
48
49 void SaveContext(ThreadContext32& ctx) override {}
50 void SaveContext(ThreadContext64& ctx) override;
51 void LoadContext(const ThreadContext32& ctx) override {}
52 void LoadContext(const ThreadContext64& ctx) override;
53
54private:
55 static void InterruptHook(uc_engine* uc, u32 int_no, void* user_data);
56
57 uc_engine* uc{};
58 GDBStub::BreakpointAddress last_bkpt{};
59 bool last_bkpt_hit = false;
60 std::size_t core_index;
61};
62
63} // 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 @@
2// Licensed under GPLv2 or any later version 2// Licensed under GPLv2 or any later version
3// Refer to the license.txt file included. 3// Refer to the license.txt file included.
4 4
5#include "common/assert.h"
6#include "common/logging/log.h"
7#include "common/spin_lock.h" 5#include "common/spin_lock.h"
8#include "core/arm/arm_interface.h"
9#ifdef ARCHITECTURE_x86_64
10#include "core/arm/dynarmic/arm_dynarmic_32.h"
11#include "core/arm/dynarmic/arm_dynarmic_64.h"
12#endif
13#include "core/arm/cpu_interrupt_handler.h" 6#include "core/arm/cpu_interrupt_handler.h"
14#include "core/arm/exclusive_monitor.h"
15#include "core/arm/unicorn/arm_unicorn.h"
16#include "core/core.h" 7#include "core/core.h"
17#include "core/hle/kernel/physical_core.h" 8#include "core/hle/kernel/physical_core.h"
18#include "core/hle/kernel/scheduler.h" 9#include "core/hle/kernel/scheduler.h"
19#include "core/hle/kernel/thread.h"
20 10
21namespace Kernel { 11namespace Kernel {
22 12
23PhysicalCore::PhysicalCore(Core::System& system, std::size_t id, Kernel::Scheduler& scheduler, 13PhysicalCore::PhysicalCore(Core::System& system, std::size_t id, Kernel::Scheduler& scheduler,
24 Core::CPUInterruptHandler& interrupt_handler) 14 Core::CPUInterruptHandler& interrupt_handler)
25 : interrupt_handler{interrupt_handler}, core_index{id}, scheduler{scheduler} { 15 : interrupt_handler{interrupt_handler},
26 16 core_index{id}, scheduler{scheduler}, guard{std::make_unique<Common::SpinLock>()} {}
27 guard = std::make_unique<Common::SpinLock>();
28}
29 17
30PhysicalCore::~PhysicalCore() = default; 18PhysicalCore::~PhysicalCore() = default;
31 19
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 @@
13#include "common/logging/log.h" 13#include "common/logging/log.h"
14#include "common/thread_queue_list.h" 14#include "common/thread_queue_list.h"
15#include "core/arm/arm_interface.h" 15#include "core/arm/arm_interface.h"
16#include "core/arm/unicorn/arm_unicorn.h"
17#include "core/core.h" 16#include "core/core.h"
18#include "core/cpu_manager.h" 17#include "core/cpu_manager.h"
19#include "core/hardware_properties.h" 18#include "core/hardware_properties.h"
@@ -217,8 +216,7 @@ ResultVal<std::shared_ptr<Thread>> Thread::Create(Core::System& system, ThreadTy
217 } else { 216 } else {
218 thread->tls_address = 0; 217 thread->tls_address = 0;
219 } 218 }
220 // TODO(peachum): move to ScheduleThread() when scheduler is added so selected core is used 219
221 // to initialize the context
222 thread->arm_interface.reset(); 220 thread->arm_interface.reset();
223 if ((type_flags & THREADTYPE_HLE) == 0) { 221 if ((type_flags & THREADTYPE_HLE) == 0) {
224#ifdef ARCHITECTURE_x86_64 222#ifdef ARCHITECTURE_x86_64
@@ -231,19 +229,10 @@ ResultVal<std::shared_ptr<Thread>> Thread::Create(Core::System& system, ThreadTy
231 system, kernel.Interrupts(), kernel.IsMulticore(), kernel.GetExclusiveMonitor(), 229 system, kernel.Interrupts(), kernel.IsMulticore(), kernel.GetExclusiveMonitor(),
232 processor_id); 230 processor_id);
233 } 231 }
234
235#else 232#else
236 if (owner_process && !owner_process->Is64BitProcess()) { 233#error Platform not supported yet.
237 thread->arm_interface = std::make_shared<Core::ARM_Unicorn>(
238 system, kernel.Interrupts(), kernel.IsMulticore(), ARM_Unicorn::Arch::AArch32,
239 processor_id);
240 } else {
241 thread->arm_interface = std::make_shared<Core::ARM_Unicorn>(
242 system, kernel.Interrupts(), kernel.IsMulticore(), ARM_Unicorn::Arch::AArch64,
243 processor_id);
244 }
245 LOG_WARNING(Core, "CPU JIT requested, but Dynarmic not available");
246#endif 234#endif
235
247 ResetThreadContext32(thread->context_32, static_cast<u32>(stack_top), 236 ResetThreadContext32(thread->context_32, static_cast<u32>(stack_top),
248 static_cast<u32>(entry_point), static_cast<u32>(arg)); 237 static_cast<u32>(entry_point), static_cast<u32>(arg));
249 ResetThreadContext64(thread->context_64, stack_top, entry_point, arg); 238 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()
264if (MSVC) 264if (MSVC)
265 include(CopyYuzuQt5Deps) 265 include(CopyYuzuQt5Deps)
266 include(CopyYuzuSDLDeps) 266 include(CopyYuzuSDLDeps)
267 include(CopyYuzuUnicornDeps)
268 include(CopyYuzuFFmpegDeps) 267 include(CopyYuzuFFmpegDeps)
269 copy_yuzu_Qt5_deps(yuzu) 268 copy_yuzu_Qt5_deps(yuzu)
270 copy_yuzu_SDL_deps(yuzu) 269 copy_yuzu_SDL_deps(yuzu)
271 copy_yuzu_unicorn_deps(yuzu)
272 copy_yuzu_FFmpeg_deps(yuzu) 270 copy_yuzu_FFmpeg_deps(yuzu)
273endif() 271endif()
274 272
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()
39 39
40if (MSVC) 40if (MSVC)
41 include(CopyYuzuSDLDeps) 41 include(CopyYuzuSDLDeps)
42 include(CopyYuzuUnicornDeps)
43 copy_yuzu_SDL_deps(yuzu-cmd) 42 copy_yuzu_SDL_deps(yuzu-cmd)
44 copy_yuzu_unicorn_deps(yuzu-cmd)
45endif() 43endif()
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()
28 28
29if (MSVC) 29if (MSVC)
30 include(CopyYuzuSDLDeps) 30 include(CopyYuzuSDLDeps)
31 include(CopyYuzuUnicornDeps)
32 copy_yuzu_SDL_deps(yuzu-tester) 31 copy_yuzu_SDL_deps(yuzu-tester)
33 copy_yuzu_unicorn_deps(yuzu-tester)
34endif() 32endif()