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|.
CountPopulation32(uint32_t 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|.
CountPopulation64(uint64_t 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.
CountPopulation(uint32_t value)48 inline unsigned CountPopulation(uint32_t value) {
49 return CountPopulation32(value);
50 }
51
52
CountPopulation(uint64_t value)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.
CountLeadingZeros32(uint32_t value)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.
CountLeadingZeros64(uint64_t value)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.
CountTrailingZeros32(uint32_t value)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.
CountTrailingZeros64(uint64_t value)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.
IsPowerOfTwo32(uint32_t value)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.
IsPowerOfTwo64(uint64_t value)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.
RoundDownToPowerOfTwo32(uint32_t value)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
RotateRight32(uint32_t value,uint32_t shift)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
RotateLeft32(uint32_t value,uint32_t shift)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
RotateRight64(uint64_t value,uint64_t shift)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
RotateLeft64(uint64_t value,uint64_t shift)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.
SignedAddOverflow32(int32_t lhs,int32_t rhs,int32_t * val)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.
SignedSubOverflow32(int32_t lhs,int32_t rhs,int32_t * val)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.
SignedAddOverflow64(int64_t lhs,int64_t rhs,int64_t * val)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.
SignedSubOverflow64(int64_t lhs,int64_t rhs,int64_t * val)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.
UnsignedAddOverflow32(uint32_t lhs,uint32_t rhs,uint32_t * val)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.
UnsignedDiv32(uint32_t lhs,uint32_t rhs)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.
UnsignedMod32(uint32_t lhs,uint32_t rhs)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