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 11namespace v8 { 12namespace base { 13namespace bits { 14 15uint32_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 31uint64_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 49int32_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 55int32_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 61int32_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 68int32_t SignedMod32(int32_t lhs, int32_t rhs) { 69 if (rhs == 0 || rhs == -1) return 0; 70 return lhs % rhs; 71} 72 73int64_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 82int64_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 91bool 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