From f65ee46f7cf2f0d0914ca2dba53cd463c885e567 Mon Sep 17 00:00:00 2001 From: Rick Altherr Date: Fri, 1 Dec 2017 08:47:21 -0800 Subject: [PATCH] lib: bit manipulation functions Functions for hiding all the masking and shifting required for accessing bit ranges within an integer type. Signed-off-by: Rick Altherr Signed-off-by: Tim 'mithro' Ansell --- lib/CMakeLists.txt | 5 ++++ lib/bit_ops_test.cc | 43 +++++++++++++++++++++++++++++++++++ lib/include/prjxray/bit_ops.h | 36 +++++++++++++++++++++++++++++ 3 files changed, 84 insertions(+) create mode 100644 lib/bit_ops_test.cc create mode 100644 lib/include/prjxray/bit_ops.h diff --git a/lib/CMakeLists.txt b/lib/CMakeLists.txt index 844a5e84..d6722609 100644 --- a/lib/CMakeLists.txt +++ b/lib/CMakeLists.txt @@ -6,6 +6,11 @@ target_include_directories(libprjxray PUBLIC "include") target_link_libraries(libprjxray absl::strings) if (PRJXRAY_BUILD_TESTING) + add_executable(bit_ops_test bit_ops_test.cc) + target_link_libraries(bit_ops_test libprjxray gtest_main) + add_test(NAME bit_ops_test + COMMAND bit_ops_test) + add_executable(memory_mapped_file_test memory_mapped_file_test.cc) target_link_libraries(memory_mapped_file_test libprjxray gtest_main) add_test(NAME memory_mapped_file_test diff --git a/lib/bit_ops_test.cc b/lib/bit_ops_test.cc new file mode 100644 index 00000000..81adfbdc --- /dev/null +++ b/lib/bit_ops_test.cc @@ -0,0 +1,43 @@ +#include + +#include + +TEST(BitMaskTest, Bit0) { + uint32_t expected = prjxray::bit_mask(0); + EXPECT_EQ(static_cast(0x1), expected); +} + +TEST(BitMaskTest, Bit3) { + uint32_t expected = prjxray::bit_mask(3); + EXPECT_EQ(static_cast(0x8), expected); +} + +TEST(BitMaskRange, SingleBit) { + uint32_t expected = prjxray::bit_mask_range(23, 23); + EXPECT_EQ(static_cast(0x800000), expected); +} + +TEST(BitMaskRange, DownToZero) { + uint32_t expected = prjxray::bit_mask_range(7, 0); + EXPECT_EQ(static_cast(0xFF), expected); +} + +TEST(BitMaskRange, MiddleBits) { + uint32_t expected = prjxray::bit_mask_range(18, 8); + EXPECT_EQ(static_cast(0x7FF00), expected); +} + +TEST(BitFieldGetTest, OneSelectedBit) { + uint32_t expected = prjxray::bit_field_get(0xFFFFFFFF, 23, 23); + EXPECT_EQ(static_cast(1), expected); +} + +TEST(BitFieldGetTest, SelectDownToZero) { + uint32_t expected = prjxray::bit_field_get(0xFFCCBBAA, 7, 0); + EXPECT_EQ(static_cast(0xAA), expected); +} + +TEST(BitFieldGetTest, SelectMidway) { + uint32_t expected = prjxray::bit_field_get(0xFFCCBBAA, 18, 8); + EXPECT_EQ(static_cast(0x4BB), expected); +} diff --git a/lib/include/prjxray/bit_ops.h b/lib/include/prjxray/bit_ops.h new file mode 100644 index 00000000..ac779b4e --- /dev/null +++ b/lib/include/prjxray/bit_ops.h @@ -0,0 +1,36 @@ +#ifndef PRJXRAY_LIB_BIT_OPS_H +#define PRJXRAY_LIB_BIT_OPS_H + +namespace prjxray { + +template +constexpr UInt bit_mask(int bit) { + return (static_cast(1) << bit); +} + +template +constexpr UInt bit_sizeof() { + return sizeof(UInt) * 8; +} + +template +constexpr UInt bit_all_ones() { + return ~static_cast(0); +} + +template +constexpr UInt bit_mask_range(int top_bit, int bottom_bit) { + return ((bit_all_ones() >> (bit_sizeof() - 1 - top_bit)) & + (bit_all_ones() - bit_mask(bottom_bit) + + static_cast(1))); +} + + +template +constexpr UInt bit_field_get(UInt value, int top_bit, int bottom_bit) { + return (value & bit_mask_range(top_bit, bottom_bit)) >> bottom_bit; +} + +} // namespace prjxray + +#endif // PRJXRAY_LIB_BIT_OPS_H