1 // Copyright (c) 2013 The Chromium Authors. All rights reserved. 2 // Use of this source code is governed by a BSD-style license that can be 3 // found in the LICENSE file. 4 5 // This file defines some bit utilities. 6 7 #ifndef BASE_BITS_H_ 8 #define BASE_BITS_H_ 9 10 #include <stddef.h> 11 #include <stdint.h> 12 13 #include "third_party/base/compiler_specific.h" 14 #include "third_party/base/logging.h" 15 16 #if defined(COMPILER_MSVC) 17 #include <intrin.h> 18 #endif 19 20 namespace pdfium { 21 namespace base { 22 namespace bits { 23 24 // Returns the integer i such as 2^i <= n < 2^(i+1) 25 inline int Log2Floor(uint32_t n) { 26 if (n == 0) 27 return -1; 28 int log = 0; 29 uint32_t value = n; 30 for (int i = 4; i >= 0; --i) { 31 int shift = (1 << i); 32 uint32_t x = value >> shift; 33 if (x != 0) { 34 value = x; 35 log += shift; 36 } 37 } 38 DCHECK_EQ(value, 1u); 39 return log; 40 } 41 42 // Returns the integer i such as 2^(i-1) < n <= 2^i 43 inline int Log2Ceiling(uint32_t n) { 44 if (n == 0) { 45 return -1; 46 } else { 47 // Log2Floor returns -1 for 0, so the following works correctly for n=1. 48 return 1 + Log2Floor(n - 1); 49 } 50 } 51 52 // Round up |size| to a multiple of alignment, which must be a power of two. 53 inline size_t Align(size_t size, size_t alignment) { 54 DCHECK_EQ(alignment & (alignment - 1), 0u); 55 return (size + alignment - 1) & ~(alignment - 1); 56 } 57 58 // These functions count the number of leading zeros in a binary value, starting 59 // with the most significant bit. C does not have an operator to do this, but 60 // fortunately the various compilers have built-ins that map to fast underlying 61 // processor instructions. 62 #if defined(COMPILER_MSVC) 63 64 ALWAYS_INLINE uint32_t CountLeadingZeroBits32(uint32_t x) { 65 unsigned long index; 66 return LIKELY(_BitScanReverse(&index, x)) ? (31 - index) : 32; 67 } 68 69 #if defined(ARCH_CPU_64_BITS) 70 71 // MSVC only supplies _BitScanForward64 when building for a 64-bit target. 72 ALWAYS_INLINE uint64_t CountLeadingZeroBits64(uint64_t x) { 73 unsigned long index; 74 return LIKELY(_BitScanReverse64(&index, x)) ? (63 - index) : 64; 75 } 76 77 #endif 78 79 #elif defined(COMPILER_GCC) 80 81 // This is very annoying. __builtin_clz has undefined behaviour for an input of 82 // 0, even though there's clearly a return value that makes sense, and even 83 // though some processor clz instructions have defined behaviour for 0. We could 84 // drop to raw __asm__ to do better, but we'll avoid doing that unless we see 85 // proof that we need to. 86 ALWAYS_INLINE uint32_t CountLeadingZeroBits32(uint32_t x) { 87 return LIKELY(x) ? __builtin_clz(x) : 32; 88 } 89 90 ALWAYS_INLINE uint64_t CountLeadingZeroBits64(uint64_t x) { 91 return LIKELY(x) ? __builtin_clzll(x) : 64; 92 } 93 94 #endif 95 96 #if defined(ARCH_CPU_64_BITS) 97 98 ALWAYS_INLINE size_t CountLeadingZeroBitsSizeT(size_t x) { 99 return CountLeadingZeroBits64(x); 100 } 101 102 #else 103 104 ALWAYS_INLINE size_t CountLeadingZeroBitsSizeT(size_t x) { 105 return CountLeadingZeroBits32(x); 106 } 107 108 #endif 109 110 } // namespace bits 111 } // namespace base 112 } // namespace pdfium 113 114 #endif // BASE_BITS_H_ 115