1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28#ifndef VIXL_COMPILER_INTRINSICS_H
29#define VIXL_COMPILER_INTRINSICS_H
30
31#include "globals.h"
32
33namespace vixl {
34
35
36
37#define MAJOR 1000000
38#define MINOR 1000
39#if defined(__GNUC__) && defined(__GNUC_MINOR__) && defined(__GNUC_PATCHLEVEL__)
40#define GCC_VERSION_OR_NEWER(major, minor, patchlevel) \
41 ((__GNUC__ * MAJOR + __GNUC_MINOR__ * MINOR + __GNUC_PATCHLEVEL__) >= \
42 ((major) * MAJOR + (minor) * MINOR + (patchlevel)))
43#elif defined(__GNUC__) && defined(__GNUC_MINOR__)
44#define GCC_VERSION_OR_NEWER(major, minor, patchlevel) \
45 ((__GNUC__ * MAJOR + __GNUC_MINOR__ * MINOR) >= \
46 ((major) * MAJOR + (minor) * MINOR + (patchlevel)))
47#else
48#define GCC_VERSION_OR_NEWER(major, minor, patchlevel) 0
49#endif
50
51
52#if defined(__clang__) && !defined(VIXL_NO_COMPILER_BUILTINS)
53
54#define COMPILER_HAS_BUILTIN_CLRSB (__has_builtin(__builtin_clrsb))
55#define COMPILER_HAS_BUILTIN_CLZ (__has_builtin(__builtin_clz))
56#define COMPILER_HAS_BUILTIN_CTZ (__has_builtin(__builtin_ctz))
57#define COMPILER_HAS_BUILTIN_FFS (__has_builtin(__builtin_ffs))
58#define COMPILER_HAS_BUILTIN_POPCOUNT (__has_builtin(__builtin_popcount))
59
60#elif defined(__GNUC__) && !defined(VIXL_NO_COMPILER_BUILTINS)
61
62
63
64# define COMPILER_HAS_BUILTIN_CLRSB (GCC_VERSION_OR_NEWER(4, 7, 0))
65# define COMPILER_HAS_BUILTIN_CLZ (GCC_VERSION_OR_NEWER(3, 4, 0))
66# define COMPILER_HAS_BUILTIN_CTZ (GCC_VERSION_OR_NEWER(3, 4, 0))
67# define COMPILER_HAS_BUILTIN_FFS (GCC_VERSION_OR_NEWER(3, 4, 0))
68# define COMPILER_HAS_BUILTIN_POPCOUNT (GCC_VERSION_OR_NEWER(3, 4, 0))
69
70#else
71
72
73
74#define COMPILER_HAS_BUILTIN_BSWAP false
75#define COMPILER_HAS_BUILTIN_CLRSB false
76#define COMPILER_HAS_BUILTIN_CLZ false
77#define COMPILER_HAS_BUILTIN_CTZ false
78#define COMPILER_HAS_BUILTIN_FFS false
79#define COMPILER_HAS_BUILTIN_POPCOUNT false
80
81#endif
82
83
84template<typename V>
85inline bool IsPowerOf2(V value) {
86 return (value != 0) && ((value & (value - 1)) == 0);
87}
88
89
90
91int CountLeadingSignBitsFallBack(int64_t value, int width);
92int CountLeadingZerosFallBack(uint64_t value, int width);
93int CountSetBitsFallBack(uint64_t value, int width);
94int CountTrailingZerosFallBack(uint64_t value, int width);
95
96
97
98
99
100
101template<typename V>
102inline int CountLeadingSignBits(V value, int width = (sizeof(V) * 8)) {
103#if COMPILER_HAS_BUILTIN_CLRSB
104 if (width == 32) {
105 return __builtin_clrsb(value);
106 } else if (width == 64) {
107 return __builtin_clrsbll(value);
108 }
109#endif
110 return CountLeadingSignBitsFallBack(value, width);
111}
112
113
114template<typename V>
115inline int CountLeadingZeros(V value, int width = (sizeof(V) * 8)) {
116#if COMPILER_HAS_BUILTIN_CLZ
117 if (width == 32) {
118 return (value == 0) ? 32 : __builtin_clz(static_cast<unsigned>(value));
119 } else if (width == 64) {
120 return (value == 0) ? 64 : __builtin_clzll(value);
121 }
122#endif
123 return CountLeadingZerosFallBack(value, width);
124}
125
126
127template<typename V>
128inline int CountSetBits(V value, int width = (sizeof(V) * 8)) {
129#if COMPILER_HAS_BUILTIN_POPCOUNT
130 if (width == 32) {
131 return __builtin_popcount(static_cast<unsigned>(value));
132 } else if (width == 64) {
133 return __builtin_popcountll(value);
134 }
135#endif
136 return CountSetBitsFallBack(value, width);
137}
138
139
140template<typename V>
141inline int CountTrailingZeros(V value, int width = (sizeof(V) * 8)) {
142#if COMPILER_HAS_BUILTIN_CTZ
143 if (width == 32) {
144 return (value == 0) ? 32 : __builtin_ctz(static_cast<unsigned>(value));
145 } else if (width == 64) {
146 return (value == 0) ? 64 : __builtin_ctzll(value);
147 }
148#endif
149 return CountTrailingZerosFallBack(value, width);
150}
151
152}
153
154#endif
155
156