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 #include "src/base/bits.h"
6
7 #include <limits>
8
9 #include "src/base/logging.h"
10
11 namespace v8 {
12 namespace base {
13 namespace bits {
14
RoundUpToPowerOfTwo32(uint32_t value)15 uint32_t RoundUpToPowerOfTwo32(uint32_t value) {
16 DCHECK_LE(value, uint32_t{1} << 31);
17 if (value) --value;
18 // Use computation based on leading zeros if we have compiler support for that.
19 #if V8_HAS_BUILTIN_CLZ || V8_CC_MSVC
20 return 1u << (32 - CountLeadingZeros(value));
21 #else
22 value |= value >> 1;
23 value |= value >> 2;
24 value |= value >> 4;
25 value |= value >> 8;
26 value |= value >> 16;
27 return value + 1;
28 #endif
29 }
30
RoundUpToPowerOfTwo64(uint64_t value)31 uint64_t RoundUpToPowerOfTwo64(uint64_t value) {
32 DCHECK_LE(value, uint64_t{1} << 63);
33 if (value) --value;
34 // Use computation based on leading zeros if we have compiler support for that.
35 #if V8_HAS_BUILTIN_CLZ
36 return uint64_t{1} << (64 - CountLeadingZeros(value));
37 #else
38 value |= value >> 1;
39 value |= value >> 2;
40 value |= value >> 4;
41 value |= value >> 8;
42 value |= value >> 16;
43 value |= value >> 32;
44 return value + 1;
45 #endif
46 }
47
48
SignedMulHigh32(int32_t lhs,int32_t rhs)49 int32_t SignedMulHigh32(int32_t lhs, int32_t rhs) {
50 int64_t const value = static_cast<int64_t>(lhs) * static_cast<int64_t>(rhs);
51 return bit_cast<int32_t, uint32_t>(bit_cast<uint64_t>(value) >> 32u);
52 }
53
54
SignedMulHighAndAdd32(int32_t lhs,int32_t rhs,int32_t acc)55 int32_t SignedMulHighAndAdd32(int32_t lhs, int32_t rhs, int32_t acc) {
56 return bit_cast<int32_t>(bit_cast<uint32_t>(acc) +
57 bit_cast<uint32_t>(SignedMulHigh32(lhs, rhs)));
58 }
59
60
SignedDiv32(int32_t lhs,int32_t rhs)61 int32_t SignedDiv32(int32_t lhs, int32_t rhs) {
62 if (rhs == 0) return 0;
63 if (rhs == -1) return lhs == std::numeric_limits<int32_t>::min() ? lhs : -lhs;
64 return lhs / rhs;
65 }
66
67
SignedMod32(int32_t lhs,int32_t rhs)68 int32_t SignedMod32(int32_t lhs, int32_t rhs) {
69 if (rhs == 0 || rhs == -1) return 0;
70 return lhs % rhs;
71 }
72
SignedSaturatedAdd64(int64_t lhs,int64_t rhs)73 int64_t SignedSaturatedAdd64(int64_t lhs, int64_t rhs) {
74 using limits = std::numeric_limits<int64_t>;
75 // Underflow if {lhs + rhs < min}. In that case, return {min}.
76 if (rhs < 0 && lhs < limits::min() - rhs) return limits::min();
77 // Overflow if {lhs + rhs > max}. In that case, return {max}.
78 if (rhs >= 0 && lhs > limits::max() - rhs) return limits::max();
79 return lhs + rhs;
80 }
81
SignedSaturatedSub64(int64_t lhs,int64_t rhs)82 int64_t SignedSaturatedSub64(int64_t lhs, int64_t rhs) {
83 using limits = std::numeric_limits<int64_t>;
84 // Underflow if {lhs - rhs < min}. In that case, return {min}.
85 if (rhs > 0 && lhs < limits::min() + rhs) return limits::min();
86 // Overflow if {lhs - rhs > max}. In that case, return {max}.
87 if (rhs <= 0 && lhs > limits::max() + rhs) return limits::max();
88 return lhs - rhs;
89 }
90
SignedMulOverflow32(int32_t lhs,int32_t rhs,int32_t * val)91 bool SignedMulOverflow32(int32_t lhs, int32_t rhs, int32_t* val) {
92 // Compute the result as {int64_t}, then check for overflow.
93 int64_t result = int64_t{lhs} * int64_t{rhs};
94 *val = static_cast<int32_t>(result);
95 using limits = std::numeric_limits<int32_t>;
96 return result < limits::min() || result > limits::max();
97 }
98
99 } // namespace bits
100 } // namespace base
101 } // namespace v8
102