diff options
| author | 2019-03-20 23:44:20 -0400 | |
|---|---|---|
| committer | 2019-03-20 23:44:20 -0400 | |
| commit | 3e930304fe6fb29a2421dd0fdfef6e66ebb213ad (patch) | |
| tree | 3298c05a68692803d9124b919f7f3fe284d535c8 /src | |
| parent | Merge pull request #2262 from lioncash/enum (diff) | |
| parent | Make bitfield assignment operator public (diff) | |
| download | yuzu-3e930304fe6fb29a2421dd0fdfef6e66ebb213ad.tar.gz yuzu-3e930304fe6fb29a2421dd0fdfef6e66ebb213ad.tar.xz yuzu-3e930304fe6fb29a2421dd0fdfef6e66ebb213ad.zip | |
Merge pull request #2090 from FearlessTobi/port-4599
Port citra-emu/citra#4244 and citra-emu/citra#4599: Changes to BitField
Diffstat (limited to 'src')
| -rw-r--r-- | src/common/bit_field.h | 14 | ||||
| -rw-r--r-- | src/common/swap.h | 174 | ||||
| -rw-r--r-- | src/core/hle/ipc.h | 44 | ||||
| -rw-r--r-- | src/core/hle/service/hid/controllers/debug_pad.h | 30 | ||||
| -rw-r--r-- | src/core/hle/service/hid/controllers/npad.h | 102 | ||||
| -rw-r--r-- | src/core/hle/service/hid/controllers/touchscreen.h | 4 | ||||
| -rw-r--r-- | src/core/hle/service/lm/lm.cpp | 2 | ||||
| -rw-r--r-- | src/core/hle/service/nvdrv/devices/nvdevice.h | 10 | ||||
| -rw-r--r-- | src/tests/CMakeLists.txt | 1 | ||||
| -rw-r--r-- | src/tests/common/bit_field.cpp | 90 |
10 files changed, 337 insertions, 134 deletions
diff --git a/src/common/bit_field.h b/src/common/bit_field.h index 7433c39ba..8e35c463f 100644 --- a/src/common/bit_field.h +++ b/src/common/bit_field.h | |||
| @@ -34,6 +34,7 @@ | |||
| 34 | #include <limits> | 34 | #include <limits> |
| 35 | #include <type_traits> | 35 | #include <type_traits> |
| 36 | #include "common/common_funcs.h" | 36 | #include "common/common_funcs.h" |
| 37 | #include "common/swap.h" | ||
| 37 | 38 | ||
| 38 | /* | 39 | /* |
| 39 | * Abstract bitfield class | 40 | * Abstract bitfield class |
| @@ -108,7 +109,7 @@ | |||
| 108 | * symptoms. | 109 | * symptoms. |
| 109 | */ | 110 | */ |
| 110 | #pragma pack(1) | 111 | #pragma pack(1) |
| 111 | template <std::size_t Position, std::size_t Bits, typename T> | 112 | template <std::size_t Position, std::size_t Bits, typename T, typename EndianTag = LETag> |
| 112 | struct BitField { | 113 | struct BitField { |
| 113 | private: | 114 | private: |
| 114 | // UnderlyingType is T for non-enum types and the underlying type of T if | 115 | // UnderlyingType is T for non-enum types and the underlying type of T if |
| @@ -121,7 +122,11 @@ private: | |||
| 121 | // We store the value as the unsigned type to avoid undefined behaviour on value shifting | 122 | // We store the value as the unsigned type to avoid undefined behaviour on value shifting |
| 122 | using StorageType = std::make_unsigned_t<UnderlyingType>; | 123 | using StorageType = std::make_unsigned_t<UnderlyingType>; |
| 123 | 124 | ||
| 125 | using StorageTypeWithEndian = typename AddEndian<StorageType, EndianTag>::type; | ||
| 126 | |||
| 124 | public: | 127 | public: |
| 128 | BitField& operator=(const BitField&) = default; | ||
| 129 | |||
| 125 | /// Constants to allow limited introspection of fields if needed | 130 | /// Constants to allow limited introspection of fields if needed |
| 126 | static constexpr std::size_t position = Position; | 131 | static constexpr std::size_t position = Position; |
| 127 | static constexpr std::size_t bits = Bits; | 132 | static constexpr std::size_t bits = Bits; |
| @@ -170,7 +175,7 @@ public: | |||
| 170 | } | 175 | } |
| 171 | 176 | ||
| 172 | constexpr FORCE_INLINE void Assign(const T& value) { | 177 | constexpr FORCE_INLINE void Assign(const T& value) { |
| 173 | storage = (storage & ~mask) | FormatValue(value); | 178 | storage = (static_cast<StorageType>(storage) & ~mask) | FormatValue(value); |
| 174 | } | 179 | } |
| 175 | 180 | ||
| 176 | constexpr T Value() const { | 181 | constexpr T Value() const { |
| @@ -182,7 +187,7 @@ public: | |||
| 182 | } | 187 | } |
| 183 | 188 | ||
| 184 | private: | 189 | private: |
| 185 | StorageType storage; | 190 | StorageTypeWithEndian storage; |
| 186 | 191 | ||
| 187 | static_assert(bits + position <= 8 * sizeof(T), "Bitfield out of range"); | 192 | static_assert(bits + position <= 8 * sizeof(T), "Bitfield out of range"); |
| 188 | 193 | ||
| @@ -193,3 +198,6 @@ private: | |||
| 193 | static_assert(std::is_trivially_copyable_v<T>, "T must be trivially copyable in a BitField"); | 198 | static_assert(std::is_trivially_copyable_v<T>, "T must be trivially copyable in a BitField"); |
| 194 | }; | 199 | }; |
| 195 | #pragma pack() | 200 | #pragma pack() |
| 201 | |||
| 202 | template <std::size_t Position, std::size_t Bits, typename T> | ||
| 203 | using BitFieldBE = BitField<Position, Bits, T, BETag>; | ||
diff --git a/src/common/swap.h b/src/common/swap.h index 0e219747f..b3eab1324 100644 --- a/src/common/swap.h +++ b/src/common/swap.h | |||
| @@ -17,6 +17,8 @@ | |||
| 17 | 17 | ||
| 18 | #pragma once | 18 | #pragma once |
| 19 | 19 | ||
| 20 | #include <type_traits> | ||
| 21 | |||
| 20 | #if defined(_MSC_VER) | 22 | #if defined(_MSC_VER) |
| 21 | #include <cstdlib> | 23 | #include <cstdlib> |
| 22 | #elif defined(__linux__) | 24 | #elif defined(__linux__) |
| @@ -170,7 +172,7 @@ struct swap_struct_t { | |||
| 170 | using swapped_t = swap_struct_t; | 172 | using swapped_t = swap_struct_t; |
| 171 | 173 | ||
| 172 | protected: | 174 | protected: |
| 173 | T value = T(); | 175 | T value; |
| 174 | 176 | ||
| 175 | static T swap(T v) { | 177 | static T swap(T v) { |
| 176 | return F::swap(v); | 178 | return F::swap(v); |
| @@ -605,52 +607,154 @@ struct swap_double_t { | |||
| 605 | } | 607 | } |
| 606 | }; | 608 | }; |
| 607 | 609 | ||
| 608 | #if COMMON_LITTLE_ENDIAN | 610 | template <typename T> |
| 609 | using u16_le = u16; | 611 | struct swap_enum_t { |
| 610 | using u32_le = u32; | 612 | static_assert(std::is_enum_v<T>); |
| 611 | using u64_le = u64; | 613 | using base = std::underlying_type_t<T>; |
| 614 | |||
| 615 | public: | ||
| 616 | swap_enum_t() = default; | ||
| 617 | swap_enum_t(const T& v) : value(swap(v)) {} | ||
| 618 | |||
| 619 | swap_enum_t& operator=(const T& v) { | ||
| 620 | value = swap(v); | ||
| 621 | return *this; | ||
| 622 | } | ||
| 623 | |||
| 624 | operator T() const { | ||
| 625 | return swap(value); | ||
| 626 | } | ||
| 627 | |||
| 628 | explicit operator base() const { | ||
| 629 | return static_cast<base>(swap(value)); | ||
| 630 | } | ||
| 612 | 631 | ||
| 613 | using s16_le = s16; | 632 | protected: |
| 614 | using s32_le = s32; | 633 | T value{}; |
| 615 | using s64_le = s64; | 634 | // clang-format off |
| 635 | using swap_t = std::conditional_t< | ||
| 636 | std::is_same_v<base, u16>, swap_16_t<u16>, std::conditional_t< | ||
| 637 | std::is_same_v<base, s16>, swap_16_t<s16>, std::conditional_t< | ||
| 638 | std::is_same_v<base, u32>, swap_32_t<u32>, std::conditional_t< | ||
| 639 | std::is_same_v<base, s32>, swap_32_t<s32>, std::conditional_t< | ||
| 640 | std::is_same_v<base, u64>, swap_64_t<u64>, std::conditional_t< | ||
| 641 | std::is_same_v<base, s64>, swap_64_t<s64>, void>>>>>>; | ||
| 642 | // clang-format on | ||
| 643 | static T swap(T x) { | ||
| 644 | return static_cast<T>(swap_t::swap(static_cast<base>(x))); | ||
| 645 | } | ||
| 646 | }; | ||
| 616 | 647 | ||
| 617 | using float_le = float; | 648 | struct SwapTag {}; // Use the different endianness from the system |
| 618 | using double_le = double; | 649 | struct KeepTag {}; // Use the same endianness as the system |
| 619 | 650 | ||
| 620 | using u64_be = swap_struct_t<u64, swap_64_t<u64>>; | 651 | template <typename T, typename Tag> |
| 621 | using s64_be = swap_struct_t<s64, swap_64_t<s64>>; | 652 | struct AddEndian; |
| 622 | 653 | ||
| 623 | using u32_be = swap_struct_t<u32, swap_32_t<u32>>; | 654 | // KeepTag specializations |
| 624 | using s32_be = swap_struct_t<s32, swap_32_t<s32>>; | ||
| 625 | 655 | ||
| 626 | using u16_be = swap_struct_t<u16, swap_16_t<u16>>; | 656 | template <typename T> |
| 627 | using s16_be = swap_struct_t<s16, swap_16_t<s16>>; | 657 | struct AddEndian<T, KeepTag> { |
| 658 | using type = T; | ||
| 659 | }; | ||
| 628 | 660 | ||
| 629 | using float_be = swap_struct_t<float, swap_float_t<float>>; | 661 | // SwapTag specializations |
| 630 | using double_be = swap_struct_t<double, swap_double_t<double>>; | 662 | |
| 631 | #else | 663 | template <> |
| 664 | struct AddEndian<u8, SwapTag> { | ||
| 665 | using type = u8; | ||
| 666 | }; | ||
| 667 | |||
| 668 | template <> | ||
| 669 | struct AddEndian<u16, SwapTag> { | ||
| 670 | using type = swap_struct_t<u16, swap_16_t<u16>>; | ||
| 671 | }; | ||
| 672 | |||
| 673 | template <> | ||
| 674 | struct AddEndian<u32, SwapTag> { | ||
| 675 | using type = swap_struct_t<u32, swap_32_t<u32>>; | ||
| 676 | }; | ||
| 632 | 677 | ||
| 633 | using u64_le = swap_struct_t<u64, swap_64_t<u64>>; | 678 | template <> |
| 634 | using s64_le = swap_struct_t<s64, swap_64_t<s64>>; | 679 | struct AddEndian<u64, SwapTag> { |
| 680 | using type = swap_struct_t<u64, swap_64_t<u64>>; | ||
| 681 | }; | ||
| 682 | |||
| 683 | template <> | ||
| 684 | struct AddEndian<s8, SwapTag> { | ||
| 685 | using type = s8; | ||
| 686 | }; | ||
| 635 | 687 | ||
| 636 | using u32_le = swap_struct_t<u32, swap_32_t<u32>>; | 688 | template <> |
| 637 | using s32_le = swap_struct_t<s32, swap_32_t<s32>>; | 689 | struct AddEndian<s16, SwapTag> { |
| 690 | using type = swap_struct_t<s16, swap_16_t<s16>>; | ||
| 691 | }; | ||
| 638 | 692 | ||
| 639 | using u16_le = swap_struct_t<u16, swap_16_t<u16>>; | 693 | template <> |
| 640 | using s16_le = swap_struct_t<s16, swap_16_t<s16>>; | 694 | struct AddEndian<s32, SwapTag> { |
| 695 | using type = swap_struct_t<s32, swap_32_t<s32>>; | ||
| 696 | }; | ||
| 697 | |||
| 698 | template <> | ||
| 699 | struct AddEndian<s64, SwapTag> { | ||
| 700 | using type = swap_struct_t<s64, swap_64_t<s64>>; | ||
| 701 | }; | ||
| 702 | |||
| 703 | template <> | ||
| 704 | struct AddEndian<float, SwapTag> { | ||
| 705 | using type = swap_struct_t<float, swap_float_t<float>>; | ||
| 706 | }; | ||
| 707 | |||
| 708 | template <> | ||
| 709 | struct AddEndian<double, SwapTag> { | ||
| 710 | using type = swap_struct_t<double, swap_double_t<double>>; | ||
| 711 | }; | ||
| 712 | |||
| 713 | template <typename T> | ||
| 714 | struct AddEndian<T, SwapTag> { | ||
| 715 | static_assert(std::is_enum_v<T>); | ||
| 716 | using type = swap_enum_t<T>; | ||
| 717 | }; | ||
| 641 | 718 | ||
| 642 | using float_le = swap_struct_t<float, swap_float_t<float>>; | 719 | // Alias LETag/BETag as KeepTag/SwapTag depending on the system |
| 643 | using double_le = swap_struct_t<double, swap_double_t<double>>; | 720 | #if COMMON_LITTLE_ENDIAN |
| 644 | 721 | ||
| 645 | using u16_be = u16; | 722 | using LETag = KeepTag; |
| 646 | using u32_be = u32; | 723 | using BETag = SwapTag; |
| 647 | using u64_be = u64; | ||
| 648 | 724 | ||
| 649 | using s16_be = s16; | 725 | #else |
| 650 | using s32_be = s32; | ||
| 651 | using s64_be = s64; | ||
| 652 | 726 | ||
| 653 | using float_be = float; | 727 | using BETag = KeepTag; |
| 654 | using double_be = double; | 728 | using LETag = SwapTag; |
| 655 | 729 | ||
| 656 | #endif | 730 | #endif |
| 731 | |||
| 732 | // Aliases for LE types | ||
| 733 | using u16_le = AddEndian<u16, LETag>::type; | ||
| 734 | using u32_le = AddEndian<u32, LETag>::type; | ||
| 735 | using u64_le = AddEndian<u64, LETag>::type; | ||
| 736 | |||
| 737 | using s16_le = AddEndian<s16, LETag>::type; | ||
| 738 | using s32_le = AddEndian<s32, LETag>::type; | ||
| 739 | using s64_le = AddEndian<s64, LETag>::type; | ||
| 740 | |||
| 741 | template <typename T> | ||
| 742 | using enum_le = std::enable_if_t<std::is_enum_v<T>, typename AddEndian<T, LETag>::type>; | ||
| 743 | |||
| 744 | using float_le = AddEndian<float, LETag>::type; | ||
| 745 | using double_le = AddEndian<double, LETag>::type; | ||
| 746 | |||
| 747 | // Aliases for BE types | ||
| 748 | using u16_be = AddEndian<u16, BETag>::type; | ||
| 749 | using u32_be = AddEndian<u32, BETag>::type; | ||
| 750 | using u64_be = AddEndian<u64, BETag>::type; | ||
| 751 | |||
| 752 | using s16_be = AddEndian<s16, BETag>::type; | ||
| 753 | using s32_be = AddEndian<s32, BETag>::type; | ||
| 754 | using s64_be = AddEndian<s64, BETag>::type; | ||
| 755 | |||
| 756 | template <typename T> | ||
| 757 | using enum_be = std::enable_if_t<std::is_enum_v<T>, typename AddEndian<T, BETag>::type>; | ||
| 758 | |||
| 759 | using float_be = AddEndian<float, BETag>::type; | ||
| 760 | using double_be = AddEndian<double, BETag>::type; | ||
diff --git a/src/core/hle/ipc.h b/src/core/hle/ipc.h index 455d1f346..fae54bcc7 100644 --- a/src/core/hle/ipc.h +++ b/src/core/hle/ipc.h | |||
| @@ -39,10 +39,10 @@ struct CommandHeader { | |||
| 39 | union { | 39 | union { |
| 40 | u32_le raw_low; | 40 | u32_le raw_low; |
| 41 | BitField<0, 16, CommandType> type; | 41 | BitField<0, 16, CommandType> type; |
| 42 | BitField<16, 4, u32_le> num_buf_x_descriptors; | 42 | BitField<16, 4, u32> num_buf_x_descriptors; |
| 43 | BitField<20, 4, u32_le> num_buf_a_descriptors; | 43 | BitField<20, 4, u32> num_buf_a_descriptors; |
| 44 | BitField<24, 4, u32_le> num_buf_b_descriptors; | 44 | BitField<24, 4, u32> num_buf_b_descriptors; |
| 45 | BitField<28, 4, u32_le> num_buf_w_descriptors; | 45 | BitField<28, 4, u32> num_buf_w_descriptors; |
| 46 | }; | 46 | }; |
| 47 | 47 | ||
| 48 | enum class BufferDescriptorCFlag : u32 { | 48 | enum class BufferDescriptorCFlag : u32 { |
| @@ -53,28 +53,28 @@ struct CommandHeader { | |||
| 53 | 53 | ||
| 54 | union { | 54 | union { |
| 55 | u32_le raw_high; | 55 | u32_le raw_high; |
| 56 | BitField<0, 10, u32_le> data_size; | 56 | BitField<0, 10, u32> data_size; |
| 57 | BitField<10, 4, BufferDescriptorCFlag> buf_c_descriptor_flags; | 57 | BitField<10, 4, BufferDescriptorCFlag> buf_c_descriptor_flags; |
| 58 | BitField<31, 1, u32_le> enable_handle_descriptor; | 58 | BitField<31, 1, u32> enable_handle_descriptor; |
| 59 | }; | 59 | }; |
| 60 | }; | 60 | }; |
| 61 | static_assert(sizeof(CommandHeader) == 8, "CommandHeader size is incorrect"); | 61 | static_assert(sizeof(CommandHeader) == 8, "CommandHeader size is incorrect"); |
| 62 | 62 | ||
| 63 | union HandleDescriptorHeader { | 63 | union HandleDescriptorHeader { |
| 64 | u32_le raw_high; | 64 | u32_le raw_high; |
| 65 | BitField<0, 1, u32_le> send_current_pid; | 65 | BitField<0, 1, u32> send_current_pid; |
| 66 | BitField<1, 4, u32_le> num_handles_to_copy; | 66 | BitField<1, 4, u32> num_handles_to_copy; |
| 67 | BitField<5, 4, u32_le> num_handles_to_move; | 67 | BitField<5, 4, u32> num_handles_to_move; |
| 68 | }; | 68 | }; |
| 69 | static_assert(sizeof(HandleDescriptorHeader) == 4, "HandleDescriptorHeader size is incorrect"); | 69 | static_assert(sizeof(HandleDescriptorHeader) == 4, "HandleDescriptorHeader size is incorrect"); |
| 70 | 70 | ||
| 71 | struct BufferDescriptorX { | 71 | struct BufferDescriptorX { |
| 72 | union { | 72 | union { |
| 73 | BitField<0, 6, u32_le> counter_bits_0_5; | 73 | BitField<0, 6, u32> counter_bits_0_5; |
| 74 | BitField<6, 3, u32_le> address_bits_36_38; | 74 | BitField<6, 3, u32> address_bits_36_38; |
| 75 | BitField<9, 3, u32_le> counter_bits_9_11; | 75 | BitField<9, 3, u32> counter_bits_9_11; |
| 76 | BitField<12, 4, u32_le> address_bits_32_35; | 76 | BitField<12, 4, u32> address_bits_32_35; |
| 77 | BitField<16, 16, u32_le> size; | 77 | BitField<16, 16, u32> size; |
| 78 | }; | 78 | }; |
| 79 | 79 | ||
| 80 | u32_le address_bits_0_31; | 80 | u32_le address_bits_0_31; |
| @@ -103,10 +103,10 @@ struct BufferDescriptorABW { | |||
| 103 | u32_le address_bits_0_31; | 103 | u32_le address_bits_0_31; |
| 104 | 104 | ||
| 105 | union { | 105 | union { |
| 106 | BitField<0, 2, u32_le> flags; | 106 | BitField<0, 2, u32> flags; |
| 107 | BitField<2, 3, u32_le> address_bits_36_38; | 107 | BitField<2, 3, u32> address_bits_36_38; |
| 108 | BitField<24, 4, u32_le> size_bits_32_35; | 108 | BitField<24, 4, u32> size_bits_32_35; |
| 109 | BitField<28, 4, u32_le> address_bits_32_35; | 109 | BitField<28, 4, u32> address_bits_32_35; |
| 110 | }; | 110 | }; |
| 111 | 111 | ||
| 112 | VAddr Address() const { | 112 | VAddr Address() const { |
| @@ -128,8 +128,8 @@ struct BufferDescriptorC { | |||
| 128 | u32_le address_bits_0_31; | 128 | u32_le address_bits_0_31; |
| 129 | 129 | ||
| 130 | union { | 130 | union { |
| 131 | BitField<0, 16, u32_le> address_bits_32_47; | 131 | BitField<0, 16, u32> address_bits_32_47; |
| 132 | BitField<16, 16, u32_le> size; | 132 | BitField<16, 16, u32> size; |
| 133 | }; | 133 | }; |
| 134 | 134 | ||
| 135 | VAddr Address() const { | 135 | VAddr Address() const { |
| @@ -167,8 +167,8 @@ struct DomainMessageHeader { | |||
| 167 | struct { | 167 | struct { |
| 168 | union { | 168 | union { |
| 169 | BitField<0, 8, CommandType> command; | 169 | BitField<0, 8, CommandType> command; |
| 170 | BitField<8, 8, u32_le> input_object_count; | 170 | BitField<8, 8, u32> input_object_count; |
| 171 | BitField<16, 16, u32_le> size; | 171 | BitField<16, 16, u32> size; |
| 172 | }; | 172 | }; |
| 173 | u32_le object_id; | 173 | u32_le object_id; |
| 174 | INSERT_PADDING_WORDS(2); | 174 | INSERT_PADDING_WORDS(2); |
diff --git a/src/core/hle/service/hid/controllers/debug_pad.h b/src/core/hle/service/hid/controllers/debug_pad.h index 929035034..e584b92ec 100644 --- a/src/core/hle/service/hid/controllers/debug_pad.h +++ b/src/core/hle/service/hid/controllers/debug_pad.h | |||
| @@ -41,20 +41,20 @@ private: | |||
| 41 | struct PadState { | 41 | struct PadState { |
| 42 | union { | 42 | union { |
| 43 | u32_le raw{}; | 43 | u32_le raw{}; |
| 44 | BitField<0, 1, u32_le> a; | 44 | BitField<0, 1, u32> a; |
| 45 | BitField<1, 1, u32_le> b; | 45 | BitField<1, 1, u32> b; |
| 46 | BitField<2, 1, u32_le> x; | 46 | BitField<2, 1, u32> x; |
| 47 | BitField<3, 1, u32_le> y; | 47 | BitField<3, 1, u32> y; |
| 48 | BitField<4, 1, u32_le> l; | 48 | BitField<4, 1, u32> l; |
| 49 | BitField<5, 1, u32_le> r; | 49 | BitField<5, 1, u32> r; |
| 50 | BitField<6, 1, u32_le> zl; | 50 | BitField<6, 1, u32> zl; |
| 51 | BitField<7, 1, u32_le> zr; | 51 | BitField<7, 1, u32> zr; |
| 52 | BitField<8, 1, u32_le> plus; | 52 | BitField<8, 1, u32> plus; |
| 53 | BitField<9, 1, u32_le> minus; | 53 | BitField<9, 1, u32> minus; |
| 54 | BitField<10, 1, u32_le> d_left; | 54 | BitField<10, 1, u32> d_left; |
| 55 | BitField<11, 1, u32_le> d_up; | 55 | BitField<11, 1, u32> d_up; |
| 56 | BitField<12, 1, u32_le> d_right; | 56 | BitField<12, 1, u32> d_right; |
| 57 | BitField<13, 1, u32_le> d_down; | 57 | BitField<13, 1, u32> d_down; |
| 58 | }; | 58 | }; |
| 59 | }; | 59 | }; |
| 60 | static_assert(sizeof(PadState) == 0x4, "PadState is an invalid size"); | 60 | static_assert(sizeof(PadState) == 0x4, "PadState is an invalid size"); |
| @@ -62,7 +62,7 @@ private: | |||
| 62 | struct Attributes { | 62 | struct Attributes { |
| 63 | union { | 63 | union { |
| 64 | u32_le raw{}; | 64 | u32_le raw{}; |
| 65 | BitField<0, 1, u32_le> connected; | 65 | BitField<0, 1, u32> connected; |
| 66 | }; | 66 | }; |
| 67 | }; | 67 | }; |
| 68 | static_assert(sizeof(Attributes) == 0x4, "Attributes is an invalid size"); | 68 | static_assert(sizeof(Attributes) == 0x4, "Attributes is an invalid size"); |
diff --git a/src/core/hle/service/hid/controllers/npad.h b/src/core/hle/service/hid/controllers/npad.h index 18c7a94e6..4ff50b3cd 100644 --- a/src/core/hle/service/hid/controllers/npad.h +++ b/src/core/hle/service/hid/controllers/npad.h | |||
| @@ -39,13 +39,13 @@ public: | |||
| 39 | union { | 39 | union { |
| 40 | u32_le raw{}; | 40 | u32_le raw{}; |
| 41 | 41 | ||
| 42 | BitField<0, 1, u32_le> pro_controller; | 42 | BitField<0, 1, u32> pro_controller; |
| 43 | BitField<1, 1, u32_le> handheld; | 43 | BitField<1, 1, u32> handheld; |
| 44 | BitField<2, 1, u32_le> joycon_dual; | 44 | BitField<2, 1, u32> joycon_dual; |
| 45 | BitField<3, 1, u32_le> joycon_left; | 45 | BitField<3, 1, u32> joycon_left; |
| 46 | BitField<4, 1, u32_le> joycon_right; | 46 | BitField<4, 1, u32> joycon_right; |
| 47 | 47 | ||
| 48 | BitField<6, 1, u32_le> pokeball; // TODO(ogniK): Confirm when possible | 48 | BitField<6, 1, u32> pokeball; // TODO(ogniK): Confirm when possible |
| 49 | }; | 49 | }; |
| 50 | }; | 50 | }; |
| 51 | static_assert(sizeof(NPadType) == 4, "NPadType is an invalid size"); | 51 | static_assert(sizeof(NPadType) == 4, "NPadType is an invalid size"); |
| @@ -150,43 +150,43 @@ private: | |||
| 150 | union { | 150 | union { |
| 151 | u64_le raw{}; | 151 | u64_le raw{}; |
| 152 | // Button states | 152 | // Button states |
| 153 | BitField<0, 1, u64_le> a; | 153 | BitField<0, 1, u64> a; |
| 154 | BitField<1, 1, u64_le> b; | 154 | BitField<1, 1, u64> b; |
| 155 | BitField<2, 1, u64_le> x; | 155 | BitField<2, 1, u64> x; |
| 156 | BitField<3, 1, u64_le> y; | 156 | BitField<3, 1, u64> y; |
| 157 | BitField<4, 1, u64_le> l_stick; | 157 | BitField<4, 1, u64> l_stick; |
| 158 | BitField<5, 1, u64_le> r_stick; | 158 | BitField<5, 1, u64> r_stick; |
| 159 | BitField<6, 1, u64_le> l; | 159 | BitField<6, 1, u64> l; |
| 160 | BitField<7, 1, u64_le> r; | 160 | BitField<7, 1, u64> r; |
| 161 | BitField<8, 1, u64_le> zl; | 161 | BitField<8, 1, u64> zl; |
| 162 | BitField<9, 1, u64_le> zr; | 162 | BitField<9, 1, u64> zr; |
| 163 | BitField<10, 1, u64_le> plus; | 163 | BitField<10, 1, u64> plus; |
| 164 | BitField<11, 1, u64_le> minus; | 164 | BitField<11, 1, u64> minus; |
| 165 | 165 | ||
| 166 | // D-Pad | 166 | // D-Pad |
| 167 | BitField<12, 1, u64_le> d_left; | 167 | BitField<12, 1, u64> d_left; |
| 168 | BitField<13, 1, u64_le> d_up; | 168 | BitField<13, 1, u64> d_up; |
| 169 | BitField<14, 1, u64_le> d_right; | 169 | BitField<14, 1, u64> d_right; |
| 170 | BitField<15, 1, u64_le> d_down; | 170 | BitField<15, 1, u64> d_down; |
| 171 | 171 | ||
| 172 | // Left JoyStick | 172 | // Left JoyStick |
| 173 | BitField<16, 1, u64_le> l_stick_left; | 173 | BitField<16, 1, u64> l_stick_left; |
| 174 | BitField<17, 1, u64_le> l_stick_up; | 174 | BitField<17, 1, u64> l_stick_up; |
| 175 | BitField<18, 1, u64_le> l_stick_right; | 175 | BitField<18, 1, u64> l_stick_right; |
| 176 | BitField<19, 1, u64_le> l_stick_down; | 176 | BitField<19, 1, u64> l_stick_down; |
| 177 | 177 | ||
| 178 | // Right JoyStick | 178 | // Right JoyStick |
| 179 | BitField<20, 1, u64_le> r_stick_left; | 179 | BitField<20, 1, u64> r_stick_left; |
| 180 | BitField<21, 1, u64_le> r_stick_up; | 180 | BitField<21, 1, u64> r_stick_up; |
| 181 | BitField<22, 1, u64_le> r_stick_right; | 181 | BitField<22, 1, u64> r_stick_right; |
| 182 | BitField<23, 1, u64_le> r_stick_down; | 182 | BitField<23, 1, u64> r_stick_down; |
| 183 | 183 | ||
| 184 | // Not always active? | 184 | // Not always active? |
| 185 | BitField<24, 1, u64_le> left_sl; | 185 | BitField<24, 1, u64> left_sl; |
| 186 | BitField<25, 1, u64_le> left_sr; | 186 | BitField<25, 1, u64> left_sr; |
| 187 | 187 | ||
| 188 | BitField<26, 1, u64_le> right_sl; | 188 | BitField<26, 1, u64> right_sl; |
| 189 | BitField<27, 1, u64_le> right_sr; | 189 | BitField<27, 1, u64> right_sr; |
| 190 | }; | 190 | }; |
| 191 | }; | 191 | }; |
| 192 | static_assert(sizeof(ControllerPadState) == 8, "ControllerPadState is an invalid size"); | 192 | static_assert(sizeof(ControllerPadState) == 8, "ControllerPadState is an invalid size"); |
| @@ -200,12 +200,12 @@ private: | |||
| 200 | struct ConnectionState { | 200 | struct ConnectionState { |
| 201 | union { | 201 | union { |
| 202 | u32_le raw{}; | 202 | u32_le raw{}; |
| 203 | BitField<0, 1, u32_le> IsConnected; | 203 | BitField<0, 1, u32> IsConnected; |
| 204 | BitField<1, 1, u32_le> IsWired; | 204 | BitField<1, 1, u32> IsWired; |
| 205 | BitField<2, 1, u32_le> IsLeftJoyConnected; | 205 | BitField<2, 1, u32> IsLeftJoyConnected; |
| 206 | BitField<3, 1, u32_le> IsLeftJoyWired; | 206 | BitField<3, 1, u32> IsLeftJoyWired; |
| 207 | BitField<4, 1, u32_le> IsRightJoyConnected; | 207 | BitField<4, 1, u32> IsRightJoyConnected; |
| 208 | BitField<5, 1, u32_le> IsRightJoyWired; | 208 | BitField<5, 1, u32> IsRightJoyWired; |
| 209 | }; | 209 | }; |
| 210 | }; | 210 | }; |
| 211 | static_assert(sizeof(ConnectionState) == 4, "ConnectionState is an invalid size"); | 211 | static_assert(sizeof(ConnectionState) == 4, "ConnectionState is an invalid size"); |
| @@ -240,23 +240,23 @@ private: | |||
| 240 | struct NPadProperties { | 240 | struct NPadProperties { |
| 241 | union { | 241 | union { |
| 242 | s64_le raw{}; | 242 | s64_le raw{}; |
| 243 | BitField<11, 1, s64_le> is_vertical; | 243 | BitField<11, 1, s64> is_vertical; |
| 244 | BitField<12, 1, s64_le> is_horizontal; | 244 | BitField<12, 1, s64> is_horizontal; |
| 245 | BitField<13, 1, s64_le> use_plus; | 245 | BitField<13, 1, s64> use_plus; |
| 246 | BitField<14, 1, s64_le> use_minus; | 246 | BitField<14, 1, s64> use_minus; |
| 247 | }; | 247 | }; |
| 248 | }; | 248 | }; |
| 249 | 249 | ||
| 250 | struct NPadDevice { | 250 | struct NPadDevice { |
| 251 | union { | 251 | union { |
| 252 | u32_le raw{}; | 252 | u32_le raw{}; |
| 253 | BitField<0, 1, s32_le> pro_controller; | 253 | BitField<0, 1, s32> pro_controller; |
| 254 | BitField<1, 1, s32_le> handheld; | 254 | BitField<1, 1, s32> handheld; |
| 255 | BitField<2, 1, s32_le> handheld_left; | 255 | BitField<2, 1, s32> handheld_left; |
| 256 | BitField<3, 1, s32_le> handheld_right; | 256 | BitField<3, 1, s32> handheld_right; |
| 257 | BitField<4, 1, s32_le> joycon_left; | 257 | BitField<4, 1, s32> joycon_left; |
| 258 | BitField<5, 1, s32_le> joycon_right; | 258 | BitField<5, 1, s32> joycon_right; |
| 259 | BitField<6, 1, s32_le> pokeball; | 259 | BitField<6, 1, s32> pokeball; |
| 260 | }; | 260 | }; |
| 261 | }; | 261 | }; |
| 262 | 262 | ||
diff --git a/src/core/hle/service/hid/controllers/touchscreen.h b/src/core/hle/service/hid/controllers/touchscreen.h index 012b6e0dd..76fc340e9 100644 --- a/src/core/hle/service/hid/controllers/touchscreen.h +++ b/src/core/hle/service/hid/controllers/touchscreen.h | |||
| @@ -33,8 +33,8 @@ private: | |||
| 33 | struct Attributes { | 33 | struct Attributes { |
| 34 | union { | 34 | union { |
| 35 | u32 raw{}; | 35 | u32 raw{}; |
| 36 | BitField<0, 1, u32_le> start_touch; | 36 | BitField<0, 1, u32> start_touch; |
| 37 | BitField<1, 1, u32_le> end_touch; | 37 | BitField<1, 1, u32> end_touch; |
| 38 | }; | 38 | }; |
| 39 | }; | 39 | }; |
| 40 | static_assert(sizeof(Attributes) == 0x4, "Attributes is an invalid size"); | 40 | static_assert(sizeof(Attributes) == 0x4, "Attributes is an invalid size"); |
diff --git a/src/core/hle/service/lm/lm.cpp b/src/core/hle/service/lm/lm.cpp index 1f462e087..2a61593e2 100644 --- a/src/core/hle/service/lm/lm.cpp +++ b/src/core/hle/service/lm/lm.cpp | |||
| @@ -42,7 +42,7 @@ private: | |||
| 42 | union { | 42 | union { |
| 43 | BitField<0, 16, Flags> flags; | 43 | BitField<0, 16, Flags> flags; |
| 44 | BitField<16, 8, Severity> severity; | 44 | BitField<16, 8, Severity> severity; |
| 45 | BitField<24, 8, u32_le> verbosity; | 45 | BitField<24, 8, u32> verbosity; |
| 46 | }; | 46 | }; |
| 47 | u32_le payload_size; | 47 | u32_le payload_size; |
| 48 | 48 | ||
diff --git a/src/core/hle/service/nvdrv/devices/nvdevice.h b/src/core/hle/service/nvdrv/devices/nvdevice.h index 0f02a1a18..4f6042b00 100644 --- a/src/core/hle/service/nvdrv/devices/nvdevice.h +++ b/src/core/hle/service/nvdrv/devices/nvdevice.h | |||
| @@ -19,11 +19,11 @@ public: | |||
| 19 | virtual ~nvdevice() = default; | 19 | virtual ~nvdevice() = default; |
| 20 | union Ioctl { | 20 | union Ioctl { |
| 21 | u32_le raw; | 21 | u32_le raw; |
| 22 | BitField<0, 8, u32_le> cmd; | 22 | BitField<0, 8, u32> cmd; |
| 23 | BitField<8, 8, u32_le> group; | 23 | BitField<8, 8, u32> group; |
| 24 | BitField<16, 14, u32_le> length; | 24 | BitField<16, 14, u32> length; |
| 25 | BitField<30, 1, u32_le> is_in; | 25 | BitField<30, 1, u32> is_in; |
| 26 | BitField<31, 1, u32_le> is_out; | 26 | BitField<31, 1, u32> is_out; |
| 27 | }; | 27 | }; |
| 28 | 28 | ||
| 29 | /** | 29 | /** |
diff --git a/src/tests/CMakeLists.txt b/src/tests/CMakeLists.txt index 37f09ce5f..d0284bdf4 100644 --- a/src/tests/CMakeLists.txt +++ b/src/tests/CMakeLists.txt | |||
| @@ -1,4 +1,5 @@ | |||
| 1 | add_executable(tests | 1 | add_executable(tests |
| 2 | common/bit_field.cpp | ||
| 2 | common/param_package.cpp | 3 | common/param_package.cpp |
| 3 | common/ring_buffer.cpp | 4 | common/ring_buffer.cpp |
| 4 | core/arm/arm_test_common.cpp | 5 | core/arm/arm_test_common.cpp |
diff --git a/src/tests/common/bit_field.cpp b/src/tests/common/bit_field.cpp new file mode 100644 index 000000000..8ca1889f9 --- /dev/null +++ b/src/tests/common/bit_field.cpp | |||
| @@ -0,0 +1,90 @@ | |||
| 1 | // Copyright 2019 Citra Emulator Project | ||
| 2 | // Licensed under GPLv2 or any later version | ||
| 3 | // Refer to the license.txt file included. | ||
| 4 | |||
| 5 | #include <array> | ||
| 6 | #include <cstring> | ||
| 7 | #include <type_traits> | ||
| 8 | #include <catch2/catch.hpp> | ||
| 9 | #include "common/bit_field.h" | ||
| 10 | |||
| 11 | TEST_CASE("BitField", "[common]") { | ||
| 12 | enum class TestEnum : u32 { | ||
| 13 | A = 0b10111101, | ||
| 14 | B = 0b10101110, | ||
| 15 | C = 0b00001111, | ||
| 16 | }; | ||
| 17 | |||
| 18 | union LEBitField { | ||
| 19 | u32_le raw; | ||
| 20 | BitField<0, 6, u32> a; | ||
| 21 | BitField<6, 4, s32> b; | ||
| 22 | BitField<10, 8, TestEnum> c; | ||
| 23 | BitField<18, 14, u32> d; | ||
| 24 | } le_bitfield; | ||
| 25 | |||
| 26 | union BEBitField { | ||
| 27 | u32_be raw; | ||
| 28 | BitFieldBE<0, 6, u32> a; | ||
| 29 | BitFieldBE<6, 4, s32> b; | ||
| 30 | BitFieldBE<10, 8, TestEnum> c; | ||
| 31 | BitFieldBE<18, 14, u32> d; | ||
| 32 | } be_bitfield; | ||
| 33 | |||
| 34 | static_assert(sizeof(LEBitField) == sizeof(u32)); | ||
| 35 | static_assert(sizeof(BEBitField) == sizeof(u32)); | ||
| 36 | static_assert(std::is_trivially_copyable_v<LEBitField>); | ||
| 37 | static_assert(std::is_trivially_copyable_v<BEBitField>); | ||
| 38 | |||
| 39 | std::array<u8, 4> raw{{ | ||
| 40 | 0b01101100, | ||
| 41 | 0b11110110, | ||
| 42 | 0b10111010, | ||
| 43 | 0b11101100, | ||
| 44 | }}; | ||
| 45 | |||
| 46 | std::memcpy(&le_bitfield, &raw, sizeof(raw)); | ||
| 47 | std::memcpy(&be_bitfield, &raw, sizeof(raw)); | ||
| 48 | |||
| 49 | // bit fields: 11101100101110'10111101'1001'101100 | ||
| 50 | REQUIRE(le_bitfield.raw == 0b11101100'10111010'11110110'01101100); | ||
| 51 | REQUIRE(le_bitfield.a == 0b101100); | ||
| 52 | REQUIRE(le_bitfield.b == -7); // 1001 as two's complement | ||
| 53 | REQUIRE(le_bitfield.c == TestEnum::A); | ||
| 54 | REQUIRE(le_bitfield.d == 0b11101100101110); | ||
| 55 | |||
| 56 | le_bitfield.a.Assign(0b000111); | ||
| 57 | le_bitfield.b.Assign(-1); | ||
| 58 | le_bitfield.c.Assign(TestEnum::C); | ||
| 59 | le_bitfield.d.Assign(0b01010101010101); | ||
| 60 | std::memcpy(&raw, &le_bitfield, sizeof(raw)); | ||
| 61 | // bit fields: 01010101010101'00001111'1111'000111 | ||
| 62 | REQUIRE(le_bitfield.raw == 0b01010101'01010100'00111111'11000111); | ||
| 63 | REQUIRE(raw == std::array<u8, 4>{{ | ||
| 64 | 0b11000111, | ||
| 65 | 0b00111111, | ||
| 66 | 0b01010100, | ||
| 67 | 0b01010101, | ||
| 68 | }}); | ||
| 69 | |||
| 70 | // bit fields: 01101100111101'10101110'1011'101100 | ||
| 71 | REQUIRE(be_bitfield.raw == 0b01101100'11110110'10111010'11101100); | ||
| 72 | REQUIRE(be_bitfield.a == 0b101100); | ||
| 73 | REQUIRE(be_bitfield.b == -5); // 1011 as two's complement | ||
| 74 | REQUIRE(be_bitfield.c == TestEnum::B); | ||
| 75 | REQUIRE(be_bitfield.d == 0b01101100111101); | ||
| 76 | |||
| 77 | be_bitfield.a.Assign(0b000111); | ||
| 78 | be_bitfield.b.Assign(-1); | ||
| 79 | be_bitfield.c.Assign(TestEnum::C); | ||
| 80 | be_bitfield.d.Assign(0b01010101010101); | ||
| 81 | std::memcpy(&raw, &be_bitfield, sizeof(raw)); | ||
| 82 | // bit fields: 01010101010101'00001111'1111'000111 | ||
| 83 | REQUIRE(be_bitfield.raw == 0b01010101'01010100'00111111'11000111); | ||
| 84 | REQUIRE(raw == std::array<u8, 4>{{ | ||
| 85 | 0b01010101, | ||
| 86 | 0b01010100, | ||
| 87 | 0b00111111, | ||
| 88 | 0b11000111, | ||
| 89 | }}); | ||
| 90 | } | ||