blob: f0dd850e1fc13e6cfb9651bf4b0dd6c6bd64cf7d [file] [log] [blame]
ths05f778c2007-10-27 13:05:54 +00001/*
2 * Utility compute operations used by translated code.
3 *
4 * Copyright (c) 2007 Thiemo Seufer
5 * Copyright (c) 2007 Jocelyn Mayer
6 *
7 * Permission is hereby granted, free of charge, to any person obtaining a copy
8 * of this software and associated documentation files (the "Software"), to deal
9 * in the Software without restriction, including without limitation the rights
10 * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
11 * copies of the Software, and to permit persons to whom the Software is
12 * furnished to do so, subject to the following conditions:
13 *
14 * The above copyright notice and this permission notice shall be included in
15 * all copies or substantial portions of the Software.
16 *
17 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
18 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
19 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
20 * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
21 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
22 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
23 * THE SOFTWARE.
24 */
Paolo Bonzinicb9c3772012-12-06 12:15:58 +010025#ifndef HOST_UTILS_H
26#define HOST_UTILS_H 1
ths05f778c2007-10-27 13:05:54 +000027
Paolo Bonzini1de7afc2012-12-17 18:20:00 +010028#include "qemu/compiler.h" /* QEMU_GNUC_PREREQ */
Richard Henderson01654372013-02-13 17:47:34 -080029#include <limits.h>
thscebdff72008-06-05 22:55:54 +000030
j_mayer7a51ad82007-11-04 02:24:58 +000031#if defined(__x86_64__)
32#define __HAVE_FAST_MULU64__
Blue Swirlfacd2852009-08-16 08:03:26 +000033static inline void mulu64(uint64_t *plow, uint64_t *phigh,
34 uint64_t a, uint64_t b)
j_mayer7a51ad82007-11-04 02:24:58 +000035{
36 __asm__ ("mul %0\n\t"
37 : "=d" (*phigh), "=a" (*plow)
38 : "a" (a), "0" (b));
39}
40#define __HAVE_FAST_MULS64__
Blue Swirlfacd2852009-08-16 08:03:26 +000041static inline void muls64(uint64_t *plow, uint64_t *phigh,
42 int64_t a, int64_t b)
j_mayer7a51ad82007-11-04 02:24:58 +000043{
44 __asm__ ("imul %0\n\t"
45 : "=d" (*phigh), "=a" (*plow)
46 : "a" (a), "0" (b));
47}
48#else
j_mayer05e1d832007-11-05 13:16:23 +000049void muls64(uint64_t *phigh, uint64_t *plow, int64_t a, int64_t b);
j_mayer7a51ad82007-11-04 02:24:58 +000050void mulu64(uint64_t *phigh, uint64_t *plow, uint64_t a, uint64_t b);
51#endif
52
Richard Henderson72d81152013-02-13 17:47:35 -080053/**
54 * clz32 - count leading zeros in a 32-bit value.
55 * @val: The value to search
56 *
57 * Returns 32 if the value is zero. Note that the GCC builtin is
58 * undefined if the value is zero.
59 */
Blue Swirlfacd2852009-08-16 08:03:26 +000060static inline int clz32(uint32_t val)
ths05f778c2007-10-27 13:05:54 +000061{
aurel32bad5b1e2008-10-12 16:15:04 +000062#if QEMU_GNUC_PREREQ(3, 4)
Richard Henderson72d81152013-02-13 17:47:35 -080063 return val ? __builtin_clz(val) : 32;
aurel327d019982008-10-12 00:53:08 +000064#else
Richard Henderson72d81152013-02-13 17:47:35 -080065 /* Binary search for the leading one bit. */
ths05f778c2007-10-27 13:05:54 +000066 int cnt = 0;
67
68 if (!(val & 0xFFFF0000U)) {
69 cnt += 16;
70 val <<= 16;
71 }
72 if (!(val & 0xFF000000U)) {
73 cnt += 8;
74 val <<= 8;
75 }
76 if (!(val & 0xF0000000U)) {
77 cnt += 4;
78 val <<= 4;
79 }
80 if (!(val & 0xC0000000U)) {
81 cnt += 2;
82 val <<= 2;
83 }
84 if (!(val & 0x80000000U)) {
85 cnt++;
86 val <<= 1;
87 }
88 if (!(val & 0x80000000U)) {
89 cnt++;
90 }
91 return cnt;
aurel327d019982008-10-12 00:53:08 +000092#endif
ths05f778c2007-10-27 13:05:54 +000093}
94
Richard Henderson72d81152013-02-13 17:47:35 -080095/**
96 * clo32 - count leading ones in a 32-bit value.
97 * @val: The value to search
98 *
99 * Returns 32 if the value is -1.
100 */
Blue Swirlfacd2852009-08-16 08:03:26 +0000101static inline int clo32(uint32_t val)
ths05f778c2007-10-27 13:05:54 +0000102{
103 return clz32(~val);
104}
105
Richard Henderson72d81152013-02-13 17:47:35 -0800106/**
107 * clz64 - count leading zeros in a 64-bit value.
108 * @val: The value to search
109 *
110 * Returns 64 if the value is zero. Note that the GCC builtin is
111 * undefined if the value is zero.
112 */
Blue Swirlfacd2852009-08-16 08:03:26 +0000113static inline int clz64(uint64_t val)
ths05f778c2007-10-27 13:05:54 +0000114{
aurel32bad5b1e2008-10-12 16:15:04 +0000115#if QEMU_GNUC_PREREQ(3, 4)
Richard Henderson72d81152013-02-13 17:47:35 -0800116 return val ? __builtin_clzll(val) : 64;
aurel327d019982008-10-12 00:53:08 +0000117#else
ths05f778c2007-10-27 13:05:54 +0000118 int cnt = 0;
119
j_mayer7a51ad82007-11-04 02:24:58 +0000120 if (!(val >> 32)) {
ths05f778c2007-10-27 13:05:54 +0000121 cnt += 32;
j_mayer7a51ad82007-11-04 02:24:58 +0000122 } else {
123 val >>= 32;
ths05f778c2007-10-27 13:05:54 +0000124 }
j_mayer7a51ad82007-11-04 02:24:58 +0000125
126 return cnt + clz32(val);
aurel327d019982008-10-12 00:53:08 +0000127#endif
ths05f778c2007-10-27 13:05:54 +0000128}
129
Richard Henderson72d81152013-02-13 17:47:35 -0800130/**
131 * clo64 - count leading ones in a 64-bit value.
132 * @val: The value to search
133 *
134 * Returns 64 if the value is -1.
135 */
Blue Swirlfacd2852009-08-16 08:03:26 +0000136static inline int clo64(uint64_t val)
ths05f778c2007-10-27 13:05:54 +0000137{
138 return clz64(~val);
139}
j_mayerb9ef45f2007-10-28 12:52:38 +0000140
Richard Henderson72d81152013-02-13 17:47:35 -0800141/**
142 * ctz32 - count trailing zeros in a 32-bit value.
143 * @val: The value to search
144 *
145 * Returns 32 if the value is zero. Note that the GCC builtin is
146 * undefined if the value is zero.
147 */
Blue Swirlfacd2852009-08-16 08:03:26 +0000148static inline int ctz32(uint32_t val)
j_mayerb9ef45f2007-10-28 12:52:38 +0000149{
aurel32bad5b1e2008-10-12 16:15:04 +0000150#if QEMU_GNUC_PREREQ(3, 4)
Richard Henderson72d81152013-02-13 17:47:35 -0800151 return val ? __builtin_ctz(val) : 32;
aurel327d019982008-10-12 00:53:08 +0000152#else
Richard Henderson72d81152013-02-13 17:47:35 -0800153 /* Binary search for the trailing one bit. */
j_mayerb9ef45f2007-10-28 12:52:38 +0000154 int cnt;
155
156 cnt = 0;
157 if (!(val & 0x0000FFFFUL)) {
balrogc8906842008-11-12 17:18:41 +0000158 cnt += 16;
j_mayerb9ef45f2007-10-28 12:52:38 +0000159 val >>= 16;
balrogc8906842008-11-12 17:18:41 +0000160 }
j_mayerb9ef45f2007-10-28 12:52:38 +0000161 if (!(val & 0x000000FFUL)) {
balrogc8906842008-11-12 17:18:41 +0000162 cnt += 8;
j_mayerb9ef45f2007-10-28 12:52:38 +0000163 val >>= 8;
balrogc8906842008-11-12 17:18:41 +0000164 }
j_mayerb9ef45f2007-10-28 12:52:38 +0000165 if (!(val & 0x0000000FUL)) {
balrogc8906842008-11-12 17:18:41 +0000166 cnt += 4;
j_mayerb9ef45f2007-10-28 12:52:38 +0000167 val >>= 4;
balrogc8906842008-11-12 17:18:41 +0000168 }
j_mayerb9ef45f2007-10-28 12:52:38 +0000169 if (!(val & 0x00000003UL)) {
balrogc8906842008-11-12 17:18:41 +0000170 cnt += 2;
j_mayerb9ef45f2007-10-28 12:52:38 +0000171 val >>= 2;
balrogc8906842008-11-12 17:18:41 +0000172 }
j_mayerb9ef45f2007-10-28 12:52:38 +0000173 if (!(val & 0x00000001UL)) {
balrogc8906842008-11-12 17:18:41 +0000174 cnt++;
j_mayerb9ef45f2007-10-28 12:52:38 +0000175 val >>= 1;
balrogc8906842008-11-12 17:18:41 +0000176 }
j_mayerb9ef45f2007-10-28 12:52:38 +0000177 if (!(val & 0x00000001UL)) {
balrogc8906842008-11-12 17:18:41 +0000178 cnt++;
179 }
j_mayerb9ef45f2007-10-28 12:52:38 +0000180
balrogc8906842008-11-12 17:18:41 +0000181 return cnt;
aurel327d019982008-10-12 00:53:08 +0000182#endif
balrogc8906842008-11-12 17:18:41 +0000183}
184
Richard Henderson72d81152013-02-13 17:47:35 -0800185/**
186 * cto32 - count trailing ones in a 32-bit value.
187 * @val: The value to search
188 *
189 * Returns 32 if the value is -1.
190 */
Blue Swirlfacd2852009-08-16 08:03:26 +0000191static inline int cto32(uint32_t val)
balrogc8906842008-11-12 17:18:41 +0000192{
j_mayerb9ef45f2007-10-28 12:52:38 +0000193 return ctz32(~val);
194}
195
Richard Henderson72d81152013-02-13 17:47:35 -0800196/**
197 * ctz64 - count trailing zeros in a 64-bit value.
198 * @val: The value to search
199 *
200 * Returns 64 if the value is zero. Note that the GCC builtin is
201 * undefined if the value is zero.
202 */
Blue Swirlfacd2852009-08-16 08:03:26 +0000203static inline int ctz64(uint64_t val)
j_mayerb9ef45f2007-10-28 12:52:38 +0000204{
aurel32bad5b1e2008-10-12 16:15:04 +0000205#if QEMU_GNUC_PREREQ(3, 4)
Richard Henderson72d81152013-02-13 17:47:35 -0800206 return val ? __builtin_ctzll(val) : 64;
aurel327d019982008-10-12 00:53:08 +0000207#else
j_mayerb9ef45f2007-10-28 12:52:38 +0000208 int cnt;
209
210 cnt = 0;
211 if (!((uint32_t)val)) {
212 cnt += 32;
213 val >>= 32;
214 }
215
216 return cnt + ctz32(val);
aurel327d019982008-10-12 00:53:08 +0000217#endif
j_mayerb9ef45f2007-10-28 12:52:38 +0000218}
219
Richard Henderson72d81152013-02-13 17:47:35 -0800220/**
221 * ctz64 - count trailing ones in a 64-bit value.
222 * @val: The value to search
223 *
224 * Returns 64 if the value is -1.
225 */
Blue Swirlfacd2852009-08-16 08:03:26 +0000226static inline int cto64(uint64_t val)
j_mayerb9ef45f2007-10-28 12:52:38 +0000227{
228 return ctz64(~val);
229}
230
Richard Henderson72d81152013-02-13 17:47:35 -0800231/**
232 * ctpop8 - count the population of one bits in an 8-bit value.
233 * @val: The value to search
234 */
Blue Swirlfacd2852009-08-16 08:03:26 +0000235static inline int ctpop8(uint8_t val)
j_mayerb9ef45f2007-10-28 12:52:38 +0000236{
Richard Henderson72d81152013-02-13 17:47:35 -0800237#if QEMU_GNUC_PREREQ(3, 4)
238 return __builtin_popcount(val);
239#else
j_mayerb9ef45f2007-10-28 12:52:38 +0000240 val = (val & 0x55) + ((val >> 1) & 0x55);
241 val = (val & 0x33) + ((val >> 2) & 0x33);
242 val = (val & 0x0f) + ((val >> 4) & 0x0f);
243
244 return val;
Richard Henderson72d81152013-02-13 17:47:35 -0800245#endif
j_mayerb9ef45f2007-10-28 12:52:38 +0000246}
247
Richard Henderson72d81152013-02-13 17:47:35 -0800248/**
249 * ctpop16 - count the population of one bits in a 16-bit value.
250 * @val: The value to search
251 */
Blue Swirlfacd2852009-08-16 08:03:26 +0000252static inline int ctpop16(uint16_t val)
j_mayerb9ef45f2007-10-28 12:52:38 +0000253{
Richard Henderson72d81152013-02-13 17:47:35 -0800254#if QEMU_GNUC_PREREQ(3, 4)
255 return __builtin_popcount(val);
256#else
j_mayerb9ef45f2007-10-28 12:52:38 +0000257 val = (val & 0x5555) + ((val >> 1) & 0x5555);
258 val = (val & 0x3333) + ((val >> 2) & 0x3333);
259 val = (val & 0x0f0f) + ((val >> 4) & 0x0f0f);
260 val = (val & 0x00ff) + ((val >> 8) & 0x00ff);
261
262 return val;
Richard Henderson72d81152013-02-13 17:47:35 -0800263#endif
j_mayerb9ef45f2007-10-28 12:52:38 +0000264}
265
Richard Henderson72d81152013-02-13 17:47:35 -0800266/**
267 * ctpop32 - count the population of one bits in a 32-bit value.
268 * @val: The value to search
269 */
Blue Swirlfacd2852009-08-16 08:03:26 +0000270static inline int ctpop32(uint32_t val)
j_mayerb9ef45f2007-10-28 12:52:38 +0000271{
aurel32bad5b1e2008-10-12 16:15:04 +0000272#if QEMU_GNUC_PREREQ(3, 4)
aurel327d019982008-10-12 00:53:08 +0000273 return __builtin_popcount(val);
274#else
j_mayerb9ef45f2007-10-28 12:52:38 +0000275 val = (val & 0x55555555) + ((val >> 1) & 0x55555555);
276 val = (val & 0x33333333) + ((val >> 2) & 0x33333333);
277 val = (val & 0x0f0f0f0f) + ((val >> 4) & 0x0f0f0f0f);
278 val = (val & 0x00ff00ff) + ((val >> 8) & 0x00ff00ff);
279 val = (val & 0x0000ffff) + ((val >> 16) & 0x0000ffff);
280
281 return val;
aurel327d019982008-10-12 00:53:08 +0000282#endif
j_mayerb9ef45f2007-10-28 12:52:38 +0000283}
284
Richard Henderson72d81152013-02-13 17:47:35 -0800285/**
286 * ctpop64 - count the population of one bits in a 64-bit value.
287 * @val: The value to search
288 */
Blue Swirlfacd2852009-08-16 08:03:26 +0000289static inline int ctpop64(uint64_t val)
j_mayerb9ef45f2007-10-28 12:52:38 +0000290{
aurel32bad5b1e2008-10-12 16:15:04 +0000291#if QEMU_GNUC_PREREQ(3, 4)
aurel327d019982008-10-12 00:53:08 +0000292 return __builtin_popcountll(val);
293#else
j_mayerb9ef45f2007-10-28 12:52:38 +0000294 val = (val & 0x5555555555555555ULL) + ((val >> 1) & 0x5555555555555555ULL);
295 val = (val & 0x3333333333333333ULL) + ((val >> 2) & 0x3333333333333333ULL);
296 val = (val & 0x0f0f0f0f0f0f0f0fULL) + ((val >> 4) & 0x0f0f0f0f0f0f0f0fULL);
297 val = (val & 0x00ff00ff00ff00ffULL) + ((val >> 8) & 0x00ff00ff00ff00ffULL);
298 val = (val & 0x0000ffff0000ffffULL) + ((val >> 16) & 0x0000ffff0000ffffULL);
299 val = (val & 0x00000000ffffffffULL) + ((val >> 32) & 0x00000000ffffffffULL);
300
301 return val;
aurel327d019982008-10-12 00:53:08 +0000302#endif
ths3800af92007-12-18 01:58:05 +0000303}
Paolo Bonzinicb9c3772012-12-06 12:15:58 +0100304
Richard Henderson01654372013-02-13 17:47:34 -0800305/* Host type specific sizes of these routines. */
306
307#if ULONG_MAX == UINT32_MAX
308# define clzl clz32
309# define ctzl ctz32
310# define clol clo32
311# define ctol cto32
312# define ctpopl ctpop32
313#elif ULONG_MAX == UINT64_MAX
314# define clzl clz64
315# define ctzl ctz64
316# define clol clo64
317# define ctol cto64
318# define ctpopl ctpop64
319#else
320# error Unknown sizeof long
321#endif
322
Paolo Bonzinicb9c3772012-12-06 12:15:58 +0100323#endif