From 94f52d6dc0e28bafd8746defa5e0a06c212843b0 Mon Sep 17 00:00:00 2001 From: DH Date: Fri, 28 Feb 2025 21:12:22 +0300 Subject: [PATCH] android: jit: teach fallback_cpu_detection provide meaningful results for aarch64 --- Utilities/JIT.h | 2 +- Utilities/JITLLVM.cpp | 36 ++++++++++++++--- .../CPU/Backends/AArch64/AArch64Common.cpp | 39 +++++++++++++++++++ .../Emu/CPU/Backends/AArch64/AArch64Common.h | 1 + 4 files changed, 71 insertions(+), 7 deletions(-) diff --git a/Utilities/JIT.h b/Utilities/JIT.h index fcdc59352e..6dfa9e7cd0 100644 --- a/Utilities/JIT.h +++ b/Utilities/JIT.h @@ -569,6 +569,6 @@ public: bool add_sub_disk_space(ssz space); }; -llvm::StringRef fallback_cpu_detection(); +const char *fallback_cpu_detection(); #endif // LLVM_AVAILABLE diff --git a/Utilities/JITLLVM.cpp b/Utilities/JITLLVM.cpp index b6061634bb..cd2fd2dc15 100644 --- a/Utilities/JITLLVM.cpp +++ b/Utilities/JITLLVM.cpp @@ -46,6 +46,10 @@ LOG_CHANNEL(jit_log, "JIT"); #pragma GCC diagnostic pop #endif +#ifdef ARCH_ARM64 +#include "Emu/CPU/Backends/AArch64/AArch64Common.h" +#endif + const bool jit_initialize = []() -> bool { llvm::InitializeNativeTarget(); @@ -590,8 +594,10 @@ std::string jit_compiler::triple1() return llvm::Triple::normalize(llvm::sys::getProcessTriple()); #elif defined(__APPLE__) && defined(ARCH_X64) return llvm::Triple::normalize("x86_64-unknown-linux-gnu"); -#elif defined(__APPLE__) && defined(ARCH_ARM64) +#elif (defined(__ANDROID__) || defined(__APPLE__)) && defined(ARCH_ARM64) return llvm::Triple::normalize("aarch64-unknown-linux-android"); // Set environment to android to reserve x18 +#elif defined(__ANDROID__) && defined(ARCH_X64) + return llvm::Triple::normalize("x86_64-unknown-linux-android"); #else return llvm::Triple::normalize(llvm::sys::getProcessTriple()); #endif @@ -605,8 +611,10 @@ std::string jit_compiler::triple2() return llvm::Triple::normalize("aarch64-unknown-linux-gnu"); #elif defined(__APPLE__) && defined(ARCH_X64) return llvm::Triple::normalize("x86_64-unknown-linux-gnu"); -#elif defined(__APPLE__) && defined(ARCH_ARM64) +#elif (defined(__ANDROID__) || defined(__APPLE__)) && defined(ARCH_ARM64) return llvm::Triple::normalize("aarch64-unknown-linux-android"); // Set environment to android to reserve x18 +#elif defined(__ANDROID__) && defined(ARCH_X64) + return llvm::Triple::normalize("x86_64-unknown-linux-android"); // Set environment to android to reserve x18 #else return llvm::Triple::normalize(llvm::sys::getProcessTriple()); #endif @@ -817,9 +825,9 @@ u64 jit_compiler::get(const std::string& name) return m_engine->getGlobalValueAddress(name); } -llvm::StringRef fallback_cpu_detection() +const char * fallback_cpu_detection() { -#if defined (ARCH_X64) +#if defined(ARCH_X64) // If we got here we either have a very old and outdated CPU or a new CPU that has not been seen by LLVM yet. const std::string brand = utils::get_cpu_brand(); const auto family = utils::get_cpu_family(); @@ -851,8 +859,8 @@ llvm::StringRef fallback_cpu_detection() default: // Safest guesses return utils::has_avx512() ? "znver4" : - utils::has_avx2() ? "znver1" : - utils::has_avx() ? "bdver1" : + utils::has_avx2() ? "znver1" : + utils::has_avx() ? "bdver1" : "nehalem"; } } @@ -883,10 +891,26 @@ llvm::StringRef fallback_cpu_detection() } #elif defined(ARCH_ARM64) +#ifdef ANDROID + static std::string s_result = []() -> std::string + { + std::string result = aarch64::get_cpu_name(); + if (result.empty()) + { + return "cortex-a78"; + } + + std::transform(result.begin(), result.end(), result.begin(), ::tolower); + return result; + }(); + + return s_result.c_str(); +#else // TODO: Read the data from /proc/cpuinfo. ARM CPU registers are not accessible from usermode. // This will be a pain when supporting snapdragon on windows but we'll cross that bridge when we get there. // Require at least armv8-2a. Older chips are going to be useless anyway. return "cortex-a78"; +#endif #endif // Failed to guess, use generic fallback diff --git a/rpcs3/Emu/CPU/Backends/AArch64/AArch64Common.cpp b/rpcs3/Emu/CPU/Backends/AArch64/AArch64Common.cpp index f12b77d0c0..9125222a66 100644 --- a/rpcs3/Emu/CPU/Backends/AArch64/AArch64Common.cpp +++ b/rpcs3/Emu/CPU/Backends/AArch64/AArch64Common.cpp @@ -136,6 +136,45 @@ namespace aarch64 #endif } + std::string get_cpu_name() + { + std::map core_layout; + for (u32 i = 0; i < std::thread::hardware_concurrency(); ++i) + { + const auto midr = read_MIDR_EL1(i); + if (midr == umax) + { + break; + } + + core_layout[midr]++; + } + + if (core_layout.empty()) + { + return {}; + } + + const cpu_entry_t *lowest_part_info = nullptr; + for (const auto& [midr, count] : core_layout) + { + const auto implementer_id = (midr >> 24) & 0xff; + const auto part_id = (midr >> 4) & 0xfff; + + const auto part_info = find_cpu_part(implementer_id, part_id); + if (!part_info) + { + return {}; + } + + if (lowest_part_info == nullptr || lowest_part_info > part_info) { + lowest_part_info = part_info; + } + } + + return lowest_part_info == nullptr ? "" : lowest_part_info->name; + } + std::string get_cpu_brand() { // Fetch vendor and part numbers. ARM CPUs often have more than 1 architecture on the SoC, so we check all of them. diff --git a/rpcs3/Emu/CPU/Backends/AArch64/AArch64Common.h b/rpcs3/Emu/CPU/Backends/AArch64/AArch64Common.h index b0d64947ae..dff06dfb81 100644 --- a/rpcs3/Emu/CPU/Backends/AArch64/AArch64Common.h +++ b/rpcs3/Emu/CPU/Backends/AArch64/AArch64Common.h @@ -37,5 +37,6 @@ namespace aarch64 "xzr", ".", "sp" }; + std::string get_cpu_name(); std::string get_cpu_brand(); }