]> rtime.felk.cvut.cz Git - l4.git/blob - l4/pkg/l4util/include/ARCH-amd64/bitops_arch.h
update
[l4.git] / l4 / pkg / l4util / include / ARCH-amd64 / bitops_arch.h
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 /* set bit */
30 #define __L4UTIL_BITOPS_HAVE_ARCH_SET_BIT32
31 L4_INLINE void
32 l4util_set_bit32(int b, volatile l4_uint32_t * dest)
33 {
34   __asm__ __volatile__
35     (
36      "btsl  %1,%0   \n\t"
37      :
38      :
39      "m"   (*dest),   /* 0 mem, destination operand */
40      "Ir"  (b)       /* 1,     bit number */
41      :
42      "memory", "cc"
43      );
44 }
45
46 #define __L4UTIL_BITOPS_HAVE_ARCH_SET_BIT64
47 L4_INLINE void
48 l4util_set_bit64(int b, volatile l4_uint64_t * dest)
49 {
50   __asm__ __volatile__
51     (
52      "btsl  %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 #define __L4UTIL_BITOPS_HAVE_ARCH_SET_BIT
63 L4_INLINE void
64 l4util_set_bit(int b, volatile l4_umword_t * dest)
65 {
66   return l4util_set_bit64(b, (volatile l4_uint64_t*)dest);
67 }
68
69 /* clear bit */
70 #define __L4UTIL_BITOPS_HAVE_ARCH_CLEAR_BIT32
71 L4_INLINE void
72 l4util_clear_bit32(int b, volatile l4_uint32_t * dest)
73 {
74   __asm__ __volatile__
75     (
76      "btrl  %1,%0   \n\t"
77      :
78      :
79      "m"   (*dest),   /* 0 mem, destination operand */
80      "Ir"  (b)        /* 1,     bit number */
81      :
82      "memory", "cc"
83      );
84 }
85
86 #define __L4UTIL_BITOPS_HAVE_ARCH_CLEAR_BIT64
87 L4_INLINE void
88 l4util_clear_bit64(int b, volatile l4_uint64_t * dest)
89 {
90   __asm__ __volatile__
91     (
92      "btrl  %1,%0   \n\t"
93      :
94      :
95      "m"   (*dest),   /* 0 mem, destination operand */
96      "Ir"  (b)        /* 1,     bit number */
97      :
98      "memory", "cc"
99      );
100 }
101
102 #define __L4UTIL_BITOPS_HAVE_ARCH_CLEAR_BIT
103 L4_INLINE void
104 l4util_clear_bit(int b, volatile l4_umword_t * dest)
105 {
106   return l4util_clear_bit64(b, (volatile l4_uint64_t*)dest);
107 }
108
109 /* change bit */
110 #define __L4UTIL_BITOPS_HAVE_ARCH_COMPLEMENT_BIT
111 L4_INLINE void
112 l4util_complement_bit(int b, volatile l4_umword_t * dest)
113 {
114   __asm__ __volatile__
115     (
116      "btcq  %1,%0   \n\t"
117      :
118      :
119      "m"   (*dest),   /* 0 mem, destination operand */
120      "Ir"  ((l4_umword_t)b)        /* 1,     bit number */
121      :
122      "memory", "cc"
123      );
124 }
125
126 /* test bit */
127 #define __L4UTIL_BITOPS_HAVE_ARCH_TEST_BIT32
128 L4_INLINE int
129 l4util_test_bit32(int b, const volatile l4_uint32_t * dest)
130 {
131   l4_int8_t bit;
132
133   __asm__ __volatile__
134     (
135      "btl   %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 #define __L4UTIL_BITOPS_HAVE_ARCH_TEST_BIT64
150 L4_INLINE int
151 l4util_test_bit64(int b, const volatile l4_uint64_t * dest)
152 {
153   l4_int8_t bit;
154
155   __asm__ __volatile__
156     (
157      "btl   %2,%1   \n\t"
158      "setc  %0      \n\t"
159      :
160      "=r"  (bit)      /* 0,     old bit value */
161      :
162      "m"   (*dest),   /* 1 mem, destination operand */
163      "Ir"  (b)        /* 2,     bit number */
164      :
165      "memory", "cc"
166      );
167
168   return (int)bit;
169 }
170
171 #define __L4UTIL_BITOPS_HAVE_ARCH_TEST_BIT
172 L4_INLINE int
173 l4util_test_bit(int b, const volatile l4_umword_t * dest)
174 {
175   return l4util_test_bit64(b, (const volatile l4_uint64_t *)dest);
176 }
177
178
179 /* bit test and set */
180 #define __L4UTIL_BITOPS_HAVE_ARCH_BIT_TEST_AND_SET
181 L4_INLINE int
182 l4util_bts(int b, volatile l4_umword_t * dest)
183 {
184   l4_int8_t bit;
185
186   __asm__ __volatile__
187     (
188      "btsl  %2,%1   \n\t"
189      "setc  %0      \n\t"
190      :
191      "=r"  (bit)      /* 0,     old bit value */
192      :
193      "m"   (*dest),   /* 1 mem, destination operand */
194      "Ir"  (b)        /* 2,     bit number */
195      :
196      "memory", "cc"
197      );
198
199   return (int)bit;
200 }
201
202 /* bit test and reset */
203 #define __L4UTIL_BITOPS_HAVE_ARCH_BIT_TEST_AND_RESET
204 L4_INLINE int
205 l4util_btr(int b, volatile l4_umword_t * dest)
206 {
207   l4_int8_t bit;
208
209   __asm__ __volatile__
210     (
211      "btrl  %2,%1   \n\t"
212      "setc  %0      \n\t"
213      :
214      "=r"  (bit)      /* 0,     old bit value */
215      :
216      "m"   (*dest),   /* 1 mem, destination operand */
217      "Ir"  (b)        /* 2,     bit number */
218      :
219      "memory", "cc"
220      );
221
222   return (int)bit;
223 }
224
225 /* bit test and complement */
226 #define __L4UTIL_BITOPS_HAVE_ARCH_BIT_TEST_AND_COMPLEMENT
227 L4_INLINE int
228 l4util_btc(int b, volatile l4_umword_t * dest)
229 {
230   l4_int8_t bit;
231
232   __asm__ __volatile__
233     (
234      "btc   %2,%1   \n\t"
235      "setc  %0      \n\t"
236      :
237      "=r"  (bit)      /* 0,     old bit value */
238      :
239      "m"   (*dest),   /* 1 mem, destination operand */
240      "Ir"  ((l4_umword_t)b)        /* 2,     bit number */
241      :
242      "memory", "cc"
243      );
244
245   return (int)bit;
246 }
247
248 /* bit scan reverse */
249 #define __L4UTIL_BITOPS_HAVE_ARCH_BIT_SCAN_REVERSE
250 L4_INLINE int
251 l4util_bsr(l4_umword_t word)
252 {
253   l4_umword_t tmp;
254
255   if (EXPECT_FALSE(word == 0))
256     return -1;
257
258   __asm__ __volatile__
259     (
260      "bsr %1,%0 \n\t"
261      :
262      "=r" (tmp)       /* 0, index of most significant set bit */
263      :
264      "r"  (word)      /* 1, argument */
265      );
266
267   return tmp;
268 }
269
270 /* bit scan forwad */
271 #define __L4UTIL_BITOPS_HAVE_ARCH_BIT_SCAN_FORWARD
272 L4_INLINE int
273 l4util_bsf(l4_umword_t word)
274 {
275   l4_umword_t tmp;
276
277   if (EXPECT_FALSE(word == 0))
278     return -1;
279
280   __asm__ __volatile__
281     (
282      "bsf %1,%0 \n\t"
283      :
284      "=r" (tmp)       /* 0, index of least significant set bit */
285      :
286      "r"  (word)      /* 1, argument */
287      );
288
289   return tmp;
290 }
291
292 #define __L4UTIL_BITOPS_HAVE_ARCH_FIND_FIRST_SET_BIT
293 L4_INLINE int
294 l4util_find_first_set_bit(const void * dest, l4_size_t size)
295 {
296   l4_mword_t dummy0, dummy1, res;
297
298   __asm__ __volatile__
299     (
300      "xor  %%rax,%%rax          \n\t"
301      "repe; scasl               \n\t"
302      "jz    1f                  \n\t"
303      "lea  -4(%%rdi),%%rdi      \n\t"
304      "bsfq  (%%rdi),%%rax       \n"
305      "1:                        \n\t"
306      "sub  %%rbx,%%rdi          \n\t"
307      "shl  $3,%%rdi             \n\t"
308      "add  %%rdi,%%rax          \n\t"
309      :
310      "=a" (res), "=&c" (dummy0), "=&D" (dummy1)
311      :
312      "1" ((size + 31) >> 5), "2" (dest), "b" (dest)
313      :
314      "cc", "memory");
315
316   return res;
317 }
318
319 #define __L4UTIL_BITOPS_HAVE_ARCH_FIND_FIRST_ZERO_BIT
320 L4_INLINE int
321 l4util_find_first_zero_bit(const void * dest, l4_size_t size)
322 {
323   l4_mword_t dummy0, dummy1, dummy2, res;
324
325   if (!size)
326     return 0;
327
328   __asm__ __volatile__
329     (
330      "mov   $-1,%%rax           \n\t"
331      "xor   %%rdx,%%rdx \n\t"
332      "repe;  scasl              \n\t"
333      "je     1f                 \n\t"
334      "xor   -4(%%rdi),%%rax     \n\t"
335      "sub   $4,%%rdi            \n\t"
336      "bsf   %%rax,%%rdx \n"
337      "1:                        \n\t"
338      "sub   %[dest],%%rdi       \n\t"
339      "shl   $3,%%rdi            \n\t"
340      "add   %%rdi,%%rdx \n\t"
341      :
342      "=d" (res), "=&c" (dummy0), "=&D" (dummy1), "=&a" (dummy2)
343      :
344      "1" ((size + 31) >> 5), "2" (dest), [dest] "S" (dest)
345      :
346      "cc", "memory");
347
348   return res;
349 }
350
351 EXTERN_C_END
352
353 #endif /* ! __L4UTIL__INCLUDE__ARCH_AMD64__BITOPS_ARCH_H__ */