summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/android/app/build.gradle.kts3
-rw-r--r--src/common/fs/path_util.cpp38
-rw-r--r--src/common/fs/path_util.h6
-rw-r--r--src/common/host_memory.cpp38
-rw-r--r--src/common/host_memory.h2
-rw-r--r--src/core/CMakeLists.txt18
-rw-r--r--src/core/arm/nce/arm_nce.cpp107
-rw-r--r--src/core/arm/nce/arm_nce.h13
-rw-r--r--src/core/arm/nce/arm_nce.s60
-rw-r--r--src/core/arm/nce/arm_nce_asm_definitions.h3
-rw-r--r--src/core/arm/nce/interpreter_visitor.cpp825
-rw-r--r--src/core/arm/nce/interpreter_visitor.h103
-rw-r--r--src/core/arm/nce/visitor_base.h2777
-rw-r--r--src/core/file_sys/vfs.cpp8
-rw-r--r--src/core/file_sys/vfs_real.cpp8
-rw-r--r--src/core/hid/input_interpreter.cpp3
-rw-r--r--src/core/hle/kernel/k_memory_manager.cpp5
-rw-r--r--src/core/hle/kernel/k_page_table_base.cpp14
-rw-r--r--src/core/hle/kernel/kernel.cpp15
-rw-r--r--src/core/hle/kernel/kernel.h6
-rw-r--r--src/core/hle/service/filesystem/filesystem.cpp6
-rw-r--r--src/core/hle/service/hid/controllers/applet_resource.cpp39
-rw-r--r--src/core/hle/service/hid/controllers/applet_resource.h7
-rw-r--r--src/core/hle/service/hid/controllers/console_six_axis.cpp21
-rw-r--r--src/core/hle/service/hid/controllers/console_six_axis.h19
-rw-r--r--src/core/hle/service/hid/controllers/controller_base.h3
-rw-r--r--src/core/hle/service/hid/controllers/debug_pad.cpp23
-rw-r--r--src/core/hle/service/hid/controllers/debug_pad.h48
-rw-r--r--src/core/hle/service/hid/controllers/gesture.cpp36
-rw-r--r--src/core/hle/service/hid/controllers/gesture.h90
-rw-r--r--src/core/hle/service/hid/controllers/keyboard.cpp23
-rw-r--r--src/core/hle/service/hid/controllers/keyboard.h33
-rw-r--r--src/core/hle/service/hid/controllers/mouse.cpp19
-rw-r--r--src/core/hle/service/hid/controllers/mouse.h16
-rw-r--r--src/core/hle/service/hid/controllers/npad.cpp28
-rw-r--r--src/core/hle/service/hid/controllers/npad.h314
-rw-r--r--src/core/hle/service/hid/controllers/palma.cpp3
-rw-r--r--src/core/hle/service/hid/controllers/palma.h3
-rw-r--r--src/core/hle/service/hid/controllers/shared_memory_format.h240
-rw-r--r--src/core/hle/service/hid/controllers/shared_memory_holder.cpp53
-rw-r--r--src/core/hle/service/hid/controllers/shared_memory_holder.h44
-rw-r--r--src/core/hle/service/hid/controllers/six_axis.cpp25
-rw-r--r--src/core/hle/service/hid/controllers/stubbed.cpp19
-rw-r--r--src/core/hle/service/hid/controllers/stubbed.h18
-rw-r--r--src/core/hle/service/hid/controllers/touchscreen.cpp24
-rw-r--r--src/core/hle/service/hid/controllers/touchscreen.h32
-rw-r--r--src/core/hle/service/hid/controllers/types/debug_pad_types.h31
-rw-r--r--src/core/hle/service/hid/controllers/types/gesture_types.h77
-rw-r--r--src/core/hle/service/hid/controllers/types/keyboard_types.h20
-rw-r--r--src/core/hle/service/hid/controllers/types/mouse_types.h8
-rw-r--r--src/core/hle/service/hid/controllers/types/npad_types.h254
-rw-r--r--src/core/hle/service/hid/controllers/types/touch_types.h90
-rw-r--r--src/core/hle/service/hid/controllers/xpad.cpp39
-rw-r--r--src/core/hle/service/hid/controllers/xpad.h112
-rw-r--r--src/core/hle/service/hid/hid_server.cpp23
-rw-r--r--src/core/hle/service/hid/hid_system_server.cpp3
-rw-r--r--src/core/hle/service/hid/resource_manager.cpp65
-rw-r--r--src/core/hle/service/hid/resource_manager.h8
-rw-r--r--src/core/hle/service/ssl/ssl.cpp6
-rw-r--r--src/core/memory/cheat_engine.cpp2
-rw-r--r--src/tests/video_core/memory_tracker.cpp6
-rw-r--r--src/video_core/buffer_cache/word_manager.h2
-rw-r--r--src/video_core/rasterizer_accelerated.cpp99
-rw-r--r--src/video_core/rasterizer_accelerated.h29
-rw-r--r--src/video_core/rasterizer_interface.h2
-rw-r--r--src/video_core/shader_cache.cpp4
-rw-r--r--src/video_core/texture_cache/texture_cache.h10
67 files changed, 5086 insertions, 1042 deletions
diff --git a/src/android/app/build.gradle.kts b/src/android/app/build.gradle.kts
index 5721327e7..f763c657e 100644
--- a/src/android/app/build.gradle.kts
+++ b/src/android/app/build.gradle.kts
@@ -174,7 +174,8 @@ android {
174 "-DANDROID_ARM_NEON=true", // cryptopp requires Neon to work 174 "-DANDROID_ARM_NEON=true", // cryptopp requires Neon to work
175 "-DYUZU_USE_BUNDLED_VCPKG=ON", 175 "-DYUZU_USE_BUNDLED_VCPKG=ON",
176 "-DYUZU_USE_BUNDLED_FFMPEG=ON", 176 "-DYUZU_USE_BUNDLED_FFMPEG=ON",
177 "-DYUZU_ENABLE_LTO=ON" 177 "-DYUZU_ENABLE_LTO=ON",
178 "-DCMAKE_EXPORT_COMPILE_COMMANDS=ON"
178 ) 179 )
179 180
180 abiFilters("arm64-v8a", "x86_64") 181 abiFilters("arm64-v8a", "x86_64")
diff --git a/src/common/fs/path_util.cpp b/src/common/fs/path_util.cpp
index c3a81f9a9..d2f50432a 100644
--- a/src/common/fs/path_util.cpp
+++ b/src/common/fs/path_util.cpp
@@ -354,18 +354,36 @@ std::string_view RemoveTrailingSlash(std::string_view path) {
354 return path; 354 return path;
355} 355}
356 356
357std::vector<std::string> SplitPathComponents(std::string_view filename) { 357template <typename F>
358 std::string copy(filename); 358static void ForEachPathComponent(std::string_view filename, F&& cb) {
359 std::replace(copy.begin(), copy.end(), '\\', '/'); 359 const char* component_begin = filename.data();
360 std::vector<std::string> out; 360 const char* const end = component_begin + filename.size();
361 361 for (const char* it = component_begin; it != end; ++it) {
362 std::stringstream stream(copy); 362 const char c = *it;
363 std::string item; 363 if (c == '\\' || c == '/') {
364 while (std::getline(stream, item, '/')) { 364 if (component_begin != it) {
365 out.push_back(std::move(item)); 365 cb(std::string_view{component_begin, it});
366 }
367 component_begin = it + 1;
368 }
366 } 369 }
370 if (component_begin != end) {
371 cb(std::string_view{component_begin, end});
372 }
373}
374
375std::vector<std::string_view> SplitPathComponents(std::string_view filename) {
376 std::vector<std::string_view> components;
377 ForEachPathComponent(filename, [&](auto component) { components.emplace_back(component); });
378
379 return components;
380}
381
382std::vector<std::string> SplitPathComponentsCopy(std::string_view filename) {
383 std::vector<std::string> components;
384 ForEachPathComponent(filename, [&](auto component) { components.emplace_back(component); });
367 385
368 return out; 386 return components;
369} 387}
370 388
371std::string SanitizePath(std::string_view path_, DirectorySeparator directory_separator) { 389std::string SanitizePath(std::string_view path_, DirectorySeparator directory_separator) {
diff --git a/src/common/fs/path_util.h b/src/common/fs/path_util.h
index 2874ea738..23c8b1359 100644
--- a/src/common/fs/path_util.h
+++ b/src/common/fs/path_util.h
@@ -289,7 +289,11 @@ enum class DirectorySeparator {
289 289
290// Splits the path on '/' or '\' and put the components into a vector 290// Splits the path on '/' or '\' and put the components into a vector
291// i.e. "C:\Users\Yuzu\Documents\save.bin" becomes {"C:", "Users", "Yuzu", "Documents", "save.bin" } 291// i.e. "C:\Users\Yuzu\Documents\save.bin" becomes {"C:", "Users", "Yuzu", "Documents", "save.bin" }
292[[nodiscard]] std::vector<std::string> SplitPathComponents(std::string_view filename); 292[[nodiscard]] std::vector<std::string_view> SplitPathComponents(std::string_view filename);
293
294// Splits the path on '/' or '\' and put the components into a vector
295// i.e. "C:\Users\Yuzu\Documents\save.bin" becomes {"C:", "Users", "Yuzu", "Documents", "save.bin" }
296[[nodiscard]] std::vector<std::string> SplitPathComponentsCopy(std::string_view filename);
293 297
294// Removes trailing slash, makes all '\\' into '/', and removes duplicate '/'. Makes '/' into '\\' 298// Removes trailing slash, makes all '\\' into '/', and removes duplicate '/'. Makes '/' into '\\'
295// depending if directory_separator is BackwardSlash or PlatformDefault and running on windows 299// depending if directory_separator is BackwardSlash or PlatformDefault and running on windows
diff --git a/src/common/host_memory.cpp b/src/common/host_memory.cpp
index 4bfc64f2d..e540375b8 100644
--- a/src/common/host_memory.cpp
+++ b/src/common/host_memory.cpp
@@ -11,10 +11,6 @@
11 11
12#elif defined(__linux__) || defined(__FreeBSD__) // ^^^ Windows ^^^ vvv Linux vvv 12#elif defined(__linux__) || defined(__FreeBSD__) // ^^^ Windows ^^^ vvv Linux vvv
13 13
14#ifdef ANDROID
15#include <android/sharedmem.h>
16#endif
17
18#ifndef _GNU_SOURCE 14#ifndef _GNU_SOURCE
19#define _GNU_SOURCE 15#define _GNU_SOURCE
20#endif 16#endif
@@ -193,6 +189,11 @@ public:
193 } 189 }
194 } 190 }
195 191
192 bool ClearBackingRegion(size_t physical_offset, size_t length) {
193 // TODO: This does not seem to be possible on Windows.
194 return false;
195 }
196
196 void EnableDirectMappedAddress() { 197 void EnableDirectMappedAddress() {
197 // TODO 198 // TODO
198 UNREACHABLE(); 199 UNREACHABLE();
@@ -442,9 +443,7 @@ public:
442 } 443 }
443 444
444 // Backing memory initialization 445 // Backing memory initialization
445#ifdef ANDROID 446#if defined(__FreeBSD__) && __FreeBSD__ < 13
446 fd = ASharedMemory_create("HostMemory", backing_size);
447#elif defined(__FreeBSD__) && __FreeBSD__ < 13
448 // XXX Drop after FreeBSD 12.* reaches EOL on 2024-06-30 447 // XXX Drop after FreeBSD 12.* reaches EOL on 2024-06-30
449 fd = shm_open(SHM_ANON, O_RDWR, 0600); 448 fd = shm_open(SHM_ANON, O_RDWR, 0600);
450#else 449#else
@@ -455,7 +454,6 @@ public:
455 throw std::bad_alloc{}; 454 throw std::bad_alloc{};
456 } 455 }
457 456
458#ifndef ANDROID
459 // Defined to extend the file with zeros 457 // Defined to extend the file with zeros
460 int ret = ftruncate(fd, backing_size); 458 int ret = ftruncate(fd, backing_size);
461 if (ret != 0) { 459 if (ret != 0) {
@@ -463,7 +461,6 @@ public:
463 strerror(errno)); 461 strerror(errno));
464 throw std::bad_alloc{}; 462 throw std::bad_alloc{};
465 } 463 }
466#endif
467 464
468 backing_base = static_cast<u8*>( 465 backing_base = static_cast<u8*>(
469 mmap(nullptr, backing_size, PROT_READ | PROT_WRITE, MAP_SHARED, fd, 0)); 466 mmap(nullptr, backing_size, PROT_READ | PROT_WRITE, MAP_SHARED, fd, 0));
@@ -552,6 +549,19 @@ public:
552 ASSERT_MSG(ret == 0, "mprotect failed: {}", strerror(errno)); 549 ASSERT_MSG(ret == 0, "mprotect failed: {}", strerror(errno));
553 } 550 }
554 551
552 bool ClearBackingRegion(size_t physical_offset, size_t length) {
553#ifdef __linux__
554 // Set MADV_REMOVE on backing map to destroy it instantly.
555 // This also deletes the area from the backing file.
556 int ret = madvise(backing_base + physical_offset, length, MADV_REMOVE);
557 ASSERT_MSG(ret == 0, "madvise failed: {}", strerror(errno));
558
559 return true;
560#else
561 return false;
562#endif
563 }
564
555 void EnableDirectMappedAddress() { 565 void EnableDirectMappedAddress() {
556 virtual_base = nullptr; 566 virtual_base = nullptr;
557 } 567 }
@@ -623,6 +633,10 @@ public:
623 633
624 void Protect(size_t virtual_offset, size_t length, bool read, bool write, bool execute) {} 634 void Protect(size_t virtual_offset, size_t length, bool read, bool write, bool execute) {}
625 635
636 bool ClearBackingRegion(size_t physical_offset, size_t length) {
637 return false;
638 }
639
626 void EnableDirectMappedAddress() {} 640 void EnableDirectMappedAddress() {}
627 641
628 u8* backing_base{nullptr}; 642 u8* backing_base{nullptr};
@@ -698,6 +712,12 @@ void HostMemory::Protect(size_t virtual_offset, size_t length, bool read, bool w
698 impl->Protect(virtual_offset + virtual_base_offset, length, read, write, execute); 712 impl->Protect(virtual_offset + virtual_base_offset, length, read, write, execute);
699} 713}
700 714
715void HostMemory::ClearBackingRegion(size_t physical_offset, size_t length, u32 fill_value) {
716 if (!impl || fill_value != 0 || !impl->ClearBackingRegion(physical_offset, length)) {
717 std::memset(backing_base + physical_offset, fill_value, length);
718 }
719}
720
701void HostMemory::EnableDirectMappedAddress() { 721void HostMemory::EnableDirectMappedAddress() {
702 if (impl) { 722 if (impl) {
703 impl->EnableDirectMappedAddress(); 723 impl->EnableDirectMappedAddress();
diff --git a/src/common/host_memory.h b/src/common/host_memory.h
index cebfacab2..747c5850c 100644
--- a/src/common/host_memory.h
+++ b/src/common/host_memory.h
@@ -48,6 +48,8 @@ public:
48 48
49 void EnableDirectMappedAddress(); 49 void EnableDirectMappedAddress();
50 50
51 void ClearBackingRegion(size_t physical_offset, size_t length, u32 fill_value);
52
51 [[nodiscard]] u8* BackingBasePointer() noexcept { 53 [[nodiscard]] u8* BackingBasePointer() noexcept {
52 return backing_base; 54 return backing_base;
53 } 55 }
diff --git a/src/core/CMakeLists.txt b/src/core/CMakeLists.txt
index 1ff90bbaf..96ab39cb8 100644
--- a/src/core/CMakeLists.txt
+++ b/src/core/CMakeLists.txt
@@ -549,6 +549,11 @@ add_library(core STATIC
549 hle/service/hid/xcd.cpp 549 hle/service/hid/xcd.cpp
550 hle/service/hid/xcd.h 550 hle/service/hid/xcd.h
551 hle/service/hid/errors.h 551 hle/service/hid/errors.h
552 hle/service/hid/controllers/types/debug_pad_types.h
553 hle/service/hid/controllers/types/keyboard_types.h
554 hle/service/hid/controllers/types/mouse_types.h
555 hle/service/hid/controllers/types/npad_types.h
556 hle/service/hid/controllers/types/touch_types.h
552 hle/service/hid/controllers/applet_resource.cpp 557 hle/service/hid/controllers/applet_resource.cpp
553 hle/service/hid/controllers/applet_resource.h 558 hle/service/hid/controllers/applet_resource.h
554 hle/service/hid/controllers/console_six_axis.cpp 559 hle/service/hid/controllers/console_six_axis.cpp
@@ -569,14 +574,15 @@ add_library(core STATIC
569 hle/service/hid/controllers/palma.h 574 hle/service/hid/controllers/palma.h
570 hle/service/hid/controllers/seven_six_axis.cpp 575 hle/service/hid/controllers/seven_six_axis.cpp
571 hle/service/hid/controllers/seven_six_axis.h 576 hle/service/hid/controllers/seven_six_axis.h
577 hle/service/hid/controllers/shared_memory_format.h
578 hle/service/hid/controllers/shared_memory_holder.cpp
579 hle/service/hid/controllers/shared_memory_holder.h
572 hle/service/hid/controllers/six_axis.cpp 580 hle/service/hid/controllers/six_axis.cpp
573 hle/service/hid/controllers/six_axis.h 581 hle/service/hid/controllers/six_axis.h
574 hle/service/hid/controllers/stubbed.cpp 582 hle/service/hid/controllers/stubbed.cpp
575 hle/service/hid/controllers/stubbed.h 583 hle/service/hid/controllers/stubbed.h
576 hle/service/hid/controllers/touchscreen.cpp 584 hle/service/hid/controllers/touchscreen.cpp
577 hle/service/hid/controllers/touchscreen.h 585 hle/service/hid/controllers/touchscreen.h
578 hle/service/hid/controllers/xpad.cpp
579 hle/service/hid/controllers/xpad.h
580 hle/service/hid/hidbus/hidbus_base.cpp 586 hle/service/hid/hidbus/hidbus_base.cpp
581 hle/service/hid/hidbus/hidbus_base.h 587 hle/service/hid/hidbus/hidbus_base.h
582 hle/service/hid/hidbus/ringcon.cpp 588 hle/service/hid/hidbus/ringcon.cpp
@@ -955,15 +961,19 @@ if (HAS_NCE)
955 set(CMAKE_ASM_FLAGS "${CFLAGS} -x assembler-with-cpp") 961 set(CMAKE_ASM_FLAGS "${CFLAGS} -x assembler-with-cpp")
956 962
957 target_sources(core PRIVATE 963 target_sources(core PRIVATE
964 arm/nce/arm_nce_asm_definitions.h
958 arm/nce/arm_nce.cpp 965 arm/nce/arm_nce.cpp
959 arm/nce/arm_nce.h 966 arm/nce/arm_nce.h
960 arm/nce/arm_nce.s 967 arm/nce/arm_nce.s
961 arm/nce/guest_context.h 968 arm/nce/guest_context.h
969 arm/nce/instructions.h
970 arm/nce/interpreter_visitor.cpp
971 arm/nce/interpreter_visitor.h
962 arm/nce/patcher.cpp 972 arm/nce/patcher.cpp
963 arm/nce/patcher.h 973 arm/nce/patcher.h
964 arm/nce/instructions.h 974 arm/nce/visitor_base.h
965 ) 975 )
966 target_link_libraries(core PRIVATE merry::oaknut) 976 target_link_libraries(core PRIVATE merry::mcl merry::oaknut)
967endif() 977endif()
968 978
969if (ARCHITECTURE_x86_64 OR ARCHITECTURE_arm64) 979if (ARCHITECTURE_x86_64 OR ARCHITECTURE_arm64)
diff --git a/src/core/arm/nce/arm_nce.cpp b/src/core/arm/nce/arm_nce.cpp
index b42a32a0b..1311e66a9 100644
--- a/src/core/arm/nce/arm_nce.cpp
+++ b/src/core/arm/nce/arm_nce.cpp
@@ -6,7 +6,7 @@
6 6
7#include "common/signal_chain.h" 7#include "common/signal_chain.h"
8#include "core/arm/nce/arm_nce.h" 8#include "core/arm/nce/arm_nce.h"
9#include "core/arm/nce/guest_context.h" 9#include "core/arm/nce/interpreter_visitor.h"
10#include "core/arm/nce/patcher.h" 10#include "core/arm/nce/patcher.h"
11#include "core/core.h" 11#include "core/core.h"
12#include "core/memory.h" 12#include "core/memory.h"
@@ -21,7 +21,8 @@ namespace Core {
21 21
22namespace { 22namespace {
23 23
24struct sigaction g_orig_action; 24struct sigaction g_orig_bus_action;
25struct sigaction g_orig_segv_action;
25 26
26// Verify assembly offsets. 27// Verify assembly offsets.
27using NativeExecutionParameters = Kernel::KThread::NativeExecutionParameters; 28using NativeExecutionParameters = Kernel::KThread::NativeExecutionParameters;
@@ -37,6 +38,9 @@ fpsimd_context* GetFloatingPointState(mcontext_t& host_ctx) {
37 return reinterpret_cast<fpsimd_context*>(header); 38 return reinterpret_cast<fpsimd_context*>(header);
38} 39}
39 40
41using namespace Common::Literals;
42constexpr u32 StackSize = 32_KiB;
43
40} // namespace 44} // namespace
41 45
42void* ArmNce::RestoreGuestContext(void* raw_context) { 46void* ArmNce::RestoreGuestContext(void* raw_context) {
@@ -104,19 +108,10 @@ void ArmNce::SaveGuestContext(GuestContext* guest_ctx, void* raw_context) {
104 host_ctx.regs[0] = guest_ctx->esr_el1.exchange(0); 108 host_ctx.regs[0] = guest_ctx->esr_el1.exchange(0);
105} 109}
106 110
107bool ArmNce::HandleGuestFault(GuestContext* guest_ctx, void* raw_info, void* raw_context) { 111bool ArmNce::HandleFailedGuestFault(GuestContext* guest_ctx, void* raw_info, void* raw_context) {
108 auto& host_ctx = static_cast<ucontext_t*>(raw_context)->uc_mcontext; 112 auto& host_ctx = static_cast<ucontext_t*>(raw_context)->uc_mcontext;
109 auto* info = static_cast<siginfo_t*>(raw_info); 113 auto* info = static_cast<siginfo_t*>(raw_info);
110 114
111 // Try to handle an invalid access.
112 // TODO: handle accesses which split a page?
113 const Common::ProcessAddress addr =
114 (reinterpret_cast<u64>(info->si_addr) & ~Memory::YUZU_PAGEMASK);
115 if (guest_ctx->system->ApplicationMemory().InvalidateNCE(addr, Memory::YUZU_PAGESIZE)) {
116 // We handled the access successfully and are returning to guest code.
117 return true;
118 }
119
120 // We can't handle the access, so determine why we crashed. 115 // We can't handle the access, so determine why we crashed.
121 const bool is_prefetch_abort = host_ctx.pc == reinterpret_cast<u64>(info->si_addr); 116 const bool is_prefetch_abort = host_ctx.pc == reinterpret_cast<u64>(info->si_addr);
122 117
@@ -143,8 +138,44 @@ bool ArmNce::HandleGuestFault(GuestContext* guest_ctx, void* raw_info, void* raw
143 return false; 138 return false;
144} 139}
145 140
146void ArmNce::HandleHostFault(int sig, void* raw_info, void* raw_context) { 141bool ArmNce::HandleGuestAlignmentFault(GuestContext* guest_ctx, void* raw_info, void* raw_context) {
147 return g_orig_action.sa_sigaction(sig, static_cast<siginfo_t*>(raw_info), raw_context); 142 auto& host_ctx = static_cast<ucontext_t*>(raw_context)->uc_mcontext;
143 auto* fpctx = GetFloatingPointState(host_ctx);
144 auto& memory = guest_ctx->system->ApplicationMemory();
145
146 // Match and execute an instruction.
147 auto next_pc = MatchAndExecuteOneInstruction(memory, &host_ctx, fpctx);
148 if (next_pc) {
149 host_ctx.pc = *next_pc;
150 return true;
151 }
152
153 // We couldn't handle the access.
154 return HandleFailedGuestFault(guest_ctx, raw_info, raw_context);
155}
156
157bool ArmNce::HandleGuestAccessFault(GuestContext* guest_ctx, void* raw_info, void* raw_context) {
158 auto* info = static_cast<siginfo_t*>(raw_info);
159
160 // Try to handle an invalid access.
161 // TODO: handle accesses which split a page?
162 const Common::ProcessAddress addr =
163 (reinterpret_cast<u64>(info->si_addr) & ~Memory::YUZU_PAGEMASK);
164 if (guest_ctx->system->ApplicationMemory().InvalidateNCE(addr, Memory::YUZU_PAGESIZE)) {
165 // We handled the access successfully and are returning to guest code.
166 return true;
167 }
168
169 // We couldn't handle the access.
170 return HandleFailedGuestFault(guest_ctx, raw_info, raw_context);
171}
172
173void ArmNce::HandleHostAlignmentFault(int sig, void* raw_info, void* raw_context) {
174 return g_orig_bus_action.sa_sigaction(sig, static_cast<siginfo_t*>(raw_info), raw_context);
175}
176
177void ArmNce::HandleHostAccessFault(int sig, void* raw_info, void* raw_context) {
178 return g_orig_segv_action.sa_sigaction(sig, static_cast<siginfo_t*>(raw_info), raw_context);
148} 179}
149 180
150void ArmNce::LockThread(Kernel::KThread* thread) { 181void ArmNce::LockThread(Kernel::KThread* thread) {
@@ -225,18 +256,31 @@ ArmNce::ArmNce(System& system, bool uses_wall_clock, std::size_t core_index)
225ArmNce::~ArmNce() = default; 256ArmNce::~ArmNce() = default;
226 257
227void ArmNce::Initialize() { 258void ArmNce::Initialize() {
228 m_thread_id = gettid(); 259 if (m_thread_id == -1) {
260 m_thread_id = gettid();
261 }
262
263 // Configure signal stack.
264 if (!m_stack) {
265 m_stack = std::make_unique<u8[]>(StackSize);
266
267 stack_t ss{};
268 ss.ss_sp = m_stack.get();
269 ss.ss_size = StackSize;
270 sigaltstack(&ss, nullptr);
271 }
229 272
230 // Setup our signals 273 // Set up signals.
231 static std::once_flag signals; 274 static std::once_flag flag;
232 std::call_once(signals, [] { 275 std::call_once(flag, [] {
233 using HandlerType = decltype(sigaction::sa_sigaction); 276 using HandlerType = decltype(sigaction::sa_sigaction);
234 277
235 sigset_t signal_mask; 278 sigset_t signal_mask;
236 sigemptyset(&signal_mask); 279 sigemptyset(&signal_mask);
237 sigaddset(&signal_mask, ReturnToRunCodeByExceptionLevelChangeSignal); 280 sigaddset(&signal_mask, ReturnToRunCodeByExceptionLevelChangeSignal);
238 sigaddset(&signal_mask, BreakFromRunCodeSignal); 281 sigaddset(&signal_mask, BreakFromRunCodeSignal);
239 sigaddset(&signal_mask, GuestFaultSignal); 282 sigaddset(&signal_mask, GuestAlignmentFaultSignal);
283 sigaddset(&signal_mask, GuestAccessFaultSignal);
240 284
241 struct sigaction return_to_run_code_action {}; 285 struct sigaction return_to_run_code_action {};
242 return_to_run_code_action.sa_flags = SA_SIGINFO | SA_ONSTACK; 286 return_to_run_code_action.sa_flags = SA_SIGINFO | SA_ONSTACK;
@@ -253,18 +297,19 @@ void ArmNce::Initialize() {
253 break_from_run_code_action.sa_mask = signal_mask; 297 break_from_run_code_action.sa_mask = signal_mask;
254 Common::SigAction(BreakFromRunCodeSignal, &break_from_run_code_action, nullptr); 298 Common::SigAction(BreakFromRunCodeSignal, &break_from_run_code_action, nullptr);
255 299
256 struct sigaction fault_action {}; 300 struct sigaction alignment_fault_action {};
257 fault_action.sa_flags = SA_SIGINFO | SA_ONSTACK | SA_RESTART; 301 alignment_fault_action.sa_flags = SA_SIGINFO | SA_ONSTACK;
258 fault_action.sa_sigaction = reinterpret_cast<HandlerType>(&ArmNce::GuestFaultSignalHandler); 302 alignment_fault_action.sa_sigaction =
259 fault_action.sa_mask = signal_mask; 303 reinterpret_cast<HandlerType>(&ArmNce::GuestAlignmentFaultSignalHandler);
260 Common::SigAction(GuestFaultSignal, &fault_action, &g_orig_action); 304 alignment_fault_action.sa_mask = signal_mask;
261 305 Common::SigAction(GuestAlignmentFaultSignal, &alignment_fault_action, nullptr);
262 // Simplify call for g_orig_action. 306
263 // These fields occupy the same space in memory, so this should be a no-op in practice. 307 struct sigaction access_fault_action {};
264 if (!(g_orig_action.sa_flags & SA_SIGINFO)) { 308 access_fault_action.sa_flags = SA_SIGINFO | SA_ONSTACK | SA_RESTART;
265 g_orig_action.sa_sigaction = 309 access_fault_action.sa_sigaction =
266 reinterpret_cast<decltype(g_orig_action.sa_sigaction)>(g_orig_action.sa_handler); 310 reinterpret_cast<HandlerType>(&ArmNce::GuestAccessFaultSignalHandler);
267 } 311 access_fault_action.sa_mask = signal_mask;
312 Common::SigAction(GuestAccessFaultSignal, &access_fault_action, &g_orig_segv_action);
268 }); 313 });
269} 314}
270 315
diff --git a/src/core/arm/nce/arm_nce.h b/src/core/arm/nce/arm_nce.h
index f55c10d1d..be9b304c4 100644
--- a/src/core/arm/nce/arm_nce.h
+++ b/src/core/arm/nce/arm_nce.h
@@ -61,7 +61,8 @@ private:
61 static void ReturnToRunCodeByExceptionLevelChangeSignalHandler(int sig, void* info, 61 static void ReturnToRunCodeByExceptionLevelChangeSignalHandler(int sig, void* info,
62 void* raw_context); 62 void* raw_context);
63 static void BreakFromRunCodeSignalHandler(int sig, void* info, void* raw_context); 63 static void BreakFromRunCodeSignalHandler(int sig, void* info, void* raw_context);
64 static void GuestFaultSignalHandler(int sig, void* info, void* raw_context); 64 static void GuestAlignmentFaultSignalHandler(int sig, void* info, void* raw_context);
65 static void GuestAccessFaultSignalHandler(int sig, void* info, void* raw_context);
65 66
66 static void LockThreadParameters(void* tpidr); 67 static void LockThreadParameters(void* tpidr);
67 static void UnlockThreadParameters(void* tpidr); 68 static void UnlockThreadParameters(void* tpidr);
@@ -70,8 +71,11 @@ private:
70 // C++ implementation functions for assembly definitions. 71 // C++ implementation functions for assembly definitions.
71 static void* RestoreGuestContext(void* raw_context); 72 static void* RestoreGuestContext(void* raw_context);
72 static void SaveGuestContext(GuestContext* ctx, void* raw_context); 73 static void SaveGuestContext(GuestContext* ctx, void* raw_context);
73 static bool HandleGuestFault(GuestContext* ctx, void* info, void* raw_context); 74 static bool HandleFailedGuestFault(GuestContext* ctx, void* info, void* raw_context);
74 static void HandleHostFault(int sig, void* info, void* raw_context); 75 static bool HandleGuestAlignmentFault(GuestContext* ctx, void* info, void* raw_context);
76 static bool HandleGuestAccessFault(GuestContext* ctx, void* info, void* raw_context);
77 static void HandleHostAlignmentFault(int sig, void* info, void* raw_context);
78 static void HandleHostAccessFault(int sig, void* info, void* raw_context);
75 79
76public: 80public:
77 Core::System& m_system; 81 Core::System& m_system;
@@ -83,6 +87,9 @@ public:
83 // Core context. 87 // Core context.
84 GuestContext m_guest_ctx{}; 88 GuestContext m_guest_ctx{};
85 Kernel::KThread* m_running_thread{}; 89 Kernel::KThread* m_running_thread{};
90
91 // Stack for signal processing.
92 std::unique_ptr<u8[]> m_stack{};
86}; 93};
87 94
88} // namespace Core 95} // namespace Core
diff --git a/src/core/arm/nce/arm_nce.s b/src/core/arm/nce/arm_nce.s
index 4aeda4740..c68c05949 100644
--- a/src/core/arm/nce/arm_nce.s
+++ b/src/core/arm/nce/arm_nce.s
@@ -130,11 +130,11 @@ _ZN4Core6ArmNce29BreakFromRunCodeSignalHandlerEiPvS1_:
130 ret 130 ret
131 131
132 132
133/* static void Core::ArmNce::GuestFaultSignalHandler(int sig, void* info, void* raw_context) */ 133/* static void Core::ArmNce::GuestAlignmentFaultSignalHandler(int sig, void* info, void* raw_context) */
134.section .text._ZN4Core6ArmNce23GuestFaultSignalHandlerEiPvS1_, "ax", %progbits 134.section .text._ZN4Core6ArmNce32GuestAlignmentFaultSignalHandlerEiPvS1_, "ax", %progbits
135.global _ZN4Core6ArmNce23GuestFaultSignalHandlerEiPvS1_ 135.global _ZN4Core6ArmNce32GuestAlignmentFaultSignalHandlerEiPvS1_
136.type _ZN4Core6ArmNce23GuestFaultSignalHandlerEiPvS1_, %function 136.type _ZN4Core6ArmNce32GuestAlignmentFaultSignalHandlerEiPvS1_, %function
137_ZN4Core6ArmNce23GuestFaultSignalHandlerEiPvS1_: 137_ZN4Core6ArmNce32GuestAlignmentFaultSignalHandlerEiPvS1_:
138 /* Check to see if we have the correct TLS magic. */ 138 /* Check to see if we have the correct TLS magic. */
139 mrs x8, tpidr_el0 139 mrs x8, tpidr_el0
140 ldr w9, [x8, #(TpidrEl0TlsMagic)] 140 ldr w9, [x8, #(TpidrEl0TlsMagic)]
@@ -146,7 +146,7 @@ _ZN4Core6ArmNce23GuestFaultSignalHandlerEiPvS1_:
146 146
147 /* Incorrect TLS magic, so this is a host fault. */ 147 /* Incorrect TLS magic, so this is a host fault. */
148 /* Tail call the handler. */ 148 /* Tail call the handler. */
149 b _ZN4Core6ArmNce15HandleHostFaultEiPvS1_ 149 b _ZN4Core6ArmNce24HandleHostAlignmentFaultEiPvS1_
150 150
1511: 1511:
152 /* Correct TLS magic, so this is a guest fault. */ 152 /* Correct TLS magic, so this is a guest fault. */
@@ -163,7 +163,53 @@ _ZN4Core6ArmNce23GuestFaultSignalHandlerEiPvS1_:
163 msr tpidr_el0, x3 163 msr tpidr_el0, x3
164 164
165 /* Call the handler. */ 165 /* Call the handler. */
166 bl _ZN4Core6ArmNce16HandleGuestFaultEPNS_12GuestContextEPvS3_ 166 bl _ZN4Core6ArmNce25HandleGuestAlignmentFaultEPNS_12GuestContextEPvS3_
167
168 /* If the handler returned false, we want to preserve the host tpidr_el0. */
169 cbz x0, 2f
170
171 /* Otherwise, restore guest tpidr_el0. */
172 msr tpidr_el0, x19
173
1742:
175 ldr x19, [sp, #0x10]
176 ldp x29, x30, [sp], #0x20
177 ret
178
179/* static void Core::ArmNce::GuestAccessFaultSignalHandler(int sig, void* info, void* raw_context) */
180.section .text._ZN4Core6ArmNce29GuestAccessFaultSignalHandlerEiPvS1_, "ax", %progbits
181.global _ZN4Core6ArmNce29GuestAccessFaultSignalHandlerEiPvS1_
182.type _ZN4Core6ArmNce29GuestAccessFaultSignalHandlerEiPvS1_, %function
183_ZN4Core6ArmNce29GuestAccessFaultSignalHandlerEiPvS1_:
184 /* Check to see if we have the correct TLS magic. */
185 mrs x8, tpidr_el0
186 ldr w9, [x8, #(TpidrEl0TlsMagic)]
187
188 LOAD_IMMEDIATE_32(w10, TlsMagic)
189
190 cmp w9, w10
191 b.eq 1f
192
193 /* Incorrect TLS magic, so this is a host fault. */
194 /* Tail call the handler. */
195 b _ZN4Core6ArmNce21HandleHostAccessFaultEiPvS1_
196
1971:
198 /* Correct TLS magic, so this is a guest fault. */
199 stp x29, x30, [sp, #-0x20]!
200 str x19, [sp, #0x10]
201 mov x29, sp
202
203 /* Save the old tpidr_el0. */
204 mov x19, x8
205
206 /* Restore host tpidr_el0. */
207 ldr x0, [x8, #(TpidrEl0NativeContext)]
208 ldr x3, [x0, #(GuestContextHostContext + HostContextTpidrEl0)]
209 msr tpidr_el0, x3
210
211 /* Call the handler. */
212 bl _ZN4Core6ArmNce22HandleGuestAccessFaultEPNS_12GuestContextEPvS3_
167 213
168 /* If the handler returned false, we want to preserve the host tpidr_el0. */ 214 /* If the handler returned false, we want to preserve the host tpidr_el0. */
169 cbz x0, 2f 215 cbz x0, 2f
diff --git a/src/core/arm/nce/arm_nce_asm_definitions.h b/src/core/arm/nce/arm_nce_asm_definitions.h
index 8a9b285b5..8ea4383f7 100644
--- a/src/core/arm/nce/arm_nce_asm_definitions.h
+++ b/src/core/arm/nce/arm_nce_asm_definitions.h
@@ -10,7 +10,8 @@
10 10
11#define ReturnToRunCodeByExceptionLevelChangeSignal SIGUSR2 11#define ReturnToRunCodeByExceptionLevelChangeSignal SIGUSR2
12#define BreakFromRunCodeSignal SIGURG 12#define BreakFromRunCodeSignal SIGURG
13#define GuestFaultSignal SIGSEGV 13#define GuestAccessFaultSignal SIGSEGV
14#define GuestAlignmentFaultSignal SIGBUS
14 15
15#define GuestContextSp 0xF8 16#define GuestContextSp 0xF8
16#define GuestContextHostContext 0x320 17#define GuestContextHostContext 0x320
diff --git a/src/core/arm/nce/interpreter_visitor.cpp b/src/core/arm/nce/interpreter_visitor.cpp
new file mode 100644
index 000000000..8e81c66a5
--- /dev/null
+++ b/src/core/arm/nce/interpreter_visitor.cpp
@@ -0,0 +1,825 @@
1// SPDX-FileCopyrightText: Copyright 2023 yuzu Emulator Project
2// SPDX-FileCopyrightText: Copyright 2023 merryhime <https://mary.rs>
3// SPDX-License-Identifier: GPL-2.0-or-later
4
5#include "common/bit_cast.h"
6#include "core/arm/nce/interpreter_visitor.h"
7
8#include <dynarmic/frontend/A64/decoder/a64.h>
9
10namespace Core {
11
12template <u32 BitSize>
13u64 SignExtendToLong(u64 value) {
14 u64 mask = 1ULL << (BitSize - 1);
15 value &= (1ULL << BitSize) - 1;
16 return (value ^ mask) - mask;
17}
18
19static u64 SignExtendToLong(u64 value, u64 bitsize) {
20 switch (bitsize) {
21 case 8:
22 return SignExtendToLong<8>(value);
23 case 16:
24 return SignExtendToLong<16>(value);
25 case 32:
26 return SignExtendToLong<32>(value);
27 default:
28 return value;
29 }
30}
31
32template <u64 BitSize>
33u32 SignExtendToWord(u32 value) {
34 u32 mask = 1ULL << (BitSize - 1);
35 value &= (1ULL << BitSize) - 1;
36 return (value ^ mask) - mask;
37}
38
39static u32 SignExtendToWord(u32 value, u64 bitsize) {
40 switch (bitsize) {
41 case 8:
42 return SignExtendToWord<8>(value);
43 case 16:
44 return SignExtendToWord<16>(value);
45 default:
46 return value;
47 }
48}
49
50static u64 SignExtend(u64 value, u64 bitsize, u64 regsize) {
51 if (regsize == 64) {
52 return SignExtendToLong(value, bitsize);
53 } else {
54 return SignExtendToWord(static_cast<u32>(value), bitsize);
55 }
56}
57
58static u128 VectorGetElement(u128 value, u64 bitsize) {
59 switch (bitsize) {
60 case 8:
61 return {value[0] & ((1ULL << 8) - 1), 0};
62 case 16:
63 return {value[0] & ((1ULL << 16) - 1), 0};
64 case 32:
65 return {value[0] & ((1ULL << 32) - 1), 0};
66 case 64:
67 return {value[0], 0};
68 default:
69 return value;
70 }
71}
72
73u64 InterpreterVisitor::ExtendReg(size_t bitsize, Reg reg, Imm<3> option, u8 shift) {
74 ASSERT(shift <= 4);
75 ASSERT(bitsize == 32 || bitsize == 64);
76 u64 val = this->GetReg(reg);
77 size_t len;
78 u64 extended;
79 bool signed_extend;
80
81 switch (option.ZeroExtend()) {
82 case 0b000: { // UXTB
83 val &= ((1ULL << 8) - 1);
84 len = 8;
85 signed_extend = false;
86 break;
87 }
88 case 0b001: { // UXTH
89 val &= ((1ULL << 16) - 1);
90 len = 16;
91 signed_extend = false;
92 break;
93 }
94 case 0b010: { // UXTW
95 val &= ((1ULL << 32) - 1);
96 len = 32;
97 signed_extend = false;
98 break;
99 }
100 case 0b011: { // UXTX
101 len = 64;
102 signed_extend = false;
103 break;
104 }
105 case 0b100: { // SXTB
106 val &= ((1ULL << 8) - 1);
107 len = 8;
108 signed_extend = true;
109 break;
110 }
111 case 0b101: { // SXTH
112 val &= ((1ULL << 16) - 1);
113 len = 16;
114 signed_extend = true;
115 break;
116 }
117 case 0b110: { // SXTW
118 val &= ((1ULL << 32) - 1);
119 len = 32;
120 signed_extend = true;
121 break;
122 }
123 case 0b111: { // SXTX
124 len = 64;
125 signed_extend = true;
126 break;
127 }
128 default:
129 UNREACHABLE();
130 }
131
132 if (len < bitsize && signed_extend) {
133 extended = SignExtend(val, len, bitsize);
134 } else {
135 extended = val;
136 }
137
138 return extended << shift;
139}
140
141u128 InterpreterVisitor::GetVec(Vec v) {
142 return m_fpsimd_regs[static_cast<u32>(v)];
143}
144
145u64 InterpreterVisitor::GetReg(Reg r) {
146 return m_regs[static_cast<u32>(r)];
147}
148
149u64 InterpreterVisitor::GetSp() {
150 return m_sp;
151}
152
153u64 InterpreterVisitor::GetPc() {
154 return m_pc;
155}
156
157void InterpreterVisitor::SetVec(Vec v, u128 value) {
158 m_fpsimd_regs[static_cast<u32>(v)] = value;
159}
160
161void InterpreterVisitor::SetReg(Reg r, u64 value) {
162 m_regs[static_cast<u32>(r)] = value;
163}
164
165void InterpreterVisitor::SetSp(u64 value) {
166 m_sp = value;
167}
168
169bool InterpreterVisitor::Ordered(size_t size, bool L, bool o0, Reg Rn, Reg Rt) {
170 const auto memop = L ? MemOp::Load : MemOp::Store;
171 const size_t elsize = 8 << size;
172 const size_t datasize = elsize;
173
174 // Operation
175 const size_t dbytes = datasize / 8;
176
177 u64 address;
178 if (Rn == Reg::SP) {
179 address = this->GetSp();
180 } else {
181 address = this->GetReg(Rn);
182 }
183
184 switch (memop) {
185 case MemOp::Store: {
186 std::atomic_thread_fence(std::memory_order_seq_cst);
187 u64 value = this->GetReg(Rt);
188 m_memory.WriteBlock(address, &value, dbytes);
189 std::atomic_thread_fence(std::memory_order_seq_cst);
190 break;
191 }
192 case MemOp::Load: {
193 u64 value = 0;
194 m_memory.ReadBlock(address, &value, dbytes);
195 this->SetReg(Rt, value);
196 std::atomic_thread_fence(std::memory_order_seq_cst);
197 break;
198 }
199 default:
200 UNREACHABLE();
201 }
202
203 return true;
204}
205
206bool InterpreterVisitor::STLLR(Imm<2> sz, Reg Rn, Reg Rt) {
207 const size_t size = sz.ZeroExtend<size_t>();
208 const bool L = 0;
209 const bool o0 = 0;
210 return this->Ordered(size, L, o0, Rn, Rt);
211}
212
213bool InterpreterVisitor::STLR(Imm<2> sz, Reg Rn, Reg Rt) {
214 const size_t size = sz.ZeroExtend<size_t>();
215 const bool L = 0;
216 const bool o0 = 1;
217 return this->Ordered(size, L, o0, Rn, Rt);
218}
219
220bool InterpreterVisitor::LDLAR(Imm<2> sz, Reg Rn, Reg Rt) {
221 const size_t size = sz.ZeroExtend<size_t>();
222 const bool L = 1;
223 const bool o0 = 0;
224 return this->Ordered(size, L, o0, Rn, Rt);
225}
226
227bool InterpreterVisitor::LDAR(Imm<2> sz, Reg Rn, Reg Rt) {
228 const size_t size = sz.ZeroExtend<size_t>();
229 const bool L = 1;
230 const bool o0 = 1;
231 return this->Ordered(size, L, o0, Rn, Rt);
232}
233
234bool InterpreterVisitor::LDR_lit_gen(bool opc_0, Imm<19> imm19, Reg Rt) {
235 const size_t size = opc_0 == 0 ? 4 : 8;
236 const s64 offset = Dynarmic::concatenate(imm19, Imm<2>{0}).SignExtend<s64>();
237 const u64 address = this->GetPc() + offset;
238
239 u64 data = 0;
240 m_memory.ReadBlock(address, &data, size);
241
242 this->SetReg(Rt, data);
243 return true;
244}
245
246bool InterpreterVisitor::LDR_lit_fpsimd(Imm<2> opc, Imm<19> imm19, Vec Vt) {
247 if (opc == 0b11) {
248 // Unallocated encoding
249 return false;
250 }
251
252 const u64 size = 4 << opc.ZeroExtend();
253 const u64 offset = imm19.SignExtend<u64>() << 2;
254 const u64 address = this->GetPc() + offset;
255
256 u128 data{};
257 m_memory.ReadBlock(address, &data, size);
258 this->SetVec(Vt, data);
259 return true;
260}
261
262bool InterpreterVisitor::STP_LDP_gen(Imm<2> opc, bool not_postindex, bool wback, Imm<1> L,
263 Imm<7> imm7, Reg Rt2, Reg Rn, Reg Rt) {
264 if ((L == 0 && opc.Bit<0>() == 1) || opc == 0b11) {
265 // Unallocated encoding
266 return false;
267 }
268
269 const auto memop = L == 1 ? MemOp::Load : MemOp::Store;
270 if (memop == MemOp::Load && wback && (Rt == Rn || Rt2 == Rn) && Rn != Reg::R31) {
271 // Unpredictable instruction
272 return false;
273 }
274 if (memop == MemOp::Store && wback && (Rt == Rn || Rt2 == Rn) && Rn != Reg::R31) {
275 // Unpredictable instruction
276 return false;
277 }
278 if (memop == MemOp::Load && Rt == Rt2) {
279 // Unpredictable instruction
280 return false;
281 }
282
283 u64 address;
284 if (Rn == Reg::SP) {
285 address = this->GetSp();
286 } else {
287 address = this->GetReg(Rn);
288 }
289
290 const bool postindex = !not_postindex;
291 const bool signed_ = opc.Bit<0>() != 0;
292 const size_t scale = 2 + opc.Bit<1>();
293 const size_t datasize = 8 << scale;
294 const u64 offset = imm7.SignExtend<u64>() << scale;
295
296 if (!postindex) {
297 address += offset;
298 }
299
300 const size_t dbytes = datasize / 8;
301 switch (memop) {
302 case MemOp::Store: {
303 u64 data1 = this->GetReg(Rt);
304 u64 data2 = this->GetReg(Rt2);
305 m_memory.WriteBlock(address, &data1, dbytes);
306 m_memory.WriteBlock(address + dbytes, &data2, dbytes);
307 break;
308 }
309 case MemOp::Load: {
310 u64 data1 = 0, data2 = 0;
311 m_memory.ReadBlock(address, &data1, dbytes);
312 m_memory.ReadBlock(address + dbytes, &data2, dbytes);
313 if (signed_) {
314 this->SetReg(Rt, SignExtend(data1, datasize, 64));
315 this->SetReg(Rt2, SignExtend(data2, datasize, 64));
316 } else {
317 this->SetReg(Rt, data1);
318 this->SetReg(Rt2, data2);
319 }
320 break;
321 }
322 default:
323 UNREACHABLE();
324 }
325
326 if (wback) {
327 if (postindex) {
328 address += offset;
329 }
330
331 if (Rn == Reg::SP) {
332 this->SetSp(address);
333 } else {
334 this->SetReg(Rn, address);
335 }
336 }
337
338 return true;
339}
340
341bool InterpreterVisitor::STP_LDP_fpsimd(Imm<2> opc, bool not_postindex, bool wback, Imm<1> L,
342 Imm<7> imm7, Vec Vt2, Reg Rn, Vec Vt) {
343 if (opc == 0b11) {
344 // Unallocated encoding
345 return false;
346 }
347
348 const auto memop = L == 1 ? MemOp::Load : MemOp::Store;
349 if (memop == MemOp::Load && Vt == Vt2) {
350 // Unpredictable instruction
351 return false;
352 }
353
354 u64 address;
355 if (Rn == Reg::SP) {
356 address = this->GetSp();
357 } else {
358 address = this->GetReg(Rn);
359 }
360
361 const bool postindex = !not_postindex;
362 const size_t scale = 2 + opc.ZeroExtend<size_t>();
363 const size_t datasize = 8 << scale;
364 const u64 offset = imm7.SignExtend<u64>() << scale;
365 const size_t dbytes = datasize / 8;
366
367 if (!postindex) {
368 address += offset;
369 }
370
371 switch (memop) {
372 case MemOp::Store: {
373 u128 data1 = VectorGetElement(this->GetVec(Vt), datasize);
374 u128 data2 = VectorGetElement(this->GetVec(Vt2), datasize);
375 m_memory.WriteBlock(address, &data1, dbytes);
376 m_memory.WriteBlock(address + dbytes, &data2, dbytes);
377 break;
378 }
379 case MemOp::Load: {
380 u128 data1{}, data2{};
381 m_memory.ReadBlock(address, &data1, dbytes);
382 m_memory.ReadBlock(address + dbytes, &data2, dbytes);
383 this->SetVec(Vt, data1);
384 this->SetVec(Vt2, data2);
385 break;
386 }
387 default:
388 UNREACHABLE();
389 }
390
391 if (wback) {
392 if (postindex) {
393 address += offset;
394 }
395
396 if (Rn == Reg::SP) {
397 this->SetSp(address);
398 } else {
399 this->SetReg(Rn, address);
400 }
401 }
402
403 return true;
404}
405
406bool InterpreterVisitor::RegisterImmediate(bool wback, bool postindex, size_t scale, u64 offset,
407 Imm<2> size, Imm<2> opc, Reg Rn, Reg Rt) {
408 MemOp memop;
409 bool signed_ = false;
410 size_t regsize = 0;
411
412 if (opc.Bit<1>() == 0) {
413 memop = opc.Bit<0>() ? MemOp::Load : MemOp::Store;
414 regsize = size == 0b11 ? 64 : 32;
415 signed_ = false;
416 } else if (size == 0b11) {
417 memop = MemOp::Prefetch;
418 ASSERT(!opc.Bit<0>());
419 } else {
420 memop = MemOp::Load;
421 ASSERT(!(size == 0b10 && opc.Bit<0>() == 1));
422 regsize = opc.Bit<0>() ? 32 : 64;
423 signed_ = true;
424 }
425
426 if (memop == MemOp::Load && wback && Rn == Rt && Rn != Reg::R31) {
427 // Unpredictable instruction
428 return false;
429 }
430 if (memop == MemOp::Store && wback && Rn == Rt && Rn != Reg::R31) {
431 // Unpredictable instruction
432 return false;
433 }
434
435 u64 address;
436 if (Rn == Reg::SP) {
437 address = this->GetSp();
438 } else {
439 address = this->GetReg(Rn);
440 }
441 if (!postindex) {
442 address += offset;
443 }
444
445 const size_t datasize = 8 << scale;
446 switch (memop) {
447 case MemOp::Store: {
448 u64 data = this->GetReg(Rt);
449 m_memory.WriteBlock(address, &data, datasize / 8);
450 break;
451 }
452 case MemOp::Load: {
453 u64 data = 0;
454 m_memory.ReadBlock(address, &data, datasize / 8);
455 if (signed_) {
456 this->SetReg(Rt, SignExtend(data, datasize, regsize));
457 } else {
458 this->SetReg(Rt, data);
459 }
460 break;
461 }
462 case MemOp::Prefetch:
463 // this->Prefetch(address, Rt)
464 break;
465 }
466
467 if (wback) {
468 if (postindex) {
469 address += offset;
470 }
471
472 if (Rn == Reg::SP) {
473 this->SetSp(address);
474 } else {
475 this->SetReg(Rn, address);
476 }
477 }
478
479 return true;
480}
481
482bool InterpreterVisitor::STRx_LDRx_imm_1(Imm<2> size, Imm<2> opc, Imm<9> imm9, bool not_postindex,
483 Reg Rn, Reg Rt) {
484 const bool wback = true;
485 const bool postindex = !not_postindex;
486 const size_t scale = size.ZeroExtend<size_t>();
487 const u64 offset = imm9.SignExtend<u64>();
488
489 return this->RegisterImmediate(wback, postindex, scale, offset, size, opc, Rn, Rt);
490}
491
492bool InterpreterVisitor::STRx_LDRx_imm_2(Imm<2> size, Imm<2> opc, Imm<12> imm12, Reg Rn, Reg Rt) {
493 const bool wback = false;
494 const bool postindex = false;
495 const size_t scale = size.ZeroExtend<size_t>();
496 const u64 offset = imm12.ZeroExtend<u64>() << scale;
497
498 return this->RegisterImmediate(wback, postindex, scale, offset, size, opc, Rn, Rt);
499}
500
501bool InterpreterVisitor::STURx_LDURx(Imm<2> size, Imm<2> opc, Imm<9> imm9, Reg Rn, Reg Rt) {
502 const bool wback = false;
503 const bool postindex = false;
504 const size_t scale = size.ZeroExtend<size_t>();
505 const u64 offset = imm9.SignExtend<u64>();
506
507 return this->RegisterImmediate(wback, postindex, scale, offset, size, opc, Rn, Rt);
508}
509
510bool InterpreterVisitor::SIMDImmediate(bool wback, bool postindex, size_t scale, u64 offset,
511 MemOp memop, Reg Rn, Vec Vt) {
512 const size_t datasize = 8 << scale;
513
514 u64 address;
515 if (Rn == Reg::SP) {
516 address = this->GetSp();
517 } else {
518 address = this->GetReg(Rn);
519 }
520
521 if (!postindex) {
522 address += offset;
523 }
524
525 switch (memop) {
526 case MemOp::Store: {
527 u128 data = VectorGetElement(this->GetVec(Vt), datasize);
528 m_memory.WriteBlock(address, &data, datasize / 8);
529 break;
530 }
531 case MemOp::Load: {
532 u128 data{};
533 m_memory.ReadBlock(address, &data, datasize);
534 this->SetVec(Vt, data);
535 break;
536 }
537 default:
538 UNREACHABLE();
539 }
540
541 if (wback) {
542 if (postindex) {
543 address += offset;
544 }
545
546 if (Rn == Reg::SP) {
547 this->SetSp(address);
548 } else {
549 this->SetReg(Rn, address);
550 }
551 }
552
553 return true;
554}
555
556bool InterpreterVisitor::STR_imm_fpsimd_1(Imm<2> size, Imm<1> opc_1, Imm<9> imm9,
557 bool not_postindex, Reg Rn, Vec Vt) {
558 const size_t scale = Dynarmic::concatenate(opc_1, size).ZeroExtend<size_t>();
559 if (scale > 4) {
560 // Unallocated encoding
561 return false;
562 }
563
564 const bool wback = true;
565 const bool postindex = !not_postindex;
566 const u64 offset = imm9.SignExtend<u64>();
567
568 return this->SIMDImmediate(wback, postindex, scale, offset, MemOp::Store, Rn, Vt);
569}
570
571bool InterpreterVisitor::STR_imm_fpsimd_2(Imm<2> size, Imm<1> opc_1, Imm<12> imm12, Reg Rn,
572 Vec Vt) {
573 const size_t scale = Dynarmic::concatenate(opc_1, size).ZeroExtend<size_t>();
574 if (scale > 4) {
575 // Unallocated encoding
576 return false;
577 }
578
579 const bool wback = false;
580 const bool postindex = false;
581 const u64 offset = imm12.ZeroExtend<u64>() << scale;
582
583 return this->SIMDImmediate(wback, postindex, scale, offset, MemOp::Store, Rn, Vt);
584}
585
586bool InterpreterVisitor::LDR_imm_fpsimd_1(Imm<2> size, Imm<1> opc_1, Imm<9> imm9,
587 bool not_postindex, Reg Rn, Vec Vt) {
588 const size_t scale = Dynarmic::concatenate(opc_1, size).ZeroExtend<size_t>();
589 if (scale > 4) {
590 // Unallocated encoding
591 return false;
592 }
593
594 const bool wback = true;
595 const bool postindex = !not_postindex;
596 const u64 offset = imm9.SignExtend<u64>();
597
598 return this->SIMDImmediate(wback, postindex, scale, offset, MemOp::Load, Rn, Vt);
599}
600
601bool InterpreterVisitor::LDR_imm_fpsimd_2(Imm<2> size, Imm<1> opc_1, Imm<12> imm12, Reg Rn,
602 Vec Vt) {
603 const size_t scale = Dynarmic::concatenate(opc_1, size).ZeroExtend<size_t>();
604 if (scale > 4) {
605 // Unallocated encoding
606 return false;
607 }
608
609 const bool wback = false;
610 const bool postindex = false;
611 const u64 offset = imm12.ZeroExtend<u64>() << scale;
612
613 return this->SIMDImmediate(wback, postindex, scale, offset, MemOp::Load, Rn, Vt);
614}
615
616bool InterpreterVisitor::STUR_fpsimd(Imm<2> size, Imm<1> opc_1, Imm<9> imm9, Reg Rn, Vec Vt) {
617 const size_t scale = Dynarmic::concatenate(opc_1, size).ZeroExtend<size_t>();
618 if (scale > 4) {
619 // Unallocated encoding
620 return false;
621 }
622
623 const bool wback = false;
624 const bool postindex = false;
625 const u64 offset = imm9.SignExtend<u64>();
626
627 return this->SIMDImmediate(wback, postindex, scale, offset, MemOp::Store, Rn, Vt);
628}
629
630bool InterpreterVisitor::LDUR_fpsimd(Imm<2> size, Imm<1> opc_1, Imm<9> imm9, Reg Rn, Vec Vt) {
631 const size_t scale = Dynarmic::concatenate(opc_1, size).ZeroExtend<size_t>();
632 if (scale > 4) {
633 // Unallocated encoding
634 return false;
635 }
636
637 const bool wback = false;
638 const bool postindex = false;
639 const u64 offset = imm9.SignExtend<u64>();
640
641 return this->SIMDImmediate(wback, postindex, scale, offset, MemOp::Load, Rn, Vt);
642}
643
644bool InterpreterVisitor::RegisterOffset(size_t scale, u8 shift, Imm<2> size, Imm<1> opc_1,
645 Imm<1> opc_0, Reg Rm, Imm<3> option, Reg Rn, Reg Rt) {
646 MemOp memop;
647 size_t regsize = 64;
648 bool signed_ = false;
649
650 if (opc_1 == 0) {
651 memop = opc_0 == 1 ? MemOp::Load : MemOp::Store;
652 regsize = size == 0b11 ? 64 : 32;
653 signed_ = false;
654 } else if (size == 0b11) {
655 memop = MemOp::Prefetch;
656 if (opc_0 == 1) {
657 // Unallocated encoding
658 return false;
659 }
660 } else {
661 memop = MemOp::Load;
662 if (size == 0b10 && opc_0 == 1) {
663 // Unallocated encoding
664 return false;
665 }
666 regsize = opc_0 == 1 ? 32 : 64;
667 signed_ = true;
668 }
669
670 const size_t datasize = 8 << scale;
671
672 // Operation
673 const u64 offset = this->ExtendReg(64, Rm, option, shift);
674
675 u64 address;
676 if (Rn == Reg::SP) {
677 address = this->GetSp();
678 } else {
679 address = this->GetReg(Rn);
680 }
681 address += offset;
682
683 switch (memop) {
684 case MemOp::Store: {
685 u64 data = this->GetReg(Rt);
686 m_memory.WriteBlock(address, &data, datasize / 8);
687 break;
688 }
689 case MemOp::Load: {
690 u64 data = 0;
691 m_memory.ReadBlock(address, &data, datasize / 8);
692 if (signed_) {
693 this->SetReg(Rt, SignExtend(data, datasize, regsize));
694 } else {
695 this->SetReg(Rt, data);
696 }
697 break;
698 }
699 case MemOp::Prefetch:
700 break;
701 }
702
703 return true;
704}
705
706bool InterpreterVisitor::STRx_reg(Imm<2> size, Imm<1> opc_1, Reg Rm, Imm<3> option, bool S, Reg Rn,
707 Reg Rt) {
708 const Imm<1> opc_0{0};
709 const size_t scale = size.ZeroExtend<size_t>();
710 const u8 shift = S ? static_cast<u8>(scale) : 0;
711 if (!option.Bit<1>()) {
712 // Unallocated encoding
713 return false;
714 }
715 return this->RegisterOffset(scale, shift, size, opc_1, opc_0, Rm, option, Rn, Rt);
716}
717
718bool InterpreterVisitor::LDRx_reg(Imm<2> size, Imm<1> opc_1, Reg Rm, Imm<3> option, bool S, Reg Rn,
719 Reg Rt) {
720 const Imm<1> opc_0{1};
721 const size_t scale = size.ZeroExtend<size_t>();
722 const u8 shift = S ? static_cast<u8>(scale) : 0;
723 if (!option.Bit<1>()) {
724 // Unallocated encoding
725 return false;
726 }
727 return this->RegisterOffset(scale, shift, size, opc_1, opc_0, Rm, option, Rn, Rt);
728}
729
730bool InterpreterVisitor::SIMDOffset(size_t scale, u8 shift, Imm<1> opc_0, Reg Rm, Imm<3> option,
731 Reg Rn, Vec Vt) {
732 const auto memop = opc_0 == 1 ? MemOp::Load : MemOp::Store;
733 const size_t datasize = 8 << scale;
734
735 // Operation
736 const u64 offset = this->ExtendReg(64, Rm, option, shift);
737
738 u64 address;
739 if (Rn == Reg::SP) {
740 address = this->GetSp();
741 } else {
742 address = this->GetReg(Rn);
743 }
744 address += offset;
745
746 switch (memop) {
747 case MemOp::Store: {
748 u128 data = VectorGetElement(this->GetVec(Vt), datasize);
749 m_memory.WriteBlock(address, &data, datasize / 8);
750 break;
751 }
752 case MemOp::Load: {
753 u128 data{};
754 m_memory.ReadBlock(address, &data, datasize / 8);
755 this->SetVec(Vt, data);
756 break;
757 }
758 default:
759 UNREACHABLE();
760 }
761
762 return true;
763}
764
765bool InterpreterVisitor::STR_reg_fpsimd(Imm<2> size, Imm<1> opc_1, Reg Rm, Imm<3> option, bool S,
766 Reg Rn, Vec Vt) {
767 const Imm<1> opc_0{0};
768 const size_t scale = Dynarmic::concatenate(opc_1, size).ZeroExtend<size_t>();
769 if (scale > 4) {
770 // Unallocated encoding
771 return false;
772 }
773 const u8 shift = S ? static_cast<u8>(scale) : 0;
774 if (!option.Bit<1>()) {
775 // Unallocated encoding
776 return false;
777 }
778 return this->SIMDOffset(scale, shift, opc_0, Rm, option, Rn, Vt);
779}
780
781bool InterpreterVisitor::LDR_reg_fpsimd(Imm<2> size, Imm<1> opc_1, Reg Rm, Imm<3> option, bool S,
782 Reg Rn, Vec Vt) {
783 const Imm<1> opc_0{1};
784 const size_t scale = Dynarmic::concatenate(opc_1, size).ZeroExtend<size_t>();
785 if (scale > 4) {
786 // Unallocated encoding
787 return false;
788 }
789 const u8 shift = S ? static_cast<u8>(scale) : 0;
790 if (!option.Bit<1>()) {
791 // Unallocated encoding
792 return false;
793 }
794 return this->SIMDOffset(scale, shift, opc_0, Rm, option, Rn, Vt);
795}
796
797std::optional<u64> MatchAndExecuteOneInstruction(Core::Memory::Memory& memory, mcontext_t* context,
798 fpsimd_context* fpsimd_context) {
799 // Construct the interpreter.
800 std::span<u64, 31> regs(reinterpret_cast<u64*>(context->regs), 31);
801 std::span<u128, 32> vregs(reinterpret_cast<u128*>(fpsimd_context->vregs), 32);
802 u64& sp = *reinterpret_cast<u64*>(&context->sp);
803 const u64& pc = *reinterpret_cast<u64*>(&context->pc);
804
805 InterpreterVisitor visitor(memory, regs, vregs, sp, pc);
806
807 // Read the instruction at the program counter.
808 u32 instruction = memory.Read32(pc);
809 bool was_executed = false;
810
811 // Interpret the instruction.
812 if (auto decoder = Dynarmic::A64::Decode<VisitorBase>(instruction)) {
813 was_executed = decoder->get().call(visitor, instruction);
814 } else {
815 LOG_ERROR(Core_ARM, "Unallocated encoding: {:#x}", instruction);
816 }
817
818 if (was_executed) {
819 return pc + 4;
820 }
821
822 return std::nullopt;
823}
824
825} // namespace Core
diff --git a/src/core/arm/nce/interpreter_visitor.h b/src/core/arm/nce/interpreter_visitor.h
new file mode 100644
index 000000000..f90d876ab
--- /dev/null
+++ b/src/core/arm/nce/interpreter_visitor.h
@@ -0,0 +1,103 @@
1// SPDX-FileCopyrightText: Copyright 2023 yuzu Emulator Project
2// SPDX-FileCopyrightText: Copyright 2023 merryhime <https://mary.rs>
3// SPDX-License-Identifier: GPL-2.0-or-later
4
5#pragma once
6
7#include <signal.h>
8#include <unistd.h>
9
10#include "core/arm/nce/visitor_base.h"
11
12namespace Core {
13
14namespace Memory {
15class Memory;
16}
17
18class InterpreterVisitor final : public VisitorBase {
19public:
20 explicit InterpreterVisitor(Core::Memory::Memory& memory, std::span<u64, 31> regs,
21 std::span<u128, 32> fpsimd_regs, u64& sp, const u64& pc)
22 : m_memory(memory), m_regs(regs), m_fpsimd_regs(fpsimd_regs), m_sp(sp), m_pc(pc) {}
23 ~InterpreterVisitor() override = default;
24
25 enum class MemOp {
26 Load,
27 Store,
28 Prefetch,
29 };
30
31 u128 GetVec(Vec v);
32 u64 GetReg(Reg r);
33 u64 GetSp();
34 u64 GetPc();
35
36 void SetVec(Vec v, u128 value);
37 void SetReg(Reg r, u64 value);
38 void SetSp(u64 value);
39
40 u64 ExtendReg(size_t bitsize, Reg reg, Imm<3> option, u8 shift);
41
42 // Loads and stores - Load/Store Exclusive
43 bool Ordered(size_t size, bool L, bool o0, Reg Rn, Reg Rt);
44 bool STLLR(Imm<2> size, Reg Rn, Reg Rt) override;
45 bool STLR(Imm<2> size, Reg Rn, Reg Rt) override;
46 bool LDLAR(Imm<2> size, Reg Rn, Reg Rt) override;
47 bool LDAR(Imm<2> size, Reg Rn, Reg Rt) override;
48
49 // Loads and stores - Load register (literal)
50 bool LDR_lit_gen(bool opc_0, Imm<19> imm19, Reg Rt) override;
51 bool LDR_lit_fpsimd(Imm<2> opc, Imm<19> imm19, Vec Vt) override;
52
53 // Loads and stores - Load/Store register pair
54 bool STP_LDP_gen(Imm<2> opc, bool not_postindex, bool wback, Imm<1> L, Imm<7> imm7, Reg Rt2,
55 Reg Rn, Reg Rt) override;
56 bool STP_LDP_fpsimd(Imm<2> opc, bool not_postindex, bool wback, Imm<1> L, Imm<7> imm7, Vec Vt2,
57 Reg Rn, Vec Vt) override;
58
59 // Loads and stores - Load/Store register (immediate)
60 bool RegisterImmediate(bool wback, bool postindex, size_t scale, u64 offset, Imm<2> size,
61 Imm<2> opc, Reg Rn, Reg Rt);
62 bool STRx_LDRx_imm_1(Imm<2> size, Imm<2> opc, Imm<9> imm9, bool not_postindex, Reg Rn,
63 Reg Rt) override;
64 bool STRx_LDRx_imm_2(Imm<2> size, Imm<2> opc, Imm<12> imm12, Reg Rn, Reg Rt) override;
65 bool STURx_LDURx(Imm<2> size, Imm<2> opc, Imm<9> imm9, Reg Rn, Reg Rt) override;
66
67 bool SIMDImmediate(bool wback, bool postindex, size_t scale, u64 offset, MemOp memop, Reg Rn,
68 Vec Vt);
69 bool STR_imm_fpsimd_1(Imm<2> size, Imm<1> opc_1, Imm<9> imm9, bool not_postindex, Reg Rn,
70 Vec Vt) override;
71 bool STR_imm_fpsimd_2(Imm<2> size, Imm<1> opc_1, Imm<12> imm12, Reg Rn, Vec Vt) override;
72 bool LDR_imm_fpsimd_1(Imm<2> size, Imm<1> opc_1, Imm<9> imm9, bool not_postindex, Reg Rn,
73 Vec Vt) override;
74 bool LDR_imm_fpsimd_2(Imm<2> size, Imm<1> opc_1, Imm<12> imm12, Reg Rn, Vec Vt) override;
75 bool STUR_fpsimd(Imm<2> size, Imm<1> opc_1, Imm<9> imm9, Reg Rn, Vec Vt) override;
76 bool LDUR_fpsimd(Imm<2> size, Imm<1> opc_1, Imm<9> imm9, Reg Rn, Vec Vt) override;
77
78 // Loads and stores - Load/Store register (register offset)
79 bool RegisterOffset(size_t scale, u8 shift, Imm<2> size, Imm<1> opc_1, Imm<1> opc_0, Reg Rm,
80 Imm<3> option, Reg Rn, Reg Rt);
81 bool STRx_reg(Imm<2> size, Imm<1> opc_1, Reg Rm, Imm<3> option, bool S, Reg Rn,
82 Reg Rt) override;
83 bool LDRx_reg(Imm<2> size, Imm<1> opc_1, Reg Rm, Imm<3> option, bool S, Reg Rn,
84 Reg Rt) override;
85
86 bool SIMDOffset(size_t scale, u8 shift, Imm<1> opc_0, Reg Rm, Imm<3> option, Reg Rn, Vec Vt);
87 bool STR_reg_fpsimd(Imm<2> size, Imm<1> opc_1, Reg Rm, Imm<3> option, bool S, Reg Rn,
88 Vec Vt) override;
89 bool LDR_reg_fpsimd(Imm<2> size, Imm<1> opc_1, Reg Rm, Imm<3> option, bool S, Reg Rn,
90 Vec Vt) override;
91
92private:
93 Core::Memory::Memory& m_memory;
94 std::span<u64, 31> m_regs;
95 std::span<u128, 32> m_fpsimd_regs;
96 u64& m_sp;
97 const u64& m_pc;
98};
99
100std::optional<u64> MatchAndExecuteOneInstruction(Core::Memory::Memory& memory, mcontext_t* context,
101 fpsimd_context* fpsimd_context);
102
103} // namespace Core
diff --git a/src/core/arm/nce/visitor_base.h b/src/core/arm/nce/visitor_base.h
new file mode 100644
index 000000000..8fb032912
--- /dev/null
+++ b/src/core/arm/nce/visitor_base.h
@@ -0,0 +1,2777 @@
1// SPDX-FileCopyrightText: Copyright 2023 yuzu Emulator Project
2// SPDX-FileCopyrightText: Copyright 2023 merryhime <https://mary.rs>
3// SPDX-License-Identifier: GPL-2.0-or-later
4
5#pragma once
6
7#include <dynarmic/frontend/A64/a64_types.h>
8#include <dynarmic/frontend/imm.h>
9
10namespace Core {
11
12class VisitorBase {
13public:
14 using instruction_return_type = bool;
15
16 template <size_t BitSize>
17 using Imm = Dynarmic::Imm<BitSize>;
18 using Reg = Dynarmic::A64::Reg;
19 using Vec = Dynarmic::A64::Vec;
20 using Cond = Dynarmic::A64::Cond;
21
22 virtual ~VisitorBase() {}
23
24 virtual bool UnallocatedEncoding() {
25 return false;
26 }
27
28 // Data processing - Immediate - PC relative addressing
29 virtual bool ADR(Imm<2> immlo, Imm<19> immhi, Reg Rd) {
30 return false;
31 }
32 virtual bool ADRP(Imm<2> immlo, Imm<19> immhi, Reg Rd) {
33 return false;
34 }
35
36 // Data processing - Immediate - Add/Sub (with tag)
37 virtual bool ADDG(Imm<6> offset_imm, Imm<4> tag_offset, Reg Rn, Reg Rd) {
38 return false;
39 }
40 virtual bool SUBG(Imm<6> offset_imm, Imm<4> tag_offset, Reg Rn, Reg Rd) {
41 return false;
42 }
43
44 // Data processing - Immediate - Add/Sub
45 virtual bool ADD_imm(bool sf, Imm<2> shift, Imm<12> imm12, Reg Rn, Reg Rd) {
46 return false;
47 }
48 virtual bool ADDS_imm(bool sf, Imm<2> shift, Imm<12> imm12, Reg Rn, Reg Rd) {
49 return false;
50 }
51 virtual bool SUB_imm(bool sf, Imm<2> shift, Imm<12> imm12, Reg Rn, Reg Rd) {
52 return false;
53 }
54 virtual bool SUBS_imm(bool sf, Imm<2> shift, Imm<12> imm12, Reg Rn, Reg Rd) {
55 return false;
56 }
57
58 // Data processing - Immediate - Logical
59 virtual bool AND_imm(bool sf, bool N, Imm<6> immr, Imm<6> imms, Reg Rn, Reg Rd) {
60 return false;
61 }
62 virtual bool ORR_imm(bool sf, bool N, Imm<6> immr, Imm<6> imms, Reg Rn, Reg Rd) {
63 return false;
64 }
65 virtual bool EOR_imm(bool sf, bool N, Imm<6> immr, Imm<6> imms, Reg Rn, Reg Rd) {
66 return false;
67 }
68 virtual bool ANDS_imm(bool sf, bool N, Imm<6> immr, Imm<6> imms, Reg Rn, Reg Rd) {
69 return false;
70 }
71
72 // Data processing - Immediate - Move Wide
73 virtual bool MOVN(bool sf, Imm<2> hw, Imm<16> imm16, Reg Rd) {
74 return false;
75 }
76 virtual bool MOVZ(bool sf, Imm<2> hw, Imm<16> imm16, Reg Rd) {
77 return false;
78 }
79 virtual bool MOVK(bool sf, Imm<2> hw, Imm<16> imm16, Reg Rd) {
80 return false;
81 }
82
83 // Data processing - Immediate - Bitfield
84 virtual bool SBFM(bool sf, bool N, Imm<6> immr, Imm<6> imms, Reg Rn, Reg Rd) {
85 return false;
86 }
87 virtual bool BFM(bool sf, bool N, Imm<6> immr, Imm<6> imms, Reg Rn, Reg Rd) {
88 return false;
89 }
90 virtual bool UBFM(bool sf, bool N, Imm<6> immr, Imm<6> imms, Reg Rn, Reg Rd) {
91 return false;
92 }
93 virtual bool ASR_1(Imm<5> immr, Reg Rn, Reg Rd) {
94 return false;
95 }
96 virtual bool ASR_2(Imm<6> immr, Reg Rn, Reg Rd) {
97 return false;
98 }
99 virtual bool SXTB_1(Reg Rn, Reg Rd) {
100 return false;
101 }
102 virtual bool SXTB_2(Reg Rn, Reg Rd) {
103 return false;
104 }
105 virtual bool SXTH_1(Reg Rn, Reg Rd) {
106 return false;
107 }
108 virtual bool SXTH_2(Reg Rn, Reg Rd) {
109 return false;
110 }
111 virtual bool SXTW(Reg Rn, Reg Rd) {
112 return false;
113 }
114
115 // Data processing - Immediate - Extract
116 virtual bool EXTR(bool sf, bool N, Reg Rm, Imm<6> imms, Reg Rn, Reg Rd) {
117 return false;
118 }
119
120 // Conditional branch
121 virtual bool B_cond(Imm<19> imm19, Cond cond) {
122 return false;
123 }
124
125 // Exception generation
126 virtual bool SVC(Imm<16> imm16) {
127 return false;
128 }
129 virtual bool HVC(Imm<16> imm16) {
130 return false;
131 }
132 virtual bool SMC(Imm<16> imm16) {
133 return false;
134 }
135 virtual bool BRK(Imm<16> imm16) {
136 return false;
137 }
138 virtual bool HLT(Imm<16> imm16) {
139 return false;
140 }
141 virtual bool DCPS1(Imm<16> imm16) {
142 return false;
143 }
144 virtual bool DCPS2(Imm<16> imm16) {
145 return false;
146 }
147 virtual bool DCPS3(Imm<16> imm16) {
148 return false;
149 }
150
151 // System
152 virtual bool MSR_imm(Imm<3> op1, Imm<4> CRm, Imm<3> op2) {
153 return false;
154 }
155 virtual bool HINT(Imm<4> CRm, Imm<3> op2) {
156 return false;
157 }
158 virtual bool NOP() {
159 return false;
160 }
161 virtual bool YIELD() {
162 return false;
163 }
164 virtual bool WFE() {
165 return false;
166 }
167 virtual bool WFI() {
168 return false;
169 }
170 virtual bool SEV() {
171 return false;
172 }
173 virtual bool SEVL() {
174 return false;
175 }
176 virtual bool XPAC_1(bool D, Reg Rd) {
177 return false;
178 }
179 virtual bool XPAC_2() {
180 return false;
181 }
182 virtual bool PACIA_1(bool Z, Reg Rn, Reg Rd) {
183 return false;
184 }
185 virtual bool PACIA_2() {
186 return false;
187 }
188 virtual bool PACIB_1(bool Z, Reg Rn, Reg Rd) {
189 return false;
190 }
191 virtual bool PACIB_2() {
192 return false;
193 }
194 virtual bool AUTIA_1(bool Z, Reg Rn, Reg Rd) {
195 return false;
196 }
197 virtual bool AUTIA_2() {
198 return false;
199 }
200 virtual bool AUTIB_1(bool Z, Reg Rn, Reg Rd) {
201 return false;
202 }
203 virtual bool AUTIB_2() {
204 return false;
205 }
206 virtual bool BTI(Imm<2> upper_op2) {
207 return false;
208 }
209 virtual bool ESB() {
210 return false;
211 }
212 virtual bool PSB() {
213 return false;
214 }
215 virtual bool TSB() {
216 return false;
217 }
218 virtual bool CSDB() {
219 return false;
220 }
221 virtual bool CLREX(Imm<4> CRm) {
222 return false;
223 }
224 virtual bool DSB(Imm<4> CRm) {
225 return false;
226 }
227 virtual bool SSBB() {
228 return false;
229 }
230 virtual bool PSSBB() {
231 return false;
232 }
233 virtual bool DMB(Imm<4> CRm) {
234 return false;
235 }
236 virtual bool ISB(Imm<4> CRm) {
237 return false;
238 }
239 virtual bool SYS(Imm<3> op1, Imm<4> CRn, Imm<4> CRm, Imm<3> op2, Reg Rt) {
240 return false;
241 }
242 virtual bool SB() {
243 return false;
244 }
245 virtual bool MSR_reg(Imm<1> o0, Imm<3> op1, Imm<4> CRn, Imm<4> CRm, Imm<3> op2, Reg Rt) {
246 return false;
247 }
248 virtual bool SYSL(Imm<3> op1, Imm<4> CRn, Imm<4> CRm, Imm<3> op2, Reg Rt) {
249 return false;
250 }
251 virtual bool MRS(Imm<1> o0, Imm<3> op1, Imm<4> CRn, Imm<4> CRm, Imm<3> op2, Reg Rt) {
252 return false;
253 }
254
255 // System - Flag manipulation instructions
256 virtual bool CFINV() {
257 return false;
258 }
259 virtual bool RMIF(Imm<6> lsb, Reg Rn, Imm<4> mask) {
260 return false;
261 }
262 virtual bool SETF8(Reg Rn) {
263 return false;
264 }
265 virtual bool SETF16(Reg Rn) {
266 return false;
267 }
268
269 // System - Flag format instructions
270 virtual bool XAFlag() {
271 return false;
272 }
273 virtual bool AXFlag() {
274 return false;
275 }
276
277 // SYS: Data Cache
278 virtual bool DC_IVAC(Reg Rt) {
279 return false;
280 }
281 virtual bool DC_ISW(Reg Rt) {
282 return false;
283 }
284 virtual bool DC_CSW(Reg Rt) {
285 return false;
286 }
287 virtual bool DC_CISW(Reg Rt) {
288 return false;
289 }
290 virtual bool DC_ZVA(Reg Rt) {
291 return false;
292 }
293 virtual bool DC_CVAC(Reg Rt) {
294 return false;
295 }
296 virtual bool DC_CVAU(Reg Rt) {
297 return false;
298 }
299 virtual bool DC_CVAP(Reg Rt) {
300 return false;
301 }
302 virtual bool DC_CIVAC(Reg Rt) {
303 return false;
304 }
305
306 // SYS: Instruction Cache
307 virtual bool IC_IALLU() {
308 return false;
309 }
310 virtual bool IC_IALLUIS() {
311 return false;
312 }
313 virtual bool IC_IVAU(Reg Rt) {
314 return false;
315 }
316
317 // Unconditional branch (Register)
318 virtual bool BR(Reg Rn) {
319 return false;
320 }
321 virtual bool BRA(bool Z, bool M, Reg Rn, Reg Rm) {
322 return false;
323 }
324 virtual bool BLR(Reg Rn) {
325 return false;
326 }
327 virtual bool BLRA(bool Z, bool M, Reg Rn, Reg Rm) {
328 return false;
329 }
330 virtual bool RET(Reg Rn) {
331 return false;
332 }
333 virtual bool RETA(bool M) {
334 return false;
335 }
336 virtual bool ERET() {
337 return false;
338 }
339 virtual bool ERETA(bool M) {
340 return false;
341 }
342 virtual bool DRPS() {
343 return false;
344 }
345
346 // Unconditional branch (immediate)
347 virtual bool B_uncond(Imm<26> imm26) {
348 return false;
349 }
350 virtual bool BL(Imm<26> imm26) {
351 return false;
352 }
353
354 // Compare and branch (immediate)
355 virtual bool CBZ(bool sf, Imm<19> imm19, Reg Rt) {
356 return false;
357 }
358 virtual bool CBNZ(bool sf, Imm<19> imm19, Reg Rt) {
359 return false;
360 }
361 virtual bool TBZ(Imm<1> b5, Imm<5> b40, Imm<14> imm14, Reg Rt) {
362 return false;
363 }
364 virtual bool TBNZ(Imm<1> b5, Imm<5> b40, Imm<14> imm14, Reg Rt) {
365 return false;
366 }
367
368 // Loads and stores - Advanced SIMD Load/Store multiple structures
369 virtual bool STx_mult_1(bool Q, Imm<4> opcode, Imm<2> size, Reg Rn, Vec Vt) {
370 return false;
371 }
372 virtual bool STx_mult_2(bool Q, Reg Rm, Imm<4> opcode, Imm<2> size, Reg Rn, Vec Vt) {
373 return false;
374 }
375 virtual bool LDx_mult_1(bool Q, Imm<4> opcode, Imm<2> size, Reg Rn, Vec Vt) {
376 return false;
377 }
378 virtual bool LDx_mult_2(bool Q, Reg Rm, Imm<4> opcode, Imm<2> size, Reg Rn, Vec Vt) {
379 return false;
380 }
381
382 // Loads and stores - Advanced SIMD Load/Store single structures
383 virtual bool ST1_sngl_1(bool Q, Imm<2> upper_opcode, bool S, Imm<2> size, Reg Rn, Vec Vt) {
384 return false;
385 }
386 virtual bool ST1_sngl_2(bool Q, Reg Rm, Imm<2> upper_opcode, bool S, Imm<2> size, Reg Rn,
387 Vec Vt) {
388 return false;
389 }
390 virtual bool ST3_sngl_1(bool Q, Imm<2> upper_opcode, bool S, Imm<2> size, Reg Rn, Vec Vt) {
391 return false;
392 }
393 virtual bool ST3_sngl_2(bool Q, Reg Rm, Imm<2> upper_opcode, bool S, Imm<2> size, Reg Rn,
394 Vec Vt) {
395 return false;
396 }
397 virtual bool ST2_sngl_1(bool Q, Imm<2> upper_opcode, bool S, Imm<2> size, Reg Rn, Vec Vt) {
398 return false;
399 }
400 virtual bool ST2_sngl_2(bool Q, Reg Rm, Imm<2> upper_opcode, bool S, Imm<2> size, Reg Rn,
401 Vec Vt) {
402 return false;
403 }
404 virtual bool ST4_sngl_1(bool Q, Imm<2> upper_opcode, bool S, Imm<2> size, Reg Rn, Vec Vt) {
405 return false;
406 }
407 virtual bool ST4_sngl_2(bool Q, Reg Rm, Imm<2> upper_opcode, bool S, Imm<2> size, Reg Rn,
408 Vec Vt) {
409 return false;
410 }
411 virtual bool LD1_sngl_1(bool Q, Imm<2> upper_opcode, bool S, Imm<2> size, Reg Rn, Vec Vt) {
412 return false;
413 }
414 virtual bool LD1_sngl_2(bool Q, Reg Rm, Imm<2> upper_opcode, bool S, Imm<2> size, Reg Rn,
415 Vec Vt) {
416 return false;
417 }
418 virtual bool LD3_sngl_1(bool Q, Imm<2> upper_opcode, bool S, Imm<2> size, Reg Rn, Vec Vt) {
419 return false;
420 }
421 virtual bool LD3_sngl_2(bool Q, Reg Rm, Imm<2> upper_opcode, bool S, Imm<2> size, Reg Rn,
422 Vec Vt) {
423 return false;
424 }
425 virtual bool LD1R_1(bool Q, Imm<2> size, Reg Rn, Vec Vt) {
426 return false;
427 }
428 virtual bool LD1R_2(bool Q, Reg Rm, Imm<2> size, Reg Rn, Vec Vt) {
429 return false;
430 }
431 virtual bool LD3R_1(bool Q, Imm<2> size, Reg Rn, Vec Vt) {
432 return false;
433 }
434 virtual bool LD3R_2(bool Q, Reg Rm, Imm<2> size, Reg Rn, Vec Vt) {
435 return false;
436 }
437 virtual bool LD2_sngl_1(bool Q, Imm<2> upper_opcode, bool S, Imm<2> size, Reg Rn, Vec Vt) {
438 return false;
439 }
440 virtual bool LD2_sngl_2(bool Q, Reg Rm, Imm<2> upper_opcode, bool S, Imm<2> size, Reg Rn,
441 Vec Vt) {
442 return false;
443 }
444 virtual bool LD4_sngl_1(bool Q, Imm<2> upper_opcode, bool S, Imm<2> size, Reg Rn, Vec Vt) {
445 return false;
446 }
447 virtual bool LD4_sngl_2(bool Q, Reg Rm, Imm<2> upper_opcode, bool S, Imm<2> size, Reg Rn,
448 Vec Vt) {
449 return false;
450 }
451 virtual bool LD2R_1(bool Q, Imm<2> size, Reg Rn, Vec Vt) {
452 return false;
453 }
454 virtual bool LD2R_2(bool Q, Reg Rm, Imm<2> size, Reg Rn, Vec Vt) {
455 return false;
456 }
457 virtual bool LD4R_1(bool Q, Imm<2> size, Reg Rn, Vec Vt) {
458 return false;
459 }
460 virtual bool LD4R_2(bool Q, Reg Rm, Imm<2> size, Reg Rn, Vec Vt) {
461 return false;
462 }
463
464 // Loads and stores - Load/Store Exclusive
465 virtual bool STXR(Imm<2> size, Reg Rs, Reg Rn, Reg Rt) {
466 return false;
467 }
468 virtual bool STLXR(Imm<2> size, Reg Rs, Reg Rn, Reg Rt) {
469 return false;
470 }
471 virtual bool STXP(Imm<1> size, Reg Rs, Reg Rt2, Reg Rn, Reg Rt) {
472 return false;
473 }
474 virtual bool STLXP(Imm<1> size, Reg Rs, Reg Rt2, Reg Rn, Reg Rt) {
475 return false;
476 }
477 virtual bool LDXR(Imm<2> size, Reg Rn, Reg Rt) {
478 return false;
479 }
480 virtual bool LDAXR(Imm<2> size, Reg Rn, Reg Rt) {
481 return false;
482 }
483 virtual bool LDXP(Imm<1> size, Reg Rt2, Reg Rn, Reg Rt) {
484 return false;
485 }
486 virtual bool LDAXP(Imm<1> size, Reg Rt2, Reg Rn, Reg Rt) {
487 return false;
488 }
489 virtual bool STLLR(Imm<2> size, Reg Rn, Reg Rt) {
490 return false;
491 }
492 virtual bool STLR(Imm<2> size, Reg Rn, Reg Rt) {
493 return false;
494 }
495 virtual bool LDLAR(Imm<2> size, Reg Rn, Reg Rt) {
496 return false;
497 }
498 virtual bool LDAR(Imm<2> size, Reg Rn, Reg Rt) {
499 return false;
500 }
501 virtual bool CASP(bool sz, bool L, Reg Rs, bool o0, Reg Rn, Reg Rt) {
502 return false;
503 }
504 virtual bool CASB(bool L, Reg Rs, bool o0, Reg Rn, Reg Rt) {
505 return false;
506 }
507 virtual bool CASH(bool L, Reg Rs, bool o0, Reg Rn, Reg Rt) {
508 return false;
509 }
510 virtual bool CAS(bool sz, bool L, Reg Rs, bool o0, Reg Rn, Reg Rt) {
511 return false;
512 }
513
514 // Loads and stores - Load register (literal)
515 virtual bool LDR_lit_gen(bool opc_0, Imm<19> imm19, Reg Rt) {
516 return false;
517 }
518 virtual bool LDR_lit_fpsimd(Imm<2> opc, Imm<19> imm19, Vec Vt) {
519 return false;
520 }
521 virtual bool LDRSW_lit(Imm<19> imm19, Reg Rt) {
522 return false;
523 }
524 virtual bool PRFM_lit(Imm<19> imm19, Imm<5> prfop) {
525 return false;
526 }
527
528 // Loads and stores - Load/Store no-allocate pair
529 virtual bool STNP_LDNP_gen(Imm<1> upper_opc, Imm<1> L, Imm<7> imm7, Reg Rt2, Reg Rn, Reg Rt) {
530 return false;
531 }
532 virtual bool STNP_LDNP_fpsimd(Imm<2> opc, Imm<1> L, Imm<7> imm7, Vec Vt2, Reg Rn, Vec Vt) {
533 return false;
534 }
535
536 // Loads and stores - Load/Store register pair
537 virtual bool STP_LDP_gen(Imm<2> opc, bool not_postindex, bool wback, Imm<1> L, Imm<7> imm7,
538 Reg Rt2, Reg Rn, Reg Rt) {
539 return false;
540 }
541 virtual bool STP_LDP_fpsimd(Imm<2> opc, bool not_postindex, bool wback, Imm<1> L, Imm<7> imm7,
542 Vec Vt2, Reg Rn, Vec Vt) {
543 return false;
544 }
545 virtual bool STGP_1(Imm<7> offset_imm, Reg Rt2, Reg Rn, Reg Rt) {
546 return false;
547 }
548 virtual bool STGP_2(Imm<7> offset_imm, Reg Rt2, Reg Rn, Reg Rt) {
549 return false;
550 }
551 virtual bool STGP_3(Imm<7> offset_imm, Reg Rt2, Reg Rn, Reg Rt) {
552 return false;
553 }
554
555 // Loads and stores - Load/Store register (immediate)
556 virtual bool STRx_LDRx_imm_1(Imm<2> size, Imm<2> opc, Imm<9> imm9, bool not_postindex, Reg Rn,
557 Reg Rt) {
558 return false;
559 }
560 virtual bool STRx_LDRx_imm_2(Imm<2> size, Imm<2> opc, Imm<12> imm12, Reg Rn, Reg Rt) {
561 return false;
562 }
563 virtual bool STURx_LDURx(Imm<2> size, Imm<2> opc, Imm<9> imm9, Reg Rn, Reg Rt) {
564 return false;
565 }
566 virtual bool PRFM_imm(Imm<12> imm12, Reg Rn, Reg Rt) {
567 return false;
568 }
569 virtual bool PRFM_unscaled_imm(Imm<9> imm9, Reg Rn, Reg Rt) {
570 return false;
571 }
572 virtual bool STR_imm_fpsimd_1(Imm<2> size, Imm<1> opc_1, Imm<9> imm9, bool not_postindex,
573 Reg Rn, Vec Vt) {
574 return false;
575 }
576 virtual bool STR_imm_fpsimd_2(Imm<2> size, Imm<1> opc_1, Imm<12> imm12, Reg Rn, Vec Vt) {
577 return false;
578 }
579 virtual bool LDR_imm_fpsimd_1(Imm<2> size, Imm<1> opc_1, Imm<9> imm9, bool not_postindex,
580 Reg Rn, Vec Vt) {
581 return false;
582 }
583 virtual bool LDR_imm_fpsimd_2(Imm<2> size, Imm<1> opc_1, Imm<12> imm12, Reg Rn, Vec Vt) {
584 return false;
585 }
586 virtual bool STUR_fpsimd(Imm<2> size, Imm<1> opc_1, Imm<9> imm9, Reg Rn, Vec Vt) {
587 return false;
588 }
589 virtual bool LDUR_fpsimd(Imm<2> size, Imm<1> opc_1, Imm<9> imm9, Reg Rn, Vec Vt) {
590 return false;
591 }
592
593 // Loads and stores - Load/Store register (unprivileged)
594 virtual bool STTRB(Imm<9> imm9, Reg Rn, Reg Rt) {
595 return false;
596 }
597 virtual bool LDTRB(Imm<9> imm9, Reg Rn, Reg Rt) {
598 return false;
599 }
600 virtual bool LDTRSB(Imm<2> opc, Imm<9> imm9, Reg Rn, Reg Rt) {
601 return false;
602 }
603 virtual bool STTRH(Imm<9> imm9, Reg Rn, Reg Rt) {
604 return false;
605 }
606 virtual bool LDTRH(Imm<9> imm9, Reg Rn, Reg Rt) {
607 return false;
608 }
609 virtual bool LDTRSH(Imm<2> opc, Imm<9> imm9, Reg Rn, Reg Rt) {
610 return false;
611 }
612 virtual bool STTR(Imm<2> size, Imm<9> imm9, Reg Rn, Reg Rt) {
613 return false;
614 }
615 virtual bool LDTR(Imm<2> size, Imm<9> imm9, Reg Rn, Reg Rt) {
616 return false;
617 }
618 virtual bool LDTRSW(Imm<9> imm9, Reg Rn, Reg Rt) {
619 return false;
620 }
621
622 // Loads and stores - Atomic memory options
623 virtual bool LDADDB(bool A, bool R, Reg Rs, Reg Rn, Reg Rt) {
624 return false;
625 }
626 virtual bool LDCLRB(bool A, bool R, Reg Rs, Reg Rn, Reg Rt) {
627 return false;
628 }
629 virtual bool LDEORB(bool A, bool R, Reg Rs, Reg Rn, Reg Rt) {
630 return false;
631 }
632 virtual bool LDSETB(bool A, bool R, Reg Rs, Reg Rn, Reg Rt) {
633 return false;
634 }
635 virtual bool LDSMAXB(bool A, bool R, Reg Rs, Reg Rn, Reg Rt) {
636 return false;
637 }
638 virtual bool LDSMINB(bool A, bool R, Reg Rs, Reg Rn, Reg Rt) {
639 return false;
640 }
641 virtual bool LDUMAXB(bool A, bool R, Reg Rs, Reg Rn, Reg Rt) {
642 return false;
643 }
644 virtual bool LDUMINB(bool A, bool R, Reg Rs, Reg Rn, Reg Rt) {
645 return false;
646 }
647 virtual bool SWPB(bool A, bool R, Reg Rs, Reg Rn, Reg Rt) {
648 return false;
649 }
650 virtual bool LDAPRB(Reg Rn, Reg Rt) {
651 return false;
652 }
653 virtual bool LDADDH(bool A, bool R, Reg Rs, Reg Rn, Reg Rt) {
654 return false;
655 }
656 virtual bool LDCLRH(bool A, bool R, Reg Rs, Reg Rn, Reg Rt) {
657 return false;
658 }
659 virtual bool LDEORH(bool A, bool R, Reg Rs, Reg Rn, Reg Rt) {
660 return false;
661 }
662 virtual bool LDSETH(bool A, bool R, Reg Rs, Reg Rn, Reg Rt) {
663 return false;
664 }
665 virtual bool LDSMAXH(bool A, bool R, Reg Rs, Reg Rn, Reg Rt) {
666 return false;
667 }
668 virtual bool LDSMINH(bool A, bool R, Reg Rs, Reg Rn, Reg Rt) {
669 return false;
670 }
671 virtual bool LDUMAXH(bool A, bool R, Reg Rs, Reg Rn, Reg Rt) {
672 return false;
673 }
674 virtual bool LDUMINH(bool A, bool R, Reg Rs, Reg Rn, Reg Rt) {
675 return false;
676 }
677 virtual bool SWPH(bool A, bool R, Reg Rs, Reg Rn, Reg Rt) {
678 return false;
679 }
680 virtual bool LDAPRH(Reg Rn, Reg Rt) {
681 return false;
682 }
683 virtual bool LDADD(bool A, bool R, Reg Rs, Reg Rn, Reg Rt) {
684 return false;
685 }
686 virtual bool LDCLR(bool A, bool R, Reg Rs, Reg Rn, Reg Rt) {
687 return false;
688 }
689 virtual bool LDEOR(bool A, bool R, Reg Rs, Reg Rn, Reg Rt) {
690 return false;
691 }
692 virtual bool LDSET(bool A, bool R, Reg Rs, Reg Rn, Reg Rt) {
693 return false;
694 }
695 virtual bool LDSMAX(bool A, bool R, Reg Rs, Reg Rn, Reg Rt) {
696 return false;
697 }
698 virtual bool LDSMIN(bool A, bool R, Reg Rs, Reg Rn, Reg Rt) {
699 return false;
700 }
701 virtual bool LDUMAX(bool A, bool R, Reg Rs, Reg Rn, Reg Rt) {
702 return false;
703 }
704 virtual bool LDUMIN(bool A, bool R, Reg Rs, Reg Rn, Reg Rt) {
705 return false;
706 }
707 virtual bool SWP(bool A, bool R, Reg Rs, Reg Rn, Reg Rt) {
708 return false;
709 }
710 virtual bool LDAPR(Reg Rn, Reg Rt) {
711 return false;
712 }
713
714 // Loads and stores - Load/Store register (register offset)
715 virtual bool STRx_reg(Imm<2> size, Imm<1> opc_1, Reg Rm, Imm<3> option, bool S, Reg Rn,
716 Reg Rt) {
717 return false;
718 }
719 virtual bool LDRx_reg(Imm<2> size, Imm<1> opc_1, Reg Rm, Imm<3> option, bool S, Reg Rn,
720 Reg Rt) {
721 return false;
722 }
723 virtual bool STR_reg_fpsimd(Imm<2> size, Imm<1> opc_1, Reg Rm, Imm<3> option, bool S, Reg Rn,
724 Vec Vt) {
725 return false;
726 }
727 virtual bool LDR_reg_fpsimd(Imm<2> size, Imm<1> opc_1, Reg Rm, Imm<3> option, bool S, Reg Rn,
728 Vec Vt) {
729 return false;
730 }
731
732 // Loads and stores - Load/Store memory tags
733 virtual bool STG_1(Imm<9> imm9, Reg Rn) {
734 return false;
735 }
736 virtual bool STG_2(Imm<9> imm9, Reg Rn) {
737 return false;
738 }
739 virtual bool STG_3(Imm<9> imm9, Reg Rn) {
740 return false;
741 }
742 virtual bool LDG(Imm<9> offset_imm, Reg Rn, Reg Rt) {
743 return false;
744 }
745 virtual bool STZG_1(Imm<9> offset_imm, Reg Rn) {
746 return false;
747 }
748 virtual bool STZG_2(Imm<9> offset_imm, Reg Rn) {
749 return false;
750 }
751 virtual bool STZG_3(Imm<9> offset_imm, Reg Rn) {
752 return false;
753 }
754 virtual bool ST2G_1(Imm<9> offset_imm, Reg Rn) {
755 return false;
756 }
757 virtual bool ST2G_2(Imm<9> offset_imm, Reg Rn) {
758 return false;
759 }
760 virtual bool ST2G_3(Imm<9> offset_imm, Reg Rn) {
761 return false;
762 }
763 virtual bool STGV(Reg Rn, Reg Rt) {
764 return false;
765 }
766 virtual bool STZ2G_1(Imm<9> offset_imm, Reg Rn) {
767 return false;
768 }
769 virtual bool STZ2G_2(Imm<9> offset_imm, Reg Rn) {
770 return false;
771 }
772 virtual bool STZ2G_3(Imm<9> offset_imm, Reg Rn) {
773 return false;
774 }
775 virtual bool LDGV(Reg Rn, Reg Rt) {
776 return false;
777 }
778
779 // Loads and stores - Load/Store register (pointer authentication)
780 virtual bool LDRA(bool M, bool S, Imm<9> imm9, bool W, Reg Rn, Reg Rt) {
781 return false;
782 }
783
784 // Data Processing - Register - 2 source
785 virtual bool UDIV(bool sf, Reg Rm, Reg Rn, Reg Rd) {
786 return false;
787 }
788 virtual bool SDIV(bool sf, Reg Rm, Reg Rn, Reg Rd) {
789 return false;
790 }
791 virtual bool LSLV(bool sf, Reg Rm, Reg Rn, Reg Rd) {
792 return false;
793 }
794 virtual bool LSRV(bool sf, Reg Rm, Reg Rn, Reg Rd) {
795 return false;
796 }
797 virtual bool ASRV(bool sf, Reg Rm, Reg Rn, Reg Rd) {
798 return false;
799 }
800 virtual bool RORV(bool sf, Reg Rm, Reg Rn, Reg Rd) {
801 return false;
802 }
803 virtual bool CRC32(bool sf, Reg Rm, Imm<2> sz, Reg Rn, Reg Rd) {
804 return false;
805 }
806 virtual bool CRC32C(bool sf, Reg Rm, Imm<2> sz, Reg Rn, Reg Rd) {
807 return false;
808 }
809 virtual bool PACGA(Reg Rm, Reg Rn, Reg Rd) {
810 return false;
811 }
812 virtual bool SUBP(Reg Rm, Reg Rn, Reg Rd) {
813 return false;
814 }
815 virtual bool IRG(Reg Rm, Reg Rn, Reg Rd) {
816 return false;
817 }
818 virtual bool GMI(Reg Rm, Reg Rn, Reg Rd) {
819 return false;
820 }
821 virtual bool SUBPS(Reg Rm, Reg Rn, Reg Rd) {
822 return false;
823 }
824
825 // Data Processing - Register - 1 source
826 virtual bool RBIT_int(bool sf, Reg Rn, Reg Rd) {
827 return false;
828 }
829 virtual bool REV16_int(bool sf, Reg Rn, Reg Rd) {
830 return false;
831 }
832 virtual bool REV(bool sf, bool opc_0, Reg Rn, Reg Rd) {
833 return false;
834 }
835 virtual bool CLZ_int(bool sf, Reg Rn, Reg Rd) {
836 return false;
837 }
838 virtual bool CLS_int(bool sf, Reg Rn, Reg Rd) {
839 return false;
840 }
841 virtual bool REV32_int(Reg Rn, Reg Rd) {
842 return false;
843 }
844 virtual bool PACDA(bool Z, Reg Rn, Reg Rd) {
845 return false;
846 }
847 virtual bool PACDB(bool Z, Reg Rn, Reg Rd) {
848 return false;
849 }
850 virtual bool AUTDA(bool Z, Reg Rn, Reg Rd) {
851 return false;
852 }
853 virtual bool AUTDB(bool Z, Reg Rn, Reg Rd) {
854 return false;
855 }
856
857 // Data Processing - Register - Logical (shifted register)
858 virtual bool AND_shift(bool sf, Imm<2> shift, Reg Rm, Imm<6> imm6, Reg Rn, Reg Rd) {
859 return false;
860 }
861 virtual bool BIC_shift(bool sf, Imm<2> shift, Reg Rm, Imm<6> imm6, Reg Rn, Reg Rd) {
862 return false;
863 }
864 virtual bool ORR_shift(bool sf, Imm<2> shift, Reg Rm, Imm<6> imm6, Reg Rn, Reg Rd) {
865 return false;
866 }
867 virtual bool ORN_shift(bool sf, Imm<2> shift, Reg Rm, Imm<6> imm6, Reg Rn, Reg Rd) {
868 return false;
869 }
870 virtual bool EOR_shift(bool sf, Imm<2> shift, Reg Rm, Imm<6> imm6, Reg Rn, Reg Rd) {
871 return false;
872 }
873 virtual bool EON(bool sf, Imm<2> shift, Reg Rm, Imm<6> imm6, Reg Rn, Reg Rd) {
874 return false;
875 }
876 virtual bool ANDS_shift(bool sf, Imm<2> shift, Reg Rm, Imm<6> imm6, Reg Rn, Reg Rd) {
877 return false;
878 }
879 virtual bool BICS(bool sf, Imm<2> shift, Reg Rm, Imm<6> imm6, Reg Rn, Reg Rd) {
880 return false;
881 }
882
883 // Data Processing - Register - Add/Sub (shifted register)
884 virtual bool ADD_shift(bool sf, Imm<2> shift, Reg Rm, Imm<6> imm6, Reg Rn, Reg Rd) {
885 return false;
886 }
887 virtual bool ADDS_shift(bool sf, Imm<2> shift, Reg Rm, Imm<6> imm6, Reg Rn, Reg Rd) {
888 return false;
889 }
890 virtual bool SUB_shift(bool sf, Imm<2> shift, Reg Rm, Imm<6> imm6, Reg Rn, Reg Rd) {
891 return false;
892 }
893 virtual bool SUBS_shift(bool sf, Imm<2> shift, Reg Rm, Imm<6> imm6, Reg Rn, Reg Rd) {
894 return false;
895 }
896
897 // Data Processing - Register - Add/Sub (shifted register)
898 virtual bool ADD_ext(bool sf, Reg Rm, Imm<3> option, Imm<3> imm3, Reg Rn, Reg Rd) {
899 return false;
900 }
901 virtual bool ADDS_ext(bool sf, Reg Rm, Imm<3> option, Imm<3> imm3, Reg Rn, Reg Rd) {
902 return false;
903 }
904 virtual bool SUB_ext(bool sf, Reg Rm, Imm<3> option, Imm<3> imm3, Reg Rn, Reg Rd) {
905 return false;
906 }
907 virtual bool SUBS_ext(bool sf, Reg Rm, Imm<3> option, Imm<3> imm3, Reg Rn, Reg Rd) {
908 return false;
909 }
910
911 // Data Processing - Register - Add/Sub (with carry)
912 virtual bool ADC(bool sf, Reg Rm, Reg Rn, Reg Rd) {
913 return false;
914 }
915 virtual bool ADCS(bool sf, Reg Rm, Reg Rn, Reg Rd) {
916 return false;
917 }
918 virtual bool SBC(bool sf, Reg Rm, Reg Rn, Reg Rd) {
919 return false;
920 }
921 virtual bool SBCS(bool sf, Reg Rm, Reg Rn, Reg Rd) {
922 return false;
923 }
924
925 // Data Processing - Register - Conditional compare
926 virtual bool CCMN_reg(bool sf, Reg Rm, Cond cond, Reg Rn, Imm<4> nzcv) {
927 return false;
928 }
929 virtual bool CCMP_reg(bool sf, Reg Rm, Cond cond, Reg Rn, Imm<4> nzcv) {
930 return false;
931 }
932 virtual bool CCMN_imm(bool sf, Imm<5> imm5, Cond cond, Reg Rn, Imm<4> nzcv) {
933 return false;
934 }
935 virtual bool CCMP_imm(bool sf, Imm<5> imm5, Cond cond, Reg Rn, Imm<4> nzcv) {
936 return false;
937 }
938
939 // Data Processing - Register - Conditional select
940 virtual bool CSEL(bool sf, Reg Rm, Cond cond, Reg Rn, Reg Rd) {
941 return false;
942 }
943 virtual bool CSINC(bool sf, Reg Rm, Cond cond, Reg Rn, Reg Rd) {
944 return false;
945 }
946 virtual bool CSINV(bool sf, Reg Rm, Cond cond, Reg Rn, Reg Rd) {
947 return false;
948 }
949 virtual bool CSNEG(bool sf, Reg Rm, Cond cond, Reg Rn, Reg Rd) {
950 return false;
951 }
952
953 // Data Processing - Register - 3 source
954 virtual bool MADD(bool sf, Reg Rm, Reg Ra, Reg Rn, Reg Rd) {
955 return false;
956 }
957 virtual bool MSUB(bool sf, Reg Rm, Reg Ra, Reg Rn, Reg Rd) {
958 return false;
959 }
960 virtual bool SMADDL(Reg Rm, Reg Ra, Reg Rn, Reg Rd) {
961 return false;
962 }
963 virtual bool SMSUBL(Reg Rm, Reg Ra, Reg Rn, Reg Rd) {
964 return false;
965 }
966 virtual bool SMULH(Reg Rm, Reg Rn, Reg Rd) {
967 return false;
968 }
969 virtual bool UMADDL(Reg Rm, Reg Ra, Reg Rn, Reg Rd) {
970 return false;
971 }
972 virtual bool UMSUBL(Reg Rm, Reg Ra, Reg Rn, Reg Rd) {
973 return false;
974 }
975 virtual bool UMULH(Reg Rm, Reg Rn, Reg Rd) {
976 return false;
977 }
978
979 // Data Processing - FP and SIMD - AES
980 virtual bool AESE(Vec Vn, Vec Vd) {
981 return false;
982 }
983 virtual bool AESD(Vec Vn, Vec Vd) {
984 return false;
985 }
986 virtual bool AESMC(Vec Vn, Vec Vd) {
987 return false;
988 }
989 virtual bool AESIMC(Vec Vn, Vec Vd) {
990 return false;
991 }
992
993 // Data Processing - FP and SIMD - SHA
994 virtual bool SHA1C(Vec Vm, Vec Vn, Vec Vd) {
995 return false;
996 }
997 virtual bool SHA1P(Vec Vm, Vec Vn, Vec Vd) {
998 return false;
999 }
1000 virtual bool SHA1M(Vec Vm, Vec Vn, Vec Vd) {
1001 return false;
1002 }
1003 virtual bool SHA1SU0(Vec Vm, Vec Vn, Vec Vd) {
1004 return false;
1005 }
1006 virtual bool SHA256H(Vec Vm, Vec Vn, Vec Vd) {
1007 return false;
1008 }
1009 virtual bool SHA256H2(Vec Vm, Vec Vn, Vec Vd) {
1010 return false;
1011 }
1012 virtual bool SHA256SU1(Vec Vm, Vec Vn, Vec Vd) {
1013 return false;
1014 }
1015 virtual bool SHA1H(Vec Vn, Vec Vd) {
1016 return false;
1017 }
1018 virtual bool SHA1SU1(Vec Vn, Vec Vd) {
1019 return false;
1020 }
1021 virtual bool SHA256SU0(Vec Vn, Vec Vd) {
1022 return false;
1023 }
1024
1025 // Data Processing - FP and SIMD - Scalar copy
1026 virtual bool DUP_elt_1(Imm<5> imm5, Vec Vn, Vec Vd) {
1027 return false;
1028 }
1029
1030 // Data Processing - FP and SIMD - Scalar three
1031 virtual bool FMULX_vec_1(Vec Vm, Vec Vn, Vec Vd) {
1032 return false;
1033 }
1034 virtual bool FMULX_vec_2(bool sz, Vec Vm, Vec Vn, Vec Vd) {
1035 return false;
1036 }
1037 virtual bool FCMEQ_reg_1(Vec Vm, Vec Vn, Vec Vd) {
1038 return false;
1039 }
1040 virtual bool FCMEQ_reg_2(bool sz, Vec Vm, Vec Vn, Vec Vd) {
1041 return false;
1042 }
1043 virtual bool FRECPS_1(Vec Vm, Vec Vn, Vec Vd) {
1044 return false;
1045 }
1046 virtual bool FRECPS_2(bool sz, Vec Vm, Vec Vn, Vec Vd) {
1047 return false;
1048 }
1049 virtual bool FRSQRTS_1(Vec Vm, Vec Vn, Vec Vd) {
1050 return false;
1051 }
1052 virtual bool FRSQRTS_2(bool sz, Vec Vm, Vec Vn, Vec Vd) {
1053 return false;
1054 }
1055 virtual bool FCMGE_reg_1(Vec Vm, Vec Vn, Vec Vd) {
1056 return false;
1057 }
1058 virtual bool FCMGE_reg_2(bool sz, Vec Vm, Vec Vn, Vec Vd) {
1059 return false;
1060 }
1061 virtual bool FACGE_1(Vec Vm, Vec Vn, Vec Vd) {
1062 return false;
1063 }
1064 virtual bool FACGE_2(bool sz, Vec Vm, Vec Vn, Vec Vd) {
1065 return false;
1066 }
1067 virtual bool FABD_1(Vec Vm, Vec Vn, Vec Vd) {
1068 return false;
1069 }
1070 virtual bool FABD_2(bool sz, Vec Vm, Vec Vn, Vec Vd) {
1071 return false;
1072 }
1073 virtual bool FCMGT_reg_1(Vec Vm, Vec Vn, Vec Vd) {
1074 return false;
1075 }
1076 virtual bool FCMGT_reg_2(bool sz, Vec Vm, Vec Vn, Vec Vd) {
1077 return false;
1078 }
1079 virtual bool FACGT_1(Vec Vm, Vec Vn, Vec Vd) {
1080 return false;
1081 }
1082 virtual bool FACGT_2(bool sz, Vec Vm, Vec Vn, Vec Vd) {
1083 return false;
1084 }
1085
1086 // Data Processing - FP and SIMD - Two register misc FP16
1087 virtual bool FCVTNS_1(Vec Vn, Vec Vd) {
1088 return false;
1089 }
1090 virtual bool FCVTMS_1(Vec Vn, Vec Vd) {
1091 return false;
1092 }
1093 virtual bool FCVTAS_1(Vec Vn, Vec Vd) {
1094 return false;
1095 }
1096 virtual bool SCVTF_int_1(Vec Vn, Vec Vd) {
1097 return false;
1098 }
1099 virtual bool FCMGT_zero_1(Vec Vn, Vec Vd) {
1100 return false;
1101 }
1102 virtual bool FCMEQ_zero_1(Vec Vn, Vec Vd) {
1103 return false;
1104 }
1105 virtual bool FCMLT_1(Vec Vn, Vec Vd) {
1106 return false;
1107 }
1108 virtual bool FCVTPS_1(Vec Vn, Vec Vd) {
1109 return false;
1110 }
1111 virtual bool FCVTZS_int_1(Vec Vn, Vec Vd) {
1112 return false;
1113 }
1114 virtual bool FRECPE_1(Vec Vn, Vec Vd) {
1115 return false;
1116 }
1117 virtual bool FRECPX_1(Vec Vn, Vec Vd) {
1118 return false;
1119 }
1120 virtual bool FCVTNU_1(Vec Vn, Vec Vd) {
1121 return false;
1122 }
1123 virtual bool FCVTMU_1(Vec Vn, Vec Vd) {
1124 return false;
1125 }
1126 virtual bool FCVTAU_1(Vec Vn, Vec Vd) {
1127 return false;
1128 }
1129 virtual bool UCVTF_int_1(Vec Vn, Vec Vd) {
1130 return false;
1131 }
1132 virtual bool FCMGE_zero_1(Vec Vn, Vec Vd) {
1133 return false;
1134 }
1135 virtual bool FCMLE_1(Vec Vn, Vec Vd) {
1136 return false;
1137 }
1138 virtual bool FCVTPU_1(Vec Vn, Vec Vd) {
1139 return false;
1140 }
1141 virtual bool FCVTZU_int_1(Vec Vn, Vec Vd) {
1142 return false;
1143 }
1144 virtual bool FRSQRTE_1(Vec Vn, Vec Vd) {
1145 return false;
1146 }
1147
1148 // Data Processing - FP and SIMD - Two register misc
1149 virtual bool FCVTNS_2(bool sz, Vec Vn, Vec Vd) {
1150 return false;
1151 }
1152 virtual bool FCVTMS_2(bool sz, Vec Vn, Vec Vd) {
1153 return false;
1154 }
1155 virtual bool FCVTAS_2(bool sz, Vec Vn, Vec Vd) {
1156 return false;
1157 }
1158 virtual bool SCVTF_int_2(bool sz, Vec Vn, Vec Vd) {
1159 return false;
1160 }
1161 virtual bool FCMGT_zero_2(bool sz, Vec Vn, Vec Vd) {
1162 return false;
1163 }
1164 virtual bool FCMEQ_zero_2(bool sz, Vec Vn, Vec Vd) {
1165 return false;
1166 }
1167 virtual bool FCMLT_2(bool sz, Vec Vn, Vec Vd) {
1168 return false;
1169 }
1170 virtual bool FCVTPS_2(bool sz, Vec Vn, Vec Vd) {
1171 return false;
1172 }
1173 virtual bool FCVTZS_int_2(bool sz, Vec Vn, Vec Vd) {
1174 return false;
1175 }
1176 virtual bool FRECPE_2(bool sz, Vec Vn, Vec Vd) {
1177 return false;
1178 }
1179 virtual bool FRECPX_2(bool sz, Vec Vn, Vec Vd) {
1180 return false;
1181 }
1182 virtual bool FCVTNU_2(bool sz, Vec Vn, Vec Vd) {
1183 return false;
1184 }
1185 virtual bool FCVTMU_2(bool sz, Vec Vn, Vec Vd) {
1186 return false;
1187 }
1188 virtual bool FCVTAU_2(bool sz, Vec Vn, Vec Vd) {
1189 return false;
1190 }
1191 virtual bool UCVTF_int_2(bool sz, Vec Vn, Vec Vd) {
1192 return false;
1193 }
1194 virtual bool FCMGE_zero_2(bool sz, Vec Vn, Vec Vd) {
1195 return false;
1196 }
1197 virtual bool FCMLE_2(bool sz, Vec Vn, Vec Vd) {
1198 return false;
1199 }
1200 virtual bool FCVTPU_2(bool sz, Vec Vn, Vec Vd) {
1201 return false;
1202 }
1203 virtual bool FCVTZU_int_2(bool sz, Vec Vn, Vec Vd) {
1204 return false;
1205 }
1206 virtual bool FRSQRTE_2(bool sz, Vec Vn, Vec Vd) {
1207 return false;
1208 }
1209
1210 // Data Processing - FP and SIMD - Scalar two register misc FP16
1211 virtual bool FCVTNS_3(bool Q, Vec Vn, Vec Vd) {
1212 return false;
1213 }
1214 virtual bool FCVTMS_3(bool Q, Vec Vn, Vec Vd) {
1215 return false;
1216 }
1217 virtual bool FCVTAS_3(bool Q, Vec Vn, Vec Vd) {
1218 return false;
1219 }
1220 virtual bool SCVTF_int_3(bool Q, Vec Vn, Vec Vd) {
1221 return false;
1222 }
1223 virtual bool FCMGT_zero_3(bool Q, Vec Vn, Vec Vd) {
1224 return false;
1225 }
1226 virtual bool FCMEQ_zero_3(bool Q, Vec Vn, Vec Vd) {
1227 return false;
1228 }
1229 virtual bool FCMLT_3(bool Q, Vec Vn, Vec Vd) {
1230 return false;
1231 }
1232 virtual bool FCVTPS_3(bool Q, Vec Vn, Vec Vd) {
1233 return false;
1234 }
1235 virtual bool FCVTZS_int_3(bool Q, Vec Vn, Vec Vd) {
1236 return false;
1237 }
1238 virtual bool FRECPE_3(bool Q, Vec Vn, Vec Vd) {
1239 return false;
1240 }
1241 virtual bool FCVTNU_3(bool Q, Vec Vn, Vec Vd) {
1242 return false;
1243 }
1244 virtual bool FCVTMU_3(bool Q, Vec Vn, Vec Vd) {
1245 return false;
1246 }
1247 virtual bool FCVTAU_3(bool Q, Vec Vn, Vec Vd) {
1248 return false;
1249 }
1250 virtual bool UCVTF_int_3(bool Q, Vec Vn, Vec Vd) {
1251 return false;
1252 }
1253 virtual bool FCMGE_zero_3(bool Q, Vec Vn, Vec Vd) {
1254 return false;
1255 }
1256 virtual bool FCMLE_3(bool Q, Vec Vn, Vec Vd) {
1257 return false;
1258 }
1259 virtual bool FCVTPU_3(bool Q, Vec Vn, Vec Vd) {
1260 return false;
1261 }
1262 virtual bool FCVTZU_int_3(bool Q, Vec Vn, Vec Vd) {
1263 return false;
1264 }
1265 virtual bool FRSQRTE_3(bool Q, Vec Vn, Vec Vd) {
1266 return false;
1267 }
1268
1269 // Data Processing - FP and SIMD - Scalar two register misc
1270 virtual bool FCVTNS_4(bool Q, bool sz, Vec Vn, Vec Vd) {
1271 return false;
1272 }
1273 virtual bool FCVTMS_4(bool Q, bool sz, Vec Vn, Vec Vd) {
1274 return false;
1275 }
1276 virtual bool FCVTAS_4(bool Q, bool sz, Vec Vn, Vec Vd) {
1277 return false;
1278 }
1279 virtual bool SCVTF_int_4(bool Q, bool sz, Vec Vn, Vec Vd) {
1280 return false;
1281 }
1282 virtual bool FCMGT_zero_4(bool Q, bool sz, Vec Vn, Vec Vd) {
1283 return false;
1284 }
1285 virtual bool FCMEQ_zero_4(bool Q, bool sz, Vec Vn, Vec Vd) {
1286 return false;
1287 }
1288 virtual bool FCMLT_4(bool Q, bool sz, Vec Vn, Vec Vd) {
1289 return false;
1290 }
1291 virtual bool FCVTPS_4(bool Q, bool sz, Vec Vn, Vec Vd) {
1292 return false;
1293 }
1294 virtual bool FCVTZS_int_4(bool Q, bool sz, Vec Vn, Vec Vd) {
1295 return false;
1296 }
1297 virtual bool FRECPE_4(bool Q, bool sz, Vec Vn, Vec Vd) {
1298 return false;
1299 }
1300 virtual bool FCVTNU_4(bool Q, bool sz, Vec Vn, Vec Vd) {
1301 return false;
1302 }
1303 virtual bool FCVTMU_4(bool Q, bool sz, Vec Vn, Vec Vd) {
1304 return false;
1305 }
1306 virtual bool FCVTAU_4(bool Q, bool sz, Vec Vn, Vec Vd) {
1307 return false;
1308 }
1309 virtual bool UCVTF_int_4(bool Q, bool sz, Vec Vn, Vec Vd) {
1310 return false;
1311 }
1312 virtual bool FCMGE_zero_4(bool Q, bool sz, Vec Vn, Vec Vd) {
1313 return false;
1314 }
1315 virtual bool FCMLE_4(bool Q, bool sz, Vec Vn, Vec Vd) {
1316 return false;
1317 }
1318 virtual bool FCVTPU_4(bool Q, bool sz, Vec Vn, Vec Vd) {
1319 return false;
1320 }
1321 virtual bool FCVTZU_int_4(bool Q, bool sz, Vec Vn, Vec Vd) {
1322 return false;
1323 }
1324 virtual bool FRSQRTE_4(bool Q, bool sz, Vec Vn, Vec Vd) {
1325 return false;
1326 }
1327
1328 // Data Processing - FP and SIMD - Scalar three same extra
1329 virtual bool SQRDMLAH_vec_1(Imm<2> size, Vec Vm, Vec Vn, Vec Vd) {
1330 return false;
1331 }
1332 virtual bool SQRDMLAH_vec_2(bool Q, Imm<2> size, Vec Vm, Vec Vn, Vec Vd) {
1333 return false;
1334 }
1335 virtual bool SQRDMLSH_vec_1(Imm<2> size, Vec Vm, Vec Vn, Vec Vd) {
1336 return false;
1337 }
1338 virtual bool SQRDMLSH_vec_2(bool Q, Imm<2> size, Vec Vm, Vec Vn, Vec Vd) {
1339 return false;
1340 }
1341
1342 // Data Processing - FP and SIMD - Scalar two-register misc
1343 virtual bool SUQADD_1(Imm<2> size, Vec Vn, Vec Vd) {
1344 return false;
1345 }
1346 virtual bool SQABS_1(Imm<2> size, Vec Vn, Vec Vd) {
1347 return false;
1348 }
1349 virtual bool CMGT_zero_1(Imm<2> size, Vec Vn, Vec Vd) {
1350 return false;
1351 }
1352 virtual bool CMEQ_zero_1(Imm<2> size, Vec Vn, Vec Vd) {
1353 return false;
1354 }
1355 virtual bool CMLT_1(Imm<2> size, Vec Vn, Vec Vd) {
1356 return false;
1357 }
1358 virtual bool ABS_1(Imm<2> size, Vec Vn, Vec Vd) {
1359 return false;
1360 }
1361 virtual bool SQXTN_1(Imm<2> size, Vec Vn, Vec Vd) {
1362 return false;
1363 }
1364 virtual bool USQADD_1(Imm<2> size, Vec Vn, Vec Vd) {
1365 return false;
1366 }
1367 virtual bool SQNEG_1(Imm<2> size, Vec Vn, Vec Vd) {
1368 return false;
1369 }
1370 virtual bool CMGE_zero_1(Imm<2> size, Vec Vn, Vec Vd) {
1371 return false;
1372 }
1373 virtual bool CMLE_1(Imm<2> size, Vec Vn, Vec Vd) {
1374 return false;
1375 }
1376 virtual bool NEG_1(Imm<2> size, Vec Vn, Vec Vd) {
1377 return false;
1378 }
1379 virtual bool SQXTUN_1(Imm<2> size, Vec Vn, Vec Vd) {
1380 return false;
1381 }
1382 virtual bool UQXTN_1(Imm<2> size, Vec Vn, Vec Vd) {
1383 return false;
1384 }
1385 virtual bool FCVTXN_1(bool sz, Vec Vn, Vec Vd) {
1386 return false;
1387 }
1388
1389 // Data Processing - FP and SIMD - SIMD Scalar pairwise
1390 virtual bool ADDP_pair(Imm<2> size, Vec Vn, Vec Vd) {
1391 return false;
1392 }
1393 virtual bool FMAXNMP_pair_1(Vec Vn, Vec Vd) {
1394 return false;
1395 }
1396 virtual bool FMAXNMP_pair_2(bool sz, Vec Vn, Vec Vd) {
1397 return false;
1398 }
1399 virtual bool FADDP_pair_1(Vec Vn, Vec Vd) {
1400 return false;
1401 }
1402 virtual bool FADDP_pair_2(bool sz, Vec Vn, Vec Vd) {
1403 return false;
1404 }
1405 virtual bool FMAXP_pair_1(Vec Vn, Vec Vd) {
1406 return false;
1407 }
1408 virtual bool FMAXP_pair_2(bool sz, Vec Vn, Vec Vd) {
1409 return false;
1410 }
1411 virtual bool FMINNMP_pair_1(Vec Vn, Vec Vd) {
1412 return false;
1413 }
1414 virtual bool FMINNMP_pair_2(bool sz, Vec Vn, Vec Vd) {
1415 return false;
1416 }
1417 virtual bool FMINP_pair_1(Vec Vn, Vec Vd) {
1418 return false;
1419 }
1420 virtual bool FMINP_pair_2(bool sz, Vec Vn, Vec Vd) {
1421 return false;
1422 }
1423
1424 // Data Processing - FP and SIMD - SIMD Scalar three different
1425 virtual bool SQDMLAL_vec_1(Imm<2> size, Reg Rm, Reg Rn, Vec Vd) {
1426 return false;
1427 }
1428 virtual bool SQDMLSL_vec_1(Imm<2> size, Reg Rm, Reg Rn, Vec Vd) {
1429 return false;
1430 }
1431 virtual bool SQDMULL_vec_1(Imm<2> size, Reg Rm, Reg Rn, Vec Vd) {
1432 return false;
1433 }
1434
1435 // Data Processing - FP and SIMD - SIMD Scalar three same
1436 virtual bool SQADD_1(Imm<2> size, Vec Vm, Vec Vn, Vec Vd) {
1437 return false;
1438 }
1439 virtual bool SQSUB_1(Imm<2> size, Vec Vm, Vec Vn, Vec Vd) {
1440 return false;
1441 }
1442 virtual bool CMGT_reg_1(Imm<2> size, Vec Vm, Vec Vn, Vec Vd) {
1443 return false;
1444 }
1445 virtual bool CMGE_reg_1(Imm<2> size, Vec Vm, Vec Vn, Vec Vd) {
1446 return false;
1447 }
1448 virtual bool SSHL_1(Imm<2> size, Vec Vm, Vec Vn, Vec Vd) {
1449 return false;
1450 }
1451 virtual bool SQSHL_reg_1(Imm<2> size, Vec Vm, Vec Vn, Vec Vd) {
1452 return false;
1453 }
1454 virtual bool SRSHL_1(Imm<2> size, Vec Vm, Vec Vn, Vec Vd) {
1455 return false;
1456 }
1457 virtual bool SQRSHL_1(Imm<2> size, Vec Vm, Vec Vn, Vec Vd) {
1458 return false;
1459 }
1460 virtual bool ADD_1(Imm<2> size, Vec Vm, Vec Vn, Vec Vd) {
1461 return false;
1462 }
1463 virtual bool CMTST_1(Imm<2> size, Vec Vm, Vec Vn, Vec Vd) {
1464 return false;
1465 }
1466 virtual bool SQDMULH_vec_1(Imm<2> size, Vec Vm, Vec Vn, Vec Vd) {
1467 return false;
1468 }
1469 virtual bool UQADD_1(Imm<2> size, Vec Vm, Vec Vn, Vec Vd) {
1470 return false;
1471 }
1472 virtual bool UQSUB_1(Imm<2> size, Vec Vm, Vec Vn, Vec Vd) {
1473 return false;
1474 }
1475 virtual bool CMHI_1(Imm<2> size, Vec Vm, Vec Vn, Vec Vd) {
1476 return false;
1477 }
1478 virtual bool CMHS_1(Imm<2> size, Vec Vm, Vec Vn, Vec Vd) {
1479 return false;
1480 }
1481 virtual bool USHL_1(Imm<2> size, Vec Vm, Vec Vn, Vec Vd) {
1482 return false;
1483 }
1484 virtual bool UQSHL_reg_1(Imm<2> size, Vec Vm, Vec Vn, Vec Vd) {
1485 return false;
1486 }
1487 virtual bool URSHL_1(Imm<2> size, Vec Vm, Vec Vn, Vec Vd) {
1488 return false;
1489 }
1490 virtual bool UQRSHL_1(Imm<2> size, Vec Vm, Vec Vn, Vec Vd) {
1491 return false;
1492 }
1493 virtual bool SUB_1(Imm<2> size, Vec Vm, Vec Vn, Vec Vd) {
1494 return false;
1495 }
1496 virtual bool CMEQ_reg_1(Imm<2> size, Vec Vm, Vec Vn, Vec Vd) {
1497 return false;
1498 }
1499 virtual bool SQRDMULH_vec_1(Imm<2> size, Vec Vm, Vec Vn, Vec Vd) {
1500 return false;
1501 }
1502
1503 // Data Processing - FP and SIMD - SIMD Scalar shift by immediate
1504 virtual bool SSHR_1(Imm<4> immh, Imm<3> immb, Vec Vn, Vec Vd) {
1505 return false;
1506 }
1507 virtual bool SSRA_1(Imm<4> immh, Imm<3> immb, Vec Vn, Vec Vd) {
1508 return false;
1509 }
1510 virtual bool SRSHR_1(Imm<4> immh, Imm<3> immb, Vec Vn, Vec Vd) {
1511 return false;
1512 }
1513 virtual bool SRSRA_1(Imm<4> immh, Imm<3> immb, Vec Vn, Vec Vd) {
1514 return false;
1515 }
1516 virtual bool SHL_1(Imm<4> immh, Imm<3> immb, Vec Vn, Vec Vd) {
1517 return false;
1518 }
1519 virtual bool SQSHL_imm_1(Imm<4> immh, Imm<3> immb, Vec Vn, Vec Vd) {
1520 return false;
1521 }
1522 virtual bool SQSHRN_1(Imm<4> immh, Imm<3> immb, Vec Vn, Vec Vd) {
1523 return false;
1524 }
1525 virtual bool SQRSHRN_1(Imm<4> immh, Imm<3> immb, Vec Vn, Vec Vd) {
1526 return false;
1527 }
1528 virtual bool SCVTF_fix_1(Imm<4> immh, Imm<3> immb, Vec Vn, Vec Vd) {
1529 return false;
1530 }
1531 virtual bool FCVTZS_fix_1(Imm<4> immh, Imm<3> immb, Vec Vn, Vec Vd) {
1532 return false;
1533 }
1534 virtual bool USHR_1(Imm<4> immh, Imm<3> immb, Vec Vn, Vec Vd) {
1535 return false;
1536 }
1537 virtual bool USRA_1(Imm<4> immh, Imm<3> immb, Vec Vn, Vec Vd) {
1538 return false;
1539 }
1540 virtual bool URSHR_1(Imm<4> immh, Imm<3> immb, Vec Vn, Vec Vd) {
1541 return false;
1542 }
1543 virtual bool URSRA_1(Imm<4> immh, Imm<3> immb, Vec Vn, Vec Vd) {
1544 return false;
1545 }
1546 virtual bool SRI_1(Imm<4> immh, Imm<3> immb, Vec Vn, Vec Vd) {
1547 return false;
1548 }
1549 virtual bool SLI_1(Imm<4> immh, Imm<3> immb, Vec Vn, Vec Vd) {
1550 return false;
1551 }
1552 virtual bool SQSHLU_1(Imm<4> immh, Imm<3> immb, Vec Vn, Vec Vd) {
1553 return false;
1554 }
1555 virtual bool UQSHL_imm_1(Imm<4> immh, Imm<3> immb, Vec Vn, Vec Vd) {
1556 return false;
1557 }
1558 virtual bool SQSHRUN_1(Imm<4> immh, Imm<3> immb, Vec Vn, Vec Vd) {
1559 return false;
1560 }
1561 virtual bool SQRSHRUN_1(Imm<4> immh, Imm<3> immb, Vec Vn, Vec Vd) {
1562 return false;
1563 }
1564 virtual bool UQSHRN_1(Imm<4> immh, Imm<3> immb, Vec Vn, Vec Vd) {
1565 return false;
1566 }
1567 virtual bool UQRSHRN_1(Imm<4> immh, Imm<3> immb, Vec Vn, Vec Vd) {
1568 return false;
1569 }
1570 virtual bool UCVTF_fix_1(Imm<4> immh, Imm<3> immb, Vec Vn, Vec Vd) {
1571 return false;
1572 }
1573 virtual bool FCVTZU_fix_1(Imm<4> immh, Imm<3> immb, Vec Vn, Vec Vd) {
1574 return false;
1575 }
1576
1577 // Data Processing - FP and SIMD - SIMD Scalar x indexed element
1578 virtual bool SQDMLAL_elt_1(Imm<2> size, Imm<1> L, Imm<1> M, Imm<4> Vmlo, Imm<1> H, Vec Vn,
1579 Vec Vd) {
1580 return false;
1581 }
1582 virtual bool SQDMLSL_elt_1(Imm<2> size, Imm<1> L, Imm<1> M, Imm<4> Vmlo, Imm<1> H, Vec Vn,
1583 Vec Vd) {
1584 return false;
1585 }
1586 virtual bool SQDMULL_elt_1(Imm<2> size, Imm<1> L, Imm<1> M, Imm<4> Vmlo, Imm<1> H, Vec Vn,
1587 Vec Vd) {
1588 return false;
1589 }
1590 virtual bool SQDMULH_elt_1(Imm<2> size, Imm<1> L, Imm<1> M, Imm<4> Vmlo, Imm<1> H, Vec Vn,
1591 Vec Vd) {
1592 return false;
1593 }
1594 virtual bool SQRDMULH_elt_1(Imm<2> size, Imm<1> L, Imm<1> M, Imm<4> Vmlo, Imm<1> H, Vec Vn,
1595 Vec Vd) {
1596 return false;
1597 }
1598 virtual bool FMLA_elt_1(Imm<1> L, Imm<1> M, Imm<4> Vmlo, Imm<1> H, Vec Vn, Vec Vd) {
1599 return false;
1600 }
1601 virtual bool FMLA_elt_2(bool sz, Imm<1> L, Imm<1> M, Imm<4> Vmlo, Imm<1> H, Vec Vn, Vec Vd) {
1602 return false;
1603 }
1604 virtual bool FMLS_elt_1(Imm<1> L, Imm<1> M, Imm<4> Vmlo, Imm<1> H, Vec Vn, Vec Vd) {
1605 return false;
1606 }
1607 virtual bool FMLS_elt_2(bool sz, Imm<1> L, Imm<1> M, Imm<4> Vmlo, Imm<1> H, Vec Vn, Vec Vd) {
1608 return false;
1609 }
1610 virtual bool FMUL_elt_1(Imm<1> L, Imm<1> M, Imm<4> Vmlo, Imm<1> H, Vec Vn, Vec Vd) {
1611 return false;
1612 }
1613 virtual bool FMUL_elt_2(bool sz, Imm<1> L, Imm<1> M, Imm<4> Vmlo, Imm<1> H, Vec Vn, Vec Vd) {
1614 return false;
1615 }
1616 virtual bool SQRDMLAH_elt_1(Imm<2> size, Imm<1> L, Imm<1> M, Imm<4> Vmlo, Imm<1> H, Vec Vn,
1617 Vec Vd) {
1618 return false;
1619 }
1620 virtual bool SQRDMLSH_elt_1(Imm<2> size, Imm<1> L, Imm<1> M, Imm<4> Vmlo, Imm<1> H, Vec Vn,
1621 Vec Vd) {
1622 return false;
1623 }
1624 virtual bool FMULX_elt_1(Imm<1> L, Imm<1> M, Imm<4> Vmlo, Imm<1> H, Vec Vn, Vec Vd) {
1625 return false;
1626 }
1627 virtual bool FMULX_elt_2(bool sz, Imm<1> L, Imm<1> M, Imm<4> Vmlo, Imm<1> H, Vec Vn, Vec Vd) {
1628 return false;
1629 }
1630
1631 // Data Processing - FP and SIMD - SIMD Table Lookup
1632 virtual bool TBL(bool Q, Vec Vm, Imm<2> len, size_t Vn, Vec Vd) {
1633 return false;
1634 }
1635 virtual bool TBX(bool Q, Vec Vm, Imm<2> len, size_t Vn, Vec Vd) {
1636 return false;
1637 }
1638
1639 // Data Processing - FP and SIMD - SIMD Permute
1640 virtual bool UZP1(bool Q, Imm<2> size, Vec Vm, Vec Vn, Vec Vd) {
1641 return false;
1642 }
1643 virtual bool TRN1(bool Q, Imm<2> size, Vec Vm, Vec Vn, Vec Vd) {
1644 return false;
1645 }
1646 virtual bool ZIP1(bool Q, Imm<2> size, Vec Vm, Vec Vn, Vec Vd) {
1647 return false;
1648 }
1649 virtual bool UZP2(bool Q, Imm<2> size, Vec Vm, Vec Vn, Vec Vd) {
1650 return false;
1651 }
1652 virtual bool TRN2(bool Q, Imm<2> size, Vec Vm, Vec Vn, Vec Vd) {
1653 return false;
1654 }
1655 virtual bool ZIP2(bool Q, Imm<2> size, Vec Vm, Vec Vn, Vec Vd) {
1656 return false;
1657 }
1658
1659 // Data Processing - FP and SIMD - SIMD Extract
1660 virtual bool EXT(bool Q, Vec Vm, Imm<4> imm4, Vec Vn, Vec Vd) {
1661 return false;
1662 }
1663
1664 // Data Processing - FP and SIMD - SIMD Copy
1665 virtual bool DUP_elt_2(bool Q, Imm<5> imm5, Vec Vn, Vec Vd) {
1666 return false;
1667 }
1668 virtual bool DUP_gen(bool Q, Imm<5> imm5, Reg Rn, Vec Vd) {
1669 return false;
1670 }
1671 virtual bool SMOV(bool Q, Imm<5> imm5, Vec Vn, Reg Rd) {
1672 return false;
1673 }
1674 virtual bool UMOV(bool Q, Imm<5> imm5, Vec Vn, Reg Rd) {
1675 return false;
1676 }
1677 virtual bool INS_gen(Imm<5> imm5, Reg Rn, Vec Vd) {
1678 return false;
1679 }
1680 virtual bool INS_elt(Imm<5> imm5, Imm<4> imm4, Vec Vn, Vec Vd) {
1681 return false;
1682 }
1683
1684 // Data Processing - FP and SIMD - SIMD Three same
1685 virtual bool FMULX_vec_3(bool Q, Vec Vm, Vec Vn, Vec Vd) {
1686 return false;
1687 }
1688 virtual bool FCMEQ_reg_3(bool Q, Vec Vm, Vec Vn, Vec Vd) {
1689 return false;
1690 }
1691 virtual bool FRECPS_3(bool Q, Vec Vm, Vec Vn, Vec Vd) {
1692 return false;
1693 }
1694 virtual bool FRSQRTS_3(bool Q, Vec Vm, Vec Vn, Vec Vd) {
1695 return false;
1696 }
1697 virtual bool FCMGE_reg_3(bool Q, Vec Vm, Vec Vn, Vec Vd) {
1698 return false;
1699 }
1700 virtual bool FACGE_3(bool Q, Vec Vm, Vec Vn, Vec Vd) {
1701 return false;
1702 }
1703 virtual bool FABD_3(bool Q, Vec Vm, Vec Vn, Vec Vd) {
1704 return false;
1705 }
1706 virtual bool FCMGT_reg_3(bool Q, Vec Vm, Vec Vn, Vec Vd) {
1707 return false;
1708 }
1709 virtual bool FACGT_3(bool Q, Vec Vm, Vec Vn, Vec Vd) {
1710 return false;
1711 }
1712 virtual bool FMAXNM_1(bool Q, Vec Vm, Vec Vn, Vec Vd) {
1713 return false;
1714 }
1715 virtual bool FMLA_vec_1(bool Q, Vec Vm, Vec Vn, Vec Vd) {
1716 return false;
1717 }
1718 virtual bool FADD_1(bool Q, Vec Vm, Vec Vn, Vec Vd) {
1719 return false;
1720 }
1721 virtual bool FMAX_1(bool Q, Vec Vm, Vec Vn, Vec Vd) {
1722 return false;
1723 }
1724 virtual bool FMINNM_1(bool Q, Vec Vm, Vec Vn, Vec Vd) {
1725 return false;
1726 }
1727 virtual bool FMLS_vec_1(bool Q, Vec Vm, Vec Vn, Vec Vd) {
1728 return false;
1729 }
1730 virtual bool FSUB_1(bool Q, Vec Vm, Vec Vn, Vec Vd) {
1731 return false;
1732 }
1733 virtual bool FMIN_1(bool Q, Vec Vm, Vec Vn, Vec Vd) {
1734 return false;
1735 }
1736 virtual bool FMAXNMP_vec_1(bool Q, Vec Vm, Vec Vn, Vec Vd) {
1737 return false;
1738 }
1739 virtual bool FADDP_vec_1(bool Q, Vec Vm, Vec Vn, Vec Vd) {
1740 return false;
1741 }
1742 virtual bool FMUL_vec_1(bool Q, Vec Vm, Vec Vn, Vec Vd) {
1743 return false;
1744 }
1745 virtual bool FMAXP_vec_1(bool Q, Vec Vm, Vec Vn, Vec Vd) {
1746 return false;
1747 }
1748 virtual bool FDIV_1(bool Q, Vec Vm, Vec Vn, Vec Vd) {
1749 return false;
1750 }
1751 virtual bool FMINNMP_vec_1(bool Q, Vec Vm, Vec Vn, Vec Vd) {
1752 return false;
1753 }
1754 virtual bool FMINP_vec_1(bool Q, Vec Vm, Vec Vn, Vec Vd) {
1755 return false;
1756 }
1757
1758 // Data Processing - FP and SIMD - SIMD Three same extra
1759 virtual bool SDOT_vec(bool Q, Imm<2> size, Vec Vm, Vec Vn, Vec Vd) {
1760 return false;
1761 }
1762 virtual bool UDOT_vec(bool Q, Imm<2> size, Vec Vm, Vec Vn, Vec Vd) {
1763 return false;
1764 }
1765 virtual bool FCMLA_vec(bool Q, Imm<2> size, Vec Vm, Imm<2> rot, Vec Vn, Vec Vd) {
1766 return false;
1767 }
1768 virtual bool FCADD_vec(bool Q, Imm<2> size, Vec Vm, Imm<1> rot, Vec Vn, Vec Vd) {
1769 return false;
1770 }
1771
1772 // Data Processing - FP and SIMD - SIMD Two register misc
1773 virtual bool REV64_asimd(bool Q, Imm<2> size, Vec Vn, Vec Vd) {
1774 return false;
1775 }
1776 virtual bool REV16_asimd(bool Q, Imm<2> size, Vec Vn, Vec Vd) {
1777 return false;
1778 }
1779 virtual bool SADDLP(bool Q, Imm<2> size, Vec Vn, Vec Vd) {
1780 return false;
1781 }
1782 virtual bool CLS_asimd(bool Q, Imm<2> size, Vec Vn, Vec Vd) {
1783 return false;
1784 }
1785 virtual bool CNT(bool Q, Imm<2> size, Vec Vn, Vec Vd) {
1786 return false;
1787 }
1788 virtual bool SADALP(bool Q, Imm<2> size, Vec Vn, Vec Vd) {
1789 return false;
1790 }
1791 virtual bool XTN(bool Q, Imm<2> size, Vec Vn, Vec Vd) {
1792 return false;
1793 }
1794 virtual bool FCVTN(bool Q, bool sz, Vec Vn, Vec Vd) {
1795 return false;
1796 }
1797 virtual bool FCVTL(bool Q, bool sz, Vec Vn, Vec Vd) {
1798 return false;
1799 }
1800 virtual bool URECPE(bool Q, bool sz, Vec Vn, Vec Vd) {
1801 return false;
1802 }
1803 virtual bool REV32_asimd(bool Q, Imm<2> size, Vec Vn, Vec Vd) {
1804 return false;
1805 }
1806 virtual bool UADDLP(bool Q, Imm<2> size, Vec Vn, Vec Vd) {
1807 return false;
1808 }
1809 virtual bool CLZ_asimd(bool Q, Imm<2> size, Vec Vn, Vec Vd) {
1810 return false;
1811 }
1812 virtual bool UADALP(bool Q, Imm<2> size, Vec Vn, Vec Vd) {
1813 return false;
1814 }
1815 virtual bool SHLL(bool Q, Imm<2> size, Vec Vn, Vec Vd) {
1816 return false;
1817 }
1818 virtual bool NOT(bool Q, Vec Vn, Vec Vd) {
1819 return false;
1820 }
1821 virtual bool RBIT_asimd(bool Q, Vec Vn, Vec Vd) {
1822 return false;
1823 }
1824 virtual bool URSQRTE(bool Q, bool sz, Vec Vn, Vec Vd) {
1825 return false;
1826 }
1827 virtual bool SUQADD_2(bool Q, Imm<2> size, Vec Vn, Vec Vd) {
1828 return false;
1829 }
1830 virtual bool SQABS_2(bool Q, Imm<2> size, Vec Vn, Vec Vd) {
1831 return false;
1832 }
1833 virtual bool CMGT_zero_2(bool Q, Imm<2> size, Vec Vn, Vec Vd) {
1834 return false;
1835 }
1836 virtual bool CMEQ_zero_2(bool Q, Imm<2> size, Vec Vn, Vec Vd) {
1837 return false;
1838 }
1839 virtual bool CMLT_2(bool Q, Imm<2> size, Vec Vn, Vec Vd) {
1840 return false;
1841 }
1842 virtual bool ABS_2(bool Q, Imm<2> size, Vec Vn, Vec Vd) {
1843 return false;
1844 }
1845 virtual bool SQXTN_2(bool Q, Imm<2> size, Vec Vn, Vec Vd) {
1846 return false;
1847 }
1848 virtual bool USQADD_2(bool Q, Imm<2> size, Vec Vn, Vec Vd) {
1849 return false;
1850 }
1851 virtual bool SQNEG_2(bool Q, Imm<2> size, Vec Vn, Vec Vd) {
1852 return false;
1853 }
1854 virtual bool CMGE_zero_2(bool Q, Imm<2> size, Vec Vn, Vec Vd) {
1855 return false;
1856 }
1857 virtual bool CMLE_2(bool Q, Imm<2> size, Vec Vn, Vec Vd) {
1858 return false;
1859 }
1860 virtual bool NEG_2(bool Q, Imm<2> size, Vec Vn, Vec Vd) {
1861 return false;
1862 }
1863 virtual bool SQXTUN_2(bool Q, Imm<2> size, Vec Vn, Vec Vd) {
1864 return false;
1865 }
1866 virtual bool UQXTN_2(bool Q, Imm<2> size, Vec Vn, Vec Vd) {
1867 return false;
1868 }
1869 virtual bool FCVTXN_2(bool Q, bool sz, Vec Vn, Vec Vd) {
1870 return false;
1871 }
1872 virtual bool FRINTN_1(bool Q, Vec Vn, Vec Vd) {
1873 return false;
1874 }
1875 virtual bool FRINTN_2(bool Q, bool sz, Vec Vn, Vec Vd) {
1876 return false;
1877 }
1878 virtual bool FRINTM_1(bool Q, Vec Vn, Vec Vd) {
1879 return false;
1880 }
1881 virtual bool FRINTM_2(bool Q, bool sz, Vec Vn, Vec Vd) {
1882 return false;
1883 }
1884 virtual bool FABS_1(bool Q, Vec Vn, Vec Vd) {
1885 return false;
1886 }
1887 virtual bool FABS_2(bool Q, bool sz, Vec Vn, Vec Vd) {
1888 return false;
1889 }
1890 virtual bool FRINTP_1(bool Q, Vec Vn, Vec Vd) {
1891 return false;
1892 }
1893 virtual bool FRINTP_2(bool Q, bool sz, Vec Vn, Vec Vd) {
1894 return false;
1895 }
1896 virtual bool FRINTZ_1(bool Q, Vec Vn, Vec Vd) {
1897 return false;
1898 }
1899 virtual bool FRINTZ_2(bool Q, bool sz, Vec Vn, Vec Vd) {
1900 return false;
1901 }
1902 virtual bool FRINTA_1(bool Q, Vec Vn, Vec Vd) {
1903 return false;
1904 }
1905 virtual bool FRINTA_2(bool Q, bool sz, Vec Vn, Vec Vd) {
1906 return false;
1907 }
1908 virtual bool FRINTX_1(bool Q, Vec Vn, Vec Vd) {
1909 return false;
1910 }
1911 virtual bool FRINTX_2(bool Q, bool sz, Vec Vn, Vec Vd) {
1912 return false;
1913 }
1914 virtual bool FNEG_1(bool Q, Vec Vn, Vec Vd) {
1915 return false;
1916 }
1917 virtual bool FNEG_2(bool Q, bool sz, Vec Vn, Vec Vd) {
1918 return false;
1919 }
1920 virtual bool FRINTI_1(bool Q, Vec Vn, Vec Vd) {
1921 return false;
1922 }
1923 virtual bool FRINTI_2(bool Q, bool sz, Vec Vn, Vec Vd) {
1924 return false;
1925 }
1926 virtual bool FSQRT_1(bool Q, Vec Vn, Vec Vd) {
1927 return false;
1928 }
1929 virtual bool FSQRT_2(bool Q, bool sz, Vec Vn, Vec Vd) {
1930 return false;
1931 }
1932 virtual bool FRINT32X_1(bool Q, bool sz, Vec Vn, Vec Vd) {
1933 return false;
1934 }
1935 virtual bool FRINT64X_1(bool Q, bool sz, Vec Vn, Vec Vd) {
1936 return false;
1937 }
1938 virtual bool FRINT32Z_1(bool Q, bool sz, Vec Vn, Vec Vd) {
1939 return false;
1940 }
1941 virtual bool FRINT64Z_1(bool Q, bool sz, Vec Vn, Vec Vd) {
1942 return false;
1943 }
1944
1945 // Data Processing - FP and SIMD - SIMD across lanes
1946 virtual bool SADDLV(bool Q, Imm<2> size, Vec Vn, Vec Vd) {
1947 return false;
1948 }
1949 virtual bool SMAXV(bool Q, Imm<2> size, Vec Vn, Vec Vd) {
1950 return false;
1951 }
1952 virtual bool SMINV(bool Q, Imm<2> size, Vec Vn, Vec Vd) {
1953 return false;
1954 }
1955 virtual bool ADDV(bool Q, Imm<2> size, Vec Vn, Vec Vd) {
1956 return false;
1957 }
1958 virtual bool FMAXNMV_1(bool Q, Vec Vn, Vec Vd) {
1959 return false;
1960 }
1961 virtual bool FMAXNMV_2(bool Q, bool sz, Vec Vn, Vec Vd) {
1962 return false;
1963 }
1964 virtual bool FMAXV_1(bool Q, Vec Vn, Vec Vd) {
1965 return false;
1966 }
1967 virtual bool FMAXV_2(bool Q, bool sz, Vec Vn, Vec Vd) {
1968 return false;
1969 }
1970 virtual bool FMINNMV_1(bool Q, Vec Vn, Vec Vd) {
1971 return false;
1972 }
1973 virtual bool FMINNMV_2(bool Q, bool sz, Vec Vn, Vec Vd) {
1974 return false;
1975 }
1976 virtual bool FMINV_1(bool Q, Vec Vn, Vec Vd) {
1977 return false;
1978 }
1979 virtual bool FMINV_2(bool Q, bool sz, Vec Vn, Vec Vd) {
1980 return false;
1981 }
1982 virtual bool UADDLV(bool Q, Imm<2> size, Vec Vn, Vec Vd) {
1983 return false;
1984 }
1985 virtual bool UMAXV(bool Q, Imm<2> size, Vec Vn, Vec Vd) {
1986 return false;
1987 }
1988 virtual bool UMINV(bool Q, Imm<2> size, Vec Vn, Vec Vd) {
1989 return false;
1990 }
1991
1992 // Data Processing - FP and SIMD - SIMD three different
1993 virtual bool SADDL(bool Q, Imm<2> size, Vec Vm, Vec Vn, Vec Vd) {
1994 return false;
1995 }
1996 virtual bool SADDW(bool Q, Imm<2> size, Vec Vm, Vec Vn, Vec Vd) {
1997 return false;
1998 }
1999 virtual bool SSUBL(bool Q, Imm<2> size, Vec Vm, Vec Vn, Vec Vd) {
2000 return false;
2001 }
2002 virtual bool SSUBW(bool Q, Imm<2> size, Vec Vm, Vec Vn, Vec Vd) {
2003 return false;
2004 }
2005 virtual bool ADDHN(bool Q, Imm<2> size, Vec Vm, Vec Vn, Vec Vd) {
2006 return false;
2007 }
2008 virtual bool SABAL(bool Q, Imm<2> size, Vec Vm, Vec Vn, Vec Vd) {
2009 return false;
2010 }
2011 virtual bool SUBHN(bool Q, Imm<2> size, Vec Vm, Vec Vn, Vec Vd) {
2012 return false;
2013 }
2014 virtual bool SABDL(bool Q, Imm<2> size, Vec Vm, Vec Vn, Vec Vd) {
2015 return false;
2016 }
2017 virtual bool SMLAL_vec(bool Q, Imm<2> size, Vec Vm, Vec Vn, Vec Vd) {
2018 return false;
2019 }
2020 virtual bool SMLSL_vec(bool Q, Imm<2> size, Vec Vm, Vec Vn, Vec Vd) {
2021 return false;
2022 }
2023 virtual bool SMULL_vec(bool Q, Imm<2> size, Vec Vm, Vec Vn, Vec Vd) {
2024 return false;
2025 }
2026 virtual bool PMULL(bool Q, Imm<2> size, Vec Vm, Vec Vn, Vec Vd) {
2027 return false;
2028 }
2029 virtual bool UADDL(bool Q, Imm<2> size, Vec Vm, Vec Vn, Vec Vd) {
2030 return false;
2031 }
2032 virtual bool UADDW(bool Q, Imm<2> size, Vec Vm, Vec Vn, Vec Vd) {
2033 return false;
2034 }
2035 virtual bool USUBL(bool Q, Imm<2> size, Vec Vm, Vec Vn, Vec Vd) {
2036 return false;
2037 }
2038 virtual bool USUBW(bool Q, Imm<2> size, Vec Vm, Vec Vn, Vec Vd) {
2039 return false;
2040 }
2041 virtual bool RADDHN(bool Q, Imm<2> size, Vec Vm, Vec Vn, Vec Vd) {
2042 return false;
2043 }
2044 virtual bool UABAL(bool Q, Imm<2> size, Vec Vm, Vec Vn, Vec Vd) {
2045 return false;
2046 }
2047 virtual bool RSUBHN(bool Q, Imm<2> size, Vec Vm, Vec Vn, Vec Vd) {
2048 return false;
2049 }
2050 virtual bool UABDL(bool Q, Imm<2> size, Vec Vm, Vec Vn, Vec Vd) {
2051 return false;
2052 }
2053 virtual bool UMLAL_vec(bool Q, Imm<2> size, Vec Vm, Vec Vn, Vec Vd) {
2054 return false;
2055 }
2056 virtual bool UMLSL_vec(bool Q, Imm<2> size, Vec Vm, Vec Vn, Vec Vd) {
2057 return false;
2058 }
2059 virtual bool UMULL_vec(bool Q, Imm<2> size, Vec Vm, Vec Vn, Vec Vd) {
2060 return false;
2061 }
2062 virtual bool SQDMLAL_vec_2(bool Q, Imm<2> size, Vec Vm, Vec Vn, Vec Vd) {
2063 return false;
2064 }
2065 virtual bool SQDMLSL_vec_2(bool Q, Imm<2> size, Vec Vm, Vec Vn, Vec Vd) {
2066 return false;
2067 }
2068 virtual bool SQDMULL_vec_2(bool Q, Imm<2> size, Vec Vm, Vec Vn, Vec Vd) {
2069 return false;
2070 }
2071
2072 // Data Processing - FP and SIMD - SIMD three same
2073 virtual bool SHADD(bool Q, Imm<2> size, Vec Vm, Vec Vn, Vec Vd) {
2074 return false;
2075 }
2076 virtual bool SRHADD(bool Q, Imm<2> size, Vec Vm, Vec Vn, Vec Vd) {
2077 return false;
2078 }
2079 virtual bool SHSUB(bool Q, Imm<2> size, Vec Vm, Vec Vn, Vec Vd) {
2080 return false;
2081 }
2082 virtual bool SMAX(bool Q, Imm<2> size, Vec Vm, Vec Vn, Vec Vd) {
2083 return false;
2084 }
2085 virtual bool SMIN(bool Q, Imm<2> size, Vec Vm, Vec Vn, Vec Vd) {
2086 return false;
2087 }
2088 virtual bool SABD(bool Q, Imm<2> size, Vec Vm, Vec Vn, Vec Vd) {
2089 return false;
2090 }
2091 virtual bool SABA(bool Q, Imm<2> size, Vec Vm, Vec Vn, Vec Vd) {
2092 return false;
2093 }
2094 virtual bool MLA_vec(bool Q, Imm<2> size, Vec Vm, Vec Vn, Vec Vd) {
2095 return false;
2096 }
2097 virtual bool MUL_vec(bool Q, Imm<2> size, Vec Vm, Vec Vn, Vec Vd) {
2098 return false;
2099 }
2100 virtual bool SMAXP(bool Q, Imm<2> size, Vec Vm, Vec Vn, Vec Vd) {
2101 return false;
2102 }
2103 virtual bool SMINP(bool Q, Imm<2> size, Vec Vm, Vec Vn, Vec Vd) {
2104 return false;
2105 }
2106 virtual bool ADDP_vec(bool Q, Imm<2> size, Vec Vm, Vec Vn, Vec Vd) {
2107 return false;
2108 }
2109 virtual bool FMLAL_vec_1(bool Q, bool sz, Vec Vm, Vec Vn, Vec Vd) {
2110 return false;
2111 }
2112 virtual bool FMLAL_vec_2(bool Q, bool sz, Vec Vm, Vec Vn, Vec Vd) {
2113 return false;
2114 }
2115 virtual bool AND_asimd(bool Q, Vec Vm, Vec Vn, Vec Vd) {
2116 return false;
2117 }
2118 virtual bool BIC_asimd_reg(bool Q, Vec Vm, Vec Vn, Vec Vd) {
2119 return false;
2120 }
2121 virtual bool FMLSL_vec_1(bool Q, bool sz, Vec Vm, Vec Vn, Vec Vd) {
2122 return false;
2123 }
2124 virtual bool FMLSL_vec_2(bool Q, bool sz, Vec Vm, Vec Vn, Vec Vd) {
2125 return false;
2126 }
2127 virtual bool ORR_asimd_reg(bool Q, Vec Vm, Vec Vn, Vec Vd) {
2128 return false;
2129 }
2130 virtual bool ORN_asimd(bool Q, Vec Vm, Vec Vn, Vec Vd) {
2131 return false;
2132 }
2133 virtual bool UHADD(bool Q, Imm<2> size, Vec Vm, Vec Vn, Vec Vd) {
2134 return false;
2135 }
2136 virtual bool URHADD(bool Q, Imm<2> size, Vec Vm, Vec Vn, Vec Vd) {
2137 return false;
2138 }
2139 virtual bool UHSUB(bool Q, Imm<2> size, Vec Vm, Vec Vn, Vec Vd) {
2140 return false;
2141 }
2142 virtual bool UMAX(bool Q, Imm<2> size, Vec Vm, Vec Vn, Vec Vd) {
2143 return false;
2144 }
2145 virtual bool UMIN(bool Q, Imm<2> size, Vec Vm, Vec Vn, Vec Vd) {
2146 return false;
2147 }
2148 virtual bool UABD(bool Q, Imm<2> size, Vec Vm, Vec Vn, Vec Vd) {
2149 return false;
2150 }
2151 virtual bool UABA(bool Q, Imm<2> size, Vec Vm, Vec Vn, Vec Vd) {
2152 return false;
2153 }
2154 virtual bool MLS_vec(bool Q, Imm<2> size, Vec Vm, Vec Vn, Vec Vd) {
2155 return false;
2156 }
2157 virtual bool PMUL(bool Q, Imm<2> size, Vec Vm, Vec Vn, Vec Vd) {
2158 return false;
2159 }
2160 virtual bool UMAXP(bool Q, Imm<2> size, Vec Vm, Vec Vn, Vec Vd) {
2161 return false;
2162 }
2163 virtual bool UMINP(bool Q, Imm<2> size, Vec Vm, Vec Vn, Vec Vd) {
2164 return false;
2165 }
2166 virtual bool EOR_asimd(bool Q, Vec Vm, Vec Vn, Vec Vd) {
2167 return false;
2168 }
2169 virtual bool BSL(bool Q, Vec Vm, Vec Vn, Vec Vd) {
2170 return false;
2171 }
2172 virtual bool BIT(bool Q, Vec Vm, Vec Vn, Vec Vd) {
2173 return false;
2174 }
2175 virtual bool BIF(bool Q, Vec Vm, Vec Vn, Vec Vd) {
2176 return false;
2177 }
2178 virtual bool FMAXNM_2(bool Q, bool sz, Vec Vm, Vec Vn, Vec Vd) {
2179 return false;
2180 }
2181 virtual bool FMLA_vec_2(bool Q, bool sz, Vec Vm, Vec Vn, Vec Vd) {
2182 return false;
2183 }
2184 virtual bool FADD_2(bool Q, bool sz, Vec Vm, Vec Vn, Vec Vd) {
2185 return false;
2186 }
2187 virtual bool FMAX_2(bool Q, bool sz, Vec Vm, Vec Vn, Vec Vd) {
2188 return false;
2189 }
2190 virtual bool FMINNM_2(bool Q, bool sz, Vec Vm, Vec Vn, Vec Vd) {
2191 return false;
2192 }
2193 virtual bool FMLS_vec_2(bool Q, bool sz, Vec Vm, Vec Vn, Vec Vd) {
2194 return false;
2195 }
2196 virtual bool FSUB_2(bool Q, bool sz, Vec Vm, Vec Vn, Vec Vd) {
2197 return false;
2198 }
2199 virtual bool FMIN_2(bool Q, bool sz, Vec Vm, Vec Vn, Vec Vd) {
2200 return false;
2201 }
2202 virtual bool FMAXNMP_vec_2(bool Q, bool sz, Vec Vm, Vec Vn, Vec Vd) {
2203 return false;
2204 }
2205 virtual bool FADDP_vec_2(bool Q, bool sz, Vec Vm, Vec Vn, Vec Vd) {
2206 return false;
2207 }
2208 virtual bool FMUL_vec_2(bool Q, bool sz, Vec Vm, Vec Vn, Vec Vd) {
2209 return false;
2210 }
2211 virtual bool FMAXP_vec_2(bool Q, bool sz, Vec Vm, Vec Vn, Vec Vd) {
2212 return false;
2213 }
2214 virtual bool FDIV_2(bool Q, bool sz, Vec Vm, Vec Vn, Vec Vd) {
2215 return false;
2216 }
2217 virtual bool FMINNMP_vec_2(bool Q, bool sz, Vec Vm, Vec Vn, Vec Vd) {
2218 return false;
2219 }
2220 virtual bool FMINP_vec_2(bool Q, bool sz, Vec Vm, Vec Vn, Vec Vd) {
2221 return false;
2222 }
2223 virtual bool FMULX_vec_4(bool Q, bool sz, Vec Vm, Vec Vn, Vec Vd) {
2224 return false;
2225 }
2226 virtual bool FCMEQ_reg_4(bool Q, bool sz, Vec Vm, Vec Vn, Vec Vd) {
2227 return false;
2228 }
2229 virtual bool FRECPS_4(bool Q, bool sz, Vec Vm, Vec Vn, Vec Vd) {
2230 return false;
2231 }
2232 virtual bool FRSQRTS_4(bool Q, bool sz, Vec Vm, Vec Vn, Vec Vd) {
2233 return false;
2234 }
2235 virtual bool FCMGE_reg_4(bool Q, bool sz, Vec Vm, Vec Vn, Vec Vd) {
2236 return false;
2237 }
2238 virtual bool FACGE_4(bool Q, bool sz, Vec Vm, Vec Vn, Vec Vd) {
2239 return false;
2240 }
2241 virtual bool FABD_4(bool Q, bool sz, Vec Vm, Vec Vn, Vec Vd) {
2242 return false;
2243 }
2244 virtual bool FCMGT_reg_4(bool Q, bool sz, Vec Vm, Vec Vn, Vec Vd) {
2245 return false;
2246 }
2247 virtual bool FACGT_4(bool Q, bool sz, Vec Vm, Vec Vn, Vec Vd) {
2248 return false;
2249 }
2250 virtual bool SQADD_2(bool Q, Imm<2> size, Vec Vm, Vec Vn, Vec Vd) {
2251 return false;
2252 }
2253 virtual bool SQSUB_2(bool Q, Imm<2> size, Vec Vm, Vec Vn, Vec Vd) {
2254 return false;
2255 }
2256 virtual bool CMGT_reg_2(bool Q, Imm<2> size, Vec Vm, Vec Vn, Vec Vd) {
2257 return false;
2258 }
2259 virtual bool CMGE_reg_2(bool Q, Imm<2> size, Vec Vm, Vec Vn, Vec Vd) {
2260 return false;
2261 }
2262 virtual bool SSHL_2(bool Q, Imm<2> size, Vec Vm, Vec Vn, Vec Vd) {
2263 return false;
2264 }
2265 virtual bool SQSHL_reg_2(bool Q, Imm<2> size, Vec Vm, Vec Vn, Vec Vd) {
2266 return false;
2267 }
2268 virtual bool SRSHL_2(bool Q, Imm<2> size, Vec Vm, Vec Vn, Vec Vd) {
2269 return false;
2270 }
2271 virtual bool SQRSHL_2(bool Q, Imm<2> size, Vec Vm, Vec Vn, Vec Vd) {
2272 return false;
2273 }
2274 virtual bool ADD_vector(bool Q, Imm<2> size, Vec Vm, Vec Vn, Vec Vd) {
2275 return false;
2276 }
2277 virtual bool CMTST_2(bool Q, Imm<2> size, Vec Vm, Vec Vn, Vec Vd) {
2278 return false;
2279 }
2280 virtual bool SQDMULH_vec_2(bool Q, Imm<2> size, Vec Vm, Vec Vn, Vec Vd) {
2281 return false;
2282 }
2283 virtual bool UQADD_2(bool Q, Imm<2> size, Vec Vm, Vec Vn, Vec Vd) {
2284 return false;
2285 }
2286 virtual bool UQSUB_2(bool Q, Imm<2> size, Vec Vm, Vec Vn, Vec Vd) {
2287 return false;
2288 }
2289 virtual bool CMHI_2(bool Q, Imm<2> size, Vec Vm, Vec Vn, Vec Vd) {
2290 return false;
2291 }
2292 virtual bool CMHS_2(bool Q, Imm<2> size, Vec Vm, Vec Vn, Vec Vd) {
2293 return false;
2294 }
2295 virtual bool USHL_2(bool Q, Imm<2> size, Vec Vm, Vec Vn, Vec Vd) {
2296 return false;
2297 }
2298 virtual bool UQSHL_reg_2(bool Q, Imm<2> size, Vec Vm, Vec Vn, Vec Vd) {
2299 return false;
2300 }
2301 virtual bool URSHL_2(bool Q, Imm<2> size, Vec Vm, Vec Vn, Vec Vd) {
2302 return false;
2303 }
2304 virtual bool UQRSHL_2(bool Q, Imm<2> size, Vec Vm, Vec Vn, Vec Vd) {
2305 return false;
2306 }
2307 virtual bool SUB_2(bool Q, Imm<2> size, Vec Vm, Vec Vn, Vec Vd) {
2308 return false;
2309 }
2310 virtual bool CMEQ_reg_2(bool Q, Imm<2> size, Vec Vm, Vec Vn, Vec Vd) {
2311 return false;
2312 }
2313 virtual bool SQRDMULH_vec_2(bool Q, Imm<2> size, Vec Vm, Vec Vn, Vec Vd) {
2314 return false;
2315 }
2316
2317 // Data Processing - FP and SIMD - SIMD modified immediate
2318 virtual bool MOVI(bool Q, bool op, Imm<1> a, Imm<1> b, Imm<1> c, Imm<4> cmode, Imm<1> d,
2319 Imm<1> e, Imm<1> f, Imm<1> g, Imm<1> h, Vec Vd) {
2320 return false;
2321 }
2322 virtual bool FMOV_2(bool Q, bool op, Imm<1> a, Imm<1> b, Imm<1> c, Imm<1> d, Imm<1> e, Imm<1> f,
2323 Imm<1> g, Imm<1> h, Vec Vd) {
2324 return false;
2325 }
2326 virtual bool FMOV_3(bool Q, Imm<1> a, Imm<1> b, Imm<1> c, Imm<1> d, Imm<1> e, Imm<1> f,
2327 Imm<1> g, Imm<1> h, Vec Vd) {
2328 return false;
2329 }
2330
2331 // Data Processing - FP and SIMD - SIMD Shift by immediate
2332 virtual bool SSHR_2(bool Q, Imm<4> immh, Imm<3> immb, Vec Vn, Vec Vd) {
2333 return false;
2334 }
2335 virtual bool SSRA_2(bool Q, Imm<4> immh, Imm<3> immb, Vec Vn, Vec Vd) {
2336 return false;
2337 }
2338 virtual bool SRSHR_2(bool Q, Imm<4> immh, Imm<3> immb, Vec Vn, Vec Vd) {
2339 return false;
2340 }
2341 virtual bool SRSRA_2(bool Q, Imm<4> immh, Imm<3> immb, Vec Vn, Vec Vd) {
2342 return false;
2343 }
2344 virtual bool SHL_2(bool Q, Imm<4> immh, Imm<3> immb, Vec Vn, Vec Vd) {
2345 return false;
2346 }
2347 virtual bool SQSHL_imm_2(bool Q, Imm<4> immh, Imm<3> immb, Vec Vn, Vec Vd) {
2348 return false;
2349 }
2350 virtual bool SHRN(bool Q, Imm<4> immh, Imm<3> immb, Vec Vn, Vec Vd) {
2351 return false;
2352 }
2353 virtual bool RSHRN(bool Q, Imm<4> immh, Imm<3> immb, Vec Vn, Vec Vd) {
2354 return false;
2355 }
2356 virtual bool SQSHRN_2(bool Q, Imm<4> immh, Imm<3> immb, Vec Vn, Vec Vd) {
2357 return false;
2358 }
2359 virtual bool SQRSHRN_2(bool Q, Imm<4> immh, Imm<3> immb, Vec Vn, Vec Vd) {
2360 return false;
2361 }
2362 virtual bool SSHLL(bool Q, Imm<4> immh, Imm<3> immb, Vec Vn, Vec Vd) {
2363 return false;
2364 }
2365 virtual bool SCVTF_fix_2(bool Q, Imm<4> immh, Imm<3> immb, Vec Vn, Vec Vd) {
2366 return false;
2367 }
2368 virtual bool FCVTZS_fix_2(bool Q, Imm<4> immh, Imm<3> immb, Vec Vn, Vec Vd) {
2369 return false;
2370 }
2371 virtual bool USHR_2(bool Q, Imm<4> immh, Imm<3> immb, Vec Vn, Vec Vd) {
2372 return false;
2373 }
2374 virtual bool USRA_2(bool Q, Imm<4> immh, Imm<3> immb, Vec Vn, Vec Vd) {
2375 return false;
2376 }
2377 virtual bool URSHR_2(bool Q, Imm<4> immh, Imm<3> immb, Vec Vn, Vec Vd) {
2378 return false;
2379 }
2380 virtual bool URSRA_2(bool Q, Imm<4> immh, Imm<3> immb, Vec Vn, Vec Vd) {
2381 return false;
2382 }
2383 virtual bool SRI_2(bool Q, Imm<4> immh, Imm<3> immb, Vec Vn, Vec Vd) {
2384 return false;
2385 }
2386 virtual bool SLI_2(bool Q, Imm<4> immh, Imm<3> immb, Vec Vn, Vec Vd) {
2387 return false;
2388 }
2389 virtual bool SQSHLU_2(bool Q, Imm<4> immh, Imm<3> immb, Vec Vn, Vec Vd) {
2390 return false;
2391 }
2392 virtual bool UQSHL_imm_2(bool Q, Imm<4> immh, Imm<3> immb, Vec Vn, Vec Vd) {
2393 return false;
2394 }
2395 virtual bool SQSHRUN_2(bool Q, Imm<4> immh, Imm<3> immb, Vec Vn, Vec Vd) {
2396 return false;
2397 }
2398 virtual bool SQRSHRUN_2(bool Q, Imm<4> immh, Imm<3> immb, Vec Vn, Vec Vd) {
2399 return false;
2400 }
2401 virtual bool UQSHRN_2(bool Q, Imm<4> immh, Imm<3> immb, Vec Vn, Vec Vd) {
2402 return false;
2403 }
2404 virtual bool UQRSHRN_2(bool Q, Imm<4> immh, Imm<3> immb, Vec Vn, Vec Vd) {
2405 return false;
2406 }
2407 virtual bool USHLL(bool Q, Imm<4> immh, Imm<3> immb, Vec Vn, Vec Vd) {
2408 return false;
2409 }
2410 virtual bool UCVTF_fix_2(bool Q, Imm<4> immh, Imm<3> immb, Vec Vn, Vec Vd) {
2411 return false;
2412 }
2413 virtual bool FCVTZU_fix_2(bool Q, Imm<4> immh, Imm<3> immb, Vec Vn, Vec Vd) {
2414 return false;
2415 }
2416
2417 // Data Processing - FP and SIMD - SIMD vector x indexed element
2418 virtual bool SMLAL_elt(bool Q, Imm<2> size, Imm<1> L, Imm<1> M, Imm<4> Vmlo, Imm<1> H, Vec Vn,
2419 Vec Vd) {
2420 return false;
2421 }
2422 virtual bool SQDMLAL_elt_2(bool Q, Imm<2> size, Imm<1> L, Imm<1> M, Imm<4> Vmlo, Imm<1> H,
2423 Vec Vn, Vec Vd) {
2424 return false;
2425 }
2426 virtual bool SMLSL_elt(bool Q, Imm<2> size, Imm<1> L, Imm<1> M, Imm<4> Vmlo, Imm<1> H, Vec Vn,
2427 Vec Vd) {
2428 return false;
2429 }
2430 virtual bool SQDMLSL_elt_2(bool Q, Imm<2> size, Imm<1> L, Imm<1> M, Imm<4> Vmlo, Imm<1> H,
2431 Vec Vn, Vec Vd) {
2432 return false;
2433 }
2434 virtual bool MUL_elt(bool Q, Imm<2> size, Imm<1> L, Imm<1> M, Imm<4> Vmlo, Imm<1> H, Vec Vn,
2435 Vec Vd) {
2436 return false;
2437 }
2438 virtual bool SMULL_elt(bool Q, Imm<2> size, Imm<1> L, Imm<1> M, Imm<4> Vm, Imm<1> H, Vec Vn,
2439 Vec Vd) {
2440 return false;
2441 }
2442 virtual bool SQDMULL_elt_2(bool Q, Imm<2> size, Imm<1> L, Imm<1> M, Imm<4> Vmlo, Imm<1> H,
2443 Vec Vn, Vec Vd) {
2444 return false;
2445 }
2446 virtual bool SQDMULH_elt_2(bool Q, Imm<2> size, Imm<1> L, Imm<1> M, Imm<4> Vmlo, Imm<1> H,
2447 Vec Vn, Vec Vd) {
2448 return false;
2449 }
2450 virtual bool SQRDMULH_elt_2(bool Q, Imm<2> size, Imm<1> L, Imm<1> M, Imm<4> Vmlo, Imm<1> H,
2451 Vec Vn, Vec Vd) {
2452 return false;
2453 }
2454 virtual bool SDOT_elt(bool Q, Imm<2> size, Imm<1> L, Imm<1> M, Imm<4> Vmlo, Imm<1> H, Vec Vn,
2455 Vec Vd) {
2456 return false;
2457 }
2458 virtual bool FMLA_elt_3(bool Q, Imm<1> L, Imm<1> M, Imm<4> Vmlo, Imm<1> H, Vec Vn, Vec Vd) {
2459 return false;
2460 }
2461 virtual bool FMLA_elt_4(bool Q, bool sz, Imm<1> L, Imm<1> M, Imm<4> Vmlo, Imm<1> H, Vec Vn,
2462 Vec Vd) {
2463 return false;
2464 }
2465 virtual bool FMLS_elt_3(bool Q, Imm<1> L, Imm<1> M, Imm<4> Vmlo, Imm<1> H, Vec Vn, Vec Vd) {
2466 return false;
2467 }
2468 virtual bool FMLS_elt_4(bool Q, bool sz, Imm<1> L, Imm<1> M, Imm<4> Vmlo, Imm<1> H, Vec Vn,
2469 Vec Vd) {
2470 return false;
2471 }
2472 virtual bool FMUL_elt_3(bool Q, Imm<1> L, Imm<1> M, Imm<4> Vmlo, Imm<1> H, Vec Vn, Vec Vd) {
2473 return false;
2474 }
2475 virtual bool FMUL_elt_4(bool Q, bool sz, Imm<1> L, Imm<1> M, Imm<4> Vmlo, Imm<1> H, Vec Vn,
2476 Vec Vd) {
2477 return false;
2478 }
2479 virtual bool FMLAL_elt_1(bool Q, bool sz, Imm<1> L, Imm<1> M, Imm<4> Vmlo, Imm<1> H, Vec Vn,
2480 Vec Vd) {
2481 return false;
2482 }
2483 virtual bool FMLAL_elt_2(bool Q, bool sz, Imm<1> L, Imm<1> M, Imm<4> Vmlo, Imm<1> H, Vec Vn,
2484 Vec Vd) {
2485 return false;
2486 }
2487 virtual bool FMLSL_elt_1(bool Q, bool sz, Imm<1> L, Imm<1> M, Imm<4> Vmlo, Imm<1> H, Vec Vn,
2488 Vec Vd) {
2489 return false;
2490 }
2491 virtual bool FMLSL_elt_2(bool Q, bool sz, Imm<1> L, Imm<1> M, Imm<4> Vmlo, Imm<1> H, Vec Vn,
2492 Vec Vd) {
2493 return false;
2494 }
2495 virtual bool MLA_elt(bool Q, Imm<2> size, Imm<1> L, Imm<1> M, Imm<4> Vmlo, Imm<1> H, Vec Vn,
2496 Vec Vd) {
2497 return false;
2498 }
2499 virtual bool UMLAL_elt(bool Q, Imm<2> size, Imm<1> L, Imm<1> M, Imm<4> Vmlo, Imm<1> H, Vec Vn,
2500 Vec Vd) {
2501 return false;
2502 }
2503 virtual bool MLS_elt(bool Q, Imm<2> size, Imm<1> L, Imm<1> M, Imm<4> Vmlo, Imm<1> H, Vec Vn,
2504 Vec Vd) {
2505 return false;
2506 }
2507 virtual bool UMLSL_elt(bool Q, Imm<2> size, Imm<1> L, Imm<1> M, Imm<4> Vmlo, Imm<1> H, Vec Vn,
2508 Vec Vd) {
2509 return false;
2510 }
2511 virtual bool UMULL_elt(bool Q, Imm<2> size, Imm<1> L, Imm<1> M, Imm<4> Vmlo, Imm<1> H, Vec Vn,
2512 Vec Vd) {
2513 return false;
2514 }
2515 virtual bool SQRDMLAH_elt_2(bool Q, Imm<2> size, Imm<1> L, Imm<1> M, Imm<4> Vmlo, Imm<1> H,
2516 Vec Vn, Vec Vd) {
2517 return false;
2518 }
2519 virtual bool UDOT_elt(bool Q, Imm<2> size, Imm<1> L, Imm<1> M, Imm<4> Vmlo, Imm<1> H, Vec Vn,
2520 Vec Vd) {
2521 return false;
2522 }
2523 virtual bool SQRDMLSH_elt_2(bool Q, Imm<2> size, Imm<1> L, Imm<1> M, Imm<4> Vmlo, Imm<1> H,
2524 Vec Vn, Vec Vd) {
2525 return false;
2526 }
2527 virtual bool FMULX_elt_3(bool Q, Imm<1> L, Imm<1> M, Imm<4> Vmlo, Imm<1> H, Vec Vn, Vec Vd) {
2528 return false;
2529 }
2530 virtual bool FMULX_elt_4(bool Q, bool sz, Imm<1> L, Imm<1> M, Imm<4> Vmlo, Imm<1> H, Vec Vn,
2531 Vec Vd) {
2532 return false;
2533 }
2534 virtual bool FCMLA_elt(bool Q, Imm<2> size, Imm<1> L, Imm<1> M, Imm<4> Vmlo, Imm<2> rot,
2535 Imm<1> H, Vec Vn, Vec Vd) {
2536 return false;
2537 }
2538
2539 // Data Processing - FP and SIMD - Cryptographic three register
2540 virtual bool SM3TT1A(Vec Vm, Imm<2> imm2, Vec Vn, Vec Vd) {
2541 return false;
2542 }
2543 virtual bool SM3TT1B(Vec Vm, Imm<2> imm2, Vec Vn, Vec Vd) {
2544 return false;
2545 }
2546 virtual bool SM3TT2A(Vec Vm, Imm<2> imm2, Vec Vn, Vec Vd) {
2547 return false;
2548 }
2549 virtual bool SM3TT2B(Vec Vm, Imm<2> imm2, Vec Vn, Vec Vd) {
2550 return false;
2551 }
2552
2553 // Data Processing - FP and SIMD - SHA512 three register
2554 virtual bool SHA512H(Vec Vm, Vec Vn, Vec Vd) {
2555 return false;
2556 }
2557 virtual bool SHA512H2(Vec Vm, Vec Vn, Vec Vd) {
2558 return false;
2559 }
2560 virtual bool SHA512SU1(Vec Vm, Vec Vn, Vec Vd) {
2561 return false;
2562 }
2563 virtual bool RAX1(Vec Vm, Vec Vn, Vec Vd) {
2564 return false;
2565 }
2566 virtual bool XAR(Vec Vm, Imm<6> imm6, Vec Vn, Vec Vd) {
2567 return false;
2568 }
2569 virtual bool SM3PARTW1(Vec Vm, Vec Vn, Vec Vd) {
2570 return false;
2571 }
2572 virtual bool SM3PARTW2(Vec Vm, Vec Vn, Vec Vd) {
2573 return false;
2574 }
2575 virtual bool SM4EKEY(Vec Vm, Vec Vn, Vec Vd) {
2576 return false;
2577 }
2578
2579 // Data Processing - FP and SIMD - Cryptographic four register
2580 virtual bool EOR3(Vec Vm, Vec Va, Vec Vn, Vec Vd) {
2581 return false;
2582 }
2583 virtual bool BCAX(Vec Vm, Vec Va, Vec Vn, Vec Vd) {
2584 return false;
2585 }
2586 virtual bool SM3SS1(Vec Vm, Vec Va, Vec Vn, Vec Vd) {
2587 return false;
2588 }
2589
2590 // Data Processing - FP and SIMD - SHA512 two register
2591 virtual bool SHA512SU0(Vec Vn, Vec Vd) {
2592 return false;
2593 }
2594 virtual bool SM4E(Vec Vn, Vec Vd) {
2595 return false;
2596 }
2597
2598 // Data Processing - FP and SIMD - Conversion between floating point and fixed point
2599 virtual bool SCVTF_float_fix(bool sf, Imm<2> type, Imm<6> scale, Reg Rn, Vec Vd) {
2600 return false;
2601 }
2602 virtual bool UCVTF_float_fix(bool sf, Imm<2> type, Imm<6> scale, Reg Rn, Vec Vd) {
2603 return false;
2604 }
2605 virtual bool FCVTZS_float_fix(bool sf, Imm<2> type, Imm<6> scale, Vec Vn, Reg Rd) {
2606 return false;
2607 }
2608 virtual bool FCVTZU_float_fix(bool sf, Imm<2> type, Imm<6> scale, Vec Vn, Reg Rd) {
2609 return false;
2610 }
2611
2612 // Data Processing - FP and SIMD - Conversion between floating point and integer
2613 virtual bool FCVTNS_float(bool sf, Imm<2> type, Vec Vn, Reg Rd) {
2614 return false;
2615 }
2616 virtual bool FCVTNU_float(bool sf, Imm<2> type, Vec Vn, Reg Rd) {
2617 return false;
2618 }
2619 virtual bool SCVTF_float_int(bool sf, Imm<2> type, Reg Rn, Vec Vd) {
2620 return false;
2621 }
2622 virtual bool UCVTF_float_int(bool sf, Imm<2> type, Reg Rn, Vec Vd) {
2623 return false;
2624 }
2625 virtual bool FCVTAS_float(bool sf, Imm<2> type, Vec Vn, Reg Rd) {
2626 return false;
2627 }
2628 virtual bool FCVTAU_float(bool sf, Imm<2> type, Vec Vn, Reg Rd) {
2629 return false;
2630 }
2631 virtual bool FMOV_float_gen(bool sf, Imm<2> type, Imm<1> rmode_0, Imm<1> opc_0, size_t n,
2632 size_t d) {
2633 return false;
2634 }
2635 virtual bool FCVTPS_float(bool sf, Imm<2> type, Vec Vn, Reg Rd) {
2636 return false;
2637 }
2638 virtual bool FCVTPU_float(bool sf, Imm<2> type, Vec Vn, Reg Rd) {
2639 return false;
2640 }
2641 virtual bool FCVTMS_float(bool sf, Imm<2> type, Vec Vn, Reg Rd) {
2642 return false;
2643 }
2644 virtual bool FCVTMU_float(bool sf, Imm<2> type, Vec Vn, Reg Rd) {
2645 return false;
2646 }
2647 virtual bool FCVTZS_float_int(bool sf, Imm<2> type, Vec Vn, Reg Rd) {
2648 return false;
2649 }
2650 virtual bool FCVTZU_float_int(bool sf, Imm<2> type, Vec Vn, Reg Rd) {
2651 return false;
2652 }
2653 virtual bool FJCVTZS(Vec Vn, Reg Rd) {
2654 return false;
2655 }
2656
2657 // Data Processing - FP and SIMD - Floating point data processing
2658 virtual bool FMOV_float(Imm<2> type, Vec Vn, Vec Vd) {
2659 return false;
2660 }
2661 virtual bool FABS_float(Imm<2> type, Vec Vn, Vec Vd) {
2662 return false;
2663 }
2664 virtual bool FNEG_float(Imm<2> type, Vec Vn, Vec Vd) {
2665 return false;
2666 }
2667 virtual bool FSQRT_float(Imm<2> type, Vec Vn, Vec Vd) {
2668 return false;
2669 }
2670 virtual bool FCVT_float(Imm<2> type, Imm<2> opc, Vec Vn, Vec Vd) {
2671 return false;
2672 }
2673 virtual bool FRINTN_float(Imm<2> type, Vec Vn, Vec Vd) {
2674 return false;
2675 }
2676 virtual bool FRINTP_float(Imm<2> type, Vec Vn, Vec Vd) {
2677 return false;
2678 }
2679 virtual bool FRINTM_float(Imm<2> type, Vec Vn, Vec Vd) {
2680 return false;
2681 }
2682 virtual bool FRINTZ_float(Imm<2> type, Vec Vn, Vec Vd) {
2683 return false;
2684 }
2685 virtual bool FRINTA_float(Imm<2> type, Vec Vn, Vec Vd) {
2686 return false;
2687 }
2688 virtual bool FRINTX_float(Imm<2> type, Vec Vn, Vec Vd) {
2689 return false;
2690 }
2691 virtual bool FRINTI_float(Imm<2> type, Vec Vn, Vec Vd) {
2692 return false;
2693 }
2694 virtual bool FRINT32X_float(Imm<2> type, Vec Vn, Vec Vd) {
2695 return false;
2696 }
2697 virtual bool FRINT64X_float(Imm<2> type, Vec Vn, Vec Vd) {
2698 return false;
2699 }
2700 virtual bool FRINT32Z_float(Imm<2> type, Vec Vn, Vec Vd) {
2701 return false;
2702 }
2703 virtual bool FRINT64Z_float(Imm<2> type, Vec Vn, Vec Vd) {
2704 return false;
2705 }
2706
2707 // Data Processing - FP and SIMD - Floating point compare
2708 virtual bool FCMP_float(Imm<2> type, Vec Vm, Vec Vn, bool cmp_with_zero) {
2709 return false;
2710 }
2711 virtual bool FCMPE_float(Imm<2> type, Vec Vm, Vec Vn, bool cmp_with_zero) {
2712 return false;
2713 }
2714
2715 // Data Processing - FP and SIMD - Floating point immediate
2716 virtual bool FMOV_float_imm(Imm<2> type, Imm<8> imm8, Vec Vd) {
2717 return false;
2718 }
2719
2720 // Data Processing - FP and SIMD - Floating point conditional compare
2721 virtual bool FCCMP_float(Imm<2> type, Vec Vm, Cond cond, Vec Vn, Imm<4> nzcv) {
2722 return false;
2723 }
2724 virtual bool FCCMPE_float(Imm<2> type, Vec Vm, Cond cond, Vec Vn, Imm<4> nzcv) {
2725 return false;
2726 }
2727
2728 // Data Processing - FP and SIMD - Floating point data processing two register
2729 virtual bool FMUL_float(Imm<2> type, Vec Vm, Vec Vn, Vec Vd) {
2730 return false;
2731 }
2732 virtual bool FDIV_float(Imm<2> type, Vec Vm, Vec Vn, Vec Vd) {
2733 return false;
2734 }
2735 virtual bool FADD_float(Imm<2> type, Vec Vm, Vec Vn, Vec Vd) {
2736 return false;
2737 }
2738 virtual bool FSUB_float(Imm<2> type, Vec Vm, Vec Vn, Vec Vd) {
2739 return false;
2740 }
2741 virtual bool FMAX_float(Imm<2> type, Vec Vm, Vec Vn, Vec Vd) {
2742 return false;
2743 }
2744 virtual bool FMIN_float(Imm<2> type, Vec Vm, Vec Vn, Vec Vd) {
2745 return false;
2746 }
2747 virtual bool FMAXNM_float(Imm<2> type, Vec Vm, Vec Vn, Vec Vd) {
2748 return false;
2749 }
2750 virtual bool FMINNM_float(Imm<2> type, Vec Vm, Vec Vn, Vec Vd) {
2751 return false;
2752 }
2753 virtual bool FNMUL_float(Imm<2> type, Vec Vm, Vec Vn, Vec Vd) {
2754 return false;
2755 }
2756
2757 // Data Processing - FP and SIMD - Floating point conditional select
2758 virtual bool FCSEL_float(Imm<2> type, Vec Vm, Cond cond, Vec Vn, Vec Vd) {
2759 return false;
2760 }
2761
2762 // Data Processing - FP and SIMD - Floating point data processing three register
2763 virtual bool FMADD_float(Imm<2> type, Vec Vm, Vec Va, Vec Vn, Vec Vd) {
2764 return false;
2765 }
2766 virtual bool FMSUB_float(Imm<2> type, Vec Vm, Vec Va, Vec Vn, Vec Vd) {
2767 return false;
2768 }
2769 virtual bool FNMADD_float(Imm<2> type, Vec Vm, Vec Va, Vec Vn, Vec Vd) {
2770 return false;
2771 }
2772 virtual bool FNMSUB_float(Imm<2> type, Vec Vm, Vec Va, Vec Vn, Vec Vd) {
2773 return false;
2774 }
2775};
2776
2777} // namespace Core
diff --git a/src/core/file_sys/vfs.cpp b/src/core/file_sys/vfs.cpp
index 639842401..b7105c8ff 100644
--- a/src/core/file_sys/vfs.cpp
+++ b/src/core/file_sys/vfs.cpp
@@ -201,8 +201,6 @@ std::string VfsFile::GetFullPath() const {
201 201
202VirtualFile VfsDirectory::GetFileRelative(std::string_view path) const { 202VirtualFile VfsDirectory::GetFileRelative(std::string_view path) const {
203 auto vec = Common::FS::SplitPathComponents(path); 203 auto vec = Common::FS::SplitPathComponents(path);
204 vec.erase(std::remove_if(vec.begin(), vec.end(), [](const auto& str) { return str.empty(); }),
205 vec.end());
206 if (vec.empty()) { 204 if (vec.empty()) {
207 return nullptr; 205 return nullptr;
208 } 206 }
@@ -237,8 +235,6 @@ VirtualFile VfsDirectory::GetFileAbsolute(std::string_view path) const {
237 235
238VirtualDir VfsDirectory::GetDirectoryRelative(std::string_view path) const { 236VirtualDir VfsDirectory::GetDirectoryRelative(std::string_view path) const {
239 auto vec = Common::FS::SplitPathComponents(path); 237 auto vec = Common::FS::SplitPathComponents(path);
240 vec.erase(std::remove_if(vec.begin(), vec.end(), [](const auto& str) { return str.empty(); }),
241 vec.end());
242 if (vec.empty()) { 238 if (vec.empty()) {
243 // TODO(DarkLordZach): Return this directory if path is '/' or similar. Can't currently 239 // TODO(DarkLordZach): Return this directory if path is '/' or similar. Can't currently
244 // because of const-ness 240 // because of const-ness
@@ -303,8 +299,6 @@ std::size_t VfsDirectory::GetSize() const {
303 299
304VirtualFile VfsDirectory::CreateFileRelative(std::string_view path) { 300VirtualFile VfsDirectory::CreateFileRelative(std::string_view path) {
305 auto vec = Common::FS::SplitPathComponents(path); 301 auto vec = Common::FS::SplitPathComponents(path);
306 vec.erase(std::remove_if(vec.begin(), vec.end(), [](const auto& str) { return str.empty(); }),
307 vec.end());
308 if (vec.empty()) { 302 if (vec.empty()) {
309 return nullptr; 303 return nullptr;
310 } 304 }
@@ -334,8 +328,6 @@ VirtualFile VfsDirectory::CreateFileAbsolute(std::string_view path) {
334 328
335VirtualDir VfsDirectory::CreateDirectoryRelative(std::string_view path) { 329VirtualDir VfsDirectory::CreateDirectoryRelative(std::string_view path) {
336 auto vec = Common::FS::SplitPathComponents(path); 330 auto vec = Common::FS::SplitPathComponents(path);
337 vec.erase(std::remove_if(vec.begin(), vec.end(), [](const auto& str) { return str.empty(); }),
338 vec.end());
339 if (vec.empty()) { 331 if (vec.empty()) {
340 return nullptr; 332 return nullptr;
341 } 333 }
diff --git a/src/core/file_sys/vfs_real.cpp b/src/core/file_sys/vfs_real.cpp
index 1c706e4d8..cd9b79786 100644
--- a/src/core/file_sys/vfs_real.cpp
+++ b/src/core/file_sys/vfs_real.cpp
@@ -268,7 +268,7 @@ void RealVfsFilesystem::RemoveReferenceFromListLocked(FileReference& reference)
268RealVfsFile::RealVfsFile(RealVfsFilesystem& base_, std::unique_ptr<FileReference> reference_, 268RealVfsFile::RealVfsFile(RealVfsFilesystem& base_, std::unique_ptr<FileReference> reference_,
269 const std::string& path_, Mode perms_, std::optional<u64> size_) 269 const std::string& path_, Mode perms_, std::optional<u64> size_)
270 : base(base_), reference(std::move(reference_)), path(path_), 270 : base(base_), reference(std::move(reference_)), path(path_),
271 parent_path(FS::GetParentPath(path_)), path_components(FS::SplitPathComponents(path_)), 271 parent_path(FS::GetParentPath(path_)), path_components(FS::SplitPathComponentsCopy(path_)),
272 size(size_), perms(perms_) {} 272 size(size_), perms(perms_) {}
273 273
274RealVfsFile::~RealVfsFile() { 274RealVfsFile::~RealVfsFile() {
@@ -276,7 +276,7 @@ RealVfsFile::~RealVfsFile() {
276} 276}
277 277
278std::string RealVfsFile::GetName() const { 278std::string RealVfsFile::GetName() const {
279 return path_components.back(); 279 return path_components.empty() ? "" : std::string(path_components.back());
280} 280}
281 281
282std::size_t RealVfsFile::GetSize() const { 282std::size_t RealVfsFile::GetSize() const {
@@ -375,7 +375,7 @@ std::vector<VirtualDir> RealVfsDirectory::IterateEntries<RealVfsDirectory, VfsDi
375 375
376RealVfsDirectory::RealVfsDirectory(RealVfsFilesystem& base_, const std::string& path_, Mode perms_) 376RealVfsDirectory::RealVfsDirectory(RealVfsFilesystem& base_, const std::string& path_, Mode perms_)
377 : base(base_), path(FS::RemoveTrailingSlash(path_)), parent_path(FS::GetParentPath(path)), 377 : base(base_), path(FS::RemoveTrailingSlash(path_)), parent_path(FS::GetParentPath(path)),
378 path_components(FS::SplitPathComponents(path)), perms(perms_) { 378 path_components(FS::SplitPathComponentsCopy(path)), perms(perms_) {
379 if (!FS::Exists(path) && True(perms & Mode::Write)) { 379 if (!FS::Exists(path) && True(perms & Mode::Write)) {
380 void(FS::CreateDirs(path)); 380 void(FS::CreateDirs(path));
381 } 381 }
@@ -464,7 +464,7 @@ bool RealVfsDirectory::IsReadable() const {
464} 464}
465 465
466std::string RealVfsDirectory::GetName() const { 466std::string RealVfsDirectory::GetName() const {
467 return path_components.back(); 467 return path_components.empty() ? "" : std::string(path_components.back());
468} 468}
469 469
470VirtualDir RealVfsDirectory::GetParentDirectory() const { 470VirtualDir RealVfsDirectory::GetParentDirectory() const {
diff --git a/src/core/hid/input_interpreter.cpp b/src/core/hid/input_interpreter.cpp
index a6bdd28f2..072f38a68 100644
--- a/src/core/hid/input_interpreter.cpp
+++ b/src/core/hid/input_interpreter.cpp
@@ -20,6 +20,9 @@ InputInterpreter::InputInterpreter(Core::System& system)
20InputInterpreter::~InputInterpreter() = default; 20InputInterpreter::~InputInterpreter() = default;
21 21
22void InputInterpreter::PollInput() { 22void InputInterpreter::PollInput() {
23 if (npad == nullptr) {
24 return;
25 }
23 const auto button_state = npad->GetAndResetPressState(); 26 const auto button_state = npad->GetAndResetPressState();
24 27
25 previous_index = current_index; 28 previous_index = current_index;
diff --git a/src/core/hle/kernel/k_memory_manager.cpp b/src/core/hle/kernel/k_memory_manager.cpp
index 0a973ec8c..d6bd27296 100644
--- a/src/core/hle/kernel/k_memory_manager.cpp
+++ b/src/core/hle/kernel/k_memory_manager.cpp
@@ -421,8 +421,9 @@ Result KMemoryManager::AllocateForProcess(KPageGroup* out, size_t num_pages, u32
421 } else { 421 } else {
422 // Set all the allocated memory. 422 // Set all the allocated memory.
423 for (const auto& block : *out) { 423 for (const auto& block : *out) {
424 std::memset(m_system.DeviceMemory().GetPointer<void>(block.GetAddress()), fill_pattern, 424 m_system.DeviceMemory().buffer.ClearBackingRegion(GetInteger(block.GetAddress()) -
425 block.GetSize()); 425 Core::DramMemoryMap::Base,
426 block.GetSize(), fill_pattern);
426 } 427 }
427 } 428 }
428 429
diff --git a/src/core/hle/kernel/k_page_table_base.cpp b/src/core/hle/kernel/k_page_table_base.cpp
index 4c416d809..423289145 100644
--- a/src/core/hle/kernel/k_page_table_base.cpp
+++ b/src/core/hle/kernel/k_page_table_base.cpp
@@ -81,6 +81,11 @@ void InvalidateInstructionCache(KernelCore& kernel, AddressType addr, u64 size)
81 } 81 }
82} 82}
83 83
84void ClearBackingRegion(Core::System& system, KPhysicalAddress addr, u64 size, u32 fill_value) {
85 system.DeviceMemory().buffer.ClearBackingRegion(GetInteger(addr) - Core::DramMemoryMap::Base,
86 size, fill_value);
87}
88
84template <typename AddressType> 89template <typename AddressType>
85Result InvalidateDataCache(AddressType addr, u64 size) { 90Result InvalidateDataCache(AddressType addr, u64 size) {
86 R_SUCCEED(); 91 R_SUCCEED();
@@ -1363,8 +1368,7 @@ Result KPageTableBase::MapInsecureMemory(KProcessAddress address, size_t size) {
1363 1368
1364 // Clear all the newly allocated pages. 1369 // Clear all the newly allocated pages.
1365 for (const auto& it : pg) { 1370 for (const auto& it : pg) {
1366 std::memset(GetHeapVirtualPointer(m_kernel, it.GetAddress()), 1371 ClearBackingRegion(m_system, it.GetAddress(), it.GetSize(), m_heap_fill_value);
1367 static_cast<u32>(m_heap_fill_value), it.GetSize());
1368 } 1372 }
1369 1373
1370 // Lock the table. 1374 // Lock the table.
@@ -1570,8 +1574,7 @@ Result KPageTableBase::AllocateAndMapPagesImpl(PageLinkedList* page_list, KProce
1570 1574
1571 // Clear all pages. 1575 // Clear all pages.
1572 for (const auto& it : pg) { 1576 for (const auto& it : pg) {
1573 std::memset(GetHeapVirtualPointer(m_kernel, it.GetAddress()), 1577 ClearBackingRegion(m_system, it.GetAddress(), it.GetSize(), m_heap_fill_value);
1574 static_cast<u32>(m_heap_fill_value), it.GetSize());
1575 } 1578 }
1576 1579
1577 // Map the pages. 1580 // Map the pages.
@@ -2159,8 +2162,7 @@ Result KPageTableBase::SetHeapSize(KProcessAddress* out, size_t size) {
2159 2162
2160 // Clear all the newly allocated pages. 2163 // Clear all the newly allocated pages.
2161 for (const auto& it : pg) { 2164 for (const auto& it : pg) {
2162 std::memset(GetHeapVirtualPointer(m_kernel, it.GetAddress()), m_heap_fill_value, 2165 ClearBackingRegion(m_system, it.GetAddress(), it.GetSize(), m_heap_fill_value);
2163 it.GetSize());
2164 } 2166 }
2165 2167
2166 // Map the pages. 2168 // Map the pages.
diff --git a/src/core/hle/kernel/kernel.cpp b/src/core/hle/kernel/kernel.cpp
index 8cb05ca0b..e479dacde 100644
--- a/src/core/hle/kernel/kernel.cpp
+++ b/src/core/hle/kernel/kernel.cpp
@@ -135,7 +135,6 @@ struct KernelCore::Impl {
135 obj = nullptr; 135 obj = nullptr;
136 } 136 }
137 }; 137 };
138 CleanupObject(hid_shared_mem);
139 CleanupObject(font_shared_mem); 138 CleanupObject(font_shared_mem);
140 CleanupObject(irs_shared_mem); 139 CleanupObject(irs_shared_mem);
141 CleanupObject(time_shared_mem); 140 CleanupObject(time_shared_mem);
@@ -744,22 +743,16 @@ struct KernelCore::Impl {
744 void InitializeHackSharedMemory(KernelCore& kernel) { 743 void InitializeHackSharedMemory(KernelCore& kernel) {
745 // Setup memory regions for emulated processes 744 // Setup memory regions for emulated processes
746 // TODO(bunnei): These should not be hardcoded regions initialized within the kernel 745 // TODO(bunnei): These should not be hardcoded regions initialized within the kernel
747 constexpr std::size_t hid_size{0x40000};
748 constexpr std::size_t font_size{0x1100000}; 746 constexpr std::size_t font_size{0x1100000};
749 constexpr std::size_t irs_size{0x8000}; 747 constexpr std::size_t irs_size{0x8000};
750 constexpr std::size_t time_size{0x1000}; 748 constexpr std::size_t time_size{0x1000};
751 constexpr std::size_t hidbus_size{0x1000}; 749 constexpr std::size_t hidbus_size{0x1000};
752 750
753 hid_shared_mem = KSharedMemory::Create(system.Kernel());
754 font_shared_mem = KSharedMemory::Create(system.Kernel()); 751 font_shared_mem = KSharedMemory::Create(system.Kernel());
755 irs_shared_mem = KSharedMemory::Create(system.Kernel()); 752 irs_shared_mem = KSharedMemory::Create(system.Kernel());
756 time_shared_mem = KSharedMemory::Create(system.Kernel()); 753 time_shared_mem = KSharedMemory::Create(system.Kernel());
757 hidbus_shared_mem = KSharedMemory::Create(system.Kernel()); 754 hidbus_shared_mem = KSharedMemory::Create(system.Kernel());
758 755
759 hid_shared_mem->Initialize(system.DeviceMemory(), nullptr, Svc::MemoryPermission::None,
760 Svc::MemoryPermission::Read, hid_size);
761 KSharedMemory::Register(kernel, hid_shared_mem);
762
763 font_shared_mem->Initialize(system.DeviceMemory(), nullptr, Svc::MemoryPermission::None, 756 font_shared_mem->Initialize(system.DeviceMemory(), nullptr, Svc::MemoryPermission::None,
764 Svc::MemoryPermission::Read, font_size); 757 Svc::MemoryPermission::Read, font_size);
765 KSharedMemory::Register(kernel, font_shared_mem); 758 KSharedMemory::Register(kernel, font_shared_mem);
@@ -1190,14 +1183,6 @@ const KSystemResource& KernelCore::GetSystemSystemResource() const {
1190 return *impl->sys_system_resource; 1183 return *impl->sys_system_resource;
1191} 1184}
1192 1185
1193Kernel::KSharedMemory& KernelCore::GetHidSharedMem() {
1194 return *impl->hid_shared_mem;
1195}
1196
1197const Kernel::KSharedMemory& KernelCore::GetHidSharedMem() const {
1198 return *impl->hid_shared_mem;
1199}
1200
1201Kernel::KSharedMemory& KernelCore::GetFontSharedMem() { 1186Kernel::KSharedMemory& KernelCore::GetFontSharedMem() {
1202 return *impl->font_shared_mem; 1187 return *impl->font_shared_mem;
1203} 1188}
diff --git a/src/core/hle/kernel/kernel.h b/src/core/hle/kernel/kernel.h
index 69b5bbd6c..78c88902c 100644
--- a/src/core/hle/kernel/kernel.h
+++ b/src/core/hle/kernel/kernel.h
@@ -239,12 +239,6 @@ public:
239 /// Gets the system resource manager. 239 /// Gets the system resource manager.
240 const KSystemResource& GetSystemSystemResource() const; 240 const KSystemResource& GetSystemSystemResource() const;
241 241
242 /// Gets the shared memory object for HID services.
243 Kernel::KSharedMemory& GetHidSharedMem();
244
245 /// Gets the shared memory object for HID services.
246 const Kernel::KSharedMemory& GetHidSharedMem() const;
247
248 /// Gets the shared memory object for font services. 242 /// Gets the shared memory object for font services.
249 Kernel::KSharedMemory& GetFontSharedMem(); 243 Kernel::KSharedMemory& GetFontSharedMem();
250 244
diff --git a/src/core/hle/service/filesystem/filesystem.cpp b/src/core/hle/service/filesystem/filesystem.cpp
index 508db7360..780f8c74d 100644
--- a/src/core/hle/service/filesystem/filesystem.cpp
+++ b/src/core/hle/service/filesystem/filesystem.cpp
@@ -104,11 +104,7 @@ Result VfsDirectoryServiceWrapper::CreateDirectory(const std::string& path_) con
104 const auto components = Common::FS::SplitPathComponents(path); 104 const auto components = Common::FS::SplitPathComponents(path);
105 std::string relative_path; 105 std::string relative_path;
106 for (const auto& component : components) { 106 for (const auto& component : components) {
107 // Skip empty path components 107 relative_path = Common::FS::SanitizePath(fmt::format("{}/{}", relative_path, component));
108 if (component.empty()) {
109 continue;
110 }
111 relative_path = Common::FS::SanitizePath(relative_path + '/' + component);
112 auto new_dir = backing->CreateSubdirectory(relative_path); 108 auto new_dir = backing->CreateSubdirectory(relative_path);
113 if (new_dir == nullptr) { 109 if (new_dir == nullptr) {
114 // TODO(DarkLordZach): Find a better error code for this 110 // TODO(DarkLordZach): Find a better error code for this
diff --git a/src/core/hle/service/hid/controllers/applet_resource.cpp b/src/core/hle/service/hid/controllers/applet_resource.cpp
index 435b86233..c8e74c764 100644
--- a/src/core/hle/service/hid/controllers/applet_resource.cpp
+++ b/src/core/hle/service/hid/controllers/applet_resource.cpp
@@ -4,6 +4,7 @@
4#include "core/core.h" 4#include "core/core.h"
5#include "core/hle/kernel/k_shared_memory.h" 5#include "core/hle/kernel/k_shared_memory.h"
6#include "core/hle/service/hid/controllers/applet_resource.h" 6#include "core/hle/service/hid/controllers/applet_resource.h"
7#include "core/hle/service/hid/controllers/shared_memory_format.h"
7#include "core/hle/service/hid/errors.h" 8#include "core/hle/service/hid/errors.h"
8 9
9namespace Service::HID { 10namespace Service::HID {
@@ -23,11 +24,24 @@ Result AppletResource::CreateAppletResource(u64 aruid) {
23 return ResultAruidAlreadyRegistered; 24 return ResultAruidAlreadyRegistered;
24 } 25 }
25 26
26 // TODO: Here shared memory is created for the process we don't quite emulate this part so 27 auto& shared_memory = shared_memory_holder[index];
27 // obtain this pointer from system 28 if (!shared_memory.IsMapped()) {
28 auto& shared_memory = system.Kernel().GetHidSharedMem(); 29 const Result result = shared_memory.Initialize(system);
30 if (result.IsError()) {
31 return result;
32 }
33 if (shared_memory.GetAddress() == nullptr) {
34 shared_memory.Finalize();
35 return ResultSharedMemoryNotInitialized;
36 }
37 }
38
39 auto* shared_memory_format = shared_memory.GetAddress();
40 if (shared_memory_format != nullptr) {
41 shared_memory_format->Initialize();
42 }
29 43
30 data[index].shared_memory_handle = &shared_memory; 44 data[index].shared_memory_format = shared_memory_format;
31 data[index].flag.is_assigned.Assign(true); 45 data[index].flag.is_assigned.Assign(true);
32 // TODO: InitializeSixAxisControllerConfig(false); 46 // TODO: InitializeSixAxisControllerConfig(false);
33 active_aruid = aruid; 47 active_aruid = aruid;
@@ -94,7 +108,7 @@ void AppletResource::UnregisterAppletResourceUserId(u64 aruid) {
94 108
95 if (index < AruidIndexMax) { 109 if (index < AruidIndexMax) {
96 if (data[index].flag.is_assigned) { 110 if (data[index].flag.is_assigned) {
97 data[index].shared_memory_handle = nullptr; 111 data[index].shared_memory_format = nullptr;
98 data[index].flag.is_assigned.Assign(false); 112 data[index].flag.is_assigned.Assign(false);
99 } 113 }
100 } 114 }
@@ -120,7 +134,7 @@ void AppletResource::FreeAppletResourceId(u64 aruid) {
120 134
121 auto& aruid_data = data[index]; 135 auto& aruid_data = data[index];
122 if (aruid_data.flag.is_assigned) { 136 if (aruid_data.flag.is_assigned) {
123 aruid_data.shared_memory_handle = nullptr; 137 aruid_data.shared_memory_format = nullptr;
124 aruid_data.flag.is_assigned.Assign(false); 138 aruid_data.flag.is_assigned.Assign(false);
125 } 139 }
126} 140}
@@ -135,7 +149,18 @@ Result AppletResource::GetSharedMemoryHandle(Kernel::KSharedMemory** out_handle,
135 return ResultAruidNotRegistered; 149 return ResultAruidNotRegistered;
136 } 150 }
137 151
138 *out_handle = data[index].shared_memory_handle; 152 *out_handle = shared_memory_holder[index].GetHandle();
153 return ResultSuccess;
154}
155
156Result AppletResource::GetSharedMemoryFormat(SharedMemoryFormat** out_shared_memory_format,
157 u64 aruid) {
158 u64 index = GetIndexFromAruid(aruid);
159 if (index >= AruidIndexMax) {
160 return ResultAruidNotRegistered;
161 }
162
163 *out_shared_memory_format = data[index].shared_memory_format;
139 return ResultSuccess; 164 return ResultSuccess;
140} 165}
141 166
diff --git a/src/core/hle/service/hid/controllers/applet_resource.h b/src/core/hle/service/hid/controllers/applet_resource.h
index 62137db13..e7991f93a 100644
--- a/src/core/hle/service/hid/controllers/applet_resource.h
+++ b/src/core/hle/service/hid/controllers/applet_resource.h
@@ -8,6 +8,7 @@
8#include "common/bit_field.h" 8#include "common/bit_field.h"
9#include "common/common_types.h" 9#include "common/common_types.h"
10#include "core/hle/result.h" 10#include "core/hle/result.h"
11#include "core/hle/service/hid/controllers/shared_memory_holder.h"
11 12
12namespace Core { 13namespace Core {
13class System; 14class System;
@@ -18,6 +19,8 @@ class KSharedMemory;
18} 19}
19 20
20namespace Service::HID { 21namespace Service::HID {
22struct SharedMemoryFormat;
23
21class AppletResource { 24class AppletResource {
22public: 25public:
23 explicit AppletResource(Core::System& system_); 26 explicit AppletResource(Core::System& system_);
@@ -32,6 +35,7 @@ public:
32 35
33 u64 GetActiveAruid(); 36 u64 GetActiveAruid();
34 Result GetSharedMemoryHandle(Kernel::KSharedMemory** out_handle, u64 aruid); 37 Result GetSharedMemoryHandle(Kernel::KSharedMemory** out_handle, u64 aruid);
38 Result GetSharedMemoryFormat(SharedMemoryFormat** out_shared_memory_format, u64 aruid);
35 39
36 u64 GetIndexFromAruid(u64 aruid); 40 u64 GetIndexFromAruid(u64 aruid);
37 41
@@ -80,12 +84,13 @@ private:
80 struct AruidData { 84 struct AruidData {
81 DataStatusFlag flag{}; 85 DataStatusFlag flag{};
82 u64 aruid{}; 86 u64 aruid{};
83 Kernel::KSharedMemory* shared_memory_handle{nullptr}; 87 SharedMemoryFormat* shared_memory_format{nullptr};
84 }; 88 };
85 89
86 u64 active_aruid{}; 90 u64 active_aruid{};
87 AruidRegisterList registration_list{}; 91 AruidRegisterList registration_list{};
88 std::array<AruidData, AruidIndexMax> data{}; 92 std::array<AruidData, AruidIndexMax> data{};
93 std::array<SharedMemoryHolder, AruidIndexMax> shared_memory_holder{};
89 s32 ref_counter{}; 94 s32 ref_counter{};
90 95
91 Core::System& system; 96 Core::System& system;
diff --git a/src/core/hle/service/hid/controllers/console_six_axis.cpp b/src/core/hle/service/hid/controllers/console_six_axis.cpp
index b2bf1d78d..3961d2b5f 100644
--- a/src/core/hle/service/hid/controllers/console_six_axis.cpp
+++ b/src/core/hle/service/hid/controllers/console_six_axis.cpp
@@ -1,23 +1,18 @@
1// SPDX-FileCopyrightText: Copyright 2021 yuzu Emulator Project 1// SPDX-FileCopyrightText: Copyright 2021 yuzu Emulator Project
2// SPDX-License-Identifier: GPL-2.0-or-later 2// SPDX-License-Identifier: GPL-2.0-or-later
3 3
4#include "core/core.h"
5#include "core/core_timing.h" 4#include "core/core_timing.h"
6#include "core/hid/emulated_console.h" 5#include "core/hid/emulated_console.h"
7#include "core/hid/hid_core.h" 6#include "core/hid/hid_core.h"
8#include "core/hle/service/hid/controllers/console_six_axis.h" 7#include "core/hle/service/hid/controllers/console_six_axis.h"
9#include "core/memory.h" 8#include "core/hle/service/hid/controllers/shared_memory_format.h"
10 9
11namespace Service::HID { 10namespace Service::HID {
12constexpr std::size_t SHARED_MEMORY_OFFSET = 0x3C200;
13 11
14ConsoleSixAxis::ConsoleSixAxis(Core::HID::HIDCore& hid_core_, u8* raw_shared_memory_) 12ConsoleSixAxis::ConsoleSixAxis(Core::HID::HIDCore& hid_core_,
15 : ControllerBase{hid_core_} { 13 ConsoleSixAxisSensorSharedMemoryFormat& console_shared_memory)
14 : ControllerBase{hid_core_}, shared_memory{console_shared_memory} {
16 console = hid_core.GetEmulatedConsole(); 15 console = hid_core.GetEmulatedConsole();
17 static_assert(SHARED_MEMORY_OFFSET + sizeof(ConsoleSharedMemory) < shared_memory_size,
18 "ConsoleSharedMemory is bigger than the shared memory");
19 shared_memory = std::construct_at(
20 reinterpret_cast<ConsoleSharedMemory*>(raw_shared_memory_ + SHARED_MEMORY_OFFSET));
21} 16}
22 17
23ConsoleSixAxis::~ConsoleSixAxis() = default; 18ConsoleSixAxis::~ConsoleSixAxis() = default;
@@ -33,10 +28,10 @@ void ConsoleSixAxis::OnUpdate(const Core::Timing::CoreTiming& core_timing) {
33 28
34 const auto motion_status = console->GetMotion(); 29 const auto motion_status = console->GetMotion();
35 30
36 shared_memory->sampling_number++; 31 shared_memory.sampling_number++;
37 shared_memory->is_seven_six_axis_sensor_at_rest = motion_status.is_at_rest; 32 shared_memory.is_seven_six_axis_sensor_at_rest = motion_status.is_at_rest;
38 shared_memory->verticalization_error = motion_status.verticalization_error; 33 shared_memory.verticalization_error = motion_status.verticalization_error;
39 shared_memory->gyro_bias = motion_status.gyro_bias; 34 shared_memory.gyro_bias = motion_status.gyro_bias;
40} 35}
41 36
42} // namespace Service::HID 37} // namespace Service::HID
diff --git a/src/core/hle/service/hid/controllers/console_six_axis.h b/src/core/hle/service/hid/controllers/console_six_axis.h
index 5b7c6a29a..3d1c9ce23 100644
--- a/src/core/hle/service/hid/controllers/console_six_axis.h
+++ b/src/core/hle/service/hid/controllers/console_six_axis.h
@@ -3,7 +3,6 @@
3 3
4#pragma once 4#pragma once
5 5
6#include "common/vector_math.h"
7#include "core/hle/service/hid/controllers/controller_base.h" 6#include "core/hle/service/hid/controllers/controller_base.h"
8 7
9namespace Core::HID { 8namespace Core::HID {
@@ -11,9 +10,12 @@ class EmulatedConsole;
11} // namespace Core::HID 10} // namespace Core::HID
12 11
13namespace Service::HID { 12namespace Service::HID {
13struct ConsoleSixAxisSensorSharedMemoryFormat;
14
14class ConsoleSixAxis final : public ControllerBase { 15class ConsoleSixAxis final : public ControllerBase {
15public: 16public:
16 explicit ConsoleSixAxis(Core::HID::HIDCore& hid_core_, u8* raw_shared_memory_); 17 explicit ConsoleSixAxis(Core::HID::HIDCore& hid_core_,
18 ConsoleSixAxisSensorSharedMemoryFormat& console_shared_memory);
17 ~ConsoleSixAxis() override; 19 ~ConsoleSixAxis() override;
18 20
19 // Called when the controller is initialized 21 // Called when the controller is initialized
@@ -26,18 +28,7 @@ public:
26 void OnUpdate(const Core::Timing::CoreTiming& core_timing) override; 28 void OnUpdate(const Core::Timing::CoreTiming& core_timing) override;
27 29
28private: 30private:
29 // This is nn::hid::detail::ConsoleSixAxisSensorSharedMemoryFormat 31 ConsoleSixAxisSensorSharedMemoryFormat& shared_memory;
30 struct ConsoleSharedMemory {
31 u64 sampling_number{};
32 bool is_seven_six_axis_sensor_at_rest{};
33 INSERT_PADDING_BYTES(3); // padding
34 f32 verticalization_error{};
35 Common::Vec3f gyro_bias{};
36 INSERT_PADDING_BYTES(4); // padding
37 };
38 static_assert(sizeof(ConsoleSharedMemory) == 0x20, "ConsoleSharedMemory is an invalid size");
39
40 ConsoleSharedMemory* shared_memory = nullptr;
41 Core::HID::EmulatedConsole* console = nullptr; 32 Core::HID::EmulatedConsole* console = nullptr;
42}; 33};
43} // namespace Service::HID 34} // namespace Service::HID
diff --git a/src/core/hle/service/hid/controllers/controller_base.h b/src/core/hle/service/hid/controllers/controller_base.h
index 9a44ee41e..4326c7821 100644
--- a/src/core/hle/service/hid/controllers/controller_base.h
+++ b/src/core/hle/service/hid/controllers/controller_base.h
@@ -39,9 +39,6 @@ public:
39 39
40 bool IsControllerActivated() const; 40 bool IsControllerActivated() const;
41 41
42 static const std::size_t hid_entry_count = 17;
43 static const std::size_t shared_memory_size = 0x40000;
44
45protected: 42protected:
46 bool is_activated{false}; 43 bool is_activated{false};
47 44
diff --git a/src/core/hle/service/hid/controllers/debug_pad.cpp b/src/core/hle/service/hid/controllers/debug_pad.cpp
index 9de19ebfc..7d2370b4f 100644
--- a/src/core/hle/service/hid/controllers/debug_pad.cpp
+++ b/src/core/hle/service/hid/controllers/debug_pad.cpp
@@ -1,24 +1,19 @@
1// SPDX-FileCopyrightText: Copyright 2018 yuzu Emulator Project 1// SPDX-FileCopyrightText: Copyright 2018 yuzu Emulator Project
2// SPDX-License-Identifier: GPL-2.0-or-later 2// SPDX-License-Identifier: GPL-2.0-or-later
3 3
4#include <cstring>
5#include "common/common_types.h"
6#include "common/settings.h" 4#include "common/settings.h"
7#include "core/core_timing.h" 5#include "core/core_timing.h"
8#include "core/hid/emulated_controller.h" 6#include "core/hid/emulated_controller.h"
9#include "core/hid/hid_core.h" 7#include "core/hid/hid_core.h"
10#include "core/hid/hid_types.h" 8#include "core/hid/hid_types.h"
11#include "core/hle/service/hid/controllers/debug_pad.h" 9#include "core/hle/service/hid/controllers/debug_pad.h"
10#include "core/hle/service/hid/controllers/shared_memory_format.h"
12 11
13namespace Service::HID { 12namespace Service::HID {
14constexpr std::size_t SHARED_MEMORY_OFFSET = 0x00000; 13
15 14DebugPad::DebugPad(Core::HID::HIDCore& hid_core_,
16DebugPad::DebugPad(Core::HID::HIDCore& hid_core_, u8* raw_shared_memory_) 15 DebugPadSharedMemoryFormat& debug_pad_shared_memory)
17 : ControllerBase{hid_core_} { 16 : ControllerBase{hid_core_}, shared_memory{debug_pad_shared_memory} {
18 static_assert(SHARED_MEMORY_OFFSET + sizeof(DebugPadSharedMemory) < shared_memory_size,
19 "DebugPadSharedMemory is bigger than the shared memory");
20 shared_memory = std::construct_at(
21 reinterpret_cast<DebugPadSharedMemory*>(raw_shared_memory_ + SHARED_MEMORY_OFFSET));
22 controller = hid_core.GetEmulatedController(Core::HID::NpadIdType::Other); 17 controller = hid_core.GetEmulatedController(Core::HID::NpadIdType::Other);
23} 18}
24 19
@@ -30,12 +25,12 @@ void DebugPad::OnRelease() {}
30 25
31void DebugPad::OnUpdate(const Core::Timing::CoreTiming& core_timing) { 26void DebugPad::OnUpdate(const Core::Timing::CoreTiming& core_timing) {
32 if (!IsControllerActivated()) { 27 if (!IsControllerActivated()) {
33 shared_memory->debug_pad_lifo.buffer_count = 0; 28 shared_memory.debug_pad_lifo.buffer_count = 0;
34 shared_memory->debug_pad_lifo.buffer_tail = 0; 29 shared_memory.debug_pad_lifo.buffer_tail = 0;
35 return; 30 return;
36 } 31 }
37 32
38 const auto& last_entry = shared_memory->debug_pad_lifo.ReadCurrentEntry().state; 33 const auto& last_entry = shared_memory.debug_pad_lifo.ReadCurrentEntry().state;
39 next_state.sampling_number = last_entry.sampling_number + 1; 34 next_state.sampling_number = last_entry.sampling_number + 1;
40 35
41 if (Settings::values.debug_pad_enabled) { 36 if (Settings::values.debug_pad_enabled) {
@@ -49,7 +44,7 @@ void DebugPad::OnUpdate(const Core::Timing::CoreTiming& core_timing) {
49 next_state.r_stick = stick_state.right; 44 next_state.r_stick = stick_state.right;
50 } 45 }
51 46
52 shared_memory->debug_pad_lifo.WriteNextEntry(next_state); 47 shared_memory.debug_pad_lifo.WriteNextEntry(next_state);
53} 48}
54 49
55} // namespace Service::HID 50} // namespace Service::HID
diff --git a/src/core/hle/service/hid/controllers/debug_pad.h b/src/core/hle/service/hid/controllers/debug_pad.h
index 5566dba77..8ab29eca8 100644
--- a/src/core/hle/service/hid/controllers/debug_pad.h
+++ b/src/core/hle/service/hid/controllers/debug_pad.h
@@ -3,21 +3,24 @@
3 3
4#pragma once 4#pragma once
5 5
6#include "common/bit_field.h"
7#include "common/common_types.h"
8#include "core/hle/service/hid/controllers/controller_base.h" 6#include "core/hle/service/hid/controllers/controller_base.h"
9#include "core/hle/service/hid/ring_lifo.h" 7#include "core/hle/service/hid/controllers/types/debug_pad_types.h"
10 8
11namespace Core::HID { 9namespace Core::HID {
12class EmulatedController; 10class HIDCore;
13struct DebugPadButton; 11}
14struct AnalogStickState; 12
15} // namespace Core::HID 13namespace Core::Timing {
14class CoreTiming;
15}
16 16
17namespace Service::HID { 17namespace Service::HID {
18struct DebugPadSharedMemoryFormat;
19
18class DebugPad final : public ControllerBase { 20class DebugPad final : public ControllerBase {
19public: 21public:
20 explicit DebugPad(Core::HID::HIDCore& hid_core_, u8* raw_shared_memory_); 22 explicit DebugPad(Core::HID::HIDCore& hid_core_,
23 DebugPadSharedMemoryFormat& debug_pad_shared_memory);
21 ~DebugPad() override; 24 ~DebugPad() override;
22 25
23 // Called when the controller is initialized 26 // Called when the controller is initialized
@@ -30,35 +33,8 @@ public:
30 void OnUpdate(const Core::Timing::CoreTiming& core_timing) override; 33 void OnUpdate(const Core::Timing::CoreTiming& core_timing) override;
31 34
32private: 35private:
33 // This is nn::hid::DebugPadAttribute
34 struct DebugPadAttribute {
35 union {
36 u32 raw{};
37 BitField<0, 1, u32> connected;
38 };
39 };
40 static_assert(sizeof(DebugPadAttribute) == 0x4, "DebugPadAttribute is an invalid size");
41
42 // This is nn::hid::DebugPadState
43 struct DebugPadState {
44 s64 sampling_number{};
45 DebugPadAttribute attribute{};
46 Core::HID::DebugPadButton pad_state{};
47 Core::HID::AnalogStickState r_stick{};
48 Core::HID::AnalogStickState l_stick{};
49 };
50 static_assert(sizeof(DebugPadState) == 0x20, "DebugPadState is an invalid state");
51
52 struct DebugPadSharedMemory {
53 // This is nn::hid::detail::DebugPadLifo
54 Lifo<DebugPadState, hid_entry_count> debug_pad_lifo{};
55 static_assert(sizeof(debug_pad_lifo) == 0x2C8, "debug_pad_lifo is an invalid size");
56 INSERT_PADDING_WORDS(0x4E);
57 };
58 static_assert(sizeof(DebugPadSharedMemory) == 0x400, "DebugPadSharedMemory is an invalid size");
59
60 DebugPadState next_state{}; 36 DebugPadState next_state{};
61 DebugPadSharedMemory* shared_memory = nullptr; 37 DebugPadSharedMemoryFormat& shared_memory;
62 Core::HID::EmulatedController* controller = nullptr; 38 Core::HID::EmulatedController* controller = nullptr;
63}; 39};
64} // namespace Service::HID 40} // namespace Service::HID
diff --git a/src/core/hle/service/hid/controllers/gesture.cpp b/src/core/hle/service/hid/controllers/gesture.cpp
index 59b2ec73c..f658005f6 100644
--- a/src/core/hle/service/hid/controllers/gesture.cpp
+++ b/src/core/hle/service/hid/controllers/gesture.cpp
@@ -1,17 +1,15 @@
1// SPDX-FileCopyrightText: Copyright 2021 yuzu Emulator Project 1// SPDX-FileCopyrightText: Copyright 2021 yuzu Emulator Project
2// SPDX-License-Identifier: GPL-2.0-or-later 2// SPDX-License-Identifier: GPL-2.0-or-later
3 3
4#include "common/logging/log.h"
5#include "common/math_util.h" 4#include "common/math_util.h"
6#include "common/settings.h" 5#include "common/settings.h"
7#include "core/core_timing.h"
8#include "core/frontend/emu_window.h" 6#include "core/frontend/emu_window.h"
7#include "core/hid/emulated_console.h"
9#include "core/hid/hid_core.h" 8#include "core/hid/hid_core.h"
10#include "core/hle/service/hid/controllers/gesture.h" 9#include "core/hle/service/hid/controllers/gesture.h"
10#include "core/hle/service/hid/controllers/shared_memory_format.h"
11 11
12namespace Service::HID { 12namespace Service::HID {
13constexpr std::size_t SHARED_MEMORY_OFFSET = 0x3BA00;
14
15// HW is around 700, value is set to 400 to make it easier to trigger with mouse 13// HW is around 700, value is set to 400 to make it easier to trigger with mouse
16constexpr f32 swipe_threshold = 400.0f; // Threshold in pixels/s 14constexpr f32 swipe_threshold = 400.0f; // Threshold in pixels/s
17constexpr f32 angle_threshold = 0.015f; // Threshold in radians 15constexpr f32 angle_threshold = 0.015f; // Threshold in radians
@@ -23,19 +21,15 @@ constexpr f32 Square(s32 num) {
23 return static_cast<f32>(num * num); 21 return static_cast<f32>(num * num);
24} 22}
25 23
26Gesture::Gesture(Core::HID::HIDCore& hid_core_, u8* raw_shared_memory_) 24Gesture::Gesture(Core::HID::HIDCore& hid_core_, GestureSharedMemoryFormat& gesture_shared_memory)
27 : ControllerBase(hid_core_) { 25 : ControllerBase(hid_core_), shared_memory{gesture_shared_memory} {
28 static_assert(SHARED_MEMORY_OFFSET + sizeof(GestureSharedMemory) < shared_memory_size,
29 "GestureSharedMemory is bigger than the shared memory");
30 shared_memory = std::construct_at(
31 reinterpret_cast<GestureSharedMemory*>(raw_shared_memory_ + SHARED_MEMORY_OFFSET));
32 console = hid_core.GetEmulatedConsole(); 26 console = hid_core.GetEmulatedConsole();
33} 27}
34Gesture::~Gesture() = default; 28Gesture::~Gesture() = default;
35 29
36void Gesture::OnInit() { 30void Gesture::OnInit() {
37 shared_memory->gesture_lifo.buffer_count = 0; 31 shared_memory.gesture_lifo.buffer_count = 0;
38 shared_memory->gesture_lifo.buffer_tail = 0; 32 shared_memory.gesture_lifo.buffer_tail = 0;
39 force_update = true; 33 force_update = true;
40} 34}
41 35
@@ -43,8 +37,8 @@ void Gesture::OnRelease() {}
43 37
44void Gesture::OnUpdate(const Core::Timing::CoreTiming& core_timing) { 38void Gesture::OnUpdate(const Core::Timing::CoreTiming& core_timing) {
45 if (!IsControllerActivated()) { 39 if (!IsControllerActivated()) {
46 shared_memory->gesture_lifo.buffer_count = 0; 40 shared_memory.gesture_lifo.buffer_count = 0;
47 shared_memory->gesture_lifo.buffer_tail = 0; 41 shared_memory.gesture_lifo.buffer_tail = 0;
48 return; 42 return;
49 } 43 }
50 44
@@ -52,7 +46,7 @@ void Gesture::OnUpdate(const Core::Timing::CoreTiming& core_timing) {
52 46
53 GestureProperties gesture = GetGestureProperties(); 47 GestureProperties gesture = GetGestureProperties();
54 f32 time_difference = 48 f32 time_difference =
55 static_cast<f32>(shared_memory->gesture_lifo.timestamp - last_update_timestamp) / 49 static_cast<f32>(shared_memory.gesture_lifo.timestamp - last_update_timestamp) /
56 (1000 * 1000 * 1000); 50 (1000 * 1000 * 1000);
57 51
58 // Only update if necessary 52 // Only update if necessary
@@ -60,7 +54,7 @@ void Gesture::OnUpdate(const Core::Timing::CoreTiming& core_timing) {
60 return; 54 return;
61 } 55 }
62 56
63 last_update_timestamp = shared_memory->gesture_lifo.timestamp; 57 last_update_timestamp = shared_memory.gesture_lifo.timestamp;
64 UpdateGestureSharedMemory(gesture, time_difference); 58 UpdateGestureSharedMemory(gesture, time_difference);
65} 59}
66 60
@@ -103,7 +97,7 @@ void Gesture::UpdateGestureSharedMemory(GestureProperties& gesture, f32 time_dif
103 GestureType type = GestureType::Idle; 97 GestureType type = GestureType::Idle;
104 GestureAttribute attributes{}; 98 GestureAttribute attributes{};
105 99
106 const auto& last_entry = shared_memory->gesture_lifo.ReadCurrentEntry().state; 100 const auto& last_entry = shared_memory.gesture_lifo.ReadCurrentEntry().state;
107 101
108 // Reset next state to default 102 // Reset next state to default
109 next_state.sampling_number = last_entry.sampling_number + 1; 103 next_state.sampling_number = last_entry.sampling_number + 1;
@@ -133,7 +127,7 @@ void Gesture::UpdateGestureSharedMemory(GestureProperties& gesture, f32 time_dif
133 next_state.points = gesture.points; 127 next_state.points = gesture.points;
134 last_gesture = gesture; 128 last_gesture = gesture;
135 129
136 shared_memory->gesture_lifo.WriteNextEntry(next_state); 130 shared_memory.gesture_lifo.WriteNextEntry(next_state);
137} 131}
138 132
139void Gesture::NewGesture(GestureProperties& gesture, GestureType& type, 133void Gesture::NewGesture(GestureProperties& gesture, GestureType& type,
@@ -305,11 +299,11 @@ void Gesture::SetSwipeEvent(GestureProperties& gesture, GestureProperties& last_
305 next_state.direction = GestureDirection::Up; 299 next_state.direction = GestureDirection::Up;
306} 300}
307 301
308const Gesture::GestureState& Gesture::GetLastGestureEntry() const { 302const GestureState& Gesture::GetLastGestureEntry() const {
309 return shared_memory->gesture_lifo.ReadCurrentEntry().state; 303 return shared_memory.gesture_lifo.ReadCurrentEntry().state;
310} 304}
311 305
312Gesture::GestureProperties Gesture::GetGestureProperties() { 306GestureProperties Gesture::GetGestureProperties() {
313 GestureProperties gesture; 307 GestureProperties gesture;
314 std::array<Core::HID::TouchFinger, MAX_POINTS> active_fingers; 308 std::array<Core::HID::TouchFinger, MAX_POINTS> active_fingers;
315 const auto end_iter = std::copy_if(fingers.begin(), fingers.end(), active_fingers.begin(), 309 const auto end_iter = std::copy_if(fingers.begin(), fingers.end(), active_fingers.begin(),
diff --git a/src/core/hle/service/hid/controllers/gesture.h b/src/core/hle/service/hid/controllers/gesture.h
index 4c6f8ee07..41fdfcd03 100644
--- a/src/core/hle/service/hid/controllers/gesture.h
+++ b/src/core/hle/service/hid/controllers/gesture.h
@@ -4,17 +4,22 @@
4#pragma once 4#pragma once
5 5
6#include <array> 6#include <array>
7#include "common/bit_field.h" 7
8#include "common/common_types.h" 8#include "common/common_types.h"
9#include "common/point.h"
10#include "core/hid/emulated_console.h"
11#include "core/hle/service/hid/controllers/controller_base.h" 9#include "core/hle/service/hid/controllers/controller_base.h"
12#include "core/hle/service/hid/ring_lifo.h" 10#include "core/hle/service/hid/controllers/types/touch_types.h"
11
12namespace Core::HID {
13class EmulatedConsole;
14}
13 15
14namespace Service::HID { 16namespace Service::HID {
17struct GestureSharedMemoryFormat;
18
15class Gesture final : public ControllerBase { 19class Gesture final : public ControllerBase {
16public: 20public:
17 explicit Gesture(Core::HID::HIDCore& hid_core_, u8* raw_shared_memory_); 21 explicit Gesture(Core::HID::HIDCore& hid_core_,
22 GestureSharedMemoryFormat& gesture_shared_memory);
18 ~Gesture() override; 23 ~Gesture() override;
19 24
20 // Called when the controller is initialized 25 // Called when the controller is initialized
@@ -27,79 +32,6 @@ public:
27 void OnUpdate(const Core::Timing::CoreTiming& core_timing) override; 32 void OnUpdate(const Core::Timing::CoreTiming& core_timing) override;
28 33
29private: 34private:
30 static constexpr size_t MAX_FINGERS = 16;
31 static constexpr size_t MAX_POINTS = 4;
32
33 // This is nn::hid::GestureType
34 enum class GestureType : u32 {
35 Idle, // Nothing touching the screen
36 Complete, // Set at the end of a touch event
37 Cancel, // Set when the number of fingers change
38 Touch, // A finger just touched the screen
39 Press, // Set if last type is touch and the finger hasn't moved
40 Tap, // Fast press then release
41 Pan, // All points moving together across the screen
42 Swipe, // Fast press movement and release of a single point
43 Pinch, // All points moving away/closer to the midpoint
44 Rotate, // All points rotating from the midpoint
45 };
46
47 // This is nn::hid::GestureDirection
48 enum class GestureDirection : u32 {
49 None,
50 Left,
51 Up,
52 Right,
53 Down,
54 };
55
56 // This is nn::hid::GestureAttribute
57 struct GestureAttribute {
58 union {
59 u32 raw{};
60
61 BitField<4, 1, u32> is_new_touch;
62 BitField<8, 1, u32> is_double_tap;
63 };
64 };
65 static_assert(sizeof(GestureAttribute) == 4, "GestureAttribute is an invalid size");
66
67 // This is nn::hid::GestureState
68 struct GestureState {
69 s64 sampling_number{};
70 s64 detection_count{};
71 GestureType type{GestureType::Idle};
72 GestureDirection direction{GestureDirection::None};
73 Common::Point<s32> pos{};
74 Common::Point<s32> delta{};
75 f32 vel_x{};
76 f32 vel_y{};
77 GestureAttribute attributes{};
78 f32 scale{};
79 f32 rotation_angle{};
80 s32 point_count{};
81 std::array<Common::Point<s32>, 4> points{};
82 };
83 static_assert(sizeof(GestureState) == 0x60, "GestureState is an invalid size");
84
85 struct GestureProperties {
86 std::array<Common::Point<s32>, MAX_POINTS> points{};
87 std::size_t active_points{};
88 Common::Point<s32> mid_point{};
89 s64 detection_count{};
90 u64 delta_time{};
91 f32 average_distance{};
92 f32 angle{};
93 };
94
95 struct GestureSharedMemory {
96 // This is nn::hid::detail::GestureLifo
97 Lifo<GestureState, hid_entry_count> gesture_lifo{};
98 static_assert(sizeof(gesture_lifo) == 0x708, "gesture_lifo is an invalid size");
99 INSERT_PADDING_WORDS(0x3E);
100 };
101 static_assert(sizeof(GestureSharedMemory) == 0x800, "GestureSharedMemory is an invalid size");
102
103 // Reads input from all available input engines 35 // Reads input from all available input engines
104 void ReadTouchInput(); 36 void ReadTouchInput();
105 37
@@ -142,7 +74,7 @@ private:
142 GestureProperties GetGestureProperties(); 74 GestureProperties GetGestureProperties();
143 75
144 GestureState next_state{}; 76 GestureState next_state{};
145 GestureSharedMemory* shared_memory = nullptr; 77 GestureSharedMemoryFormat& shared_memory;
146 Core::HID::EmulatedConsole* console = nullptr; 78 Core::HID::EmulatedConsole* console = nullptr;
147 79
148 std::array<Core::HID::TouchFinger, MAX_POINTS> fingers{}; 80 std::array<Core::HID::TouchFinger, MAX_POINTS> fingers{};
diff --git a/src/core/hle/service/hid/controllers/keyboard.cpp b/src/core/hle/service/hid/controllers/keyboard.cpp
index ddb1b0ba4..871e5036a 100644
--- a/src/core/hle/service/hid/controllers/keyboard.cpp
+++ b/src/core/hle/service/hid/controllers/keyboard.cpp
@@ -1,23 +1,18 @@
1// SPDX-FileCopyrightText: Copyright 2018 yuzu Emulator Project 1// SPDX-FileCopyrightText: Copyright 2018 yuzu Emulator Project
2// SPDX-License-Identifier: GPL-2.0-or-later 2// SPDX-License-Identifier: GPL-2.0-or-later
3 3
4#include <cstring>
5#include "common/common_types.h"
6#include "common/settings.h" 4#include "common/settings.h"
7#include "core/core_timing.h" 5#include "core/core_timing.h"
8#include "core/hid/emulated_devices.h" 6#include "core/hid/emulated_devices.h"
9#include "core/hid/hid_core.h" 7#include "core/hid/hid_core.h"
10#include "core/hle/service/hid/controllers/keyboard.h" 8#include "core/hle/service/hid/controllers/keyboard.h"
9#include "core/hle/service/hid/controllers/shared_memory_format.h"
11 10
12namespace Service::HID { 11namespace Service::HID {
13constexpr std::size_t SHARED_MEMORY_OFFSET = 0x3800; 12
14 13Keyboard::Keyboard(Core::HID::HIDCore& hid_core_,
15Keyboard::Keyboard(Core::HID::HIDCore& hid_core_, u8* raw_shared_memory_) 14 KeyboardSharedMemoryFormat& keyboard_shared_memory)
16 : ControllerBase{hid_core_} { 15 : ControllerBase{hid_core_}, shared_memory{keyboard_shared_memory} {
17 static_assert(SHARED_MEMORY_OFFSET + sizeof(KeyboardSharedMemory) < shared_memory_size,
18 "KeyboardSharedMemory is bigger than the shared memory");
19 shared_memory = std::construct_at(
20 reinterpret_cast<KeyboardSharedMemory*>(raw_shared_memory_ + SHARED_MEMORY_OFFSET));
21 emulated_devices = hid_core.GetEmulatedDevices(); 16 emulated_devices = hid_core.GetEmulatedDevices();
22} 17}
23 18
@@ -29,12 +24,12 @@ void Keyboard::OnRelease() {}
29 24
30void Keyboard::OnUpdate(const Core::Timing::CoreTiming& core_timing) { 25void Keyboard::OnUpdate(const Core::Timing::CoreTiming& core_timing) {
31 if (!IsControllerActivated()) { 26 if (!IsControllerActivated()) {
32 shared_memory->keyboard_lifo.buffer_count = 0; 27 shared_memory.keyboard_lifo.buffer_count = 0;
33 shared_memory->keyboard_lifo.buffer_tail = 0; 28 shared_memory.keyboard_lifo.buffer_tail = 0;
34 return; 29 return;
35 } 30 }
36 31
37 const auto& last_entry = shared_memory->keyboard_lifo.ReadCurrentEntry().state; 32 const auto& last_entry = shared_memory.keyboard_lifo.ReadCurrentEntry().state;
38 next_state.sampling_number = last_entry.sampling_number + 1; 33 next_state.sampling_number = last_entry.sampling_number + 1;
39 34
40 if (Settings::values.keyboard_enabled) { 35 if (Settings::values.keyboard_enabled) {
@@ -46,7 +41,7 @@ void Keyboard::OnUpdate(const Core::Timing::CoreTiming& core_timing) {
46 next_state.attribute.is_connected.Assign(1); 41 next_state.attribute.is_connected.Assign(1);
47 } 42 }
48 43
49 shared_memory->keyboard_lifo.WriteNextEntry(next_state); 44 shared_memory.keyboard_lifo.WriteNextEntry(next_state);
50} 45}
51 46
52} // namespace Service::HID 47} // namespace Service::HID
diff --git a/src/core/hle/service/hid/controllers/keyboard.h b/src/core/hle/service/hid/controllers/keyboard.h
index 172ec1309..4d72171b9 100644
--- a/src/core/hle/service/hid/controllers/keyboard.h
+++ b/src/core/hle/service/hid/controllers/keyboard.h
@@ -3,20 +3,16 @@
3 3
4#pragma once 4#pragma once
5 5
6#include "common/common_types.h"
7#include "core/hle/service/hid/controllers/controller_base.h" 6#include "core/hle/service/hid/controllers/controller_base.h"
8#include "core/hle/service/hid/ring_lifo.h" 7#include "core/hle/service/hid/controllers/types/keyboard_types.h"
9
10namespace Core::HID {
11class EmulatedDevices;
12struct KeyboardModifier;
13struct KeyboardKey;
14} // namespace Core::HID
15 8
16namespace Service::HID { 9namespace Service::HID {
10struct KeyboardSharedMemoryFormat;
11
17class Keyboard final : public ControllerBase { 12class Keyboard final : public ControllerBase {
18public: 13public:
19 explicit Keyboard(Core::HID::HIDCore& hid_core_, u8* raw_shared_memory_); 14 explicit Keyboard(Core::HID::HIDCore& hid_core_,
15 KeyboardSharedMemoryFormat& keyboard_shared_memory);
20 ~Keyboard() override; 16 ~Keyboard() override;
21 17
22 // Called when the controller is initialized 18 // Called when the controller is initialized
@@ -29,25 +25,8 @@ public:
29 void OnUpdate(const Core::Timing::CoreTiming& core_timing) override; 25 void OnUpdate(const Core::Timing::CoreTiming& core_timing) override;
30 26
31private: 27private:
32 // This is nn::hid::detail::KeyboardState
33 struct KeyboardState {
34 s64 sampling_number{};
35 Core::HID::KeyboardModifier modifier{};
36 Core::HID::KeyboardAttribute attribute{};
37 Core::HID::KeyboardKey key{};
38 };
39 static_assert(sizeof(KeyboardState) == 0x30, "KeyboardState is an invalid size");
40
41 struct KeyboardSharedMemory {
42 // This is nn::hid::detail::KeyboardLifo
43 Lifo<KeyboardState, hid_entry_count> keyboard_lifo{};
44 static_assert(sizeof(keyboard_lifo) == 0x3D8, "keyboard_lifo is an invalid size");
45 INSERT_PADDING_WORDS(0xA);
46 };
47 static_assert(sizeof(KeyboardSharedMemory) == 0x400, "KeyboardSharedMemory is an invalid size");
48
49 KeyboardState next_state{}; 28 KeyboardState next_state{};
50 KeyboardSharedMemory* shared_memory = nullptr; 29 KeyboardSharedMemoryFormat& shared_memory;
51 Core::HID::EmulatedDevices* emulated_devices = nullptr; 30 Core::HID::EmulatedDevices* emulated_devices = nullptr;
52}; 31};
53} // namespace Service::HID 32} // namespace Service::HID
diff --git a/src/core/hle/service/hid/controllers/mouse.cpp b/src/core/hle/service/hid/controllers/mouse.cpp
index 6e5a04e34..de5b2c804 100644
--- a/src/core/hle/service/hid/controllers/mouse.cpp
+++ b/src/core/hle/service/hid/controllers/mouse.cpp
@@ -1,22 +1,17 @@
1// SPDX-FileCopyrightText: Copyright 2018 yuzu Emulator Project 1// SPDX-FileCopyrightText: Copyright 2018 yuzu Emulator Project
2// SPDX-License-Identifier: GPL-2.0-or-later 2// SPDX-License-Identifier: GPL-2.0-or-later
3 3
4#include <cstring>
5#include "common/common_types.h"
6#include "core/core_timing.h" 4#include "core/core_timing.h"
7#include "core/frontend/emu_window.h" 5#include "core/frontend/emu_window.h"
8#include "core/hid/emulated_devices.h" 6#include "core/hid/emulated_devices.h"
9#include "core/hid/hid_core.h" 7#include "core/hid/hid_core.h"
10#include "core/hle/service/hid/controllers/mouse.h" 8#include "core/hle/service/hid/controllers/mouse.h"
9#include "core/hle/service/hid/controllers/shared_memory_format.h"
11 10
12namespace Service::HID { 11namespace Service::HID {
13constexpr std::size_t SHARED_MEMORY_OFFSET = 0x3400;
14 12
15Mouse::Mouse(Core::HID::HIDCore& hid_core_, u8* raw_shared_memory_) : ControllerBase{hid_core_} { 13Mouse::Mouse(Core::HID::HIDCore& hid_core_, MouseSharedMemoryFormat& mouse_shared_memory)
16 static_assert(SHARED_MEMORY_OFFSET + sizeof(MouseSharedMemory) < shared_memory_size, 14 : ControllerBase{hid_core_}, shared_memory{mouse_shared_memory} {
17 "MouseSharedMemory is bigger than the shared memory");
18 shared_memory = std::construct_at(
19 reinterpret_cast<MouseSharedMemory*>(raw_shared_memory_ + SHARED_MEMORY_OFFSET));
20 emulated_devices = hid_core.GetEmulatedDevices(); 15 emulated_devices = hid_core.GetEmulatedDevices();
21} 16}
22 17
@@ -27,14 +22,14 @@ void Mouse::OnRelease() {}
27 22
28void Mouse::OnUpdate(const Core::Timing::CoreTiming& core_timing) { 23void Mouse::OnUpdate(const Core::Timing::CoreTiming& core_timing) {
29 if (!IsControllerActivated()) { 24 if (!IsControllerActivated()) {
30 shared_memory->mouse_lifo.buffer_count = 0; 25 shared_memory.mouse_lifo.buffer_count = 0;
31 shared_memory->mouse_lifo.buffer_tail = 0; 26 shared_memory.mouse_lifo.buffer_tail = 0;
32 return; 27 return;
33 } 28 }
34 29
35 next_state = {}; 30 next_state = {};
36 31
37 const auto& last_entry = shared_memory->mouse_lifo.ReadCurrentEntry().state; 32 const auto& last_entry = shared_memory.mouse_lifo.ReadCurrentEntry().state;
38 next_state.sampling_number = last_entry.sampling_number + 1; 33 next_state.sampling_number = last_entry.sampling_number + 1;
39 34
40 if (Settings::values.mouse_enabled) { 35 if (Settings::values.mouse_enabled) {
@@ -53,7 +48,7 @@ void Mouse::OnUpdate(const Core::Timing::CoreTiming& core_timing) {
53 next_state.button = mouse_button_state; 48 next_state.button = mouse_button_state;
54 } 49 }
55 50
56 shared_memory->mouse_lifo.WriteNextEntry(next_state); 51 shared_memory.mouse_lifo.WriteNextEntry(next_state);
57} 52}
58 53
59} // namespace Service::HID 54} // namespace Service::HID
diff --git a/src/core/hle/service/hid/controllers/mouse.h b/src/core/hle/service/hid/controllers/mouse.h
index a80f3823f..363f316a5 100644
--- a/src/core/hle/service/hid/controllers/mouse.h
+++ b/src/core/hle/service/hid/controllers/mouse.h
@@ -3,9 +3,7 @@
3 3
4#pragma once 4#pragma once
5 5
6#include "common/common_types.h"
7#include "core/hle/service/hid/controllers/controller_base.h" 6#include "core/hle/service/hid/controllers/controller_base.h"
8#include "core/hle/service/hid/ring_lifo.h"
9 7
10namespace Core::HID { 8namespace Core::HID {
11class EmulatedDevices; 9class EmulatedDevices;
@@ -14,9 +12,11 @@ struct AnalogStickState;
14} // namespace Core::HID 12} // namespace Core::HID
15 13
16namespace Service::HID { 14namespace Service::HID {
15struct MouseSharedMemoryFormat;
16
17class Mouse final : public ControllerBase { 17class Mouse final : public ControllerBase {
18public: 18public:
19 explicit Mouse(Core::HID::HIDCore& hid_core_, u8* raw_shared_memory_); 19 explicit Mouse(Core::HID::HIDCore& hid_core_, MouseSharedMemoryFormat& mouse_shared_memory);
20 ~Mouse() override; 20 ~Mouse() override;
21 21
22 // Called when the controller is initialized 22 // Called when the controller is initialized
@@ -29,17 +29,9 @@ public:
29 void OnUpdate(const Core::Timing::CoreTiming& core_timing) override; 29 void OnUpdate(const Core::Timing::CoreTiming& core_timing) override;
30 30
31private: 31private:
32 struct MouseSharedMemory {
33 // This is nn::hid::detail::MouseLifo
34 Lifo<Core::HID::MouseState, hid_entry_count> mouse_lifo{};
35 static_assert(sizeof(mouse_lifo) == 0x350, "mouse_lifo is an invalid size");
36 INSERT_PADDING_WORDS(0x2C);
37 };
38 static_assert(sizeof(MouseSharedMemory) == 0x400, "MouseSharedMemory is an invalid size");
39
40 Core::HID::MouseState next_state{}; 32 Core::HID::MouseState next_state{};
41 Core::HID::AnalogStickState last_mouse_wheel_state{}; 33 Core::HID::AnalogStickState last_mouse_wheel_state{};
42 MouseSharedMemory* shared_memory = nullptr; 34 MouseSharedMemoryFormat& shared_memory;
43 Core::HID::EmulatedDevices* emulated_devices = nullptr; 35 Core::HID::EmulatedDevices* emulated_devices = nullptr;
44}; 36};
45} // namespace Service::HID 37} // namespace Service::HID
diff --git a/src/core/hle/service/hid/controllers/npad.cpp b/src/core/hle/service/hid/controllers/npad.cpp
index 08ee9de9c..53a737cf5 100644
--- a/src/core/hle/service/hid/controllers/npad.cpp
+++ b/src/core/hle/service/hid/controllers/npad.cpp
@@ -17,12 +17,12 @@
17#include "core/hle/kernel/k_event.h" 17#include "core/hle/kernel/k_event.h"
18#include "core/hle/kernel/k_readable_event.h" 18#include "core/hle/kernel/k_readable_event.h"
19#include "core/hle/service/hid/controllers/npad.h" 19#include "core/hle/service/hid/controllers/npad.h"
20#include "core/hle/service/hid/controllers/shared_memory_format.h"
20#include "core/hle/service/hid/errors.h" 21#include "core/hle/service/hid/errors.h"
21#include "core/hle/service/hid/hid_util.h" 22#include "core/hle/service/hid/hid_util.h"
22#include "core/hle/service/kernel_helpers.h" 23#include "core/hle/service/kernel_helpers.h"
23 24
24namespace Service::HID { 25namespace Service::HID {
25constexpr std::size_t NPAD_OFFSET = 0x9A00;
26constexpr std::array<Core::HID::NpadIdType, 10> npad_id_list{ 26constexpr std::array<Core::HID::NpadIdType, 10> npad_id_list{
27 Core::HID::NpadIdType::Player1, Core::HID::NpadIdType::Player2, Core::HID::NpadIdType::Player3, 27 Core::HID::NpadIdType::Player1, Core::HID::NpadIdType::Player2, Core::HID::NpadIdType::Player3,
28 Core::HID::NpadIdType::Player4, Core::HID::NpadIdType::Player5, Core::HID::NpadIdType::Player6, 28 Core::HID::NpadIdType::Player4, Core::HID::NpadIdType::Player5, Core::HID::NpadIdType::Player6,
@@ -30,14 +30,12 @@ constexpr std::array<Core::HID::NpadIdType, 10> npad_id_list{
30 Core::HID::NpadIdType::Handheld, 30 Core::HID::NpadIdType::Handheld,
31}; 31};
32 32
33NPad::NPad(Core::HID::HIDCore& hid_core_, u8* raw_shared_memory_, 33NPad::NPad(Core::HID::HIDCore& hid_core_, NpadSharedMemoryFormat& npad_shared_memory_format,
34 KernelHelpers::ServiceContext& service_context_) 34 KernelHelpers::ServiceContext& service_context_)
35 : ControllerBase{hid_core_}, service_context{service_context_} { 35 : ControllerBase{hid_core_}, service_context{service_context_} {
36 static_assert(NPAD_OFFSET + (NPAD_COUNT * sizeof(NpadInternalState)) < shared_memory_size);
37 for (std::size_t i = 0; i < controller_data.size(); ++i) { 36 for (std::size_t i = 0; i < controller_data.size(); ++i) {
38 auto& controller = controller_data[i]; 37 auto& controller = controller_data[i];
39 controller.shared_memory = std::construct_at(reinterpret_cast<NpadInternalState*>( 38 controller.shared_memory = &npad_shared_memory_format.npad_entry[i].internal_state;
40 raw_shared_memory_ + NPAD_OFFSET + (i * sizeof(NpadInternalState))));
41 controller.device = hid_core.GetEmulatedControllerByIndex(i); 39 controller.device = hid_core.GetEmulatedControllerByIndex(i);
42 controller.vibration[Core::HID::EmulatedDeviceIndex::LeftIndex].latest_vibration_value = 40 controller.vibration[Core::HID::EmulatedDeviceIndex::LeftIndex].latest_vibration_value =
43 Core::HID::DEFAULT_VIBRATION_VALUE; 41 Core::HID::DEFAULT_VIBRATION_VALUE;
@@ -617,7 +615,7 @@ void NPad::SetHoldType(NpadJoyHoldType joy_hold_type) {
617 hold_type = joy_hold_type; 615 hold_type = joy_hold_type;
618} 616}
619 617
620NPad::NpadJoyHoldType NPad::GetHoldType() const { 618NpadJoyHoldType NPad::GetHoldType() const {
621 return hold_type; 619 return hold_type;
622} 620}
623 621
@@ -630,7 +628,7 @@ void NPad::SetNpadHandheldActivationMode(NpadHandheldActivationMode activation_m
630 handheld_activation_mode = activation_mode; 628 handheld_activation_mode = activation_mode;
631} 629}
632 630
633NPad::NpadHandheldActivationMode NPad::GetNpadHandheldActivationMode() const { 631NpadHandheldActivationMode NPad::GetNpadHandheldActivationMode() const {
634 return handheld_activation_mode; 632 return handheld_activation_mode;
635} 633}
636 634
@@ -638,7 +636,7 @@ void NPad::SetNpadCommunicationMode(NpadCommunicationMode communication_mode_) {
638 communication_mode = communication_mode_; 636 communication_mode = communication_mode_;
639} 637}
640 638
641NPad::NpadCommunicationMode NPad::GetNpadCommunicationMode() const { 639NpadCommunicationMode NPad::GetNpadCommunicationMode() const {
642 return communication_mode; 640 return communication_mode;
643} 641}
644 642
@@ -978,27 +976,27 @@ Result NPad::ResetIsSixAxisSensorDeviceNewlyAssigned(
978 return ResultSuccess; 976 return ResultSuccess;
979} 977}
980 978
981NPad::SixAxisLifo& NPad::GetSixAxisFullkeyLifo(Core::HID::NpadIdType npad_id) { 979NpadSixAxisSensorLifo& NPad::GetSixAxisFullkeyLifo(Core::HID::NpadIdType npad_id) {
982 return GetControllerFromNpadIdType(npad_id).shared_memory->sixaxis_fullkey_lifo; 980 return GetControllerFromNpadIdType(npad_id).shared_memory->sixaxis_fullkey_lifo;
983} 981}
984 982
985NPad::SixAxisLifo& NPad::GetSixAxisHandheldLifo(Core::HID::NpadIdType npad_id) { 983NpadSixAxisSensorLifo& NPad::GetSixAxisHandheldLifo(Core::HID::NpadIdType npad_id) {
986 return GetControllerFromNpadIdType(npad_id).shared_memory->sixaxis_handheld_lifo; 984 return GetControllerFromNpadIdType(npad_id).shared_memory->sixaxis_handheld_lifo;
987} 985}
988 986
989NPad::SixAxisLifo& NPad::GetSixAxisDualLeftLifo(Core::HID::NpadIdType npad_id) { 987NpadSixAxisSensorLifo& NPad::GetSixAxisDualLeftLifo(Core::HID::NpadIdType npad_id) {
990 return GetControllerFromNpadIdType(npad_id).shared_memory->sixaxis_dual_left_lifo; 988 return GetControllerFromNpadIdType(npad_id).shared_memory->sixaxis_dual_left_lifo;
991} 989}
992 990
993NPad::SixAxisLifo& NPad::GetSixAxisDualRightLifo(Core::HID::NpadIdType npad_id) { 991NpadSixAxisSensorLifo& NPad::GetSixAxisDualRightLifo(Core::HID::NpadIdType npad_id) {
994 return GetControllerFromNpadIdType(npad_id).shared_memory->sixaxis_dual_right_lifo; 992 return GetControllerFromNpadIdType(npad_id).shared_memory->sixaxis_dual_right_lifo;
995} 993}
996 994
997NPad::SixAxisLifo& NPad::GetSixAxisLeftLifo(Core::HID::NpadIdType npad_id) { 995NpadSixAxisSensorLifo& NPad::GetSixAxisLeftLifo(Core::HID::NpadIdType npad_id) {
998 return GetControllerFromNpadIdType(npad_id).shared_memory->sixaxis_left_lifo; 996 return GetControllerFromNpadIdType(npad_id).shared_memory->sixaxis_left_lifo;
999} 997}
1000 998
1001NPad::SixAxisLifo& NPad::GetSixAxisRightLifo(Core::HID::NpadIdType npad_id) { 999NpadSixAxisSensorLifo& NPad::GetSixAxisRightLifo(Core::HID::NpadIdType npad_id) {
1002 return GetControllerFromNpadIdType(npad_id).shared_memory->sixaxis_right_lifo; 1000 return GetControllerFromNpadIdType(npad_id).shared_memory->sixaxis_right_lifo;
1003} 1001}
1004 1002
@@ -1343,7 +1341,7 @@ const Core::HID::SixAxisSensorProperties& NPad::GetSixaxisProperties(
1343 } 1341 }
1344} 1342}
1345 1343
1346NPad::AppletDetailedUiType NPad::GetAppletDetailedUiType(Core::HID::NpadIdType npad_id) { 1344AppletDetailedUiType NPad::GetAppletDetailedUiType(Core::HID::NpadIdType npad_id) {
1347 const auto& shared_memory = GetControllerFromNpadIdType(npad_id).shared_memory; 1345 const auto& shared_memory = GetControllerFromNpadIdType(npad_id).shared_memory;
1348 1346
1349 return { 1347 return {
diff --git a/src/core/hle/service/hid/controllers/npad.h b/src/core/hle/service/hid/controllers/npad.h
index 9167c93f0..4e2412356 100644
--- a/src/core/hle/service/hid/controllers/npad.h
+++ b/src/core/hle/service/hid/controllers/npad.h
@@ -8,12 +8,10 @@
8#include <mutex> 8#include <mutex>
9#include <span> 9#include <span>
10 10
11#include "common/bit_field.h"
12#include "common/common_types.h" 11#include "common/common_types.h"
13
14#include "core/hid/hid_types.h" 12#include "core/hid/hid_types.h"
15#include "core/hle/service/hid/controllers/controller_base.h" 13#include "core/hle/service/hid/controllers/controller_base.h"
16#include "core/hle/service/hid/ring_lifo.h" 14#include "core/hle/service/hid/controllers/types/npad_types.h"
17 15
18namespace Core::HID { 16namespace Core::HID {
19class EmulatedController; 17class EmulatedController;
@@ -32,10 +30,13 @@ class ServiceContext;
32union Result; 30union Result;
33 31
34namespace Service::HID { 32namespace Service::HID {
33struct NpadInternalState;
34struct NpadSixAxisSensorLifo;
35struct NpadSharedMemoryFormat;
35 36
36class NPad final : public ControllerBase { 37class NPad final : public ControllerBase {
37public: 38public:
38 explicit NPad(Core::HID::HIDCore& hid_core_, u8* raw_shared_memory_, 39 explicit NPad(Core::HID::HIDCore& hid_core_, NpadSharedMemoryFormat& npad_shared_memory_format,
39 KernelHelpers::ServiceContext& service_context_); 40 KernelHelpers::ServiceContext& service_context_);
40 ~NPad() override; 41 ~NPad() override;
41 42
@@ -48,89 +49,6 @@ public:
48 // When the controller is requesting an update for the shared memory 49 // When the controller is requesting an update for the shared memory
49 void OnUpdate(const Core::Timing::CoreTiming& core_timing) override; 50 void OnUpdate(const Core::Timing::CoreTiming& core_timing) override;
50 51
51 // This is nn::hid::NpadJoyHoldType
52 enum class NpadJoyHoldType : u64 {
53 Vertical = 0,
54 Horizontal = 1,
55 };
56
57 // This is nn::hid::NpadJoyAssignmentMode
58 enum class NpadJoyAssignmentMode : u32 {
59 Dual = 0,
60 Single = 1,
61 };
62
63 // This is nn::hid::NpadJoyDeviceType
64 enum class NpadJoyDeviceType : s64 {
65 Left = 0,
66 Right = 1,
67 };
68
69 // This is nn::hid::NpadHandheldActivationMode
70 enum class NpadHandheldActivationMode : u64 {
71 Dual = 0,
72 Single = 1,
73 None = 2,
74 MaxActivationMode = 3,
75 };
76
77 // This is nn::hid::system::AppletFooterUiAttributesSet
78 struct AppletFooterUiAttributes {
79 INSERT_PADDING_BYTES(0x4);
80 };
81
82 // This is nn::hid::system::AppletFooterUiType
83 enum class AppletFooterUiType : u8 {
84 None = 0,
85 HandheldNone = 1,
86 HandheldJoyConLeftOnly = 2,
87 HandheldJoyConRightOnly = 3,
88 HandheldJoyConLeftJoyConRight = 4,
89 JoyDual = 5,
90 JoyDualLeftOnly = 6,
91 JoyDualRightOnly = 7,
92 JoyLeftHorizontal = 8,
93 JoyLeftVertical = 9,
94 JoyRightHorizontal = 10,
95 JoyRightVertical = 11,
96 SwitchProController = 12,
97 CompatibleProController = 13,
98 CompatibleJoyCon = 14,
99 LarkHvc1 = 15,
100 LarkHvc2 = 16,
101 LarkNesLeft = 17,
102 LarkNesRight = 18,
103 Lucia = 19,
104 Verification = 20,
105 Lagon = 21,
106 };
107
108 using AppletFooterUiVariant = u8;
109
110 // This is "nn::hid::system::AppletDetailedUiType".
111 struct AppletDetailedUiType {
112 AppletFooterUiVariant ui_variant;
113 INSERT_PADDING_BYTES(0x2);
114 AppletFooterUiType footer;
115 };
116 static_assert(sizeof(AppletDetailedUiType) == 0x4, "AppletDetailedUiType is an invalid size");
117 // This is nn::hid::NpadCommunicationMode
118 enum class NpadCommunicationMode : u64 {
119 Mode_5ms = 0,
120 Mode_10ms = 1,
121 Mode_15ms = 2,
122 Default = 3,
123 };
124
125 enum class NpadRevision : u32 {
126 Revision0 = 0,
127 Revision1 = 1,
128 Revision2 = 2,
129 Revision3 = 3,
130 };
131
132 using SixAxisLifo = Lifo<Core::HID::SixAxisSensorState, hid_entry_count>;
133
134 void SetSupportedStyleSet(Core::HID::NpadStyleTag style_set); 52 void SetSupportedStyleSet(Core::HID::NpadStyleTag style_set);
135 Core::HID::NpadStyleTag GetSupportedStyleSet() const; 53 Core::HID::NpadStyleTag GetSupportedStyleSet() const;
136 54
@@ -188,12 +106,12 @@ public:
188 Result ResetIsSixAxisSensorDeviceNewlyAssigned( 106 Result ResetIsSixAxisSensorDeviceNewlyAssigned(
189 const Core::HID::SixAxisSensorHandle& sixaxis_handle); 107 const Core::HID::SixAxisSensorHandle& sixaxis_handle);
190 108
191 SixAxisLifo& GetSixAxisFullkeyLifo(Core::HID::NpadIdType npad_id); 109 NpadSixAxisSensorLifo& GetSixAxisFullkeyLifo(Core::HID::NpadIdType npad_id);
192 SixAxisLifo& GetSixAxisHandheldLifo(Core::HID::NpadIdType npad_id); 110 NpadSixAxisSensorLifo& GetSixAxisHandheldLifo(Core::HID::NpadIdType npad_id);
193 SixAxisLifo& GetSixAxisDualLeftLifo(Core::HID::NpadIdType npad_id); 111 NpadSixAxisSensorLifo& GetSixAxisDualLeftLifo(Core::HID::NpadIdType npad_id);
194 SixAxisLifo& GetSixAxisDualRightLifo(Core::HID::NpadIdType npad_id); 112 NpadSixAxisSensorLifo& GetSixAxisDualRightLifo(Core::HID::NpadIdType npad_id);
195 SixAxisLifo& GetSixAxisLeftLifo(Core::HID::NpadIdType npad_id); 113 NpadSixAxisSensorLifo& GetSixAxisLeftLifo(Core::HID::NpadIdType npad_id);
196 SixAxisLifo& GetSixAxisRightLifo(Core::HID::NpadIdType npad_id); 114 NpadSixAxisSensorLifo& GetSixAxisRightLifo(Core::HID::NpadIdType npad_id);
197 115
198 Result GetLedPattern(Core::HID::NpadIdType npad_id, Core::HID::LedPattern& pattern) const; 116 Result GetLedPattern(Core::HID::NpadIdType npad_id, Core::HID::LedPattern& pattern) const;
199 Result IsUnintendedHomeButtonInputProtectionEnabled(Core::HID::NpadIdType npad_id, 117 Result IsUnintendedHomeButtonInputProtectionEnabled(Core::HID::NpadIdType npad_id,
@@ -221,214 +139,6 @@ public:
221 AppletDetailedUiType GetAppletDetailedUiType(Core::HID::NpadIdType npad_id); 139 AppletDetailedUiType GetAppletDetailedUiType(Core::HID::NpadIdType npad_id);
222 140
223private: 141private:
224 static constexpr std::size_t NPAD_COUNT = 10;
225
226 // This is nn::hid::detail::ColorAttribute
227 enum class ColorAttribute : u32 {
228 Ok = 0,
229 ReadError = 1,
230 NoController = 2,
231 };
232 static_assert(sizeof(ColorAttribute) == 4, "ColorAttribute is an invalid size");
233
234 // This is nn::hid::detail::NpadFullKeyColorState
235 struct NpadFullKeyColorState {
236 ColorAttribute attribute{ColorAttribute::NoController};
237 Core::HID::NpadControllerColor fullkey{};
238 };
239 static_assert(sizeof(NpadFullKeyColorState) == 0xC, "NpadFullKeyColorState is an invalid size");
240
241 // This is nn::hid::detail::NpadJoyColorState
242 struct NpadJoyColorState {
243 ColorAttribute attribute{ColorAttribute::NoController};
244 Core::HID::NpadControllerColor left{};
245 Core::HID::NpadControllerColor right{};
246 };
247 static_assert(sizeof(NpadJoyColorState) == 0x14, "NpadJoyColorState is an invalid size");
248
249 // This is nn::hid::NpadAttribute
250 struct NpadAttribute {
251 union {
252 u32 raw{};
253 BitField<0, 1, u32> is_connected;
254 BitField<1, 1, u32> is_wired;
255 BitField<2, 1, u32> is_left_connected;
256 BitField<3, 1, u32> is_left_wired;
257 BitField<4, 1, u32> is_right_connected;
258 BitField<5, 1, u32> is_right_wired;
259 };
260 };
261 static_assert(sizeof(NpadAttribute) == 4, "NpadAttribute is an invalid size");
262
263 // This is nn::hid::NpadFullKeyState
264 // This is nn::hid::NpadHandheldState
265 // This is nn::hid::NpadJoyDualState
266 // This is nn::hid::NpadJoyLeftState
267 // This is nn::hid::NpadJoyRightState
268 // This is nn::hid::NpadPalmaState
269 // This is nn::hid::NpadSystemExtState
270 struct NPadGenericState {
271 s64_le sampling_number{};
272 Core::HID::NpadButtonState npad_buttons{};
273 Core::HID::AnalogStickState l_stick{};
274 Core::HID::AnalogStickState r_stick{};
275 NpadAttribute connection_status{};
276 INSERT_PADDING_BYTES(4); // Reserved
277 };
278 static_assert(sizeof(NPadGenericState) == 0x28, "NPadGenericState is an invalid size");
279
280 // This is nn::hid::server::NpadGcTriggerState
281 struct NpadGcTriggerState {
282 s64 sampling_number{};
283 s32 l_analog{};
284 s32 r_analog{};
285 };
286 static_assert(sizeof(NpadGcTriggerState) == 0x10, "NpadGcTriggerState is an invalid size");
287
288 // This is nn::hid::NpadSystemProperties
289 struct NPadSystemProperties {
290 union {
291 s64 raw{};
292 BitField<0, 1, s64> is_charging_joy_dual;
293 BitField<1, 1, s64> is_charging_joy_left;
294 BitField<2, 1, s64> is_charging_joy_right;
295 BitField<3, 1, s64> is_powered_joy_dual;
296 BitField<4, 1, s64> is_powered_joy_left;
297 BitField<5, 1, s64> is_powered_joy_right;
298 BitField<9, 1, s64> is_system_unsupported_button;
299 BitField<10, 1, s64> is_system_ext_unsupported_button;
300 BitField<11, 1, s64> is_vertical;
301 BitField<12, 1, s64> is_horizontal;
302 BitField<13, 1, s64> use_plus;
303 BitField<14, 1, s64> use_minus;
304 BitField<15, 1, s64> use_directional_buttons;
305 };
306 };
307 static_assert(sizeof(NPadSystemProperties) == 0x8, "NPadSystemProperties is an invalid size");
308
309 // This is nn::hid::NpadSystemButtonProperties
310 struct NpadSystemButtonProperties {
311 union {
312 s32 raw{};
313 BitField<0, 1, s32> is_home_button_protection_enabled;
314 };
315 };
316 static_assert(sizeof(NpadSystemButtonProperties) == 0x4,
317 "NPadButtonProperties is an invalid size");
318
319 // This is nn::hid::system::DeviceType
320 struct DeviceType {
321 union {
322 u32 raw{};
323 BitField<0, 1, s32> fullkey;
324 BitField<1, 1, s32> debug_pad;
325 BitField<2, 1, s32> handheld_left;
326 BitField<3, 1, s32> handheld_right;
327 BitField<4, 1, s32> joycon_left;
328 BitField<5, 1, s32> joycon_right;
329 BitField<6, 1, s32> palma;
330 BitField<7, 1, s32> lark_hvc_left;
331 BitField<8, 1, s32> lark_hvc_right;
332 BitField<9, 1, s32> lark_nes_left;
333 BitField<10, 1, s32> lark_nes_right;
334 BitField<11, 1, s32> handheld_lark_hvc_left;
335 BitField<12, 1, s32> handheld_lark_hvc_right;
336 BitField<13, 1, s32> handheld_lark_nes_left;
337 BitField<14, 1, s32> handheld_lark_nes_right;
338 BitField<15, 1, s32> lucia;
339 BitField<16, 1, s32> lagon;
340 BitField<17, 1, s32> lager;
341 BitField<31, 1, s32> system;
342 };
343 };
344
345 // This is nn::hid::detail::NfcXcdDeviceHandleStateImpl
346 struct NfcXcdDeviceHandleStateImpl {
347 u64 handle{};
348 bool is_available{};
349 bool is_activated{};
350 INSERT_PADDING_BYTES(0x6); // Reserved
351 u64 sampling_number{};
352 };
353 static_assert(sizeof(NfcXcdDeviceHandleStateImpl) == 0x18,
354 "NfcXcdDeviceHandleStateImpl is an invalid size");
355
356 // This is nn::hid::NpadLarkType
357 enum class NpadLarkType : u32 {
358 Invalid,
359 H1,
360 H2,
361 NL,
362 NR,
363 };
364
365 // This is nn::hid::NpadLuciaType
366 enum class NpadLuciaType : u32 {
367 Invalid,
368 J,
369 E,
370 U,
371 };
372
373 // This is nn::hid::NpadLagonType
374 enum class NpadLagonType : u32 {
375 Invalid,
376 };
377
378 // This is nn::hid::NpadLagerType
379 enum class NpadLagerType : u32 {
380 Invalid,
381 J,
382 E,
383 U,
384 };
385
386 // This is nn::hid::detail::NpadInternalState
387 struct NpadInternalState {
388 Core::HID::NpadStyleTag style_tag{Core::HID::NpadStyleSet::None};
389 NpadJoyAssignmentMode assignment_mode{NpadJoyAssignmentMode::Dual};
390 NpadFullKeyColorState fullkey_color{};
391 NpadJoyColorState joycon_color{};
392 Lifo<NPadGenericState, hid_entry_count> fullkey_lifo{};
393 Lifo<NPadGenericState, hid_entry_count> handheld_lifo{};
394 Lifo<NPadGenericState, hid_entry_count> joy_dual_lifo{};
395 Lifo<NPadGenericState, hid_entry_count> joy_left_lifo{};
396 Lifo<NPadGenericState, hid_entry_count> joy_right_lifo{};
397 Lifo<NPadGenericState, hid_entry_count> palma_lifo{};
398 Lifo<NPadGenericState, hid_entry_count> system_ext_lifo{};
399 Lifo<Core::HID::SixAxisSensorState, hid_entry_count> sixaxis_fullkey_lifo{};
400 Lifo<Core::HID::SixAxisSensorState, hid_entry_count> sixaxis_handheld_lifo{};
401 Lifo<Core::HID::SixAxisSensorState, hid_entry_count> sixaxis_dual_left_lifo{};
402 Lifo<Core::HID::SixAxisSensorState, hid_entry_count> sixaxis_dual_right_lifo{};
403 Lifo<Core::HID::SixAxisSensorState, hid_entry_count> sixaxis_left_lifo{};
404 Lifo<Core::HID::SixAxisSensorState, hid_entry_count> sixaxis_right_lifo{};
405 DeviceType device_type{};
406 INSERT_PADDING_BYTES(0x4); // Reserved
407 NPadSystemProperties system_properties{};
408 NpadSystemButtonProperties button_properties{};
409 Core::HID::NpadBatteryLevel battery_level_dual{};
410 Core::HID::NpadBatteryLevel battery_level_left{};
411 Core::HID::NpadBatteryLevel battery_level_right{};
412 AppletFooterUiAttributes applet_footer_attributes{};
413 AppletFooterUiType applet_footer_type{AppletFooterUiType::None};
414 INSERT_PADDING_BYTES(0x5B); // Reserved
415 INSERT_PADDING_BYTES(0x20); // Unknown
416 Lifo<NpadGcTriggerState, hid_entry_count> gc_trigger_lifo{};
417 NpadLarkType lark_type_l_and_main{};
418 NpadLarkType lark_type_r{};
419 NpadLuciaType lucia_type{};
420 NpadLagonType lagon_type{};
421 NpadLagerType lager_type{};
422 Core::HID::SixAxisSensorProperties sixaxis_fullkey_properties;
423 Core::HID::SixAxisSensorProperties sixaxis_handheld_properties;
424 Core::HID::SixAxisSensorProperties sixaxis_dual_left_properties;
425 Core::HID::SixAxisSensorProperties sixaxis_dual_right_properties;
426 Core::HID::SixAxisSensorProperties sixaxis_left_properties;
427 Core::HID::SixAxisSensorProperties sixaxis_right_properties;
428 INSERT_PADDING_BYTES(0xc06); // Unknown
429 };
430 static_assert(sizeof(NpadInternalState) == 0x5000, "NpadInternalState is an invalid size");
431
432 struct VibrationData { 142 struct VibrationData {
433 bool device_mounted{}; 143 bool device_mounted{};
434 Core::HID::VibrationValue latest_vibration_value{}; 144 Core::HID::VibrationValue latest_vibration_value{};
@@ -479,7 +189,7 @@ private:
479 189
480 std::atomic<u64> press_state{}; 190 std::atomic<u64> press_state{};
481 191
482 std::array<NpadControllerData, NPAD_COUNT> controller_data{}; 192 std::array<NpadControllerData, NpadCount> controller_data{};
483 KernelHelpers::ServiceContext& service_context; 193 KernelHelpers::ServiceContext& service_context;
484 std::mutex mutex; 194 std::mutex mutex;
485 std::vector<Core::HID::NpadIdType> supported_npad_id_types{}; 195 std::vector<Core::HID::NpadIdType> supported_npad_id_types{};
diff --git a/src/core/hle/service/hid/controllers/palma.cpp b/src/core/hle/service/hid/controllers/palma.cpp
index 588ff9d62..aa0454b5e 100644
--- a/src/core/hle/service/hid/controllers/palma.cpp
+++ b/src/core/hle/service/hid/controllers/palma.cpp
@@ -12,8 +12,7 @@
12 12
13namespace Service::HID { 13namespace Service::HID {
14 14
15Palma::Palma(Core::HID::HIDCore& hid_core_, u8* raw_shared_memory_, 15Palma::Palma(Core::HID::HIDCore& hid_core_, KernelHelpers::ServiceContext& service_context_)
16 KernelHelpers::ServiceContext& service_context_)
17 : ControllerBase{hid_core_}, service_context{service_context_} { 16 : ControllerBase{hid_core_}, service_context{service_context_} {
18 controller = hid_core.GetEmulatedController(Core::HID::NpadIdType::Other); 17 controller = hid_core.GetEmulatedController(Core::HID::NpadIdType::Other);
19 operation_complete_event = service_context.CreateEvent("hid:PalmaOperationCompleteEvent"); 18 operation_complete_event = service_context.CreateEvent("hid:PalmaOperationCompleteEvent");
diff --git a/src/core/hle/service/hid/controllers/palma.h b/src/core/hle/service/hid/controllers/palma.h
index a6047f36a..73884230d 100644
--- a/src/core/hle/service/hid/controllers/palma.h
+++ b/src/core/hle/service/hid/controllers/palma.h
@@ -97,8 +97,7 @@ public:
97 static_assert(sizeof(PalmaConnectionHandle) == 0x8, 97 static_assert(sizeof(PalmaConnectionHandle) == 0x8,
98 "PalmaConnectionHandle has incorrect size."); 98 "PalmaConnectionHandle has incorrect size.");
99 99
100 explicit Palma(Core::HID::HIDCore& hid_core_, u8* raw_shared_memory_, 100 explicit Palma(Core::HID::HIDCore& hid_core_, KernelHelpers::ServiceContext& service_context_);
101 KernelHelpers::ServiceContext& service_context_);
102 ~Palma() override; 101 ~Palma() override;
103 102
104 // Called when the controller is initialized 103 // Called when the controller is initialized
diff --git a/src/core/hle/service/hid/controllers/shared_memory_format.h b/src/core/hle/service/hid/controllers/shared_memory_format.h
new file mode 100644
index 000000000..2986c113e
--- /dev/null
+++ b/src/core/hle/service/hid/controllers/shared_memory_format.h
@@ -0,0 +1,240 @@
1// SPDX-FileCopyrightText: Copyright 2023 yuzu Emulator Project
2// SPDX-License-Identifier: GPL-3.0-or-later
3
4#pragma once
5
6#include "common/common_funcs.h"
7#include "common/common_types.h"
8#include "common/vector_math.h"
9#include "core/hid/hid_types.h"
10#include "core/hle/service/hid//controllers/types/debug_pad_types.h"
11#include "core/hle/service/hid//controllers/types/keyboard_types.h"
12#include "core/hle/service/hid//controllers/types/mouse_types.h"
13#include "core/hle/service/hid//controllers/types/npad_types.h"
14#include "core/hle/service/hid//controllers/types/touch_types.h"
15#include "core/hle/service/hid/ring_lifo.h"
16
17namespace Service::HID {
18static const std::size_t HidEntryCount = 17;
19
20struct CommonHeader {
21 s64 timestamp{};
22 s64 total_entry_count{};
23 s64 last_entry_index{};
24 s64 entry_count{};
25};
26static_assert(sizeof(CommonHeader) == 0x20, "CommonHeader is an invalid size");
27
28// This is nn::hid::detail::DebugPadSharedMemoryFormat
29struct DebugPadSharedMemoryFormat {
30 // This is nn::hid::detail::DebugPadLifo
31 Lifo<DebugPadState, HidEntryCount> debug_pad_lifo{};
32 static_assert(sizeof(debug_pad_lifo) == 0x2C8, "debug_pad_lifo is an invalid size");
33 INSERT_PADDING_WORDS(0x4E);
34};
35static_assert(sizeof(DebugPadSharedMemoryFormat) == 0x400,
36 "DebugPadSharedMemoryFormat is an invalid size");
37
38// This is nn::hid::detail::TouchScreenSharedMemoryFormat
39struct TouchScreenSharedMemoryFormat {
40 // This is nn::hid::detail::TouchScreenLifo
41 Lifo<TouchScreenState, HidEntryCount> touch_screen_lifo{};
42 static_assert(sizeof(touch_screen_lifo) == 0x2C38, "touch_screen_lifo is an invalid size");
43 INSERT_PADDING_WORDS(0xF2);
44};
45static_assert(sizeof(TouchScreenSharedMemoryFormat) == 0x3000,
46 "TouchScreenSharedMemoryFormat is an invalid size");
47
48// This is nn::hid::detail::MouseSharedMemoryFormat
49struct MouseSharedMemoryFormat {
50 // This is nn::hid::detail::MouseLifo
51 Lifo<Core::HID::MouseState, HidEntryCount> mouse_lifo{};
52 static_assert(sizeof(mouse_lifo) == 0x350, "mouse_lifo is an invalid size");
53 INSERT_PADDING_WORDS(0x2C);
54};
55static_assert(sizeof(MouseSharedMemoryFormat) == 0x400,
56 "MouseSharedMemoryFormat is an invalid size");
57
58// This is nn::hid::detail::KeyboardSharedMemoryFormat
59struct KeyboardSharedMemoryFormat {
60 // This is nn::hid::detail::KeyboardLifo
61 Lifo<KeyboardState, HidEntryCount> keyboard_lifo{};
62 static_assert(sizeof(keyboard_lifo) == 0x3D8, "keyboard_lifo is an invalid size");
63 INSERT_PADDING_WORDS(0xA);
64};
65static_assert(sizeof(KeyboardSharedMemoryFormat) == 0x400,
66 "KeyboardSharedMemoryFormat is an invalid size");
67
68// This is nn::hid::detail::DigitizerSharedMemoryFormat
69struct DigitizerSharedMemoryFormat {
70 CommonHeader header;
71 INSERT_PADDING_BYTES(0xFE0);
72};
73static_assert(sizeof(DigitizerSharedMemoryFormat) == 0x1000,
74 "DigitizerSharedMemoryFormat is an invalid size");
75
76// This is nn::hid::detail::HomeButtonSharedMemoryFormat
77struct HomeButtonSharedMemoryFormat {
78 CommonHeader header;
79 INSERT_PADDING_BYTES(0x1E0);
80};
81static_assert(sizeof(HomeButtonSharedMemoryFormat) == 0x200,
82 "HomeButtonSharedMemoryFormat is an invalid size");
83
84// This is nn::hid::detail::SleepButtonSharedMemoryFormat
85struct SleepButtonSharedMemoryFormat {
86 CommonHeader header;
87 INSERT_PADDING_BYTES(0x1E0);
88};
89static_assert(sizeof(SleepButtonSharedMemoryFormat) == 0x200,
90 "SleepButtonSharedMemoryFormat is an invalid size");
91
92// This is nn::hid::detail::CaptureButtonSharedMemoryFormat
93struct CaptureButtonSharedMemoryFormat {
94 CommonHeader header;
95 INSERT_PADDING_BYTES(0x1E0);
96};
97static_assert(sizeof(CaptureButtonSharedMemoryFormat) == 0x200,
98 "CaptureButtonSharedMemoryFormat is an invalid size");
99
100// This is nn::hid::detail::InputDetectorSharedMemoryFormat
101struct InputDetectorSharedMemoryFormat {
102 CommonHeader header;
103 INSERT_PADDING_BYTES(0x7E0);
104};
105static_assert(sizeof(InputDetectorSharedMemoryFormat) == 0x800,
106 "InputDetectorSharedMemoryFormat is an invalid size");
107
108// This is nn::hid::detail::UniquePadSharedMemoryFormat
109struct UniquePadSharedMemoryFormat {
110 CommonHeader header;
111 INSERT_PADDING_BYTES(0x3FE0);
112};
113static_assert(sizeof(UniquePadSharedMemoryFormat) == 0x4000,
114 "UniquePadSharedMemoryFormat is an invalid size");
115
116// This is nn::hid::detail::NpadSixAxisSensorLifo
117struct NpadSixAxisSensorLifo {
118 Lifo<Core::HID::SixAxisSensorState, HidEntryCount> lifo;
119};
120
121// This is nn::hid::detail::NpadInternalState
122struct NpadInternalState {
123 Core::HID::NpadStyleTag style_tag{Core::HID::NpadStyleSet::None};
124 NpadJoyAssignmentMode assignment_mode{NpadJoyAssignmentMode::Dual};
125 NpadFullKeyColorState fullkey_color{};
126 NpadJoyColorState joycon_color{};
127 Lifo<NPadGenericState, HidEntryCount> fullkey_lifo{};
128 Lifo<NPadGenericState, HidEntryCount> handheld_lifo{};
129 Lifo<NPadGenericState, HidEntryCount> joy_dual_lifo{};
130 Lifo<NPadGenericState, HidEntryCount> joy_left_lifo{};
131 Lifo<NPadGenericState, HidEntryCount> joy_right_lifo{};
132 Lifo<NPadGenericState, HidEntryCount> palma_lifo{};
133 Lifo<NPadGenericState, HidEntryCount> system_ext_lifo{};
134 NpadSixAxisSensorLifo sixaxis_fullkey_lifo{};
135 NpadSixAxisSensorLifo sixaxis_handheld_lifo{};
136 NpadSixAxisSensorLifo sixaxis_dual_left_lifo{};
137 NpadSixAxisSensorLifo sixaxis_dual_right_lifo{};
138 NpadSixAxisSensorLifo sixaxis_left_lifo{};
139 NpadSixAxisSensorLifo sixaxis_right_lifo{};
140 DeviceType device_type{};
141 INSERT_PADDING_BYTES(0x4); // Reserved
142 NPadSystemProperties system_properties{};
143 NpadSystemButtonProperties button_properties{};
144 Core::HID::NpadBatteryLevel battery_level_dual{};
145 Core::HID::NpadBatteryLevel battery_level_left{};
146 Core::HID::NpadBatteryLevel battery_level_right{};
147 AppletFooterUiAttributes applet_footer_attributes{};
148 AppletFooterUiType applet_footer_type{AppletFooterUiType::None};
149 INSERT_PADDING_BYTES(0x5B); // Reserved
150 INSERT_PADDING_BYTES(0x20); // Unknown
151 Lifo<NpadGcTriggerState, HidEntryCount> gc_trigger_lifo{};
152 NpadLarkType lark_type_l_and_main{};
153 NpadLarkType lark_type_r{};
154 NpadLuciaType lucia_type{};
155 NpadLagerType lager_type{};
156 Core::HID::SixAxisSensorProperties sixaxis_fullkey_properties;
157 Core::HID::SixAxisSensorProperties sixaxis_handheld_properties;
158 Core::HID::SixAxisSensorProperties sixaxis_dual_left_properties;
159 Core::HID::SixAxisSensorProperties sixaxis_dual_right_properties;
160 Core::HID::SixAxisSensorProperties sixaxis_left_properties;
161 Core::HID::SixAxisSensorProperties sixaxis_right_properties;
162};
163static_assert(sizeof(NpadInternalState) == 0x43F8, "NpadInternalState is an invalid size");
164
165// This is nn::hid::detail::NpadSharedMemoryEntry
166struct NpadSharedMemoryEntry {
167 NpadInternalState internal_state;
168 INSERT_PADDING_BYTES(0xC08);
169};
170static_assert(sizeof(NpadSharedMemoryEntry) == 0x5000, "NpadSharedMemoryEntry is an invalid size");
171
172// This is nn::hid::detail::NpadSharedMemoryFormat
173struct NpadSharedMemoryFormat {
174 std::array<NpadSharedMemoryEntry, NpadCount> npad_entry;
175};
176static_assert(sizeof(NpadSharedMemoryFormat) == 0x32000,
177 "NpadSharedMemoryFormat is an invalid size");
178
179// This is nn::hid::detail::GestureSharedMemoryFormat
180struct GestureSharedMemoryFormat {
181 // This is nn::hid::detail::GestureLifo
182 Lifo<GestureState, HidEntryCount> gesture_lifo{};
183 static_assert(sizeof(gesture_lifo) == 0x708, "gesture_lifo is an invalid size");
184 INSERT_PADDING_WORDS(0x3E);
185};
186static_assert(sizeof(GestureSharedMemoryFormat) == 0x800,
187 "GestureSharedMemoryFormat is an invalid size");
188
189// This is nn::hid::detail::ConsoleSixAxisSensorSharedMemoryFormat
190struct ConsoleSixAxisSensorSharedMemoryFormat {
191 u64 sampling_number{};
192 bool is_seven_six_axis_sensor_at_rest{};
193 INSERT_PADDING_BYTES(3); // padding
194 f32 verticalization_error{};
195 Common::Vec3f gyro_bias{};
196 INSERT_PADDING_BYTES(4); // padding
197};
198static_assert(sizeof(ConsoleSixAxisSensorSharedMemoryFormat) == 0x20,
199 "ConsoleSixAxisSensorSharedMemoryFormat is an invalid size");
200
201// This is nn::hid::detail::SharedMemoryFormat
202struct SharedMemoryFormat {
203 void Initialize() {}
204
205 DebugPadSharedMemoryFormat debug_pad;
206 TouchScreenSharedMemoryFormat touch_screen;
207 MouseSharedMemoryFormat mouse;
208 KeyboardSharedMemoryFormat keyboard;
209 DigitizerSharedMemoryFormat digitizer;
210 HomeButtonSharedMemoryFormat home_button;
211 SleepButtonSharedMemoryFormat sleep_button;
212 CaptureButtonSharedMemoryFormat capture_button;
213 InputDetectorSharedMemoryFormat input_detector;
214 UniquePadSharedMemoryFormat unique_pad;
215 NpadSharedMemoryFormat npad;
216 GestureSharedMemoryFormat gesture;
217 ConsoleSixAxisSensorSharedMemoryFormat console;
218 INSERT_PADDING_BYTES(0x19E0);
219 MouseSharedMemoryFormat debug_mouse;
220 INSERT_PADDING_BYTES(0x2000);
221};
222static_assert(offsetof(SharedMemoryFormat, debug_pad) == 0x0, "debug_pad has wrong offset");
223static_assert(offsetof(SharedMemoryFormat, touch_screen) == 0x400, "touch_screen has wrong offset");
224static_assert(offsetof(SharedMemoryFormat, mouse) == 0x3400, "mouse has wrong offset");
225static_assert(offsetof(SharedMemoryFormat, keyboard) == 0x3800, "keyboard has wrong offset");
226static_assert(offsetof(SharedMemoryFormat, digitizer) == 0x3C00, "digitizer has wrong offset");
227static_assert(offsetof(SharedMemoryFormat, home_button) == 0x4C00, "home_button has wrong offset");
228static_assert(offsetof(SharedMemoryFormat, sleep_button) == 0x4E00,
229 "sleep_button has wrong offset");
230static_assert(offsetof(SharedMemoryFormat, capture_button) == 0x5000,
231 "capture_button has wrong offset");
232static_assert(offsetof(SharedMemoryFormat, input_detector) == 0x5200,
233 "input_detector has wrong offset");
234static_assert(offsetof(SharedMemoryFormat, npad) == 0x9A00, "npad has wrong offset");
235static_assert(offsetof(SharedMemoryFormat, gesture) == 0x3BA00, "gesture has wrong offset");
236static_assert(offsetof(SharedMemoryFormat, console) == 0x3C200, "console has wrong offset");
237static_assert(offsetof(SharedMemoryFormat, debug_mouse) == 0x3DC00, "debug_mouse has wrong offset");
238static_assert(sizeof(SharedMemoryFormat) == 0x40000, "SharedMemoryFormat is an invalid size");
239
240} // namespace Service::HID
diff --git a/src/core/hle/service/hid/controllers/shared_memory_holder.cpp b/src/core/hle/service/hid/controllers/shared_memory_holder.cpp
new file mode 100644
index 000000000..51581188e
--- /dev/null
+++ b/src/core/hle/service/hid/controllers/shared_memory_holder.cpp
@@ -0,0 +1,53 @@
1// SPDX-FileCopyrightText: Copyright 2023 yuzu Emulator Project
2// SPDX-License-Identifier: GPL-3.0-or-later
3
4#include "core/core.h"
5#include "core/hle/kernel/k_shared_memory.h"
6#include "core/hle/service/hid/controllers/shared_memory_format.h"
7#include "core/hle/service/hid/controllers/shared_memory_holder.h"
8#include "core/hle/service/hid/errors.h"
9
10namespace Service::HID {
11SharedMemoryHolder::SharedMemoryHolder() {}
12
13SharedMemoryHolder::~SharedMemoryHolder() {
14 Finalize();
15}
16
17Result SharedMemoryHolder::Initialize(Core::System& system) {
18 shared_memory = Kernel::KSharedMemory::Create(system.Kernel());
19 const Result result = shared_memory->Initialize(
20 system.DeviceMemory(), nullptr, Kernel::Svc::MemoryPermission::None,
21 Kernel::Svc::MemoryPermission::Read, sizeof(SharedMemoryFormat));
22 if (result.IsError()) {
23 return result;
24 }
25 Kernel::KSharedMemory::Register(system.Kernel(), shared_memory);
26
27 is_created = true;
28 is_mapped = true;
29 address = std::construct_at(reinterpret_cast<SharedMemoryFormat*>(shared_memory->GetPointer()));
30 return ResultSuccess;
31}
32
33void SharedMemoryHolder::Finalize() {
34 if (address != nullptr) {
35 shared_memory->Close();
36 }
37 is_created = false;
38 is_mapped = false;
39 address = nullptr;
40}
41
42bool SharedMemoryHolder::IsMapped() {
43 return is_mapped;
44}
45
46SharedMemoryFormat* SharedMemoryHolder::GetAddress() {
47 return address;
48}
49
50Kernel::KSharedMemory* SharedMemoryHolder::GetHandle() {
51 return shared_memory;
52}
53} // namespace Service::HID
diff --git a/src/core/hle/service/hid/controllers/shared_memory_holder.h b/src/core/hle/service/hid/controllers/shared_memory_holder.h
new file mode 100644
index 000000000..943407c00
--- /dev/null
+++ b/src/core/hle/service/hid/controllers/shared_memory_holder.h
@@ -0,0 +1,44 @@
1// SPDX-FileCopyrightText: Copyright 2023 yuzu Emulator Project
2// SPDX-License-Identifier: GPL-3.0-or-later
3
4#pragma once
5
6#include "core/hle/result.h"
7
8namespace Core {
9class System;
10}
11
12namespace Kernel {
13class KSharedMemory;
14}
15
16namespace Service::HID {
17struct SharedMemoryFormat;
18
19// This is nn::hid::detail::SharedMemoryHolder
20class SharedMemoryHolder {
21public:
22 SharedMemoryHolder();
23 ~SharedMemoryHolder();
24
25 Result Initialize(Core::System& system);
26 void Finalize();
27
28 bool IsMapped();
29 SharedMemoryFormat* GetAddress();
30 Kernel::KSharedMemory* GetHandle();
31
32private:
33 bool is_owner{};
34 bool is_created{};
35 bool is_mapped{};
36 INSERT_PADDING_BYTES(0x5);
37 Kernel::KSharedMemory* shared_memory;
38 INSERT_PADDING_BYTES(0x38);
39 SharedMemoryFormat* address = nullptr;
40};
41// Correct size is 0x50 bytes
42static_assert(sizeof(SharedMemoryHolder) == 0x50, "SharedMemoryHolder is an invalid size");
43
44} // namespace Service::HID
diff --git a/src/core/hle/service/hid/controllers/six_axis.cpp b/src/core/hle/service/hid/controllers/six_axis.cpp
index 3d24a5c04..36b72f9ea 100644
--- a/src/core/hle/service/hid/controllers/six_axis.cpp
+++ b/src/core/hle/service/hid/controllers/six_axis.cpp
@@ -6,6 +6,7 @@
6#include "core/hid/emulated_controller.h" 6#include "core/hid/emulated_controller.h"
7#include "core/hid/hid_core.h" 7#include "core/hid/hid_core.h"
8#include "core/hle/service/hid/controllers/npad.h" 8#include "core/hle/service/hid/controllers/npad.h"
9#include "core/hle/service/hid/controllers/shared_memory_format.h"
9#include "core/hle/service/hid/controllers/six_axis.h" 10#include "core/hle/service/hid/controllers/six_axis.h"
10#include "core/hle/service/hid/errors.h" 11#include "core/hle/service/hid/errors.h"
11#include "core/hle/service/hid/hid_util.h" 12#include "core/hle/service/hid/hid_util.h"
@@ -132,30 +133,30 @@ void SixAxis::OnUpdate(const Core::Timing::CoreTiming& core_timing) {
132 } 133 }
133 134
134 sixaxis_fullkey_state.sampling_number = 135 sixaxis_fullkey_state.sampling_number =
135 sixaxis_fullkey_lifo.ReadCurrentEntry().state.sampling_number + 1; 136 sixaxis_fullkey_lifo.lifo.ReadCurrentEntry().state.sampling_number + 1;
136 sixaxis_handheld_state.sampling_number = 137 sixaxis_handheld_state.sampling_number =
137 sixaxis_handheld_lifo.ReadCurrentEntry().state.sampling_number + 1; 138 sixaxis_handheld_lifo.lifo.ReadCurrentEntry().state.sampling_number + 1;
138 sixaxis_dual_left_state.sampling_number = 139 sixaxis_dual_left_state.sampling_number =
139 sixaxis_dual_left_lifo.ReadCurrentEntry().state.sampling_number + 1; 140 sixaxis_dual_left_lifo.lifo.ReadCurrentEntry().state.sampling_number + 1;
140 sixaxis_dual_right_state.sampling_number = 141 sixaxis_dual_right_state.sampling_number =
141 sixaxis_dual_right_lifo.ReadCurrentEntry().state.sampling_number + 1; 142 sixaxis_dual_right_lifo.lifo.ReadCurrentEntry().state.sampling_number + 1;
142 sixaxis_left_lifo_state.sampling_number = 143 sixaxis_left_lifo_state.sampling_number =
143 sixaxis_left_lifo.ReadCurrentEntry().state.sampling_number + 1; 144 sixaxis_left_lifo.lifo.ReadCurrentEntry().state.sampling_number + 1;
144 sixaxis_right_lifo_state.sampling_number = 145 sixaxis_right_lifo_state.sampling_number =
145 sixaxis_right_lifo.ReadCurrentEntry().state.sampling_number + 1; 146 sixaxis_right_lifo.lifo.ReadCurrentEntry().state.sampling_number + 1;
146 147
147 if (IndexToNpadIdType(i) == Core::HID::NpadIdType::Handheld) { 148 if (IndexToNpadIdType(i) == Core::HID::NpadIdType::Handheld) {
148 // This buffer only is updated on handheld on HW 149 // This buffer only is updated on handheld on HW
149 sixaxis_handheld_lifo.WriteNextEntry(sixaxis_handheld_state); 150 sixaxis_handheld_lifo.lifo.WriteNextEntry(sixaxis_handheld_state);
150 } else { 151 } else {
151 // Handheld doesn't update this buffer on HW 152 // Handheld doesn't update this buffer on HW
152 sixaxis_fullkey_lifo.WriteNextEntry(sixaxis_fullkey_state); 153 sixaxis_fullkey_lifo.lifo.WriteNextEntry(sixaxis_fullkey_state);
153 } 154 }
154 155
155 sixaxis_dual_left_lifo.WriteNextEntry(sixaxis_dual_left_state); 156 sixaxis_dual_left_lifo.lifo.WriteNextEntry(sixaxis_dual_left_state);
156 sixaxis_dual_right_lifo.WriteNextEntry(sixaxis_dual_right_state); 157 sixaxis_dual_right_lifo.lifo.WriteNextEntry(sixaxis_dual_right_state);
157 sixaxis_left_lifo.WriteNextEntry(sixaxis_left_lifo_state); 158 sixaxis_left_lifo.lifo.WriteNextEntry(sixaxis_left_lifo_state);
158 sixaxis_right_lifo.WriteNextEntry(sixaxis_right_lifo_state); 159 sixaxis_right_lifo.lifo.WriteNextEntry(sixaxis_right_lifo_state);
159 } 160 }
160} 161}
161 162
diff --git a/src/core/hle/service/hid/controllers/stubbed.cpp b/src/core/hle/service/hid/controllers/stubbed.cpp
index 9e2f3ab21..e2a5f5d79 100644
--- a/src/core/hle/service/hid/controllers/stubbed.cpp
+++ b/src/core/hle/service/hid/controllers/stubbed.cpp
@@ -1,18 +1,15 @@
1// SPDX-FileCopyrightText: Copyright 2018 yuzu Emulator Project 1// SPDX-FileCopyrightText: Copyright 2018 yuzu Emulator Project
2// SPDX-License-Identifier: GPL-2.0-or-later 2// SPDX-License-Identifier: GPL-2.0-or-later
3 3
4#include <cstring>
5#include "common/common_types.h"
6#include "core/core_timing.h" 4#include "core/core_timing.h"
7#include "core/hid/hid_core.h" 5#include "core/hle/service/hid/controllers/shared_memory_format.h"
8#include "core/hle/service/hid/controllers/stubbed.h" 6#include "core/hle/service/hid/controllers/stubbed.h"
9 7
10namespace Service::HID { 8namespace Service::HID {
11 9
12Controller_Stubbed::Controller_Stubbed(Core::HID::HIDCore& hid_core_, u8* raw_shared_memory_) 10Controller_Stubbed::Controller_Stubbed(Core::HID::HIDCore& hid_core_,
13 : ControllerBase{hid_core_} { 11 CommonHeader& ring_lifo_header)
14 raw_shared_memory = raw_shared_memory_; 12 : ControllerBase{hid_core_}, header{ring_lifo_header} {}
15}
16 13
17Controller_Stubbed::~Controller_Stubbed() = default; 14Controller_Stubbed::~Controller_Stubbed() = default;
18 15
@@ -25,18 +22,10 @@ void Controller_Stubbed::OnUpdate(const Core::Timing::CoreTiming& core_timing) {
25 return; 22 return;
26 } 23 }
27 24
28 CommonHeader header{};
29 header.timestamp = core_timing.GetGlobalTimeNs().count(); 25 header.timestamp = core_timing.GetGlobalTimeNs().count();
30 header.total_entry_count = 17; 26 header.total_entry_count = 17;
31 header.entry_count = 0; 27 header.entry_count = 0;
32 header.last_entry_index = 0; 28 header.last_entry_index = 0;
33
34 std::memcpy(raw_shared_memory + common_offset, &header, sizeof(CommonHeader));
35}
36
37void Controller_Stubbed::SetCommonHeaderOffset(std::size_t off) {
38 common_offset = off;
39 smart_update = true;
40} 29}
41 30
42} // namespace Service::HID 31} // namespace Service::HID
diff --git a/src/core/hle/service/hid/controllers/stubbed.h b/src/core/hle/service/hid/controllers/stubbed.h
index 1483a968e..d2052fb17 100644
--- a/src/core/hle/service/hid/controllers/stubbed.h
+++ b/src/core/hle/service/hid/controllers/stubbed.h
@@ -3,13 +3,14 @@
3 3
4#pragma once 4#pragma once
5 5
6#include "common/common_types.h"
7#include "core/hle/service/hid/controllers/controller_base.h" 6#include "core/hle/service/hid/controllers/controller_base.h"
8 7
9namespace Service::HID { 8namespace Service::HID {
9struct CommonHeader;
10
10class Controller_Stubbed final : public ControllerBase { 11class Controller_Stubbed final : public ControllerBase {
11public: 12public:
12 explicit Controller_Stubbed(Core::HID::HIDCore& hid_core_, u8* raw_shared_memory_); 13 explicit Controller_Stubbed(Core::HID::HIDCore& hid_core_, CommonHeader& ring_lifo_header);
13 ~Controller_Stubbed() override; 14 ~Controller_Stubbed() override;
14 15
15 // Called when the controller is initialized 16 // Called when the controller is initialized
@@ -21,19 +22,8 @@ public:
21 // When the controller is requesting an update for the shared memory 22 // When the controller is requesting an update for the shared memory
22 void OnUpdate(const Core::Timing::CoreTiming& core_timing) override; 23 void OnUpdate(const Core::Timing::CoreTiming& core_timing) override;
23 24
24 void SetCommonHeaderOffset(std::size_t off);
25
26private: 25private:
27 struct CommonHeader { 26 CommonHeader& header;
28 s64 timestamp{};
29 s64 total_entry_count{};
30 s64 last_entry_index{};
31 s64 entry_count{};
32 };
33 static_assert(sizeof(CommonHeader) == 0x20, "CommonHeader is an invalid size");
34
35 u8* raw_shared_memory = nullptr;
36 bool smart_update{}; 27 bool smart_update{};
37 std::size_t common_offset{};
38}; 28};
39} // namespace Service::HID 29} // namespace Service::HID
diff --git a/src/core/hle/service/hid/controllers/touchscreen.cpp b/src/core/hle/service/hid/controllers/touchscreen.cpp
index fcd973414..469750006 100644
--- a/src/core/hle/service/hid/controllers/touchscreen.cpp
+++ b/src/core/hle/service/hid/controllers/touchscreen.cpp
@@ -2,26 +2,22 @@
2// SPDX-License-Identifier: GPL-2.0-or-later 2// SPDX-License-Identifier: GPL-2.0-or-later
3 3
4#include <algorithm> 4#include <algorithm>
5#include <cstring>
6#include "common/common_types.h" 5#include "common/common_types.h"
7#include "common/settings.h" 6#include "common/settings.h"
8#include "core/core.h"
9#include "core/core_timing.h" 7#include "core/core_timing.h"
10#include "core/frontend/emu_window.h" 8#include "core/frontend/emu_window.h"
11#include "core/hid/emulated_console.h" 9#include "core/hid/emulated_console.h"
12#include "core/hid/hid_core.h" 10#include "core/hid/hid_core.h"
11#include "core/hle/service/hid/controllers/shared_memory_format.h"
13#include "core/hle/service/hid/controllers/touchscreen.h" 12#include "core/hle/service/hid/controllers/touchscreen.h"
14 13
15namespace Service::HID { 14namespace Service::HID {
16constexpr std::size_t SHARED_MEMORY_OFFSET = 0x400;
17 15
18TouchScreen::TouchScreen(Core::HID::HIDCore& hid_core_, u8* raw_shared_memory_) 16TouchScreen::TouchScreen(Core::HID::HIDCore& hid_core_,
19 : ControllerBase{hid_core_}, touchscreen_width(Layout::ScreenUndocked::Width), 17 TouchScreenSharedMemoryFormat& touch_shared_memory)
18 : ControllerBase{hid_core_}, shared_memory{touch_shared_memory},
19 touchscreen_width(Layout::ScreenUndocked::Width),
20 touchscreen_height(Layout::ScreenUndocked::Height) { 20 touchscreen_height(Layout::ScreenUndocked::Height) {
21 static_assert(SHARED_MEMORY_OFFSET + sizeof(TouchSharedMemory) < shared_memory_size,
22 "TouchSharedMemory is bigger than the shared memory");
23 shared_memory = std::construct_at(
24 reinterpret_cast<TouchSharedMemory*>(raw_shared_memory_ + SHARED_MEMORY_OFFSET));
25 console = hid_core.GetEmulatedConsole(); 21 console = hid_core.GetEmulatedConsole();
26} 22}
27 23
@@ -32,11 +28,11 @@ void TouchScreen::OnInit() {}
32void TouchScreen::OnRelease() {} 28void TouchScreen::OnRelease() {}
33 29
34void TouchScreen::OnUpdate(const Core::Timing::CoreTiming& core_timing) { 30void TouchScreen::OnUpdate(const Core::Timing::CoreTiming& core_timing) {
35 shared_memory->touch_screen_lifo.timestamp = core_timing.GetGlobalTimeNs().count(); 31 shared_memory.touch_screen_lifo.timestamp = core_timing.GetGlobalTimeNs().count();
36 32
37 if (!IsControllerActivated()) { 33 if (!IsControllerActivated()) {
38 shared_memory->touch_screen_lifo.buffer_count = 0; 34 shared_memory.touch_screen_lifo.buffer_count = 0;
39 shared_memory->touch_screen_lifo.buffer_tail = 0; 35 shared_memory.touch_screen_lifo.buffer_tail = 0;
40 return; 36 return;
41 } 37 }
42 38
@@ -86,7 +82,7 @@ void TouchScreen::OnUpdate(const Core::Timing::CoreTiming& core_timing) {
86 static_cast<std::size_t>(std::distance(active_fingers.begin(), end_iter)); 82 static_cast<std::size_t>(std::distance(active_fingers.begin(), end_iter));
87 83
88 const u64 timestamp = static_cast<u64>(core_timing.GetGlobalTimeNs().count()); 84 const u64 timestamp = static_cast<u64>(core_timing.GetGlobalTimeNs().count());
89 const auto& last_entry = shared_memory->touch_screen_lifo.ReadCurrentEntry().state; 85 const auto& last_entry = shared_memory.touch_screen_lifo.ReadCurrentEntry().state;
90 86
91 next_state.sampling_number = last_entry.sampling_number + 1; 87 next_state.sampling_number = last_entry.sampling_number + 1;
92 next_state.entry_count = static_cast<s32>(active_fingers_count); 88 next_state.entry_count = static_cast<s32>(active_fingers_count);
@@ -118,7 +114,7 @@ void TouchScreen::OnUpdate(const Core::Timing::CoreTiming& core_timing) {
118 } 114 }
119 } 115 }
120 116
121 shared_memory->touch_screen_lifo.WriteNextEntry(next_state); 117 shared_memory.touch_screen_lifo.WriteNextEntry(next_state);
122} 118}
123 119
124void TouchScreen::SetTouchscreenDimensions(u32 width, u32 height) { 120void TouchScreen::SetTouchscreenDimensions(u32 width, u32 height) {
diff --git a/src/core/hle/service/hid/controllers/touchscreen.h b/src/core/hle/service/hid/controllers/touchscreen.h
index 79f026a81..5b6305bfc 100644
--- a/src/core/hle/service/hid/controllers/touchscreen.h
+++ b/src/core/hle/service/hid/controllers/touchscreen.h
@@ -3,20 +3,23 @@
3 3
4#pragma once 4#pragma once
5 5
6#include "common/common_funcs.h" 6#include <array>
7#include "common/common_types.h" 7
8#include "core/hid/hid_types.h" 8#include "core/hid/hid_types.h"
9#include "core/hle/service/hid/controllers/controller_base.h" 9#include "core/hle/service/hid/controllers/controller_base.h"
10#include "core/hle/service/hid/ring_lifo.h" 10#include "core/hle/service/hid/controllers/types/touch_types.h"
11 11
12namespace Core::HID { 12namespace Core::HID {
13class EmulatedConsole; 13class EmulatedConsole;
14} // namespace Core::HID 14} // namespace Core::HID
15 15
16namespace Service::HID { 16namespace Service::HID {
17struct TouchScreenSharedMemoryFormat;
18
17class TouchScreen final : public ControllerBase { 19class TouchScreen final : public ControllerBase {
18public: 20public:
19 explicit TouchScreen(Core::HID::HIDCore& hid_core_, u8* raw_shared_memory_); 21 explicit TouchScreen(Core::HID::HIDCore& hid_core_,
22 TouchScreenSharedMemoryFormat& touch_shared_memory);
20 ~TouchScreen() override; 23 ~TouchScreen() override;
21 24
22 // Called when the controller is initialized 25 // Called when the controller is initialized
@@ -31,27 +34,8 @@ public:
31 void SetTouchscreenDimensions(u32 width, u32 height); 34 void SetTouchscreenDimensions(u32 width, u32 height);
32 35
33private: 36private:
34 static constexpr std::size_t MAX_FINGERS = 16;
35
36 // This is nn::hid::TouchScreenState
37 struct TouchScreenState {
38 s64 sampling_number{};
39 s32 entry_count{};
40 INSERT_PADDING_BYTES(4); // Reserved
41 std::array<Core::HID::TouchState, MAX_FINGERS> states{};
42 };
43 static_assert(sizeof(TouchScreenState) == 0x290, "TouchScreenState is an invalid size");
44
45 struct TouchSharedMemory {
46 // This is nn::hid::detail::TouchScreenLifo
47 Lifo<TouchScreenState, hid_entry_count> touch_screen_lifo{};
48 static_assert(sizeof(touch_screen_lifo) == 0x2C38, "touch_screen_lifo is an invalid size");
49 INSERT_PADDING_WORDS(0xF2);
50 };
51 static_assert(sizeof(TouchSharedMemory) == 0x3000, "TouchSharedMemory is an invalid size");
52
53 TouchScreenState next_state{}; 37 TouchScreenState next_state{};
54 TouchSharedMemory* shared_memory = nullptr; 38 TouchScreenSharedMemoryFormat& shared_memory;
55 Core::HID::EmulatedConsole* console = nullptr; 39 Core::HID::EmulatedConsole* console = nullptr;
56 40
57 std::array<Core::HID::TouchFinger, MAX_FINGERS> fingers{}; 41 std::array<Core::HID::TouchFinger, MAX_FINGERS> fingers{};
diff --git a/src/core/hle/service/hid/controllers/types/debug_pad_types.h b/src/core/hle/service/hid/controllers/types/debug_pad_types.h
new file mode 100644
index 000000000..a96171b62
--- /dev/null
+++ b/src/core/hle/service/hid/controllers/types/debug_pad_types.h
@@ -0,0 +1,31 @@
1// SPDX-FileCopyrightText: Copyright 2023 yuzu Emulator Project
2// SPDX-License-Identifier: GPL-3.0-or-later
3
4#pragma once
5
6#include "common/bit_field.h"
7#include "common/common_types.h"
8#include "core/hid/hid_types.h"
9
10namespace Service::HID {
11
12// This is nn::hid::DebugPadAttribute
13struct DebugPadAttribute {
14 union {
15 u32 raw{};
16 BitField<0, 1, u32> connected;
17 };
18};
19static_assert(sizeof(DebugPadAttribute) == 0x4, "DebugPadAttribute is an invalid size");
20
21// This is nn::hid::DebugPadState
22struct DebugPadState {
23 s64 sampling_number{};
24 DebugPadAttribute attribute{};
25 Core::HID::DebugPadButton pad_state{};
26 Core::HID::AnalogStickState r_stick{};
27 Core::HID::AnalogStickState l_stick{};
28};
29static_assert(sizeof(DebugPadState) == 0x20, "DebugPadState is an invalid state");
30
31} // namespace Service::HID
diff --git a/src/core/hle/service/hid/controllers/types/gesture_types.h b/src/core/hle/service/hid/controllers/types/gesture_types.h
new file mode 100644
index 000000000..b4f034cd3
--- /dev/null
+++ b/src/core/hle/service/hid/controllers/types/gesture_types.h
@@ -0,0 +1,77 @@
1// SPDX-FileCopyrightText: Copyright 2023 yuzu Emulator Project
2// SPDX-License-Identifier: GPL-3.0-or-later
3
4#pragma once
5
6#include <array>
7#include "common/bit_field.h"
8#include "common/common_types.h"
9#include "common/point.h"
10
11namespace Service::HID {
12static constexpr size_t MAX_FINGERS = 16;
13static constexpr size_t MAX_POINTS = 4;
14
15// This is nn::hid::GestureType
16enum class GestureType : u32 {
17 Idle, // Nothing touching the screen
18 Complete, // Set at the end of a touch event
19 Cancel, // Set when the number of fingers change
20 Touch, // A finger just touched the screen
21 Press, // Set if last type is touch and the finger hasn't moved
22 Tap, // Fast press then release
23 Pan, // All points moving together across the screen
24 Swipe, // Fast press movement and release of a single point
25 Pinch, // All points moving away/closer to the midpoint
26 Rotate, // All points rotating from the midpoint
27};
28
29// This is nn::hid::GestureDirection
30enum class GestureDirection : u32 {
31 None,
32 Left,
33 Up,
34 Right,
35 Down,
36};
37
38// This is nn::hid::GestureAttribute
39struct GestureAttribute {
40 union {
41 u32 raw{};
42
43 BitField<4, 1, u32> is_new_touch;
44 BitField<8, 1, u32> is_double_tap;
45 };
46};
47static_assert(sizeof(GestureAttribute) == 4, "GestureAttribute is an invalid size");
48
49// This is nn::hid::GestureState
50struct GestureState {
51 s64 sampling_number{};
52 s64 detection_count{};
53 GestureType type{GestureType::Idle};
54 GestureDirection direction{GestureDirection::None};
55 Common::Point<s32> pos{};
56 Common::Point<s32> delta{};
57 f32 vel_x{};
58 f32 vel_y{};
59 GestureAttribute attributes{};
60 f32 scale{};
61 f32 rotation_angle{};
62 s32 point_count{};
63 std::array<Common::Point<s32>, 4> points{};
64};
65static_assert(sizeof(GestureState) == 0x60, "GestureState is an invalid size");
66
67struct GestureProperties {
68 std::array<Common::Point<s32>, MAX_POINTS> points{};
69 std::size_t active_points{};
70 Common::Point<s32> mid_point{};
71 s64 detection_count{};
72 u64 delta_time{};
73 f32 average_distance{};
74 f32 angle{};
75};
76
77} // namespace Service::HID
diff --git a/src/core/hle/service/hid/controllers/types/keyboard_types.h b/src/core/hle/service/hid/controllers/types/keyboard_types.h
new file mode 100644
index 000000000..f44a536b9
--- /dev/null
+++ b/src/core/hle/service/hid/controllers/types/keyboard_types.h
@@ -0,0 +1,20 @@
1// SPDX-FileCopyrightText: Copyright 2023 yuzu Emulator Project
2// SPDX-License-Identifier: GPL-3.0-or-later
3
4#pragma once
5
6#include "common/common_types.h"
7#include "core/hid/hid_types.h"
8
9namespace Service::HID {
10
11// This is nn::hid::detail::KeyboardState
12struct KeyboardState {
13 s64 sampling_number{};
14 Core::HID::KeyboardModifier modifier{};
15 Core::HID::KeyboardAttribute attribute{};
16 Core::HID::KeyboardKey key{};
17};
18static_assert(sizeof(KeyboardState) == 0x30, "KeyboardState is an invalid size");
19
20} // namespace Service::HID
diff --git a/src/core/hle/service/hid/controllers/types/mouse_types.h b/src/core/hle/service/hid/controllers/types/mouse_types.h
new file mode 100644
index 000000000..8bd6e167c
--- /dev/null
+++ b/src/core/hle/service/hid/controllers/types/mouse_types.h
@@ -0,0 +1,8 @@
1// SPDX-FileCopyrightText: Copyright 2023 yuzu Emulator Project
2// SPDX-License-Identifier: GPL-3.0-or-later
3
4#pragma once
5
6#include "common/common_types.h"
7
8namespace Service::HID {} // namespace Service::HID
diff --git a/src/core/hle/service/hid/controllers/types/npad_types.h b/src/core/hle/service/hid/controllers/types/npad_types.h
new file mode 100644
index 000000000..a5ce2562b
--- /dev/null
+++ b/src/core/hle/service/hid/controllers/types/npad_types.h
@@ -0,0 +1,254 @@
1// SPDX-FileCopyrightText: Copyright 2023 yuzu Emulator Project
2// SPDX-License-Identifier: GPL-3.0-or-later
3
4#pragma once
5
6#include "common/bit_field.h"
7#include "common/common_funcs.h"
8#include "common/common_types.h"
9#include "core/hid/hid_types.h"
10
11namespace Service::HID {
12static constexpr std::size_t NpadCount = 10;
13
14// This is nn::hid::NpadJoyHoldType
15enum class NpadJoyHoldType : u64 {
16 Vertical = 0,
17 Horizontal = 1,
18};
19
20// This is nn::hid::NpadJoyAssignmentMode
21enum class NpadJoyAssignmentMode : u32 {
22 Dual = 0,
23 Single = 1,
24};
25
26// This is nn::hid::NpadJoyDeviceType
27enum class NpadJoyDeviceType : s64 {
28 Left = 0,
29 Right = 1,
30};
31
32// This is nn::hid::NpadHandheldActivationMode
33enum class NpadHandheldActivationMode : u64 {
34 Dual = 0,
35 Single = 1,
36 None = 2,
37 MaxActivationMode = 3,
38};
39
40// This is nn::hid::system::AppletFooterUiAttributesSet
41struct AppletFooterUiAttributes {
42 INSERT_PADDING_BYTES(0x4);
43};
44
45// This is nn::hid::system::AppletFooterUiType
46enum class AppletFooterUiType : u8 {
47 None = 0,
48 HandheldNone = 1,
49 HandheldJoyConLeftOnly = 2,
50 HandheldJoyConRightOnly = 3,
51 HandheldJoyConLeftJoyConRight = 4,
52 JoyDual = 5,
53 JoyDualLeftOnly = 6,
54 JoyDualRightOnly = 7,
55 JoyLeftHorizontal = 8,
56 JoyLeftVertical = 9,
57 JoyRightHorizontal = 10,
58 JoyRightVertical = 11,
59 SwitchProController = 12,
60 CompatibleProController = 13,
61 CompatibleJoyCon = 14,
62 LarkHvc1 = 15,
63 LarkHvc2 = 16,
64 LarkNesLeft = 17,
65 LarkNesRight = 18,
66 Lucia = 19,
67 Verification = 20,
68 Lagon = 21,
69};
70
71using AppletFooterUiVariant = u8;
72
73// This is "nn::hid::system::AppletDetailedUiType".
74struct AppletDetailedUiType {
75 AppletFooterUiVariant ui_variant;
76 INSERT_PADDING_BYTES(0x2);
77 AppletFooterUiType footer;
78};
79static_assert(sizeof(AppletDetailedUiType) == 0x4, "AppletDetailedUiType is an invalid size");
80// This is nn::hid::NpadCommunicationMode
81enum class NpadCommunicationMode : u64 {
82 Mode_5ms = 0,
83 Mode_10ms = 1,
84 Mode_15ms = 2,
85 Default = 3,
86};
87
88enum class NpadRevision : u32 {
89 Revision0 = 0,
90 Revision1 = 1,
91 Revision2 = 2,
92 Revision3 = 3,
93};
94
95// This is nn::hid::detail::ColorAttribute
96enum class ColorAttribute : u32 {
97 Ok = 0,
98 ReadError = 1,
99 NoController = 2,
100};
101static_assert(sizeof(ColorAttribute) == 4, "ColorAttribute is an invalid size");
102
103// This is nn::hid::detail::NpadFullKeyColorState
104struct NpadFullKeyColorState {
105 ColorAttribute attribute{ColorAttribute::NoController};
106 Core::HID::NpadControllerColor fullkey{};
107};
108static_assert(sizeof(NpadFullKeyColorState) == 0xC, "NpadFullKeyColorState is an invalid size");
109
110// This is nn::hid::detail::NpadJoyColorState
111struct NpadJoyColorState {
112 ColorAttribute attribute{ColorAttribute::NoController};
113 Core::HID::NpadControllerColor left{};
114 Core::HID::NpadControllerColor right{};
115};
116static_assert(sizeof(NpadJoyColorState) == 0x14, "NpadJoyColorState is an invalid size");
117
118// This is nn::hid::NpadAttribute
119struct NpadAttribute {
120 union {
121 u32 raw{};
122 BitField<0, 1, u32> is_connected;
123 BitField<1, 1, u32> is_wired;
124 BitField<2, 1, u32> is_left_connected;
125 BitField<3, 1, u32> is_left_wired;
126 BitField<4, 1, u32> is_right_connected;
127 BitField<5, 1, u32> is_right_wired;
128 };
129};
130static_assert(sizeof(NpadAttribute) == 4, "NpadAttribute is an invalid size");
131
132// This is nn::hid::NpadFullKeyState
133// This is nn::hid::NpadHandheldState
134// This is nn::hid::NpadJoyDualState
135// This is nn::hid::NpadJoyLeftState
136// This is nn::hid::NpadJoyRightState
137// This is nn::hid::NpadPalmaState
138// This is nn::hid::NpadSystemExtState
139struct NPadGenericState {
140 s64_le sampling_number{};
141 Core::HID::NpadButtonState npad_buttons{};
142 Core::HID::AnalogStickState l_stick{};
143 Core::HID::AnalogStickState r_stick{};
144 NpadAttribute connection_status{};
145 INSERT_PADDING_BYTES(4); // Reserved
146};
147static_assert(sizeof(NPadGenericState) == 0x28, "NPadGenericState is an invalid size");
148
149// This is nn::hid::server::NpadGcTriggerState
150struct NpadGcTriggerState {
151 s64 sampling_number{};
152 s32 l_analog{};
153 s32 r_analog{};
154};
155static_assert(sizeof(NpadGcTriggerState) == 0x10, "NpadGcTriggerState is an invalid size");
156
157// This is nn::hid::NpadSystemProperties
158struct NPadSystemProperties {
159 union {
160 s64 raw{};
161 BitField<0, 1, s64> is_charging_joy_dual;
162 BitField<1, 1, s64> is_charging_joy_left;
163 BitField<2, 1, s64> is_charging_joy_right;
164 BitField<3, 1, s64> is_powered_joy_dual;
165 BitField<4, 1, s64> is_powered_joy_left;
166 BitField<5, 1, s64> is_powered_joy_right;
167 BitField<9, 1, s64> is_system_unsupported_button;
168 BitField<10, 1, s64> is_system_ext_unsupported_button;
169 BitField<11, 1, s64> is_vertical;
170 BitField<12, 1, s64> is_horizontal;
171 BitField<13, 1, s64> use_plus;
172 BitField<14, 1, s64> use_minus;
173 BitField<15, 1, s64> use_directional_buttons;
174 };
175};
176static_assert(sizeof(NPadSystemProperties) == 0x8, "NPadSystemProperties is an invalid size");
177
178// This is nn::hid::NpadSystemButtonProperties
179struct NpadSystemButtonProperties {
180 union {
181 s32 raw{};
182 BitField<0, 1, s32> is_home_button_protection_enabled;
183 };
184};
185static_assert(sizeof(NpadSystemButtonProperties) == 0x4, "NPadButtonProperties is an invalid size");
186
187// This is nn::hid::system::DeviceType
188struct DeviceType {
189 union {
190 u32 raw{};
191 BitField<0, 1, s32> fullkey;
192 BitField<1, 1, s32> debug_pad;
193 BitField<2, 1, s32> handheld_left;
194 BitField<3, 1, s32> handheld_right;
195 BitField<4, 1, s32> joycon_left;
196 BitField<5, 1, s32> joycon_right;
197 BitField<6, 1, s32> palma;
198 BitField<7, 1, s32> lark_hvc_left;
199 BitField<8, 1, s32> lark_hvc_right;
200 BitField<9, 1, s32> lark_nes_left;
201 BitField<10, 1, s32> lark_nes_right;
202 BitField<11, 1, s32> handheld_lark_hvc_left;
203 BitField<12, 1, s32> handheld_lark_hvc_right;
204 BitField<13, 1, s32> handheld_lark_nes_left;
205 BitField<14, 1, s32> handheld_lark_nes_right;
206 BitField<15, 1, s32> lucia;
207 BitField<16, 1, s32> lagon;
208 BitField<17, 1, s32> lager;
209 BitField<31, 1, s32> system;
210 };
211};
212
213// This is nn::hid::detail::NfcXcdDeviceHandleStateImpl
214struct NfcXcdDeviceHandleStateImpl {
215 u64 handle{};
216 bool is_available{};
217 bool is_activated{};
218 INSERT_PADDING_BYTES(0x6); // Reserved
219 u64 sampling_number{};
220};
221static_assert(sizeof(NfcXcdDeviceHandleStateImpl) == 0x18,
222 "NfcXcdDeviceHandleStateImpl is an invalid size");
223
224// This is nn::hid::NpadLarkType
225enum class NpadLarkType : u32 {
226 Invalid,
227 H1,
228 H2,
229 NL,
230 NR,
231};
232
233// This is nn::hid::NpadLuciaType
234enum class NpadLuciaType : u32 {
235 Invalid,
236 J,
237 E,
238 U,
239};
240
241// This is nn::hid::NpadLagonType
242enum class NpadLagonType : u32 {
243 Invalid,
244};
245
246// This is nn::hid::NpadLagerType
247enum class NpadLagerType : u32 {
248 Invalid,
249 J,
250 E,
251 U,
252};
253
254} // namespace Service::HID
diff --git a/src/core/hle/service/hid/controllers/types/touch_types.h b/src/core/hle/service/hid/controllers/types/touch_types.h
new file mode 100644
index 000000000..efeaa796d
--- /dev/null
+++ b/src/core/hle/service/hid/controllers/types/touch_types.h
@@ -0,0 +1,90 @@
1// SPDX-FileCopyrightText: Copyright 2023 yuzu Emulator Project
2// SPDX-License-Identifier: GPL-3.0-or-later
3
4#pragma once
5
6#include <array>
7
8#include <array>
9#include "common/bit_field.h"
10#include "common/common_funcs.h"
11#include "common/common_types.h"
12#include "common/point.h"
13#include "core/hid/hid_types.h"
14
15namespace Service::HID {
16static constexpr std::size_t MAX_FINGERS = 16;
17static constexpr size_t MAX_POINTS = 4;
18
19// This is nn::hid::GestureType
20enum class GestureType : u32 {
21 Idle, // Nothing touching the screen
22 Complete, // Set at the end of a touch event
23 Cancel, // Set when the number of fingers change
24 Touch, // A finger just touched the screen
25 Press, // Set if last type is touch and the finger hasn't moved
26 Tap, // Fast press then release
27 Pan, // All points moving together across the screen
28 Swipe, // Fast press movement and release of a single point
29 Pinch, // All points moving away/closer to the midpoint
30 Rotate, // All points rotating from the midpoint
31};
32
33// This is nn::hid::GestureDirection
34enum class GestureDirection : u32 {
35 None,
36 Left,
37 Up,
38 Right,
39 Down,
40};
41
42// This is nn::hid::GestureAttribute
43struct GestureAttribute {
44 union {
45 u32 raw{};
46
47 BitField<4, 1, u32> is_new_touch;
48 BitField<8, 1, u32> is_double_tap;
49 };
50};
51static_assert(sizeof(GestureAttribute) == 4, "GestureAttribute is an invalid size");
52
53// This is nn::hid::GestureState
54struct GestureState {
55 s64 sampling_number{};
56 s64 detection_count{};
57 GestureType type{GestureType::Idle};
58 GestureDirection direction{GestureDirection::None};
59 Common::Point<s32> pos{};
60 Common::Point<s32> delta{};
61 f32 vel_x{};
62 f32 vel_y{};
63 GestureAttribute attributes{};
64 f32 scale{};
65 f32 rotation_angle{};
66 s32 point_count{};
67 std::array<Common::Point<s32>, 4> points{};
68};
69static_assert(sizeof(GestureState) == 0x60, "GestureState is an invalid size");
70
71struct GestureProperties {
72 std::array<Common::Point<s32>, MAX_POINTS> points{};
73 std::size_t active_points{};
74 Common::Point<s32> mid_point{};
75 s64 detection_count{};
76 u64 delta_time{};
77 f32 average_distance{};
78 f32 angle{};
79};
80
81// This is nn::hid::TouchScreenState
82struct TouchScreenState {
83 s64 sampling_number{};
84 s32 entry_count{};
85 INSERT_PADDING_BYTES(4); // Reserved
86 std::array<Core::HID::TouchState, MAX_FINGERS> states{};
87};
88static_assert(sizeof(TouchScreenState) == 0x290, "TouchScreenState is an invalid size");
89
90} // namespace Service::HID
diff --git a/src/core/hle/service/hid/controllers/xpad.cpp b/src/core/hle/service/hid/controllers/xpad.cpp
deleted file mode 100644
index 0aaed1fa7..000000000
--- a/src/core/hle/service/hid/controllers/xpad.cpp
+++ /dev/null
@@ -1,39 +0,0 @@
1// SPDX-FileCopyrightText: Copyright 2018 yuzu Emulator Project
2// SPDX-License-Identifier: GPL-2.0-or-later
3
4#include <cstring>
5#include "common/common_types.h"
6#include "core/core_timing.h"
7#include "core/hid/hid_core.h"
8#include "core/hle/service/hid/controllers/xpad.h"
9
10namespace Service::HID {
11constexpr std::size_t SHARED_MEMORY_OFFSET = 0x3C00;
12
13XPad::XPad(Core::HID::HIDCore& hid_core_, u8* raw_shared_memory_) : ControllerBase{hid_core_} {
14 static_assert(SHARED_MEMORY_OFFSET + sizeof(XpadSharedMemory) < shared_memory_size,
15 "XpadSharedMemory is bigger than the shared memory");
16 shared_memory = std::construct_at(
17 reinterpret_cast<XpadSharedMemory*>(raw_shared_memory_ + SHARED_MEMORY_OFFSET));
18}
19XPad::~XPad() = default;
20
21void XPad::OnInit() {}
22
23void XPad::OnRelease() {}
24
25void XPad::OnUpdate(const Core::Timing::CoreTiming& core_timing) {
26 if (!IsControllerActivated()) {
27 shared_memory->basic_xpad_lifo.buffer_count = 0;
28 shared_memory->basic_xpad_lifo.buffer_tail = 0;
29 return;
30 }
31
32 const auto& last_entry = shared_memory->basic_xpad_lifo.ReadCurrentEntry().state;
33 next_state.sampling_number = last_entry.sampling_number + 1;
34 // TODO(ogniK): Update xpad states
35
36 shared_memory->basic_xpad_lifo.WriteNextEntry(next_state);
37}
38
39} // namespace Service::HID
diff --git a/src/core/hle/service/hid/controllers/xpad.h b/src/core/hle/service/hid/controllers/xpad.h
deleted file mode 100644
index 9e63a317a..000000000
--- a/src/core/hle/service/hid/controllers/xpad.h
+++ /dev/null
@@ -1,112 +0,0 @@
1// SPDX-FileCopyrightText: Copyright 2018 yuzu Emulator Project
2// SPDX-License-Identifier: GPL-2.0-or-later
3
4#pragma once
5
6#include "common/bit_field.h"
7#include "common/common_types.h"
8#include "core/hid/hid_types.h"
9#include "core/hle/service/hid/controllers/controller_base.h"
10#include "core/hle/service/hid/ring_lifo.h"
11
12namespace Service::HID {
13class XPad final : public ControllerBase {
14public:
15 explicit XPad(Core::HID::HIDCore& hid_core_, u8* raw_shared_memory_);
16 ~XPad() override;
17
18 // Called when the controller is initialized
19 void OnInit() override;
20
21 // When the controller is released
22 void OnRelease() override;
23
24 // When the controller is requesting an update for the shared memory
25 void OnUpdate(const Core::Timing::CoreTiming& core_timing) override;
26
27private:
28 // This is nn::hid::BasicXpadAttributeSet
29 struct BasicXpadAttributeSet {
30 union {
31 u32 raw{};
32 BitField<0, 1, u32> is_connected;
33 BitField<1, 1, u32> is_wired;
34 BitField<2, 1, u32> is_left_connected;
35 BitField<3, 1, u32> is_left_wired;
36 BitField<4, 1, u32> is_right_connected;
37 BitField<5, 1, u32> is_right_wired;
38 };
39 };
40 static_assert(sizeof(BasicXpadAttributeSet) == 4, "BasicXpadAttributeSet is an invalid size");
41
42 // This is nn::hid::BasicXpadButtonSet
43 struct BasicXpadButtonSet {
44 union {
45 u32 raw{};
46 // Button states
47 BitField<0, 1, u32> a;
48 BitField<1, 1, u32> b;
49 BitField<2, 1, u32> x;
50 BitField<3, 1, u32> y;
51 BitField<4, 1, u32> l_stick;
52 BitField<5, 1, u32> r_stick;
53 BitField<6, 1, u32> l;
54 BitField<7, 1, u32> r;
55 BitField<8, 1, u32> zl;
56 BitField<9, 1, u32> zr;
57 BitField<10, 1, u32> plus;
58 BitField<11, 1, u32> minus;
59
60 // D-Pad
61 BitField<12, 1, u32> d_left;
62 BitField<13, 1, u32> d_up;
63 BitField<14, 1, u32> d_right;
64 BitField<15, 1, u32> d_down;
65
66 // Left JoyStick
67 BitField<16, 1, u32> l_stick_left;
68 BitField<17, 1, u32> l_stick_up;
69 BitField<18, 1, u32> l_stick_right;
70 BitField<19, 1, u32> l_stick_down;
71
72 // Right JoyStick
73 BitField<20, 1, u32> r_stick_left;
74 BitField<21, 1, u32> r_stick_up;
75 BitField<22, 1, u32> r_stick_right;
76 BitField<23, 1, u32> r_stick_down;
77
78 // Not always active?
79 BitField<24, 1, u32> left_sl;
80 BitField<25, 1, u32> left_sr;
81
82 BitField<26, 1, u32> right_sl;
83 BitField<27, 1, u32> right_sr;
84
85 BitField<28, 1, u32> palma;
86 BitField<30, 1, u32> handheld_left_b;
87 };
88 };
89 static_assert(sizeof(BasicXpadButtonSet) == 4, "BasicXpadButtonSet is an invalid size");
90
91 // This is nn::hid::detail::BasicXpadState
92 struct BasicXpadState {
93 s64 sampling_number{};
94 BasicXpadAttributeSet attributes{};
95 BasicXpadButtonSet pad_states{};
96 Core::HID::AnalogStickState l_stick{};
97 Core::HID::AnalogStickState r_stick{};
98 };
99 static_assert(sizeof(BasicXpadState) == 0x20, "BasicXpadState is an invalid size");
100
101 struct XpadSharedMemory {
102 // This is nn::hid::detail::BasicXpadLifo
103 Lifo<BasicXpadState, hid_entry_count> basic_xpad_lifo{};
104 static_assert(sizeof(basic_xpad_lifo) == 0x2C8, "basic_xpad_lifo is an invalid size");
105 INSERT_PADDING_WORDS(0x4E);
106 };
107 static_assert(sizeof(XpadSharedMemory) == 0x400, "XpadSharedMemory is an invalid size");
108
109 BasicXpadState next_state{};
110 XpadSharedMemory* shared_memory = nullptr;
111};
112} // namespace Service::HID
diff --git a/src/core/hle/service/hid/hid_server.cpp b/src/core/hle/service/hid/hid_server.cpp
index b06ea467e..de24b0401 100644
--- a/src/core/hle/service/hid/hid_server.cpp
+++ b/src/core/hle/service/hid/hid_server.cpp
@@ -28,6 +28,7 @@
28#include "core/hle/service/hid/controllers/seven_six_axis.h" 28#include "core/hle/service/hid/controllers/seven_six_axis.h"
29#include "core/hle/service/hid/controllers/six_axis.h" 29#include "core/hle/service/hid/controllers/six_axis.h"
30#include "core/hle/service/hid/controllers/touchscreen.h" 30#include "core/hle/service/hid/controllers/touchscreen.h"
31#include "core/hle/service/hid/controllers/types/npad_types.h"
31 32
32namespace Service::HID { 33namespace Service::HID {
33 34
@@ -1099,7 +1100,7 @@ void IHidServer::GetPlayerLedPattern(HLERequestContext& ctx) {
1099void IHidServer::ActivateNpadWithRevision(HLERequestContext& ctx) { 1100void IHidServer::ActivateNpadWithRevision(HLERequestContext& ctx) {
1100 IPC::RequestParser rp{ctx}; 1101 IPC::RequestParser rp{ctx};
1101 struct Parameters { 1102 struct Parameters {
1102 NPad::NpadRevision revision; 1103 NpadRevision revision;
1103 INSERT_PADDING_WORDS_NOINIT(1); 1104 INSERT_PADDING_WORDS_NOINIT(1);
1104 u64 applet_resource_user_id; 1105 u64 applet_resource_user_id;
1105 }; 1106 };
@@ -1122,7 +1123,7 @@ void IHidServer::ActivateNpadWithRevision(HLERequestContext& ctx) {
1122void IHidServer::SetNpadJoyHoldType(HLERequestContext& ctx) { 1123void IHidServer::SetNpadJoyHoldType(HLERequestContext& ctx) {
1123 IPC::RequestParser rp{ctx}; 1124 IPC::RequestParser rp{ctx};
1124 const auto applet_resource_user_id{rp.Pop<u64>()}; 1125 const auto applet_resource_user_id{rp.Pop<u64>()};
1125 const auto hold_type{rp.PopEnum<NPad::NpadJoyHoldType>()}; 1126 const auto hold_type{rp.PopEnum<NpadJoyHoldType>()};
1126 1127
1127 GetResourceManager()->GetNpad()->SetHoldType(hold_type); 1128 GetResourceManager()->GetNpad()->SetHoldType(hold_type);
1128 1129
@@ -1157,8 +1158,8 @@ void IHidServer::SetNpadJoyAssignmentModeSingleByDefault(HLERequestContext& ctx)
1157 1158
1158 Core::HID::NpadIdType new_npad_id{}; 1159 Core::HID::NpadIdType new_npad_id{};
1159 auto controller = GetResourceManager()->GetNpad(); 1160 auto controller = GetResourceManager()->GetNpad();
1160 controller->SetNpadMode(new_npad_id, parameters.npad_id, NPad::NpadJoyDeviceType::Left, 1161 controller->SetNpadMode(new_npad_id, parameters.npad_id, NpadJoyDeviceType::Left,
1161 NPad::NpadJoyAssignmentMode::Single); 1162 NpadJoyAssignmentMode::Single);
1162 1163
1163 LOG_INFO(Service_HID, "called, npad_id={}, applet_resource_user_id={}", parameters.npad_id, 1164 LOG_INFO(Service_HID, "called, npad_id={}, applet_resource_user_id={}", parameters.npad_id,
1164 parameters.applet_resource_user_id); 1165 parameters.applet_resource_user_id);
@@ -1173,7 +1174,7 @@ void IHidServer::SetNpadJoyAssignmentModeSingle(HLERequestContext& ctx) {
1173 Core::HID::NpadIdType npad_id; 1174 Core::HID::NpadIdType npad_id;
1174 INSERT_PADDING_WORDS_NOINIT(1); 1175 INSERT_PADDING_WORDS_NOINIT(1);
1175 u64 applet_resource_user_id; 1176 u64 applet_resource_user_id;
1176 NPad::NpadJoyDeviceType npad_joy_device_type; 1177 NpadJoyDeviceType npad_joy_device_type;
1177 }; 1178 };
1178 static_assert(sizeof(Parameters) == 0x18, "Parameters has incorrect size."); 1179 static_assert(sizeof(Parameters) == 0x18, "Parameters has incorrect size.");
1179 1180
@@ -1182,7 +1183,7 @@ void IHidServer::SetNpadJoyAssignmentModeSingle(HLERequestContext& ctx) {
1182 Core::HID::NpadIdType new_npad_id{}; 1183 Core::HID::NpadIdType new_npad_id{};
1183 auto controller = GetResourceManager()->GetNpad(); 1184 auto controller = GetResourceManager()->GetNpad();
1184 controller->SetNpadMode(new_npad_id, parameters.npad_id, parameters.npad_joy_device_type, 1185 controller->SetNpadMode(new_npad_id, parameters.npad_id, parameters.npad_joy_device_type,
1185 NPad::NpadJoyAssignmentMode::Single); 1186 NpadJoyAssignmentMode::Single);
1186 1187
1187 LOG_INFO(Service_HID, "called, npad_id={}, applet_resource_user_id={}, npad_joy_device_type={}", 1188 LOG_INFO(Service_HID, "called, npad_id={}, applet_resource_user_id={}, npad_joy_device_type={}",
1188 parameters.npad_id, parameters.applet_resource_user_id, 1189 parameters.npad_id, parameters.applet_resource_user_id,
@@ -1205,7 +1206,7 @@ void IHidServer::SetNpadJoyAssignmentModeDual(HLERequestContext& ctx) {
1205 1206
1206 Core::HID::NpadIdType new_npad_id{}; 1207 Core::HID::NpadIdType new_npad_id{};
1207 auto controller = GetResourceManager()->GetNpad(); 1208 auto controller = GetResourceManager()->GetNpad();
1208 controller->SetNpadMode(new_npad_id, parameters.npad_id, {}, NPad::NpadJoyAssignmentMode::Dual); 1209 controller->SetNpadMode(new_npad_id, parameters.npad_id, {}, NpadJoyAssignmentMode::Dual);
1209 1210
1210 LOG_DEBUG(Service_HID, "called, npad_id={}, applet_resource_user_id={}", parameters.npad_id, 1211 LOG_DEBUG(Service_HID, "called, npad_id={}, applet_resource_user_id={}", parameters.npad_id,
1211 parameters.applet_resource_user_id); // Spams a lot when controller applet is open 1212 parameters.applet_resource_user_id); // Spams a lot when controller applet is open
@@ -1257,7 +1258,7 @@ void IHidServer::StopLrAssignmentMode(HLERequestContext& ctx) {
1257void IHidServer::SetNpadHandheldActivationMode(HLERequestContext& ctx) { 1258void IHidServer::SetNpadHandheldActivationMode(HLERequestContext& ctx) {
1258 IPC::RequestParser rp{ctx}; 1259 IPC::RequestParser rp{ctx};
1259 const auto applet_resource_user_id{rp.Pop<u64>()}; 1260 const auto applet_resource_user_id{rp.Pop<u64>()};
1260 const auto activation_mode{rp.PopEnum<NPad::NpadHandheldActivationMode>()}; 1261 const auto activation_mode{rp.PopEnum<NpadHandheldActivationMode>()};
1261 1262
1262 GetResourceManager()->GetNpad()->SetNpadHandheldActivationMode(activation_mode); 1263 GetResourceManager()->GetNpad()->SetNpadHandheldActivationMode(activation_mode);
1263 1264
@@ -1349,7 +1350,7 @@ void IHidServer::SetNpadJoyAssignmentModeSingleWithDestination(HLERequestContext
1349 Core::HID::NpadIdType npad_id; 1350 Core::HID::NpadIdType npad_id;
1350 INSERT_PADDING_WORDS_NOINIT(1); 1351 INSERT_PADDING_WORDS_NOINIT(1);
1351 u64 applet_resource_user_id; 1352 u64 applet_resource_user_id;
1352 NPad::NpadJoyDeviceType npad_joy_device_type; 1353 NpadJoyDeviceType npad_joy_device_type;
1353 }; 1354 };
1354 static_assert(sizeof(Parameters) == 0x18, "Parameters has incorrect size."); 1355 static_assert(sizeof(Parameters) == 0x18, "Parameters has incorrect size.");
1355 1356
@@ -1359,7 +1360,7 @@ void IHidServer::SetNpadJoyAssignmentModeSingleWithDestination(HLERequestContext
1359 auto controller = GetResourceManager()->GetNpad(); 1360 auto controller = GetResourceManager()->GetNpad();
1360 const auto is_reassigned = 1361 const auto is_reassigned =
1361 controller->SetNpadMode(new_npad_id, parameters.npad_id, parameters.npad_joy_device_type, 1362 controller->SetNpadMode(new_npad_id, parameters.npad_id, parameters.npad_joy_device_type,
1362 NPad::NpadJoyAssignmentMode::Single); 1363 NpadJoyAssignmentMode::Single);
1363 1364
1364 LOG_INFO(Service_HID, "called, npad_id={}, applet_resource_user_id={}, npad_joy_device_type={}", 1365 LOG_INFO(Service_HID, "called, npad_id={}, applet_resource_user_id={}, npad_joy_device_type={}",
1365 parameters.npad_id, parameters.applet_resource_user_id, 1366 parameters.npad_id, parameters.applet_resource_user_id,
@@ -2315,7 +2316,7 @@ void IHidServer::SetDisallowedPalmaConnection(HLERequestContext& ctx) {
2315void IHidServer::SetNpadCommunicationMode(HLERequestContext& ctx) { 2316void IHidServer::SetNpadCommunicationMode(HLERequestContext& ctx) {
2316 IPC::RequestParser rp{ctx}; 2317 IPC::RequestParser rp{ctx};
2317 const auto applet_resource_user_id{rp.Pop<u64>()}; 2318 const auto applet_resource_user_id{rp.Pop<u64>()};
2318 const auto communication_mode{rp.PopEnum<NPad::NpadCommunicationMode>()}; 2319 const auto communication_mode{rp.PopEnum<NpadCommunicationMode>()};
2319 2320
2320 GetResourceManager()->GetNpad()->SetNpadCommunicationMode(communication_mode); 2321 GetResourceManager()->GetNpad()->SetNpadCommunicationMode(communication_mode);
2321 2322
diff --git a/src/core/hle/service/hid/hid_system_server.cpp b/src/core/hle/service/hid/hid_system_server.cpp
index 4d33456a3..5cc88c4a1 100644
--- a/src/core/hle/service/hid/hid_system_server.cpp
+++ b/src/core/hle/service/hid/hid_system_server.cpp
@@ -5,6 +5,7 @@
5#include "core/hle/service/hid/controllers/npad.h" 5#include "core/hle/service/hid/controllers/npad.h"
6#include "core/hle/service/hid/controllers/palma.h" 6#include "core/hle/service/hid/controllers/palma.h"
7#include "core/hle/service/hid/controllers/touchscreen.h" 7#include "core/hle/service/hid/controllers/touchscreen.h"
8#include "core/hle/service/hid/controllers/types/npad_types.h"
8#include "core/hle/service/hid/errors.h" 9#include "core/hle/service/hid/errors.h"
9#include "core/hle/service/hid/hid_system_server.h" 10#include "core/hle/service/hid/hid_system_server.h"
10#include "core/hle/service/hid/resource_manager.h" 11#include "core/hle/service/hid/resource_manager.h"
@@ -328,7 +329,7 @@ void IHidSystemServer::GetAppletDetailedUiType(HLERequestContext& ctx) {
328 LOG_DEBUG(Service_HID, "called, npad_id_type={}", 329 LOG_DEBUG(Service_HID, "called, npad_id_type={}",
329 npad_id_type); // Spams a lot when controller applet is running 330 npad_id_type); // Spams a lot when controller applet is running
330 331
331 const NPad::AppletDetailedUiType detailed_ui_type = 332 const AppletDetailedUiType detailed_ui_type =
332 GetResourceManager()->GetNpad()->GetAppletDetailedUiType(npad_id_type); 333 GetResourceManager()->GetNpad()->GetAppletDetailedUiType(npad_id_type);
333 334
334 IPC::ResponseBuilder rb{ctx, 3}; 335 IPC::ResponseBuilder rb{ctx, 3};
diff --git a/src/core/hle/service/hid/resource_manager.cpp b/src/core/hle/service/hid/resource_manager.cpp
index 89cdc19cc..6c6cbd802 100644
--- a/src/core/hle/service/hid/resource_manager.cpp
+++ b/src/core/hle/service/hid/resource_manager.cpp
@@ -18,10 +18,10 @@
18#include "core/hle/service/hid/controllers/npad.h" 18#include "core/hle/service/hid/controllers/npad.h"
19#include "core/hle/service/hid/controllers/palma.h" 19#include "core/hle/service/hid/controllers/palma.h"
20#include "core/hle/service/hid/controllers/seven_six_axis.h" 20#include "core/hle/service/hid/controllers/seven_six_axis.h"
21#include "core/hle/service/hid/controllers/shared_memory_format.h"
21#include "core/hle/service/hid/controllers/six_axis.h" 22#include "core/hle/service/hid/controllers/six_axis.h"
22#include "core/hle/service/hid/controllers/stubbed.h" 23#include "core/hle/service/hid/controllers/stubbed.h"
23#include "core/hle/service/hid/controllers/touchscreen.h" 24#include "core/hle/service/hid/controllers/touchscreen.h"
24#include "core/hle/service/hid/controllers/xpad.h"
25 25
26namespace Service::HID { 26namespace Service::HID {
27 27
@@ -45,40 +45,43 @@ void ResourceManager::Initialize() {
45 return; 45 return;
46 } 46 }
47 47
48 u8* shared_memory = system.Kernel().GetHidSharedMem().GetPointer(); 48 system.HIDCore().ReloadInputDevices();
49 debug_pad = std::make_shared<DebugPad>(system.HIDCore(), shared_memory); 49 is_initialized = true;
50 mouse = std::make_shared<Mouse>(system.HIDCore(), shared_memory); 50}
51 debug_mouse = std::make_shared<DebugMouse>(system.HIDCore(), shared_memory); 51
52 keyboard = std::make_shared<Keyboard>(system.HIDCore(), shared_memory); 52void ResourceManager::InitializeController(u64 aruid) {
53 unique_pad = std::make_shared<UniquePad>(system.HIDCore(), shared_memory); 53 SharedMemoryFormat* shared_memory = nullptr;
54 npad = std::make_shared<NPad>(system.HIDCore(), shared_memory, service_context); 54 const auto result = applet_resource->GetSharedMemoryFormat(&shared_memory, aruid);
55 gesture = std::make_shared<Gesture>(system.HIDCore(), shared_memory); 55 if (result.IsError()) {
56 touch_screen = std::make_shared<TouchScreen>(system.HIDCore(), shared_memory); 56 return;
57 xpad = std::make_shared<XPad>(system.HIDCore(), shared_memory); 57 }
58
59 debug_pad = std::make_shared<DebugPad>(system.HIDCore(), shared_memory->debug_pad);
60 mouse = std::make_shared<Mouse>(system.HIDCore(), shared_memory->mouse);
61 debug_mouse = std::make_shared<DebugMouse>(system.HIDCore(), shared_memory->debug_mouse);
62 keyboard = std::make_shared<Keyboard>(system.HIDCore(), shared_memory->keyboard);
63 unique_pad = std::make_shared<UniquePad>(system.HIDCore(), shared_memory->unique_pad.header);
64 npad = std::make_shared<NPad>(system.HIDCore(), shared_memory->npad, service_context);
65 gesture = std::make_shared<Gesture>(system.HIDCore(), shared_memory->gesture);
66 touch_screen = std::make_shared<TouchScreen>(system.HIDCore(), shared_memory->touch_screen);
58 67
59 palma = std::make_shared<Palma>(system.HIDCore(), shared_memory, service_context); 68 palma = std::make_shared<Palma>(system.HIDCore(), service_context);
60 69
61 home_button = std::make_shared<HomeButton>(system.HIDCore(), shared_memory); 70 home_button = std::make_shared<HomeButton>(system.HIDCore(), shared_memory->home_button.header);
62 sleep_button = std::make_shared<SleepButton>(system.HIDCore(), shared_memory); 71 sleep_button =
63 capture_button = std::make_shared<CaptureButton>(system.HIDCore(), shared_memory); 72 std::make_shared<SleepButton>(system.HIDCore(), shared_memory->sleep_button.header);
73 capture_button =
74 std::make_shared<CaptureButton>(system.HIDCore(), shared_memory->capture_button.header);
75 digitizer = std::make_shared<Digitizer>(system.HIDCore(), shared_memory->digitizer.header);
64 76
65 six_axis = std::make_shared<SixAxis>(system.HIDCore(), npad); 77 six_axis = std::make_shared<SixAxis>(system.HIDCore(), npad);
66 console_six_axis = std::make_shared<ConsoleSixAxis>(system.HIDCore(), shared_memory); 78 console_six_axis = std::make_shared<ConsoleSixAxis>(system.HIDCore(), shared_memory->console);
67 seven_six_axis = std::make_shared<SevenSixAxis>(system); 79 seven_six_axis = std::make_shared<SevenSixAxis>(system);
68 80
69 home_button->SetCommonHeaderOffset(0x4C00);
70 sleep_button->SetCommonHeaderOffset(0x4E00);
71 capture_button->SetCommonHeaderOffset(0x5000);
72 unique_pad->SetCommonHeaderOffset(0x5A00);
73 debug_mouse->SetCommonHeaderOffset(0x3DC00);
74
75 // Homebrew doesn't try to activate some controllers, so we activate them by default 81 // Homebrew doesn't try to activate some controllers, so we activate them by default
76 npad->Activate(); 82 npad->Activate();
77 six_axis->Activate(); 83 six_axis->Activate();
78 touch_screen->Activate(); 84 touch_screen->Activate();
79
80 system.HIDCore().ReloadInputDevices();
81 is_initialized = true;
82} 85}
83 86
84std::shared_ptr<AppletResource> ResourceManager::GetAppletResource() const { 87std::shared_ptr<AppletResource> ResourceManager::GetAppletResource() const {
@@ -101,6 +104,10 @@ std::shared_ptr<DebugPad> ResourceManager::GetDebugPad() const {
101 return debug_pad; 104 return debug_pad;
102} 105}
103 106
107std::shared_ptr<Digitizer> ResourceManager::GetDigitizer() const {
108 return digitizer;
109}
110
104std::shared_ptr<Gesture> ResourceManager::GetGesture() const { 111std::shared_ptr<Gesture> ResourceManager::GetGesture() const {
105 return gesture; 112 return gesture;
106} 113}
@@ -163,7 +170,11 @@ Result ResourceManager::CreateAppletResource(u64 aruid) {
163 170
164Result ResourceManager::CreateAppletResourceImpl(u64 aruid) { 171Result ResourceManager::CreateAppletResourceImpl(u64 aruid) {
165 std::scoped_lock lock{shared_mutex}; 172 std::scoped_lock lock{shared_mutex};
166 return applet_resource->CreateAppletResource(aruid); 173 const auto result = applet_resource->CreateAppletResource(aruid);
174 if (result.IsSuccess()) {
175 InitializeController(aruid);
176 }
177 return result;
167} 178}
168 179
169Result ResourceManager::RegisterCoreAppletResource() { 180Result ResourceManager::RegisterCoreAppletResource() {
@@ -220,6 +231,7 @@ void ResourceManager::UpdateControllers(std::uintptr_t user_data,
220 std::chrono::nanoseconds ns_late) { 231 std::chrono::nanoseconds ns_late) {
221 auto& core_timing = system.CoreTiming(); 232 auto& core_timing = system.CoreTiming();
222 debug_pad->OnUpdate(core_timing); 233 debug_pad->OnUpdate(core_timing);
234 digitizer->OnUpdate(core_timing);
223 unique_pad->OnUpdate(core_timing); 235 unique_pad->OnUpdate(core_timing);
224 gesture->OnUpdate(core_timing); 236 gesture->OnUpdate(core_timing);
225 touch_screen->OnUpdate(core_timing); 237 touch_screen->OnUpdate(core_timing);
@@ -227,7 +239,6 @@ void ResourceManager::UpdateControllers(std::uintptr_t user_data,
227 home_button->OnUpdate(core_timing); 239 home_button->OnUpdate(core_timing);
228 sleep_button->OnUpdate(core_timing); 240 sleep_button->OnUpdate(core_timing);
229 capture_button->OnUpdate(core_timing); 241 capture_button->OnUpdate(core_timing);
230 xpad->OnUpdate(core_timing);
231} 242}
232 243
233void ResourceManager::UpdateNpad(std::uintptr_t user_data, std::chrono::nanoseconds ns_late) { 244void ResourceManager::UpdateNpad(std::uintptr_t user_data, std::chrono::nanoseconds ns_late) {
diff --git a/src/core/hle/service/hid/resource_manager.h b/src/core/hle/service/hid/resource_manager.h
index 15c1beb1a..5ad7cb564 100644
--- a/src/core/hle/service/hid/resource_manager.h
+++ b/src/core/hle/service/hid/resource_manager.h
@@ -31,10 +31,10 @@ class Palma;
31class SevenSixAxis; 31class SevenSixAxis;
32class SixAxis; 32class SixAxis;
33class TouchScreen; 33class TouchScreen;
34class XPad;
35 34
36using CaptureButton = Controller_Stubbed; 35using CaptureButton = Controller_Stubbed;
37using DebugMouse = Controller_Stubbed; 36using DebugMouse = Mouse;
37using Digitizer = Controller_Stubbed;
38using HomeButton = Controller_Stubbed; 38using HomeButton = Controller_Stubbed;
39using SleepButton = Controller_Stubbed; 39using SleepButton = Controller_Stubbed;
40using UniquePad = Controller_Stubbed; 40using UniquePad = Controller_Stubbed;
@@ -46,12 +46,14 @@ public:
46 ~ResourceManager(); 46 ~ResourceManager();
47 47
48 void Initialize(); 48 void Initialize();
49 void InitializeController(u64 aruid);
49 50
50 std::shared_ptr<AppletResource> GetAppletResource() const; 51 std::shared_ptr<AppletResource> GetAppletResource() const;
51 std::shared_ptr<CaptureButton> GetCaptureButton() const; 52 std::shared_ptr<CaptureButton> GetCaptureButton() const;
52 std::shared_ptr<ConsoleSixAxis> GetConsoleSixAxis() const; 53 std::shared_ptr<ConsoleSixAxis> GetConsoleSixAxis() const;
53 std::shared_ptr<DebugMouse> GetDebugMouse() const; 54 std::shared_ptr<DebugMouse> GetDebugMouse() const;
54 std::shared_ptr<DebugPad> GetDebugPad() const; 55 std::shared_ptr<DebugPad> GetDebugPad() const;
56 std::shared_ptr<Digitizer> GetDigitizer() const;
55 std::shared_ptr<Gesture> GetGesture() const; 57 std::shared_ptr<Gesture> GetGesture() const;
56 std::shared_ptr<HomeButton> GetHomeButton() const; 58 std::shared_ptr<HomeButton> GetHomeButton() const;
57 std::shared_ptr<Keyboard> GetKeyboard() const; 59 std::shared_ptr<Keyboard> GetKeyboard() const;
@@ -96,6 +98,7 @@ private:
96 std::shared_ptr<ConsoleSixAxis> console_six_axis = nullptr; 98 std::shared_ptr<ConsoleSixAxis> console_six_axis = nullptr;
97 std::shared_ptr<DebugMouse> debug_mouse = nullptr; 99 std::shared_ptr<DebugMouse> debug_mouse = nullptr;
98 std::shared_ptr<DebugPad> debug_pad = nullptr; 100 std::shared_ptr<DebugPad> debug_pad = nullptr;
101 std::shared_ptr<Digitizer> digitizer = nullptr;
99 std::shared_ptr<Gesture> gesture = nullptr; 102 std::shared_ptr<Gesture> gesture = nullptr;
100 std::shared_ptr<HomeButton> home_button = nullptr; 103 std::shared_ptr<HomeButton> home_button = nullptr;
101 std::shared_ptr<Keyboard> keyboard = nullptr; 104 std::shared_ptr<Keyboard> keyboard = nullptr;
@@ -107,7 +110,6 @@ private:
107 std::shared_ptr<SleepButton> sleep_button = nullptr; 110 std::shared_ptr<SleepButton> sleep_button = nullptr;
108 std::shared_ptr<TouchScreen> touch_screen = nullptr; 111 std::shared_ptr<TouchScreen> touch_screen = nullptr;
109 std::shared_ptr<UniquePad> unique_pad = nullptr; 112 std::shared_ptr<UniquePad> unique_pad = nullptr;
110 std::shared_ptr<XPad> xpad = nullptr;
111 113
112 // TODO: Create these resources 114 // TODO: Create these resources
113 // std::shared_ptr<AudioControl> audio_control = nullptr; 115 // std::shared_ptr<AudioControl> audio_control = nullptr;
diff --git a/src/core/hle/service/ssl/ssl.cpp b/src/core/hle/service/ssl/ssl.cpp
index 6c8427b0d..0fbb43057 100644
--- a/src/core/hle/service/ssl/ssl.cpp
+++ b/src/core/hle/service/ssl/ssl.cpp
@@ -240,7 +240,7 @@ private:
240 return ret; 240 return ret;
241 } 241 }
242 242
243 Result ReadImpl(std::vector<u8>* out_data, size_t size) { 243 Result ReadImpl(std::vector<u8>* out_data) {
244 ASSERT_OR_EXECUTE(did_handshake, { return ResultInternalError; }); 244 ASSERT_OR_EXECUTE(did_handshake, { return ResultInternalError; });
245 size_t actual_size{}; 245 size_t actual_size{};
246 Result res = backend->Read(&actual_size, *out_data); 246 Result res = backend->Read(&actual_size, *out_data);
@@ -326,8 +326,8 @@ private:
326 } 326 }
327 327
328 void Read(HLERequestContext& ctx) { 328 void Read(HLERequestContext& ctx) {
329 std::vector<u8> output_bytes; 329 std::vector<u8> output_bytes(ctx.GetWriteBufferSize());
330 const Result res = ReadImpl(&output_bytes, ctx.GetWriteBufferSize()); 330 const Result res = ReadImpl(&output_bytes);
331 IPC::ResponseBuilder rb{ctx, 3}; 331 IPC::ResponseBuilder rb{ctx, 3};
332 rb.Push(res); 332 rb.Push(res);
333 if (res == ResultSuccess) { 333 if (res == ResultSuccess) {
diff --git a/src/core/memory/cheat_engine.cpp b/src/core/memory/cheat_engine.cpp
index db30ba598..3fc4024dc 100644
--- a/src/core/memory/cheat_engine.cpp
+++ b/src/core/memory/cheat_engine.cpp
@@ -62,7 +62,7 @@ u64 StandardVmCallbacks::HidKeysDown() {
62 } 62 }
63 63
64 const auto applet_resource = hid->GetResourceManager(); 64 const auto applet_resource = hid->GetResourceManager();
65 if (applet_resource == nullptr) { 65 if (applet_resource == nullptr || applet_resource->GetNpad() == nullptr) {
66 LOG_WARNING(CheatEngine, 66 LOG_WARNING(CheatEngine,
67 "Attempted to read input state, but applet resource is not initialized!"); 67 "Attempted to read input state, but applet resource is not initialized!");
68 return 0; 68 return 0;
diff --git a/src/tests/video_core/memory_tracker.cpp b/src/tests/video_core/memory_tracker.cpp
index 618793668..2dbff21af 100644
--- a/src/tests/video_core/memory_tracker.cpp
+++ b/src/tests/video_core/memory_tracker.cpp
@@ -23,13 +23,13 @@ constexpr VAddr c = 16 * HIGH_PAGE_SIZE;
23 23
24class RasterizerInterface { 24class RasterizerInterface {
25public: 25public:
26 void UpdatePagesCachedCount(VAddr addr, u64 size, int delta) { 26 void UpdatePagesCachedCount(VAddr addr, u64 size, bool cache) {
27 const u64 page_start{addr >> Core::Memory::YUZU_PAGEBITS}; 27 const u64 page_start{addr >> Core::Memory::YUZU_PAGEBITS};
28 const u64 page_end{(addr + size + Core::Memory::YUZU_PAGESIZE - 1) >> 28 const u64 page_end{(addr + size + Core::Memory::YUZU_PAGESIZE - 1) >>
29 Core::Memory::YUZU_PAGEBITS}; 29 Core::Memory::YUZU_PAGEBITS};
30 for (u64 page = page_start; page < page_end; ++page) { 30 for (u64 page = page_start; page < page_end; ++page) {
31 int& value = page_table[page]; 31 int& value = page_table[page];
32 value += delta; 32 value += (cache ? 1 : -1);
33 if (value < 0) { 33 if (value < 0) {
34 throw std::logic_error{"negative page"}; 34 throw std::logic_error{"negative page"};
35 } 35 }
@@ -546,4 +546,4 @@ TEST_CASE("MemoryTracker: Cached write downloads") {
546 REQUIRE(!memory_track->IsRegionGpuModified(c + PAGE, PAGE)); 546 REQUIRE(!memory_track->IsRegionGpuModified(c + PAGE, PAGE));
547 memory_track->MarkRegionAsCpuModified(c, WORD); 547 memory_track->MarkRegionAsCpuModified(c, WORD);
548 REQUIRE(rasterizer.Count() == 0); 548 REQUIRE(rasterizer.Count() == 0);
549} \ No newline at end of file 549}
diff --git a/src/video_core/buffer_cache/word_manager.h b/src/video_core/buffer_cache/word_manager.h
index a336bde41..95b752055 100644
--- a/src/video_core/buffer_cache/word_manager.h
+++ b/src/video_core/buffer_cache/word_manager.h
@@ -473,7 +473,7 @@ private:
473 VAddr addr = cpu_addr + word_index * BYTES_PER_WORD; 473 VAddr addr = cpu_addr + word_index * BYTES_PER_WORD;
474 IteratePages(changed_bits, [&](size_t offset, size_t size) { 474 IteratePages(changed_bits, [&](size_t offset, size_t size) {
475 rasterizer->UpdatePagesCachedCount(addr + offset * BYTES_PER_PAGE, 475 rasterizer->UpdatePagesCachedCount(addr + offset * BYTES_PER_PAGE,
476 size * BYTES_PER_PAGE, add_to_rasterizer ? 1 : -1); 476 size * BYTES_PER_PAGE, add_to_rasterizer);
477 }); 477 });
478 } 478 }
479 479
diff --git a/src/video_core/rasterizer_accelerated.cpp b/src/video_core/rasterizer_accelerated.cpp
index f200a650f..3c9477f6e 100644
--- a/src/video_core/rasterizer_accelerated.cpp
+++ b/src/video_core/rasterizer_accelerated.cpp
@@ -3,6 +3,7 @@
3 3
4#include <atomic> 4#include <atomic>
5 5
6#include "common/alignment.h"
6#include "common/assert.h" 7#include "common/assert.h"
7#include "common/common_types.h" 8#include "common/common_types.h"
8#include "common/div_ceil.h" 9#include "common/div_ceil.h"
@@ -11,61 +12,65 @@
11 12
12namespace VideoCore { 13namespace VideoCore {
13 14
15static constexpr u16 IdentityValue = 1;
16
14using namespace Core::Memory; 17using namespace Core::Memory;
15 18
16RasterizerAccelerated::RasterizerAccelerated(Memory& cpu_memory_) 19RasterizerAccelerated::RasterizerAccelerated(Memory& cpu_memory_) : map{}, cpu_memory{cpu_memory_} {
17 : cached_pages(std::make_unique<CachedPages>()), cpu_memory{cpu_memory_} {} 20 // We are tracking CPU memory, which cannot map more than 39 bits.
21 const VAddr start_address = 0;
22 const VAddr end_address = (1ULL << 39);
23 const IntervalType address_space_interval(start_address, end_address);
24 const auto value = std::make_pair(address_space_interval, IdentityValue);
25
26 map.add(value);
27}
18 28
19RasterizerAccelerated::~RasterizerAccelerated() = default; 29RasterizerAccelerated::~RasterizerAccelerated() = default;
20 30
21void RasterizerAccelerated::UpdatePagesCachedCount(VAddr addr, u64 size, int delta) { 31void RasterizerAccelerated::UpdatePagesCachedCount(VAddr addr, u64 size, bool cache) {
22 u64 uncache_begin = 0; 32 std::scoped_lock lk{map_lock};
23 u64 cache_begin = 0;
24 u64 uncache_bytes = 0;
25 u64 cache_bytes = 0;
26
27 std::atomic_thread_fence(std::memory_order_acquire);
28 const u64 page_end = Common::DivCeil(addr + size, YUZU_PAGESIZE);
29 for (u64 page = addr >> YUZU_PAGEBITS; page != page_end; ++page) {
30 std::atomic_uint16_t& count = cached_pages->at(page >> 2).Count(page);
31
32 if (delta > 0) {
33 ASSERT_MSG(count.load(std::memory_order::relaxed) < UINT16_MAX, "Count may overflow!");
34 } else if (delta < 0) {
35 ASSERT_MSG(count.load(std::memory_order::relaxed) > 0, "Count may underflow!");
36 } else {
37 ASSERT_MSG(false, "Delta must be non-zero!");
38 }
39 33
40 // Adds or subtracts 1, as count is a unsigned 8-bit value 34 // Align sizes.
41 count.fetch_add(static_cast<u16>(delta), std::memory_order_release); 35 addr = Common::AlignDown(addr, YUZU_PAGESIZE);
42 36 size = Common::AlignUp(size, YUZU_PAGESIZE);
43 // Assume delta is either -1 or 1 37
44 if (count.load(std::memory_order::relaxed) == 0) { 38 // Declare the overall interval we are going to operate on.
45 if (uncache_bytes == 0) { 39 const VAddr start_address = addr;
46 uncache_begin = page; 40 const VAddr end_address = addr + size;
47 } 41 const IntervalType modification_range(start_address, end_address);
48 uncache_bytes += YUZU_PAGESIZE; 42
49 } else if (uncache_bytes > 0) { 43 // Find the boundaries of where to iterate.
50 cpu_memory.RasterizerMarkRegionCached(uncache_begin << YUZU_PAGEBITS, uncache_bytes, 44 const auto lower = map.lower_bound(modification_range);
51 false); 45 const auto upper = map.upper_bound(modification_range);
52 uncache_bytes = 0; 46
53 } 47 // Iterate over the contained intervals.
54 if (count.load(std::memory_order::relaxed) == 1 && delta > 0) { 48 for (auto it = lower; it != upper; it++) {
55 if (cache_bytes == 0) { 49 // Intersect interval range with modification range.
56 cache_begin = page; 50 const auto current_range = modification_range & it->first;
57 } 51
58 cache_bytes += YUZU_PAGESIZE; 52 // Calculate the address and size to operate over.
59 } else if (cache_bytes > 0) { 53 const auto current_addr = current_range.lower();
60 cpu_memory.RasterizerMarkRegionCached(cache_begin << YUZU_PAGEBITS, cache_bytes, true); 54 const auto current_size = current_range.upper() - current_addr;
61 cache_bytes = 0; 55
56 // Get the current value of the range.
57 const auto value = it->second;
58
59 if (cache && value == IdentityValue) {
60 // If we are going to cache, and the value is not yet referenced, then cache this range.
61 cpu_memory.RasterizerMarkRegionCached(current_addr, current_size, true);
62 } else if (!cache && value == IdentityValue + 1) {
63 // If we are going to uncache, and this is the last reference, then uncache this range.
64 cpu_memory.RasterizerMarkRegionCached(current_addr, current_size, false);
62 } 65 }
63 } 66 }
64 if (uncache_bytes > 0) { 67
65 cpu_memory.RasterizerMarkRegionCached(uncache_begin << YUZU_PAGEBITS, uncache_bytes, false); 68 // Update the set.
66 } 69 const auto value = std::make_pair(modification_range, IdentityValue);
67 if (cache_bytes > 0) { 70 if (cache) {
68 cpu_memory.RasterizerMarkRegionCached(cache_begin << YUZU_PAGEBITS, cache_bytes, true); 71 map.add(value);
72 } else {
73 map.subtract(value);
69 } 74 }
70} 75}
71 76
diff --git a/src/video_core/rasterizer_accelerated.h b/src/video_core/rasterizer_accelerated.h
index e6c0ea87a..f1968f186 100644
--- a/src/video_core/rasterizer_accelerated.h
+++ b/src/video_core/rasterizer_accelerated.h
@@ -3,8 +3,8 @@
3 3
4#pragma once 4#pragma once
5 5
6#include <array> 6#include <mutex>
7#include <atomic> 7#include <boost/icl/interval_map.hpp>
8 8
9#include "common/common_types.h" 9#include "common/common_types.h"
10#include "video_core/rasterizer_interface.h" 10#include "video_core/rasterizer_interface.h"
@@ -21,28 +21,17 @@ public:
21 explicit RasterizerAccelerated(Core::Memory::Memory& cpu_memory_); 21 explicit RasterizerAccelerated(Core::Memory::Memory& cpu_memory_);
22 ~RasterizerAccelerated() override; 22 ~RasterizerAccelerated() override;
23 23
24 void UpdatePagesCachedCount(VAddr addr, u64 size, int delta) override; 24 void UpdatePagesCachedCount(VAddr addr, u64 size, bool cache) override;
25 25
26private: 26private:
27 class CacheEntry final { 27 using PageIndex = VAddr;
28 public: 28 using PageReferenceCount = u16;
29 CacheEntry() = default;
30 29
31 std::atomic_uint16_t& Count(std::size_t page) { 30 using IntervalMap = boost::icl::interval_map<PageIndex, PageReferenceCount>;
32 return values[page & 3]; 31 using IntervalType = IntervalMap::interval_type;
33 }
34 32
35 const std::atomic_uint16_t& Count(std::size_t page) const { 33 IntervalMap map;
36 return values[page & 3]; 34 std::mutex map_lock;
37 }
38
39 private:
40 std::array<std::atomic_uint16_t, 4> values{};
41 };
42 static_assert(sizeof(CacheEntry) == 8, "CacheEntry should be 8 bytes!");
43
44 using CachedPages = std::array<CacheEntry, 0x2000000>;
45 std::unique_ptr<CachedPages> cached_pages;
46 Core::Memory::Memory& cpu_memory; 35 Core::Memory::Memory& cpu_memory;
47}; 36};
48 37
diff --git a/src/video_core/rasterizer_interface.h b/src/video_core/rasterizer_interface.h
index af1469147..fd42d26b5 100644
--- a/src/video_core/rasterizer_interface.h
+++ b/src/video_core/rasterizer_interface.h
@@ -162,7 +162,7 @@ public:
162 } 162 }
163 163
164 /// Increase/decrease the number of object in pages touching the specified region 164 /// Increase/decrease the number of object in pages touching the specified region
165 virtual void UpdatePagesCachedCount(VAddr addr, u64 size, int delta) {} 165 virtual void UpdatePagesCachedCount(VAddr addr, u64 size, bool cache) {}
166 166
167 /// Initialize disk cached resources for the game being emulated 167 /// Initialize disk cached resources for the game being emulated
168 virtual void LoadDiskResources(u64 title_id, std::stop_token stop_loading, 168 virtual void LoadDiskResources(u64 title_id, std::stop_token stop_loading,
diff --git a/src/video_core/shader_cache.cpp b/src/video_core/shader_cache.cpp
index e81cd031b..a109f9cbe 100644
--- a/src/video_core/shader_cache.cpp
+++ b/src/video_core/shader_cache.cpp
@@ -132,7 +132,7 @@ void ShaderCache::Register(std::unique_ptr<ShaderInfo> data, VAddr addr, size_t
132 132
133 storage.push_back(std::move(data)); 133 storage.push_back(std::move(data));
134 134
135 rasterizer.UpdatePagesCachedCount(addr, size, 1); 135 rasterizer.UpdatePagesCachedCount(addr, size, true);
136} 136}
137 137
138void ShaderCache::InvalidatePagesInRegion(VAddr addr, size_t size) { 138void ShaderCache::InvalidatePagesInRegion(VAddr addr, size_t size) {
@@ -209,7 +209,7 @@ void ShaderCache::UnmarkMemory(Entry* entry) {
209 209
210 const VAddr addr = entry->addr_start; 210 const VAddr addr = entry->addr_start;
211 const size_t size = entry->addr_end - addr; 211 const size_t size = entry->addr_end - addr;
212 rasterizer.UpdatePagesCachedCount(addr, size, -1); 212 rasterizer.UpdatePagesCachedCount(addr, size, false);
213} 213}
214 214
215void ShaderCache::RemoveShadersFromStorage(std::span<ShaderInfo*> removed_shaders) { 215void ShaderCache::RemoveShadersFromStorage(std::span<ShaderInfo*> removed_shaders) {
diff --git a/src/video_core/texture_cache/texture_cache.h b/src/video_core/texture_cache/texture_cache.h
index 0d5a1709f..d7941f6a4 100644
--- a/src/video_core/texture_cache/texture_cache.h
+++ b/src/video_core/texture_cache/texture_cache.h
@@ -2080,7 +2080,7 @@ void TextureCache<P>::TrackImage(ImageBase& image, ImageId image_id) {
2080 ASSERT(False(image.flags & ImageFlagBits::Tracked)); 2080 ASSERT(False(image.flags & ImageFlagBits::Tracked));
2081 image.flags |= ImageFlagBits::Tracked; 2081 image.flags |= ImageFlagBits::Tracked;
2082 if (False(image.flags & ImageFlagBits::Sparse)) { 2082 if (False(image.flags & ImageFlagBits::Sparse)) {
2083 rasterizer.UpdatePagesCachedCount(image.cpu_addr, image.guest_size_bytes, 1); 2083 rasterizer.UpdatePagesCachedCount(image.cpu_addr, image.guest_size_bytes, true);
2084 return; 2084 return;
2085 } 2085 }
2086 if (True(image.flags & ImageFlagBits::Registered)) { 2086 if (True(image.flags & ImageFlagBits::Registered)) {
@@ -2091,13 +2091,13 @@ void TextureCache<P>::TrackImage(ImageBase& image, ImageId image_id) {
2091 const auto& map = slot_map_views[map_view_id]; 2091 const auto& map = slot_map_views[map_view_id];
2092 const VAddr cpu_addr = map.cpu_addr; 2092 const VAddr cpu_addr = map.cpu_addr;
2093 const std::size_t size = map.size; 2093 const std::size_t size = map.size;
2094 rasterizer.UpdatePagesCachedCount(cpu_addr, size, 1); 2094 rasterizer.UpdatePagesCachedCount(cpu_addr, size, true);
2095 } 2095 }
2096 return; 2096 return;
2097 } 2097 }
2098 ForEachSparseSegment(image, 2098 ForEachSparseSegment(image,
2099 [this]([[maybe_unused]] GPUVAddr gpu_addr, VAddr cpu_addr, size_t size) { 2099 [this]([[maybe_unused]] GPUVAddr gpu_addr, VAddr cpu_addr, size_t size) {
2100 rasterizer.UpdatePagesCachedCount(cpu_addr, size, 1); 2100 rasterizer.UpdatePagesCachedCount(cpu_addr, size, true);
2101 }); 2101 });
2102} 2102}
2103 2103
@@ -2106,7 +2106,7 @@ void TextureCache<P>::UntrackImage(ImageBase& image, ImageId image_id) {
2106 ASSERT(True(image.flags & ImageFlagBits::Tracked)); 2106 ASSERT(True(image.flags & ImageFlagBits::Tracked));
2107 image.flags &= ~ImageFlagBits::Tracked; 2107 image.flags &= ~ImageFlagBits::Tracked;
2108 if (False(image.flags & ImageFlagBits::Sparse)) { 2108 if (False(image.flags & ImageFlagBits::Sparse)) {
2109 rasterizer.UpdatePagesCachedCount(image.cpu_addr, image.guest_size_bytes, -1); 2109 rasterizer.UpdatePagesCachedCount(image.cpu_addr, image.guest_size_bytes, false);
2110 return; 2110 return;
2111 } 2111 }
2112 ASSERT(True(image.flags & ImageFlagBits::Registered)); 2112 ASSERT(True(image.flags & ImageFlagBits::Registered));
@@ -2117,7 +2117,7 @@ void TextureCache<P>::UntrackImage(ImageBase& image, ImageId image_id) {
2117 const auto& map = slot_map_views[map_view_id]; 2117 const auto& map = slot_map_views[map_view_id];
2118 const VAddr cpu_addr = map.cpu_addr; 2118 const VAddr cpu_addr = map.cpu_addr;
2119 const std::size_t size = map.size; 2119 const std::size_t size = map.size;
2120 rasterizer.UpdatePagesCachedCount(cpu_addr, size, -1); 2120 rasterizer.UpdatePagesCachedCount(cpu_addr, size, false);
2121 } 2121 }
2122} 2122}
2123 2123