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