1// Copyright 2013, ARM Limited 2// All rights reserved. 3// 4// Redistribution and use in source and binary forms, with or without 5// modification, are permitted provided that the following conditions are met: 6// 7// * Redistributions of source code must retain the above copyright notice, 8// this list of conditions and the following disclaimer. 9// * Redistributions in binary form must reproduce the above copyright notice, 10// this list of conditions and the following disclaimer in the documentation 11// and/or other materials provided with the distribution. 12// * Neither the name of ARM Limited nor the names of its contributors may be 13// used to endorse or promote products derived from this software without 14// specific prior written permission. 15// 16// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS CONTRIBUTORS "AS IS" AND 17// ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED 18// WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE 19// DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE 20// FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 21// DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR 22// SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER 23// CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, 24// OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 25// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 26 27#include "utils-vixl.h" 28#include <stdio.h> 29 30namespace vixl { 31 32uint32_t float_to_rawbits(float value) { 33 uint32_t bits = 0; 34 memcpy(&bits, &value, 4); 35 return bits; 36} 37 38 39uint64_t double_to_rawbits(double value) { 40 uint64_t bits = 0; 41 memcpy(&bits, &value, 8); 42 return bits; 43} 44 45 46float rawbits_to_float(uint32_t bits) { 47 float value = 0.0; 48 memcpy(&value, &bits, 4); 49 return value; 50} 51 52 53double rawbits_to_double(uint64_t bits) { 54 double value = 0.0; 55 memcpy(&value, &bits, 8); 56 return value; 57} 58 59 60int CountLeadingZeros(uint64_t value, int width) { 61 VIXL_ASSERT((width == 32) || (width == 64)); 62 int count = 0; 63 uint64_t bit_test = UINT64_C(1) << (width - 1); 64 while ((count < width) && ((bit_test & value) == 0)) { 65 count++; 66 bit_test >>= 1; 67 } 68 return count; 69} 70 71 72int CountLeadingSignBits(int64_t value, int width) { 73 VIXL_ASSERT((width == 32) || (width == 64)); 74 if (value >= 0) { 75 return CountLeadingZeros(value, width) - 1; 76 } else { 77 return CountLeadingZeros(~value, width) - 1; 78 } 79} 80 81 82int CountTrailingZeros(uint64_t value, int width) { 83 VIXL_ASSERT((width == 32) || (width == 64)); 84 int count = 0; 85 while ((count < width) && (((value >> count) & 1) == 0)) { 86 count++; 87 } 88 return count; 89} 90 91 92int CountSetBits(uint64_t value, int width) { 93 // TODO: Other widths could be added here, as the implementation already 94 // supports them. 95 VIXL_ASSERT((width == 32) || (width == 64)); 96 97 // Mask out unused bits to ensure that they are not counted. 98 value &= (UINT64_C(0xffffffffffffffff) >> (64-width)); 99 100 // Add up the set bits. 101 // The algorithm works by adding pairs of bit fields together iteratively, 102 // where the size of each bit field doubles each time. 103 // An example for an 8-bit value: 104 // Bits: h g f e d c b a 105 // \ | \ | \ | \ | 106 // value = h+g f+e d+c b+a 107 // \ | \ | 108 // value = h+g+f+e d+c+b+a 109 // \ | 110 // value = h+g+f+e+d+c+b+a 111 const uint64_t kMasks[] = { 112 UINT64_C(0x5555555555555555), 113 UINT64_C(0x3333333333333333), 114 UINT64_C(0x0f0f0f0f0f0f0f0f), 115 UINT64_C(0x00ff00ff00ff00ff), 116 UINT64_C(0x0000ffff0000ffff), 117 UINT64_C(0x00000000ffffffff), 118 }; 119 120 for (unsigned i = 0; i < (sizeof(kMasks) / sizeof(kMasks[0])); i++) { 121 int shift = 1 << i; 122 value = ((value >> shift) & kMasks[i]) + (value & kMasks[i]); 123 } 124 125 return value; 126} 127} // namespace vixl 128