1 // Copyright 2014 the V8 project 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 #ifndef V8_BASE_BITS_H_ 6 #define V8_BASE_BITS_H_ 7 8 #include <stdint.h> 9 #include "src/base/macros.h" 10 #if V8_CC_MSVC 11 #include <intrin.h> 12 #endif 13 #if V8_OS_WIN32 14 #include "src/base/win32-headers.h" 15 #endif 16 17 namespace v8 { 18 namespace base { 19 namespace bits { 20 21 // CountPopulation32(value) returns the number of bits set in |value|. 22 inline unsigned CountPopulation32(uint32_t value) { 23 #if V8_HAS_BUILTIN_POPCOUNT 24 return __builtin_popcount(value); 25 #else 26 value = ((value >> 1) & 0x55555555) + (value & 0x55555555); 27 value = ((value >> 2) & 0x33333333) + (value & 0x33333333); 28 value = ((value >> 4) & 0x0f0f0f0f) + (value & 0x0f0f0f0f); 29 value = ((value >> 8) & 0x00ff00ff) + (value & 0x00ff00ff); 30 value = ((value >> 16) & 0x0000ffff) + (value & 0x0000ffff); 31 return static_cast<unsigned>(value); 32 #endif 33 } 34 35 36 // CountPopulation64(value) returns the number of bits set in |value|. 37 inline unsigned CountPopulation64(uint64_t value) { 38 #if V8_HAS_BUILTIN_POPCOUNT 39 return __builtin_popcountll(value); 40 #else 41 return CountPopulation32(static_cast<uint32_t>(value)) + 42 CountPopulation32(static_cast<uint32_t>(value >> 32)); 43 #endif 44 } 45 46 47 // Overloaded versions of CountPopulation32/64. 48 inline unsigned CountPopulation(uint32_t value) { 49 return CountPopulation32(value); 50 } 51 52 53 inline unsigned CountPopulation(uint64_t value) { 54 return CountPopulation64(value); 55 } 56 57 58 // CountLeadingZeros32(value) returns the number of zero bits following the most 59 // significant 1 bit in |value| if |value| is non-zero, otherwise it returns 32. 60 inline unsigned CountLeadingZeros32(uint32_t value) { 61 #if V8_HAS_BUILTIN_CLZ 62 return value ? __builtin_clz(value) : 32; 63 #elif V8_CC_MSVC 64 unsigned long result; // NOLINT(runtime/int) 65 if (!_BitScanReverse(&result, value)) return 32; 66 return static_cast<unsigned>(31 - result); 67 #else 68 value = value | (value >> 1); 69 value = value | (value >> 2); 70 value = value | (value >> 4); 71 value = value | (value >> 8); 72 value = value | (value >> 16); 73 return CountPopulation32(~value); 74 #endif 75 } 76 77 78 // CountLeadingZeros64(value) returns the number of zero bits following the most 79 // significant 1 bit in |value| if |value| is non-zero, otherwise it returns 64. 80 inline unsigned CountLeadingZeros64(uint64_t value) { 81 #if V8_HAS_BUILTIN_CLZ 82 return value ? __builtin_clzll(value) : 64; 83 #else 84 value = value | (value >> 1); 85 value = value | (value >> 2); 86 value = value | (value >> 4); 87 value = value | (value >> 8); 88 value = value | (value >> 16); 89 value = value | (value >> 32); 90 return CountPopulation64(~value); 91 #endif 92 } 93 94 95 // CountTrailingZeros32(value) returns the number of zero bits preceding the 96 // least significant 1 bit in |value| if |value| is non-zero, otherwise it 97 // returns 32. 98 inline unsigned CountTrailingZeros32(uint32_t value) { 99 #if V8_HAS_BUILTIN_CTZ 100 return value ? __builtin_ctz(value) : 32; 101 #elif V8_CC_MSVC 102 unsigned long result; // NOLINT(runtime/int) 103 if (!_BitScanForward(&result, value)) return 32; 104 return static_cast<unsigned>(result); 105 #else 106 if (value == 0) return 32; 107 unsigned count = 0; 108 for (value ^= value - 1; value >>= 1; ++count) { 109 } 110 return count; 111 #endif 112 } 113 114 115 // CountTrailingZeros64(value) returns the number of zero bits preceding the 116 // least significant 1 bit in |value| if |value| is non-zero, otherwise it 117 // returns 64. 118 inline unsigned CountTrailingZeros64(uint64_t value) { 119 #if V8_HAS_BUILTIN_CTZ 120 return value ? __builtin_ctzll(value) : 64; 121 #else 122 if (value == 0) return 64; 123 unsigned count = 0; 124 for (value ^= value - 1; value >>= 1; ++count) { 125 } 126 return count; 127 #endif 128 } 129 130 131 // Returns true iff |value| is a power of 2. 132 inline bool IsPowerOfTwo32(uint32_t value) { 133 return value && !(value & (value - 1)); 134 } 135 136 137 // Returns true iff |value| is a power of 2. 138 inline bool IsPowerOfTwo64(uint64_t value) { 139 return value && !(value & (value - 1)); 140 } 141 142 143 // RoundUpToPowerOfTwo32(value) returns the smallest power of two which is 144 // greater than or equal to |value|. If you pass in a |value| that is already a 145 // power of two, it is returned as is. |value| must be less than or equal to 146 // 0x80000000u. Implementation is from "Hacker's Delight" by Henry S. Warren, 147 // Jr., figure 3-3, page 48, where the function is called clp2. 148 uint32_t RoundUpToPowerOfTwo32(uint32_t value); 149 150 151 // RoundDownToPowerOfTwo32(value) returns the greatest power of two which is 152 // less than or equal to |value|. If you pass in a |value| that is already a 153 // power of two, it is returned as is. 154 inline uint32_t RoundDownToPowerOfTwo32(uint32_t value) { 155 if (value > 0x80000000u) return 0x80000000u; 156 uint32_t result = RoundUpToPowerOfTwo32(value); 157 if (result > value) result >>= 1; 158 return result; 159 } 160 161 162 // Precondition: 0 <= shift < 32 163 inline uint32_t RotateRight32(uint32_t value, uint32_t shift) { 164 if (shift == 0) return value; 165 return (value >> shift) | (value << (32 - shift)); 166 } 167 168 // Precondition: 0 <= shift < 32 169 inline uint32_t RotateLeft32(uint32_t value, uint32_t shift) { 170 if (shift == 0) return value; 171 return (value << shift) | (value >> (32 - shift)); 172 } 173 174 // Precondition: 0 <= shift < 64 175 inline uint64_t RotateRight64(uint64_t value, uint64_t shift) { 176 if (shift == 0) return value; 177 return (value >> shift) | (value << (64 - shift)); 178 } 179 180 // Precondition: 0 <= shift < 64 181 inline uint64_t RotateLeft64(uint64_t value, uint64_t shift) { 182 if (shift == 0) return value; 183 return (value << shift) | (value >> (64 - shift)); 184 } 185 186 187 // SignedAddOverflow32(lhs,rhs,val) performs a signed summation of |lhs| and 188 // |rhs| and stores the result into the variable pointed to by |val| and 189 // returns true if the signed summation resulted in an overflow. 190 inline bool SignedAddOverflow32(int32_t lhs, int32_t rhs, int32_t* val) { 191 #if V8_HAS_BUILTIN_SADD_OVERFLOW 192 return __builtin_sadd_overflow(lhs, rhs, val); 193 #else 194 uint32_t res = static_cast<uint32_t>(lhs) + static_cast<uint32_t>(rhs); 195 *val = bit_cast<int32_t>(res); 196 return ((res ^ lhs) & (res ^ rhs) & (1U << 31)) != 0; 197 #endif 198 } 199 200 201 // SignedSubOverflow32(lhs,rhs,val) performs a signed subtraction of |lhs| and 202 // |rhs| and stores the result into the variable pointed to by |val| and 203 // returns true if the signed subtraction resulted in an overflow. 204 inline bool SignedSubOverflow32(int32_t lhs, int32_t rhs, int32_t* val) { 205 #if V8_HAS_BUILTIN_SSUB_OVERFLOW 206 return __builtin_ssub_overflow(lhs, rhs, val); 207 #else 208 uint32_t res = static_cast<uint32_t>(lhs) - static_cast<uint32_t>(rhs); 209 *val = bit_cast<int32_t>(res); 210 return ((res ^ lhs) & (res ^ ~rhs) & (1U << 31)) != 0; 211 #endif 212 } 213 214 215 // SignedAddOverflow64(lhs,rhs,val) performs a signed summation of |lhs| and 216 // |rhs| and stores the result into the variable pointed to by |val| and 217 // returns true if the signed summation resulted in an overflow. 218 inline bool SignedAddOverflow64(int64_t lhs, int64_t rhs, int64_t* val) { 219 uint64_t res = static_cast<uint64_t>(lhs) + static_cast<uint64_t>(rhs); 220 *val = bit_cast<int64_t>(res); 221 return ((res ^ lhs) & (res ^ rhs) & (1ULL << 63)) != 0; 222 } 223 224 225 // SignedSubOverflow64(lhs,rhs,val) performs a signed subtraction of |lhs| and 226 // |rhs| and stores the result into the variable pointed to by |val| and 227 // returns true if the signed subtraction resulted in an overflow. 228 inline bool SignedSubOverflow64(int64_t lhs, int64_t rhs, int64_t* val) { 229 uint64_t res = static_cast<uint64_t>(lhs) - static_cast<uint64_t>(rhs); 230 *val = bit_cast<int64_t>(res); 231 return ((res ^ lhs) & (res ^ ~rhs) & (1ULL << 63)) != 0; 232 } 233 234 235 // SignedMulHigh32(lhs, rhs) multiplies two signed 32-bit values |lhs| and 236 // |rhs|, extracts the most significant 32 bits of the result, and returns 237 // those. 238 int32_t SignedMulHigh32(int32_t lhs, int32_t rhs); 239 240 241 // SignedMulHighAndAdd32(lhs, rhs, acc) multiplies two signed 32-bit values 242 // |lhs| and |rhs|, extracts the most significant 32 bits of the result, and 243 // adds the accumulate value |acc|. 244 int32_t SignedMulHighAndAdd32(int32_t lhs, int32_t rhs, int32_t acc); 245 246 247 // SignedDiv32(lhs, rhs) divides |lhs| by |rhs| and returns the quotient 248 // truncated to int32. If |rhs| is zero, then zero is returned. If |lhs| 249 // is minint and |rhs| is -1, it returns minint. 250 int32_t SignedDiv32(int32_t lhs, int32_t rhs); 251 252 253 // SignedMod32(lhs, rhs) divides |lhs| by |rhs| and returns the remainder 254 // truncated to int32. If either |rhs| is zero or |lhs| is minint and |rhs| 255 // is -1, it returns zero. 256 int32_t SignedMod32(int32_t lhs, int32_t rhs); 257 258 259 // UnsignedAddOverflow32(lhs,rhs,val) performs an unsigned summation of |lhs| 260 // and |rhs| and stores the result into the variable pointed to by |val| and 261 // returns true if the unsigned summation resulted in an overflow. 262 inline bool UnsignedAddOverflow32(uint32_t lhs, uint32_t rhs, uint32_t* val) { 263 #if V8_HAS_BUILTIN_SADD_OVERFLOW 264 return __builtin_uadd_overflow(lhs, rhs, val); 265 #else 266 *val = lhs + rhs; 267 return *val < (lhs | rhs); 268 #endif 269 } 270 271 272 // UnsignedDiv32(lhs, rhs) divides |lhs| by |rhs| and returns the quotient 273 // truncated to uint32. If |rhs| is zero, then zero is returned. 274 inline uint32_t UnsignedDiv32(uint32_t lhs, uint32_t rhs) { 275 return rhs ? lhs / rhs : 0u; 276 } 277 278 279 // UnsignedMod32(lhs, rhs) divides |lhs| by |rhs| and returns the remainder 280 // truncated to uint32. If |rhs| is zero, then zero is returned. 281 inline uint32_t UnsignedMod32(uint32_t lhs, uint32_t rhs) { 282 return rhs ? lhs % rhs : 0u; 283 } 284 285 } // namespace bits 286 } // namespace base 287 } // namespace v8 288 289 #endif // V8_BASE_BITS_H_ 290