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