From 0a6f0dfb74d2a5ebacd20c13452f3eb3af994417 Mon Sep 17 00:00:00 2001 From: Lioncash Date: Fri, 13 Jan 2017 17:18:10 -0500 Subject: Common: Add bit utility header This attempts to make some bit arithmetic more self-documenting and also make it easier during review to identify potential off-by-one errors by making it possible to just specify which bits are being extracted. Functions both support the case where bits being extracted can vary and fixed bit extraction. In the case the bits are fixed, compile-time asserts are present to prevent accidental API usage at compile-time. e.g. Instead of shifting and masking to get bits 10 to 15, Common::ExtractBits<10, 15>(value) can just be done instead. --- Source/UnitTests/Common/BitUtilsTest.cpp | 59 ++++++++++++++++++++++++++++++++ 1 file changed, 59 insertions(+) create mode 100644 Source/UnitTests/Common/BitUtilsTest.cpp (limited to 'Source/UnitTests/Common/BitUtilsTest.cpp') diff --git a/Source/UnitTests/Common/BitUtilsTest.cpp b/Source/UnitTests/Common/BitUtilsTest.cpp new file mode 100644 index 0000000000..f607f0da2f --- /dev/null +++ b/Source/UnitTests/Common/BitUtilsTest.cpp @@ -0,0 +1,59 @@ +// Copyright 2017 Dolphin Emulator Project +// Licensed under GPLv2+ +// Refer to the license.txt file included. + +#include + +#include "Common/BitUtils.h" +#include "Common/CommonTypes.h" + +TEST(BitUtils, BitSize) +{ + EXPECT_EQ(Common::BitSize(), 8); + EXPECT_EQ(Common::BitSize(), 16); + EXPECT_EQ(Common::BitSize(), 32); + EXPECT_EQ(Common::BitSize(), 64); + + EXPECT_EQ(Common::BitSize(), 8); + EXPECT_EQ(Common::BitSize(), 16); + EXPECT_EQ(Common::BitSize(), 32); + EXPECT_EQ(Common::BitSize(), 64); +} + +TEST(BitUtils, ExtractBit) +{ + constexpr s32 zero = 0; + EXPECT_EQ(Common::ExtractBit<0>(zero), 0); + + constexpr s32 one = 1; + EXPECT_EQ(Common::ExtractBit<0>(one), 1); + + constexpr s32 negative_one = -1; + EXPECT_EQ(Common::ExtractBit<31>(negative_one), 1); + + constexpr s32 one_hundred_twenty_eight = 0b10000000; + EXPECT_EQ(Common::ExtractBit<7>(one_hundred_twenty_eight), 1); +} + +TEST(BitUtils, ExtractBits) +{ + // Note: Parenthesizing is necessary to prevent the macros from + // mangling the template function usages. + + constexpr s32 two_hundred_four_signed = 0b0011001100; + EXPECT_EQ((Common::ExtractBits<2, 3>(two_hundred_four_signed)), 3); + EXPECT_EQ((Common::ExtractBits<2, 7>(two_hundred_four_signed)), 51); + EXPECT_EQ((Common::ExtractBits<3, 6>(two_hundred_four_signed)), 9); + + constexpr u32 two_hundred_four_unsigned = 0b0011001100; + EXPECT_EQ((Common::ExtractBits<2, 3>(two_hundred_four_unsigned)), 3); + EXPECT_EQ((Common::ExtractBits<2, 7>(two_hundred_four_unsigned)), 51); + EXPECT_EQ((Common::ExtractBits<3, 6>(two_hundred_four_unsigned)), 9); + + // Ensure bit extraction remains sign-independent even when signed types are used. + constexpr s32 negative_one = -1; + EXPECT_EQ((Common::ExtractBits<0, 31>(negative_one)), 0xFFFFFFFFU); + + // Ensure bit extraction with type overriding works as expected + EXPECT_EQ((Common::ExtractBits<0, 31, s32, s32>(negative_one)), -1); +} -- cgit v1.2.3