fe306f6e4828927342e66e40bab74fe9f33993da
[qemu] / host-utils.h
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 /* Note that some of those functions may end up calling libgcc functions,
27    depending on the host machine. It is up to the target emulation to
28    cope with that. */
29
30 /* Binary search for leading zeros.  */
31
32 static always_inline int clz32(uint32_t val)
33 {
34     int cnt = 0;
35
36     if (!(val & 0xFFFF0000U)) {
37         cnt += 16;
38         val <<= 16;
39     }
40     if (!(val & 0xFF000000U)) {
41         cnt += 8;
42         val <<= 8;
43     }
44     if (!(val & 0xF0000000U)) {
45         cnt += 4;
46         val <<= 4;
47     }
48     if (!(val & 0xC0000000U)) {
49         cnt += 2;
50         val <<= 2;
51     }
52     if (!(val & 0x80000000U)) {
53         cnt++;
54         val <<= 1;
55     }
56     if (!(val & 0x80000000U)) {
57         cnt++;
58     }
59     return cnt;
60 }
61
62 static always_inline int clo32(uint32_t val)
63 {
64     return clz32(~val);
65 }
66
67 static always_inline int clz64(uint64_t val)
68 {
69     int cnt = 0;
70
71     if (!(val & 0xFFFFFFFF00000000ULL)) {
72         cnt += 32;
73         val <<= 32;
74     }
75     if (!(val & 0xFFFF000000000000ULL)) {
76         cnt += 16;
77         val <<= 16;
78     }
79     if (!(val & 0xFF00000000000000ULL)) {
80         cnt += 8;
81         val <<= 8;
82     }
83     if (!(val & 0xF000000000000000ULL)) {
84         cnt += 4;
85         val <<= 4;
86     }
87     if (!(val & 0xC000000000000000ULL)) {
88         cnt += 2;
89         val <<= 2;
90     }
91     if (!(val & 0x8000000000000000ULL)) {
92         cnt++;
93         val <<= 1;
94     }
95     if (!(val & 0x8000000000000000ULL)) {
96         cnt++;
97     }
98     return cnt;
99 }
100
101 static always_inline int clo64(uint64_t val)
102 {
103     return clz64(~val);
104 }
105
106 static always_inline int ctz32 (uint32_t val)
107 {
108     int cnt;
109
110     cnt = 0;
111     if (!(val & 0x0000FFFFUL)) {
112          cnt += 16;
113         val >>= 16;
114      }
115     if (!(val & 0x000000FFUL)) {
116          cnt += 8;
117         val >>= 8;
118      }
119     if (!(val & 0x0000000FUL)) {
120          cnt += 4;
121         val >>= 4;
122      }
123     if (!(val & 0x00000003UL)) {
124          cnt += 2;
125         val >>= 2;
126      }
127     if (!(val & 0x00000001UL)) {
128          cnt++;
129         val >>= 1;
130      }
131     if (!(val & 0x00000001UL)) {
132          cnt++;
133      }
134
135      return cnt;
136  }
137  
138 static always_inline int cto32 (uint32_t val)
139  {
140     return ctz32(~val);
141 }
142
143 static always_inline int ctz64 (uint64_t val)
144 {
145     int cnt;
146
147     cnt = 0;
148     if (!((uint32_t)val)) {
149         cnt += 32;
150         val >>= 32;
151     }
152
153     return cnt + ctz32(val);
154 }
155
156 static always_inline int cto64 (uint64_t val)
157 {
158     return ctz64(~val);
159 }
160
161 static always_inline int ctpop8 (uint8_t val)
162 {
163     val = (val & 0x55) + ((val >> 1) & 0x55);
164     val = (val & 0x33) + ((val >> 2) & 0x33);
165     val = (val & 0x0f) + ((val >> 4) & 0x0f);
166
167     return val;
168 }
169
170 static always_inline int ctpop16 (uint16_t val)
171 {
172     val = (val & 0x5555) + ((val >> 1) & 0x5555);
173     val = (val & 0x3333) + ((val >> 2) & 0x3333);
174     val = (val & 0x0f0f) + ((val >> 4) & 0x0f0f);
175     val = (val & 0x00ff) + ((val >> 8) & 0x00ff);
176
177     return val;
178 }
179
180 static always_inline int ctpop32 (uint32_t val)
181 {
182     val = (val & 0x55555555) + ((val >>  1) & 0x55555555);
183     val = (val & 0x33333333) + ((val >>  2) & 0x33333333);
184     val = (val & 0x0f0f0f0f) + ((val >>  4) & 0x0f0f0f0f);
185     val = (val & 0x00ff00ff) + ((val >>  8) & 0x00ff00ff);
186     val = (val & 0x0000ffff) + ((val >> 16) & 0x0000ffff);
187
188     return val;
189 }
190
191 static always_inline int ctpop64 (uint64_t val)
192 {
193     val = (val & 0x5555555555555555ULL) + ((val >>  1) & 0x5555555555555555ULL);
194     val = (val & 0x3333333333333333ULL) + ((val >>  2) & 0x3333333333333333ULL);
195     val = (val & 0x0f0f0f0f0f0f0f0fULL) + ((val >>  4) & 0x0f0f0f0f0f0f0f0fULL);
196     val = (val & 0x00ff00ff00ff00ffULL) + ((val >>  8) & 0x00ff00ff00ff00ffULL);
197     val = (val & 0x0000ffff0000ffffULL) + ((val >> 16) & 0x0000ffff0000ffffULL);
198     val = (val & 0x00000000ffffffffULL) + ((val >> 32) & 0x00000000ffffffffULL);
199
200     return val;
201  }