1 /*****************************************************************************/
2 /**
3 * \file
4 * \brief amd64 bit manipulation functions
5 * \ingroup bitops
6 *
7 * \date 07/03/2001
8 * \author Lars Reuther <reuther@os.inf.tu-dresden.de>
9 * Torsten Frenzel <frenzel@os.inf.tu-dresden.de>
10 * Frank Mehnert <fm3@os.inf.tu-dresden.de> */
11 /*
12 * (c) 2000-2009 Author(s)
13 * economic rights: Technische Universität Dresden (Germany)
14 * This file is part of TUD:OS and distributed under the terms of the
15 * GNU Lesser General Public License 2.1.
16 * Please see the COPYING-LGPL-2.1 file for details.
17 */
18
19 /*****************************************************************************/
20 #ifndef __L4UTIL__INCLUDE__ARCH_AMD64__BITOPS_ARCH_H__
21 #define __L4UTIL__INCLUDE__ARCH_AMD64__BITOPS_ARCH_H__
22
23 EXTERN_C_BEGIN
24
25 /*****************************************************************************
26 *** Implementation
27 *****************************************************************************/
28
29 #define __L4UTIL_BITOPS_HAVE_ARCH_SET_BIT
30 L4_INLINE void
l4util_set_bit(int b,volatile l4_umword_t * dest)31 l4util_set_bit(int b, volatile l4_umword_t * dest)
32 {
33 __asm__ __volatile__
34 (
35 "lock; bts %1,%0 \n\t"
36 :
37 :
38 "m" (*dest), /* 0 mem, destination operand */
39 "Ir" (b) /* 1, bit number */
40 :
41 "memory", "cc"
42 );
43 }
44
45 /* clear bit */
46 #define __L4UTIL_BITOPS_HAVE_ARCH_CLEAR_BIT
47 L4_INLINE void
l4util_clear_bit(int b,volatile l4_umword_t * dest)48 l4util_clear_bit(int b, volatile l4_umword_t * dest)
49 {
50 __asm__ __volatile__
51 (
52 "lock; btr %1,%0 \n\t"
53 :
54 :
55 "m" (*dest), /* 0 mem, destination operand */
56 "Ir" (b) /* 1, bit number */
57 :
58 "memory", "cc"
59 );
60 }
61
62 /* change bit */
63 #define __L4UTIL_BITOPS_HAVE_ARCH_COMPLEMENT_BIT
64 L4_INLINE void
l4util_complement_bit(int b,volatile l4_umword_t * dest)65 l4util_complement_bit(int b, volatile l4_umword_t * dest)
66 {
67 __asm__ __volatile__
68 (
69 "lock; btc %1,%0 \n\t"
70 :
71 :
72 "m" (*dest), /* 0 mem, destination operand */
73 "Ir" (b) /* 1, bit number */
74 :
75 "memory", "cc"
76 );
77 }
78
79 /* test bit */
80 #define __L4UTIL_BITOPS_HAVE_ARCH_TEST_BIT
81 L4_INLINE int
l4util_test_bit(int b,const volatile l4_umword_t * dest)82 l4util_test_bit(int b, const volatile l4_umword_t * dest)
83 {
84 l4_int8_t bit;
85
86 __asm__ __volatile__
87 (
88 "bt %2,%1 \n\t"
89 "setc %0 \n\t"
90 :
91 "=r" (bit) /* 0, old bit value */
92 :
93 "m" (*dest), /* 1 mem, destination operand */
94 "Ir" (b) /* 2, bit number */
95 :
96 "memory", "cc"
97 );
98
99 return (int)bit;
100 }
101
102
103 /* bit test and set */
104 #define __L4UTIL_BITOPS_HAVE_ARCH_BIT_TEST_AND_SET
105 L4_INLINE int
l4util_bts(int b,volatile l4_umword_t * dest)106 l4util_bts(int b, volatile l4_umword_t * dest)
107 {
108 l4_int8_t bit;
109
110 __asm__ __volatile__
111 (
112 "lock; bts %2,%1 \n\t"
113 "setc %0 \n\t"
114 :
115 "=r" (bit) /* 0, old bit value */
116 :
117 "m" (*dest), /* 1 mem, destination operand */
118 "Ir" (b) /* 2, bit number */
119 :
120 "memory", "cc"
121 );
122
123 return (int)bit;
124 }
125
126 /* bit test and reset */
127 #define __L4UTIL_BITOPS_HAVE_ARCH_BIT_TEST_AND_RESET
128 L4_INLINE int
l4util_btr(int b,volatile l4_umword_t * dest)129 l4util_btr(int b, volatile l4_umword_t * dest)
130 {
131 l4_int8_t bit;
132
133 __asm__ __volatile__
134 (
135 "lock; btr %2,%1 \n\t"
136 "setc %0 \n\t"
137 :
138 "=r" (bit) /* 0, old bit value */
139 :
140 "m" (*dest), /* 1 mem, destination operand */
141 "Ir" (b) /* 2, bit number */
142 :
143 "memory", "cc"
144 );
145
146 return (int)bit;
147 }
148
149 /* bit test and complement */
150 #define __L4UTIL_BITOPS_HAVE_ARCH_BIT_TEST_AND_COMPLEMENT
151 L4_INLINE int
l4util_btc(int b,volatile l4_umword_t * dest)152 l4util_btc(int b, volatile l4_umword_t * dest)
153 {
154 l4_int8_t bit;
155
156 __asm__ __volatile__
157 (
158 "lock; btc %2,%1 \n\t"
159 "setc %0 \n\t"
160 :
161 "=r" (bit) /* 0, old bit value */
162 :
163 "m" (*dest), /* 1 mem, destination operand */
164 "Ir" ((l4_umword_t)b) /* 2, bit number */
165 :
166 "memory", "cc"
167 );
168
169 return (int)bit;
170 }
171
172 /* bit scan reverse */
173 #define __L4UTIL_BITOPS_HAVE_ARCH_BIT_SCAN_REVERSE
174 L4_INLINE int
l4util_bsr(l4_umword_t word)175 l4util_bsr(l4_umword_t word)
176 {
177 l4_umword_t tmp;
178
179 if (L4_UNLIKELY(word == 0))
180 return -1;
181
182 __asm__ __volatile__
183 (
184 "bsr %1,%0 \n\t"
185 :
186 "=r" (tmp) /* 0, index of most significant set bit */
187 :
188 "r" (word) /* 1, argument */
189 );
190
191 return tmp;
192 }
193
194 /* bit scan forwad */
195 #define __L4UTIL_BITOPS_HAVE_ARCH_BIT_SCAN_FORWARD
196 L4_INLINE int
l4util_bsf(l4_umword_t word)197 l4util_bsf(l4_umword_t word)
198 {
199 l4_umword_t tmp;
200
201 if (L4_UNLIKELY(word == 0))
202 return -1;
203
204 __asm__ __volatile__
205 (
206 "bsf %1,%0 \n\t"
207 :
208 "=r" (tmp) /* 0, index of least significant set bit */
209 :
210 "r" (word) /* 1, argument */
211 );
212
213 return tmp;
214 }
215
216 #define __L4UTIL_BITOPS_HAVE_ARCH_FIND_FIRST_SET_BIT
217 L4_INLINE int
l4util_find_first_set_bit(const void * dest,l4_size_t size)218 l4util_find_first_set_bit(const void * dest, l4_size_t size)
219 {
220 l4_mword_t dummy0, dummy1, res;
221
222 __asm__ __volatile__
223 (
224 "xor %%rax,%%rax \n\t"
225 "repe; scasl \n\t"
226 "jz 1f \n\t"
227 "lea -4(%%rdi),%%rdi \n\t"
228 "bsfq (%%rdi),%%rax \n"
229 "1: \n\t"
230 "sub %%rbx,%%rdi \n\t"
231 "shl $3,%%rdi \n\t"
232 "add %%rdi,%%rax \n\t"
233 :
234 "=a" (res), "=&c" (dummy0), "=&D" (dummy1)
235 :
236 "1" ((size + 31) >> 5), "2" (dest), "b" (dest)
237 :
238 "cc", "memory");
239
240 return res;
241 }
242
243 #define __L4UTIL_BITOPS_HAVE_ARCH_FIND_FIRST_ZERO_BIT
244 L4_INLINE int
l4util_find_first_zero_bit(const void * dest,l4_size_t size)245 l4util_find_first_zero_bit(const void * dest, l4_size_t size)
246 {
247 l4_mword_t dummy0, dummy1, dummy2, res;
248
249 if (!size)
250 return 0;
251
252 __asm__ __volatile__
253 (
254 "mov $-1,%%rax \n\t"
255 "xor %%rdx,%%rdx \n\t"
256 "repe; scasl \n\t"
257 "je 1f \n\t"
258 "xor -4(%%rdi),%%rax \n\t"
259 "sub $4,%%rdi \n\t"
260 "bsf %%rax,%%rdx \n"
261 "1: \n\t"
262 "sub %[dest],%%rdi \n\t"
263 "shl $3,%%rdi \n\t"
264 "add %%rdi,%%rdx \n\t"
265 :
266 "=d" (res), "=&c" (dummy0), "=&D" (dummy1), "=&a" (dummy2)
267 :
268 "1" ((size + 31) >> 5), "2" (dest), [dest] "S" (dest)
269 :
270 "cc", "memory");
271
272 return res;
273 }
274
275 EXTERN_C_END
276
277 #endif /* ! __L4UTIL__INCLUDE__ARCH_AMD64__BITOPS_ARCH_H__ */
278