Statistics
| Branch: | Revision:

root / host-utils.h @ a74cdab4

History | View | Annotate | Download (5.4 kB)

1
/*
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
 */
25

    
26
#include "osdep.h"
27

    
28
#if defined(__x86_64__)
29
#define __HAVE_FAST_MULU64__
30
static inline void mulu64(uint64_t *plow, uint64_t *phigh,
31
                          uint64_t a, uint64_t b)
32
{
33
    __asm__ ("mul %0\n\t"
34
             : "=d" (*phigh), "=a" (*plow)
35
             : "a" (a), "0" (b));
36
}
37
#define __HAVE_FAST_MULS64__
38
static inline void muls64(uint64_t *plow, uint64_t *phigh,
39
                          int64_t a, int64_t b)
40
{
41
    __asm__ ("imul %0\n\t"
42
             : "=d" (*phigh), "=a" (*plow)
43
             : "a" (a), "0" (b));
44
}
45
#else
46
void muls64(uint64_t *phigh, uint64_t *plow, int64_t a, int64_t b);
47
void mulu64(uint64_t *phigh, uint64_t *plow, uint64_t a, uint64_t b);
48
#endif
49

    
50
/* Binary search for leading zeros.  */
51

    
52
static inline int clz32(uint32_t val)
53
{
54
#if QEMU_GNUC_PREREQ(3, 4)
55
    if (val)
56
        return __builtin_clz(val);
57
    else
58
        return 32;
59
#else
60
    int cnt = 0;
61

    
62
    if (!(val & 0xFFFF0000U)) {
63
        cnt += 16;
64
        val <<= 16;
65
    }
66
    if (!(val & 0xFF000000U)) {
67
        cnt += 8;
68
        val <<= 8;
69
    }
70
    if (!(val & 0xF0000000U)) {
71
        cnt += 4;
72
        val <<= 4;
73
    }
74
    if (!(val & 0xC0000000U)) {
75
        cnt += 2;
76
        val <<= 2;
77
    }
78
    if (!(val & 0x80000000U)) {
79
        cnt++;
80
        val <<= 1;
81
    }
82
    if (!(val & 0x80000000U)) {
83
        cnt++;
84
    }
85
    return cnt;
86
#endif
87
}
88

    
89
static inline int clo32(uint32_t val)
90
{
91
    return clz32(~val);
92
}
93

    
94
static inline int clz64(uint64_t val)
95
{
96
#if QEMU_GNUC_PREREQ(3, 4)
97
    if (val)
98
        return __builtin_clzll(val);
99
    else
100
        return 64;
101
#else
102
    int cnt = 0;
103

    
104
    if (!(val >> 32)) {
105
        cnt += 32;
106
    } else {
107
        val >>= 32;
108
    }
109

    
110
    return cnt + clz32(val);
111
#endif
112
}
113

    
114
static inline int clo64(uint64_t val)
115
{
116
    return clz64(~val);
117
}
118

    
119
static inline int ctz32(uint32_t val)
120
{
121
#if QEMU_GNUC_PREREQ(3, 4)
122
    if (val)
123
        return __builtin_ctz(val);
124
    else
125
        return 32;
126
#else
127
    int cnt;
128

    
129
    cnt = 0;
130
    if (!(val & 0x0000FFFFUL)) {
131
        cnt += 16;
132
        val >>= 16;
133
    }
134
    if (!(val & 0x000000FFUL)) {
135
        cnt += 8;
136
        val >>= 8;
137
    }
138
    if (!(val & 0x0000000FUL)) {
139
        cnt += 4;
140
        val >>= 4;
141
    }
142
    if (!(val & 0x00000003UL)) {
143
        cnt += 2;
144
        val >>= 2;
145
    }
146
    if (!(val & 0x00000001UL)) {
147
        cnt++;
148
        val >>= 1;
149
    }
150
    if (!(val & 0x00000001UL)) {
151
        cnt++;
152
    }
153

    
154
    return cnt;
155
#endif
156
}
157

    
158
static inline int cto32(uint32_t val)
159
{
160
    return ctz32(~val);
161
}
162

    
163
static inline int ctz64(uint64_t val)
164
{
165
#if QEMU_GNUC_PREREQ(3, 4)
166
    if (val)
167
        return __builtin_ctzll(val);
168
    else
169
        return 64;
170
#else
171
    int cnt;
172

    
173
    cnt = 0;
174
    if (!((uint32_t)val)) {
175
        cnt += 32;
176
        val >>= 32;
177
    }
178

    
179
    return cnt + ctz32(val);
180
#endif
181
}
182

    
183
static inline int cto64(uint64_t val)
184
{
185
    return ctz64(~val);
186
}
187

    
188
static inline int ctpop8(uint8_t val)
189
{
190
    val = (val & 0x55) + ((val >> 1) & 0x55);
191
    val = (val & 0x33) + ((val >> 2) & 0x33);
192
    val = (val & 0x0f) + ((val >> 4) & 0x0f);
193

    
194
    return val;
195
}
196

    
197
static inline int ctpop16(uint16_t val)
198
{
199
    val = (val & 0x5555) + ((val >> 1) & 0x5555);
200
    val = (val & 0x3333) + ((val >> 2) & 0x3333);
201
    val = (val & 0x0f0f) + ((val >> 4) & 0x0f0f);
202
    val = (val & 0x00ff) + ((val >> 8) & 0x00ff);
203

    
204
    return val;
205
}
206

    
207
static inline int ctpop32(uint32_t val)
208
{
209
#if QEMU_GNUC_PREREQ(3, 4)
210
    return __builtin_popcount(val);
211
#else
212
    val = (val & 0x55555555) + ((val >>  1) & 0x55555555);
213
    val = (val & 0x33333333) + ((val >>  2) & 0x33333333);
214
    val = (val & 0x0f0f0f0f) + ((val >>  4) & 0x0f0f0f0f);
215
    val = (val & 0x00ff00ff) + ((val >>  8) & 0x00ff00ff);
216
    val = (val & 0x0000ffff) + ((val >> 16) & 0x0000ffff);
217

    
218
    return val;
219
#endif
220
}
221

    
222
static inline int ctpop64(uint64_t val)
223
{
224
#if QEMU_GNUC_PREREQ(3, 4)
225
    return __builtin_popcountll(val);
226
#else
227
    val = (val & 0x5555555555555555ULL) + ((val >>  1) & 0x5555555555555555ULL);
228
    val = (val & 0x3333333333333333ULL) + ((val >>  2) & 0x3333333333333333ULL);
229
    val = (val & 0x0f0f0f0f0f0f0f0fULL) + ((val >>  4) & 0x0f0f0f0f0f0f0f0fULL);
230
    val = (val & 0x00ff00ff00ff00ffULL) + ((val >>  8) & 0x00ff00ff00ff00ffULL);
231
    val = (val & 0x0000ffff0000ffffULL) + ((val >> 16) & 0x0000ffff0000ffffULL);
232
    val = (val & 0x00000000ffffffffULL) + ((val >> 32) & 0x00000000ffffffffULL);
233

    
234
    return val;
235
#endif
236
}