diff --git a/.ci/actool.sh b/.ci/actool.sh new file mode 100755 index 0000000000..5be658d2bb --- /dev/null +++ b/.ci/actool.sh @@ -0,0 +1,22 @@ +#!/bin/sh -e + +# SPDX-FileCopyrightText: Copyright 2026 Eden Emulator Project +# SPDX-License-Identifier: GPL-3.0-or-later + +# SPDX-FileCopyrightText: Copyright 2026 crueter +# SPDX-License-Identifier: GPL-3.0-or-later + +_svg=dev.eden_emu.eden.svg +_icon=dist/eden.icon +_composed="$_icon/Assets/$_svg" +_svg="dist/$_svg" + +rm "$_composed" +cp "$_svg" "$_composed" + +xcrun actool "$_icon" \ + --compile dist \ + --platform macosx \ + --minimum-deployment-target 11.0 \ + --app-icon eden \ + --output-partial-info-plist /dev/null diff --git a/.patch/mcl/0001-assert-macro.patch b/.patch/mcl/0001-assert-macro.patch deleted file mode 100644 index 2d7d0dd1b0..0000000000 --- a/.patch/mcl/0001-assert-macro.patch +++ /dev/null @@ -1,55 +0,0 @@ -diff --git a/include/mcl/assert.hpp b/include/mcl/assert.hpp -index f77dbe7..9ec0b9c 100644 ---- a/include/mcl/assert.hpp -+++ b/include/mcl/assert.hpp -@@ -23,8 +23,11 @@ template - - } // namespace mcl::detail - -+#ifndef UNREACHABLE - #define UNREACHABLE() ASSERT_FALSE("Unreachable code!") -+#endif - -+#ifndef ASSERT - #define ASSERT(expr) \ - [&] { \ - if (std::is_constant_evaluated()) { \ -@@ -37,7 +40,9 @@ template - } \ - } \ - }() -+#endif - -+#ifndef ASSERT_MSG - #define ASSERT_MSG(expr, ...) \ - [&] { \ - if (std::is_constant_evaluated()) { \ -@@ -50,13 +55,24 @@ template - } \ - } \ - }() -+#endif - -+#ifndef ASSERT_FALSE - #define ASSERT_FALSE(...) ::mcl::detail::assert_terminate("false", __VA_ARGS__) -+#endif - - #if defined(NDEBUG) || defined(MCL_IGNORE_ASSERTS) --# define DEBUG_ASSERT(expr) ASSUME(expr) --# define DEBUG_ASSERT_MSG(expr, ...) ASSUME(expr) -+# ifndef DEBUG_ASSERT -+# define DEBUG_ASSERT(expr) ASSUME(expr) -+# endif -+# ifndef DEBUG_ASSERT_MSG -+# define DEBUG_ASSERT_MSG(expr, ...) ASSUME(expr) -+# endif - #else --# define DEBUG_ASSERT(expr) ASSERT(expr) --# define DEBUG_ASSERT_MSG(expr, ...) ASSERT_MSG(expr, __VA_ARGS__) -+# ifndef DEBUG_ASSERT -+# define DEBUG_ASSERT(expr) ASSERT(expr) -+# endif -+# ifndef DEBUG_ASSERT_MSG -+# define DEBUG_ASSERT_MSG(expr, ...) ASSERT_MSG(expr, __VA_ARGS__) -+# endif - #endif diff --git a/CMakeLists.txt b/CMakeLists.txt index 4ab08739f7..42717c496d 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -143,8 +143,8 @@ if (MSVC AND ARCHITECTURE_x86) endif() if (CXX_CLANG_CL) + # clang-cl prints literally 10000+ warnings without this add_compile_options( - # clang-cl prints literally 10000+ warnings without this $<$:-Wno-unused-command-line-argument> $<$:-Wno-unsafe-buffer-usage> $<$:-Wno-unused-value> @@ -154,12 +154,12 @@ if (CXX_CLANG_CL) $<$:-Wno-deprecated-declarations> $<$:-Wno-cast-function-type-mismatch> $<$:/EHsc>) - # REQUIRED CPU features IN Windows-amd64 if (ARCHITECTURE_x86_64) add_compile_options( $<$:-msse4.1> - $<$:-mcx16>) + $<$:-mcx16> + ) endif() endif() @@ -395,13 +395,15 @@ if (Boost_ADDED) if (NOT MSVC OR CXX_CLANG) # boost sucks if (PLATFORM_SUN) - set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -pthreads") - set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -pthreads") + add_compile_options($<$:-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) + 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> + ) endif() endif() @@ -440,7 +442,7 @@ if (NOT YUZU_STATIC_ROOM) if (Opus_ADDED) if (MSVC AND CXX_CLANG) target_compile_options(opus PRIVATE - -Wno-implicit-function-declaration + $<$:-Wno-implicit-function-declaration> ) endif() endif() @@ -484,10 +486,10 @@ endfunction() # ============================================= if (APPLE) - # Umbrella framework for everything GUI-related - find_library(COCOA_LIBRARY Cocoa REQUIRED) - find_library(IOKIT_LIBRARY IOKit REQUIRED) - set(PLATFORM_LIBRARIES ${COCOA_LIBRARY} ${IOKIT_LIBRARY} ${COREVIDEO_LIBRARY}) + foreach(fw Carbon Metal Cocoa IOKit CoreVideo CoreMedia) + find_library(${fw}_LIBRARY ${fw} REQUIRED) + list(APPEND PLATFORM_LIBRARIES ${${fw}_LIBRARY}) + endforeach() elseif (WIN32) # Target Windows 10 add_compile_definitions(_WIN32_WINNT=0x0A00 WINVER=0x0A00) @@ -524,7 +526,6 @@ if (NOT YUZU_STATIC_ROOM) find_package(SPIRV-Tools) find_package(sirit) find_package(gamemode) - find_package(mcl) find_package(frozen) if (ARCHITECTURE_riscv64) diff --git a/cpmfile.json b/cpmfile.json index c938e67e88..1bb29afae4 100644 --- a/cpmfile.json +++ b/cpmfile.json @@ -87,8 +87,8 @@ "bundled": true }, "llvm-mingw": { - "repo": "misc/llvm-mingw", - "git_host": "git.crueter.xyz", + "repo": "eden-emu/llvm-mingw", + "git_host": "git.eden-emu.dev", "tag": "%VERSION%", "version": "20250828", "artifact": "clang-rt-builtins.tar.zst", diff --git a/dist/Assets.car b/dist/Assets.car index eb54881fac..9ae9bca8a4 100644 Binary files a/dist/Assets.car and b/dist/Assets.car differ diff --git a/dist/eden.icns b/dist/eden.icns index 680800951d..82529ba224 100644 Binary files a/dist/eden.icns and b/dist/eden.icns differ diff --git a/dist/eden.icon/Assets/dev.eden_emu.eden.svg b/dist/eden.icon/Assets/dev.eden_emu.eden.svg new file mode 100644 index 0000000000..f88b52f625 --- /dev/null +++ b/dist/eden.icon/Assets/dev.eden_emu.eden.svg @@ -0,0 +1,230 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/dist/eden.icon/icon.json b/dist/eden.icon/icon.json new file mode 100644 index 0000000000..1f1e7da516 --- /dev/null +++ b/dist/eden.icon/icon.json @@ -0,0 +1,37 @@ +{ + "fill" : { + "automatic-gradient" : "srgb:0.00000,0.00000,0.00000,1.00000" + }, + "groups" : [ + { + "layers" : [ + { + "fill" : "none", + "image-name" : "dev.eden_emu.eden.svg", + "name" : "dev.eden_emu.eden", + "position" : { + "scale" : 1.8, + "translation-in-points" : [ + 0, + 0 + ] + } + } + ], + "shadow" : { + "kind" : "neutral", + "opacity" : 0.5 + }, + "translucency" : { + "enabled" : true, + "value" : 0.5 + } + } + ], + "supported-platforms" : { + "circles" : [ + "watchOS" + ], + "squares" : "shared" + } +} \ No newline at end of file diff --git a/docs/Deps.md b/docs/Deps.md index fe1f7a14b2..a34e838534 100644 --- a/docs/Deps.md +++ b/docs/Deps.md @@ -76,7 +76,6 @@ Certain other dependencies will be fetched by CPM regardless. System packages *c * This package is known to be broken on the AUR. * [cpp-jwt](https://github.com/arun11299/cpp-jwt) 1.4+ - if `ENABLE_WEB_SERVICE` is on * [unordered-dense](https://github.com/martinus/unordered_dense) -* [mcl](https://github.com/azahar-emu/mcl) - subject to removal On amd64: diff --git a/externals/CMakeLists.txt b/externals/CMakeLists.txt index 7b4c481ba5..00bdf10a4f 100644 --- a/externals/CMakeLists.txt +++ b/externals/CMakeLists.txt @@ -76,9 +76,6 @@ if (ARCHITECTURE_riscv64) AddJsonPackage(biscuit) endif() -# mcl -AddJsonPackage(mcl) - # Vulkan stuff AddDependentPackages(vulkan-headers vulkan-utility-libraries) @@ -109,16 +106,15 @@ if(ENABLE_CUBEB) if (cubeb_ADDED) if (NOT MSVC) if (TARGET speex) - target_compile_options(speex PRIVATE -Wno-sign-compare) + 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 + $<$:-Wno-implicit-const-int-float-conversion> + $<$:-Wno-shadow> + $<$:-Wno-missing-declarations> + $<$:-Wno-return-type> + $<$:-Wno-uninitialized> ) else() target_compile_options(cubeb PRIVATE @@ -184,7 +180,9 @@ if (YUZU_USE_BUNDLED_SIRIT) else() AddJsonPackage(sirit) if(MSVC AND CXX_CLANG) - target_compile_options(siritobj PRIVATE -Wno-error=unused-command-line-argument) + target_compile_options(siritobj PRIVATE + $<$:-Wno-error=unused-command-line-argument> + ) endif() endif() @@ -220,7 +218,7 @@ AddJsonPackage(vulkan-memory-allocator) if (VulkanMemoryAllocator_ADDED) if (CXX_CLANG) target_compile_options(VulkanMemoryAllocator INTERFACE - -Wno-unused-variable + $<$:-Wno-unused-variable> ) elseif(MSVC) target_compile_options(VulkanMemoryAllocator INTERFACE diff --git a/externals/cpmfile.json b/externals/cpmfile.json index 8209e431a3..f849426a4d 100644 --- a/externals/cpmfile.json +++ b/externals/cpmfile.json @@ -208,18 +208,6 @@ "version": "0.9.1", "git_version": "0.19.0" }, - "mcl": { - "version": "0.1.12", - "repo": "azahar-emu/mcl", - "sha": "7b08d83418", - "hash": "9c6ba624cb22ef622f78046a82abb99bf5026284ba17dfacaf46ac842cbd3b0f515f5ba45a1598c7671318a78a2e648db72ce8d10e7537f34e39800bdcb57694", - "options": [ - "MCL_INSTALL OFF" - ], - "patches": [ - "0001-assert-macro.patch" - ] - }, "libusb": { "repo": "libusb/libusb", "tag": "v%VERSION%", @@ -246,12 +234,13 @@ }, "tzdb": { "package": "nx_tzdb", - "repo": "misc/tzdb_to_nx", - "git_host": "git.crueter.xyz", + "repo": "eden-emu/tzdb_to_nx", + "git_host": "git.eden-emu.dev", "artifact": "%VERSION%.tar.gz", "tag": "%VERSION%", - "hash": "dc37a189a44ce8b5c988ca550582431a6c7eadfd3c6e709bee6277116ee803e714333e85c9e6cbb5c69346a14d6f2cc7ed96e8aa09cc5fb8a89f945059651db6", - "version": "121125" + "hash": "cce65a12bf90f4ead43b24a0b95dfad77ac3d9bfbaaf66c55e6701346e7a1e44ca5d2f23f47ee35ee02271eb1082bf1762af207aad9fb236f1c8476812d008ed", + "version": "121125", + "git_version": "230326" }, "vulkan-headers": { "repo": "KhronosGroup/Vulkan-Headers", diff --git a/externals/libusb/CMakeLists.txt b/externals/libusb/CMakeLists.txt index 7eae81d3b6..47b54f43cc 100644 --- a/externals/libusb/CMakeLists.txt +++ b/externals/libusb/CMakeLists.txt @@ -1,4 +1,4 @@ -# SPDX-FileCopyrightText: Copyright 2025 Eden Emulator Project +# SPDX-FileCopyrightText: Copyright 2026 Eden Emulator Project # SPDX-License-Identifier: GPL-3.0-or-later # SPDX-FileCopyrightText: 2020 yuzu Emulator Project @@ -232,7 +232,7 @@ else() # MINGW OR (${CMAKE_SYSTEM_NAME} MATCHES "Linux") ) find_package(Threads REQUIRED) if(THREADS_HAVE_PTHREAD_ARG) - target_compile_options(usb PUBLIC "-pthread") + target_compile_options(usb PUBLIC $<$:-pthread>) endif() if(CMAKE_THREAD_LIBS_INIT) target_link_libraries(usb PRIVATE "${CMAKE_THREAD_LIBS_INIT}") diff --git a/externals/renderdoc/renderdoc_app.h b/externals/renderdoc/renderdoc_app.h index e6c1511deb..c379f0ac40 100644 --- a/externals/renderdoc/renderdoc_app.h +++ b/externals/renderdoc/renderdoc_app.h @@ -7,7 +7,7 @@ /****************************************************************************** * The MIT License (MIT) * - * Copyright (c) 2019-2025 Baldur Karlsson + * Copyright (c) 2015-2026 Baldur Karlsson * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal @@ -72,6 +72,10 @@ extern "C" { // truncated version when only a uint64_t is available (e.g. Vulkan tags): #define RENDERDOC_ShaderDebugMagicValue_truncated 0x48656670eab25520ULL +// this is a magic value for vulkan user tags to indicate which dispatchable API objects are which +// for object annotations +#define RENDERDOC_APIObjectAnnotationHelper 0xfbb3b337b664d0adULL + ////////////////////////////////////////////////////////////////////////////////////////////////// // RenderDoc capture options // @@ -564,6 +568,128 @@ typedef uint32_t(RENDERDOC_CC *pRENDERDOC_DiscardFrameCapture)(RENDERDOC_DeviceP // multiple times only the last title will be used. typedef void(RENDERDOC_CC *pRENDERDOC_SetCaptureTitle)(const char *title); +// Annotations API: +// +// These functions allow you to specify annotations either on a per-command level, or a per-object +// level. +// +// Basic types of annotations are supported, as well as vector versions and references to API objects. +// +// The annotations are stored as keys, with the key being a dot-separated path allowing arbitrary +// nesting and user organisation. The keys are sorted in human order so `foo.2.bar` will be displayed +// before `foo.10.bar` to allow creation of arrays if desired. +// +// Deleting an annotation can be done by assigning an empty value to it. + +// the type of an annotation value, or Empty to delete an annotation +typedef enum RENDERDOC_AnnotationType +{ + eRENDERDOC_Empty, + eRENDERDOC_Bool, + eRENDERDOC_Int32, + eRENDERDOC_UInt32, + eRENDERDOC_Int64, + eRENDERDOC_UInt64, + eRENDERDOC_Float, + eRENDERDOC_Double, + eRENDERDOC_String, + eRENDERDOC_APIObject, + eRENDERDOC_AnnotationMax = 0x7FFFFFFF, +} RENDERDOC_AnnotationType; + +// a union with vector annotation value data +typedef union RENDERDOC_AnnotationVectorValue +{ + bool boolean[4]; + int32_t int32[4]; + int64_t int64[4]; + uint32_t uint32[4]; + uint64_t uint64[4]; + float float32[4]; + double float64[4]; +} RENDERDOC_AnnotationVectorValue; + +// a union with scalar annotation value data +typedef union RENDERDOC_AnnotationValue +{ + bool boolean; + int32_t int32; + int64_t int64; + uint32_t uint32; + uint64_t uint64; + float float32; + double float64; + + RENDERDOC_AnnotationVectorValue vector; + + const char *string; + void *apiObject; +} RENDERDOC_AnnotationValue; + +// a struct for specifying a GL object, as we don't have pointers we can use so instead we specify a +// pointer to this struct giving both the type and the name +typedef struct RENDERDOC_GLResourceReference +{ + // this is the same GLenum identifier as passed to glObjectLabel + uint32_t identifier; + uint32_t name; +} GLResourceReference; + +// simple C++ helpers to avoid the need for a temporary objects for value passing and GL object specification +#ifdef __cplusplus +struct RDGLObjectHelper +{ + RENDERDOC_GLResourceReference gl; + + RDGLObjectHelper(uint32_t identifier, uint32_t name) + { + gl.identifier = identifier; + gl.name = name; + } + + operator RENDERDOC_GLResourceReference *() { return ≷ } +}; + +struct RDAnnotationHelper +{ + RENDERDOC_AnnotationValue val; + + RDAnnotationHelper(bool b) { val.boolean = b; } + RDAnnotationHelper(int32_t i) { val.int32 = i; } + RDAnnotationHelper(int64_t i) { val.int64 = i; } + RDAnnotationHelper(uint32_t i) { val.uint32 = i; } + RDAnnotationHelper(uint64_t i) { val.uint64 = i; } + RDAnnotationHelper(float f) { val.float32 = f; } + RDAnnotationHelper(double d) { val.float64 = d; } + RDAnnotationHelper(const char *s) { val.string = s; } + + operator RENDERDOC_AnnotationValue *() { return &val; } +}; +#endif + +// The device is specified in the same way as other API calls that take a RENDERDOC_DevicePointer +// to specify the device. +// +// The object or queue/commandbuffer will depend on the graphics API in question. +// +// Return value: +// 0 - The annotation was applied successfully. +// 1 - The device is unknown/invalid +// 2 - The device is valid but the annotation is not supported for API-specific reasons, such as an +// unrecognised or invalid object or queue/commandbuffer +// 3 - The call is ill-formed or invalid e.g. empty is specified with a value pointer, or non-empty +// is specified with a NULL value pointer +typedef uint32_t(RENDERDOC_CC *pRENDERDOC_SetObjectAnnotation)(RENDERDOC_DevicePointer device, + void *object, const char *key, + RENDERDOC_AnnotationType valueType, + uint32_t valueVectorWidth, + const RENDERDOC_AnnotationValue *value); + +typedef uint32_t(RENDERDOC_CC *pRENDERDOC_SetCommandAnnotation)( + RENDERDOC_DevicePointer device, void *queueOrCommandBuffer, const char *key, + RENDERDOC_AnnotationType valueType, uint32_t valueVectorWidth, + const RENDERDOC_AnnotationValue *value); + ////////////////////////////////////////////////////////////////////////////////////////////////// // RenderDoc API versions // @@ -592,6 +718,7 @@ typedef enum RENDERDOC_Version eRENDERDOC_API_Version_1_4_2 = 10402, // RENDERDOC_API_1_4_2 = 1 04 02 eRENDERDOC_API_Version_1_5_0 = 10500, // RENDERDOC_API_1_5_0 = 1 05 00 eRENDERDOC_API_Version_1_6_0 = 10600, // RENDERDOC_API_1_6_0 = 1 06 00 + eRENDERDOC_API_Version_1_7_0 = 10700, // RENDERDOC_API_1_7_0 = 1 07 00 } RENDERDOC_Version; // API version changelog: @@ -622,8 +749,10 @@ typedef enum RENDERDOC_Version // 1.5.0 - Added feature: ShowReplayUI() to request that the replay UI show itself if connected // 1.6.0 - Added feature: SetCaptureTitle() which can be used to set a title for a // capture made with StartFrameCapture() or EndFrameCapture() +// 1.7.0 - Added feature: SetObjectAnnotation() / SetCommandAnnotation() for adding rich +// annotations to objects and command streams -typedef struct RENDERDOC_API_1_6_0 +typedef struct RENDERDOC_API_1_7_0 { pRENDERDOC_GetAPIVersion GetAPIVersion; @@ -701,20 +830,25 @@ typedef struct RENDERDOC_API_1_6_0 // new function in 1.6.0 pRENDERDOC_SetCaptureTitle SetCaptureTitle; -} RENDERDOC_API_1_6_0; -typedef RENDERDOC_API_1_6_0 RENDERDOC_API_1_0_0; -typedef RENDERDOC_API_1_6_0 RENDERDOC_API_1_0_1; -typedef RENDERDOC_API_1_6_0 RENDERDOC_API_1_0_2; -typedef RENDERDOC_API_1_6_0 RENDERDOC_API_1_1_0; -typedef RENDERDOC_API_1_6_0 RENDERDOC_API_1_1_1; -typedef RENDERDOC_API_1_6_0 RENDERDOC_API_1_1_2; -typedef RENDERDOC_API_1_6_0 RENDERDOC_API_1_2_0; -typedef RENDERDOC_API_1_6_0 RENDERDOC_API_1_3_0; -typedef RENDERDOC_API_1_6_0 RENDERDOC_API_1_4_0; -typedef RENDERDOC_API_1_6_0 RENDERDOC_API_1_4_1; -typedef RENDERDOC_API_1_6_0 RENDERDOC_API_1_4_2; -typedef RENDERDOC_API_1_6_0 RENDERDOC_API_1_5_0; + // new functions in 1.7.0 + pRENDERDOC_SetObjectAnnotation SetObjectAnnotation; + pRENDERDOC_SetCommandAnnotation SetCommandAnnotation; +} RENDERDOC_API_1_7_0; + +typedef RENDERDOC_API_1_7_0 RENDERDOC_API_1_0_0; +typedef RENDERDOC_API_1_7_0 RENDERDOC_API_1_0_1; +typedef RENDERDOC_API_1_7_0 RENDERDOC_API_1_0_2; +typedef RENDERDOC_API_1_7_0 RENDERDOC_API_1_1_0; +typedef RENDERDOC_API_1_7_0 RENDERDOC_API_1_1_1; +typedef RENDERDOC_API_1_7_0 RENDERDOC_API_1_1_2; +typedef RENDERDOC_API_1_7_0 RENDERDOC_API_1_2_0; +typedef RENDERDOC_API_1_7_0 RENDERDOC_API_1_3_0; +typedef RENDERDOC_API_1_7_0 RENDERDOC_API_1_4_0; +typedef RENDERDOC_API_1_7_0 RENDERDOC_API_1_4_1; +typedef RENDERDOC_API_1_7_0 RENDERDOC_API_1_4_2; +typedef RENDERDOC_API_1_7_0 RENDERDOC_API_1_5_0; +typedef RENDERDOC_API_1_7_0 RENDERDOC_API_1_6_0; ////////////////////////////////////////////////////////////////////////////////////////////////// // RenderDoc API entry point diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt index a9fa5314b7..600b985609 100644 --- a/src/CMakeLists.txt +++ b/src/CMakeLists.txt @@ -118,47 +118,42 @@ if (MSVC AND NOT CXX_CLANG) else() if (NOT MSVC) add_compile_options( - -fwrapv - -fno-rtti # Disable RTTI - -pipe - ) + $<$:-fwrapv> + $<$:-pipe> + # Disable RTTI (C++ only) + $<$:-fno-rtti>) endif() add_compile_options( - -Werror=all - -Werror=extra - -Werror=missing-declarations - -Werror=shadow - -Werror=unused - - -Wno-attributes - -Wno-invalid-offsetof - -Wno-unused-parameter - -Wno-missing-field-initializers - ) + $<$:-Werror=all> + $<$:-Werror=extra> + $<$:-Werror=missing-declarations> + $<$:-Werror=shadow> + $<$:-Werror=unused> + $<$:-Wno-attributes> + $<$:-Wno-invalid-offsetof> + $<$:-Wno-unused-parameter> + $<$:-Wno-missing-field-initializers>) if (CXX_CLANG OR CXX_ICC OR CXX_APPLE) # Clang, AppleClang, or Intel C++ if (NOT MSVC) add_compile_options( - -Werror=shadow-uncaptured-local - -Werror=implicit-fallthrough - -Werror=type-limits - ) + $<$:-Werror=shadow-uncaptured-local> + $<$:-Werror=implicit-fallthrough> + $<$:-Werror=type-limits>) endif() - add_compile_options( - -Wno-braced-scalar-init - -Wno-unused-private-field - -Wno-nullability-completeness - ) + $<$:-Wno-braced-scalar-init> + $<$:-Wno-unused-private-field> + $<$:-Wno-nullability-completeness>) endif() if (ARCHITECTURE_x86_64) - add_compile_options("-mcx16") + add_compile_options(-mcx16) endif() if (APPLE AND CXX_CLANG) - add_compile_options("-stdlib=libc++") + add_compile_options($<$:-stdlib=libc++>) endif() # GCC bugs @@ -166,10 +161,9 @@ else() # These diagnostics would be great if they worked, but are just completely broken # and produce bogus errors on external libraries like fmt. add_compile_options( - -Wno-array-bounds - -Wno-stringop-overread - -Wno-stringop-overflow - ) + $<$:-Wno-array-bounds> + $<$:-Wno-stringop-overread> + $<$:-Wno-stringop-overflow>) endif() # Set file offset size to 64 bits. diff --git a/src/android/app/src/main/java/org/yuzu/yuzu_emu/dialogs/ChatDialog.kt b/src/android/app/src/main/java/org/yuzu/yuzu_emu/dialogs/ChatDialog.kt index 5d6679bd28..431125ca8e 100644 --- a/src/android/app/src/main/java/org/yuzu/yuzu_emu/dialogs/ChatDialog.kt +++ b/src/android/app/src/main/java/org/yuzu/yuzu_emu/dialogs/ChatDialog.kt @@ -1,4 +1,4 @@ -// SPDX-FileCopyrightText: Copyright 2025 Eden Emulator Project +// SPDX-FileCopyrightText: Copyright 2026 Eden Emulator Project // SPDX-License-Identifier: GPL-3.0-or-later package org.yuzu.yuzu_emu.dialogs @@ -20,6 +20,8 @@ import org.yuzu.yuzu_emu.databinding.DialogChatBinding import org.yuzu.yuzu_emu.databinding.ItemChatMessageBinding import org.yuzu.yuzu_emu.features.settings.model.StringSetting import org.yuzu.yuzu_emu.network.NetPlayManager +import org.yuzu.yuzu_emu.utils.CompatUtils +import org.yuzu.yuzu_emu.utils.FullscreenHelper import java.text.SimpleDateFormat import java.util.* @@ -34,6 +36,13 @@ class ChatDialog(context: Context) : BottomSheetDialog(context) { private lateinit var binding: DialogChatBinding private lateinit var chatAdapter: ChatAdapter private val handler = Handler(Looper.getMainLooper()) + private val hideSystemBars: Boolean by lazy { + runCatching { + FullscreenHelper.shouldHideSystemBars(CompatUtils.findActivity(context)) + }.getOrElse { + FullscreenHelper.isFullscreenEnabled(context) + } + } // TODO(alekpop, crueter): Top drawer for message notifications, perhaps use system notifs? // TODO(alekpop, crueter): Context menu actions for chat users @@ -41,6 +50,7 @@ class ChatDialog(context: Context) : BottomSheetDialog(context) { @SuppressLint("NotifyDataSetChanged") override fun onCreate(savedInstanceState: Bundle?) { super.onCreate(savedInstanceState) + setOnShowListener { applyFullscreenMode() } binding = DialogChatBinding.inflate(LayoutInflater.from(context)) setContentView(binding.root) @@ -75,6 +85,11 @@ class ChatDialog(context: Context) : BottomSheetDialog(context) { } } + override fun onStart() { + super.onStart() + applyFullscreenMode() + } + override fun dismiss() { NetPlayManager.setChatOpen(false) super.dismiss() @@ -108,6 +123,12 @@ class ChatDialog(context: Context) : BottomSheetDialog(context) { private fun scrollToBottom() { binding.chatRecyclerView.scrollToPosition(chatAdapter.itemCount - 1) } + + private fun applyFullscreenMode() { + window?.let { window -> + FullscreenHelper.applyToWindow(window, hideSystemBars) + } + } } class ChatAdapter(private val messages: List) : diff --git a/src/android/app/src/main/java/org/yuzu/yuzu_emu/dialogs/LobbyBrowser.kt b/src/android/app/src/main/java/org/yuzu/yuzu_emu/dialogs/LobbyBrowser.kt index 6d5c6ef23f..10ff2da6c7 100644 --- a/src/android/app/src/main/java/org/yuzu/yuzu_emu/dialogs/LobbyBrowser.kt +++ b/src/android/app/src/main/java/org/yuzu/yuzu_emu/dialogs/LobbyBrowser.kt @@ -31,15 +31,25 @@ import org.yuzu.yuzu_emu.databinding.DialogLobbyBrowserBinding import org.yuzu.yuzu_emu.databinding.ItemLobbyRoomBinding import org.yuzu.yuzu_emu.features.settings.model.StringSetting import org.yuzu.yuzu_emu.network.NetPlayManager +import org.yuzu.yuzu_emu.utils.CompatUtils +import org.yuzu.yuzu_emu.utils.FullscreenHelper import java.util.Locale class LobbyBrowser(context: Context) : BottomSheetDialog(context) { private lateinit var binding: DialogLobbyBrowserBinding private lateinit var adapter: LobbyRoomAdapter private val handler = Handler(Looper.getMainLooper()) + private val hideSystemBars: Boolean by lazy { + runCatching { + FullscreenHelper.shouldHideSystemBars(CompatUtils.findActivity(context)) + }.getOrElse { + FullscreenHelper.isFullscreenEnabled(context) + } + } override fun onCreate(savedInstanceState: Bundle?) { super.onCreate(savedInstanceState) + setOnShowListener { applyFullscreenMode() } behavior.state = BottomSheetBehavior.STATE_EXPANDED behavior.skipCollapsed = @@ -81,6 +91,7 @@ class LobbyBrowser(context: Context) : BottomSheetDialog(context) { behavior.expandedOffset = 0 behavior.skipCollapsed = true behavior.state = BottomSheetBehavior.STATE_EXPANDED + applyFullscreenMode() } private fun setupRecyclerView() { @@ -274,4 +285,10 @@ class LobbyBrowser(context: Context) : BottomSheetDialog(context) { } private inner class ScoreItem(val score: Double, val item: NetPlayManager.RoomInfo) + + private fun applyFullscreenMode() { + window?.let { window -> + FullscreenHelper.applyToWindow(window, hideSystemBars) + } + } } diff --git a/src/android/app/src/main/java/org/yuzu/yuzu_emu/dialogs/NetPlayDialog.kt b/src/android/app/src/main/java/org/yuzu/yuzu_emu/dialogs/NetPlayDialog.kt index 73452b4b69..45ce5fb0cf 100644 --- a/src/android/app/src/main/java/org/yuzu/yuzu_emu/dialogs/NetPlayDialog.kt +++ b/src/android/app/src/main/java/org/yuzu/yuzu_emu/dialogs/NetPlayDialog.kt @@ -1,4 +1,4 @@ -// SPDX-FileCopyrightText: Copyright 2025 Eden Emulator Project +// SPDX-FileCopyrightText: Copyright 2026 Eden Emulator Project // SPDX-License-Identifier: GPL-3.0-or-later package org.yuzu.yuzu_emu.dialogs @@ -36,6 +36,7 @@ import org.yuzu.yuzu_emu.features.settings.model.StringSetting import org.yuzu.yuzu_emu.network.NetDataValidators import org.yuzu.yuzu_emu.network.NetPlayManager import org.yuzu.yuzu_emu.utils.CompatUtils +import org.yuzu.yuzu_emu.utils.FullscreenHelper import org.yuzu.yuzu_emu.utils.GameHelper class NetPlayDialog(context: Context) : BottomSheetDialog(context) { @@ -43,9 +44,17 @@ class NetPlayDialog(context: Context) : BottomSheetDialog(context) { private val gameNameList: MutableList> = mutableListOf() private val gameIdList: MutableList> = mutableListOf() + private val hideSystemBars: Boolean by lazy { + runCatching { + FullscreenHelper.shouldHideSystemBars(CompatUtils.findActivity(context)) + }.getOrElse { + FullscreenHelper.isFullscreenEnabled(context) + } + } override fun onCreate(savedInstanceState: Bundle?) { super.onCreate(savedInstanceState) + setOnShowListener { applyFullscreenMode() } behavior.state = BottomSheetBehavior.STATE_EXPANDED behavior.state = BottomSheetBehavior.STATE_EXPANDED @@ -118,6 +127,11 @@ class NetPlayDialog(context: Context) : BottomSheetDialog(context) { } } + override fun onStart() { + super.onStart() + applyFullscreenMode() + } + data class NetPlayItems( val option: Int, val name: String, @@ -352,6 +366,11 @@ class NetPlayDialog(context: Context) : BottomSheetDialog(context) { TextValidatorWatcher.validStates.clear() val activity = CompatUtils.findActivity(context) val dialog = BottomSheetDialog(activity) + dialog.setOnShowListener { + dialog.window?.let { window -> + FullscreenHelper.applyToWindow(window, hideSystemBars) + } + } dialog.behavior.state = BottomSheetBehavior.STATE_EXPANDED dialog.behavior.state = BottomSheetBehavior.STATE_EXPANDED @@ -582,6 +601,12 @@ class NetPlayDialog(context: Context) : BottomSheetDialog(context) { dialog.show() } + private fun applyFullscreenMode() { + window?.let { window -> + FullscreenHelper.applyToWindow(window, hideSystemBars) + } + } + private fun showModerationDialog() { val activity = CompatUtils.findActivity(context) val dialog = MaterialAlertDialogBuilder(activity) diff --git a/src/android/app/src/main/java/org/yuzu/yuzu_emu/features/settings/model/Settings.kt b/src/android/app/src/main/java/org/yuzu/yuzu_emu/features/settings/model/Settings.kt index 0f89533d8e..b438812d58 100644 --- a/src/android/app/src/main/java/org/yuzu/yuzu_emu/features/settings/model/Settings.kt +++ b/src/android/app/src/main/java/org/yuzu/yuzu_emu/features/settings/model/Settings.kt @@ -104,6 +104,8 @@ object Settings { const val PREF_THEME_MODE = "ThemeMode" const val PREF_BLACK_BACKGROUNDS = "BlackBackgrounds" const val PREF_STATIC_THEME_COLOR = "StaticThemeColor" + const val PREF_APP_FULLSCREEN = "AppFullscreen" + const val APP_FULLSCREEN_DEFAULT = false enum class EmulationOrientation(val int: Int) { Unspecified(0), 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 a20858f0a9..6f25856cbf 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 @@ -670,15 +670,6 @@ abstract class SettingsItem( valuesId = R.array.dmaAccuracyValues ) ) - put( - SingleChoiceSetting( - IntSetting.FRAME_PACING_MODE, - titleId = R.string.frame_pacing_mode, - descriptionId = R.string.frame_pacing_mode_description, - choicesId = R.array.framePacingModeNames, - valuesId = R.array.framePacingModeValues - ) - ) put( SwitchSetting( BooleanSetting.RENDERER_ASYNCHRONOUS_SHADERS, diff --git a/src/android/app/src/main/java/org/yuzu/yuzu_emu/features/settings/ui/SettingsActivity.kt b/src/android/app/src/main/java/org/yuzu/yuzu_emu/features/settings/ui/SettingsActivity.kt index d33bbc3d7d..ad1ecba64c 100644 --- a/src/android/app/src/main/java/org/yuzu/yuzu_emu/features/settings/ui/SettingsActivity.kt +++ b/src/android/app/src/main/java/org/yuzu/yuzu_emu/features/settings/ui/SettingsActivity.kt @@ -103,6 +103,7 @@ class SettingsActivity : AppCompatActivity() { ) setInsets() + applyFullscreenPreference() } fun navigateBack() { @@ -122,6 +123,18 @@ class SettingsActivity : AppCompatActivity() { } } + override fun onResume() { + super.onResume() + applyFullscreenPreference() + } + + override fun onWindowFocusChanged(hasFocus: Boolean) { + super.onWindowFocusChanged(hasFocus) + if (hasFocus) { + applyFullscreenPreference() + } + } + override fun onStop() { super.onStop() Log.info("[SettingsActivity] Settings activity stopping. Saving settings to INI...") @@ -188,4 +201,8 @@ class SettingsActivity : AppCompatActivity() { windowInsets } } + + private fun applyFullscreenPreference() { + FullscreenHelper.applyToActivity(this) + } } 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 ff25584c92..060a6fe9ae 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 @@ -29,6 +29,8 @@ import org.yuzu.yuzu_emu.features.settings.model.view.* import org.yuzu.yuzu_emu.utils.InputHandler import org.yuzu.yuzu_emu.utils.NativeConfig import org.yuzu.yuzu_emu.utils.DirectoryInitialization +import org.yuzu.yuzu_emu.utils.FullscreenHelper +import androidx.core.content.edit import androidx.fragment.app.FragmentActivity import org.yuzu.yuzu_emu.fragments.MessageDialogFragment @@ -254,7 +256,6 @@ class SettingsFragmentPresenter( add(IntSetting.RENDERER_ACCURACY.key) add(IntSetting.DMA_ACCURACY.key) - add(IntSetting.FRAME_PACING_MODE.key) add(IntSetting.MAX_ANISOTROPY.key) add(IntSetting.RENDERER_VRAM_USAGE_MODE.key) add(IntSetting.RENDERER_ASTC_DECODE_METHOD.key) @@ -1187,6 +1188,39 @@ class SettingsFragmentPresenter( ) ) + val fullscreenSetting: AbstractBooleanSetting = object : AbstractBooleanSetting { + override fun getBoolean(needsGlobal: Boolean): Boolean = + FullscreenHelper.isFullscreenEnabled(context) + + override fun setBoolean(value: Boolean) { + FullscreenHelper.setFullscreenEnabled(context, value) + settingsViewModel.setShouldRecreate(true) + } + + override val key: String = Settings.PREF_APP_FULLSCREEN + override val isRuntimeModifiable: Boolean = true + override val pairedSettingKey: String = "" + override val isSwitchable: Boolean = false + override var global: Boolean = true + override val isSaveable: Boolean = true + override val defaultValue: Boolean = Settings.APP_FULLSCREEN_DEFAULT + + override fun getValueAsString(needsGlobal: Boolean): String = + getBoolean(needsGlobal).toString() + + override fun reset() { + setBoolean(defaultValue) + } + } + + add( + SwitchSetting( + fullscreenSetting, + titleId = R.string.fullscreen_mode, + descriptionId = R.string.fullscreen_mode_description + ) + ) + add(HeaderSetting(R.string.buttons)) add(BooleanSetting.ENABLE_FOLDER_BUTTON.key) add(BooleanSetting.ENABLE_QLAUNCH_BUTTON.key) diff --git a/src/android/app/src/main/java/org/yuzu/yuzu_emu/features/settings/ui/SettingsSubscreenActivity.kt b/src/android/app/src/main/java/org/yuzu/yuzu_emu/features/settings/ui/SettingsSubscreenActivity.kt index 11ecd355fb..91888dce12 100644 --- a/src/android/app/src/main/java/org/yuzu/yuzu_emu/features/settings/ui/SettingsSubscreenActivity.kt +++ b/src/android/app/src/main/java/org/yuzu/yuzu_emu/features/settings/ui/SettingsSubscreenActivity.kt @@ -20,6 +20,7 @@ import org.yuzu.yuzu_emu.R import org.yuzu.yuzu_emu.YuzuApplication import org.yuzu.yuzu_emu.databinding.ActivitySettingsBinding import org.yuzu.yuzu_emu.utils.DirectoryInitialization +import org.yuzu.yuzu_emu.utils.FullscreenHelper import org.yuzu.yuzu_emu.utils.InsetsHelper import org.yuzu.yuzu_emu.utils.ThemeHelper @@ -89,6 +90,7 @@ class SettingsSubscreenActivity : AppCompatActivity() { ) setInsets() + applyFullscreenPreference() } override fun onStart() { @@ -98,6 +100,18 @@ class SettingsSubscreenActivity : AppCompatActivity() { } } + override fun onResume() { + super.onResume() + applyFullscreenPreference() + } + + override fun onWindowFocusChanged(hasFocus: Boolean) { + super.onWindowFocusChanged(hasFocus) + if (hasFocus) { + applyFullscreenPreference() + } + } + fun navigateBack() { val navHostFragment = supportFragmentManager.findFragmentById(R.id.fragment_container) as NavHostFragment @@ -149,4 +163,8 @@ class SettingsSubscreenActivity : AppCompatActivity() { windowInsets } } + + private fun applyFullscreenPreference() { + FullscreenHelper.applyToActivity(this) + } } diff --git a/src/android/app/src/main/java/org/yuzu/yuzu_emu/fragments/DriverManagerFragment.kt b/src/android/app/src/main/java/org/yuzu/yuzu_emu/fragments/DriverManagerFragment.kt index 877097dc80..3aa55522e6 100644 --- a/src/android/app/src/main/java/org/yuzu/yuzu_emu/fragments/DriverManagerFragment.kt +++ b/src/android/app/src/main/java/org/yuzu/yuzu_emu/fragments/DriverManagerFragment.kt @@ -29,7 +29,6 @@ import org.yuzu.yuzu_emu.databinding.FragmentDriverManagerBinding import org.yuzu.yuzu_emu.features.settings.model.Settings import org.yuzu.yuzu_emu.features.settings.model.StringSetting import org.yuzu.yuzu_emu.features.settings.ui.SettingsSubscreen -import org.yuzu.yuzu_emu.model.Driver.Companion.toDriver import org.yuzu.yuzu_emu.model.DriverViewModel import org.yuzu.yuzu_emu.model.HomeViewModel import org.yuzu.yuzu_emu.utils.FileUtil @@ -216,19 +215,23 @@ class DriverManagerFragment : Fragment() { val driverData = GpuDriverHelper.getMetadataFromZip(driverFile) val driverInList = - driverViewModel.driverData.firstOrNull { it.second == driverData } + driverViewModel.driverData.firstOrNull { + it.first == driverPath || it.second == driverData + } if (driverInList != null) { return@newInstance getString(R.string.driver_already_installed) } else { driverViewModel.onDriverAdded(Pair(driverPath, driverData)) withContext(Dispatchers.Main) { if (_binding != null) { + refreshDriverList() val adapter = binding.listDrivers.adapter as DriverAdapter - adapter.addItem(driverData.toDriver()) - adapter.selectItem(adapter.currentList.indices.last) + val selectedPosition = adapter.currentList + .indexOfFirst { it.selected } + .let { if (it == -1) 0 else it } driverViewModel.showClearButton(!StringSetting.DRIVER_PATH.global) binding.listDrivers - .smoothScrollToPosition(adapter.currentList.indices.last) + .smoothScrollToPosition(selectedPosition) } } } diff --git a/src/android/app/src/main/java/org/yuzu/yuzu_emu/fragments/GamePropertiesFragment.kt b/src/android/app/src/main/java/org/yuzu/yuzu_emu/fragments/GamePropertiesFragment.kt index 46b75197d5..faa35bc3eb 100644 --- a/src/android/app/src/main/java/org/yuzu/yuzu_emu/fragments/GamePropertiesFragment.kt +++ b/src/android/app/src/main/java/org/yuzu/yuzu_emu/fragments/GamePropertiesFragment.kt @@ -133,8 +133,11 @@ class GamePropertiesFragment : Fragment() { } override fun onDestroy() { + val isChangingConfigurations = activity?.isChangingConfigurations == true super.onDestroy() - gamesViewModel.reloadGames(true) + if (!isChangingConfigurations) { + gamesViewModel.reloadGames(true) + } } private fun getPlayTime() { diff --git a/src/android/app/src/main/java/org/yuzu/yuzu_emu/fragments/ProfileManagerFragment.kt b/src/android/app/src/main/java/org/yuzu/yuzu_emu/fragments/ProfileManagerFragment.kt index 2786906f6b..bd37c4c9c7 100644 --- a/src/android/app/src/main/java/org/yuzu/yuzu_emu/fragments/ProfileManagerFragment.kt +++ b/src/android/app/src/main/java/org/yuzu/yuzu_emu/fragments/ProfileManagerFragment.kt @@ -9,6 +9,7 @@ import android.view.View import android.view.ViewGroup import androidx.core.view.ViewCompat import androidx.core.view.WindowInsetsCompat +import androidx.core.view.updatePadding import androidx.fragment.app.Fragment import androidx.fragment.app.activityViewModels import androidx.navigation.fragment.findNavController @@ -22,6 +23,7 @@ import org.yuzu.yuzu_emu.databinding.FragmentProfileManagerBinding import org.yuzu.yuzu_emu.model.HomeViewModel import org.yuzu.yuzu_emu.model.UserProfile import org.yuzu.yuzu_emu.utils.NativeConfig +import org.yuzu.yuzu_emu.utils.ViewUtils.updateMargins class ProfileManagerFragment : Fragment() { private var _binding: FragmentProfileManagerBinding? = null @@ -172,11 +174,19 @@ class ProfileManagerFragment : Fragment() { val leftInsets = barInsets.left + cutoutInsets.left val rightInsets = barInsets.right + cutoutInsets.right - val fabLayoutParams = binding.buttonAddUser.layoutParams as ViewGroup.MarginLayoutParams - fabLayoutParams.leftMargin = leftInsets + 24 - fabLayoutParams.rightMargin = rightInsets + 24 - fabLayoutParams.bottomMargin = barInsets.bottom + 24 - binding.buttonAddUser.layoutParams = fabLayoutParams + binding.toolbarProfiles.updateMargins(left = leftInsets, right = rightInsets) + binding.listProfiles.updateMargins(left = leftInsets, right = rightInsets) + binding.listProfiles.updatePadding( + bottom = barInsets.bottom + + resources.getDimensionPixelSize(R.dimen.spacing_bottom_list_fab) + ) + + val fabSpacing = resources.getDimensionPixelSize(R.dimen.spacing_fab) + binding.buttonAddUser.updateMargins( + left = leftInsets + fabSpacing, + right = rightInsets + fabSpacing, + bottom = barInsets.bottom + fabSpacing + ) windowInsets } diff --git a/src/android/app/src/main/java/org/yuzu/yuzu_emu/model/DriverViewModel.kt b/src/android/app/src/main/java/org/yuzu/yuzu_emu/model/DriverViewModel.kt index fc7fbc9bfc..3904f83279 100644 --- a/src/android/app/src/main/java/org/yuzu/yuzu_emu/model/DriverViewModel.kt +++ b/src/android/app/src/main/java/org/yuzu/yuzu_emu/model/DriverViewModel.kt @@ -154,15 +154,30 @@ class DriverViewModel : ViewModel() { } fun onDriverRemoved(removedPosition: Int, selectedPosition: Int) { - driversToDelete.add(driverData[removedPosition - 1].first) - driverData.removeAt(removedPosition - 1) - onDriverSelected(selectedPosition) + val driverIndex = removedPosition - 1 + if (driverIndex !in driverData.indices) { + updateDriverList() + return + } + + driversToDelete.add(driverData[driverIndex].first) + driverData.removeAt(driverIndex) + val safeSelectedPosition = selectedPosition.coerceIn(0, driverData.size) + onDriverSelected(safeSelectedPosition) } fun onDriverAdded(driver: Pair) { if (driversToDelete.contains(driver.first)) { driversToDelete.remove(driver.first) } + + val existingDriverIndex = driverData.indexOfFirst { + it.first == driver.first || it.second == driver.second + } + if (existingDriverIndex != -1) { + onDriverSelected(existingDriverIndex + 1) + return + } driverData.add(driver) onDriverSelected(driverData.size) } diff --git a/src/android/app/src/main/java/org/yuzu/yuzu_emu/ui/main/MainActivity.kt b/src/android/app/src/main/java/org/yuzu/yuzu_emu/ui/main/MainActivity.kt index 3a771edfcb..584322df50 100644 --- a/src/android/app/src/main/java/org/yuzu/yuzu_emu/ui/main/MainActivity.kt +++ b/src/android/app/src/main/java/org/yuzu/yuzu_emu/ui/main/MainActivity.kt @@ -86,8 +86,6 @@ class MainActivity : AppCompatActivity(), ThemeProvider { binding = ActivityMainBinding.inflate(layoutInflater) - // Since Android 15, google automatically forces "games" to be 60 hrz - // This ensures the display's max refresh rate is actually used display?.let { val supportedModes = it.supportedModes val maxRefreshRate = supportedModes.maxByOrNull { mode -> mode.refreshRate } @@ -169,6 +167,7 @@ class MainActivity : AppCompatActivity(), ThemeProvider { checkForUpdates() } setInsets() + applyFullscreenPreference() } private fun checkForUpdates() { @@ -345,6 +344,14 @@ class MainActivity : AppCompatActivity(), ThemeProvider { override fun onResume() { ThemeHelper.setCorrectTheme(this) super.onResume() + applyFullscreenPreference() + } + + override fun onWindowFocusChanged(hasFocus: Boolean) { + super.onWindowFocusChanged(hasFocus) + if (hasFocus) { + applyFullscreenPreference() + } } private fun setInsets() = ViewCompat.setOnApplyWindowInsetsListener( @@ -364,6 +371,10 @@ class MainActivity : AppCompatActivity(), ThemeProvider { windowInsets } + private fun applyFullscreenPreference() { + FullscreenHelper.applyToActivity(this) + } + override fun setTheme(resId: Int) { super.setTheme(resId) themeId = resId diff --git a/src/android/app/src/main/java/org/yuzu/yuzu_emu/utils/FullscreenHelper.kt b/src/android/app/src/main/java/org/yuzu/yuzu_emu/utils/FullscreenHelper.kt new file mode 100644 index 0000000000..62c83e1806 --- /dev/null +++ b/src/android/app/src/main/java/org/yuzu/yuzu_emu/utils/FullscreenHelper.kt @@ -0,0 +1,52 @@ +// SPDX-FileCopyrightText: Copyright 2026 Eden Emulator Project +// SPDX-License-Identifier: GPL-3.0-or-later + +package org.yuzu.yuzu_emu.utils + +import android.app.Activity +import android.content.Context +import android.view.Window +import androidx.core.content.edit +import androidx.core.view.ViewCompat +import androidx.core.view.WindowInsetsCompat +import androidx.core.view.WindowInsetsControllerCompat +import androidx.preference.PreferenceManager +import org.yuzu.yuzu_emu.features.settings.model.Settings + +object FullscreenHelper { + fun isFullscreenEnabled(context: Context): Boolean { + return PreferenceManager.getDefaultSharedPreferences(context).getBoolean( + Settings.PREF_APP_FULLSCREEN, + Settings.APP_FULLSCREEN_DEFAULT + ) + } + + fun setFullscreenEnabled(context: Context, enabled: Boolean) { + PreferenceManager.getDefaultSharedPreferences(context).edit { + putBoolean(Settings.PREF_APP_FULLSCREEN, enabled) + } + } + + fun shouldHideSystemBars(activity: Activity): Boolean { + val rootInsets = ViewCompat.getRootWindowInsets(activity.window.decorView) + val barsCurrentlyHidden = + rootInsets?.isVisible(WindowInsetsCompat.Type.systemBars())?.not() ?: false + return isFullscreenEnabled(activity) || barsCurrentlyHidden + } + + fun applyToWindow(window: Window, hideSystemBars: Boolean) { + val controller = WindowInsetsControllerCompat(window, window.decorView) + + if (hideSystemBars) { + controller.hide(WindowInsetsCompat.Type.systemBars()) + controller.systemBarsBehavior = + WindowInsetsControllerCompat.BEHAVIOR_SHOW_TRANSIENT_BARS_BY_SWIPE + } else { + controller.show(WindowInsetsCompat.Type.systemBars()) + } + } + + fun applyToActivity(activity: Activity) { + applyToWindow(activity.window, isFullscreenEnabled(activity)) + } +} diff --git a/src/android/app/src/main/jni/emu_window/emu_window.cpp b/src/android/app/src/main/jni/emu_window/emu_window.cpp index 4e6fd560f4..6886dac172 100644 --- a/src/android/app/src/main/jni/emu_window/emu_window.cpp +++ b/src/android/app/src/main/jni/emu_window/emu_window.cpp @@ -6,8 +6,15 @@ #include +#include +#include +#include +#include +#include + #include "common/android/id_cache.h" #include "common/logging.h" +#include "common/settings.h" #include "input_common/drivers/android.h" #include "input_common/drivers/touch_screen.h" #include "input_common/drivers/virtual_amiibo.h" @@ -22,6 +29,12 @@ void EmuWindow_Android::OnSurfaceChanged(ANativeWindow* surface) { m_window_width = 0; m_window_height = 0; window_info.render_surface = nullptr; + m_last_frame_rate_hint = -1.0f; + m_pending_frame_rate_hint = -1.0f; + m_pending_frame_rate_hint_votes = 0; + m_smoothed_present_rate = 0.0f; + m_last_frame_display_time = {}; + m_pending_frame_rate_since = {}; return; } @@ -32,6 +45,7 @@ void EmuWindow_Android::OnSurfaceChanged(ANativeWindow* surface) { UpdateCurrentFramebufferLayout(m_window_width, m_window_height); window_info.render_surface = reinterpret_cast(surface); + UpdateFrameRateHint(); } void EmuWindow_Android::OnTouchPressed(int id, float x, float y) { @@ -51,6 +65,9 @@ void EmuWindow_Android::OnTouchReleased(int id) { } void EmuWindow_Android::OnFrameDisplayed() { + UpdateObservedFrameRate(); + UpdateFrameRateHint(); + if (!m_first_frame) { Common::Android::RunJNIOnFiber( [&](JNIEnv* env) { EmulationSession::GetInstance().OnEmulationStarted(); }); @@ -58,6 +75,175 @@ void EmuWindow_Android::OnFrameDisplayed() { } } +void EmuWindow_Android::UpdateObservedFrameRate() { + const auto now = Clock::now(); + if (m_last_frame_display_time.time_since_epoch().count() != 0) { + const auto frame_time = std::chrono::duration(now - m_last_frame_display_time); + const float seconds = frame_time.count(); + if (seconds > 0.0f) { + const float instantaneous_rate = 1.0f / seconds; + if (std::isfinite(instantaneous_rate) && instantaneous_rate >= 1.0f && + instantaneous_rate <= 240.0f) { + constexpr float SmoothingFactor = 0.15f; + if (m_smoothed_present_rate <= 0.0f) { + m_smoothed_present_rate = instantaneous_rate; + } else { + m_smoothed_present_rate += + (instantaneous_rate - m_smoothed_present_rate) * SmoothingFactor; + } + } + } + } + m_last_frame_display_time = now; +} + +float EmuWindow_Android::QuantizeFrameRateHint(float frame_rate) { + if (!std::isfinite(frame_rate) || frame_rate <= 0.0f) { + return 0.0f; + } + + frame_rate = std::clamp(frame_rate, 1.0f, 240.0f); + + constexpr float Step = 0.5f; + return std::round(frame_rate / Step) * Step; +} + +float EmuWindow_Android::GetFrameTimeVerifiedHint() const { + if (!EmulationSession::GetInstance().IsRunning()) { + return 0.0f; + } + + const double frame_time_scale = + EmulationSession::GetInstance().System().GetPerfStats().GetLastFrameTimeScale(); + if (!std::isfinite(frame_time_scale) || frame_time_scale <= 0.0) { + return 0.0f; + } + + const float verified_rate = + std::clamp(60.0f / static_cast(frame_time_scale), 0.0f, 240.0f); + return QuantizeFrameRateHint(verified_rate); +} + +float EmuWindow_Android::GetFrameRateHint() const { + const float observed_rate = std::clamp(m_smoothed_present_rate, 0.0f, 240.0f); + const float frame_time_verified_hint = GetFrameTimeVerifiedHint(); + + if (m_last_frame_rate_hint > 0.0f && observed_rate > 0.0f) { + const float tolerance = std::max(m_last_frame_rate_hint * 0.12f, 4.0f); + if (std::fabs(observed_rate - m_last_frame_rate_hint) <= tolerance) { + return m_last_frame_rate_hint; + } + } + + const float observed_hint = QuantizeFrameRateHint(observed_rate); + if (observed_hint > 0.0f) { + if (frame_time_verified_hint > 0.0f) { + const float tolerance = std::max(observed_hint * 0.20f, 3.0f); + if (std::fabs(observed_hint - frame_time_verified_hint) <= tolerance) { + return QuantizeFrameRateHint((observed_hint + frame_time_verified_hint) * 0.5f); + } + } + return observed_hint; + } + + if (frame_time_verified_hint > 0.0f) { + return frame_time_verified_hint; + } + + constexpr float NominalFrameRate = 60.0f; + if (!Settings::values.use_speed_limit.GetValue()) { + return NominalFrameRate; + } + + const u16 speed_limit = Settings::SpeedLimit(); + if (speed_limit == 0) { + return 0.0f; + } + + const float speed_limited_rate = + NominalFrameRate * (static_cast(std::min(speed_limit, 100)) / 100.0f); + return QuantizeFrameRateHint(speed_limited_rate); +} + +void EmuWindow_Android::UpdateFrameRateHint() { + auto* const surface = reinterpret_cast(window_info.render_surface); + if (!surface) { + return; + } + + const auto now = Clock::now(); + const float frame_rate_hint = GetFrameRateHint(); + if (std::fabs(frame_rate_hint - m_last_frame_rate_hint) < 0.01f) { + m_pending_frame_rate_hint = frame_rate_hint; + m_pending_frame_rate_hint_votes = 0; + m_pending_frame_rate_since = {}; + return; + } + + if (frame_rate_hint == 0.0f) { + m_pending_frame_rate_hint = frame_rate_hint; + m_pending_frame_rate_hint_votes = 0; + m_pending_frame_rate_since = now; + } else if (m_last_frame_rate_hint >= 0.0f) { + if (std::fabs(frame_rate_hint - m_pending_frame_rate_hint) >= 0.01f) { + m_pending_frame_rate_hint = frame_rate_hint; + m_pending_frame_rate_hint_votes = 1; + m_pending_frame_rate_since = now; + return; + } + + ++m_pending_frame_rate_hint_votes; + if (m_pending_frame_rate_since.time_since_epoch().count() == 0) { + m_pending_frame_rate_since = now; + } + + const auto stable_for = now - m_pending_frame_rate_since; + const float reference_rate = std::max(frame_rate_hint, 1.0f); + const auto stable_duration = std::chrono::duration_cast( + std::chrono::duration(std::clamp(3.0f / reference_rate, 0.15f, 0.40f))); + constexpr std::uint32_t MinStableVotes = 3; + + if (m_pending_frame_rate_hint_votes < MinStableVotes || stable_for < stable_duration) { + return; + } + } else { + m_pending_frame_rate_since = now; + } + + using SetFrameRateWithChangeStrategyFn = + int32_t (*)(ANativeWindow*, float, int8_t, int8_t); + using SetFrameRateFn = int32_t (*)(ANativeWindow*, float, int8_t); + static const auto set_frame_rate_with_change_strategy = + reinterpret_cast( + dlsym(RTLD_DEFAULT, "ANativeWindow_setFrameRateWithChangeStrategy")); + static const auto set_frame_rate = reinterpret_cast( + dlsym(RTLD_DEFAULT, "ANativeWindow_setFrameRate")); + + constexpr int8_t FrameRateCompatibilityDefault = 0; + constexpr int8_t ChangeFrameRateOnlyIfSeamless = 0; + + int32_t result = -1; + if (set_frame_rate_with_change_strategy) { + result = set_frame_rate_with_change_strategy(surface, frame_rate_hint, + FrameRateCompatibilityDefault, + ChangeFrameRateOnlyIfSeamless); + } else if (set_frame_rate) { + result = set_frame_rate(surface, frame_rate_hint, FrameRateCompatibilityDefault); + } else { + return; + } + + if (result != 0) { + LOG_DEBUG(Frontend, "Failed to update Android surface frame rate hint: {}", result); + return; + } + + m_last_frame_rate_hint = frame_rate_hint; + m_pending_frame_rate_hint = frame_rate_hint; + m_pending_frame_rate_hint_votes = 0; + m_pending_frame_rate_since = {}; +} + EmuWindow_Android::EmuWindow_Android(ANativeWindow* surface, std::shared_ptr driver_library) : m_driver_library{driver_library} { diff --git a/src/android/app/src/main/jni/emu_window/emu_window.h b/src/android/app/src/main/jni/emu_window/emu_window.h index d7b5fc6dac..b73e8b9b4d 100644 --- a/src/android/app/src/main/jni/emu_window/emu_window.h +++ b/src/android/app/src/main/jni/emu_window/emu_window.h @@ -1,8 +1,13 @@ +// SPDX-FileCopyrightText: Copyright 2026 Eden Emulator Project +// SPDX-License-Identifier: GPL-3.0-or-later + // SPDX-FileCopyrightText: 2023 yuzu Emulator Project // SPDX-License-Identifier: GPL-3.0-or-later #pragma once +#include +#include #include #include @@ -50,10 +55,24 @@ public: }; private: + using Clock = std::chrono::steady_clock; + + void UpdateFrameRateHint(); + void UpdateObservedFrameRate(); + [[nodiscard]] float GetFrameRateHint() const; + [[nodiscard]] float GetFrameTimeVerifiedHint() const; + [[nodiscard]] static float QuantizeFrameRateHint(float frame_rate); + float m_window_width{}; float m_window_height{}; std::shared_ptr m_driver_library; bool m_first_frame = false; + float m_last_frame_rate_hint = -1.0f; + float m_pending_frame_rate_hint = -1.0f; + float m_smoothed_present_rate = 0.0f; + Clock::time_point m_last_frame_display_time{}; + Clock::time_point m_pending_frame_rate_since{}; + std::uint32_t m_pending_frame_rate_hint_votes = 0; }; diff --git a/src/android/app/src/main/res/layout/fragment_profile_manager.xml b/src/android/app/src/main/res/layout/fragment_profile_manager.xml index e70a3f3da5..67828ca69e 100644 --- a/src/android/app/src/main/res/layout/fragment_profile_manager.xml +++ b/src/android/app/src/main/res/layout/fragment_profile_manager.xml @@ -5,21 +5,22 @@ xmlns:tools="http://schemas.android.com/tools" android:layout_width="match_parent" android:layout_height="match_parent" - android:background="?attr/colorSurface" - android:fitsSystemWindows="true"> + android:background="?attr/colorSurface"> + android:fitsSystemWindows="true" + android:touchscreenBlocksFocus="false"> 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 2a3d430716..577b88396b 100644 --- a/src/android/app/src/main/res/values-ar/strings.xml +++ b/src/android/app/src/main/res/values-ar/strings.xml @@ -473,8 +473,6 @@ يتحكم في وضع محاكاة وحدة معالجة الرسومات. تعمل معظم الألعاب بشكل جيد مع وضعي سريع أو متوازن، لكن الوضع الدقيق لا يزال مطلوبًا لبعض الألعاب. تميل الجسيمات إلى العرض بشكل صحيح فقط عند استخدام الوضع الدقيق. دقة DMA يتحكم في دقة DMA. يمكن أن تؤدي الدقة الآمنة إلى حل المشكلات في بعض الألعاب، ولكنها قد تؤثر أيضًا على الأداء في بعض الحالات. إذا لم تكن متأكدًا، فاترك هذا الخيار على الإعداد الافتراضي. - وضع توقيت الإطارات - يتحكم في كيفية إدارة المحاكي لسرعة الإطارات لتقليل التقطع وجعل معدل الإطارات أكثر سلاسة واتساقًا. تصفية متباينة الخواص يحسن جودة الأنسجة عند عرضها بزوايا مائلة وضع استخدام ذاكرة VRAM @@ -999,13 +997,6 @@ غير آمن آمن - - تلقائي - 30 إطارًا في الثانية - 60 إطارًا في الثانية - 90 إطارًا في الثانية - 120 إطارًا في الثانية - غير مضغوط 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 979f1dd707..f42e743173 100644 --- a/src/android/app/src/main/res/values-cs/strings.xml +++ b/src/android/app/src/main/res/values-cs/strings.xml @@ -452,8 +452,6 @@ Určuje režim emulovaného GPU. Většina her běží bez problémů v rychlém, nebo vyváženém režimu, ale některé stále vyžadují přesný režim. Částicové efekty se většinou zobrazují korektně pouze v přesném režimu. Přesnost DMA Ovládá přesnost DMA. Bezpečná přesnost může vyřešit problémy v některých hrách, ale v některých případech může také ovlivnit výkon. Pokud si nejste jisti, použijte výchozí nastavení. - Režim Framepacingu - Řídí způsob jakým emulátor spravuje časování snímku aby snížil trhání a zlepšení plynulost a stabilitu snímkové frekvence. Anizotropní filtrování Zlepšuje kvalitu textur při pohledu pod úhlem Režim využití VRAM 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 0b3955ac4b..f9d921745e 100644 --- a/src/android/app/src/main/res/values-es/strings.xml +++ b/src/android/app/src/main/res/values-es/strings.xml @@ -467,8 +467,6 @@ Controla el modo de la emulación de la GPU. La mayoría de los juegos se renderizan correctamente en los modos Rápido o Equilibrado, pero algunos requieren Preciso. Las partículas tienden a renderizarse correctamente solo con el modo Preciso. Precisión de DMA Controla la precisión de DMA. La precisión segura puede solucionar problemas en algunos juegos, pero también puede afectar al rendimiento en algunos casos. Si no está seguro, déjelo en Predeterminado. - Modo de ritmo de fotogramas - Controla cómo el emulador gestiona el ritmo de los fotogramas para reducir los tirones y hacer que la velocidad de los fotogramas sea más suave y consistente. Filtrado anisotrópico Mejora la calidad de las texturas al ser observadas desde ángulos oblicuos Modo de uso de VRAM @@ -993,13 +991,6 @@ Inseguro Seguro - - Automático - 30 FPS - 60 FPS - 90 FPS - 120 FPS - Sin compresión 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 2a6c559cf2..718b2da696 100644 --- a/src/android/app/src/main/res/values-ru/strings.xml +++ b/src/android/app/src/main/res/values-ru/strings.xml @@ -468,8 +468,6 @@ Управляет режимом эмуляции графического процессора. Большинство игр нормально отображаются в режимах «Быстрый» или «Сбалансированный», но для некоторых требуется режим «Точный». Частицы обычно корректно отображаются только в режиме «Точный». Точность DMA Управляет точностью DMA. Безопасная точность может исправить проблемы в некоторых играх, но в некоторых случаях также может повлиять на производительность. Если не уверены, оставьте значение По умолчанию. - Режим синхронизации кадров - Управляет синхронизацией кадров в эмуляторе для уменьшения рывков и обеспечения более плавной и стабильной частоты кадров. Анизотропная фильтрация Улучшает качество текстур под углом Режим VRAM @@ -994,13 +992,6 @@ Небезопасно Безопасный - - Авто - 30 FPS - 60 FPS - 90 FPS - 120 FPS - Без сжатия 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 1f78a85773..5f1dbd8e28 100644 --- a/src/android/app/src/main/res/values-uk/strings.xml +++ b/src/android/app/src/main/res/values-uk/strings.xml @@ -469,8 +469,6 @@ Керує режимом емуляції ГП. Більшість ігор добре візуалізуються з режимами «Швидко» або «Збалансовано», але деякі ігри можуть потребувати режиму «Точно». Частинки зазвичай правильно візуалізуються лише з режимом «Точно». Точність DMA Керує точністю DMA. Безпечна точність може виправити проблеми в деяких іграх, але в деяких випадках також може вплинути на продуктивність. Якщо не впевнені, залиште це значення за замовчуванням. - Режим виведення кадрів - Керує тим, як емулятор виконує виведення кадрів, щоб зменшити затримки й забезпечити плавнішу й стабільнішу частоту кадрів. Анізотропне фільтрування Покращує якість текстур під кутом. Режим використання VRAM @@ -995,13 +993,6 @@ Небезпечно Безпечно - - Автоматично - 30 к/с - 60 к/с - 90 к/с - 120 к/с - Без стиснення 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 bb5fe53596..beda261a2e 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 @@ -462,8 +462,6 @@ 控制 GPU 模拟的精确度。大部分游戏在性能或平衡模式下可以正常渲染,但部分游戏需要设置为精确。粒子效果通常只有在精确模式下才能正确显示。 DMA 精度 控制 DMA 精度。安全精度可以修复某些游戏中的问题,但在某些情况下也可能影响性能。如果不确定,请保留为“默认”。 - 帧同步模式 - 控制模拟器如何管理帧同步,以减少卡顿,使帧率表现更加平稳顺滑。 各向异性过滤 提高斜角的纹理质量 显存使用模式 @@ -988,13 +986,6 @@ 不安全 安全 - - 自动 - 30 FPS - 60 FPS - 90 FPS - 120 FPS - 不压缩 diff --git a/src/android/app/src/main/res/values/arrays.xml b/src/android/app/src/main/res/values/arrays.xml index 565decb390..9f787ab00c 100644 --- a/src/android/app/src/main/res/values/arrays.xml +++ b/src/android/app/src/main/res/values/arrays.xml @@ -533,20 +533,6 @@ 2 - - @string/frame_pacing_mode_target_Auto - @string/frame_pacing_mode_target_30 - @string/frame_pacing_mode_target_60 - @string/frame_pacing_mode_target_90 - @string/frame_pacing_mode_target_120 - - - 0 - 1 - 2 - 3 - 4 - @string/applet_hle diff --git a/src/android/app/src/main/res/values/strings.xml b/src/android/app/src/main/res/values/strings.xml index e9bd0f1d1c..74c5bcd276 100644 --- a/src/android/app/src/main/res/values/strings.xml +++ b/src/android/app/src/main/res/values/strings.xml @@ -479,8 +479,6 @@ Controls the GPU emulation mode. Most games render fine with Fast or Balanced modes, but Accurate is still required for some. Particles tend to only render correctly with Accurate mode. DMA Accuracy Controls the DMA precision accuracy. Safe precision can fix issues in some games, but it can also impact performance in some cases. If unsure, leave this on Default. - Frame Pacing Mode - Controls how the emulator manages frame pacing to reduce stuttering and make the frame rate smoother and more consistent. Anisotropic filtering Improves the quality of textures when viewed at oblique angles VRAM Usage Mode @@ -1038,13 +1036,6 @@ Unsafe Safe - - Auto - 30 FPS - 60 FPS - 90 FPS - 120 FPS - CPU GPU @@ -1160,6 +1151,8 @@ Material You App Settings Theme And Color + Fullscreen mode + Hide Android system bars across app screens. Swipe from an edge to reveal them temporarily. Change theme mode diff --git a/src/audio_core/CMakeLists.txt b/src/audio_core/CMakeLists.txt index 4f8cc7d1ca..e31fd2c5b9 100644 --- a/src/audio_core/CMakeLists.txt +++ b/src/audio_core/CMakeLists.txt @@ -222,10 +222,8 @@ if (MSVC) ) else() target_compile_options(audio_core PRIVATE - -Werror=conversion - - -Wno-sign-conversion - ) + $<$:-Werror=conversion> + $<$:-Wno-sign-conversion>) endif() target_include_directories(audio_core PRIVATE ${OPUS_INCLUDE_DIRS}) diff --git a/src/common/CMakeLists.txt b/src/common/CMakeLists.txt index fc3d9b59d8..1ee4794272 100644 --- a/src/common/CMakeLists.txt +++ b/src/common/CMakeLists.txt @@ -225,8 +225,9 @@ else() endif() if(CXX_CLANG) - target_compile_options(common PRIVATE -fsized-deallocation - -Werror=unreachable-code-aggressive) + target_compile_options(common PRIVATE + $<$:-fsized-deallocation> + $<$:-Werror=unreachable-code-aggressive>) target_compile_definitions( common PRIVATE diff --git a/src/common/host_memory.cpp b/src/common/host_memory.cpp index d4b1709377..04f3a65778 100644 --- a/src/common/host_memory.cpp +++ b/src/common/host_memory.cpp @@ -30,6 +30,8 @@ #include #include #include +#elif defined(__FreeBSD__) +#include #endif // FreeBSD @@ -503,8 +505,7 @@ public: fd = shm_open_anon(O_RDWR | O_CREAT | O_EXCL | O_NOFOLLOW, 0600); #elif defined(__OpenBSD__) fd = shm_open_anon(O_RDWR | O_CREAT | O_EXCL | O_NOFOLLOW, 0600); -#elif defined(__FreeBSD__) && __FreeBSD__ < 13 - // XXX Drop after FreeBSD 12.* reaches EOL on 2024-06-30 +#elif defined(__FreeBSD__) fd = shm_open(SHM_ANON, O_RDWR, 0600); #elif defined(__APPLE__) // macOS doesn't have memfd_create, use anonymous temporary file @@ -571,9 +572,9 @@ public: if (True(perms & MemoryPermission::Execute)) prot_flags |= PROT_EXEC; #endif - int flags = (fd > 0 ? MAP_SHARED : MAP_PRIVATE) | MAP_FIXED; + int flags = (fd >= 0 ? MAP_SHARED : MAP_PRIVATE) | MAP_FIXED; void* ret = mmap(virtual_base + virtual_offset, length, prot_flags, flags, fd, host_offset); - ASSERT_MSG(ret != MAP_FAILED, "mmap: {}", strerror(errno)); + ASSERT_MSG(ret != MAP_FAILED, "mmap: {} {}", strerror(errno), fd); } void Unmap(size_t virtual_offset, size_t length) { @@ -587,9 +588,8 @@ public: auto [merged_pointer, merged_size] = free_manager.FreeBlock(virtual_base + virtual_offset, length); - void* ret = mmap(merged_pointer, merged_size, PROT_NONE, - MAP_PRIVATE | MAP_ANONYMOUS | MAP_FIXED, -1, 0); - ASSERT_MSG(ret != MAP_FAILED, "mmap failed: {}", strerror(errno)); + void* ret = mmap(merged_pointer, merged_size, PROT_NONE, MAP_PRIVATE | MAP_ANONYMOUS | MAP_FIXED, -1, 0); + ASSERT_MSG(ret != MAP_FAILED, "mmap: {}", strerror(errno)); } void Protect(size_t virtual_offset, size_t length, bool read, bool write, bool execute) { diff --git a/src/common/settings.cpp b/src/common/settings.cpp index f549169cd2..54848c4dd1 100644 --- a/src/common/settings.cpp +++ b/src/common/settings.cpp @@ -186,7 +186,7 @@ bool IsFastmemEnabled() { // Only 4kb systems support host MMU right now // TODO: Support this return getpagesize() == 4096; -#elif !defined(__APPLE__) && !defined(__ANDROID__) && !defined(_WIN32) && !defined(__linux__) +#elif !defined(__APPLE__) && !defined(__ANDROID__) && !defined(_WIN32) && !defined(__linux__) && !defined(__FreeBSD__) return false; #else return true; diff --git a/src/core/CMakeLists.txt b/src/core/CMakeLists.txt index 7566372b51..08a2d0e2db 100644 --- a/src/core/CMakeLists.txt +++ b/src/core/CMakeLists.txt @@ -1195,13 +1195,13 @@ if (MSVC) ) else() target_compile_options(core PRIVATE - -Werror=conversion - -Wno-sign-conversion - -Wno-cast-function-type + $<$:-Werror=conversion> + $<$:-Wno-sign-conversion> + $<$:-Wno-cast-function-type> $<$:-fsized-deallocation>) # pre-clang19 will spam with "OH DID YOU MEAN THIS?" otherwise... if (CXX_CLANG AND CMAKE_CXX_COMPILER_VERSION VERSION_GREATER_EQUAL 19) - target_compile_options(core PRIVATE -Wno-cast-function-type-mismatch) + target_compile_options(core PRIVATE $<$:-Wno-cast-function-type-mismatch>) endif() endif() diff --git a/src/core/arm/dynarmic/arm_dynarmic_32.cpp b/src/core/arm/dynarmic/arm_dynarmic_32.cpp index 912a15475b..1520f128cf 100644 --- a/src/core/arm/dynarmic/arm_dynarmic_32.cpp +++ b/src/core/arm/dynarmic/arm_dynarmic_32.cpp @@ -186,7 +186,7 @@ void ArmDynarmic32::MakeJit(Common::PageTable* page_table) { config.only_detect_misalignment_via_page_table_on_page_boundary = true; config.fastmem_pointer = page_table->fastmem_arena ? - std::optional{reinterpret_cast(page_table->fastmem_arena)} : + std::optional{uintptr_t(page_table->fastmem_arena)} : std::nullopt; config.fastmem_exclusive_access = config.fastmem_pointer != std::nullopt; @@ -286,10 +286,6 @@ void ArmDynarmic32::MakeJit(Common::PageTable* page_table) { // Curated optimizations case Settings::CpuAccuracy::Auto: config.unsafe_optimizations = true; -#if defined(__FreeBSD__) || defined(__OpenBSD__) || defined(__sun__) || defined(__HAIKU__) || defined(__DragonFly__) || defined(__NetBSD__) - 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; @@ -304,6 +300,10 @@ void ArmDynarmic32::MakeJit(Common::PageTable* page_table) { default: break; } + if (!Settings::IsFastmemEnabled()) { + config.fastmem_pointer = std::nullopt; + config.fastmem_exclusive_access = false; + } m_jit.emplace(config); } diff --git a/src/core/arm/dynarmic/arm_dynarmic_64.cpp b/src/core/arm/dynarmic/arm_dynarmic_64.cpp index 55584d0e38..7e4bf456d2 100644 --- a/src/core/arm/dynarmic/arm_dynarmic_64.cpp +++ b/src/core/arm/dynarmic/arm_dynarmic_64.cpp @@ -226,7 +226,7 @@ void ArmDynarmic64::MakeJit(Common::PageTable* page_table, std::size_t address_s config.only_detect_misalignment_via_page_table_on_page_boundary = true; config.fastmem_pointer = page_table->fastmem_arena ? - std::optional{reinterpret_cast(page_table->fastmem_arena)} : + std::optional{uintptr_t(page_table->fastmem_arena)} : std::nullopt; config.fastmem_address_space_bits = std::uint32_t(address_space_bits); config.silently_mirror_fastmem = false; @@ -338,10 +338,6 @@ void ArmDynarmic64::MakeJit(Common::PageTable* page_table, std::size_t address_s // Safe optimisations case Settings::CpuAccuracy::Auto: config.unsafe_optimizations = true; -#if !defined(__APPLE__) && !defined(__linux__) && !defined(__ANDROID__) && !defined(_WIN32) - 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; @@ -355,6 +351,10 @@ void ArmDynarmic64::MakeJit(Common::PageTable* page_table, std::size_t address_s default: break; } + if (!Settings::IsFastmemEnabled()) { + config.fastmem_pointer = std::nullopt; + config.fastmem_exclusive_access = false; + } m_jit.emplace(config); } diff --git a/src/core/arm/nce/interpreter_visitor.cpp b/src/core/arm/nce/interpreter_visitor.cpp index be6fee8613..077a696cc8 100644 --- a/src/core/arm/nce/interpreter_visitor.cpp +++ b/src/core/arm/nce/interpreter_visitor.cpp @@ -773,7 +773,11 @@ std::optional MatchAndExecuteOneInstruction(Core::Memory::Memory& memory, m bool was_executed = false; auto decoder = Dynarmic::A64::Decode(instruction); - was_executed = decoder.get().call(visitor, instruction); + if (decoder) { + was_executed = decoder->get().call(visitor, instruction); + } else { + was_executed = false; + } return was_executed ? std::optional(pc + 4) : std::nullopt; } diff --git a/src/core/hle/service/acc/acc.cpp b/src/core/hle/service/acc/acc.cpp index d8767f9fed..43c569851d 100644 --- a/src/core/hle/service/acc/acc.cpp +++ b/src/core/hle/service/acc/acc.cpp @@ -712,9 +712,8 @@ public: private: void CheckAvailability(HLERequestContext& ctx) { LOG_DEBUG(Service_ACC, "(STUBBED) called"); - IPC::ResponseBuilder rb{ctx, 3}; + IPC::ResponseBuilder rb{ctx, 2}; rb.Push(ResultSuccess); - rb.Push(false); // TODO: Check when this is supposed to return true and when not } void GetAccountId(HLERequestContext& ctx) { diff --git a/src/core/hle/service/jit/jit_context.cpp b/src/core/hle/service/jit/jit_context.cpp index 522d849e6f..447d36a0d0 100644 --- a/src/core/hle/service/jit/jit_context.cpp +++ b/src/core/hle/service/jit/jit_context.cpp @@ -48,6 +48,8 @@ public: mapped_ranges{mapped_ranges_}, parent{parent_} {} std::optional MemoryReadCode(VAddr vaddr) override { + if (!memory.IsValidVirtualAddressRange(vaddr, sizeof(u32))) + return std::nullopt; static_assert(Core::Memory::YUZU_PAGESIZE == Dynarmic::CODE_PAGE_SIZE); auto const aligned_vaddr = vaddr & ~Core::Memory::YUZU_PAGEMASK; if (last_code_addr != aligned_vaddr) { diff --git a/src/core/hle/service/nifm/nifm.cpp b/src/core/hle/service/nifm/nifm.cpp index 710a95a455..a0302a5841 100644 --- a/src/core/hle/service/nifm/nifm.cpp +++ b/src/core/hle/service/nifm/nifm.cpp @@ -183,8 +183,8 @@ struct NifmWirelessSettingData { static_assert(sizeof(NifmWirelessSettingData) == 0x70, "NifmWirelessSettingData has incorrect size."); -#pragma pack(push, 1) // This is nn::nifm::detail::sf::NetworkProfileData +#pragma pack(push, 1) struct SfNetworkProfileData { IpSettingData ip_setting_data{}; u128 uuid{}; @@ -196,9 +196,11 @@ struct SfNetworkProfileData { SfWirelessSettingData wireless_setting_data{}; INSERT_PADDING_BYTES(1); }; +#pragma pack(pop) static_assert(sizeof(SfNetworkProfileData) == 0x17C, "SfNetworkProfileData has incorrect size."); // This is nn::nifm::NetworkProfileData +#pragma pack(push, 1) struct NifmNetworkProfileData { u128 uuid{}; std::array network_name{}; @@ -210,8 +212,8 @@ struct NifmNetworkProfileData { NifmWirelessSettingData wireless_setting_data{}; IpSettingData ip_setting_data{}; }; -static_assert(sizeof(NifmNetworkProfileData) == 0x18E, - "NifmNetworkProfileData has incorrect size."); +#pragma pack(pop) +static_assert(sizeof(NifmNetworkProfileData) == 0x18E, "NifmNetworkProfileData has incorrect size."); struct PendingProfile { std::array ssid{}; diff --git a/src/core/hle/service/sockets/sfdnsres.cpp b/src/core/hle/service/sockets/sfdnsres.cpp index 68d73f0a59..f9f0ee56eb 100644 --- a/src/core/hle/service/sockets/sfdnsres.cpp +++ b/src/core/hle/service/sockets/sfdnsres.cpp @@ -1,4 +1,4 @@ -// SPDX-FileCopyrightText: Copyright 2025 Eden Emulator Project +// SPDX-FileCopyrightText: Copyright 2026 Eden Emulator Project // SPDX-License-Identifier: GPL-3.0-or-later // SPDX-FileCopyrightText: Copyright 2018 yuzu Emulator Project @@ -53,12 +53,15 @@ enum class NetDbError : s32 { NoData = 4, }; -static const constexpr std::array blockedDomains = {"srv.nintendo.net", - "battle.net", - "microsoft.com", - "mojang.com", - "xboxlive.com", - "minecraftservices.com"}; +static const constexpr std::array blockedDomains = { + "srv.nintendo.net", //obvious + "phoenix-api.wbagora.com", //hogwarts legacy + "battle.net", + "microsoft.com", //minecraft dungeons + other games + "mojang.com", + "xboxlive.com", + "minecraftservices.com" +}; static bool IsBlockedHost(const std::string& host) { return std::any_of( diff --git a/src/core/hle/service/vi/shared_buffer_manager.cpp b/src/core/hle/service/vi/shared_buffer_manager.cpp index 1568344830..21e42e2094 100644 --- a/src/core/hle/service/vi/shared_buffer_manager.cpp +++ b/src/core/hle/service/vi/shared_buffer_manager.cpp @@ -1,4 +1,4 @@ -// SPDX-FileCopyrightText: Copyright 2025 Eden Emulator Project +// SPDX-FileCopyrightText: Copyright 2026 Eden Emulator Project // SPDX-License-Identifier: GPL-3.0-or-later // SPDX-FileCopyrightText: Copyright 2023 yuzu Emulator Project @@ -373,6 +373,8 @@ Result SharedBufferManager::PresentSharedFrameBuffer(android::Fence fence, android::Status::NoError, VI::ResultOperationFailed); + (void)m_container.SetLayerZIndex(layer_id, 100000); + // We succeeded. R_SUCCEED(); } diff --git a/src/core/tools/renderdoc.h b/src/core/tools/renderdoc.h index 0e5e43da5b..689b0a383a 100644 --- a/src/core/tools/renderdoc.h +++ b/src/core/tools/renderdoc.h @@ -1,9 +1,12 @@ +// SPDX-FileCopyrightText: Copyright 2026 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 -struct RENDERDOC_API_1_6_0; +struct RENDERDOC_API_1_7_0; namespace Tools { @@ -15,7 +18,7 @@ public: void ToggleCapture(); private: - RENDERDOC_API_1_6_0* rdoc_api{}; + RENDERDOC_API_1_7_0* rdoc_api{}; bool is_capturing{false}; }; diff --git a/src/dynarmic/CMakeLists.txt b/src/dynarmic/CMakeLists.txt index e0d1f942f0..dd1def5273 100644 --- a/src/dynarmic/CMakeLists.txt +++ b/src/dynarmic/CMakeLists.txt @@ -78,7 +78,9 @@ if (MSVC) /Zc:throwingNew # Assumes new (without std::nothrow) never returns null. /volatile:iso # Use strict standard-abiding volatile semantics /bigobj # Increase number of sections in .obj files - /DNOMINMAX) + /DNOMINMAX + /GR- + ) if (CXX_CLANG) list(APPEND DYNARMIC_CXX_FLAGS @@ -91,8 +93,10 @@ else() -Wextra -Wcast-qual -pedantic - -Wno-missing-braces) - + -Wno-missing-braces + -fno-rtti + #-fno-exceptions + ) if (CXX_GCC) # GCC produces bogus -Warray-bounds warnings from xbyak headers for code paths that are not # actually reachable. Specifically, it happens in cases where some code casts an Operand& @@ -102,7 +106,6 @@ else() list(APPEND DYNARMIC_CXX_FLAGS -Wno-array-bounds) list(APPEND DYNARMIC_CXX_FLAGS -Wstack-usage=4096) endif() - if (CXX_CLANG) # Bracket depth determines maximum size of a fold expression in Clang since 9c9974c3ccb6. # And this in turns limits the size of a std::array. @@ -117,7 +120,6 @@ if (NOT Boost_FOUND) endif() find_package(fmt 8 CONFIG) -find_package(mcl 0.1.12 REQUIRED) find_package(unordered_dense REQUIRED) if ("arm64" IN_LIST ARCHITECTURE OR DYNARMIC_TESTS) diff --git a/src/dynarmic/CMakeModules/impl/TargetArchitectureSpecificSourcesWrapFile.cmake b/src/dynarmic/CMakeModules/impl/TargetArchitectureSpecificSourcesWrapFile.cmake index 82b3078a11..82c6c3bae0 100644 --- a/src/dynarmic/CMakeModules/impl/TargetArchitectureSpecificSourcesWrapFile.cmake +++ b/src/dynarmic/CMakeModules/impl/TargetArchitectureSpecificSourcesWrapFile.cmake @@ -1,3 +1,6 @@ +# SPDX-FileCopyrightText: Copyright 2026 Eden Emulator Project +# SPDX-License-Identifier: GPL-3.0-or-later + string(TOUPPER "${arch}" arch) file(READ "${input_file}" f_contents) -file(WRITE "${output_file}" "#include \n#if defined(MCL_ARCHITECTURE_${arch})\n${f_contents}\n#endif\n") +file(WRITE "${output_file}" "#if defined(ARCHITECTURE_${arch})\n${f_contents}\n#endif\n") diff --git a/src/dynarmic/src/dynarmic/CMakeLists.txt b/src/dynarmic/src/dynarmic/CMakeLists.txt index 3d2ea4d42e..f79d18c15a 100644 --- a/src/dynarmic/src/dynarmic/CMakeLists.txt +++ b/src/dynarmic/src/dynarmic/CMakeLists.txt @@ -3,6 +3,12 @@ include(TargetArchitectureSpecificSources) add_library(dynarmic STATIC + mcl/bit.hpp + mcl/function_info.hpp + mcl/integer_of_size.hpp + mcl/intrusive_list.hpp + mcl/is_instance_of_template.hpp + backend/block_range_information.cpp backend/block_range_information.h backend/exception_handler.h @@ -53,7 +59,6 @@ add_library(dynarmic STATIC common/fp/util.h common/llvm_disassemble.cpp common/llvm_disassemble.h - common/lut_from_list.h common/math_util.cpp common/math_util.h common/safe_ops.h @@ -69,6 +74,7 @@ add_library(dynarmic STATIC frontend/decoder/matcher.h frontend/imm.cpp frontend/imm.h + interface/halt_reason.h interface/exclusive_monitor.h interface/optimization_flags.h ir/acc_type.h @@ -353,7 +359,7 @@ set_target_properties(dynarmic PROPERTIES target_compile_options(dynarmic PRIVATE ${DYNARMIC_CXX_FLAGS}) target_link_libraries(dynarmic PRIVATE unordered_dense::unordered_dense) -target_link_libraries(dynarmic PUBLIC fmt::fmt merry::mcl) +target_link_libraries(dynarmic PUBLIC fmt::fmt) if (BOOST_NO_HEADERS) target_link_libraries(dynarmic PRIVATE Boost::variant Boost::icl Boost::pool) diff --git a/src/dynarmic/src/dynarmic/backend/arm64/a32_interface.cpp b/src/dynarmic/src/dynarmic/backend/arm64/a32_interface.cpp index 91adc5783b..d16a34275b 100644 --- a/src/dynarmic/src/dynarmic/backend/arm64/a32_interface.cpp +++ b/src/dynarmic/src/dynarmic/backend/arm64/a32_interface.cpp @@ -1,4 +1,4 @@ -// SPDX-FileCopyrightText: Copyright 2025 Eden Emulator Project +// SPDX-FileCopyrightText: Copyright 2026 Eden Emulator Project // SPDX-License-Identifier: GPL-3.0-or-later /* This file is part of the dynarmic project. @@ -11,7 +11,6 @@ #include #include "dynarmic/common/assert.h" -#include #include "dynarmic/common/common_types.h" #include "dynarmic/backend/arm64/a32_address_space.h" @@ -36,14 +35,9 @@ struct Jit::Impl final { PerformRequestedCacheInvalidation(static_cast(Atomic::Load(&halt_reason))); jit_interface->is_executing = true; - SCOPE_EXIT { - jit_interface->is_executing = false; - }; - HaltReason hr = core.Run(current_address_space, current_state, &halt_reason); - PerformRequestedCacheInvalidation(hr); - + jit_interface->is_executing = false; return hr; } @@ -52,14 +46,9 @@ struct Jit::Impl final { PerformRequestedCacheInvalidation(static_cast(Atomic::Load(&halt_reason))); jit_interface->is_executing = true; - SCOPE_EXIT { - jit_interface->is_executing = false; - }; - HaltReason hr = core.Step(current_address_space, current_state, &halt_reason); - PerformRequestedCacheInvalidation(hr); - + jit_interface->is_executing = false; return hr; } diff --git a/src/dynarmic/src/dynarmic/backend/arm64/a32_jitstate.cpp b/src/dynarmic/src/dynarmic/backend/arm64/a32_jitstate.cpp index 67390a311d..0ce51d0e17 100644 --- a/src/dynarmic/src/dynarmic/backend/arm64/a32_jitstate.cpp +++ b/src/dynarmic/src/dynarmic/backend/arm64/a32_jitstate.cpp @@ -1,4 +1,4 @@ -// SPDX-FileCopyrightText: Copyright 2025 Eden Emulator Project +// SPDX-FileCopyrightText: Copyright 2026 Eden Emulator Project // SPDX-License-Identifier: GPL-3.0-or-later /* This file is part of the dynarmic project. @@ -8,7 +8,7 @@ #include "dynarmic/backend/arm64/a32_jitstate.h" -#include +#include "dynarmic/mcl/bit.hpp" #include "dynarmic/common/common_types.h" namespace Dynarmic::Backend::Arm64 { diff --git a/src/dynarmic/src/dynarmic/backend/arm64/a64_interface.cpp b/src/dynarmic/src/dynarmic/backend/arm64/a64_interface.cpp index 10324394a5..b230f455c5 100644 --- a/src/dynarmic/src/dynarmic/backend/arm64/a64_interface.cpp +++ b/src/dynarmic/src/dynarmic/backend/arm64/a64_interface.cpp @@ -1,4 +1,4 @@ -// SPDX-FileCopyrightText: Copyright 2025 Eden Emulator Project +// SPDX-FileCopyrightText: Copyright 2026 Eden Emulator Project // SPDX-License-Identifier: GPL-3.0-or-later /* This file is part of the dynarmic project. @@ -11,7 +11,6 @@ #include #include "dynarmic/common/assert.h" -#include #include "dynarmic/common/common_types.h" #include "dynarmic/backend/arm64/a64_address_space.h" @@ -34,32 +33,20 @@ struct Jit::Impl final { HaltReason Run() { ASSERT(!is_executing); PerformRequestedCacheInvalidation(static_cast(Atomic::Load(&halt_reason))); - is_executing = true; - SCOPE_EXIT { - is_executing = false; - }; - HaltReason hr = core.Run(current_address_space, current_state, &halt_reason); - PerformRequestedCacheInvalidation(hr); - + is_executing = false; return hr; } HaltReason Step() { ASSERT(!is_executing); PerformRequestedCacheInvalidation(static_cast(Atomic::Load(&halt_reason))); - is_executing = true; - SCOPE_EXIT { - is_executing = false; - }; - HaltReason hr = core.Step(current_address_space, current_state, &halt_reason); - PerformRequestedCacheInvalidation(hr); - + is_executing = false; return hr; } diff --git a/src/dynarmic/src/dynarmic/backend/arm64/abi.cpp b/src/dynarmic/src/dynarmic/backend/arm64/abi.cpp index 04d8ca2eaf..acff6a89f0 100644 --- a/src/dynarmic/src/dynarmic/backend/arm64/abi.cpp +++ b/src/dynarmic/src/dynarmic/backend/arm64/abi.cpp @@ -1,4 +1,4 @@ -// SPDX-FileCopyrightText: Copyright 2025 Eden Emulator Project +// SPDX-FileCopyrightText: Copyright 2026 Eden Emulator Project // SPDX-License-Identifier: GPL-3.0-or-later /* This file is part of the dynarmic project. @@ -10,7 +10,7 @@ #include -#include +#include "dynarmic/mcl/bit.hpp" #include "dynarmic/common/common_types.h" #include diff --git a/src/dynarmic/src/dynarmic/backend/arm64/abi.h b/src/dynarmic/src/dynarmic/backend/arm64/abi.h index f2b6b1dca1..b2e29d49e0 100644 --- a/src/dynarmic/src/dynarmic/backend/arm64/abi.h +++ b/src/dynarmic/src/dynarmic/backend/arm64/abi.h @@ -1,4 +1,4 @@ -// SPDX-FileCopyrightText: Copyright 2025 Eden Emulator Project +// SPDX-FileCopyrightText: Copyright 2026 Eden Emulator Project // SPDX-License-Identifier: GPL-3.0-or-later /* This file is part of the dynarmic project. @@ -12,7 +12,6 @@ #include #include -#include #include "dynarmic/common/common_types.h" #include "dynarmic/common/assert.h" #include @@ -37,7 +36,7 @@ constexpr auto Rscratch0() { } else if constexpr (bitsize == 64) { return Xscratch0; } else { - static_assert(Common::always_false_v>); + return Xscratch0; //UNREACHABLE(); } } @@ -48,7 +47,7 @@ constexpr auto Rscratch1() { } else if constexpr (bitsize == 64) { return Xscratch1; } else { - static_assert(Common::always_false_v>); + return Xscratch1; //UNREACHABLE(); } } diff --git a/src/dynarmic/src/dynarmic/backend/arm64/devirtualize.h b/src/dynarmic/src/dynarmic/backend/arm64/devirtualize.h index 60ce823066..737a6572e3 100644 --- a/src/dynarmic/src/dynarmic/backend/arm64/devirtualize.h +++ b/src/dynarmic/src/dynarmic/backend/arm64/devirtualize.h @@ -1,4 +1,4 @@ -// SPDX-FileCopyrightText: Copyright 2025 Eden Emulator Project +// SPDX-FileCopyrightText: Copyright 2026 Eden Emulator Project // SPDX-License-Identifier: GPL-3.0-or-later /* This file is part of the dynarmic project. @@ -10,7 +10,7 @@ #include #include "dynarmic/common/common_types.h" -#include +#include "dynarmic/mcl/function_info.hpp" namespace Dynarmic::Backend::Arm64 { diff --git a/src/dynarmic/src/dynarmic/backend/arm64/emit_arm64_a32.cpp b/src/dynarmic/src/dynarmic/backend/arm64/emit_arm64_a32.cpp index a65efb3c59..213403b4ba 100644 --- a/src/dynarmic/src/dynarmic/backend/arm64/emit_arm64_a32.cpp +++ b/src/dynarmic/src/dynarmic/backend/arm64/emit_arm64_a32.cpp @@ -6,7 +6,7 @@ * SPDX-License-Identifier: 0BSD */ -#include +#include "dynarmic/mcl/bit.hpp" #include #include "dynarmic/backend/arm64/a32_jitstate.h" diff --git a/src/dynarmic/src/dynarmic/backend/arm64/emit_arm64_data_processing.cpp b/src/dynarmic/src/dynarmic/backend/arm64/emit_arm64_data_processing.cpp index ef21fd45bd..6e4ce06eb6 100644 --- a/src/dynarmic/src/dynarmic/backend/arm64/emit_arm64_data_processing.cpp +++ b/src/dynarmic/src/dynarmic/backend/arm64/emit_arm64_data_processing.cpp @@ -1,4 +1,4 @@ -// SPDX-FileCopyrightText: Copyright 2025 Eden Emulator Project +// SPDX-FileCopyrightText: Copyright 2026 Eden Emulator Project // SPDX-License-Identifier: GPL-3.0-or-later /* This file is part of the dynarmic project. @@ -642,7 +642,7 @@ void EmitIR(oaknut::CodeGenerator& code, Emi } template<> -void EmitIR(oaknut::CodeGenerator& code, EmitContext& ctx, IR::Inst* inst) { +void EmitIR(oaknut::CodeGenerator& code, EmitContext& ctx, IR::Inst* inst) { const auto carry_inst = inst->GetAssociatedPseudoOperation(IR::Opcode::GetCarryFromOp); auto args = ctx.reg_alloc.GetArgumentInfo(inst); @@ -708,7 +708,7 @@ void EmitIR(oaknut::CodeGenerator& code, EmitContext& } template<> -void EmitIR(oaknut::CodeGenerator& code, EmitContext& ctx, IR::Inst* inst) { +void EmitIR(oaknut::CodeGenerator& code, EmitContext& ctx, IR::Inst* inst) { auto args = ctx.reg_alloc.GetArgumentInfo(inst); auto& operand_arg = args[0]; auto& shift_arg = args[1]; diff --git a/src/dynarmic/src/dynarmic/backend/arm64/emit_arm64_memory.cpp b/src/dynarmic/src/dynarmic/backend/arm64/emit_arm64_memory.cpp index 67ab61f8a3..b7ea792a38 100644 --- a/src/dynarmic/src/dynarmic/backend/arm64/emit_arm64_memory.cpp +++ b/src/dynarmic/src/dynarmic/backend/arm64/emit_arm64_memory.cpp @@ -209,9 +209,9 @@ void CallbackOnlyEmitExclusiveWriteMemory(oaknut::CodeGenerator& code, EmitConte ctx.reg_alloc.DefineAsRegister(inst, X0); } -constexpr size_t page_bits = 12; -constexpr size_t page_size = 1 << page_bits; -constexpr size_t page_mask = (1 << page_bits) - 1; +constexpr size_t page_table_const_bits = 12; +constexpr size_t page_table_const_size = 1 << page_table_const_bits; +constexpr size_t page_table_const_mask = (1 << page_table_const_bits) - 1; // This function may use Xscratch0 as a scratch register // Trashes NZCV @@ -242,28 +242,28 @@ void EmitDetectMisalignedVAddr(oaknut::CodeGenerator& code, EmitContext& ctx, oa code.TST(Xaddr, align_mask); code.B(NE, *fallback); } else { - // If (addr & page_mask) > page_size - byte_size, use fallback. - code.AND(Xscratch0, Xaddr, page_mask); - code.CMP(Xscratch0, page_size - bitsize / 8); + // If (addr & page_table_const_mask) > page_table_const_size - byte_size, use fallback. + code.AND(Xscratch0, Xaddr, page_table_const_mask); + code.CMP(Xscratch0, page_table_const_size - bitsize / 8); code.B(HI, *fallback); } } -// Outputs Xscratch0 = page_table[addr >> page_bits] +// Outputs Xscratch0 = page_table[addr >> page_table_const_bits] // May use Xscratch1 as scratch register // Address to read/write = [ret0 + ret1], ret0 is always Xscratch0 and ret1 is either Xaddr or Xscratch1 // Trashes NZCV template std::pair InlinePageTableEmitVAddrLookup(oaknut::CodeGenerator& code, EmitContext& ctx, oaknut::XReg Xaddr, const SharedLabel& fallback) { - const size_t valid_page_index_bits = ctx.conf.page_table_address_space_bits - page_bits; + const size_t valid_page_index_bits = ctx.conf.page_table_address_space_bits - page_table_const_bits; const size_t unused_top_bits = 64 - ctx.conf.page_table_address_space_bits; EmitDetectMisalignedVAddr(code, ctx, Xaddr, fallback); if (ctx.conf.silently_mirror_page_table || unused_top_bits == 0) { - code.UBFX(Xscratch0, Xaddr, page_bits, valid_page_index_bits); + code.UBFX(Xscratch0, Xaddr, page_table_const_bits, valid_page_index_bits); } else { - code.LSR(Xscratch0, Xaddr, page_bits); + code.LSR(Xscratch0, Xaddr, page_table_const_bits); code.TST(Xscratch0, u64(~u64(0)) << valid_page_index_bits); code.B(NE, *fallback); } @@ -283,7 +283,7 @@ std::pair InlinePageTableEmitVAddrLookup(oaknut::Cod if (ctx.conf.absolute_offset_page_table) { return std::make_pair(Xscratch0, Xaddr); } - code.AND(Xscratch1, Xaddr, page_mask); + code.AND(Xscratch1, Xaddr, page_table_const_mask); return std::make_pair(Xscratch0, Xscratch1); } diff --git a/src/dynarmic/src/dynarmic/backend/arm64/emit_arm64_vector.cpp b/src/dynarmic/src/dynarmic/backend/arm64/emit_arm64_vector.cpp index a8c3aa02bf..c773d5a339 100644 --- a/src/dynarmic/src/dynarmic/backend/arm64/emit_arm64_vector.cpp +++ b/src/dynarmic/src/dynarmic/backend/arm64/emit_arm64_vector.cpp @@ -1,4 +1,4 @@ -// SPDX-FileCopyrightText: Copyright 2025 Eden Emulator Project +// SPDX-FileCopyrightText: Copyright 2026 Eden Emulator Project // SPDX-License-Identifier: GPL-3.0-or-later /* This file is part of the dynarmic project. @@ -6,7 +6,6 @@ * SPDX-License-Identifier: 0BSD */ -#include #include #include "dynarmic/backend/arm64/a32_jitstate.h" @@ -46,7 +45,7 @@ static void EmitTwoOpArranged(oaknut::CodeGenerator& code, EmitContext& ctx, IR: } else if constexpr (size == 64) { emit(Qresult->D2(), Qoperand->D2()); } else { - static_assert(Common::always_false_v>); + UNREACHABLE(); } }); } @@ -69,7 +68,7 @@ static void EmitTwoOpArrangedWiden(oaknut::CodeGenerator& code, EmitContext& ctx } else if constexpr (size == 32) { emit(Qresult->D2(), Qoperand->toD().S2()); } else { - static_assert(Common::always_false_v>); + UNREACHABLE(); } }); } @@ -84,7 +83,7 @@ static void EmitTwoOpArrangedNarrow(oaknut::CodeGenerator& code, EmitContext& ct } else if constexpr (size == 64) { emit(Qresult->toD().S2(), Qoperand->D2()); } else { - static_assert(Common::always_false_v>); + UNREACHABLE(); } }); } @@ -107,7 +106,7 @@ static void EmitTwoOpArrangedPairWiden(oaknut::CodeGenerator& code, EmitContext& } else if constexpr (size == 32) { emit(Qresult->D2(), Qoperand->S4()); } else { - static_assert(Common::always_false_v>); + UNREACHABLE(); } }); } @@ -122,7 +121,7 @@ static void EmitTwoOpArrangedLower(oaknut::CodeGenerator& code, EmitContext& ctx } else if constexpr (size == 32) { emit(Qresult->toD().S2(), Qoperand->toD().S2()); } else { - static_assert(Common::always_false_v>); + UNREACHABLE(); } }); } @@ -150,7 +149,7 @@ static void EmitThreeOpArranged(oaknut::CodeGenerator& code, EmitContext& ctx, I } else if constexpr (size == 64) { emit(Qresult->D2(), Qa->D2(), Qb->D2()); } else { - static_assert(Common::always_false_v>); + UNREACHABLE(); } }); } @@ -175,7 +174,7 @@ static void EmitThreeOpArrangedWiden(oaknut::CodeGenerator& code, EmitContext& c } else if constexpr (size == 64) { emit(Qresult->Q1(), Qa->toD().D1(), Qb->toD().D1()); } else { - static_assert(Common::always_false_v>); + UNREACHABLE(); } }); } @@ -198,7 +197,7 @@ static void EmitThreeOpArrangedLower(oaknut::CodeGenerator& code, EmitContext& c } else if constexpr (size == 32) { emit(Qresult->toD().S2(), Qa->toD().S2(), Qb->toD().S2()); } else { - static_assert(Common::always_false_v>); + UNREACHABLE(); } }); } @@ -220,7 +219,7 @@ static void EmitSaturatedAccumulate(oaknut::CodeGenerator&, EmitContext& ctx, IR } else if constexpr (size == 64) { emit(Qaccumulator->D2(), Qoperand->D2()); } else { - static_assert(Common::always_false_v>); + UNREACHABLE(); } } @@ -241,7 +240,7 @@ static void EmitImmShift(oaknut::CodeGenerator&, EmitContext& ctx, IR::Inst* ins } else if constexpr (size == 64) { emit(Qresult->D2(), Qoperand->D2(), shift_amount); } else { - static_assert(Common::always_false_v>); + UNREACHABLE(); } } @@ -269,7 +268,7 @@ static void EmitReduce(oaknut::CodeGenerator&, EmitContext& ctx, IR::Inst* inst, } else if constexpr (size == 64) { emit(Vresult, Qoperand->D2()); } else { - static_assert(Common::always_false_v>); + UNREACHABLE(); } } diff --git a/src/dynarmic/src/dynarmic/backend/arm64/emit_arm64_vector_floating_point.cpp b/src/dynarmic/src/dynarmic/backend/arm64/emit_arm64_vector_floating_point.cpp index 4d11c62abd..557d6284ed 100644 --- a/src/dynarmic/src/dynarmic/backend/arm64/emit_arm64_vector_floating_point.cpp +++ b/src/dynarmic/src/dynarmic/backend/arm64/emit_arm64_vector_floating_point.cpp @@ -1,4 +1,4 @@ -// SPDX-FileCopyrightText: Copyright 2025 Eden Emulator Project +// SPDX-FileCopyrightText: Copyright 2026 Eden Emulator Project // SPDX-License-Identifier: GPL-3.0-or-later /* This file is part of the dynarmic project. @@ -7,14 +7,8 @@ */ #include -#include -#include -#include -#include -#include -#include -#include -#include +#include "dynarmic/mcl/function_info.hpp" +#include "dynarmic/mcl/integer_of_size.hpp" #include #include "dynarmic/backend/arm64/a32_jitstate.h" @@ -31,7 +25,6 @@ #include "dynarmic/common/fp/info.h" #include "dynarmic/common/fp/op.h" #include "dynarmic/common/fp/rounding_mode.h" -#include "dynarmic/common/lut_from_list.h" #include "dynarmic/ir/basic_block.h" #include "dynarmic/ir/microinstruction.h" #include "dynarmic/ir/opcodes.h" @@ -39,8 +32,6 @@ namespace Dynarmic::Backend::Arm64 { using namespace oaknut::util; -namespace mp = mcl::mp; - using A64FullVectorWidth = std::integral_constant; // Array alias that always sizes itself according to the given type T @@ -84,7 +75,7 @@ static void EmitTwoOpArranged(oaknut::CodeGenerator& code, EmitContext& ctx, IR: } else if constexpr (size == 64) { emit(Qresult->D2(), Qa->D2()); } else { - static_assert(Common::always_false_v>); + UNREACHABLE(); } }); } @@ -112,7 +103,7 @@ static void EmitThreeOpArranged(oaknut::CodeGenerator& code, EmitContext& ctx, I } else if constexpr (size == 64) { emit(Qresult->D2(), Qa->D2(), Qb->D2()); } else { - static_assert(Common::always_false_v>); + UNREACHABLE(); } }); } @@ -135,7 +126,7 @@ static void EmitFMA(oaknut::CodeGenerator& code, EmitContext& ctx, IR::Inst* ins } else if constexpr (size == 64) { emit(Qresult->D2(), Qm->D2(), Qn->D2()); } else { - static_assert(Common::always_false_v>); + UNREACHABLE(); } }); } @@ -157,7 +148,7 @@ static void EmitFromFixed(oaknut::CodeGenerator& code, EmitContext& ctx, IR::Ins } else if constexpr (size == 64) { emit(Qto->D2(), Qfrom->D2(), fbits); } else { - static_assert(Common::always_false_v>); + UNREACHABLE(); } }); } @@ -179,7 +170,7 @@ void EmitToFixed(oaknut::CodeGenerator& code, EmitContext& ctx, IR::Inst* inst) } else if constexpr (fsize == 64) { return Qto->D2(); } else { - static_assert(Common::always_false_v>); + UNREACHABLE(); } }(); auto Vfrom = [&] { @@ -188,7 +179,7 @@ void EmitToFixed(oaknut::CodeGenerator& code, EmitContext& ctx, IR::Inst* inst) } else if constexpr (fsize == 64) { return Qfrom->D2(); } else { - static_assert(Common::always_false_v>); + UNREACHABLE(); } }(); diff --git a/src/dynarmic/src/dynarmic/backend/arm64/emit_arm64_vector_saturation.cpp b/src/dynarmic/src/dynarmic/backend/arm64/emit_arm64_vector_saturation.cpp index 722a09176b..d63c1d92d0 100644 --- a/src/dynarmic/src/dynarmic/backend/arm64/emit_arm64_vector_saturation.cpp +++ b/src/dynarmic/src/dynarmic/backend/arm64/emit_arm64_vector_saturation.cpp @@ -1,9 +1,11 @@ +// SPDX-FileCopyrightText: Copyright 2026 Eden Emulator Project +// SPDX-License-Identifier: GPL-3.0-or-later + /* This file is part of the dynarmic project. * Copyright (c) 2022 MerryMage * SPDX-License-Identifier: 0BSD */ -#include #include #include "dynarmic/backend/arm64/a32_jitstate.h" @@ -39,7 +41,7 @@ static void Emit(oaknut::CodeGenerator&, EmitContext& ctx, IR::Inst* inst, EmitF } else if constexpr (size == 64) { emit(Qresult->D2(), Qa->D2(), Qb->D2()); } else { - static_assert(Common::always_false_v>); + UNREACHABLE(); } } diff --git a/src/dynarmic/src/dynarmic/backend/arm64/fastmem.h b/src/dynarmic/src/dynarmic/backend/arm64/fastmem.h index cae05bcf23..8e40e81569 100644 --- a/src/dynarmic/src/dynarmic/backend/arm64/fastmem.h +++ b/src/dynarmic/src/dynarmic/backend/arm64/fastmem.h @@ -1,4 +1,4 @@ -// SPDX-FileCopyrightText: Copyright 2025 Eden Emulator Project +// SPDX-FileCopyrightText: Copyright 2026 Eden Emulator Project // SPDX-License-Identifier: GPL-3.0-or-later /* This file is part of the dynarmic project. @@ -10,11 +10,10 @@ #include #include - -#include -#include "dynarmic/common/common_types.h" #include +#include "dynarmic/mcl/bit.hpp" +#include "dynarmic/common/common_types.h" #include "dynarmic/backend/exception_handler.h" #include "dynarmic/ir/location_descriptor.h" @@ -22,9 +21,16 @@ namespace Dynarmic::Backend::Arm64 { using DoNotFastmemMarker = std::tuple; +constexpr size_t xmrx(size_t x) noexcept { + x ^= x >> 32; + x *= 0xff51afd7ed558ccd; + x ^= mcl::bit::rotate_right(x, 47) ^ mcl::bit::rotate_right(x, 23); + return x; +} + struct DoNotFastmemMarkerHash { - size_t operator()(const DoNotFastmemMarker& value) const { - return mcl::hash::xmrx(std::get<0>(value).Value() ^ static_cast(std::get<1>(value))); + [[nodiscard]] size_t operator()(const DoNotFastmemMarker& value) const noexcept { + return xmrx(std::get<0>(value).Value() ^ u64(std::get<1>(value))); } }; diff --git a/src/dynarmic/src/dynarmic/backend/arm64/reg_alloc.cpp b/src/dynarmic/src/dynarmic/backend/arm64/reg_alloc.cpp index e98a2f6e71..47d83f2362 100644 --- a/src/dynarmic/src/dynarmic/backend/arm64/reg_alloc.cpp +++ b/src/dynarmic/src/dynarmic/backend/arm64/reg_alloc.cpp @@ -13,9 +13,8 @@ #include #include "dynarmic/common/assert.h" -#include +#include "dynarmic/mcl/bit.hpp" #include -#include #include "dynarmic/common/common_types.h" #include "dynarmic/backend/arm64/abi.h" @@ -299,7 +298,7 @@ int RegAlloc::GenerateImmediate(const IR::Value& value) { return 0; } else { - static_assert(Common::always_false_v>); + UNREACHABLE(); } } @@ -366,7 +365,7 @@ int RegAlloc::RealizeReadImpl(const IR::Value& value) { } else if constexpr (required_kind == HostLoc::Kind::Flags) { UNREACHABLE(); //A simple read from flags is likely a logic error } else { - static_assert(Common::always_false_v>); + UNREACHABLE(); } } @@ -390,7 +389,7 @@ int RegAlloc::RealizeWriteImpl(const IR::Inst* value) { flags.SetupLocation(value); return 0; } else { - static_assert(Common::always_false_v>); + UNREACHABLE(); } } @@ -410,7 +409,7 @@ int RegAlloc::RealizeReadWriteImpl(const IR::Value& read_value, const IR::Inst* } else if constexpr (kind == HostLoc::Kind::Flags) { ASSERT(false && "Incorrect function for ReadWrite of flags"); } else { - static_assert(Common::always_false_v>); + UNREACHABLE(); } } diff --git a/src/dynarmic/src/dynarmic/backend/arm64/reg_alloc.h b/src/dynarmic/src/dynarmic/backend/arm64/reg_alloc.h index 87446a240b..22ab5af662 100644 --- a/src/dynarmic/src/dynarmic/backend/arm64/reg_alloc.h +++ b/src/dynarmic/src/dynarmic/backend/arm64/reg_alloc.h @@ -16,7 +16,7 @@ #include "dynarmic/common/assert.h" #include "dynarmic/common/common_types.h" -#include +#include "dynarmic/mcl/is_instance_of_template.hpp" #include #include diff --git a/src/dynarmic/src/dynarmic/backend/exception_handler.h b/src/dynarmic/src/dynarmic/backend/exception_handler.h index cd274b111f..ff116c5775 100644 --- a/src/dynarmic/src/dynarmic/backend/exception_handler.h +++ b/src/dynarmic/src/dynarmic/backend/exception_handler.h @@ -1,4 +1,4 @@ -// SPDX-FileCopyrightText: Copyright 2025 Eden Emulator Project +// SPDX-FileCopyrightText: Copyright 2026 Eden Emulator Project // SPDX-License-Identifier: GPL-3.0-or-later /* This file is part of the dynarmic project. @@ -12,7 +12,6 @@ #include #include -#include #include "dynarmic/common/common_types.h" #if defined(ARCHITECTURE_x86_64) diff --git a/src/dynarmic/src/dynarmic/backend/exception_handler_macos.cpp b/src/dynarmic/src/dynarmic/backend/exception_handler_macos.cpp index 622f86816f..be44207f0a 100644 --- a/src/dynarmic/src/dynarmic/backend/exception_handler_macos.cpp +++ b/src/dynarmic/src/dynarmic/backend/exception_handler_macos.cpp @@ -1,4 +1,4 @@ -// SPDX-FileCopyrightText: Copyright 2025 Eden Emulator Project +// SPDX-FileCopyrightText: Copyright 2026 Eden Emulator Project // SPDX-License-Identifier: GPL-3.0-or-later /* This file is part of the dynarmic project. @@ -16,11 +16,10 @@ #include #include #include +#include #include #include "dynarmic/common/assert.h" -#include -#include #include "dynarmic/common/common_types.h" #include "dynarmic/backend/exception_handler.h" diff --git a/src/dynarmic/src/dynarmic/backend/exception_handler_macos_mig.c b/src/dynarmic/src/dynarmic/backend/exception_handler_macos_mig.c index 25678ab115..ebbe5a079f 100644 --- a/src/dynarmic/src/dynarmic/backend/exception_handler_macos_mig.c +++ b/src/dynarmic/src/dynarmic/backend/exception_handler_macos_mig.c @@ -3,8 +3,6 @@ * SPDX-License-Identifier: 0BSD */ -#include - #if defined(ARCHITECTURE_x86_64) # include "dynarmic/backend/x64/mig/mach_exc_server.c" #elif defined(ARCHITECTURE_arm64) diff --git a/src/dynarmic/src/dynarmic/backend/exception_handler_windows.cpp b/src/dynarmic/src/dynarmic/backend/exception_handler_windows.cpp index 58a3325e17..8b52437930 100644 --- a/src/dynarmic/src/dynarmic/backend/exception_handler_windows.cpp +++ b/src/dynarmic/src/dynarmic/backend/exception_handler_windows.cpp @@ -1,4 +1,4 @@ -// SPDX-FileCopyrightText: Copyright 2025 Eden Emulator Project +// SPDX-FileCopyrightText: Copyright 2026 Eden Emulator Project // SPDX-License-Identifier: GPL-3.0-or-later /* This file is part of the dynarmic project. @@ -6,8 +6,6 @@ * SPDX-License-Identifier: 0BSD */ -#include - #if defined(ARCHITECTURE_x86_64) # include "dynarmic/backend/x64/exception_handler_windows.cpp" #elif defined(ARCHITECTURE_arm64) diff --git a/src/dynarmic/src/dynarmic/backend/riscv64/a32_address_space.cpp b/src/dynarmic/src/dynarmic/backend/riscv64/a32_address_space.cpp index 05f43774b6..edb24761f6 100644 --- a/src/dynarmic/src/dynarmic/backend/riscv64/a32_address_space.cpp +++ b/src/dynarmic/src/dynarmic/backend/riscv64/a32_address_space.cpp @@ -99,7 +99,7 @@ void A32AddressSpace::SetCursorPtr(CodePtr ptr) { } size_t A32AddressSpace::GetRemainingSize() { - return conf.code_cache_size - (GetCursorPtr() - GetMemPtr()); + return conf.code_cache_size - (GetCursorPtr() - GetMemPtr()); } EmittedBlockInfo A32AddressSpace::Emit(IR::Block block) { diff --git a/src/dynarmic/src/dynarmic/backend/riscv64/a32_address_space.h b/src/dynarmic/src/dynarmic/backend/riscv64/a32_address_space.h index 24148b192c..e882a9e2e6 100644 --- a/src/dynarmic/src/dynarmic/backend/riscv64/a32_address_space.h +++ b/src/dynarmic/src/dynarmic/backend/riscv64/a32_address_space.h @@ -41,25 +41,25 @@ private: template T GetMemPtr() { - static_assert(std::is_pointer_v || std::is_same_v || std::is_same_v); + static_assert(std::is_pointer_v || std::is_same_v || std::is_same_v); return reinterpret_cast(as.GetBufferPointer(0)); } template T GetMemPtr() const { - static_assert(std::is_pointer_v || std::is_same_v || std::is_same_v); + static_assert(std::is_pointer_v || std::is_same_v || std::is_same_v); return reinterpret_cast(as.GetBufferPointer(0)); } template T GetCursorPtr() { - static_assert(std::is_pointer_v || std::is_same_v || std::is_same_v); + static_assert(std::is_pointer_v || std::is_same_v || std::is_same_v); return reinterpret_cast(as.GetCursorPointer()); } template T GetCursorPtr() const { - static_assert(std::is_pointer_v || std::is_same_v || std::is_same_v); + static_assert(std::is_pointer_v || std::is_same_v || std::is_same_v); return reinterpret_cast(as.GetCursorPointer()); } diff --git a/src/dynarmic/src/dynarmic/backend/riscv64/a32_interface.cpp b/src/dynarmic/src/dynarmic/backend/riscv64/a32_interface.cpp index c0f65a49ed..3f395bfafb 100644 --- a/src/dynarmic/src/dynarmic/backend/riscv64/a32_interface.cpp +++ b/src/dynarmic/src/dynarmic/backend/riscv64/a32_interface.cpp @@ -1,4 +1,4 @@ -// SPDX-FileCopyrightText: Copyright 2025 Eden Emulator Project +// SPDX-FileCopyrightText: Copyright 2026 Eden Emulator Project // SPDX-License-Identifier: GPL-3.0-or-later /* This file is part of the dynarmic project. @@ -11,7 +11,6 @@ #include #include "dynarmic/common/assert.h" -#include #include "dynarmic/common/common_types.h" #include "dynarmic/backend/riscv64/a32_address_space.h" @@ -34,28 +33,18 @@ struct Jit::Impl final { HaltReason Run() { ASSERT(!jit_interface->is_executing); jit_interface->is_executing = true; - SCOPE_EXIT { - jit_interface->is_executing = false; - }; - HaltReason hr = core.Run(current_address_space, current_state, &halt_reason); - RequestCacheInvalidation(); - + jit_interface->is_executing = false; return hr; } HaltReason Step() { ASSERT(!jit_interface->is_executing); jit_interface->is_executing = true; - SCOPE_EXIT { - jit_interface->is_executing = false; - }; - UNIMPLEMENTED(); - RequestCacheInvalidation(); - + jit_interface->is_executing = false; return HaltReason{}; } diff --git a/src/dynarmic/src/dynarmic/backend/riscv64/a32_jitstate.cpp b/src/dynarmic/src/dynarmic/backend/riscv64/a32_jitstate.cpp index 87eeab6b0f..70cd6bf0f1 100644 --- a/src/dynarmic/src/dynarmic/backend/riscv64/a32_jitstate.cpp +++ b/src/dynarmic/src/dynarmic/backend/riscv64/a32_jitstate.cpp @@ -1,4 +1,4 @@ -// SPDX-FileCopyrightText: Copyright 2025 Eden Emulator Project +// SPDX-FileCopyrightText: Copyright 2026 Eden Emulator Project // SPDX-License-Identifier: GPL-3.0-or-later /* This file is part of the dynarmic project. @@ -8,7 +8,7 @@ #include "dynarmic/backend/riscv64/a32_jitstate.h" -#include +#include "dynarmic/mcl/bit.hpp" #include "dynarmic/common/common_types.h" namespace Dynarmic::Backend::RV64 { diff --git a/src/dynarmic/src/dynarmic/backend/riscv64/code_block.h b/src/dynarmic/src/dynarmic/backend/riscv64/code_block.h index 7d53486a48..02bfa44eec 100644 --- a/src/dynarmic/src/dynarmic/backend/riscv64/code_block.h +++ b/src/dynarmic/src/dynarmic/backend/riscv64/code_block.h @@ -1,4 +1,4 @@ -// SPDX-FileCopyrightText: Copyright 2025 Eden Emulator Project +// SPDX-FileCopyrightText: Copyright 2026 Eden Emulator Project // SPDX-License-Identifier: GPL-3.0-or-later /* This file is part of the dynarmic project. @@ -30,7 +30,7 @@ public: template T ptr() const noexcept { - static_assert(std::is_pointer_v || std::is_same_v || std::is_same_v); + static_assert(std::is_pointer_v || std::is_same_v || std::is_same_v); return reinterpret_cast(mem); } diff --git a/src/dynarmic/src/dynarmic/backend/riscv64/emit_riscv64.cpp b/src/dynarmic/src/dynarmic/backend/riscv64/emit_riscv64.cpp index 50cbaf9526..5ce7dee1e1 100644 --- a/src/dynarmic/src/dynarmic/backend/riscv64/emit_riscv64.cpp +++ b/src/dynarmic/src/dynarmic/backend/riscv64/emit_riscv64.cpp @@ -12,7 +12,7 @@ #include #include -#include +#include "dynarmic/mcl/bit.hpp" #include "dynarmic/backend/riscv64/a32_jitstate.h" #include "dynarmic/backend/riscv64/abi.h" diff --git a/src/dynarmic/src/dynarmic/backend/riscv64/emit_riscv64_data_processing.cpp b/src/dynarmic/src/dynarmic/backend/riscv64/emit_riscv64_data_processing.cpp index 51ed027a05..114147e018 100644 --- a/src/dynarmic/src/dynarmic/backend/riscv64/emit_riscv64_data_processing.cpp +++ b/src/dynarmic/src/dynarmic/backend/riscv64/emit_riscv64_data_processing.cpp @@ -1,3 +1,6 @@ +// SPDX-FileCopyrightText: Copyright 2026 Eden Emulator Project +// SPDX-License-Identifier: GPL-3.0-or-later + /* This file is part of the dynarmic project. * Copyright (c) 2024 MerryMage * SPDX-License-Identifier: 0BSD @@ -164,12 +167,12 @@ void EmitIR(biscuit::Assembler&, EmitContext } template<> -void EmitIR(biscuit::Assembler&, EmitContext&, IR::Inst*) { +void EmitIR(biscuit::Assembler&, EmitContext&, IR::Inst*) { UNIMPLEMENTED(); } template<> -void EmitIR(biscuit::Assembler&, EmitContext&, IR::Inst*) { +void EmitIR(biscuit::Assembler&, EmitContext&, IR::Inst*) { UNIMPLEMENTED(); } diff --git a/src/dynarmic/src/dynarmic/backend/riscv64/reg_alloc.cpp b/src/dynarmic/src/dynarmic/backend/riscv64/reg_alloc.cpp index 49489c40a4..4ab5d43db8 100644 --- a/src/dynarmic/src/dynarmic/backend/riscv64/reg_alloc.cpp +++ b/src/dynarmic/src/dynarmic/backend/riscv64/reg_alloc.cpp @@ -1,4 +1,4 @@ -// SPDX-FileCopyrightText: Copyright 2025 Eden Emulator Project +// SPDX-FileCopyrightText: Copyright 2026 Eden Emulator Project // SPDX-License-Identifier: GPL-3.0-or-later /* This file is part of the dynarmic project. @@ -12,7 +12,6 @@ #include #include "dynarmic/common/assert.h" -#include #include "dynarmic/common/common_types.h" #include "dynarmic/common/always_false.h" @@ -164,9 +163,8 @@ u32 RegAlloc::GenerateImmediate(const IR::Value& value) { } else if constexpr (kind == HostLoc::Kind::Fpr) { UNIMPLEMENTED(); } else { - static_assert(Common::always_false_v>); + UNREACHABLE(); } - return 0; } @@ -225,7 +223,7 @@ u32 RegAlloc::RealizeReadImpl(const IR::Value& value) { fprs[new_location_index].realized = true; return new_location_index; } else { - static_assert(Common::always_false_v>); + UNREACHABLE(); } } @@ -252,7 +250,7 @@ u32 RegAlloc::RealizeWriteImpl(const IR::Inst* value) { setup_location(fprs[new_location_index]); return new_location_index; } else { - static_assert(Common::always_false_v>); + UNREACHABLE(); } } diff --git a/src/dynarmic/src/dynarmic/backend/riscv64/reg_alloc.h b/src/dynarmic/src/dynarmic/backend/riscv64/reg_alloc.h index e8fd471ae1..be826e63f6 100644 --- a/src/dynarmic/src/dynarmic/backend/riscv64/reg_alloc.h +++ b/src/dynarmic/src/dynarmic/backend/riscv64/reg_alloc.h @@ -1,4 +1,4 @@ -// SPDX-FileCopyrightText: Copyright 2025 Eden Emulator Project +// SPDX-FileCopyrightText: Copyright 2026 Eden Emulator Project // SPDX-License-Identifier: GPL-3.0-or-later /* This file is part of the dynarmic project. @@ -18,7 +18,7 @@ #include #include "dynarmic/common/assert.h" #include "dynarmic/common/common_types.h" -#include +#include "dynarmic/mcl/is_instance_of_template.hpp" #include #include "dynarmic/backend/riscv64/stack_layout.h" 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 f037919eb0..80f0f9cc2f 100644 --- a/src/dynarmic/src/dynarmic/backend/x64/a32_emit_x64.cpp +++ b/src/dynarmic/src/dynarmic/backend/x64/a32_emit_x64.cpp @@ -15,8 +15,7 @@ #include #include #include "dynarmic/common/assert.h" -#include -#include +#include "dynarmic/mcl/bit.hpp" #include "dynarmic/common/common_types.h" #include 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 a6b99b545f..f138b5f137 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 @@ -13,7 +13,7 @@ #include #include -#include +#include "dynarmic/mcl/integer_of_size.hpp" #include "dynarmic/backend/x64/xbyak.h" #include "dynarmic/backend/x64/a32_emit_x64.h" diff --git a/src/dynarmic/src/dynarmic/backend/x64/a32_interface.cpp b/src/dynarmic/src/dynarmic/backend/x64/a32_interface.cpp index e540839fd5..b48dcf9046 100644 --- a/src/dynarmic/src/dynarmic/backend/x64/a32_interface.cpp +++ b/src/dynarmic/src/dynarmic/backend/x64/a32_interface.cpp @@ -14,7 +14,6 @@ #include #include "dynarmic/common/assert.h" #include -#include #include "dynarmic/common/common_types.h" #include "dynarmic/common/llvm_disassemble.h" @@ -77,12 +76,7 @@ struct Jit::Impl { HaltReason Run() { ASSERT(!jit_interface->is_executing); PerformRequestedCacheInvalidation(static_cast(Atomic::Load(&jit_state.halt_reason))); - jit_interface->is_executing = true; - SCOPE_EXIT { - jit_interface->is_executing = false; - }; - const CodePtr current_codeptr = [this] { // RSB optimization const u32 new_rsb_ptr = (jit_state.rsb_ptr - 1) & A32JitState::RSBPtrMask; @@ -93,27 +87,19 @@ struct Jit::Impl { return GetCurrentBlock(); }(); - const HaltReason hr = block_of_code.RunCode(&jit_state, current_codeptr); - PerformRequestedCacheInvalidation(hr); - + jit_interface->is_executing = false; return hr; } HaltReason Step() { ASSERT(!jit_interface->is_executing); PerformRequestedCacheInvalidation(static_cast(Atomic::Load(&jit_state.halt_reason))); - jit_interface->is_executing = true; - SCOPE_EXIT { - jit_interface->is_executing = false; - }; - const HaltReason hr = block_of_code.StepCode(&jit_state, GetCurrentSingleStep()); - PerformRequestedCacheInvalidation(hr); - + jit_interface->is_executing = false; return hr; } diff --git a/src/dynarmic/src/dynarmic/backend/x64/a32_jitstate.cpp b/src/dynarmic/src/dynarmic/backend/x64/a32_jitstate.cpp index ed5a8f9454..066b931350 100644 --- a/src/dynarmic/src/dynarmic/backend/x64/a32_jitstate.cpp +++ b/src/dynarmic/src/dynarmic/backend/x64/a32_jitstate.cpp @@ -1,4 +1,4 @@ -// SPDX-FileCopyrightText: Copyright 2025 Eden Emulator Project +// SPDX-FileCopyrightText: Copyright 2026 Eden Emulator Project // SPDX-License-Identifier: GPL-3.0-or-later /* This file is part of the dynarmic project. @@ -9,7 +9,7 @@ #include "dynarmic/backend/x64/a32_jitstate.h" #include "dynarmic/common/assert.h" -#include +#include "dynarmic/mcl/bit.hpp" #include "dynarmic/common/common_types.h" #include "dynarmic/backend/x64/block_of_code.h" 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 ff82d8b05c..832cfdcce2 100644 --- a/src/dynarmic/src/dynarmic/backend/x64/a64_emit_x64.cpp +++ b/src/dynarmic/src/dynarmic/backend/x64/a64_emit_x64.cpp @@ -11,9 +11,8 @@ #include #include #include "dynarmic/common/assert.h" -#include #include "dynarmic/common/common_types.h" -#include +#include "dynarmic/mcl/integer_of_size.hpp" #include #include "dynarmic/backend/x64/a64_jitstate.h" 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 6b3d4d86a5..4b7054b4b2 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 @@ -13,7 +13,7 @@ #include #include -#include +#include "dynarmic/mcl/integer_of_size.hpp" #include "dynarmic/backend/x64/xbyak.h" #include "dynarmic/backend/x64/a64_emit_x64.h" diff --git a/src/dynarmic/src/dynarmic/backend/x64/a64_interface.cpp b/src/dynarmic/src/dynarmic/backend/x64/a64_interface.cpp index 44c63bdfc5..96440d273e 100644 --- a/src/dynarmic/src/dynarmic/backend/x64/a64_interface.cpp +++ b/src/dynarmic/src/dynarmic/backend/x64/a64_interface.cpp @@ -15,7 +15,6 @@ #include "dynarmic/common/fp/fpcr.h" #include "dynarmic/common/llvm_disassemble.h" #include -#include #include "dynarmic/backend/x64/a64_emit_x64.h" #include "dynarmic/backend/x64/a64_jitstate.h" @@ -75,14 +74,8 @@ public: HaltReason Run() { ASSERT(!is_executing); PerformRequestedCacheInvalidation(static_cast(Atomic::Load(&jit_state.halt_reason))); - is_executing = true; - SCOPE_EXIT { - this->is_executing = false; - }; - // TODO: Check code alignment - const CodePtr current_code_ptr = [this] { // RSB optimization const u32 new_rsb_ptr = (jit_state.rsb_ptr - 1) & A64JitState::RSBPtrMask; @@ -92,27 +85,19 @@ public: } return CodePtr((uintptr_t(GetCurrentBlock()) + 15) & ~uintptr_t(15)); }(); - const HaltReason hr = block_of_code.RunCode(&jit_state, current_code_ptr); - PerformRequestedCacheInvalidation(hr); - + is_executing = false; return hr; } HaltReason Step() { ASSERT(!is_executing); PerformRequestedCacheInvalidation(static_cast(Atomic::Load(&jit_state.halt_reason))); - is_executing = true; - SCOPE_EXIT { - this->is_executing = false; - }; - const HaltReason hr = block_of_code.StepCode(&jit_state, GetCurrentSingleStep()); - PerformRequestedCacheInvalidation(hr); - + is_executing = false; return hr; } diff --git a/src/dynarmic/src/dynarmic/backend/x64/a64_jitstate.cpp b/src/dynarmic/src/dynarmic/backend/x64/a64_jitstate.cpp index 9f983f3955..3f04ed63f0 100644 --- a/src/dynarmic/src/dynarmic/backend/x64/a64_jitstate.cpp +++ b/src/dynarmic/src/dynarmic/backend/x64/a64_jitstate.cpp @@ -1,3 +1,6 @@ +// SPDX-FileCopyrightText: Copyright 2026 Eden Emulator Project +// SPDX-License-Identifier: GPL-3.0-or-later + /* This file is part of the dynarmic project. * Copyright (c) 2016 MerryMage * SPDX-License-Identifier: 0BSD @@ -5,7 +8,7 @@ #include "dynarmic/backend/x64/a64_jitstate.h" -#include +#include "dynarmic/mcl/bit.hpp" #include "dynarmic/frontend/A64/a64_location_descriptor.h" 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 28c821ab59..3a161fca6b 100644 --- a/src/dynarmic/src/dynarmic/backend/x64/block_of_code.cpp +++ b/src/dynarmic/src/dynarmic/backend/x64/block_of_code.cpp @@ -25,7 +25,7 @@ #include #include "dynarmic/common/assert.h" -#include +#include "dynarmic/mcl/bit.hpp" #include "dynarmic/backend/x64/xbyak.h" #include "dynarmic/backend/x64/a32_jitstate.h" 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 5ccab7a3ed..f6c12edaaa 100644 --- a/src/dynarmic/src/dynarmic/backend/x64/block_of_code.h +++ b/src/dynarmic/src/dynarmic/backend/x64/block_of_code.h @@ -13,7 +13,7 @@ #include #include -#include +#include "dynarmic/mcl/bit.hpp" #include "dynarmic/common/common_types.h" #include "dynarmic/backend/x64/xbyak.h" #include "dynarmic/backend/x64/abi.h" diff --git a/src/dynarmic/src/dynarmic/backend/x64/constants.h b/src/dynarmic/src/dynarmic/backend/x64/constants.h index 65c5a09a53..a0ae9f3c1e 100644 --- a/src/dynarmic/src/dynarmic/backend/x64/constants.h +++ b/src/dynarmic/src/dynarmic/backend/x64/constants.h @@ -1,4 +1,4 @@ -// SPDX-FileCopyrightText: Copyright 2025 Eden Emulator Project +// SPDX-FileCopyrightText: Copyright 2026 Eden Emulator Project // SPDX-License-Identifier: GPL-3.0-or-later /* This file is part of the dynarmic project. @@ -10,7 +10,7 @@ #include -#include +#include "dynarmic/mcl/bit.hpp" #include "dynarmic/common/common_types.h" #include "dynarmic/common/fp/rounding_mode.h" diff --git a/src/dynarmic/src/dynarmic/backend/x64/devirtualize.h b/src/dynarmic/src/dynarmic/backend/x64/devirtualize.h index 6f22646157..422d21169f 100644 --- a/src/dynarmic/src/dynarmic/backend/x64/devirtualize.h +++ b/src/dynarmic/src/dynarmic/backend/x64/devirtualize.h @@ -1,4 +1,4 @@ -// SPDX-FileCopyrightText: Copyright 2025 Eden Emulator Project +// SPDX-FileCopyrightText: Copyright 2026 Eden Emulator Project // SPDX-License-Identifier: GPL-3.0-or-later /* This file is part of the dynarmic project. @@ -13,7 +13,7 @@ #include #include "dynarmic/common/common_types.h" -#include +#include "dynarmic/mcl/function_info.hpp" #include "dynarmic/backend/x64/callback.h" diff --git a/src/dynarmic/src/dynarmic/backend/x64/emit_x64.cpp b/src/dynarmic/src/dynarmic/backend/x64/emit_x64.cpp index 2b0540e4a7..4e515fef2f 100644 --- a/src/dynarmic/src/dynarmic/backend/x64/emit_x64.cpp +++ b/src/dynarmic/src/dynarmic/backend/x64/emit_x64.cpp @@ -12,8 +12,7 @@ #include "dynarmic/common/assert.h" #include -#include -#include +#include "dynarmic/mcl/bit.hpp" #include "dynarmic/common/common_types.h" #include diff --git a/src/dynarmic/src/dynarmic/backend/x64/emit_x64.h b/src/dynarmic/src/dynarmic/backend/x64/emit_x64.h index 5de5f2dc7a..301f4ffc89 100644 --- a/src/dynarmic/src/dynarmic/backend/x64/emit_x64.h +++ b/src/dynarmic/src/dynarmic/backend/x64/emit_x64.h @@ -16,7 +16,7 @@ #include #include -#include +#include "dynarmic/mcl/bit.hpp" #include #include "dynarmic/backend/x64/xbyak.h" #include 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 f2af4e5b80..38e107fb13 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 @@ -663,7 +663,7 @@ void EmitX64::EmitArithmeticShiftRight64(EmitContext& ctx, IR::Inst* inst) { } } -void EmitX64::EmitRotateRight32(EmitContext& ctx, IR::Inst* inst) { +void EmitX64::EmitBitRotateRight32(EmitContext& ctx, IR::Inst* inst) { const auto carry_inst = inst->GetAssociatedPseudoOperation(IR::Opcode::GetCarryFromOp); auto args = ctx.reg_alloc.GetArgumentInfo(inst); @@ -736,7 +736,7 @@ void EmitX64::EmitRotateRight32(EmitContext& ctx, IR::Inst* inst) { } } -void EmitX64::EmitRotateRight64(EmitContext& ctx, IR::Inst* inst) { +void EmitX64::EmitBitRotateRight64(EmitContext& ctx, IR::Inst* inst) { auto args = ctx.reg_alloc.GetArgumentInfo(inst); auto& operand_arg = args[0]; auto& shift_arg = args[1]; 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 76c103ec6f..d073991fbe 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 @@ -11,14 +11,8 @@ #include #include "dynarmic/common/assert.h" -#include -#include -#include -#include -#include -#include #include "dynarmic/common/common_types.h" -#include +#include "dynarmic/mcl/integer_of_size.hpp" #include "dynarmic/backend/x64/xbyak.h" #include "dynarmic/backend/x64/abi.h" @@ -31,7 +25,6 @@ #include "dynarmic/common/fp/info.h" #include "dynarmic/common/fp/op.h" #include "dynarmic/common/fp/rounding_mode.h" -#include "dynarmic/common/lut_from_list.h" #include "dynarmic/interface/optimization_flags.h" #include "dynarmic/ir/basic_block.h" #include "dynarmic/ir/microinstruction.h" @@ -42,7 +35,6 @@ namespace Dynarmic::Backend::X64 { using namespace Xbyak::util; -namespace mp = mcl::mp; namespace { 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 aaed8b43f2..54fc595214 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 @@ -3,7 +3,8 @@ * SPDX-License-Identifier: 0BSD */ -#include +#define CONCATENATE_TOKENS(x, y) CONCATENATE_TOKENS_IMPL(x, y) +#define CONCATENATE_TOKENS_IMPL(x, y) x##y #define AxxEmitX64 CONCATENATE_TOKENS(Axx, EmitX64) #define AxxEmitContext CONCATENATE_TOKENS(Axx, EmitContext) 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 211f620ceb..b354efcb51 100644 --- a/src/dynarmic/src/dynarmic/backend/x64/emit_x64_memory.h +++ b/src/dynarmic/src/dynarmic/backend/x64/emit_x64_memory.h @@ -6,6 +6,8 @@ * SPDX-License-Identifier: 0BSD */ +#pragma once + #include #include "dynarmic/backend/x64/xbyak.h" @@ -22,9 +24,9 @@ namespace { using namespace Xbyak::util; -constexpr size_t page_bits = 12; -constexpr size_t page_size = 1 << page_bits; -constexpr size_t page_mask = (1 << page_bits) - 1; +constexpr size_t page_table_const_bits = 12; +constexpr size_t page_table_const_size = 1 << page_table_const_bits; +constexpr size_t page_table_const_mask = (1 << page_table_const_bits) - 1; template void EmitDetectMisalignedVAddr(BlockOfCode& code, EmitContext& ctx, size_t bitsize, Xbyak::Label& abort, Xbyak::Reg64 vaddr, Xbyak::Reg64 tmp) { @@ -50,7 +52,7 @@ 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) { - const u32 page_align_mask = static_cast(page_size - 1) & ~align_mask; + const u32 page_align_mask = static_cast(page_table_const_size - 1) & ~align_mask; SharedLabel detect_boundary = GenSharedLabel(), resume = GenSharedLabel(); @@ -83,7 +85,7 @@ template<> // TODO: This code assumes vaddr has been zext from 32-bits to 64-bits. code.mov(tmp, vaddr.cvt32()); - code.shr(tmp, int(page_bits)); + code.shr(tmp, int(page_table_const_bits)); code.shl(tmp, int(ctx.conf.page_table_log2_stride)); code.mov(page, qword[r14 + tmp.cvt64()]); if (ctx.conf.page_table_pointer_mask_bits == 0) { @@ -96,13 +98,13 @@ template<> return page + vaddr; } code.mov(tmp, vaddr.cvt32()); - code.and_(tmp, static_cast(page_mask)); + code.and_(tmp, static_cast(page_table_const_mask)); return page + tmp.cvt64(); } template<> [[maybe_unused]] Xbyak::RegExp EmitVAddrLookup(BlockOfCode& code, A64EmitContext& ctx, size_t bitsize, Xbyak::Label& abort, Xbyak::Reg64 vaddr) { - const size_t valid_page_index_bits = ctx.conf.page_table_address_space_bits - page_bits; + const size_t valid_page_index_bits = ctx.conf.page_table_address_space_bits - page_table_const_bits; const size_t unused_top_bits = 64 - ctx.conf.page_table_address_space_bits; const Xbyak::Reg64 page = ctx.reg_alloc.ScratchGpr(code); @@ -112,29 +114,29 @@ template<> if (unused_top_bits == 0) { code.mov(tmp, vaddr); - code.shr(tmp, int(page_bits)); + code.shr(tmp, int(page_table_const_bits)); } else if (ctx.conf.silently_mirror_page_table) { if (valid_page_index_bits >= 32) { if (code.HasHostFeature(HostFeature::BMI2)) { const Xbyak::Reg64 bit_count = ctx.reg_alloc.ScratchGpr(code); code.mov(bit_count, unused_top_bits); code.bzhi(tmp, vaddr, bit_count); - code.shr(tmp, int(page_bits)); + code.shr(tmp, int(page_table_const_bits)); ctx.reg_alloc.Release(bit_count); } else { code.mov(tmp, vaddr); code.shl(tmp, int(unused_top_bits)); - code.shr(tmp, int(unused_top_bits + page_bits)); + code.shr(tmp, int(unused_top_bits + page_table_const_bits)); } } else { code.mov(tmp, vaddr); - code.shr(tmp, int(page_bits)); + code.shr(tmp, int(page_table_const_bits)); code.and_(tmp, u32((1 << valid_page_index_bits) - 1)); } } else { ASSERT(valid_page_index_bits < 32); code.mov(tmp, vaddr); - code.shr(tmp, int(page_bits)); + code.shr(tmp, int(page_table_const_bits)); code.test(tmp, u32(-(1 << valid_page_index_bits))); code.jnz(abort, code.T_NEAR); } @@ -151,7 +153,7 @@ template<> return page + vaddr; } code.mov(tmp, vaddr); - code.and_(tmp, static_cast(page_mask)); + code.and_(tmp, static_cast(page_table_const_mask)); return page + tmp; } 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 85ee3584eb..4c9ea821cc 100644 --- a/src/dynarmic/src/dynarmic/backend/x64/emit_x64_saturation.cpp +++ b/src/dynarmic/src/dynarmic/backend/x64/emit_x64_saturation.cpp @@ -9,9 +9,9 @@ #include #include "dynarmic/common/assert.h" -#include +#include "dynarmic/mcl/bit.hpp" #include "dynarmic/common/common_types.h" -#include +#include "dynarmic/mcl/integer_of_size.hpp" #include "dynarmic/backend/x64/block_of_code.h" #include "dynarmic/backend/x64/emit_x64.h" @@ -25,12 +25,12 @@ using namespace Xbyak::util; namespace { -enum class Op { +enum class SaturationOp { Add, Sub, }; -template +template void EmitSignedSaturatedOp(BlockOfCode& code, EmitContext& ctx, IR::Inst* inst) { auto args = ctx.reg_alloc.GetArgumentInfo(inst); @@ -51,7 +51,7 @@ void EmitSignedSaturatedOp(BlockOfCode& code, EmitContext& ctx, IR::Inst* inst) // overflow now contains 0x7F... if a was positive, or 0x80... if a was negative - if constexpr (op == Op::Add) { + if constexpr (op == SaturationOp::Add) { code.add(result, addend); } else { code.sub(result, addend); @@ -75,16 +75,16 @@ void EmitSignedSaturatedOp(BlockOfCode& code, EmitContext& ctx, IR::Inst* inst) ctx.reg_alloc.DefineValue(code, inst, result); } -template +template void EmitUnsignedSaturatedOp(BlockOfCode& code, EmitContext& ctx, IR::Inst* inst) { auto args = ctx.reg_alloc.GetArgumentInfo(inst); Xbyak::Reg op_result = ctx.reg_alloc.UseScratchGpr(code, args[0]).changeBit(size); Xbyak::Reg addend = ctx.reg_alloc.UseScratchGpr(code, args[1]).changeBit(size); - constexpr u64 boundary = op == Op::Add ? (std::numeric_limits>::max)() : 0; + constexpr u64 boundary = op == SaturationOp::Add ? (std::numeric_limits>::max)() : 0; - if constexpr (op == Op::Add) { + if constexpr (op == SaturationOp::Add) { code.add(op_result, addend); } else { code.sub(op_result, addend); @@ -106,11 +106,11 @@ void EmitUnsignedSaturatedOp(BlockOfCode& code, EmitContext& ctx, IR::Inst* inst } // anonymous namespace void EmitX64::EmitSignedSaturatedAddWithFlag32(EmitContext& ctx, IR::Inst* inst) { - EmitSignedSaturatedOp(code, ctx, inst); + EmitSignedSaturatedOp(code, ctx, inst); } void EmitX64::EmitSignedSaturatedSubWithFlag32(EmitContext& ctx, IR::Inst* inst) { - EmitSignedSaturatedOp(code, ctx, inst); + EmitSignedSaturatedOp(code, ctx, inst); } void EmitX64::EmitSignedSaturation(EmitContext& ctx, IR::Inst* inst) { @@ -192,19 +192,19 @@ void EmitX64::EmitUnsignedSaturation(EmitContext& ctx, IR::Inst* inst) { } void EmitX64::EmitSignedSaturatedAdd8(EmitContext& ctx, IR::Inst* inst) { - EmitSignedSaturatedOp(code, ctx, inst); + EmitSignedSaturatedOp(code, ctx, inst); } void EmitX64::EmitSignedSaturatedAdd16(EmitContext& ctx, IR::Inst* inst) { - EmitSignedSaturatedOp(code, ctx, inst); + EmitSignedSaturatedOp(code, ctx, inst); } void EmitX64::EmitSignedSaturatedAdd32(EmitContext& ctx, IR::Inst* inst) { - EmitSignedSaturatedOp(code, ctx, inst); + EmitSignedSaturatedOp(code, ctx, inst); } void EmitX64::EmitSignedSaturatedAdd64(EmitContext& ctx, IR::Inst* inst) { - EmitSignedSaturatedOp(code, ctx, inst); + EmitSignedSaturatedOp(code, ctx, inst); } void EmitX64::EmitSignedSaturatedDoublingMultiplyReturnHigh16(EmitContext& ctx, IR::Inst* inst) { @@ -256,51 +256,51 @@ void EmitX64::EmitSignedSaturatedDoublingMultiplyReturnHigh32(EmitContext& ctx, } void EmitX64::EmitSignedSaturatedSub8(EmitContext& ctx, IR::Inst* inst) { - EmitSignedSaturatedOp(code, ctx, inst); + EmitSignedSaturatedOp(code, ctx, inst); } void EmitX64::EmitSignedSaturatedSub16(EmitContext& ctx, IR::Inst* inst) { - EmitSignedSaturatedOp(code, ctx, inst); + EmitSignedSaturatedOp(code, ctx, inst); } void EmitX64::EmitSignedSaturatedSub32(EmitContext& ctx, IR::Inst* inst) { - EmitSignedSaturatedOp(code, ctx, inst); + EmitSignedSaturatedOp(code, ctx, inst); } void EmitX64::EmitSignedSaturatedSub64(EmitContext& ctx, IR::Inst* inst) { - EmitSignedSaturatedOp(code, ctx, inst); + EmitSignedSaturatedOp(code, ctx, inst); } void EmitX64::EmitUnsignedSaturatedAdd8(EmitContext& ctx, IR::Inst* inst) { - EmitUnsignedSaturatedOp(code, ctx, inst); + EmitUnsignedSaturatedOp(code, ctx, inst); } void EmitX64::EmitUnsignedSaturatedAdd16(EmitContext& ctx, IR::Inst* inst) { - EmitUnsignedSaturatedOp(code, ctx, inst); + EmitUnsignedSaturatedOp(code, ctx, inst); } void EmitX64::EmitUnsignedSaturatedAdd32(EmitContext& ctx, IR::Inst* inst) { - EmitUnsignedSaturatedOp(code, ctx, inst); + EmitUnsignedSaturatedOp(code, ctx, inst); } void EmitX64::EmitUnsignedSaturatedAdd64(EmitContext& ctx, IR::Inst* inst) { - EmitUnsignedSaturatedOp(code, ctx, inst); + EmitUnsignedSaturatedOp(code, ctx, inst); } void EmitX64::EmitUnsignedSaturatedSub8(EmitContext& ctx, IR::Inst* inst) { - EmitUnsignedSaturatedOp(code, ctx, inst); + EmitUnsignedSaturatedOp(code, ctx, inst); } void EmitX64::EmitUnsignedSaturatedSub16(EmitContext& ctx, IR::Inst* inst) { - EmitUnsignedSaturatedOp(code, ctx, inst); + EmitUnsignedSaturatedOp(code, ctx, inst); } void EmitX64::EmitUnsignedSaturatedSub32(EmitContext& ctx, IR::Inst* inst) { - EmitUnsignedSaturatedOp(code, ctx, inst); + EmitUnsignedSaturatedOp(code, ctx, inst); } void EmitX64::EmitUnsignedSaturatedSub64(EmitContext& ctx, IR::Inst* inst) { - EmitUnsignedSaturatedOp(code, ctx, inst); + EmitUnsignedSaturatedOp(code, ctx, inst); } } // namespace Dynarmic::Backend::X64 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 1f96939d88..a0fd944041 100644 --- a/src/dynarmic/src/dynarmic/backend/x64/emit_x64_vector.cpp +++ b/src/dynarmic/src/dynarmic/backend/x64/emit_x64_vector.cpp @@ -13,11 +13,9 @@ #include #include "dynarmic/common/assert.h" -#include -#include -#include +#include "dynarmic/mcl/bit.hpp" #include "dynarmic/common/common_types.h" -#include +#include "dynarmic/mcl/function_info.hpp" #include "dynarmic/backend/x64/xbyak.h" #include "dynarmic/backend/x64/abi.h" @@ -5856,3 +5854,5 @@ void EmitX64::EmitZeroVector(EmitContext& ctx, IR::Inst* inst) { } } // namespace Dynarmic::Backend::X64 + +#undef ICODE 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 2247b18fcd..70edfbd0bc 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 @@ -13,14 +13,8 @@ #include #include "dynarmic/common/assert.h" -#include -#include -#include -#include -#include -#include -#include -#include +#include "dynarmic/mcl/function_info.hpp" +#include "dynarmic/mcl/integer_of_size.hpp" #include "dynarmic/backend/x64/xbyak.h" #include "dynarmic/backend/x64/abi.h" @@ -31,7 +25,6 @@ #include "dynarmic/common/fp/info.h" #include "dynarmic/common/fp/op.h" #include "dynarmic/common/fp/util.h" -#include "dynarmic/common/lut_from_list.h" #include "dynarmic/interface/optimization_flags.h" #include "dynarmic/ir/basic_block.h" #include "dynarmic/ir/microinstruction.h" @@ -42,7 +35,6 @@ namespace Dynarmic::Backend::X64 { using namespace Xbyak::util; -namespace mp = mcl::mp; namespace { @@ -2001,6 +1993,7 @@ void EmitX64::EmitFPVectorToHalf32(EmitContext& ctx, IR::Inst* inst) { } } + // Assembly thunk; just remember not to specialise too much otherwise i-cache death! // template // static void EmitFPVectorToFixedThunk(VectorArray& output, const VectorArray& input, FP::FPCR fpcr, FP::FPSR& fpsr) { @@ -2127,28 +2120,42 @@ void EmitFPVectorToFixed(BlockOfCode& code, EmitContext& ctx, IR::Inst* inst) { } } - using fbits_list = mp::lift_sequence>; - using rounding_list = mp::list< - mp::lift_value, - mp::lift_value, - mp::lift_value, - mp::lift_value, - mp::lift_value>; - - static const auto lut = Common::GenerateLookupTableFromList([](I) { - using FPT = mcl::unsigned_integer_of_size; // WORKAROUND: For issue 678 on MSVC - return std::pair{ - mp::lower_to_tuple_v, - Common::FptrCast([](VectorArray& output, const VectorArray& input, FP::FPCR fpcr, FP::FPSR& fpsr) { - constexpr size_t fbits = mp::get<0, I>::value; - constexpr FP::RoundingMode rounding_mode = mp::get<1, I>::value; + using FPT = mcl::unsigned_integer_of_size; // WORKAROUND: For issue 678 on MSVC + auto const func = [rounding]() -> void(*)(VectorArray& output, const VectorArray& input, FP::FPCR fpcr, FP::FPSR& fpsr) { + switch (rounding) { + case FP::RoundingMode::ToNearest_TieEven: + return [](VectorArray& output, const VectorArray& input, FP::FPCR fpcr, FP::FPSR& fpsr) { for (size_t i = 0; i < output.size(); ++i) - output[i] = FPT(FP::FPToFixed(fsize, input[i], fbits, unsigned_, fpcr, rounding_mode, fpsr)); - }) - }; - }, mp::cartesian_product{}); - - EmitTwoOpFallback<3>(code, ctx, inst, lut.at(std::make_tuple(fbits, rounding))); + output[i] = FPT(FP::FPToFixed(fsize, input[i], fsize, unsigned_, fpcr, FP::RoundingMode::ToNearest_TieEven, fpsr)); + }; + case FP::RoundingMode::TowardsPlusInfinity: + return [](VectorArray& output, const VectorArray& input, FP::FPCR fpcr, FP::FPSR& fpsr) { + for (size_t i = 0; i < output.size(); ++i) + output[i] = FPT(FP::FPToFixed(fsize, input[i], fsize, unsigned_, fpcr, FP::RoundingMode::TowardsPlusInfinity, fpsr)); + }; + case FP::RoundingMode::TowardsMinusInfinity: + return [](VectorArray& output, const VectorArray& input, FP::FPCR fpcr, FP::FPSR& fpsr) { + for (size_t i = 0; i < output.size(); ++i) + output[i] = FPT(FP::FPToFixed(fsize, input[i], fsize, unsigned_, fpcr, FP::RoundingMode::TowardsMinusInfinity, fpsr)); + }; + case FP::RoundingMode::TowardsZero: + return [](VectorArray& output, const VectorArray& input, FP::FPCR fpcr, FP::FPSR& fpsr) { + for (size_t i = 0; i < output.size(); ++i) + output[i] = FPT(FP::FPToFixed(fsize, input[i], fsize, unsigned_, fpcr, FP::RoundingMode::TowardsZero, fpsr)); + }; + case FP::RoundingMode::ToNearest_TieAwayFromZero: + return [](VectorArray& output, const VectorArray& input, FP::FPCR fpcr, FP::FPSR& fpsr) { + for (size_t i = 0; i < output.size(); ++i) + output[i] = FPT(FP::FPToFixed(fsize, input[i], fsize, unsigned_, fpcr, FP::RoundingMode::ToNearest_TieAwayFromZero, fpsr)); + }; + case FP::RoundingMode::ToOdd: + return [](VectorArray& output, const VectorArray& input, FP::FPCR fpcr, FP::FPSR& fpsr) { + for (size_t i = 0; i < output.size(); ++i) + output[i] = FPT(FP::FPToFixed(fsize, input[i], fsize, unsigned_, fpcr, FP::RoundingMode::ToOdd, fpsr)); + }; + } + }(); + EmitTwoOpFallback<3>(code, ctx, inst, func); } void EmitX64::EmitFPVectorToSignedFixed16(EmitContext& ctx, IR::Inst* inst) { 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 03ded4066d..f0b02169d7 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 @@ -1,4 +1,4 @@ -// SPDX-FileCopyrightText: Copyright 2025 Eden Emulator Project +// SPDX-FileCopyrightText: Copyright 2026 Eden Emulator Project // SPDX-License-Identifier: GPL-3.0-or-later /* This file is part of the dynarmic project. @@ -52,12 +52,12 @@ void EmitVectorSaturatedNative(BlockOfCode& code, EmitContext& ctx, IR::Inst* in ctx.reg_alloc.DefineValue(code, inst, result); } -enum class Op { +enum class VectorSaturationOp { Add, Sub, }; -template +template void EmitVectorSignedSaturated(BlockOfCode& code, EmitContext& ctx, IR::Inst* inst) { static_assert(esize == 32 || esize == 64); constexpr u64 msb_mask = esize == 32 ? 0x8000000080000000 : 0x8000000000000000; @@ -72,7 +72,7 @@ void EmitVectorSignedSaturated(BlockOfCode& code, EmitContext& ctx, IR::Inst* in code.movaps(xmm0, operand1); - if constexpr (op == Op::Add) { + if constexpr (op == VectorSaturationOp::Add) { ICODE(vpadd)(result, operand1, operand2); code.vpternlogd(xmm0, result, operand2, 0b00100100); } else { @@ -102,7 +102,7 @@ void EmitVectorSignedSaturated(BlockOfCode& code, EmitContext& ctx, IR::Inst* in const Xbyak::Xmm tmp = ctx.reg_alloc.ScratchXmm(code); if (code.HasHostFeature(HostFeature::AVX)) { - if constexpr (op == Op::Add) { + if constexpr (op == VectorSaturationOp::Add) { ICODE(vpadd)(result, operand1, operand2); } else { ICODE(vpsub)(result, operand1, operand2); @@ -112,7 +112,7 @@ void EmitVectorSignedSaturated(BlockOfCode& code, EmitContext& ctx, IR::Inst* in } else { code.movaps(xmm0, operand1); code.movaps(tmp, operand1); - if constexpr (op == Op::Add) { + if constexpr (op == VectorSaturationOp::Add) { ICODE(padd)(result, operand2); } else { ICODE(psub)(result, operand2); @@ -121,7 +121,7 @@ void EmitVectorSignedSaturated(BlockOfCode& code, EmitContext& ctx, IR::Inst* in code.pxor(tmp, result); } - if constexpr (op == Op::Add) { + if constexpr (op == VectorSaturationOp::Add) { code.pandn(xmm0, tmp); } else { code.pand(xmm0, tmp); @@ -165,7 +165,7 @@ void EmitVectorSignedSaturated(BlockOfCode& code, EmitContext& ctx, IR::Inst* in } } -template +template void EmitVectorUnsignedSaturated(BlockOfCode& code, EmitContext& ctx, IR::Inst* inst) { static_assert(esize == 32 || esize == 64); @@ -177,7 +177,7 @@ void EmitVectorUnsignedSaturated(BlockOfCode& code, EmitContext& ctx, IR::Inst* const Xbyak::Xmm result = ctx.reg_alloc.ScratchXmm(code); const Xbyak::Reg8 overflow = ctx.reg_alloc.ScratchGpr(code).cvt8(); - if constexpr (op == Op::Add) { + if constexpr (op == VectorSaturationOp::Add) { ICODE(vpadd)(result, operand1, operand2); ICODE(vpcmpu)(k1, result, operand1, CmpInt::LessThan); ICODE(vpternlog)(result | k1, result, result, u8(0xFF)); @@ -201,7 +201,7 @@ void EmitVectorUnsignedSaturated(BlockOfCode& code, EmitContext& ctx, IR::Inst* const Xbyak::Reg8 overflow = ctx.reg_alloc.ScratchGpr(code).cvt8(); const Xbyak::Xmm tmp = ctx.reg_alloc.ScratchXmm(code); - if constexpr (op == Op::Add) { + if constexpr (op == VectorSaturationOp::Add) { if (code.HasHostFeature(HostFeature::AVX)) { code.vpxor(xmm0, operand1, operand2); code.vpand(tmp, operand1, operand2); @@ -250,7 +250,7 @@ void EmitVectorUnsignedSaturated(BlockOfCode& code, EmitContext& ctx, IR::Inst* code.setnz(overflow); code.or_(code.byte[code.ABI_JIT_PTR + code.GetJitStateInfo().offsetof_fpsr_qc], overflow); - if constexpr (op == Op::Add) { + if constexpr (op == VectorSaturationOp::Add) { code.por(result, tmp); ctx.reg_alloc.DefineValue(code, inst, result); } else { @@ -270,11 +270,11 @@ void EmitX64::EmitVectorSignedSaturatedAdd16(EmitContext& ctx, IR::Inst* inst) { } void EmitX64::EmitVectorSignedSaturatedAdd32(EmitContext& ctx, IR::Inst* inst) { - EmitVectorSignedSaturated(code, ctx, inst); + EmitVectorSignedSaturated(code, ctx, inst); } void EmitX64::EmitVectorSignedSaturatedAdd64(EmitContext& ctx, IR::Inst* inst) { - EmitVectorSignedSaturated(code, ctx, inst); + EmitVectorSignedSaturated(code, ctx, inst); } void EmitX64::EmitVectorSignedSaturatedSub8(EmitContext& ctx, IR::Inst* inst) { @@ -286,11 +286,11 @@ void EmitX64::EmitVectorSignedSaturatedSub16(EmitContext& ctx, IR::Inst* inst) { } void EmitX64::EmitVectorSignedSaturatedSub32(EmitContext& ctx, IR::Inst* inst) { - EmitVectorSignedSaturated(code, ctx, inst); + EmitVectorSignedSaturated(code, ctx, inst); } void EmitX64::EmitVectorSignedSaturatedSub64(EmitContext& ctx, IR::Inst* inst) { - EmitVectorSignedSaturated(code, ctx, inst); + EmitVectorSignedSaturated(code, ctx, inst); } void EmitX64::EmitVectorUnsignedSaturatedAdd8(EmitContext& ctx, IR::Inst* inst) { @@ -302,11 +302,11 @@ void EmitX64::EmitVectorUnsignedSaturatedAdd16(EmitContext& ctx, IR::Inst* inst) } void EmitX64::EmitVectorUnsignedSaturatedAdd32(EmitContext& ctx, IR::Inst* inst) { - EmitVectorUnsignedSaturated(code, ctx, inst); + EmitVectorUnsignedSaturated(code, ctx, inst); } void EmitX64::EmitVectorUnsignedSaturatedAdd64(EmitContext& ctx, IR::Inst* inst) { - EmitVectorUnsignedSaturated(code, ctx, inst); + EmitVectorUnsignedSaturated(code, ctx, inst); } void EmitX64::EmitVectorUnsignedSaturatedSub8(EmitContext& ctx, IR::Inst* inst) { @@ -318,11 +318,11 @@ void EmitX64::EmitVectorUnsignedSaturatedSub16(EmitContext& ctx, IR::Inst* inst) } void EmitX64::EmitVectorUnsignedSaturatedSub32(EmitContext& ctx, IR::Inst* inst) { - EmitVectorUnsignedSaturated(code, ctx, inst); + EmitVectorUnsignedSaturated(code, ctx, inst); } void EmitX64::EmitVectorUnsignedSaturatedSub64(EmitContext& ctx, IR::Inst* inst) { - EmitVectorUnsignedSaturated(code, ctx, inst); + EmitVectorUnsignedSaturated(code, ctx, inst); } } // namespace Dynarmic::Backend::X64 diff --git a/src/dynarmic/src/dynarmic/backend/x64/perf_map.cpp b/src/dynarmic/src/dynarmic/backend/x64/perf_map.cpp index a0b5c4fdde..095d6194f6 100644 --- a/src/dynarmic/src/dynarmic/backend/x64/perf_map.cpp +++ b/src/dynarmic/src/dynarmic/backend/x64/perf_map.cpp @@ -1,4 +1,4 @@ -// SPDX-FileCopyrightText: Copyright 2025 Eden Emulator Project +// SPDX-FileCopyrightText: Copyright 2026 Eden Emulator Project // SPDX-License-Identifier: GPL-3.0-or-later /* This file is part of the dynarmic project. @@ -6,17 +6,16 @@ * SPDX-License-Identifier: 0BSD */ -#include "dynarmic/backend/x64/perf_map.h" - #include #include +#include +#include "dynarmic/backend/x64/perf_map.h" +#include "dynarmic/common/common_types.h" #if defined(__linux__) && !defined(__ANDROID__) # include # include # include -# include -# include # include # include diff --git a/src/dynarmic/src/dynarmic/common/cast_util.h b/src/dynarmic/src/dynarmic/common/cast_util.h index 92c9a259b3..aed9067977 100644 --- a/src/dynarmic/src/dynarmic/common/cast_util.h +++ b/src/dynarmic/src/dynarmic/common/cast_util.h @@ -1,3 +1,6 @@ +// SPDX-FileCopyrightText: Copyright 2026 Eden Emulator Project +// SPDX-License-Identifier: GPL-3.0-or-later + /* This file is part of the dynarmic project. * Copyright (c) 2018 MerryMage * SPDX-License-Identifier: 0BSD @@ -5,7 +8,7 @@ #pragma once -#include +#include "dynarmic/mcl/function_info.hpp" namespace Dynarmic::Common { diff --git a/src/dynarmic/src/dynarmic/common/fp/fpcr.h b/src/dynarmic/src/dynarmic/common/fp/fpcr.h index be963a2099..948917bc35 100644 --- a/src/dynarmic/src/dynarmic/common/fp/fpcr.h +++ b/src/dynarmic/src/dynarmic/common/fp/fpcr.h @@ -1,4 +1,4 @@ -// SPDX-FileCopyrightText: Copyright 2025 Eden Emulator Project +// SPDX-FileCopyrightText: Copyright 2026 Eden Emulator Project // SPDX-License-Identifier: GPL-3.0-or-later /* This file is part of the dynarmic project. @@ -11,7 +11,7 @@ #include #include "dynarmic/common/assert.h" -#include +#include "dynarmic/mcl/bit.hpp" #include "dynarmic/common/common_types.h" #include "dynarmic/common/fp/rounding_mode.h" diff --git a/src/dynarmic/src/dynarmic/common/fp/fpsr.h b/src/dynarmic/src/dynarmic/common/fp/fpsr.h index 9308132879..caa5cb92c7 100644 --- a/src/dynarmic/src/dynarmic/common/fp/fpsr.h +++ b/src/dynarmic/src/dynarmic/common/fp/fpsr.h @@ -1,4 +1,4 @@ -// SPDX-FileCopyrightText: Copyright 2025 Eden Emulator Project +// SPDX-FileCopyrightText: Copyright 2026 Eden Emulator Project // SPDX-License-Identifier: GPL-3.0-or-later /* This file is part of the dynarmic project. @@ -8,7 +8,7 @@ #pragma once -#include +#include "dynarmic/mcl/bit.hpp" #include "dynarmic/common/common_types.h" namespace Dynarmic::FP { diff --git a/src/dynarmic/src/dynarmic/common/fp/fused.cpp b/src/dynarmic/src/dynarmic/common/fp/fused.cpp index 5c32b05eb4..d16eb44791 100644 --- a/src/dynarmic/src/dynarmic/common/fp/fused.cpp +++ b/src/dynarmic/src/dynarmic/common/fp/fused.cpp @@ -1,3 +1,6 @@ +// SPDX-FileCopyrightText: Copyright 2026 Eden Emulator Project +// SPDX-License-Identifier: GPL-3.0-or-later + /* This file is part of the dynarmic project. * Copyright (c) 2018 MerryMage * SPDX-License-Identifier: 0BSD @@ -5,7 +8,7 @@ #include "dynarmic/common/fp/fused.h" -#include +#include "dynarmic/mcl/bit.hpp" #include "dynarmic/common/fp/unpacked.h" #include "dynarmic/common/u128.h" @@ -32,7 +35,7 @@ FPUnpacked FusedMulAdd(FPUnpacked addend, FPUnpacked op1, FPUnpacked op2) { return std::make_tuple(exponent, value); }(); - if (product_value == 0) { + if (product_value == u128(0, 0)) { return addend; } @@ -52,13 +55,13 @@ FPUnpacked FusedMulAdd(FPUnpacked addend, FPUnpacked op1, FPUnpacked op2) { } // addend < product - const u128 result = product_value + StickyLogicalShiftRight(addend.mantissa, exp_diff - normalized_point_position); + const u128 result = product_value + StickyLogicalShiftRight(u128(addend.mantissa, 0), exp_diff - normalized_point_position); return ReduceMantissa(product_sign, product_exponent, result); } // Subtraction - const u128 addend_long = u128(addend.mantissa) << normalized_point_position; + const u128 addend_long = u128(addend.mantissa, 0) << normalized_point_position; bool result_sign; u128 result; diff --git a/src/dynarmic/src/dynarmic/common/fp/info.h b/src/dynarmic/src/dynarmic/common/fp/info.h index 3969843f0f..eebca0fc0c 100644 --- a/src/dynarmic/src/dynarmic/common/fp/info.h +++ b/src/dynarmic/src/dynarmic/common/fp/info.h @@ -1,4 +1,4 @@ -// SPDX-FileCopyrightText: Copyright 2025 Eden Emulator Project +// SPDX-FileCopyrightText: Copyright 2026 Eden Emulator Project // SPDX-License-Identifier: GPL-3.0-or-later /* This file is part of the dynarmic project. @@ -8,7 +8,7 @@ #pragma once -#include +#include "dynarmic/mcl/bit.hpp" #include "dynarmic/common/common_types.h" namespace Dynarmic::FP { diff --git a/src/dynarmic/src/dynarmic/common/fp/mantissa_util.h b/src/dynarmic/src/dynarmic/common/fp/mantissa_util.h index 3999f97c27..43bb5fe604 100644 --- a/src/dynarmic/src/dynarmic/common/fp/mantissa_util.h +++ b/src/dynarmic/src/dynarmic/common/fp/mantissa_util.h @@ -1,4 +1,4 @@ -// SPDX-FileCopyrightText: Copyright 2025 Eden Emulator Project +// SPDX-FileCopyrightText: Copyright 2026 Eden Emulator Project // SPDX-License-Identifier: GPL-3.0-or-later /* This file is part of the dynarmic project. @@ -8,8 +8,7 @@ #pragma once -#include -#include +#include "dynarmic/mcl/bit.hpp" #include "dynarmic/common/common_types.h" namespace Dynarmic::FP { diff --git a/src/dynarmic/src/dynarmic/common/fp/op/FPConvert.cpp b/src/dynarmic/src/dynarmic/common/fp/op/FPConvert.cpp index 906aa781a1..82803f715d 100644 --- a/src/dynarmic/src/dynarmic/common/fp/op/FPConvert.cpp +++ b/src/dynarmic/src/dynarmic/common/fp/op/FPConvert.cpp @@ -1,4 +1,4 @@ -// SPDX-FileCopyrightText: Copyright 2025 Eden Emulator Project +// SPDX-FileCopyrightText: Copyright 2026 Eden Emulator Project // SPDX-License-Identifier: GPL-3.0-or-later /* This file is part of the dynarmic project. @@ -8,8 +8,7 @@ #include "dynarmic/common/fp/op/FPConvert.h" -#include -#include +#include "dynarmic/mcl/bit.hpp" #include "dynarmic/common/common_types.h" #include "dynarmic/common/fp/fpcr.h" diff --git a/src/dynarmic/src/dynarmic/common/fp/op/FPRecipExponent.cpp b/src/dynarmic/src/dynarmic/common/fp/op/FPRecipExponent.cpp index e932e02803..332870eb8a 100644 --- a/src/dynarmic/src/dynarmic/common/fp/op/FPRecipExponent.cpp +++ b/src/dynarmic/src/dynarmic/common/fp/op/FPRecipExponent.cpp @@ -1,4 +1,4 @@ -// SPDX-FileCopyrightText: Copyright 2025 Eden Emulator Project +// SPDX-FileCopyrightText: Copyright 2026 Eden Emulator Project // SPDX-License-Identifier: GPL-3.0-or-later /* This file is part of the dynarmic project. @@ -8,7 +8,7 @@ #include "dynarmic/common/fp/op/FPRecipExponent.h" -#include +#include "dynarmic/mcl/bit.hpp" #include "dynarmic/common/common_types.h" #include "dynarmic/common/fp/fpcr.h" diff --git a/src/dynarmic/src/dynarmic/common/fp/op/FPRoundInt.cpp b/src/dynarmic/src/dynarmic/common/fp/op/FPRoundInt.cpp index 198a71c807..4bcfcd7c8a 100644 --- a/src/dynarmic/src/dynarmic/common/fp/op/FPRoundInt.cpp +++ b/src/dynarmic/src/dynarmic/common/fp/op/FPRoundInt.cpp @@ -1,4 +1,4 @@ -// SPDX-FileCopyrightText: Copyright 2025 Eden Emulator Project +// SPDX-FileCopyrightText: Copyright 2026 Eden Emulator Project // SPDX-License-Identifier: GPL-3.0-or-later /* This file is part of the dynarmic project. @@ -9,7 +9,7 @@ #include "dynarmic/common/fp/op/FPRoundInt.h" #include "dynarmic/common/assert.h" -#include +#include "dynarmic/mcl/bit.hpp" #include "dynarmic/common/common_types.h" #include "dynarmic/common/fp/fpcr.h" diff --git a/src/dynarmic/src/dynarmic/common/fp/op/FPToFixed.cpp b/src/dynarmic/src/dynarmic/common/fp/op/FPToFixed.cpp index 8e3474952a..2f37797b70 100644 --- a/src/dynarmic/src/dynarmic/common/fp/op/FPToFixed.cpp +++ b/src/dynarmic/src/dynarmic/common/fp/op/FPToFixed.cpp @@ -1,4 +1,4 @@ -// SPDX-FileCopyrightText: Copyright 2025 Eden Emulator Project +// SPDX-FileCopyrightText: Copyright 2026 Eden Emulator Project // SPDX-License-Identifier: GPL-3.0-or-later /* This file is part of the dynarmic project. @@ -10,8 +10,7 @@ #include #include "dynarmic/common/assert.h" -#include -#include +#include "dynarmic/mcl/bit.hpp" #include "dynarmic/common/common_types.h" #include "dynarmic/common/fp/fpcr.h" diff --git a/src/dynarmic/src/dynarmic/common/fp/process_nan.cpp b/src/dynarmic/src/dynarmic/common/fp/process_nan.cpp index ff1b09f4ba..7f47852d98 100644 --- a/src/dynarmic/src/dynarmic/common/fp/process_nan.cpp +++ b/src/dynarmic/src/dynarmic/common/fp/process_nan.cpp @@ -1,4 +1,4 @@ -// SPDX-FileCopyrightText: Copyright 2025 Eden Emulator Project +// SPDX-FileCopyrightText: Copyright 2026 Eden Emulator Project // SPDX-License-Identifier: GPL-3.0-or-later /* This file is part of the dynarmic project. @@ -11,7 +11,7 @@ #include #include "dynarmic/common/assert.h" -#include +#include "dynarmic/mcl/bit.hpp" #include "dynarmic/common/fp/fpcr.h" #include "dynarmic/common/fp/fpsr.h" diff --git a/src/dynarmic/src/dynarmic/common/fp/unpacked.cpp b/src/dynarmic/src/dynarmic/common/fp/unpacked.cpp index f853ab07e1..d6bb615cb4 100644 --- a/src/dynarmic/src/dynarmic/common/fp/unpacked.cpp +++ b/src/dynarmic/src/dynarmic/common/fp/unpacked.cpp @@ -1,3 +1,6 @@ +// SPDX-FileCopyrightText: Copyright 2026 Eden Emulator Project +// SPDX-License-Identifier: GPL-3.0-or-later + /* This file is part of the dynarmic project. * Copyright (c) 2018 MerryMage * SPDX-License-Identifier: 0BSD @@ -7,8 +10,7 @@ #include -#include -#include +#include "dynarmic/mcl/bit.hpp" #include "dynarmic/common/fp/fpsr.h" #include "dynarmic/common/fp/info.h" diff --git a/src/dynarmic/src/dynarmic/common/fp/unpacked.h b/src/dynarmic/src/dynarmic/common/fp/unpacked.h index 49dca74304..effc604fb0 100644 --- a/src/dynarmic/src/dynarmic/common/fp/unpacked.h +++ b/src/dynarmic/src/dynarmic/common/fp/unpacked.h @@ -1,4 +1,4 @@ -// SPDX-FileCopyrightText: Copyright 2025 Eden Emulator Project +// SPDX-FileCopyrightText: Copyright 2026 Eden Emulator Project // SPDX-License-Identifier: GPL-3.0-or-later /* This file is part of the dynarmic project. @@ -10,7 +10,7 @@ #include -#include +#include "dynarmic/mcl/bit.hpp" #include "dynarmic/common/common_types.h" #include "dynarmic/common/fp/fpcr.h" diff --git a/src/dynarmic/src/dynarmic/common/lut_from_list.h b/src/dynarmic/src/dynarmic/common/lut_from_list.h deleted file mode 100644 index 633b62aeda..0000000000 --- a/src/dynarmic/src/dynarmic/common/lut_from_list.h +++ /dev/null @@ -1,55 +0,0 @@ -// SPDX-FileCopyrightText: Copyright 2025 Eden Emulator Project -// SPDX-License-Identifier: GPL-3.0-or-later - -/* This file is part of the dynarmic project. - * Copyright (c) 2018 MerryMage - * SPDX-License-Identifier: 0BSD - */ - -#pragma once - -#include -#include -#include - -#include -#include -#include - -#ifdef _MSC_VER -# include -#endif - -namespace Dynarmic::Common { - -// prevents this function from printing 56,000 character warning messages -#ifdef __GNUC__ -#pragma GCC diagnostic push -#pragma GCC diagnostic ignored "-Wno-stack-usage" -#endif -#ifdef __clang__ -#pragma clang diagnostic push -#pragma clang diagnostic ignored "-Wno-stack-usage" -#endif - -template -inline auto GenerateLookupTableFromList(Function f, mcl::mp::list) { -#ifdef _MSC_VER - using PairT = std::invoke_result_t>>; -#else - using PairT = std::common_type_t...>; -#endif - using MapT = mcl::mp::apply; - static_assert(mcl::is_instance_of_template_v); - const std::initializer_list pair_array{f(Values{})...}; - return MapT(pair_array.begin(), pair_array.end()); -} - -#ifdef __GNUC__ -#pragma GCC diagnostic pop -#endif -#ifdef __clang__ -#pragma clang diagnostic pop -#endif - -} // namespace Dynarmic::Common diff --git a/src/dynarmic/src/dynarmic/common/safe_ops.h b/src/dynarmic/src/dynarmic/common/safe_ops.h index f494bdb24b..5cc8cb5049 100644 --- a/src/dynarmic/src/dynarmic/common/safe_ops.h +++ b/src/dynarmic/src/dynarmic/common/safe_ops.h @@ -1,4 +1,4 @@ -// SPDX-FileCopyrightText: Copyright 2025 Eden Emulator Project +// SPDX-FileCopyrightText: Copyright 2026 Eden Emulator Project // SPDX-License-Identifier: GPL-3.0-or-later /* This file is part of the dynarmic project. @@ -10,7 +10,7 @@ #include -#include +#include "dynarmic/mcl/bit.hpp" #include "dynarmic/common/common_types.h" #include "dynarmic/common/u128.h" diff --git a/src/dynarmic/src/dynarmic/common/u128.cpp b/src/dynarmic/src/dynarmic/common/u128.cpp index fb7de7a495..541e009b23 100644 --- a/src/dynarmic/src/dynarmic/common/u128.cpp +++ b/src/dynarmic/src/dynarmic/common/u128.cpp @@ -1,4 +1,4 @@ -// SPDX-FileCopyrightText: Copyright 2025 Eden Emulator Project +// SPDX-FileCopyrightText: Copyright 2026 Eden Emulator Project // SPDX-License-Identifier: GPL-3.0-or-later /* This file is part of the dynarmic project. @@ -137,7 +137,7 @@ u128 StickyLogicalShiftRight(u128 operand, int amount) { } if (operand.lower != 0 || operand.upper != 0) { - return u128(1); + return u128(1, 0); } return {}; } diff --git a/src/dynarmic/src/dynarmic/common/u128.h b/src/dynarmic/src/dynarmic/common/u128.h index 9ab4aa0bd5..4fa842b3cd 100644 --- a/src/dynarmic/src/dynarmic/common/u128.h +++ b/src/dynarmic/src/dynarmic/common/u128.h @@ -1,4 +1,4 @@ -// SPDX-FileCopyrightText: Copyright 2025 Eden Emulator Project +// SPDX-FileCopyrightText: Copyright 2026 Eden Emulator Project // SPDX-License-Identifier: GPL-3.0-or-later /* This file is part of the dynarmic project. @@ -11,8 +11,7 @@ #include #include -#include -#include +#include "dynarmic/mcl/bit.hpp" #include "dynarmic/common/common_types.h" namespace Dynarmic { @@ -23,22 +22,13 @@ struct u128 { u128(u128&&) = default; u128& operator=(const u128&) = default; u128& operator=(u128&&) = default; - - u128(u64 lower_, u64 upper_) - : lower(lower_), upper(upper_) {} - - template - /* implicit */ u128(T value) - : lower(value), upper(0) { - static_assert(std::is_integral_v); - static_assert(mcl::bitsizeof <= mcl::bitsizeof); - } + explicit u128(u64 lower_, u64 upper_) : lower(lower_), upper(upper_) {} u64 lower = 0; u64 upper = 0; template - bool Bit() const { + [[nodiscard]] inline bool Bit() const { static_assert(bit_position < 128); if constexpr (bit_position < 64) { return mcl::bit::get_bit(lower); diff --git a/src/dynarmic/src/dynarmic/frontend/A32/FPSCR.h b/src/dynarmic/src/dynarmic/frontend/A32/FPSCR.h index 7a4c738e9e..7e0532ee93 100644 --- a/src/dynarmic/src/dynarmic/frontend/A32/FPSCR.h +++ b/src/dynarmic/src/dynarmic/frontend/A32/FPSCR.h @@ -1,4 +1,4 @@ -// SPDX-FileCopyrightText: Copyright 2025 Eden Emulator Project +// SPDX-FileCopyrightText: Copyright 2026 Eden Emulator Project // SPDX-License-Identifier: GPL-3.0-or-later /* This file is part of the dynarmic project. @@ -10,7 +10,7 @@ #include -#include +#include "dynarmic/mcl/bit.hpp" #include "dynarmic/common/common_types.h" #include "dynarmic/common/fp/rounding_mode.h" diff --git a/src/dynarmic/src/dynarmic/frontend/A32/ITState.h b/src/dynarmic/src/dynarmic/frontend/A32/ITState.h index eeddaeb6b5..baabc1ca15 100644 --- a/src/dynarmic/src/dynarmic/frontend/A32/ITState.h +++ b/src/dynarmic/src/dynarmic/frontend/A32/ITState.h @@ -1,4 +1,4 @@ -// SPDX-FileCopyrightText: Copyright 2025 Eden Emulator Project +// SPDX-FileCopyrightText: Copyright 2026 Eden Emulator Project // SPDX-License-Identifier: GPL-3.0-or-later /* This file is part of the dynarmic project. @@ -8,7 +8,7 @@ #pragma once -#include +#include "dynarmic/mcl/bit.hpp" #include "dynarmic/common/common_types.h" #include "dynarmic/ir/cond.h" diff --git a/src/dynarmic/src/dynarmic/frontend/A32/PSR.h b/src/dynarmic/src/dynarmic/frontend/A32/PSR.h index 328fdb17c0..16ca86aeac 100644 --- a/src/dynarmic/src/dynarmic/frontend/A32/PSR.h +++ b/src/dynarmic/src/dynarmic/frontend/A32/PSR.h @@ -1,4 +1,4 @@ -// SPDX-FileCopyrightText: Copyright 2025 Eden Emulator Project +// SPDX-FileCopyrightText: Copyright 2026 Eden Emulator Project // SPDX-License-Identifier: GPL-3.0-or-later /* This file is part of the dynarmic project. @@ -8,7 +8,7 @@ #pragma once -#include +#include "dynarmic/mcl/bit.hpp" #include "dynarmic/common/common_types.h" #include "dynarmic/frontend/A32/ITState.h" diff --git a/src/dynarmic/src/dynarmic/frontend/A32/a32_types.cpp b/src/dynarmic/src/dynarmic/frontend/A32/a32_types.cpp index a47ce0b78b..704179ecfb 100644 --- a/src/dynarmic/src/dynarmic/frontend/A32/a32_types.cpp +++ b/src/dynarmic/src/dynarmic/frontend/A32/a32_types.cpp @@ -1,3 +1,6 @@ +// SPDX-FileCopyrightText: Copyright 2026 Eden Emulator Project +// SPDX-License-Identifier: GPL-3.0-or-later + /* This file is part of the dynarmic project. * Copyright (c) 2016 MerryMage * SPDX-License-Identifier: 0BSD @@ -8,7 +11,7 @@ #include #include -#include +#include "dynarmic/mcl/bit.hpp" namespace Dynarmic::A32 { diff --git a/src/dynarmic/src/dynarmic/frontend/A32/decoder/arm.h b/src/dynarmic/src/dynarmic/frontend/A32/decoder/arm.h index c6f034ae21..bbf128d797 100644 --- a/src/dynarmic/src/dynarmic/frontend/A32/decoder/arm.h +++ b/src/dynarmic/src/dynarmic/frontend/A32/decoder/arm.h @@ -1,4 +1,4 @@ -// SPDX-FileCopyrightText: Copyright 2025 Eden Emulator Project +// SPDX-FileCopyrightText: Copyright 2026 Eden Emulator Project // SPDX-License-Identifier: GPL-3.0-or-later /* This file is part of the dynarmic project. @@ -15,7 +15,7 @@ #include #include -#include +#include "dynarmic/mcl/bit.hpp" #include "dynarmic/common/common_types.h" #include "dynarmic/frontend/decoder/decoder_detail.h" diff --git a/src/dynarmic/src/dynarmic/frontend/A32/decoder/asimd.h b/src/dynarmic/src/dynarmic/frontend/A32/decoder/asimd.h index 6bf52b87e6..a16caedd87 100644 --- a/src/dynarmic/src/dynarmic/frontend/A32/decoder/asimd.h +++ b/src/dynarmic/src/dynarmic/frontend/A32/decoder/asimd.h @@ -1,4 +1,4 @@ -// SPDX-FileCopyrightText: Copyright 2025 Eden Emulator Project +// SPDX-FileCopyrightText: Copyright 2026 Eden Emulator Project // SPDX-License-Identifier: GPL-3.0-or-later /* This file is part of the dynarmic project. @@ -15,7 +15,7 @@ #include #include -#include +#include "dynarmic/mcl/bit.hpp" #include "dynarmic/common/common_types.h" #include "dynarmic/frontend/decoder/decoder_detail.h" diff --git a/src/dynarmic/src/dynarmic/frontend/A32/translate/conditional_state.cpp b/src/dynarmic/src/dynarmic/frontend/A32/translate/conditional_state.cpp index 8c55588a28..82d25f1337 100644 --- a/src/dynarmic/src/dynarmic/frontend/A32/translate/conditional_state.cpp +++ b/src/dynarmic/src/dynarmic/frontend/A32/translate/conditional_state.cpp @@ -32,8 +32,7 @@ bool CondCanContinue(const ConditionalState cond_state, const A32::IREmitter& ir } bool IsConditionPassed(TranslatorVisitor& v, IR::Cond cond) { - ASSERT_MSG(v.cond_state != ConditionalState::Break, - "This should never happen. We requested a break but that wasn't honored."); + ASSERT(v.cond_state != ConditionalState::Break && "This should never happen. We requested a break but that wasn't honored."); if (cond == IR::Cond::NV) { // NV conditional is obsolete diff --git a/src/dynarmic/src/dynarmic/frontend/A32/translate/impl/a32_branch.cpp b/src/dynarmic/src/dynarmic/frontend/A32/translate/impl/a32_branch.cpp index d87cfcfe82..63b40b8c31 100644 --- a/src/dynarmic/src/dynarmic/frontend/A32/translate/impl/a32_branch.cpp +++ b/src/dynarmic/src/dynarmic/frontend/A32/translate/impl/a32_branch.cpp @@ -1,9 +1,12 @@ +// SPDX-FileCopyrightText: Copyright 2026 Eden Emulator Project +// SPDX-License-Identifier: GPL-3.0-or-later + /* This file is part of the dynarmic project. * Copyright (c) 2016 MerryMage * SPDX-License-Identifier: 0BSD */ -#include +#include "dynarmic/mcl/bit.hpp" #include "dynarmic/frontend/A32/translate/impl/a32_translate_impl.h" diff --git a/src/dynarmic/src/dynarmic/frontend/A32/translate/impl/a32_translate_impl.h b/src/dynarmic/src/dynarmic/frontend/A32/translate/impl/a32_translate_impl.h index a03b2e666b..a8888c355f 100644 --- a/src/dynarmic/src/dynarmic/frontend/A32/translate/impl/a32_translate_impl.h +++ b/src/dynarmic/src/dynarmic/frontend/A32/translate/impl/a32_translate_impl.h @@ -9,8 +9,7 @@ #pragma once #include "dynarmic/common/assert.h" -#include -#include +#include "dynarmic/mcl/bit.hpp" #include "dynarmic/frontend/A32/a32_ir_emitter.h" #include "dynarmic/frontend/A32/a32_location_descriptor.h" diff --git a/src/dynarmic/src/dynarmic/frontend/A32/translate/impl/asimd_load_store_structures.cpp b/src/dynarmic/src/dynarmic/frontend/A32/translate/impl/asimd_load_store_structures.cpp index 68c0d983af..8d0f78396a 100644 --- a/src/dynarmic/src/dynarmic/frontend/A32/translate/impl/asimd_load_store_structures.cpp +++ b/src/dynarmic/src/dynarmic/frontend/A32/translate/impl/asimd_load_store_structures.cpp @@ -1,4 +1,4 @@ -// SPDX-FileCopyrightText: Copyright 2025 Eden Emulator Project +// SPDX-FileCopyrightText: Copyright 2026 Eden Emulator Project // SPDX-License-Identifier: GPL-3.0-or-later /* This file is part of the dynarmic project. @@ -9,7 +9,7 @@ #include #include -#include +#include "dynarmic/mcl/bit.hpp" #include "dynarmic/frontend/A32/translate/impl/a32_translate_impl.h" diff --git a/src/dynarmic/src/dynarmic/frontend/A32/translate/impl/asimd_misc.cpp b/src/dynarmic/src/dynarmic/frontend/A32/translate/impl/asimd_misc.cpp index 9d73e7d4ae..9aa50c6b8c 100644 --- a/src/dynarmic/src/dynarmic/frontend/A32/translate/impl/asimd_misc.cpp +++ b/src/dynarmic/src/dynarmic/frontend/A32/translate/impl/asimd_misc.cpp @@ -1,4 +1,4 @@ -// SPDX-FileCopyrightText: Copyright 2025 Eden Emulator Project +// SPDX-FileCopyrightText: Copyright 2026 Eden Emulator Project // SPDX-License-Identifier: GPL-3.0-or-later /* This file is part of the dynarmic project. @@ -9,8 +9,7 @@ #include #include "dynarmic/common/assert.h" -#include -#include +#include "dynarmic/mcl/bit.hpp" #include "dynarmic/frontend/A32/translate/impl/a32_translate_impl.h" diff --git a/src/dynarmic/src/dynarmic/frontend/A32/translate/impl/asimd_one_reg_modified_immediate.cpp b/src/dynarmic/src/dynarmic/frontend/A32/translate/impl/asimd_one_reg_modified_immediate.cpp index 459cbfea06..c5bdb1b551 100644 --- a/src/dynarmic/src/dynarmic/frontend/A32/translate/impl/asimd_one_reg_modified_immediate.cpp +++ b/src/dynarmic/src/dynarmic/frontend/A32/translate/impl/asimd_one_reg_modified_immediate.cpp @@ -1,4 +1,4 @@ -// SPDX-FileCopyrightText: Copyright 2025 Eden Emulator Project +// SPDX-FileCopyrightText: Copyright 2026 Eden Emulator Project // SPDX-License-Identifier: GPL-3.0-or-later /* This file is part of the dynarmic project. @@ -7,7 +7,7 @@ */ #include "dynarmic/common/assert.h" -#include +#include "dynarmic/mcl/bit.hpp" #include "dynarmic/frontend/A32/translate/impl/a32_translate_impl.h" diff --git a/src/dynarmic/src/dynarmic/frontend/A32/translate/impl/asimd_three_regs.cpp b/src/dynarmic/src/dynarmic/frontend/A32/translate/impl/asimd_three_regs.cpp index da8f43f2fb..8d5e694bca 100644 --- a/src/dynarmic/src/dynarmic/frontend/A32/translate/impl/asimd_three_regs.cpp +++ b/src/dynarmic/src/dynarmic/frontend/A32/translate/impl/asimd_three_regs.cpp @@ -1,9 +1,12 @@ +// SPDX-FileCopyrightText: Copyright 2026 Eden Emulator Project +// SPDX-License-Identifier: GPL-3.0-or-later + /* This file is part of the dynarmic project. * Copyright (c) 2020 MerryMage * SPDX-License-Identifier: 0BSD */ -#include +#include "dynarmic/mcl/bit.hpp" #include "dynarmic/frontend/A32/translate/impl/a32_translate_impl.h" #include "dynarmic/frontend/A32/translate/impl/common.h" diff --git a/src/dynarmic/src/dynarmic/frontend/A32/translate/impl/asimd_two_regs_misc.cpp b/src/dynarmic/src/dynarmic/frontend/A32/translate/impl/asimd_two_regs_misc.cpp index ddae1f420b..45455aa444 100644 --- a/src/dynarmic/src/dynarmic/frontend/A32/translate/impl/asimd_two_regs_misc.cpp +++ b/src/dynarmic/src/dynarmic/frontend/A32/translate/impl/asimd_two_regs_misc.cpp @@ -1,3 +1,6 @@ +// SPDX-FileCopyrightText: Copyright 2026 Eden Emulator Project +// SPDX-License-Identifier: GPL-3.0-or-later + /* This file is part of the dynarmic project. * Copyright (c) 2020 MerryMage * SPDX-License-Identifier: 0BSD @@ -5,7 +8,7 @@ #include -#include +#include "dynarmic/mcl/bit.hpp" #include "dynarmic/frontend/A32/translate/impl/a32_translate_impl.h" #include "dynarmic/frontend/A32/translate/impl/common.h" diff --git a/src/dynarmic/src/dynarmic/frontend/A32/translate/impl/asimd_two_regs_scalar.cpp b/src/dynarmic/src/dynarmic/frontend/A32/translate/impl/asimd_two_regs_scalar.cpp index 4d6855f1ed..d9cc3b1e64 100644 --- a/src/dynarmic/src/dynarmic/frontend/A32/translate/impl/asimd_two_regs_scalar.cpp +++ b/src/dynarmic/src/dynarmic/frontend/A32/translate/impl/asimd_two_regs_scalar.cpp @@ -1,4 +1,4 @@ -// SPDX-FileCopyrightText: Copyright 2025 Eden Emulator Project +// SPDX-FileCopyrightText: Copyright 2026 Eden Emulator Project // SPDX-License-Identifier: GPL-3.0-or-later /* This file is part of the dynarmic project. @@ -9,7 +9,7 @@ #include #include "dynarmic/common/assert.h" -#include +#include "dynarmic/mcl/bit.hpp" #include "dynarmic/frontend/A32/translate/impl/a32_translate_impl.h" diff --git a/src/dynarmic/src/dynarmic/frontend/A32/translate/impl/asimd_two_regs_shift.cpp b/src/dynarmic/src/dynarmic/frontend/A32/translate/impl/asimd_two_regs_shift.cpp index 27e94628a8..e5a4eb537f 100644 --- a/src/dynarmic/src/dynarmic/frontend/A32/translate/impl/asimd_two_regs_shift.cpp +++ b/src/dynarmic/src/dynarmic/frontend/A32/translate/impl/asimd_two_regs_shift.cpp @@ -1,4 +1,4 @@ -// SPDX-FileCopyrightText: Copyright 2025 Eden Emulator Project +// SPDX-FileCopyrightText: Copyright 2026 Eden Emulator Project // SPDX-License-Identifier: GPL-3.0-or-later /* This file is part of the dynarmic project. @@ -7,8 +7,7 @@ */ #include "dynarmic/common/assert.h" -#include -#include +#include "dynarmic/mcl/bit.hpp" #include "dynarmic/frontend/A32/translate/impl/a32_translate_impl.h" 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 49c5d65b3a..d7c667aecf 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 @@ -6,8 +6,7 @@ * SPDX-License-Identifier: 0BSD */ -#include -#include +#include "dynarmic/mcl/bit.hpp" #include "dynarmic/frontend/A32/translate/impl/a32_translate_impl.h" diff --git a/src/dynarmic/src/dynarmic/frontend/A32/translate/impl/misc.cpp b/src/dynarmic/src/dynarmic/frontend/A32/translate/impl/misc.cpp index ef54b66827..bb33c3c47c 100644 --- a/src/dynarmic/src/dynarmic/frontend/A32/translate/impl/misc.cpp +++ b/src/dynarmic/src/dynarmic/frontend/A32/translate/impl/misc.cpp @@ -1,9 +1,12 @@ +// SPDX-FileCopyrightText: Copyright 2026 Eden Emulator Project +// SPDX-License-Identifier: GPL-3.0-or-later + /* This file is part of the dynarmic project. * Copyright (c) 2016 MerryMage * SPDX-License-Identifier: 0BSD */ -#include +#include "dynarmic/mcl/bit.hpp" #include "dynarmic/frontend/A32/translate/impl/a32_translate_impl.h" diff --git a/src/dynarmic/src/dynarmic/frontend/A32/translate/impl/status_register_access.cpp b/src/dynarmic/src/dynarmic/frontend/A32/translate/impl/status_register_access.cpp index 8dfc64d6d7..7a0640598c 100644 --- a/src/dynarmic/src/dynarmic/frontend/A32/translate/impl/status_register_access.cpp +++ b/src/dynarmic/src/dynarmic/frontend/A32/translate/impl/status_register_access.cpp @@ -6,7 +6,7 @@ * SPDX-License-Identifier: 0BSD */ -#include +#include "dynarmic/mcl/bit.hpp" #include "dynarmic/frontend/A32/translate/impl/a32_translate_impl.h" diff --git a/src/dynarmic/src/dynarmic/frontend/A32/translate/impl/thumb16.cpp b/src/dynarmic/src/dynarmic/frontend/A32/translate/impl/thumb16.cpp index 926c499222..a8c75e22b9 100644 --- a/src/dynarmic/src/dynarmic/frontend/A32/translate/impl/thumb16.cpp +++ b/src/dynarmic/src/dynarmic/frontend/A32/translate/impl/thumb16.cpp @@ -1,4 +1,4 @@ -// SPDX-FileCopyrightText: Copyright 2025 Eden Emulator Project +// SPDX-FileCopyrightText: Copyright 2026 Eden Emulator Project // SPDX-License-Identifier: GPL-3.0-or-later /* This file is part of the dynarmic project. @@ -6,7 +6,7 @@ * SPDX-License-Identifier: 0BSD */ -#include +#include "dynarmic/mcl/bit.hpp" #include "dynarmic/frontend/A32/translate/impl/a32_translate_impl.h" #include "dynarmic/interface/A32/config.h" diff --git a/src/dynarmic/src/dynarmic/frontend/A32/translate/impl/thumb32_data_processing_plain_binary_immediate.cpp b/src/dynarmic/src/dynarmic/frontend/A32/translate/impl/thumb32_data_processing_plain_binary_immediate.cpp index 090e98d1aa..7ea31d40ee 100644 --- a/src/dynarmic/src/dynarmic/frontend/A32/translate/impl/thumb32_data_processing_plain_binary_immediate.cpp +++ b/src/dynarmic/src/dynarmic/frontend/A32/translate/impl/thumb32_data_processing_plain_binary_immediate.cpp @@ -1,4 +1,4 @@ -// SPDX-FileCopyrightText: Copyright 2025 Eden Emulator Project +// SPDX-FileCopyrightText: Copyright 2026 Eden Emulator Project // SPDX-License-Identifier: GPL-3.0-or-later /* This file is part of the dynarmic project. @@ -7,7 +7,7 @@ */ #include "dynarmic/common/assert.h" -#include +#include "dynarmic/mcl/bit.hpp" #include "dynarmic/frontend/A32/translate/impl/a32_translate_impl.h" #include "dynarmic/frontend/A32/translate/impl/common.h" diff --git a/src/dynarmic/src/dynarmic/frontend/A32/translate/impl/thumb32_load_store_dual.cpp b/src/dynarmic/src/dynarmic/frontend/A32/translate/impl/thumb32_load_store_dual.cpp index eb574d773c..e76666ecc2 100644 --- a/src/dynarmic/src/dynarmic/frontend/A32/translate/impl/thumb32_load_store_dual.cpp +++ b/src/dynarmic/src/dynarmic/frontend/A32/translate/impl/thumb32_load_store_dual.cpp @@ -1,9 +1,12 @@ +// SPDX-FileCopyrightText: Copyright 2026 Eden Emulator Project +// SPDX-License-Identifier: GPL-3.0-or-later + /* This file is part of the dynarmic project. * Copyright (c) 2021 MerryMage * SPDX-License-Identifier: 0BSD */ -#include +#include "dynarmic/mcl/bit.hpp" #include "dynarmic/frontend/A32/translate/impl/a32_translate_impl.h" #include "dynarmic/frontend/A32/translate/impl/common.h" diff --git a/src/dynarmic/src/dynarmic/frontend/A32/translate/impl/thumb32_load_store_multiple.cpp b/src/dynarmic/src/dynarmic/frontend/A32/translate/impl/thumb32_load_store_multiple.cpp index d446fbf3dd..b68a2cb7c5 100644 --- a/src/dynarmic/src/dynarmic/frontend/A32/translate/impl/thumb32_load_store_multiple.cpp +++ b/src/dynarmic/src/dynarmic/frontend/A32/translate/impl/thumb32_load_store_multiple.cpp @@ -1,9 +1,12 @@ +// SPDX-FileCopyrightText: Copyright 2026 Eden Emulator Project +// SPDX-License-Identifier: GPL-3.0-or-later + /* This file is part of the dynarmic project. * Copyright (c) 2021 MerryMage * SPDX-License-Identifier: 0BSD */ -#include +#include "dynarmic/mcl/bit.hpp" #include "dynarmic/frontend/A32/translate/impl/a32_translate_impl.h" #include "dynarmic/frontend/A32/translate/impl/common.h" diff --git a/src/dynarmic/src/dynarmic/frontend/A32/translate/translate_thumb.cpp b/src/dynarmic/src/dynarmic/frontend/A32/translate/translate_thumb.cpp index e0333e487d..309dd080f9 100644 --- a/src/dynarmic/src/dynarmic/frontend/A32/translate/translate_thumb.cpp +++ b/src/dynarmic/src/dynarmic/frontend/A32/translate/translate_thumb.cpp @@ -9,8 +9,7 @@ #include #include "dynarmic/common/assert.h" -#include -#include +#include "dynarmic/mcl/bit.hpp" #include "dynarmic/frontend/A32/a32_ir_emitter.h" #include "dynarmic/frontend/A32/a32_location_descriptor.h" diff --git a/src/dynarmic/src/dynarmic/frontend/A64/a64_location_descriptor.h b/src/dynarmic/src/dynarmic/frontend/A64/a64_location_descriptor.h index 4bfc5f890e..a8be0232ca 100644 --- a/src/dynarmic/src/dynarmic/frontend/A64/a64_location_descriptor.h +++ b/src/dynarmic/src/dynarmic/frontend/A64/a64_location_descriptor.h @@ -1,4 +1,4 @@ -// SPDX-FileCopyrightText: Copyright 2025 Eden Emulator Project +// SPDX-FileCopyrightText: Copyright 2026 Eden Emulator Project // SPDX-License-Identifier: GPL-3.0-or-later /* This file is part of the dynarmic project. @@ -13,7 +13,7 @@ #include #include -#include +#include "dynarmic/mcl/bit.hpp" #include "dynarmic/common/common_types.h" #include "dynarmic/common/fp/fpcr.h" diff --git a/src/dynarmic/src/dynarmic/frontend/A64/decoder/a64.h b/src/dynarmic/src/dynarmic/frontend/A64/decoder/a64.h index 68422ed40d..eba9d73942 100644 --- a/src/dynarmic/src/dynarmic/frontend/A64/decoder/a64.h +++ b/src/dynarmic/src/dynarmic/frontend/A64/decoder/a64.h @@ -15,7 +15,7 @@ #include #include -#include +#include "dynarmic/mcl/bit.hpp" #include "dynarmic/common/common_types.h" #include "dynarmic/frontend/decoder/decoder_detail.h" @@ -70,14 +70,15 @@ constexpr DecodeTable GetDecodeTable() { /// In practice it must always suceed, otherwise something else unrelated would have gone awry template -std::reference_wrapper> Decode(u32 instruction) { +std::optional>> Decode(u32 instruction) { alignas(64) static const auto table = GetDecodeTable(); const auto& subtable = table[detail::ToFastLookupIndex(instruction)]; auto iter = std::find_if(subtable.begin(), subtable.end(), [instruction](const auto& matcher) { return matcher.Matches(instruction); }); - DEBUG_ASSERT(iter != subtable.end()); - return std::reference_wrapper>(*iter); + return iter != subtable.end() + ? std::optional{ std::reference_wrapper>(*iter) } + : std::nullopt; } template diff --git a/src/dynarmic/src/dynarmic/frontend/A64/translate/a64_translate.cpp b/src/dynarmic/src/dynarmic/frontend/A64/translate/a64_translate.cpp index 6778d13890..4afce6bd29 100644 --- a/src/dynarmic/src/dynarmic/frontend/A64/translate/a64_translate.cpp +++ b/src/dynarmic/src/dynarmic/frontend/A64/translate/a64_translate.cpp @@ -25,7 +25,11 @@ void Translate(IR::Block& block, LocationDescriptor descriptor, MemoryReadCodeFu const u64 pc = visitor.ir.current_location->PC(); if (const auto instruction = memory_read_code(pc)) { auto decoder = Decode(*instruction); - should_continue = decoder.get().call(visitor, *instruction); + if (decoder) { + should_continue = decoder->get().call(visitor, *instruction); + } else { + should_continue = visitor.RaiseException(Exception::UnallocatedEncoding); + } } else { should_continue = visitor.RaiseException(Exception::NoExecuteFault); } @@ -45,13 +49,15 @@ bool TranslateSingleInstruction(IR::Block& block, LocationDescriptor descriptor, bool should_continue = true; auto const decoder = Decode(instruction); - should_continue = decoder.get().call(visitor, instruction); + if (decoder) { + should_continue = decoder->get().call(visitor, instruction); + } else { + should_continue = false; + } visitor.ir.current_location = visitor.ir.current_location->AdvancePC(4); block.CycleCount()++; - block.SetEndLocation(*visitor.ir.current_location); - return should_continue; } diff --git a/src/dynarmic/src/dynarmic/frontend/A64/translate/impl/impl.cpp b/src/dynarmic/src/dynarmic/frontend/A64/translate/impl/impl.cpp index de63f560bc..f3ecd7c604 100644 --- a/src/dynarmic/src/dynarmic/frontend/A64/translate/impl/impl.cpp +++ b/src/dynarmic/src/dynarmic/frontend/A64/translate/impl/impl.cpp @@ -8,9 +8,7 @@ #include "dynarmic/frontend/A64/translate/impl/impl.h" -#include -#include -#include +#include "dynarmic/mcl/bit.hpp" #include "dynarmic/ir/terminal.h" diff --git a/src/dynarmic/src/dynarmic/frontend/A64/translate/impl/simd_copy.cpp b/src/dynarmic/src/dynarmic/frontend/A64/translate/impl/simd_copy.cpp index b33bc8f5ad..9354b54fa5 100644 --- a/src/dynarmic/src/dynarmic/frontend/A64/translate/impl/simd_copy.cpp +++ b/src/dynarmic/src/dynarmic/frontend/A64/translate/impl/simd_copy.cpp @@ -1,9 +1,12 @@ +// SPDX-FileCopyrightText: Copyright 2026 Eden Emulator Project +// SPDX-License-Identifier: GPL-3.0-or-later + /* This file is part of the dynarmic project. * Copyright (c) 2018 MerryMage * SPDX-License-Identifier: 0BSD */ -#include +#include "dynarmic/mcl/bit.hpp" #include "dynarmic/frontend/A64/translate/impl/impl.h" diff --git a/src/dynarmic/src/dynarmic/frontend/A64/translate/impl/simd_modified_immediate.cpp b/src/dynarmic/src/dynarmic/frontend/A64/translate/impl/simd_modified_immediate.cpp index db8e83631a..2afece1c46 100644 --- a/src/dynarmic/src/dynarmic/frontend/A64/translate/impl/simd_modified_immediate.cpp +++ b/src/dynarmic/src/dynarmic/frontend/A64/translate/impl/simd_modified_immediate.cpp @@ -1,9 +1,12 @@ +// SPDX-FileCopyrightText: Copyright 2026 Eden Emulator Project +// SPDX-License-Identifier: GPL-3.0-or-later + /* This file is part of the dynarmic project. * Copyright (c) 2018 MerryMage * SPDX-License-Identifier: 0BSD */ -#include +#include "dynarmic/mcl/bit.hpp" #include "dynarmic/frontend/A64/translate/impl/impl.h" diff --git a/src/dynarmic/src/dynarmic/frontend/A64/translate/impl/simd_scalar_shift_by_immediate.cpp b/src/dynarmic/src/dynarmic/frontend/A64/translate/impl/simd_scalar_shift_by_immediate.cpp index 5d60cb31c3..332eb35ebe 100644 --- a/src/dynarmic/src/dynarmic/frontend/A64/translate/impl/simd_scalar_shift_by_immediate.cpp +++ b/src/dynarmic/src/dynarmic/frontend/A64/translate/impl/simd_scalar_shift_by_immediate.cpp @@ -1,9 +1,12 @@ +// SPDX-FileCopyrightText: Copyright 2026 Eden Emulator Project +// SPDX-License-Identifier: GPL-3.0-or-later + /* This file is part of the dynarmic project. * Copyright (c) 2018 MerryMage * SPDX-License-Identifier: 0BSD */ -#include +#include "dynarmic/mcl/bit.hpp" #include "dynarmic/common/fp/rounding_mode.h" #include "dynarmic/frontend/A64/translate/impl/impl.h" diff --git a/src/dynarmic/src/dynarmic/frontend/A64/translate/impl/simd_scalar_three_same.cpp b/src/dynarmic/src/dynarmic/frontend/A64/translate/impl/simd_scalar_three_same.cpp index d551605bda..ad5b89df3a 100644 --- a/src/dynarmic/src/dynarmic/frontend/A64/translate/impl/simd_scalar_three_same.cpp +++ b/src/dynarmic/src/dynarmic/frontend/A64/translate/impl/simd_scalar_three_same.cpp @@ -1,3 +1,6 @@ +// SPDX-FileCopyrightText: Copyright 2026 Eden Emulator Project +// SPDX-License-Identifier: GPL-3.0-or-later + /* This file is part of the dynarmic project. * Copyright (c) 2018 MerryMage * SPDX-License-Identifier: 0BSD @@ -5,7 +8,7 @@ #include -#include +#include "dynarmic/mcl/bit.hpp" #include "dynarmic/frontend/A64/translate/impl/impl.h" diff --git a/src/dynarmic/src/dynarmic/frontend/A64/translate/impl/simd_shift_by_immediate.cpp b/src/dynarmic/src/dynarmic/frontend/A64/translate/impl/simd_shift_by_immediate.cpp index 559721a22a..33debd1062 100644 --- a/src/dynarmic/src/dynarmic/frontend/A64/translate/impl/simd_shift_by_immediate.cpp +++ b/src/dynarmic/src/dynarmic/frontend/A64/translate/impl/simd_shift_by_immediate.cpp @@ -1,9 +1,12 @@ +// SPDX-FileCopyrightText: Copyright 2026 Eden Emulator Project +// SPDX-License-Identifier: GPL-3.0-or-later + /* This file is part of the dynarmic project. * Copyright (c) 2018 MerryMage * SPDX-License-Identifier: 0BSD */ -#include +#include "dynarmic/mcl/bit.hpp" #include "dynarmic/common/fp/rounding_mode.h" #include "dynarmic/frontend/A64/translate/impl/impl.h" diff --git a/src/dynarmic/src/dynarmic/frontend/decoder/decoder_detail.h b/src/dynarmic/src/dynarmic/frontend/decoder/decoder_detail.h index 0d9da6169c..3ab360c287 100644 --- a/src/dynarmic/src/dynarmic/frontend/decoder/decoder_detail.h +++ b/src/dynarmic/src/dynarmic/frontend/decoder/decoder_detail.h @@ -1,4 +1,4 @@ -// SPDX-FileCopyrightText: Copyright 2025 Eden Emulator Project +// SPDX-FileCopyrightText: Copyright 2026 Eden Emulator Project // SPDX-License-Identifier: GPL-3.0-or-later /* This file is part of the dynarmic project. @@ -13,8 +13,8 @@ #include #include "dynarmic/common/assert.h" -#include -#include +#include "dynarmic/mcl/bit.hpp" +#include "dynarmic/mcl/function_info.hpp" namespace Dynarmic::Decoder { namespace detail { @@ -75,11 +75,11 @@ struct detail { /// An argument is specified by a continuous string of the same character. template static consteval auto GetArgInfo(std::array bitstring) { + //static_assert(N > 0, "unexpected field"); std::array masks = {}; std::array shifts = {}; size_t arg_index = 0; char ch = 0; - for (size_t i = 0; i < opcode_bitsize; i++) { if (bitstring[i] == '0' || bitstring[i] == '1' || bitstring[i] == '-') { if (ch != 0) { @@ -93,17 +93,10 @@ struct detail { ch = bitstring[i]; arg_index++; } - - if constexpr (N > 0) { - const size_t bit_position = opcode_bitsize - i - 1; - if (arg_index >= N) - throw std::out_of_range("Unexpected field"); - - masks[arg_index] |= static_cast(1) << bit_position; - shifts[arg_index] = bit_position; - } else { - throw std::out_of_range("Unexpected field"); - } + const size_t bit_position = opcode_bitsize - i - 1; + //static_assert(arg_index >= N, "unexpected field"); + masks[arg_index] |= opcode_type(1) << bit_position; + shifts[arg_index] = bit_position; } } #if !defined(DYNARMIC_IGNORE_ASSERTS) && !defined(__ANDROID__) diff --git a/src/dynarmic/src/dynarmic/frontend/imm.cpp b/src/dynarmic/src/dynarmic/frontend/imm.cpp index 95e24206d7..aeb7b5d3f6 100644 --- a/src/dynarmic/src/dynarmic/frontend/imm.cpp +++ b/src/dynarmic/src/dynarmic/frontend/imm.cpp @@ -1,4 +1,4 @@ -// SPDX-FileCopyrightText: Copyright 2025 Eden Emulator Project +// SPDX-FileCopyrightText: Copyright 2026 Eden Emulator Project // SPDX-License-Identifier: GPL-3.0-or-later /* This file is part of the dynarmic project. @@ -9,7 +9,7 @@ #include "dynarmic/frontend/imm.h" #include "dynarmic/common/assert.h" -#include +#include "dynarmic/mcl/bit.hpp" #include "dynarmic/common/common_types.h" namespace Dynarmic { diff --git a/src/dynarmic/src/dynarmic/frontend/imm.h b/src/dynarmic/src/dynarmic/frontend/imm.h index 4e277ede3b..3a6c10316a 100644 --- a/src/dynarmic/src/dynarmic/frontend/imm.h +++ b/src/dynarmic/src/dynarmic/frontend/imm.h @@ -1,4 +1,4 @@ -// SPDX-FileCopyrightText: Copyright 2025 Eden Emulator Project +// SPDX-FileCopyrightText: Copyright 2026 Eden Emulator Project // SPDX-License-Identifier: GPL-3.0-or-later /* This file is part of the dynarmic project. @@ -11,8 +11,7 @@ #include #include "dynarmic/common/assert.h" -#include -#include +#include "dynarmic/mcl/bit.hpp" #include "dynarmic/common/common_types.h" #include "dynarmic/common/math_util.h" diff --git a/src/dynarmic/src/dynarmic/ir/basic_block.h b/src/dynarmic/src/dynarmic/ir/basic_block.h index 4044005bd0..bbf1319957 100644 --- a/src/dynarmic/src/dynarmic/ir/basic_block.h +++ b/src/dynarmic/src/dynarmic/ir/basic_block.h @@ -16,7 +16,7 @@ #include #include #include -#include +#include "dynarmic/mcl/intrusive_list.hpp" #include "dynarmic/common/common_types.h" #include "dynarmic/ir/location_descriptor.h" diff --git a/src/dynarmic/src/dynarmic/ir/ir_emitter.h b/src/dynarmic/src/dynarmic/ir/ir_emitter.h index 2b5c7d5cdd..ed95c8b5be 100644 --- a/src/dynarmic/src/dynarmic/ir/ir_emitter.h +++ b/src/dynarmic/src/dynarmic/ir/ir_emitter.h @@ -12,7 +12,7 @@ #include "dynarmic/common/common_types.h" #include "dynarmic/common/assert.h" -#include +#include "dynarmic/mcl/bit.hpp" #include "dynarmic/ir/opcodes.h" #include "dynarmic/ir/acc_type.h" @@ -228,7 +228,7 @@ public: } ResultAndCarry RotateRight(const U32& value_in, const U8& shift_amount, const U1& carry_in) { - const auto result = Inst(Opcode::RotateRight32, value_in, shift_amount, carry_in); + const auto result = Inst(Opcode::BitRotateRight32, value_in, shift_amount, carry_in); const auto carry_out = Inst(Opcode::GetCarryFromOp, result); return {result, carry_out}; } @@ -265,9 +265,9 @@ public: U32U64 RotateRight(const U32U64& value_in, const U8& shift_amount) { if (value_in.GetType() == Type::U32) { - return Inst(Opcode::RotateRight32, value_in, shift_amount, Imm1(0)); + return Inst(Opcode::BitRotateRight32, value_in, shift_amount, Imm1(0)); } else { - return Inst(Opcode::RotateRight64, value_in, shift_amount); + return Inst(Opcode::BitRotateRight64, value_in, shift_amount); } } diff --git a/src/dynarmic/src/dynarmic/ir/microinstruction.h b/src/dynarmic/src/dynarmic/ir/microinstruction.h index 1700eb110b..fb3ac1f49a 100644 --- a/src/dynarmic/src/dynarmic/ir/microinstruction.h +++ b/src/dynarmic/src/dynarmic/ir/microinstruction.h @@ -10,7 +10,7 @@ #include -#include +#include "dynarmic/mcl/intrusive_list.hpp" #include "dynarmic/common/common_types.h" #include "dynarmic/ir/value.h" diff --git a/src/dynarmic/src/dynarmic/ir/opcodes.h b/src/dynarmic/src/dynarmic/ir/opcodes.h index 5886eb6a20..cb0c2db8a4 100644 --- a/src/dynarmic/src/dynarmic/ir/opcodes.h +++ b/src/dynarmic/src/dynarmic/ir/opcodes.h @@ -1,4 +1,4 @@ -// SPDX-FileCopyrightText: Copyright 2025 Eden Emulator Project +// SPDX-FileCopyrightText: Copyright 2026 Eden Emulator Project // SPDX-License-Identifier: GPL-3.0-or-later /* This file is part of the dynarmic project. @@ -45,8 +45,8 @@ constexpr bool IsArithmeticShift(const Opcode op) noexcept { /// @brief Determines whether or not this instruction performs a logical shift. constexpr bool IsCircularShift(const Opcode op) noexcept { - return op == Opcode::RotateRight32 - || op == Opcode::RotateRight64 + return op == Opcode::BitRotateRight32 + || op == Opcode::BitRotateRight64 || op == Opcode::RotateRightExtended; } diff --git a/src/dynarmic/src/dynarmic/ir/opcodes.inc b/src/dynarmic/src/dynarmic/ir/opcodes.inc index b05220834d..6f57f278a3 100644 --- a/src/dynarmic/src/dynarmic/ir/opcodes.inc +++ b/src/dynarmic/src/dynarmic/ir/opcodes.inc @@ -46,8 +46,9 @@ OPCODE(LogicalShiftRight32, U32, U32, OPCODE(LogicalShiftRight64, U64, U64, U8 ) OPCODE(ArithmeticShiftRight32, U32, U32, U8, U1 ) OPCODE(ArithmeticShiftRight64, U64, U64, U8 ) -OPCODE(RotateRight32, U32, U32, U8, U1 ) -OPCODE(RotateRight64, U64, U64, U8 ) +// windows.h defines RotateRight64 and RotateRight32 +OPCODE(BitRotateRight32, U32, U32, U8, U1 ) +OPCODE(BitRotateRight64, U64, U64, U8 ) OPCODE(RotateRightExtended, U32, U32, U1 ) OPCODE(LogicalShiftLeftMasked32, U32, U32, U32 ) OPCODE(LogicalShiftLeftMasked64, U64, U64, U64 ) diff --git a/src/dynarmic/src/dynarmic/ir/opt_passes.cpp b/src/dynarmic/src/dynarmic/ir/opt_passes.cpp index f22e8aaa69..999d4c49bc 100644 --- a/src/dynarmic/src/dynarmic/ir/opt_passes.cpp +++ b/src/dynarmic/src/dynarmic/ir/opt_passes.cpp @@ -27,8 +27,8 @@ #include "dynarmic/ir/opcodes.h" #include "dynarmic/ir/opt_passes.h" #include "dynarmic/ir/type.h" -#include "mcl/bit/swap.hpp" -#include "mcl/bit/rotate.hpp" +#include "dynarmic/mcl/bit.hpp" +#include "dynarmic/mcl/bit.hpp" namespace Dynarmic::Optimization { @@ -1072,12 +1072,12 @@ static void ConstantPropagation(IR::Block& block) { ReplaceUsesWith(inst, false, Safe::ArithmeticShiftRight(inst.GetArg(0).GetU64(), inst.GetArg(1).GetU8())); } break; - case Op::RotateRight32: + case Op::BitRotateRight32: if (FoldShifts(inst)) { ReplaceUsesWith(inst, true, mcl::bit::rotate_right(inst.GetArg(0).GetU32(), inst.GetArg(1).GetU8())); } break; - case Op::RotateRight64: + case Op::BitRotateRight64: if (FoldShifts(inst)) { ReplaceUsesWith(inst, false, mcl::bit::rotate_right(inst.GetArg(0).GetU64(), inst.GetArg(1).GetU8())); } diff --git a/src/dynarmic/src/dynarmic/ir/value.cpp b/src/dynarmic/src/dynarmic/ir/value.cpp index 59b17b5a7b..451036b1fd 100644 --- a/src/dynarmic/src/dynarmic/ir/value.cpp +++ b/src/dynarmic/src/dynarmic/ir/value.cpp @@ -1,4 +1,4 @@ -// SPDX-FileCopyrightText: Copyright 2025 Eden Emulator Project +// SPDX-FileCopyrightText: Copyright 2026 Eden Emulator Project // SPDX-License-Identifier: GPL-3.0-or-later /* This file is part of the dynarmic project. @@ -9,7 +9,7 @@ #include "dynarmic/ir/value.h" #include "dynarmic/common/assert.h" -#include +#include "dynarmic/mcl/bit.hpp" #include "dynarmic/ir/microinstruction.h" #include "dynarmic/ir/opcodes.h" diff --git a/src/dynarmic/src/dynarmic/mcl/bit.hpp b/src/dynarmic/src/dynarmic/mcl/bit.hpp new file mode 100644 index 0000000000..1ef9880a5f --- /dev/null +++ b/src/dynarmic/src/dynarmic/mcl/bit.hpp @@ -0,0 +1,311 @@ +// SPDX-FileCopyrightText: Copyright 2026 Eden Emulator Project +// SPDX-License-Identifier: GPL-3.0-or-later +// SPDX-FileCopyrightText: Copyright 2022 merryhime +// SPDX-License-Identifier: MIT + +#pragma once + +#include +#include +#include + +#include "dynarmic/common/common_types.h" +#include "dynarmic/common/assert.h" + +namespace mcl { +namespace detail { +template +concept SameHelper = std::is_same_v; +} // namespace detail +template +concept SameAs = detail::SameHelper && detail::SameHelper; +template +concept IsAnyOf = (SameAs || ...); +/// Integral upon which bit operations can be safely performed. +template +concept BitIntegral = IsAnyOf; + +template +constexpr std::size_t bitsizeof = CHAR_BIT * sizeof(T); + +} // namespace mcl + +namespace mcl::bit { + +constexpr u16 swap_bytes_16(u16 value) { + return static_cast(u32{value} >> 8 | u32{value} << 8); +} + +constexpr u32 swap_bytes_32(u32 value) { + return ((value & 0xff000000u) >> 24) + | ((value & 0x00ff0000u) >> 8) + | ((value & 0x0000ff00u) << 8) + | ((value & 0x000000ffu) << 24); +} + +constexpr u64 swap_bytes_64(u64 value) { + return ((value & 0xff00000000000000ull) >> 56) + | ((value & 0x00ff000000000000ull) >> 40) + | ((value & 0x0000ff0000000000ull) >> 24) + | ((value & 0x000000ff00000000ull) >> 8) + | ((value & 0x00000000ff000000ull) << 8) + | ((value & 0x0000000000ff0000ull) << 24) + | ((value & 0x000000000000ff00ull) << 40) + | ((value & 0x00000000000000ffull) << 56); +} + +constexpr u32 swap_halves_32(u32 value) { + return ((value & 0xffff0000u) >> 16) + | ((value & 0x0000ffffu) << 16); +} + +constexpr u64 swap_halves_64(u64 value) { + return ((value & 0xffff000000000000ull) >> 48) + | ((value & 0x0000ffff00000000ull) >> 16) + | ((value & 0x00000000ffff0000ull) << 16) + | ((value & 0x000000000000ffffull) << 48); +} + +constexpr u64 swap_words_64(u64 value) { + return ((value & 0xffffffff00000000ull) >> 32) + | ((value & 0x00000000ffffffffull) << 32); +} + +template +constexpr T rotate_right(T x, size_t amount) { + amount %= bitsizeof; + if (amount == 0) { + return x; + } + return static_cast((x >> amount) | (x << (bitsizeof - amount))); +} + +template +constexpr T rotate_left(T x, size_t amount) { + amount %= bitsizeof; + if (amount == 0) { + return x; + } + return static_cast((x << amount) | (x >> (bitsizeof - amount))); +} + +/// Create a mask with `count` number of one bits. +template +constexpr T ones() { + static_assert(count <= bitsizeof, "count larger than bitsize of T"); + + if constexpr (count == 0) { + return 0; + } else { + return static_cast(~static_cast(0)) >> (bitsizeof - count); + } +} + +/// Create a mask with `count` number of one bits. +template +constexpr T ones(size_t count) { + ASSERT(count <= bitsizeof && "count larger than bitsize of T"); + if (count == 0) { + return 0; + } + return static_cast(~static_cast(0)) >> (bitsizeof - count); +} + +/// Create a mask of type T for bits [begin_bit, end_bit] inclusive. +template +constexpr T mask() { + static_assert(begin_bit <= end_bit, "invalid bit range (position of beginning bit cannot be greater than that of end bit)"); + static_assert(begin_bit < bitsizeof, "begin_bit must be smaller than size of T"); + static_assert(end_bit < bitsizeof, "end_bit must be smaller than size of T"); + + return ones() << begin_bit; +} + +/// Create a mask of type T for bits [begin_bit, end_bit] inclusive. +template +constexpr T mask(size_t begin_bit, size_t end_bit) { + ASSERT(begin_bit <= end_bit && "invalid bit range (position of beginning bit cannot be greater than that of end bit)"); + ASSERT(begin_bit < bitsizeof && "begin_bit must be smaller than size of T"); + ASSERT(end_bit < bitsizeof && "end_bit must be smaller than size of T"); + return ones(end_bit - begin_bit + 1) << begin_bit; +} + +/// Extract bits [begin_bit, end_bit] inclusive from value of type T. +template +constexpr T get_bits(T value) { + constexpr T m = mask(); + return (value & m) >> begin_bit; +} + +/// Extract bits [begin_bit, end_bit] inclusive from value of type T. +template +constexpr T get_bits(size_t begin_bit, size_t end_bit, T value) { + const T m = mask(begin_bit, end_bit); + return (value & m) >> begin_bit; +} + +/// Clears bits [begin_bit, end_bit] inclusive of value of type T. +template +constexpr T clear_bits(T value) { + constexpr T m = mask(); + return value & ~m; +} + +/// Clears bits [begin_bit, end_bit] inclusive of value of type T. +template +constexpr T clear_bits(size_t begin_bit, size_t end_bit, T value) { + const T m = mask(begin_bit, end_bit); + return value & ~m; +} + +/// Modifies bits [begin_bit, end_bit] inclusive of value of type T. +template +constexpr T set_bits(T value, T new_bits) { + constexpr T m = mask(); + return (value & ~m) | ((new_bits << begin_bit) & m); +} + +/// Modifies bits [begin_bit, end_bit] inclusive of value of type T. +template +constexpr T set_bits(size_t begin_bit, size_t end_bit, T value, T new_bits) { + const T m = mask(begin_bit, end_bit); + return (value & ~m) | ((new_bits << begin_bit) & m); +} + +/// Extract bit at bit_position from value of type T. +template +constexpr bool get_bit(T value) { + constexpr T m = mask(); + return (value & m) != 0; +} + +/// Extract bit at bit_position from value of type T. +template +constexpr bool get_bit(size_t bit_position, T value) { + const T m = mask(bit_position, bit_position); + return (value & m) != 0; +} + +/// Clears bit at bit_position of value of type T. +template +constexpr T clear_bit(T value) { + constexpr T m = mask(); + return value & ~m; +} + +/// Clears bit at bit_position of value of type T. +template +constexpr T clear_bit(size_t bit_position, T value) { + const T m = mask(bit_position, bit_position); + return value & ~m; +} + +/// Modifies bit at bit_position of value of type T. +template +constexpr T set_bit(T value, bool new_bit) { + constexpr T m = mask(); + return (value & ~m) | (new_bit ? m : static_cast(0)); +} + +/// Modifies bit at bit_position of value of type T. +template +constexpr T set_bit(size_t bit_position, T value, bool new_bit) { + const T m = mask(bit_position, bit_position); + return (value & ~m) | (new_bit ? m : static_cast(0)); +} + +/// Sign-extends a value that has bit_count bits to the full bitwidth of type T. +template +constexpr T sign_extend(T value) { + static_assert(bit_count != 0, "cannot sign-extend zero-sized value"); + + using S = std::make_signed_t; + constexpr size_t shift_amount = bitsizeof - bit_count; + return static_cast(static_cast(value << shift_amount) >> shift_amount); +} + +/// Sign-extends a value that has bit_count bits to the full bitwidth of type T. +template +constexpr T sign_extend(size_t bit_count, T value) { + ASSERT(bit_count != 0 && "cannot sign-extend zero-sized value"); + using S = std::make_signed_t; + const size_t shift_amount = bitsizeof - bit_count; + return T(S(value << shift_amount) >> shift_amount); +} + +/// Replicate an element across a value of type T. +template +constexpr T replicate_element(T value) { + static_assert(element_size <= bitsizeof, "element_size is too large"); + static_assert(bitsizeof % element_size == 0, "bitsize of T not divisible by element_size"); + + if constexpr (element_size == bitsizeof) { + return value; + } else { + return replicate_element(static_cast(value | (value << element_size))); + } +} + +/// Replicate an element of type U across a value of type T. +template +constexpr T replicate_element(T value) { + static_assert(bitsizeof <= bitsizeof, "element_size is too large"); + + return replicate_element, T>(value); +} + +/// Replicate an element across a value of type T. +template +constexpr T replicate_element(size_t element_size, T value) { + ASSERT(element_size <= bitsizeof && "element_size is too large"); + ASSERT(bitsizeof % element_size == 0 && "bitsize of T not divisible by element_size"); + if (element_size == bitsizeof) + return value; + return replicate_element(element_size * 2, static_cast(value | (value << element_size))); +} + +template +constexpr bool most_significant_bit(T value) { + return get_bit - 1, T>(value); +} + +template +inline size_t count_ones(T x) { + return std::bitset>(x).count(); +} + +template +constexpr size_t count_leading_zeros(T x) { + size_t result = bitsizeof; + while (x != 0) { + x >>= 1; + result--; + } + return result; +} + +template +constexpr int highest_set_bit(T x) { + int result = -1; + while (x != 0) { + x >>= 1; + result++; + } + return result; +} + +template +constexpr size_t lowest_set_bit(T x) { + if (x == 0) { + return bitsizeof; + } + + size_t result = 0; + while ((x & 1) == 0) { + x >>= 1; + result++; + } + return result; +} + +} // namespace mcl::bit diff --git a/src/dynarmic/src/dynarmic/mcl/function_info.hpp b/src/dynarmic/src/dynarmic/mcl/function_info.hpp new file mode 100644 index 0000000000..452bd88bfc --- /dev/null +++ b/src/dynarmic/src/dynarmic/mcl/function_info.hpp @@ -0,0 +1,73 @@ +// SPDX-FileCopyrightText: Copyright 2026 Eden Emulator Project +// SPDX-License-Identifier: GPL-3.0-or-later +// SPDX-FileCopyrightText: Copyright 2022 merryhime +// SPDX-License-Identifier: MIT + +#pragma once + +#include +#include + +namespace mcl { + +/// Contains a list of types +template +struct type_list {}; + +template +struct function_info : function_info {}; + +template +struct function_info { + using return_type = R; + using parameter_list = type_list; + static constexpr std::size_t parameter_count = sizeof...(As); + + using equivalent_function_type = R(As...); + + template + struct parameter { + static_assert(I < parameter_count, "Non-existent parameter"); + using type = std::tuple_element_t>; + }; +}; + +template +struct function_info : function_info {}; + +template +struct function_info : function_info { + using class_type = C; + + using equivalent_function_type_with_class = R(C*, As...); +}; + +template +struct function_info : function_info { + using class_type = C; + + using equivalent_function_type_with_class = R(C*, As...); +}; + +template +constexpr size_t parameter_count_v = function_info::parameter_count; + +template +using parameter_list = typename function_info::parameter_list; + +template +using get_parameter = typename function_info::template parameter::type; + +template +using equivalent_function_type = typename function_info::equivalent_function_type; + +template +using equivalent_function_type_with_class = typename function_info::equivalent_function_type_with_class; + +template +using return_type = typename function_info::return_type; + +template +using class_type = typename function_info::class_type; + +} // namespace mcl diff --git a/src/dynarmic/src/dynarmic/mcl/integer_of_size.hpp b/src/dynarmic/src/dynarmic/mcl/integer_of_size.hpp new file mode 100644 index 0000000000..8bdecc955d --- /dev/null +++ b/src/dynarmic/src/dynarmic/mcl/integer_of_size.hpp @@ -0,0 +1,49 @@ +// SPDX-FileCopyrightText: Copyright 2026 Eden Emulator Project +// SPDX-License-Identifier: GPL-3.0-or-later +// SPDX-FileCopyrightText: Copyright 2022 merryhime +// SPDX-License-Identifier: MIT + +#pragma once + +#include "dynarmic/common/common_types.h" + +namespace mcl { + +namespace detail { + +template +struct integer_of_size_impl {}; + +template<> +struct integer_of_size_impl<8> { + using unsigned_type = u8; + using signed_type = s8; +}; + +template<> +struct integer_of_size_impl<16> { + using unsigned_type = u16; + using signed_type = s16; +}; + +template<> +struct integer_of_size_impl<32> { + using unsigned_type = u32; + using signed_type = s32; +}; + +template<> +struct integer_of_size_impl<64> { + using unsigned_type = u64; + using signed_type = s64; +}; + +} // namespace detail + +template +using unsigned_integer_of_size = typename detail::integer_of_size_impl::unsigned_type; + +template +using signed_integer_of_size = typename detail::integer_of_size_impl::signed_type; + +} // namespace mcl diff --git a/src/dynarmic/src/dynarmic/mcl/intrusive_list.hpp b/src/dynarmic/src/dynarmic/mcl/intrusive_list.hpp new file mode 100644 index 0000000000..3b1c1d6699 --- /dev/null +++ b/src/dynarmic/src/dynarmic/mcl/intrusive_list.hpp @@ -0,0 +1,408 @@ +// SPDX-FileCopyrightText: Copyright 2026 Eden Emulator Project +// SPDX-License-Identifier: GPL-3.0-or-later +// SPDX-FileCopyrightText: Copyright 2022 merryhime +// SPDX-License-Identifier: MIT + +#pragma once + +#include +#include +#include +#include +#include "dynarmic/common/assert.h" + +namespace mcl { + +template +class intrusive_list; +template +class intrusive_list_iterator; + +template +class intrusive_list_node { +public: + bool is_sentinel() const + { + return is_sentinel_; + } + +protected: + intrusive_list_node* next = nullptr; + intrusive_list_node* prev = nullptr; + bool is_sentinel_ = false; + + friend class intrusive_list; + friend class intrusive_list_iterator; + friend class intrusive_list_iterator; +}; + +template +class intrusive_list_sentinel final : public intrusive_list_node { + using intrusive_list_node::next; + using intrusive_list_node::prev; + using intrusive_list_node::is_sentinel_; + +public: + intrusive_list_sentinel() + { + next = this; + prev = this; + is_sentinel_ = true; + } +}; + +template +class intrusive_list_iterator { +public: + using iterator_category = std::bidirectional_iterator_tag; + using difference_type = std::ptrdiff_t; + using value_type = T; + using pointer = value_type*; + using const_pointer = const value_type*; + using reference = value_type&; + using const_reference = const value_type&; + + // If value_type is const, we want "const intrusive_list_node", not "intrusive_list_node" + using node_type = std::conditional_t::value, + const intrusive_list_node>, + intrusive_list_node>; + using node_pointer = node_type*; + using node_reference = node_type&; + + intrusive_list_iterator() = default; + intrusive_list_iterator(const intrusive_list_iterator& other) = default; + intrusive_list_iterator& operator=(const intrusive_list_iterator& other) = default; + + explicit intrusive_list_iterator(node_pointer list_node) + : node(list_node) {} + explicit intrusive_list_iterator(pointer data) + : node(data) {} + explicit intrusive_list_iterator(reference data) + : node(&data) {} + + intrusive_list_iterator& operator++() + { + node = node->next; + return *this; + } + intrusive_list_iterator& operator--() + { + node = node->prev; + return *this; + } + intrusive_list_iterator operator++(int) + { + intrusive_list_iterator it(*this); + ++*this; + return it; + } + intrusive_list_iterator operator--(int) + { + intrusive_list_iterator it(*this); + --*this; + return it; + } + + bool operator==(const intrusive_list_iterator& other) const + { + return node == other.node; + } + bool operator!=(const intrusive_list_iterator& other) const + { + return !operator==(other); + } + + reference operator*() const + { + DEBUG_ASSERT(!node->is_sentinel()); + return static_cast(*node); + } + pointer operator->() const + { + return std::addressof(operator*()); + } + + node_pointer AsNodePointer() const + { + return node; + } + +private: + friend class intrusive_list; + node_pointer node = nullptr; +}; + +template +class intrusive_list { +public: + using difference_type = std::ptrdiff_t; + using size_type = std::size_t; + using value_type = T; + using pointer = value_type*; + using const_pointer = const value_type*; + using reference = value_type&; + using const_reference = const value_type&; + using iterator = intrusive_list_iterator; + using const_iterator = intrusive_list_iterator; + using reverse_iterator = std::reverse_iterator; + using const_reverse_iterator = std::reverse_iterator; + + /** + * Inserts a node at the given location indicated by an iterator. + * + * @param location The location to insert the node. + * @param new_node The node to add. + */ + iterator insert(iterator location, pointer new_node) + { + return insert_before(location, new_node); + } + + /** + * Inserts a node at the given location, moving the previous + * node occupant ahead of the one inserted. + * + * @param location The location to insert the new node. + * @param new_node The node to insert into the list. + */ + iterator insert_before(iterator location, pointer new_node) + { + auto existing_node = location.AsNodePointer(); + + new_node->next = existing_node; + new_node->prev = existing_node->prev; + existing_node->prev->next = new_node; + existing_node->prev = new_node; + + return iterator(new_node); + } + + /** + * Inserts a new node into the list ahead of the position indicated. + * + * @param position Location to insert the node in front of. + * @param new_node The node to be inserted into the list. + */ + iterator insert_after(iterator position, pointer new_node) + { + if (empty()) + return insert(begin(), new_node); + + return insert(++position, new_node); + } + + /** + * Add an entry to the start of the list. + * @param node Node to add to the list. + */ + void push_front(pointer node) + { + insert(begin(), node); + } + + /** + * Add an entry to the end of the list + * @param node Node to add to the list. + */ + void push_back(pointer node) + { + insert(end(), node); + } + + /** + * Erases the node at the front of the list. + * @note Must not be called on an empty list. + */ + void pop_front() + { + DEBUG_ASSERT(!empty()); + erase(begin()); + } + + /** + * Erases the node at the back of the list. + * @note Must not be called on an empty list. + */ + void pop_back() + { + DEBUG_ASSERT(!empty()); + erase(--end()); + } + + /** + * Removes a node from this list + * @param it An iterator that points to the node to remove from list. + */ + pointer remove(iterator& it) + { + DEBUG_ASSERT(it != end()); + + pointer node = &*it++; + + node->prev->next = node->next; + node->next->prev = node->prev; +#if !defined(NDEBUG) + node->next = nullptr; + node->prev = nullptr; +#endif + + return node; + } + + /** + * Removes a node from this list + * @param it A constant iterator that points to the node to remove from list. + */ + pointer remove(const iterator& it) + { + iterator copy = it; + return remove(copy); + } + + /** + * Removes a node from this list. + * @param node A pointer to the node to remove. + */ + pointer remove(pointer node) + { + return remove(iterator(node)); + } + + /** + * Removes a node from this list. + * @param node A reference to the node to remove. + */ + pointer remove(reference node) + { + return remove(iterator(node)); + } + + /** + * Is this list empty? + * @returns true if there are no nodes in this list. + */ + bool empty() const + { + return root->next == root.get(); + } + + /** + * Gets the total number of elements within this list. + * @return the number of elements in this list. + */ + size_type size() const + { + return static_cast(std::distance(begin(), end())); + } + + /** + * Retrieves a reference to the node at the front of the list. + * @note Must not be called on an empty list. + */ + reference front() + { + DEBUG_ASSERT(!empty()); + return *begin(); + } + + /** + * Retrieves a constant reference to the node at the front of the list. + * @note Must not be called on an empty list. + */ + const_reference front() const + { + DEBUG_ASSERT(!empty()); + return *begin(); + } + + /** + * Retrieves a reference to the node at the back of the list. + * @note Must not be called on an empty list. + */ + reference back() + { + DEBUG_ASSERT(!empty()); + return *--end(); + } + + /** + * Retrieves a constant reference to the node at the back of the list. + * @note Must not be called on an empty list. + */ + const_reference back() const + { + DEBUG_ASSERT(!empty()); + return *--end(); + } + + // Iterator interface + iterator begin() { return iterator(root->next); } + const_iterator begin() const { return const_iterator(root->next); } + const_iterator cbegin() const { return begin(); } + + iterator end() { return iterator(root.get()); } + const_iterator end() const { return const_iterator(root.get()); } + const_iterator cend() const { return end(); } + + reverse_iterator rbegin() { return reverse_iterator(end()); } + const_reverse_iterator rbegin() const { return const_reverse_iterator(end()); } + const_reverse_iterator crbegin() const { return rbegin(); } + + reverse_iterator rend() { return reverse_iterator(begin()); } + const_reverse_iterator rend() const { return const_reverse_iterator(begin()); } + const_reverse_iterator crend() const { return rend(); } + + /** + * Erases a node from the list, indicated by an iterator. + * @param it The iterator that points to the node to erase. + */ + iterator erase(iterator it) + { + remove(it); + return it; + } + + /** + * Erases a node from this list. + * @param node A pointer to the node to erase from this list. + */ + iterator erase(pointer node) + { + return erase(iterator(node)); + } + + /** + * Erases a node from this list. + * @param node A reference to the node to erase from this list. + */ + iterator erase(reference node) + { + return erase(iterator(node)); + } + + /** + * Exchanges contents of this list with another list instance. + * @param other The other list to swap with. + */ + void swap(intrusive_list& other) noexcept + { + root.swap(other.root); + } + +private: + std::shared_ptr> root = std::make_shared>(); +}; + +/** + * Exchanges contents of an intrusive list with another intrusive list. + * @tparam T The type of data being kept track of by the lists. + * @param lhs The first list. + * @param rhs The second list. + */ +template +void swap(intrusive_list& lhs, intrusive_list& rhs) noexcept +{ + lhs.swap(rhs); +} + +} // namespace mcl diff --git a/src/dynarmic/src/dynarmic/mcl/is_instance_of_template.hpp b/src/dynarmic/src/dynarmic/mcl/is_instance_of_template.hpp new file mode 100644 index 0000000000..0cb143430d --- /dev/null +++ b/src/dynarmic/src/dynarmic/mcl/is_instance_of_template.hpp @@ -0,0 +1,35 @@ +// SPDX-FileCopyrightText: Copyright 2026 Eden Emulator Project +// SPDX-License-Identifier: GPL-3.0-or-later +// SPDX-FileCopyrightText: Copyright 2022 merryhime +// SPDX-License-Identifier: MIT + +#pragma once + +#include +#include + +namespace mcl { + +/// A metavalue (of type VT and value v). +template using value = std::integral_constant; +/// A metavalue of type size_t (and value v). +template using size_value = value; +/// A metavalue of type bool (and value v). (Aliases to std::bool_constant.) +template using bool_value = value; +/// true metavalue (Aliases to std::true_type). +using true_type = bool_value; +/// false metavalue (Aliases to std::false_type). +using false_type = bool_value; + +/// Is type T an instance of template class C? +template class, class> +struct is_instance_of_template : false_type {}; + +template class C, class... As> +struct is_instance_of_template> : true_type {}; + +/// Is type T an instance of template class C? +template class C, class T> +constexpr bool is_instance_of_template_v = is_instance_of_template::value; + +} // namespace mcl diff --git a/src/dynarmic/tests/A32/fuzz_arm.cpp b/src/dynarmic/tests/A32/fuzz_arm.cpp index fd17b3bd01..e9834a6663 100644 --- a/src/dynarmic/tests/A32/fuzz_arm.cpp +++ b/src/dynarmic/tests/A32/fuzz_arm.cpp @@ -15,20 +15,17 @@ #include #include -#include -#include -#include +#include "dynarmic/mcl/bit.hpp" #include "dynarmic/common/common_types.h" -#include "../fuzz_util.h" -#include "../rand_int.h" -#include "../unicorn_emu/a32_unicorn.h" -#include "./testenv.h" -#include "../native/testenv.h" +#include "dynarmic/tests/fuzz_util.h" +#include "dynarmic/tests/rand_int.h" +#include "dynarmic/tests/unicorn_emu/a32_unicorn.h" +#include "dynarmic/tests/A32/testenv.h" +#include "dynarmic/tests/native/testenv.h" #include "dynarmic/common/fp/fpcr.h" #include "dynarmic/common/fp/fpsr.h" #include "dynarmic/common/llvm_disassemble.h" -#include "dynarmic/common/variant_util.h" #include "dynarmic/frontend/A32/ITState.h" #include "dynarmic/frontend/A32/a32_location_descriptor.h" #include "dynarmic/frontend/A32/a32_types.h" @@ -357,67 +354,67 @@ static void RunTestInstance(Dynarmic::A32::Jit& jit, uni_env.ticks_left = instructions.size(); // Unicorn counts thumb instructions weirdly. uni.Run(); - SCOPE_FAIL { - fmt::print("Instruction Listing:\n"); - fmt::print("{}\n", Common::DisassembleAArch32(std::is_same_v, initial_pc, (const u8*)instructions.data(), instructions.size() * sizeof(instructions[0]))); + // SCOPE_FAIL { + // fmt::print("Instruction Listing:\n"); + // fmt::print("{}\n", Common::DisassembleAArch32(std::is_same_v, initial_pc, (const u8*)instructions.data(), instructions.size() * sizeof(instructions[0]))); - fmt::print("Initial register listing:\n"); - for (size_t i = 0; i < regs.size(); ++i) { - fmt::print("{:3s}: {:08x}\n", static_cast(i), regs[i]); - } - for (size_t i = 0; i < vecs.size(); ++i) { - fmt::print("{:3s}: {:08x}\n", static_cast(i), vecs[i]); - } - fmt::print("cpsr {:08x}\n", cpsr); - fmt::print("fpcr {:08x}\n", fpscr); - fmt::print("fpcr.AHP {}\n", FP::FPCR{fpscr}.AHP()); - fmt::print("fpcr.DN {}\n", FP::FPCR{fpscr}.DN()); - fmt::print("fpcr.FZ {}\n", FP::FPCR{fpscr}.FZ()); - fmt::print("fpcr.RMode {}\n", static_cast(FP::FPCR{fpscr}.RMode())); - fmt::print("fpcr.FZ16 {}\n", FP::FPCR{fpscr}.FZ16()); - fmt::print("\n"); + // fmt::print("Initial register listing:\n"); + // for (size_t i = 0; i < regs.size(); ++i) { + // fmt::print("{:3s}: {:08x}\n", static_cast(i), regs[i]); + // } + // for (size_t i = 0; i < vecs.size(); ++i) { + // fmt::print("{:3s}: {:08x}\n", static_cast(i), vecs[i]); + // } + // fmt::print("cpsr {:08x}\n", cpsr); + // fmt::print("fpcr {:08x}\n", fpscr); + // fmt::print("fpcr.AHP {}\n", FP::FPCR{fpscr}.AHP()); + // fmt::print("fpcr.DN {}\n", FP::FPCR{fpscr}.DN()); + // fmt::print("fpcr.FZ {}\n", FP::FPCR{fpscr}.FZ()); + // fmt::print("fpcr.RMode {}\n", static_cast(FP::FPCR{fpscr}.RMode())); + // fmt::print("fpcr.FZ16 {}\n", FP::FPCR{fpscr}.FZ16()); + // fmt::print("\n"); - fmt::print("Final register listing:\n"); - fmt::print(" unicorn dynarmic\n"); - const auto uni_regs = uni.GetRegisters(); - for (size_t i = 0; i < regs.size(); ++i) { - fmt::print("{:3s}: {:08x} {:08x} {}\n", static_cast(i), uni_regs[i], jit.Regs()[i], uni_regs[i] != jit.Regs()[i] ? "*" : ""); - } - const auto uni_ext_regs = uni.GetExtRegs(); - for (size_t i = 0; i < vecs.size(); ++i) { - fmt::print("s{:2d}: {:08x} {:08x} {}\n", static_cast(i), uni_ext_regs[i], jit.ExtRegs()[i], uni_ext_regs[i] != jit.ExtRegs()[i] ? "*" : ""); - } - fmt::print("cpsr {:08x} {:08x} {}\n", uni.GetCpsr(), jit.Cpsr(), uni.GetCpsr() != jit.Cpsr() ? "*" : ""); - fmt::print("fpsr {:08x} {:08x} {}\n", uni.GetFpscr(), jit.Fpscr(), (uni.GetFpscr() & 0xF0000000) != (jit.Fpscr() & 0xF0000000) ? "*" : ""); - fmt::print("\n"); + // fmt::print("Final register listing:\n"); + // fmt::print(" unicorn dynarmic\n"); + // const auto uni_regs = uni.GetRegisters(); + // for (size_t i = 0; i < regs.size(); ++i) { + // fmt::print("{:3s}: {:08x} {:08x} {}\n", static_cast(i), uni_regs[i], jit.Regs()[i], uni_regs[i] != jit.Regs()[i] ? "*" : ""); + // } + // const auto uni_ext_regs = uni.GetExtRegs(); + // for (size_t i = 0; i < vecs.size(); ++i) { + // fmt::print("s{:2d}: {:08x} {:08x} {}\n", static_cast(i), uni_ext_regs[i], jit.ExtRegs()[i], uni_ext_regs[i] != jit.ExtRegs()[i] ? "*" : ""); + // } + // fmt::print("cpsr {:08x} {:08x} {}\n", uni.GetCpsr(), jit.Cpsr(), uni.GetCpsr() != jit.Cpsr() ? "*" : ""); + // fmt::print("fpsr {:08x} {:08x} {}\n", uni.GetFpscr(), jit.Fpscr(), (uni.GetFpscr() & 0xF0000000) != (jit.Fpscr() & 0xF0000000) ? "*" : ""); + // fmt::print("\n"); - fmt::print("Modified memory:\n"); - fmt::print(" uni dyn\n"); - auto uni_iter = uni_env.modified_memory.begin(); - auto jit_iter = jit_env.modified_memory.begin(); - while (uni_iter != uni_env.modified_memory.end() || jit_iter != jit_env.modified_memory.end()) { - if (uni_iter == uni_env.modified_memory.end() || (jit_iter != jit_env.modified_memory.end() && uni_iter->first > jit_iter->first)) { - fmt::print("{:08x}: {:02x} *\n", jit_iter->first, jit_iter->second); - jit_iter++; - } else if (jit_iter == jit_env.modified_memory.end() || jit_iter->first > uni_iter->first) { - fmt::print("{:08x}: {:02x} *\n", uni_iter->first, uni_iter->second); - uni_iter++; - } else if (uni_iter->first == jit_iter->first) { - fmt::print("{:08x}: {:02x} {:02x} {}\n", uni_iter->first, uni_iter->second, jit_iter->second, uni_iter->second != jit_iter->second ? "*" : ""); - uni_iter++; - jit_iter++; - } - } - fmt::print("\n"); + // fmt::print("Modified memory:\n"); + // fmt::print(" uni dyn\n"); + // auto uni_iter = uni_env.modified_memory.begin(); + // auto jit_iter = jit_env.modified_memory.begin(); + // while (uni_iter != uni_env.modified_memory.end() || jit_iter != jit_env.modified_memory.end()) { + // if (uni_iter == uni_env.modified_memory.end() || (jit_iter != jit_env.modified_memory.end() && uni_iter->first > jit_iter->first)) { + // fmt::print("{:08x}: {:02x} *\n", jit_iter->first, jit_iter->second); + // jit_iter++; + // } else if (jit_iter == jit_env.modified_memory.end() || jit_iter->first > uni_iter->first) { + // fmt::print("{:08x}: {:02x} *\n", uni_iter->first, uni_iter->second); + // uni_iter++; + // } else if (uni_iter->first == jit_iter->first) { + // fmt::print("{:08x}: {:02x} {:02x} {}\n", uni_iter->first, uni_iter->second, jit_iter->second, uni_iter->second != jit_iter->second ? "*" : ""); + // uni_iter++; + // jit_iter++; + // } + // } + // fmt::print("\n"); - fmt::print("x86_64:\n"); - fmt::print("{}", jit.Disassemble()); + // fmt::print("x86_64:\n"); + // fmt::print("{}", jit.Disassemble()); - fmt::print("Interrupts:\n"); - for (const auto& i : uni_env.interrupts) { - std::puts(i.c_str()); - } - }; + // fmt::print("Interrupts:\n"); + // for (const auto& i : uni_env.interrupts) { + // std::puts(i.c_str()); + // } + // }; REQUIRE(uni_env.code_mem_modified_by_guest == jit_env.code_mem_modified_by_guest); if (uni_env.code_mem_modified_by_guest) { diff --git a/src/dynarmic/tests/A32/fuzz_thumb.cpp b/src/dynarmic/tests/A32/fuzz_thumb.cpp index 3a561a18d9..7fef968b95 100644 --- a/src/dynarmic/tests/A32/fuzz_thumb.cpp +++ b/src/dynarmic/tests/A32/fuzz_thumb.cpp @@ -16,13 +16,13 @@ #include #include -#include +#include "dynarmic/mcl/bit.hpp" #include "dynarmic/common/common_types.h" -#include "../rand_int.h" -#include "../unicorn_emu/a32_unicorn.h" -#include "./testenv.h" -#include "../native/testenv.h" +#include "dynarmic/tests/rand_int.h" +#include "dynarmic/tests/unicorn_emu/a32_unicorn.h" +#include "dynarmic/tests/A32/testenv.h" +#include "dynarmic/tests/native/testenv.h" #include "dynarmic/frontend/A32/FPSCR.h" #include "dynarmic/frontend/A32/PSR.h" #include "dynarmic/frontend/A32/a32_location_descriptor.h" @@ -107,7 +107,7 @@ static bool DoesBehaviorMatch(const A32Unicorn& uni, const A32::Ji return std::equal(interp_regs.begin(), interp_regs.end(), jit_regs.begin(), jit_regs.end()) && uni.GetCpsr() == jit.Cpsr() && interp_write_records == jit_write_records; } -static void RunInstance(size_t run_number, ThumbTestEnv& test_env, A32Unicorn& uni, A32::Jit& jit, const ThumbTestEnv::RegisterArray& initial_regs, size_t instruction_count, size_t instructions_to_execute_count) { +static void RunInstance(size_t run_number, ThumbTestEnv& test_env, A32::UserConfig const& config, A32Unicorn& uni, A32::Jit& jit, const ThumbTestEnv::RegisterArray& initial_regs, size_t instruction_count, size_t instructions_to_execute_count) { uni.ClearPageCache(); jit.ClearCache(); @@ -145,9 +145,8 @@ static void RunInstance(size_t run_number, ThumbTestEnv& test_env, A32Unicorn uni{test_env}; - A32::Jit jit{GetUserConfig(&test_env)}; + A32::UserConfig config{GetUserConfig(&test_env)}; + A32::Jit jit{config}; constexpr ThumbTestEnv::RegisterArray initial_regs{ 0xe90ecd70, @@ -534,5 +539,5 @@ TEST_CASE("Verify fix for off by one error in MemoryRead32 worked", "[Thumb][Thu 0xE7FE, // b +#0 }; - RunInstance(1, test_env, uni, jit, initial_regs, 5, 5); + RunInstance(1, test_env, config, uni, jit, initial_regs, 5, 5); } diff --git a/src/dynarmic/tests/A32/test_arm_instructions.cpp b/src/dynarmic/tests/A32/test_arm_instructions.cpp index 2e7e7dc5d8..5a27cd499c 100644 --- a/src/dynarmic/tests/A32/test_arm_instructions.cpp +++ b/src/dynarmic/tests/A32/test_arm_instructions.cpp @@ -1,4 +1,4 @@ -// SPDX-FileCopyrightText: Copyright 2025 Eden Emulator Project +// SPDX-FileCopyrightText: Copyright 2026 Eden Emulator Project // SPDX-License-Identifier: GPL-3.0-or-later /* This file is part of the dynarmic project. @@ -8,8 +8,8 @@ #include -#include "./testenv.h" -#include "../native/testenv.h" +#include "dynarmic/tests/A32/testenv.h" +#include "dynarmic/tests/native/testenv.h" #include "dynarmic/frontend/A32/a32_location_descriptor.h" #include "dynarmic/interface/A32/a32.h" diff --git a/src/dynarmic/tests/A32/test_coprocessor.cpp b/src/dynarmic/tests/A32/test_coprocessor.cpp index 3888d2c68b..66ae6ebb09 100644 --- a/src/dynarmic/tests/A32/test_coprocessor.cpp +++ b/src/dynarmic/tests/A32/test_coprocessor.cpp @@ -1,4 +1,4 @@ -// SPDX-FileCopyrightText: Copyright 2025 Eden Emulator Project +// SPDX-FileCopyrightText: Copyright 2026 Eden Emulator Project // SPDX-License-Identifier: GPL-3.0-or-later /* This file is part of the dynarmic project. @@ -10,8 +10,8 @@ #include -#include "./testenv.h" -#include "../native/testenv.h" +#include "dynarmic/tests/A32/testenv.h" +#include "dynarmic/tests/native/testenv.h" #include "dynarmic/frontend/A32/a32_location_descriptor.h" #include "dynarmic/interface/A32/a32.h" #include "dynarmic/interface/A32/coprocessor.h" diff --git a/src/dynarmic/tests/A32/test_svc.cpp b/src/dynarmic/tests/A32/test_svc.cpp index 0be2432c7b..0cfaf23ec5 100644 --- a/src/dynarmic/tests/A32/test_svc.cpp +++ b/src/dynarmic/tests/A32/test_svc.cpp @@ -1,4 +1,4 @@ -// SPDX-FileCopyrightText: Copyright 2025 Eden Emulator Project +// SPDX-FileCopyrightText: Copyright 2026 Eden Emulator Project // SPDX-License-Identifier: GPL-3.0-or-later /* This file is part of the dynarmic project. @@ -10,8 +10,8 @@ #include -#include "./testenv.h" -#include "../native/testenv.h" +#include "dynarmic/tests/A32/testenv.h" +#include "dynarmic/tests/native/testenv.h" using namespace Dynarmic; diff --git a/src/dynarmic/tests/A32/test_thumb_instructions.cpp b/src/dynarmic/tests/A32/test_thumb_instructions.cpp index d509acdd8d..6aa1b7389b 100644 --- a/src/dynarmic/tests/A32/test_thumb_instructions.cpp +++ b/src/dynarmic/tests/A32/test_thumb_instructions.cpp @@ -1,4 +1,4 @@ -// SPDX-FileCopyrightText: Copyright 2025 Eden Emulator Project +// SPDX-FileCopyrightText: Copyright 2026 Eden Emulator Project // SPDX-License-Identifier: GPL-3.0-or-later /* This file is part of the dynarmic project. @@ -9,8 +9,8 @@ #include #include "dynarmic/common/common_types.h" -#include "./testenv.h" -#include "../native/testenv.h" +#include "dynarmic/tests/A32/testenv.h" +#include "dynarmic/tests/native/testenv.h" #include "dynarmic/interface/A32/a32.h" static Dynarmic::A32::UserConfig GetUserConfig(ThumbTestEnv* testenv) { diff --git a/src/dynarmic/tests/A64/a64.cpp b/src/dynarmic/tests/A64/a64.cpp index d331c5e8a1..4d4484e53e 100644 --- a/src/dynarmic/tests/A64/a64.cpp +++ b/src/dynarmic/tests/A64/a64.cpp @@ -9,8 +9,8 @@ #include #include -#include "./testenv.h" -#include "../native/testenv.h" +#include "dynarmic/tests/A64/testenv.h" +#include "dynarmic/tests/native/testenv.h" #include "dynarmic/common/fp/fpsr.h" #include "dynarmic/interface/exclusive_monitor.h" #include "dynarmic/interface/optimization_flags.h" diff --git a/src/dynarmic/tests/A64/fp_min_max.cpp b/src/dynarmic/tests/A64/fp_min_max.cpp index 1669b63071..313b5e5117 100644 --- a/src/dynarmic/tests/A64/fp_min_max.cpp +++ b/src/dynarmic/tests/A64/fp_min_max.cpp @@ -1,4 +1,4 @@ -// SPDX-FileCopyrightText: Copyright 2025 Eden Emulator Project +// SPDX-FileCopyrightText: Copyright 2026 Eden Emulator Project // SPDX-License-Identifier: GPL-3.0-or-later /* This file is part of the dynarmic project. @@ -11,8 +11,8 @@ #include #include "dynarmic/common/common_types.h" -#include "./testenv.h" -#include "../native/testenv.h" +#include "dynarmic/tests/A64/testenv.h" +#include "dynarmic/tests/native/testenv.h" using namespace Dynarmic; diff --git a/src/dynarmic/tests/A64/fuzz_with_unicorn.cpp b/src/dynarmic/tests/A64/fuzz_with_unicorn.cpp index 2cdf288eab..749cc77126 100644 --- a/src/dynarmic/tests/A64/fuzz_with_unicorn.cpp +++ b/src/dynarmic/tests/A64/fuzz_with_unicorn.cpp @@ -12,14 +12,13 @@ #include #include -#include #include "dynarmic/common/common_types.h" -#include "../fuzz_util.h" -#include "../rand_int.h" -#include "../unicorn_emu/a64_unicorn.h" -#include "./testenv.h" -#include "../native/testenv.h" +#include "dynarmic/tests/fuzz_util.h" +#include "dynarmic/tests/rand_int.h" +#include "dynarmic/tests/unicorn_emu/a64_unicorn.h" +#include "dynarmic/tests/A64/testenv.h" +#include "dynarmic/tests/native/testenv.h" #include "dynarmic/common/fp/fpcr.h" #include "dynarmic/common/fp/fpsr.h" #include "dynarmic/common/llvm_disassemble.h" @@ -168,7 +167,7 @@ static Dynarmic::A64::UserConfig GetUserConfig(A64TestEnv& jit_env) { return jit_user_config; } -static void RunTestInstance(Dynarmic::A64::Jit& jit, A64Unicorn& uni, A64TestEnv& jit_env, A64TestEnv& uni_env, const A64Unicorn::RegisterArray& regs, const A64Unicorn::VectorArray& vecs, const size_t instructions_start, const std::vector& instructions, const u32 pstate, const u32 fpcr) { +static void RunTestInstance(Dynarmic::A64::Jit& jit, A64Unicorn& uni, A64TestEnv& jit_env, A64TestEnv& uni_env, Dynarmic::A64::UserConfig& conf, const A64Unicorn::RegisterArray& regs, const A64Unicorn::VectorArray& vecs, const size_t instructions_start, const std::vector& instructions, const u32 pstate, const u32 fpcr) { jit_env.code_mem = instructions; uni_env.code_mem = instructions; jit_env.code_mem.emplace_back(0x14000000); // B . @@ -205,85 +204,82 @@ static void RunTestInstance(Dynarmic::A64::Jit& jit, A64Unicorn& uni, A64TestEnv uni_env.ticks_left = instructions.size() * 4; uni.Run(); - SCOPE_FAIL { - fmt::print("Instruction Listing:\n"); - for (u32 instruction : instructions) { - fmt::print("{:08x} {}\n", instruction, Common::DisassembleAArch64(instruction)); - } - fmt::print("\n"); + // SCOPE_FAIL { + // fmt::print("Instruction Listing:\n"); + // for (u32 instruction : instructions) { + // fmt::print("{:08x} {}\n", instruction, Common::DisassembleAArch64(instruction)); + // } + // fmt::print("\n"); - fmt::print("Initial register listing:\n"); - for (size_t i = 0; i < regs.size(); ++i) { - fmt::print("{:3s}: {:016x}\n", A64::RegToString(static_cast(i)), regs[i]); - } - for (size_t i = 0; i < vecs.size(); ++i) { - fmt::print("{:3s}: {:016x}{:016x}\n", A64::VecToString(static_cast(i)), vecs[i][1], vecs[i][0]); - } - fmt::print("sp : {:016x}\n", initial_sp); - fmt::print("pc : {:016x}\n", instructions_start); - fmt::print("p : {:08x}\n", pstate); - fmt::print("fpcr {:08x}\n", fpcr); - fmt::print("fpcr.AHP {}\n", FP::FPCR{fpcr}.AHP()); - fmt::print("fpcr.DN {}\n", FP::FPCR{fpcr}.DN()); - fmt::print("fpcr.FZ {}\n", FP::FPCR{fpcr}.FZ()); - fmt::print("fpcr.RMode {}\n", static_cast(FP::FPCR{fpcr}.RMode())); - fmt::print("fpcr.FZ16 {}\n", FP::FPCR{fpcr}.FZ16()); - fmt::print("\n"); + // fmt::print("Initial register listing:\n"); + // for (size_t i = 0; i < regs.size(); ++i) { + // fmt::print("{:3s}: {:016x}\n", A64::RegToString(static_cast(i)), regs[i]); + // } + // for (size_t i = 0; i < vecs.size(); ++i) { + // fmt::print("{:3s}: {:016x}{:016x}\n", A64::VecToString(static_cast(i)), vecs[i][1], vecs[i][0]); + // } + // fmt::print("sp : {:016x}\n", initial_sp); + // fmt::print("pc : {:016x}\n", instructions_start); + // fmt::print("p : {:08x}\n", pstate); + // fmt::print("fpcr {:08x}\n", fpcr); + // fmt::print("fpcr.AHP {}\n", FP::FPCR{fpcr}.AHP()); + // fmt::print("fpcr.DN {}\n", FP::FPCR{fpcr}.DN()); + // fmt::print("fpcr.FZ {}\n", FP::FPCR{fpcr}.FZ()); + // fmt::print("fpcr.RMode {}\n", static_cast(FP::FPCR{fpcr}.RMode())); + // fmt::print("fpcr.FZ16 {}\n", FP::FPCR{fpcr}.FZ16()); + // fmt::print("\n"); - fmt::print("Final register listing:\n"); - fmt::print(" unicorn dynarmic\n"); - const auto uni_regs = uni.GetRegisters(); - for (size_t i = 0; i < regs.size(); ++i) { - fmt::print("{:3s}: {:016x} {:016x} {}\n", A64::RegToString(static_cast(i)), uni_regs[i], jit.GetRegisters()[i], uni_regs[i] != jit.GetRegisters()[i] ? "*" : ""); - } - const auto uni_vecs = uni.GetVectors(); - for (size_t i = 0; i < vecs.size(); ++i) { - fmt::print("{:3s}: {:016x}{:016x} {:016x}{:016x} {}\n", A64::VecToString(static_cast(i)), - uni_vecs[i][1], uni_vecs[i][0], - jit.GetVectors()[i][1], jit.GetVectors()[i][0], - uni_vecs[i] != jit.GetVectors()[i] ? "*" : ""); - } - fmt::print("sp : {:016x} {:016x} {}\n", uni.GetSP(), jit.GetSP(), uni.GetSP() != jit.GetSP() ? "*" : ""); - fmt::print("pc : {:016x} {:016x} {}\n", uni.GetPC(), jit.GetPC(), uni.GetPC() != jit.GetPC() ? "*" : ""); - fmt::print("p : {:08x} {:08x} {}\n", uni.GetPstate(), jit.GetPstate(), (uni.GetPstate() & 0xF0000000) != (jit.GetPstate() & 0xF0000000) ? "*" : ""); - fmt::print("qc : {:08x} {:08x} {}\n", uni.GetFpsr(), jit.GetFpsr(), FP::FPSR{uni.GetFpsr()}.QC() != FP::FPSR{jit.GetFpsr()}.QC() ? "*" : ""); - fmt::print("\n"); + // fmt::print("Final register listing:\n"); + // fmt::print(" unicorn dynarmic\n"); + // const auto uni_regs = uni.GetRegisters(); + // for (size_t i = 0; i < regs.size(); ++i) { + // fmt::print("{:3s}: {:016x} {:016x} {}\n", A64::RegToString(static_cast(i)), uni_regs[i], jit.GetRegisters()[i], uni_regs[i] != jit.GetRegisters()[i] ? "*" : ""); + // } + // const auto uni_vecs = uni.GetVectors(); + // for (size_t i = 0; i < vecs.size(); ++i) { + // fmt::print("{:3s}: {:016x}{:016x} {:016x}{:016x} {}\n", A64::VecToString(static_cast(i)), + // uni_vecs[i][1], uni_vecs[i][0], + // jit.GetVectors()[i][1], jit.GetVectors()[i][0], + // uni_vecs[i] != jit.GetVectors()[i] ? "*" : ""); + // } + // fmt::print("sp : {:016x} {:016x} {}\n", uni.GetSP(), jit.GetSP(), uni.GetSP() != jit.GetSP() ? "*" : ""); + // fmt::print("pc : {:016x} {:016x} {}\n", uni.GetPC(), jit.GetPC(), uni.GetPC() != jit.GetPC() ? "*" : ""); + // fmt::print("p : {:08x} {:08x} {}\n", uni.GetPstate(), jit.GetPstate(), (uni.GetPstate() & 0xF0000000) != (jit.GetPstate() & 0xF0000000) ? "*" : ""); + // fmt::print("qc : {:08x} {:08x} {}\n", uni.GetFpsr(), jit.GetFpsr(), FP::FPSR{uni.GetFpsr()}.QC() != FP::FPSR{jit.GetFpsr()}.QC() ? "*" : ""); + // fmt::print("\n"); - fmt::print("Modified memory:\n"); - fmt::print(" uni dyn\n"); - auto uni_iter = uni_env.modified_memory.begin(); - auto jit_iter = jit_env.modified_memory.begin(); - while (uni_iter != uni_env.modified_memory.end() || jit_iter != jit_env.modified_memory.end()) { - if (uni_iter == uni_env.modified_memory.end() || (jit_iter != jit_env.modified_memory.end() && uni_iter->first > jit_iter->first)) { - fmt::print("{:016x}: {:02x} *\n", jit_iter->first, jit_iter->second); - jit_iter++; - } else if (jit_iter == jit_env.modified_memory.end() || jit_iter->first > uni_iter->first) { - fmt::print("{:016x}: {:02x} *\n", uni_iter->first, uni_iter->second); - uni_iter++; - } else if (uni_iter->first == jit_iter->first) { - fmt::print("{:016x}: {:02x} {:02x} {}\n", uni_iter->first, uni_iter->second, jit_iter->second, uni_iter->second != jit_iter->second ? "*" : ""); - uni_iter++; - jit_iter++; - } - } - fmt::print("\n"); + // fmt::print("Modified memory:\n"); + // fmt::print(" uni dyn\n"); + // auto uni_iter = uni_env.modified_memory.begin(); + // auto jit_iter = jit_env.modified_memory.begin(); + // while (uni_iter != uni_env.modified_memory.end() || jit_iter != jit_env.modified_memory.end()) { + // if (uni_iter == uni_env.modified_memory.end() || (jit_iter != jit_env.modified_memory.end() && uni_iter->first > jit_iter->first)) { + // fmt::print("{:016x}: {:02x} *\n", jit_iter->first, jit_iter->second); + // jit_iter++; + // } else if (jit_iter == jit_env.modified_memory.end() || jit_iter->first > uni_iter->first) { + // fmt::print("{:016x}: {:02x} *\n", uni_iter->first, uni_iter->second); + // uni_iter++; + // } else if (uni_iter->first == jit_iter->first) { + // fmt::print("{:016x}: {:02x} {:02x} {}\n", uni_iter->first, uni_iter->second, jit_iter->second, uni_iter->second != jit_iter->second ? "*" : ""); + // uni_iter++; + // jit_iter++; + // } + // } + // fmt::print("\n"); - const auto get_code = [&jit_env](u64 vaddr) { return jit_env.MemoryReadCode(vaddr); }; - IR::Block ir_block = A64::Translate({instructions_start, FP::FPCR{fpcr}}, get_code, {}); - fmt::print("IR:\n"); - fmt::print("{}\n", IR::DumpBlock(ir_block)); - Optimization::Optimize(ir_block, conf, {}); - fmt::print("Optimized IR:\n"); - fmt::print("{}\n", IR::DumpBlock(ir_block)); - - fmt::print("x86_64:\n"); - fmt::print("{}", jit.Disassemble()); - - fmt::print("Interrupts:\n"); - for (auto& i : uni_env.interrupts) { - puts(i.c_str()); - } - }; + // const auto get_code = [&jit_env](u64 vaddr) { return jit_env.MemoryReadCode(vaddr); }; + // const A64::LocationDescriptor location{instructions_start, FP::FPCR{fpcr}}; + // IR::Block ir_block{location}; + // A64::Translate(ir_block, location, get_code, {}); + // fmt::print("IR:\n{}\n", IR::DumpBlock(ir_block)); + // Optimization::Optimize(ir_block, conf, {}); + // fmt::print("Optimized IR:\n{}\n", IR::DumpBlock(ir_block)); + // fmt::print("x86_64:\n{}", jit.Disassemble()); + // fmt::print("Interrupts:\n"); + // for (auto& i : uni_env.interrupts) { + // puts(i.c_str()); + // } + // }; REQUIRE(uni_env.code_mem_modified_by_guest == jit_env.code_mem_modified_by_guest); if (uni_env.code_mem_modified_by_guest) { @@ -304,7 +300,8 @@ TEST_CASE("A64: Single random instruction", "[a64][unicorn]") { A64TestEnv jit_env{}; A64TestEnv uni_env{}; - Dynarmic::A64::Jit jit{GetUserConfig(jit_env)}; + Dynarmic::A64::UserConfig conf{GetUserConfig(jit_env)}; + Dynarmic::A64::Jit jit{conf}; A64Unicorn uni{uni_env}; A64Unicorn::RegisterArray regs; @@ -323,7 +320,7 @@ TEST_CASE("A64: Single random instruction", "[a64][unicorn]") { INFO("Instruction: 0x" << std::hex << instructions[0]); - RunTestInstance(jit, uni, jit_env, uni_env, regs, vecs, start_address, instructions, pstate, fpcr); + RunTestInstance(jit, uni, jit_env, uni_env, conf, regs, vecs, start_address, instructions, pstate, fpcr); } } @@ -331,7 +328,8 @@ TEST_CASE("A64: Floating point instructions", "[a64][unicorn]") { A64TestEnv jit_env{}; A64TestEnv uni_env{}; - Dynarmic::A64::Jit jit{GetUserConfig(jit_env)}; + Dynarmic::A64::UserConfig conf{GetUserConfig(jit_env)}; + Dynarmic::A64::Jit jit{conf}; A64Unicorn uni{uni_env}; static constexpr std::array float_numbers{ @@ -448,7 +446,7 @@ TEST_CASE("A64: Floating point instructions", "[a64][unicorn]") { INFO("Instruction: 0x" << std::hex << instructions[0]); - RunTestInstance(jit, uni, jit_env, uni_env, regs, vecs, start_address, instructions, pstate, fpcr); + RunTestInstance(jit, uni, jit_env, uni_env, conf, regs, vecs, start_address, instructions, pstate, fpcr); } } @@ -456,7 +454,8 @@ TEST_CASE("A64: Small random block", "[a64][unicorn]") { A64TestEnv jit_env{}; A64TestEnv uni_env{}; - Dynarmic::A64::Jit jit{GetUserConfig(jit_env)}; + Dynarmic::A64::UserConfig conf{GetUserConfig(jit_env)}; + Dynarmic::A64::Jit jit{conf}; A64Unicorn uni{uni_env}; A64Unicorn::RegisterArray regs; @@ -483,7 +482,7 @@ TEST_CASE("A64: Small random block", "[a64][unicorn]") { INFO("Instruction 4: 0x" << std::hex << instructions[3]); INFO("Instruction 5: 0x" << std::hex << instructions[4]); - RunTestInstance(jit, uni, jit_env, uni_env, regs, vecs, start_address, instructions, pstate, fpcr); + RunTestInstance(jit, uni, jit_env, uni_env, conf, regs, vecs, start_address, instructions, pstate, fpcr); } } @@ -491,7 +490,8 @@ TEST_CASE("A64: Large random block", "[a64][unicorn]") { A64TestEnv jit_env{}; A64TestEnv uni_env{}; - Dynarmic::A64::Jit jit{GetUserConfig(jit_env)}; + Dynarmic::A64::UserConfig conf{GetUserConfig(jit_env)}; + Dynarmic::A64::Jit jit{conf}; A64Unicorn uni{uni_env}; A64Unicorn::RegisterArray regs; @@ -512,6 +512,6 @@ TEST_CASE("A64: Large random block", "[a64][unicorn]") { const u32 pstate = RandInt(0, 0xF) << 28; const u32 fpcr = RandomFpcr(); - RunTestInstance(jit, uni, jit_env, uni_env, regs, vecs, start_address, instructions, pstate, fpcr); + RunTestInstance(jit, uni, jit_env, uni_env, conf, regs, vecs, start_address, instructions, pstate, fpcr); } } diff --git a/src/dynarmic/tests/A64/misaligned_page_table.cpp b/src/dynarmic/tests/A64/misaligned_page_table.cpp index fc0bc77428..99afba519d 100644 --- a/src/dynarmic/tests/A64/misaligned_page_table.cpp +++ b/src/dynarmic/tests/A64/misaligned_page_table.cpp @@ -1,4 +1,4 @@ -// SPDX-FileCopyrightText: Copyright 2025 Eden Emulator Project +// SPDX-FileCopyrightText: Copyright 2026 Eden Emulator Project // SPDX-License-Identifier: GPL-3.0-or-later /* This file is part of the dynarmic project. @@ -8,8 +8,8 @@ #include -#include "./testenv.h" -#include "../native/testenv.h" +#include "dynarmic/tests/A64/testenv.h" +#include "dynarmic/tests/native/testenv.h" #include "dynarmic/interface/A64/a64.h" TEST_CASE("misaligned load/store do not use page_table when detect_misaligned_access_via_page_table is set", "[a64]") { diff --git a/src/dynarmic/tests/A64/real_world.cpp b/src/dynarmic/tests/A64/real_world.cpp index a083f16d61..c15f307c3d 100644 --- a/src/dynarmic/tests/A64/real_world.cpp +++ b/src/dynarmic/tests/A64/real_world.cpp @@ -1,11 +1,11 @@ -// SPDX-FileCopyrightText: Copyright 2025 Eden Emulator Project +// SPDX-FileCopyrightText: Copyright 2026 Eden Emulator Project // SPDX-License-Identifier: GPL-3.0-or-later #include #include -#include "./testenv.h" -#include "../native/testenv.h" +#include "dynarmic/tests/A64/testenv.h" +#include "dynarmic/tests/native/testenv.h" #include "dynarmic/interface/A64/a64.h" using namespace Dynarmic; diff --git a/src/dynarmic/tests/A64/test_invalidation.cpp b/src/dynarmic/tests/A64/test_invalidation.cpp index 0c92f5f606..3b2d5fef98 100644 --- a/src/dynarmic/tests/A64/test_invalidation.cpp +++ b/src/dynarmic/tests/A64/test_invalidation.cpp @@ -1,4 +1,4 @@ -// SPDX-FileCopyrightText: Copyright 2025 Eden Emulator Project +// SPDX-FileCopyrightText: Copyright 2026 Eden Emulator Project // SPDX-License-Identifier: GPL-3.0-or-later /* This file is part of the dynarmic project. @@ -8,8 +8,8 @@ #include -#include "./testenv.h" -#include "../native/testenv.h" +#include "dynarmic/tests/A64/testenv.h" +#include "dynarmic/tests/native/testenv.h" #include "dynarmic/interface/A64/a64.h" using namespace Dynarmic; diff --git a/src/dynarmic/tests/A64/verify_unicorn.cpp b/src/dynarmic/tests/A64/verify_unicorn.cpp index 0c0ccc1609..5bdcd0dc3e 100644 --- a/src/dynarmic/tests/A64/verify_unicorn.cpp +++ b/src/dynarmic/tests/A64/verify_unicorn.cpp @@ -1,3 +1,6 @@ +// SPDX-FileCopyrightText: Copyright 2026 Eden Emulator Project +// SPDX-License-Identifier: GPL-3.0-or-later + /* This file is part of the dynarmic project. * Copyright (c) 2018 MerryMage * SPDX-License-Identifier: 0BSD @@ -7,9 +10,9 @@ #include -#include "../rand_int.h" -#include "../unicorn_emu/a64_unicorn.h" -#include "./testenv.h" +#include "dynarmic/tests/rand_int.h" +#include "dynarmic/tests/unicorn_emu/a64_unicorn.h" +#include "dynarmic/tests/A64/testenv.h" using namespace Dynarmic; diff --git a/src/dynarmic/tests/CMakeLists.txt b/src/dynarmic/tests/CMakeLists.txt index 395181efe3..ca44dce593 100644 --- a/src/dynarmic/tests/CMakeLists.txt +++ b/src/dynarmic/tests/CMakeLists.txt @@ -72,7 +72,7 @@ add_executable(dynarmic_print_info print_info.cpp ) create_target_directory_groups(dynarmic_print_info) -target_link_libraries(dynarmic_print_info PRIVATE dynarmic fmt::fmt merry::mcl unordered_dense::unordered_dense) +target_link_libraries(dynarmic_print_info PRIVATE dynarmic fmt::fmt unordered_dense::unordered_dense) if (BOOST_NO_HEADERS) target_link_libraries(dynarmic_print_info PRIVATE Boost::variant Boost::icl Boost::pool) else() @@ -93,7 +93,7 @@ add_executable(dynarmic_test_generator create_target_directory_groups(dynarmic_test_generator) -target_link_libraries(dynarmic_test_generator PRIVATE dynarmic fmt::fmt merry::mcl unordered_dense::unordered_dense) +target_link_libraries(dynarmic_test_generator PRIVATE dynarmic fmt::fmt unordered_dense::unordered_dense) if (BOOST_NO_HEADERS) target_link_libraries(dynarmic_test_generator PRIVATE Boost::variant Boost::icl Boost::pool) else() @@ -110,7 +110,7 @@ add_executable(dynarmic_test_reader test_reader.cpp ) create_target_directory_groups(dynarmic_test_reader) -target_link_libraries(dynarmic_test_reader PRIVATE dynarmic fmt::fmt merry::mcl unordered_dense::unordered_dense) +target_link_libraries(dynarmic_test_reader PRIVATE dynarmic fmt::fmt unordered_dense::unordered_dense) if (BOOST_NO_HEADERS) target_link_libraries(dynarmic_test_reader PRIVATE Boost::variant Boost::icl Boost::pool) else() @@ -123,7 +123,7 @@ target_compile_definitions(dynarmic_test_reader PRIVATE FMT_USE_USER_DEFINED_LIT # create_target_directory_groups(dynarmic_tests) -target_link_libraries(dynarmic_tests PRIVATE dynarmic Catch2::Catch2WithMain fmt::fmt merry::mcl unordered_dense::unordered_dense) +target_link_libraries(dynarmic_tests PRIVATE dynarmic Catch2::Catch2WithMain fmt::fmt unordered_dense::unordered_dense) if (BOOST_NO_HEADERS) target_link_libraries(dynarmic_tests PRIVATE Boost::variant Boost::icl Boost::pool) else() diff --git a/src/dynarmic/tests/fp/FPToFixed.cpp b/src/dynarmic/tests/fp/FPToFixed.cpp index 570ebcbbd7..e16e4460ed 100644 --- a/src/dynarmic/tests/fp/FPToFixed.cpp +++ b/src/dynarmic/tests/fp/FPToFixed.cpp @@ -1,4 +1,4 @@ -// SPDX-FileCopyrightText: Copyright 2025 Eden Emulator Project +// SPDX-FileCopyrightText: Copyright 2026 Eden Emulator Project // SPDX-License-Identifier: GPL-3.0-or-later /* This file is part of the dynarmic project. @@ -12,7 +12,7 @@ #include #include "dynarmic/common/common_types.h" -#include "../rand_int.h" +#include "dynarmic/tests/rand_int.h" #include "dynarmic/common/fp/fpcr.h" #include "dynarmic/common/fp/fpsr.h" #include "dynarmic/common/fp/op.h" diff --git a/src/dynarmic/tests/fp/mantissa_util_tests.cpp b/src/dynarmic/tests/fp/mantissa_util_tests.cpp index de29d51865..9d16c3624c 100644 --- a/src/dynarmic/tests/fp/mantissa_util_tests.cpp +++ b/src/dynarmic/tests/fp/mantissa_util_tests.cpp @@ -1,4 +1,4 @@ -// SPDX-FileCopyrightText: Copyright 2025 Eden Emulator Project +// SPDX-FileCopyrightText: Copyright 2026 Eden Emulator Project // SPDX-License-Identifier: GPL-3.0-or-later /* This file is part of the dynarmic project. @@ -12,7 +12,7 @@ #include #include "dynarmic/common/common_types.h" -#include "../rand_int.h" +#include "dynarmic/tests/rand_int.h" #include "dynarmic/common/fp/mantissa_util.h" #include "dynarmic/common/safe_ops.h" diff --git a/src/dynarmic/tests/fp/unpacked_tests.cpp b/src/dynarmic/tests/fp/unpacked_tests.cpp index 919f21bf2f..a4f10d1273 100644 --- a/src/dynarmic/tests/fp/unpacked_tests.cpp +++ b/src/dynarmic/tests/fp/unpacked_tests.cpp @@ -1,4 +1,4 @@ -// SPDX-FileCopyrightText: Copyright 2025 Eden Emulator Project +// SPDX-FileCopyrightText: Copyright 2026 Eden Emulator Project // SPDX-License-Identifier: GPL-3.0-or-later /* This file is part of the dynarmic project. @@ -12,7 +12,7 @@ #include #include "dynarmic/common/common_types.h" -#include "../rand_int.h" +#include "dynarmic/tests/rand_int.h" #include "dynarmic/common/fp/fpcr.h" #include "dynarmic/common/fp/fpsr.h" #include "dynarmic/common/fp/unpacked.h" diff --git a/src/dynarmic/tests/fuzz_util.cpp b/src/dynarmic/tests/fuzz_util.cpp index 351eb1e10f..05f0a9e865 100644 --- a/src/dynarmic/tests/fuzz_util.cpp +++ b/src/dynarmic/tests/fuzz_util.cpp @@ -1,4 +1,4 @@ -// SPDX-FileCopyrightText: Copyright 2025 Eden Emulator Project +// SPDX-FileCopyrightText: Copyright 2026 Eden Emulator Project // SPDX-License-Identifier: GPL-3.0-or-later /* This file is part of the dynarmic project. @@ -6,7 +6,7 @@ * SPDX-License-Identifier: 0BSD */ -#include "./fuzz_util.h" +#include "dynarmic/tests/fuzz_util.h" #include @@ -14,7 +14,7 @@ #include #include "dynarmic/common/assert.h" -#include "./rand_int.h" +#include "dynarmic/tests/rand_int.h" #include "dynarmic/common/fp/fpcr.h" #include "dynarmic/common/fp/rounding_mode.h" diff --git a/src/dynarmic/tests/native/preserve_xmm.cpp b/src/dynarmic/tests/native/preserve_xmm.cpp index 7421252063..6369e1a74d 100644 --- a/src/dynarmic/tests/native/preserve_xmm.cpp +++ b/src/dynarmic/tests/native/preserve_xmm.cpp @@ -1,12 +1,12 @@ -// SPDX-FileCopyrightText: Copyright 2025 Eden Emulator Project +// SPDX-FileCopyrightText: Copyright 2026 Eden Emulator Project // SPDX-License-Identifier: GPL-3.0-or-later #include #include #include -#include "../A64/testenv.h" -#include "../native/testenv.h" +#include "dynarmic/tests/A64/testenv.h" +#include "dynarmic/tests/native/testenv.h" #include "dynarmic/common/fp/fpsr.h" #include "dynarmic/interface/exclusive_monitor.h" diff --git a/src/dynarmic/tests/print_info.cpp b/src/dynarmic/tests/print_info.cpp index 33d84ba8cd..19e2ca38b2 100644 --- a/src/dynarmic/tests/print_info.cpp +++ b/src/dynarmic/tests/print_info.cpp @@ -18,7 +18,7 @@ #include #include #include -#include +#include "dynarmic/mcl/bit.hpp" #include "dynarmic/common/common_types.h" #include "dynarmic/common/llvm_disassemble.h" diff --git a/src/dynarmic/tests/test_generator.cpp b/src/dynarmic/tests/test_generator.cpp index 4435e762ae..43203c3e13 100644 --- a/src/dynarmic/tests/test_generator.cpp +++ b/src/dynarmic/tests/test_generator.cpp @@ -16,14 +16,13 @@ #include #include -#include -#include +#include "dynarmic/mcl/bit.hpp" #include "dynarmic/common/common_types.h" #include "./A32/testenv.h" #include "./A64/testenv.h" -#include "./fuzz_util.h" -#include "./rand_int.h" +#include "dynarmic/tests/fuzz_util.h" +#include "dynarmic/tests/rand_int.h" #include "dynarmic/common/fp/fpcr.h" #include "dynarmic/common/fp/fpsr.h" #include "dynarmic/common/llvm_disassemble.h" diff --git a/src/dynarmic/tests/unicorn_emu/a32_unicorn.cpp b/src/dynarmic/tests/unicorn_emu/a32_unicorn.cpp index 1a4f1845d5..9a17bc5582 100644 --- a/src/dynarmic/tests/unicorn_emu/a32_unicorn.cpp +++ b/src/dynarmic/tests/unicorn_emu/a32_unicorn.cpp @@ -1,4 +1,4 @@ -// SPDX-FileCopyrightText: Copyright 2025 Eden Emulator Project +// SPDX-FileCopyrightText: Copyright 2026 Eden Emulator Project // SPDX-License-Identifier: GPL-3.0-or-later /* This file is part of the dynarmic project. @@ -6,22 +6,14 @@ * SPDX-License-Identifier: 0BSD */ -#include "./a32_unicorn.h" - #include - +#include +#include "dynarmic/mcl/bit.hpp" +#include "dynarmic/tests/unicorn_emu/a32_unicorn.h" #include "dynarmic/common/assert.h" -#include +#include "dynarmic/tests/A32/testenv.h" -#include "../A32/testenv.h" - -#define CHECKED(expr) \ - do { \ - if (auto cerr_ = (expr)) { \ - ASSERT(false && "Call " #expr " failed with error: {} ({})\n", static_cast(cerr_), \ - uc_strerror(cerr_)); \ - } \ - } while (0) +#define CHECKED(expr) do if ((expr)) ASSERT(false && "Call " #expr " failed with error\n"); while (0) constexpr u32 BEGIN_ADDRESS = 0; constexpr u32 END_ADDRESS = ~u32(0); diff --git a/src/dynarmic/tests/unicorn_emu/a32_unicorn.h b/src/dynarmic/tests/unicorn_emu/a32_unicorn.h index 79831b8111..d94724d9f2 100644 --- a/src/dynarmic/tests/unicorn_emu/a32_unicorn.h +++ b/src/dynarmic/tests/unicorn_emu/a32_unicorn.h @@ -1,4 +1,4 @@ -// SPDX-FileCopyrightText: Copyright 2025 Eden Emulator Project +// SPDX-FileCopyrightText: Copyright 2026 Eden Emulator Project // SPDX-License-Identifier: GPL-3.0-or-later /* This file is part of the dynarmic project. @@ -21,7 +21,7 @@ #include "dynarmic/common/common_types.h" -#include "../A32/testenv.h" +#include "dynarmic/tests/A32/testenv.h" namespace Unicorn::A32 { static constexpr size_t num_gprs = 16; diff --git a/src/dynarmic/tests/unicorn_emu/a64_unicorn.cpp b/src/dynarmic/tests/unicorn_emu/a64_unicorn.cpp index 3f13377f71..c8aa404199 100644 --- a/src/dynarmic/tests/unicorn_emu/a64_unicorn.cpp +++ b/src/dynarmic/tests/unicorn_emu/a64_unicorn.cpp @@ -1,4 +1,4 @@ -// SPDX-FileCopyrightText: Copyright 2025 Eden Emulator Project +// SPDX-FileCopyrightText: Copyright 2026 Eden Emulator Project // SPDX-License-Identifier: GPL-3.0-or-later /* This file is part of the dynarmic project. @@ -6,17 +6,11 @@ * SPDX-License-Identifier: 0BSD */ -#include "./a64_unicorn.h" - +#include +#include "dynarmic/tests/unicorn_emu/a64_unicorn.h" #include "dynarmic/common/assert.h" -#define CHECKED(expr) \ - do { \ - if (auto cerr_ = (expr)) { \ - ASSERT(false && "Call " #expr " failed with error: {} ({})\n", static_cast(cerr_), \ - uc_strerror(cerr_)); \ - } \ - } while (0) +#define CHECKED(expr) do if ((expr)) ASSERT(false && "Call " #expr " failed with error\n"); while (0) constexpr u64 BEGIN_ADDRESS = 0; constexpr u64 END_ADDRESS = ~u64(0); @@ -172,7 +166,7 @@ void A64Unicorn::DumpMemoryInformation() { void A64Unicorn::InterruptHook(uc_engine* uc, u32 int_number, void* user_data) { auto* this_ = static_cast(user_data); - u32 esr; + u32 esr = 0; //CHECKED(uc_reg_read(uc, UC_ARM64_REG_ESR_EL0, &esr)); auto ec = esr >> 26; diff --git a/src/dynarmic/tests/unicorn_emu/a64_unicorn.h b/src/dynarmic/tests/unicorn_emu/a64_unicorn.h index 54f09c3b28..1bc5b1cb8e 100644 --- a/src/dynarmic/tests/unicorn_emu/a64_unicorn.h +++ b/src/dynarmic/tests/unicorn_emu/a64_unicorn.h @@ -1,4 +1,4 @@ -// SPDX-FileCopyrightText: Copyright 2025 Eden Emulator Project +// SPDX-FileCopyrightText: Copyright 2026 Eden Emulator Project // SPDX-License-Identifier: GPL-3.0-or-later /* This file is part of the dynarmic project. @@ -21,7 +21,7 @@ #include "dynarmic/common/common_types.h" -#include "../A64/testenv.h" +#include "dynarmic/tests/A64/testenv.h" class A64Unicorn final { public: diff --git a/src/hid_core/CMakeLists.txt b/src/hid_core/CMakeLists.txt index 26d9ec1d3f..c740cdbe7f 100644 --- a/src/hid_core/CMakeLists.txt +++ b/src/hid_core/CMakeLists.txt @@ -1,3 +1,6 @@ +# SPDX-FileCopyrightText: Copyright 2026 Eden Emulator Project +# SPDX-License-Identifier: GPL-3.0-or-later + # SPDX-FileCopyrightText: 2018 yuzu Emulator Project # SPDX-License-Identifier: GPL-2.0-or-later @@ -148,13 +151,10 @@ if (MSVC) ) else() target_compile_options(hid_core PRIVATE - -Werror=conversion - - -Wno-sign-conversion - -Wno-cast-function-type - - $<$:-fsized-deallocation> - ) + $<$:-Werror=conversion> + $<$:-Wno-sign-conversion> + $<$:-Wno-cast-function-type> + $<$:-fsized-deallocation>) endif() create_target_directory_groups(hid_core) diff --git a/src/hid_core/resources/npad/npad.cpp b/src/hid_core/resources/npad/npad.cpp index 9355a88c4b..d625617bd5 100644 --- a/src/hid_core/resources/npad/npad.cpp +++ b/src/hid_core/resources/npad/npad.cpp @@ -800,6 +800,10 @@ Result NPad::DisconnectNpad(u64 aruid, Core::HID::NpadIdType npad_id) { auto& controller = GetControllerFromNpadIdType(aruid, npad_id); auto* shared_memory = controller.shared_memory; + if (!shared_memory) { + LOG_WARNING(Service_HID, "DisconnectNpad: shared_memory is null for npad_id={}", npad_id); + return ResultSuccess; + } // Don't reset shared_memory->assignment_mode this value is persistent shared_memory->style_tag.raw = Core::HID::NpadStyleSet::None; // Zero out shared_memory->device_type.raw = 0; diff --git a/src/input_common/CMakeLists.txt b/src/input_common/CMakeLists.txt index ef1308b1d0..406ee967b0 100644 --- a/src/input_common/CMakeLists.txt +++ b/src/input_common/CMakeLists.txt @@ -44,9 +44,7 @@ if (MSVC) /we4800 # Implicit conversion from 'type' to bool. Possible information loss ) else() - target_compile_options(input_common PRIVATE - -Werror=conversion - ) + target_compile_options(input_common PRIVATE $<$:-Werror=conversion>) endif() if (ANDROID) diff --git a/src/shader_recompiler/CMakeLists.txt b/src/shader_recompiler/CMakeLists.txt index c385951318..e91803c8c6 100644 --- a/src/shader_recompiler/CMakeLists.txt +++ b/src/shader_recompiler/CMakeLists.txt @@ -1,4 +1,4 @@ -# SPDX-FileCopyrightText: Copyright 2025 Eden Emulator Project +# SPDX-FileCopyrightText: Copyright 2026 Eden Emulator Project # SPDX-License-Identifier: GPL-3.0-or-later # SPDX-FileCopyrightText: 2018 yuzu Emulator Project @@ -253,8 +253,7 @@ if (MSVC) ) else() target_compile_options(shader_recompiler PRIVATE - -Werror=conversion - + $<$:-Werror=conversion> # Bracket depth determines maximum size of a fold expression in Clang since 9c9974c3ccb6. # And this in turns limits the size of a std::array. $<$:-fbracket-depth=1024> diff --git a/src/shader_recompiler/backend/spirv/emit_spirv_context_get_set.cpp b/src/shader_recompiler/backend/spirv/emit_spirv_context_get_set.cpp index db11def7b2..378d2cd0ec 100644 --- a/src/shader_recompiler/backend/spirv/emit_spirv_context_get_set.cpp +++ b/src/shader_recompiler/backend/spirv/emit_spirv_context_get_set.cpp @@ -142,14 +142,12 @@ Id GetCbuf(EmitContext& ctx, Id result_type, Id UniformDefinitions::*member_ptr, const auto is_float = UniformDefinitions::IsFloat(member_ptr); const auto num_elements = UniformDefinitions::NumElements(member_ptr); - const std::array zero_vec{ - is_float ? ctx.Const(0.0f) : ctx.Const(0u), - is_float ? ctx.Const(0.0f) : ctx.Const(0u), - is_float ? ctx.Const(0.0f) : ctx.Const(0u), - is_float ? ctx.Const(0.0f) : ctx.Const(0u), - }; + auto const zero_const = is_float ? ctx.Const(0.0f) : ctx.Const(0u); + const std::array zero_vec{zero_const, zero_const, zero_const, zero_const}; const Id cond = ctx.OpULessThanEqual(ctx.TypeBool(), buffer_offset, ctx.Const(0xFFFFu)); - const Id zero = ctx.OpCompositeConstruct(result_type, std::span(zero_vec.data(), num_elements)); + const Id zero = num_elements > 1 + ? ctx.OpCompositeConstruct(result_type, std::span(zero_vec.data(), num_elements)) + : zero_const; return ctx.OpSelect(result_type, cond, val, zero); } diff --git a/src/tests/CMakeLists.txt b/src/tests/CMakeLists.txt index 43745af429..875c40604c 100644 --- a/src/tests/CMakeLists.txt +++ b/src/tests/CMakeLists.txt @@ -1,4 +1,4 @@ -# SPDX-FileCopyrightText: Copyright 2025 Eden Emulator Project +# SPDX-FileCopyrightText: Copyright 2026 Eden Emulator Project # SPDX-License-Identifier: GPL-3.0-or-later # SPDX-FileCopyrightText: 2018 yuzu Emulator Project @@ -32,8 +32,8 @@ add_test(NAME tests COMMAND tests) # needed for vma if (NOT MSVC) target_compile_options(tests PRIVATE - -Wno-conversion - -Wno-unused-variable - -Wno-unused-parameter - -Wno-missing-field-initializers) + $<$:-Wno-conversion> + $<$:-Wno-unused-variable> + $<$:-Wno-unused-parameter> + $<$:-Wno-missing-field-initializers>) endif() diff --git a/src/video_core/CMakeLists.txt b/src/video_core/CMakeLists.txt index 3324682639..362b068656 100644 --- a/src/video_core/CMakeLists.txt +++ b/src/video_core/CMakeLists.txt @@ -363,14 +363,14 @@ else() if (APPLE) # error: declaration shadows a typedef in 'interval_base_set' # error: implicit conversion loses integer precision: 'int' to 'boost::icl::bound_type' (aka 'unsigned char') - target_compile_options(video_core PRIVATE -Wno-shadow -Wno-unused-local-typedef) + target_compile_options(video_core PRIVATE + $<$:-Wno-shadow> + $<$:-Wno-unused-local-typedef>) else() - target_compile_options(video_core PRIVATE -Werror=conversion) + target_compile_options(video_core PRIVATE $<$:-Werror=conversion>) endif() - target_compile_options(video_core PRIVATE - -Wno-sign-conversion - ) + target_compile_options(video_core PRIVATE $<$:-Wno-sign-conversion>) # xbyak set_source_files_properties(macro/macro_jit_x64.cpp PROPERTIES COMPILE_OPTIONS "-Wno-conversion;-Wno-shadow") diff --git a/src/video_core/renderer_vulkan/vk_swapchain.cpp b/src/video_core/renderer_vulkan/vk_swapchain.cpp index 5d55cf551b..0e4c274d94 100644 --- a/src/video_core/renderer_vulkan/vk_swapchain.cpp +++ b/src/video_core/renderer_vulkan/vk_swapchain.cpp @@ -9,6 +9,10 @@ #include #include +#ifdef __ANDROID__ +#include +#endif + #include "common/logging.h" #include "common/settings.h" #include "common/settings_enums.h" @@ -170,6 +174,7 @@ bool Swapchain::AcquireNextImage() { break; } + const auto wait_with_frame_pacing = [this] { switch (Settings::values.frame_pacing_mode.GetValue()) { case Settings::FramePacingMode::Target_Auto: scheduler.Wait(resource_ticks[image_index]); @@ -187,6 +192,17 @@ bool Swapchain::AcquireNextImage() { scheduler.Wait(resource_ticks[image_index], 120.0); break; } + }; + +#ifdef __ANDROID__ + if (android_get_device_api_level() >= 30) { + scheduler.Wait(resource_ticks[image_index]); + } else { + wait_with_frame_pacing(); + } +#else + wait_with_frame_pacing(); +#endif resource_ticks[image_index] = scheduler.CurrentTick(); diff --git a/src/yuzu/CMakeLists.txt b/src/yuzu/CMakeLists.txt index 982c0eb196..1ed1fdff2a 100644 --- a/src/yuzu/CMakeLists.txt +++ b/src/yuzu/CMakeLists.txt @@ -362,16 +362,27 @@ target_sources(yuzu ${LANGUAGES} ${THEMES}) +# TODO(crueter): Move Assets.car/icon/icns handling to its own Module. if (APPLE) - # Normal icns - set(MACOSX_ICON "${CMAKE_SOURCE_DIR}/dist/eden.icns") - set_source_files_properties(${MACOSX_ICON} PROPERTIES MACOSX_PACKAGE_LOCATION Resources) - target_sources(yuzu PRIVATE ${MACOSX_ICON}) + # Xcode will automatically generate the Assets.car and icns file for us. + set(_dist "${CMAKE_SOURCE_DIR}/dist") + if (CMAKE_GENERATOR MATCHES "Xcode") + set(_icons "${_dist}/eden.icon") - # Liquid glass - set(MACOSX_LIQUID_GLASS_ICON "${CMAKE_SOURCE_DIR}/dist/Assets.car") - set_source_files_properties(${MACOSX_LIQUID_GLASS_ICON} PROPERTIES MACOSX_PACKAGE_LOCATION Resources) - target_sources(yuzu PRIVATE ${MACOSX_LIQUID_GLASS_ICON}) + set_target_properties(eden PROPERTIES + XCODE_ATTRIBUTE_ASSETCATALOG_COMPILER_APPICON_NAME eden + MACOSX_BUNDLE_ICON_FILE eden + # Also force xcode to manage signing for us. + XCODE_ATTRIBUTE_CODE_SIGNING_REQUIRED ON + XCODE_ATTRIBUTE_CODE_SIGNING_ALLOWED ON) + # Otherwise, we'll use our own. + else() + set(_icons "${_dist}/eden.icns" "${_dist}/Assets.car") + endif() + + set_source_files_properties(${_icons} PROPERTIES + MACOSX_PACKAGE_LOCATION Resources) + target_sources(yuzu PRIVATE ${_icons}) set_target_properties(yuzu PROPERTIES MACOSX_BUNDLE TRUE) set_target_properties(yuzu PROPERTIES MACOSX_BUNDLE_INFO_PLIST ${CMAKE_CURRENT_SOURCE_DIR}/Info.plist) @@ -443,10 +454,10 @@ endif() if (NOT MSVC AND (APPLE OR NOT YUZU_STATIC_BUILD)) # needed for vma target_compile_options(yuzu PRIVATE - -Wno-conversion - -Wno-unused-variable - -Wno-unused-parameter - -Wno-missing-field-initializers) + $<$:-Wno-conversion> + $<$:-Wno-unused-variable> + $<$:-Wno-unused-parameter> + $<$:-Wno-missing-field-initializers>) endif() # Remember that the linker is incredibly stupid. diff --git a/src/yuzu/user_data_migration.h b/src/yuzu/user_data_migration.h index df8057eaa5..3b404a1a14 100644 --- a/src/yuzu/user_data_migration.h +++ b/src/yuzu/user_data_migration.h @@ -8,7 +8,7 @@ #pragma once #include -#include "../yuzu/migration_worker.h" +#include "yuzu/migration_worker.h" // TODO(crueter): Quick implementation class UserDataMigrator { diff --git a/src/yuzu_cmd/CMakeLists.txt b/src/yuzu_cmd/CMakeLists.txt index a1f16be75c..8f92525ad6 100644 --- a/src/yuzu_cmd/CMakeLists.txt +++ b/src/yuzu_cmd/CMakeLists.txt @@ -1,4 +1,4 @@ -# SPDX-FileCopyrightText: Copyright 2025 Eden Emulator Project +# SPDX-FileCopyrightText: Copyright 2026 Eden Emulator Project # SPDX-License-Identifier: GPL-3.0-or-later # SPDX-FileCopyrightText: 2018 yuzu Emulator Project @@ -60,8 +60,8 @@ create_target_directory_groups(yuzu-cmd) # needed for vma if (NOT MSVC) target_compile_options(yuzu-cmd PRIVATE - -Wno-conversion - -Wno-unused-variable - -Wno-unused-parameter - -Wno-missing-field-initializers) + $<$:-Wno-conversion> + $<$:-Wno-unused-variable> + $<$:-Wno-unused-parameter> + $<$:-Wno-missing-field-initializers>) endif()