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