Add sharable clz/clo inline functions and use them for the mips target.
[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 }