From 1893237a554d2c5bb687cc88c51a8dc969030af2 Mon Sep 17 00:00:00 2001 From: lizzie Date: Thu, 21 Aug 2025 10:16:43 +0000 Subject: [PATCH 01/39] [common] replace Common:: stuffs with libstdc++ equivalents Signed-off-by: lizzie --- src/common/common_funcs.h | 15 --------------- src/common/concepts.h | 20 -------------------- src/common/fixed_point.h | 12 ++++++++---- src/core/file_sys/fs_path_utility.h | 6 +++--- src/core/hle/kernel/k_priority_queue.h | 9 ++++----- src/core/hle/service/sm/sm.h | 4 ++-- src/video_core/gpu_thread.cpp | 4 +--- 7 files changed, 18 insertions(+), 52 deletions(-) diff --git a/src/common/common_funcs.h b/src/common/common_funcs.h index ba3081efb4..9272dbd6a6 100644 --- a/src/common/common_funcs.h +++ b/src/common/common_funcs.h @@ -129,19 +129,4 @@ namespace Common { u64(g) << 48 | u64(h) << 56; } -// std::size() does not support zero-size C arrays. We're fixing that. -template -constexpr auto Size(const C& c) -> decltype(c.size()) { - return std::size(c); -} - -template -constexpr std::size_t Size(const C& c) { - if constexpr (sizeof(C) == 0) { - return 0; - } else { - return std::size(c); - } -} - } // namespace Common diff --git a/src/common/concepts.h b/src/common/concepts.h index 61df1d32a2..d991bdd893 100644 --- a/src/common/concepts.h +++ b/src/common/concepts.h @@ -12,24 +12,4 @@ namespace Common { template concept IsContiguousContainer = std::contiguous_iterator; -// TODO: Replace with std::derived_from when the header -// is available on all supported platforms. -template -concept DerivedFrom = requires { - std::is_base_of_v; - std::is_convertible_v; - }; - -// TODO: Replace with std::convertible_to when libc++ implements it. -template -concept ConvertibleTo = std::is_convertible_v; - -// No equivalents in the stdlib - -template -concept IsArithmetic = std::is_arithmetic_v; - -template -concept IsIntegral = std::is_integral_v; - } // namespace Common diff --git a/src/common/fixed_point.h b/src/common/fixed_point.h index b0f3ae2ccb..3beec38b0d 100644 --- a/src/common/fixed_point.h +++ b/src/common/fixed_point.h @@ -16,6 +16,10 @@ namespace Common { +// No equivalent for "std::arithmetic" in the stdlib +template +concept IsArithmetic = std::is_arithmetic_v; + template class FixedPoint; @@ -392,13 +396,13 @@ public: // binary math operators, effects underlying bit pattern since these return *this; } - template + template constexpr FixedPoint& operator>>=(Integer n) { data_ >>= n; return *this; } - template + template constexpr FixedPoint& operator<<=(Integer n) { data_ <<= n; return *this; @@ -587,12 +591,12 @@ constexpr FixedPoint operator/(Number lhs, FixedPoint rhs) { } // shift operators -template +template constexpr FixedPoint operator<<(FixedPoint lhs, Integer rhs) { lhs <<= rhs; return lhs; } -template +template constexpr FixedPoint operator>>(FixedPoint lhs, Integer rhs) { lhs >>= rhs; return lhs; diff --git a/src/core/file_sys/fs_path_utility.h b/src/core/file_sys/fs_path_utility.h index cdfd8c7729..b8702f4f3f 100644 --- a/src/core/file_sys/fs_path_utility.h +++ b/src/core/file_sys/fs_path_utility.h @@ -57,15 +57,15 @@ constexpr bool IsInvalidCharacterImpl(char c) { } // namespace impl constexpr bool IsInvalidCharacter(char c) { - return impl::IsInvalidCharacterImpl(c); + return impl::IsInvalidCharacterImpl(c); } constexpr bool IsInvalidCharacterForHostName(char c) { return impl::IsInvalidCharacterImpl(c); + std::size(InvalidCharactersForHostName)>(c); } constexpr bool IsInvalidCharacterForMountName(char c) { return impl::IsInvalidCharacterImpl(c); + std::size(InvalidCharactersForMountName)>(c); } } // namespace StringTraits diff --git a/src/core/hle/kernel/k_priority_queue.h b/src/core/hle/kernel/k_priority_queue.h index 26677ec65c..14a406bdc8 100644 --- a/src/core/hle/kernel/k_priority_queue.h +++ b/src/core/hle/kernel/k_priority_queue.h @@ -10,7 +10,6 @@ #include "common/assert.h" #include "common/bit_set.h" #include "common/common_types.h" -#include "common/concepts.h" namespace Kernel { @@ -19,7 +18,7 @@ class KThread; template concept KPriorityQueueAffinityMask = ! std::is_reference_v&& requires(T& t) { - { t.GetAffinityMask() } -> Common::ConvertibleTo; + { t.GetAffinityMask() } -> std::convertible_to; { t.SetAffinityMask(0) }; { t.GetAffinity(0) } -> std::same_as; @@ -45,9 +44,9 @@ std::is_reference_v&& requires(T& t) { std::remove_cvref_t() } -> KPriorityQueueAffinityMask; - { t.GetActiveCore() } -> Common::ConvertibleTo; - { t.GetPriority() } -> Common::ConvertibleTo; - { t.IsDummyThread() } -> Common::ConvertibleTo; + { t.GetActiveCore() } -> std::convertible_to; + { t.GetPriority() } -> std::convertible_to; + { t.IsDummyThread() } -> std::convertible_to; }; template diff --git a/src/core/hle/service/sm/sm.h b/src/core/hle/service/sm/sm.h index 32c218638d..07ccfc1c78 100644 --- a/src/core/hle/service/sm/sm.h +++ b/src/core/hle/service/sm/sm.h @@ -8,8 +8,8 @@ #include #include #include +#include -#include "common/concepts.h" #include "core/hle/kernel/k_port.h" #include "core/hle/kernel/svc.h" #include "core/hle/result.h" @@ -63,7 +63,7 @@ public: Result UnregisterService(const std::string& name); Result GetServicePort(Kernel::KClientPort** out_client_port, const std::string& name); - template T> + template T> std::shared_ptr GetService(const std::string& service_name, bool block = false) const { auto service = registered_services.find(service_name); if (service == registered_services.end() && !block) { diff --git a/src/video_core/gpu_thread.cpp b/src/video_core/gpu_thread.cpp index 9392534e7d..b0cafbf270 100644 --- a/src/video_core/gpu_thread.cpp +++ b/src/video_core/gpu_thread.cpp @@ -23,9 +23,7 @@ namespace VideoCommon::GPUThread { static void RunThread(std::stop_token stop_token, Core::System& system, VideoCore::RendererBase& renderer, Core::Frontend::GraphicsContext& context, Tegra::Control::Scheduler& scheduler, SynchState& state) { - std::string name = "GPU"; - - Common::SetCurrentThreadName(name.c_str()); + Common::SetCurrentThreadName("GPU"); Common::SetCurrentThreadPriority(Common::ThreadPriority::Critical); system.RegisterHostThread(); From 35ec256c742f011ce422368a94e0a8c7cbbc9541 Mon Sep 17 00:00:00 2001 From: PavelBARABANOV Date: Thu, 21 Aug 2025 23:57:32 +0200 Subject: [PATCH 02/39] [translation] EDS Description (#297) Reviewed-on: https://git.eden-emu.dev/eden-emu/eden/pulls/297 Reviewed-by: Maufeat Co-authored-by: PavelBARABANOV Co-committed-by: PavelBARABANOV --- src/android/app/src/main/res/values-ar/strings.xml | 2 +- src/android/app/src/main/res/values-ckb/strings.xml | 2 +- src/android/app/src/main/res/values-cs/strings.xml | 2 +- src/android/app/src/main/res/values-de/strings.xml | 2 +- src/android/app/src/main/res/values-es/strings.xml | 2 +- src/android/app/src/main/res/values-fa/strings.xml | 2 +- src/android/app/src/main/res/values-fr/strings.xml | 2 +- src/android/app/src/main/res/values-he/strings.xml | 2 +- src/android/app/src/main/res/values-hu/strings.xml | 2 +- src/android/app/src/main/res/values-id/strings.xml | 2 +- src/android/app/src/main/res/values-it/strings.xml | 2 +- src/android/app/src/main/res/values-ja/strings.xml | 2 +- src/android/app/src/main/res/values-ko/strings.xml | 2 +- src/android/app/src/main/res/values-nb/strings.xml | 2 +- src/android/app/src/main/res/values-pl/strings.xml | 2 +- src/android/app/src/main/res/values-pt-rBR/strings.xml | 2 +- src/android/app/src/main/res/values-pt-rPT/strings.xml | 2 +- src/android/app/src/main/res/values-ru/strings.xml | 2 +- src/android/app/src/main/res/values-sr/strings.xml | 2 +- src/android/app/src/main/res/values-uk/strings.xml | 2 +- src/android/app/src/main/res/values-vi/strings.xml | 2 +- src/android/app/src/main/res/values-zh-rCN/strings.xml | 2 +- src/android/app/src/main/res/values-zh-rTW/strings.xml | 2 +- src/android/app/src/main/res/values/strings.xml | 2 +- 24 files changed, 24 insertions(+), 24 deletions(-) diff --git a/src/android/app/src/main/res/values-ar/strings.xml b/src/android/app/src/main/res/values-ar/strings.xml index 001074baad..f9130457cc 100644 --- a/src/android/app/src/main/res/values-ar/strings.xml +++ b/src/android/app/src/main/res/values-ar/strings.xml @@ -84,7 +84,7 @@ تمكين ذاكرة التخزين المؤقت LRU تمكين أو تعطيل ذاكرة التخزين المؤقت الأقل استخداماً مؤخراً (LRU) لتحسين الأداء عن طريق تقليل استخدام وحدة المعالجة المركزية. بعض الألعاب قد تواجه مشاكل معه، خاصةً TotK 1.2.1، لذا قم بتعطيله إذا لم تعمل اللعبة أو انهارت عشوائياً. الحالة الديناميكية الممتدة - تمكين ميزات فولكان لتحسين الأداء، العرض، وتوفير الموارد أثناء إنشاء خطوط المعالجة مع الحفاظ على استهلاك منخفض لوحدة المعالجة المركزية/وحدة معالجة الرسومات. هذه الامتدادات قد تزيد من حرارة الجهاز، ووحدات معالجة الرسومات من سلسلة A6XX القديمة قد لا تعمل بشكل صحيح. قم بتعطيله لمحاكاة الصيغ المضبوطة. + يتحكم في عدد الميزات التي يمكن استخدامها في الحالة الديناميكية الممتدة. الأرقام الأعلى تسمح بالمزيد من Мيزات ويمكن أن تزيد الأداء، ولكن قد تسبب مشاكل مع بعض برامج التشغيل والبائعين. قد تختلف القيمة الافتراضية اعتمادًا على نظامك وقدرات硬件. يمكن تغيير هذه القيمة حتى يتم تحقيق الاستقرار وجودة بصرية أفضل. معطل مزامنة سرعة النواة مزامنة سرعة النواة مع النسبة القصوى للسرعة لتحسين الأداء دون تغيير السرعة الفعلية للعبة. diff --git a/src/android/app/src/main/res/values-ckb/strings.xml b/src/android/app/src/main/res/values-ckb/strings.xml index 9cbd89d886..c005e0cab7 100644 --- a/src/android/app/src/main/res/values-ckb/strings.xml +++ b/src/android/app/src/main/res/values-ckb/strings.xml @@ -85,7 +85,7 @@ تمكين ذاكرة التخزين المؤقت LRU چالاک یان ناچالاککردنی کاشەی LRU، کارایی باشتر دەکات بە هەڵگرتنی بەکارهێنانی پرۆسەی CPU. هەندێک یاری کێشەی لەگەڵ هەیە، بەتایبەتی TotK 1.2.1، بۆیە بیخەوێنە ئەگەر یاریەکە نەگەڕێت یان بە هەڕەمەکی بشکێت. الحالة الديناميكية الممتدة - کاریگەرییەکانی ڤولکان چالاک بکە بۆ باشترکردنی کارایی، رێندرکردن، و هەڵگرتنی سەرچاوەکان لە دروستکردنی پایپلاین بە هەمان کات کەمترین بەکارهێنانی CPU/GPU بەکاربهێنرێت. ئەم زیادکراوانە ڕەنگە پلەی گەرمی ئامێر زیاد بکەن، و GPU-کانی هێڵی کۆنی A6XX ڕەنگە بە شێوەیەکی گونجاو کارنەکەن. بیخەوێنە بۆ نەخشەکێشانی فۆرماتە پێوانەکراوەکان. + کۆntrolی ژمارەی تایبەتمەندییەکان دەکات کە دەتوانرێت لە دۆخی هایپرDynamic بەکاربهێنرێت. ژمارەی زیاتر ڕێگە بە تایبەتمەندییەکی زیاتر دەدات و دەتوانێت کارایی باشتر بکات، بەڵام لەوانەیە کێشە دروست بکات لەگەڵ هەندێک لە درایڤەرەکان و فرۆشەکان. نرخی گریمانەیی دەگۆڕێت بەپێی سیستەم و تواناکانی hardwareی تۆ. دەتوانیت ئەم نرخە بگۆڕیت تا جێگیری و جێیەکی بینینی باشتر دەستبکەوێت. ناچالاک مزامنة سرعة النواة خێرایی تیکەکانی ناوک ڕێکبخە لەگەڵ ڕێژەی خێرایی بەرزترین بۆ باشترکردنی کارایی بەبێ گۆڕینی خێرایی ڕاستەقینەی یارییەکە. diff --git a/src/android/app/src/main/res/values-cs/strings.xml b/src/android/app/src/main/res/values-cs/strings.xml index a7eca41678..8cdc753e8d 100644 --- a/src/android/app/src/main/res/values-cs/strings.xml +++ b/src/android/app/src/main/res/values-cs/strings.xml @@ -84,7 +84,7 @@ Povolit LRU mezipaměť Povolte nebo zakažte mezipaměť LRU, čímž zvýšíte výkon snížením využití procesoru CPU. Některé hry s ní mají problémy, zejména TotK 1.2.1, takže ji deaktivujte, pokud hra neběží nebo náhodně padá. Rozšířený dynamický stav - Umožňuje funkce Vulkan pro zlepšení výkonu, vykreslování a úsporu zdrojů při vytváření pipeline při zachování nižšího využití CPU/GPU. Tato rozšíření mohou zvýšit teplotu zařízení a starší GPU řady A6XX nemusí správně reagovat. Vypněte pro emulaci měřítkových formátů. + Ovládá počet funkcí, které lze použít v rozšířeném dynamickém stavu. Vyšší hodnoty umožňují více funkcí a mohou zvýšit výkon, ale mohou způsobit problémy s některými ovladači a výrobci. Výchozí hodnota se může lišit v závislosti na vašem systému a hardwarových schopnostech. Tuto hodnotu lze měnit, dokud nedosáhnete stability a lepší vizuální kvality. Vypnuto Synchronizovat rychlost jádra Synchronizuje rychlost jádra s maximálním procentem rychlosti, aby se zlepšil výkon bez změny skutečné rychlosti hry. diff --git a/src/android/app/src/main/res/values-de/strings.xml b/src/android/app/src/main/res/values-de/strings.xml index fbf9aa31c7..9aae9f3bd3 100644 --- a/src/android/app/src/main/res/values-de/strings.xml +++ b/src/android/app/src/main/res/values-de/strings.xml @@ -85,7 +85,7 @@ LRU-Cache aktivieren Aktivieren oder deaktivieren Sie den LRU-Cache, um die Leistung durch Einsparung von CPU-Prozessorauslastung zu verbessern. Einige Spiele haben Probleme damit, insbesondere TotK 1.2.1, deaktivieren Sie es also, wenn das Spiel nicht startet oder zufällig abstürzt. Erweiterter dynamischer Status - Aktiviert Vulkan-Funktionen zur Verbesserung der Leistung, des Renderings und zur Einsparung von Ressourcen bei der Pipeline-Erstellung bei gleichzeitig geringer CPU/GPU-Auslastung. Diese Erweiterungen können die Gerätetemperatur erhöhen, und ältere GPUs der A6XX-Serie reagieren möglicherweise nicht richtig. Deaktivieren Sie dies, um skalierte Formate zu emulieren. + Steuert die Anzahl der Funktionen, die im Erweiterten Dynamischen Zustand verwendet werden können. Höhere Werte ermöglichen mehr Funktionen und können die Leistung steigern, können jedoch bei einigen Treibern und Herstellern zu Problemen führen. Der Standardwert kann je nach System und Hardwarefähigkeiten variieren. Dieser Wert kann geändert werden, bis Stabilität und eine bessere visuelle Qualität erreicht sind. Deaktiviert Kern-Geschwindigkeit synchronisieren Synchronisiert die Taktrate des Kerns mit der maximalen Geschwindigkeit, um die Leistung zu verbessern, ohne die tatsächliche Spielgeschwindigkeit zu verändern. diff --git a/src/android/app/src/main/res/values-es/strings.xml b/src/android/app/src/main/res/values-es/strings.xml index 93b4fe159e..ebd0768d6b 100644 --- a/src/android/app/src/main/res/values-es/strings.xml +++ b/src/android/app/src/main/res/values-es/strings.xml @@ -85,7 +85,7 @@ Habilitar caché LRU Activa o desactiva la caché LRU, mejorando el rendimiento al ahorrar uso del proceso de la CPU. Algunos juegos tienen problemas con ella, notablemente TotK 1.2.1, así que desactívala si el juego no inicia o se cierra aleatoriamente. Estado dinámico extendido - Habilita funciones de Vulkan para mejorar el rendimiento, el renderizado y ahorrar recursos en la creación de pipelines manteniendo un uso bajo de CPU/GPU. Estas extensiones pueden aumentar la temperatura del dispositivo, y las GPU de la antigua línea A6XX pueden no reaccionar correctamente. Desactívalo para emular formatos escalados. + Controla la cantidad de funciones que se pueden usar en el Estado Dinámico Extendido. Los valores más altos permiten más funciones y pueden aumentar el rendimiento, pero pueden causar problemas con algunos controladores y fabricantes. El valor predeterminado puede variar según su sistema y las capacidades de su hardware. Este valor se puede cambiar hasta lograr estabilidad y una mejor calidad visual. Desactivado Sincronizar velocidad del núcleo Sincroniza la velocidad del núcleo con el porcentaje máximo de velocidad para mejorar el rendimiento sin alterar la velocidad real del juego. diff --git a/src/android/app/src/main/res/values-fa/strings.xml b/src/android/app/src/main/res/values-fa/strings.xml index f4793d1e2b..dec0a1c842 100644 --- a/src/android/app/src/main/res/values-fa/strings.xml +++ b/src/android/app/src/main/res/values-fa/strings.xml @@ -85,7 +85,7 @@ فعال‌سازی حافظه نهان LRU حافظه پنهان LRU را فعال یا غیرفعال کنید تا با کاهش استفاده از پردازنده، عملکرد بهبود یابد. برخی بازی‌ها مانند TotK 1.2.1 با این ویژگی مشکل دارند، در صورت عدم راه‌اندازی یا قطعی تصادفی بازی، آن را غیرفعال کنید. حالت پویای گسترده - قابلیت‌های ولکان را برای بهبود عملکرد، رندرینگ و صرفه‌جویی در منابع هنگام ایجاد خط لوله فعال می‌کند، در حالی که استفاده کمتری از CPU/GPU دارد. این پسوندها ممکن است دمای دستگاه را افزایش دهند و GPUهای قدیمی خط A6XX ممکن است به درستی واکنش نشان ندهند. برای شبیه‌سازی فرمت‌های مقیاس‌شده غیرفعال کنید. + تعداد قابلیت‌هایی که می‌توان در حالت Extended Dynamic State استفاده کرد را کنترل می‌کند. اعداد بالاتر قابلیت‌های بیشتری را فعال کرده و می‌توانند عملکرد را افزایش دهند، اما ممکن است با برخی درایورها و فروشندگان مشکلاتی ایجاد کنند. مقدار پیش‌فرض بسته به سیستم و قابلیت‌های سخت‌افزاری شما ممکن است متفاوت باشد. این مقدار را می‌توان تغییر داد تا زمانی که پایداری و کیفیت بصری بهتری حاصل شود. غیرفعال همگام‌سازی سرعت هسته همگام‌سازی سرعت هسته با حداکثر درصد سرعت برای بهبود عملکرد بدون تغییر سرعت واقعی بازی. diff --git a/src/android/app/src/main/res/values-fr/strings.xml b/src/android/app/src/main/res/values-fr/strings.xml index 7a70aaf022..6ca92875cf 100644 --- a/src/android/app/src/main/res/values-fr/strings.xml +++ b/src/android/app/src/main/res/values-fr/strings.xml @@ -85,7 +85,7 @@ Activer le cache LRU Active ou désactive le cache LRU pour améliorer les performances en réduisant l\'utilisation du processeur. Certains jeux comme TotK 1.2.1 ont des problèmes - désactivez-le si le jeu ne démarre pas ou plante aléatoirement. État dynamique étendu - Active les fonctionnalités Vulkan pour améliorer les performances, le rendu et économiser les ressources lors de la création des pipelines tout en maintenant une utilisation réduite du CPU/GPU. Ces extensions peuvent augmenter la température de l\'appareil et les GPU anciens de la série A6XX peuvent mal réagir. Désactivez pour émuler les formats mis à l\'échelle. + Contrôle le nombre de fonctionnalités utilisables dans l\'état dynamique étendu. Des valeurs plus élevées permettent plus de fonctionnalités et peuvent augmenter les performances, mais peuvent causer des problèmes avec certains pilotes et fabricants. La valeur par défaut peut varier selon votre système et vos capacités matérielles. Cette valeur peut être modifiée jusqu\'à obtenir une stabilité et une meilleure qualité visuelle. Désactivé Synchroniser la vitesse du cœur Synchronise la vitesse du cœur avec le pourcentage de vitesse maximal pour améliorer les performances sans modifier la vitesse réelle du jeu. diff --git a/src/android/app/src/main/res/values-he/strings.xml b/src/android/app/src/main/res/values-he/strings.xml index 516ac45210..caf4f5bf74 100644 --- a/src/android/app/src/main/res/values-he/strings.xml +++ b/src/android/app/src/main/res/values-he/strings.xml @@ -85,7 +85,7 @@ הפעלת מטמון LRU הפעל או השבת מטמון LRU לשיפור ביצועים על ידי חיסכון בשימוש במעבד. לחלק מהמשחקים כמו TotK 1.2.1 יש בעיות - השבת אם המשחק לא עולה או קורס באקראי. מצב דינמי מורחב - מאפשר תכונות Vulkan לשיפור ביצועים, רינדור וחיסכון במשאבים בעת יצירת צינורות עיבוד תוך שמירה על שימוש נמוך במעבד/מעבד גרפי. הרחבות אלו עלולות להעלות את טמפרטורת המכשיר, ומעבדים גרפיים מקו A6XX הישן עשויים לא להגיב כראוי. השבת כדי לדמות פורמטים מוקטנים. + שולט במספר התכונות שניתן להשתמש בהן במצב דינמי מורחב. מספרים גבוהים יותר מאפשרים יותר תכונות ויכולים לשפר את הביצועים, אך עלולים לגרום לבעיות עם כמה מנהלי התקנים וספקים. הערך המוגדר כברירת מחדל עשוי להשתנות בהתאם למערכת שלך ויכולות החומרה. ניתן לשנות ערך זה עד להשגת יציבות ואיכות ויזואלית טובה יותר. מושבת סנכרון מהירות ליבה סנכרן את מהירות הליבה לאחוז המהירות המרבי כדי לשפר ביצועים מבלי לשנות את מהירות המשחק בפועל. diff --git a/src/android/app/src/main/res/values-hu/strings.xml b/src/android/app/src/main/res/values-hu/strings.xml index f43bdf28ac..6ea078a78d 100644 --- a/src/android/app/src/main/res/values-hu/strings.xml +++ b/src/android/app/src/main/res/values-hu/strings.xml @@ -85,7 +85,7 @@ LRU gyorsítótár engedélyezése Engedélyezi vagy letiltja az LRU gyorsítótárat, növelve a teljesítményt a CPU használat csökkentésével. Néhány játéknak (különösen a TotK 1.2.1-nek) problémája lehet vele - tiltsa le, ha a játék nem indul el vagy véletlenszerűen összeomlik. Kiterjesztett Dinamikus Állapot - Engedélyezi a Vulkan funkciókat a teljesítmény, renderelés javítására és erőforrások spórolására a pipeline létrehozásánál, miközben alacsony CPU/GPU használatot tart fenn. Ezek a kiterjesztések növelhetik az eszköz hőmérsékletét, és a régebbi A6XX sorozatú GPU-k nem feltétlenül működnek megfelelően. Tiltsa le a skálázott formátumok emulálásához. + Szabályozza a Kiterjesztett Dynamikus Állapotban használható funkciók számát. A magasabb értékek több funkciót tesznek lehetővé és növelhetik a teljesítményt, de problémákat okozhatnak egyes meghajtókkal és gyártókkal. Az alapértelmezett érték eltérő lehet a rendszertől és a hardverképességektől függően. Ez az érték módosítható, amíg el nem éri a stabilitást és a jobb vizuális minőséget. Letiltva Magsebesség szinkronizálása A mag sebességének szinkronizálása a maximális sebesség százalékával a teljesítmény javítása érdekében a játék tényleges sebességének megváltoztatása nélkül. diff --git a/src/android/app/src/main/res/values-id/strings.xml b/src/android/app/src/main/res/values-id/strings.xml index 9017c1622f..f37e3bb4c5 100644 --- a/src/android/app/src/main/res/values-id/strings.xml +++ b/src/android/app/src/main/res/values-id/strings.xml @@ -85,7 +85,7 @@ Aktifkan LRU Cache Aktifkan atau nonaktifkan cache LRU untuk meningkatkan performa dengan mengurangi penggunaan proses CPU. Beberapa game seperti TotK 1.2.1 memiliki masalah - nonaktifkan jika game tidak mau berjalan atau crash acak. Status Dinamis Ekstensi - Aktifkan fitur Vulkan untuk meningkatkan performa, rendering dan menghemat sumber daya saat pembuatan pipeline sambil mempertahankan penggunaan CPU/GPU yang rendah. Ekstensi ini dapat meningkatkan suhu perangkat, dan GPU seri A6XX lama mungkin tidak merespons dengan benar. Nonaktifkan untuk emulasi format skala. + Mengontrol jumlah fitur yang dapat digunakan dalam Extended Dynamic State. Angka yang lebih tinggi memungkinkan lebih banyak fitur dan dapat meningkatkan performa, tetapi dapat menyebabkan masalah dengan beberapa driver dan vendor. Nilai default dapat bervariasi tergantung pada sistem dan kemampuan hardware Anda. Nilai ini dapat diubah hingga stabilitas dan kualitas visual yang lebih baik tercapai. Dinonaktifkan Sinkronisasi Kecepatan Inti Sinkronkan kecepatan inti dengan persentase kecepatan maksimum untuk meningkatkan performa tanpa mengubah kecepatan sebenarnya dari permainan. diff --git a/src/android/app/src/main/res/values-it/strings.xml b/src/android/app/src/main/res/values-it/strings.xml index b38b1c6c5a..ddce663c7c 100644 --- a/src/android/app/src/main/res/values-it/strings.xml +++ b/src/android/app/src/main/res/values-it/strings.xml @@ -85,7 +85,7 @@ Abilita cache LRU Abilita o disabilita la cache LRU per migliorare le prestazioni riducendo l\'uso della CPU. Alcuni giochi come TotK 1.2.1 hanno problemi - disabilitalo se il gioco non si avvia o crasha casualmente. Stato dinamico esteso - Abilita le funzionalità Vulkan per migliorare prestazioni, rendering e risparmiare risorse durante la creazione della pipeline mantenendo un basso utilizzo di CPU/GPU. Queste estensioni possono aumentare la temperatura del dispositivo e le GPU della vecchia serie A6XX potrebbero non rispondere correttamente. Disabilita per emulare formati scalati. + Controlla il numero di funzioni utilizzabili nello Stato Dinamico Esteso. Valori più alti consentono più funzioni e possono aumentare le prestazioni, ma potrebbero causare problemi con alcuni driver e vendor. Il valore predefinito può variare in base al sistema e alle capacità hardware. Questo valore può essere modificato finché non si raggiunge la stabilità e una migliore qualità visiva. Disabilitato Sincronizza velocità core Sincronizza la velocità del core con la percentuale massima di velocità per migliorare le prestazioni senza alterare la velocità effettiva del gioco. diff --git a/src/android/app/src/main/res/values-ja/strings.xml b/src/android/app/src/main/res/values-ja/strings.xml index c76814e17d..85ac46dd71 100644 --- a/src/android/app/src/main/res/values-ja/strings.xml +++ b/src/android/app/src/main/res/values-ja/strings.xml @@ -85,7 +85,7 @@ LRUキャッシュを有効化 LRUキャッシュを有効/無効にし、CPUプロセスの使用を節約してパフォーマンスを向上させます。TotK 1.2.1など一部のゲームで問題が発生する可能性があるため、ゲームが起動しない場合やランダムにクラッシュする場合は無効にしてください。 拡張ダイナミックステート - Vulkan機能を有効にし、パイプライン作成時のCPU/GPU使用率を低く保ちながら、パフォーマンス、レンダリング、リソース節約を改善します。これらの拡張機能はデバイスの温度を上昇させる可能性があり、旧A6XXシリーズのGPUは正しく反応しない場合があります。スケールフォーマットをエミュレートするには無効にしてください。 + 拡張ダイナミックステートで使用できる機能の数を制御します。数値が高いほどより多くの機能が使用可能になり、パフォーマンスが向上する可能性がありますが、一部のドライバーやベンダーで問題が発生する可能性があります。デフォルト値は、お使いのシステムとハードウェアの機能によって異なります。安定性とより良い画質が得られるまでこの値を変更できます。 無効 コア速度の同期 コアの速度を最大速度パーセンテージに同期させ、ゲームの実際の速度を変えずにパフォーマンスを向上させます。 diff --git a/src/android/app/src/main/res/values-ko/strings.xml b/src/android/app/src/main/res/values-ko/strings.xml index 1be258d243..a2974f99fa 100644 --- a/src/android/app/src/main/res/values-ko/strings.xml +++ b/src/android/app/src/main/res/values-ko/strings.xml @@ -85,7 +85,7 @@ LRU 캐시 사용 LRU 캐시를 활성화 또는 비활성화하여 CPU 프로세스 사용을 절약하고 성능을 향상시킵니다. TotK 1.2.1을 포함한 일부 게임에서 문제가 발생할 수 있으므로 게임이 부팅되지 않거나 무작위로 충돌하는 경우 비활성화하세요. 확장 동적 상태 - 파이프라인 생성 시 CPU/GPU 사용량을 낮게 유지하면서 성능, 렌더링 및 리소스 절약을 개선하기 위해 Vulkan 기능을 활성화합니다. 이 확장 기능은 장치 온도를 높일 수 있으며 이전 A6XX 라인에 속하는 GPU가 제대로 반응하지 않을 수 있습니다. 스케일된 형식을 에뮬레이트하려면 비활성화하세요. + 확장 동적 상태에서 사용할 수 있는 기능의 수를 제어합니다. 높은 값은 더 많은 기능을 허용하고 성능을 높일 수 있지만, 일부 드라이버 및 벤더에서 문제를 일으킬 수 있습니다. 기본값은 시스템 및 하드웨어 기능에 따라 다를 수 있습니다. 안정성과 더 나은 시각적 품질이 달성될 때까지 이 값을 변경할 수 있습니다. 비활성화됨 코어 속도 동기화 코어 틱 속도를 최대 속도 백분율과 동기화하여 게임의 실제 속도를 변경하지 않고 성능을 향상시킵니다. diff --git a/src/android/app/src/main/res/values-nb/strings.xml b/src/android/app/src/main/res/values-nb/strings.xml index 83bb02f3ff..3bea2895b5 100644 --- a/src/android/app/src/main/res/values-nb/strings.xml +++ b/src/android/app/src/main/res/values-nb/strings.xml @@ -85,7 +85,7 @@ Aktiver LRU-mellomlager Aktiver eller deaktiver LRU-mellomlager for å forbedre ytelsen ved å spare CPU-prosessorbruk. Noen spill som TotK 1.2.1 har problemer med dette - deaktiver hvis spillet ikke starter eller krasjer tilfeldig. Utvidet dynamisk tilstand - Aktiverer Vulkan-funksjoner for å forbedre ytelse, rendering og spare ressurser ved oppretting av pipeline samtidig som CPU/GPU-bruken holdes lav. Disse utvidelsene kan øke enhetstemperaturen, og eldre GPU-er fra A6XX-serien reagerer kanskje ikke ordentlig. Deaktiver for å emulere skalerte formater. + Kontrollerer antall funksjoner som kan brukes i Utvidet Dynamisk Tilstand. Høyere tall tillater flere funksjoner og kan øke ytelsen, men kan forårsake problemer med noen drivere og leverandører. Standardverdien kan variere avhengig av systemet og maskinvareevnene dine. Denne verdien kan endres til stabilitet og bedre visuell kvalitet er oppnådd. Deaktivert Synkroniser kjernespeed Synkroniser kjernens hastighet med maksimal hastighetsprosent for å forbedre ytelsen uten å endre spillets faktiske hastighet. diff --git a/src/android/app/src/main/res/values-pl/strings.xml b/src/android/app/src/main/res/values-pl/strings.xml index ec22ae0a4c..a87a4eabb5 100644 --- a/src/android/app/src/main/res/values-pl/strings.xml +++ b/src/android/app/src/main/res/values-pl/strings.xml @@ -85,7 +85,7 @@ Włącz pamięć podręczną LRU Włącz lub wyłącz pamięć podręczną LRU, aby poprawić wydajność poprzez zmniejszenie użycia procesora. Niektóre gry, takie jak TotK 1.2.1, mogą mieć problemy - wyłącz, jeśli gra się nie uruchamia lub losowo zawiesza. Rozszerzony stan dynamiczny - Włącza funkcje Vulkan w celu poprawy wydajności, renderowania i oszczędzania zasobów podczas tworzenia potoku, przy jednoczesnym utrzymaniu niskiego wykorzystania CPU/GPU. Te rozszerzenia mogą zwiększać temperaturę urządzenia, a starsze GPU z linii A6XX mogą nie działać poprawnie. Wyłącz, aby emulować formaty skalowane. + Kontroluje liczbę funkcji, które mogą być używane w Rozszerzonym Stanie Dynamicznym. Wyższe wartości pozwalają na więcej funkcji i mogą zwiększyć wydajność, ale mogą powodować problemy z niektórymi sterownikami i producentami. Wartość domyślna może się różnić w zależności od systemu i możliwości sprzętowych. Tę wartość można zmieniać, aż do osiągnięcia stabilności i lepszej jakości wizualnej. Wyłączone Synchronizuj prędkość rdzenia Synchronizuje prędkość rdzenia z maksymalnym procentem prędkości, aby poprawić wydajność bez zmiany rzeczywistej prędkości gry. diff --git a/src/android/app/src/main/res/values-pt-rBR/strings.xml b/src/android/app/src/main/res/values-pt-rBR/strings.xml index d7f528fb2a..8db231dff0 100644 --- a/src/android/app/src/main/res/values-pt-rBR/strings.xml +++ b/src/android/app/src/main/res/values-pt-rBR/strings.xml @@ -85,7 +85,7 @@ Ativar cache LRU Ative ou desative o cache LRU para melhorar o desempenho economizando uso do processador. Alguns jogos como TotK 1.2.1 têm problemas - desative se o jogo não iniciar ou travar aleatoriamente. Estado Dinâmico Estendido - Ativa recursos Vulkan para melhorar desempenho, renderização e economizar recursos na criação de pipelines mantendo baixo uso de CPU/GPU. Essas extensões podem aumentar a temperatura do dispositivo e GPUs da linha A6XX mais antigos podem não responder adequadamente. Desative para emular formatos dimensionados. + Controla o número de recursos que podem ser usados no Estado Dinâmico Estendido. Números mais altos permitem mais recursos e podem aumentar o desempenho, mas podem causar problemas com alguns drivers e fabricantes. O valor padrão pode variar dependendo do seu sistema e capacidades de hardware. Este valor pode ser alterado até que a estabilidade e uma melhor qualidade visual sejam alcançadas. Desativado Sincronizar velocidade do núcleo Sincroniza a velocidade do núcleo com a porcentagem máxima de velocidade para melhorar o desempenho sem alterar a velocidade real do jogo. diff --git a/src/android/app/src/main/res/values-pt-rPT/strings.xml b/src/android/app/src/main/res/values-pt-rPT/strings.xml index f312b0604a..3f0248110e 100644 --- a/src/android/app/src/main/res/values-pt-rPT/strings.xml +++ b/src/android/app/src/main/res/values-pt-rPT/strings.xml @@ -85,7 +85,7 @@ Ativar cache LRU Ative ou desative a cache LRU para melhorar desempenho poupando uso do processador. Alguns jogos como TotK 1.2.1 têm problemas - desative se o jogo não iniciar ou falhar aleatoriamente. Estado Dinâmico Estendido - Ativa funcionalidades Vulkan para melhorar desempenho, renderização e poupar recursos na criação de pipelines mantendo baixa utilização de CPU/GPU. Estas extensões podem aumentar a temperatura do dispositivo e GPUs da linha A6XX mais antigos podem não responder corretamente. Desative para emular formatos dimensionados. + Controla o número de funcionalidades que podem ser utilizadas no Estado Dinâmico Alargado. Valores mais elevados permitem mais funcionalidades e podem aumentar o desempenho, mas podem causar problemas com alguns controladores e fabricantes. O valor predefinido pode variar consoante o seu sistema e capacidades de hardware. Este valor pode ser alterado até ser alcançada a estabilidade e uma melhor qualidade visual. Desativado Sincronizar velocidade do núcleo Sincroniza a velocidade do núcleo com a percentagem máxima de velocidade para melhorar o desempenho sem alterar a velocidade real do jogo. diff --git a/src/android/app/src/main/res/values-ru/strings.xml b/src/android/app/src/main/res/values-ru/strings.xml index 285ec49606..955a013e30 100644 --- a/src/android/app/src/main/res/values-ru/strings.xml +++ b/src/android/app/src/main/res/values-ru/strings.xml @@ -85,7 +85,7 @@ Включить LRU-кеш Включите или отключите кэш LRU (наименее недавно использованный), повышая производительность за счёт снижения нагрузки на ЦП. Некоторые игры могут работать с ним некорректно (например, TotK 1.2.1), поэтому отключите, если игра не запускается или случайно вылетает. Расширенное динамическое состояние - Включает функции Vulkan для улучшения производительности, рендеринга и экономии ресурсов при создании конвейера, сохраняя низкое использование ЦП/ГПУ. Эти расширения могут увеличить температуру устройства, а ГПУ из старой линейки A6XX могут работать некорректно. Отключите для эмуляции масштабируемых форматов. + Управляет количеством функций, которые можно использовать в расширенном динамическом состоянии. Более высокие значения позволяют использовать больше функций и могут повысить производительность, но могут вызвать проблемы с некоторыми драйверами и производителями. Значение по умолчанию может варьироваться в зависимости от вашей системы и возможностей оборудования. Это значение можно изменять до достижения стабильности и лучшего визуального качества. Отключено Синхронизация скорости ядра Синхронизирует скорость ядра с максимальным процентом скорости для улучшения производительности без изменения фактической скорости игры. diff --git a/src/android/app/src/main/res/values-sr/strings.xml b/src/android/app/src/main/res/values-sr/strings.xml index d63f8a3f1d..2f25a95179 100644 --- a/src/android/app/src/main/res/values-sr/strings.xml +++ b/src/android/app/src/main/res/values-sr/strings.xml @@ -73,7 +73,7 @@ ГПУ екстензије Проширена динамичка држава - Омогућава функције Вулкана да побољшају перформансе, приказивање и уштеде ресурсе за креирање на цевоводама, задржавајући нижи ЦПУ / ГПУ коришћење. Ови продужеци могу повећати температуру уређаја и ГПУ који припадају старијој А6кк линији не могу правилно реаговати. Искључите за емулацију скалираних формата. + Управља бројем функција које се могу користити у Проширеном динамичком стању. Веће вредности омогућавају више функција и могу повећати перформансе, али могу изазвати проблеме са неким драјверима и произвођачима. Подразумевана вредност може се разликовати у зависности од вашег система и хардверских могућности. Ова вредност се може мењати док се не постигне стабилност и бољи визуелни квалитет. Искључено Провоцирајући врх Побољшава осветљење и вертификат руковања у одређеним играма. Подржан само на Вулкану 1.0+ ГПУ-у. diff --git a/src/android/app/src/main/res/values-uk/strings.xml b/src/android/app/src/main/res/values-uk/strings.xml index abeefa142e..595d0c7395 100644 --- a/src/android/app/src/main/res/values-uk/strings.xml +++ b/src/android/app/src/main/res/values-uk/strings.xml @@ -85,7 +85,7 @@ Увімкнути LRU-кеш Увімкніть або вимкніть кеш LRU (Least Recently Used) для покращення продуктивності шляхом зменшення навантаження на CPU. Деякі ігри (зокрема TotK 1.2.1) можуть працювати некоректно - вимкніть, якщо гра не запускається або раптово вилітає. Розширений динамічний стан - Активує функції Vulkan для покращення продуктивності, поліпшеня рендерингу та економії ресурсів під час створення конвеєрів (pipeline), зберігаючи низьке використання CPU/GPU. Ці розширення можуть підвищити температуру пристрою, а старі GPU серії A6XX можуть реагувати некоректно. Вимкніть для емуляції масштабованих форматів. + Керує кількістю функцій, які можна використовувати в розширеному динамічному стані. Вищі значення дозволяють більше функцій і можуть підвищити продуктивність, але можуть спричинити проблеми з деякими драйверами та постачальниками. Значення за замовчуванням може відрізнятися залежно від вашої системи та апаратних можливостей. Це значення можна змінювати, док не буде досягнуто стабільності та кращої якості зображення. Вимкнено Синхронізувати швидкість ядра Синхронізує швидкість ядра з максимальним відсотком швидкості для покращення продуктивності без зміни реальної швидкості гри. diff --git a/src/android/app/src/main/res/values-vi/strings.xml b/src/android/app/src/main/res/values-vi/strings.xml index 4e6fd8a436..a11769ed97 100644 --- a/src/android/app/src/main/res/values-vi/strings.xml +++ b/src/android/app/src/main/res/values-vi/strings.xml @@ -85,7 +85,7 @@ Bật bộ nhớ đệm LRU Bật hoặc tắt bộ nhớ đệm LRU để cải thiện hiệu suất bằng cách tiết kiệm quy trình sử dụng CPU. Một số trò chơi như TotK 1.2.1 có vấn đề - hãy tắt nếu trò chơi không khởi động hoặc bị treo ngẫu nhiên. Trạng thái động mở rộng - Kích hoạt tính năng Vulkan để cải thiện hiệu suất, kết xuất và tiết kiệm tài nguyên khi tạo pipeline trong khi vẫn duy trì mức sử dụng CPU/GPU thấp. Các tiện ích mở rộng này có thể làm tăng nhiệt độ thiết bị và GPU thuộc dòng A6XX cũ có thể không phản ứng đúng. Tắt để mô phỏng các định dạng tỷ lệ. + Điều khiển số tính năng có thể được sử dụng trong Trạng thái Động Mở rộng. Giá trị cao hơn cho phép nhiều tính năng hơn và có thể tăng hiệu suất, nhưng có thể gây ra sự cố với một số trình điều khiển và nhà cung cấp. Giá trị mặc định có thể thay đổi tùy thuộc vào hệ thống và khả năng phần cứng của bạn. Giá trị này có thể được thay đổi cho đến khi đạt được độ ổn định và chất lượng hình ảnh tốt hơn. Đã tắt Đồng bộ tốc độ lõi Đồng bộ tốc độ lõi với tỷ lệ phần trăm tốc độ tối đa để cải thiện hiệu suất mà không làm thay đổi tốc độ thực tế của trò chơi. diff --git a/src/android/app/src/main/res/values-zh-rCN/strings.xml b/src/android/app/src/main/res/values-zh-rCN/strings.xml index aff8ffbf08..9a1c9e8824 100644 --- a/src/android/app/src/main/res/values-zh-rCN/strings.xml +++ b/src/android/app/src/main/res/values-zh-rCN/strings.xml @@ -84,7 +84,7 @@ 启用LRU缓存 启用或禁用LRU缓存,通过节省CPU进程使用来提高性能。某些游戏可能存在问题,特别是TotK 1.2.1,如果游戏无法启动或随机崩溃,请禁用此选项。 扩展动态状态 - 启用Vulkan功能以提高性能、渲染效果,并在创建管道时节省资源,同时保持较低的CPU/GPU使用率。这些扩展可能会提高设备温度,旧款A6XX系列GPU可能无法正常工作。禁用可模拟缩放格式。 + 控制扩展动态状态中可使用的功能数量。数值越高,允许的功能越多,并可能提高性能,但可能会导致某些驱动程序和供应商出现问题。默认值可能因系统和硬件能力而异。可以更改此值,直到实现稳定性和更好的视觉质量。 已禁用 同步核心速度 将核心速度与最大速度百分比同步,在不改变游戏实际速度的情况下提高性能。 diff --git a/src/android/app/src/main/res/values-zh-rTW/strings.xml b/src/android/app/src/main/res/values-zh-rTW/strings.xml index 3a11d83b84..79e2f9ea2f 100644 --- a/src/android/app/src/main/res/values-zh-rTW/strings.xml +++ b/src/android/app/src/main/res/values-zh-rTW/strings.xml @@ -85,7 +85,7 @@ 啟用LRU快取 啟用或停用LRU快取,透過節省CPU進程使用來提高效能。某些遊戲可能存在問題,特別是TotK 1.2.1,如果遊戲無法啟動或隨機崩潰,請停用此選項。 擴展動態狀態 - 啟用Vulkan功能以提高效能、渲染效果,並在創建管線時節省資源,同時保持較低的CPU/GPU使用率。這些擴充功能可能會提高裝置溫度,舊款A6XX系列GPU可能無法正常運作。停用可模擬縮放格式。 + 控制擴展動態狀態中可使用的功能數量。數值越高,允許的功能越多,並可能提高效能,但可能會導致某些驅動程式和供應商出現問題。預設值可能因系統和硬體能力而異。可以變更此值,直到實現穩定性和更好的視覺品質。 已停用 同步核心速度 將核心速度與最大速度百分比同步,在不改變遊戲實際速度的情況下提高效能。 diff --git a/src/android/app/src/main/res/values/strings.xml b/src/android/app/src/main/res/values/strings.xml index 06bcdd2d14..c4e85bde08 100644 --- a/src/android/app/src/main/res/values/strings.xml +++ b/src/android/app/src/main/res/values/strings.xml @@ -74,7 +74,7 @@ GPU Extensions Extended Dynamic State - Enables Vulkan features to improve performance, rendering, and save resources on pipeline creation while maintaining lower CPU/GPU usage. These extensions may increase device temperature, and GPUs belonging to the older A6XX line may not react properly. Disable to emulate scaled formats. + Controls the number of features that can be used in Extended Dynamic State. Higher numbers allow for more features and can increase performance, but may cause issues with some drivers and vendors. The default value may vary depending on your system and hardware capabilities. This value can be changed until stability and a better visual quality are achieved. Disabled Provoking Vertex Improves lighting and vertex handling in certain games. Only supported on Vulkan 1.0+ GPUs. From a51953e4f9f8ec4868c473857a4f297eb7a5e2b8 Mon Sep 17 00:00:00 2001 From: MaranBr Date: Fri, 22 Aug 2025 16:23:34 +0200 Subject: [PATCH 03/39] [video_core] Add hability to change Sync Memory Operations at runtime (#300) This adds the hability to change Sync Memory Operations at runtime. Reviewed-on: https://git.eden-emu.dev/eden-emu/eden/pulls/300 Reviewed-by: Shinmegumi Co-authored-by: MaranBr Co-committed-by: MaranBr --- src/common/settings.h | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/src/common/settings.h b/src/common/settings.h index 9ca635c518..2a1c88c79e 100644 --- a/src/common/settings.h +++ b/src/common/settings.h @@ -466,7 +466,13 @@ struct Values { true, true}; #endif - SwitchableSetting sync_memory_operations{linkage, false, "sync_memory_operations", Category::RendererAdvanced, true, true}; + SwitchableSetting sync_memory_operations{linkage, + false, + "sync_memory_operations", + Category::RendererAdvanced, + Specialization::Default, + true, + true}; SwitchableSetting async_presentation{linkage, #ifdef ANDROID true, From 5b864d406d44cd786b00ce0a4cec70fc44930652 Mon Sep 17 00:00:00 2001 From: MaranBr Date: Sat, 23 Aug 2025 19:42:10 +0200 Subject: [PATCH 04/39] [video_core] Add option to control the DMA precision level at runtime (#304) This adds an option to control the DMA precision level at runtime. Co-authored-by: crueter Co-authored-by: PavelBARABANOV Reviewed-on: https://git.eden-emu.dev/eden-emu/eden/pulls/304 Reviewed-by: crueter Co-authored-by: MaranBr Co-committed-by: MaranBr --- .../features/settings/model/IntSetting.kt | 1 + .../features/settings/model/view/SettingsItem.kt | 9 +++++++++ .../settings/ui/SettingsFragmentPresenter.kt | 1 + .../app/src/main/res/values-ar/strings.xml | 8 ++++++++ .../app/src/main/res/values-ckb/strings.xml | 10 ++++++++++ .../app/src/main/res/values-cs/strings.xml | 8 ++++++++ .../app/src/main/res/values-de/strings.xml | 8 ++++++++ .../app/src/main/res/values-es/strings.xml | 8 ++++++++ .../app/src/main/res/values-fa/strings.xml | 8 ++++++++ .../app/src/main/res/values-fr/strings.xml | 8 ++++++++ .../app/src/main/res/values-he/strings.xml | 8 ++++++++ .../app/src/main/res/values-hu/strings.xml | 8 ++++++++ .../app/src/main/res/values-id/strings.xml | 8 ++++++++ .../app/src/main/res/values-it/strings.xml | 8 ++++++++ .../app/src/main/res/values-ja/strings.xml | 8 ++++++++ .../app/src/main/res/values-ko/strings.xml | 8 ++++++++ .../app/src/main/res/values-nb/strings.xml | 10 ++++++++++ .../app/src/main/res/values-pl/strings.xml | 9 +++++++++ .../app/src/main/res/values-pt-rBR/strings.xml | 8 ++++++++ .../app/src/main/res/values-pt-rPT/strings.xml | 8 ++++++++ .../app/src/main/res/values-ru/strings.xml | 8 ++++++++ .../app/src/main/res/values-sr/strings.xml | 8 ++++++++ .../app/src/main/res/values-uk/strings.xml | 8 ++++++++ .../app/src/main/res/values-vi/strings.xml | 10 ++++++++++ .../app/src/main/res/values-zh-rCN/strings.xml | 8 ++++++++ .../app/src/main/res/values-zh-rTW/strings.xml | 8 ++++++++ src/android/app/src/main/res/values/arrays.xml | 13 +++++++++++++ src/android/app/src/main/res/values/strings.xml | 8 ++++++++ src/common/settings.h | 12 ++++++++++++ src/common/settings_enums.h | 2 ++ src/video_core/dma_pusher.cpp | 13 +++++++++++-- src/yuzu/configuration/shared_translation.cpp | 15 +++++++++++++-- src/yuzu/uisettings.h | 1 + 33 files changed, 262 insertions(+), 4 deletions(-) diff --git a/src/android/app/src/main/java/org/yuzu/yuzu_emu/features/settings/model/IntSetting.kt b/src/android/app/src/main/java/org/yuzu/yuzu_emu/features/settings/model/IntSetting.kt index 6ba101263a..21aad8b5d1 100644 --- a/src/android/app/src/main/java/org/yuzu/yuzu_emu/features/settings/model/IntSetting.kt +++ b/src/android/app/src/main/java/org/yuzu/yuzu_emu/features/settings/model/IntSetting.kt @@ -27,6 +27,7 @@ enum class IntSetting(override val key: String) : AbstractIntSetting { RENDERER_SCREEN_LAYOUT("screen_layout"), RENDERER_ASPECT_RATIO("aspect_ratio"), RENDERER_OPTIMIZE_SPIRV_OUTPUT("optimize_spirv_output"), + DMA_ACCURACY("dma_accuracy"), AUDIO_OUTPUT_ENGINE("output_engine"), MAX_ANISOTROPY("max_anisotropy"), THEME("theme"), diff --git a/src/android/app/src/main/java/org/yuzu/yuzu_emu/features/settings/model/view/SettingsItem.kt b/src/android/app/src/main/java/org/yuzu/yuzu_emu/features/settings/model/view/SettingsItem.kt index 15fde13bf3..062038aa44 100644 --- a/src/android/app/src/main/java/org/yuzu/yuzu_emu/features/settings/model/view/SettingsItem.kt +++ b/src/android/app/src/main/java/org/yuzu/yuzu_emu/features/settings/model/view/SettingsItem.kt @@ -602,6 +602,15 @@ abstract class SettingsItem( valuesId = R.array.optimizeSpirvOutputValues ) ) + put( + SingleChoiceSetting( + IntSetting.DMA_ACCURACY, + titleId = R.string.dma_accuracy, + descriptionId = R.string.dma_accuracy_description, + choicesId = R.array.dmaAccuracyNames, + valuesId = R.array.dmaAccuracyValues + ) + ) put( SwitchSetting( BooleanSetting.RENDERER_ASYNCHRONOUS_SHADERS, diff --git a/src/android/app/src/main/java/org/yuzu/yuzu_emu/features/settings/ui/SettingsFragmentPresenter.kt b/src/android/app/src/main/java/org/yuzu/yuzu_emu/features/settings/ui/SettingsFragmentPresenter.kt index bcdd65b1a3..672bcd492c 100644 --- a/src/android/app/src/main/java/org/yuzu/yuzu_emu/features/settings/ui/SettingsFragmentPresenter.kt +++ b/src/android/app/src/main/java/org/yuzu/yuzu_emu/features/settings/ui/SettingsFragmentPresenter.kt @@ -448,6 +448,7 @@ class SettingsFragmentPresenter( add(HeaderSetting(R.string.veil_renderer)) add(BooleanSetting.ENABLE_RAII.key) add(BooleanSetting.RENDERER_EARLY_RELEASE_FENCES.key) + add(IntSetting.DMA_ACCURACY.key) add(BooleanSetting.BUFFER_REORDER_DISABLE.key) add(BooleanSetting.FRAME_INTERPOLATION.key) add(BooleanSetting.RENDERER_FAST_GPU.key) diff --git a/src/android/app/src/main/res/values-ar/strings.xml b/src/android/app/src/main/res/values-ar/strings.xml index f9130457cc..a775e3c176 100644 --- a/src/android/app/src/main/res/values-ar/strings.xml +++ b/src/android/app/src/main/res/values-ar/strings.xml @@ -117,6 +117,8 @@ دورات تخطي إبطال ذاكرة التخزين المؤقت الداخلية للوحدة المركزية يتخطى بعض عمليات إبطال ذاكرة التخزين المؤقت أثناء تحديثات الذاكرة، مما يقلل استخدام المعالج ويحسن أدائه. قد يسبب هذا أعطالاً أو تعطلًا في بعض الألعاب. + مستوى DMA + يتحكم في دقة تحديد مستوى DMA. الدقة الأعلى يمكنها إصلاح بعض المشاكل في بعض الألعاب، ولكنها قد تؤثر أيضًا على الأداء في بعض الحالات. إذا كنت غير متأكد، اتركه على الوضع الافتراضي. 4 جيجابايت (موصى به) @@ -741,6 +743,12 @@ عالي Extreme (بطيء) + + افتراضي + عادي + عالي + مفرط + 0.25X (180p/270p) 0.5X (360p/540p) diff --git a/src/android/app/src/main/res/values-ckb/strings.xml b/src/android/app/src/main/res/values-ckb/strings.xml index c005e0cab7..7c71e9e8fe 100644 --- a/src/android/app/src/main/res/values-ckb/strings.xml +++ b/src/android/app/src/main/res/values-ckb/strings.xml @@ -126,6 +126,8 @@ تیک بازنەکردنی ناوەکی CPU هەندێک لە بازنەکردنەکانی هەڵگر لە کاتی نوێکردنەوەی بیرگە دەنێرێت، کەمکردنەوەی بەکارهێنانی CPU و باشترکردنی کارایی. لەوانەیە لە هەندێک یاری کێشە درووست بکات. + ئاستی DMA + کۆنتڕۆڵی وردی ڕێکخستنی DMA دەکات. وردی زیاتر دەتوانێ هەندێک کێشە لە هەندێک یاری چارەسەر بکات، بەڵام لە هەندێک حاڵەتدا کاریگەری لەسەر کارایی هەیە. ئەگەر دڵنیا نیت، بە ڕێکخستنی بنەڕەتی بێڵە. 4GB (پێشنیارکراو) 6GB (نائاسایش) @@ -688,6 +690,7 @@ هەڵەی کوشندە هەڵەیەکی کوشندە ڕوویدا. بۆ وردەکارییەکان لۆگەکە بپشکنە.\nبەردەوامی ئیمولەیشن لەوانەیە ببێتە هۆی تێکچوون و فڕێدانەدەرەوە. کوژاندنەوەی ئەم ڕێکخستنە دەبێتە هۆی کەمکردنەوەی کارایی ئیمولەیشن! بۆ باشترین ئەزموون، باشترە ئەم ڕێکخستنە چالاک بهێڵیتەوە. + ژاپۆن ئەمریکا @@ -699,6 +702,7 @@ B GB + ڤوڵکان هیچ @@ -708,6 +712,12 @@ بەرز ئەوپەڕ (خاو) + + بنەڕەتی + ئاسایی + بەرز + زۆر بەرز + 0.25X (180p/270p) 0.5X (360p/540p) diff --git a/src/android/app/src/main/res/values-cs/strings.xml b/src/android/app/src/main/res/values-cs/strings.xml index 8cdc753e8d..18df8c8413 100644 --- a/src/android/app/src/main/res/values-cs/strings.xml +++ b/src/android/app/src/main/res/values-cs/strings.xml @@ -125,6 +125,8 @@ Takty Přeskočit vnitřní invalidaci CPU Přeskočí některé invalidace mezipaměti na straně CPU během aktualizací paměti, čímž sníží zatížení CPU a zlepší jeho výkon. Může způsobit chyby nebo pády v některých hrách. + Úroveň DMA + Ovládá přesnost DMA. Vyšší přesnost může opravit problémy v některých hrách, ale může také ovlivnit výkon. Pokud si nejste jisti, ponechejte výchozí nastavení. 4GB (Doporučeno) 6GB (Nebezpečné) @@ -684,6 +686,12 @@ Vysoká Extrémní (Pomalé) + + Výchozí + Normální + Vysoká + Extrémní + 0.25X (180p/270p) 0.5X (360p/540p) diff --git a/src/android/app/src/main/res/values-de/strings.xml b/src/android/app/src/main/res/values-de/strings.xml index 9aae9f3bd3..fcd85018cc 100644 --- a/src/android/app/src/main/res/values-de/strings.xml +++ b/src/android/app/src/main/res/values-de/strings.xml @@ -126,6 +126,8 @@ Ticks CPU-interne Invalidierung überspringen Überspringt bestimmte Cache-Invalidierungen auf CPU-Seite während Speicherupdates, reduziert die CPU-Auslastung und verbessert die Leistung. Kann in einigen Spielen zu Fehlern oder Abstürzen führen. + DMA-Level + Steuert die DMA-Präzisionsgenauigkeit. Eine höhere Präzision kann Probleme in einigen Spielen beheben, kann aber in einigen Fällen auch die Leistung beeinträchtigen. Im Zweifel auf „Standard“ belassen. 4 GB (Empfohlen) 6 GB (Unsicher) @@ -770,6 +772,12 @@ Wirklich fortfahren? Hoch Extrem (Langsam) + + Standard + Normal + Hoch + Extrem + 0.25X (180p/270p) 0.5X (360p/540p) diff --git a/src/android/app/src/main/res/values-es/strings.xml b/src/android/app/src/main/res/values-es/strings.xml index ebd0768d6b..8cd93efe73 100644 --- a/src/android/app/src/main/res/values-es/strings.xml +++ b/src/android/app/src/main/res/values-es/strings.xml @@ -126,6 +126,8 @@ Ticks Omitir invalidación interna de la CPU Omite ciertas invalidaciones de caché durante actualizaciones de memoria, reduciendo el uso de CPU y mejorando su rendimiento. Puede causar fallos en algunos juegos. + Nivel de DMA + Controla la precisión del DMA. Una mayor precisión puede solucionar problemas en algunos juegos, pero también puede afectar el rendimiento en algunos casos. Si no está seguro, déjelo en Predeterminado. 4GB (Recomendado) 6GB (Inseguro) @@ -819,6 +821,12 @@ Alto Extremo (Lento) + + Predeterminado + Normal + Alto + Extremo + 0.25X (180p/270p) 0.5X (360p/540p) diff --git a/src/android/app/src/main/res/values-fa/strings.xml b/src/android/app/src/main/res/values-fa/strings.xml index dec0a1c842..5bf8a634d1 100644 --- a/src/android/app/src/main/res/values-fa/strings.xml +++ b/src/android/app/src/main/res/values-fa/strings.xml @@ -126,6 +126,8 @@ تیک‌ها رد کردن ابطال داخلی CPU بعضی ابطال‌های حافظه نهان در هنگام به‌روزرسانی‌های حافظه را رد می‌کند، استفاده از CPU را کاهش داده و عملکرد آن را بهبود می‌بخشد. ممکن است در برخی بازی‌ها باعث مشکلات یا خرابی شود. + سطح DMA + دقت صحت DMA را کنترل می کند. دقت بالاتر می تواند مشکلات برخی بازی ها را برطرف کند، اما در برخی موارد نیز می تواند بر عملکرد تأثیر بگذارد. اگر مطمئن نیستید، آن را روی پیش فرض بگذارید. 4 گیگابایت (توصیه شده) 6 گیگابایت (ناامن) @@ -818,6 +820,12 @@ زیاد افراطی (کند) + + پیش فرض + معمولی + بالا + فوق العاده + 0.25X (180p/270p) 0.5X (360p/540p) diff --git a/src/android/app/src/main/res/values-fr/strings.xml b/src/android/app/src/main/res/values-fr/strings.xml index 6ca92875cf..9a74bb61bb 100644 --- a/src/android/app/src/main/res/values-fr/strings.xml +++ b/src/android/app/src/main/res/values-fr/strings.xml @@ -126,6 +126,8 @@ Ticks Ignorer l\'invalidation interne du CPU Ignore certaines invalidations de cache côté CPU lors des mises à jour mémoire, réduisant l\'utilisation du CPU et améliorant ses performances. Peut causer des bugs ou plantages sur certains jeux. + Niveau DMA + Contrôle la précision du DMA. Une précision plus élevée peut résoudre les problèmes dans certains jeux, mais peut aussi affecter les performances dans certains cas. Si vous n\'êtes pas sûr, laissez-la sur Défaut. 4 Go (Recommandé) 6 Go (Dangereux) @@ -867,6 +869,12 @@ Haut Extrême (Lent) + + Défaut + Normal + Élevé + Extrême + 0.25X (180p/270p) 0.5X (360p/540p) diff --git a/src/android/app/src/main/res/values-he/strings.xml b/src/android/app/src/main/res/values-he/strings.xml index caf4f5bf74..5413c0797b 100644 --- a/src/android/app/src/main/res/values-he/strings.xml +++ b/src/android/app/src/main/res/values-he/strings.xml @@ -127,6 +127,8 @@ טיקים דלג על איפוס מטמון פנימי של המעבד מדלג על איפוסי מטמון מסוימים במהלך עדכוני זיכרון, מפחית שימוש במעבד ומשפר ביצועים. עלול לגרום לתקלות או קריסות בחלק מהמשחקים. + רמת DMA + שולטת בדיוק הדיוק של DMA. דיוק גבוה יותר יכול לתקן בעיות בחלק מהמשחקים, אך הוא עלול גם להשפיע על הביצועים במקרים מסוימים. אם אינך בטוח, השאר ברירת מחדל. 4GB (מומלץ) 6GB (לא בטוח) @@ -749,6 +751,12 @@ גבוה אקסטרים (איטי) + + ברירת מחדל + רגיל + גבוה + קיצוני + 0.25X (180p/270p) 0.5X (360p/540p) diff --git a/src/android/app/src/main/res/values-hu/strings.xml b/src/android/app/src/main/res/values-hu/strings.xml index 6ea078a78d..73ccbd03e0 100644 --- a/src/android/app/src/main/res/values-hu/strings.xml +++ b/src/android/app/src/main/res/values-hu/strings.xml @@ -126,6 +126,8 @@ Tick-ek CPU belső érvénytelenítés kihagyása Kihagy néhány CPU-oldali gyorsítótár-érvénytelenítést memóriafrissítések közben, csökkentve a CPU használatát és javítva a teljesítményt. Néhány játékban hibákat vagy összeomlást okozhat. + DMA szint + Szabályozza a DMA pontosságát. A magasabb pontosság megoldhat néhány játék problémáit, de bizonyos esetekben befolyásolhatja a teljesítményt. Ha bizonytalan, hagyja Alapértelmezett beállításnál. 4GB (Ajánlott) 6GB (Nem biztonságos) @@ -856,6 +858,12 @@ Magas Extrém (Lassú) + + Alapértelmezett + Normál + Magas + Extrém + 0.25X (180p/270p) 0.5X (360p/540p) diff --git a/src/android/app/src/main/res/values-id/strings.xml b/src/android/app/src/main/res/values-id/strings.xml index f37e3bb4c5..44d43b4578 100644 --- a/src/android/app/src/main/res/values-id/strings.xml +++ b/src/android/app/src/main/res/values-id/strings.xml @@ -126,6 +126,8 @@ Ticks Lewati Pembatalan Internal CPU Melewati beberapa pembatalan cache sisi CPU selama pembaruan memori, mengurangi penggunaan CPU dan meningkatkan kinerjanya. Mungkin menyebabkan gangguan atau crash pada beberapa game. + Level DMA + Mengontrol akurasi presisi DMA. Presisi yang lebih tinggi dapat memperbaiki masalah di beberapa game, tetapi juga dapat memengaruhi performa dalam beberapa kasus. Jika tidak yakin, biarkan di Bawaan. 4GB (Direkomendasikan) 6GB (Tidak Aman) @@ -811,6 +813,12 @@ Tinggi Ekstrim (Lambat) + + Bawaan + Normal + Tinggi + Ekstrem + 0.25X (180p/270p) 0.5X (360p/540p) diff --git a/src/android/app/src/main/res/values-it/strings.xml b/src/android/app/src/main/res/values-it/strings.xml index ddce663c7c..4fc29eb597 100644 --- a/src/android/app/src/main/res/values-it/strings.xml +++ b/src/android/app/src/main/res/values-it/strings.xml @@ -126,6 +126,8 @@ Tick Salta invalidamento interno CPU Salta alcuni invalidamenti della cache lato CPU durante gli aggiornamenti di memoria, riducendo l\'uso della CPU e migliorandone le prestazioni. Potrebbe causare glitch o crash in alcuni giochi. + Livello DMA + Controlla la precisione del DMA. Una precisione più alta può risolvere problemi in alcuni giochi, ma in alcuni casi può influire sulle prestazioni. Se non sei sicuro, lascia su Predefinito. 4GB (Consigliato) 6GB (Non sicuro) @@ -780,6 +782,12 @@ Alta Estrema (Lenta) + + Predefinito + Normale + Alto + Estremo + 0.25X (180p/270p) 0.5X (360p/540p) diff --git a/src/android/app/src/main/res/values-ja/strings.xml b/src/android/app/src/main/res/values-ja/strings.xml index 85ac46dd71..d65a32230a 100644 --- a/src/android/app/src/main/res/values-ja/strings.xml +++ b/src/android/app/src/main/res/values-ja/strings.xml @@ -126,6 +126,8 @@ ティック CPU内部無効化をスキップ メモリ更新時のCPU側キャッシュ無効化をスキップし、CPU使用率を減らして性能を向上させます。一部のゲームで不具合やクラッシュが発生する可能性があります。 + DMAレベル + DMAの精度を制御します。精度を高くすると一部のゲームの問題が修正される場合がありますが、場合によってはパフォーマンスに影響を与える可能性もあります。不明な場合は、デフォルトのままにしてください。 4GB (推奨) 6GB (安全でない) @@ -739,6 +741,12 @@ 最高 (低速) + + デフォルト + 標準 + + 最高 + 0.25X (180p/270p) 0.5X (360p/540p) diff --git a/src/android/app/src/main/res/values-ko/strings.xml b/src/android/app/src/main/res/values-ko/strings.xml index a2974f99fa..7871fa7427 100644 --- a/src/android/app/src/main/res/values-ko/strings.xml +++ b/src/android/app/src/main/res/values-ko/strings.xml @@ -126,6 +126,8 @@ CPU 내부 무효화 건너뛰기 메모리 업데이트 시 일부 CPU 측 캐시 무효화를 건너뛰어 CPU 사용량을 줄이고 성능을 향상시킵니다. 일부 게임에서 오류 또는 충돌을 일으킬 수 있습니다. + DMA 수준 + DMA 정밀도를 제어합니다. 높은 정밀도는 일부 게임의 문제를 해결할 수 있지만 경우에 따라 성능에 영향을 미칠 수도 있습니다. 확실하지 않다면 기본값으로 두세요. 4GB (권장) 6GB (안전하지 않음) @@ -810,6 +812,12 @@ 높음 극한 (느림) + + 기본값 + 보통 + 높음 + 극단적 + 0.25X (180p/270p) 0.5X (360p/540p) diff --git a/src/android/app/src/main/res/values-nb/strings.xml b/src/android/app/src/main/res/values-nb/strings.xml index 3bea2895b5..8717f212d1 100644 --- a/src/android/app/src/main/res/values-nb/strings.xml +++ b/src/android/app/src/main/res/values-nb/strings.xml @@ -126,6 +126,8 @@ Takter Hopp over CPU intern invalidering Hopper over enkelte CPU-side cache-invalideringer under minneoppdateringer, reduserer CPU-bruk og forbedrer ytelsen. Kan forårsake feil eller krasj i noen spill. + DMA-nivå + Styrer DMA-presisjonsnøyaktigheten. Høyere presisjon kan fikse problemer i noen spill, men kan også påvirke ytelsen i noen tilfeller. Hvis du er usikker, la den stå på Standard. 4GB (Anbefalt) 6GB (Usikkert) @@ -698,6 +700,7 @@ Fatal Feil Det oppstod en fatal feil. Sjekk loggen for mer informasjon.\nFortsatt emulering kan føre til krasj og feil. Hvis du slår av denne innstillingen, reduseres emuleringsytelsen betydelig! Vi anbefaler at du lar denne innstillingen være aktivert for å få den beste opplevelsen. + Japan USA @@ -709,6 +712,7 @@ B GB + Vulkan Ingen @@ -718,6 +722,12 @@ Høy Ekstrem (Treg) + + Standard + Normal + Høy + Ekstrem + 0.25X (180p/270p) 0.5X (360p/540p) diff --git a/src/android/app/src/main/res/values-pl/strings.xml b/src/android/app/src/main/res/values-pl/strings.xml index a87a4eabb5..0c0a3e9012 100644 --- a/src/android/app/src/main/res/values-pl/strings.xml +++ b/src/android/app/src/main/res/values-pl/strings.xml @@ -126,6 +126,8 @@ Takty Pomiń wewnętrzne unieważnienie CPU Pomija niektóre unieważnienia pamięci podręcznej po stronie CPU podczas aktualizacji pamięci, zmniejszając użycie CPU i poprawiając jego wydajność. Może powodować błędy lub awarie w niektórych grach. + Poziom DMA + Kontroluje dokładność precyzji DMA. Wyższy poziom może naprawić problemy w niektórych grach, ale może również wpłynąć na wydajność. Jeśli nie jesteś pewien, pozostaw wartość «Domyślny». 4GB (Zalecane) 6GB (Niebezpieczne) @@ -707,6 +709,7 @@ B GB + Vulkan Żadny @@ -716,6 +719,12 @@ Wysoki Ekstremalny (Wolny) + + 預設 + 普通 + + 極高 + 0.25X (180p/270p) 0.5X (360p/540p) diff --git a/src/android/app/src/main/res/values-pt-rBR/strings.xml b/src/android/app/src/main/res/values-pt-rBR/strings.xml index 8db231dff0..d9a143921d 100644 --- a/src/android/app/src/main/res/values-pt-rBR/strings.xml +++ b/src/android/app/src/main/res/values-pt-rBR/strings.xml @@ -126,6 +126,8 @@ Ticks Pular invalidação interna da CPU Ignora algumas invalidações de cache do lado da CPU durante atualizações de memória, reduzindo o uso da CPU e melhorando seu desempenho. Pode causar falhas ou travamentos em alguns jogos. + Nível DMA + Controla a precisão do DMA. Maior precisão pode corrigir problemas em alguns jogos, mas também pode impactar o desempenho em alguns casos. Se não tiver certeza, deixe em Padrão. 4GB (Recomendado) 6GB (Inseguro) @@ -868,6 +870,12 @@ uma tentativa de mapeamento automático Alta Extrema (Lenta) + + Padrão + Normal + Alto + Extremo + 0.25X (180p/270p) 0.5X (360p/540p) diff --git a/src/android/app/src/main/res/values-pt-rPT/strings.xml b/src/android/app/src/main/res/values-pt-rPT/strings.xml index 3f0248110e..fd3787cb00 100644 --- a/src/android/app/src/main/res/values-pt-rPT/strings.xml +++ b/src/android/app/src/main/res/values-pt-rPT/strings.xml @@ -126,6 +126,8 @@ Ticks Ignorar invalidação interna da CPU Ignora algumas invalidações de cache do lado da CPU durante atualizações de memória, reduzindo a utilização da CPU e melhorando o desempenho. Pode causar falhas ou crashes em alguns jogos. + Nível DMA + Controla a precisão do DMA. Maior precisão pode corrigir problemas em alguns jogos, mas também pode afetar o desempenho nalguns casos. Se não tiver a certeza, deixe em Predefinido. 4GB (Recomendado) 6GB (Inseguro) @@ -868,6 +870,12 @@ uma tentativa de mapeamento automático Alto Estremo (Lento) + + Predefinido + Normal + Alto + Extremo + 0.25X (180p/270p) 0.5X (360p/540p) diff --git a/src/android/app/src/main/res/values-ru/strings.xml b/src/android/app/src/main/res/values-ru/strings.xml index 955a013e30..787111cde4 100644 --- a/src/android/app/src/main/res/values-ru/strings.xml +++ b/src/android/app/src/main/res/values-ru/strings.xml @@ -126,6 +126,8 @@ Такты Пропустить внутреннюю инвалидацию ЦП Пропускает некоторые инвалидации кэша на стороне ЦП при обновлениях памяти, уменьшая нагрузку на процессор и повышая производительность. Может вызывать сбои в некоторых играх. + Уровень DMA + Управляет точностью DMA. Более высокий уровень может исправить проблемы в некоторых играх, но также может повлиять на производительность. Если не уверены, оставьте значение «По умолчанию». 4 ГБ (Рекомендуется) 6 ГБ (Небезопасно) @@ -869,6 +871,12 @@ Высокая Экстрим (медленный) + + По умолчанию + Нормальный + Высокий + Экстремальный + 0.25X (180p/270p) 0.5X (360p/540p) diff --git a/src/android/app/src/main/res/values-sr/strings.xml b/src/android/app/src/main/res/values-sr/strings.xml index 2f25a95179..1eba9baa16 100644 --- a/src/android/app/src/main/res/values-sr/strings.xml +++ b/src/android/app/src/main/res/values-sr/strings.xml @@ -119,6 +119,8 @@ Тактови Preskoči unutrašnje poništavanje CPU-a Preskače određena poništavanja keša na strani CPU-a tokom ažuriranja memorije, smanjujući opterećenje procesora i poboljšavajući performanse. Može izazvati greške u nekim igrama. + DMA ниво + Контролише тачност DMA прецизности. Виши ниво може да поправи проблеме у неким играма, али може и да утиче на перформансе. Ако нисте сигурни, оставите на «Подразумевано». Схадер Бацкенд @@ -864,6 +866,12 @@ Високо Екстремни (спор) + + Подразумевано + Нормално + Високо + Екстремно + АСТЦ метода декодирања Изаберите како су текстуре са компримираним текстовима декодиране за приказивање: ЦПУ (споро, сигуран), ГПУ (Фаст, Препоручи) или ЦПУ АСИНЦ (без затезача, могу да изазове питања) diff --git a/src/android/app/src/main/res/values-uk/strings.xml b/src/android/app/src/main/res/values-uk/strings.xml index 595d0c7395..7dc9ded033 100644 --- a/src/android/app/src/main/res/values-uk/strings.xml +++ b/src/android/app/src/main/res/values-uk/strings.xml @@ -126,6 +126,8 @@ Такти Пропустити внутрішнє інвалідування CPU Пропускає деякі інвалідації кешу на стороні CPU під час оновлення пам\'яті, зменшуючи навантаження на процесор і покращуючи продуктивність. Може спричинити збої в деяких іграх. + Рівень DMA + Керує точністю DMA. Вищий рівень може виправити проблеми в деяких іграх, але також може вплинути на продуктивність. Якщо не впевнені, залиште значення «Типово». 4 ГБ (Рекомендовано) 6 ГБ (Небезпечно) @@ -735,6 +737,12 @@ Висока Екстрим (повільно) + + Типово + Нормальний + Високий + Екстремальний + 0.25X (180p/270p) 0.5X (360p/540p) diff --git a/src/android/app/src/main/res/values-vi/strings.xml b/src/android/app/src/main/res/values-vi/strings.xml index a11769ed97..5655f2c745 100644 --- a/src/android/app/src/main/res/values-vi/strings.xml +++ b/src/android/app/src/main/res/values-vi/strings.xml @@ -126,6 +126,8 @@ Tích Bỏ qua vô hiệu hóa bên trong CPU Bỏ qua một số lần vô hiệu hóa bộ nhớ đệm phía CPU trong khi cập nhật bộ nhớ, giảm mức sử dụng CPU và cải thiện hiệu suất. Có thể gây ra lỗi hoặc treo máy trong một số trò chơi. + Cấp độ DMA + Điều khiển độ chính xác của DMA. Độ chính xác cao hơn có thể sửa lỗi trong một số trò chơi, nhưng cũng có thể ảnh hưởng đến hiệu suất trong một số trường hợp. Nếu không chắc chắn, hãy để ở Mặc định. 4GB (Được đề xuất) 6GB (Không an toàn) @@ -701,6 +703,7 @@ Lỗi nghiêm trọng Đã xảy ra lỗi nghiêm trọng. Kiểm tra nhật ký để biết chi tiết.\nViệc tiếp tục giả lập có thể dẫn đến sự cố và lỗi. Tắt cài đặt này sẽ làm giảm đáng kể hiệu suất giả lập! Để có trải nghiệm tốt nhất, bạn nên bật cài này. + Nhật Bản Hoa Kỳ @@ -712,6 +715,7 @@ B GB + Vulkan Trống @@ -721,6 +725,12 @@ Khỏe Tối đa (Chậm) + + Mặc định + Bình thường + Cao + Cực cao + 0.25X (180p/270p) 0.5X (360p/540p) diff --git a/src/android/app/src/main/res/values-zh-rCN/strings.xml b/src/android/app/src/main/res/values-zh-rCN/strings.xml index 9a1c9e8824..ec519cec56 100644 --- a/src/android/app/src/main/res/values-zh-rCN/strings.xml +++ b/src/android/app/src/main/res/values-zh-rCN/strings.xml @@ -125,6 +125,8 @@ 时钟 跳过CPU内部无效化 在内存更新期间跳过某些CPU端缓存无效化,减少CPU使用率并提高其性能。可能会导致某些游戏出现故障或崩溃。 + DMA 级别 + 控制 DMA 精度。更高的精度可以修复某些游戏中的问题,但在某些情况下也可能影响性能。如果不确定,请保留为“默认”。 4GB (推荐) 6GB (不安全) @@ -861,6 +863,12 @@ 极高 (慢速) + + 默认 + 普通 + + 极高 + 0.25X (180p/270p) 0.5X (360p/540p) diff --git a/src/android/app/src/main/res/values-zh-rTW/strings.xml b/src/android/app/src/main/res/values-zh-rTW/strings.xml index 79e2f9ea2f..0d154af67c 100644 --- a/src/android/app/src/main/res/values-zh-rTW/strings.xml +++ b/src/android/app/src/main/res/values-zh-rTW/strings.xml @@ -118,6 +118,8 @@ 時脈 跳過CPU內部無效化 在記憶體更新期間跳過某些CPU端快取無效化,減少CPU使用率並提高其性能。可能會導致某些遊戲出現故障或崩潰。 + DMA 級別 + 控制 DMA 精確度。更高的精確度可以修復某些遊戲中的問題,但在某些情況下也可能影響效能。如果不確定,請保留為「預設」。 4GB (推薦) @@ -866,6 +868,12 @@ 極高 (慢) + + 預設 + 普通 + + 極高 + 0.25X (180p/270p) 0.5X (360p/540p) diff --git a/src/android/app/src/main/res/values/arrays.xml b/src/android/app/src/main/res/values/arrays.xml index 602003cf8a..2f0392675d 100644 --- a/src/android/app/src/main/res/values/arrays.xml +++ b/src/android/app/src/main/res/values/arrays.xml @@ -452,6 +452,19 @@ 2 + + @string/dma_accuracy_default + @string/dma_accuracy_normal + @string/dma_accuracy_high + @string/dma_accuracy_extreme + + + 0 + 1 + 2 + 3 + + @string/applet_hle @string/applet_lle diff --git a/src/android/app/src/main/res/values/strings.xml b/src/android/app/src/main/res/values/strings.xml index c4e85bde08..975bd1741a 100644 --- a/src/android/app/src/main/res/values/strings.xml +++ b/src/android/app/src/main/res/values/strings.xml @@ -113,6 +113,8 @@ Use Boost (1700MHz) to run at the Switch\'s highest native clock, or Fast (2000MHz) to run at 2x clock. Memory Layout (EXPERIMENTAL) Change the emulated memory layout. This setting will not increase performance, but may help with games utilizing high resolutions via mods. Do not use on phones with 8GB of RAM or less. Only works on the Dynarmic (JIT) backend. + DMA Level + Controls the DMA precision accuracy. Higher precision can fix issues in some games, but it can also impact performance in some cases. If unsure, leave it at Default. Shader Backend @@ -932,6 +934,12 @@ High Extreme (Slow) + + Default + Normal + High + Extreme + ASTC Decoding Method Pick how ASTC-compressed textures are decoded for rendering: CPU (slow, safe), GPU (fast, recommended), or CPU Async (no stutters, may cause issues) diff --git a/src/common/settings.h b/src/common/settings.h index 2a1c88c79e..01e391d501 100644 --- a/src/common/settings.h +++ b/src/common/settings.h @@ -427,7 +427,19 @@ struct Values { Specialization::Default, true, true}; + GpuAccuracy current_gpu_accuracy{GpuAccuracy::High}; + + SwitchableSetting dma_accuracy{linkage, + DmaAccuracy::Default, + DmaAccuracy::Default, + DmaAccuracy::Extreme, + "dma_accuracy", + Category::RendererAdvanced, + Specialization::Default, + true, + true}; + SwitchableSetting max_anisotropy{linkage, #ifdef ANDROID AnisotropyMode::Default, diff --git a/src/common/settings_enums.h b/src/common/settings_enums.h index c2347f74d0..52b4a128f7 100644 --- a/src/common/settings_enums.h +++ b/src/common/settings_enums.h @@ -136,6 +136,8 @@ ENUM(ShaderBackend, Glsl, Glasm, SpirV); ENUM(GpuAccuracy, Normal, High, Extreme); +ENUM(DmaAccuracy, Default, Normal, High, Extreme); + ENUM(CpuBackend, Dynarmic, Nce); ENUM(CpuAccuracy, Auto, Accurate, Unsafe, Paranoid); diff --git a/src/video_core/dma_pusher.cpp b/src/video_core/dma_pusher.cpp index 8ea4cbd43a..4b9a506cdf 100644 --- a/src/video_core/dma_pusher.cpp +++ b/src/video_core/dma_pusher.cpp @@ -102,9 +102,18 @@ bool DmaPusher::Step() { ProcessCommands(headers); }; - if (Settings::IsGPULevelExtreme()) { + const Settings::DmaAccuracy accuracy = Settings::values.dma_accuracy.GetValue(); + const bool use_gpu_accuracy = accuracy == Settings::DmaAccuracy::Default; + + // reduces eye bleeding but also macros are dumb so idk +#define CHECK_LEVEL(level) use_gpu_accuracy ? Settings::IsGPULevel##level() : accuracy == Settings::DmaAccuracy::level; + const bool force_safe = CHECK_LEVEL(Extreme) + const bool unsafe_compute = CHECK_LEVEL(High) +#undef CHECK_LEVEL + + if (force_safe) { safe_process(); - } else if (Settings::IsGPULevelHigh()) { + } else if (unsafe_compute) { if (dma_state.method >= MacroRegistersStart) { unsafe_process(); } else { diff --git a/src/yuzu/configuration/shared_translation.cpp b/src/yuzu/configuration/shared_translation.cpp index c237015fed..f6d590c0ee 100644 --- a/src/yuzu/configuration/shared_translation.cpp +++ b/src/yuzu/configuration/shared_translation.cpp @@ -288,12 +288,16 @@ std::unique_ptr InitializeTranslations(QWidget* parent) "and safe to set at 16x on most GPUs.")); INSERT(Settings, gpu_accuracy, - tr("Accuracy Level:"), - tr("GPU emulation accuracy.\nMost games render fine with Normal, but High is still " + tr("GPU Level:"), + tr("Controls the GPU emulation accuracy.\nMost games render fine with Normal, but High is still " "required for some.\nParticles tend to only render correctly with High " "accuracy.\nExtreme should only be used for debugging.\nThis option can " "be changed while playing.\nSome games may require booting on high to render " "properly.")); + INSERT(Settings, + dma_accuracy, + tr("DMA Level:"), + tr("Controls the DMA precision accuracy. Higher precision can fix issues in some games, but it can also impact performance in some cases.\nIf unsure, leave it at Default.")); INSERT(Settings, use_asynchronous_shaders, tr("Use asynchronous shader building (Hack)"), @@ -522,6 +526,13 @@ std::unique_ptr ComboboxEnumeration(QWidget* parent) PAIR(GpuAccuracy, High, tr("High")), PAIR(GpuAccuracy, Extreme, tr("Extreme")), }}); + translations->insert({Settings::EnumMetadata::Index(), + { + PAIR(DmaAccuracy, Default, tr("Default")), + PAIR(DmaAccuracy, Normal, tr("Normal")), + PAIR(DmaAccuracy, High, tr("High")), + PAIR(DmaAccuracy, Extreme, tr("Extreme")), + }}); translations->insert( {Settings::EnumMetadata::Index(), { diff --git a/src/yuzu/uisettings.h b/src/yuzu/uisettings.h index 0502fe75e4..85de0ae72d 100644 --- a/src/yuzu/uisettings.h +++ b/src/yuzu/uisettings.h @@ -270,6 +270,7 @@ Q_DECLARE_METATYPE(UISettings::GameDir*); // These metatype declarations cannot be in common/settings.h because core is devoid of QT Q_DECLARE_METATYPE(Settings::CpuAccuracy); Q_DECLARE_METATYPE(Settings::GpuAccuracy); +Q_DECLARE_METATYPE(Settings::DmaAccuracy); Q_DECLARE_METATYPE(Settings::FullscreenMode); Q_DECLARE_METATYPE(Settings::NvdecEmulation); Q_DECLARE_METATYPE(Settings::ResolutionSetup); From 94bcd64153b9b784cd989b04fa4adfca159e96af Mon Sep 17 00:00:00 2001 From: crueter Date: Sat, 23 Aug 2025 19:42:49 +0200 Subject: [PATCH 05/39] [cmake] refactor: SDL2 CI and CPMUtil::AddCIPackage (#284) Replaces bundled SDL2 with my SDL2 CI, and updates external SDL2 Additionally, reduces all that boilerplate with a common AddCIPackage in CPMUtil.cmake, currently used by OpenSSL and SDL2. To be used with ffmpeg in the future Signed-off-by: crueter Reviewed-on: https://git.eden-emu.dev/eden-emu/eden/pulls/284 Reviewed-by: Lizzie Reviewed-by: Shinmegumi --- CMakeLists.txt | 342 ++++++++------------------ CMakeModules/CPMUtil.cmake | 168 +++++++++++++ CMakeModules/DownloadExternals.cmake | 3 - externals/CMakeLists.txt | 45 +--- src/core/CMakeLists.txt | 6 +- src/core/internal_network/network.cpp | 4 +- src/core/internal_network/network.h | 2 +- src/core/internal_network/sockets.h | 4 +- src/web_service/CMakeLists.txt | 8 +- src/yuzu/CMakeLists.txt | 6 +- 10 files changed, 281 insertions(+), 307 deletions(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index ecb8a8268d..dacbc73685 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -44,24 +44,18 @@ if (PLATFORM_FREEBSD) set(CMAKE_EXE_LINKER_FLAGS "${CMAKE_EXE_LINKER_FLAGS} -L/usr/local/lib") endif() -# Check if SDL2::SDL2 target exists; if not, create an alias -if (TARGET SDL2::SDL2-static) - add_library(SDL2::SDL2 ALIAS SDL2::SDL2-static) -elseif (TARGET SDL2::SDL2-shared) - add_library(SDL2::SDL2 ALIAS SDL2::SDL2-shared) -endif() - # Set bundled sdl2/qt as dependent options. # On Linux system SDL2 is likely to be lacking HIDAPI support which have drawbacks but is needed for SDL motion -option(ENABLE_SDL2 "Enable the SDL2 frontend" ON) -CMAKE_DEPENDENT_OPTION(YUZU_USE_BUNDLED_SDL2 "Download bundled SDL2 binaries" ON "ENABLE_SDL2;MSVC" OFF) +CMAKE_DEPENDENT_OPTION(ENABLE_SDL2 "Enable the SDL2 frontend" ON "NOT ANDROID" OFF) + +set(EXT_DEFAULT ON) if (PLATFORM_FREEBSD) - CMAKE_DEPENDENT_OPTION(YUZU_USE_EXTERNAL_SDL2 "Compile external SDL2" OFF "ENABLE_SDL2;NOT MSVC" OFF) -else() - CMAKE_DEPENDENT_OPTION(YUZU_USE_EXTERNAL_SDL2 "Compile external SDL2" ON "ENABLE_SDL2;NOT MSVC" OFF) + set(EXT_DEFAULT OFF) endif() +CMAKE_DEPENDENT_OPTION(YUZU_USE_EXTERNAL_SDL2 "Compile external SDL2" ${EXT_DEFAULT} "ENABLE_SDL2;NOT MSVC" OFF) + cmake_dependent_option(ENABLE_LIBUSB "Enable the use of LibUSB" ON "NOT ANDROID" OFF) option(ENABLE_OPENGL "Enable OpenGL" ON) @@ -78,29 +72,10 @@ option(YUZU_USE_CPM "Use CPM to fetch Eden dependencies if needed" ON) option(ENABLE_WEB_SERVICE "Enable web services (telemetry, etc.)" ON) option(ENABLE_WIFI_SCAN "Enable WiFi scanning" OFF) -if (PLATFORM_FREEBSD) - option(YUZU_USE_BUNDLED_FFMPEG "Download/Build bundled FFmpeg" OFF) -else() - option(YUZU_USE_BUNDLED_FFMPEG "Download/Build bundled FFmpeg" ON) -endif() - -if (PLATFORM_FREEBSD) - option(YUZU_USE_EXTERNAL_VULKAN_HEADERS "Use Vulkan-Headers from externals" OFF) -else() - option(YUZU_USE_EXTERNAL_VULKAN_HEADERS "Use Vulkan-Headers from externals" ON) -endif() - -if (PLATFORM_FREEBSD) - option(YUZU_USE_EXTERNAL_VULKAN_UTILITY_LIBRARIES "Use Vulkan-Utility-Libraries from externals" OFF) -else() - option(YUZU_USE_EXTERNAL_VULKAN_UTILITY_LIBRARIES "Use Vulkan-Utility-Libraries from externals" ON) -endif() - -if (PLATFORM_FREEBSD) - option(YUZU_USE_EXTERNAL_VULKAN_SPIRV_TOOLS "Use SPIRV-Tools from externals" OFF) -else() - option(YUZU_USE_EXTERNAL_VULKAN_SPIRV_TOOLS "Use SPIRV-Tools from externals" ON) -endif() +option(YUZU_USE_BUNDLED_FFMPEG "Download/Build bundled FFmpeg" ${EXT_DEFAULT}) +option(YUZU_USE_EXTERNAL_VULKAN_HEADERS "Use Vulkan-Headers from externals" ${EXT_DEFAULT}) +option(YUZU_USE_EXTERNAL_VULKAN_UTILITY_LIBRARIES "Use Vulkan-Utility-Libraries from externals" ${EXT_DEFAULT}) +option(YUZU_USE_EXTERNAL_VULKAN_SPIRV_TOOLS "Use SPIRV-Tools from externals" ${EXT_DEFAULT}) option(YUZU_USE_QT_MULTIMEDIA "Use QtMultimedia for Camera" OFF) @@ -116,17 +91,16 @@ option(ENABLE_MICROPROFILE "Enables microprofile capabilities" OFF) option(YUZU_TESTS "Compile tests" "${BUILD_TESTING}") -if (PLATFORM_FREEBSD) - option(YUZU_USE_PRECOMPILED_HEADERS "Use precompiled headers" OFF) -else() - option(YUZU_USE_PRECOMPILED_HEADERS "Use precompiled headers" ON) -endif() +option(YUZU_USE_PRECOMPILED_HEADERS "Use precompiled headers" ${EXT_DEFAULT}) option(YUZU_DOWNLOAD_ANDROID_VVL "Download validation layer binary for android" ON) option(FORCE_DOWNLOAD_WIN_BUNDLES "Forcefully download bundled Windows dependencies (useful for CI)" OFF) -option(FORCE_DOWNLOAD_OPENSSL "Forcefully download all bundled OpenSSL builds (useful for CI)" OFF) +if (YUZU_USE_CPM AND ENABLE_SDL2) + option(YUZU_USE_BUNDLED_SDL2 "Download bundled SDL2 build" "${MSVC}") + CMAKE_DEPENDENT_OPTION(FORCE_DOWNLOAD_SDL2 "Forcefully download all bundled SDL2 builds (useful for CI)" OFF "YUZU_USE_BUNDLED_SDL2" OFF) +endif() CMAKE_DEPENDENT_OPTION(YUZU_ROOM "Enable dedicated room functionality" ON "NOT ANDROID" OFF) @@ -169,6 +143,11 @@ endif() option(ENABLE_OPENSSL "Enable OpenSSL backend for ISslConnection" ${DEFAULT_ENABLE_OPENSSL}) +if (YUZU_USE_CPM AND ENABLE_OPENSSL) + CMAKE_DEPENDENT_OPTION(YUZU_USE_BUNDLED_OPENSSL "Download bundled OpenSSL build" "${MSVC}" "NOT ANDROID" ON) + CMAKE_DEPENDENT_OPTION(FORCE_DOWNLOAD_OPENSSL "Forcefully download all bundled OpenSSL builds (useful for CI)" OFF "YUZU_USE_BUNDLED_OPENSSL" OFF) +endif() + if (ANDROID AND YUZU_DOWNLOAD_ANDROID_VVL) set(vvl_version "sdk-1.3.261.1") set(vvl_zip_file "${CMAKE_BINARY_DIR}/externals/vvl-android.zip") @@ -330,7 +309,7 @@ if (UNIX) add_definitions(-DYUZU_UNIX=1) endif() -if (ARCHITECTURE_arm64 AND (ANDROID OR APPLE OR PLATFORM_LINUX)) +if (ARCHITECTURE_arm64 AND (ANDROID OR PLATFORM_LINUX)) set(HAS_NCE 1) add_definitions(-DHAS_NCE=1) endif() @@ -398,183 +377,18 @@ if (YUZU_USE_CPM) # openssl funniness if (ENABLE_OPENSSL) - set(SSL_VERSION 3.5.2) - - if ((MSVC AND ARCHITECTURE_x86_64) OR FORCE_DOWNLOAD_OPENSSL) - set(ARTIFACT openssl-windows-amd64-${SSL_VERSION}.tar.zst) - set(KEY windows-amd64) - - if (MSVC AND ARCHITECTURE_x86_64) - set(DOWNLOAD_ONLY OFF) - set(BUILD_SHARED_LIBS OFF) - else() - set(DOWNLOAD_ONLY ON) - endif() - - AddPackage( - NAME OpenSSL-windows-amd64 - REPO crueter/OpenSSL-CI - TAG v${SSL_VERSION} - VERSION ${SSL_VERSION} - ARTIFACT ${ARTIFACT} - - KEY ${KEY} - HASH_SUFFIX sha512sum - BUNDLED_PACKAGE ON - DOWNLOAD_ONLY ${DOWNLOAD_ONLY} + if (YUZU_USE_BUNDLED_OPENSSL) + AddCIPackage( + PACKAGE OpenSSL + NAME openssl + REPO crueter-ci/OpenSSL + VERSION 3.5.2 + MIN_VERSION 1.1.1 + FORCE_DOWNLOAD ${FORCE_DOWNLOAD_OPENSSL} ) - - if (NOT DOWNLOAD_ONLY) - set(OPENSSL_DIR ${OpenSSL-windows-amd64_SOURCE_DIR}) - endif() - message("OPENSSL ${DOWNLOAD_ONLY} ${OPENSSL_DIR}") - endif() - if ((MSVC AND ARCHITECTURE_arm64) OR FORCE_DOWNLOAD_OPENSSL) - set(ARTIFACT openssl-windows-arm64-${SSL_VERSION}.tar.zst) - set(KEY windows-arm64) - - if (MSVC AND ARCHITECTURE_arm64) - set(DOWNLOAD_ONLY OFF) - set(BUILD_SHARED_LIBS OFF) - else() - set(DOWNLOAD_ONLY ON) - endif() - - AddPackage( - NAME OpenSSL-windows-arm64 - REPO crueter/OpenSSL-CI - TAG v${SSL_VERSION} - VERSION ${SSL_VERSION} - ARTIFACT ${ARTIFACT} - - KEY ${KEY} - HASH_SUFFIX sha512sum - BUNDLED_PACKAGE ON - DOWNLOAD_ONLY ${DOWNLOAD_ONLY} - ) - - if (NOT DOWNLOAD_ONLY) - set(OPENSSL_DIR ${OpenSSL-windows-arm64_SOURCE_DIR}) - endif() - endif() - - if (ANDROID OR FORCE_DOWNLOAD_OPENSSL) - if (ANDROID) - set(DOWNLOAD_ONLY OFF) - set(BUILD_SHARED_LIBS OFF) - else() - set(DOWNLOAD_ONLY ON) - endif() - - AddPackage( - NAME OpenSSL-android - REPO crueter/OpenSSL-CI - TAG v${SSL_VERSION} - VERSION ${SSL_VERSION} - ARTIFACT openssl-android-${SSL_VERSION}.tar.zst - - KEY android - HASH_SUFFIX sha512sum - BUNDLED_PACKAGE ON - DOWNLOAD_ONLY ${DOWNLOAD_ONLY} - ) - - if (NOT DOWNLOAD_ONLY) - set(OPENSSL_DIR ${OpenSSL-android_SOURCE_DIR}) - endif() - endif() - - if(PLATFORM_SUN OR FORCE_DOWNLOAD_OPENSSL) - if (PLATFORM_SUN) - set(DOWNLOAD_ONLY OFF) - set(BUILD_SHARED_LIBS OFF) - else() - set(DOWNLOAD_ONLY ON) - endif() - - AddPackage( - NAME OpenSSL-solaris - REPO crueter/OpenSSL-CI - TAG v${SSL_VERSION} - VERSION ${SSL_VERSION} - ARTIFACT openssl-solaris-${SSL_VERSION}.tar.zst - - KEY solaris - HASH_SUFFIX sha512sum - BUNDLED_PACKAGE ON - DOWNLOAD_ONLY ${DOWNLOAD_ONLY} - ) - - if (NOT DOWNLOAD_ONLY) - set(OPENSSL_DIR ${OpenSSL-solaris_SOURCE_DIR}) - endif() - endif() - - if(PLATFORM_FREEBSD OR FORCE_DOWNLOAD_OPENSSL) - if (PLATFORM_FREEBSD) - set(DOWNLOAD_ONLY OFF) - set(BUILD_SHARED_LIBS OFF) - else() - set(DOWNLOAD_ONLY ON) - endif() - - AddPackage( - NAME OpenSSL-freebsd - REPO crueter/OpenSSL-CI - TAG v${SSL_VERSION} - VERSION ${SSL_VERSION} - ARTIFACT openssl-freebsd-${SSL_VERSION}.tar.zst - - KEY freebsd - HASH_SUFFIX sha512sum - BUNDLED_PACKAGE ON - DOWNLOAD_ONLY ${DOWNLOAD_ONLY} - ) - - if (NOT DOWNLOAD_ONLY) - set(OPENSSL_DIR ${OpenSSL-freebsd_SOURCE_DIR}) - endif() - endif() - - if(PLATFORM_LINUX OR FORCE_DOWNLOAD_OPENSSL) - if (PLATFORM_LINUX) - set(DOWNLOAD_ONLY OFF) - set(BUILD_SHARED_LIBS OFF) - else() - set(DOWNLOAD_ONLY ON) - endif() - - AddPackage( - NAME OpenSSL-linux - REPO crueter/OpenSSL-CI - TAG v${SSL_VERSION} - VERSION ${SSL_VERSION} - ARTIFACT openssl-linux-${SSL_VERSION}.tar.zst - - KEY linux - HASH_SUFFIX sha512sum - BUNDLED_PACKAGE ON - DOWNLOAD_ONLY ${DOWNLOAD_ONLY} - ) - - if (NOT DOWNLOAD_ONLY) - set(OPENSSL_DIR ${OpenSSL-linux_SOURCE_DIR}) - endif() - endif() - - if (DEFINED OPENSSL_DIR) - include(${OPENSSL_DIR}/openssl.cmake) - - # Overrides find package - CPMAddPackage( - NAME OpenSSL - SOURCE_DIR ${OPENSSL_DIR} - ) - else() - find_package(OpenSSL 1.1.1 REQUIRED) - endif() + find_package(OpenSSL 1.1.1 REQUIRED) endif() # boost @@ -589,6 +403,7 @@ if (YUZU_USE_CPM) GIT_VERSION 1.88.0 VERSION 1.57 + EXCLUDE_FROM_ALL ON ) # really annoying thing where boost::headers doesn't work with cpm @@ -619,6 +434,7 @@ if (YUZU_USE_CPM) VERSION 8 OPTIONS "FMT_INSTALL OFF" + EXCLUDE_FROM_ALL ON ) # lz4 @@ -628,6 +444,7 @@ if (YUZU_USE_CPM) SHA ebb370ca83 HASH 43600e87b35256005c0f2498fa56a77de6783937ba4cfce38c099f27c03188d097863e8a50c5779ca0a7c63c29c4f7ed0ae526ec798c1fd2e3736861b62e0a37 SOURCE_SUBDIR build/cmake + EXCLUDE_FROM_ALL ON ) if (lz4_ADDED) @@ -641,6 +458,7 @@ if (YUZU_USE_CPM) SHA 55f93686c0 HASH b739749b066800e21154506ea150d2c5cbce8a45344177f46f884547a1399d26753166fd0df8135269ce28cf223552b1b65cd625b88c844d54753f2434900486 VERSION 3.8 + EXCLUDE_FROM_ALL ON ) # zlib @@ -681,6 +499,7 @@ if (YUZU_USE_CPM) SHA 644821ce28 HASH f8795f98acf2c02c0db8e734cc866d5caebab4b4a306e93598b97cb3c0c728dafe8283dce27ffe8d42460e5ae7302f3f32e7e274a7f991b73511ac88eef21b1f VERSION 3.0.1 + EXCLUDE_FROM_ALL ON ) endif() @@ -692,6 +511,7 @@ if (YUZU_USE_CPM) VERSION 1.3 HASH 3de1beb4fa3d6b1e03eda8dd1e7580694f854af3ed3975dcdabfdcdf76b97f322b9734d35ea7f185855bb490d957842b938b26da4dd2dfded509390f8d2794dd FIND_PACKAGE_ARGUMENTS "MODULE" + EXCLUDE_FROM_ALL ON ) if (enet_ADDED) @@ -711,6 +531,7 @@ if (YUZU_USE_CPM) "OPUS_BUILD_PROGRAMS OFF" "OPUS_INSTALL_PKG_CONFIG_MODULE OFF" "OPUS_INSTALL_CMAKE_CONFIG_MODULE OFF" + EXCLUDE_FROM_ALL ON ) if(ENABLE_CUBEB) @@ -725,6 +546,7 @@ if (YUZU_USE_CPM) "BUILD_TESTS OFF" "BUILD_TOOLS OFF" "BUNDLE_SPEEX ON" + EXCLUDE_FROM_ALL ON ) if (cubeb_ADDED) @@ -786,6 +608,7 @@ if(NOT TARGET Boost::headers) SHA 0456900fad HASH 50cd75dcdfc5f082225cdace058f47b4fb114a47585f7aee1d22236a910a80b667186254c214fa2fcebac67ae6d37ba4b6e695e1faea8affd6fd42a03cf996e3 BUNDLED_PACKAGE ON + EXCLUDE_FROM_ALL ON ) endif() @@ -823,8 +646,8 @@ AddPackage( REPO brofield/simpleini SHA 09c21bda1d HASH 99779ca9b6e040d36558cadf484f9ffdab5b47bcc8fc72e4d33639d1d60c0ceb4410d335ba445d72a4324e455167fd6769d99b459943aa135bec085dff2d4b7c - EXCLUDE_FROM_ALL ON FIND_PACKAGE_ARGUMENTS "MODULE" + EXCLUDE_FROM_ALL ON ) # TODO(crueter): Work around this @@ -834,33 +657,66 @@ if (NOT YUZU_USE_EXTERNAL_VULKAN_SPIRV_TOOLS) endif() # find SDL2 exports a bunch of variables that are needed, so its easier to do this outside of the YUZU_find_package -# TODO(crueter): combine this all with CPM. if (ENABLE_SDL2) - if (YUZU_USE_BUNDLED_SDL2) - # Detect toolchain and platform - if ((MSVC_VERSION GREATER_EQUAL 1920) AND ARCHITECTURE_x86_64) - set(SDL2_VER "SDL2-2.32.8") - else() - message(FATAL_ERROR "No bundled SDL2 binaries for your toolchain. Disable YUZU_USE_BUNDLED_SDL2 and provide your own.") - endif() - - if (DEFINED SDL2_VER) - download_bundled_external("sdl2/" ${SDL2_VER} "sdl2-bundled" SDL2_PREFIX 2.32.8) - endif() - - set(SDL2_FOUND YES) - set(SDL2_INCLUDE_DIR "${SDL2_PREFIX}/include" CACHE PATH "Path to SDL2 headers") - set(SDL2_LIBRARY "${SDL2_PREFIX}/lib/x64/SDL2.lib" CACHE PATH "Path to SDL2 library") - set(SDL2_DLL_DIR "${SDL2_PREFIX}/lib/x64/" CACHE PATH "Path to SDL2.dll") - - add_library(SDL2::SDL2 INTERFACE IMPORTED) - target_link_libraries(SDL2::SDL2 INTERFACE "${SDL2_LIBRARY}") - target_include_directories(SDL2::SDL2 INTERFACE "${SDL2_INCLUDE_DIR}") - elseif (YUZU_USE_EXTERNAL_SDL2) + # this was hard to get right, but ultimately I decided to make it so that FORCE_DOWNLOAD_SDL2 also downloads the + # external one. Really silly behavior imo but in the interest of getting something out there I'm leaving it for now + if (YUZU_USE_EXTERNAL_SDL2 OR FORCE_DOWNLOAD_SDL2) message(STATUS "Using SDL2 from externals.") - else() - find_package(SDL2 2.26.4 REQUIRED) + if (NOT WIN32) + # Yuzu itself needs: Atomic Audio Events Joystick Haptic Sensor Threads Timers + # Since 2.0.18 Atomic+Threads required for HIDAPI/libusb (see https://github.com/libsdl-org/SDL/issues/5095) + # Yuzu-cmd also needs: Video (depends on Loadso/Dlopen) + # CPUinfo also required for SDL Audio, at least until 2.28.0 (see https://github.com/libsdl-org/SDL/issues/7809) + set(SDL_UNUSED_SUBSYSTEMS + File Filesystem + Locale Power Render) + foreach(_SUB ${SDL_UNUSED_SUBSYSTEMS}) + string(TOUPPER ${_SUB} _OPT) + set(SDL_${_OPT} OFF) + endforeach() + + set(HIDAPI ON) + endif() + + if (APPLE) + set(SDL_FILE ON) + endif() + + if ("${YUZU_SYSTEM_PROFILE}" STREQUAL "steamdeck") + set(SDL_HASH cc016b0046) + set(SDL_PIPEWIRE OFF) # build errors out with this on + set(SDL_SHA512SUM 34d5ef58da6a4f9efa6689c82f67badcbd741f5a4f562a9c2c30828fa839830fb07681c5dc6a7851520e261c8405a416ac0a2c2513b51984fb3b4fa4dcb3e20b) + else() + set(SDL_HASH 54772f345a) + set(SDL_SHA512SUM 2a68a0e01c390043aa9d9df63d8a20a52076c88bb460ac4e0f33194ca7d9bc8fadbbcc04e7506872ac4b6354a73fbc267c036f82200da59465789b87c7d9e3a4) + endif() + + AddPackage( + NAME SDL2 + REPO "libsdl-org/SDL" + SHA ${SDL_HASH} + HASH ${SDL_SHA512SUM} + KEY ${YUZU_SYSTEM_PROFILE} + BUNDLED_PACKAGE ON + EXCLUDE_FROM_ALL ON + ) endif() + + if (YUZU_USE_BUNDLED_SDL2) + message(STATUS "Using bundled SDL2") + AddCIPackage( + PACKAGE SDL2 + NAME SDL2 + REPO crueter-ci/SDL2 + VERSION 2.32.8 + MIN_VERSION 2.26.4 + CMAKE_FILENAME sdl2 + FORCE_DOWNLOAD ${FORCE_DOWNLOAD_SDL2} + TARGET "SDL2::SDL2" + ) + endif() + + find_package(SDL2 2.26.4 REQUIRED) endif() # List of all FFmpeg components required @@ -903,7 +759,7 @@ if (ENABLE_WEB_SERVICE OR ENABLE_QT_UPDATE_CHECKER) find_package(cpp-jwt) endif() -if (NOT YUZU_USE_BUNDLED_SDL2) +if (ENABLE_SDL2) find_package(SDL2) endif() @@ -925,7 +781,7 @@ if (ENABLE_QT) endif() if (CMAKE_SYSTEM_NAME STREQUAL "Linux") - find_package(Qt6 REQUIRED COMPONENTS DBus GuiPrivate) + find_package(Qt6 REQUIRED COMPONENTS DBus OPTIONAL_COMPONENTS GuiPrivate) elseif (UNIX AND NOT APPLE) find_package(Qt6 REQUIRED COMPONENTS DBus Gui) endif() diff --git a/CMakeModules/CPMUtil.cmake b/CMakeModules/CPMUtil.cmake index 07393d6ccd..519e7e32a8 100644 --- a/CMakeModules/CPMUtil.cmake +++ b/CMakeModules/CPMUtil.cmake @@ -252,3 +252,171 @@ function(AddPackage) PARENT_SCOPE) endfunction() + +function(add_ci_package key) + set(ARTIFACT ${ARTIFACT_NAME}-${key}-${ARTIFACT_VERSION}.${ARTIFACT_EXT}) + + AddPackage( + NAME ${ARTIFACT_PACKAGE}-${key} + REPO ${ARTIFACT_REPO} + TAG v${ARTIFACT_VERSION} + VERSION ${ARTIFACT_VERSION} + ARTIFACT ${ARTIFACT} + + KEY ${key} + HASH_SUFFIX sha512sum + BUNDLED_PACKAGE ON + DOWNLOAD_ONLY ON + ) + + if (NOT ARTIFACT_FORCE_DOWNLOAD OR ARTIFACT_OVERRIDE) + set(ARTIFACT_DIR ${${ARTIFACT_PACKAGE}-${key}_SOURCE_DIR} PARENT_SCOPE) + endif() +endfunction() + +# TODO(crueter): doc +function(AddCIPackage) + set(oneValueArgs + VERSION + NAME + REPO + PACKAGE + EXTENSION + FORCE_DOWNLOAD + MIN_VERSION + DISABLED_PLATFORMS + CMAKE_FILENAME + TARGET + ) + + cmake_parse_arguments(PKG_ARGS "" "${oneValueArgs}" "" ${ARGN}) + + if(NOT DEFINED PKG_ARGS_VERSION) + message(FATAL_ERROR "[CPMUtil] VERSION is required") + endif() + if(NOT DEFINED PKG_ARGS_NAME) + message(FATAL_ERROR "[CPMUtil] NAME is required") + endif() + if(NOT DEFINED PKG_ARGS_REPO) + message(FATAL_ERROR "[CPMUtil] REPO is required") + endif() + if(NOT DEFINED PKG_ARGS_PACKAGE) + message(FATAL_ERROR "[CPMUtil] PACKAGE is required") + endif() + + if (NOT DEFINED PKG_ARGS_CMAKE_FILENAME) + set(ARTIFACT_CMAKE ${PKG_ARGS_NAME}) + else() + set(ARTIFACT_CMAKE ${PKG_ARGS_CMAKE_FILENAME}) + endif() + + if(NOT DEFINED PKG_ARGS_EXTENSION) + set(ARTIFACT_EXT "tar.zst") + else() + set(ARTIFACT_EXT ${PKG_ARGS_EXTENSION}) + endif() + + if(NOT DEFINED PKG_ARGS_FORCE_DOWNLOAD) + set(ARTIFACT_FORCE_DOWNLOAD OFF) + else() + set(ARTIFACT_FORCE_DOWNLOAD ${PKG_ARGS_FORCE_DOWNLOAD}) + endif() + + if (DEFINED PKG_ARGS_MIN_VERSION) + set(ARTIFACT_MIN_VERSION ${PKG_ARGS_MIN_VERSION}) + endif() + + if (DEFINED PKG_ARGS_DISABLED_PLATFORMS) + set(DISABLED_PLATFORMS ${PKG_ARGS_DISABLED_PLATFORMS}) + endif() + + # this is mildly annoying + set(ARTIFACT_VERSION ${PKG_ARGS_VERSION}) + set(ARTIFACT_NAME ${PKG_ARGS_NAME}) + set(ARTIFACT_REPO ${PKG_ARGS_REPO}) + set(ARTIFACT_PACKAGE ${PKG_ARGS_PACKAGE}) + + if ((MSVC AND ARCHITECTURE_x86_64) OR ARTIFACT_FORCE_DOWNLOAD AND NOT "windows-amd64" IN_LIST DISABLED_PLATFORMS) + # kinda hacky + if(MSVC AND ARCHITECTURE_x86_64) + set(ARTIFACT_OVERRIDE ON) + endif() + + add_ci_package(windows-amd64) + set(ARTIFACT_OVERRIDE OFF) + endif() + + if ((MSVC AND ARCHITECTURE_arm64) OR ARTIFACT_FORCE_DOWNLOAD AND NOT "windows-arm64" IN_LIST DISABLED_PLATFORMS) + if(MSVC AND ARCHITECTURE_arm64) + set(ARTIFACT_OVERRIDE ON) + endif() + + add_ci_package(windows-arm64) + set(ARTIFACT_OVERRIDE OFF) + endif() + + if (ANDROID OR ARTIFACT_FORCE_DOWNLOAD AND NOT "android" IN_LIST DISABLED_PLATFORMS) + if(ANDROID) + set(ARTIFACT_OVERRIDE ON) + endif() + + add_ci_package(android) + set(ARTIFACT_OVERRIDE OFF) + endif() + + if(PLATFORM_SUN OR ARTIFACT_FORCE_DOWNLOAD AND NOT "solaris" IN_LIST DISABLED_PLATFORMS) + if(PLATFORM_SUN) + set(ARTIFACT_OVERRIDE ON) + endif() + + add_ci_package(solaris) + set(ARTIFACT_OVERRIDE OFF) + endif() + + if(PLATFORM_FREEBSD OR ARTIFACT_FORCE_DOWNLOAD AND NOT "freebsd" IN_LIST DISABLED_PLATFORMS) + if(PLATFORM_FREEBSD) + set(ARTIFACT_OVERRIDE ON) + endif() + + add_ci_package(freebsd) + set(ARTIFACT_OVERRIDE OFF) + endif() + + if((PLATFORM_LINUX AND ARCHITECTURE_x86_64) OR ARTIFACT_FORCE_DOWNLOAD AND NOT "linux" IN_LIST DISABLED_PLATFORMS) + if(PLATFORM_LINUX AND ARCHITECTURE_x86_64) + set(ARTIFACT_OVERRIDE ON) + endif() + + add_ci_package(linux) + set(ARTIFACT_OVERRIDE OFF) + endif() + + if((PLATFORM_LINUX AND ARCHITECTURE_arm64) OR ARTIFACT_FORCE_DOWNLOAD AND NOT "linux-aarch64" IN_LIST DISABLED_PLATFORMS) + if(PLATFORM_LINUX AND ARCHITECTURE_arm64) + set(ARTIFACT_OVERRIDE ON) + endif() + + add_ci_package(linux-aarch64) + set(ARTIFACT_OVERRIDE OFF) + endif() + + if (DEFINED ARTIFACT_DIR) + if (NOT DEFINED PKG_ARGS_TARGET OR NOT TARGET "${PKG_ARGS_TARGET}") + include(${ARTIFACT_DIR}/${ARTIFACT_CMAKE}.cmake) + + # Overrides find package + CPMAddPackage( + NAME ${ARTIFACT_PACKAGE} + SOURCE_DIR ${ARTIFACT_DIR} + ) + + set_property(GLOBAL APPEND PROPERTY CPM_PACKAGE_NAMES ${ARTIFACT_NAME}) + set_property(GLOBAL APPEND PROPERTY CPM_PACKAGE_URLS "https://github.com/${ARTIFACT_REPO}") # TODO(crueter) other hosts? + set_property(GLOBAL APPEND PROPERTY CPM_PACKAGE_SHAS ${ARTIFACT_VERSION}) + + set(${ARTIFACT_PACKAGE}_ADDED TRUE PARENT_SCOPE) + endif() + else() + find_package(${ARTIFACT_PACKAGE} ${ARTIFACT_MIN_VERSION} REQUIRED) + endif() +endfunction() diff --git a/CMakeModules/DownloadExternals.cmake b/CMakeModules/DownloadExternals.cmake index 3651781f93..642d7d0df1 100644 --- a/CMakeModules/DownloadExternals.cmake +++ b/CMakeModules/DownloadExternals.cmake @@ -49,9 +49,6 @@ function(download_win_archives) download_bundled_external("ffmpeg/" ${FFmpeg_EXT_NAME} "ffmpeg-bundled" "" 7.1.1) - # TODO(crueter): separate handling for arm64 - set(SDL2_VER "SDL2-2.32.8") - download_bundled_external("sdl2/" ${SDL2_VER} "sdl2-bundled" "" 2.32.8) set(FORCE_WIN_ARCHIVES OFF) endfunction() diff --git a/externals/CMakeLists.txt b/externals/CMakeLists.txt index 71dd2962e7..64592a8855 100644 --- a/externals/CMakeLists.txt +++ b/externals/CMakeLists.txt @@ -32,7 +32,7 @@ endif() # Xbyak (also used by Dynarmic, so needs to be added first) if (ARCHITECTURE_x86 OR ARCHITECTURE_x86_64) - if ("${CMAKE_SYSTEM_NAME}" STREQUAL "SunOS") + if (PLATFORM_SUN) # Fix regset.h collisions set(XBYAK_HASH 51f507b0b3) set(XBYAK_SHA512SUM 4a29a3c2f97f7d5adf667a21a008be03c951fb6696b0d7ba27e7e4afa037bc76eb5e059bb84860e01baf741d4d3ac851b840cd54c99d038812fbe0f1fa6d38a4) @@ -94,49 +94,6 @@ if (ENABLE_LIBUSB AND NOT TARGET libusb::usb) add_subdirectory(libusb) endif() -# SDL2 -if (NOT YUZU_USE_BUNDLED_SDL2) - if (NOT WIN32) - # Yuzu itself needs: Atomic Audio Events Joystick Haptic Sensor Threads Timers - # Since 2.0.18 Atomic+Threads required for HIDAPI/libusb (see https://github.com/libsdl-org/SDL/issues/5095) - # Yuzu-cmd also needs: Video (depends on Loadso/Dlopen) - # CPUinfo also required for SDL Audio, at least until 2.28.0 (see https://github.com/libsdl-org/SDL/issues/7809) - set(SDL_UNUSED_SUBSYSTEMS - File Filesystem - Locale Power Render) - foreach(_SUB ${SDL_UNUSED_SUBSYSTEMS}) - string(TOUPPER ${_SUB} _OPT) - set(SDL_${_OPT} OFF) - endforeach() - - set(HIDAPI ON) - endif() - if (APPLE) - set(SDL_FILE ON) - endif() - - if ("${YUZU_SYSTEM_PROFILE}" STREQUAL "steamdeck") - set(SDL_HASH cc016b0046) - set(SDL_PIPEWIRE OFF) # build errors out with this on - set(SDL_SHA512SUM 34d5ef58da6a4f9efa6689c82f67badcbd741f5a4f562a9c2c30828fa839830fb07681c5dc6a7851520e261c8405a416ac0a2c2513b51984fb3b4fa4dcb3e20b) - elseif ("${CMAKE_SYSTEM_NAME}" STREQUAL "SunOS") - set(SDL_HASH d310b5679f) - set(SDL_SHA512SUM cf83e1357eefb8bdf1542850d66d8007d620e4050b5715dc83f4a921d36ce9ce47d0d13c5d85f2b0ff8318d2877eec2f63b931bd47417a81a538327af927da3e) - else() - set(SDL_HASH 2e4c12cd2c) - set(SDL_SHA512SUM d95af47f469a312876f8ab361074a1e7b8083db19935a102d9c6e5887ace6008e64475a8c54b00164b40cad86492bb1b2366084efdd0b2555e5fea6d9c5da80e) - endif() - - AddPackage( - NAME SDL2 - REPO "libsdl-org/SDL" - SHA ${SDL_HASH} - HASH ${SDL_SHA512SUM} - KEY ${YUZU_SYSTEM_PROFILE} - BUNDLED_PACKAGE ${YUZU_USE_EXTERNAL_SDL2} - ) -endif() - # Sirit # TODO(crueter): spirv-tools doesn't work w/ system set(SPIRV_WERROR OFF) diff --git a/src/core/CMakeLists.txt b/src/core/CMakeLists.txt index 5f9bfa2214..eab506f194 100644 --- a/src/core/CMakeLists.txt +++ b/src/core/CMakeLists.txt @@ -1251,11 +1251,7 @@ if(ENABLE_OPENSSL) find_package(OpenSSL REQUIRED) - if (OpenSSL_ADDED) - link_openssl(core) - else() - target_link_libraries(core PRIVATE OpenSSL::SSL) - endif() + target_link_libraries(core PRIVATE OpenSSL::SSL OpenSSL::Crypto) elseif (APPLE) target_sources(core PRIVATE hle/service/ssl/ssl_backend_securetransport.cpp) diff --git a/src/core/internal_network/network.cpp b/src/core/internal_network/network.cpp index 49179617a7..6a3c6e9c41 100644 --- a/src/core/internal_network/network.cpp +++ b/src/core/internal_network/network.cpp @@ -12,7 +12,7 @@ #ifdef _WIN32 #include #include -#elif defined(__unix__) +#elif defined(__unix__) || defined(__APPLE__) #include #include #include @@ -162,7 +162,7 @@ Errno TranslateNativeError(int e, CallType call_type = CallType::Other) { } } -#elif defined(__unix__) // ^ _WIN32 v __unix__ +#elif defined(__unix__) || defined(__APPLE__) // ^ _WIN32 v __unix__ using SOCKET = int; using WSAPOLLFD = pollfd; diff --git a/src/core/internal_network/network.h b/src/core/internal_network/network.h index 64f3f121df..5a3343efd9 100644 --- a/src/core/internal_network/network.h +++ b/src/core/internal_network/network.h @@ -104,7 +104,7 @@ constexpr IPv4Address TranslateIPv4(in_addr addr) { auto& bytes = addr.S_un.S_un_b; return IPv4Address{bytes.s_b1, bytes.s_b2, bytes.s_b3, bytes.s_b4}; } -#elif defined(__unix__) +#elif defined(__unix__) || defined(__APPLE__) constexpr IPv4Address TranslateIPv4(in_addr addr) { const u32 bytes = addr.s_addr; return IPv4Address{static_cast(bytes), static_cast(bytes >> 8), diff --git a/src/core/internal_network/sockets.h b/src/core/internal_network/sockets.h index 65ebb893ad..27468709fd 100644 --- a/src/core/internal_network/sockets.h +++ b/src/core/internal_network/sockets.h @@ -10,7 +10,7 @@ #if defined(_WIN32) // windows -#elif defined(__unix__) +#elif defined(__unix__) || defined(__APPLE__) // unix #else // haiku @@ -28,7 +28,7 @@ struct ProxyPacket; class SocketBase { public: -#ifdef __unix__ +#if defined(__unix__) || defined(__APPLE__) using SOCKET = int; static constexpr SOCKET INVALID_SOCKET = -1; static constexpr SOCKET SOCKET_ERROR = -1; diff --git a/src/web_service/CMakeLists.txt b/src/web_service/CMakeLists.txt index c1d5a84225..c1aaac9881 100644 --- a/src/web_service/CMakeLists.txt +++ b/src/web_service/CMakeLists.txt @@ -18,12 +18,8 @@ create_target_directory_groups(web_service) target_include_directories(web_service PUBLIC ${cpp-jwt_SOURCE_DIR}/include) target_link_libraries(web_service PRIVATE common network nlohmann_json::nlohmann_json httplib::httplib cpp-jwt::cpp-jwt) -if (OpenSSL_ADDED) - link_openssl(web_service) -else() - find_package(OpenSSL REQUIRED) - target_link_libraries(web_service PRIVATE OpenSSL::SSL) -endif() +find_package(OpenSSL REQUIRED) +target_link_libraries(web_service PRIVATE OpenSSL::SSL OpenSSL::Crypto) if (YUZU_USE_PRECOMPILED_HEADERS) target_precompile_headers(web_service PRIVATE precompiled_headers.h) diff --git a/src/yuzu/CMakeLists.txt b/src/yuzu/CMakeLists.txt index f7ec2985c7..f979a5c181 100644 --- a/src/yuzu/CMakeLists.txt +++ b/src/yuzu/CMakeLists.txt @@ -406,7 +406,11 @@ if (NOT WIN32) target_include_directories(yuzu PRIVATE ${Qt6Gui_PRIVATE_INCLUDE_DIRS}) endif() if (UNIX AND NOT APPLE) - target_link_libraries(yuzu PRIVATE Qt6::DBus Qt6::GuiPrivate) + target_link_libraries(yuzu PRIVATE Qt6::DBus) + + if (TARGET Qt6::GuiPrivate) + target_link_libraries(yuzu PRIVATE Qt6::GuiPrivate) + endif() endif() target_compile_definitions(yuzu PRIVATE From c228f9b74695ceb1e1e554762f3103b29c515405 Mon Sep 17 00:00:00 2001 From: PavelBARABANOV Date: Sat, 23 Aug 2025 19:53:16 +0200 Subject: [PATCH 06/39] updated the translation (#288) Reviewed-on: https://git.eden-emu.dev/eden-emu/eden/pulls/288 Reviewed-by: Shinmegumi Co-authored-by: PavelBARABANOV Co-committed-by: PavelBARABANOV --- .../app/src/main/res/values-ar/strings.xml | 44 ++++++++++++ .../app/src/main/res/values-ckb/strings.xml | 44 ++++++++++++ .../app/src/main/res/values-cs/strings.xml | 44 ++++++++++++ .../app/src/main/res/values-de/strings.xml | 44 ++++++++++++ .../app/src/main/res/values-es/strings.xml | 44 ++++++++++++ .../app/src/main/res/values-fa/strings.xml | 44 ++++++++++++ .../app/src/main/res/values-fr/strings.xml | 44 ++++++++++++ .../app/src/main/res/values-he/strings.xml | 44 ++++++++++++ .../app/src/main/res/values-hu/strings.xml | 44 ++++++++++++ .../app/src/main/res/values-id/strings.xml | 44 ++++++++++++ .../app/src/main/res/values-it/strings.xml | 44 ++++++++++++ .../app/src/main/res/values-ja/strings.xml | 44 ++++++++++++ .../app/src/main/res/values-ko/strings.xml | 44 ++++++++++++ .../app/src/main/res/values-nb/strings.xml | 44 ++++++++++++ .../app/src/main/res/values-pl/strings.xml | 44 ++++++++++++ .../src/main/res/values-pt-rBR/strings.xml | 44 ++++++++++++ .../src/main/res/values-pt-rPT/strings.xml | 44 ++++++++++++ .../app/src/main/res/values-ru/strings.xml | 46 ++++++++++++- .../app/src/main/res/values-sr/strings.xml | 44 ++++++++++++ .../app/src/main/res/values-uk/strings.xml | 67 +++++++++++++++++++ .../app/src/main/res/values-vi/strings.xml | 44 ++++++++++++ .../src/main/res/values-zh-rCN/strings.xml | 44 ++++++++++++ .../src/main/res/values-zh-rTW/strings.xml | 44 ++++++++++++ 23 files changed, 1036 insertions(+), 1 deletion(-) diff --git a/src/android/app/src/main/res/values-ar/strings.xml b/src/android/app/src/main/res/values-ar/strings.xml index a775e3c176..155d165f2d 100644 --- a/src/android/app/src/main/res/values-ar/strings.xml +++ b/src/android/app/src/main/res/values-ar/strings.xml @@ -679,6 +679,50 @@ اللعبة تتطلب برنامجاً ثابتاً نسخ وتثبيت البرنامج الثابت، أو اضغط "موافق" للمتابعة على أي حال.]]> + + جاري البحث عن اللعبة... + لم يتم العثور على اللعبة لمعرف العنوان: %1$s + فشل الإعدادات المخصصة + فشل تطبيق الإعدادات المخصصة لـ %1$s: %2$s + بدء التشغيل بالإعدادات الافتراضية + تم إلغاء البدء + غير قادر على تطبيق الإعدادات المطلوبة. قد يكون هذا بسبب отсут برامج تشغيل GPU أو مشاكل في التهيئة. + تم تطبيق الإعدادات المخصصة + جاري تشغيل %1$s... + فشل تهيئة اللعبة + هل تريد تشغيل %1$s بالإعدادات المخصصة؟ + هل تريد تشغيل %1$s؟ + تشغيل اللعبة + تشغيل + + + فشل كتابة ملف التهيئة + فشل تطبيق التهيئة + التهيئة موجودة بالفعل + توجد إعدادات مخصصة بالفعل لـ %1$s.\n\nهل تريد الكتابة فوق التهيئة الموجودة؟\n\nلا يمكن التراجع عن هذا الإجراء. + جاري التحقق من وجود تهيئة حالية... + تم إلغاء الكتابة فوق + جاري التحقق من وجود برنامج تشغيل مخصص: %1$s + برنامج التشغيل المخصص غير متاح لهذا الجهاز + الكتابة فوق + + + برنامج تشغيل GPU مفقود + برنامج التشغيل المخصص المحدد \"%s\" غير مثبت. هل تريد تنزيله وتثبيته الآن؟ + جاري تنزيل برنامج التشغيل... + تم تثبيت برنامج التشغيل بنجاح + فشل تثبيت برنامج التشغيل + فشل تثبيت برنامج تشغيل GPU: %s + برنامج التشغيل غير متاح + برنامج التشغيل المحدد غير متاح للتنزيل. + برنامج التشغيل المطلوب غير مثبت: %s + ملف برنامج تشغيل غير صالح: %s + لا يوجد اتصال بالشبكة. يرجى التحقق من اتصال الإنترنت والمحاولة مرة أخرى. + مطلوب برنامج تشغيل GPU + تكوين اللعبة يتطلب برنامج تشغيل GPU \"%s\" غير المثبت على جهازك.\n\nهل تريد تنزيله وتثبيته الآن? + تم إلغاء تنزيل برنامج التشغيل. لا يمكن تشغيل اللعبة بدون برنامج التشغيل المطلوب. + تنزيل + الخروج من المحاكاة إنهاء diff --git a/src/android/app/src/main/res/values-ckb/strings.xml b/src/android/app/src/main/res/values-ckb/strings.xml index 7c71e9e8fe..1845dbbade 100644 --- a/src/android/app/src/main/res/values-ckb/strings.xml +++ b/src/android/app/src/main/res/values-ckb/strings.xml @@ -656,6 +656,50 @@ یارییەکە فریموێر پێویستە فریموێر دامپ بکە و دابنێ, یان پەنجە بنێ سەر "باشە" بۆ بەردەوامبوون هەرچۆنێک بێت.]]> + + گەڕان بە دوای یارییە... + یاری نەدۆزرایەوە بۆ ناسنامەی ناونیشان: %1$s + ڕێکخستنە هەڵبژێردراوەکان سەرکەوتوو نەبوو + سەرکەوتوو نەبوو لە جێبەجێکردنی ڕێکخستنە هەڵبژێردراوەکان بۆ %1$s: %2$s + دەستپێکردن بە ڕێکخستنە بنەڕەتییەکان + دەستپێکردن هەڵوەشیندراوە + ناتوانێت ڕێکخستنە داواکراوەکان جێبەجێ بکات. لەوانەیە ئەمە بەهۆی ونبوونی ڕاهێنەری GPU یان کێشەکانی ڕێکخستنەوە بێت. + ڕێکخستنە هەڵبژێردراوەکان جێبەجێ کرا + دەستپێکردنی %1$s... + سەرکەوتوو نەبوو لە دەستپێکردنی یارییەکە + ئایا دەتەوێت %1$s بە ڕێکخستنە هەڵبژێردراوەکان دەستپێبکەیت؟ + ئایا دەتەوێت %1$s دەستپێبکەیت? + دەستپێکردنی یاری + دەستپێکردن + + + سەرکەوتوو نەبوو لە نووسینی پەڕگەی ڕێکخستن + سەرکەوتوو نەبوو لە جێبەجێکردنی ڕێکخستن + ڕێکخستن هەبووی تری هەیە + ڕێکخستنە هەڵبژێردراوەکان هەڵە بۆ %1$s.\n\nئایا دەتەوێت ڕێکخستنە هەبووەکە بسڕیتەوە؟\n\nناتوانیت ئەم کردارە بگەڕێنیتەوە. + پشکنین بۆ ڕێکخستنی ئێستا... + سڕینەوە هەڵوەشیندراوە + پشکنین بۆ ڕاهێنەری هەڵبژێردراو: %1$s + ڕاهێنەری هەڵبژێردراو بۆ ئەم ئامێرە بەردەست نییە + سڕینەوە + + + ڕاهێنەری GPU ونبووە + ڕاهێنەری هەڵبژێردراوی دیاریکراو \"%s\" دامەزراو نییە. ئایا دەتەوێت ئێستا دایببزێنیت و دامەزرێنیت? + داگرتنی ڕاهێنەر... + ڕاهێنەر بە سەرکەوتوویی دامەزرا + دامەزرانی ڕاهێنەر سەرکەوتوو نەبوو + سەرکەوتوو نەبوو لە دامەزراندنی ڕاهێنەری GPU: %s + ڕاهێنەر بەردەست نییە + ڕاهێنەری دیاریکراو بۆ داگرتن بەردەست نییە. + ڕاهێنەری پێویست دامەزراو نییە: %s + پەڕگەی ڕاهێنەری نادروست: %s + هیچ پەیوەندییەکی تۆڕ بەردەست نییە. تکایە پەیوەندیی ئینتەرنێتەکەت بپشکنە و دووبارە هەوڵبدە. + ڕاهێنەری GPU پێویستە + ڕێکخستنی یارییەکە پێویستی بە ڕاهێنەری GPU \"%s\" هەیە کە لەسەر ئامێرەکەت دامەزراو نییە.\n\nئایا دەتەوێت ئێستا دایببزێنیت و دامەزرێنیت? + داگرتنی ڕاهێنەر هەڵوەشیندراوە. ناتوانیت یارییەکە دەستپێبکەیت بەبێ ڕاهێنەری پێویست. + داگرتن + دەرچوون لە ئیمولەیشن تەواو diff --git a/src/android/app/src/main/res/values-cs/strings.xml b/src/android/app/src/main/res/values-cs/strings.xml index 18df8c8413..484ba1fc5f 100644 --- a/src/android/app/src/main/res/values-cs/strings.xml +++ b/src/android/app/src/main/res/values-cs/strings.xml @@ -636,6 +636,50 @@ Hra vyžaduje firmware převezměte a nainstalujte firmware, nebo stiskněte "OK" pro pokračování v každém případě.]]> + + Hledání hry... + Hra nebyla nalezena pro ID titulu: %1$s + Vlastní nastavení selhalo + Nepodařilo se použít vlastní nastavení pro %1$s: %2$s + Spustit s výchozím nastavením + Spuštění zrušeno + Nelze použít požadovaná nastavení. Důvodem může být chybějící ovladač GPU nebo problémy s konfigurací. + Vlastní nastavení použito + Spouštím %1$s... + Nepodařilo se inicializovat hru + Chcete spustit %1$s s vlastním nastavením? + Chcete spustit %1$s? + Spustit hru + Spustit + + + Nepodařilo se zapsat konfigurační soubor + Nepodařilo se použít konfiguraci + Konfigurace již existuje + Vlastní nastavení již existuje pro %1$s.\n\nChcete přepsat stávající konfiguraci?\n\nTuto akci nelze vrátit zpět. + Kontrola existující konfigurace... + Přepsání zrušeno + Kontrola vlastního ovladače: %1$s + Vlastní ovladač není pro toto zařízení k dispozici + Přepsat + + + Chybí ovladač GPU + Vybraný vlastní ovladač \"%s\" není nainstalován. Chcete jej nyní stáhnout и nainstalovat? + Stahování ovladače... + Ovladač byl úspěšně nainstalován + Instalace ovladače selhala + Nepodařilo se nainstalovat ovladač GPU: %s + Ovladač není k dispozici + Vybraný ovladač není k dispozici ke stažení. + Požadovaný ovladač není nainstalován: %s + Neplatný soubor ovladače: %s + Není dostupné síťové připojení. Zkontrolujte prosím připojení k internetu a zkuste to znovu. + Vyžadován ovladač GPU + Konfigurace hry vyžaduje ovladač GPU \"%s\", který není na vašem zařízení nainstalován.\n\nChcete jej nyní stáhnout a nainstalovat? + Stahování ovladače bylo zrušeno. Hru nelze spustit bez požadovaného ovladače. + Stáhnout + Ukončit emulaci Hotovo diff --git a/src/android/app/src/main/res/values-de/strings.xml b/src/android/app/src/main/res/values-de/strings.xml index fcd85018cc..821ba56399 100644 --- a/src/android/app/src/main/res/values-de/strings.xml +++ b/src/android/app/src/main/res/values-de/strings.xml @@ -712,6 +712,50 @@ Wirklich fortfahren? Spiel erfordert Firmware dumpen und installieren Sie Firmware, oder drücken Sie "OK", um trotzdem zu starten.]]> + + Suche nach Spiel... + Spiel nicht gefunden für Titel-ID: %1$s + Benutzerdefinierte Einstellungen fehlgeschlagen + Fehler beim Anwenden der benutzerdefinierten Einstellungen für %1$s: %2$s + Mit Standardeinstellungen starten + Start abgebrochen + Die angeforderten Einstellungen konnten nicht angewendet werden. Dies kann an fehlenden GPU-Treibern oder Konfigurationsproblemen liegen. + Benutzerdefinierte Einstellungen übernommen + Starte %1$s... + Spielinitialisierung fehlgeschlagen + Möchten Sie %1$s mit benutzerdefinierten Einstellungen starten? + Möchten Sie %1$s starten? + Spiel starten + Starten + + + Konfigurationsdatei konnte nicht geschrieben werden + Konfiguration konnte nicht angewendet werden + Konfiguration existiert bereits + Benutzerdefinierte Einstellungen existieren bereits für %1$s.\n\nMöchten Sie die bestehende Konfiguration überschreiben?\n\nDiese Aktion kann nicht rückgängig gemacht werden. + Überprüfe auf vorhandene Konfiguration... + Überschreiben abgebrochen + Üoverprüfe benutzerdefinierten Treiber: %1$s + Benutzerdefinierter Treiber für dieses Gerät nicht verfügbar + Überschreiben + + + GPU-Treiber fehlt + Der ausgewählte benutzerdefinierte Treiber \"%s\" ist nicht installiert. Möchten Sie ihn jetzt herunterladen und installieren? + Treiber wird heruntergeladen... + Treiber erfolgreich installiert + Treiberinstallation fehlgeschlagen + Fehler beim Installieren des GPU-Treibers: %s + Treiber nicht verfügbar + Der ausgewählte Treiber ist nicht zum Download verfügbar. + Erforderlicher Treiber nicht installiert: %s + Ungültige Treiberdatei: %s + Keine Netzwerkverbindung verfügbar. Bitte überprüfen Sie Ihre Internetverbindung und versuchen Sie es erneut. + GPU-Treiber erforderlich + Die Spielkonfiguration erfordert den GPU-Treiber \"%s\", der auf Ihrem Gerät nicht installiert ist.\n\nMöchten Sie ihn jetzt herunterladen и installieren? + Treiberdownload abgebrochen. Das Spiel kann ohne den erforderlichen Treiber nicht gestartet werden. + Herunterladen + Emulation beenden Fertig diff --git a/src/android/app/src/main/res/values-es/strings.xml b/src/android/app/src/main/res/values-es/strings.xml index 8cd93efe73..9db08e1425 100644 --- a/src/android/app/src/main/res/values-es/strings.xml +++ b/src/android/app/src/main/res/values-es/strings.xml @@ -751,6 +751,50 @@ El juego requiere firmware vuelca e instala el firmware, o pulsa "Aceptar" para continuar de todos modos.]]> + + Buscando juego... + Juego no encontrado para el ID de título: %1$s + Configuración personalizada fallida + Error al aplicar la configuración personalizada para %1$s: %2$s + Iniciar con configuración predeterminada + Inicio cancelado + No se pueden aplicar los ajustes solicitados. Esto puede deberse a controladores GPU faltantes o problemas de configuración. + Configuración personalizada aplicada + Iniciando %1$s... + Error al inicializar el juego + ¿Quieres iniciar %1$s con configuración personalizada? + ¿Quieres iniciar %1$s? + Iniciar juego + Iniciar + + + Error al escribir el archivo de configuración + Error al aplicar la configuración + La configuración ya existe + Ya existe una configuración personalizada para %1$s.\n\n¿Quieres sobrescribir la configuración existente?\n\nEsta acción no se puede deshacer. + Comprobando la configuración existente... + Sobrescritura cancelada + Comprobando controlador personalizado: %1$s + Controlador personalizado no disponible para este dispositivo + Sobrescribir + + + Falta controlador de GPU + El controlador personalizado seleccionado \"%s\" no está instalado. ¿Quieres descargarlo e instalarlo ahora? + Descargando controlador... + Controlador instalado correctamente + Error en la instalación del controlador + Error al instalar el controlador de GPU: %s + Controlador no disponible + El controlador seleccionado no está disponible para descargar. + Controlador requerido no instalado: %s + Archivo de controlador no válido: %s + No hay conexión de red disponible. Por favor, compruebe su conexión a Internet e inténtelo de nuevo. + Se requiere controlador de GPU + La configuración del juego requiere el controlador de GPU \"%s\" que no está instalado en su dispositivo.\n\n¿Quieres descargarlo e instalarlo ahora? + Descarga del controlador cancelada. El juego no se puede iniciar sin el controlador requerido. + Descargar + Salir de la emulación Hecho diff --git a/src/android/app/src/main/res/values-fa/strings.xml b/src/android/app/src/main/res/values-fa/strings.xml index 5bf8a634d1..91fa4bd5c2 100644 --- a/src/android/app/src/main/res/values-fa/strings.xml +++ b/src/android/app/src/main/res/values-fa/strings.xml @@ -750,6 +750,50 @@ بازی نیاز به فیرمور دارد فیرمور را دامپ و نصب کنید یا برای ادامه کار "تایید" را فشار دهید.]]> + + در حال جستجوی بازی... + بازی برای شناسه عنوان یافت نشد: %1$s + تنظیمات سفارشی ناموفق بود + اعمال تنظیمات سفارشی برای %1$s ناموفق بود: %2$s + اجرا با تنظیمات پیش‌فرض + اجرا لغو شد + قادر به اعمال تنظیمات درخواستی نیست. این ممکن است به دلیل عدم وجود درایورهای GPU یا مشکلات پیکربندی باشد. + تنظیمات سفارشی اعمال شد + در حال اجرای %1$s... + مشکل در مقداردهی اولیه بازی + آیا می‌خواهید %1$s را با تنظیمات سفارشی اجرا کنید؟ + آیا می‌خواهید %1$s را اجرا کنید؟ + اجرای بازی + اجرا + + + نوشتن فایل پیکربندی ناموفق بود + اعمال پیکربندی ناموفق بود + پیکربندی از قبل وجود دارد + تنظیمات سفارشی از قبل برای %1$s وجود دارد.\n\nآیا می‌خواهید پیکربندی موجود را بازنویسی کنید؟\n\nاین عمل قابل بازگشت نیست. + در حال بررسی پیکربندی موجود... + بازنویسی لغو شد + در حال بررسی درایور سفارشی: %1$s + درایور سفارشی برای این دستگاه در دسترس نیست + بازنویسی + + + درایور GPU یافت نشد + درایور سفارشی انتخاب شده \"%s\" نصب نشده است. آیا می‌خواهید هم اکنون آن را دانلود و نصب کنید؟ + در حال دانلود درایور... + درایور با موفقیت نصب شد + نصب درایور ناموفق بود + نصب درایور GPU ناموفق بود: %s + درایور در دسترس نیست + درایور انتخاب شده برای دانلود در دسترس نیست. + درایور مورد نیاز نصب نشده است: %s + فایل درایور نامعتبر: %s + اتصال شبکه در دسترس نیست. لطفاً اتصال اینترنت خود را بررسی کرده و مجدداً تلاش کنید. + درایور GPU مورد نیاز است + پیکربندی بازی به درایور GPU \"%s\" نیاز دارد که روی دستگاه شما نصب نیست.\n\nآیا می‌خواهید هم اکنون آن را دانلود و نصب کنید? + دانلود درایور لغو شد. بازی بدون درایور مورد نیاز قابل اجرا نیست. + دانلود + خروج از شبیه‌سازی انجام شد diff --git a/src/android/app/src/main/res/values-fr/strings.xml b/src/android/app/src/main/res/values-fr/strings.xml index 9a74bb61bb..a7139ddbf6 100644 --- a/src/android/app/src/main/res/values-fr/strings.xml +++ b/src/android/app/src/main/res/values-fr/strings.xml @@ -799,6 +799,50 @@ Jeu nécessite un firmware dumper et installer le firmware ou appuyez sur "OK" pour continuer quand même.]]> + + Recherche du jeu... + Jeu non trouvé pour l\'ID de titre : %1$s + Échec des paramètres personnalisés + Échec de l\'application des paramètres personnalisés pour %1$s : %2$s + Lancer avec les paramètres par défaut + Lancement annulé + Impossible d\'appliquer les paramètres demandés. Cela peut être dû à des pilotes GPU manquants ou à des problèmes de configuration. + Paramètres personnalisés appliqués + Lancement de %1$s... + Échec de l\'initialisation du jeu + Voulez-vous lancer %1$s avec des paramètres personnalisés ? + Voulez-vous lancer %1$s ? + Lancer le jeu + Lancer + + + Échec de l\'écriture du fichier de configuration + Échec de l\'application de la configuration + Configuration déjà existante + Des paramètres personnalisés existent déjà pour %1$s.\n\nVoulez-vous écraser la configuration existante ?\n\nCette action ne peut pas être annulée. + Vérification de la configuration existante... + Écrasement annulé + Vérification du pilote personnalisé : %1$s + Pilote personnalisé non disponible pour cet appareil + Écraser + + + Pilote GPU manquant + Le pilote personnalisé sélectionné \"%s\" n\'est pas installé. Voulez-vous le télécharger et l\'installer maintenant ? + Téléchargement du pilote... + Pilote installé avec succès + Échec de l\'installation du pilote + Échec de l\'installation du pilote GPU : %s + Pilote non disponible + Le pilote sélectionné n\'est pas disponible au téléchargement. + Pilote requis non installé : %s + Fichier de pilote invalide : %s + Aucune connexion réseau disponible. Veuillez vérifier votre connexion Internet et réessayer. + Pilote GPU requis + La configuration du jeu nécessite le pilote GPU \"%s\" qui n\'est pas installé sur votre appareil.\n\nVoulez-vous le télécharger et l\'installer maintenant ? + Téléchargement du pilote annulé. Le jeu ne peut pas être lancé sans le pilote requis. + Télécharger + Quitter l\'émulation Terminé diff --git a/src/android/app/src/main/res/values-he/strings.xml b/src/android/app/src/main/res/values-he/strings.xml index 5413c0797b..63aaee043e 100644 --- a/src/android/app/src/main/res/values-he/strings.xml +++ b/src/android/app/src/main/res/values-he/strings.xml @@ -685,6 +685,50 @@ המשחק דורש קושחה שמור והתקן קושחה או לחץ "אישור" כדי להמשיך בכל מקרה.]]> + + מחפש משחק... + משחק לא נמצא למזהה כותרת: %1$s + הגדרות מותאמות אישית נכשלו + נכשל בהחלת הגדרות מותאמות אישית עבור %1$s: %2$s + הפעל עם הגדרות ברירת מחדל + ההפעלה בוטלה + לא ניתן להחיל את ההגדרות המבוקשות. זה עשוי להיות עקב חסרון מנהלי התקן של GPU או בעיות תצורה. + הגדרות מותאמות אישית הוחלו + מפעיל את %1$s... + נכשל באתחול המשחק + האם ברצונך להפעיל את %1$s עם הגדרות מותאמות אישית? + האם ברצונך להפעיל את %1$s? + הפעל משחק + הפעל + + + נכשל בכתיבת קובץ התצורה + נכשל בהחלת התצורה + תצורה כבר קיימת + הגדרות מותאמות אישית כבר קיימות עבור %1$s.\n\nהאם ברצונך לדרוס את התצורה הקיימת?\n\nפעולה זו לא ניתנת לביטול. + בודק אם קיימת תצורה... + דריסה בוטלה + בודק מנהל התקן מותאם אישית: %1$s + מנהל התקן מותאם אישית לא זמין למכשיר זה + דרוס + + + מנהל התקן GPU חסר + מנהל ההתקן המותאם אישית הנבחר \"%s\" אינו מותקן. האם ברצונך להוריד ולהתקין אותו כעת? + מוריד מנהל התקן... + מנהל ההתקן הותקן בהצלחה + התקנת מנהל ההתקן נכשלה + נכשלה התקנת מנהל ההתקן של GPU: %s + מנהל התקן לא זמין + מנהל ההתקן הנבחר אינו זמין להורדה. + מנהל התקן נדרש לא מותקן: %s + קובץ מנהל התקן לא חוקי: %s + אין חיבור אינטרנט זמין. אנא בדוק את חיבור האינטרנט שלך ונסה שוב. + נדרש מנהל התקן GPU + תצורת המשחק דורשת מנהל התקן GPU \"%s\" אשר אינו מותקן במכשירך.\n\nהאם ברצונך להוריד ולהתקין אותו כעת? + הורדת מנהל ההתקן בוטלה. לא ניתן להפעיל את המשחק ללא מנהל ההתקן הנדרש. + הורד + צא מהאמולציה סיום diff --git a/src/android/app/src/main/res/values-hu/strings.xml b/src/android/app/src/main/res/values-hu/strings.xml index 73ccbd03e0..15dd00997b 100644 --- a/src/android/app/src/main/res/values-hu/strings.xml +++ b/src/android/app/src/main/res/values-hu/strings.xml @@ -789,6 +789,50 @@ A játék firmware-t igényel dumpolja és telepítse a firmware-t, vagy nyomja meg az "OK" gombot a folytatáshoz.]]> + + Játék keresése... + A játék nem található a következő címazonosítóhoz: %1$s + Egyéni beállítások sikertelenek + Nem sikerült alkalmazni az egyéni beállításokat ehhez: %1$s: %2$s + Indítás alapértelmezett beállításokkal + Indítás megszakítva + Nem sikerült alkalmazni a kért beállításokat. Ennek oka hiányzó GPU illesztőprogramok vagy konfigurációs problémák lehetnek. + Egyéni beállítások alkalmazva + %1$s indítása... + A játék inicializálása sikertelen + Szeretné elindítani a(z) %1$s-t egyéni beállításokkal? + Szeretné elindítani a(z) %1$s-t? + Játék indítása + Indítás + + + A konfigurációs fájl írása sikertelen + A konfiguráció alkalmazása sikertelen + A konfiguráció már létezik + Már léteznek egyéni beállítások a(z) %1$s számára.\n\nSzeretné felülírni a meglévő konfigurációt?\n\nEzt a műveletet nem lehet visszavonni. + Létező konfiguráció keresése... + A felülírás megszakítva + Egyéni illesztőprogram ellenőrzése: %1$s + Egyéni illesztőprogram nem elérhető ehhez az eszközhöz + Felülírás + + + GPU illesztőprogram hiányzik + A kiválasztott egyéni illesztőprogram \"%s\" nincs telepítve. Szeretné most letölteni és telepíteni? + Illesztőprogram letöltése... + Az illesztőprogram sikeresen telepítve + Az illesztőprogram telepítése sikertelen + Nem sikerült telepíteni a GPU illesztőprogramot: %s + Az illesztőprogram nem elérhető + A kiválasztott illesztőprogram nem érhető el letöltésre. + A szükséges illesztőprogram nincs telepítve: %s + Érvénytelen illesztőprogramfájl: %s + Nincs hálózati kapcsolat. Kérjük, ellenőrizze az internetkapcsolatát, és próbálja újra. + GPU illesztőprogram szükséges + A játék konfigurációja \"%s\" GPU illesztőprogramot igényel, amely nincs telepítve az eszközén.\n\nSzeretné most letölteni és telepíteni? + Az illesztőprogram letöltése megszakítva. A játék nem indítható el a szükséges illesztőprogram nélkül. + Letöltés + Emuláció bezárása Kész diff --git a/src/android/app/src/main/res/values-id/strings.xml b/src/android/app/src/main/res/values-id/strings.xml index 44d43b4578..7daa4a8e94 100644 --- a/src/android/app/src/main/res/values-id/strings.xml +++ b/src/android/app/src/main/res/values-id/strings.xml @@ -743,6 +743,50 @@ Game memerlukan firmware dump dan instal firmware, atau tekan "OK" untuk melanjutkan.]]> + + Mencari game... + Game tidak ditemukan untuk ID Judul: %1$s + Pengaturan Kustom Gagal + Gagal menerapkan pengaturan kustom untuk %1$s: %2$s + Luncurkan dengan Pengaturan Default + Peluncuran dibatalkan + Tidak dapat menerapkan pengaturan yang diminta. Ini mungkin karena driver GPU yang hilang atau masalah konfigurasi. + Pengaturan kustom diterapkan + Meluncurkan %1$s... + Gagal menginisialisasi game + Apakah Anda ingin meluncurkan %1$s dengan pengaturan kustom? + Apakah Anda ingin meluncurkan %1$s? + Luncurkan Game + Luncurkan + + + Gagal menulis file konfigurasi + Gagal menerapkan konfigurasi + Konfigurasi Sudah Ada + Pengaturan kustom sudah ada untuk %1$s.\n\nApakah Anda ingin menimpa konfigurasi yang ada?\n\nTindakan ini tidak dapat dibatalkan. + Memeriksa konfigurasi yang ada... + Penimpaan dibatalkan + Memeriksa driver kustom: %1$s + Driver kustom tidak tersedia untuk perangkat ini + Timpa + + + Driver GPU Hilang + Driver kustom yang dipilih \"%s\" tidak terinstal. Apakah Anda ingin mengunduh dan menginstalnya sekarang? + Mengunduh driver... + Driver berhasil diinstal + Instalasi Driver Gagal + Gagal menginstal driver GPU: %s + Driver Tidak Tersedia + Driver yang dipilih tidak tersedia untuk diunduh. + Driver yang diperlukan tidak terinstal: %s + File driver tidak valid: %s + Tidak ada koneksi jaringan yang tersedia. Silakan periksa koneksi internet Anda dan coba lagi. + Driver GPU Diperlukan + Konfigurasi game memerlukan driver GPU \"%s\" yang tidak terinstal di perangkat Anda.\n\nApakah Anda ingin mengunduh dan menginstalnya sekarang? + Pengunduhan driver dibatalkan. Game tidak dapat diluncurkan tanpa driver yang diperlukan. + Unduh + Keluar Selesai diff --git a/src/android/app/src/main/res/values-it/strings.xml b/src/android/app/src/main/res/values-it/strings.xml index 4fc29eb597..66446eae34 100644 --- a/src/android/app/src/main/res/values-it/strings.xml +++ b/src/android/app/src/main/res/values-it/strings.xml @@ -716,6 +716,50 @@ Il gioco richiede firmware dumpa e installa il firmware, o premi "OK" per continuare comunque.]]> + + Ricerca del gioco in corso... + Gioco non trovato per l\'ID titolo: %1$s + Impostazioni personalizzate non riuscite + Impossibile applicare le impostazioni personalizzate per %1$s: %2$s + Avvia con impostazioni predefinite + Avvio annullato + Impossibile applicare le impostazioni richieste. Ciò potrebbe essere dovuto a driver GPU mancanti o problemi di configurazione. + Impostazioni personalizzate applicate + Avvio di %1$s... + Impossibile inizializzare il gioco + Vuoi avviare %1$s con impostazioni personalizzate? + Vuoi avviare %1$s? + Avvia gioco + Avvia + + + Impossibile scrivere il file di configurazione + Impossibile applicare la configurazione + Configurazione già esistente + Impostazioni personalizzate già esistenti per %1$s.\n\nVuoi sovrascrivere la configurazione esistente?\n\nQuesta azione non può essere annullata. + Verifica della configurazione esistente... + Sovrascrittura annullata + Verifica del driver personalizzato: %1$s + Driver personalizzato non disponibile per questo dispositivo + Sovrascrivi + + + Driver GPU mancante + Il driver personalizzato selezionato \"%s\" non è installato. Vuoi scaricarlo e installarlo ora? + Download del driver in corso... + Driver installato correttamente + Installazione del driver non riuscita + Impossibile installare il driver GPU: %s + Driver non disponibile + Il driver selezionato non è disponibile per il download. + Driver richiesto non installato: %s + File driver non valido: %s + Nessuna connessione di rete disponibile. Controlla la connessione Internet e riprova. + Driver GPU richiesto + La configurazione del gioco richiede il driver GPU \"%s\" che non è installato sul tuo dispositivo.\n\nVuoi scaricarlo e installarlo ora? + Download del driver annullato. Il gioco non può essere avviato senza il driver richiesto. + Scarica + Arresta emulazione Fatto diff --git a/src/android/app/src/main/res/values-ja/strings.xml b/src/android/app/src/main/res/values-ja/strings.xml index d65a32230a..2090aa5f74 100644 --- a/src/android/app/src/main/res/values-ja/strings.xml +++ b/src/android/app/src/main/res/values-ja/strings.xml @@ -675,6 +675,50 @@ ゲームにはファームウェアが必要です ファームウェアをダンプしてインストールするか、"OK"を押して続行してください。]]> + + ゲームを検索中... + タイトルID: %1$s のゲームが見つかりません + カスタム設定の失敗 + %1$s のカスタム設定の適用に失敗しました: %2$s + デフォルト設定で起動 + 起動がキャンセルされました + 要求された設定を適用できません。GPUドライバーの不足または設定の問題が原因である可能性があります。 + カスタム設定が適用されました + %1$s を起動中... + ゲームの初期化に失敗しました + %1$s をカスタム設定で起動しますか? + %1$s を起動しますか? + ゲームを起動 + 起動 + + + 設定ファイルの書き込みに失敗しました + 設定の適用に失敗しました + 設定が既に存在します + %1$s のカスタム設定は既に存在します。\n\n既存の設定を上書きしますか?\n\nこの操作は元に戻せません。 + 既存の設定を確認中... + 上書きがキャンセルされました + カスタムドライバーを確認中: %1$s + このデバイスではカスタムドライバーは利用できません + 上書き + + + GPUドライバーが見つかりません + 選択したカスタムドライバー \"%s\" がインストールされていません。今すぐダウンロードしてインストールしますか? + ドライバーをダウンロード中... + ドライバーが正常にインストールされました + ドライバーのインストールに失敗しました + GPUドライバーのインストールに失敗しました: %s + ドライバーが利用できません + 選択したドライバーはダウンロードできません。 + 必要なドライバーがインストールされていません: %s + 無効なドライバーファイル: %s + ネットワーク接続が利用できません。インターネット接続を確認してからもう一度お試しください。 + GPUドライバーが必要です + ゲーム設定にはGPUドライバー \"%s\" が必要ですが、お使いのデバイスにインストールされていません。\n\n今すぐダウンロードしてインストールしますか? + ドライバーのダウンロードがキャンセルされました。必要なドライバーがないとゲームを起動できません。 + ダウンロード + 終了 完了 diff --git a/src/android/app/src/main/res/values-ko/strings.xml b/src/android/app/src/main/res/values-ko/strings.xml index 7871fa7427..d73dc53987 100644 --- a/src/android/app/src/main/res/values-ko/strings.xml +++ b/src/android/app/src/main/res/values-ko/strings.xml @@ -743,6 +743,50 @@ 게임에 펌웨어가 필요합니다 펌웨어를 덤프하여 설치하거나 "확인"을 눌러 계속 진행하세요.]]> + + 게임 검색 중... + 타이틀 ID에 대한 게임을 찾을 수 없음: %1$s + 사용자 지정 설정 실패 + %1$s에 대한 사용자 지정 설정 적용 실패: %2$s + 기본 설정으로 실행 + 실행 취소됨 + 요청한 설정을 적용할 수 없습니다. GPU 드라이버 누락 또는 구성 문제 때문일 수 있습니다. + 사용자 지정 설정이 적용됨 + %1$s 실행 중... + 게임 초기화 실패 + %1$s을(를) 사용자 지정 설정으로 실행하시겠습니까? + %1$s을(를) 실행하시겠습니까? + 게임 실행 + 실행 + + + 구성 파일 작성 실패 + 구성 적용 실패 + 구성이 이미 존재함 + %1$s에 대한 사용자 지정 설정이 이미 존재합니다.\n\n기존 구성을 덮어쓰시겠습니까?\n\n이 작업은 취소할 수 없습니다. + 기존 구성 확인 중... + 덮어쓰기 취소됨 + 사용자 지정 드라이버 확인 중: %1$s + 이 기기에서는 사용자 지정 드라이버를 사용할 수 없음 + 덮어쓰기 + + + GPU 드라이버 누락 + 선택한 사용자 지정 드라이버 \"%s\"이(가) 설치되지 않았습니다. 지금 다운로드하여 설치하시겠습니까? + 드라이버 다운로드 중... + 드라이버가 성공적으로 설치됨 + 드라이버 설치 실패 + GPU 드라이버 설치 실패: %s + 드라이버를 사용할 수 없음 + 선택한 드라이버를 다운로드할 수 없습니다. + 필요한 드라이버가 설치되지 않았습니다: %s + 잘못된 드라이버 파일: %s + 사용 가능한 네트워크 연결이 없습니다. 인터넷 연결을 확인하고 다시 시도하십시오. + GPU 드라이버 필요 + 게임 구성에 GPU 드라이버 \"%s\"이(가) 필요하지만 기기에 설치되어 있지 않습니다.\n\n지금 다운로드하여 설치하시겠습니까? + 드라이버 다운로드가 취소되었습니다. 필요한 드라이버 없이는 게임을 실행할 수 없습니다. + 다운로드 + 에뮬레이션 종료 완료 diff --git a/src/android/app/src/main/res/values-nb/strings.xml b/src/android/app/src/main/res/values-nb/strings.xml index 8717f212d1..61fa5792e5 100644 --- a/src/android/app/src/main/res/values-nb/strings.xml +++ b/src/android/app/src/main/res/values-nb/strings.xml @@ -666,6 +666,50 @@ Spillet krever fastvare dump og installer fastvare, eller trykk "OK" for å fortsette likevel.]]> + + Søker etter spill... + Spill ikke funnet for tittel-ID: %1$s + Egendefinerte innstillinger mislyktes + Kunne ikke bruke egendefinerte innstillinger for %1$s: %2$s + Start med standardinnstillinger + Start avbrutt + Kan ikke bruke de forespurte innstillingene. Dette kan skyldes manglende GPU-drivere eller konfigurasjonsproblemer. + Egendefinerte innstillinger brukt + Starter %1$s... + Kunne ikke initialisere spillet + Vil du starte %1$s med egendefinerte innstillinger? + Vil du starte %1$s? + Start spill + Start + + + Kunne ikke skrive konfigurasjonsfil + Kunne ikke bruke konfigurasjon + Konfigurasjon finnes allerede + Egendefinerte innstillinger finnes allerede for %1$s.\n\nVil du overskrive den eksisterende konfigurasjonen?\n\nDenne handlingen kan ikke angres. + Sjekker for eksisterende konfigurasjon... + Overskriving avbrutt + Sjekker for egendefinert driver: %1$s + Egendefinert driver ikke tilgjengelig for denne enheten + Overskriv + + + GPU-driver mangler + Den valgte egendefinerte driveren \"%s\" er ikke installert. Vil du laste ned og installere den nå? + Laster ned driver... + Driver installert vellykket + Driverinstallasjon mislyktes + Kunne ikke installere GPU-driveren: %s + Driver ikke tilgjengelig + Den valgte driveren er ikke tilgjengelig for nedlasting. + Påkrevd driver ikke installert: %s + Ugyldig driverfil: %s + Ingen nettverkstilkobling tilgjengelig. Vennligst sjekk internettilkoblingen din og prøv på nytt. + GPU-driver kreves + Spillkonfigurasjonen krever GPU-driver \"%s\" som ikke er installert på enheten din.\n\nVil du laste ned og installere den nå? + Driver-nedlasting avbrutt. Spillet kan ikke startes uten den påkrevde driveren. + Last ned + Avslutt emulering Ferdig diff --git a/src/android/app/src/main/res/values-pl/strings.xml b/src/android/app/src/main/res/values-pl/strings.xml index 0c0a3e9012..d640112fca 100644 --- a/src/android/app/src/main/res/values-pl/strings.xml +++ b/src/android/app/src/main/res/values-pl/strings.xml @@ -664,6 +664,50 @@ Gra wymaga oprogramowania sprzętowego zrzuć i zainstaluj oprogramowanie sprzętowe, lub naciśnij "OK", aby kontynuować mimo to.]]> + + Wyszukiwanie gry... + Nie znaleziono gry dla ID tytułu: %1$s + Niestandardowe ustawienia nie powiodły się + Nie udało się zastosować niestandardowych ustawień dla %1$s: %2$s + Uruchom z ustawieniami domyślnymi + Uruchamianie anulowane + Nie można zastosować żądanych ustawień. Może to być spowodowane brakującymi sterownikami GPU lub problemami z konfiguracją. + Zastosowano niestandardowe ustawienia + Uruchamianie %1$s... + Nie udało się zainicjować gry + Czy chcesz uruchomić %1$s z niestandardowymi ustawieniami? + Czy chcesz uruchomić %1$s? + Uruchom grę + Uruchom + + + Nie udało się zapisać pliku konfiguracyjnego + Nie udało się zastosować konfiguracji + Konfiguracja już istnieje + Niestandardowe ustawienia już istnieją dla %1$s.\n\nCzy chcesz nadpisać istniejącą konfigurację?\n\nTej czynności nie można cofnąć. + Sprawdzanie istniejącej konfiguracji... + Nadpisywanie anulowane + Sprawdzanie niestandardowego sterownika: %1$s + Niestandardowy sterownik niedostępny dla tego urządzenia + Nadpisz + + + Brak sterownika GPU + Wybrany niestandardowy sterownik \"%s\" nie jest zainstalowany. Czy chcesz go teraz pobrać i zainstalować? + Pobieranie sterownika... + Sterownik pomyślnie zainstalowany + Instalacja sterownika nie powiodła się + Nie udało się zainstalować sterownika GPU: %s + Sterownik niedostępny + Wybrany sterownik nie jest dostępny do pobrania. + Wymagany sterownik nie jest zainstalowany: %s + Nieprawidłowy plik sterownika: %s + Brak dostępnego połączenia sieciowego. Sprawdź swoje połączenie internetowe i spróbuj ponownie. + Wymagany sterownik GPU + Konfiguracja gry wymaga sterownika GPU \"%s\", który nie jest zainstalowany na Twoim urządzeniu.\n\nCzy chcesz go teraz pobrać i zainstalować? + Pobieranie sterownika anulowane. Gra nie może zostać uruchomiona bez wymaganego sterownika. + Pobierz + Zakończ emulację Gotowe diff --git a/src/android/app/src/main/res/values-pt-rBR/strings.xml b/src/android/app/src/main/res/values-pt-rBR/strings.xml index d9a143921d..d0ec24f453 100644 --- a/src/android/app/src/main/res/values-pt-rBR/strings.xml +++ b/src/android/app/src/main/res/values-pt-rBR/strings.xml @@ -800,6 +800,50 @@ uma tentativa de mapeamento automático O jogo requer firmware faça dump e instale o firmware, ou pressione "OK" para continuar mesmo assim.]]> + + Procurando jogo... + Jogo não encontrado para o ID do Título: %1$s + Configurações Personalizadas Falharam + Falha ao aplicar configurações personalizadas para %1$s: %2$s + Iniciar com Configurações Padrão + Inicialização cancelada + Não foi possível aplicar as configurações solicitadas. Isso pode ser devido a drivers de GPU ausentes ou problemas de configuração. + Configurações personalizadas aplicadas + Iniciando %1$s... + Falha ao inicializar o jogo + Deseja iniciar %1$s com configurações personalizadas? + Deseja iniciar %1$s? + Iniciar Jogo + Iniciar + + + Falha ao escrever arquivo de configuração + Falha ao aplicar configuração + Configuração Já Existe + Configurações personalizadas já existem para %1$s.\n\nDeseja sobrescrever a configuração existente?\n\nEsta ação não pode ser desfeita. + Verificando configuração existente... + Sobrescrita cancelada + Verificando driver personalizado: %1$s + Driver personalizado não disponível para este dispositivo + Sobrescrever + + + Driver de GPU Ausente + O driver personalizado selecionado \"%s\" não está instalado. Deseja baixar e instalá-lo agora? + Baixando driver... + Driver instalado com sucesso + Instalação do Driver Falhou + Falha ao instalar o driver da GPU: %s + Driver Não Disponível + O driver selecionado não está disponível para download. + Driver necessário não instalado: %s + Arquivo de driver inválido: %s + Nenhuma conexão de rede disponível. Verifique sua conexão com a internet e tente novamente. + Driver de GPU Necessário + A configuração do jogo requer o driver de GPU \"%s\" que não está instalado em seu dispositivo.\n\nDeseja baixar e instalá-lo agora? + Download do driver cancelado. O jogo não pode ser iniciado sem o driver necessário. + Baixar + Sair da emulação Feito diff --git a/src/android/app/src/main/res/values-pt-rPT/strings.xml b/src/android/app/src/main/res/values-pt-rPT/strings.xml index fd3787cb00..4e0fc4167a 100644 --- a/src/android/app/src/main/res/values-pt-rPT/strings.xml +++ b/src/android/app/src/main/res/values-pt-rPT/strings.xml @@ -800,6 +800,50 @@ uma tentativa de mapeamento automático O jogo requer firmware faça dump e instale o firmware, ou pressione "OK" para continuar mesmo assim.]]> + + A procurar jogo... + Jogo não encontrado para o ID do Título: %1$s + Definições Personalizadas Falharam + Falha ao aplicar definições personalizadas para %1$s: %2$s + Iniciar com Definições Predefinidas + Inicialização cancelada + Não foi possível aplicar as definições solicitadas. Isto pode ser devido a controladores de GPU em falta ou problemas de configuração. + Definições personalizadas aplicadas + A iniciar %1$s... + Falha ao inicializar o jogo + Deseja iniciar %1$s com definições personalizadas? + Deseja iniciar %1$s? + Iniciar Jogo + Iniciar + + + Falha ao escrever ficheiro de configuração + Falha ao aplicar configuração + Configuração Já Existe + Definições personalizadas já existem para %1$s.\n\nDeseja substituir a configuração existente?\n\nEsta ação não pode ser desfeita. + A verificar configuração existente... + Substituição cancelada + A verificar controlador personalizado: %1$s + Controlador personalizado não disponível para este dispositivo + Substituir + + + Controlador de GPU em Falta + O controlador personalizado selecionado \"%s\" não está instalado. Deseja transferir e instalá-lo agora? + A transferir controlador... + Controlador instalado com sucesso + Instalação do Controlador Falhou + Falha ao instalar o controlador da GPU: %s + Controlador Não Disponível + O controlador selecionado não está disponível para transferência. + Controlador necessário não instalado: %s + Ficheiro de controlador inválido: %s + Nenhuma ligação de rede disponível. Verifique a sua ligação à internet e tente novamente. + Controlador de GPU Necessário + A configuração do jogo requer o controlador de GPU \"%s\" que não está instalado no seu dispositivo.\n\nDeseja transferir e instalá-lo agora? + Transferência do controlador cancelada. O jogo não pode ser iniciado sem o controlador necessário. + Transferir + Parar emulação Feito diff --git a/src/android/app/src/main/res/values-ru/strings.xml b/src/android/app/src/main/res/values-ru/strings.xml index 787111cde4..658286152b 100644 --- a/src/android/app/src/main/res/values-ru/strings.xml +++ b/src/android/app/src/main/res/values-ru/strings.xml @@ -674,7 +674,7 @@ Удалить Редактировать Экспорт успешно выполнен - Start + Запуск Очистить Глобальный Другое @@ -801,6 +801,50 @@ Игре требуется прошивка сохраните и установите прошивку или нажмите "OK" для запуска в любом случае.]]> + + Поиск игры... + Игра не найдена для ID заголовка: %1$s + Пользовательские настройки не применены + Не удалось применить пользовательские настройки для %1$s: %2$s + Запустить с настройками по умолчанию + Запуск отменен + Не удалось применить запрошенные настройки. Это может быть связано с отсутствием драйверов GPU или проблемами конфигурации. + Пользовательские настройки применены + Запуск %1$s... + Не удалось инициализировать игру + Хотите запустить %1$s с пользовательскими настройками? + Хотите запустить %1$s? + Запуск игры + Запустить + + + Не удалось записать файл конфигурации + Не удалось применить конфигурацию + Конфигурация уже существует + Пользовательские настройки уже существуют для %1$s.\n\nХотите перезаписать существующую конфигурацию?\n\nЭто действие нельзя отменить. + Проверка существующей конфигурации... + Перезапись отменена + Проверка пользовательского драйвера: %1$s + Пользовательский драйвер недоступен для этого устройства + Перезаписать + + + Отсутствует драйвер GPU + Выбранный пользовательский драйвер \"%s\" не установлен. Хотите скачать и установить его сейчас? + Загрузка драйвера... + Драйвер успешно установлен + Ошибка установки драйвера + Не удалось установить драйвер GPU: %s + Драйвер недоступен + Выбранный драйвер недоступен для загрузки. + Необходимый драйвер не установлен: %s + Неверный файл драйвера: %s + Сетевое соединение недоступно. Проверьте подключение к интернету и попробуйте снова. + Требуется драйвер GPU + Конфигурация игры требует драйвер GPU \"%s\", который не установлен на вашем устройстве.\n\nХотите скачать и установить его сейчас? + Загрузка драйвера отменена. Игра не может быть запущена без необходимого драйвера. + Скачать + Выход из эмуляции Готово diff --git a/src/android/app/src/main/res/values-sr/strings.xml b/src/android/app/src/main/res/values-sr/strings.xml index 1eba9baa16..18612333f9 100644 --- a/src/android/app/src/main/res/values-sr/strings.xml +++ b/src/android/app/src/main/res/values-sr/strings.xml @@ -757,6 +757,50 @@ Игра захтева firmware направите дамп и инсталирајте firmware, или притисните "OK" да бисте наставили у сваком случају.]]> + + Тражење игре... + Игра није пронађена за ID наслова: %1$s + Прилагођена подешавања нису успела + Неуспело применљивање прилагођених подешавања за %1$s: %2$s + Покрени са подразумеваним подешавањима + Покретање отказано + Није могуће применити тражена подешавања. Ово може бити услед недостајућих GPU драјвера или проблема са конфигурацијом. + Прилагођена подешавања применљена + Покрећем %1$s... + Неуспела иницијализација игре + Да ли желите да покренете %1$s са прилагођеним подешавањима? + Да ли желите да покренете %1$s? + Покрени игру + Покрени + + + Неуспело писање конфигурационе датотеке + Неуспела примена конфигурације + Конфигурација већ постоји + Прилагођена подешавања већ постоје за %1$s.\n\nДа ли желите да препишете постојећу конфигурацију?\n\nОву радњу није могуће поништити. + Провера постојеће конфигурације... + Преписивање отказано + Провера прилагођеног драјвера: %1$s + Прилагођени драјвер није доступан за овај уређај + Препиши + + + GPU драјвер недостаје + Одабрани прилагођени драјвер \"%s\" није инсталиран. Да ли желите да га преузмете и инсталирате сада? + Преузимање драјвера... + Драјвер успешно инсталиран + Инсталација драјвера није успела + Неуспела инсталација GPU драјвера: %s + Драјвер није доступан + Одабрани драјвер није доступан за преузимање. + Потребни драјвер није инсталиран: %s + Неисправна датотека драјвера: %s + Мрежна веза није доступна. Проверите интернет конекцију и покушајте поново. + GPU драјвер је потребан + Конфигурација игре захтева GPU драјвер \"%s\" који није инсталиран на вашем уређају.\n\nДа ли желите да га преузмете и инсталирате сада? + Преузимање драјвера отказано. Игра се не може покренути без потребног драјвера. + Преузми + Излазни емулација Доношен diff --git a/src/android/app/src/main/res/values-uk/strings.xml b/src/android/app/src/main/res/values-uk/strings.xml index 7dc9ded033..830e1f0ef9 100644 --- a/src/android/app/src/main/res/values-uk/strings.xml +++ b/src/android/app/src/main/res/values-uk/strings.xml @@ -694,10 +694,77 @@ Гра вимагає прошивки зробіть дамп і встановіть прошивку, або натисніть "OK", щоб продовжити в будь-якому разі.]]> + + Пошук гри... + Гру не знайдено для ID заголовку: %1$s + Користувацькі налаштування не застосовано + Не вдалося застосувати користувацькі налаштування для %1$s: %2$s + Запустити з налаштуваннями за замовчуванням + Запуск скасовано + Не вдалося застосувати запитувані налаштування. Це може бути пов\'язано з відсутністю драйверів GPU або проблемами конфігурації. + Користувацькі налаштування застосовано + Запуск %1$s... + Не вдалося ініціалізувати гру + Бажаєте запустити %1$s з користувацькими налаштуваннями? + Бажаєте запустити %1$s? + Запустити гру + Запустити + + + Не вдалося записати файл конфігурації + Не вдалося застосувати конфігурацію + Конфігурація вже існує + Користувацькі налаштування вже існують для %1$s.\n\nБажаєте перезаписати існуючу конфігурацію?\n\nЦю дію не можна скасувати. + Перевірка наявної конфігурації... + Перезапис скасовано + Перевірка користувацького драйвера: %1$s + Користувацький драйвер недоступний для цього пристрою + Перезаписати + + + Відсутній драйвер GPU + Обраний користувацький драйвер \"%s\" не встановлено. Бажаєте завантажити та встановити його зараз? + Завантаження драйвера... + Драйвер успішно встановлено + Помилка встановлення драйвера + Не вдалося встановити драйвер GPU: %s + Драйвер недоступний + Обраний драйвер недоступний для завантаження. + Необхідний драйвер не встановлено: %s + Недійсний файл драйвера: %s + Мережеве з\'єднання недоступне. Перевірте підключення до інтернету та спробуйте ще раз. + Потрібен драйвер GPU + Конфігурація гри вимагає драйвер GPU \"%s\", який не встановлено на вашому пристрої.\n\nБажаєте завантажити та встановити його зараз? + Завантаження драйвера скасовано. Гру не можна запустити без необхідного драйвера. + Завантажити + + + Вийти з емуляції Готово + Лічильник FPS + Індикатор температури + Перемкнути елементи керування + Відносний центр джойстика + Ковзання D-pad + Тактильний відгук + Показати накладання + Перемкнути все + Налаштувати накладання Масштаб Непрозорість + Скинути накладання + Редагувати накладання + Призупинити емуляцію + Продовжити емуляцію + Опції накладання Сенсорний екран + Заблокувати панель + Розблокувати панель + + Завантаження налаштувань… + + + Програмна клавіатура Зупинити diff --git a/src/android/app/src/main/res/values-vi/strings.xml b/src/android/app/src/main/res/values-vi/strings.xml index 5655f2c745..1c656fc7bb 100644 --- a/src/android/app/src/main/res/values-vi/strings.xml +++ b/src/android/app/src/main/res/values-vi/strings.xml @@ -669,6 +669,50 @@ Trò chơi yêu cầu firmware dump và cài đặt firmware, hoặc nhấn "OK" để tiếp tục dù sao đi nữa.]]> + + Đang tìm kiếm trò chơi... + Không tìm thấy trò chơi cho ID Tiêu đề: %1$s + Cài đặt Tùy chỉnh Thất bại + Không thể áp dụng cài đặt tùy chỉnh cho %1$s: %2$s + Khởi chạy với Cài đặt Mặc định + Đã hủy khởi chạy + Không thể áp dụng các cài đặt được yêu cầu. Điều này có thể do thiếu trình điều khiển GPU hoặc sự cố cấu hình. + Đã áp dụng cài đặt tùy chỉnh + Đang khởi chạy %1$s... + Không thể khởi tạo trò chơi + Bạn có muốn khởi chạy %1$s với cài đặt tùy chỉnh không? + Bạn có muốn khởi chạy %1$s không? + Khởi chạy Trò chơi + Khởi chạy + + + Không thể ghi tệp cấu hình + Không thể áp dụng cấu hình + Cấu hình Đã Tồn tại + Cài đặt tùy chỉnh đã tồn tại cho %1$s.\n\nBạn có muốn ghi đè cấu hình hiện có không?\n\nHành động này không thể hoàn tác. + Đang kiểm tra cấu hình hiện có... + Đã hủy ghi đè + Đang kiểm tra trình điều khiển tùy chỉnh: %1$s + Trình điều khiển tùy chỉnh không khả dụng cho thiết bị này + Ghi đè + + + Thiếu Trình điều khiển GPU + Trình điều khiển tùy chỉnh được chọn \"%s\" chưa được cài đặt. Bạn có muốn tải xuống và cài đặt ngay bây giờ không? + Đang tải xuống trình điều khiển... + Đã cài đặt trình điều khiển thành công + Cài đặt Trình điều khiển Thất bại + Không thể cài đặt trình điều khiển GPU: %s + Trình điều khiển Không khả dụng + Trình điều khiển được chọn không có sẵn để tải xuống. + Không tìm thấy trình điều khiển bắt buộc: %s + Tệp trình điều khiển không hợp lệ: %s + Không có kết nối mạng khả dụng. Vui lòng kiểm tra kết nối internet của bạn và thử lại. + Yêu cầu Trình điều khiển GPU + Cấu hình trò chơi yêu cầu trình điều khiển GPU \"%s\" chưa được cài đặt trên thiết bị của bạn.\n\nBạn có muốn tải xuống và cài đặt ngay bây giờ không? + Đã hủy tải xuống trình điều khiển. Không thể khởi chạy trò chơi nếu thiếu trình điều khiển bắt buộc. + Tải xuống + Thoát giả lập Hoàn tất diff --git a/src/android/app/src/main/res/values-zh-rCN/strings.xml b/src/android/app/src/main/res/values-zh-rCN/strings.xml index ec519cec56..f3e7d9282c 100644 --- a/src/android/app/src/main/res/values-zh-rCN/strings.xml +++ b/src/android/app/src/main/res/values-zh-rCN/strings.xml @@ -793,6 +793,50 @@ 游戏需要固件 转储并安装固件,或点击"确定"继续。]]> + + 正在搜索游戏... + 未找到标题ID的游戏: %1$s + 自定义设置失败 + 无法应用自定义设置 %1$s: %2$s + 使用默认设置启动 + 启动已取消 + 无法应用请求的设置。这可能是由于缺少GPU驱动程序或配置问题。 + 已应用自定义设置 + 正在启动 %1$s... + 无法初始化游戏 + 是否要使用自定义设置启动 %1$s? + 是否要启动 %1$s? + 启动游戏 + 启动 + + + 无法写入配置文件 + 无法应用配置 + 配置已存在 + %1$s 的自定义设置已存在。\n\n是否要覆盖现有配置?\n\n此操作无法撤消。 + 正在检查现有配置... + 覆盖已取消 + 正在检查自定义驱动程序: %1$s + 自定义驱动程序不适用于此设备 + 覆盖 + + + 缺少GPU驱动程序 + 选定的自定义驱动程序 \"%s\" 未安装。是否要立即下载并安装? + 正在下载驱动程序... + 驱动程序安装成功 + 驱动程序安装失败 + 无法安装GPU驱动程序: %s + 驱动程序不可用 + 选定的驱动程序不可下载。 + 未安装所需的驱动程序: %s + 无效的驱动程序文件: %s + 无可用网络连接。请检查您的互联网连接并重试。 + 需要GPU驱动程序 + 游戏配置需要GPU驱动程序 \"%s\",但您的设备上未安装。\n\n是否要立即下载并安装? + 驱动程序下载已取消。没有所需的驱动程序无法启动游戏。 + 下载 + 退出模拟 完成 diff --git a/src/android/app/src/main/res/values-zh-rTW/strings.xml b/src/android/app/src/main/res/values-zh-rTW/strings.xml index 0d154af67c..b6c17745be 100644 --- a/src/android/app/src/main/res/values-zh-rTW/strings.xml +++ b/src/android/app/src/main/res/values-zh-rTW/strings.xml @@ -798,6 +798,50 @@ 遊戲需要韌體 轉儲並安裝韌體,或點擊"確定"繼續。]]> + + 正在搜尋遊戲... + 找不到標題ID的遊戲: %1$s + 自訂設定失敗 + 無法套用自訂設定 %1$s: %2$s + 使用預設設定啟動 + 啟動已取消 + 無法套用請求的設定。這可能是由於缺少GPU驅動程式或設定問題。 + 已套用自訂設定 + 正在啟動 %1$s... + 無法初始化遊戲 + 是否要使用自訂設定啟動 %1$s? + 是否要啟動 %1$s? + 啟動遊戲 + 啟動 + + + 無法寫入設定檔 + 無法套用設定 + 設定已存在 + %1$s 的自訂設定已存在。\n\n是否要覆蓋現有設定?\n\n此操作無法復原。 + 正在檢查現有設定... + 覆蓋已取消 + 正在檢查自訂驅動程式: %1$s + 自訂驅動程式不適用於此裝置 + 覆蓋 + + + 缺少GPU驅動程式 + 選定的自訂驅動程式 \"%s\" 未安裝。是否要立即下載並安裝? + 正在下載驅動程式... + 驅動程式安裝成功 + 驅動程式安裝失敗 + 無法安裝GPU驅動程式: %s + 驅動程式不可用 + 選定的驅動程式無法下載。 + 未安裝所需的驅動程式: %s + 無效的驅動程式檔案: %s + 無可用網路連線。請檢查您的網路連線並重試。 + 需要GPU驅動程式 + 遊戲設定需要GPU驅動程式 \"%s\",但您的裝置上未安裝。\n\n是否要立即下載並安裝? + 驅動程式下載已取消。沒有所需的驅動程式無法啟動遊戲。 + 下載 + 結束模擬 完成 From 949f72222b9274a8a12de388fe1fc0f2fd36f4d7 Mon Sep 17 00:00:00 2001 From: wildcard Date: Sat, 23 Aug 2025 20:00:58 +0200 Subject: [PATCH 07/39] [VK] spec-clean MasterSemaphore submits (#285) fixes this error [ 18.505526] Render.Vulkan video_core/vulkan_common/vulkan_debug_callback.cpp:DebugUtilCallback:59: Validation Information: [ UNASSIGNED-BestPractices-SemaphoreCount ] | MessageID = 0x6cfe18a5 | pSubmits[0].pWaitSemaphores is set, but pSubmits[0].waitSemaphoreCount is 0. This patch is only corrective in nature and is trivial and should not fix or break anything just one of the best practices in vulkan. It nulls pWaitSemaphores / pWaitDstStageMask / pSignalSemaphores when the corresponding counts are zero. Reviewed-on: https://git.eden-emu.dev/eden-emu/eden/pulls/285 Reviewed-by: Shinmegumi Co-authored-by: wildcard Co-committed-by: wildcard --- .../renderer_vulkan/vk_master_semaphore.cpp | 33 ++++++++++++++----- 1 file changed, 25 insertions(+), 8 deletions(-) diff --git a/src/video_core/renderer_vulkan/vk_master_semaphore.cpp b/src/video_core/renderer_vulkan/vk_master_semaphore.cpp index ac8b6e838e..4e5a2ff049 100644 --- a/src/video_core/renderer_vulkan/vk_master_semaphore.cpp +++ b/src/video_core/renderer_vulkan/vk_master_semaphore.cpp @@ -1,3 +1,6 @@ +// SPDX-FileCopyrightText: Copyright 2025 Eden Emulator Project +// SPDX-License-Identifier: GPL-3.0-or-later + // SPDX-FileCopyrightText: Copyright 2020 yuzu Emulator Project // SPDX-License-Identifier: GPL-2.0-or-later @@ -129,11 +132,19 @@ VkResult MasterSemaphore::SubmitQueueTimeline(vk::CommandBuffer& cmdbuf, const std::array cmdbuffers{*upload_cmdbuf, *cmdbuf}; const u32 num_wait_semaphores = wait_semaphore ? 1 : 0; + // Pointers must be null when the count is zero (best-practices) + const VkSemaphore* p_wait_sems = + (num_wait_semaphores > 0) ? &wait_semaphore : nullptr; + const VkPipelineStageFlags* p_wait_masks = + (num_wait_semaphores > 0) ? wait_stage_masks.data() : nullptr; + const VkSemaphore* p_signal_sems = + (num_signal_semaphores > 0) ? signal_semaphores.data() : nullptr; + const u64 wait_zero = 0; // dummy for binary wait const VkTimelineSemaphoreSubmitInfo timeline_si{ .sType = VK_STRUCTURE_TYPE_TIMELINE_SEMAPHORE_SUBMIT_INFO, .pNext = nullptr, - .waitSemaphoreValueCount = 0, - .pWaitSemaphoreValues = nullptr, + .waitSemaphoreValueCount = num_wait_semaphores, + .pWaitSemaphoreValues = num_wait_semaphores ? &wait_zero : nullptr, .signalSemaphoreValueCount = num_signal_semaphores, .pSignalSemaphoreValues = signal_values.data(), }; @@ -141,12 +152,12 @@ VkResult MasterSemaphore::SubmitQueueTimeline(vk::CommandBuffer& cmdbuf, .sType = VK_STRUCTURE_TYPE_SUBMIT_INFO, .pNext = &timeline_si, .waitSemaphoreCount = num_wait_semaphores, - .pWaitSemaphores = &wait_semaphore, - .pWaitDstStageMask = wait_stage_masks.data(), + .pWaitSemaphores = p_wait_sems, + .pWaitDstStageMask = p_wait_masks, .commandBufferCount = static_cast(cmdbuffers.size()), .pCommandBuffers = cmdbuffers.data(), .signalSemaphoreCount = num_signal_semaphores, - .pSignalSemaphores = signal_semaphores.data(), + .pSignalSemaphores = p_signal_sems, }; return device.GetGraphicsQueue().Submit(submit_info); @@ -159,18 +170,24 @@ VkResult MasterSemaphore::SubmitQueueFence(vk::CommandBuffer& cmdbuf, const u32 num_signal_semaphores = signal_semaphore ? 1 : 0; const u32 num_wait_semaphores = wait_semaphore ? 1 : 0; + const VkSemaphore* p_wait_sems = + (num_wait_semaphores > 0) ? &wait_semaphore : nullptr; + const VkPipelineStageFlags* p_wait_masks = + (num_wait_semaphores > 0) ? wait_stage_masks.data() : nullptr; + const VkSemaphore* p_signal_sems = + (num_signal_semaphores > 0) ? &signal_semaphore : nullptr; const std::array cmdbuffers{*upload_cmdbuf, *cmdbuf}; const VkSubmitInfo submit_info{ .sType = VK_STRUCTURE_TYPE_SUBMIT_INFO, .pNext = nullptr, .waitSemaphoreCount = num_wait_semaphores, - .pWaitSemaphores = &wait_semaphore, - .pWaitDstStageMask = wait_stage_masks.data(), + .pWaitSemaphores = p_wait_sems, + .pWaitDstStageMask = p_wait_masks, .commandBufferCount = static_cast(cmdbuffers.size()), .pCommandBuffers = cmdbuffers.data(), .signalSemaphoreCount = num_signal_semaphores, - .pSignalSemaphores = &signal_semaphore, + .pSignalSemaphores = p_signal_sems, }; auto fence = GetFreeFence(); From 4eb6d10d623622f6623ee46935fe1df98a681592 Mon Sep 17 00:00:00 2001 From: wildcard Date: Sat, 23 Aug 2025 20:04:48 +0200 Subject: [PATCH 08/39] [Vk] Improve Stencil Handling and Fix Read-After-Write Hazard (#235) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit 1. Improves stencil handling: - Adds surface type detection to distinguish between color, depth, stencil, and depth-stencil formats - Only enables stencil load/store operations for surfaces that actually contain stencil data - Avoids unnecessary stencil operations for non-stencil formats (DONT_CARE) 2. Fixes read-after-write (RAW) synchronization hazards: - Adds a subpass self-dependency (subpass 0 → subpass 0) - Synchronizes color/depth writes with subsequent shader reads - Uses VK_DEPENDENCY_BY_REGION_BIT for efficient synchronization - Covers all possible relevant stages, • src: Color output + Early/Late fragment tests • dst: Fragment shader • Access: Write → Read transitions here is what hazard looks like [1147.550616] Render.Vulkan video_core/vulkan_common/vulkan_debug_callback.cpp:DebugUtilCallback:55: Validation Error: [ SYNC-HAZARD-READ-AFTER-WRITE ] Object 0: handle = 0x7409630000000192, type = VK_OBJECT_TYPE_IMAGE_VIEW; | MessageID = 0xe4d96472 | vkCmdDrawIndexed: Hazard READ_AFTER_WRITE for VkImageView 0x7409630000000192[], in VkCommandBuffer 0xb400007cb003ea70[], and VkPipeline 0x44d3470000000213[], VkDescriptorSet 0x0[], type: VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER, imageLayout: VK_IMAGE_LAYOUT_GENERAL, binding #2, index 0. Access info (usage: SYNC_FRAGMENT_SHADER_SHADER_SAMPLED_READ, prior_usage: SYNC_IMAGE_LAYOUT_TRANSITION, write_barriers: SYNC_FRAGMENT_SHADER_COLOR_ATTACHMENT_READ|SYNC_FRAGMENT_SHADER_DEPTH_STENCIL_ATTACHMENT_READ|SYNC_FRAGMENT_SHADER_INPUT_ATTACHMENT_READ|SYNC_EARLY_FRAGMENT_TESTS_DEPTH_STENCIL_ATTACHMENT_READ|SYNC_EARLY_FRAGMENT_TESTS_DEPTH_STENCIL_ATTACHMENT_WRITE|SYNC_LATE_FRAGMENT_TESTS_DEPTH_STENCIL_ATTACHMENT_READ|SYNC_LATE_FRAGMENT_TESTS_DEPTH_STENCIL_ATTACHMENT_WRITE|SYNC_COLOR_ATTACHMENT_OUTPUT_COLOR_ATTACHMENT_READ|SYNC_COLOR_ATTACHMENT_OUTPUT_COLOR_ATTACHMENT_WRITE|SYNC_SUBPASS_SHADER_HUAWEI_INPUT_ATTACHMENT_READ, command: vkCmdPipelineBarrier, seq_no: 45, reset_no: 129). Reviewed-on: https://git.eden-emu.dev/eden-emu/eden/pulls/235 Reviewed-by: crueter Reviewed-by: Shinmegumi Co-authored-by: wildcard Co-committed-by: wildcard --- .../renderer_vulkan/vk_render_pass_cache.cpp | 83 +++++++++++++++---- 1 file changed, 65 insertions(+), 18 deletions(-) diff --git a/src/video_core/renderer_vulkan/vk_render_pass_cache.cpp b/src/video_core/renderer_vulkan/vk_render_pass_cache.cpp index 7746a88d34..80ff75e3b9 100644 --- a/src/video_core/renderer_vulkan/vk_render_pass_cache.cpp +++ b/src/video_core/renderer_vulkan/vk_render_pass_cache.cpp @@ -1,3 +1,6 @@ +// SPDX-FileCopyrightText: Copyright 2025 Eden Emulator Project +// SPDX-License-Identifier: GPL-3.0-or-later + // SPDX-FileCopyrightText: Copyright 2021 yuzu Emulator Project // SPDX-License-Identifier: GPL-2.0-or-later @@ -14,23 +17,55 @@ namespace Vulkan { namespace { using VideoCore::Surface::PixelFormat; +using VideoCore::Surface::SurfaceType; -VkAttachmentDescription AttachmentDescription(const Device& device, PixelFormat format, - VkSampleCountFlagBits samples) { - using MaxwellToVK::SurfaceFormat; - return { - .flags = {}, - .format = SurfaceFormat(device, FormatType::Optimal, true, format).format, - .samples = samples, - .loadOp = VK_ATTACHMENT_LOAD_OP_LOAD, - .storeOp = VK_ATTACHMENT_STORE_OP_STORE, - .stencilLoadOp = VK_ATTACHMENT_LOAD_OP_LOAD, - .stencilStoreOp = VK_ATTACHMENT_STORE_OP_STORE, - .initialLayout = VK_IMAGE_LAYOUT_GENERAL, - .finalLayout = VK_IMAGE_LAYOUT_GENERAL, - }; -} -} // Anonymous namespace + constexpr SurfaceType GetSurfaceType(PixelFormat format) { + switch (format) { + // Depth formats + case PixelFormat::D16_UNORM: + case PixelFormat::D32_FLOAT: + case PixelFormat::X8_D24_UNORM: + return SurfaceType::Depth; + + // Stencil formats + case PixelFormat::S8_UINT: + return SurfaceType::Stencil; + + // Depth+Stencil formats + case PixelFormat::D24_UNORM_S8_UINT: + case PixelFormat::S8_UINT_D24_UNORM: + case PixelFormat::D32_FLOAT_S8_UINT: + return SurfaceType::DepthStencil; + + // Everything else is a color texture + default: + return SurfaceType::ColorTexture; + } + } + + VkAttachmentDescription AttachmentDescription(const Device& device, PixelFormat format, + VkSampleCountFlagBits samples) { + using MaxwellToVK::SurfaceFormat; + + const SurfaceType surface_type = GetSurfaceType(format); + const bool has_stencil = surface_type == SurfaceType::DepthStencil || + surface_type == SurfaceType::Stencil; + + return { + .flags = {}, + .format = SurfaceFormat(device, FormatType::Optimal, true, format).format, + .samples = samples, + .loadOp = VK_ATTACHMENT_LOAD_OP_LOAD, + .storeOp = VK_ATTACHMENT_STORE_OP_STORE, + .stencilLoadOp = has_stencil ? VK_ATTACHMENT_LOAD_OP_LOAD + : VK_ATTACHMENT_LOAD_OP_DONT_CARE, + .stencilStoreOp = has_stencil ? VK_ATTACHMENT_STORE_OP_STORE + : VK_ATTACHMENT_STORE_OP_DONT_CARE, + .initialLayout = VK_IMAGE_LAYOUT_GENERAL, + .finalLayout = VK_IMAGE_LAYOUT_GENERAL, + }; + } + } // Anonymous namespace RenderPassCache::RenderPassCache(const Device& device_) : device{&device_} {} @@ -78,6 +113,18 @@ VkRenderPass RenderPassCache::Get(const RenderPassKey& key) { .preserveAttachmentCount = 0, .pPreserveAttachments = nullptr, }; + const VkSubpassDependency dependency{ + .srcSubpass = 0, // Current subpass + .dstSubpass = 0, // Same subpass (self-dependency) + .srcStageMask = VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT | + VK_PIPELINE_STAGE_EARLY_FRAGMENT_TESTS_BIT | + VK_PIPELINE_STAGE_LATE_FRAGMENT_TESTS_BIT, + .dstStageMask = VK_PIPELINE_STAGE_FRAGMENT_SHADER_BIT, + .srcAccessMask = VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT | + VK_ACCESS_DEPTH_STENCIL_ATTACHMENT_WRITE_BIT, + .dstAccessMask = VK_ACCESS_SHADER_READ_BIT, + .dependencyFlags = VK_DEPENDENCY_BY_REGION_BIT + }; pair->second = device->GetLogical().CreateRenderPass({ .sType = VK_STRUCTURE_TYPE_RENDER_PASS_CREATE_INFO, .pNext = nullptr, @@ -86,8 +133,8 @@ VkRenderPass RenderPassCache::Get(const RenderPassKey& key) { .pAttachments = descriptions.empty() ? nullptr : descriptions.data(), .subpassCount = 1, .pSubpasses = &subpass, - .dependencyCount = 0, - .pDependencies = nullptr, + .dependencyCount = 1, + .pDependencies = &dependency, }); return *pair->second; } From eb72a358e3d85f3a282ac9e03794114a5e6b57c4 Mon Sep 17 00:00:00 2001 From: Shinmegumi Date: Sat, 23 Aug 2025 20:34:05 +0200 Subject: [PATCH 09/39] [vk] Fix dynamic vertex input state handling (#295) only applies vertex input state if the pipeline was created with it Reviewed-on: https://git.eden-emu.dev/eden-emu/eden/pulls/295 Reviewed-by: Lizzie Co-authored-by: Shinmegumi Co-committed-by: Shinmegumi --- src/video_core/renderer_vulkan/vk_graphics_pipeline.h | 3 ++- src/video_core/renderer_vulkan/vk_rasterizer.cpp | 5 ++++- 2 files changed, 6 insertions(+), 2 deletions(-) diff --git a/src/video_core/renderer_vulkan/vk_graphics_pipeline.h b/src/video_core/renderer_vulkan/vk_graphics_pipeline.h index 7e9dbb583a..650c8e07ed 100644 --- a/src/video_core/renderer_vulkan/vk_graphics_pipeline.h +++ b/src/video_core/renderer_vulkan/vk_graphics_pipeline.h @@ -80,7 +80,8 @@ public: PipelineStatistics* pipeline_statistics, RenderPassCache& render_pass_cache, const GraphicsPipelineCacheKey& key, std::array stages, const std::array& infos); - + // True if this pipeline was created with VK_DYNAMIC_STATE_VERTEX_INPUT_EXT + bool HasDynamicVertexInput() const noexcept { return key.state.dynamic_vertex_input; } GraphicsPipeline& operator=(GraphicsPipeline&&) noexcept = delete; GraphicsPipeline(GraphicsPipeline&&) noexcept = delete; diff --git a/src/video_core/renderer_vulkan/vk_rasterizer.cpp b/src/video_core/renderer_vulkan/vk_rasterizer.cpp index 9ce5ea60a4..2d12fc658f 100644 --- a/src/video_core/renderer_vulkan/vk_rasterizer.cpp +++ b/src/video_core/renderer_vulkan/vk_rasterizer.cpp @@ -1002,7 +1002,10 @@ void RasterizerVulkan::UpdateDynamicStates() { } } if (features.has_dynamic_vertex_input) { - UpdateVertexInput(regs); + if (auto* gp = pipeline_cache.CurrentGraphicsPipeline(); + gp && gp->HasDynamicVertexInput()) { + UpdateVertexInput(regs); + } } } From e59065b54224b1338186fb959bffc5190b156819 Mon Sep 17 00:00:00 2001 From: wildcard Date: Sun, 24 Aug 2025 01:16:06 +0200 Subject: [PATCH 10/39] [VK] change bind point from Graphics to Compute since its a compute pipeline (#293) Title is sufficient Reviewed-on: https://git.eden-emu.dev/eden-emu/eden/pulls/293 Reviewed-by: Shinmegumi Co-authored-by: wildcard Co-committed-by: wildcard --- src/video_core/renderer_vulkan/vk_compute_pass.cpp | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/src/video_core/renderer_vulkan/vk_compute_pass.cpp b/src/video_core/renderer_vulkan/vk_compute_pass.cpp index 617f92910c..5938de6100 100644 --- a/src/video_core/renderer_vulkan/vk_compute_pass.cpp +++ b/src/video_core/renderer_vulkan/vk_compute_pass.cpp @@ -1,3 +1,6 @@ +// SPDX-FileCopyrightText: Copyright 2025 Eden Emulator Project +// SPDX-License-Identifier: GPL-3.0-or-later + // SPDX-FileCopyrightText: Copyright 2019 yuzu Emulator Project // SPDX-License-Identifier: GPL-2.0-or-later @@ -258,7 +261,7 @@ ComputePass::ComputePass(const Device& device_, DescriptorPool& descriptor_pool, .pDescriptorUpdateEntries = templates.data(), .templateType = VK_DESCRIPTOR_UPDATE_TEMPLATE_TYPE_DESCRIPTOR_SET, .descriptorSetLayout = *descriptor_set_layout, - .pipelineBindPoint = VK_PIPELINE_BIND_POINT_GRAPHICS, + .pipelineBindPoint = VK_PIPELINE_BIND_POINT_COMPUTE, .pipelineLayout = *layout, .set = 0, }); From 4ea9664ff4216b69902c310ba5d56b4e60c8079c Mon Sep 17 00:00:00 2001 From: MaranBr Date: Sun, 24 Aug 2025 02:05:38 +0200 Subject: [PATCH 11/39] [video_core] Fix EDS defaults by platform (#305) Reviewed-on: https://git.eden-emu.dev/eden-emu/eden/pulls/305 Reviewed-by: crueter Co-authored-by: MaranBr Co-committed-by: MaranBr --- src/common/settings.h | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/src/common/settings.h b/src/common/settings.h index 01e391d501..b846f41318 100644 --- a/src/common/settings.h +++ b/src/common/settings.h @@ -538,12 +538,12 @@ struct Values { SwitchableSetting dyna_state{linkage, #if defined (_WIN32) 3, -#elif defined(__FreeBSD__) +#elif defined (__FreeBSD__) 3, -#elif defined(__unix__) - 2, -#else +#elif defined (ANDROID) 0, +#else + 2, #endif 0, 3, From 302509d84d0612ce7823d82c4498d01fb86f72fd Mon Sep 17 00:00:00 2001 From: lizzie Date: Mon, 25 Aug 2025 14:43:50 +0200 Subject: [PATCH 12/39] [compat] fix clang std::terminate error (#307) Signed-off-by: lizzie Reviewed-on: https://git.eden-emu.dev/eden-emu/eden/pulls/307 Reviewed-by: crueter Co-authored-by: lizzie Co-committed-by: lizzie --- src/dynarmic/src/dynarmic/common/assert.cpp | 2 ++ 1 file changed, 2 insertions(+) diff --git a/src/dynarmic/src/dynarmic/common/assert.cpp b/src/dynarmic/src/dynarmic/common/assert.cpp index b0d3450c36..84a398f23e 100644 --- a/src/dynarmic/src/dynarmic/common/assert.cpp +++ b/src/dynarmic/src/dynarmic/common/assert.cpp @@ -4,6 +4,8 @@ // SPDX-License-Identifier: GPL-2.0-or-later #include +#include +#include [[noreturn]] void assert_terminate_impl(const char* expr_str, fmt::string_view msg, fmt::format_args args) { fmt::print(stderr, "assertion failed: {}\n", expr_str); From a1c5b5c911a71cd0c79161fb7285bb45768aa6dc Mon Sep 17 00:00:00 2001 From: MaranBr Date: Mon, 25 Aug 2025 18:23:38 +0200 Subject: [PATCH 13/39] [core] Fix a specific condition where the controller applet would still freeze in MK8D (#311) This fixes a specific condition where the controller applet would still freeze on the MK8D under certain circumstances. Reviewed-on: https://git.eden-emu.dev/eden-emu/eden/pulls/311 Reviewed-by: Shinmegumi Co-authored-by: MaranBr Co-committed-by: MaranBr --- .../am/service/library_applet_accessor.cpp | 15 +++++++++------ 1 file changed, 9 insertions(+), 6 deletions(-) diff --git a/src/core/hle/service/am/service/library_applet_accessor.cpp b/src/core/hle/service/am/service/library_applet_accessor.cpp index 5ce96a1e3f..b603cdb573 100644 --- a/src/core/hle/service/am/service/library_applet_accessor.cpp +++ b/src/core/hle/service/am/service/library_applet_accessor.cpp @@ -1,3 +1,6 @@ +// SPDX-FileCopyrightText: Copyright 2025 Eden Emulator Project +// SPDX-License-Identifier: GPL-3.0-or-later + // SPDX-FileCopyrightText: Copyright 2024 yuzu Emulator Project // SPDX-License-Identifier: GPL-2.0-or-later @@ -101,12 +104,12 @@ Result ILibraryAppletAccessor::PushInData(SharedPointer storage) { Result ILibraryAppletAccessor::PopOutData(Out> out_storage) { LOG_DEBUG(Service_AM, "called"); - if (auto caller_applet = m_applet->caller_applet.lock(); caller_applet) { - Event m_system_event = caller_applet->lifecycle_manager.GetSystemEvent(); - m_system_event.Signal(); - caller_applet->lifecycle_manager.RequestResumeNotification(); - m_system_event.Clear(); - } + if (auto caller_applet = m_applet->caller_applet.lock(); caller_applet) { + caller_applet->lifecycle_manager.GetSystemEvent().Signal(); + caller_applet->lifecycle_manager.RequestResumeNotification(); + caller_applet->lifecycle_manager.GetSystemEvent().Clear(); + caller_applet->lifecycle_manager.SignalSystemEventIfNeeded(); + } R_RETURN(m_broker->GetOutData().Pop(out_storage.Get())); } From 44d658bbc56c271ab0961ebc7743c241dcdf6c76 Mon Sep 17 00:00:00 2001 From: MaranBr Date: Mon, 25 Aug 2025 21:04:44 +0200 Subject: [PATCH 14/39] [core] Fix Diablo 3 (#314) This fixes Diablo 3. Regression introduced on PR 311. Reviewed-on: https://git.eden-emu.dev/eden-emu/eden/pulls/314 Co-authored-by: MaranBr Co-committed-by: MaranBr --- src/core/hle/service/am/service/library_applet_accessor.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/core/hle/service/am/service/library_applet_accessor.cpp b/src/core/hle/service/am/service/library_applet_accessor.cpp index b603cdb573..f7314b8f28 100644 --- a/src/core/hle/service/am/service/library_applet_accessor.cpp +++ b/src/core/hle/service/am/service/library_applet_accessor.cpp @@ -108,7 +108,7 @@ Result ILibraryAppletAccessor::PopOutData(Out> out_stora caller_applet->lifecycle_manager.GetSystemEvent().Signal(); caller_applet->lifecycle_manager.RequestResumeNotification(); caller_applet->lifecycle_manager.GetSystemEvent().Clear(); - caller_applet->lifecycle_manager.SignalSystemEventIfNeeded(); + caller_applet->lifecycle_manager.UpdateRequestedFocusState(); } R_RETURN(m_broker->GetOutData().Pop(out_storage.Get())); } From 380cfcaeed88b99970cada0ebb5f03df126704fb Mon Sep 17 00:00:00 2001 From: wildcard Date: Wed, 27 Aug 2025 04:45:50 +0200 Subject: [PATCH 15/39] [VK] Hybrid memory allocation with robust alignment (#325) Combines robust OOM handling with progressive size reduction and spec-compliant alignment: This hybrid approach maximizes allocation success rates through multiple recovery tries. Reviewed-on: https://git.eden-emu.dev/eden-emu/eden/pulls/325 Reviewed-by: CamilleLaVey Credits to Wildcard Co-authored-by: wildcard Co-committed-by: wildcard --- .../vulkan_common/vulkan_memory_allocator.cpp | 139 +++++++++++++++--- 1 file changed, 119 insertions(+), 20 deletions(-) diff --git a/src/video_core/vulkan_common/vulkan_memory_allocator.cpp b/src/video_core/vulkan_common/vulkan_memory_allocator.cpp index e80808621b..4c92d4bfa0 100644 --- a/src/video_core/vulkan_common/vulkan_memory_allocator.cpp +++ b/src/video_core/vulkan_common/vulkan_memory_allocator.cpp @@ -143,6 +143,10 @@ public: return (flags & property_flags) == flags && (type_mask & shifted_memory_type) != 0; } + [[nodiscard]] bool IsEmpty() const noexcept { + return commits.empty(); + } + private: [[nodiscard]] static constexpr u32 ShiftType(u32 type) { return 1U << type; @@ -290,36 +294,117 @@ MemoryCommit MemoryAllocator::Commit(const VkMemoryRequirements& requirements, M if (std::optional commit = TryCommit(requirements, flags)) { return std::move(*commit); } - // Commit has failed, allocate more memory. - const u64 chunk_size = AllocationChunkSize(requirements.size); - if (!TryAllocMemory(flags, type_mask, chunk_size)) { - // TODO(Rodrigo): Handle out of memory situations in some way like flushing to guest memory. - throw vk::Exception(VK_ERROR_OUT_OF_DEVICE_MEMORY); + + // Commit has failed, try progressive fallback strategy + u64 chunk_size = AllocationChunkSize(requirements.size); + const u64 minimum_size = std::max(requirements.size, 4ULL << 20); // 4MB minimum + + // try 1: Try allocating with original chunk size + if (TryAllocMemory(flags, type_mask, chunk_size)) { + return TryCommit(requirements, flags).value(); } - // Commit again, this time it won't fail since there's a fresh allocation above. - // If it does, there's a bug. - return TryCommit(requirements, flags).value(); + + // try 2: Clean up empty allocations and try again + bool cleaned_up = false; + for (auto it = allocations.begin(); it != allocations.end();) { + if ((*it)->IsEmpty()) { + it = allocations.erase(it); + cleaned_up = true; + } else { + ++it; + } + } + + if (cleaned_up && TryAllocMemory(flags, type_mask, chunk_size)) { + LOG_INFO(Render_Vulkan, "Memory allocation succeeded after cleanup"); + return TryCommit(requirements, flags).value(); + } + + // try 3: Progressive size reduction with cleanup between attempts + while (chunk_size > minimum_size) { + chunk_size >>= 1; // Halve the chunk size + chunk_size = std::max(chunk_size, minimum_size); + + if (TryAllocMemory(flags, type_mask, chunk_size)) { + LOG_WARNING(Render_Vulkan, "Memory allocation succeeded with reduced chunk size: {} MB", + chunk_size >> 20); + return TryCommit(requirements, flags).value(); + } + + // Clean up again between size reduction attempts + for (auto it = allocations.begin(); it != allocations.end();) { + if ((*it)->IsEmpty()) { + it = allocations.erase(it); + } else { + ++it; + } + } + } + + // try 4: Try minimum size allocation + if (chunk_size <= minimum_size && TryAllocMemory(flags, type_mask, minimum_size)) { + LOG_WARNING(Render_Vulkan, "Memory allocation succeeded with minimum size: {} MB", + minimum_size >> 20); + return TryCommit(requirements, flags).value(); + } + // try 5: Fallback to non-device-local memory if original was device-local + if (flags & VK_MEMORY_PROPERTY_DEVICE_LOCAL_BIT) { + const VkMemoryPropertyFlags fallback_flags = flags & ~VK_MEMORY_PROPERTY_DEVICE_LOCAL_BIT; + + // Try with original chunk size first + u64 fallback_chunk_size = AllocationChunkSize(requirements.size); + if (TryAllocMemory(fallback_flags, type_mask, fallback_chunk_size)) { + if (auto commit = TryCommit(requirements, fallback_flags)) { + LOG_WARNING(Render_Vulkan, "Falling back to non-device-local memory due to OOM"); + return std::move(*commit); + } + } + + // Progressive size reduction for non-device-local memory + while (fallback_chunk_size > minimum_size) { + fallback_chunk_size >>= 1; + fallback_chunk_size = std::max(fallback_chunk_size, minimum_size); + + if (TryAllocMemory(fallback_flags, type_mask, fallback_chunk_size)) { + if (auto commit = TryCommit(requirements, fallback_flags)) { + LOG_WARNING(Render_Vulkan, + "Falling back to non-device-local memory with reduced size: {} MB", + fallback_chunk_size >> 20); + return std::move(*commit); + } + } + } + } + + + LOG_CRITICAL(Render_Vulkan, "Vulkan memory allocation failed - exhausted all strategies"); + throw vk::Exception(VK_ERROR_OUT_OF_DEVICE_MEMORY); } bool MemoryAllocator::TryAllocMemory(VkMemoryPropertyFlags flags, u32 type_mask, u64 size) { - const u32 type = FindType(flags, type_mask).value(); + const auto type_opt = FindType(flags, type_mask); + if (!type_opt) { + return false; + } + + // Adreno requires 4KB alignment(subject to review) + const u64 aligned_size = (device.GetDriverID() == VK_DRIVER_ID_QUALCOMM_PROPRIETARY) ? + Common::AlignUp(size, 4096) : + size; + vk::DeviceMemory memory = device.GetLogical().TryAllocateMemory({ .sType = VK_STRUCTURE_TYPE_MEMORY_ALLOCATE_INFO, .pNext = nullptr, - .allocationSize = size, - .memoryTypeIndex = type, + .allocationSize = aligned_size, + .memoryTypeIndex = *type_opt, }); + if (!memory) { - if ((flags & VK_MEMORY_PROPERTY_DEVICE_LOCAL_BIT) != 0) { - // Try to allocate non device local memory - return TryAllocMemory(flags & ~VK_MEMORY_PROPERTY_DEVICE_LOCAL_BIT, type_mask, size); - } else { - // RIP - return false; - } + return false; } + allocations.push_back( - std::make_unique(this, std::move(memory), flags, size, type)); + std::make_unique(this, std::move(memory), flags, aligned_size, *type_opt)); return true; } @@ -331,11 +416,25 @@ void MemoryAllocator::ReleaseMemory(MemoryAllocation* alloc) { std::optional MemoryAllocator::TryCommit(const VkMemoryRequirements& requirements, VkMemoryPropertyFlags flags) { + // Conservative, spec-compliant alignment for suballocation + VkDeviceSize eff_align = requirements.alignment; + const auto& limits = device.GetPhysical().GetProperties().limits; + if ((flags & VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT) && + !(flags & VK_MEMORY_PROPERTY_HOST_COHERENT_BIT)) { + // Non-coherent memory must be invalidated on atom boundary + if (limits.nonCoherentAtomSize > eff_align) eff_align = limits.nonCoherentAtomSize; + } + // Separate buffers to avoid stalls on tilers + if (buffer_image_granularity > eff_align) { + eff_align = buffer_image_granularity; + } + eff_align = std::bit_ceil(eff_align); + for (auto& allocation : allocations) { if (!allocation->IsCompatible(flags, requirements.memoryTypeBits)) { continue; } - if (auto commit = allocation->Commit(requirements.size, requirements.alignment)) { + if (auto commit = allocation->Commit(requirements.size, eff_align)) { return commit; } } From c9a3baab5d5ba524778492027ef8961da947df2d Mon Sep 17 00:00:00 2001 From: lizzie Date: Wed, 27 Aug 2025 05:00:38 +0200 Subject: [PATCH 16/39] [heap_tracker] Use ankerl map instead of rb tree (#249) Signed-off-by: lizzie Reviewed-on: https://git.eden-emu.dev/eden-emu/eden/pulls/249 Reviewed-by: CamilleLaVey Co-authored-by: lizzie Co-committed-by: lizzie --- externals/CMakeLists.txt | 11 ++ src/common/CMakeLists.txt | 11 +- src/common/heap_tracker.cpp | 200 ++++++---------------- src/common/heap_tracker.h | 82 +++------ src/core/arm/dynarmic/arm_dynarmic.cpp | 44 +---- src/core/arm/dynarmic/arm_dynarmic.h | 20 --- src/core/arm/dynarmic/arm_dynarmic_32.cpp | 5 - src/core/arm/dynarmic/arm_dynarmic_64.cpp | 5 - src/core/hle/kernel/k_process.cpp | 4 - src/core/memory.cpp | 21 +-- src/core/memory.h | 5 - 11 files changed, 103 insertions(+), 305 deletions(-) diff --git a/externals/CMakeLists.txt b/externals/CMakeLists.txt index 64592a8855..07e9ae7a8f 100644 --- a/externals/CMakeLists.txt +++ b/externals/CMakeLists.txt @@ -151,6 +151,17 @@ if (ENABLE_WEB_SERVICE) ) endif() +# unordered_dense +AddPackage( + NAME unordered_dense + REPO "Lizzie841/unordered_dense" + SHA e59d30b7b1 + HASH 71eff7bd9ba4b9226967bacd56a8ff000946f8813167cb5664bb01e96fb79e4e220684d824fe9c59c4d1cc98c606f13aff05b7940a1ed8ab3c95d6974ee34fa0 + FIND_PACKAGE_ARGUMENTS "CONFIG" + OPTIONS + "UNORDERED_DENSE_INSTALL OFF" +) + # FFMpeg if (YUZU_USE_BUNDLED_FFMPEG) add_subdirectory(ffmpeg) diff --git a/src/common/CMakeLists.txt b/src/common/CMakeLists.txt index e9aed1d7af..cbe1d35fc5 100644 --- a/src/common/CMakeLists.txt +++ b/src/common/CMakeLists.txt @@ -262,13 +262,13 @@ if(CMAKE_CXX_COMPILER_ID STREQUAL "Clang") endif() if (BOOST_NO_HEADERS) - target_link_libraries(common PUBLIC Boost::algorithm Boost::icl Boost::pool) + target_link_libraries(common PUBLIC Boost::algorithm Boost::icl Boost::pool) else() - target_link_libraries(common PUBLIC Boost::headers) + target_link_libraries(common PUBLIC Boost::headers) endif() if (lz4_ADDED) - target_include_directories(common PRIVATE ${lz4_SOURCE_DIR}/lib) + target_include_directories(common PRIVATE ${lz4_SOURCE_DIR}/lib) endif() target_link_libraries(common PUBLIC fmt::fmt stb::headers Threads::Threads) @@ -280,6 +280,11 @@ else() target_link_libraries(common PRIVATE zstd) endif() +if (TARGET unordered_dense::unordered_dense) + # weird quirk of system installs + target_link_libraries(common PUBLIC unordered_dense::unordered_dense) +endif() + if(ANDROID) # For ASharedMemory_create target_link_libraries(common PRIVATE android) diff --git a/src/common/heap_tracker.cpp b/src/common/heap_tracker.cpp index 6832087959..d509f2644c 100644 --- a/src/common/heap_tracker.cpp +++ b/src/common/heap_tracker.cpp @@ -1,3 +1,5 @@ +// SPDX-FileCopyrightText: Copyright 2025 Eden Emulator Project +// SPDX-License-Identifier: GPL-3.0-or-later // SPDX-FileCopyrightText: Copyright 2023 yuzu Emulator Project // SPDX-License-Identifier: GPL-2.0-or-later @@ -34,68 +36,60 @@ HeapTracker::~HeapTracker() = default; void HeapTracker::Map(size_t virtual_offset, size_t host_offset, size_t length, MemoryPermission perm, bool is_separate_heap) { + bool rebuild_required = false; // When mapping other memory, map pages immediately. if (!is_separate_heap) { m_buffer.Map(virtual_offset, host_offset, length, perm, false); return; } - { - // We are mapping part of a separate heap. + // We are mapping part of a separate heap and insert into mappings. std::scoped_lock lk{m_lock}; - - auto* const map = new SeparateHeapMap{ - .vaddr = virtual_offset, + m_map_count++; + const auto it = m_mappings.insert_or_assign(virtual_offset, SeparateHeapMap{ .paddr = host_offset, .size = length, .tick = m_tick++, .perm = perm, .is_resident = false, - }; - - // Insert into mappings. - m_map_count++; - m_mappings.insert(*map); + }); + // Update tick before possible rebuild. + it.first->second.tick = m_tick++; + // Check if we need to rebuild. + if (m_resident_map_count >= m_max_resident_map_count) + rebuild_required = true; + // Map the area. + m_buffer.Map(it.first->first, it.first->second.paddr, it.first->second.size, it.first->second.perm, false); + // This map is now resident. + it.first->second.is_resident = true; + m_resident_map_count++; + m_resident_mappings.insert(*it.first); } - - // Finally, map. - this->DeferredMapSeparateHeap(virtual_offset); + // A rebuild was required, so perform it now. + if (rebuild_required) + this->RebuildSeparateHeapAddressSpace(); } void HeapTracker::Unmap(size_t virtual_offset, size_t size, bool is_separate_heap) { // If this is a separate heap... if (is_separate_heap) { std::scoped_lock lk{m_lock}; - - const SeparateHeapMap key{ - .vaddr = virtual_offset, - }; - // Split at the boundaries of the region we are removing. this->SplitHeapMapLocked(virtual_offset); this->SplitHeapMapLocked(virtual_offset + size); - // Erase all mappings in range. - auto it = m_mappings.find(key); - while (it != m_mappings.end() && it->vaddr < virtual_offset + size) { - // Get underlying item. - auto* const item = std::addressof(*it); - + auto it = m_mappings.find(virtual_offset); + while (it != m_mappings.end() && it->first < virtual_offset + size) { // If resident, erase from resident map. - if (item->is_resident) { + if (it->second.is_resident) { ASSERT(--m_resident_map_count >= 0); - m_resident_mappings.erase(m_resident_mappings.iterator_to(*item)); + m_resident_mappings.erase(m_resident_mappings.find(it->first)); } - // Erase from map. ASSERT(--m_map_count >= 0); it = m_mappings.erase(it); - - // Free the item. - delete item; } } - // Unmap pages. m_buffer.Unmap(virtual_offset, size, false); } @@ -117,110 +111,51 @@ void HeapTracker::Protect(size_t virtual_offset, size_t size, MemoryPermission p { std::scoped_lock lk2{m_lock}; - - const SeparateHeapMap key{ - .vaddr = next, - }; - // Try to get the next mapping corresponding to this address. - const auto it = m_mappings.nfind(key); - + const auto it = m_mappings.find(next); if (it == m_mappings.end()) { // There are no separate heap mappings remaining. next = end; should_protect = true; - } else if (it->vaddr == cur) { + } else if (it->first == cur) { // We are in range. // Update permission bits. - it->perm = perm; + it->second.perm = perm; // Determine next address and whether we should protect. - next = cur + it->size; - should_protect = it->is_resident; + next = cur + it->second.size; + should_protect = it->second.is_resident; } else /* if (it->vaddr > cur) */ { // We weren't in range, but there is a block coming up that will be. - next = it->vaddr; + next = it->first; should_protect = true; } } // Clamp to end. next = std::min(next, end); - // Reprotect, if we need to. - if (should_protect) { + if (should_protect) m_buffer.Protect(cur, next - cur, perm); - } - // Advance. cur = next; } } -bool HeapTracker::DeferredMapSeparateHeap(u8* fault_address) { - if (m_buffer.IsInVirtualRange(fault_address)) { - return this->DeferredMapSeparateHeap(fault_address - m_buffer.VirtualBasePointer()); - } - - return false; -} - -bool HeapTracker::DeferredMapSeparateHeap(size_t virtual_offset) { - bool rebuild_required = false; - - { - std::scoped_lock lk{m_lock}; - - // Check to ensure this was a non-resident separate heap mapping. - const auto it = this->GetNearestHeapMapLocked(virtual_offset); - if (it == m_mappings.end() || it->is_resident) { - return false; - } - - // Update tick before possible rebuild. - it->tick = m_tick++; - - // Check if we need to rebuild. - if (m_resident_map_count > m_max_resident_map_count) { - rebuild_required = true; - } - - // Map the area. - m_buffer.Map(it->vaddr, it->paddr, it->size, it->perm, false); - - // This map is now resident. - it->is_resident = true; - m_resident_map_count++; - m_resident_mappings.insert(*it); - } - - if (rebuild_required) { - // A rebuild was required, so perform it now. - this->RebuildSeparateHeapAddressSpace(); - } - - return true; -} - void HeapTracker::RebuildSeparateHeapAddressSpace() { std::scoped_lock lk{m_rebuild_lock, m_lock}; - ASSERT(!m_resident_mappings.empty()); - // Dump half of the mappings. - // // Despite being worse in theory, this has proven to be better in practice than more // regularly dumping a smaller amount, because it significantly reduces average case // lock contention. - const size_t desired_count = std::min(m_resident_map_count, m_max_resident_map_count) / 2; - const size_t evict_count = m_resident_map_count - desired_count; + std::size_t const desired_count = std::min(m_resident_map_count, m_max_resident_map_count) / 2; + std::size_t const evict_count = m_resident_map_count - desired_count; auto it = m_resident_mappings.begin(); - - for (size_t i = 0; i < evict_count && it != m_resident_mappings.end(); i++) { + for (std::size_t i = 0; i < evict_count && it != m_resident_mappings.end(); i++) { // Unmark and unmap. - it->is_resident = false; - m_buffer.Unmap(it->vaddr, it->size, false); - + it->second.is_resident = false; + m_buffer.Unmap(it->first, it->second.size, false); // Advance. ASSERT(--m_resident_map_count >= 0); it = m_resident_mappings.erase(it); @@ -229,53 +164,32 @@ void HeapTracker::RebuildSeparateHeapAddressSpace() { void HeapTracker::SplitHeapMap(VAddr offset, size_t size) { std::scoped_lock lk{m_lock}; - this->SplitHeapMapLocked(offset); this->SplitHeapMapLocked(offset + size); } void HeapTracker::SplitHeapMapLocked(VAddr offset) { - const auto it = this->GetNearestHeapMapLocked(offset); - if (it == m_mappings.end() || it->vaddr == offset) { - // Not contained or no split required. - return; + auto it = this->GetNearestHeapMapLocked(offset); + if (it != m_mappings.end() && it->first != offset) { + // Adjust left iterator + auto const orig_size = it->second.size; + auto const left_size = offset - it->first; + it->second.size = left_size; + // Insert the new right map. + auto const right = SeparateHeapMap{ + .paddr = it->second.paddr + left_size, + .size = orig_size - left_size, + .tick = it->second.tick, + .perm = it->second.perm, + .is_resident = it->second.is_resident, + }; + m_map_count++; + auto rit = m_mappings.insert_or_assign(it->first + left_size, right); + if (rit.first->second.is_resident) { + m_resident_map_count++; + m_resident_mappings.insert(*rit.first); + } } - - // Cache the original values. - auto* const left = std::addressof(*it); - const size_t orig_size = left->size; - - // Adjust the left map. - const size_t left_size = offset - left->vaddr; - left->size = left_size; - - // Create the new right map. - auto* const right = new SeparateHeapMap{ - .vaddr = left->vaddr + left_size, - .paddr = left->paddr + left_size, - .size = orig_size - left_size, - .tick = left->tick, - .perm = left->perm, - .is_resident = left->is_resident, - }; - - // Insert the new right map. - m_map_count++; - m_mappings.insert(*right); - - // If resident, also insert into resident map. - if (right->is_resident) { - m_resident_map_count++; - m_resident_mappings.insert(*right); - } -} - -HeapTracker::AddrTree::iterator HeapTracker::GetNearestHeapMapLocked(VAddr offset) { - const SeparateHeapMap key{ - .vaddr = offset, - }; - - return m_mappings.find(key); } } // namespace Common diff --git a/src/common/heap_tracker.h b/src/common/heap_tracker.h index ee5b0bf43a..14b5401c18 100644 --- a/src/common/heap_tracker.h +++ b/src/common/heap_tracker.h @@ -1,93 +1,55 @@ +// SPDX-FileCopyrightText: Copyright 2025 Eden Emulator Project +// SPDX-License-Identifier: GPL-3.0-or-later // SPDX-FileCopyrightText: Copyright 2023 yuzu Emulator Project // SPDX-License-Identifier: GPL-2.0-or-later #pragma once -#include #include -#include #include - +#include #include "common/host_memory.h" -#include "common/intrusive_red_black_tree.h" namespace Common { struct SeparateHeapMap { - Common::IntrusiveRedBlackTreeNode addr_node{}; - Common::IntrusiveRedBlackTreeNode tick_node{}; - VAddr vaddr{}; - PAddr paddr{}; - size_t size{}; - size_t tick{}; - MemoryPermission perm{}; - bool is_resident{}; -}; - -struct SeparateHeapMapAddrComparator { - static constexpr int Compare(const SeparateHeapMap& lhs, const SeparateHeapMap& rhs) { - if (lhs.vaddr < rhs.vaddr) { - return -1; - } else if (lhs.vaddr <= (rhs.vaddr + rhs.size - 1)) { - return 0; - } else { - return 1; - } - } -}; - -struct SeparateHeapMapTickComparator { - static constexpr int Compare(const SeparateHeapMap& lhs, const SeparateHeapMap& rhs) { - if (lhs.tick < rhs.tick) { - return -1; - } else if (lhs.tick > rhs.tick) { - return 1; - } else { - return SeparateHeapMapAddrComparator::Compare(lhs, rhs); - } - } + PAddr paddr{}; //8 + std::size_t size{}; //8 (16) + std::size_t tick{}; //8 (24) + // 4 bits needed, sync with host_memory.h if needed + MemoryPermission perm : 4 = MemoryPermission::Read; + bool is_resident : 1 = false; }; +static_assert(sizeof(SeparateHeapMap) == 32); //half a cache line! good for coherency class HeapTracker { public: explicit HeapTracker(Common::HostMemory& buffer); ~HeapTracker(); - - void Map(size_t virtual_offset, size_t host_offset, size_t length, MemoryPermission perm, - bool is_separate_heap); + void Map(size_t virtual_offset, size_t host_offset, size_t length, MemoryPermission perm, bool is_separate_heap); void Unmap(size_t virtual_offset, size_t size, bool is_separate_heap); void Protect(size_t virtual_offset, size_t length, MemoryPermission perm); - u8* VirtualBasePointer() { + inline u8* VirtualBasePointer() noexcept { return m_buffer.VirtualBasePointer(); } - - bool DeferredMapSeparateHeap(u8* fault_address); - bool DeferredMapSeparateHeap(size_t virtual_offset); - private: - using AddrTreeTraits = - Common::IntrusiveRedBlackTreeMemberTraitsDeferredAssert<&SeparateHeapMap::addr_node>; - using AddrTree = AddrTreeTraits::TreeType; - - using TickTreeTraits = - Common::IntrusiveRedBlackTreeMemberTraitsDeferredAssert<&SeparateHeapMap::tick_node>; - using TickTree = TickTreeTraits::TreeType; - - AddrTree m_mappings{}; - TickTree m_resident_mappings{}; - + // TODO: You may want to "fake-map" the first 2GB of 64-bit address space + // and dedicate it entirely to a recursive PTE mapping :) + // However Ankerl is way better than using an RB tree, in all senses + using AddrTree = ankerl::unordered_dense::map; + AddrTree m_mappings; + using TicksTree = ankerl::unordered_dense::map; + TicksTree m_resident_mappings; private: void SplitHeapMap(VAddr offset, size_t size); void SplitHeapMapLocked(VAddr offset); - - AddrTree::iterator GetNearestHeapMapLocked(VAddr offset); - void RebuildSeparateHeapAddressSpace(); - + inline HeapTracker::AddrTree::iterator GetNearestHeapMapLocked(VAddr offset) noexcept { + return m_mappings.find(offset); + } private: Common::HostMemory& m_buffer; const s64 m_max_resident_map_count; - std::shared_mutex m_rebuild_lock{}; std::mutex m_lock{}; s64 m_map_count{}; diff --git a/src/core/arm/dynarmic/arm_dynarmic.cpp b/src/core/arm/dynarmic/arm_dynarmic.cpp index e6e9fc45be..9d26db51f7 100644 --- a/src/core/arm/dynarmic/arm_dynarmic.cpp +++ b/src/core/arm/dynarmic/arm_dynarmic.cpp @@ -3,47 +3,9 @@ #ifdef __linux__ -#include "common/signal_chain.h" - +//#include "common/signal_chain.h" #include "core/arm/dynarmic/arm_dynarmic.h" -#include "core/hle/kernel/k_process.h" -#include "core/memory.h" - -namespace Core { - -namespace { - -thread_local Core::Memory::Memory* g_current_memory{}; -std::once_flag g_registered{}; -struct sigaction g_old_segv {}; - -void HandleSigSegv(int sig, siginfo_t* info, void* ctx) { - if (g_current_memory && g_current_memory->InvalidateSeparateHeap(info->si_addr)) { - return; - } - - return g_old_segv.sa_sigaction(sig, info, ctx); -} - -} // namespace - -ScopedJitExecution::ScopedJitExecution(Kernel::KProcess* process) { - g_current_memory = std::addressof(process->GetMemory()); -} - -ScopedJitExecution::~ScopedJitExecution() { - g_current_memory = nullptr; -} - -void ScopedJitExecution::RegisterHandler() { - std::call_once(g_registered, [] { - struct sigaction sa {}; - sa.sa_sigaction = &HandleSigSegv; - sa.sa_flags = SA_SIGINFO | SA_ONSTACK; - Common::SigAction(SIGSEGV, std::addressof(sa), std::addressof(g_old_segv)); - }); -} - -} // namespace Core +//#include "core/hle/kernel/k_process.h" +//#include "core/memory.h" #endif diff --git a/src/core/arm/dynarmic/arm_dynarmic.h b/src/core/arm/dynarmic/arm_dynarmic.h index 53dd188151..eef7c31160 100644 --- a/src/core/arm/dynarmic/arm_dynarmic.h +++ b/src/core/arm/dynarmic/arm_dynarmic.h @@ -26,24 +26,4 @@ constexpr HaltReason TranslateHaltReason(Dynarmic::HaltReason hr) { return static_cast(hr); } -#ifdef __linux__ - -class ScopedJitExecution { -public: - explicit ScopedJitExecution(Kernel::KProcess* process); - ~ScopedJitExecution(); - static void RegisterHandler(); -}; - -#else - -class ScopedJitExecution { -public: - explicit ScopedJitExecution(Kernel::KProcess* process) {} - ~ScopedJitExecution() {} - static void RegisterHandler() {} -}; - -#endif - } // namespace Core diff --git a/src/core/arm/dynarmic/arm_dynarmic_32.cpp b/src/core/arm/dynarmic/arm_dynarmic_32.cpp index afbf178349..1731ef1aec 100644 --- a/src/core/arm/dynarmic/arm_dynarmic_32.cpp +++ b/src/core/arm/dynarmic/arm_dynarmic_32.cpp @@ -336,15 +336,11 @@ bool ArmDynarmic32::IsInThumbMode() const { } HaltReason ArmDynarmic32::RunThread(Kernel::KThread* thread) { - ScopedJitExecution sj(thread->GetOwnerProcess()); - m_jit->ClearExclusiveState(); return TranslateHaltReason(m_jit->Run()); } HaltReason ArmDynarmic32::StepThread(Kernel::KThread* thread) { - ScopedJitExecution sj(thread->GetOwnerProcess()); - m_jit->ClearExclusiveState(); return TranslateHaltReason(m_jit->Step()); } @@ -386,7 +382,6 @@ ArmDynarmic32::ArmDynarmic32(System& system, bool uses_wall_clock, Kernel::KProc m_cp15(std::make_shared(*this)), m_core_index{core_index} { auto& page_table_impl = process->GetPageTable().GetBasePageTable().GetImpl(); m_jit = MakeJit(&page_table_impl); - ScopedJitExecution::RegisterHandler(); } ArmDynarmic32::~ArmDynarmic32() = default; diff --git a/src/core/arm/dynarmic/arm_dynarmic_64.cpp b/src/core/arm/dynarmic/arm_dynarmic_64.cpp index 99a80644ad..f9d1232f83 100644 --- a/src/core/arm/dynarmic/arm_dynarmic_64.cpp +++ b/src/core/arm/dynarmic/arm_dynarmic_64.cpp @@ -367,15 +367,11 @@ std::shared_ptr ArmDynarmic64::MakeJit(Common::PageTable* pa } HaltReason ArmDynarmic64::RunThread(Kernel::KThread* thread) { - ScopedJitExecution sj(thread->GetOwnerProcess()); - m_jit->ClearExclusiveState(); return TranslateHaltReason(m_jit->Run()); } HaltReason ArmDynarmic64::StepThread(Kernel::KThread* thread) { - ScopedJitExecution sj(thread->GetOwnerProcess()); - m_jit->ClearExclusiveState(); return TranslateHaltReason(m_jit->Step()); } @@ -415,7 +411,6 @@ ArmDynarmic64::ArmDynarmic64(System& system, bool uses_wall_clock, Kernel::KProc auto& page_table = process->GetPageTable().GetBasePageTable(); auto& page_table_impl = page_table.GetImpl(); m_jit = MakeJit(&page_table_impl, page_table.GetAddressSpaceWidth()); - ScopedJitExecution::RegisterHandler(); } ArmDynarmic64::~ArmDynarmic64() = default; diff --git a/src/core/hle/kernel/k_process.cpp b/src/core/hle/kernel/k_process.cpp index 80566b7e77..cf03353f84 100644 --- a/src/core/hle/kernel/k_process.cpp +++ b/src/core/hle/kernel/k_process.cpp @@ -1266,10 +1266,6 @@ void KProcess::InitializeInterfaces() { #ifdef HAS_NCE if (this->IsApplication() && Settings::IsNceEnabled()) { - // Register the scoped JIT handler before creating any NCE instances - // so that its signal handler will appear first in the signal chain. - Core::ScopedJitExecution::RegisterHandler(); - for (size_t i = 0; i < Core::Hardware::NUM_CPU_CORES; i++) { m_arm_interfaces[i] = std::make_unique(m_kernel.System(), true, i); } diff --git a/src/core/memory.cpp b/src/core/memory.cpp index 0035c626e2..08391cd815 100644 --- a/src/core/memory.cpp +++ b/src/core/memory.cpp @@ -61,8 +61,7 @@ struct Memory::Impl { } #ifdef __linux__ - heap_tracker.emplace(system.DeviceMemory().buffer); - buffer = std::addressof(*heap_tracker); + buffer.emplace(system.DeviceMemory().buffer); #else buffer = std::addressof(system.DeviceMemory().buffer); #endif @@ -1024,9 +1023,8 @@ struct Memory::Impl { std::span gpu_dirty_managers; std::mutex sys_core_guard; - std::optional heap_tracker; #ifdef __linux__ - Common::HeapTracker* buffer{}; + std::optional buffer; #else Common::HostMemory* buffer{}; #endif @@ -1230,22 +1228,7 @@ bool Memory::InvalidateNCE(Common::ProcessAddress vaddr, size_t size) { if (rasterizer) { impl->InvalidateGPUMemory(ptr, size); } - -#ifdef __linux__ - if (!rasterizer && mapped) { - impl->buffer->DeferredMapSeparateHeap(GetInteger(vaddr)); - } -#endif - return mapped && ptr != nullptr; } -bool Memory::InvalidateSeparateHeap(void* fault_address) { -#ifdef __linux__ - return impl->buffer->DeferredMapSeparateHeap(static_cast(fault_address)); -#else - return false; -#endif -} - } // namespace Core::Memory diff --git a/src/core/memory.h b/src/core/memory.h index dcca26892b..99108ecf0d 100644 --- a/src/core/memory.h +++ b/src/core/memory.h @@ -487,13 +487,8 @@ public: * marked as debug or non-debug. */ void MarkRegionDebug(Common::ProcessAddress vaddr, u64 size, bool debug); - void SetGPUDirtyManagers(std::span managers); - bool InvalidateNCE(Common::ProcessAddress vaddr, size_t size); - - bool InvalidateSeparateHeap(void* fault_address); - private: Core::System& system; From 21cd44ec04111f3b0ac2f57e8a84a9a3b427211a Mon Sep 17 00:00:00 2001 From: crueter Date: Wed, 27 Aug 2025 06:49:50 +0200 Subject: [PATCH 17/39] [dynarmic] jit fix branch v2 (#203) Co-authored-by: lizzie Reviewed-on: https://git.eden-emu.dev/eden-emu/eden/pulls/203 Reviewed-by: Shinmegumi --- docs/Development.md | 14 +- src/common/x64/xbyak_abi.h | 1 + src/core/arm/dynarmic/arm_dynarmic_64.cpp | 9 +- src/core/debugger/gdbstub.cpp | 79 ++--- src/core/hardware_properties.h | 2 +- .../docs/ReturnStackBufferOptimization.md | 18 +- .../backend/arm64/exclusive_monitor.cpp | 2 +- .../backend/arm64/verbose_debugging_output.h | 2 +- .../src/dynarmic/backend/x64/a32_emit_x64.cpp | 179 ++++++------ .../backend/x64/a32_emit_x64_memory.cpp | 6 +- .../src/dynarmic/backend/x64/a64_emit_x64.cpp | 159 +++++----- .../src/dynarmic/backend/x64/a64_emit_x64.h | 8 +- .../backend/x64/a64_emit_x64_memory.cpp | 6 +- src/dynarmic/src/dynarmic/backend/x64/abi.cpp | 56 ++-- src/dynarmic/src/dynarmic/backend/x64/abi.h | 1 + .../dynarmic/backend/x64/block_of_code.cpp | 33 ++- .../src/dynarmic/backend/x64/block_of_code.h | 1 + .../src/dynarmic/backend/x64/emit_x64.cpp | 23 +- .../dynarmic/backend/x64/emit_x64_crc32.cpp | 31 +- .../backend/x64/emit_x64_data_processing.cpp | 28 +- .../backend/x64/emit_x64_floating_point.cpp | 42 +-- .../backend/x64/emit_x64_memory.cpp.inc | 57 ++-- .../dynarmic/backend/x64/emit_x64_memory.h | 155 +++++----- .../backend/x64/emit_x64_saturation.cpp | 8 +- .../dynarmic/backend/x64/emit_x64_vector.cpp | 172 ++++++----- .../x64/emit_x64_vector_floating_point.cpp | 10 +- .../x64/emit_x64_vector_saturation.cpp | 10 +- .../backend/x64/exclusive_monitor.cpp | 12 +- .../src/dynarmic/backend/x64/hostloc.h | 44 +-- .../src/dynarmic/backend/x64/reg_alloc.cpp | 125 ++++---- .../src/dynarmic/backend/x64/reg_alloc.h | 12 +- .../backend/x64/verbose_debugging_output.cpp | 2 +- .../backend/x64/verbose_debugging_output.h | 2 +- .../src/dynarmic/common/crypto/crc32.cpp | 2 - src/dynarmic/src/dynarmic/common/spin_lock.h | 5 +- .../src/dynarmic/common/spin_lock_arm64.cpp | 4 +- .../src/dynarmic/common/spin_lock_x64.cpp | 11 +- .../A32/translate/impl/load_store.cpp | 8 +- .../A64/translate/impl/a64_branch.cpp | 1 + .../dynarmic/interface/exclusive_monitor.h | 8 +- .../dynarmic/interface/optimization_flags.h | 2 + src/dynarmic/src/dynarmic/ir/basic_block.cpp | 22 +- .../src/dynarmic/ir/microinstruction.h | 2 +- src/dynarmic/src/dynarmic/ir/opcodes.cpp | 50 +++- src/dynarmic/src/dynarmic/ir/opcodes.h | 4 +- src/dynarmic/src/dynarmic/ir/type.h | 2 +- src/dynarmic/tests/A32/fuzz_arm.cpp | 5 +- src/dynarmic/tests/A32/fuzz_thumb.cpp | 2 +- .../tests/A32/test_arm_instructions.cpp | 38 +-- src/dynarmic/tests/A32/test_coprocessor.cpp | 8 +- src/dynarmic/tests/A32/test_svc.cpp | 2 +- .../tests/A32/test_thumb_instructions.cpp | 18 +- src/dynarmic/tests/A32/testenv.h | 2 +- src/dynarmic/tests/A64/a64.cpp | 275 ++++++++++++------ src/dynarmic/tests/A64/fibonacci.cpp | 4 +- src/dynarmic/tests/A64/fp_min_max.cpp | 12 +- src/dynarmic/tests/A64/fuzz_with_unicorn.cpp | 17 +- .../tests/A64/misaligned_page_table.cpp | 2 +- src/dynarmic/tests/A64/real_world.cpp | 102 +++++++ src/dynarmic/tests/A64/test_invalidation.cpp | 24 +- src/dynarmic/tests/A64/testenv.h | 14 +- src/dynarmic/tests/A64/verify_unicorn.cpp | 6 +- src/dynarmic/tests/CMakeLists.txt | 8 +- src/dynarmic/tests/native/preserve_xmm.cpp | 64 ++++ src/dynarmic/tests/native/testenv.h | 50 ++++ .../tests/unicorn_emu/a64_unicorn.cpp | 2 +- src/tests/video_core/memory_tracker.cpp | 5 +- 67 files changed, 1214 insertions(+), 876 deletions(-) create mode 100644 src/dynarmic/tests/A64/real_world.cpp create mode 100644 src/dynarmic/tests/native/preserve_xmm.cpp create mode 100644 src/dynarmic/tests/native/testenv.h diff --git a/docs/Development.md b/docs/Development.md index 0db4131dbb..e60384e8ab 100644 --- a/docs/Development.md +++ b/docs/Development.md @@ -1,11 +1,11 @@ # Development -* **Windows**: [Windows Building Guide](./docs/build/Windows.md) -* **Linux**: [Linux Building Guide](./docs/build/Linux.md) -* **Android**: [Android Building Guide](./docs/build/Android.md) -* **Solaris**: [Solaris Building Guide](./docs/build/Solaris.md) -* **FreeBSD**: [FreeBSD Building Guide](./docs/build/FreeBSD.md) -* **macOS**: [macOS Building Guide](./docs/build/macOS.md) +* **Windows**: [Windows Building Guide](./build/Windows.md) +* **Linux**: [Linux Building Guide](./build/Linux.md) +* **Android**: [Android Building Guide](./build/Android.md) +* **Solaris**: [Solaris Building Guide](./build/Solaris.md) +* **FreeBSD**: [FreeBSD Building Guide](./build/FreeBSD.md) +* **macOS**: [macOS Building Guide](./build/macOS.md) # CPM @@ -104,7 +104,7 @@ Then type `target remote localhost:1234` and type `c` (for continue) - and then ### gdb cheatsheet -- `mo `: Monitor commands, `get info`, `get fastmem` and `get mappings` are available. +- `mo `: Monitor commands, `get info`, `get fastmem` and `get mappings` are available. Type `mo help` for more info. - `detach`: Detach from remote (i.e restarting the emulator). - `c`: Continue - `p `: Print variable, `p/x ` for hexadecimal. diff --git a/src/common/x64/xbyak_abi.h b/src/common/x64/xbyak_abi.h index 67e6e63c85..8aea5db583 100644 --- a/src/common/x64/xbyak_abi.h +++ b/src/common/x64/xbyak_abi.h @@ -47,6 +47,7 @@ constexpr std::bitset<32> BuildRegSet(std::initializer_list regs) { constexpr inline std::bitset<32> ABI_ALL_GPRS(0x0000FFFF); constexpr inline std::bitset<32> ABI_ALL_XMMS(0xFFFF0000); +constexpr inline Xbyak::Reg ABI_JIT_REG = Xbyak::util::rbx; #ifdef _WIN32 // Microsoft x64 ABI diff --git a/src/core/arm/dynarmic/arm_dynarmic_64.cpp b/src/core/arm/dynarmic/arm_dynarmic_64.cpp index f9d1232f83..9674e88d9d 100644 --- a/src/core/arm/dynarmic/arm_dynarmic_64.cpp +++ b/src/core/arm/dynarmic/arm_dynarmic_64.cpp @@ -136,6 +136,7 @@ public: case Dynarmic::A64::Exception::SendEvent: case Dynarmic::A64::Exception::SendEventLocal: case Dynarmic::A64::Exception::Yield: + LOG_TRACE(Core_ARM, "ExceptionRaised(exception = {}, pc = {:08X}, code = {:08X})", static_cast(exception), pc, m_memory.Read32(pc)); return; case Dynarmic::A64::Exception::NoExecuteFault: LOG_CRITICAL(Core_ARM, "Cannot execute instruction at unmapped address {:#016x}", pc); @@ -144,12 +145,10 @@ public: default: if (m_debugger_enabled) { ReturnException(pc, InstructionBreakpoint); - return; + } else { + m_parent.LogBacktrace(m_process); + LOG_CRITICAL(Core_ARM, "ExceptionRaised(exception = {}, pc = {:08X}, code = {:08X})", static_cast(exception), pc, m_memory.Read32(pc)); } - - m_parent.LogBacktrace(m_process); - LOG_CRITICAL(Core_ARM, "ExceptionRaised(exception = {}, pc = {:08X}, code = {:08X})", - static_cast(exception), pc, m_memory.Read32(pc)); } } diff --git a/src/core/debugger/gdbstub.cpp b/src/core/debugger/gdbstub.cpp index 80091cc7e0..fcb5787147 100644 --- a/src/core/debugger/gdbstub.cpp +++ b/src/core/debugger/gdbstub.cpp @@ -554,32 +554,31 @@ void GDBStub::HandleVCont(std::string_view command, std::vector& } } -constexpr std::array, 22> MemoryStateNames{{ - {"----- Free ------", Kernel::Svc::MemoryState::Free}, - {"Io ", Kernel::Svc::MemoryState::Io}, - {"Static ", Kernel::Svc::MemoryState::Static}, - {"Code ", Kernel::Svc::MemoryState::Code}, - {"CodeData ", Kernel::Svc::MemoryState::CodeData}, - {"Normal ", Kernel::Svc::MemoryState::Normal}, - {"Shared ", Kernel::Svc::MemoryState::Shared}, - {"AliasCode ", Kernel::Svc::MemoryState::AliasCode}, - {"AliasCodeData ", Kernel::Svc::MemoryState::AliasCodeData}, - {"Ipc ", Kernel::Svc::MemoryState::Ipc}, - {"Stack ", Kernel::Svc::MemoryState::Stack}, - {"ThreadLocal ", Kernel::Svc::MemoryState::ThreadLocal}, - {"Transferred ", Kernel::Svc::MemoryState::Transferred}, - {"SharedTransferred", Kernel::Svc::MemoryState::SharedTransferred}, - {"SharedCode ", Kernel::Svc::MemoryState::SharedCode}, - {"Inaccessible ", Kernel::Svc::MemoryState::Inaccessible}, - {"NonSecureIpc ", Kernel::Svc::MemoryState::NonSecureIpc}, - {"NonDeviceIpc ", Kernel::Svc::MemoryState::NonDeviceIpc}, - {"Kernel ", Kernel::Svc::MemoryState::Kernel}, - {"GeneratedCode ", Kernel::Svc::MemoryState::GeneratedCode}, - {"CodeOut ", Kernel::Svc::MemoryState::CodeOut}, - {"Coverage ", Kernel::Svc::MemoryState::Coverage}, -}}; - static constexpr const char* GetMemoryStateName(Kernel::Svc::MemoryState state) { + constexpr std::array, 22> MemoryStateNames{{ + {"----- Free ------", Kernel::Svc::MemoryState::Free}, + {"Io ", Kernel::Svc::MemoryState::Io}, + {"Static ", Kernel::Svc::MemoryState::Static}, + {"Code ", Kernel::Svc::MemoryState::Code}, + {"CodeData ", Kernel::Svc::MemoryState::CodeData}, + {"Normal ", Kernel::Svc::MemoryState::Normal}, + {"Shared ", Kernel::Svc::MemoryState::Shared}, + {"AliasCode ", Kernel::Svc::MemoryState::AliasCode}, + {"AliasCodeData ", Kernel::Svc::MemoryState::AliasCodeData}, + {"Ipc ", Kernel::Svc::MemoryState::Ipc}, + {"Stack ", Kernel::Svc::MemoryState::Stack}, + {"ThreadLocal ", Kernel::Svc::MemoryState::ThreadLocal}, + {"Transferred ", Kernel::Svc::MemoryState::Transferred}, + {"SharedTransferred", Kernel::Svc::MemoryState::SharedTransferred}, + {"SharedCode ", Kernel::Svc::MemoryState::SharedCode}, + {"Inaccessible ", Kernel::Svc::MemoryState::Inaccessible}, + {"NonSecureIpc ", Kernel::Svc::MemoryState::NonSecureIpc}, + {"NonDeviceIpc ", Kernel::Svc::MemoryState::NonDeviceIpc}, + {"Kernel ", Kernel::Svc::MemoryState::Kernel}, + {"GeneratedCode ", Kernel::Svc::MemoryState::GeneratedCode}, + {"CodeOut ", Kernel::Svc::MemoryState::CodeOut}, + {"Coverage ", Kernel::Svc::MemoryState::Coverage}, + }}; for (size_t i = 0; i < MemoryStateNames.size(); i++) { if (std::get<1>(MemoryStateNames[i]) == state) { return std::get<0>(MemoryStateNames[i]); @@ -611,13 +610,7 @@ void GDBStub::HandleRcmd(const std::vector& command) { auto* process = GetProcess(); auto& page_table = process->GetPageTable(); - - const char* commands = "Commands:\n" - " get fastmem\n" - " get info\n" - " get mappings\n"; - - if (command_str == "get fastmem") { + if (command_str == "fastmem" || command_str == "get fastmem") { if (Settings::IsFastmemEnabled()) { const auto& impl = page_table.GetImpl(); const auto region = reinterpret_cast(impl.fastmem_arena); @@ -630,7 +623,7 @@ void GDBStub::HandleRcmd(const std::vector& command) { } else { reply = "Fastmem is not enabled.\n"; } - } else if (command_str == "get info") { + } else if (command_str == "info" || command_str == "get info") { auto modules = Core::FindModules(process); reply = fmt::format("Process: {:#x} ({})\n" @@ -648,8 +641,7 @@ void GDBStub::HandleRcmd(const std::vector& command) { GetInteger(page_table.GetHeapRegionStart()), GetInteger(page_table.GetHeapRegionStart()) + page_table.GetHeapRegionSize() - 1, GetInteger(page_table.GetAliasCodeRegionStart()), - GetInteger(page_table.GetAliasCodeRegionStart()) + page_table.GetAliasCodeRegionSize() - - 1, + GetInteger(page_table.GetAliasCodeRegionStart()) + page_table.GetAliasCodeRegionSize() - 1, GetInteger(page_table.GetStackRegionStart()), GetInteger(page_table.GetStackRegionStart()) + page_table.GetStackRegionSize() - 1); @@ -657,7 +649,7 @@ void GDBStub::HandleRcmd(const std::vector& command) { reply += fmt::format(" {:#012x} - {:#012x} {}\n", vaddr, GetInteger(Core::GetModuleEnd(process, vaddr)), name); } - } else if (command_str == "get mappings") { + } else if (command_str == "mappings" || command_str == "get mappings") { reply = "Mappings:\n"; VAddr cur_addr = 0; @@ -675,15 +667,11 @@ void GDBStub::HandleRcmd(const std::vector& command) { std::numeric_limits::max()) { const char* state = GetMemoryStateName(svc_mem_info.state); const char* perm = GetMemoryPermissionString(svc_mem_info); - const char l = True(svc_mem_info.attribute & MemoryAttribute::Locked) ? 'L' : '-'; - const char i = - True(svc_mem_info.attribute & MemoryAttribute::IpcLocked) ? 'I' : '-'; - const char d = - True(svc_mem_info.attribute & MemoryAttribute::DeviceShared) ? 'D' : '-'; + const char i = True(svc_mem_info.attribute & MemoryAttribute::IpcLocked) ? 'I' : '-'; + const char d = True(svc_mem_info.attribute & MemoryAttribute::DeviceShared) ? 'D' : '-'; const char u = True(svc_mem_info.attribute & MemoryAttribute::Uncached) ? 'U' : '-'; - const char p = - True(svc_mem_info.attribute & MemoryAttribute::PermissionLocked) ? 'P' : '-'; + const char p =True(svc_mem_info.attribute & MemoryAttribute::PermissionLocked) ? 'P' : '-'; reply += fmt::format( " {:#012x} - {:#012x} {} {} {}{}{}{}{} [{}, {}]\n", svc_mem_info.base_address, @@ -698,11 +686,8 @@ void GDBStub::HandleRcmd(const std::vector& command) { cur_addr = next_address; } - } else if (command_str == "help") { - reply = commands; } else { - reply = "Unknown command.\n"; - reply += commands; + reply += "Commands: fastmem, info, mappings\n"; } std::span reply_span{reinterpret_cast(&reply.front()), reply.size()}; diff --git a/src/core/hardware_properties.h b/src/core/hardware_properties.h index 191c28bb46..3f870becbf 100644 --- a/src/core/hardware_properties.h +++ b/src/core/hardware_properties.h @@ -15,7 +15,7 @@ namespace Hardware { constexpr u64 BASE_CLOCK_RATE = 1'020'000'000; // Default CPU Frequency = 1020 MHz constexpr u64 CNTFREQ = 19'200'000; // CNTPCT_EL0 Frequency = 19.2 MHz -constexpr u32 NUM_CPU_CORES = 4; // Number of CPU Cores +constexpr u32 NUM_CPU_CORES = 4; // Number of CPU Cores - sync with dynarmic exclusive_monitor.h // Virtual to Physical core map. constexpr std::array()> VirtualToPhysicalCoreMap{ diff --git a/src/dynarmic/docs/ReturnStackBufferOptimization.md b/src/dynarmic/docs/ReturnStackBufferOptimization.md index e5298cad92..6ffe41bcc6 100644 --- a/src/dynarmic/docs/ReturnStackBufferOptimization.md +++ b/src/dynarmic/docs/ReturnStackBufferOptimization.md @@ -79,7 +79,7 @@ contain a prediction with the same `UniqueHash`. ? u64(unique_hash_to_code_ptr[imm64]) : u64(code->GetReturnFromRunCodeAddress()); - code->mov(index_reg, dword[r15 + offsetof(JitState, rsb_ptr)]); + code->mov(index_reg, dword[code.ABI_JIT_PTR + offsetof(JitState, rsb_ptr)]); code->add(index_reg, 1); code->and_(index_reg, u32(JitState::RSBSize - 1)); @@ -91,13 +91,13 @@ contain a prediction with the same `UniqueHash`. Xbyak::Label label; for (size_t i = 0; i < JitState::RSBSize; ++i) { - code->cmp(loc_desc_reg, qword[r15 + offsetof(JitState, rsb_location_descriptors) + i * sizeof(u64)]); + code->cmp(loc_desc_reg, qword[code.ABI_JIT_PTR + offsetof(JitState, rsb_location_descriptors) + i * sizeof(u64)]); code->je(label, code->T_SHORT); } - code->mov(dword[r15 + offsetof(JitState, rsb_ptr)], index_reg); - code->mov(qword[r15 + index_reg.cvt64() * 8 + offsetof(JitState, rsb_location_descriptors)], loc_desc_reg); - code->mov(qword[r15 + index_reg.cvt64() * 8 + offsetof(JitState, rsb_codeptrs)], code_ptr_reg); + code->mov(dword[code.ABI_JIT_PTR + offsetof(JitState, rsb_ptr)], index_reg); + code->mov(qword[code.ABI_JIT_PTR + index_reg.cvt64() * 8 + offsetof(JitState, rsb_location_descriptors)], loc_desc_reg); + code->mov(qword[code.ABI_JIT_PTR + index_reg.cvt64() * 8 + offsetof(JitState, rsb_codeptrs)], code_ptr_reg); code->L(label); } @@ -122,14 +122,14 @@ To check if a predicition is in the RSB, we linearly scan the RSB. // This calculation has to match up with IREmitter::PushRSB code->mov(ecx, MJitStateReg(Arm::Reg::PC)); code->shl(rcx, 32); - code->mov(ebx, dword[r15 + offsetof(JitState, FPSCR_mode)]); - code->or_(ebx, dword[r15 + offsetof(JitState, CPSR_et)]); + code->mov(ebx, dword[code.ABI_JIT_PTR + offsetof(JitState, FPSCR_mode)]); + code->or_(ebx, dword[code.ABI_JIT_PTR + offsetof(JitState, CPSR_et)]); code->or_(rbx, rcx); code->mov(rax, u64(code->GetReturnFromRunCodeAddress())); for (size_t i = 0; i < JitState::RSBSize; ++i) { - code->cmp(rbx, qword[r15 + offsetof(JitState, rsb_location_descriptors) + i * sizeof(u64)]); - code->cmove(rax, qword[r15 + offsetof(JitState, rsb_codeptrs) + i * sizeof(u64)]); + code->cmp(rbx, qword[code.ABI_JIT_PTR + offsetof(JitState, rsb_location_descriptors) + i * sizeof(u64)]); + code->cmove(rax, qword[code.ABI_JIT_PTR + offsetof(JitState, rsb_codeptrs) + i * sizeof(u64)]); } code->jmp(rax); diff --git a/src/dynarmic/src/dynarmic/backend/arm64/exclusive_monitor.cpp b/src/dynarmic/src/dynarmic/backend/arm64/exclusive_monitor.cpp index 326ab4ad00..b47167bf6f 100644 --- a/src/dynarmic/src/dynarmic/backend/arm64/exclusive_monitor.cpp +++ b/src/dynarmic/src/dynarmic/backend/arm64/exclusive_monitor.cpp @@ -14,7 +14,7 @@ namespace Dynarmic { -ExclusiveMonitor::ExclusiveMonitor(size_t processor_count) +ExclusiveMonitor::ExclusiveMonitor(std::size_t processor_count) : exclusive_addresses(processor_count, INVALID_EXCLUSIVE_ADDRESS), exclusive_values(processor_count) {} size_t ExclusiveMonitor::GetProcessorCount() const { diff --git a/src/dynarmic/src/dynarmic/backend/arm64/verbose_debugging_output.h b/src/dynarmic/src/dynarmic/backend/arm64/verbose_debugging_output.h index 84beda4057..b5187f6375 100644 --- a/src/dynarmic/src/dynarmic/backend/arm64/verbose_debugging_output.h +++ b/src/dynarmic/src/dynarmic/backend/arm64/verbose_debugging_output.h @@ -20,7 +20,7 @@ struct Label; } // namespace oaknut namespace Dynarmic::IR { -enum class Type; +enum class Type : u16; } // namespace Dynarmic::IR namespace Dynarmic::Backend::Arm64 { diff --git a/src/dynarmic/src/dynarmic/backend/x64/a32_emit_x64.cpp b/src/dynarmic/src/dynarmic/backend/x64/a32_emit_x64.cpp index 43e0750d68..fb306336cf 100644 --- a/src/dynarmic/src/dynarmic/backend/x64/a32_emit_x64.cpp +++ b/src/dynarmic/src/dynarmic/backend/x64/a32_emit_x64.cpp @@ -44,21 +44,21 @@ namespace Dynarmic::Backend::X64 { using namespace Xbyak::util; static Xbyak::Address MJitStateReg(A32::Reg reg) { - return dword[r15 + offsetof(A32JitState, Reg) + sizeof(u32) * static_cast(reg)]; + return dword[BlockOfCode::ABI_JIT_PTR + offsetof(A32JitState, Reg) + sizeof(u32) * static_cast(reg)]; } static Xbyak::Address MJitStateExtReg(A32::ExtReg reg) { if (A32::IsSingleExtReg(reg)) { const size_t index = static_cast(reg) - static_cast(A32::ExtReg::S0); - return dword[r15 + offsetof(A32JitState, ExtReg) + sizeof(u32) * index]; + return dword[BlockOfCode::ABI_JIT_PTR + offsetof(A32JitState, ExtReg) + sizeof(u32) * index]; } if (A32::IsDoubleExtReg(reg)) { const size_t index = static_cast(reg) - static_cast(A32::ExtReg::D0); - return qword[r15 + offsetof(A32JitState, ExtReg) + sizeof(u64) * index]; + return qword[BlockOfCode::ABI_JIT_PTR + offsetof(A32JitState, ExtReg) + sizeof(u64) * index]; } if (A32::IsQuadExtReg(reg)) { const size_t index = static_cast(reg) - static_cast(A32::ExtReg::Q0); - return xword[r15 + offsetof(A32JitState, ExtReg) + 2 * sizeof(u64) * index]; + return xword[BlockOfCode::ABI_JIT_PTR + offsetof(A32JitState, ExtReg) + 2 * sizeof(u64) * index]; } ASSERT_FALSE("Should never happen."); } @@ -109,12 +109,12 @@ A32EmitX64::BlockDescriptor A32EmitX64::Emit(IR::Block& block) { const boost::container::static_vector gpr_order = [this] { boost::container::static_vector gprs{any_gpr}; - if (conf.page_table) { - gprs.erase(std::find(gprs.begin(), gprs.end(), HostLoc::R14)); - } if (conf.fastmem_pointer) { gprs.erase(std::find(gprs.begin(), gprs.end(), HostLoc::R13)); } + if (conf.page_table) { + gprs.erase(std::find(gprs.begin(), gprs.end(), HostLoc::R14)); + } return gprs; }(); @@ -220,7 +220,7 @@ void A32EmitX64::GenTerminalHandlers() { // PC ends up in ebp, location_descriptor ends up in rbx const auto calculate_location_descriptor = [this] { // This calculation has to match up with IREmitter::PushRSB - code.mov(ebx, dword[r15 + offsetof(A32JitState, upper_location_descriptor)]); + code.mov(ebx, dword[code.ABI_JIT_PTR + offsetof(A32JitState, upper_location_descriptor)]); code.shl(rbx, 32); code.mov(ecx, MJitStateReg(A32::Reg::PC)); code.mov(ebp, ecx); @@ -232,17 +232,17 @@ void A32EmitX64::GenTerminalHandlers() { code.align(); terminal_handler_pop_rsb_hint = code.getCurr(); calculate_location_descriptor(); - code.mov(eax, dword[r15 + offsetof(A32JitState, rsb_ptr)]); - code.dec(eax); + code.mov(eax, dword[code.ABI_JIT_PTR + offsetof(A32JitState, rsb_ptr)]); + code.sub(eax, 1); code.and_(eax, u32(A32JitState::RSBPtrMask)); - code.mov(dword[r15 + offsetof(A32JitState, rsb_ptr)], eax); - code.cmp(rbx, qword[r15 + offsetof(A32JitState, rsb_location_descriptors) + rax * sizeof(u64)]); + code.mov(dword[code.ABI_JIT_PTR + offsetof(A32JitState, rsb_ptr)], eax); + code.cmp(rbx, qword[code.ABI_JIT_PTR + offsetof(A32JitState, rsb_location_descriptors) + rax * sizeof(u64)]); if (conf.HasOptimization(OptimizationFlag::FastDispatch)) { code.jne(rsb_cache_miss); } else { code.jne(code.GetReturnFromRunCodeAddress()); } - code.mov(rax, qword[r15 + offsetof(A32JitState, rsb_codeptrs) + rax * sizeof(u64)]); + code.mov(rax, qword[code.ABI_JIT_PTR + offsetof(A32JitState, rsb_codeptrs) + rax * sizeof(u64)]); code.jmp(rax); PerfMapRegister(terminal_handler_pop_rsb_hint, code.getCurr(), "a32_terminal_handler_pop_rsb_hint"); @@ -392,17 +392,17 @@ void A32EmitX64::EmitA32GetCpsr(A32EmitContext& ctx, IR::Inst* inst) { // so we load them both at the same time with one 64-bit read. This allows us to // extract all of their bits together at once with one pext. static_assert(offsetof(A32JitState, upper_location_descriptor) + 4 == offsetof(A32JitState, cpsr_ge)); - code.mov(result.cvt64(), qword[r15 + offsetof(A32JitState, upper_location_descriptor)]); + code.mov(result.cvt64(), qword[code.ABI_JIT_PTR + offsetof(A32JitState, upper_location_descriptor)]); code.mov(tmp.cvt64(), 0x80808080'00000003ull); code.pext(result.cvt64(), result.cvt64(), tmp.cvt64()); code.mov(tmp, 0x000f0220); code.pdep(result, result, tmp); } else { - code.mov(result, dword[r15 + offsetof(A32JitState, upper_location_descriptor)]); + code.mov(result, dword[code.ABI_JIT_PTR + offsetof(A32JitState, upper_location_descriptor)]); code.imul(result, result, 0x120); code.and_(result, 0x00000220); - code.mov(tmp, dword[r15 + offsetof(A32JitState, cpsr_ge)]); + code.mov(tmp, dword[code.ABI_JIT_PTR + offsetof(A32JitState, cpsr_ge)]); code.and_(tmp, 0x80808080); code.imul(tmp, tmp, 0x00204081); code.shr(tmp, 12); @@ -410,11 +410,11 @@ void A32EmitX64::EmitA32GetCpsr(A32EmitContext& ctx, IR::Inst* inst) { code.or_(result, tmp); } - code.mov(tmp, dword[r15 + offsetof(A32JitState, cpsr_q)]); + code.mov(tmp, dword[code.ABI_JIT_PTR + offsetof(A32JitState, cpsr_q)]); code.shl(tmp, 27); code.or_(result, tmp); - code.mov(tmp2, dword[r15 + offsetof(A32JitState, cpsr_nzcv)]); + code.mov(tmp2, dword[code.ABI_JIT_PTR + offsetof(A32JitState, cpsr_nzcv)]); if (code.HasHostFeature(HostFeature::FastBMI2)) { code.mov(tmp, NZCV::x64_mask); code.pext(tmp2, tmp2, tmp); @@ -426,7 +426,7 @@ void A32EmitX64::EmitA32GetCpsr(A32EmitContext& ctx, IR::Inst* inst) { } code.or_(result, tmp2); - code.or_(result, dword[r15 + offsetof(A32JitState, cpsr_jaifm)]); + code.or_(result, dword[code.ABI_JIT_PTR + offsetof(A32JitState, cpsr_jaifm)]); ctx.reg_alloc.DefineValue(inst, result); } @@ -444,7 +444,7 @@ void A32EmitX64::EmitA32SetCpsr(A32EmitContext& ctx, IR::Inst* inst) { // cpsr_q code.bt(cpsr, 27); - code.setc(code.byte[r15 + offsetof(A32JitState, cpsr_q)]); + code.setc(code.byte[code.ABI_JIT_PTR + offsetof(A32JitState, cpsr_q)]); // cpsr_nzcv code.mov(tmp, cpsr); @@ -456,12 +456,12 @@ void A32EmitX64::EmitA32SetCpsr(A32EmitContext& ctx, IR::Inst* inst) { code.imul(tmp, tmp, NZCV::to_x64_multiplier); code.and_(tmp, NZCV::x64_mask); } - code.mov(dword[r15 + offsetof(A32JitState, cpsr_nzcv)], tmp); + code.mov(dword[code.ABI_JIT_PTR + offsetof(A32JitState, cpsr_nzcv)], tmp); // cpsr_jaifm code.mov(tmp, cpsr); code.and_(tmp, 0x010001DF); - code.mov(dword[r15 + offsetof(A32JitState, cpsr_jaifm)], tmp); + code.mov(dword[code.ABI_JIT_PTR + offsetof(A32JitState, cpsr_jaifm)], tmp); if (code.HasHostFeature(HostFeature::FastBMI2)) { // cpsr_et and cpsr_ge @@ -469,7 +469,7 @@ void A32EmitX64::EmitA32SetCpsr(A32EmitContext& ctx, IR::Inst* inst) { // This mask is 0x7FFF0000, because we do not want the MSB to be sign extended to the upper dword. static_assert((A32::LocationDescriptor::FPSCR_MODE_MASK & ~0x7FFF0000) == 0); - code.and_(qword[r15 + offsetof(A32JitState, upper_location_descriptor)], u32(0x7FFF0000)); + code.and_(qword[code.ABI_JIT_PTR + offsetof(A32JitState, upper_location_descriptor)], u32(0x7FFF0000)); code.mov(tmp, 0x000f0220); code.pext(cpsr, cpsr, tmp); code.mov(tmp.cvt64(), 0x01010101'00000003ull); @@ -479,14 +479,14 @@ void A32EmitX64::EmitA32SetCpsr(A32EmitContext& ctx, IR::Inst* inst) { code.mov(tmp2.cvt64(), tmp.cvt64()); code.sub(tmp.cvt64(), cpsr.cvt64()); code.xor_(tmp.cvt64(), tmp2.cvt64()); - code.or_(qword[r15 + offsetof(A32JitState, upper_location_descriptor)], tmp.cvt64()); + code.or_(qword[code.ABI_JIT_PTR + offsetof(A32JitState, upper_location_descriptor)], tmp.cvt64()); } else { - code.and_(dword[r15 + offsetof(A32JitState, upper_location_descriptor)], u32(0xFFFF0000)); + code.and_(dword[code.ABI_JIT_PTR + offsetof(A32JitState, upper_location_descriptor)], u32(0xFFFF0000)); code.mov(tmp, cpsr); code.and_(tmp, 0x00000220); code.imul(tmp, tmp, 0x00900000); code.shr(tmp, 28); - code.or_(dword[r15 + offsetof(A32JitState, upper_location_descriptor)], tmp); + code.or_(dword[code.ABI_JIT_PTR + offsetof(A32JitState, upper_location_descriptor)], tmp); code.and_(cpsr, 0x000f0000); code.shr(cpsr, 16); @@ -495,14 +495,14 @@ void A32EmitX64::EmitA32SetCpsr(A32EmitContext& ctx, IR::Inst* inst) { code.mov(tmp, 0x80808080); code.sub(tmp, cpsr); code.xor_(tmp, 0x80808080); - code.mov(dword[r15 + offsetof(A32JitState, cpsr_ge)], tmp); + code.mov(dword[code.ABI_JIT_PTR + offsetof(A32JitState, cpsr_ge)], tmp); } } void A32EmitX64::EmitA32SetCpsrNZCV(A32EmitContext& ctx, IR::Inst* inst) { auto args = ctx.reg_alloc.GetArgumentInfo(inst); const Xbyak::Reg32 to_store = ctx.reg_alloc.UseScratchGpr(args[0]).cvt32(); - code.mov(dword[r15 + offsetof(A32JitState, cpsr_nzcv)], to_store); + code.mov(dword[code.ABI_JIT_PTR + offsetof(A32JitState, cpsr_nzcv)], to_store); } void A32EmitX64::EmitA32SetCpsrNZCVRaw(A32EmitContext& ctx, IR::Inst* inst) { @@ -510,7 +510,7 @@ void A32EmitX64::EmitA32SetCpsrNZCVRaw(A32EmitContext& ctx, IR::Inst* inst) { if (args[0].IsImmediate()) { const u32 imm = args[0].GetImmediateU32(); - code.mov(dword[r15 + offsetof(A32JitState, cpsr_nzcv)], NZCV::ToX64(imm)); + code.mov(dword[code.ABI_JIT_PTR + offsetof(A32JitState, cpsr_nzcv)], NZCV::ToX64(imm)); } else if (code.HasHostFeature(HostFeature::FastBMI2)) { const Xbyak::Reg32 a = ctx.reg_alloc.UseScratchGpr(args[0]).cvt32(); const Xbyak::Reg32 b = ctx.reg_alloc.ScratchGpr().cvt32(); @@ -518,14 +518,14 @@ void A32EmitX64::EmitA32SetCpsrNZCVRaw(A32EmitContext& ctx, IR::Inst* inst) { code.shr(a, 28); code.mov(b, NZCV::x64_mask); code.pdep(a, a, b); - code.mov(dword[r15 + offsetof(A32JitState, cpsr_nzcv)], a); + code.mov(dword[code.ABI_JIT_PTR + offsetof(A32JitState, cpsr_nzcv)], a); } else { const Xbyak::Reg32 a = ctx.reg_alloc.UseScratchGpr(args[0]).cvt32(); code.shr(a, 28); code.imul(a, a, NZCV::to_x64_multiplier); code.and_(a, NZCV::x64_mask); - code.mov(dword[r15 + offsetof(A32JitState, cpsr_nzcv)], a); + code.mov(dword[code.ABI_JIT_PTR + offsetof(A32JitState, cpsr_nzcv)], a); } } @@ -534,25 +534,25 @@ void A32EmitX64::EmitA32SetCpsrNZCVQ(A32EmitContext& ctx, IR::Inst* inst) { if (args[0].IsImmediate()) { const u32 imm = args[0].GetImmediateU32(); - code.mov(dword[r15 + offsetof(A32JitState, cpsr_nzcv)], NZCV::ToX64(imm)); - code.mov(code.byte[r15 + offsetof(A32JitState, cpsr_q)], u8((imm & 0x08000000) != 0 ? 1 : 0)); + code.mov(dword[code.ABI_JIT_PTR + offsetof(A32JitState, cpsr_nzcv)], NZCV::ToX64(imm)); + code.mov(code.byte[code.ABI_JIT_PTR + offsetof(A32JitState, cpsr_q)], u8((imm & 0x08000000) != 0 ? 1 : 0)); } else if (code.HasHostFeature(HostFeature::FastBMI2)) { const Xbyak::Reg32 a = ctx.reg_alloc.UseScratchGpr(args[0]).cvt32(); const Xbyak::Reg32 b = ctx.reg_alloc.ScratchGpr().cvt32(); code.shr(a, 28); - code.setc(code.byte[r15 + offsetof(A32JitState, cpsr_q)]); + code.setc(code.byte[code.ABI_JIT_PTR + offsetof(A32JitState, cpsr_q)]); code.mov(b, NZCV::x64_mask); code.pdep(a, a, b); - code.mov(dword[r15 + offsetof(A32JitState, cpsr_nzcv)], a); + code.mov(dword[code.ABI_JIT_PTR + offsetof(A32JitState, cpsr_nzcv)], a); } else { const Xbyak::Reg32 a = ctx.reg_alloc.UseScratchGpr(args[0]).cvt32(); code.shr(a, 28); - code.setc(code.byte[r15 + offsetof(A32JitState, cpsr_q)]); + code.setc(code.byte[code.ABI_JIT_PTR + offsetof(A32JitState, cpsr_q)]); code.imul(a, a, NZCV::to_x64_multiplier); code.and_(a, NZCV::x64_mask); - code.mov(dword[r15 + offsetof(A32JitState, cpsr_nzcv)], a); + code.mov(dword[code.ABI_JIT_PTR + offsetof(A32JitState, cpsr_nzcv)], a); } } @@ -562,10 +562,10 @@ void A32EmitX64::EmitA32SetCpsrNZ(A32EmitContext& ctx, IR::Inst* inst) { const Xbyak::Reg32 nz = ctx.reg_alloc.UseGpr(args[0]).cvt32(); const Xbyak::Reg32 tmp = ctx.reg_alloc.ScratchGpr().cvt32(); - code.movzx(tmp, code.byte[r15 + offsetof(A32JitState, cpsr_nzcv) + 1]); + code.movzx(tmp, code.byte[code.ABI_JIT_PTR + offsetof(A32JitState, cpsr_nzcv) + 1]); code.and_(tmp, 1); code.or_(tmp, nz); - code.mov(code.byte[r15 + offsetof(A32JitState, cpsr_nzcv) + 1], tmp.cvt8()); + code.mov(code.byte[code.ABI_JIT_PTR + offsetof(A32JitState, cpsr_nzcv) + 1], tmp.cvt8()); } void A32EmitX64::EmitA32SetCpsrNZC(A32EmitContext& ctx, IR::Inst* inst) { @@ -575,11 +575,11 @@ void A32EmitX64::EmitA32SetCpsrNZC(A32EmitContext& ctx, IR::Inst* inst) { if (args[1].IsImmediate()) { const bool c = args[1].GetImmediateU1(); - code.mov(code.byte[r15 + offsetof(A32JitState, cpsr_nzcv) + 1], c); + code.mov(code.byte[code.ABI_JIT_PTR + offsetof(A32JitState, cpsr_nzcv) + 1], c); } else { const Xbyak::Reg8 c = ctx.reg_alloc.UseGpr(args[1]).cvt8(); - code.mov(code.byte[r15 + offsetof(A32JitState, cpsr_nzcv) + 1], c); + code.mov(code.byte[code.ABI_JIT_PTR + offsetof(A32JitState, cpsr_nzcv) + 1], c); } } else { const Xbyak::Reg32 nz = ctx.reg_alloc.UseScratchGpr(args[0]).cvt32(); @@ -588,19 +588,19 @@ void A32EmitX64::EmitA32SetCpsrNZC(A32EmitContext& ctx, IR::Inst* inst) { const bool c = args[1].GetImmediateU1(); code.or_(nz, c); - code.mov(code.byte[r15 + offsetof(A32JitState, cpsr_nzcv) + 1], nz.cvt8()); + code.mov(code.byte[code.ABI_JIT_PTR + offsetof(A32JitState, cpsr_nzcv) + 1], nz.cvt8()); } else { const Xbyak::Reg32 c = ctx.reg_alloc.UseGpr(args[1]).cvt32(); code.or_(nz, c); - code.mov(code.byte[r15 + offsetof(A32JitState, cpsr_nzcv) + 1], nz.cvt8()); + code.mov(code.byte[code.ABI_JIT_PTR + offsetof(A32JitState, cpsr_nzcv) + 1], nz.cvt8()); } } } static void EmitGetFlag(BlockOfCode& code, A32EmitContext& ctx, IR::Inst* inst, size_t flag_bit) { const Xbyak::Reg32 result = ctx.reg_alloc.ScratchGpr().cvt32(); - code.mov(result, dword[r15 + offsetof(A32JitState, cpsr_nzcv)]); + code.mov(result, dword[code.ABI_JIT_PTR + offsetof(A32JitState, cpsr_nzcv)]); if (flag_bit != 0) { code.shr(result, static_cast(flag_bit)); } @@ -616,18 +616,18 @@ void A32EmitX64::EmitA32OrQFlag(A32EmitContext& ctx, IR::Inst* inst) { auto args = ctx.reg_alloc.GetArgumentInfo(inst); if (args[0].IsImmediate()) { if (args[0].GetImmediateU1()) { - code.mov(dword[r15 + offsetof(A32JitState, cpsr_q)], 1); + code.mov(dword[code.ABI_JIT_PTR + offsetof(A32JitState, cpsr_q)], 1); } } else { const Xbyak::Reg8 to_store = ctx.reg_alloc.UseGpr(args[0]).cvt8(); - code.or_(code.byte[r15 + offsetof(A32JitState, cpsr_q)], to_store); + code.or_(code.byte[code.ABI_JIT_PTR + offsetof(A32JitState, cpsr_q)], to_store); } } void A32EmitX64::EmitA32GetGEFlags(A32EmitContext& ctx, IR::Inst* inst) { const Xbyak::Xmm result = ctx.reg_alloc.ScratchXmm(); - code.movd(result, dword[r15 + offsetof(A32JitState, cpsr_ge)]); + code.movd(result, dword[code.ABI_JIT_PTR + offsetof(A32JitState, cpsr_ge)]); ctx.reg_alloc.DefineValue(inst, result); } @@ -637,10 +637,10 @@ void A32EmitX64::EmitA32SetGEFlags(A32EmitContext& ctx, IR::Inst* inst) { if (args[0].IsInXmm()) { const Xbyak::Xmm to_store = ctx.reg_alloc.UseXmm(args[0]); - code.movd(dword[r15 + offsetof(A32JitState, cpsr_ge)], to_store); + code.movd(dword[code.ABI_JIT_PTR + offsetof(A32JitState, cpsr_ge)], to_store); } else { const Xbyak::Reg32 to_store = ctx.reg_alloc.UseGpr(args[0]).cvt32(); - code.mov(dword[r15 + offsetof(A32JitState, cpsr_ge)], to_store); + code.mov(dword[code.ABI_JIT_PTR + offsetof(A32JitState, cpsr_ge)], to_store); } } @@ -654,7 +654,7 @@ void A32EmitX64::EmitA32SetGEFlagsCompressed(A32EmitContext& ctx, IR::Inst* inst ge |= mcl::bit::get_bit<17>(imm) ? 0x0000FF00 : 0; ge |= mcl::bit::get_bit<16>(imm) ? 0x000000FF : 0; - code.mov(dword[r15 + offsetof(A32JitState, cpsr_ge)], ge); + code.mov(dword[code.ABI_JIT_PTR + offsetof(A32JitState, cpsr_ge)], ge); } else if (code.HasHostFeature(HostFeature::FastBMI2)) { const Xbyak::Reg32 a = ctx.reg_alloc.UseScratchGpr(args[0]).cvt32(); const Xbyak::Reg32 b = ctx.reg_alloc.ScratchGpr().cvt32(); @@ -663,7 +663,7 @@ void A32EmitX64::EmitA32SetGEFlagsCompressed(A32EmitContext& ctx, IR::Inst* inst code.shr(a, 16); code.pdep(a, a, b); code.imul(a, a, 0xFF); - code.mov(dword[r15 + offsetof(A32JitState, cpsr_ge)], a); + code.mov(dword[code.ABI_JIT_PTR + offsetof(A32JitState, cpsr_ge)], a); } else { const Xbyak::Reg32 a = ctx.reg_alloc.UseScratchGpr(args[0]).cvt32(); @@ -672,7 +672,7 @@ void A32EmitX64::EmitA32SetGEFlagsCompressed(A32EmitContext& ctx, IR::Inst* inst code.imul(a, a, 0x00204081); code.and_(a, 0x01010101); code.imul(a, a, 0xFF); - code.mov(dword[r15 + offsetof(A32JitState, cpsr_ge)], a); + code.mov(dword[code.ABI_JIT_PTR + offsetof(A32JitState, cpsr_ge)], a); } } @@ -716,7 +716,7 @@ void A32EmitX64::EmitA32BXWritePC(A32EmitContext& ctx, IR::Inst* inst) { const u32 new_upper = upper_without_t | (mcl::bit::get_bit<0>(new_pc) ? 1 : 0); code.mov(MJitStateReg(A32::Reg::PC), new_pc & mask); - code.mov(dword[r15 + offsetof(A32JitState, upper_location_descriptor)], new_upper); + code.mov(dword[code.ABI_JIT_PTR + offsetof(A32JitState, upper_location_descriptor)], new_upper); } else { const Xbyak::Reg32 new_pc = ctx.reg_alloc.UseScratchGpr(arg).cvt32(); const Xbyak::Reg32 mask = ctx.reg_alloc.ScratchGpr().cvt32(); @@ -728,7 +728,7 @@ void A32EmitX64::EmitA32BXWritePC(A32EmitContext& ctx, IR::Inst* inst) { code.lea(mask, ptr[mask.cvt64() + mask.cvt64() * 1 - 4]); // mask = pc & 1 ? 0xFFFFFFFE : 0xFFFFFFFC code.and_(new_pc, mask); code.mov(MJitStateReg(A32::Reg::PC), new_pc); - code.mov(dword[r15 + offsetof(A32JitState, upper_location_descriptor)], new_upper); + code.mov(dword[code.ABI_JIT_PTR + offsetof(A32JitState, upper_location_descriptor)], new_upper); } } @@ -798,9 +798,9 @@ static u32 GetFpscrImpl(A32JitState* jit_state) { void A32EmitX64::EmitA32GetFpscr(A32EmitContext& ctx, IR::Inst* inst) { ctx.reg_alloc.HostCall(inst); - code.mov(code.ABI_PARAM1, code.r15); + code.mov(code.ABI_PARAM1, code.ABI_JIT_PTR); - code.stmxcsr(code.dword[code.r15 + offsetof(A32JitState, guest_MXCSR)]); + code.stmxcsr(code.dword[code.ABI_JIT_PTR + offsetof(A32JitState, guest_MXCSR)]); code.CallFunction(&GetFpscrImpl); } @@ -811,15 +811,15 @@ static void SetFpscrImpl(u32 value, A32JitState* jit_state) { void A32EmitX64::EmitA32SetFpscr(A32EmitContext& ctx, IR::Inst* inst) { auto args = ctx.reg_alloc.GetArgumentInfo(inst); ctx.reg_alloc.HostCall(nullptr, args[0]); - code.mov(code.ABI_PARAM2, code.r15); + code.mov(code.ABI_PARAM2, code.ABI_JIT_PTR); code.CallFunction(&SetFpscrImpl); - code.ldmxcsr(code.dword[code.r15 + offsetof(A32JitState, guest_MXCSR)]); + code.ldmxcsr(code.dword[code.ABI_JIT_PTR + offsetof(A32JitState, guest_MXCSR)]); } void A32EmitX64::EmitA32GetFpscrNZCV(A32EmitContext& ctx, IR::Inst* inst) { const Xbyak::Reg32 result = ctx.reg_alloc.ScratchGpr().cvt32(); - code.mov(result, dword[r15 + offsetof(A32JitState, fpsr_nzcv)]); + code.mov(result, dword[code.ABI_JIT_PTR + offsetof(A32JitState, fpsr_nzcv)]); ctx.reg_alloc.DefineValue(inst, result); } @@ -833,7 +833,7 @@ void A32EmitX64::EmitA32SetFpscrNZCV(A32EmitContext& ctx, IR::Inst* inst) { code.mov(tmp, NZCV::x64_mask); code.pext(tmp, value, tmp); code.shl(tmp, 28); - code.mov(dword[r15 + offsetof(A32JitState, fpsr_nzcv)], tmp); + code.mov(dword[code.ABI_JIT_PTR + offsetof(A32JitState, fpsr_nzcv)], tmp); return; } @@ -843,7 +843,7 @@ void A32EmitX64::EmitA32SetFpscrNZCV(A32EmitContext& ctx, IR::Inst* inst) { code.and_(value, NZCV::x64_mask); code.imul(value, value, NZCV::from_x64_multiplier); code.and_(value, NZCV::arm_mask); - code.mov(dword[r15 + offsetof(A32JitState, fpsr_nzcv)], value); + code.mov(dword[code.ABI_JIT_PTR + offsetof(A32JitState, fpsr_nzcv)], value); } static void EmitCoprocessorException() { @@ -1155,7 +1155,7 @@ void A32EmitX64::EmitSetUpperLocationDescriptor(IR::LocationDescriptor new_locat }(); if (old_upper != new_upper) { - code.mov(dword[r15 + offsetof(A32JitState, upper_location_descriptor)], new_upper); + code.mov(dword[code.ABI_JIT_PTR + offsetof(A32JitState, upper_location_descriptor)], new_upper); } } @@ -1165,32 +1165,28 @@ void A32EmitX64::EmitTerminalImpl(IR::Term::LinkBlock terminal, IR::LocationDesc if (!conf.HasOptimization(OptimizationFlag::BlockLinking) || is_single_step) { code.mov(MJitStateReg(A32::Reg::PC), A32::LocationDescriptor{terminal.next}.PC()); code.ReturnFromRunCode(); - return; - } - - if (conf.enable_cycle_counting) { - code.cmp(qword[rsp + ABI_SHADOW_SPACE + offsetof(StackLayout, cycles_remaining)], 0); - - patch_information[terminal.next].jg.push_back(code.getCurr()); - if (const auto next_bb = GetBasicBlock(terminal.next)) { - EmitPatchJg(terminal.next, next_bb->entrypoint); - } else { - EmitPatchJg(terminal.next); - } } else { - code.cmp(dword[r15 + offsetof(A32JitState, halt_reason)], 0); - - patch_information[terminal.next].jz.push_back(code.getCurr()); - if (const auto next_bb = GetBasicBlock(terminal.next)) { - EmitPatchJz(terminal.next, next_bb->entrypoint); + if (conf.enable_cycle_counting) { + code.cmp(qword[rsp + ABI_SHADOW_SPACE + offsetof(StackLayout, cycles_remaining)], 0); + patch_information[terminal.next].jg.push_back(code.getCurr()); + if (const auto next_bb = GetBasicBlock(terminal.next)) { + EmitPatchJg(terminal.next, next_bb->entrypoint); + } else { + EmitPatchJg(terminal.next); + } } else { - EmitPatchJz(terminal.next); + code.cmp(dword[code.ABI_JIT_PTR + offsetof(A32JitState, halt_reason)], 0); + patch_information[terminal.next].jz.push_back(code.getCurr()); + if (const auto next_bb = GetBasicBlock(terminal.next)) { + EmitPatchJz(terminal.next, next_bb->entrypoint); + } else { + EmitPatchJz(terminal.next); + } } + code.mov(MJitStateReg(A32::Reg::PC), A32::LocationDescriptor{terminal.next}.PC()); + PushRSBHelper(rax, rbx, terminal.next); + code.ForceReturnFromRunCode(); } - - code.mov(MJitStateReg(A32::Reg::PC), A32::LocationDescriptor{terminal.next}.PC()); - PushRSBHelper(rax, rbx, terminal.next); - code.ForceReturnFromRunCode(); } void A32EmitX64::EmitTerminalImpl(IR::Term::LinkBlockFast terminal, IR::LocationDescriptor initial_location, bool is_single_step) { @@ -1199,14 +1195,13 @@ void A32EmitX64::EmitTerminalImpl(IR::Term::LinkBlockFast terminal, IR::Location if (!conf.HasOptimization(OptimizationFlag::BlockLinking) || is_single_step) { code.mov(MJitStateReg(A32::Reg::PC), A32::LocationDescriptor{terminal.next}.PC()); code.ReturnFromRunCode(); - return; - } - - patch_information[terminal.next].jmp.push_back(code.getCurr()); - if (const auto next_bb = GetBasicBlock(terminal.next)) { - EmitPatchJmp(terminal.next, next_bb->entrypoint); } else { - EmitPatchJmp(terminal.next); + patch_information[terminal.next].jmp.push_back(code.getCurr()); + if (const auto next_bb = GetBasicBlock(terminal.next)) { + EmitPatchJmp(terminal.next, next_bb->entrypoint); + } else { + EmitPatchJmp(terminal.next); + } } } @@ -1245,7 +1240,7 @@ void A32EmitX64::EmitTerminalImpl(IR::Term::CheckBit terminal, IR::LocationDescr } void A32EmitX64::EmitTerminalImpl(IR::Term::CheckHalt terminal, IR::LocationDescriptor initial_location, bool is_single_step) { - code.cmp(dword[r15 + offsetof(A32JitState, halt_reason)], 0); + code.cmp(dword[code.ABI_JIT_PTR + offsetof(A32JitState, halt_reason)], 0); code.jne(code.GetForceReturnFromRunCodeAddress()); EmitTerminal(terminal.else_, initial_location, is_single_step); } diff --git a/src/dynarmic/src/dynarmic/backend/x64/a32_emit_x64_memory.cpp b/src/dynarmic/src/dynarmic/backend/x64/a32_emit_x64_memory.cpp index f2919485be..a1fca21f47 100644 --- a/src/dynarmic/src/dynarmic/backend/x64/a32_emit_x64_memory.cpp +++ b/src/dynarmic/src/dynarmic/backend/x64/a32_emit_x64_memory.cpp @@ -168,7 +168,7 @@ void A32EmitX64::EmitA32WriteMemory64(A32EmitContext& ctx, IR::Inst* inst) { } void A32EmitX64::EmitA32ClearExclusive(A32EmitContext&, IR::Inst*) { - code.mov(code.byte[r15 + offsetof(A32JitState, exclusive_state)], u8(0)); + code.mov(code.byte[code.ABI_JIT_PTR + offsetof(A32JitState, exclusive_state)], u8(0)); } void A32EmitX64::EmitA32ExclusiveReadMemory8(A32EmitContext& ctx, IR::Inst* inst) { @@ -244,14 +244,14 @@ void A32EmitX64::EmitCheckMemoryAbort(A32EmitContext& ctx, IR::Inst* inst, Xbyak const A32::LocationDescriptor current_location{IR::LocationDescriptor{inst->GetArg(0).GetU64()}}; - code.test(dword[r15 + offsetof(A32JitState, halt_reason)], static_cast(HaltReason::MemoryAbort)); + code.test(dword[code.ABI_JIT_PTR + offsetof(A32JitState, halt_reason)], static_cast(HaltReason::MemoryAbort)); if (end) { code.jz(*end, code.T_NEAR); } else { code.jz(skip, code.T_NEAR); } EmitSetUpperLocationDescriptor(current_location, ctx.Location()); - code.mov(dword[r15 + offsetof(A32JitState, Reg) + sizeof(u32) * 15], current_location.PC()); + code.mov(dword[code.ABI_JIT_PTR + offsetof(A32JitState, Reg) + sizeof(u32) * 15], current_location.PC()); code.ForceReturnFromRunCode(); code.L(skip); } diff --git a/src/dynarmic/src/dynarmic/backend/x64/a64_emit_x64.cpp b/src/dynarmic/src/dynarmic/backend/x64/a64_emit_x64.cpp index 47a2236a87..1e673338a8 100644 --- a/src/dynarmic/src/dynarmic/backend/x64/a64_emit_x64.cpp +++ b/src/dynarmic/src/dynarmic/backend/x64/a64_emit_x64.cpp @@ -80,12 +80,12 @@ A64EmitX64::BlockDescriptor A64EmitX64::Emit(IR::Block& block) noexcept { const boost::container::static_vector gpr_order = [this] { boost::container::static_vector gprs{any_gpr}; - if (conf.page_table) { - gprs.erase(std::find(gprs.begin(), gprs.end(), HostLoc::R14)); - } if (conf.fastmem_pointer) { gprs.erase(std::find(gprs.begin(), gprs.end(), HostLoc::R13)); } + if (conf.page_table) { + gprs.erase(std::find(gprs.begin(), gprs.end(), HostLoc::R14)); + } return gprs; }(); @@ -192,10 +192,10 @@ void A64EmitX64::GenTerminalHandlers() { const auto calculate_location_descriptor = [this] { // This calculation has to match up with A64::LocationDescriptor::UniqueHash // TODO: Optimization is available here based on known state of fpcr. - code.mov(rbp, qword[r15 + offsetof(A64JitState, pc)]); + code.mov(rbp, qword[code.ABI_JIT_PTR + offsetof(A64JitState, pc)]); code.mov(rcx, A64::LocationDescriptor::pc_mask); code.and_(rcx, rbp); - code.mov(ebx, dword[r15 + offsetof(A64JitState, fpcr)]); + code.mov(ebx, dword[code.ABI_JIT_PTR + offsetof(A64JitState, fpcr)]); code.and_(ebx, A64::LocationDescriptor::fpcr_mask); code.shl(rbx, A64::LocationDescriptor::fpcr_shift); code.or_(rbx, rcx); @@ -207,17 +207,17 @@ void A64EmitX64::GenTerminalHandlers() { code.align(); terminal_handler_pop_rsb_hint = code.getCurr(); calculate_location_descriptor(); - code.mov(eax, dword[r15 + offsetof(A64JitState, rsb_ptr)]); - code.dec(eax); + code.mov(eax, dword[code.ABI_JIT_PTR + offsetof(A64JitState, rsb_ptr)]); + code.sub(eax, 1); code.and_(eax, u32(A64JitState::RSBPtrMask)); - code.mov(dword[r15 + offsetof(A64JitState, rsb_ptr)], eax); - code.cmp(rbx, qword[r15 + offsetof(A64JitState, rsb_location_descriptors) + rax * sizeof(u64)]); + code.mov(dword[code.ABI_JIT_PTR + offsetof(A64JitState, rsb_ptr)], eax); + code.cmp(rbx, qword[code.ABI_JIT_PTR + offsetof(A64JitState, rsb_location_descriptors) + rax * sizeof(u64)]); if (conf.HasOptimization(OptimizationFlag::FastDispatch)) { code.jne(rsb_cache_miss, code.T_NEAR); } else { code.jne(code.GetReturnFromRunCodeAddress()); } - code.mov(rax, qword[r15 + offsetof(A64JitState, rsb_codeptrs) + rax * sizeof(u64)]); + code.mov(rax, qword[code.ABI_JIT_PTR + offsetof(A64JitState, rsb_codeptrs) + rax * sizeof(u64)]); code.jmp(rax); PerfMapRegister(terminal_handler_pop_rsb_hint, code.getCurr(), "a64_terminal_handler_pop_rsb_hint"); @@ -272,7 +272,7 @@ void A64EmitX64::EmitA64SetCheckBit(A64EmitContext& ctx, IR::Inst* inst) { void A64EmitX64::EmitA64GetCFlag(A64EmitContext& ctx, IR::Inst* inst) { const Xbyak::Reg32 result = ctx.reg_alloc.ScratchGpr().cvt32(); - code.mov(result, dword[r15 + offsetof(A64JitState, cpsr_nzcv)]); + code.mov(result, dword[code.ABI_JIT_PTR + offsetof(A64JitState, cpsr_nzcv)]); code.shr(result, NZCV::x64_c_flag_bit); code.and_(result, 1); ctx.reg_alloc.DefineValue(inst, result); @@ -281,7 +281,7 @@ void A64EmitX64::EmitA64GetCFlag(A64EmitContext& ctx, IR::Inst* inst) { void A64EmitX64::EmitA64GetNZCVRaw(A64EmitContext& ctx, IR::Inst* inst) { const Xbyak::Reg32 nzcv_raw = ctx.reg_alloc.ScratchGpr().cvt32(); - code.mov(nzcv_raw, dword[r15 + offsetof(A64JitState, cpsr_nzcv)]); + code.mov(nzcv_raw, dword[code.ABI_JIT_PTR + offsetof(A64JitState, cpsr_nzcv)]); if (code.HasHostFeature(HostFeature::FastBMI2)) { const Xbyak::Reg32 tmp = ctx.reg_alloc.ScratchGpr().cvt32(); @@ -310,20 +310,20 @@ void A64EmitX64::EmitA64SetNZCVRaw(A64EmitContext& ctx, IR::Inst* inst) { code.imul(nzcv_raw, nzcv_raw, NZCV::to_x64_multiplier); code.and_(nzcv_raw, NZCV::x64_mask); } - code.mov(dword[r15 + offsetof(A64JitState, cpsr_nzcv)], nzcv_raw); + code.mov(dword[code.ABI_JIT_PTR + offsetof(A64JitState, cpsr_nzcv)], nzcv_raw); } void A64EmitX64::EmitA64SetNZCV(A64EmitContext& ctx, IR::Inst* inst) { auto args = ctx.reg_alloc.GetArgumentInfo(inst); const Xbyak::Reg32 to_store = ctx.reg_alloc.UseScratchGpr(args[0]).cvt32(); - code.mov(dword[r15 + offsetof(A64JitState, cpsr_nzcv)], to_store); + code.mov(dword[code.ABI_JIT_PTR + offsetof(A64JitState, cpsr_nzcv)], to_store); } void A64EmitX64::EmitA64GetW(A64EmitContext& ctx, IR::Inst* inst) { const A64::Reg reg = inst->GetArg(0).GetA64RegRef(); const Xbyak::Reg32 result = ctx.reg_alloc.ScratchGpr().cvt32(); - code.mov(result, dword[r15 + offsetof(A64JitState, reg) + sizeof(u64) * static_cast(reg)]); + code.mov(result, dword[code.ABI_JIT_PTR + offsetof(A64JitState, reg) + sizeof(u64) * static_cast(reg)]); ctx.reg_alloc.DefineValue(inst, result); } @@ -331,13 +331,13 @@ void A64EmitX64::EmitA64GetX(A64EmitContext& ctx, IR::Inst* inst) { const A64::Reg reg = inst->GetArg(0).GetA64RegRef(); const Xbyak::Reg64 result = ctx.reg_alloc.ScratchGpr(); - code.mov(result, qword[r15 + offsetof(A64JitState, reg) + sizeof(u64) * static_cast(reg)]); + code.mov(result, qword[code.ABI_JIT_PTR + offsetof(A64JitState, reg) + sizeof(u64) * static_cast(reg)]); ctx.reg_alloc.DefineValue(inst, result); } void A64EmitX64::EmitA64GetS(A64EmitContext& ctx, IR::Inst* inst) { const A64::Vec vec = inst->GetArg(0).GetA64VecRef(); - const auto addr = qword[r15 + offsetof(A64JitState, vec) + sizeof(u64) * 2 * static_cast(vec)]; + const auto addr = qword[code.ABI_JIT_PTR + offsetof(A64JitState, vec) + sizeof(u64) * 2 * static_cast(vec)]; const Xbyak::Xmm result = ctx.reg_alloc.ScratchXmm(); code.movd(result, addr); @@ -346,7 +346,7 @@ void A64EmitX64::EmitA64GetS(A64EmitContext& ctx, IR::Inst* inst) { void A64EmitX64::EmitA64GetD(A64EmitContext& ctx, IR::Inst* inst) { const A64::Vec vec = inst->GetArg(0).GetA64VecRef(); - const auto addr = qword[r15 + offsetof(A64JitState, vec) + sizeof(u64) * 2 * static_cast(vec)]; + const auto addr = qword[code.ABI_JIT_PTR + offsetof(A64JitState, vec) + sizeof(u64) * 2 * static_cast(vec)]; const Xbyak::Xmm result = ctx.reg_alloc.ScratchXmm(); code.movq(result, addr); @@ -355,7 +355,7 @@ void A64EmitX64::EmitA64GetD(A64EmitContext& ctx, IR::Inst* inst) { void A64EmitX64::EmitA64GetQ(A64EmitContext& ctx, IR::Inst* inst) { const A64::Vec vec = inst->GetArg(0).GetA64VecRef(); - const auto addr = xword[r15 + offsetof(A64JitState, vec) + sizeof(u64) * 2 * static_cast(vec)]; + const auto addr = xword[code.ABI_JIT_PTR + offsetof(A64JitState, vec) + sizeof(u64) * 2 * static_cast(vec)]; const Xbyak::Xmm result = ctx.reg_alloc.ScratchXmm(); code.movaps(result, addr); @@ -364,13 +364,13 @@ void A64EmitX64::EmitA64GetQ(A64EmitContext& ctx, IR::Inst* inst) { void A64EmitX64::EmitA64GetSP(A64EmitContext& ctx, IR::Inst* inst) { const Xbyak::Reg64 result = ctx.reg_alloc.ScratchGpr(); - code.mov(result, qword[r15 + offsetof(A64JitState, sp)]); + code.mov(result, qword[code.ABI_JIT_PTR + offsetof(A64JitState, sp)]); ctx.reg_alloc.DefineValue(inst, result); } void A64EmitX64::EmitA64GetFPCR(A64EmitContext& ctx, IR::Inst* inst) { const Xbyak::Reg32 result = ctx.reg_alloc.ScratchGpr().cvt32(); - code.mov(result, dword[r15 + offsetof(A64JitState, fpcr)]); + code.mov(result, dword[code.ABI_JIT_PTR + offsetof(A64JitState, fpcr)]); ctx.reg_alloc.DefineValue(inst, result); } @@ -380,15 +380,15 @@ static u32 GetFPSRImpl(A64JitState* jit_state) { void A64EmitX64::EmitA64GetFPSR(A64EmitContext& ctx, IR::Inst* inst) { ctx.reg_alloc.HostCall(inst); - code.mov(code.ABI_PARAM1, code.r15); - code.stmxcsr(code.dword[code.r15 + offsetof(A64JitState, guest_MXCSR)]); + code.mov(code.ABI_PARAM1, code.ABI_JIT_PTR); + code.stmxcsr(code.dword[code.ABI_JIT_PTR + offsetof(A64JitState, guest_MXCSR)]); code.CallFunction(GetFPSRImpl); } void A64EmitX64::EmitA64SetW(A64EmitContext& ctx, IR::Inst* inst) { auto args = ctx.reg_alloc.GetArgumentInfo(inst); const A64::Reg reg = inst->GetArg(0).GetA64RegRef(); - const auto addr = qword[r15 + offsetof(A64JitState, reg) + sizeof(u64) * static_cast(reg)]; + const auto addr = qword[code.ABI_JIT_PTR + offsetof(A64JitState, reg) + sizeof(u64) * static_cast(reg)]; if (args[1].FitsInImmediateS32()) { code.mov(addr, args[1].GetImmediateS32()); } else { @@ -402,7 +402,7 @@ void A64EmitX64::EmitA64SetW(A64EmitContext& ctx, IR::Inst* inst) { void A64EmitX64::EmitA64SetX(A64EmitContext& ctx, IR::Inst* inst) { auto args = ctx.reg_alloc.GetArgumentInfo(inst); const A64::Reg reg = inst->GetArg(0).GetA64RegRef(); - const auto addr = qword[r15 + offsetof(A64JitState, reg) + sizeof(u64) * static_cast(reg)]; + const auto addr = qword[code.ABI_JIT_PTR + offsetof(A64JitState, reg) + sizeof(u64) * static_cast(reg)]; if (args[1].FitsInImmediateS32()) { code.mov(addr, args[1].GetImmediateS32()); } else if (args[1].IsInXmm()) { @@ -417,7 +417,7 @@ void A64EmitX64::EmitA64SetX(A64EmitContext& ctx, IR::Inst* inst) { void A64EmitX64::EmitA64SetS(A64EmitContext& ctx, IR::Inst* inst) { auto args = ctx.reg_alloc.GetArgumentInfo(inst); const A64::Vec vec = inst->GetArg(0).GetA64VecRef(); - const auto addr = xword[r15 + offsetof(A64JitState, vec) + sizeof(u64) * 2 * static_cast(vec)]; + const auto addr = xword[code.ABI_JIT_PTR + offsetof(A64JitState, vec) + sizeof(u64) * 2 * static_cast(vec)]; const Xbyak::Xmm to_store = ctx.reg_alloc.UseXmm(args[1]); const Xbyak::Xmm tmp = ctx.reg_alloc.ScratchXmm(); @@ -430,7 +430,7 @@ void A64EmitX64::EmitA64SetS(A64EmitContext& ctx, IR::Inst* inst) { void A64EmitX64::EmitA64SetD(A64EmitContext& ctx, IR::Inst* inst) { auto args = ctx.reg_alloc.GetArgumentInfo(inst); const A64::Vec vec = inst->GetArg(0).GetA64VecRef(); - const auto addr = xword[r15 + offsetof(A64JitState, vec) + sizeof(u64) * 2 * static_cast(vec)]; + const auto addr = xword[code.ABI_JIT_PTR + offsetof(A64JitState, vec) + sizeof(u64) * 2 * static_cast(vec)]; const Xbyak::Xmm to_store = ctx.reg_alloc.UseScratchXmm(args[1]); code.movq(to_store, to_store); // TODO: Remove when able @@ -440,7 +440,7 @@ void A64EmitX64::EmitA64SetD(A64EmitContext& ctx, IR::Inst* inst) { void A64EmitX64::EmitA64SetQ(A64EmitContext& ctx, IR::Inst* inst) { auto args = ctx.reg_alloc.GetArgumentInfo(inst); const A64::Vec vec = inst->GetArg(0).GetA64VecRef(); - const auto addr = xword[r15 + offsetof(A64JitState, vec) + sizeof(u64) * 2 * static_cast(vec)]; + const auto addr = xword[code.ABI_JIT_PTR + offsetof(A64JitState, vec) + sizeof(u64) * 2 * static_cast(vec)]; const Xbyak::Xmm to_store = ctx.reg_alloc.UseXmm(args[1]); code.movaps(addr, to_store); @@ -448,7 +448,7 @@ void A64EmitX64::EmitA64SetQ(A64EmitContext& ctx, IR::Inst* inst) { void A64EmitX64::EmitA64SetSP(A64EmitContext& ctx, IR::Inst* inst) { auto args = ctx.reg_alloc.GetArgumentInfo(inst); - const auto addr = qword[r15 + offsetof(A64JitState, sp)]; + const auto addr = qword[code.ABI_JIT_PTR + offsetof(A64JitState, sp)]; if (args[0].FitsInImmediateS32()) { code.mov(addr, args[0].GetImmediateS32()); } else if (args[0].IsInXmm()) { @@ -467,9 +467,9 @@ static void SetFPCRImpl(A64JitState* jit_state, u32 value) { void A64EmitX64::EmitA64SetFPCR(A64EmitContext& ctx, IR::Inst* inst) { auto args = ctx.reg_alloc.GetArgumentInfo(inst); ctx.reg_alloc.HostCall(nullptr, {}, args[0]); - code.mov(code.ABI_PARAM1, code.r15); + code.mov(code.ABI_PARAM1, code.ABI_JIT_PTR); code.CallFunction(SetFPCRImpl); - code.ldmxcsr(code.dword[code.r15 + offsetof(A64JitState, guest_MXCSR)]); + code.ldmxcsr(code.dword[code.ABI_JIT_PTR + offsetof(A64JitState, guest_MXCSR)]); } static void SetFPSRImpl(A64JitState* jit_state, u32 value) { @@ -479,14 +479,14 @@ static void SetFPSRImpl(A64JitState* jit_state, u32 value) { void A64EmitX64::EmitA64SetFPSR(A64EmitContext& ctx, IR::Inst* inst) { auto args = ctx.reg_alloc.GetArgumentInfo(inst); ctx.reg_alloc.HostCall(nullptr, {}, args[0]); - code.mov(code.ABI_PARAM1, code.r15); + code.mov(code.ABI_PARAM1, code.ABI_JIT_PTR); code.CallFunction(SetFPSRImpl); - code.ldmxcsr(code.dword[code.r15 + offsetof(A64JitState, guest_MXCSR)]); + code.ldmxcsr(code.dword[code.ABI_JIT_PTR + offsetof(A64JitState, guest_MXCSR)]); } void A64EmitX64::EmitA64SetPC(A64EmitContext& ctx, IR::Inst* inst) { auto args = ctx.reg_alloc.GetArgumentInfo(inst); - const auto addr = qword[r15 + offsetof(A64JitState, pc)]; + const auto addr = qword[code.ABI_JIT_PTR + offsetof(A64JitState, pc)]; if (args[0].FitsInImmediateS32()) { code.mov(addr, args[0].GetImmediateS32()); } else if (args[0].IsInXmm()) { @@ -507,7 +507,7 @@ void A64EmitX64::EmitA64CallSupervisor(A64EmitContext& ctx, IR::Inst* inst) { code.mov(param[0], imm); }); // The kernel would have to execute ERET to get here, which would clear exclusive state. - code.mov(code.byte[r15 + offsetof(A64JitState, exclusive_state)], u8(0)); + code.mov(code.byte[code.ABI_JIT_PTR + offsetof(A64JitState, exclusive_state)], u8(0)); } void A64EmitX64::EmitA64ExceptionRaised(A64EmitContext& ctx, IR::Inst* inst) { @@ -621,7 +621,7 @@ void A64EmitX64::EmitTerminalImpl(IR::Term::Interpret terminal, IR::LocationDesc code.SwitchMxcsrOnExit(); Devirtualize<&A64::UserCallbacks::InterpreterFallback>(conf.callbacks).EmitCall(code, [&](RegList param) { code.mov(param[0], A64::LocationDescriptor{terminal.next}.PC()); - code.mov(qword[r15 + offsetof(A64JitState, pc)], param[0]); + code.mov(qword[code.ABI_JIT_PTR + offsetof(A64JitState, pc)], param[0]); code.mov(param[1].cvt32(), terminal.num_instructions); }); code.ReturnFromRunCode(true); // TODO: Check cycles @@ -632,61 +632,56 @@ void A64EmitX64::EmitTerminalImpl(IR::Term::ReturnToDispatch, IR::LocationDescri } void A64EmitX64::EmitTerminalImpl(IR::Term::LinkBlock terminal, IR::LocationDescriptor, bool is_single_step) { - if (!conf.HasOptimization(OptimizationFlag::BlockLinking) || is_single_step) { + // Used for patches and linking + if (conf.HasOptimization(OptimizationFlag::BlockLinking) && !is_single_step) { + if (conf.enable_cycle_counting) { + code.cmp(qword[rsp + ABI_SHADOW_SPACE + offsetof(StackLayout, cycles_remaining)], 0); + patch_information[terminal.next].jg.push_back(code.getCurr()); + if (const auto next_bb = GetBasicBlock(terminal.next)) { + EmitPatchJg(terminal.next, next_bb->entrypoint); + } else { + EmitPatchJg(terminal.next); + } + } else { + code.cmp(dword[code.ABI_JIT_PTR + offsetof(A64JitState, halt_reason)], 0); + patch_information[terminal.next].jz.push_back(code.getCurr()); + if (const auto next_bb = GetBasicBlock(terminal.next)) { + EmitPatchJz(terminal.next, next_bb->entrypoint); + } else { + EmitPatchJz(terminal.next); + } + } code.mov(rax, A64::LocationDescriptor{terminal.next}.PC()); - code.mov(qword[r15 + offsetof(A64JitState, pc)], rax); - code.ReturnFromRunCode(); - return; - } - - if (conf.enable_cycle_counting) { - code.cmp(qword[rsp + ABI_SHADOW_SPACE + offsetof(StackLayout, cycles_remaining)], 0); - - patch_information[terminal.next].jg.push_back(code.getCurr()); - if (const auto next_bb = GetBasicBlock(terminal.next)) { - EmitPatchJg(terminal.next, next_bb->entrypoint); - } else { - EmitPatchJg(terminal.next); - } + code.mov(qword[code.ABI_JIT_PTR + offsetof(A64JitState, pc)], rax); + code.ForceReturnFromRunCode(); } else { - code.cmp(dword[r15 + offsetof(A64JitState, halt_reason)], 0); - - patch_information[terminal.next].jz.push_back(code.getCurr()); - if (const auto next_bb = GetBasicBlock(terminal.next)) { - EmitPatchJz(terminal.next, next_bb->entrypoint); - } else { - EmitPatchJz(terminal.next); - } + code.mov(rax, A64::LocationDescriptor{terminal.next}.PC()); + code.mov(qword[code.ABI_JIT_PTR + offsetof(A64JitState, pc)], rax); + code.ReturnFromRunCode(); } - - code.mov(rax, A64::LocationDescriptor{terminal.next}.PC()); - code.mov(qword[r15 + offsetof(A64JitState, pc)], rax); - code.ForceReturnFromRunCode(); } void A64EmitX64::EmitTerminalImpl(IR::Term::LinkBlockFast terminal, IR::LocationDescriptor, bool is_single_step) { - if (!conf.HasOptimization(OptimizationFlag::BlockLinking) || is_single_step) { - code.mov(rax, A64::LocationDescriptor{terminal.next}.PC()); - code.mov(qword[r15 + offsetof(A64JitState, pc)], rax); - code.ReturnFromRunCode(); - return; - } - - patch_information[terminal.next].jmp.push_back(code.getCurr()); - if (auto next_bb = GetBasicBlock(terminal.next)) { - EmitPatchJmp(terminal.next, next_bb->entrypoint); + if (conf.HasOptimization(OptimizationFlag::BlockLinking) && !is_single_step) { + patch_information[terminal.next].jmp.push_back(code.getCurr()); + if (auto next_bb = GetBasicBlock(terminal.next)) { + EmitPatchJmp(terminal.next, next_bb->entrypoint); + } else { + EmitPatchJmp(terminal.next); + } } else { - EmitPatchJmp(terminal.next); + code.mov(rax, A64::LocationDescriptor{terminal.next}.PC()); + code.mov(qword[code.ABI_JIT_PTR + offsetof(A64JitState, pc)], rax); + code.ReturnFromRunCode(); } } void A64EmitX64::EmitTerminalImpl(IR::Term::PopRSBHint, IR::LocationDescriptor, bool is_single_step) { - if (!conf.HasOptimization(OptimizationFlag::ReturnStackBuffer) || is_single_step) { + if (conf.HasOptimization(OptimizationFlag::ReturnStackBuffer) && !is_single_step) { + code.jmp(terminal_handler_pop_rsb_hint); + } else { code.ReturnFromRunCode(); - return; } - - code.jmp(terminal_handler_pop_rsb_hint); } void A64EmitX64::EmitTerminalImpl(IR::Term::FastDispatchHint, IR::LocationDescriptor, bool is_single_step) { @@ -723,7 +718,7 @@ void A64EmitX64::EmitTerminalImpl(IR::Term::CheckBit terminal, IR::LocationDescr } void A64EmitX64::EmitTerminalImpl(IR::Term::CheckHalt terminal, IR::LocationDescriptor initial_location, bool is_single_step) { - code.cmp(dword[r15 + offsetof(A64JitState, halt_reason)], 0); + code.cmp(dword[code.ABI_JIT_PTR + offsetof(A64JitState, halt_reason)], 0); code.jne(code.GetForceReturnFromRunCodeAddress()); EmitTerminal(terminal.else_, initial_location, is_single_step); } @@ -734,7 +729,7 @@ void A64EmitX64::EmitPatchJg(const IR::LocationDescriptor& target_desc, CodePtr code.jg(target_code_ptr); } else { code.mov(rax, A64::LocationDescriptor{target_desc}.PC()); - code.mov(qword[r15 + offsetof(A64JitState, pc)], rax); + code.mov(qword[code.ABI_JIT_PTR + offsetof(A64JitState, pc)], rax); code.jg(code.GetReturnFromRunCodeAddress()); } code.EnsurePatchLocationSize(patch_location, 23); @@ -746,7 +741,7 @@ void A64EmitX64::EmitPatchJz(const IR::LocationDescriptor& target_desc, CodePtr code.jz(target_code_ptr); } else { code.mov(rax, A64::LocationDescriptor{target_desc}.PC()); - code.mov(qword[r15 + offsetof(A64JitState, pc)], rax); + code.mov(qword[code.ABI_JIT_PTR + offsetof(A64JitState, pc)], rax); code.jz(code.GetReturnFromRunCodeAddress()); } code.EnsurePatchLocationSize(patch_location, 23); @@ -758,7 +753,7 @@ void A64EmitX64::EmitPatchJmp(const IR::LocationDescriptor& target_desc, CodePtr code.jmp(target_code_ptr); } else { code.mov(rax, A64::LocationDescriptor{target_desc}.PC()); - code.mov(qword[r15 + offsetof(A64JitState, pc)], rax); + code.mov(qword[code.ABI_JIT_PTR + offsetof(A64JitState, pc)], rax); code.jmp(code.GetReturnFromRunCodeAddress()); } code.EnsurePatchLocationSize(patch_location, 22); diff --git a/src/dynarmic/src/dynarmic/backend/x64/a64_emit_x64.h b/src/dynarmic/src/dynarmic/backend/x64/a64_emit_x64.h index f26723092f..a1917a3594 100644 --- a/src/dynarmic/src/dynarmic/backend/x64/a64_emit_x64.h +++ b/src/dynarmic/src/dynarmic/backend/x64/a64_emit_x64.h @@ -127,10 +127,10 @@ protected: BlockRangeInformation block_ranges; std::array fast_dispatch_table; ankerl::unordered_dense::map fastmem_patch_info; - std::map, void (*)()> read_fallbacks; - std::map, void (*)()> write_fallbacks; - std::map, void (*)()> exclusive_write_fallbacks; - std::set do_not_fastmem; + ankerl::unordered_dense::map, void (*)()> read_fallbacks; + ankerl::unordered_dense::map, void (*)()> write_fallbacks; + ankerl::unordered_dense::map, void (*)()> exclusive_write_fallbacks; + ankerl::unordered_dense::set do_not_fastmem; const void* terminal_handler_pop_rsb_hint = nullptr; const void* terminal_handler_fast_dispatch_hint = nullptr; FastDispatchEntry& (*fast_dispatch_table_lookup)(u64) = nullptr; diff --git a/src/dynarmic/src/dynarmic/backend/x64/a64_emit_x64_memory.cpp b/src/dynarmic/src/dynarmic/backend/x64/a64_emit_x64_memory.cpp index fe7dfa011f..8fd6777542 100644 --- a/src/dynarmic/src/dynarmic/backend/x64/a64_emit_x64_memory.cpp +++ b/src/dynarmic/src/dynarmic/backend/x64/a64_emit_x64_memory.cpp @@ -324,7 +324,7 @@ void A64EmitX64::EmitA64WriteMemory128(A64EmitContext& ctx, IR::Inst* inst) { } void A64EmitX64::EmitA64ClearExclusive(A64EmitContext&, IR::Inst*) { - code.mov(code.byte[r15 + offsetof(A64JitState, exclusive_state)], u8(0)); + code.mov(code.byte[code.ABI_JIT_PTR + offsetof(A64JitState, exclusive_state)], u8(0)); } void A64EmitX64::EmitA64ExclusiveReadMemory8(A64EmitContext& ctx, IR::Inst* inst) { @@ -416,14 +416,14 @@ void A64EmitX64::EmitCheckMemoryAbort(A64EmitContext&, IR::Inst* inst, Xbyak::La const A64::LocationDescriptor current_location{IR::LocationDescriptor{inst->GetArg(0).GetU64()}}; - code.test(dword[r15 + offsetof(A64JitState, halt_reason)], static_cast(HaltReason::MemoryAbort)); + code.test(dword[code.ABI_JIT_PTR + offsetof(A64JitState, halt_reason)], static_cast(HaltReason::MemoryAbort)); if (end) { code.jz(*end, code.T_NEAR); } else { code.jz(skip, code.T_NEAR); } code.mov(rax, current_location.PC()); - code.mov(qword[r15 + offsetof(A64JitState, pc)], rax); + code.mov(qword[code.ABI_JIT_PTR + offsetof(A64JitState, pc)], rax); code.ForceReturnFromRunCode(); code.L(skip); } diff --git a/src/dynarmic/src/dynarmic/backend/x64/abi.cpp b/src/dynarmic/src/dynarmic/backend/x64/abi.cpp index e8eaddcbac..a9bbab3d10 100644 --- a/src/dynarmic/src/dynarmic/backend/x64/abi.cpp +++ b/src/dynarmic/src/dynarmic/backend/x64/abi.cpp @@ -49,16 +49,11 @@ void ABI_PushRegistersAndAdjustStack(BlockOfCode& code, const size_t frame_size, const size_t num_xmms = std::count_if(regs.begin(), regs.end(), HostLocIsXMM); const FrameInfo frame_info = CalculateFrameInfo(num_gprs, num_xmms, frame_size); - for (auto const gpr : regs) { - if (HostLocIsGPR(gpr)) { + for (auto const gpr : regs) + if (HostLocIsGPR(gpr)) code.push(HostLocToReg64(gpr)); - } - } - - if (frame_info.stack_subtraction != 0) { + if (frame_info.stack_subtraction != 0) code.sub(rsp, u32(frame_info.stack_subtraction)); - } - size_t xmm_offset = frame_info.xmm_offset; for (auto const xmm : regs) { if (HostLocIsXMM(xmm)) { @@ -80,27 +75,22 @@ void ABI_PopRegistersAndAdjustStack(BlockOfCode& code, const size_t frame_size, const size_t num_xmms = std::count_if(regs.begin(), regs.end(), HostLocIsXMM); const FrameInfo frame_info = CalculateFrameInfo(num_gprs, num_xmms, frame_size); - size_t xmm_offset = frame_info.xmm_offset; - for (auto const xmm : regs) { + size_t xmm_offset = frame_info.xmm_offset + (num_xmms * XMM_SIZE); + for (auto const xmm : mcl::iterator::reverse(regs)) { if (HostLocIsXMM(xmm)) { + xmm_offset -= XMM_SIZE; if (code.HasHostFeature(HostFeature::AVX)) { code.vmovaps(HostLocToXmm(xmm), code.xword[rsp + xmm_offset]); } else { code.movaps(HostLocToXmm(xmm), code.xword[rsp + xmm_offset]); } - xmm_offset += XMM_SIZE; } } - - if (frame_info.stack_subtraction != 0) { + if (frame_info.stack_subtraction != 0) code.add(rsp, u32(frame_info.stack_subtraction)); - } - - for (auto const gpr : mcl::iterator::reverse(regs)) { - if (HostLocIsGPR(gpr)) { + for (auto const gpr : mcl::iterator::reverse(regs)) + if (HostLocIsGPR(gpr)) code.pop(HostLocToReg64(gpr)); - } - } } void ABI_PushCalleeSaveRegistersAndAdjustStack(BlockOfCode& code, const std::size_t frame_size) { @@ -119,6 +109,20 @@ void ABI_PopCallerSaveRegistersAndAdjustStack(BlockOfCode& code, const std::size ABI_PopRegistersAndAdjustStack(code, frame_size, ABI_ALL_CALLER_SAVE); } +// Windows ABI registers are not in the same allocation algorithm as unix's +#ifdef _MSC_VER +void ABI_PushCallerSaveRegistersAndAdjustStackExcept(BlockOfCode& code, const HostLoc exception) { + std::vector regs; + std::remove_copy(ABI_ALL_CALLER_SAVE.begin(), ABI_ALL_CALLER_SAVE.end(), std::back_inserter(regs), exception); + ABI_PushRegistersAndAdjustStack(code, 0, regs); +} + +void ABI_PopCallerSaveRegistersAndAdjustStackExcept(BlockOfCode& code, const HostLoc exception) { + std::vector regs; + std::remove_copy(ABI_ALL_CALLER_SAVE.begin(), ABI_ALL_CALLER_SAVE.end(), std::back_inserter(regs), exception); + ABI_PopRegistersAndAdjustStack(code, 0, regs); +} +#else static consteval size_t ABI_AllCallerSaveSize() noexcept { return ABI_ALL_CALLER_SAVE.max_size(); } @@ -166,24 +170,14 @@ alignas(64) static constinit std::array AB }; void ABI_PushCallerSaveRegistersAndAdjustStackExcept(BlockOfCode& code, const HostLoc exception) { -#ifdef _MSC_VER - std::vector regs; - std::remove_copy(ABI_ALL_CALLER_SAVE.begin(), ABI_ALL_CALLER_SAVE.end(), std::back_inserter(regs), exception); - ABI_PushRegistersAndAdjustStack(code, 0, regs); -#else ASSUME(size_t(exception) < 32); ABI_PushRegistersAndAdjustStack(code, 0, ABI_CALLER_SAVED_EXCEPT_TABLE[size_t(exception)]); -#endif } void ABI_PopCallerSaveRegistersAndAdjustStackExcept(BlockOfCode& code, const HostLoc exception) { -#ifdef _MSC_VER - std::vector regs; - std::remove_copy(ABI_ALL_CALLER_SAVE.begin(), ABI_ALL_CALLER_SAVE.end(), std::back_inserter(regs), exception); - ABI_PopRegistersAndAdjustStack(code, 0, regs); -#else ASSUME(size_t(exception) < 32); ABI_PopRegistersAndAdjustStack(code, 0, ABI_CALLER_SAVED_EXCEPT_TABLE[size_t(exception)]); -#endif } +#endif + } // namespace Dynarmic::Backend::X64 diff --git a/src/dynarmic/src/dynarmic/backend/x64/abi.h b/src/dynarmic/src/dynarmic/backend/x64/abi.h index 32f2bdac67..307817a864 100644 --- a/src/dynarmic/src/dynarmic/backend/x64/abi.h +++ b/src/dynarmic/src/dynarmic/backend/x64/abi.h @@ -17,6 +17,7 @@ namespace Dynarmic::Backend::X64 { class BlockOfCode; +constexpr HostLoc ABI_JIT_PTR = HostLoc::R15; #ifdef _WIN32 constexpr HostLoc ABI_RETURN = HostLoc::RAX; diff --git a/src/dynarmic/src/dynarmic/backend/x64/block_of_code.cpp b/src/dynarmic/src/dynarmic/backend/x64/block_of_code.cpp index 41603abf86..5a33ac7727 100644 --- a/src/dynarmic/src/dynarmic/backend/x64/block_of_code.cpp +++ b/src/dynarmic/src/dynarmic/backend/x64/block_of_code.cpp @@ -36,6 +36,7 @@ namespace Dynarmic::Backend::X64 { +const Xbyak::Reg64 BlockOfCode::ABI_JIT_PTR = HostLocToReg64(Dynarmic::Backend::X64::ABI_JIT_PTR); #ifdef _WIN32 const Xbyak::Reg64 BlockOfCode::ABI_RETURN = HostLocToReg64(Dynarmic::Backend::X64::ABI_RETURN); const Xbyak::Reg64 BlockOfCode::ABI_PARAM1 = HostLocToReg64(Dynarmic::Backend::X64::ABI_PARAM1); @@ -322,8 +323,8 @@ void BlockOfCode::GenRunCode(std::function rcp) { // that the stack is appropriately aligned for CALLs. ABI_PushCalleeSaveRegistersAndAdjustStack(*this, sizeof(StackLayout)); - mov(r15, ABI_PARAM1); - mov(rbx, ABI_PARAM2); // save temporarily in non-volatile register + mov(ABI_JIT_PTR, ABI_PARAM1); + mov(rbx, ABI_PARAM2); // save temporarily in non-volatile register if (cb.enable_cycle_counting) { cb.GetTicksRemaining->EmitCall(*this); @@ -331,9 +332,11 @@ void BlockOfCode::GenRunCode(std::function rcp) { mov(qword[rsp + ABI_SHADOW_SPACE + offsetof(StackLayout, cycles_remaining)], ABI_RETURN); } + // r14 = page table + // r13 = fastmem pointer rcp(*this); - cmp(dword[r15 + jsi.offsetof_halt_reason], 0); + cmp(dword[ABI_JIT_PTR + jsi.offsetof_halt_reason], 0); jne(return_to_caller_mxcsr_already_exited, T_NEAR); SwitchMxcsrOnEntry(); @@ -344,7 +347,7 @@ void BlockOfCode::GenRunCode(std::function rcp) { ABI_PushCalleeSaveRegistersAndAdjustStack(*this, sizeof(StackLayout)); - mov(r15, ABI_PARAM1); + mov(ABI_JIT_PTR, ABI_PARAM1); if (cb.enable_cycle_counting) { mov(qword[rsp + ABI_SHADOW_SPACE + offsetof(StackLayout, cycles_to_run)], 1); @@ -353,10 +356,10 @@ void BlockOfCode::GenRunCode(std::function rcp) { rcp(*this); - cmp(dword[r15 + jsi.offsetof_halt_reason], 0); + cmp(dword[ABI_JIT_PTR + jsi.offsetof_halt_reason], 0); jne(return_to_caller_mxcsr_already_exited, T_NEAR); lock(); - or_(dword[r15 + jsi.offsetof_halt_reason], static_cast(HaltReason::Step)); + or_(dword[ABI_JIT_PTR + jsi.offsetof_halt_reason], static_cast(HaltReason::Step)); SwitchMxcsrOnEntry(); jmp(ABI_PARAM2); @@ -366,7 +369,7 @@ void BlockOfCode::GenRunCode(std::function rcp) { align(); return_from_run_code[0] = getCurr(); - cmp(dword[r15 + jsi.offsetof_halt_reason], 0); + cmp(dword[ABI_JIT_PTR + jsi.offsetof_halt_reason], 0); jne(return_to_caller); if (cb.enable_cycle_counting) { cmp(qword[rsp + ABI_SHADOW_SPACE + offsetof(StackLayout, cycles_remaining)], 0); @@ -378,7 +381,7 @@ void BlockOfCode::GenRunCode(std::function rcp) { align(); return_from_run_code[MXCSR_ALREADY_EXITED] = getCurr(); - cmp(dword[r15 + jsi.offsetof_halt_reason], 0); + cmp(dword[ABI_JIT_PTR + jsi.offsetof_halt_reason], 0); jne(return_to_caller_mxcsr_already_exited); if (cb.enable_cycle_counting) { cmp(qword[rsp + ABI_SHADOW_SPACE + offsetof(StackLayout, cycles_remaining)], 0); @@ -407,7 +410,7 @@ void BlockOfCode::GenRunCode(std::function rcp) { xor_(eax, eax); lock(); - xchg(dword[r15 + jsi.offsetof_halt_reason], eax); + xchg(dword[ABI_JIT_PTR + jsi.offsetof_halt_reason], eax); ABI_PopCalleeSaveRegistersAndAdjustStack(*this, sizeof(StackLayout)); ret(); @@ -417,22 +420,22 @@ void BlockOfCode::GenRunCode(std::function rcp) { void BlockOfCode::SwitchMxcsrOnEntry() { stmxcsr(dword[rsp + ABI_SHADOW_SPACE + offsetof(StackLayout, save_host_MXCSR)]); - ldmxcsr(dword[r15 + jsi.offsetof_guest_MXCSR]); + ldmxcsr(dword[ABI_JIT_PTR + jsi.offsetof_guest_MXCSR]); } void BlockOfCode::SwitchMxcsrOnExit() { - stmxcsr(dword[r15 + jsi.offsetof_guest_MXCSR]); + stmxcsr(dword[ABI_JIT_PTR + jsi.offsetof_guest_MXCSR]); ldmxcsr(dword[rsp + ABI_SHADOW_SPACE + offsetof(StackLayout, save_host_MXCSR)]); } void BlockOfCode::EnterStandardASIMD() { - stmxcsr(dword[r15 + jsi.offsetof_guest_MXCSR]); - ldmxcsr(dword[r15 + jsi.offsetof_asimd_MXCSR]); + stmxcsr(dword[ABI_JIT_PTR + jsi.offsetof_guest_MXCSR]); + ldmxcsr(dword[ABI_JIT_PTR + jsi.offsetof_asimd_MXCSR]); } void BlockOfCode::LeaveStandardASIMD() { - stmxcsr(dword[r15 + jsi.offsetof_asimd_MXCSR]); - ldmxcsr(dword[r15 + jsi.offsetof_guest_MXCSR]); + stmxcsr(dword[ABI_JIT_PTR + jsi.offsetof_asimd_MXCSR]); + ldmxcsr(dword[ABI_JIT_PTR + jsi.offsetof_guest_MXCSR]); } void BlockOfCode::UpdateTicks() { diff --git a/src/dynarmic/src/dynarmic/backend/x64/block_of_code.h b/src/dynarmic/src/dynarmic/backend/x64/block_of_code.h index 4cc8663e11..095e75336b 100644 --- a/src/dynarmic/src/dynarmic/backend/x64/block_of_code.h +++ b/src/dynarmic/src/dynarmic/backend/x64/block_of_code.h @@ -155,6 +155,7 @@ public: void SetCodePtr(CodePtr code_ptr); void EnsurePatchLocationSize(CodePtr begin, size_t size); + static const Xbyak::Reg64 ABI_JIT_PTR; // ABI registers #ifdef _WIN32 static const Xbyak::Reg64 ABI_RETURN; diff --git a/src/dynarmic/src/dynarmic/backend/x64/emit_x64.cpp b/src/dynarmic/src/dynarmic/backend/x64/emit_x64.cpp index d428199585..a13baa6a97 100644 --- a/src/dynarmic/src/dynarmic/backend/x64/emit_x64.cpp +++ b/src/dynarmic/src/dynarmic/backend/x64/emit_x64.cpp @@ -91,19 +91,18 @@ void EmitX64::PushRSBHelper(Xbyak::Reg64 loc_desc_reg, Xbyak::Reg64 index_reg, I ? iter->second.entrypoint : code.GetReturnFromRunCodeAddress(); - code.mov(index_reg.cvt32(), dword[r15 + code.GetJitStateInfo().offsetof_rsb_ptr]); - + code.mov(index_reg.cvt32(), dword[code.ABI_JIT_PTR + code.GetJitStateInfo().offsetof_rsb_ptr]); code.mov(loc_desc_reg, target.Value()); - patch_information[target].mov_rcx.push_back(code.getCurr()); EmitPatchMovRcx(target_code_ptr); - - code.mov(qword[r15 + index_reg * 8 + code.GetJitStateInfo().offsetof_rsb_location_descriptors], loc_desc_reg); - code.mov(qword[r15 + index_reg * 8 + code.GetJitStateInfo().offsetof_rsb_codeptrs], rcx); - - code.add(index_reg.cvt32(), 1); - code.and_(index_reg.cvt32(), u32(code.GetJitStateInfo().rsb_ptr_mask)); - code.mov(dword[r15 + code.GetJitStateInfo().offsetof_rsb_ptr], index_reg.cvt32()); + code.mov(qword[code.ABI_JIT_PTR + index_reg * 8 + code.GetJitStateInfo().offsetof_rsb_location_descriptors], loc_desc_reg); + code.mov(qword[code.ABI_JIT_PTR + index_reg * 8 + code.GetJitStateInfo().offsetof_rsb_codeptrs], rcx); + // Byte size hack + DEBUG_ASSERT(code.GetJitStateInfo().rsb_ptr_mask <= 0xFF); + code.add(index_reg.cvt32(), 1); //flags trashed, 1 single byte, haswell doesn't care + code.and_(index_reg.cvt32(), u32(code.GetJitStateInfo().rsb_ptr_mask)); //trashes flags + // Results ready and sort by least needed: give OOO some break + code.mov(dword[code.ABI_JIT_PTR + code.GetJitStateInfo().offsetof_rsb_ptr], index_reg.cvt32()); } void EmitX64::EmitVerboseDebuggingOutput(RegAlloc& reg_alloc) { @@ -119,7 +118,7 @@ void EmitX64::EmitVerboseDebuggingOutput(RegAlloc& reg_alloc) { code.movaps(xword[rsp + offsetof(RegisterData, xmms) + 2 * sizeof(u64) * i], Xbyak::Xmm{i}); } code.lea(rax, ptr[rsp + sizeof(RegisterData) + offsetof(StackLayout, spill)]); - code.mov(xword[rsp + offsetof(RegisterData, spill)], rax); + code.mov(qword[rsp + offsetof(RegisterData, spill)], rax); reg_alloc.EmitVerboseDebuggingOutput(); @@ -285,7 +284,7 @@ void EmitX64::EmitAddCycles(size_t cycles) { Xbyak::Label EmitX64::EmitCond(IR::Cond cond) { Xbyak::Label pass; - code.mov(eax, dword[r15 + code.GetJitStateInfo().offsetof_cpsr_nzcv]); + code.mov(eax, dword[code.ABI_JIT_PTR + code.GetJitStateInfo().offsetof_cpsr_nzcv]); code.LoadRequiredFlagsForCondFromRax(cond); diff --git a/src/dynarmic/src/dynarmic/backend/x64/emit_x64_crc32.cpp b/src/dynarmic/src/dynarmic/backend/x64/emit_x64_crc32.cpp index 842a8612ee..9d7c57cb57 100644 --- a/src/dynarmic/src/dynarmic/backend/x64/emit_x64_crc32.cpp +++ b/src/dynarmic/src/dynarmic/backend/x64/emit_x64_crc32.cpp @@ -18,24 +18,20 @@ namespace CRC32 = Common::Crypto::CRC32; static void EmitCRC32Castagnoli(BlockOfCode& code, EmitContext& ctx, IR::Inst* inst, const int data_size) { auto args = ctx.reg_alloc.GetArgumentInfo(inst); - if (code.HasHostFeature(HostFeature::SSE42)) { const Xbyak::Reg32 crc = ctx.reg_alloc.UseScratchGpr(args[0]).cvt32(); const Xbyak::Reg value = ctx.reg_alloc.UseGpr(args[1]).changeBit(data_size); - if (data_size != 64) { code.crc32(crc, value); } else { code.crc32(crc.cvt64(), value); } - ctx.reg_alloc.DefineValue(inst, crc); - return; + } else { + ctx.reg_alloc.HostCall(inst, args[0], args[1], {}); + code.mov(code.ABI_PARAM3.cvt32(), data_size / CHAR_BIT); //zext + code.CallFunction(&CRC32::ComputeCRC32Castagnoli); } - - ctx.reg_alloc.HostCall(inst, args[0], args[1], {}); - code.mov(code.ABI_PARAM3, data_size / CHAR_BIT); - code.CallFunction(&CRC32::ComputeCRC32Castagnoli); } static void EmitCRC32ISO(BlockOfCode& code, EmitContext& ctx, IR::Inst* inst, const int data_size) { @@ -69,10 +65,7 @@ static void EmitCRC32ISO(BlockOfCode& code, EmitContext& ctx, IR::Inst* inst, co code.pextrd(crc, xmm_value, 2); ctx.reg_alloc.DefineValue(inst, crc); - return; - } - - if (code.HasHostFeature(HostFeature::PCLMULQDQ) && data_size == 32) { + } else if (code.HasHostFeature(HostFeature::PCLMULQDQ) && data_size == 32) { const Xbyak::Reg32 crc = ctx.reg_alloc.UseScratchGpr(args[0]).cvt32(); const Xbyak::Reg32 value = ctx.reg_alloc.UseGpr(args[1]).cvt32(); const Xbyak::Xmm xmm_value = ctx.reg_alloc.ScratchXmm(); @@ -90,10 +83,7 @@ static void EmitCRC32ISO(BlockOfCode& code, EmitContext& ctx, IR::Inst* inst, co code.pextrd(crc, xmm_value, 2); ctx.reg_alloc.DefineValue(inst, crc); - return; - } - - if (code.HasHostFeature(HostFeature::PCLMULQDQ) && data_size == 64) { + } else if (code.HasHostFeature(HostFeature::PCLMULQDQ) && data_size == 64) { const Xbyak::Reg32 crc = ctx.reg_alloc.UseScratchGpr(args[0]).cvt32(); const Xbyak::Reg64 value = ctx.reg_alloc.UseGpr(args[1]); const Xbyak::Xmm xmm_value = ctx.reg_alloc.ScratchXmm(); @@ -111,12 +101,11 @@ static void EmitCRC32ISO(BlockOfCode& code, EmitContext& ctx, IR::Inst* inst, co code.pextrd(crc, xmm_value, 2); ctx.reg_alloc.DefineValue(inst, crc); - return; + } else { + ctx.reg_alloc.HostCall(inst, args[0], args[1], {}); + code.mov(code.ABI_PARAM3, data_size / CHAR_BIT); + code.CallFunction(&CRC32::ComputeCRC32ISO); } - - ctx.reg_alloc.HostCall(inst, args[0], args[1], {}); - code.mov(code.ABI_PARAM3, data_size / CHAR_BIT); - code.CallFunction(&CRC32::ComputeCRC32ISO); } void EmitX64::EmitCRC32Castagnoli8(EmitContext& ctx, IR::Inst* inst) { diff --git a/src/dynarmic/src/dynarmic/backend/x64/emit_x64_data_processing.cpp b/src/dynarmic/src/dynarmic/backend/x64/emit_x64_data_processing.cpp index 4128ef1721..7e03e3dcd1 100644 --- a/src/dynarmic/src/dynarmic/backend/x64/emit_x64_data_processing.cpp +++ b/src/dynarmic/src/dynarmic/backend/x64/emit_x64_data_processing.cpp @@ -143,7 +143,7 @@ static void EmitConditionalSelect(BlockOfCode& code, EmitContext& ctx, IR::Inst* const Xbyak::Reg then_ = ctx.reg_alloc.UseGpr(args[1]).changeBit(bitsize); const Xbyak::Reg else_ = ctx.reg_alloc.UseScratchGpr(args[2]).changeBit(bitsize); - code.mov(nzcv, dword[r15 + code.GetJitStateInfo().offsetof_cpsr_nzcv]); + code.mov(nzcv, dword[code.ABI_JIT_PTR + code.GetJitStateInfo().offsetof_cpsr_nzcv]); code.LoadRequiredFlagsForCondFromRax(args[0].GetImmediateCond()); @@ -909,11 +909,11 @@ static Xbyak::Reg8 DoCarry(RegAlloc& reg_alloc, Argument& carry_in, IR::Inst* ca } } +// AL contains flags (after LAHF + SETO sequence) static Xbyak::Reg64 DoNZCV(BlockOfCode& code, RegAlloc& reg_alloc, IR::Inst* nzcv_out) { if (!nzcv_out) { return Xbyak::Reg64{-1}; } - const Xbyak::Reg64 nzcv = reg_alloc.ScratchGpr(HostLoc::RAX); code.xor_(nzcv.cvt32(), nzcv.cvt32()); return nzcv; @@ -1168,7 +1168,7 @@ void EmitX64::EmitUnsignedDiv32(EmitContext& ctx, IR::Inst* inst) { code.xor_(eax, eax); code.test(divisor, divisor); - code.jz(end); + code.jz(end, code.T_NEAR); code.mov(eax, dividend); code.xor_(edx, edx); code.div(divisor); @@ -1189,7 +1189,7 @@ void EmitX64::EmitUnsignedDiv64(EmitContext& ctx, IR::Inst* inst) { code.xor_(eax, eax); code.test(divisor, divisor); - code.jz(end); + code.jz(end, code.T_NEAR); code.mov(rax, dividend); code.xor_(edx, edx); code.div(divisor); @@ -1568,14 +1568,14 @@ void EmitX64::EmitCountLeadingZeros32(EmitContext& ctx, IR::Inst* inst) { } else { const Xbyak::Reg32 source = ctx.reg_alloc.UseScratchGpr(args[0]).cvt32(); const Xbyak::Reg32 result = ctx.reg_alloc.ScratchGpr().cvt32(); + const Xbyak::Reg32 temp = ctx.reg_alloc.ScratchGpr().cvt32(); // The result of a bsr of zero is undefined, but zf is set after it. code.bsr(result, source); - code.mov(source, 0xFFFFFFFF); - code.cmovz(result, source); - code.neg(result); - code.add(result, 31); - + code.mov(temp, 32); + code.xor_(result, 31); + code.test(source, source); + code.cmove(result, temp); ctx.reg_alloc.DefineValue(inst, result); } } @@ -1592,14 +1592,14 @@ void EmitX64::EmitCountLeadingZeros64(EmitContext& ctx, IR::Inst* inst) { } else { const Xbyak::Reg64 source = ctx.reg_alloc.UseScratchGpr(args[0]).cvt64(); const Xbyak::Reg64 result = ctx.reg_alloc.ScratchGpr().cvt64(); + const Xbyak::Reg64 temp = ctx.reg_alloc.ScratchGpr().cvt64(); // The result of a bsr of zero is undefined, but zf is set after it. code.bsr(result, source); - code.mov(source.cvt32(), 0xFFFFFFFF); - code.cmovz(result.cvt32(), source.cvt32()); - code.neg(result.cvt32()); - code.add(result.cvt32(), 63); - + code.mov(temp.cvt32(), 64); + code.xor_(result.cvt32(), 63); + code.test(source, source); + code.cmove(result.cvt32(), temp.cvt32()); ctx.reg_alloc.DefineValue(inst, result); } } diff --git a/src/dynarmic/src/dynarmic/backend/x64/emit_x64_floating_point.cpp b/src/dynarmic/src/dynarmic/backend/x64/emit_x64_floating_point.cpp index 63b9659618..47e51acb03 100644 --- a/src/dynarmic/src/dynarmic/backend/x64/emit_x64_floating_point.cpp +++ b/src/dynarmic/src/dynarmic/backend/x64/emit_x64_floating_point.cpp @@ -712,12 +712,12 @@ static void EmitFPMulAdd(BlockOfCode& code, EmitContext& ctx, IR::Inst* inst) { code.mov(code.ABI_PARAM4.cvt32(), ctx.FPCR().Value()); #ifdef _WIN32 code.lea(rsp, ptr[rsp - (16 + ABI_SHADOW_SPACE)]); - code.lea(rax, code.ptr[code.r15 + code.GetJitStateInfo().offsetof_fpsr_exc]); + code.lea(rax, code.ptr[code.ABI_JIT_PTR + code.GetJitStateInfo().offsetof_fpsr_exc]); code.mov(qword[rsp + ABI_SHADOW_SPACE], rax); code.CallFunction(fallback_fn); code.add(rsp, 16 + ABI_SHADOW_SPACE); #else - code.lea(code.ABI_PARAM5, code.ptr[code.r15 + code.GetJitStateInfo().offsetof_fpsr_exc]); + code.lea(code.ABI_PARAM5, code.ptr[code.ABI_JIT_PTR + code.GetJitStateInfo().offsetof_fpsr_exc]); code.CallFunction(fallback_fn); #endif code.movq(result, code.ABI_RETURN); @@ -821,12 +821,12 @@ static void EmitFPMulAdd(BlockOfCode& code, EmitContext& ctx, IR::Inst* inst) { code.mov(code.ABI_PARAM4.cvt32(), ctx.FPCR().Value()); #ifdef _WIN32 ctx.reg_alloc.AllocStackSpace(16 + ABI_SHADOW_SPACE); - code.lea(rax, code.ptr[code.r15 + code.GetJitStateInfo().offsetof_fpsr_exc]); + code.lea(rax, code.ptr[code.ABI_JIT_PTR + code.GetJitStateInfo().offsetof_fpsr_exc]); code.mov(qword[rsp + ABI_SHADOW_SPACE], rax); code.CallFunction(fallback_fn); ctx.reg_alloc.ReleaseStackSpace(16 + ABI_SHADOW_SPACE); #else - code.lea(code.ABI_PARAM5, code.ptr[code.r15 + code.GetJitStateInfo().offsetof_fpsr_exc]); + code.lea(code.ABI_PARAM5, code.ptr[code.ABI_JIT_PTR + code.GetJitStateInfo().offsetof_fpsr_exc]); code.CallFunction(fallback_fn); #endif } @@ -945,7 +945,7 @@ static void EmitFPRecipEstimate(BlockOfCode& code, EmitContext& ctx, IR::Inst* i auto args = ctx.reg_alloc.GetArgumentInfo(inst); ctx.reg_alloc.HostCall(inst, args[0]); code.mov(code.ABI_PARAM2.cvt32(), ctx.FPCR().Value()); - code.lea(code.ABI_PARAM3, code.ptr[code.r15 + code.GetJitStateInfo().offsetof_fpsr_exc]); + code.lea(code.ABI_PARAM3, code.ptr[code.ABI_JIT_PTR + code.GetJitStateInfo().offsetof_fpsr_exc]); code.CallFunction(&FP::FPRecipEstimate); } @@ -968,7 +968,7 @@ static void EmitFPRecipExponent(BlockOfCode& code, EmitContext& ctx, IR::Inst* i auto args = ctx.reg_alloc.GetArgumentInfo(inst); ctx.reg_alloc.HostCall(inst, args[0]); code.mov(code.ABI_PARAM2.cvt32(), ctx.FPCR().Value()); - code.lea(code.ABI_PARAM3, code.ptr[code.r15 + code.GetJitStateInfo().offsetof_fpsr_exc]); + code.lea(code.ABI_PARAM3, code.ptr[code.ABI_JIT_PTR + code.GetJitStateInfo().offsetof_fpsr_exc]); code.CallFunction(&FP::FPRecipExponent); } @@ -1026,7 +1026,7 @@ static void EmitFPRecipStepFused(BlockOfCode& code, EmitContext& ctx, IR::Inst* code.movq(code.ABI_PARAM1, operand1); code.movq(code.ABI_PARAM2, operand2); code.mov(code.ABI_PARAM3.cvt32(), ctx.FPCR().Value()); - code.lea(code.ABI_PARAM4, code.ptr[code.r15 + code.GetJitStateInfo().offsetof_fpsr_exc]); + code.lea(code.ABI_PARAM4, code.ptr[code.ABI_JIT_PTR + code.GetJitStateInfo().offsetof_fpsr_exc]); code.CallFunction(&FP::FPRecipStepFused); code.movq(result, code.ABI_RETURN); ABI_PopCallerSaveRegistersAndAdjustStackExcept(code, HostLocXmmIdx(result.getIdx())); @@ -1055,7 +1055,7 @@ static void EmitFPRecipStepFused(BlockOfCode& code, EmitContext& ctx, IR::Inst* ctx.reg_alloc.HostCall(inst, args[0], args[1]); code.mov(code.ABI_PARAM3.cvt32(), ctx.FPCR().Value()); - code.lea(code.ABI_PARAM4, code.ptr[code.r15 + code.GetJitStateInfo().offsetof_fpsr_exc]); + code.lea(code.ABI_PARAM4, code.ptr[code.ABI_JIT_PTR + code.GetJitStateInfo().offsetof_fpsr_exc]); code.CallFunction(&FP::FPRecipStepFused); } @@ -1119,7 +1119,7 @@ static void EmitFPRound(BlockOfCode& code, EmitContext& ctx, IR::Inst* inst, siz auto args = ctx.reg_alloc.GetArgumentInfo(inst); ctx.reg_alloc.HostCall(inst, args[0]); - code.lea(code.ABI_PARAM2, code.ptr[code.r15 + code.GetJitStateInfo().offsetof_fpsr_exc]); + code.lea(code.ABI_PARAM2, code.ptr[code.ABI_JIT_PTR + code.GetJitStateInfo().offsetof_fpsr_exc]); code.mov(code.ABI_PARAM3.cvt32(), ctx.FPCR().Value()); code.CallFunction(lut.at(std::make_tuple(fsize, rounding_mode, exact))); } @@ -1206,7 +1206,7 @@ static void EmitFPRSqrtEstimate(BlockOfCode& code, EmitContext& ctx, IR::Inst* i } // a > 0 && a < 0x00800000; - code.dec(tmp); + code.sub(tmp, 1); code.cmp(tmp, 0x007FFFFF); code.jb(fallback, code.T_NEAR); //within -127,128 needs_fallback = true; @@ -1284,7 +1284,7 @@ static void EmitFPRSqrtEstimate(BlockOfCode& code, EmitContext& ctx, IR::Inst* i ABI_PushCallerSaveRegistersAndAdjustStackExcept(code, HostLocXmmIdx(result.getIdx())); code.movq(code.ABI_PARAM1, operand); code.mov(code.ABI_PARAM2.cvt32(), ctx.FPCR().Value()); - code.lea(code.ABI_PARAM3, code.ptr[code.r15 + code.GetJitStateInfo().offsetof_fpsr_exc]); + code.lea(code.ABI_PARAM3, code.ptr[code.ABI_JIT_PTR + code.GetJitStateInfo().offsetof_fpsr_exc]); code.CallFunction(&FP::FPRSqrtEstimate); code.movq(result, rax); ABI_PopCallerSaveRegistersAndAdjustStackExcept(code, HostLocXmmIdx(result.getIdx())); @@ -1298,7 +1298,7 @@ static void EmitFPRSqrtEstimate(BlockOfCode& code, EmitContext& ctx, IR::Inst* i auto args = ctx.reg_alloc.GetArgumentInfo(inst); ctx.reg_alloc.HostCall(inst, args[0]); code.mov(code.ABI_PARAM2.cvt32(), ctx.FPCR().Value()); - code.lea(code.ABI_PARAM3, code.ptr[code.r15 + code.GetJitStateInfo().offsetof_fpsr_exc]); + code.lea(code.ABI_PARAM3, code.ptr[code.ABI_JIT_PTR + code.GetJitStateInfo().offsetof_fpsr_exc]); code.CallFunction(&FP::FPRSqrtEstimate); } } @@ -1368,7 +1368,7 @@ static void EmitFPRSqrtStepFused(BlockOfCode& code, EmitContext& ctx, IR::Inst* code.movq(code.ABI_PARAM1, operand1); code.movq(code.ABI_PARAM2, operand2); code.mov(code.ABI_PARAM3.cvt32(), ctx.FPCR().Value()); - code.lea(code.ABI_PARAM4, code.ptr[code.r15 + code.GetJitStateInfo().offsetof_fpsr_exc]); + code.lea(code.ABI_PARAM4, code.ptr[code.ABI_JIT_PTR + code.GetJitStateInfo().offsetof_fpsr_exc]); code.CallFunction(&FP::FPRSqrtStepFused); code.movq(result, code.ABI_RETURN); ABI_PopCallerSaveRegistersAndAdjustStackExcept(code, HostLocXmmIdx(result.getIdx())); @@ -1398,7 +1398,7 @@ static void EmitFPRSqrtStepFused(BlockOfCode& code, EmitContext& ctx, IR::Inst* ctx.reg_alloc.HostCall(inst, args[0], args[1]); code.mov(code.ABI_PARAM3.cvt32(), ctx.FPCR().Value()); - code.lea(code.ABI_PARAM4, code.ptr[code.r15 + code.GetJitStateInfo().offsetof_fpsr_exc]); + code.lea(code.ABI_PARAM4, code.ptr[code.ABI_JIT_PTR + code.GetJitStateInfo().offsetof_fpsr_exc]); code.CallFunction(&FP::FPRSqrtStepFused); } @@ -1511,7 +1511,7 @@ void EmitX64::EmitFPHalfToDouble(EmitContext& ctx, IR::Inst* inst) { ctx.reg_alloc.HostCall(inst, args[0]); code.mov(code.ABI_PARAM2.cvt32(), ctx.FPCR().Value()); code.mov(code.ABI_PARAM3.cvt32(), static_cast(rounding_mode)); - code.lea(code.ABI_PARAM4, code.ptr[code.r15 + code.GetJitStateInfo().offsetof_fpsr_exc]); + code.lea(code.ABI_PARAM4, code.ptr[code.ABI_JIT_PTR + code.GetJitStateInfo().offsetof_fpsr_exc]); code.CallFunction(&FP::FPConvert); } @@ -1535,7 +1535,7 @@ void EmitX64::EmitFPHalfToSingle(EmitContext& ctx, IR::Inst* inst) { ctx.reg_alloc.HostCall(inst, args[0]); code.mov(code.ABI_PARAM2.cvt32(), ctx.FPCR().Value()); code.mov(code.ABI_PARAM3.cvt32(), static_cast(rounding_mode)); - code.lea(code.ABI_PARAM4, code.ptr[code.r15 + code.GetJitStateInfo().offsetof_fpsr_exc]); + code.lea(code.ABI_PARAM4, code.ptr[code.ABI_JIT_PTR + code.GetJitStateInfo().offsetof_fpsr_exc]); code.CallFunction(&FP::FPConvert); } @@ -1556,7 +1556,7 @@ void EmitX64::EmitFPSingleToDouble(EmitContext& ctx, IR::Inst* inst) { ctx.reg_alloc.HostCall(inst, args[0]); code.mov(code.ABI_PARAM2.cvt32(), ctx.FPCR().Value()); code.mov(code.ABI_PARAM3.cvt32(), static_cast(rounding_mode)); - code.lea(code.ABI_PARAM4, code.ptr[code.r15 + code.GetJitStateInfo().offsetof_fpsr_exc]); + code.lea(code.ABI_PARAM4, code.ptr[code.ABI_JIT_PTR + code.GetJitStateInfo().offsetof_fpsr_exc]); code.CallFunction(&FP::FPConvert); } } @@ -1581,7 +1581,7 @@ void EmitX64::EmitFPSingleToHalf(EmitContext& ctx, IR::Inst* inst) { ctx.reg_alloc.HostCall(inst, args[0]); code.mov(code.ABI_PARAM2.cvt32(), ctx.FPCR().Value()); code.mov(code.ABI_PARAM3.cvt32(), static_cast(rounding_mode)); - code.lea(code.ABI_PARAM4, code.ptr[code.r15 + code.GetJitStateInfo().offsetof_fpsr_exc]); + code.lea(code.ABI_PARAM4, code.ptr[code.ABI_JIT_PTR + code.GetJitStateInfo().offsetof_fpsr_exc]); code.CallFunction(&FP::FPConvert); } @@ -1595,7 +1595,7 @@ void EmitX64::EmitFPDoubleToHalf(EmitContext& ctx, IR::Inst* inst) { ctx.reg_alloc.HostCall(inst, args[0]); code.mov(code.ABI_PARAM2.cvt32(), ctx.FPCR().Value()); code.mov(code.ABI_PARAM3.cvt32(), static_cast(rounding_mode)); - code.lea(code.ABI_PARAM4, code.ptr[code.r15 + code.GetJitStateInfo().offsetof_fpsr_exc]); + code.lea(code.ABI_PARAM4, code.ptr[code.ABI_JIT_PTR + code.GetJitStateInfo().offsetof_fpsr_exc]); code.CallFunction(&FP::FPConvert); } @@ -1616,7 +1616,7 @@ void EmitX64::EmitFPDoubleToSingle(EmitContext& ctx, IR::Inst* inst) { ctx.reg_alloc.HostCall(inst, args[0]); code.mov(code.ABI_PARAM2.cvt32(), ctx.FPCR().Value()); code.mov(code.ABI_PARAM3.cvt32(), static_cast(rounding_mode)); - code.lea(code.ABI_PARAM4, code.ptr[code.r15 + code.GetJitStateInfo().offsetof_fpsr_exc]); + code.lea(code.ABI_PARAM4, code.ptr[code.ABI_JIT_PTR + code.GetJitStateInfo().offsetof_fpsr_exc]); code.CallFunction(&FP::FPConvert); } } @@ -1757,7 +1757,7 @@ static void EmitFPToFixed(BlockOfCode& code, EmitContext& ctx, IR::Inst* inst) { mp::cartesian_product{}); ctx.reg_alloc.HostCall(inst, args[0]); - code.lea(code.ABI_PARAM2, code.ptr[code.r15 + code.GetJitStateInfo().offsetof_fpsr_exc]); + code.lea(code.ABI_PARAM2, code.ptr[code.ABI_JIT_PTR + code.GetJitStateInfo().offsetof_fpsr_exc]); code.mov(code.ABI_PARAM3.cvt32(), ctx.FPCR().Value()); code.CallFunction(lut.at(std::make_tuple(fbits, rounding_mode))); } diff --git a/src/dynarmic/src/dynarmic/backend/x64/emit_x64_memory.cpp.inc b/src/dynarmic/src/dynarmic/backend/x64/emit_x64_memory.cpp.inc index 272b896ae3..34f77b0446 100644 --- a/src/dynarmic/src/dynarmic/backend/x64/emit_x64_memory.cpp.inc +++ b/src/dynarmic/src/dynarmic/backend/x64/emit_x64_memory.cpp.inc @@ -28,27 +28,24 @@ std::optional AxxEmitX64::ShouldFastmem(AxxEmitC FakeCall AxxEmitX64::FastmemCallback(u64 rip_) { const auto iter = fastmem_patch_info.find(rip_); - - if (iter == fastmem_patch_info.end()) { + if (iter != fastmem_patch_info.end()) { + FakeCall result{ + .call_rip = iter->second.callback, + .ret_rip = iter->second.resume_rip, + }; + if (iter->second.recompile) { + const auto marker = iter->second.marker; + do_not_fastmem.insert(marker); + InvalidateBasicBlocks({std::get<0>(marker)}); + } + return result; + } else { fmt::print("dynarmic: Segfault happened within JITted code at rip = {:016x}\n", rip_); fmt::print("Segfault wasn't at a fastmem patch location!\n"); fmt::print("Now dumping code.......\n\n"); Common::DumpDisassembledX64((void*)(rip_ & ~u64(0xFFF)), 0x1000); ASSERT_FALSE("iter != fastmem_patch_info.end()"); } - - FakeCall result{ - .call_rip = iter->second.callback, - .ret_rip = iter->second.resume_rip, - }; - - if (iter->second.recompile) { - const auto marker = iter->second.marker; - do_not_fastmem.insert(marker); - InvalidateBasicBlocks({std::get<0>(marker)}); - } - - return result; } template @@ -95,7 +92,7 @@ void AxxEmitX64::EmitMemoryRead(AxxEmitContext& ctx, IR::Inst* inst) { if (fastmem_marker) { // Use fastmem - bool require_abort_handling; + bool require_abort_handling = false; const auto src_ptr = EmitFastmemVAddr(code, ctx, *abort, vaddr, require_abort_handling); const auto location = EmitReadMemoryMov(code, value_idx, src_ptr, ordered); @@ -182,7 +179,7 @@ void AxxEmitX64::EmitMemoryWrite(AxxEmitContext& ctx, IR::Inst* inst) { if (fastmem_marker) { // Use fastmem - bool require_abort_handling; + bool require_abort_handling = false; const auto dest_ptr = EmitFastmemVAddr(code, ctx, *abort, vaddr, require_abort_handling); const auto location = EmitWriteMemoryMov(code, dest_ptr, value_idx, ordered); @@ -230,7 +227,7 @@ void AxxEmitX64::EmitExclusiveReadMemory(AxxEmitContext& ctx, IR::Inst* inst) { ctx.reg_alloc.HostCall(inst, {}, args[1]); - code.mov(code.byte[r15 + offsetof(AxxJitState, exclusive_state)], u8(1)); + code.mov(code.byte[code.ABI_JIT_PTR + offsetof(AxxJitState, exclusive_state)], u8(1)); code.mov(code.ABI_PARAM1, reinterpret_cast(&conf)); if (ordered) { code.mfence(); @@ -248,7 +245,7 @@ void AxxEmitX64::EmitExclusiveReadMemory(AxxEmitContext& ctx, IR::Inst* inst) { ctx.reg_alloc.EndOfAllocScope(); ctx.reg_alloc.HostCall(nullptr); - code.mov(code.byte[r15 + offsetof(AxxJitState, exclusive_state)], u8(1)); + code.mov(code.byte[code.ABI_JIT_PTR + offsetof(AxxJitState, exclusive_state)], u8(1)); code.mov(code.ABI_PARAM1, reinterpret_cast(&conf)); ctx.reg_alloc.AllocStackSpace(16 + ABI_SHADOW_SPACE); code.lea(code.ABI_PARAM3, ptr[rsp + ABI_SHADOW_SPACE]); @@ -288,9 +285,9 @@ void AxxEmitX64::EmitExclusiveWriteMemory(AxxEmitContext& ctx, IR::Inst* inst) { Xbyak::Label end; code.mov(code.ABI_RETURN, u32(1)); - code.cmp(code.byte[r15 + offsetof(AxxJitState, exclusive_state)], u8(0)); + code.cmp(code.byte[code.ABI_JIT_PTR + offsetof(AxxJitState, exclusive_state)], u8(0)); code.je(end); - code.mov(code.byte[r15 + offsetof(AxxJitState, exclusive_state)], u8(0)); + code.mov(code.byte[code.ABI_JIT_PTR + offsetof(AxxJitState, exclusive_state)], u8(0)); code.mov(code.ABI_PARAM1, reinterpret_cast(&conf)); if constexpr (bitsize != 128) { using T = mcl::unsigned_integer_of_size; @@ -358,7 +355,7 @@ void AxxEmitX64::EmitExclusiveReadMemoryInline(AxxEmitContext& ctx, IR::Inst* in EmitExclusiveLock(code, conf, tmp, tmp2.cvt32()); - code.mov(code.byte[r15 + offsetof(AxxJitState, exclusive_state)], u8(1)); + code.mov(code.byte[code.ABI_JIT_PTR + offsetof(AxxJitState, exclusive_state)], u8(1)); code.mov(tmp, mcl::bit_cast(GetExclusiveMonitorAddressPointer(conf.global_monitor, conf.processor_id))); code.mov(qword[tmp], vaddr); @@ -442,14 +439,14 @@ void AxxEmitX64::EmitExclusiveWriteMemoryInline(AxxEmitContext& ctx, IR::Inst* i code.mov(tmp, mcl::bit_cast(GetExclusiveMonitorAddressPointer(conf.global_monitor, conf.processor_id))); code.mov(status, u32(1)); - code.cmp(code.byte[r15 + offsetof(AxxJitState, exclusive_state)], u8(0)); + code.cmp(code.byte[code.ABI_JIT_PTR + offsetof(AxxJitState, exclusive_state)], u8(0)); code.je(*end, code.T_NEAR); code.cmp(qword[tmp], vaddr); code.jne(*end, code.T_NEAR); EmitExclusiveTestAndClear(code, conf, vaddr, tmp, rax); - code.mov(code.byte[r15 + offsetof(AxxJitState, exclusive_state)], u8(0)); + code.mov(code.byte[code.ABI_JIT_PTR + offsetof(AxxJitState, exclusive_state)], u8(0)); code.mov(tmp, mcl::bit_cast(GetExclusiveMonitorValuePointer(conf.global_monitor, conf.processor_id))); if constexpr (bitsize == 128) { @@ -504,7 +501,6 @@ void AxxEmitX64::EmitExclusiveWriteMemoryInline(AxxEmitContext& ctx, IR::Inst* i } code.setnz(status.cvt8()); - ctx.deferred_emits.emplace_back([=, this] { code.L(*abort); code.call(wrapped_fn); @@ -518,24 +514,21 @@ void AxxEmitX64::EmitExclusiveWriteMemoryInline(AxxEmitContext& ctx, IR::Inst* i conf.recompile_on_exclusive_fastmem_failure, }); - code.cmp(al, 0); + code.xor_(status.cvt32(), status.cvt32()); //dep-break + code.test(code.al, code.al); code.setz(status.cvt8()); - code.movzx(status.cvt32(), status.cvt8()); code.jmp(*end, code.T_NEAR); }); } else { code.call(wrapped_fn); - code.cmp(al, 0); + code.xor_(status.cvt32(), status.cvt32()); //dep-break + code.test(code.al, code.al); code.setz(status.cvt8()); - code.movzx(status.cvt32(), status.cvt8()); } code.L(*end); - EmitExclusiveUnlock(code, conf, tmp, eax); - ctx.reg_alloc.DefineValue(inst, status); - EmitCheckMemoryAbort(ctx, inst); } diff --git a/src/dynarmic/src/dynarmic/backend/x64/emit_x64_memory.h b/src/dynarmic/src/dynarmic/backend/x64/emit_x64_memory.h index b25b33101c..75a47c6a80 100644 --- a/src/dynarmic/src/dynarmic/backend/x64/emit_x64_memory.h +++ b/src/dynarmic/src/dynarmic/backend/x64/emit_x64_memory.h @@ -46,26 +46,25 @@ void EmitDetectMisalignedVAddr(BlockOfCode& code, EmitContext& ctx, size_t bitsi code.test(vaddr, align_mask); - if (!ctx.conf.only_detect_misalignment_via_page_table_on_page_boundary) { + if (ctx.conf.only_detect_misalignment_via_page_table_on_page_boundary) { + const u32 page_align_mask = static_cast(page_size - 1) & ~align_mask; + + SharedLabel detect_boundary = GenSharedLabel(), resume = GenSharedLabel(); + + code.jnz(*detect_boundary, code.T_NEAR); + code.L(*resume); + + ctx.deferred_emits.emplace_back([=, &code] { + code.L(*detect_boundary); + code.mov(tmp, vaddr); + code.and_(tmp, page_align_mask); + code.cmp(tmp, page_align_mask); + code.jne(*resume, code.T_NEAR); + // NOTE: We expect to fallthrough into abort code here. + }); + } else { code.jnz(abort, code.T_NEAR); - return; } - - const u32 page_align_mask = static_cast(page_size - 1) & ~align_mask; - - SharedLabel detect_boundary = GenSharedLabel(), resume = GenSharedLabel(); - - code.jnz(*detect_boundary, code.T_NEAR); - code.L(*resume); - - ctx.deferred_emits.emplace_back([=, &code] { - code.L(*detect_boundary); - code.mov(tmp, vaddr); - code.and_(tmp, page_align_mask); - code.cmp(tmp, page_align_mask); - code.jne(*resume, code.T_NEAR); - // NOTE: We expect to fallthrough into abort code here. - }); } template @@ -202,7 +201,7 @@ template const void* EmitReadMemoryMov(BlockOfCode& code, int value_idx, const Xbyak::RegExp& addr, bool ordered) { if (ordered) { if constexpr (bitsize != 128) { - code.xor_(Xbyak::Reg32{value_idx}, Xbyak::Reg32{value_idx}); + code.xor_(Xbyak::Reg32(value_idx), Xbyak::Reg32(value_idx)); } else { code.xor_(eax, eax); code.xor_(ebx, ebx); @@ -214,59 +213,59 @@ const void* EmitReadMemoryMov(BlockOfCode& code, int value_idx, const Xbyak::Reg switch (bitsize) { case 8: code.lock(); - code.xadd(code.byte[addr], Xbyak::Reg32{value_idx}.cvt8()); + code.xadd(code.byte[addr], Xbyak::Reg32(value_idx).cvt8()); break; case 16: code.lock(); - code.xadd(word[addr], Xbyak::Reg16{value_idx}); + code.xadd(word[addr], Xbyak::Reg64(value_idx).cvt16()); break; case 32: code.lock(); - code.xadd(dword[addr], Xbyak::Reg32{value_idx}); + code.xadd(dword[addr], Xbyak::Reg64(value_idx).cvt32()); break; case 64: code.lock(); - code.xadd(qword[addr], Xbyak::Reg64{value_idx}); + code.xadd(qword[addr], Xbyak::Reg64(value_idx)); break; case 128: code.lock(); code.cmpxchg16b(xword[addr]); if (code.HasHostFeature(HostFeature::SSE41)) { - code.movq(Xbyak::Xmm{value_idx}, rax); - code.pinsrq(Xbyak::Xmm{value_idx}, rdx, 1); + code.movq(Xbyak::Xmm(value_idx), rax); + code.pinsrq(Xbyak::Xmm(value_idx), rdx, 1); } else { - code.movq(Xbyak::Xmm{value_idx}, rax); + code.movq(Xbyak::Xmm(value_idx), rax); code.movq(xmm0, rdx); - code.punpcklqdq(Xbyak::Xmm{value_idx}, xmm0); + code.punpcklqdq(Xbyak::Xmm(value_idx), xmm0); } break; default: ASSERT_FALSE("Invalid bitsize"); } return fastmem_location; + } else { + const void* fastmem_location = code.getCurr(); + switch (bitsize) { + case 8: + code.movzx(Xbyak::Reg64(value_idx).cvt32(), code.byte[addr]); + break; + case 16: + code.movzx(Xbyak::Reg64(value_idx).cvt32(), word[addr]); + break; + case 32: + code.mov(Xbyak::Reg64(value_idx).cvt32(), dword[addr]); + break; + case 64: + code.mov(Xbyak::Reg64(value_idx), qword[addr]); + break; + case 128: + code.movups(Xbyak::Xmm(value_idx), xword[addr]); + break; + default: + ASSERT_FALSE("Invalid bitsize"); + } + return fastmem_location; } - - const void* fastmem_location = code.getCurr(); - switch (bitsize) { - case 8: - code.movzx(Xbyak::Reg32{value_idx}, code.byte[addr]); - break; - case 16: - code.movzx(Xbyak::Reg32{value_idx}, word[addr]); - break; - case 32: - code.mov(Xbyak::Reg32{value_idx}, dword[addr]); - break; - case 64: - code.mov(Xbyak::Reg64{value_idx}, qword[addr]); - break; - case 128: - code.movups(Xbyak::Xmm{value_idx}, xword[addr]); - break; - default: - ASSERT_FALSE("Invalid bitsize"); - } - return fastmem_location; } template @@ -276,10 +275,10 @@ const void* EmitWriteMemoryMov(BlockOfCode& code, const Xbyak::RegExp& addr, int code.xor_(eax, eax); code.xor_(edx, edx); if (code.HasHostFeature(HostFeature::SSE41)) { - code.movq(rbx, Xbyak::Xmm{value_idx}); - code.pextrq(rcx, Xbyak::Xmm{value_idx}, 1); + code.movq(rbx, Xbyak::Xmm(value_idx)); + code.pextrq(rcx, Xbyak::Xmm(value_idx), 1); } else { - code.movaps(xmm0, Xbyak::Xmm{value_idx}); + code.movaps(xmm0, Xbyak::Xmm(value_idx)); code.movq(rbx, xmm0); code.punpckhqdq(xmm0, xmm0); code.movq(rcx, xmm0); @@ -289,16 +288,16 @@ const void* EmitWriteMemoryMov(BlockOfCode& code, const Xbyak::RegExp& addr, int const void* fastmem_location = code.getCurr(); switch (bitsize) { case 8: - code.xchg(code.byte[addr], Xbyak::Reg64{value_idx}.cvt8()); + code.xchg(code.byte[addr], Xbyak::Reg64(value_idx).cvt8()); break; case 16: - code.xchg(word[addr], Xbyak::Reg16{value_idx}); + code.xchg(word[addr], Xbyak::Reg64(value_idx).cvt16()); break; case 32: - code.xchg(dword[addr], Xbyak::Reg32{value_idx}); + code.xchg(dword[addr], Xbyak::Reg64(value_idx).cvt32()); break; case 64: - code.xchg(qword[addr], Xbyak::Reg64{value_idx}); + code.xchg(qword[addr], Xbyak::Reg64(value_idx)); break; case 128: { Xbyak::Label loop; @@ -312,29 +311,29 @@ const void* EmitWriteMemoryMov(BlockOfCode& code, const Xbyak::RegExp& addr, int ASSERT_FALSE("Invalid bitsize"); } return fastmem_location; + } else { + const void* fastmem_location = code.getCurr(); + switch (bitsize) { + case 8: + code.mov(code.byte[addr], Xbyak::Reg64(value_idx).cvt8()); + break; + case 16: + code.mov(word[addr], Xbyak::Reg64(value_idx).cvt16()); + break; + case 32: + code.mov(dword[addr], Xbyak::Reg64(value_idx).cvt32()); + break; + case 64: + code.mov(qword[addr], Xbyak::Reg64(value_idx)); + break; + case 128: + code.movups(xword[addr], Xbyak::Xmm(value_idx)); + break; + default: + ASSERT_FALSE("Invalid bitsize"); + } + return fastmem_location; } - - const void* fastmem_location = code.getCurr(); - switch (bitsize) { - case 8: - code.mov(code.byte[addr], Xbyak::Reg64{value_idx}.cvt8()); - break; - case 16: - code.mov(word[addr], Xbyak::Reg16{value_idx}); - break; - case 32: - code.mov(dword[addr], Xbyak::Reg32{value_idx}); - break; - case 64: - code.mov(qword[addr], Xbyak::Reg64{value_idx}); - break; - case 128: - code.movups(xword[addr], Xbyak::Xmm{value_idx}); - break; - default: - ASSERT_FALSE("Invalid bitsize"); - } - return fastmem_location; } template diff --git a/src/dynarmic/src/dynarmic/backend/x64/emit_x64_saturation.cpp b/src/dynarmic/src/dynarmic/backend/x64/emit_x64_saturation.cpp index d36a75426a..e795181872 100644 --- a/src/dynarmic/src/dynarmic/backend/x64/emit_x64_saturation.cpp +++ b/src/dynarmic/src/dynarmic/backend/x64/emit_x64_saturation.cpp @@ -69,7 +69,7 @@ void EmitSignedSaturatedOp(BlockOfCode& code, EmitContext& ctx, IR::Inst* inst) ctx.reg_alloc.DefineValue(overflow_inst, overflow); } } else { - code.or_(code.byte[code.r15 + code.GetJitStateInfo().offsetof_fpsr_qc], overflow.cvt8()); + code.or_(code.byte[code.ABI_JIT_PTR + code.GetJitStateInfo().offsetof_fpsr_qc], overflow.cvt8()); } ctx.reg_alloc.DefineValue(inst, result); @@ -98,7 +98,7 @@ void EmitUnsignedSaturatedOp(BlockOfCode& code, EmitContext& ctx, IR::Inst* inst const Xbyak::Reg overflow = ctx.reg_alloc.ScratchGpr(); code.setb(overflow.cvt8()); - code.or_(code.byte[code.r15 + code.GetJitStateInfo().offsetof_fpsr_qc], overflow.cvt8()); + code.or_(code.byte[code.ABI_JIT_PTR + code.GetJitStateInfo().offsetof_fpsr_qc], overflow.cvt8()); ctx.reg_alloc.DefineValue(inst, addend); } @@ -226,7 +226,7 @@ void EmitX64::EmitSignedSaturatedDoublingMultiplyReturnHigh16(EmitContext& ctx, code.cmovns(y, tmp); code.sets(tmp.cvt8()); - code.or_(code.byte[code.r15 + code.GetJitStateInfo().offsetof_fpsr_qc], tmp.cvt8()); + code.or_(code.byte[code.ABI_JIT_PTR + code.GetJitStateInfo().offsetof_fpsr_qc], tmp.cvt8()); ctx.reg_alloc.DefineValue(inst, y); } @@ -250,7 +250,7 @@ void EmitX64::EmitSignedSaturatedDoublingMultiplyReturnHigh32(EmitContext& ctx, code.cmovns(y.cvt32(), tmp.cvt32()); code.sets(tmp.cvt8()); - code.or_(code.byte[code.r15 + code.GetJitStateInfo().offsetof_fpsr_qc], tmp.cvt8()); + code.or_(code.byte[code.ABI_JIT_PTR + code.GetJitStateInfo().offsetof_fpsr_qc], tmp.cvt8()); ctx.reg_alloc.DefineValue(inst, y); } diff --git a/src/dynarmic/src/dynarmic/backend/x64/emit_x64_vector.cpp b/src/dynarmic/src/dynarmic/backend/x64/emit_x64_vector.cpp index e9b8866b52..e1b9e54df8 100644 --- a/src/dynarmic/src/dynarmic/backend/x64/emit_x64_vector.cpp +++ b/src/dynarmic/src/dynarmic/backend/x64/emit_x64_vector.cpp @@ -25,6 +25,7 @@ #include "dynarmic/backend/x64/constants.h" #include "dynarmic/backend/x64/emit_x64.h" #include "dynarmic/common/math_util.h" +#include "dynarmic/interface/optimization_flags.h" #include "dynarmic/ir/basic_block.h" #include "dynarmic/ir/microinstruction.h" #include "dynarmic/ir/opcodes.h" @@ -109,7 +110,7 @@ static void EmitOneArgumentFallbackWithSaturation(BlockOfCode& code, EmitContext ctx.reg_alloc.ReleaseStackSpace(stack_space + ABI_SHADOW_SPACE); - code.or_(code.byte[code.r15 + code.GetJitStateInfo().offsetof_fpsr_qc], code.ABI_RETURN.cvt8()); + code.or_(code.byte[code.ABI_JIT_PTR + code.GetJitStateInfo().offsetof_fpsr_qc], code.ABI_RETURN.cvt8()); ctx.reg_alloc.DefineValue(inst, result); } @@ -137,7 +138,7 @@ static void EmitTwoArgumentFallbackWithSaturation(BlockOfCode& code, EmitContext ctx.reg_alloc.ReleaseStackSpace(stack_space + ABI_SHADOW_SPACE); - code.or_(code.byte[code.r15 + code.GetJitStateInfo().offsetof_fpsr_qc], code.ABI_RETURN.cvt8()); + code.or_(code.byte[code.ABI_JIT_PTR + code.GetJitStateInfo().offsetof_fpsr_qc], code.ABI_RETURN.cvt8()); ctx.reg_alloc.DefineValue(inst, result); } @@ -164,7 +165,7 @@ static void EmitTwoArgumentFallbackWithSaturationAndImmediate(BlockOfCode& code, ctx.reg_alloc.ReleaseStackSpace(stack_space + ABI_SHADOW_SPACE); - code.or_(code.byte[code.r15 + code.GetJitStateInfo().offsetof_fpsr_qc], code.ABI_RETURN.cvt8()); + code.or_(code.byte[code.ABI_JIT_PTR + code.GetJitStateInfo().offsetof_fpsr_qc], code.ABI_RETURN.cvt8()); ctx.reg_alloc.DefineValue(inst, result); } @@ -1009,10 +1010,7 @@ void EmitX64::EmitVectorCountLeadingZeros8(EmitContext& ctx, IR::Inst* inst) { code.gf2p8affineqb(result, code.BConst<64>(xword, 0xaaccf0ff'00000000), 8); ctx.reg_alloc.DefineValue(inst, result); - return; - } - - if (code.HasHostFeature(HostFeature::SSSE3)) { + } else if (code.HasHostFeature(HostFeature::SSSE3)) { auto args = ctx.reg_alloc.GetArgumentInfo(inst); const Xbyak::Xmm data = ctx.reg_alloc.UseScratchXmm(args[0]); @@ -1034,10 +1032,9 @@ void EmitX64::EmitVectorCountLeadingZeros8(EmitContext& ctx, IR::Inst* inst) { code.paddb(data, tmp1); ctx.reg_alloc.DefineValue(inst, data); - return; + } else { + EmitOneArgumentFallback(code, ctx, inst, EmitVectorCountLeadingZeros); } - - EmitOneArgumentFallback(code, ctx, inst, EmitVectorCountLeadingZeros); } void EmitX64::EmitVectorCountLeadingZeros16(EmitContext& ctx, IR::Inst* inst) { @@ -1070,10 +1067,7 @@ void EmitX64::EmitVectorCountLeadingZeros16(EmitContext& ctx, IR::Inst* inst) { code.vpshufb(result, result, data); ctx.reg_alloc.DefineValue(inst, result); - return; - } - - if (code.HasHostFeature(HostFeature::SSSE3)) { + } else if (code.HasHostFeature(HostFeature::SSSE3)) { auto args = ctx.reg_alloc.GetArgumentInfo(inst); const Xbyak::Xmm data = ctx.reg_alloc.UseScratchXmm(args[0]); @@ -1106,24 +1100,33 @@ void EmitX64::EmitVectorCountLeadingZeros16(EmitContext& ctx, IR::Inst* inst) { code.pshufb(result, data); ctx.reg_alloc.DefineValue(inst, result); - return; + } else { + EmitOneArgumentFallback(code, ctx, inst, EmitVectorCountLeadingZeros); } - - EmitOneArgumentFallback(code, ctx, inst, EmitVectorCountLeadingZeros); } void EmitX64::EmitVectorCountLeadingZeros32(EmitContext& ctx, IR::Inst* inst) { + auto args = ctx.reg_alloc.GetArgumentInfo(inst); if (code.HasHostFeature(HostFeature::AVX512_Ortho | HostFeature::AVX512CD)) { - auto args = ctx.reg_alloc.GetArgumentInfo(inst); - const Xbyak::Xmm data = ctx.reg_alloc.UseScratchXmm(args[0]); code.vplzcntd(data, data); - ctx.reg_alloc.DefineValue(inst, data); - return; + // See https://stackoverflow.com/questions/58823140/count-leading-zero-bits-for-each-element-in-avx2-vector-emulate-mm256-lzcnt-ep/58827596#58827596 + } else if (code.HasHostFeature(HostFeature::AVX2)) { + const Xbyak::Xmm data = ctx.reg_alloc.UseScratchXmm(args[0]); + const Xbyak::Xmm temp = ctx.reg_alloc.ScratchXmm(); + code.vmovdqa(temp, data); + code.vpsrld(data, data, 8); + code.vpandn(data, data, temp); + code.vmovdqa(temp, code.Const(xword, 0x0000009E0000009E, 0x0000009E0000009E)); + code.vcvtdq2ps(data, data); + code.vpsrld(data, data, 23); + code.vpsubusw(data, temp, data); + code.vpminsw(data, data, code.Const(xword, 0x0000002000000020, 0x0000002000000020)); + ctx.reg_alloc.DefineValue(inst, data); + } else { + EmitOneArgumentFallback(code, ctx, inst, EmitVectorCountLeadingZeros); } - - EmitOneArgumentFallback(code, ctx, inst, EmitVectorCountLeadingZeros); } void EmitX64::EmitVectorDeinterleaveEven8(EmitContext& ctx, IR::Inst* inst) { @@ -3323,7 +3326,7 @@ void EmitX64::EmitVectorPolynomialMultiply8(EmitContext& ctx, IR::Inst* inst) { code.paddb(mask, mask); code.paddb(xmm_a, xmm_a); code.pblendvb(result, alternate); - code.dec(counter); + code.sub(counter, 1); code.jnz(loop); ctx.reg_alloc.DefineValue(inst, result); @@ -3367,7 +3370,7 @@ void EmitX64::EmitVectorPolynomialMultiplyLong8(EmitContext& ctx, IR::Inst* inst code.paddw(mask, mask); code.paddw(xmm_a, xmm_a); code.pblendvb(result, alternate); - code.dec(counter); + code.sub(counter, 1); code.jnz(loop); ctx.reg_alloc.DefineValue(inst, result); @@ -4258,7 +4261,7 @@ static void EmitVectorSignedSaturatedAbs(size_t esize, BlockOfCode& code, EmitCo UNREACHABLE(); } - code.or_(code.dword[code.r15 + code.GetJitStateInfo().offsetof_fpsr_qc], bit); + code.or_(code.dword[code.ABI_JIT_PTR + code.GetJitStateInfo().offsetof_fpsr_qc], bit); ctx.reg_alloc.DefineValue(inst, data); } @@ -4393,7 +4396,7 @@ static void EmitVectorSignedSaturatedAccumulateUnsigned(BlockOfCode& code, EmitC const Xbyak::Reg32 mask = ctx.reg_alloc.ScratchGpr().cvt32(); code.pmovmskb(mask, xmm0); - code.or_(code.dword[code.r15 + code.GetJitStateInfo().offsetof_fpsr_qc], mask); + code.or_(code.dword[code.ABI_JIT_PTR + code.GetJitStateInfo().offsetof_fpsr_qc], mask); if (code.HasHostFeature(HostFeature::SSE41)) { code.pblendvb(result, tmp); @@ -4479,7 +4482,7 @@ static void EmitVectorSignedSaturatedDoublingMultiply16(BlockOfCode& code, EmitC const Xbyak::Reg32 bit = ctx.reg_alloc.ScratchGpr().cvt32(); code.pmovmskb(bit, upper_tmp); - code.or_(code.dword[code.r15 + code.GetJitStateInfo().offsetof_fpsr_qc], bit); + code.or_(code.dword[code.ABI_JIT_PTR + code.GetJitStateInfo().offsetof_fpsr_qc], bit); ctx.reg_alloc.DefineValue(inst, result); } @@ -4530,7 +4533,7 @@ void EmitVectorSignedSaturatedDoublingMultiply32(BlockOfCode& code, EmitContext& code.vpcmpeqd(mask, result, code.Const(xword, 0x8000000080000000, 0x8000000080000000)); code.vpxor(result, result, mask); code.pmovmskb(bit, mask); - code.or_(code.dword[code.r15 + code.GetJitStateInfo().offsetof_fpsr_qc], bit); + code.or_(code.dword[code.ABI_JIT_PTR + code.GetJitStateInfo().offsetof_fpsr_qc], bit); ctx.reg_alloc.Release(mask); ctx.reg_alloc.Release(bit); @@ -4586,7 +4589,7 @@ void EmitVectorSignedSaturatedDoublingMultiply32(BlockOfCode& code, EmitContext& code.pcmpeqd(tmp, result); code.pxor(result, tmp); code.pmovmskb(bit, tmp); - code.or_(code.dword[code.r15 + code.GetJitStateInfo().offsetof_fpsr_qc], bit); + code.or_(code.dword[code.ABI_JIT_PTR + code.GetJitStateInfo().offsetof_fpsr_qc], bit); ctx.reg_alloc.DefineValue(inst, result); } @@ -4620,7 +4623,7 @@ void EmitX64::EmitVectorSignedSaturatedDoublingMultiplyLong16(EmitContext& ctx, const Xbyak::Reg32 bit = ctx.reg_alloc.ScratchGpr().cvt32(); code.pmovmskb(bit, y); - code.or_(code.dword[code.r15 + code.GetJitStateInfo().offsetof_fpsr_qc], bit); + code.or_(code.dword[code.ABI_JIT_PTR + code.GetJitStateInfo().offsetof_fpsr_qc], bit); ctx.reg_alloc.DefineValue(inst, x); } @@ -4673,7 +4676,7 @@ void EmitX64::EmitVectorSignedSaturatedDoublingMultiplyLong32(EmitContext& ctx, code.pxor(x, y); code.pmovmskb(bit, y); } - code.or_(code.dword[code.r15 + code.GetJitStateInfo().offsetof_fpsr_qc], bit); + code.or_(code.dword[code.ABI_JIT_PTR + code.GetJitStateInfo().offsetof_fpsr_qc], bit); ctx.reg_alloc.DefineValue(inst, x); } @@ -4712,7 +4715,7 @@ static void EmitVectorSignedSaturatedNarrowToSigned(size_t original_esize, Block code.pcmpeqd(reconstructed, src); code.movmskps(bit, reconstructed); code.xor_(bit, 0b1111); - code.or_(code.dword[code.r15 + code.GetJitStateInfo().offsetof_fpsr_qc], bit); + code.or_(code.dword[code.ABI_JIT_PTR + code.GetJitStateInfo().offsetof_fpsr_qc], bit); ctx.reg_alloc.DefineValue(inst, dest); } @@ -4767,7 +4770,7 @@ static void EmitVectorSignedSaturatedNarrowToUnsigned(size_t original_esize, Blo code.pcmpeqd(reconstructed, src); code.movmskps(bit, reconstructed); code.xor_(bit, 0b1111); - code.or_(code.dword[code.r15 + code.GetJitStateInfo().offsetof_fpsr_qc], bit); + code.or_(code.dword[code.ABI_JIT_PTR + code.GetJitStateInfo().offsetof_fpsr_qc], bit); ctx.reg_alloc.DefineValue(inst, dest); } @@ -4870,7 +4873,7 @@ static void EmitVectorSignedSaturatedNeg(size_t esize, BlockOfCode& code, EmitCo // Check if any elements matched the mask prior to performing saturation. If so, set the Q bit. const Xbyak::Reg32 bit = ctx.reg_alloc.ScratchGpr().cvt32(); code.pmovmskb(bit, tmp); - code.or_(code.dword[code.r15 + code.GetJitStateInfo().offsetof_fpsr_qc], bit); + code.or_(code.dword[code.ABI_JIT_PTR + code.GetJitStateInfo().offsetof_fpsr_qc], bit); ctx.reg_alloc.DefineValue(inst, zero); } @@ -5641,6 +5644,7 @@ static void EmitVectorUnsignedAbsoluteDifference(size_t esize, EmitContext& ctx, break; } case 32: + // See https://stackoverflow.com/questions/3380785/compute-the-absolute-difference-between-unsigned-integers-using-sse/3527267#3527267 if (code.HasHostFeature(HostFeature::SSE41)) { const Xbyak::Xmm x = ctx.reg_alloc.UseScratchXmm(args[0]); const Xbyak::Xmm y = ctx.reg_alloc.UseXmm(args[1]); @@ -5652,16 +5656,33 @@ static void EmitVectorUnsignedAbsoluteDifference(size_t esize, EmitContext& ctx, } else { const Xbyak::Xmm x = ctx.reg_alloc.UseScratchXmm(args[0]); const Xbyak::Xmm y = ctx.reg_alloc.UseScratchXmm(args[1]); - - code.movdqa(temp, code.Const(xword, 0x8000000080000000, 0x8000000080000000)); - code.pxor(x, temp); - code.pxor(y, temp); - code.movdqa(temp, x); - code.psubd(temp, y); - code.pcmpgtd(y, x); - code.psrld(y, 1); - code.pxor(temp, y); - code.psubd(temp, y); + if (ctx.HasOptimization(OptimizationFlag::CodeSpeed)) { + // About 45 bytes + const Xbyak::Xmm temp_x = ctx.reg_alloc.ScratchXmm(); + const Xbyak::Xmm temp_y = ctx.reg_alloc.ScratchXmm(); + code.pcmpeqd(temp, temp); + code.pslld(temp, 31); + code.movdqa(temp_x, x); + code.movdqa(temp_y, y); + code.paddd(temp_x, x); + code.paddd(temp_y, y); + code.pcmpgtd(temp_y, temp_x); + code.psubd(x, y); + code.pandn(temp, temp_y); + code.pxor(x, y); + code.psubd(x, y); + } else { + // Smaller code size - about 36 bytes + code.movdqa(temp, code.Const(xword, 0x8000000080000000, 0x8000000080000000)); + code.pxor(x, temp); + code.pxor(y, temp); + code.movdqa(temp, x); + code.psubd(temp, y); + code.pcmpgtd(y, x); + code.psrld(y, 1); + code.pxor(temp, y); + code.psubd(temp, y); + } } break; } @@ -5727,10 +5748,7 @@ void EmitX64::EmitVectorUnsignedMultiply32(EmitContext& ctx, IR::Inst* inst) { code.vpmulld(result, x, y); ctx.reg_alloc.DefineValue(lower_inst, result); - return; - } - - if (code.HasHostFeature(HostFeature::AVX)) { + } else if (code.HasHostFeature(HostFeature::AVX)) { const Xbyak::Xmm x = ctx.reg_alloc.UseScratchXmm(args[0]); const Xbyak::Xmm y = ctx.reg_alloc.UseScratchXmm(args[1]); @@ -5749,39 +5767,33 @@ void EmitX64::EmitVectorUnsignedMultiply32(EmitContext& ctx, IR::Inst* inst) { code.shufps(result, x, 0b11011101); ctx.reg_alloc.DefineValue(upper_inst, result); - return; - } + } else { + const Xbyak::Xmm x = ctx.reg_alloc.UseScratchXmm(args[0]); + const Xbyak::Xmm y = ctx.reg_alloc.UseScratchXmm(args[1]); + const Xbyak::Xmm tmp = ctx.reg_alloc.ScratchXmm(); + const Xbyak::Xmm upper_result = upper_inst ? ctx.reg_alloc.ScratchXmm() : Xbyak::Xmm{-1}; + const Xbyak::Xmm lower_result = lower_inst ? ctx.reg_alloc.ScratchXmm() : Xbyak::Xmm{-1}; - const Xbyak::Xmm x = ctx.reg_alloc.UseScratchXmm(args[0]); - const Xbyak::Xmm y = ctx.reg_alloc.UseScratchXmm(args[1]); - const Xbyak::Xmm tmp = ctx.reg_alloc.ScratchXmm(); - const Xbyak::Xmm upper_result = ctx.reg_alloc.ScratchXmm(); - const Xbyak::Xmm lower_result = ctx.reg_alloc.ScratchXmm(); + // calculate unsigned multiply + code.movdqa(tmp, x); + code.pmuludq(tmp, y); + code.psrlq(x, 32); + code.psrlq(y, 32); + code.pmuludq(x, y); - // calculate unsigned multiply - code.movdqa(tmp, x); - code.pmuludq(tmp, y); - code.psrlq(x, 32); - code.psrlq(y, 32); - code.pmuludq(x, y); - - // put everything into place - code.pcmpeqw(upper_result, upper_result); - code.pcmpeqw(lower_result, lower_result); - code.psllq(upper_result, 32); - code.psrlq(lower_result, 32); - code.pand(upper_result, x); - code.pand(lower_result, tmp); - code.psrlq(tmp, 32); - code.psllq(x, 32); - code.por(upper_result, tmp); - code.por(lower_result, x); - - if (upper_inst) { - ctx.reg_alloc.DefineValue(upper_inst, upper_result); - } - if (lower_inst) { - ctx.reg_alloc.DefineValue(lower_inst, lower_result); + // put everything into place - only if needed + if (upper_inst) code.pcmpeqw(upper_result, upper_result); + if (lower_inst) code.pcmpeqw(lower_result, lower_result); + if (upper_inst) code.psllq(upper_result, 32); + if (lower_inst) code.psrlq(lower_result, 32); + if (upper_inst) code.pand(upper_result, x); + if (lower_inst) code.pand(lower_result, tmp); + if (upper_inst) code.psrlq(tmp, 32); + if (lower_inst) code.psllq(x, 32); + if (upper_inst) code.por(upper_result, tmp); + if (lower_inst) code.por(lower_result, x); + if (upper_inst) ctx.reg_alloc.DefineValue(upper_inst, upper_result); + if (lower_inst) ctx.reg_alloc.DefineValue(lower_inst, lower_result); } } diff --git a/src/dynarmic/src/dynarmic/backend/x64/emit_x64_vector_floating_point.cpp b/src/dynarmic/src/dynarmic/backend/x64/emit_x64_vector_floating_point.cpp index b24120c346..c8f0d9575c 100644 --- a/src/dynarmic/src/dynarmic/backend/x64/emit_x64_vector_floating_point.cpp +++ b/src/dynarmic/src/dynarmic/backend/x64/emit_x64_vector_floating_point.cpp @@ -450,7 +450,7 @@ void EmitTwoOpFallbackWithoutRegAlloc(BlockOfCode& code, EmitContext& ctx, Xbyak code.lea(code.ABI_PARAM1, ptr[rsp + ABI_SHADOW_SPACE + 0 * 16]); code.lea(code.ABI_PARAM2, ptr[rsp + ABI_SHADOW_SPACE + 1 * 16]); code.mov(code.ABI_PARAM3.cvt32(), fpcr); - code.lea(code.ABI_PARAM4, code.ptr[code.r15 + code.GetJitStateInfo().offsetof_fpsr_exc]); + code.lea(code.ABI_PARAM4, code.ptr[code.ABI_JIT_PTR + code.GetJitStateInfo().offsetof_fpsr_exc]); code.movaps(xword[code.ABI_PARAM2], arg1); code.CallFunction(fn); @@ -487,7 +487,7 @@ void EmitThreeOpFallbackWithoutRegAlloc(BlockOfCode& code, EmitContext& ctx, Xby code.lea(code.ABI_PARAM2, ptr[rsp + ABI_SHADOW_SPACE + 2 * 16]); code.lea(code.ABI_PARAM3, ptr[rsp + ABI_SHADOW_SPACE + 3 * 16]); code.mov(code.ABI_PARAM4.cvt32(), fpcr); - code.lea(rax, code.ptr[code.r15 + code.GetJitStateInfo().offsetof_fpsr_exc]); + code.lea(rax, code.ptr[code.ABI_JIT_PTR + code.GetJitStateInfo().offsetof_fpsr_exc]); code.mov(qword[rsp + ABI_SHADOW_SPACE + 0], rax); #else constexpr u32 stack_space = 3 * 16; @@ -496,7 +496,7 @@ void EmitThreeOpFallbackWithoutRegAlloc(BlockOfCode& code, EmitContext& ctx, Xby code.lea(code.ABI_PARAM2, ptr[rsp + ABI_SHADOW_SPACE + 1 * 16]); code.lea(code.ABI_PARAM3, ptr[rsp + ABI_SHADOW_SPACE + 2 * 16]); code.mov(code.ABI_PARAM4.cvt32(), fpcr); - code.lea(code.ABI_PARAM5, code.ptr[code.r15 + code.GetJitStateInfo().offsetof_fpsr_exc]); + code.lea(code.ABI_PARAM5, code.ptr[code.ABI_JIT_PTR + code.GetJitStateInfo().offsetof_fpsr_exc]); #endif code.movaps(xword[code.ABI_PARAM2], arg1); @@ -545,7 +545,7 @@ void EmitFourOpFallbackWithoutRegAlloc(BlockOfCode& code, EmitContext& ctx, Xbya code.lea(code.ABI_PARAM3, ptr[rsp + ABI_SHADOW_SPACE + 3 * 16]); code.lea(code.ABI_PARAM4, ptr[rsp + ABI_SHADOW_SPACE + 4 * 16]); code.mov(qword[rsp + ABI_SHADOW_SPACE + 0], ctx.FPCR(fpcr_controlled).Value()); - code.lea(rax, code.ptr[code.r15 + code.GetJitStateInfo().offsetof_fpsr_exc]); + code.lea(rax, code.ptr[code.ABI_JIT_PTR + code.GetJitStateInfo().offsetof_fpsr_exc]); code.mov(qword[rsp + ABI_SHADOW_SPACE + 8], rax); #else constexpr u32 stack_space = 4 * 16; @@ -555,7 +555,7 @@ void EmitFourOpFallbackWithoutRegAlloc(BlockOfCode& code, EmitContext& ctx, Xbya code.lea(code.ABI_PARAM3, ptr[rsp + ABI_SHADOW_SPACE + 2 * 16]); code.lea(code.ABI_PARAM4, ptr[rsp + ABI_SHADOW_SPACE + 3 * 16]); code.mov(code.ABI_PARAM5.cvt32(), ctx.FPCR(fpcr_controlled).Value()); - code.lea(code.ABI_PARAM6, code.ptr[code.r15 + code.GetJitStateInfo().offsetof_fpsr_exc]); + code.lea(code.ABI_PARAM6, code.ptr[code.ABI_JIT_PTR + code.GetJitStateInfo().offsetof_fpsr_exc]); #endif if constexpr (load_previous_result == LoadPreviousResult::Yes) { diff --git a/src/dynarmic/src/dynarmic/backend/x64/emit_x64_vector_saturation.cpp b/src/dynarmic/src/dynarmic/backend/x64/emit_x64_vector_saturation.cpp index 88bd41a47e..580a32dec8 100644 --- a/src/dynarmic/src/dynarmic/backend/x64/emit_x64_vector_saturation.cpp +++ b/src/dynarmic/src/dynarmic/backend/x64/emit_x64_vector_saturation.cpp @@ -62,7 +62,7 @@ void EmitVectorSaturatedNative(BlockOfCode& code, EmitContext& ctx, IR::Inst* in code.test(overflow.cvt32(), overflow.cvt32()); } code.setnz(overflow); - code.or_(code.byte[code.r15 + code.GetJitStateInfo().offsetof_fpsr_qc], overflow); + code.or_(code.byte[code.ABI_JIT_PTR + code.GetJitStateInfo().offsetof_fpsr_qc], overflow); ctx.reg_alloc.DefineValue(inst, result); } @@ -104,7 +104,7 @@ void EmitVectorSignedSaturated(BlockOfCode& code, EmitContext& ctx, IR::Inst* in code.ktestb(k1, k1); code.setnz(overflow); - code.or_(code.byte[code.r15 + code.GetJitStateInfo().offsetof_fpsr_qc], overflow); + code.or_(code.byte[code.ABI_JIT_PTR + code.GetJitStateInfo().offsetof_fpsr_qc], overflow); ctx.reg_alloc.DefineValue(inst, result); return; @@ -160,7 +160,7 @@ void EmitVectorSignedSaturated(BlockOfCode& code, EmitContext& ctx, IR::Inst* in code.test(overflow.cvt32(), overflow.cvt32()); } code.setnz(overflow); - code.or_(code.byte[code.r15 + code.GetJitStateInfo().offsetof_fpsr_qc], overflow); + code.or_(code.byte[code.ABI_JIT_PTR + code.GetJitStateInfo().offsetof_fpsr_qc], overflow); if (code.HasHostFeature(HostFeature::SSE41)) { FCODE(blendvp)(result, tmp); @@ -204,7 +204,7 @@ void EmitVectorUnsignedSaturated(BlockOfCode& code, EmitContext& ctx, IR::Inst* code.ktestb(k1, k1); code.setnz(overflow); - code.or_(code.byte[code.r15 + code.GetJitStateInfo().offsetof_fpsr_qc], overflow); + code.or_(code.byte[code.ABI_JIT_PTR + code.GetJitStateInfo().offsetof_fpsr_qc], overflow); ctx.reg_alloc.DefineValue(inst, result); return; @@ -263,7 +263,7 @@ void EmitVectorUnsignedSaturated(BlockOfCode& code, EmitContext& ctx, IR::Inst* } code.setnz(overflow); - code.or_(code.byte[code.r15 + code.GetJitStateInfo().offsetof_fpsr_qc], overflow); + code.or_(code.byte[code.ABI_JIT_PTR + code.GetJitStateInfo().offsetof_fpsr_qc], overflow); if constexpr (op == Op::Add) { code.por(result, tmp); diff --git a/src/dynarmic/src/dynarmic/backend/x64/exclusive_monitor.cpp b/src/dynarmic/src/dynarmic/backend/x64/exclusive_monitor.cpp index 09ef60205f..f8237c99e8 100644 --- a/src/dynarmic/src/dynarmic/backend/x64/exclusive_monitor.cpp +++ b/src/dynarmic/src/dynarmic/backend/x64/exclusive_monitor.cpp @@ -14,7 +14,7 @@ namespace Dynarmic { -ExclusiveMonitor::ExclusiveMonitor(size_t processor_count) +ExclusiveMonitor::ExclusiveMonitor(std::size_t processor_count) : exclusive_addresses(processor_count, INVALID_EXCLUSIVE_ADDRESS), exclusive_values(processor_count) {} size_t ExclusiveMonitor::GetProcessorCount() const { @@ -29,20 +29,16 @@ void ExclusiveMonitor::Unlock() { lock.Unlock(); } -bool ExclusiveMonitor::CheckAndClear(size_t processor_id, VAddr address) { +bool ExclusiveMonitor::CheckAndClear(std::size_t processor_id, VAddr address) { const VAddr masked_address = address & RESERVATION_GRANULE_MASK; - Lock(); if (exclusive_addresses[processor_id] != masked_address) { Unlock(); return false; } - - for (VAddr& other_address : exclusive_addresses) { - if (other_address == masked_address) { + for (VAddr& other_address : exclusive_addresses) + if (other_address == masked_address) other_address = INVALID_EXCLUSIVE_ADDRESS; - } - } return true; } diff --git a/src/dynarmic/src/dynarmic/backend/x64/hostloc.h b/src/dynarmic/src/dynarmic/backend/x64/hostloc.h index 1b27edbdee..d6fb88554e 100644 --- a/src/dynarmic/src/dynarmic/backend/x64/hostloc.h +++ b/src/dynarmic/src/dynarmic/backend/x64/hostloc.h @@ -13,9 +13,9 @@ namespace Dynarmic::Backend::X64 { -// Our static vector will contain 32 elements, stt. an uint16_t will fill up 64 bytes +// Our static vector will contain 32 elements, stt. an uint8_t will fill up 64 bytes // (an entire cache line). Thanks. -enum class HostLoc : uint16_t { +enum class HostLoc : std::uint8_t { // Ordering of the registers is intentional. See also: HostLocToX64. RAX, RCX, @@ -60,48 +60,48 @@ enum class HostLoc : uint16_t { constexpr size_t NonSpillHostLocCount = static_cast(HostLoc::FirstSpill); -inline bool HostLocIsGPR(HostLoc reg) { +constexpr bool HostLocIsGPR(HostLoc reg) { return reg >= HostLoc::RAX && reg <= HostLoc::R15; } -inline bool HostLocIsXMM(HostLoc reg) { +constexpr bool HostLocIsXMM(HostLoc reg) { return reg >= HostLoc::XMM0 && reg <= HostLoc::XMM15; } -inline bool HostLocIsRegister(HostLoc reg) { +constexpr bool HostLocIsRegister(HostLoc reg) { return HostLocIsGPR(reg) || HostLocIsXMM(reg); } -inline bool HostLocIsFlag(HostLoc reg) { +constexpr bool HostLocIsFlag(HostLoc reg) { return reg >= HostLoc::CF && reg <= HostLoc::OF; } -inline HostLoc HostLocRegIdx(int idx) { +constexpr HostLoc HostLocRegIdx(int idx) { ASSERT(idx >= 0 && idx <= 15); - return static_cast(idx); + return HostLoc(idx); } -inline HostLoc HostLocXmmIdx(int idx) { +constexpr HostLoc HostLocXmmIdx(int idx) { ASSERT(idx >= 0 && idx <= 15); - return static_cast(static_cast(HostLoc::XMM0) + idx); + return HostLoc(size_t(HostLoc::XMM0) + idx); } -inline HostLoc HostLocSpill(size_t i) { - return static_cast(static_cast(HostLoc::FirstSpill) + i); +constexpr HostLoc HostLocSpill(size_t i) { + return HostLoc(size_t(HostLoc::FirstSpill) + i); } -inline bool HostLocIsSpill(HostLoc reg) { +constexpr bool HostLocIsSpill(HostLoc reg) { return reg >= HostLoc::FirstSpill; } -inline size_t HostLocBitWidth(HostLoc loc) { +constexpr size_t HostLocBitWidth(HostLoc loc) { if (HostLocIsGPR(loc)) return 64; - if (HostLocIsXMM(loc)) + else if (HostLocIsXMM(loc)) return 128; - if (HostLocIsSpill(loc)) + else if (HostLocIsSpill(loc)) return 128; - if (HostLocIsFlag(loc)) + else if (HostLocIsFlag(loc)) return 1; UNREACHABLE(); } @@ -109,6 +109,8 @@ inline size_t HostLocBitWidth(HostLoc loc) { using HostLocList = std::initializer_list; // RSP is preserved for function calls +// R13 contains fastmem pointer if any +// R14 contains the pagetable pointer // R15 contains the JitState pointer const HostLocList any_gpr = { HostLoc::RAX, @@ -125,12 +127,16 @@ const HostLocList any_gpr = { HostLoc::R12, HostLoc::R13, HostLoc::R14, + //HostLoc::R15, }; // XMM0 is reserved for use by instructions that implicitly use it as an argument +// XMM1 is used by 128 mem accessors +// XMM2 is also used by that (and other stuff) +// Basically dont use either XMM0, XMM1 or XMM2 ever; they're left for the regsel const HostLocList any_xmm = { - HostLoc::XMM1, - HostLoc::XMM2, + //HostLoc::XMM1, + //HostLoc::XMM2, HostLoc::XMM3, HostLoc::XMM4, HostLoc::XMM5, diff --git a/src/dynarmic/src/dynarmic/backend/x64/reg_alloc.cpp b/src/dynarmic/src/dynarmic/backend/x64/reg_alloc.cpp index 916c74193c..fa6006ed2a 100644 --- a/src/dynarmic/src/dynarmic/backend/x64/reg_alloc.cpp +++ b/src/dynarmic/src/dynarmic/backend/x64/reg_alloc.cpp @@ -357,9 +357,8 @@ void RegAlloc::HostCall(IR::Inst* result_def, static const boost::container::static_vector other_caller_save = [args_hostloc]() noexcept { boost::container::static_vector ret(ABI_ALL_CALLER_SAVE.begin(), ABI_ALL_CALLER_SAVE.end()); ret.erase(std::find(ret.begin(), ret.end(), ABI_RETURN)); - for (auto const hostloc : args_hostloc) { + for (auto const hostloc : args_hostloc) ret.erase(std::find(ret.begin(), ret.end(), hostloc)); - } return ret; }(); @@ -368,7 +367,7 @@ void RegAlloc::HostCall(IR::Inst* result_def, DefineValueImpl(result_def, ABI_RETURN); } - for (size_t i = 0; i < args_count; i++) { + for (size_t i = 0; i < args.size(); i++) { if (args[i] && !args[i]->get().IsVoid()) { UseScratch(*args[i], args_hostloc[i]); // LLVM puts the burden of zero-extension of 8 and 16 bit values on the caller instead of the callee @@ -383,36 +382,35 @@ void RegAlloc::HostCall(IR::Inst* result_def, case IR::Type::U32: code->mov(reg.cvt32(), reg.cvt32()); break; + case IR::Type::U64: + break; //no op default: - break; // Nothing needs to be done + UNREACHABLE(); } } } - for (size_t i = 0; i < args_count; i++) { + for (size_t i = 0; i < args.size(); i++) if (!args[i]) { // TODO: Force spill ScratchGpr(args_hostloc[i]); } - } - - for (HostLoc caller_saved : other_caller_save) { + for (auto const caller_saved : other_caller_save) ScratchImpl({caller_saved}); - } } void RegAlloc::AllocStackSpace(const size_t stack_space) noexcept { - ASSERT(stack_space < static_cast(std::numeric_limits::max())); + ASSERT(stack_space < size_t(std::numeric_limits::max())); ASSERT(reserved_stack_space == 0); reserved_stack_space = stack_space; - code->sub(code->rsp, static_cast(stack_space)); + code->sub(code->rsp, u32(stack_space)); } void RegAlloc::ReleaseStackSpace(const size_t stack_space) noexcept { - ASSERT(stack_space < static_cast(std::numeric_limits::max())); + ASSERT(stack_space < size_t(std::numeric_limits::max())); ASSERT(reserved_stack_space == stack_space); reserved_stack_space = 0; - code->add(code->rsp, static_cast(stack_space)); + code->add(code->rsp, u32(stack_space)); } HostLoc RegAlloc::SelectARegister(const boost::container::static_vector& desired_locations) const noexcept { @@ -429,13 +427,22 @@ HostLoc RegAlloc::SelectARegister(const boost::container::static_vector= HostLoc::R13 && *it <= HostLoc::R15) { + // skip, do not touch + // Intel recommends to reuse registers as soon as they're overwritable (DO NOT SPILL) + } else if (loc_info.IsEmpty()) { + it_empty_candidate = it; + break; + // No empty registers for some reason (very evil) - just do normal LRU } else { if (loc_info.lru_counter < min_lru_counter) { - if (loc_info.IsEmpty()) - it_empty_candidate = it; // Otherwise a "quasi"-LRU min_lru_counter = loc_info.lru_counter; if (*it >= HostLoc::R8 && *it <= HostLoc::R15) { @@ -446,9 +453,6 @@ HostLoc RegAlloc::SelectARegister(const boost::container::static_vectormov(reg, imm_value); } - return host_loc; - } - - if (HostLocIsXMM(host_loc)) { + } else if (HostLocIsXMM(host_loc)) { const Xbyak::Xmm reg = HostLocToXmm(host_loc); const u64 imm_value = imm.GetImmediateAsU64(); if (imm_value == 0) { @@ -508,22 +508,19 @@ HostLoc RegAlloc::LoadImmediate(IR::Value imm, HostLoc host_loc) noexcept { } else { MAYBE_AVX(movaps, reg, code->Const(code->xword, imm_value)); } - return host_loc; + } else { + UNREACHABLE(); } - - UNREACHABLE(); + return host_loc; } void RegAlloc::Move(HostLoc to, HostLoc from) noexcept { const size_t bit_width = LocInfo(from).GetMaxBitWidth(); - ASSERT(LocInfo(to).IsEmpty() && !LocInfo(from).IsLocked()); ASSERT(bit_width <= HostLocBitWidth(to)); - - if (!LocInfo(from).IsEmpty()) { - EmitMove(bit_width, to, from); - LocInfo(to) = std::exchange(LocInfo(from), {}); - } + ASSERT_MSG(!LocInfo(from).IsEmpty(), "Mov eliminated"); + EmitMove(bit_width, to, from); + LocInfo(to) = std::exchange(LocInfo(from), {}); } void RegAlloc::CopyToScratch(size_t bit_width, HostLoc to, HostLoc from) noexcept { @@ -557,30 +554,44 @@ void RegAlloc::SpillRegister(HostLoc loc) noexcept { ASSERT_MSG(HostLocIsRegister(loc), "Only registers can be spilled"); ASSERT_MSG(!LocInfo(loc).IsEmpty(), "There is no need to spill unoccupied registers"); ASSERT_MSG(!LocInfo(loc).IsLocked(), "Registers that have been allocated must not be spilt"); - - const HostLoc new_loc = FindFreeSpill(); + auto const new_loc = FindFreeSpill(HostLocIsXMM(loc)); Move(new_loc, loc); } -HostLoc RegAlloc::FindFreeSpill() const noexcept { - for (size_t i = static_cast(HostLoc::FirstSpill); i < hostloc_info.size(); i++) { - const auto loc = static_cast(i); - if (LocInfo(loc).IsEmpty()) { - return loc; - } +HostLoc RegAlloc::FindFreeSpill(bool is_xmm) const noexcept { +#if 0 + // TODO(lizzie): Ok, Windows hates XMM spills, this means less perf for windows + // but it's fine anyways. We can find other ways to cheat it later - but which?!?! + // we should NOT save xmm each block entering... MAYBE xbyak has a bug on start/end? + // TODO(lizzie): This needs to be investigated further later. + // Do not spill XMM into other XMM silly + if (!is_xmm) { + // TODO(lizzie): Using lower (xmm0 and such) registers results in issues/crashes - INVESTIGATE WHY + // Intel recommends to spill GPR onto XMM registers IF POSSIBLE + // TODO(lizzie): Issues on DBZ, theory: Scratch XMM not properly restored after a function call? + // Must sync with ABI registers (except XMM0, XMM1 and XMM2) + for (size_t i = size_t(HostLoc::XMM15); i >= size_t(HostLoc::XMM3); --i) + if (const auto loc = HostLoc(i); LocInfo(loc).IsEmpty()) + return loc; } - +#endif + // Otherwise go to stack spilling + for (size_t i = size_t(HostLoc::FirstSpill); i < hostloc_info.size(); ++i) + if (const auto loc = HostLoc(i); LocInfo(loc).IsEmpty()) + return loc; ASSERT_FALSE("All spill locations are full"); -} - -inline static Xbyak::RegExp SpillToOpArg_Helper1(HostLoc loc, size_t reserved_stack_space) noexcept { - ASSERT(HostLocIsSpill(loc)); - size_t i = static_cast(loc) - static_cast(HostLoc::FirstSpill); - ASSERT_MSG(i < SpillCount, "Spill index greater than number of available spill locations"); - return Xbyak::util::rsp + reserved_stack_space + ABI_SHADOW_SPACE + offsetof(StackLayout, spill) + i * sizeof(StackLayout::spill[0]); -} +}; void RegAlloc::EmitMove(const size_t bit_width, const HostLoc to, const HostLoc from) noexcept { + auto const spill_to_op_arg_helper = [&](HostLoc loc, size_t reserved_stack_space) { + ASSERT(HostLocIsSpill(loc)); + size_t i = size_t(loc) - size_t(HostLoc::FirstSpill); + ASSERT_MSG(i < SpillCount, "Spill index greater than number of available spill locations"); + return Xbyak::util::rsp + reserved_stack_space + ABI_SHADOW_SPACE + offsetof(StackLayout, spill) + i * sizeof(StackLayout::spill[0]); + }; + auto const spill_xmm_to_op = [&](const HostLoc loc) { + return Xbyak::util::xword[spill_to_op_arg_helper(loc, reserved_stack_space)]; + }; if (HostLocIsXMM(to) && HostLocIsXMM(from)) { MAYBE_AVX(movaps, HostLocToXmm(to), HostLocToXmm(from)); } else if (HostLocIsGPR(to) && HostLocIsGPR(from)) { @@ -605,7 +616,7 @@ void RegAlloc::EmitMove(const size_t bit_width, const HostLoc to, const HostLoc MAYBE_AVX(movd, HostLocToReg64(to).cvt32(), HostLocToXmm(from)); } } else if (HostLocIsXMM(to) && HostLocIsSpill(from)) { - const Xbyak::Address spill_addr = SpillToOpArg(from); + const Xbyak::Address spill_addr = spill_xmm_to_op(from); ASSERT(spill_addr.getBit() >= bit_width); switch (bit_width) { case 128: @@ -623,7 +634,7 @@ void RegAlloc::EmitMove(const size_t bit_width, const HostLoc to, const HostLoc UNREACHABLE(); } } else if (HostLocIsSpill(to) && HostLocIsXMM(from)) { - const Xbyak::Address spill_addr = SpillToOpArg(to); + const Xbyak::Address spill_addr = spill_xmm_to_op(to); ASSERT(spill_addr.getBit() >= bit_width); switch (bit_width) { case 128: @@ -643,16 +654,16 @@ void RegAlloc::EmitMove(const size_t bit_width, const HostLoc to, const HostLoc } else if (HostLocIsGPR(to) && HostLocIsSpill(from)) { ASSERT(bit_width != 128); if (bit_width == 64) { - code->mov(HostLocToReg64(to), Xbyak::util::qword[SpillToOpArg_Helper1(from, reserved_stack_space)]); + code->mov(HostLocToReg64(to), Xbyak::util::qword[spill_to_op_arg_helper(from, reserved_stack_space)]); } else { - code->mov(HostLocToReg64(to).cvt32(), Xbyak::util::dword[SpillToOpArg_Helper1(from, reserved_stack_space)]); + code->mov(HostLocToReg64(to).cvt32(), Xbyak::util::dword[spill_to_op_arg_helper(from, reserved_stack_space)]); } } else if (HostLocIsSpill(to) && HostLocIsGPR(from)) { ASSERT(bit_width != 128); if (bit_width == 64) { - code->mov(Xbyak::util::qword[SpillToOpArg_Helper1(to, reserved_stack_space)], HostLocToReg64(from)); + code->mov(Xbyak::util::qword[spill_to_op_arg_helper(to, reserved_stack_space)], HostLocToReg64(from)); } else { - code->mov(Xbyak::util::dword[SpillToOpArg_Helper1(to, reserved_stack_space)], HostLocToReg64(from).cvt32()); + code->mov(Xbyak::util::dword[spill_to_op_arg_helper(to, reserved_stack_space)], HostLocToReg64(from).cvt32()); } } else { ASSERT_FALSE("Invalid RegAlloc::EmitMove"); @@ -669,8 +680,4 @@ void RegAlloc::EmitExchange(const HostLoc a, const HostLoc b) noexcept { } } -Xbyak::Address RegAlloc::SpillToOpArg(const HostLoc loc) noexcept { - return Xbyak::util::xword[SpillToOpArg_Helper1(loc, reserved_stack_space)]; -} - } // namespace Dynarmic::Backend::X64 diff --git a/src/dynarmic/src/dynarmic/backend/x64/reg_alloc.h b/src/dynarmic/src/dynarmic/backend/x64/reg_alloc.h index 12b6010aa8..f70329f471 100644 --- a/src/dynarmic/src/dynarmic/backend/x64/reg_alloc.h +++ b/src/dynarmic/src/dynarmic/backend/x64/reg_alloc.h @@ -22,6 +22,7 @@ #include "dynarmic/backend/x64/hostloc.h" #include "dynarmic/backend/x64/stack_layout.h" #include "dynarmic/backend/x64/oparg.h" +#include "dynarmic/backend/x64/abi.h" #include "dynarmic/ir/cond.h" #include "dynarmic/ir/microinstruction.h" #include "dynarmic/ir/value.h" @@ -242,20 +243,19 @@ private: void MoveOutOfTheWay(HostLoc reg) noexcept; void SpillRegister(HostLoc loc) noexcept; - HostLoc FindFreeSpill() const noexcept; + HostLoc FindFreeSpill(bool is_xmm) const noexcept; inline HostLocInfo& LocInfo(const HostLoc loc) noexcept { - ASSERT(loc != HostLoc::RSP && loc != HostLoc::R15); + ASSERT(loc != HostLoc::RSP && loc != ABI_JIT_PTR); return hostloc_info[static_cast(loc)]; } inline const HostLocInfo& LocInfo(const HostLoc loc) const noexcept { - ASSERT(loc != HostLoc::RSP && loc != HostLoc::R15); + ASSERT(loc != HostLoc::RSP && loc != ABI_JIT_PTR); return hostloc_info[static_cast(loc)]; } void EmitMove(const size_t bit_width, const HostLoc to, const HostLoc from) noexcept; void EmitExchange(const HostLoc a, const HostLoc b) noexcept; - Xbyak::Address SpillToOpArg(const HostLoc loc) noexcept; //data alignas(64) boost::container::static_vector gpr_order; @@ -264,7 +264,7 @@ private: BlockOfCode* code = nullptr; size_t reserved_stack_space = 0; }; -// Ensure a cache line is used, this is primordial -static_assert(sizeof(boost::container::static_vector) == 64); +// Ensure a cache line (or less) is used, this is primordial +static_assert(sizeof(boost::container::static_vector) == 40); } // namespace Dynarmic::Backend::X64 diff --git a/src/dynarmic/src/dynarmic/backend/x64/verbose_debugging_output.cpp b/src/dynarmic/src/dynarmic/backend/x64/verbose_debugging_output.cpp index 3378786c46..b3a02005eb 100644 --- a/src/dynarmic/src/dynarmic/backend/x64/verbose_debugging_output.cpp +++ b/src/dynarmic/src/dynarmic/backend/x64/verbose_debugging_output.cpp @@ -22,7 +22,7 @@ void PrintVerboseDebuggingOutputLine(RegisterData& reg_data, HostLoc hostloc, si } else if (HostLocIsXMM(hostloc)) { return reg_data.xmms[HostLocToXmm(hostloc).getIdx()]; } else if (HostLocIsSpill(hostloc)) { - return (*reg_data.spill)[static_cast(hostloc) - static_cast(HostLoc::FirstSpill)]; + return (*reg_data.spill)[size_t(hostloc) - size_t(HostLoc::FirstSpill)]; } else { fmt::print("invalid hostloc! "); return {0, 0}; diff --git a/src/dynarmic/src/dynarmic/backend/x64/verbose_debugging_output.h b/src/dynarmic/src/dynarmic/backend/x64/verbose_debugging_output.h index 68d0ccff24..3f4823010b 100644 --- a/src/dynarmic/src/dynarmic/backend/x64/verbose_debugging_output.h +++ b/src/dynarmic/src/dynarmic/backend/x64/verbose_debugging_output.h @@ -16,7 +16,7 @@ namespace Dynarmic::Backend::X64 { -enum class HostLoc : uint16_t; +enum class HostLoc : std::uint8_t; using Vector = std::array; #ifdef _MSC_VER diff --git a/src/dynarmic/src/dynarmic/common/crypto/crc32.cpp b/src/dynarmic/src/dynarmic/common/crypto/crc32.cpp index c2821fa2c3..6b9c129a44 100644 --- a/src/dynarmic/src/dynarmic/common/crypto/crc32.cpp +++ b/src/dynarmic/src/dynarmic/common/crypto/crc32.cpp @@ -152,11 +152,9 @@ constexpr CRC32Table iso_table{ static u32 ComputeCRC32(const CRC32Table& table, u32 crc, const u64 value, int length) { const auto* data = reinterpret_cast(&value); - while (length-- > 0) { crc = (crc >> 8) ^ table[(crc ^ (*data++)) & 0xFF]; } - return crc; } diff --git a/src/dynarmic/src/dynarmic/common/spin_lock.h b/src/dynarmic/src/dynarmic/common/spin_lock.h index f653704db6..e97ba2897f 100644 --- a/src/dynarmic/src/dynarmic/common/spin_lock.h +++ b/src/dynarmic/src/dynarmic/common/spin_lock.h @@ -8,9 +8,8 @@ namespace Dynarmic { struct SpinLock { - void Lock(); - void Unlock(); - + void Lock() noexcept; + void Unlock() noexcept; volatile int storage = 0; }; diff --git a/src/dynarmic/src/dynarmic/common/spin_lock_arm64.cpp b/src/dynarmic/src/dynarmic/common/spin_lock_arm64.cpp index ccf807e2d2..7833b65403 100644 --- a/src/dynarmic/src/dynarmic/common/spin_lock_arm64.cpp +++ b/src/dynarmic/src/dynarmic/common/spin_lock_arm64.cpp @@ -73,12 +73,12 @@ void SpinLockImpl::Initialize() { } // namespace -void SpinLock::Lock() { +void SpinLock::Lock() noexcept { std::call_once(flag, &SpinLockImpl::Initialize, impl); impl.lock(&storage); } -void SpinLock::Unlock() { +void SpinLock::Unlock() noexcept { std::call_once(flag, &SpinLockImpl::Initialize, impl); impl.unlock(&storage); } diff --git a/src/dynarmic/src/dynarmic/common/spin_lock_x64.cpp b/src/dynarmic/src/dynarmic/common/spin_lock_x64.cpp index fdea94f4be..474c2f8404 100644 --- a/src/dynarmic/src/dynarmic/common/spin_lock_x64.cpp +++ b/src/dynarmic/src/dynarmic/common/spin_lock_x64.cpp @@ -16,15 +16,14 @@ namespace Dynarmic { void EmitSpinLockLock(Xbyak::CodeGenerator& code, Xbyak::Reg64 ptr, Xbyak::Reg32 tmp) { Xbyak::Label start, loop; - code.jmp(start); + code.jmp(start, code.T_NEAR); code.L(loop); code.pause(); code.L(start); code.mov(tmp, 1); - code.lock(); - code.xchg(code.dword[ptr], tmp); + /*code.lock();*/ code.xchg(code.dword[ptr], tmp); code.test(tmp, tmp); - code.jnz(loop); + code.jnz(loop, code.T_NEAR); } void EmitSpinLockUnlock(Xbyak::CodeGenerator& code, Xbyak::Reg64 ptr, Xbyak::Reg32 tmp) { @@ -63,12 +62,12 @@ void SpinLockImpl::Initialize() { } // namespace -void SpinLock::Lock() { +void SpinLock::Lock() noexcept { std::call_once(flag, &SpinLockImpl::Initialize, impl); impl.lock(&storage); } -void SpinLock::Unlock() { +void SpinLock::Unlock() noexcept { std::call_once(flag, &SpinLockImpl::Initialize, impl); impl.unlock(&storage); } diff --git a/src/dynarmic/src/dynarmic/frontend/A32/translate/impl/load_store.cpp b/src/dynarmic/src/dynarmic/frontend/A32/translate/impl/load_store.cpp index 7ef8b7e890..6a25eb97c6 100644 --- a/src/dynarmic/src/dynarmic/frontend/A32/translate/impl/load_store.cpp +++ b/src/dynarmic/src/dynarmic/frontend/A32/translate/impl/load_store.cpp @@ -109,13 +109,11 @@ bool TranslatorVisitor::arm_LDR_imm(Cond cond, bool P, bool U, bool W, Reg n, Re if (t == Reg::PC) { ir.LoadWritePC(data); - if (!P && W && n == Reg::R13) { ir.SetTerm(IR::Term::PopRSBHint{}); } else { ir.SetTerm(IR::Term::FastDispatchHint{}); } - return false; } @@ -145,7 +143,11 @@ bool TranslatorVisitor::arm_LDR_reg(Cond cond, bool P, bool U, bool W, Reg n, Re if (t == Reg::PC) { ir.LoadWritePC(data); - ir.SetTerm(IR::Term::FastDispatchHint{}); + if (!P && W && n == Reg::R13) { + ir.SetTerm(IR::Term::PopRSBHint{}); + } else { + ir.SetTerm(IR::Term::FastDispatchHint{}); + } return false; } diff --git a/src/dynarmic/src/dynarmic/frontend/A64/translate/impl/a64_branch.cpp b/src/dynarmic/src/dynarmic/frontend/A64/translate/impl/a64_branch.cpp index 01cc1390c7..faf0686231 100644 --- a/src/dynarmic/src/dynarmic/frontend/A64/translate/impl/a64_branch.cpp +++ b/src/dynarmic/src/dynarmic/frontend/A64/translate/impl/a64_branch.cpp @@ -21,6 +21,7 @@ bool TranslatorVisitor::B_uncond(Imm<26> imm26) { const s64 offset = concatenate(imm26, Imm<2>{0}).SignExtend(); const u64 target = ir.PC() + offset; + //ir.SetTerm(IR::Term::LinkBlockFast{ir.current_location->SetPC(target)}); ir.SetTerm(IR::Term::LinkBlock{ir.current_location->SetPC(target)}); return false; } diff --git a/src/dynarmic/src/dynarmic/interface/exclusive_monitor.h b/src/dynarmic/src/dynarmic/interface/exclusive_monitor.h index 4813675873..566743c767 100644 --- a/src/dynarmic/src/dynarmic/interface/exclusive_monitor.h +++ b/src/dynarmic/src/dynarmic/interface/exclusive_monitor.h @@ -6,11 +6,10 @@ #pragma once #include -#include #include #include #include -#include +#include #include @@ -80,9 +79,10 @@ private: static constexpr VAddr RESERVATION_GRANULE_MASK = 0xFFFF'FFFF'FFFF'FFFFull; static constexpr VAddr INVALID_EXCLUSIVE_ADDRESS = 0xDEAD'DEAD'DEAD'DEADull; + static constexpr size_t MAX_NUM_CPU_CORES = 4; // Sync with src/core/hardware_properties + boost::container::static_vector exclusive_addresses; + boost::container::static_vector exclusive_values; SpinLock lock; - std::vector exclusive_addresses; - std::vector exclusive_values; }; } // namespace Dynarmic diff --git a/src/dynarmic/src/dynarmic/interface/optimization_flags.h b/src/dynarmic/src/dynarmic/interface/optimization_flags.h index 2f65f0bfa4..743d902767 100644 --- a/src/dynarmic/src/dynarmic/interface/optimization_flags.h +++ b/src/dynarmic/src/dynarmic/interface/optimization_flags.h @@ -32,6 +32,8 @@ enum class OptimizationFlag : std::uint32_t { ConstProp = 0x00000010, /// This is enables miscellaneous safe IR optimizations. MiscIROpt = 0x00000020, + /// Optimize for code speed rather than for code size (this serves well for tight loops) + CodeSpeed = 0x00000040, /// This is an UNSAFE optimization that reduces accuracy of fused multiply-add operations. /// This unfuses fused instructions to improve performance on host CPUs without FMA support. diff --git a/src/dynarmic/src/dynarmic/ir/basic_block.cpp b/src/dynarmic/src/dynarmic/ir/basic_block.cpp index 12765e26a8..b00ab3cb20 100644 --- a/src/dynarmic/src/dynarmic/ir/basic_block.cpp +++ b/src/dynarmic/src/dynarmic/ir/basic_block.cpp @@ -86,11 +86,9 @@ static std::string TerminalToString(const Terminal& terminal_variant) noexcept { } std::string DumpBlock(const IR::Block& block) noexcept { - std::string ret; - - ret += fmt::format("Block: location={}\n", block.Location()); - ret += fmt::format("cycles={}", block.CycleCount()); - ret += fmt::format(", entry_cond={}", A64::CondToString(block.GetCondition())); + std::string ret = fmt::format("Block: location={}-{}\n", block.Location(), block.EndLocation()) + + fmt::format("cycles={}", block.CycleCount()) + + fmt::format(", entry_cond={}", A64::CondToString(block.GetCondition())); if (block.GetCondition() != Cond::AL) { ret += fmt::format(", cond_fail={}", block.ConditionFailedLocation()); } @@ -116,6 +114,8 @@ std::string DumpBlock(const IR::Block& block) noexcept { return fmt::format("#{:#x}", arg.GetU32()); case Type::U64: return fmt::format("#{:#x}", arg.GetU64()); + case Type::U128: + return fmt::format("#"); case Type::A32Reg: return A32::RegToString(arg.GetA32RegRef()); case Type::A32ExtReg: @@ -124,8 +124,18 @@ std::string DumpBlock(const IR::Block& block) noexcept { return A64::RegToString(arg.GetA64RegRef()); case Type::A64Vec: return A64::VecToString(arg.GetA64VecRef()); + case Type::CoprocInfo: + return fmt::format("#"); + case Type::NZCVFlags: + return fmt::format("#"); + case Type::Cond: + return fmt::format("#", A32::CondToString(arg.GetCond())); + case Type::Table: + return fmt::format("#"); + case Type::AccType: + return fmt::format("#", u32(arg.GetAccType())); default: - return ""; + return fmt::format("", arg.GetType()); } }; diff --git a/src/dynarmic/src/dynarmic/ir/microinstruction.h b/src/dynarmic/src/dynarmic/ir/microinstruction.h index bc5a355793..6651aab7c5 100644 --- a/src/dynarmic/src/dynarmic/ir/microinstruction.h +++ b/src/dynarmic/src/dynarmic/ir/microinstruction.h @@ -19,7 +19,7 @@ namespace Dynarmic::IR { enum class Opcode; -enum class Type; +enum class Type : u16; constexpr size_t max_arg_count = 4; diff --git a/src/dynarmic/src/dynarmic/ir/opcodes.cpp b/src/dynarmic/src/dynarmic/ir/opcodes.cpp index e7e73b7032..828cdb5109 100644 --- a/src/dynarmic/src/dynarmic/ir/opcodes.cpp +++ b/src/dynarmic/src/dynarmic/ir/opcodes.cpp @@ -16,12 +16,6 @@ namespace Dynarmic::IR { namespace OpcodeInfo { -struct Meta { - std::vector arg_types; - const char* name; - Type type; -}; - constexpr Type Void = Type::Void; constexpr Type A32Reg = Type::A32Reg; constexpr Type A32ExtReg = Type::A32ExtReg; @@ -40,36 +34,62 @@ constexpr Type Cond = Type::Cond; constexpr Type Table = Type::Table; constexpr Type AccType = Type::AccType; -alignas(64) static const std::array opcode_info{ -#define OPCODE(name, type, ...) Meta{{__VA_ARGS__}, #name, type}, -#define A32OPC(name, type, ...) Meta{{__VA_ARGS__}, #name, type}, -#define A64OPC(name, type, ...) Meta{{__VA_ARGS__}, #name, type}, +struct Meta { + std::vector arg_types; + Type type; +}; + +// Evil macro magic for Intel C++ compiler +// Helper macro to force expanding __VA_ARGS__ to satisfy MSVC compiler. +#define PP_EXPAND(x) x +#define PP_NARGS(...) PP_EXPAND(PP_ARG_N(__VA_ARGS__, 5, 4, 3, 2, 1, 0)) +#define PP_ARG_N(_1, _2, _3, _4, _5, N, ...) N + +alignas(64) static const Meta opcode_info[] = { +#define OPCODE(name, type, ...) Meta{{__VA_ARGS__}, type}, +#define A32OPC(name, type, ...) Meta{{__VA_ARGS__}, type}, +#define A64OPC(name, type, ...) Meta{{__VA_ARGS__}, type}, #include "./opcodes.inc" #undef OPCODE #undef A32OPC #undef A64OPC }; +// Be aware of trailing commas, they can cause PP_NARG to return 2! +static_assert(PP_EXPAND(PP_NARGS(u8,)) == 2); +static_assert(PP_EXPAND(PP_NARGS(u8)) == 1); +static_assert(PP_EXPAND(PP_NARGS(u8, u16)) == 2); +static_assert(PP_EXPAND(PP_NARGS(u8, u16, u32)) == 3); + } // namespace OpcodeInfo /// @brief Get return type of an opcode Type GetTypeOf(Opcode op) noexcept { - return OpcodeInfo::opcode_info.at(size_t(op)).type; + return OpcodeInfo::opcode_info[size_t(op)].type; } /// @brief Get the number of arguments an opcode accepts size_t GetNumArgsOf(Opcode op) noexcept { - return OpcodeInfo::opcode_info.at(size_t(op)).arg_types.size(); + return OpcodeInfo::opcode_info[size_t(op)].arg_types.size(); } /// @brief Get the required type of an argument of an opcode Type GetArgTypeOf(Opcode op, size_t arg_index) noexcept { - return OpcodeInfo::opcode_info.at(size_t(op)).arg_types.at(arg_index); + return OpcodeInfo::opcode_info[size_t(op)].arg_types[arg_index]; } /// @brief Get the name of an opcode. -std::string GetNameOf(Opcode op) noexcept { - return OpcodeInfo::opcode_info.at(size_t(op)).name; +std::string_view GetNameOf(Opcode op) noexcept { + static const std::string_view opcode_names[] = { +#define OPCODE(name, type, ...) #name, +#define A32OPC(name, type, ...) #name, +#define A64OPC(name, type, ...) #name, +#include "./opcodes.inc" +#undef OPCODE +#undef A32OPC +#undef A64OPC + }; + return opcode_names[size_t(op)]; } } // namespace Dynarmic::IR diff --git a/src/dynarmic/src/dynarmic/ir/opcodes.h b/src/dynarmic/src/dynarmic/ir/opcodes.h index c11ad549da..a231365fa7 100644 --- a/src/dynarmic/src/dynarmic/ir/opcodes.h +++ b/src/dynarmic/src/dynarmic/ir/opcodes.h @@ -15,7 +15,7 @@ namespace Dynarmic::IR { -enum class Type; +enum class Type : u16; /// @brief The Opcodes of our intermediate representation. /// Type signatures for each opcode can be found in opcodes.inc @@ -35,7 +35,7 @@ constexpr size_t OpcodeCount = static_cast(Opcode::NUM_OPCODE); Type GetTypeOf(Opcode op) noexcept; size_t GetNumArgsOf(Opcode op) noexcept; Type GetArgTypeOf(Opcode op, size_t arg_index) noexcept; -std::string GetNameOf(Opcode op) noexcept; +std::string_view GetNameOf(Opcode op) noexcept; /// @brief Determines whether or not this instruction performs an arithmetic shift. constexpr bool IsArithmeticShift(const Opcode op) noexcept { diff --git a/src/dynarmic/src/dynarmic/ir/type.h b/src/dynarmic/src/dynarmic/ir/type.h index 0aaf9d9414..e223513367 100644 --- a/src/dynarmic/src/dynarmic/ir/type.h +++ b/src/dynarmic/src/dynarmic/ir/type.h @@ -18,7 +18,7 @@ namespace Dynarmic::IR { /** * The intermediate representation is typed. These are the used by our IR. */ -enum class Type { +enum class Type : u16 { Void = 0, A32Reg = 1 << 0, A32ExtReg = 1 << 1, diff --git a/src/dynarmic/tests/A32/fuzz_arm.cpp b/src/dynarmic/tests/A32/fuzz_arm.cpp index 9498f86d9b..087ce54813 100644 --- a/src/dynarmic/tests/A32/fuzz_arm.cpp +++ b/src/dynarmic/tests/A32/fuzz_arm.cpp @@ -357,7 +357,7 @@ static void RunTestInstance(Dynarmic::A32::Jit& jit, uni.ClearPageCache(); jit_env.ticks_left = ticks_left; - jit.Run(); + CheckedRun([&]() { jit.Run(); }); uni_env.ticks_left = instructions.size(); // Unicorn counts thumb instructions weirdly. uni.Run(); @@ -445,6 +445,9 @@ static void RunTestInstance(Dynarmic::A32::Jit& jit, } } + // TODO: Why the difference? QEMU what are you doing??? + jit.Regs()[15] = uni.GetRegisters()[15]; + REQUIRE(uni.GetRegisters() == jit.Regs()); REQUIRE(uni.GetExtRegs() == jit.ExtRegs()); REQUIRE((uni.GetCpsr() & 0xFFFFFDDF) == (jit.Cpsr() & 0xFFFFFDDF)); diff --git a/src/dynarmic/tests/A32/fuzz_thumb.cpp b/src/dynarmic/tests/A32/fuzz_thumb.cpp index dfd5672772..4d14141bbf 100644 --- a/src/dynarmic/tests/A32/fuzz_thumb.cpp +++ b/src/dynarmic/tests/A32/fuzz_thumb.cpp @@ -130,7 +130,7 @@ static void RunInstance(size_t run_number, ThumbTestEnv& test_env, A32Unicorn
expected = {0x954d53b0, 0x4caaad40, 0xb0afaead, 0x0da0cdb6, 0x0f43507e, 0xb4b3b2b1, 0x00000066, 0x892a6888, 0x3b9ffb23, 0x0a92ef93, 0x38dee619, 0xc0e95e81, 0x6a448690, 0xc2d4d6b9, 0xe93600b9, 0x0000000a}; diff --git a/src/dynarmic/tests/A32/testenv.h b/src/dynarmic/tests/A32/testenv.h index b196c5e568..a6df2017ce 100644 --- a/src/dynarmic/tests/A32/testenv.h +++ b/src/dynarmic/tests/A32/testenv.h @@ -16,8 +16,8 @@ #include "dynarmic/common/assert.h" #include "dynarmic/common/common_types.h" - #include "dynarmic/interface/A32/a32.h" +#include "../native/testenv.h" template class A32TestEnv : public Dynarmic::A32::UserCallbacks { diff --git a/src/dynarmic/tests/A64/a64.cpp b/src/dynarmic/tests/A64/a64.cpp index 801b01d555..40eff1f071 100644 --- a/src/dynarmic/tests/A64/a64.cpp +++ b/src/dynarmic/tests/A64/a64.cpp @@ -28,7 +28,7 @@ TEST_CASE("A64: ADD", "[a64]") { jit.SetPC(0); env.ticks_left = 2; - jit.Run(); + CheckedRun([&]() { jit.Run(); }); REQUIRE(jit.GetRegister(0) == 3); REQUIRE(jit.GetRegister(1) == 1); @@ -54,7 +54,7 @@ TEST_CASE("A64: ADD{V,P}", "[a64]") { jit.SetPC(0); env.ticks_left = 7; - jit.Run(); + CheckedRun([&]() { jit.Run(); }); REQUIRE(jit.GetVector(1) == Vector{0x0000000000000008, 0x0000000000000000}); REQUIRE(jit.GetVector(2) == Vector{0x0000000000000010, 0x0000000000000000}); @@ -79,9 +79,8 @@ TEST_CASE("A64: CLZ", "[a64]") { jit.SetVector(0, {0xeff0fafbfcfdfeff, 0xff7f3f1f0f070301}); jit.SetVector(1, {0xfffcfffdfffeffff, 0x000F000700030001}); jit.SetVector(2, {0xfffffffdfffffffe, 0x0000000300000001}); - env.ticks_left = env.code_mem.size(); - jit.Run(); + CheckedRun([&]() { jit.Run(); }); REQUIRE(jit.GetVector(3) == Vector{0x0, 0x0001020304050607}); REQUIRE(jit.GetVector(4) == Vector{0x0, 0x000c000d000e000f}); @@ -106,7 +105,7 @@ TEST_CASE("A64: UADDL{V,P}", "[a64]") { jit.SetPC(0); env.ticks_left = 7; - jit.Run(); + CheckedRun([&]() { jit.Run(); }); REQUIRE(jit.GetVector(1) == Vector{0x00000000000007f8, 0x0000000000000000}); REQUIRE(jit.GetVector(2) == Vector{0x0000000000000ff0, 0x0000000000000000}); @@ -134,7 +133,7 @@ TEST_CASE("A64: SADDL{V,P}", "[a64]") { jit.SetPC(0); env.ticks_left = 7; - jit.Run(); + CheckedRun([&]() { jit.Run(); }); REQUIRE(jit.GetVector(1) == Vector{0x000000000000fff8, 0x0000000000000000}); REQUIRE(jit.GetVector(2) == Vector{0x000000000000fff0, 0x0000000000000000}); @@ -165,7 +164,7 @@ TEST_CASE("A64: VQADD", "[a64]") { jit.SetPC(0); env.ticks_left = 9; - jit.Run(); + CheckedRun([&]() { jit.Run(); }); REQUIRE(jit.GetVector(2) == Vector{0xff8fff7ffffe7f7f, 0xffffffffffffffff}); REQUIRE(jit.GetVector(3) == Vector{0xff7f7e7fff7f7f7f, 0xffffffffffffffff}); @@ -198,7 +197,7 @@ TEST_CASE("A64: VQSUB", "[a64]") { jit.SetPC(0); env.ticks_left = 9; - jit.Run(); + CheckedRun([&]() { jit.Run(); }); REQUIRE(jit.GetVector(2) == Vector{0x0100800001000000, 0x0100000001000100}); REQUIRE(jit.GetVector(3) == Vector{0x8091808180008181, 0x8001010180018001}); @@ -225,7 +224,7 @@ TEST_CASE("A64: REV", "[a64]") { jit.SetPC(0); env.ticks_left = 3; - jit.Run(); + CheckedRun([&]() { jit.Run(); }); REQUIRE(jit.GetRegister(0) == 0x11ffeeddccbbaa); REQUIRE(jit.GetRegister(1) == 0xddccbbaa); @@ -245,7 +244,7 @@ TEST_CASE("A64: REV32", "[a64]") { jit.SetPC(0); env.ticks_left = 2; - jit.Run(); + CheckedRun([&]() { jit.Run(); }); REQUIRE(jit.GetRegister(0) == 0xddccbbaa0011ffee); REQUIRE(jit.GetPC() == 4); } @@ -266,7 +265,7 @@ TEST_CASE("A64: REV16", "[a64]") { jit.SetPC(0); env.ticks_left = 3; - jit.Run(); + CheckedRun([&]() { jit.Run(); }); REQUIRE(jit.GetRegister(0) == 0xbbaaddccffee0011); REQUIRE(jit.GetRegister(1) == 0xbbaaddcc); REQUIRE(jit.GetPC() == 8); @@ -299,7 +298,7 @@ TEST_CASE("A64: SSHL", "[a64]") { jit.SetVector(17, {0x8000000000000000, 0xFFFFFFFFFFFFFFFF}); env.ticks_left = env.code_mem.size(); - jit.Run(); + CheckedRun([&]() { jit.Run(); }); CHECK(jit.GetVector(4) == Vector{0xfffffefcf8f0e0c0, 0x0080e0f0f8fcfeff}); CHECK(jit.GetVector(5) == Vector{0xf800f000e000c000, 0xfff0fff8fffcfffe}); @@ -344,7 +343,7 @@ TEST_CASE("A64: USHL", "[a64]") { jit.SetVector(17, {0x8000000000000000, 0x0000000000000001}); env.ticks_left = env.code_mem.size(); - jit.Run(); + CheckedRun([&]() { jit.Run(); }); CHECK(jit.GetVector(4) == Vector{0x003f000000000000, 0x0080e0f0f8fcfeff}); CHECK(jit.GetVector(14) == Vector{0x0000000102040810}); @@ -380,7 +379,7 @@ TEST_CASE("A64: URSHL", "[a64]") { jit.SetVector(11, Vector{0xffffffffffffffc1, 0x00555555555555f5}); env.ticks_left = env.code_mem.size(); - jit.Run(); + CheckedRun([&]() { jit.Run(); }); CHECK(jit.GetVector(0) == Vector{0x00000001'53500000, 0x00000001'00000000}); CHECK(jit.GetVector(3) == Vector{0x00000001'00000002, 0x80000000'fffffffe}); @@ -406,7 +405,7 @@ TEST_CASE("A64: XTN", "[a64]") { jit.SetVector(2, {0x0000000000000000, 0x1111111111111111}); env.ticks_left = 4; - jit.Run(); + CheckedRun([&]() { jit.Run(); }); REQUIRE(jit.GetVector(3) == Vector{0x7766554433221100, 0x0000000000000000}); REQUIRE(jit.GetVector(4) == Vector{0x3333222211110000, 0x0000000000000000}); @@ -449,7 +448,7 @@ TEST_CASE("A64: TBL", "[a64]") { jit.SetPC(0); env.ticks_left = 9; - jit.Run(); + CheckedRun([&]() { jit.Run(); }); REQUIRE(jit.GetVector(0) == Vector{0x001122334455'00'77, 0x0000000000000000}); REQUIRE(jit.GetVector(1) == Vector{0x001122334455'00'77, 0x8899aabbccddeeff}); @@ -497,7 +496,7 @@ TEST_CASE("A64: TBX", "[a64]") { jit.SetPC(0); env.ticks_left = 9; - jit.Run(); + CheckedRun([&]() { jit.Run(); }); REQUIRE(jit.GetVector(0) == Vector{0x001122334455'FF'77, 0x0000000000000000}); REQUIRE(jit.GetVector(1) == Vector{0x001122334455'FF'77, 0x8899aabbccddeeff}); @@ -524,7 +523,7 @@ TEST_CASE("A64: AND", "[a64]") { jit.SetPC(0); env.ticks_left = 2; - jit.Run(); + CheckedRun([&]() { jit.Run(); }); REQUIRE(jit.GetRegister(0) == 1); REQUIRE(jit.GetRegister(1) == 1); @@ -546,7 +545,7 @@ TEST_CASE("A64: Bitmasks", "[a64]") { jit.SetPC(0); env.ticks_left = 4; - jit.Run(); + CheckedRun([&]() { jit.Run(); }); REQUIRE(jit.GetRegister(0) == 0x01010101); REQUIRE(jit.GetRegister(1) == 0x00F000F0); @@ -570,7 +569,7 @@ TEST_CASE("A64: ANDS NZCV", "[a64]") { jit.SetPC(0); env.ticks_left = 2; - jit.Run(); + CheckedRun([&]() { jit.Run(); }); REQUIRE(jit.GetRegister(0) == 0xFFFFFFFF); REQUIRE(jit.GetRegister(1) == 0xFFFFFFFF); @@ -586,7 +585,7 @@ TEST_CASE("A64: ANDS NZCV", "[a64]") { jit.SetPC(0); env.ticks_left = 2; - jit.Run(); + CheckedRun([&]() { jit.Run(); }); REQUIRE(jit.GetRegister(0) == 0x00000000); REQUIRE(jit.GetRegister(1) == 0xFFFFFFFF); @@ -601,7 +600,7 @@ TEST_CASE("A64: ANDS NZCV", "[a64]") { jit.SetPC(0); env.ticks_left = 2; - jit.Run(); + CheckedRun([&]() { jit.Run(); }); REQUIRE(jit.GetRegister(0) == 0x12240010); REQUIRE(jit.GetRegister(1) == 0x12345678); @@ -628,7 +627,7 @@ TEST_CASE("A64: CBZ", "[a64]") { jit.SetRegister(0, 1); env.ticks_left = 4; - jit.Run(); + CheckedRun([&]() { jit.Run(); }); REQUIRE(jit.GetRegister(2) == 1); REQUIRE(jit.GetPC() == 8); @@ -639,7 +638,7 @@ TEST_CASE("A64: CBZ", "[a64]") { jit.SetRegister(0, 0); env.ticks_left = 4; - jit.Run(); + CheckedRun([&]() { jit.Run(); }); REQUIRE(jit.GetRegister(2) == 2); REQUIRE(jit.GetPC() == 16); @@ -663,7 +662,7 @@ TEST_CASE("A64: TBZ", "[a64]") { jit.SetRegister(0, 0xFF); env.ticks_left = 4; - jit.Run(); + CheckedRun([&]() { jit.Run(); }); REQUIRE(jit.GetRegister(2) == 1); REQUIRE(jit.GetPC() == 8); @@ -674,7 +673,7 @@ TEST_CASE("A64: TBZ", "[a64]") { jit.SetRegister(0, 0); env.ticks_left = 4; - jit.Run(); + CheckedRun([&]() { jit.Run(); }); REQUIRE(jit.GetRegister(2) == 2); REQUIRE(jit.GetPC() == 16); @@ -685,7 +684,7 @@ TEST_CASE("A64: TBZ", "[a64]") { jit.SetRegister(0, 1); env.ticks_left = 4; - jit.Run(); + CheckedRun([&]() { jit.Run(); }); REQUIRE(jit.GetRegister(2) == 2); REQUIRE(jit.GetPC() == 16); @@ -706,7 +705,7 @@ TEST_CASE("A64: FABD", "[a64]") { jit.SetVector(21, {0x56d3f085ff890e2b, 0x6e4b0a41801a2d00}); env.ticks_left = 2; - jit.Run(); + CheckedRun([&]() { jit.Run(); }); REQUIRE(jit.GetVector(22) == Vector{0x56d3f0857fc90e2b, 0x6e4b0a4144873176}); } @@ -728,7 +727,7 @@ TEST_CASE("A64: FABS", "[a64]") { jit.SetVector(2, {0xffffffffffffffff, 0x8000000000000000}); env.ticks_left = 4; - jit.Run(); + CheckedRun([&]() { jit.Run(); }); REQUIRE(jit.GetVector(4) == Vector{0x7fff7fff7fff7fff, 0x7fff7fff7fff0000}); REQUIRE(jit.GetVector(5) == Vector{0x7fbfffff7fc00000, 0x7f80000000000000}); @@ -753,7 +752,7 @@ TEST_CASE("A64: FMIN (example)", "[a64]") { jit.SetVector(3, {0xbff0000000000000, 0x6e4b0a41ffffffff}); env.ticks_left = 2; - jit.Run(); + CheckedRun([&]() { jit.Run(); }); REQUIRE(jit.GetVector(0) == Vector{0x7fc00000'00000001, 0x00000000'7fd84a37}); REQUIRE(jit.GetVector(2) == Vector{0xbff0000000000000, 0x3ff0000000000000}); @@ -777,7 +776,7 @@ TEST_CASE("A64: FMAX (example)", "[a64]") { jit.SetVector(3, {0xbff0000000000000, 0x6e4b0a41ffffffff}); env.ticks_left = 2; - jit.Run(); + CheckedRun([&]() { jit.Run(); }); REQUIRE(jit.GetVector(0) == Vector{0x7fc00000'09503366, 0x6e4b0a41'7fd84a37}); REQUIRE(jit.GetVector(2) == Vector{0x7fc0000009503366, 0x6e4b0a41ffffffff}); @@ -801,7 +800,7 @@ TEST_CASE("A64: FMINNM (example)", "[a64]") { jit.SetVector(3, {0xfff0000000000000, 0xffffffffffffffff}); env.ticks_left = 2; - jit.Run(); + CheckedRun([&]() { jit.Run(); }); REQUIRE(jit.GetVector(0) == Vector{0xc1200000'00000001, 0x00000000'7fd84a37}); REQUIRE(jit.GetVector(2) == Vector{0xfff0000000000000, 0x3ff0000000000000}); @@ -825,7 +824,7 @@ TEST_CASE("A64: FMAXNM (example)", "[a64]") { jit.SetVector(3, {0xfff0000000000000, 0xffffffffffffffff}); env.ticks_left = 2; - jit.Run(); + CheckedRun([&]() { jit.Run(); }); REQUIRE(jit.GetVector(0) == Vector{0xc1200000'09503366, 0x6e4b0a41'7fd84a37}); REQUIRE(jit.GetVector(2) == Vector{0x7fc0000009503366, 0x3ff0000000000000}); @@ -846,7 +845,7 @@ TEST_CASE("A64: FMAXNM (example 2)", "[a64]") { jit.SetVector(27, {0xbc48d091'c79b271e, 0xff800001'3304c3ef}); env.ticks_left = 2; - jit.Run(); + CheckedRun([&]() { jit.Run(); }); REQUIRE(jit.GetVector(29) == Vector{0xb485877c'42280000, 0xffc00001'3304c3ef}); } @@ -876,7 +875,7 @@ TEST_CASE("A64: 128-bit exclusive read/write", "[a64]") { jit.SetRegister(6, 0xd0d0cacad0d0caca); env.ticks_left = 3; - jit.Run(); + CheckedRun([&]() { jit.Run(); }); REQUIRE(jit.GetRegister(1) == 0x7f7e7d7c7b7a7978); REQUIRE(jit.GetRegister(2) == 0x8786858483828180); @@ -903,7 +902,7 @@ TEST_CASE("A64: CNTPCT_EL0", "[a64]") { env.code_mem.emplace_back(0x14000000); // B . env.ticks_left = 10; - jit.Run(); + CheckedRun([&]() { jit.Run(); }); REQUIRE(jit.GetRegister(3) == 7); } @@ -923,7 +922,7 @@ TEST_CASE("A64: FNMSUB 1", "[a64]") { jit.SetVector(2, {0x0000000000000000, 0xc79b271e3f000000}); env.ticks_left = 2; - jit.Run(); + CheckedRun([&]() { jit.Run(); }); REQUIRE(jit.GetVector(28) == Vector{0x66ca513533ee6076, 0x0000000000000000}); } @@ -944,7 +943,7 @@ TEST_CASE("A64: FNMSUB 2", "[a64]") { jit.SetFpcr(0x00400000); env.ticks_left = 2; - jit.Run(); + CheckedRun([&]() { jit.Run(); }); REQUIRE(jit.GetVector(14) == Vector{0x0000000080045284, 0x0000000000000000}); } @@ -965,7 +964,7 @@ TEST_CASE("A64: FMADD", "[a64]") { jit.SetFpcr(0x00400000); env.ticks_left = 2; - jit.Run(); + CheckedRun([&]() { jit.Run(); }); REQUIRE(jit.GetVector(10) == Vector{0x3f059921bf0dbfff, 0x0000000000000000}); } @@ -992,7 +991,7 @@ TEST_CASE("A64: FMLA.4S(lane)", "[a64]") { jit.SetVector(15, {0x3ff00000'40000000, 0x40400000'40800000}); env.ticks_left = 5; - jit.Run(); + CheckedRun([&]() { jit.Run(); }); REQUIRE(jit.GetVector(0) == Vector{0x40b4000040b40000, 0x4070000040700000}); REQUIRE(jit.GetVector(1) == Vector{0x40ac800040ac8000, 0x4061000040610000}); @@ -1017,7 +1016,7 @@ TEST_CASE("A64: FMUL.4S(lane)", "[a64]") { jit.SetVector(15, {0x3ff00000'40000000, 0x40400000'40800000}); env.ticks_left = 5; - jit.Run(); + CheckedRun([&]() { jit.Run(); }); REQUIRE(jit.GetVector(0) == Vector{0x4070000040700000, 0x4070000040700000}); REQUIRE(jit.GetVector(1) == Vector{0x4061000040610000, 0x4061000040610000}); @@ -1041,7 +1040,7 @@ TEST_CASE("A64: FMLA.4S (denormal)", "[a64]") { jit.SetFpcr(0x01000000); env.ticks_left = 2; - jit.Run(); + CheckedRun([&]() { jit.Run(); }); REQUIRE(jit.GetVector(12) == Vector{0x7ff800007fc00000, 0xbff0000068e8e581}); } @@ -1062,7 +1061,7 @@ TEST_CASE("A64: FMLA.4S (0x80800000)", "[a64]") { jit.SetFpcr(0x03000000); env.ticks_left = 2; - jit.Run(); + CheckedRun([&]() { jit.Run(); }); REQUIRE(jit.GetVector(11) == Vector{0xc79b271e7fc00000, 0x7fc0000080000000}); } @@ -1086,7 +1085,7 @@ TEST_CASE("A64: FMADD (0x80800000)", "[a64]") { jit.SetFpcr(0x01000000); env.ticks_left = 2; - jit.Run(); + CheckedRun([&]() { jit.Run(); }); REQUIRE(jit.GetVector(25) == Vector{0x80000000, 0}); } @@ -1106,7 +1105,7 @@ TEST_CASE("A64: FNEG failed to zero upper", "[a64]") { jit.SetFpcr(0x01000000); env.ticks_left = 6; - jit.Run(); + CheckedRun([&]() { jit.Run(); }); REQUIRE(jit.GetVector(28) == Vector{0x79ee7a03980db670, 0}); REQUIRE(FP::FPSR{jit.GetFpsr()}.QC() == false); @@ -1131,7 +1130,7 @@ TEST_CASE("A64: FRSQRTS", "[a64]") { jit.SetFpcr(0x00400000); env.ticks_left = 2; - jit.Run(); + CheckedRun([&]() { jit.Run(); }); REQUIRE(jit.GetVector(13) == Vector{0xff7fffff, 0}); } @@ -1153,7 +1152,7 @@ TEST_CASE("A64: SQDMULH.8H (saturate)", "[a64]") { jit.SetFpsr(0); env.ticks_left = 2; - jit.Run(); + CheckedRun([&]() { jit.Run(); }); REQUIRE(jit.GetVector(0) == Vector{0x7ffe7fff7ffc7ffe, 0x8001800180028002}); REQUIRE(FP::FPSR{jit.GetFpsr()}.QC() == true); @@ -1176,7 +1175,7 @@ TEST_CASE("A64: SQDMULH.4S (saturate)", "[a64]") { jit.SetFpsr(0); env.ticks_left = 2; - jit.Run(); + CheckedRun([&]() { jit.Run(); }); REQUIRE(jit.GetVector(0) == Vector{0x7ffffffe7fffffff, 0x8000000180000001}); REQUIRE(FP::FPSR{jit.GetFpsr()}.QC() == true); @@ -1197,7 +1196,7 @@ TEST_CASE("A64: This is an infinite loop if fast dispatch is enabled", "[a64]") env.code_mem.emplace_back(0x14000000); // B . env.ticks_left = 6; - jit.Run(); + CheckedRun([&]() { jit.Run(); }); } TEST_CASE("A64: EXTR", "[a64]") { @@ -1214,7 +1213,7 @@ TEST_CASE("A64: EXTR", "[a64]") { jit.SetRegister(24, 1); env.ticks_left = 2; - jit.Run(); + CheckedRun([&]() { jit.Run(); }); REQUIRE(jit.GetRegister(23) == 0); } @@ -1249,7 +1248,7 @@ TEST_CASE("A64: Isolated GetNZCVFromOp", "[a64]") { jit.SetPC(0); env.ticks_left = 20; - jit.Run(); + CheckedRun([&]() { jit.Run(); }); } TEST_CASE("A64: Optimization failure when folding ADD", "[a64]") { @@ -1302,7 +1301,7 @@ TEST_CASE("A64: Optimization failure when folding ADD", "[a64]") { jit.SetPstate(0x30000000); env.ticks_left = 6; - jit.Run(); + CheckedRun([&]() { jit.Run(); }); REQUIRE(jit.GetRegister(0) == 0x46e15845dba57924); REQUIRE(jit.GetRegister(1) == 0x6f60d04350581fea); @@ -1365,7 +1364,7 @@ TEST_CASE("A64: Cache Maintenance Instructions", "[a64]") { env.code_mem.emplace_back(0x14000000); // B . env.ticks_left = 3; - jit.Run(); + CheckedRun([&]() { jit.Run(); }); } TEST_CASE("A64: Memory access (fastmem)", "[a64]") { @@ -1408,7 +1407,7 @@ TEST_CASE("A64: Memory access (fastmem)", "[a64]") { jit.SetPstate(0x30000000); env.ticks_left = 5; - jit.Run(); + CheckedRun([&]() { jit.Run(); }); REQUIRE(strncmp(backing_memory + 0x100, backing_memory + 0x1F0, 23) == 0); } @@ -1428,7 +1427,7 @@ TEST_CASE("A64: SQRDMULH QC flag when output invalidated", "[a64]") { jit.SetFpcr(0x05400000); env.ticks_left = 3; - jit.Run(); + CheckedRun([&]() { jit.Run(); }); REQUIRE(jit.GetFpsr() == 0x08000000); REQUIRE(jit.GetVector(11) == Vector{0xb4cb'4fec'8563'1032, 0x0000'0000'0000'0000}); @@ -1449,7 +1448,7 @@ TEST_CASE("A64: SDIV maximally", "[a64]") { jit.SetPC(0); env.ticks_left = 2; - jit.Run(); + CheckedRun([&]() { jit.Run(); }); REQUIRE(jit.GetRegister(0) == 0xffffffffffffffff); REQUIRE(jit.GetRegister(1) == 0x8000000000000000); @@ -1540,7 +1539,7 @@ TEST_CASE("A64: rand1", "[a64]") { jit.SetFpcr(0x01080000); env.ticks_left = 16; - jit.Run(); + CheckedRun([&]() { jit.Run(); }); REQUIRE(jit.GetRegister(0) == 0x67e1d59cc30a788c); REQUIRE(jit.GetRegister(1) == 0x0e771a2a79dfb060); @@ -1575,15 +1574,67 @@ TEST_CASE("A64: rand1", "[a64]") { REQUIRE(jit.GetRegister(30) == 0x9a5d96aa066e5c39); } -TEST_CASE("A64: rand2", "[a64][.]") { - A64TestEnv env; - A64::UserConfig jit_user_config{}; - jit_user_config.callbacks = &env; - jit_user_config.fastmem_pointer = 0xffffffff00000000; - A64::Jit jit{jit_user_config}; +TEST_CASE("A64: rand3", "[a64]") { + constexpr size_t address_width = 12; + constexpr size_t memory_size = 1ull << address_width; // 4K + constexpr size_t page_size = 4 * 1024; + constexpr size_t buffer_size = 2 * page_size; + char buffer[buffer_size]; - env.code_mem = {0xea80f352, 0x6e65e59d, 0x1e20c343, 0x2e3a7192, 0x2e267249, 0xd500405f, 0x6f01f461, 0x6eb684fc, 0x58028edd, 0x0ea5f5b6, 0x0ea069fb, 0x2e769517, 0x5e066063, 0x1e65c3f5, 0x4f00ff52, 0x93401cf6, 0x1e274248, 0x6f67aaf5, 0x5e0c0782, 0x5ef43f3c, 0x2e6595b7, 0x4e20590f, 0xb35aa451, 0x6ee2c5ed, 0x4e32bf46, 0x2ea1ba8f, 0x2f68a85e, 0x9237d90a, 0x5e23dd10, 0x0e762e32, 0x4e31a8cf, 0xce1f3360, 0x781a4ac0, 0x13834066, 0x5fa8101c, 0x6f7c5594, 0x0e71bb68, 0xbc0b3e8f, 0x785dbbda, 0x6f51e794, 0xce50af75, 0x1ad728ec, 0x6ee0da4c, 0xb84efa14, 0x2eb3f613, 0x4e287ade, 0x4eb8c734, 0x2e83f4e8, 0x0e397c80, 0xd08f93f8, 0xce718e48, 0x0f672a0d, 0x2e9edd40, 0x0e14128b, 0x6f5942e6, 0x8b3a0f03, 0x3c5d16b9, 0x7f7e3743, 0x4f4c54e4, 0x0ea0a9e9, 0x9e59dbe6, 0x6e7ddcd3, 0xcec08377, 0x9ba759f8, 0x2ea5046e, 0x0e24c569, 0xb8979780, 0x4e31b98c, 0x4efe4f46, 0x4ea7c762, 0x7e61c9c6, 0x6e30c880, 0x1ada0c25, 0x4e603a2f, 0xda9d7218, 0x0d40c5d9, 0x5e214b05, 0x9ba9efc5, 0x5e61b81e, 0x6e7bc31c, 0x0e61a163, 0x9e5832d2, 0x4e772248, 0x4e3d17c8, 0x92624f60, 0x7a1a02dc, 0x79891f65, 0x6eb45036, 0x0e321ee8, 0x4e2566f0, 0x4ea02b9b, 0x0f9dcb3d, 0x2e21b9f9, 0x0e21a8c3, 0xda1700bd, 0x6ea0fb38, 0x7e607a0b, 0x72845817, 0x7f61068e, 0x0d60e529, 0x4ea0ca5c, 0x1a94b20f, 0x8b87419d, 0x7ea9ed71, 0x2ea1a86e, 0x4d40c4da, 0x5ea0eada, 0x784ba96e, 0x7eb6ee02, 0x3db1c710, 0x0e217836, 0x7ee0bb96, 0x4e786c08, 0x4e976a08, 0x489ffe86, 0x4e79fc9b, 0x0e21cbce, 0x5ef7fc65, 0x4ea1286d, 0xd29c771e, 0x6f5c2839, 0x0ea00a9d, 0x6ee44c06, 0x5ee1d858, 0x5ef2fda6, 0x7eb0c9fe, 0x7f762791, 0x2e212ae6, 0x4e61c9db, 0x13003c57, 0x5ee1b8f8, 0x0f2396d2, 0x6ea0db1e, 0x0e71ba82, 0xab29c807, 0x6ef8f8b3, 0x1f18d4a1, 0x0e261d15, 0x1e290081, 0x1b0c7d12, 0x4e7771c3, 0xf845f1e4, 0x4d40c9e8, 0xce778452, 0x6eb9879d, 0x6e21c93d, 0xcec0829f, 0x52a0969f, 0x1e772b4f, 0x7ee1da88, 0x5f52fe0a, 0x7f3387b1, 0x5e214850, 0x1e65c025, 0x0e2ca294, 0x2e614829, 0x1e640077, 0x9e240048, 0x4ebe9537, 0x9bb7925e, 0x38b669c5, 0x2840d089, 0x6f43e648, 0x2e662d28, 0x4eabaff3, 0x6e734cc7, 0x0e31baee, 0x7ee0d93c, 0x5e282bde, 0x7e21bba4, 0x4e6c75fa, 0x5ac01217, 0x7f4304af, 0x1e7878ed, 0x1ada2196, 0x7ee1aba3, 0x93407f3c, 0x4f6c34eb, 0x6e3447a9, 0x7e7ae545, 0x5e0802bb, 0x6eeae63a, 0x7ee1da62, 0x5e280bb3, 0xf81d4009, 0x1e603b21, 0x5e281a14, 0x6eb0a99b, 0x1e266a25, 0x0d60cafe, 0x0e0b6194, 0x7a4ed2c5, 0x92b762ec, 0x4e6b5749, 0x3c16a6e5, 0x4ea0a92b, 0x0fa58b6a, 0x5f76148c, 0x6e30c95f, 0x1e6540fd, 0x5e28e40f, 0x0d403fd4, 0x7e30da36, 0x7fda9b51, 0x2ea04bde, 0x1e25c3d2, 0x1ee0434c, 0x5e21d8e7, 0x5ee1ba51, 0x5e61aba9, 0x4e2849fb, 0x5ee098ea, 0x4e60f63d, 0x0f280443, 0x5ee0da27, 0x2e78a6ce, 0x78054afc, 0x4e14286b, 0x4e218bd8, 0x2a3d2551, 0x3a04017a, 0x5f4317cd, 0x0e604a37, 0x9a834614, 0x0e2edf4d, 0x7a51a0a0, 0x5f8e9043, 0x6ea06bb2, 0xaa2857dd, 0x7a1903fc, 0x301ba9ba, 0x9ac929cd, 0x4e061ff0, 0x2e38fcfc, 0x0e2f614a, 0x7ee0d8e4, 0x6e73afda, 0x7f4156f7, 0x0e6078bf, 0x4ee1d9ed, 0x93403fbe, 0xce6f8640, 0x4e3855e3, 0x6f76fe23, 0x112466e8, 0x1e358a90, 0x7f45272c, 0x6ea19a9d, 0x8a696350, 0x1e3900f6, 0x5e61c866, 0x0e3fbfd0, 0x5ee09ad0, 0x0e651d27, 0x4dffc35e, 0x2e20c6ce, 0x0fbe118d, 0x1e656a15, 0xd1357365, 0x0e20a847, 0xce4a835c, 0x4e203905, 0x2e60090d, 0x7f4a27bb, 0x1e64c316, 0xce7d86a4, 0x7ebded2d, 0x6e70a97e, 0x4eb9a42b, 0x0e209bef, 0x6f151730, 0x0e7e30f7, 0x4e724509, 0xd503375f, 0xce58b6ae, 0x5e21a9b8, 0xcb2ca538, 0x5ac01131, 0x6ea19a24, 0xeb40c8b3, 0xc8df7d65, 0x78108341, 0x3218ab9b, 0x0f3da7dd, 0x2e003089, 0x4e21cab5, 0x8aa5c924, 0x1a94950c, 0x123e506f, 0x13117e37, 0x1ee6005b, 0x5ac00647, 0x5eec8cd5, 0x7ef0fb3d, 0x9223272a, 0x5ee0cb02, 0x6e66071d, 0x6ea1dbbf, 0x5e61c903, 0x5ac015ea, 0x93db6206, 0x7e62b5e3, 0x6ea0c87b, 0xdac0090e, 0x48df7d90, 0x6e206ba5, 0x9e2503c2, 0x6e25fc89, 0x4d60e2db, 0x1e3e22a0, 0x2eb81c19, 0x7856ea00, 0x5fbfb22d, 0x1e630244, 0x4e202a83, 0x1f50a722, 0x7f7b55d2, 0x0fae89b9, 0x4e781d73, 0xce738c3a, 0x4f15a591, 0x6e21c7e1, 0x586ff77e, 0x8a5d3592, 0x93401c67, 0x5e61cb86, 0xce6bc2c1, 0x6e393f10, 0x9bb70ec3, 0xdac0098c, 0x4da84b95, 0x7f494476, 0x9ace5c11, 0x7e61ca14, 0x4f7a60ef, 0x1ad32b39, 0x0ea3777f, 0x5e61da7f, 0x4f1404e2, 0x4e3244e2, 0x6e1b1ceb, 0x0dee5aac, 0x4e2f9dc4, 0x5ea1b8c3, 0x1e59f863, 0xd500403f, 0x4e3ae7d0, 0x4ef5c6ea, 0x08dffe3b, 0x6e36f4f6, 0x2e764f29, 0x0e726f23, 0x5f42375b, 0x7f71fc40, 0x6e618aad, 0x93403e5b, 0x0e205976, 0x0e7250c4, 0x6eb0abc9, 0x2e2049f0, 0x5f14754d, 0x7f6ce468, 0x6f950bbe, 0x6e31aa47, 0x4eb83396, 0x0dccc952, 0x2ea1ca90, 0xce69c701, 0xb0bed69e, 0x7c5dec39, 0x4e2868a2, 0x0e591b08, 0x5f34e6dd, 0x3a449184, 0x5e3ce6de, 0x4ea149b7, 0x4e7ad29b, 0xba198503, 0x1f683e8f, 0xfa52f2a7, 0x6e30dffc, 0x4e6c3d17, 0x2eae3248, 0xd503349f, 0x1e60002c, 0x0f180680, 0x9e240049, 0x6f75774e, 0xa90d8678, 0x9ad924c4, 0x7eb0f85b, 0x0e205aaf, 0x7ee08899, 0x5f4bffd8, 0x1b0ff5f3, 0x4ee11dcd, 0x2e218948, 0x0dcb2733, 0x4eac107c, 0x4ea04a53, 0x4e287b44, 0x0e60b82a, 0x5ee0ebbc, 0xce454ff1, 0x5e1761e7, 0x5e09202f, 0x0e0c0754, 0x1e72e6b9, 0x7e21da70, 0x0fbdb20c, 0x5efb8c84, 0xd500401f, 0x3a47526e, 0x1e680acf, 0x7f7375fc, 0xf80522da, 0x4ee60c02, 0x4d40c2e7, 0x6f89096b, 0x7ee1bb6e, 0x5e280b4a, 0x1e3120c8, 0x7eb2ef96, 0x4fd012dd, 0x0f3027ef, 0x4e2078a8, 0xd503201f, 0x2e2312d9, 0x6ebf1c6e, 0x5ee1f8df, 0x4e607a46, 0x6e30c877, 0x6c09d2d1, 0x4e61abd8, 0x0e35267e, 0x6ac17728, 0x0e861aa0, 0x6f63fe26, 0x6f157628, 0x6f30a5f9, 0x4d60cc0c, 0x4e21cb59, 0x2e68a3fb, 0x7efae601, 0x6ea0f82c, 0x9b25ec12, 0x1a1a0305, 0x0e043fe1, 0x6e73c0ed, 0x6ea1b8c0, 0x7e20380b, 0x0f0534e8, 0x1f56bc7d, 0xba0c0128, 0x1e672160, 0x6e7b259b, 0x7ee07b5d, 0x9a820443, 0x4e040581, 0x2f1d87e8, 0x1acd2f5b, 0x6e20794f, 0x2e6a3c93, 0xc8dffe13, 0xce5ab1c6, 0x6eea55f6, 0x4ea039b3, 0x0d602fec, 0x2e246e2f, 0x7857be39, 0xb80608fb, 0x1e67c017, 0x9bcf7f63, 0x0f92d857, 0x5e0812f7, 0x1e210172, 0x7e6128e9, 0x7ea94d41, 0x981179e1, 0x1effb018, 0x2e600828, 0x0eb9c6b2, 0x6ee1baae, 0x4ea0db28, 0x2ea1487b, 0x4ea6c7f0, 0x2e2374c7, 0x7e30d8dd, 0xb9991fa7, 0x4e791e3e, 0x889f7c4b, 0x0e6c753c, 0x1e740ad1, 0x1e244324, 0x1ef33010, 0x5ac01102, 0x9bd97fba, 0x6e290143, 0x1e2220d8, 0x4d8d5aee, 0x6f28570b, 0xfa4ab0c1, 0xdac00b14, 0x7ea1a90e, 0x2e3027d8, 0x6f25a733, 0x4e61a96e, 0x4e1a2fcb, 0x0e22fe0a, 0xc8df7cd0, 0x5e280a55, 0x4e012b20, 0x7e70dbf4, 0x520c5a4e, 0x6ea6c57f, 0x0e861af8, 0xd503233f, 0x889ffe3c, 0x5e274ea9, 0x4e21a89a, 0x0e170c02, 0x6efd4c0b, 0xd5033ebf, 0x6e61a92c, 0x2e205b72, 0x789fb828, 0x0e626e94, 0x2ea6724c, 0x9a10028b, 0x2c6c51fc, 0x5a9de6b9, 0x6e6881f3, 0x5ee0ea6b, 0x0faec36e, 0x0e955bca, 0x1acf206d, 0x7f6f571b, 0x4e286930, 0x12b41ceb, 0x1e770b7a, 0x0ea18ac2, 0x5e282aaf, 0xf2b7fa1e, 0x1ac34311, 0x13167d11, 0x4ea63412, 0x6e758038, 0x2f1d85d6, 0x0f275480, 0x0ead6c71, 0x6e204b69, 0x1e6303f4, 0x5e0031ef, 0x13001e40, 0x7a16006f, 0x6e6ae4c0, 0x0f0f242f, 0x6e674f50, 0x4e606b7a, 0x7e6ee684, 0x1e6b5957, 0x7ea1bbab, 0x7ea0b6cb, 0xce4da241, 0x0ea1b953, 0x0eb2af4b, 0x9ac309d0, 0x6e61d8bd, 0x5ea0d890, 0x5f47d1e7, 0xfa5981ca, 0x1e7f7959, 0x6ef24dd8, 0x0e0a41d1, 0x5ee0e898, 0x4e6038e2, 0x13097d65, 0x6f839088, 0x9e290265, 0x0e208824, 0x2e65af79, 0x6f36a561, 0x9ad3204b, 0x0e21482e, 0x1e24431d, 0xd50330bf, 0x0df641aa, 0x6e602a83, 0xce30505f, 0x5e025238, 0xd503201f, 0x4e608880, 0x4de9c38d, 0x5e0f5348, 0x6eb48ca9, 0x50fda31b, 0x2e251eec, 0x7842ba50, 0xd8a1cd86, 0x2ea09862, 0x0ea09983, 0x2ea333b0, 0x0ea6032c, 0x4f94801b, 0x7e3ee57d, 0x38135e4f, 0xd8fdd9dd, 0x5ee0fcde, 0x9e64033d, 0x6e37f547, 0x6e3dd7ef, 0x13003f3d, 0x0e602f9f, 0x4e7ad014, 0x9b3b6857, 0x5ea0cb67, 0x0eb31c9f, 0x4e7c5372, 0x5e61b8c0, 0x0ea19b23, 0x0ee6e1df, 0x6e63a626, 0x2f139405, 0x7eb0f96d, 0x9e588c63, 0x2e714c3a, 0x6e8c941e, 0x0f61b331, 0x6f01f625, 0x4e78d4ea, 0x6f403709, 0x1a0300da, 0xda0102c8, 0x7e61d9fd, 0xb89469bb, 0x0c838780, 0x2e60a590, 0x4dfd29e1, 0x4e150f2e, 0xce2810bc, 0x5f541591, 0x9ee60259, 0x2eb40e56, 0x5e014027, 0x2ef71faf, 0x4e2d452f, 0x5ee0a813, 0x4eb03301, 0x38443acf, 0x6eabd502, 0x0e2ee71e, 0x5a960364, 0xce7ec596, 0x7efbed09, 0x4ef42ea2, 0x0eb30ea5, 0x5ee0d9f8, 0x6f513552, 0xf89eb3fa, 0x7ea2eca6, 0x9b00cc19, 0xf897409e, 0x1e73485f, 0x381afa77, 0x0f169f3b, 0x5ee1aa70, 0x5e1803ee, 0x0dbf5a4c, 0xce78c7a6, 0x9b0b260c, 0x2ef8fa19, 0x6e70aa4b, 0xce45b805, 0x2ea08e86, 0x4ee0bafd, 0x2ea09a1f, 0x4e218900, 0x6e744f13, 0xce518653, 0xf81b7a68, 0xce45ac5e, 0x7e62e416, 0x1a1b02b6, 0x7e21db48, 0x381daaaf, 0x6b2c0987, 0x0e2ec651, 0x4eae8502, 0x9bde7ca0, 0x6f47201f, 0x7e61a8a3, 0x6e60d5db, 0x4e2879de, 0xf81d194e, 0x4f1b8d05, 0x4d0048b2, 0x6e203be9, 0x4e3e7eb1, 0x0e260ef8, 0x2e688518, 0x7e3fec46, 0xdac00843, 0xf85c8917, 0x2e212a0f, 0x0e8196da, 0xd503359f, 0xce4c81f2, 0x6ee19992, 0x6e21ca79, 0x4d40c1d2, 0x4f5816ef, 0x4e34c3ea, 0x4df7c283, 0x7ef7eeb6, 0x18e276ce, 0xab0d21c0, 0xd5032f7f, 0x4ea00dbf, 0x5ac01251, 0xd0121955, 0x7f1495e4, 0x7ef0fa11, 0x5e24dd9c, 0x9add25b5, 0x0eb2bdef, 0x9e1977c7, 0x6f4b26bd, 0x0e200a9c, 0x9b4f7c00, 0x0ea0392e, 0x7e212a2c, 0x0b248b90, 0x1acc27a1, 0x2e701c90, 0x5ee1b870, 0x5e280aba, 0x5ea0780e, 0x1e264246, 0x4e052d04, 0x0e731dc4, 0xce461997, 0x9a9e9413, 0x3d462048, 0x5ea1fac5, 0x2ea0c8c4, 0x9a030280, 0x2ebda4b8, 0x5eef8614, 0x6eadc4e0, 0xbd035a8f, 0x4e606b84, 0x4eb1aba1, 0x4e286928, 0x4e2858cc, 0x9add0ce9, 0x4e070d65, 0x5fd399d5, 0x0f03fde7, 0x6ee90c74, 0x4ef8e31e, 0x381d986a, 0x5ea0ebf4, 0x5ea0d87e, 0x2e76ac9e, 0x6eb36cd4, 0x2e6e1c4c, 0x2e2feebc, 0x1ace4b03, 0x5ee0db12, 0x5ea0e9b1, 0x2e1c32d5, 0x5fa49a09, 0x0e258737, 0x7e21ca8e, 0xce4f9988, 0x5f7f56a6, 0x0e739766, 0x4e28586c, 0x6e619908, 0xd500401f, 0xf88b9252, 0x6e251c8e, 0x9e20015b, 0x7f1486b9, 0x717c339b, 0x1f31ff70, 0x4ea0eb62, 0x9acb0926, 0x489f7d85, 0x4e209b54, 0x2e84cf03, 0x2e65946c, 0x0e7d80cd, 0xc8dffecc, 0xce668bd8, 0x6e2188af, 0xeb4ada34, 0x2b25ec33, 0x0d40e6e7, 0x4eb2c757, 0x4ec82ad0, 0x7e21cb0a, 0x0e21a847, 0x4e0b1ec0, 0x381e6ac0, 0x6e61c8f5, 0x0f10071c, 0x2ee21daa, 0x5e61ab31, 0x6e218892, 0x2e7e7cb5, 0x6f2826aa, 0x7f6b54df, 0x4eaa2620, 0xdac00034, 0x4f6477be, 0x7e6148ea, 0x4eef1f57, 0x78459aeb, 0x2ebc3f10, 0x2e35f4eb, 0x4fbf19ce, 0xd8d0e58e, 0x2e21bbc7, 0x6ee0cab6, 0x9bc57e3f, 0x2f854037, 0x4e92181c, 0x6e6d1f89, 0x0f305545, 0x4ee19a57, 0x0e887bdf, 0x5e1a4185, 0x7ef0c821, 0x2eb6607c, 0x2ea0d9b8, 0x9e0380f4, 0x2ebf1c83, 0x1e62597d, 0x7f6e2548, 0x5ac00205, 0x4e616adb, 0xce638b8c, 0x5e1653cf, 0x2e6069be, 0x0e2ac641, 0x1e33c76f, 0xce44956d, 0x9bb90d31, 0x1e24c20a, 0x7ee038c1, 0x93407e5e, 0x4e280127, 0xc8df7f7d, 0xba42f263, 0x1e6f199c, 0x6e212889, 0x6e92f60e, 0x6ebdc499, 0x8b9acbf8, 0x4d40c581, 0x3a020250, 0x6e6a6716, 0x9248403b, 0x9081ffea, 0x4e603856, 0x9ad1242b, 0x6f270579, 0x1a070349, 0xcec08133, 0xd503305f, 0x5a1a00ca, 0x2e60b8a2, 0x0e5f28fd, 0x0e31a3da, 0x7e61cbc1, 0xd503399f, 0x5f5e54aa, 0x0eb8bdea, 0x4eba8f10, 0x4e2a2e60, 0x2f3da7d6, 0x1e58e297, 0x6e71aa3e, 0x6b86701a, 0xce4fa5e6, 0x4ee7c463, 0x8a79307f, 0x0ebea541, 0x2e218af4, 0x4e774f8a, 0xb9b95dc5, 0x6e61abd5, 0x4dd1e814, 0x4da72098, 0x98307582, 0x3a512101, 0x7ef95497, 0x1ace5535, 0x5a0c0349, 0x4e28581b, 0x6ebf1c02, 0x5ea1da23, 0x1e274314, 0x5e25dd29, 0x6e75f594, 0x6eaf6ed5, 0x4e214abe, 0x4e064172, 0x2e21c8f4, 0xf84c5b08, 0x1e244312, 0x14000000}; - env.code_mem.emplace_back(0x14000000); // B . + void* buffer_ptr = reinterpret_cast(buffer); + size_t buffer_size_nconst = buffer_size; + char* backing_memory = reinterpret_cast(std::align(page_size, memory_size, buffer_ptr, buffer_size_nconst)); + + A64FastmemTestEnv env{backing_memory}; + Dynarmic::A64::UserConfig config{}; + config.callbacks = &env; + config.fastmem_pointer = reinterpret_cast(backing_memory); + config.fastmem_address_space_bits = address_width; + config.recompile_on_fastmem_failure = false; + config.silently_mirror_fastmem = true; + config.processor_id = 0; + A64::Jit jit{config}; + memset(backing_memory, 0, memory_size); + + // cat rand2.txt | awk '{print "env.code_mem.emplace_back(0x"$2"); // "$0}' > rand2-out.txt + env.MemoryWrite32(100, 0x58028edd); // 0000000000000084 58028edd ldr x29, #20952 + env.MemoryWrite32(104, 0x14000000); // 0000000000000ea4 14000000 b #0 + + jit.SetPC(100); + jit.SetPstate(0xb0000000); + jit.SetFpcr(0x01000000); + env.ticks_left = 110; + //jit.DumpDisassembly(); + CheckedRun([&]() { jit.Run(); }); +} + +TEST_CASE("A64: rand2", "[a64][.]") { + constexpr size_t address_width = 12; + constexpr size_t memory_size = 1ull << address_width; // 4K + constexpr size_t page_size = 4 * 1024; + constexpr size_t buffer_size = 2 * page_size; + char buffer[buffer_size]; + + void* buffer_ptr = reinterpret_cast(buffer); + size_t buffer_size_nconst = buffer_size; + char* backing_memory = reinterpret_cast(std::align(page_size, memory_size, buffer_ptr, buffer_size_nconst)); + + A64FastmemTestEnv env{backing_memory}; + Dynarmic::A64::UserConfig config{}; + config.callbacks = &env; + config.fastmem_pointer = reinterpret_cast(backing_memory); + config.fastmem_address_space_bits = address_width; + config.recompile_on_fastmem_failure = false; + config.silently_mirror_fastmem = true; + config.processor_id = 0; + A64::Jit jit{config}; + memset(backing_memory, 0, memory_size); + + // cat rand2.txt | awk '{print "env.code_mem.emplace_back(0x"$2"); // "$0}' > rand2-out.txt + const std::array code32 = {0xea80f352, 0x6e65e59d, 0x1e20c343, 0x2e3a7192, 0x2e267249, 0xd500405f, 0x6f01f461, 0x6eb684fc, 0x58028edd, 0x0ea5f5b6, 0x0ea069fb, 0x2e769517, 0x5e066063, 0x1e65c3f5, 0x4f00ff52, 0x93401cf6, 0x1e274248, 0x6f67aaf5, 0x5e0c0782, 0x5ef43f3c, 0x2e6595b7, 0x4e20590f, 0xb35aa451, 0x6ee2c5ed, 0x4e32bf46, 0x2ea1ba8f, 0x2f68a85e, 0x9237d90a, 0x5e23dd10, 0x0e762e32, 0x4e31a8cf, 0xce1f3360, 0x781a4ac0, 0x13834066, 0x5fa8101c, 0x6f7c5594, 0x0e71bb68, 0xbc0b3e8f, 0x785dbbda, 0x6f51e794, 0xce50af75, 0x1ad728ec, 0x6ee0da4c, 0xb84efa14, 0x2eb3f613, 0x4e287ade, 0x4eb8c734, 0x2e83f4e8, 0x0e397c80, 0xd08f93f8, 0xce718e48, 0x0f672a0d, 0x2e9edd40, 0x0e14128b, 0x6f5942e6, 0x8b3a0f03, 0x3c5d16b9, 0x7f7e3743, 0x4f4c54e4, 0x0ea0a9e9, 0x9e59dbe6, 0x6e7ddcd3, 0xcec08377, 0x9ba759f8, 0x2ea5046e, 0x0e24c569, 0xb8979780, 0x4e31b98c, 0x4efe4f46, 0x4ea7c762, 0x7e61c9c6, 0x6e30c880, 0x1ada0c25, 0x4e603a2f, 0xda9d7218, 0x0d40c5d9, 0x5e214b05, 0x9ba9efc5, 0x5e61b81e, 0x6e7bc31c, 0x0e61a163, 0x9e5832d2, 0x4e772248, 0x4e3d17c8, 0x92624f60, 0x7a1a02dc, 0x79891f65, 0x6eb45036, 0x0e321ee8, 0x4e2566f0, 0x4ea02b9b, 0x0f9dcb3d, 0x2e21b9f9, 0x0e21a8c3, 0xda1700bd, 0x6ea0fb38, 0x7e607a0b, 0x72845817, 0x7f61068e, 0x0d60e529, 0x4ea0ca5c, 0x1a94b20f, 0x8b87419d, 0x7ea9ed71, 0x2ea1a86e, 0x4d40c4da, 0x5ea0eada, 0x784ba96e, 0x7eb6ee02, 0x3db1c710, 0x0e217836, 0x7ee0bb96, 0x4e786c08, 0x4e976a08, 0x489ffe86, 0x4e79fc9b, 0x0e21cbce, 0x5ef7fc65, 0x4ea1286d, 0xd29c771e, 0x6f5c2839, 0x0ea00a9d, 0x6ee44c06, 0x5ee1d858, 0x5ef2fda6, 0x7eb0c9fe, 0x7f762791, 0x2e212ae6, 0x4e61c9db, 0x13003c57, 0x5ee1b8f8, 0x0f2396d2, 0x6ea0db1e, 0x0e71ba82, 0xab29c807, 0x6ef8f8b3, 0x1f18d4a1, 0x0e261d15, 0x1e290081, 0x1b0c7d12, 0x4e7771c3, 0xf845f1e4, 0x4d40c9e8, 0xce778452, 0x6eb9879d, 0x6e21c93d, 0xcec0829f, 0x52a0969f, 0x1e772b4f, 0x7ee1da88, 0x5f52fe0a, 0x7f3387b1, 0x5e214850, 0x1e65c025, 0x0e2ca294, 0x2e614829, 0x1e640077, 0x9e240048, 0x4ebe9537, 0x9bb7925e, 0x38b669c5, 0x2840d089, 0x6f43e648, 0x2e662d28, 0x4eabaff3, 0x6e734cc7, 0x0e31baee, 0x7ee0d93c, 0x5e282bde, 0x7e21bba4, 0x4e6c75fa, 0x5ac01217, 0x7f4304af, 0x1e7878ed, 0x1ada2196, 0x7ee1aba3, 0x93407f3c, 0x4f6c34eb, 0x6e3447a9, 0x7e7ae545, 0x5e0802bb, 0x6eeae63a, 0x7ee1da62, 0x5e280bb3, 0xf81d4009, 0x1e603b21, 0x5e281a14, 0x6eb0a99b, 0x1e266a25, 0x0d60cafe, 0x0e0b6194, 0x7a4ed2c5, 0x92b762ec, 0x4e6b5749, 0x3c16a6e5, 0x4ea0a92b, 0x0fa58b6a, 0x5f76148c, 0x6e30c95f, 0x1e6540fd, 0x5e28e40f, 0x0d403fd4, 0x7e30da36, 0x7fda9b51, 0x2ea04bde, 0x1e25c3d2, 0x1ee0434c, 0x5e21d8e7, 0x5ee1ba51, 0x5e61aba9, 0x4e2849fb, 0x5ee098ea, 0x4e60f63d, 0x0f280443, 0x5ee0da27, 0x2e78a6ce, 0x78054afc, 0x4e14286b, 0x4e218bd8, 0x2a3d2551, 0x3a04017a, 0x5f4317cd, 0x0e604a37, 0x9a834614, 0x0e2edf4d, 0x7a51a0a0, 0x5f8e9043, 0x6ea06bb2, 0xaa2857dd, 0x7a1903fc, 0x301ba9ba, 0x9ac929cd, 0x4e061ff0, 0x2e38fcfc, 0x0e2f614a, 0x7ee0d8e4, 0x6e73afda, 0x7f4156f7, 0x0e6078bf, 0x4ee1d9ed, 0x93403fbe, 0xce6f8640, 0x4e3855e3, 0x6f76fe23, 0x112466e8, 0x1e358a90, 0x7f45272c, 0x6ea19a9d, 0x8a696350, 0x1e3900f6, 0x5e61c866, 0x0e3fbfd0, 0x5ee09ad0, 0x0e651d27, 0x4dffc35e, 0x2e20c6ce, 0x0fbe118d, 0x1e656a15, 0xd1357365, 0x0e20a847, 0xce4a835c, 0x4e203905, 0x2e60090d, 0x7f4a27bb, 0x1e64c316, 0xce7d86a4, 0x7ebded2d, 0x6e70a97e, 0x4eb9a42b, 0x0e209bef, 0x6f151730, 0x0e7e30f7, 0x4e724509, 0xd503375f, 0xce58b6ae, 0x5e21a9b8, 0xcb2ca538, 0x5ac01131, 0x6ea19a24, 0xeb40c8b3, 0xc8df7d65, 0x78108341, 0x3218ab9b, 0x0f3da7dd, 0x2e003089, 0x4e21cab5, 0x8aa5c924, 0x1a94950c, 0x123e506f, 0x13117e37, 0x1ee6005b, 0x5ac00647, 0x5eec8cd5, 0x7ef0fb3d, 0x9223272a, 0x5ee0cb02, 0x6e66071d, 0x6ea1dbbf, 0x5e61c903, 0x5ac015ea, 0x93db6206, 0x7e62b5e3, 0x6ea0c87b, 0xdac0090e, 0x48df7d90, 0x6e206ba5, 0x9e2503c2, 0x6e25fc89, 0x4d60e2db, 0x1e3e22a0, 0x2eb81c19, 0x7856ea00, 0x5fbfb22d, 0x1e630244, 0x4e202a83, 0x1f50a722, 0x7f7b55d2, 0x0fae89b9, 0x4e781d73, 0xce738c3a, 0x4f15a591, 0x6e21c7e1, 0x586ff77e, 0x8a5d3592, 0x93401c67, 0x5e61cb86, 0xce6bc2c1, 0x6e393f10, 0x9bb70ec3, 0xdac0098c, 0x4da84b95, 0x7f494476, 0x9ace5c11, 0x7e61ca14, 0x4f7a60ef, 0x1ad32b39, 0x0ea3777f, 0x5e61da7f, 0x4f1404e2, 0x4e3244e2, 0x6e1b1ceb, 0x0dee5aac, 0x4e2f9dc4, 0x5ea1b8c3, 0x1e59f863, 0xd500403f, 0x4e3ae7d0, 0x4ef5c6ea, 0x08dffe3b, 0x6e36f4f6, 0x2e764f29, 0x0e726f23, 0x5f42375b, 0x7f71fc40, 0x6e618aad, 0x93403e5b, 0x0e205976, 0x0e7250c4, 0x6eb0abc9, 0x2e2049f0, 0x5f14754d, 0x7f6ce468, 0x6f950bbe, 0x6e31aa47, 0x4eb83396, 0x0dccc952, 0x2ea1ca90, 0xce69c701, 0xb0bed69e, 0x7c5dec39, 0x4e2868a2, 0x0e591b08, 0x5f34e6dd, 0x3a449184, 0x5e3ce6de, 0x4ea149b7, 0x4e7ad29b, 0xba198503, 0x1f683e8f, 0xfa52f2a7, 0x6e30dffc, 0x4e6c3d17, 0x2eae3248, 0xd503349f, 0x1e60002c, 0x0f180680, 0x9e240049, 0x6f75774e, 0xa90d8678, 0x9ad924c4, 0x7eb0f85b, 0x0e205aaf, 0x7ee08899, 0x5f4bffd8, 0x1b0ff5f3, 0x4ee11dcd, 0x2e218948, 0x0dcb2733, 0x4eac107c, 0x4ea04a53, 0x4e287b44, 0x0e60b82a, 0x5ee0ebbc, 0xce454ff1, 0x5e1761e7, 0x5e09202f, 0x0e0c0754, 0x1e72e6b9, 0x7e21da70, 0x0fbdb20c, 0x5efb8c84, 0xd500401f, 0x3a47526e, 0x1e680acf, 0x7f7375fc, 0xf80522da, 0x4ee60c02, 0x4d40c2e7, 0x6f89096b, 0x7ee1bb6e, 0x5e280b4a, 0x1e3120c8, 0x7eb2ef96, 0x4fd012dd, 0x0f3027ef, 0x4e2078a8, 0xd503201f, 0x2e2312d9, 0x6ebf1c6e, 0x5ee1f8df, 0x4e607a46, 0x6e30c877, 0x6c09d2d1, 0x4e61abd8, 0x0e35267e, 0x6ac17728, 0x0e861aa0, 0x6f63fe26, 0x6f157628, 0x6f30a5f9, 0x4d60cc0c, 0x4e21cb59, 0x2e68a3fb, 0x7efae601, 0x6ea0f82c, 0x9b25ec12, 0x1a1a0305, 0x0e043fe1, 0x6e73c0ed, 0x6ea1b8c0, 0x7e20380b, 0x0f0534e8, 0x1f56bc7d, 0xba0c0128, 0x1e672160, 0x6e7b259b, 0x7ee07b5d, 0x9a820443, 0x4e040581, 0x2f1d87e8, 0x1acd2f5b, 0x6e20794f, 0x2e6a3c93, 0xc8dffe13, 0xce5ab1c6, 0x6eea55f6, 0x4ea039b3, 0x0d602fec, 0x2e246e2f, 0x7857be39, 0xb80608fb, 0x1e67c017, 0x9bcf7f63, 0x0f92d857, 0x5e0812f7, 0x1e210172, 0x7e6128e9, 0x7ea94d41, 0x981179e1, 0x1effb018, 0x2e600828, 0x0eb9c6b2, 0x6ee1baae, 0x4ea0db28, 0x2ea1487b, 0x4ea6c7f0, 0x2e2374c7, 0x7e30d8dd, 0xb9991fa7, 0x4e791e3e, 0x889f7c4b, 0x0e6c753c, 0x1e740ad1, 0x1e244324, 0x1ef33010, 0x5ac01102, 0x9bd97fba, 0x6e290143, 0x1e2220d8, 0x4d8d5aee, 0x6f28570b, 0xfa4ab0c1, 0xdac00b14, 0x7ea1a90e, 0x2e3027d8, 0x6f25a733, 0x4e61a96e, 0x4e1a2fcb, 0x0e22fe0a, 0xc8df7cd0, 0x5e280a55, 0x4e012b20, 0x7e70dbf4, 0x520c5a4e, 0x6ea6c57f, 0x0e861af8, 0xd503233f, 0x889ffe3c, 0x5e274ea9, 0x4e21a89a, 0x0e170c02, 0x6efd4c0b, 0xd5033ebf, 0x6e61a92c, 0x2e205b72, 0x789fb828, 0x0e626e94, 0x2ea6724c, 0x9a10028b, 0x2c6c51fc, 0x5a9de6b9, 0x6e6881f3, 0x5ee0ea6b, 0x0faec36e, 0x0e955bca, 0x1acf206d, 0x7f6f571b, 0x4e286930, 0x12b41ceb, 0x1e770b7a, 0x0ea18ac2, 0x5e282aaf, 0xf2b7fa1e, 0x1ac34311, 0x13167d11, 0x4ea63412, 0x6e758038, 0x2f1d85d6, 0x0f275480, 0x0ead6c71, 0x6e204b69, 0x1e6303f4, 0x5e0031ef, 0x13001e40, 0x7a16006f, 0x6e6ae4c0, 0x0f0f242f, 0x6e674f50, 0x4e606b7a, 0x7e6ee684, 0x1e6b5957, 0x7ea1bbab, 0x7ea0b6cb, 0xce4da241, 0x0ea1b953, 0x0eb2af4b, 0x9ac309d0, 0x6e61d8bd, 0x5ea0d890, 0x5f47d1e7, 0xfa5981ca, 0x1e7f7959, 0x6ef24dd8, 0x0e0a41d1, 0x5ee0e898, 0x4e6038e2, 0x13097d65, 0x6f839088, 0x9e290265, 0x0e208824, 0x2e65af79, 0x6f36a561, 0x9ad3204b, 0x0e21482e, 0x1e24431d, 0xd50330bf, 0x0df641aa, 0x6e602a83, 0xce30505f, 0x5e025238, 0xd503201f, 0x4e608880, 0x4de9c38d, 0x5e0f5348, 0x6eb48ca9, 0x50fda31b, 0x2e251eec, 0x7842ba50, 0xd8a1cd86, 0x2ea09862, 0x0ea09983, 0x2ea333b0, 0x0ea6032c, 0x4f94801b, 0x7e3ee57d, 0x38135e4f, 0xd8fdd9dd, 0x5ee0fcde, 0x9e64033d, 0x6e37f547, 0x6e3dd7ef, 0x13003f3d, 0x0e602f9f, 0x4e7ad014, 0x9b3b6857, 0x5ea0cb67, 0x0eb31c9f, 0x4e7c5372, 0x5e61b8c0, 0x0ea19b23, 0x0ee6e1df, 0x6e63a626, 0x2f139405, 0x7eb0f96d, 0x9e588c63, 0x2e714c3a, 0x6e8c941e, 0x0f61b331, 0x6f01f625, 0x4e78d4ea, 0x6f403709, 0x1a0300da, 0xda0102c8, 0x7e61d9fd, 0xb89469bb, 0x0c838780, 0x2e60a590, 0x4dfd29e1, 0x4e150f2e, 0xce2810bc, 0x5f541591, 0x9ee60259, 0x2eb40e56, 0x5e014027, 0x2ef71faf, 0x4e2d452f, 0x5ee0a813, 0x4eb03301, 0x38443acf, 0x6eabd502, 0x0e2ee71e, 0x5a960364, 0xce7ec596, 0x7efbed09, 0x4ef42ea2, 0x0eb30ea5, 0x5ee0d9f8, 0x6f513552, 0xf89eb3fa, 0x7ea2eca6, 0x9b00cc19, 0xf897409e, 0x1e73485f, 0x381afa77, 0x0f169f3b, 0x5ee1aa70, 0x5e1803ee, 0x0dbf5a4c, 0xce78c7a6, 0x9b0b260c, 0x2ef8fa19, 0x6e70aa4b, 0xce45b805, 0x2ea08e86, 0x4ee0bafd, 0x2ea09a1f, 0x4e218900, 0x6e744f13, 0xce518653, 0xf81b7a68, 0xce45ac5e, 0x7e62e416, 0x1a1b02b6, 0x7e21db48, 0x381daaaf, 0x6b2c0987, 0x0e2ec651, 0x4eae8502, 0x9bde7ca0, 0x6f47201f, 0x7e61a8a3, 0x6e60d5db, 0x4e2879de, 0xf81d194e, 0x4f1b8d05, 0x4d0048b2, 0x6e203be9, 0x4e3e7eb1, 0x0e260ef8, 0x2e688518, 0x7e3fec46, 0xdac00843, 0xf85c8917, 0x2e212a0f, 0x0e8196da, 0xd503359f, 0xce4c81f2, 0x6ee19992, 0x6e21ca79, 0x4d40c1d2, 0x4f5816ef, 0x4e34c3ea, 0x4df7c283, 0x7ef7eeb6, 0x18e276ce, 0xab0d21c0, 0xd5032f7f, 0x4ea00dbf, 0x5ac01251, 0xd0121955, 0x7f1495e4, 0x7ef0fa11, 0x5e24dd9c, 0x9add25b5, 0x0eb2bdef, 0x9e1977c7, 0x6f4b26bd, 0x0e200a9c, 0x9b4f7c00, 0x0ea0392e, 0x7e212a2c, 0x0b248b90, 0x1acc27a1, 0x2e701c90, 0x5ee1b870, 0x5e280aba, 0x5ea0780e, 0x1e264246, 0x4e052d04, 0x0e731dc4, 0xce461997, 0x9a9e9413, 0x3d462048, 0x5ea1fac5, 0x2ea0c8c4, 0x9a030280, 0x2ebda4b8, 0x5eef8614, 0x6eadc4e0, 0xbd035a8f, 0x4e606b84, 0x4eb1aba1, 0x4e286928, 0x4e2858cc, 0x9add0ce9, 0x4e070d65, 0x5fd399d5, 0x0f03fde7, 0x6ee90c74, 0x4ef8e31e, 0x381d986a, 0x5ea0ebf4, 0x5ea0d87e, 0x2e76ac9e, 0x6eb36cd4, 0x2e6e1c4c, 0x2e2feebc, 0x1ace4b03, 0x5ee0db12, 0x5ea0e9b1, 0x2e1c32d5, 0x5fa49a09, 0x0e258737, 0x7e21ca8e, 0xce4f9988, 0x5f7f56a6, 0x0e739766, 0x4e28586c, 0x6e619908, 0xd500401f, 0xf88b9252, 0x6e251c8e, 0x9e20015b, 0x7f1486b9, 0x717c339b, 0x1f31ff70, 0x4ea0eb62, 0x9acb0926, 0x489f7d85, 0x4e209b54, 0x2e84cf03, 0x2e65946c, 0x0e7d80cd, 0xc8dffecc, 0xce668bd8, 0x6e2188af, 0xeb4ada34, 0x2b25ec33, 0x0d40e6e7, 0x4eb2c757, 0x4ec82ad0, 0x7e21cb0a, 0x0e21a847, 0x4e0b1ec0, 0x381e6ac0, 0x6e61c8f5, 0x0f10071c, 0x2ee21daa, 0x5e61ab31, 0x6e218892, 0x2e7e7cb5, 0x6f2826aa, 0x7f6b54df, 0x4eaa2620, 0xdac00034, 0x4f6477be, 0x7e6148ea, 0x4eef1f57, 0x78459aeb, 0x2ebc3f10, 0x2e35f4eb, 0x4fbf19ce, 0xd8d0e58e, 0x2e21bbc7, 0x6ee0cab6, 0x9bc57e3f, 0x2f854037, 0x4e92181c, 0x6e6d1f89, 0x0f305545, 0x4ee19a57, 0x0e887bdf, 0x5e1a4185, 0x7ef0c821, 0x2eb6607c, 0x2ea0d9b8, 0x9e0380f4, 0x2ebf1c83, 0x1e62597d, 0x7f6e2548, 0x5ac00205, 0x4e616adb, 0xce638b8c, 0x5e1653cf, 0x2e6069be, 0x0e2ac641, 0x1e33c76f, 0xce44956d, 0x9bb90d31, 0x1e24c20a, 0x7ee038c1, 0x93407e5e, 0x4e280127, 0xc8df7f7d, 0xba42f263, 0x1e6f199c, 0x6e212889, 0x6e92f60e, 0x6ebdc499, 0x8b9acbf8, 0x4d40c581, 0x3a020250, 0x6e6a6716, 0x9248403b, 0x9081ffea, 0x4e603856, 0x9ad1242b, 0x6f270579, 0x1a070349, 0xcec08133, 0xd503305f, 0x5a1a00ca, 0x2e60b8a2, 0x0e5f28fd, 0x0e31a3da, 0x7e61cbc1, 0xd503399f, 0x5f5e54aa, 0x0eb8bdea, 0x4eba8f10, 0x4e2a2e60, 0x2f3da7d6, 0x1e58e297, 0x6e71aa3e, 0x6b86701a, 0xce4fa5e6, 0x4ee7c463, 0x8a79307f, 0x0ebea541, 0x2e218af4, 0x4e774f8a, 0xb9b95dc5, 0x6e61abd5, 0x4dd1e814, 0x4da72098, 0x98307582, 0x3a512101, 0x7ef95497, 0x1ace5535, 0x5a0c0349, 0x4e28581b, 0x6ebf1c02, 0x5ea1da23, 0x1e274314, 0x5e25dd29, 0x6e75f594, 0x6eaf6ed5, 0x4e214abe, 0x4e064172, 0x2e21c8f4, 0xf84c5b08, 0x1e244312, 0x14000000}; + for (size_t i = 0; i < code32.size(); ++i) + env.MemoryWrite32(100 + i, code32[i]); + env.ignore_invalid_insn = true; jit.SetRegister(0, 0x866524401a1d4e47); jit.SetRegister(1, 0x02ca8cec51301b60); @@ -1619,8 +1670,6 @@ TEST_CASE("A64: rand2", "[a64][.]") { jit.SetPC(100); jit.SetSP(0x000000cdfadeaff0); - env.code_mem_start_address = 100; - jit.SetVector(0, {0x4d5a180ac0ffdac8, 0xfc6eb113cd5ff2a8}); jit.SetVector(1, {0x39f8cecc9de9cefd, 0x3a6b35d333d89a6b}); jit.SetVector(2, {0x791fd8290bbdd2f4, 0xdc0e5e7aee311411}); @@ -1658,7 +1707,7 @@ TEST_CASE("A64: rand2", "[a64][.]") { jit.SetFpcr(0x01000000); env.ticks_left = 110; - jit.Run(); + CheckedRun([&]() { jit.Run(); }); REQUIRE(jit.GetVector(0) == Vector{0x0101010211914707, 0x090000007fd9991a}); REQUIRE(jit.GetVector(1) == Vector{0x00000000fffffffe, 0x0000000000000000}); @@ -1730,7 +1779,7 @@ TEST_CASE("A64: SABD", "[a64]") { jit.SetVector(8, vectors[8]); env.ticks_left = env.code_mem.size(); - jit.Run(); + CheckedRun([&]() { jit.Run(); }); CHECK(jit.GetVector(0) == vectors[0]); CHECK(jit.GetVector(1) == vectors[1]); @@ -1747,7 +1796,7 @@ TEST_CASE("A64: SABD", "[a64]") { jit.SetVector(8, vectors[7]); env.ticks_left = 4; - jit.Run(); + CheckedRun([&]() { jit.Run(); }); CHECK(jit.GetVector(0) == vectors[0]); CHECK(jit.GetVector(1) == vectors[1]); @@ -1769,7 +1818,7 @@ TEST_CASE("A64: UZP{1,2}.2D", "[a64]") { jit.SetVector(1, {0xA0A1A2A3A4A5A6A7, 0xB0B1B2B3B4B5B6B7}); env.ticks_left = env.code_mem.size(); - jit.Run(); + CheckedRun([&]() { jit.Run(); }); REQUIRE(jit.GetVector(2) == Vector{0xF0F1F2F3F4F5F6F7, 0xA0A1A2A3A4A5A6A7}); REQUIRE(jit.GetVector(3) == Vector{0xE0E1E2E3E4E5E6E7, 0xB0B1B2B3B4B5B6B7}); @@ -1792,7 +1841,7 @@ TEST_CASE("A64: UZP{1,2}.S", "[a64]") { jit.SetVector(1, {0xA4A5A6A7'A0A1A2A3, 0xB4B5B6B7'B0B1B2B3}); env.ticks_left = env.code_mem.size(); - jit.Run(); + CheckedRun([&]() { jit.Run(); }); REQUIRE(jit.GetVector(2) == Vector{0xA0A1A2A3'F0F1F2F3, 0}); REQUIRE(jit.GetVector(3) == Vector{0xA4A5A6A7'F4F5F6F7, 0}); @@ -1817,7 +1866,7 @@ TEST_CASE("A64: UZP{1,2}.H", "[a64]") { jit.SetVector(1, {0xA6A7'A4A5'A2A3'A0A1, 0xB6B7'B4B5'B2B3'B0B1}); env.ticks_left = env.code_mem.size(); - jit.Run(); + CheckedRun([&]() { jit.Run(); }); REQUIRE(jit.GetVector(2) == Vector{0xA4A5'A0A1'F4F5'F0F1, 0}); REQUIRE(jit.GetVector(3) == Vector{0xA6A7'A2A3'F6F7'F2F3, 0}); @@ -1842,7 +1891,7 @@ TEST_CASE("A64: UZP{1,2}.B", "[a64]") { jit.SetVector(1, {0xA7'A6'A5'A4'A3'A2'A1'A0, 0xB7'B6'B5'B4'B3'B2'B1'B0}); env.ticks_left = env.code_mem.size(); - jit.Run(); + CheckedRun([&]() { jit.Run(); }); REQUIRE(jit.GetVector(2) == Vector{0xA6'A4'A2'A0'F6'F4'F2'F0, 0}); REQUIRE(jit.GetVector(3) == Vector{0xA7'A5'A3'A1'F7'F5'F3'F1, 0}); @@ -1883,7 +1932,7 @@ TEST_CASE("A64: {S,U}MIN.S, {S,U}MAX.S", "[a64]") { jit.SetVector(1, vectors[1]); env.ticks_left = env.code_mem.size(); - jit.Run(); + CheckedRun([&]() { jit.Run(); }); CHECK(jit.GetVector(2) == vectors[2]); CHECK(jit.GetVector(3) == vectors[3]); @@ -1929,7 +1978,7 @@ TEST_CASE("A64: {S,U}MIN.H, {S,U}MAX.H", "[a64]") { jit.SetVector(1, vectors[1]); env.ticks_left = env.code_mem.size(); - jit.Run(); + CheckedRun([&]() { jit.Run(); }); CHECK(jit.GetVector(2) == vectors[2]); CHECK(jit.GetVector(3) == vectors[3]); @@ -1975,7 +2024,7 @@ TEST_CASE("A64: {S,U}MIN.B, {S,U}MAX.B", "[a64]") { jit.SetVector(1, vectors[1]); env.ticks_left = env.code_mem.size(); - jit.Run(); + CheckedRun([&]() { jit.Run(); }); CHECK(jit.GetVector(2) == vectors[2]); CHECK(jit.GetVector(3) == vectors[3]); @@ -2027,7 +2076,7 @@ TEST_CASE("A64: {S,U}MINP.S, {S,U}MAXP.S", "[a64]") { jit.SetVector(1, vectors[1]); env.ticks_left = env.code_mem.size(); - jit.Run(); + CheckedRun([&]() { jit.Run(); }); CHECK(jit.GetVector(2) == vectors[2]); CHECK(jit.GetVector(3) == vectors[3]); @@ -2046,7 +2095,7 @@ TEST_CASE("A64: {S,U}MINP.S, {S,U}MAXP.S", "[a64]") { jit.SetVector(1, vectors[11]); env.ticks_left = env.code_mem.size(); - jit.Run(); + CheckedRun([&]() { jit.Run(); }); CHECK(jit.GetVector(2) == vectors[2]); CHECK(jit.GetVector(3) == vectors[3]); @@ -2097,7 +2146,7 @@ TEST_CASE("A64: {S,U}MINP.H, {S,U}MAXP.H", "[a64]") { jit.SetVector(1, vectors[1]); env.ticks_left = env.code_mem.size(); - jit.Run(); + CheckedRun([&]() { jit.Run(); }); CHECK(jit.GetVector(2) == vectors[2]); CHECK(jit.GetVector(3) == vectors[3]); @@ -2116,7 +2165,7 @@ TEST_CASE("A64: {S,U}MINP.H, {S,U}MAXP.H", "[a64]") { jit.SetVector(1, vectors[11]); env.ticks_left = env.code_mem.size(); - jit.Run(); + CheckedRun([&]() { jit.Run(); }); CHECK(jit.GetVector(2) == vectors[2]); CHECK(jit.GetVector(3) == vectors[3]); @@ -2167,7 +2216,7 @@ TEST_CASE("A64: {S,U}MINP.B, {S,U}MAXP.B", "[a64]") { jit.SetVector(1, vectors[1]); env.ticks_left = env.code_mem.size(); - jit.Run(); + CheckedRun([&]() { jit.Run(); }); CHECK(jit.GetVector(2) == vectors[2]); CHECK(jit.GetVector(3) == vectors[3]); @@ -2189,7 +2238,7 @@ TEST_CASE("A64: {S,U}MINP.B, {S,U}MAXP.B", "[a64]") { jit.SetVector(1, vectors[11]); env.ticks_left = env.code_mem.size(); - jit.Run(); + CheckedRun([&]() { jit.Run(); }); CHECK(jit.GetVector(2) == vectors[2]); CHECK(jit.GetVector(3) == vectors[3]); @@ -2258,7 +2307,7 @@ TEST_CASE("A64: SQABS", "[a64]") { jit.SetVector(13, Vector{0x89C1B48FBC43F53B, 0x5FDD5D671D399E2}); env.ticks_left = env.code_mem.size(); - jit.Run(); + CheckedRun([&]() { jit.Run(); }); CHECK(jit.GetVector(0) == Vector{0x2B'7F'14'2A'77'32'7F'10, 0x63'16'7E'45'7F'33'42'04}); CHECK(FP::FPSR{(uint32_t)jit.GetRegister(0)}.QC() == 1); @@ -2278,3 +2327,61 @@ TEST_CASE("A64: SQABS", "[a64]") { CHECK(jit.GetVector(13) == Vector{0x763E4B7043BC0AC5, 0x5FDD5D671D399E2}); CHECK(FP::FPSR{(uint32_t)jit.GetRegister(13)}.QC() == 0); } + +TEST_CASE("A64: RBIT{16b}", "[a64]") { + A64TestEnv env; + A64::UserConfig conf{}; + conf.callbacks = &env; + A64::Jit jit{conf}; + env.code_mem.emplace_back(0x6e605841); // rbit v1.16b, v2.16b + env.code_mem.emplace_back(0x6e605822); // rbit v2.16b, v1.16b + env.code_mem.emplace_back(0x14000000); // b . + jit.SetVector(2, { 0xcafedead, 0xbabebeef }); + jit.SetPC(0); // at _start + env.ticks_left = 4; + CheckedRun([&]() { jit.Run(); }); + REQUIRE(jit.GetVector(1)[0] == 0x537f7bb5); + REQUIRE(jit.GetVector(1)[1] == 0x5d7d7df7); + REQUIRE(jit.GetVector(2)[0] == 0xcafedead); + REQUIRE(jit.GetVector(2)[1] == 0xbabebeef); +} + +TEST_CASE("A64: CLZ{X}", "[a64]") { + A64TestEnv env; + A64::UserConfig conf{}; + conf.callbacks = &env; + A64::Jit jit{conf}; + env.code_mem.emplace_back(0xdac01060); // clz x0, x3 + env.code_mem.emplace_back(0xdac01081); // clz x1, x4 + env.code_mem.emplace_back(0xdac010a2); // clz x2, x5 + env.code_mem.emplace_back(0x14000000); // b . + jit.SetRegister(3, 0xfffffffffffffff0); + jit.SetRegister(4, 0x0fffffff0ffffff0); + jit.SetRegister(5, 0x07fffffeffeffef0); + jit.SetPC(0); // at _start + env.ticks_left = 4; + CheckedRun([&]() { jit.Run(); }); + REQUIRE(jit.GetRegister(0) == 0); + REQUIRE(jit.GetRegister(1) == 4); + REQUIRE(jit.GetRegister(2) == 5); +} + +TEST_CASE("A64: CLZ{W}", "[a64]") { + A64TestEnv env; + A64::UserConfig conf{}; + conf.callbacks = &env; + A64::Jit jit{conf}; + env.code_mem.emplace_back(0x5ac01060); // clz w0, w3 + env.code_mem.emplace_back(0x5ac01081); // clz w1, w4 + env.code_mem.emplace_back(0x5ac010a2); // clz w2, w5 + env.code_mem.emplace_back(0x14000000); // b . + jit.SetRegister(3, 0xffff1110); + jit.SetRegister(4, 0x0fff1110); + jit.SetRegister(5, 0x07fffffe); + jit.SetPC(0); // at _start + env.ticks_left = 4; + CheckedRun([&]() { jit.Run(); }); + REQUIRE(jit.GetRegister(0) == 0); + REQUIRE(jit.GetRegister(1) == 4); + REQUIRE(jit.GetRegister(2) == 5); +} diff --git a/src/dynarmic/tests/A64/fibonacci.cpp b/src/dynarmic/tests/A64/fibonacci.cpp index cbb02d1b01..713a48cab7 100644 --- a/src/dynarmic/tests/A64/fibonacci.cpp +++ b/src/dynarmic/tests/A64/fibonacci.cpp @@ -8,7 +8,7 @@ #include #include -#include +#include #include #include "dynarmic/common/common_types.h" @@ -23,7 +23,7 @@ namespace { class MyEnvironment final : public A64::UserCallbacks { public: u64 ticks_left = 0; - std::map memory{}; + std::unordered_map memory{}; u8 MemoryRead8(u64 vaddr) override { return memory[vaddr]; diff --git a/src/dynarmic/tests/A64/fp_min_max.cpp b/src/dynarmic/tests/A64/fp_min_max.cpp index 3d997d956d..d8b45db807 100644 --- a/src/dynarmic/tests/A64/fp_min_max.cpp +++ b/src/dynarmic/tests/A64/fp_min_max.cpp @@ -87,7 +87,7 @@ void run_test(u32 instruction, Fn fn) { jit.SetPC(0); env.ticks_left = 2; - jit.Run(); + CheckedRun([&]() { jit.Run(); }); REQUIRE(jit.GetVector(0)[0] == fn(test_case)); @@ -97,7 +97,7 @@ void run_test(u32 instruction, Fn fn) { jit.SetPC(0); env.ticks_left = 2; - jit.Run(); + CheckedRun([&]() { jit.Run(); }); REQUIRE(jit.GetVector(0)[0] == fn(test_case)); @@ -109,7 +109,7 @@ void run_test(u32 instruction, Fn fn) { jit.SetPC(0); env.ticks_left = 2; - jit.Run(); + CheckedRun([&]() { jit.Run(); }); REQUIRE(jit.GetVector(0)[0] == force_default_nan(fn(test_case))); @@ -119,7 +119,7 @@ void run_test(u32 instruction, Fn fn) { jit.SetPC(0); env.ticks_left = 2; - jit.Run(); + CheckedRun([&]() { jit.Run(); }); REQUIRE(jit.GetVector(0)[0] == force_default_nan(fn(test_case))); } @@ -136,7 +136,7 @@ void run_test(u32 instruction, Fn fn) { jit.SetPC(0); env.ticks_left = 2; - jit.Run(); + CheckedRun([&]() { jit.Run(); }); REQUIRE(jit.GetVector(0)[0] == fn(test_case)); @@ -148,7 +148,7 @@ void run_test(u32 instruction, Fn fn) { jit.SetPC(0); env.ticks_left = 2; - jit.Run(); + CheckedRun([&]() { jit.Run(); }); REQUIRE(jit.GetVector(0)[0] == force_default_nan(fn(test_case))); } diff --git a/src/dynarmic/tests/A64/fuzz_with_unicorn.cpp b/src/dynarmic/tests/A64/fuzz_with_unicorn.cpp index 8eda62f21e..885bf3c0e7 100644 --- a/src/dynarmic/tests/A64/fuzz_with_unicorn.cpp +++ b/src/dynarmic/tests/A64/fuzz_with_unicorn.cpp @@ -91,6 +91,9 @@ static u32 GenRandomInst(u64 pc, bool is_last_inst) { "MSR_reg", "MSR_imm", "MRS", + // Does not need test + "SVC", + "BRK" }; for (const auto& [fn, bitstring] : list) { @@ -198,9 +201,9 @@ static void RunTestInstance(Dynarmic::A64::Jit& jit, A64Unicorn& uni, A64TestEnv uni.ClearPageCache(); jit_env.ticks_left = instructions.size(); - jit.Run(); + CheckedRun([&]() { jit.Run(); }); - uni_env.ticks_left = instructions.size(); + uni_env.ticks_left = instructions.size() * 4; uni.Run(); SCOPE_FAIL { @@ -296,7 +299,7 @@ static void RunTestInstance(Dynarmic::A64::Jit& jit, A64Unicorn& uni, A64TestEnv return; } - REQUIRE(uni.GetPC() == jit.GetPC()); + REQUIRE(uni.GetPC() + 4 == jit.GetPC()); REQUIRE(uni.GetRegisters() == jit.GetRegisters()); REQUIRE(uni.GetVectors() == jit.GetVectors()); REQUIRE(uni.GetSP() == jit.GetSP()); @@ -306,7 +309,7 @@ static void RunTestInstance(Dynarmic::A64::Jit& jit, A64Unicorn& uni, A64TestEnv REQUIRE(FP::FPSR{uni.GetFpsr()}.QC() == FP::FPSR{jit.GetFpsr()}.QC()); } -TEST_CASE("A64: Single random instruction", "[a64]") { +TEST_CASE("A64: Single random instruction", "[a64][unicorn]") { A64TestEnv jit_env{}; A64TestEnv uni_env{}; @@ -333,7 +336,7 @@ TEST_CASE("A64: Single random instruction", "[a64]") { } } -TEST_CASE("A64: Floating point instructions", "[a64]") { +TEST_CASE("A64: Floating point instructions", "[a64][unicorn]") { A64TestEnv jit_env{}; A64TestEnv uni_env{}; @@ -458,7 +461,7 @@ TEST_CASE("A64: Floating point instructions", "[a64]") { } } -TEST_CASE("A64: Small random block", "[a64]") { +TEST_CASE("A64: Small random block", "[a64][unicorn]") { A64TestEnv jit_env{}; A64TestEnv uni_env{}; @@ -493,7 +496,7 @@ TEST_CASE("A64: Small random block", "[a64]") { } } -TEST_CASE("A64: Large random block", "[a64]") { +TEST_CASE("A64: Large random block", "[a64][unicorn]") { A64TestEnv jit_env{}; A64TestEnv uni_env{}; diff --git a/src/dynarmic/tests/A64/misaligned_page_table.cpp b/src/dynarmic/tests/A64/misaligned_page_table.cpp index 75ac41e06d..8235e14a67 100644 --- a/src/dynarmic/tests/A64/misaligned_page_table.cpp +++ b/src/dynarmic/tests/A64/misaligned_page_table.cpp @@ -24,7 +24,7 @@ TEST_CASE("misaligned load/store do not use page_table when detect_misaligned_ac jit.SetRegister(0, 0x000000000b0afff8); env.ticks_left = 2; - jit.Run(); + CheckedRun([&]() { jit.Run(); }); // If we don't crash we're fine. } diff --git a/src/dynarmic/tests/A64/real_world.cpp b/src/dynarmic/tests/A64/real_world.cpp new file mode 100644 index 0000000000..07532d95af --- /dev/null +++ b/src/dynarmic/tests/A64/real_world.cpp @@ -0,0 +1,102 @@ +// SPDX-FileCopyrightText: Copyright 2025 Eden Emulator Project +// SPDX-License-Identifier: GPL-3.0-or-later + +#include +#include + +#include "./testenv.h" +#include "dynarmic/interface/A64/a64.h" + +using namespace Dynarmic; +/* Following C program: +int M[64]; +int grob(int a, int b, int c, int d, int e, int f, int g, int h, int i, int j, int k, int l) { + M[a] += M[b]; // TOTAL GCC DESTRUCTION + return a * b * c * d * e * f * g * h * i * j * k * l; +} +int _start() { + return grob( + grob(M[1], M[2], M[3], M[4], M[5], M[6], M[7], M[8], M[9], M[10], M[11], M[12]), + grob(M[1], M[2], M[3], M[4], M[5], M[6], M[7], M[8], M[9], M[10], M[11], M[12]), + grob(M[1], M[2], M[3], M[4], M[5], M[6], M[7], M[8], M[9], M[10], M[11], M[12]), + grob(M[1], M[2], M[3], M[4], M[5], M[6], M[7], M[8], M[9], M[10], M[11], M[12]), + grob(M[1], M[2], M[3], M[4], M[5], M[6], M[7], M[8], M[9], M[10], M[11], M[12]), + grob(M[1], M[2], M[3], M[4], M[5], M[6], M[7], M[8], M[9], M[10], M[11], M[12]), + grob(M[1], M[2], M[3], M[4], M[5], M[6], M[7], M[8], M[9], M[10], M[11], M[12]), + grob(M[1], M[2], M[3], M[4], M[5], M[6], M[7], M[8], M[9], M[10], M[11], M[12]), + grob(M[1], M[2], M[3], M[4], M[5], M[6], M[7], M[8], M[9], M[10], M[11], M[12]), + grob(M[1], M[2], M[3], M[4], M[5], M[6], M[7], M[8], M[9], M[10], M[11], M[12]), + grob(M[1], M[2], M[3], M[4], M[5], M[6], M[7], M[8], M[9], M[10], M[11], M[12]), + grob(M[1], M[2], M[3], M[4], M[5], M[6], M[7], M[8], M[9], M[10], M[11], M[12]) + ); +} +#ifdef __x86_64__ +#include +int main() { + return printf("%i", start_e()); +} +#endif + +cat < a64-linker.ld >> EOF +ENTRY(_start); +PHDRS { text PT_LOAD; rodata PT_LOAD; data PT_LOAD; } +SECTIONS { + . = 0; + .text : { *(.text .text.*) } :text + .rodata : { *(.rodata .rodata.*) } :rodata + .data : ALIGN(CONSTANT(MAXPAGESIZE)) { *(.data .data.*) } :data + .bss : { *(.bss .bss.*) *(COMMON) } :data + /DISCARD/ : { *(.eh_frame*) *(.note .note.*) } +} +EOF +aarch64-linux-gnu-gcc -Wl,-Ta64-linker.ld -Wall -Wextra -ffreestanding -nostdlib -fno-whole-program -O2 grob.c -o grob | aarch64-linux-gnu-objdump -SC grob | awk '{print "env.code_mem.emplace_back(0x"$2"); //" $0}' +aarch64-linux-gnu-gcc -Wl,-Ta64-linker.ld -Wall -Wextra -ffreestanding -nostdlib -fno-whole-program -O2 grob.c -o grob | aarch64-linux-gnu-objdump -SC grob | awk '{print $2", "}' +*/ +TEST_CASE("high register pressure proper handling with block linking 1", "[a64][c]") { + A64TestEnv env; + A64::UserConfig conf{}; + conf.callbacks = &env; + A64::Jit jit{conf}; + + REQUIRE(conf.HasOptimization(OptimizationFlag::BlockLinking)); + env.code_mem = { 0x90000008, 0x91230108, 0xb860d909, 0xb861d90a, 0x0b0a0129, 0xb820d909, 0x1b017c00, 0xb94003e1, 0x1b027c00, 0x1b037c00, 0x1b047c00, 0x1b057c00, 0x1b067c00, 0x1b077c00, 0x1b017c00, 0xb9400be1, 0x1b017c00, 0xb94013e1, 0x1b017c00, 0xb9401be1, 0x1b017c00, 0xd65f03c0, 0xd503201f, 0xd503201f, 0xa9a27bfd, 0x90000000, 0x91230000, 0x910003fd, 0xa90153f3, 0xa9025bf5, 0xa90363f7, 0xa9046bf9, 0xa90573fb, 0x29408c01, 0x2941b40e, 0xb863d804, 0xb861d802, 0x2942ac0c, 0x0b040042, 0x1b037c24, 0x2943a40a, 0x29449c08, 0x1b0e7c84, 0x29459406, 0xb821d802, 0x1b0d7c84, 0x29408c01, 0x2941b40e, 0x1b0c7c84, 0x1b0b7c84, 0x2942ac0c, 0x1b0a7c84, 0x1b097c84, 0x2943a40a, 0x1b087c84, 0x1b077c84, 0x29449c08, 0xb863d80f, 0x1b037c23, 0x1b067c84, 0xb861d802, 0x0b0f0042, 0x1b0e7c63, 0x1b057c84, 0x29459406, 0xb821d802, 0x1b0d7c63, 0x2943f002, 0x2940d801, 0x1b0c7c63, 0x2941e81b, 0x2942e019, 0x1b0b7c63, 0xb90067e2, 0x1b0a7c63, 0x1b097c63, 0x1b087c63, 0x1b077c63, 0x1b067c63, 0x1b057c63, 0x29449402, 0x290d17e2, 0xb876d805, 0xb861d802, 0x29459c06, 0x0b050042, 0xb821d802, 0x1b167c21, 0x290e1fe6, 0x2940d40c, 0x1b1b7c21, 0x2941a408, 0x290f27e8, 0x2942ac0a, 0x1b1a7c21, 0xb86cd802, 0xb875d805, 0x29102fea, 0x0b050042, 0x1b197c21, 0x2943b80d, 0x29113bed, 0x2944c00f, 0x291243ef, 0x1b187c21, 0x2945c811, 0xb82cd802, 0x29134bf1, 0x1b157d8c, 0x2941f813, 0x2940d00b, 0x29147bf3, 0x29429402, 0x291517e2, 0x29439c06, 0x29161fe6, 0x2944a408, 0xb874d805, 0xb86bd802, 0x291727e8, 0x0b050042, 0x2945b80a, 0xb82bd802, 0x29183bea, 0x1b147d6b, 0x2941c00f, 0x2940cc0a, 0x291943ef, 0x2942c811, 0x291a4bf1, 0x2943881e, 0x291b0bfe, 0x29449805, 0x291c1be5, 0x2945a007, 0x291d23e7, 0xb86ad802, 0xb873d805, 0x0b050042, 0xb82ad802, 0x1b137d4a, 0x2941b80d, 0x2940f809, 0x291e3bed, 0x2942c00f, 0x291f43ef, 0x2943c811, 0xb90103f1, 0xb90107f2, 0x29449402, 0xb9010be2, 0xb9010fe5, 0xb869d802, 0xb87ed805, 0x29459c06, 0x0b050042, 0xb829d802, 0x1b1e7d29, 0xb90113e6, 0xb90117e7, 0x2941bc0e, 0x2940c808, 0xb9011bee, 0xb9011fef, 0x2942c410, 0xb90123f0, 0xb90127f1, 0x29439402, 0xb9012be2, 0xb9012fe5, 0xb868d802, 0x29449c06, 0xb90133e6, 0xb90137e7, 0xb872d805, 0x2945b80d, 0x0b050042, 0xb828d802, 0x1b127d08, 0xb9013bed, 0xb9013fee, 0x2941c00f, 0x2940c407, 0xb90143ef, 0xb90147f0, 0x29429402, 0xb9014be2, 0xb9014fe5, 0x2943b806, 0xb90153e6, 0xb90157ee, 0x2944c00f, 0xb9015bef, 0xb9015ff0, 0x29459402, 0xb90163e2, 0xb867d802, 0xb90167e5, 0xb871d805, 0x0b050042, 0xb827d802, 0x1b117ce7, 0x2940c002, 0x2941b406, 0xb9016be6, 0xb9016fed, 0x2942bc0e, 0xb90173ee, 0xb90177ef, 0x29439805, 0xb9017be5, 0xb9017fe6, 0x2944bc0e, 0xb90183ee, 0xb90187ef, 0x29459805, 0xb9018be5, 0xb862d805, 0xb9018fe6, 0xb870d806, 0x0b0600a5, 0xb822d805, 0x1b107c42, 0x2941b80d, 0x2940bc06, 0xb90193ed, 0xb90197ee, 0x2942b805, 0xb9019be5, 0xb9019fee, 0x2943b405, 0xb901a3e5, 0xb901a7ed, 0xb86fd80d, 0x2944940e, 0xb901abee, 0xb901afe5, 0x2945940e, 0xb901b7e5, 0xb866d805, 0xb901b3ee, 0x0b0d00a5, 0xb826d805, 0x2941dc0d, 0x2940b805, 0xb901bbed, 0xb901bff7, 0x2942b417, 0xb901c3f7, 0xb901c7ed, 0x2943b417, 0xb901cbf7, 0xb901cfed, 0x2944b417, 0xb901d3f7, 0xb901d7ed, 0x2945b417, 0xb901dbf7, 0xb86ed817, 0xb901dfed, 0xb865d80d, 0x0b1701ad, 0xb825d80d, 0xb863d817, 0x1b047c63, 0xb864d80d, 0x0b1701ad, 0xb824d80d, 0xb94067e0, 0xb9408bed, 0x1b007c21, 0xb9406be0, 0x1b1c7c21, 0x1b007c21, 0xb9406fe0, 0x1b007c21, 0xb94073e0, 0x1b007c21, 0xb94077e0, 0x1b007c21, 0xb9407be0, 0x1b007d8c, 0xb9407fe0, 0x1b037c21, 0x1b007d8c, 0xb94083e0, 0x1b007d8c, 0xb94087e0, 0x1b007d8c, 0xb9408fe0, 0x1b0d7d8c, 0xb940f3ed, 0x1b007d8c, 0xb94093e0, 0x1b0d7d29, 0x1b007d8c, 0xb94097e0, 0x1b007d8c, 0xb9409be0, 0x1b007d8c, 0xb9409fe0, 0x1b007d8c, 0xb940a3e0, 0x1b007d6b, 0xb940a7e0, 0x1b0c7c21, 0x1b007d6b, 0xb940abe0, 0x1b007d6b, 0xb940afe0, 0x1b007d6b, 0xb940b3e0, 0x1b007d6b, 0xb940b7e0, 0x1b007d6b, 0xb940bbe0, 0xb9413bed, 0x1b007d6b, 0xb940bfe0, 0x1b007d6b, 0xb940c3e0, 0x1b007d6b, 0xb940c7e0, 0x1b007d6b, 0xb940cbe0, 0x1b007d4a, 0xb940cfe0, 0x1b0b7c21, 0x1b007d4a, 0xb940d3e0, 0x1b007d4a, 0xb940d7e0, 0x1b007d4a, 0xb940dbe0, 0x1b007d4a, 0xb940dfe0, 0x1b007d4a, 0xb940e3e0, 0x1b007d4a, 0xb940e7e0, 0x1b007d4a, 0xb940ebe0, 0x1b007d4a, 0xb940efe0, 0x1b007d4a, 0xb940f7e0, 0x1b007d29, 0xb940fbe0, 0x1b0a7c21, 0x1b007d29, 0x295f8fe0, 0x1b007d20, 0x1b037c00, 0xb94107e3, 0x1b037c00, 0xb9410be3, 0x1b037c00, 0xb9410fe3, 0x1b037c00, 0xb94113e3, 0x1b037c00, 0xb94117e3, 0x1b037c00, 0x1b007c21, 0xb9411be0, 0x1b007d08, 0xb9411fe0, 0x1b007d08, 0xb94123e0, 0x1b007d08, 0xb94127e0, 0x1b007d08, 0xb9412be0, 0x1b007d08, 0xb9412fe0, 0x1b007d08, 0xb94133e0, 0x1b007d08, 0xb94137e0, 0x1b007d08, 0xb9413fe0, 0xb941bff7, 0xa94153f3, 0x1b0d7d08, 0xb9416fed, 0xa9425bf5, 0xa9446bf9, 0x1b007d08, 0xb94143e0, 0x1b087c21, 0x1b007ce7, 0xb94147e0, 0x1b007ce7, 0xb9414be0, 0x1b007ce7, 0xb9414fe0, 0x1b007ce7, 0xb94153e0, 0x1b007ce7, 0xb94157e0, 0x1b007ce7, 0xb9415be0, 0x1b007ce7, 0xb9415fe0, 0x1b007ce7, 0xb94163e0, 0x1b007ce7, 0xb94167e0, 0x1b007ce7, 0xb9416be0, 0x1b007c42, 0xb94173e0, 0x1b077c21, 0x1b0d7c42, 0xb94193ed, 0x1b007c42, 0xb94177e0, 0x1b007c42, 0xb9417be0, 0x1b007c42, 0xb9417fe0, 0x1b007c42, 0xb94183e0, 0x1b007c40, 0xb94187e2, 0x1b027c00, 0xb9418be2, 0x1b027c00, 0xb9418fe2, 0x1b027c00, 0xb94197e2, 0x1b007c20, 0x1b0f7cc1, 0x1b0d7c21, 0xb941a7ed, 0x1b027c21, 0xb9419be2, 0x1b027c21, 0xb9419fe2, 0xa94573fb, 0x1b027c21, 0xb941a3e2, 0x1b027c21, 0xb941abe2, 0x1b0d7c21, 0xb941bbed, 0x1b027c21, 0xb941afe2, 0x1b027c21, 0xb941b3e2, 0x1b027c21, 0xb941b7e2, 0x1b027c21, 0x1b017c01, 0x1b0e7ca0, 0x1b0d7c00, 0xb941c7ed, 0x1b177c00, 0xb941c3f7, 0x1b177c00, 0xb941cbf7, 0x1b0d7c00, 0xb941cfed, 0x1b177c00, 0xb941d3f7, 0x1b0d7c00, 0xb941d7ed, 0x1b177c00, 0xb941dbf7, 0x1b0d7c00, 0xb941dfed, 0x1b177c00, 0xa94363f7, 0xa8de7bfd, 0x1b0d7c00, 0x1b007c20, 0x14000000 }; + jit.SetPC(0x60); // at _start + env.ticks_left = 4; + CheckedRun([&]() { jit.Run(); }); + REQUIRE(jit.GetRegister(0) == 0); +} + +/* +Following C program: +extern int printf(const char*, ...); +int square(int num) { + return (num > 10) ? printf((void*)(num - 10)) : num * num; +} +*/ +TEST_CASE("Block branching (unpredictable)", "[a64][c]") { + A64TestEnv env; + A64::UserConfig conf{}; + conf.callbacks = &env; + //conf.very_verbose_debugging_output = true; + A64::Jit jit{conf}; + REQUIRE(conf.HasOptimization(OptimizationFlag::BlockLinking)); + oaknut::VectorCodeGenerator code{env.code_mem, nullptr}; + { + using namespace oaknut::util; + oaknut::Label lb0_2, lb_printf, lb_hlt; + code.ADD(W0, W0, 11); + code.CMP(W0, 11); + code.B(LT, lb0_2); + code.SUB(W0, W0, 10); + code.B(lb_printf); + code.l(lb0_2); + code.MUL(W0, W0, W0); + code.l(lb_hlt); + code.B(lb_hlt); + code.l(lb_printf); + code.RET(); + } + jit.SetPC(0); // at _start + env.ticks_left = env.code_mem.size(); + CheckedRun([&]() { jit.Run(); }); +} diff --git a/src/dynarmic/tests/A64/test_invalidation.cpp b/src/dynarmic/tests/A64/test_invalidation.cpp index cba47dd8ca..168043c1cb 100644 --- a/src/dynarmic/tests/A64/test_invalidation.cpp +++ b/src/dynarmic/tests/A64/test_invalidation.cpp @@ -27,38 +27,38 @@ TEST_CASE("ensure fast dispatch entry is cleared even when a block does not have jit.SetPC(100); env.ticks_left = 4; - jit.Run(); + CheckedRun([&]() { jit.Run(); }); REQUIRE(jit.GetRegister(0) == 42); jit.SetPC(100); env.ticks_left = 4; - jit.Run(); + CheckedRun([&]() { jit.Run(); }); REQUIRE(jit.GetRegister(0) == 42); jit.InvalidateCacheRange(108, 4); jit.SetPC(100); env.ticks_left = 4; - jit.Run(); + CheckedRun([&]() { jit.Run(); }); REQUIRE(jit.GetRegister(0) == 42); env.code_mem[2] = 0xd28008a0; // MOV X0, 69 jit.SetPC(100); env.ticks_left = 4; - jit.Run(); + CheckedRun([&]() { jit.Run(); }); REQUIRE(jit.GetRegister(0) == 42); jit.InvalidateCacheRange(108, 4); jit.SetPC(100); env.ticks_left = 4; - jit.Run(); + CheckedRun([&]() { jit.Run(); }); REQUIRE(jit.GetRegister(0) == 69); jit.SetPC(100); env.ticks_left = 4; - jit.Run(); + CheckedRun([&]() { jit.Run(); }); REQUIRE(jit.GetRegister(0) == 69); } @@ -77,37 +77,37 @@ TEST_CASE("ensure fast dispatch entry is cleared even when a block does not have jit.SetPC(0); env.ticks_left = 4; - jit.Run(); + CheckedRun([&]() { jit.Run(); }); REQUIRE(jit.GetRegister(0) == 42); jit.SetPC(0); env.ticks_left = 4; - jit.Run(); + CheckedRun([&]() { jit.Run(); }); REQUIRE(jit.GetRegister(0) == 42); jit.InvalidateCacheRange(8, 4); jit.SetPC(0); env.ticks_left = 4; - jit.Run(); + CheckedRun([&]() { jit.Run(); }); REQUIRE(jit.GetRegister(0) == 42); env.code_mem[2] = 0xd28008a0; // MOV X0, 69 jit.SetPC(0); env.ticks_left = 4; - jit.Run(); + CheckedRun([&]() { jit.Run(); }); REQUIRE(jit.GetRegister(0) == 42); jit.InvalidateCacheRange(8, 4); jit.SetPC(0); env.ticks_left = 4; - jit.Run(); + CheckedRun([&]() { jit.Run(); }); REQUIRE(jit.GetRegister(0) == 69); jit.SetPC(0); env.ticks_left = 4; - jit.Run(); + CheckedRun([&]() { jit.Run(); }); REQUIRE(jit.GetRegister(0) == 69); } diff --git a/src/dynarmic/tests/A64/testenv.h b/src/dynarmic/tests/A64/testenv.h index 2c5a500f75..31e338b138 100644 --- a/src/dynarmic/tests/A64/testenv.h +++ b/src/dynarmic/tests/A64/testenv.h @@ -8,13 +8,11 @@ #pragma once -#include -#include - +#include #include "dynarmic/common/assert.h" #include "dynarmic/common/common_types.h" - #include "dynarmic/interface/A64/a64.h" +#include "../native/testenv.h" using Vector = Dynarmic::A64::Vector; @@ -26,7 +24,7 @@ public: u64 code_mem_start_address = 0; std::vector code_mem; - std::map modified_memory; + std::unordered_map modified_memory; std::vector interrupts; bool IsInCodeMem(u64 vaddr) const { @@ -133,9 +131,9 @@ class A64FastmemTestEnv final : public Dynarmic::A64::UserCallbacks { public: u64 ticks_left = 0; char* backing_memory = nullptr; + bool ignore_invalid_insn = false; - explicit A64FastmemTestEnv(char* addr) - : backing_memory(addr) {} + explicit A64FastmemTestEnv(char* addr) : backing_memory(addr) {} template T read(u64 vaddr) { @@ -205,7 +203,7 @@ public: return true; } - void InterpreterFallback(u64 pc, size_t num_instructions) override { ASSERT_MSG(false, "InterpreterFallback({:016x}, {})", pc, num_instructions); } + void InterpreterFallback(u64 pc, size_t num_instructions) override { ASSERT_MSG(ignore_invalid_insn, "InterpreterFallback({:016x}, {})", pc, num_instructions); } void CallSVC(std::uint32_t swi) override { ASSERT_MSG(false, "CallSVC({})", swi); } diff --git a/src/dynarmic/tests/A64/verify_unicorn.cpp b/src/dynarmic/tests/A64/verify_unicorn.cpp index 5ffe4f15b0..0c0ccc1609 100644 --- a/src/dynarmic/tests/A64/verify_unicorn.cpp +++ b/src/dynarmic/tests/A64/verify_unicorn.cpp @@ -13,7 +13,7 @@ using namespace Dynarmic; -TEST_CASE("Unicorn: Sanity test", "[a64]") { +TEST_CASE("Unicorn: Sanity test", "[a64][unicorn]") { A64TestEnv env; env.code_mem.emplace_back(0x8b020020); // ADD X0, X1, X2 @@ -39,7 +39,7 @@ TEST_CASE("Unicorn: Sanity test", "[a64]") { REQUIRE(unicorn.GetPC() == 4); } -TEST_CASE("Unicorn: Ensure 0xFFFF'FFFF'FFFF'FFFF is readable", "[a64]") { +TEST_CASE("Unicorn: Ensure 0xFFFF'FFFF'FFFF'FFFF is readable", "[a64][unicorn]") { A64TestEnv env; env.code_mem.emplace_back(0x385fed99); // LDRB W25, [X12, #0xfffffffffffffffe]! @@ -59,7 +59,7 @@ TEST_CASE("Unicorn: Ensure 0xFFFF'FFFF'FFFF'FFFF is readable", "[a64]") { REQUIRE(unicorn.GetPC() == 4); } -TEST_CASE("Unicorn: Ensure is able to read across page boundaries", "[a64]") { +TEST_CASE("Unicorn: Ensure is able to read across page boundaries", "[a64][unicorn]") { A64TestEnv env; env.code_mem.emplace_back(0xb85f93d9); // LDUR W25, [X30, #0xfffffffffffffff9] diff --git a/src/dynarmic/tests/CMakeLists.txt b/src/dynarmic/tests/CMakeLists.txt index b56f884c38..85d86c7966 100644 --- a/src/dynarmic/tests/CMakeLists.txt +++ b/src/dynarmic/tests/CMakeLists.txt @@ -29,6 +29,7 @@ if ("A64" IN_LIST DYNARMIC_FRONTENDS) A64/fp_min_max.cpp A64/misaligned_page_table.cpp A64/test_invalidation.cpp + A64/real_world.cpp A64/testenv.h ) endif() @@ -66,11 +67,14 @@ endif() if ("x86_64" IN_LIST ARCHITECTURE) target_link_libraries(dynarmic_tests PRIVATE xbyak::xbyak) - target_architecture_specific_sources(dynarmic_tests "x86_64" x64_cpu_info.cpp ) + target_architecture_specific_sources(dynarmic_tests "x86_64" + native/preserve_xmm.cpp + ) + if (NOT MSVC AND NOT DYNARMIC_MULTIARCH_BUILD) target_sources(dynarmic_tests PRIVATE rsqrt_test.cpp @@ -129,4 +133,6 @@ target_include_directories(dynarmic_tests PRIVATE . ../src) target_compile_options(dynarmic_tests PRIVATE ${DYNARMIC_CXX_FLAGS}) target_compile_definitions(dynarmic_tests PRIVATE FMT_USE_USER_DEFINED_LITERALS=1) +target_compile_options(dynarmic_tests PRIVATE -mavx2) + add_test(dynarmic_tests dynarmic_tests --durations yes) diff --git a/src/dynarmic/tests/native/preserve_xmm.cpp b/src/dynarmic/tests/native/preserve_xmm.cpp new file mode 100644 index 0000000000..0f69697b7a --- /dev/null +++ b/src/dynarmic/tests/native/preserve_xmm.cpp @@ -0,0 +1,64 @@ +// SPDX-FileCopyrightText: Copyright 2025 Eden Emulator Project +// SPDX-License-Identifier: GPL-3.0-or-later + +#include +#include +#include + +#include "../A64/testenv.h" +#include "dynarmic/common/fp/fpsr.h" +#include "dynarmic/interface/exclusive_monitor.h" + +using namespace Dynarmic; +using namespace oaknut::util; + +TEST_CASE("X86: Preserve XMM regs", "[x86]") { + A64TestEnv env; + A64::UserConfig jit_user_config{}; + jit_user_config.callbacks = &env; + A64::Jit jit{jit_user_config}; + + oaknut::VectorCodeGenerator code{env.code_mem, nullptr}; + code.SMINP(V2.S2(), V0.S2(), V1.S2()); + code.UMINP(V3.S2(), V0.S2(), V1.S2()); + code.SMINP(V4.S4(), V0.S4(), V1.S4()); + code.UMINP(V5.S4(), V0.S4(), V1.S4()); + code.SMAXP(V6.S2(), V0.S2(), V1.S2()); + code.UMAXP(V7.S2(), V0.S2(), V1.S2()); + code.SMAXP(V8.S4(), V0.S4(), V1.S4()); + code.UMAXP(V9.S4(), V0.S4(), V1.S4()); + + constexpr std::array vectors = { + // initial input vectors [0-1] + Vector{0x00000003'00000002, 0xF1234567'01234567}, + Vector{0x80000000'7FFFFFFF, 0x76543210'76543209}, + // expected output vectors [2-9] + Vector{0x80000000'00000002, 0}, + Vector{0x7FFFFFFF'00000002, 0}, + Vector{0xF1234567'00000002, 0x76543209'80000000}, + Vector{0x01234567'00000002, 0x76543209'7FFFFFFF}, + Vector{0x7FFFFFFF'00000003, 0}, + Vector{0x80000000'00000003, 0}, + Vector{0x01234567'00000003, 0x76543210'7FFFFFFF}, + Vector{0xF1234567'00000003, 0x76543210'80000000}, + // input vectors with elements swapped pairwise [10-11] + Vector{0x00000002'00000003, 0x01234567'F1234567}, + Vector{0x7FFFFFFF'80000000, 0x76543209'76543210}, + }; + + jit.SetPC(0); + jit.SetVector(0, vectors[0]); + jit.SetVector(1, vectors[1]); + + env.ticks_left = env.code_mem.size(); + CheckedRun([&]() { jit.Run(); }); + + CHECK(jit.GetVector(2) == vectors[2]); + CHECK(jit.GetVector(3) == vectors[3]); + CHECK(jit.GetVector(4) == vectors[4]); + CHECK(jit.GetVector(5) == vectors[5]); + CHECK(jit.GetVector(6) == vectors[6]); + CHECK(jit.GetVector(7) == vectors[7]); + CHECK(jit.GetVector(8) == vectors[8]); + CHECK(jit.GetVector(9) == vectors[9]); +} diff --git a/src/dynarmic/tests/native/testenv.h b/src/dynarmic/tests/native/testenv.h new file mode 100644 index 0000000000..7a3d14eea0 --- /dev/null +++ b/src/dynarmic/tests/native/testenv.h @@ -0,0 +1,50 @@ +#pragma once + +#include +#ifdef __AVX__ +#include +#endif +template +void CheckedRun(F&& fn) { +#ifdef __AVX__ + __m256i xmm0 = _mm256_set_epi32(0, 0, 0, 0, 0, 0, 0, 0); + __m256i xmm1 = _mm256_set_epi32(1, 1, 0, 0, 0, 0, 0, 1); + __m256i xmm2 = _mm256_set_epi32(2, 2, 0, 0, 0, 0, 0, 2); + __m256i xmm3 = _mm256_set_epi32(3, 3, 0, 0, 0, 0, 0, 3); + __m256i xmm4 = _mm256_set_epi32(4, 4, 0, 0, 0, 0, 0, 4); + __m256i xmm5 = _mm256_set_epi32(4, 4, 0, 0, 0, 0, 0, 5); + __m256i xmm6 = _mm256_set_epi32(4, 4, 0, 0, 0, 0, 0, 6); + __m256i xmm7 = _mm256_set_epi32(4, 4, 0, 0, 0, 0, 0, 7); + __m256i xmm8 = _mm256_set_epi32(4, 4, 0, 0, 0, 0, 0, 8); + __m256i xmm9 = _mm256_set_epi32(4, 4, 0, 0, 0, 0, 0, 9); + __m256i xmm10 = _mm256_set_epi32(4, 4, 0, 0, 0, 0, 0, 10); + __m256i xmm11 = _mm256_set_epi32(4, 4, 0, 0, 0, 0, 0, 11); + asm volatile("" + : "+x"(xmm0), "+x"(xmm1), "+x"(xmm2), "+x"(xmm3) + , "+x"(xmm4), "+x"(xmm5), "+x"(xmm6), "+x"(xmm7) + , "+x"(xmm8), "+x"(xmm9), "+x"(xmm10), "+x"(xmm11) + : + ); + fn(); + asm volatile("" + : "+x"(xmm0), "+x"(xmm1), "+x"(xmm2), "+x"(xmm3) + , "+x"(xmm4), "+x"(xmm5), "+x"(xmm6), "+x"(xmm7) + , "+x"(xmm8), "+x"(xmm9), "+x"(xmm10), "+x"(xmm11) + : + ); + CHECK(std::bit_cast(xmm0[0]) == 0); + CHECK(std::bit_cast(xmm1[0]) == 1); + CHECK(std::bit_cast(xmm2[0]) == 2); + CHECK(std::bit_cast(xmm3[0]) == 3); + CHECK(std::bit_cast(xmm4[0]) == 4); + CHECK(std::bit_cast(xmm5[0]) == 5); + CHECK(std::bit_cast(xmm6[0]) == 6); + CHECK(std::bit_cast(xmm7[0]) == 7); + CHECK(std::bit_cast(xmm8[0]) == 8); + CHECK(std::bit_cast(xmm9[0]) == 9); + CHECK(std::bit_cast(xmm10[0]) == 10); + CHECK(std::bit_cast(xmm11[0]) == 11); +#else + fn(); +#endif +} diff --git a/src/dynarmic/tests/unicorn_emu/a64_unicorn.cpp b/src/dynarmic/tests/unicorn_emu/a64_unicorn.cpp index 42b72bdb91..aa66ff7f9a 100644 --- a/src/dynarmic/tests/unicorn_emu/a64_unicorn.cpp +++ b/src/dynarmic/tests/unicorn_emu/a64_unicorn.cpp @@ -173,7 +173,7 @@ void A64Unicorn::InterruptHook(uc_engine* uc, u32 int_number, void* user_data) { auto* this_ = static_cast(user_data); u32 esr; - CHECKED(uc_reg_read(uc, UC_ARM64_REG_ESR, &esr)); + //CHECKED(uc_reg_read(uc, UC_ARM64_REG_ESR_EL0, &esr)); auto ec = esr >> 26; auto iss = esr & 0xFFFFFF; diff --git a/src/tests/video_core/memory_tracker.cpp b/src/tests/video_core/memory_tracker.cpp index da7e88ea03..b6fdefe0fc 100644 --- a/src/tests/video_core/memory_tracker.cpp +++ b/src/tests/video_core/memory_tracker.cpp @@ -28,11 +28,10 @@ public: for (u64 page = page_start; page < page_end; ++page) { int& value = page_table[page]; value += delta; - if (value < 0) { - throw std::logic_error{"negative page"}; - } if (value == 0) { page_table.erase(page); + } else if (value < 0) { + throw std::logic_error{"negative page"}; } } } From 3cb8e6111a7b2c7cf218fe8afe212857cb5a00d5 Mon Sep 17 00:00:00 2001 From: lizzie Date: Wed, 27 Aug 2025 12:10:53 +0200 Subject: [PATCH 18/39] [jit] Increase x86_64 default code size to full 2GiB hugepage (#318) Abuses the existence of transparent huge pages on Unix. 4*2 = 8GiB virtual memory used total by JIT. May reduce native host TLB trees. Signed-off-by: lizzie Reviewed-on: https://git.eden-emu.dev/eden-emu/eden/pulls/318 Reviewed-by: Shinmegumi Co-authored-by: lizzie Co-committed-by: lizzie --- src/core/arm/dynarmic/arm_dynarmic_32.cpp | 2 +- src/core/arm/dynarmic/arm_dynarmic_64.cpp | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/src/core/arm/dynarmic/arm_dynarmic_32.cpp b/src/core/arm/dynarmic/arm_dynarmic_32.cpp index 1731ef1aec..db159388bf 100644 --- a/src/core/arm/dynarmic/arm_dynarmic_32.cpp +++ b/src/core/arm/dynarmic/arm_dynarmic_32.cpp @@ -215,7 +215,7 @@ std::shared_ptr ArmDynarmic32::MakeJit(Common::PageTable* pa #ifdef ARCHITECTURE_arm64 config.code_cache_size = std::uint32_t(128_MiB); #else - config.code_cache_size = std::uint32_t(512_MiB); + config.code_cache_size = std::uint32_t(2_GiB); #endif // Allow memory fault handling to work diff --git a/src/core/arm/dynarmic/arm_dynarmic_64.cpp b/src/core/arm/dynarmic/arm_dynarmic_64.cpp index 9674e88d9d..dcff0ddf3f 100644 --- a/src/core/arm/dynarmic/arm_dynarmic_64.cpp +++ b/src/core/arm/dynarmic/arm_dynarmic_64.cpp @@ -273,7 +273,7 @@ std::shared_ptr ArmDynarmic64::MakeJit(Common::PageTable* pa #ifdef ARCHITECTURE_arm64 config.code_cache_size = std::uint32_t(128_MiB); #else - config.code_cache_size = std::uint32_t(512_MiB); + config.code_cache_size = std::uint32_t(2_GiB); #endif // Allow memory fault handling to work From 22847ec78a4369497855672db71977ead871c49d Mon Sep 17 00:00:00 2001 From: lizzie Date: Wed, 27 Aug 2025 12:12:32 +0200 Subject: [PATCH 19/39] [jit] Disable fastmem (by default) on FreeBSD, Solaris and OpenBSD due to subpar timings of SIGSEGV (#319) Reviewed-on: https://git.eden-emu.dev/eden-emu/eden/pulls/319 Reviewed-by: Shinmegumi Co-authored-by: lizzie Co-committed-by: lizzie --- src/core/arm/dynarmic/arm_dynarmic_32.cpp | 20 +++++++++++++------- src/core/arm/dynarmic/arm_dynarmic_64.cpp | 20 +++++++++++++------- 2 files changed, 26 insertions(+), 14 deletions(-) diff --git a/src/core/arm/dynarmic/arm_dynarmic_32.cpp b/src/core/arm/dynarmic/arm_dynarmic_32.cpp index db159388bf..798623a5fa 100644 --- a/src/core/arm/dynarmic/arm_dynarmic_32.cpp +++ b/src/core/arm/dynarmic/arm_dynarmic_32.cpp @@ -269,8 +269,13 @@ std::shared_ptr ArmDynarmic32::MakeJit(Common::PageTable* pa config.check_halt_on_memory_access = true; } } else { +#if defined(__FreeBSD__) || defined(__OpenBSD__) || defined(__sun__) + config.fastmem_pointer = std::nullopt; + config.fastmem_exclusive_access = false; +#endif + switch (Settings::values.cpu_accuracy.GetValue()) { // Unsafe optimizations - if (Settings::values.cpu_accuracy.GetValue() == Settings::CpuAccuracy::Unsafe) { + case Settings::CpuAccuracy::Unsafe: config.unsafe_optimizations = true; if (Settings::values.cpuopt_unsafe_unfuse_fma) { config.optimizations |= Dynarmic::OptimizationFlag::Unsafe_UnfuseFMA; @@ -287,21 +292,22 @@ std::shared_ptr ArmDynarmic32::MakeJit(Common::PageTable* pa if (Settings::values.cpuopt_unsafe_ignore_global_monitor) { config.optimizations |= Dynarmic::OptimizationFlag::Unsafe_IgnoreGlobalMonitor; } - } - + break; // Curated optimizations - if (Settings::values.cpu_accuracy.GetValue() == Settings::CpuAccuracy::Auto) { + case Settings::CpuAccuracy::Auto: config.unsafe_optimizations = true; config.optimizations |= Dynarmic::OptimizationFlag::Unsafe_UnfuseFMA; config.optimizations |= Dynarmic::OptimizationFlag::Unsafe_IgnoreStandardFPCRValue; config.optimizations |= Dynarmic::OptimizationFlag::Unsafe_InaccurateNaN; config.optimizations |= Dynarmic::OptimizationFlag::Unsafe_IgnoreGlobalMonitor; - } - + break; // Paranoia mode for debugging optimizations - if (Settings::values.cpu_accuracy.GetValue() == Settings::CpuAccuracy::Paranoid) { + case Settings::CpuAccuracy::Paranoid: config.unsafe_optimizations = false; config.optimizations = Dynarmic::no_optimizations; + break; + default: + break; } } diff --git a/src/core/arm/dynarmic/arm_dynarmic_64.cpp b/src/core/arm/dynarmic/arm_dynarmic_64.cpp index dcff0ddf3f..7b59ce2633 100644 --- a/src/core/arm/dynarmic/arm_dynarmic_64.cpp +++ b/src/core/arm/dynarmic/arm_dynarmic_64.cpp @@ -327,8 +327,13 @@ std::shared_ptr ArmDynarmic64::MakeJit(Common::PageTable* pa config.check_halt_on_memory_access = true; } } else { +#if defined(__FreeBSD__) || defined(__OpenBSD__) || defined(__sun__) + config.fastmem_pointer = std::nullopt; + config.fastmem_exclusive_access = false; +#endif // Unsafe optimizations - if (Settings::values.cpu_accuracy.GetValue() == Settings::CpuAccuracy::Unsafe) { + switch(Settings::values.cpu_accuracy.GetValue()) { + case Settings::CpuAccuracy::Unsafe: config.unsafe_optimizations = true; if (Settings::values.cpuopt_unsafe_unfuse_fma) { config.optimizations |= Dynarmic::OptimizationFlag::Unsafe_UnfuseFMA; @@ -345,20 +350,21 @@ std::shared_ptr ArmDynarmic64::MakeJit(Common::PageTable* pa if (Settings::values.cpuopt_unsafe_ignore_global_monitor) { config.optimizations |= Dynarmic::OptimizationFlag::Unsafe_IgnoreGlobalMonitor; } - } - + break; // Curated optimizations - if (Settings::values.cpu_accuracy.GetValue() == Settings::CpuAccuracy::Auto) { + case Settings::CpuAccuracy::Auto: config.unsafe_optimizations = true; config.optimizations |= Dynarmic::OptimizationFlag::Unsafe_UnfuseFMA; config.fastmem_address_space_bits = 64; config.optimizations |= Dynarmic::OptimizationFlag::Unsafe_IgnoreGlobalMonitor; - } - + break; // Paranoia mode for debugging optimizations - if (Settings::values.cpu_accuracy.GetValue() == Settings::CpuAccuracy::Paranoid) { + case Settings::CpuAccuracy::Paranoid: config.unsafe_optimizations = false; config.optimizations = Dynarmic::no_optimizations; + break; + default: + break; } } From eb80a30c42e956ff26076575b20642e330217b2d Mon Sep 17 00:00:00 2001 From: Shinmegumi Date: Wed, 27 Aug 2025 15:12:16 +0200 Subject: [PATCH 20/39] revert 22847ec78a4369497855672db71977ead871c49d (#331) revert [jit] Disable fastmem (by default) on FreeBSD, Solaris and OpenBSD due to subpar timings of SIGSEGV (#319) According to MaranBR, this should have never been merged and should have been closed instead as they iterated on it in 324. Reviewed-on: https://git.eden-emu.dev/eden-emu/eden/pulls/319 Reviewed-by: Shinmegumi Co-authored-by: lizzie Co-committed-by: lizzie Reviewed-on: https://git.eden-emu.dev/eden-emu/eden/pulls/331 Co-authored-by: Shinmegumi Co-committed-by: Shinmegumi --- src/core/arm/dynarmic/arm_dynarmic_32.cpp | 20 +++++++------------- src/core/arm/dynarmic/arm_dynarmic_64.cpp | 20 +++++++------------- 2 files changed, 14 insertions(+), 26 deletions(-) diff --git a/src/core/arm/dynarmic/arm_dynarmic_32.cpp b/src/core/arm/dynarmic/arm_dynarmic_32.cpp index 798623a5fa..db159388bf 100644 --- a/src/core/arm/dynarmic/arm_dynarmic_32.cpp +++ b/src/core/arm/dynarmic/arm_dynarmic_32.cpp @@ -269,13 +269,8 @@ std::shared_ptr ArmDynarmic32::MakeJit(Common::PageTable* pa config.check_halt_on_memory_access = true; } } else { -#if defined(__FreeBSD__) || defined(__OpenBSD__) || defined(__sun__) - config.fastmem_pointer = std::nullopt; - config.fastmem_exclusive_access = false; -#endif - switch (Settings::values.cpu_accuracy.GetValue()) { // Unsafe optimizations - case Settings::CpuAccuracy::Unsafe: + if (Settings::values.cpu_accuracy.GetValue() == Settings::CpuAccuracy::Unsafe) { config.unsafe_optimizations = true; if (Settings::values.cpuopt_unsafe_unfuse_fma) { config.optimizations |= Dynarmic::OptimizationFlag::Unsafe_UnfuseFMA; @@ -292,22 +287,21 @@ std::shared_ptr ArmDynarmic32::MakeJit(Common::PageTable* pa if (Settings::values.cpuopt_unsafe_ignore_global_monitor) { config.optimizations |= Dynarmic::OptimizationFlag::Unsafe_IgnoreGlobalMonitor; } - break; + } + // Curated optimizations - case Settings::CpuAccuracy::Auto: + if (Settings::values.cpu_accuracy.GetValue() == Settings::CpuAccuracy::Auto) { config.unsafe_optimizations = true; config.optimizations |= Dynarmic::OptimizationFlag::Unsafe_UnfuseFMA; config.optimizations |= Dynarmic::OptimizationFlag::Unsafe_IgnoreStandardFPCRValue; config.optimizations |= Dynarmic::OptimizationFlag::Unsafe_InaccurateNaN; config.optimizations |= Dynarmic::OptimizationFlag::Unsafe_IgnoreGlobalMonitor; - break; + } + // Paranoia mode for debugging optimizations - case Settings::CpuAccuracy::Paranoid: + if (Settings::values.cpu_accuracy.GetValue() == Settings::CpuAccuracy::Paranoid) { config.unsafe_optimizations = false; config.optimizations = Dynarmic::no_optimizations; - break; - default: - break; } } diff --git a/src/core/arm/dynarmic/arm_dynarmic_64.cpp b/src/core/arm/dynarmic/arm_dynarmic_64.cpp index 7b59ce2633..dcff0ddf3f 100644 --- a/src/core/arm/dynarmic/arm_dynarmic_64.cpp +++ b/src/core/arm/dynarmic/arm_dynarmic_64.cpp @@ -327,13 +327,8 @@ std::shared_ptr ArmDynarmic64::MakeJit(Common::PageTable* pa config.check_halt_on_memory_access = true; } } else { -#if defined(__FreeBSD__) || defined(__OpenBSD__) || defined(__sun__) - config.fastmem_pointer = std::nullopt; - config.fastmem_exclusive_access = false; -#endif // Unsafe optimizations - switch(Settings::values.cpu_accuracy.GetValue()) { - case Settings::CpuAccuracy::Unsafe: + if (Settings::values.cpu_accuracy.GetValue() == Settings::CpuAccuracy::Unsafe) { config.unsafe_optimizations = true; if (Settings::values.cpuopt_unsafe_unfuse_fma) { config.optimizations |= Dynarmic::OptimizationFlag::Unsafe_UnfuseFMA; @@ -350,21 +345,20 @@ std::shared_ptr ArmDynarmic64::MakeJit(Common::PageTable* pa if (Settings::values.cpuopt_unsafe_ignore_global_monitor) { config.optimizations |= Dynarmic::OptimizationFlag::Unsafe_IgnoreGlobalMonitor; } - break; + } + // Curated optimizations - case Settings::CpuAccuracy::Auto: + if (Settings::values.cpu_accuracy.GetValue() == Settings::CpuAccuracy::Auto) { config.unsafe_optimizations = true; config.optimizations |= Dynarmic::OptimizationFlag::Unsafe_UnfuseFMA; config.fastmem_address_space_bits = 64; config.optimizations |= Dynarmic::OptimizationFlag::Unsafe_IgnoreGlobalMonitor; - break; + } + // Paranoia mode for debugging optimizations - case Settings::CpuAccuracy::Paranoid: + if (Settings::values.cpu_accuracy.GetValue() == Settings::CpuAccuracy::Paranoid) { config.unsafe_optimizations = false; config.optimizations = Dynarmic::no_optimizations; - break; - default: - break; } } From 9fae048a5a2c63777c080f0c432d31997de7478a Mon Sep 17 00:00:00 2001 From: CamilleLaVey Date: Wed, 27 Aug 2025 21:28:23 +0200 Subject: [PATCH 21/39] revert [jit] Increase x86_64 default code size to full 2GiB hugepage (#318) (#337) revert [jit] Increase x86_64 default code size to full 2GiB hugepage (#318) Abuses the existence of transparent huge pages on Unix. 4*2 = 8GiB virtual memory used total by JIT. May reduce native host TLB trees. -------------- WIP: Wasn't meant to be merged, it's going to be refined to be added later when more data/ testing have been made about this approach. Signed-off-by: lizzie Reviewed-on: https://git.eden-emu.dev/eden-emu/eden/pulls/318 Reviewed-by: Shinmegumi Co-authored-by: lizzie Co-committed-by: lizzie Reviewed-on: https://git.eden-emu.dev/eden-emu/eden/pulls/337 Co-authored-by: CamilleLaVey Co-committed-by: CamilleLaVey --- src/core/arm/dynarmic/arm_dynarmic_32.cpp | 2 +- src/core/arm/dynarmic/arm_dynarmic_64.cpp | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/src/core/arm/dynarmic/arm_dynarmic_32.cpp b/src/core/arm/dynarmic/arm_dynarmic_32.cpp index db159388bf..1731ef1aec 100644 --- a/src/core/arm/dynarmic/arm_dynarmic_32.cpp +++ b/src/core/arm/dynarmic/arm_dynarmic_32.cpp @@ -215,7 +215,7 @@ std::shared_ptr ArmDynarmic32::MakeJit(Common::PageTable* pa #ifdef ARCHITECTURE_arm64 config.code_cache_size = std::uint32_t(128_MiB); #else - config.code_cache_size = std::uint32_t(2_GiB); + config.code_cache_size = std::uint32_t(512_MiB); #endif // Allow memory fault handling to work diff --git a/src/core/arm/dynarmic/arm_dynarmic_64.cpp b/src/core/arm/dynarmic/arm_dynarmic_64.cpp index dcff0ddf3f..9674e88d9d 100644 --- a/src/core/arm/dynarmic/arm_dynarmic_64.cpp +++ b/src/core/arm/dynarmic/arm_dynarmic_64.cpp @@ -273,7 +273,7 @@ std::shared_ptr ArmDynarmic64::MakeJit(Common::PageTable* pa #ifdef ARCHITECTURE_arm64 config.code_cache_size = std::uint32_t(128_MiB); #else - config.code_cache_size = std::uint32_t(2_GiB); + config.code_cache_size = std::uint32_t(512_MiB); #endif // Allow memory fault handling to work From 37375220e8dafd35e35f0eabfa7771e8ef61143a Mon Sep 17 00:00:00 2001 From: JPikachu Date: Wed, 27 Aug 2025 22:19:17 +0200 Subject: [PATCH 22/39] [VK] Refine VRAM allocation strategy for improved stability and performance (#334) These adjustments enhance memory management, While increasing shader performance across all GPU types, including iGPUs. This commit fixes a bug in Super Mario Odyssey where loading into a new area or pausing the game Would cause the whole game to slow down (Most noticeable on RDNA 2 GPUs like the Steam Deck) Thank you to all of our testers for helping eliminate this bug, And thank you to Camille for the instructions/commit and to Zephyron for addressing this in Citron. Co-authored-by: JPikachu Reviewed-on: https://git.eden-emu.dev/eden-emu/eden/pulls/334 Reviewed-by: CamilleLaVey Co-authored-by: JPikachu Co-committed-by: JPikachu --- src/video_core/vulkan_common/vulkan_device.cpp | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/src/video_core/vulkan_common/vulkan_device.cpp b/src/video_core/vulkan_common/vulkan_device.cpp index 6bd6eab009..cfa88850a0 100644 --- a/src/video_core/vulkan_common/vulkan_device.cpp +++ b/src/video_core/vulkan_common/vulkan_device.cpp @@ -1378,13 +1378,13 @@ void Device::CollectPhysicalMemoryInfo() { device_access_memory += mem_properties.memoryHeaps[element].size; } if (!is_integrated) { - const u64 reserve_memory = std::min(device_access_memory / 8, 1_GiB); + const u64 reserve_memory = std::min(device_access_memory / 4, 2_GiB); device_access_memory -= reserve_memory; if (Settings::values.vram_usage_mode.GetValue() != Settings::VramUsageMode::Aggressive) { // Account for resolution scaling in memory limits - const size_t normal_memory = 6_GiB; - const size_t scaler_memory = 1_GiB * Settings::values.resolution_info.ScaleUp(1); + const size_t normal_memory = 8_GiB; + const size_t scaler_memory = 2_GiB * Settings::values.resolution_info.ScaleUp(1); device_access_memory = std::min(device_access_memory, normal_memory + scaler_memory); } @@ -1393,7 +1393,7 @@ void Device::CollectPhysicalMemoryInfo() { } const s64 available_memory = static_cast(device_access_memory - device_initial_usage); device_access_memory = static_cast(std::max( - std::min(available_memory - 8_GiB, 4_GiB), std::min(local_memory, 4_GiB))); + std::min(available_memory - 4_GiB, 6_GiB), std::min(local_memory, 6_GiB))); } void Device::CollectToolingInfo() { From dae0d7bec678253bd5ee5d10690bec5ffbfab024 Mon Sep 17 00:00:00 2001 From: wildcard Date: Wed, 27 Aug 2025 22:20:02 +0200 Subject: [PATCH 23/39] [VK] Very conservative and spec-compliant alignment (#335) spec-compliant alignment: Implement spec-compliant alignment for non-coherent memory and buffer-image granularity revert oom handling Reviewed-on: https://git.eden-emu.dev/eden-emu/eden/pulls/335 Reviewed-by: CamilleLaVey Co-authored-by: wildcard Co-committed-by: wildcard --- .../vulkan_common/vulkan_memory_allocator.cpp | 111 +++--------------- 1 file changed, 16 insertions(+), 95 deletions(-) diff --git a/src/video_core/vulkan_common/vulkan_memory_allocator.cpp b/src/video_core/vulkan_common/vulkan_memory_allocator.cpp index 4c92d4bfa0..2e37615f99 100644 --- a/src/video_core/vulkan_common/vulkan_memory_allocator.cpp +++ b/src/video_core/vulkan_common/vulkan_memory_allocator.cpp @@ -143,9 +143,6 @@ public: return (flags & property_flags) == flags && (type_mask & shifted_memory_type) != 0; } - [[nodiscard]] bool IsEmpty() const noexcept { - return commits.empty(); - } private: [[nodiscard]] static constexpr u32 ShiftType(u32 type) { @@ -287,107 +284,31 @@ vk::Buffer MemoryAllocator::CreateBuffer(const VkBufferCreateInfo& ci, MemoryUsa } MemoryCommit MemoryAllocator::Commit(const VkMemoryRequirements& requirements, MemoryUsage usage) { - // Find the fastest memory flags we can afford with the current requirements - const u32 type_mask = requirements.memoryTypeBits; - const VkMemoryPropertyFlags usage_flags = MemoryUsagePropertyFlags(usage); - const VkMemoryPropertyFlags flags = MemoryPropertyFlags(type_mask, usage_flags); - if (std::optional commit = TryCommit(requirements, flags)) { - return std::move(*commit); - } - - // Commit has failed, try progressive fallback strategy - u64 chunk_size = AllocationChunkSize(requirements.size); - const u64 minimum_size = std::max(requirements.size, 4ULL << 20); // 4MB minimum - - // try 1: Try allocating with original chunk size - if (TryAllocMemory(flags, type_mask, chunk_size)) { + // Find the fastest memory flags we can afford with the current requirements + const u32 type_mask = requirements.memoryTypeBits; + const VkMemoryPropertyFlags usage_flags = MemoryUsagePropertyFlags(usage); + const VkMemoryPropertyFlags flags = MemoryPropertyFlags(type_mask, usage_flags); + if (std::optional commit = TryCommit(requirements, flags)) { + return std::move(*commit); + } + // Commit has failed, allocate more memory. + const u64 chunk_size = AllocationChunkSize(requirements.size); + if (!TryAllocMemory(flags, type_mask, chunk_size)) { + // TODO(Rodrigo): Handle out of memory situations in some way like flushing to guest memory. + throw vk::Exception(VK_ERROR_OUT_OF_DEVICE_MEMORY); + } + // Commit again, this time it won't fail since there's a fresh allocation above. + // If it does, there's a bug. return TryCommit(requirements, flags).value(); } - // try 2: Clean up empty allocations and try again - bool cleaned_up = false; - for (auto it = allocations.begin(); it != allocations.end();) { - if ((*it)->IsEmpty()) { - it = allocations.erase(it); - cleaned_up = true; - } else { - ++it; - } - } - - if (cleaned_up && TryAllocMemory(flags, type_mask, chunk_size)) { - LOG_INFO(Render_Vulkan, "Memory allocation succeeded after cleanup"); - return TryCommit(requirements, flags).value(); - } - - // try 3: Progressive size reduction with cleanup between attempts - while (chunk_size > minimum_size) { - chunk_size >>= 1; // Halve the chunk size - chunk_size = std::max(chunk_size, minimum_size); - - if (TryAllocMemory(flags, type_mask, chunk_size)) { - LOG_WARNING(Render_Vulkan, "Memory allocation succeeded with reduced chunk size: {} MB", - chunk_size >> 20); - return TryCommit(requirements, flags).value(); - } - - // Clean up again between size reduction attempts - for (auto it = allocations.begin(); it != allocations.end();) { - if ((*it)->IsEmpty()) { - it = allocations.erase(it); - } else { - ++it; - } - } - } - - // try 4: Try minimum size allocation - if (chunk_size <= minimum_size && TryAllocMemory(flags, type_mask, minimum_size)) { - LOG_WARNING(Render_Vulkan, "Memory allocation succeeded with minimum size: {} MB", - minimum_size >> 20); - return TryCommit(requirements, flags).value(); - } - // try 5: Fallback to non-device-local memory if original was device-local - if (flags & VK_MEMORY_PROPERTY_DEVICE_LOCAL_BIT) { - const VkMemoryPropertyFlags fallback_flags = flags & ~VK_MEMORY_PROPERTY_DEVICE_LOCAL_BIT; - - // Try with original chunk size first - u64 fallback_chunk_size = AllocationChunkSize(requirements.size); - if (TryAllocMemory(fallback_flags, type_mask, fallback_chunk_size)) { - if (auto commit = TryCommit(requirements, fallback_flags)) { - LOG_WARNING(Render_Vulkan, "Falling back to non-device-local memory due to OOM"); - return std::move(*commit); - } - } - - // Progressive size reduction for non-device-local memory - while (fallback_chunk_size > minimum_size) { - fallback_chunk_size >>= 1; - fallback_chunk_size = std::max(fallback_chunk_size, minimum_size); - - if (TryAllocMemory(fallback_flags, type_mask, fallback_chunk_size)) { - if (auto commit = TryCommit(requirements, fallback_flags)) { - LOG_WARNING(Render_Vulkan, - "Falling back to non-device-local memory with reduced size: {} MB", - fallback_chunk_size >> 20); - return std::move(*commit); - } - } - } - } - - - LOG_CRITICAL(Render_Vulkan, "Vulkan memory allocation failed - exhausted all strategies"); - throw vk::Exception(VK_ERROR_OUT_OF_DEVICE_MEMORY); -} - bool MemoryAllocator::TryAllocMemory(VkMemoryPropertyFlags flags, u32 type_mask, u64 size) { const auto type_opt = FindType(flags, type_mask); if (!type_opt) { return false; } - // Adreno requires 4KB alignment(subject to review) + // Adreno stands firm const u64 aligned_size = (device.GetDriverID() == VK_DRIVER_ID_QUALCOMM_PROPRIETARY) ? Common::AlignUp(size, 4096) : size; From 09e77fa146f6630c8a01f59166a572dd58a30d2e Mon Sep 17 00:00:00 2001 From: lizzie Date: Wed, 27 Aug 2025 22:21:04 +0200 Subject: [PATCH 24/39] [common, fs] Use std::string_view instead of std::string&; inline functions that are used rarely (#330) Signed-off-by: lizzie Co-authored-by: crueter Reviewed-on: https://git.eden-emu.dev/eden-emu/eden/pulls/330 Reviewed-by: crueter Co-authored-by: lizzie Co-committed-by: lizzie --- src/common/fs/path_util.cpp | 20 ---------- src/common/fs/path_util.h | 12 +++++- src/common/heap_tracker.cpp | 3 +- src/common/string_util.cpp | 46 +++++------------------ src/common/string_util.h | 53 ++++++++++++++++++--------- src/core/file_sys/xts_archive.cpp | 7 +++- src/core/loader/loader.cpp | 19 +++++----- src/frontend_common/content_manager.h | 5 ++- 8 files changed, 76 insertions(+), 89 deletions(-) diff --git a/src/common/fs/path_util.cpp b/src/common/fs/path_util.cpp index e032360961..fa1403225e 100644 --- a/src/common/fs/path_util.cpp +++ b/src/common/fs/path_util.cpp @@ -517,24 +517,4 @@ std::string_view GetPathWithoutTop(std::string_view path) { return path.substr(std::min(name_bck_index, name_fwd_index) + 1); } -std::string_view GetFilename(std::string_view path) { - const auto name_index = path.find_last_of("\\/"); - - if (name_index == std::string_view::npos) { - return {}; - } - - return path.substr(name_index + 1); -} - -std::string_view GetExtensionFromFilename(std::string_view name) { - const std::size_t index = name.rfind('.'); - - if (index == std::string_view::npos) { - return {}; - } - - return name.substr(index + 1); -} - } // namespace Common::FS diff --git a/src/common/fs/path_util.h b/src/common/fs/path_util.h index c1f478690a..b34efc472f 100644 --- a/src/common/fs/path_util.h +++ b/src/common/fs/path_util.h @@ -352,9 +352,17 @@ enum class DirectorySeparator { [[nodiscard]] std::string_view GetPathWithoutTop(std::string_view path); // Gets the filename of the path -[[nodiscard]] std::string_view GetFilename(std::string_view path); +[[nodiscard]] inline std::string_view GetFilename(const std::string_view path) noexcept { + if (auto const name_index = path.find_last_of("\\/"); name_index != std::string_view::npos) + return path.substr(name_index + 1); + return {}; +} // Gets the extension of the filename -[[nodiscard]] std::string_view GetExtensionFromFilename(std::string_view name); +[[nodiscard]] inline std::string_view GetExtensionFromFilename(const std::string_view name) noexcept { + if (auto const index = name.rfind('.'); index != std::string_view::npos) + return name.substr(index + 1); + return {}; +} } // namespace Common::FS diff --git a/src/common/heap_tracker.cpp b/src/common/heap_tracker.cpp index d509f2644c..c147c279bd 100644 --- a/src/common/heap_tracker.cpp +++ b/src/common/heap_tracker.cpp @@ -4,10 +4,9 @@ // SPDX-License-Identifier: GPL-2.0-or-later #include -#include - #include "common/heap_tracker.h" #include "common/logging/log.h" +#include "common/assert.h" namespace Common { diff --git a/src/common/string_util.cpp b/src/common/string_util.cpp index 1909aced54..7bcbe737b6 100644 --- a/src/common/string_util.cpp +++ b/src/common/string_util.cpp @@ -1,3 +1,6 @@ +// SPDX-FileCopyrightText: Copyright 2025 Eden Emulator Project +// SPDX-License-Identifier: GPL-3.0-or-later + // SPDX-FileCopyrightText: 2013 Dolphin Emulator Project // SPDX-FileCopyrightText: 2014 Citra Emulator Project // SPDX-License-Identifier: GPL-2.0-or-later @@ -7,6 +10,7 @@ #include #include #include +#include #include "common/string_util.h" @@ -21,51 +25,21 @@ namespace Common { /// Make a string lowercase -std::string ToLower(std::string str) { +std::string ToLower(const std::string_view sv) { + std::string str{sv}; std::transform(str.begin(), str.end(), str.begin(), - [](unsigned char c) { return static_cast(std::tolower(c)); }); + [](auto const c) { return char(std::tolower(c)); }); return str; } /// Make a string uppercase -std::string ToUpper(std::string str) { +std::string ToUpper(const std::string_view sv) { + std::string str{sv}; std::transform(str.begin(), str.end(), str.begin(), - [](unsigned char c) { return static_cast(std::toupper(c)); }); + [](auto const c) { return char(std::toupper(c)); }); return str; } -std::string StringFromBuffer(std::span data) { - return std::string(data.begin(), std::find(data.begin(), data.end(), '\0')); -} - -std::string StringFromBuffer(std::span data) { - return std::string(data.begin(), std::find(data.begin(), data.end(), '\0')); -} - -// Turns " hej " into "hej". Also handles tabs. -std::string StripSpaces(const std::string& str) { - const std::size_t s = str.find_first_not_of(" \t\r\n"); - - if (str.npos != s) - return str.substr(s, str.find_last_not_of(" \t\r\n") - s + 1); - else - return ""; -} - -// "\"hello\"" is turned to "hello" -// This one assumes that the string has already been space stripped in both -// ends, as done by StripSpaces above, for example. -std::string StripQuotes(const std::string& s) { - if (s.size() && '\"' == s[0] && '\"' == *s.rbegin()) - return s.substr(1, s.size() - 2); - else - return s; -} - -std::string StringFromBool(bool value) { - return value ? "True" : "False"; -} - bool SplitPath(const std::string& full_path, std::string* _pPath, std::string* _pFilename, std::string* _pExtension) { if (full_path.empty()) diff --git a/src/common/string_util.h b/src/common/string_util.h index 53d0549ca7..8ed87cdadc 100644 --- a/src/common/string_util.h +++ b/src/common/string_util.h @@ -1,3 +1,6 @@ +// SPDX-FileCopyrightText: Copyright 2025 Eden Emulator Project +// SPDX-License-Identifier: GPL-3.0-or-later + // SPDX-FileCopyrightText: 2013 Dolphin Emulator Project // SPDX-FileCopyrightText: 2014 Citra Emulator Project // SPDX-License-Identifier: GPL-2.0-or-later @@ -13,18 +16,38 @@ namespace Common { /// Make a string lowercase -[[nodiscard]] std::string ToLower(std::string str); +[[nodiscard]] std::string ToLower(const std::string_view sv); /// Make a string uppercase -[[nodiscard]] std::string ToUpper(std::string str); +[[nodiscard]] std::string ToUpper(const std::string_view sv); -[[nodiscard]] std::string StringFromBuffer(std::span data); -[[nodiscard]] std::string StringFromBuffer(std::span data); +[[nodiscard]] inline std::string StringFromBuffer(std::span data) noexcept { + return std::string(data.begin(), std::find(data.begin(), data.end(), '\0')); +} +[[nodiscard]] inline std::string StringFromBuffer(std::span data) noexcept { + return std::string(data.begin(), std::find(data.begin(), data.end(), '\0')); +} -[[nodiscard]] std::string StripSpaces(const std::string& s); -[[nodiscard]] std::string StripQuotes(const std::string& s); +/// Turns " hej " into "hej". Also handles tabs. +[[nodiscard]] inline std::string StripSpaces(const std::string_view str) noexcept { + const std::size_t s = str.find_first_not_of(" \t\r\n"); + if (str.npos != s) + return std::string{str.substr(s, str.find_last_not_of(" \t\r\n") - s + 1)}; + return {}; +} -[[nodiscard]] std::string StringFromBool(bool value); +/// "\"hello\"" is turned to "hello" +/// This one assumes that the string has already been space stripped in both +/// ends, as done by StripSpaces above, for example. +[[nodiscard]] inline std::string StripQuotes(const std::string_view s) noexcept { + if (s.size() && '\"' == s[0] && '\"' == *s.rbegin()) + return std::string{s.substr(1, s.size() - 2)}; + return std::string{s}; +} + +[[nodiscard]] inline std::string StringFromBool(bool value) noexcept { + return value ? "True" : "False"; +} [[nodiscard]] std::string TabsToSpaces(int tab_size, std::string in); @@ -54,7 +77,7 @@ bool SplitPath(const std::string& full_path, std::string* _pPath, std::string* _ * `other` for equality. */ template -[[nodiscard]] bool ComparePartialString(InIt begin, InIt end, const char* other) { +[[nodiscard]] inline bool ComparePartialString(InIt begin, InIt end, const char* other) noexcept { for (; begin != end && *other != '\0'; ++begin, ++other) { if (*begin != *other) { return false; @@ -64,18 +87,14 @@ template return (begin == end) == (*other == '\0'); } -/** - * Creates a std::string from a fixed-size NUL-terminated char buffer. If the buffer isn't - * NUL-terminated then the string ends at max_len characters. - */ +/// Creates a std::string from a fixed-size NUL-terminated char buffer. If the buffer isn't +/// NUL-terminated then the string ends at max_len characters. [[nodiscard]] std::string StringFromFixedZeroTerminatedBuffer(std::string_view buffer, std::size_t max_len); -/** - * Creates a UTF-16 std::u16string from a fixed-size NUL-terminated char buffer. If the buffer isn't - * null-terminated, then the string ends at the greatest multiple of two less then or equal to - * max_len_bytes. - */ +/// Creates a UTF-16 std::u16string from a fixed-size NUL-terminated char buffer. If the buffer isn't +/// null-terminated, then the string ends at the greatest multiple of two less then or equal to +/// max_len_bytes. [[nodiscard]] std::u16string UTF16StringFromFixedZeroTerminatedBuffer(std::u16string_view buffer, std::size_t max_len); diff --git a/src/core/file_sys/xts_archive.cpp b/src/core/file_sys/xts_archive.cpp index 6692211e1d..fd5342021c 100644 --- a/src/core/file_sys/xts_archive.cpp +++ b/src/core/file_sys/xts_archive.cpp @@ -1,3 +1,6 @@ +// SPDX-FileCopyrightText: Copyright 2025 Eden Emulator Project +// SPDX-License-Identifier: GPL-3.0-or-later + // SPDX-FileCopyrightText: Copyright 2018 yuzu Emulator Project // SPDX-License-Identifier: GPL-2.0-or-later @@ -56,8 +59,8 @@ NAX::NAX(VirtualFile file_) return; } - const std::string two_dir = Common::ToUpper(match[1]); - const std::string nca_id = Common::ToLower(match[2]); + const std::string two_dir = Common::ToUpper(std::string{match[1]}); + const std::string nca_id = Common::ToLower(std::string{match[2]}); status = Parse(fmt::format("/registered/{}/{}.nca", two_dir, nca_id)); } diff --git a/src/core/loader/loader.cpp b/src/core/loader/loader.cpp index 6aabdc75e1..1f0bc4d2c1 100644 --- a/src/core/loader/loader.cpp +++ b/src/core/loader/loader.cpp @@ -1,3 +1,6 @@ +// SPDX-FileCopyrightText: Copyright 2025 Eden Emulator Project +// SPDX-License-Identifier: GPL-3.0-or-later + // SPDX-FileCopyrightText: Copyright 2018 yuzu Emulator Project // SPDX-License-Identifier: GPL-2.0-or-later @@ -61,25 +64,23 @@ FileType IdentifyFile(FileSys::VirtualFile file) { FileType GuessFromFilename(const std::string& name) { if (name == "main") return FileType::DeconstructedRomDirectory; - if (name == "00") + else if (name == "00") return FileType::NCA; - const std::string extension = + auto const extension = Common::ToLower(std::string(Common::FS::GetExtensionFromFilename(name))); - if (extension == "nro") return FileType::NRO; - if (extension == "nso") + else if (extension == "nso") return FileType::NSO; - if (extension == "nca") + else if (extension == "nca") return FileType::NCA; - if (extension == "xci") + else if (extension == "xci") return FileType::XCI; - if (extension == "nsp") + else if (extension == "nsp") return FileType::NSP; - if (extension == "kip") + else if (extension == "kip") return FileType::KIP; - return FileType::Unknown; } diff --git a/src/frontend_common/content_manager.h b/src/frontend_common/content_manager.h index c4e97a47b8..4f3112e3fb 100644 --- a/src/frontend_common/content_manager.h +++ b/src/frontend_common/content_manager.h @@ -1,3 +1,6 @@ +// SPDX-FileCopyrightText: Copyright 2025 Eden Emulator Project +// SPDX-License-Identifier: GPL-3.0-or-later + // SPDX-FileCopyrightText: 2024 yuzu Emulator Project // SPDX-License-Identifier: GPL-2.0-or-later @@ -160,7 +163,7 @@ inline InstallResult InstallNSP(Core::System& system, FileSys::VfsFilesystem& vf std::shared_ptr nsp; FileSys::VirtualFile file = vfs.OpenFile(filename, FileSys::OpenMode::Read); - if (boost::to_lower_copy(file->GetName()).ends_with(std::string("nsp"))) { + if (boost::to_lower_copy(file->GetName()).ends_with("nsp")) { nsp = std::make_shared(file); if (nsp->IsExtractedType()) { return InstallResult::Failure; From 7950c5cca05836a8030a807d26a5e591041a6bec Mon Sep 17 00:00:00 2001 From: lizzie Date: Wed, 27 Aug 2025 22:26:08 +0200 Subject: [PATCH 25/39] [common/host_memory] use assert instead of throw on Impl() ctor; abort on error (#316) Rationale: Throwing when running out of memory just creates sad paths for no reason (and at that point, just abort immediately). We are using MAP_NORESERVE, if there isn't enough memory a crash will follow anyways. Signed-off-by: lizzie Reviewed-on: https://git.eden-emu.dev/eden-emu/eden/pulls/316 Reviewed-by: crueter Co-authored-by: lizzie Co-committed-by: lizzie --- src/common/host_memory.cpp | 42 +++++------------------ src/core/arm/dynarmic/arm_dynarmic_32.cpp | 1 - 2 files changed, 8 insertions(+), 35 deletions(-) diff --git a/src/common/host_memory.cpp b/src/common/host_memory.cpp index 949cd188f3..f847ea2a62 100644 --- a/src/common/host_memory.cpp +++ b/src/common/host_memory.cpp @@ -477,19 +477,9 @@ class HostMemory::Impl { public: explicit Impl(size_t backing_size_, size_t virtual_size_) : backing_size{backing_size_}, virtual_size{virtual_size_} { - bool good = false; - SCOPE_EXIT { - if (!good) { - Release(); - } - }; - long page_size = sysconf(_SC_PAGESIZE); - if (page_size != 0x1000) { - LOG_CRITICAL(HW_Memory, "page size {:#x} is incompatible with 4K paging", page_size); - throw std::bad_alloc{}; - } - + ASSERT_MSG(page_size == 0x1000, "page size {:#x} is incompatible with 4K paging", + page_size); // Backing memory initialization #if defined(__sun__) || defined(__HAIKU__) || defined(__NetBSD__) || defined(__DragonFly__) fd = shm_open_anon(O_RDWR | O_CREAT | O_EXCL | O_NOFOLLOW, 0600); @@ -501,38 +491,23 @@ public: #else fd = memfd_create("HostMemory", 0); #endif - if (fd < 0) { - LOG_CRITICAL(HW_Memory, "memfd_create failed: {}", strerror(errno)); - throw std::bad_alloc{}; - } + ASSERT_MSG(fd >= 0, "memfd_create failed: {}", strerror(errno)); // Defined to extend the file with zeros int ret = ftruncate(fd, backing_size); - if (ret != 0) { - LOG_CRITICAL(HW_Memory, "ftruncate failed with {}, are you out-of-memory?", - strerror(errno)); - throw std::bad_alloc{}; - } + ASSERT_MSG(ret == 0, "ftruncate failed with {}, are you out-of-memory?", strerror(errno)); backing_base = static_cast( mmap(nullptr, backing_size, PROT_READ | PROT_WRITE, MAP_SHARED, fd, 0)); - if (backing_base == MAP_FAILED) { - LOG_CRITICAL(HW_Memory, "mmap failed: {}", strerror(errno)); - throw std::bad_alloc{}; - } + ASSERT_MSG(backing_base != MAP_FAILED, "mmap failed: {}", strerror(errno)); // Virtual memory initialization virtual_base = virtual_map_base = static_cast(ChooseVirtualBase(virtual_size)); - if (virtual_base == MAP_FAILED) { - LOG_CRITICAL(HW_Memory, "mmap failed: {}", strerror(errno)); - throw std::bad_alloc{}; - } + ASSERT_MSG(virtual_base != MAP_FAILED, "mmap failed: {}", strerror(errno)); #if defined(__linux__) madvise(virtual_base, virtual_size, MADV_HUGEPAGE); #endif - free_manager.SetAddressSpace(virtual_base, virtual_size); - good = true; } ~Impl() { @@ -673,10 +648,9 @@ private: class HostMemory::Impl { public: - explicit Impl(size_t /*backing_size */, size_t /* virtual_size */) { + explicit Impl([[maybe_unused]] size_t backing_size, [[maybe_unused]] size_t virtual_size) { // This is just a place holder. - // Please implement fastmem in a proper way on your platform. - throw std::bad_alloc{}; + ASSERT_MSG(false, "Please implement fastmem in a proper way on your platform."); } void Map(size_t virtual_offset, size_t host_offset, size_t length, MemoryPermission perm) {} diff --git a/src/core/arm/dynarmic/arm_dynarmic_32.cpp b/src/core/arm/dynarmic/arm_dynarmic_32.cpp index 1731ef1aec..7bb5156147 100644 --- a/src/core/arm/dynarmic/arm_dynarmic_32.cpp +++ b/src/core/arm/dynarmic/arm_dynarmic_32.cpp @@ -175,7 +175,6 @@ public: Kernel::KProcess* m_process{}; const bool m_debugger_enabled{}; const bool m_check_memory_access{}; - static constexpr u64 MinimumRunCycles = 10000U; }; std::shared_ptr ArmDynarmic32::MakeJit(Common::PageTable* page_table) const { From 9d53933a9533bb99887e508a25e8609187de8ed3 Mon Sep 17 00:00:00 2001 From: lizzie Date: Wed, 27 Aug 2025 22:39:11 +0200 Subject: [PATCH 26/39] [fmt] use {:#X} for format instead of 0x{:X} (#309) Signed-off-by: lizzie Reviewed-on: https://git.eden-emu.dev/eden-emu/eden/pulls/309 Reviewed-by: crueter Co-authored-by: lizzie Co-committed-by: lizzie --- src/audio_core/opus/decoder.cpp | 5 +++- src/core/arm/dynarmic/arm_dynarmic_32.cpp | 2 +- src/core/arm/dynarmic/arm_dynarmic_64.cpp | 2 +- src/core/file_sys/program_metadata.cpp | 5 +++- .../hle/kernel/svc/svc_address_arbiter.cpp | 7 +++-- src/core/hle/kernel/svc/svc_code_memory.cpp | 9 ++++--- .../hle/kernel/svc/svc_condition_variable.cpp | 5 +++- src/core/hle/kernel/svc/svc_info.cpp | 2 +- src/core/hle/kernel/svc/svc_lock.cpp | 7 +++-- src/core/hle/kernel/svc/svc_memory.cpp | 11 +++++--- .../hle/kernel/svc/svc_physical_memory.cpp | 13 +++++---- src/core/hle/kernel/svc/svc_process.cpp | 5 +++- .../hle/kernel/svc/svc_process_memory.cpp | 9 ++++--- src/core/hle/kernel/svc/svc_shared_memory.cpp | 5 +++- .../hle/kernel/svc/svc_synchronization.cpp | 5 +++- src/core/hle/kernel/svc/svc_thread.cpp | 5 +++- src/core/hle/service/fatal/fatal.cpp | 7 +++-- .../hle/service/filesystem/fsp/fs_i_file.cpp | 7 +++-- .../filesystem/fsp/fs_i_filesystem.cpp | 5 +++- .../service/filesystem/fsp/fs_i_storage.cpp | 5 +++- src/core/hle/service/hid/applet_resource.cpp | 5 +++- src/core/hle/service/hid/hid_server.cpp | 2 +- .../service/nvdrv/devices/nvhost_as_gpu.cpp | 16 +++++------ .../service/nvdrv/devices/nvhost_ctrl_gpu.cpp | 9 ++++--- .../hle/service/nvdrv/devices/nvhost_gpu.cpp | 6 ++--- src/core/hle/service/nvdrv/devices/nvmap.cpp | 5 +++- .../hle/service/nvdrv/nvdrv_interface.cpp | 5 +++- .../hle/service/psc/time/steady_clock.cpp | 5 +++- src/core/hle/service/service.cpp | 9 ++++--- src/core/loader/kip.cpp | 5 +++- src/core/loader/nso.cpp | 5 +++- src/video_core/cdma_pusher.cpp | 6 ++--- src/video_core/host1x/codecs/decoder.cpp | 4 +-- src/video_core/host1x/control.cpp | 5 +++- src/video_core/host1x/vic.cpp | 27 ++++++++++--------- src/video_core/texture_cache/formatter.cpp | 21 ++++++++------- 36 files changed, 170 insertions(+), 86 deletions(-) diff --git a/src/audio_core/opus/decoder.cpp b/src/audio_core/opus/decoder.cpp index 0c110cbeb6..e60a7d48d4 100644 --- a/src/audio_core/opus/decoder.cpp +++ b/src/audio_core/opus/decoder.cpp @@ -1,3 +1,6 @@ +// SPDX-FileCopyrightText: Copyright 2025 Eden Emulator Project +// SPDX-License-Identifier: GPL-3.0-or-later + // SPDX-FileCopyrightText: Copyright 2023 yuzu Emulator Project // SPDX-License-Identifier: GPL-2.0-or-later @@ -148,7 +151,7 @@ Result OpusDecoder::DecodeInterleavedForMultiStream(u32* out_data_size, u64* out auto* header_p{reinterpret_cast(input_data.data())}; OpusPacketHeader header{ReverseHeader(*header_p)}; - LOG_TRACE(Service_Audio, "header size 0x{:X} input data size 0x{:X} in_data size 0x{:X}", + LOG_TRACE(Service_Audio, "header size {:#X} input data size 0x{:X} in_data size 0x{:X}", header.size, input_data.size_bytes(), in_data.size_bytes()); R_UNLESS(in_data.size_bytes() >= header.size && diff --git a/src/core/arm/dynarmic/arm_dynarmic_32.cpp b/src/core/arm/dynarmic/arm_dynarmic_32.cpp index 7bb5156147..c6e159cc9c 100644 --- a/src/core/arm/dynarmic/arm_dynarmic_32.cpp +++ b/src/core/arm/dynarmic/arm_dynarmic_32.cpp @@ -88,7 +88,7 @@ public: void InterpreterFallback(u32 pc, std::size_t num_instructions) override { m_parent.LogBacktrace(m_process); LOG_ERROR(Core_ARM, - "Unimplemented instruction @ 0x{:X} for {} instructions (instr = {:08X})", pc, + "Unimplemented instruction @ {:#X} for {} instructions (instr = {:08X})", pc, num_instructions, m_memory.Read32(pc)); } diff --git a/src/core/arm/dynarmic/arm_dynarmic_64.cpp b/src/core/arm/dynarmic/arm_dynarmic_64.cpp index 9674e88d9d..ba5c608a03 100644 --- a/src/core/arm/dynarmic/arm_dynarmic_64.cpp +++ b/src/core/arm/dynarmic/arm_dynarmic_64.cpp @@ -102,7 +102,7 @@ public: void InterpreterFallback(u64 pc, std::size_t num_instructions) override { m_parent.LogBacktrace(m_process); LOG_ERROR(Core_ARM, - "Unimplemented instruction @ 0x{:X} for {} instructions (instr = {:08X})", pc, + "Unimplemented instruction @ {:#X} for {} instructions (instr = {:08X})", pc, num_instructions, m_memory.Read32(pc)); ReturnException(pc, PrefetchAbort); } diff --git a/src/core/file_sys/program_metadata.cpp b/src/core/file_sys/program_metadata.cpp index 289969cc4c..f542a09d0e 100644 --- a/src/core/file_sys/program_metadata.cpp +++ b/src/core/file_sys/program_metadata.cpp @@ -1,3 +1,6 @@ +// SPDX-FileCopyrightText: Copyright 2025 Eden Emulator Project +// SPDX-License-Identifier: GPL-3.0-or-later + // SPDX-FileCopyrightText: Copyright 2018 yuzu Emulator Project // SPDX-License-Identifier: GPL-2.0-or-later @@ -180,7 +183,7 @@ void ProgramMetadata::Print() const { LOG_DEBUG(Service_FS, "Magic: {:.4}", npdm_header.magic.data()); LOG_DEBUG(Service_FS, "Main thread priority: 0x{:02X}", npdm_header.main_thread_priority); LOG_DEBUG(Service_FS, "Main thread core: {}", npdm_header.main_thread_cpu); - LOG_DEBUG(Service_FS, "Main thread stack size: 0x{:X} bytes", npdm_header.main_stack_size); + LOG_DEBUG(Service_FS, "Main thread stack size: {:#X} bytes", npdm_header.main_stack_size); LOG_DEBUG(Service_FS, "Process category: {}", npdm_header.process_category); LOG_DEBUG(Service_FS, "Flags: 0x{:02X}", npdm_header.flags); LOG_DEBUG(Service_FS, " > 64-bit instructions: {}", diff --git a/src/core/hle/kernel/svc/svc_address_arbiter.cpp b/src/core/hle/kernel/svc/svc_address_arbiter.cpp index 90ee435219..ab91d74433 100644 --- a/src/core/hle/kernel/svc/svc_address_arbiter.cpp +++ b/src/core/hle/kernel/svc/svc_address_arbiter.cpp @@ -1,3 +1,6 @@ +// SPDX-FileCopyrightText: Copyright 2025 Eden Emulator Project +// SPDX-License-Identifier: GPL-3.0-or-later + // SPDX-FileCopyrightText: Copyright 2023 yuzu Emulator Project // SPDX-License-Identifier: GPL-2.0-or-later @@ -40,7 +43,7 @@ constexpr bool IsValidArbitrationType(Svc::ArbitrationType type) { // Wait for an address (via Address Arbiter) Result WaitForAddress(Core::System& system, u64 address, ArbitrationType arb_type, s32 value, s64 timeout_ns) { - LOG_TRACE(Kernel_SVC, "called, address=0x{:X}, arb_type=0x{:X}, value=0x{:X}, timeout_ns={}", + LOG_TRACE(Kernel_SVC, "called, address={:#X}, arb_type=0x{:X}, value=0x{:X}, timeout_ns={}", address, arb_type, value, timeout_ns); // Validate input. @@ -71,7 +74,7 @@ Result WaitForAddress(Core::System& system, u64 address, ArbitrationType arb_typ // Signals to an address (via Address Arbiter) Result SignalToAddress(Core::System& system, u64 address, SignalType signal_type, s32 value, s32 count) { - LOG_TRACE(Kernel_SVC, "called, address=0x{:X}, signal_type=0x{:X}, value=0x{:X}, count=0x{:X}", + LOG_TRACE(Kernel_SVC, "called, address={:#X}, signal_type=0x{:X}, value=0x{:X}, count=0x{:X}", address, signal_type, value, count); // Validate input. diff --git a/src/core/hle/kernel/svc/svc_code_memory.cpp b/src/core/hle/kernel/svc/svc_code_memory.cpp index 7be2802f07..4e7af9f575 100644 --- a/src/core/hle/kernel/svc/svc_code_memory.cpp +++ b/src/core/hle/kernel/svc/svc_code_memory.cpp @@ -1,3 +1,6 @@ +// SPDX-FileCopyrightText: Copyright 2025 Eden Emulator Project +// SPDX-License-Identifier: GPL-3.0-or-later + // SPDX-FileCopyrightText: Copyright 2023 yuzu Emulator Project // SPDX-License-Identifier: GPL-2.0-or-later @@ -30,7 +33,7 @@ constexpr bool IsValidUnmapFromOwnerCodeMemoryPermission(MemoryPermission perm) } // namespace Result CreateCodeMemory(Core::System& system, Handle* out, u64 address, uint64_t size) { - LOG_TRACE(Kernel_SVC, "called, address=0x{:X}, size=0x{:X}", address, size); + LOG_TRACE(Kernel_SVC, "called, address={:#X}, size=0x{:X}", address, size); // Get kernel instance. auto& kernel = system.Kernel(); @@ -70,8 +73,8 @@ Result ControlCodeMemory(Core::System& system, Handle code_memory_handle, MemoryPermission perm) { LOG_TRACE(Kernel_SVC, - "called, code_memory_handle=0x{:X}, operation=0x{:X}, address=0x{:X}, size=0x{:X}, " - "permission=0x{:X}", + "called, code_memory_handle={:#X}, operation=0x{:X}, address=0x{:X}, size=0x{:X}, " + "permission={:#X}", code_memory_handle, operation, address, size, perm); // Validate the address / size. diff --git a/src/core/hle/kernel/svc/svc_condition_variable.cpp b/src/core/hle/kernel/svc/svc_condition_variable.cpp index bb678e6c56..0f4550a795 100644 --- a/src/core/hle/kernel/svc/svc_condition_variable.cpp +++ b/src/core/hle/kernel/svc/svc_condition_variable.cpp @@ -1,3 +1,6 @@ +// SPDX-FileCopyrightText: Copyright 2025 Eden Emulator Project +// SPDX-License-Identifier: GPL-3.0-or-later + // SPDX-FileCopyrightText: Copyright 2023 yuzu Emulator Project // SPDX-License-Identifier: GPL-2.0-or-later @@ -45,7 +48,7 @@ Result WaitProcessWideKeyAtomic(Core::System& system, u64 address, u64 cv_key, u /// Signal process wide key void SignalProcessWideKey(Core::System& system, u64 cv_key, s32 count) { - LOG_TRACE(Kernel_SVC, "called, cv_key=0x{:X}, count=0x{:08X}", cv_key, count); + LOG_TRACE(Kernel_SVC, "called, cv_key={:#X}, count=0x{:08X}", cv_key, count); // Signal the condition variable. return GetCurrentProcess(system.Kernel()) diff --git a/src/core/hle/kernel/svc/svc_info.cpp b/src/core/hle/kernel/svc/svc_info.cpp index 37f4eba69c..16271883f2 100644 --- a/src/core/hle/kernel/svc/svc_info.cpp +++ b/src/core/hle/kernel/svc/svc_info.cpp @@ -15,7 +15,7 @@ namespace Kernel::Svc { /// Gets system/memory information for the current process Result GetInfo(Core::System& system, u64* result, InfoType info_id_type, Handle handle, u64 info_sub_id) { - LOG_TRACE(Kernel_SVC, "called info_id=0x{:X}, info_sub_id=0x{:X}, handle=0x{:08X}", + LOG_TRACE(Kernel_SVC, "called info_id={:#X}, info_sub_id=0x{:X}, handle=0x{:08X}", info_id_type, info_sub_id, handle); u32 info_id = static_cast(info_id_type); diff --git a/src/core/hle/kernel/svc/svc_lock.cpp b/src/core/hle/kernel/svc/svc_lock.cpp index 5f0833fcbf..c44317617e 100644 --- a/src/core/hle/kernel/svc/svc_lock.cpp +++ b/src/core/hle/kernel/svc/svc_lock.cpp @@ -1,3 +1,6 @@ +// SPDX-FileCopyrightText: Copyright 2025 Eden Emulator Project +// SPDX-License-Identifier: GPL-3.0-or-later + // SPDX-FileCopyrightText: Copyright 2023 yuzu Emulator Project // SPDX-License-Identifier: GPL-2.0-or-later @@ -10,7 +13,7 @@ namespace Kernel::Svc { /// Attempts to locks a mutex Result ArbitrateLock(Core::System& system, Handle thread_handle, u64 address, u32 tag) { - LOG_TRACE(Kernel_SVC, "called thread_handle=0x{:08X}, address=0x{:X}, tag=0x{:08X}", + LOG_TRACE(Kernel_SVC, "called thread_handle=0x{:08X}, address={:#X}, tag=0x{:08X}", thread_handle, address, tag); // Validate the input address. @@ -22,7 +25,7 @@ Result ArbitrateLock(Core::System& system, Handle thread_handle, u64 address, u3 /// Unlock a mutex Result ArbitrateUnlock(Core::System& system, u64 address) { - LOG_TRACE(Kernel_SVC, "called address=0x{:X}", address); + LOG_TRACE(Kernel_SVC, "called address={:#X}", address); // Validate the input address. R_UNLESS(!IsKernelAddress(address), ResultInvalidCurrentMemory); diff --git a/src/core/hle/kernel/svc/svc_memory.cpp b/src/core/hle/kernel/svc/svc_memory.cpp index 4ca62860d5..740e11ff87 100644 --- a/src/core/hle/kernel/svc/svc_memory.cpp +++ b/src/core/hle/kernel/svc/svc_memory.cpp @@ -1,3 +1,6 @@ +// SPDX-FileCopyrightText: Copyright 2025 Eden Emulator Project +// SPDX-License-Identifier: GPL-3.0-or-later + // SPDX-FileCopyrightText: Copyright 2023 yuzu Emulator Project // SPDX-License-Identifier: GPL-2.0-or-later @@ -77,7 +80,7 @@ Result MapUnmapMemorySanityChecks(const KProcessPageTable& manager, u64 dst_addr } // namespace Result SetMemoryPermission(Core::System& system, u64 address, u64 size, MemoryPermission perm) { - LOG_DEBUG(Kernel_SVC, "called, address=0x{:016X}, size=0x{:X}, perm=0x{:08X}", address, size, + LOG_DEBUG(Kernel_SVC, "called, address=0x{:016X}, size={:#X}, perm=0x{:08X}", address, size, perm); // Validate address / size. @@ -99,7 +102,7 @@ Result SetMemoryPermission(Core::System& system, u64 address, u64 size, MemoryPe Result SetMemoryAttribute(Core::System& system, u64 address, u64 size, u32 mask, u32 attr) { LOG_DEBUG(Kernel_SVC, - "called, address=0x{:016X}, size=0x{:X}, mask=0x{:08X}, attribute=0x{:08X}", address, + "called, address=0x{:016X}, size={:#X}, mask=0x{:08X}, attribute=0x{:08X}", address, size, mask, attr); // Validate address / size. @@ -130,7 +133,7 @@ Result SetMemoryAttribute(Core::System& system, u64 address, u64 size, u32 mask, /// Maps a memory range into a different range. Result MapMemory(Core::System& system, u64 dst_addr, u64 src_addr, u64 size) { - LOG_TRACE(Kernel_SVC, "called, dst_addr=0x{:X}, src_addr=0x{:X}, size=0x{:X}", dst_addr, + LOG_TRACE(Kernel_SVC, "called, dst_addr={:#X}, src_addr=0x{:X}, size=0x{:X}", dst_addr, src_addr, size); auto& page_table{GetCurrentProcess(system.Kernel()).GetPageTable()}; @@ -145,7 +148,7 @@ Result MapMemory(Core::System& system, u64 dst_addr, u64 src_addr, u64 size) { /// Unmaps a region that was previously mapped with svcMapMemory Result UnmapMemory(Core::System& system, u64 dst_addr, u64 src_addr, u64 size) { - LOG_TRACE(Kernel_SVC, "called, dst_addr=0x{:X}, src_addr=0x{:X}, size=0x{:X}", dst_addr, + LOG_TRACE(Kernel_SVC, "called, dst_addr={:#X}, src_addr=0x{:X}, size=0x{:X}", dst_addr, src_addr, size); auto& page_table{GetCurrentProcess(system.Kernel()).GetPageTable()}; diff --git a/src/core/hle/kernel/svc/svc_physical_memory.cpp b/src/core/hle/kernel/svc/svc_physical_memory.cpp index 793e9f8d01..facf8ee638 100644 --- a/src/core/hle/kernel/svc/svc_physical_memory.cpp +++ b/src/core/hle/kernel/svc/svc_physical_memory.cpp @@ -1,3 +1,6 @@ +// SPDX-FileCopyrightText: Copyright 2025 Eden Emulator Project +// SPDX-License-Identifier: GPL-3.0-or-later + // SPDX-FileCopyrightText: Copyright 2023 yuzu Emulator Project // SPDX-License-Identifier: GPL-2.0-or-later @@ -9,7 +12,7 @@ namespace Kernel::Svc { /// Set the process heap to a given Size. It can both extend and shrink the heap. Result SetHeapSize(Core::System& system, u64* out_address, u64 size) { - LOG_TRACE(Kernel_SVC, "called, heap_size=0x{:X}", size); + LOG_TRACE(Kernel_SVC, "called, heap_size={:#X}", size); // Validate size. R_UNLESS(Common::IsAligned(size, HeapSizeAlignment), ResultInvalidSize); @@ -28,7 +31,7 @@ Result SetHeapSize(Core::System& system, u64* out_address, u64 size) { /// Maps memory at a desired address Result MapPhysicalMemory(Core::System& system, u64 addr, u64 size) { - LOG_DEBUG(Kernel_SVC, "called, addr=0x{:016X}, size=0x{:X}", addr, size); + LOG_DEBUG(Kernel_SVC, "called, addr=0x{:016X}, size={:#X}", addr, size); if (!Common::Is4KBAligned(addr)) { LOG_ERROR(Kernel_SVC, "Address is not aligned to 4KB, 0x{:016X}", addr); @@ -36,7 +39,7 @@ Result MapPhysicalMemory(Core::System& system, u64 addr, u64 size) { } if (!Common::Is4KBAligned(size)) { - LOG_ERROR(Kernel_SVC, "Size is not aligned to 4KB, 0x{:X}", size); + LOG_ERROR(Kernel_SVC, "Size is not aligned to 4KB, {:#X}", size); R_THROW(ResultInvalidSize); } @@ -77,7 +80,7 @@ Result MapPhysicalMemory(Core::System& system, u64 addr, u64 size) { /// Unmaps memory previously mapped via MapPhysicalMemory Result UnmapPhysicalMemory(Core::System& system, u64 addr, u64 size) { - LOG_DEBUG(Kernel_SVC, "called, addr=0x{:016X}, size=0x{:X}", addr, size); + LOG_DEBUG(Kernel_SVC, "called, addr=0x{:016X}, size={:#X}", addr, size); if (!Common::Is4KBAligned(addr)) { LOG_ERROR(Kernel_SVC, "Address is not aligned to 4KB, 0x{:016X}", addr); @@ -85,7 +88,7 @@ Result UnmapPhysicalMemory(Core::System& system, u64 addr, u64 size) { } if (!Common::Is4KBAligned(size)) { - LOG_ERROR(Kernel_SVC, "Size is not aligned to 4KB, 0x{:X}", size); + LOG_ERROR(Kernel_SVC, "Size is not aligned to 4KB, {:#X}", size); R_THROW(ResultInvalidSize); } diff --git a/src/core/hle/kernel/svc/svc_process.cpp b/src/core/hle/kernel/svc/svc_process.cpp index 5c3e8829ff..87845d64a6 100644 --- a/src/core/hle/kernel/svc/svc_process.cpp +++ b/src/core/hle/kernel/svc/svc_process.cpp @@ -1,3 +1,6 @@ +// SPDX-FileCopyrightText: Copyright 2025 Eden Emulator Project +// SPDX-License-Identifier: GPL-3.0-or-later + // SPDX-FileCopyrightText: Copyright 2023 yuzu Emulator Project // SPDX-License-Identifier: GPL-2.0-or-later @@ -92,7 +95,7 @@ Result GetProcessList(Core::System& system, s32* out_num_processes, u64 out_proc Result GetProcessInfo(Core::System& system, s64* out, Handle process_handle, ProcessInfoType info_type) { - LOG_DEBUG(Kernel_SVC, "called, handle=0x{:08X}, type=0x{:X}", process_handle, info_type); + LOG_DEBUG(Kernel_SVC, "called, handle=0x{:08X}, type={:#X}", process_handle, info_type); const auto& handle_table = GetCurrentProcess(system.Kernel()).GetHandleTable(); KScopedAutoObject process = handle_table.GetObject(process_handle); diff --git a/src/core/hle/kernel/svc/svc_process_memory.cpp b/src/core/hle/kernel/svc/svc_process_memory.cpp index e1427947b0..3313118dfa 100644 --- a/src/core/hle/kernel/svc/svc_process_memory.cpp +++ b/src/core/hle/kernel/svc/svc_process_memory.cpp @@ -1,3 +1,6 @@ +// SPDX-FileCopyrightText: Copyright 2025 Eden Emulator Project +// SPDX-License-Identifier: GPL-3.0-or-later + // SPDX-FileCopyrightText: Copyright 2023 yuzu Emulator Project // SPDX-License-Identifier: GPL-2.0-or-later @@ -29,7 +32,7 @@ constexpr bool IsValidProcessMemoryPermission(Svc::MemoryPermission perm) { Result SetProcessMemoryPermission(Core::System& system, Handle process_handle, u64 address, u64 size, Svc::MemoryPermission perm) { LOG_TRACE(Kernel_SVC, - "called, process_handle=0x{:X}, addr=0x{:X}, size=0x{:X}, permissions=0x{:08X}", + "called, process_handle={:#X}, addr=0x{:X}, size=0x{:X}, permissions=0x{:08X}", process_handle, address, size, perm); // Validate the address/size. @@ -59,7 +62,7 @@ Result SetProcessMemoryPermission(Core::System& system, Handle process_handle, u Result MapProcessMemory(Core::System& system, u64 dst_address, Handle process_handle, u64 src_address, u64 size) { LOG_TRACE(Kernel_SVC, - "called, dst_address=0x{:X}, process_handle=0x{:X}, src_address=0x{:X}, size=0x{:X}", + "called, dst_address={:#X}, process_handle=0x{:X}, src_address=0x{:X}, size=0x{:X}", dst_address, process_handle, src_address, size); // Validate the address/size. @@ -100,7 +103,7 @@ Result MapProcessMemory(Core::System& system, u64 dst_address, Handle process_ha Result UnmapProcessMemory(Core::System& system, u64 dst_address, Handle process_handle, u64 src_address, u64 size) { LOG_TRACE(Kernel_SVC, - "called, dst_address=0x{:X}, process_handle=0x{:X}, src_address=0x{:X}, size=0x{:X}", + "called, dst_address={:#X}, process_handle=0x{:X}, src_address=0x{:X}, size=0x{:X}", dst_address, process_handle, src_address, size); // Validate the address/size. diff --git a/src/core/hle/kernel/svc/svc_shared_memory.cpp b/src/core/hle/kernel/svc/svc_shared_memory.cpp index 012b1ae2bc..3ca07abe8b 100644 --- a/src/core/hle/kernel/svc/svc_shared_memory.cpp +++ b/src/core/hle/kernel/svc/svc_shared_memory.cpp @@ -1,3 +1,6 @@ +// SPDX-FileCopyrightText: Copyright 2025 Eden Emulator Project +// SPDX-License-Identifier: GPL-3.0-or-later + // SPDX-FileCopyrightText: Copyright 2023 yuzu Emulator Project // SPDX-License-Identifier: GPL-2.0-or-later @@ -29,7 +32,7 @@ constexpr bool IsValidSharedMemoryPermission(MemoryPermission perm) { Result MapSharedMemory(Core::System& system, Handle shmem_handle, u64 address, u64 size, Svc::MemoryPermission map_perm) { LOG_TRACE(Kernel_SVC, - "called, shared_memory_handle=0x{:X}, addr=0x{:X}, size=0x{:X}, permissions=0x{:08X}", + "called, shared_memory_handle={:#X}, addr=0x{:X}, size=0x{:X}, permissions=0x{:08X}", shmem_handle, address, size, map_perm); // Validate the address/size. diff --git a/src/core/hle/kernel/svc/svc_synchronization.cpp b/src/core/hle/kernel/svc/svc_synchronization.cpp index fb03908d73..fdd4408d4d 100644 --- a/src/core/hle/kernel/svc/svc_synchronization.cpp +++ b/src/core/hle/kernel/svc/svc_synchronization.cpp @@ -1,3 +1,6 @@ +// SPDX-FileCopyrightText: Copyright 2025 Eden Emulator Project +// SPDX-License-Identifier: GPL-3.0-or-later + // SPDX-FileCopyrightText: Copyright 2023 yuzu Emulator Project // SPDX-License-Identifier: GPL-2.0-or-later @@ -105,7 +108,7 @@ Result WaitSynchronization(Core::System& system, int32_t* out_index, u64 user_ha /// Resumes a thread waiting on WaitSynchronization Result CancelSynchronization(Core::System& system, Handle handle) { - LOG_TRACE(Kernel_SVC, "called handle=0x{:X}", handle); + LOG_TRACE(Kernel_SVC, "called handle={:#X}", handle); // Get the thread from its handle. KScopedAutoObject thread = diff --git a/src/core/hle/kernel/svc/svc_thread.cpp b/src/core/hle/kernel/svc/svc_thread.cpp index 7517bb9d39..77cd634c0d 100644 --- a/src/core/hle/kernel/svc/svc_thread.cpp +++ b/src/core/hle/kernel/svc/svc_thread.cpp @@ -1,3 +1,6 @@ +// SPDX-FileCopyrightText: Copyright 2025 Eden Emulator Project +// SPDX-License-Identifier: GPL-3.0-or-later + // SPDX-FileCopyrightText: Copyright 2023 yuzu Emulator Project // SPDX-License-Identifier: GPL-2.0-or-later @@ -136,7 +139,7 @@ void SleepThread(Core::System& system, s64 ns) { /// Gets the thread context Result GetThreadContext3(Core::System& system, u64 out_context, Handle thread_handle) { - LOG_DEBUG(Kernel_SVC, "called, out_context=0x{:08X}, thread_handle=0x{:X}", out_context, + LOG_DEBUG(Kernel_SVC, "called, out_context=0x{:08X}, thread_handle={:#X}", out_context, thread_handle); auto& kernel = system.Kernel(); diff --git a/src/core/hle/service/fatal/fatal.cpp b/src/core/hle/service/fatal/fatal.cpp index dfcac1ffda..360abf5da9 100644 --- a/src/core/hle/service/fatal/fatal.cpp +++ b/src/core/hle/service/fatal/fatal.cpp @@ -1,3 +1,6 @@ +// SPDX-FileCopyrightText: Copyright 2025 Eden Emulator Project +// SPDX-License-Identifier: GPL-3.0-or-later + // SPDX-FileCopyrightText: Copyright 2018 yuzu Emulator Project // SPDX-License-Identifier: GPL-2.0-or-later @@ -68,7 +71,7 @@ static void GenerateErrorReport(Core::System& system, Result error_code, const F std::string crash_report = fmt::format( "Yuzu {}-{} crash report\n" "Title ID: {:016x}\n" - "Result: 0x{:X} ({:04}-{:04d})\n" + "Result: {:#X} ({:04}-{:04d})\n" "Set flags: 0x{:16X}\n" "Program entry point: 0x{:16X}\n" "\n", @@ -108,7 +111,7 @@ static void GenerateErrorReport(Core::System& system, Result error_code, const F static void ThrowFatalError(Core::System& system, Result error_code, FatalType fatal_type, const FatalInfo& info) { - LOG_ERROR(Service_Fatal, "Threw fatal error type {} with error code 0x{:X}", fatal_type, + LOG_ERROR(Service_Fatal, "Threw fatal error type {} with error code {:#X}", fatal_type, error_code.raw); switch (fatal_type) { diff --git a/src/core/hle/service/filesystem/fsp/fs_i_file.cpp b/src/core/hle/service/filesystem/fsp/fs_i_file.cpp index a355d46ae1..ef9dd60ae1 100644 --- a/src/core/hle/service/filesystem/fsp/fs_i_file.cpp +++ b/src/core/hle/service/filesystem/fsp/fs_i_file.cpp @@ -1,3 +1,6 @@ +// SPDX-FileCopyrightText: Copyright 2025 Eden Emulator Project +// SPDX-License-Identifier: GPL-3.0-or-later + // SPDX-FileCopyrightText: Copyright 2023 yuzu Emulator Project // SPDX-License-Identifier: GPL-2.0-or-later @@ -27,7 +30,7 @@ Result IFile::Read( FileSys::ReadOption option, Out out_size, s64 offset, const OutBuffer out_buffer, s64 size) { - LOG_DEBUG(Service_FS, "called, option={}, offset=0x{:X}, length={}", option.value, offset, + LOG_DEBUG(Service_FS, "called, option={}, offset={:#X}, length={}", option.value, offset, size); // Read the data from the Storage backend @@ -38,7 +41,7 @@ Result IFile::Read( Result IFile::Write( const InBuffer buffer, FileSys::WriteOption option, s64 offset, s64 size) { - LOG_DEBUG(Service_FS, "called, option={}, offset=0x{:X}, length={}", option.value, offset, + LOG_DEBUG(Service_FS, "called, option={}, offset={:#X}, length={}", option.value, offset, size); R_RETURN(backend->Write(offset, buffer.data(), size, option)); diff --git a/src/core/hle/service/filesystem/fsp/fs_i_filesystem.cpp b/src/core/hle/service/filesystem/fsp/fs_i_filesystem.cpp index d881e144d3..352b8f77b0 100644 --- a/src/core/hle/service/filesystem/fsp/fs_i_filesystem.cpp +++ b/src/core/hle/service/filesystem/fsp/fs_i_filesystem.cpp @@ -1,3 +1,6 @@ +// SPDX-FileCopyrightText: Copyright 2025 Eden Emulator Project +// SPDX-License-Identifier: GPL-3.0-or-later + // SPDX-FileCopyrightText: Copyright 2023 yuzu Emulator Project // SPDX-License-Identifier: GPL-2.0-or-later @@ -38,7 +41,7 @@ IFileSystem::IFileSystem(Core::System& system_, FileSys::VirtualDir dir_, SizeGe Result IFileSystem::CreateFile(const InLargeData path, s32 option, s64 size) { - LOG_DEBUG(Service_FS, "called. file={}, option=0x{:X}, size=0x{:08X}", path->str, option, size); + LOG_DEBUG(Service_FS, "called. file={}, option={:#X}, size=0x{:08X}", path->str, option, size); R_RETURN(backend->CreateFile(FileSys::Path(path->str), size)); } diff --git a/src/core/hle/service/filesystem/fsp/fs_i_storage.cpp b/src/core/hle/service/filesystem/fsp/fs_i_storage.cpp index 213f198085..376a8bda29 100644 --- a/src/core/hle/service/filesystem/fsp/fs_i_storage.cpp +++ b/src/core/hle/service/filesystem/fsp/fs_i_storage.cpp @@ -1,3 +1,6 @@ +// SPDX-FileCopyrightText: Copyright 2025 Eden Emulator Project +// SPDX-License-Identifier: GPL-3.0-or-later + // SPDX-FileCopyrightText: Copyright 2023 yuzu Emulator Project // SPDX-License-Identifier: GPL-2.0-or-later @@ -23,7 +26,7 @@ IStorage::IStorage(Core::System& system_, FileSys::VirtualFile backend_) Result IStorage::Read( OutBuffer out_bytes, s64 offset, s64 length) { - LOG_DEBUG(Service_FS, "called, offset=0x{:X}, length={}", offset, length); + LOG_DEBUG(Service_FS, "called, offset={:#X}, length={}", offset, length); R_UNLESS(length >= 0, FileSys::ResultInvalidSize); R_UNLESS(offset >= 0, FileSys::ResultInvalidOffset); diff --git a/src/core/hle/service/hid/applet_resource.cpp b/src/core/hle/service/hid/applet_resource.cpp index 4814d7ad51..4c5df44be5 100644 --- a/src/core/hle/service/hid/applet_resource.cpp +++ b/src/core/hle/service/hid/applet_resource.cpp @@ -1,3 +1,6 @@ +// SPDX-FileCopyrightText: Copyright 2025 Eden Emulator Project +// SPDX-License-Identifier: GPL-3.0-or-later + // SPDX-FileCopyrightText: Copyright 2024 yuzu Emulator Project // SPDX-License-Identifier: GPL-3.0-or-later @@ -27,7 +30,7 @@ Result IAppletResource::GetSharedMemoryHandle( OutCopyHandle out_shared_memory_handle) { const auto result = resource_manager->GetSharedMemoryHandle(out_shared_memory_handle, aruid); - LOG_DEBUG(Service_HID, "called, applet_resource_user_id={}, result=0x{:X}", aruid, result.raw); + LOG_DEBUG(Service_HID, "called, applet_resource_user_id={}, result={:#X}", aruid, result.raw); R_RETURN(result); } diff --git a/src/core/hle/service/hid/hid_server.cpp b/src/core/hle/service/hid/hid_server.cpp index ebda7fc3f2..1749c53ca2 100644 --- a/src/core/hle/service/hid/hid_server.cpp +++ b/src/core/hle/service/hid/hid_server.cpp @@ -200,7 +200,7 @@ Result IHidServer::CreateAppletResource(OutInterface out_applet ClientAppletResourceUserId aruid) { const auto result = GetResourceManager()->CreateAppletResource(aruid.pid); - LOG_DEBUG(Service_HID, "called, applet_resource_user_id={}, result=0x{:X}", aruid.pid, + LOG_DEBUG(Service_HID, "called, applet_resource_user_id={}, result={:#X}", aruid.pid, result.raw); *out_applet_resource = std::make_shared(system, resource_manager, aruid.pid); diff --git a/src/core/hle/service/nvdrv/devices/nvhost_as_gpu.cpp b/src/core/hle/service/nvdrv/devices/nvhost_as_gpu.cpp index 029a9d9cd5..02913a5817 100644 --- a/src/core/hle/service/nvdrv/devices/nvhost_as_gpu.cpp +++ b/src/core/hle/service/nvdrv/devices/nvhost_as_gpu.cpp @@ -93,7 +93,7 @@ void nvhost_as_gpu::OnOpen(NvCore::SessionId session_id, DeviceFD fd) {} void nvhost_as_gpu::OnClose(DeviceFD fd) {} NvResult nvhost_as_gpu::AllocAsEx(IoctlAllocAsEx& params) { - LOG_DEBUG(Service_NVDRV, "called, big_page_size=0x{:X}", params.big_page_size); + LOG_DEBUG(Service_NVDRV, "called, big_page_size={:#X}", params.big_page_size); std::scoped_lock lock(mutex); @@ -104,12 +104,12 @@ NvResult nvhost_as_gpu::AllocAsEx(IoctlAllocAsEx& params) { if (params.big_page_size) { if (!std::has_single_bit(params.big_page_size)) { - LOG_ERROR(Service_NVDRV, "Non power-of-2 big page size: 0x{:X}!", params.big_page_size); + LOG_ERROR(Service_NVDRV, "Non power-of-2 big page size: {:#X}!", params.big_page_size); return NvResult::BadValue; } if ((params.big_page_size & VM::SUPPORTED_BIG_PAGE_SIZES) == 0) { - LOG_ERROR(Service_NVDRV, "Unsupported big page size: 0x{:X}!", params.big_page_size); + LOG_ERROR(Service_NVDRV, "Unsupported big page size: {:#X}!", params.big_page_size); return NvResult::BadValue; } @@ -267,7 +267,7 @@ NvResult nvhost_as_gpu::FreeSpace(IoctlFreeSpace& params) { } NvResult nvhost_as_gpu::Remap(std::span entries) { - LOG_DEBUG(Service_NVDRV, "called, num_entries=0x{:X}", entries.size()); + LOG_DEBUG(Service_NVDRV, "called, num_entries={:#X}", entries.size()); if (!vm.initialised) { return NvResult::BadValue; @@ -315,7 +315,7 @@ NvResult nvhost_as_gpu::Remap(std::span entries) { NvResult nvhost_as_gpu::MapBufferEx(IoctlMapBufferEx& params) { LOG_DEBUG(Service_NVDRV, "called, flags={:X}, nvmap_handle={:X}, buffer_offset={}, mapping_size={}" - ", offset=0x{:X}", + ", offset={:#X}", params.flags, params.handle, params.buffer_offset, params.mapping_size, params.offset); @@ -332,7 +332,7 @@ NvResult nvhost_as_gpu::MapBufferEx(IoctlMapBufferEx& params) { if (mapping->size < params.mapping_size) { LOG_WARNING(Service_NVDRV, - "Cannot remap a partially mapped GPU address space region: 0x{:X}", + "Cannot remap a partially mapped GPU address space region: {:#X}", params.offset); return NvResult::BadValue; } @@ -345,7 +345,7 @@ NvResult nvhost_as_gpu::MapBufferEx(IoctlMapBufferEx& params) { return NvResult::Success; } catch (const std::out_of_range&) { - LOG_WARNING(Service_NVDRV, "Cannot remap an unmapped GPU address space region: 0x{:X}", + LOG_WARNING(Service_NVDRV, "Cannot remap an unmapped GPU address space region: {:#X}", params.offset); return NvResult::BadValue; } @@ -416,7 +416,7 @@ NvResult nvhost_as_gpu::MapBufferEx(IoctlMapBufferEx& params) { NvResult nvhost_as_gpu::UnmapBuffer(IoctlUnmapBuffer& params) { if (map_buffer_offsets.find(params.offset) != map_buffer_offsets.end()) { - LOG_DEBUG(Service_NVDRV, "called, offset=0x{:X}", params.offset); + LOG_DEBUG(Service_NVDRV, "called, offset={:#X}", params.offset); std::scoped_lock lock(mutex); diff --git a/src/core/hle/service/nvdrv/devices/nvhost_ctrl_gpu.cpp b/src/core/hle/service/nvdrv/devices/nvhost_ctrl_gpu.cpp index 45a4a402da..a7551ec154 100644 --- a/src/core/hle/service/nvdrv/devices/nvhost_ctrl_gpu.cpp +++ b/src/core/hle/service/nvdrv/devices/nvhost_ctrl_gpu.cpp @@ -1,3 +1,6 @@ +// SPDX-FileCopyrightText: Copyright 2025 Eden Emulator Project +// SPDX-License-Identifier: GPL-3.0-or-later + // SPDX-FileCopyrightText: Copyright 2018 yuzu Emulator Project // SPDX-License-Identifier: GPL-2.0-or-later @@ -205,7 +208,7 @@ NvResult nvhost_ctrl_gpu::GetCharacteristics3( } NvResult nvhost_ctrl_gpu::GetTPCMasks1(IoctlGpuGetTpcMasksArgs& params) { - LOG_DEBUG(Service_NVDRV, "called, mask_buffer_size=0x{:X}", params.mask_buffer_size); + LOG_DEBUG(Service_NVDRV, "called, mask_buffer_size={:#X}", params.mask_buffer_size); if (params.mask_buffer_size != 0) { params.tcp_mask = 3; } @@ -213,7 +216,7 @@ NvResult nvhost_ctrl_gpu::GetTPCMasks1(IoctlGpuGetTpcMasksArgs& params) { } NvResult nvhost_ctrl_gpu::GetTPCMasks3(IoctlGpuGetTpcMasksArgs& params, std::span tpc_mask) { - LOG_DEBUG(Service_NVDRV, "called, mask_buffer_size=0x{:X}", params.mask_buffer_size); + LOG_DEBUG(Service_NVDRV, "called, mask_buffer_size={:#X}", params.mask_buffer_size); if (params.mask_buffer_size != 0) { params.tcp_mask = 3; } @@ -312,7 +315,7 @@ NvResult nvhost_ctrl_gpu::ZBCQueryTable(IoctlZbcQueryTable& params) { } NvResult nvhost_ctrl_gpu::FlushL2(IoctlFlushL2& params) { - LOG_DEBUG(Service_NVDRV, "called 0x{:X}", params.flush); + LOG_DEBUG(Service_NVDRV, "called {:#X}", params.flush); // if ((params.flush & 0x01) != 0) //l2 flush // /* we dont emulate l2 */; // if ((params.flush & 0x04) != 0) //fb flush diff --git a/src/core/hle/service/nvdrv/devices/nvhost_gpu.cpp b/src/core/hle/service/nvdrv/devices/nvhost_gpu.cpp index d01642fe7c..95bf18dbf7 100644 --- a/src/core/hle/service/nvdrv/devices/nvhost_gpu.cpp +++ b/src/core/hle/service/nvdrv/devices/nvhost_gpu.cpp @@ -360,20 +360,20 @@ NvResult nvhost_gpu::SubmitGPFIFOBase2(IoctlSubmitGpfifo& params, } NvResult nvhost_gpu::GetWaitbase(IoctlGetWaitbase& params) { - LOG_INFO(Service_NVDRV, "called, unknown=0x{:X}", params.unknown); + LOG_INFO(Service_NVDRV, "called, unknown={:#X}", params.unknown); params.value = 0; // Seems to be hard coded at 0 return NvResult::Success; } NvResult nvhost_gpu::ChannelSetTimeout(IoctlChannelSetTimeout& params) { - LOG_INFO(Service_NVDRV, "called, timeout=0x{:X}", params.timeout); + LOG_INFO(Service_NVDRV, "called, timeout={:#X}", params.timeout); return NvResult::Success; } NvResult nvhost_gpu::ChannelSetTimeslice(IoctlSetTimeslice& params) { - LOG_INFO(Service_NVDRV, "called, timeslice=0x{:X}", params.timeslice); + LOG_INFO(Service_NVDRV, "called, timeslice={:#X}", params.timeslice); channel_timeslice = params.timeslice; diff --git a/src/core/hle/service/nvdrv/devices/nvmap.cpp b/src/core/hle/service/nvdrv/devices/nvmap.cpp index da61a3bfeb..b9131ee5ce 100644 --- a/src/core/hle/service/nvdrv/devices/nvmap.cpp +++ b/src/core/hle/service/nvdrv/devices/nvmap.cpp @@ -1,3 +1,6 @@ +// SPDX-FileCopyrightText: Copyright 2025 Eden Emulator Project +// SPDX-License-Identifier: GPL-3.0-or-later + // SPDX-FileCopyrightText: Copyright 2018 yuzu Emulator Project // SPDX-License-Identifier: GPL-2.0-or-later @@ -89,7 +92,7 @@ NvResult nvmap::IocCreate(IocCreateParams& params) { } handle_description->orig_size = params.size; // Orig size is the unaligned size params.handle = handle_description->id; - LOG_DEBUG(Service_NVDRV, "handle: {}, size: 0x{:X}", handle_description->id, params.size); + LOG_DEBUG(Service_NVDRV, "handle: {}, size: {:#X}", handle_description->id, params.size); return NvResult::Success; } diff --git a/src/core/hle/service/nvdrv/nvdrv_interface.cpp b/src/core/hle/service/nvdrv/nvdrv_interface.cpp index 258970fd53..db9467f4d1 100644 --- a/src/core/hle/service/nvdrv/nvdrv_interface.cpp +++ b/src/core/hle/service/nvdrv/nvdrv_interface.cpp @@ -1,3 +1,6 @@ +// SPDX-FileCopyrightText: Copyright 2025 Eden Emulator Project +// SPDX-License-Identifier: GPL-3.0-or-later + // SPDX-FileCopyrightText: 2021 yuzu Emulator Project // SPDX-FileCopyrightText: 2021 Skyline Team and Contributors // SPDX-License-Identifier: GPL-3.0-or-later @@ -209,7 +212,7 @@ void NVDRV::QueryEvent(HLERequestContext& ctx) { void NVDRV::SetAruid(HLERequestContext& ctx) { IPC::RequestParser rp{ctx}; pid = rp.Pop(); - LOG_WARNING(Service_NVDRV, "(STUBBED) called, pid=0x{:X}", pid); + LOG_WARNING(Service_NVDRV, "(STUBBED) called, pid={:#X}", pid); IPC::ResponseBuilder rb{ctx, 3}; rb.Push(ResultSuccess); diff --git a/src/core/hle/service/psc/time/steady_clock.cpp b/src/core/hle/service/psc/time/steady_clock.cpp index 78dcf532ce..cfeaf0a653 100644 --- a/src/core/hle/service/psc/time/steady_clock.cpp +++ b/src/core/hle/service/psc/time/steady_clock.cpp @@ -1,3 +1,6 @@ +// SPDX-FileCopyrightText: Copyright 2025 Eden Emulator Project +// SPDX-License-Identifier: GPL-3.0-or-later + // SPDX-FileCopyrightText: Copyright 2023 yuzu Emulator Project // SPDX-License-Identifier: GPL-2.0-or-later @@ -87,7 +90,7 @@ Result SteadyClock::IsRtcResetDetected(Out out_is_detected) { Result SteadyClock::GetSetupResultValue(Out out_result) { SCOPE_EXIT { - LOG_DEBUG(Service_Time, "called. out_result=0x{:X}", out_result->raw); + LOG_DEBUG(Service_Time, "called. out_result={:#X}", out_result->raw); }; R_UNLESS(m_can_write_uninitialized_clock || m_clock_core.IsInitialized(), diff --git a/src/core/hle/service/service.cpp b/src/core/hle/service/service.cpp index e5779de2fd..d70dc2978f 100644 --- a/src/core/hle/service/service.cpp +++ b/src/core/hle/service/service.cpp @@ -1,3 +1,6 @@ +// SPDX-FileCopyrightText: Copyright 2025 Eden Emulator Project +// SPDX-License-Identifier: GPL-3.0-or-later + // SPDX-FileCopyrightText: Copyright 2018 yuzu Emulator Project // SPDX-License-Identifier: GPL-2.0-or-later @@ -27,7 +30,7 @@ namespace Service { std::string function_string = fmt::format("function '{}': port={}", name, port_name); for (int i = 1; i <= num_params; ++i) { - function_string += fmt::format(", cmd_buff[{}]=0x{:X}", i, cmd_buff[i]); + function_string += fmt::format(", cmd_buff[{}]={:#X}", i, cmd_buff[i]); } return function_string; } @@ -66,10 +69,10 @@ void ServiceFrameworkBase::ReportUnimplementedFunction(HLERequestContext& ctx, std::string function_name = info == nullptr ? "" : info->name; fmt::memory_buffer buf; - fmt::format_to(std::back_inserter(buf), "function '{}({})': port='{}' cmd_buf={{[0]=0x{:X}", + fmt::format_to(std::back_inserter(buf), "function '{}({})': port='{}' cmd_buf={{[0]={:#X}", ctx.GetCommand(), function_name, service_name, cmd_buf[0]); for (int i = 1; i <= 8; ++i) { - fmt::format_to(std::back_inserter(buf), ", [{}]=0x{:X}", i, cmd_buf[i]); + fmt::format_to(std::back_inserter(buf), ", [{}]={:#X}", i, cmd_buf[i]); } buf.push_back('}'); diff --git a/src/core/loader/kip.cpp b/src/core/loader/kip.cpp index cd69829217..4dc98040ae 100644 --- a/src/core/loader/kip.cpp +++ b/src/core/loader/kip.cpp @@ -1,3 +1,6 @@ +// SPDX-FileCopyrightText: Copyright 2025 Eden Emulator Project +// SPDX-License-Identifier: GPL-3.0-or-later + // SPDX-FileCopyrightText: Copyright 2019 yuzu Emulator Project // SPDX-License-Identifier: GPL-2.0-or-later @@ -101,7 +104,7 @@ AppLoader::LoadResult AppLoader_KIP::Load(Kernel::KProcess& process, const VAddr base_address = GetInteger(process.GetEntryPoint()); process.LoadModule(std::move(codeset), base_address); - LOG_DEBUG(Loader, "loaded module {} @ 0x{:X}", kip->GetName(), base_address); + LOG_DEBUG(Loader, "loaded module {} @ {:#X}", kip->GetName(), base_address); is_loaded = true; return {ResultStatus::Success, diff --git a/src/core/loader/nso.cpp b/src/core/loader/nso.cpp index 2cd62df072..e3e3f83ca2 100644 --- a/src/core/loader/nso.cpp +++ b/src/core/loader/nso.cpp @@ -1,3 +1,6 @@ +// SPDX-FileCopyrightText: Copyright 2025 Eden Emulator Project +// SPDX-License-Identifier: GPL-3.0-or-later + // SPDX-FileCopyrightText: Copyright 2018 yuzu Emulator Project // SPDX-License-Identifier: GPL-2.0-or-later @@ -223,7 +226,7 @@ AppLoader_NSO::LoadResult AppLoader_NSO::Load(Kernel::KProcess& process, Core::S } modules.insert_or_assign(base_address, file->GetName()); - LOG_DEBUG(Loader, "loaded module {} @ 0x{:X}", file->GetName(), base_address); + LOG_DEBUG(Loader, "loaded module {} @ {:#X}", file->GetName(), base_address); is_loaded = true; return {ResultStatus::Success, LoadParameters{Kernel::KThread::DefaultThreadPriority, diff --git a/src/video_core/cdma_pusher.cpp b/src/video_core/cdma_pusher.cpp index 2a13594719..1b6b4c6d45 100644 --- a/src/video_core/cdma_pusher.cpp +++ b/src/video_core/cdma_pusher.cpp @@ -90,7 +90,7 @@ void CDmaPusher::ProcessEntries(std::stop_token stop_token) { break; } default: - LOG_ERROR(HW_GPU, "Bad command at index {} (bytes 0x{:X}), buffer size {}", i - 1, + LOG_ERROR(HW_GPU, "Bad command at index {} (bytes {:#X}), buffer size {}", i - 1, (i - 1) * sizeof(u32), command_list.size()); UNIMPLEMENTED_MSG("ChSubmission mode {} is not implemented!", static_cast(mode)); @@ -103,7 +103,7 @@ void CDmaPusher::ProcessEntries(std::stop_token stop_token) { void CDmaPusher::ExecuteCommand(u32 method, u32 arg) { switch (current_class) { case ChClassId::Control: - LOG_TRACE(Service_NVDRV, "Class {} method 0x{:X} arg 0x{:X}", + LOG_TRACE(Service_NVDRV, "Class {} method {:#X} arg 0x{:X}", static_cast(current_class), method, arg); host_processor->ProcessMethod(static_cast(method), arg); break; @@ -121,7 +121,7 @@ void CDmaPusher::ExecuteCommand(u32 method, u32 arg) { break; } case ThiMethod::SetMethod1: - LOG_TRACE(Service_NVDRV, "Class {} method 0x{:X} arg 0x{:X}", + LOG_TRACE(Service_NVDRV, "Class {} method {:#X} arg 0x{:X}", static_cast(current_class), static_cast(thi_regs.method_0), arg); ProcessMethod(thi_regs.method_0, arg); break; diff --git a/src/video_core/host1x/codecs/decoder.cpp b/src/video_core/host1x/codecs/decoder.cpp index 391bfabc1e..cb17784b19 100755 --- a/src/video_core/host1x/codecs/decoder.cpp +++ b/src/video_core/host1x/codecs/decoder.cpp @@ -44,7 +44,7 @@ void Decoder::Decode() { if (!frame.get()) { LOG_ERROR(HW_GPU, - "Nvdec {} failed to decode interlaced frame for top 0x{:X} bottom 0x{:X}", id, + "Nvdec {} failed to decode interlaced frame for top {:#X} bottom 0x{:X}", id, luma_top, luma_bottom); } @@ -59,7 +59,7 @@ void Decoder::Decode() { auto [luma_offset, chroma_offset] = GetProgressiveOffsets(); if (!frame.get()) { - LOG_ERROR(HW_GPU, "Nvdec {} failed to decode progressive frame for luma 0x{:X}", id, + LOG_ERROR(HW_GPU, "Nvdec {} failed to decode progressive frame for luma {:#X}", id, luma_offset); } diff --git a/src/video_core/host1x/control.cpp b/src/video_core/host1x/control.cpp index bd0ce91609..53b3063557 100644 --- a/src/video_core/host1x/control.cpp +++ b/src/video_core/host1x/control.cpp @@ -1,3 +1,6 @@ +// SPDX-FileCopyrightText: Copyright 2025 Eden Emulator Project +// SPDX-License-Identifier: GPL-3.0-or-later + // SPDX-FileCopyrightText: 2021 yuzu Emulator Project // SPDX-License-Identifier: GPL-3.0-or-later @@ -21,7 +24,7 @@ void Control::ProcessMethod(Method method, u32 argument) { Execute(argument); break; default: - UNIMPLEMENTED_MSG("Control method 0x{:X}", static_cast(method)); + UNIMPLEMENTED_MSG("Control method {:#X}", static_cast(method)); break; } } diff --git a/src/video_core/host1x/vic.cpp b/src/video_core/host1x/vic.cpp index 3ad56bb80c..0f821eb397 100644 --- a/src/video_core/host1x/vic.cpp +++ b/src/video_core/host1x/vic.cpp @@ -1,3 +1,6 @@ +// SPDX-FileCopyrightText: Copyright 2025 Eden Emulator Project +// SPDX-License-Identifier: GPL-3.0-or-later + // SPDX-FileCopyrightText: Copyright 2020 yuzu Emulator Project // SPDX-License-Identifier: GPL-2.0-or-later @@ -105,7 +108,7 @@ Vic::~Vic() { } void Vic::ProcessMethod(u32 method, u32 arg) { - LOG_TRACE(HW_GPU, "Vic {} method 0x{:X}", id, static_cast(method)); + LOG_TRACE(HW_GPU, "Vic {} method {:#X}", id, static_cast(method)); regs.reg_array[method] = arg; switch (static_cast(method * sizeof(u32))) { @@ -142,7 +145,7 @@ void Vic::Execute() { auto frame = frame_queue.GetFrame(nvdec_id, luma_offset); if (!frame.get()) { - LOG_ERROR(HW_GPU, "Vic {} failed to get frame with offset 0x{:X}", id, luma_offset); + LOG_ERROR(HW_GPU, "Vic {} failed to get frame with offset {:#X}", id, luma_offset); continue; } @@ -999,9 +1002,9 @@ void Vic::WriteY8__V8U8_N420(const OutputSurfaceConfig& output_surface_config) { LOG_TRACE( HW_GPU, "Writing Y8__V8U8_N420 swizzled frame\n" - "\tinput surface {}x{} stride {} size 0x{:X}\n" - "\toutput luma {}x{} stride {} size 0x{:X} block height {} swizzled size 0x{:X}\n", - "\toutput chroma {}x{} stride {} size 0x{:X} block height {} swizzled size 0x{:X}", + "\tinput surface {}x{} stride {} size {:#X}\n" + "\toutput luma {}x{} stride {} size {:#X} block height {} swizzled size 0x{:X}\n", + "\toutput chroma {}x{} stride {} size {:#X} block height {} swizzled size 0x{:X}", surface_width, surface_height, surface_stride * BytesPerPixel, surface_stride * surface_height * BytesPerPixel, out_luma_width, out_luma_height, out_luma_stride, out_luma_size, block_height, out_luma_swizzle_size, out_chroma_width, @@ -1041,9 +1044,9 @@ void Vic::WriteY8__V8U8_N420(const OutputSurfaceConfig& output_surface_config) { LOG_TRACE( HW_GPU, "Writing Y8__V8U8_N420 swizzled frame\n" - "\tinput surface {}x{} stride {} size 0x{:X}\n" - "\toutput luma {}x{} stride {} size 0x{:X} block height {} swizzled size 0x{:X}\n", - "\toutput chroma {}x{} stride {} size 0x{:X} block height {} swizzled size 0x{:X}", + "\tinput surface {}x{} stride {} size {:#X}\n" + "\toutput luma {}x{} stride {} size {:#X} block height {} swizzled size 0x{:X}\n", + "\toutput chroma {}x{} stride {} size {:#X} block height {} swizzled size 0x{:X}", surface_width, surface_height, surface_stride * BytesPerPixel, surface_stride * surface_height * BytesPerPixel, out_luma_width, out_luma_height, out_luma_stride, out_luma_size, out_chroma_width, out_chroma_height, out_chroma_stride, @@ -1212,8 +1215,8 @@ void Vic::WriteABGR(const OutputSurfaceConfig& output_surface_config) { LOG_TRACE( HW_GPU, "Writing ABGR swizzled frame\n" - "\tinput surface {}x{} stride {} size 0x{:X}\n" - "\toutput surface {}x{} stride {} size 0x{:X} block height {} swizzled size 0x{:X}", + "\tinput surface {}x{} stride {} size {:#X}\n" + "\toutput surface {}x{} stride {} size {:#X} block height {} swizzled size 0x{:X}", surface_width, surface_height, surface_stride * BytesPerPixel, surface_stride * surface_height * BytesPerPixel, out_luma_width, out_luma_height, out_luma_stride, out_luma_size, block_height, out_swizzle_size); @@ -1237,8 +1240,8 @@ void Vic::WriteABGR(const OutputSurfaceConfig& output_surface_config) { case BLK_KIND::PITCH: { LOG_TRACE(HW_GPU, "Writing ABGR pitch frame\n" - "\tinput surface {}x{} stride {} size 0x{:X}" - "\toutput surface {}x{} stride {} size 0x{:X}", + "\tinput surface {}x{} stride {} size {:#X}" + "\toutput surface {}x{} stride {} size {:#X}", surface_width, surface_height, surface_stride, surface_stride * surface_height * BytesPerPixel, out_luma_width, out_luma_height, out_luma_stride, out_luma_size); diff --git a/src/video_core/texture_cache/formatter.cpp b/src/video_core/texture_cache/formatter.cpp index 2b7e0df72a..b48afee0c5 100644 --- a/src/video_core/texture_cache/formatter.cpp +++ b/src/video_core/texture_cache/formatter.cpp @@ -1,3 +1,6 @@ +// SPDX-FileCopyrightText: Copyright 2025 Eden Emulator Project +// SPDX-License-Identifier: GPL-3.0-or-later + // SPDX-FileCopyrightText: Copyright 2020 yuzu Emulator Project // SPDX-License-Identifier: GPL-2.0-or-later @@ -60,25 +63,25 @@ std::string Name(const ImageViewBase& image_view, GPUVAddr addr) { const std::string level = num_levels > 1 ? fmt::format(":{}", num_levels) : ""; switch (image_view.type) { case ImageViewType::e1D: - return fmt::format("ImageView 1D 0x{:X} {}{}", addr, width, level); + return fmt::format("ImageView 1D {:#X} {}{}", addr, width, level); case ImageViewType::e2D: - return fmt::format("ImageView 2D 0x{:X} {}x{}{}", addr, width, height, level); + return fmt::format("ImageView 2D {:#X} {}x{}{}", addr, width, height, level); case ImageViewType::Cube: - return fmt::format("ImageView Cube 0x{:X} {}x{}{}", addr, width, height, level); + return fmt::format("ImageView Cube {:#X} {}x{}{}", addr, width, height, level); case ImageViewType::e3D: - return fmt::format("ImageView 3D 0x{:X} {}x{}x{}{}", addr, width, height, depth, level); + return fmt::format("ImageView 3D {:#X} {}x{}x{}{}", addr, width, height, depth, level); case ImageViewType::e1DArray: - return fmt::format("ImageView 1DArray 0x{:X} {}{}|{}", addr, width, level, num_layers); + return fmt::format("ImageView 1DArray {:#X} {}{}|{}", addr, width, level, num_layers); case ImageViewType::e2DArray: - return fmt::format("ImageView 2DArray 0x{:X} {}x{}{}|{}", addr, width, height, level, + return fmt::format("ImageView 2DArray {:#X} {}x{}{}|{}", addr, width, height, level, num_layers); case ImageViewType::CubeArray: - return fmt::format("ImageView CubeArray 0x{:X} {}x{}{}|{}", addr, width, height, level, + return fmt::format("ImageView CubeArray {:#X} {}x{}{}|{}", addr, width, height, level, num_layers); case ImageViewType::Rect: - return fmt::format("ImageView Rect 0x{:X} {}x{}{}", addr, width, height, level); + return fmt::format("ImageView Rect {:#X} {}x{}{}", addr, width, height, level); case ImageViewType::Buffer: - return fmt::format("BufferView 0x{:X} {}", addr, width); + return fmt::format("BufferView {:#X} {}", addr, width); } return "Invalid"; } From 7f482d0730a8e954ab6f6dc6e18f2c1ed09a0ebb Mon Sep 17 00:00:00 2001 From: MaranBr Date: Wed, 27 Aug 2025 23:02:46 +0200 Subject: [PATCH 27/39] [core] Add option to control Host MMU Emulation (#324) This adds an option to enable or disable Host MMU Emulation [Android/PC], brings better config per-game handling with Disable Buffer Reorder, disables Flush Debug Lines by Log, option which was enabled by default on Android/PC taxing performance and translates to all supported languages the recent changes. Leaves room for NCE improvements in the foreseable future. Co-authored-by: crueter Co-authored-by: PavelBARABANOV Reviewed-on: https://git.eden-emu.dev/eden-emu/eden/pulls/324 Reviewed-by: crueter Reviewed-by: CamilleLaVey Co-authored-by: MaranBr Co-committed-by: MaranBr --- .../features/settings/model/BooleanSetting.kt | 1 + .../settings/model/view/SettingsItem.kt | 7 +++++++ .../settings/ui/SettingsFragmentPresenter.kt | 1 + .../app/src/main/res/values-ar/strings.xml | 2 ++ .../app/src/main/res/values-ckb/strings.xml | 2 ++ .../app/src/main/res/values-cs/strings.xml | 2 ++ .../app/src/main/res/values-de/strings.xml | 2 ++ .../app/src/main/res/values-es/strings.xml | 2 ++ .../app/src/main/res/values-fa/strings.xml | 2 ++ .../app/src/main/res/values-fr/strings.xml | 2 ++ .../app/src/main/res/values-he/strings.xml | 2 ++ .../app/src/main/res/values-hu/strings.xml | 2 ++ .../app/src/main/res/values-id/strings.xml | 2 ++ .../app/src/main/res/values-it/strings.xml | 2 ++ .../app/src/main/res/values-ja/strings.xml | 2 ++ .../app/src/main/res/values-ko/strings.xml | 2 ++ .../app/src/main/res/values-nb/strings.xml | 2 ++ .../app/src/main/res/values-pl/strings.xml | 2 ++ .../src/main/res/values-pt-rBR/strings.xml | 2 ++ .../src/main/res/values-pt-rPT/strings.xml | 2 ++ .../app/src/main/res/values-ru/strings.xml | 2 ++ .../app/src/main/res/values-sr/strings.xml | 2 ++ .../app/src/main/res/values-uk/strings.xml | 2 ++ .../app/src/main/res/values-vi/strings.xml | 2 ++ .../src/main/res/values-zh-rCN/strings.xml | 2 ++ .../src/main/res/values-zh-rTW/strings.xml | 2 ++ .../app/src/main/res/values/strings.xml | 2 ++ src/common/settings.cpp | 6 ++++++ src/common/settings.h | 21 ++++++++++++++++--- src/core/arm/dynarmic/arm_dynarmic_32.cpp | 10 ++++++++- src/core/arm/dynarmic/arm_dynarmic_64.cpp | 8 +++++++ src/yuzu/configuration/configure_cpu.cpp | 14 ++++++------- src/yuzu/configuration/configure_cpu.h | 2 +- src/yuzu/configuration/shared_translation.cpp | 2 ++ 34 files changed, 108 insertions(+), 12 deletions(-) diff --git a/src/android/app/src/main/java/org/yuzu/yuzu_emu/features/settings/model/BooleanSetting.kt b/src/android/app/src/main/java/org/yuzu/yuzu_emu/features/settings/model/BooleanSetting.kt index 21a159676d..d91c026acf 100644 --- a/src/android/app/src/main/java/org/yuzu/yuzu_emu/features/settings/model/BooleanSetting.kt +++ b/src/android/app/src/main/java/org/yuzu/yuzu_emu/features/settings/model/BooleanSetting.kt @@ -18,6 +18,7 @@ enum class BooleanSetting(override val key: String) : AbstractBooleanSetting { USE_FAST_CPU_TIME("use_fast_cpu_time"), USE_CUSTOM_CPU_TICKS("use_custom_cpu_ticks"), SKIP_CPU_INNER_INVALIDATION("skip_cpu_inner_invalidation"), + CPUOPT_UNSAFE_HOST_MMU("cpuopt_unsafe_host_mmu"), USE_DOCKED_MODE("use_docked_mode"), USE_AUTO_STUB("use_auto_stub"), RENDERER_USE_DISK_SHADER_CACHE("use_disk_shader_cache"), diff --git a/src/android/app/src/main/java/org/yuzu/yuzu_emu/features/settings/model/view/SettingsItem.kt b/src/android/app/src/main/java/org/yuzu/yuzu_emu/features/settings/model/view/SettingsItem.kt index 062038aa44..a689b6ce76 100644 --- a/src/android/app/src/main/java/org/yuzu/yuzu_emu/features/settings/model/view/SettingsItem.kt +++ b/src/android/app/src/main/java/org/yuzu/yuzu_emu/features/settings/model/view/SettingsItem.kt @@ -673,6 +673,13 @@ abstract class SettingsItem( descriptionId = R.string.skip_cpu_inner_invalidation_description ) ) + put( + SwitchSetting( + BooleanSetting.CPUOPT_UNSAFE_HOST_MMU, + titleId = R.string.cpuopt_unsafe_host_mmu, + descriptionId = R.string.cpuopt_unsafe_host_mmu_description + ) + ) put( SwitchSetting( BooleanSetting.RENDERER_REACTIVE_FLUSHING, diff --git a/src/android/app/src/main/java/org/yuzu/yuzu_emu/features/settings/ui/SettingsFragmentPresenter.kt b/src/android/app/src/main/java/org/yuzu/yuzu_emu/features/settings/ui/SettingsFragmentPresenter.kt index 672bcd492c..14d62ceec3 100644 --- a/src/android/app/src/main/java/org/yuzu/yuzu_emu/features/settings/ui/SettingsFragmentPresenter.kt +++ b/src/android/app/src/main/java/org/yuzu/yuzu_emu/features/settings/ui/SettingsFragmentPresenter.kt @@ -466,6 +466,7 @@ class SettingsFragmentPresenter( add(BooleanSetting.USE_CUSTOM_CPU_TICKS.key) add(IntSetting.CPU_TICKS.key) add(BooleanSetting.SKIP_CPU_INNER_INVALIDATION.key) + add(BooleanSetting.CPUOPT_UNSAFE_HOST_MMU.key) add(BooleanSetting.USE_LRU_CACHE.key) add(BooleanSetting.CORE_SYNC_CORE_SPEED.key) add(BooleanSetting.SYNC_MEMORY_OPERATIONS.key) diff --git a/src/android/app/src/main/res/values-ar/strings.xml b/src/android/app/src/main/res/values-ar/strings.xml index 155d165f2d..7373abdf76 100644 --- a/src/android/app/src/main/res/values-ar/strings.xml +++ b/src/android/app/src/main/res/values-ar/strings.xml @@ -117,6 +117,8 @@ دورات تخطي إبطال ذاكرة التخزين المؤقت الداخلية للوحدة المركزية يتخطى بعض عمليات إبطال ذاكرة التخزين المؤقت أثناء تحديثات الذاكرة، مما يقلل استخدام المعالج ويحسن أدائه. قد يسبب هذا أعطالاً أو تعطلًا في بعض الألعاب. + تمكين محاكاة MMU المضيف + يعمل هذا التحسين على تسريع وصول الذاكرة بواسطة البرنامج الضيف. يؤدي تمكينه إلى إجراء عمليات قراءة/كتابة ذاكرة الضيف مباشرة في الذاكرة والاستفادة من MMU المضيف. يؤدي تعطيل هذا إلى إجبار جميع عمليات الوصول إلى الذاكرة على استخدام محاكاة MMU البرمجية. مستوى DMA يتحكم في دقة تحديد مستوى DMA. الدقة الأعلى يمكنها إصلاح بعض المشاكل في بعض الألعاب، ولكنها قد تؤثر أيضًا على الأداء في بعض الحالات. إذا كنت غير متأكد، اتركه على الوضع الافتراضي. diff --git a/src/android/app/src/main/res/values-ckb/strings.xml b/src/android/app/src/main/res/values-ckb/strings.xml index 1845dbbade..221a197843 100644 --- a/src/android/app/src/main/res/values-ckb/strings.xml +++ b/src/android/app/src/main/res/values-ckb/strings.xml @@ -126,6 +126,8 @@ تیک بازنەکردنی ناوەکی CPU هەندێک لە بازنەکردنەکانی هەڵگر لە کاتی نوێکردنەوەی بیرگە دەنێرێت، کەمکردنەوەی بەکارهێنانی CPU و باشترکردنی کارایی. لەوانەیە لە هەندێک یاری کێشە درووست بکات. + چالاککردنی میمیکردنی MMU میواندە + ئەم باشکردنە خێرایی دەستکەوتنی بیرگە لەلایەن پرۆگرامی میوانەکە زیاد دەکات. چالاککردنی وای لێدەکات کە خوێندنەوە/نووسینەکانی بیرگەی میوانەکە ڕاستەوخۆ لە بیرگە ئەنجام بدرێت و میمیکردنی MMU میواندە بەکاربهێنێت. ناچالاککردنی ئەمە هەموو دەستکەوتنەکانی بیرگە ڕەت دەکاتەوە لە بەکارهێنانی میمیکردنی MMU نەرمەکاڵا. ئاستی DMA کۆنتڕۆڵی وردی ڕێکخستنی DMA دەکات. وردی زیاتر دەتوانێ هەندێک کێشە لە هەندێک یاری چارەسەر بکات، بەڵام لە هەندێک حاڵەتدا کاریگەری لەسەر کارایی هەیە. ئەگەر دڵنیا نیت، بە ڕێکخستنی بنەڕەتی بێڵە. diff --git a/src/android/app/src/main/res/values-cs/strings.xml b/src/android/app/src/main/res/values-cs/strings.xml index 484ba1fc5f..61e389f9fc 100644 --- a/src/android/app/src/main/res/values-cs/strings.xml +++ b/src/android/app/src/main/res/values-cs/strings.xml @@ -125,6 +125,8 @@ Takty Přeskočit vnitřní invalidaci CPU Přeskočí některé invalidace mezipaměti na straně CPU během aktualizací paměti, čímž sníží zatížení CPU a zlepší jeho výkon. Může způsobit chyby nebo pády v některých hrách. + Povolit emulaci hostitelské MMU + Tato optimalizace zrychluje přístup do paměti hostovaného programu. Její povolení způsobí, že čtení a zápisy do paměti hosta se provádějí přímo v paměti a využívají hostitelskou MMU. Zakázání této funkce vynutí použití softwarové emulace MMU pro všechny přístupy do paměti. Úroveň DMA Ovládá přesnost DMA. Vyšší přesnost může opravit problémy v některých hrách, ale může také ovlivnit výkon. Pokud si nejste jisti, ponechejte výchozí nastavení. diff --git a/src/android/app/src/main/res/values-de/strings.xml b/src/android/app/src/main/res/values-de/strings.xml index 821ba56399..bff0b0379e 100644 --- a/src/android/app/src/main/res/values-de/strings.xml +++ b/src/android/app/src/main/res/values-de/strings.xml @@ -126,6 +126,8 @@ Ticks CPU-interne Invalidierung überspringen Überspringt bestimmte Cache-Invalidierungen auf CPU-Seite während Speicherupdates, reduziert die CPU-Auslastung und verbessert die Leistung. Kann in einigen Spielen zu Fehlern oder Abstürzen führen. + Host-MMU-Emulation aktivieren + Diese Optimierung beschleunigt Speicherzugriffe durch das Gastprogramm. Wenn aktiviert, erfolgen Speicherlese- und -schreibvorgänge des Gastes direkt im Speicher und nutzen die MMU des Hosts. Das Deaktivieren erzwingt die Verwendung der Software-MMU-Emulation für alle Speicherzugriffe. DMA-Level Steuert die DMA-Präzisionsgenauigkeit. Eine höhere Präzision kann Probleme in einigen Spielen beheben, kann aber in einigen Fällen auch die Leistung beeinträchtigen. Im Zweifel auf „Standard“ belassen. diff --git a/src/android/app/src/main/res/values-es/strings.xml b/src/android/app/src/main/res/values-es/strings.xml index 9db08e1425..888d6d1684 100644 --- a/src/android/app/src/main/res/values-es/strings.xml +++ b/src/android/app/src/main/res/values-es/strings.xml @@ -126,6 +126,8 @@ Ticks Omitir invalidación interna de la CPU Omite ciertas invalidaciones de caché durante actualizaciones de memoria, reduciendo el uso de CPU y mejorando su rendimiento. Puede causar fallos en algunos juegos. + Habilitar emulación de MMU del host + Esta optimización acelera los accesos a la memoria por parte del programa invitado. Al habilitarla, las lecturas/escrituras de memoria del invitado se realizan directamente en la memoria y utilizan la MMU del host. Deshabilitar esto obliga a que todos los accesos a la memoria utilicen la emulación de MMU por software. Nivel de DMA Controla la precisión del DMA. Una mayor precisión puede solucionar problemas en algunos juegos, pero también puede afectar el rendimiento en algunos casos. Si no está seguro, déjelo en Predeterminado. diff --git a/src/android/app/src/main/res/values-fa/strings.xml b/src/android/app/src/main/res/values-fa/strings.xml index 91fa4bd5c2..60b1626aa5 100644 --- a/src/android/app/src/main/res/values-fa/strings.xml +++ b/src/android/app/src/main/res/values-fa/strings.xml @@ -126,6 +126,8 @@ تیک‌ها رد کردن ابطال داخلی CPU بعضی ابطال‌های حافظه نهان در هنگام به‌روزرسانی‌های حافظه را رد می‌کند، استفاده از CPU را کاهش داده و عملکرد آن را بهبود می‌بخشد. ممکن است در برخی بازی‌ها باعث مشکلات یا خرابی شود. + فعال‌سازی شبیه‌سازی MMU میزبان + این بهینه‌سازی دسترسی‌های حافظه توسط برنامه میهمان را تسریع می‌کند. فعال‌سازی آن باعث می‌شود خواندن/نوشتن حافظه میهمان مستقیماً در حافظه انجام شود و از MMU میزبان استفاده کند. غیرفعال کردن این قابلیت، همه دسترسی‌های حافظه را مجبور به استفاده از شبیه‌سازی نرم‌افزاری MMU می‌کند. سطح DMA دقت صحت DMA را کنترل می کند. دقت بالاتر می تواند مشکلات برخی بازی ها را برطرف کند، اما در برخی موارد نیز می تواند بر عملکرد تأثیر بگذارد. اگر مطمئن نیستید، آن را روی پیش فرض بگذارید. diff --git a/src/android/app/src/main/res/values-fr/strings.xml b/src/android/app/src/main/res/values-fr/strings.xml index a7139ddbf6..fde02d1aa8 100644 --- a/src/android/app/src/main/res/values-fr/strings.xml +++ b/src/android/app/src/main/res/values-fr/strings.xml @@ -126,6 +126,8 @@ Ticks Ignorer l\'invalidation interne du CPU Ignore certaines invalidations de cache côté CPU lors des mises à jour mémoire, réduisant l\'utilisation du CPU et améliorant ses performances. Peut causer des bugs ou plantages sur certains jeux. + Activer l\'émulation de la MMU hôte + Cette optimisation accélère les accès mémoire par le programme invité. L\'activer entraîne que les lectures/écritures mémoire de l\'invité sont effectuées directement en mémoire et utilisent la MMU de l\'hôte. Désactiver cela force tous les accès mémoire à utiliser l\'émulation logicielle de la MMU. Niveau DMA Contrôle la précision du DMA. Une précision plus élevée peut résoudre les problèmes dans certains jeux, mais peut aussi affecter les performances dans certains cas. Si vous n\'êtes pas sûr, laissez-la sur Défaut. diff --git a/src/android/app/src/main/res/values-he/strings.xml b/src/android/app/src/main/res/values-he/strings.xml index 63aaee043e..59312086e9 100644 --- a/src/android/app/src/main/res/values-he/strings.xml +++ b/src/android/app/src/main/res/values-he/strings.xml @@ -127,6 +127,8 @@ טיקים דלג על איפוס מטמון פנימי של המעבד מדלג על איפוסי מטמון מסוימים במהלך עדכוני זיכרון, מפחית שימוש במעבד ומשפר ביצועים. עלול לגרום לתקלות או קריסות בחלק מהמשחקים. + הפעל אמולציית MMU מארח + אופטימיזציה זו מאיצה את גישת הזיכרון על ידי התוכנית האורחת. הפעלתה גורמת לכך שפעולות קריאה/כתיבה לזיכרון האורח מתבצעות ישירות לזיכרון ומשתמשות ב-MMU של המארח. השבתת זאת מאלצת את כל גישות הזיכרון להשתמש באמולציית MMU תוכנתית. רמת DMA שולטת בדיוק הדיוק של DMA. דיוק גבוה יותר יכול לתקן בעיות בחלק מהמשחקים, אך הוא עלול גם להשפיע על הביצועים במקרים מסוימים. אם אינך בטוח, השאר ברירת מחדל. diff --git a/src/android/app/src/main/res/values-hu/strings.xml b/src/android/app/src/main/res/values-hu/strings.xml index 15dd00997b..f95e2d3f97 100644 --- a/src/android/app/src/main/res/values-hu/strings.xml +++ b/src/android/app/src/main/res/values-hu/strings.xml @@ -126,6 +126,8 @@ Tick-ek CPU belső érvénytelenítés kihagyása Kihagy néhány CPU-oldali gyorsítótár-érvénytelenítést memóriafrissítések közben, csökkentve a CPU használatát és javítva a teljesítményt. Néhány játékban hibákat vagy összeomlást okozhat. + Gazda MMU emuláció engedélyezése + Ez az optimalizáció gyorsítja a vendégprogram memória-hozzáférését. Engedélyezése esetén a vendég memóriaolvasási/írási műveletei közvetlenül a memóriában történnek, és kihasználják a gazda MMU-ját. Letiltás esetén minden memória-hozzáférés a szoftveres MMU emulációt használja. DMA szint Szabályozza a DMA pontosságát. A magasabb pontosság megoldhat néhány játék problémáit, de bizonyos esetekben befolyásolhatja a teljesítményt. Ha bizonytalan, hagyja Alapértelmezett beállításnál. diff --git a/src/android/app/src/main/res/values-id/strings.xml b/src/android/app/src/main/res/values-id/strings.xml index 7daa4a8e94..dae77d53af 100644 --- a/src/android/app/src/main/res/values-id/strings.xml +++ b/src/android/app/src/main/res/values-id/strings.xml @@ -126,6 +126,8 @@ Ticks Lewati Pembatalan Internal CPU Melewati beberapa pembatalan cache sisi CPU selama pembaruan memori, mengurangi penggunaan CPU dan meningkatkan kinerjanya. Mungkin menyebabkan gangguan atau crash pada beberapa game. + Aktifkan Emulasi MMU Host + Optimasi ini mempercepat akses memori oleh program tamu. Mengaktifkannya menyebabkan pembacaan/penulisan memori tamu dilakukan langsung ke memori dan memanfaatkan MMU Host. Menonaktifkan ini memaksa semua akses memori menggunakan Emulasi MMU Perangkat Lunak. Level DMA Mengontrol akurasi presisi DMA. Presisi yang lebih tinggi dapat memperbaiki masalah di beberapa game, tetapi juga dapat memengaruhi performa dalam beberapa kasus. Jika tidak yakin, biarkan di Bawaan. diff --git a/src/android/app/src/main/res/values-it/strings.xml b/src/android/app/src/main/res/values-it/strings.xml index 66446eae34..dd184e9d9a 100644 --- a/src/android/app/src/main/res/values-it/strings.xml +++ b/src/android/app/src/main/res/values-it/strings.xml @@ -126,6 +126,8 @@ Tick Salta invalidamento interno CPU Salta alcuni invalidamenti della cache lato CPU durante gli aggiornamenti di memoria, riducendo l\'uso della CPU e migliorandone le prestazioni. Potrebbe causare glitch o crash in alcuni giochi. + Abilita emulazione MMU host + Questa ottimizzazione accelera gli accessi alla memoria da parte del programma guest. Abilitandola, le letture/scritture della memoria guest vengono eseguite direttamente in memoria e sfruttano la MMU host. Disabilitandola, tutti gli accessi alla memoria sono costretti a utilizzare l\'emulazione software della MMU. Livello DMA Controlla la precisione del DMA. Una precisione più alta può risolvere problemi in alcuni giochi, ma in alcuni casi può influire sulle prestazioni. Se non sei sicuro, lascia su Predefinito. diff --git a/src/android/app/src/main/res/values-ja/strings.xml b/src/android/app/src/main/res/values-ja/strings.xml index 2090aa5f74..873d433fc0 100644 --- a/src/android/app/src/main/res/values-ja/strings.xml +++ b/src/android/app/src/main/res/values-ja/strings.xml @@ -126,6 +126,8 @@ ティック CPU内部無効化をスキップ メモリ更新時のCPU側キャッシュ無効化をスキップし、CPU使用率を減らして性能を向上させます。一部のゲームで不具合やクラッシュが発生する可能性があります。 + ホストMMUエミュレーションを有効化 + この最適化により、ゲストプログラムによるメモリアクセスが高速化されます。有効にすると、ゲストのメモリ読み書きが直接メモリ内で実行され、ホストのMMUを利用します。無効にすると、すべてのメモリアクセスでソフトウェアMMUエミュレーションが使用されます。 DMAレベル DMAの精度を制御します。精度を高くすると一部のゲームの問題が修正される場合がありますが、場合によってはパフォーマンスに影響を与える可能性もあります。不明な場合は、デフォルトのままにしてください。 diff --git a/src/android/app/src/main/res/values-ko/strings.xml b/src/android/app/src/main/res/values-ko/strings.xml index d73dc53987..3f3a4a96c0 100644 --- a/src/android/app/src/main/res/values-ko/strings.xml +++ b/src/android/app/src/main/res/values-ko/strings.xml @@ -126,6 +126,8 @@ CPU 내부 무효화 건너뛰기 메모리 업데이트 시 일부 CPU 측 캐시 무효화를 건너뛰어 CPU 사용량을 줄이고 성능을 향상시킵니다. 일부 게임에서 오류 또는 충돌을 일으킬 수 있습니다. + 호스트 MMU 에뮬레이션 사용 + 이 최적화는 게스트 프로그램의 메모리 접근 속도를 높입니다. 활성화하면 게스트의 메모리 읽기/쓰기가 메모리에서 직접 수행되고 호스트의 MMU를 활용합니다. 비활성화하면 모든 메모리 접근에 소프트웨어 MMU 에뮬레이션을 사용하게 됩니다. DMA 수준 DMA 정밀도를 제어합니다. 높은 정밀도는 일부 게임의 문제를 해결할 수 있지만 경우에 따라 성능에 영향을 미칠 수도 있습니다. 확실하지 않다면 기본값으로 두세요. diff --git a/src/android/app/src/main/res/values-nb/strings.xml b/src/android/app/src/main/res/values-nb/strings.xml index 61fa5792e5..1e898fca79 100644 --- a/src/android/app/src/main/res/values-nb/strings.xml +++ b/src/android/app/src/main/res/values-nb/strings.xml @@ -126,6 +126,8 @@ Takter Hopp over CPU intern invalidering Hopper over enkelte CPU-side cache-invalideringer under minneoppdateringer, reduserer CPU-bruk og forbedrer ytelsen. Kan forårsake feil eller krasj i noen spill. + Aktiver verts-MMU-emulering + Denne optimaliseringen fremskynder minnetilgang av gjesteprogrammet. Hvis aktivert, utføres gjestens minnelesing/skriving direkte i minnet og bruker vertens MMU. Deaktivering tvinger alle minnetilganger til å bruke programvarebasert MMU-emulering. DMA-nivå Styrer DMA-presisjonsnøyaktigheten. Høyere presisjon kan fikse problemer i noen spill, men kan også påvirke ytelsen i noen tilfeller. Hvis du er usikker, la den stå på Standard. diff --git a/src/android/app/src/main/res/values-pl/strings.xml b/src/android/app/src/main/res/values-pl/strings.xml index d640112fca..724d7608b6 100644 --- a/src/android/app/src/main/res/values-pl/strings.xml +++ b/src/android/app/src/main/res/values-pl/strings.xml @@ -126,6 +126,8 @@ Takty Pomiń wewnętrzne unieważnienie CPU Pomija niektóre unieważnienia pamięci podręcznej po stronie CPU podczas aktualizacji pamięci, zmniejszając użycie CPU i poprawiając jego wydajność. Może powodować błędy lub awarie w niektórych grach. + Włącz emulację MMU hosta + Ta optymalizacja przyspiesza dostęp do pamięci przez program gościa. Włączenie powoduje, że odczyty/zapisy pamięci gościa są wykonywane bezpośrednio w pamięci i wykorzystują MMU hosta. Wyłączenie wymusza użycie programowej emulacji MMU dla wszystkich dostępów do pamięci. Poziom DMA Kontroluje dokładność precyzji DMA. Wyższy poziom może naprawić problemy w niektórych grach, ale może również wpłynąć na wydajność. Jeśli nie jesteś pewien, pozostaw wartość «Domyślny». diff --git a/src/android/app/src/main/res/values-pt-rBR/strings.xml b/src/android/app/src/main/res/values-pt-rBR/strings.xml index d0ec24f453..a3fd3fe13a 100644 --- a/src/android/app/src/main/res/values-pt-rBR/strings.xml +++ b/src/android/app/src/main/res/values-pt-rBR/strings.xml @@ -126,6 +126,8 @@ Ticks Pular invalidação interna da CPU Ignora algumas invalidações de cache do lado da CPU durante atualizações de memória, reduzindo o uso da CPU e melhorando seu desempenho. Pode causar falhas ou travamentos em alguns jogos. + Ativar Emulação de MMU do Host + Esta otimização acelera os acessos à memória pelo programa convidado. Ativar isso faz com que as leituras/gravações de memória do convidado sejam feitas diretamente na memória e utilizem a MMU do Host. Desativar isso força todos os acessos à memória a usarem a Emulação de MMU por Software. Nível DMA Controla a precisão do DMA. Maior precisão pode corrigir problemas em alguns jogos, mas também pode impactar o desempenho em alguns casos. Se não tiver certeza, deixe em Padrão. diff --git a/src/android/app/src/main/res/values-pt-rPT/strings.xml b/src/android/app/src/main/res/values-pt-rPT/strings.xml index 4e0fc4167a..7adce075cf 100644 --- a/src/android/app/src/main/res/values-pt-rPT/strings.xml +++ b/src/android/app/src/main/res/values-pt-rPT/strings.xml @@ -126,6 +126,8 @@ Ticks Ignorar invalidação interna da CPU Ignora algumas invalidações de cache do lado da CPU durante atualizações de memória, reduzindo a utilização da CPU e melhorando o desempenho. Pode causar falhas ou crashes em alguns jogos. + Ativar Emulação de MMU do Anfitrião + Esta otimização acelera os acessos à memória pelo programa convidado. Ativar faz com que as leituras/escritas de memória do convidado sejam efetuadas diretamente na memória e utilizem a MMU do Anfitrião. Desativar força todos os acessos à memória a usar a Emulação de MMU por Software. Nível DMA Controla a precisão do DMA. Maior precisão pode corrigir problemas em alguns jogos, mas também pode afetar o desempenho nalguns casos. Se não tiver a certeza, deixe em Predefinido. diff --git a/src/android/app/src/main/res/values-ru/strings.xml b/src/android/app/src/main/res/values-ru/strings.xml index 658286152b..8d02ff7b58 100644 --- a/src/android/app/src/main/res/values-ru/strings.xml +++ b/src/android/app/src/main/res/values-ru/strings.xml @@ -126,6 +126,8 @@ Такты Пропустить внутреннюю инвалидацию ЦП Пропускает некоторые инвалидации кэша на стороне ЦП при обновлениях памяти, уменьшая нагрузку на процессор и повышая производительность. Может вызывать сбои в некоторых играх. + Включить эмуляцию MMU хоста + Эта оптимизация ускоряет доступ к памяти гостевой программой. При включении операции чтения/записи памяти гостя выполняются напрямую в памяти с использованием MMU хоста. Отключение заставляет все обращения к памяти использовать программную эмуляцию MMU. Уровень DMA Управляет точностью DMA. Более высокий уровень может исправить проблемы в некоторых играх, но также может повлиять на производительность. Если не уверены, оставьте значение «По умолчанию». diff --git a/src/android/app/src/main/res/values-sr/strings.xml b/src/android/app/src/main/res/values-sr/strings.xml index 18612333f9..2294033550 100644 --- a/src/android/app/src/main/res/values-sr/strings.xml +++ b/src/android/app/src/main/res/values-sr/strings.xml @@ -119,6 +119,8 @@ Тактови Preskoči unutrašnje poništavanje CPU-a Preskače određena poništavanja keša na strani CPU-a tokom ažuriranja memorije, smanjujući opterećenje procesora i poboljšavajući performanse. Može izazvati greške u nekim igrama. + Омогући емулацију MMU домаћина + Ова оптимизација убрзава приступ меморији од стране гостујућег програма. Укључивање изазива да се читања/уписа меморије госта обављају директно у меморији и користе MMU домаћина. Искључивање присиљава све приступе меморији да користе софтверску емулацију MMU. DMA ниво Контролише тачност DMA прецизности. Виши ниво може да поправи проблеме у неким играма, али може и да утиче на перформансе. Ако нисте сигурни, оставите на «Подразумевано». diff --git a/src/android/app/src/main/res/values-uk/strings.xml b/src/android/app/src/main/res/values-uk/strings.xml index 830e1f0ef9..ebb5493f12 100644 --- a/src/android/app/src/main/res/values-uk/strings.xml +++ b/src/android/app/src/main/res/values-uk/strings.xml @@ -126,6 +126,8 @@ Такти Пропустити внутрішнє інвалідування CPU Пропускає деякі інвалідації кешу на стороні CPU під час оновлення пам\'яті, зменшуючи навантаження на процесор і покращуючи продуктивність. Може спричинити збої в деяких іграх. + Увімкнути емуляцію MMU хоста + Ця оптимізація пришвидшує доступ до пам\'яті гостьовою програмою. Увімкнення призводить до того, що читання/запис пам\'яті гостя виконуються безпосередньо в пам\'яті та використовують MMU хоста. Вимкнення змушує всі звернення до пам\'яті використовувати програмну емуляцію MMU. Рівень DMA Керує точністю DMA. Вищий рівень може виправити проблеми в деяких іграх, але також може вплинути на продуктивність. Якщо не впевнені, залиште значення «Типово». diff --git a/src/android/app/src/main/res/values-vi/strings.xml b/src/android/app/src/main/res/values-vi/strings.xml index 1c656fc7bb..102c720835 100644 --- a/src/android/app/src/main/res/values-vi/strings.xml +++ b/src/android/app/src/main/res/values-vi/strings.xml @@ -126,6 +126,8 @@ Tích Bỏ qua vô hiệu hóa bên trong CPU Bỏ qua một số lần vô hiệu hóa bộ nhớ đệm phía CPU trong khi cập nhật bộ nhớ, giảm mức sử dụng CPU và cải thiện hiệu suất. Có thể gây ra lỗi hoặc treo máy trong một số trò chơi. + Bật giả lập MMU Máy chủ + Tối ưu hóa này tăng tốc độ truy cập bộ nhớ của chương trình khách. Bật nó lên khiến các thao tác đọc/ghi bộ nhớ khách được thực hiện trực tiếp vào bộ nhớ và sử dụng MMU của Máy chủ. Tắt tính năng này buộc tất cả quyền truy cập bộ nhớ phải sử dụng Giả lập MMU Phần mềm. Cấp độ DMA Điều khiển độ chính xác của DMA. Độ chính xác cao hơn có thể sửa lỗi trong một số trò chơi, nhưng cũng có thể ảnh hưởng đến hiệu suất trong một số trường hợp. Nếu không chắc chắn, hãy để ở Mặc định. diff --git a/src/android/app/src/main/res/values-zh-rCN/strings.xml b/src/android/app/src/main/res/values-zh-rCN/strings.xml index f3e7d9282c..a0dab375d0 100644 --- a/src/android/app/src/main/res/values-zh-rCN/strings.xml +++ b/src/android/app/src/main/res/values-zh-rCN/strings.xml @@ -125,6 +125,8 @@ 时钟 跳过CPU内部无效化 在内存更新期间跳过某些CPU端缓存无效化,减少CPU使用率并提高其性能。可能会导致某些游戏出现故障或崩溃。 + 启用主机 MMU 模拟 + 此优化可加速来宾程序的内存访问。启用后,来宾内存读取/写入将直接在内存中执行并利用主机的 MMU。禁用此功能将强制所有内存访问使用软件 MMU 模拟。 DMA 级别 控制 DMA 精度。更高的精度可以修复某些游戏中的问题,但在某些情况下也可能影响性能。如果不确定,请保留为“默认”。 diff --git a/src/android/app/src/main/res/values-zh-rTW/strings.xml b/src/android/app/src/main/res/values-zh-rTW/strings.xml index b6c17745be..851483668a 100644 --- a/src/android/app/src/main/res/values-zh-rTW/strings.xml +++ b/src/android/app/src/main/res/values-zh-rTW/strings.xml @@ -118,6 +118,8 @@ 時脈 跳過CPU內部無效化 在記憶體更新期間跳過某些CPU端快取無效化,減少CPU使用率並提高其性能。可能會導致某些遊戲出現故障或崩潰。 + 啟用主機 MMU 模擬 + 此最佳化可加速來賓程式的記憶體存取。啟用後,來賓記憶體讀取/寫入將直接在記憶體中執行並利用主機的 MMU。停用此功能將強制所有記憶體存取使用軟體 MMU 模擬。 DMA 級別 控制 DMA 精確度。更高的精確度可以修復某些遊戲中的問題,但在某些情況下也可能影響效能。如果不確定,請保留為「預設」。 diff --git a/src/android/app/src/main/res/values/strings.xml b/src/android/app/src/main/res/values/strings.xml index 975bd1741a..f73fc1d9aa 100644 --- a/src/android/app/src/main/res/values/strings.xml +++ b/src/android/app/src/main/res/values/strings.xml @@ -109,6 +109,8 @@ Ticks Skip CPU Inner Invalidation Skips certain CPU-side cache invalidations during memory updates, reducing CPU usage and improving it\'s performance. This may cause glitches or crashes on some games. + Enable Host MMU Emulation + This optimization speeds up memory accesses by the guest program. Enabling it causes guest memory reads/writes to be done directly into memory and make use of Host\'s MMU. Disabling this forces all memory accesses to use Software MMU Emulation. CPU Clock Use Boost (1700MHz) to run at the Switch\'s highest native clock, or Fast (2000MHz) to run at 2x clock. Memory Layout diff --git a/src/common/settings.cpp b/src/common/settings.cpp index 63d46722ea..19140bce0d 100644 --- a/src/common/settings.cpp +++ b/src/common/settings.cpp @@ -158,6 +158,12 @@ bool IsFastmemEnabled() { if (values.cpu_debug_mode) { return static_cast(values.cpuopt_fastmem); } + if (Settings::values.cpu_accuracy.GetValue() == Settings::CpuAccuracy::Unsafe) { + return static_cast(values.cpuopt_unsafe_host_mmu); + } +#if defined(__FreeBSD__) || defined(__OpenBSD__) || defined(__sun__) + return false; +#endif return true; } diff --git a/src/common/settings.h b/src/common/settings.h index b846f41318..27196fbd69 100644 --- a/src/common/settings.h +++ b/src/common/settings.h @@ -299,6 +299,18 @@ struct Values { Category::CpuDebug}; Setting cpuopt_ignore_memory_aborts{linkage, true, "cpuopt_ignore_memory_aborts", Category::CpuDebug}; + + SwitchableSetting cpuopt_unsafe_host_mmu{linkage, +#if defined(__FreeBSD__) || defined(__OpenBSD__) || defined(__sun__) + false, +#else + true, +#endif + "cpuopt_unsafe_host_mmu", + Category::CpuUnsafe, + Specialization::Default, + true, + true}; SwitchableSetting cpuopt_unsafe_unfuse_fma{linkage, true, "cpuopt_unsafe_unfuse_fma", Category::CpuUnsafe}; SwitchableSetting cpuopt_unsafe_reduce_fp_error{ @@ -574,8 +586,11 @@ struct Values { linkage, false, "disable_shader_loop_safety_checks", Category::RendererDebug}; Setting enable_renderdoc_hotkey{linkage, false, "renderdoc_hotkey", Category::RendererDebug}; - Setting disable_buffer_reorder{linkage, false, "disable_buffer_reorder", - Category::RendererDebug}; + SwitchableSetting disable_buffer_reorder{linkage, false, "disable_buffer_reorder", + Category::RendererDebug, + Specialization::Default, + true, + true}; // System SwitchableSetting language_index{linkage, @@ -741,7 +756,7 @@ struct Values { // Miscellaneous Setting log_filter{linkage, "*:Info", "log_filter", Category::Miscellaneous}; - Setting log_flush_lines{linkage, true, "flush_lines", Category::Miscellaneous, Specialization::Default, true, true}; + Setting log_flush_lines{linkage, false, "flush_lines", Category::Miscellaneous, Specialization::Default, true, true}; Setting censor_username{linkage, true, "censor_username", Category::Miscellaneous}; Setting use_dev_keys{linkage, false, "use_dev_keys", Category::Miscellaneous}; Setting first_launch{linkage, true, "first_launch", Category::Miscellaneous}; diff --git a/src/core/arm/dynarmic/arm_dynarmic_32.cpp b/src/core/arm/dynarmic/arm_dynarmic_32.cpp index c6e159cc9c..7123497682 100644 --- a/src/core/arm/dynarmic/arm_dynarmic_32.cpp +++ b/src/core/arm/dynarmic/arm_dynarmic_32.cpp @@ -271,6 +271,10 @@ std::shared_ptr ArmDynarmic32::MakeJit(Common::PageTable* pa // Unsafe optimizations if (Settings::values.cpu_accuracy.GetValue() == Settings::CpuAccuracy::Unsafe) { config.unsafe_optimizations = true; + if (!Settings::values.cpuopt_unsafe_host_mmu) { + config.fastmem_pointer = std::nullopt; + config.fastmem_exclusive_access = false; + } if (Settings::values.cpuopt_unsafe_unfuse_fma) { config.optimizations |= Dynarmic::OptimizationFlag::Unsafe_UnfuseFMA; } @@ -291,13 +295,17 @@ std::shared_ptr ArmDynarmic32::MakeJit(Common::PageTable* pa // Curated optimizations if (Settings::values.cpu_accuracy.GetValue() == Settings::CpuAccuracy::Auto) { config.unsafe_optimizations = true; +#if defined(__FreeBSD__) || defined(__OpenBSD__) || defined(__sun__) + config.fastmem_pointer = std::nullopt; + config.fastmem_exclusive_access = false; +#endif config.optimizations |= Dynarmic::OptimizationFlag::Unsafe_UnfuseFMA; config.optimizations |= Dynarmic::OptimizationFlag::Unsafe_IgnoreStandardFPCRValue; config.optimizations |= Dynarmic::OptimizationFlag::Unsafe_InaccurateNaN; config.optimizations |= Dynarmic::OptimizationFlag::Unsafe_IgnoreGlobalMonitor; } - // Paranoia mode for debugging optimizations + // Paranoid mode for debugging optimizations if (Settings::values.cpu_accuracy.GetValue() == Settings::CpuAccuracy::Paranoid) { config.unsafe_optimizations = false; config.optimizations = Dynarmic::no_optimizations; diff --git a/src/core/arm/dynarmic/arm_dynarmic_64.cpp b/src/core/arm/dynarmic/arm_dynarmic_64.cpp index ba5c608a03..2745aeb862 100644 --- a/src/core/arm/dynarmic/arm_dynarmic_64.cpp +++ b/src/core/arm/dynarmic/arm_dynarmic_64.cpp @@ -330,6 +330,10 @@ std::shared_ptr ArmDynarmic64::MakeJit(Common::PageTable* pa // Unsafe optimizations if (Settings::values.cpu_accuracy.GetValue() == Settings::CpuAccuracy::Unsafe) { config.unsafe_optimizations = true; + if (!Settings::values.cpuopt_unsafe_host_mmu) { + config.fastmem_pointer = std::nullopt; + config.fastmem_exclusive_access = false; + } if (Settings::values.cpuopt_unsafe_unfuse_fma) { config.optimizations |= Dynarmic::OptimizationFlag::Unsafe_UnfuseFMA; } @@ -350,6 +354,10 @@ std::shared_ptr ArmDynarmic64::MakeJit(Common::PageTable* pa // Curated optimizations if (Settings::values.cpu_accuracy.GetValue() == Settings::CpuAccuracy::Auto) { config.unsafe_optimizations = true; +#if defined(__FreeBSD__) || defined(__OpenBSD__) || defined(__sun__) + config.fastmem_pointer = std::nullopt; + config.fastmem_exclusive_access = false; +#endif config.optimizations |= Dynarmic::OptimizationFlag::Unsafe_UnfuseFMA; config.fastmem_address_space_bits = 64; config.optimizations |= Dynarmic::OptimizationFlag::Unsafe_IgnoreGlobalMonitor; diff --git a/src/yuzu/configuration/configure_cpu.cpp b/src/yuzu/configuration/configure_cpu.cpp index 74def6fc60..6407efbb26 100644 --- a/src/yuzu/configuration/configure_cpu.cpp +++ b/src/yuzu/configuration/configure_cpu.cpp @@ -90,15 +90,15 @@ void ConfigureCpu::Setup(const ConfigurationShared::Builder& builder) { unsafe_layout->addWidget(widget); } - UpdateGroup(accuracy_combobox->currentIndex()); - UpdateGroup(backend_combobox->currentIndex()); + UpdateGroup(); } -void ConfigureCpu::UpdateGroup(int index) { - const auto accuracy = static_cast( - combobox_translations.at(Settings::EnumMetadata::Index())[index] - .first); - ui->unsafe_group->setVisible(accuracy == Settings::CpuAccuracy::Unsafe); +void ConfigureCpu::UpdateGroup() +{ + const u32 accuracy = accuracy_combobox->currentIndex(); + const u32 backend = backend_combobox->currentIndex(); + // TODO(crueter): see if this works on NCE + ui->unsafe_group->setVisible(accuracy == (u32) Settings::CpuAccuracy::Unsafe && backend == (u32) Settings::CpuBackend::Dynarmic); } void ConfigureCpu::ApplyConfiguration() { diff --git a/src/yuzu/configuration/configure_cpu.h b/src/yuzu/configuration/configure_cpu.h index 7bbeac4963..098e0e397b 100644 --- a/src/yuzu/configuration/configure_cpu.h +++ b/src/yuzu/configuration/configure_cpu.h @@ -39,7 +39,7 @@ private: void changeEvent(QEvent* event) override; void RetranslateUI(); - void UpdateGroup(int index); + void UpdateGroup(); void Setup(const ConfigurationShared::Builder& builder); diff --git a/src/yuzu/configuration/shared_translation.cpp b/src/yuzu/configuration/shared_translation.cpp index f6d590c0ee..fca4c94893 100644 --- a/src/yuzu/configuration/shared_translation.cpp +++ b/src/yuzu/configuration/shared_translation.cpp @@ -118,6 +118,8 @@ std::unique_ptr InitializeTranslations(QWidget* parent) // Cpu Debug // Cpu Unsafe + INSERT(Settings, cpuopt_unsafe_host_mmu, tr("Enable Host MMU Emulation (fastmem)"), + tr("This optimization speeds up memory accesses by the guest program.\nEnabling it causes guest memory reads/writes to be done directly into memory and make use of Host's MMU.\nDisabling this forces all memory accesses to use Software MMU Emulation.")); INSERT( Settings, cpuopt_unsafe_unfuse_fma, From 8407510f76e9a5105a6bb85a959e86ca6f14a0bc Mon Sep 17 00:00:00 2001 From: lizzie Date: Thu, 28 Aug 2025 01:32:37 +0200 Subject: [PATCH 28/39] [video_core] fix nixOS flake build patch (#339) See https://github.com/NixOS/nixpkgs/pull/406630/files Signed-off-by: lizzie Reviewed-on: https://git.eden-emu.dev/eden-emu/eden/pulls/339 Reviewed-by: crueter Co-authored-by: lizzie Co-committed-by: lizzie --- src/video_core/host1x/vic.cpp | 2 ++ 1 file changed, 2 insertions(+) diff --git a/src/video_core/host1x/vic.cpp b/src/video_core/host1x/vic.cpp index 0f821eb397..18b3077f9a 100644 --- a/src/video_core/host1x/vic.cpp +++ b/src/video_core/host1x/vic.cpp @@ -17,6 +17,8 @@ #elif defined(ARCHITECTURE_arm64) #pragma GCC diagnostic push #pragma GCC diagnostic ignored "-Wimplicit-int-conversion" +#pragma GCC diagnostic ignored "-Wconversion" +#pragma GCC diagnostic ignored "-Wshadow" #include #pragma GCC diagnostic pop #endif From 434bd42a5e0f5b3b37a18c74bf89dcfc58deb826 Mon Sep 17 00:00:00 2001 From: crueter Date: Thu, 28 Aug 2025 01:34:41 +0200 Subject: [PATCH 29/39] [desktop] fix controls dialog text clipping (#336) Signed-off-by: crueter Reviewed-on: https://git.eden-emu.dev/eden-emu/eden/pulls/336 Reviewed-by: CamilleLaVey --- CMakeLists.txt | 4 +- dist/qt_themes/default/style.qss | 54 +++++++++++++++++++ dist/qt_themes/default_dark/style.qss | 26 +++++++++ dist/qt_themes/qdarkstyle/style.qss | 2 +- .../qdarkstyle_midnight_blue/style.qss | 3 +- 5 files changed, 84 insertions(+), 5 deletions(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index dacbc73685..6a8401759d 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -579,8 +579,8 @@ else() find_package(lz4 REQUIRED) find_package(RenderDoc MODULE) find_package(stb MODULE) - find_package(enet 1.3 MODULE) - find_package(Opus 1.3 MODULE) + find_package(enet 1.3 MODULE REQUIRED) + find_package(Opus 1.3 MODULE REQUIRED) find_package(ZLIB 1.2 REQUIRED) find_package(zstd 1.5 REQUIRED) diff --git a/dist/qt_themes/default/style.qss b/dist/qt_themes/default/style.qss index db55b9b490..701086299d 100644 --- a/dist/qt_themes/default/style.qss +++ b/dist/qt_themes/default/style.qss @@ -95,6 +95,60 @@ QPushButton#button_reset_defaults { padding: 4px 8px; } +/* QGroupBox -------------------------------------------------------------- + +https://doc.qt.io/qt-5/stylesheet-examples.html#customizing-qgroupbox + +--------------------------------------------------------------------------- */ +QGroupBox { + border: 1px solid #32414B; + border-radius: 4px; + margin-top: 20px; + padding: 2px; +} + +QGroupBox::title { + subcontrol-origin: margin; + subcontrol-position: top left; + padding-left: 3px; + padding-right: 5px; + padding-top: 2px; +} + +QGroupBox::indicator { + margin-left: 2px; + height: 16px; + width: 16px; +} + +QGroupBox::indicator:unchecked { + border: none; + image: url(":/qss_icons/rc/checkbox_unchecked.png"); +} + +QGroupBox::indicator:unchecked:hover, QGroupBox::indicator:unchecked:focus, QGroupBox::indicator:unchecked:pressed { + border: none; + image: url(":/qss_icons/rc/checkbox_unchecked_focus.png"); +} + +QGroupBox::indicator:unchecked:disabled { + image: url(":/qss_icons/rc/checkbox_unchecked_disabled.png"); +} + +QGroupBox::indicator:checked { + border: none; + image: url(":/qss_icons/rc/checkbox_checked.png"); +} + +QGroupBox::indicator:checked:hover, QGroupBox::indicator:checked:focus, QGroupBox::indicator:checked:pressed { + border: none; + image: url(":/qss_icons/rc/checkbox_checked_focus.png"); +} + +QGroupBox::indicator:checked:disabled { + image: url(":/qss_icons/rc/checkbox_checked_disabled.png"); +} + QWidget#bottomPerGameInput, QWidget#topControllerApplet, QWidget#bottomControllerApplet, diff --git a/dist/qt_themes/default_dark/style.qss b/dist/qt_themes/default_dark/style.qss index 6a3f517cb6..dd224c3322 100644 --- a/dist/qt_themes/default_dark/style.qss +++ b/dist/qt_themes/default_dark/style.qss @@ -697,3 +697,29 @@ QDialog#QtSoftwareKeyboardDialog QPushButton#button_space:disabled, QDialog#QtSoftwareKeyboardDialog QPushButton#button_space_shift:disabled { image: url(:/overlay/osk_button_Y_disabled.png); } + +/* QGroupBox -------------------------------------------------------------- + +https://doc.qt.io/qt-5/stylesheet-examples.html#customizing-qgroupbox + +--------------------------------------------------------------------------- */ +QGroupBox { + border: 1px solid #32414B; + border-radius: 4px; + margin-top: 22px; + padding: 2px; +} + +QGroupBox::title { + subcontrol-origin: margin; + subcontrol-position: top left; + padding-left: 10px; + padding-right: 10px; + padding-top: 2px; +} + +QGroupBox::indicator { + margin-left: 2px; + height: 16px; + width: 16px; +} diff --git a/dist/qt_themes/qdarkstyle/style.qss b/dist/qt_themes/qdarkstyle/style.qss index 32610b131e..d018b9b64b 100644 --- a/dist/qt_themes/qdarkstyle/style.qss +++ b/dist/qt_themes/qdarkstyle/style.qss @@ -307,7 +307,7 @@ QAbstractItemView QLineEdit { QGroupBox { border: 1px solid #54575B; border-radius: 2px; - margin-top: 12px; + margin-top: 20px; padding-top: 2px; } diff --git a/dist/qt_themes/qdarkstyle_midnight_blue/style.qss b/dist/qt_themes/qdarkstyle_midnight_blue/style.qss index 43db5ad0b5..ca80f8b665 100644 --- a/dist/qt_themes/qdarkstyle_midnight_blue/style.qss +++ b/dist/qt_themes/qdarkstyle_midnight_blue/style.qss @@ -235,10 +235,9 @@ https://doc.qt.io/qt-5/stylesheet-examples.html#customizing-qgroupbox --------------------------------------------------------------------------- */ QGroupBox { - font-weight: bold; border: 1px solid #32414B; border-radius: 4px; - margin-top: 12px; + margin-top: 20px; padding: 2px; } From 529f78b95f499d9b6ca86a4eabe23f113e449f98 Mon Sep 17 00:00:00 2001 From: lizzie Date: Thu, 28 Aug 2025 01:55:27 +0200 Subject: [PATCH 30/39] [audio] fix ringbuffer datarace (#205) Signed-off-by: lizzie Reviewed-on: https://git.eden-emu.dev/eden-emu/eden/pulls/205 Reviewed-by: CamilleLaVey Co-authored-by: lizzie Co-committed-by: lizzie --- src/common/ring_buffer.h | 42 ++++++++++++++++------------------------ 1 file changed, 17 insertions(+), 25 deletions(-) diff --git a/src/common/ring_buffer.h b/src/common/ring_buffer.h index b92db6185b..14f6eceeb8 100644 --- a/src/common/ring_buffer.h +++ b/src/common/ring_buffer.h @@ -1,3 +1,5 @@ +// SPDX-FileCopyrightText: Copyright 2025 Eden Emulator Project +// SPDX-License-Identifier: GPL-3.0-or-later // SPDX-FileCopyrightText: Copyright 2018 yuzu Emulator Project // SPDX-License-Identifier: GPL-2.0-or-later @@ -37,10 +39,10 @@ public: /// @param slot_count Number of slots to push /// @returns The number of slots actually pushed std::size_t Push(const void* new_slots, std::size_t slot_count) { - const std::size_t write_index = m_write_index.load(); - const std::size_t slots_free = capacity + m_read_index.load() - write_index; - const std::size_t push_count = std::min(slot_count, slots_free); + std::lock_guard lock(rb_mutex); + const std::size_t slots_free = capacity + read_index - write_index; + const std::size_t push_count = std::min(slot_count, slots_free); const std::size_t pos = write_index % capacity; const std::size_t first_copy = std::min(capacity - pos, push_count); const std::size_t second_copy = push_count - first_copy; @@ -50,8 +52,7 @@ public: in += first_copy * slot_size; std::memcpy(m_data.data(), in, second_copy * slot_size); - m_write_index.store(write_index + push_count); - + write_index = write_index + push_count; return push_count; } @@ -64,10 +65,10 @@ public: /// @param max_slots Maximum number of slots to pop /// @returns The number of slots actually popped std::size_t Pop(void* output, std::size_t max_slots = ~std::size_t(0)) { - const std::size_t read_index = m_read_index.load(); - const std::size_t slots_filled = m_write_index.load() - read_index; - const std::size_t pop_count = std::min(slots_filled, max_slots); + std::lock_guard lock(rb_mutex); + const std::size_t slots_filled = write_index - read_index; + const std::size_t pop_count = std::min(slots_filled, max_slots); const std::size_t pos = read_index % capacity; const std::size_t first_copy = std::min(capacity - pos, pop_count); const std::size_t second_copy = pop_count - first_copy; @@ -77,8 +78,7 @@ public: out += first_copy * slot_size; std::memcpy(out, m_data.data(), second_copy * slot_size); - m_read_index.store(read_index + pop_count); - + read_index = read_index + pop_count; return pop_count; } @@ -90,29 +90,21 @@ public: } /// @returns Number of slots used - [[nodiscard]] std::size_t Size() const { - return m_write_index.load() - m_read_index.load(); + [[nodiscard]] inline std::size_t Size() const { + return write_index - read_index; } /// @returns Maximum size of ring buffer - [[nodiscard]] constexpr std::size_t Capacity() const { + [[nodiscard]] consteval std::size_t Capacity() const { return capacity; } private: - // It is important to align the below variables for performance reasons: - // Having them on the same cache-line would result in false-sharing between them. - // TODO: Remove this ifdef whenever clang and GCC support - // std::hardware_destructive_interference_size. -#ifdef __cpp_lib_hardware_interference_size - alignas(std::hardware_destructive_interference_size) std::atomic_size_t m_read_index{0}; - alignas(std::hardware_destructive_interference_size) std::atomic_size_t m_write_index{0}; -#else - alignas(128) std::atomic_size_t m_read_index{0}; - alignas(128) std::atomic_size_t m_write_index{0}; -#endif - std::array m_data; + // This is wrong, a thread-safe ringbuffer is impossible. + std::size_t read_index{0}; + std::size_t write_index{0}; + std::mutex rb_mutex; }; } // namespace Common From 26b5286250e80ddb8de96a0162bed4ed3701b25d Mon Sep 17 00:00:00 2001 From: lizzie Date: Thu, 28 Aug 2025 05:14:24 +0200 Subject: [PATCH 31/39] [veil] fix flush log option not being available (#341) Signed-off-by: lizzie Reviewed-on: https://git.eden-emu.dev/eden-emu/eden/pulls/341 Reviewed-by: CamilleLaVey Co-authored-by: lizzie Co-committed-by: lizzie --- .../org/yuzu/yuzu_emu/features/settings/model/BooleanSetting.kt | 2 +- src/common/settings.h | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/src/android/app/src/main/java/org/yuzu/yuzu_emu/features/settings/model/BooleanSetting.kt b/src/android/app/src/main/java/org/yuzu/yuzu_emu/features/settings/model/BooleanSetting.kt index d91c026acf..3c5b9003de 100644 --- a/src/android/app/src/main/java/org/yuzu/yuzu_emu/features/settings/model/BooleanSetting.kt +++ b/src/android/app/src/main/java/org/yuzu/yuzu_emu/features/settings/model/BooleanSetting.kt @@ -66,7 +66,7 @@ enum class BooleanSetting(override val key: String) : AbstractBooleanSetting { SHOW_POWER_INFO("show_power_info"), SHOW_SHADERS_BUILDING("show_shaders_building"), - DEBUG_FLUSH_BY_LINE("flush_lines"), + DEBUG_FLUSH_BY_LINE("flush_line"), USE_LRU_CACHE("use_lru_cache"); external fun isRaiiEnabled(): Boolean diff --git a/src/common/settings.h b/src/common/settings.h index 27196fbd69..9ceef99cff 100644 --- a/src/common/settings.h +++ b/src/common/settings.h @@ -756,7 +756,7 @@ struct Values { // Miscellaneous Setting log_filter{linkage, "*:Info", "log_filter", Category::Miscellaneous}; - Setting log_flush_lines{linkage, false, "flush_lines", Category::Miscellaneous, Specialization::Default, true, true}; + Setting log_flush_lines{linkage, false, "flush_line", Category::Miscellaneous, Specialization::Default, true, true}; Setting censor_username{linkage, true, "censor_username", Category::Miscellaneous}; Setting use_dev_keys{linkage, false, "use_dev_keys", Category::Miscellaneous}; Setting first_launch{linkage, true, "first_launch", Category::Miscellaneous}; From 8ed05425dddf17aeafa4daa751cb3a3a13c5a31b Mon Sep 17 00:00:00 2001 From: wildcard Date: Thu, 28 Aug 2025 05:21:05 +0200 Subject: [PATCH 32/39] [Vulkan][TextureCache] Always use identity-swizzled views for storage images (#321) Validation flagged writes to a VK_DESCRIPTOR_TYPE_STORAGE_IMAGE descriptor because the bound VkImageView had a non-identity component mapping and hence the vuid-00336 error, this fixes the said error. ------ This commit helps to fix some graphical issues on games like Trident's Tale, where game didn't render anything than just plain terrain, helps to stabilize Nier Automata graphical issues, meanwhile the most annoying glitches are gone, there's still remain other issues. Reviewed-on: https://git.eden-emu.dev/eden-emu/eden/pulls/321 Reviewed-by: CamilleLaVey Co-authored-by: wildcard Co-committed-by: wildcard --- .../renderer_vulkan/vk_texture_cache.cpp | 32 +++++++++++++------ 1 file changed, 23 insertions(+), 9 deletions(-) diff --git a/src/video_core/renderer_vulkan/vk_texture_cache.cpp b/src/video_core/renderer_vulkan/vk_texture_cache.cpp index ba58060d20..eda9ff2a5a 100644 --- a/src/video_core/renderer_vulkan/vk_texture_cache.cpp +++ b/src/video_core/renderer_vulkan/vk_texture_cache.cpp @@ -2160,20 +2160,34 @@ VkImageView ImageView::StorageView(Shader::TextureType texture_type, if (!image_handle) { return VK_NULL_HANDLE; } - if (image_format == Shader::ImageFormat::Typeless) { - return Handle(texture_type); - } - const bool is_signed{image_format == Shader::ImageFormat::R8_SINT || - image_format == Shader::ImageFormat::R16_SINT}; + if (!storage_views) { storage_views = std::make_unique(); } - auto& views{is_signed ? storage_views->signeds : storage_views->unsigneds}; - auto& view{views[static_cast(texture_type)]}; - if (view) { + + // Storage images MUST use identity component mapping. + // Typeless: use the underlying image's native format. + if (image_format == Shader::ImageFormat::Typeless) { + auto& view = storage_views->unsigneds[static_cast(texture_type)]; + if (view) { + return *view; + } + const auto fmt_info = + MaxwellToVK::SurfaceFormat(*device, FormatType::Optimal, /*is_image=*/true, format); + const VkFormat vk_format = fmt_info.format; + // Storage images are color-aspect only + view = MakeView(vk_format, VK_IMAGE_ASPECT_COLOR_BIT); // identity components inside return *view; } - view = MakeView(Format(image_format), VK_IMAGE_ASPECT_COLOR_BIT); + const bool is_signed = (image_format == Shader::ImageFormat::R8_SINT ||image_format == Shader::ImageFormat::R16_SINT); + auto& views = is_signed ? storage_views->signeds : storage_views->unsigneds; + auto& view = views[static_cast(texture_type)]; + if (view) { + return *view; + } + + const VkFormat vk_format = Format(image_format); + view = MakeView(vk_format, VK_IMAGE_ASPECT_COLOR_BIT);// identity components inside return *view; } From 428249cb01f60668a1842d184e95fb68b68970c1 Mon Sep 17 00:00:00 2001 From: MaranBr Date: Thu, 28 Aug 2025 16:46:24 +0200 Subject: [PATCH 33/39] [debug] Rename remaining names in accordance with PR 341 (#343) This renames the remaining names in accordance with PR 341. Reviewed-on: https://git.eden-emu.dev/eden-emu/eden/pulls/343 Reviewed-by: CamilleLaVey Co-authored-by: MaranBr Co-committed-by: MaranBr --- src/common/logging/backend.cpp | 5 ++++- src/common/settings.h | 2 +- src/yuzu/configuration/configure_debug.cpp | 7 +++++-- 3 files changed, 10 insertions(+), 4 deletions(-) diff --git a/src/common/logging/backend.cpp b/src/common/logging/backend.cpp index ff07ab68eb..4621771090 100644 --- a/src/common/logging/backend.cpp +++ b/src/common/logging/backend.cpp @@ -1,3 +1,6 @@ +// SPDX-FileCopyrightText: Copyright 2025 Eden Emulator Project +// SPDX-License-Identifier: GPL-3.0-or-later + // SPDX-FileCopyrightText: 2014 Citra Emulator Project // SPDX-License-Identifier: GPL-2.0-or-later @@ -121,7 +124,7 @@ public: bytes_written += file->WriteString(message); // Option to log each line rather than 4k buffers - if (Settings::values.log_flush_lines.GetValue()) { + if (Settings::values.log_flush_line.GetValue()) { file->Flush(); } diff --git a/src/common/settings.h b/src/common/settings.h index 9ceef99cff..ce845b31f5 100644 --- a/src/common/settings.h +++ b/src/common/settings.h @@ -756,7 +756,7 @@ struct Values { // Miscellaneous Setting log_filter{linkage, "*:Info", "log_filter", Category::Miscellaneous}; - Setting log_flush_lines{linkage, false, "flush_line", Category::Miscellaneous, Specialization::Default, true, true}; + Setting log_flush_line{linkage, false, "flush_line", Category::Miscellaneous, Specialization::Default, true, true}; Setting censor_username{linkage, true, "censor_username", Category::Miscellaneous}; Setting use_dev_keys{linkage, false, "use_dev_keys", Category::Miscellaneous}; Setting first_launch{linkage, true, "first_launch", Category::Miscellaneous}; diff --git a/src/yuzu/configuration/configure_debug.cpp b/src/yuzu/configuration/configure_debug.cpp index 10607ee233..733c419c4b 100644 --- a/src/yuzu/configuration/configure_debug.cpp +++ b/src/yuzu/configuration/configure_debug.cpp @@ -1,3 +1,6 @@ +// SPDX-FileCopyrightText: Copyright 2025 Eden Emulator Project +// SPDX-License-Identifier: GPL-3.0-or-later + // SPDX-FileCopyrightText: 2016 Citra Emulator Project // SPDX-License-Identifier: GPL-2.0-or-later @@ -39,7 +42,7 @@ void ConfigureDebug::SetConfiguration() { ui->toggle_console->setEnabled(runtime_lock); ui->toggle_console->setChecked(UISettings::values.show_console.GetValue()); ui->log_filter_edit->setText(QString::fromStdString(Settings::values.log_filter.GetValue())); - ui->flush_line->setChecked(Settings::values.log_flush_lines.GetValue()); + ui->flush_line->setChecked(Settings::values.log_flush_line.GetValue()); ui->censor_username->setChecked(Settings::values.censor_username.GetValue()); ui->homebrew_args_edit->setText( QString::fromStdString(Settings::values.program_args.GetValue())); @@ -90,7 +93,7 @@ void ConfigureDebug::ApplyConfiguration() { Settings::values.gdbstub_port = ui->gdbport_spinbox->value(); UISettings::values.show_console = ui->toggle_console->isChecked(); Settings::values.log_filter = ui->log_filter_edit->text().toStdString(); - Settings::values.log_flush_lines = ui->flush_line->isChecked(); + Settings::values.log_flush_line = ui->flush_line->isChecked(); Settings::values.censor_username = ui->censor_username->isChecked(); Settings::values.program_args = ui->homebrew_args_edit->text().toStdString(); Settings::values.enable_fs_access_log = ui->fs_access_log->isChecked(); From d709771d67d9405edaa215d25af2d521cdb1983b Mon Sep 17 00:00:00 2001 From: MaranBr Date: Fri, 29 Aug 2025 00:07:21 +0200 Subject: [PATCH 34/39] [core] Unsafe toggles cannot be changed at runtime (#344) Reviewed-on: https://git.eden-emu.dev/eden-emu/eden/pulls/344 Reviewed-by: CamilleLaVey Reviewed-by: crueter Co-authored-by: MaranBr Co-committed-by: MaranBr --- src/common/settings.h | 5 +---- 1 file changed, 1 insertion(+), 4 deletions(-) diff --git a/src/common/settings.h b/src/common/settings.h index ce845b31f5..64545d10ff 100644 --- a/src/common/settings.h +++ b/src/common/settings.h @@ -307,10 +307,7 @@ struct Values { true, #endif "cpuopt_unsafe_host_mmu", - Category::CpuUnsafe, - Specialization::Default, - true, - true}; + Category::CpuUnsafe}; SwitchableSetting cpuopt_unsafe_unfuse_fma{linkage, true, "cpuopt_unsafe_unfuse_fma", Category::CpuUnsafe}; SwitchableSetting cpuopt_unsafe_reduce_fp_error{ From 702a2beb7c3b30f84b90e88fc06ece2cd64d36f4 Mon Sep 17 00:00:00 2001 From: crueter Date: Fri, 29 Aug 2025 00:18:02 +0200 Subject: [PATCH 35/39] [cmake] refactor: cpmfile, deps prefetch, force system and more (#322) CPM Dependencies are now managed in a singular json file, where each can be properly prefetched at-will via `tools/cpm-fetch.sh `, or all at once via `tools/cpm-fetch-all.sh`. Adds docs for CPMUtil as well. Also adds `_FORCE_{BUNDLED,SYSTEM}` overrides Signed-off-by: crueter Reviewed-on: https://git.eden-emu.dev/eden-emu/eden/pulls/322 Reviewed-by: CamilleLaVey --- .gitignore | 1 + CMakeLists.txt | 297 ++++++--------------- CMakeModules/CPMUtil.cmake | 354 +++++++++++++++++++------- CMakeModules/DownloadExternals.cmake | 1 + CMakeModules/FindSPIRV-Tools.cmake | 19 ++ CMakeModules/Findzstd.cmake | 17 +- cpmfile.json | 147 +++++++++++ docs/CPM.md | 252 ++++++++++++++++++ externals/CMakeLists.txt | 142 +++-------- externals/cpmfile.json | 109 ++++++++ externals/ffmpeg/CMakeLists.txt | 12 +- externals/ffmpeg/cpmfile.json | 8 + externals/nx_tzdb/CMakeLists.txt | 67 +++-- externals/nx_tzdb/cpmfile.json | 8 + src/android/app/build.gradle.kts | 5 +- src/common/CMakeLists.txt | 8 +- src/dynarmic/externals/CMakeLists.txt | 86 ++----- src/dynarmic/externals/cpmfile.json | 47 ++++ src/shader_recompiler/CMakeLists.txt | 2 +- src/yuzu/externals/CMakeLists.txt | 13 +- src/yuzu/externals/cpmfile.json | 12 + tools/cpm-fetch-all.sh | 10 + tools/cpm-fetch.sh | 198 ++++++++++++++ 23 files changed, 1253 insertions(+), 562 deletions(-) create mode 100644 CMakeModules/FindSPIRV-Tools.cmake create mode 100644 cpmfile.json create mode 100644 docs/CPM.md create mode 100644 externals/cpmfile.json create mode 100644 externals/ffmpeg/cpmfile.json create mode 100644 externals/nx_tzdb/cpmfile.json create mode 100644 src/dynarmic/externals/cpmfile.json create mode 100644 src/yuzu/externals/cpmfile.json create mode 100755 tools/cpm-fetch-all.sh create mode 100755 tools/cpm-fetch.sh diff --git a/.gitignore b/.gitignore index 83881117ac..2b342e5145 100644 --- a/.gitignore +++ b/.gitignore @@ -52,3 +52,4 @@ Thumbs.db eden-windows-msvc artifacts *.AppImage* +/install* diff --git a/CMakeLists.txt b/CMakeLists.txt index 6a8401759d..d11b58bf1f 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -99,7 +99,6 @@ option(FORCE_DOWNLOAD_WIN_BUNDLES "Forcefully download bundled Windows dependenc if (YUZU_USE_CPM AND ENABLE_SDL2) option(YUZU_USE_BUNDLED_SDL2 "Download bundled SDL2 build" "${MSVC}") - CMAKE_DEPENDENT_OPTION(FORCE_DOWNLOAD_SDL2 "Forcefully download all bundled SDL2 builds (useful for CI)" OFF "YUZU_USE_BUNDLED_SDL2" OFF) endif() CMAKE_DEPENDENT_OPTION(YUZU_ROOM "Enable dedicated room functionality" ON "NOT ANDROID" OFF) @@ -110,11 +109,7 @@ CMAKE_DEPENDENT_OPTION(YUZU_CMD "Compile the eden-cli executable" ON "NOT ANDROI CMAKE_DEPENDENT_OPTION(YUZU_CRASH_DUMPS "Compile crash dump (Minidump) support" OFF "WIN32 OR LINUX" OFF) -if (PLATFORM_FREEBSD) - option(YUZU_CHECK_SUBMODULES "Check if submodules are present" OFF) -else() - option(YUZU_CHECK_SUBMODULES "Check if submodules are present" ON) -endif() +option(YUZU_CHECK_SUBMODULES "Check if submodules are present" ${EXT_DEFAULT}) option(YUZU_ENABLE_LTO "Enable link-time optimization" OFF) @@ -143,9 +138,8 @@ endif() option(ENABLE_OPENSSL "Enable OpenSSL backend for ISslConnection" ${DEFAULT_ENABLE_OPENSSL}) -if (YUZU_USE_CPM AND ENABLE_OPENSSL) +if (ENABLE_OPENSSL) CMAKE_DEPENDENT_OPTION(YUZU_USE_BUNDLED_OPENSSL "Download bundled OpenSSL build" "${MSVC}" "NOT ANDROID" ON) - CMAKE_DEPENDENT_OPTION(FORCE_DOWNLOAD_OPENSSL "Forcefully download all bundled OpenSSL builds (useful for CI)" OFF "YUZU_USE_BUNDLED_OPENSSL" OFF) endif() if (ANDROID AND YUZU_DOWNLOAD_ANDROID_VVL) @@ -180,12 +174,12 @@ if (YUZU_USE_PRECOMPILED_HEADERS) set(YUZU_USE_PRECOMPILED_HEADERS OFF CACHE BOOL "" FORCE) endif() endif() + if (YUZU_USE_PRECOMPILED_HEADERS) message(STATUS "Using Precompiled Headers.") set(CMAKE_PCH_INSTANTIATE_TEMPLATES ON) endif() - # Default to a Release build get_property(IS_MULTI_CONFIG GLOBAL PROPERTY GENERATOR_IS_MULTI_CONFIG) if (NOT IS_MULTI_CONFIG AND NOT CMAKE_BUILD_TYPE) @@ -246,20 +240,24 @@ endfunction() if(EXISTS ${PROJECT_SOURCE_DIR}/.gitmodules AND YUZU_CHECK_SUBMODULES) check_submodules_present() endif() + configure_file(${PROJECT_SOURCE_DIR}/dist/compatibility_list/compatibility_list.qrc ${PROJECT_BINARY_DIR}/dist/compatibility_list/compatibility_list.qrc COPYONLY) + if (EXISTS ${PROJECT_SOURCE_DIR}/dist/compatibility_list/compatibility_list.json) configure_file("${PROJECT_SOURCE_DIR}/dist/compatibility_list/compatibility_list.json" "${PROJECT_BINARY_DIR}/dist/compatibility_list/compatibility_list.json" COPYONLY) endif() + if (ENABLE_COMPATIBILITY_LIST_DOWNLOAD AND NOT EXISTS ${PROJECT_BINARY_DIR}/dist/compatibility_list/compatibility_list.json) message(STATUS "Downloading compatibility list for yuzu...") file(DOWNLOAD https://api.yuzu-emu.org/gamedb/ "${PROJECT_BINARY_DIR}/dist/compatibility_list/compatibility_list.json" SHOW_PROGRESS) endif() + if (NOT EXISTS ${PROJECT_BINARY_DIR}/dist/compatibility_list/compatibility_list.json) file(WRITE ${PROJECT_BINARY_DIR}/dist/compatibility_list/compatibility_list.json "") endif() @@ -303,8 +301,15 @@ if (NOT DEFINED ARCHITECTURE) set(ARCHITECTURE_GENERIC 1) add_definitions(-DARCHITECTURE_GENERIC=1) endif() + message(STATUS "Target architecture: ${ARCHITECTURE}") +if (MSVC AND ARCHITECTURE_x86) + message(FATAL_ERROR "Attempting to build with the x86 environment is not supported. \ + This can typically happen if you used the Developer Command Prompt from the start menu;\ + instead, run vcvars64.bat directly, located at C:/Program Files/Microsoft Visual Studio/2022/Community/VC/Auxiliary/Build/vcvars64.bat") +endif() + if (UNIX) add_definitions(-DYUZU_UNIX=1) endif() @@ -367,6 +372,15 @@ set(CMAKE_RUNTIME_OUTPUT_DIRECTORY ${PROJECT_BINARY_DIR}/bin) include(CPMUtil) +# openssl funniness +if (ENABLE_OPENSSL) + if (YUZU_USE_BUNDLED_OPENSSL) + AddJsonPackage(openssl) + endif() + + find_package(OpenSSL 1.1.1 REQUIRED) +endif() + if (YUZU_USE_CPM) message(STATUS "Fetching needed dependencies with CPM") @@ -375,36 +389,9 @@ if (YUZU_USE_CPM) # TODO(crueter): renderdoc? - # openssl funniness - if (ENABLE_OPENSSL) - if (YUZU_USE_BUNDLED_OPENSSL) - AddCIPackage( - PACKAGE OpenSSL - NAME openssl - REPO crueter-ci/OpenSSL - VERSION 3.5.2 - MIN_VERSION 1.1.1 - FORCE_DOWNLOAD ${FORCE_DOWNLOAD_OPENSSL} - ) - endif() - - find_package(OpenSSL 1.1.1 REQUIRED) - endif() - # boost set(BOOST_INCLUDE_LIBRARIES algorithm icl pool container heap asio headers process filesystem crc variant) - AddPackage( - NAME Boost - REPO boostorg/boost - TAG boost-1.88.0 - ARTIFACT boost-1.88.0-cmake.7z - - HASH e5b049e5b61964480ca816395f63f95621e66cb9bcf616a8b10e441e0e69f129e22443acb11e77bc1e8170f8e4171b9b7719891efc43699782bfcd4b3a365f01 - - GIT_VERSION 1.88.0 - VERSION 1.57 - EXCLUDE_FROM_ALL ON - ) + AddJsonPackage(boost) # really annoying thing where boost::headers doesn't work with cpm # TODO(crueter) investigate @@ -419,6 +406,10 @@ if (YUZU_USE_CPM) if (NOT MSVC) # boost sucks + if (NOT PLATFORM_LINUX AND NOT ANDROID) + target_compile_definitions(boost_container INTERFACE BOOST_HAS_PTHREADS) + endif() + target_compile_options(boost_heap INTERFACE -Wno-shadow) target_compile_options(boost_icl INTERFACE -Wno-shadow) target_compile_options(boost_asio INTERFACE -Wno-conversion -Wno-implicit-fallthrough) @@ -426,151 +417,46 @@ if (YUZU_USE_CPM) endif() # fmt - AddPackage( - NAME fmt - REPO fmtlib/fmt - SHA 40626af88b - HASH d59f06c24339f223de4ec2afeba1c67b5835a0f350a1ffa86242a72fc3e616a6b8b21798355428d4200c75287308b66634619ffa0b52ba5bd74cc01772ea1a8a - VERSION 8 - OPTIONS - "FMT_INSTALL OFF" - EXCLUDE_FROM_ALL ON - ) + AddJsonPackage(fmt) # lz4 - AddPackage( - NAME lz4 - REPO lz4/lz4 - SHA ebb370ca83 - HASH 43600e87b35256005c0f2498fa56a77de6783937ba4cfce38c099f27c03188d097863e8a50c5779ca0a7c63c29c4f7ed0ae526ec798c1fd2e3736861b62e0a37 - SOURCE_SUBDIR build/cmake - EXCLUDE_FROM_ALL ON - ) + AddJsonPackage(lz4) if (lz4_ADDED) add_library(lz4::lz4 ALIAS lz4_static) endif() # nlohmann - AddPackage( - NAME nlohmann_json - REPO nlohmann/json - SHA 55f93686c0 - HASH b739749b066800e21154506ea150d2c5cbce8a45344177f46f884547a1399d26753166fd0df8135269ce28cf223552b1b65cd625b88c844d54753f2434900486 - VERSION 3.8 - EXCLUDE_FROM_ALL ON - ) + AddJsonPackage(nlohmann) # zlib - AddPackage( - NAME ZLIB - REPO madler/zlib - SHA 51b7f2abda - HASH 16eaf1f3752489d12fd9ce30f7b5f7cbd5cb8ff53d617005a9847ae72d937f65e01e68be747f62d7ac19fd0c9aeba9956e60f16d6b465c5fdc2f3d08b4db2e6c - VERSION 1.2 - OPTIONS - "ZLIB_BUILD_SHARED OFF" - "ZLIB_INSTALL OFF" - EXCLUDE_FROM_ALL ON - ) + AddJsonPackage(zlib) if (ZLIB_ADDED) add_library(ZLIB::ZLIB ALIAS zlibstatic) endif() # zstd - AddPackage( - NAME zstd - REPO facebook/zstd - SHA f8745da6ff - HASH 3037007f990040fe32573b46f9bef8762fd5dbeeb07ffffcbfeba51ec98167edae39bb9c87f9299efcd61c4e467c5e84f7c19f0df7799bc1fc04864a278792ee - VERSION 1.5 - SOURCE_SUBDIR build/cmake - OPTIONS - "ZSTD_BUILD_SHARED OFF" - EXCLUDE_FROM_ALL ON - ) + AddJsonPackage(zstd) + + if (zstd_ADDED) + add_library(zstd::zstd ALIAS libzstd_static) + endif() # Catch2 if (YUZU_TESTS OR DYNARMIC_TESTS) - AddPackage( - NAME Catch2 - REPO catchorg/Catch2 - SHA 644821ce28 - HASH f8795f98acf2c02c0db8e734cc866d5caebab4b4a306e93598b97cb3c0c728dafe8283dce27ffe8d42460e5ae7302f3f32e7e274a7f991b73511ac88eef21b1f - VERSION 3.0.1 - EXCLUDE_FROM_ALL ON - ) + AddJsonPackage(catch2) endif() # ENet - AddPackage( - NAME enet - REPO lsalzman/enet - SHA 2662c0de09 - VERSION 1.3 - HASH 3de1beb4fa3d6b1e03eda8dd1e7580694f854af3ed3975dcdabfdcdf76b97f322b9734d35ea7f185855bb490d957842b938b26da4dd2dfded509390f8d2794dd - FIND_PACKAGE_ARGUMENTS "MODULE" - EXCLUDE_FROM_ALL ON - ) + AddJsonPackage(enet) if (enet_ADDED) target_include_directories(enet INTERFACE ${enet_SOURCE_DIR}/include) endif() # Opus - AddPackage( - NAME Opus - VERSION 1.3 - REPO "xiph/opus" - SHA 5ded705cf4 - HASH 0dc89e58ddda1f3bc6a7037963994770c5806c10e66f5cc55c59286fc76d0544fe4eca7626772b888fd719f434bc8a92f792bdb350c807968b2ac14cfc04b203 - FIND_PACKAGE_ARGUMENTS "MODULE" - OPTIONS - "OPUS_BUILD_TESTING OFF" - "OPUS_BUILD_PROGRAMS OFF" - "OPUS_INSTALL_PKG_CONFIG_MODULE OFF" - "OPUS_INSTALL_CMAKE_CONFIG_MODULE OFF" - EXCLUDE_FROM_ALL ON - ) - - if(ENABLE_CUBEB) - AddPackage( - NAME cubeb - REPO "mozilla/cubeb" - SHA fa02160712 - HASH 82d808356752e4064de48c8fecbe7856715ade1e76b53937116bf07129fc1cc5b3de5e4b408de3cd000187ba8dc32ca4109661cb7e0355a52e54bd81b9be1c61 - FIND_PACKAGE_ARGUMENTS "CONFIG" # not sure this works outside of gentoo - OPTIONS - "USE_SANITIZERS OFF" - "BUILD_TESTS OFF" - "BUILD_TOOLS OFF" - "BUNDLE_SPEEX ON" - EXCLUDE_FROM_ALL ON - ) - - if (cubeb_ADDED) - if (NOT MSVC) - if (TARGET speex) - target_compile_options(speex PRIVATE -Wno-sign-compare) - endif() - - set_target_properties(cubeb PROPERTIES COMPILE_OPTIONS "") - target_compile_options(cubeb INTERFACE - -Wno-implicit-const-int-float-conversion - -Wno-shadow - -Wno-missing-declarations - -Wno-return-type - -Wno-uninitialized - ) - else() - target_compile_options(cubeb PRIVATE - /wd4456 - /wd4458 - ) - endif() - endif() - endif() + AddJsonPackage(opus) else() # Enforce the search mode of non-required packages for better and shorter failure messages find_package(fmt 8 REQUIRED) @@ -582,11 +468,7 @@ else() find_package(enet 1.3 MODULE REQUIRED) find_package(Opus 1.3 MODULE REQUIRED) find_package(ZLIB 1.2 REQUIRED) - find_package(zstd 1.5 REQUIRED) - - if (ENABLE_CUBEB) - find_package(cubeb CONFIG) - endif() + find_package(zstd 1.5 REQUIRED MODULE) if (YUZU_TESTS) find_package(Catch2 3.0.1 REQUIRED) @@ -602,14 +484,7 @@ else() endif() if(NOT TARGET Boost::headers) - AddPackage( - NAME boost_headers - REPO "boostorg/headers" - SHA 0456900fad - HASH 50cd75dcdfc5f082225cdace058f47b4fb114a47585f7aee1d22236a910a80b667186254c214fa2fcebac67ae6d37ba4b6e695e1faea8affd6fd42a03cf996e3 - BUNDLED_PACKAGE ON - EXCLUDE_FROM_ALL ON - ) + AddJsonPackage(boost_headers) endif() if (ENABLE_LIBUSB) @@ -622,45 +497,45 @@ endif() # DiscordRPC if (USE_DISCORD_PRESENCE) - AddPackage( - NAME discord-rpc - REPO "discord/discord-rpc" - SHA 963aa9f3e5 - HASH 386e1344e9a666d730f2d335ee3aef1fd05b1039febefd51aa751b705009cc764411397f3ca08dffd46205c72f75b235c870c737b2091a4ed0c3b061f5919bde - OPTIONS - "BUILD_EXAMPLES OFF" - PATCHES - ${CMAKE_SOURCE_DIR}/.patch/discord-rpc/0001-cmake-version.patch - ${CMAKE_SOURCE_DIR}/.patch/discord-rpc/0002-no-clang-format.patch - ${CMAKE_SOURCE_DIR}/.patch/discord-rpc/0003-fix-cpp17.patch - EXCLUDE_FROM_ALL ON - ) + AddJsonPackage(discord-rpc) target_include_directories(discord-rpc INTERFACE ${discord-rpc_SOURCE_DIR}/include) add_library(DiscordRPC::discord-rpc ALIAS discord-rpc) endif() # SimpleIni -AddPackage( - NAME SimpleIni - REPO brofield/simpleini - SHA 09c21bda1d - HASH 99779ca9b6e040d36558cadf484f9ffdab5b47bcc8fc72e4d33639d1d60c0ceb4410d335ba445d72a4324e455167fd6769d99b459943aa135bec085dff2d4b7c - FIND_PACKAGE_ARGUMENTS "MODULE" - EXCLUDE_FROM_ALL ON -) +AddJsonPackage(simpleini) -# TODO(crueter): Work around this -if (NOT YUZU_USE_EXTERNAL_VULKAN_SPIRV_TOOLS) - find_package(PkgConfig REQUIRED) - pkg_check_modules(SPIRV-Tools REQUIRED SPIRV-Tools) +# Most linux distros don't package cubeb, so enable regardless of cpm settings +if(ENABLE_CUBEB) + AddJsonPackage(cubeb) + + if (cubeb_ADDED) + if (NOT MSVC) + if (TARGET speex) + target_compile_options(speex PRIVATE -Wno-sign-compare) + endif() + + set_target_properties(cubeb PROPERTIES COMPILE_OPTIONS "") + target_compile_options(cubeb INTERFACE + -Wno-implicit-const-int-float-conversion + -Wno-shadow + -Wno-missing-declarations + -Wno-return-type + -Wno-uninitialized + ) + else() + target_compile_options(cubeb PRIVATE + /wd4456 + /wd4458 + ) + endif() + endif() endif() # find SDL2 exports a bunch of variables that are needed, so its easier to do this outside of the YUZU_find_package if (ENABLE_SDL2) - # this was hard to get right, but ultimately I decided to make it so that FORCE_DOWNLOAD_SDL2 also downloads the - # external one. Really silly behavior imo but in the interest of getting something out there I'm leaving it for now - if (YUZU_USE_EXTERNAL_SDL2 OR FORCE_DOWNLOAD_SDL2) + if (YUZU_USE_EXTERNAL_SDL2) message(STATUS "Using SDL2 from externals.") if (NOT WIN32) # Yuzu itself needs: Atomic Audio Events Joystick Haptic Sensor Threads Timers @@ -683,37 +558,14 @@ if (ENABLE_SDL2) endif() if ("${YUZU_SYSTEM_PROFILE}" STREQUAL "steamdeck") - set(SDL_HASH cc016b0046) set(SDL_PIPEWIRE OFF) # build errors out with this on - set(SDL_SHA512SUM 34d5ef58da6a4f9efa6689c82f67badcbd741f5a4f562a9c2c30828fa839830fb07681c5dc6a7851520e261c8405a416ac0a2c2513b51984fb3b4fa4dcb3e20b) + AddJsonPackage("sdl2_steamdeck") else() - set(SDL_HASH 54772f345a) - set(SDL_SHA512SUM 2a68a0e01c390043aa9d9df63d8a20a52076c88bb460ac4e0f33194ca7d9bc8fadbbcc04e7506872ac4b6354a73fbc267c036f82200da59465789b87c7d9e3a4) + AddJsonPackage("sdl2_generic") endif() - - AddPackage( - NAME SDL2 - REPO "libsdl-org/SDL" - SHA ${SDL_HASH} - HASH ${SDL_SHA512SUM} - KEY ${YUZU_SYSTEM_PROFILE} - BUNDLED_PACKAGE ON - EXCLUDE_FROM_ALL ON - ) - endif() - - if (YUZU_USE_BUNDLED_SDL2) + elseif (YUZU_USE_BUNDLED_SDL2) message(STATUS "Using bundled SDL2") - AddCIPackage( - PACKAGE SDL2 - NAME SDL2 - REPO crueter-ci/SDL2 - VERSION 2.32.8 - MIN_VERSION 2.26.4 - CMAKE_FILENAME sdl2 - FORCE_DOWNLOAD ${FORCE_DOWNLOAD_SDL2} - TARGET "SDL2::SDL2" - ) + AddJsonPackage(sdl2) endif() find_package(SDL2 2.26.4 REQUIRED) @@ -750,6 +602,7 @@ add_subdirectory(externals) find_package(VulkanHeaders) find_package(VulkanUtilityLibraries) find_package(VulkanMemoryAllocator) +find_package(SPIRV-Tools) if (ENABLE_WEB_SERVICE) find_package(httplib) diff --git a/CMakeModules/CPMUtil.cmake b/CMakeModules/CPMUtil.cmake index 519e7e32a8..4d7db6ed61 100644 --- a/CMakeModules/CPMUtil.cmake +++ b/CMakeModules/CPMUtil.cmake @@ -1,28 +1,222 @@ # SPDX-FileCopyrightText: Copyright 2025 Eden Emulator Project # SPDX-License-Identifier: GPL-3.0-or-later +# SPDX-FileCopyrightText: Copyright 2025 crueter +# SPDX-License-Identifier: GPL-3.0-or-later + # Created-By: crueter # Docs will come at a later date, mostly this is to just reduce boilerplate # and some cmake magic to allow for runtime viewing of dependency versions -include(CMakeDependentOption) +# Future crueter: Wow this was a lie and a half, at this point I might as well make my own CPN +# haha just kidding... unless? + if (MSVC OR ANDROID) - set(SYSTEM_DEFAULT OFF) + set(BUNDLED_DEFAULT OFF) else() - set(SYSTEM_DEFAULT ON) + set(BUNDLED_DEFAULT ON) endif() -CMAKE_DEPENDENT_OPTION(CPMUTIL_DEFAULT_SYSTEM - "Allow usage of system packages for CPM dependencies" ${SYSTEM_DEFAULT} - "NOT ANDROID" OFF) +option(CPMUTIL_FORCE_BUNDLED + "Force bundled packages for all CPM depdendencies" ${BUNDLED_DEFAULT}) + +option(CPMUTIL_FORCE_SYSTEM + "Force system packages for all CPM dependencies (NOT RECOMMENDED)" OFF) cmake_minimum_required(VERSION 3.22) include(CPM) +# TODO(crueter): Better solution for separate cpmfiles e.g. per-directory +set(CPMUTIL_JSON_FILE "${CMAKE_CURRENT_SOURCE_DIR}/cpmfile.json" CACHE STRING "Location of cpmfile.json") + +if (EXISTS ${CPMUTIL_JSON_FILE}) + file(READ ${CPMUTIL_JSON_FILE} CPMFILE_CONTENT) +else() + message(WARNING "[CPMUtil] cpmfile ${CPMUTIL_JSON_FILE} does not exist, AddJsonPackage will be a no-op") +endif() + +# utility function(cpm_utils_message level name message) message(${level} "[CPMUtil] ${name}: ${message}") endfunction() +# utility +function(array_to_list array length out) + math(EXPR range "${length} - 1") + + foreach(IDX RANGE ${range}) + string(JSON _element GET "${array}" "${IDX}") + + list(APPEND NEW_LIST ${_element}) + endforeach() + + set("${out}" "${NEW_LIST}" PARENT_SCOPE) +endfunction() + +# utility +function(get_json_element object out member default) + string(JSON out_type ERROR_VARIABLE err TYPE "${object}" ${member}) + + if (err) + set("${out}" "${default}" PARENT_SCOPE) + return() + endif() + + string(JSON outvar GET "${object}" ${member}) + + if (out_type STREQUAL "ARRAY") + string(JSON _len LENGTH "${object}" ${member}) + # array_to_list("${outvar}" ${_len} outvar) + set("${out}_LENGTH" "${_len}" PARENT_SCOPE) + endif() + + set("${out}" "${outvar}" PARENT_SCOPE) +endfunction() + +# Kinda cancerous but whatever +function(AddJsonPackage) + set(oneValueArgs + NAME + + # these are overrides that can be generated at runtime, so can be defined separately from the json + DOWNLOAD_ONLY + SYSTEM_PACKAGE + BUNDLED_PACKAGE + ) + + set(multiValueArgs OPTIONS) + + cmake_parse_arguments(JSON "" "${oneValueArgs}" "${multiValueArgs}" + "${ARGN}") + + list(LENGTH ARGN argnLength) + # single name argument + if(argnLength EQUAL 1) + set(JSON_NAME "${ARGV0}") + endif() + + if (NOT DEFINED CPMFILE_CONTENT) + cpm_utils_message(WARNING ${name} "No cpmfile, AddJsonPackage is a no-op") + return() + endif() + + if (NOT DEFINED JSON_NAME) + cpm_utils_message(FATAL_ERROR "json package" "No name specified") + endif() + + string(JSON object ERROR_VARIABLE err GET "${CPMFILE_CONTENT}" "${JSON_NAME}") + + if (err) + cpm_utils_message(FATAL_ERROR ${JSON_NAME} "Not found in cpmfile") + endif() + + get_json_element("${object}" package package ${JSON_NAME}) + get_json_element("${object}" repo repo "") + get_json_element("${object}" ci ci OFF) + get_json_element("${object}" version version "") + + if (ci) + get_json_element("${object}" name name "${JSON_NAME}") + get_json_element("${object}" extension extension "tar.zst") + get_json_element("${object}" min_version min_version "") + get_json_element("${object}" cmake_filename cmake_filename "") + get_json_element("${object}" raw_disabled disabled_platforms "") + + if (raw_disabled) + array_to_list("${raw_disabled}" ${raw_disabled_LENGTH} disabled_platforms) + else() + set(disabled_platforms "") + endif() + + AddCIPackage( + VERSION ${version} + NAME ${name} + REPO ${repo} + PACKAGE ${package} + EXTENSION ${extension} + MIN_VERSION ${min_version} + DISABLED_PLATFORMS ${disabled_platforms} + CMAKE_FILENAME ${cmake_filename} + ) + return() + endif() + + get_json_element("${object}" hash hash "") + get_json_element("${object}" sha sha "") + get_json_element("${object}" url url "") + get_json_element("${object}" key key "") + get_json_element("${object}" tag tag "") + get_json_element("${object}" artifact artifact "") + get_json_element("${object}" git_version git_version "") + get_json_element("${object}" source_subdir source_subdir "") + get_json_element("${object}" bundled bundled "unset") + get_json_element("${object}" find_args find_args "") + get_json_element("${object}" raw_patches patches "") + + # format patchdir + if (raw_patches) + math(EXPR range "${raw_patches_LENGTH} - 1") + + foreach(IDX RANGE ${range}) + string(JSON _patch GET "${raw_patches}" "${IDX}") + + set(full_patch "${CMAKE_SOURCE_DIR}/.patch/${JSON_NAME}/${_patch}") + if (NOT EXISTS ${full_patch}) + cpm_utils_message(FATAL_ERROR ${JSON_NAME} "specifies patch ${full_patch} which does not exist") + endif() + + list(APPEND patches "${full_patch}") + endforeach() + endif() + # end format patchdir + + # options + get_json_element("${object}" raw_options options "") + + if (raw_options) + array_to_list("${raw_options}" ${raw_options_LENGTH} options) + endif() + + set(options ${options} ${JSON_OPTIONS}) + + # end options + + # system/bundled + if (bundled STREQUAL "unset" AND DEFINED JSON_BUNDLED_PACKAGE) + set(bundled ${JSON_BUNDLED_PACKAGE}) + else() + set(bundled ON) + endif() + + AddPackage( + NAME "${package}" + VERSION "${version}" + URL "${url}" + HASH "${hash}" + SHA "${sha}" + REPO "${repo}" + KEY "${key}" + PATCHES "${patches}" + OPTIONS "${options}" + FIND_PACKAGE_ARGUMENTS "${find_args}" + BUNDLED_PACKAGE "${bundled}" + SOURCE_SUBDIR "${source_subdir}" + + GIT_VERSION ${git_version} + ARTIFACT ${artifact} + TAG ${tag} + ) + + # pass stuff to parent scope + set(${package}_ADDED "${${package}_ADDED}" + PARENT_SCOPE) + set(${package}_SOURCE_DIR "${${package}_SOURCE_DIR}" + PARENT_SCOPE) + set(${package}_BINARY_DIR "${${package}_BINARY_DIR}" + PARENT_SCOPE) + +endfunction() + function(AddPackage) cpm_set_policies() @@ -64,9 +258,6 @@ function(AddPackage) GIT_URL KEY - DOWNLOAD_ONLY - FIND_PACKAGE_ARGUMENTS - SYSTEM_PACKAGE BUNDLED_PACKAGE ) @@ -79,6 +270,9 @@ function(AddPackage) cpm_utils_message(FATAL_ERROR "package" "No package name defined") endif() + option(${PKG_ARGS_NAME}_FORCE_SYSTEM "Force the system package for ${PKG_ARGS_NAME}") + option(${PKG_ARGS_NAME}_FORCE_BUNDLED "Force the bundled package for ${PKG_ARGS_NAME}") + if (DEFINED PKG_ARGS_URL) set(pkg_url ${PKG_ARGS_URL}) @@ -124,9 +318,9 @@ function(AddPackage) cpm_utils_message(STATUS ${PKG_ARGS_NAME} "Download URL is ${pkg_url}") if (DEFINED PKG_ARGS_GIT_VERSION) - set(git_version ${PKG_ARGS_VERSION}) - elseif(DEFINED PKG_ARGS_VERSION) set(git_version ${PKG_ARGS_GIT_VERSION}) + elseif(DEFINED PKG_ARGS_VERSION) + set(git_version ${PKG_ARGS_VERSION}) endif() if (NOT DEFINED PKG_ARGS_KEY) @@ -178,25 +372,55 @@ function(AddPackage) if (DEFINED hash_url) set(outfile ${CMAKE_CURRENT_BINARY_DIR}/${PKG_ARGS_NAME}.hash) - file(DOWNLOAD ${hash_url} ${outfile}) - file(READ ${outfile} pkg_hash_tmp) - file(REMOVE ${outfile}) + # TODO(crueter): This is kind of a bad solution + # because "technically" the hash is invalidated each week + # but it works for now kjsdnfkjdnfjksdn + string(TOLOWER ${PKG_ARGS_NAME} lowername) + if (NOT EXISTS ${outfile} AND NOT EXISTS ${CPM_SOURCE_CACHE}/${lowername}/${pkg_key}) + file(DOWNLOAD ${hash_url} ${outfile}) + endif() - set(pkg_hash "${hash_algo}=${pkg_hash_tmp}") + if (EXISTS ${outfile}) + file(READ ${outfile} pkg_hash_tmp) + endif() + + if (DEFINED ${pkg_hash_tmp}) + set(pkg_hash "${hash_algo}=${pkg_hash_tmp}") + endif() endif() - if (NOT CPMUTIL_DEFAULT_SYSTEM) - set(CPM_USE_LOCAL_PACKAGES OFF) - elseif (DEFINED PKG_ARGS_SYSTEM_PACKAGE) - set(CPM_USE_LOCAL_PACKAGES ${PKG_ARGS_SYSTEM_PACKAGE}) + macro(set_precedence local force) + set(CPM_USE_LOCAL_PACKAGES ${local}) + set(CPM_LOCAL_PACKAGES_ONLY ${force}) + endmacro() + + #[[ + Precedence: + - package_FORCE_SYSTEM + - package_FORCE_BUNDLED + - CPMUTIL_FORCE_SYSTEM + - CPMUTIL_FORCE_BUNDLED + - BUNDLED_PACKAGE + - default to allow local + ]]# + if (${PKG_ARGS_NAME}_FORCE_SYSTEM) + set_precedence(ON ON) + elseif (${PKG_ARGS_NAME}_FORCE_BUNDLED) + set_precedence(OFF OFF) + elseif (CPMUTIL_FORCE_SYSTEM) + set_precedence(ON ON) + elseif(NOT CPMUTIL_FORCE_BUNDLED) + set_precedence(OFF OFF) elseif (DEFINED PKG_ARGS_BUNDLED_PACKAGE) if (PKG_ARGS_BUNDLED_PACKAGE) - set(CPM_USE_LOCAL_PACKAGES OFF) + set(local OFF) else() - set(CPM_USE_LOCAL_PACKAGES ON) + set(local ON) endif() + + set_precedence(${local} OFF) else() - set(CPM_USE_LOCAL_PACKAGES ON) + set_precedence(ON OFF) endif() CPMAddPackage( @@ -210,6 +434,7 @@ function(AddPackage) OPTIONS ${PKG_ARGS_OPTIONS} PATCHES ${PKG_ARGS_PATCHES} + EXCLUDE_FROM_ALL ON ${PKG_ARGS_UNPARSED_ARGUMENTS} ) @@ -257,7 +482,7 @@ function(add_ci_package key) set(ARTIFACT ${ARTIFACT_NAME}-${key}-${ARTIFACT_VERSION}.${ARTIFACT_EXT}) AddPackage( - NAME ${ARTIFACT_PACKAGE}-${key} + NAME ${ARTIFACT_PACKAGE} REPO ${ARTIFACT_REPO} TAG v${ARTIFACT_VERSION} VERSION ${ARTIFACT_VERSION} @@ -266,15 +491,12 @@ function(add_ci_package key) KEY ${key} HASH_SUFFIX sha512sum BUNDLED_PACKAGE ON - DOWNLOAD_ONLY ON ) - if (NOT ARTIFACT_FORCE_DOWNLOAD OR ARTIFACT_OVERRIDE) - set(ARTIFACT_DIR ${${ARTIFACT_PACKAGE}-${key}_SOURCE_DIR} PARENT_SCOPE) - endif() + set(ARTIFACT_DIR ${${ARTIFACT_PACKAGE}_SOURCE_DIR} PARENT_SCOPE) endfunction() -# TODO(crueter): doc +# name is the artifact name, package is for find_package override function(AddCIPackage) set(oneValueArgs VERSION @@ -282,11 +504,9 @@ function(AddCIPackage) REPO PACKAGE EXTENSION - FORCE_DOWNLOAD MIN_VERSION DISABLED_PLATFORMS CMAKE_FILENAME - TARGET ) cmake_parse_arguments(PKG_ARGS "" "${oneValueArgs}" "" ${ARGN}) @@ -316,12 +536,6 @@ function(AddCIPackage) set(ARTIFACT_EXT ${PKG_ARGS_EXTENSION}) endif() - if(NOT DEFINED PKG_ARGS_FORCE_DOWNLOAD) - set(ARTIFACT_FORCE_DOWNLOAD OFF) - else() - set(ARTIFACT_FORCE_DOWNLOAD ${PKG_ARGS_FORCE_DOWNLOAD}) - endif() - if (DEFINED PKG_ARGS_MIN_VERSION) set(ARTIFACT_MIN_VERSION ${PKG_ARGS_MIN_VERSION}) endif() @@ -336,86 +550,42 @@ function(AddCIPackage) set(ARTIFACT_REPO ${PKG_ARGS_REPO}) set(ARTIFACT_PACKAGE ${PKG_ARGS_PACKAGE}) - if ((MSVC AND ARCHITECTURE_x86_64) OR ARTIFACT_FORCE_DOWNLOAD AND NOT "windows-amd64" IN_LIST DISABLED_PLATFORMS) - # kinda hacky - if(MSVC AND ARCHITECTURE_x86_64) - set(ARTIFACT_OVERRIDE ON) - endif() - + if ((MSVC AND ARCHITECTURE_x86_64) AND NOT "windows-amd64" IN_LIST DISABLED_PLATFORMS) add_ci_package(windows-amd64) - set(ARTIFACT_OVERRIDE OFF) endif() - if ((MSVC AND ARCHITECTURE_arm64) OR ARTIFACT_FORCE_DOWNLOAD AND NOT "windows-arm64" IN_LIST DISABLED_PLATFORMS) - if(MSVC AND ARCHITECTURE_arm64) - set(ARTIFACT_OVERRIDE ON) - endif() - + if ((MSVC AND ARCHITECTURE_arm64) AND NOT "windows-arm64" IN_LIST DISABLED_PLATFORMS) add_ci_package(windows-arm64) - set(ARTIFACT_OVERRIDE OFF) endif() - if (ANDROID OR ARTIFACT_FORCE_DOWNLOAD AND NOT "android" IN_LIST DISABLED_PLATFORMS) - if(ANDROID) - set(ARTIFACT_OVERRIDE ON) - endif() - + if (ANDROID AND NOT "android" IN_LIST DISABLED_PLATFORMS) add_ci_package(android) - set(ARTIFACT_OVERRIDE OFF) endif() - if(PLATFORM_SUN OR ARTIFACT_FORCE_DOWNLOAD AND NOT "solaris" IN_LIST DISABLED_PLATFORMS) - if(PLATFORM_SUN) - set(ARTIFACT_OVERRIDE ON) - endif() - + if(PLATFORM_SUN AND NOT "solaris" IN_LIST DISABLED_PLATFORMS) add_ci_package(solaris) - set(ARTIFACT_OVERRIDE OFF) endif() - if(PLATFORM_FREEBSD OR ARTIFACT_FORCE_DOWNLOAD AND NOT "freebsd" IN_LIST DISABLED_PLATFORMS) - if(PLATFORM_FREEBSD) - set(ARTIFACT_OVERRIDE ON) - endif() - + if(PLATFORM_FREEBSD AND NOT "freebsd" IN_LIST DISABLED_PLATFORMS) add_ci_package(freebsd) - set(ARTIFACT_OVERRIDE OFF) endif() - if((PLATFORM_LINUX AND ARCHITECTURE_x86_64) OR ARTIFACT_FORCE_DOWNLOAD AND NOT "linux" IN_LIST DISABLED_PLATFORMS) - if(PLATFORM_LINUX AND ARCHITECTURE_x86_64) - set(ARTIFACT_OVERRIDE ON) - endif() - + if((PLATFORM_LINUX AND ARCHITECTURE_x86_64) AND NOT "linux" IN_LIST DISABLED_PLATFORMS) add_ci_package(linux) - set(ARTIFACT_OVERRIDE OFF) endif() - if((PLATFORM_LINUX AND ARCHITECTURE_arm64) OR ARTIFACT_FORCE_DOWNLOAD AND NOT "linux-aarch64" IN_LIST DISABLED_PLATFORMS) - if(PLATFORM_LINUX AND ARCHITECTURE_arm64) - set(ARTIFACT_OVERRIDE ON) - endif() - + if((PLATFORM_LINUX AND ARCHITECTURE_arm64) AND NOT "linux-aarch64" IN_LIST DISABLED_PLATFORMS) add_ci_package(linux-aarch64) - set(ARTIFACT_OVERRIDE OFF) endif() if (DEFINED ARTIFACT_DIR) - if (NOT DEFINED PKG_ARGS_TARGET OR NOT TARGET "${PKG_ARGS_TARGET}") - include(${ARTIFACT_DIR}/${ARTIFACT_CMAKE}.cmake) + include(${ARTIFACT_DIR}/${ARTIFACT_CMAKE}.cmake) - # Overrides find package - CPMAddPackage( - NAME ${ARTIFACT_PACKAGE} - SOURCE_DIR ${ARTIFACT_DIR} - ) + set_property(GLOBAL APPEND PROPERTY CPM_PACKAGE_NAMES ${ARTIFACT_NAME}) + set_property(GLOBAL APPEND PROPERTY CPM_PACKAGE_URLS "https://github.com/${ARTIFACT_REPO}") # TODO(crueter) other hosts? + set_property(GLOBAL APPEND PROPERTY CPM_PACKAGE_SHAS ${ARTIFACT_VERSION}) - set_property(GLOBAL APPEND PROPERTY CPM_PACKAGE_NAMES ${ARTIFACT_NAME}) - set_property(GLOBAL APPEND PROPERTY CPM_PACKAGE_URLS "https://github.com/${ARTIFACT_REPO}") # TODO(crueter) other hosts? - set_property(GLOBAL APPEND PROPERTY CPM_PACKAGE_SHAS ${ARTIFACT_VERSION}) - - set(${ARTIFACT_PACKAGE}_ADDED TRUE PARENT_SCOPE) - endif() + set(${ARTIFACT_PACKAGE}_ADDED TRUE PARENT_SCOPE) else() find_package(${ARTIFACT_PACKAGE} ${ARTIFACT_MIN_VERSION} REQUIRED) endif() diff --git a/CMakeModules/DownloadExternals.cmake b/CMakeModules/DownloadExternals.cmake index 642d7d0df1..de45d15d2a 100644 --- a/CMakeModules/DownloadExternals.cmake +++ b/CMakeModules/DownloadExternals.cmake @@ -29,6 +29,7 @@ function(download_bundled_external remote_path lib_name cpm_key prefix_var versi set(package_url "${package_base_url}${package_repo}") set(full_url ${package_url}${remote_path}${lib_name}${package_extension}) + # TODO(crueter): DELETE THIS ENTIRELY, GLORY BE TO THE CI! AddPackage( NAME ${cpm_key} VERSION ${version} diff --git a/CMakeModules/FindSPIRV-Tools.cmake b/CMakeModules/FindSPIRV-Tools.cmake new file mode 100644 index 0000000000..aef74df5d9 --- /dev/null +++ b/CMakeModules/FindSPIRV-Tools.cmake @@ -0,0 +1,19 @@ +# SPDX-FileCopyrightText: 2022 yuzu Emulator Project +# SPDX-License-Identifier: GPL-2.0-or-later + +include(FindPackageHandleStandardArgs) + +find_package(PkgConfig QUIET) +pkg_search_module(SPIRV-Tools QUIET IMPORTED_TARGET SPIRV-Tools) +find_package_handle_standard_args(SPIRV-Tools + REQUIRED_VARS SPIRV-Tools_LINK_LIBRARIES + VERSION_VAR SPIRV-Tools_VERSION +) + +if (SPIRV-Tools_FOUND AND NOT TARGET SPIRV-Tools::SPIRV-Tools) + if (TARGET SPIRV-Tools) + add_library(SPIRV-Tools::SPIRV-Tools ALIAS SPIRV-Tools) + else() + add_library(SPIRV-Tools::SPIRV-Tools ALIAS PkgConfig::SPIRV-Tools) + endif() +endif() diff --git a/CMakeModules/Findzstd.cmake b/CMakeModules/Findzstd.cmake index ae3ea08653..bf38d20fbf 100644 --- a/CMakeModules/Findzstd.cmake +++ b/CMakeModules/Findzstd.cmake @@ -3,17 +3,12 @@ include(FindPackageHandleStandardArgs) -find_package(zstd QUIET CONFIG) -if (zstd_CONSIDERED_CONFIGS) - find_package_handle_standard_args(zstd CONFIG_MODE) -else() - find_package(PkgConfig QUIET) - pkg_search_module(ZSTD QUIET IMPORTED_TARGET libzstd) - find_package_handle_standard_args(zstd - REQUIRED_VARS ZSTD_LINK_LIBRARIES - VERSION_VAR ZSTD_VERSION - ) -endif() +find_package(PkgConfig QUIET) +pkg_search_module(ZSTD QUIET IMPORTED_TARGET libzstd) +find_package_handle_standard_args(zstd + REQUIRED_VARS ZSTD_LINK_LIBRARIES + VERSION_VAR ZSTD_VERSION +) if (zstd_FOUND AND NOT TARGET zstd::zstd) if (TARGET zstd::libzstd_shared) diff --git a/cpmfile.json b/cpmfile.json new file mode 100644 index 0000000000..495382fed0 --- /dev/null +++ b/cpmfile.json @@ -0,0 +1,147 @@ +{ + "openssl": { + "ci": true, + "package": "OpenSSL", + "name": "openssl", + "repo": "crueter-ci/OpenSSL", + "version": "3.5.2", + "min_version": "1.1.1" + }, + "boost": { + "package": "Boost", + "repo": "boostorg/boost", + "tag": "boost-1.88.0", + "artifact": "boost-1.88.0-cmake.7z", + "hash": "e5b049e5b61964480ca816395f63f95621e66cb9bcf616a8b10e441e0e69f129e22443acb11e77bc1e8170f8e4171b9b7719891efc43699782bfcd4b3a365f01", + "git_version": "1.88.0", + "version": "1.57" + }, + "fmt": { + "repo": "fmtlib/fmt", + "sha": "40626af88b", + "hash": "d59f06c24339f223de4ec2afeba1c67b5835a0f350a1ffa86242a72fc3e616a6b8b21798355428d4200c75287308b66634619ffa0b52ba5bd74cc01772ea1a8a", + "version": "8", + "options": [ + "FMT_INSTALL OFF" + ] + }, + "lz4": { + "name": "lz4", + "repo": "lz4/lz4", + "sha": "ebb370ca83", + "hash": "43600e87b35256005c0f2498fa56a77de6783937ba4cfce38c099f27c03188d097863e8a50c5779ca0a7c63c29c4f7ed0ae526ec798c1fd2e3736861b62e0a37", + "source_subdir": "build/cmake" + }, + "nlohmann": { + "package": "nlohmann_json", + "repo": "nlohmann/json", + "sha": "55f93686c0", + "hash": "b739749b066800e21154506ea150d2c5cbce8a45344177f46f884547a1399d26753166fd0df8135269ce28cf223552b1b65cd625b88c844d54753f2434900486", + "version": "3.8" + }, + "zlib": { + "package": "ZLIB", + "repo": "madler/zlib", + "sha": "51b7f2abda", + "hash": "16eaf1f3752489d12fd9ce30f7b5f7cbd5cb8ff53d617005a9847ae72d937f65e01e68be747f62d7ac19fd0c9aeba9956e60f16d6b465c5fdc2f3d08b4db2e6c", + "version": "1.2", + "options": [ + "ZLIB_BUILD_SHARED OFF", + "ZLIB_INSTALL OFF" + ] + }, + "zstd": { + "repo": "facebook/zstd", + "sha": "f8745da6ff", + "hash": "3037007f990040fe32573b46f9bef8762fd5dbeeb07ffffcbfeba51ec98167edae39bb9c87f9299efcd61c4e467c5e84f7c19f0df7799bc1fc04864a278792ee", + "version": "1.5", + "source_subdir": "build/cmake", + "find_args": "MODULE", + "options": [ + "ZSTD_BUILD_SHARED OFF" + ] + }, + "catch2": { + "package": "Catch2", + "repo": "catchorg/Catch2", + "sha": "644821ce28", + "hash": "f8795f98acf2c02c0db8e734cc866d5caebab4b4a306e93598b97cb3c0c728dafe8283dce27ffe8d42460e5ae7302f3f32e7e274a7f991b73511ac88eef21b1f", + "version": "3.0.1" + }, + "enet": { + "repo": "lsalzman/enet", + "sha": "2662c0de09", + "hash": "3de1beb4fa3d6b1e03eda8dd1e7580694f854af3ed3975dcdabfdcdf76b97f322b9734d35ea7f185855bb490d957842b938b26da4dd2dfded509390f8d2794dd", + "version": "1.3", + "find_args": "MODULE" + }, + "opus": { + "package": "Opus", + "repo": "xiph/opus", + "sha": "5ded705cf4", + "hash": "0dc89e58ddda1f3bc6a7037963994770c5806c10e66f5cc55c59286fc76d0544fe4eca7626772b888fd719f434bc8a92f792bdb350c807968b2ac14cfc04b203", + "version": "1.3", + "find_args": "MODULE", + "options": [ + "OPUS_BUILD_TESTING OFF", + "OPUS_BUILD_PROGRAMS OFF", + "OPUS_INSTALL_PKG_CONFIG_MODULE OFF", + "OPUS_INSTALL_CMAKE_CONFIG_MODULE OFF" + ] + }, + "cubeb": { + "repo": "mozilla/cubeb", + "sha": "fa02160712", + "hash": "82d808356752e4064de48c8fecbe7856715ade1e76b53937116bf07129fc1cc5b3de5e4b408de3cd000187ba8dc32ca4109661cb7e0355a52e54bd81b9be1c61", + "find_args": "CONFIG", + "options": [ + "USE_SANITIZERS OFF", + "BUILD_TESTS OFF", + "BUILD_TOOLS OFF", + "BUNDLE_SPEEX ON" + ] + }, + "boost_headers": { + "repo": "boostorg/headers", + "sha": "0456900fad", + "hash": "50cd75dcdfc5f082225cdace058f47b4fb114a47585f7aee1d22236a910a80b667186254c214fa2fcebac67ae6d37ba4b6e695e1faea8affd6fd42a03cf996e3", + "bundled": true + }, + "discord-rpc": { + "repo": "eden-emulator/discord-rpc", + "sha": "1cf7772bb6", + "hash": "e9b35e6f2c075823257bcd59f06fe7bb2ccce1976f44818d2e28810435ef79c712a3c4f20f40da41f691342a4058cf86b078eb7f9d9e4dae83c0547c21ec4f97" + }, + "simpleini": { + "package": "SimpleIni", + "repo": "brofield/simpleini", + "sha": "09c21bda1d", + "hash": "99779ca9b6e040d36558cadf484f9ffdab5b47bcc8fc72e4d33639d1d60c0ceb4410d335ba445d72a4324e455167fd6769d99b459943aa135bec085dff2d4b7c", + "find_args": "MODULE" + }, + "sdl2_generic": { + "package": "SDL2", + "repo": "libsdl-org/SDL", + "sha": "54772f345a", + "hash": "2a68a0e01c390043aa9d9df63d8a20a52076c88bb460ac4e0f33194ca7d9bc8fadbbcc04e7506872ac4b6354a73fbc267c036f82200da59465789b87c7d9e3a4", + "key": "generic", + "bundled": true + }, + "sdl2_steamdeck": { + "package": "SDL2", + "repo": "libsdl-org/SDL", + "sha": "cc016b0046", + "hash": "34d5ef58da6a4f9efa6689c82f67badcbd741f5a4f562a9c2c30828fa839830fb07681c5dc6a7851520e261c8405a416ac0a2c2513b51984fb3b4fa4dcb3e20b", + "key": "steamdeck", + "bundled": true + }, + "sdl2": { + "ci": true, + "package": "SDL2", + "name": "SDL2", + "repo": "crueter-ci/SDL2", + "version": "2.32.8", + "min_version": "2.26.4", + "cmake_filename": "sdl2" + } +} diff --git a/docs/CPM.md b/docs/CPM.md new file mode 100644 index 0000000000..f90002891c --- /dev/null +++ b/docs/CPM.md @@ -0,0 +1,252 @@ +# CPM + +CPM (CMake Package Manager) is the preferred method of managing dependencies within Eden. + +Global Options: + +- `YUZU_USE_CPM` is set by default on MSVC and Android. Other platforms should use this if certain "required" system dependencies (e.g. OpenSSL) are broken or missing + * If this is `OFF`, required system dependencies will be searched via `find_package`, although certain externals use CPM regardless. +- `CPMUTIL_FORCE_SYSTEM` (default `OFF`): Require all CPM dependencies to use system packages. NOT RECOMMENDED! + * Many packages, e.g. mcl, sirit, xbyak, discord-rpc, are not generally available as a system package. + * You may optionally override these (see CPMUtil section) +- `CPMUTIL_FORCE_BUNDLED` (default `ON` on MSVC and Android, `OFF` elsewhere): Require all CPM dependencies to use bundled packages. + +## CPMUtil + +CPMUtil is a wrapper around CPM that aims to reduce boilerplate and add useful utility functions to make dependency management a piece of cake. + +### AddPackage + +`AddPackage` is the core of the CPMUtil wrapper, and is generally the lowest level you will need to go when dealing with dependencies. + +**Identification/Fetching** + +- `NAME` (required): The package name (must be the same as the `find_package` name if applicable) +- `VERSION`: The minimum version of this package that can be used on the system +- `GIT_VERSION`: The version found within git, only used for identification +- `URL`: The URL to fetch. +- `REPO`: The GitHub repo to use (`owner/repo`). + * Only GitHub is supported for now, though other platforms will see support at some point +- `TAG`: The tag to fetch, if applicable. +- `ARTIFACT`: The name of the artifact, if applicable. +- `SHA`: Commit sha to fetch, if applicable. +- `BRANCH`: Branch to fetch, if applicable. + +The following configurations are supported, in descending order of precedence: + +- `URL`: Bare URL download, useful for custom artifacts + * If this is set, `GIT_URL` or `REPO` should be set to allow the dependency viewer to link to the project's Git repository. + * If this is NOT set, `REPO` must be defined. +- `REPO + TAG + ARTIFACT`: GitHub release artifact + * The final download URL will be `https://github.com/${REPO}/releases/download/${TAG}/${ARTIFACT}` + * Useful for prebuilt libraries and prefetched archives +- `REPO + TAG`: GitHub tag archive + * The final download URL will be `https://github.com/${REPO}/archive/refs/tags/${TAG}.tar.gz` + * Useful for pinning to a specific tag, better for build identification +- `REPO + SHA`: GitHub commit archive + * The final download URL will be `https://github.com/${REPO}/archive/${SHA}.zip` + * Useful for pinning to a specific commit +- `REPO + BRANCH`: GitHub branch archive + * The final download URL will be `https://github.com/${REPO}/archive/refs/heads/${BRANCH}.zip` + * Generally not recommended unless the branch is frozen +- `REPO`: GitHub master archive + * The final download URL will be `https://github.com/${REPO}/archive/refs/heads/master.zip` + * Generally not recommended unless the project is dead + +**Hashing** + +Hashing is used for verifying downloads. It's highly recommended to use these. + +- `HASH_ALGO` (default `SHA512`): Hash algorithm to use + +Hashing strategies, descending order of precedence: + +- `HASH`: Bare hash verification, useful for static downloads e.g. commit archives +- `HASH_SUFFIX`: Download the hash as `${DOWNLOAD_URL}.${HASH_SUFFIX}` + * The downloaded hash *must* match the hash algorithm and contain nothing but the hash; no filenames or extra content. +- `HASH_URL`: Download the hash from a separate URL + +**Additional Options** + +- `KEY`: Custom cache key to use (stored as `.cache/cpm/${packagename_lower}/${key}`) + * Default is based on, in descending order of precedence: + - First 4 characters of the sha + - `GIT_VERSION`, or `VERSION` if not specified + - Tag + - Otherwise, CPM defaults will be used. This is not recommended as it doesn't produce reproducible caches +- `DOWNLOAD_ONLY`: Whether or not to configure the downloaded package via CMake + * Useful to turn `OFF` if the project doesn't use CMake +- `SOURCE_SUBDIR`: Subdirectory of the project containing a CMakeLists.txt file +- `FIND_PACKAGE_ARGUMENTS`: Arguments to pass to the `find_package` call +- `BUNDLED_PACKAGE`: Set to `ON` to force the usage of a bundled package +- `OPTIONS`: Options to pass to the configuration of the package +- `PATCHES`: Patches to apply to the package, stored in `.patch/${packagename_lower}/0001-patch-name.patch` and so on +- Other arguments can be passed to CPM as well + +**Extra Variables** + +For each added package, users may additionally force usage of the system/bundled package. + +- `${package}_FORCE_SYSTEM`: Require the package to be installed on the system +- `${package}_FORCE_BUNDLED`: Force the package to be fetched and use the bundled version + +**Bundled/System Switching** + +Descending order of precedence: +- If `${package}_FORCE_SYSTEM` is true, requires the package to be on the system +- If `${package}_FORCE_BUNDLED` is true, forcefully uses the bundled package +- If `CPMUTIL_FORCE_SYSTEM` is true, requires the package to be on the system +- If `CPMUTIL_FORCE_BUNDLED` is true, forcefully uses the bundled package +- If the `BUNDLED_PACKAGE` argument is true, forcefully uses the bundled package +- Otherwise, CPM will search for the package first, and if not found, will use the bundled package + +**Identification** + +All dependencies must be identifiable in some way for usage in the dependency viewer. Lists are provided in descending order of precedence. + +URLs: + +- `GIT_URL` +- `REPO` as a GitHub repository +- `URL` + +Versions (bundled): + +- `SHA` +- `GIT_VERSION` +- `VERSION` +- `TAG` +- "unknown" + +If the package is a system package, AddPackage will attempt to determine the package version and append ` (system)` to the identifier. Otherwise, it will be marked as `unknown (system)` + +### AddCIPackage + +Adds a package that follows crueter's CI repository spec. + +- `VERSION` (required): The version to get (the tag will be `v${VERSION}`) +- `NAME` (required): Name used within the artifacts +- `REPO` (required): CI repository, e.g. `crueter-ci/OpenSSL` +- `PACKAGE` (required): `find_package` package name +- `EXTENSION`: Artifact extension (default `tar.zst`) +- `MIN_VERSION`: Minimum version for `find_package`. Only used if platform does not support this package as a bundled artifact +- `DISABLED_PLATFORMS`: List of platforms that lack artifacts for this package. One of: + * `windows-amd64` + * `windows-arm64` + * `android` + * `solaris` + * `freebsd` + * `linux` + * `linux-aarch64` +- `CMAKE_FILENAME`: Custom CMake filename, relative to the package root (default `${PACKAGE_ROOT}/${NAME}.cmake`) + +### AddJsonPackage + +This is the recommended method of usage for CPMUtil. In each directory that utilizes `CPMUtil`, there must be a `cpmfile.json` that defines dependencies in a similar manner to the individual calls. + +The cpmfile is an object of objects, with each sub-object being named according to the package's identifier, e.g. `openssl`, which can then be fetched with `AddJsonPackage()`. Options are designed to map closely to the argument names, and are always strings unless otherwise specified. + +- `package` -> `NAME` (`PACKAGE` for CI), defaults to the object key +- `repo` -> `REPO` +- `version` -> `VERSION` +- `ci` (bool) + +If `ci` is `false`: + +- `hash` -> `HASH` +- `sha` -> `SHA` +- `tag` -> `TAG` +- `artifact` -> `ARTIFACT` +- `git_version` -> `GIT_VERSION` +- `source_subdir` -> `SOURCE_SUBDIR` +- `bundled` -> `BUNDLED_PACKAGE` +- `find_args` -> `FIND_PACKAGE_ARGUMENTS` +- `patches` -> `PATCHES` (array) +- `options` -> `OPTIONS` (array) + +Other arguments aren't currently supported. If you wish to add them, see the `AddJsonPackage` function in `CMakeModules/CPMUtil.cmake`. + +If `ci` is `true`: + +- `name` -> `NAME`, defaults to the object key +- `extension` -> `EXTENSION`, defaults to `tar.zst` +- `min_version` -> `MIN_VERSION` +- `cmake_filename` -> `CMAKE_FILENAME` +- `extension` -> `EXTENSION` + +### Examples + +In order: OpenSSL CI, Boost (tag + artifact), discord-rpc (sha + options + patches), Opus (options + find_args) + +```json +{ + "openssl": { + "ci": true, + "package": "OpenSSL", + "name": "openssl", + "repo": "crueter-ci/OpenSSL", + "version": "3.5.2", + "min_version": "1.1.1" + }, + "boost": { + "package": "Boost", + "repo": "boostorg/boost", + "tag": "boost-1.88.0", + "artifact": "boost-1.88.0-cmake.7z", + "hash": "e5b049e5b61964480ca816395f63f95621e66cb9bcf616a8b10e441e0e69f129e22443acb11e77bc1e8170f8e4171b9b7719891efc43699782bfcd4b3a365f01", + "git_version": "1.88.0", + "version": "1.57" + }, + "opus": { + "package": "Opus", + "repo": "xiph/opus", + "sha": "5ded705cf4", + "hash": "0dc89e58ddda1f3bc6a7037963994770c5806c10e66f5cc55c59286fc76d0544fe4eca7626772b888fd719f434bc8a92f792bdb350c807968b2ac14cfc04b203", + "version": "1.3", + "find_args": "MODULE", + "options": [ + "OPUS_BUILD_TESTING OFF", + "OPUS_BUILD_PROGRAMS OFF", + "OPUS_INSTALL_PKG_CONFIG_MODULE OFF", + "OPUS_INSTALL_CMAKE_CONFIG_MODULE OFF" + ] + }, + "discord-rpc": { + "repo": "discord/discord-rpc", + "sha": "963aa9f3e5", + "hash": "386e1344e9a666d730f2d335ee3aef1fd05b1039febefd51aa751b705009cc764411397f3ca08dffd46205c72f75b235c870c737b2091a4ed0c3b061f5919bde", + "options": [ + "BUILD_EXAMPLES OFF" + ], + "patches": [ + "0001-cmake-version.patch", + "0002-no-clang-format.patch", + "0003-fix-cpp17.patch" + ] + }, +} +``` + +### Inclusion + +To include CPMUtil: + +```cmake +set(CPMUTIL_JSON_FILE ${CMAKE_CURRENT_SOURCE_DIR}/cpmfile.json) +include(CPMUtil) +``` + +You may omit the first line if you are not utilizing cpmfile. + +## Prefetching + +- To prefetch a CPM dependency (requires cpmfile): + * `tools/cpm-fetch.sh ` +- To prefetch all CPM dependencies: + * `tools/cpm-fetch-all.sh` + +Currently, `cpm-fetch.sh` defines the following directories for cpmfiles: + +`externals src/yuzu/externals externals/ffmpeg src/dynarmic/externals externals/nx_tzdb` + +Whenever you add a new cpmfile, update the script accordingly \ No newline at end of file diff --git a/externals/CMakeLists.txt b/externals/CMakeLists.txt index 07e9ae7a8f..b209b48db9 100644 --- a/externals/CMakeLists.txt +++ b/externals/CMakeLists.txt @@ -7,7 +7,8 @@ # TODO(crueter): A lot of this should be moved to the root. # otherwise we have to do weird shenanigans with library linking and stuff -# cpm +# Explicitly include CPMUtil here since we have a separate cpmfile for externals +set(CPMUTIL_JSON_FILE ${CMAKE_CURRENT_SOURCE_DIR}/cpmfile.json) include(CPMUtil) # Explicitly declare this option here to propagate to the oaknut CPM call @@ -33,32 +34,15 @@ endif() # Xbyak (also used by Dynarmic, so needs to be added first) if (ARCHITECTURE_x86 OR ARCHITECTURE_x86_64) if (PLATFORM_SUN) - # Fix regset.h collisions - set(XBYAK_HASH 51f507b0b3) - set(XBYAK_SHA512SUM 4a29a3c2f97f7d5adf667a21a008be03c951fb6696b0d7ba27e7e4afa037bc76eb5e059bb84860e01baf741d4d3ac851b840cd54c99d038812fbe0f1fa6d38a4) + AddJsonPackage(xbyak_sun) else() - set(XBYAK_HASH 4e44f4614d) - set(XBYAK_SHA512SUM 5824e92159e07fa36a774aedd3b3ef3541d0241371d522cffa4ab3e1f215fa5097b1b77865b47b2481376c704fa079875557ea463ca63d0a7fd6a8a20a589e70) + AddJsonPackage(xbyak) endif() - - AddPackage( - NAME xbyak - REPO "Lizzie841/xbyak" - SHA ${XBYAK_HASH} - HASH ${XBYAK_SHA512SUM} - BUNDLED_PACKAGE ON - ) endif() # Oaknut (also used by Dynarmic, so needs to be added first) if (ARCHITECTURE_arm64 OR DYNARMIC_TESTS) - AddPackage( - NAME oaknut - VERSION 2.0.1 - REPO "merryhime/oaknut" - SHA 94c726ce03 - HASH d8d082242fa1881abce3c82f8dafa002c4e561e66a69e7fc038af67faa5eff2630f082d3d19579c88c4c9f9488e54552accc8cb90e7ce743efe043b6230c08ac - ) + AddJsonPackage(oaknut) endif() # getopt @@ -70,14 +54,7 @@ endif() add_subdirectory(glad) # mbedtls -AddPackage( - NAME mbedtls - REPO "Mbed-TLS/mbedtls" - SHA "8c88150ca1" - HASH 769ad1e94c570671071e1f2a5c0f1027e0bf6bcdd1a80ea8ac970f2c86bc45ce4e31aa88d6d8110fc1bed1de81c48bc624df1b38a26f8b340a44e109d784a966 - PATCHES - ${CMAKE_SOURCE_DIR}/.patch/mbedtls/0001-cmake-version.patch -) +AddJsonPackage(mbedtls) if (mbedtls_ADDED) target_include_directories(mbedtls PUBLIC ${mbedtls_SOURCE_DIR}/include) @@ -97,23 +74,11 @@ endif() # Sirit # TODO(crueter): spirv-tools doesn't work w/ system set(SPIRV_WERROR OFF) -AddPackage( - NAME SPIRV-Headers - REPO "KhronosGroup/SPIRV-Headers" - SHA 4e209d3d7e - HASH f48bbe18341ed55ea0fe280dbbbc0a44bf222278de6e716e143ca1e95ca320b06d4d23d6583fbf8d03e1428f3dac8fa00e5b82ddcd6b425e6236d85af09550a4 -) +AddJsonPackage(spirv-headers) -AddPackage( - NAME sirit - REPO "eden-emulator/sirit" - SHA db1f1e8ab5 - HASH 73eb3a042848c63a10656545797e85f40d142009dfb7827384548a385e1e28e1ac72f42b25924ce530d58275f8638554281e884d72f9c7aaf4ed08690a414b05 - OPTIONS - "SIRIT_USE_SYSTEM_SPIRV_HEADERS ON" -) +AddJsonPackage(sirit) -if(MSVC AND USE_CCACHE AND TARGET sirit) +if(MSVC AND USE_CCACHE AND sirit_ADDED) get_target_property(_opts sirit COMPILE_OPTIONS) list(FILTER _opts EXCLUDE REGEX "/Zi") list(APPEND _opts "/Z7") @@ -122,33 +87,12 @@ endif() # httplib if (ENABLE_WEB_SERVICE OR ENABLE_QT_UPDATE_CHECKER) - AddPackage( - NAME httplib - REPO "yhirose/cpp-httplib" - SHA a609330e4c - HASH dd3fd0572f8367d8549e1319fd98368b3e75801a293b0c3ac9b4adb806473a4506a484b3d389dc5bee5acc460cb90af7a20e5df705a1696b56496b30b9ce7ed2 - OPTIONS - "HTTPLIB_REQUIRE_OPENSSL ${ENABLE_OPENSSL}" - ) + AddJsonPackage(httplib) endif() # cpp-jwt if (ENABLE_WEB_SERVICE) - AddPackage( - NAME cpp-jwt - VERSION 1.4 - REPO "arun11299/cpp-jwt" - SHA a54fa08a3b - HASH a90f7e594ada0c7e49d5ff9211c71097534e7742a8e44bf0851b0362642a7271d53f5d83d04eeaae2bad17ef3f35e09e6818434d8eaefa038f3d1f7359d0969a - FIND_PACKAGE_ARGUMENTS "CONFIG" - OPTIONS - "CPP_JWT_BUILD_EXAMPLES OFF" - "CPP_JWT_BUILD_TESTS OFF" - "CPP_JWT_USE_VENDORED_NLOHMANN_JSON OFF" - PATCHES - ${CMAKE_SOURCE_DIR}/.patch/cpp-jwt/0001-no-install.patch - ${CMAKE_SOURCE_DIR}/.patch/cpp-jwt/0002-missing-decl.patch - ) + AddJsonPackage(cpp-jwt) endif() # unordered_dense @@ -175,47 +119,33 @@ endif() # TODO(crueter): Vk1.4 impl -AddPackage( - NAME VulkanHeaders - VERSION 1.3.274 - REPO "KhronosGroup/Vulkan-Headers" - SHA 89268a6d17 - HASH 3ab349f74298ba72cafb8561015690c0674d428a09fb91ccd3cd3daca83650d190d46d33fd97b0a8fd4223fe6df2bcabae89136fbbf7c0bfeb8776f9448304c8 +AddJsonPackage( + NAME vulkan-headers BUNDLED_PACKAGE ${YUZU_USE_EXTERNAL_VULKAN_HEADERS} ) # Vulkan-Utility-Libraries -AddPackage( - NAME VulkanUtilityLibraries - REPO "KhronosGroup/Vulkan-Utility-Libraries" - SHA df2e358152 - HASH 3e468c3d9ff93f6d418d71e5527abe0a12c8c7ab5b0b52278bbbee4d02bb87e99073906729b727e0147242b7e3fd5dedf68b803f1878cb4c0e4f730bc2238d79 +AddJsonPackage( + NAME vulkan-utility-libraries BUNDLED_PACKAGE ${YUZU_USE_EXTERNAL_VULKAN_UTILITY_LIBRARIES} ) -# SPIRV-Tools -if (YUZU_USE_EXTERNAL_VULKAN_SPIRV_TOOLS) - AddPackage( - NAME SPIRV-Tools - REPO "KhronosGroup/SPIRV-Tools" - SHA 40eb301f32 - HASH 58d0fb1047d69373cf24c73e6f78c73a72a6cca3b4df1d9f083b9dcc0962745ef154abf3dbe9b3623b835be20c6ec769431cf11733349f45e7568b3525f707aa - OPTIONS - "SPIRV_SKIP_EXECUTABLES ON" - ) +# SPIRV Tools +AddJsonPackage( + NAME spirv-tools + BUNDLED_PACKAGE ${YUZU_USE_EXTERNAL_VULKAN_SPIRV_TOOLS} +) + +if (SPIRV-Tools_ADDED) + add_library(SPIRV-Tools::SPIRV-Tools ALIAS SPIRV-Tools-static) + target_link_libraries(SPIRV-Tools-static PRIVATE SPIRV-Tools-opt SPIRV-Tools-link) endif() # TZDB (Time Zone Database) add_subdirectory(nx_tzdb) # VMA -AddPackage( - NAME VulkanMemoryAllocator - REPO "GPUOpen-LibrariesAndSDKs/VulkanMemoryAllocator" - SHA 1076b348ab - HASH a46b44e4286d08cffda058e856c47f44c7fed3da55fe9555976eb3907fdcc20ead0b1860b0c38319cda01dbf9b1aa5d4b4038c7f1f8fbd97283d837fa9af9772 - FIND_PACKAGE_ARGUMENTS "CONFIG" -) +AddJsonPackage(vulkan-memory-allocator) if (NOT TARGET LLVM::Demangle) add_library(demangle demangle/ItaniumDemangle.cpp) @@ -245,17 +175,8 @@ if (NOT TARGET RenderDoc::API) add_library(RenderDoc::API ALIAS renderdoc) endif() -if (ANDROID) - if (ARCHITECTURE_arm64) - AddPackage( - NAME libadrenotools - REPO "bylaws/libadrenotools" - SHA 8fae8ce254 - HASH c74fa855f0edebbf25c9bce40b00966daa2447bfc5e15f0cf1a95f86cbf70fc6b02590707edbde16328a0a2a4fb9a1fc419d2dfc22a4a4150971be91892d4edb - PATCHES - ${CMAKE_SOURCE_DIR}/.patch/libadrenotools/0001-linkerns-cpm.patch - ) - endif() +if (ANDROID AND ARCHITECTURE_arm64) + AddJsonPackage(libadrenotools) endif() if (UNIX AND NOT APPLE AND NOT TARGET gamemode::headers) @@ -278,6 +199,7 @@ if (YUZU_CRASH_DUMPS AND NOT TARGET libbreakpad_client) _CRT_NONSTDC_NO_DEPRECATE ) + # TODO AddPackage( NAME breakpad URL "google/breakpad" @@ -378,13 +300,7 @@ endif() # oboe if (ANDROID) - AddPackage( - NAME oboe - REPO "google/oboe" - SHA 2bc873e53c - HASH 02329058a7f9cf7d5039afaae5ab170d9f42f60f4c01e21eaf4f46073886922b057a9ae30eeac040b3ac182f51b9c1bfe9fe1050a2c9f6ce567a1a9a0ec2c768 - BUNDLED_PACKAGE ON - ) + AddJsonPackage(oboe) add_library(oboe::oboe ALIAS oboe) endif() diff --git a/externals/cpmfile.json b/externals/cpmfile.json new file mode 100644 index 0000000000..effcbcc01f --- /dev/null +++ b/externals/cpmfile.json @@ -0,0 +1,109 @@ +{ + "mbedtls": { + "repo": "Mbed-TLS/mbedtls", + "sha": "8c88150ca1", + "hash": "769ad1e94c570671071e1f2a5c0f1027e0bf6bcdd1a80ea8ac970f2c86bc45ce4e31aa88d6d8110fc1bed1de81c48bc624df1b38a26f8b340a44e109d784a966", + "patches": [ + "0001-cmake-version.patch" + ] + }, + "spirv-headers": { + "package": "SPIRV-Headers", + "repo": "KhronosGroup/SPIRV-Headers", + "sha": "4e209d3d7e", + "hash": "f48bbe18341ed55ea0fe280dbbbc0a44bf222278de6e716e143ca1e95ca320b06d4d23d6583fbf8d03e1428f3dac8fa00e5b82ddcd6b425e6236d85af09550a4" + }, + "sirit": { + "repo": "eden-emulator/sirit", + "sha": "db1f1e8ab5", + "hash": "73eb3a042848c63a10656545797e85f40d142009dfb7827384548a385e1e28e1ac72f42b25924ce530d58275f8638554281e884d72f9c7aaf4ed08690a414b05", + "options": [ + "SIRIT_USE_SYSTEM_SPIRV_HEADERS ON" + ] + }, + "httplib": { + "repo": "yhirose/cpp-httplib", + "sha": "a609330e4c", + "hash": "dd3fd0572f8367d8549e1319fd98368b3e75801a293b0c3ac9b4adb806473a4506a484b3d389dc5bee5acc460cb90af7a20e5df705a1696b56496b30b9ce7ed2" + }, + "cpp-jwt": { + "version": "1.4", + "repo": "arun11299/cpp-jwt", + "sha": "a54fa08a3b", + "hash": "a90f7e594ada0c7e49d5ff9211c71097534e7742a8e44bf0851b0362642a7271d53f5d83d04eeaae2bad17ef3f35e09e6818434d8eaefa038f3d1f7359d0969a", + "find_args": "CONFIG", + "options": [ + "CPP_JWT_BUILD_EXAMPLES OFF", + "CPP_JWT_BUILD_TESTS OFF", + "CPP_JWT_USE_VENDORED_NLOHMANN_JSON OFF" + ], + "patches": [ + "0001-no-install.patch", + "0002-missing-decl.patch" + ] + }, + "vulkan-headers": { + "package": "VulkanHeaders", + "version": "1.3.274", + "repo": "KhronosGroup/Vulkan-Headers", + "sha": "89268a6d17", + "hash": "3ab349f74298ba72cafb8561015690c0674d428a09fb91ccd3cd3daca83650d190d46d33fd97b0a8fd4223fe6df2bcabae89136fbbf7c0bfeb8776f9448304c8" + }, + "vulkan-utility-libraries": { + "package": "VulkanUtilityLibraries", + "repo": "KhronosGroup/Vulkan-Utility-Libraries", + "sha": "df2e358152", + "hash": "3e468c3d9ff93f6d418d71e5527abe0a12c8c7ab5b0b52278bbbee4d02bb87e99073906729b727e0147242b7e3fd5dedf68b803f1878cb4c0e4f730bc2238d79" + }, + "vulkan-memory-allocator": { + "package": "VulkanMemoryAllocator", + "repo": "GPUOpen-LibrariesAndSDKs/VulkanMemoryAllocator", + "sha": "1076b348ab", + "hash": "a46b44e4286d08cffda058e856c47f44c7fed3da55fe9555976eb3907fdcc20ead0b1860b0c38319cda01dbf9b1aa5d4b4038c7f1f8fbd97283d837fa9af9772", + "find_args": "CONFIG" + }, + "spirv-tools": { + "package": "SPIRV-Tools", + "repo": "KhronosGroup/SPIRV-Tools", + "sha": "40eb301f32", + "hash": "58d0fb1047d69373cf24c73e6f78c73a72a6cca3b4df1d9f083b9dcc0962745ef154abf3dbe9b3623b835be20c6ec769431cf11733349f45e7568b3525f707aa", + "find_args": "MODULE", + "options": [ + "SPIRV_SKIP_EXECUTABLES ON" + ] + }, + "xbyak_sun": { + "package": "xbyak", + "repo": "Lizzie841/xbyak", + "sha": "51f507b0b3", + "hash": "4a29a3c2f97f7d5adf667a21a008be03c951fb6696b0d7ba27e7e4afa037bc76eb5e059bb84860e01baf741d4d3ac851b840cd54c99d038812fbe0f1fa6d38a4", + "bundled": true + }, + "xbyak": { + "package": "xbyak", + "repo": "Lizzie841/xbyak", + "sha": "4e44f4614d", + "hash": "5824e92159e07fa36a774aedd3b3ef3541d0241371d522cffa4ab3e1f215fa5097b1b77865b47b2481376c704fa079875557ea463ca63d0a7fd6a8a20a589e70", + "bundled": true + }, + "oaknut": { + "version": "2.0.1", + "repo": "merryhime/oaknut", + "sha": "94c726ce03", + "hash": "d8d082242fa1881abce3c82f8dafa002c4e561e66a69e7fc038af67faa5eff2630f082d3d19579c88c4c9f9488e54552accc8cb90e7ce743efe043b6230c08ac" + }, + "libadrenotools": { + "repo": "bylaws/libadrenotools", + "sha": "8fae8ce254", + "hash": "c74fa855f0edebbf25c9bce40b00966daa2447bfc5e15f0cf1a95f86cbf70fc6b02590707edbde16328a0a2a4fb9a1fc419d2dfc22a4a4150971be91892d4edb", + "patches": [ + "0001-linkerns-cpm.patch" + ] + }, + "oboe": { + "repo": "google/oboe", + "sha": "2bc873e53c", + "hash": "02329058a7f9cf7d5039afaae5ab170d9f42f60f4c01e21eaf4f46073886922b057a9ae30eeac040b3ac182f51b9c1bfe9fe1050a2c9f6ce567a1a9a0ec2c768", + "bundled": true + } +} diff --git a/externals/ffmpeg/CMakeLists.txt b/externals/ffmpeg/CMakeLists.txt index 048ab36c17..b514ede3be 100644 --- a/externals/ffmpeg/CMakeLists.txt +++ b/externals/ffmpeg/CMakeLists.txt @@ -1,6 +1,10 @@ # SPDX-FileCopyrightText: 2021 yuzu Emulator Project # SPDX-License-Identifier: GPL-2.0-or-later +# Explicitly include CPMUtil here since we have a separate cpmfile for ffmpeg +set(CPMUTIL_JSON_FILE ${CMAKE_CURRENT_SOURCE_DIR}/cpmfile.json) +include(CPMUtil) + if (NOT WIN32 AND NOT ANDROID) # Build FFmpeg from externals message(STATUS "Using FFmpeg from externals") @@ -19,13 +23,7 @@ if (NOT WIN32 AND NOT ANDROID) message(FATAL_ERROR "Required program `autoconf` not found.") endif() - AddPackage( - NAME ffmpeg - REPO "FFmpeg/FFmpeg" - SHA c2184b65d2 - HASH 2a89d664119debbb3c006ab1c48d5d7f26e889f4a65ad2e25c8b0503308295123d5a9c5c78bf683aef5ff09acef8c3fc2837f22d3e8c611528b933bf03bcdd97 - SYSTEM_PACKAGE OFF - ) + AddJsonPackage(ffmpeg) set(FFmpeg_PREFIX ${ffmpeg_SOURCE_DIR}) set(FFmpeg_BUILD_DIR ${ffmpeg_BINARY_DIR}) diff --git a/externals/ffmpeg/cpmfile.json b/externals/ffmpeg/cpmfile.json new file mode 100644 index 0000000000..dd9179703e --- /dev/null +++ b/externals/ffmpeg/cpmfile.json @@ -0,0 +1,8 @@ +{ + "ffmpeg": { + "repo": "FFmpeg/FFmpeg", + "sha": "c2184b65d2", + "hash": "2a89d664119debbb3c006ab1c48d5d7f26e889f4a65ad2e25c8b0503308295123d5a9c5c78bf683aef5ff09acef8c3fc2837f22d3e8c611528b933bf03bcdd97", + "bundled": true + } +} diff --git a/externals/nx_tzdb/CMakeLists.txt b/externals/nx_tzdb/CMakeLists.txt index a86a97b4da..5812a62f98 100644 --- a/externals/nx_tzdb/CMakeLists.txt +++ b/externals/nx_tzdb/CMakeLists.txt @@ -1,6 +1,10 @@ # SPDX-FileCopyrightText: 2023 yuzu Emulator Project # SPDX-License-Identifier: GPL-2.0-or-later +# Explicitly include CPMUtil here since we have a separate cpmfile for nx_tzdb +set(CPMUTIL_JSON_FILE ${CMAKE_CURRENT_SOURCE_DIR}/cpmfile.json) +include(CPMUtil) + set(NX_TZDB_INCLUDE_DIR "${CMAKE_CURRENT_BINARY_DIR}/include") add_library(nx_tzdb INTERFACE) @@ -28,28 +32,15 @@ if (CMAKE_SYSTEM_NAME STREQUAL "Windows" OR ANDROID) endif() set(NX_TZDB_VERSION "250725") -set(NX_TZDB_ARCHIVE "${CPM_SOURCE_CACHE}/nx_tzdb/${NX_TZDB_VERSION}.zip") -set(NX_TZDB_ROMFS_DIR "${CPM_SOURCE_CACHE}/nx_tzdb/tz") +set(NX_TZDB_ROMFS_DIR "${CPM_SOURCE_CACHE}/nx_tzdb/") if ((NOT CAN_BUILD_NX_TZDB OR YUZU_DOWNLOAD_TIME_ZONE_DATA) AND NOT EXISTS ${NX_TZDB_ROMFS_DIR}) - set(NX_TZDB_DOWNLOAD_URL "https://github.com/crueter/tzdb_to_nx/releases/download/${NX_TZDB_VERSION}/${NX_TZDB_VERSION}.zip") - - message(STATUS "Downloading time zone data from ${NX_TZDB_DOWNLOAD_URL}...") - file(DOWNLOAD ${NX_TZDB_DOWNLOAD_URL} ${NX_TZDB_ARCHIVE} - STATUS NX_TZDB_DOWNLOAD_STATUS) - list(GET NX_TZDB_DOWNLOAD_STATUS 0 NX_TZDB_DOWNLOAD_STATUS_CODE) - if (NOT NX_TZDB_DOWNLOAD_STATUS_CODE EQUAL 0) - message(FATAL_ERROR "Time zone data download failed (status code ${NX_TZDB_DOWNLOAD_STATUS_CODE})") - endif() - - file(ARCHIVE_EXTRACT - INPUT - ${NX_TZDB_ARCHIVE} - DESTINATION - ${NX_TZDB_ROMFS_DIR}) + message(STATUS "Downloading time zone data...") + AddJsonPackage(tzdb) elseif (CAN_BUILD_NX_TZDB AND NOT YUZU_DOWNLOAD_TIME_ZONE_DATA) # TODO(crueter): this sucked to do with cpm, see if i can get it to work again + message(FATAL_ERROR "Building tzdb is currently unsupported. Check back later.") add_subdirectory(tzdb_to_nx) add_dependencies(nx_tzdb x80e) @@ -79,24 +70,24 @@ function(CreateHeader ZONE_PATH HEADER_NAME) endfunction() CreateHeader(${NX_TZDB_ROMFS_DIR} base) -CreateHeader(${NX_TZDB_ROMFS_DIR}/zoneinfo zoneinfo) -CreateHeader(${NX_TZDB_ROMFS_DIR}/zoneinfo/Africa africa) -CreateHeader(${NX_TZDB_ROMFS_DIR}/zoneinfo/America america) -CreateHeader(${NX_TZDB_ROMFS_DIR}/zoneinfo/America/Argentina america_argentina) -CreateHeader(${NX_TZDB_ROMFS_DIR}/zoneinfo/America/Indiana america_indiana) -CreateHeader(${NX_TZDB_ROMFS_DIR}/zoneinfo/America/Kentucky america_kentucky) -CreateHeader(${NX_TZDB_ROMFS_DIR}/zoneinfo/America/North_Dakota america_north_dakota) -CreateHeader(${NX_TZDB_ROMFS_DIR}/zoneinfo/Antarctica antarctica) -CreateHeader(${NX_TZDB_ROMFS_DIR}/zoneinfo/Arctic arctic) -CreateHeader(${NX_TZDB_ROMFS_DIR}/zoneinfo/Asia asia) -CreateHeader(${NX_TZDB_ROMFS_DIR}/zoneinfo/Atlantic atlantic) -CreateHeader(${NX_TZDB_ROMFS_DIR}/zoneinfo/Australia australia) -CreateHeader(${NX_TZDB_ROMFS_DIR}/zoneinfo/Brazil brazil) -CreateHeader(${NX_TZDB_ROMFS_DIR}/zoneinfo/Canada canada) -CreateHeader(${NX_TZDB_ROMFS_DIR}/zoneinfo/Chile chile) -CreateHeader(${NX_TZDB_ROMFS_DIR}/zoneinfo/Etc etc) -CreateHeader(${NX_TZDB_ROMFS_DIR}/zoneinfo/Europe europe) -CreateHeader(${NX_TZDB_ROMFS_DIR}/zoneinfo/Indian indian) -CreateHeader(${NX_TZDB_ROMFS_DIR}/zoneinfo/Mexico mexico) -CreateHeader(${NX_TZDB_ROMFS_DIR}/zoneinfo/Pacific pacific) -CreateHeader(${NX_TZDB_ROMFS_DIR}/zoneinfo/US us) +CreateHeader(${NX_TZDB_ROMFS_DIR}/${NX_TZDB_VERSION} zoneinfo) +CreateHeader(${NX_TZDB_ROMFS_DIR}/${NX_TZDB_VERSION}/Africa africa) +CreateHeader(${NX_TZDB_ROMFS_DIR}/${NX_TZDB_VERSION}/America america) +CreateHeader(${NX_TZDB_ROMFS_DIR}/${NX_TZDB_VERSION}/America/Argentina america_argentina) +CreateHeader(${NX_TZDB_ROMFS_DIR}/${NX_TZDB_VERSION}/America/Indiana america_indiana) +CreateHeader(${NX_TZDB_ROMFS_DIR}/${NX_TZDB_VERSION}/America/Kentucky america_kentucky) +CreateHeader(${NX_TZDB_ROMFS_DIR}/${NX_TZDB_VERSION}/America/North_Dakota america_north_dakota) +CreateHeader(${NX_TZDB_ROMFS_DIR}/${NX_TZDB_VERSION}/Antarctica antarctica) +CreateHeader(${NX_TZDB_ROMFS_DIR}/${NX_TZDB_VERSION}/Arctic arctic) +CreateHeader(${NX_TZDB_ROMFS_DIR}/${NX_TZDB_VERSION}/Asia asia) +CreateHeader(${NX_TZDB_ROMFS_DIR}/${NX_TZDB_VERSION}/Atlantic atlantic) +CreateHeader(${NX_TZDB_ROMFS_DIR}/${NX_TZDB_VERSION}/Australia australia) +CreateHeader(${NX_TZDB_ROMFS_DIR}/${NX_TZDB_VERSION}/Brazil brazil) +CreateHeader(${NX_TZDB_ROMFS_DIR}/${NX_TZDB_VERSION}/Canada canada) +CreateHeader(${NX_TZDB_ROMFS_DIR}/${NX_TZDB_VERSION}/Chile chile) +CreateHeader(${NX_TZDB_ROMFS_DIR}/${NX_TZDB_VERSION}/Etc etc) +CreateHeader(${NX_TZDB_ROMFS_DIR}/${NX_TZDB_VERSION}/Europe europe) +CreateHeader(${NX_TZDB_ROMFS_DIR}/${NX_TZDB_VERSION}/Indian indian) +CreateHeader(${NX_TZDB_ROMFS_DIR}/${NX_TZDB_VERSION}/Mexico mexico) +CreateHeader(${NX_TZDB_ROMFS_DIR}/${NX_TZDB_VERSION}/Pacific pacific) +CreateHeader(${NX_TZDB_ROMFS_DIR}/${NX_TZDB_VERSION}/US us) diff --git a/externals/nx_tzdb/cpmfile.json b/externals/nx_tzdb/cpmfile.json new file mode 100644 index 0000000000..fc7dd77628 --- /dev/null +++ b/externals/nx_tzdb/cpmfile.json @@ -0,0 +1,8 @@ +{ + "tzdb": { + "package": "nx_tzdb", + "url": "https://github.com/crueter/tzdb_to_nx/releases/download/250725/250725.zip", + "hash": "8f60b4b29f285e39c0443f3d5572a73780f3dbfcfd5b35004451fadad77f3a215b2e2aa8d0fffe7e348e2a7b0660882b35228b6178dda8804a14ce44509fd2ca", + "version": "250725" + } +} diff --git a/src/android/app/build.gradle.kts b/src/android/app/build.gradle.kts index 0cbb29b01b..d907284bb7 100644 --- a/src/android/app/build.gradle.kts +++ b/src/android/app/build.gradle.kts @@ -175,7 +175,10 @@ android { "-DYUZU_USE_CPM=ON", "-DYUZU_USE_BUNDLED_FFMPEG=ON", "-DYUZU_ENABLE_LTO=ON", - "-DCMAKE_EXPORT_COMPILE_COMMANDS=ON" + "-DCMAKE_EXPORT_COMPILE_COMMANDS=ON", + "-DBUILD_TESTING=OFF", + "-DYUZU_TESTS=OFF", + "-DDYNARMIC_TESTS=OFF" ) abiFilters("arm64-v8a") diff --git a/src/common/CMakeLists.txt b/src/common/CMakeLists.txt index cbe1d35fc5..6173e29f45 100644 --- a/src/common/CMakeLists.txt +++ b/src/common/CMakeLists.txt @@ -272,13 +272,7 @@ if (lz4_ADDED) endif() target_link_libraries(common PUBLIC fmt::fmt stb::headers Threads::Threads) -target_link_libraries(common PRIVATE lz4::lz4 LLVM::Demangle) - -if (TARGET libzstd_static) - target_link_libraries(common PRIVATE libzstd_static) -else() - target_link_libraries(common PRIVATE zstd) -endif() +target_link_libraries(common PRIVATE lz4::lz4 LLVM::Demangle zstd::zstd) if (TARGET unordered_dense::unordered_dense) # weird quirk of system installs diff --git a/src/dynarmic/externals/CMakeLists.txt b/src/dynarmic/externals/CMakeLists.txt index 072558a618..23cfd42236 100644 --- a/src/dynarmic/externals/CMakeLists.txt +++ b/src/dynarmic/externals/CMakeLists.txt @@ -1,11 +1,11 @@ +# Explicitly include CPMUtil here since we have a separate cpmfile for dynarmic +set(CPMUTIL_JSON_FILE ${CMAKE_CURRENT_SOURCE_DIR}/cpmfile.json) include(CPMUtil) # Always build externals as static libraries, even when dynarmic is built as shared -if (BUILD_SHARED_LIBS) - set(BUILD_SHARED_LIBS OFF) - set(CMAKE_POSITION_INDEPENDENT_CODE ON) - set_property(DIRECTORY PROPERTY EXCLUDE_FROM_ALL ON) -endif() +set(BUILD_SHARED_LIBS OFF) +set(CMAKE_POSITION_INDEPENDENT_CODE ON) +set_property(DIRECTORY PROPERTY EXCLUDE_FROM_ALL ON) # Allow options shadowing with normal variables when subproject use old cmake policy set(CMAKE_POLICY_DEFAULT_CMP0077 NEW) @@ -22,42 +22,32 @@ set(BUILD_TESTING OFF) if ("riscv" IN_LIST ARCHITECTURE) add_subdirectory(biscuit) - AddPackage( + AddJsonPackage( NAME biscuit - VERSION 0.9.1 - REPO "lioncash/biscuit" - SHA 76b0be8dae - HASH 47d55ed02d032d6cf3dc107c6c0a9aea686d5f25aefb81d1af91db027b6815bd5add1755505e19d76625feeb17aa2db6cd1668fe0dad2e6a411519bde6ca4489 BUNDLED_PACKAGE ${DYNARMIC_USE_BUNDLED_EXTERNALS} ) endif() # catch -# TODO(crueter): dedup -if (NOT TARGET Catch2::Catch2WithMain) - if (DYNARMIC_TESTS) - find_package(Catch2 3.0.1 REQUIRED) - endif() -endif() +# if (NOT TARGET Catch2::Catch2WithMain) +# if (DYNARMIC_TESTS) +# find_package(Catch2 3.0.1 REQUIRED) +# endif() +# endif() # fmt -if (NOT TARGET fmt::fmt) - # fmtlib formatting library - set(FMT_INSTALL ON) - add_subdirectory(fmt) -endif() +# if (NOT TARGET fmt::fmt) +# # fmtlib formatting library +# set(FMT_INSTALL ON) +# add_subdirectory(fmt) +# endif() # mcl -AddPackage( +AddJsonPackage( NAME mcl - VERSION 0.1.12 - REPO "azahar-emu/mcl" - SHA 7b08d83418 - HASH f943bac39c1879986decad7a442ff4288eaeca4a2907684c7914e115a55ecc43c2782ded85c0835763fe04e40d5c82220ce864423e489e648e408a84f54dc4f3 - OPTIONS - "MCL_INSTALL OFF" + BUNDLED_PACKAGE ${DYNARMIC_USE_BUNDLED_EXTERNALS} ) # oaknut @@ -72,14 +62,9 @@ AddPackage( # unordered_dense -AddPackage( - NAME unordered_dense - REPO "Lizzie841/unordered_dense" - SHA e59d30b7b1 - HASH 71eff7bd9ba4b9226967bacd56a8ff000946f8813167cb5664bb01e96fb79e4e220684d824fe9c59c4d1cc98c606f13aff05b7940a1ed8ab3c95d6974ee34fa0 - FIND_PACKAGE_ARGUMENTS "CONFIG" - OPTIONS - "UNORDERED_DENSE_INSTALL OFF" +AddJsonPackage( + NAME unordered-dense + BUNDLED_PACKAGE ${DYNARMIC_USE_BUNDLED_EXTERNALS} ) # xbyak @@ -95,31 +80,12 @@ AddPackage( # TODO(crueter): maybe it's just Gentoo but zydis system package really sucks if ("x86_64" IN_LIST ARCHITECTURE) + set(CMAKE_DISABLE_FIND_PACKAGE_Doxygen ON) # TODO(crueter): system zycore doesn't work with zydis - AddPackage( - NAME Zycore - REPO "zyantific/zycore-c" - SHA 75a36c45ae - HASH 15aa399f39713e042c4345bc3175c82f14dca849fde2a21d4f591f62c43e227b70d868d8bb86beb5f4eb68b1d6bd3792cdd638acf89009e787e3d10ee7401924 - OPTIONS - "CMAKE_DISABLE_FIND_PACKAGE_Doxygen ON" - EXCLUDE_FROM_ALL ON - SYSTEM_PACKAGE OFF - ) + AddJsonPackage(zycore) - AddPackage( - NAME Zydis - VERSION 4 - REPO "zyantific/zydis" - SHA c2d2bab025 - HASH 7b48f213ff7aab2926f8c9c65195959143bebbfb2b9a25051ffd8b8b0f1baf1670d9739781de674577d955925f91ac89376e16b476a03828c84e2fd765d45020 - FIND_PACKAGE_ARGUMENTS "CONFIG" - OPTIONS - "ZYDIS_BUILD_TOOLS OFF" - "ZYDIS_BUILD_EXAMPLES OFF" - "ZYDIS_BUILD_DOXYGEN OFF" - "ZYAN_SYSTEM_ZYCORE ON" - "CMAKE_DISABLE_FIND_PACKAGE_Doxygen ON" - EXCLUDE_FROM_ALL ON + AddJsonPackage( + NAME zydis + BUNDLED_PACKAGE ${DYNARMIC_USE_BUNDLED_EXTERNALS} ) endif() diff --git a/src/dynarmic/externals/cpmfile.json b/src/dynarmic/externals/cpmfile.json new file mode 100644 index 0000000000..b934856af2 --- /dev/null +++ b/src/dynarmic/externals/cpmfile.json @@ -0,0 +1,47 @@ +{ + "biscuit": { + "version": "0.9.1", + "repo": "lioncash/biscuit", + "sha": "76b0be8dae", + "hash": "47d55ed02d032d6cf3dc107c6c0a9aea686d5f25aefb81d1af91db027b6815bd5add1755505e19d76625feeb17aa2db6cd1668fe0dad2e6a411519bde6ca4489" + }, + "mcl": { + "version": "0.1.12", + "repo": "azahar-emu/mcl", + "sha": "7b08d83418", + "hash": "f943bac39c1879986decad7a442ff4288eaeca4a2907684c7914e115a55ecc43c2782ded85c0835763fe04e40d5c82220ce864423e489e648e408a84f54dc4f3", + "options": [ + "MCL_INSTALL OFF" + ] + }, + "unordered-dense": { + "package": "unordered_dense", + "repo": "Lizzie841/unordered_dense", + "sha": "e59d30b7b1", + "hash": "71eff7bd9ba4b9226967bacd56a8ff000946f8813167cb5664bb01e96fb79e4e220684d824fe9c59c4d1cc98c606f13aff05b7940a1ed8ab3c95d6974ee34fa0", + "find_args": "CONFIG", + "options": [ + "UNORDERED_DENSE_INSTALL OFF" + ] + }, + "zycore": { + "package": "Zycore", + "repo": "zyantific/zycore-c", + "sha": "75a36c45ae", + "hash": "15aa399f39713e042c4345bc3175c82f14dca849fde2a21d4f591f62c43e227b70d868d8bb86beb5f4eb68b1d6bd3792cdd638acf89009e787e3d10ee7401924", + "bundled": true + }, + "zydis": { + "package": "Zydis", + "version": "4", + "repo": "zyantific/zydis", + "sha": "c2d2bab025", + "hash": "7b48f213ff7aab2926f8c9c65195959143bebbfb2b9a25051ffd8b8b0f1baf1670d9739781de674577d955925f91ac89376e16b476a03828c84e2fd765d45020", + "options": [ + "ZYDIS_BUILD_TOOLS OFF", + "ZYDIS_BUILD_EXAMPLES OFF", + "ZYDIS_BUILD_DOXYGEN OFF", + "ZYAN_SYSTEM_ZYCORE ON" + ] + } +} diff --git a/src/shader_recompiler/CMakeLists.txt b/src/shader_recompiler/CMakeLists.txt index 5d896db93d..55cdc17c1f 100644 --- a/src/shader_recompiler/CMakeLists.txt +++ b/src/shader_recompiler/CMakeLists.txt @@ -246,7 +246,7 @@ add_library(shader_recompiler STATIC ) -target_link_libraries(shader_recompiler PUBLIC common fmt::fmt sirit SPIRV-Tools-opt SPIRV-Tools SPIRV-Tools-link) +target_link_libraries(shader_recompiler PUBLIC common fmt::fmt sirit SPIRV-Tools::SPIRV-Tools) if (MSVC) target_compile_options(shader_recompiler PRIVATE diff --git a/src/yuzu/externals/CMakeLists.txt b/src/yuzu/externals/CMakeLists.txt index d7f3f1457a..7de41f6dfd 100644 --- a/src/yuzu/externals/CMakeLists.txt +++ b/src/yuzu/externals/CMakeLists.txt @@ -1,7 +1,8 @@ # SPDX-FileCopyrightText: Copyright 2025 Eden Emulator Project # SPDX-License-Identifier: GPL-3.0-or-later -# cpm +# Explicitly include CPMUtil here since we have a separate cpmfile for Qt externals +set(CPMUTIL_JSON_FILE ${CMAKE_CURRENT_SOURCE_DIR}/cpmfile.json) include(CPMUtil) # Disable tests/tools in all externals supporting the standard option name @@ -14,12 +15,4 @@ set(BUILD_SHARED_LIBS OFF) set_directory_properties(PROPERTIES EXCLUDE_FROM_ALL ON) # QuaZip -AddPackage( - NAME QuaZip-Qt6 - VERSION 1.3 - REPO "crueter/quazip-qt6" - SHA f838774d63 - HASH 9f629a438699801244a106c8df6d5f8f8d19e80df54f530a89403a10c8c4e37a6e95606bbdd307f23636961e8ce34eb37a2186d589a1f227ac9c8e2c678e326e - OPTIONS - "QUAZIP_INSTALL OFF" -) +AddJsonPackage(quazip) diff --git a/src/yuzu/externals/cpmfile.json b/src/yuzu/externals/cpmfile.json new file mode 100644 index 0000000000..e3590d0f7f --- /dev/null +++ b/src/yuzu/externals/cpmfile.json @@ -0,0 +1,12 @@ +{ + "quazip": { + "package": "QuaZip-Qt6", + "repo": "crueter/quazip-qt6", + "sha": "f838774d63", + "hash": "9f629a438699801244a106c8df6d5f8f8d19e80df54f530a89403a10c8c4e37a6e95606bbdd307f23636961e8ce34eb37a2186d589a1f227ac9c8e2c678e326e", + "version": "1.3", + "options": [ + "QUAZIP_INSTALL OFF" + ] + } +} diff --git a/tools/cpm-fetch-all.sh b/tools/cpm-fetch-all.sh new file mode 100755 index 0000000000..38f7b1f941 --- /dev/null +++ b/tools/cpm-fetch-all.sh @@ -0,0 +1,10 @@ +#!/bin/bash -e + +# SPDX-FileCopyrightText: 2025 Eden Emulator Project +# SPDX-License-Identifier: GPL-3.0-or-later + +# SPDX-FileCopyrightText: 2025 crueter +# SPDX-License-Identifier: GPL-3.0-or-later + +LIBS=$(find . externals externals/nx_tzdb src/yuzu/externals externals/ffmpeg src/dynarmic/externals -maxdepth 1 -name cpmfile.json -exec jq -j 'keys_unsorted | join(" ")' {} \; -printf " ") +tools/cpm-fetch.sh $LIBS \ No newline at end of file diff --git a/tools/cpm-fetch.sh b/tools/cpm-fetch.sh new file mode 100755 index 0000000000..1c2ce007d2 --- /dev/null +++ b/tools/cpm-fetch.sh @@ -0,0 +1,198 @@ +#!/bin/bash -e + +# SPDX-FileCopyrightText: 2025 Eden Emulator Project +# SPDX-License-Identifier: GPL-3.0-or-later + +# SPDX-FileCopyrightText: 2025 crueter +# SPDX-License-Identifier: GPL-3.0-or-later + +[ -z "$CPM_SOURCE_CACHE" ] && CPM_SOURCE_CACHE=$PWD/.cache/cpm + +mkdir -p $CPM_SOURCE_CACHE + +ROOTDIR="$PWD" + +TMP=$(mktemp -d) + +download_package() { + FILENAME=$(basename "$DOWNLOAD") + + OUTFILE="$TMP/$FILENAME" + + LOWER_PACKAGE=$(tr '[:upper:]' '[:lower:]' <<< "$PACKAGE_NAME") + OUTDIR="${CPM_SOURCE_CACHE}/${LOWER_PACKAGE}/${KEY}" + [ -d "$OUTDIR" ] && return + + curl "$DOWNLOAD" -sS -L -o "$OUTFILE" + + ACTUAL_HASH=$(${HASH_ALGO}sum "$OUTFILE" | cut -d" " -f1) + [ "$ACTUAL_HASH" != "$HASH" ] && echo "$FILENAME did not match expected hash; expected $HASH but got $ACTUAL_HASH" && exit 1 + + mkdir -p "$OUTDIR" + + pushd "$OUTDIR" > /dev/null + + case "$FILENAME" in + (*.7z) + 7z x "$OUTFILE" > /dev/null + ;; + (*.tar*) + tar xf "$OUTFILE" > /dev/null + ;; + (*.zip) + unzip "$OUTFILE" > /dev/null + ;; + esac + + # basically if only one real item exists at the top we just move everything from there + # since github and some vendors hate me + DIRS=$(find -maxdepth 1 -type d -o -type f) + + # thanks gnu + if [ $(wc -l <<< "$DIRS") -eq 2 ]; then + SUBDIR=$(find . -maxdepth 1 -type d -not -name ".") + mv "$SUBDIR"/* . + mv "$SUBDIR"/.* . 2>/dev/null || true + rmdir "$SUBDIR" + fi + + if grep -e "patches" <<< "$JSON" > /dev/null; then + PATCHES=$(jq -r '.patches | join(" ")' <<< "$JSON") + for patch in $PATCHES; do + patch -p1 < "$ROOTDIR"/.patch/$package/$patch + done + fi + + popd > /dev/null +} + +ci_package() { + REPO=$(jq -r ".repo" <<< "$JSON") + EXT=$(jq -r '.extension' <<< "$JSON") + [ "$EXT" == null ] && EXT="tar.zst" + + VERSION=$(jq -r ".version" <<< "$JSON") + NAME=$(jq -r ".name | \"$package\"" <<< "$JSON") + PACKAGE=$(jq -r ".package | \"$package\"" <<< "$JSON") + + # TODO(crueter) + # DISABLED=$(jq -j '.disabled_platforms | join(" ")' <<< "$JSON") + + [ "$REPO" == null ] && echo "No repo defined for CI package $package" && return + + echo "CI package $PACKAGE" + + for platform in windows-amd64 windows-arm64 android solaris freebsd linux linux-aarch64; do + FILENAME="${NAME}-${platform}-${VERSION}.${EXT}" + DOWNLOAD="https://github.com/${REPO}/releases/download/v${VERSION}/${FILENAME}" + PACKAGE_NAME="$PACKAGE" + KEY=$platform + + echo "- platform $KEY" + + HASH_ALGO=$(jq -r ".hash_algo" <<< "$JSON") + [ "$HASH_ALGO" == null ] && HASH_ALGO=sha512 + + HASH_SUFFIX="${HASH_ALGO}sum" + HASH_URL="${DOWNLOAD}.${HASH_SUFFIX}" + + HASH=$(curl "$HASH_URL" -sS -q -L -o -) + + download_package + done +} + +for package in $@ +do + # prepare for cancer + JSON=$(find . externals src/yuzu/externals externals/ffmpeg src/dynarmic/externals externals/nx_tzdb -maxdepth 1 -name cpmfile.json -exec jq -r ".\"$package\" | select( . != null )" {} \;) + + [ -z "$JSON" ] && echo "No cpmfile definition for $package" && continue + + PACKAGE_NAME=$(jq -r ".package" <<< "$JSON") + [ "$PACKAGE_NAME" == null ] && PACKAGE_NAME="$package" + + CI=$(jq -r ".ci" <<< "$JSON") + if [ "$CI" != null ]; then + ci_package + continue + fi + + # url parsing WOOOHOOHOHOOHOHOH + URL=$(jq -r ".url" <<< "$JSON") + REPO=$(jq -r ".repo" <<< "$JSON") + SHA=$(jq -r ".sha" <<< "$JSON") + + if [ "$URL" != "null" ]; then + DOWNLOAD="$URL" + elif [ "$REPO" != "null" ]; then + GIT_URL="https://github.com/$REPO" + + TAG=$(jq -r ".tag" <<< "$JSON") + ARTIFACT=$(jq -r ".artifact" <<< "$JSON") + BRANCH=$(jq -r ".branch" <<< "$JSON") + + if [ "$TAG" != "null" ]; then + if [ "$ARTIFACT" != "null" ]; then + DOWNLOAD="${GIT_URL}/releases/download/${TAG}/${ARTIFACT}" + else + DOWNLOAD="${GIT_URL}/archive/refs/tags/${TAG}.tar.gz" + fi + elif [ "$SHA" != "null" ]; then + DOWNLOAD="${GIT_URL}/archive/${SHA}.zip" + else + if [ "$BRANCH" == null ]; then + BRANCH=master + fi + + DOWNLOAD="${GIT_URL}/archive/refs/heads/${BRANCH}.zip" + fi + else + echo "No repo or URL defined for $package" + continue + fi + + # key parsing + KEY=$(jq -r ".key" <<< "$JSON") + + if [ "$KEY" == null ]; then + VERSION=$(jq -r ".version" <<< "$JSON") + GIT_VERSION=$(jq -r ".git_version" <<< "$JSON") + + if [ "$SHA" != null ]; then + KEY=$(cut -c1-4 - <<< "$SHA") + elif [ "$GIT_VERSION" != null ]; then + KEY="$GIT_VERSION" + elif [ "$VERSION" != null ]; then + KEY="$VERSION" + else + echo "No valid key could be determined for $package. Must define one of: key, sha, version, git_version" + continue + fi + fi + + echo $KEY + + echo "Downloading regular package $package, with key $KEY, from $DOWNLOAD" + + # hash parsing + HASH_ALGO=$(jq -r ".hash_algo" <<< "$JSON") + [ "$HASH_ALGO" == null ] && HASH_ALGO=sha512 + + HASH=$(jq -r ".hash" <<< "$JSON") + + if [ "$HASH" == null ]; then + HASH_SUFFIX="${HASH_ALGO}sum" + HASH_URL=$(jq -r ".hash_url" <<< "$JSON") + + if [ "$HASH_URL" == null ]; then + HASH_URL="${DOWNLOAD}.${HASH_SUFFIX}" + fi + + HASH=$(curl "$HASH_URL" -L -o -) + fi + + download_package +done + +rm -rf $TMP \ No newline at end of file From cf689a7a4927e9aba25a9b78e4467a8c8b8e149e Mon Sep 17 00:00:00 2001 From: crueter Date: Fri, 29 Aug 2025 01:35:01 +0200 Subject: [PATCH 36/39] [cmake] properly invalidate tzdb cache; require matching version (#346) Signed-off-by: crueter Reviewed-on: https://git.eden-emu.dev/eden-emu/eden/pulls/346 Reviewed-by: CamilleLaVey --- externals/nx_tzdb/CMakeLists.txt | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/externals/nx_tzdb/CMakeLists.txt b/externals/nx_tzdb/CMakeLists.txt index 5812a62f98..2d6b2fcc66 100644 --- a/externals/nx_tzdb/CMakeLists.txt +++ b/externals/nx_tzdb/CMakeLists.txt @@ -32,10 +32,9 @@ if (CMAKE_SYSTEM_NAME STREQUAL "Windows" OR ANDROID) endif() set(NX_TZDB_VERSION "250725") +set(NX_TZDB_ROMFS_DIR "${CPM_SOURCE_CACHE}/nx_tzdb") -set(NX_TZDB_ROMFS_DIR "${CPM_SOURCE_CACHE}/nx_tzdb/") - -if ((NOT CAN_BUILD_NX_TZDB OR YUZU_DOWNLOAD_TIME_ZONE_DATA) AND NOT EXISTS ${NX_TZDB_ROMFS_DIR}) +if ((NOT CAN_BUILD_NX_TZDB OR YUZU_DOWNLOAD_TIME_ZONE_DATA) AND NOT EXISTS ${NX_TZDB_ROMFS_DIR}/${NX_TZDB_VERSION}) message(STATUS "Downloading time zone data...") AddJsonPackage(tzdb) elseif (CAN_BUILD_NX_TZDB AND NOT YUZU_DOWNLOAD_TIME_ZONE_DATA) From f07309afd2a360d555938d458c4430e02b9e9987 Mon Sep 17 00:00:00 2001 From: Caio Oliveira Date: Fri, 29 Aug 2025 01:49:20 +0200 Subject: [PATCH 37/39] [ffmpeg] proper drm inclusion (#328) * this fixes build on ubuntu 25.04 Signed-off-by: Caio Oliveira Reviewed-on: https://git.eden-emu.dev/eden-emu/eden/pulls/328 Reviewed-by: CamilleLaVey Co-authored-by: Caio Oliveira Co-committed-by: Caio Oliveira --- docs/build/Linux.md | 2 +- externals/ffmpeg/CMakeLists.txt | 35 ++++++++++++++++++++++----------- src/yuzu/CMakeLists.txt | 5 ----- src/yuzu_cmd/CMakeLists.txt | 5 ----- 4 files changed, 25 insertions(+), 22 deletions(-) diff --git a/docs/build/Linux.md b/docs/build/Linux.md index ab653dad00..be58b451fa 100644 --- a/docs/build/Linux.md +++ b/docs/build/Linux.md @@ -37,7 +37,7 @@ Dependencies are listed here as commands that can be copied/pasted. Of course, t - GCC 11 or later is required. - Ubuntu / Linux Mint / Debian: - - `sudo apt-get install autoconf cmake g++ gcc git glslang-tools libasound2 libboost-context-dev libglu1-mesa-dev libhidapi-dev libpulse-dev libtool libudev-dev libxcb-icccm4 libxcb-image0 libxcb-keysyms1 libxcb-render-util0 libxcb-xinerama0 libxcb-xkb1 libxext-dev libxkbcommon-x11-0 mesa-common-dev nasm ninja-build qt6-base-private-dev libmbedtls-dev catch2 libfmt-dev liblz4-dev nlohmann-json3-dev libzstd-dev libssl-dev libavfilter-dev libavcodec-dev libswscale-dev pkg-config zlib1g-dev` + - `sudo apt-get install autoconf cmake g++ gcc git glslang-tools libasound2 libboost-context-dev libglu1-mesa-dev libhidapi-dev libpulse-dev libtool libudev-dev libxcb-icccm4 libxcb-image0 libxcb-keysyms1 libxcb-render-util0 libxcb-xinerama0 libxcb-xkb1 libxext-dev libxkbcommon-x11-0 mesa-common-dev nasm ninja-build qt6-base-private-dev libmbedtls-dev catch2 libfmt-dev liblz4-dev nlohmann-json3-dev libzstd-dev libssl-dev libavfilter-dev libavcodec-dev libswscale-dev pkg-config zlib1g-dev libva-dev libvdpau-dev` - Ubuntu 22.04, Linux Mint 20, or Debian 12 or later is required. - Users need to manually specify building with QT Web Engine enabled. This is done using the parameter `-DYUZU_USE_QT_WEB_ENGINE=ON` when running CMake. - Users need to manually disable building SDL2 from externals if they intend to use the version provided by their system by adding the parameters `-DYUZU_USE_EXTERNAL_SDL2=OFF` diff --git a/externals/ffmpeg/CMakeLists.txt b/externals/ffmpeg/CMakeLists.txt index b514ede3be..54c852f831 100644 --- a/externals/ffmpeg/CMakeLists.txt +++ b/externals/ffmpeg/CMakeLists.txt @@ -63,32 +63,44 @@ if (NOT WIN32 AND NOT ANDROID) set(FFmpeg_HWACCEL_INCLUDE_DIRS) set(FFmpeg_HWACCEL_LDFLAGS) - if(LIBVA_FOUND) + # In Solaris needs explicit linking for ffmpeg which links to /lib/amd64/libX11.so + if(PLATFORM_SUN) + list(APPEND FFmpeg_HWACCEL_LIBRARIES + X11 + "/usr/lib/xorg/amd64/libdrm.so") + else() pkg_check_modules(LIBDRM libdrm REQUIRED) + list(APPEND FFmpeg_HWACCEL_LIBRARIES + ${LIBDRM_LIBRARIES}) + list(APPEND FFmpeg_HWACCEL_INCLUDE_DIRS + ${LIBDRM_INCLUDE_DIRS}) + endif() + list(APPEND FFmpeg_HWACCEL_FLAGS + --enable-libdrm) + + if(LIBVA_FOUND) find_package(X11 REQUIRED) pkg_check_modules(LIBVA-DRM libva-drm REQUIRED) pkg_check_modules(LIBVA-X11 libva-x11 REQUIRED) list(APPEND FFmpeg_HWACCEL_LIBRARIES - ${LIBDRM_LIBRARIES} ${X11_LIBRARIES} ${LIBVA-DRM_LIBRARIES} ${LIBVA-X11_LIBRARIES} ${LIBVA_LIBRARIES}) - set(FFmpeg_HWACCEL_FLAGS + list(APPEND FFmpeg_HWACCEL_FLAGS --enable-hwaccel=h264_vaapi --enable-hwaccel=vp8_vaapi - --enable-hwaccel=vp9_vaapi - --enable-libdrm) + --enable-hwaccel=vp9_vaapi) list(APPEND FFmpeg_HWACCEL_INCLUDE_DIRS - ${LIBDRM_INCLUDE_DIRS} ${X11_INCLUDE_DIRS} ${LIBVA-DRM_INCLUDE_DIRS} ${LIBVA-X11_INCLUDE_DIRS} ${LIBVA_INCLUDE_DIRS} ) - message(STATUS "VA-API found") + message(STATUS "ffmpeg: va-api libraries version ${LIBVA_VERSION} found") else() - set(FFmpeg_HWACCEL_FLAGS --disable-vaapi) + list(APPEND FFmpeg_HWACCEL_FLAGS --disable-vaapi) + message(WARNING "ffmpeg: libva-dev not found, disabling Video Aceleraion API (VA-API)...") endif() if (FFNVCODEC_FOUND) @@ -103,7 +115,7 @@ if (NOT WIN32 AND NOT ANDROID) list(APPEND FFmpeg_HWACCEL_LIBRARIES ${FFNVCODEC_LIBRARIES}) list(APPEND FFmpeg_HWACCEL_INCLUDE_DIRS ${FFNVCODEC_INCLUDE_DIRS}) list(APPEND FFmpeg_HWACCEL_LDFLAGS ${FFNVCODEC_LDFLAGS}) - message(STATUS "ffnvcodec libraries version ${FFNVCODEC_VERSION} found") + message(STATUS "ffmpeg: ffnvcodec libraries version ${FFNVCODEC_VERSION} found") # ffnvenc could load CUDA libraries at the runtime using dlopen/dlsym or LoadLibrary/GetProcAddress # here we handle the hard-linking senario where CUDA is linked during compilation if (CUDA_FOUND) @@ -112,7 +124,7 @@ if (NOT WIN32 AND NOT ANDROID) list(APPEND FFmpeg_HWACCEL_LIBRARIES ${CUDA_LIBRARIES}) list(APPEND FFmpeg_HWACCEL_INCLUDE_DIRS ${CUDA_INCLUDE_DIRS}) list(APPEND FFmpeg_HWACCEL_LDFLAGS ${CUDA_LDFLAGS}) - message(STATUS "CUDA libraries found, hard-linking will be performed") + message(STATUS "ffmpeg: CUDA libraries found, hard-linking will be performed") endif(CUDA_FOUND) endif() @@ -125,9 +137,10 @@ if (NOT WIN32 AND NOT ANDROID) list(APPEND FFmpeg_HWACCEL_LIBRARIES ${VDPAU_LIBRARIES}) list(APPEND FFmpeg_HWACCEL_INCLUDE_DIRS ${VDPAU_INCLUDE_DIRS}) list(APPEND FFmpeg_HWACCEL_LDFLAGS ${VDPAU_LDFLAGS}) - message(STATUS "vdpau libraries version ${VDPAU_VERSION} found") + message(STATUS "ffmpeg: vdpau libraries version ${VDPAU_VERSION} found") else() list(APPEND FFmpeg_HWACCEL_FLAGS --disable-vdpau) + message(WARNING "ffmpeg: libvdpau-dev not found, disabling Video Decode and Presentation API for Unix (VDPAU)...") endif() find_program(BASH_PROGRAM bash REQUIRED) diff --git a/src/yuzu/CMakeLists.txt b/src/yuzu/CMakeLists.txt index f979a5c181..0ce8f3b898 100644 --- a/src/yuzu/CMakeLists.txt +++ b/src/yuzu/CMakeLists.txt @@ -501,11 +501,6 @@ if (YUZU_ROOM) target_link_libraries(yuzu PRIVATE yuzu-room) endif() -# Explicit linking required -if (PLATFORM_SUN) - target_link_libraries(yuzu PRIVATE X11 "/usr/lib/xorg/amd64/libdrm.so") -endif() - # Extra deps add_subdirectory(externals) target_link_libraries(yuzu PRIVATE QuaZip::QuaZip) diff --git a/src/yuzu_cmd/CMakeLists.txt b/src/yuzu_cmd/CMakeLists.txt index afd003a86c..ebd8fd7387 100644 --- a/src/yuzu_cmd/CMakeLists.txt +++ b/src/yuzu_cmd/CMakeLists.txt @@ -40,11 +40,6 @@ target_include_directories(yuzu-cmd PRIVATE ${RESOURCES_DIR}) target_link_libraries(yuzu-cmd PRIVATE SDL2::SDL2 Vulkan::Headers) -# In Solaris needs explicit linking for ffmpeg which links to /lib/amd64/libX11.so -if (PLATFORM_SUN) - target_link_libraries(yuzu-cmd PRIVATE X11 "/usr/lib/xorg/amd64/libdrm.so") -endif() - if(UNIX AND NOT APPLE) install(TARGETS yuzu-cmd) endif() From 57fbdd516ee03ef7a52b9a1ba54bf866f24da53a Mon Sep 17 00:00:00 2001 From: MaranBr Date: Fri, 29 Aug 2025 14:20:22 +0200 Subject: [PATCH 38/39] [host_memory] Fix a bunch of memory errors on Windows (#303) This fixes a bunch of memory errors that could happen on Windows. Possibly regression introduced on PR 187. Reviewed-on: https://git.eden-emu.dev/eden-emu/eden/pulls/303 Reviewed-by: CamilleLaVey Co-authored-by: MaranBr Co-committed-by: MaranBr --- src/common/host_memory.cpp | 10 +++++++--- 1 file changed, 7 insertions(+), 3 deletions(-) diff --git a/src/common/host_memory.cpp b/src/common/host_memory.cpp index f847ea2a62..edb64de8ec 100644 --- a/src/common/host_memory.cpp +++ b/src/common/host_memory.cpp @@ -417,11 +417,15 @@ static void* ChooseVirtualBase(size_t virtual_size) { #else static void* ChooseVirtualBase(size_t virtual_size) { +#if defined(__OpenBSD__) || defined(__sun__) || defined(__HAIKU__) || defined(__managarm__) void* virtual_base = mmap(nullptr, virtual_size, PROT_READ | PROT_WRITE, MAP_PRIVATE | MAP_ANONYMOUS | MAP_NORESERVE | MAP_ALIGNED_SUPER, -1, 0); - if (virtual_base != MAP_FAILED) + + if (virtual_base != MAP_FAILED) { return virtual_base; - return mmap(nullptr, virtual_size, PROT_READ | PROT_WRITE, - MAP_PRIVATE | MAP_ANONYMOUS | MAP_NORESERVE, -1, 0); + } +#endif + + return mmap(nullptr, virtual_size, PROT_READ | PROT_WRITE, MAP_PRIVATE | MAP_ANONYMOUS | MAP_NORESERVE, -1, 0); } #endif From c14b6bcc346caace65aaac180c9f37047e80dfd1 Mon Sep 17 00:00:00 2001 From: lizzie Date: Thu, 21 Aug 2025 10:16:43 +0000 Subject: [PATCH 39/39] [common] replace Common:: stuffs with libstdc++ equivalents Signed-off-by: lizzie --- src/common/common_funcs.h | 15 --------------- src/common/concepts.h | 20 -------------------- src/common/fixed_point.h | 12 ++++++++---- src/core/file_sys/fs_path_utility.h | 6 +++--- src/core/hle/kernel/k_priority_queue.h | 9 ++++----- src/core/hle/service/sm/sm.h | 4 ++-- src/video_core/gpu_thread.cpp | 4 +--- 7 files changed, 18 insertions(+), 52 deletions(-) diff --git a/src/common/common_funcs.h b/src/common/common_funcs.h index ba3081efb4..9272dbd6a6 100644 --- a/src/common/common_funcs.h +++ b/src/common/common_funcs.h @@ -129,19 +129,4 @@ namespace Common { u64(g) << 48 | u64(h) << 56; } -// std::size() does not support zero-size C arrays. We're fixing that. -template -constexpr auto Size(const C& c) -> decltype(c.size()) { - return std::size(c); -} - -template -constexpr std::size_t Size(const C& c) { - if constexpr (sizeof(C) == 0) { - return 0; - } else { - return std::size(c); - } -} - } // namespace Common diff --git a/src/common/concepts.h b/src/common/concepts.h index 61df1d32a2..d991bdd893 100644 --- a/src/common/concepts.h +++ b/src/common/concepts.h @@ -12,24 +12,4 @@ namespace Common { template concept IsContiguousContainer = std::contiguous_iterator; -// TODO: Replace with std::derived_from when the header -// is available on all supported platforms. -template -concept DerivedFrom = requires { - std::is_base_of_v; - std::is_convertible_v; - }; - -// TODO: Replace with std::convertible_to when libc++ implements it. -template -concept ConvertibleTo = std::is_convertible_v; - -// No equivalents in the stdlib - -template -concept IsArithmetic = std::is_arithmetic_v; - -template -concept IsIntegral = std::is_integral_v; - } // namespace Common diff --git a/src/common/fixed_point.h b/src/common/fixed_point.h index b0f3ae2ccb..3beec38b0d 100644 --- a/src/common/fixed_point.h +++ b/src/common/fixed_point.h @@ -16,6 +16,10 @@ namespace Common { +// No equivalent for "std::arithmetic" in the stdlib +template +concept IsArithmetic = std::is_arithmetic_v; + template class FixedPoint; @@ -392,13 +396,13 @@ public: // binary math operators, effects underlying bit pattern since these return *this; } - template + template constexpr FixedPoint& operator>>=(Integer n) { data_ >>= n; return *this; } - template + template constexpr FixedPoint& operator<<=(Integer n) { data_ <<= n; return *this; @@ -587,12 +591,12 @@ constexpr FixedPoint operator/(Number lhs, FixedPoint rhs) { } // shift operators -template +template constexpr FixedPoint operator<<(FixedPoint lhs, Integer rhs) { lhs <<= rhs; return lhs; } -template +template constexpr FixedPoint operator>>(FixedPoint lhs, Integer rhs) { lhs >>= rhs; return lhs; diff --git a/src/core/file_sys/fs_path_utility.h b/src/core/file_sys/fs_path_utility.h index cdfd8c7729..b8702f4f3f 100644 --- a/src/core/file_sys/fs_path_utility.h +++ b/src/core/file_sys/fs_path_utility.h @@ -57,15 +57,15 @@ constexpr bool IsInvalidCharacterImpl(char c) { } // namespace impl constexpr bool IsInvalidCharacter(char c) { - return impl::IsInvalidCharacterImpl(c); + return impl::IsInvalidCharacterImpl(c); } constexpr bool IsInvalidCharacterForHostName(char c) { return impl::IsInvalidCharacterImpl(c); + std::size(InvalidCharactersForHostName)>(c); } constexpr bool IsInvalidCharacterForMountName(char c) { return impl::IsInvalidCharacterImpl(c); + std::size(InvalidCharactersForMountName)>(c); } } // namespace StringTraits diff --git a/src/core/hle/kernel/k_priority_queue.h b/src/core/hle/kernel/k_priority_queue.h index 26677ec65c..14a406bdc8 100644 --- a/src/core/hle/kernel/k_priority_queue.h +++ b/src/core/hle/kernel/k_priority_queue.h @@ -10,7 +10,6 @@ #include "common/assert.h" #include "common/bit_set.h" #include "common/common_types.h" -#include "common/concepts.h" namespace Kernel { @@ -19,7 +18,7 @@ class KThread; template concept KPriorityQueueAffinityMask = ! std::is_reference_v&& requires(T& t) { - { t.GetAffinityMask() } -> Common::ConvertibleTo; + { t.GetAffinityMask() } -> std::convertible_to; { t.SetAffinityMask(0) }; { t.GetAffinity(0) } -> std::same_as; @@ -45,9 +44,9 @@ std::is_reference_v&& requires(T& t) { std::remove_cvref_t() } -> KPriorityQueueAffinityMask; - { t.GetActiveCore() } -> Common::ConvertibleTo; - { t.GetPriority() } -> Common::ConvertibleTo; - { t.IsDummyThread() } -> Common::ConvertibleTo; + { t.GetActiveCore() } -> std::convertible_to; + { t.GetPriority() } -> std::convertible_to; + { t.IsDummyThread() } -> std::convertible_to; }; template diff --git a/src/core/hle/service/sm/sm.h b/src/core/hle/service/sm/sm.h index 32c218638d..07ccfc1c78 100644 --- a/src/core/hle/service/sm/sm.h +++ b/src/core/hle/service/sm/sm.h @@ -8,8 +8,8 @@ #include #include #include +#include -#include "common/concepts.h" #include "core/hle/kernel/k_port.h" #include "core/hle/kernel/svc.h" #include "core/hle/result.h" @@ -63,7 +63,7 @@ public: Result UnregisterService(const std::string& name); Result GetServicePort(Kernel::KClientPort** out_client_port, const std::string& name); - template T> + template T> std::shared_ptr GetService(const std::string& service_name, bool block = false) const { auto service = registered_services.find(service_name); if (service == registered_services.end() && !block) { diff --git a/src/video_core/gpu_thread.cpp b/src/video_core/gpu_thread.cpp index 9392534e7d..b0cafbf270 100644 --- a/src/video_core/gpu_thread.cpp +++ b/src/video_core/gpu_thread.cpp @@ -23,9 +23,7 @@ namespace VideoCommon::GPUThread { static void RunThread(std::stop_token stop_token, Core::System& system, VideoCore::RendererBase& renderer, Core::Frontend::GraphicsContext& context, Tegra::Control::Scheduler& scheduler, SynchState& state) { - std::string name = "GPU"; - - Common::SetCurrentThreadName(name.c_str()); + Common::SetCurrentThreadName("GPU"); Common::SetCurrentThreadPriority(Common::ThreadPriority::Critical); system.RegisterHostThread();