From 9d2e93ee219c1cd10561aa9c2695c6cae180ed56 Mon Sep 17 00:00:00 2001 From: SciresM Date: Sat, 22 Feb 2020 19:07:05 -0800 Subject: [PATCH] Merge branch 'master' into mesosphere-dev --- libvapours/include/vapours/includes.hpp | 33 +++----- libvapours/include/vapours/types.hpp | 25 ++++++ libvapours/include/vapours/util.hpp | 1 + .../include/vapours/util/util_bitutil.hpp | 77 +++++++++++++++++++ 4 files changed, 113 insertions(+), 23 deletions(-) create mode 100644 libvapours/include/vapours/util/util_bitutil.hpp diff --git a/libvapours/include/vapours/includes.hpp b/libvapours/include/vapours/includes.hpp index 64ac45ee..9180881e 100644 --- a/libvapours/include/vapours/includes.hpp +++ b/libvapours/include/vapours/includes.hpp @@ -26,36 +26,29 @@ #include #include - +/* C++ headers. */ #include #include #include #include -#include #include - -/* Stratosphere wants stdlib headers, others do not.. */ -#ifdef ATMOSPHERE_IS_STRATOSPHERE - -/* C++ headers. */ +#include #include #include -#include -#include -#include #include #include #include + +/* Stratosphere wants additional libstdc++ headers, others do not. */ +#ifdef ATMOSPHERE_IS_STRATOSPHERE + +#include +#include +#include #include #include #include -#endif /* ATMOSPHERE_IS_STRATOSPHERE */ - -#ifdef ATMOSPHERE_BOARD_NINTENDO_NX - -#ifdef ATMOSPHERE_IS_STRATOSPHERE - /* Libnx. */ #include @@ -64,13 +57,7 @@ /* Non-EL0 code can't include libnx. */ #include "types.hpp" -#endif - -#else - -#error "Unsupported board" - -#endif /* ATMOSPHERE_BOARD_NINTENDO_NX */ +#endif /* ATMOSPHERE_IS_STRATOSPHERE */ /* Atmosphere meta. */ #include "ams_version.h" diff --git a/libvapours/include/vapours/types.hpp b/libvapours/include/vapours/types.hpp index 891d661d..0d4b4b6f 100644 --- a/libvapours/include/vapours/types.hpp +++ b/libvapours/include/vapours/types.hpp @@ -52,6 +52,31 @@ typedef u32 Result; ///< Function error code result type. #define BIT(n) (1U<<(n)) #endif +/// Creates a bitmask from a bit number (long). +#ifndef BITL +#define BITL(n) (1UL<<(n)) +#endif + +/// Creates a bitmask representing the n least significant bits. +#ifndef MASK +#define MASK(n) (BIT(n) - 1U) +#endif + +/// Creates a bitmask representing the n least significant bits (long). +#ifndef MASKL +#define MASKL(n) (BITL(n) - 1UL) +#endif + +/// Creates a bitmask for bit range extraction. +#ifndef MASK2 +#define MASK2(a,b) (MASK(a) & ~MASK(b)) +#endif + +/// Creates a bitmask for bit range extraction (long). +#ifndef MASK2L +#define MASK2L(a,b) (MASKL(a) & ~MASKL(b)) +#endif + /// Marks a function as not returning, for the purposes of compiler optimization. #ifndef NORETURN #define NORETURN __attribute__((noreturn)) diff --git a/libvapours/include/vapours/util.hpp b/libvapours/include/vapours/util.hpp index 94013a1a..2f1035ec 100644 --- a/libvapours/include/vapours/util.hpp +++ b/libvapours/include/vapours/util.hpp @@ -28,3 +28,4 @@ #include "util/util_intrusive_list.hpp" #include "util/util_intrusive_red_black_tree.hpp" #include "util/util_tinymt.hpp" +#include "util/util_bitutil.hpp" \ No newline at end of file diff --git a/libvapours/include/vapours/util/util_bitutil.hpp b/libvapours/include/vapours/util/util_bitutil.hpp new file mode 100644 index 00000000..ade7193b --- /dev/null +++ b/libvapours/include/vapours/util/util_bitutil.hpp @@ -0,0 +1,77 @@ +/* + * Copyright (c) 2018-2020 Atmosphère-NX + * + * This program is free software; you can redistribute it and/or modify it + * under the terms and conditions of the GNU General Public License, + * version 2, as published by the Free Software Foundation. + * + * This program is distributed in the hope it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for + * more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + +#pragma once + +#include "../defines.hpp" +#include "../types.hpp" + +namespace ams::util { + + template + class BitsOf { + private: + static_assert(std::is_integral::value); + + static constexpr ALWAYS_INLINE int GetLsbPos(T v) { + return __builtin_ctzll(static_cast(v)); + } + + T value; + public: + /* Note: GCC has a bug in constant-folding here. Workaround: wrap entire caller with constexpr. */ + constexpr ALWAYS_INLINE BitsOf(T value = T(0u)) : value(value) { + /* ... */ + } + + constexpr ALWAYS_INLINE bool operator==(const BitsOf &other) const { + return this->value == other.value; + } + + constexpr ALWAYS_INLINE bool operator!=(const BitsOf &other) const { + return this->value != other.value; + } + + constexpr ALWAYS_INLINE int operator*() const { + return GetLsbPos(this->value); + } + + constexpr ALWAYS_INLINE BitsOf &operator++() { + this->value &= ~(T(1u) << GetLsbPos(this->value)); + return *this; + } + + constexpr ALWAYS_INLINE BitsOf &operator++(int) { + BitsOf ret(this->value); + ++(*this); + return ret; + } + + constexpr ALWAYS_INLINE BitsOf begin() const { + return *this; + } + + constexpr ALWAYS_INLINE BitsOf end() const { + return BitsOf(T(0u)); + } + }; + + template + constexpr ALWAYS_INLINE T CombineBits(Args... args) { + return (... | (T(1u) << args)); + } + +}