• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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