]> CyberLeo.Net >> Repos - FreeBSD/releng/7.2.git/blob - sys/gnu/fs/ext2fs/sparc64-bitops.h
Create releng/7.2 from stable/7 in preparation for 7.2-RELEASE.
[FreeBSD/releng/7.2.git] / sys / gnu / fs / ext2fs / sparc64-bitops.h
1 /*-
2  * $Id: bitops.h,v 1.31 2000/09/23 02:09:21 davem Exp $
3  * bitops.h: Bit string operations on the V9.
4  *
5  * Copyright 1996, 1997 David S. Miller (davem@caip.rutgers.edu)
6  *
7  *      This program is free software; you can redistribute it and/or modify
8  *      it under the terms of the GNU General Public License as published by
9  *      the Free Software Foundation; either version 2 of the License.
10  *
11  *      This program is distributed in the hope that it will be useful,
12  *      but WITHOUT ANY WARRANTY; without even the implied warranty of
13  *      MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
14  *      GNU General Public License for more details.
15  *
16  *      You should have received a copy of the GNU General Public License
17  *      along with this program; if not, write to the Free Software
18  *      Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
19  *
20  */
21
22 /* $FreeBSD$ */
23 #ifndef _SPARC64_BITOPS_H
24 #define _SPARC64_BITOPS_H
25
26 #include <asm/byteorder.h>
27
28 extern long __test_and_set_bit(unsigned long nr, volatile void *addr);
29 extern long __test_and_clear_bit(unsigned long nr, volatile void *addr);
30 extern long __test_and_change_bit(unsigned long nr, volatile void *addr);
31
32 #define test_and_set_bit(nr,addr)       (__test_and_set_bit(nr,addr)!=0)
33 #define test_and_clear_bit(nr,addr)     (__test_and_clear_bit(nr,addr)!=0)
34 #define test_and_change_bit(nr,addr)    (__test_and_change_bit(nr,addr)!=0)
35 #define set_bit(nr,addr)                ((void)__test_and_set_bit(nr,addr))
36 #define clear_bit(nr,addr)              ((void)__test_and_clear_bit(nr,addr))
37 #define change_bit(nr,addr)             ((void)__test_and_change_bit(nr,addr))
38
39 #define smp_mb__before_clear_bit()      do { } while(0)
40 #define smp_mb__after_clear_bit()       do { } while(0)
41
42 extern __inline__ int test_bit(int nr, __const__ void *addr)
43 {
44         return (1UL & (((__const__ long *) addr)[nr >> 6] >> (nr & 63))) != 0UL;
45 }
46
47 /* The easy/cheese version for now. */
48 extern __inline__ unsigned long ffz(unsigned long word)
49 {
50         unsigned long result;
51
52 #ifdef ULTRA_HAS_POPULATION_COUNT       /* Thanks for nothing Sun... */
53         __asm__ __volatile__("
54         brz,pn  %0, 1f
55          neg    %0, %%g1
56         xnor    %0, %%g1, %%g2
57         popc    %%g2, %0
58 1:      " : "=&r" (result)
59           : "0" (word)
60           : "g1", "g2");
61 #else
62 #if 1 /* def EASY_CHEESE_VERSION */
63         result = 0;
64         while(word & 1) {
65                 result++;
66                 word >>= 1;
67         }
68 #else
69         unsigned long tmp;
70
71         result = 0;     
72         tmp = ~word & -~word;
73         if (!(unsigned)tmp) {
74                 tmp >>= 32;
75                 result = 32;
76         }
77         if (!(unsigned short)tmp) {
78                 tmp >>= 16;
79                 result += 16;
80         }
81         if (!(unsigned char)tmp) {
82                 tmp >>= 8;
83                 result += 8;
84         }
85         if (tmp & 0xf0) result += 4;
86         if (tmp & 0xcc) result += 2;
87         if (tmp & 0xaa) result ++;
88 #endif
89 #endif
90         return result;
91 }
92
93 #ifdef __KERNEL__
94
95 /*
96  * ffs: find first bit set. This is defined the same way as
97  * the libc and compiler builtin ffs routines, therefore
98  * differs in spirit from the above ffz (man ffs).
99  */
100
101 #define ffs(x) generic_ffs(x)
102
103 /*
104  * hweightN: returns the hamming weight (i.e. the number
105  * of bits set) of a N-bit word
106  */
107
108 #ifdef ULTRA_HAS_POPULATION_COUNT
109
110 extern __inline__ unsigned int hweight32(unsigned int w)
111 {
112         unsigned int res;
113
114         __asm__ ("popc %1,%0" : "=r" (res) : "r" (w & 0xffffffff));
115         return res;
116 }
117
118 extern __inline__ unsigned int hweight16(unsigned int w)
119 {
120         unsigned int res;
121
122         __asm__ ("popc %1,%0" : "=r" (res) : "r" (w & 0xffff));
123         return res;
124 }
125
126 extern __inline__ unsigned int hweight8(unsigned int w)
127 {
128         unsigned int res;
129
130         __asm__ ("popc %1,%0" : "=r" (res) : "r" (w & 0xff));
131         return res;
132 }
133
134 #else
135
136 #define hweight32(x) generic_hweight32(x)
137 #define hweight16(x) generic_hweight16(x)
138 #define hweight8(x) generic_hweight8(x)
139
140 #endif
141 #endif /* __KERNEL__ */
142
143 /* find_next_zero_bit() finds the first zero bit in a bit string of length
144  * 'size' bits, starting the search at bit 'offset'. This is largely based
145  * on Linus's ALPHA routines, which are pretty portable BTW.
146  */
147
148 extern __inline__ unsigned long find_next_zero_bit(void *addr, unsigned long size, unsigned long offset)
149 {
150         unsigned long *p = ((unsigned long *) addr) + (offset >> 6);
151         unsigned long result = offset & ~63UL;
152         unsigned long tmp;
153
154         if (offset >= size)
155                 return size;
156         size -= result;
157         offset &= 63UL;
158         if (offset) {
159                 tmp = *(p++);
160                 tmp |= ~0UL >> (64-offset);
161                 if (size < 64)
162                         goto found_first;
163                 if (~tmp)
164                         goto found_middle;
165                 size -= 64;
166                 result += 64;
167         }
168         while (size & ~63UL) {
169                 if (~(tmp = *(p++)))
170                         goto found_middle;
171                 result += 64;
172                 size -= 64;
173         }
174         if (!size)
175                 return result;
176         tmp = *p;
177
178 found_first:
179         tmp |= ~0UL << size;
180         if (tmp == ~0UL)        /* Are any bits zero? */
181                 return result + size; /* Nope. */
182 found_middle:
183         return result + ffz(tmp);
184 }
185
186 #define find_first_zero_bit(addr, size) \
187         find_next_zero_bit((addr), (size), 0)
188
189 extern long __test_and_set_le_bit(int nr, volatile void *addr);
190 extern long __test_and_clear_le_bit(int nr, volatile void *addr);
191
192 #define test_and_set_le_bit(nr,addr)    (__test_and_set_le_bit(nr,addr)!=0)
193 #define test_and_clear_le_bit(nr,addr)  (__test_and_clear_le_bit(nr,addr)!=0)
194 #define set_le_bit(nr,addr)             ((void)__test_and_set_le_bit(nr,addr))
195 #define clear_le_bit(nr,addr)           ((void)__test_and_clear_le_bit(nr,addr))
196
197 extern __inline__ int test_le_bit(int nr, __const__ void * addr)
198 {
199         int                     mask;
200         __const__ unsigned char *ADDR = (__const__ unsigned char *) addr;
201
202         ADDR += nr >> 3;
203         mask = 1 << (nr & 0x07);
204         return ((mask & *ADDR) != 0);
205 }
206
207 #define find_first_zero_le_bit(addr, size) \
208         find_next_zero_le_bit((addr), (size), 0)
209
210 extern __inline__ unsigned long find_next_zero_le_bit(void *addr, unsigned long size, unsigned long offset)
211 {
212         unsigned long *p = ((unsigned long *) addr) + (offset >> 6);
213         unsigned long result = offset & ~63UL;
214         unsigned long tmp;
215
216         if (offset >= size)
217                 return size;
218         size -= result;
219         offset &= 63UL;
220         if(offset) {
221                 tmp = __swab64p(p++);
222                 tmp |= (~0UL >> (64-offset));
223                 if(size < 64)
224                         goto found_first;
225                 if(~tmp)
226                         goto found_middle;
227                 size -= 64;
228                 result += 64;
229         }
230         while(size & ~63) {
231                 if(~(tmp = __swab64p(p++)))
232                         goto found_middle;
233                 result += 64;
234                 size -= 64;
235         }
236         if(!size)
237                 return result;
238         tmp = __swab64p(p);
239 found_first:
240         tmp |= (~0UL << size);
241         if (tmp == ~0UL)        /* Are any bits zero? */
242                 return result + size; /* Nope. */
243 found_middle:
244         return result + ffz(tmp);
245 }
246
247 #ifdef __KERNEL__
248
249 #define ext2_set_bit                    test_and_set_le_bit
250 #define ext2_clear_bit                  test_and_clear_le_bit
251 #define ext2_test_bit                   test_le_bit
252 #define ext2_find_first_zero_bit        find_first_zero_le_bit
253 #define ext2_find_next_zero_bit         find_next_zero_le_bit
254
255 /* Bitmap functions for the minix filesystem.  */
256 #define minix_test_and_set_bit(nr,addr) test_and_set_bit(nr,addr)
257 #define minix_set_bit(nr,addr) set_bit(nr,addr)
258 #define minix_test_and_clear_bit(nr,addr) test_and_clear_bit(nr,addr)
259 #define minix_test_bit(nr,addr) test_bit(nr,addr)
260 #define minix_find_first_zero_bit(addr,size) find_first_zero_bit(addr,size)
261
262 #endif /* __KERNEL__ */
263
264 #endif /* defined(_SPARC64_BITOPS_H) */