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