diff --git a/libraries/libvapours/include/vapours/defines.hpp b/libraries/libvapours/include/vapours/defines.hpp
index 9d0982a8b..629b3723f 100644
--- a/libraries/libvapours/include/vapours/defines.hpp
+++ b/libraries/libvapours/include/vapours/defines.hpp
@@ -42,6 +42,8 @@
#define CONCATENATE_IMPL(S1, s2) s1##s2
#define CONCATENATE(s1, s2) CONCATENATE_IMPL(s1, s2)
+#define BITSIZEOF(x) (sizeof(x) * CHAR_BIT)
+
#ifdef __COUNTER__
#define ANONYMOUS_VARIABLE(pref) CONCATENATE(pref, __COUNTER__)
#else
@@ -55,8 +57,8 @@
probability; \
}))
-#define AMS_PREDICT_TRUE(expr, probability) AMS_PREDICT(!!expr, 1, probability)
-#define AMS_PREDICT_FALSE(expr, probability) AMS_PREDICT(!!expr, 0, probability)
+#define AMS_PREDICT_TRUE(expr, probability) AMS_PREDICT(!!(expr), 1, probability)
+#define AMS_PREDICT_FALSE(expr, probability) AMS_PREDICT(!!(expr), 0, probability)
#define AMS_LIKELY(expr) AMS_PREDICT_TRUE(expr, 1.0)
#define AMS_UNLIKELY(expr) AMS_PREDICT_FALSE(expr, 1.0)
diff --git a/libraries/libvapours/include/vapours/util.hpp b/libraries/libvapours/include/vapours/util.hpp
index c35192e45..a3562c93a 100644
--- a/libraries/libvapours/include/vapours/util.hpp
+++ b/libraries/libvapours/include/vapours/util.hpp
@@ -20,6 +20,7 @@
#include "util/util_alignment.hpp"
#include "util/util_size.hpp"
#include "util/util_fourcc.hpp"
+#include "util/util_bitpack.hpp"
#include "util/util_scope_guard.hpp"
#include "util/util_typed_storage.hpp"
#include "util/util_intrusive_list.hpp"
diff --git a/libraries/libvapours/include/vapours/util/util_bitpack.hpp b/libraries/libvapours/include/vapours/util/util_bitpack.hpp
new file mode 100644
index 000000000..ccec50e98
--- /dev/null
+++ b/libraries/libvapours/include/vapours/util/util_bitpack.hpp
@@ -0,0 +1,87 @@
+/*
+ * Copyright (c) 2018-2019 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"
+
+namespace ams::util {
+
+ namespace impl {
+
+ template
+ class BitPack {
+ private:
+ static_assert(std::is_integral::value);
+ static_assert(std::is_unsigned::value);
+
+ template
+ static constexpr inline IntegralStorageType Mask = [] {
+ static_assert(Index < BITSIZEOF(IntegralStorageType));
+ static_assert(0 < Count && Count <= BITSIZEOF(IntegralStorageType));
+ static_assert(Index + Count <= BITSIZEOF(IntegralStorageType));
+
+ return ((IntegralStorageType(1) << Count) - 1) << Index;
+ }();
+ public:
+ template
+ struct Field {
+ using Type = T;
+ static constexpr size_t Index = _Index;
+ static constexpr size_t Count = _Count;
+ static constexpr size_t Next = Index + Count;
+
+ using BitPackType = BitPack;
+
+ static_assert(Mask != 0);
+ static_assert(std::is_integral::value);
+ static_assert(!std::is_same::value || Count == 1);
+ };
+ private:
+ IntegralStorageType value;
+ public:
+ constexpr ALWAYS_INLINE void Clear() {
+ constexpr IntegralStorageType Zero = IntegralStorageType(0);
+ this->value = Zero;
+ }
+
+ template
+ constexpr ALWAYS_INLINE typename FieldType::Type Get() const {
+ static_assert(std::is_same>::value);
+ return static_cast((this->value & Mask) >> FieldType::Index);
+ }
+
+ template
+ constexpr ALWAYS_INLINE void Set(typename FieldType::Type field_value) {
+ static_assert(std::is_same>::value);
+ constexpr IntegralStorageType FieldMask = Mask;
+ this->value &= ~FieldMask;
+ this->value |= (static_cast(field_value) << FieldType::Index) & FieldMask;
+ }
+ };
+
+ }
+
+ using BitPack8 = impl::BitPack;
+ using BitPack16 = impl::BitPack;
+ using BitPack32 = impl::BitPack;
+ using BitPack64 = impl::BitPack;
+
+ static_assert(std::is_pod::value);
+ static_assert(std::is_pod::value);
+ static_assert(std::is_pod::value);
+ static_assert(std::is_pod::value);
+
+}